aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKai Koehne <kai.koehne@nokia.com>2010-01-07 12:14:35 +0100
committerKai Koehne <kai.koehne@nokia.com>2010-01-07 12:14:35 +0100
commit818a7b226bb79fe6e7e82d25ad329419c931287c (patch)
treeaa6e11b64a22bdbda9c74b1c31fe7f39dd5e6eab
parentae535daa20eecc9feb07941caf65f2966fb8f9b5 (diff)
New QmlDesigner plugin & Design mode
This adds a new "Design" mode that can be used to manipulate qml files in a visual way. It will only get build if you have the declarativeui module in Qt. This is a squashed import from the Bauhaus project. Share & enjoy :)
-rw-r--r--.gitignore3
-rw-r--r--share/qtcreator/qmldesigner/Button.qml86
-rw-r--r--share/qtcreator/qmldesigner/gradient.pngbin0 -> 340205 bytes
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/AnchorBox.qml199
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/BorderImageSpecifics.qml69
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/CheckBox.qml38
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/ColumnSpecifics.qml29
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/DoubleSpinBox.qml144
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/Extended.qml191
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/ExtendedPane.qml30
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/ExtendedSwitches.qml60
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/FlickableSpecifics.qml111
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/FlipableSpecifics.qml135
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/Geometry.qml173
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/GridSpecifics.qml49
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/GroupBox.qml57
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/GroupBoxOption.qml21
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/HorizontalLine.qml8
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/ImageSpecifics.qml26
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/IntEditor.qml51
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/ItemPane.qml104
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/Layout.qml22
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/LayoutPane.qml29
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/ListView.qml85
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/ListViewSpecifics.qml106
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/Modifiers.qml218
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/PropertyFrame.qml10
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/RectangleSpecifics.qml134
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/ResetPane.qml41
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/RowSpecifics.qml29
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/ScrollArea.qml14
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/SpinBox.qml72
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/Switches.qml85
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/TextEditSpecifics.qml273
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/TextInputSpecifics.qml176
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/TextSpecifics.qml172
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/Type.qml94
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/WebViewSpecifics.qml96
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/anchorbox.css32
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/emptyPane.qml45
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/images/behaivour.pngbin0 -> 433 bytes
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/images/blended-image-icon.pngbin0 -> 340 bytes
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/images/button.pngbin0 -> 687 bytes
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/images/default-icon.pngbin0 -> 341 bytes
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/images/downArrow.pngbin0 -> 855 bytes
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/images/expression.pngbin0 -> 575 bytes
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/images/extended.pngbin0 -> 293 bytes
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/images/grid-icon.pngbin0 -> 369 bytes
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/images/image-icon.pngbin0 -> 292 bytes
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/images/item-icon.pngbin0 -> 293 bytes
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/images/layout.pngbin0 -> 369 bytes
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/images/leftArrow.pngbin0 -> 885 bytes
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/images/list-icon.pngbin0 -> 424 bytes
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/images/mouse-region-icon.pngbin0 -> 511 bytes
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/images/placeholder.pngbin0 -> 311 bytes
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/images/rect-icon.pngbin0 -> 237 bytes
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/images/reset-button.pngbin0 -> 741 bytes
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/images/rightArrow.pngbin0 -> 871 bytes
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/images/standard.pngbin0 -> 340 bytes
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/images/submenu.pngbin0 -> 447 bytes
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/images/text-edit-icon.pngbin0 -> 368 bytes
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/images/text-icon.pngbin0 -> 582 bytes
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/images/upArrow.pngbin0 -> 849 bytes
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/layoutWidget.css35
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/propertyEditor.css397
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/specialCheckBox.css20
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/switch.css32
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/typeLabel.css8
-rw-r--r--share/qtcreator/qmldesigner/welcome-card.pngbin0 -> 59043 bytes
-rw-r--r--share/qtcreator/qmldesigner/welcomescreen.qml147
-rw-r--r--share/qtcreator/static.pro3
-rw-r--r--src/plugins/plugins.pro7
-rw-r--r--src/plugins/qmldesigner/QmlDesigner.pluginspec25
-rw-r--r--src/plugins/qmldesigner/application.cpp46
-rw-r--r--src/plugins/qmldesigner/application.h40
-rw-r--r--src/plugins/qmldesigner/components/formeditor/abstractformeditortool.cpp190
-rw-r--r--src/plugins/qmldesigner/components/formeditor/abstractformeditortool.h103
-rw-r--r--src/plugins/qmldesigner/components/formeditor/anchor.pngbin0 -> 415 bytes
-rw-r--r--src/plugins/qmldesigner/components/formeditor/anchorcontroller.cpp537
-rw-r--r--src/plugins/qmldesigner/components/formeditor/anchorcontroller.h117
-rw-r--r--src/plugins/qmldesigner/components/formeditor/anchorhandleitem.cpp212
-rw-r--r--src/plugins/qmldesigner/components/formeditor/anchorhandleitem.h91
-rw-r--r--src/plugins/qmldesigner/components/formeditor/anchorindicator.cpp116
-rw-r--r--src/plugins/qmldesigner/components/formeditor/anchorindicator.h64
-rw-r--r--src/plugins/qmldesigner/components/formeditor/anchorlinecontroller.cpp236
-rw-r--r--src/plugins/qmldesigner/components/formeditor/anchorlinecontroller.h93
-rw-r--r--src/plugins/qmldesigner/components/formeditor/anchorlinehandleitem.cpp148
-rw-r--r--src/plugins/qmldesigner/components/formeditor/anchorlinehandleitem.h86
-rw-r--r--src/plugins/qmldesigner/components/formeditor/anchorlineindicator.cpp131
-rw-r--r--src/plugins/qmldesigner/components/formeditor/anchorlineindicator.h69
-rw-r--r--src/plugins/qmldesigner/components/formeditor/anchormanipulator.cpp144
-rw-r--r--src/plugins/qmldesigner/components/formeditor/anchormanipulator.h71
-rw-r--r--src/plugins/qmldesigner/components/formeditor/anchortool.cpp226
-rw-r--r--src/plugins/qmldesigner/components/formeditor/anchortool.h88
-rw-r--r--src/plugins/qmldesigner/components/formeditor/controlelement.cpp66
-rw-r--r--src/plugins/qmldesigner/components/formeditor/controlelement.h57
-rw-r--r--src/plugins/qmldesigner/components/formeditor/dragtool.cpp315
-rw-r--r--src/plugins/qmldesigner/components/formeditor/dragtool.h105
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditor.pri84
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditor.qrc12
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.cpp88
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.h51
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp323
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditoritem.h131
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditormainview.cpp401
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditormainview.h123
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditormainwidget.cpp156
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditormainwidget.h74
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditornodeinstanceview.cpp48
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditornodeinstanceview.h50
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp364
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditorscene.h133
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditorsubwindow.cpp38
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditorsubwindow.h45
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditorview.cpp531
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditorview.h141
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditorwidget.cpp221
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditorwidget.h91
-rw-r--r--src/plugins/qmldesigner/components/formeditor/itemcreatortool.cpp191
-rw-r--r--src/plugins/qmldesigner/components/formeditor/itemcreatortool.h82
-rw-r--r--src/plugins/qmldesigner/components/formeditor/itemutilfunctions.cpp78
-rw-r--r--src/plugins/qmldesigner/components/formeditor/itemutilfunctions.h48
-rw-r--r--src/plugins/qmldesigner/components/formeditor/layeritem.cpp73
-rw-r--r--src/plugins/qmldesigner/components/formeditor/layeritem.h66
-rw-r--r--src/plugins/qmldesigner/components/formeditor/manipulatorlayeritem.h39
-rw-r--r--src/plugins/qmldesigner/components/formeditor/movemanipulator.cpp363
-rw-r--r--src/plugins/qmldesigner/components/formeditor/movemanipulator.h114
-rw-r--r--src/plugins/qmldesigner/components/formeditor/movetool.cpp345
-rw-r--r--src/plugins/qmldesigner/components/formeditor/movetool.h97
-rw-r--r--src/plugins/qmldesigner/components/formeditor/numberseriesaction.cpp88
-rw-r--r--src/plugins/qmldesigner/components/formeditor/numberseriesaction.h66
-rw-r--r--src/plugins/qmldesigner/components/formeditor/onedimensionalcluster.cpp146
-rw-r--r--src/plugins/qmldesigner/components/formeditor/onedimensionalcluster.h70
-rw-r--r--src/plugins/qmldesigner/components/formeditor/resize_handle.pngbin0 -> 160 bytes
-rw-r--r--src/plugins/qmldesigner/components/formeditor/resizecontroller.cpp273
-rw-r--r--src/plugins/qmldesigner/components/formeditor/resizecontroller.h104
-rw-r--r--src/plugins/qmldesigner/components/formeditor/resizehandleitem.cpp118
-rw-r--r--src/plugins/qmldesigner/components/formeditor/resizehandleitem.h84
-rw-r--r--src/plugins/qmldesigner/components/formeditor/resizeindicator.cpp91
-rw-r--r--src/plugins/qmldesigner/components/formeditor/resizeindicator.h81
-rw-r--r--src/plugins/qmldesigner/components/formeditor/resizemanipulator.cpp504
-rw-r--r--src/plugins/qmldesigner/components/formeditor/resizemanipulator.h91
-rw-r--r--src/plugins/qmldesigner/components/formeditor/resizetool.cpp177
-rw-r--r--src/plugins/qmldesigner/components/formeditor/resizetool.h76
-rw-r--r--src/plugins/qmldesigner/components/formeditor/rubberbandselectionmanipulator.cpp153
-rw-r--r--src/plugins/qmldesigner/components/formeditor/rubberbandselectionmanipulator.h83
-rw-r--r--src/plugins/qmldesigner/components/formeditor/scaleitem.cpp49
-rw-r--r--src/plugins/qmldesigner/components/formeditor/scaleitem.h53
-rw-r--r--src/plugins/qmldesigner/components/formeditor/scalemanipulator.cpp45
-rw-r--r--src/plugins/qmldesigner/components/formeditor/scalemanipulator.h63
-rw-r--r--src/plugins/qmldesigner/components/formeditor/selectionindicator.cpp118
-rw-r--r--src/plugins/qmldesigner/components/formeditor/selectionindicator.h65
-rw-r--r--src/plugins/qmldesigner/components/formeditor/selectionrectangle.cpp87
-rw-r--r--src/plugins/qmldesigner/components/formeditor/selectionrectangle.h63
-rw-r--r--src/plugins/qmldesigner/components/formeditor/selectiontool.cpp280
-rw-r--r--src/plugins/qmldesigner/components/formeditor/selectiontool.h93
-rw-r--r--src/plugins/qmldesigner/components/formeditor/singleselectionmanipulator.cpp132
-rw-r--r--src/plugins/qmldesigner/components/formeditor/singleselectionmanipulator.h72
-rw-r--r--src/plugins/qmldesigner/components/formeditor/snapper.cpp626
-rw-r--r--src/plugins/qmldesigner/components/formeditor/snapper.h112
-rw-r--r--src/plugins/qmldesigner/components/formeditor/snapping.pngbin0 -> 359 bytes
-rw-r--r--src/plugins/qmldesigner/components/formeditor/snappinglinecreator.cpp190
-rw-r--r--src/plugins/qmldesigner/components/formeditor/snappinglinecreator.h102
-rw-r--r--src/plugins/qmldesigner/components/formeditor/toolbox.cpp81
-rw-r--r--src/plugins/qmldesigner/components/formeditor/toolbox.h52
-rw-r--r--src/plugins/qmldesigner/components/formeditor/transform.pngbin0 -> 17296 bytes
-rw-r--r--src/plugins/qmldesigner/components/formeditor/zoomaction.cpp116
-rw-r--r--src/plugins/qmldesigner/components/formeditor/zoomaction.h68
-rw-r--r--src/plugins/qmldesigner/components/integration/allpropertiesviewcontroller.cpp64
-rw-r--r--src/plugins/qmldesigner/components/integration/allpropertiesviewcontroller.h54
-rw-r--r--src/plugins/qmldesigner/components/integration/componentaction.cpp74
-rw-r--r--src/plugins/qmldesigner/components/integration/componentaction.h66
-rw-r--r--src/plugins/qmldesigner/components/integration/componentview.cpp179
-rw-r--r--src/plugins/qmldesigner/components/integration/componentview.h105
-rw-r--r--src/plugins/qmldesigner/components/integration/designdocumentcontroller.cpp815
-rw-r--r--src/plugins/qmldesigner/components/integration/designdocumentcontroller.h142
-rw-r--r--src/plugins/qmldesigner/components/integration/designdocumentcontrollerview.cpp137
-rw-r--r--src/plugins/qmldesigner/components/integration/designdocumentcontrollerview.h78
-rw-r--r--src/plugins/qmldesigner/components/integration/documentcloser.cpp139
-rw-r--r--src/plugins/qmldesigner/components/integration/documentcloser.h67
-rw-r--r--src/plugins/qmldesigner/components/integration/integration.pri34
-rw-r--r--src/plugins/qmldesigner/components/integration/integrationcore.cpp94
-rw-r--r--src/plugins/qmldesigner/components/integration/integrationcore.h61
-rw-r--r--src/plugins/qmldesigner/components/integration/multipledocumentscontroller.cpp353
-rw-r--r--src/plugins/qmldesigner/components/integration/multipledocumentscontroller.h120
-rw-r--r--src/plugins/qmldesigner/components/integration/navigatorcontroller.cpp53
-rw-r--r--src/plugins/qmldesigner/components/integration/navigatorcontroller.h48
-rw-r--r--src/plugins/qmldesigner/components/integration/stackedutilitypanelcontroller.cpp76
-rw-r--r--src/plugins/qmldesigner/components/integration/stackedutilitypanelcontroller.h60
-rw-r--r--src/plugins/qmldesigner/components/integration/stateseditorcontroller.cpp50
-rw-r--r--src/plugins/qmldesigner/components/integration/stateseditorcontroller.h48
-rw-r--r--src/plugins/qmldesigner/components/integration/utilitypanelcontroller.cpp54
-rw-r--r--src/plugins/qmldesigner/components/integration/utilitypanelcontroller.h55
-rw-r--r--src/plugins/qmldesigner/components/integration/widgetboxcontroller.cpp51
-rw-r--r--src/plugins/qmldesigner/components/integration/widgetboxcontroller.h48
-rw-r--r--src/plugins/qmldesigner/components/integration/xuifiledialog.cpp91
-rw-r--r--src/plugins/qmldesigner/components/integration/xuifiledialog.h65
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/customdraganddrop.cpp301
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/customdraganddrop.h127
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/default-icon.pngbin0 -> 341 bytes
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrary.cpp319
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrary.h80
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrary.pri12
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrary.qrc5
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrary.ui122
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp297
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.h89
-rw-r--r--src/plugins/qmldesigner/components/logger/logger.cpp171
-rw-r--r--src/plugins/qmldesigner/components/logger/logger.h81
-rw-r--r--src/plugins/qmldesigner/components/logger/logger.pri6
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigator.pri9
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp393
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigatortreemodel.h115
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigatorview.cpp227
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigatorview.h98
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigatorwidget.cpp88
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigatorwidget.h56
-rw-r--r--src/plugins/qmldesigner/components/pluginmanager/iplugin.cpp36
-rw-r--r--src/plugins/qmldesigner/components/pluginmanager/iplugin.h56
-rw-r--r--src/plugins/qmldesigner/components/pluginmanager/pluginmanager.cpp174
-rw-r--r--src/plugins/qmldesigner/components/pluginmanager/pluginmanager.h75
-rw-r--r--src/plugins/qmldesigner/components/pluginmanager/pluginmanager.pri10
-rw-r--r--src/plugins/qmldesigner/components/pluginmanager/pluginpath.cpp193
-rw-r--r--src/plugins/qmldesigner/components/pluginmanager/pluginpath.h98
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/allpropertiesbox.cpp85
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/allpropertiesbox.h64
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/basiclayouts.cpp83
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/basiclayouts.h197
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/basicwidgets.cpp1142
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/basicwidgets.h132
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/behaviordialog.cpp174
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/behaviordialog.h98
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/behaviordialog.ui472
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/colorwidget.cpp259
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/colorwidget.h108
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/filewidget.cpp87
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/filewidget.h89
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/fontwidget.cpp172
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/fontwidget.h100
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/genericpropertieswidget.cpp380
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/genericpropertieswidget.h96
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/gradientdialog.cpp353
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/gradientdialog.h89
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/gradientdialog.ui122
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/gradienteditor.cpp933
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/gradienteditor.h113
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/gradienteditor.ui1255
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/images/button2_hovered.pngbin0 -> 898 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/images/button2_normal.pngbin0 -> 898 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/images/button2_pressed.pngbin0 -> 898 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/images/button_hovered.pngbin0 -> 390 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/images/button_normal.pngbin0 -> 379 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/images/button_pressed.pngbin0 -> 1328 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/images/frame.pngbin0 -> 4826 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/images/gradient.pngbin0 -> 604 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/layoutwidget.cpp106
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/layoutwidget.h137
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditor.cpp583
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditor.h126
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditor.pri34
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditor.qrc12
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp343
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.h155
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qlayoutobject.cpp57
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qlayoutobject.h69
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qmlanchorbindingproxy.cpp287
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qmlanchorbindingproxy.h117
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qproxylayoutitem.cpp176
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qproxylayoutitem.h107
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/down.pngbin0 -> 594 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/edit.pngbin0 -> 503 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/editdelete.pngbin0 -> 831 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/minus.pngbin0 -> 250 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/plus.pngbin0 -> 462 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/spreadpad.pngbin0 -> 151 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/spreadreflect.pngbin0 -> 165 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/spreadrepeat.pngbin0 -> 156 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/typeconical.pngbin0 -> 937 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/typelinear.pngbin0 -> 145 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/typeradial.pngbin0 -> 583 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/up.pngbin0 -> 692 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/zoomin.pngbin0 -> 1208 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/zoomout.pngbin0 -> 1226 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtcolorbutton.cpp272
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtcolorbutton.h86
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtcolorbutton.pri4
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtcolorline.cpp1122
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtcolorline.h124
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientdialog.cpp353
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientdialog.h87
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientdialog.ui121
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradienteditor.cpp952
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradienteditor.h111
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradienteditor.pri33
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradienteditor.qrc18
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradienteditor.ui1377
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientmanager.cpp135
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientmanager.h92
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientstopscontroller.cpp724
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientstopscontroller.h106
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientstopsmodel.cpp477
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientstopsmodel.h121
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientstopswidget.cpp1154
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientstopswidget.h115
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientutils.cpp420
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientutils.h66
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientview.cpp292
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientview.h99
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientview.ui135
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientviewdialog.cpp89
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientviewdialog.h75
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientviewdialog.ui121
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientwidget.cpp815
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientwidget.h120
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/resetwidget.cpp129
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/resetwidget.h102
-rw-r--r--src/plugins/qmldesigner/components/resources/images/checkbox_checked.pngbin0 -> 299 bytes
-rw-r--r--src/plugins/qmldesigner/components/resources/images/checkbox_checked_hover.pngbin0 -> 302 bytes
-rw-r--r--src/plugins/qmldesigner/components/resources/images/checkbox_checked_pressed.pngbin0 -> 474 bytes
-rw-r--r--src/plugins/qmldesigner/components/resources/images/checkbox_unchecked.pngbin0 -> 190 bytes
-rw-r--r--src/plugins/qmldesigner/components/resources/images/checkbox_unchecked_hover.pngbin0 -> 190 bytes
-rw-r--r--src/plugins/qmldesigner/components/resources/images/checkbox_unchecked_pressed.pngbin0 -> 345 bytes
-rw-r--r--src/plugins/qmldesigner/components/resources/images/down_arrow.pngbin0 -> 271 bytes
-rw-r--r--src/plugins/qmldesigner/components/resources/images/down_arrow_disabled.pngbin0 -> 258 bytes
-rw-r--r--src/plugins/qmldesigner/components/resources/images/frame.pngbin0 -> 544 bytes
-rw-r--r--src/plugins/qmldesigner/components/resources/images/pushbutton.pngbin0 -> 508 bytes
-rw-r--r--src/plugins/qmldesigner/components/resources/images/pushbutton_hover.pngbin0 -> 503 bytes
-rw-r--r--src/plugins/qmldesigner/components/resources/images/pushbutton_pressed.pngbin0 -> 485 bytes
-rw-r--r--src/plugins/qmldesigner/components/resources/images/radiobutton_checked.pngbin0 -> 355 bytes
-rw-r--r--src/plugins/qmldesigner/components/resources/images/radiobutton_checked_hover.pngbin0 -> 532 bytes
-rw-r--r--src/plugins/qmldesigner/components/resources/images/radiobutton_checked_pressed.pngbin0 -> 599 bytes
-rw-r--r--src/plugins/qmldesigner/components/resources/images/radiobutton_unchecked.pngbin0 -> 240 bytes
-rw-r--r--src/plugins/qmldesigner/components/resources/images/radiobutton_unchecked_hover.pngbin0 -> 492 bytes
-rw-r--r--src/plugins/qmldesigner/components/resources/images/radiobutton_unchecked_pressed.pngbin0 -> 556 bytes
-rw-r--r--src/plugins/qmldesigner/components/resources/images/sizegrip.pngbin0 -> 129 bytes
-rw-r--r--src/plugins/qmldesigner/components/resources/images/spindown.pngbin0 -> 227 bytes
-rw-r--r--src/plugins/qmldesigner/components/resources/images/spindown_hover.pngbin0 -> 227 bytes
-rw-r--r--src/plugins/qmldesigner/components/resources/images/spindown_off.pngbin0 -> 249 bytes
-rw-r--r--src/plugins/qmldesigner/components/resources/images/spindown_pressed.pngbin0 -> 222 bytes
-rw-r--r--src/plugins/qmldesigner/components/resources/images/spinup.pngbin0 -> 236 bytes
-rw-r--r--src/plugins/qmldesigner/components/resources/images/spinup_hover.pngbin0 -> 236 bytes
-rw-r--r--src/plugins/qmldesigner/components/resources/images/spinup_off.pngbin0 -> 274 bytes
-rw-r--r--src/plugins/qmldesigner/components/resources/images/spinup_pressed.pngbin0 -> 232 bytes
-rw-r--r--src/plugins/qmldesigner/components/resources/images/up_arrow.pngbin0 -> 273 bytes
-rw-r--r--src/plugins/qmldesigner/components/resources/images/up_arrow_disabled.pngbin0 -> 266 bytes
-rw-r--r--src/plugins/qmldesigner/components/resources/resources.pri3
-rw-r--r--src/plugins/qmldesigner/components/resources/resources.qrc37
-rw-r--r--src/plugins/qmldesigner/components/resources/scrollbar.css42
-rw-r--r--src/plugins/qmldesigner/components/resources/stylesheet.css72
-rw-r--r--src/plugins/qmldesigner/components/resources/templates/Standard/Form.xml10
-rw-r--r--src/plugins/qmldesigner/components/resources/toolbutton.css23
-rw-r--r--src/plugins/qmldesigner/components/stateseditor/stateseditor.pri10
-rw-r--r--src/plugins/qmldesigner/components/stateseditor/stateseditor.qrc5
-rw-r--r--src/plugins/qmldesigner/components/stateseditor/stateseditormodel.cpp147
-rw-r--r--src/plugins/qmldesigner/components/stateseditor/stateseditormodel.h79
-rw-r--r--src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp438
-rw-r--r--src/plugins/qmldesigner/components/stateseditor/stateseditorview.h100
-rw-r--r--src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.cpp218
-rw-r--r--src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.h65
-rw-r--r--src/plugins/qmldesigner/components/stateseditor/stateslist.qml337
-rw-r--r--src/plugins/qmldesigner/components/themeloader/qts60stylethemeio.cpp357
-rw-r--r--src/plugins/qmldesigner/components/themeloader/qts60stylethemeio.h58
-rw-r--r--src/plugins/qmldesigner/components/themeloader/qts60stylethemeio.pri6
-rw-r--r--src/plugins/qmldesigner/config.pri27
-rw-r--r--src/plugins/qmldesigner/core/core.pri183
-rw-r--r--src/plugins/qmldesigner/core/core.qrc6
-rw-r--r--src/plugins/qmldesigner/core/depend_paths.pri1
-rw-r--r--src/plugins/qmldesigner/core/exceptions/exception.cpp192
-rw-r--r--src/plugins/qmldesigner/core/exceptions/invalidargumentexception.cpp75
-rw-r--r--src/plugins/qmldesigner/core/exceptions/invalididexception.cpp45
-rw-r--r--src/plugins/qmldesigner/core/exceptions/invalidmetainfoexception.cpp64
-rw-r--r--src/plugins/qmldesigner/core/exceptions/invalidmodelnodeexception.cpp64
-rw-r--r--src/plugins/qmldesigner/core/exceptions/invalidmodelstateexception.cpp65
-rw-r--r--src/plugins/qmldesigner/core/exceptions/invalidnodeinstanceexception.cpp65
-rw-r--r--src/plugins/qmldesigner/core/exceptions/invalidnodestateexception.cpp65
-rw-r--r--src/plugins/qmldesigner/core/exceptions/invalidpropertyexception.cpp74
-rw-r--r--src/plugins/qmldesigner/core/exceptions/invalidqmlsourceexception.cpp71
-rw-r--r--src/plugins/qmldesigner/core/exceptions/invalidreparentingexception.cpp62
-rw-r--r--src/plugins/qmldesigner/core/exceptions/invalidslideindexexception.cpp64
-rw-r--r--src/plugins/qmldesigner/core/exceptions/modificationgroupexception.cpp63
-rw-r--r--src/plugins/qmldesigner/core/exceptions/noanchoringpossibleexception.cpp46
-rw-r--r--src/plugins/qmldesigner/core/exceptions/notimplementedexception.cpp45
-rw-r--r--src/plugins/qmldesigner/core/exceptions/removebasestateexception.cpp64
-rw-r--r--src/plugins/qmldesigner/core/filemanager/addarraymembervisitor.cpp118
-rw-r--r--src/plugins/qmldesigner/core/filemanager/addarraymembervisitor.h72
-rw-r--r--src/plugins/qmldesigner/core/filemanager/addobjectvisitor.cpp93
-rw-r--r--src/plugins/qmldesigner/core/filemanager/addobjectvisitor.h62
-rw-r--r--src/plugins/qmldesigner/core/filemanager/addpropertyvisitor.cpp136
-rw-r--r--src/plugins/qmldesigner/core/filemanager/addpropertyvisitor.h68
-rw-r--r--src/plugins/qmldesigner/core/filemanager/astobjecttextextractor.cpp75
-rw-r--r--src/plugins/qmldesigner/core/filemanager/astobjecttextextractor.h59
-rw-r--r--src/plugins/qmldesigner/core/filemanager/changeimportsvisitor.cpp80
-rw-r--r--src/plugins/qmldesigner/core/filemanager/changeimportsvisitor.h61
-rw-r--r--src/plugins/qmldesigner/core/filemanager/changeobjecttypevisitor.cpp81
-rw-r--r--src/plugins/qmldesigner/core/filemanager/changeobjecttypevisitor.h60
-rw-r--r--src/plugins/qmldesigner/core/filemanager/changepropertyvisitor.cpp191
-rw-r--r--src/plugins/qmldesigner/core/filemanager/changepropertyvisitor.h70
-rw-r--r--src/plugins/qmldesigner/core/filemanager/changeset.cpp359
-rw-r--r--src/plugins/qmldesigner/core/filemanager/changeset.h120
-rw-r--r--src/plugins/qmldesigner/core/filemanager/filemanager.pri41
-rw-r--r--src/plugins/qmldesigner/core/filemanager/firstdefinitionfinder.cpp98
-rw-r--r--src/plugins/qmldesigner/core/filemanager/firstdefinitionfinder.h63
-rw-r--r--src/plugins/qmldesigner/core/filemanager/idcollector.cpp93
-rw-r--r--src/plugins/qmldesigner/core/filemanager/idcollector.h69
-rw-r--r--src/plugins/qmldesigner/core/filemanager/indenter.cpp90
-rw-r--r--src/plugins/qmldesigner/core/filemanager/indenter.h43
-rw-r--r--src/plugins/qmldesigner/core/filemanager/moveobjectbeforeobjectvisitor.cpp158
-rw-r--r--src/plugins/qmldesigner/core/filemanager/moveobjectbeforeobjectvisitor.h79
-rw-r--r--src/plugins/qmldesigner/core/filemanager/moveobjectvisitor.cpp293
-rw-r--r--src/plugins/qmldesigner/core/filemanager/moveobjectvisitor.h72
-rw-r--r--src/plugins/qmldesigner/core/filemanager/objectlengthcalculator.cpp91
-rw-r--r--src/plugins/qmldesigner/core/filemanager/objectlengthcalculator.h60
-rw-r--r--src/plugins/qmldesigner/core/filemanager/parser/parser.pri22
-rw-r--r--src/plugins/qmldesigner/core/filemanager/parser/qmljs.g3029
-rw-r--r--src/plugins/qmldesigner/core/filemanager/parser/qmljsast.cpp943
-rw-r--r--src/plugins/qmldesigner/core/filemanager/parser/qmljsast_p.h2665
-rw-r--r--src/plugins/qmldesigner/core/filemanager/parser/qmljsastfwd_p.h176
-rw-r--r--src/plugins/qmldesigner/core/filemanager/parser/qmljsastvisitor.cpp46
-rw-r--r--src/plugins/qmldesigner/core/filemanager/parser/qmljsastvisitor_p.h323
-rw-r--r--src/plugins/qmldesigner/core/filemanager/parser/qmljsengine_p.cpp198
-rw-r--r--src/plugins/qmldesigner/core/filemanager/parser/qmljsengine_p.h161
-rw-r--r--src/plugins/qmldesigner/core/filemanager/parser/qmljsglobal_p.h43
-rw-r--r--src/plugins/qmldesigner/core/filemanager/parser/qmljsgrammar.cpp960
-rw-r--r--src/plugins/qmldesigner/core/filemanager/parser/qmljsgrammar_p.h207
-rw-r--r--src/plugins/qmldesigner/core/filemanager/parser/qmljslexer.cpp1141
-rw-r--r--src/plugins/qmldesigner/core/filemanager/parser/qmljslexer_p.h237
-rw-r--r--src/plugins/qmldesigner/core/filemanager/parser/qmljsmemorypool_p.h120
-rw-r--r--src/plugins/qmldesigner/core/filemanager/parser/qmljsnodepool_p.h127
-rw-r--r--src/plugins/qmldesigner/core/filemanager/parser/qmljsparser.cpp1812
-rw-r--r--src/plugins/qmldesigner/core/filemanager/parser/qmljsparser_p.h230
-rw-r--r--src/plugins/qmldesigner/core/filemanager/qmldocument.cpp165
-rw-r--r--src/plugins/qmldesigner/core/filemanager/qmldocument.h109
-rw-r--r--src/plugins/qmldesigner/core/filemanager/qmleditor_global.h41
-rw-r--r--src/plugins/qmldesigner/core/filemanager/qmlrefactoring.cpp160
-rw-r--r--src/plugins/qmldesigner/core/filemanager/qmlrefactoring.h80
-rw-r--r--src/plugins/qmldesigner/core/filemanager/qmlrewriter.cpp317
-rw-r--r--src/plugins/qmldesigner/core/filemanager/qmlrewriter.h97
-rw-r--r--src/plugins/qmldesigner/core/filemanager/qmlsymbol.cpp116
-rw-r--r--src/plugins/qmldesigner/core/filemanager/qmlsymbol.h121
-rw-r--r--src/plugins/qmldesigner/core/filemanager/removepropertyvisitor.cpp108
-rw-r--r--src/plugins/qmldesigner/core/filemanager/removepropertyvisitor.h63
-rw-r--r--src/plugins/qmldesigner/core/filemanager/removeuiobjectmembervisitor.cpp139
-rw-r--r--src/plugins/qmldesigner/core/filemanager/removeuiobjectmembervisitor.h75
-rw-r--r--src/plugins/qmldesigner/core/filemanager/utils_global.h37
-rw-r--r--src/plugins/qmldesigner/core/include/abstractproperty.h127
-rw-r--r--src/plugins/qmldesigner/core/include/abstractview.h148
-rw-r--r--src/plugins/qmldesigner/core/include/anchorline.h118
-rw-r--r--src/plugins/qmldesigner/core/include/bindingproperty.h64
-rw-r--r--src/plugins/qmldesigner/core/include/bytearraymodifier.h58
-rw-r--r--src/plugins/qmldesigner/core/include/componenttextmodifier.h69
-rw-r--r--src/plugins/qmldesigner/core/include/corelib_global.h56
-rw-r--r--src/plugins/qmldesigner/core/include/customnotifications.h42
-rw-r--r--src/plugins/qmldesigner/core/include/enumeratormetainfo.h85
-rw-r--r--src/plugins/qmldesigner/core/include/exception.h72
-rw-r--r--src/plugins/qmldesigner/core/include/forwardview.h272
-rw-r--r--src/plugins/qmldesigner/core/include/import.h76
-rw-r--r--src/plugins/qmldesigner/core/include/invalidargumentexception.h55
-rw-r--r--src/plugins/qmldesigner/core/include/invalididexception.h50
-rw-r--r--src/plugins/qmldesigner/core/include/invalidmetainfoexception.h50
-rw-r--r--src/plugins/qmldesigner/core/include/invalidmodelnodeexception.h50
-rw-r--r--src/plugins/qmldesigner/core/include/invalidmodelstateexception.h50
-rw-r--r--src/plugins/qmldesigner/core/include/invalidnodeinstanceexception.h48
-rw-r--r--src/plugins/qmldesigner/core/include/invalidnodestateexception.h50
-rw-r--r--src/plugins/qmldesigner/core/include/invalidpropertyexception.h54
-rw-r--r--src/plugins/qmldesigner/core/include/invalidqmlsourceexception.h54
-rw-r--r--src/plugins/qmldesigner/core/include/invalidreparentingexception.h49
-rw-r--r--src/plugins/qmldesigner/core/include/invalidslideindexexception.h48
-rw-r--r--src/plugins/qmldesigner/core/include/itemlibraryinfo.h100
-rw-r--r--src/plugins/qmldesigner/core/include/iwidgetplugin.h52
-rw-r--r--src/plugins/qmldesigner/core/include/mathutils.h46
-rw-r--r--src/plugins/qmldesigner/core/include/metainfo.h123
-rw-r--r--src/plugins/qmldesigner/core/include/metainfoparser.h77
-rw-r--r--src/plugins/qmldesigner/core/include/model.h109
-rw-r--r--src/plugins/qmldesigner/core/include/modelmerger.h59
-rw-r--r--src/plugins/qmldesigner/core/include/modelnode.h186
-rw-r--r--src/plugins/qmldesigner/core/include/modelnodepositionstorage.h82
-rw-r--r--src/plugins/qmldesigner/core/include/modelutilities.h51
-rw-r--r--src/plugins/qmldesigner/core/include/modificationgroupexception.h47
-rw-r--r--src/plugins/qmldesigner/core/include/modificationgrouptoken.h75
-rw-r--r--src/plugins/qmldesigner/core/include/noanchoringpossibleexception.h50
-rw-r--r--src/plugins/qmldesigner/core/include/nodeabstractproperty.h63
-rw-r--r--src/plugins/qmldesigner/core/include/nodeanchors.h114
-rw-r--r--src/plugins/qmldesigner/core/include/nodeinstance.h166
-rw-r--r--src/plugins/qmldesigner/core/include/nodeinstanceview.h153
-rw-r--r--src/plugins/qmldesigner/core/include/nodelistproperty.h71
-rw-r--r--src/plugins/qmldesigner/core/include/nodemetainfo.h139
-rw-r--r--src/plugins/qmldesigner/core/include/nodeproperty.h62
-rw-r--r--src/plugins/qmldesigner/core/include/notimplementedexception.h50
-rw-r--r--src/plugins/qmldesigner/core/include/objectpropertybinding.h55
-rw-r--r--src/plugins/qmldesigner/core/include/plaintexteditmodifier.h90
-rw-r--r--src/plugins/qmldesigner/core/include/propertybinding.h62
-rw-r--r--src/plugins/qmldesigner/core/include/propertycontainer.h82
-rw-r--r--src/plugins/qmldesigner/core/include/propertymetainfo.h123
-rw-r--r--src/plugins/qmldesigner/core/include/propertynode.h48
-rw-r--r--src/plugins/qmldesigner/core/include/qmlanchors.h113
-rw-r--r--src/plugins/qmldesigner/core/include/qmlchangeset.h61
-rw-r--r--src/plugins/qmldesigner/core/include/qmlitemnode.h120
-rw-r--r--src/plugins/qmldesigner/core/include/qmlmodelnodefacade.h61
-rw-r--r--src/plugins/qmldesigner/core/include/qmlmodelview.h114
-rw-r--r--src/plugins/qmldesigner/core/include/qmlobjectnode.h103
-rw-r--r--src/plugins/qmldesigner/core/include/qmlstate.h82
-rw-r--r--src/plugins/qmldesigner/core/include/removebasestateexception.h49
-rw-r--r--src/plugins/qmldesigner/core/include/replaceallobjectdefinitionsvisitor.h59
-rw-r--r--src/plugins/qmldesigner/core/include/rewriterview.h177
-rw-r--r--src/plugins/qmldesigner/core/include/stylemanager.h68
-rw-r--r--src/plugins/qmldesigner/core/include/subcomponentmanager.h68
-rw-r--r--src/plugins/qmldesigner/core/include/textmodifier.h91
-rw-r--r--src/plugins/qmldesigner/core/include/variantproperty.h70
-rw-r--r--src/plugins/qmldesigner/core/include/widgetplugin_helper.h37
-rw-r--r--src/plugins/qmldesigner/core/include/widgetqueryview.h56
-rw-r--r--src/plugins/qmldesigner/core/instances/componentnodeinstance.cpp100
-rw-r--r--src/plugins/qmldesigner/core/instances/componentnodeinstance.h60
-rw-r--r--src/plugins/qmldesigner/core/instances/dummynodeinstance.cpp121
-rw-r--r--src/plugins/qmldesigner/core/instances/dummynodeinstance.h73
-rw-r--r--src/plugins/qmldesigner/core/instances/graphicsobjectnodeinstance.cpp226
-rw-r--r--src/plugins/qmldesigner/core/instances/graphicsobjectnodeinstance.h90
-rw-r--r--src/plugins/qmldesigner/core/instances/graphicsscenenodeinstance.cpp158
-rw-r--r--src/plugins/qmldesigner/core/instances/graphicsscenenodeinstance.h75
-rw-r--r--src/plugins/qmldesigner/core/instances/graphicsviewnodeinstance.cpp111
-rw-r--r--src/plugins/qmldesigner/core/instances/graphicsviewnodeinstance.h67
-rw-r--r--src/plugins/qmldesigner/core/instances/graphicswidgetnodeinstance.cpp185
-rw-r--r--src/plugins/qmldesigner/core/instances/graphicswidgetnodeinstance.h80
-rw-r--r--src/plugins/qmldesigner/core/instances/nodeinstance.cpp589
-rw-r--r--src/plugins/qmldesigner/core/instances/nodeinstanceview.cpp610
-rw-r--r--src/plugins/qmldesigner/core/instances/objectnodeinstance.cpp690
-rw-r--r--src/plugins/qmldesigner/core/instances/objectnodeinstance.h185
-rw-r--r--src/plugins/qmldesigner/core/instances/proxywidgetnodeinstance.cpp82
-rw-r--r--src/plugins/qmldesigner/core/instances/proxywidgetnodeinstance.h59
-rw-r--r--src/plugins/qmldesigner/core/instances/qmlgraphicsitemnodeinstance.cpp562
-rw-r--r--src/plugins/qmldesigner/core/instances/qmlgraphicsitemnodeinstance.h79
-rw-r--r--src/plugins/qmldesigner/core/instances/qmlpropertychangesnodeinstance.cpp205
-rw-r--r--src/plugins/qmldesigner/core/instances/qmlpropertychangesnodeinstance.h103
-rw-r--r--src/plugins/qmldesigner/core/instances/qmlstatenodeinstance.cpp134
-rw-r--r--src/plugins/qmldesigner/core/instances/qmlstatenodeinstance.h66
-rw-r--r--src/plugins/qmldesigner/core/instances/qmltransitionnodeinstance.cpp87
-rw-r--r--src/plugins/qmldesigner/core/instances/qmltransitionnodeinstance.h60
-rw-r--r--src/plugins/qmldesigner/core/instances/qmlviewnodeinstance.cpp88
-rw-r--r--src/plugins/qmldesigner/core/instances/qmlviewnodeinstance.h61
-rw-r--r--src/plugins/qmldesigner/core/instances/widgetnodeinstance.cpp154
-rw-r--r--src/plugins/qmldesigner/core/instances/widgetnodeinstance.h75
-rw-r--r--src/plugins/qmldesigner/core/iwidgetplugin.pri1
-rw-r--r--src/plugins/qmldesigner/core/metainfo/enumeratormetainfo.cpp153
-rw-r--r--src/plugins/qmldesigner/core/metainfo/gui.metainfo184
-rw-r--r--src/plugins/qmldesigner/core/metainfo/itemlibraryinfo.cpp208
-rw-r--r--src/plugins/qmldesigner/core/metainfo/metainfo.cpp678
-rw-r--r--src/plugins/qmldesigner/core/metainfo/metainfoparser.cpp386
-rw-r--r--src/plugins/qmldesigner/core/metainfo/nodemetainfo.cpp728
-rw-r--r--src/plugins/qmldesigner/core/metainfo/propertymetainfo.cpp441
-rw-r--r--src/plugins/qmldesigner/core/metainfo/subcomponentmanager.cpp442
-rw-r--r--src/plugins/qmldesigner/core/model/abstractproperty.cpp429
-rw-r--r--src/plugins/qmldesigner/core/model/abstractview.cpp354
-rw-r--r--src/plugins/qmldesigner/core/model/anchorline.cpp130
-rw-r--r--src/plugins/qmldesigner/core/model/bindingproperty.cpp200
-rw-r--r--src/plugins/qmldesigner/core/model/bytearraymodifier.cpp68
-rw-r--r--src/plugins/qmldesigner/core/model/componenttextmodifier.cpp127
-rw-r--r--src/plugins/qmldesigner/core/model/copyhelper.cpp89
-rw-r--r--src/plugins/qmldesigner/core/model/copyhelper.h63
-rw-r--r--src/plugins/qmldesigner/core/model/copypasteutil.cpp61
-rw-r--r--src/plugins/qmldesigner/core/model/copypasteutil.h63
-rw-r--r--src/plugins/qmldesigner/core/model/import.cpp92
-rw-r--r--src/plugins/qmldesigner/core/model/internalbindingproperty.cpp77
-rw-r--r--src/plugins/qmldesigner/core/model/internalbindingproperty.h65
-rw-r--r--src/plugins/qmldesigner/core/model/internalnode.cpp315
-rw-r--r--src/plugins/qmldesigner/core/model/internalnode_p.h144
-rw-r--r--src/plugins/qmldesigner/core/model/internalnodeabstractproperty.cpp52
-rw-r--r--src/plugins/qmldesigner/core/model/internalnodeabstractproperty.h64
-rw-r--r--src/plugins/qmldesigner/core/model/internalnodelistproperty.cpp107
-rw-r--r--src/plugins/qmldesigner/core/model/internalnodelistproperty.h71
-rw-r--r--src/plugins/qmldesigner/core/model/internalnodeproperty.cpp109
-rw-r--r--src/plugins/qmldesigner/core/model/internalnodeproperty.h67
-rw-r--r--src/plugins/qmldesigner/core/model/internalproperty.cpp175
-rw-r--r--src/plugins/qmldesigner/core/model/internalproperty.h109
-rw-r--r--src/plugins/qmldesigner/core/model/internalvariantproperty.cpp77
-rw-r--r--src/plugins/qmldesigner/core/model/internalvariantproperty.h64
-rw-r--r--src/plugins/qmldesigner/core/model/model.cpp918
-rw-r--r--src/plugins/qmldesigner/core/model/model_p.h195
-rw-r--r--src/plugins/qmldesigner/core/model/modelmerger.cpp168
-rw-r--r--src/plugins/qmldesigner/core/model/modelnode.cpp943
-rw-r--r--src/plugins/qmldesigner/core/model/modelnodepositionrecalculator.cpp100
-rw-r--r--src/plugins/qmldesigner/core/model/modelnodepositionrecalculator.h71
-rw-r--r--src/plugins/qmldesigner/core/model/modelnodepositionstorage.cpp67
-rw-r--r--src/plugins/qmldesigner/core/model/modelrewriter.cpp510
-rw-r--r--src/plugins/qmldesigner/core/model/modelrewriter.h125
-rw-r--r--src/plugins/qmldesigner/core/model/modeltotextmerger.cpp319
-rw-r--r--src/plugins/qmldesigner/core/model/modeltotextmerger.h95
-rw-r--r--src/plugins/qmldesigner/core/model/modelutilities.cpp125
-rw-r--r--src/plugins/qmldesigner/core/model/modificationgrouptoken.cpp42
-rw-r--r--src/plugins/qmldesigner/core/model/nodeabstractproperty.cpp120
-rw-r--r--src/plugins/qmldesigner/core/model/nodeanchors.cpp373
-rw-r--r--src/plugins/qmldesigner/core/model/nodelistproperty.cpp125
-rw-r--r--src/plugins/qmldesigner/core/model/nodeproperty.cpp91
-rw-r--r--src/plugins/qmldesigner/core/model/objectpropertybinding.cpp55
-rw-r--r--src/plugins/qmldesigner/core/model/painteventfilter.cpp73
-rw-r--r--src/plugins/qmldesigner/core/model/painteventfilter_p.h65
-rw-r--r--src/plugins/qmldesigner/core/model/parsedqml.cpp53
-rw-r--r--src/plugins/qmldesigner/core/model/parsedqml.h64
-rw-r--r--src/plugins/qmldesigner/core/model/paster.cpp307
-rw-r--r--src/plugins/qmldesigner/core/model/paster.h76
-rw-r--r--src/plugins/qmldesigner/core/model/plaintexteditmodifier.cpp186
-rw-r--r--src/plugins/qmldesigner/core/model/propertybinding.cpp67
-rw-r--r--src/plugins/qmldesigner/core/model/propertycontainer.cpp143
-rw-r--r--src/plugins/qmldesigner/core/model/propertynode.cpp38
-rw-r--r--src/plugins/qmldesigner/core/model/propertyparser.cpp176
-rw-r--r--src/plugins/qmldesigner/core/model/propertyparser.h49
-rw-r--r--src/plugins/qmldesigner/core/model/qmlanchors.cpp411
-rw-r--r--src/plugins/qmldesigner/core/model/qmlchangeset.cpp72
-rw-r--r--src/plugins/qmldesigner/core/model/qmlitemnode.cpp330
-rw-r--r--src/plugins/qmldesigner/core/model/qmlmodelnodefacade.cpp59
-rw-r--r--src/plugins/qmldesigner/core/model/qmlmodelview.cpp321
-rw-r--r--src/plugins/qmldesigner/core/model/qmlobjectnode.cpp401
-rw-r--r--src/plugins/qmldesigner/core/model/qmlstate.cpp288
-rw-r--r--src/plugins/qmldesigner/core/model/qmltextgenerator.cpp178
-rw-r--r--src/plugins/qmldesigner/core/model/qmltextgenerator.h67
-rw-r--r--src/plugins/qmldesigner/core/model/rewriteaction.cpp256
-rw-r--r--src/plugins/qmldesigner/core/model/rewriteaction.h261
-rw-r--r--src/plugins/qmldesigner/core/model/rewriteactioncompressor.cpp305
-rw-r--r--src/plugins/qmldesigner/core/model/rewriteactioncompressor.h63
-rw-r--r--src/plugins/qmldesigner/core/model/rewriterview.cpp459
-rw-r--r--src/plugins/qmldesigner/core/model/textmodifier.cpp36
-rw-r--r--src/plugins/qmldesigner/core/model/texttomodelmerger.cpp509
-rw-r--r--src/plugins/qmldesigner/core/model/texttomodelmerger.h159
-rw-r--r--src/plugins/qmldesigner/core/model/variantparser.cpp149
-rw-r--r--src/plugins/qmldesigner/core/model/variantparser.h65
-rw-r--r--src/plugins/qmldesigner/core/model/variantproperty.cpp143
-rw-r--r--src/plugins/qmldesigner/core/model/viewlogger.cpp200
-rw-r--r--src/plugins/qmldesigner/core/model/viewlogger.h85
-rw-r--r--src/plugins/qmldesigner/core/pluginmanager/widgetpluginmanager.cpp103
-rw-r--r--src/plugins/qmldesigner/core/pluginmanager/widgetpluginmanager.h76
-rw-r--r--src/plugins/qmldesigner/core/pluginmanager/widgetpluginpath.cpp206
-rw-r--r--src/plugins/qmldesigner/core/pluginmanager/widgetpluginpath.h102
-rw-r--r--src/plugins/qmldesigner/core/preview/stylemanager.cpp102
-rw-r--r--src/plugins/qmldesigner/core/rewritertransaction.cpp91
-rw-r--r--src/plugins/qmldesigner/core/rewritertransaction.h60
-rw-r--r--src/plugins/qmldesigner/designmode.cpp287
-rw-r--r--src/plugins/qmldesigner/designmode.h101
-rw-r--r--src/plugins/qmldesigner/designmodewidget.cpp675
-rw-r--r--src/plugins/qmldesigner/designmodewidget.h212
-rw-r--r--src/plugins/qmldesigner/fxplugin/fx.metainfo143
-rw-r--r--src/plugins/qmldesigner/fxplugin/fxplugin.cpp49
-rw-r--r--src/plugins/qmldesigner/fxplugin/fxplugin.h58
-rw-r--r--src/plugins/qmldesigner/fxplugin/fxplugin.pri17
-rw-r--r--src/plugins/qmldesigner/fxplugin/fxplugin.pro4
-rw-r--r--src/plugins/qmldesigner/fxplugin/fxplugin.qrc15
-rw-r--r--src/plugins/qmldesigner/fxplugin/images/blended-image-icon.pngbin0 -> 340 bytes
-rw-r--r--src/plugins/qmldesigner/fxplugin/images/default-icon.pngbin0 -> 341 bytes
-rw-r--r--src/plugins/qmldesigner/fxplugin/images/grid-icon.pngbin0 -> 369 bytes
-rw-r--r--src/plugins/qmldesigner/fxplugin/images/image-icon.pngbin0 -> 292 bytes
-rw-r--r--src/plugins/qmldesigner/fxplugin/images/item-icon.pngbin0 -> 293 bytes
-rw-r--r--src/plugins/qmldesigner/fxplugin/images/list-icon.pngbin0 -> 424 bytes
-rw-r--r--src/plugins/qmldesigner/fxplugin/images/mouse-region-icon.pngbin0 -> 511 bytes
-rw-r--r--src/plugins/qmldesigner/fxplugin/images/rect-icon.pngbin0 -> 237 bytes
-rw-r--r--src/plugins/qmldesigner/fxplugin/images/template_image.pngbin0 -> 4652 bytes
-rw-r--r--src/plugins/qmldesigner/fxplugin/images/text-edit-icon.pngbin0 -> 368 bytes
-rw-r--r--src/plugins/qmldesigner/fxplugin/images/text-icon.pngbin0 -> 582 bytes
-rw-r--r--src/plugins/qmldesigner/fxplugin/images/widget.pngbin0 -> 716 bytes
-rw-r--r--src/plugins/qmldesigner/fxplugin/plugindestdir.pri5
-rw-r--r--src/plugins/qmldesigner/images/mode_Design.pngbin0 -> 394 bytes
-rw-r--r--src/plugins/qmldesigner/qmldesigner.pro3
-rw-r--r--src/plugins/qmldesigner/qmldesigner_dependencies.pri3
-rw-r--r--src/plugins/qmldesigner/qmldesignerconstants.h58
-rw-r--r--src/plugins/qmldesigner/qmldesignerplugin.cpp100
-rw-r--r--src/plugins/qmldesigner/qmldesignerplugin.h68
-rw-r--r--src/plugins/qmldesigner/qmldesignerplugin.pro29
-rw-r--r--src/plugins/qmldesigner/qmldesignerplugin.qrc5
-rw-r--r--src/plugins/qmleditor/qmleditor.cpp1
-rw-r--r--src/plugins/qmleditor/qmlhoverhandler.cpp10
-rw-r--r--src/plugins/qmleditor/qmllookupcontext.cpp2
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectmanager.cpp16
-rw-r--r--src/plugins/qmlprojectmanager/qmltaskmanager.cpp2
-rw-r--r--src/shared/qml/metatype/QtDeclarativeMetaTypeBackend.cpp6
-rw-r--r--src/shared/qml/metatype/exception.cpp2
-rw-r--r--src/shared/qml/metatype/invalidmetainfoexception.cpp2
-rw-r--r--src/shared/qml/metatype/metainfo.cpp6
-rw-r--r--src/shared/qml/metatype/nodemetainfo.cpp4
-rw-r--r--src/shared/qml/metatype/propertymetainfo.cpp4
-rw-r--r--src/shared/qml/qml.pri2
-rw-r--r--src/shared/qml/qmlsymbol.cpp15
-rw-r--r--src/shared/qml/qmlsymbol.h2
-rw-r--r--src/tools/qmldesigner/qmldom/main.cpp173
-rw-r--r--src/tools/qmldesigner/qmldom/qmldom.pro21
-rw-r--r--src/tools/qmldesigner/standalone/128xBauhaus_Logo.pngbin0 -> 15545 bytes
-rw-r--r--src/tools/qmldesigner/standalone/16xBauhaus_Logo.pngbin0 -> 537 bytes
-rw-r--r--src/tools/qmldesigner/standalone/256xBauhaus_Logo.pngbin0 -> 54353 bytes
-rw-r--r--src/tools/qmldesigner/standalone/32xBauhaus_Logo.pngbin0 -> 36752 bytes
-rw-r--r--src/tools/qmldesigner/standalone/512xBauhaus_Logo.pngbin0 -> 154832 bytes
-rw-r--r--src/tools/qmldesigner/standalone/64xBauhaus_Logo.pngbin0 -> 4512 bytes
-rw-r--r--src/tools/qmldesigner/standalone/Info.plist189
-rw-r--r--src/tools/qmldesigner/standalone/aboutdialog.cpp95
-rw-r--r--src/tools/qmldesigner/standalone/aboutdialog.h53
-rw-r--r--src/tools/qmldesigner/standalone/application.cpp43
-rw-r--r--src/tools/qmldesigner/standalone/application.h40
-rw-r--r--src/tools/qmldesigner/standalone/bauhaus-logo.icnsbin0 -> 267319 bytes
-rw-r--r--src/tools/qmldesigner/standalone/bauhaus-macos.css0
-rw-r--r--src/tools/qmldesigner/standalone/bauhaus-windows.css3
-rw-r--r--src/tools/qmldesigner/standalone/bauhaus-x11.css3
-rw-r--r--src/tools/qmldesigner/standalone/bauhaus.css28
-rw-r--r--src/tools/qmldesigner/standalone/bauhaus.icobin0 -> 22382 bytes
-rw-r--r--src/tools/qmldesigner/standalone/bauhaus.qrc19
-rw-r--r--src/tools/qmldesigner/standalone/css.pngbin0 -> 4170 bytes
-rw-r--r--src/tools/qmldesigner/standalone/edit.pngbin0 -> 3573 bytes
-rw-r--r--src/tools/qmldesigner/standalone/main.cpp162
-rw-r--r--src/tools/qmldesigner/standalone/mainwindow.cpp565
-rw-r--r--src/tools/qmldesigner/standalone/mainwindow.h120
-rw-r--r--src/tools/qmldesigner/standalone/preview.pngbin0 -> 1681 bytes
-rw-r--r--src/tools/qmldesigner/standalone/standalone.pro44
-rw-r--r--src/tools/qmldesigner/standalone/templates/fx.qml7
-rw-r--r--src/tools/qmldesigner/standalone/templates/qgraphicsview.qml10
-rw-r--r--src/tools/qmldesigner/standalone/templates/qwidget.qml9
-rw-r--r--src/tools/qmldesigner/standalone/toolbar-cssedit.pngbin0 -> 1808 bytes
-rw-r--r--src/tools/qmldesigner/standalone/toolbar-edit.pngbin0 -> 1142 bytes
-rw-r--r--src/tools/qmldesigner/standalone/welcomescreen.cpp150
-rw-r--r--src/tools/qmldesigner/standalone/welcomescreen.h77
-rw-r--r--tests/auto/auto.pro3
-rw-r--r--tests/auto/qml/qml.pro3
-rw-r--r--tests/auto/qml/qmldesigner/bauhaustests/bauhaustests.pro18
-rw-r--r--tests/auto/qml/qmldesigner/bauhaustests/testbauhaus.cpp122
-rw-r--r--tests/auto/qml/qmldesigner/bauhaustests/testbauhaus.h51
-rw-r--r--tests/auto/qml/qmldesigner/common/statichelpers.cpp174
-rw-r--r--tests/auto/qml/qmldesigner/coretests/coretests.pro22
-rw-r--r--tests/auto/qml/qmldesigner/coretests/testcore.cpp6485
-rw-r--r--tests/auto/qml/qmldesigner/coretests/testcore.h233
-rw-r--r--tests/auto/qml/qmldesigner/coretests/testrewriterview.cpp113
-rw-r--r--tests/auto/qml/qmldesigner/coretests/testrewriterview.h68
-rw-r--r--tests/auto/qml/qmldesigner/data/fx/attributes.qml8
-rw-r--r--tests/auto/qml/qmldesigner/data/fx/bigtest.qml78
-rw-r--r--tests/auto/qml/qmldesigner/data/fx/components.qml26
-rw-r--r--tests/auto/qml/qmldesigner/data/fx/empty.qml4
-rw-r--r--tests/auto/qml/qmldesigner/data/fx/helloworld.qml76
-rw-r--r--tests/auto/qml/qmldesigner/data/fx/image.qml10
-rw-r--r--tests/auto/qml/qmldesigner/data/fx/properties.qml5
-rw-r--r--tests/auto/qml/qmldesigner/data/fx/selectiontest.qml39
-rw-r--r--tests/auto/qml/qmldesigner/data/fx/states.qml59
-rw-r--r--tests/auto/qml/qmldesigner/data/fx/subitems/SubItem.qml14
-rw-r--r--tests/auto/qml/qmldesigner/data/fx/topitem.qml17
-rw-r--r--tests/auto/qml/qmldesigner/data/qt-logo.pngbin0 -> 23519 bytes
-rw-r--r--tests/auto/qml/qmldesigner/data/qwidget/test.qml27
-rw-r--r--tests/auto/qml/qmldesigner/data/testfiles.qrc11
-rw-r--r--tests/auto/qml/qmldesigner/propertyeditortests/propertyeditortests.pro24
-rw-r--r--tests/auto/qml/qmldesigner/propertyeditortests/testpropertyeditor.cpp370
-rw-r--r--tests/auto/qml/qmldesigner/propertyeditortests/testpropertyeditor.h57
-rw-r--r--tests/auto/qml/qmldesigner/qmldesigner.pro5
-rw-r--r--tests/auto/qml/qmldesigner/testview.cpp213
-rw-r--r--tests/auto/qml/qmldesigner/testview.h93
743 files changed, 102919 insertions, 23 deletions
diff --git a/.gitignore b/.gitignore
index 85e9a5aca7..15a20a779f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -73,3 +73,6 @@ bin/qtcreator_process_stub*
bin/qtcreator.exe
share/doc/qtcreator/qtcreator.qch
tests/manual/cplusplus/cplusplus0
+tests/auto/qml/qmldesigner/bauhaustests/tst_bauhaus
+tests/auto/qml/qmldesigner/coretests/tst_qmldesigner_core
+tests/auto/qml/qmldesigner/propertyeditortests/tst_propertyeditor
diff --git a/share/qtcreator/qmldesigner/Button.qml b/share/qtcreator/qmldesigner/Button.qml
new file mode 100644
index 0000000000..22b2a9c063
--- /dev/null
+++ b/share/qtcreator/qmldesigner/Button.qml
@@ -0,0 +1,86 @@
+import Qt 4.6
+
+Rectangle {
+ property var label: "Button"
+ signal clicked
+
+ width: 75
+ height: 20
+ radius: 10
+ color: "grey"
+
+ Rectangle {
+ anchors.fill: parent;
+ anchors.leftMargin: 1;
+ anchors.rightMargin: 1;
+ anchors.topMargin: 1;
+ anchors.bottomMargin: 1;
+
+ color: "#2c2c2c";
+ radius: 9
+
+ Rectangle {
+ id: buttonGradientRectangle
+ anchors.fill: parent;
+ anchors.leftMargin: 1;
+ anchors.rightMargin: 1;
+ anchors.topMargin: 1;
+ anchors.bottomMargin: 1;
+
+ color: "black";
+ gradient: normalGradient
+ radius: 8;
+
+ Gradient {
+ id: pressedGradient
+ GradientStop { position: 0.0; color: "#686868" }
+ GradientStop { position: 1.0; color: "#8a8a8a" }
+ }
+
+ Gradient {
+ id: normalGradient
+ GradientStop { position: 0.0; color: "#8a8a8a" }
+ GradientStop { position: 1.0; color: "#686868" }
+ }
+ }
+ }
+
+ Text {
+ color: "white"
+ text: parent.label
+ style: "Raised";
+ anchors.left: parent.left
+ anchors.top: parent.top
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ horizontalAlignment: "AlignHCenter";
+ verticalAlignment: "AlignVCenter";
+ }
+
+ MouseRegion {
+ id: mouseRegion
+ anchors.fill: parent
+ onReleased: { parent.clicked.emit(); }
+ }
+
+ states: [
+ State {
+ name: "released"
+ when: !mouseRegion.pressed
+
+ PropertyChanges {
+ target: buttonGradientRectangle
+ gradient: normalGradient
+ }
+ },
+ State {
+ name: "pressed"
+ when: mouseRegion.pressed
+
+ PropertyChanges {
+ target: buttonGradientRectangle
+ gradient: pressedGradient
+ }
+ }
+ ]
+}
diff --git a/share/qtcreator/qmldesigner/gradient.png b/share/qtcreator/qmldesigner/gradient.png
new file mode 100644
index 0000000000..dd71b4b691
--- /dev/null
+++ b/share/qtcreator/qmldesigner/gradient.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/AnchorBox.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/AnchorBox.qml
new file mode 100644
index 0000000000..d76e657d67
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/AnchorBox.qml
@@ -0,0 +1,199 @@
+import Qt 4.6
+
+QWidget {
+ width:220;fixedWidth: width
+ height:220;fixedHeight: height
+ styleSheetFile: "anchorbox.css"
+
+ Script {
+ function isBorderAnchored() {
+ return anchorBackend.leftAnchored || anchorBackend.topAnchored || anchorBackend.rightAnchored || anchorBackend.bottomAnchored;
+ }
+
+ function fill() {
+ anchorBackend.fill();
+ }
+
+ function breakLayout() {
+ anchorBackend.resetLayout()
+ }
+ }
+
+ QPushButton {
+ text: "fill";
+ height:20;fixedHeight: height;
+ x: 0;
+ y: 0;
+ width:200;fixedWidth: width;
+ id: QPushButton1;
+ onReleased: fill();
+ }
+
+ QPushButton {
+ text: "break";
+ y: 200;
+ height:20;fixedHeight: height;
+ width:200;fixedWidth: width;
+ x: 0;
+ id: QPushButton3;
+ onReleased: breakLayout();
+ }
+
+ QPushButton {
+ height:100;fixedHeight: height;
+ text: "left";
+ font.bold: true;
+ x: 16 ;
+ y: 60;
+ //styleSheet: "border-radius:5px; background-color: #ffda82";
+ width:30;fixedWidth: width;
+ id: QPushButton5;
+ checkable: true;
+ checked: anchorBackend.leftAnchored;
+ onReleased: {
+ if (checked) {
+ anchorBackend.horizontalCentered = false;
+ anchorBackend.leftAnchored = true;
+ } else {
+ anchorBackend.leftAnchored = false;
+ }
+ }
+ }
+
+ QPushButton {
+ text: "top";
+ font.bold: true;
+ //styleSheet: "border-radius:5px; background-color: #ffda82";
+ height:72;fixedHeight: height;
+ width:100;fixedWidth: width;
+ x: 49;
+ y: 30;
+ id: QPushButton6;
+ checkable: true;
+ checked: anchorBackend.topAnchored;
+ onReleased: {
+ if (checked) {
+ anchorBackend.verticalCentered = false;
+ anchorBackend.topAnchored = true;
+ } else {
+ anchorBackend.topAnchored = false;
+ }
+ }
+ }
+
+ QPushButton {
+ text: "right";
+ font.bold: true;
+ x: 153;
+ y: 60;
+ //styleSheet: "border-radius:5px; background-color: #ffda82";
+ width:30;fixedWidth: width;
+ height:100;fixedHeight: height;
+ id: QPushButton7;
+ checkable: true;
+ checked: anchorBackend.rightAnchored;
+ onReleased: {
+ if (checked) {
+ anchorBackend.horizontalCentered = false;
+ anchorBackend.rightAnchored = true;
+ } else {
+ anchorBackend.rightAnchored = false;
+ }
+ }
+ }
+
+ QPushButton {
+ text: "bottom";
+ font.bold: true;
+ //styleSheet: "border-radius:5px; background-color: #ffda82";
+ width:100;fixedWidth: width;
+ x: 49;
+ y: 164;
+ height:27;fixedHeight: height;
+ id: QPushButton8;
+ checkable: true;
+ checked: anchorBackend.bottomAnchored;
+ onReleased: {
+ if (checked) {
+ anchorBackend.verticalCentered = false;
+ anchorBackend.bottomAnchored = true;
+ } else {
+ anchorBackend.bottomAnchored = false;
+ }
+ }
+ }
+
+ QToolButton {
+ width:100;fixedWidth: width;
+ //styleSheet: "border-radius:50px;background-color: rgba(85, 170, 255, 255)";
+ x: 49;
+ y: 60;
+ height:100;fixedHeight: height;
+ id: QPushButton9;
+
+ QPushButton {
+ width:24;fixedWidth: width;
+ //styleSheet: "border-radius:5px; background-color: #bf3f00;";
+ x: 38;
+ y: 2;
+ height:96;fixedHeight: height;
+ checkable: true;
+ id: horizontalCenterButton;
+ checked: anchorBackend.horizontalCentered;
+ onReleased: {
+ if (checked) {
+ anchorBackend.rightAnchored = false;
+ anchorBackend.leftAnchored = false;
+ anchorBackend.horizontalCentered = true;
+ } else {
+ anchorBackend.horizontalCentered = false;
+ }
+ }
+ }
+
+ QPushButton {
+ height:24;fixedHeight: height;
+ x: 2;
+ y: 38;
+ width:96;fixedWidth: width;
+ id: verticalCenterButton;
+ checkable: true;
+ checked: anchorBackend.verticalCentered;
+ onReleased: {
+ if (checked) {
+ anchorBackend.topAnchored = false;
+ anchorBackend.bottomAnchored = false;
+ anchorBackend.verticalCentered = true;
+ } else {
+ anchorBackend.verticalCentered = false;
+ }
+ }
+ }
+
+ QPushButton {
+ text: "center";
+ font.bold: true;
+ //styleSheet: "border-radius:20px; background-color: #ff5500";
+ width:40;fixedWidth: width;
+ height:40;fixedHeight: height;
+ x: 30;
+ y: 30;
+ id: centerButton;
+ checkable: true;
+ checked: anchorBackend.verticalCentered && anchorBackend.horizontalCentered;
+ onReleased: {
+ if (checked) {
+ anchorBackend.leftAnchored = false;
+ anchorBackend.topAnchored = false;
+ anchorBackend.rightAnchored = false;
+ anchorBackend.bottomAnchored = false;
+ anchorBackend.verticalCentered = true;
+ anchorBackend.horizontalCentered = true;
+ } else {
+ anchorBackend.verticalCentered = false;
+ anchorBackend.horizontalCentered = false;
+ }
+ }
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/BorderImageSpecifics.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/BorderImageSpecifics.qml
new file mode 100644
index 0000000000..ed26dbc374
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/BorderImageSpecifics.qml
@@ -0,0 +1,69 @@
+import Qt 4.6
+import Bauhaus 1.0
+
+GroupBox {
+ maximumHeight: 240;
+
+
+ finished: finishedNotify;
+ caption: "Image";
+
+ layout: QVBoxLayout {
+ topMargin: 12;
+ bottomMargin: 12;
+ leftMargin: 12;
+ rightMargin: 12;
+
+ FileWidget {
+ enabled: isBaseState || backendValues.id.value != "";
+ maximumWidth: 250;
+ text: "Source: ";
+ fileName: backendValues.source.value;
+ onFileNameChanged: {
+ backendValues.source.value = fileName;
+ }
+ }
+
+
+ IntEditor {
+ id: pixelSize;
+ backendValue: backendValues.border_left;
+ caption: "Border Left: "
+ baseStateFlag: isBaseState;
+
+ step: 1;
+ minimumValue: 0;
+ maximumValue: 2000;
+ }
+
+ IntEditor {
+ backendValue: backendValues.border_right;
+ caption: "Border Right: "
+ baseStateFlag: isBaseState;
+
+ step: 1;
+ minimumValue: 0;
+ maximumValue: 2000;
+ }
+
+ IntEditor {
+ backendValue: backendValues.border_top;
+ caption: "Border Top: "
+ baseStateFlag: isBaseState;
+
+ step: 1;
+ minimumValue: 0;
+ maximumValue: 2000;
+ }
+
+ IntEditor {
+ backendValue: backendValues.border_bottom;
+ caption: "Border Bottom:"
+ baseStateFlag: isBaseState;
+
+ step: 1;
+ minimumValue: 0;
+ maximumValue: 2000;
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/CheckBox.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/CheckBox.qml
new file mode 100644
index 0000000000..f5ad1b91ac
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/CheckBox.qml
@@ -0,0 +1,38 @@
+import Qt 4.6
+
+QCheckBox { //This is a special CheckBox that does color coding for states
+ id: CheckBox;
+
+ property var backendValue;
+ property var baseStateFlag;
+
+ checkable: true;
+ checked: backendValue.value === undefined ? false : backendValue.value;
+ onToggled: {
+ backendValue.value = checked;
+ }
+
+ onBaseStateFlagChanged: {
+ evaluate();
+ }
+
+ onBackendValueChanged: {
+ evaluate();
+ }
+
+ Script {
+ function evaluate() {
+ if (baseStateFlag) {
+ if (backendValue.isInModel)
+ CheckBox.setStyleSheet("color: white;");
+ else
+ CheckBox.setStyleSheet("color: gray;");
+ } else {
+ if (backendValue.IsInSubState)
+ CheckBox.setStyleSheet("color: blue;");
+ else
+ CheckBox.setStyleSheet("color: gray;");
+ }
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/ColumnSpecifics.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/ColumnSpecifics.qml
new file mode 100644
index 0000000000..f95f56a101
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/ColumnSpecifics.qml
@@ -0,0 +1,29 @@
+import Qt 4.6
+import Bauhaus 1.0
+
+GroupBox {
+ maximumHeight: 200;
+
+ finished: finishedNotify;
+ caption: "Grid";
+ id: GridSpecifics;
+
+ layout: QVBoxLayout {
+
+ topMargin: 18;
+ bottomMargin: 2;
+ leftMargin: 8;
+ rightMargin: 8;
+
+
+ IntEditor {
+ id: spacing;
+ backendValue: backendValues.spacing;
+ caption: "Spacing: "
+ baseStateFlag: isBaseState;
+ step: 1;
+ minimumValue: 0;
+ maximumValue: 2000;
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/DoubleSpinBox.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/DoubleSpinBox.qml
new file mode 100644
index 0000000000..d792680479
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/DoubleSpinBox.qml
@@ -0,0 +1,144 @@
+import Qt 4.6
+import Bauhaus 1.0
+
+QWidget { //This is a special DoubleSpinBox that does color coding for states
+ id: DoubleSpinBox;
+
+ property var backendValue;
+ property var baseStateFlag;
+ property alias singleStep: box.singleStep
+ property alias minimum: box.minimum
+ property alias maximum: box.maximum
+
+ minimumHeight: 22;
+
+ onBaseStateFlagChanged: {
+ evaluate();
+ setIcon();
+ }
+
+ onBackendValueChanged: {
+ evaluate();
+ setIcon();
+ }
+
+ Script {
+ function evaluate() {
+ if (baseStateFlag) {
+ if (backendValue != null && backendValue.isInModel)
+ DoubleSpinBox.setStyleSheet("color: white;");
+ else
+ DoubleSpinBox.setStyleSheet("color: gray;");
+ } else {
+ if (backendValue != null && backendValue.isInSubState)
+ DoubleSpinBox.setStyleSheet("color: blue;");
+ else
+ DoubleSpinBox.setStyleSheet("color: gray;");
+ }
+ }
+ }
+
+ layout: QHBoxLayout {
+ topMargin: 0;
+ bottomMargin: 0;
+ leftMargin: 0;
+ rightMargin: 2;
+ spacing: 0;
+
+ QDoubleSpinBox {
+ id: box;
+ decimals: 2;
+ keyboardTracking: false;
+ enabled: (backendValue == null || backendValue.complexNode == null) ? false : !backendValue.isBound && !backendValue.complexNode.exists
+ value: DoubleSpinBox.backendValue == null ? .0 : DoubleSpinBox.backendValue.value;
+ onValueChanged: {
+ if (DoubleSpinBox.backendValue != null)
+ DoubleSpinBox.backendValue.value = value;
+ }
+ onFocusChanged: {
+ //extendedSwitches.active = focus;
+ //extendedSwitches.backendValue = backendValue;
+ }
+
+ onMouseOverChanged: {
+ //extendedButton.active = mouseOver;
+ }
+ }
+ }
+
+ QToolButton {
+ property bool active: false;
+ id: extendedButton;
+ iconFromFile: "images/expression.png";
+ visible: false;
+ width: 14;
+ height: 14;
+ y: box.y + 2;
+ x: box.x + 2;
+ focusPolicy: "Qt::NoFocus";
+ opacity: 0;
+
+ opacity: Behavior {
+ NumberAnimation {
+ easing: "easeInSine"
+ duration: 200
+ }
+ }
+
+ onPressed: {
+
+ }
+
+ Script {
+ function setIcon() {
+ if (backendValue == null)
+ extendedButton.iconFromFile = "images/placeholder.png"
+ else if (backendValue.isBound) {
+ extendedButton.iconFromFile = "images/expression.png"
+ } else {
+ if (backendValue.complexNode != null && backendValue.complexNode.exists) {
+ extendedButton.iconFromFile = "images/behaivour.png"
+ } else {
+ extendedButton.iconFromFile = "images/placeholder.png"
+ }
+ }
+ }
+ }
+
+ onMouseOverChanged: {
+ if (mouseOver) {
+ iconFromFile = "images/submenu.png";
+ opacity = 1;
+ } else {
+ setIcon();
+ opacity = 0;
+ }
+ }
+
+ onActiveChanged: {
+ if (active) {
+ setIcon();
+ opacity = 1;
+ } else {
+ opacity = 0;
+ }
+ }
+
+ menu: QMenu {
+ actions: [
+ QAction {
+ text: "Reset";
+ },
+ QAction {
+ text: "Set Expression";
+ },
+ QAction {
+ text: "Add Behaivour";
+ }
+ ]
+ }
+ toolButtonStyle: "Qt::ToolButtonIconOnly";
+ popupMode: "QToolButton::InstantPopup";
+ arrowType: "Qt::NoArrow";
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/Extended.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/Extended.qml
new file mode 100644
index 0000000000..ad568ffd0a
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/Extended.qml
@@ -0,0 +1,191 @@
+import Qt 4.6
+import Bauhaus 1.0
+
+GroupBox {
+caption: "Effects"
+id: Extended;
+maximumHeight: 260;
+
+layout: QVBoxLayout {
+ topMargin: 12;
+ leftMargin: 10;
+ rightMargin: 10;
+
+ property var effect: backendValues == null || backendValues.effect === undefined ? null : backendValues.effect
+ property var complexNode : effect === null ? null : effect.complexNode
+
+ QWidget {
+ maximumHeight: 40;
+ layout: QHBoxLayout {
+ QLabel {
+ text: "Effects: ";
+ font.bold: true;
+ }
+ QComboBox {
+ enabled: isBaseState;
+ property var type: complexNode == null ? null : complexNode.type
+ property var dirty;
+ id: effectComboBox;
+ items : { [
+ "None",
+ "Blur",
+ "Opacity",
+ "Colorize",
+ "DropShadow"
+ ] }
+
+ onCurrentTextChanged: {
+ if (dirty) //avoid recursion;
+ return;
+ if (complexNode != null && complexNode.exists)
+ complexNode.remove();
+ if (currentText == "None") {
+ ;
+ } else if (complexNode != null) {
+ complexNode.add("Qt/" + currentText);
+ }
+ }
+
+ onTypeChanged: {
+ dirty = true;
+ if (complexNode != null && complexNode.type != "")
+ currentText = complexNode.type;
+ else
+ currentText = "None";
+ dirty = false;
+ }
+ }
+ }
+ }// QWidget
+
+ property var properties: complexNode == null ? null : complexNode.properties
+
+ QWidget {
+ minimumHeight: 20;
+ layout: QVBoxLayout {
+
+ QWidget {
+ visible: effectComboBox.currentText == "Blur";
+ layout: QVBoxLayout {
+ topMargin: 12;
+ IntEditor {
+ id: blurRadius;
+ backendValue: properties == null ? null : properties.blurRadius;
+ caption: "Blur Radius:"
+ baseStateFlag: isBaseState;
+
+ step: 1;
+ minimumValue: 0;
+ maximumValue: 20;
+ }
+ }
+ }
+
+ QWidget {
+ visible: effectComboBox.currentText == "Opacity";
+ layout: QVBoxLayout {
+ DoubleSpinBox {
+ id: OpcacityEffectSpinBox;
+ objectName: "OpcacityEffectSpinBox";
+ backendValue: properties == null ? null : properties.opacity;
+ minimum: 0;
+ maximum: 1;
+ singleStep: 0.1;
+ baseStateFlag: isBaseState;
+ }
+ }
+ }
+
+ QWidget {
+ visible: effectComboBox.currentText == "Colorize";
+ layout: QVBoxLayout {
+
+ property var colorProp: properties == null ? null : properties.color
+
+ ColorWidget {
+ id: ColorizeColor;
+ text: "Color:";
+ minimumHeight: 20;
+ minimumWidth: 20;
+ color: (colorProp == null) ? "black" : colorProp.value;
+ onColorChanged: {
+ colorProp.value = strColor;
+ }
+ }
+
+ }
+ }
+
+ QWidget {
+ visible: effectComboBox.currentText == "Pixelize";
+ layout: QVBoxLayout {
+ topMargin: 12;
+ IntEditor {
+ id: pixelSize;
+ backendValue: properties == null ? null : properties.pixelSize;
+ caption: "Pixel Size:"
+ baseStateFlag: isBaseState;
+
+ step: 1;
+ minimumValue: 0;
+ maximumValue: 20;
+ }
+ }
+ }
+
+ QWidget {
+ visible: effectComboBox.currentText == "DropShadow";
+ layout: QVBoxLayout {
+
+ topMargin: 12;
+ IntEditor {
+ id: blurRadiusShadow;
+ backendValue: properties == null ? null : properties.blurRadius;
+ caption: "Blur Radius:"
+ baseStateFlag: isBaseState;
+
+ step: 1;
+ minimumValue: 0;
+ maximumValue: 20;
+ }
+
+ ColorWidget {
+ id: DropShadowColor;
+ maximumHeight: 40;
+ text: "Color:";
+ minimumHeight: 20;
+ minimumWidth: 20;
+ color: properties == null || properties.color == null ? "black" : properties.color.value
+ onColorChanged: {
+ if (properties != null && properties.color != null)
+ properties.color.value = strColor;
+ }
+ }
+
+ IntEditor {
+ id: xOffset;
+ backendValue: properties == null ? 0 : properties.xOffset;
+ caption: "x Offset: "
+ baseStateFlag: isBaseState;
+
+ step: 1;
+ minimumValue: 0;
+ maximumValue: 20;
+ }
+
+ IntEditor {
+ id: yOffset;
+ backendValue: properties == null ? 0 : properties.yOffset;
+ caption: "y Offset: "
+ baseStateFlag: isBaseState;
+
+ step: 1;
+ minimumValue: 0;
+ maximumValue: 20;
+ }
+ }
+ }
+ }
+ }
+ } //QVBoxLayout
+} //GroupBox
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/ExtendedPane.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/ExtendedPane.qml
new file mode 100644
index 0000000000..8283e6ecdb
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/ExtendedPane.qml
@@ -0,0 +1,30 @@
+import Qt 4.6
+import Bauhaus 1.0
+
+QScrollArea {
+ widgetResizable: true;
+ styleSheetFile: ":/qmldesigner/scrollbar.css";
+ horizontalScrollBarPolicy: "Qt::ScrollBarAlwaysOff";
+ id: ExtendedPane;
+ visible: false;
+ visible: false;
+ content: ProperyEditorExtended;
+ QFrame {
+ minimumHeight: 440;
+ id: ProperyEditorExtended
+ layout: QVBoxLayout {
+ topMargin: 2;
+ bottomMargin: 2;
+ leftMargin: 2;
+ rightMargin: 2;
+ Type {
+ }
+ Extended {
+ id: extendedBox;
+ }
+
+ QScrollArea {
+ }
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/ExtendedSwitches.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/ExtendedSwitches.qml
new file mode 100644
index 0000000000..508711314b
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/ExtendedSwitches.qml
@@ -0,0 +1,60 @@
+import Qt 4.6
+import Bauhaus 1.0
+
+QFrame {
+ visible: false;
+ focusPolicy: "Qt::NoFocus"
+ id: extendedSwitches;
+ property bool active: false;
+ property var backendValue;
+ styleSheetFile: "switch.css";
+ property var specialModeIcon;
+ specialModeIcon: "images/standard.png";
+
+ opacity: 0;
+
+ opacity: Behavior {
+ NumberAnimation {
+ easing: "easeInSine"
+ duration: 200
+ }
+ }
+
+ onActiveChanged: {
+ if (!nameLineEdit.focus)
+ if (active) {
+ opacity = 1;
+ } else {
+ opacity = 0;
+ }
+ }
+
+ layout: QHBoxLayout {
+ topMargin: 6;
+ bottomMargin: 4;
+ leftMargin: 10;
+ rightMargin: 8;
+ spacing: 4;
+
+ QPushButton {
+ focusPolicy: "Qt::NoFocus"
+ onReleased: backendValue.resetValue();
+ iconFromFile: "images/reset-button.png";
+ toolTip: "reset property";
+ }
+
+ QLineEdit {
+ id: nameLineEdit;
+ readOnly: false;
+ //focusPolicy: "Qt::NoFocus"
+ text: backendValue == null ? "" : backendValue.expression;
+ onEditingFinished: {
+ if (backendValue != null)
+ backendValue.expression = text;
+ }
+ onFocusChanged: {
+ extendedSwitches.active = focus;
+ }
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/FlickableSpecifics.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/FlickableSpecifics.qml
new file mode 100644
index 0000000000..758fc1a3ca
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/FlickableSpecifics.qml
@@ -0,0 +1,111 @@
+import Qt 4.6
+import Bauhaus 1.0
+
+GroupBox {
+ finished: finishedNotify;
+ caption: "Flickable";
+
+ layout: QVBoxLayout {
+ topMargin: 15;
+ bottomMargin: 6;
+ leftMargin: 0;
+ rightMargin: 0;
+
+ QWidget {
+ id: contentWidget;
+ maximumHeight: 220;
+
+ layout: QHBoxLayout {
+ topMargin: 0;
+ bottomMargin: 0;
+ leftMargin: 10;
+ rightMargin: 10;
+
+ QWidget {
+ layout: QVBoxLayout {
+ topMargin: 0;
+ bottomMargin: 0;
+ leftMargin: 0;
+ rightMargin: 0;
+ QLabel {
+ minimumHeight: 20;
+ text: "Horizontal Velocity:"
+ font.bold: true;
+ }
+
+ QLabel {
+ minimumHeight: 20;
+ text: "Vertical Velocity:"
+ font.bold: true;
+ }
+
+ QLabel {
+ minimumHeight: 20;
+ text: "Maximum Flick Velocity:"
+ font.bold: true;
+ }
+
+ QLabel {
+ minimumHeight: 20;
+ text: "Over Shoot:"
+ font.bold: true;
+ }
+ }
+ }
+
+
+ QWidget {
+ layout: QVBoxLayout {
+ topMargin: 0;
+ bottomMargin: 0;
+ leftMargin: 0;
+ rightMargin: 0;
+
+
+ DoubleSpinBox {
+ id: HorizontalVelocitySpinBox;
+ objectName: "HorizontalVelocitySpinBox";
+ backendValue: backendValues.horizontalVelocity;
+ minimumWidth: 30;
+ minimum: 0.1
+ maximum: 10
+ singleStep: 0.1
+ baseStateFlag: isBaseState;
+ }
+
+ DoubleSpinBox {
+ id: VerticalVelocitySpinBox;
+ objectName: "VerticalVelocitySpinBox";
+ backendValue: backendValues.verticalVelocity;
+ minimumWidth: 30;
+ minimum: 0.1
+ maximum: 10
+ singleStep: 0.1
+ baseStateFlag: isBaseState;
+ }
+
+ DoubleSpinBox {
+ id: MaximumVelocitySpinBox;
+ objectName: "MaximumVelocitySpinBox";
+ backendValue: backendValues.maximumFlickVelocity;
+ minimumWidth: 30;
+ minimum: 0.1
+ maximum: 10
+ singleStep: 0.1
+ baseStateFlag: isBaseState;
+ }
+
+ CheckBox {
+ id: OvershootCheckBox;
+ text: "overshoot";
+ backendValue: backendValues.overShoot;
+ baseStateFlag: isBaseState;
+ checkable: true;
+ }
+ }
+ }
+
+ }
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/FlipableSpecifics.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/FlipableSpecifics.qml
new file mode 100644
index 0000000000..a5efb0d319
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/FlipableSpecifics.qml
@@ -0,0 +1,135 @@
+import Qt 4.6
+import Bauhaus 1.0
+
+GroupBox {
+ maximumHeight: 200;
+
+ finished: finishedNotify;
+ caption: "Text";
+
+ layout: QVBoxLayout {
+ id: textSpecifics;
+ topMargin: 4;
+ bottomMargin: 2;
+ leftMargin: 4;
+ rightMargin: 4;
+ QWidget {
+ layout: QHBoxLayout {
+ topMargin: 8;
+ bottomMargin: 2;
+ leftMargin: 10;
+ rightMargin: 10;
+ QLabel {
+ text: "Text:"
+ font.bold: true;
+ }
+ QLineEdit {
+ text: backendValues.text.value;
+ onTextChanged: {
+ backendValues.text.value = text;
+ }
+ }
+ }
+ }
+ QWidget {
+ layout: QHBoxLayout {
+ topMargin: 6;
+ bottomMargin: 2;
+ leftMargin: 10;
+ rightMargin: 10;
+ QLabel {
+ text: "wrap:"
+ font.bold: true;
+ }
+ QCheckBox {
+
+ text: "isWrapping";
+ checkable: true;
+ checked: backendValues.wrap.value;
+ onToggled: {
+ backendValues.wrap.value = checked;
+ }
+ }
+ }
+ }
+
+ FontWidget {
+ text: "Font:";
+ dataFont: backendValues.font.value;
+ onDataFontChanged: {
+ backendValues.font.value = dataFont;
+ }
+ }
+
+ QWidget {
+ layout: QHBoxLayout {
+ topMargin: 4;
+ bottomMargin: 2;
+ leftMargin: 10;
+ rightMargin: 6;
+
+ }
+ }
+
+ QWidget {
+ layout: QHBoxLayout {
+ topMargin: 4;
+ bottomMargin: 2;
+ leftMargin: 10;
+ rightMargin: 6;
+ QLabel {
+ text: "Alignment:"
+ font.bold: true;
+ }
+ QLabel {
+ styleSheet: "QLabel {font: normal }";
+ text: backendValues.horizontalAlignment.value;
+ }
+
+ QComboBox {
+ items : { ["AlignLeft", "AlignRight", "AlignHCenter"] }
+ currentText: backendValues.hAlign.value;
+ onItemsChanged: {
+ currentText = backendValues.horizontalAlignment.value;
+ print(currentText);
+ }
+
+ onCurrentTextChanged: {
+ if (count == 3)
+ print("set");
+ print(currentText);
+ backendValues.horizontalAlignment.value = currentText;
+ print(currentText);
+ print("set");
+ }
+
+ }
+ }
+ }
+ HorizontalLine {
+ }
+ QWidget {
+ layout: QHBoxLayout {
+ topMargin: 2;
+ bottomMargin: 2;
+ leftMargin: 10;
+ rightMargin: 10;
+
+ ColorWidget {
+ text: "Color:";
+ color: backendValues.color.value;
+ onColorChanged: {
+ backendValues.color.value = strColor;
+ }
+ }
+ ColorWidget {
+ text: "Style color:";
+ color: backendValues.styleColor.value;
+ onColorChanged: {
+ backendValues.styleColor.value = strColor;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/Geometry.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/Geometry.qml
new file mode 100644
index 0000000000..d23246c4a3
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/Geometry.qml
@@ -0,0 +1,173 @@
+import Qt 4.6
+
+GroupBox {
+ finished: finishedNotify;
+ id: Geometry;
+ caption: "Geometry";
+
+ maximumHeight: 240;
+
+ layout: QHBoxLayout {
+ topMargin: 14;
+ bottomMargin: 4;
+ leftMargin: 4;
+ rightMargin: 4;
+
+ QWidget {
+
+ layout: QVBoxLayout {
+ topMargin: 0;
+ bottomMargin: 60;
+ leftMargin: 10;
+ rightMargin: 10;
+ spacing: 25;
+
+ QLabel {
+ text: "Position:";
+ font.bold: true;
+ }
+ QLabel {
+ text: "Size:"
+ font.bold: true
+ }
+ }
+ }
+
+ QWidget {
+ layout: QVBoxLayout {
+ topMargin: 0;
+ bottomMargin: 0;
+ QWidget {
+ layout: QHBoxLayout {
+ topMargin: 0;
+ bottomMargin: 0;
+
+ //---
+
+ QWidget { // 1
+ layout: QHBoxLayout { //2
+ topMargin: 0;
+ bottomMargin: 0;
+ QWidget { //3
+ layout: QVBoxLayout { //4
+ topMargin: 0;
+ bottomMargin: 0;
+ DoubleSpinBox {
+ id: XSpinBox;
+ singleStep: 1;
+ objectName: "XSpinBox";
+ enabled: anchorBackend.hasParent;
+ backendValue: backendValues.x == undefined ? 0 : backendValues.x
+ minimum: -2000;
+ maximum: 2000;
+ baseStateFlag: isBaseState;
+ }
+ QLabel { //6
+ text: "X";
+ alignment: "Qt::AlignHCenter"
+ font.bold: true;
+ } // 6
+ } //QHBoxLayout //4
+ } //QWidget //3
+ QWidget { // 7
+ layout: QVBoxLayout { //8
+ topMargin: 0;
+ bottomMargin: 0;
+
+ DoubleSpinBox {
+ id: YSpinBox;
+ singleStep: 1;
+ objectName: "YSpinBox";
+ backendValue: backendValues.y == undefined ? 0 : backendValues.y
+ enabled: anchorBackend.hasParent;
+ minimum: -2000;
+ maximum: 2000;
+ baseStateFlag: isBaseState;
+ }
+ QLabel { //10
+ text: "Y";
+ alignment: "Qt::AlignHCenter";
+ font.bold: true;
+ } //10
+ } //QVBoxLayout //8
+ } // QWidget //3
+
+ } //QHBoxLayout //7
+ } //QWidget //1
+ //---
+ } //QHBoxLayout
+ } //GroupBox
+ QWidget {
+ layout: QHBoxLayout {
+ topMargin: 0;
+ bottomMargin: 10;
+ //---
+ QWidget {
+ layout: QHBoxLayout {
+ topMargin: 0;
+ bottomMargin: 0;
+ QWidget {
+ layout: QVBoxLayout {
+ topMargin: 0;
+ bottomMargin: 0;
+ DoubleSpinBox {
+ id: WidthSpinBox;
+ singleStep: 1;
+ objectName: "WidthSpinBox";
+ backendValue: backendValues.width == undefined ? 0 : backendValues.width
+ minimum: -2000;
+ maximum: 2000;
+ baseStateFlag: isBaseState;
+ }
+ QLabel {
+ text: "Width";
+ alignment: "Qt::AlignHCenter";
+ font.bold: true;
+ }
+ } //QVBoxLayout
+ } //QWidget
+ QWidget {
+ layout: QVBoxLayout {
+ topMargin: 0;
+ bottomMargin: 0;
+ DoubleSpinBox {
+ id: HeightSpinBox;
+ singleStep: 1;
+ objectName: "HeightSpinBox";
+ backendValue: backendValues.height == undefined ? 0 : backendValues.height
+ minimum: -2000;
+ maximum: 2000;
+ baseStateFlag: isBaseState;
+ }
+ QLabel {
+ id: HeightLabel;
+ text: "Height";
+ alignment: "Qt::AlignHCenter";
+ font.bold: true;
+ }
+ } //QVBoxLayout
+ } //QWidget
+ } //QHBoxLayout
+ } //QWidget
+ //---
+
+ } // QHBoxLayout
+ } //Widget
+
+ IntEditor {
+ id: borderWidth;
+ backendValue: backendValues.z == undefined ? 0 : backendValues.z
+ caption: "z:"
+ baseStateFlag: isBaseState;
+ step: 1;
+ minimumValue: 0;
+ maximumValue: 100;
+ }
+ } //QVBoxLayout
+
+ } //QWidget
+
+
+ } //QHBoxLayout
+
+} //QGroupBox
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/GridSpecifics.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/GridSpecifics.qml
new file mode 100644
index 0000000000..f2215d7632
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/GridSpecifics.qml
@@ -0,0 +1,49 @@
+import Qt 4.6
+import Bauhaus 1.0
+
+GroupBox {
+ maximumHeight: 200;
+
+ finished: finishedNotify;
+ caption: "Grid";
+ id: GridSpecifics;
+
+ layout: QVBoxLayout {
+
+ topMargin: 18;
+ bottomMargin: 2;
+ leftMargin: 8;
+ rightMargin: 8;
+
+
+ IntEditor {
+ id: spacing;
+ backendValue: backendValues.spacing;
+ caption: "Spacing: "
+ baseStateFlag: isBaseState;
+ step: 1;
+ minimumValue: 0;
+ maximumValue: 2000;
+ }
+
+ IntEditor {
+ id: rows;
+ backendValue: backendValues.rows;
+ caption: "Rows: "
+ baseStateFlag: isBaseState;
+ step: 1;
+ minimumValue: 0;
+ maximumValue: 2000;
+ }
+
+ IntEditor {
+ id: columns;
+ backendValue: backendValues.columns;
+ caption: "Columns: "
+ baseStateFlag: isBaseState;
+ step: 1;
+ minimumValue: 0;
+ maximumValue: 2000;
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/GroupBox.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/GroupBox.qml
new file mode 100644
index 0000000000..d1106cc1cf
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/GroupBox.qml
@@ -0,0 +1,57 @@
+import Qt 4.6
+import Bauhaus 1.0
+
+QExtGroupBox {
+ id: GroupBox;
+
+ property var finished;
+
+ property var caption;
+
+ property var oldMaximumHeight;
+
+ onFinishedChanged: {
+ CheckBox.raise();
+ maximumHeight = height;
+ oldMaximumHeight = maximumHeight;
+ visible = false;
+ visible = true;
+ x = 6;
+ }
+
+ QToolButton {
+ //QCheckBox {
+ id: CheckBox;
+ text: "";
+ focusPolicy: "Qt::NoFocus";
+ styleSheetFile: "specialCheckBox.css";
+ y: 4;
+ x: 6;
+ height: 12;
+ width: 12;
+ arrowType: "Qt::DownArrow";
+ toolButtonStyle: "Qt::ToolButtonTextBesideIcon";
+ checkable: true;
+ checked: true;
+ font.bold: true;
+ onClicked: {
+ if (checked) {
+ //GroupBox.maximumHeight = oldMaximumHeight;
+ collapsed = false;
+ text = "";
+ width = 12;
+ x = 6;
+ arrowType = "Qt::DownArrow";
+ } else {
+ //GroupBox.maximumHeight = 20;
+
+ collapsed = true;
+ text = GroupBox.caption;
+ visible = true;
+ width = 120;
+ x = 2;
+ arrowType = "Qt::RightArrow";
+ }
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/GroupBoxOption.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/GroupBoxOption.qml
new file mode 100644
index 0000000000..0e62cd036c
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/GroupBoxOption.qml
@@ -0,0 +1,21 @@
+import Qt 4.6
+import Bauhaus 1.0
+
+QExtGroupBox {
+ id: GroupBoxOption;
+
+ property var finished;
+
+ property var caption;
+
+ property var oldMaximumHeight;
+
+ onFinishedChanged: {
+ CheckBox.raise();
+ maximumHeight = height;
+ oldMaximumHeight = maximumHeight;
+ minimumHeight = height;
+ x = 6;
+ visible = false;
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/HorizontalLine.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/HorizontalLine.qml
new file mode 100644
index 0000000000..b1f6418567
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/HorizontalLine.qml
@@ -0,0 +1,8 @@
+import Qt 4.6
+
+ QLineEdit {
+ text: "";
+ readOnly: true;
+ maximumHeight: 2;
+ styleSheet: "QLineEdit {border: 2px solid #3F3F3F;}";
+ } \ No newline at end of file
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/ImageSpecifics.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/ImageSpecifics.qml
new file mode 100644
index 0000000000..28d475853f
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/ImageSpecifics.qml
@@ -0,0 +1,26 @@
+import Qt 4.6
+import Bauhaus 1.0
+
+GroupBox {
+ maximumHeight: 240;
+
+ finished: finishedNotify;
+ caption: "Image";
+
+ layout: QVBoxLayout {
+ topMargin: 12;
+ bottomMargin: 12;
+ leftMargin: 2;
+ rightMargin: 2;
+
+ FileWidget {
+ enabled: isBaseState || backendValues.id.value != "";
+ maximumWidth: 250;
+ text: "Source: ";
+ fileName: backendValues.source.value;
+ onFileNameChanged: {
+ backendValues.source.value = fileName;
+ }
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/IntEditor.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/IntEditor.qml
new file mode 100644
index 0000000000..69a34bb40b
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/IntEditor.qml
@@ -0,0 +1,51 @@
+import Qt 4.6
+import Bauhaus 1.0
+
+QWidget {
+ id: IntEditor;
+
+ property var backendValue;
+ property var baseStateFlag;
+
+ property var caption;
+
+ property var maximumValue: 99
+ property var minimumValue: 0
+ property var step: 1
+
+ layout: QHBoxLayout {
+ topMargin: 2;
+ bottomMargin: 2;
+ leftMargin: 0;
+ rightMargin: 0;
+ QLabel {
+ text: caption
+ font.bold: true;
+ }
+
+ SpinBox {
+ backendValue: IntEditor.backendValue;
+ minimum: minimumValue;
+ maximum: maximumValue;
+ baseStateFlag: IntEditor.baseStateFlag;
+ }
+
+
+ QSlider {
+ property alias backendValue: IntEditor.backendValue
+ orientation: "Qt::Horizontal";
+ minimum: minimumValue
+ maximum: maximumValue
+ singleStep: step
+
+ value: (backendValue == undefined
+ || backendValue == null
+ || backendValue.value == undefined
+ || backendValue.value == null) ? 0 : backendValue.value
+ onValueChanged: {
+ if (backendValue != undefined && backendValue != null)
+ backendValue.value = value;
+ }
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/ItemPane.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/ItemPane.qml
new file mode 100644
index 0000000000..94842b81cb
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/ItemPane.qml
@@ -0,0 +1,104 @@
+import Qt 4.6
+import Bauhaus 1.0
+
+PropertyFrame {
+ layout: QVBoxLayout {
+ topMargin: 0;
+ bottomMargin: 0;
+ leftMargin: 0;
+ rightMargin: 0;
+ spacing: 0;
+
+ Switches {
+ }
+
+ ExtendedSwitches {
+ id: extendedSwitches;
+ }
+
+ ScrollArea {
+ styleSheetFile: ":/qmldesigner/scrollbar.css";
+ widgetResizable: true;
+
+ finished: finishedNotify;
+
+ horizontalScrollBarPolicy: "Qt::ScrollBarAlwaysOff";
+ id: standardPane;
+
+
+ content: ProperyEditorStandard;
+ QFrame {
+ minimumHeight: 1100;
+ id: ProperyEditorStandard
+ layout: QVBoxLayout {
+ topMargin: 2;
+ bottomMargin: 2;
+ leftMargin: 2;
+ rightMargin: 2;
+ Type {
+ }
+ HorizontalLine {
+ }
+
+ Geometry {
+ }
+
+ Modifiers {
+
+ }
+
+ WidgetLoader {
+ id: specificsOne;
+ source: specificsUrl;
+ }
+
+
+ QScrollArea {
+ }
+
+ } // layout
+ } //QWidget
+ } //QScrollArea
+
+
+ ScrollArea {
+ widgetResizable: true;
+ styleSheetFile: ":/qmldesigner/scrollbar.css";
+ finished: finishedNotify;
+ horizontalScrollBarPolicy: "Qt::ScrollBarAlwaysOff";
+ id: specialPane;
+ visible: false;
+ visible: false;
+ content: ProperyEditorSpecial;
+ QFrame {
+ minimumHeight: 600;
+ id: ProperyEditorSpecial
+ layout: QVBoxLayout {
+ topMargin: 2;
+ bottomMargin: 2;
+ leftMargin: 2;
+ rightMargin: 2;
+ Type {
+ }
+
+ WidgetLoader {
+ id: specificsOne2;
+ source: specificsUrl;
+ }
+
+ QScrollArea {
+ }
+ }
+ }
+ }
+
+ ExtendedPane {
+ id: extendedPane;
+ }
+
+ LayoutPane {
+ id: layoutPane;
+ }
+
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/Layout.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/Layout.qml
new file mode 100644
index 0000000000..e1460cbc80
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/Layout.qml
@@ -0,0 +1,22 @@
+import Qt 4.6
+
+GroupBox {
+ finished: finishedNotify;
+ caption: "Layout";
+id: Layout;
+maximumHeight: 340;
+ enabled: anchorBackend.hasParent;
+
+ layout: QVBoxLayout {
+ topMargin: 20;
+ bottomMargin: 10;
+ leftMargin: 40;
+ rightMargin: 20;
+ spacing: 20
+ QLabel {
+ text: "Layout"
+ }
+ AnchorBox {}
+ }
+
+}
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/LayoutPane.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/LayoutPane.qml
new file mode 100644
index 0000000000..d2698c629a
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/LayoutPane.qml
@@ -0,0 +1,29 @@
+import Qt 4.6
+import Bauhaus 1.0
+
+QScrollArea {
+ widgetResizable: true;
+ styleSheetFile: ":/qmldesigner/scrollbar.css";
+ horizontalScrollBarPolicy: "Qt::ScrollBarAlwaysOff";
+ id: LayoutPane;
+ visible: false;
+ content: ProperyEditorLayout;
+ QFrame {
+ enabled: isBaseState;
+ id: ProperyEditorLayout;
+ minimumHeight: 460;
+ layout: QVBoxLayout {
+ topMargin: 2;
+ bottomMargin: 2;
+ leftMargin: 2;
+ rightMargin: 2;
+ Type {
+ }
+ Layout {
+ id: layoutBox;
+ }
+ QScrollArea {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/ListView.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/ListView.qml
new file mode 100644
index 0000000000..b5a4443531
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/ListView.qml
@@ -0,0 +1,85 @@
+import Qt 4.6
+import Bauhaus 1.0
+
+PropertyFrame {
+ layout: QVBoxLayout {
+ topMargin: 0;
+ bottomMargin: 0;
+ leftMargin: 0;
+ rightMargin: 0;
+ spacing: 0;
+
+ Switches {
+ }
+
+ QScrollArea {
+ horizontalScrollBarPolicy: "Qt::ScrollBarAlwaysOff";
+ id: standardPane;
+ content: ProperyEditorStandard;
+ QFrame {
+ minimumHeight: 400;
+ id: ProperyEditorStandard
+ layout: QVBoxLayout {
+ topMargin: 2;
+ bottomMargin: 2;
+ leftMargin: 2;
+ rightMargin: 2;
+ Type {
+ }
+ HorizontalLine {
+ }
+
+ Geometry {
+ }
+
+ Modifiers {
+
+ }
+
+ QScrollArea {
+ }
+
+ } // layout
+ } //QWidget
+ } //QScrollArea
+
+
+ QScrollArea {
+ horizontalScrollBarPolicy: "Qt::ScrollBarAlwaysOff";
+ id: specialPane;
+ visible: false;
+ visible: false;
+ content: ProperyEditorSpecial;
+ QFrame {
+ minimumHeight: 200;
+ id: ProperyEditorSpecial
+ layout: QVBoxLayout {
+ topMargin: 2;
+ bottomMargin: 2;
+ leftMargin: 2;
+ rightMargin: 2;
+ Type {
+ }
+
+ QScrollArea {
+ }
+ }
+ }
+ }
+
+ ExtendedPane {
+ id: extendedPane;
+ }
+
+ LayoutPane {
+ id: layoutPane;
+ }
+
+
+ ResetPane {
+ id: resetPane;
+ }
+
+
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/ListViewSpecifics.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/ListViewSpecifics.qml
new file mode 100644
index 0000000000..28f7c4c870
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/ListViewSpecifics.qml
@@ -0,0 +1,106 @@
+import Qt 4.6
+import Bauhaus 1.0
+
+GroupBox {
+ finished: finishedNotify;
+ caption: "List View";
+
+ layout: QVBoxLayout {
+ topMargin: 15;
+ bottomMargin: 6;
+ leftMargin: 0;
+ rightMargin: 0;
+
+ QWidget {
+ id: contentWidget;
+ maximumHeight: 260;
+
+ layout: QHBoxLayout {
+ topMargin: 0;
+ bottomMargin: 0;
+ leftMargin: 10;
+ rightMargin: 10;
+
+ QWidget {
+ layout: QVBoxLayout {
+ topMargin: 0;
+ bottomMargin: 0;
+ leftMargin: 0;
+ rightMargin: 0;
+ QLabel {
+ minimumHeight: 22;
+ text: "Highlight Follows:"
+ font.bold: true;
+ }
+
+ QLabel {
+ minimumHeight: 22;
+ text: "Key Navigation Wraps:"
+ font.bold: true;
+ }
+
+ QLabel {
+ minimumHeight: 22;
+ text: "Snap Position:"
+ font.bold: true;
+ }
+
+ QLabel {
+ minimumHeight: 22;
+ text: "Spacing:"
+ font.bold: true;
+ }
+ }
+ }
+
+ QWidget {
+ layout: QVBoxLayout {
+ topMargin: 0;
+ bottomMargin: 0;
+ leftMargin: 0;
+ rightMargin: 0;
+
+ CheckBox {
+ id: HighlightFollowsCurrentItemCheckBox;
+ text: "";
+ backendValue: backendValues.highlightFollowsCurrentItem;
+ baseStateFlag: isBaseState;
+ checkable: true;
+ }
+
+ CheckBox {
+ id: WrapCheckBox;
+ text: "";
+ backendValue: backendValues.wrap;
+ baseStateFlag: isBaseState;
+ checkable: true;
+ }
+
+ SpinBox {
+ id: SnapPositionSpinBox;
+ objectName: "SnapPositionSpinBox";
+ backendValue: backendValues.snapPosition;
+ minimumWidth: 30;
+ minimum: 0;
+ maximum: 1000;
+ singleStep: 1;
+ baseStateFlag: isBaseState;
+ }
+
+ SpinBox {
+ id: SpacingSpinBox;
+ objectName: "SpacingSpinBox";
+ backendValue: backendValues.spacing;
+ minimumWidth: 30;
+ minimum: 0;
+ maximum: 1000;
+ singleStep: 1;
+ baseStateFlag: isBaseState;
+ }
+
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/Modifiers.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/Modifiers.qml
new file mode 100644
index 0000000000..6d4a764514
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/Modifiers.qml
@@ -0,0 +1,218 @@
+import Qt 4.6
+
+GroupBox {
+
+
+
+ finished: finishedNotify;
+ caption: "Modifiers"
+ minimumHeight: 30;
+ minimumHeight: 180;
+ id: Mofifiers;
+
+ layout: QVBoxLayout {
+ topMargin: 2;
+ bottomMargin: 6;
+ leftMargin: 0;
+ rightMargin: 0;
+
+ QWidget {
+ id: contentWidget;
+ maximumHeight: 240;
+
+ layout: QHBoxLayout {
+ topMargin: 0;
+ bottomMargin: 0;
+ leftMargin: 10;
+ rightMargin: 10;
+ QWidget {
+ layout: QVBoxLayout {
+ topMargin: 0;
+ bottomMargin: 30;
+ leftMargin: 0;
+ rightMargin: 0;
+
+ QLabel {
+ minimumHeight: 50;
+ text: "Rotation:"
+ font.bold: true;
+ }
+
+ QLabel {
+ text: "Scale:"
+ font.bold: true;
+ }
+
+ QLabel {
+ text: "Scale:"
+ text: ""
+ font.bold: true;
+ }
+
+ QLabel {
+ text: "Opacity:"
+ font.bold: true;
+ }
+ QLabel {
+ text: "Visibility:"
+ font.bold: true;
+ }
+ }
+ }
+ QWidget {
+ layout: QVBoxLayout {
+
+ topMargin: 02;
+ bottomMargin: 2;
+ leftMargin: 5;
+ rightMargin: 0;
+
+ QWidget {
+ layout: QHBoxLayout {
+ topMargin: 3;
+ bottomMargin: 0;
+ leftMargin: 0;
+ rightMargin: 0;
+ SpinBox {
+ id: RotationSpinBox;
+ backendValue: backendValues.rotation;
+ onBackendValueChanged: {
+ if (backendValue.value > 180)
+ RotationDial.value = (backendValue.value - 360);
+ else
+ RotationDial.value = backendValue.value;
+ }
+ minimum: 0;
+ maximum: 360;
+ baseStateFlag: isBaseState;
+ }
+ QDial {
+ id: RotationDial;
+ wrapping: true;
+ focusPolicy: "Qt::ClickFocus";
+ minimumHeight: 20;
+ maximumHeight: 50;
+ minimum: -180;
+ maximum: 180;
+ singleStep: 45;
+ onValueChanged : {
+ if (value < 0)
+ RotationSpinBox.backendValue.value = 360 + value;
+ else
+ RotationSpinBox.backendValue.value = value;
+ }
+ }
+ }
+ }
+
+
+
+ QWidget {
+ layout: QHBoxLayout {
+ topMargin: 10;
+ bottomMargin: 0;
+ leftMargin: 0;
+ rightMargin: 0;
+ DoubleSpinBox {
+ id: ScaleSpinBox;
+ objectName: "ScaleSpinBox";
+ backendValue: backendValues.scale;
+ minimumWidth: 60;
+ minimum: 0.01
+ maximum: 10
+ singleStep: 0.1
+ baseStateFlag: isBaseState;
+ onBackendValueChanged: {
+ ScaleSlider.value = backendValue.value * 10;
+ }
+ }
+ QSlider {
+ id: ScaleSlider;
+ orientation: "Qt::Horizontal";
+ minimum: 1;
+ maximum: 100;
+ singleStep: 1;
+ onValueChanged: {
+ backendValues.scale.value = value / 10;
+ }
+ }
+ }
+ }
+
+ QWidget {
+ layout: QHBoxLayout {
+ topMargin: 5;
+ bottomMargin: 5;
+ leftMargin: 10;
+ rightMargin: 0;
+
+ QLabel {
+ text: "Origin: ";
+ }
+ QComboBox {
+ items : { [
+ "TopLeft", "Top", "TopRight", "Left", "Center", "Right", "BottomLeft", "Bottom",
+ "BottomRight"
+ ] }
+
+ currentText: backendValues.transformOrigin.value;
+ onItemsChanged: {
+ currentText = backendValues.transformOrigin.value;
+ }
+ onCurrentTextChanged: {
+ backendValues.transformOrigin.value = currentText;
+ }
+ }
+
+ }
+ }
+
+ QWidget {
+ layout: QHBoxLayout {
+ topMargin: 5;
+ bottomMargin: 10;
+ leftMargin: 0;
+ rightMargin: 0;
+
+ DoubleSpinBox {
+ id: OpacitySpinBox;
+ backendValue: backendValues.opacity === undefined ? null : backendValues.opacity
+ minimumWidth: 60;
+ minimum: 0;
+ maximum: 1;
+ singleStep: 0.1
+ baseStateFlag: isBaseState;
+ }
+ QSlider {
+ orientation: "Qt::Horizontal";
+ minimum: 0
+ maximum: 100
+ singleStep: 5;
+ value: backendValues.opacity === undefined ? 0 : (backendValues.opacity.value * 100)
+ onValueChanged: {
+ if (backendValues.opacity !== undefined)
+ backendValues.opacity.value = value / 100;
+ }
+ }
+ }
+ }
+ CheckBox {
+ id: VisibleCheckBox;
+ text: "item visibilty";
+ backendValue: backendValues.visible === undefined ? false : backendValues.visible;
+ baseStateFlag: isBaseState;
+ checkable: true;
+ }
+ CheckBox {
+ id: ClipCheckBox;
+ text: "clipping item";
+ backendValue: backendValues.clip === undefined ? false : backendValues.clip;
+ baseStateFlag: isBaseState;
+ checkable: true;
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/PropertyFrame.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/PropertyFrame.qml
new file mode 100644
index 0000000000..84e9082fe4
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/PropertyFrame.qml
@@ -0,0 +1,10 @@
+import Qt 4.6
+
+WidgetFrame {
+ id: PropertyFrame;
+
+ minimumWidth: 300;
+ //maximumWidth: 300;
+ styleSheetFile: "propertyEditor.css";
+ //visible: isBaseState;
+}
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/RectangleSpecifics.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/RectangleSpecifics.qml
new file mode 100644
index 0000000000..a33264ef48
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/RectangleSpecifics.qml
@@ -0,0 +1,134 @@
+import Qt 4.6
+import Bauhaus 1.0
+
+GroupBox {
+
+ finished: finishedNotify;
+ caption: "Rect"
+
+ minimumHeight: 340;
+ maximumHeight: 340;
+
+ layout: QVBoxLayout {
+ topMargin: 12;
+ bottomMargin: 20;
+ leftMargin: 20;
+ rightMargin: 20;
+
+ QWidget {
+ layout: QVBoxLayout {
+ topMargin: 2;
+ bottomMargin: 20;
+ leftMargin: 0;
+ rightMargin: 0;
+
+ QWidget {
+ layout: QHBoxLayout {
+ topMargin: 8;
+ bottomMargin: 20;
+ leftMargin: 10;
+ rightMargin: 10;
+ QLabel {
+ text: "Radius:"
+ font.bold: true;
+ }
+ SpinBox {
+ id: RadiusSpinBox;
+ backendValue: backendValues.radius === undefined ? null : backendValues.radius
+ minimum: 0;
+ maximum: 100;
+ baseStateFlag: isBaseState;
+ }
+ QSlider {
+ orientation: "Qt::Horizontal";
+ minimum: 0;
+ maximum: 100;
+ singleStep: 1;
+ value: backendValues.radius === undefined ? null : backendValues.radius.value
+ onValueChanged: {
+ backendValues.radius.value = value;
+ }
+ }
+ }
+ }
+ QWidget {
+ layout: QHBoxLayout {
+ topMargin: 2;
+ bottomMargin: 2;
+ leftMargin: 10;
+ rightMargin: 10;
+ spacing: 20;
+
+ ColorWidget {
+ text: "Color:";
+ color: backendValues.color === undefined ? null : backendValues.color.value;
+ onColorChanged: {
+ backendValues.color.value = strColor;
+ }
+ //modelNode: backendValues.color.modelNode;
+ complexGradientNode: backendValues.color === undefined ? null : backendValues.color.complexNode
+
+ showGradientButton: true;
+ }
+ ColorWidget {
+ text: "Tint color:";
+ color: backendValues.tintColor === undefined ? "black" : backendValues.tintColor.value
+ onColorChanged: {
+ backendValues.color.value = strColor;
+ }
+ }
+ }
+ }
+ HorizontalLine {
+ }
+ }
+ }
+ QWidget {
+ minimumHeight: 80;
+ maximumHeight: 120;
+
+ layout: QHBoxLayout {
+ topMargin: 2;
+ topMargin: 0;
+ bottomMargin: 0;
+ leftMargin: 0;
+ rightMargin: 0;
+
+ QWidget {
+ id: PenGroupBox;
+
+ maximumHeight: 80;
+
+ layout: QVBoxLayout {
+ topMargin: 10;
+ bottomMargin: 10;
+ leftMargin: 20;
+ rightMargin: 20;
+ IntEditor {
+
+ id: borderWidth;
+ backendValue: backendValues.border_width === undefined ? 0 : backendValues.border_width
+
+ caption: "Pen Width:"
+ baseStateFlag: isBaseState;
+
+ step: 1;
+ minimumValue: 0;
+ maximumValue: 100;
+ }
+ ColorWidget {
+ id: PenColor;
+ text: "Pen Color:";
+ minimumHeight: 20;
+ minimumWidth: 20;
+ color: backendValues.border_color.value;
+ onColorChanged: {
+ backendValues.border_color.value = strColor;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/ResetPane.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/ResetPane.qml
new file mode 100644
index 0000000000..aa164ddda4
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/ResetPane.qml
@@ -0,0 +1,41 @@
+import Qt 4.6
+import Bauhaus 1.0
+
+QScrollArea {
+ horizontalScrollBarPolicy: "Qt::ScrollBarAlwaysOff";
+ id: ResetPane;
+ visible: false;
+ content: ProperyEditorReset;
+ QFrame {
+ //minimumHeight: 1800;
+ id: ProperyEditorReset
+ layout: QVBoxLayout {
+ topMargin: 2;
+ bottomMargin: 2;
+ leftMargin: 2;
+ rightMargin: 2;
+
+ Type {
+ }
+ ResetWidget {
+ id: resetWidget;
+ //minimumHeight: 2000;
+
+
+ height: 500;
+ width: 200;
+ backendObject: backendValues;
+
+ QLineEdit {
+ visible: false;
+ text: backendValues.id;
+ onTextChanged: {
+ resetWidget.resetView();
+ }
+ }
+ }
+
+
+ }
+ }
+} \ No newline at end of file
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/RowSpecifics.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/RowSpecifics.qml
new file mode 100644
index 0000000000..f95f56a101
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/RowSpecifics.qml
@@ -0,0 +1,29 @@
+import Qt 4.6
+import Bauhaus 1.0
+
+GroupBox {
+ maximumHeight: 200;
+
+ finished: finishedNotify;
+ caption: "Grid";
+ id: GridSpecifics;
+
+ layout: QVBoxLayout {
+
+ topMargin: 18;
+ bottomMargin: 2;
+ leftMargin: 8;
+ rightMargin: 8;
+
+
+ IntEditor {
+ id: spacing;
+ backendValue: backendValues.spacing;
+ caption: "Spacing: "
+ baseStateFlag: isBaseState;
+ step: 1;
+ minimumValue: 0;
+ maximumValue: 2000;
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/ScrollArea.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/ScrollArea.qml
new file mode 100644
index 0000000000..19acd3361a
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/ScrollArea.qml
@@ -0,0 +1,14 @@
+import Qt 4.6
+import Bauhaus 1.0
+
+
+QScrollArea {
+
+ property var finished;
+
+ onFinishedChanged: {
+ setupProperWheelBehaviour();
+ }
+
+
+} \ No newline at end of file
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/SpinBox.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/SpinBox.qml
new file mode 100644
index 0000000000..868236afc1
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/SpinBox.qml
@@ -0,0 +1,72 @@
+import Qt 4.6
+import Bauhaus 1.0
+
+QWidget { //This is a special SpinBox that does color coding for states
+ id: SpinBox;
+
+ property var backendValue;
+ property var baseStateFlag;
+ property alias singleStep: box.singleStep;
+ property alias minimum: box.minimum
+ property alias maximum: box.maximum
+
+ minimumHeight: 22;
+
+ onBaseStateFlagChanged: {
+ evaluate();
+ }
+
+ onBackendValueChanged: {
+ evaluate();
+ }
+
+ Script {
+ function evaluate() {
+ if (baseStateFlag) {
+ if (backendValue != null && backendValue.isInModel)
+ SpinBox.setStyleSheet("color: white;");
+ else
+ SpinBox.setStyleSheet("color: gray;");
+ } else {
+ if (backendValue != null && backendValue.isInSubState)
+ SpinBox.setStyleSheet("color: blue;");
+ else
+ SpinBox.setStyleSheet("color: gray;");
+ }
+ }
+ }
+
+ layout: QHBoxLayout {
+ topMargin: 0;
+ bottomMargin: 0;
+ leftMargin: 0;
+ rightMargin: 10;
+ spacing: 0;
+
+ QSpinBox {
+ property alias backendValue: SpinBox.backendValue
+
+ keyboardTracking: false;
+ id: box;
+ enabled: backendValue === undefined || backendValue.isBound === undefined || backendValue.isBound === null ? false : !backendValue.isBound
+ value: backendValue == undefined || backendValue.value == undefined || backendValue.value === null ? 0 : backendValue.value;
+ onValueChanged: {
+ if (backendValue != undefined && backendValue != null)
+ backendValue.value = value;
+ }
+ onFocusChanged: {
+ //extendedSwitches.active = focus;
+ //extendedSwitches.backendValue = backendValue;
+ }
+ }
+ }
+
+ QToolButton {
+ visible: false;
+ width: 10;
+ height: 10;
+ y: box.y + box.height - 11;
+ x: box.width - 1;
+ focusPolicy: "Qt::NoFocus";
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/Switches.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/Switches.qml
new file mode 100644
index 0000000000..84db9bbc25
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/Switches.qml
@@ -0,0 +1,85 @@
+import Qt 4.6
+
+QFrame {
+ styleSheetFile: "switch.css";
+ property var specialModeIcon;
+ specialModeIcon: "images/standard.png";
+ maximumWidth: 286;
+ minimumWidth: 286;
+ layout: QHBoxLayout {
+ topMargin: 4;
+ bottomMargin: 0;
+ leftMargin: 4;
+ rightMargin: 80;
+ spacing: 0;
+
+ QPushButton {
+ checkable: true;
+ checked: true;
+ id: standardMode;
+ toolTip: "general item properties";
+ iconFromFile: "images/rect-icon.png";
+ onClicked: {
+ extendedMode.checked = false;
+ layoutMode.checked = false;
+ specialMode.checked = false;
+ checked = true;
+ standardPane.visible = true;
+ extendedPane.visible = false;
+ layoutPane.visible = false;
+ specialPane.visible = false;
+ }
+ }
+ QPushButton {
+ checkable: true;
+ checked: false;
+ id: specialMode;
+ toolTip: "type specific properties";
+ iconFromFile: specialModeIcon;
+ onClicked: {
+ extendedMode.checked = false;
+ standardMode.checked = false;
+ layoutMode.checked = false;
+ checked = true;
+ specialPane.visible = true;
+ standardPane.visible = false;
+ extendedPane.visible = false;
+ layoutPane.visible = false;
+ }
+ }
+ QPushButton {
+ id: extendedMode;
+ toolTip: "extended properties";
+ checkable: true;
+ checked: false;
+ iconFromFile: "images/extended.png";
+ onClicked: {
+ standardMode.checked = false;
+ layoutMode.checked = false;
+ specialMode.checked = false;
+ checked = true;
+ standardPane.visible = false;
+ extendedPane.visible = true;
+ layoutPane.visible = false;
+ specialPane.visible = false;
+ }
+ }
+ QPushButton {
+ id: layoutMode;
+ checkable: true;
+ checked: false;
+ toolTip: "layout properties";
+ iconFromFile: "images/layout.png";
+ onClicked: {
+ extendedMode.checked = false;
+ standardMode.checked = false;
+ specialMode.checked = false;
+ checked = true;
+ standardPane.visible = false;
+ extendedPane.visible = false;
+ layoutPane.visible = true;
+ specialPane.visible = false;
+ }
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/TextEditSpecifics.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/TextEditSpecifics.qml
new file mode 100644
index 0000000000..34fd8168b6
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/TextEditSpecifics.qml
@@ -0,0 +1,273 @@
+import Qt 4.6
+import Bauhaus 1.0
+
+GroupBox {
+ maximumHeight: 600;
+
+ finished: finishedNotify;
+ caption: "Text Edit";
+
+ layout: QVBoxLayout {
+ id: textSpecifics;
+ topMargin: 20;
+ bottomMargin: 2;
+ leftMargin: 4;
+ rightMargin: 4;
+ QWidget {
+ layout: QHBoxLayout {
+ topMargin: 8;
+ bottomMargin: 2;
+ leftMargin: 10;
+ rightMargin: 0;
+ spacing: 20;
+ QLabel {
+ alignment: "AlignTop";
+ text: "Text:"
+ font.bold: true;
+ }
+ QTextEdit {
+ minimumHeight: 80;
+ property var localText: backendValues.text.value;
+ onLocalTextChanged: {
+ if (localText != plainText)
+ plainText = localText;
+ }
+
+ onTextChanged: {
+ backendValues.text.value = plainText;
+ }
+
+ }
+ }
+ }
+ QWidget {
+ layout: QHBoxLayout {
+ topMargin: 2;
+ bottomMargin: 2;
+ leftMargin: 10;
+ rightMargin: 10;
+ QLabel {
+ text: "wrap:"
+ font.bold: true;
+ }
+ CheckBox {
+ text: "isWrapping";
+ baseStateFlag: isBaseState;
+ checkable: true;
+ backendValue: backendValues.wrap;
+ }
+ }
+ }
+
+ FontWidget {
+ text: "Font:";
+
+ bold: backendValues.font_bold.value;
+ italic: backendValues.font_italic.value;
+ family: backendValues.font_family.value;
+ fontSize: backendValues.font_pointSize.value;
+
+ onDataFontChanged: {
+ if (bold)
+ backendValues.font_bold.value = bold;
+ else
+ backendValues.font_bold.resetValue();
+
+ if (italic)
+ backendValues.font_italic.value = bold;
+ else
+ backendValues.font_italic.resetValue();
+
+ backendValues.font_family.value = family;
+ backendValues.font_pointSize.value = fontSize;
+ }
+ }
+
+ HorizontalLine {
+ }
+
+ QWidget {
+ layout: QHBoxLayout {
+ topMargin: 4;
+ bottomMargin: 2;
+ leftMargin: 10;
+ rightMargin: 6;
+
+ }
+ }
+
+
+ QWidget {
+ layout: QHBoxLayout {
+ topMargin: 4;
+ bottomMargin: 8;
+ leftMargin: 6;
+ rightMargin: 6;
+ QLabel {
+ text: "Text Format:"
+ font.bold: true;
+ }
+
+ QComboBox {
+ minimumHeight: 22;
+ items : { ["PlainText", "RichText", "AutoText"] }
+ currentText: backendValues.textFormat.value;
+ onItemsChanged: {
+ currentText = backendValues.textFormat.value;
+ }
+
+ onCurrentTextChanged: {
+ if (count == 3)
+ backendValues.textFormat.value = currentText;
+ }
+ }
+ }
+ }
+
+
+ HorizontalLine {
+ }
+
+
+ QWidget {
+ layout: QHBoxLayout {
+ topMargin: 4;
+ bottomMargin: 2;
+ leftMargin: 6;
+ rightMargin: 6;
+ QLabel {
+ text: "Horizontal Alignment:"
+ font.bold: true;
+ }
+
+ QComboBox {
+ items : { ["AlignLeft", "AlignRight", "AlignHCenter"] }
+ currentText: backendValues.horizontalAlignment.value;
+ onItemsChanged: {
+ currentText = backendValues.horizontalAlignment.value;
+ }
+
+ onCurrentTextChanged: {
+ if (count == 3)
+ backendValues.horizontalAlignment.value = currentText;
+ }
+ }
+ }
+ }
+
+ QWidget {
+ layout: QHBoxLayout {
+ topMargin: 4;
+ bottomMargin: 2;
+ leftMargin: 6;
+ rightMargin: 6;
+ QLabel {
+ text: "Vertical Alignment:"
+ font.bold: true;
+ }
+
+ QComboBox {
+ items : { ["AlignTop", "AlignBottom", "AlignVCenter"] }
+ currentText: backendValues.verticalAlignment.value;
+ onItemsChanged: {
+ currentText = backendValues.verticalAlignment.value;
+ }
+
+ onCurrentTextChanged: {
+ if (count == 3)
+ backendValues.verticalAlignment.value = currentText;
+ }
+ }
+ }
+ }
+
+ HorizontalLine {
+ }
+
+ ColorWidget {
+ minimumHeight: 20;
+ maximumHeight: 20;
+ text: "Color:";
+ color: backendValues.color.value;
+ onColorChanged: {
+ backendValues.color.value = strColor;
+ }
+ }
+
+ ColorWidget {
+ minimumHeight: 20;
+ maximumHeight: 20;
+ text: "Selection Color:";
+ color: backendValues.selectionColor.value;
+ onColorChanged: {
+ backendValues.selectionColor.value = strColor;
+ }
+ }
+
+ ColorWidget {
+ minimumHeight: 20;
+ maximumHeight: 20;
+ text: "Selected Text Color:";
+ color: backendValues.selectedTextColor.value;
+ onColorChanged: {
+ backendValues.selectedTextColor.value = strColor;
+ }
+ }
+
+ HorizontalLine {
+ }
+
+
+ QWidget {
+ layout: QHBoxLayout {
+ topMargin: 2;
+ bottomMargin: 2;
+ leftMargin: 10;
+ rightMargin: 10;
+
+ CheckBox {
+
+ text: "Read Only";
+ baseStateFlag: isBaseState;
+ checkable: true;
+ backendValue: backendValues.readOnly;
+ }
+
+ CheckBox {
+ text: "Cursor Visible";
+ baseStateFlag: isBaseState;
+ checkable: true;
+ backendValue: backendValues.cursorVisible;
+ }
+ }
+ }
+
+ HorizontalLine {
+ }
+
+ QWidget {
+ layout: QHBoxLayout {
+ topMargin: 2;
+ bottomMargin: 2;
+ leftMargin: 10;
+ rightMargin: 10;
+
+ CheckBox {
+ text: "Focus On Press";
+ baseStateFlag: isBaseState;
+ checkable: true;
+ backendValue: backendValues. focusOnPress.value;
+ }
+
+ CheckBox {
+ text: "Persistent Selection";
+ baseStateFlag: isBaseState;
+ checkable: true;
+ backendValue: backendValues.persistentSelection.value;
+ }
+
+ }
+ }
+
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/TextInputSpecifics.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/TextInputSpecifics.qml
new file mode 100644
index 0000000000..82a1cd21fc
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/TextInputSpecifics.qml
@@ -0,0 +1,176 @@
+import Qt 4.6
+import Bauhaus 1.0
+
+GroupBox {
+ maximumHeight: 420;
+ minimumHeight: 420;
+
+ finished: finishedNotify;
+ caption: "Text Input";
+
+ layout: QVBoxLayout {
+ id: textSpecifics;
+ topMargin: 12;
+ bottomMargin: 2;
+ leftMargin: 10;
+ rightMargin: 10;
+ QWidget {
+ layout: QHBoxLayout {
+ topMargin: 8;
+ bottomMargin: 2;
+ leftMargin: 10;
+ rightMargin: 10;
+ QLabel {
+ text: "Text:"
+ font.bold: true;
+ }
+ QLineEdit {
+ minimumHeight: 24;
+ text: backendValues.text.value;
+ onTextChanged: {
+ backendValues.text.value = text;
+ }
+ }
+ }
+ }
+
+ FontWidget {
+ text: "Font:";
+
+ bold: backendValues.font_bold.value;
+ italic: backendValues.font_italic.value;
+ family: backendValues.font_family.value;
+ fontSize: backendValues.font_pointSize.value;
+
+ onDataFontChanged: {
+
+ if (bold)
+ backendValues.font_bold.value = bold;
+ else
+ backendValues.font_bold.resetValue();
+
+ if (italic)
+ backendValues.font_italic.value = bold;
+ else
+ backendValues.font_italic.resetValue();
+
+ backendValues.font_family.value = family;
+ backendValues.font_pointSize.value = fontSize;
+ }
+ }
+
+ HorizontalLine {
+ }
+
+
+ QWidget {
+ layout: QHBoxLayout {
+ topMargin: 4;
+ bottomMargin: 2;
+ leftMargin: 6;
+ rightMargin: 6;
+ QLabel {
+ text: "Horizontal Alignment:"
+ font.bold: true;
+ }
+
+ QComboBox {
+ items : { ["AlignLeft", "AlignRight", "AlignHCenter"] }
+ currentText: backendValues.horizontalAlignment.value;
+ onItemsChanged: {
+ currentText = backendValues.horizontalAlignment.value;
+ }
+
+ onCurrentTextChanged: {
+ if (count == 3)
+ backendValues.horizontalAlignment.value = currentText;
+ }
+
+ }
+ }
+ }
+
+ HorizontalLine {
+ }
+
+ ColorWidget {
+ minimumHeight: 20;
+ maximumHeight: 20;
+ text: "Color:";
+ color: backendValues.color.value;
+ onColorChanged: {
+ backendValues.color.value = strColor;
+ }
+ }
+
+ ColorWidget {
+ minimumHeight: 20;
+ maximumHeight: 20;
+ text: "Selection Color:";
+ color: backendValues.selectionColor.value;
+ onColorChanged: {
+ backendValues.selectionColor.value = strColor;
+ }
+ }
+
+ ColorWidget {
+ minimumHeight: 20;
+ maximumHeight: 20;
+ text: "Selected Text Color:";
+ color: backendValues.selectedTextColor.value;
+ onColorChanged: {
+ backendValues.selectedTextColor.value = strColor;
+ }
+ }
+
+ HorizontalLine {
+ }
+
+
+ QWidget {
+ layout: QHBoxLayout {
+ topMargin: 2;
+ bottomMargin: 2;
+ leftMargin: 10;
+ rightMargin: 10;
+
+ CheckBox {
+
+ text: "Read Only";
+ baseStateFlag: isBaseState;
+ checkable: true;
+ backendValue: backendValues.readOnly;
+ }
+
+ CheckBox {
+
+ text: "Cursor Visible";
+ baseStateFlag: isBaseState;
+ checkable: true;
+ backendValue: backendValues.cursorVisible;
+
+ }
+ }
+ }
+
+ HorizontalLine {
+ }
+
+ QWidget {
+ layout: QHBoxLayout {
+ topMargin: 2;
+ bottomMargin: 2;
+ leftMargin: 10;
+ rightMargin: 10;
+
+ CheckBox {
+ text: "Focus On Press";
+ baseStateFlag: isBaseState;
+ checkable: true;
+ backendValue: backendValues. focusOnPress;
+ }
+
+ }
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/TextSpecifics.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/TextSpecifics.qml
new file mode 100644
index 0000000000..0b0c0cd2ed
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/TextSpecifics.qml
@@ -0,0 +1,172 @@
+import Qt 4.6
+import Bauhaus 1.0
+
+GroupBox {
+ maximumHeight: 280;
+
+ finished: finishedNotify;
+ caption: "Text";
+
+ layout: QVBoxLayout {
+ id: textSpecifics;
+ topMargin: 12;
+ bottomMargin: 2;
+ leftMargin: 4;
+ rightMargin: 4;
+ QWidget {
+ layout: QHBoxLayout {
+ topMargin: 8;
+ bottomMargin: 2;
+ leftMargin: 10;
+ rightMargin: 10;
+ QLabel {
+ text: "Text:"
+ font.bold: true;
+ }
+ QLineEdit {
+ minimumHeight: 24;
+ text: backendValues.text.value;
+ onTextChanged: {
+ backendValues.text.value = text;
+ }
+ }
+ }
+ }
+ QWidget {
+ layout: QHBoxLayout {
+ topMargin: 6;
+ bottomMargin: 2;
+ leftMargin: 10;
+ rightMargin: 10;
+ QLabel {
+ text: "wrap:"
+ font.bold: true;
+ }
+ CheckBox {
+ baseStateFlag: isBaseState;
+ text: "isWrapping";
+ checkable: true;
+ backendValue: backendValues.wrap;
+ }
+ }
+ }
+
+ FontWidget {
+ text: "Font:";
+
+ bold: backendValues.font_bold.value;
+ italic: backendValues.font_italic.value;
+ family: backendValues.font_family.value;
+ fontSize: backendValues.font_pointSize.value;
+
+ onDataFontChanged: {
+
+ if (bold)
+ backendValues.font_bold.value = bold;
+ else
+ backendValues.font_bold.resetValue();
+
+ if (italic)
+ backendValues.font_italic.value = bold;
+ else
+ backendValues.font_italic.resetValue();
+
+ backendValues.font_family.value = family;
+ backendValues.font_pointSize.value = fontSize;
+ }
+ }
+
+ HorizontalLine {
+ }
+
+ QWidget {
+ layout: QHBoxLayout {
+ topMargin: 4;
+ bottomMargin: 2;
+ leftMargin: 10;
+ rightMargin: 6;
+
+ }
+ }
+
+ QWidget {
+ layout: QHBoxLayout {
+ topMargin: 4;
+ bottomMargin: 2;
+ leftMargin: 10;
+ rightMargin: 6;
+ QLabel {
+ text: "Horizontal Alignment:"
+ font.bold: true;
+ }
+
+ QComboBox {
+ items : { ["AlignLeft", "AlignRight", "AlignHCenter"] }
+ currentText: backendValues.horizontalAlignment.value;
+ onItemsChanged: {
+ currentText = backendValues.horizontalAlignment.value;
+ }
+
+ onCurrentTextChanged: {
+ if (count == 3);
+ backendValues.horizontalAlignment.value = currentText;
+ }
+
+ }
+ }
+ }
+
+ QWidget {
+ layout: QHBoxLayout {
+ topMargin: 4;
+ bottomMargin: 2;
+ leftMargin: 10;
+ rightMargin: 6;
+ QLabel {
+ text: "Vertical Alignment:"
+ font.bold: true;
+ }
+
+ QComboBox {
+ items : { ["AlignTop", "AlignBottom", "AlignVCenter"] }
+ currentText: backendValues.verticalAlignment.value;
+ onItemsChanged: {
+ currentText = backendValues.verticalAlignment.value;
+ }
+
+ onCurrentTextChanged: {
+ if (count == 3)
+ backendValues.verticalAlignment.value = currentText;
+ }
+
+ }
+ }
+ }
+
+ HorizontalLine {
+ }
+ QWidget {
+ layout: QHBoxLayout {
+ topMargin: 2;
+ bottomMargin: 2;
+ leftMargin: 10;
+ rightMargin: 10;
+
+ ColorWidget {
+ text: "Color:";
+ color: backendValues.color.value;
+ onColorChanged: {
+ backendValues.color.value = strColor;
+ }
+ }
+ ColorWidget {
+ text: "Style color:";
+ color: backendValues.styleColor.value;
+ onColorChanged: {
+ backendValues.styleColor.value = strColor;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/Type.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/Type.qml
new file mode 100644
index 0000000000..aa9b72291d
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/Type.qml
@@ -0,0 +1,94 @@
+import Qt 4.6
+
+GroupBox {
+ id: Type;
+ finished: finishedNotify;
+ caption: "Type";
+
+ maximumHeight: 100;
+ minimumWidth: 280;
+ layout: QHBoxLayout {
+
+ topMargin: 2;
+ bottomMargin: 0;
+ leftMargin: 10;
+ rightMargin: 10;
+
+
+
+ QWidget {
+ layout: QVBoxLayout {
+ topMargin: 6;
+ bottomMargin: 0;
+ leftMargin: 10;
+ bottomMargin: 10;
+
+ QLabel {
+ text: "Type:";
+ windowTextColor: isBaseState ? "#000000" : "#FF0000";
+ }
+
+ QLabel {
+ font.bold: true;
+ text: "Id:";
+ }
+
+ QLabel {
+ text: "state:";
+ font.bold: true;
+ }
+
+ } //QVBoxLayout
+ } //QWidget
+ QWidget {
+
+ layout: QVBoxLayout {
+ topMargin: 6;
+ bottomMargin: 0;
+ leftMargin: 10;
+ bottomMargin: 10;
+
+ QLineEdit {
+ styleSheetFile: "typeLabel.css"
+ text: backendValues.className === undefined ? "" : backendValues.className.value;
+ readOnly :true;
+ }
+
+ QLineEdit {
+ id: IdLineEdit;
+ objectName: "IdLineEdit";
+ readOnly: isBaseState != true;
+ text: backendValues.id === undefined ? "" : backendValues.id.value;
+ onEditingFinished: {
+ backendValues.id.value = text;
+ }
+ } //LineEdit
+
+ QLineEdit {
+ visible: isBaseState != true;
+ textColor: "#ff0000";
+ readOnly :true;
+ text: stateName;
+ styleSheetFile: "typeLabel.css"
+ onTextChanged: {
+ if (!visible) {
+ IdLineEdit.textColor = "#000000";
+ } else {
+ IdLineEdit.textColor = "#777777";
+ }
+ }
+ } //LineEdit
+
+ QLineEdit {
+ visible: isBaseState;
+ readOnly :true;
+ text: "";
+ styleSheetFile: "typeLabel.css"
+ } //LineEdit
+
+ } //QVBoxLayout
+ } //QWidget
+
+
+ } //QHBoxLayout
+}
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/WebViewSpecifics.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/WebViewSpecifics.qml
new file mode 100644
index 0000000000..925c2bd4f3
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/WebViewSpecifics.qml
@@ -0,0 +1,96 @@
+import Qt 4.6
+import Bauhaus 1.0
+
+GroupBox {
+ maximumHeight: 200;
+
+ finished: finishedNotify;
+ caption: "WebView";
+ id: webViewSpecifics;
+
+ layout: QVBoxLayout {
+
+ topMargin: 18;
+ bottomMargin: 2;
+ leftMargin: 8;
+ rightMargin: 8;
+ QWidget {
+ layout: QHBoxLayout {
+ leftMargin: 0;
+ rightMargin: 0;
+ QLabel {
+ minimumHeight: 20;
+ text: "Url:"
+ font.bold: true;
+ }
+ QLineEdit {
+ text: backendValues.url.value;
+ onEditingFinished: {
+ backendValues.url.value = text;
+ }
+ }
+ }
+ }
+
+
+
+ IntEditor {
+ id: preferredWidth;
+ backendValue: backendValues.preferredWidth;
+ caption: "Prefered Width: "
+ baseStateFlag: isBaseState;
+ step: 1;
+ minimumValue: 0;
+ maximumValue: 2000;
+ }
+
+ IntEditor {
+ id: webPageWidth;
+ backendValue: backendValues.preferredHeight;
+ caption: "Web Page Height:"
+ baseStateFlag: isBaseState;
+ step: 1;
+ minimumValue: 0;
+ maximumValue: 2000;
+ }
+
+ QWidget {
+ layout: QHBoxLayout {
+ topMargin: 10;
+ bottomMargin: 0;
+ leftMargin: 0;
+ rightMargin: 0;
+ spacing: 20;
+
+ QLabel {
+ minimumHeight: 20;
+ text: "ZommFactor:"
+ font.bold: true;
+ }
+ DoubleSpinBox {
+ id: ZoomSpinBox;
+ objectName: "ZommSpinBox";
+ backendValue: backendValues.zoomFactor;
+ minimumWidth: 60;
+ minimum: 0.01
+ maximum: 10
+ singleStep: 0.1
+ baseStateFlag: isBaseState;
+ onBackendValueChanged: {
+ ZoomSlider.value = backendValue.value * 10;
+ }
+ }
+ QSlider {
+ id: ZoomSlider;
+ orientation: "Qt::Horizontal";
+ minimum: 1;
+ maximum: 100;
+ singleStep: 1;
+ onValueChanged: {
+ backendValues.zoomFactor.value = value / 10;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/anchorbox.css b/share/qtcreator/qmldesigner/propertyeditor/Qt/anchorbox.css
new file mode 100644
index 0000000000..d93895b1c8
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/anchorbox.css
@@ -0,0 +1,32 @@
+QPushButton::checked
+{
+ border: 3px solid #2222aa;
+ border-radius: 4px;
+ border-image: none;
+ background-color: #909090;
+}
+
+QPushButton:pressed
+{
+ border: 2px solid #000000;
+}
+
+QPushButton:flat {
+ border: 1px solid #000000;
+}
+
+QPushButton:default {
+ border-color: 1px solid black;
+}
+
+QPushButton {
+ border: 2px solid #333333;
+ color: white;
+}
+
+QFrame{
+ border: 2px solid black;
+ border-radius: 4px;
+ padding: 2px;
+ background: #aaabae;
+ } \ No newline at end of file
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/emptyPane.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/emptyPane.qml
new file mode 100644
index 0000000000..cb4d9bccb8
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/emptyPane.qml
@@ -0,0 +1,45 @@
+import Qt 4.6
+import Bauhaus 1.0
+
+PropertyFrame {
+ layout: QVBoxLayout {
+ topMargin: 0;
+ bottomMargin: 0;
+ leftMargin: 0;
+ rightMargin: 0;
+ spacing: 0;
+
+ Switches {
+ }
+
+ ScrollArea {
+ styleSheetFile: ":/qmldesigner/scrollbar.css";
+ widgetResizable: true;
+ content: QFrame {
+ maximumHeight: 38;
+ layout: QVBoxLayout {
+ topMargin: 6;
+ bottomMargin: 2;
+ leftMargin: 2;
+ rightMargin: 2;
+ QExtGroupBox {
+ font.bold: true;
+ maximumHeight: 100;
+ minimumWidth: 280;
+ minimumHeight: 32;
+ layout: QHBoxLayout {
+ topMargin: 6;
+ bottomMargin: 2;
+ QLabel {
+ minimumHeight: 20;
+ text: "No Item Selected";
+ alignment: "AlignHCenter";
+ }
+ }
+ }
+ }
+ }
+ }
+
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/images/behaivour.png b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/behaivour.png
new file mode 100644
index 0000000000..15113bd4d1
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/behaivour.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/images/blended-image-icon.png b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/blended-image-icon.png
new file mode 100644
index 0000000000..7c0911d63d
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/blended-image-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/images/button.png b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/button.png
new file mode 100644
index 0000000000..cc16dbbec3
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/button.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/images/default-icon.png b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/default-icon.png
new file mode 100644
index 0000000000..a90779f02a
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/default-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/images/downArrow.png b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/downArrow.png
new file mode 100644
index 0000000000..b92cb987b9
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/downArrow.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/images/expression.png b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/expression.png
new file mode 100644
index 0000000000..680bd408cc
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/expression.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/images/extended.png b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/extended.png
new file mode 100644
index 0000000000..82587ae0ec
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/extended.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/images/grid-icon.png b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/grid-icon.png
new file mode 100644
index 0000000000..113e14c00a
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/grid-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/images/image-icon.png b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/image-icon.png
new file mode 100644
index 0000000000..4dfcae7d47
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/image-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/images/item-icon.png b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/item-icon.png
new file mode 100644
index 0000000000..82587ae0ec
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/item-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/images/layout.png b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/layout.png
new file mode 100644
index 0000000000..113e14c00a
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/layout.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/images/leftArrow.png b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/leftArrow.png
new file mode 100644
index 0000000000..45187cf047
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/leftArrow.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/images/list-icon.png b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/list-icon.png
new file mode 100644
index 0000000000..9c96743f0e
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/list-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/images/mouse-region-icon.png b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/mouse-region-icon.png
new file mode 100644
index 0000000000..8c23b6c0fc
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/mouse-region-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/images/placeholder.png b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/placeholder.png
new file mode 100644
index 0000000000..18010a5ee5
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/placeholder.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/images/rect-icon.png b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/rect-icon.png
new file mode 100644
index 0000000000..4555d886fb
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/rect-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/images/reset-button.png b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/reset-button.png
new file mode 100644
index 0000000000..bf53422b9e
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/reset-button.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/images/rightArrow.png b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/rightArrow.png
new file mode 100644
index 0000000000..118436bbcc
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/rightArrow.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/images/standard.png b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/standard.png
new file mode 100644
index 0000000000..7c0911d63d
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/standard.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/images/submenu.png b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/submenu.png
new file mode 100644
index 0000000000..99c01e5563
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/submenu.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/images/text-edit-icon.png b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/text-edit-icon.png
new file mode 100644
index 0000000000..6a064ab07c
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/text-edit-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/images/text-icon.png b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/text-icon.png
new file mode 100644
index 0000000000..9ce62037ba
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/text-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/images/upArrow.png b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/upArrow.png
new file mode 100644
index 0000000000..e689de743e
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/images/upArrow.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/layoutWidget.css b/share/qtcreator/qmldesigner/propertyeditor/Qt/layoutWidget.css
new file mode 100644
index 0000000000..ce857900b8
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/layoutWidget.css
@@ -0,0 +1,35 @@
+QPushButton::checked
+ {
+ border-radius: 4px;
+ border: 4px solid #4f4f41;
+ border-image: none;
+ background-color: #9a9b9e;
+ }
+
+ QPushButton:pressed
+ {
+ border: 1px solid #5f5f51;
+ background-color: #dadbde;
+ background: none;
+ color: white;
+ }
+
+ QPushButton:flat {
+ border: 1px solid #5f5f51;
+ background-color: #eadbde;
+ color: white;
+ }
+
+ QPushButton:default {
+ border-color: 1px solid black;
+ background-color: #eadbde;
+ color: white;
+ }
+
+
+QFrame{
+ border: 2px solid black;
+ border-radius: 4px;
+ padding: 2px;
+ background: #aaabae;
+ } \ No newline at end of file
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/propertyEditor.css b/share/qtcreator/qmldesigner/propertyeditor/Qt/propertyEditor.css
new file mode 100644
index 0000000000..31af443f4c
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/propertyEditor.css
@@ -0,0 +1,397 @@
+QFrame, QSpinBox {
+ background-color: #707070;
+}
+
+QFrame
+{
+ border-radius: 0px;
+ font-size: 11px
+}
+
+WidgetFrame {
+ border: 0px;
+ background-color: #707070;
+}
+
+ QComboBox QAbstractItemView {
+ border: 2px solid darkgray;
+ background-color: White;
+ }
+
+QLabel {
+ border: none;
+ border-image: none;
+ padding: 0;
+ background: none;
+ color: #dedede;
+ font: bold
+}
+
+QScrollArea {
+ border: 0px;
+ border-radius: 0px;
+ background-color: #707070;
+}
+
+QGroupBox
+{
+background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0,
+ stop: 0 #4a4a4a, stop: 1 #4f4f4f);
+ border: 1px solid #4F4F4F;
+ border-radius: 5px;
+ color: white;
+ font: bold
+}
+
+QLineEdit
+{
+ color: white;
+ border: 2px solid #0F0F0F;
+ border-radius: 6px;
+ border-width: 1;
+ background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
+ stop: 0 #2c2c2c, stop: 1 #333333);
+}
+
+QTextEdit
+{
+ border: 2px solid #8F8F8F;
+ border-radius: 10px;
+ padding: 0 8px;
+ background-color: white;
+ selection-background-color: darkgray;
+}
+
+ QSpinBox
+ {
+ font-size: 11px;
+ color: white;
+ padding-right: 20px; /* make room for the arrows */
+ padding-top: 2px; /* make room for the arrows */
+ padding-bottom: 2px; /* make room for the arrows */
+ border: 2px solid #0F0F0F;
+ border-radius: 6px;
+ border-width: 1;
+ background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
+ stop: 0 #2c2c2c, stop: 1 #333333);
+
+ min-height: 14px;
+ max-height: 14px;
+ }
+
+ QDoubleSpinBox
+ {
+ font-size: 11px;
+ color: white;
+ padding-right: 20px; /* make room for the arrows */
+ padding-top: 2px; /* make room for the arrows */
+ padding-bottom: 2px; /* make room for the arrows */
+ border: 2px solid #0F0F0F;
+ border-radius: 6px;
+ border-width: 1;
+ background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
+ stop: 0 #2c2c2c, stop: 1 #333333);
+ max-height: 14px;
+ min-height: 14px;
+ }
+
+ QSpinBox::down-button {
+ subcontrol-origin: border;
+ subcontrol-position: bottom right; /* position at bottom right corner */
+ border-image: url(:/qmldesigner/images/spindown.png) 1;
+
+ width: 16px;
+ border-width: 1px;
+ border-top-width: 0;
+ }
+
+QSpinBox::down-button:hover {
+ border-image: url(:/qmldesigner/images/spindown_hover.png) 1;
+}
+
+QSpinBox::down-button:pressed {
+ border-image: url(:/qmldesigner/images/spindown_pressed.png) 1;
+}
+
+
+ QSpinBox::up-button {
+ subcontrol-origin: border;
+ subcontrol-position: top right; /* position at bottom right corner */
+ border-image: url(:/qmldesigner/images/spinup.png) 1;
+
+ width: 16px;
+ border-width: 1px;
+ }
+
+QSpinBox::up-button:hover {
+ border-image: url(:/qmldesigner/images/spinup_hover.png) 1;
+}
+
+QSpinBox::up-button:pressed {
+ border-image: url(:/qmldesigner/images/spinup_pressed.png) 1;
+}
+
+
+ QDoubleSpinBox::down-button {
+ subcontrol-origin: border;
+ subcontrol-position: bottom right; /* position at bottom right corner */
+ border-image: url(:/qmldesigner/images/spindown.png) 1;
+
+ width: 16px;
+ border-width: 1px;
+ }
+
+QDoubleSpinBox::down-button:hover {
+ border-image: url(:/qmldesigner/images/spindown_hover.png) 1;
+}
+
+QDoubleSpinBox::down-button:pressed {
+ border-image: url(:/qmldesigner/images/spindown_pressed.png) 1;
+}
+
+QDoubleSpinBox::up-button {
+ subcontrol-origin: border;
+ subcontrol-position: top right; /* position at bottom right corner */
+ border-image: url(:/qmldesigner/images/spinup.png) 1;
+
+ width: 16px;
+ border-width: 1px;
+}
+
+QDoubleSpinBox::up-button:hover {
+ border-image: url(:/qmldesigner/images/spinup_hover.png) 1;
+}
+
+QDoubleSpinBox::up-button:pressed {
+ border-image: url(:/qmldesigner/images/spinup_pressed.png) 1;
+}
+
+QToolButton
+{
+ background: none;
+ border: none;
+ background-color: none;
+}
+
+QToolButton::pressed
+{
+ background: none;
+ border: none;
+ background-color: none;
+}
+
+QToolButton::checked
+{
+ background: none;
+ border: none;
+}
+
+QPushButton {
+ padding: 0px;
+ font-size: 11px
+}
+
+QPushButton, QComboBox[editable="false"],
+QComboBox[editable="true"]::drop-down {
+ border-image: url(:/qmldesigner/images/pushbutton.png) 3;
+ border-width: 3;
+}
+
+QPushButton:hover, QComboBox[editable="false"]:hover,
+QComboBox[editable="true"]::drop-down:hover, QMenuBar::item:hover {
+ border-image: url(:/qmldesigner/images/pushbutton_hover.png) 3;
+ border-width: 3;
+}
+
+QPushButton:pressed, QComboBox[editable="false"]:on,
+QComboBox[editable="true"]::drop-down:on, QMenuBar::item:on {
+ border-image: url(:/qmldesigner/images/pushbutton_pressed.png) 3;
+ border-width: 3;
+}
+
+/* Customize read-only comboboxes. */
+
+QComboBox
+{
+ font-size: 11px;
+ color: white;
+}
+
+QComboBox[editable="false"] {
+ padding-left: 3px;
+ padding-right: 20px; /* space for the arrow */
+}
+
+QComboBox[editable="false"]::drop-down {
+ subcontrol-origin: padding;
+ subcontrol-position: top right;
+ width: 15px;
+ border-left-style: solid;
+ border-left-color: black;
+ border-left-width: 1px;
+}
+
+QComboBox[editable="false"]::down-arrow {
+ subcontrol-origin: content;
+ subcontrol-position: center;
+ position: relative;
+ left: 1px; /* 1 pixel dropdown border */
+}
+
+/* The combobox arrow is on when the popup is open. */
+QComboBox[editable="false"]::down-arrow:on {
+ position: relative;
+ top: 1px;
+ left: 2px;
+}
+
+/* Customize editable comboboxes. */
+
+QComboBox[editable="true"] {
+ padding-right: 16px;
+}
+
+QComboBox[editable="true"]::drop-down {
+ subcontrol-origin: border;
+ subcontrol-position: top right;
+ width: 13px;
+ position: absolute;
+ top: 2px;
+ bottom: 2px;
+ right: 2px;
+}
+
+QComboBox[editable="true"]::drop-down,
+QComboBox[editable="true"]::drop-down:hover,
+QComboBox[editable="true"]::drop-down:on {
+ border-width: 0px;
+ border-left-width: 3px; /* we need only left and center part */
+}
+
+/* Shift the arrow when it's open. */
+QComboBox[editable="true"]::down-arrow:on {
+ position: relative;
+ top: 1px;
+ left: 1px;
+}
+
+ QRadioButton {
+ spacing: 5px;
+}
+
+QRadioButton::indicator {
+ width: 13px;
+ height: 13px;
+}
+
+QRadioButton::indicator::unchecked {
+ image: url(:/qmldesigner/images/radiobutton_unchecked.png);
+}
+
+QRadioButton::indicator:unchecked:hover {
+ image: url(:/qmldesigner/images/radiobutton_unchecked_hover.png);
+}
+
+QRadioButton::indicator:unchecked:pressed {
+ image: url(:/qmldesigner/images/radiobutton_unchecked_pressed.png);
+}
+
+QRadioButton::indicator::checked {
+ image: url(:/qmldesigner/images/radiobutton_checked.png);
+}
+
+QRadioButton::indicator:checked:hover {
+ image: url(:/qmldesigner/images/radiobutton_checked_hover.png);
+}
+
+QRadioButton::indicator:checked:pressed {
+ image: url(:/qmldesigner/images/radiobutton_checked_pressed.png);
+}
+
+/* Customize arrows. */
+
+*::down-arrow, *::menu-indicator {
+ image: url(:/qmldesigner/images/down_arrow.png);
+ width: 7px;
+ height: 7px;
+}
+
+*::down-arrow:disabled, *::down-arrow:off {
+ image: url(:/qmldesigner/images/down_arrow_disabled.png);
+}
+
+*::up-arrow {
+ image: url(:/qmldesigner/images/up_arrow.png);
+ width: 7px;
+ height: 7px;
+}
+
+*::up-arrow:disabled, *::up-arrow:off {
+ image: url(:/qmldesigner/images/up_arrow_disabled.png);
+}
+
+/* Customize push buttons and comboboxes. Our read-only combobox
+ is very similar to a push button, so they share the same border image. */
+
+
+/* Customize check boxes. */
+QCheckBox {
+ spacing: 8px;
+ font-size: 11px
+}
+
+QCheckBox::indicator {
+ width: 20px;
+ height: 20px;
+}
+
+QCheckBox::indicator:unchecked {
+ image: url(:/qmldesigner/images/checkbox_unchecked.png);
+}
+
+QCheckBox::indicator:unchecked:hover {
+ image: url(:/qmldesigner/images/checkbox_unchecked_hover.png);
+}
+
+QCheckBox::indicator:unchecked:pressed {
+ image: url(:/qmldesigner/images/checkbox_unchecked_pressed.png);
+}
+
+QCheckBox::indicator:checked {
+ image: url(:/qmldesigner/images/checkbox_checked.png);
+}
+
+QCheckBox::indicator:checked:hover {
+ image: url(:/qmldesigner/images/checkbox_checked_hover.png);
+}
+
+QCheckBox::indicator:checked:pressed {
+ image: url(:/qmldesigner/images/checkbox_checked_pressed.png);
+}
+
+QMenu {
+ background-color: #494949; /* sets background of the menu */
+ border: 1px solid black;
+ margin: 0px; /* some spacing around the menu */
+ color: #cacaca;
+ }
+
+ QMenu::item {
+ /* sets background of menu item. set this to something non-transparent
+ if you want menu color and menu item color to be different */
+ background-color: transparent;
+ padding: 2px 25px 2px 20px;
+ }
+
+ QMenu::item:selected { /* when user selects item using mouse or keyboard */
+ background-color: #d2d2d2;
+ padding: 2px;
+ color: #404040;
+ border-radius: 4px;
+ }
+QMenu::separator {
+ height: 1px;
+ background: #404040;
+ margin-left: 5px;
+ margin-right: 5px;
+ }
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/specialCheckBox.css b/share/qtcreator/qmldesigner/propertyeditor/Qt/specialCheckBox.css
new file mode 100644
index 0000000000..73aa535f7f
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/specialCheckBox.css
@@ -0,0 +1,20 @@
+QCheckBox {
+ spacing: 2px;
+ border-width: 2px;
+ border-radius: 2px;
+ }
+
+ QCheckBox::indicator {
+ width: 13px;
+ height: 13px;
+ }
+ QLabel {
+ border : 2px solid gray;
+ border-radius: 10px;
+ padding: 0 8px;
+ background: yellow;
+ selection-background-color: darkgray;
+ }
+
+
+ \ No newline at end of file
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/switch.css b/share/qtcreator/qmldesigner/propertyeditor/Qt/switch.css
new file mode 100644
index 0000000000..b4fc0a3080
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/switch.css
@@ -0,0 +1,32 @@
+QPushButton {
+ border: 0px solid #6f6f61;
+ border-image: url(:/images/button2_normal.png) 2 2 2 2;
+ border-radius: 1px;
+ min-width: 20px;
+ min-height: 20px;
+ margin: 0px 0 2px 0;
+ }
+
+ QPushButton::checked
+ {
+ border-image: url(:/images/button2_pressed.png) 2 2 2 2;
+ border: 1px solid #4f4f41;
+ }
+
+ QPushButton:pressed {
+ border-image: url(:/images/button2_pressed.png) 2 2 2 2;
+
+ }
+
+ QPushButton:flat {
+ border: none; /* no border for a flat push button */
+ }
+
+ QPushButton:default {
+ border-image: url(:/images/button2_normal.png) 2 2 2 2;
+ }
+
+ QPushButton:hover {
+ border-image: url(:/images/button2_hovered.png) 2 2 2 2;
+ }
+ \ No newline at end of file
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/typeLabel.css b/share/qtcreator/qmldesigner/propertyeditor/Qt/typeLabel.css
new file mode 100644
index 0000000000..8df9e606db
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/typeLabel.css
@@ -0,0 +1,8 @@
+QLineEdit {
+ color: lightGray;
+ border: 2px solid #0F0F0F;
+ border-radius: 6px;
+ border-width: 2;
+ background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
+ stop: 0 #2c2c2c, stop: 1 #333333);
+} \ No newline at end of file
diff --git a/share/qtcreator/qmldesigner/welcome-card.png b/share/qtcreator/qmldesigner/welcome-card.png
new file mode 100644
index 0000000000..36633ddb87
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcome-card.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/welcomescreen.qml b/share/qtcreator/qmldesigner/welcomescreen.qml
new file mode 100644
index 0000000000..81a4cc4356
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomescreen.qml
@@ -0,0 +1,147 @@
+import Qt 4.6
+
+Image {
+ id: screen
+ property var selectedFile
+ signal openFile
+ source: "gradient.png"
+
+ width: 1045
+ height: 680
+
+ Image {
+ source: "welcome-card.png"
+
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.horizontalCenter: parent.horizontalCenter
+ transformOrigin: "Center"
+ smooth: true
+ scale: 0
+
+ //Animation
+ scale: SequentialAnimation {
+ running: true
+ NumberAnimation {
+ to: 1
+ duration: 400
+ easing: "easeOutCirc"
+ }
+ }
+ Text {
+ text: "Recent files"
+ style: "Sunken"
+ color: "white"
+ font.pointSize: 14
+ x: 70
+ y: 160
+ }
+
+ Text {
+ text: "New file"
+ style: "Sunken"
+ color: "white"
+ font.pointSize: 14
+ x: 380
+ y: 160
+ opacity: 0.8
+ }
+
+ Item {
+ id: leftSide
+ width: 300
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+
+ ListView {
+ id: recentFilesListView
+ width: 280
+ height: 320
+ x: 60
+ y: 200
+ overShoot: false
+
+ model: recentFiles
+ delegate: fileDelegate
+ }
+ }
+
+ Item {
+ id: rightSide
+ x: 300
+ width: 300
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+
+
+
+ ListView {
+ id: templatesListView
+ width: 280
+ height: 320
+ x: 80
+ y: 200
+ overShoot: false
+
+ model: templatesList
+ delegate: fileDelegate
+ }
+ }
+ Button {
+ id: chooseButton
+ label: " Choose"
+
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: 13
+ anchors.rightMargin: 40
+ }
+ }
+
+ Component {
+ id: fileDelegate
+ Item {
+ width: parent.width
+ height: fileDelegateText.height
+
+ Text {
+ id: fileDelegateText
+ anchors.left: parent.left
+ color: "white"
+ text: name
+ }
+
+ MouseRegion {
+ anchors.top: fileDelegateText.top
+ anchors.left: fileDelegateText.left
+ anchors.right: fileDelegateText.right
+ anchors.bottom: fileDelegateText.bottom
+ onClicked: {
+ screen.selectedFile = fileName;
+ screen.openFile();
+ }
+ }
+ }
+ }
+/*
+ ListModel {
+ id: recentFiles
+ ListElement {
+ fileName: "file1.qml"
+ }
+ ListElement {
+ fileName: "file2.qml"
+ }
+ ListElement {
+ fileName: "file3.qml"
+ }
+ }
+*/
+
+ ListModel {
+ id: templatesList
+ ListElement {
+ fileName: ":/qmldesigner/templates/General/Empty Fx"
+ name: "Fx Rectangle (640x480)"
+ }
+ }
+}
diff --git a/share/qtcreator/static.pro b/share/qtcreator/static.pro
index 0256c8ad73..46db15fa93 100644
--- a/share/qtcreator/static.pro
+++ b/share/qtcreator/static.pro
@@ -28,7 +28,8 @@ DATA_DIRS = \
designer \
schemes \
styles \
- gdbmacros
+ gdbmacros \
+ qmldesigner
!isEmpty(copydata) {
diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
index 11060df762..d889f91d21 100644
--- a/src/plugins/plugins.pro
+++ b/src/plugins/plugins.pro
@@ -38,7 +38,8 @@ SUBDIRS = plugin_coreplugin \
debugger/dumper.pro
contains(QT_CONFIG, declarative) {
- SUBDIRS += plugin_qmlinspector
+ SUBDIRS += plugin_qmlinspector \
+ plugin_qmldesigner
}
plugin_coreplugin.subdir = coreplugin
@@ -184,6 +185,10 @@ plugin_qmlprojectmanager.depends += plugin_projectexplorer
plugin_qmlprojectmanager.depends += plugin_help
plugin_qmlprojectmanager.depends += plugin_qmleditor
+plugin_qmldesigner.subdir = qmldesigner
+plugin_qmldesigner.depends = plugin_coreplugin
+plugin_qmldesigner.depends += plugin_texteditor
+
plugin_qmlinspector.subdir = qmlinspector
plugin_qmlinspector.depends += plugin_projectexplorer
plugin_qmlinspector.depends += plugin_coreplugin
diff --git a/src/plugins/qmldesigner/QmlDesigner.pluginspec b/src/plugins/qmldesigner/QmlDesigner.pluginspec
new file mode 100644
index 0000000000..a7894e6353
--- /dev/null
+++ b/src/plugins/qmldesigner/QmlDesigner.pluginspec
@@ -0,0 +1,25 @@
+<plugin name="QmlDesigner" version="1.3.80" compatVersion="1.3.80">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2008-2009 Nokia Corporation</copyright>
+ <license>
+Commercial Usage
+
+Licensees holding valid Qt Commercial licenses may use this plugin 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 plugin may be used under the terms of the GNU Lesser
+General Public License version 2.1 as published by the Free Software
+Foundation. Please review the following information to
+ensure the GNU Lesser General Public License version 2.1 requirements
+will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.</license>
+ <description>Editor for QML.</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name="Core" version="1.3.80"/>
+ <dependency name="TextEditor" version="1.3.80"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/qmldesigner/application.cpp b/src/plugins/qmldesigner/application.cpp
new file mode 100644
index 0000000000..223f185c67
--- /dev/null
+++ b/src/plugins/qmldesigner/application.cpp
@@ -0,0 +1,46 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "application.h"
+#include <QtCore/QCoreApplication>
+#include <QtCore/QFileInfo>
+
+
+#ifdef Q_OS_MAC
+# define SHARE_PATH "/../Resources/qmldesigner"
+#else
+# define SHARE_PATH "/../share/qtcreator/qmldesigner"
+#endif
+
+QString Application::sharedDirPath()
+{
+ QString appPath = QCoreApplication::applicationDirPath();
+
+ return QFileInfo(appPath + SHARE_PATH).absoluteFilePath();
+}
diff --git a/src/plugins/qmldesigner/application.h b/src/plugins/qmldesigner/application.h
new file mode 100644
index 0000000000..adf7f81001
--- /dev/null
+++ b/src/plugins/qmldesigner/application.h
@@ -0,0 +1,40 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef APPLICATION_H
+#define APPLICATION_H
+
+#include <QtCore/QString>
+
+class Application {
+public:
+ static QString sharedDirPath();
+};
+
+#endif // APPLICATION_H
diff --git a/src/plugins/qmldesigner/components/formeditor/abstractformeditortool.cpp b/src/plugins/qmldesigner/components/formeditor/abstractformeditortool.cpp
new file mode 100644
index 0000000000..884ba4c351
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/abstractformeditortool.cpp
@@ -0,0 +1,190 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "abstractformeditortool.h"
+#include "formeditorview.h"
+#include "formeditorview.h"
+
+#include <QtDebug>
+#include <QGraphicsSceneDragDropEvent>
+#include <nodemetainfo.h>
+
+namespace QmlDesigner {
+
+AbstractFormEditorTool::AbstractFormEditorTool(FormEditorView *editorView) : m_view(editorView)
+{
+}
+
+
+AbstractFormEditorTool::~AbstractFormEditorTool()
+{
+
+}
+
+FormEditorView* AbstractFormEditorTool::view() const
+{
+ return m_view;
+}
+
+FormEditorScene* AbstractFormEditorTool::scene() const
+{
+ return view()->scene();
+}
+
+void AbstractFormEditorTool::setItems(const QList<FormEditorItem*> &itemList)
+{
+ m_itemList = itemList;
+ selectedItemsChanged(m_itemList);
+}
+
+QList<FormEditorItem*> AbstractFormEditorTool::items() const
+{
+ return m_itemList;
+}
+
+bool AbstractFormEditorTool::topItemIsMovable(const QList<QGraphicsItem*> & itemList)
+{
+ QGraphicsItem *firstSelectableItem = topMovableGraphicsItem(itemList);
+ if (firstSelectableItem == 0)
+ return false;
+
+ FormEditorItem *formEditorItem = FormEditorItem::fromQGraphicsItem(firstSelectableItem);
+ QList<QmlItemNode> selectedNodes = view()->selectedQmlItemNodes();
+
+ if (formEditorItem != 0
+ && selectedNodes.contains(formEditorItem->qmlItemNode()))
+ return true;
+
+ return false;
+
+}
+
+bool AbstractFormEditorTool::topSelectedItemIsMovable(const QList<QGraphicsItem*> &itemList)
+{
+ QList<QmlItemNode> selectedNodes = view()->selectedQmlItemNodes();
+
+ foreach (QGraphicsItem *item, itemList) {
+ FormEditorItem *formEditorItem = FormEditorItem::fromQGraphicsItem(item);
+ if (formEditorItem
+ && selectedNodes.contains(formEditorItem->qmlItemNode())
+ && !formEditorItem->qmlItemNode().isRootNode()
+ && (formEditorItem->qmlItemNode().hasShowContent()))
+ return true;
+ }
+
+ foreach (QGraphicsItem *item, itemList) {
+ FormEditorItem *formEditorItem = FormEditorItem::fromQGraphicsItem(item);
+ if (formEditorItem
+ && !formEditorItem->qmlItemNode().isRootNode()
+ && selectedNodes.contains(formEditorItem->qmlItemNode()))
+ return true;
+ }
+
+ return false;
+
+}
+
+
+bool AbstractFormEditorTool::topItemIsResizeHandle(const QList<QGraphicsItem*> &/*itemList*/)
+{
+ return false;
+}
+
+QGraphicsItem *AbstractFormEditorTool::topMovableGraphicsItem(const QList<QGraphicsItem*> &itemList)
+{
+ foreach (QGraphicsItem *item, itemList) {
+ if (item->flags().testFlag(QGraphicsItem::ItemIsMovable))
+ return item;
+ }
+
+ return 0;
+}
+FormEditorItem *AbstractFormEditorTool::topMovableFormEditorItem(const QList<QGraphicsItem*> &itemList)
+{
+ foreach (QGraphicsItem *item, itemList) {
+ FormEditorItem *formEditorItem = FormEditorItem::fromQGraphicsItem(item);
+ if (formEditorItem
+ && (formEditorItem->qmlItemNode().hasShowContent()))
+ return formEditorItem;
+ }
+
+ return 0;
+}
+
+FormEditorItem* AbstractFormEditorTool::topFormEditorItem(const QList<QGraphicsItem*> & itemList)
+{
+ foreach (QGraphicsItem *item, itemList) {
+ FormEditorItem *formEditorItem = FormEditorItem::fromQGraphicsItem(item);
+ if (formEditorItem && !formEditorItem->qmlItemNode().isRootNode())
+ return formEditorItem;
+ }
+
+ return 0;
+}
+
+FormEditorItem* AbstractFormEditorTool::topFormEditorItemWithRootItem(const QList<QGraphicsItem*> & itemList)
+{
+ foreach (QGraphicsItem *item, itemList) {
+ FormEditorItem *formEditorItem = FormEditorItem::fromQGraphicsItem(item);
+ if (formEditorItem)
+ return formEditorItem;
+ }
+
+ return 0;
+}
+
+void AbstractFormEditorTool::dropEvent(QGraphicsSceneDragDropEvent * /* event */)
+{
+ Q_ASSERT(false);
+}
+
+void AbstractFormEditorTool::dragEnterEvent(QGraphicsSceneDragDropEvent * event)
+{
+ if (event->mimeData()->hasFormat("application/vnd.bauhaus.itemlibraryinfo") ||
+ event->mimeData()->hasFormat("application/vnd.bauhaus.libraryresource")) {
+ event->accept();
+ view()->changeToDragTool();
+ view()->currentTool()->dragEnterEvent(event);
+ } else {
+ event->ignore();
+ }
+}
+
+void AbstractFormEditorTool::dragLeaveEvent(QGraphicsSceneDragDropEvent * /* event */)
+{
+ Q_ASSERT(false);
+}
+
+void AbstractFormEditorTool::dragMoveEvent(QGraphicsSceneDragDropEvent * /* event */)
+{
+ Q_ASSERT(false);
+}
+
+
+}
diff --git a/src/plugins/qmldesigner/components/formeditor/abstractformeditortool.h b/src/plugins/qmldesigner/components/formeditor/abstractformeditortool.h
new file mode 100644
index 0000000000..c2e387c696
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/abstractformeditortool.h
@@ -0,0 +1,103 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef ABSTRACTFORMEDITORTOOL_H
+#define ABSTRACTFORMEDITORTOOL_H
+
+#include "formeditoritem.h"
+
+class QGraphicsItem;
+
+namespace QmlDesigner {
+
+class FormEditorView;
+
+class AbstractFormEditorTool
+{
+
+public:
+ AbstractFormEditorTool(FormEditorView* view);
+
+ virtual ~AbstractFormEditorTool();
+
+ virtual void mousePressEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event) = 0;
+ virtual void mouseMoveEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event) = 0;
+ virtual void mouseReleaseEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event) = 0;
+ virtual void mouseDoubleClickEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event) = 0;
+
+ virtual void hoverMoveEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event) = 0;
+
+ virtual void dropEvent(QGraphicsSceneDragDropEvent * event);
+ virtual void dragEnterEvent(QGraphicsSceneDragDropEvent * event);
+ virtual void dragLeaveEvent(QGraphicsSceneDragDropEvent * event);
+ virtual void dragMoveEvent(QGraphicsSceneDragDropEvent * event);
+
+ virtual void keyPressEvent(QKeyEvent *event) = 0;
+ virtual void keyReleaseEvent(QKeyEvent *keyEvent) = 0;
+
+ virtual void itemsAboutToRemoved(const QList<FormEditorItem*> &itemList) = 0;
+ // virtual QVariant itemChange(QList<QGraphicsItem*> itemList,
+// QGraphicsItem::GraphicsItemChange change,
+// const QVariant &value ) = 0;
+// virtual void update() = 0;
+ virtual void clear() = 0;
+
+ virtual void formEditorItemsChanged(const QList<FormEditorItem*> &itemList) = 0;
+
+ void setItems(const QList<FormEditorItem*> &itemList);
+ QList<FormEditorItem*> items() const;
+
+ static QGraphicsItem* topMovableGraphicsItem(const QList<QGraphicsItem*> &itemList);
+ static FormEditorItem* topMovableFormEditorItem(const QList<QGraphicsItem*> &itemList);
+ bool topItemIsMovable(const QList<QGraphicsItem*> &itemList);
+ bool topSelectedItemIsMovable(const QList<QGraphicsItem*> &itemList);
+ bool topItemIsResizeHandle(const QList<QGraphicsItem*> &itemList);
+
+ static FormEditorItem* topFormEditorItem(const QList<QGraphicsItem*> &itemList);
+ static FormEditorItem* topFormEditorItemWithRootItem(const QList<QGraphicsItem*> &itemList);
+protected:
+
+ virtual void selectedItemsChanged(const QList<FormEditorItem*> &itemList) = 0;
+
+
+ FormEditorView *view() const;
+ FormEditorScene* scene() const;
+private:
+ FormEditorView *m_view;
+ QList<FormEditorItem*> m_itemList;
+};
+
+}
+
+#endif // ABSTRACTFORMEDITORTOOL_H
diff --git a/src/plugins/qmldesigner/components/formeditor/anchor.png b/src/plugins/qmldesigner/components/formeditor/anchor.png
new file mode 100644
index 0000000000..fa59038318
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/anchor.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/formeditor/anchorcontroller.cpp b/src/plugins/qmldesigner/components/formeditor/anchorcontroller.cpp
new file mode 100644
index 0000000000..e59712216c
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/anchorcontroller.cpp
@@ -0,0 +1,537 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "anchorcontroller.h"
+
+#include "formeditoritem.h"
+#include "layeritem.h"
+#include "formeditorscene.h"
+#include "anchorhandleitem.h"
+#include <QtDebug>
+#include <cmath>
+namespace QmlDesigner {
+
+AnchorControllerData::AnchorControllerData(LayerItem *layerItem, FormEditorItem *formEditorItem)
+ : layerItem(layerItem),
+ formEditorItem(formEditorItem),
+ topItem(0),
+ leftItem(0),
+ rightItem(0),
+ bottomItem(0)
+{
+}
+
+AnchorControllerData::AnchorControllerData(const AnchorControllerData &other)
+ : layerItem(other.layerItem),
+ formEditorItem(other.formEditorItem),
+ topItem(other.topItem),
+ leftItem(other.leftItem),
+ rightItem(other.rightItem),
+ bottomItem(other.bottomItem)
+{
+}
+
+AnchorControllerData::~AnchorControllerData()
+{
+ if (layerItem) {
+ layerItem->scene()->removeItem(topItem);
+ layerItem->scene()->removeItem(leftItem);
+ layerItem->scene()->removeItem(rightItem);
+ layerItem->scene()->removeItem(bottomItem);
+ }
+}
+
+
+AnchorController::AnchorController()
+ : m_data(new AnchorControllerData(0, 0))
+{
+
+}
+
+AnchorController::AnchorController(const QSharedPointer<AnchorControllerData> &data)
+ : m_data(data)
+{
+
+}
+
+AnchorController::AnchorController(LayerItem *layerItem, FormEditorItem *formEditorItem)
+ : m_data(new AnchorControllerData(layerItem, formEditorItem))
+{
+ m_data->topItem = new AnchorHandleItem(layerItem, *this);
+ m_data->topItem->setZValue(400);
+ m_data->topItem->setToolTip(m_data->topItem->toolTipString());
+
+ m_data->leftItem = new AnchorHandleItem(layerItem, *this);
+ m_data->leftItem->setZValue(400);
+ m_data->leftItem->setToolTip(m_data->leftItem->toolTipString());
+
+ m_data->rightItem = new AnchorHandleItem(layerItem, *this);
+ m_data->rightItem->setZValue(400);
+ m_data->rightItem->setToolTip(m_data->rightItem->toolTipString());
+
+ m_data->bottomItem = new AnchorHandleItem(layerItem, *this);
+ m_data->bottomItem->setZValue(400);
+ m_data->bottomItem->setToolTip(m_data->bottomItem->toolTipString());
+
+ m_data->sceneTransform = formEditorItem->sceneTransform();
+
+ updatePosition();
+}
+
+
+bool AnchorController::isValid() const
+{
+ return m_data->formEditorItem != 0;
+}
+
+void AnchorController::show()
+{
+ m_data->topItem->show();
+ m_data->leftItem->show();
+ m_data->rightItem->show();
+ m_data->bottomItem->show();
+}
+
+
+
+void AnchorController::hide()
+{
+ m_data->topItem->hide();
+ m_data->leftItem->hide();
+ m_data->rightItem->hide();
+ m_data->bottomItem->hide();
+}
+
+
+static QPointF topCenter(const QRectF &rect)
+{
+ return QPointF(rect.center().x(), rect.top());
+}
+
+static QPointF leftCenter(const QRectF &rect)
+{
+ return QPointF(rect.left(), rect.center().y());
+}
+
+static QPointF rightCenter(const QRectF &rect)
+{
+ return QPointF(rect.right(), rect.center().y());
+}
+
+static QPointF bottomCenter(const QRectF &rect)
+{
+ return QPointF(rect.center().x(), rect.bottom());
+}
+
+static QPainterPath curveToPath(const QPointF &firstPoint,
+ const QPointF &secondPoint,
+ const QPointF &thirdPoint,
+ const QPointF &fourthPoint)
+{
+ QPainterPath path;
+ path.moveTo(firstPoint);
+ path.cubicTo(secondPoint, thirdPoint, fourthPoint);
+
+ return path;
+}
+
+static QPointF anchorPoint(const QRectF &boundingRect, AnchorLine::Type anchorLine, double baseOffset, double innerOffset = 0.0)
+{
+ switch(anchorLine) {
+ case AnchorLine::Top : return topCenter(boundingRect) + QPointF(baseOffset, innerOffset);
+ case AnchorLine::Bottom : return bottomCenter(boundingRect) - QPointF(baseOffset, innerOffset);
+ case AnchorLine::Left : return leftCenter(boundingRect) + QPointF(innerOffset, baseOffset);
+ case AnchorLine::Right : return rightCenter(boundingRect) - QPointF(innerOffset, baseOffset);
+ default: return QPointF();
+ }
+
+ return QPointF();
+}
+
+
+static QPainterPath createArrowPath(QPointF arrowCenter, double arrowDegrees)
+{
+ QRectF arrowRect(0.0, 0.0, 16., 16.);
+ arrowRect.moveCenter(arrowCenter);
+ QPainterPath arrowPath;
+
+
+ arrowPath.moveTo(arrowCenter);
+
+ arrowPath.arcTo(arrowRect, arrowDegrees + 180 - 20, 40.);
+
+ return arrowPath;
+}
+
+AnchorHandlePathData AnchorController::createPainterPathForAnchor(const QRectF &boundingRect,
+ AnchorLine::Type anchorLine,
+ const QPointF &targetPoint) const
+{
+
+
+ QPointF firstPointInLayerSpace(m_data->sceneTransform.map(anchorPoint(boundingRect, anchorLine, 0.0, 5.0)));
+
+ QPointF topLeftBoundingBoxInLayerSpace(m_data->sceneTransform.map(boundingRect.topLeft()));
+ QPointF bottomLeftBoundingBoxInLayerSpace(m_data->sceneTransform.map(boundingRect.bottomLeft()));
+ QPointF topRightBoundingBoxInLayerSpace(m_data->sceneTransform.map(boundingRect.topRight()));
+ QPointF bottomRightBoundingBoxInLayerSpace(m_data->sceneTransform.map(boundingRect.bottomRight()));
+
+ AnchorLine::Type secondAnchorLine(AnchorLine::Invalid);
+
+ QPointF secondPointInLayerSpace(targetPoint);
+ if (targetPoint.isNull()) {
+ AnchorLine targetAnchorLine(m_data->formEditorItem->qmlItemNode().anchors().instanceAnchor(anchorLine));
+ secondAnchorLine = targetAnchorLine.type();
+ FormEditorItem *targetItem = m_data->formEditorItem->scene()->itemForQmlItemNode(targetAnchorLine.qmlItemNode());;
+ bool secondItemIsParent = m_data->formEditorItem->parentItem() == targetItem;
+
+ if (secondItemIsParent)
+ secondPointInLayerSpace = (targetItem->mapToItem(m_data->layerItem.data(),
+ anchorPoint(targetItem->qmlItemNode().instanceBoundingRect(), targetAnchorLine.type(), 0.0)));
+ else
+
+ secondPointInLayerSpace = (targetItem->mapToItem(m_data->layerItem.data(),
+ anchorPoint(targetItem->qmlItemNode().instanceBoundingRect(), targetAnchorLine.type(), 0.0)));
+ }
+
+ QPointF firstControlPointInLayerSpace = (3. * firstPointInLayerSpace + 3 * secondPointInLayerSpace) / 6.;
+ QPointF secondControlPointInLayerSpace = (3 * firstPointInLayerSpace + 3. * secondPointInLayerSpace) / 6.;
+
+ bool showAnchorLine(true);
+ switch (anchorLine) {
+ case AnchorLine::Top :
+ case AnchorLine::Bottom :
+ firstControlPointInLayerSpace.rx() = firstPointInLayerSpace.x();
+ if (qAbs(secondPointInLayerSpace.y() - firstPointInLayerSpace.y()) < 18.0)
+ showAnchorLine = false;
+ if (qAbs(secondControlPointInLayerSpace.y() - secondPointInLayerSpace.y()) < 20.0 &&
+ qAbs(secondControlPointInLayerSpace.x() - secondPointInLayerSpace.x()) > 20.0) {
+ firstControlPointInLayerSpace.ry() = firstPointInLayerSpace.y() + ((firstControlPointInLayerSpace.y() - firstPointInLayerSpace.y() > 0) ? 20 : -20);
+ }
+ break;
+ case AnchorLine::Left :
+ case AnchorLine::Right :
+ firstControlPointInLayerSpace.ry() = firstPointInLayerSpace.y();
+ if (qAbs(secondPointInLayerSpace.x() - firstPointInLayerSpace.x()) < 18.0)
+ showAnchorLine = false;
+ if (qAbs(secondControlPointInLayerSpace.x() - secondPointInLayerSpace.x()) < 20.0 &&
+ qAbs(secondControlPointInLayerSpace.y() - secondPointInLayerSpace.y()) > 20.0) {
+ firstControlPointInLayerSpace.rx() = firstPointInLayerSpace.x() + ((firstControlPointInLayerSpace.x() - firstPointInLayerSpace.x() > 0) ? 20 : -20);
+ }
+ break;
+ default: break;
+ }
+
+ switch(secondAnchorLine) {
+ case AnchorLine::Top :
+ case AnchorLine::Bottom :
+ secondControlPointInLayerSpace.rx() = secondPointInLayerSpace.x();
+ if (qAbs(secondControlPointInLayerSpace.y() - secondPointInLayerSpace.y()) < 20.0 &&
+ qAbs(secondControlPointInLayerSpace.x() - secondPointInLayerSpace.x()) > 20.0) {
+ secondControlPointInLayerSpace.ry() = secondPointInLayerSpace.y() + ((secondControlPointInLayerSpace.y() - secondPointInLayerSpace.y() < 0) ? 20 : -20);
+ }
+ break;
+ case AnchorLine::Left :
+ case AnchorLine::Right :
+ secondControlPointInLayerSpace.ry() = secondPointInLayerSpace.y();
+ if (qAbs(secondControlPointInLayerSpace.x() - secondPointInLayerSpace.x()) < 20.0 &&
+ qAbs(secondControlPointInLayerSpace.y() - secondPointInLayerSpace.y()) > 20.0) {
+ secondControlPointInLayerSpace.rx() = secondPointInLayerSpace.x() + ((secondControlPointInLayerSpace.x() - secondPointInLayerSpace.x() < 0) ? 20 : -20);
+ }
+ break;
+ default: break;
+ }
+
+ QPainterPath anchorLinePath;
+ anchorLinePath.setFillRule(Qt::WindingFill);
+
+ QRectF baseRect(0.0, 0.0, 5., 5.);
+ baseRect.moveCenter(firstPointInLayerSpace);
+ QPainterPath basePath;
+ basePath.addRoundedRect(baseRect, 6., 6.);
+ anchorLinePath = anchorLinePath.united(basePath);
+
+ QRectF baseLineRect;
+ switch (anchorLine) {
+ case AnchorLine::Left : {
+ baseLineRect = QRectF(topLeftBoundingBoxInLayerSpace, bottomLeftBoundingBoxInLayerSpace);
+ baseLineRect.setWidth(3);
+ }
+ break;
+ case AnchorLine::Top : {
+ baseLineRect = QRectF(topLeftBoundingBoxInLayerSpace, topRightBoundingBoxInLayerSpace);
+ baseLineRect.setHeight(3);
+ }
+ break;
+ case AnchorLine::Right : {
+ baseLineRect = QRectF(topRightBoundingBoxInLayerSpace, bottomRightBoundingBoxInLayerSpace);
+ baseLineRect.adjust(-3, 0, 0, 0);
+ }
+ break;
+ case AnchorLine::Bottom : {
+ baseLineRect = QRectF(bottomLeftBoundingBoxInLayerSpace, bottomRightBoundingBoxInLayerSpace);
+ baseLineRect.adjust(0, -3, 0, 0);
+ }
+ break;
+ default: break;
+ }
+
+ if (!baseLineRect.isEmpty()) {
+
+ QPainterPath baseLinePath;
+ baseLinePath.addRoundedRect(baseLineRect, 1., 1.);
+ anchorLinePath = anchorLinePath.united(baseLinePath);
+ }
+
+ QPainterPath arrowPath;
+ arrowPath.setFillRule(Qt::WindingFill);
+
+
+
+ if (showAnchorLine) {
+ QPainterPath curvePath(curveToPath(firstPointInLayerSpace,
+ firstControlPointInLayerSpace,
+ secondControlPointInLayerSpace,
+ secondPointInLayerSpace));
+
+ double arrowDegrees = curvePath.angleAtPercent(curvePath.percentAtLength(curvePath.length() - 2.5));
+
+
+
+ QPainterPathStroker arrowPathStroker;
+ arrowPathStroker.setWidth(2.0);
+ arrowPathStroker.setCapStyle(Qt::RoundCap);
+
+ arrowPath = arrowPath.united(arrowPathStroker.createStroke(curvePath));
+
+
+
+
+
+ QRectF arrowCutRect(0.0, 0.0, 8., 8.);
+ arrowCutRect.moveCenter(secondPointInLayerSpace);
+ QPainterPath arrowCutPath;
+ arrowCutPath.addRect(arrowCutRect);
+ arrowPath = arrowPath.subtracted(arrowCutPath);
+
+ arrowPath = arrowPath.united(createArrowPath(secondPointInLayerSpace, arrowDegrees));
+ }
+
+ AnchorHandlePathData pathData;
+ pathData.arrowPath = arrowPath;
+ pathData.sourceAnchorLinePath = anchorLinePath;
+ pathData.beginArrowPoint = firstPointInLayerSpace;
+ pathData.endArrowPoint = secondPointInLayerSpace;
+
+ pathData.targetAnchorLinePath = createTargetAnchorLinePath(anchorLine);
+ pathData.targetNamePath = createTargetNamePathPath(anchorLine);
+
+ return pathData;
+}
+
+QPainterPath AnchorController::createTargetNamePathPath(AnchorLine::Type anchorLine) const
+{
+ QPainterPath path;
+ QmlAnchors anchors(formEditorItem()->qmlItemNode().anchors());
+ if (anchors.instanceHasAnchor(anchorLine)) {
+ AnchorLine targetAnchorLine(anchors.instanceAnchor(anchorLine));
+
+ FormEditorItem *targetItem = formEditorItem()->scene()->itemForQmlItemNode(targetAnchorLine.qmlItemNode());
+ QRectF boundingRect(targetItem->qmlItemNode().instanceBoundingRect());
+
+ QTransform sceneTransform(targetItem->qmlItemNode().instanceSceneTransform());
+
+ QPointF centerBoundingBoxInLayerSpace(sceneTransform.map(boundingRect.center()));
+
+ QFont font;
+ font.setPixelSize(24);
+ QString nameString(QString("%1 (%2)").arg(targetAnchorLine.qmlItemNode().simplfiedTypeName()).arg(targetAnchorLine.qmlItemNode().id()));
+ path.addText(0., -4., font, nameString);
+ //path.translate(centerBoundingBoxInLayerSpace - path.qmlItemNode().instanceBoundingRect().center());
+
+ }
+
+ return path;
+}
+
+QPainterPath AnchorController::createTargetAnchorLinePath(AnchorLine::Type anchorLine) const
+{
+ QPainterPath path;
+ QmlAnchors anchors(formEditorItem()->qmlItemNode().anchors());
+ if (anchors.instanceHasAnchor(anchorLine)) {
+ AnchorLine targetAnchorLine(anchors.instanceAnchor(anchorLine));
+
+ FormEditorItem *targetItem = formEditorItem()->scene()->itemForQmlItemNode(targetAnchorLine.qmlItemNode());
+ QRectF boundingRect(targetItem->qmlItemNode().instanceBoundingRect());
+
+ QTransform sceneTransform(targetItem->qmlItemNode().instanceSceneTransform());
+
+ QPointF topLeftBoundingBoxInLayerSpace(sceneTransform.map(boundingRect.topLeft()));
+ QPointF bottomLeftBoundingBoxInLayerSpace(sceneTransform.map(boundingRect.bottomLeft()));
+ QPointF topRightBoundingBoxInLayerSpace(sceneTransform.map(boundingRect.topRight()));
+ QPointF bottomRightBoundingBoxInLayerSpace(sceneTransform.map(boundingRect.bottomRight()));
+
+
+ switch(targetAnchorLine.type()) {
+ case AnchorLine::Top : {
+ path.moveTo(topLeftBoundingBoxInLayerSpace);
+ path.lineTo(topRightBoundingBoxInLayerSpace);
+ }
+ break;
+ case AnchorLine::Bottom : {
+ path.moveTo(bottomLeftBoundingBoxInLayerSpace);
+ path.lineTo(bottomRightBoundingBoxInLayerSpace);
+ }
+ break;
+ case AnchorLine::Left : {
+ path.moveTo(topLeftBoundingBoxInLayerSpace);
+ path.lineTo(bottomLeftBoundingBoxInLayerSpace);
+ }
+ break;
+ case AnchorLine::Right : {
+ path.moveTo(topRightBoundingBoxInLayerSpace);
+ path.lineTo(bottomRightBoundingBoxInLayerSpace);
+ }
+ break;
+ default: break;
+ }
+
+ QPainterPathStroker pathStroker;
+ pathStroker.setWidth(20.0);
+ pathStroker.setCapStyle(Qt::RoundCap);
+ path = pathStroker.createStroke(path);
+
+
+ }
+
+ return path;
+}
+
+void AnchorController::updatePosition()
+{
+ QRectF boundingRect = m_data->formEditorItem->qmlItemNode().instanceBoundingRect();
+ QPointF beginPoint;
+ QPointF endPoint;
+ QmlAnchors anchors(m_data->formEditorItem->qmlItemNode().anchors());
+ m_data->sceneTransform = m_data->formEditorItem->sceneTransform();
+
+ if (anchors.instanceHasAnchor(AnchorLine::Top))
+ m_data->topItem->setHandlePath(createPainterPathForAnchor(boundingRect, AnchorLine::Top));
+ else
+ m_data->topItem->setHandlePath(AnchorHandlePathData());
+
+ if (anchors.instanceHasAnchor(AnchorLine::Bottom))
+ m_data->bottomItem->setHandlePath(createPainterPathForAnchor(boundingRect, AnchorLine::Bottom));
+ else
+ m_data->bottomItem->setHandlePath(AnchorHandlePathData());
+
+ if (anchors.instanceHasAnchor(AnchorLine::Right))
+ m_data->rightItem->setHandlePath(createPainterPathForAnchor(boundingRect, AnchorLine::Right));
+ else
+ m_data->rightItem->setHandlePath(AnchorHandlePathData());
+
+ if (anchors.instanceHasAnchor(AnchorLine::Left))
+ m_data->leftItem->setHandlePath(createPainterPathForAnchor(boundingRect, AnchorLine::Left));
+ else
+ m_data->leftItem->setHandlePath(AnchorHandlePathData());
+}
+
+
+FormEditorItem* AnchorController::formEditorItem() const
+{
+ return m_data->formEditorItem;
+}
+
+QWeakPointer<AnchorControllerData> AnchorController::weakPointer() const
+{
+ return m_data;
+}
+
+
+bool AnchorController::isTopHandle(const AnchorHandleItem *handle) const
+{
+ return handle == m_data->topItem;
+}
+
+bool AnchorController::isLeftHandle(const AnchorHandleItem *handle) const
+{
+ return handle == m_data->leftItem;
+}
+
+bool AnchorController::isRightHandle(const AnchorHandleItem *handle) const
+{
+ return handle == m_data->rightItem;
+}
+
+bool AnchorController::isBottomHandle(const AnchorHandleItem *handle) const
+{
+ return handle == m_data->bottomItem;
+}
+
+void AnchorController::updateTargetPoint(AnchorLine::Type anchorLine, const QPointF &targetPoint)
+{
+ QRectF boundingRect = m_data->formEditorItem->qmlItemNode().instanceBoundingRect();
+
+ switch(anchorLine) {
+ case AnchorLine::Top :
+ m_data->topItem->setHandlePath(createPainterPathForAnchor(boundingRect, anchorLine, targetPoint)); break;
+ case AnchorLine::Bottom :
+ m_data->bottomItem->setHandlePath(createPainterPathForAnchor(boundingRect, anchorLine, targetPoint)); break;
+ case AnchorLine::Left :
+ m_data->leftItem->setHandlePath(createPainterPathForAnchor(boundingRect, anchorLine, targetPoint)); break;
+ case AnchorLine::Right :
+ m_data->rightItem->setHandlePath(createPainterPathForAnchor(boundingRect, anchorLine, targetPoint)); break;
+ default: break;
+ }
+}
+
+void AnchorController::highlight(AnchorLine::Type anchorLine)
+{
+ switch(anchorLine) {
+ case AnchorLine::Top :
+ m_data->topItem->setHighlighted(true); break;
+ case AnchorLine::Bottom :
+ m_data->bottomItem->setHighlighted(true); break;
+ case AnchorLine::Left :
+ m_data->leftItem->setHighlighted(true); break;
+ case AnchorLine::Right :
+ m_data->rightItem->setHighlighted(true); break;
+ default: break;
+ }
+}
+
+void AnchorController::clearHighlight()
+{
+ m_data->topItem->setHighlighted(false);
+ m_data->leftItem->setHighlighted(false);
+ m_data->rightItem->setHighlighted(false);
+ m_data->bottomItem->setHighlighted(false);
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/formeditor/anchorcontroller.h b/src/plugins/qmldesigner/components/formeditor/anchorcontroller.h
new file mode 100644
index 0000000000..4d693dd4b0
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/anchorcontroller.h
@@ -0,0 +1,117 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef ANCHORCONTROLLER_H
+#define ANCHORCONTROLLER_H
+
+#include <QSharedPointer>
+#include <QPainterPath>
+#include <QPair>
+#include <QTransform>
+#include <qmlanchors.h>
+
+namespace QmlDesigner {
+
+struct AnchorHandlePathData
+{
+ QPainterPath sourceAnchorLinePath;
+ QPainterPath targetAnchorLinePath;
+ QPainterPath arrowPath;
+ QPainterPath targetNamePath;
+ QPointF beginArrowPoint;
+ QPointF endArrowPoint;
+};
+
+class FormEditorItem;
+class LayerItem;
+class AnchorHandleItem;
+
+class AnchorControllerData
+{
+public:
+ AnchorControllerData(LayerItem *layerItem,
+ FormEditorItem *formEditorItem);
+ AnchorControllerData(const AnchorControllerData &other);
+ ~AnchorControllerData();
+
+ QWeakPointer<LayerItem> layerItem;
+ FormEditorItem *formEditorItem;
+
+ AnchorHandleItem *topItem;
+ AnchorHandleItem *leftItem;
+ AnchorHandleItem *rightItem;
+ AnchorHandleItem *bottomItem;
+
+ QTransform sceneTransform;
+};
+
+
+class AnchorController
+{
+ public:
+ AnchorController();
+ AnchorController(LayerItem *layerItem, FormEditorItem *formEditorItem);
+ AnchorController(const QSharedPointer<AnchorControllerData> &data);
+
+
+ void show();
+ void hide();
+
+ void updatePosition();
+
+ bool isValid() const;
+
+ QWeakPointer<AnchorControllerData> weakPointer() const;
+
+
+ FormEditorItem *formEditorItem() const;
+
+ bool isTopHandle(const AnchorHandleItem *handle) const;
+ bool isLeftHandle(const AnchorHandleItem *handle) const;
+ bool isRightHandle(const AnchorHandleItem *handle) const;
+ bool isBottomHandle(const AnchorHandleItem *handle) const;
+
+ void updateTargetPoint(AnchorLine::Type anchorLine, const QPointF &targetPoint);
+
+ void clearHighlight();
+ void highlight(AnchorLine::Type anchorLine);
+
+private: //functions
+ AnchorHandlePathData createPainterPathForAnchor(const QRectF &boundingRect,
+ AnchorLine::Type anchorLine,
+ const QPointF &targetPoint = QPointF()) const;
+ QPainterPath createTargetAnchorLinePath(AnchorLine::Type anchorLine) const;
+ QPainterPath createTargetNamePathPath(AnchorLine::Type anchorLine) const;
+private:
+ QSharedPointer<AnchorControllerData> m_data;
+};
+
+} // namespace QmlDesigner
+
+#endif // ANCHORCONTROLLER_H
diff --git a/src/plugins/qmldesigner/components/formeditor/anchorhandleitem.cpp b/src/plugins/qmldesigner/components/formeditor/anchorhandleitem.cpp
new file mode 100644
index 0000000000..95939c6e0f
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/anchorhandleitem.cpp
@@ -0,0 +1,212 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "anchorhandleitem.h"
+
+#include <formeditoritem.h>
+#include <QPen>
+#include <QPainterPathStroker>
+#include <cmath>
+#include <QtDebug>
+
+namespace QmlDesigner {
+
+AnchorHandleItem::AnchorHandleItem(QGraphicsItem *parent, const AnchorController &anchorController)
+ : QGraphicsItemGroup(parent),
+ m_anchorControllerData(anchorController.weakPointer()),
+ m_sourceAnchorLinePathItem(new QGraphicsPathItem(this)),
+ m_arrowPathItem(new QGraphicsPathItem(this)),
+ m_targetAnchorLinePathItem(new QGraphicsPathItem(this)),
+ m_targetNamePathItem(new QGraphicsPathItem(this))
+{
+ addToGroup(m_sourceAnchorLinePathItem);
+ addToGroup(m_arrowPathItem);
+ addToGroup(m_targetAnchorLinePathItem);
+ addToGroup(m_targetNamePathItem);
+
+ setFlag(QGraphicsItem::ItemIsMovable, true);
+}
+
+AnchorLine::Type AnchorHandleItem::sourceAnchorLine() const
+{
+ if (isTopHandle())
+ return AnchorLine::Top;
+ if (isBottomHandle())
+ return AnchorLine::Bottom;
+ if (isLeftHandle())
+ return AnchorLine::Left;
+ if (isRightHandle())
+ return AnchorLine::Right;
+
+ return AnchorLine::Invalid;
+}
+
+AnchorLine AnchorHandleItem::targetAnchorLine() const
+{
+ QmlAnchors anchors(anchorController().formEditorItem()->qmlItemNode().anchors());
+
+ if (isTopHandle())
+ return anchors.instanceAnchor(AnchorLine::Top);
+ if (isBottomHandle())
+ return anchors.instanceAnchor(AnchorLine::Bottom);
+ if (isLeftHandle())
+ return anchors.instanceAnchor(AnchorLine::Left);
+ if (isRightHandle())
+ return anchors.instanceAnchor(AnchorLine::Right);
+
+ return AnchorLine();
+}
+
+static QString anchorLineToString(AnchorLine::Type anchorLineType)
+{
+ switch(anchorLineType) {
+ case AnchorLine::Top: return "Top";
+ case AnchorLine::Bottom: return "Bottom";
+ case AnchorLine::Left: return "Left";
+ case AnchorLine::Right: return "Right";
+ default: break;
+ }
+
+ return QString();
+
+}
+
+QString AnchorHandleItem::toolTipString() const
+{
+ QString templateString("<p>Anchor Handle</p><p>%1</p><p>%2</p>");
+ QmlItemNode fromNode(anchorController().formEditorItem()->qmlItemNode());
+ QString fromString(QString("%3: %1(%2)").arg(fromNode.simplfiedTypeName(), fromNode.id(), anchorLineToString(sourceAnchorLine())));
+
+ AnchorLine toAnchorLine(targetAnchorLine());
+ QmlItemNode toNode(toAnchorLine.qmlItemNode());
+ QString toString;
+ if (toNode.isValid())
+ toString = QString("%3: %1(%2)").arg(toNode.simplfiedTypeName(), toNode.id(), anchorLineToString(toAnchorLine.type()));
+
+ return templateString.arg(fromString).arg(toString);
+}
+
+void AnchorHandleItem::setHandlePath(const AnchorHandlePathData &pathData)
+{
+ m_beginArrowPoint = pathData.beginArrowPoint;
+ m_endArrowPoint = pathData.endArrowPoint;
+ m_arrowPathItem->setPath(pathData.arrowPath);
+ m_sourceAnchorLinePathItem->setPath(pathData.sourceAnchorLinePath);
+ m_targetAnchorLinePathItem->setPath(pathData.targetAnchorLinePath);
+ m_targetNamePathItem->setPath(pathData.targetNamePath);
+
+ setHighlighted(false);
+}
+
+AnchorController AnchorHandleItem::anchorController() const
+{
+ Q_ASSERT(!m_anchorControllerData.isNull());
+ return AnchorController(m_anchorControllerData.toStrongRef());
+}
+
+AnchorHandleItem* AnchorHandleItem::fromGraphicsItem(QGraphicsItem *item)
+{
+ return qgraphicsitem_cast<AnchorHandleItem*>(item);
+}
+
+bool AnchorHandleItem::isTopHandle() const
+{
+ return anchorController().isTopHandle(this);
+}
+
+bool AnchorHandleItem::isLeftHandle() const
+{
+ return anchorController().isLeftHandle(this);
+}
+
+bool AnchorHandleItem::isRightHandle() const
+{
+ return anchorController().isRightHandle(this);
+}
+
+bool AnchorHandleItem::isBottomHandle() const
+{
+ return anchorController().isBottomHandle(this);
+}
+
+AnchorLine::Type AnchorHandleItem::anchorType() const
+{
+ if (isTopHandle())
+ return AnchorLine::Top;
+
+ if (isBottomHandle())
+ return AnchorLine::Bottom;
+
+ if (isLeftHandle())
+ return AnchorLine::Left;
+
+ if (isRightHandle())
+ return AnchorLine::Right;
+
+
+ return AnchorLine::Invalid;
+}
+
+void AnchorHandleItem::setHighlighted(bool highlight)
+{
+ QLinearGradient gradient(m_beginArrowPoint, m_endArrowPoint);
+ gradient.setCoordinateMode(QGradient::LogicalMode);
+ m_arrowPathItem->setPen(QPen(QBrush(Qt::gray), 1.0, Qt::SolidLine, Qt::RoundCap, Qt::MiterJoin));
+ m_targetAnchorLinePathItem->setPen(QColor(70, 0, 0, 90));
+ m_targetAnchorLinePathItem->setBrush(QColor(255, 0, 0, 50));
+ m_arrowPathItem->setPen(QPen(QBrush(Qt::gray), 1.0, Qt::SolidLine, Qt::RoundCap, Qt::MiterJoin));
+ m_targetNamePathItem->setPen(QColor(0, 0, 255, 90));
+ m_targetNamePathItem->setBrush(QColor(0, 0, 255, 50));
+
+ if (highlight) {
+ gradient.setColorAt(0.0, QColor(0, 0, 120, 255));
+ gradient.setColorAt(1.0, QColor(120, 0, 0, 255));
+ m_arrowPathItem->setBrush(gradient);
+ m_sourceAnchorLinePathItem->setPen(QColor(0, 0, 70, 255));
+ m_sourceAnchorLinePathItem->setBrush(QColor(0, 0, 70, 255));
+ m_targetAnchorLinePathItem->show();
+ m_targetNamePathItem->show();
+
+ } else {
+ gradient.setColorAt(0.0, QColor(0, 0, 255, 255));
+ gradient.setColorAt(1.0, QColor(255, 0, 0, 255));
+ m_arrowPathItem->setBrush(gradient);
+ m_sourceAnchorLinePathItem->setPen(QColor(0, 0, 100, 255));
+ m_sourceAnchorLinePathItem->setBrush(QColor(0, 0, 100, 255));
+ m_targetAnchorLinePathItem->hide();
+ m_targetNamePathItem->hide();
+ }
+}
+
+QPointF AnchorHandleItem::itemSpacePosition() const
+{
+ return parentItem()->mapToItem(anchorController().formEditorItem(), pos());
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/formeditor/anchorhandleitem.h b/src/plugins/qmldesigner/components/formeditor/anchorhandleitem.h
new file mode 100644
index 0000000000..6d6bd057f7
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/anchorhandleitem.h
@@ -0,0 +1,91 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef ANCHORHANDLEITEM_H
+#define ANCHORHANDLEITEM_H
+
+#include <QGraphicsItemGroup>
+
+#include "anchorcontroller.h"
+
+namespace QmlDesigner {
+
+class AnchorHandleItem : public QGraphicsItemGroup
+{
+public:
+ enum
+ {
+ Type = 0xEAEC
+ };
+
+
+ AnchorHandleItem(QGraphicsItem *parent, const AnchorController &anchorController);
+
+ void setHandlePath(const AnchorHandlePathData &pathData);
+
+ int type() const;
+
+ AnchorController anchorController() const;
+
+ static AnchorHandleItem* fromGraphicsItem(QGraphicsItem *item);
+
+
+ bool isTopHandle() const;
+ bool isLeftHandle() const;
+ bool isRightHandle() const;
+ bool isBottomHandle() const;
+
+ QPointF itemSpacePosition() const;
+
+ AnchorLine::Type anchorType() const;
+
+ QString toolTipString() const;
+ AnchorLine targetAnchorLine() const;
+ AnchorLine::Type sourceAnchorLine() const;
+
+ void setHighlighted(bool highlight);
+
+private:
+ QWeakPointer<AnchorControllerData> m_anchorControllerData;
+ QGraphicsPathItem *m_sourceAnchorLinePathItem;
+ QGraphicsPathItem *m_arrowPathItem;
+ QGraphicsPathItem *m_targetAnchorLinePathItem;
+ QGraphicsPathItem *m_targetNamePathItem;
+ QPointF m_beginArrowPoint;
+ QPointF m_endArrowPoint;
+};
+
+inline int AnchorHandleItem::type() const
+{
+ return Type;
+}
+
+} // namespace QmlDesigner
+
+#endif // ANCHORHANDLEITEM_H
diff --git a/src/plugins/qmldesigner/components/formeditor/anchorindicator.cpp b/src/plugins/qmldesigner/components/formeditor/anchorindicator.cpp
new file mode 100644
index 0000000000..78762c23f7
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/anchorindicator.cpp
@@ -0,0 +1,116 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "anchorindicator.h"
+
+#include <QSet>
+
+namespace QmlDesigner {
+
+AnchorIndicator::AnchorIndicator(LayerItem *layerItem)
+ : m_layerItem(layerItem)
+{
+ Q_ASSERT(layerItem);
+}
+
+AnchorIndicator::~AnchorIndicator()
+{
+ m_itemControllerHash.clear();
+}
+
+void AnchorIndicator::show()
+{
+ QHashIterator<FormEditorItem*, AnchorController> itemControllerIterator(m_itemControllerHash);
+ while (itemControllerIterator.hasNext()) {
+ AnchorController controller = itemControllerIterator.next().value();
+ controller.show();
+ }
+}
+
+
+void AnchorIndicator::hide()
+{
+ QHashIterator<FormEditorItem*, AnchorController> itemControllerIterator(m_itemControllerHash);
+ while (itemControllerIterator.hasNext()) {
+ AnchorController controller = itemControllerIterator.next().value();
+ controller.hide();
+ }
+}
+
+void AnchorIndicator::clear()
+{
+ m_itemControllerHash.clear();
+}
+
+void AnchorIndicator::setItems(const QList<FormEditorItem*> &itemList)
+{
+ clear();
+
+ foreach (FormEditorItem *item, itemList) {
+ AnchorController controller(m_layerItem, item);
+ m_itemControllerHash.insert(item, controller);
+ }
+
+ updateItems(itemList);
+}
+
+void AnchorIndicator::updateItems(const QList<FormEditorItem*> &itemList)
+{
+ foreach (FormEditorItem *item, itemList) {
+ if (m_itemControllerHash.contains(item)) {
+ AnchorController controller(m_itemControllerHash.value(item));
+ controller.updatePosition();
+ }
+ }
+}
+
+void AnchorIndicator::updateTargetPoint(FormEditorItem *item, AnchorLine::Type anchorLine, const QPointF &targetPoint)
+{
+ AnchorController controller(m_itemControllerHash.value(item));
+ controller.updateTargetPoint(anchorLine, targetPoint);
+}
+
+void AnchorIndicator::clearHighlight()
+{
+ QHashIterator<FormEditorItem*, AnchorController> itemControllerIterator(m_itemControllerHash);
+ while (itemControllerIterator.hasNext()) {
+ AnchorController controller = itemControllerIterator.next().value();
+ controller.clearHighlight();
+ }
+}
+
+void AnchorIndicator::highlight(FormEditorItem *item, AnchorLine::Type anchorLine)
+{
+ if (m_itemControllerHash.contains(item)) {
+ AnchorController controller(m_itemControllerHash.value(item));
+ controller.highlight(anchorLine);
+ }
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/formeditor/anchorindicator.h b/src/plugins/qmldesigner/components/formeditor/anchorindicator.h
new file mode 100644
index 0000000000..c36ed04be8
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/anchorindicator.h
@@ -0,0 +1,64 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef ANCHORINDICATOR_H
+#define ANCHORINDICATOR_H
+
+#include "anchorcontroller.h"
+#include <QList>
+#include <QHash>
+
+namespace QmlDesigner {
+
+class AnchorIndicator
+{
+public:
+ AnchorIndicator(LayerItem *layerItem);
+ ~AnchorIndicator();
+
+ void show();
+ void hide();
+ void clear();
+
+ void setItems(const QList<FormEditorItem*> &itemList);
+
+ void updateItems(const QList<FormEditorItem*> &itemList);
+ void updateTargetPoint(FormEditorItem *item, AnchorLine::Type anchorLine, const QPointF &targetPoint);
+
+ void clearHighlight();
+ void highlight(FormEditorItem *item, AnchorLine::Type anchorLine);
+
+private:
+ QHash<FormEditorItem*, AnchorController> m_itemControllerHash;
+ LayerItem *m_layerItem;
+};
+
+} // namespace QmlDesigner
+
+#endif // ANCHORINDICATOR_H
diff --git a/src/plugins/qmldesigner/components/formeditor/anchorlinecontroller.cpp b/src/plugins/qmldesigner/components/formeditor/anchorlinecontroller.cpp
new file mode 100644
index 0000000000..6877ad1b0f
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/anchorlinecontroller.cpp
@@ -0,0 +1,236 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "anchorlinecontroller.h"
+
+#include "formeditoritem.h"
+#include "layeritem.h"
+#include <QGraphicsScene>
+
+#include "anchorlinehandleitem.h"
+
+namespace QmlDesigner {
+
+
+AnchorLineControllerData::AnchorLineControllerData(LayerItem *layerItem, FormEditorItem *formEditorItem)
+ : layerItem(layerItem),
+ formEditorItem(formEditorItem),
+ topItem(0),
+ leftItem(0),
+ rightItem(0),
+ bottomItem(0)
+{
+}
+
+AnchorLineControllerData::AnchorLineControllerData(const AnchorLineControllerData &other)
+ : layerItem(other.layerItem),
+ formEditorItem(other.formEditorItem),
+ topItem(other.topItem),
+ leftItem(other.leftItem),
+ rightItem(other.rightItem),
+ bottomItem(other.bottomItem)
+{}
+
+AnchorLineControllerData::~AnchorLineControllerData()
+{
+ if (layerItem) {
+ layerItem->scene()->removeItem(topItem);
+ layerItem->scene()->removeItem(leftItem);
+ layerItem->scene()->removeItem(rightItem);
+ layerItem->scene()->removeItem(bottomItem);
+ }
+}
+
+
+AnchorLineController::AnchorLineController()
+ : m_data(new AnchorLineControllerData(0, 0))
+{
+
+}
+
+AnchorLineController::AnchorLineController(const QSharedPointer<AnchorLineControllerData> &data)
+ : m_data(data)
+{
+
+}
+
+AnchorLineController::AnchorLineController(LayerItem *layerItem, FormEditorItem *formEditorItem)
+ : m_data(new AnchorLineControllerData(layerItem, formEditorItem))
+{
+ m_data->topItem = new AnchorLineHandleItem(layerItem, *this);
+ m_data->topItem->setZValue(300);
+
+ m_data->leftItem = new AnchorLineHandleItem(layerItem, *this);
+ m_data->leftItem->setZValue(300);
+
+ m_data->rightItem = new AnchorLineHandleItem(layerItem, *this);
+ m_data->rightItem->setZValue(300);
+
+ m_data->bottomItem = new AnchorLineHandleItem(layerItem, *this);
+ m_data->bottomItem->setZValue(300);
+
+ updatePosition();
+}
+
+
+bool AnchorLineController::isValid() const
+{
+ return m_data->formEditorItem != 0;
+}
+
+void AnchorLineController::show(AnchorLine::Type anchorLineMask)
+{
+ if (anchorLineMask & AnchorLine::Top)
+ m_data->topItem->show();
+ else
+ m_data->topItem->hide();
+
+ if (anchorLineMask & AnchorLine::Left)
+ m_data->leftItem->show();
+ else
+ m_data->leftItem->hide();
+
+ if (anchorLineMask & AnchorLine::Right)
+ m_data->rightItem->show();
+ else
+ m_data->rightItem->hide();
+
+ if (anchorLineMask & AnchorLine::Bottom)
+ m_data->bottomItem->show();
+ else
+ m_data->bottomItem->hide();
+}
+
+void AnchorLineController::hide()
+{
+ m_data->topItem->hide();
+ m_data->leftItem->hide();
+ m_data->rightItem->hide();
+ m_data->bottomItem->hide();
+}
+
+static QPainterPath rectToPath(const QRectF &rect)
+{
+ QPainterPath path;
+ path.addRoundedRect(rect, 4, 4);
+
+ return path;
+}
+
+void AnchorLineController::updatePosition()
+{
+ QRectF boundingRect = m_data->formEditorItem->qmlItemNode().instanceBoundingRect();
+
+ QRectF topBoundingRect(boundingRect);
+ QRectF leftBoundingRect(boundingRect);
+ QRectF bottomBoundingRect(boundingRect);
+ QRectF rightBoundingRect(boundingRect);
+
+
+ if (formEditorItem()->isContainer()) {
+ topBoundingRect.setBottom(boundingRect.top() + 6);
+ topBoundingRect.adjust(7, -5, -7, 0);
+
+ leftBoundingRect.setRight(boundingRect.left() + 6);
+ leftBoundingRect.adjust(-5, 7, 0, -7);
+
+ bottomBoundingRect.setTop(boundingRect.bottom() - 6);
+ bottomBoundingRect.adjust(7, 0, -7, 5);
+
+ rightBoundingRect.setLeft(boundingRect.right() - 6);
+ rightBoundingRect.adjust(0, 7, 5, -7);
+
+ } else {
+ double height = qMin(boundingRect.height() / 4., 10.);
+ double width = qMin(boundingRect.width() / 4., 10.);
+
+ topBoundingRect.setHeight(height);
+ topBoundingRect.adjust(width, -4, -width, -1);
+
+ leftBoundingRect.setWidth(width);
+ leftBoundingRect.adjust(-4, height, -1, -height);
+
+ bottomBoundingRect.setTop(boundingRect.bottom() - height);
+ bottomBoundingRect.adjust(width, 1, -width, 4);
+
+ rightBoundingRect.setLeft(boundingRect.right() - width);
+ rightBoundingRect.adjust(1, height, 4, -height);
+ }
+
+ m_data->topItem->setHandlePath(m_data->formEditorItem->mapToItem(m_data->layerItem.data(),
+ rectToPath(topBoundingRect)));
+ m_data->leftItem->setHandlePath(m_data->formEditorItem->mapToItem(m_data->layerItem.data(),
+ rectToPath(leftBoundingRect)));
+ m_data->bottomItem->setHandlePath(m_data->formEditorItem->mapToItem(m_data->layerItem.data(),
+ rectToPath(bottomBoundingRect)));
+ m_data->rightItem->setHandlePath(m_data->formEditorItem->mapToItem(m_data->layerItem.data(),
+ rectToPath(rightBoundingRect)));
+}
+
+
+FormEditorItem* AnchorLineController::formEditorItem() const
+{
+ return m_data->formEditorItem;
+}
+
+QWeakPointer<AnchorLineControllerData> AnchorLineController::weakPointer() const
+{
+ return m_data;
+}
+
+
+bool AnchorLineController::isTopHandle(const AnchorLineHandleItem *handle) const
+{
+ return handle == m_data->topItem;
+}
+
+bool AnchorLineController::isLeftHandle(const AnchorLineHandleItem *handle) const
+{
+ return handle == m_data->leftItem;
+}
+
+bool AnchorLineController::isRightHandle(const AnchorLineHandleItem *handle) const
+{
+ return handle == m_data->rightItem;
+}
+
+bool AnchorLineController::isBottomHandle(const AnchorLineHandleItem *handle) const
+{
+ return handle == m_data->bottomItem;
+}
+
+void AnchorLineController::clearHighlight()
+{
+ m_data->topItem->setHiglighted(false);
+ m_data->leftItem->setHiglighted(false);
+ m_data->rightItem->setHiglighted(false);
+ m_data->bottomItem->setHiglighted(false);
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/formeditor/anchorlinecontroller.h b/src/plugins/qmldesigner/components/formeditor/anchorlinecontroller.h
new file mode 100644
index 0000000000..98701705e0
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/anchorlinecontroller.h
@@ -0,0 +1,93 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef ANCHORLINECONTROLLER_H
+#define ANCHORLINECONTROLLER_H
+
+#include <QWeakPointer>
+#include <QSharedPointer>
+#include <qmlanchors.h>
+
+namespace QmlDesigner {
+
+class FormEditorItem;
+class LayerItem;
+class AnchorLineHandleItem;
+
+class AnchorLineControllerData
+{
+public:
+ AnchorLineControllerData(LayerItem *layerItem,
+ FormEditorItem *formEditorItem);
+ AnchorLineControllerData(const AnchorLineControllerData &other);
+ ~AnchorLineControllerData();
+
+ QWeakPointer<LayerItem> layerItem;
+ FormEditorItem *formEditorItem;
+
+ AnchorLineHandleItem *topItem;
+ AnchorLineHandleItem *leftItem;
+ AnchorLineHandleItem *rightItem;
+ AnchorLineHandleItem *bottomItem;
+};
+
+
+class AnchorLineController
+{
+ public:
+ AnchorLineController();
+ AnchorLineController(LayerItem *layerItem, FormEditorItem *formEditorItem);
+ AnchorLineController(const QSharedPointer<AnchorLineControllerData> &data);
+
+ void show(AnchorLine::Type anchorLineMask);
+ void hide();
+
+ void updatePosition();
+
+ bool isValid() const;
+
+ QWeakPointer<AnchorLineControllerData> weakPointer() const;
+
+
+ FormEditorItem *formEditorItem() const;
+
+ bool isTopHandle(const AnchorLineHandleItem *handle) const;
+ bool isLeftHandle(const AnchorLineHandleItem *handle) const;
+ bool isRightHandle(const AnchorLineHandleItem *handle) const;
+ bool isBottomHandle(const AnchorLineHandleItem *handle) const;
+
+ void clearHighlight();
+
+private:
+ QSharedPointer<AnchorLineControllerData> m_data;
+};
+
+} // namespace QmlDesigner
+
+#endif // ANCHORLINECONTROLLER_H
diff --git a/src/plugins/qmldesigner/components/formeditor/anchorlinehandleitem.cpp b/src/plugins/qmldesigner/components/formeditor/anchorlinehandleitem.cpp
new file mode 100644
index 0000000000..e2aa10b67f
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/anchorlinehandleitem.cpp
@@ -0,0 +1,148 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "anchorlinehandleitem.h"
+
+#include <formeditoritem.h>
+#include <QPen>
+#include <cmath>
+
+namespace QmlDesigner {
+
+AnchorLineHandleItem::AnchorLineHandleItem(QGraphicsItem *parent, const AnchorLineController &anchorLineController)
+ : QGraphicsPathItem(parent),
+ m_anchorLineControllerData(anchorLineController.weakPointer())
+{
+ setFlag(QGraphicsItem::ItemIsMovable, true);
+ setHiglighted(false);
+}
+
+void AnchorLineHandleItem::setHandlePath(const QPainterPath & path)
+{
+ setPath(path);
+ update();
+}
+
+QRectF AnchorLineHandleItem::boundingRect() const
+{
+ return QGraphicsPathItem::boundingRect();
+}
+
+QPainterPath AnchorLineHandleItem::shape() const
+{
+ return QGraphicsPathItem::shape();
+}
+
+AnchorLineController AnchorLineHandleItem::anchorLineController() const
+{
+ Q_ASSERT(!m_anchorLineControllerData.isNull());
+ return AnchorLineController(m_anchorLineControllerData.toStrongRef());
+}
+
+AnchorLine::Type AnchorLineHandleItem::anchorLine() const
+{
+ if (isTopHandle())
+ return AnchorLine::Top;
+
+ if (isLeftHandle())
+ return AnchorLine::Left;
+
+ if (isRightHandle())
+ return AnchorLine::Right;
+
+ if (isBottomHandle())
+ return AnchorLine::Bottom;
+
+ return AnchorLine::Invalid;
+}
+
+AnchorLineHandleItem* AnchorLineHandleItem::fromGraphicsItem(QGraphicsItem *item)
+{
+ return qgraphicsitem_cast<AnchorLineHandleItem*>(item);
+}
+
+bool AnchorLineHandleItem::isTopHandle() const
+{
+ return anchorLineController().isTopHandle(this);
+}
+
+bool AnchorLineHandleItem::isLeftHandle() const
+{
+ return anchorLineController().isLeftHandle(this);
+}
+
+bool AnchorLineHandleItem::isRightHandle() const
+{
+ return anchorLineController().isRightHandle(this);
+}
+
+bool AnchorLineHandleItem::isBottomHandle() const
+{
+ return anchorLineController().isBottomHandle(this);
+}
+
+AnchorLine::Type AnchorLineHandleItem::anchorLineType() const
+{
+ if (isTopHandle())
+ return AnchorLine::Top;
+
+ if (isBottomHandle())
+ return AnchorLine::Bottom;
+
+ if (isLeftHandle())
+ return AnchorLine::Left;
+
+ if (isRightHandle())
+ return AnchorLine::Right;
+
+
+ return AnchorLine::Invalid;
+}
+
+QPointF AnchorLineHandleItem::itemSpacePosition() const
+{
+ return parentItem()->mapToItem(anchorLineController().formEditorItem(), pos());
+}
+
+void AnchorLineHandleItem::setHiglighted(bool highlight)
+{
+ if (highlight) {
+ QPen pen;
+ pen.setColor(QColor(108, 141, 221));
+ setPen(pen);
+ setBrush(QColor(108, 141, 221, 140));
+ } else {
+ QPen pen;
+ pen.setColor(QColor(108, 141, 221));
+ setPen(pen);
+ setBrush(QColor(108, 141, 221, 60));
+ }
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/formeditor/anchorlinehandleitem.h b/src/plugins/qmldesigner/components/formeditor/anchorlinehandleitem.h
new file mode 100644
index 0000000000..b35ec346ac
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/anchorlinehandleitem.h
@@ -0,0 +1,86 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef ANCHORLINEHANDLEITEM_H
+#define ANCHORLINEHANDLEITEM_H
+
+#include <QGraphicsPathItem>
+
+#include "anchorlinecontroller.h"
+
+namespace QmlDesigner {
+
+class AnchorLineHandleItem : public QGraphicsPathItem
+{
+public:
+ enum
+ {
+ Type = 0xEAEB
+ };
+
+
+ AnchorLineHandleItem(QGraphicsItem *parent, const AnchorLineController &AnchorLineController);
+
+ void setHandlePath(const QPainterPath & path);
+
+ int type() const;
+ QRectF boundingRect() const;
+ QPainterPath shape() const;
+
+ AnchorLineController anchorLineController() const;
+ AnchorLine::Type anchorLine() const;
+
+
+ static AnchorLineHandleItem* fromGraphicsItem(QGraphicsItem *item);
+
+
+ bool isTopHandle() const;
+ bool isLeftHandle() const;
+ bool isRightHandle() const;
+ bool isBottomHandle() const;
+
+ QPointF itemSpacePosition() const;
+
+ AnchorLine::Type anchorLineType() const;
+
+ void setHiglighted(bool highlight);
+
+
+private:
+ QWeakPointer<AnchorLineControllerData> m_anchorLineControllerData;
+};
+
+inline int AnchorLineHandleItem::type() const
+{
+ return Type;
+}
+
+} // namespace QmlDesigner
+
+#endif // ANCHORLINEHANDLEITEM_H
diff --git a/src/plugins/qmldesigner/components/formeditor/anchorlineindicator.cpp b/src/plugins/qmldesigner/components/formeditor/anchorlineindicator.cpp
new file mode 100644
index 0000000000..a521faf216
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/anchorlineindicator.cpp
@@ -0,0 +1,131 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "anchorlineindicator.h"
+
+#include <QSet>
+
+namespace QmlDesigner {
+
+AnchorLineIndicator::AnchorLineIndicator(LayerItem *layerItem)
+ : m_layerItem(layerItem)
+{
+ Q_ASSERT(layerItem);
+}
+
+AnchorLineIndicator::~AnchorLineIndicator()
+{
+ m_itemControllerHash.clear();
+}
+
+void AnchorLineIndicator::show(AnchorLine::Type anchorLineMask)
+{
+ QHashIterator<FormEditorItem*, AnchorLineController> itemControllerIterator(m_itemControllerHash);
+ while (itemControllerIterator.hasNext()) {
+ AnchorLineController controller = itemControllerIterator.next().value();
+ controller.show(anchorLineMask);
+ }
+}
+
+void AnchorLineIndicator::hide()
+{
+ QHashIterator<FormEditorItem*, AnchorLineController> itemControllerIterator(m_itemControllerHash);
+ while (itemControllerIterator.hasNext()) {
+ AnchorLineController controller = itemControllerIterator.next().value();
+ controller.hide();
+ }
+}
+
+void AnchorLineIndicator::clear()
+{
+ m_itemControllerHash.clear();
+}
+
+void AnchorLineIndicator::setItem(FormEditorItem* item)
+{
+ if (!item)
+ return;
+
+ QList<FormEditorItem*> itemList;
+ itemList.append(item);
+
+ setItems(itemList);
+}
+
+static bool equalLists(const QList<FormEditorItem*> &firstList, const QList<FormEditorItem*> &secondList)
+{
+ return firstList.toSet() == secondList.toSet();
+}
+
+void AnchorLineIndicator::setItems(const QList<FormEditorItem*> &itemList)
+{
+ if (equalLists(itemList, m_itemControllerHash.keys()))
+ return;
+
+ clear();
+
+ foreach (FormEditorItem *item, itemList) {
+ AnchorLineController controller(m_layerItem, item);
+ m_itemControllerHash.insert(item, controller);
+ }
+
+ show(AnchorLine::AllMask);
+}
+
+void AnchorLineIndicator::updateItems(const QList<FormEditorItem*> &itemList)
+{
+ foreach (FormEditorItem *item, itemList) {
+ if (m_itemControllerHash.contains(item)) {
+ AnchorLineController controller(m_itemControllerHash.value(item));
+ controller.updatePosition();
+ }
+ }
+}
+
+void AnchorLineIndicator::update()
+{
+ foreach (FormEditorItem *item, m_itemControllerHash.keys()) {
+ if (m_itemControllerHash.contains(item)) {
+ AnchorLineController controller(m_itemControllerHash.value(item));
+ controller.updatePosition();
+ }
+ }
+}
+
+void AnchorLineIndicator::clearHighlight()
+{
+ foreach (FormEditorItem *item, m_itemControllerHash.keys()) {
+ if (m_itemControllerHash.contains(item)) {
+ AnchorLineController controller(m_itemControllerHash.value(item));
+ controller.clearHighlight();
+ }
+ }
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/formeditor/anchorlineindicator.h b/src/plugins/qmldesigner/components/formeditor/anchorlineindicator.h
new file mode 100644
index 0000000000..2a4c9966fc
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/anchorlineindicator.h
@@ -0,0 +1,69 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef ANCHORLINEINDICATOR_H
+#define ANCHORLINEINDICATOR_H
+
+#include "layeritem.h"
+#include "anchorlinecontroller.h"
+#include <QHash>
+
+namespace QmlDesigner {
+
+class FormEditorItem;
+
+class AnchorLineIndicator
+{
+public:
+ AnchorLineIndicator(LayerItem *layerItem);
+ ~AnchorLineIndicator();
+
+ void show(AnchorLine::Type anchorLineMask);
+
+ void hide();
+
+ void clear();
+
+ void update();
+
+ void setItems(const QList<FormEditorItem*> &itemList);
+ void setItem(FormEditorItem* item);
+ void updateItems(const QList<FormEditorItem*> &itemList);
+
+ void clearHighlight();
+
+private:
+ QHash<FormEditorItem*, AnchorLineController> m_itemControllerHash;
+
+ LayerItem *m_layerItem;
+};
+
+} // namespace QmlDesigner
+
+#endif // ANCHORLINEINDICATOR_H
diff --git a/src/plugins/qmldesigner/components/formeditor/anchormanipulator.cpp b/src/plugins/qmldesigner/components/formeditor/anchormanipulator.cpp
new file mode 100644
index 0000000000..1468ae1e5f
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/anchormanipulator.cpp
@@ -0,0 +1,144 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "anchormanipulator.h"
+
+#include "formeditoritem.h"
+#include "formeditorscene.h"
+#include "formeditorview.h"
+#include <model.h>
+#include <rewritertransaction.h>
+
+namespace QmlDesigner {
+
+AnchorManipulator::AnchorManipulator(FormEditorView *view)
+ : m_beginFormEditorItem(0),
+ m_beginAnchorLine(AnchorLine::Invalid),
+ m_view(view)
+{
+}
+
+AnchorManipulator::~AnchorManipulator()
+{
+ clear();
+}
+
+void AnchorManipulator::begin(FormEditorItem *beginItem, AnchorLine::Type anchorLine)
+{
+ m_beginFormEditorItem = beginItem;
+ m_beginAnchorLine = anchorLine;
+}
+
+static double offset(const QPointF &topLeft, const QPointF &bottomRight, AnchorLine::Type anchorLine)
+{
+ switch(anchorLine) {
+ case AnchorLine::Top : return topLeft.y();
+ case AnchorLine::Left : return topLeft.x();
+ case AnchorLine::Bottom : return bottomRight.y();
+ case AnchorLine::Right : return bottomRight.x();
+ default: break;
+ }
+
+ return 0.0;
+}
+
+void AnchorManipulator::setMargin(FormEditorItem *endItem, AnchorLine::Type endAnchorLine)
+{
+ QPointF beginItemTopLeft(m_beginFormEditorItem->mapToParent(m_beginFormEditorItem->qmlItemNode().instanceBoundingRect().topLeft()));
+ QPointF endItemTopLeft(m_beginFormEditorItem->parentItem()->mapFromItem(endItem, endItem->qmlItemNode().instanceBoundingRect().topLeft()));
+
+ QPointF beginItemBottomRight(m_beginFormEditorItem->mapToParent(m_beginFormEditorItem->qmlItemNode().instanceBoundingRect().bottomRight()));
+ QPointF endItemBottomRight(m_beginFormEditorItem->parentItem()->mapFromItem(endItem, endItem->qmlItemNode().instanceBoundingRect().bottomRight()));
+
+ QPointF topLeftAnchorOffset = beginItemTopLeft - endItemTopLeft;
+ QPointF bottomRightAnchorOffset = endItemBottomRight - beginItemBottomRight;
+
+
+ double anchorOffset = 0.0;
+ if (m_beginAnchorLine & (AnchorLine::Bottom | AnchorLine::Right)) {
+ anchorOffset = offset(endItemTopLeft, endItemBottomRight, endAnchorLine) -
+ offset(beginItemTopLeft, beginItemBottomRight, m_beginAnchorLine);
+ } else {
+ anchorOffset = offset(beginItemTopLeft, beginItemBottomRight, m_beginAnchorLine) -
+ offset(endItemTopLeft, endItemBottomRight, endAnchorLine);
+ }
+
+ m_beginFormEditorItem->qmlItemNode().anchors().setMargin(m_beginAnchorLine, anchorOffset);
+}
+void AnchorManipulator::addAnchor(FormEditorItem *endItem, AnchorLine::Type endAnchorLine)
+{
+ RewriterTransaction m_rewriterTransaction = m_view->beginRewriterTransaction();
+ setMargin(endItem, endAnchorLine);
+
+ m_beginFormEditorItem->qmlItemNode().anchors().setAnchor(m_beginAnchorLine,
+ endItem->qmlItemNode(),
+ endAnchorLine);
+}
+
+void AnchorManipulator::removeAnchor()
+{
+ RewriterTransaction transaction = m_view->beginRewriterTransaction();
+ QmlAnchors anchors(m_beginFormEditorItem->qmlItemNode().anchors());
+ if (anchors.instanceHasAnchor(m_beginAnchorLine)) {
+ anchors.removeAnchor(m_beginAnchorLine);
+ anchors.removeMargin(m_beginAnchorLine);
+ }
+}
+
+void AnchorManipulator::clear()
+{
+ m_beginFormEditorItem = 0;
+ m_beginAnchorLine = AnchorLine::Invalid;
+}
+
+bool AnchorManipulator::isActive() const
+{
+ return m_beginFormEditorItem && m_beginAnchorLine != AnchorLine::Invalid;
+}
+
+AnchorLine::Type AnchorManipulator::beginAnchorLine() const
+{
+ return m_beginAnchorLine;
+}
+
+bool AnchorManipulator::beginAnchorLineIsHorizontal() const
+{
+ return beginAnchorLine() & AnchorLine::HorizontalMask;
+}
+bool AnchorManipulator::beginAnchorLineIsVertical() const
+{
+ return beginAnchorLine() & AnchorLine::HorizontalMask;
+}
+
+FormEditorItem *AnchorManipulator::beginFormEditorItem() const
+{
+ return m_beginFormEditorItem;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/formeditor/anchormanipulator.h b/src/plugins/qmldesigner/components/formeditor/anchormanipulator.h
new file mode 100644
index 0000000000..b44238a4e1
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/anchormanipulator.h
@@ -0,0 +1,71 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef ANCHORMANIPULATOR_H
+#define ANCHORMANIPULATOR_H
+
+#include <qmlanchors.h>
+
+namespace QmlDesigner {
+
+class FormEditorItem;
+class FormEditorView;
+
+class AnchorManipulator
+{
+public:
+ AnchorManipulator(FormEditorView *view);
+ ~AnchorManipulator();
+ void begin(FormEditorItem *beginItem, AnchorLine::Type anchorLine);
+ void addAnchor(FormEditorItem *endItem, AnchorLine::Type anchorLine);
+ void removeAnchor();
+
+ void clear();
+
+ bool isActive() const;
+
+ bool beginAnchorLineIsHorizontal() const;
+ bool beginAnchorLineIsVertical() const;
+
+ AnchorLine::Type beginAnchorLine() const;
+
+ FormEditorItem *beginFormEditorItem() const;
+
+private: // fucntions
+ void setMargin(FormEditorItem *endItem, AnchorLine::Type endAnchorLine);
+
+private: // variables
+ FormEditorItem *m_beginFormEditorItem;
+ AnchorLine::Type m_beginAnchorLine;
+ QWeakPointer<FormEditorView> m_view;
+};
+
+} // namespace QmlDesigner
+
+#endif // ANCHORMANIPULATOR_H
diff --git a/src/plugins/qmldesigner/components/formeditor/anchortool.cpp b/src/plugins/qmldesigner/components/formeditor/anchortool.cpp
new file mode 100644
index 0000000000..524352819d
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/anchortool.cpp
@@ -0,0 +1,226 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "anchortool.h"
+
+#include "formeditorscene.h"
+#include "formeditorview.h"
+#include <qmlitemnode.h>
+#include <qmlanchors.h>
+#include "anchorlinehandleitem.h"
+
+#include <QGraphicsSceneMouseEvent>
+
+#include <QtDebug>
+
+namespace QmlDesigner {
+
+AnchorTool::AnchorTool(FormEditorView* editorView)
+ : AbstractFormEditorTool(editorView),
+ m_anchorLineIndicator(editorView->scene()->manipulatorLayerItem()),
+ m_anchorIndicator(editorView->scene()->manipulatorLayerItem()),
+ m_anchorManipulator(editorView),
+ m_lastAnchorLineHandleItem(0)
+{
+ m_hoverTimeLine.setDuration(200);
+ connect(&m_hoverTimeLine, SIGNAL(finished()), SLOT(checkIfStillHovering()));
+}
+
+AnchorTool::~AnchorTool()
+{
+
+}
+
+void AnchorTool::mousePressEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *)
+{
+ AnchorLineHandleItem *anchorLineHandleItem = topAnchorLineHandleItem(itemList);
+ if (anchorLineHandleItem) {
+ m_anchorManipulator.begin(anchorLineHandleItem->anchorLineController().formEditorItem(),
+ anchorLineHandleItem->anchorLineType());
+ }
+
+ m_anchorLineIndicator.clear();
+
+}
+
+bool areAchorable(FormEditorItem *firstItem, FormEditorItem *secondItem)
+{
+ return firstItem->qmlItemNode().anchors().canAnchor(secondItem->qmlItemNode());
+}
+
+void AnchorTool::mouseMoveEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event)
+{
+ if (m_anchorManipulator.isActive()) {
+ FormEditorItem *targetItem = 0;
+ AnchorLineHandleItem *anchorLineHandleItem = topAnchorLineHandleItem(itemList);
+ if (anchorLineHandleItem && areAchorable(m_anchorManipulator.beginFormEditorItem(), anchorLineHandleItem->anchorLineController().formEditorItem())) {
+ targetItem = anchorLineHandleItem->anchorLineController().formEditorItem();
+ } else {
+ FormEditorItem *topFormEditItem = topFormEditorItemWithRootItem(itemList);
+ if (topFormEditItem && areAchorable(m_anchorManipulator.beginFormEditorItem(), topFormEditItem)) {
+ targetItem = topFormEditItem;
+ } else {
+ m_anchorLineIndicator.hide();
+ m_anchorIndicator.updateTargetPoint(m_anchorManipulator.beginFormEditorItem(), m_anchorManipulator.beginAnchorLine(), event->scenePos());
+ }
+ }
+
+ if (targetItem) {
+ targetItem->qmlItemNode().selectNode();
+ m_anchorLineIndicator.setItem(targetItem);
+ m_anchorLineIndicator.show(m_anchorManipulator.beginFormEditorItem()->qmlItemNode().anchors().possibleAnchorLines(m_anchorManipulator.beginAnchorLine(), targetItem->qmlItemNode()));
+ m_anchorIndicator.updateTargetPoint(m_anchorManipulator.beginFormEditorItem(), m_anchorManipulator.beginAnchorLine(), event->scenePos());
+ targetItem->qmlItemNode().selectNode();
+ }
+ }
+
+}
+
+void AnchorTool::mouseReleaseEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *)
+{
+ if (m_anchorManipulator.isActive()) {
+ AnchorLineHandleItem *anchorLineHandleItem = topAnchorLineHandleItem(itemList);
+ if (anchorLineHandleItem) {
+ m_anchorManipulator.addAnchor(anchorLineHandleItem->anchorLineController().formEditorItem(),
+ anchorLineHandleItem->anchorLineType());
+ } else {
+ m_anchorManipulator.removeAnchor();
+ }
+
+
+ }
+
+ FormEditorItem *topFormEditItem = topFormEditorItem(itemList);
+ if (topFormEditItem)
+ topFormEditItem->qmlItemNode().selectNode();
+
+ m_anchorManipulator.clear();
+ m_anchorLineIndicator.clear();
+}
+
+void AnchorTool::mouseDoubleClickEvent(const QList<QGraphicsItem*> & /*itemList*/,
+ QGraphicsSceneMouseEvent * /*event*/)
+{
+}
+
+void AnchorTool::hoverMoveEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event)
+{
+ m_anchorLineIndicator.clearHighlight();
+ m_anchorIndicator.clearHighlight();
+ m_lastMousePosition = event->scenePos();
+ FormEditorItem *topFormEditItem = 0;
+ AnchorLineHandleItem *anchorLineHandleItem = topAnchorLineHandleItem(itemList);
+
+ if (anchorLineHandleItem) {
+ anchorLineHandleItem->setHiglighted(true);
+ m_anchorIndicator.highlight(anchorLineHandleItem->anchorLineController().formEditorItem(),
+ anchorLineHandleItem->anchorLineType());
+ topFormEditItem = anchorLineHandleItem->anchorLineController().formEditorItem();
+ if (m_hoverTimeLine.state() == QTimeLine::NotRunning) {
+ m_lastAnchorLineHandleItem = anchorLineHandleItem;
+ m_hoverTimeLine.start();
+ }
+ } else {
+ topFormEditItem = topFormEditorItem(itemList);
+ }
+
+ if (topFormEditItem) {
+ m_anchorLineIndicator.setItem(topFormEditItem);
+ m_anchorLineIndicator.show(AnchorLine::AllMask);
+ topFormEditItem->qmlItemNode().selectNode();
+ } else {
+
+ m_anchorLineIndicator.clear();
+ }
+}
+
+void AnchorTool::checkIfStillHovering()
+{
+ AnchorLineHandleItem *anchorLineHandleItem = topAnchorLineHandleItem(scene()->items(m_lastMousePosition));
+
+ if (anchorLineHandleItem && anchorLineHandleItem == m_lastAnchorLineHandleItem) {
+ FormEditorItem *sourceFormEditItem = anchorLineHandleItem->anchorLineController().formEditorItem();
+ QmlAnchors anchors(sourceFormEditItem->qmlItemNode().anchors());
+ if (anchors.instanceHasAnchor(anchorLineHandleItem->anchorLine())) {
+ QmlItemNode targetNode(anchors.instanceAnchor(anchorLineHandleItem->anchorLine()).qmlItemNode());
+ FormEditorItem *targetFormEditorItem = scene()->itemForQmlItemNode(targetNode);
+ targetFormEditorItem->showAttention();
+ }
+ }
+}
+
+void AnchorTool::keyPressEvent(QKeyEvent *)
+{
+}
+
+void AnchorTool::keyReleaseEvent(QKeyEvent *)
+{
+}
+
+void AnchorTool::itemsAboutToRemoved(const QList<FormEditorItem*> &removedItems)
+{
+ QList<FormEditorItem*> newItemList = items().toSet().subtract(removedItems.toSet()).toList();
+ setItems(newItemList);
+ m_anchorIndicator.setItems(newItemList);
+ m_anchorLineIndicator.clear();
+}
+
+void AnchorTool::selectedItemsChanged(const QList<FormEditorItem*> &/*itemList*/)
+{
+ m_anchorIndicator.setItems(view()->scene()->allFormEditorItems());
+ m_anchorIndicator.show();
+}
+
+void AnchorTool::clear()
+{
+ m_anchorLineIndicator.clear();
+ m_anchorIndicator.clear();
+}
+
+void AnchorTool::formEditorItemsChanged(const QList<FormEditorItem*> &)
+{
+ m_anchorLineIndicator.updateItems(view()->scene()->allFormEditorItems());
+ m_anchorIndicator.updateItems(view()->scene()->allFormEditorItems());
+}
+
+AnchorLineHandleItem* AnchorTool::topAnchorLineHandleItem(const QList<QGraphicsItem*> & itemList)
+{
+ foreach (QGraphicsItem *item, itemList) {
+ AnchorLineHandleItem *anchorLineItem = AnchorLineHandleItem::fromGraphicsItem(item);
+ if (anchorLineItem)
+ return anchorLineItem;
+ }
+
+ return 0;
+}
+}
diff --git a/src/plugins/qmldesigner/components/formeditor/anchortool.h b/src/plugins/qmldesigner/components/formeditor/anchortool.h
new file mode 100644
index 0000000000..d11dd1818e
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/anchortool.h
@@ -0,0 +1,88 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef ANCHORTOOL_H
+#define ANCHORTOOL_H
+
+#include <QTimeLine>
+
+#include "abstractformeditortool.h"
+
+#include "anchorlineindicator.h"
+#include "anchorindicator.h"
+#include "anchormanipulator.h"
+
+namespace QmlDesigner {
+
+class AnchorLineHandleItem;
+
+class AnchorTool : public QObject, public AbstractFormEditorTool
+{
+ Q_OBJECT
+public:
+ AnchorTool(FormEditorView* editorView);
+ ~AnchorTool();
+
+ void mousePressEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event);
+ void mouseMoveEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event);
+ void mouseDoubleClickEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event);
+ void hoverMoveEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event);
+ void keyPressEvent(QKeyEvent *event);
+ void keyReleaseEvent(QKeyEvent *keyEvent);
+
+ void itemsAboutToRemoved(const QList<FormEditorItem*> &itemList);
+
+ void selectedItemsChanged(const QList<FormEditorItem*> &itemList);
+
+ void clear();
+
+ void formEditorItemsChanged(const QList<FormEditorItem*> &itemList);
+
+ static AnchorLineHandleItem* topAnchorLineHandleItem(const QList<QGraphicsItem*> & itemList);
+
+private slots:
+ void checkIfStillHovering();
+
+private: //variables
+ AnchorLineIndicator m_anchorLineIndicator;
+ AnchorIndicator m_anchorIndicator;
+ AnchorManipulator m_anchorManipulator;
+ QTimeLine m_hoverTimeLine;
+ QPointF m_lastMousePosition;
+ AnchorLineHandleItem *m_lastAnchorLineHandleItem;
+};
+
+}
+#endif // ANCHORTOOL_H
diff --git a/src/plugins/qmldesigner/components/formeditor/controlelement.cpp b/src/plugins/qmldesigner/components/formeditor/controlelement.cpp
new file mode 100644
index 0000000000..5894fe5c45
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/controlelement.cpp
@@ -0,0 +1,66 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "controlelement.h"
+
+#include <QGraphicsScene>
+#include <QGraphicsRectItem>
+#include <QBrush>
+#include "layeritem.h"
+#include <QtDebug>
+
+
+namespace QmlDesigner {
+
+ControlElement::ControlElement(LayerItem *layerItem)
+ : m_controlShape(new QGraphicsRectItem(layerItem))
+{
+ QPen pen;
+ pen.setStyle(Qt::DashLine);
+ pen.setColor(Qt::blue);
+ m_controlShape->setPen(pen);
+}
+
+ControlElement::~ControlElement()
+{
+ delete m_controlShape;
+}
+
+void ControlElement::hide()
+{
+ m_controlShape->hide();
+}
+
+void ControlElement::setBoundingRect(const QRectF &rect)
+{
+ m_controlShape->show();
+ m_controlShape->setRect(m_controlShape->mapFromScene(rect).boundingRect());
+}
+
+}
diff --git a/src/plugins/qmldesigner/components/formeditor/controlelement.h b/src/plugins/qmldesigner/components/formeditor/controlelement.h
new file mode 100644
index 0000000000..1ec1f3a864
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/controlelement.h
@@ -0,0 +1,57 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef CONTROLELEMENT_H
+#define CONTROLELEMENT_H
+
+
+#include <QGraphicsRectItem>
+
+
+namespace QmlDesigner {
+
+class LayerItem;
+
+class ControlElement
+{
+public:
+ ControlElement(LayerItem *layerItem);
+ ~ControlElement();
+
+ void hide();
+
+ void setBoundingRect(const QRectF &rect);
+
+private:
+ QGraphicsRectItem *m_controlShape;
+};
+
+}
+
+#endif // CONTROLELEMENT_H
diff --git a/src/plugins/qmldesigner/components/formeditor/dragtool.cpp b/src/plugins/qmldesigner/components/formeditor/dragtool.cpp
new file mode 100644
index 0000000000..7878cf86a3
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/dragtool.cpp
@@ -0,0 +1,315 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "dragtool.h"
+
+#include "formeditorscene.h"
+#include "formeditorview.h"
+#include "modelutilities.h"
+#include "itemutilfunctions.h"
+#include <customdraganddrop.h>
+#include <metainfo.h>
+
+#include "resizehandleitem.h"
+
+#include <QApplication>
+#include <QGraphicsSceneMouseEvent>
+#include <QtDebug>
+
+namespace QmlDesigner {
+
+DragTool::DragTool(FormEditorView *editorView)
+ : AbstractFormEditorTool(editorView),
+ m_moveManipulator(editorView->scene()->manipulatorLayerItem(), editorView),
+ m_selectionIndicator(editorView->scene()->manipulatorLayerItem())
+{
+// view()->setCursor(Qt::SizeAllCursor);
+}
+
+
+DragTool::~DragTool()
+{
+
+}
+
+void DragTool::clear()
+{
+ m_moveManipulator.clear();
+ m_selectionIndicator.clear();
+ m_movingItem.clear();
+}
+
+void DragTool::mousePressEvent(const QList<QGraphicsItem*> &,
+ QGraphicsSceneMouseEvent *)
+{
+
+}
+
+void DragTool::mouseMoveEvent(const QList<QGraphicsItem*> &,
+ QGraphicsSceneMouseEvent *)
+{
+
+}
+
+void DragTool::hoverMoveEvent(const QList<QGraphicsItem*> &,
+ QGraphicsSceneMouseEvent * /*event*/)
+{
+
+}
+
+void DragTool::keyPressEvent(QKeyEvent *)
+{
+
+}
+
+void DragTool::keyReleaseEvent(QKeyEvent *)
+{
+
+}
+
+
+void DragTool::mouseReleaseEvent(const QList<QGraphicsItem*> &/*itemList*/,
+ QGraphicsSceneMouseEvent *)
+{
+
+}
+
+void DragTool::mouseDoubleClickEvent(const QList<QGraphicsItem*> & /*itemList*/,
+ QGraphicsSceneMouseEvent * /*event*/)
+{
+
+}
+
+void DragTool::itemsAboutToRemoved(const QList<FormEditorItem*> & /* removedItemList */)
+{
+
+}
+
+void DragTool::selectedItemsChanged(const QList<FormEditorItem*> &)
+{
+
+}
+
+
+
+void DragTool::updateMoveManipulator()
+{
+ if (m_moveManipulator.isActive())
+ return;
+}
+
+void DragTool::beginWithPoint(const QPointF &beginPoint)
+{
+ m_movingItem = scene()->itemForQmlItemNode(m_dragNode);
+
+ m_moveManipulator.setItem(m_movingItem.data());
+ m_moveManipulator.begin(beginPoint);
+
+}
+
+void DragTool::createQmlItemNode(const ItemLibraryInfo &itemLibraryRepresentation, QmlItemNode parentNode, QPointF scenePos)
+{
+ QmlDesignerItemLibraryDragAndDrop::CustomDragAndDrop::hide();
+
+ MetaInfo metaInfo = MetaInfo::global();
+
+ FormEditorItem *parentItem = scene()->itemForQmlItemNode(parentNode);
+ QPointF pos = parentItem->mapFromScene(scenePos);
+
+ m_dragNode = view()->createQmlItemNode(itemLibraryRepresentation, pos, parentNode);
+
+ Q_ASSERT(m_dragNode.modelNode().isValid());
+ Q_ASSERT(m_dragNode.isValid());
+
+ QList<QmlItemNode> nodeList;
+ nodeList.append(m_dragNode);
+ view()->setSelectedQmlItemNodes(nodeList);
+ m_selectionIndicator.setItems(scene()->itemsForQmlItemNodes(nodeList));
+}
+
+void DragTool::createQmlItemNodeFromImage(const QString &imageName, QmlItemNode parentNode, QPointF scenePos)
+{
+ QmlDesignerItemLibraryDragAndDrop::CustomDragAndDrop::hide();
+
+ MetaInfo metaInfo = MetaInfo::global();
+
+ FormEditorItem *parentItem = scene()->itemForQmlItemNode(parentNode);
+ QPointF pos = parentItem->mapFromScene(scenePos);
+
+ m_dragNode = view()->createQmlItemNodeFromImage(imageName, pos, parentNode);
+
+ QList<QmlItemNode> nodeList;
+ nodeList.append(m_dragNode);
+ view()->setSelectedQmlItemNodes(nodeList);
+ m_selectionIndicator.setItems(scene()->itemsForQmlItemNodes(nodeList));
+}
+
+FormEditorItem* DragTool::calculateContainer(const QPointF &point, FormEditorItem * currentItem)
+{
+ QList<QGraphicsItem *> list = scene()->items(point);
+ foreach (QGraphicsItem *item, list) {
+ FormEditorItem *formEditorItem = FormEditorItem::fromQGraphicsItem(item);
+ if (formEditorItem && formEditorItem != currentItem && formEditorItem->isContainer())
+ return formEditorItem;
+ }
+ return 0;
+}
+
+
+void DragTool::formEditorItemsChanged(const QList<FormEditorItem*> & itemList)
+{
+ if (m_movingItem && itemList.contains(m_movingItem.data())) {
+ QList<FormEditorItem*> updateItemList;
+ updateItemList.append(m_movingItem.data());
+ m_selectionIndicator.updateItems(updateItemList);
+ }
+}
+
+
+void DragTool::dropEvent(QGraphicsSceneDragDropEvent * event)
+{
+ if (event->mimeData()->hasFormat("application/vnd.bauhaus.itemlibraryinfo") ||
+ event->mimeData()->hasFormat("application/vnd.bauhaus.libraryresource")) {
+ event->accept();
+ end(event->scenePos());
+ //Q_ASSERT(m_token.isValid());
+ m_rewriterTransaction.commit();
+ m_dragNode = ModelNode();
+ view()->changeToSelectionTool();
+ }
+}
+
+void DragTool::dragEnterEvent(QGraphicsSceneDragDropEvent * event)
+{
+ if (event->mimeData()->hasFormat("application/vnd.bauhaus.itemlibraryinfo") ||
+ event->mimeData()->hasFormat("application/vnd.bauhaus.libraryresource")) {
+ if (!m_rewriterTransaction.isValid()) {
+ m_rewriterTransaction = view()->beginRewriterTransaction();
+ }
+ }
+}
+
+void DragTool::dragLeaveEvent(QGraphicsSceneDragDropEvent * event)
+{
+ if (event->mimeData()->hasFormat("application/vnd.bauhaus.itemlibraryinfo") ||
+ event->mimeData()->hasFormat("application/vnd.bauhaus.libraryresource")) {
+ event->accept();
+ if (m_dragNode.isValid())
+ m_dragNode.destroy();
+ end(event->scenePos());
+ m_rewriterTransaction.commit();
+ QmlDesignerItemLibraryDragAndDrop::CustomDragAndDrop::show();
+ QList<QmlItemNode> nodeList;
+ view()->setSelectedQmlItemNodes(nodeList);
+ view()->changeToSelectionTool();
+ }
+}
+
+static ItemLibraryInfo ItemLibraryInfoFromData(const QByteArray &data)
+{
+ QDataStream stream(data);
+
+ ItemLibraryInfo itemLibraryInfo;
+ stream >> itemLibraryInfo;
+
+ return itemLibraryInfo;
+}
+
+void DragTool::dragMoveEvent(QGraphicsSceneDragDropEvent * event)
+{
+ if (event->mimeData()->hasFormat("application/vnd.bauhaus.itemlibraryinfo") ||
+ event->mimeData()->hasFormat("application/vnd.bauhaus.libraryresource")) {
+ event->accept();
+ QPointF scenePos = event->scenePos();
+ if (m_dragNode.isValid()) {
+
+ FormEditorItem *parentItem = calculateContainer(event->scenePos() - QPoint(2, 2));
+ if (!parentItem) { //if there is no parent any more - the use left the scene
+ end(event->scenePos());
+ m_dragNode.destroy(); //delete the node then
+ QmlDesignerItemLibraryDragAndDrop::CustomDragAndDrop::show();
+ return;
+ }
+ //move
+ move(event->scenePos());
+ } else {
+ //create new node if container
+
+ FormEditorItem *parentItem = calculateContainer(event->scenePos());
+ if (!parentItem)
+ return;
+ QmlItemNode parentNode; //get possible container parentNode
+ if (parentItem)
+ parentNode = parentItem->qmlItemNode();
+
+ if (event->mimeData()->hasFormat("application/vnd.bauhaus.itemlibraryinfo")) {
+ Q_ASSERT(!event->mimeData()->data("application/vnd.bauhaus.itemlibraryinfo").isEmpty());
+ ItemLibraryInfo ItemLibraryInfo = ItemLibraryInfoFromData(event->mimeData()->data("application/vnd.bauhaus.itemlibraryinfo"));
+ createQmlItemNode(ItemLibraryInfo, parentNode, event->scenePos());
+ } else if (event->mimeData()->hasFormat("application/vnd.bauhaus.libraryresource")) {
+ Q_ASSERT(!event->mimeData()->data("application/vnd.bauhaus.libraryresource").isEmpty());
+ QString imageName = QString::fromLatin1((event->mimeData()->data("application/vnd.bauhaus.libraryresource")));
+ createQmlItemNodeFromImage(imageName, parentNode, event->scenePos());
+ } else Q_ASSERT(false);
+ beginWithPoint(event->scenePos());
+ }
+ }
+ if (event->mimeData()->hasFormat("application/vnd.bauhaus.libraryresource")) {
+ }
+}
+
+void DragTool::end(QPointF scenePos)
+{
+ m_moveManipulator.end(scenePos);
+ clear();
+}
+
+void DragTool::move(QPointF scenePos)
+{
+ if (!m_movingItem)
+ return;
+
+ FormEditorItem *containerItem = calculateContainer(scenePos - QPoint(2, 2), m_movingItem.data());
+ if (containerItem &&
+ containerItem != m_movingItem->parentItem() &&
+ view()->currentState().isBaseState()) {
+
+ m_moveManipulator.reparentTo(containerItem);
+ }
+
+ //MoveManipulator::Snapping useSnapping = MoveManipulator::NoSnapping;
+ MoveManipulator::Snapping useSnapping = MoveManipulator::UseSnapping;
+ /* if (event->modifiers().testFlag(Qt::ControlModifier) != view()->isSnapButtonChecked())
+ useSnapping = MoveManipulator::UseSnapping;*/
+
+ m_moveManipulator.update(scenePos, useSnapping);
+}
+
+
+}
diff --git a/src/plugins/qmldesigner/components/formeditor/dragtool.h b/src/plugins/qmldesigner/components/formeditor/dragtool.h
new file mode 100644
index 0000000000..97f676482b
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/dragtool.h
@@ -0,0 +1,105 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef DRAGTOOL_H
+#define DRAGTOOL_H
+
+#include "abstractformeditortool.h"
+#include "movemanipulator.h"
+#include "selectionindicator.h"
+#include "resizeindicator.h"
+
+#include <QHash>
+
+
+namespace QmlDesigner {
+
+
+class DragTool : public AbstractFormEditorTool
+{
+public:
+ DragTool(FormEditorView* editorView);
+ ~DragTool();
+
+ void mousePressEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event);
+ void mouseMoveEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event);
+ void mouseDoubleClickEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event);
+ void hoverMoveEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event);
+
+ void keyPressEvent(QKeyEvent *event);
+ void keyReleaseEvent(QKeyEvent *keyEvent);
+
+ void itemsAboutToRemoved(const QList<FormEditorItem*> &itemList);
+
+ void selectedItemsChanged(const QList<FormEditorItem*> &itemList);
+
+ void updateMoveManipulator();
+
+ void beginWithPoint(const QPointF &beginPoint);
+
+
+ virtual void dropEvent(QGraphicsSceneDragDropEvent * event);
+ virtual void dragEnterEvent(QGraphicsSceneDragDropEvent * event);
+ virtual void dragLeaveEvent(QGraphicsSceneDragDropEvent * event);
+ virtual void dragMoveEvent(QGraphicsSceneDragDropEvent * event);
+
+ //void beginWithPoint(const QPointF &beginPoint);
+
+ void clear();
+
+ void formEditorItemsChanged(const QList<FormEditorItem*> &itemList);
+
+protected:
+
+
+private:
+
+ void createQmlItemNode(const ItemLibraryInfo &ItemLibraryRepresentation, QmlItemNode parentNode, QPointF scenePos);
+ void createQmlItemNodeFromImage(const QString &imageName, QmlItemNode parentNode, QPointF scenePos);
+ FormEditorItem* calculateContainer(const QPointF &point, FormEditorItem * currentItem = 0);
+
+ void begin(QPointF scenePos);
+ void end(QPointF scenePos);
+ void move(QPointF scenePos);
+
+ MoveManipulator m_moveManipulator;
+ SelectionIndicator m_selectionIndicator;
+ QWeakPointer<FormEditorItem> m_movingItem;
+ RewriterTransaction m_rewriterTransaction;
+ QmlItemNode m_dragNode;
+};
+
+}
+#endif // DRAGTOOL_H
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditor.pri b/src/plugins/qmldesigner/components/formeditor/formeditor.pri
new file mode 100644
index 0000000000..1c3bd78988
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/formeditor.pri
@@ -0,0 +1,84 @@
+VPATH += $$PWD
+QT += opengl
+INCLUDEPATH += $$PWD
+INCLUDEPATH += $$PWD/../navigator
+DEPENDPATH += $$PWD
+SOURCES += formeditoritem.cpp \
+ formeditorview.cpp \
+ formeditorscene.cpp \
+ formeditorwidget.cpp \
+ selectiontool.cpp \
+ abstractformeditortool.cpp \
+ controlelement.cpp \
+ resizemanipulator.cpp \
+ movemanipulator.cpp \
+ layeritem.cpp \
+ itemutilfunctions.cpp \
+ selectionrectangle.cpp \
+ rubberbandselectionmanipulator.cpp \
+ movetool.cpp \
+ selectionindicator.cpp \
+ snappinglinecreator.cpp \
+ snapper.cpp \
+ onedimensionalcluster.cpp \
+ singleselectionmanipulator.cpp \
+ scalemanipulator.cpp \
+ resizetool.cpp \
+ resizeindicator.cpp \
+ scaleitem.cpp \
+ resizecontroller.cpp \
+ resizehandleitem.cpp \
+ anchortool.cpp \
+ anchorlineindicator.cpp \
+ anchorlinecontroller.cpp \
+ anchorlinehandleitem.cpp \
+ anchormanipulator.cpp \
+ anchorindicator.cpp \
+ anchorcontroller.cpp \
+ anchorhandleitem.cpp \
+ dragtool.cpp \
+ itemcreatortool.cpp \
+ toolbox.cpp \
+ zoomaction.cpp \
+ formeditorgraphicsview.cpp \
+ numberseriesaction.cpp
+HEADERS += formeditorscene.h \
+ formeditorwidget.h \
+ formeditoritem.h \
+ formeditorview.h \
+ selectiontool.h \
+ abstractformeditortool.h \
+ controlelement.h \
+ resizemanipulator.h \
+ movemanipulator.h \
+ layeritem.h \
+ itemutilfunctions.h \
+ selectionrectangle.h \
+ rubberbandselectionmanipulator.h \
+ movetool.h \
+ selectionindicator.h \
+ snappinglinecreator.h \
+ snapper.h \
+ onedimensionalcluster.h \
+ singleselectionmanipulator.h \
+ scalemanipulator.h \
+ resizetool.h \
+ resizeindicator.h \
+ scaleitem.h \
+ resizecontroller.h \
+ resizehandleitem.h \
+ anchortool.h \
+ anchorlineindicator.h \
+ anchorlinecontroller.h \
+ anchorlinehandleitem.h \
+ anchormanipulator.h \
+ anchorindicator.h \
+ anchorcontroller.h \
+ anchorhandleitem.h \
+ dragtool.h \
+ itemcreatortool.cpp \
+ toolbox.h \
+ zoomaction.h \
+ formeditorgraphicsview.h \
+ numberseriesaction.h
+RESOURCES += formeditor.qrc
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditor.qrc b/src/plugins/qmldesigner/components/formeditor/formeditor.qrc
new file mode 100644
index 0000000000..14e0dbd0fb
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/formeditor.qrc
@@ -0,0 +1,12 @@
+<RCC>
+ <qresource prefix="/icon/handle">
+ <file>resize_handle.png</file>
+ </qresource>
+ <qresource prefix="/icon/tool">
+ <file>anchor.png</file>
+ <file>transform.png</file>
+ </qresource>
+ <qresource prefix="/icon/layout">
+ <file>snapping.png</file>
+ </qresource>
+</RCC>
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.cpp
new file mode 100644
index 0000000000..fb2e905eda
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.cpp
@@ -0,0 +1,88 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "formeditorgraphicsview.h"
+
+#include <QWheelEvent>
+
+namespace QmlDesigner {
+
+FormEditorGraphicsView::FormEditorGraphicsView(QWidget *parent) :
+ QGraphicsView(parent)
+{
+ setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
+ setResizeAnchor(QGraphicsView::AnchorViewCenter);
+// setCacheMode(QGraphicsView::CacheNone);
+ setCacheMode(QGraphicsView::CacheBackground);
+ setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
+// setViewportUpdateMode(QGraphicsView::NoViewportUpdate);
+ setRenderHint(QPainter::Antialiasing, false);
+
+ setFrameShape(QFrame::NoFrame);
+
+ setAutoFillBackground(true);
+ setBackgroundRole(QPalette::Window);
+
+ const int checkerbordSize= 20;
+ QPixmap tilePixmap(checkerbordSize * 2, checkerbordSize * 2);
+ tilePixmap.fill(Qt::white);
+ QPainter tilePainter(&tilePixmap);
+ QColor color(220, 220, 220);
+ tilePainter.fillRect(0, 0, checkerbordSize, checkerbordSize, color);
+ tilePainter.fillRect(checkerbordSize, checkerbordSize, checkerbordSize, checkerbordSize, color);
+ tilePainter.end();
+
+ setBackgroundBrush(tilePixmap);
+
+ viewport()->setMouseTracking(true);
+}
+
+void FormEditorGraphicsView::wheelEvent(QWheelEvent *event)
+{
+ if (event->modifiers().testFlag(Qt::ControlModifier)) {
+ event->ignore();
+ } else {
+ QGraphicsView::wheelEvent(event);
+ }
+
+}
+
+void FormEditorGraphicsView::drawBackground(QPainter *painter, const QRectF &rect)
+{
+ painter->save();
+ painter->setBrushOrigin(0, 0);
+ painter->fillRect(rect.intersected(sceneRect()), backgroundBrush());
+ // paint rect around editable area
+ painter->setPen(Qt::darkGray);
+ QRectF frameRect = sceneRect().adjusted(-1, -1, 0, 0);
+ painter->drawRect(frameRect);
+ painter->restore();
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.h b/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.h
new file mode 100644
index 0000000000..2e79f656a4
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.h
@@ -0,0 +1,51 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef FORMEDITORGRAPHICSVIEW_H
+#define FORMEDITORGRAPHICSVIEW_H
+
+#include <QGraphicsView>
+
+namespace QmlDesigner {
+
+class FormEditorGraphicsView : public QGraphicsView
+{
+Q_OBJECT
+public:
+ explicit FormEditorGraphicsView(QWidget *parent = 0);
+
+
+protected:
+ void drawBackground(QPainter *painter, const QRectF &rect);
+ void wheelEvent(QWheelEvent *event);
+};
+
+} // namespace QmlDesigner
+
+#endif // FORMEDITORGRAPHICSVIEW_H
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp b/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp
new file mode 100644
index 0000000000..91652fc37c
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp
@@ -0,0 +1,323 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "formeditoritem.h"
+#include "formeditorscene.h"
+#include "formeditornodeinstanceview.h"
+#include "selectiontool.h"
+
+#include <modelnode.h>
+#include <nodemetainfo.h>
+#include <widgetqueryview.h>
+
+#include <QGraphicsSceneMouseEvent>
+#include <QDebug>
+#include <QPainter>
+#include <QStyleOptionGraphicsItem>
+#include <QGraphicsView>
+#include <QTimeLine>
+
+#include <cmath>
+
+#include <invalidmodelnodeexception.h>
+#include <invalidnodestateexception.h>
+
+namespace QmlDesigner {
+
+
+
+FormEditorScene *FormEditorItem::scene() const {
+ return qobject_cast<FormEditorScene*>(QGraphicsItem::scene());
+}
+
+FormEditorItem::FormEditorItem(const QmlItemNode &qmlItemNode, FormEditorScene* scene)
+ : QGraphicsObject(scene->formLayerItem()),
+ m_snappingLineCreator(this),
+ m_qmlItemNode(qmlItemNode),
+ m_borderWidth(1.0),
+ m_opacity(0.6)
+{
+ setCacheMode(QGraphicsItem::ItemCoordinateCache);
+ setup();
+}
+
+void FormEditorItem::setup()
+{
+ if (qmlItemNode().hasInstanceParent())
+ setParentItem(scene()->itemForQmlItemNode(qmlItemNode().instanceParent().toQmlItemNode()));
+
+ if (QGraphicsItem::parentItem() == scene()->formLayerItem())
+ m_borderWidth = 0.0;
+
+ setFlag(QGraphicsItem::ItemIsMovable, true);
+ updateGeometry();
+ updateVisibilty();
+}
+
+QRectF FormEditorItem::boundingRect() const
+{
+ return m_boundingRect;
+}
+
+void FormEditorItem::updateGeometry()
+{
+ prepareGeometryChange();
+ m_boundingRect = qmlItemNode().instanceBoundingRect();
+ setTransform(qmlItemNode().instanceTransform());
+ setTransform(m_attentionTransform, true);
+ //the property for zValue is called z in QGraphicsObject
+ Q_ASSERT(qmlItemNode().instanceValue("z").isValid());
+ setZValue(qmlItemNode().instanceValue("z").toDouble());
+}
+
+void FormEditorItem::updateVisibilty()
+{
+// setVisible(nodeInstance().isVisible());
+// setOpacity(nodeInstance().opacity());
+}
+
+void FormEditorItem::showAttention()
+{
+ if (m_attentionTimeLine.isNull()) {
+ m_attentionTimeLine = new QTimeLine(500, this);
+ m_attentionTimeLine->setCurveShape(QTimeLine::SineCurve);
+ connect(m_attentionTimeLine.data(), SIGNAL(valueChanged(qreal)), SLOT(changeAttention(qreal)));
+ connect(m_attentionTimeLine.data(), SIGNAL(finished()), m_attentionTimeLine.data(), SLOT(deleteLater()));
+
+ m_attentionTimeLine->start();
+ }
+}
+
+void FormEditorItem::changeAttention(qreal value)
+{
+ if (QGraphicsItem::parentItem() == scene()->formLayerItem()) {
+ setAttentionHighlight(value);
+ } else {
+ setAttentionHighlight(value);
+ setAttentionScale(value);
+ }
+}
+
+FormEditorView *FormEditorItem::formEditorView() const
+{
+ return scene()->editorView();
+}
+
+void FormEditorItem::setAttentionScale(double sinusScale)
+{
+ if (!qFuzzyIsNull(sinusScale)) {
+ double scale = std::sqrt(sinusScale);
+ m_attentionTransform.reset();
+ QPointF centerPoint(qmlItemNode().instanceBoundingRect().center());
+ m_attentionTransform.translate(centerPoint.x(), centerPoint.y());
+ m_attentionTransform.scale(scale * 0.15 + 1.0, scale * 0.15 + 1.0);
+ m_attentionTransform.translate(-centerPoint.x(), -centerPoint.y());
+ m_inverseAttentionTransform = m_attentionTransform.inverted();
+ prepareGeometryChange();
+ setTransform(qmlItemNode().instanceTransform());
+ setTransform(m_attentionTransform, true);
+ } else {
+ m_attentionTransform.reset();
+ prepareGeometryChange();
+ setTransform(qmlItemNode().instanceTransform());
+ }
+}
+
+void FormEditorItem::setAttentionHighlight(double value)
+{
+ m_opacity = 0.6 + value;
+ if (QGraphicsItem::parentItem() == scene()->formLayerItem())
+ m_borderWidth = value * 4;
+ else
+ m_borderWidth = 1. + value * 3;
+
+ update();
+}
+
+FormEditorItem::~FormEditorItem()
+{
+ scene()->removeItemFromHash(this);
+}
+
+/* \brief returns the parent item skipping all proxyItem*/
+FormEditorItem *FormEditorItem::parentItem() const
+{
+ return qgraphicsitem_cast<FormEditorItem*> (QGraphicsItem::parentItem());
+}
+
+FormEditorItem* FormEditorItem::fromQGraphicsItem(QGraphicsItem *graphicsItem)
+{
+ return qgraphicsitem_cast<FormEditorItem*>(graphicsItem);
+}
+
+static QRectF alignedRect(const QRectF &rect)
+{
+ QRectF alignedRect(rect);
+ alignedRect.setTop(std::floor(rect.top()) + 0.5);
+ alignedRect.setBottom(std::floor(rect.bottom()) + 0.5);
+ alignedRect.setLeft(std::floor(rect.left()) + 0.5);
+ alignedRect.setRight(std::floor(rect.right()) + 0.5);
+
+ return alignedRect;
+}
+
+void FormEditorItem::paintBoundingRect(QPainter *painter) const
+{
+ if (QGraphicsItem::parentItem() == scene()->formLayerItem() && qFuzzyIsNull(m_borderWidth))
+ return;
+
+ QPen pen;
+ pen.setJoinStyle(Qt::MiterJoin);
+
+ switch(scene()->paintMode()) {
+ case FormEditorScene::AnchorMode: {
+ pen.setColor(Qt::black);
+ pen.setWidth(m_borderWidth);
+ }
+ break;
+ case FormEditorScene::NormalMode: {
+ pen.setColor(Qt::gray);
+ }
+ break;
+ }
+
+ painter->setPen(pen);
+ int offset = m_borderWidth / 2;
+ painter->drawRect(alignedRect(boundingRect().adjusted(offset, offset, -offset, -offset)));
+}
+
+void FormEditorItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+{
+ painter->save();
+ painter->setRenderHint(QPainter::Antialiasing, true);
+ switch(scene()->paintMode()) {
+ case FormEditorScene::AnchorMode:
+ painter->setOpacity(m_opacity);
+ break;
+ case FormEditorScene::NormalMode:
+ painter->setOpacity(qmlItemNode().instanceValue("opacity").toDouble());
+ break;
+ }
+
+ qmlItemNode().paintInstance(painter);
+
+ painter->setRenderHint(QPainter::Antialiasing, false);
+ paintBoundingRect(painter);
+
+ painter->restore();
+}
+
+AbstractFormEditorTool* FormEditorItem::tool() const
+{
+ return static_cast<FormEditorScene*>(scene())->currentTool();
+}
+
+SnapLineMap FormEditorItem::topSnappingLines() const
+{
+ return m_snappingLineCreator.topLines();
+}
+
+SnapLineMap FormEditorItem::bottomSnappingLines() const
+{
+ return m_snappingLineCreator.bottomLines();
+}
+
+SnapLineMap FormEditorItem::leftSnappingLines() const
+{
+ return m_snappingLineCreator.leftLines();
+}
+
+SnapLineMap FormEditorItem::rightSnappingLines() const
+{
+ return m_snappingLineCreator.rightLines();
+}
+
+SnapLineMap FormEditorItem::horizontalCenterSnappingLines() const
+{
+ return m_snappingLineCreator.horizontalCenterLines();
+}
+
+SnapLineMap FormEditorItem::verticalCenterSnappingLines() const
+{
+ return m_snappingLineCreator.verticalCenterLines();
+}
+
+SnapLineMap FormEditorItem::topSnappingOffsets() const
+{
+ return m_snappingLineCreator.topOffsets();
+}
+
+SnapLineMap FormEditorItem::bottomSnappingOffsets() const
+{
+ return m_snappingLineCreator.bottomOffsets();
+}
+
+SnapLineMap FormEditorItem::leftSnappingOffsets() const
+{
+ return m_snappingLineCreator.leftOffsets();
+}
+
+SnapLineMap FormEditorItem::rightSnappingOffsets() const
+{
+ return m_snappingLineCreator.rightOffsets();
+}
+
+
+void FormEditorItem::updateSnappingLines(const QList<FormEditorItem*> &exceptionList,
+ FormEditorItem *transformationSpaceItem)
+{
+ m_snappingLineCreator.update(exceptionList, transformationSpaceItem);
+}
+
+
+QList<FormEditorItem*> FormEditorItem::childFormEditorItems() const
+{
+ QList<FormEditorItem*> formEditorItemList;
+
+ foreach (QGraphicsItem *item, childItems()) {
+ FormEditorItem *formEditorItem = fromQGraphicsItem(item);
+ if (formEditorItem)
+ formEditorItemList.append(formEditorItem);
+ }
+
+ return formEditorItemList;
+}
+
+bool FormEditorItem::isContainer() const
+{
+ return qmlItemNode().modelNode().metaInfo().isContainer();
+}
+
+QmlItemNode FormEditorItem::qmlItemNode() const
+{
+ return m_qmlItemNode;
+}
+
+}
+
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditoritem.h b/src/plugins/qmldesigner/components/formeditor/formeditoritem.h
new file mode 100644
index 0000000000..b5ffc76992
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/formeditoritem.h
@@ -0,0 +1,131 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef FORMEDITORITEM_H
+#define FORMEDITORITEM_H
+
+#include <QWeakPointer>
+#include <QGraphicsWidget>
+#include <qmlitemnode.h>
+#include "snappinglinecreator.h"
+
+class QTimeLine;
+
+namespace QmlDesigner {
+
+class FormEditorScene;
+class FormEditorView;
+class AbstractFormEditorTool;
+
+namespace Internal {
+ class GraphicItemResizer;
+ class MoveController;
+}
+
+class FormEditorItem : public QGraphicsObject
+{
+ Q_OBJECT
+
+ friend class QmlDesigner::FormEditorScene;
+public:
+ ~FormEditorItem();
+
+ void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0 );
+
+ bool isContainer() const;
+ QmlItemNode qmlItemNode() const;
+
+
+ enum { Type = UserType + 0xfffa };
+
+ int type() const;
+
+ static FormEditorItem* fromQGraphicsItem(QGraphicsItem *graphicsItem);
+
+ void updateSnappingLines(const QList<FormEditorItem*> &exceptionList,
+ FormEditorItem *transformationSpaceItem);
+
+ SnapLineMap topSnappingLines() const;
+ SnapLineMap bottomSnappingLines() const;
+ SnapLineMap leftSnappingLines() const;
+ SnapLineMap rightSnappingLines() const;
+ SnapLineMap horizontalCenterSnappingLines() const;
+ SnapLineMap verticalCenterSnappingLines() const;
+
+ SnapLineMap topSnappingOffsets() const;
+ SnapLineMap bottomSnappingOffsets() const;
+ SnapLineMap leftSnappingOffsets() const;
+ SnapLineMap rightSnappingOffsets() const;
+
+ QList<FormEditorItem*> childFormEditorItems() const;
+ FormEditorScene *scene() const;
+ FormEditorItem *parentItem() const;
+
+ QRectF boundingRect() const;
+
+ void updateGeometry();
+ void updateVisibilty();
+
+ void showAttention();
+
+ FormEditorView *formEditorView() const;
+
+protected:
+ AbstractFormEditorTool* tool() const;
+ void paintBoundingRect(QPainter *painter) const;
+
+private slots:
+ void changeAttention(qreal value);
+
+private: // functions
+ FormEditorItem(const QmlItemNode &qmlItemNode, FormEditorScene* scene);
+ void setup();
+ void setAttentionScale(double scale);
+ void setAttentionHighlight(double value);
+
+private: // variables
+ SnappingLineCreator m_snappingLineCreator;
+ QmlItemNode m_qmlItemNode;
+ QWeakPointer<QTimeLine> m_attentionTimeLine;
+ QTransform m_attentionTransform; // make item larger in anchor mode
+ QTransform m_inverseAttentionTransform;
+ QRectF m_boundingRect;
+ double m_borderWidth;
+ double m_opacity;
+};
+
+
+inline int FormEditorItem::type() const
+{
+ return UserType + 0xfffa;
+}
+
+}
+
+#endif // FORMEDITORITEM_H
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditormainview.cpp b/src/plugins/qmldesigner/components/formeditor/formeditormainview.cpp
new file mode 100644
index 0000000000..d1da63fafc
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/formeditormainview.cpp
@@ -0,0 +1,401 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "formeditormainview.h"
+
+#include "formeditorview.h"
+#include "formeditorwidget.h"
+#include <QPixmapCache>
+#include <QtDebug>
+
+#include "zoomaction.h"
+
+namespace QmlDesigner {
+
+
+FormEditorMainView::FormEditorMainView()
+ : m_formMainEditorWidget(new FormEditorMainWidget(this))
+{
+ QPixmapCache::setCacheLimit(1024 * 100);
+}
+
+FormEditorMainView::~FormEditorMainView()
+{
+ resetViews();
+
+ if (m_formMainEditorWidget)
+ m_formMainEditorWidget->deleteLater();
+}
+
+void FormEditorMainView::modelAttached(Model *model)
+{
+ AbstractView::modelAttached(model);
+
+ setupSubViews();
+
+ foreach(const QWeakPointer<FormEditorView> &view, m_formEditorViewList) {
+ if (view)
+ view->modelAttached(model);
+ }
+
+ m_formMainEditorWidget->setModel(model);
+}
+
+void FormEditorMainView::createSubView(const QmlModelState &state)
+{
+ FormEditorView *subView = new FormEditorView(this);
+ subView->setCurrentState(state);
+ m_formEditorViewList.append(subView);
+
+ m_formMainEditorWidget->addWidget(subView->widget());
+ m_subWindowMap.insert(state, subView->widget());
+
+ subView->setZoomLevel(zoomAction()->zoomLevel());
+ connect(zoomAction(), SIGNAL(zoomLevelChanged(double)), subView, SLOT(setZoomLevel(double)));
+}
+
+void FormEditorMainView::removeSubView(const ModelState &state)
+{
+ QWidget *subWindow = m_subWindowMap.take(state).data();
+ Q_ASSERT(subWindow);
+ if (subWindow == m_formMainEditorWidget->currentWidget())
+ setCurrentState();
+ delete subWindow;
+
+ FormEditorView *editorView = 0;
+ foreach(const QWeakPointer<FormEditorView> &view, m_formEditorViewList) {
+ if (view->modelState() == state) {
+ editorView = view.data();
+ break;
+ }
+ }
+ Q_ASSERT(editorView);
+ m_formEditorViewList.removeOne(editorView);
+ delete editorView;
+}
+
+static bool modelStateLessThan(const ModelState &firstState, const ModelState &secondState)
+ {
+ if (firstState.isBaseState())
+ return false;
+
+ return firstState.name().toLower() > secondState.name().toLower();
+ }
+
+void FormEditorMainView::setupSubViews()
+{
+ foreach(const QWeakPointer<FormEditorView> &view, m_formEditorViewList)
+ delete view.data();
+ m_formEditorViewList.clear();
+
+ foreach(const QWeakPointer<QWidget> &view, m_subWindowMap.values())
+ delete view.data();
+ m_subWindowMap.clear();
+
+ QList<ModelState> invertedStates(model()->modelStates());
+ qSort(invertedStates.begin(), invertedStates.end(), modelStateLessThan);
+ foreach(const ModelState &state, invertedStates)
+ createSubView(state);
+}
+
+void FormEditorMainView::resetViews()
+{
+ m_subWindowMap.clear();
+ foreach(const QWeakPointer<FormEditorView> &view, m_formEditorViewList)
+ delete view.data();
+ m_formEditorViewList.clear();
+}
+
+void FormEditorMainView::nodeCreated(const ModelNode &createdNode)
+{
+ foreach(const QWeakPointer<FormEditorView> &view, m_formEditorViewList) {
+ if (view)
+ view->nodeCreated(createdNode);
+ }
+}
+
+void FormEditorMainView::modelAboutToBeDetached(Model *model)
+{
+ foreach(const QWeakPointer<FormEditorView> &view, m_formEditorViewList) {
+ if (view)
+ view->modelAboutToBeDetached(model);
+ }
+
+ resetViews();
+
+ m_formMainEditorWidget->setModel(0);
+
+ AbstractView::modelAboutToBeDetached(model);
+}
+
+void FormEditorMainView::nodeAboutToBeRemoved(const ModelNode &removedNode)
+{
+ foreach(const QWeakPointer<FormEditorView> &view, m_formEditorViewList) {
+ if (view)
+ view->nodeAboutToBeRemoved(removedNode);
+ }
+}
+
+void FormEditorMainView::propertiesAdded(const NodeState &state, const QList<NodeProperty>& propertyList)
+{
+ foreach(const QWeakPointer<FormEditorView> &view, m_formEditorViewList) {
+ if (view)
+ view->propertiesAdded(state, propertyList);
+ }
+}
+
+void FormEditorMainView::propertiesAboutToBeRemoved(const NodeState &state, const QList<NodeProperty>& propertyList)
+{
+ foreach(const QWeakPointer<FormEditorView> &view, m_formEditorViewList) {
+ if (view)
+ view->propertiesAboutToBeRemoved(state, propertyList);
+ }
+}
+
+void FormEditorMainView::propertyValuesChanged(const NodeState &state, const QList<NodeProperty>& propertyList)
+{
+ foreach(const QWeakPointer<FormEditorView> &view, m_formEditorViewList) {
+ if (view)
+ view->propertyValuesChanged(state, propertyList);
+ }
+}
+
+void FormEditorMainView::nodeIdChanged(const ModelNode& node, const QString& newId, const QString& oldId)
+{
+ foreach(const QWeakPointer<FormEditorView> &view, m_formEditorViewList) {
+ if (view)
+ view->nodeIdChanged(node, newId, oldId);
+ }
+}
+
+void FormEditorMainView::nodeReparented(const ModelNode &node, const ModelNode &oldParent, const ModelNode &newParent)
+{
+ foreach(const QWeakPointer<FormEditorView> &view, m_formEditorViewList) {
+ if (view)
+ view->nodeReparented(node, oldParent, newParent);
+ }
+}
+
+FormEditorMainWidget *FormEditorMainView::widget() const
+{
+ return m_formMainEditorWidget.data();
+}
+
+NodeInstanceView *FormEditorMainView::nodeInstanceView(const ModelState &modelState) const
+{
+ foreach (const QWeakPointer<FormEditorView> &view, m_formEditorViewList) {
+ if (view->modelState() == modelState)
+ return view->nodeInstanceView();
+ }
+
+ return 0;
+}
+
+void FormEditorMainView::selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
+ const QList<ModelNode> &lastSelectedNodeList)
+{
+ foreach(const QWeakPointer<FormEditorView> &view, m_formEditorViewList) {
+ if (view)
+ view->selectedNodesChanged(selectedNodeList, lastSelectedNodeList);
+ }
+}
+
+void FormEditorMainView::modelStateAboutToBeRemoved(const ModelState &modelState)
+{
+ foreach(const QWeakPointer<FormEditorView> &view, m_formEditorViewList) {
+ if (view)
+ view->modelStateAboutToBeRemoved(modelState);
+ }
+
+ removeSubView(modelState);
+}
+
+void FormEditorMainView::modelStateAdded(const ModelState &modelState)
+{
+ createSubView(modelState);
+ m_formEditorViewList.last()->modelAttached(model());
+
+ foreach(const QWeakPointer<FormEditorView> &view, m_formEditorViewList) {
+ if (view)
+ view->modelStateAdded(modelState);
+ }
+}
+
+void FormEditorMainView::nodeStatesAboutToBeRemoved(const QList<NodeState> &nodeStateList)
+{
+ foreach(const QWeakPointer<FormEditorView> &view, m_formEditorViewList) {
+ if (view)
+ view->nodeStatesAboutToBeRemoved(nodeStateList);
+ }
+}
+
+void FormEditorMainView::nodeStatesAdded(const QList<NodeState> &nodeStateList)
+{
+ foreach(const QWeakPointer<FormEditorView> &view, m_formEditorViewList) {
+ if (view)
+ view->nodeStatesAdded(nodeStateList);
+ }
+}
+
+void FormEditorMainView::setCurrentState(const QmlModelState &state)
+{
+ Q_ASSERT(m_subWindowMap.contains(state));
+ m_formMainEditorWidget->setCurrentWidget(m_subWindowMap.value(state).data());
+ emit stateChanged(state);
+}
+
+ModelState FormEditorMainView::currentState() const
+{
+ QWidget *currentWidget = m_formMainEditorWidget->currentWidget();
+ QMapIterator<ModelState, QWeakPointer<QWidget> > iter(m_subWindowMap);
+ while (iter.hasNext()) {
+ iter.next();
+ if (iter.value().data() == currentWidget) {
+ return iter.key();
+ }
+ }
+ Q_ASSERT_X(0, Q_FUNC_INFO, "cannot find current state");
+ return ModelState();
+}
+
+FormEditorMainView::EditorTool FormEditorMainView::currentTool() const
+{
+ return m_currentTool;
+}
+
+void FormEditorMainView::setCurrentTool(FormEditorMainView::EditorTool tool)
+{
+ if (m_currentTool == tool)
+ return;
+ m_currentTool = tool;
+ switch (tool) {
+ case MoveTool: {
+ foreach(const QWeakPointer<FormEditorView> &view, m_formEditorViewList)
+ view->changeToMoveTool();
+ break;
+ }
+ case DragTool: {
+ foreach(const QWeakPointer<FormEditorView> &view, m_formEditorViewList)
+ view->changeToDragTool();
+ break;
+ }
+ case SelectTool: {
+ foreach(const QWeakPointer<FormEditorView> &view, m_formEditorViewList)
+ view->changeToSelectionTool();
+ break;
+ }
+ case ResizeTool: {
+ foreach(const QWeakPointer<FormEditorView> &view, m_formEditorViewList)
+ view->changeToResizeTool();
+ break;
+ }
+ case AnchorTool: {
+ foreach(const QWeakPointer<FormEditorView> &view, m_formEditorViewList)
+ view->changeToAnchorTool();
+ break;
+ }
+ default: Q_ASSERT(0);
+ }
+ emit toolChanged(m_currentTool);
+}
+
+void FormEditorMainView::changeToDragTool()
+{
+ setCurrentTool(DragTool);
+}
+
+
+void FormEditorMainView::changeToMoveTool()
+{
+ setCurrentTool(MoveTool);
+}
+
+void FormEditorMainView::changeToMoveTool(const QPointF &/*beginPoint*/)
+{
+ setCurrentTool(MoveTool);
+}
+
+void FormEditorMainView::changeToSelectionTool()
+{
+ setCurrentTool(SelectTool);
+}
+
+void FormEditorMainView::changeToResizeTool()
+{
+ setCurrentTool(ResizeTool);
+}
+
+void FormEditorMainView::changeToAnchorTool()
+{
+ setCurrentTool(AnchorTool);
+}
+
+void FormEditorMainView::changeToTransformTools()
+{
+ foreach(const QWeakPointer<FormEditorView> &view, m_formEditorViewList)
+ if (view)
+ view->changeToTransformTools();
+}
+
+void FormEditorMainView::anchorsChanged(const NodeState &nodeState)
+{
+ foreach(const QWeakPointer<FormEditorView> &view, m_formEditorViewList) {
+ if (view)
+ view->anchorsChanged(nodeState);
+ }
+}
+
+
+void FormEditorMainView::auxiliaryDataChanged(const ModelNode &node, const QString &name, const QVariant &data)
+{
+ foreach(const QWeakPointer<FormEditorView> &view, m_formEditorViewList) {
+ if (view)
+ view->auxiliaryDataChanged(node, name, data);
+ }
+}
+
+void FormEditorMainView::nodeSlidedToIndex(const ModelNode &node, int newIndex, int oldIndex)
+{
+ foreach(const QWeakPointer<FormEditorView> &view, m_formEditorViewList) {
+ if (view)
+ view->nodeSlidedToIndex(node, newIndex, oldIndex);
+ }
+}
+
+ComponentAction *FormEditorMainView::componentAction() const
+{
+ return m_formMainEditorWidget->componentAction();
+}
+
+ZoomAction *FormEditorMainView::zoomAction() const
+{
+ return m_formMainEditorWidget->zoomAction();
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditormainview.h b/src/plugins/qmldesigner/components/formeditor/formeditormainview.h
new file mode 100644
index 0000000000..05a563f09e
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/formeditormainview.h
@@ -0,0 +1,123 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef FORMEDITORMAINVIEW_H
+#define FORMEDITORMAINVIEW_H
+
+#include <forwardview.h>
+
+#include <formeditormainwidget.h>
+#include <formeditorview.h>
+#include <QPointer>
+
+
+namespace QmlDesigner {
+class AbstractFormEditorTool;
+
+class FormEditorMainView : public ForwardView<FormEditorView>
+{
+ Q_OBJECT
+
+public:
+ FormEditorMainView();
+ ~FormEditorMainView();
+
+ // AbstractView
+ void modelAttached(Model *model);
+ void modelAboutToBeDetached(Model *model);
+ void nodeCreated(const ModelNode &createdNode);
+ void nodeAboutToBeRemoved(const ModelNode &removedNode);
+ void nodeReparented(const ModelNode &node, const ModelNode &oldParent, const ModelNode &newParent);
+ void propertiesAdded(const NodeState &state, const QList<NodeProperty>& propertyList);
+ void propertiesAboutToBeRemoved(const NodeState &state, const QList<NodeProperty>& propertyList);
+ void propertyValuesChanged(const NodeState& state, const QList<NodeProperty> &propertyList);
+ void nodeIdChanged(const ModelNode& node, const QString& newId, const QString& oldId);
+
+ void selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
+ const QList<ModelNode> &lastSelectedNodeList);
+
+ void modelStateAboutToBeRemoved(const ModelState &modelState);
+ void modelStateAdded(const ModelState &modelState);
+
+ void nodeStatesAboutToBeRemoved(const QList<NodeState> &nodeStateList);
+ void nodeStatesAdded(const QList<NodeState> &nodeStateList);
+
+ void auxiliaryDataChanged(const ModelNode &node, const QString &name, const QVariant &data);
+ // FormEditorMainView
+ FormEditorMainWidget *widget() const;
+ NodeInstanceView *nodeInstanceView(const ModelState &modelState) const;
+
+ void setCurrentState(const ModelState &state);
+ ModelState currentState() const;
+
+ enum EditorTool {
+ MoveTool,
+ DragTool,
+ SelectTool,
+ ResizeTool,
+ AnchorTool
+ };
+
+ EditorTool currentTool() const;
+ void setCurrentTool(EditorTool tool);
+
+ void changeToMoveTool();
+ void changeToMoveTool(const QPointF &beginPoint);
+ void changeToDragTool();
+ void changeToSelectionTool();
+ void changeToResizeTool();
+ void changeToTransformTools();
+ void changeToAnchorTool();
+
+ void anchorsChanged(const NodeState &nodeState);
+ void nodeSlidedToIndex(const ModelNode &node, int newIndex, int oldIndex);
+
+ ComponentAction *componentAction() const;
+ ZoomAction *zoomAction() const;
+
+signals:
+ void stateChanged(const ModelState &state);
+ void toolChanged(EditorTool tool);
+
+protected:
+ void setupSubViews();
+ void createSubView(const QmlModelState &state);
+ void removeSubView(const QmlModelState &state);
+ void resetViews();
+
+private:
+ QWeakPointer<FormEditorMainWidget> m_formMainEditorWidget;
+ QList<QWeakPointer<FormEditorView> > m_formEditorViewList;
+ QMap<ModelState, QWeakPointer<QWidget> > m_subWindowMap;
+ EditorTool m_currentTool;
+};
+
+} // namespace QmlDesigner
+
+#endif // FORMEDITORMAINVIEW_H
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditormainwidget.cpp b/src/plugins/qmldesigner/components/formeditor/formeditormainwidget.cpp
new file mode 100644
index 0000000000..ade4aace51
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/formeditormainwidget.cpp
@@ -0,0 +1,156 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "formeditormainwidget.h"
+
+#include <QAction>
+#include <formeditormainview.h>
+#include <QtDebug>
+#include <QToolBar>
+#include <QVBoxLayout>
+#include <QFile>
+#include "toolbox.h"
+#include "componentaction.h"
+#include "zoomaction.h"
+#include <QWheelEvent>
+#include <cmath>
+
+namespace QmlDesigner {
+
+FormEditorMainWidget::FormEditorMainWidget(FormEditorMainView *mainView)
+ : QWidget(),
+ m_formEditorMainView(mainView),
+ m_stackedWidget(new QStackedWidget(this))
+{
+ QFile file(":/qmldesigner/stylesheet.css");
+ file.open(QFile::ReadOnly);
+ QString styleSheet = QLatin1String(file.readAll());
+ setStyleSheet(styleSheet);
+
+ QVBoxLayout *fillLayout = new QVBoxLayout(this);
+ fillLayout->setMargin(0);
+ fillLayout->setSpacing(0);
+ setLayout(fillLayout);
+
+ QActionGroup *toolActionGroup = new QActionGroup(this);
+
+ QAction *transformToolAction = toolActionGroup->addAction("Transform Tool (Press Key Q)");
+ transformToolAction->setShortcut(Qt::Key_Q);
+ transformToolAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+ transformToolAction->setCheckable(true);
+ transformToolAction->setChecked(true);
+ transformToolAction->setIcon(QPixmap(":/icon/tool/transform.png"));
+ connect(transformToolAction, SIGNAL(triggered(bool)), SLOT(changeTransformTool(bool)));
+
+ QAction *anchorToolAction = toolActionGroup->addAction("Anchor Tool (Press Key W)");
+ anchorToolAction->setShortcut(Qt::Key_W);
+ anchorToolAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+ anchorToolAction->setCheckable(true);
+ anchorToolAction->setIcon(QPixmap(":/icon/tool/anchor.png"));
+ connect(anchorToolAction, SIGNAL(triggered(bool)), SLOT(changeAnchorTool(bool)));
+
+ addActions(toolActionGroup->actions());
+
+
+ m_componentAction = new ComponentAction(toolActionGroup);
+ addAction(m_componentAction.data());
+
+ m_zoomAction = new ZoomAction(toolActionGroup);
+ addAction(m_zoomAction.data());
+
+ ToolBox *toolBox = new ToolBox(this);
+ toolBox->setActions(actions());
+ fillLayout->addWidget(toolBox);
+
+ fillLayout->addWidget(m_stackedWidget.data());
+}
+
+void FormEditorMainWidget::addWidget(QWidget *widget)
+{
+ m_stackedWidget->addWidget(widget);
+}
+
+QWidget *FormEditorMainWidget::currentWidget() const
+{
+ return m_stackedWidget->currentWidget();
+}
+
+void FormEditorMainWidget::setCurrentWidget(QWidget *widget)
+{
+ m_stackedWidget->setCurrentWidget(widget);
+}
+
+void FormEditorMainWidget::setModel(Model *model)
+{
+ m_componentAction->setDisabled(true);
+
+ if (model) {
+ m_componentAction->setModel(model->masterModel());
+ m_componentAction->setEnabled(true);
+ }
+}
+
+void FormEditorMainWidget::changeTransformTool(bool checked)
+{
+ if (checked)
+ m_formEditorMainView->changeToTransformTools();
+}
+
+void FormEditorMainWidget::changeAnchorTool(bool checked)
+{
+ if (checked)
+ m_formEditorMainView->changeToAnchorTool();
+}
+
+ComponentAction *FormEditorMainWidget::componentAction() const
+{
+ return m_componentAction.data();
+}
+
+ZoomAction *FormEditorMainWidget::zoomAction() const
+{
+ return m_zoomAction.data();
+}
+
+void FormEditorMainWidget::wheelEvent(QWheelEvent *event)
+{
+ if (event->modifiers().testFlag(Qt::ControlModifier)) {
+ if (event->delta() > 0) {
+ zoomAction()->zoomIn();
+ } else {
+ zoomAction()->zoomOut();
+ }
+
+ event->accept();
+ } else {
+ QWidget::wheelEvent(event);
+ }
+}
+
+}
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditormainwidget.h b/src/plugins/qmldesigner/components/formeditor/formeditormainwidget.h
new file mode 100644
index 0000000000..d07afa5fc4
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/formeditormainwidget.h
@@ -0,0 +1,74 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef FORMEDITORMAINWIDGET_H
+#define FORMEDITORMAINWIDGET_H
+
+#include <QStackedWidget>
+#include <QWeakPointer>
+
+
+
+namespace QmlDesigner {
+
+class Model;
+class FormEditorMainView;
+class ComponentAction;
+class ZoomAction;
+
+class FormEditorMainWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ FormEditorMainWidget(FormEditorMainView *mainView);
+
+ void addWidget(QWidget *widget);
+ QWidget *currentWidget() const;
+ void setCurrentWidget(QWidget *widget);
+ void setModel(Model *model);
+
+ ComponentAction *componentAction() const;
+ ZoomAction *zoomAction() const;
+
+protected:
+ void wheelEvent(QWheelEvent *event);
+
+private slots:
+ void changeTransformTool(bool checked);
+ void changeAnchorTool(bool checked);
+
+private:
+ QWeakPointer<FormEditorMainView> m_formEditorMainView;
+ QWeakPointer<QStackedWidget> m_stackedWidget;
+ QWeakPointer<ComponentAction> m_componentAction;
+ QWeakPointer<ZoomAction> m_zoomAction;
+};
+
+}
+#endif // FORMEDITORMAINWIDGET_H
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditornodeinstanceview.cpp b/src/plugins/qmldesigner/components/formeditor/formeditornodeinstanceview.cpp
new file mode 100644
index 0000000000..7516f55934
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/formeditornodeinstanceview.cpp
@@ -0,0 +1,48 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "formeditornodeinstanceview.h"
+#include "formeditorview.h"
+
+#include <modelnode.h>
+#include <QtCore/QDebug>
+
+
+namespace QmlDesigner {
+
+FormEditorNodeInstanceView::FormEditorNodeInstanceView(QObject * parent) : NodeInstanceView(parent)
+{
+
+}
+
+FormEditorNodeInstanceView::~FormEditorNodeInstanceView()
+{
+}
+
+}
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditornodeinstanceview.h b/src/plugins/qmldesigner/components/formeditor/formeditornodeinstanceview.h
new file mode 100644
index 0000000000..b1c9909e92
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/formeditornodeinstanceview.h
@@ -0,0 +1,50 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef FORMEDITORNODEINSTANCE_H
+#define FORMEDITORNODEINSTANCE_H
+
+
+#include <nodeinstanceview.h>
+
+namespace QmlDesigner {
+
+class FormEditorView;
+
+class FormEditorNodeInstanceView : public NodeInstanceView
+{
+ Q_OBJECT
+public:
+ FormEditorNodeInstanceView(QObject * parent);
+ ~FormEditorNodeInstanceView();
+};
+
+
+}
+#endif //FORMEDITORNODEINSTANCE_H
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp
new file mode 100644
index 0000000000..9c7c69d67a
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp
@@ -0,0 +1,364 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "formeditorscene.h"
+#include "formeditorview.h"
+#include "formeditorwidget.h"
+#include "formeditoritem.h"
+#include "movemanipulator.h"
+#include <metainfo.h>
+#include <QGraphicsSceneDragDropEvent>
+
+#include <QEvent>
+#include <QGraphicsSceneMouseEvent>
+#include <QGraphicsSceneHoverEvent>
+#include <QGraphicsView>
+
+#include <QApplication>
+#include <QDebug>
+#include <QList>
+
+#include "formeditornodeinstanceview.h"
+
+#include "resizehandleitem.h"
+#include <QtDebug>
+
+
+
+namespace QmlDesigner {
+
+FormEditorScene::FormEditorScene(FormEditorWidget *view, FormEditorView *editorView)
+ : QGraphicsScene(),
+ m_editorView(editorView),
+ m_formLayerItem(new LayerItem(this)),
+ m_manipulatorLayerItem(new LayerItem(this)),
+ m_paintMode(NormalMode)
+
+{
+ setSceneRect(0, 0, 1, 1); // prevent automatic calculation (causing a recursion), right size will be set later
+
+ m_manipulatorLayerItem->setZValue(1.0);
+ m_formLayerItem->setZValue(0.0);
+ m_formLayerItem->setFlag(QGraphicsItem::ItemClipsChildrenToShape, true);
+ view->setScene(this);
+
+// setItemIndexMethod(QGraphicsScene::NoIndex);
+}
+
+FormEditorScene::~FormEditorScene()
+{
+ clear(); //FormEditorItems have to be cleared before destruction
+ //Reason: FormEditorItems accesses FormEditorScene in destructor
+}
+
+
+FormEditorItem* FormEditorScene::itemForQmlItemNode(const QmlItemNode &qmlItemNode) const
+{
+ Q_ASSERT(hasItemForQmlItemNode(qmlItemNode));
+ return m_qmlItemNodeItemHash.value(qmlItemNode);
+}
+
+
+QList<FormEditorItem*> FormEditorScene::itemsForQmlItemNodes(const QList<QmlItemNode> &nodeList) const
+{
+ QList<FormEditorItem*> itemList;
+ foreach (const QmlItemNode &node, nodeList) {
+ if (hasItemForQmlItemNode(node))
+ itemList += itemForQmlItemNode(node);
+ }
+
+ return itemList;
+}
+
+QList<FormEditorItem*> FormEditorScene::allFormEditorItems() const
+{
+ return m_qmlItemNodeItemHash.values();
+}
+
+void FormEditorScene::updateAllFormEditorItems()
+{
+ foreach (FormEditorItem *item, allFormEditorItems()) {
+ item->update();
+ }
+}
+
+bool FormEditorScene::hasItemForQmlItemNode(const QmlItemNode &qmlItemNode) const
+{
+ return m_qmlItemNodeItemHash.contains(qmlItemNode);
+}
+
+void FormEditorScene::removeItemFromHash(FormEditorItem *item)
+{
+ m_qmlItemNodeItemHash.remove(item->qmlItemNode());
+}
+
+
+AbstractFormEditorTool* FormEditorScene::currentTool() const
+{
+ return m_editorView->currentTool();
+}
+
+//This method calculates the possible parent for reparent
+FormEditorItem* FormEditorScene::calulateNewParent(FormEditorItem *formEditorItem)
+{
+ QList<QGraphicsItem *> list = items(formEditorItem->qmlItemNode().instanceBoundingRect().center());
+ foreach (QGraphicsItem *graphicsItem, list) {
+ if (qgraphicsitem_cast<FormEditorItem*>(graphicsItem) &&
+ graphicsItem->collidesWithItem(formEditorItem, Qt::ContainsItemShape))
+ return qgraphicsitem_cast<FormEditorItem*>(graphicsItem);
+ }
+ return 0;
+}
+
+void FormEditorScene::synchronizeTransformation(const QmlItemNode &qmlItemNode)
+{
+ FormEditorItem *item = itemForQmlItemNode(qmlItemNode);
+ item->updateGeometry();
+ item->update();
+
+ if (qmlItemNode.isRootNode()) {
+ QRectF sceneRect(qmlItemNode.instanceBoundingRect());
+
+ setSceneRect(sceneRect);
+ formLayerItem()->update();
+ manipulatorLayerItem()->update();
+ }
+}
+
+void FormEditorScene::synchronizeParent(const QmlItemNode &qmlItemNode)
+{
+ QmlItemNode parentNode = qmlItemNode.instanceParent().toQmlItemNode();
+ if (parentNode.isValid())
+ reparentItem(qmlItemNode, parentNode);
+}
+
+void FormEditorScene::synchronizeOtherProperty(const QmlItemNode &qmlItemNode)
+{
+ if (hasItemForQmlItemNode(qmlItemNode)) {
+ FormEditorItem *item = itemForQmlItemNode(qmlItemNode);
+ if (item)
+ item->update();
+ }
+}
+
+void FormEditorScene::synchronizeState(const QmlItemNode &qmlItemNode)
+{
+ if (hasItemForQmlItemNode(qmlItemNode)) {
+ FormEditorItem *item = itemForQmlItemNode(qmlItemNode);
+ if (item)
+ item->update();
+ }
+}
+
+
+FormEditorItem *FormEditorScene::addFormEditorItem(const QmlItemNode &qmlItemNode)
+{
+ FormEditorItem *formEditorItem = new FormEditorItem(qmlItemNode, this);
+ Q_ASSERT(!m_qmlItemNodeItemHash.contains(qmlItemNode));
+
+ m_qmlItemNodeItemHash.insert(qmlItemNode, formEditorItem);
+ if (qmlItemNode.isRootNode()) {
+ QRectF sceneRect(qmlItemNode.instanceBoundingRect());
+
+ setSceneRect(sceneRect);
+ formLayerItem()->update();
+ manipulatorLayerItem()->update();
+ }
+
+ return formEditorItem;
+}
+
+
+void FormEditorScene::dropEvent(QGraphicsSceneDragDropEvent * event)
+{
+ currentTool()->dropEvent(event);
+
+ if (views().first())
+ views().first()->setFocus();
+}
+
+void FormEditorScene::dragEnterEvent(QGraphicsSceneDragDropEvent * event)
+{
+ currentTool()->dragEnterEvent(event);
+}
+
+void FormEditorScene::dragLeaveEvent(QGraphicsSceneDragDropEvent * event)
+{
+ currentTool()->dragLeaveEvent(event);
+
+ return;
+
+ if (m_dragNode.isValid()) {
+ m_dragNode.destroy();
+ }
+}
+
+void FormEditorScene::dragMoveEvent(QGraphicsSceneDragDropEvent * event)
+{
+ currentTool()->dragMoveEvent(event);
+}
+
+QList<QGraphicsItem *> FormEditorScene::removeLayerItems(const QList<QGraphicsItem *> &itemList)
+{
+ QList<QGraphicsItem *> itemListWithoutLayerItems;
+
+ foreach (QGraphicsItem *item, itemList)
+ if (item != manipulatorLayerItem() && item != formLayerItem())
+ itemListWithoutLayerItems.append(item);
+
+ return itemListWithoutLayerItems;
+}
+
+void FormEditorScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ currentTool()->mousePressEvent(removeLayerItems(items(event->scenePos())), event);
+}
+
+void FormEditorScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ if (event->buttons())
+ currentTool()->mouseMoveEvent(removeLayerItems(items(event->scenePos())), event);
+ else
+ currentTool()->hoverMoveEvent(removeLayerItems(items(event->scenePos())), event);
+
+ event->accept();
+}
+
+void FormEditorScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ currentTool()->mouseReleaseEvent(removeLayerItems(items(event->scenePos())), event);
+
+ event->accept();
+ }
+
+void FormEditorScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
+{
+ currentTool()->mouseDoubleClickEvent(removeLayerItems(items(event->scenePos())), event);
+
+ event->accept();
+}
+
+void FormEditorScene::keyPressEvent(QKeyEvent *keyEvent)
+{
+ currentTool()->keyPressEvent(keyEvent);
+}
+
+void FormEditorScene::keyReleaseEvent(QKeyEvent *keyEvent)
+{
+ currentTool()->keyReleaseEvent(keyEvent);
+}
+
+FormEditorView *FormEditorScene::editorView() const
+{
+ return m_editorView;
+}
+
+LayerItem* FormEditorScene::manipulatorLayerItem() const
+{
+ return m_manipulatorLayerItem.data();
+}
+
+LayerItem* FormEditorScene::formLayerItem() const
+{
+ return m_formLayerItem.data();
+}
+
+bool FormEditorScene::event(QEvent * event)
+{
+ switch(event->type())
+ {
+ case QEvent::GraphicsSceneHoverEnter :
+ hoverEnterEvent(static_cast<QGraphicsSceneHoverEvent *>(event));
+ return true;
+ case QEvent::GraphicsSceneHoverMove :
+ hoverMoveEvent(static_cast<QGraphicsSceneHoverEvent *>(event));
+ return true;
+ case QEvent::GraphicsSceneHoverLeave :
+ hoverLeaveEvent(static_cast<QGraphicsSceneHoverEvent *>(event));
+ return true;
+ default: return QGraphicsScene::event(event);
+ }
+
+}
+
+void FormEditorScene::hoverEnterEvent(QGraphicsSceneHoverEvent * /*event*/)
+{
+ qDebug() << __FUNCTION__;
+}
+
+void FormEditorScene::hoverMoveEvent(QGraphicsSceneHoverEvent * /*event*/)
+{
+ qDebug() << __FUNCTION__;
+}
+
+void FormEditorScene::hoverLeaveEvent(QGraphicsSceneHoverEvent * /*event*/)
+{
+ qDebug() << __FUNCTION__;
+}
+
+
+void FormEditorScene::reparentItem(const QmlItemNode &node, const QmlItemNode &newParent)
+{
+ Q_ASSERT(hasItemForQmlItemNode(node));
+ Q_ASSERT(hasItemForQmlItemNode(newParent));
+ FormEditorItem *item = itemForQmlItemNode(node);
+ FormEditorItem *parentItem = itemForQmlItemNode(newParent);
+ item->setParentItem(parentItem);
+ item->setParent(parentItem);
+}
+
+FormEditorItem* FormEditorScene::rootFormEditorItem() const
+{
+ QList<QGraphicsItem*> childItemList(m_formLayerItem->childItems());
+ if (!childItemList.isEmpty())
+ return FormEditorItem::fromQGraphicsItem(childItemList.first());
+
+ return 0;
+}
+
+FormEditorScene::PaintMode FormEditorScene::paintMode() const
+{
+ return m_paintMode;
+}
+
+void FormEditorScene::setPaintMode(PaintMode paintMode)
+{
+ m_paintMode = paintMode;
+}
+
+void FormEditorScene::clearFormEditorItems()
+{
+ foreach (QGraphicsItem *item, items()) {
+ if (qgraphicsitem_cast<FormEditorItem* >(item))
+ delete item;
+ }
+}
+
+}
+
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorscene.h b/src/plugins/qmldesigner/components/formeditor/formeditorscene.h
new file mode 100644
index 0000000000..89098ba7ab
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/formeditorscene.h
@@ -0,0 +1,133 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef FORMEDITORSCENE_H
+#define FORMEDITORSCENE_H
+
+
+#include <QGraphicsScene>
+#include <QWeakPointer>
+#include <QHash>
+#include <qmlitemnode.h>
+#include "abstractformeditortool.h"
+
+
+class QGraphicsSceneMouseEvent;
+
+namespace QmlDesigner {
+
+class FormEditorWidget;
+class FormEditorItem;
+class FormEditorView;
+class LayerItem;
+
+class FormEditorScene : public QGraphicsScene
+{
+ Q_OBJECT
+
+ friend class QmlDesigner::FormEditorItem;
+ friend class QmlDesigner::FormEditorView;
+
+public:
+ enum PaintMode {
+ NormalMode,
+ AnchorMode
+ };
+
+ FormEditorScene(FormEditorWidget *widget, FormEditorView *editorView);
+ ~FormEditorScene();
+ FormEditorItem *addFormEditorItem(const QmlItemNode &qmlItemNode);
+
+ FormEditorItem* itemForQmlItemNode(const QmlItemNode &qmlItemNode) const;
+
+ QList<FormEditorItem*> itemsForQmlItemNodes(const QList<QmlItemNode> &nodeList) const;
+ QList<FormEditorItem*> allFormEditorItems() const;
+
+ void updateAllFormEditorItems();
+
+ bool hasItemForQmlItemNode(const QmlItemNode &qmlItemNode) const;
+
+ void synchronizeTransformation(const QmlItemNode &qmlItemNode);
+ void synchronizeParent(const QmlItemNode &qmlItemNode);
+ void synchronizeOtherProperty(const QmlItemNode &qmlItemNode);
+ void synchronizeState(const QmlItemNode &qmlItemNode);
+
+ FormEditorItem* calulateNewParent(FormEditorItem *widget);
+ bool event(QEvent *event);
+ LayerItem* manipulatorLayerItem() const;
+ LayerItem* formLayerItem() const;
+ FormEditorView *editorView() const;
+
+ FormEditorItem *rootFormEditorItem() const;
+
+ void reparentItem(const QmlItemNode &node, const QmlItemNode &newParent);
+
+ PaintMode paintMode() const;
+ void setPaintMode(PaintMode paintMode);
+
+ void clearFormEditorItems();
+
+protected:
+ void dropEvent(QGraphicsSceneDragDropEvent * event);
+ void dragEnterEvent(QGraphicsSceneDragDropEvent * event);
+ void dragLeaveEvent(QGraphicsSceneDragDropEvent * event);
+ void dragMoveEvent(QGraphicsSceneDragDropEvent * event);
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+ void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
+
+ void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
+ void hoverMoveEvent(QGraphicsSceneHoverEvent *event);
+ void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
+
+ void keyPressEvent(QKeyEvent *keyEvent);
+ void keyReleaseEvent(QKeyEvent *keyEvent);
+
+private:
+ QList<QGraphicsItem *> removeLayerItems(const QList<QGraphicsItem *> &itemList);
+
+ AbstractFormEditorTool* currentTool() const;
+ void removeItemFromHash(FormEditorItem*);
+
+ FormEditorView *m_editorView;
+ AbstractFormEditorTool *m_currentTool;
+ QHash<QmlItemNode, FormEditorItem*> m_qmlItemNodeItemHash;
+ QWeakPointer<LayerItem> m_formLayerItem;
+ QWeakPointer<LayerItem> m_manipulatorLayerItem;
+ ModelNode m_dragNode;
+ PaintMode m_paintMode;
+};
+
+
+
+
+}
+#endif //FORMEDITORSCENE_H
+
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorsubwindow.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorsubwindow.cpp
new file mode 100644
index 0000000000..8fe38a042e
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/formeditorsubwindow.cpp
@@ -0,0 +1,38 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "formeditorsubwindow.h"
+
+namespace QmlDesigner {
+
+FormEditorSubWindow::FormEditorSubWindow()
+{
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorsubwindow.h b/src/plugins/qmldesigner/components/formeditor/formeditorsubwindow.h
new file mode 100644
index 0000000000..9376d73b89
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/formeditorsubwindow.h
@@ -0,0 +1,45 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef FORMEDITORSUBWINDOW_H
+#define FORMEDITORSUBWINDOW_H
+
+#include <QMdiSubWindow>
+
+namespace QmlDesigner {
+
+class FormEditorSubWindow : public QMdiSubWindow
+{
+public:
+ FormEditorSubWindow();
+};
+
+} // namespace QmlDesigner
+
+#endif // FORMEDITORSUBWINDOW_H
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp
new file mode 100644
index 0000000000..7da0cb9ed5
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp
@@ -0,0 +1,531 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "selectiontool.h"
+#include "movetool.h"
+#include "resizetool.h"
+#include "anchortool.h"
+#include "dragtool.h"
+#include "itemcreatortool.h"
+#include "formeditorview.h"
+#include "formeditorwidget.h"
+#include "formeditornodeinstanceview.h"
+#include "formeditoritem.h"
+#include "formeditorscene.h"
+#include <rewritertransaction.h>
+#include <modelnode.h>
+#include <modelutilities.h>
+#include <itemlibraryinfo.h>
+#include <metainfo.h>
+#include <model.h>
+#include <QApplication>
+#include <QtDebug>
+#include <QPair>
+#include <QString>
+#include <QDir>
+#include <QAction>
+#include <zoomaction.h>
+
+namespace QmlDesigner {
+
+FormEditorView::FormEditorView(QObject *parent)
+ : QmlModelView(parent),
+ m_formEditorWidget(new FormEditorWidget(this)),
+ m_scene(new FormEditorScene(m_formEditorWidget.data(), this)),
+ m_moveTool(new MoveTool(this)),
+ m_selectionTool(new SelectionTool(this)),
+ m_resizeTool(new ResizeTool(this)),
+ m_anchorTool(new AnchorTool(this)),
+ m_dragTool(new DragTool(this)),
+ m_itemCreatorTool(new ItemCreatorTool(this)),
+ m_currentTool(m_selectionTool)
+{
+ connect(widget()->zoomAction(), SIGNAL(zoomLevelChanged(double)), SLOT(updateGraphicsIndicators()));
+}
+
+FormEditorScene* FormEditorView::scene() const
+{
+ return m_scene.data();
+}
+
+FormEditorView::~FormEditorView()
+{
+ delete m_selectionTool;
+ m_selectionTool = 0;
+ delete m_moveTool;
+ m_moveTool = 0;
+ delete m_resizeTool;
+ m_resizeTool = 0;
+ delete m_anchorTool;
+ m_anchorTool = 0;
+ delete m_dragTool;
+ m_dragTool = 0;
+
+
+ // delete scene after tools to prevent double deletion
+ // of items
+ delete m_scene.data();
+ delete m_formEditorWidget.data();
+}
+
+void FormEditorView::modelAttached(Model *model)
+{
+ Q_ASSERT(model);
+
+ QmlModelView::modelAttached(model);
+
+ Q_ASSERT(m_scene->formLayerItem());
+
+ if (rootQmlObjectNode().toQmlItemNode().isValid())
+ setupFormEditorItemTree(rootQmlObjectNode().toQmlItemNode());
+}
+
+
+//This method does the setup of the inital FormEditorItem tree in the scene
+void FormEditorView::setupFormEditorItemTree(const QmlItemNode &qmlItemNode)
+{
+ m_scene->addFormEditorItem(qmlItemNode);
+
+ foreach (const QmlItemNode &nextNode, qmlItemNode.children()) //TODO instance children
+ setupFormEditorItemTree(nextNode);
+}
+
+void FormEditorView::nodeCreated(const ModelNode &createdNode)
+{
+ QmlModelView::nodeCreated(createdNode);
+ ModelNode node(createdNode);
+ if (QmlItemNode(node).isValid()) //only setup QmlItems
+ setupFormEditorItemTree(QmlItemNode(node));
+}
+
+void FormEditorView::modelAboutToBeDetached(Model *model)
+{
+ m_selectionTool->clear();
+ m_moveTool->clear();
+ m_resizeTool->clear();
+ m_anchorTool->clear();
+ m_dragTool->clear();
+ m_scene->clearFormEditorItems();
+
+ QmlModelView::modelAboutToBeDetached(model);
+}
+
+void FormEditorView::nodeAboutToBeRemoved(const ModelNode &removedNode)
+{
+ QmlItemNode qmlItemNode(removedNode);
+
+ if (qmlItemNode.isValid()) {
+
+ FormEditorItem *item = m_scene->itemForQmlItemNode(qmlItemNode);
+
+ QList<QmlItemNode> nodeList;
+ nodeList.append(qmlItemNode.allSubModelNodes());
+ nodeList.append(qmlItemNode);
+
+ QList<FormEditorItem*> removedItemList;
+ removedItemList.append(scene()->itemsForQmlItemNodes(nodeList));
+ m_currentTool->itemsAboutToRemoved(removedItemList);
+
+ delete item;
+ }
+
+ QmlModelView::nodeAboutToBeRemoved(removedNode);
+}
+
+ void FormEditorView::nodeTypeChanged(const ModelNode &node,const QString &type, int majorVersion, int minorVersion)
+ {
+ QmlItemNode oldItemNode(node);
+ if (oldItemNode.isValid() && m_scene->hasItemForQmlItemNode(oldItemNode)) {
+ FormEditorItem *item = m_scene->itemForQmlItemNode(oldItemNode);
+
+ QList<QmlItemNode> nodeList;
+ nodeList.append(oldItemNode.allSubModelNodes());
+ nodeList.append(oldItemNode);
+
+ QList<FormEditorItem*> removedItemList;
+ removedItemList.append(scene()->itemsForQmlItemNodes(nodeList));
+ m_currentTool->itemsAboutToRemoved(removedItemList);
+
+ delete item;
+ }
+
+ QmlModelView::nodeTypeChanged(node, type, majorVersion, minorVersion);
+
+ QmlItemNode newItemNode(node);
+ if (newItemNode.isValid()) //only setup QmlItems
+ setupFormEditorItemTree(newItemNode);
+ }
+
+void FormEditorView::propertiesAboutToBeRemoved(const QList<AbstractProperty>& propertyList)
+{
+ QmlModelView::propertiesAboutToBeRemoved(propertyList);
+}
+void FormEditorView::nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange)
+{
+ QmlModelView::nodeReparented(node, newPropertyParent, oldPropertyParent, propertyChange);
+}
+
+void FormEditorView::variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags propertyChange)
+{
+ QmlModelView::variantPropertiesChanged(propertyList, propertyChange);
+}
+
+void FormEditorView::bindingPropertiesChanged(const QList<BindingProperty>& propertyList, PropertyChangeFlags propertyChange)
+{
+ QmlModelView::bindingPropertiesChanged(propertyList, propertyChange);
+}
+
+FormEditorWidget *FormEditorView::widget() const
+{
+ Q_ASSERT(!m_formEditorWidget.isNull());
+ return m_formEditorWidget.data();
+}
+
+void FormEditorView::nodeIdChanged(const ModelNode& node, const QString& newId, const QString& oldId)
+{
+ nodeInstanceView()->nodeIdChanged(node, newId, oldId);
+}
+
+void FormEditorView::selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
+ const QList<ModelNode> &lastSelectedNodeList)
+{
+ QmlModelView::selectedNodesChanged(selectedNodeList, lastSelectedNodeList);
+
+ m_currentTool->setItems(scene()->itemsForQmlItemNodes(toQmlItemNodeList(selectedNodeList)));
+ if (scene()->paintMode() == FormEditorScene::AnchorMode) {
+ foreach (FormEditorItem *item, m_scene->itemsForQmlItemNodes(toQmlItemNodeList(selectedNodeList)))
+ item->update();
+
+ foreach (FormEditorItem *item, m_scene->itemsForQmlItemNodes(toQmlItemNodeList(lastSelectedNodeList)))
+ item->update();
+ }
+
+ m_scene->update();
+}
+
+AbstractFormEditorTool* FormEditorView::currentTool() const
+{
+ return m_currentTool;
+}
+
+void FormEditorView::changeToMoveTool()
+{
+ if (m_currentTool == m_moveTool)
+ return;
+
+ scene()->setPaintMode(FormEditorScene::NormalMode);
+ m_scene->updateAllFormEditorItems();
+ setCursor(Qt::SizeAllCursor);
+ m_currentTool->clear();
+ m_currentTool = m_moveTool;
+ m_currentTool->clear();
+ m_currentTool->setItems(scene()->itemsForQmlItemNodes(selectedQmlItemNodes()));
+}
+
+void FormEditorView::changeToDragTool()
+{
+ if (m_currentTool == m_dragTool)
+ return;
+
+ scene()->setPaintMode(FormEditorScene::NormalMode);
+ m_scene->updateAllFormEditorItems();
+ setCursor(Qt::ArrowCursor);
+ setCurrentState(baseState());
+ m_currentTool->clear();
+ m_currentTool = m_dragTool;
+ m_currentTool->clear();
+ m_currentTool->setItems(scene()->itemsForQmlItemNodes(selectedQmlItemNodes()));
+}
+
+
+void FormEditorView::changeToMoveTool(const QPointF &beginPoint)
+{
+ if (m_currentTool == m_moveTool)
+ return;
+
+ scene()->setPaintMode(FormEditorScene::NormalMode);
+ m_scene->updateAllFormEditorItems();
+ setCursor(Qt::SizeAllCursor);
+ m_currentTool->clear();
+ m_currentTool = m_moveTool;
+ m_currentTool->clear();
+ m_currentTool->setItems(scene()->itemsForQmlItemNodes(selectedQmlItemNodes()));
+ m_moveTool->beginWithPoint(beginPoint);
+}
+
+void FormEditorView::changeToSelectionTool()
+{
+ if (m_currentTool == m_selectionTool)
+ return;
+
+ scene()->setPaintMode(FormEditorScene::NormalMode);
+ m_scene->updateAllFormEditorItems();
+ setCursor(Qt::ArrowCursor);
+ m_currentTool->clear();
+ m_currentTool = m_selectionTool;
+ m_currentTool->clear();
+ m_currentTool->setItems(scene()->itemsForQmlItemNodes(selectedQmlItemNodes()));
+}
+
+void FormEditorView::changeToItemCreatorTool()
+{
+ if(m_currentTool == m_itemCreatorTool)
+ return;
+
+ scene()->setPaintMode(FormEditorScene::NormalMode);
+ m_scene->updateAllFormEditorItems();
+ setCursor(Qt::CrossCursor);
+ setCurrentState(baseState());
+ m_currentTool->clear();
+ m_currentTool = m_itemCreatorTool;
+ m_currentTool->clear();
+ setSelectedQmlItemNodes(QList<QmlItemNode>());
+ m_currentTool->setItems(scene()->itemsForQmlItemNodes(selectedQmlItemNodes()));
+}
+
+void FormEditorView::changeToSelectionTool(QGraphicsSceneMouseEvent *event)
+{
+ if (m_currentTool == m_selectionTool)
+ return;
+
+ scene()->setPaintMode(FormEditorScene::NormalMode);
+ m_scene->updateAllFormEditorItems();
+ setCursor(Qt::ArrowCursor);
+ m_currentTool->clear();
+ m_currentTool = m_selectionTool;
+ m_currentTool->clear();
+ m_currentTool->setItems(scene()->itemsForQmlItemNodes(selectedQmlItemNodes()));
+
+ m_selectionTool->selectUnderPoint(event);
+}
+
+void FormEditorView::changeToResizeTool()
+{
+ if (m_currentTool == m_resizeTool)
+ return;
+
+ scene()->setPaintMode(FormEditorScene::NormalMode);
+ m_scene->updateAllFormEditorItems();
+ setCursor(Qt::ArrowCursor);
+ m_currentTool->clear();
+ m_currentTool = m_resizeTool;
+ m_currentTool->clear();
+ m_currentTool->setItems(scene()->itemsForQmlItemNodes(selectedQmlItemNodes()));
+}
+
+void FormEditorView::changeToAnchorTool()
+{
+ if (m_currentTool == m_anchorTool)
+ return;
+
+ scene()->setPaintMode(FormEditorScene::AnchorMode);
+ m_scene->updateAllFormEditorItems();
+ setCursor(Qt::ArrowCursor);
+ m_currentTool->clear();
+ m_currentTool = m_anchorTool;
+ m_currentTool->clear();
+ m_currentTool->setItems(scene()->itemsForQmlItemNodes(selectedQmlItemNodes()));
+}
+
+void FormEditorView::changeToTransformTools()
+{
+ if (m_currentTool == m_moveTool ||
+ m_currentTool == m_resizeTool ||
+ m_currentTool == m_selectionTool)
+ return;
+
+ changeToSelectionTool();
+}
+
+void FormEditorView::setCursor(const QCursor &cursor)
+{
+ m_formEditorWidget->setCursor(cursor);
+}
+
+bool FormEditorView::isSnapButtonChecked() const
+{
+ return m_formEditorWidget->isSnapButtonChecked();
+}
+
+
+void FormEditorView::nodeSlidedToIndex(const NodeListProperty &listProperty, int /*newIndex*/, int /*oldIndex*/)
+{
+ QList<ModelNode> newOrderModelNodeList = listProperty.toModelNodeList();
+ foreach(const ModelNode &node, newOrderModelNodeList) {
+ FormEditorItem *item = m_scene->itemForQmlItemNode(QmlItemNode(node));
+ if (item) {
+ FormEditorItem *oldParentItem = item->parentItem();
+ item->setParentItem(0);
+ item->setParentItem(oldParentItem);
+ }
+ }
+
+ m_currentTool->formEditorItemsChanged(scene()->allFormEditorItems());
+}
+
+void FormEditorView::auxiliaryDataChanged(const ModelNode &node, const QString &name, const QVariant &data)
+{
+ QmlModelView::auxiliaryDataChanged(node, name, data);
+ if (name == "invisible") {
+ FormEditorItem *item(m_scene->itemForQmlItemNode(QmlItemNode(node)));
+ bool isInvisible = data.toBool();
+ item->setVisible(!isInvisible);
+ ModelNode newNode(node);
+ if (isInvisible)
+ newNode.deselectNode();
+ }
+}
+
+double FormEditorView::margins() const
+{
+ return m_formEditorWidget->margins();
+}
+
+double FormEditorView::spacing() const
+{
+ return m_formEditorWidget->spacing();
+}
+
+void FormEditorView::activateItemCreator(const QString &name)
+{
+ if (m_currentTool == m_itemCreatorTool) {
+ m_itemCreatorTool->setItemString(name);
+ return;
+ }
+ changeToItemCreatorTool();
+ m_itemCreatorTool->setItemString(name);
+}
+
+void FormEditorView::deActivateItemCreator()
+{
+ if (m_currentTool == m_itemCreatorTool) {
+ changeToSelectionTool();
+ emit ItemCreatorDeActivated();
+ }
+}
+
+QList<ModelNode> FormEditorView::adjustStatesForModelNodes(const QList<ModelNode> &nodeList) const
+{
+ QList<ModelNode> adjustedNodeList;
+ foreach (const ModelNode &node, nodeList)
+ adjustedNodeList.append(node);
+
+ return adjustedNodeList;
+}
+
+QmlItemNode findRecursiveQmlItemNode(const QmlObjectNode &firstQmlObjectNode)
+{
+ QmlObjectNode qmlObjectNode = firstQmlObjectNode;
+
+ while (true) {
+ QmlItemNode itemNode = qmlObjectNode.toQmlItemNode();
+ if (itemNode.isValid())
+ return itemNode;
+ if (qmlObjectNode.hasInstanceParent())
+ qmlObjectNode = qmlObjectNode.instanceParent();
+ else
+ break;
+ }
+
+ return QmlItemNode();
+}
+
+void FormEditorView::transformChanged(const QmlObjectNode &qmlObjectNode)
+{
+ QmlItemNode itemNode = qmlObjectNode.toQmlItemNode();
+ if (itemNode.isValid() && scene()->hasItemForQmlItemNode(itemNode)) {
+ m_scene->synchronizeTransformation(itemNode);
+ m_currentTool->formEditorItemsChanged(QList<FormEditorItem*>() << m_scene->itemForQmlItemNode(itemNode));
+ }
+}
+
+void FormEditorView::parentChanged(const QmlObjectNode &qmlObjectNode)
+{
+ QmlItemNode itemNode = qmlObjectNode.toQmlItemNode();
+ QmlItemNode parentNode = qmlObjectNode.instanceParent().toQmlItemNode();
+ if (itemNode.isValid()
+ && scene()->hasItemForQmlItemNode(itemNode)
+ && parentNode.isValid()
+ && scene()->hasItemForQmlItemNode(parentNode)
+ && scene()->itemForQmlItemNode(itemNode)->parentItem() != scene()->itemForQmlItemNode(parentNode)) {
+ scene()->synchronizeParent(itemNode);
+ m_currentTool->formEditorItemsChanged(QList<FormEditorItem*>() << m_scene->itemForQmlItemNode(itemNode));
+ }
+}
+
+void FormEditorView::otherPropertyChanged(const QmlObjectNode &qmlObjectNode)
+{
+ Q_ASSERT(qmlObjectNode.isValid());
+
+ QmlItemNode itemNode = findRecursiveQmlItemNode(qmlObjectNode);
+
+ if (itemNode.isValid() && scene()->hasItemForQmlItemNode(itemNode)) {
+ m_scene->synchronizeOtherProperty(itemNode);
+ m_currentTool->formEditorItemsChanged(QList<FormEditorItem*>() << m_scene->itemForQmlItemNode(itemNode));
+ }
+}
+
+void FormEditorView::updateGraphicsIndicators()
+{
+ m_currentTool->formEditorItemsChanged(scene()->allFormEditorItems());
+}
+
+void FormEditorView::updateItem(const QmlObjectNode &qmlObjectNode)
+{
+
+ Q_ASSERT(qmlObjectNode.isValid());
+
+ QmlItemNode itemNode = findRecursiveQmlItemNode(qmlObjectNode);
+
+ if (itemNode.isValid() && scene()->hasItemForQmlItemNode(itemNode)) {
+ m_scene->synchronizeOtherProperty(itemNode);
+ m_currentTool->formEditorItemsChanged(QList<FormEditorItem*>() << m_scene->itemForQmlItemNode(itemNode));
+ }
+}
+
+void FormEditorView::stateChanged(const QmlModelState &newQmlModelState, const QmlModelState &oldQmlModelState)
+{
+ QmlModelView::stateChanged(newQmlModelState, oldQmlModelState);
+
+
+ m_formEditorWidget->anchorToolAction()->setEnabled(newQmlModelState.isBaseState());
+
+ if (!newQmlModelState.isBaseState() && currentTool() == m_anchorTool) {
+ changeToTransformTools();
+ m_formEditorWidget->transformToolAction()->setChecked(true);
+ }
+
+// FormEditorItem *item = m_scene->itemForQmlItemNode(fxObjectNode);
+//
+// m_currentTool->formEditorItemsChanged(itemList);
+}
+
+
+}
+
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorview.h b/src/plugins/qmldesigner/components/formeditor/formeditorview.h
new file mode 100644
index 0000000000..82b6f18a75
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/formeditorview.h
@@ -0,0 +1,141 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef FORMEDITORVIEW_H
+#define FORMEDITORVIEW_H
+
+#include <qmlmodelview.h>
+
+class QGraphicsScene;
+class QGraphicsSceneMouseEvent;
+
+namespace QmlDesigner {
+
+class FormEditorWidget;
+class FormEditorNodeInstanceView;
+class FormEditorScene;
+class NodeInstanceView;
+
+class AbstractFormEditorTool;
+class MoveTool;
+class SelectionTool;
+class ResizeTool;
+class AnchorTool;
+class DragTool;
+class ItemCreatorTool;
+class ItemLibraryInfo;
+class QmlItemNode;
+
+class FormEditorView : public QmlModelView
+{
+ Q_OBJECT
+
+public:
+ FormEditorView(QObject *parent);
+ ~FormEditorView();
+
+ // AbstractView
+ void modelAttached(Model *model);
+ void modelAboutToBeDetached(Model *model);
+
+ void nodeCreated(const ModelNode &createdNode);
+ void nodeAboutToBeRemoved(const ModelNode &removedNode);
+ void nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange);
+ void nodeIdChanged(const ModelNode& node, const QString& newId, const QString& oldId);
+ void propertiesAboutToBeRemoved(const QList<AbstractProperty>& propertyList);
+ void variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags propertyChange);
+ void bindingPropertiesChanged(const QList<BindingProperty>& propertyList, PropertyChangeFlags propertyChange);
+ void nodeTypeChanged(const ModelNode &node,const QString &type, int majorVersion, int minorVersion);
+
+ void selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
+ const QList<ModelNode> &lastSelectedNodeList);
+
+ // FormEditorView
+ FormEditorWidget *widget() const;
+ AbstractFormEditorTool *currentTool() const;
+ FormEditorScene *scene() const;
+
+ void changeToMoveTool();
+ void changeToMoveTool(const QPointF &beginPoint);
+ void changeToDragTool();
+ void changeToSelectionTool();
+ void changeToItemCreatorTool();
+ void changeToSelectionTool(QGraphicsSceneMouseEvent *event);
+ void changeToResizeTool();
+ void changeToAnchorTool();
+ void changeToTransformTools();
+
+ void setCursor(const QCursor &cursor);
+
+ bool isSnapButtonChecked() const;
+
+ void nodeSlidedToIndex(const NodeListProperty &listProperty, int newIndex, int oldIndex);
+ void auxiliaryDataChanged(const ModelNode &node, const QString &name, const QVariant &data);
+
+ double margins() const;
+ double spacing() const;
+ void deActivateItemCreator();
+
+public slots:
+ void activateItemCreator(const QString &name);
+
+signals:
+ void ItemCreatorDeActivated();
+
+protected:
+ void transformChanged(const QmlObjectNode &qmlObjectNode);
+ void parentChanged(const QmlObjectNode &qmlObjectNode);
+ void otherPropertyChanged(const QmlObjectNode &qmlObjectNode);
+ void updateItem(const QmlObjectNode &qmlObjectNode);
+ void stateChanged(const QmlModelState &newQmlModelState, const QmlModelState &oldQmlModelState);
+
+protected slots:
+ QList<ModelNode> adjustStatesForModelNodes(const QList<ModelNode> &nodeList) const;
+ void updateGraphicsIndicators();
+
+private: //functions
+ void setupFormEditorItemTree(const QmlItemNode &qmlItemNode);
+
+
+private: //variables
+ QWeakPointer<FormEditorWidget> m_formEditorWidget;
+ QWeakPointer<FormEditorScene> m_scene;
+ MoveTool *m_moveTool;
+ SelectionTool *m_selectionTool;
+ ResizeTool *m_resizeTool;
+ AnchorTool *m_anchorTool;
+ DragTool *m_dragTool;
+ ItemCreatorTool *m_itemCreatorTool;
+ AbstractFormEditorTool *m_currentTool;
+
+};
+
+}
+
+#endif //FORMEDITORVIEW_H
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorwidget.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorwidget.cpp
new file mode 100644
index 0000000000..5217711fa4
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/formeditorwidget.cpp
@@ -0,0 +1,221 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "formeditorwidget.h"
+
+#include <QWheelEvent>
+#include <cmath>
+#include <QCoreApplication>
+#include <QPushButton>
+#include <QFile>
+#include <QVBoxLayout>
+#include <QActionGroup>
+#include <QGraphicsView>
+#include <toolbox.h>
+#include <zoomaction.h>
+#include <formeditorgraphicsview.h>
+#include <formeditorscene.h>
+#include <formeditorview.h>
+#include "numberseriesaction.h"
+
+namespace QmlDesigner {
+
+FormEditorWidget::FormEditorWidget(FormEditorView *view)
+ : QWidget(),
+ m_formEditorView(view)
+{
+ QFile file(":/qmldesigner/stylesheet.css");
+ file.open(QFile::ReadOnly);
+ QString styleSheet = QLatin1String(file.readAll());
+ setStyleSheet(styleSheet);
+
+ QVBoxLayout *fillLayout = new QVBoxLayout(this);
+ fillLayout->setMargin(0);
+ fillLayout->setSpacing(0);
+ setLayout(fillLayout);
+
+ m_toolActionGroup = new QActionGroup(this);
+
+ m_transformToolAction = m_toolActionGroup->addAction("Transform Tool (Press Key Q)");
+ m_transformToolAction->setShortcut(Qt::Key_Q);
+ m_transformToolAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+ m_transformToolAction->setCheckable(true);
+ m_transformToolAction->setChecked(true);
+ m_transformToolAction->setIcon(QPixmap(":/icon/tool/transform.png"));
+ connect(m_transformToolAction.data(), SIGNAL(triggered(bool)), SLOT(changeTransformTool(bool)));
+
+ m_anchorToolAction = m_toolActionGroup->addAction("Anchor Tool (Press Key W)");
+ m_anchorToolAction->setShortcut(Qt::Key_W);
+ m_anchorToolAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+ m_anchorToolAction->setCheckable(true);
+ m_anchorToolAction->setIcon(QPixmap(":/icon/tool/anchor.png"));
+ connect(m_anchorToolAction.data(), SIGNAL(triggered(bool)), SLOT(changeAnchorTool(bool)));
+
+ addActions(m_toolActionGroup->actions());
+
+ QActionGroup *layoutActionGroup = new QActionGroup(this);
+ layoutActionGroup->setExclusive(false);
+
+ m_snappingToolAction = layoutActionGroup->addAction("Toogle Snapping (Press Key E)");
+ m_snappingToolAction->setShortcut(Qt::Key_E);
+ m_snappingToolAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+ m_snappingToolAction->setCheckable(true);
+ m_snappingToolAction->setChecked(true);
+ m_snappingToolAction->setIcon(QPixmap(":/icon/layout/snapping.png"));
+ connect(m_snappingToolAction.data(), SIGNAL(triggered(bool)), SLOT(changeSnappingTool(bool)));
+
+ m_snappingMarginAction = new NumberSeriesAction(layoutActionGroup);
+ m_snappingMarginAction->addEntry("no margins (0)", 0);
+ m_snappingMarginAction->addEntry("small margin (2)", 2);
+ m_snappingMarginAction->addEntry("medium margin (6)", 6);
+ m_snappingMarginAction->addEntry("all in margin (10)", 10);
+ m_snappingMarginAction->setCurrentEntryIndex(3);
+ layoutActionGroup->addAction(m_snappingMarginAction.data());
+ addActions(layoutActionGroup->actions());
+
+ m_snappingSpacingAction = new NumberSeriesAction(layoutActionGroup);
+ m_snappingSpacingAction->addEntry("no spacing (0)", 0);
+ m_snappingSpacingAction->addEntry("small spacing (2)", 2);
+ m_snappingSpacingAction->addEntry("medium spacing (4)", 4);
+ m_snappingSpacingAction->addEntry("all in spacing (6)", 6);
+ m_snappingSpacingAction->setCurrentEntryIndex(1);
+ layoutActionGroup->addAction(m_snappingSpacingAction.data());
+
+ addActions(layoutActionGroup->actions());
+
+ m_zoomAction = new ZoomAction(toolActionGroup());
+ connect(m_zoomAction.data(), SIGNAL(zoomLevelChanged(double)), SLOT(setZoomLevel(double)));
+ addAction(m_zoomAction.data());
+
+ QAction *separatorAction = new QAction(toolActionGroup());
+ separatorAction->setSeparator(true);
+ addAction(separatorAction);
+
+ m_toolBox = new ToolBox(this);
+ toolBox()->setActions(actions());
+ fillLayout->addWidget(toolBox());
+
+ m_graphicsView = new FormEditorGraphicsView(this);
+ fillLayout->addWidget(m_graphicsView.data());
+}
+
+void FormEditorWidget::enterEvent(QEvent *event)
+{
+ setFocus();
+ QWidget::enterEvent(event);
+}
+
+void FormEditorWidget::changeTransformTool(bool checked)
+{
+ if (checked)
+ m_formEditorView->changeToTransformTools();
+}
+
+void FormEditorWidget::changeAnchorTool(bool checked)
+{
+ if (checked && m_formEditorView->currentState().isBaseState())
+ m_formEditorView->changeToAnchorTool();
+}
+
+void FormEditorWidget::changeSnappingTool(bool /*checked*/)
+{
+ // TODO
+}
+
+void FormEditorWidget::wheelEvent(QWheelEvent *event)
+{
+ if (event->modifiers().testFlag(Qt::ControlModifier)) {
+ if (event->delta() > 0) {
+ zoomAction()->zoomIn();
+ } else {
+ zoomAction()->zoomOut();
+ }
+
+ event->accept();
+ } else {
+ QWidget::wheelEvent(event);
+ }
+
+}
+
+ZoomAction *FormEditorWidget::zoomAction() const
+{
+ return m_zoomAction.data();
+}
+
+QAction *FormEditorWidget::anchorToolAction() const
+{
+ return m_anchorToolAction.data();
+}
+
+QAction *FormEditorWidget::transformToolAction() const
+{
+ return m_transformToolAction.data();
+}
+
+void FormEditorWidget::setZoomLevel(double zoomLevel)
+{
+ m_graphicsView->resetTransform();
+
+ m_graphicsView->scale(zoomLevel, zoomLevel);
+}
+
+void FormEditorWidget::setScene(FormEditorScene *scene)
+{
+ m_graphicsView->setScene(scene);
+}
+
+QActionGroup *FormEditorWidget::toolActionGroup() const
+{
+ return m_toolActionGroup.data();
+}
+
+ToolBox *FormEditorWidget::toolBox() const
+{
+ return m_toolBox.data();
+}
+
+bool FormEditorWidget::isSnapButtonChecked() const
+{
+ return m_snappingToolAction->isChecked();
+}
+
+double FormEditorWidget::spacing() const
+{
+ return m_snappingSpacingAction->currentValue().toDouble();
+}
+
+double FormEditorWidget::margins() const
+{
+ return m_snappingMarginAction->currentValue().toDouble();
+}
+
+}
+
+
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorwidget.h b/src/plugins/qmldesigner/components/formeditor/formeditorwidget.h
new file mode 100644
index 0000000000..2a718507f8
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/formeditorwidget.h
@@ -0,0 +1,91 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef FORMEDITORWIDGET_H
+#define FORMEDITORWIDGET_H
+
+#include <QWidget>
+
+class QActionGroup;
+
+namespace QmlDesigner {
+
+class ZoomAction;
+class FormEditorView;
+class FormEditorScene;
+class FormEditorGraphicsView;
+class ToolBox;
+class NumberSeriesAction;
+
+class FormEditorWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ FormEditorWidget(FormEditorView *view);
+ bool isSnapButtonChecked() const;
+
+ ZoomAction *zoomAction() const;
+ QAction *anchorToolAction() const;
+ QAction *transformToolAction() const;
+
+ void setScene(FormEditorScene *scene);
+ ToolBox *toolBox() const;
+
+ double spacing() const;
+ double margins() const;
+
+
+protected:
+ void enterEvent(QEvent *event);
+ void wheelEvent(QWheelEvent *event);
+ QActionGroup *toolActionGroup() const;
+
+private slots:
+ void changeTransformTool(bool checked);
+ void changeAnchorTool(bool checked);
+ void setZoomLevel(double zoomLevel);
+ void changeSnappingTool(bool checked);
+
+private:
+ QWeakPointer<FormEditorView> m_formEditorView;
+ QWeakPointer<FormEditorGraphicsView> m_graphicsView;
+ QWeakPointer<ZoomAction> m_zoomAction;
+ QWeakPointer<QAction> m_anchorToolAction;
+ QWeakPointer<QAction> m_transformToolAction;
+ QWeakPointer<QActionGroup> m_toolActionGroup;
+ QWeakPointer<ToolBox> m_toolBox;
+ QWeakPointer<QAction> m_snappingToolAction;
+ QWeakPointer<NumberSeriesAction> m_snappingMarginAction;
+ QWeakPointer<NumberSeriesAction> m_snappingSpacingAction;
+};
+
+
+}
+#endif //FORMEDITORWIDGET_H
+
diff --git a/src/plugins/qmldesigner/components/formeditor/itemcreatortool.cpp b/src/plugins/qmldesigner/components/formeditor/itemcreatortool.cpp
new file mode 100644
index 0000000000..9376ed18dc
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/itemcreatortool.cpp
@@ -0,0 +1,191 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "itemcreatortool.h"
+#include "formeditorscene.h"
+#include "formeditorview.h"
+
+#include <metainfo.h>
+#include <itemlibrary.h>
+
+#include <QApplication>
+#include <QGraphicsSceneMouseEvent>
+#include <QtDebug>
+#include <QClipboard>
+
+namespace QmlDesigner {
+
+ItemCreatorTool::ItemCreatorTool(FormEditorView *editorView)
+ : AbstractFormEditorTool(editorView),
+ m_rubberbandSelectionManipulator(editorView->scene()->manipulatorLayerItem(), editorView)
+
+{
+
+}
+
+
+ItemCreatorTool::~ItemCreatorTool()
+{
+}
+
+void ItemCreatorTool::mousePressEvent(const QList<QGraphicsItem*> &/*itemList*/,
+ QGraphicsSceneMouseEvent *event)
+{
+ if (event->button() == Qt::LeftButton)
+ m_rubberbandSelectionManipulator.begin(event->scenePos());
+ else
+ view()->deActivateItemCreator();
+}
+
+void ItemCreatorTool::mouseMoveEvent(const QList<QGraphicsItem*> &/*itemList*/,
+ QGraphicsSceneMouseEvent *event)
+{
+ view()->setCursor(Qt::CrossCursor);
+ if (m_rubberbandSelectionManipulator.isActive()) {
+ m_rubberbandSelectionManipulator.update(event->scenePos());
+ } else {
+
+ }
+}
+
+void ItemCreatorTool::hoverMoveEvent(const QList<QGraphicsItem*> &/*itemList*/,
+ QGraphicsSceneMouseEvent * /*event*/)
+{
+}
+
+void ItemCreatorTool::mouseReleaseEvent(const QList<QGraphicsItem*> &/*itemList*/,
+ QGraphicsSceneMouseEvent *event)
+{
+ if (event->button() == Qt::LeftButton) {
+ if (m_rubberbandSelectionManipulator.isActive()) {
+ QPointF mouseMovementVector = m_rubberbandSelectionManipulator.beginPoint() - event->scenePos();
+ if (mouseMovementVector.toPoint().manhattanLength() < QApplication::startDragDistance()) {
+ m_rubberbandSelectionManipulator.update(event->scenePos());
+ } else {
+ m_rubberbandSelectionManipulator.update(event->scenePos());
+ QRectF rect(m_rubberbandSelectionManipulator.beginPoint(), event->scenePos());
+ createAtItem(rect);
+ m_rubberbandSelectionManipulator.end();
+ view()->deActivateItemCreator();
+ }
+ }
+ } else {
+ view()->deActivateItemCreator();
+ }
+}
+
+void ItemCreatorTool::mouseDoubleClickEvent(const QList<QGraphicsItem*> &/*itemList*/,
+ QGraphicsSceneMouseEvent * /*event*/)
+{
+
+}
+
+void ItemCreatorTool::keyPressEvent(QKeyEvent *event)
+{
+ switch(event->key()) {
+ case Qt::Key_Escape:
+ view()->deActivateItemCreator();
+ break;
+ }
+}
+
+void ItemCreatorTool::keyReleaseEvent(QKeyEvent * /*keyEvent*/)
+{
+
+}
+
+void ItemCreatorTool::itemsAboutToRemoved(const QList<FormEditorItem*> &/*itemList*/)
+{
+
+}
+
+void ItemCreatorTool::clear()
+{
+ m_rubberbandSelectionManipulator.clear();
+}
+
+void ItemCreatorTool::selectedItemsChanged(const QList<FormEditorItem*> &/*itemList*/)
+{
+}
+
+void ItemCreatorTool::formEditorItemsChanged(const QList<FormEditorItem*> &/*itemList*/)
+{
+}
+
+void ItemCreatorTool::setItemString(const QString &itemString)
+{
+ m_itemString = itemString;
+}
+
+FormEditorItem* ItemCreatorTool::calculateContainer(const QPointF &point)
+{
+ QList<QGraphicsItem *> list = scene()->items(point);
+ foreach (QGraphicsItem *item, list) {
+ FormEditorItem *formEditorItem = FormEditorItem::fromQGraphicsItem(item);
+ if (formEditorItem && formEditorItem->isContainer())
+ return formEditorItem;
+ }
+ return 0;
+}
+
+void ItemCreatorTool::createAtItem(const QRectF &rect)
+{
+ QPointF pos = rect.topLeft();
+
+ QmlItemNode parentNode = view()->rootQmlItemNode();
+ FormEditorItem *parentItem = calculateContainer(pos);
+ if (parentItem) {
+ parentNode = parentItem->qmlItemNode();
+ pos = parentItem->mapFromScene(pos);
+ }
+
+ QStringList list = m_itemString.split("^");
+ if (list.count() != 2)
+ return;
+ if (list.first() == "item") {
+ RewriterTransaction transaction = view()->beginRewriterTransaction();
+ ItemLibraryInfo itemLibraryRepresentation = view()->model()->metaInfo().itemLibraryRepresentation(list.at(1));
+ QmlItemNode newNode = view()->createQmlItemNode(itemLibraryRepresentation, pos, parentNode);
+ newNode.modelNode().variantProperty("width") = rect.width();
+ newNode.modelNode().variantProperty("height") = rect.height();
+ QList<QmlItemNode> nodeList;
+ nodeList.append(newNode);
+ view()->setSelectedQmlItemNodes(nodeList);
+ } else if (list.first() == "image") {
+ RewriterTransaction transaction = view()->beginRewriterTransaction();
+ QmlItemNode newNode = view()->createQmlItemNodeFromImage(list.at(1), pos, parentNode);
+ newNode.modelNode().variantProperty("width") = rect.width();
+ newNode.modelNode().variantProperty("height") = rect.height();
+ QList<QmlItemNode> nodeList;
+ nodeList.append(newNode);
+ view()->setSelectedQmlItemNodes(nodeList);
+ }
+}
+
+} //QmlDesigner
diff --git a/src/plugins/qmldesigner/components/formeditor/itemcreatortool.h b/src/plugins/qmldesigner/components/formeditor/itemcreatortool.h
new file mode 100644
index 0000000000..c266103905
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/itemcreatortool.h
@@ -0,0 +1,82 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef ITEMCREATORTOOL_H
+#define ITEMCREATORTOOL_H
+
+
+#include "abstractformeditortool.h"
+#include "rubberbandselectionmanipulator.h"
+
+#include <QHash>
+
+
+namespace QmlDesigner {
+
+
+class ItemCreatorTool : public AbstractFormEditorTool
+{
+public:
+ ItemCreatorTool(FormEditorView* editorView);
+ ~ItemCreatorTool();
+
+ void mousePressEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event);
+ void mouseMoveEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event);
+ void mouseDoubleClickEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event);
+ void hoverMoveEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event);
+ void keyPressEvent(QKeyEvent *event);
+ void keyReleaseEvent(QKeyEvent *keyEvent);
+
+ void itemsAboutToRemoved(const QList<FormEditorItem*> &itemList);
+
+ void clear();
+
+ void selectedItemsChanged(const QList<FormEditorItem*> &itemList);
+
+ void formEditorItemsChanged(const QList<FormEditorItem*> &itemList);
+
+ void setItemString(const QString &itemString);
+
+ FormEditorItem* calculateContainer(const QPointF &point);
+
+ void createAtItem(const QRectF &rect);
+
+private:
+ RubberBandSelectionManipulator m_rubberbandSelectionManipulator;
+ QString m_itemString;
+};
+
+}
+#endif // ITEMCREATORTOOL_H
diff --git a/src/plugins/qmldesigner/components/formeditor/itemutilfunctions.cpp b/src/plugins/qmldesigner/components/formeditor/itemutilfunctions.cpp
new file mode 100644
index 0000000000..405b617e9d
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/itemutilfunctions.cpp
@@ -0,0 +1,78 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "itemutilfunctions.h"
+#include <modelutilities.h>
+#include <formeditorscene.h>
+
+#include <QRectF>
+#include <QtDebug>
+
+namespace QmlDesigner {
+
+class FormEditorItem;
+
+QRectF boundingRectForItemList(QList<FormEditorItem*> itemList)
+{
+ QRectF boundingRect;
+
+ foreach (FormEditorItem *item, itemList)
+ {
+ boundingRect = boundingRect.united(item->mapToScene(item->qmlItemNode().instanceBoundingRect()).boundingRect());
+ }
+
+ return boundingRect;
+}
+
+//ModelNode parentNodeSemanticallyChecked(const ModelNode &childNode, const ModelNode &parentNode)
+//{
+// if (ModelUtilities::canReparent(childNode, parentNode)) {
+// ModelNode newParentNode;
+// newParentNode = ModelUtilities::mapGraphicsViewToGraphicsScene(parentNode);
+// if (newParentNode == childNode.parentNode())
+// return ModelNode();
+// if (ModelUtilities::isQWidget(childNode))
+// return ModelUtilities::reparentAndProxymize(childNode, newParentNode);
+// else
+// return parentNode;
+// }
+//
+// return ModelNode();
+//}
+
+//FormEditorItem* mapGraphicsViewToGraphicsScene(FormEditorItem* item)
+//{
+// if (item == 0) //null pointer
+// return 0;
+// ModelNode newNode = ModelUtilities::mapGraphicsViewToGraphicsScene(item->modelNode());
+// return item->scene()->itemForNode(newNode);
+//}
+
+
+}
diff --git a/src/plugins/qmldesigner/components/formeditor/itemutilfunctions.h b/src/plugins/qmldesigner/components/formeditor/itemutilfunctions.h
new file mode 100644
index 0000000000..95760f2cb8
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/itemutilfunctions.h
@@ -0,0 +1,48 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef ITEMUTILFUNCTIONS_H
+#define ITEMUTILFUNCTIONS_H
+
+#include <QRectF>
+#include <QGraphicsItem>
+#include "formeditoritem.h"
+
+
+namespace QmlDesigner {
+
+QRectF boundingRectForItemList(QList<FormEditorItem*> itemList);
+
+ModelNode parentNodeSemanticallyChecked(const ModelNode &childNode, const ModelNode &parentNode);
+
+FormEditorItem* mapGraphicsViewToGraphicsScene(FormEditorItem* item);
+
+}
+
+#endif // ITEMUTILFUNCTIONS_H
diff --git a/src/plugins/qmldesigner/components/formeditor/layeritem.cpp b/src/plugins/qmldesigner/components/formeditor/layeritem.cpp
new file mode 100644
index 0000000000..5a94811531
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/layeritem.cpp
@@ -0,0 +1,73 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "layeritem.h"
+
+#include <formeditorscene.h>
+
+
+namespace QmlDesigner {
+
+LayerItem::LayerItem(FormEditorScene* scene)
+ : QGraphicsObject()
+{
+ scene->addItem(this);
+ setZValue(1);
+ setFlag(QGraphicsItem::ItemIsMovable, false);
+}
+
+LayerItem::~LayerItem()
+{
+}
+
+void LayerItem::paint(QPainter * /*painter*/, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/)
+{
+}
+
+QRectF LayerItem::boundingRect() const
+{
+ return childrenBoundingRect();
+}
+
+QList<QGraphicsItem*> LayerItem::findAllChildItems() const
+{
+ return findAllChildItems(this);
+}
+
+QList<QGraphicsItem*> LayerItem::findAllChildItems(const QGraphicsItem *item) const
+{
+ QList<QGraphicsItem*> itemList(item->childItems());
+
+ foreach (QGraphicsItem *childItem, item->childItems())
+ itemList += findAllChildItems(childItem);
+
+ return itemList;
+}
+
+}
diff --git a/src/plugins/qmldesigner/components/formeditor/layeritem.h b/src/plugins/qmldesigner/components/formeditor/layeritem.h
new file mode 100644
index 0000000000..09881a065c
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/layeritem.h
@@ -0,0 +1,66 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef LAYERITEM_H
+#define LAYERITEM_H
+
+#include <QGraphicsObject>
+#include <QWeakPointer>
+
+namespace QmlDesigner {
+
+class FormEditorScene;
+
+class LayerItem : public QGraphicsObject
+{
+public:
+ enum
+ {
+ Type = 0xEAAA
+ };
+ LayerItem(FormEditorScene* scene);
+ ~LayerItem();
+ void paint ( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0 );
+ QRectF boundingRect() const;
+ int type() const;
+
+ QList<QGraphicsItem*> findAllChildItems() const;
+
+protected:
+ QList<QGraphicsItem*> findAllChildItems(const QGraphicsItem *item) const;
+};
+
+inline int LayerItem::type() const
+{
+ return Type;
+}
+
+}
+
+#endif // LAYERITEM_H
diff --git a/src/plugins/qmldesigner/components/formeditor/manipulatorlayeritem.h b/src/plugins/qmldesigner/components/formeditor/manipulatorlayeritem.h
new file mode 100644
index 0000000000..215d1702fe
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/manipulatorlayeritem.h
@@ -0,0 +1,39 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef MANIPULATORLAYERITEM_H
+#define MANIPULATORLAYERITEM_H
+
+class ManipulatorLayerItem
+{
+public:
+ ManipulatorLayerItem();
+};
+
+#endif // MANIPULATORLAYERITEM_H
diff --git a/src/plugins/qmldesigner/components/formeditor/movemanipulator.cpp b/src/plugins/qmldesigner/components/formeditor/movemanipulator.cpp
new file mode 100644
index 0000000000..fe0ca9893a
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/movemanipulator.cpp
@@ -0,0 +1,363 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "movemanipulator.h"
+#include "itemutilfunctions.h"
+#include "layeritem.h"
+#include "formeditoritem.h"
+#include "formeditorscene.h"
+
+#include <QPointF>
+#include <QtDebug>
+#include <QColor>
+#include <QPen>
+#include <QApplication>
+
+#include <limits>
+#include <model.h>
+#include <qmlanchors.h>
+
+
+namespace QmlDesigner {
+
+MoveManipulator::MoveManipulator(LayerItem *layerItem, FormEditorView *view)
+ : m_layerItem(layerItem),
+ m_view(view),
+ m_isActive(false)
+{
+}
+
+MoveManipulator::~MoveManipulator()
+{
+ deleteSnapLines();
+}
+
+QPointF MoveManipulator::beginPoint() const
+{
+ return m_beginPoint;
+}
+
+void MoveManipulator::setItem(FormEditorItem* item)
+{
+ QList<FormEditorItem*> itemList;
+ itemList.append(item);
+
+ setItems(itemList);
+}
+
+void MoveManipulator::setItems(const QList<FormEditorItem*> &itemList)
+{
+ m_itemList = itemList;
+ if (!m_itemList.isEmpty()) {
+ if (m_itemList.first()->parentItem())
+ m_snapper.setContainerFormEditorItem(m_itemList.first()->parentItem());
+ else
+ m_snapper.setContainerFormEditorItem(m_itemList.first());
+ m_snapper.setTransformtionSpaceFormEditorItem(m_snapper.containerFormEditorItem());
+ }
+}
+
+void MoveManipulator::updateHashes()
+{
+// foreach (FormEditorItem* item, m_itemList)
+// m_beginItemRectHash[item] = item->mapRectToParent(item->qmlItemNode().instanceBoundingRect());
+
+ foreach (FormEditorItem* item, m_itemList) {
+ QPointF positionInParentSpace = m_snapper.containerFormEditorItem()->mapFromScene(m_beginPositionInSceneSpaceHash.value(item));
+ m_beginItemRectHash[item].translate(positionInParentSpace - m_beginPositionHash.value(item));
+ m_beginPositionHash.insert(item, positionInParentSpace);
+ }
+}
+
+bool MoveManipulator::itemsCanReparented() const
+{
+ foreach (FormEditorItem* item, m_itemList) {
+ if (!item->qmlItemNode().canReparent())
+ return false;
+ }
+
+ return true;
+}
+
+void MoveManipulator::begin(const QPointF &beginPoint)
+{
+ m_isActive = true;
+
+ m_snapper.updateSnappingLines(m_itemList);
+
+
+ foreach (FormEditorItem* item, m_itemList)
+ m_beginItemRectHash.insert(item, m_snapper.containerFormEditorItem()->mapRectFromItem(item, item->qmlItemNode().instanceBoundingRect()));
+
+ foreach (FormEditorItem* item, m_itemList) {
+ QPointF positionInParentSpace(item->qmlItemNode().instancePosition());
+ QPointF positionInScenesSpace = m_snapper.containerFormEditorItem()->mapToScene(positionInParentSpace);
+ m_beginPositionInSceneSpaceHash.insert(item, positionInScenesSpace);
+ }
+
+ foreach (FormEditorItem* item, m_itemList) {
+ QPointF positionInParentSpace = m_snapper.containerFormEditorItem()->mapFromScene(m_beginPositionInSceneSpaceHash.value(item));
+ m_beginPositionHash.insert(item, positionInParentSpace);
+
+ QmlAnchors anchors(item->qmlItemNode().anchors());
+ m_beginTopMarginHash.insert(item, anchors.instanceMargin(AnchorLine::Top));
+ m_beginLeftMarginHash.insert(item, anchors.instanceMargin(AnchorLine::Left));
+ m_beginRightMarginHash.insert(item, anchors.instanceMargin(AnchorLine::Right));
+ m_beginBottomMarginHash.insert(item, anchors.instanceMargin(AnchorLine::Bottom));
+ m_beginHorizontalCenterHash.insert(item, anchors.instanceMargin(AnchorLine::HorizontalCenter));
+ m_beginVerticalCenterHash.insert(item, anchors.instanceMargin(AnchorLine::VerticalCenter));
+ }
+
+ m_beginPoint = beginPoint;
+
+// setOpacityForAllElements(0.62);
+
+ m_rewriterTransaction = m_view->beginRewriterTransaction();
+}
+
+
+
+
+
+QPointF MoveManipulator::findSnappingOffset(const QList<QRectF> &boundingRectList)
+{
+ QPointF offset;
+
+ QMap<double, double> verticalOffsetMap;
+ foreach (const QRectF &boundingRect, boundingRectList) {
+ double verticalOffset = m_snapper.snappedVerticalOffset(boundingRect);
+ if (verticalOffset < std::numeric_limits<double>::max())
+ verticalOffsetMap.insert(qAbs(verticalOffset), verticalOffset);
+ }
+
+
+ if (!verticalOffsetMap.isEmpty())
+ offset.rx() = verticalOffsetMap.begin().value();
+
+
+
+ QMap<double, double> horizontalOffsetMap;
+ foreach (const QRectF &boundingRect, boundingRectList) {
+ double horizontalOffset = m_snapper.snappedHorizontalOffset(boundingRect);
+ if (horizontalOffset < std::numeric_limits<double>::max())
+ horizontalOffsetMap.insert(qAbs(horizontalOffset), horizontalOffset);
+ }
+
+
+ if (!horizontalOffsetMap.isEmpty())
+ offset.ry() = horizontalOffsetMap.begin().value();
+
+ return offset;
+}
+
+
+void MoveManipulator::generateSnappingLines(const QList<QRectF> &boundingRectList)
+{
+ m_graphicsLineList = m_snapper.generateSnappingLines(boundingRectList,
+ m_layerItem.data(),
+ m_snapper.transformtionSpaceFormEditorItem()->sceneTransform());
+}
+
+
+
+QList<QRectF> MoveManipulator::tanslatedBoundingRects(const QList<QRectF> &boundingRectList, const QPointF& offsetVector)
+{
+ QList<QRectF> translatedBoundingRectList;
+ foreach (const QRectF &boundingRect, boundingRectList)
+ translatedBoundingRectList.append(boundingRect.translated(offsetVector));
+
+ return translatedBoundingRectList;
+}
+
+
+
+/*
+ /brief updates the position of the items.
+*/
+void MoveManipulator::update(const QPointF& updatePoint, Snapping useSnapping)
+{
+ deleteSnapLines(); //Since they position is changed and the item is moved the snapping lines are
+ //are obsolete. The new updated snapping lines (color and visibility) will be
+ //calculated in snapPoint() called in moveNode() later
+
+ if (m_itemList.isEmpty()) {
+ return;
+ } else {
+ QPointF updatePointInContainerSpace(m_snapper.containerFormEditorItem()->mapFromScene(updatePoint));
+ QPointF beginPointInContainerSpace(m_snapper.containerFormEditorItem()->mapFromScene(m_beginPoint));
+
+ QPointF offsetVector(updatePointInContainerSpace - beginPointInContainerSpace);
+ if (useSnapping == UseSnapping) {
+ offsetVector -= findSnappingOffset(tanslatedBoundingRects(m_beginItemRectHash.values(), offsetVector));
+ generateSnappingLines(tanslatedBoundingRects(m_beginItemRectHash.values(), offsetVector));
+ }
+
+ foreach (FormEditorItem* item, m_itemList) {
+ QPointF positionInContainerSpace(m_beginPositionHash.value(item) + offsetVector);
+ QmlAnchors anchors(item->qmlItemNode().anchors());
+
+ if (anchors.instanceHasAnchor(AnchorLine::Top)) {
+ anchors.setMargin(AnchorLine::Top, m_beginTopMarginHash.value(item) + offsetVector.y());
+ }
+
+ if (anchors.instanceHasAnchor(AnchorLine::Left)) {
+ anchors.setMargin(AnchorLine::Left, m_beginLeftMarginHash.value(item) + offsetVector.x());
+ }
+
+ if (anchors.instanceHasAnchor(AnchorLine::Bottom)) {
+ anchors.setMargin(AnchorLine::Bottom, m_beginBottomMarginHash.value(item) - offsetVector.y());
+ }
+
+ if (anchors.instanceHasAnchor(AnchorLine::Right)) {
+ anchors.setMargin(AnchorLine::Right, m_beginRightMarginHash.value(item) - offsetVector.x());
+ }
+
+ if (anchors.instanceHasAnchor(AnchorLine::HorizontalCenter)) {
+ anchors.setMargin(AnchorLine::HorizontalCenter, m_beginHorizontalCenterHash.value(item) + offsetVector.x());
+ }
+
+ if (anchors.instanceHasAnchor(AnchorLine::VerticalCenter)) {
+ anchors.setMargin(AnchorLine::VerticalCenter, m_beginVerticalCenterHash.value(item) + offsetVector.y());
+ }
+
+ item->qmlItemNode().setPosition(positionInContainerSpace);
+ }
+
+
+ }
+}
+
+void MoveManipulator::clear()
+{
+ deleteSnapLines();
+ m_beginItemRectHash.clear();
+ m_beginPositionHash.clear();
+ m_beginPositionInSceneSpaceHash.clear();
+ m_itemList.clear();
+
+ m_rewriterTransaction.commit();
+
+ m_beginTopMarginHash.clear();
+ m_beginLeftMarginHash.clear();
+ m_beginRightMarginHash.clear();
+ m_beginBottomMarginHash.clear();
+ m_beginHorizontalCenterHash.clear();
+ m_beginVerticalCenterHash.clear();
+}
+
+void MoveManipulator::reparentTo(FormEditorItem *newParent)
+{
+ deleteSnapLines();
+
+ if (!newParent)
+ return;
+
+ if (!itemsCanReparented())
+ return;
+
+ foreach (FormEditorItem* item, m_itemList) {
+ QmlItemNode parent(newParent->qmlItemNode());
+ if (parent.isValid()) {
+ item->qmlItemNode().setParentProperty(parent.nodeAbstractProperty("data"));
+ }
+ }
+
+ if (m_view->model()) {
+ m_snapper.setContainerFormEditorItem(newParent);
+ m_snapper.setTransformtionSpaceFormEditorItem(m_snapper.containerFormEditorItem());
+ m_snapper.updateSnappingLines(m_itemList);
+ updateHashes();
+ }
+}
+
+
+void MoveManipulator::end(const QPointF &/*endPoint*/)
+{
+ m_isActive = false;
+ deleteSnapLines();
+// setOpacityForAllElements(1.0);
+ clear();
+}
+
+void MoveManipulator::moveBy(double deltaX, double deltaY)
+{
+ foreach (FormEditorItem* item, m_itemList) {
+ QmlAnchors anchors(item->qmlItemNode().anchors());
+
+ if (anchors.instanceHasAnchor(AnchorLine::Top)) {
+ anchors.setMargin(AnchorLine::Top, anchors.instanceMargin(AnchorLine::Top) - deltaY);
+ }
+
+ if (anchors.instanceHasAnchor(AnchorLine::Left)) {
+ anchors.setMargin(AnchorLine::Left, anchors.instanceMargin(AnchorLine::Left) + deltaX);
+ }
+
+ if (anchors.instanceHasAnchor(AnchorLine::Bottom)) {
+ anchors.setMargin(AnchorLine::Bottom, anchors.instanceMargin(AnchorLine::Bottom) + deltaY);
+ }
+
+ if (anchors.instanceHasAnchor(AnchorLine::Right)) {
+ anchors.setMargin(AnchorLine::Right, anchors.instanceMargin(AnchorLine::Right) - deltaX);
+ }
+
+ if (anchors.instanceHasAnchor(AnchorLine::HorizontalCenter)) {
+ anchors.setMargin(AnchorLine::HorizontalCenter, anchors.instanceMargin(AnchorLine::HorizontalCenter) + deltaX);
+ }
+
+ if (anchors.instanceHasAnchor(AnchorLine::VerticalCenter)) {
+ anchors.setMargin(AnchorLine::VerticalCenter, anchors.instanceMargin(AnchorLine::VerticalCenter) + deltaY);
+ }
+
+ item->qmlItemNode().setPosition(QPointF(item->qmlItemNode().instanceValue("x").toDouble() + deltaX,
+ item->qmlItemNode().instanceValue("y").toDouble() + deltaY));
+ }
+}
+
+void MoveManipulator::setOpacityForAllElements(qreal opacity)
+{
+ foreach (FormEditorItem* item, m_itemList)
+ item->setOpacity(opacity);
+}
+
+void MoveManipulator::deleteSnapLines()
+{
+ if (m_layerItem) {
+ foreach (QGraphicsItem *item, m_graphicsLineList)
+ m_layerItem->scene()->removeItem(item);
+ }
+ m_graphicsLineList.clear();
+ m_view->scene()->update();
+}
+
+bool MoveManipulator::isActive() const
+{
+ return m_isActive;
+}
+
+}
diff --git a/src/plugins/qmldesigner/components/formeditor/movemanipulator.h b/src/plugins/qmldesigner/components/formeditor/movemanipulator.h
new file mode 100644
index 0000000000..3501625b4d
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/movemanipulator.h
@@ -0,0 +1,114 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef MOVEMANIPULATOR_H
+#define MOVEMANIPULATOR_H
+
+#include <QWeakPointer>
+#include <QGraphicsItem>
+#include <QGraphicsLineItem>
+#include <QHash>
+#include <QPointF>
+#include <QRectF>
+
+#include "controlelement.h"
+#include "formeditoritem.h"
+#include "rewritertransaction.h"
+#include "snapper.h"
+#include "formeditorview.h"
+
+namespace QmlDesigner {
+
+class ModelNodeChangeSet;
+class Model;
+
+class MoveManipulator
+{
+public:
+ enum Snapping {
+ UseSnapping,
+ NoSnapping
+ };
+
+ MoveManipulator(LayerItem *layerItem, FormEditorView *view);
+ ~MoveManipulator();
+ void setItems(const QList<FormEditorItem*> &itemList);
+ void setItem(FormEditorItem* item);
+
+ void begin(const QPointF& beginPoint);
+ void update(const QPointF& updatePoint, Snapping useSnapping);
+ void reparentTo(FormEditorItem *newParent);
+ void end(const QPointF& endPoint);
+
+ void moveBy(double deltaX, double deltaY);
+
+ QPointF beginPoint() const;
+
+ void clear();
+
+ bool isActive() const;
+
+protected:
+ void setOpacityForAllElements(qreal opacity);
+
+ QPointF findSnappingOffset(const QList<QRectF> &boundingRectList);
+
+ void deleteSnapLines();
+
+ QList<QRectF> tanslatedBoundingRects(const QList<QRectF> &boundingRectList, const QPointF& offset);
+ QPointF calculateBoundingRectMovementOffset(const QPointF& updatePoint);
+ QRectF boundingRect(FormEditorItem* item, const QPointF& updatePoint);
+
+ void generateSnappingLines(const QList<QRectF> &boundingRectList);
+ void updateHashes();
+
+ bool itemsCanReparented() const;
+
+private:
+ Snapper m_snapper;
+ QWeakPointer<LayerItem> m_layerItem;
+ QWeakPointer<FormEditorView> m_view;
+ QList<FormEditorItem*> m_itemList;
+ QHash<FormEditorItem*, QRectF> m_beginItemRectHash;
+ QHash<FormEditorItem*, QPointF> m_beginPositionHash;
+ QHash<FormEditorItem*, QPointF> m_beginPositionInSceneSpaceHash;
+ QPointF m_beginPoint;
+ QHash<FormEditorItem*, double> m_beginTopMarginHash;
+ QHash<FormEditorItem*, double> m_beginLeftMarginHash;
+ QHash<FormEditorItem*, double> m_beginRightMarginHash;
+ QHash<FormEditorItem*, double> m_beginBottomMarginHash;
+ QHash<FormEditorItem*, double> m_beginHorizontalCenterHash;
+ QHash<FormEditorItem*, double> m_beginVerticalCenterHash;
+ QList<QGraphicsItem*> m_graphicsLineList;
+ bool m_isActive;
+ RewriterTransaction m_rewriterTransaction;
+};
+
+}
+#endif // MOVEMANIPULATOR_H
diff --git a/src/plugins/qmldesigner/components/formeditor/movetool.cpp b/src/plugins/qmldesigner/components/formeditor/movetool.cpp
new file mode 100644
index 0000000000..09f5ec73c1
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/movetool.cpp
@@ -0,0 +1,345 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "movetool.h"
+
+#include "formeditorscene.h"
+#include "formeditorview.h"
+#include "modelutilities.h"
+#include "itemutilfunctions.h"
+
+#include "resizehandleitem.h"
+
+#include <QApplication>
+#include <QGraphicsSceneMouseEvent>
+#include <QtDebug>
+
+namespace QmlDesigner {
+
+MoveTool::MoveTool(FormEditorView *editorView)
+ : AbstractFormEditorTool(editorView),
+ m_moveManipulator(editorView->scene()->manipulatorLayerItem(), editorView),
+ m_selectionIndicator(editorView->scene()->manipulatorLayerItem()),
+ m_resizeIndicator(editorView->scene()->manipulatorLayerItem())
+{
+// view()->setCursor(Qt::SizeAllCursor);
+}
+
+
+MoveTool::~MoveTool()
+{
+
+}
+
+void MoveTool::clear()
+{
+ m_moveManipulator.clear();
+ m_movingItems.clear();
+ m_selectionIndicator.clear();
+ m_resizeIndicator.clear();
+}
+
+void MoveTool::mousePressEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event)
+{
+ if (itemList.isEmpty())
+ return;
+ m_movingItems = movingItems(items());
+ if (m_movingItems.isEmpty())
+ return;
+
+ m_moveManipulator.setItems(m_movingItems);
+ m_moveManipulator.begin(event->scenePos());
+}
+
+void MoveTool::mouseMoveEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event)
+{
+ if (m_movingItems.isEmpty())
+ return;
+
+// m_selectionIndicator.hide();
+ m_resizeIndicator.hide();
+
+ FormEditorItem *containerItem = containerFormEditorItem(itemList, m_movingItems);
+ if (containerItem &&
+ containerItem != m_movingItems.first()->parentItem() &&
+ view()->currentState().isBaseState() &&
+ !event->modifiers().testFlag(Qt::ShiftModifier)) {
+
+ m_moveManipulator.reparentTo(containerItem);
+ }
+
+ MoveManipulator::Snapping useSnapping = MoveManipulator::NoSnapping;
+ if (event->modifiers().testFlag(Qt::ControlModifier) != view()->isSnapButtonChecked())
+ useSnapping = MoveManipulator::UseSnapping;
+
+ m_moveManipulator.update(event->scenePos(), useSnapping);
+}
+
+void MoveTool::hoverMoveEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent * /*event*/)
+{
+ if (itemList.isEmpty()) {
+ view()->changeToSelectionTool();
+ return;
+ }
+
+ ResizeHandleItem* resizeHandle = ResizeHandleItem::fromGraphicsItem(itemList.first());
+ if (resizeHandle) {
+ view()->changeToResizeTool();
+ return;
+ }
+
+ if (!topSelectedItemIsMovable(itemList)) {
+ view()->changeToSelectionTool();
+ return;
+ }
+}
+
+void MoveTool::keyPressEvent(QKeyEvent *event)
+{
+ switch(event->key()) {
+ case Qt::Key_Shift:
+ case Qt::Key_Alt:
+ case Qt::Key_Control:
+ case Qt::Key_AltGr:
+ event->setAccepted(false);
+ return;
+ }
+
+ double moveStep = 1.0;
+
+ if (event->modifiers().testFlag(Qt::ShiftModifier))
+ moveStep = 10.0;
+
+ if (!event->isAutoRepeat()) {
+ QList<FormEditorItem*> movableItems(movingItems(items()));
+ if (movableItems.isEmpty())
+ return;
+
+ m_moveManipulator.setItems(movableItems);
+// m_selectionIndicator.hide();
+ m_resizeIndicator.hide();
+ }
+
+ switch(event->key()) {
+ case Qt::Key_Left: m_moveManipulator.moveBy(-moveStep, 0.0); break;
+ case Qt::Key_Right: m_moveManipulator.moveBy(moveStep, 0.0); break;
+ case Qt::Key_Up: m_moveManipulator.moveBy(0.0, -moveStep); break;
+ case Qt::Key_Down: m_moveManipulator.moveBy(0.0, moveStep); break;
+ }
+
+
+}
+
+void MoveTool::keyReleaseEvent(QKeyEvent *keyEvent)
+{
+ switch(keyEvent->key()) {
+ case Qt::Key_Shift:
+ case Qt::Key_Alt:
+ case Qt::Key_Control:
+ case Qt::Key_AltGr:
+ keyEvent->setAccepted(false);
+ return;
+ }
+
+ if (!keyEvent->isAutoRepeat()) {
+ m_moveManipulator.clear();
+// m_selectionIndicator.show();
+ m_resizeIndicator.show();
+ }
+}
+
+void MoveTool::mouseReleaseEvent(const QList<QGraphicsItem*> &/*itemList*/,
+ QGraphicsSceneMouseEvent *event)
+{
+ if (m_movingItems.isEmpty())
+ return;
+
+ QLineF moveVector(event->scenePos(), m_moveManipulator.beginPoint());
+ if (moveVector.length() < QApplication::startDragDistance())
+ {
+ QPointF beginPoint(m_moveManipulator.beginPoint());
+
+ m_moveManipulator.end(beginPoint);
+
+// m_selectionIndicator.show();
+ m_resizeIndicator.show();
+ m_movingItems.clear();
+
+ view()->changeToSelectionTool(event);
+ } else {
+ m_moveManipulator.end(event->scenePos());
+
+ m_selectionIndicator.show();
+ m_resizeIndicator.show();
+ m_movingItems.clear();
+ }
+}
+
+void MoveTool::mouseDoubleClickEvent(const QList<QGraphicsItem*> & /*itemList*/,
+ QGraphicsSceneMouseEvent * /*event*/)
+{
+
+}
+
+void MoveTool::itemsAboutToRemoved(const QList<FormEditorItem*> &removedItemList)
+{
+ foreach (FormEditorItem* removedItem, removedItemList)
+ m_movingItems.removeOne(removedItem);
+}
+
+void MoveTool::selectedItemsChanged(const QList<FormEditorItem*> &itemList)
+{
+ m_selectionIndicator.setItems(movingItems(itemList));
+ m_resizeIndicator.setItems(itemList);
+ updateMoveManipulator();
+}
+
+bool MoveTool::haveSameParent(const QList<FormEditorItem*> &itemList)
+{
+ if (itemList.isEmpty())
+ return false;
+
+ QGraphicsItem *firstParent = itemList.first()->parentItem();
+ foreach (FormEditorItem* item, itemList)
+ {
+ if (firstParent != item->parentItem())
+ return false;
+ }
+
+ return true;
+}
+
+bool MoveTool::isAncestorOfAllItems(FormEditorItem* maybeAncestorItem,
+ const QList<FormEditorItem*> &itemList)
+{
+ foreach (FormEditorItem* item, itemList)
+ {
+ if (!maybeAncestorItem->isAncestorOf(item) && item != maybeAncestorItem)
+ return false;
+ }
+
+ return true;
+}
+
+
+FormEditorItem* MoveTool::ancestorIfOtherItemsAreChild(const QList<FormEditorItem*> &itemList)
+{
+ if (itemList.isEmpty())
+ return 0;
+
+
+ foreach (FormEditorItem* item, itemList)
+ {
+ if (isAncestorOfAllItems(item, itemList))
+ return item;
+ }
+
+ return 0;
+}
+
+void MoveTool::updateMoveManipulator()
+{
+ if (m_moveManipulator.isActive())
+ return;
+}
+
+void MoveTool::beginWithPoint(const QPointF &beginPoint)
+{
+ m_movingItems = movingItems(items());
+ if (m_movingItems.isEmpty())
+ return;
+
+ m_moveManipulator.setItems(m_movingItems);
+ m_moveManipulator.begin(beginPoint);
+}
+
+static bool isNotAncestorOfItemInList(FormEditorItem *formEditorItem, const QList<FormEditorItem*> &itemList)
+{
+ foreach (FormEditorItem *item, itemList) {
+ if (item->qmlItemNode().isAncestorOf(formEditorItem->qmlItemNode()))
+ return false;
+ }
+
+ return true;
+}
+
+FormEditorItem* MoveTool::containerFormEditorItem(const QList<QGraphicsItem*> &itemUnderMouseList,
+ const QList<FormEditorItem*> &selectedItemList)
+{
+ Q_ASSERT(!selectedItemList.isEmpty());
+
+ foreach (QGraphicsItem* item, itemUnderMouseList) {
+ FormEditorItem *formEditorItem = FormEditorItem::fromQGraphicsItem(item);
+ if (formEditorItem
+ && !selectedItemList.contains(formEditorItem)
+ && isNotAncestorOfItemInList(formEditorItem, selectedItemList))
+ if (formEditorItem->isContainer()) {
+ return formEditorItem;
+ }
+
+ }
+
+ return 0;
+}
+
+
+QList<FormEditorItem*> MoveTool::movingItems(const QList<FormEditorItem*> &selectedItemList)
+{
+ FormEditorItem* ancestorItem = ancestorIfOtherItemsAreChild(selectedItemList);
+
+ if (ancestorItem != 0 && ancestorItem->qmlItemNode().isRootNode()) {
+// view()->changeToSelectionTool();
+ return QList<FormEditorItem*>();
+ }
+
+
+ if (ancestorItem != 0 && ancestorItem->parentItem() != 0) {
+ QList<FormEditorItem*> ancestorItemList;
+ ancestorItemList.append(ancestorItem);
+ return ancestorItemList;
+ }
+
+ if (!haveSameParent(selectedItemList)) {
+// view()->changeToSelectionTool();
+ return QList<FormEditorItem*>();
+ }
+
+ return selectedItemList;
+}
+
+void MoveTool::formEditorItemsChanged(const QList<FormEditorItem*> &itemList)
+{
+ m_selectionIndicator.updateItems(itemList);
+ m_resizeIndicator.updateItems(itemList);
+}
+
+}
diff --git a/src/plugins/qmldesigner/components/formeditor/movetool.h b/src/plugins/qmldesigner/components/formeditor/movetool.h
new file mode 100644
index 0000000000..df3c65b791
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/movetool.h
@@ -0,0 +1,97 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef MOVETOOL_H
+#define MOVETOOL_H
+
+#include "abstractformeditortool.h"
+#include "movemanipulator.h"
+#include "selectionindicator.h"
+#include "resizeindicator.h"
+
+#include <QHash>
+
+
+namespace QmlDesigner {
+
+
+class MoveTool : public AbstractFormEditorTool
+{
+public:
+ MoveTool(FormEditorView* editorView);
+ ~MoveTool();
+
+ void mousePressEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event);
+ void mouseMoveEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event);
+ void mouseDoubleClickEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event);
+ void hoverMoveEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event);
+ void keyPressEvent(QKeyEvent *event);
+ void keyReleaseEvent(QKeyEvent *keyEvent);
+
+ void itemsAboutToRemoved(const QList<FormEditorItem*> &itemList);
+
+ void selectedItemsChanged(const QList<FormEditorItem*> &itemList);
+
+ void updateMoveManipulator();
+
+
+
+ void beginWithPoint(const QPointF &beginPoint);
+
+ void clear();
+
+ void formEditorItemsChanged(const QList<FormEditorItem*> &itemList);
+
+protected:
+ static bool haveSameParent(const QList<FormEditorItem*> &itemList);
+
+ static QList<FormEditorItem*> movingItems(const QList<FormEditorItem*> &selectedItemList);
+
+ static FormEditorItem* containerFormEditorItem(const QList<QGraphicsItem*> &itemUnderMouseList,
+ const QList<FormEditorItem*> &selectedItemList);
+
+ static bool isAncestorOfAllItems(FormEditorItem* maybeAncestorItem,
+ const QList<FormEditorItem*> &itemList);
+ static FormEditorItem* ancestorIfOtherItemsAreChild(const QList<FormEditorItem*> &itemList);
+
+private:
+ MoveManipulator m_moveManipulator;
+ SelectionIndicator m_selectionIndicator;
+ ResizeIndicator m_resizeIndicator;
+ QList<FormEditorItem*> m_movingItems;
+};
+
+}
+#endif // MOVETOOL_H
diff --git a/src/plugins/qmldesigner/components/formeditor/numberseriesaction.cpp b/src/plugins/qmldesigner/components/formeditor/numberseriesaction.cpp
new file mode 100644
index 0000000000..ba6354f01d
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/numberseriesaction.cpp
@@ -0,0 +1,88 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "numberseriesaction.h"
+#include <QStandardItemModel>
+#include <QComboBox>
+#include <QtDebug>
+
+
+namespace QmlDesigner {
+
+NumberSeriesAction::NumberSeriesAction(QObject *parent) :
+ QWidgetAction(parent),
+ m_comboBoxModelIndex(-1)
+{
+}
+
+void NumberSeriesAction::addEntry(const QString &text, const QVariant &value)
+{
+ if (m_comboBoxModel.isNull())
+ m_comboBoxModel = new QStandardItemModel(this);
+
+ QStandardItem *newItem = new QStandardItem(text);
+ newItem->setData(value);
+ m_comboBoxModel->appendRow(newItem);
+}
+
+QVariant NumberSeriesAction::currentValue() const
+{
+ return m_comboBoxModel->item(m_comboBoxModelIndex)->data();
+}
+
+QWidget *NumberSeriesAction::createWidget(QWidget *parent)
+{
+ QComboBox *comboBox = new QComboBox(parent);
+
+ comboBox->setModel(m_comboBoxModel.data());
+
+ comboBox->setCurrentIndex(m_comboBoxModelIndex);
+ connect(comboBox, SIGNAL(currentIndexChanged(int)), SLOT(emitValueChanged(int)));
+
+ return comboBox;
+}
+
+void NumberSeriesAction::emitValueChanged(int index)
+{
+ if (index == -1)
+ return;
+
+ m_comboBoxModelIndex = index;
+
+ emit valueChanged(m_comboBoxModel.data()->item(index)->data());
+}
+
+void NumberSeriesAction::setCurrentEntryIndex(int index)
+{
+ Q_ASSERT(index < m_comboBoxModel->rowCount());
+
+ m_comboBoxModelIndex = index;
+}
+
+} // namespace QKinecticDesigner
diff --git a/src/plugins/qmldesigner/components/formeditor/numberseriesaction.h b/src/plugins/qmldesigner/components/formeditor/numberseriesaction.h
new file mode 100644
index 0000000000..e6a8c82f16
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/numberseriesaction.h
@@ -0,0 +1,66 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef NUMBERSERIESACTION_H
+#define NUMBERSERIESACTION_H
+
+#include <QWidgetAction>
+
+class QStandardItemModel;
+
+namespace QmlDesigner {
+
+class NumberSeriesAction : public QWidgetAction
+{
+Q_OBJECT
+public:
+ explicit NumberSeriesAction(QObject *parent = 0);
+
+ void addEntry(const QString &text, const QVariant &value);
+ void setCurrentEntryIndex(int index);
+
+ QVariant currentValue() const;
+
+protected:
+ QWidget *createWidget(QWidget *parent);
+
+signals:
+ void valueChanged(const QVariant &value);
+
+private slots:
+ void emitValueChanged(int index);
+
+private:
+ QWeakPointer<QStandardItemModel> m_comboBoxModel;
+ int m_comboBoxModelIndex;
+};
+
+} // namespace QKinecticDesigner
+
+#endif // NUMBERSERIESACTION_H
diff --git a/src/plugins/qmldesigner/components/formeditor/onedimensionalcluster.cpp b/src/plugins/qmldesigner/components/formeditor/onedimensionalcluster.cpp
new file mode 100644
index 0000000000..e77afe8a14
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/onedimensionalcluster.cpp
@@ -0,0 +1,146 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "onedimensionalcluster.h"
+
+#include <QtDebug>
+
+namespace QmlDesigner {
+
+double sum(const QList<double> & list)
+{
+ double sum = 0.0;
+ for(QList<double>::const_iterator iterator = list.constBegin(); iterator != list.constEnd(); ++iterator)
+ {
+ sum += *iterator;
+ }
+
+ return sum;
+}
+
+OneDimensionalCluster::OneDimensionalCluster(const QList<double> & coordinateList )
+ : m_coordinateList(coordinateList)
+{
+}
+
+double OneDimensionalCluster::mean() const
+{
+ Q_ASSERT(!m_coordinateList.isEmpty());
+
+ if (m_coordinateList.size() == 1)
+ {
+ return m_coordinateList.first();
+ }
+
+ return sum(m_coordinateList) / m_coordinateList.size();
+}
+
+double OneDimensionalCluster::first() const
+{
+ Q_ASSERT(!m_coordinateList.isEmpty());
+
+ return m_coordinateList.first();
+}
+
+QList<OneDimensionalCluster> OneDimensionalCluster::createOneDimensionalClusterList(const QList<double> & oneDimensionalCoordinateList)
+{
+ QList<OneDimensionalCluster> oneDimensionalClusterList;
+ foreach (double coordinate, oneDimensionalCoordinateList)
+ {
+ QList<double> initialList;
+ initialList.append(coordinate);
+ OneDimensionalCluster cluster(initialList);
+ oneDimensionalClusterList.append(initialList);
+ }
+
+ return oneDimensionalClusterList;
+}
+
+QList<OneDimensionalCluster> OneDimensionalCluster::reduceOneDimensionalClusterList(const QList<OneDimensionalCluster> & unreducedClusterList, double maximumDistance)
+{
+ if (unreducedClusterList.size() < 2)
+ return unreducedClusterList;
+
+
+ QList<OneDimensionalCluster> workingList(unreducedClusterList);
+ QList<OneDimensionalCluster> reducedList;
+ while (true)
+ {
+ qSort(workingList);
+ reducedList.clear();
+ bool clusterMerged = false;
+ QListIterator<OneDimensionalCluster> clusterIterator(workingList);
+ while (clusterIterator.hasNext())
+ {
+ OneDimensionalCluster currentCluster = clusterIterator.next();
+ if (clusterIterator.hasNext())
+ {
+ OneDimensionalCluster nextCluster = clusterIterator.peekNext();
+ if ((nextCluster.mean() - currentCluster.mean()) < maximumDistance)
+ {
+ reducedList.append(currentCluster + nextCluster);
+ clusterIterator.next();
+ clusterMerged = true;
+ }
+ else
+ {
+ reducedList.append(currentCluster);
+ }
+ }
+ else
+ {
+ reducedList.append(currentCluster);
+ break;
+ }
+
+ }
+
+ workingList = reducedList;
+
+ if (clusterMerged == false)
+ break;
+ }
+
+
+ return reducedList;
+}
+
+QList<double> OneDimensionalCluster::reduceLines(const QList<double> & oneDimensionalCoordinateList, double maximumDistance)
+{
+ QList<OneDimensionalCluster> clusterList(createOneDimensionalClusterList(oneDimensionalCoordinateList));
+ clusterList = reduceOneDimensionalClusterList(clusterList, maximumDistance);
+
+ QList<double> lineList;
+ foreach (const OneDimensionalCluster &cluster, clusterList)
+ lineList.append(cluster.first());
+
+ return lineList;
+}
+
+}
diff --git a/src/plugins/qmldesigner/components/formeditor/onedimensionalcluster.h b/src/plugins/qmldesigner/components/formeditor/onedimensionalcluster.h
new file mode 100644
index 0000000000..dcf179eb18
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/onedimensionalcluster.h
@@ -0,0 +1,70 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef ONEDIMENSIONALCLUSTER_H
+#define ONEDIMENSIONALCLUSTER_H
+
+#include <QList>
+
+namespace QmlDesigner {
+
+class OneDimensionalCluster
+{
+ friend inline OneDimensionalCluster operator+(const OneDimensionalCluster & firstCluster, const OneDimensionalCluster & secondCluster);
+ friend inline bool operator < (const OneDimensionalCluster & firstCluster, const OneDimensionalCluster & secondCluster);
+public:
+ static QList<double> reduceLines(const QList<double> & oneDimensionalCoordinateList, double maximumDistance);
+
+private:
+
+ OneDimensionalCluster(const QList<double> & coordinateList );
+ double mean() const;
+ double first() const;
+
+
+
+ static QList<OneDimensionalCluster> createOneDimensionalClusterList(const QList<double> & oneDimensionalCoordinateList);
+ static QList<OneDimensionalCluster> reduceOneDimensionalClusterList(const QList<OneDimensionalCluster> & unreducedClusterList, double maximumDistance);
+
+ QList<double> m_coordinateList;
+};
+
+inline bool operator < (const OneDimensionalCluster & firstCluster, const OneDimensionalCluster & secondCluster)
+{
+ return firstCluster.mean() < secondCluster.mean();
+}
+
+inline OneDimensionalCluster operator+(const OneDimensionalCluster & firstCluster, const OneDimensionalCluster & secondCluster)
+{
+
+ return OneDimensionalCluster(firstCluster.m_coordinateList + secondCluster.m_coordinateList);
+}
+
+}
+#endif // ONEDIMENSIONALCLUSTER_H
diff --git a/src/plugins/qmldesigner/components/formeditor/resize_handle.png b/src/plugins/qmldesigner/components/formeditor/resize_handle.png
new file mode 100644
index 0000000000..2934f25b74
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/resize_handle.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/formeditor/resizecontroller.cpp b/src/plugins/qmldesigner/components/formeditor/resizecontroller.cpp
new file mode 100644
index 0000000000..9929df14ee
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/resizecontroller.cpp
@@ -0,0 +1,273 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "resizecontroller.h"
+
+#include "formeditoritem.h"
+#include "layeritem.h"
+
+#include <resizehandleitem.h>
+#include <QCursor>
+#include <QGraphicsScene>
+
+namespace QmlDesigner {
+
+
+
+ResizeControllerData::ResizeControllerData(LayerItem *layerItem, FormEditorItem *formEditorItem)
+ : layerItem(layerItem),
+ formEditorItem(formEditorItem),
+ topLeftItem(0),
+ topRightItem(0),
+ bottomLeftItem(0),
+ bottomRightItem(0),
+ topItem(0),
+ leftItem(0),
+ rightItem(0),
+ bottomItem(0)
+{
+
+}
+
+ResizeControllerData::ResizeControllerData(const ResizeControllerData &other)
+ : layerItem(other.layerItem),
+ formEditorItem(other.formEditorItem),
+ topLeftItem(other.topLeftItem),
+ topRightItem(other.topRightItem),
+ bottomLeftItem(other.bottomLeftItem),
+ bottomRightItem(other.bottomRightItem),
+ topItem(other.topItem),
+ leftItem(other.leftItem),
+ rightItem(other.rightItem),
+ bottomItem(other.bottomItem)
+{}
+
+ResizeControllerData::~ResizeControllerData()
+{
+ if (layerItem) {
+ layerItem->scene()->removeItem(topLeftItem);
+ layerItem->scene()->removeItem(topRightItem);
+ layerItem->scene()->removeItem(bottomLeftItem);
+ layerItem->scene()->removeItem(bottomRightItem);
+ layerItem->scene()->removeItem(topItem);
+ layerItem->scene()->removeItem(leftItem);
+ layerItem->scene()->removeItem(rightItem);
+ layerItem->scene()->removeItem(bottomItem);
+ }
+}
+
+
+ResizeController::ResizeController()
+ : m_data(new ResizeControllerData(0, 0))
+{
+
+}
+
+ResizeController::ResizeController(const QSharedPointer<ResizeControllerData> &data)
+ : m_data(data)
+{
+
+}
+
+ResizeController::ResizeController(LayerItem *layerItem, FormEditorItem *formEditorItem)
+ : m_data(new ResizeControllerData(layerItem, formEditorItem))
+{
+ m_data->topLeftItem = new ResizeHandleItem(layerItem, *this);
+ m_data->topLeftItem->setZValue(302);
+ m_data->topLeftItem->setCursor(Qt::SizeFDiagCursor);
+
+ m_data->topRightItem = new ResizeHandleItem(layerItem, *this);
+ m_data->topRightItem->setZValue(301);
+ m_data->topRightItem->setCursor(Qt::SizeBDiagCursor);
+
+ m_data->bottomLeftItem = new ResizeHandleItem(layerItem, *this);
+ m_data->bottomLeftItem->setZValue(301);
+ m_data->bottomLeftItem->setCursor(Qt::SizeBDiagCursor);
+
+ m_data->bottomRightItem = new ResizeHandleItem(layerItem, *this);
+ m_data->bottomRightItem->setZValue(305);
+ m_data->bottomRightItem->setCursor(Qt::SizeFDiagCursor);
+
+ m_data->topItem = new ResizeHandleItem(layerItem, *this);
+ m_data->topItem->setZValue(300);
+ m_data->topItem->setCursor(Qt::SizeVerCursor);
+
+ m_data->leftItem = new ResizeHandleItem(layerItem, *this);
+ m_data->leftItem->setZValue(300);
+ m_data->leftItem->setCursor(Qt::SizeHorCursor);
+
+ m_data->rightItem = new ResizeHandleItem(layerItem, *this);
+ m_data->rightItem->setZValue(300);
+ m_data->rightItem->setCursor(Qt::SizeHorCursor);
+
+ m_data->bottomItem = new ResizeHandleItem(layerItem, *this);
+ m_data->bottomItem->setZValue(300);
+ m_data->bottomItem->setCursor(Qt::SizeVerCursor);
+
+ updatePosition();
+}
+
+
+bool ResizeController::isValid() const
+{
+ return m_data->formEditorItem != 0;
+}
+
+void ResizeController::show()
+{
+ m_data->topLeftItem->show();
+ m_data->topRightItem->show();
+ m_data->bottomLeftItem->show();
+ m_data->bottomRightItem->show();
+ m_data->topItem->show();
+ m_data->leftItem->show();
+ m_data->rightItem->show();
+ m_data->bottomItem->show();
+}
+void ResizeController::hide()
+{
+ m_data->topLeftItem->hide();
+ m_data->topRightItem->hide();
+ m_data->bottomLeftItem->hide();
+ m_data->bottomRightItem->hide();
+ m_data->topItem->hide();
+ m_data->leftItem->hide();
+ m_data->rightItem->hide();
+ m_data->bottomItem->hide();
+}
+
+
+static QPointF topCenter(const QRectF &rect)
+{
+ return QPointF(rect.center().x(), rect.top());
+}
+
+static QPointF leftCenter(const QRectF &rect)
+{
+ return QPointF(rect.left(), rect.center().y());
+}
+
+static QPointF rightCenter(const QRectF &rect)
+{
+ return QPointF(rect.right(), rect.center().y());
+}
+
+static QPointF bottomCenter(const QRectF &rect)
+{
+ return QPointF(rect.center().x(), rect.bottom());
+}
+
+
+void ResizeController::updatePosition()
+{
+ QRectF originalBoundingRect = m_data->formEditorItem->qmlItemNode().instanceBoundingRect();
+ QRectF boundingRect = m_data->formEditorItem->qmlItemNode().instanceBoundingRect().adjusted(0.49, 0.49, 0.49, 0.49);
+ QPointF topLeftPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(),
+ boundingRect.topLeft()));
+ QPointF topRightPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(),
+ boundingRect.topRight()));
+ QPointF bottomLeftPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(),
+ boundingRect.bottomLeft()));
+ QPointF bottomRightPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(),
+ boundingRect.bottomRight()));
+
+ QPointF topPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(),
+ topCenter(boundingRect)));
+ QPointF leftPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(),
+ leftCenter(boundingRect)));
+
+ QPointF rightPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(),
+ rightCenter(boundingRect)));
+ QPointF bottomPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(),
+ bottomCenter(boundingRect)));
+
+
+
+ m_data->topRightItem->setHandlePosition(topRightPointInLayerSpace, originalBoundingRect.topRight());
+ m_data->topLeftItem->setHandlePosition(topLeftPointInLayerSpace, originalBoundingRect.topLeft());
+ m_data->bottomLeftItem->setHandlePosition(bottomLeftPointInLayerSpace, originalBoundingRect.bottomLeft());
+ m_data->bottomRightItem->setHandlePosition(bottomRightPointInLayerSpace, originalBoundingRect.bottomRight());
+ m_data->topItem->setHandlePosition(topPointInLayerSpace, topCenter(originalBoundingRect));
+ m_data->leftItem->setHandlePosition(leftPointInLayerSpace, leftCenter(originalBoundingRect));
+ m_data->rightItem->setHandlePosition(rightPointInLayerSpace, rightCenter(originalBoundingRect));
+ m_data->bottomItem->setHandlePosition(bottomPointInLayerSpace, bottomCenter(originalBoundingRect));
+}
+
+
+FormEditorItem* ResizeController::formEditorItem() const
+{
+ return m_data->formEditorItem;
+}
+
+QWeakPointer<ResizeControllerData> ResizeController::weakPointer() const
+{
+ return m_data;
+}
+
+bool ResizeController::isTopLeftHandle(const ResizeHandleItem *handle) const
+{
+ return handle == m_data->topLeftItem;
+}
+
+bool ResizeController::isTopRightHandle(const ResizeHandleItem *handle) const
+{
+ return handle == m_data->topRightItem;
+}
+
+bool ResizeController::isBottomLeftHandle(const ResizeHandleItem *handle) const
+{
+ return handle == m_data->bottomLeftItem;
+}
+
+bool ResizeController::isBottomRightHandle(const ResizeHandleItem *handle) const
+{
+ return handle == m_data->bottomRightItem;
+}
+
+bool ResizeController::isTopHandle(const ResizeHandleItem *handle) const
+{
+ return handle == m_data->topItem;
+}
+
+bool ResizeController::isLeftHandle(const ResizeHandleItem *handle) const
+{
+ return handle == m_data->leftItem;
+}
+
+bool ResizeController::isRightHandle(const ResizeHandleItem *handle) const
+{
+ return handle == m_data->rightItem;
+}
+
+bool ResizeController::isBottomHandle(const ResizeHandleItem *handle) const
+{
+ return handle == m_data->bottomItem;
+}
+
+}
diff --git a/src/plugins/qmldesigner/components/formeditor/resizecontroller.h b/src/plugins/qmldesigner/components/formeditor/resizecontroller.h
new file mode 100644
index 0000000000..be1e44824a
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/resizecontroller.h
@@ -0,0 +1,104 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef RESIZECONTROLLER_H
+#define RESIZECONTROLLER_H
+
+#include <QWeakPointer>
+#include <QSharedPointer>
+
+
+namespace QmlDesigner {
+
+class FormEditorItem;
+class LayerItem;
+class ResizeHandleItem;
+
+
+class ResizeControllerData
+{
+public:
+ ResizeControllerData(LayerItem *layerItem,
+ FormEditorItem *formEditorItem);
+ ResizeControllerData(const ResizeControllerData &other);
+ ~ResizeControllerData();
+
+
+ QWeakPointer<LayerItem> layerItem;
+ FormEditorItem *formEditorItem;
+ ResizeHandleItem *topLeftItem;
+ ResizeHandleItem *topRightItem;
+ ResizeHandleItem *bottomLeftItem;
+ ResizeHandleItem *bottomRightItem;
+ ResizeHandleItem *topItem;
+ ResizeHandleItem *leftItem;
+ ResizeHandleItem *rightItem;
+ ResizeHandleItem *bottomItem;
+};
+
+
+
+
+class ResizeController
+{
+public:
+ friend class ResizeHandleItem;
+
+ ResizeController();
+ ResizeController(LayerItem *layerItem, FormEditorItem *formEditorItem);
+
+ void show();
+ void hide();
+
+ void updatePosition();
+
+ bool isValid() const;
+
+ FormEditorItem *formEditorItem() const;
+
+ bool isTopLeftHandle(const ResizeHandleItem *handle) const;
+ bool isTopRightHandle(const ResizeHandleItem *handle) const;
+ bool isBottomLeftHandle(const ResizeHandleItem *handle) const;
+ bool isBottomRightHandle(const ResizeHandleItem *handle) const;
+
+ bool isTopHandle(const ResizeHandleItem *handle) const;
+ bool isLeftHandle(const ResizeHandleItem *handle) const;
+ bool isRightHandle(const ResizeHandleItem *handle) const;
+ bool isBottomHandle(const ResizeHandleItem *handle) const;
+
+private: // functions
+ ResizeController(const QSharedPointer<ResizeControllerData> &data);
+ QWeakPointer<ResizeControllerData> weakPointer() const;
+private: // variables
+ QSharedPointer<ResizeControllerData> m_data;
+};
+
+}
+
+#endif // RESIZECONTROLLER_H
diff --git a/src/plugins/qmldesigner/components/formeditor/resizehandleitem.cpp b/src/plugins/qmldesigner/components/formeditor/resizehandleitem.cpp
new file mode 100644
index 0000000000..ae388cf2cd
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/resizehandleitem.cpp
@@ -0,0 +1,118 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "resizehandleitem.h"
+
+#include <formeditoritem.h>
+#include <QCursor>
+
+namespace QmlDesigner {
+
+ResizeHandleItem::ResizeHandleItem(QGraphicsItem *parent, const ResizeController &resizeController)
+ : QGraphicsPixmapItem(QPixmap(":/icon/handle/resize_handle.png"), parent),
+ m_resizeControllerData(resizeController.weakPointer())
+{
+ setShapeMode(QGraphicsPixmapItem::BoundingRectShape);
+ setOffset(-pixmap().rect().center());
+ setFlag(QGraphicsItem::ItemIsMovable, true);
+ setFlag(QGraphicsItem::ItemIgnoresTransformations, true);
+}
+
+void ResizeHandleItem::setHandlePosition(const QPointF & globalPosition, const QPointF & itemSpacePosition)
+{
+ m_itemSpacePosition = itemSpacePosition;
+ setPos(globalPosition);
+}
+
+QRectF ResizeHandleItem::boundingRect() const
+{
+ return QGraphicsPixmapItem::boundingRect().adjusted(-1, -1, 1, 1);
+}
+
+QPainterPath ResizeHandleItem::shape() const
+{
+ return QGraphicsItem::shape();
+}
+
+ResizeController ResizeHandleItem::resizeController() const
+{
+ Q_ASSERT(!m_resizeControllerData.isNull());
+ return ResizeController(m_resizeControllerData.toStrongRef());
+}
+
+ResizeHandleItem* ResizeHandleItem::fromGraphicsItem(QGraphicsItem *item)
+{
+ return qgraphicsitem_cast<ResizeHandleItem*>(item);
+}
+
+bool ResizeHandleItem::isTopLeftHandle() const
+{
+ return resizeController().isTopLeftHandle(this);
+}
+
+bool ResizeHandleItem::isTopRightHandle() const
+{
+ return resizeController().isTopRightHandle(this);
+}
+
+bool ResizeHandleItem::isBottomLeftHandle() const
+{
+ return resizeController().isBottomLeftHandle(this);
+}
+
+bool ResizeHandleItem::isBottomRightHandle() const
+{
+ return resizeController().isBottomRightHandle(this);
+}
+
+bool ResizeHandleItem::isTopHandle() const
+{
+ return resizeController().isTopHandle(this);
+}
+
+bool ResizeHandleItem::isLeftHandle() const
+{
+ return resizeController().isLeftHandle(this);
+}
+
+bool ResizeHandleItem::isRightHandle() const
+{
+ return resizeController().isRightHandle(this);
+}
+
+bool ResizeHandleItem::isBottomHandle() const
+{
+ return resizeController().isBottomHandle(this);
+}
+
+QPointF ResizeHandleItem::itemSpacePosition() const
+{
+ return m_itemSpacePosition;
+}
+}
diff --git a/src/plugins/qmldesigner/components/formeditor/resizehandleitem.h b/src/plugins/qmldesigner/components/formeditor/resizehandleitem.h
new file mode 100644
index 0000000000..3177e3aa24
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/resizehandleitem.h
@@ -0,0 +1,84 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef RESIZEHANDLEITEM_H
+#define RESIZEHANDLEITEM_H
+
+#include <QGraphicsPixmapItem>
+
+#include "resizecontroller.h"
+
+namespace QmlDesigner {
+
+class ResizeHandleItem : public QGraphicsPixmapItem
+{
+public:
+ enum
+ {
+ Type = 0xEAEA
+ };
+
+
+ ResizeHandleItem(QGraphicsItem *parent, const ResizeController &resizeController);
+
+ void setHandlePosition(const QPointF & globalPosition, const QPointF & itemSpacePosition);
+
+ int type() const;
+ QRectF boundingRect() const;
+ QPainterPath shape() const;
+
+ ResizeController resizeController() const;
+
+ static ResizeHandleItem* fromGraphicsItem(QGraphicsItem *item);
+
+ bool isTopLeftHandle() const;
+ bool isTopRightHandle() const;
+ bool isBottomLeftHandle() const;
+ bool isBottomRightHandle() const;
+
+ bool isTopHandle() const;
+ bool isLeftHandle() const;
+ bool isRightHandle() const;
+ bool isBottomHandle() const;
+
+ QPointF itemSpacePosition() const;
+
+private:
+ QWeakPointer<ResizeControllerData> m_resizeControllerData;
+ QPointF m_itemSpacePosition;
+};
+
+inline int ResizeHandleItem::type() const
+{
+ return Type;
+}
+
+}
+
+#endif // RESIZEHANDLEITEM_H
diff --git a/src/plugins/qmldesigner/components/formeditor/resizeindicator.cpp b/src/plugins/qmldesigner/components/formeditor/resizeindicator.cpp
new file mode 100644
index 0000000000..9add9a65c7
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/resizeindicator.cpp
@@ -0,0 +1,91 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "resizeindicator.h"
+
+#include "formeditoritem.h"
+
+namespace QmlDesigner {
+
+ResizeIndicator::ResizeIndicator(LayerItem *layerItem)
+ : m_layerItem(layerItem)
+{
+ Q_ASSERT(layerItem);
+}
+
+ResizeIndicator::~ResizeIndicator()
+{
+ m_itemControllerHash.clear();
+}
+
+void ResizeIndicator::show()
+{
+ QHashIterator<FormEditorItem*, ResizeController> itemControllerIterator(m_itemControllerHash);
+ while (itemControllerIterator.hasNext()) {
+ ResizeController controller = itemControllerIterator.next().value();
+ controller.show();
+ }
+}
+void ResizeIndicator::hide()
+{
+ QHashIterator<FormEditorItem*, ResizeController> itemControllerIterator(m_itemControllerHash);
+ while (itemControllerIterator.hasNext()) {
+ ResizeController controller = itemControllerIterator.next().value();
+ controller.hide();
+ }
+}
+
+void ResizeIndicator::clear()
+{
+ m_itemControllerHash.clear();
+}
+
+void ResizeIndicator::setItems(const QList<FormEditorItem*> &itemList)
+{
+ clear();
+
+ foreach (FormEditorItem* item, itemList) {
+ if (item->qmlItemNode().isRootNode())
+ continue;
+ ResizeController controller(m_layerItem, item);
+ m_itemControllerHash.insert(item, controller);
+ }
+}
+
+void ResizeIndicator::updateItems(const QList<FormEditorItem*> &itemList)
+{
+ foreach (FormEditorItem* item, itemList) {
+ if (m_itemControllerHash.contains(item)) {
+ ResizeController controller(m_itemControllerHash.value(item));
+ controller.updatePosition();
+ }
+ }
+}
+
+}
diff --git a/src/plugins/qmldesigner/components/formeditor/resizeindicator.h b/src/plugins/qmldesigner/components/formeditor/resizeindicator.h
new file mode 100644
index 0000000000..e8881ec3e7
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/resizeindicator.h
@@ -0,0 +1,81 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef RESIZEINDICATOR_H
+#define RESIZEINDICATOR_H
+
+#include <QHash>
+#include <QPair>
+
+#include "resizecontroller.h"
+
+class QGraphicsRectItem;
+
+namespace QmlDesigner {
+
+class FormEditorItem;
+class LayerItem;
+
+class ResizeIndicator
+{
+public:
+ enum Orientation {
+ Top = 1,
+ Right = 2,
+ Bottom = 4,
+ Left = 8
+ };
+
+ ResizeIndicator(LayerItem *layerItem);
+ ~ResizeIndicator();
+
+ void show();
+ void hide();
+
+ void clear();
+
+ void setItems(const QList<FormEditorItem*> &itemList);
+ void updateItems(const QList<FormEditorItem*> &itemList);
+
+//
+// QPair<FormEditorItem*,Orientation> pick(QGraphicsRectItem* pickedItem) const;
+//
+// void show();
+// void hide();
+
+
+
+private:
+ QHash<FormEditorItem*, ResizeController> m_itemControllerHash;
+
+ LayerItem *m_layerItem;
+};
+
+}
+#endif // SCALEINDICATOR_H
diff --git a/src/plugins/qmldesigner/components/formeditor/resizemanipulator.cpp b/src/plugins/qmldesigner/components/formeditor/resizemanipulator.cpp
new file mode 100644
index 0000000000..b0f2189646
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/resizemanipulator.cpp
@@ -0,0 +1,504 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "resizemanipulator.h"
+
+#include "formeditoritem.h"
+#include "formeditorscene.h"
+#include "qmlanchors.h"
+#include <QtDebug>
+#include <model.h>
+#include "mathutils.h"
+
+#include <limits>
+
+namespace QmlDesigner {
+
+ResizeManipulator::ResizeManipulator(LayerItem *layerItem, FormEditorView *view)
+ : m_view(view),
+ m_beginTopMargin(0.0),
+ m_beginLeftMargin(0.0),
+ m_beginRightMargin(0.0),
+ m_beginBottomMargin(0.0),
+ m_layerItem(layerItem),
+ m_resizeHandle(0)
+{
+}
+
+ResizeManipulator::~ResizeManipulator()
+{
+ deleteSnapLines();
+}
+
+void ResizeManipulator::setHandle(ResizeHandleItem *resizeHandle)
+{
+ Q_ASSERT(resizeHandle);
+ m_resizeHandle = resizeHandle;
+ m_resizeController = resizeHandle->resizeController();
+ m_snapper.setContainerFormEditorItem(m_resizeController.formEditorItem()->parentItem());
+ m_snapper.setTransformtionSpaceFormEditorItem(m_resizeController.formEditorItem());
+ Q_ASSERT(m_resizeController.isValid());
+}
+
+void ResizeManipulator::removeHandle()
+{
+ m_resizeController = ResizeController();
+ m_resizeHandle = 0;
+}
+
+void ResizeManipulator::begin(const QPointF &/*beginPoint*/)
+{
+ if (m_resizeController.isValid()) {
+ m_beginBoundingRect = m_resizeController.formEditorItem()->qmlItemNode().instanceBoundingRect();
+ m_beginToSceneTransform = m_resizeController.formEditorItem()->qmlItemNode().instanceSceneTransform();
+ m_beginFromSceneTransform = m_beginToSceneTransform.inverted();
+ m_beginToParentTransform = m_resizeController.formEditorItem()->qmlItemNode().instanceTransform();
+ m_rewriterTransaction = m_view->beginRewriterTransaction();
+ m_snapper.updateSnappingLines(m_resizeController.formEditorItem());
+ m_beginBottomRightPoint = m_beginToParentTransform.map(m_resizeController.formEditorItem()->qmlItemNode().instanceBoundingRect().bottomRight());
+
+ QmlAnchors anchors(m_resizeController.formEditorItem()->qmlItemNode().anchors());
+ m_beginTopMargin = anchors.instanceMargin(AnchorLine::Top);
+ m_beginLeftMargin = anchors.instanceMargin(AnchorLine::Left);
+ m_beginRightMargin = anchors.instanceMargin(AnchorLine::Right);
+ m_beginBottomMargin = anchors.instanceMargin(AnchorLine::Bottom);
+ }
+}
+
+//static QSizeF mapSizeToParent(const QSizeF &size, QGraphicsItem *item)
+//{
+// QPointF sizeAsPoint(size.width(), size.height());
+// sizeAsPoint = item->mapToParent(sizeAsPoint);
+// return QSizeF(sizeAsPoint.x(), sizeAsPoint.y());
+//}
+
+void ResizeManipulator::update(const QPointF& updatePoint, Snapping useSnapping)
+{
+ const double minimumWidth = 15.0;
+ const double minimumHeight = 15.0;
+
+ deleteSnapLines();
+
+ if (m_resizeController.isValid()) {
+
+ FormEditorItem *formEditorItem = m_resizeController.formEditorItem();
+ FormEditorItem *containerItem = m_snapper.containerFormEditorItem();
+
+ if (!containerItem)
+ return;
+
+ QPointF updatePointInLocalSpace = m_beginFromSceneTransform.map(updatePoint);
+ QmlAnchors anchors(formEditorItem->qmlItemNode().anchors());
+
+ QRectF boundingRect(m_beginBoundingRect);
+ if (m_resizeHandle->isBottomRightHandle()) {
+ boundingRect.setBottomRight(updatePointInLocalSpace);
+
+ if (useSnapping == UseSnapping) {
+ double rightOffset = m_snapper.snapRightOffset(boundingRect);
+ if (rightOffset < std::numeric_limits<double>::max())
+ updatePointInLocalSpace.rx() -= rightOffset;
+
+ double bottomOffset = m_snapper.snapBottomOffset(boundingRect);
+ if (bottomOffset < std::numeric_limits<double>::max())
+ updatePointInLocalSpace.ry() -= bottomOffset;
+ }
+ boundingRect.setBottomRight(updatePointInLocalSpace);
+
+ if (anchors.instanceHasAnchor(AnchorLine::HorizontalCenter)) {
+ boundingRect.setLeft(boundingRect.left() - (updatePointInLocalSpace.x() - m_beginBoundingRect.right()));
+ }
+
+ if (anchors.instanceHasAnchor(AnchorLine::VerticalCenter)) {
+ boundingRect.setTop(boundingRect.top() - (updatePointInLocalSpace.y() - m_beginBoundingRect.bottom()));
+ }
+
+ if (boundingRect.width() < minimumWidth)
+ boundingRect.setWidth(minimumWidth);
+ if (boundingRect.height() < minimumHeight)
+ boundingRect.setHeight(minimumHeight);
+
+ formEditorItem->qmlItemNode().setSize(boundingRect.size());
+
+
+ if (anchors.instanceHasAnchor(AnchorLine::Bottom)) {
+ anchors.setMargin(AnchorLine::Bottom,
+ m_beginBottomMargin - (m_beginToParentTransform.map(boundingRect.bottomRight()) - m_beginBottomRightPoint).y());
+ }
+
+ if (anchors.instanceHasAnchor(AnchorLine::Right)) {
+ anchors.setMargin(AnchorLine::Right,
+ m_beginRightMargin - (m_beginToParentTransform.map(boundingRect.bottomRight()) - m_beginBottomRightPoint).x());
+ }
+ } else if (m_resizeHandle->isTopLeftHandle()) {
+ boundingRect.setTopLeft(updatePointInLocalSpace);
+
+ if (useSnapping == UseSnapping) {
+ double leftOffset = m_snapper.snapLeftOffset(boundingRect);
+ if (leftOffset < std::numeric_limits<double>::max())
+ updatePointInLocalSpace.rx() -= leftOffset;
+
+ double topOffset = m_snapper.snapTopOffset(boundingRect);
+ if (topOffset < std::numeric_limits<double>::max())
+ updatePointInLocalSpace.ry() -= topOffset;
+ }
+ boundingRect.setTopLeft(updatePointInLocalSpace);
+
+ if (anchors.instanceHasAnchor(AnchorLine::HorizontalCenter)) {
+ boundingRect.setRight(boundingRect.right() - (updatePointInLocalSpace.x() - m_beginBoundingRect.left()));
+ }
+
+ if (anchors.instanceHasAnchor(AnchorLine::VerticalCenter)) {
+ boundingRect.setBottom(boundingRect.bottom() - (updatePointInLocalSpace.y() - m_beginBoundingRect.top()));
+ }
+
+
+ if (boundingRect.width() < minimumWidth)
+ boundingRect.setLeft(boundingRect.left() - minimumWidth + boundingRect.width());
+ if (boundingRect.height() < minimumHeight)
+ boundingRect.setTop(boundingRect.top() - minimumHeight + boundingRect.height());
+
+ formEditorItem->qmlItemNode().setSize(boundingRect.size());
+ formEditorItem->qmlItemNode().setPosition(m_beginToParentTransform.map(boundingRect.topLeft()));
+
+
+ if (anchors.instanceHasAnchor(AnchorLine::Top)) {
+ anchors.setMargin(AnchorLine::Top,
+ m_beginTopMargin + (-m_beginToParentTransform.map(m_beginBoundingRect.topLeft()).y() + m_beginToParentTransform.map(boundingRect.topLeft()).y()));
+ }
+
+ if (anchors.instanceHasAnchor(AnchorLine::Left)) {
+ anchors.setMargin(AnchorLine::Left,
+ m_beginLeftMargin + (-m_beginToParentTransform.map(m_beginBoundingRect.topLeft()).x() + m_beginToParentTransform.map(boundingRect.topLeft()).x()));
+ }
+
+ } else if (m_resizeHandle->isTopRightHandle()) {
+ boundingRect.setTopRight(updatePointInLocalSpace);
+
+ if (useSnapping == UseSnapping) {
+ double rightOffset = m_snapper.snapRightOffset(boundingRect);
+ if (rightOffset < std::numeric_limits<double>::max())
+ updatePointInLocalSpace.rx() -= rightOffset;
+
+ double topOffset = m_snapper.snapTopOffset(boundingRect);
+ if (topOffset < std::numeric_limits<double>::max())
+ updatePointInLocalSpace.ry() -= topOffset;
+ }
+ boundingRect.setTopRight(updatePointInLocalSpace);
+
+ if (anchors.instanceHasAnchor(AnchorLine::HorizontalCenter)) {
+ boundingRect.setLeft(boundingRect.left() - (updatePointInLocalSpace.x() - m_beginBoundingRect.right()));
+ }
+
+ if (anchors.instanceHasAnchor(AnchorLine::VerticalCenter)) {
+ boundingRect.setBottom(boundingRect.bottom() - (updatePointInLocalSpace.y() - m_beginBoundingRect.top()));
+ }
+
+ if (boundingRect.height() < minimumHeight)
+ boundingRect.setTop(boundingRect.top() - minimumHeight + boundingRect.height());
+ if (boundingRect.width() < minimumWidth)
+ boundingRect.setWidth(minimumWidth);
+
+ formEditorItem->qmlItemNode().setSize(boundingRect.size());
+ formEditorItem->qmlItemNode().setPosition(m_beginToParentTransform.map(boundingRect.topLeft()));
+
+ if (anchors.instanceHasAnchor(AnchorLine::Top)) {
+ anchors.setMargin(AnchorLine::Top,
+ m_beginTopMargin + (-m_beginToParentTransform.map(m_beginBoundingRect.topLeft()).y() + m_beginToParentTransform.map(boundingRect.topLeft()).y()));
+ }
+
+ if (anchors.instanceHasAnchor(AnchorLine::Right)) {
+ anchors.setMargin(AnchorLine::Right,
+ m_beginRightMargin - (m_beginToParentTransform.map(boundingRect.bottomRight()) - m_beginBottomRightPoint).x());
+ }
+ } else if (m_resizeHandle->isBottomLeftHandle()) {
+ boundingRect.setBottomLeft(updatePointInLocalSpace);
+
+ if (useSnapping == UseSnapping) {
+ double leftOffset = m_snapper.snapLeftOffset(boundingRect);
+ if (leftOffset < std::numeric_limits<double>::max())
+ updatePointInLocalSpace.rx() -= leftOffset;
+
+ double bottomOffset = m_snapper.snapBottomOffset(boundingRect);
+ if (bottomOffset < std::numeric_limits<double>::max())
+ updatePointInLocalSpace.ry() -= bottomOffset;
+ }
+
+ boundingRect.setBottomLeft(updatePointInLocalSpace);
+
+ if (anchors.instanceHasAnchor(AnchorLine::HorizontalCenter)) {
+ boundingRect.setRight(boundingRect.right() - (updatePointInLocalSpace.x() - m_beginBoundingRect.left()));
+ }
+
+ if (anchors.instanceHasAnchor(AnchorLine::VerticalCenter)) {
+ boundingRect.setTop(boundingRect.top() - (updatePointInLocalSpace.y() - m_beginBoundingRect.bottom()));
+ }
+
+ if (boundingRect.height() < minimumHeight)
+ boundingRect.setHeight(minimumHeight);
+ if (boundingRect.width() < minimumWidth)
+ boundingRect.setLeft(boundingRect.left() - minimumWidth + boundingRect.width());
+
+ formEditorItem->qmlItemNode().setSize(boundingRect.size());
+ formEditorItem->qmlItemNode().setPosition(m_beginToParentTransform.map(boundingRect.topLeft()));
+
+ if (anchors.instanceHasAnchor(AnchorLine::Left)) {
+ anchors.setMargin(AnchorLine::Left,
+ m_beginLeftMargin + (-m_beginToParentTransform.map(m_beginBoundingRect.topLeft()).x() + m_beginToParentTransform.map(boundingRect.topLeft()).x()));
+ }
+
+ if (anchors.instanceHasAnchor(AnchorLine::Bottom)) {
+ anchors.setMargin(AnchorLine::Bottom,
+ m_beginBottomMargin - (m_beginToParentTransform.map(boundingRect.bottomRight()) - m_beginBottomRightPoint).y());
+ }
+ } else if (m_resizeHandle->isBottomHandle()) {
+ boundingRect.setBottom(updatePointInLocalSpace.y());
+
+ if (useSnapping == UseSnapping) {
+ double bottomOffset = m_snapper.snapBottomOffset(boundingRect);
+ if (bottomOffset < std::numeric_limits<double>::max())
+ updatePointInLocalSpace.ry() -= bottomOffset;
+ }
+
+ boundingRect.setBottom(updatePointInLocalSpace.y());
+
+ if (anchors.instanceHasAnchor(AnchorLine::VerticalCenter)) {
+ boundingRect.setTop(boundingRect.top() - (updatePointInLocalSpace.y() - m_beginBoundingRect.bottom()));
+ }
+
+ if (boundingRect.height() < minimumHeight)
+ boundingRect.setHeight(minimumHeight);
+
+ formEditorItem->qmlItemNode().setSize(boundingRect.size());
+
+ if (anchors.instanceHasAnchor(AnchorLine::Bottom)) {
+ anchors.setMargin(AnchorLine::Bottom,
+ m_beginBottomMargin - (m_beginToParentTransform.map(boundingRect.bottomRight()) - m_beginBottomRightPoint).y());
+ }
+ } else if (m_resizeHandle->isTopHandle()) {
+ boundingRect.setTop(updatePointInLocalSpace.y());
+
+ if (useSnapping == UseSnapping) {
+ double topOffset = m_snapper.snapTopOffset(boundingRect);
+ if (topOffset < std::numeric_limits<double>::max())
+ updatePointInLocalSpace.ry() -= topOffset;
+ }
+
+ boundingRect.setTop(updatePointInLocalSpace.y());
+
+ if (anchors.instanceHasAnchor(AnchorLine::VerticalCenter)) {
+ boundingRect.setBottom(boundingRect.bottom() - (updatePointInLocalSpace.y() - m_beginBoundingRect.top()));
+ }
+
+ if (boundingRect.height() < minimumHeight)
+ boundingRect.setTop(boundingRect.top() - minimumHeight + boundingRect.height());
+
+ formEditorItem->qmlItemNode().setSize(boundingRect.size());
+ formEditorItem->qmlItemNode().setPosition(m_beginToParentTransform.map(boundingRect.topLeft()));
+
+ if (anchors.instanceHasAnchor(AnchorLine::Top)) {
+ anchors.setMargin(AnchorLine::Top,
+ m_beginTopMargin + (-m_beginToParentTransform.map(m_beginBoundingRect.topLeft()).y() + m_beginToParentTransform.map(boundingRect.topLeft()).y()));
+ }
+ } else if (m_resizeHandle->isRightHandle()) {
+ boundingRect.setRight(updatePointInLocalSpace.x());
+
+ if (useSnapping == UseSnapping) {
+ double rightOffset = m_snapper.snapRightOffset(boundingRect);
+ if (rightOffset < std::numeric_limits<double>::max())
+ updatePointInLocalSpace.rx() -= rightOffset;
+ }
+
+ boundingRect.setRight(updatePointInLocalSpace.x());
+
+ if (anchors.instanceHasAnchor(AnchorLine::HorizontalCenter)) {
+ boundingRect.setLeft(boundingRect.left() - (updatePointInLocalSpace.x() - m_beginBoundingRect.right()));
+ }
+
+ if (boundingRect.width() < minimumWidth)
+ boundingRect.setWidth(minimumWidth);
+
+ formEditorItem->qmlItemNode().setSize(boundingRect.size());
+
+
+ if (anchors.instanceHasAnchor(AnchorLine::Right)) {
+ anchors.setMargin(AnchorLine::Right,
+ m_beginRightMargin - (m_beginToParentTransform.map(boundingRect.bottomRight()) - m_beginBottomRightPoint).x());
+ }
+ } else if (m_resizeHandle->isLeftHandle()) {
+ boundingRect.setLeft(updatePointInLocalSpace.x());
+
+ if (useSnapping == UseSnapping) {
+ double leftOffset = m_snapper.snapLeftOffset(boundingRect);
+ if (leftOffset < std::numeric_limits<double>::max())
+ updatePointInLocalSpace.rx() -= leftOffset;
+ }
+
+ boundingRect.setLeft(updatePointInLocalSpace.x());
+
+ if (anchors.instanceHasAnchor(AnchorLine::HorizontalCenter)) {
+ boundingRect.setRight(boundingRect.right() - (updatePointInLocalSpace.x() - m_beginBoundingRect.left()));
+ }
+
+ if (boundingRect.width() < minimumWidth)
+ boundingRect.setLeft(boundingRect.left() - minimumWidth + boundingRect.width());
+
+ formEditorItem->qmlItemNode().setSize(boundingRect.size());
+ formEditorItem->qmlItemNode().setPosition(m_beginToParentTransform.map(boundingRect.topLeft()));
+
+ if (anchors.instanceHasAnchor(AnchorLine::Left)) {
+ anchors.setMargin(AnchorLine::Left,
+ m_beginLeftMargin + (-m_beginToParentTransform.map(m_beginBoundingRect.topLeft()).x() + m_beginToParentTransform.map(boundingRect.topLeft()).x()));
+ }
+ }
+
+ if (useSnapping == UseSnapping)
+ m_graphicsLineList = m_snapper.generateSnappingLines(boundingRect,
+ m_layerItem.data(),
+ m_beginToSceneTransform);
+ }
+}
+
+void ResizeManipulator::end()
+{
+ m_rewriterTransaction.commit();
+ clear();
+ removeHandle();
+}
+
+void ResizeManipulator::moveBy(double deltaX, double deltaY)
+{
+ if (resizeHandle()) {
+ QmlItemNode qmlItemNode(m_resizeController.formEditorItem()->qmlItemNode());
+ QmlAnchors anchors(qmlItemNode.anchors());
+
+ if (m_resizeController.isLeftHandle(resizeHandle())
+ || m_resizeController.isTopLeftHandle(resizeHandle())
+ || m_resizeController.isBottomLeftHandle(resizeHandle())) {
+ qmlItemNode.setVariantProperty("x", round((qmlItemNode.instanceValue("x").toDouble() + deltaX), 4));
+ qmlItemNode.setVariantProperty("width", round(qmlItemNode.instanceValue("width").toDouble() - deltaX, 4));
+
+
+ if (anchors.instanceHasAnchor(AnchorLine::Left)) {
+ anchors.setMargin(AnchorLine::Left, anchors.instanceMargin(AnchorLine::Left) + deltaX);
+ }
+
+ if (anchors.instanceHasAnchor(AnchorLine::HorizontalCenter)) {
+ qmlItemNode.setVariantProperty("width", round(qmlItemNode.instanceValue("width").toDouble() - (deltaX * 2), 4));
+ }
+ }
+
+ if (m_resizeController.isRightHandle(resizeHandle())
+ || m_resizeController.isTopRightHandle(resizeHandle())
+ || m_resizeController.isBottomRightHandle(resizeHandle())) {
+ qmlItemNode.setVariantProperty("width", round(qmlItemNode.instanceValue("width").toDouble() + deltaX, 4));
+
+ if (anchors.instanceHasAnchor(AnchorLine::Right)) {
+ anchors.setMargin(AnchorLine::Right, round(anchors.instanceMargin(AnchorLine::Right) - deltaX, 4));
+ }
+
+ if (anchors.instanceHasAnchor(AnchorLine::HorizontalCenter)) {
+ qmlItemNode.setVariantProperty("width", round(qmlItemNode.instanceValue("width").toDouble() + (deltaX * 2), 4));
+ }
+ }
+
+
+ if (m_resizeController.isTopHandle(resizeHandle())
+ || m_resizeController.isTopLeftHandle(resizeHandle())
+ || m_resizeController.isTopRightHandle(resizeHandle())) {
+ qmlItemNode.setVariantProperty("y", round(qmlItemNode.instanceValue("y").toDouble() + deltaY, 4));
+ qmlItemNode.setVariantProperty("height", round(qmlItemNode.instanceValue("height").toDouble() - deltaY, 4));
+
+ if (anchors.instanceHasAnchor(AnchorLine::Top)) {
+ anchors.setMargin(AnchorLine::Top, anchors.instanceMargin(AnchorLine::Top) + deltaY);
+ }
+
+ if (anchors.instanceHasAnchor(AnchorLine::VerticalCenter)) {
+ qmlItemNode.setVariantProperty("height", round(qmlItemNode.instanceValue("height").toDouble() - (deltaY * 2), 4));
+ }
+ }
+
+ if (m_resizeController.isBottomHandle(resizeHandle())
+ || m_resizeController.isBottomLeftHandle(resizeHandle())
+ || m_resizeController.isBottomRightHandle(resizeHandle())) {
+ qmlItemNode.setVariantProperty("height", round(qmlItemNode.instanceValue("height").toDouble() + deltaY, 4));
+
+ if (anchors.instanceHasAnchor(AnchorLine::Bottom)) {
+ anchors.setMargin(AnchorLine::Bottom, anchors.instanceMargin(AnchorLine::Bottom) - deltaY);
+ }
+
+ if (anchors.instanceHasAnchor(AnchorLine::VerticalCenter)) {
+ qmlItemNode.setVariantProperty("height", round(qmlItemNode.instanceValue("height").toDouble() + (deltaY * 2), 4));
+ }
+ }
+
+ }
+}
+
+bool ResizeManipulator::isInvalidSize(const QSizeF & size)
+{
+ if (size.width() < 15 || size.height() < 15)
+ return true;
+
+ return false;
+}
+
+void ResizeManipulator::deleteSnapLines()
+{
+ if (m_layerItem) {
+ foreach (QGraphicsItem *item, m_graphicsLineList)
+ m_layerItem->scene()->removeItem(item);
+ }
+
+ m_graphicsLineList.clear();
+ m_view->scene()->update();
+}
+
+ResizeHandleItem *ResizeManipulator::resizeHandle()
+{
+ return m_resizeHandle;
+}
+
+void ResizeManipulator::clear()
+{
+ m_rewriterTransaction.commit();
+
+ deleteSnapLines();
+ m_beginBoundingRect = QRectF();
+ m_beginFromSceneTransform = QTransform();
+ m_beginToSceneTransform = QTransform();
+ m_beginToParentTransform = QTransform();
+ m_beginTopMargin = 0.0;
+ m_beginLeftMargin = 0.0;
+ m_beginRightMargin = 0.0;
+ m_beginBottomMargin = 0.0;
+ removeHandle();
+}
+
+}
diff --git a/src/plugins/qmldesigner/components/formeditor/resizemanipulator.h b/src/plugins/qmldesigner/components/formeditor/resizemanipulator.h
new file mode 100644
index 0000000000..913966537f
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/resizemanipulator.h
@@ -0,0 +1,91 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef RESIZEMANIPULATOR_H
+#define RESIZEMANIPULATOR_H
+
+#include <QWeakPointer>
+#include "resizehandleitem.h"
+#include <snapper.h>
+#include "rewritertransaction.h"
+#include "formeditorview.h"
+
+namespace QmlDesigner {
+
+class ResizeHandleItem;
+class Model;
+
+class ResizeManipulator
+{
+public:
+ enum Snapping {
+ UseSnapping,
+ NoSnapping
+ };
+
+ ResizeManipulator(LayerItem *layerItem, FormEditorView *view);
+ ~ResizeManipulator();
+
+ void setHandle(ResizeHandleItem *resizeHandle);
+ void removeHandle();
+
+ void begin(const QPointF& beginPoint);
+ void update(const QPointF& updatePoint, Snapping useSnapping);
+ void end();
+
+ void moveBy(double deltaX, double deltaY);
+
+ void clear();
+
+protected:
+ bool isInvalidSize(const QSizeF & size);
+ void deleteSnapLines();
+ ResizeHandleItem *resizeHandle();
+
+private:
+ Snapper m_snapper;
+ QWeakPointer<FormEditorView> m_view;
+ QList<QGraphicsItem*> m_graphicsLineList;
+ ResizeController m_resizeController; // hold the controller so that the handle cant be deleted
+ QTransform m_beginFromSceneTransform;
+ QTransform m_beginToSceneTransform;
+ QTransform m_beginToParentTransform;
+ QRectF m_beginBoundingRect;
+ QPointF m_beginBottomRightPoint;
+ double m_beginTopMargin;
+ double m_beginLeftMargin;
+ double m_beginRightMargin;
+ double m_beginBottomMargin;
+ QWeakPointer<LayerItem> m_layerItem;
+ ResizeHandleItem *m_resizeHandle;
+ RewriterTransaction m_rewriterTransaction;
+};
+
+}
+#endif // RESIZEMANIPULATOR_H
diff --git a/src/plugins/qmldesigner/components/formeditor/resizetool.cpp b/src/plugins/qmldesigner/components/formeditor/resizetool.cpp
new file mode 100644
index 0000000000..bd7d5157e1
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/resizetool.cpp
@@ -0,0 +1,177 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "resizetool.h"
+
+#include "formeditorscene.h"
+#include "formeditorview.h"
+
+#include "resizehandleitem.h"
+
+#include <QApplication>
+#include <QGraphicsSceneMouseEvent>
+#include <QtDebug>
+
+namespace QmlDesigner {
+
+ResizeTool::ResizeTool(FormEditorView *editorView)
+ : AbstractFormEditorTool(editorView),
+ m_selectionIndicator(editorView->scene()->manipulatorLayerItem()),
+ m_resizeIndicator(editorView->scene()->manipulatorLayerItem()),
+ m_resizeManipulator(editorView->scene()->manipulatorLayerItem(), editorView)
+{
+}
+
+
+ResizeTool::~ResizeTool()
+{
+}
+
+void ResizeTool::mousePressEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event)
+{
+ if (itemList.isEmpty())
+ return;
+
+ ResizeHandleItem *resizeHandle = ResizeHandleItem::fromGraphicsItem(itemList.first());
+ if (resizeHandle) {
+ m_resizeManipulator.setHandle(resizeHandle);
+ m_resizeManipulator.begin(event->scenePos());
+ m_selectionIndicator.hide();
+ m_resizeIndicator.hide();
+ }
+}
+
+void ResizeTool::mouseMoveEvent(const QList<QGraphicsItem*> &,
+ QGraphicsSceneMouseEvent *event)
+{
+
+
+ ResizeManipulator::Snapping useSnapping = ResizeManipulator::NoSnapping;
+ if (event->modifiers().testFlag(Qt::ControlModifier) != view()->isSnapButtonChecked())
+ useSnapping = ResizeManipulator::UseSnapping;
+
+ m_resizeManipulator.update(event->scenePos(), useSnapping);
+}
+
+void ResizeTool::hoverMoveEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent * /*event*/)
+{
+ if (itemList.isEmpty())
+ return;
+ ResizeHandleItem* resizeHandle = ResizeHandleItem::fromGraphicsItem(itemList.first());
+ if (resizeHandle) {
+ m_resizeManipulator.setHandle(resizeHandle);
+ } else {
+ view()->changeToSelectionTool();
+ return;
+ }
+}
+
+void ResizeTool::mouseReleaseEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent * /*event*/)
+{
+ if (itemList.isEmpty())
+ return;
+
+ m_selectionIndicator.show();
+ m_resizeIndicator.show();
+ m_resizeManipulator.end();
+}
+
+void ResizeTool::mouseDoubleClickEvent(const QList<QGraphicsItem*> & /*itemList*/,
+ QGraphicsSceneMouseEvent * /*event*/)
+{
+}
+
+void ResizeTool::keyPressEvent(QKeyEvent * event)
+{
+ switch(event->key()) {
+ case Qt::Key_Shift:
+ case Qt::Key_Alt:
+ case Qt::Key_Control:
+ case Qt::Key_AltGr:
+ event->setAccepted(false);
+ return;
+ }
+
+ double moveStep = 1.0;
+
+ if (event->modifiers().testFlag(Qt::ShiftModifier))
+ moveStep = 10.0;
+
+ switch(event->key()) {
+ case Qt::Key_Left: m_resizeManipulator.moveBy(-moveStep, 0.0); break;
+ case Qt::Key_Right: m_resizeManipulator.moveBy(moveStep, 0.0); break;
+ case Qt::Key_Up: m_resizeManipulator.moveBy(0.0, -moveStep); break;
+ case Qt::Key_Down: m_resizeManipulator.moveBy(0.0, moveStep); break;
+ }
+
+}
+
+void ResizeTool::keyReleaseEvent(QKeyEvent * keyEvent)
+{
+ switch(keyEvent->key()) {
+ case Qt::Key_Shift:
+ case Qt::Key_Alt:
+ case Qt::Key_Control:
+ case Qt::Key_AltGr:
+ keyEvent->setAccepted(false);
+ return;
+ }
+
+// if (!keyEvent->isAutoRepeat())
+// m_resizeManipulator.clear();
+}
+
+void ResizeTool::itemsAboutToRemoved(const QList<FormEditorItem*> & /*itemList*/)
+{
+
+}
+
+void ResizeTool::selectedItemsChanged(const QList<FormEditorItem*> & /*itemList*/)
+{
+ m_selectionIndicator.setItems(items());
+ m_resizeIndicator.setItems(items());
+}
+
+void ResizeTool::clear()
+{
+ m_selectionIndicator.clear();
+ m_resizeIndicator.clear();
+ m_resizeManipulator.clear();
+}
+
+void ResizeTool::formEditorItemsChanged(const QList<FormEditorItem*> &itemList)
+{
+ m_selectionIndicator.updateItems(itemList);
+ m_resizeIndicator.updateItems(itemList);
+}
+
+}
diff --git a/src/plugins/qmldesigner/components/formeditor/resizetool.h b/src/plugins/qmldesigner/components/formeditor/resizetool.h
new file mode 100644
index 0000000000..f376748ac0
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/resizetool.h
@@ -0,0 +1,76 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef RESIZETOOL_H
+#define RESIZETOOL_H
+
+#include "abstractformeditortool.h"
+#include "selectionindicator.h"
+#include "resizeindicator.h"
+#include "resizemanipulator.h"
+
+
+namespace QmlDesigner {
+
+class ResizeTool : public AbstractFormEditorTool
+{
+public:
+ ResizeTool(FormEditorView* editorView);
+ ~ResizeTool();
+
+ void mousePressEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event);
+ void mouseMoveEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event);
+ void mouseDoubleClickEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event);
+ void hoverMoveEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event);
+ void keyPressEvent(QKeyEvent *event);
+ void keyReleaseEvent(QKeyEvent *keyEvent);
+
+ void itemsAboutToRemoved(const QList<FormEditorItem*> &itemList);
+
+ void selectedItemsChanged(const QList<FormEditorItem*> &itemList);
+
+ void clear();
+
+ void formEditorItemsChanged(const QList<FormEditorItem*> &itemList);
+
+private:
+ SelectionIndicator m_selectionIndicator;
+ ResizeIndicator m_resizeIndicator;
+ ResizeManipulator m_resizeManipulator;
+};
+
+}
+
+#endif // RESIZETOOL_H
diff --git a/src/plugins/qmldesigner/components/formeditor/rubberbandselectionmanipulator.cpp b/src/plugins/qmldesigner/components/formeditor/rubberbandselectionmanipulator.cpp
new file mode 100644
index 0000000000..f9ca6b0831
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/rubberbandselectionmanipulator.cpp
@@ -0,0 +1,153 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "rubberbandselectionmanipulator.h"
+
+#include "model.h"
+#include "formeditorscene.h"
+
+namespace QmlDesigner {
+
+RubberBandSelectionManipulator::RubberBandSelectionManipulator(LayerItem *layerItem, FormEditorView *editorView)
+ : m_selectionRectangleElement(layerItem),
+ m_editorView(editorView),
+ m_beginFormEditorItem(0),
+ m_isActive(false)
+{
+ m_selectionRectangleElement.hide();
+}
+
+void RubberBandSelectionManipulator::clear()
+{
+ m_selectionRectangleElement.clear();
+ m_isActive = false;
+ m_beginPoint = QPointF();
+ m_itemList.clear();
+ m_oldSelectionList.clear();
+}
+
+FormEditorItem *RubberBandSelectionManipulator::topFormEditorItem(const QList<QGraphicsItem*> &itemList)
+{
+ foreach (QGraphicsItem *item, itemList) {
+ FormEditorItem *formEditorItem = FormEditorItem::fromQGraphicsItem(item);
+
+ if (formEditorItem)
+ {
+ return formEditorItem;
+ }
+ }
+
+ return m_editorView->scene()->rootFormEditorItem();
+}
+
+void RubberBandSelectionManipulator::begin(const QPointF& beginPoint)
+{
+ m_beginPoint = beginPoint;
+ m_selectionRectangleElement.setRect(m_beginPoint, m_beginPoint);
+ m_selectionRectangleElement.show();
+ m_isActive = true;
+ m_beginFormEditorItem = topFormEditorItem(m_editorView->scene()->items(beginPoint));
+ m_oldSelectionList = m_editorView->selectedQmlItemNodes();
+}
+
+void RubberBandSelectionManipulator::update(const QPointF& updatePoint)
+{
+ m_selectionRectangleElement.setRect(m_beginPoint, updatePoint);
+}
+
+void RubberBandSelectionManipulator::end()
+{
+ m_oldSelectionList.clear();
+ m_selectionRectangleElement.hide();
+ m_isActive = false;
+}
+
+void RubberBandSelectionManipulator::select(SelectionType selectionType)
+{
+ if (!m_beginFormEditorItem)
+ return;
+
+ QList<QGraphicsItem*> itemList = m_editorView->scene()->items(m_selectionRectangleElement.rect(),
+ Qt::IntersectsItemBoundingRect);
+ QList<QmlItemNode> newNodeList;
+
+ foreach (QGraphicsItem* item, itemList)
+ {
+ FormEditorItem *formEditorItem = FormEditorItem::fromQGraphicsItem(item);
+
+ if (formEditorItem
+ && m_beginFormEditorItem->childItems().contains(formEditorItem)
+ && !formEditorItem->qmlItemNode().isRootNode())
+ {
+ newNodeList.append(formEditorItem->qmlItemNode());
+ }
+ }
+
+ if (newNodeList.isEmpty() && !m_beginFormEditorItem->qmlItemNode().isRootNode())
+ newNodeList.append(m_beginFormEditorItem->qmlItemNode());
+
+ QList<QmlItemNode> nodeList;
+
+ switch(selectionType) {
+ case AddToSelection: {
+ nodeList.append(m_oldSelectionList);
+ nodeList.append(newNodeList);
+ }
+ break;
+ case ReplaceSelection: {
+ nodeList.append(newNodeList);
+ }
+ break;
+ case RemoveFromSelection: {
+ QSet<QmlItemNode> oldSelectionSet(m_oldSelectionList.toSet());
+ QSet<QmlItemNode> newSelectionSet(newNodeList.toSet());
+ nodeList.append(oldSelectionSet.subtract(newSelectionSet).toList());
+ }
+ }
+
+ m_editorView->setSelectedQmlItemNodes(nodeList);
+}
+
+
+void RubberBandSelectionManipulator::setItems(const QList<FormEditorItem*> &itemList)
+{
+ m_itemList = itemList;
+}
+
+QPointF RubberBandSelectionManipulator::beginPoint() const
+{
+ return m_beginPoint;
+}
+
+bool RubberBandSelectionManipulator::isActive() const
+{
+ return m_isActive;
+}
+
+}
diff --git a/src/plugins/qmldesigner/components/formeditor/rubberbandselectionmanipulator.h b/src/plugins/qmldesigner/components/formeditor/rubberbandselectionmanipulator.h
new file mode 100644
index 0000000000..bd8d9b6b2a
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/rubberbandselectionmanipulator.h
@@ -0,0 +1,83 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef RUBBERBANDSELECTIONMANIPULATOR_H
+#define RUBBERBANDSELECTIONMANIPULATOR_H
+
+
+#include "selectionrectangle.h"
+#include "formeditorview.h"
+#include "formeditoritem.h"
+
+namespace QmlDesigner {
+
+
+class RubberBandSelectionManipulator
+{
+public:
+ enum SelectionType {
+ ReplaceSelection,
+ AddToSelection,
+ RemoveFromSelection
+ };
+
+
+ RubberBandSelectionManipulator(LayerItem *layerItem, FormEditorView *editorView);
+
+ void setItems(const QList<FormEditorItem*> &itemList);
+
+ void begin(const QPointF& beginPoint);
+ void update(const QPointF& updatePoint);
+ void end();
+
+ void clear();
+
+ void select(SelectionType selectionType);
+
+ QPointF beginPoint() const;
+
+ bool isActive() const;
+
+protected:
+ FormEditorItem *topFormEditorItem(const QList<QGraphicsItem*> &itemList);
+
+
+private:
+ QList<FormEditorItem*> m_itemList;
+ QList<QmlItemNode> m_oldSelectionList;
+ SelectionRectangle m_selectionRectangleElement;
+ QPointF m_beginPoint;
+ FormEditorView *m_editorView;
+ FormEditorItem *m_beginFormEditorItem;
+ bool m_isActive;
+};
+
+}
+
+#endif // RUBBERBANDSELECTIONMANIPULATOR_H
diff --git a/src/plugins/qmldesigner/components/formeditor/scaleitem.cpp b/src/plugins/qmldesigner/components/formeditor/scaleitem.cpp
new file mode 100644
index 0000000000..def9aeb5ee
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/scaleitem.cpp
@@ -0,0 +1,49 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "scaleitem.h"
+
+#include "layeritem.h"
+
+namespace QmlDesigner {
+
+ScaleItem::ScaleItem(LayerItem *layerItem, ScaleIndicator *indicator)
+ : QGraphicsRectItem(layerItem),
+ m_indicator(indicator)
+{
+ Q_ASSERT(layerItem);
+ Q_ASSERT(indicator);
+}
+
+ScaleIndicator* ScaleItem::indicator() const
+{
+ return m_indicator;
+}
+
+}
diff --git a/src/plugins/qmldesigner/components/formeditor/scaleitem.h b/src/plugins/qmldesigner/components/formeditor/scaleitem.h
new file mode 100644
index 0000000000..c06d2170e2
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/scaleitem.h
@@ -0,0 +1,53 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef SCALEITEM_H
+#define SCALEITEM_H
+
+#include <QGraphicsRectItem>
+
+namespace QmlDesigner {
+
+class LayerItem;
+class ScaleIndicator;
+
+class ScaleItem : public QGraphicsRectItem
+{
+public:
+ ScaleItem(LayerItem *layerItem, ScaleIndicator *indicator);
+
+ ScaleIndicator* indicator() const;
+
+private:
+ ScaleIndicator* m_indicator;
+};
+
+};
+
+#endif // SCALEITEM_H
diff --git a/src/plugins/qmldesigner/components/formeditor/scalemanipulator.cpp b/src/plugins/qmldesigner/components/formeditor/scalemanipulator.cpp
new file mode 100644
index 0000000000..0c329f22b9
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/scalemanipulator.cpp
@@ -0,0 +1,45 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "scalemanipulator.h"
+
+
+namespace QmlDesigner {
+
+ScaleManipulator::ScaleManipulator(LayerItem *layerItem, FormEditorItem *formEditorItem)
+ : m_layerItem(layerItem),
+ m_formEditorItem(formEditorItem)
+{
+}
+
+ScaleManipulator::~ScaleManipulator()
+{
+}
+
+}
diff --git a/src/plugins/qmldesigner/components/formeditor/scalemanipulator.h b/src/plugins/qmldesigner/components/formeditor/scalemanipulator.h
new file mode 100644
index 0000000000..9d853d7f35
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/scalemanipulator.h
@@ -0,0 +1,63 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef SCALEMANIPULATOR_H
+#define SCALEMANIPULATOR_H
+
+#include <QPointF>
+#include <QList>
+
+
+
+class QGraphicsLineItem;
+
+namespace QmlDesigner {
+
+class LayerItem;
+class FormEditorItem;
+
+class ScaleManipulator
+{
+public:
+ ScaleManipulator(LayerItem *layerItem, FormEditorItem *formEditorItem);
+ virtual ~ScaleManipulator();
+
+
+ void begin(const QPointF& beginPoint);
+ void update(const QPointF& updatePoint);
+ void reparentTo(FormEditorItem *newParent);
+ void end(const QPointF& updatePoint);
+
+private:
+ LayerItem *m_layerItem;
+ FormEditorItem *m_formEditorItem;
+};
+
+}
+#endif // SCALEMANIPULATOR_H
diff --git a/src/plugins/qmldesigner/components/formeditor/selectionindicator.cpp b/src/plugins/qmldesigner/components/formeditor/selectionindicator.cpp
new file mode 100644
index 0000000000..d71ef6cca2
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/selectionindicator.cpp
@@ -0,0 +1,118 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "selectionindicator.h"
+
+#include <QPen>
+#include <cmath>
+#include <QGraphicsScene>
+#include <formeditorview.h>
+#include <formeditorwidget.h>
+#include <zoomaction.h>
+
+namespace QmlDesigner {
+
+SelectionIndicator::SelectionIndicator(LayerItem *layerItem)
+ : m_layerItem(layerItem)
+{
+}
+
+SelectionIndicator::~SelectionIndicator()
+{
+ clear();
+}
+
+void SelectionIndicator::show()
+{
+ foreach (QGraphicsPolygonItem *item, m_indicatorShapeHash.values())
+ item->show();
+}
+
+void SelectionIndicator::hide()
+{
+ foreach (QGraphicsPolygonItem *item, m_indicatorShapeHash.values())
+ item->hide();
+}
+
+void SelectionIndicator::clear()
+{
+ if (m_layerItem) {
+ foreach (QGraphicsItem *item, m_indicatorShapeHash.values())
+ m_layerItem->scene()->removeItem(item);
+ }
+ m_indicatorShapeHash.clear();
+}
+
+static void alignVertices(QPolygonF &polygon, double factor)
+{
+ QMutableVectorIterator<QPointF> iterator(polygon);
+ while (iterator.hasNext()) {
+ QPointF &vertex = iterator.next();
+ vertex.setX(std::floor(vertex.x()) + factor);
+ vertex.setY(std::floor(vertex.y()) + factor);
+ }
+
+}
+
+void SelectionIndicator::setItems(const QList<FormEditorItem*> &itemList)
+{
+ clear();
+
+ foreach (FormEditorItem *item, itemList) {
+ QGraphicsPolygonItem *newSelectionIndicatorGraphicsItem = new QGraphicsPolygonItem(m_layerItem.data());
+ m_indicatorShapeHash.insert(item, newSelectionIndicatorGraphicsItem);
+ QPolygonF boundingRectInSceneSpace(item->mapToScene(item->qmlItemNode().instanceBoundingRect()));
+ alignVertices(boundingRectInSceneSpace, 0.5 / item->formEditorView()->widget()->zoomAction()->zoomLevel());
+ QPolygonF boundingRectInLayerItemSpace = m_layerItem->mapFromScene(boundingRectInSceneSpace);
+ newSelectionIndicatorGraphicsItem->setPolygon(boundingRectInLayerItemSpace);
+ newSelectionIndicatorGraphicsItem->setFlag(QGraphicsItem::ItemIsSelectable, false);
+
+ QPen pen;
+ pen.setColor(QColor(108, 141, 221));
+ newSelectionIndicatorGraphicsItem->setPen(pen);
+ }
+}
+
+
+
+void SelectionIndicator::updateItems(const QList<FormEditorItem*> &itemList)
+{
+ foreach (FormEditorItem *item, itemList) {
+ if (m_indicatorShapeHash.contains(item)) {
+ QGraphicsPolygonItem *indicatorGraphicsItem = m_indicatorShapeHash.value(item);
+ QPolygonF boundingRectInSceneSpace(item->mapToScene(item->qmlItemNode().instanceBoundingRect()));
+ alignVertices(boundingRectInSceneSpace, 0.5 / item->formEditorView()->widget()->zoomAction()->zoomLevel());
+ QPolygonF boundingRectInLayerItemSpace = m_layerItem->mapFromScene(boundingRectInSceneSpace);
+ indicatorGraphicsItem->setPolygon(boundingRectInLayerItemSpace);
+ }
+ }
+}
+
+}
+
diff --git a/src/plugins/qmldesigner/components/formeditor/selectionindicator.h b/src/plugins/qmldesigner/components/formeditor/selectionindicator.h
new file mode 100644
index 0000000000..27e641b0a8
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/selectionindicator.h
@@ -0,0 +1,65 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef SELECTIONINDICATOR_H
+#define SELECTIONINDICATOR_H
+
+#include <QWeakPointer>
+#include <QGraphicsPolygonItem>
+#include "layeritem.h"
+#include "formeditoritem.h"
+
+
+
+namespace QmlDesigner {
+
+
+class SelectionIndicator
+{
+public:
+ SelectionIndicator(LayerItem *layerItem);
+ ~SelectionIndicator();
+
+ void show();
+ void hide();
+
+ void clear();
+
+ void setItems(const QList<FormEditorItem*> &itemList);
+ void updateItems(const QList<FormEditorItem*> &itemList);
+
+private:
+ QHash<FormEditorItem*, QGraphicsPolygonItem *> m_indicatorShapeHash;
+ QWeakPointer<LayerItem> m_layerItem;
+
+};
+
+}
+
+#endif // SELECTIONINDICATOR_H
diff --git a/src/plugins/qmldesigner/components/formeditor/selectionrectangle.cpp b/src/plugins/qmldesigner/components/formeditor/selectionrectangle.cpp
new file mode 100644
index 0000000000..058de243e0
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/selectionrectangle.cpp
@@ -0,0 +1,87 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "selectionrectangle.h"
+
+#include <QPen>
+#include <QGraphicsScene>
+#include <QtDebug>
+#include <cmath>
+#include <QGraphicsScene>
+
+namespace QmlDesigner {
+
+SelectionRectangle::SelectionRectangle(LayerItem *layerItem)
+ : m_controlShape(new QGraphicsRectItem(layerItem)),
+ m_layerItem(layerItem)
+{
+ m_controlShape->setPen(QPen(Qt::black));
+ m_controlShape->setBrush(QColor(128, 128, 128, 50));
+}
+
+SelectionRectangle::~SelectionRectangle()
+{
+ if (m_layerItem)
+ m_layerItem->scene()->removeItem(m_controlShape);
+}
+
+void SelectionRectangle::clear()
+{
+ hide();
+}
+void SelectionRectangle::show()
+{
+ m_controlShape->show();
+}
+
+void SelectionRectangle::hide()
+{
+ m_controlShape->hide();
+}
+
+QRectF SelectionRectangle::rect() const
+{
+ return m_controlShape->mapFromScene(m_controlShape->rect()).boundingRect();
+}
+
+void SelectionRectangle::setRect(const QPointF &firstPoint,
+ const QPointF &secondPoint)
+{
+ double firstX = std::floor(firstPoint.x()) + 0.5;
+ double firstY = std::floor(firstPoint.y()) + 0.5;
+ double secondX = std::floor(secondPoint.x()) + 0.5;
+ double secondY = std::floor(secondPoint.y()) + 0.5;
+ QPointF topLeftPoint(firstX < secondX ? firstX : secondX, firstY < secondY ? firstY : secondY);
+ QPointF bottomRightPoint(firstX > secondX ? firstX : secondX, firstY > secondY ? firstY : secondY);
+
+ QRectF rect(topLeftPoint, bottomRightPoint);
+ m_controlShape->setRect(rect);
+}
+
+}
diff --git a/src/plugins/qmldesigner/components/formeditor/selectionrectangle.h b/src/plugins/qmldesigner/components/formeditor/selectionrectangle.h
new file mode 100644
index 0000000000..91839be73f
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/selectionrectangle.h
@@ -0,0 +1,63 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef SELECTIONRECTANGLE_H
+#define SELECTIONRECTANGLE_H
+
+#include <QWeakPointer>
+#include <QGraphicsRectItem>
+#include "layeritem.h"
+
+
+namespace QmlDesigner {
+
+class SelectionRectangle
+{
+public:
+ SelectionRectangle(LayerItem *layerItem);
+ ~SelectionRectangle();
+
+ void show();
+ void hide();
+
+ void clear();
+
+ void setRect(const QPointF &firstPoint,
+ const QPointF &secondPoint);
+
+ QRectF rect() const;
+
+private:
+ QGraphicsRectItem *m_controlShape;
+ QWeakPointer<LayerItem> m_layerItem;
+};
+
+}
+
+#endif // SELECTIONRECTANGLE_H
diff --git a/src/plugins/qmldesigner/components/formeditor/selectiontool.cpp b/src/plugins/qmldesigner/components/formeditor/selectiontool.cpp
new file mode 100644
index 0000000000..a3e7c1ee60
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/selectiontool.cpp
@@ -0,0 +1,280 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "selectiontool.h"
+#include "formeditorscene.h"
+#include "formeditorview.h"
+
+#include "resizehandleitem.h"
+
+
+#include <QApplication>
+#include <QGraphicsSceneMouseEvent>
+#include <QtDebug>
+#include <QClipboard>
+
+namespace QmlDesigner {
+
+SelectionTool::SelectionTool(FormEditorView *editorView)
+ : AbstractFormEditorTool(editorView),
+ m_rubberbandSelectionManipulator(editorView->scene()->manipulatorLayerItem(), editorView),
+ m_singleSelectionManipulator(editorView),
+ m_selectionIndicator(editorView->scene()->manipulatorLayerItem()),
+ m_resizeIndicator(editorView->scene()->manipulatorLayerItem())
+
+{
+// view()->setCursor(Qt::CrossCursor);
+}
+
+
+SelectionTool::~SelectionTool()
+{
+}
+
+void SelectionTool::mousePressEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event)
+{
+ m_mousePressTimer.start();
+ FormEditorItem* formEditorItem = topFormEditorItem(itemList);
+ if (formEditorItem && !formEditorItem->qmlItemNode().hasChildren()) {
+ m_singleSelectionManipulator.begin(event->scenePos());
+
+ if (event->modifiers().testFlag(Qt::ControlModifier))
+ m_singleSelectionManipulator.select(SingleSelectionManipulator::RemoveFromSelection);
+ else if (event->modifiers().testFlag(Qt::ShiftModifier))
+ m_singleSelectionManipulator.select(SingleSelectionManipulator::AddToSelection);
+ else
+ m_singleSelectionManipulator.select(SingleSelectionManipulator::InvertSelection);
+ } else {
+ if (event->modifiers().testFlag(Qt::AltModifier)) {
+ m_singleSelectionManipulator.begin(event->scenePos());
+
+ if (event->modifiers().testFlag(Qt::ControlModifier))
+ m_singleSelectionManipulator.select(SingleSelectionManipulator::RemoveFromSelection);
+ else if (event->modifiers().testFlag(Qt::ShiftModifier))
+ m_singleSelectionManipulator.select(SingleSelectionManipulator::AddToSelection);
+ else
+ m_singleSelectionManipulator.select(SingleSelectionManipulator::InvertSelection);
+
+ m_singleSelectionManipulator.end(event->scenePos());
+ view()->changeToMoveTool(event->scenePos());
+ } else {
+ m_rubberbandSelectionManipulator.begin(event->scenePos());
+ }
+ }
+}
+
+void SelectionTool::mouseMoveEvent(const QList<QGraphicsItem*> &/*itemList*/,
+ QGraphicsSceneMouseEvent *event)
+{
+ if (m_singleSelectionManipulator.isActive()) {
+ QPointF mouseMovementVector = m_singleSelectionManipulator.beginPoint() - event->scenePos();
+ if ((mouseMovementVector.toPoint().manhattanLength() > QApplication::startDragDistance())
+ && (m_mousePressTimer.elapsed() > QApplication::startDragTime())) {
+ m_singleSelectionManipulator.end(event->scenePos());
+ view()->changeToMoveTool(m_singleSelectionManipulator.beginPoint());
+ return;
+ }
+ } else if (m_rubberbandSelectionManipulator.isActive()) {
+ QPointF mouseMovementVector = m_rubberbandSelectionManipulator.beginPoint() - event->scenePos();
+ if ((mouseMovementVector.toPoint().manhattanLength() > QApplication::startDragDistance())
+ && (m_mousePressTimer.elapsed() > QApplication::startDragTime())) {
+ m_rubberbandSelectionManipulator.update(event->scenePos());
+
+ if (event->modifiers().testFlag(Qt::ControlModifier))
+ m_rubberbandSelectionManipulator.select(RubberBandSelectionManipulator::RemoveFromSelection);
+ else if (event->modifiers().testFlag(Qt::ShiftModifier))
+ m_rubberbandSelectionManipulator.select(RubberBandSelectionManipulator::AddToSelection);
+ else
+ m_rubberbandSelectionManipulator.select(RubberBandSelectionManipulator::ReplaceSelection);
+ }
+ }
+}
+
+void SelectionTool::hoverMoveEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent * /*event*/)
+{
+ if (itemList.isEmpty())
+ return;
+
+ ResizeHandleItem* resizeHandle = ResizeHandleItem::fromGraphicsItem(itemList.first());
+ if (resizeHandle) {
+ view()->changeToResizeTool();
+ return;
+ }
+
+ if (topSelectedItemIsMovable(itemList))
+ view()->changeToMoveTool();
+}
+
+void SelectionTool::mouseReleaseEvent(const QList<QGraphicsItem*> &/*itemList*/,
+ QGraphicsSceneMouseEvent *event)
+{
+ if (m_singleSelectionManipulator.isActive()) {
+ qDebug() << __FUNCTION__ << "single";
+ m_singleSelectionManipulator.end(event->scenePos());
+ }
+ else if (m_rubberbandSelectionManipulator.isActive()) {
+
+ QPointF mouseMovementVector = m_rubberbandSelectionManipulator.beginPoint() - event->scenePos();
+ if (mouseMovementVector.toPoint().manhattanLength() < QApplication::startDragDistance()) {
+ m_singleSelectionManipulator.begin(event->scenePos());
+
+ if (event->modifiers().testFlag(Qt::ControlModifier))
+ m_singleSelectionManipulator.select(SingleSelectionManipulator::RemoveFromSelection);
+ else if (event->modifiers().testFlag(Qt::ShiftModifier))
+ m_singleSelectionManipulator.select(SingleSelectionManipulator::AddToSelection);
+ else
+ m_singleSelectionManipulator.select(SingleSelectionManipulator::InvertSelection);
+
+ m_singleSelectionManipulator.end(event->scenePos());
+ } else {
+ m_rubberbandSelectionManipulator.update(event->scenePos());
+
+ if (event->modifiers().testFlag(Qt::ControlModifier))
+ m_rubberbandSelectionManipulator.select(RubberBandSelectionManipulator::RemoveFromSelection);
+ else if (event->modifiers().testFlag(Qt::ShiftModifier))
+ m_rubberbandSelectionManipulator.select(RubberBandSelectionManipulator::AddToSelection);
+ else
+ m_rubberbandSelectionManipulator.select(RubberBandSelectionManipulator::ReplaceSelection);
+
+ m_rubberbandSelectionManipulator.end();
+ }
+ }
+
+}
+
+void SelectionTool::mouseDoubleClickEvent(const QList<QGraphicsItem*> &/*itemList*/,
+ QGraphicsSceneMouseEvent * /*event*/)
+{
+
+}
+
+void SelectionTool::keyPressEvent(QKeyEvent *event)
+{
+ switch(event->key()) {
+ case Qt::Key_Left:
+ case Qt::Key_Right:
+ case Qt::Key_Up:
+ case Qt::Key_Down:
+ view()->changeToMoveTool();
+ view()->currentTool()->keyPressEvent(event);
+ break;
+ case Qt::Key_C:
+ if (event->modifiers().testFlag(Qt::ControlModifier)) {
+ copySelectedNodeToClipBoard();
+ break;
+ }
+ case Qt::Key_V:
+ if (event->modifiers().testFlag(Qt::ControlModifier)) {
+ pasteClipBoard();
+ break;
+ }
+ case Qt::Key_X:
+ if (event->modifiers().testFlag(Qt::ControlModifier)) {
+ cutSelectedNodeToClipBoard();
+ break;
+ }
+ }
+}
+
+void SelectionTool::keyReleaseEvent(QKeyEvent * /*keyEvent*/)
+{
+
+}
+
+void SelectionTool::copySelectedNodeToClipBoard()
+{
+ // QClipboard *clipboard = QApplication::clipboard();
+}
+
+void SelectionTool::cutSelectedNodeToClipBoard()
+{
+ // QClipboard *clipboard = QApplication::clipboard();
+}
+
+void SelectionTool::pasteClipBoard()
+{
+ // QClipboard *clipboard = QApplication::clipboard();
+}
+
+void SelectionTool::itemsAboutToRemoved(const QList<FormEditorItem*> &/*itemList*/)
+{
+
+}
+
+//QVariant SelectionTool::itemChange(const QList<QGraphicsItem*> &itemList,
+// QGraphicsItem::GraphicsItemChange change,
+// const QVariant &value )
+//{
+// qDebug() << Q_FUNC_INFO;
+// return QVariant();
+//}
+
+//void SelectionTool::update()
+//{
+//
+//}
+
+
+void SelectionTool::clear()
+{
+ m_rubberbandSelectionManipulator.clear(),
+ m_singleSelectionManipulator.clear();
+ m_selectionIndicator.clear();
+ m_resizeIndicator.clear();
+}
+
+void SelectionTool::selectedItemsChanged(const QList<FormEditorItem*> &itemList)
+{
+ m_selectionIndicator.setItems(itemList);
+ m_resizeIndicator.setItems(itemList);
+}
+
+void SelectionTool::formEditorItemsChanged(const QList<FormEditorItem*> &itemList)
+{
+ m_selectionIndicator.updateItems(itemList);
+ m_resizeIndicator.updateItems(itemList);
+}
+
+void SelectionTool::selectUnderPoint(QGraphicsSceneMouseEvent *event)
+{
+ m_singleSelectionManipulator.begin(event->scenePos());
+
+ if (event->modifiers().testFlag(Qt::ControlModifier))
+ m_singleSelectionManipulator.select(SingleSelectionManipulator::RemoveFromSelection);
+ else if (event->modifiers().testFlag(Qt::ShiftModifier))
+ m_singleSelectionManipulator.select(SingleSelectionManipulator::AddToSelection);
+ else
+ m_singleSelectionManipulator.select(SingleSelectionManipulator::ReplaceSelection);
+
+ m_singleSelectionManipulator.end(event->scenePos());
+}
+
+}
diff --git a/src/plugins/qmldesigner/components/formeditor/selectiontool.h b/src/plugins/qmldesigner/components/formeditor/selectiontool.h
new file mode 100644
index 0000000000..062eb20fbc
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/selectiontool.h
@@ -0,0 +1,93 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef SELECTIONTOOL_H
+#define SELECTIONTOOL_H
+
+
+#include "abstractformeditortool.h"
+#include "movemanipulator.h"
+#include "rubberbandselectionmanipulator.h"
+#include "singleselectionmanipulator.h"
+#include "selectionindicator.h"
+#include "resizeindicator.h"
+
+#include <QHash>
+#include <QTime>
+
+namespace QmlDesigner {
+
+
+class SelectionTool : public AbstractFormEditorTool
+{
+public:
+ SelectionTool(FormEditorView* editorView);
+ ~SelectionTool();
+
+ void mousePressEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event);
+ void mouseMoveEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event);
+ void mouseDoubleClickEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event);
+ void hoverMoveEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event);
+ void keyPressEvent(QKeyEvent *event);
+ void keyReleaseEvent(QKeyEvent *keyEvent);
+
+ void itemsAboutToRemoved(const QList<FormEditorItem*> &itemList);
+ // QVariant itemChange(const QList<QGraphicsItem*> &itemList,
+// QGraphicsItem::GraphicsItemChange change,
+// const QVariant &value );
+
+// void update();
+
+ void clear();
+
+ void selectedItemsChanged(const QList<FormEditorItem*> &itemList);
+
+ void formEditorItemsChanged(const QList<FormEditorItem*> &itemList);
+
+ void selectUnderPoint(QGraphicsSceneMouseEvent *event);
+
+ void copySelectedNodeToClipBoard();
+ void cutSelectedNodeToClipBoard();
+ void pasteClipBoard();
+private:
+ RubberBandSelectionManipulator m_rubberbandSelectionManipulator;
+ SingleSelectionManipulator m_singleSelectionManipulator;
+ SelectionIndicator m_selectionIndicator;
+ ResizeIndicator m_resizeIndicator;
+ QTime m_mousePressTimer;
+};
+
+}
+#endif // SELECTIONTOOL_H
diff --git a/src/plugins/qmldesigner/components/formeditor/singleselectionmanipulator.cpp b/src/plugins/qmldesigner/components/formeditor/singleselectionmanipulator.cpp
new file mode 100644
index 0000000000..43625eb955
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/singleselectionmanipulator.cpp
@@ -0,0 +1,132 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "singleselectionmanipulator.h"
+
+#include "model.h"
+#include "nodemetainfo.h"
+#include "formeditorscene.h"
+#include "formeditorview.h"
+#include <QtDebug>
+
+namespace QmlDesigner {
+
+SingleSelectionManipulator::SingleSelectionManipulator(FormEditorView *editorView)
+ : m_editorView(editorView),
+ m_isActive(false)
+{
+}
+
+
+void SingleSelectionManipulator::begin(const QPointF &beginPoint)
+{
+ m_beginPoint = beginPoint;
+ m_isActive = true;
+ m_oldSelectionList = m_editorView->selectedQmlItemNodes();
+}
+
+void SingleSelectionManipulator::update(const QPointF &/*updatePoint*/)
+{
+ m_oldSelectionList.clear();
+}
+
+void SingleSelectionManipulator::clear()
+{
+ m_beginPoint = QPointF();
+ m_oldSelectionList.clear();
+}
+
+
+void SingleSelectionManipulator::end(const QPointF &/*updatePoint*/)
+{
+ m_oldSelectionList.clear();
+ m_isActive = false;
+}
+
+void SingleSelectionManipulator::select(SelectionType selectionType)
+{
+ QList<QGraphicsItem*> itemList = m_editorView->scene()->items(m_beginPoint);
+
+ QmlItemNode selectedNode;
+
+ foreach(QGraphicsItem* item, itemList)
+ {
+ FormEditorItem *formEditorItem = FormEditorItem::fromQGraphicsItem(item);
+
+ if (formEditorItem
+ && !formEditorItem->qmlItemNode().isRootNode()
+ && (formEditorItem->qmlItemNode().hasShowContent()))
+ {
+ selectedNode = formEditorItem->qmlItemNode();
+ break;
+ }
+ }
+
+ QList<QmlItemNode> nodeList;
+
+ switch(selectionType) {
+ case AddToSelection: {
+ nodeList.append(m_oldSelectionList);
+ if (selectedNode.isValid())
+ nodeList.append(selectedNode);
+ }
+ break;
+ case ReplaceSelection: {
+ if (selectedNode.isValid())
+ nodeList.append(selectedNode);
+ }
+ break;
+ case RemoveFromSelection: {
+ nodeList.append(m_oldSelectionList);
+ if (selectedNode.isValid())
+ nodeList.removeAll(selectedNode);
+ }
+ break;
+ case InvertSelection: {
+ if (selectedNode.isValid()
+ && !m_oldSelectionList.contains(selectedNode))
+ nodeList.append(selectedNode);
+ }
+ }
+
+ m_editorView->setSelectedQmlItemNodes(nodeList);
+}
+
+
+bool SingleSelectionManipulator::isActive() const
+{
+ return m_isActive;
+}
+
+QPointF SingleSelectionManipulator::beginPoint() const
+{
+ return m_beginPoint;
+}
+
+}
diff --git a/src/plugins/qmldesigner/components/formeditor/singleselectionmanipulator.h b/src/plugins/qmldesigner/components/formeditor/singleselectionmanipulator.h
new file mode 100644
index 0000000000..a97abaa145
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/singleselectionmanipulator.h
@@ -0,0 +1,72 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef SINGLESELECTIONMANIPULATOR_H
+#define SINGLESELECTIONMANIPULATOR_H
+
+#include "selectionrectangle.h"
+#include "formeditorview.h"
+
+namespace QmlDesigner {
+
+class SingleSelectionManipulator
+{
+public:
+ SingleSelectionManipulator(FormEditorView *editorView);
+
+// void setItems(const QList<FormEditorItem*> &itemList);
+
+ enum SelectionType {
+ ReplaceSelection,
+ AddToSelection,
+ RemoveFromSelection,
+ InvertSelection
+ };
+
+ void begin(const QPointF& beginPoint);
+ void update(const QPointF& updatePoint);
+ void end(const QPointF& updatePoint);
+
+ void select(SelectionType selectionType);
+
+ void clear();
+
+ QPointF beginPoint() const;
+
+ bool isActive() const;
+
+private:
+ QList<QmlItemNode> m_oldSelectionList;
+ QPointF m_beginPoint;
+ FormEditorView *m_editorView;
+ bool m_isActive;
+};
+
+}
+#endif // SINGLESELECTIONMANIPULATOR_H
diff --git a/src/plugins/qmldesigner/components/formeditor/snapper.cpp b/src/plugins/qmldesigner/components/formeditor/snapper.cpp
new file mode 100644
index 0000000000..506146836c
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/snapper.cpp
@@ -0,0 +1,626 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "snapper.h"
+
+#include <QtDebug>
+
+#include <limits>
+#include <cmath>
+#include <QLineF>
+#include <QPen>
+#include <QApplication>
+
+namespace QmlDesigner {
+
+Snapper::Snapper()
+ : m_containerFormEditorItem(0),
+ m_transformtionSpaceFormEditorItem(0),
+ m_snappingDistance(5.0)
+{
+}
+
+void Snapper::updateSnappingLines(const QList<FormEditorItem*> &exceptionList)
+{
+ if (m_containerFormEditorItem)
+ m_containerFormEditorItem->updateSnappingLines(exceptionList, m_transformtionSpaceFormEditorItem);
+}
+
+void Snapper::updateSnappingLines(FormEditorItem* exceptionItem)
+{
+ QList<FormEditorItem*> exceptionList;
+ exceptionList.append(exceptionItem);
+ updateSnappingLines(exceptionList);
+}
+
+
+void Snapper::setContainerFormEditorItem(FormEditorItem *formEditorItem)
+{
+ m_containerFormEditorItem = formEditorItem;
+}
+
+
+void Snapper::setTransformtionSpaceFormEditorItem(FormEditorItem *formEditorItem)
+{
+ m_transformtionSpaceFormEditorItem = formEditorItem;
+}
+
+FormEditorItem *Snapper::transformtionSpaceFormEditorItem() const
+{
+ return m_transformtionSpaceFormEditorItem;
+}
+
+double Snapper::snappedVerticalOffset(const QRectF &boundingRect) const
+{
+ double offset = std::numeric_limits<double>::max();
+
+ offset = qMin(offset, snappedOffsetForLines(containerFormEditorItem()->leftSnappingLines(),
+ boundingRect.left()));
+
+ offset = qMin(offset, snappedOffsetForOffsetLines(containerFormEditorItem()->rightSnappingOffsets(),
+ Qt::Vertical,
+ boundingRect.left(),
+ boundingRect.top(),
+ boundingRect.bottom()));
+
+ offset = qMin(offset, snappedOffsetForLines(containerFormEditorItem()->rightSnappingLines(),
+ boundingRect.right()));
+
+ offset = qMin(offset, snappedOffsetForOffsetLines(containerFormEditorItem()->leftSnappingOffsets(),
+ Qt::Vertical,
+ boundingRect.right(),
+ boundingRect.top(),
+ boundingRect.bottom()));
+
+ offset = qMin(offset, snappedOffsetForLines(containerFormEditorItem()->verticalCenterSnappingLines(),
+ boundingRect.center().x()));
+
+ return offset;
+}
+
+double Snapper::snappedHorizontalOffset(const QRectF &boundingRect) const
+{
+ double offset = std::numeric_limits<double>::max();
+
+ offset = qMin(offset, snappedOffsetForLines(containerFormEditorItem()->topSnappingLines(),
+ boundingRect.top()));
+
+ offset = qMin(offset, snappedOffsetForOffsetLines(containerFormEditorItem()->bottomSnappingOffsets(),
+ Qt::Horizontal,
+ boundingRect.top(),
+ boundingRect.left(),
+ boundingRect.right()));
+
+ offset = qMin(offset, snappedOffsetForLines(containerFormEditorItem()->bottomSnappingLines(),
+ boundingRect.bottom()));
+
+ offset = qMin(offset, snappedOffsetForOffsetLines(containerFormEditorItem()->topSnappingOffsets(),
+ Qt::Horizontal,
+ boundingRect.bottom(),
+ boundingRect.left(),
+ boundingRect.right()));
+
+ offset = qMin(offset, snappedOffsetForLines(containerFormEditorItem()->horizontalCenterSnappingLines(),
+ boundingRect.center().y()));
+ return offset;
+}
+
+
+double Snapper::snapTopOffset(const QRectF &boundingRect) const
+{
+ double offset = std::numeric_limits<double>::max();
+
+ offset = qMin(offset, snappedOffsetForLines(containerFormEditorItem()->topSnappingLines(),
+ boundingRect.top()));
+
+ offset = qMin(offset, snappedOffsetForOffsetLines(containerFormEditorItem()->bottomSnappingOffsets(),
+ Qt::Horizontal,
+ boundingRect.top(),
+ boundingRect.left(),
+ boundingRect.right()));
+ return offset;
+}
+
+double Snapper::snapRightOffset(const QRectF &boundingRect) const
+{
+ double offset = std::numeric_limits<double>::max();
+
+ offset = qMin(offset, snappedOffsetForLines(containerFormEditorItem()->rightSnappingLines(),
+ boundingRect.right()));
+
+ offset = qMin(offset, snappedOffsetForOffsetLines(containerFormEditorItem()->leftSnappingOffsets(),
+ Qt::Vertical,
+ boundingRect.right(),
+ boundingRect.top(),
+ boundingRect.bottom()));
+ return offset;
+}
+
+double Snapper::snapLeftOffset(const QRectF &boundingRect) const
+{
+ double offset = std::numeric_limits<double>::max();
+
+ offset = qMin(offset, snappedOffsetForLines(containerFormEditorItem()->leftSnappingLines(),
+ boundingRect.left()));
+
+ offset = qMin(offset, snappedOffsetForOffsetLines(containerFormEditorItem()->rightSnappingOffsets(),
+ Qt::Vertical,
+ boundingRect.left(),
+ boundingRect.top(),
+ boundingRect.bottom()));
+ return offset;
+}
+
+double Snapper::snapBottomOffset(const QRectF &boundingRect) const
+{
+ double offset = std::numeric_limits<double>::max();
+
+ offset = qMin(offset, snappedOffsetForLines(containerFormEditorItem()->bottomSnappingLines(),
+ boundingRect.bottom()));
+
+ offset = qMin(offset, snappedOffsetForOffsetLines(containerFormEditorItem()->topSnappingOffsets(),
+ Qt::Horizontal,
+ boundingRect.bottom(),
+ boundingRect.left(),
+ boundingRect.right()));
+ return offset;
+
+}
+
+
+QList<QLineF> Snapper::verticalSnappedLines(const QRectF &boundingRect, QList<QRectF> *boundingRects) const
+{
+ QList<QLineF> lineList = findSnappingLines(containerFormEditorItem()->leftSnappingLines(),
+ Qt::Vertical,
+ boundingRect.left(),
+ boundingRect.top(),
+ boundingRect.bottom(),
+ boundingRects);
+
+ lineList += findSnappingOffsetLines(containerFormEditorItem()->rightSnappingOffsets(),
+ Qt::Vertical,
+ boundingRect.left(),
+ boundingRect.top(),
+ boundingRect.bottom(),
+ boundingRects);
+
+
+ lineList += findSnappingLines(containerFormEditorItem()->rightSnappingLines(),
+ Qt::Vertical,
+ boundingRect.right(),
+ boundingRect.top(),
+ boundingRect.bottom(),
+ boundingRects);
+
+ lineList += findSnappingOffsetLines(containerFormEditorItem()->leftSnappingOffsets(),
+ Qt::Vertical,
+ boundingRect.right(),
+ boundingRect.top(),
+ boundingRect.bottom(),
+ boundingRects);
+
+ lineList += findSnappingLines(containerFormEditorItem()->verticalCenterSnappingLines(),
+ Qt::Vertical,
+ boundingRect.center().x(),
+ boundingRect.top(),
+ boundingRect.bottom(),
+ boundingRects);
+
+ return lineList;
+}
+
+QList<QLineF> Snapper::horizontalSnappedLines(const QRectF &boundingRect, QList<QRectF> *boundingRects) const
+{
+ QList<QLineF> lineList = findSnappingLines(containerFormEditorItem()->topSnappingLines(),
+ Qt::Horizontal,
+ boundingRect.top(),
+ boundingRect.left(),
+ boundingRect.right());
+
+ lineList += findSnappingOffsetLines(containerFormEditorItem()->bottomSnappingOffsets(),
+ Qt::Horizontal,
+ boundingRect.top(),
+ boundingRect.left(),
+ boundingRect.right(),
+ boundingRects);
+
+
+ lineList += findSnappingLines(containerFormEditorItem()->bottomSnappingLines(),
+ Qt::Horizontal,
+ boundingRect.bottom(),
+ boundingRect.left(),
+ boundingRect.right(),
+ boundingRects);
+
+ lineList += findSnappingOffsetLines(containerFormEditorItem()->topSnappingOffsets(),
+ Qt::Horizontal,
+ boundingRect.bottom(),
+ boundingRect.left(),
+ boundingRect.right(),
+ boundingRects);
+
+ lineList += findSnappingLines(containerFormEditorItem()->horizontalCenterSnappingLines(),
+ Qt::Horizontal,
+ boundingRect.center().y(),
+ boundingRect.left(),
+ boundingRect.right(),
+ boundingRects);
+
+ return lineList;
+}
+
+
+
+FormEditorItem *Snapper::containerFormEditorItem() const
+{
+ return m_containerFormEditorItem;
+}
+
+QLineF Snapper::createSnapLine(Qt::Orientation orientation,
+ double snapLine,
+ double lowerLimit,
+ double upperLimit,
+ const QRectF &itemRect) const
+{
+ if (orientation == Qt::Horizontal) {
+ double lowerX(qMin(lowerLimit, itemRect.left()));
+ double upperX(qMax(upperLimit, itemRect.right()));
+ return QLineF(lowerX, snapLine, upperX, snapLine);
+ } else {
+ double lowerY(qMin(lowerLimit, itemRect.top()));
+ double upperY(qMax(upperLimit, itemRect.bottom()));
+ return QLineF(snapLine, lowerY, snapLine, upperY);
+ }
+}
+
+static bool compareLines(double snapLine, double lineToSnap)
+{
+// if (qAbs(snapLine - lineToSnap) < 1.0)
+// return true;
+//
+// return false;
+ return qFuzzyCompare(snapLine, lineToSnap);
+}
+
+QList<QLineF> Snapper::findSnappingLines(const SnapLineMap &snappingLineMap,
+ Qt::Orientation orientation,
+ double snapLine,
+ double lowerLimit,
+ double upperLimit,
+ QList<QRectF> *boundingRects) const
+{
+ QList<QLineF> lineList;
+
+ SnapLineMapIterator snappingLineIterator(snappingLineMap);
+ while (snappingLineIterator.hasNext()) {
+ snappingLineIterator.next();
+
+ if (compareLines(snapLine, snappingLineIterator.key())) { // near distance snapping lines
+ lineList += createSnapLine(orientation,
+ snappingLineIterator.key(),
+ lowerLimit,
+ upperLimit,
+ snappingLineIterator.value().first);
+ if (boundingRects != 0)
+ boundingRects->append(snappingLineIterator.value().first);
+ }
+ }
+
+ return lineList;
+}
+
+
+QList<QLineF> Snapper::findSnappingOffsetLines(const SnapLineMap &snappingOffsetMap,
+ Qt::Orientation orientation,
+ double snapLine,
+ double lowerLimit,
+ double upperLimit,
+ QList<QRectF> *boundingRects) const
+{
+ QList<QLineF> lineList;
+
+ SnapLineMapIterator snappingOffsetIterator(snappingOffsetMap);
+ while (snappingOffsetIterator.hasNext()) {
+ snappingOffsetIterator.next();
+
+ const QRectF &formEditorItemRect(snappingOffsetIterator.value().first);
+ double formEditorItemRectLowerLimit;
+ double formEditorItemRectUpperLimit;
+ if (orientation == Qt::Horizontal) {
+ formEditorItemRectLowerLimit = formEditorItemRect.left();
+ formEditorItemRectUpperLimit = formEditorItemRect.right();
+ } else {
+ formEditorItemRectLowerLimit = formEditorItemRect.top();
+ formEditorItemRectUpperLimit = formEditorItemRect.bottom();
+ }
+
+
+ if (qFuzzyCompare(snapLine, snappingOffsetIterator.key()) &&
+ !(lowerLimit > formEditorItemRectUpperLimit ||
+ upperLimit < formEditorItemRectLowerLimit)) {
+ lineList += createSnapLine(orientation,
+ snapLine,
+ lowerLimit,
+ upperLimit,
+ formEditorItemRect);
+ if (boundingRects != 0)
+ boundingRects->append(snappingOffsetIterator.value().first);
+ }
+ }
+
+
+ return lineList;
+}
+
+double Snapper::snappedOffsetForLines(const SnapLineMap &snappingLineMap,
+ double value) const
+{
+ QMultiMap<double, double> minimumSnappingLineMap;
+
+ SnapLineMapIterator snappingLineIterator(snappingLineMap);
+ while (snappingLineIterator.hasNext()) {
+ snappingLineIterator.next();
+ double snapLine = snappingLineIterator.key();
+ double offset = value - snapLine;
+ double distance = qAbs(offset);
+
+ if (distance < snappingDistance()) {
+ minimumSnappingLineMap.insert(distance, offset);
+ }
+ }
+
+ if (!minimumSnappingLineMap.isEmpty()) {
+ return minimumSnappingLineMap.begin().value();
+ }
+
+ return std::numeric_limits<double>::max();
+}
+
+
+double Snapper::snappedOffsetForOffsetLines(const SnapLineMap &snappingOffsetMap,
+ Qt::Orientation orientation,
+ double value,
+ double lowerLimit,
+ double upperLimit) const
+{
+ QMultiMap<double, double> minimumSnappingLineMap;
+
+ SnapLineMapIterator snappingOffsetIterator(snappingOffsetMap);
+ while (snappingOffsetIterator.hasNext()) {
+ snappingOffsetIterator.next();
+ double snapLine = snappingOffsetIterator.key();
+ const QRectF &formEditorItemRect(snappingOffsetIterator.value().first);
+ double formEditorItemRectLowerLimit;
+ double formEditorItemRectUpperLimit;
+ if (orientation == Qt::Horizontal) {
+ formEditorItemRectLowerLimit = formEditorItemRect.left();
+ formEditorItemRectUpperLimit = formEditorItemRect.right();
+ } else {
+ formEditorItemRectLowerLimit = formEditorItemRect.top();
+ formEditorItemRectUpperLimit = formEditorItemRect.bottom();
+ }
+
+ double offset = value - snapLine;
+ double distance = qAbs(offset);
+
+ if (distance < snappingDistance() &&
+ !(lowerLimit > formEditorItemRectUpperLimit ||
+ upperLimit < formEditorItemRectLowerLimit)) {
+
+ minimumSnappingLineMap.insert(distance, offset);
+ }
+ }
+
+ if (!minimumSnappingLineMap.isEmpty()) {
+ return minimumSnappingLineMap.begin().value();
+ }
+
+ return std::numeric_limits<double>::max();
+}
+
+
+void Snapper::setSnappingDistance(double snappingDistance)
+{
+ m_snappingDistance = snappingDistance;
+}
+
+double Snapper::snappingDistance() const
+{
+ return m_snappingDistance;
+}
+
+static bool lineXLessThan(const QLineF &firstLine, const QLineF &secondLine)
+{
+ return firstLine.x1() < secondLine.x2();
+}
+
+static bool lineYLessThan(const QLineF &firstLine, const QLineF &secondLine)
+{
+ return firstLine.y1() < secondLine.y2();
+}
+
+
+static QLineF mergedHorizontalLine(const QList<QLineF> &lineList)
+{
+ if (lineList.count() == 1)
+ return lineList.first();
+
+ double minimumX = std::numeric_limits<double>::max();
+ double maximumX = std::numeric_limits<double>::min();
+ foreach(const QLineF &line, lineList) {
+ minimumX = qMin(minimumX, line.x1());
+ minimumX = qMin(minimumX, line.x2());
+ maximumX = qMax(maximumX, line.x1());
+ maximumX = qMax(maximumX, line.x2());
+ }
+
+ double y(lineList.first().y1());
+ return QLineF(minimumX, y, maximumX, y);;
+}
+
+static QLineF mergedVerticalLine(const QList<QLineF> &lineList)
+{
+ if (lineList.count() == 1)
+ return lineList.first();
+
+ double minimumY = std::numeric_limits<double>::max();
+ double maximumY = std::numeric_limits<double>::min();
+ foreach(const QLineF &line, lineList) {
+ minimumY = qMin(minimumY, line.y1());
+ minimumY = qMin(minimumY, line.y2());
+ maximumY = qMax(maximumY, line.y1());
+ maximumY = qMax(maximumY, line.y2());
+ }
+
+ double x(lineList.first().x1());
+ return QLineF(x, minimumY, x, maximumY);;
+}
+
+static QList<QLineF> mergedHorizontalLines(const QList<QLineF> &lineList)
+{
+ QList<QLineF> mergedLineList;
+
+ QList<QLineF> sortedLineList(lineList);
+ qSort(sortedLineList.begin(), sortedLineList.end(), lineYLessThan);
+
+ QList<QLineF> lineWithTheSameY;
+ QListIterator<QLineF> sortedLineListIterator(sortedLineList);
+ while (sortedLineListIterator.hasNext()) {
+ QLineF line = sortedLineListIterator.next();
+ lineWithTheSameY.append(line);
+
+ if (sortedLineListIterator.hasNext()) {
+ QLineF nextLine = sortedLineListIterator.peekNext();
+ if (!qFuzzyCompare(line.y1(), nextLine.y1())) {
+ mergedLineList.append(mergedHorizontalLine(lineWithTheSameY));
+ lineWithTheSameY.clear();
+ }
+ } else {
+ mergedLineList.append(mergedHorizontalLine(lineWithTheSameY));
+ }
+ }
+
+ return mergedLineList;
+}
+
+
+
+
+
+
+static QList<QLineF> mergedVerticalLines(const QList<QLineF> &lineList)
+{
+ QList<QLineF> mergedLineList;
+
+ QList<QLineF> sortedLineList(lineList);
+ qSort(sortedLineList.begin(), sortedLineList.end(), lineXLessThan);
+
+ QList<QLineF> lineWithTheSameX;
+ QListIterator<QLineF> sortedLineListIterator(sortedLineList);
+ while (sortedLineListIterator.hasNext()) {
+ QLineF line = sortedLineListIterator.next();
+ lineWithTheSameX.append(line);
+
+ if (sortedLineListIterator.hasNext()) {
+ QLineF nextLine = sortedLineListIterator.peekNext();
+ if (!qFuzzyCompare(line.x1(), nextLine.x1())) {
+ mergedLineList.append(mergedVerticalLine(lineWithTheSameX));
+ lineWithTheSameX.clear();
+ }
+ } else {
+ mergedLineList.append(mergedVerticalLine(lineWithTheSameX));
+ }
+ }
+
+ return mergedLineList;
+}
+
+QList<QGraphicsItem*> Snapper::generateSnappingLines(const QRectF &boundingRect,
+ QGraphicsItem *layerItem,
+ const QTransform &transform)
+{
+ QList<QRectF> boundingRectList;
+ boundingRectList.append(boundingRect);
+
+ return generateSnappingLines(boundingRectList, layerItem, transform);
+}
+
+static void alignLine(QLineF &line)
+{
+ line.setP1(QPointF(std::floor(line.p1().x()) + 0.5,
+ std::floor(line.p1().y()) + 0.5));
+ line.setP2(QPointF(std::floor(line.p2().x()) + 0.5,
+ std::floor(line.p2().y()) + 0.5));
+}
+
+QList<QGraphicsItem*> Snapper::generateSnappingLines(const QList<QRectF> &boundingRectList,
+ QGraphicsItem *layerItem,
+ const QTransform &transform)
+{
+ QList<QGraphicsItem*> graphicsItemList;
+ QList<QLineF> lineList;
+ foreach(const QRectF &boundingRect, boundingRectList) {
+ QList<QRectF> snappedBoundingRectList;
+ lineList += mergedHorizontalLines(horizontalSnappedLines(boundingRect, &snappedBoundingRectList));
+ lineList += mergedVerticalLines(verticalSnappedLines(boundingRect, &snappedBoundingRectList));
+
+// snappedBoundingRectList.append(boundingRect);
+// foreach(const QRectF &snappedBoundingRect, snappedBoundingRectList) {
+// QPolygonF rect = transform.map(snappedBoundingRect);
+// alignVertices(rect);
+// QGraphicsPolygonItem * item = new QGraphicsPolygonItem(rect, layerItem);
+// item->setZValue(20);
+
+// QColor brushColor(QApplication::palette().highlight().color());
+// QColor brushColor(Qt::gray);
+// brushColor.setAlphaF(0.25);
+// QBrush brush(brushColor);
+// item->setBrush(brush);
+// item->setPen(Qt::NoPen);
+// graphicsItemList.append(item);
+// }
+ }
+
+ foreach(const QLineF &line, lineList) {
+ QLineF lineInTransformationSpace = transform.map(line);
+ alignLine(lineInTransformationSpace);
+ QGraphicsLineItem * lineItem = new QGraphicsLineItem(lineInTransformationSpace, layerItem);
+ lineItem->setZValue(40);
+ QPen linePen;
+// linePen.setStyle(Qt::DashLine);
+ linePen.setColor("#5d2dd7");
+ lineItem->setPen(linePen);
+
+ graphicsItemList.append(lineItem);
+ }
+
+ return graphicsItemList;
+}
+
+}
diff --git a/src/plugins/qmldesigner/components/formeditor/snapper.h b/src/plugins/qmldesigner/components/formeditor/snapper.h
new file mode 100644
index 0000000000..a176b4e6e1
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/snapper.h
@@ -0,0 +1,112 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef SNAPPER_H
+#define SNAPPER_H
+
+#include "formeditoritem.h"
+
+class QLineF;
+
+namespace QmlDesigner {
+
+
+class Snapper
+{
+public:
+ Snapper();
+
+ void setContainerFormEditorItem(FormEditorItem *formEditorItem);
+ FormEditorItem *containerFormEditorItem() const;
+
+ void setTransformtionSpaceFormEditorItem(FormEditorItem *formEditorItem);
+ FormEditorItem *transformtionSpaceFormEditorItem() const;
+
+ double snappedVerticalOffset(const QRectF &boundingRect) const;
+ double snappedHorizontalOffset(const QRectF &boundingRect) const;
+
+ double snapTopOffset(const QRectF &boundingRect) const;
+ double snapRightOffset(const QRectF &boundingRect) const;
+ double snapLeftOffset(const QRectF &boundingRect) const;
+ double snapBottomOffset(const QRectF &boundingRect) const;
+
+ QList<QLineF> horizontalSnappedLines(const QRectF &boundingRect, QList<QRectF> *boundingRects = 0) const;
+ QList<QLineF> verticalSnappedLines(const QRectF &boundingRect, QList<QRectF> *boundingRects = 0) const;
+
+ void setSnappingDistance(double snappingDistance);
+ double snappingDistance() const;
+
+ void updateSnappingLines(const QList<FormEditorItem*> &exceptionList);
+ void updateSnappingLines(FormEditorItem* exceptionItem);
+
+ QList<QGraphicsItem*> generateSnappingLines(const QList<QRectF> &boundingRectList,
+ QGraphicsItem *layerItem,
+ const QTransform &transform);
+ QList<QGraphicsItem*> generateSnappingLines(const QRectF &boundingRect,
+ QGraphicsItem *layerItem,
+ const QTransform &transform);
+protected:
+ double snappedOffsetForLines(const SnapLineMap &snappingLineMap,
+ double value) const;
+
+ double snappedOffsetForOffsetLines(const SnapLineMap &snappingOffsetMap,
+ Qt::Orientation orientation,
+ double value,
+ double lowerLimit,
+ double upperLimit) const;
+
+ QList<QLineF> findSnappingLines(const SnapLineMap &snappingLineMap,
+ Qt::Orientation orientation,
+ double snapLine,
+ double lowerLimit,
+ double upperLimit,
+ QList<QRectF> *boundingRects = 0) const;
+
+ QList<QLineF> findSnappingOffsetLines(const SnapLineMap &snappingOffsetMap,
+ Qt::Orientation orientation,
+ double snapLine,
+ double lowerLimit,
+ double upperLimit,
+ QList<QRectF> *boundingRects = 0) const;
+
+ QLineF createSnapLine(Qt::Orientation orientation,
+ double snapLine,
+ double lowerEdge,
+ double upperEdge,
+ const QRectF &itemRect) const;
+
+// bool canSnap(QList<double> snappingLineList, double value) const;
+private:
+ FormEditorItem *m_containerFormEditorItem;
+ FormEditorItem *m_transformtionSpaceFormEditorItem;
+ double m_snappingDistance;
+};
+
+}
+#endif // SNAPPER_H
diff --git a/src/plugins/qmldesigner/components/formeditor/snapping.png b/src/plugins/qmldesigner/components/formeditor/snapping.png
new file mode 100644
index 0000000000..ceee8b94bb
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/snapping.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/formeditor/snappinglinecreator.cpp b/src/plugins/qmldesigner/components/formeditor/snappinglinecreator.cpp
new file mode 100644
index 0000000000..7c3b9e36a3
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/snappinglinecreator.cpp
@@ -0,0 +1,190 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "snappinglinecreator.h"
+
+#include <QGraphicsItem>
+#include "onedimensionalcluster.h"
+#include "formeditoritem.h"
+#include "formeditorview.h"
+
+namespace QmlDesigner {
+
+SnappingLineCreator::SnappingLineCreator(FormEditorItem *formEditorItem)
+ : m_formEditorItem(formEditorItem),
+ m_topOffset(formEditorItem->formEditorView()->spacing()),
+ m_bottomOffset(formEditorItem->formEditorView()->spacing()),
+ m_leftOffset(formEditorItem->formEditorView()->spacing()),
+ m_rightOffset(formEditorItem->formEditorView()->spacing()),
+ m_topMargin(formEditorItem->formEditorView()->margins()),
+ m_bottomMargin(formEditorItem->formEditorView()->margins()),
+ m_leftMargin(formEditorItem->formEditorView()->margins()),
+ m_rightMargin(formEditorItem->formEditorView()->margins())
+{
+ Q_ASSERT(m_formEditorItem);
+}
+
+void SnappingLineCreator::clearLines()
+{
+ m_topLineMap.clear();
+ m_bottomLineMap.clear();
+ m_leftLineMap.clear();
+ m_rightLineMap.clear();
+ m_horizontalCenterLineMap.clear();
+ m_verticalCenterLineMap.clear();
+
+ m_topOffsetMap.clear();
+ m_bottomOffsetMap.clear();
+ m_leftOffsetMap.clear();
+ m_rightOffsetMap.clear();
+
+}
+
+void SnappingLineCreator::addLines(const QRectF &rectInSceneSpace, FormEditorItem *item)
+{
+ m_topLineMap.insert(rectInSceneSpace.top(), qMakePair(rectInSceneSpace, item));
+ m_bottomLineMap.insert(rectInSceneSpace.bottom(), qMakePair(rectInSceneSpace, item));
+ m_leftLineMap.insert(rectInSceneSpace.left(), qMakePair(rectInSceneSpace, item));
+ m_rightLineMap.insert(rectInSceneSpace.right(), qMakePair(rectInSceneSpace, item));
+ QPointF centerPoint(rectInSceneSpace.center());
+ m_horizontalCenterLineMap.insert(centerPoint.y(), qMakePair(rectInSceneSpace, item));
+ m_verticalCenterLineMap.insert(centerPoint.x(), qMakePair(rectInSceneSpace, item));
+}
+
+void SnappingLineCreator::addOffsets(const QRectF &rectInSceneSpace, FormEditorItem *item)
+{
+ m_topOffsetMap.insert(rectInSceneSpace.top() - m_topOffset, qMakePair(rectInSceneSpace, item));
+ m_bottomOffsetMap.insert(rectInSceneSpace.bottom() + m_bottomOffset, qMakePair(rectInSceneSpace, item));
+ m_leftOffsetMap.insert(rectInSceneSpace.left() - m_leftOffset, qMakePair(rectInSceneSpace, item));
+ m_rightOffsetMap.insert(rectInSceneSpace.right() + m_rightOffset, qMakePair(rectInSceneSpace, item));
+}
+
+void SnappingLineCreator::generateLines(const QList<FormEditorItem*> &exceptionList,
+ FormEditorItem *transformationSpaceItem)
+{
+ Q_ASSERT(transformationSpaceItem);
+ {
+ QRectF containerBoundingRectInTransformationSpace = m_formEditorItem->mapRectToItem(transformationSpaceItem,
+ m_formEditorItem->boundingRect());
+
+ addLines(containerBoundingRectInTransformationSpace, m_formEditorItem);
+ containerBoundingRectInTransformationSpace.adjust(m_leftMargin, m_topMargin, -m_rightMargin, -m_rightMargin);
+ addLines(containerBoundingRectInTransformationSpace, m_formEditorItem);
+ }
+
+ foreach (FormEditorItem *item, m_formEditorItem->childFormEditorItems()) {
+ if (exceptionList.contains(item))
+ continue;
+ QRectF boundingRectInContainerSpace;
+
+ boundingRectInContainerSpace = item->mapRectToItem(transformationSpaceItem, item->boundingRect());
+
+ boundingRectInContainerSpace = boundingRectInContainerSpace.toRect(); // round to integer
+
+ addLines(boundingRectInContainerSpace, item);
+ addOffsets(boundingRectInContainerSpace, item);
+ }
+}
+
+void SnappingLineCreator::setMargins(double margin)
+{
+ m_topMargin = margin;
+ m_bottomMargin = margin;
+ m_leftMargin = margin;
+ m_rightMargin = margin;
+}
+
+void SnappingLineCreator::setSpacing(double spacing)
+{
+ m_topOffset = spacing;
+ m_bottomOffset = spacing;
+ m_leftOffset = spacing;
+ m_rightOffset = spacing;
+}
+
+void SnappingLineCreator::update(const QList<FormEditorItem*> &exceptionList,
+ FormEditorItem *transformationSpaceItem)
+{
+ clearLines();
+ setMargins(m_formEditorItem->formEditorView()->margins());
+ setSpacing(m_formEditorItem->formEditorView()->spacing());
+ generateLines(exceptionList, transformationSpaceItem);
+}
+
+SnapLineMap SnappingLineCreator::topLines() const
+{
+ return m_topLineMap;
+}
+
+SnapLineMap SnappingLineCreator::bottomLines() const
+{
+ return m_bottomLineMap;
+}
+
+SnapLineMap SnappingLineCreator::leftLines() const
+{
+ return m_leftLineMap;
+}
+
+SnapLineMap SnappingLineCreator::rightLines() const
+{
+ return m_rightLineMap;
+}
+
+SnapLineMap SnappingLineCreator::horizontalCenterLines() const
+{
+ return m_horizontalCenterLineMap;
+}
+
+SnapLineMap SnappingLineCreator::verticalCenterLines() const
+{
+ return m_verticalCenterLineMap;
+}
+
+SnapLineMap SnappingLineCreator::topOffsets() const
+{
+ return m_topOffsetMap;
+}
+
+SnapLineMap SnappingLineCreator::bottomOffsets() const
+{
+ return m_bottomOffsetMap;
+}
+
+SnapLineMap SnappingLineCreator::leftOffsets() const
+{
+ return m_leftOffsetMap;
+}
+
+SnapLineMap SnappingLineCreator::rightOffsets() const
+{
+ return m_rightOffsetMap;
+}
+
+}
diff --git a/src/plugins/qmldesigner/components/formeditor/snappinglinecreator.h b/src/plugins/qmldesigner/components/formeditor/snappinglinecreator.h
new file mode 100644
index 0000000000..7d8eb3b51b
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/snappinglinecreator.h
@@ -0,0 +1,102 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef SNAPPINGLINECREATOR_H
+#define SNAPPINGLINECREATOR_H
+
+#include "layeritem.h"
+#include <QPair>
+
+namespace QmlDesigner {
+
+class FormEditorItem;
+
+typedef QMultiMap<double, QPair<QRectF, FormEditorItem*> > SnapLineMap;
+typedef QMapIterator<double, QPair<QRectF, FormEditorItem*> > SnapLineMapIterator;
+
+class FormEditorItem;
+
+class SnappingLineCreator
+{
+public:
+ SnappingLineCreator(FormEditorItem *formEditorItem);
+
+ void update(const QList<FormEditorItem*> &exceptionList,
+ FormEditorItem *transformationSpaceItem);
+
+
+ SnapLineMap topLines() const;
+ SnapLineMap bottomLines() const;
+ SnapLineMap leftLines() const;
+ SnapLineMap rightLines() const;
+ SnapLineMap horizontalCenterLines() const;
+ SnapLineMap verticalCenterLines() const;
+
+ SnapLineMap topOffsets() const;
+ SnapLineMap bottomOffsets() const;
+ SnapLineMap leftOffsets() const;
+ SnapLineMap rightOffsets() const;
+
+ void setMargins(double margin);
+ void setSpacing(double spacing);
+
+protected:
+ void addLines(const QRectF &rectInSceneSpace, FormEditorItem *item);
+ void addOffsets(const QRectF &rectInSceneSpace, FormEditorItem *item);
+
+ void clearLines();
+ void generateLines(const QList<FormEditorItem*> &exceptionList,
+ FormEditorItem *transformationSpaceItem);
+
+private:
+ SnapLineMap m_topLineMap;
+ SnapLineMap m_bottomLineMap;
+ SnapLineMap m_leftLineMap;
+ SnapLineMap m_rightLineMap;
+ SnapLineMap m_horizontalCenterLineMap;
+ SnapLineMap m_verticalCenterLineMap;
+
+ SnapLineMap m_topOffsetMap;
+ SnapLineMap m_bottomOffsetMap;
+ SnapLineMap m_leftOffsetMap;
+ SnapLineMap m_rightOffsetMap;
+
+ FormEditorItem *m_formEditorItem;
+ double m_topOffset;
+ double m_bottomOffset;
+ double m_leftOffset;
+ double m_rightOffset;
+ double m_topMargin;
+ double m_bottomMargin;
+ double m_leftMargin;
+ double m_rightMargin;
+};
+
+}
+#endif // SNAPPINGLINECREATOR_H
diff --git a/src/plugins/qmldesigner/components/formeditor/toolbox.cpp b/src/plugins/qmldesigner/components/formeditor/toolbox.cpp
new file mode 100644
index 0000000000..04d4486b78
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/toolbox.cpp
@@ -0,0 +1,81 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "toolbox.h"
+
+#include <QToolBar>
+#include <QHBoxLayout>
+#include <QPainter>
+#include <QtDebug>
+#include <QFile>
+
+namespace QmlDesigner {
+
+ToolBox::ToolBox(QWidget *parentWidget)
+ : QWidget(parentWidget),
+ m_toolBar(new QToolBar("Sidebar", this))
+{
+ QHBoxLayout *fillLayout = new QHBoxLayout(this);
+ fillLayout->setMargin(0);
+ setLayout(fillLayout);
+ //setContentsMargins(4, 12, 4, 4);
+
+ m_toolBar->setFloatable(true);
+ m_toolBar->setMovable(true);
+ m_toolBar->setOrientation(Qt::Horizontal);
+ m_toolBar->setIconSize(QSize(24, 24));
+ fillLayout->addWidget(m_toolBar);
+
+
+// QPalette toolPalette(palette());
+// QColor newColor(palette().color(QPalette::Window));
+// newColor.setAlphaF(0.7);
+// toolPalette.setColor(QPalette::Window, newColor);
+// setPalette(toolPalette);
+// setBackgroundRole(QPalette::Window);
+// setAutoFillBackground(true);
+// setAttribute(Qt::WA_NoSystemBackground, true);
+
+}
+
+
+
+void ToolBox::setActions(const QList<QAction*> &actions)
+{
+ m_toolBar->clear();
+ m_toolBar->addActions(actions);
+ resize(sizeHint());
+}
+
+void ToolBox::addAction(QAction *action)
+{
+ m_toolBar->addAction(action);
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/formeditor/toolbox.h b/src/plugins/qmldesigner/components/formeditor/toolbox.h
new file mode 100644
index 0000000000..98fed3a271
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/toolbox.h
@@ -0,0 +1,52 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef TOOLBOX_H
+#define TOOLBOX_H
+
+#include <QWidget>
+
+class QToolBar;
+
+namespace QmlDesigner {
+
+class ToolBox : public QWidget
+{
+public:
+ ToolBox(QWidget *parentWidget);
+ void setActions(const QList<QAction*> &actions);
+ void addAction(QAction *action);
+
+private:
+ QToolBar *m_toolBar;
+};
+
+} // namespace QmlDesigner
+
+#endif // TOOLBOX_H
diff --git a/src/plugins/qmldesigner/components/formeditor/transform.png b/src/plugins/qmldesigner/components/formeditor/transform.png
new file mode 100644
index 0000000000..e9e7662b3a
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/transform.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/formeditor/zoomaction.cpp b/src/plugins/qmldesigner/components/formeditor/zoomaction.cpp
new file mode 100644
index 0000000000..9a6560927f
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/zoomaction.cpp
@@ -0,0 +1,116 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "zoomaction.h"
+
+#include <QComboBox>
+#include <QLineEdit>
+#include <QEvent>
+#include <QCoreApplication>
+
+namespace QmlDesigner {
+
+
+ZoomAction::ZoomAction(QObject *parent)
+ : QWidgetAction(parent),
+ m_zoomLevel(1.0),
+ m_currentComboBoxIndex(-1)
+{
+
+}
+
+double ZoomAction::zoomLevel() const
+{
+ return m_zoomLevel;
+}
+
+void ZoomAction::zoomIn()
+{
+ if (m_currentComboBoxIndex > 0)
+ emit indexChanged(m_currentComboBoxIndex - 1);
+}
+
+void ZoomAction::zoomOut()
+{
+ if (m_currentComboBoxIndex < (m_comboBoxModel->rowCount() - 1))
+ emit indexChanged(m_currentComboBoxIndex + 1);
+}
+
+void ZoomAction::setZoomLevel(double zoomLevel)
+{
+ if (zoomLevel < .1) {
+ m_zoomLevel = 0.1;
+ } else if (zoomLevel > 16.0) {
+ m_zoomLevel = 16.0;
+ } else {
+ m_zoomLevel = zoomLevel;
+ }
+
+ emit zoomLevelChanged(m_zoomLevel);
+}
+
+
+QWidget *ZoomAction::createWidget(QWidget *parent)
+{
+ QComboBox *comboBox = new QComboBox(parent);
+
+ if (m_comboBoxModel.isNull()) {
+ m_comboBoxModel = comboBox->model();
+ comboBox->addItem("10 %", 0.1);
+ comboBox->addItem("25 %", 0.25);
+ comboBox->addItem("50 %", 0.5);
+ comboBox->addItem("100 %", 1.0);
+ comboBox->addItem("200 %", 2.0);
+ comboBox->addItem("400 %", 4.0);
+ comboBox->addItem("800 %", 8.0);
+ comboBox->addItem("1600 %", 16.0);
+
+ } else {
+ comboBox->setModel(m_comboBoxModel.data());
+ }
+
+ comboBox->setCurrentIndex(3);
+ connect(comboBox, SIGNAL(currentIndexChanged(int)), SLOT(emitZoomLevelChanged(int)));
+ connect(this, SIGNAL(indexChanged(int)), comboBox, SLOT(setCurrentIndex(int)));
+
+ return comboBox;
+}
+
+void ZoomAction::emitZoomLevelChanged(int index)
+{
+ m_currentComboBoxIndex = index;
+
+ if (index == -1)
+ return;
+
+ QModelIndex modelIndex(m_comboBoxModel.data()->index(index, 0));
+ setZoomLevel(m_comboBoxModel.data()->data(modelIndex, Qt::UserRole).toDouble());
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/formeditor/zoomaction.h b/src/plugins/qmldesigner/components/formeditor/zoomaction.h
new file mode 100644
index 0000000000..02ceb9acc0
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/zoomaction.h
@@ -0,0 +1,68 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef ZOOMACTION_H
+#define ZOOMACTION_H
+
+#include <QWidgetAction>
+
+class QAbstractItemModel;
+
+namespace QmlDesigner {
+
+class ZoomAction : public QWidgetAction
+{
+ Q_OBJECT
+
+public:
+ ZoomAction(QObject *parent);
+
+ double zoomLevel() const;
+
+ void zoomIn();
+ void zoomOut();
+
+protected:
+ QWidget *createWidget(QWidget *parent);
+ void setZoomLevel(double zoomLevel);
+signals:
+ void zoomLevelChanged(double zoom);
+ void indexChanged(int);
+private slots:
+ void emitZoomLevelChanged(int index);
+
+private:
+ QWeakPointer<QAbstractItemModel> m_comboBoxModel;
+ double m_zoomLevel;
+ int m_currentComboBoxIndex;
+};
+
+} // namespace QmlDesigner
+
+#endif // ZOOMACTION_H
diff --git a/src/plugins/qmldesigner/components/integration/allpropertiesviewcontroller.cpp b/src/plugins/qmldesigner/components/integration/allpropertiesviewcontroller.cpp
new file mode 100644
index 0000000000..c1956ee6a0
--- /dev/null
+++ b/src/plugins/qmldesigner/components/integration/allpropertiesviewcontroller.cpp
@@ -0,0 +1,64 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <QtGui/QStackedWidget>
+
+#include <allpropertiesbox.h>
+
+#include "designdocumentcontroller.h"
+#include "allpropertiesviewcontroller.h"
+
+namespace QmlDesigner {
+
+AllPropertiesViewController::AllPropertiesViewController(QObject* parent):
+ StackedUtilityPanelController(parent)
+{
+ setObjectName("PropertiesViewController");
+}
+
+QWidget* AllPropertiesViewController::stackedPageWidget(DesignDocumentController* designDocumentController) const
+{
+ return designDocumentController->allPropertiesBox();
+}
+
+void AllPropertiesViewController::showNewLookProperties()
+{
+ AllPropertiesBox* propsBox = dynamic_cast<AllPropertiesBox*>(dynamic_cast<QStackedWidget*>(contentWidget())->currentWidget());
+ if (propsBox)
+ propsBox->showNewLook();
+}
+
+void AllPropertiesViewController::showTraditionalProperties()
+{
+ AllPropertiesBox* propsBox = dynamic_cast<AllPropertiesBox*>(dynamic_cast<QStackedWidget*>(contentWidget())->currentWidget());
+ if (propsBox)
+ propsBox->showTraditional();
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/integration/allpropertiesviewcontroller.h b/src/plugins/qmldesigner/components/integration/allpropertiesviewcontroller.h
new file mode 100644
index 0000000000..15eff733d0
--- /dev/null
+++ b/src/plugins/qmldesigner/components/integration/allpropertiesviewcontroller.h
@@ -0,0 +1,54 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef ALLPROPERTIESVIEWCONTROLLER_H
+#define ALLPROPERTIESVIEWCONTROLLER_H
+
+#include "stackedutilitypanelcontroller.h"
+
+namespace QmlDesigner {
+
+class AllPropertiesViewController : public StackedUtilityPanelController
+{
+ Q_OBJECT
+
+public:
+ AllPropertiesViewController(QObject* parent = 0);
+
+public slots:
+ void showNewLookProperties();
+ void showTraditionalProperties();
+
+protected:
+ class QWidget* stackedPageWidget(class DesignDocumentController* designDocumentController) const;
+};
+
+} // namespace QmlDesigner
+
+#endif // ALLPROPERTIESVIEWCONTROLLER_H
diff --git a/src/plugins/qmldesigner/components/integration/componentaction.cpp b/src/plugins/qmldesigner/components/integration/componentaction.cpp
new file mode 100644
index 0000000000..450cab497e
--- /dev/null
+++ b/src/plugins/qmldesigner/components/integration/componentaction.cpp
@@ -0,0 +1,74 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "componentaction.h"
+
+#include <QComboBox>
+#include "componentview.h"
+#include <QStandardItemModel>
+#include <QtDebug>
+
+namespace QmlDesigner {
+
+ComponentAction::ComponentAction(QObject *parent)
+ : QWidgetAction(parent),
+ m_componentView(new ComponentView(this))
+{
+}
+
+void ComponentAction::setModel(Model* model)
+{
+ if (model == m_componentView->model())
+ return;
+
+ blockSignals(true);
+
+ if (model)
+ model->attachView(m_componentView.data());
+ else if (m_componentView->model())
+ m_componentView->model()->detachView(m_componentView.data());
+
+ blockSignals(false);
+}
+
+QWidget *ComponentAction::createWidget(QWidget *parent)
+{
+ QComboBox *comboBox = new QComboBox(parent);
+ comboBox->setModel(m_componentView->standardItemModel());
+ connect(comboBox, SIGNAL(currentIndexChanged(int)), SLOT(emitCurrentComponentChanged(int)));
+
+ return comboBox;
+}
+
+void ComponentAction::emitCurrentComponentChanged(int index)
+{
+ emit currentComponentChanged(m_componentView->modelNode(index));
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/integration/componentaction.h b/src/plugins/qmldesigner/components/integration/componentaction.h
new file mode 100644
index 0000000000..e4ee74645f
--- /dev/null
+++ b/src/plugins/qmldesigner/components/integration/componentaction.h
@@ -0,0 +1,66 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef COMPONENTACTION_H
+#define COMPONENTACTION_H
+
+#include <QWidgetAction>
+#include <QWeakPointer>
+
+class QComboBox;
+
+namespace QmlDesigner {
+
+class Model;
+class ComponentView;
+class ModelNode;
+
+class ComponentAction : public QWidgetAction
+{
+ Q_OBJECT
+public:
+ ComponentAction(QObject *parent);
+ void setModel(Model* model);
+
+protected:
+ QWidget *createWidget(QWidget *parent);
+
+signals:
+ void currentComponentChanged(const ModelNode &node);
+
+private slots:
+ void emitCurrentComponentChanged(int index);
+
+private:
+ QWeakPointer<ComponentView> m_componentView;
+};
+
+} // namespace QmlDesigner
+
+#endif // COMPONENTACTION_H
diff --git a/src/plugins/qmldesigner/components/integration/componentview.cpp b/src/plugins/qmldesigner/components/integration/componentview.cpp
new file mode 100644
index 0000000000..ccd0a39518
--- /dev/null
+++ b/src/plugins/qmldesigner/components/integration/componentview.cpp
@@ -0,0 +1,179 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "componentview.h"
+#include <QtDebug>
+
+#include <nodemetainfo.h>
+#include <QStandardItemModel>
+
+// silence gcc warnings about unused parameters
+
+namespace QmlDesigner {
+
+ComponentView::ComponentView(QObject *parent)
+ : AbstractView(parent),
+ m_standardItemModel(new QStandardItemModel(this)),
+ m_listChanged(false)
+{
+}
+
+
+
+void ComponentView::nodeAboutToBeRemoved(const ModelNode &removedNode)
+{
+ for (int index = 1; index < m_standardItemModel->rowCount(); index++) {
+ QStandardItem *item = m_standardItemModel->item(index);
+ if (item->data(ModelNodeRole).value<ModelNode>() == removedNode)
+ m_standardItemModel->removeRow(index);
+ }
+}
+
+QStandardItemModel *ComponentView::standardItemModel() const
+{
+ return m_standardItemModel;
+}
+
+ModelNode ComponentView::modelNode(int index) const
+{
+ if (m_standardItemModel->hasIndex(index, 0)) {
+ QStandardItem *item = m_standardItemModel->item(index, 0);
+ return item->data(ModelNodeRole).value<ModelNode>();
+ }
+
+ return ModelNode();
+}
+
+void ComponentView::appendWholeDocumentAsComponent()
+{
+ QStandardItem *item = new QStandardItem("Whole Document");
+ item->setData(QVariant::fromValue(rootModelNode()), ModelNodeRole);
+ item->setEditable(false);
+ m_standardItemModel->appendRow(item);
+}
+
+void ComponentView::modelAttached(Model *model)
+{
+ if (AbstractView::model() == model)
+ return;
+
+ AbstractView::modelAttached(model);
+
+ Q_ASSERT(model->masterModel());
+ appendWholeDocumentAsComponent();
+ searchForComponentAndAddToList(rootModelNode());
+}
+
+void ComponentView::modelAboutToBeDetached(Model *model)
+{
+ m_standardItemModel->clear();
+ AbstractView::modelAboutToBeDetached(model);
+}
+
+void ComponentView::nodeCreated(const ModelNode &createdNode)
+{
+ searchForComponentAndAddToList(createdNode);
+}
+
+void ComponentView::searchForComponentAndAddToList(const ModelNode &node)
+{
+ QList<ModelNode> nodeList;
+ nodeList.append(node);
+ nodeList.append(node.allSubModelNodes());
+
+
+ foreach (const ModelNode &childNode, nodeList) {
+ if (childNode.type() == "Qt/Component") {
+ if (!childNode.id().isEmpty()) {
+ QStandardItem *item = new QStandardItem(childNode.id());
+ item->setData(QVariant::fromValue(childNode), ModelNodeRole);
+ item->setEditable(false);
+ m_standardItemModel->appendRow(item);
+ }
+ } else if (node.metaInfo().isComponent() && !m_componentList.contains(node.type())) {
+ m_componentList.append(node.type());
+ m_componentList.sort();
+ m_listChanged = true;
+ }
+ }
+}
+
+void ComponentView::nodeRemoved(const ModelNode & /*removedNode*/, const NodeAbstractProperty & /*parentProperty*/, PropertyChangeFlags /*propertyChange*/)
+{
+
+}
+
+//void ComponentView::searchForComponentAndRemoveFromList(const ModelNode &node)
+//{
+// QList<ModelNode> nodeList;
+// nodeList.append(node);
+// nodeList.append(node.allSubModelNodes());
+//
+//
+// foreach (const ModelNode &childNode, nodeList) {
+// if (node.type() == "Qt/Component") {
+// if (!node.id().isEmpty()) {
+// for(int row = 0; row < m_standardItemModel->rowCount(); row++) {
+// if (m_standardItemModel->item(row)->text() == node.id())
+// m_standardItemModel->removeRow(row);
+// }
+// }
+// } else if (node.metaInfo().isComponent() && !m_componentList.contains(node.type())) {
+// m_componentList.append(node.type());
+// m_componentList.sort();
+// m_listChanged = true;
+// }
+// }
+//}
+
+void ComponentView::nodeReparented(const ModelNode &/*node*/, const NodeAbstractProperty &/*newPropertyParent*/, const NodeAbstractProperty &/*oldPropertyParent*/, AbstractView::PropertyChangeFlags /*propertyChange*/) {}
+void ComponentView::nodeIdChanged(const ModelNode& /*node*/, const QString& /*newId*/, const QString& /*oldId*/) {}
+void ComponentView::propertiesAboutToBeRemoved(const QList<AbstractProperty>& /*propertyList*/) {}
+void ComponentView::propertiesRemoved(const QList<AbstractProperty>& /*propertyList*/) {}
+void ComponentView::variantPropertiesChanged(const QList<VariantProperty>& /*propertyList*/, PropertyChangeFlags /*propertyChange*/) {}
+void ComponentView::bindingPropertiesChanged(const QList<BindingProperty>& /*propertyList*/, PropertyChangeFlags /*propertyChange*/) {}
+void ComponentView::nodeTypeChanged(const ModelNode &/*node*/, const QString &/*type*/, int /*majorVersion*/, int /*minorVersion*/) {}
+
+
+
+void ComponentView::selectedNodesChanged(const QList<ModelNode> &/*selectedNodeList*/,
+ const QList<ModelNode> &/*lastSelectedNodeList*/) {}
+
+void ComponentView::fileUrlChanged(const QUrl &/*oldUrl*/, const QUrl &/*newUrl*/) {}
+
+void ComponentView::nodeSlidedToIndex(const NodeListProperty &/*listProperty*/, int /*newIndex*/, int /*oldIndex*/) {}
+
+void ComponentView::importsChanged() {}
+
+void ComponentView::auxiliaryDataChanged(const ModelNode &/*node*/, const QString &/*name*/, const QVariant &/*data*/) {}
+
+void ComponentView::customNotification(const AbstractView */*view*/, const QString &/*identifier*/, const QList<ModelNode> &/*nodeList*/, const QList<QVariant> &/*data*/) {}
+
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/integration/componentview.h b/src/plugins/qmldesigner/components/integration/componentview.h
new file mode 100644
index 0000000000..b4ec1e8361
--- /dev/null
+++ b/src/plugins/qmldesigner/components/integration/componentview.h
@@ -0,0 +1,105 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef COMPONENTVIEW_H
+#define COMPONENTVIEW_H
+
+#include <abstractview.h>
+#include <modelnode.h>
+
+#include <QStringList>
+
+class QStandardItemModel;
+
+namespace QmlDesigner {
+
+class ComponentView : public AbstractView
+{
+ Q_OBJECT
+
+public:
+ enum UserRoles
+ {
+ ModelNodeRole = Qt::UserRole
+ };
+
+ ComponentView(QObject *parent);
+
+ void modelAttached(Model *model);
+ void modelAboutToBeDetached(Model *model);
+
+ void nodeCreated(const ModelNode &createdNode);
+ void nodeAboutToBeRemoved(const ModelNode &removedNode);
+ void nodeRemoved(const ModelNode &removedNode, const NodeAbstractProperty &parentProperty, PropertyChangeFlags propertyChange);
+ void nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange);
+ void nodeIdChanged(const ModelNode& node, const QString& newId, const QString& oldId);
+ void propertiesAboutToBeRemoved(const QList<AbstractProperty>& propertyList);
+ void propertiesRemoved(const QList<AbstractProperty>& propertyList);
+ void variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags propertyChange);
+ void bindingPropertiesChanged(const QList<BindingProperty>& propertyList, PropertyChangeFlags propertyChange);
+ void nodeTypeChanged(const ModelNode &node,const QString &type, int majorVersion, int minorVersion);
+
+
+
+ void selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
+ const QList<ModelNode> &lastSelectedNodeList);
+
+ void fileUrlChanged(const QUrl &oldUrl, const QUrl &newUrl);
+
+ void nodeSlidedToIndex(const NodeListProperty &listProperty, int newIndex, int oldIndex);
+
+ void importsChanged();
+
+ void auxiliaryDataChanged(const ModelNode &node, const QString &name, const QVariant &data);
+
+ void customNotification(const AbstractView *view, const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> &data);
+
+
+ QStandardItemModel *standardItemModel() const;
+
+ ModelNode modelNode(int index) const;
+
+signals:
+ void componentListChanged(const QStringList &componentList);
+
+private: //functions
+ void updateModel();
+ void searchForComponentAndAddToList(const ModelNode &node);
+// void searchForComponentAndRemoveFromList(const ModelNode &node);
+ void appendWholeDocumentAsComponent();
+
+private:
+ QStringList m_componentList;
+ QStandardItemModel *m_standardItemModel;
+ bool m_listChanged;
+};
+
+} // namespace QmlDesigner
+
+#endif // COMPONENTVIEW_H
diff --git a/src/plugins/qmldesigner/components/integration/designdocumentcontroller.cpp b/src/plugins/qmldesigner/components/integration/designdocumentcontroller.cpp
new file mode 100644
index 0000000000..b0602c8689
--- /dev/null
+++ b/src/plugins/qmldesigner/components/integration/designdocumentcontroller.cpp
@@ -0,0 +1,815 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "designdocumentcontroller.h"
+#include "designdocumentcontrollerview.h"
+#include "xuifiledialog.h"
+#include "componentview.h"
+#include "subcomponentmanager.h"
+#include "model/viewlogger.h"
+
+#include <allpropertiesbox.h>
+#include <itemlibrary.h>
+#include <navigatorview.h>
+#include <stateseditorwidget.h>
+#include <formeditorview.h>
+#include <formeditorwidget.h>
+#include <plaintexteditmodifier.h>
+#include <componenttextmodifier.h>
+#include <metainfo.h>
+#include <invalidargumentexception.h>
+#include <componentaction.h>
+#include <qmlobjectnode.h>
+#include <rewriterview.h>
+#include <nodelistproperty.h>
+#include <toolbox.h>
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDir>
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+#include <QtCore/QUrl>
+#include <QtCore/QProcess>
+#include <QtCore/QTemporaryFile>
+#include <QtCore/QtDebug>
+#include <QtCore/QEvent>
+
+#include <QtGui/QBoxLayout>
+#include <QtGui/QComboBox>
+#include <QtGui/QErrorMessage>
+#include <QtGui/QFileDialog>
+#include <QtGui/QLabel>
+#include <QtGui/QMdiArea>
+#include <QtGui/QMdiSubWindow>
+#include <QtGui/QMessageBox>
+#include <QtGui/QUndoStack>
+#include <QtGui/QPlainTextEdit>
+
+enum {
+ debug = false
+};
+
+namespace QmlDesigner {
+
+class DesignDocumentControllerPrivate {
+public:
+ QWeakPointer<FormEditorView> formEditorView;
+
+ QWeakPointer<ItemLibrary> itemLibrary;
+ QWeakPointer<NavigatorView> navigator;
+ QWeakPointer<AllPropertiesBox> allPropertiesBox;
+ QWeakPointer<StatesEditorWidget> statesEditorWidget;
+ QWeakPointer<QStackedWidget> stackedWidget;
+
+ QWeakPointer<QmlDesigner::Model> model;
+ QWeakPointer<QmlDesigner::Model> subComponentModel;
+ QWeakPointer<QmlDesigner::Model> masterModel;
+ QWeakPointer<QPlainTextEdit> textEdit;
+ QWeakPointer<RewriterView> rewriterView;
+ QmlDesigner::PlainTextEditModifier *textModifier;
+ QmlDesigner::ComponentTextModifier *componentTextModifier;
+ QWeakPointer<SubComponentManager> subComponentManager;
+ QWeakPointer<Internal::ViewLogger> viewLogger;
+
+ QWeakPointer<QProcess> previewProcess;
+ QWeakPointer<QProcess> previewWithDebugProcess;
+
+ QString fileName;
+ QUrl searchPath;
+ bool documentLoaded;
+ bool syncBlocked;
+
+};
+
+/**
+ \class QmlDesigner::DesignDocumentController
+
+ DesignDocumentController acts as a facade to a model representing a qml document,
+ and the different views/widgets accessing it.
+ */
+DesignDocumentController::DesignDocumentController(QObject *parent) :
+ QObject(parent),
+ m_d(new DesignDocumentControllerPrivate)
+{
+ m_d->itemLibrary = new ItemLibrary;
+ m_d->navigator = new NavigatorView(this);
+ m_d->allPropertiesBox = new AllPropertiesBox;
+ m_d->statesEditorWidget = new StatesEditorWidget;
+ m_d->stackedWidget = new QStackedWidget;
+
+ m_d->documentLoaded = false;
+ m_d->syncBlocked = false;
+}
+
+DesignDocumentController::~DesignDocumentController()
+{
+ delete m_d->formEditorView.data();
+
+ // deleting the widgets should be safe because these are QWeakPointer's
+ delete m_d->itemLibrary.data();
+ delete m_d->allPropertiesBox.data();
+ delete m_d->statesEditorWidget.data();
+ delete m_d->stackedWidget.data();
+
+ delete m_d->model.data();
+ delete m_d->subComponentModel.data();
+
+ delete m_d->rewriterView.data();
+ // m_d->textEdit is child of stackedWidget or owned by external widget
+ delete m_d->textModifier;
+
+ if (m_d->componentTextModifier) //componentTextModifier might not be created
+ delete m_d->componentTextModifier;
+
+ delete m_d->previewProcess.data();
+ delete m_d->previewWithDebugProcess.data();
+
+ delete m_d;
+}
+
+Model *DesignDocumentController::model() const
+{
+ return m_d->model.data();
+}
+
+Model *DesignDocumentController::masterModel() const
+{
+ return m_d->masterModel.data();
+}
+
+QWidget *DesignDocumentController::documentWidget() const
+{
+ return m_d->stackedWidget.data();
+}
+
+void DesignDocumentController::togglePreview(bool visible)
+{
+ if (!m_d->documentLoaded)
+ return;
+
+ if (visible) {
+ Q_ASSERT(!m_d->previewProcess);
+
+ QString directory;
+ if (!m_d->fileName.isEmpty()) {
+ directory = QFileInfo(m_d->fileName).absoluteDir().path();
+ } else {
+ directory = QDir::tempPath();
+ }
+ m_d->previewProcess = createPreviewProcess(directory);
+ connect(m_d->previewProcess.data(), SIGNAL(finished(int, QProcess::ExitStatus)),
+ this, SLOT(emitPreviewVisibilityChanged()));
+ } else {
+ Q_ASSERT(m_d->previewProcess);
+
+ delete m_d->previewProcess.data();
+ }
+}
+
+void DesignDocumentController::toggleWithDebugPreview(bool visible)
+{
+ if (!m_d->documentLoaded)
+ return;
+
+ if (visible) {
+ Q_ASSERT(!m_d->previewWithDebugProcess);
+
+ QString directory;
+ if (!m_d->fileName.isEmpty()) {
+ directory = QFileInfo(m_d->fileName).absoluteDir().path();
+ } else {
+ directory = QDir::tempPath();
+ }
+ m_d->previewWithDebugProcess = createPreviewWithDebugProcess(directory);
+ connect(m_d->previewWithDebugProcess.data(), SIGNAL(finished(int, QProcess::ExitStatus)),
+ this, SLOT(emitPreviewWithDebugVisibilityChanged()));
+ } else {
+ Q_ASSERT(m_d->previewWithDebugProcess);
+
+ delete m_d->previewWithDebugProcess.data();
+ }
+}
+
+bool DesignDocumentController::previewVisible() const
+{
+ if (!m_d->documentLoaded)
+ return false;
+
+ return m_d->previewProcess;
+}
+
+bool DesignDocumentController::previewWithDebugVisible() const
+{
+ if (!m_d->documentLoaded)
+ return false;
+
+ return m_d->previewWithDebugProcess;
+}
+
+
+/*!
+ Returns whether the model is automatically updated if the text editor changes.
+ */
+bool DesignDocumentController::isModelSyncBlocked() const
+{
+ return m_d->syncBlocked;
+}
+
+/*!
+ Switches whether the model (and therefore the views) are updated if the text editor
+ changes.
+
+ If the synchronization is enabled again, the model is automatically resynchronized
+ with the current state of the text editor.
+ */
+void DesignDocumentController::blockModelSync(bool block)
+{
+ if (m_d->syncBlocked == block)
+ return;
+
+ m_d->syncBlocked = block;
+
+ if (m_d->textModifier) {
+ if (m_d->syncBlocked) {
+ m_d->textModifier->deactivateChangeSignals();
+ } else {
+ m_d->textModifier->reactivateChangeSignals();
+ }
+ }
+}
+
+/*!
+ Returns any errors that happened when parsing the latest qml file.
+ */
+QList<RewriterView::Error> DesignDocumentController::qmlErrors() const
+{
+ return m_d->rewriterView->errors();
+}
+
+void DesignDocumentController::emitPreviewVisibilityChanged()
+{
+ emit previewVisibilityChanged(false);
+}
+
+void DesignDocumentController::emitPreviewWithDebugVisibilityChanged()
+{
+ emit previewWithDebugVisibilityChanged(false);
+}
+
+QString DesignDocumentController::displayName() const
+{
+ if (fileName().isEmpty())
+ return tr("-New Form-");
+ else
+ return fileName();
+}
+
+QString DesignDocumentController::fileName() const
+{
+ return m_d->fileName;
+}
+
+void DesignDocumentController::setFileName(const QString &fileName)
+{
+ m_d->fileName = fileName;
+
+ if (QFileInfo(fileName).exists()) {
+ m_d->searchPath = QUrl::fromLocalFile(fileName);
+ } else {
+ m_d->searchPath = QUrl(fileName);
+ }
+
+ if (m_d->model)
+ m_d->model->setFileUrl(m_d->searchPath);
+
+ if (m_d->itemLibrary)
+ m_d->itemLibrary->setResourcePath(QFileInfo(fileName).absolutePath());
+ emit displayNameChanged(displayName());
+}
+
+QList<RewriterView::Error> DesignDocumentController::loadMaster(QPlainTextEdit *edit)
+{
+ Q_CHECK_PTR(edit);
+
+ m_d->textEdit = edit;
+
+ connect(edit, SIGNAL(undoAvailable(bool)),
+ this, SIGNAL(undoAvailable(bool)));
+ connect(edit, SIGNAL(redoAvailable(bool)),
+ this, SIGNAL(redoAvailable(bool)));
+ connect(edit, SIGNAL(modificationChanged(bool)),
+ this, SIGNAL(dirtyStateChanged(bool)));
+
+ m_d->textModifier = new PlainTextEditModifier(m_d->textEdit.data());
+
+ m_d->componentTextModifier = 0;
+
+ //m_d->masterModel = Model::create(m_d->textModifier, m_d->searchPath, errors);
+
+ m_d->masterModel = Model::create("Item", 4, 6);
+ m_d->masterModel->setFileUrl(m_d->searchPath);
+
+ m_d->subComponentModel = Model::create("Item", 4, 6);
+ m_d->subComponentModel->setFileUrl(m_d->searchPath);
+
+ m_d->subComponentManager = new SubComponentManager(m_d->masterModel->metaInfo(), this);
+ m_d->subComponentManager->update(m_d->searchPath, m_d->textModifier->text().toUtf8());
+
+ m_d->rewriterView = new RewriterView(RewriterView::Amend, m_d->masterModel.data());
+ m_d->rewriterView->setTextModifier( m_d->textModifier);
+ connect(m_d->rewriterView.data(), SIGNAL(errorsChanged(const QList<RewriterView::Error> &)),
+ this, SIGNAL(qmlErrorsChanged(const QList<RewriterView::Error> &)));
+
+ m_d->masterModel->attachView(m_d->rewriterView.data());
+ m_d->model = m_d->masterModel;
+
+#if defined(VIEWLOGGER)
+ m_d->viewLogger = new Internal::ViewLogger(m_d->model.data());
+ m_d->masterModel->attachView(m_d->viewLogger.data());
+#endif
+
+ // m_d->masterModel->detachView(m_d->rewriterView.data());
+
+ QList<RewriterView::Error> errors = m_d->rewriterView->errors();
+ if (errors.isEmpty())
+ loadCurrentModel();
+
+ return errors;
+}
+
+void DesignDocumentController::changeCurrentModelTo(const ModelNode &componentNode)
+{
+ Q_ASSERT(m_d->masterModel);
+ QWeakPointer<Model> oldModel = m_d->model;
+ Q_ASSERT(oldModel.data());
+
+ if (m_d->model == m_d->subComponentModel) {
+ //change back to master model
+ m_d->model->detachView(m_d->rewriterView.data());
+ m_d->rewriterView->setTextModifier(m_d->textModifier);
+ m_d->model = m_d->masterModel;
+ m_d->model->attachView(m_d->rewriterView.data());
+ }
+ if (!componentNode.isRootNode()) {
+ Q_ASSERT(m_d->model == m_d->masterModel);
+ Q_ASSERT(componentNode.isValid());
+ //change to subcomponent model
+ ModelNode rootModelNode = componentNode.view()->rootModelNode();
+ Q_ASSERT(rootModelNode.isValid());
+ if (m_d->componentTextModifier)
+ delete m_d->componentTextModifier;
+
+ int componentStartOffset = m_d->rewriterView->firstDefinitionInsideOffset(componentNode);
+ int componentEndOffset = componentStartOffset + m_d->rewriterView->firstDefinitionInsideLength(componentNode);
+ int rootStartOffset = m_d->rewriterView->nodeOffset(rootModelNode);
+
+ m_d->componentTextModifier = new ComponentTextModifier (m_d->textModifier, componentStartOffset, componentEndOffset, rootStartOffset);
+
+
+ m_d->model->detachView(m_d->rewriterView.data());
+
+ m_d->rewriterView->setTextModifier(m_d->componentTextModifier);
+
+ m_d->subComponentModel->attachView(m_d->rewriterView.data());
+
+ Q_ASSERT(m_d->rewriterView->rootModelNode().isValid());
+
+ m_d->model = m_d->subComponentModel;
+ }
+
+ Q_ASSERT(m_d->masterModel);
+ Q_ASSERT(m_d->model);
+
+ loadCurrentModel();
+}
+
+ void DesignDocumentController::loadCurrentModel()
+ {
+ Q_ASSERT(m_d->masterModel);
+ Q_ASSERT(m_d->model);
+ m_d->model->setMasterModel(m_d->masterModel.data());
+
+ m_d->allPropertiesBox->setModel(m_d->model.data());
+
+ m_d->model->attachView(m_d->navigator.data());
+ m_d->itemLibrary->setMetaInfo(m_d->model->metaInfo());
+
+ if (m_d->formEditorView .isNull()) {
+ m_d->formEditorView = new FormEditorView(this);
+ m_d->stackedWidget->addWidget(m_d->formEditorView->widget());
+ ComponentAction *componentAction = new ComponentAction(m_d->formEditorView->widget());
+ componentAction->setModel(m_d->model.data());
+ m_d->formEditorView->widget()->toolBox()->addAction(componentAction);
+ connect(componentAction, SIGNAL(currentComponentChanged(ModelNode)), SLOT(changeCurrentModelTo(ModelNode))); //TODO component action
+ connect(m_d->itemLibrary.data(), SIGNAL(itemActivated(const QString&)), m_d->formEditorView.data(), SLOT(activateItemCreator(const QString&)));
+ }
+
+ m_d->model->attachView(m_d->formEditorView.data());
+
+
+ if (!m_d->textEdit->parent()) // hack to prevent changing owner of external text edit
+ m_d->stackedWidget->addWidget(m_d->textEdit.data());
+
+ // Will call setCurrentState (formEditorView etc has to be constructed first)
+ m_d->statesEditorWidget->setup(m_d->model.data());
+
+ m_d->documentLoaded = true;
+ Q_ASSERT(m_d->masterModel);
+ }
+
+QList<RewriterView::Error> DesignDocumentController::loadMaster(const QByteArray &qml)
+{
+ QPlainTextEdit *textEdit = new QPlainTextEdit;
+ textEdit->setReadOnly(true);
+ textEdit->setPlainText(QString(qml));
+ return loadMaster(textEdit);
+}
+
+void DesignDocumentController::saveAs(QWidget *parent)
+{
+ QFileInfo oldFileInfo(m_d->fileName);
+ XUIFileDialog::runSaveFileDialog(oldFileInfo.path(), parent, this, SLOT(doRealSaveAs(QString)));
+}
+
+void DesignDocumentController::doRealSaveAs(const QString &fileName)
+{
+ if (fileName.isNull())
+ return;
+
+ QFileInfo fileInfo(fileName);
+ if (fileInfo.exists() && !fileInfo.isWritable()) {
+ QMessageBox msgBox(documentWidget());
+ msgBox.setIcon(QMessageBox::Warning);
+ msgBox.setText(tr("Cannot save to file \"%1\": permission denied.").arg(fileInfo.baseName()));
+ msgBox.exec();
+ return;
+ } else if (!fileInfo.exists() && !fileInfo.dir().exists()) {
+ QMessageBox msgBox(documentWidget());
+ msgBox.setIcon(QMessageBox::Warning);
+ msgBox.setText(tr("Parent folder \"%1\" for file \"%2\" does not exist.")
+ .arg(fileInfo.dir().dirName())
+ .arg(fileInfo.baseName()));
+ msgBox.exec();
+ return;
+ }
+
+ setFileName(fileName);
+ save(documentWidget());
+}
+
+bool DesignDocumentController::save(QWidget *parent)
+{
+// qDebug() << "Saving document to file \"" << m_d->fileName << "\"...";
+//
+ if (m_d->fileName.isEmpty()) {
+ saveAs(parent);
+ return true;
+ }
+ QFile file(m_d->fileName);
+ if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ showError(tr("Cannot write file: \"%1\".").arg(m_d->fileName), parent);
+ return false;
+ }
+
+ QString errorMessage;
+ bool result = save(&file, &errorMessage);
+ if (!result)
+ showError(errorMessage, parent);
+ return result;
+}
+
+bool DesignDocumentController::isDirty() const
+{
+ if (m_d->textEdit)
+ return m_d->textEdit->document()->isModified();
+ else
+ return false;
+}
+
+bool DesignDocumentController::isUndoAvailable() const
+{
+ return m_d->textEdit->document()->isUndoAvailable();
+}
+
+bool DesignDocumentController::isRedoAvailable() const
+{
+ return m_d->textEdit->document()->isRedoAvailable();
+}
+
+void DesignDocumentController::close()
+{
+ documentWidget()->close();
+ m_d->documentLoaded = false;
+ emit designDocumentClosed();
+}
+
+void DesignDocumentController::deleteSelected()
+{
+ if (!m_d->model)
+ return;
+
+ if (m_d->formEditorView) {
+ QList<ModelNode> toDelete = m_d->formEditorView->selectedModelNodes();
+ foreach (ModelNode node, toDelete) {
+ if (node.isValid() && !node.isRootNode() && QmlObjectNode(node).isValid())
+ QmlObjectNode(node).destroy();
+ }
+ }
+}
+
+void DesignDocumentController::copySelected()
+{
+ QScopedPointer<Model> model(Model::create("Qt/Rectangle"));
+ Q_ASSERT(model);
+
+ DesignDocumentControllerView view;
+
+ m_d->model->attachView(&view);
+
+ if (view.selectedModelNodes().isEmpty())
+ return;
+
+ QList<ModelNode> selectedNodes(view.selectedModelNodes());
+
+ foreach (const ModelNode &node, selectedNodes) {
+ foreach (const ModelNode &node2, selectedNodes) {
+ if (node.isAncestorOf(node2))
+ selectedNodes.removeAll(node2);
+ }
+ }
+
+ if (selectedNodes.count() == 1) {
+ ModelNode selectedNode(selectedNodes.first());
+
+ if (!selectedNode.isValid())
+ return;
+
+ m_d->model->detachView(&view);
+
+ model->attachView(&view);
+ view.replaceModel(selectedNode);
+
+ Q_ASSERT(view.rootModelNode().isValid());
+ Q_ASSERT(view.rootModelNode().type() != "empty");
+
+ view.toClipboard();
+ } else { //multi items selected
+ m_d->model->detachView(&view);
+ model->attachView(&view);
+
+ foreach (ModelNode node, view.rootModelNode().allDirectSubModelNodes()) {
+ node.destroy();
+ }
+ view.rootModelNode().changeType("Qt/Rectangle", 4, 6);
+ view.rootModelNode().setId("designer__Selection");
+
+ foreach (const ModelNode &selectedNode, selectedNodes) {
+ ModelNode newNode(view.insertModel(selectedNode));
+ view.rootModelNode().nodeListProperty("data").reparentHere(newNode);
+ }
+
+ view.toClipboard();
+ }
+}
+
+void DesignDocumentController::cutSelected()
+{
+ copySelected();
+ deleteSelected();
+}
+
+void DesignDocumentController::paste()
+{
+ QScopedPointer<Model> model(Model::create("empty"));
+ Q_ASSERT(model);
+
+ if (!m_d->model)
+ return;
+
+ DesignDocumentControllerView view;
+ model->attachView(&view);
+
+ view.fromClipboard();
+
+ ModelNode rootNode(view.rootModelNode());
+
+ if (rootNode.type() == "empty")
+ return;
+
+ if (rootNode.id() == "designer__Selection") {
+ QList<ModelNode> selectedNodes = rootNode.allDirectSubModelNodes();
+ model->detachView(&view);
+ m_d->model->attachView(&view);
+
+ ModelNode selectedNode;
+
+ if (!view.selectedModelNodes().isEmpty())
+ selectedNode = view.selectedModelNodes().first();
+
+ if (!selectedNode.isValid())
+ selectedNode = view.rootModelNode();
+ foreach (const ModelNode &node, selectedNodes) {
+ foreach (const ModelNode &node2, selectedNodes) {
+ if (node.isAncestorOf(node2))
+ selectedNodes.removeAll(node2);
+ }
+
+ }
+ foreach (const ModelNode &node, selectedNodes) {
+ QString defaultProperty(selectedNode.metaInfo().defaultProperty());
+ ModelNode pastedNode(view.insertModel(node));
+ selectedNode.nodeListProperty(defaultProperty).reparentHere(pastedNode);
+ }
+ } else {
+ model->detachView(&view);
+ m_d->model->attachView(&view);
+ ModelNode pastedNode(view.insertModel(rootNode));
+ ModelNode selectedNode;
+
+ if (!view.selectedModelNodes().isEmpty())
+ selectedNode = view.selectedModelNodes().first();
+
+ if (!selectedNode.isValid())
+ selectedNode = view.rootModelNode();
+
+ QString defaultProperty(selectedNode.metaInfo().defaultProperty());
+ selectedNode.nodeListProperty(defaultProperty).reparentHere(pastedNode);
+ }
+}
+
+void DesignDocumentController::showError(const QString &message, QWidget *parent) const
+{
+ if (!parent)
+ parent = m_d->stackedWidget.data();
+
+ QMessageBox msgBox(parent);
+ msgBox.setWindowFlags(Qt::Sheet | Qt::MSWindowsFixedSizeDialogHint);
+ msgBox.setWindowTitle("Invalid qml");
+ msgBox.setText(message);
+ msgBox.setIcon(QMessageBox::Warning);
+ msgBox.exec();
+}
+
+QWidget *DesignDocumentController::itemLibrary() const
+{
+ return m_d->itemLibrary.data();
+}
+
+QWidget *DesignDocumentController::navigator() const
+{
+ return m_d->navigator->widget();
+}
+
+QWidget *DesignDocumentController::allPropertiesBox() const
+{
+ return m_d->allPropertiesBox.data();
+}
+
+QWidget *DesignDocumentController::statesEditorWidget() const
+{
+ return m_d->statesEditorWidget.data();
+}
+
+RewriterView *DesignDocumentController::rewriterView() const
+{
+ return m_d->rewriterView.data();
+}
+
+void DesignDocumentController::undo()
+{
+ m_d->textEdit->undo();
+}
+
+void DesignDocumentController::redo()
+{
+ m_d->textEdit->redo();
+}
+
+#ifdef ENABLE_TEXT_VIEW
+void DesignDocumentController::showText()
+{
+ m_d->stackedWidget->setCurrentWidget(m_d->textEdit.data());
+}
+#endif // ENABLE_TEXT_VIEW
+
+#ifdef ENABLE_TEXT_VIEW
+void DesignDocumentController::showForm()
+{
+ m_d->stackedWidget->setCurrentWidget(m_d->formEditorView->widget());
+}
+#endif // ENABLE_TEXT_VIEW
+
+QProcess *DesignDocumentController::createPreviewProcess(const QString &dirPath)
+{
+ Q_ASSERT(QDir(dirPath).exists());
+
+ QProcess *previewProcess = new QProcess(this);
+ previewProcess->setWorkingDirectory(dirPath);
+
+ QTemporaryFile *temporaryFile = new QTemporaryFile(QDir(dirPath).absoluteFilePath("bauhaus_tmp"));
+ temporaryFile->setParent(previewProcess);
+
+ temporaryFile->open();
+
+ m_d->textModifier->save(temporaryFile);
+
+ QStringList qmlViewerArgumentList;
+// qmlViewerArgumentList.append("-L");
+// qmlViewerArgumentList.append(dirPath);
+ previewProcess->setWorkingDirectory(dirPath);
+ qmlViewerArgumentList.append(temporaryFile->fileName());
+
+ temporaryFile->close();
+
+ previewProcess->start(QString("%1/qmlviewer").arg(QCoreApplication::applicationDirPath()), qmlViewerArgumentList);
+ if (!previewProcess->waitForStarted())
+ previewProcess->start("qmlviewer", qmlViewerArgumentList);
+ if (!previewProcess->waitForStarted())
+ QMessageBox::warning(documentWidget(), "qmlviewer not found", "qmlviewer should be in the PATH or in the same directory like the bauhaus binary.");
+
+ return previewProcess;
+}
+
+QProcess *DesignDocumentController::createPreviewWithDebugProcess(const QString &dirPath)
+{
+ Q_ASSERT(QDir(dirPath).exists());
+
+ QProcess *previewProcess = new QProcess(this);
+ previewProcess->setWorkingDirectory(dirPath);
+
+ QProcess *debugger = new QProcess(previewProcess);
+
+ QTemporaryFile *temporaryFile = new QTemporaryFile(QDir(dirPath).absoluteFilePath("bauhaus_tmp"));
+ temporaryFile->setParent(previewProcess);
+
+ temporaryFile->open();
+
+ m_d->textModifier->save(temporaryFile);
+
+ QStringList environmentList = QProcess::systemEnvironment();
+ environmentList.append("QML_DEBUG_SERVER_PORT=3768");
+ previewProcess->setEnvironment(environmentList);
+
+ QStringList qmlViewerArgumentList;
+// qmlViewerArgumentList.append("-L");
+// qmlViewerArgumentList.append(libraryPath);
+ qmlViewerArgumentList.append(temporaryFile->fileName());
+
+ temporaryFile->close();
+
+ debugger->setWorkingDirectory(dirPath);
+ debugger->start(QString("%1/qmldebugger").arg(QCoreApplication::applicationDirPath()));
+ if (!debugger->waitForStarted())
+ debugger->start("qmldebugger", qmlViewerArgumentList);
+ if (!debugger->waitForStarted())
+ QMessageBox::warning(documentWidget(), "qmldebugger not found", "qmldebugger should in the PATH or in the same directory like the bauhaus binary.");
+
+ previewProcess->setWorkingDirectory(dirPath);
+ previewProcess->start(QString("%1/qmlviewer").arg(QCoreApplication::applicationDirPath()), qmlViewerArgumentList);
+ if (!previewProcess->waitForStarted())
+ previewProcess->start("qmlviewer", qmlViewerArgumentList);
+ if (!previewProcess->waitForStarted())
+ QMessageBox::warning(documentWidget(), "qmlviewer not found", "qmlviewer should in the PATH or in the same directory like the bauhaus binary.");
+
+ return previewProcess;
+}
+
+bool DesignDocumentController::save(QIODevice *device, QString * /*errorMessage*/)
+{
+ if (m_d->model) {
+ QByteArray data = m_d->textEdit->toPlainText().toLatin1();
+ device->write(data);
+ m_d->textEdit->setPlainText(data); // clear undo/redo history
+ return true;
+ } else {
+ return false;
+ }
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/integration/designdocumentcontroller.h b/src/plugins/qmldesigner/components/integration/designdocumentcontroller.h
new file mode 100644
index 0000000000..355cf79e00
--- /dev/null
+++ b/src/plugins/qmldesigner/components/integration/designdocumentcontroller.h
@@ -0,0 +1,142 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef DesignDocumentController_h
+#define DesignDocumentController_h
+
+#include "rewriterview.h"
+
+#include <QtCore/QObject>
+#include <QtCore/QString>
+
+class QUndoStack;
+class QWidget;
+class QIODevice;
+class QProcess;
+class QPlainTextEdit;
+class QmlError;
+
+namespace QmlDesigner {
+
+class Model;
+class ModelNode;
+class TextModifier;
+class QmlObjectNode;
+class RewriterView;
+
+class DesignDocumentController: public QObject
+{
+ Q_OBJECT
+
+public:
+ DesignDocumentController(QObject *parent);
+ ~DesignDocumentController();
+
+ QString displayName() const;
+ QString fileName() const;
+ void setFileName(const QString &fileName);
+
+ QList<RewriterView::Error> loadMaster(QPlainTextEdit *edit);
+ QList<RewriterView::Error> loadMaster(const QByteArray &qml);
+ void loadCurrentModel();
+ void close();
+
+ bool isDirty() const;
+ bool isUndoAvailable() const;
+ bool isRedoAvailable() const;
+
+ Model *model() const;
+ Model *masterModel() const;
+
+ QWidget *documentWidget() const;
+ QWidget *itemLibrary() const;
+ QWidget *navigator() const;
+ QWidget *allPropertiesBox() const;
+ QWidget *statesEditorWidget() const;
+
+ RewriterView *rewriterView() const;
+
+ bool previewVisible() const;
+ bool previewWithDebugVisible() const;
+
+ bool isModelSyncBlocked() const;
+ void blockModelSync(bool block);
+
+ QList<RewriterView::Error> qmlErrors() const;
+
+signals:
+ void displayNameChanged(const QString &newFileName);
+ void dirtyStateChanged(bool newState);
+
+ void undoAvailable(bool isAvailable);
+ void redoAvailable(bool isAvailable);
+ void previewVisibilityChanged(bool visible);
+ void previewWithDebugVisibilityChanged(bool visible);
+ void designDocumentClosed();
+ void qmlErrorsChanged(const QList<RewriterView::Error> &errors);
+
+ void fileToOpen(const QString &path);
+
+public slots:
+ bool save(QWidget *parent = 0);
+ void saveAs(QWidget *parent = 0);
+ void deleteSelected();
+ void copySelected();
+ void cutSelected();
+ void paste();
+
+ void togglePreview(bool visible);
+ void toggleWithDebugPreview(bool visible);
+
+ void emitPreviewVisibilityChanged();
+ void emitPreviewWithDebugVisibilityChanged();
+ void undo();
+ void redo();
+
+#ifdef ENABLE_TEXT_VIEW
+ void showText();
+ void showForm();
+#endif // ENABLE_TEXT_VIEW
+
+private slots:
+ void doRealSaveAs(const QString &fileName);
+ void showError(const QString &message, QWidget *parent = 0) const;
+ void changeCurrentModelTo(const ModelNode &node);
+
+private:
+ QProcess *createPreviewProcess(const QString &dirPath);
+ QProcess *createPreviewWithDebugProcess(const QString &dirPath);
+ bool save(QIODevice *device, QString *errorMessage);
+
+ class DesignDocumentControllerPrivate *m_d;
+};
+
+} // namespace QmlDesigner
+
+#endif // DesignDocumentController_h
diff --git a/src/plugins/qmldesigner/components/integration/designdocumentcontrollerview.cpp b/src/plugins/qmldesigner/components/integration/designdocumentcontrollerview.cpp
new file mode 100644
index 0000000000..187328bad8
--- /dev/null
+++ b/src/plugins/qmldesigner/components/integration/designdocumentcontrollerview.cpp
@@ -0,0 +1,137 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "designdocumentcontrollerview.h"
+#include <rewriterview.h>
+#include <plaintexteditmodifier.h>
+
+#include <QApplication>
+#include <QPlainTextEdit>
+#include <QClipboard>
+#include <QDebug>
+
+namespace QmlDesigner {
+
+void DesignDocumentControllerView::nodeCreated(const ModelNode & /*createdNode*/) {};
+void DesignDocumentControllerView::nodeAboutToBeRemoved(const ModelNode & /*removedNode*/) {};
+void DesignDocumentControllerView::nodeRemoved(const ModelNode & /*removedNode*/, const NodeAbstractProperty & /*parentProperty*/, AbstractView::PropertyChangeFlags /*propertyChange*/) {};
+void DesignDocumentControllerView::nodeReparented(const ModelNode & /*node*/, const NodeAbstractProperty & /*newPropertyParent*/, const NodeAbstractProperty & /*oldPropertyParent*/, AbstractView::PropertyChangeFlags /*propertyChange*/) {};
+void DesignDocumentControllerView::nodeIdChanged(const ModelNode& /*node*/, const QString& /*newId*/, const QString& /*oldId*/) {};
+void DesignDocumentControllerView::propertiesAboutToBeRemoved(const QList<AbstractProperty>& /*propertyList*/) {};
+void DesignDocumentControllerView::propertiesRemoved(const QList<AbstractProperty>& /*propertyList*/) {};
+void DesignDocumentControllerView::variantPropertiesChanged(const QList<VariantProperty>& /*propertyList*/, AbstractView::PropertyChangeFlags /*propertyChange*/) {};
+void DesignDocumentControllerView::bindingPropertiesChanged(const QList<BindingProperty>& /*propertyList*/, AbstractView::PropertyChangeFlags /*propertyChange*/) {};
+void DesignDocumentControllerView::nodeTypeChanged(const ModelNode & /*node*/,const QString & /*type*/, int /*majorVersion*/, int /*minorVersion*/) {};
+
+void DesignDocumentControllerView::selectedNodesChanged(const QList<ModelNode> & /*selectedNodeList*/,
+ const QList<ModelNode> & /*lastSelectedNodeList*/) {};
+
+void DesignDocumentControllerView::nodeSlidedToIndex(const NodeListProperty & /*listProperty*/, int /*newIndex*/, int /*oldIndex*/) {};
+
+static QStringList arrayToStringList(const QByteArray &byteArray)
+{
+ QString str(QString::fromLatin1(byteArray));
+ return str.split("\n");
+}
+
+static QByteArray stringListToArray(const QStringList &stringList)
+{
+ QString str;
+ foreach (const QString &subString, stringList)
+ str += subString + "\n";
+ return str.toLatin1();
+}
+
+void DesignDocumentControllerView::toClipboard() const
+{
+ QClipboard *clipboard = QApplication::clipboard();
+
+ QMimeData *data = new QMimeData;
+
+ data->setText(toText());
+ QStringList imports;
+ foreach (const Import &import, model()->imports())
+ imports.append(import.toString());
+
+ data->setData("QmlDesigner::imports", stringListToArray(imports));
+ clipboard->setMimeData(data);
+}
+
+void DesignDocumentControllerView::fromClipboard()
+{
+ QClipboard *clipboard = QApplication::clipboard();
+ fromText(clipboard->text());
+ QStringList imports = arrayToStringList(clipboard->mimeData()->data("QmlDesigner::imports"));
+// foreach (const QString &importString, imports) {
+// Import import(Import::createLibraryImport();
+// model()->addImport(import); //### imports
+// }
+}
+
+
+QString DesignDocumentControllerView::toText() const
+{
+ QScopedPointer<Model> model(Model::create("Qt/Rectangle"));
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText("import Qt 4.6; Item {}");
+ PlainTextEditModifier modifier(&textEdit);
+
+ QScopedPointer<RewriterView> rewriterView(new RewriterView(RewriterView::Amend, 0));
+ rewriterView->setTextModifier(&modifier);
+ model->attachView(rewriterView.data());
+
+ ModelMerger merger(rewriterView.data());
+
+ merger.replaceModel(rootModelNode());
+
+ ModelNode rewriterNode(rewriterView->rootModelNode());
+
+ //get the text of the root item without imports
+ return rewriterView->extractText(QList<ModelNode>() << rewriterNode).value(rewriterNode);
+}
+
+void DesignDocumentControllerView::fromText(QString text)
+{
+ QScopedPointer<Model> model(Model::create("Qt/Rectangle"));
+ QPlainTextEdit textEdit;
+ QString imports("import Qt 4.6;\n");
+ textEdit.setPlainText(imports + text);
+ PlainTextEditModifier modifier(&textEdit);
+
+ QScopedPointer<RewriterView> rewriterView(new RewriterView(RewriterView::Amend, 0));
+ rewriterView->setTextModifier(&modifier);
+ model->attachView(rewriterView.data());
+
+ if (rewriterView->errors().isEmpty() && rewriterView->rootModelNode().isValid()) {
+ ModelMerger merger(this);
+ merger.replaceModel(rewriterView->rootModelNode());
+ }
+}
+
+}// namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/integration/designdocumentcontrollerview.h b/src/plugins/qmldesigner/components/integration/designdocumentcontrollerview.h
new file mode 100644
index 0000000000..6b4c89ea62
--- /dev/null
+++ b/src/plugins/qmldesigner/components/integration/designdocumentcontrollerview.h
@@ -0,0 +1,78 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef DESIGNDOCUMENTCONTROLLERVIEW_H
+#define DESIGNDOCUMENTCONTROLLERVIEW_H
+
+#include <abstractview.h>
+#include <modelmerger.h>
+
+namespace QmlDesigner {
+
+class DesignDocumentControllerView : public AbstractView
+{
+ Q_OBJECT
+public:
+ DesignDocumentControllerView(QObject *parent = 0)
+ : AbstractView(parent), m_modelMerger(this) {}
+
+ virtual void nodeCreated(const ModelNode &createdNode);
+ virtual void nodeAboutToBeRemoved(const ModelNode &removedNode);
+ virtual void nodeRemoved(const ModelNode &removedNode, const NodeAbstractProperty &parentProperty, PropertyChangeFlags propertyChange);
+ virtual void nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange);
+ virtual void nodeIdChanged(const ModelNode& node, const QString& newId, const QString& oldId);
+ virtual void propertiesAboutToBeRemoved(const QList<AbstractProperty>& propertyList);
+ virtual void propertiesRemoved(const QList<AbstractProperty>& propertyList);
+ virtual void variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags propertyChange);
+ virtual void bindingPropertiesChanged(const QList<BindingProperty>& propertyList, PropertyChangeFlags propertyChange);
+ virtual void nodeTypeChanged(const ModelNode &node,const QString &type, int majorVersion, int minorVersion);
+
+ virtual void selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
+ const QList<ModelNode> &lastSelectedNodeList);
+
+ virtual void nodeSlidedToIndex(const NodeListProperty &listProperty, int newIndex, int oldIndex);
+
+ ModelNode insertModel(const ModelNode &modelNode)
+ { return m_modelMerger.insertModel(modelNode); }
+ void replaceModel(const ModelNode &modelNode)
+ { m_modelMerger.replaceModel(modelNode); }
+
+ void toClipboard() const;
+ void fromClipboard();
+
+ QString toText() const;
+ void fromText(QString text);
+
+private:
+ ModelMerger m_modelMerger;
+};
+
+}// namespace QmlDesigner
+
+#endif // DESIGNDOCUMENTCONTROLLERVIEW_H
diff --git a/src/plugins/qmldesigner/components/integration/documentcloser.cpp b/src/plugins/qmldesigner/components/integration/documentcloser.cpp
new file mode 100644
index 0000000000..c7c0c5636b
--- /dev/null
+++ b/src/plugins/qmldesigner/components/integration/documentcloser.cpp
@@ -0,0 +1,139 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "documentcloser.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDebug>
+#include <QtCore/QFileInfo>
+
+#include <QtGui/QMessageBox>
+
+#include "designdocumentcontroller.h"
+
+namespace QmlDesigner {
+
+DocumentCloser::DocumentCloser():
+ m_quitWhenDone(false)
+{
+}
+
+void DocumentCloser::close(DesignDocumentController* designDocument)
+{
+ DocumentCloser* closer = new DocumentCloser;
+ closer->m_designDocuments.append(designDocument);
+ closer->runClose(designDocument);
+}
+
+void DocumentCloser::runClose(DesignDocumentController* designDocument)
+{
+ bool isDirty = designDocument->isDirty();
+
+//#ifndef QT_NO_DEBUG
+// isDirty=false;
+//#endif
+
+ if (isDirty) {
+ QMessageBox* msgBox = new QMessageBox(designDocument->documentWidget());
+ QString txt = tr("Do you want to save the changes you made in the document \"%1\"?");
+ QString shortFileName = QFileInfo(designDocument->fileName()).baseName();
+ msgBox->setText(txt.arg(shortFileName));
+ msgBox->setInformativeText(tr("Your changes will be lost if you don't save them."));
+ msgBox->setIcon(QMessageBox::Question);
+ msgBox->setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
+ msgBox->setDefaultButton(QMessageBox::Save);
+ msgBox->setEscapeButton(QMessageBox::Cancel);
+ msgBox->resize(451, 131);
+ msgBox->open(this, SLOT(choiceMade()));
+ } else {
+ designDocument->close();
+ closeDone();
+ }
+}
+
+void DocumentCloser::choiceMade()
+{
+ QMessageBox* msgBox = dynamic_cast<QMessageBox*>(sender());
+ if (!msgBox)
+ return;
+
+ switch (msgBox->result()) {
+ case QMessageBox::Save:
+ m_designDocuments.first()->save();
+
+ case QMessageBox::Discard:
+ m_designDocuments.first()->close();
+ closeDone();
+ break;
+
+ case QMessageBox::Cancel:
+ default:
+ closeCancelled();
+ }
+}
+
+void DocumentCloser::closeCancelled()
+{
+ delete this;
+}
+
+void DocumentCloser::closeDone()
+{
+ if (!m_designDocuments.isEmpty()) // should always be the case, but let's be safe.
+ m_designDocuments.removeFirst();
+
+ bool quit = m_quitWhenDone;
+
+ if (m_designDocuments.isEmpty()) {
+ delete this;
+
+ if (quit) {
+ qApp->quit();
+ }
+ } else {
+ runClose(m_designDocuments.first().data());
+ }
+}
+
+void DocumentCloser::close(QList<QWeakPointer<DesignDocumentController> > designDocuments, bool quitWhenAllEditorsClosed)
+{
+ if (designDocuments.isEmpty()) {
+ if (quitWhenAllEditorsClosed) {
+ qApp->quit();
+ }
+ } else {
+ DocumentCloser* closer = new DocumentCloser;
+ closer->m_designDocuments = designDocuments;
+ closer->m_quitWhenDone = quitWhenAllEditorsClosed;
+ closer->runClose(closer->m_designDocuments.first().data());
+ }
+}
+
+} // namespace QmlDesigner
+
diff --git a/src/plugins/qmldesigner/components/integration/documentcloser.h b/src/plugins/qmldesigner/components/integration/documentcloser.h
new file mode 100644
index 0000000000..35933af1f0
--- /dev/null
+++ b/src/plugins/qmldesigner/components/integration/documentcloser.h
@@ -0,0 +1,67 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef DOCUMENTCLOSER_H
+#define DOCUMENTCLOSER_H
+
+#include <QWeakPointer>
+#include <QtCore/QList>
+#include <QtCore/QObject>
+
+
+#include "designdocumentcontroller.h"
+
+namespace QmlDesigner {
+
+class DocumentCloser : public QObject
+{
+ Q_OBJECT
+
+public:
+ static void close(DesignDocumentController* designDocument);
+ static void close(QList<QWeakPointer<DesignDocumentController> > designDocuments, bool quitWhenAllEditorsClosed);
+
+private:
+ DocumentCloser();
+
+ void runClose(DesignDocumentController* designDocument);
+ void closeDone();
+ void closeCancelled();
+
+private slots:
+ void choiceMade();
+
+private:
+ QList<QWeakPointer<DesignDocumentController> > m_designDocuments;
+ bool m_quitWhenDone;
+};
+
+} // namespace QmlDesigner
+
+#endif // DOCUMENTCLOSER_H
diff --git a/src/plugins/qmldesigner/components/integration/integration.pri b/src/plugins/qmldesigner/components/integration/integration.pri
new file mode 100644
index 0000000000..0247e2df10
--- /dev/null
+++ b/src/plugins/qmldesigner/components/integration/integration.pri
@@ -0,0 +1,34 @@
+VPATH += $$PWD
+INCLUDEPATH += $$PWD
+SOURCES += \
+ integrationcore.cpp \
+ multipledocumentscontroller.cpp \
+ designdocumentcontroller.cpp \
+ designdocumentcontrollerview.cpp \
+ navigatorcontroller.cpp \
+ allpropertiesviewcontroller.cpp \
+ utilitypanelcontroller.cpp \
+ widgetboxcontroller.cpp \
+ stackedutilitypanelcontroller.cpp \
+ stateseditorcontroller.cpp \
+ documentcloser.cpp \
+ componentaction.cpp \
+ componentview.cpp \
+ xuifiledialog.cpp
+
+HEADERS += \
+ integrationcore.h \
+ multipledocumentscontroller.h \
+ designdocumentcontrollerview.h \
+ designdocumentcontroller.h \
+ navigatorcontroller.h \
+ allpropertiesviewcontroller.h \
+ utilitypanelcontroller.h \
+ widgetboxcontroller.h \
+ stackedutilitypanelcontroller.h \
+ stateseditorcontroller.h \
+ documentcloser.h \
+ componentaction.h \
+ componentview.h \
+ xuifiledialog.h
+
diff --git a/src/plugins/qmldesigner/components/integration/integrationcore.cpp b/src/plugins/qmldesigner/components/integration/integrationcore.cpp
new file mode 100644
index 0000000000..518cf23ecd
--- /dev/null
+++ b/src/plugins/qmldesigner/components/integration/integrationcore.cpp
@@ -0,0 +1,94 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "integrationcore.h"
+#include "pluginmanager.h"
+#include "itemlibrary.h"
+#include "navigatorwidget.h"
+#include "metainfo.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QObject>
+
+namespace QmlDesigner {
+
+class CorePrivate
+{
+ public:
+ CorePrivate();
+ ~CorePrivate();
+
+ static IntegrationCore *m_instance;
+
+ PluginManager m_pluginManager;
+};
+
+CorePrivate::CorePrivate()
+{
+}
+
+CorePrivate::~CorePrivate()
+{
+ MetaInfo::clearGlobal();
+}
+
+IntegrationCore *CorePrivate::m_instance = 0;
+
+/*!
+ \class QmlDesigner::Core
+
+ Convenience class to access the plugin manager singleton,
+ and manage the lifecycle of static data (e.g. in the metatype system).
+*/
+
+IntegrationCore::IntegrationCore() :
+ m_d(new CorePrivate)
+{
+ Q_ASSERT(CorePrivate::m_instance == 0);
+ CorePrivate::m_instance = this;
+}
+
+IntegrationCore::~IntegrationCore()
+{
+ CorePrivate::m_instance = 0;
+ delete m_d;
+}
+
+IntegrationCore *IntegrationCore::instance()
+{
+ Q_ASSERT(CorePrivate::m_instance);
+ return CorePrivate::m_instance;
+}
+
+PluginManager *IntegrationCore::pluginManager() const
+{
+ return &m_d->m_pluginManager;
+}
+
+}
diff --git a/src/plugins/qmldesigner/components/integration/integrationcore.h b/src/plugins/qmldesigner/components/integration/integrationcore.h
new file mode 100644
index 0000000000..170eb6ac48
--- /dev/null
+++ b/src/plugins/qmldesigner/components/integration/integrationcore.h
@@ -0,0 +1,61 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef QMLDESIGNERCORE_H
+#define QMLDESIGNERCORE_H
+
+#include <QtCore/QObject>
+
+class QWidget;
+class QDialog;
+
+namespace QmlDesigner {
+
+class ItemLibrary;
+class FormWindowManager;
+class PluginManager;
+class CorePrivate;
+
+class IntegrationCore
+{
+ Q_DISABLE_COPY(IntegrationCore)
+public:
+ IntegrationCore();
+ ~IntegrationCore();
+
+ PluginManager *pluginManager() const;
+
+ static IntegrationCore *instance();
+
+private:
+ CorePrivate *m_d;
+};
+}
+
+#endif // QMLDESIGNERCORE_H
diff --git a/src/plugins/qmldesigner/components/integration/multipledocumentscontroller.cpp b/src/plugins/qmldesigner/components/integration/multipledocumentscontroller.cpp
new file mode 100644
index 0000000000..4e3b34bf47
--- /dev/null
+++ b/src/plugins/qmldesigner/components/integration/multipledocumentscontroller.cpp
@@ -0,0 +1,353 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "multipledocumentscontroller.h"
+
+#include <QtCore/QFileInfo>
+#include <QtGui/QTextEdit>
+#include <QtGui/QMessageBox>
+
+#include <QmlError>
+
+#include <model.h>
+#include "designdocumentcontroller.h"
+#include "documentcloser.h"
+
+
+namespace QmlDesigner {
+
+static QString createTitle(const QString& fileName)
+{
+ return QFileInfo(fileName).baseName();
+}
+
+MultipleDocumentsController::MultipleDocumentsController(QWidget* parent):
+ QObject(parent),
+ m_tabWidget(new QTabWidget),
+ m_undoAction(new QAction(tr("&Undo"), this)),
+ m_redoAction(new QAction(tr("&Redo"), this))
+{
+ m_tabWidget->setDocumentMode(true);
+ m_tabWidget->setTabsClosable(true);
+ m_tabWidget->setMovable(true);
+
+ connect(tabWidget(), SIGNAL(currentChanged(int)), this, SLOT(currentTabChanged(int)));
+ connect(tabWidget(), SIGNAL(tabCloseRequested(int)), this, SLOT(tabCloseRequested(int)));
+}
+
+MultipleDocumentsController::~MultipleDocumentsController()
+{
+}
+
+QTabWidget *MultipleDocumentsController::tabWidget() const
+{
+ return m_tabWidget.data();
+}
+
+DesignDocumentController* MultipleDocumentsController::findActiveDocument(QWidget* documentWidget)
+{
+ foreach (const QWeakPointer<DesignDocumentController> &controller, m_documentControllers)
+ if (controller->documentWidget() == documentWidget)
+ return controller.data();
+
+ return 0;
+}
+
+void MultipleDocumentsController::rewireDocumentActions(DesignDocumentController* oldActiveDocument, DesignDocumentController* newActiveDocument)
+{
+ if (oldActiveDocument) {
+ disconnect(undoAction(), SIGNAL(triggered()), oldActiveDocument, SLOT(undo()));
+ disconnect(redoAction(), SIGNAL(triggered()), oldActiveDocument, SLOT(redo()));
+#ifdef ENABLE_TEXT_VIEW
+ disconnect(m_showTextAction.data(), SIGNAL(triggered()), oldActiveDocument, SLOT(showText()));
+ disconnect(m_showFormAction.data(), SIGNAL(triggered()), oldActiveDocument, SLOT(showForm()));
+#endif // ENABLE_TEXT_VIEW
+ }
+
+ if (newActiveDocument) {
+ connect(undoAction(), SIGNAL(triggered()), newActiveDocument, SLOT(undo()));
+ connect(redoAction(), SIGNAL(triggered()), newActiveDocument, SLOT(redo()));
+#ifdef ENABLE_TEXT_VIEW
+ connect(m_showTextAction.data(), SIGNAL(triggered()), newActiveDocument, SLOT(showText()));
+ connect(m_showFormAction.data(), SIGNAL(triggered()), newActiveDocument, SLOT(showForm()));
+ if (m_showTextAction->isChecked())
+ newActiveDocument->showText();
+ else
+ newActiveDocument->showForm();
+#endif // ENABLE_TEXT_VIEW
+ }
+}
+
+void MultipleDocumentsController::currentTabChanged(int newCurrentTab)
+{
+ DesignDocumentController* oldActiveDocument = 0;
+ if (!m_documentControllers.isEmpty()) {
+ oldActiveDocument = m_documentControllers.first().data();
+ }
+
+ if (newCurrentTab == -1) {
+ emit activeDocumentChanged(0);
+ if (oldActiveDocument && oldActiveDocument->previewVisible())
+ emit previewVisibilityChanged(false);
+ if (oldActiveDocument && oldActiveDocument->previewWithDebugVisible())
+ emit previewWithDebugVisibilityChanged(false);
+
+ if (oldActiveDocument)
+ rewireDocumentActions(oldActiveDocument, 0);
+ } else {
+ DesignDocumentController* newActiveDocument = findActiveDocument(m_tabWidget->currentWidget());
+ m_undoAction->setEnabled(newActiveDocument->isUndoAvailable());
+ m_redoAction->setEnabled(newActiveDocument->isRedoAvailable());
+
+ rewireDocumentActions(oldActiveDocument, newActiveDocument);
+
+ m_documentControllers.removeOne(newActiveDocument);
+ m_documentControllers.prepend(newActiveDocument);
+ emit activeDocumentChanged(newActiveDocument);
+ if (oldActiveDocument && oldActiveDocument->previewVisible())
+ emit previewVisibilityChanged(newActiveDocument->previewVisible());
+ if (oldActiveDocument && oldActiveDocument->previewWithDebugVisible())
+ emit previewWithDebugVisibilityChanged(newActiveDocument->previewWithDebugVisible());
+ }
+}
+
+void MultipleDocumentsController::tabCloseRequested(int tabIndex)
+{
+ DesignDocumentController* controller = findActiveDocument(m_tabWidget->widget(tabIndex));
+
+ if (controller)
+ DocumentCloser::close(controller);
+}
+
+void MultipleDocumentsController::documentDisplayNameChanged(const QString &/*fileName*/)
+{
+ DesignDocumentController *documentController = qobject_cast<DesignDocumentController*>(sender());
+ Q_ASSERT(documentController);
+ documentDirtyStateChanged(documentController->isDirty());
+}
+
+void MultipleDocumentsController::documentDirtyStateChanged(bool newState)
+{
+ DesignDocumentController *documentController = qobject_cast<DesignDocumentController*>(sender());
+ Q_ASSERT(documentController);
+
+ int tabIdx = m_tabWidget->indexOf(documentController->documentWidget());
+
+ if (newState)
+ m_tabWidget->setTabText(tabIdx, tr("* %1").arg(createTitle(documentController->displayName())));
+ else
+ m_tabWidget->setTabText(tabIdx, createTitle(documentController->displayName()));
+}
+
+void MultipleDocumentsController::documentUndoAvailable(bool isAvailable)
+{
+ DesignDocumentController *documentController = qobject_cast<DesignDocumentController*>(sender());
+ Q_ASSERT(documentController);
+
+ if (m_documentControllers.first().data() == documentController)
+ m_undoAction->setEnabled(isAvailable);
+}
+
+void MultipleDocumentsController::documentRedoAvailable(bool isAvailable)
+{
+ DesignDocumentController *documentController = qobject_cast<DesignDocumentController*>(sender());
+ Q_ASSERT(documentController);
+
+ if (m_documentControllers.first().data() == documentController)
+ m_redoAction->setEnabled(isAvailable);
+}
+
+void MultipleDocumentsController::documentPreviewVisibilityChanged(bool visible)
+{
+ DesignDocumentController *documentController = qobject_cast<DesignDocumentController*>(sender());
+ Q_ASSERT(documentController);
+
+ if (m_documentControllers.first().data() == documentController)
+ emit previewVisibilityChanged(visible);
+}
+
+void MultipleDocumentsController::documentPreviewWithDebugVisibilityChanged(bool visible)
+{
+ DesignDocumentController *documentController = qobject_cast<DesignDocumentController*>(sender());
+ Q_ASSERT(documentController);
+
+ if (m_documentControllers.first().data() == documentController)
+ emit previewWithDebugVisibilityChanged(visible);
+}
+
+void MultipleDocumentsController::open(DesignDocumentController* documentController)
+{
+ m_documentControllers.append(documentController);
+
+ int newTabIndex = m_tabWidget->addTab(documentController->documentWidget(), createTitle(documentController->displayName()));
+ m_tabWidget->setCurrentIndex(newTabIndex);
+
+ connect(documentController, SIGNAL(displayNameChanged(QString)),
+ this, SLOT(documentDisplayNameChanged(QString)));
+ connect(documentController, SIGNAL(dirtyStateChanged(bool)),
+ this, SLOT(documentDirtyStateChanged(bool)));
+ connect(documentController, SIGNAL(undoAvailable(bool)),
+ this, SLOT(documentUndoAvailable(bool)));
+ connect(documentController, SIGNAL(redoAvailable(bool)),
+ this, SLOT(documentRedoAvailable(bool)));
+ connect(documentController, SIGNAL(previewVisibilityChanged(bool)),
+ this, SLOT(documentPreviewVisibilityChanged(bool)));
+ connect(documentController, SIGNAL(previewWithDebugVisibilityChanged(bool)),
+ this, SLOT(documentPreviewWithDebugVisibilityChanged(bool)));
+ connect(documentController, SIGNAL(designDocumentClosed()),
+ this, SLOT(designDocumentClosed()));
+ connect(documentController, SIGNAL(qmlErrorsChanged(QList<RewriterView::Error>)),
+ this, SLOT(designDocumentError(QList<RewriterView::Error>)));
+
+ emit documentCountChanged(m_documentControllers.size());
+}
+
+void MultipleDocumentsController::designDocumentClosed()
+{
+ DesignDocumentController *documentController = qobject_cast<DesignDocumentController*>(sender());
+ Q_ASSERT(documentController);
+
+ rewireDocumentActions(documentController, 0);
+
+ m_tabWidget->removeTab(m_tabWidget->indexOf(documentController->documentWidget()));
+ m_documentControllers.removeOne(documentController);
+ emit documentClosed(documentController);
+ emit documentCountChanged(m_documentControllers.size());
+}
+
+void MultipleDocumentsController::designDocumentError(const QList<RewriterView::Error> &error)
+{
+ DesignDocumentController *documentController = qobject_cast<DesignDocumentController*>(sender());
+ Q_ASSERT(documentController);
+
+ if (error.isEmpty())
+ return;
+
+ QMessageBox msgBox(documentController->documentWidget());
+ msgBox.setWindowFlags(Qt::Sheet | Qt::MSWindowsFixedSizeDialogHint);
+ msgBox.setWindowTitle("Invalid qml");
+ msgBox.setText(error.first().toString());
+ msgBox.setIcon(QMessageBox::Warning);
+ msgBox.exec();
+}
+
+void MultipleDocumentsController::doSave()
+{
+ if (!m_documentControllers.isEmpty())
+ m_documentControllers.first()->save(dynamic_cast<QWidget*>(parent()));
+}
+
+void MultipleDocumentsController::doSaveAs()
+{
+ QWidget* parentWindow = dynamic_cast<QWidget*>(parent());
+
+ if (!m_documentControllers.isEmpty())
+ m_documentControllers.first()->saveAs(parentWindow);
+}
+
+void MultipleDocumentsController::doPreview(bool visible)
+{
+ if (m_documentControllers.isEmpty())
+ return;
+
+ m_documentControllers.first()->togglePreview(visible);
+}
+
+void MultipleDocumentsController::doPreviewWithDebug(bool visible)
+{
+ if (m_documentControllers.isEmpty())
+ return;
+
+ m_documentControllers.first()->toggleWithDebugPreview(visible);
+}
+
+void MultipleDocumentsController::doDelete()
+{
+ m_documentControllers.first()->deleteSelected();
+}
+
+void MultipleDocumentsController::doCopy()
+{
+ m_documentControllers.first()->copySelected();
+}
+
+void MultipleDocumentsController::doCut()
+{
+ m_documentControllers.first()->cutSelected();
+}
+
+void MultipleDocumentsController::doPaste()
+{
+ m_documentControllers.first()->paste();
+}
+
+void MultipleDocumentsController::closeAll(bool quitWhenAllEditorsClosed)
+{
+ DocumentCloser::close(m_documentControllers, quitWhenAllEditorsClosed);
+}
+
+QAction* MultipleDocumentsController::undoAction()
+{
+ return m_undoAction.data();
+}
+
+QAction* MultipleDocumentsController::redoAction()
+{
+ return m_redoAction.data();
+}
+
+#ifdef ENABLE_TEXT_VIEW
+QAction* MultipleDocumentsController::showFormAction(QMenu* parent)
+{
+ if (!m_showFormAction) {
+ m_showFormAction = new QAction(tr("&Form"), parent);
+ m_showFormAction->setShortcut(QKeySequence("Ctrl+Shift+F"));
+ m_showFormAction->setCheckable(true);
+ }
+
+ return m_showFormAction.data();
+}
+#endif // ENABLE_TEXT_VIEW
+
+#ifdef ENABLE_TEXT_VIEW
+QAction* MultipleDocumentsController::showTextAction(QMenu* parent)
+{
+ if (!m_showTextAction) {
+ m_showTextAction = new QAction(tr("&Text"), parent);
+ m_showTextAction->setShortcut(QKeySequence("Ctrl+Shift+T"));
+ m_showTextAction->setCheckable(true);
+ }
+
+ return m_showTextAction.data();
+}
+
+#endif // ENABLE_TEXT_VIEW
+
+} // namespace QmlDesigner
+
diff --git a/src/plugins/qmldesigner/components/integration/multipledocumentscontroller.h b/src/plugins/qmldesigner/components/integration/multipledocumentscontroller.h
new file mode 100644
index 0000000000..91347d6918
--- /dev/null
+++ b/src/plugins/qmldesigner/components/integration/multipledocumentscontroller.h
@@ -0,0 +1,120 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef MultipleDocumentsController_h
+#define MultipleDocumentsController_h
+
+#include <rewriterview.h>
+
+#include <QWeakPointer>
+#include <QtCore/QObject>
+#include <QtCore/QList>
+#include <QWeakPointer>
+
+#include <QtGui/QAction>
+#include <QtGui/QMenu>
+#include <QtGui/QTabWidget>
+#include <QtGui/QUndoGroup>
+
+class QmlError;
+
+namespace QmlDesigner {
+
+class DesignDocumentController;
+
+class MultipleDocumentsController : public QObject
+{
+ Q_OBJECT
+
+public:
+ MultipleDocumentsController(QWidget* parent = 0); // a bit of a hack
+ ~MultipleDocumentsController();
+
+ QTabWidget* tabWidget() const;
+
+ QAction* undoAction();
+ QAction* redoAction();
+#ifdef ENABLE_TEXT_VIEW
+ QAction* showFormAction(QMenu* parent);
+ QAction* showTextAction(QMenu* parent);
+#endif // ENABLE_TEXT_VIEW
+ void open(DesignDocumentController* documentController);
+ void closeAll(bool quitWhenAllEditorsClosed);
+ unsigned activeDocumentCount() const { return m_documentControllers.size(); }
+
+signals:
+ void activeDocumentChanged(DesignDocumentController* documentController);
+ void documentClosed(DesignDocumentController* documentController);
+ void documentCountChanged(unsigned newDocumentCount);
+
+ void previewVisibilityChanged(bool);
+ void previewWithDebugVisibilityChanged(bool);
+
+public slots:
+ void doSave();
+ void doSaveAs();
+ void doPreview(bool visible);
+ void doPreviewWithDebug(bool visible);
+ void doDelete();
+ void doCopy();
+ void doCut();
+ void doPaste();
+
+ void documentDisplayNameChanged(const QString &fileName);
+ void documentDirtyStateChanged(bool newState);
+ void documentUndoAvailable(bool isAvailable);
+ void documentRedoAvailable(bool isAvailable);
+ void documentPreviewVisibilityChanged(bool visible);
+ void documentPreviewWithDebugVisibilityChanged(bool visible);
+
+protected slots:
+ void currentTabChanged(int newCurrentTab);
+ void tabCloseRequested(int tabIndex);
+ void designDocumentClosed();
+ void designDocumentError(const QList<RewriterView::Error> &errors);
+
+private:
+ DesignDocumentController* findActiveDocument(QWidget* documentWidget);
+ void rewireDocumentActions(DesignDocumentController* oldActiveDocument, DesignDocumentController* newActiveDocument);
+
+private:
+ QWeakPointer<QTabWidget> m_tabWidget;
+ QWeakPointer<QAction> m_undoAction;
+ QWeakPointer<QAction> m_redoAction;
+#ifdef ENABLE_TEXT_VIEW
+ QWeakPointer<QAction> m_showTextAction;
+ QWeakPointer<QAction> m_showFormAction;
+#endif // ENABLE_TEXT_VIEW
+
+ QList<QWeakPointer<DesignDocumentController> > m_documentControllers;
+};
+
+} // namespace QmlDesigner
+
+#endif // MultipleDocumentsController_h
diff --git a/src/plugins/qmldesigner/components/integration/navigatorcontroller.cpp b/src/plugins/qmldesigner/components/integration/navigatorcontroller.cpp
new file mode 100644
index 0000000000..e09f028ba8
--- /dev/null
+++ b/src/plugins/qmldesigner/components/integration/navigatorcontroller.cpp
@@ -0,0 +1,53 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <navigatorwidget.h>
+
+#include "designdocumentcontroller.h"
+#include "navigatorcontroller.h"
+
+namespace QmlDesigner {
+
+NavigatorController::NavigatorController(QObject* parent):
+ StackedUtilityPanelController(parent)
+{
+ setObjectName("navigatorController");
+ contentWidget()->setObjectName("navigatorStack");
+}
+
+QWidget* NavigatorController::stackedPageWidget(DesignDocumentController* designDocumentController) const
+{
+ if (designDocumentController)
+ return designDocumentController->navigator();
+ else
+ return 0;
+}
+
+} // namespace QmlDesigner
+
diff --git a/src/plugins/qmldesigner/components/integration/navigatorcontroller.h b/src/plugins/qmldesigner/components/integration/navigatorcontroller.h
new file mode 100644
index 0000000000..7c44b3d698
--- /dev/null
+++ b/src/plugins/qmldesigner/components/integration/navigatorcontroller.h
@@ -0,0 +1,48 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef NAVIGATORCONTROLLER_H
+#define NAVIGATORCONTROLLER_H
+
+#include "stackedutilitypanelcontroller.h"
+
+namespace QmlDesigner {
+
+class NavigatorController : public StackedUtilityPanelController
+{
+public:
+ NavigatorController(QObject* parent = 0);
+
+protected:
+ class QWidget* stackedPageWidget(class DesignDocumentController* designDocumentController) const;
+};
+
+} // namespace QmlDesigner
+
+#endif // NAVIGATORCONTROLLER_H
diff --git a/src/plugins/qmldesigner/components/integration/stackedutilitypanelcontroller.cpp b/src/plugins/qmldesigner/components/integration/stackedutilitypanelcontroller.cpp
new file mode 100644
index 0000000000..b708ff2f8b
--- /dev/null
+++ b/src/plugins/qmldesigner/components/integration/stackedutilitypanelcontroller.cpp
@@ -0,0 +1,76 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <QtGui/QStackedWidget>
+
+#include "designdocumentcontroller.h"
+#include "stackedutilitypanelcontroller.h"
+
+namespace QmlDesigner {
+
+StackedUtilityPanelController::StackedUtilityPanelController(QObject* parent):
+ UtilityPanelController(parent),
+ m_stackedWidget(new QStackedWidget)
+{
+ m_stackedWidget->setLineWidth(0);
+ m_stackedWidget->setMidLineWidth(0);
+ m_stackedWidget->setFrameStyle(QFrame::NoFrame);
+}
+
+void StackedUtilityPanelController::show(DesignDocumentController* designDocumentController)
+{
+ if (!designDocumentController)
+ return;
+
+ QWidget* page = stackedPageWidget(designDocumentController);
+
+ if (!m_stackedWidget->children().contains(page))
+ m_stackedWidget->addWidget(page);
+
+ m_stackedWidget->setCurrentWidget(page);
+ page->show();
+}
+
+void StackedUtilityPanelController::close(DesignDocumentController* designDocumentController)
+{
+ QWidget* page = stackedPageWidget(designDocumentController);
+
+ if (m_stackedWidget->children().contains(page)) {
+ page->hide();
+ m_stackedWidget->removeWidget(page);
+ }
+}
+
+QWidget* StackedUtilityPanelController::contentWidget() const
+{
+ return m_stackedWidget;
+}
+
+} // namespace QmlDesigner
+
diff --git a/src/plugins/qmldesigner/components/integration/stackedutilitypanelcontroller.h b/src/plugins/qmldesigner/components/integration/stackedutilitypanelcontroller.h
new file mode 100644
index 0000000000..971b50c61a
--- /dev/null
+++ b/src/plugins/qmldesigner/components/integration/stackedutilitypanelcontroller.h
@@ -0,0 +1,60 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef StackedUtilityPanelController_h
+#define StackedUtilityPanelController_h
+
+#include "utilitypanelcontroller.h"
+
+namespace QmlDesigner {
+
+class DesignDocumentController;
+
+class StackedUtilityPanelController : public UtilityPanelController
+{
+ Q_OBJECT
+
+public:
+ StackedUtilityPanelController(QObject* parent = 0);
+
+public slots:
+ void show(DesignDocumentController* designDocumentController);
+ void close(DesignDocumentController* designDocumentController);
+
+protected:
+ virtual QWidget* contentWidget() const;
+ virtual QWidget* stackedPageWidget(DesignDocumentController* designDocumentController) const = 0;
+
+private:
+ class QStackedWidget* m_stackedWidget;
+};
+
+} // namespace QmlDesigner
+
+#endif // StackedUtilityPanelController_h
diff --git a/src/plugins/qmldesigner/components/integration/stateseditorcontroller.cpp b/src/plugins/qmldesigner/components/integration/stateseditorcontroller.cpp
new file mode 100644
index 0000000000..a403dd2e1d
--- /dev/null
+++ b/src/plugins/qmldesigner/components/integration/stateseditorcontroller.cpp
@@ -0,0 +1,50 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "designdocumentcontroller.h"
+#include "stateseditorcontroller.h"
+
+namespace QmlDesigner {
+
+StatesEditorController::StatesEditorController(QObject* parent):
+ StackedUtilityPanelController(parent)
+{
+ setObjectName("StatesEditorController");
+ contentWidget()->setObjectName("statesEditorStack");
+}
+
+QWidget* StatesEditorController::stackedPageWidget(DesignDocumentController* designDocumentController) const
+{
+ if (designDocumentController)
+ return designDocumentController->statesEditorWidget();
+ else
+ return 0;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/integration/stateseditorcontroller.h b/src/plugins/qmldesigner/components/integration/stateseditorcontroller.h
new file mode 100644
index 0000000000..ce90b29b73
--- /dev/null
+++ b/src/plugins/qmldesigner/components/integration/stateseditorcontroller.h
@@ -0,0 +1,48 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef STATESEDITORCONTROLLER_H
+#define STATESEDITORCONTROLLER_H
+
+#include "stackedutilitypanelcontroller.h"
+
+namespace QmlDesigner {
+
+class StatesEditorController : public StackedUtilityPanelController
+{
+public:
+ StatesEditorController(QObject* parent = 0);
+
+protected:
+ class QWidget* stackedPageWidget(class DesignDocumentController* designDocumentController) const;
+};
+
+} // namespace QmlDesigner
+
+#endif // STATESEDITORCONTROLLER_H
diff --git a/src/plugins/qmldesigner/components/integration/utilitypanelcontroller.cpp b/src/plugins/qmldesigner/components/integration/utilitypanelcontroller.cpp
new file mode 100644
index 0000000000..1f430e6ae5
--- /dev/null
+++ b/src/plugins/qmldesigner/components/integration/utilitypanelcontroller.cpp
@@ -0,0 +1,54 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <QtDebug>
+#include <QEvent>
+#include <QtGui/QDockWidget>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QWidget>
+
+#include "utilitypanelcontroller.h"
+
+namespace QmlDesigner {
+
+UtilityPanelController::UtilityPanelController(QObject* parent):
+ QObject(parent)
+{
+}
+
+UtilityPanelController::~UtilityPanelController()
+{
+}
+
+QWidget* UtilityPanelController::widget()
+{
+ return contentWidget();
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/integration/utilitypanelcontroller.h b/src/plugins/qmldesigner/components/integration/utilitypanelcontroller.h
new file mode 100644
index 0000000000..878eacac56
--- /dev/null
+++ b/src/plugins/qmldesigner/components/integration/utilitypanelcontroller.h
@@ -0,0 +1,55 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef UtilityPanelController_h
+#define UtilityPanelController_h
+
+#include <QtCore/QObject>
+#include <QtCore/QString>
+#include <QtGui/QWidget>
+
+namespace QmlDesigner {
+
+class UtilityPanelController : public QObject
+{
+ Q_OBJECT
+
+public:
+ UtilityPanelController(QObject* parent = 0);
+ virtual ~UtilityPanelController() = 0;
+
+ QWidget* widget();
+
+protected:
+ virtual class QWidget* contentWidget() const = 0;
+};
+
+} // namespace QmlDesigner
+
+#endif // UtilityPanelController_h
diff --git a/src/plugins/qmldesigner/components/integration/widgetboxcontroller.cpp b/src/plugins/qmldesigner/components/integration/widgetboxcontroller.cpp
new file mode 100644
index 0000000000..1c7066c0d5
--- /dev/null
+++ b/src/plugins/qmldesigner/components/integration/widgetboxcontroller.cpp
@@ -0,0 +1,51 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <itemlibrary.h>
+
+#include "designdocumentcontroller.h"
+#include "widgetboxcontroller.h"
+
+namespace QmlDesigner {
+
+ItemLibraryController::ItemLibraryController(QObject* parent):
+ StackedUtilityPanelController(parent)
+{
+ setObjectName("ItemLibraryController");
+}
+
+QWidget* ItemLibraryController::stackedPageWidget(DesignDocumentController* designDocumentController) const
+{
+ if (designDocumentController)
+ return designDocumentController->itemLibrary();
+ else
+ return 0;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/integration/widgetboxcontroller.h b/src/plugins/qmldesigner/components/integration/widgetboxcontroller.h
new file mode 100644
index 0000000000..27d69d6288
--- /dev/null
+++ b/src/plugins/qmldesigner/components/integration/widgetboxcontroller.h
@@ -0,0 +1,48 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef ItemLibraryCONTROLLER_H
+#define ItemLibraryCONTROLLER_H
+
+#include "stackedutilitypanelcontroller.h"
+
+namespace QmlDesigner {
+
+class ItemLibraryController : public StackedUtilityPanelController
+{
+public:
+ ItemLibraryController(QObject* parent = 0);
+
+protected:
+ class QWidget* stackedPageWidget(class DesignDocumentController* designDocumentController) const;
+};
+
+} // namespace QmlDesigner
+
+#endif // ItemLibraryCONTROLLER_H
diff --git a/src/plugins/qmldesigner/components/integration/xuifiledialog.cpp b/src/plugins/qmldesigner/components/integration/xuifiledialog.cpp
new file mode 100644
index 0000000000..720ef5403f
--- /dev/null
+++ b/src/plugins/qmldesigner/components/integration/xuifiledialog.cpp
@@ -0,0 +1,91 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <QDebug>
+#include <QtCore/QDir>
+#include <QtCore/QObject>
+
+#include "xuifiledialog.h"
+
+namespace QmlDesigner {
+
+void XUIFileDialog::runOpenFileDialog(const QString& path, QWidget* parent, QObject* receiver, const char* member)
+{
+ QString dir = path;
+ if (dir.isNull())
+ dir = XUIFileDialog::defaultFolder();
+
+ QString caption = QObject::tr("Open file", "XUIFileDialog::runOpenFileDialog");
+ QString fileName = QFileDialog::getOpenFileName(parent, caption, dir, XUIFileDialog::fileNameFilters().join(";;"), 0, QFileDialog::ReadOnly);
+
+ QmlDesigner::Internal::SignalEmitter emitter;
+ QObject::connect(&emitter, SIGNAL(fileNameSelected(QString)), receiver, member);
+ emitter.emitFileNameSelected(fileName);
+}
+
+void XUIFileDialog::runSaveFileDialog(const QString& path, QWidget* parent, QObject* receiver, const char* member)
+{
+ QString dir = path;
+ if (dir.isNull())
+ dir = XUIFileDialog::defaultFolder();
+
+#ifdef Q_WS_MAC
+ QFileDialog *dialog = new QFileDialog(parent, Qt::Sheet);
+ dialog->setFileMode(QFileDialog::AnyFile);
+ dialog->setAcceptMode(QFileDialog::AcceptSave);
+ dialog->setNameFilters(XUIFileDialog::fileNameFilters());
+ dialog->setDirectory(dir);
+ dialog->open(receiver, member);
+#else // !Q_WS_MAC
+ QString caption = QObject::tr("Save file", "XUIFileDialog::runSaveFileDialog");
+ QString fileName = QFileDialog::getSaveFileName(parent, caption, dir, XUIFileDialog::fileNameFilters().join(";;"));
+
+ QmlDesigner::Internal::SignalEmitter emitter;
+ QObject::connect(&emitter, SIGNAL(fileNameSelected(QString)), receiver, member);
+ emitter.emitFileNameSelected(fileName);
+#endif // Q_WS_MAC
+}
+
+QStringList XUIFileDialog::fileNameFilters()
+{
+ QStringList filters;
+
+ filters
+ << QObject::tr("Declarative UI files (*.qml)", "XUIFileDialog::fileNameFilters")
+ << QObject::tr("All files (*)", "XUIFileDialog::fileNameFilters");
+
+ return filters;
+}
+
+QString XUIFileDialog::defaultFolder()
+{
+ return QDir::currentPath();
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/integration/xuifiledialog.h b/src/plugins/qmldesigner/components/integration/xuifiledialog.h
new file mode 100644
index 0000000000..bcd0ff52f8
--- /dev/null
+++ b/src/plugins/qmldesigner/components/integration/xuifiledialog.h
@@ -0,0 +1,65 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef XUIFILEDIALOG_H
+#define XUIFILEDIALOG_H
+
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+
+#include <QtGui/QFileDialog>
+
+namespace QmlDesigner {
+
+class XUIFileDialog
+{
+public:
+ static void runOpenFileDialog(const QString& path, QWidget* parent, QObject* receiver, const char* member);
+ static void runSaveFileDialog(const QString& path, QWidget* parent, QObject* receiver, const char* member);
+
+ static QStringList fileNameFilters();
+ static QString defaultFolder();
+};
+
+namespace Internal {
+class SignalEmitter: public QObject
+{
+ Q_OBJECT
+
+public:
+ void emitFileNameSelected(const QString& fileName) { emit fileNameSelected(fileName); }
+
+signals:
+ void fileNameSelected(const QString&);
+};
+
+} // namespace Internal
+} // namespace QmlDesigner
+
+#endif // XUIFILEDIALOG_H
diff --git a/src/plugins/qmldesigner/components/itemlibrary/customdraganddrop.cpp b/src/plugins/qmldesigner/components/itemlibrary/customdraganddrop.cpp
new file mode 100644
index 0000000000..a080096665
--- /dev/null
+++ b/src/plugins/qmldesigner/components/itemlibrary/customdraganddrop.cpp
@@ -0,0 +1,301 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "customdraganddrop.h"
+
+#include <QtCore/QMimeData>
+#include <QtCore/QPoint>
+#include <QLabel>
+
+#include <QMouseEvent>
+#include <QApplication>
+#include <QDebug>
+#include <QPainter>
+
+namespace QmlDesigner {
+
+namespace QmlDesignerItemLibraryDragAndDrop {
+
+void CustomDragAndDropIcon::startDrag()
+{
+ m_size = m_icon.size();
+ setPixmap(m_icon);
+ m_iconAlpha = 1;
+ m_previewAlpha = 0;
+
+ QPoint pos = QCursor::pos();
+ QWidget *widget = QApplication::topLevelAt(pos);
+ setParent(widget);
+ raise();
+ show();
+
+ grabMouse();
+}
+
+void CustomDragAndDropIcon::mouseReleaseEvent(QMouseEvent *event)
+{
+ QPoint globalPos = event->globalPos();
+ releaseMouse();
+ move(-1000, -1000); //-1000, -1000 is used to hide because hiding causes propblems with the mouse grabber
+ QWidget* target = QApplication::widgetAt(globalPos - QPoint(2,2)); //-(2, 2) because:
+ // otherwise we just get this widget
+
+ if (CustomDragAndDrop::isAccepted()) // if the target widget accepted the enter event,
+ // then create a drop event
+ CustomDragAndDrop::drop(target, globalPos);
+ CustomDragAndDrop::endCustomDrag();
+}
+
+void CustomDragAndDropIcon::mouseMoveEvent(QMouseEvent *event)
+{
+ QPoint globalPos = event->globalPos();
+ QWidget * widget = QApplication::topLevelAt(globalPos); //grap the "current" top level widget
+ if (widget) {
+ setParent(widget); //set the current top level widget as parent
+ QPoint pos = parentWidget()->mapFromGlobal(globalPos);
+ if ((pos.y() > 30 && CustomDragAndDrop::isVisible())) //do not allow dragging over the menubar
+ move(pos);
+ else
+ move(-1000, -1000); //no hiding because of mouse grabbing
+ setPixmap(currentImage());
+ resize(m_size);
+ show();
+ update();
+ }
+ else {
+ move(-1000, -1000); //if no top level widget is found we are out of the main window
+ }
+ QWidget* target = QApplication::widgetAt(globalPos - QPoint(2,2)); //-(2, 2) because:
+ // otherwise we just get this widget
+ if (target != m_oldTarget) {
+ if (CustomDragAndDrop::isAccepted())
+ CustomDragAndDrop::leave(m_oldTarget, globalPos); // create DragLeave event if drag enter
+ // event was accepted
+ bool wasAccepted = CustomDragAndDrop::isAccepted();
+ CustomDragAndDrop::enter(target, globalPos); // create and handle the create enter event
+ releaseMouse(); //to set the cursor we have to disable the mouse grabber
+ if (CustomDragAndDrop::isAccepted()) { //setting the right cursor and trigger animation
+ setCursor(Qt::CrossCursor);
+ if (!wasAccepted)
+ enter(); //trigger animation if enter event was accepted
+ } else {
+ setCursor(Qt::ForbiddenCursor);
+ if (wasAccepted)
+ leave(); // trigger animation if we leave a widget that accepted
+ // the drag enter event
+ }
+ grabMouse(); //enable the mouse grabber again - after the curser is set
+ } else {
+ if (CustomDragAndDrop::isAccepted()) // create DragMoveEvents if the current widget
+ // accepted the DragEnter event
+ CustomDragAndDrop::move(target, globalPos);
+ }
+ m_oldTarget = target;
+}
+
+
+QPixmap CustomDragAndDropIcon::currentImage()
+{
+ //blend the two images (icon and preview) according to alpha values
+ QPixmap pixmap(m_size);
+ pixmap.fill(Qt::white);
+ QPainter p(&pixmap);
+ if (CustomDragAndDrop::isAccepted()) {
+ p.setOpacity(m_previewAlpha);
+ p.drawPixmap(0 ,0 , m_size.width(), m_size.height(), m_preview);
+ p.setOpacity(m_iconAlpha);
+ p.drawPixmap(0, 0, m_size.width(), m_size.height(), m_icon);
+ } else {
+ p.setOpacity(m_iconAlpha);
+ p.drawPixmap(0, 0, m_size.width(), m_size.height(), m_icon);
+ p.setOpacity(m_previewAlpha);
+ p.drawPixmap(0 ,0 , m_size.width(), m_size.height(), m_preview);
+ }
+ return pixmap;
+}
+
+void CustomDragAndDropIcon::enter()
+{
+ connect(&m_timeLine, SIGNAL( frameChanged (int)), this, SLOT(animateDrag(int)));
+ m_timeLine.setFrameRange(0, 10);
+ m_timeLine.setDuration(250);
+ m_timeLine.setLoopCount(1);
+ m_timeLine.setCurveShape(QTimeLine::EaseInCurve);
+ m_timeLine.start();
+ m_size = m_icon.size();
+ m_iconAlpha = 1;
+ m_previewAlpha = 0;
+}
+
+void CustomDragAndDropIcon::leave()
+{
+ connect(&m_timeLine, SIGNAL( frameChanged (int)), this, SLOT(animateDrag(int)));
+ m_timeLine.setFrameRange(0, 10);
+ m_timeLine.setDuration(250);
+ m_timeLine.setLoopCount(1);
+ m_timeLine.setCurveShape(QTimeLine::EaseInCurve);
+ m_timeLine.start();
+ m_size = m_preview.size();
+ m_iconAlpha = 0;
+ m_previewAlpha = 1;
+}
+
+void CustomDragAndDropIcon::animateDrag(int frame)
+{
+ //interpolation of m_size and alpha values
+ if (CustomDragAndDrop::isAccepted()) {
+ //small -> big
+ m_iconAlpha = 1.0 - qreal(frame) / 10.0;
+ m_previewAlpha = qreal(frame) / 10.0;
+ int width = qreal(m_preview.width()) * (qreal(frame) / 10.0) + qreal(m_icon.width()) * (1.0 - qreal(frame) / 10.0);
+ int height = qreal(m_preview.height()) * (qreal(frame) / 10.0) + qreal(m_icon.height()) * (1 - qreal(frame) / 10.0);
+ m_size = QSize(width, height);
+ } else {
+ //big -> small
+ m_previewAlpha = 1.0 - qreal(frame) / 10.0;
+ m_iconAlpha = qreal(frame) / 10.0;
+ int width = qreal(m_icon.width()) * (qreal(frame) / 10.0) + qreal(m_preview.width()) * (1.0 - qreal(frame) / 10.0);
+ int height = qreal(m_icon.height()) * (qreal(frame) / 10.0) + qreal(m_preview.height()) * (1 - qreal(frame) / 10.0);
+ m_size = QSize(width, height);
+ }
+ QPoint p = pos();
+ setPixmap(currentImage());
+ resize(m_size);
+ move(p);
+ update(); //redrawing needed
+}
+
+
+class CustomDragAndDropGuard { //This guard destroys the singleton in its destructor
+public: //This should avoid that a memory leak is reported
+ ~CustomDragAndDropGuard() {
+ if (CustomDragAndDrop::m_instance != 0)
+ delete CustomDragAndDrop::m_instance;
+ }
+};
+
+
+CustomDragAndDrop* CustomDragAndDrop::m_instance = 0;
+
+CustomDragAndDrop::CustomDragAndDrop() : m_customDragActive(0), m_mimeData(0), m_accepted(false)
+{
+ m_widget = new CustomDragAndDropIcon(QApplication::topLevelWidgets().first());
+ m_widget->move(-1000, 1000);
+ m_widget->resize(32, 32);
+ m_widget->show();
+}
+
+
+CustomDragAndDrop* CustomDragAndDrop::instance()
+{
+ static CustomDragAndDropGuard guard; //The destructor destroys the singleton. See above
+ if (m_instance == 0)
+ m_instance = new CustomDragAndDrop();
+ return m_instance;
+}
+
+void CustomDragAndDrop::endCustomDrag()
+{
+ instance()->m_customDragActive = false;
+}
+
+void CustomDragAndDrop::startCustomDrag(const QPixmap icon, const QPixmap preview, QMimeData * mimeData)
+{
+ if (instance()->m_customDragActive) {
+ qWarning("CustomDragAndDrop::startCustomDrag drag is active");
+ return ;
+ }
+ instance()->m_customDragActive = true;
+ instance()-> m_accepted = false;
+ show();
+ instance()->m_mimeData = mimeData;
+ instance()->m_widget->setIcon(icon);
+ instance()->m_widget->setPreview(preview);
+ instance()->m_widget->startDrag();
+
+}
+
+bool CustomDragAndDrop::customDragActive()
+{
+ return instance()->m_customDragActive;
+}
+
+bool CustomDragAndDrop::isAccepted()
+{
+ return instance()->m_accepted;
+}
+
+void CustomDragAndDrop::enter(QWidget *target, QPoint globalPos)
+{
+ if (target) {
+ QPoint pos = target->mapFromGlobal(globalPos);
+ QDragEnterEvent event(pos, Qt::MoveAction, instance()->m_mimeData ,Qt::RightButton, Qt::NoModifier);
+ QApplication::sendEvent(target, &event);
+ instance()-> m_accepted = event.isAccepted(); //if the event is accepted we enter the "accepted" state
+ } else {
+ instance()-> m_accepted = false;
+ }
+}
+
+void CustomDragAndDrop::leave(QWidget *target, QPoint globalPos)
+{
+ if (target) {
+ QPoint pos = target->mapFromGlobal(globalPos);
+ QDragLeaveEvent event;
+ QApplication::sendEvent(target, &event);
+ } else {
+ qWarning() << "CustomDragAndDrop::leave leaving invalid target";
+ }
+}
+
+void CustomDragAndDrop::move(QWidget *target, QPoint globalPos)
+{
+ if (target) {
+ QPoint pos = target->mapFromGlobal(globalPos);
+ QDragMoveEvent event(pos, Qt::MoveAction, instance()->m_mimeData ,Qt::RightButton, Qt::NoModifier);
+ QApplication::sendEvent(target, &event);
+ } else {
+ qWarning() << "CustomDragAndDrop::move move in invalid target";
+ }
+}
+
+void CustomDragAndDrop::drop(QWidget *target, QPoint globalPos)
+{
+ if (target) {
+ QPoint pos = target->mapFromGlobal(globalPos);
+ QDropEvent event(pos, Qt::MoveAction, instance()->m_mimeData ,Qt::RightButton, Qt::NoModifier);
+ QApplication::sendEvent(target, &event);
+ } else {
+ qWarning() << "CustomDragAndDrop::drop dropping in invalid target";
+ }
+}
+
+} //namespace QmlDesignerItemLibraryDragAndDrop
+} //namespave QmlDesigner
+
diff --git a/src/plugins/qmldesigner/components/itemlibrary/customdraganddrop.h b/src/plugins/qmldesigner/components/itemlibrary/customdraganddrop.h
new file mode 100644
index 0000000000..df50fe6c32
--- /dev/null
+++ b/src/plugins/qmldesigner/components/itemlibrary/customdraganddrop.h
@@ -0,0 +1,127 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <QPixmap>
+#include <QLabel>
+#include <QTimeLine>
+#include <QDrag>
+
+class QMimeData;
+
+namespace QmlDesigner {
+
+namespace QmlDesignerItemLibraryDragAndDrop {
+
+class CustomDragAndDropIcon : public QLabel { //this class shows the icon for the drag drop operation
+ Q_OBJECT
+public:
+ CustomDragAndDropIcon(QWidget *parent = 0) : QLabel(parent), m_oldTarget(0)
+ {
+ }
+ void setPreview(const QPixmap &pixmap)
+ { m_preview = pixmap; }
+ void setIcon(const QPixmap &pixmap)
+ { m_icon = pixmap; }
+
+ void enter();
+ void leave();
+ void startDrag();
+
+public slots:
+ void animateDrag(int frame);
+
+protected:
+ virtual void mouseMoveEvent(QMouseEvent *);
+ virtual void mouseReleaseEvent(QMouseEvent *);
+private:
+ QPixmap currentImage();
+
+ QWidget *m_oldTarget;
+ QPixmap m_preview;
+ QPixmap m_icon;
+ QTimeLine m_timeLine;
+ QSize m_size;
+ qreal m_iconAlpha, m_previewAlpha;
+};
+
+
+class CustomDragAndDrop { //this class handles the drag and drop logic
+public:
+ static void startCustomDrag(const QPixmap icon, const QPixmap preview, QMimeData * mimeData);
+ static bool customDragActive();
+ static bool isAccepted();
+ static void endCustomDrag();
+ static void enter(QWidget *target, QPoint globalPos);
+ static void leave(QWidget *target, QPoint globalPos);
+ static void move(QWidget *target, QPoint globalPos);
+ static void drop(QWidget *target, QPoint globalPos);
+ static void hide()
+ { instance()->m_isVisible = false; }
+ static void show()
+ { instance()->m_isVisible = true; }
+ static bool isVisible()
+ { return instance()->m_isVisible; }
+
+private:
+ CustomDragAndDrop();
+ static CustomDragAndDrop* instance();
+ static CustomDragAndDrop* m_instance;
+
+ CustomDragAndDropIcon *m_widget;
+ bool m_customDragActive;
+ QPoint m_pos;
+ QMimeData *m_mimeData;
+ bool m_accepted;
+ bool m_isVisible;
+
+ friend class CustomDragAndDropGuard;
+};
+
+} //namespace QmlDesignerItemLibraryDragAndDrop
+
+class CustomItemLibraryDrag : public QDrag {
+ Q_OBJECT
+ public:
+ CustomItemLibraryDrag(QWidget * dragSource) : QDrag(dragSource), m_mimeData(0)
+ {}
+ void setPixmap(const QPixmap &pixmap)
+ { m_pixmap = pixmap; }
+ void setPreview(const QPixmap &pixmap)
+ { m_preview = pixmap; }
+ void setMimeData(QMimeData *mimeData)
+ { m_mimeData = mimeData; }
+ void exec()
+ { QmlDesignerItemLibraryDragAndDrop::CustomDragAndDrop::startCustomDrag(m_pixmap, m_preview, m_mimeData); }
+
+private:
+ QPixmap m_pixmap, m_preview;
+ QMimeData *m_mimeData;
+ };
+
+} //namespave QmlDesigner
diff --git a/src/plugins/qmldesigner/components/itemlibrary/default-icon.png b/src/plugins/qmldesigner/components/itemlibrary/default-icon.png
new file mode 100644
index 0000000000..a90779f02a
--- /dev/null
+++ b/src/plugins/qmldesigner/components/itemlibrary/default-icon.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrary.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrary.cpp
new file mode 100644
index 0000000000..3616992fcd
--- /dev/null
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrary.cpp
@@ -0,0 +1,319 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "itemlibrary.h"
+
+#include "itemlibrarymodel.h"
+#include "customdraganddrop.h"
+
+#include "ui_itemlibrary.h"
+#include <metainfo.h>
+#include <itemlibraryinfo.h>
+#include <formeditorscene.h>
+
+#include <QtCore/QDebug>
+#include <QtGui/QContextMenuEvent>
+#include <QtGui/QMenu>
+#include <QtGui/QAction>
+#include <QtGui/QGraphicsView>
+#include <QtGui/QGraphicsScene>
+#include <QtGui/QGraphicsItem>
+#include <QtGui/QPixmap>
+#include <QSortFilterProxyModel>
+#include <QLabel>
+#include <QMainWindow>
+#include <QMenuBar>
+#include <QFile>
+#include <QDirModel>
+#include <QFileIconProvider>
+
+
+namespace QmlDesigner {
+
+class MyFileIconProvider : public QFileIconProvider
+{
+public:
+ MyFileIconProvider() : QFileIconProvider()
+ {}
+ virtual QIcon icon ( const QFileInfo & info ) const
+ {
+ QPixmap pixmap(info.absoluteFilePath());
+ if (pixmap.isNull())
+ return QFileIconProvider::icon(info);
+ else return pixmap; //pixmap.scaled(128, 128, Qt::KeepAspectRatio);
+ }
+};
+
+
+
+class GrabHelper {
+ Q_DISABLE_COPY(GrabHelper)
+public:
+ GrabHelper();
+ QPixmap grabItem(QGraphicsItem *item);
+
+private:
+ QGraphicsScene m_scene;
+ QGraphicsView m_view;
+};
+
+GrabHelper::GrabHelper()
+{
+ m_view.setScene(&m_scene);
+ m_view.setFrameShape(QFrame::NoFrame);
+ m_view.setAlignment(Qt::AlignLeft|Qt::AlignTop);
+ m_view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ m_view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+}
+
+QPixmap GrabHelper::grabItem(QGraphicsItem *item)
+{
+ if (item->scene()) {
+ qWarning("%s: WARNING: Attempt to grab item that is part of another scene!", Q_FUNC_INFO);
+ return QPixmap();
+ }
+ // Temporarily add the item, resize the view widget and grab it.
+ m_scene.addItem(item);
+ item->setPos(0.0, 0.0);
+ const QSize size = item->boundingRect().size().toSize();
+ QPixmap rc;
+ if (!size.isEmpty()) { // We have seen horses barf...
+ m_view.resize(size);
+ rc = QPixmap::grabWidget(&m_view);
+ }
+ m_scene.removeItem(item);
+ return rc;
+}
+
+// ---------- ItemLibraryPrivate
+class ItemLibraryPrivate {
+public:
+ ItemLibraryPrivate(QObject *object);
+ ~ItemLibraryPrivate();
+
+ Ui::ItemLibrary m_ui;
+ Internal::ItemLibraryModel *m_itemLibraryModel;
+ QDirModel *m_resourcesDirModel;
+ QSortFilterProxyModel *m_filterProxy;
+ GrabHelper *m_grabHelper;
+ QString m_resourcePath;
+};
+
+ItemLibraryPrivate::ItemLibraryPrivate(QObject *object) :
+ m_itemLibraryModel(0),
+ m_grabHelper(0)
+{
+ m_resourcePath = QDir::currentPath();
+ Q_UNUSED(object);
+}
+
+ItemLibraryPrivate::~ItemLibraryPrivate()
+{
+ delete m_grabHelper;
+}
+
+ItemLibrary::ItemLibrary(QWidget *parent) :
+ QFrame(parent),
+ m_d(new ItemLibraryPrivate(this))
+{
+ m_d->m_ui.setupUi(this);
+ m_d->m_itemLibraryModel = new Internal::ItemLibraryModel(this);
+ m_d->m_resourcesDirModel = new QDirModel(this);
+ m_d->m_filterProxy = new QSortFilterProxyModel(this);
+ m_d->m_filterProxy->setSourceModel(m_d->m_itemLibraryModel);
+ m_d->m_ui.ItemLibraryTreeView->setModel(m_d->m_filterProxy);
+ m_d->m_filterProxy->setDynamicSortFilter(true);
+ m_d->m_ui.ItemLibraryTreeView->setRealModel(m_d->m_itemLibraryModel);
+ m_d->m_ui.ItemLibraryTreeView->setIconSize(QSize(64, 64));
+ m_d->m_ui.ItemLibraryTreeView->setSortingEnabled(true);
+ m_d->m_ui.ItemLibraryTreeView->setHeaderHidden(true);
+ m_d->m_ui.ItemLibraryTreeView->setIndentation(10);
+ m_d->m_ui.ItemLibraryTreeView->setAnimated(true);
+ m_d->m_ui.ItemLibraryTreeView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
+ m_d->m_ui.ItemLibraryTreeView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ m_d->m_ui.ItemLibraryTreeView->setAttribute(Qt::WA_MacShowFocusRect, false);
+ m_d->m_filterProxy->setFilterCaseSensitivity(Qt::CaseInsensitive);
+ m_d->m_filterProxy->setFilterRole(Qt::UserRole);
+ m_d->m_filterProxy->setSortRole(Qt::DisplayRole);
+ connect(m_d->m_ui.lineEdit, SIGNAL(textChanged(QString)), m_d->m_filterProxy, SLOT(setFilterRegExp(QString)));
+ connect(m_d->m_ui.lineEdit, SIGNAL(textChanged(QString)), this, SLOT(setNameFilter(QString)));
+ connect(m_d->m_ui.lineEdit, SIGNAL(textChanged(QString)), this, SLOT(expandAll()));
+ connect(m_d->m_ui.buttonItems, SIGNAL(toggled (bool)), this, SLOT(itemLibraryButton()));
+ connect(m_d->m_ui.buttonResources, SIGNAL(toggled (bool)), this, SLOT(resourcesButton()));
+ connect(m_d->m_ui.ItemLibraryTreeView, SIGNAL(itemActivated(const QString&)), this, SIGNAL(itemActivated(const QString&)));
+ m_d->m_ui.lineEdit->setDragEnabled(false);
+ setNameFilter("");
+
+ MyFileIconProvider *fileIconProvider = new MyFileIconProvider();
+ m_d->m_resourcesDirModel->setIconProvider(fileIconProvider);
+
+ setWindowTitle(tr("Library", "Title of library view"));
+
+ {
+ QFile file(":/qmldesigner/stylesheet.css");
+ file.open(QFile::ReadOnly);
+ QString styleSheet = QLatin1String(file.readAll());
+ setStyleSheet(styleSheet);
+
+ QFile fileTool(":/qmldesigner/toolbutton.css");
+ fileTool.open(QFile::ReadOnly);
+ styleSheet = QLatin1String(fileTool.readAll());
+ m_d->m_ui.buttonItems->setStyleSheet(styleSheet);
+ m_d->m_ui.buttonResources->setStyleSheet(styleSheet);
+ }
+
+ {
+ QFile file(":/qmldesigner/scrollbar.css");
+ file.open(QFile::ReadOnly);
+ QString styleSheet = QLatin1String(file.readAll());
+ m_d->m_ui.ItemLibraryTreeView->setStyleSheet(styleSheet);
+ }
+
+ m_d->m_ui.buttonItems->setChecked(true);
+}
+
+ItemLibrary::~ItemLibrary()
+{
+ delete m_d;
+}
+
+void ItemLibrary::setNameFilter(const QString &nameFilter)
+{
+ QStringList nameFilterList;
+ nameFilterList.append(nameFilter + "*.gif");
+ nameFilterList.append(nameFilter + "*.png");
+ nameFilterList.append(nameFilter + "*.jpg");
+ nameFilterList.append(nameFilter + "*.");
+ m_d->m_resourcesDirModel->setFilter(QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot);
+ m_d->m_resourcesDirModel->setNameFilters(nameFilterList);
+ m_d->m_ui.ItemLibraryTreeView->setRootIndex(m_d->m_resourcesDirModel->index(m_d->m_resourcePath));
+}
+
+void ItemLibrary::itemLibraryButton()
+{
+ if (m_d->m_ui.buttonItems->isChecked()) {
+ m_d->m_filterProxy->setSourceModel(m_d->m_itemLibraryModel);
+ m_d->m_ui.ItemLibraryTreeView->setModel(m_d->m_filterProxy);
+ m_d->m_ui.ItemLibraryTreeView->setIconSize(QSize(64, 64));
+ m_d->m_ui.buttonResources->setChecked(false);
+ m_d->m_ui.ItemLibraryTreeView->setRealModel(m_d->m_itemLibraryModel);
+ expandAll();
+ }
+}
+
+void ItemLibrary::resourcesButton()
+{
+ if (m_d->m_ui.buttonResources->isChecked()) {
+ m_d->m_ui.ItemLibraryTreeView->setModel(m_d->m_resourcesDirModel);
+ m_d->m_ui.ItemLibraryTreeView->setIconSize(QSize(32, 32));
+ m_d->m_ui.buttonItems->setChecked(false);
+ m_d->m_ui.ItemLibraryTreeView->setRootIndex(m_d->m_resourcesDirModel->index(m_d->m_resourcePath));
+ m_d->m_ui.ItemLibraryTreeView->setColumnHidden(1, true);
+ m_d->m_ui.ItemLibraryTreeView->setColumnHidden(2, true);
+ m_d->m_ui.ItemLibraryTreeView->setColumnHidden(3, true);
+ expandAll();
+ }
+}
+
+void ItemLibrary::addItemLibraryInfo(const ItemLibraryInfo &itemLibraryInfo)
+{
+ m_d->m_itemLibraryModel->addItemLibraryInfo(itemLibraryInfo);
+}
+
+void ItemLibrary::setResourcePath(const QString &resourcePath)
+{
+ m_d->m_resourcePath = resourcePath;
+}
+
+void ItemLibrary::setMetaInfo(const MetaInfo &metaInfo)
+{
+ m_d->m_itemLibraryModel->clear();
+
+ foreach (const QString &type, metaInfo.itemLibraryItems()) {
+ NodeMetaInfo nodeInfo = metaInfo.nodeMetaInfo(type);
+
+ QList<ItemLibraryInfo> itemLibraryRepresentationList = metaInfo.itemLibraryRepresentations(nodeInfo);
+
+ if (!metaInfo.hasNodeMetaInfo(type))
+ qWarning() << "ItemLibrary: type not declared: " << type;
+ if (!itemLibraryRepresentationList.isEmpty() && metaInfo.hasNodeMetaInfo(type)) {
+ foreach (ItemLibraryInfo itemLibraryRepresentation, itemLibraryRepresentationList) {
+ QImage image(64, 64, QImage::Format_RGB32); // = m_d->m_queryView->paintObject(nodeInfo, itemLibraryRepresentation.properties()); TODO
+ if (!image.isNull()) {
+ QPainter p(&image);
+ QPen pen(Qt::gray);
+ pen.setWidth(2);
+ p.setPen(pen);
+ p.drawRect(1, 1, image.width() - 2, image.height() - 2);
+ }
+ QIcon icon = itemLibraryRepresentation.icon();
+ if (itemLibraryRepresentation.icon().isNull())
+ itemLibraryRepresentation.setIcon(QIcon(":/ItemLibrary/images/default-icon.png"));
+
+ if (itemLibraryRepresentation.category().isEmpty())
+ itemLibraryRepresentation.setCategory(nodeInfo.category());
+ if (!image.isNull()) {
+ itemLibraryRepresentation.setDragIcon(QPixmap::fromImage(image));
+ addItemLibraryInfo(itemLibraryRepresentation);
+ }
+ }
+ } else {
+ QImage image; // = m_d->m_queryView->paintObject(nodeInfo); TODO we have to render image
+ QIcon icon = nodeInfo.icon();
+ if (icon.isNull())
+ icon = QIcon(":/ItemLibrary/images/default-icon.png");
+
+ ItemLibraryInfo itemLibraryInfo;
+ itemLibraryInfo.setName(type);
+ itemLibraryInfo.setTypeName(nodeInfo.typeName());
+ itemLibraryInfo.setCategory(nodeInfo.category());
+ itemLibraryInfo.setIcon(icon);
+ itemLibraryInfo.setMajorVersion(nodeInfo.majorVersion());
+ itemLibraryInfo.setMinorVersion(nodeInfo.minorVersion());
+ itemLibraryInfo.setDragIcon(QPixmap::fromImage(image));
+ addItemLibraryInfo(itemLibraryInfo);
+ }
+ }
+ expandAll();
+}
+
+void ItemLibrary::expandAll()
+{
+ m_d->m_ui.ItemLibraryTreeView->expandToDepth(1);
+}
+
+void ItemLibrary::contextMenuEvent (QContextMenuEvent *event)
+{
+ event->accept();
+ QMenu menu;
+ menu.addAction(tr("About plugins..."));
+ menu.exec(event->globalPos());
+}
+
+}
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrary.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibrary.h
new file mode 100644
index 0000000000..309e120490
--- /dev/null
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrary.h
@@ -0,0 +1,80 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef ITEMLIBRARY_H
+#define ITEMLIBRARY_H
+
+#include <QtGui/QFrame>
+
+class QGraphicsItem;
+class QPixmap;
+class QMimeData;
+
+namespace QmlDesigner {
+
+class ItemLibraryPrivate;
+class MetaInfo;
+class ItemLibraryInfo;
+
+class ItemLibrary : public QFrame
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(ItemLibrary)
+public:
+ ItemLibrary(QWidget *parent = 0);
+ virtual ~ItemLibrary();
+
+ void addItemLibraryInfo(const ItemLibraryInfo &ItemLibraryInfo);
+ void setMetaInfo(const MetaInfo &metaInfo);
+
+ // Helper for creating widget box items. Note that this temporarily
+ // adds the item to a scene, so, the item must not be associated
+ // with a scene.
+
+public Q_SLOTS:
+ void expandAll();
+ void itemLibraryButton();
+ void resourcesButton();
+ void setNameFilter(const QString &nameFilter);
+ void setResourcePath(const QString &resourcePath);
+signals:
+ void itemActivated(const QString& itemName);
+
+protected:
+ virtual void contextMenuEvent (QContextMenuEvent * event);
+
+private:
+ ItemLibraryPrivate *m_d;
+};
+
+//class ItemLibraryFilter : public QObject
+
+}
+
+#endif // ITEMLIBRARY_H
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrary.pri b/src/plugins/qmldesigner/components/itemlibrary/itemlibrary.pri
new file mode 100644
index 0000000000..b8212323f1
--- /dev/null
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrary.pri
@@ -0,0 +1,12 @@
+######################################################################
+# Automatically generated by qmake (2.01a) Fri Mar 6 12:55:36 2009
+######################################################################
+
+VPATH += $$PWD
+INCLUDEPATH += $$PWD
+
+# Input
+HEADERS += itemlibrary.h itemlibrarymodel.h customdraganddrop.h
+FORMS += itemlibrary.ui
+SOURCES += itemlibrary.cpp itemlibrarymodel.cpp customdraganddrop.cpp
+RESOURCES += itemlibrary.qrc
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrary.qrc b/src/plugins/qmldesigner/components/itemlibrary/itemlibrary.qrc
new file mode 100644
index 0000000000..c1d136b81d
--- /dev/null
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrary.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/ItemLibrary/images" >
+ <file>default-icon.png</file>
+ </qresource>
+</RCC>
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrary.ui b/src/plugins/qmldesigner/components/itemlibrary/itemlibrary.ui
new file mode 100644
index 0000000000..029896d37b
--- /dev/null
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrary.ui
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>QmlDesigner::ItemLibrary</class>
+ <widget class="QFrame" name="QmlDesigner::ItemLibrary">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>497</width>
+ <height>792</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>ItemLibrary</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <property name="leftMargin">
+ <number>2</number>
+ </property>
+ <property name="topMargin">
+ <number>6</number>
+ </property>
+ <property name="rightMargin">
+ <number>2</number>
+ </property>
+ <property name="bottomMargin">
+ <number>2</number>
+ </property>
+ <property name="horizontalSpacing">
+ <number>4</number>
+ </property>
+ <item row="0" column="0">
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>6</width>
+ <height>27</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Filter: </string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QLineEdit" name="lineEdit"/>
+ </item>
+ <item row="0" column="3">
+ <widget class="QToolButton" name="buttonItems">
+ <property name="minimumSize">
+ <size>
+ <width>80</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Items</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="4">
+ <widget class="QToolButton" name="buttonResources">
+ <property name="minimumSize">
+ <size>
+ <width>80</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Resources</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <property name="autoExclusive">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="5">
+ <widget class="Line" name="line">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" colspan="5">
+ <widget class="QmlDesigner::Internal::ItemLibraryTreeView" name="ItemLibraryTreeView">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <layoutdefault spacing="0" margin="0"/>
+ <customwidgets>
+ <customwidget>
+ <class>QmlDesigner::Internal::ItemLibraryTreeView</class>
+ <extends>QTreeView</extends>
+ <header>itemlibrarymodel.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp
new file mode 100644
index 0000000000..89e81f8313
--- /dev/null
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp
@@ -0,0 +1,297 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "itemlibrarymodel.h"
+#include "itemlibrary.h"
+#include "customdraganddrop.h"
+
+#include <QtCore/QMimeData>
+#include <QtCore/QDebug>
+
+#include <QtGui/QImage>
+#include <QtGui/QPixmap>
+#include <QtGui/QDrag>
+#include <QSortFilterProxyModel>
+#include <QPainter>
+#include <QLabel>
+#include <itemlibraryinfo.h>
+#include <QDirModel>
+
+
+enum { debug = 0 };
+// Store data and a type enumeration along with the QStandardItem
+enum ItemType { CategoryItem, WidgetItem };
+enum Roles { TypeRole = Qt::UserRole + 1,
+ DataRole = Qt::UserRole + 2,
+ DragPixmapRole = Qt::UserRole + 3};
+
+
+static inline ItemType itemType(const QStandardItem *item)
+{
+ return static_cast<ItemType>(item->data(TypeRole).toInt());
+}
+
+static inline QmlDesigner::ItemLibraryInfo widgetItemData(const QStandardItem *item)
+{
+ const QVariant data = item->data(DataRole);
+ if (!data.isValid())
+ return QmlDesigner::ItemLibraryInfo();
+ return qvariant_cast<QmlDesigner::ItemLibraryInfo>(data);
+}
+
+
+
+namespace QmlDesigner {
+namespace Internal {
+
+// Cache a drag pixmap on the icon using the DragPixmapRole data field.
+static QImage cachedDragImage(const ItemLibraryInfo &ItemLibraryInfo,
+ QStandardItem *item)
+{
+ const QVariant cached = item->data(DragPixmapRole);
+ if (cached.type() != QVariant::Invalid)
+ return qvariant_cast<QImage>(cached);
+ // TODO: Grab using factory
+ const QIcon icon = ItemLibraryInfo.dragIcon();
+ if (icon.isNull())
+ return QImage();
+ const QList<QSize> sizes = icon.availableSizes();
+ if (sizes.isEmpty())
+ return QImage();
+ const QImage image = icon.pixmap(sizes.front()).toImage();
+ item->setData(image, DragPixmapRole);
+ return image;
+}
+
+ItemLibraryModel::ItemLibraryModel(QObject *parent) :
+ QStandardItemModel(parent)
+{
+ setSupportedDragActions(Qt::CopyAction);
+}
+
+static inline QStandardItem *categoryToItem(const QString &g)
+{
+ QStandardItem *rc = new QStandardItem(g);
+ rc->setFlags(Qt::ItemIsEnabled);
+ rc->setData(QVariant(CategoryItem), TypeRole);
+ rc->setData(g, Qt::UserRole);
+ return rc;
+}
+
+
+static QStandardItem *customWidgetDataToItem(const ItemLibraryInfo &ItemLibraryInfo)
+{
+ QStandardItem *item = new QStandardItem(ItemLibraryInfo.name());
+ const QIcon icon = ItemLibraryInfo.icon();
+ if (!icon.isNull() && !icon.availableSizes().empty()) {
+ item->setIcon(icon);
+ if (icon.availableSizes().count() == 1) {
+ item->setSizeHint(icon.availableSizes().first() + QSize(1, 1));
+ }
+ }
+
+ item->setFlags(Qt::ItemIsEnabled|Qt::ItemIsDragEnabled|Qt::ItemIsSelectable);
+ item->setData(qVariantFromValue(ItemLibraryInfo), DataRole);
+ item->setData(QVariant(WidgetItem), TypeRole);
+ item->setData(ItemLibraryInfo.name(), Qt::UserRole);
+ return item;
+}
+
+
+void ItemLibraryModel::addItemLibraryInfo(const ItemLibraryInfo &itemLibraryInfo)
+{
+ QStandardItem *categoryItem = findCategoryItem(itemLibraryInfo.category());
+ if (!categoryItem) {
+ categoryItem = categoryToItem(itemLibraryInfo.category());
+ appendRow(categoryItem);
+ }
+ categoryItem->appendRow(customWidgetDataToItem(itemLibraryInfo));
+ QString filterList = categoryItem->data(Qt::UserRole).toString();
+ filterList += itemLibraryInfo.name();
+ categoryItem->setData(filterList, Qt::UserRole);
+}
+
+QStandardItem *ItemLibraryModel::findCategoryItem(const QString &category)
+{
+ const QStandardItem *root = invisibleRootItem();
+ const int rowCount = root->rowCount();
+ for (int i = 0 ; i < rowCount; i++) {
+ QStandardItem *categoryItem = root->child(i, 0);
+ if (categoryItem->text() == category)
+ return categoryItem;
+ }
+ return 0;
+}
+
+Qt::DropActions ItemLibraryModel::supportedDragActions() const
+{
+ return Qt::CopyAction;
+}
+
+Qt::DropActions ItemLibraryModel::supportedDropActions() const
+{
+ return Qt::IgnoreAction;
+}
+
+QStringList ItemLibraryModel::mimeTypes () const
+{
+ if (debug)
+ qDebug() << Q_FUNC_INFO;
+ return QStringList(QLatin1String("text/xml"));
+}
+
+QByteArray ItemLibraryInfoToByteArray(const ItemLibraryInfo &ItemLibraryInfo)
+{
+ QByteArray byteArray;
+ QDataStream stream(&byteArray, QIODevice::WriteOnly);
+
+ stream << ItemLibraryInfo;
+
+ return byteArray;
+}
+
+QMimeData *ItemLibraryModel::mimeData(const QModelIndexList &indexes) const
+{
+ if (debug)
+ qDebug() << Q_FUNC_INFO << indexes.size();
+ if (indexes.size() != 1)
+ return 0;
+ QStandardItem *item = itemFromIndex (indexes.front());
+ if (!item || itemType(item) != WidgetItem)
+ return 0;
+ QMimeData *mimeData = new QMimeData;
+
+ ItemLibraryInfo ItemLibraryInfo(widgetItemData(item));
+
+ const QImage image = cachedDragImage(ItemLibraryInfo, item);
+ if (!image.isNull())
+ mimeData->setImageData(image);
+
+
+ mimeData->setData("application/vnd.bauhaus.itemlibraryinfo", ItemLibraryInfoToByteArray(ItemLibraryInfo));
+ mimeData->removeFormat("text/plain");
+
+ return mimeData;
+}
+
+ItemLibraryTreeView::ItemLibraryTreeView(QWidget *parent) :
+ QTreeView(parent)
+{
+ setDragEnabled(true);
+ setDragDropMode(QAbstractItemView::DragOnly);
+ connect(this, SIGNAL(clicked(const QModelIndex &)), this, SLOT(activateItem(const QModelIndex &)));
+}
+
+// We need to implement startDrag ourselves since we cannot
+// otherwise influence drag pixmap and hotspot in the standard
+// implementation.
+void ItemLibraryTreeView::startDrag(Qt::DropActions /* supportedActions */)
+{
+ if (debug)
+ qDebug() << Q_FUNC_INFO;
+ QMimeData *mimeData = model()->mimeData(selectedIndexes());
+ if (!mimeData)
+ return;
+
+ if (qobject_cast<QSortFilterProxyModel*>(model())) {
+ QModelIndex index = qobject_cast<QSortFilterProxyModel*>(model())->mapToSource(selectedIndexes().front());
+
+ QStandardItem *item = m_model->itemFromIndex(index);
+
+ if (!item)
+ return;
+
+ CustomItemLibraryDrag *drag = new CustomItemLibraryDrag(this);
+ const QImage image = qvariant_cast<QImage>(mimeData->imageData());
+ drag->setPixmap(item->icon().pixmap(32, 32));
+ drag->setPreview(QPixmap::fromImage(image));
+ drag->setMimeData(mimeData);
+
+ drag->exec();
+ } else {
+ QDirModel *dirModel = qobject_cast<QDirModel*>(model());
+ Q_ASSERT(dirModel);
+ QFileInfo fileInfo = dirModel->fileInfo(selectedIndexes().front());
+ QPixmap pixmap(fileInfo.absoluteFilePath());
+ if (!pixmap.isNull()) {
+ CustomItemLibraryDrag *drag = new CustomItemLibraryDrag(this);
+ drag->setPreview(pixmap);
+ drag->setPixmap(QIcon(pixmap).pixmap(128, 128));
+ QMimeData *mimeData = new QMimeData;
+ mimeData->setData("application/vnd.bauhaus.libraryresource", fileInfo.absoluteFilePath().toLatin1());
+ drag->setMimeData(mimeData);
+ drag->exec();
+ }
+ }
+}
+
+static ItemLibraryInfo ItemLibraryInfoFromData(const QByteArray &data)
+{
+ QDataStream stream(data);
+
+ ItemLibraryInfo itemLibraryInfo;
+ stream >> itemLibraryInfo;
+
+ return itemLibraryInfo;
+}
+
+void ItemLibraryTreeView::activateItem( const QModelIndex & /*index*/)
+{
+ QMimeData *mimeData = model()->mimeData(selectedIndexes());
+ if (!mimeData)
+ return;
+
+ QString name;
+ if (qobject_cast<QSortFilterProxyModel*>(model())) {
+ QModelIndex index = qobject_cast<QSortFilterProxyModel*>(model())->mapToSource(selectedIndexes().front());
+
+ QStandardItem *item = m_model->itemFromIndex(index);
+
+ if (!item)
+ return;
+
+ ItemLibraryInfo itemLibraryInfo = ItemLibraryInfoFromData(mimeData->data("application/vnd.bauhaus.itemlibraryinfo"));
+ QString type = itemLibraryInfo.name();
+
+ name = "item^" + type;
+ emit itemActivated(name);
+ } else {
+ QDirModel *dirModel = qobject_cast<QDirModel*>(model());
+ Q_ASSERT(dirModel);
+ QFileInfo fileInfo = dirModel->fileInfo(selectedIndexes().front());
+ QPixmap pixmap(fileInfo.absoluteFilePath());
+ if (!pixmap.isNull()) {
+ name = "image^" + fileInfo.absoluteFilePath();
+ emit itemActivated(name);
+ }
+ }
+}
+
+} // namespace Internal
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.h
new file mode 100644
index 0000000000..f969fdf885
--- /dev/null
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.h
@@ -0,0 +1,89 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef ITEMLIBRARYMODEL_H
+#define ITEMLIBRARYMODEL_H
+
+#include <QtGui/QStandardItemModel>
+#include <QtGui/QTreeView>
+#include <QDrag>
+#include <QDebug>
+#include <QTimeLine>
+
+class QLabel;
+
+namespace QmlDesigner {
+
+class ItemLibraryInfo;
+
+namespace Internal {
+
+// QStandardItemModel-based model for the widget box.
+class ItemLibraryModel : public QStandardItemModel
+{
+ Q_OBJECT
+public:
+ explicit ItemLibraryModel(QObject *parent = 0);
+ void addItemLibraryInfo(const ItemLibraryInfo &ItemLibraryInfo);
+
+
+ QStandardItem *findCategoryItem(const QString &category);
+
+ virtual Qt::DropActions supportedDragActions() const;
+ virtual Qt::DropActions supportedDropActions() const;
+
+ virtual QStringList mimeTypes() const;
+ virtual QMimeData *mimeData(const QModelIndexList &indexes) const;
+};
+
+// ItemLibraryTreeView with Drag implementation
+class ItemLibraryTreeView : public QTreeView {
+ Q_OBJECT
+ public:
+ explicit ItemLibraryTreeView(QWidget *parent = 0);
+
+ virtual void startDrag(Qt::DropActions supportedActions);
+
+ void setRealModel(QStandardItemModel *model) { m_model = model; }
+
+signals:
+ void itemActivated(const QString &itemName);
+private slots:
+ void activateItem( const QModelIndex & index);
+
+private:
+ QPixmap m_smallImage, m_bigImage;
+ QStandardItemModel *m_model;
+};
+
+
+
+} // namespace Internal
+} // namespace QmlDesigner
+#endif // ITEMLIBRARYMODEL_H
diff --git a/src/plugins/qmldesigner/components/logger/logger.cpp b/src/plugins/qmldesigner/components/logger/logger.cpp
new file mode 100644
index 0000000000..93c91944d2
--- /dev/null
+++ b/src/plugins/qmldesigner/components/logger/logger.cpp
@@ -0,0 +1,171 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "logger.h"
+
+#include <qapplication.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <QTime>
+#include <QFile>
+
+#ifdef Q_OS_WIN
+#include <windows.h>
+#endif
+
+QLogger* QLogger::m_instance;
+
+void QLogger::loggerMessageOutput(QtMsgType type, const char *msg)
+{
+ switch (type) {
+ case QtDebugMsg:
+ if (!QLogger::instance()->m_silent)
+ QLogger::instance()->output(msg);
+ break;
+ case QtWarningMsg:
+ fprintf(stderr, "Warning: %s\n", msg);
+ break;
+ case QtCriticalMsg:
+ fprintf(stderr, "Critical: %s\n", msg);
+ break;
+ case QtFatalMsg:
+ fprintf(stderr, "Fatal: %s\n", msg);
+ abort();
+ }
+}
+
+void QLogger::setLevel(int level)
+{
+ instance()->m_level = level;
+}
+
+void QLogger::setSilent(bool silent)
+{
+ instance()->m_silent = silent;
+}
+
+void QLogger::setModul(const QString &modul)
+{
+ instance()->m_modul = modul;
+}
+
+void QLogger::setFilename(const QString &filename)
+{
+ instance()->m_fileName = filename;
+ if (instance()->m_file) {
+ instance()->m_file->close();
+ delete instance()->m_file;
+ }
+ instance()->m_file = new QFile(filename);
+ instance()->m_fileName = filename;
+ instance()->m_file->open(QIODevice::WriteOnly);
+}
+
+void QLogger::setEnabled(bool enabled)
+{
+ instance()->m_enabled = enabled;
+}
+
+void QLogger::setFlush(int msec)
+{
+ instance()->m_flushTime = msec;
+}
+
+void QLogger::flush()
+{
+ instance()->m_lastFlush = QTime::currentTime().elapsed();
+ if (instance()->m_file) {
+ foreach (QString s, instance()->m_buffer) {
+ s += QLatin1String("\n");
+ instance()->m_file->write (s.toAscii());
+ }
+ instance()->m_file->flush();
+ } else {
+ foreach ( QString s, instance()->m_buffer) {
+ s += QLatin1String("\n");
+#ifdef Q_OS_WIN
+ OutputDebugStringW((TCHAR*)s.utf16());
+#else
+ fprintf(stderr, "Debug: %s\n", s.toAscii().constData());
+#endif
+ }
+ }
+ instance()->m_buffer.clear();
+}
+
+QLogger::QLogger() : m_level(0), m_modul(), m_fileName(), m_file(0), m_enabled(true), m_silent(false), m_flushTime(1000)
+{
+ qInstallMsgHandler(loggerMessageOutput);
+ m_timer = new QTime();
+ m_timer->start();
+ m_lastFlush = m_timer->elapsed();
+}
+
+QLogger::~QLogger()
+{
+ flush();
+ if (m_file) {
+ m_file->close();
+ delete m_file;
+ }
+ delete m_timer;
+}
+
+QLogger* QLogger::instance()
+{
+ if (!m_instance) {
+ m_instance = new QLogger();
+ }
+ return m_instance;
+}
+
+void QLogger::output(const char *msg)
+{
+
+ QString s = QString::fromAscii(msg);
+ if (m_enabled && (m_modul.isEmpty() || s.contains(m_modul, Qt::CaseInsensitive))) {
+ int level = 0;
+ if (s.contains("LEVEL=1")) {
+ s = s.remove("LEVEL=1");
+ level = 1;
+ } else if (s.contains("LEVEL=2")) {
+ s = s.remove("LEVEL=2");
+ level = 2;
+ } else if (s.contains("LEVEL=3")) {
+ s = s.remove("LEVEL=3");
+ level = 3;
+ }
+ if (m_level >= level)
+ m_buffer.append(s);
+ }
+ int time = m_timer->elapsed();
+ if (time > m_lastFlush + m_flushTime)
+ flush();
+}
diff --git a/src/plugins/qmldesigner/components/logger/logger.h b/src/plugins/qmldesigner/components/logger/logger.h
new file mode 100644
index 0000000000..73f13cdb72
--- /dev/null
+++ b/src/plugins/qmldesigner/components/logger/logger.h
@@ -0,0 +1,81 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef QLOGGER_H
+#define QLOGGER_H
+
+#include <QString>
+#include <QStringList>
+
+
+#define qLogger(str) qDebug() << QString("GLOBAL %1, %2").arg(__FUNC__).arg(#str);
+#define qLogger(module, str) qDebug() << QString("%1, %2 %3").arg(__FUNC__).arg(#str).arg(#module);
+
+class QFile;
+class QTime;
+
+class QLogger {
+public:
+ static void enable() {
+ setEnabled(true);
+ }
+ static void disable() {
+ setEnabled(false);
+ }
+ static void setLevel(int level);
+ static void setModul(const QString &modul);
+ static void setFilename(const QString &filename);
+ static void setEnabled(bool enabled);
+ static void setFlush(int msec);
+ static void flush();
+ static void setSilent(bool silent);
+ ~QLogger();
+
+private:
+ QLogger();
+
+ static QLogger* instance();
+ static QLogger* m_instance;
+ void output(const char *msg);
+ static void loggerMessageOutput(QtMsgType type, const char *msg);
+
+ int m_level;
+ QString m_modul;
+ QString m_fileName;
+ QFile* m_file;
+ bool m_enabled;
+ bool m_silent;
+ int m_flushTime;
+ int m_lastFlush;
+ QStringList m_buffer;
+ QTime *m_timer;
+
+};
+
+#endif // QLOGGER_H
diff --git a/src/plugins/qmldesigner/components/logger/logger.pri b/src/plugins/qmldesigner/components/logger/logger.pri
new file mode 100644
index 0000000000..7e9c5355a3
--- /dev/null
+++ b/src/plugins/qmldesigner/components/logger/logger.pri
@@ -0,0 +1,6 @@
+VPATH += $$PWD
+INCLUDEPATH += $$PWD
+HEADERS += logger.h
+SOURCES += logger.cpp
+
+
diff --git a/src/plugins/qmldesigner/components/navigator/navigator.pri b/src/plugins/qmldesigner/components/navigator/navigator.pri
new file mode 100644
index 0000000000..e58d573acf
--- /dev/null
+++ b/src/plugins/qmldesigner/components/navigator/navigator.pri
@@ -0,0 +1,9 @@
+VPATH += $$PWD
+INCLUDEPATH += $$PWD
+SOURCES += navigatorview.cpp \
+ navigatortreemodel.cpp \
+ navigatorwidget.cpp
+
+HEADERS += navigatorview.h \
+ navigatortreemodel.h \
+ navigatorwidget.h
diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp
new file mode 100644
index 0000000000..ef9b860143
--- /dev/null
+++ b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp
@@ -0,0 +1,393 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "navigatortreemodel.h"
+
+#include <nodeabstractproperty.h>
+#include <nodelistproperty.h>
+#include <abstractview.h>
+#include <qmlitemnode.h>
+#include <invalididexception.h>
+
+#include <QMimeData>
+
+namespace QmlDesigner {
+
+NavigatorTreeModel::NavigatorTreeModel(QObject *parent)
+ : QStandardItemModel(parent)
+{
+ invisibleRootItem()->setFlags(Qt::NoItemFlags);
+
+ setHorizontalHeaderItem(0, new QStandardItem(tr("Name")));
+ setHorizontalHeaderItem(1, new QStandardItem(tr("Type")));
+ setHorizontalHeaderItem(2, new QStandardItem(tr("Show in Editor")));
+
+ setSupportedDragActions(Qt::MoveAction);
+
+ connect(this, SIGNAL(itemChanged(QStandardItem*)),
+ this, SLOT(handleChangedItem(QStandardItem*)));
+}
+
+NavigatorTreeModel::~NavigatorTreeModel()
+{
+}
+
+Qt::DropActions NavigatorTreeModel::supportedDropActions() const
+{
+ return Qt::MoveAction;
+}
+
+QStringList NavigatorTreeModel::mimeTypes() const
+{
+ QStringList types;
+ types << "application/vnd.modelnode.list";
+ return types;
+}
+
+QMimeData *NavigatorTreeModel::mimeData(const QModelIndexList &indexList) const
+{
+ QMimeData *mimeData = new QMimeData();
+ QByteArray encodedData;
+
+ QSet<QModelIndex> rowAlreadyUsedSet;
+
+ QDataStream stream(&encodedData, QIODevice::WriteOnly);
+
+ foreach (const QModelIndex &index, indexList) {
+ if (!index.isValid())
+ continue;
+ QModelIndex idIndex = index.sibling(index.row(), 0);
+ if (rowAlreadyUsedSet.contains(idIndex))
+ continue;
+
+ rowAlreadyUsedSet.insert(idIndex);
+ stream << idIndex.data(Qt::UserRole).toUInt();
+ }
+
+ mimeData->setData("application/vnd.modelnode.list", encodedData);
+
+ return mimeData;
+}
+
+static bool isAnchestorInList(const ModelNode &node, const QList<ModelNode> &nodeList)
+{
+ foreach (const ModelNode &nodeInList, nodeList) {
+ if (nodeInList.isAncestorOf(node))
+ return true;
+ }
+
+ return false;
+}
+
+bool NavigatorTreeModel::dropMimeData(const QMimeData *data,
+ Qt::DropAction action,
+ int row,
+ int column,
+ const QModelIndex &parentIndex)
+{
+ if (action == Qt::IgnoreAction)
+ return true;
+ if (action != Qt::MoveAction)
+ return false;
+ if (!data->hasFormat("application/vnd.modelnode.list"))
+ return false;
+ if (column > 1)
+ return false;
+ if (parentIndex.model() != this)
+ return false;
+
+ int beginRow = 0;
+
+ QModelIndex parentIdIndex = parentIndex;
+ parentIdIndex = parentIdIndex.sibling(parentIdIndex.row(), 0);
+
+ Q_ASSERT(parentIdIndex.isValid());
+
+ if (row > -1)
+ beginRow = row;
+ else if (parentIdIndex.isValid())
+ beginRow = rowCount(parentIdIndex);
+ else
+ beginRow = rowCount(QModelIndex());
+
+
+ QByteArray encodedData = data->data("application/vnd.modelnode.list");
+ QDataStream stream(&encodedData, QIODevice::ReadOnly);
+
+ uint nodeHash = parentIdIndex.data(Qt::UserRole).toUInt();
+ QmlItemNode parentItemNode(nodeForHash(nodeHash));
+
+ QList<ModelNode> nodeList;
+
+ while (!stream.atEnd()) {
+ uint nodeHash;
+ stream >> nodeHash;
+ ModelNode node(nodeForHash(nodeHash));
+ if (!node.isValid() || node.isAncestorOf(parentItemNode))
+ return false;
+ nodeList.append(node);
+ }
+
+ RewriterTransaction transaction = m_view->beginRewriterTransaction();
+ foreach (const ModelNode &node, nodeList) {
+ if (!isAnchestorInList(node, nodeList)) {
+ if (node.parentProperty().parentModelNode() != parentItemNode) {
+ QmlItemNode itemNode(node);
+ itemNode.setParent(parentItemNode);
+ }
+
+ if (node.parentProperty().isNodeListProperty()) {
+ int index = node.parentProperty().toNodeListProperty().toModelNodeList().indexOf(node);
+ node.parentProperty().toNodeListProperty().slide(index, beginRow);
+ }
+ }
+ }
+
+ return false; // don't let the view do drag&drop on its own
+}
+
+NavigatorTreeModel::ItemRow NavigatorTreeModel::createItemRow(const ModelNode &node)
+{
+ Q_ASSERT(node.isValid());
+
+ uint hash = qHash(node);
+
+ QStandardItem *idItem = new QStandardItem;
+ idItem->setDragEnabled(true);
+ idItem->setDropEnabled(node.metaInfo().isContainer());
+ idItem->setEditable(true);
+ idItem->setData(hash, Qt::UserRole);
+
+ QStandardItem *typeItem = new QStandardItem;
+ typeItem->setDragEnabled(true);
+ idItem->setDropEnabled(node.metaInfo().isContainer());
+ typeItem->setEditable(false);
+ typeItem->setData(hash, Qt::UserRole);
+
+ QStandardItem *visibilityItem = new QStandardItem;
+ visibilityItem->setDropEnabled(node.metaInfo().isContainer());
+ visibilityItem->setCheckable(true);
+ visibilityItem->setData(hash, Qt::UserRole);
+
+ return ItemRow(idItem, typeItem, visibilityItem);
+}
+
+void NavigatorTreeModel::updateItemRow(const ModelNode &node, ItemRow items)
+{
+ items.idItem->setText(node.id());
+ items.typeItem->setText(node.simplifiedTypeName());
+ items.visibilityItem->setCheckState(node.auxiliaryData("invisible").toBool() ? Qt::Unchecked : Qt::Checked);
+}
+
+/**
+ Update the information shown for a node / property
+ */
+void NavigatorTreeModel::updateItemRow(const ModelNode &node)
+{
+ if (!containsNode(node))
+ return;
+ updateItemRow(node, itemRowForNode(node));
+}
+
+/**
+ Updates the sibling position of the item, depending on the position in the model.
+ */
+void NavigatorTreeModel::updateItemRowOrder(const ModelNode &node)
+{
+ if (!containsNode(node))
+ return;
+ ItemRow itemRow = itemRowForNode(node);
+ int currentRow = itemRow.idItem->row();
+ int newRow = currentRow;
+ if (node.parentProperty().parentModelNode().isValid())
+ newRow = modelNodeChildren(node.parentProperty().parentModelNode()).indexOf(node);
+ Q_ASSERT(newRow >= 0);
+
+ if (currentRow != newRow) {
+ QStandardItem *parentIdItem = itemRow.idItem->parent();
+ QList<QStandardItem*> items = parentIdItem->takeRow(currentRow);
+ parentIdItem->insertRow(newRow, items);
+ }
+}
+
+void NavigatorTreeModel::handleChangedItem(QStandardItem *item)
+{
+ uint nodeHash = item->data(Qt::UserRole).toUInt();
+ Q_ASSERT(nodeHash && containsNodeHash(nodeHash));
+ ModelNode node = nodeForHash(nodeHash);
+
+ ItemRow itemRow = itemRowForNode(node);
+ if (item == itemRow.idItem) {
+ try {
+ if (ModelNode::isValidId(item->text()))
+ node.setId(item->text());
+ else
+ item->setText(node.id());
+ } catch (InvalidIdException &) {
+ item->setText(node.id());
+ }
+ } else if (item == itemRow.visibilityItem) {
+ bool invisible = (item->checkState() == Qt::Unchecked);
+
+ node.setAuxiliaryData("invisible", invisible);
+ }
+}
+
+ModelNode NavigatorTreeModel::nodeForHash(uint hash) const
+{
+ ModelNode node = m_nodeHash.value(hash);
+ Q_ASSERT(node.isValid());
+ return node;
+}
+
+bool NavigatorTreeModel::containsNodeHash(uint hash) const
+{
+ return m_nodeHash.contains(hash);
+}
+
+bool NavigatorTreeModel::containsNode(const ModelNode &node) const
+{
+ return m_nodeItemHash.contains(node);
+}
+
+NavigatorTreeModel::ItemRow NavigatorTreeModel::itemRowForNode(const ModelNode &node)
+{
+ Q_ASSERT(node.isValid());
+ return m_nodeItemHash.value(node);
+}
+
+void NavigatorTreeModel::setView(AbstractView *view)
+{
+ m_view = view;
+ addSubTree(view->rootModelNode());
+}
+
+void NavigatorTreeModel::clearView()
+{
+ m_view.clear();
+ m_nodeHash.clear();
+ m_nodeItemHash.clear();
+ clear();
+}
+
+QModelIndex NavigatorTreeModel::indexForNode(const ModelNode &node) const
+{
+ Q_ASSERT(node.isValid());
+ if (!containsNode(node))
+ return QModelIndex();
+ ItemRow row = m_nodeItemHash.value(node);
+ return row.idItem->index();
+}
+
+ModelNode NavigatorTreeModel::nodeForIndex(const QModelIndex &index) const
+{
+ Q_ASSERT(index.isValid());
+ uint hash = index.data(Qt::UserRole).toUInt();
+ Q_ASSERT(hash);
+ Q_ASSERT(containsNodeHash(hash));
+ return nodeForHash(hash);
+}
+
+bool NavigatorTreeModel::isInTree(const ModelNode &node) const
+{
+ return m_nodeHash.keys().contains(qHash(node));
+}
+
+/**
+ Adds node & all children to the visible tree hierarchy (if node should be visible at all).
+
+ It always adds the node to the _end_ of the list of items.
+ */
+void NavigatorTreeModel::addSubTree(const ModelNode &node)
+{
+ Q_ASSERT(node.isValid());
+ Q_ASSERT(!containsNodeHash(qHash(node)));
+
+ // only add items that are in the modelNodeChildren list (that means, visible in the editor)
+ if (!node.isRootNode()
+ && !modelNodeChildren(node.parentProperty().parentModelNode()).contains(node)) {
+ return;
+ }
+
+ ItemRow newRow = createItemRow(node);
+ m_nodeHash.insert(qHash(node), node);
+ m_nodeItemHash.insert(node, newRow);
+
+ updateItemRow(node, newRow);
+
+ foreach (const ModelNode &childNode, modelNodeChildren(node))
+ addSubTree(childNode);
+
+ // We assume that the node is always added to the _end_ of the property list.
+ if (node.hasParentProperty()) {
+ ItemRow parentRow = itemRowForNode(node.parentProperty().parentModelNode());
+ if (parentRow.idItem)
+ parentRow.idItem->appendRow(newRow.toList());
+ } else {
+ appendRow(newRow.toList());
+ }
+}
+
+/**
+ Deletes visual representation for the node (subtree).
+ */
+void NavigatorTreeModel::removeSubTree(const ModelNode &node)
+{
+ Q_ASSERT(node.isValid());
+
+ if (!containsNode(node))
+ return;
+
+ QList<QStandardItem*> rowList;
+ ItemRow itemRow = itemRowForNode(node);
+ if (itemRow.idItem->parent()) {
+ rowList = itemRow.idItem->parent()->takeRow(itemRow.idItem->row());
+ }
+
+ foreach (const ModelNode &node, modelNodeChildren(node)) {
+ removeSubTree(node);
+ }
+
+ qDeleteAll(rowList);
+
+ m_nodeHash.remove(qHash(node));
+ m_nodeItemHash.remove(node);
+}
+
+QList<ModelNode> NavigatorTreeModel::modelNodeChildren(const ModelNode &parentNode)
+{
+ QList<ModelNode> children;
+ if (QmlItemNode(parentNode).isValid())
+ foreach (const QmlItemNode &childNode, QmlItemNode(parentNode).children())
+ children << childNode.modelNode();
+ return children;
+}
+
+}
+
diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.h b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.h
new file mode 100644
index 0000000000..d4212ffd99
--- /dev/null
+++ b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.h
@@ -0,0 +1,115 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef NAVIGATORTREEMODEL_H
+#define NAVIGATORTREEMODEL_H
+
+#include <modelnode.h>
+#include <nodemetainfo.h>
+
+#include <QStandardItem>
+#include <QStandardItemModel>
+
+namespace QmlDesigner {
+
+class Model;
+class AbstractView;
+class ModelNode;
+
+class NavigatorTreeModel : public QStandardItemModel
+{
+ Q_OBJECT
+
+ struct ItemRow {
+ ItemRow()
+ : idItem(0), typeItem(0), visibilityItem(0) {}
+ ItemRow(QStandardItem *id, QStandardItem *type, QStandardItem *visibility)
+ : idItem(id), typeItem(type), visibilityItem(visibility) {}
+
+ QList<QStandardItem*> toList() const {
+ return QList<QStandardItem*>() << idItem << typeItem << visibilityItem;
+ }
+
+ QStandardItem *idItem;
+ QStandardItem *typeItem;
+ QStandardItem *visibilityItem;
+ };
+
+public:
+ NavigatorTreeModel(QObject *parent = 0);
+ ~NavigatorTreeModel();
+
+ Qt::DropActions supportedDropActions() const;
+
+ QStringList mimeTypes() const;
+ QMimeData *mimeData(const QModelIndexList &indexes) const;
+ bool dropMimeData(const QMimeData *data,
+ Qt::DropAction action,
+ int row,
+ int column,
+ const QModelIndex &parent);
+
+ void setView(AbstractView *view);
+ void clearView();
+
+ QModelIndex indexForNode(const ModelNode &node) const;
+ ModelNode nodeForIndex(const QModelIndex &index) const;
+
+ bool isInTree(const ModelNode &node) const;
+
+ void addSubTree(const ModelNode &node);
+ void removeSubTree(const ModelNode &node);
+ void updateItemRow(const ModelNode &node);
+ void updateItemRowOrder(const ModelNode &node);
+
+private slots:
+ void handleChangedItem(QStandardItem *item);
+
+private:
+ bool containsNodeHash(uint hash) const;
+ ModelNode nodeForHash(uint hash) const;
+
+ bool containsNode(const ModelNode &node) const;
+ ItemRow itemRowForNode(const ModelNode &node);
+
+ ItemRow createItemRow(const ModelNode &node);
+ void updateItemRow(const ModelNode &node, ItemRow row);
+
+ QList<ModelNode> modelNodeChildren(const ModelNode &parentNode);
+
+private:
+
+ QHash<ModelNode, ItemRow> m_nodeItemHash;
+ QHash<uint, ModelNode> m_nodeHash;
+ QWeakPointer<AbstractView> m_view;
+};
+
+} // namespace QmlDesigner
+
+#endif // NAVIGATORTREEMODEL_H
diff --git a/src/plugins/qmldesigner/components/navigator/navigatorview.cpp b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp
new file mode 100644
index 0000000000..9e9c4661b0
--- /dev/null
+++ b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp
@@ -0,0 +1,227 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "navigatorview.h"
+#include "navigatortreemodel.h"
+#include "navigatorwidget.h"
+
+#include <nodeproperty.h>
+
+
+namespace QmlDesigner {
+
+NavigatorView::NavigatorView(QObject* parent) :
+ QmlModelView(parent),
+ m_blockSelectionChangedSignal(false),
+ m_widget(new NavigatorWidget),
+ m_treeModel(new NavigatorTreeModel(this))
+{
+ m_widget->setTreeModel(m_treeModel.data());
+
+ connect(treeWidget()->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(changeSelection(QItemSelection,QItemSelection)));
+ treeWidget()->setIndentation(treeWidget()->indentation() * 0.5);
+}
+
+NavigatorView::~NavigatorView()
+{
+ if (m_widget && !m_widget->parent())
+ delete m_widget.data();
+}
+
+QWidget *NavigatorView::widget()
+{
+ return m_widget.data();
+}
+
+void NavigatorView::modelAttached(Model *model)
+{
+ QmlModelView::modelAttached(model);
+
+ m_treeModel->setView(this);
+
+ treeWidget()->expandAll();
+}
+
+void NavigatorView::modelAboutToBeDetached(Model *model)
+{
+ m_treeModel->clearView();
+ QmlModelView::modelAboutToBeDetached(model);
+}
+
+void NavigatorView::nodeAboutToBeRemoved(const ModelNode &removedNode)
+{
+ if (m_treeModel->isInTree(removedNode))
+ m_treeModel->removeSubTree(removedNode);
+ QmlModelView::nodeAboutToBeRemoved(removedNode);
+}
+
+void NavigatorView::nodeReparented(const ModelNode &node, const NodeAbstractProperty & /*newPropertyParent*/, const NodeAbstractProperty & /*oldPropertyParent*/, AbstractView::PropertyChangeFlags /*propertyChange*/)
+{
+ bool blocked = blockSelectionChangedSignal(true);
+
+ if (m_treeModel->isInTree(node))
+ m_treeModel->removeSubTree(node);
+ if (node.isInHierarchy())
+ m_treeModel->addSubTree(node);
+
+ // make sure selection is in sync again
+ updateItemSelection();
+
+ blockSelectionChangedSignal(blocked);
+}
+
+void NavigatorView::nodeIdChanged(const ModelNode& node, const QString& newId, const QString& oldId)
+{
+ QmlModelView::nodeIdChanged(node, newId, oldId);
+ if (m_treeModel->isInTree(node))
+ m_treeModel->updateItemRow(node);
+}
+
+void NavigatorView::propertiesAboutToBeRemoved(const QList<AbstractProperty>& propertyList)
+{
+ QmlModelView::propertiesAboutToBeRemoved(propertyList);
+ foreach (const AbstractProperty &property, propertyList) {
+ if (property.isNodeProperty()) {
+ NodeProperty nodeProperty(property.toNodeProperty());
+ m_treeModel->removeSubTree(nodeProperty.modelNode());
+ } else if (property.isNodeListProperty()) {
+ NodeListProperty nodeListProperty(property.toNodeListProperty());
+ foreach (const ModelNode &node, nodeListProperty.toModelNodeList()) {
+ m_treeModel->removeSubTree(node);
+ }
+ }
+ }
+}
+
+void NavigatorView::nodeTypeChanged(const ModelNode &node,const QString &type, int majorVersion, int minorVersion)
+{
+ QmlModelView::nodeTypeChanged(node, type, majorVersion, minorVersion);
+ if (m_treeModel->isInTree(node))
+ m_treeModel->updateItemRow(node);
+}
+
+void NavigatorView::auxiliaryDataChanged(const ModelNode &node, const QString &name, const QVariant &data)
+{
+ QmlModelView::auxiliaryDataChanged(node, name, data);
+ if (m_treeModel->isInTree(node))
+ m_treeModel->updateItemRow(node);
+}
+
+void NavigatorView::nodeSlidedToIndex(const NodeListProperty &listProperty, int newIndex, int oldIndex)
+{
+ QmlModelView::nodeSlidedToIndex(listProperty, newIndex, oldIndex);
+
+ int nodeIndex = newIndex;
+ if (oldIndex < newIndex)
+ --nodeIndex;
+ ModelNode node = listProperty.toModelNodeList().at(nodeIndex);
+ if (m_treeModel->isInTree(node))
+ m_treeModel->updateItemRowOrder(node);
+}
+
+void NavigatorView::stateChanged(const QmlModelState &/*newQmlModelState*/, const QmlModelState &/*oldQmlModelState*/)
+{
+}
+
+void NavigatorView::changeSelection(const QItemSelection & /*newSelection*/, const QItemSelection &/*deselected*/)
+{
+ if (m_blockSelectionChangedSignal)
+ return;
+ QSet<ModelNode> nodeSet;
+ foreach (const QModelIndex &index, treeWidget()->selectionModel()->selectedIndexes()) {
+ nodeSet.insert(m_treeModel->nodeForIndex(index));
+ }
+
+ bool blocked = blockSelectionChangedSignal(true);
+ setSelectedModelNodes(nodeSet.toList());
+ blockSelectionChangedSignal(blocked);
+}
+
+void NavigatorView::selectedNodesChanged(const QList<ModelNode> &selectedNodeList, const QList<ModelNode> &lastSelectedNodeList)
+{
+ QmlModelView::selectedNodesChanged(selectedNodeList, lastSelectedNodeList);
+
+ updateItemSelection();
+}
+
+void NavigatorView::updateItemSelection()
+{
+ QItemSelection itemSelection;
+ foreach (const ModelNode &node, selectedModelNodes()) {
+ const QModelIndex index = m_treeModel->indexForNode(node);
+ if (index.isValid()) {
+ const QModelIndex beginIndex(m_treeModel->index(index.row(), 0, index.parent()));
+ const QModelIndex endIndex(m_treeModel->index(index.row(), m_treeModel->columnCount(index.parent()) - 1, index.parent()));
+ if (beginIndex.isValid() && endIndex.isValid())
+ itemSelection.select(beginIndex, endIndex);
+ }
+ }
+
+ bool blocked = blockSelectionChangedSignal(true);
+ treeWidget()->selectionModel()->select(itemSelection, QItemSelectionModel::ClearAndSelect);
+ blockSelectionChangedSignal(blocked);
+
+ // make sure selected nodes a visible
+ foreach(const QModelIndex &selectedIndex, itemSelection.indexes()) {
+ if (selectedIndex.column() == 0)
+ expandRecursively(selectedIndex);
+ }
+}
+
+QTreeView *NavigatorView::treeWidget()
+{
+ if (m_widget)
+ return m_widget->treeView();
+ return 0;
+}
+
+NavigatorTreeModel *NavigatorView::treeModel()
+{
+ return m_treeModel.data();
+}
+
+// along the lines of QObject::blockSignals
+bool NavigatorView::blockSelectionChangedSignal(bool block)
+{
+ bool oldValue = m_blockSelectionChangedSignal;
+ m_blockSelectionChangedSignal = block;
+ return oldValue;
+}
+
+void NavigatorView::expandRecursively(const QModelIndex &index)
+{
+ QModelIndex currentIndex = index;
+ while (currentIndex.isValid()) {
+ if (!treeWidget()->isExpanded(currentIndex))
+ treeWidget()->expand(currentIndex);
+ currentIndex = currentIndex.parent();
+ }
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/navigator/navigatorview.h b/src/plugins/qmldesigner/components/navigator/navigatorview.h
new file mode 100644
index 0000000000..c8545f802f
--- /dev/null
+++ b/src/plugins/qmldesigner/components/navigator/navigatorview.h
@@ -0,0 +1,98 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef NAVIGATORVIEW_H
+#define NAVIGATORVIEW_H
+
+#include <qmlmodelview.h>
+
+#include <QWeakPointer>
+
+class QTreeView;
+class QStandardItem;
+class QItemSelection;
+class QModelIndex;
+
+namespace QmlDesigner {
+
+class NavigatorWidget;
+class NavigatorTreeModel;
+
+class NavigatorView : public QmlModelView
+{
+ Q_OBJECT
+
+public:
+ NavigatorView(QObject* parent = 0);
+ ~NavigatorView();
+
+ QWidget *widget();
+
+ // AbstractView
+ void modelAttached(Model *model);
+ void modelAboutToBeDetached(Model *model);
+
+ void nodeAboutToBeRemoved(const ModelNode &removedNode);
+ void nodeReparented(const ModelNode &node, const ModelNode &oldParent, const ModelNode &newParent);
+
+ void nodeSlidedToIndex(const ModelNode &node, int newIndex, int oldIndex);
+ void nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange);
+ void nodeTypeChanged(const ModelNode &node,const QString &type, int majorVersion, int minorVersion);
+ void nodeIdChanged(const ModelNode& node, const QString& newId, const QString& oldId);
+ void propertiesAboutToBeRemoved(const QList<AbstractProperty>& propertyList);
+
+ void selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
+ const QList<ModelNode> &lastSelectedNodeList);
+ void auxiliaryDataChanged(const ModelNode &node, const QString &name, const QVariant &data);
+ void nodeSlidedToIndex(const NodeListProperty &listProperty, int newIndex, int oldIndex);
+
+ void stateChanged(const QmlModelState &newQmlModelState, const QmlModelState &oldQmlModelState);
+
+private slots:
+// void handleChangedItem(QStandardItem * item);
+ void changeSelection(const QItemSelection &selected, const QItemSelection &deselected);
+ void updateItemSelection();
+
+protected: //functions
+ QTreeView *treeWidget();
+ NavigatorTreeModel *treeModel();
+ bool blockSelectionChangedSignal(bool block);
+ void expandRecursively(const QModelIndex &index);
+
+private:
+ bool m_blockSelectionChangedSignal;
+
+ QWeakPointer<NavigatorWidget> m_widget;
+ QWeakPointer<NavigatorTreeModel> m_treeModel;
+
+ friend class TestNavigator;
+};
+
+}
+#endif // NAVIGATORVIEW_H
diff --git a/src/plugins/qmldesigner/components/navigator/navigatorwidget.cpp b/src/plugins/qmldesigner/components/navigator/navigatorwidget.cpp
new file mode 100644
index 0000000000..36a0838649
--- /dev/null
+++ b/src/plugins/qmldesigner/components/navigator/navigatorwidget.cpp
@@ -0,0 +1,88 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <QtGui/QBoxLayout>
+#include <QtGui/QTreeView>
+#include <QtGui/QHeaderView>
+#include <QFile>
+#include <model.h>
+
+#include "navigatorwidget.h"
+
+
+namespace QmlDesigner {
+
+NavigatorWidget::NavigatorWidget(QWidget* parent) :
+ QFrame(parent),
+ m_treeView(new QTreeView)
+{
+ m_treeView->setDragEnabled(true);
+ m_treeView->setAcceptDrops(true);
+ m_treeView->setSelectionMode(QAbstractItemView::ExtendedSelection);
+ m_treeView->header()->setStretchLastSection(false);
+
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->setSpacing(0);
+ layout->setMargin(0);
+ layout->addWidget(m_treeView);
+
+ setLayout(layout);
+
+ setWindowTitle(tr("Navigator", "Title of navigator view"));
+
+ {
+ QFile file(":/qmldesigner/stylesheet.css");
+ file.open(QFile::ReadOnly);
+ setStyleSheet(file.readAll());
+ }
+
+ {
+ QFile file(":/qmldesigner/scrollbar.css");
+ file.open(QFile::ReadOnly);
+ m_treeView->setStyleSheet(file.readAll());
+ }
+}
+
+NavigatorWidget::~NavigatorWidget()
+{
+
+}
+
+void NavigatorWidget::setTreeModel(QAbstractItemModel* model)
+{
+ m_treeView->setModel(model);
+ m_treeView->header()->setResizeMode(0, QHeaderView::Stretch);
+}
+
+QTreeView *NavigatorWidget::treeView()
+{
+ return m_treeView;
+}
+
+}
diff --git a/src/plugins/qmldesigner/components/navigator/navigatorwidget.h b/src/plugins/qmldesigner/components/navigator/navigatorwidget.h
new file mode 100644
index 0000000000..04207027b4
--- /dev/null
+++ b/src/plugins/qmldesigner/components/navigator/navigatorwidget.h
@@ -0,0 +1,56 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef NAVIGATORWIDGET_H
+#define NAVIGATORWIDGET_H
+
+#include <QFrame>
+#include <QAbstractItemModel>
+#include <QTreeView>
+
+namespace QmlDesigner {
+
+class Model;
+
+class NavigatorWidget: public QFrame
+{
+public:
+ NavigatorWidget(QWidget* parent = 0);
+ virtual ~NavigatorWidget();
+
+ void setTreeModel(QAbstractItemModel *model);
+ QTreeView *treeView();
+
+private:
+ QTreeView *m_treeView;
+};
+
+}
+
+#endif // NAVIGATORWIDGET_H
diff --git a/src/plugins/qmldesigner/components/pluginmanager/iplugin.cpp b/src/plugins/qmldesigner/components/pluginmanager/iplugin.cpp
new file mode 100644
index 0000000000..70250f0984
--- /dev/null
+++ b/src/plugins/qmldesigner/components/pluginmanager/iplugin.cpp
@@ -0,0 +1,36 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "iplugin.h"
+
+// Put docs in here
+namespace QmlDesigner {
+
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/pluginmanager/iplugin.h b/src/plugins/qmldesigner/components/pluginmanager/iplugin.h
new file mode 100644
index 0000000000..4c2dd45315
--- /dev/null
+++ b/src/plugins/qmldesigner/components/pluginmanager/iplugin.h
@@ -0,0 +1,56 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef IPLUGIN_H
+#define IPLUGIN_H
+
+#include <QtCore/QObject>
+
+#define QMLDESIGNER_PLUGIN_INTERFACE "com.Nokia.QmlDesigner.IPlugin.v10"
+
+namespace QmlDesigner {
+
+// QmlDesigner "base" plugin with initialization method in which
+// it can retriece the core via its static accessor and do magic.
+
+class IPlugin
+{
+public:
+ virtual ~IPlugin() {}
+
+ virtual bool isInitialized() const = 0;
+
+ virtual bool initialize(QString *errorMessage) = 0;
+};
+
+} // namespace QmlDesigner
+
+Q_DECLARE_INTERFACE(QmlDesigner::IPlugin, QMLDESIGNER_PLUGIN_INTERFACE)
+
+#endif // IPLUGIN_H
diff --git a/src/plugins/qmldesigner/components/pluginmanager/pluginmanager.cpp b/src/plugins/qmldesigner/components/pluginmanager/pluginmanager.cpp
new file mode 100644
index 0000000000..1bff0ac3de
--- /dev/null
+++ b/src/plugins/qmldesigner/components/pluginmanager/pluginmanager.cpp
@@ -0,0 +1,174 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "pluginmanager.h"
+#include "iplugin.h"
+#include "pluginpath.h"
+#include <metainfo.h>
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QObject>
+#include <QtCore/QSharedData>
+#include <QtCore/QDir>
+#include <QtCore/QStringList>
+#include <QtCore/QDebug>
+#include <QWeakPointer>
+#include <QtCore/QPluginLoader>
+#include <QtCore/QFileInfo>
+#include <QtCore/QLibraryInfo>
+
+#include <QtGui/QStandardItemModel>
+#include <QtGui/QStandardItem>
+#include <QtGui/QTreeView>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QDialog>
+#include <QtGui/QLabel>
+#include <QtGui/QDialogButtonBox>
+
+enum { debug = 0 };
+
+namespace QmlDesigner {
+
+// Initialize and create instance of a plugin from scratch,
+// that is, make sure the library is loaded and has an instance
+// of the IPlugin type. Once something fails, mark it as failed
+// ignore it from then on.
+//static IPlugin *instance(PluginData &p)
+//{
+// // Go stale once something fails
+// if (p.failed)
+// return 0;
+// // Pull up the plugin, retrieve IPlugin instance.
+// if (!p.instanceGuard) {
+// p.instance = 0;
+// QPluginLoader loader(p.path);
+// if (!(loader.isLoaded() || loader.load())) {
+// p.failed = true;
+// p.errorMessage = loader.errorString();
+// return 0;
+// }
+// QObject *object = loader.instance();
+// if (!object) {
+// p.failed = true;
+// p.errorMessage = QCoreApplication::translate("PluginManager", "Failed to create instance.");
+// return 0;
+// }
+// IPlugin *iplugin = qobject_cast<IPlugin *>(object);
+// if (!iplugin) {
+// p.failed = true;
+// p.errorMessage = QCoreApplication::translate("PluginManager", "Not a QmlDesigner plugin.");
+// delete object;
+// return 0;
+// }
+// p.instanceGuard = object;
+// p.instance = iplugin;
+// }
+// // Ensure it is initialized
+// if (!p.instance->isInitialized()) {
+// if (!p.instance->initialize(&p.errorMessage)) {
+// p.failed = true;
+// delete p.instance;
+// p.instance = 0;
+// return 0;
+// }
+// }
+// return p.instance;
+//}
+
+
+// ---- PluginManager[Private]
+class PluginManagerPrivate {
+public:
+ typedef QList<PluginPath> PluginPathList;
+ PluginPathList m_paths;
+};
+
+PluginManager::PluginManager() :
+ m_d(new PluginManagerPrivate)
+{
+}
+
+PluginManager::~PluginManager()
+{
+ delete m_d;
+}
+
+PluginManager::IPluginList PluginManager::instances()
+{
+ if (debug)
+ qDebug() << '>' << Q_FUNC_INFO << QLibraryInfo::buildKey();
+ IPluginList rc;
+ const PluginManagerPrivate::PluginPathList::iterator end = m_d->m_paths.end();
+ for (PluginManagerPrivate::PluginPathList::iterator it = m_d->m_paths.begin(); it != end; ++it)
+ it->getInstances(&rc);
+ if (debug)
+ qDebug() << '<' << Q_FUNC_INFO << rc.size();
+ return rc;
+}
+
+void PluginManager::setPluginPaths(const QStringList &paths)
+{
+ foreach (const QString &path, paths) {
+ const QDir dir(path);
+ if (!dir.exists())
+ continue;
+ m_d->m_paths.push_back(PluginPath(dir));
+ }
+
+ // also register path in widgetpluginmanager
+ MetaInfo::setPluginPaths(paths);
+}
+
+QAbstractItemModel *PluginManager::createModel(QObject *parent)
+{
+ QStandardItemModel *model = new QStandardItemModel(parent);
+ const PluginManagerPrivate::PluginPathList::iterator end = m_d->m_paths.end();
+ for (PluginManagerPrivate::PluginPathList::iterator it = m_d->m_paths.begin(); it != end; ++it)
+ model->appendRow(it->createModelItem());
+ return model;
+}
+
+QDialog *PluginManager::createAboutPluginDialog(QWidget *parent)
+{
+ QDialog *rc = new QDialog(parent);
+ rc->setWindowFlags(rc->windowFlags() & ~Qt::WindowContextHelpButtonHint & Qt::Sheet);
+ rc->setWindowTitle(QCoreApplication::tr("About plugins"));
+ QTreeView *treeView = new QTreeView;
+ treeView->setModel(createModel(treeView));
+ treeView->expandAll();
+
+ QVBoxLayout *layout = new QVBoxLayout(rc);
+ layout->addWidget(treeView);
+ QDialogButtonBox *bb = new QDialogButtonBox(QDialogButtonBox::Close);
+ layout->addWidget(bb);
+ QObject::connect(bb, SIGNAL(rejected()), rc, SLOT(reject()));
+ return rc;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/pluginmanager/pluginmanager.h b/src/plugins/qmldesigner/components/pluginmanager/pluginmanager.h
new file mode 100644
index 0000000000..62afc2c5a5
--- /dev/null
+++ b/src/plugins/qmldesigner/components/pluginmanager/pluginmanager.h
@@ -0,0 +1,75 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef PLUGINMANAGER_H
+#define PLUGINMANAGER_H
+
+
+#include <QtCore/QObject>
+#include <QtCore/QList>
+
+class QString;
+class QAbstractItemModel;
+class QDialog;
+
+namespace QmlDesigner {
+
+class IPlugin;
+
+class PluginManagerPrivate;
+
+// PluginManager: Loads the plugin libraries on demand "as lazy as
+// possible", that is, directories are scanned and
+// instances are created only when instances() is called.
+
+class PluginManager
+{
+ Q_DISABLE_COPY(PluginManager)
+public:
+ typedef QList<IPlugin *> IPluginList;
+
+ PluginManager();
+ ~PluginManager();
+
+ void setPluginPaths(const QStringList &paths);
+
+ IPluginList instances();
+
+ QDialog *createAboutPluginDialog(QWidget *parent);
+
+private:
+ // Convenience to create a model for an "About Plugins"
+ // dialog. Forces plugin initialization.
+ QAbstractItemModel *createModel(QObject *parent = 0);
+
+ PluginManagerPrivate *m_d;
+};
+
+} // namespace QmlDesigner
+#endif // PLUGINMANAGER_H
diff --git a/src/plugins/qmldesigner/components/pluginmanager/pluginmanager.pri b/src/plugins/qmldesigner/components/pluginmanager/pluginmanager.pri
new file mode 100644
index 0000000000..3160b88feb
--- /dev/null
+++ b/src/plugins/qmldesigner/components/pluginmanager/pluginmanager.pri
@@ -0,0 +1,10 @@
+VPATH += $$PWD
+INCLUDEPATH += $$PWD
+
+SOURCES += pluginmanager.cpp \
+ pluginpath.cpp \
+ iplugin.cpp
+
+HEADERS += pluginmanager.h \
+ pluginpath.h \
+ iplugin.h
diff --git a/src/plugins/qmldesigner/components/pluginmanager/pluginpath.cpp b/src/plugins/qmldesigner/components/pluginmanager/pluginpath.cpp
new file mode 100644
index 0000000000..ee069bfae5
--- /dev/null
+++ b/src/plugins/qmldesigner/components/pluginmanager/pluginpath.cpp
@@ -0,0 +1,193 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "pluginpath.h"
+#include <iplugin.h>
+#include <QtCore/QLibrary>
+#include <QWeakPointer>
+#include <QtCore/QPluginLoader>
+#include <QtCore/QFileInfo>
+#include <QtCore/QLibraryInfo>
+#include <QtCore/QCoreApplication>
+#include <QtCore/QObject>
+#include <QtCore/QSharedData>
+#include <QDebug>
+
+enum { debug = 1 };
+
+namespace QmlDesigner {
+
+// Initialize and create instance of a plugin from scratch,
+// that is, make sure the library is loaded and has an instance
+// of the IPlugin type. Once something fails, mark it as failed
+// ignore it from then on.
+static IPlugin *instance(PluginData &p)
+{
+ // Go stale once something fails
+ if (p.failed)
+ return 0;
+ // Pull up the plugin, retrieve IPlugin instance.
+ if (!p.instanceGuard) {
+ p.instance = 0;
+ QPluginLoader loader(p.path);
+ if (!(loader.isLoaded() || loader.load())) {
+ p.failed = true;
+ p.errorMessage = loader.errorString();
+ return 0;
+ }
+ QObject *object = loader.instance();
+ if (!object) {
+ p.failed = true;
+ p.errorMessage = QCoreApplication::translate("WidgetPluginManager", "Failed to create instance.");
+ return 0;
+ }
+ IPlugin *iplugin = qobject_cast<IPlugin *>(object);
+ if (!iplugin) {
+ p.failed = true;
+ p.errorMessage = QCoreApplication::translate("WidgetPluginManager", "Not a QmlDesigner plugin.");
+ delete object;
+ return 0;
+ }
+ p.instanceGuard = object;
+ p.instance = iplugin;
+ }
+ // Ensure it is initialized
+ /*if (!p.instance->isInitialized()) {
+ if (!p.instance->initialize(&p.errorMessage)) {
+ p.failed = true;
+ delete p.instance;
+ p.instance = 0;
+ return 0;
+ }
+ }*/
+ return p.instance;
+}
+
+PluginData::PluginData(const QString &p) :
+ path(p),
+ failed(false),
+ instance(0)
+{
+}
+
+
+PluginPath::PluginPath(const QDir &path) :
+ m_path(path),
+ m_loaded(false)
+{
+}
+
+// Determine a unique list of library files in that directory
+QStringList PluginPath::libraryFilePaths(const QDir &dir)
+{
+ const QFileInfoList infoList = dir.entryInfoList(QDir::Files|QDir::Readable|QDir::NoDotAndDotDot);
+ if (infoList.empty())
+ return QStringList();
+ // Load symbolic links but make sure all file names are unique as not
+ // to fall for something like 'libplugin.so.1 -> libplugin.so'
+ QStringList result;
+ const QFileInfoList::const_iterator icend = infoList.constEnd();
+ for (QFileInfoList::const_iterator it = infoList.constBegin(); it != icend; ++it) {
+ QString fileName;
+ if (it->isSymLink()) {
+ const QFileInfo linkTarget = QFileInfo(it->symLinkTarget());
+ if (linkTarget.exists() && linkTarget.isFile())
+ fileName = linkTarget.absoluteFilePath();
+ } else {
+ fileName = it->absoluteFilePath();
+ }
+ if (!fileName.isEmpty() && QLibrary::isLibrary(fileName) && !result.contains(fileName))
+ result += fileName;
+ }
+
+ qDebug() << "Library file paths: " << result;
+
+ return result;
+}
+
+void PluginPath::clear()
+{
+ m_loaded = false;
+ m_plugins.clear();
+}
+
+void PluginPath::ensureLoaded()
+{
+ if (!m_loaded) {
+ const QStringList libraryFiles = libraryFilePaths(m_path);
+ if (debug)
+ qDebug() << "Checking " << libraryFiles.size() << " plugins " << m_path.absolutePath();
+ foreach (const QString &libFile, libraryFiles)
+ m_plugins.push_back(PluginData(libFile));
+ m_loaded = true;
+ }
+}
+
+void PluginPath::getInstances(PluginManager::IPluginList *list)
+{
+ ensureLoaded();
+ // Compile list of instances
+ if (m_plugins.empty())
+ return;
+ const PluginDataList::iterator end = m_plugins.end();
+ for (PluginDataList::iterator it = m_plugins.begin(); it != end; ++it)
+ if (IPlugin *i = instance(*it))
+ list->push_back(i);
+}
+
+QStandardItem *PluginPath::createModelItem()
+{
+ ensureLoaded();
+ // Create a list of plugin lib files with classes.
+ // If there are failed ones, create a separate "Failed"
+ // category at the end
+ QStandardItem *pathItem = new QStandardItem(m_path.absolutePath());
+ QStandardItem *failedCategory = 0;
+ const PluginDataList::iterator end = m_plugins.end();
+ for (PluginDataList::iterator it = m_plugins.begin(); it != end; ++it) {
+ QStandardItem *pluginItem = new QStandardItem(QFileInfo(it->path).fileName());
+ if (instance(*it)) {
+ pluginItem->appendRow(new QStandardItem(QString::fromLatin1(it->instanceGuard->metaObject()->className())));
+ pathItem->appendRow(pluginItem);
+ } else {
+ pluginItem->setToolTip(it->errorMessage);
+ if (!failedCategory) {
+ const QString failed = QCoreApplication::translate("PluginManager", "Failed Plugins");
+ failedCategory = new QStandardItem(failed);
+ }
+ failedCategory->appendRow(pluginItem);
+ }
+ }
+ if (failedCategory)
+ pathItem->appendRow(failedCategory);
+ return pathItem;
+}
+
+} // namespace QmlDesigner
+
diff --git a/src/plugins/qmldesigner/components/pluginmanager/pluginpath.h b/src/plugins/qmldesigner/components/pluginmanager/pluginpath.h
new file mode 100644
index 0000000000..226183d7d8
--- /dev/null
+++ b/src/plugins/qmldesigner/components/pluginmanager/pluginpath.h
@@ -0,0 +1,98 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef PLUGINPATH_H
+#define PLUGINPATH_H
+
+#include "pluginmanager.h"
+
+#include <QtCore/QObject>
+#include <QWeakPointer>
+#include <QtCore/QList>
+#include <QtCore/QDir>
+#include <QtGui/QStandardItem>
+
+QT_BEGIN_NAMESPACE
+class QString;
+class QAbstractItemModel;
+QT_END_NAMESPACE
+
+namespace QmlDesigner {
+
+class IPlugin;
+
+// Dumb plugin data structure. Note that whereas QObjects can
+// casted to an interface, QPointer does not work with the
+// interface class, so, we need a separate QPointer as a guard
+// to detect the deletion of a plugin instance which can happen
+// in theory.
+struct PluginData {
+ PluginData(const QString &p = QString());
+
+ QString path;
+ bool failed;
+ QString errorMessage;
+ QWeakPointer<QObject> instanceGuard;
+ IPlugin *instance;
+};
+
+
+// PluginPath: Manages a plugin directory. It does nothing
+// on construction following the "as lazy as possible" principle.
+// In the "loaded" stage, it scans the directories and creates
+// a list of PluginData for the libraries found.
+// getInstances() will return the fully initialized list of
+// IPlugins.
+
+class PluginPath {
+public:
+ explicit PluginPath(const QDir &path);
+
+
+ void getInstances(PluginManager::IPluginList *list);
+
+ QDir path() const { return m_path; }
+
+ // Convenience to populate a "About Plugin" dialog with
+ // plugins from that path. Forces initialization.
+ QStandardItem *createModelItem();
+
+private:
+ typedef QList<PluginData> PluginDataList;
+
+ static QStringList libraryFilePaths(const QDir &dir);
+ void clear();
+ void ensureLoaded();
+
+ QDir m_path;
+ bool m_loaded;
+ PluginDataList m_plugins;
+};
+} // namespace QmlDesigner
+#endif // PLUGINPATH_H
diff --git a/src/plugins/qmldesigner/components/propertyeditor/allpropertiesbox.cpp b/src/plugins/qmldesigner/components/propertyeditor/allpropertiesbox.cpp
new file mode 100644
index 0000000000..effc8539f8
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/allpropertiesbox.cpp
@@ -0,0 +1,85 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <QtGui/QBoxLayout>
+
+#include <model.h>
+
+#include "application.h"
+#include "allpropertiesbox.h"
+#include "propertyeditor.h"
+
+namespace QmlDesigner {
+
+class AllPropertiesBoxPrivate
+{
+ friend class AllPropertiesBox;
+
+private:
+ PropertyEditor* propertiesEditor;
+};
+
+AllPropertiesBox::AllPropertiesBox(QWidget* parent):
+ QStackedWidget(parent),
+ m_d(new AllPropertiesBoxPrivate)
+{
+ m_d->propertiesEditor = new PropertyEditor(this);
+ m_d->propertiesEditor->setQmlDir(Application::sharedDirPath() + QLatin1String("/propertyeditor"));
+
+ m_newLookIndex = addWidget(m_d->propertiesEditor->createPropertiesPage());
+
+ setCurrentIndex(m_newLookIndex);
+
+ setWindowTitle(tr("Properties", "Title of properties view."));
+}
+
+AllPropertiesBox::~AllPropertiesBox()
+{
+ delete m_d;
+}
+
+void AllPropertiesBox::setModel(Model* model)
+{
+ if (model)
+ model->attachView(m_d->propertiesEditor);
+ else if (m_d->propertiesEditor->model())
+ m_d->propertiesEditor->model()->detachView(m_d->propertiesEditor);
+}
+
+void AllPropertiesBox::showNewLook()
+{
+ setCurrentIndex(m_newLookIndex);
+}
+
+void AllPropertiesBox::showTraditional()
+{
+ setCurrentIndex(m_traditionalIndex);
+}
+
+}
diff --git a/src/plugins/qmldesigner/components/propertyeditor/allpropertiesbox.h b/src/plugins/qmldesigner/components/propertyeditor/allpropertiesbox.h
new file mode 100644
index 0000000000..ab88c3b6c9
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/allpropertiesbox.h
@@ -0,0 +1,64 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef allpropertiesbox_h
+#define allpropertiesbox_h
+
+#include <QtGui/QStackedWidget>
+
+namespace QmlDesigner {
+
+class FormWindow;
+class Model;
+class ModelState;
+
+class AllPropertiesBox: public QStackedWidget
+{
+ Q_OBJECT
+
+public:
+ AllPropertiesBox(QWidget* parent = 0);
+ virtual ~AllPropertiesBox();
+
+ void showNewLook();
+ void showTraditional();
+
+ void setModel(Model *model);
+
+private:
+
+private:
+ class AllPropertiesBoxPrivate* m_d;
+ int m_newLookIndex;
+ int m_traditionalIndex;
+};
+
+}
+
+#endif // allpropertiesbox_h
diff --git a/src/plugins/qmldesigner/components/propertyeditor/basiclayouts.cpp b/src/plugins/qmldesigner/components/propertyeditor/basiclayouts.cpp
new file mode 100644
index 0000000000..fe082751ed
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/basiclayouts.cpp
@@ -0,0 +1,83 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+/****************************************************************************
+**
+** 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 "basiclayouts.h"
+
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(Qt,4,6,QBoxLayout,QBoxLayoutObject);
+
+QBoxLayoutObject::QBoxLayoutObject(QObject *parent)
+: QLayoutObject(parent), _widgets(this), _layout(0)
+{
+}
+
+QBoxLayoutObject::QBoxLayoutObject(QBoxLayout *layout, QObject *parent)
+: QLayoutObject(parent), _widgets(this), _layout(layout)
+{
+}
+
+QLayout *QBoxLayoutObject::layout() const
+{
+ return _layout;
+}
+
+void QBoxLayoutObject::addWidget(QWidget *wid)
+{
+ _layout->addWidget(wid);
+}
+
+void QBoxLayoutObject::clearWidget()
+{
+}
+
+QML_DEFINE_TYPE(Qt,4,6,QHBoxLayout,QHBoxLayoutObject);
+QHBoxLayoutObject::QHBoxLayoutObject(QObject *parent)
+: QBoxLayoutObject(new QHBoxLayout, parent)
+{
+}
+
+
+QML_DEFINE_TYPE(Qt,4,6,QVBoxLayout,QVBoxLayoutObject);
+QVBoxLayoutObject::QVBoxLayoutObject(QObject *parent)
+: QBoxLayoutObject(new QVBoxLayout, parent)
+{
+}
+QT_END_NAMESPACE
diff --git a/src/plugins/qmldesigner/components/propertyeditor/basiclayouts.h b/src/plugins/qmldesigner/components/propertyeditor/basiclayouts.h
new file mode 100644
index 0000000000..f57dc2612f
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/basiclayouts.h
@@ -0,0 +1,197 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+/****************************************************************************
+**
+** 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 BASICLAYOUTS_H
+#define BASICLAYOUTS_H
+
+#include <qlayoutobject.h>
+#include <QHBoxLayout>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QBoxLayoutObject : public QLayoutObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QmlList<QWidget *> *children READ children)
+
+ Q_PROPERTY(int topMargin READ topMargin WRITE setTopMargin)
+ Q_PROPERTY(int bottomMargin READ bottomMargin WRITE setBottomMargin)
+ Q_PROPERTY(int leftMargin READ leftMargin WRITE setLeftMargin)
+ Q_PROPERTY(int rightMargin READ rightMargin WRITE setRightMargin)
+ Q_PROPERTY(int spacing READ spacing WRITE setSpacing)
+
+ Q_CLASSINFO("DefaultProperty", "children")
+public:
+ QBoxLayoutObject(QObject *parent=0);
+ QBoxLayoutObject(QBoxLayout *, QObject *parent=0);
+ virtual QLayout *layout() const;
+
+ QmlList<QWidget *> *children() { return &_widgets; }
+
+private:
+ friend class WidgetList;
+ void addWidget(QWidget *);
+ void clearWidget();
+
+ //XXX need to provide real implementations once QBoxLayoutObject is finished
+ class WidgetList : public QmlList<QWidget *>
+ {
+ public:
+ WidgetList(QBoxLayoutObject *o)
+ : obj(o) {}
+
+ virtual void append(QWidget *w) { obj->addWidget(w); }
+ virtual void clear() { obj->clearWidget(); }
+ virtual int count() const { return 0; }
+ virtual void removeAt(int) {}
+ virtual QWidget *at(int) const { return 0; }
+ virtual void insert(int, QWidget *) {}
+
+ private:
+ QBoxLayoutObject *obj;
+ };
+
+ void getMargins()
+ {
+ _layout->getContentsMargins(&mLeft, &mTop, &mRight, &mBottom);
+ }
+
+ void setMargins()
+ {
+ _layout->setContentsMargins(mLeft, mTop, mRight, mBottom);
+ }
+
+ int topMargin()
+ {
+ getMargins();
+ return mTop;
+ }
+
+ void setTopMargin(int margin)
+ {
+ getMargins();
+ mTop = margin;
+ setMargins();
+ }
+
+ int bottomMargin()
+ {
+ getMargins();
+ return mBottom;
+ }
+
+ void setBottomMargin(int margin)
+ {
+ getMargins();
+ mBottom = margin;
+ setMargins();
+ }
+
+ int leftMargin()
+ {
+ getMargins();
+ return mLeft;
+ }
+
+ void setLeftMargin(int margin)
+ {
+ getMargins();
+ mLeft = margin;
+ setMargins();
+ }
+
+ int rightMargin()
+ {
+ getMargins();
+ return mRight;
+ }
+
+ void setRightMargin(int margin)
+ {
+ getMargins();
+ mRight = margin;
+ setMargins();
+ }
+
+ int spacing() const
+ {
+ return _layout->spacing();
+ }
+
+ void setSpacing(int spacing)
+ {
+ _layout->setSpacing(spacing);
+ }
+
+ WidgetList _widgets;
+ QBoxLayout *_layout;
+
+ int mTop, mLeft, mBottom, mRight;
+
+};
+QML_DECLARE_TYPE(QBoxLayoutObject);
+
+class QHBoxLayoutObject : public QBoxLayoutObject
+{
+Q_OBJECT
+public:
+ QHBoxLayoutObject(QObject *parent=0);
+};
+QML_DECLARE_TYPE(QHBoxLayoutObject);
+
+class QVBoxLayoutObject : public QBoxLayoutObject
+{
+Q_OBJECT
+public:
+ QVBoxLayoutObject(QObject *parent=0);
+};
+QML_DECLARE_TYPE(QVBoxLayoutObject);
+
+#endif // BASICLAYOUTS_H
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/plugins/qmldesigner/components/propertyeditor/basicwidgets.cpp b/src/plugins/qmldesigner/components/propertyeditor/basicwidgets.cpp
new file mode 100644
index 0000000000..7bcac7b0b0
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/basicwidgets.cpp
@@ -0,0 +1,1142 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+/****************************************************************************
+**
+** 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 "basicwidgets.h"
+#include <qlayoutobject.h>
+#include <private/graphicswidgets_p.h>
+#include <qmlcontext.h>
+#include <qmlengine.h>
+#include <qmlcomponent.h>
+#include <QtCore/QDebug>
+#include <QFile>
+#include <QPixmap>
+#include <QTimeLine>
+#include "colorwidget.h"
+#include "filewidget.h"
+#include <QFileInfo>
+#include <QMenu>
+#include <QAction>
+#include <QListView>
+#include <QDebug>
+#include <QApplication>
+#include <QGraphicsOpacityEffect>
+
+
+QT_BEGIN_NAMESPACE
+
+
+class QWidgetDeclarativeUI;
+
+class ResizeEventFilter : public QObject
+{
+ Q_OBJECT
+public:
+ ResizeEventFilter(QObject *parent) : QObject(parent), m_target(0) { }
+
+ void setTarget(QObject *target) { m_target = target; }
+ void setDuiTarget(QWidgetDeclarativeUI* dui_target) {m_dui_target = dui_target;}
+
+protected:
+ bool eventFilter(QObject *obj, QEvent *event);
+private:
+ QObject *m_target;
+ QWidgetDeclarativeUI* m_dui_target;
+};
+
+class QWidgetDeclarativeUI : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QmlList<QObject *> *children READ children)
+ Q_PROPERTY(QLayoutObject *layout READ layout WRITE setLayout)
+ Q_PROPERTY(QFont font READ font CONSTANT)
+
+ Q_PROPERTY(QPoint pos READ pos)
+ Q_PROPERTY(QSize size READ size)
+
+ Q_PROPERTY(int x READ x WRITE setX NOTIFY xChanged)
+ Q_PROPERTY(int y READ y WRITE setY NOTIFY yChanged)
+ Q_PROPERTY(bool focus READ hasFocus NOTIFY focusChanged)
+ Q_PROPERTY(int width READ width WRITE setWidth NOTIFY widthChanged)
+ Q_PROPERTY(int height READ height WRITE setHeight NOTIFY heightChanged)
+ Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity NOTIFY opacityChanged)
+
+ Q_PROPERTY(QUrl styleSheetFile READ styleSheetFile WRITE setStyleSheetFile NOTIFY styleSheetFileChanged)
+
+ Q_PROPERTY(QColor windowColor READ windowColor WRITE setWindowColor)
+ Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor)
+ Q_PROPERTY(QColor baseColor READ baseColor WRITE setBaseColor)
+ Q_PROPERTY(QColor textColor READ textColor WRITE setTextColor)
+ Q_PROPERTY(QColor windowTextColor READ windowTextColor WRITE setWindowTextColor)
+ Q_PROPERTY(QColor buttonTextColor READ buttonTextColor WRITE setButtonTextColor)
+
+ Q_PROPERTY(int fixedWidth READ width WRITE setFixedWidth)
+ Q_PROPERTY(int fixedHeight READ height WRITE setFixedHeight)
+
+ Q_PROPERTY(bool mouseOver READ mouseOver NOTIFY mouseOverChanged)
+
+ Q_CLASSINFO("DefaultProperty", "children")
+
+signals:
+ void xChanged();
+ void yChanged();
+ void widthChanged();
+ void heightChanged();
+ void focusChanged();
+ void mouseOverChanged();
+ void opacityChanged();
+
+public:
+ QWidgetDeclarativeUI(QObject *other) : QObject(other), _children(other), _layout(0), _graphicsOpacityEffect(0) {
+
+
+ q = qobject_cast<QWidget*>(other);
+ ResizeEventFilter *filter(new ResizeEventFilter(q));
+ filter->setTarget(q);
+ filter->setDuiTarget(this);
+ m_mouseOver = false;
+ q->installEventFilter(filter);
+ Q_ASSERT(q);
+ }
+ virtual ~QWidgetDeclarativeUI() {
+ }
+
+ class Children : public QmlConcreteList<QObject *>
+ {
+ public:
+ Children(QObject *widget) : q(qobject_cast<QWidget *>(widget)) {}
+ virtual void append(QObject *o)
+ {
+ insert(-1, o);
+ }
+ virtual void clear()
+ {
+ for (int i = 0; i < count(); ++i)
+ at(i)->setParent(0);
+ QmlConcreteList<QObject *>::clear();
+ }
+ virtual void removeAt(int i)
+ {
+ at(i)->setParent(0);
+ QmlConcreteList<QObject *>::removeAt(i);
+ }
+ virtual void insert(int i, QObject *o)
+ {
+ QmlConcreteList<QObject *>::insert(i, o);
+ if (QWidget *w = qobject_cast<QWidget *>(o))
+ w->setParent(static_cast<QWidget *>(q));
+ else
+ o->setParent(q);
+ }
+
+ private:
+ QWidget *q;
+ };
+
+public:
+
+ void setMouseOver(bool _mouseOver)
+ {
+ m_mouseOver = _mouseOver;
+ }
+
+ void emitResize()
+ {
+ emit widthChanged();
+ emit heightChanged();
+ }
+
+ void emitMove()
+ {
+ emit xChanged();
+ emit yChanged();
+ }
+
+ void emitFocusChanged()
+ {
+ emit focusChanged();
+ }
+
+ void emitMouseOverChanged()
+ {
+ emit mouseOverChanged();
+ }
+
+ QmlList<QObject *> *children() { return &_children; }
+
+ QLayoutObject *layout() const { return _layout; }
+ void setLayout(QLayoutObject *lo)
+ {
+ _layout = lo;
+ static_cast<QWidget *>(parent())->setLayout(lo->layout());
+ }
+
+ QFont font() const
+ {
+ return _font;
+ }
+
+ void setFont(const QFont &font)
+ {
+ if (font != _font) {
+ _font = font;
+ static_cast<QWidget *>(parent())->setFont(_font);
+ }
+ }
+
+ int x() const {
+ return q->x();
+ }
+
+ bool hasFocus() const {
+ return q->hasFocus();
+ }
+
+ bool mouseOver() const {
+ return m_mouseOver;
+ }
+
+ void setX(int x) {
+ q->move(x, y());
+ }
+
+ int y() const {
+ return q->y();
+ }
+
+ qreal opacity() const {
+ if (_graphicsOpacityEffect)
+ return _graphicsOpacityEffect->opacity();
+ else
+ return 1;
+ }
+
+ void setOpacity(qreal newOpacity) {
+ if (newOpacity != opacity()) {
+ if (!_graphicsOpacityEffect) {
+ _graphicsOpacityEffect = new QGraphicsOpacityEffect(this);
+ q->setGraphicsEffect(_graphicsOpacityEffect);
+ }
+ _graphicsOpacityEffect->setOpacity(newOpacity);
+ emit opacityChanged();
+ }
+ }
+
+ void setY(int y) {
+ q->move(x(), y);
+ }
+
+ int width() const {
+ return q->width();
+ }
+
+ void setWidth(int width) {
+ q->resize(width, height());
+ }
+
+ int height() const {
+ return q->height();
+ }
+
+ void setHeight(int height) {
+ q->resize(width(), height);
+ }
+
+ void setFixedWidth(int width) {
+ q->setFixedWidth(width);
+ }
+
+ void setFixedHeight(int height) {
+ q->setFixedHeight(height);
+ }
+
+ QPoint pos() const {
+ return q->pos();
+ }
+
+ QSize size() const {
+ return q->size();
+ }
+
+ QUrl styleSheetFile() const {
+ return _styleSheetFile;
+ }
+
+ QColor windowColor() const
+ { return q->palette().color(QPalette::Window); }
+
+ void setWindowColor(const QColor &color)
+ {
+ QPalette pal = q->palette();
+ pal.setColor(QPalette::Window, color);
+ q->setPalette(pal);
+ }
+
+ QColor backgroundColor() const
+ { return q->palette().color(QPalette::Background); }
+
+ void setBackgroundColor(const QColor &color)
+ {
+ QPalette pal = q->palette();
+ pal.setColor(QPalette::Background, color);
+ q->setPalette(pal);
+ }
+
+ QColor baseColor() const
+ { return q->palette().color(QPalette::Base); }
+
+ void setBaseColor(const QColor &color)
+ {
+ QPalette pal = q->palette();
+ pal.setColor(QPalette::Base, color);
+ q->setPalette(pal);
+ }
+
+ QColor textColor() const
+ { return q->palette().color(QPalette::Text); }
+
+ void setTextColor(const QColor &color)
+ {
+ QPalette pal = q->palette();
+ pal.setColor(QPalette::Text, color);
+ q->setPalette(pal);
+ }
+
+ QColor windowTextColor() const
+ { return q->palette().color(QPalette::WindowText); }
+
+ void setWindowTextColor(const QColor &color)
+ {
+ QPalette pal = q->palette();
+ pal.setColor(QPalette::WindowText, color);
+ q->setPalette(pal);
+ }
+
+ QColor buttonTextColor() const
+ { return q->palette().color(QPalette::ButtonText); }
+
+ void setButtonTextColor(const QColor &color)
+ {
+ QPalette pal = q->palette();
+ pal.setColor(QPalette::ButtonText, color);
+ q->setPalette(pal);
+ }
+
+ void setStyleSheetFile(const QUrl &url) {
+ _styleSheetFile = url;
+ _styleSheetFile.setScheme("file"); //### todo
+ QString fileName;
+ if (!QFileInfo(_styleSheetFile.toLocalFile()).exists())
+ fileName = (":" + _styleSheetFile.toLocalFile().split(":").last()); //try if it is a resource
+ else
+ fileName = (_styleSheetFile.toLocalFile());
+ QFile file(fileName);
+ file.open(QIODevice::ReadOnly);
+ if (file.isOpen()) {
+ QString styleSheet(file.readAll());
+ q->setStyleSheet(styleSheet);
+ } else {
+ qWarning() << QLatin1String("setStyleSheetFile: ") << url << QLatin1String(" not found!");
+ }
+
+ }
+
+private:
+ QWidget *q;
+ Children _children;
+ QLayoutObject *_layout;
+ QFont _font;
+ QUrl _styleSheetFile;
+ QGraphicsOpacityEffect *_graphicsOpacityEffect;
+ bool m_mouseOver;
+};
+
+bool ResizeEventFilter::eventFilter(QObject *obj, QEvent *event)
+{
+ if (event->type() == QEvent::Resize) {
+ if (obj
+ && obj->isWidgetType()
+ && obj == m_target) {
+ m_dui_target->emitResize();
+ return QObject::eventFilter(obj, event);
+ }
+ } else if (event->type() == QEvent::Move) {
+ if (obj
+ && obj->isWidgetType()
+ && obj == m_target) {
+ m_dui_target->emitMove();
+ return QObject::eventFilter(obj, event);
+ }
+ } else if ((event->type() == QEvent::FocusIn) || (event->type() == QEvent::FocusOut)) {
+ if (obj
+ && obj->isWidgetType()
+ && obj == m_target) {
+ m_dui_target->emitFocusChanged();
+ return QObject::eventFilter(obj, event);
+ }
+ } else if ((event->type() == QEvent::Enter) || (event->type() == QEvent::Leave)) {
+ if (obj
+ && obj->isWidgetType()
+ && obj == m_target) {
+ m_dui_target->setMouseOver(event->type() == QEvent::Enter);
+ m_dui_target->emitMouseOverChanged();
+ return QObject::eventFilter(obj, event);
+ }
+ }
+ return QObject::eventFilter(obj, event);
+}
+
+
+class QTabObject : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QWidget *content READ content WRITE setContent)
+ Q_PROPERTY(QString label READ label WRITE setLabel)
+ Q_PROPERTY(QIcon icon READ icon WRITE setIcon)
+ Q_CLASSINFO("DefaultProperty", "content")
+public:
+ QTabObject(QObject *parent = 0) : QObject(parent), _content(0) {}
+
+ QWidget *content() const { return _content; }
+ void setContent(QWidget *content)
+ {
+ _content = content;
+ }
+
+ QString label() const { return _label; }
+ void setLabel(const QString &label)
+ {
+ _label = label;
+ }
+
+ QIcon icon() const { return _icon; }
+ void setIcon(const QIcon &icon)
+ {
+ _icon = icon;
+ }
+
+private:
+ QWidget *_content;
+ QString _label;
+ QIcon _icon;
+};
+
+class QPushButtonDeclarativeUI : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QUrl iconFromFile READ iconFromFile WRITE setIconFromFile)
+public:
+ QPushButtonDeclarativeUI(QObject *parent = 0) : QObject(parent)
+ {
+ pb = qobject_cast<QPushButton*>(parent);
+ }
+private:
+ QUrl iconFromFile() const
+ {
+ return _url;
+ }
+
+ void setIconFromFile(const QUrl &url) {
+ _url = url;
+
+ QString path;
+ if (_url.scheme() == QLatin1String("qrc")) {
+ path = ":" + _url.path();
+ } else {
+ path = _url.toLocalFile();
+ }
+
+ QFile file(path);
+ file.open(QIODevice::ReadOnly);
+ if (file.exists() && file.isOpen()) {
+ QPixmap pixmap(path);
+ if (pixmap.isNull())
+ qWarning() << QLatin1String("setIconFromFile: ") << url << QLatin1String(" not found!");
+ pb->setIcon(pixmap);
+ } else {
+ qWarning() << QLatin1String("setIconFromFile: ") << url << QLatin1String(" not found!");
+ }
+
+ }
+
+ QPushButton *pb;
+ QUrl _url;
+};
+
+class QMenuDeclarativeUI : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QmlList<Action *> *actions READ actions)
+ Q_CLASSINFO("DefaultProperty", "actions")
+
+public:
+ QMenuDeclarativeUI(QObject *parent = 0) : QObject(parent), _actions(parent)
+ {
+ menu = qobject_cast<QMenu*>(parent);
+ }
+
+ QmlList<Action *> *actions() { return &_actions; }
+
+private:
+ //if not for the at() function, we could use QmlList instead
+ class Actions : public QmlConcreteList<Action *>
+ {
+ public:
+ Actions(QObject *o) : menu(qobject_cast<QMenu*>(o)) {}
+ virtual void append(Action *o)
+ {
+ QmlConcreteList<Action *>::append(o);
+ o->setParent(menu);
+ menu->addAction(o);
+ }
+ virtual void clear()
+ {
+ QmlConcreteList<Action *>::clear();
+ menu->clear();
+ }
+ virtual void removeAt(int i)
+ {
+ QmlConcreteList<Action *>::removeAt(i);
+ menu->removeAction(menu->actions().at(i));
+ }
+ virtual void insert(int i, Action *obj)
+ {
+ QmlConcreteList<Action *>::insert(i, obj);
+ obj->setParent(menu);
+ menu->addAction(obj);
+ }
+ private:
+ QMenu *menu;
+ };
+
+ QMenu *menu;
+ Actions _actions;
+};
+
+class QToolButtonDeclarativeUI : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QUrl iconFromFile READ iconFromFile WRITE setIconFromFile)
+ Q_PROPERTY(QMenu *menu READ menu WRITE setMenu)
+
+public:
+ QToolButtonDeclarativeUI(QObject *parent = 0) : QObject(parent)
+ {
+ pb = qobject_cast<QToolButton*>(parent);
+ }
+private:
+
+ QMenu *menu() const { return pb->menu(); }
+ void setMenu(QMenu *menu)
+ {
+ pb->setMenu(menu);
+ }
+
+ QUrl iconFromFile() const
+ {
+ return _url;
+ }
+
+ void setIconFromFile(const QUrl &url) {
+ _url = url;
+
+ QString path;
+ if (_url.scheme() == QLatin1String("qrc")) {
+ path = ":" + _url.path();
+ } else {
+ path = _url.toLocalFile();
+ }
+
+ QFile file(path);
+ file.open(QIODevice::ReadOnly);
+ if (file.exists() && file.isOpen()) {
+ QPixmap pixmap(path);
+ if (pixmap.isNull())
+ qWarning() << QLatin1String("setIconFromFile: ") << url << QLatin1String(" not found!");
+ pb->setIcon(pixmap);
+ } else {
+ qWarning() << QLatin1String("setIconFromFile: ") << url << QLatin1String(" not found!");
+ }
+
+ }
+
+ QToolButton *pb;
+ QUrl _url;
+};
+
+class QComboBoxDeclarativeUI : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QStringList items READ items WRITE setItems NOTIFY itemChanged)
+ Q_PROPERTY(QString currentText READ currentText WRITE setCurrentText NOTIFY currentTextChanged)
+
+public:
+ QComboBoxDeclarativeUI(QObject *parent = 0) : QObject(parent), m_itemsSet(false)
+ {
+ cb = qobject_cast<QComboBox*>(parent);
+ connect(cb, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(setCurrentText(const QString &)));
+ }
+
+ QString currentText() const
+ {
+ return cb->currentText();
+ }
+
+public slots:
+ void setCurrentText(const QString &text)
+ {
+ if (!m_itemsSet)
+ return;
+ int i = cb->findText(text);
+ if (i != -1) {
+ cb->setCurrentIndex(i);
+ emit currentTextChanged();
+ }
+ }
+signals:
+ void currentTextChanged();
+ void itemsChanged();
+
+private:
+ void setItems(const QStringList &list)
+ {
+ _items = list;
+ cb->clear();
+ cb->addItems(list);
+ m_itemsSet = true;
+ emit itemsChanged();
+ }
+
+ QStringList items() const
+ {
+ return _items;
+ }
+
+ QComboBox *cb;
+ QStringList _items;
+
+ bool m_itemsSet;
+};
+
+class QScrollAreaDeclarativeUI : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QWidget *content READ content WRITE setContent)
+ Q_CLASSINFO("DefaultProperty", "content")
+
+public slots:
+ void setupProperWheelBehaviour();
+
+public:
+ QScrollAreaDeclarativeUI(QObject *parent = 0) : QObject(parent), _content(0)
+ {
+ sa = qobject_cast<QScrollArea*>(parent);
+ }
+
+private:
+ QWidget *content() const { return _content; }
+ void setContent(QWidget *content)
+ {
+ _content = content;
+ sa->setWidget(content);
+ sa->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
+ sa->verticalScrollBar()->show();
+ setupProperWheelBehaviour();
+ }
+
+ QWidget *_content;
+ QScrollArea *sa;
+};
+
+class MouseWheelFilter : public QObject
+{
+ Q_OBJECT
+public:
+ MouseWheelFilter(QObject *parent) : QObject(parent), m_target(0) { }
+
+ void setTarget(QObject *target) { m_target = target; }
+
+protected:
+ bool eventFilter(QObject *obj, QEvent *event);
+private:
+ QObject *m_target;
+};
+
+bool MouseWheelFilter::eventFilter(QObject *obj, QEvent *event)
+{
+ if (event->type() == QEvent::Wheel) {
+ if (obj
+ && obj->isWidgetType()
+ && obj != m_target) {
+ QApplication::sendEvent(m_target, event);
+ return true;
+ }
+ }
+ return QObject::eventFilter(obj, event);
+}
+
+void QScrollAreaDeclarativeUI::setupProperWheelBehaviour()
+{
+// We install here an eventfilter to avoid that scrolling in
+// in the ScrollArea changes values in editor widgets
+ if (_content) {
+ MouseWheelFilter *forwarder(new MouseWheelFilter(this));
+ forwarder->setTarget(_content);
+
+ foreach (QWidget *childWidget, _content->findChildren<QWidget*>()) {
+ childWidget->installEventFilter(forwarder);
+ }
+ }
+}
+
+class WidgetLoader : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(QString sourceString READ sourceString WRITE setSourceString NOTIFY sourceChanged)
+ Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
+ Q_PROPERTY(QWidget *widget READ widget NOTIFY widgetChanged)
+ Q_PROPERTY(QmlComponent *component READ component NOTIFY sourceChanged)
+
+public:
+ WidgetLoader(QWidget * parent = 0) : QWidget(parent), m_source(QUrl()), m_widget(0),
+ m_component(0), m_layout(0)
+ {
+ m_layout = new QVBoxLayout(this);
+ m_layout->setContentsMargins(0,0,0,0);
+ }
+
+ QUrl source() const;
+ void setSource(const QUrl &);
+
+ QString sourceString() const
+ { return m_source.toString(); }
+ void setSourceString(const QString &url)
+ { setSource(QUrl(url)); }
+
+ QWidget *widget() const;
+ QmlComponent *component() const
+ { return m_component; }
+
+signals:
+ void widgetChanged();
+ void sourceChanged();
+
+private:
+ QUrl m_source;
+ QWidget *m_widget;
+ QmlComponent *m_component;
+ QVBoxLayout *m_layout;
+
+};
+
+QUrl WidgetLoader::source() const
+{
+ return m_source;
+}
+
+void WidgetLoader::setSource(const QUrl &source)
+{
+ if (m_source == source)
+ return;
+
+ if (m_component) {
+ delete m_component;
+ m_component = 0;
+ }
+
+ QWidget *oldWidget = m_widget;
+
+ if (m_widget) {
+ //m_widget->deleteLater();
+ m_widget = 0;
+ }
+
+ m_source = source;
+ if (m_source.isEmpty()) {
+ emit sourceChanged();
+ emit widgetChanged();
+ return;
+ }
+
+ m_component = new QmlComponent(qmlEngine(this), m_source, this);
+
+ if (m_component) {
+ emit sourceChanged();
+ emit widgetChanged();
+
+ while (m_component->isLoading())
+ QApplication::processEvents();
+
+ if (!m_component->isReady()) {
+ if (!m_component->errors().isEmpty())
+ qWarning() << m_component->errors();
+ emit sourceChanged();
+ return;
+ }
+
+ QmlContext *ctxt = new QmlContext(qmlContext(this));
+ ctxt->addDefaultObject(this);
+
+ QObject *obj = m_component->create(ctxt);
+ if (obj) {
+ QWidget *widget = qobject_cast<QWidget *>(obj);
+ if (widget) {
+ m_widget = widget;
+ m_layout->addWidget(m_widget);
+ m_widget->show();
+ }
+ }
+ }
+
+}
+
+QWidget *WidgetLoader::widget() const
+{
+ return m_widget;
+}
+
+class MyGroupBox : public QGroupBox
+{
+ Q_OBJECT
+
+public:
+ MyGroupBox(QWidget * parent = 0) : QGroupBox(parent), m_animated(false)
+ {}
+
+void setPixmap(const QPixmap &pixmap, qreal alpha = 1)
+{ m_pixmap = pixmap; m_alpha = alpha;}
+
+void setAnimated(bool animated)
+{ m_animated = animated; }
+
+public slots:
+ virtual void setVisible ( bool visible );
+
+protected:
+ virtual void paintEvent(QPaintEvent * event);
+private:
+ qreal m_alpha;
+ QPixmap m_pixmap;
+ bool m_animated;
+};
+
+void MyGroupBox::paintEvent(QPaintEvent * event)
+{
+ QGroupBox::paintEvent(event);
+ if (m_animated) {
+ QPainter p(this);
+ p.setOpacity(m_alpha);
+ p.drawPixmap(5, 5, m_pixmap.width(), m_pixmap.height(), m_pixmap);
+ }
+}
+
+void MyGroupBox::setVisible ( bool visible )
+{
+ if (parentWidget())
+ QGroupBox::setVisible(visible);
+}
+
+class QGroupBoxDeclarativeUI : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool collapsed READ isCollapsed WRITE setCollapsed)
+public:
+ QGroupBoxDeclarativeUI(QObject *parent = 0) : QObject(parent), m_expanded(true)
+ {
+ gb = qobject_cast<MyGroupBox*>(parent);
+ connect(&m_timeLine, SIGNAL(frameChanged(int)), this, SLOT(animate(int)));
+ connect(&m_timeLine, SIGNAL(finished()), this, SLOT(finish()));
+
+ m_timeLine.setDuration(150);
+ m_timeLine.setFrameRange(0, 5);
+ }
+
+ bool isCollapsed()
+ { return ! m_expanded; }
+
+ void setCollapsed(bool collapsed)
+ {
+ if (collapsed)
+ collapse();
+ else
+ expand();
+ }
+
+public slots:
+ void collapse();
+ void expand();
+
+ void animate(int frame);
+ void finish();
+
+private:
+ MyGroupBox *gb;
+ QTimeLine m_timeLine;
+ bool m_expanded;
+ int m_oldHeight;
+ int m_oldMAxHeight;
+ QPixmap m_contens;
+
+ void hideChildren();
+ void showChildren();
+
+ void reLayout();
+};
+
+void QGroupBoxDeclarativeUI::reLayout()
+{
+ QLayout *layout = gb->parentWidget()->layout();
+ if (layout) {
+ layout->activate();
+ layout->update();
+ }
+}
+
+void QGroupBoxDeclarativeUI::finish()
+{
+ gb->setAnimated(false);
+ if (m_expanded) {
+ showChildren();
+
+ gb->setMaximumHeight(m_oldMAxHeight);
+ }
+ else {
+ gb->setMaximumHeight(30);
+ }
+ reLayout();
+}
+
+void QGroupBoxDeclarativeUI::hideChildren()
+{
+ if (gb->isVisible()) {
+ gb->setMinimumHeight(gb->height());
+ foreach (QWidget *widget, gb->findChildren<QWidget*>()) {
+ widget->setProperty("wasVisibleGB", widget->property("visible"));
+ }
+ foreach (QWidget *widget, gb->findChildren<QWidget*>())
+ if (widget->parent() == gb)
+ widget->hide();
+ }
+}
+
+void QGroupBoxDeclarativeUI::showChildren()
+{
+ foreach (QWidget *widget, gb->findChildren<QWidget*>()) {
+ if (widget->property("wasVisibleGB").toBool())
+ widget->show();
+ widget->setProperty("wasVisibleGB", QVariant());
+ widget->ensurePolished();
+ }
+ gb->show();
+}
+
+void QGroupBoxDeclarativeUI::collapse()
+{
+ m_oldMAxHeight = gb->maximumHeight();
+ m_oldHeight = gb->height();
+ if (!m_expanded)
+ return;
+ m_contens = QPixmap::grabWidget (gb, 5, 5, gb->width() - 5, gb->height() - 5);
+ gb->setPixmap(m_contens,1);
+ hideChildren();
+ m_expanded = false;
+ m_timeLine.start();
+}
+
+void QGroupBoxDeclarativeUI::expand()
+{
+ if (m_expanded)
+ return;
+ m_expanded = true;
+ m_timeLine.start();
+}
+
+void QGroupBoxDeclarativeUI::animate(int frame)
+{
+ gb->setAnimated(true);
+ qreal height;
+
+ if (m_expanded) {
+ height = ((qreal(frame) / 5.0) * qreal(m_oldHeight)) + (30.0 * (1.0 - qreal(frame) / 5.0));
+ gb->setPixmap(m_contens, qreal(frame) / 5.0);
+ }
+ else {
+ height = ((qreal(frame) / 5.0) * 30.0) + (qreal(m_oldHeight) * (1.0 - qreal(frame) / 5.0));
+ qreal alpha = 0.8 - qreal(frame) / 4.0;
+ if (alpha < 0)
+ alpha = 0;
+ gb->setPixmap(m_contens, alpha);
+ }
+
+ gb->setMaximumHeight(height);
+ gb->setMinimumHeight(height);
+ reLayout();
+ gb->update();
+}
+
+QML_DECLARE_TYPE(QTabObject);
+QML_DEFINE_TYPE(Qt,4,6,QTabObject,QTabObject); //### with namespacing, this should just be 'Tab'
+
+class QTabWidgetDeclarativeUI : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QmlList<QTabObject *> *tabs READ tabs)
+ Q_CLASSINFO("DefaultProperty", "tabs")
+public:
+ QTabWidgetDeclarativeUI(QObject *other) : QObject(other), _tabs(other) {}
+
+ QmlList<QTabObject *> *tabs() { return &_tabs; }
+
+private:
+ //if not for the at() function, we could use QmlList instead
+ class Tabs : public QmlConcreteList<QTabObject *>
+ {
+ public:
+ Tabs(QObject *o) : tw(o) {}
+ virtual void append(QTabObject *o)
+ {
+ QmlConcreteList<QTabObject *>::append(o);
+ //XXX can we insertTab(-1, o) instead?
+ if (!o->icon().isNull())
+ static_cast<QTabWidget *>(tw)->addTab(o->content(), o->icon(), o->label());
+ else
+ static_cast<QTabWidget *>(tw)->addTab(o->content(), o->label());
+ }
+ virtual void clear()
+ {
+ QmlConcreteList<QTabObject *>::clear();
+ static_cast<QTabWidget *>(tw)->clear();
+ }
+ virtual void removeAt(int i)
+ {
+ QmlConcreteList<QTabObject *>::removeAt(i);
+ static_cast<QTabWidget *>(tw)->removeTab(i);
+ }
+ virtual void insert(int i, QTabObject *obj)
+ {
+ QmlConcreteList<QTabObject *>::insert(i, obj);
+ if (!obj->icon().isNull())
+ static_cast<QTabWidget *>(tw)->insertTab(i, obj->content(), obj->icon(), obj->label());
+ else
+ static_cast<QTabWidget *>(tw)->insertTab(i, obj->content(), obj->label());
+ }
+ private:
+ QObject *tw;
+ };
+ Tabs _tabs;
+};
+
+
+class WidgetFrame : public QFrame
+{
+ Q_OBJECT
+public:
+ WidgetFrame( QWidget * parent = 0, Qt::WindowFlags f = 0 ) : QFrame(parent, f)
+ {}
+};
+
+QML_DEFINE_EXTENDED_TYPE(Qt,4,6,QWidget,QWidget,QWidgetDeclarativeUI);
+
+//display
+QML_DEFINE_TYPE(Qt,4,6,QLabel,QLabel);
+QML_DEFINE_TYPE(Qt,4,6,QProgressBar,QProgressBar);
+QML_DEFINE_TYPE(Qt,4,6,QLCDNumber,QLCDNumber);
+
+//input
+QML_DEFINE_TYPE(Qt,4,6,QLineEdit,QLineEdit);
+QML_DEFINE_TYPE(Qt,4,6,QTextEdit,QTextEdit);
+QML_DEFINE_TYPE(Qt,4,6,QPlainTextEdit,QPlainTextEdit);
+QML_DEFINE_TYPE(Qt,4,6,QSpinBox,QSpinBox);
+QML_DEFINE_TYPE(Qt,4,6,QDoubleSpinBox,QDoubleSpinBox);
+QML_DEFINE_TYPE(Qt,4,6,QSlider,QSlider);
+QML_DEFINE_TYPE(Qt,4,6,QDateTimeEdit,QDateTimeEdit);
+QML_DEFINE_TYPE(Qt,4,6,QDateEdit,QDateEdit);
+QML_DEFINE_TYPE(Qt,4,6,QTimeEdit,QTimeEdit);
+QML_DEFINE_TYPE(Qt,4,6,QFontComboBox,QFontComboBox);
+QML_DEFINE_TYPE(Qt,4,6,QDial,QDial);
+QML_DEFINE_TYPE(Qt,4,6,QScrollBar,QScrollBar);
+QML_DEFINE_TYPE(Qt,4,6,QCalendarWidget, QCalendarWidget);
+
+
+QML_DECLARE_TYPE(MyGroupBox);
+QML_DECLARE_TYPE(WidgetLoader);
+QML_DECLARE_TYPE(WidgetFrame);
+//QML_DEFINE_TYPE(Qt,4,6,QComboBox,QComboBox); //need a way to populate
+//QML_DEFINE_EXTENDED_TYPE(QComboBox,QComboBox, QComboBox); //need a way to populate
+
+//buttons
+//QML_DEFINE_TYPE(Qt,4,6,QPushButton,QPushButton);
+QML_DEFINE_TYPE(Qt,4,6,QCheckBox,QCheckBox);
+QML_DEFINE_TYPE(Qt,4,6,QAction,Action);
+QML_DEFINE_TYPE(Qt,4,6,QRadioButton,QRadioButton);
+QML_DEFINE_TYPE(Qt,4,6,FileWidget, FileWidget);
+QML_DEFINE_TYPE(Qt,4,6,LayoutWidget, LayoutWidget);
+
+//containers
+QML_DEFINE_TYPE(Qt,4,6,QFrame,QFrame);
+QML_DEFINE_TYPE(Qt,4,6,WidgetFrame,WidgetFrame);
+QML_DEFINE_TYPE(Qt,4,6,WidgetLoader,WidgetLoader);
+QML_DEFINE_EXTENDED_TYPE(Qt,4,6,QExtGroupBox,MyGroupBox,QGroupBoxDeclarativeUI);
+QML_DEFINE_EXTENDED_TYPE(Qt,4,6,QTabWidget,QTabWidget,QTabWidgetDeclarativeUI);
+QML_DEFINE_EXTENDED_TYPE(Qt,4,6,QScrollArea,QScrollArea,QScrollAreaDeclarativeUI);
+QML_DEFINE_EXTENDED_TYPE(Qt,4,6,QPushButton,QPushButton,QPushButtonDeclarativeUI);
+QML_DEFINE_EXTENDED_TYPE(Qt,4,6,QToolButton,QToolButton, QToolButtonDeclarativeUI);
+QML_DEFINE_EXTENDED_TYPE(Qt,4,6,QComboBox,QComboBox, QComboBoxDeclarativeUI);
+QML_DEFINE_EXTENDED_TYPE(Qt,4,6,QMenu,QMenu, QMenuDeclarativeUI);
+//QML_DEFINE_TYPE(Qt,4,6,QToolBox,QToolBox);
+//QML_DEFINE_TYPE(Qt,4,6,QScrollArea,QScrollArea);
+
+//QML_DEFINE_EXTENDED_TYPE(QtColorButton,QtColorButton,QtColorButtonDeclarativeUI);
+
+//itemviews
+//QML_DEFINE_TYPE(Qt,4,6,QListView,QListView);
+//QML_DEFINE_TYPE(Qt,4,6,QTreeView,QTreeView);
+//QML_DEFINE_TYPE(Qt,4,6,QTableView,QTableView);
+
+
+#include "basicwidgets.moc"
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmldesigner/components/propertyeditor/basicwidgets.h b/src/plugins/qmldesigner/components/propertyeditor/basicwidgets.h
new file mode 100644
index 0000000000..f7a12a9961
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/basicwidgets.h
@@ -0,0 +1,132 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+/****************************************************************************
+**
+** 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 BASICWIDGETS_H
+#define BASICWIDGETS_H
+
+#include <qml.h>
+#include <QGraphicsScene>
+#include <QGraphicsView>
+#include <QLabel>
+#include <QPushButton>
+#include <QToolButton>
+#include <QCheckBox>
+#include <QRadioButton>
+#include <QLineEdit>
+#include <QTextEdit>
+#include <QPlainTextEdit>
+#include <QDoubleSpinBox>
+#include <QSlider>
+#include <QDateEdit>
+#include <QTimeEdit>
+#include <QProgressBar>
+#include <QGroupBox>
+#include <QDial>
+#include <QLCDNumber>
+#include <QFontComboBox>
+#include <QScrollBar>
+#include <QCalendarWidget>
+#include <QTabWidget>
+#include <QAction>
+#include "colorwidget.h"
+#include "filewidget.h"
+#include "layoutwidget.h"
+
+
+QT_BEGIN_NAMESPACE
+
+QML_DECLARE_TYPE(QWidget);
+
+//display
+QML_DECLARE_TYPE(QLabel);
+QML_DECLARE_TYPE(QProgressBar);
+QML_DECLARE_TYPE(QLCDNumber);
+
+//input
+QML_DECLARE_TYPE(QLineEdit);
+QML_DECLARE_TYPE(QTextEdit);
+QML_DECLARE_TYPE(QPlainTextEdit);
+QML_DECLARE_TYPE(QSpinBox);
+QML_DECLARE_TYPE(QDoubleSpinBox);
+QML_DECLARE_TYPE(QSlider);
+QML_DECLARE_TYPE(QDateTimeEdit);
+QML_DECLARE_TYPE(QDateEdit);
+QML_DECLARE_TYPE(QTimeEdit);
+QML_DECLARE_TYPE(QFontComboBox);
+QML_DECLARE_TYPE(QDial);
+QML_DECLARE_TYPE(QScrollBar);
+QML_DECLARE_TYPE(QCalendarWidget);
+QML_DECLARE_TYPE(QComboBox);
+
+//buttons
+QML_DECLARE_TYPE(QPushButton);
+QML_DECLARE_TYPE(QToolButton);
+QML_DECLARE_TYPE(QCheckBox);
+QML_DECLARE_TYPE(QRadioButton);
+
+//containers
+QML_DECLARE_TYPE(QGroupBox);
+QML_DECLARE_TYPE(QFrame);
+QML_DECLARE_TYPE(QScrollArea);
+QML_DECLARE_TYPE(QTabWidget);
+QML_DECLARE_TYPE(FileWidget);
+QML_DECLARE_TYPE(LayoutWidget);
+
+class Action : public QAction {
+ Q_OBJECT
+public:
+ Action(QObject *parent = 0) : QAction(parent) {}
+};
+
+QML_DECLARE_TYPE(QMenu);
+QML_DECLARE_TYPE(Action);
+
+//QML_DECLARE_TYPE(QToolBox);
+
+//itemviews
+//QML_DECLARE_TYPE(QListView);
+//QML_DECLARE_TYPE(QTreeView);
+//QML_DECLARE_TYPE(QTableView);
+
+//top-level windows?
+
+
+QT_END_NAMESPACE
+#endif // BASICWIDGETS_H
diff --git a/src/plugins/qmldesigner/components/propertyeditor/behaviordialog.cpp b/src/plugins/qmldesigner/components/propertyeditor/behaviordialog.cpp
new file mode 100644
index 0000000000..98609a0abc
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/behaviordialog.cpp
@@ -0,0 +1,174 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "behaviordialog.h"
+
+#include <abstractview.h>
+#include <nodeproperty.h>
+#include <variantproperty.h>
+#include <bindingproperty.h>
+#include <nodeproperty.h>
+
+#include <QLineEdit>
+#include <QSpinBox>
+
+
+QML_DEFINE_TYPE(Bauhaus,1,0,BehaviorWidget,QmlDesigner::BehaviorWidget);
+
+namespace QmlDesigner {
+
+
+BehaviorWidget::BehaviorWidget() : QPushButton(), m_BehaviorDialog(new BehaviorDialog(0))
+{
+ setCheckable(true);
+ connect(this, SIGNAL(toggled(bool)), this, SLOT(buttonPressed(bool)));
+
+}
+BehaviorWidget::BehaviorWidget(QWidget *parent) : QPushButton(parent), m_BehaviorDialog(new BehaviorDialog(0))
+{
+ setCheckable(true);
+ connect(this, SIGNAL(toggled(bool)), this, SLOT(buttonPressed(bool)));
+}
+
+PropertyEditorNodeWrapper* BehaviorWidget::complexNode() const
+{
+ return m_complexNode;
+}
+
+void BehaviorWidget::setComplexNode(PropertyEditorNodeWrapper* complexNode)
+{
+ m_complexNode = complexNode;
+ m_propertyName = complexNode->propertyName();
+ m_modelNode = complexNode->parentModelNode();
+
+ if (!modelNode().isValid()) {
+ m_BehaviorDialog->hide();
+ }
+
+ m_BehaviorDialog->setup(modelNode(), propertyName());
+}
+
+void BehaviorWidget::buttonPressed(bool show)
+{
+ if (show) {
+ if (m_BehaviorDialog->isVisible()) {
+ m_BehaviorDialog->reject();
+ } else {
+ m_BehaviorDialog->setup(modelNode(), propertyName());
+ m_BehaviorDialog->show();
+ setChecked(false);
+ }
+ }
+}
+
+BehaviorDialog::BehaviorDialog(QWidget *parent) : QDialog(parent), m_ui(new Ui_BehaviorDialog)
+{
+ m_ui->setupUi(this);
+ setModal(true);
+}
+
+ void BehaviorDialog::setup(const ModelNode &node, const QString propertyName)
+{
+ m_modelNode = node;
+ m_ui->duration->setValue(100);
+ m_ui->velocity->setValue(2);
+ m_ui->spring->setValue(2);
+ m_ui->damping->setValue(2);
+ m_ui->stackedWidget->setCurrentIndex(0);
+ m_ui->curve->setCurrentIndex(0);
+
+ if (m_modelNode.isValid()) {
+ m_propertyName = propertyName;
+ m_ui->id->setText(m_modelNode.id());
+ m_ui->type->setText(m_modelNode.simplifiedTypeName());
+ m_ui->propertyName->setText(propertyName);
+ if (m_modelNode.hasProperty(m_propertyName) && m_modelNode.property(m_propertyName).isNodeProperty()) {
+ NodeProperty nodeProperty(m_modelNode.nodeProperty(m_propertyName));
+ if (nodeProperty.modelNode().type() == "Qt/SpringFollow") {
+ ModelNode springFollow = nodeProperty.modelNode();
+ m_ui->curve->setCurrentIndex(1);
+ m_ui->stackedWidget->setCurrentIndex(1);
+ if (springFollow.hasProperty("velocity") && springFollow.property("velocity").isVariantProperty())
+ m_ui->velocity->setValue(springFollow.variantProperty("velocity").value().toDouble());
+ if (springFollow.hasProperty("spring") && springFollow.property("spring").isVariantProperty())
+ m_ui->spring->setValue(springFollow.variantProperty("spring").value().toDouble());
+ if (springFollow.hasProperty("damping") && springFollow.property("damping").isVariantProperty())
+ m_ui->damping->setValue(springFollow.variantProperty("damping").value().toDouble());
+ if (springFollow.hasProperty("source") && springFollow.property("source").isVariantProperty())
+ m_ui->source->setText(springFollow.variantProperty("source").value().toString());
+ } else if (nodeProperty.modelNode().type() == "Qt/Behavior") {
+ if (nodeProperty.modelNode().hasProperty("animation") &&
+ nodeProperty.modelNode().property("animation").isNodeProperty() &&
+ nodeProperty.modelNode().nodeProperty("animation").modelNode().type() == "Qt/NumberAnimation") {
+ m_ui->curve->setCurrentIndex(0);
+ ModelNode animation = nodeProperty.modelNode().nodeProperty("animation").modelNode();
+ if (animation.hasProperty("duration") && animation.property("duration").isVariantProperty())
+ m_ui->duration->setValue(animation.variantProperty("duration").value().toInt());
+ if (animation.hasProperty("easing") && animation.property("easing").isVariantProperty()) {
+ QStringList easingItems;
+ for (int i = 0; i < m_ui->curve->count(); i++)
+ easingItems.append(m_ui->curve->itemText(i));
+ m_ui->curve->setCurrentIndex(easingItems.indexOf(animation.variantProperty("easing").value().toString()));
+ }
+ }
+ }
+ }
+ }
+}
+
+void BehaviorDialog::accept()
+{
+ QDialog::accept();
+ if (m_modelNode.hasProperty(m_propertyName))
+ m_modelNode.removeProperty(m_propertyName);
+ if (m_ui->comboBox->currentIndex() == 0) {
+ RewriterTransaction transaction(m_modelNode.view()->beginRewriterTransaction());
+ ModelNode Behavior = m_modelNode.view()->createModelNode("Qt/Behavior", 4, 6);
+ m_modelNode.nodeProperty(m_propertyName).reparentHere(Behavior);
+ ModelNode animation = m_modelNode.view()->createModelNode("Qt/NumberAnimation", 4, 6);
+ animation.variantProperty("duration") = m_ui->duration->value();
+ animation.variantProperty("easing") = m_ui->curve->currentText();
+ Behavior.nodeProperty("animation").reparentHere(animation);
+ } else {
+ RewriterTransaction transaction(m_modelNode.view()->beginRewriterTransaction());
+ ModelNode springFollow = m_modelNode.view()->createModelNode("Qt/SpringFollow", 4, 6);
+ m_modelNode.nodeProperty(m_propertyName).reparentHere(springFollow);
+ springFollow.variantProperty("velocity") = m_ui->velocity->value();
+ springFollow.variantProperty("spring") = m_ui->spring->value();
+ springFollow.variantProperty("damping") = m_ui->damping->value();
+ springFollow.bindingProperty("source") = m_ui->source->text();
+ }
+}
+
+void BehaviorDialog::reject()
+{
+ QDialog::reject();
+}
+
+};
diff --git a/src/plugins/qmldesigner/components/propertyeditor/behaviordialog.h b/src/plugins/qmldesigner/components/propertyeditor/behaviordialog.h
new file mode 100644
index 0000000000..dfc763b4e3
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/behaviordialog.h
@@ -0,0 +1,98 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef BEHAVIORDIALOG_H
+#define BEHAVIORDIALOG_H
+
+#include <modelnode.h>
+#include <propertyeditorvalue.h>
+
+#include <QPushButton>
+#include <QDialog>
+#include <QWeakPointer>
+#include <QScopedPointer>
+#include <qml.h>
+
+#include "ui_behaviordialog.h"
+
+namespace QmlDesigner {
+
+class BehaviorDialog;
+
+class BehaviorWidget : public QPushButton
+{
+ Q_PROPERTY(PropertyEditorNodeWrapper* complexNode READ complexNode WRITE setComplexNode)
+
+ Q_OBJECT
+
+public:
+
+ BehaviorWidget();
+ BehaviorWidget(QWidget* parent);
+
+ ModelNode modelNode() const {return m_modelNode; }
+ QString propertyName() const {return m_propertyName; }
+
+ PropertyEditorNodeWrapper* complexNode() const;
+ void setComplexNode(PropertyEditorNodeWrapper* complexNode);
+
+public slots:
+ void buttonPressed(bool);
+
+private:
+ ModelNode m_modelNode;
+ QString m_propertyName;
+ PropertyEditorNodeWrapper* m_complexNode;
+ QScopedPointer<BehaviorDialog> m_BehaviorDialog;
+};
+
+class BehaviorDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ BehaviorDialog(QWidget *parent);
+ void setup(const ModelNode &node, const QString propertyName);
+
+public slots:
+ virtual void accept();
+ virtual void reject();
+
+
+private:
+ ModelNode m_modelNode;
+ QString m_propertyName;
+ QScopedPointer<Ui_BehaviorDialog> m_ui;
+};
+
+
+};
+
+QML_DECLARE_TYPE(QmlDesigner::BehaviorWidget);
+
+#endif// BEHAVIORDIALOG_H
diff --git a/src/plugins/qmldesigner/components/propertyeditor/behaviordialog.ui b/src/plugins/qmldesigner/components/propertyeditor/behaviordialog.ui
new file mode 100644
index 0000000000..d3c34b0391
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/behaviordialog.ui
@@ -0,0 +1,472 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>BehaviorDialog</class>
+ <widget class="QDialog" name="BehaviorDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>247</width>
+ <height>311</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="windowTitle">
+ <string>Dialog</string>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">QDialog {
+qlineargradient(spread:pad, x1:0.585, y1:0.0284091, x2:0.517, y2:1, stop:0 rgba(85, 85, 85, 255), stop:1 rgba(173, 173, 173, 255))
+}
+
+</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>Type:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="type">
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>Id:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="id">
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_5">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>Property Name:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLineEdit" name="propertyName">
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" colspan="2">
+ <widget class="QComboBox" name="comboBox">
+ <item>
+ <property name="text">
+ <string>Animation</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>SpringFollow</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="4" column="0" colspan="2">
+ <widget class="QGroupBox" name="groupBox">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>120</height>
+ </size>
+ </property>
+ <property name="title">
+ <string>Settings</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_4">
+ <item row="0" column="0">
+ <widget class="QStackedWidget" name="stackedWidget">
+ <property name="currentIndex">
+ <number>1</number>
+ </property>
+ <widget class="QWidget" name="page">
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_7">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>Duration:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QSpinBox" name="duration">
+ <property name="maximum">
+ <number>10000</number>
+ </property>
+ <property name="singleStep">
+ <number>10</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_8">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>Curve:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="curve">
+ <item>
+ <property name="text">
+ <string>easeNone</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>easeInQuad</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>easeOutQuad</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>easeInOutQuad</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>easeOutInQuad</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>easeInCubic</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>easeOutCubic</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>easeInOutCubic</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>easeOutInCubic</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>easeOutInBounce</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>easeInOutBounce</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>easeOutBounce</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>easeInBounce</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>easeOutInBack</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>easeInOutBack</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>easeOutBack</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>easeInBack</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>easeOutInElastic</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>easeInOutElastic</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>easeOutElastic</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>easeInElastic</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>easeOutInCirc</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>easeInOutCirc</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>easeOutCirc</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>easeInCirc</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>easeOutInExpo</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>easeInOutExpo</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>easeOutExpo</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>easeInExpo</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>easeOutInSine</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>easeInOutSine</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>easeOutSine</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>easeInSine</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="page_2">
+ <layout class="QGridLayout" name="gridLayout_3">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>Source:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="source"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_9">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>Velocity:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QDoubleSpinBox" name="velocity"/>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_10">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>Spring:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QDoubleSpinBox" name="spring"/>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="label_11">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>Damping:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QDoubleSpinBox" name="damping"/>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="5" column="0" colspan="2">
+ <widget class="QDialogButtonBox" name="ButtonGroup">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>ButtonGroup</sender>
+ <signal>accepted()</signal>
+ <receiver>BehaviorDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>ButtonGroup</sender>
+ <signal>rejected()</signal>
+ <receiver>BehaviorDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>comboBox</sender>
+ <signal>currentIndexChanged(int)</signal>
+ <receiver>stackedWidget</receiver>
+ <slot>setCurrentIndex(int)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>52</x>
+ <y>106</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>121</x>
+ <y>191</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/plugins/qmldesigner/components/propertyeditor/colorwidget.cpp b/src/plugins/qmldesigner/components/propertyeditor/colorwidget.cpp
new file mode 100644
index 0000000000..da1f0cd47b
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/colorwidget.cpp
@@ -0,0 +1,259 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "colorwidget.h"
+#include "qtcolorline.h"
+#include "qtcolorbutton.h"
+#include <QHBoxLayout>
+#include <QLabel>
+#include <QToolButton>
+#include <QGradient>
+#include <qtgradientdialog.h>
+#include <QtDebug>
+#include <modelnode.h>
+#include <abstractview.h>
+#include <nodeproperty.h>
+#include <nodelistproperty.h>
+#include <variantproperty.h>
+#include <qmlobjectnode.h>
+
+QML_DEFINE_TYPE(Bauhaus,1,0,ColorWidget,QmlDesigner::ColorWidget);
+
+namespace QmlDesigner {
+
+ColorWidget::ColorWidget(QWidget *parent) :
+ QWidget(parent),
+ m_label(new QLabel(this)),
+ m_colorButton(new QtColorButton(this)),
+ m_gradientButton(new QToolButton(this))
+{
+ QHBoxLayout *horizonalBoxLayout = new QHBoxLayout(this);
+
+ m_colorButton->setFixedWidth(30);
+ m_colorButton->setFixedHeight(20);
+ m_colorButton->setStyleSheet("");
+
+ m_gradientButton->setIcon(QIcon(":/images/gradient.png"));
+ m_gradientButton->setToolButtonStyle(Qt::ToolButtonIconOnly);
+ m_gradientButton->setFixedWidth(30);
+ m_gradientButton->setFixedHeight(20);
+ m_gradientButton->setStyleSheet("");
+
+ QFont f = m_label->font();
+ f.setBold(true);
+ m_label->setFont(f);
+ horizonalBoxLayout->addWidget(m_label);
+ horizonalBoxLayout->addWidget(m_colorButton);
+ horizonalBoxLayout->addWidget(m_gradientButton);
+ horizonalBoxLayout->addStretch();
+ horizonalBoxLayout->setSpacing(0);
+ horizonalBoxLayout->setMargin(0);
+ m_gradientButton->setCheckable(true);
+ m_gradientButton->setVisible(false);
+ connect(m_colorButton, SIGNAL(colorChanged(QColor)), this, SLOT(setColor(QColor)));
+ connect(m_gradientButton, SIGNAL(toggled(bool)), SLOT(openGradientEditor(bool)));
+}
+
+ColorWidget::~ColorWidget()
+{
+}
+
+QString ColorWidget::text() const
+{
+ if (m_label)
+ return m_label->text();
+ else
+ return QString();
+}
+
+QColor ColorWidget::color() const
+{
+ return m_color;
+}
+
+void ColorWidget::setColor(const QColor &color)
+{
+ if (m_color == color)
+ return;
+ bool valid = m_color.isValid();
+ m_color = color;
+ m_colorButton->setColor(color);
+ if (valid)
+ emit colorChanged(color);
+}
+
+QString ColorWidget::strColor() const
+{
+ return m_color.name();
+}
+
+void ColorWidget::setText(const QString &text)
+{
+ if (m_label)
+ m_label->setText(text);
+}
+
+ModelNode ColorWidget::gradientNode() const
+{
+ return m_gradientNode;
+}
+
+QGradient ColorWidget::gradient() const
+{
+ if (!m_gradientNode.isValid()) {
+ return QGradient();
+ }
+
+ if (m_gradientNode.type() != "Qt/Gradient") {
+ qWarning() << "ColorWidget: gradient node is of wrong type";
+ return QGradient();
+ }
+
+ QLinearGradient gradient;
+
+ QGradientStops oldStops;
+
+ //QVariantList stopList(m_modelState.nodeState(m_gradientNode).property("stops").value().toList()); /###
+ foreach (const ModelNode &stopNode, m_gradientNode.nodeListProperty("stops").toModelNodeList()) {
+ oldStops.append(QPair<qreal, QColor>(stopNode.variantProperty("position").value().toReal(), stopNode.variantProperty("color").value().value<QColor>()));
+ }
+ gradient.setStops(oldStops);
+
+ return gradient;
+}
+
+void ColorWidget::setGradientNode(const ModelNode &gradient)
+{
+ m_gradientNode = gradient;
+}
+
+bool ColorWidget::gradientButtonShown() const
+{
+ return m_gradientButton->isVisible();
+}
+
+void ColorWidget::setShowGradientButton(bool showButton)
+{
+ m_gradientButton->setVisible(showButton);
+ if (showButton && layout()->children().contains(m_gradientButton))
+ layout()->removeWidget(m_gradientButton);
+ else if (showButton && !layout()->children().contains(m_gradientButton) )
+ layout()->addWidget(m_gradientButton);
+}
+
+void ColorWidget::openGradientEditor(bool show)
+{
+ if (show && m_gradientDialog.isNull()) {
+ m_gradientDialog = new QtGradientDialog(this);
+ m_gradientDialog->setAttribute(Qt::WA_DeleteOnClose);
+ m_gradientDialog->setGradient(gradient());
+ m_gradientDialog->show();
+ connect(m_gradientDialog.data(), SIGNAL(accepted()), SLOT(updateGradientNode()));
+ connect(m_gradientDialog.data(), SIGNAL(destroyed()), SLOT(resetGradientButton()));
+ } else {
+ delete m_gradientDialog.data();
+ }
+}
+
+void ColorWidget::updateGradientNode()
+{
+ QGradient gradient(m_gradientDialog->gradient());
+
+ ModelNode gradientNode;
+
+ if (m_modelNode.hasNodeProperty("gradient"))
+ m_gradientNode = m_modelNode.nodeProperty("gradient").modelNode();
+
+ if (m_gradientNode.isValid() && m_gradientNode.type() == "Qt/Gradient") {
+ gradientNode = m_gradientNode;
+ } else {
+ if (m_modelNode.hasProperty("gradient")) {
+ m_modelNode.removeProperty("gradient");
+ }
+ gradientNode = m_modelNode.addChildNode("Qt/Gradient", 4, 6, "gradient");
+ m_gradientNode = gradientNode;
+ }
+
+ if (QmlObjectNode(m_gradientNode).isInBaseState()) {
+
+ NodeListProperty stops(gradientNode.nodeListProperty("stops"));
+
+ foreach (ModelNode node, stops.allSubNodes())
+ node.destroy();
+
+ if (gradientNode.hasProperty("stops"))
+ gradientNode.removeProperty("stops");
+
+ foreach(const QGradientStop &stop, gradient.stops()) {
+ QList<QPair<QString, QVariant> > propertyList;
+
+ qreal p = stop.first * 100;
+ int ip = qRound(p);
+ p = qreal(ip) / 100;
+
+ ModelNode gradientStop(gradientNode.view()->createModelNode("Qt/GradientStop", 4, 6));
+ stops.reparentHere(gradientStop);
+ gradientStop.variantProperty("position").setValue(p);
+ gradientStop.variantProperty("color").setValue(stop.second.name());
+ }
+ } else { //not in base state
+ //## TODO
+ }
+}
+
+void ColorWidget::resetGradientButton()
+{
+ m_gradientButton->setChecked(false);
+}
+
+void ColorWidget::setModelNode(const ModelNode &modelNode)
+{
+ if (m_modelNode != modelNode) {
+ m_modelNode = modelNode;
+ emit modelNodeChanged();
+ }
+}
+
+ModelNode ColorWidget::modelNode() const
+{
+ return m_modelNode;
+}
+
+PropertyEditorNodeWrapper* ColorWidget::complexGradientNode() const
+{
+ return m_complexGradientNode;
+}
+
+void ColorWidget::setComplexGradientNode(PropertyEditorNodeWrapper* complexNode)
+{
+ m_complexGradientNode = complexNode;
+ setModelNode(complexNode->parentModelNode());
+}
+
+}
diff --git a/src/plugins/qmldesigner/components/propertyeditor/colorwidget.h b/src/plugins/qmldesigner/components/propertyeditor/colorwidget.h
new file mode 100644
index 0000000000..c508096694
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/colorwidget.h
@@ -0,0 +1,108 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef COLORWIDGET_H
+#define COLORWIDGET_H
+
+#include <QWeakPointer>
+#include <QtGui/QWidget>
+#include <QLabel>
+#include <modelnode.h>
+#include <qml.h>
+#include <propertyeditorvalue.h>
+
+
+class QtColorButton;
+class QToolButton;
+class QtGradientDialog;
+
+namespace QmlDesigner {
+
+class ColorWidget : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
+ Q_PROPERTY(QColor strColor READ strColor)
+ Q_PROPERTY(QString text READ text WRITE setText)
+ Q_PROPERTY(QmlDesigner::ModelNode gradient READ gradientNode WRITE setGradientNode NOTIFY gradientNodeChanged)
+ Q_PROPERTY(bool showGradientButton READ gradientButtonShown WRITE setShowGradientButton)
+ Q_PROPERTY(QmlDesigner::ModelNode modelNode READ modelNode WRITE setModelNode NOTIFY modelNodeChanged)
+ Q_PROPERTY(PropertyEditorNodeWrapper* complexGradientNode READ complexGradientNode WRITE setComplexGradientNode)
+public:
+
+ ColorWidget(QWidget *parent = 0);
+ ~ColorWidget();
+
+ QColor color() const;
+ QString text() const;
+ QString strColor() const;
+ void setText(const QString &text);
+ ModelNode gradientNode() const;
+ bool gradientButtonShown() const;
+ void setShowGradientButton(bool showButton);
+
+ void setModelNode(const ModelNode &modelNode);
+ ModelNode modelNode() const;
+
+ PropertyEditorNodeWrapper* complexGradientNode() const;
+ void setComplexGradientNode(PropertyEditorNodeWrapper* complexNode);
+
+public slots:
+ void setColor(const QColor &color);
+ void setGradientNode(const QmlDesigner::ModelNode &gradient);
+
+signals:
+ void colorChanged(const QColor &color);
+ void gradientNodeChanged();
+ void modelStateChanged();
+ void modelNodeChanged();
+
+protected:
+ QGradient gradient() const;
+
+private slots:
+ void openGradientEditor(bool show);
+ void updateGradientNode();
+ void resetGradientButton();
+private:
+ QColor m_color;
+ ModelNode m_gradientNode;
+ ModelNode m_modelNode;
+ QWeakPointer<QtGradientDialog> m_gradientDialog;
+ QLabel *m_label;
+ QtColorButton *m_colorButton;
+ QToolButton *m_gradientButton;
+ PropertyEditorNodeWrapper* m_complexGradientNode;
+};
+
+}
+
+QML_DECLARE_TYPE(QmlDesigner::ColorWidget);
+
+#endif
diff --git a/src/plugins/qmldesigner/components/propertyeditor/filewidget.cpp b/src/plugins/qmldesigner/components/propertyeditor/filewidget.cpp
new file mode 100644
index 0000000000..a63d0889d0
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/filewidget.cpp
@@ -0,0 +1,87 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "filewidget.h"
+#include <QHBoxLayout>
+#include <QFont>
+#include <QFileDialog>
+#include <QDebug>
+
+
+QT_BEGIN_NAMESPACE
+
+FileWidget::FileWidget(QWidget *parent) : QWidget(parent)
+{
+ m_pushButton = new QPushButton(this);
+ m_label = new QLabel(this);
+ m_lineEdit = new QLineEdit(this);
+ QHBoxLayout *layout = new QHBoxLayout(this);
+ setLayout(layout);
+ layout->addWidget(m_label);
+ layout->addWidget(m_lineEdit);
+ layout->addWidget(m_pushButton);
+ m_pushButton->setText("...");
+ QFont f = m_label->font();
+ f.setBold(true);
+ m_label->setFont(f);
+ connect(m_lineEdit, SIGNAL(editingFinished()), this, SLOT(lineEditChanged()));
+ connect(m_pushButton, SIGNAL(pressed()), this, SLOT(buttonPressed()));
+}
+
+FileWidget::~FileWidget()
+{
+}
+
+
+void FileWidget::lineEditChanged()
+{
+ setFileNameStr(m_lineEdit->text());
+}
+
+void FileWidget::buttonPressed()
+{
+ setFileNameStr(QFileDialog::getOpenFileName());
+}
+
+void FileWidget::setFileNameStr(const QString &fileName)
+{
+ setFileName(QUrl(fileName));
+}
+void FileWidget::setFileName(const QUrl &fileName)
+{
+ if (fileName == m_fileName)
+ return;
+
+ m_fileName = fileName;
+ m_lineEdit->setText(fileName.toString());
+ emit fileNameChanged(fileName);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/plugins/qmldesigner/components/propertyeditor/filewidget.h b/src/plugins/qmldesigner/components/propertyeditor/filewidget.h
new file mode 100644
index 0000000000..318fc4772c
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/filewidget.h
@@ -0,0 +1,89 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+
+#ifndef FILEWIDGET_H
+#define FILEWIDGET_H
+
+#include <QtGui/QWidget>
+#include <QLabel>
+#include <QPushButton>
+#include <QLineEdit>
+#include <QUrl>
+
+QT_BEGIN_NAMESPACE
+
+class FileWidget : public QWidget
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString text READ text WRITE setText)
+ Q_PROPERTY(QString fileName READ fileName WRITE setFileNameStr NOTIFY fileNameChanged)
+public:
+
+ FileWidget(QWidget *parent = 0);
+ ~FileWidget();
+
+ QString fileName() const
+ { return m_fileName.toString(); }
+
+ void setText(const QString &text)
+ {
+ m_label->setText(text);
+ }
+
+ QString text() const
+ {
+ return m_label->text();
+ }
+
+
+public slots:
+ void setFileName(const QUrl &fileName);
+ void setFileNameStr(const QString &fileName);
+ void buttonPressed();
+ void lineEditChanged();
+
+signals:
+ void fileNameChanged(const QUrl &fileName);
+
+protected:
+
+private:
+ QLabel* m_label;
+ QPushButton *m_pushButton;
+ QLineEdit *m_lineEdit;
+ QUrl m_fileName;
+
+};
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/plugins/qmldesigner/components/propertyeditor/fontwidget.cpp b/src/plugins/qmldesigner/components/propertyeditor/fontwidget.cpp
new file mode 100644
index 0000000000..8b2039dd6c
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/fontwidget.cpp
@@ -0,0 +1,172 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "fontwidget.h"
+#include <QPushButton>
+#include <QLabel>
+#include <QHBoxLayout>
+#include <QFontDialog>
+#include <QApplication>
+#include <QComboBox>
+#include <QLabel>
+
+QML_DEFINE_TYPE(Bauhaus,1,0,FontWidget,QmlDesigner::FontWidget);
+
+namespace QmlDesigner {
+
+FontWidget::FontWidget(QWidget *parent)
+ : QWidget(parent),
+ m_label(new QLabel(this)),
+ m_fontButton(new QPushButton("ABC..", this))
+{
+ QHBoxLayout *horizonalBoxLayout = new QHBoxLayout(this);
+
+ horizonalBoxLayout->addWidget(m_label);
+ horizonalBoxLayout->addWidget(m_fontButton);
+ m_fontButton->setMinimumHeight(20);
+ m_fontButton->setCheckable(true);
+ connect(m_fontButton, SIGNAL(toggled(bool)), SLOT(openFontEditor(bool)));
+}
+
+FontWidget::~FontWidget()
+{
+}
+
+void FontWidget::openFontEditor(bool show)
+{
+ if (show && m_fontDialog.isNull()) {
+ m_fontDialog = new QFontDialog();
+ m_fontDialog->setAttribute(Qt::WA_DeleteOnClose);
+ m_fontDialog->setCurrentFont(m_font);
+ QComboBox *comboBox = m_fontDialog->findChild<QComboBox*>();
+ QList<QLabel*> labels = m_fontDialog->findChildren<QLabel*>();
+ foreach (QLabel *label, labels)
+ if (label->buddy() == comboBox)
+ label->hide();
+ comboBox->hide();
+ m_fontDialog->show();
+ connect(m_fontDialog.data(), SIGNAL(accepted()), SLOT(updateFont()));
+ connect(m_fontDialog.data(), SIGNAL(destroyed(QObject*)), SLOT(resetFontButton()));
+ } else {
+ delete m_fontDialog.data();
+ }
+}
+
+void FontWidget::updateFont()
+{
+ QFont font(m_fontDialog->currentFont());
+ setFamily(font.family());
+ setItalic(font.italic());
+ setBold(font.bold());
+ setFontSize(font.pointSizeF());
+ emit dataFontChanged();
+}
+
+void FontWidget::resetFontButton()
+{
+ m_fontButton->setChecked(false);
+}
+
+QString FontWidget::text() const
+{
+ return m_label->text();
+}
+
+void FontWidget::setText(const QString &text)
+{
+ m_label->setText(text);
+}
+
+QString FontWidget::family() const
+{
+ return m_font.family();
+}
+
+void FontWidget::setFamily(const QString &fontFamily)
+{
+ if (fontFamily != m_font.family()) {
+ m_font.setFamily(fontFamily);
+ emit familyChanged();
+ }
+}
+
+bool FontWidget::isBold() const
+{
+ return m_font.bold();
+}
+
+void FontWidget::setBold(bool isBold)
+{
+ if (m_font.bold() != isBold) {
+ m_font.setBold(isBold);
+ emit boldChanged();
+ }
+}
+
+bool FontWidget::isItalic() const
+{
+ return m_font.italic();
+}
+
+void FontWidget::setItalic(bool isItalic)
+{
+ if (m_font.italic() != isItalic) {
+ m_font.setItalic(isItalic);
+ emit italicChanged();
+ }
+}
+
+
+QFont FontWidget::font() const
+{
+ return m_font;
+}
+
+void FontWidget::setFont(QFont font)
+{
+ if (m_font != font) {
+ m_font = font;
+ emit dataFontChanged();
+ }
+}
+
+qreal FontWidget::fontSize() const
+{
+ return m_font.pointSizeF();
+}
+
+void FontWidget::setFontSize(qreal size)
+{
+ if (m_font.pointSizeF() != size) {
+ m_font.setPointSizeF(size);
+ emit fontSizeChanged();
+ }
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/propertyeditor/fontwidget.h b/src/plugins/qmldesigner/components/propertyeditor/fontwidget.h
new file mode 100644
index 0000000000..5bc8afbf82
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/fontwidget.h
@@ -0,0 +1,100 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef FONTWIDGET_H
+#define FONTWIDGET_H
+
+#include <QWeakPointer>
+#include <QWidget>
+#include <qml.h>
+
+
+
+class QLabel;
+class QPushButton;
+class QFontDialog;
+
+namespace QmlDesigner {
+
+class FontWidget : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(QString text READ text WRITE setText)
+ Q_PROPERTY(QString family READ family WRITE setFamily NOTIFY familyChanged)
+ Q_PROPERTY(bool bold READ isBold WRITE setBold NOTIFY boldChanged)
+ Q_PROPERTY(bool italic READ isItalic WRITE setItalic NOTIFY italicChanged)
+ Q_PROPERTY(qreal fontSize READ fontSize WRITE setFontSize NOTIFY fontSizeChanged)
+ Q_PROPERTY(QFont dataFont READ font WRITE setFont NOTIFY dataFontChanged)
+
+public:
+ FontWidget(QWidget *parent = 0);
+ ~FontWidget();
+
+ QString text() const;
+ void setText(const QString &text);
+
+ QString family() const;
+ void setFamily(const QString &fontFamily);
+
+ bool isBold() const;
+ void setBold(bool isBold);
+
+ bool isItalic() const;
+ void setItalic(bool isItalic);
+
+ qreal fontSize() const;
+ void setFontSize(qreal size);
+
+ QFont font() const;
+ void setFont(QFont size);
+
+signals:
+ void familyChanged();
+ void boldChanged();
+ void italicChanged();
+ void fontSizeChanged();
+ void dataFontChanged();
+
+private slots:
+ void openFontEditor(bool show);
+ void updateFont();
+ void resetFontButton();
+
+private: //variables
+ QFont m_font;
+ QLabel *m_label;
+ QPushButton *m_fontButton;
+ QWeakPointer<QFontDialog> m_fontDialog;
+};
+
+} // namespace QmlDesigner
+
+QML_DECLARE_TYPE(QmlDesigner::FontWidget);
+
+#endif // FONTWIDGET_H
diff --git a/src/plugins/qmldesigner/components/propertyeditor/genericpropertieswidget.cpp b/src/plugins/qmldesigner/components/propertyeditor/genericpropertieswidget.cpp
new file mode 100644
index 0000000000..a76d73627f
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/genericpropertieswidget.cpp
@@ -0,0 +1,380 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <QSet>
+#include <QtDebug>
+#include <QWidget>
+#include <QApplication>
+
+#include "qteditorfactory.h"
+#include "qtpropertymanager.h"
+#include "qttreepropertybrowser.h"
+#include "qtvariantproperty.h"
+
+#include "genericpropertieswidget.h"
+#include "nodemetainfo.h"
+#include "propertymetainfo.h"
+
+#include "modelutilities.h"
+
+using namespace QmlDesigner;
+
+GenericPropertiesWidget::GenericPropertiesWidget(QWidget* parent):
+ AbstractView(parent),
+ editor(new QtTreePropertyBrowser()),
+ variantManager(new QtVariantPropertyManager()),
+ enumManager(new QtEnumPropertyManager())
+{
+}
+
+QWidget* GenericPropertiesWidget::createPropertiesPage()
+{
+ editor->setRootIsDecorated(false);
+
+ QtEnumEditorFactory *enumFactory = new QtEnumEditorFactory();
+ editor->setFactoryForManager(enumManager, enumFactory);
+
+ QtVariantEditorFactory *variantFactory = new QtVariantEditorFactory();
+ editor->setFactoryForManager(variantManager, variantFactory);
+
+ reconnectEditor();
+
+ return editor;
+}
+
+void GenericPropertiesWidget::selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
+ const QList<ModelNode> &lastSelectedNodeList)
+{
+ Q_UNUSED(lastSelectedNodeList);
+
+ if (selectedNode.isValid() && selectedNodeList.contains(selectedNode))
+ return;
+
+ if (selectedNodeList.isEmpty())
+ select(ModelNode());
+ else
+ select(selectedNodeList.at(0));
+}
+
+void GenericPropertiesWidget::select(const ModelNode& node)
+{
+ if (!node.isValid() || (selectedNode.isValid() && node == selectedNode))
+ return;
+
+ selectedNode = node;
+
+ disconnectEditor();
+
+ editor->setUpdatesEnabled(false);
+ editor->clear();
+ buildPropertyEditorItems();
+ editor->setUpdatesEnabled(true);
+
+ reconnectEditor();
+}
+
+void GenericPropertiesWidget::disconnectEditor()
+{
+ disconnect(variantManager, SIGNAL(propertyChanged(QtProperty*)), this, SLOT(propertyChanged(QtProperty*)));
+ disconnect(enumManager, SIGNAL(propertyChanged(QtProperty*)), this, SLOT(propertyChanged(QtProperty*)));
+}
+
+void GenericPropertiesWidget::reconnectEditor()
+{
+ connect(enumManager, SIGNAL(propertyChanged(QtProperty*)), this, SLOT(propertyChanged(QtProperty*)));
+ connect(variantManager, SIGNAL(propertyChanged(QtProperty*)), this, SLOT(propertyChanged(QtProperty*)));
+}
+
+QtProperty* GenericPropertiesWidget::addVariantProperty(const PropertyMetaInfo& propertyMetaInfo,
+ const QHash<QString, NodeProperty>& propertiesWithValues,
+ const NodeInstance& instance)
+{
+// qDebug() << "\t\tAdding variant property" << propertyMetaInfo.name() << "...";
+
+ if (variantManager->isPropertyTypeSupported(propertyMetaInfo.variantTypeId())) {
+ QtVariantProperty* item = variantManager->addProperty(propertyMetaInfo.variantTypeId(), propertyMetaInfo.name());
+
+ if (propertiesWithValues.contains(propertyMetaInfo.name())) {
+ NodeProperty nodeProperty(propertiesWithValues[propertyMetaInfo.name()]);
+
+ if (nodeProperty.isValid()) {
+ item->setValue(nodeProperty.value());
+ item->setModified(true);
+ }
+ }
+
+ if (!item->isModified()) {
+ item->setValue(instance.property(propertyMetaInfo.name())); //TODO fix this
+ }
+
+ return item;
+ } else {
+// qDebug() << "\t\t"
+// << "Property type not supported for property"
+// << propertyMetaInfo.name()
+// << ", type name:" << propertyMetaInfo.variantTypeId()
+// << "(" << propertyMetaInfo.type() << ")";
+ return 0;
+ }
+}
+
+QtProperty* GenericPropertiesWidget::addEnumProperty(const PropertyMetaInfo& propertyMetaInfo,
+ const QHash<QString, NodeProperty>& propertiesWithValues,
+ const NodeInstance& instance)
+{
+// qDebug() << "\t\tAdding enum property" << propertyMetaInfo.name() << "...";
+
+ QtProperty* item = enumManager->addProperty(propertyMetaInfo.name());
+
+ QList<QString> elementNames(propertyMetaInfo.enumerator().elementNames());
+ enumManager->setEnumNames(item, elementNames);
+
+ if (propertiesWithValues.contains(propertyMetaInfo.name())) {
+ NodeProperty nodeProperty(propertiesWithValues[propertyMetaInfo.name()]);
+
+ int selectionIndex = elementNames.indexOf(nodeProperty.value().toString());
+ if (selectionIndex != -1) {
+ enumManager->setValue(item, selectionIndex);
+ item->setModified(true);
+ }
+ }
+
+ if (!item->isModified()) {
+ int selectionIndex = elementNames.indexOf(instance.property(propertyMetaInfo.name()).toString()); // TODO Fix this
+ if (selectionIndex != -1) {
+ enumManager->setValue(item, selectionIndex);
+ }
+ }
+
+ return item;
+}
+
+QtProperty* GenericPropertiesWidget::addFlagProperty(const PropertyMetaInfo &/*propertyMetaInfo*/,
+ const QHash<QString, NodeProperty> &/*propertiesWithValues*/,
+ const NodeInstance &/*instance*/)
+{
+// qDebug() << "\t\tFlags are not yet supported. (Property: " << propertyMetaInfo.name() << ")";
+
+ return 0;
+}
+
+QtProperty* GenericPropertiesWidget::addProperties(const NodeMetaInfo& nodeMetaInfo,
+ const QHash<QString, NodeProperty>& propertiesWithValues,
+ const NodeInstance& instance)
+{
+// qDebug() << "\tAdding" << nodeMetaInfo.properties().size()
+// << "properties for (super)node with type" << nodeMetaInfo.className() << "...";
+
+ QtProperty* groupItem = variantManager->addProperty(QtVariantPropertyManager::groupTypeId(),
+ nodeMetaInfo.typeName());
+
+ foreach (PropertyMetaInfo propMetaInfo, nodeMetaInfo.properties()) {
+ if (!propMetaInfo.isVisibleToPropertyEditor())
+ continue;
+
+ QtProperty* property = 0;
+
+ if (propMetaInfo.isEnumType()) {
+ property = addEnumProperty(propMetaInfo, propertiesWithValues, instance);
+ } else if (propMetaInfo.isFlagType()) {
+ property = addFlagProperty(propMetaInfo, propertiesWithValues, instance);
+ } else {
+ property = addVariantProperty(propMetaInfo, propertiesWithValues, instance);
+ }
+
+ if (property) {
+ groupItem->addSubProperty(property);
+ }
+ }
+
+ return groupItem;
+}
+
+void GenericPropertiesWidget::buildPropertyEditorItems()
+{
+ if (!selectedNode.isValid()) {
+ return;
+ }
+
+// qDebug() << "buildPropertyEditorItems for node" << selectedNode.name() << "...";
+
+ QList<NodeMetaInfo> allClasses;
+ allClasses.append(selectedNode.metaInfo());
+ allClasses += selectedNode.metaInfo().superClasses();
+// qDebug() << "\tNode has" << allClasses.size() << "(super) classes";
+
+ QHash<QString, NodeProperty> propertiesWithValues;
+ foreach (const NodeProperty & nodeProperty, selectedNode.properties()) {
+ propertiesWithValues[nodeProperty.name()] = nodeProperty;
+ }
+
+// qDebug() << "\tNode has" << propertiesWithValues.size() << "properties set.";
+
+// NodeInstance instance = ModelUtilities::instanceForNode(selectedNode);
+//
+// foreach (const NodeMetaInfo &info, allClasses) {
+// // FIXME: the add property is quite (too) expensive!
+// editor->addProperty(addProperties(info, propertiesWithValues, instance));
+// }
+}
+
+static bool nodeHasProperty(const ModelNode& node, const QString& name)
+{
+ if (node.metaInfo().hasProperty(name))
+ return true;
+
+ foreach (const NodeMetaInfo& info, node.metaInfo().superClasses()) {
+ if (info.hasProperty(name))
+ return true;
+ }
+
+ return false;
+}
+
+void GenericPropertiesWidget::propertyChanged(QtProperty* property)
+{
+// qDebug() << "property" << property->propertyName() << "changed...";
+
+ QtVariantProperty* variantProperty = dynamic_cast<QtVariantProperty*>(property);
+
+ if (variantProperty) {
+// qDebug() << "\tnew value: " << variantProperty->value();
+
+ if (selectedNode.property(property->propertyName()).value() == variantProperty->value()) {
+// qDebug() << "\twhich is the same as the old one, so we'll forget about it.";
+ } else {
+ if (nodeHasProperty(selectedNode, property->propertyName())) {
+ selectedNode.setPropertyValue(property->propertyName(), variantProperty->value());
+
+ if (!property->isModified())
+ property->setModified(true);
+ } else {
+// qDebug() << "--- property " << property->propertyName() << "ignored: it doesn't exist in the metadata.";
+ }
+ }
+ } else {
+// qDebug("\tEep: changed property is not a variant property");
+ }
+}
+
+void GenericPropertiesWidget::modelAttached(Model *model)
+{
+ AbstractView::modelAttached(model);
+}
+
+void GenericPropertiesWidget::nodeCreated(const ModelNode&)
+{
+}
+
+void GenericPropertiesWidget::nodeAboutToBeRemoved(const ModelNode &removedNode)
+{
+ if (selectedNode.isValid() && removedNode.isValid() && selectedNode == removedNode) {
+ select(selectedNode.parentNode());
+ }
+}
+
+void GenericPropertiesWidget::propertyAdded(const NodeState& state, const NodeProperty&)
+{
+ if (selectedNode.isValid() && state.isValid() && selectedNode == state.modelNode()) {
+ select(state.modelNode());
+ }
+}
+
+void GenericPropertiesWidget::propertyAboutToBeRemoved(const NodeState& /* state */, const NodeProperty&)
+{
+}
+
+void GenericPropertiesWidget::nodeReparented(const ModelNode &node, const ModelNode &oldParent, const ModelNode &newParent)
+{
+ Q_UNUSED(node);
+ Q_UNUSED(oldParent);
+ Q_UNUSED(newParent);
+}
+
+void GenericPropertiesWidget::propertyValueChanged(const NodeState& state, const NodeProperty& property,
+ const QVariant&, const QVariant& )
+{
+ if (!selectedNode.isValid() || selectedNode != state.modelNode())
+ return;
+
+ disconnectEditor();
+
+ ModelNode node(state.modelNode());
+
+ foreach (QtProperty* qtProperty, enumManager->properties()) {
+ if (qtProperty->propertyName() == property.name()) {
+ QList<QString> elementNames = node.property(property.name()).metaInfo().enumerator().elementNames();
+ int selectionIndex = elementNames.indexOf(property.value().toString());
+ if (selectionIndex != -1) {
+ enumManager->setValue(qtProperty, selectionIndex);
+ qtProperty->setModified(true);
+ }
+
+ reconnectEditor();
+ return;
+ }
+ }
+
+ foreach (QtProperty* qtProperty, variantManager->properties()) {
+ if (qtProperty->propertyName() == property.name()) {
+ (dynamic_cast<QtVariantProperty*>(qtProperty))->setValue(property.value());
+ qtProperty->setModified(true);
+
+ reconnectEditor();
+ return;
+ }
+ }
+
+ reconnectEditor();
+}
+
+void GenericPropertiesWidget::modelStateAboutToBeRemoved(const ModelState &/*modelState*/)
+{
+// TODO: implement
+}
+
+void GenericPropertiesWidget::modelStateAdded(const ModelState &/*modelState*/)
+{
+// TODO: implement
+}
+
+void GenericPropertiesWidget::nodeStatesAboutToBeRemoved(const QList<NodeState> &/*nodeStateList*/)
+{
+// TODO: implement
+}
+
+void GenericPropertiesWidget::nodeStatesAdded(const QList<NodeState> &/*nodeStateList*/)
+{
+// TODO: implement
+}
+
+void GenericPropertiesWidget::anchorsChanged(const NodeState &/*nodeState*/)
+{
+// TODO: implement
+}
diff --git a/src/plugins/qmldesigner/components/propertyeditor/genericpropertieswidget.h b/src/plugins/qmldesigner/components/propertyeditor/genericpropertieswidget.h
new file mode 100644
index 0000000000..1b577bd479
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/genericpropertieswidget.h
@@ -0,0 +1,96 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef PropertyView_h
+#define PropertyView_h
+
+#include <QTabWidget>
+
+#include <modelnode.h>
+#include <widgetqueryview.h>
+
+
+class QtProperty;
+
+namespace QmlDesigner {
+
+class GenericPropertiesWidget: public AbstractView
+{
+ Q_OBJECT
+
+public:
+ GenericPropertiesWidget(QWidget *parent = 0);
+ QWidget* createPropertiesPage();
+ void selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
+ const QList<ModelNode> &lastSelectedNodeList);
+
+ virtual void modelAttached(Model *model);
+ virtual void nodeCreated(const ModelNode &createdNode);
+ virtual void nodeAboutToBeRemoved(const ModelNode &removedNode);
+ virtual void propertyAdded(const NodeState& state, const NodeProperty& property);
+ virtual void propertyAboutToBeRemoved(const NodeState &state, const NodeProperty &property);
+ virtual void nodeReparented(const ModelNode &node, const ModelNode &oldParent, const ModelNode &newParent);
+ virtual void propertyValueChanged(const NodeState& state, const NodeProperty& property,
+ const QVariant& newValue, const QVariant& oldValue);
+
+ void modelStateAboutToBeRemoved(const ModelState &modelState);
+ void modelStateAdded(const ModelState &modelState);
+
+ void nodeStatesAboutToBeRemoved(const QList<NodeState> &nodeStateList);
+ void nodeStatesAdded(const QList<NodeState> &nodeStateList);
+
+ void anchorsChanged(const NodeState &nodeState);
+
+public slots:
+ void select(const ModelNode& node);
+
+private slots:
+ void propertyChanged(class QtProperty* property);
+
+private:
+ void buildPropertyEditorItems();
+ QtProperty* addVariantProperty(const PropertyMetaInfo& propertyMetaInfo, const QHash<QString, NodeProperty>& propertiesWithValues, const NodeInstance& instance);
+ QtProperty* addEnumProperty(const PropertyMetaInfo& propertyMetaInfo, const QHash<QString, NodeProperty>& propertiesWithValues, const NodeInstance& instance);
+ QtProperty* addFlagProperty(const PropertyMetaInfo& propertyMetaInfo, const QHash<QString, NodeProperty>& propertiesWithValues, const NodeInstance& instance);
+ QtProperty* addProperties(const NodeMetaInfo& nodeMetaInfo, const QHash<QString, NodeProperty>& propertiesWithValues, const NodeInstance& instance);
+
+ void disconnectEditor();
+ void reconnectEditor();
+
+private:
+ class QtTreePropertyBrowser *editor;
+ class QtVariantPropertyManager* variantManager;
+ class QtEnumPropertyManager* enumManager;
+
+ ModelNode selectedNode;
+};
+
+}
+
+#endif // PropertyView_h
diff --git a/src/plugins/qmldesigner/components/propertyeditor/gradientdialog.cpp b/src/plugins/qmldesigner/components/propertyeditor/gradientdialog.cpp
new file mode 100644
index 0000000000..a763426e27
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/gradientdialog.cpp
@@ -0,0 +1,353 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "gradientdialog.h"
+#include "ui_gradientdialog.h"
+#include <QtGui/QPushButton>
+
+QT_BEGIN_NAMESPACE
+
+class GradientDialogPrivate
+{
+ GradientDialog *q_ptr;
+ Q_DECLARE_PUBLIC(GradientDialog)
+public:
+
+ void slotAboutToShowDetails(bool details, int extensionWidthHint);
+
+ Ui::GradientDialog m_ui;
+};
+
+void GradientDialogPrivate::slotAboutToShowDetails(bool details, int extensionWidthHint)
+{
+ if (details) {
+ q_ptr->resize(q_ptr->size() + QSize(extensionWidthHint, 0));
+ } else {
+ q_ptr->setMinimumSize(1, 1);
+ q_ptr->resize(q_ptr->size() - QSize(extensionWidthHint, 0));
+ q_ptr->setMinimumSize(0, 0);
+ }
+}
+
+/*!
+ \class GradientDialog
+
+ \brief The GradientDialog class provides a dialog for specifying gradients.
+
+ The gradient dialog's function is to allow users to edit gradients.
+ For example, you might use this in a drawing program to allow the user to set the brush gradient.
+
+ \table
+ \row
+ \o \inlineimage qtgradientdialog.png
+ \o \inlineimage qtgradientdialogextension.png
+ \header
+ \o Details extension hidden
+ \o Details extension visible
+ \endtable
+
+ Starting from the top of the dialog there are several buttons:
+
+ \image qtgradientdialogtopbuttons.png
+
+ The first three buttons allow for changing a type of the gradient (QGradient::Type), while the second three allow for
+ changing spread of the gradient (QGradient::Spread). The last button shows or hides the details extension of the dialog.
+ Conceptually the default view with hidden details provides the full functional control over gradient editing.
+ The additional extension with details allows to set gradient's parameters more precisely. The visibility
+ of extension can be controlled by detailsVisible property. Moreover, if you don't want the user to
+ switch on or off the visibility of extension you can set the detailsButtonVisible property to false.
+
+ Below top buttons there is an area where edited gradient is interactively previewed.
+ In addition the user can edit gradient type's specific parameters directly in this area by dragging
+ appropriate handles.
+
+ \table
+ \row
+ \o \inlineimage qtgradientdialoglineareditor.png
+ \o \inlineimage qtgradientdialogradialeditor.png
+ \o \inlineimage qtgradientdialogconicaleditor.png
+ \header
+ \o Editing linear type
+ \o Editing radial type
+ \o Editing conical type
+ \row
+ \o The user can change the start and final point positions by dragging the circular handles.
+ \o The user can change the center and focal point positions by dragging the circular handles
+ and can change the gradient's radius by dragging horizontal or vertical line.
+ \o The user can change the center point by dragging the circular handle
+ and can change the gradient's angle by dragging the big wheel.
+ \endtable
+
+ In the middle of the dialog there is an area where the user can edit gradient stops.
+
+ \table
+ \row
+ \o \inlineimage qtgradientdialogstops.png
+ \o \inlineimage qtgradientdialogstopszoomed.png
+ \endtable
+
+ The top part of this area contains stop handles, and bottom part shows the preview of gradient stops path.
+ In order to create a new gradient stop double click inside the view over the desired position.
+ If you double click on existing stop handle in the top part of the view, clicked handle will be duplicated
+ (duplicate will contain the same color).
+ The stop can be activated by clicking on its handle. You can activate previous or next stop by pressing
+ left or right key respectively. To jump to the first or last stop press home or end key respectively.
+ The gradient stops editor supports multiselection.
+ Clicking a handle holding the shift modifier key down will select a range of stops between
+ the active stop and clicked one. Clicking a handle holding control modifier key down will remove from or
+ add to selection the clicked stop depending if it was or wasn't already selected respectively.
+ Multiselection can also be created using rubberband (by pressing the left mouse button outside
+ of any handle and dragging).
+ Sometimes it's hard to select a stop because its handle can be partially covered by other handle.
+ In that case the user can zoom in the view by spinning mouse wheel.
+ The selected stop handles can be moved by drag & drop. In order to remove selected stops press delete key.
+ For convenience context menu is provided with the following actions:
+
+ \list
+ \o New Stop - creates a new gradient stop
+ \o Delete - removes the active and all selected stops
+ \o Flip All - mirrors all stops
+ \o Select All - selects all stops
+ \o Zoom In - zooms in
+ \o Zoom Out - zooms out
+ \o Zoom All - goes back to original 100% zoom
+ \endlist
+
+ The bottom part of the GradientDialog contains a set of widgets allowing to control the color of
+ the active and selected stops.
+
+ \table
+ \row
+ \o \inlineimage qtgradientdialogcolorhsv.png
+ \o \inlineimage qtgradientdialogcolorrgb.png
+ \endtable
+
+
+ The color button shows the color of the active gradient stop. It also allows for choosing
+ a color from standard color dialog and applying it to the
+ active stop and all selected stops. It's also possible to drag a color directly from the color button
+ and to drop it in gradient stops editor at desired position (it will create new stop with dragged color)
+ or at desired stop handle (it will change the color of that handle).
+
+ To the right of color button there is a set of 2 radio buttons which allows to switch between
+ HVS and RGB color spec.
+
+ Finally there are 4 color sliders working either in HSVA (hue saturation value alpha) or
+ RGBA (red green blue alpha) mode, depending on which radio button is chosen. The radio buttons
+ can be controlled programatically by spec() and setSpec() methods. The sliders show the
+ color of the active stop. By double clicking inside color slider you can set directly the desired color.
+ Changes of slider's are applied to stop selection in the way that the color
+ component being changed is applied to stops in selection only, while other components
+ remain unchanged in selected stops (e.g. when the user is changing the saturation,
+ new saturation is applied to selected stops preventing original hue, value and alpha in multiselection).
+
+ The convenient static functions getGradient() provide modal gradient dialogs, e.g.:
+
+ \snippet doc/src/snippets/code/tools_shared_qtgradienteditor_qtgradientdialog.cpp 0
+
+ In order to have more control over the properties of GradientDialog use
+ standard QDialog::exec() method:
+
+ \snippet doc/src/snippets/code/tools_shared_qtgradienteditor_qtgradientdialog.cpp 1
+
+ \sa {Gradient View Example}
+*/
+
+/*!
+ Constructs a gradient dialog with \a parent as parent widget.
+*/
+
+GradientDialog::GradientDialog(QWidget *parent)
+ : QDialog(parent), d_ptr(new GradientDialogPrivate())
+{
+// setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+ d_ptr->q_ptr = this;
+ d_ptr->m_ui.setupUi(this);
+ QPushButton *button = d_ptr->m_ui.buttonBox->button(QDialogButtonBox::Ok);
+ if (button)
+ button->setAutoDefault(false);
+ button = d_ptr->m_ui.buttonBox->button(QDialogButtonBox::Cancel);
+ if (button)
+ button->setAutoDefault(false);
+ connect(d_ptr->m_ui.gradientEditor, SIGNAL(aboutToShowDetails(bool, int)),
+ this, SLOT(slotAboutToShowDetails(bool, int)));
+}
+
+/*!
+ Destroys the gradient dialog
+*/
+
+GradientDialog::~GradientDialog()
+{
+}
+
+/*!
+ \property GradientDialog::gradient
+ \brief the gradient of the dialog
+*/
+void GradientDialog::setGradient(const QGradient &gradient)
+{
+ d_ptr->m_ui.gradientEditor->setGradient(gradient);
+}
+
+QGradient GradientDialog::gradient() const
+{
+ return d_ptr->m_ui.gradientEditor->gradient();
+}
+
+/*!
+ \property GradientDialog::backgroundCheckered
+ \brief whether the background of widgets able to show the colors with alpha channel is checkered.
+
+ \table
+ \row
+ \o \inlineimage qtgradientdialogbackgroundcheckered.png
+ \o \inlineimage qtgradientdialogbackgroundtransparent.png
+ \row
+ \o \snippet doc/src/snippets/code/tools_shared_qtgradienteditor_qtgradientdialog.cpp 2
+ \o \snippet doc/src/snippets/code/tools_shared_qtgradienteditor_qtgradientdialog.cpp 3
+ \endtable
+
+ When this property is set to true (the default) widgets inside gradient dialog like color button,
+ color sliders, gradient stops editor and gradient editor will show checkered background
+ in case of transparent colors. Otherwise the background of these widgets is transparent.
+*/
+
+bool GradientDialog::isBackgroundCheckered() const
+{
+ return d_ptr->m_ui.gradientEditor->isBackgroundCheckered();
+}
+
+void GradientDialog::setBackgroundCheckered(bool checkered)
+{
+ d_ptr->m_ui.gradientEditor->setBackgroundCheckered(checkered);
+}
+
+/*!
+ \property GradientDialog::detailsVisible
+ \brief whether details extension is visible.
+
+ When this property is set to true the details extension is visible. By default
+ this property is set to false and the details extension is hidden.
+
+ \sa detailsButtonVisible
+*/
+bool GradientDialog::detailsVisible() const
+{
+ return d_ptr->m_ui.gradientEditor->detailsVisible();
+}
+
+void GradientDialog::setDetailsVisible(bool visible)
+{
+ d_ptr->m_ui.gradientEditor->setDetailsVisible(visible);
+}
+
+/*!
+ \property GradientDialog::detailsButtonVisible
+ \brief whether the details button allowing for showing and hiding details extension is visible.
+
+ When this property is set to true (the default) the details button is visible and the user
+ can show and hide details extension interactively. Otherwise the button is hidden and the details
+ extension is always visible or hidded depending on the value of detailsVisible property.
+
+ \sa detailsVisible
+*/
+bool GradientDialog::isDetailsButtonVisible() const
+{
+ return d_ptr->m_ui.gradientEditor->isDetailsButtonVisible();
+}
+
+void GradientDialog::setDetailsButtonVisible(bool visible)
+{
+ d_ptr->m_ui.gradientEditor->setDetailsButtonVisible(visible);
+}
+
+/*!
+ Returns the current QColor::Spec used for the color sliders in the dialog.
+*/
+QColor::Spec GradientDialog::spec() const
+{
+ return d_ptr->m_ui.gradientEditor->spec();
+}
+
+/*!
+ Sets the current QColor::Spec to \a spec used for the color sliders in the dialog.
+*/
+void GradientDialog::setSpec(QColor::Spec spec)
+{
+ d_ptr->m_ui.gradientEditor->setSpec(spec);
+}
+
+/*!
+ Executes a modal gradient dialog, lets the user to specify a gradient, and returns that gradient.
+
+ If the user clicks \gui OK, the gradient specified by the user is returned. If the user clicks \gui Cancel, the \a initial gradient is returned.
+
+ The dialog is constructed with the given \a parent. \a caption is shown as the window title of the dialog and
+ \a initial is the initial gradient shown in the dialog. If the \a ok parameter is not-null,
+ the value it refers to is set to true if the user clicks \gui OK, and set to false if the user clicks \gui Cancel.
+*/
+QGradient GradientDialog::getGradient(bool *ok, const QGradient &initial, QWidget *parent, const QString &caption)
+{
+ GradientDialog dlg(parent);
+ if (!caption.isEmpty())
+ dlg.setWindowTitle(caption);
+ dlg.setGradient(initial);
+ const int res = dlg.exec();
+ if (ok) {
+ *ok = (res == QDialog::Accepted) ? true : false;
+ }
+ if (res == QDialog::Accepted)
+ return dlg.gradient();
+ return initial;
+}
+
+/*!
+ This method calls getGradient(ok, QLinearGradient(), parent, caption).
+*/
+QGradient GradientDialog::getGradient(bool *ok, QWidget *parent, const QString &caption)
+{
+ return getGradient(ok, QLinearGradient(), parent, caption);
+}
+
+QT_END_NAMESPACE
+
+#include "moc_gradientdialog.cpp"
diff --git a/src/plugins/qmldesigner/components/propertyeditor/gradientdialog.h b/src/plugins/qmldesigner/components/propertyeditor/gradientdialog.h
new file mode 100644
index 0000000000..b8f338a588
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/gradientdialog.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GRADIENTDIALOG_H
+#define GRADIENTDIALOG_H
+
+#include <QtGui/QDialog>
+
+QT_BEGIN_NAMESPACE
+
+class GradientDialogPrivate;
+
+class GradientDialog : public QDialog
+{
+ Q_OBJECT
+ Q_PROPERTY(QGradient gradient READ gradient WRITE setGradient)
+ Q_PROPERTY(bool backgroundCheckered READ isBackgroundCheckered WRITE setBackgroundCheckered)
+ Q_PROPERTY(bool detailsVisible READ detailsVisible WRITE setDetailsVisible)
+ Q_PROPERTY(bool detailsButtonVisible READ isDetailsButtonVisible WRITE setDetailsButtonVisible)
+public:
+ GradientDialog(QWidget *parent = 0);
+ ~GradientDialog();
+
+ void setGradient(const QGradient &gradient);
+ QGradient gradient() const;
+
+ bool isBackgroundCheckered() const;
+ void setBackgroundCheckered(bool checkered);
+
+ bool detailsVisible() const;
+ void setDetailsVisible(bool visible);
+
+ bool isDetailsButtonVisible() const;
+ void setDetailsButtonVisible(bool visible);
+
+ QColor::Spec spec() const;
+ void setSpec(QColor::Spec spec);
+
+ static QGradient getGradient(bool *ok, const QGradient &initial, QWidget *parent = 0, const QString &caption = QString());
+ static QGradient getGradient(bool *ok, QWidget *parent = 0, const QString &caption = QString());
+
+private:
+ QScopedPointer<GradientDialogPrivate> d_ptr;
+ Q_DECLARE_PRIVATE(GradientDialog)
+ Q_DISABLE_COPY(GradientDialog)
+ Q_PRIVATE_SLOT(d_func(), void slotAboutToShowDetails(bool details, int extensionWidthHint))
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qmldesigner/components/propertyeditor/gradientdialog.ui b/src/plugins/qmldesigner/components/propertyeditor/gradientdialog.ui
new file mode 100644
index 0000000000..d6a19c9dbb
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/gradientdialog.ui
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <class>GradientDialog</class>
+ <widget class="QDialog" name="GradientDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>178</width>
+ <height>81</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Edit Gradient</string>
+ </property>
+ <layout class="QVBoxLayout">
+ <item>
+ <widget class="GradientEditor" name="gradientEditor">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>GradientEditor</class>
+ <extends>QFrame</extends>
+ <header>gradienteditor.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>GradientDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>72</x>
+ <y>224</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>21</x>
+ <y>243</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>GradientDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>168</x>
+ <y>233</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>152</x>
+ <y>251</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/plugins/qmldesigner/components/propertyeditor/gradienteditor.cpp b/src/plugins/qmldesigner/components/propertyeditor/gradienteditor.cpp
new file mode 100644
index 0000000000..c29a21886b
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/gradienteditor.cpp
@@ -0,0 +1,933 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "gradienteditor.h"
+#include "qtgradientstopscontroller.h"
+#include "ui_gradienteditor.h"
+
+QT_BEGIN_NAMESPACE
+
+class GradientEditorPrivate
+{
+ GradientEditor *q_ptr;
+ Q_DECLARE_PUBLIC(GradientEditor)
+public:
+ GradientEditorPrivate() : m_gradient(QLinearGradient()) {}
+
+ void slotGradientStopsChanged(const QGradientStops &stops);
+ void slotTypeChanged(int type);
+ void slotSpreadChanged(int spread);
+ void slotStartLinearXChanged(double value);
+ void slotStartLinearYChanged(double value);
+ void slotEndLinearXChanged(double value);
+ void slotEndLinearYChanged(double value);
+ void slotCentralRadialXChanged(double value);
+ void slotCentralRadialYChanged(double value);
+ void slotFocalRadialXChanged(double value);
+ void slotFocalRadialYChanged(double value);
+ void slotRadiusRadialChanged(double value);
+ void slotCentralConicalXChanged(double value);
+ void slotCentralConicalYChanged(double value);
+ void slotAngleConicalChanged(double value);
+
+ void slotDetailsChanged(bool details);
+
+ void startLinearChanged(const QPointF &point);
+ void endLinearChanged(const QPointF &point);
+ void centralRadialChanged(const QPointF &point);
+ void focalRadialChanged(const QPointF &point);
+ void radiusRadialChanged(qreal radius);
+ void centralConicalChanged(const QPointF &point);
+ void angleConicalChanged(qreal angle);
+
+ void setStartLinear(const QPointF &point);
+ void setEndLinear(const QPointF &point);
+ void setCentralRadial(const QPointF &point);
+ void setFocalRadial(const QPointF &point);
+ void setRadiusRadial(qreal radius);
+ void setCentralConical(const QPointF &point);
+ void setAngleConical(qreal angle);
+
+ void setType(QGradient::Type type);
+ void showDetails(bool details);
+
+ void setSpinBox(QDoubleSpinBox *spinBox, const char *slot, double max = 1.0, double step = 0.01, int decimals = 3);
+ void reset();
+ void setLayout(bool details);
+ void layoutDetails(bool details);
+ bool row4Visible() const;
+ bool row5Visible() const;
+ int extensionWidthHint() const;
+
+ void setCombos(bool combos);
+
+ QGradient gradient() const;
+ void updateGradient(bool emitSignal);
+
+ Ui::GradientEditor m_ui;
+ QtGradientStopsController *m_gradientStopsController;
+
+ QDoubleSpinBox *startLinearXSpinBox;
+ QDoubleSpinBox *startLinearYSpinBox;
+ QDoubleSpinBox *endLinearXSpinBox;
+ QDoubleSpinBox *endLinearYSpinBox;
+ QDoubleSpinBox *centralRadialXSpinBox;
+ QDoubleSpinBox *centralRadialYSpinBox;
+ QDoubleSpinBox *focalRadialXSpinBox;
+ QDoubleSpinBox *focalRadialYSpinBox;
+ QDoubleSpinBox *radiusRadialSpinBox;
+ QDoubleSpinBox *centralConicalXSpinBox;
+ QDoubleSpinBox *centralConicalYSpinBox;
+ QDoubleSpinBox *angleConicalSpinBox;
+
+ QButtonGroup *m_typeGroup;
+ QButtonGroup *m_spreadGroup;
+
+ QGradient::Type m_type;
+
+ QGridLayout *m_gridLayout;
+ QWidget *m_hiddenWidget;
+ QGridLayout *m_hiddenLayout;
+ bool m_details;
+ bool m_detailsButtonVisible;
+ bool m_backgroundCheckered;
+
+ QGradient m_gradient;
+
+ bool m_combos;
+};
+
+QGradient GradientEditorPrivate::gradient() const
+{
+ QLinearGradient gradient;
+
+ gradient.setStops(m_ui.gradientWidget->gradientStops());
+ gradient.setSpread(m_ui.gradientWidget->gradientSpread());
+ gradient.setCoordinateMode(QGradient::StretchToDeviceMode);
+
+ return gradient;
+}
+
+void GradientEditorPrivate::updateGradient(bool emitSignal)
+{
+ QGradient grad = gradient();
+ if (m_gradient == grad)
+ return;
+
+ m_gradient = grad;
+ if (emitSignal)
+ emit q_ptr->gradientChanged(m_gradient);
+}
+
+void GradientEditorPrivate::setCombos(bool combos)
+{
+ if (m_combos == combos)
+ return;
+
+ m_combos = combos;
+ m_ui.linearButton->setVisible(!m_combos);
+ m_ui.radialButton->setVisible(!m_combos);
+ m_ui.conicalButton->setVisible(!m_combos);
+ m_ui.padButton->setVisible(!m_combos);
+ m_ui.repeatButton->setVisible(!m_combos);
+ m_ui.reflectButton->setVisible(!m_combos);
+ m_ui.typeComboBox->setVisible(m_combos);
+ m_ui.spreadComboBox->setVisible(m_combos);
+}
+
+void GradientEditorPrivate::setLayout(bool details)
+{
+ QHBoxLayout *hboxLayout = new QHBoxLayout();
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
+ hboxLayout->addWidget(m_ui.typeComboBox);
+ hboxLayout->addWidget(m_ui.spreadComboBox);
+ QHBoxLayout *typeLayout = new QHBoxLayout();
+ typeLayout->setSpacing(0);
+ typeLayout->addWidget(m_ui.linearButton);
+ typeLayout->addWidget(m_ui.radialButton);
+ typeLayout->addWidget(m_ui.conicalButton);
+ hboxLayout->addLayout(typeLayout);
+ QHBoxLayout *spreadLayout = new QHBoxLayout();
+ spreadLayout->setSpacing(0);
+ spreadLayout->addWidget(m_ui.padButton);
+ spreadLayout->addWidget(m_ui.repeatButton);
+ spreadLayout->addWidget(m_ui.reflectButton);
+ hboxLayout->addLayout(spreadLayout);
+ hboxLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum));
+ hboxLayout->addWidget(m_ui.detailsButton);
+ m_gridLayout->addLayout(hboxLayout, 0, 0, 1, 2);
+ int span = 1;
+ if (details)
+ span = 7;
+ m_gridLayout->addWidget(m_ui.frame, 1, 0, span, 2);
+ int row = 2;
+ if (details) {
+ row = 8;
+ span = 4;
+ }
+ m_gridLayout->addWidget(m_ui.gradientStopsWidget, row, 0, span, 2);
+ QHBoxLayout *hboxLayout1 = new QHBoxLayout();
+ hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
+ hboxLayout1->addWidget(m_ui.colorLabel);
+ hboxLayout1->addWidget(m_ui.colorButton);
+ hboxLayout1->addWidget(m_ui.hsvRadioButton);
+ hboxLayout1->addWidget(m_ui.rgbRadioButton);
+ hboxLayout1->addItem(new QSpacerItem(16, 23, QSizePolicy::Expanding, QSizePolicy::Minimum));
+ int addRow = 0;
+ if (details)
+ addRow = 9;
+ m_gridLayout->addLayout(hboxLayout1, 3 + addRow, 0, 1, 2);
+ m_gridLayout->addWidget(m_ui.hLabel, 4 + addRow, 0, 1, 1);
+ m_gridLayout->addWidget(m_ui.frame_2, 4 + addRow, 1, 1, 1);
+ m_gridLayout->addWidget(m_ui.sLabel, 5 + addRow, 0, 1, 1);
+ m_gridLayout->addWidget(m_ui.frame_5, 5 + addRow, 1, 1, 1);
+ m_gridLayout->addWidget(m_ui.vLabel, 6 + addRow, 0, 1, 1);
+ m_gridLayout->addWidget(m_ui.frame_3, 6 + addRow, 1, 1, 1);
+ m_gridLayout->addWidget(m_ui.aLabel, 7 + addRow, 0, 1, 1);
+ m_gridLayout->addWidget(m_ui.frame_4, 7 + addRow, 1, 1, 1);
+
+ if (details) {
+ layoutDetails(details);
+ }
+}
+
+void GradientEditorPrivate::layoutDetails(bool details)
+{
+ QGridLayout *gridLayout = m_gridLayout;
+ int col = 2;
+ if (!details) {
+ col = 0;
+ if (!m_hiddenWidget) {
+ m_hiddenWidget = new QWidget();
+ m_hiddenLayout = new QGridLayout(m_hiddenWidget);
+ m_hiddenLayout->setContentsMargins(0, 0, 0, 0);
+ m_hiddenLayout->setSizeConstraint(QLayout::SetFixedSize);
+ }
+ gridLayout = m_hiddenLayout;
+ }
+ gridLayout->addWidget(m_ui.label1, 1, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.spinBox1, 1, col + 1, 1, 1);
+ gridLayout->addWidget(m_ui.label2, 2, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.spinBox2, 2, col + 1, 1, 1);
+ gridLayout->addWidget(m_ui.label3, 3, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.spinBox3, 3, col + 1, 1, 1);
+ gridLayout->addWidget(m_ui.label4, 4, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.spinBox4, 4, col + 1, 1, 1);
+ gridLayout->addWidget(m_ui.label5, 5, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.spinBox5, 5, col + 1, 1, 1);
+ gridLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding), 6, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.line1Widget, 7, col + 0, 1, 2);
+ gridLayout->addWidget(m_ui.zoomLabel, 8, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.zoomWidget, 8, col + 1, 1, 1);
+ gridLayout->addWidget(m_ui.zoomButtonsWidget, 9, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.zoomAllButton, 9, col + 1, 1, 1);
+ gridLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Preferred), 10, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.line2Widget, 11, col + 0, 1, 2);
+ gridLayout->addWidget(m_ui.positionLabel, 12, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.positionWidget, 12, col + 1, 1, 1);
+ gridLayout->addWidget(m_ui.hueLabel, 13, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.hueWidget, 13, col + 1, 1, 1);
+ gridLayout->addWidget(m_ui.saturationLabel, 14, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.saturationWidget, 14, col + 1, 1, 1);
+ gridLayout->addWidget(m_ui.valueLabel, 15, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.valueWidget, 15, col + 1, 1, 1);
+ gridLayout->addWidget(m_ui.alphaLabel, 16, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.alphaWidget, 16, col + 1, 1, 1);
+
+ if (details) {
+ if (m_hiddenLayout) {
+ delete m_hiddenLayout;
+ m_hiddenLayout = 0;
+ }
+ if (m_hiddenWidget) {
+ delete m_hiddenWidget;
+ m_hiddenWidget = 0;
+ }
+ }
+}
+
+int GradientEditorPrivate::extensionWidthHint() const
+{
+ if (m_details)
+ return q_ptr->size().width() - m_ui.gradientStopsWidget->size().width();
+
+ const int space = m_ui.spinBox1->geometry().left() - m_ui.label1->geometry().right();
+
+ return m_hiddenLayout->minimumSize().width() + space;
+}
+
+void GradientEditorPrivate::slotDetailsChanged(bool details)
+{
+ showDetails(details);
+}
+
+bool GradientEditorPrivate::row4Visible() const
+{
+ if (m_type == QGradient::ConicalGradient)
+ return false;
+ return true;
+}
+
+bool GradientEditorPrivate::row5Visible() const
+{
+ if (m_type == QGradient::RadialGradient)
+ return true;
+ return false;
+}
+
+void GradientEditorPrivate::showDetails(bool details)
+{
+ if (m_details == details)
+ return;
+
+ bool blocked = m_ui.detailsButton->signalsBlocked();
+ m_ui.detailsButton->blockSignals(true);
+ m_ui.detailsButton->setChecked(details);
+ m_ui.detailsButton->blockSignals(blocked);
+
+ bool updates = q_ptr->updatesEnabled();
+ q_ptr->setUpdatesEnabled(false);
+
+ if (m_gridLayout) {
+ m_gridLayout->setEnabled(false);
+ delete m_gridLayout;
+ m_gridLayout = 0;
+ }
+
+ if (!details) {
+ layoutDetails(details);
+ }
+
+ emit q_ptr->aboutToShowDetails(details, extensionWidthHint());
+ m_details = details;
+
+ m_gridLayout = new QGridLayout(q_ptr);
+ m_gridLayout->setEnabled(false);
+ m_gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
+ m_gridLayout->setContentsMargins(0, 0, 0, 0);
+
+ m_ui.label4->setVisible(row4Visible());
+ m_ui.label5->setVisible(row5Visible());
+ m_ui.spinBox4->setVisible(row4Visible());
+ m_ui.spinBox5->setVisible(row5Visible());
+
+ setLayout(details);
+ m_gridLayout->setEnabled(true);
+
+ q_ptr->setUpdatesEnabled(updates);
+ q_ptr->update();
+}
+
+void GradientEditorPrivate::setSpinBox(QDoubleSpinBox *spinBox, const char *slot, double max, double step, int decimals)
+{
+ bool blocked = spinBox->signalsBlocked();
+ spinBox->blockSignals(true);
+ spinBox->setDecimals(decimals);
+ spinBox->setMaximum(max);
+ spinBox->setSingleStep(step);
+ spinBox->blockSignals(blocked);
+ QObject::connect(spinBox, SIGNAL(valueChanged(double)), q_ptr, slot);
+}
+
+void GradientEditorPrivate::reset()
+{
+ startLinearXSpinBox = 0;
+ startLinearYSpinBox = 0;
+ endLinearXSpinBox = 0;
+ endLinearYSpinBox = 0;
+ centralRadialXSpinBox = 0;
+ centralRadialYSpinBox = 0;
+ focalRadialXSpinBox = 0;
+ focalRadialYSpinBox = 0;
+ radiusRadialSpinBox = 0;
+ centralConicalXSpinBox = 0;
+ centralConicalYSpinBox = 0;
+ angleConicalSpinBox = 0;
+}
+
+void GradientEditorPrivate::setType(QGradient::Type type)
+{
+ if (m_type == type)
+ return;
+
+ m_type = type;
+ m_ui.spinBox1->disconnect(SIGNAL(valueChanged(double)));
+ m_ui.spinBox2->disconnect(SIGNAL(valueChanged(double)));
+ m_ui.spinBox3->disconnect(SIGNAL(valueChanged(double)));
+ m_ui.spinBox4->disconnect(SIGNAL(valueChanged(double)));
+ m_ui.spinBox5->disconnect(SIGNAL(valueChanged(double)));
+
+ reset();
+
+ bool ena = true;
+
+ if (m_gridLayout) {
+ ena = m_gridLayout->isEnabled();
+ m_gridLayout->setEnabled(false);
+ }
+
+ bool spreadEnabled = true;
+
+ if (type == QGradient::LinearGradient) {
+ startLinearXSpinBox = m_ui.spinBox1;
+ setSpinBox(startLinearXSpinBox, SLOT(slotStartLinearXChanged(double)));
+ m_ui.label1->setText(QApplication::translate("GradientEditor", "Start X", 0, QApplication::UnicodeUTF8));
+
+ startLinearYSpinBox = m_ui.spinBox2;
+ setSpinBox(startLinearYSpinBox, SLOT(slotStartLinearYChanged(double)));
+ m_ui.label2->setText(QApplication::translate("GradientEditor", "Start Y", 0, QApplication::UnicodeUTF8));
+
+ endLinearXSpinBox = m_ui.spinBox3;
+ setSpinBox(endLinearXSpinBox, SLOT(slotEndLinearXChanged(double)));
+ m_ui.label3->setText(QApplication::translate("GradientEditor", "Final X", 0, QApplication::UnicodeUTF8));
+
+ endLinearYSpinBox = m_ui.spinBox4;
+ setSpinBox(endLinearYSpinBox, SLOT(slotEndLinearYChanged(double)));
+ m_ui.label4->setText(QApplication::translate("GradientEditor", "Final Y", 0, QApplication::UnicodeUTF8));
+
+ setStartLinear(m_ui.gradientWidget->startLinear());
+ setEndLinear(m_ui.gradientWidget->endLinear());
+ } else if (type == QGradient::RadialGradient) {
+ centralRadialXSpinBox = m_ui.spinBox1;
+ setSpinBox(centralRadialXSpinBox, SLOT(slotCentralRadialXChanged(double)));
+ m_ui.label1->setText(QApplication::translate("GradientEditor", "Central X", 0, QApplication::UnicodeUTF8));
+
+ centralRadialYSpinBox = m_ui.spinBox2;
+ setSpinBox(centralRadialYSpinBox, SLOT(slotCentralRadialYChanged(double)));
+ m_ui.label2->setText(QApplication::translate("GradientEditor", "Central Y", 0, QApplication::UnicodeUTF8));
+
+ focalRadialXSpinBox = m_ui.spinBox3;
+ setSpinBox(focalRadialXSpinBox, SLOT(slotFocalRadialXChanged(double)));
+ m_ui.label3->setText(QApplication::translate("GradientEditor", "Focal X", 0, QApplication::UnicodeUTF8));
+
+ focalRadialYSpinBox = m_ui.spinBox4;
+ setSpinBox(focalRadialYSpinBox, SLOT(slotFocalRadialYChanged(double)));
+ m_ui.label4->setText(QApplication::translate("GradientEditor", "Focal Y", 0, QApplication::UnicodeUTF8));
+
+ radiusRadialSpinBox = m_ui.spinBox5;
+ setSpinBox(radiusRadialSpinBox, SLOT(slotRadiusRadialChanged(double)), 2.0);
+ m_ui.label5->setText(QApplication::translate("GradientEditor", "Radius", 0, QApplication::UnicodeUTF8));
+
+ setCentralRadial(m_ui.gradientWidget->centralRadial());
+ setFocalRadial(m_ui.gradientWidget->focalRadial());
+ setRadiusRadial(m_ui.gradientWidget->radiusRadial());
+ } else if (type == QGradient::ConicalGradient) {
+ centralConicalXSpinBox = m_ui.spinBox1;
+ setSpinBox(centralConicalXSpinBox, SLOT(slotCentralConicalXChanged(double)));
+ m_ui.label1->setText(QApplication::translate("GradientEditor", "Central X", 0, QApplication::UnicodeUTF8));
+
+ centralConicalYSpinBox = m_ui.spinBox2;
+ setSpinBox(centralConicalYSpinBox, SLOT(slotCentralConicalYChanged(double)));
+ m_ui.label2->setText(QApplication::translate("GradientEditor", "Central Y", 0, QApplication::UnicodeUTF8));
+
+ angleConicalSpinBox = m_ui.spinBox3;
+ setSpinBox(angleConicalSpinBox, SLOT(slotAngleConicalChanged(double)), 360.0, 1.0, 1);
+ m_ui.label3->setText(QApplication::translate("GradientEditor", "Angle", 0, QApplication::UnicodeUTF8));
+
+ setCentralConical(m_ui.gradientWidget->centralConical());
+ setAngleConical(m_ui.gradientWidget->angleConical());
+
+ spreadEnabled = false;
+ }
+ m_ui.spreadComboBox->setEnabled(spreadEnabled);
+ m_ui.padButton->setEnabled(spreadEnabled);
+ m_ui.repeatButton->setEnabled(spreadEnabled);
+ m_ui.reflectButton->setEnabled(spreadEnabled);
+
+ m_ui.label4->setVisible(row4Visible());
+ m_ui.spinBox4->setVisible(row4Visible());
+ m_ui.label5->setVisible(row5Visible());
+ m_ui.spinBox5->setVisible(row5Visible());
+
+ if (m_gridLayout) {
+ m_gridLayout->setEnabled(ena);
+ }
+}
+
+void GradientEditorPrivate::slotGradientStopsChanged(const QGradientStops &stops)
+{
+ m_ui.gradientWidget->setGradientStops(stops);
+ updateGradient(true);
+}
+
+void GradientEditorPrivate::slotTypeChanged(int idx)
+{
+ QGradient::Type type = QGradient::NoGradient;
+ if (idx == 0)
+ type = QGradient::LinearGradient;
+ else if (idx == 1)
+ type = QGradient::RadialGradient;
+ else if (idx == 2)
+ type = QGradient::ConicalGradient;
+ setType(type);
+ m_ui.typeComboBox->setCurrentIndex(idx);
+ m_typeGroup->button(idx)->setChecked(true);
+ m_ui.gradientWidget->setGradientType(type);
+ updateGradient(true);
+}
+
+void GradientEditorPrivate::slotSpreadChanged(int spread)
+{
+ if (spread == 0) {
+ m_ui.gradientWidget->setGradientSpread(QGradient::PadSpread);
+ } else if (spread == 1) {
+ m_ui.gradientWidget->setGradientSpread(QGradient::RepeatSpread);
+ } else if (spread == 2) {
+ m_ui.gradientWidget->setGradientSpread(QGradient::ReflectSpread);
+ }
+ m_ui.spreadComboBox->setCurrentIndex(spread);
+ updateGradient(true);
+}
+
+void GradientEditorPrivate::slotStartLinearXChanged(double value)
+{
+ QPointF point = m_ui.gradientWidget->startLinear();
+ point.setX(value);
+ m_ui.gradientWidget->setStartLinear(point);
+ updateGradient(true);
+}
+
+void GradientEditorPrivate::slotStartLinearYChanged(double value)
+{
+ QPointF point = m_ui.gradientWidget->startLinear();
+ point.setY(value);
+ m_ui.gradientWidget->setStartLinear(point);
+ updateGradient(true);
+}
+
+void GradientEditorPrivate::slotEndLinearXChanged(double value)
+{
+ QPointF point = m_ui.gradientWidget->endLinear();
+ point.setX(value);
+ m_ui.gradientWidget->setEndLinear(point);
+ updateGradient(true);
+}
+
+void GradientEditorPrivate::slotEndLinearYChanged(double value)
+{
+ QPointF point = m_ui.gradientWidget->endLinear();
+ point.setY(value);
+ m_ui.gradientWidget->setEndLinear(point);
+ updateGradient(true);
+}
+
+void GradientEditorPrivate::slotCentralRadialXChanged(double value)
+{
+ QPointF point = m_ui.gradientWidget->centralRadial();
+ point.setX(value);
+ m_ui.gradientWidget->setCentralRadial(point);
+ updateGradient(true);
+}
+
+void GradientEditorPrivate::slotCentralRadialYChanged(double value)
+{
+ QPointF point = m_ui.gradientWidget->centralRadial();
+ point.setY(value);
+ m_ui.gradientWidget->setCentralRadial(point);
+ updateGradient(true);
+}
+
+void GradientEditorPrivate::slotFocalRadialXChanged(double value)
+{
+ QPointF point = m_ui.gradientWidget->focalRadial();
+ point.setX(value);
+ m_ui.gradientWidget->setFocalRadial(point);
+ updateGradient(true);
+}
+
+void GradientEditorPrivate::slotFocalRadialYChanged(double value)
+{
+ QPointF point = m_ui.gradientWidget->focalRadial();
+ point.setY(value);
+ m_ui.gradientWidget->setFocalRadial(point);
+ updateGradient(true);
+}
+
+void GradientEditorPrivate::slotRadiusRadialChanged(double value)
+{
+ m_ui.gradientWidget->setRadiusRadial(value);
+ updateGradient(true);
+}
+
+void GradientEditorPrivate::slotCentralConicalXChanged(double value)
+{
+ QPointF point = m_ui.gradientWidget->centralConical();
+ point.setX(value);
+ m_ui.gradientWidget->setCentralConical(point);
+ updateGradient(true);
+}
+
+void GradientEditorPrivate::slotCentralConicalYChanged(double value)
+{
+ QPointF point = m_ui.gradientWidget->centralConical();
+ point.setY(value);
+ m_ui.gradientWidget->setCentralConical(point);
+ updateGradient(true);
+}
+
+void GradientEditorPrivate::slotAngleConicalChanged(double value)
+{
+ m_ui.gradientWidget->setAngleConical(value);
+ updateGradient(true);
+}
+
+void GradientEditorPrivate::startLinearChanged(const QPointF &point)
+{
+ setStartLinear(point);
+ updateGradient(true);
+}
+
+void GradientEditorPrivate::endLinearChanged(const QPointF &point)
+{
+ setEndLinear(point);
+ updateGradient(true);
+}
+
+void GradientEditorPrivate::centralRadialChanged(const QPointF &point)
+{
+ setCentralRadial(point);
+ updateGradient(true);
+}
+
+void GradientEditorPrivate::focalRadialChanged(const QPointF &point)
+{
+ setFocalRadial(point);
+ updateGradient(true);
+}
+
+void GradientEditorPrivate::radiusRadialChanged(qreal radius)
+{
+ setRadiusRadial(radius);
+ updateGradient(true);
+}
+
+void GradientEditorPrivate::centralConicalChanged(const QPointF &point)
+{
+ setCentralConical(point);
+ updateGradient(true);
+}
+
+void GradientEditorPrivate::angleConicalChanged(qreal angle)
+{
+ setAngleConical(angle);
+ updateGradient(true);
+}
+
+void GradientEditorPrivate::setStartLinear(const QPointF &point)
+{
+ if (startLinearXSpinBox)
+ startLinearXSpinBox->setValue(point.x());
+ if (startLinearYSpinBox)
+ startLinearYSpinBox->setValue(point.y());
+}
+
+void GradientEditorPrivate::setEndLinear(const QPointF &point)
+{
+ if (endLinearXSpinBox)
+ endLinearXSpinBox->setValue(point.x());
+ if (endLinearYSpinBox)
+ endLinearYSpinBox->setValue(point.y());
+}
+
+void GradientEditorPrivate::setCentralRadial(const QPointF &point)
+{
+ if (centralRadialXSpinBox)
+ centralRadialXSpinBox->setValue(point.x());
+ if (centralRadialYSpinBox)
+ centralRadialYSpinBox->setValue(point.y());
+}
+
+void GradientEditorPrivate::setFocalRadial(const QPointF &point)
+{
+ if (focalRadialXSpinBox)
+ focalRadialXSpinBox->setValue(point.x());
+ if (focalRadialYSpinBox)
+ focalRadialYSpinBox->setValue(point.y());
+}
+
+void GradientEditorPrivate::setRadiusRadial(qreal radius)
+{
+ if (radiusRadialSpinBox)
+ radiusRadialSpinBox->setValue(radius);
+}
+
+void GradientEditorPrivate::setCentralConical(const QPointF &point)
+{
+ if (centralConicalXSpinBox)
+ centralConicalXSpinBox->setValue(point.x());
+ if (centralConicalYSpinBox)
+ centralConicalYSpinBox->setValue(point.y());
+}
+
+void GradientEditorPrivate::setAngleConical(qreal angle)
+{
+ if (angleConicalSpinBox)
+ angleConicalSpinBox->setValue(angle);
+}
+
+GradientEditor::GradientEditor(QWidget *parent)
+ : QWidget(parent), d_ptr(new GradientEditorPrivate())
+{
+ d_ptr->q_ptr = this;
+ d_ptr->m_type = QGradient::RadialGradient;
+ d_ptr->m_ui.setupUi(this);
+ d_ptr->m_gridLayout = 0;
+ d_ptr->m_hiddenLayout = 0;
+ d_ptr->m_hiddenWidget = 0;
+ bool detailsDefault = false;
+ d_ptr->m_details = !detailsDefault;
+ d_ptr->m_detailsButtonVisible = true;
+ bool checkeredDefault = true;
+ d_ptr->m_backgroundCheckered = !checkeredDefault;
+ d_ptr->m_gradientStopsController = new QtGradientStopsController(this);
+ d_ptr->m_gradientStopsController->setUi(&d_ptr->m_ui);
+ d_ptr->reset();
+ d_ptr->setType(QGradient::LinearGradient);
+ d_ptr->m_combos = true;
+ d_ptr->setCombos(!d_ptr->m_combos);
+
+ d_ptr->showDetails(detailsDefault);
+ setBackgroundCheckered(checkeredDefault);
+
+ d_ptr->setStartLinear(QPointF(0, 0));
+ d_ptr->setEndLinear(QPointF(1, 1));
+ d_ptr->setCentralRadial(QPointF(0.5, 0.5));
+ d_ptr->setFocalRadial(QPointF(0.5, 0.5));
+ d_ptr->setRadiusRadial(0.5);
+ d_ptr->setCentralConical(QPointF(0.5, 0.5));
+ d_ptr->setAngleConical(0);
+
+ QIcon icon;
+ icon.addPixmap(style()->standardPixmap(QStyle::SP_ArrowRight), QIcon::Normal, QIcon::Off);
+ icon.addPixmap(style()->standardPixmap(QStyle::SP_ArrowLeft), QIcon::Normal, QIcon::On);
+ d_ptr->m_ui.detailsButton->setIcon(icon);
+
+ connect(d_ptr->m_ui.detailsButton, SIGNAL(clicked(bool)), this, SLOT(slotDetailsChanged(bool)));
+ connect(d_ptr->m_gradientStopsController, SIGNAL(gradientStopsChanged(const QGradientStops &)),
+ this, SLOT(slotGradientStopsChanged(const QGradientStops &)));
+
+ QIcon iconLinear(QLatin1String(":/trolltech/qtgradienteditor/images/typelinear.png"));
+ QIcon iconRadial(QLatin1String(":/trolltech/qtgradienteditor/images/typeradial.png"));
+ QIcon iconConical(QLatin1String(":/trolltech/qtgradienteditor/images/typeconical.png"));
+
+ d_ptr->m_ui.typeComboBox->addItem(iconLinear, tr("Linear"));
+ d_ptr->m_ui.typeComboBox->addItem(iconRadial, tr("Radial"));
+ d_ptr->m_ui.typeComboBox->addItem(iconConical, tr("Conical"));
+
+ d_ptr->m_ui.linearButton->setIcon(iconLinear);
+ d_ptr->m_ui.radialButton->setIcon(iconRadial);
+ d_ptr->m_ui.conicalButton->setIcon(iconConical);
+
+ d_ptr->m_typeGroup = new QButtonGroup(this);
+ d_ptr->m_typeGroup->addButton(d_ptr->m_ui.linearButton, 0);
+ d_ptr->m_typeGroup->addButton(d_ptr->m_ui.radialButton, 1);
+ d_ptr->m_typeGroup->addButton(d_ptr->m_ui.conicalButton, 2);
+
+ connect(d_ptr->m_typeGroup, SIGNAL(buttonClicked(int)),
+ this, SLOT(slotTypeChanged(int)));
+ connect(d_ptr->m_ui.typeComboBox, SIGNAL(activated(int)),
+ this, SLOT(slotTypeChanged(int)));
+
+ QIcon iconPad(QLatin1String(":/trolltech/qtgradienteditor/images/spreadpad.png"));
+ QIcon iconRepeat(QLatin1String(":/trolltech/qtgradienteditor/images/spreadrepeat.png"));
+ QIcon iconReflect(QLatin1String(":/trolltech/qtgradienteditor/images/spreadreflect.png"));
+
+ d_ptr->m_ui.spreadComboBox->addItem(iconPad, tr("Pad"));
+ d_ptr->m_ui.spreadComboBox->addItem(iconRepeat, tr("Repeat"));
+ d_ptr->m_ui.spreadComboBox->addItem(iconReflect, tr("Reflect"));
+
+ d_ptr->m_ui.padButton->setIcon(iconPad);
+ d_ptr->m_ui.repeatButton->setIcon(iconRepeat);
+ d_ptr->m_ui.reflectButton->setIcon(iconReflect);
+
+ d_ptr->m_spreadGroup = new QButtonGroup(this);
+ d_ptr->m_spreadGroup->addButton(d_ptr->m_ui.padButton, 0);
+ d_ptr->m_spreadGroup->addButton(d_ptr->m_ui.repeatButton, 1);
+ d_ptr->m_spreadGroup->addButton(d_ptr->m_ui.reflectButton, 2);
+ connect(d_ptr->m_spreadGroup, SIGNAL(buttonClicked(int)),
+ this, SLOT(slotSpreadChanged(int)));
+ connect(d_ptr->m_ui.spreadComboBox, SIGNAL(activated(int)),
+ this, SLOT(slotSpreadChanged(int)));
+
+ connect(d_ptr->m_ui.gradientWidget, SIGNAL(startLinearChanged(const QPointF &)),
+ this, SLOT(startLinearChanged(const QPointF &)));
+ connect(d_ptr->m_ui.gradientWidget, SIGNAL(endLinearChanged(const QPointF &)),
+ this, SLOT(endLinearChanged(const QPointF &)));
+ connect(d_ptr->m_ui.gradientWidget, SIGNAL(centralRadialChanged(const QPointF &)),
+ this, SLOT(centralRadialChanged(const QPointF &)));
+ connect(d_ptr->m_ui.gradientWidget, SIGNAL(focalRadialChanged(const QPointF &)),
+ this, SLOT(focalRadialChanged(const QPointF &)));
+ connect(d_ptr->m_ui.gradientWidget, SIGNAL(radiusRadialChanged(qreal)),
+ this, SLOT(radiusRadialChanged(qreal)));
+ connect(d_ptr->m_ui.gradientWidget, SIGNAL(centralConicalChanged(const QPointF &)),
+ this, SLOT(centralConicalChanged(const QPointF &)));
+ connect(d_ptr->m_ui.gradientWidget, SIGNAL(angleConicalChanged(qreal)),
+ this, SLOT(angleConicalChanged(qreal)));
+
+ QGradientStops stops = gradient().stops();
+ d_ptr->m_gradientStopsController->setGradientStops(stops);
+ d_ptr->m_ui.gradientWidget->setGradientStops(stops);
+}
+
+GradientEditor::~GradientEditor()
+{
+ if (d_ptr->m_hiddenWidget)
+ delete d_ptr->m_hiddenWidget;
+}
+
+void GradientEditor::setGradient(const QGradient &grad)
+{
+ if (grad == gradient())
+ return;
+
+ QGradient::Type type = grad.type();
+ int idx = 0;
+ switch (type) {
+ case QGradient::LinearGradient: idx = 0; break;
+ case QGradient::RadialGradient: idx = 1; break;
+ case QGradient::ConicalGradient: idx = 2; break;
+ default: return;
+ }
+ d_ptr->setType(type);
+ d_ptr->m_ui.typeComboBox->setCurrentIndex(idx);
+ d_ptr->m_ui.gradientWidget->setGradientType(type);
+ d_ptr->m_typeGroup->button(idx)->setChecked(true);
+
+ QGradient::Spread spread = grad.spread();
+ switch (spread) {
+ case QGradient::PadSpread: idx = 0; break;
+ case QGradient::RepeatSpread: idx = 1; break;
+ case QGradient::ReflectSpread: idx = 2; break;
+ default: idx = 0; break;
+ }
+ d_ptr->m_ui.spreadComboBox->setCurrentIndex(idx);
+ d_ptr->m_ui.gradientWidget->setGradientSpread(spread);
+ d_ptr->m_spreadGroup->button(idx)->setChecked(true);
+
+ if (type == QGradient::LinearGradient) {
+ QLinearGradient *gr = (QLinearGradient *)(&grad);
+ d_ptr->setStartLinear(gr->start());
+ d_ptr->setEndLinear(gr->finalStop());
+ d_ptr->m_ui.gradientWidget->setStartLinear(gr->start());
+ d_ptr->m_ui.gradientWidget->setEndLinear(gr->finalStop());
+ } else if (type == QGradient::RadialGradient) {
+ QRadialGradient *gr = (QRadialGradient *)(&grad);
+ d_ptr->setCentralRadial(gr->center());
+ d_ptr->setFocalRadial(gr->focalPoint());
+ d_ptr->setRadiusRadial(gr->radius());
+ d_ptr->m_ui.gradientWidget->setCentralRadial(gr->center());
+ d_ptr->m_ui.gradientWidget->setFocalRadial(gr->focalPoint());
+ d_ptr->m_ui.gradientWidget->setRadiusRadial(gr->radius());
+ } else if (type == QGradient::ConicalGradient) {
+ QConicalGradient *gr = (QConicalGradient *)(&grad);
+ d_ptr->setCentralConical(gr->center());
+ d_ptr->setAngleConical(gr->angle());
+ d_ptr->m_ui.gradientWidget->setCentralConical(gr->center());
+ d_ptr->m_ui.gradientWidget->setAngleConical(gr->angle());
+ }
+
+ d_ptr->m_gradientStopsController->setGradientStops(grad.stops());
+ d_ptr->m_ui.gradientWidget->setGradientStops(grad.stops());
+ d_ptr->updateGradient(false);
+}
+
+QGradient GradientEditor::gradient() const
+{
+ return d_ptr->m_gradient;
+}
+
+bool GradientEditor::isBackgroundCheckered() const
+{
+ return d_ptr->m_backgroundCheckered;
+}
+
+void GradientEditor::setBackgroundCheckered(bool checkered)
+{
+ if (d_ptr->m_backgroundCheckered == checkered)
+ return;
+
+ d_ptr->m_backgroundCheckered = checkered;
+ d_ptr->m_ui.hueColorLine->setBackgroundCheckered(checkered);
+ d_ptr->m_ui.saturationColorLine->setBackgroundCheckered(checkered);
+ d_ptr->m_ui.valueColorLine->setBackgroundCheckered(checkered);
+ d_ptr->m_ui.alphaColorLine->setBackgroundCheckered(checkered);
+ d_ptr->m_ui.gradientWidget->setBackgroundCheckered(checkered);
+ d_ptr->m_ui.gradientStopsWidget->setBackgroundCheckered(checkered);
+ d_ptr->m_ui.colorButton->setBackgroundCheckered(checkered);
+}
+
+bool GradientEditor::detailsVisible() const
+{
+ return d_ptr->m_details;
+}
+
+void GradientEditor::setDetailsVisible(bool visible)
+{
+ d_ptr->showDetails(visible);
+}
+
+bool GradientEditor::isDetailsButtonVisible() const
+{
+ return d_ptr->m_detailsButtonVisible;
+}
+
+void GradientEditor::setDetailsButtonVisible(bool visible)
+{
+ if (d_ptr->m_detailsButtonVisible == visible)
+ return;
+
+ d_ptr->m_detailsButtonVisible = visible;
+ d_ptr->m_ui.detailsButton->setVisible(visible);
+}
+
+QColor::Spec GradientEditor::spec() const
+{
+ return d_ptr->m_gradientStopsController->spec();
+}
+
+void GradientEditor::setSpec(QColor::Spec spec)
+{
+ d_ptr->m_gradientStopsController->setSpec(spec);
+}
+
+QT_END_NAMESPACE
+
+#include "moc_gradienteditor.cpp"
diff --git a/src/plugins/qmldesigner/components/propertyeditor/gradienteditor.h b/src/plugins/qmldesigner/components/propertyeditor/gradienteditor.h
new file mode 100644
index 0000000000..b0bc2a51b9
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/gradienteditor.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GRADIENTEDITOR_H
+#define GRADIENTEDITOR_H
+
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class GradientEditorPrivate;
+
+class GradientEditor : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(QGradient gradient READ gradient WRITE setGradient)
+ Q_PROPERTY(bool backgroundCheckered READ isBackgroundCheckered WRITE setBackgroundCheckered)
+ Q_PROPERTY(bool detailsVisible READ detailsVisible WRITE setDetailsVisible)
+ Q_PROPERTY(bool detailsButtonVisible READ isDetailsButtonVisible WRITE setDetailsButtonVisible)
+public:
+ GradientEditor(QWidget *parent = 0);
+ ~GradientEditor();
+
+ void setGradient(const QGradient &gradient);
+ QGradient gradient() const;
+
+ bool isBackgroundCheckered() const;
+ void setBackgroundCheckered(bool checkered);
+
+ bool detailsVisible() const;
+ void setDetailsVisible(bool visible);
+
+ bool isDetailsButtonVisible() const;
+ void setDetailsButtonVisible(bool visible);
+
+ QColor::Spec spec() const;
+ void setSpec(QColor::Spec spec);
+
+signals:
+
+ void gradientChanged(const QGradient &gradient);
+ void aboutToShowDetails(bool details, int extenstionWidthHint);
+
+private:
+ QScopedPointer<GradientEditorPrivate> d_ptr;
+ Q_DECLARE_PRIVATE(GradientEditor)
+ Q_DISABLE_COPY(GradientEditor)
+ Q_PRIVATE_SLOT(d_func(), void slotGradientStopsChanged(const QGradientStops &stops))
+ Q_PRIVATE_SLOT(d_func(), void slotTypeChanged(int type))
+ Q_PRIVATE_SLOT(d_func(), void slotSpreadChanged(int type))
+ Q_PRIVATE_SLOT(d_func(), void slotStartLinearXChanged(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotStartLinearYChanged(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotEndLinearXChanged(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotEndLinearYChanged(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotCentralRadialXChanged(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotCentralRadialYChanged(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotFocalRadialXChanged(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotFocalRadialYChanged(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotRadiusRadialChanged(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotCentralConicalXChanged(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotCentralConicalYChanged(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotAngleConicalChanged(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotDetailsChanged(bool details))
+ Q_PRIVATE_SLOT(d_func(), void startLinearChanged(const QPointF &))
+ Q_PRIVATE_SLOT(d_func(), void endLinearChanged(const QPointF &))
+ Q_PRIVATE_SLOT(d_func(), void centralRadialChanged(const QPointF &))
+ Q_PRIVATE_SLOT(d_func(), void focalRadialChanged(const QPointF &))
+ Q_PRIVATE_SLOT(d_func(), void radiusRadialChanged(qreal))
+ Q_PRIVATE_SLOT(d_func(), void centralConicalChanged(const QPointF &))
+ Q_PRIVATE_SLOT(d_func(), void angleConicalChanged(qreal))
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qmldesigner/components/propertyeditor/gradienteditor.ui b/src/plugins/qmldesigner/components/propertyeditor/gradienteditor.ui
new file mode 100644
index 0000000000..0860e07f06
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/gradienteditor.ui
@@ -0,0 +1,1255 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <class>GradientEditor</class>
+ <widget class="QWidget" name="GradientEditor">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>364</width>
+ <height>233</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <widget class="QFrame" name="frame">
+ <property name="geometry">
+ <rect>
+ <x>11</x>
+ <y>-150</y>
+ <width>193</width>
+ <height>150</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QVBoxLayout">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QtGradientWidget" name="gradientWidget" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Gradient Editor</string>
+ </property>
+ <property name="whatsThis">
+ <string>This area shows a preview of the gradient being edited. It also allows you to edit parameters specific to the gradient's type such as start and final point, radius, etc. by drag &amp; drop.</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QLabel" name="label1">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>210</x>
+ <y>-150</y>
+ <width>64</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>1</string>
+ </property>
+ </widget>
+ <widget class="QDoubleSpinBox" name="spinBox1">
+ <property name="geometry">
+ <rect>
+ <x>280</x>
+ <y>-150</y>
+ <width>73</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="keyboardTracking">
+ <bool>false</bool>
+ </property>
+ <property name="decimals">
+ <number>3</number>
+ </property>
+ <property name="maximum">
+ <double>1.000000000000000</double>
+ </property>
+ <property name="singleStep">
+ <double>0.010000000000000</double>
+ </property>
+ </widget>
+ <widget class="QLabel" name="label2">
+ <property name="geometry">
+ <rect>
+ <x>210</x>
+ <y>-120</y>
+ <width>64</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>2</string>
+ </property>
+ </widget>
+ <widget class="QDoubleSpinBox" name="spinBox2">
+ <property name="geometry">
+ <rect>
+ <x>280</x>
+ <y>-120</y>
+ <width>73</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="keyboardTracking">
+ <bool>false</bool>
+ </property>
+ <property name="decimals">
+ <number>3</number>
+ </property>
+ <property name="maximum">
+ <double>1.000000000000000</double>
+ </property>
+ <property name="singleStep">
+ <double>0.010000000000000</double>
+ </property>
+ </widget>
+ <widget class="QLabel" name="label3">
+ <property name="geometry">
+ <rect>
+ <x>210</x>
+ <y>-90</y>
+ <width>64</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>3</string>
+ </property>
+ </widget>
+ <widget class="QDoubleSpinBox" name="spinBox3">
+ <property name="geometry">
+ <rect>
+ <x>280</x>
+ <y>-90</y>
+ <width>73</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="keyboardTracking">
+ <bool>false</bool>
+ </property>
+ <property name="decimals">
+ <number>3</number>
+ </property>
+ <property name="maximum">
+ <double>1.000000000000000</double>
+ </property>
+ <property name="singleStep">
+ <double>0.010000000000000</double>
+ </property>
+ </widget>
+ <widget class="QLabel" name="label4">
+ <property name="geometry">
+ <rect>
+ <x>210</x>
+ <y>-60</y>
+ <width>64</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>4</string>
+ </property>
+ </widget>
+ <widget class="QDoubleSpinBox" name="spinBox4">
+ <property name="geometry">
+ <rect>
+ <x>280</x>
+ <y>-60</y>
+ <width>73</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="keyboardTracking">
+ <bool>false</bool>
+ </property>
+ <property name="decimals">
+ <number>3</number>
+ </property>
+ <property name="maximum">
+ <double>1.000000000000000</double>
+ </property>
+ <property name="singleStep">
+ <double>0.010000000000000</double>
+ </property>
+ </widget>
+ <widget class="QLabel" name="label5">
+ <property name="geometry">
+ <rect>
+ <x>210</x>
+ <y>-30</y>
+ <width>64</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>5</string>
+ </property>
+ </widget>
+ <widget class="QDoubleSpinBox" name="spinBox5">
+ <property name="geometry">
+ <rect>
+ <x>280</x>
+ <y>-30</y>
+ <width>73</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="keyboardTracking">
+ <bool>false</bool>
+ </property>
+ <property name="decimals">
+ <number>3</number>
+ </property>
+ <property name="maximum">
+ <double>1.000000000000000</double>
+ </property>
+ <property name="singleStep">
+ <double>0.010000000000000</double>
+ </property>
+ </widget>
+ <widget class="QtGradientStopsWidget" name="gradientStopsWidget" native="true">
+ <property name="geometry">
+ <rect>
+ <x>11</x>
+ <y>6</y>
+ <width>193</width>
+ <height>67</height>
+ </rect>
+ </property>
+ <property name="toolTip">
+ <string>Gradient Stops Editor</string>
+ </property>
+ <property name="whatsThis">
+ <string>This area allows you to edit gradient stops. Double click on the existing stop handle to duplicate it. Double click outside of the existing stop handles to create a new stop. Drag &amp; drop the handle to reposition it. Use right mouse button to popup context menu with extra actions.</string>
+ </property>
+ </widget>
+ <widget class="QLabel" name="zoomLabel">
+ <property name="geometry">
+ <rect>
+ <x>210</x>
+ <y>12</y>
+ <width>64</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Zoom</string>
+ </property>
+ </widget>
+ <widget class="QToolButton" name="zoomAllButton">
+ <property name="geometry">
+ <rect>
+ <x>280</x>
+ <y>41</y>
+ <width>72</width>
+ <height>26</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Reset Zoom</string>
+ </property>
+ <property name="text">
+ <string>Reset Zoom</string>
+ </property>
+ </widget>
+ <widget class="QLabel" name="positionLabel">
+ <property name="geometry">
+ <rect>
+ <x>210</x>
+ <y>85</y>
+ <width>64</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Position</string>
+ </property>
+ </widget>
+ <widget class="QLabel" name="hLabel">
+ <property name="geometry">
+ <rect>
+ <x>11</x>
+ <y>116</y>
+ <width>32</width>
+ <height>18</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Hue</string>
+ </property>
+ <property name="text">
+ <string>H</string>
+ </property>
+ </widget>
+ <widget class="QFrame" name="frame_2">
+ <property name="geometry">
+ <rect>
+ <x>49</x>
+ <y>114</y>
+ <width>155</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Ignored" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QHBoxLayout">
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QtColorLine" name="hueColorLine" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Hue</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QLabel" name="hueLabel">
+ <property name="geometry">
+ <rect>
+ <x>210</x>
+ <y>116</y>
+ <width>64</width>
+ <height>18</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Hue</string>
+ </property>
+ </widget>
+ <widget class="QLabel" name="sLabel">
+ <property name="geometry">
+ <rect>
+ <x>11</x>
+ <y>145</y>
+ <width>32</width>
+ <height>18</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Saturation</string>
+ </property>
+ <property name="text">
+ <string>S</string>
+ </property>
+ </widget>
+ <widget class="QFrame" name="frame_5">
+ <property name="geometry">
+ <rect>
+ <x>49</x>
+ <y>143</y>
+ <width>155</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Ignored" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QHBoxLayout">
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QtColorLine" name="saturationColorLine" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Saturation</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QLabel" name="saturationLabel">
+ <property name="geometry">
+ <rect>
+ <x>210</x>
+ <y>145</y>
+ <width>64</width>
+ <height>18</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Sat</string>
+ </property>
+ </widget>
+ <widget class="QLabel" name="vLabel">
+ <property name="geometry">
+ <rect>
+ <x>11</x>
+ <y>174</y>
+ <width>32</width>
+ <height>18</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Value</string>
+ </property>
+ <property name="text">
+ <string>V</string>
+ </property>
+ </widget>
+ <widget class="QFrame" name="frame_3">
+ <property name="geometry">
+ <rect>
+ <x>49</x>
+ <y>172</y>
+ <width>155</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Ignored" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QHBoxLayout">
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QtColorLine" name="valueColorLine" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Value</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QLabel" name="valueLabel">
+ <property name="geometry">
+ <rect>
+ <x>210</x>
+ <y>174</y>
+ <width>64</width>
+ <height>18</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Val</string>
+ </property>
+ </widget>
+ <widget class="QLabel" name="aLabel">
+ <property name="geometry">
+ <rect>
+ <x>11</x>
+ <y>203</y>
+ <width>32</width>
+ <height>18</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Alpha</string>
+ </property>
+ <property name="text">
+ <string>A</string>
+ </property>
+ </widget>
+ <widget class="QFrame" name="frame_4">
+ <property name="geometry">
+ <rect>
+ <x>49</x>
+ <y>201</y>
+ <width>155</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Ignored" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QHBoxLayout">
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QtColorLine" name="alphaColorLine" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Alpha</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QLabel" name="alphaLabel">
+ <property name="geometry">
+ <rect>
+ <x>210</x>
+ <y>203</y>
+ <width>64</width>
+ <height>18</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Alpha</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" name="typeComboBox">
+ <property name="geometry">
+ <rect>
+ <x>11</x>
+ <y>-179</y>
+ <width>79</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="toolTip">
+ <string>Type</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" name="spreadComboBox">
+ <property name="geometry">
+ <rect>
+ <x>97</x>
+ <y>-179</y>
+ <width>72</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="toolTip">
+ <string>Spread</string>
+ </property>
+ </widget>
+ <widget class="QLabel" name="colorLabel">
+ <property name="geometry">
+ <rect>
+ <x>11</x>
+ <y>79</y>
+ <width>32</width>
+ <height>29</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Color</string>
+ </property>
+ </widget>
+ <widget class="QtColorButton" name="colorButton">
+ <property name="geometry">
+ <rect>
+ <x>49</x>
+ <y>81</y>
+ <width>26</width>
+ <height>25</height>
+ </rect>
+ </property>
+ <property name="toolTip">
+ <string>Current stop's color</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ <widget class="QRadioButton" name="hsvRadioButton">
+ <property name="geometry">
+ <rect>
+ <x>81</x>
+ <y>82</y>
+ <width>49</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Show HSV specification</string>
+ </property>
+ <property name="text">
+ <string>HSV</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QRadioButton" name="rgbRadioButton">
+ <property name="geometry">
+ <rect>
+ <x>136</x>
+ <y>82</y>
+ <width>49</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Show RGB specification</string>
+ </property>
+ <property name="text">
+ <string>RGB</string>
+ </property>
+ </widget>
+ <widget class="QWidget" name="positionWidget" native="true">
+ <property name="geometry">
+ <rect>
+ <x>280</x>
+ <y>85</y>
+ <width>73</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout">
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QDoubleSpinBox" name="positionSpinBox">
+ <property name="toolTip">
+ <string>Current stop's position</string>
+ </property>
+ <property name="keyboardTracking">
+ <bool>false</bool>
+ </property>
+ <property name="decimals">
+ <number>3</number>
+ </property>
+ <property name="minimum">
+ <double>0.000000000000000</double>
+ </property>
+ <property name="maximum">
+ <double>1.000000000000000</double>
+ </property>
+ <property name="singleStep">
+ <double>0.010000000000000</double>
+ </property>
+ <property name="value">
+ <double>0.000000000000000</double>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="hueWidget" native="true">
+ <property name="geometry">
+ <rect>
+ <x>280</x>
+ <y>114</y>
+ <width>73</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout">
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QSpinBox" name="hueSpinBox">
+ <property name="keyboardTracking">
+ <bool>false</bool>
+ </property>
+ <property name="maximum">
+ <number>359</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="saturationWidget" native="true">
+ <property name="geometry">
+ <rect>
+ <x>280</x>
+ <y>143</y>
+ <width>73</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout">
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QSpinBox" name="saturationSpinBox">
+ <property name="keyboardTracking">
+ <bool>false</bool>
+ </property>
+ <property name="maximum">
+ <number>255</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="valueWidget" native="true">
+ <property name="geometry">
+ <rect>
+ <x>280</x>
+ <y>172</y>
+ <width>73</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout">
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QSpinBox" name="valueSpinBox">
+ <property name="keyboardTracking">
+ <bool>false</bool>
+ </property>
+ <property name="maximum">
+ <number>255</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="alphaWidget" native="true">
+ <property name="geometry">
+ <rect>
+ <x>280</x>
+ <y>201</y>
+ <width>73</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout">
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QSpinBox" name="alphaSpinBox">
+ <property name="keyboardTracking">
+ <bool>false</bool>
+ </property>
+ <property name="maximum">
+ <number>255</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="zoomWidget" native="true">
+ <property name="geometry">
+ <rect>
+ <x>280</x>
+ <y>12</y>
+ <width>73</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout">
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QSpinBox" name="zoomSpinBox">
+ <property name="keyboardTracking">
+ <bool>false</bool>
+ </property>
+ <property name="suffix">
+ <string>%</string>
+ </property>
+ <property name="minimum">
+ <number>100</number>
+ </property>
+ <property name="maximum">
+ <number>10000</number>
+ </property>
+ <property name="singleStep">
+ <number>100</number>
+ </property>
+ <property name="value">
+ <number>100</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="line1Widget" native="true">
+ <property name="geometry">
+ <rect>
+ <x>210</x>
+ <y>0</y>
+ <width>143</width>
+ <height>16</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout">
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="Line" name="line1">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="line2Widget" native="true">
+ <property name="geometry">
+ <rect>
+ <x>210</x>
+ <y>73</y>
+ <width>143</width>
+ <height>16</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout">
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="Line" name="line2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="zoomButtonsWidget" native="true">
+ <property name="geometry">
+ <rect>
+ <x>210</x>
+ <y>41</y>
+ <width>64</width>
+ <height>26</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <layout class="QHBoxLayout">
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QToolButton" name="zoomInButton">
+ <property name="toolTip">
+ <string>Zoom In</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="zoomOutButton">
+ <property name="toolTip">
+ <string>Zoom Out</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QToolButton" name="detailsButton">
+ <property name="geometry">
+ <rect>
+ <x>177</x>
+ <y>-179</y>
+ <width>25</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Ignored">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Toggle details extension</string>
+ </property>
+ <property name="text">
+ <string>&gt;</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="autoRaise">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QToolButton" name="linearButton">
+ <property name="geometry">
+ <rect>
+ <x>11</x>
+ <y>-209</y>
+ <width>30</width>
+ <height>26</height>
+ </rect>
+ </property>
+ <property name="toolTip">
+ <string>Linear Type</string>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="autoRaise">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QToolButton" name="radialButton">
+ <property name="geometry">
+ <rect>
+ <x>41</x>
+ <y>-209</y>
+ <width>30</width>
+ <height>26</height>
+ </rect>
+ </property>
+ <property name="toolTip">
+ <string>Radial Type</string>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="autoRaise">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QToolButton" name="conicalButton">
+ <property name="geometry">
+ <rect>
+ <x>71</x>
+ <y>-209</y>
+ <width>30</width>
+ <height>26</height>
+ </rect>
+ </property>
+ <property name="toolTip">
+ <string>Conical Type</string>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="autoRaise">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QToolButton" name="padButton">
+ <property name="geometry">
+ <rect>
+ <x>111</x>
+ <y>-209</y>
+ <width>30</width>
+ <height>26</height>
+ </rect>
+ </property>
+ <property name="toolTip">
+ <string>Pad Spread</string>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="autoRaise">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QToolButton" name="repeatButton">
+ <property name="geometry">
+ <rect>
+ <x>141</x>
+ <y>-209</y>
+ <width>30</width>
+ <height>26</height>
+ </rect>
+ </property>
+ <property name="toolTip">
+ <string>Repeat Spread</string>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="autoRaise">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QToolButton" name="reflectButton">
+ <property name="geometry">
+ <rect>
+ <x>171</x>
+ <y>-209</y>
+ <width>30</width>
+ <height>26</height>
+ </rect>
+ </property>
+ <property name="toolTip">
+ <string>Reflect Spread</string>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="autoRaise">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>QtColorButton</class>
+ <extends>QToolButton</extends>
+ <header>qtcolorbutton.h</header>
+ </customwidget>
+ <customwidget>
+ <class>QtColorLine</class>
+ <extends>QWidget</extends>
+ <header>qtcolorline.h</header>
+ <container>1</container>
+ </customwidget>
+ <customwidget>
+ <class>QtGradientStopsWidget</class>
+ <extends>QWidget</extends>
+ <header>qtgradientstopswidget.h</header>
+ <container>1</container>
+ </customwidget>
+ <customwidget>
+ <class>QtGradientWidget</class>
+ <extends>QWidget</extends>
+ <header>qtgradientwidget.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <tabstops>
+ <tabstop>typeComboBox</tabstop>
+ <tabstop>spreadComboBox</tabstop>
+ <tabstop>detailsButton</tabstop>
+ <tabstop>spinBox1</tabstop>
+ <tabstop>spinBox2</tabstop>
+ <tabstop>spinBox3</tabstop>
+ <tabstop>spinBox4</tabstop>
+ <tabstop>spinBox5</tabstop>
+ <tabstop>zoomSpinBox</tabstop>
+ <tabstop>zoomInButton</tabstop>
+ <tabstop>zoomOutButton</tabstop>
+ <tabstop>zoomAllButton</tabstop>
+ <tabstop>colorButton</tabstop>
+ <tabstop>hsvRadioButton</tabstop>
+ <tabstop>rgbRadioButton</tabstop>
+ <tabstop>positionSpinBox</tabstop>
+ <tabstop>hueSpinBox</tabstop>
+ <tabstop>saturationSpinBox</tabstop>
+ <tabstop>valueSpinBox</tabstop>
+ <tabstop>alphaSpinBox</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/plugins/qmldesigner/components/propertyeditor/images/button2_hovered.png b/src/plugins/qmldesigner/components/propertyeditor/images/button2_hovered.png
new file mode 100644
index 0000000000..b82f1fd006
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/images/button2_hovered.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/propertyeditor/images/button2_normal.png b/src/plugins/qmldesigner/components/propertyeditor/images/button2_normal.png
new file mode 100644
index 0000000000..4fef115d3e
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/images/button2_normal.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/propertyeditor/images/button2_pressed.png b/src/plugins/qmldesigner/components/propertyeditor/images/button2_pressed.png
new file mode 100644
index 0000000000..305530afaf
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/images/button2_pressed.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/propertyeditor/images/button_hovered.png b/src/plugins/qmldesigner/components/propertyeditor/images/button_hovered.png
new file mode 100644
index 0000000000..2dc66ec3e3
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/images/button_hovered.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/propertyeditor/images/button_normal.png b/src/plugins/qmldesigner/components/propertyeditor/images/button_normal.png
new file mode 100644
index 0000000000..ca29772319
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/images/button_normal.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/propertyeditor/images/button_pressed.png b/src/plugins/qmldesigner/components/propertyeditor/images/button_pressed.png
new file mode 100644
index 0000000000..7cf55d718d
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/images/button_pressed.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/propertyeditor/images/frame.png b/src/plugins/qmldesigner/components/propertyeditor/images/frame.png
new file mode 100644
index 0000000000..a951609018
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/images/frame.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/propertyeditor/images/gradient.png b/src/plugins/qmldesigner/components/propertyeditor/images/gradient.png
new file mode 100644
index 0000000000..0cdbcdec0b
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/images/gradient.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/propertyeditor/layoutwidget.cpp b/src/plugins/qmldesigner/components/propertyeditor/layoutwidget.cpp
new file mode 100644
index 0000000000..031fb9e99e
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/layoutwidget.cpp
@@ -0,0 +1,106 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "layoutwidget.h"
+#include <QGridLayout>
+#include <QFile>
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+
+
+LayoutWidget::LayoutWidget(QWidget *parent) : QFrame(parent)
+{
+ QSizePolicy policy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+
+ QGridLayout *grid = new QGridLayout(this);
+ setLayout(grid);
+ grid->setContentsMargins(0,0,0,0);
+ grid->setSpacing(4);
+
+ m_topButton = new QPushButton(this);
+ m_topButton->setCheckable(true);
+ m_topButton->setSizePolicy(policy);
+
+ grid->addWidget(m_topButton, 0, 2, 2, 1, Qt::AlignHCenter);
+
+ m_bottomButton = new QPushButton(this);
+ m_bottomButton->setCheckable(true);
+
+ m_bottomButton->setSizePolicy(policy);
+
+ grid->addWidget(m_bottomButton, 3, 2, 2, 1, Qt::AlignHCenter);
+
+ m_leftButton = new QPushButton(this);
+ m_leftButton->setCheckable(true);
+ m_leftButton->setSizePolicy(policy);
+
+
+ grid->addWidget(m_leftButton, 2, 0, 1, 2, Qt::AlignVCenter);
+
+ m_rightButton = new QPushButton(this);
+ m_rightButton->setCheckable(true);
+ m_rightButton->setSizePolicy(policy);
+
+ grid->addWidget(m_rightButton, 2, 3, 1, 2, Qt::AlignVCenter);
+
+
+ m_middleButton = new QPushButton(this);
+
+ grid->addWidget(m_middleButton, 2, 2, 1, 1, Qt::AlignCenter);
+
+ connect(m_topButton, SIGNAL(toggled(bool)), this, SLOT(setTopAnchor(bool)));
+ connect(m_bottomButton, SIGNAL(toggled(bool)), this, SLOT(setBottomAnchor(bool)));
+ connect(m_leftButton, SIGNAL(toggled(bool)), this, SLOT(setLeftAnchor(bool)));
+ connect(m_rightButton, SIGNAL(toggled(bool)), this, SLOT(setRightAnchor(bool)));
+
+ connect(m_middleButton, SIGNAL(pressed()), this, SIGNAL(fill()));
+}
+
+LayoutWidget::~LayoutWidget()
+{
+}
+
+ void LayoutWidget::setIcon(QPushButton *button, QUrl url)
+ {
+ if (url.scheme() == QLatin1String("file")) {
+ QFile file(url.toLocalFile());
+ file.open(QIODevice::ReadOnly);
+ if (file.isOpen()) {
+ QPixmap pixmap(url.toLocalFile());
+ button->setIcon(pixmap);
+ } else {
+ qWarning() << QLatin1String("setIconFromFile: ") << url << QLatin1String(" not found!");
+ }
+ }
+ }
+
+QT_END_NAMESPACE
+
+
diff --git a/src/plugins/qmldesigner/components/propertyeditor/layoutwidget.h b/src/plugins/qmldesigner/components/propertyeditor/layoutwidget.h
new file mode 100644
index 0000000000..82f7a4a269
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/layoutwidget.h
@@ -0,0 +1,137 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+
+#ifndef LAYOUTWIDGET_H
+#define LAYOUTWIDGET_H
+
+#include <QtGui/QFrame>
+#include <QLabel>
+#include <QPushButton>
+#include <QUrl>
+
+QT_BEGIN_NAMESPACE
+
+class LayoutWidget : public QFrame
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool leftAnchor READ leftAnchor WRITE setLeftAnchor NOTIFY leftAnchorChanged)
+ Q_PROPERTY(bool rightAnchor READ rightAnchor WRITE setRightAnchor NOTIFY rightAnchorChanged)
+ Q_PROPERTY(bool bottomAnchor READ bottomAnchor WRITE setBottomAnchor NOTIFY bottomAnchorChanged)
+ Q_PROPERTY(bool topAnchor READ topAnchor WRITE setTopAnchor NOTIFY topAnchorChanged)
+
+ Q_PROPERTY(QUrl leftButtonIcon READ icon WRITE setLeftButtonIcon)
+ Q_PROPERTY(QUrl rightButtonIcon READ icon WRITE setRightButtonIcon)
+ Q_PROPERTY(QUrl topButtonIcon READ icon WRITE setTopButtonIcon)
+ Q_PROPERTY(QUrl bottomButtonIcon READ icon WRITE setBottomButtonIcon)
+
+public:
+
+ void setLeftButtonIcon(const QUrl &url)
+ { setIcon(m_leftButton, url); }
+
+ void setRightButtonIcon(const QUrl &url)
+ { setIcon(m_rightButton, url); }
+
+ void setTopButtonIcon(const QUrl &url)
+ { setIcon(m_topButton, url); }
+
+ void setBottomButtonIcon(const QUrl &url)
+ { setIcon(m_bottomButton, url); }
+
+ QUrl icon() const {return QUrl(); }
+
+ LayoutWidget(QWidget *parent = 0);
+ ~LayoutWidget();
+
+ bool leftAnchor() const { return m_leftAnchor; }
+ bool rightAnchor() const { return m_rightAnchor; }
+ bool topAnchor() const { return m_topAnchor; }
+ bool bottomAnchor() const { return m_bottomAnchor; }
+
+public slots:
+ void setLeftAnchor(bool anchor)
+ {
+ if (anchor == m_leftAnchor)
+ return;
+ m_leftAnchor = anchor;
+ m_leftButton->setChecked(anchor);
+ emit leftAnchorChanged();
+ }
+
+ void setRightAnchor(bool anchor)
+ {
+ if (anchor == m_rightAnchor)
+ return;
+ m_rightAnchor = anchor;
+ m_rightButton->setChecked(anchor);
+ emit rightAnchorChanged();
+ }
+
+ void setTopAnchor(bool anchor)
+ {
+ if (anchor == m_topAnchor)
+ return;
+ m_topAnchor = anchor;
+ m_topButton->setChecked(anchor);
+ emit topAnchorChanged();
+ }
+
+ void setBottomAnchor(bool anchor)
+ {
+ if (anchor == m_bottomAnchor)
+ return;
+ m_bottomAnchor = anchor;
+ m_bottomButton->setChecked(anchor);
+ emit bottomAnchorChanged();
+ }
+
+signals:
+ //void colorChanged(const QColor &color);
+ void fill();
+ void topAnchorChanged();
+ void bottomAnchorChanged();
+ void leftAnchorChanged();
+ void rightAnchorChanged();
+
+private:
+ void setIcon(QPushButton *button, QUrl url);
+ bool m_leftAnchor, m_rightAnchor, m_topAnchor, m_bottomAnchor;
+ QPushButton *m_leftButton;
+ QPushButton *m_rightButton;
+ QPushButton *m_topButton;
+ QPushButton *m_bottomButton;
+ QPushButton *m_middleButton;
+};
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.cpp
new file mode 100644
index 0000000000..997975ffc2
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.cpp
@@ -0,0 +1,583 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "propertyeditor.h"
+
+#include <nodemetainfo.h>
+
+#include <propertymetainfo.h>
+
+#include <invalididexception.h>
+#include <invalidnodestateexception.h>
+#include <variantproperty.h>
+
+#include "propertyeditorvalue.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDir>
+#include <QtCore/QFileSystemWatcher>
+#include <QtCore/QFileInfo>
+#include <QtCore/QDebug>
+#include <QtDeclarative/QmlView>
+#include <QtDeclarative/QmlContext>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QShortcut>
+#include <QtGui/QStackedWidget>
+#include <QmlEngine>
+#include <QmlMetaType>
+
+enum {
+ debug = false
+};
+
+namespace QmlDesigner {
+
+PropertyEditor::NodeType::NodeType(const QUrl &qmlFile, PropertyEditor *propertyEditor) :
+ m_view(new QmlView)
+{
+ Q_ASSERT(QFileInfo(":/images/button_normal.png").exists());
+
+ m_view->setContentResizable(true);
+ m_view->setUrl(qmlFile);
+
+ connect(&m_backendValuesPropertyMap, SIGNAL(valueChanged(const QString&)), propertyEditor, SLOT(changeValue(const QString&)));
+}
+
+PropertyEditor::NodeType::~NodeType()
+{
+}
+
+void createPropertyEditorValue(const QmlObjectNode &fxObjectNode, const QString &name, const QVariant &value, QmlPropertyMap *propertyMap)
+{
+ QString propertyName(name);
+ propertyName.replace(".", "_");
+ PropertyEditorValue *valueObject = new PropertyEditorValue(propertyMap);
+ valueObject->setName(propertyName);
+ valueObject->setIsInModel(fxObjectNode.modelNode().hasProperty(name));
+ valueObject->setIsInSubState(fxObjectNode.propertyAffectedByCurrentState(name));
+ valueObject->setModelNode(fxObjectNode.modelNode());
+
+ if (fxObjectNode.propertyAffectedByCurrentState(name) && !(fxObjectNode.modelNode().property(propertyName).isBindingProperty())) {
+ valueObject->setValue(fxObjectNode.modelValue(name));
+
+ } else {
+ valueObject->setValue(value);
+ }
+
+ if (propertyName != QLatin1String("id") &&
+ fxObjectNode.currentState().isBaseState() &&
+ fxObjectNode.modelNode().property(propertyName).isBindingProperty()) {
+ valueObject->setExpression(fxObjectNode.modelNode().bindingProperty(propertyName).expression());
+ } else {
+ valueObject->setExpression(fxObjectNode.instanceValue(name).toString());
+ }
+
+ QObject::connect(valueObject, SIGNAL(valueChanged(QString)), propertyMap, SIGNAL(valueChanged(QString)));
+ propertyMap->insert(propertyName, QmlMetaType::qmlType(valueObject->metaObject())->fromObject(valueObject));
+}
+
+void PropertyEditor::NodeType::setValue(const QmlObjectNode &fxObjectNode, const QString &name, const QVariant &value)
+{
+ createPropertyEditorValue(fxObjectNode, name, value, &m_backendValuesPropertyMap);
+}
+
+void PropertyEditor::NodeType::setup(const QmlObjectNode &fxObjectNode, const QString &stateName, const QUrl &qmlSpecificsFile)
+{
+ if (!fxObjectNode.isValid())
+ return;
+
+ QmlContext *ctxt = m_view->rootContext();
+
+ // First remove complex objects from backend, so that we don't trigger a flood of updates
+ ctxt->setContextProperty("anchorBackend", 0);
+ ctxt->setContextProperty("backendValues", 0);
+
+ foreach (const QString &propertyName, m_backendValuesPropertyMap.keys())
+ m_backendValuesPropertyMap.clear(propertyName);
+ qDeleteAll(m_backendValuesPropertyMap.children());
+
+ if (fxObjectNode.isValid()) {
+ foreach (const QString &propertyName, fxObjectNode.modelNode().metaInfo().properties(true).keys())
+ createPropertyEditorValue(fxObjectNode, propertyName, fxObjectNode.instanceValue(propertyName), &m_backendValuesPropertyMap);
+
+ // className
+ PropertyEditorValue *valueObject = new PropertyEditorValue(&m_backendValuesPropertyMap);
+ valueObject->setName("className");
+ valueObject->setModelNode(fxObjectNode.modelNode());
+ valueObject->setValue(fxObjectNode.modelNode().simplifiedTypeName());
+ QObject::connect(valueObject, SIGNAL(valueChanged(QString)), &m_backendValuesPropertyMap, SIGNAL(valueChanged(QString)));
+ m_backendValuesPropertyMap.insert("className", QmlMetaType::qmlType(valueObject->metaObject())->fromObject(valueObject));
+
+ // id
+ valueObject = new PropertyEditorValue(&m_backendValuesPropertyMap);
+ valueObject->setName("id");
+ valueObject->setIsInModel(!fxObjectNode.modelNode().id().isEmpty());
+ valueObject->setModelNode(fxObjectNode.modelNode());
+ valueObject->setValue(fxObjectNode.modelNode().id());
+ QObject::connect(valueObject, SIGNAL(valueChanged(QString)), &m_backendValuesPropertyMap, SIGNAL(valueChanged(QString)));
+ m_backendValuesPropertyMap.insert("id", QmlMetaType::qmlType(valueObject->metaObject())->fromObject(valueObject));
+
+ // anchors
+ m_backendAnchorBinding.setup(QmlItemNode(fxObjectNode.modelNode()));
+
+ ctxt->setContextProperty("anchorBackend", &m_backendAnchorBinding);
+ ctxt->setContextProperty("backendValues", &m_backendValuesPropertyMap);
+
+ ctxt->setContextProperty("specificsUrl", QVariant(qmlSpecificsFile));
+ ctxt->setContextProperty("stateName", QVariant(stateName));
+ ctxt->setContextProperty("propertyCount", QVariant(fxObjectNode.modelNode().properties().count()));
+ ctxt->setContextProperty("isBaseState", QVariant(fxObjectNode.isInBaseState()));
+ } else {
+ qWarning() << "PropertyEditor: invalid node for setup";
+ }
+}
+
+PropertyEditor::PropertyEditor(QWidget *parent) :
+ QmlModelView(parent),
+ m_parent(parent),
+ m_updateShortcut(0),
+ m_timerId(0),
+ m_stackedWidget(new QStackedWidget(parent)),
+ m_currentType(0)
+{
+ m_updateShortcut = new QShortcut(QKeySequence("F5"), m_stackedWidget);
+ connect(m_updateShortcut, SIGNAL(activated()), this, SLOT(reloadQml()));
+
+ QFile file(":/qmldesigner/stylesheet.css");
+ file.open(QFile::ReadOnly);
+ QString styleSheet = QLatin1String(file.readAll());
+ m_stackedWidget->setStyleSheet(styleSheet);
+ m_stackedWidget->setMinimumWidth(320);
+}
+
+PropertyEditor::~PropertyEditor()
+{
+ delete m_stackedWidget;
+ qDeleteAll(m_typeHash);
+}
+
+void PropertyEditor::changeValue(const QString &name)
+{
+ if (name == "type")
+ return;
+
+ if (name == "id") {
+ PropertyEditorValue *value = qobject_cast<PropertyEditorValue*>(QmlMetaType::toQObject(m_currentType->m_backendValuesPropertyMap.value(name)));
+ const QString newId = value->value().toString();
+
+ try {
+ if (ModelNode::isValidId(newId))
+ m_selectedNode.setId(newId);
+ else
+ value->setValue(m_selectedNode.id());
+ } catch (InvalidIdException &) {
+ value->setValue(m_selectedNode.id());
+ }
+
+ return;
+ }
+
+ QString propertyName(name);
+ propertyName.replace("_", ".");
+
+ PropertyEditorValue *value = qobject_cast<PropertyEditorValue*>(QmlMetaType::toQObject(m_currentType->m_backendValuesPropertyMap.value(name)));
+
+
+ if (value ==0) {
+ qWarning() << "PropertyEditor:" <<name << " - value is null";
+ return;
+ }
+
+ QmlObjectNode fxObjectNode(m_selectedNode);
+
+ QVariant castedValue;
+ qreal castedExpressionValue;
+ bool converted = false;
+
+
+ if (fxObjectNode.modelNode().metaInfo().isValid() && fxObjectNode.modelNode().metaInfo().property(propertyName, true).isValid()) {
+ castedValue = fxObjectNode.modelNode().metaInfo().property(propertyName, true).castedValue(value->value());
+ castedExpressionValue = value->expression().toDouble(&converted);
+ } else {
+ qWarning() << "PropertyEditor:" <<name << "cannot be casted (metainfo)";
+ return ;
+ }
+
+ if (value->value().isValid() && !castedValue.isValid()) {
+ qWarning() << "PropertyEditor:" <<name << "not properly casted (metainfo)";
+ return ;
+ }
+
+ if (fxObjectNode.modelNode().metaInfo().isValid() && fxObjectNode.modelNode().metaInfo().property(propertyName).isValid())
+ if (fxObjectNode.modelNode().metaInfo().property(propertyName).type() == QLatin1String("QUrl")) { //turn absolute local file paths into relative paths
+ QString filePath = castedValue.toUrl().toString();
+ if (QFileInfo(filePath).exists() && QFileInfo(filePath).isAbsolute()) {
+ QDir fileDir(QFileInfo(model()->fileUrl().toLocalFile()).absolutePath());
+ castedValue = QUrl(fileDir.relativeFilePath(filePath));
+ }
+ }
+
+
+ if (value->expression() == value->value().toString() || !value->value().isValid() || converted) {
+ if (converted)
+ castedValue = castedExpressionValue;
+
+ if (!value->value().isValid()) {
+ fxObjectNode.removeVariantProperty(propertyName);
+ } else {
+ if (value->value().canConvert<ModelNode>()) {
+ ; //fxObjectNode.setVariantProperty(propertyName, value->value().value<NodeState>().modelNode().toVariant()); ### hmmm only in basestate blah blah
+ } else {
+ if (castedValue.isValid() && !castedValue.isNull())
+ fxObjectNode.setVariantProperty(propertyName, castedValue);
+ }
+ }
+ } else { //expression
+ changeExpression(name);
+ }
+}
+
+void PropertyEditor::changeExpression(const QString &name)
+{
+ QmlObjectNode fxObjectNode(m_selectedNode);
+ PropertyEditorValue *value = qobject_cast<PropertyEditorValue*>(QmlMetaType::toQObject(m_currentType->m_backendValuesPropertyMap.value(name)));
+ if (fxObjectNode.currentState().isBaseState()) {
+ fxObjectNode.modelNode().bindingProperty(name).setExpression(value->expression());
+ }
+}
+
+void PropertyEditor::otherPropertyChanged(const QmlObjectNode &fxObjectNode)
+{
+ if (fxObjectNode.isValid() && m_currentType && fxObjectNode == m_selectedNode && fxObjectNode.currentState().isValid()) {
+ foreach (const QString &propertyName, fxObjectNode.modelNode().metaInfo().properties(true).keys()) {
+ if ( propertyName != "id" && propertyName != "objectName") {
+ QString name(propertyName);
+ name.replace(".", "_");
+ QVariant backendValue(m_currentType->m_backendValuesPropertyMap.value(propertyName));
+ PropertyEditorValue *valueObject = 0;
+ if (backendValue.isValid())
+ valueObject = qobject_cast<PropertyEditorValue*>(QmlMetaType::toQObject(backendValue));
+ else
+ valueObject = new PropertyEditorValue(&m_currentType->m_backendValuesPropertyMap);
+
+ if (valueObject == 0) {
+ qWarning() << "PropertyEditor: you propably assigned a wrong value to backendValues";
+ return;
+ }
+
+ valueObject->setName(propertyName);
+ valueObject->setIsInModel(fxObjectNode.hasProperty(propertyName));
+ valueObject->setIsInSubState(fxObjectNode.propertyAffectedByCurrentState(propertyName));
+ valueObject->setModelNode(fxObjectNode.modelNode());
+
+ if (fxObjectNode.modelNode().property(propertyName).isBindingProperty())
+ valueObject->setValue(fxObjectNode.instanceValue(propertyName));
+ else
+ valueObject->setValue(fxObjectNode.modelValue(propertyName));
+
+ connect(valueObject, SIGNAL(valueChanged(QString)), &m_currentType->m_backendValuesPropertyMap, SIGNAL(valueChanged(QString)));
+ m_currentType->m_backendValuesPropertyMap.insert(propertyName, QmlMetaType::qmlType(valueObject->metaObject())->fromObject(valueObject));
+ }
+ }
+ }
+}
+
+void PropertyEditor::setQmlDir(const QString &qmlDir)
+{
+ m_qmlDir = qmlDir;
+
+ QFileSystemWatcher *watcher = new QFileSystemWatcher(this);
+ watcher->addPath(m_qmlDir);
+ connect(watcher, SIGNAL(directoryChanged(QString)), this, SLOT(reloadQml()));
+}
+
+void PropertyEditor::delayedResetView()
+{
+ if (m_timerId == 0)
+ m_timerId = startTimer(50);
+}
+
+void PropertyEditor::timerEvent(QTimerEvent *timerEvent)
+{
+ if (m_timerId == timerEvent->timerId()) {
+ resetView();
+ }
+}
+
+void PropertyEditor::resetView()
+{
+ if (model() == 0)
+ return;
+
+ if (debug)
+ qDebug() << "________________ RELOADING PROPERTY EDITOR QML _______________________";
+
+ if (m_timerId)
+ killTimer(m_timerId);
+
+ if (m_selectedNode.isValid() && model() != m_selectedNode.model())
+ m_selectedNode = ModelNode();
+
+ QUrl qmlFile(qmlForNode(m_selectedNode));
+ QUrl qmlSpecificsFile;
+ if (m_selectedNode.isValid())
+ qmlSpecificsFile = fileToUrl(locateQmlFile(m_selectedNode.type() + "Specifics.qml"));
+
+ NodeType *type = m_typeHash.value(qmlFile.toString());
+ if (!type) {
+ type = new NodeType(qmlFile, this);
+
+ m_stackedWidget->addWidget(type->m_view);
+ m_typeHash.insert(qmlFile.toString(), type);
+
+ QmlObjectNode fxObjectNode;
+ if (m_selectedNode.isValid()) {
+ fxObjectNode = QmlObjectNode(m_selectedNode);
+ Q_ASSERT(fxObjectNode.isValid());
+ }
+ type->setup(fxObjectNode, currentState().name(), qmlSpecificsFile);
+
+ QmlContext *ctxt = type->m_view->rootContext();
+ ctxt->setContextProperty("finishedNotify", QVariant(false));
+ type->m_view->execute();
+ ctxt->setContextProperty("finishedNotify", QVariant(true));
+ } else {
+ QmlObjectNode fxObjectNode;
+ if (m_selectedNode.isValid()) {
+ fxObjectNode = QmlObjectNode(m_selectedNode);
+ }
+ type->setup(fxObjectNode, currentState().name(), qmlSpecificsFile);
+ }
+
+ m_stackedWidget->setCurrentWidget(type->m_view);
+ m_currentType = type;
+
+ if (m_timerId)
+ m_timerId = 0;
+}
+
+void PropertyEditor::selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
+ const QList<ModelNode> &lastSelectedNodeList)
+{
+ Q_UNUSED(lastSelectedNodeList);
+
+ if (m_selectedNode.isValid() && selectedNodeList.contains(m_selectedNode))
+ return;
+
+ if (selectedNodeList.isEmpty())
+ select(ModelNode());
+ else
+ select(selectedNodeList.first());
+}
+
+void PropertyEditor::nodeAboutToBeRemoved(const ModelNode &removedNode)
+{
+ QmlModelView::nodeAboutToBeRemoved(removedNode);
+ if (m_selectedNode.isValid() && removedNode.isValid() && m_selectedNode == removedNode)
+ select(m_selectedNode.parentProperty().parentModelNode());
+}
+
+void PropertyEditor::modelAttached(Model *model)
+{
+ QmlModelView::modelAttached(model);
+
+ if (debug)
+ qDebug() << Q_FUNC_INFO;
+
+ resetView();
+}
+
+void PropertyEditor::modelAboutToBeDetached(Model *model)
+{
+ QmlModelView::modelAboutToBeDetached(model);
+
+ resetView();
+}
+
+
+void PropertyEditor::propertiesAboutToBeRemoved(const QList<AbstractProperty>& propertyList)
+{
+ QmlModelView::propertiesAboutToBeRemoved(propertyList);
+
+ if (!m_selectedNode.isValid())
+ return;
+
+ foreach (const AbstractProperty &property, propertyList) {
+ if (property.isVariantProperty() || property.isBindingProperty()) {
+ ModelNode node(property.parentModelNode());
+ m_currentType->setValue(node, property.name(), QmlObjectNode(node).instanceValue(property.name()));
+ }
+ }
+}
+
+
+void PropertyEditor::variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags propertyChange)
+{
+ QmlModelView::variantPropertiesChanged(propertyList, propertyChange);
+
+ if (!m_selectedNode.isValid())
+ return;
+
+ foreach (const VariantProperty &property, propertyList) {
+ ModelNode node(property.parentModelNode());
+
+ if (node == m_selectedNode || QmlObjectNode(m_selectedNode).propertyChangeForCurrentState() == node) {
+ if ( QmlObjectNode(m_selectedNode).modelNode().property(property.name()).isBindingProperty())
+ m_currentType->setValue(m_selectedNode, property.name(), QmlObjectNode(m_selectedNode).instanceValue(property.name()));
+ else
+ m_currentType->setValue(m_selectedNode, property.name(), QmlObjectNode(m_selectedNode).modelValue(property.name()));
+ }
+ }
+}
+
+void PropertyEditor::bindingPropertiesChanged(const QList<BindingProperty>& propertyList, PropertyChangeFlags propertyChange)
+{
+ QmlModelView::bindingPropertiesChanged(propertyList, propertyChange);
+
+ if (!m_selectedNode.isValid())
+ return;
+
+ foreach (const BindingProperty &property, propertyList) {
+ ModelNode node(property.parentModelNode());
+
+ if (node == m_selectedNode || QmlObjectNode(m_selectedNode).propertyChangeForCurrentState() == node) {
+ if ( QmlObjectNode(m_selectedNode).modelNode().property(property.name()).isBindingProperty())
+ m_currentType->setValue(m_selectedNode, property.name(), QmlObjectNode(m_selectedNode).instanceValue(property.name()));
+ else
+ m_currentType->setValue(m_selectedNode, property.name(), QmlObjectNode(m_selectedNode).modelValue(property.name()));
+ }
+ }
+}
+
+void PropertyEditor::nodeIdChanged(const ModelNode& node, const QString& newId, const QString& oldId)
+{
+ QmlModelView::nodeIdChanged(node, newId, oldId);
+
+ if (!m_selectedNode.isValid())
+ return;
+
+ if (node == m_selectedNode) {
+
+ if (m_currentType) {
+ m_currentType->setValue(node, "id", newId);
+ }
+ }
+}
+
+void PropertyEditor::select(const ModelNode &node)
+{
+ if (node.isValid())
+ m_selectedNode = node;
+ else
+ m_selectedNode = ModelNode();
+
+ delayedResetView();
+}
+
+QWidget *PropertyEditor::createPropertiesPage()
+{
+ delayedResetView();
+ return m_stackedWidget;
+}
+
+void PropertyEditor::stateChanged(const QmlModelState &newQmlModelState, const QmlModelState &oldQmlModelState)
+{
+ QmlModelView::stateChanged(newQmlModelState, oldQmlModelState);
+ Q_ASSERT(newQmlModelState.isValid());
+ if (debug)
+ qDebug() << Q_FUNC_INFO << newQmlModelState.name();
+ delayedResetView();
+}
+
+void PropertyEditor::reloadQml()
+{
+ m_typeHash.clear();
+ while (QWidget *widget = m_stackedWidget->widget(0)) {
+ m_stackedWidget->removeWidget(widget);
+ delete widget;
+ }
+ m_currentType = 0;
+
+ delayedResetView();
+}
+
+QString PropertyEditor::qmlFileName(const NodeMetaInfo &nodeInfo) const
+{
+ return nodeInfo.typeName() + QLatin1String("Pane.qml");
+}
+
+QUrl PropertyEditor::fileToUrl(const QString &filePath) const {
+ QUrl fileUrl;
+
+ if (filePath.isEmpty())
+ return fileUrl;
+
+ if (filePath.startsWith(":")) {
+ fileUrl.setScheme("qrc");
+ QString path = filePath;
+ path.remove(0, 1); // remove trailing ':'
+ fileUrl.setPath(path);
+ } else {
+ fileUrl = QUrl::fromLocalFile(filePath);
+ }
+
+ return fileUrl;
+}
+
+QUrl PropertyEditor::qmlForNode(const ModelNode &modelNode) const
+{
+ if (modelNode.isValid()) {
+ QList<NodeMetaInfo> hierarchy;
+ hierarchy << modelNode.metaInfo();
+ hierarchy << modelNode.metaInfo().superClasses();
+
+ foreach (const NodeMetaInfo &info, hierarchy) {
+ QUrl fileUrl = fileToUrl(locateQmlFile(qmlFileName(info)));
+ if (fileUrl.isValid())
+ return fileUrl;
+ }
+ }
+ return fileToUrl(QDir(m_qmlDir).filePath("Qt/emptyPane.qml"));
+}
+
+QString PropertyEditor::locateQmlFile(const QString &relativePath) const
+{
+ QDir fileSystemDir(m_qmlDir);
+ static QDir resourcesDir(":/propertyeditor");
+
+ if (fileSystemDir.exists(relativePath))
+ return fileSystemDir.absoluteFilePath(relativePath);
+ if (resourcesDir.exists(relativePath))
+ return resourcesDir.absoluteFilePath(relativePath);
+
+ return QString();
+}
+
+} //QmlDesigner
+
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.h b/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.h
new file mode 100644
index 0000000000..6f3672ed8f
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.h
@@ -0,0 +1,126 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef QmlPropertyView_h
+#define QmlPropertyView_h
+
+#include <qmlmodelview.h>
+#include <QmlView>
+#include <QHash>
+#include <QmlPropertyMap>
+
+#include "qmlanchorbindingproxy.h"
+
+class QShortcut;
+class QStackedWidget;
+
+namespace QmlDesigner {
+
+class PropertyEditor: public QmlModelView
+{
+ Q_OBJECT
+
+ class NodeType {
+ public:
+ NodeType(const QUrl &qmlFile, PropertyEditor *propertyEditor);
+ ~NodeType();
+
+ void setup(const QmlObjectNode &fxObjectNode, const QString &stateName, const QUrl &qmlSpecificsFile);
+ void setValue(const QmlObjectNode &fxObjectNode, const QString &name, const QVariant &value);
+
+ QmlView *m_view;
+ Internal::QmlAnchorBindingProxy m_backendAnchorBinding;
+ QmlPropertyMap m_backendValuesPropertyMap;
+ };
+
+public:
+ PropertyEditor(QWidget *parent = 0);
+ ~PropertyEditor();
+
+ void setQmlDir(const QString &qmlDirPath);
+
+ QWidget* createPropertiesPage();
+
+ void selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
+ const QList<ModelNode> &lastSelectedNodeList);
+ void nodeAboutToBeRemoved(const ModelNode &removedNode);
+
+ void propertiesAdded(const NodeState &state, const QList<NodeProperty>& propertyList);
+ void propertiesAboutToBeRemoved(const NodeState &state, const QList<NodeProperty>& propertyList);
+ void propertyValuesChanged(const NodeState &state, const QList<NodeProperty>& propertyList);
+
+ void modelAttached(Model *model);
+
+ void modelAboutToBeDetached(Model *model);
+
+ ModelState modelState() const;
+
+ void otherPropertyChanged(const QmlObjectNode &);
+
+ void stateChanged(const QmlModelState &newQmlModelState, const QmlModelState &oldQmlModelState);
+
+ void propertiesAboutToBeRemoved(const QList<AbstractProperty>& propertyList);
+ void variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags propertyChange);
+ void bindingPropertiesChanged(const QList<BindingProperty>& propertyList, PropertyChangeFlags propertyChange);
+
+ void nodeIdChanged(const ModelNode& node, const QString& newId, const QString& oldId);
+
+protected:
+ void timerEvent(QTimerEvent *event);
+
+private slots:
+ void reloadQml();
+ void changeValue(const QString &name);
+ void changeExpression(const QString &name);
+
+private: //functions
+ QString qmlFileName(const NodeMetaInfo &nodeInfo) const;
+ QUrl fileToUrl(const QString &filePath) const;
+ QUrl qmlForNode(const ModelNode &modelNode) const;
+ QString locateQmlFile(const QString &relativePath) const;
+ void select(const ModelNode& node);
+
+ void resetView();
+ void delayedResetView();
+
+
+private: //variables
+ ModelNode m_selectedNode;
+ QWidget *m_parent;
+ QShortcut *m_updateShortcut;
+ int m_timerId;
+ QStackedWidget* m_stackedWidget;
+ QString m_qmlDir;
+ QHash<QString, NodeType *> m_typeHash;
+ NodeType *m_currentType;
+};
+
+}
+
+#endif // QmlPropertyView_h
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.pri b/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.pri
new file mode 100644
index 0000000000..4d0fc95a6f
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.pri
@@ -0,0 +1,34 @@
+VPATH += $$PWD
+INCLUDEPATH += $$PWD
+include($$PWD/qtgradienteditor/qtgradienteditor.pri)
+SOURCES += propertyeditor.cpp \
+ qmlanchorbindingproxy.cpp \
+ allpropertiesbox.cpp \
+ resetwidget.cpp \
+ qlayoutobject.cpp \
+ basiclayouts.cpp \
+ basicwidgets.cpp \
+ colorwidget.cpp \
+ behaviordialog.cpp \
+ qproxylayoutitem.cpp \
+ layoutwidget.cpp \
+ filewidget.cpp \
+ propertyeditorvalue.cpp \
+ fontwidget.cpp
+HEADERS += propertyeditor.h \
+ qmlanchorbindingproxy.h \
+ allpropertiesbox.h \
+ resetwidget.h \
+ qlayoutobject.h \
+ basiclayouts.h \
+ basicwidgets.h \
+ colorwidget.h \
+ behaviordialog.h \
+ qproxylayoutitem.h \
+ layoutwidget.h \
+ filewidget.h \
+ propertyeditorvalue.h \
+ fontwidget.h
+QT += declarative
+RESOURCES += propertyeditor.qrc
+FORMS += behaviordialog.ui
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.qrc b/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.qrc
new file mode 100644
index 0000000000..61d22611ba
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.qrc
@@ -0,0 +1,12 @@
+<RCC>
+ <qresource prefix="/">
+ <file>images/button_hovered.png</file>
+ <file>images/button_normal.png</file>
+ <file>images/button_pressed.png</file>
+ <file>images/button2_hovered.png</file>
+ <file>images/button2_normal.png</file>
+ <file>images/button2_pressed.png</file>
+ <file>images/frame.png</file>
+ <file>images/gradient.png</file>
+ </qresource>
+</RCC>
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp
new file mode 100644
index 0000000000..c08b535a2a
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp
@@ -0,0 +1,343 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "propertyeditorvalue.h"
+#include <abstractview.h>
+#include <nodeabstractproperty.h>
+#include <nodeproperty.h>
+#include <model.h>
+#include <nodemetainfo.h>
+#include <metainfo.h>
+#include <propertymetainfo.h>
+#include <nodeproperty.h>
+#include <qmlobjectnode.h>
+
+QML_DEFINE_TYPE(Bauhaus,1,0,PropertyEditorValue,PropertyEditorValue)
+QML_DEFINE_TYPE(Bauhaus,1,0,PropertyEditorNodeWrapper,PropertyEditorNodeWrapper)
+QML_DEFINE_TYPE(Bauhaus,1,0,QmlPropertyMap,QmlPropertyMap)
+
+
+//using namespace QmlDesigner;
+
+PropertyEditorValue::PropertyEditorValue(QObject *parent)
+ : QObject(parent),
+ m_isInSubState(false),
+ m_isInModel(false),
+ m_isBound(false),
+ m_isValid(false),
+ m_complexNode(new PropertyEditorNodeWrapper(this))
+{
+}
+
+QVariant PropertyEditorValue::value() const
+{
+ QVariant returnValue = m_value;
+ if (modelNode().metaInfo().isValid() && modelNode().metaInfo().property(name()).isValid())
+ if (modelNode().metaInfo().property(name()).type() == QLatin1String("QUrl")) {
+ returnValue = returnValue.toUrl().toString();
+ }
+ return returnValue;
+}
+
+static bool cleverDoubleCompare(QVariant value1, QVariant value2)
+{ //we ignore slight changes on doubles
+ if ((value1.type() == QVariant::Double) && (value2.type() == QVariant::Double)) {
+ int a = value1.toDouble() * 100;
+ int b = value2.toDouble() * 100;
+
+ if (qFuzzyCompare((qreal(a) / 100), (qreal(b) / 100))) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void PropertyEditorValue::setValueWithEmit(const QVariant &value)
+{
+ if ( m_value != value) {
+ QVariant newValue = value;
+ if (modelNode().metaInfo().isValid() && modelNode().metaInfo().property(name()).isValid())
+ if (modelNode().metaInfo().property(name()).type() == QLatin1String("QUrl")) {
+ newValue = QUrl(newValue.toString());
+ }
+
+ if (cleverDoubleCompare(newValue, m_value))
+ return;
+ setValue(newValue);
+ setExpressionWithEmit(value.toString());
+ m_isBound = false;
+ emit valueChanged(name());
+ emit isBoundChanged();
+ }
+}
+
+void PropertyEditorValue::setValue(const QVariant &value)
+{
+ if ( m_value != value) {
+ m_value = value;
+ emit valueChanged();
+ }
+ emit isBoundChanged();
+}
+
+QString PropertyEditorValue::expression() const
+{
+
+ return m_expression;
+}
+
+void PropertyEditorValue::setExpressionWithEmit(const QString &expression)
+{
+ if ( m_expression != expression) {
+ setExpression(expression);
+ m_isBound = true;
+ emit expressionChanged(name());
+ emit valueChanged(name());
+ }
+}
+
+void PropertyEditorValue::setExpression(const QString &expression)
+{
+ if ( m_expression != expression) {
+ m_expression = expression;
+ emit expressionChanged();
+ }
+}
+
+bool PropertyEditorValue::isInSubState() const
+{
+ return m_isInSubState;
+}
+
+bool PropertyEditorValue::isBound() const
+{
+ return modelNode().property(name()).isBindingProperty();
+}
+
+void PropertyEditorValue::setIsInSubState(bool isInSubState)
+{
+ m_isInSubState = isInSubState;
+}
+
+bool PropertyEditorValue::isInModel() const
+{
+ return m_isInModel;
+}
+
+void PropertyEditorValue::setIsInModel(bool isInModel)
+{
+ m_isInModel = isInModel;
+}
+
+
+QString PropertyEditorValue::name() const
+{
+ return m_name;
+}
+
+void PropertyEditorValue::setName(const QString &name)
+{
+ m_name = name;
+}
+
+
+bool PropertyEditorValue::isValid() const
+{
+ return m_isValid;
+}
+
+void PropertyEditorValue::setIsValid(bool valid)
+{
+ m_isValid = valid;
+}
+
+ModelNode PropertyEditorValue::modelNode() const
+{
+ return m_modelNode;
+}
+
+void PropertyEditorValue::setModelNode(const ModelNode &modelNode)
+{
+ if (modelNode != m_modelNode) {
+ m_modelNode = modelNode;
+ m_complexNode->update();
+ emit modelNodeChanged();
+ }
+}
+
+PropertyEditorNodeWrapper* PropertyEditorValue::complexNode()
+{
+ return m_complexNode;
+}
+
+void PropertyEditorValue::resetValue()
+{
+ if (m_value.isValid()) {
+ setValue(QVariant());
+ m_isBound = false;
+ emit valueChanged(name());
+ }
+}
+
+PropertyEditorNodeWrapper::PropertyEditorNodeWrapper(PropertyEditorValue* parent) : m_valuesPropertyMap(this)
+{
+ m_editorValue = parent;
+ connect(m_editorValue, SIGNAL(modelNodeChanged()), this, SLOT(update()));
+}
+
+PropertyEditorNodeWrapper::PropertyEditorNodeWrapper(QObject *parent) : QObject(parent)
+{
+}
+
+bool PropertyEditorNodeWrapper::exists()
+{
+ if (!(m_editorValue && m_editorValue->modelNode().isValid()))
+ return false;
+
+ return m_modelNode.isValid();
+}
+
+QString PropertyEditorNodeWrapper::type()
+{
+ if (!(m_modelNode.isValid()))
+ return QString("");
+
+ return m_modelNode.simplifiedTypeName();
+
+}
+
+ModelNode PropertyEditorNodeWrapper::parentModelNode() const
+{
+ return m_editorValue->modelNode();
+}
+
+QString PropertyEditorNodeWrapper::propertyName() const
+{
+ return m_editorValue->name();
+}
+
+QmlPropertyMap* PropertyEditorNodeWrapper::properties()
+{
+ return &m_valuesPropertyMap;
+}
+
+void PropertyEditorNodeWrapper::add(const QString &type)
+{
+
+ QString propertyType = type;
+
+ if ((m_editorValue && m_editorValue->modelNode().isValid())) {
+ if (propertyType == "")
+ propertyType = m_editorValue->modelNode().metaInfo().property(m_editorValue->name()).type();
+ while (propertyType.contains('*')) //strip star
+ propertyType.chop(1);
+ m_modelNode = m_editorValue->modelNode().view()->createModelNode(propertyType, 4, 6);
+ m_editorValue->modelNode().nodeAbstractProperty(m_editorValue->name()).reparentHere(m_modelNode);
+ if (!m_modelNode.isValid()) {
+ qWarning("PropertyEditorNodeWrapper::add failed");
+ }
+ } else {
+ qWarning("PropertyEditorNodeWrapper::add failed - node invalid");
+ }
+ setup();
+}
+
+void PropertyEditorNodeWrapper::remove()
+{
+ if ((m_editorValue && m_editorValue->modelNode().isValid())) {
+ if (QmlDesigner::QmlObjectNode(m_modelNode).isValid())
+ QmlDesigner::QmlObjectNode(m_modelNode).destroy();
+ m_editorValue->modelNode().removeProperty(m_editorValue->name());
+ } else {
+ qWarning("PropertyEditorNodeWrapper::remove failed - node invalid");
+ }
+ m_modelNode = QmlDesigner::ModelNode();
+
+ foreach (const QString &propertyName, m_valuesPropertyMap.keys())
+ m_valuesPropertyMap.clear(propertyName);
+ foreach (QObject *object, m_valuesPropertyMap.children())
+ delete object;
+ emit propertiesChanged();
+ emit existsChanged();
+}
+
+void PropertyEditorNodeWrapper::changeValue(const QString &name)
+{
+ if (m_modelNode.isValid()) {
+ QmlDesigner::QmlObjectNode fxObjectNode(m_modelNode);
+
+ PropertyEditorValue *valueObject = qvariant_cast<PropertyEditorValue *>(m_valuesPropertyMap.value(name));
+
+ if (valueObject->value().isValid())
+ fxObjectNode.setVariantProperty(name, valueObject->value());
+ else
+ fxObjectNode.removeVariantProperty(name);
+ }
+}
+
+void PropertyEditorNodeWrapper::setup()
+{
+ Q_ASSERT(m_editorValue);
+ Q_ASSERT(m_editorValue->modelNode().isValid());
+ if ((m_editorValue->modelNode().isValid() && m_modelNode.isValid())) {
+ QmlDesigner::QmlObjectNode fxObjectNode(m_modelNode);
+ foreach ( const QString &propertyName, m_valuesPropertyMap.keys())
+ m_valuesPropertyMap.clear(propertyName);
+ foreach (QObject *object, m_valuesPropertyMap.children())
+ delete object;
+
+ foreach (const QString &propertyName, m_modelNode.metaInfo().properties().keys()) {
+ PropertyEditorValue *valueObject = new PropertyEditorValue(&m_valuesPropertyMap);
+ valueObject->setName(propertyName);
+ valueObject->setIsInModel(fxObjectNode.hasProperty(propertyName));
+ valueObject->setIsInSubState(fxObjectNode.propertyAffectedByCurrentState(propertyName));
+ valueObject->setModelNode(fxObjectNode.modelNode());
+ valueObject->setValue(fxObjectNode.instanceValue(propertyName));
+
+ connect(valueObject, SIGNAL(valueChanged(QString)), &m_valuesPropertyMap, SIGNAL(valueChanged(QString)));
+ m_valuesPropertyMap.insert(propertyName, QmlMetaType::qmlType(valueObject->metaObject())->fromObject(valueObject));
+ }
+ }
+ connect(&m_valuesPropertyMap, SIGNAL(valueChanged(const QString &)), this, SLOT(changeValue(const QString&)));
+
+ emit propertiesChanged();
+ emit existsChanged();
+}
+
+void PropertyEditorNodeWrapper::update()
+{
+ if (m_editorValue && m_editorValue->modelNode().isValid()) {
+ if (m_editorValue->modelNode().hasProperty(m_editorValue->name()) && m_editorValue->modelNode().property(m_editorValue->name()).isNodeProperty()) {
+ m_modelNode = m_editorValue->modelNode().nodeProperty(m_editorValue->name()).modelNode();
+ }
+ setup();
+ emit existsChanged();
+ emit typeChanged();
+ }
+}
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.h b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.h
new file mode 100644
index 0000000000..d07ec846cb
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.h
@@ -0,0 +1,155 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef PROPERTYEDITORVALUE_H
+#define PROPERTYEDITORVALUE_H
+
+#include <QObject>
+#include <QmlPropertyMap>
+#include <qml.h>
+#include <modelnode.h>
+
+class PropertyEditorValue;
+
+typedef QmlDesigner::ModelNode ModelNode;
+
+
+class PropertyEditorNodeWrapper : public QObject {
+ Q_OBJECT
+
+ Q_PROPERTY(bool exists READ exists NOTIFY existsChanged)
+ Q_PROPERTY(QmlPropertyMap* properties READ properties NOTIFY propertiesChanged)
+ Q_PROPERTY(QString type READ type NOTIFY typeChanged)
+
+public:
+ PropertyEditorNodeWrapper(QObject *parent=0);
+ PropertyEditorNodeWrapper(PropertyEditorValue* parent);
+ bool exists();
+ QString type();
+ QmlPropertyMap* properties();
+ ModelNode parentModelNode() const;
+ QString propertyName() const;
+
+public slots:
+ void add(const QString &type = "");
+ void remove();
+ void changeValue(const QString &name);
+ void update();
+
+signals:
+ void existsChanged();
+ void propertiesChanged();
+ void typeChanged();
+
+private:
+ void setup();
+
+ QmlDesigner::ModelNode m_modelNode;
+ QmlPropertyMap m_valuesPropertyMap;
+ PropertyEditorValue* m_editorValue;
+};
+
+
+class PropertyEditorValue : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QVariant value READ value WRITE setValueWithEmit NOTIFY valueChanged FINAL)
+ Q_PROPERTY(QString expression READ expression WRITE setExpressionWithEmit NOTIFY expressionChanged FINAL)
+ Q_PROPERTY(bool isInModel READ isInModel FINAL)
+ Q_PROPERTY(bool isInSubState READ isInSubState FINAL)
+ Q_PROPERTY(bool isBound READ isBound NOTIFY isBoundChanged FINAL)
+ Q_PROPERTY(bool isValid READ isValid NOTIFY isValid FINAL)
+ Q_PROPERTY(QString name READ name FINAL)
+ Q_PROPERTY(PropertyEditorNodeWrapper* complexNode READ complexNode NOTIFY complexNodeChanged FINAL)
+
+public:
+ PropertyEditorValue(QObject *parent=0);
+
+ QVariant value() const;
+ void setValueWithEmit(const QVariant &value);
+ void setValue(const QVariant &value);
+
+ QString expression() const;
+ void setExpressionWithEmit(const QString &expression);
+ void setExpression(const QString &expression);
+
+ bool isInSubState() const;
+ void setIsInSubState(bool isInSubState);
+
+ bool isInModel() const;
+
+ bool isBound() const;
+ bool isValid() const;
+
+ void setIsValid(bool valid);
+
+ void setIsInModel(bool isInModel);
+
+ QString name() const;
+ void setName(const QString &name);
+
+ ModelNode modelNode() const;
+ void setModelNode(const ModelNode &modelNode);
+
+ PropertyEditorNodeWrapper* complexNode();
+
+public slots:
+ void resetValue();
+
+signals:
+ void valueChanged(const QString &name);
+ void valueChanged();
+
+ void expressionChanged(const QString &name);
+ void expressionChanged();
+
+ void modelStateChanged();
+ void modelNodeChanged();
+ void complexNodeChanged();
+ void isBoundChanged();
+ void isValidChanged();
+
+private: //variables
+ ModelNode m_modelNode;
+ QVariant m_value;
+ QString m_expression;
+ QString m_name;
+ bool m_isInSubState;
+ bool m_isInModel;
+ bool m_isBound;
+ bool m_isValid; //if the property value belongs to an non existant complexProperty it is invalid
+ PropertyEditorNodeWrapper *m_complexNode;
+};
+
+QML_DECLARE_TYPE(PropertyEditorValue);
+QML_DECLARE_TYPE(PropertyEditorNodeWrapper);
+QML_DECLARE_TYPE(QmlPropertyMap);
+
+
+#endif // PROPERTYEDITORVALUE_H
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qlayoutobject.cpp b/src/plugins/qmldesigner/components/propertyeditor/qlayoutobject.cpp
new file mode 100644
index 0000000000..fede3912b0
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qlayoutobject.cpp
@@ -0,0 +1,57 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+/****************************************************************************
+**
+** 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 "qlayoutobject.h"
+
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(Qt,4,6,QLayoutObject,QLayoutObject);
+
+QLayoutObject::QLayoutObject(QObject *parent)
+: QObject(parent)
+{
+}
+
+QLayout *QLayoutObject::layout() const
+{
+ return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qlayoutobject.h b/src/plugins/qmldesigner/components/propertyeditor/qlayoutobject.h
new file mode 100644
index 0000000000..e5d23c64fb
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qlayoutobject.h
@@ -0,0 +1,69 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+/****************************************************************************
+**
+** 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 QLAYOUTOBJECT_H
+#define QLAYOUTOBJECT_H
+
+#include <QObject>
+#include <QLayout>
+#include <qml.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QLayoutObject : public QObject
+{
+Q_OBJECT
+public:
+ QLayoutObject(QObject *parent = 0);
+
+ virtual QLayout *layout() const;
+};
+QML_DECLARE_TYPE(QLayoutObject);
+
+#endif // QLAYOUTOBJECT_H
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qmlanchorbindingproxy.cpp b/src/plugins/qmldesigner/components/propertyeditor/qmlanchorbindingproxy.cpp
new file mode 100644
index 0000000000..805df99070
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qmlanchorbindingproxy.cpp
@@ -0,0 +1,287 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "qmlanchorbindingproxy.h"
+#include <qmlanchors.h>
+#include <nodeabstractproperty.h>
+#include <nodeinstance.h>
+#include <QDebug>
+
+namespace QmlDesigner {
+
+class ModelNode;
+class NodeState;
+
+namespace Internal {
+
+QmlAnchorBindingProxy::QmlAnchorBindingProxy(QObject *parent) :
+ QObject(parent)
+{
+}
+
+QmlAnchorBindingProxy::~QmlAnchorBindingProxy()
+{
+}
+
+void QmlAnchorBindingProxy::setup(const QmlItemNode &fxItemNode)
+{
+ m_fxItemNode = fxItemNode;
+ emit parentChanged();
+ emit topAnchorChanged();
+ emit bottomAnchorChanged();
+ emit leftAnchorChanged();
+ emit rightAnchorChanged();
+ emit centeredHChanged();
+ emit centeredVChanged();
+ emit anchorsChanged();
+}
+
+bool QmlAnchorBindingProxy::hasParent()
+{
+ return m_fxItemNode.hasNodeParent();
+}
+
+bool QmlAnchorBindingProxy::topAnchored()
+{
+ return m_fxItemNode.anchors().instanceHasAnchor(AnchorLine::Top);
+}
+
+bool QmlAnchorBindingProxy::bottomAnchored()
+{
+ return m_fxItemNode.anchors().instanceHasAnchor(AnchorLine::Bottom);
+}
+
+bool QmlAnchorBindingProxy::leftAnchored()
+{
+ return m_fxItemNode.anchors().instanceHasAnchor(AnchorLine::Left);
+}
+
+bool QmlAnchorBindingProxy::rightAnchored()
+{
+ return m_fxItemNode.anchors().instanceHasAnchor(AnchorLine::Right);
+}
+
+bool QmlAnchorBindingProxy::hasAnchors()
+{
+ return m_fxItemNode.anchors().instanceHasAnchors();
+}
+
+
+void QmlAnchorBindingProxy::resetLayout() {
+ m_fxItemNode.anchors().removeAnchors();
+ m_fxItemNode.anchors().removeMargins();
+
+ emit topAnchorChanged();
+ emit bottomAnchorChanged();
+ emit leftAnchorChanged();
+ emit rightAnchorChanged();
+ emit anchorsChanged();
+ }
+
+void QmlAnchorBindingProxy::setBottomAnchor(bool anchor)
+{
+ if (!m_fxItemNode.hasNodeParent())
+ return;
+
+ if (bottomAnchored() == anchor)
+ return;
+
+ if (!anchor) {
+ removeBottomAnchor();
+ } else {
+
+ qreal bottomMargin = parentBoundingBox().bottom() - transformedBoundingBox().bottom();
+
+ m_fxItemNode.anchors().setAnchor(AnchorLine::Bottom, m_fxItemNode.modelNode().parentProperty().parentModelNode(), AnchorLine::Bottom);
+ m_fxItemNode.anchors().setMargin(AnchorLine::Bottom, bottomMargin);
+ }
+ emit bottomAnchorChanged();
+
+ if (hasAnchors() != anchor)
+ emit anchorsChanged();
+}
+
+void QmlAnchorBindingProxy::setLeftAnchor(bool anchor)
+{
+ if (!m_fxItemNode.hasNodeParent())
+ return;
+
+ if (leftAnchored() == anchor)
+ return;
+
+ if (!anchor) {
+ removeLeftAnchor();
+ } else {
+ qreal leftMargin = transformedBoundingBox().left() - parentBoundingBox().left();
+
+ m_fxItemNode.anchors().setAnchor(AnchorLine::Left, m_fxItemNode.modelNode().parentProperty().parentModelNode(), AnchorLine::Left);
+ m_fxItemNode.anchors().setMargin(AnchorLine::Left, leftMargin);
+ }
+ emit leftAnchorChanged();
+ if (hasAnchors() != anchor)
+ emit anchorsChanged();
+}
+
+void QmlAnchorBindingProxy::setRightAnchor(bool anchor)
+{
+ if (!m_fxItemNode.hasNodeParent())
+ return;
+
+ if (rightAnchored() == anchor)
+ return;
+
+ if (!anchor) {
+ removeRightAnchor();
+ } else {
+
+ qreal rightMargin = parentBoundingBox().right() - transformedBoundingBox().right();
+
+ m_fxItemNode.anchors().setAnchor(AnchorLine::Right, m_fxItemNode.modelNode().parentProperty().parentModelNode(), AnchorLine::Right);
+ m_fxItemNode.anchors().setMargin(AnchorLine::Right, rightMargin);
+ }
+ emit rightAnchorChanged();
+ if (hasAnchors() != anchor)
+ emit anchorsChanged();
+}
+ QRectF QmlAnchorBindingProxy::parentBoundingBox()
+{
+ if (m_fxItemNode.hasInstanceParent())
+ return m_fxItemNode.instanceParent().toQmlItemNode().instanceBoundingRect();
+
+ return QRect();
+}
+
+QRectF QmlAnchorBindingProxy::transformedBoundingBox()
+{
+ return m_fxItemNode.instanceTransform().mapRect(m_fxItemNode.instanceBoundingRect());
+}
+
+void QmlAnchorBindingProxy::setTopAnchor(bool anchor)
+{
+ if (!m_fxItemNode.hasNodeParent())
+ return ;
+
+ if (topAnchored() == anchor)
+ return;
+
+ if (!anchor) {
+ removeTopAnchor();
+ } else {
+
+ qreal topMargin = transformedBoundingBox().top() - parentBoundingBox().top();
+
+ m_fxItemNode.anchors().setAnchor(AnchorLine::Top, m_fxItemNode.modelNode().parentProperty().parentModelNode(), AnchorLine::Top);
+ m_fxItemNode.anchors().setMargin( AnchorLine::Top, topMargin);
+ }
+ emit topAnchorChanged();
+ if (hasAnchors() != anchor)
+ emit anchorsChanged();
+}
+
+void QmlAnchorBindingProxy::removeTopAnchor() {
+ m_fxItemNode.anchors().removeAnchor(AnchorLine::Top);
+ m_fxItemNode.anchors().removeMargin(AnchorLine::Top);
+}
+
+void QmlAnchorBindingProxy::removeBottomAnchor() {
+ m_fxItemNode.anchors().removeAnchor(AnchorLine::Bottom);
+ m_fxItemNode.anchors().removeMargin(AnchorLine::Bottom);
+}
+
+void QmlAnchorBindingProxy::removeLeftAnchor() {
+ m_fxItemNode.anchors().removeAnchor(AnchorLine::Left);
+ m_fxItemNode.anchors().removeMargin(AnchorLine::Left);
+}
+
+void QmlAnchorBindingProxy::removeRightAnchor() {
+ m_fxItemNode.anchors().removeAnchor(AnchorLine::Right);
+ m_fxItemNode.anchors().removeMargin(AnchorLine::Right);
+}
+
+void QmlAnchorBindingProxy::setVerticalCentered(bool centered)
+{
+ if (!m_fxItemNode.hasNodeParent())
+ return ;
+
+ if (verticalCentered() == centered)
+ return;
+
+ if (!centered) {
+ m_fxItemNode.anchors().removeAnchor(AnchorLine::VerticalCenter);
+ } else {
+ m_fxItemNode.anchors().setAnchor(AnchorLine::VerticalCenter, m_fxItemNode.modelNode().parentProperty().parentModelNode(), AnchorLine::VerticalCenter);
+ }
+ emit centeredVChanged();
+}
+
+void QmlAnchorBindingProxy::setHorizontalCentered(bool centered)
+{
+ if (!m_fxItemNode.hasNodeParent())
+ return ;
+
+ if (horizontalCentered() == centered)
+ return;
+
+ if (!centered) {
+ m_fxItemNode.anchors().removeAnchor(AnchorLine::HorizontalCenter);
+ } else {
+ m_fxItemNode.anchors().setAnchor(AnchorLine::HorizontalCenter, m_fxItemNode.modelNode().parentProperty().parentModelNode(), AnchorLine::HorizontalCenter);
+ }
+ emit centeredHChanged();
+}
+
+bool QmlAnchorBindingProxy::verticalCentered()
+{
+ return m_fxItemNode.anchors().instanceHasAnchor(AnchorLine::VerticalCenter);
+}
+
+bool QmlAnchorBindingProxy::horizontalCentered()
+{
+ return m_fxItemNode.anchors().instanceHasAnchor(AnchorLine::HorizontalCenter);
+}
+
+void QmlAnchorBindingProxy::fill()
+{
+ m_fxItemNode.anchors().fill();
+
+ m_fxItemNode.anchors().setMargin(AnchorLine::Right, 0);
+ m_fxItemNode.anchors().setMargin(AnchorLine::Left, 0);
+ m_fxItemNode.anchors().setMargin(AnchorLine::Top, 0);
+ m_fxItemNode.anchors().setMargin(AnchorLine::Bottom, 0);
+
+ emit topAnchorChanged();
+ emit bottomAnchorChanged();
+ emit leftAnchorChanged();
+ emit rightAnchorChanged();
+ emit anchorsChanged();
+}
+
+} // namespace Internal
+} // namespace QmlDesigner
+
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qmlanchorbindingproxy.h b/src/plugins/qmldesigner/components/propertyeditor/qmlanchorbindingproxy.h
new file mode 100644
index 0000000000..f014401228
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qmlanchorbindingproxy.h
@@ -0,0 +1,117 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef QmlAnchorBindingProxy_h
+#define QmlAnchorBindingProxy_h
+
+#include <QObject>
+#include <modelnode.h>
+#include <nodeinstanceview.h>
+#include <QRectF>
+#include <qmlitemnode.h>
+
+namespace QmlDesigner {
+
+class NodeInstanceView;
+
+namespace Internal {
+
+class QmlAnchorBindingProxy : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool topAnchored READ topAnchored WRITE setTopAnchor NOTIFY topAnchorChanged)
+ Q_PROPERTY(bool bottomAnchored READ bottomAnchored WRITE setBottomAnchor NOTIFY bottomAnchorChanged)
+ Q_PROPERTY(bool leftAnchored READ leftAnchored WRITE setLeftAnchor NOTIFY leftAnchorChanged)
+ Q_PROPERTY(bool rightAnchored READ rightAnchored WRITE setRightAnchor NOTIFY rightAnchorChanged)
+ Q_PROPERTY(bool hasParent READ hasParent NOTIFY parentChanged);
+
+ Q_PROPERTY(bool hasAnchors READ hasAnchors NOTIFY anchorsChanged)
+
+ Q_PROPERTY(bool verticalCentered READ verticalCentered WRITE setVerticalCentered NOTIFY centeredVChanged)
+ Q_PROPERTY(bool horizontalCentered READ horizontalCentered WRITE setHorizontalCentered NOTIFY centeredHChanged)
+
+public:
+ //only enable if node has parent
+
+ QmlAnchorBindingProxy(QObject *parent = 0);
+ ~QmlAnchorBindingProxy();
+
+ void setup(const QmlItemNode &itemNode);
+
+ bool topAnchored();
+ bool bottomAnchored();
+ bool leftAnchored();
+ bool rightAnchored();
+
+ bool hasParent();
+
+ void removeTopAnchor();
+ void removeBottomAnchor();
+ void removeLeftAnchor();
+ void removeRightAnchor();
+ bool hasAnchors();
+
+ bool verticalCentered();
+ bool horizontalCentered();
+
+public slots:
+ void resetLayout();
+ void fill();
+ void setTopAnchor(bool anchor =true);
+ void setBottomAnchor(bool anchor = true);
+ void setLeftAnchor(bool anchor = true);
+ void setRightAnchor(bool anchor = true);
+
+ void setVerticalCentered(bool centered = true);
+ void setHorizontalCentered(bool centered = true);
+
+signals:
+ void parentChanged();
+
+ void topAnchorChanged();
+ void bottomAnchorChanged();
+ void leftAnchorChanged();
+ void rightAnchorChanged();
+ void centeredVChanged();
+ void centeredHChanged();
+ void anchorsChanged();
+private:
+ QmlItemNode m_fxItemNode;
+
+ QRectF parentBoundingBox();
+ QRectF transformedBoundingBox();
+};
+
+} // namespace Internal
+} // namespace QmlDesigner
+
+
+#endif //QmlAnchorBindingProxy
+
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qproxylayoutitem.cpp b/src/plugins/qmldesigner/components/propertyeditor/qproxylayoutitem.cpp
new file mode 100644
index 0000000000..fd997532c0
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qproxylayoutitem.cpp
@@ -0,0 +1,176 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+/****************************************************************************
+**
+** 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 "qproxylayoutitem.h"
+#include <QGraphicsWidget>
+
+QT_BEGIN_NAMESPACE
+
+QML_DEFINE_TYPE(Qt,4,6,LayoutItem,QProxyLayoutItem);
+
+QProxyLayoutItem::QProxyLayoutItem(QGraphicsLayoutItem *i)
+: enabled(true), other(i)
+{
+}
+
+void QProxyLayoutItem::setGeometry(const QRectF &r)
+{
+ geometry = r;
+ if (enabled && other)
+ other->setGeometry(r);
+}
+
+QGraphicsLayoutItem *QProxyLayoutItem::item() const
+{
+ return other;
+}
+
+void QProxyLayoutItem::setItem(QGraphicsLayoutItem *o)
+{
+ if (other == o)
+ return;
+ other = o;
+ if (enabled && other)
+ other->setGeometry(geometry);
+
+ updateGeometry();
+ if (parentLayoutItem())
+ parentLayoutItem()->updateGeometry();
+}
+
+void QProxyLayoutItem::setEnabled(bool e)
+{
+ if (e == enabled)
+ return;
+
+ enabled = e;
+ if (e && other)
+ other->setGeometry(geometry);
+}
+
+QSizeF QProxyLayoutItem::sizeHint(Qt::SizeHint which, const QSizeF &c) const
+{
+ struct Accessor : public QGraphicsLayoutItem
+ {
+ QSizeF getSizeHint(Qt::SizeHint which, const QSizeF &c) const
+ {
+ return sizeHint(which, c);
+ }
+ };
+
+ QSizeF rv;
+ if (other)
+ rv = static_cast<Accessor *>(other)->getSizeHint(which, c);
+ return rv;
+}
+
+QML_DEFINE_TYPE(Qt,4,6,ProxyLayout,QProxyLayout);
+
+QProxyLayout::QProxyLayout(QObject *parent)
+: QObject(parent), proxy(0)
+{
+}
+
+void QProxyLayout::setLayout(QGraphicsLayout *l)
+{
+ proxy = l;
+ updateGeometry();
+ if (parentLayoutItem())
+ parentLayoutItem()->updateGeometry();
+}
+
+QGraphicsLayout *QProxyLayout::layout() const
+{
+ return proxy;
+}
+
+void QProxyLayout::updateGeometry()
+{
+ QGraphicsLayout::updateGeometry();
+}
+
+void QProxyLayout::setGeometry(const QRectF &g)
+{
+ geometry = g;
+ if (proxy)
+ proxy->setGeometry(g);
+
+}
+
+int QProxyLayout::count() const
+{
+ if (proxy)
+ return proxy->count();
+ else
+ return 0;
+}
+
+QGraphicsLayoutItem *QProxyLayout::itemAt(int idx) const
+{
+ if (proxy)
+ return proxy->itemAt(idx);
+ else
+ return 0;
+}
+
+void QProxyLayout::removeAt(int idx)
+{
+ if (proxy)
+ proxy->removeAt(idx);
+}
+
+QSizeF QProxyLayout::sizeHint(Qt::SizeHint which,
+ const QSizeF &constraint) const
+{
+ struct Accessor : public QGraphicsLayout
+ {
+ QSizeF getSizeHint(Qt::SizeHint which, const QSizeF &c) const
+ {
+ return sizeHint(which, c);
+ }
+ };
+
+ if (proxy)
+ return static_cast<Accessor *>(proxy)->getSizeHint(which, constraint);
+ else
+ return QSizeF();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qproxylayoutitem.h b/src/plugins/qmldesigner/components/propertyeditor/qproxylayoutitem.h
new file mode 100644
index 0000000000..d0e3373942
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qproxylayoutitem.h
@@ -0,0 +1,107 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+/****************************************************************************
+**
+** 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 QPROXYLAYOUTITEM_H
+#define QPROXYLAYOUTITEM_H
+
+#include <qml.h>
+#include <QGraphicsLayout>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QProxyLayout : public QObject, public QGraphicsLayout
+{
+ Q_OBJECT
+ Q_INTERFACES(QGraphicsLayout QGraphicsLayoutItem)
+ Q_PROPERTY(QGraphicsLayout *layout READ layout WRITE setLayout)
+public:
+ QProxyLayout(QObject *parent=0);
+
+ void setLayout(QGraphicsLayout *);
+ QGraphicsLayout *layout() const;
+
+ virtual void setGeometry(const QRectF &);
+ virtual int count() const;
+ virtual QGraphicsLayoutItem *itemAt(int) const;
+ virtual void removeAt(int);
+ virtual void updateGeometry();
+
+protected:
+ virtual QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint) const;
+
+private:
+ QRectF geometry;
+ QGraphicsLayout *proxy;
+};
+QML_DECLARE_TYPE(QProxyLayout);
+
+class QProxyLayoutItem : public QObject, public QGraphicsLayoutItem
+{
+ Q_OBJECT
+ Q_INTERFACES(QGraphicsLayoutItem)
+ Q_PROPERTY(QGraphicsLayoutItem *widget READ item WRITE setItem)
+public:
+ QProxyLayoutItem(QGraphicsLayoutItem * = 0);
+
+ virtual void setGeometry(const QRectF &);
+
+ QGraphicsLayoutItem *item() const;
+ void setItem(QGraphicsLayoutItem *);
+
+ void setEnabled(bool);
+protected:
+ virtual QSizeF sizeHint(Qt::SizeHint, const QSizeF &) const;
+
+private:
+ bool enabled;
+ QRectF geometry;
+ QGraphicsLayoutItem *other;
+};
+QML_DECLARE_TYPE(QProxyLayoutItem);
+
+#endif // QPROXYLAYOUTITEM_H
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/down.png b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/down.png
new file mode 100644
index 0000000000..29d1d4439a
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/down.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/edit.png b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/edit.png
new file mode 100644
index 0000000000..4231bd9a90
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/edit.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/editdelete.png b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/editdelete.png
new file mode 100644
index 0000000000..df2a147d24
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/editdelete.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/minus.png b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/minus.png
new file mode 100644
index 0000000000..d6f233d739
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/minus.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/plus.png b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/plus.png
new file mode 100644
index 0000000000..40df1134f8
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/plus.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/spreadpad.png b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/spreadpad.png
new file mode 100644
index 0000000000..104c0a23d2
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/spreadpad.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/spreadreflect.png b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/spreadreflect.png
new file mode 100644
index 0000000000..17b82b711a
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/spreadreflect.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/spreadrepeat.png b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/spreadrepeat.png
new file mode 100644
index 0000000000..7aea898b1d
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/spreadrepeat.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/typeconical.png b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/typeconical.png
new file mode 100644
index 0000000000..5479811df6
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/typeconical.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/typelinear.png b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/typelinear.png
new file mode 100644
index 0000000000..dbd8a1f5a1
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/typelinear.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/typeradial.png b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/typeradial.png
new file mode 100644
index 0000000000..dc5888dca7
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/typeradial.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/up.png b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/up.png
new file mode 100644
index 0000000000..e437312217
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/up.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/zoomin.png b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/zoomin.png
new file mode 100644
index 0000000000..2e586fc7bf
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/zoomin.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/zoomout.png b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/zoomout.png
new file mode 100644
index 0000000000..a736d39343
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/zoomout.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtcolorbutton.cpp b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtcolorbutton.cpp
new file mode 100644
index 0000000000..5c38b524ad
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtcolorbutton.cpp
@@ -0,0 +1,272 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtcolorbutton.h"
+#include <QtGui/QColorDialog>
+#include <QtGui/QPainter>
+#include <QtCore/QMimeData>
+#include <QtGui/QDragEnterEvent>
+#include <QtGui/QApplication>
+
+QT_BEGIN_NAMESPACE
+
+class QtColorButtonPrivate
+{
+ QtColorButton *q_ptr;
+ Q_DECLARE_PUBLIC(QtColorButton)
+public:
+ QColor m_color;
+#ifndef QT_NO_DRAGANDDROP
+ QColor m_dragColor;
+ QPoint m_dragStart;
+ bool m_dragging;
+#endif
+ bool m_backgroundCheckered;
+
+ void slotEditColor();
+ QColor shownColor() const;
+ QPixmap generatePixmap() const;
+};
+
+void QtColorButtonPrivate::slotEditColor()
+{
+ const QColor newColor = QColorDialog::getColor(m_color, q_ptr, QString(), QColorDialog::ShowAlphaChannel);
+ if (!newColor.isValid() || newColor == q_ptr->color())
+ return;
+ q_ptr->setColor(newColor);
+ emit q_ptr->colorChanged(m_color);
+}
+
+QColor QtColorButtonPrivate::shownColor() const
+{
+#ifndef QT_NO_DRAGANDDROP
+ if (m_dragging)
+ return m_dragColor;
+#endif
+ return m_color;
+}
+
+QPixmap QtColorButtonPrivate::generatePixmap() const
+{
+ QPixmap pix(24, 24);
+
+ int pixSize = 20;
+ QBrush br(shownColor());
+
+ QPixmap pm(2 * pixSize, 2 * pixSize);
+ QPainter pmp(&pm);
+ pmp.fillRect(0, 0, pixSize, pixSize, Qt::lightGray);
+ pmp.fillRect(pixSize, pixSize, pixSize, pixSize, Qt::lightGray);
+ pmp.fillRect(0, pixSize, pixSize, pixSize, Qt::darkGray);
+ pmp.fillRect(pixSize, 0, pixSize, pixSize, Qt::darkGray);
+ pmp.fillRect(0, 0, 2 * pixSize, 2 * pixSize, shownColor());
+ br = QBrush(pm);
+
+ QPainter p(&pix);
+ int corr = 1;
+ QRect r = pix.rect().adjusted(corr, corr, -corr, -corr);
+ p.setBrushOrigin((r.width() % pixSize + pixSize) / 2 + corr, (r.height() % pixSize + pixSize) / 2 + corr);
+ p.fillRect(r, br);
+
+ p.fillRect(r.width() / 4 + corr, r.height() / 4 + corr,
+ r.width() / 2, r.height() / 2,
+ QColor(shownColor().rgb()));
+ p.drawRect(pix.rect().adjusted(0, 0, -1, -1));
+
+ return pix;
+}
+
+///////////////
+
+QtColorButton::QtColorButton(QWidget *parent)
+ : QToolButton(parent), d_ptr(new QtColorButtonPrivate)
+{
+ d_ptr->q_ptr = this;
+ d_ptr->m_dragging = false;
+ d_ptr->m_backgroundCheckered = true;
+
+ setAcceptDrops(true);
+
+ connect(this, SIGNAL(clicked()), this, SLOT(slotEditColor()));
+ setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred));
+}
+
+QtColorButton::~QtColorButton()
+{
+}
+
+void QtColorButton::setColor(const QColor &color)
+{
+ if (d_ptr->m_color == color)
+ return;
+ d_ptr->m_color = color;
+ update();
+}
+
+QColor QtColorButton::color() const
+{
+ return d_ptr->m_color;
+}
+
+void QtColorButton::setBackgroundCheckered(bool checkered)
+{
+ if (d_ptr->m_backgroundCheckered == checkered)
+ return;
+ d_ptr->m_backgroundCheckered = checkered;
+ update();
+}
+
+bool QtColorButton::isBackgroundCheckered() const
+{
+ return d_ptr->m_backgroundCheckered;
+}
+
+void QtColorButton::paintEvent(QPaintEvent *event)
+{
+ QToolButton::paintEvent(event);
+ if (!isEnabled())
+ return;
+
+ const int pixSize = 10;
+ QBrush br(d_ptr->shownColor());
+ if (d_ptr->m_backgroundCheckered) {
+ QPixmap pm(2 * pixSize, 2 * pixSize);
+ QPainter pmp(&pm);
+ pmp.fillRect(0, 0, pixSize, pixSize, Qt::white);
+ pmp.fillRect(pixSize, pixSize, pixSize, pixSize, Qt::white);
+ pmp.fillRect(0, pixSize, pixSize, pixSize, Qt::black);
+ pmp.fillRect(pixSize, 0, pixSize, pixSize, Qt::black);
+ pmp.fillRect(0, 0, 2 * pixSize, 2 * pixSize, d_ptr->shownColor());
+ br = QBrush(pm);
+ }
+
+ QPainter p(this);
+ const int corr = 4;
+ QRect r = rect().adjusted(corr, corr, -corr, -corr);
+ p.setBrushOrigin((r.width() % pixSize + pixSize) / 2 + corr, (r.height() % pixSize + pixSize) / 2 + corr);
+ p.fillRect(r, br);
+
+ //const int adjX = qRound(r.width() / 4.0);
+ //const int adjY = qRound(r.height() / 4.0);
+ //p.fillRect(r.adjusted(adjX, adjY, -adjX, -adjY),
+ // QColor(d_ptr->shownColor().rgb()));
+ /*
+ p.fillRect(r.adjusted(0, r.height() * 3 / 4, 0, 0),
+ QColor(d_ptr->shownColor().rgb()));
+ p.fillRect(r.adjusted(0, 0, 0, -r.height() * 3 / 4),
+ QColor(d_ptr->shownColor().rgb()));
+ */
+ /*
+ const QColor frameColor0(0, 0, 0, qRound(0.2 * (0xFF - d_ptr->shownColor().alpha())));
+ p.setPen(frameColor0);
+ p.drawRect(r.adjusted(adjX, adjY, -adjX - 1, -adjY - 1));
+ */
+
+ const QColor frameColor1(0, 0, 0, 26);
+ p.setPen(frameColor1);
+ p.drawRect(r.adjusted(1, 1, -2, -2));
+ const QColor frameColor2(0, 0, 0, 51);
+ p.setPen(frameColor2);
+ p.drawRect(r.adjusted(0, 0, -1, -1));
+}
+
+void QtColorButton::mousePressEvent(QMouseEvent *event)
+{
+#ifndef QT_NO_DRAGANDDROP
+ if (event->button() == Qt::LeftButton)
+ d_ptr->m_dragStart = event->pos();
+#endif
+ QToolButton::mousePressEvent(event);
+}
+
+void QtColorButton::mouseMoveEvent(QMouseEvent *event)
+{
+#ifndef QT_NO_DRAGANDDROP
+ if (event->buttons() & Qt::LeftButton &&
+ (d_ptr->m_dragStart - event->pos()).manhattanLength() > QApplication::startDragDistance()) {
+ QMimeData *mime = new QMimeData;
+ mime->setColorData(color());
+ QDrag *drg = new QDrag(this);
+ drg->setMimeData(mime);
+ drg->setPixmap(d_ptr->generatePixmap());
+ setDown(false);
+ event->accept();
+ drg->start();
+ return;
+ }
+#endif
+ QToolButton::mouseMoveEvent(event);
+}
+
+#ifndef QT_NO_DRAGANDDROP
+void QtColorButton::dragEnterEvent(QDragEnterEvent *event)
+{
+ const QMimeData *mime = event->mimeData();
+ if (!mime->hasColor())
+ return;
+
+ event->accept();
+ d_ptr->m_dragColor = qvariant_cast<QColor>(mime->colorData());
+ d_ptr->m_dragging = true;
+ update();
+}
+
+void QtColorButton::dragLeaveEvent(QDragLeaveEvent *event)
+{
+ event->accept();
+ d_ptr->m_dragging = false;
+ update();
+}
+
+void QtColorButton::dropEvent(QDropEvent *event)
+{
+ event->accept();
+ d_ptr->m_dragging = false;
+ if (d_ptr->m_dragColor == color())
+ return;
+ setColor(d_ptr->m_dragColor);
+ emit colorChanged(color());
+}
+#endif
+
+QT_END_NAMESPACE
+
+#include "moc_qtcolorbutton.cpp"
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtcolorbutton.h b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtcolorbutton.h
new file mode 100644
index 0000000000..1a8b592d89
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtcolorbutton.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTCOLORBUTTON_H
+#define QTCOLORBUTTON_H
+
+#include <QtGui/QToolButton>
+
+QT_BEGIN_NAMESPACE
+
+class QtColorButton : public QToolButton
+{
+ Q_OBJECT
+ Q_PROPERTY(bool backgroundCheckered READ isBackgroundCheckered WRITE setBackgroundCheckered)
+public:
+ QtColorButton(QWidget *parent = 0);
+ ~QtColorButton();
+
+ bool isBackgroundCheckered() const;
+ void setBackgroundCheckered(bool checkered);
+
+ QColor color() const;
+
+public slots:
+
+ void setColor(const QColor &color);
+
+signals:
+ void colorChanged(const QColor &color);
+protected:
+ void paintEvent(QPaintEvent *event);
+ void mousePressEvent(QMouseEvent *event);
+ void mouseMoveEvent(QMouseEvent *event);
+#ifndef QT_NO_DRAGANDDROP
+ void dragEnterEvent(QDragEnterEvent *event);
+ void dragLeaveEvent(QDragLeaveEvent *event);
+ void dropEvent(QDropEvent *event);
+#endif
+private:
+ QScopedPointer<class QtColorButtonPrivate> d_ptr;
+ Q_DECLARE_PRIVATE(QtColorButton)
+ Q_DISABLE_COPY(QtColorButton)
+ Q_PRIVATE_SLOT(d_func(), void slotEditColor())
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtcolorbutton.pri b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtcolorbutton.pri
new file mode 100644
index 0000000000..0e41068f8a
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtcolorbutton.pri
@@ -0,0 +1,4 @@
+INCLUDEPATH += $$PWD
+DEPENDPATH += $$PWD
+SOURCES += $$PWD/qtcolorbutton.cpp
+HEADERS += $$PWD/qtcolorbutton.h
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtcolorline.cpp b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtcolorline.cpp
new file mode 100644
index 0000000000..047d0a6cc0
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtcolorline.cpp
@@ -0,0 +1,1122 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtcolorline.h"
+#include "qdrawutil.h"
+
+#include <QtGui/QPainter>
+#include <QtGui/QPaintEvent>
+#include <QtGui/QStyleOption>
+
+QT_BEGIN_NAMESPACE
+
+class QtColorLinePrivate
+{
+ QtColorLine *q_ptr;
+ Q_DECLARE_PUBLIC(QtColorLine)
+public:
+ QtColorLinePrivate();
+
+ QColor color() const;
+ void setColor(const QColor &color);
+
+ QtColorLine::ColorComponent colorComponent() const;
+ void setColorComponent(QtColorLine::ColorComponent component);
+
+ void setIndicatorSize(int size);
+ int indicatorSize() const;
+
+ void setIndicatorSpace(int space);
+ int indicatorSpace() const;
+
+ void setFlip(bool flip);
+ bool flip() const;
+
+ void setBackgroundCheckered(bool checkered);
+ bool isBackgroundCheckered() const;
+
+ void setOrientation(Qt::Orientation orientation);
+ Qt::Orientation orientation() const;
+
+ void resizeEvent(QResizeEvent *event);
+ void paintEvent(QPaintEvent *event);
+ void mousePressEvent(QMouseEvent *event);
+ void mouseMoveEvent(QMouseEvent *event);
+ void mouseReleaseEvent(QMouseEvent *event);
+ void mouseDoubleClickEvent(QMouseEvent *event);
+private:
+ void checkColor();
+ bool isMainPixmapValid() const;
+ void validate();
+ void recreateMainPixmap();
+ QSize pixmapSizeFromGeometrySize(const QSize &geometrySize) const;
+ QPixmap gradientPixmap(int size, Qt::Orientation orientation, const QColor &begin, const QColor &end, bool flipped = false) const;
+ QPixmap gradientPixmap(Qt::Orientation orientation, const QColor &begin, const QColor &end, bool flipped = false) const;
+ QPixmap hueGradientPixmap(int size, Qt::Orientation orientation, bool flipped = false,
+ int saturation = 0xFF, int value = 0xFF, int alpha = 0xFF) const;
+ QPixmap hueGradientPixmap(Qt::Orientation orientation, bool flipped = false,
+ int saturation = 0xFF, int value = 0xFF, int alpha = 0xFF) const;
+
+ QVector<QRect> rects(const QPointF &point) const;
+
+ QColor colorFromPoint(const QPointF &point) const;
+ QPointF pointFromColor(const QColor &color) const;
+
+ QColor m_color;
+ QtColorLine::ColorComponent m_component;
+ bool m_flipped;
+ bool m_backgroundCheckered;
+ Qt::Orientation m_orientation;
+ bool m_dragging;
+ bool m_combiningAlpha;
+ int m_indicatorSize;
+ int m_indicatorSpace;
+ QPointF m_point;
+ QPoint m_clickOffset;
+
+ QPixmap m_mainPixmap;
+ QPixmap m_alphalessPixmap;
+ QPixmap m_semiAlphaPixmap;
+ QSize m_pixmapSize;
+
+ struct PixData {
+ QSize size;
+ QColor color;
+ QtColorLine::ColorComponent component;
+ bool flipped;
+ Qt::Orientation orientation;
+ };
+
+ PixData m_lastValidMainPixmapData;
+};
+
+QtColorLinePrivate::QtColorLinePrivate()
+ : m_color(Qt::black), m_component(QtColorLine::Value),
+ m_flipped(false), m_backgroundCheckered(true), m_orientation(Qt::Horizontal), m_dragging(false), m_combiningAlpha(false)
+{
+ m_indicatorSize = 22;
+ m_indicatorSpace = 0;
+ m_pixmapSize = QSize(0, 0);
+ m_point = pointFromColor(m_color);
+}
+
+void QtColorLinePrivate::setColor(const QColor &color)
+{
+ if (m_color == color)
+ return;
+ if (!color.isValid())
+ return;
+ if (m_dragging) // Warning perhaps here, recursive call
+ return;
+ m_color = color;
+ checkColor();
+ QColor c = colorFromPoint(m_point);
+ m_point = pointFromColor(m_color);
+ q_ptr->update();
+}
+
+QColor QtColorLinePrivate::color() const
+{
+ return m_color;
+}
+
+void QtColorLinePrivate::setColorComponent(QtColorLine::ColorComponent component)
+{
+ if (m_component == component)
+ return;
+ if (m_dragging) // Warning perhaps here, recursive call
+ return;
+ m_component = component;
+ checkColor();
+ m_point = pointFromColor(m_color);
+ q_ptr->update();
+}
+
+QtColorLine::ColorComponent QtColorLinePrivate::colorComponent() const
+{
+ return m_component;
+}
+
+void QtColorLinePrivate::setIndicatorSize(int size)
+{
+ if (size <= 0)
+ return;
+ if (m_dragging) // Warning perhaps here, recursive call
+ return;
+ if (m_indicatorSize == size)
+ return;
+ m_indicatorSize = size;
+ m_pixmapSize = pixmapSizeFromGeometrySize(q_ptr->contentsRect().size());
+ q_ptr->update();
+ q_ptr->updateGeometry();
+}
+
+int QtColorLinePrivate::indicatorSize() const
+{
+ return m_indicatorSize;
+}
+
+void QtColorLinePrivate::setIndicatorSpace(int space)
+{
+ if (space < 0)
+ return;
+ if (m_dragging) // Warning perhaps here, recursive call
+ return;
+ if (m_indicatorSpace == space)
+ return;
+ m_indicatorSpace = space;
+ m_pixmapSize = pixmapSizeFromGeometrySize(q_ptr->contentsRect().size());
+ q_ptr->update();
+}
+
+int QtColorLinePrivate::indicatorSpace() const
+{
+ return m_indicatorSpace;
+}
+
+void QtColorLinePrivate::setFlip(bool flip)
+{
+ if (m_dragging) // Warning perhaps here, recursive call
+ return;
+ if (m_flipped == flip)
+ return;
+ m_flipped = flip;
+ m_point = pointFromColor(m_color);
+ q_ptr->update();
+}
+
+bool QtColorLinePrivate::flip() const
+{
+ return m_flipped;
+}
+
+void QtColorLinePrivate::setBackgroundCheckered(bool checkered)
+{
+ if (m_backgroundCheckered == checkered)
+ return;
+ m_backgroundCheckered = checkered;
+ q_ptr->update();
+}
+
+bool QtColorLinePrivate::isBackgroundCheckered() const
+{
+ return m_backgroundCheckered;
+}
+
+void QtColorLinePrivate::setOrientation(Qt::Orientation orientation)
+{
+ if (m_dragging) // Warning perhaps here, recursive call
+ return;
+ if (m_orientation == orientation)
+ return;
+
+ m_orientation = orientation;
+ if (!q_ptr->testAttribute(Qt::WA_WState_OwnSizePolicy)) {
+ QSizePolicy sp = q_ptr->sizePolicy();
+ sp.transpose();
+ q_ptr->setSizePolicy(sp);
+ q_ptr->setAttribute(Qt::WA_WState_OwnSizePolicy, false);
+ }
+ m_point = pointFromColor(m_color);
+ q_ptr->update();
+ q_ptr->updateGeometry();
+}
+
+Qt::Orientation QtColorLinePrivate::orientation() const
+{
+ return m_orientation;
+}
+
+void QtColorLinePrivate::checkColor()
+{
+ switch (m_component) {
+ case QtColorLine::Red:
+ case QtColorLine::Green:
+ case QtColorLine::Blue:
+ if (m_color.spec() != QColor::Rgb)
+ m_color = m_color.toRgb();
+ break;
+ case QtColorLine::Hue:
+ case QtColorLine::Saturation:
+ case QtColorLine::Value:
+ if (m_color.spec() != QColor::Hsv)
+ m_color = m_color.toHsv();
+ break;
+ default:
+ break;
+ }
+ if (m_color.spec() == QColor::Hsv) {
+ if (m_color.hue() == 360 || m_color.hue() == -1) {
+ m_color.setHsvF(0.0, m_color.saturationF(), m_color.valueF(), m_color.alphaF());
+ }
+ }
+}
+
+bool QtColorLinePrivate::isMainPixmapValid() const
+{
+ if (m_mainPixmap.isNull()) {
+ if (m_pixmapSize.isEmpty())
+ return true;
+ else
+ return false;
+ }
+ if (m_lastValidMainPixmapData.component != m_component)
+ return false;
+ if (m_lastValidMainPixmapData.size != m_pixmapSize)
+ return false;
+ if (m_lastValidMainPixmapData.flipped != m_flipped)
+ return false;
+ if (m_lastValidMainPixmapData.orientation != m_orientation)
+ return false;
+ if (m_lastValidMainPixmapData.color == m_color)
+ return true;
+ switch (m_component) {
+ case QtColorLine::Red:
+ if (m_color.green() == m_lastValidMainPixmapData.color.green() &&
+ m_color.blue() == m_lastValidMainPixmapData.color.blue() &&
+ (!m_combiningAlpha || m_color.alpha() == m_lastValidMainPixmapData.color.alpha()))
+ return true;
+ break;
+ case QtColorLine::Green:
+ if (m_color.red() == m_lastValidMainPixmapData.color.red() &&
+ m_color.blue() == m_lastValidMainPixmapData.color.blue() &&
+ (!m_combiningAlpha || m_color.alpha() == m_lastValidMainPixmapData.color.alpha()))
+ return true;
+ break;
+ case QtColorLine::Blue:
+ if (m_color.red() == m_lastValidMainPixmapData.color.red() &&
+ m_color.green() == m_lastValidMainPixmapData.color.green() &&
+ (!m_combiningAlpha || m_color.alpha() == m_lastValidMainPixmapData.color.alpha()))
+ return true;
+ break;
+ case QtColorLine::Hue:
+ if (m_color.saturation() == m_lastValidMainPixmapData.color.saturation() &&
+ m_color.value() == m_lastValidMainPixmapData.color.value() &&
+ (!m_combiningAlpha || m_color.alpha() == m_lastValidMainPixmapData.color.alpha()))
+ return true;
+ break;
+ case QtColorLine::Saturation:
+ if (m_color.hue() == m_lastValidMainPixmapData.color.hue() &&
+ m_color.value() == m_lastValidMainPixmapData.color.value() &&
+ (!m_combiningAlpha || m_color.alpha() == m_lastValidMainPixmapData.color.alpha()))
+ return true;
+ break;
+ case QtColorLine::Value:
+ if (m_color.hue() == m_lastValidMainPixmapData.color.hue() &&
+ m_color.saturation() == m_lastValidMainPixmapData.color.saturation() &&
+ (!m_combiningAlpha || m_color.alpha() == m_lastValidMainPixmapData.color.alpha()))
+ return true;
+ break;
+ case QtColorLine::Alpha:
+ if (m_color.hue() == m_lastValidMainPixmapData.color.hue() &&
+ m_color.saturation() == m_lastValidMainPixmapData.color.saturation() &&
+ m_color.value() == m_lastValidMainPixmapData.color.value())
+ return true;
+ }
+ return false;
+}
+
+void QtColorLinePrivate::validate()
+{
+ if (isMainPixmapValid())
+ return;
+
+ recreateMainPixmap();
+}
+
+QPixmap QtColorLinePrivate::gradientPixmap(Qt::Orientation orientation, const QColor &begin, const QColor &end, bool flipped) const
+{
+ int size = m_pixmapSize.width();
+ if (orientation == Qt::Vertical)
+ size = m_pixmapSize.height();
+ return gradientPixmap(size, orientation, begin, end, flipped);
+}
+
+QPixmap QtColorLinePrivate::gradientPixmap(int size, Qt::Orientation orientation,
+ const QColor &begin, const QColor &end, bool flipped) const
+{
+ int gradW = size;
+ int gradH = size;
+ int w = size;
+ int h = size;
+ if (orientation == Qt::Horizontal) {
+ gradH = 0;
+ h = 1;
+ } else {
+ gradW = 0;
+ w = 1;
+ }
+ QColor c1 = begin;
+ QColor c2 = end;
+ if (flipped) {
+ c1 = end;
+ c2 = begin;
+ }
+ QLinearGradient lg(0, 0, gradW, gradH);
+ lg.setColorAt(0, c1);
+ lg.setColorAt(1, c2);
+ QImage img(w, h, QImage::Format_ARGB32);
+ QPainter p(&img);
+ p.setCompositionMode(QPainter::CompositionMode_Source);
+ p.fillRect(QRect(0, 0, w, h), lg);
+ return QPixmap::fromImage(img);
+}
+
+QPixmap QtColorLinePrivate::hueGradientPixmap(Qt::Orientation orientation, bool flipped,
+ int saturation, int value, int alpha) const
+{
+ int size = m_pixmapSize.width();
+ if (orientation == Qt::Vertical)
+ size = m_pixmapSize.height();
+ return hueGradientPixmap(size, orientation, flipped, saturation, value, alpha);
+}
+
+QPixmap QtColorLinePrivate::hueGradientPixmap(int size, Qt::Orientation orientation, bool flipped,
+ int saturation, int value, int alpha) const
+{
+ int gradW = size + 1;
+ int gradH = size + 1;
+ int w = size;
+ int h = size;
+ if (orientation == Qt::Horizontal) {
+ gradH = 0;
+ h = 1;
+ } else {
+ gradW = 0;
+ w = 1;
+ }
+ QList<QColor> colorList;
+ colorList << QColor::fromHsv(0, saturation, value, alpha);
+ colorList << QColor::fromHsv(60, saturation, value, alpha);
+ colorList << QColor::fromHsv(120, saturation, value, alpha);
+ colorList << QColor::fromHsv(180, saturation, value, alpha);
+ colorList << QColor::fromHsv(240, saturation, value, alpha);
+ colorList << QColor::fromHsv(300, saturation, value, alpha);
+ colorList << QColor::fromHsv(0, saturation, value, alpha);
+ QLinearGradient lg(0, 0, gradW, gradH);
+ for (int i = 0; i <= 6; i++)
+ lg.setColorAt((double)i / 6.0, flipped ? colorList.at(6 - i) : colorList.at(i));
+ QImage img(w, h, QImage::Format_ARGB32);
+ QPainter p(&img);
+ p.setCompositionMode(QPainter::CompositionMode_Source);
+ p.fillRect(QRect(0, 0, w, h), lg);
+ return QPixmap::fromImage(img);
+}
+
+void QtColorLinePrivate::recreateMainPixmap()
+{
+ m_lastValidMainPixmapData.size = m_pixmapSize;
+ m_lastValidMainPixmapData.component = m_component;
+ m_lastValidMainPixmapData.color = m_color;
+ m_lastValidMainPixmapData.flipped = m_flipped;
+ m_lastValidMainPixmapData.orientation = m_orientation;
+
+ if (m_pixmapSize.isEmpty()) {
+ m_mainPixmap = QPixmap();
+ m_alphalessPixmap = QPixmap();
+ m_semiAlphaPixmap = QPixmap();
+ return;
+ }
+
+ if (m_mainPixmap.size() != m_pixmapSize) {
+ m_mainPixmap = QPixmap(m_pixmapSize);
+ m_alphalessPixmap = QPixmap(m_pixmapSize);
+ m_semiAlphaPixmap = QPixmap(m_pixmapSize);
+ }
+
+ Qt::Orientation orient = m_orientation;
+ const bool flip = m_flipped;
+
+ const int r = m_color.red();
+ const int g = m_color.green();
+ const int b = m_color.blue();
+ const int h = m_color.hue();
+ const int s = m_color.saturation();
+ const int v = m_color.value();
+ const int a = m_color.alpha();
+ const double coef = 0.5;
+ const int semi = qRound(a * coef + 0xFF * (1.0 - coef));
+
+ if (m_component == QtColorLine::Hue) {
+ m_alphalessPixmap = hueGradientPixmap(orient, flip, s, v, 0xFF);
+ if (m_combiningAlpha) {
+ m_mainPixmap = hueGradientPixmap(orient, flip, s, v, a);
+ m_semiAlphaPixmap = hueGradientPixmap(orient, flip, s, v, semi);
+ }
+ } else if (m_component == QtColorLine::Saturation) {
+ m_alphalessPixmap = gradientPixmap(orient, QColor::fromHsv(h, 0, v, 0xFF), QColor::fromHsv(h, 0xFF, v, 0xFF), flip);
+ if (m_combiningAlpha) {
+ m_mainPixmap = gradientPixmap(orient, QColor::fromHsv(h, 0, v, a), QColor::fromHsv(h, 0xFF, v, a), flip);
+ m_semiAlphaPixmap = gradientPixmap(orient, QColor::fromHsv(h, 0, v, semi), QColor::fromHsv(h, 0xFF, v, semi), flip);
+ }
+ } else if (m_component == QtColorLine::Value) {
+ m_alphalessPixmap = gradientPixmap(orient, QColor::fromRgb(0, 0, 0, 0xFF), QColor::fromHsv(h, s, 0xFF, 0xFF), flip);
+ if (m_combiningAlpha) {
+ m_mainPixmap = gradientPixmap(orient, QColor::fromRgb(0, 0, 0, a), QColor::fromHsv(h, s, 0xFF, a), flip);
+ m_semiAlphaPixmap = gradientPixmap(orient, QColor::fromRgb(0, 0, 0, semi), QColor::fromHsv(h, s, 0xFF, semi), flip);
+ }
+ } else if (m_component == QtColorLine::Red) {
+ m_alphalessPixmap = gradientPixmap(orient, QColor::fromRgb(0, g, b, 0xFF), QColor::fromRgb(0xFF, g, b, 0xFF), flip);
+ if (m_combiningAlpha) {
+ m_mainPixmap = gradientPixmap(orient, QColor::fromRgb(0, g, b, a), QColor::fromRgb(0xFF, g, b, a), flip);
+ m_semiAlphaPixmap = gradientPixmap(orient, QColor::fromRgb(0, g, b, semi), QColor::fromRgb(0xFF, g, b, semi), flip);
+ }
+ } else if (m_component == QtColorLine::Green) {
+ m_alphalessPixmap = gradientPixmap(orient, QColor::fromRgb(r, 0, b, 0xFF), QColor::fromRgb(r, 0xFF, b, 0xFF), flip);
+ if (m_combiningAlpha) {
+ m_mainPixmap = gradientPixmap(orient, QColor::fromRgb(r, 0, b, a), QColor::fromRgb(r, 0xFF, b, a), flip);
+ m_semiAlphaPixmap = gradientPixmap(orient, QColor::fromRgb(r, 0, b, semi), QColor::fromRgb(r, 0xFF, b, semi), flip);
+ }
+ } else if (m_component == QtColorLine::Blue) {
+ m_alphalessPixmap = gradientPixmap(orient, QColor::fromRgb(r, g, 0, 0xFF), QColor::fromRgb(r, g, 0xFF, 0xFF), flip);
+ if (m_combiningAlpha) {
+ m_mainPixmap = gradientPixmap(orient, QColor::fromRgb(r, g, 0, a), QColor::fromRgb(r, g, 0xFF, a), flip);
+ m_semiAlphaPixmap = gradientPixmap(orient, QColor::fromRgb(r, g, 0, semi), QColor::fromRgb(r, g, 0xFF, semi), flip);
+ }
+ } else if (m_component == QtColorLine::Alpha) {
+ m_mainPixmap = gradientPixmap(orient, QColor::fromRgb(r, g, b, 0), QColor::fromRgb(r, g, b, 0xFF), flip);
+
+// m_alphalessPixmap = gradientPixmap(orient, QColor::fromRgb(r, g, b, 0xFF), QColor::fromRgb(r, g, b, 0xFF), flip);
+// m_semiAlphaPixmap = gradientPixmap(orient, QColor::fromRgb(r, g, b, semi), QColor::fromRgb(r, g, b, semi), flip);
+ }
+ if (!m_combiningAlpha && m_component != QtColorLine::Alpha)
+ m_mainPixmap = m_alphalessPixmap;
+}
+
+QSize QtColorLinePrivate::pixmapSizeFromGeometrySize(
+ const QSize &geometrySize) const
+{
+ QSize size(m_indicatorSize + 2 * m_indicatorSpace - 1,
+ m_indicatorSize + 2 * m_indicatorSpace - 1);
+ if (m_orientation == Qt::Horizontal)
+ size.setHeight(0);
+ else
+ size.setWidth(0);
+ return geometrySize - size;
+}
+
+QColor QtColorLinePrivate::colorFromPoint(const QPointF &point) const
+{
+ QPointF p = point;
+ if (p.x() < 0)
+ p.setX(0.0);
+ else if (p.x() > 1)
+ p.setX(1.0);
+ if (p.y() < 0)
+ p.setY(0.0);
+ else if (p.y() > 1)
+ p.setY(1.0);
+
+ double pos = p.x();
+ if (m_orientation == Qt::Vertical)
+ pos = p.y();
+ if (m_flipped)
+ pos = 1.0 - pos;
+ QColor c;
+ qreal hue;
+ switch (m_component) {
+ case QtColorLine::Red:
+ c.setRgbF(pos, m_color.greenF(), m_color.blueF(), m_color.alphaF());
+ break;
+ case QtColorLine::Green:
+ c.setRgbF(m_color.redF(), pos, m_color.blueF(), m_color.alphaF());
+ break;
+ case QtColorLine::Blue:
+ c.setRgbF(m_color.redF(), m_color.greenF(), pos, m_color.alphaF());
+ break;
+ case QtColorLine::Hue:
+ hue = pos;
+ hue *= 35999.0 / 36000.0;
+ c.setHsvF(hue, m_color.saturationF(), m_color.valueF(), m_color.alphaF());
+ break;
+ case QtColorLine::Saturation:
+ c.setHsvF(m_color.hueF(), pos, m_color.valueF(), m_color.alphaF());
+ break;
+ case QtColorLine::Value:
+ c.setHsvF(m_color.hueF(), m_color.saturationF(), pos, m_color.alphaF());
+ break;
+ case QtColorLine::Alpha:
+ c.setHsvF(m_color.hueF(), m_color.saturationF(), m_color.valueF(), pos);
+ break;
+ }
+ return c;
+}
+
+QPointF QtColorLinePrivate::pointFromColor(const QColor &color) const
+{
+ qreal hue = color.hueF();
+ if (color.hue() == 360)
+ hue = 0.0;
+ else
+ hue *= 36000.0 / 35999.0;
+
+ double pos = 0.0;
+ switch (m_component) {
+ case QtColorLine::Red:
+ pos = color.redF();
+ break;
+ case QtColorLine::Green:
+ pos = color.greenF();
+ break;
+ case QtColorLine::Blue:
+ pos = color.blueF();
+ break;
+ case QtColorLine::Hue:
+ pos = hue;
+ break;
+ case QtColorLine::Saturation:
+ pos = color.saturationF();
+ break;
+ case QtColorLine::Value:
+ pos = color.valueF();
+ break;
+ case QtColorLine::Alpha:
+ pos = color.alphaF();
+ break;
+ }
+ if (m_flipped)
+ pos = 1.0 - pos;
+ QPointF p(pos, pos);
+ if (m_orientation == Qt::Horizontal)
+ p.setY(0);
+ else
+ p.setX(0);
+ return p;
+}
+
+QVector<QRect> QtColorLinePrivate::rects(const QPointF &point) const
+{
+ QRect r = q_ptr->geometry();
+ r.moveTo(0, 0);
+
+ int x1 = (int)((r.width() - m_indicatorSize - 2 * m_indicatorSpace) * point.x() + 0.5);
+ int x2 = x1 + m_indicatorSize + 2 * m_indicatorSpace;
+ int y1 = (int)((r.height() - m_indicatorSize - 2 * m_indicatorSpace) * point.y() + 0.5);
+ int y2 = y1 + m_indicatorSize + 2 * m_indicatorSpace;
+
+ QVector<QRect> rects;
+ if (m_orientation == Qt::Horizontal) {
+ // r0 r1 r2
+ QRect r0(0, 0, x1, r.height());
+ QRect r1(x1 + m_indicatorSpace, 0, m_indicatorSize, r.height());
+ QRect r2(x2, 0, r.width() - x2, r.height());
+
+ rects << r0 << r1 << r2;
+ } else {
+ // r0
+ // r1
+ // r2
+ QRect r0(0, 0, r.width(), y1);
+ QRect r1(0, y1 + m_indicatorSpace, r.width(), m_indicatorSize);
+ QRect r2(0, y2, r.width(), r.height() - y2);
+
+ rects << r0 << r1 << r2;
+ }
+ return rects;
+}
+
+void QtColorLinePrivate::resizeEvent(QResizeEvent *event)
+{
+ m_pixmapSize = pixmapSizeFromGeometrySize(event->size());
+}
+
+void QtColorLinePrivate::paintEvent(QPaintEvent *)
+{
+ QRect rect = q_ptr->rect();
+
+ QVector<QRect> r = rects(m_point);
+
+ QColor cBack = q_ptr->palette().color(QPalette::Active, QPalette::Window);
+ QColor c = colorFromPoint(m_point);
+ if (!m_combiningAlpha && m_component != QtColorLine::Alpha)
+ c.setAlpha(0xFF);
+
+ QPainter p(q_ptr);
+ if (q_ptr->isEnabled()) {
+ if (m_backgroundCheckered) {
+ int pixSize = 20;
+ QPixmap pm(2 * pixSize, 2 * pixSize);
+ QPainter pmp(&pm);
+ pmp.fillRect(0, 0, pixSize, pixSize, Qt::white);
+ pmp.fillRect(pixSize, pixSize, pixSize, pixSize, Qt::white);
+ pmp.fillRect(0, pixSize, pixSize, pixSize, Qt::black);
+ pmp.fillRect(pixSize, 0, pixSize, pixSize, Qt::black);
+ pmp.end();
+
+ p.setBrushOrigin((rect.width() % pixSize + pixSize) / 2, (rect.height() % pixSize + pixSize) / 2);
+ p.setClipRect(r[1].adjusted(4, 4, -4, -4));
+ p.setClipRect(QRect(rect.topLeft(), QPoint(r[1].left() + 0, rect.bottom())), Qt::UniteClip);
+ p.setClipRect(QRect(QPoint(r[1].right() - 0, rect.top()), rect.bottomRight()), Qt::UniteClip);
+ p.setClipRect(QRect(rect.topLeft(), QPoint(rect.right(), r[1].top() + 0)), Qt::UniteClip);
+ p.setClipRect(QRect(QPoint(rect.left(), r[1].bottom() - 0), rect.bottomRight()), Qt::UniteClip);
+ /*
+ p.setClipRect(r[1].adjusted(3, 3, -3, -3));
+ p.setClipRect(QRect(rect.topLeft(), QPoint(r[1].left() + 1, rect.bottom())), Qt::UniteClip);
+ p.setClipRect(QRect(QPoint(r[1].right() - 1, rect.top()), rect.bottomRight()), Qt::UniteClip);
+ p.setClipRect(QRect(rect.topLeft(), QPoint(rect.right(), r[1].top() + 1)), Qt::UniteClip);
+ p.setClipRect(QRect(QPoint(rect.left(), r[1].bottom() - 1), rect.bottomRight()), Qt::UniteClip);
+ */
+ p.fillRect(rect, pm);
+ p.setBrushOrigin(0, 0);
+ p.setClipping(false);
+ }
+
+ validate();
+
+ QSize fieldSize = pixmapSizeFromGeometrySize(q_ptr->geometry().size());
+
+ QPoint posOnField = r[1].topLeft() - QPoint(m_indicatorSpace, m_indicatorSpace);
+ int x = posOnField.x();
+ int y = posOnField.y();
+ int w = fieldSize.width();
+ int h = fieldSize.height();
+
+ QRect r0, r2;
+ if (m_orientation == Qt::Horizontal) {
+ r0 = QRect(0, 0, x, m_pixmapSize.height());
+ r2 = QRect(x + 1, 0, w - x - 1, m_pixmapSize.height());
+ } else {
+ r0 = QRect(0, 0, m_pixmapSize.width(), y);
+ r2 = QRect(0, y + 1, m_pixmapSize.width(), h - y - 1);
+ }
+
+ p.setBrush(m_mainPixmap);
+ p.setPen(Qt::NoPen);
+ if (r[0].isValid()) {
+ p.drawRect(r[0]);
+ }
+ if (r[2].isValid()) {
+ p.setBrushOrigin(r[2].topLeft() - r2.topLeft());
+ p.drawRect(r[2]);
+ }
+ if (m_indicatorSpace) {
+ p.setBrush(c);
+ if (m_orientation == Qt::Horizontal) {
+ p.drawRect(r[1].adjusted(-m_indicatorSpace, 0, -r[1].width(), 0));
+ p.drawRect(r[1].adjusted(r[1].width(), 0, m_indicatorSpace, 0));
+ } else {
+ p.drawRect(r[1].adjusted(0, -m_indicatorSpace, 0, -r[1].height()));
+ p.drawRect(r[1].adjusted(0, r[1].height(), 0, m_indicatorSpace));
+ }
+ }
+
+ QPen pen(c);
+ p.setPen(pen);
+ p.setBrush(Qt::NoBrush);
+ if (r[1].isValid()) {
+ p.drawRect(r[1].adjusted(0, 0, -1, -1));
+ // p.drawRect(r[1].adjusted(1, 1, -2, -2));
+ }
+ double coef = 9.0 / 10;
+ p.setPen(Qt::NoPen);
+ if (m_component != QtColorLine::Alpha && m_combiningAlpha) {
+ p.setBrush(m_alphalessPixmap);
+ if (r[0].isValid()) {
+ p.setBrushOrigin(QPoint(0, 0));
+ QRect thinRect1 = r[0];
+ QRect thinRect2 = r[0];
+ QRect thinRect = r[0];
+ if (m_orientation == Qt::Horizontal) {
+ thinRect1.adjust(0, qRound(thinRect1.height() * coef), 0, 0);
+ thinRect2.adjust(0, 0, 0, -qRound(thinRect2.height() * coef));
+ thinRect.adjust(0, qRound(thinRect.height() * coef), 0, -qRound(thinRect.height() * coef));
+ } else {
+ thinRect1.adjust(qRound(thinRect1.width() * coef), 0, 0, 0);
+ thinRect2.adjust(0, 0, -qRound(thinRect2.width() * coef), 0);
+ thinRect.adjust(qRound(thinRect.width() * coef), 0, -qRound(thinRect.width() * coef), 0);
+ }
+ p.drawRect(thinRect1);
+ p.drawRect(thinRect2);
+ //p.drawRect(thinRect);
+ }
+ if (r[2].isValid()) {
+ p.setBrushOrigin(r[2].topLeft() - r2.topLeft());
+ QRect thinRect1 = r[2];
+ QRect thinRect2 = r[2];
+ QRect thinRect = r[2];
+ if (m_orientation == Qt::Horizontal) {
+ thinRect1.adjust(0, qRound(thinRect1.height() * coef), 0, 0);
+ thinRect2.adjust(0, 0, 0, -qRound(thinRect2.height() * coef));
+ thinRect.adjust(0, qRound(thinRect.height() * coef), 0, -qRound(thinRect.height() * coef));
+ } else {
+ thinRect1.adjust(qRound(thinRect1.width() * coef), 0, 0, 0);
+ thinRect2.adjust(0, 0, -qRound(thinRect2.width() * coef), 0);
+ thinRect.adjust(qRound(thinRect.width() * coef), 0, -qRound(thinRect.width() * coef), 0);
+ }
+ p.drawRect(thinRect1);
+ p.drawRect(thinRect2);
+ //p.drawRect(thinRect);
+ }
+ /*
+
+*/
+
+
+
+
+
+ p.setPen(Qt::NoPen);
+
+ p.setBrush(m_semiAlphaPixmap);
+ if (r[0].isValid()) {
+ p.setBrushOrigin(QPoint(0, 0));
+ QRect thinRect1 = r[0];
+ QRect thinRect2 = r[0];
+ QRect thinRect = r[0];
+ if (m_orientation == Qt::Horizontal) {
+ thinRect1.adjust(0, qRound(thinRect1.height() * coef) - 1, 0, 0);
+ thinRect1.setBottom(thinRect1.top());
+ thinRect2.adjust(0, 0, 0, -qRound(thinRect2.height() * coef) + 1);
+ thinRect2.setTop(thinRect2.bottom());
+ thinRect.adjust(0, qRound(thinRect.height() * coef), 0, -qRound(thinRect.height() * coef));
+ } else {
+ thinRect1.adjust(qRound(thinRect1.width() * coef) - 1, 0, 0, 0);
+ thinRect1.setRight(thinRect1.left());
+ thinRect2.adjust(0, 0, -qRound(thinRect2.width() * coef) + 1, 0);
+ thinRect2.setLeft(thinRect2.right());
+ thinRect.adjust(qRound(thinRect.width() * coef), 0, -qRound(thinRect.width() * coef), 0);
+ }
+ p.drawRect(thinRect1);
+ p.drawRect(thinRect2);
+ //p.drawRect(thinRect);
+ }
+ if (r[2].isValid()) {
+ p.setBrushOrigin(r[2].topLeft() - r2.topLeft());
+ QRect thinRect1 = r[2];
+ QRect thinRect2 = r[2];
+ QRect thinRect = r[2];
+ if (m_orientation == Qt::Horizontal) {
+ thinRect1.adjust(0, qRound(thinRect1.height() * coef) - 1, 0, 0);
+ thinRect1.setBottom(thinRect1.top());
+ thinRect2.adjust(0, 0, 0, -qRound(thinRect2.height() * coef) + 1);
+ thinRect2.setTop(thinRect2.bottom());
+ thinRect.adjust(0, qRound(thinRect.height() * coef), 0, -qRound(thinRect.height() * coef));
+ } else {
+ thinRect1.adjust(qRound(thinRect1.width() * coef) - 1, 0, 0, 0);
+ thinRect1.setRight(thinRect1.left());
+ thinRect2.adjust(0, 0, -qRound(thinRect2.width() * coef) + 1, 0);
+ thinRect2.setLeft(thinRect2.right());
+ thinRect.adjust(qRound(thinRect.width() * coef), 0, -qRound(thinRect.width() * coef), 0);
+ }
+ p.drawRect(thinRect1);
+ p.drawRect(thinRect2);
+ //p.drawRect(thinRect);
+ }
+ p.setBrush(m_alphalessPixmap);
+ if (m_orientation == Qt::Horizontal) {
+ p.setClipRect(r[1].adjusted(0, qRound(r[1].height() * coef), 0, 0));
+ p.setClipRect(r[1].adjusted(0, 0, 0, -qRound(r[1].height() * coef)), Qt::UniteClip);
+ } else {
+ p.setClipRect(r[1].adjusted(qRound(r[1].width() * coef), 0, 0, 0));
+ p.setClipRect(r[1].adjusted(0, 0, -qRound(r[1].width() * coef), 0), Qt::UniteClip);
+ }
+ p.setBrush(Qt::NoBrush);
+ p.setPen(QPen(QColor(c.rgb())));
+
+ p.drawRect(r[1].adjusted(0, 0, -1, -1));
+ // p.drawRect(r[1].adjusted(1, 1, -2, -2));
+/*
+ p.setBrush(m_semiAlphaPixmap);
+ if (m_orientation == Qt::Horizontal) {
+ QRect top = r[1].adjusted(0, 0, 0, -qRound(r[1].height() * coef) + 1);
+ top.setTop(top.bottom());
+ QRect bottom = r[1].adjusted(0, qRound(r[1].height() * coef) - 1, 0, 0);
+ top.setBottom(bottom.top());
+ p.setClipRect(top);
+ p.setClipRect(bottom, Qt::UniteClip);
+ } else {
+
+ }
+ QColor semiColor(c.rgb());
+ semiColor.setAlpha((c.alpha() + 0xFF) / 2);
+ p.setPen(QPen(semiColor));
+ p.drawRect(r[1].adjusted(0, 0, -1, -1));
+ // p.drawRect(r[1].adjusted(1, 1, -2, -2));
+*/
+ p.setClipping(false);
+ }
+ }
+
+ p.setBrush(Qt::NoBrush);
+ int lw = 4;
+ //int br = 1;
+ int br = 0;
+ r[1].adjust(br, br, -br, -br);
+ if (r[1].adjusted(lw, lw, -lw, -lw).isValid()) {
+ QStyleOptionFrame opt;
+ opt.init(q_ptr);
+ opt.rect = r[1];
+ opt.lineWidth = 2;
+ opt.midLineWidth = 1;
+ if (m_dragging)
+ opt.state |= QStyle::State_Sunken;
+ else
+ opt.state |= QStyle::State_Raised;
+ q_ptr->style()->drawPrimitive(QStyle::PE_Frame, &opt, &p, q_ptr);
+ QRect colorRect = r[1].adjusted(lw, lw, -lw, -lw);
+ if (q_ptr->isEnabled()) {
+ p.fillRect(colorRect, c);
+ const QColor frameColor(0, 0, 0, 38);
+ p.setPen(frameColor);
+ p.drawRect(colorRect.adjusted(0, 0, -1, -1));
+ /*
+ p.fillRect(colorRect.width() / 4 + colorRect.left(),
+ colorRect.height() / 4 + colorRect.top(),
+ colorRect.width() / 2,
+ colorRect.height() / 2,
+ QColor(c.rgb()));
+ */
+ /*
+ if (m_component != QtColorLine::Alpha) {
+ p.fillRect(colorRect.adjusted(0, colorRect.height() * 4 / 5, 0, 0), QColor(c.rgb()));
+ p.fillRect(colorRect.adjusted(0, 0, 0, -colorRect.height() * 4 / 5), QColor(c.rgb()));
+ }
+ */
+ }
+ }
+}
+
+void QtColorLinePrivate::mousePressEvent(QMouseEvent *event)
+{
+ if (event->button() != Qt::LeftButton)
+ return;
+
+ QVector<QRect> r = rects(m_point);
+ QPoint clickPos = event->pos();
+
+ QSize fieldSize = q_ptr->geometry().size() -
+ QSize(m_indicatorSize + 2 * m_indicatorSpace - 1, m_indicatorSize + 2 * m_indicatorSpace - 1);
+ QPoint posOnField = r[1].topLeft() - QPoint(m_indicatorSpace, m_indicatorSpace);
+ m_clickOffset = posOnField - clickPos;
+
+ if (!r[1].contains(clickPos))
+ return;
+ m_dragging = true;
+ q_ptr->update();
+}
+
+void QtColorLinePrivate::mouseMoveEvent(QMouseEvent *event)
+{
+ if (!m_dragging)
+ return;
+ QPoint newPos = event->pos();
+
+ QSize fieldSize = q_ptr->geometry().size() -
+ QSize(m_indicatorSize + 2 * m_indicatorSpace - 1, m_indicatorSize + 2 * m_indicatorSpace - 1);
+ QPoint newPosOnField = newPos + m_clickOffset;
+ if (newPosOnField.x() < 0)
+ newPosOnField.setX(0);
+ else if (newPosOnField.x() > fieldSize.width())
+ newPosOnField.setX(fieldSize.width());
+ if (newPosOnField.y() < 0)
+ newPosOnField.setY(0);
+ else if (newPosOnField.y() > fieldSize.height())
+ newPosOnField.setY(fieldSize.height());
+
+ double x = (double)newPosOnField.x() / fieldSize.width();
+ double y = (double)newPosOnField.y() / fieldSize.height();
+ m_point = QPointF(x, y);
+ QColor color = colorFromPoint(m_point);
+ if (m_color == color)
+ return;
+ m_color = color;
+ emit q_ptr->colorChanged(color); // maybe before internal set, 1 line above
+ q_ptr->update();
+}
+
+void QtColorLinePrivate::mouseReleaseEvent(QMouseEvent *event)
+{
+ if (event->button() != Qt::LeftButton)
+ return;
+ m_dragging = false;
+ q_ptr->update();
+}
+
+void QtColorLinePrivate::mouseDoubleClickEvent(QMouseEvent *event)
+{
+ if (event->button() != Qt::LeftButton)
+ return;
+
+ QVector<QRect> r = rects(m_point);
+ QPoint clickPos = event->pos();
+ if (!r[0].contains(clickPos) && !r[2].contains(clickPos))
+ return;
+ QPoint newPosOnField = clickPos;
+ if (r[2].contains(clickPos))
+ newPosOnField -= QPoint(m_indicatorSize + 2 * m_indicatorSpace - 2, m_indicatorSize + 2 * m_indicatorSpace - 2);
+ QSize fieldSize = q_ptr->geometry().size() -
+ QSize(m_indicatorSize + 2 * m_indicatorSpace - 1, m_indicatorSize + 2 * m_indicatorSpace - 1);
+
+ double x = (double)newPosOnField.x() / fieldSize.width();
+ double y = (double)newPosOnField.y() / fieldSize.height();
+ m_point = QPointF(x, y);
+ QColor color = colorFromPoint(m_point);
+ if (m_color == color)
+ return;
+ m_color = color;
+ emit q_ptr->colorChanged(color); // maybe before internal set, 1 line above
+ q_ptr->update();
+}
+
+////////////////////////////////////////////////////
+
+QtColorLine::QtColorLine(QWidget *parent)
+ : QWidget(parent), d_ptr(new QtColorLinePrivate)
+{
+ d_ptr->q_ptr = this;
+
+ setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
+}
+
+QtColorLine::~QtColorLine()
+{
+}
+
+QSize QtColorLine::minimumSizeHint() const
+{
+ return QSize(d_ptr->m_indicatorSize, d_ptr->m_indicatorSize);
+}
+
+QSize QtColorLine::sizeHint() const
+{
+ return QSize(d_ptr->m_indicatorSize, d_ptr->m_indicatorSize);
+}
+
+void QtColorLine::setColor(const QColor &color)
+{
+ d_ptr->setColor(color);
+}
+
+QColor QtColorLine::color() const
+{
+ return d_ptr->color();
+}
+
+void QtColorLine::setColorComponent(QtColorLine::ColorComponent component)
+{
+ d_ptr->setColorComponent(component);
+}
+
+QtColorLine::ColorComponent QtColorLine::colorComponent() const
+{
+ return d_ptr->colorComponent();
+}
+
+void QtColorLine::setIndicatorSize(int size)
+{
+ d_ptr->setIndicatorSize(size);
+}
+
+int QtColorLine::indicatorSize() const
+{
+ return d_ptr->indicatorSize();
+}
+
+void QtColorLine::setIndicatorSpace(int space)
+{
+ d_ptr->setIndicatorSpace(space);
+}
+
+int QtColorLine::indicatorSpace() const
+{
+ return d_ptr->indicatorSpace();
+}
+
+void QtColorLine::setFlip(bool flip)
+{
+ d_ptr->setFlip(flip);
+}
+
+bool QtColorLine::flip() const
+{
+ return d_ptr->flip();
+}
+
+void QtColorLine::setBackgroundCheckered(bool checkered)
+{
+ d_ptr->setBackgroundCheckered(checkered);
+}
+
+bool QtColorLine::isBackgroundCheckered() const
+{
+ return d_ptr->isBackgroundCheckered();
+}
+
+void QtColorLine::setOrientation(Qt::Orientation orientation)
+{
+ d_ptr->setOrientation(orientation);
+}
+
+Qt::Orientation QtColorLine::orientation() const
+{
+ return d_ptr->orientation();
+}
+void QtColorLine::resizeEvent(QResizeEvent *event)
+{
+ d_ptr->resizeEvent(event);
+}
+
+void QtColorLine::paintEvent(QPaintEvent *event)
+{
+ d_ptr->paintEvent(event);
+}
+
+void QtColorLine::mousePressEvent(QMouseEvent *event)
+{
+ d_ptr->mousePressEvent(event);
+}
+
+void QtColorLine::mouseMoveEvent(QMouseEvent *event)
+{
+ d_ptr->mouseMoveEvent(event);
+}
+
+void QtColorLine::mouseReleaseEvent(QMouseEvent *event)
+{
+ d_ptr->mouseReleaseEvent(event);
+}
+
+void QtColorLine::mouseDoubleClickEvent(QMouseEvent *event)
+{
+ d_ptr->mouseDoubleClickEvent(event);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtcolorline.h b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtcolorline.h
new file mode 100644
index 0000000000..5171fed4b0
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtcolorline.h
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTCOLORLINE_H
+#define QTCOLORLINE_H
+
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class QtColorLine : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(QColor color READ color WRITE setColor)
+ Q_PROPERTY(int indicatorSpace READ indicatorSpace WRITE setIndicatorSpace)
+ Q_PROPERTY(int indicatorSize READ indicatorSize WRITE setIndicatorSize)
+ Q_PROPERTY(bool flip READ flip WRITE setFlip)
+ Q_PROPERTY(bool backgroundCheckered READ isBackgroundCheckered WRITE setBackgroundCheckered)
+ Q_PROPERTY(ColorComponent colorComponent READ colorComponent WRITE setColorComponent)
+ Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation)
+ Q_ENUMS(ColorComponent)
+public:
+
+ enum ColorComponent {
+ Red,
+ Green,
+ Blue,
+ Hue,
+ Saturation,
+ Value,
+ Alpha
+ };
+
+ QSize minimumSizeHint() const;
+ QSize sizeHint() const;
+
+ QtColorLine(QWidget *parent = 0);
+ ~QtColorLine();
+
+ QColor color() const;
+
+ void setIndicatorSize(int size);
+ int indicatorSize() const;
+
+ void setIndicatorSpace(int space);
+ int indicatorSpace() const;
+
+ void setFlip(bool flip);
+ bool flip() const;
+
+ bool isBackgroundCheckered() const;
+ void setBackgroundCheckered(bool checkered);
+
+ void setOrientation(Qt::Orientation orientation);
+ Qt::Orientation orientation() const;
+
+ void setColorComponent(ColorComponent component);
+ ColorComponent colorComponent() const;
+
+public slots:
+
+ void setColor(const QColor &color);
+
+signals:
+
+ void colorChanged(const QColor &color);
+
+protected:
+
+ void resizeEvent(QResizeEvent *event);
+ void paintEvent(QPaintEvent *event);
+ void mousePressEvent(QMouseEvent *event);
+ void mouseMoveEvent(QMouseEvent *event);
+ void mouseReleaseEvent(QMouseEvent *event);
+ void mouseDoubleClickEvent(QMouseEvent *event);
+
+private:
+
+ QScopedPointer<class QtColorLinePrivate> d_ptr;
+ Q_DECLARE_PRIVATE(QtColorLine)
+ Q_DISABLE_COPY(QtColorLine)
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientdialog.cpp b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientdialog.cpp
new file mode 100644
index 0000000000..d178829fc6
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientdialog.cpp
@@ -0,0 +1,353 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtgradientdialog.h"
+#include "ui_qtgradientdialog.h"
+#include <QtGui/QPushButton>
+
+QT_BEGIN_NAMESPACE
+
+class QtGradientDialogPrivate
+{
+ QtGradientDialog *q_ptr;
+ Q_DECLARE_PUBLIC(QtGradientDialog)
+public:
+
+ void slotAboutToShowDetails(bool details, int extensionWidthHint);
+
+ Ui::QtGradientDialog m_ui;
+};
+
+void QtGradientDialogPrivate::slotAboutToShowDetails(bool details, int extensionWidthHint)
+{
+ if (details) {
+ q_ptr->resize(q_ptr->size() + QSize(extensionWidthHint, 0));
+ } else {
+ q_ptr->setMinimumSize(1, 1);
+ q_ptr->resize(q_ptr->size() - QSize(extensionWidthHint, 0));
+ q_ptr->setMinimumSize(0, 0);
+ }
+}
+
+/*!
+ \class QtGradientDialog
+
+ \brief The QtGradientDialog class provides a dialog for specifying gradients.
+
+ The gradient dialog's function is to allow users to edit gradients.
+ For example, you might use this in a drawing program to allow the user to set the brush gradient.
+
+ \table
+ \row
+ \o \inlineimage qtgradientdialog.png
+ \o \inlineimage qtgradientdialogextension.png
+ \header
+ \o Details extension hidden
+ \o Details extension visible
+ \endtable
+
+ Starting from the top of the dialog there are several buttons:
+
+ \image qtgradientdialogtopbuttons.png
+
+ The first three buttons allow for changing a type of the gradient (QGradient::Type), while the second three allow for
+ changing spread of the gradient (QGradient::Spread). The last button shows or hides the details extension of the dialog.
+ Conceptually the default view with hidden details provides the full functional control over gradient editing.
+ The additional extension with details allows to set gradient's parameters more precisely. The visibility
+ of extension can be controlled by detailsVisible property. Moreover, if you don't want the user to
+ switch on or off the visibility of extension you can set the detailsButtonVisible property to false.
+
+ Below top buttons there is an area where edited gradient is interactively previewed.
+ In addition the user can edit gradient type's specific parameters directly in this area by dragging
+ appropriate handles.
+
+ \table
+ \row
+ \o \inlineimage qtgradientdialoglineareditor.png
+ \o \inlineimage qtgradientdialogradialeditor.png
+ \o \inlineimage qtgradientdialogconicaleditor.png
+ \header
+ \o Editing linear type
+ \o Editing radial type
+ \o Editing conical type
+ \row
+ \o The user can change the start and final point positions by dragging the circular handles.
+ \o The user can change the center and focal point positions by dragging the circular handles
+ and can change the gradient's radius by dragging horizontal or vertical line.
+ \o The user can change the center point by dragging the circular handle
+ and can change the gradient's angle by dragging the big wheel.
+ \endtable
+
+ In the middle of the dialog there is an area where the user can edit gradient stops.
+
+ \table
+ \row
+ \o \inlineimage qtgradientdialogstops.png
+ \o \inlineimage qtgradientdialogstopszoomed.png
+ \endtable
+
+ The top part of this area contains stop handles, and bottom part shows the preview of gradient stops path.
+ In order to create a new gradient stop double click inside the view over the desired position.
+ If you double click on existing stop handle in the top part of the view, clicked handle will be duplicated
+ (duplicate will contain the same color).
+ The stop can be activated by clicking on its handle. You can activate previous or next stop by pressing
+ left or right key respectively. To jump to the first or last stop press home or end key respectively.
+ The gradient stops editor supports multiselection.
+ Clicking a handle holding the shift modifier key down will select a range of stops between
+ the active stop and clicked one. Clicking a handle holding control modifier key down will remove from or
+ add to selection the clicked stop depending if it was or wasn't already selected respectively.
+ Multiselection can also be created using rubberband (by pressing the left mouse button outside
+ of any handle and dragging).
+ Sometimes it's hard to select a stop because its handle can be partially covered by other handle.
+ In that case the user can zoom in the view by spinning mouse wheel.
+ The selected stop handles can be moved by drag & drop. In order to remove selected stops press delete key.
+ For convenience context menu is provided with the following actions:
+
+ \list
+ \o New Stop - creates a new gradient stop
+ \o Delete - removes the active and all selected stops
+ \o Flip All - mirrors all stops
+ \o Select All - selects all stops
+ \o Zoom In - zooms in
+ \o Zoom Out - zooms out
+ \o Zoom All - goes back to original 100% zoom
+ \endlist
+
+ The bottom part of the QtGradientDialog contains a set of widgets allowing to control the color of
+ the active and selected stops.
+
+ \table
+ \row
+ \o \inlineimage qtgradientdialogcolorhsv.png
+ \o \inlineimage qtgradientdialogcolorrgb.png
+ \endtable
+
+
+ The color button shows the color of the active gradient stop. It also allows for choosing
+ a color from standard color dialog and applying it to the
+ active stop and all selected stops. It's also possible to drag a color directly from the color button
+ and to drop it in gradient stops editor at desired position (it will create new stop with dragged color)
+ or at desired stop handle (it will change the color of that handle).
+
+ To the right of color button there is a set of 2 radio buttons which allows to switch between
+ HVS and RGB color spec.
+
+ Finally there are 4 color sliders working either in HSVA (hue saturation value alpha) or
+ RGBA (red green blue alpha) mode, depending on which radio button is chosen. The radio buttons
+ can be controlled programatically by spec() and setSpec() methods. The sliders show the
+ color of the active stop. By double clicking inside color slider you can set directly the desired color.
+ Changes of slider's are applied to stop selection in the way that the color
+ component being changed is applied to stops in selection only, while other components
+ remain unchanged in selected stops (e.g. when the user is changing the saturation,
+ new saturation is applied to selected stops preventing original hue, value and alpha in multiselection).
+
+ The convenient static functions getGradient() provide modal gradient dialogs, e.g.:
+
+ \snippet doc/src/snippets/code/tools_shared_qtgradienteditor_qtgradientdialog.cpp 0
+
+ In order to have more control over the properties of QtGradientDialog use
+ standard QDialog::exec() method:
+
+ \snippet doc/src/snippets/code/tools_shared_qtgradienteditor_qtgradientdialog.cpp 1
+
+ \sa {Gradient View Example}
+*/
+
+/*!
+ Constructs a gradient dialog with \a parent as parent widget.
+*/
+
+QtGradientDialog::QtGradientDialog(QWidget *parent)
+ : QDialog(parent), d_ptr(new QtGradientDialogPrivate())
+{
+// setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+ d_ptr->q_ptr = this;
+ d_ptr->m_ui.setupUi(this);
+ QPushButton *button = d_ptr->m_ui.buttonBox->button(QDialogButtonBox::Ok);
+ if (button)
+ button->setAutoDefault(false);
+ button = d_ptr->m_ui.buttonBox->button(QDialogButtonBox::Cancel);
+ if (button)
+ button->setAutoDefault(false);
+ connect(d_ptr->m_ui.gradientEditor, SIGNAL(aboutToShowDetails(bool,int)),
+ this, SLOT(slotAboutToShowDetails(bool,int)));
+}
+
+/*!
+ Destroys the gradient dialog
+*/
+
+QtGradientDialog::~QtGradientDialog()
+{
+}
+
+/*!
+ \property QtGradientDialog::gradient
+ \brief the gradient of the dialog
+*/
+void QtGradientDialog::setGradient(const QGradient &gradient)
+{
+ d_ptr->m_ui.gradientEditor->setGradient(gradient);
+}
+
+QGradient QtGradientDialog::gradient() const
+{
+ return d_ptr->m_ui.gradientEditor->gradient();
+}
+
+/*!
+ \property QtGradientDialog::backgroundCheckered
+ \brief whether the background of widgets able to show the colors with alpha channel is checkered.
+
+ \table
+ \row
+ \o \inlineimage qtgradientdialogbackgroundcheckered.png
+ \o \inlineimage qtgradientdialogbackgroundtransparent.png
+ \row
+ \o \snippet doc/src/snippets/code/tools_shared_qtgradienteditor_qtgradientdialog.cpp 2
+ \o \snippet doc/src/snippets/code/tools_shared_qtgradienteditor_qtgradientdialog.cpp 3
+ \endtable
+
+ When this property is set to true (the default) widgets inside gradient dialog like color button,
+ color sliders, gradient stops editor and gradient editor will show checkered background
+ in case of transparent colors. Otherwise the background of these widgets is transparent.
+*/
+
+bool QtGradientDialog::isBackgroundCheckered() const
+{
+ return d_ptr->m_ui.gradientEditor->isBackgroundCheckered();
+}
+
+void QtGradientDialog::setBackgroundCheckered(bool checkered)
+{
+ d_ptr->m_ui.gradientEditor->setBackgroundCheckered(checkered);
+}
+
+/*!
+ \property QtGradientDialog::detailsVisible
+ \brief whether details extension is visible.
+
+ When this property is set to true the details extension is visible. By default
+ this property is set to false and the details extension is hidden.
+
+ \sa detailsButtonVisible
+*/
+bool QtGradientDialog::detailsVisible() const
+{
+ return d_ptr->m_ui.gradientEditor->detailsVisible();
+}
+
+void QtGradientDialog::setDetailsVisible(bool visible)
+{
+ d_ptr->m_ui.gradientEditor->setDetailsVisible(visible);
+}
+
+/*!
+ \property QtGradientDialog::detailsButtonVisible
+ \brief whether the details button allowing for showing and hiding details extension is visible.
+
+ When this property is set to true (the default) the details button is visible and the user
+ can show and hide details extension interactively. Otherwise the button is hidden and the details
+ extension is always visible or hidded depending on the value of detailsVisible property.
+
+ \sa detailsVisible
+*/
+bool QtGradientDialog::isDetailsButtonVisible() const
+{
+ return d_ptr->m_ui.gradientEditor->isDetailsButtonVisible();
+}
+
+void QtGradientDialog::setDetailsButtonVisible(bool visible)
+{
+ d_ptr->m_ui.gradientEditor->setDetailsButtonVisible(visible);
+}
+
+/*!
+ Returns the current QColor::Spec used for the color sliders in the dialog.
+*/
+QColor::Spec QtGradientDialog::spec() const
+{
+ return d_ptr->m_ui.gradientEditor->spec();
+}
+
+/*!
+ Sets the current QColor::Spec to \a spec used for the color sliders in the dialog.
+*/
+void QtGradientDialog::setSpec(QColor::Spec spec)
+{
+ d_ptr->m_ui.gradientEditor->setSpec(spec);
+}
+
+/*!
+ Executes a modal gradient dialog, lets the user to specify a gradient, and returns that gradient.
+
+ If the user clicks \gui OK, the gradient specified by the user is returned. If the user clicks \gui Cancel, the \a initial gradient is returned.
+
+ The dialog is constructed with the given \a parent. \a caption is shown as the window title of the dialog and
+ \a initial is the initial gradient shown in the dialog. If the \a ok parameter is not-null,
+ the value it refers to is set to true if the user clicks \gui OK, and set to false if the user clicks \gui Cancel.
+*/
+QGradient QtGradientDialog::getGradient(bool *ok, const QGradient &initial, QWidget *parent, const QString &caption)
+{
+ QtGradientDialog dlg(parent);
+ if (!caption.isEmpty())
+ dlg.setWindowTitle(caption);
+ dlg.setGradient(initial);
+ const int res = dlg.exec();
+ if (ok) {
+ *ok = (res == QDialog::Accepted) ? true : false;
+ }
+ if (res == QDialog::Accepted)
+ return dlg.gradient();
+ return initial;
+}
+
+/*!
+ This method calls getGradient(ok, QLinearGradient(), parent, caption).
+*/
+QGradient QtGradientDialog::getGradient(bool *ok, QWidget *parent, const QString &caption)
+{
+ return getGradient(ok, QLinearGradient(), parent, caption);
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qtgradientdialog.cpp"
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientdialog.h b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientdialog.h
new file mode 100644
index 0000000000..f298c8ba9b
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientdialog.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTGRADIENTDIALOG_H
+#define QTGRADIENTDIALOG_H
+
+#include <QtGui/QDialog>
+
+QT_BEGIN_NAMESPACE
+
+class QtGradientDialog : public QDialog
+{
+ Q_OBJECT
+ Q_PROPERTY(QGradient gradient READ gradient WRITE setGradient)
+ Q_PROPERTY(bool backgroundCheckered READ isBackgroundCheckered WRITE setBackgroundCheckered)
+ Q_PROPERTY(bool detailsVisible READ detailsVisible WRITE setDetailsVisible)
+ Q_PROPERTY(bool detailsButtonVisible READ isDetailsButtonVisible WRITE setDetailsButtonVisible)
+public:
+ QtGradientDialog(QWidget *parent = 0);
+ ~QtGradientDialog();
+
+ void setGradient(const QGradient &gradient);
+ QGradient gradient() const;
+
+ bool isBackgroundCheckered() const;
+ void setBackgroundCheckered(bool checkered);
+
+ bool detailsVisible() const;
+ void setDetailsVisible(bool visible);
+
+ bool isDetailsButtonVisible() const;
+ void setDetailsButtonVisible(bool visible);
+
+ QColor::Spec spec() const;
+ void setSpec(QColor::Spec spec);
+
+ static QGradient getGradient(bool *ok, const QGradient &initial, QWidget *parent = 0, const QString &caption = QString());
+ static QGradient getGradient(bool *ok, QWidget *parent = 0, const QString &caption = QString());
+
+private:
+ QScopedPointer<class QtGradientDialogPrivate> d_ptr;
+ Q_DECLARE_PRIVATE(QtGradientDialog)
+ Q_DISABLE_COPY(QtGradientDialog)
+ Q_PRIVATE_SLOT(d_func(), void slotAboutToShowDetails(bool details, int extensionWidthHint))
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientdialog.ui b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientdialog.ui
new file mode 100644
index 0000000000..3fc9586ada
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientdialog.ui
@@ -0,0 +1,121 @@
+<ui version="4.0" >
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <class>QtGradientDialog</class>
+ <widget class="QDialog" name="QtGradientDialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>178</width>
+ <height>81</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Edit Gradient</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <item>
+ <widget class="QtGradientEditor" name="gradientEditor" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="MinimumExpanding" hsizetype="MinimumExpanding" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>QtGradientEditor</class>
+ <extends>QFrame</extends>
+ <header>qtgradienteditor.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>QtGradientDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>72</x>
+ <y>224</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>21</x>
+ <y>243</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>QtGradientDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>168</x>
+ <y>233</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>152</x>
+ <y>251</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradienteditor.cpp b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradienteditor.cpp
new file mode 100644
index 0000000000..d9b42beb58
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradienteditor.cpp
@@ -0,0 +1,952 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtgradienteditor.h"
+#include "qtgradientstopscontroller.h"
+#include "ui_qtgradienteditor.h"
+
+QT_BEGIN_NAMESPACE
+
+class QtGradientEditorPrivate
+{
+ QtGradientEditor *q_ptr;
+ Q_DECLARE_PUBLIC(QtGradientEditor)
+public:
+ QtGradientEditorPrivate() : m_gradient(QLinearGradient()) {}
+
+ void slotGradientStopsChanged(const QGradientStops &stops);
+ void slotTypeChanged(int type);
+ void slotSpreadChanged(int spread);
+ void slotStartLinearXChanged(double value);
+ void slotStartLinearYChanged(double value);
+ void slotEndLinearXChanged(double value);
+ void slotEndLinearYChanged(double value);
+ void slotCentralRadialXChanged(double value);
+ void slotCentralRadialYChanged(double value);
+ void slotFocalRadialXChanged(double value);
+ void slotFocalRadialYChanged(double value);
+ void slotRadiusRadialChanged(double value);
+ void slotCentralConicalXChanged(double value);
+ void slotCentralConicalYChanged(double value);
+ void slotAngleConicalChanged(double value);
+
+ void slotDetailsChanged(bool details);
+
+ void startLinearChanged(const QPointF &point);
+ void endLinearChanged(const QPointF &point);
+ void centralRadialChanged(const QPointF &point);
+ void focalRadialChanged(const QPointF &point);
+ void radiusRadialChanged(qreal radius);
+ void centralConicalChanged(const QPointF &point);
+ void angleConicalChanged(qreal angle);
+
+ void setStartLinear(const QPointF &point);
+ void setEndLinear(const QPointF &point);
+ void setCentralRadial(const QPointF &point);
+ void setFocalRadial(const QPointF &point);
+ void setRadiusRadial(qreal radius);
+ void setCentralConical(const QPointF &point);
+ void setAngleConical(qreal angle);
+
+ void setType(QGradient::Type type);
+ void showDetails(bool details);
+
+ void setSpinBox(QDoubleSpinBox *spinBox, const char *slot, double max = 1.0, double step = 0.01, int decimals = 3);
+ void reset();
+ void setLayout(bool details);
+ void layoutDetails(bool details);
+ bool row4Visible() const;
+ bool row5Visible() const;
+ int extensionWidthHint() const;
+
+ void setCombos(bool combos);
+
+ QGradient gradient() const;
+ void updateGradient(bool emitSignal);
+
+ Ui::QtGradientEditor m_ui;
+ QtGradientStopsController *m_gradientStopsController;
+
+ QDoubleSpinBox *startLinearXSpinBox;
+ QDoubleSpinBox *startLinearYSpinBox;
+ QDoubleSpinBox *endLinearXSpinBox;
+ QDoubleSpinBox *endLinearYSpinBox;
+ QDoubleSpinBox *centralRadialXSpinBox;
+ QDoubleSpinBox *centralRadialYSpinBox;
+ QDoubleSpinBox *focalRadialXSpinBox;
+ QDoubleSpinBox *focalRadialYSpinBox;
+ QDoubleSpinBox *radiusRadialSpinBox;
+ QDoubleSpinBox *centralConicalXSpinBox;
+ QDoubleSpinBox *centralConicalYSpinBox;
+ QDoubleSpinBox *angleConicalSpinBox;
+
+ QButtonGroup *m_typeGroup;
+ QButtonGroup *m_spreadGroup;
+
+ QGradient::Type m_type;
+
+ QGridLayout *m_gridLayout;
+ QWidget *m_hiddenWidget;
+ QGridLayout *m_hiddenLayout;
+ bool m_details;
+ bool m_detailsButtonVisible;
+ bool m_backgroundCheckered;
+
+ QGradient m_gradient;
+
+ bool m_combos;
+};
+
+QGradient QtGradientEditorPrivate::gradient() const
+{
+ QGradient *gradient = 0;
+ switch (m_ui.gradientWidget->gradientType()) {
+ case QGradient::LinearGradient:
+ gradient = new QLinearGradient(m_ui.gradientWidget->startLinear(),
+ m_ui.gradientWidget->endLinear());
+ break;
+ case QGradient::RadialGradient:
+ gradient = new QRadialGradient(m_ui.gradientWidget->centralRadial(),
+ m_ui.gradientWidget->radiusRadial(),
+ m_ui.gradientWidget->focalRadial());
+ break;
+ case QGradient::ConicalGradient:
+ gradient = new QConicalGradient(m_ui.gradientWidget->centralConical(),
+ m_ui.gradientWidget->angleConical());
+ break;
+ default:
+ break;
+ }
+ if (!gradient)
+ return QGradient();
+ gradient->setStops(m_ui.gradientWidget->gradientStops());
+ gradient->setSpread(m_ui.gradientWidget->gradientSpread());
+ gradient->setCoordinateMode(QGradient::StretchToDeviceMode);
+ QGradient gr = *gradient;
+ delete gradient;
+ return gr;
+}
+
+void QtGradientEditorPrivate::updateGradient(bool emitSignal)
+{
+ QGradient grad = gradient();
+ if (m_gradient == grad)
+ return;
+
+ m_gradient = grad;
+ if (emitSignal)
+ emit q_ptr->gradientChanged(m_gradient);
+}
+
+void QtGradientEditorPrivate::setCombos(bool combos)
+{
+ if (m_combos == combos)
+ return;
+
+ m_combos = combos;
+ m_ui.linearButton->setVisible(!m_combos);
+ m_ui.radialButton->setVisible(!m_combos);
+ m_ui.conicalButton->setVisible(!m_combos);
+ m_ui.padButton->setVisible(!m_combos);
+ m_ui.repeatButton->setVisible(!m_combos);
+ m_ui.reflectButton->setVisible(!m_combos);
+ m_ui.typeComboBox->setVisible(m_combos);
+ m_ui.spreadComboBox->setVisible(m_combos);
+}
+
+void QtGradientEditorPrivate::setLayout(bool details)
+{
+ QHBoxLayout *hboxLayout = new QHBoxLayout();
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
+ hboxLayout->addWidget(m_ui.typeComboBox);
+ hboxLayout->addWidget(m_ui.spreadComboBox);
+ QHBoxLayout *typeLayout = new QHBoxLayout();
+ typeLayout->setSpacing(0);
+ typeLayout->addWidget(m_ui.linearButton);
+ typeLayout->addWidget(m_ui.radialButton);
+ typeLayout->addWidget(m_ui.conicalButton);
+ hboxLayout->addLayout(typeLayout);
+ QHBoxLayout *spreadLayout = new QHBoxLayout();
+ spreadLayout->setSpacing(0);
+ spreadLayout->addWidget(m_ui.padButton);
+ spreadLayout->addWidget(m_ui.repeatButton);
+ spreadLayout->addWidget(m_ui.reflectButton);
+ hboxLayout->addLayout(spreadLayout);
+ hboxLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum));
+ hboxLayout->addWidget(m_ui.detailsButton);
+ m_gridLayout->addLayout(hboxLayout, 0, 0, 1, 2);
+ int span = 1;
+ if (details)
+ span = 7;
+ m_gridLayout->addWidget(m_ui.frame, 1, 0, span, 2);
+ int row = 2;
+ if (details) {
+ row = 8;
+ span = 4;
+ }
+ m_gridLayout->addWidget(m_ui.gradientStopsWidget, row, 0, span, 2);
+ QHBoxLayout *hboxLayout1 = new QHBoxLayout();
+ hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
+ hboxLayout1->addWidget(m_ui.colorLabel);
+ hboxLayout1->addWidget(m_ui.colorButton);
+ hboxLayout1->addWidget(m_ui.hsvRadioButton);
+ hboxLayout1->addWidget(m_ui.rgbRadioButton);
+ hboxLayout1->addItem(new QSpacerItem(16, 23, QSizePolicy::Expanding, QSizePolicy::Minimum));
+ int addRow = 0;
+ if (details)
+ addRow = 9;
+ m_gridLayout->addLayout(hboxLayout1, 3 + addRow, 0, 1, 2);
+ m_gridLayout->addWidget(m_ui.hLabel, 4 + addRow, 0, 1, 1);
+ m_gridLayout->addWidget(m_ui.frame_2, 4 + addRow, 1, 1, 1);
+ m_gridLayout->addWidget(m_ui.sLabel, 5 + addRow, 0, 1, 1);
+ m_gridLayout->addWidget(m_ui.frame_5, 5 + addRow, 1, 1, 1);
+ m_gridLayout->addWidget(m_ui.vLabel, 6 + addRow, 0, 1, 1);
+ m_gridLayout->addWidget(m_ui.frame_3, 6 + addRow, 1, 1, 1);
+ m_gridLayout->addWidget(m_ui.aLabel, 7 + addRow, 0, 1, 1);
+ m_gridLayout->addWidget(m_ui.frame_4, 7 + addRow, 1, 1, 1);
+
+ if (details) {
+ layoutDetails(details);
+ }
+}
+
+void QtGradientEditorPrivate::layoutDetails(bool details)
+{
+ QGridLayout *gridLayout = m_gridLayout;
+ int col = 2;
+ if (!details) {
+ col = 0;
+ if (!m_hiddenWidget) {
+ m_hiddenWidget = new QWidget();
+ m_hiddenLayout = new QGridLayout(m_hiddenWidget);
+ m_hiddenLayout->setContentsMargins(0, 0, 0, 0);
+ m_hiddenLayout->setSizeConstraint(QLayout::SetFixedSize);
+ }
+ gridLayout = m_hiddenLayout;
+ }
+ gridLayout->addWidget(m_ui.label1, 1, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.spinBox1, 1, col + 1, 1, 1);
+ gridLayout->addWidget(m_ui.label2, 2, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.spinBox2, 2, col + 1, 1, 1);
+ gridLayout->addWidget(m_ui.label3, 3, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.spinBox3, 3, col + 1, 1, 1);
+ gridLayout->addWidget(m_ui.label4, 4, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.spinBox4, 4, col + 1, 1, 1);
+ gridLayout->addWidget(m_ui.label5, 5, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.spinBox5, 5, col + 1, 1, 1);
+ gridLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding), 6, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.line1Widget, 7, col + 0, 1, 2);
+ gridLayout->addWidget(m_ui.zoomLabel, 8, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.zoomWidget, 8, col + 1, 1, 1);
+ gridLayout->addWidget(m_ui.zoomButtonsWidget, 9, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.zoomAllButton, 9, col + 1, 1, 1);
+ gridLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Preferred), 10, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.line2Widget, 11, col + 0, 1, 2);
+ gridLayout->addWidget(m_ui.positionLabel, 12, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.positionWidget, 12, col + 1, 1, 1);
+ gridLayout->addWidget(m_ui.hueLabel, 13, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.hueWidget, 13, col + 1, 1, 1);
+ gridLayout->addWidget(m_ui.saturationLabel, 14, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.saturationWidget, 14, col + 1, 1, 1);
+ gridLayout->addWidget(m_ui.valueLabel, 15, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.valueWidget, 15, col + 1, 1, 1);
+ gridLayout->addWidget(m_ui.alphaLabel, 16, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.alphaWidget, 16, col + 1, 1, 1);
+
+ if (details) {
+ if (m_hiddenLayout) {
+ delete m_hiddenLayout;
+ m_hiddenLayout = 0;
+ }
+ if (m_hiddenWidget) {
+ delete m_hiddenWidget;
+ m_hiddenWidget = 0;
+ }
+ }
+}
+
+int QtGradientEditorPrivate::extensionWidthHint() const
+{
+ if (m_details)
+ return q_ptr->size().width() - m_ui.gradientStopsWidget->size().width();
+
+ const int space = m_ui.spinBox1->geometry().left() - m_ui.label1->geometry().right();
+
+ return m_hiddenLayout->minimumSize().width() + space;
+}
+
+void QtGradientEditorPrivate::slotDetailsChanged(bool details)
+{
+ showDetails(details);
+}
+
+bool QtGradientEditorPrivate::row4Visible() const
+{
+ if (m_type == QGradient::ConicalGradient)
+ return false;
+ return true;
+}
+
+bool QtGradientEditorPrivate::row5Visible() const
+{
+ if (m_type == QGradient::RadialGradient)
+ return true;
+ return false;
+}
+
+void QtGradientEditorPrivate::showDetails(bool details)
+{
+ if (m_details == details)
+ return;
+
+ bool blocked = m_ui.detailsButton->signalsBlocked();
+ m_ui.detailsButton->blockSignals(true);
+ m_ui.detailsButton->setChecked(details);
+ m_ui.detailsButton->blockSignals(blocked);
+
+ bool updates = q_ptr->updatesEnabled();
+ q_ptr->setUpdatesEnabled(false);
+
+ if (m_gridLayout) {
+ m_gridLayout->setEnabled(false);
+ delete m_gridLayout;
+ m_gridLayout = 0;
+ }
+
+ if (!details) {
+ layoutDetails(details);
+ }
+
+ emit q_ptr->aboutToShowDetails(details, extensionWidthHint());
+ m_details = details;
+
+ m_gridLayout = new QGridLayout(q_ptr);
+ m_gridLayout->setEnabled(false);
+ m_gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
+ m_gridLayout->setContentsMargins(0, 0, 0, 0);
+
+ m_ui.label4->setVisible(row4Visible());
+ m_ui.label5->setVisible(row5Visible());
+ m_ui.spinBox4->setVisible(row4Visible());
+ m_ui.spinBox5->setVisible(row5Visible());
+
+ setLayout(details);
+ m_gridLayout->setEnabled(true);
+
+ q_ptr->setUpdatesEnabled(updates);
+ q_ptr->update();
+}
+
+void QtGradientEditorPrivate::setSpinBox(QDoubleSpinBox *spinBox, const char *slot, double max, double step, int decimals)
+{
+ bool blocked = spinBox->signalsBlocked();
+ spinBox->blockSignals(true);
+ spinBox->setDecimals(decimals);
+ spinBox->setMaximum(max);
+ spinBox->setSingleStep(step);
+ spinBox->blockSignals(blocked);
+ QObject::connect(spinBox, SIGNAL(valueChanged(double)), q_ptr, slot);
+}
+
+void QtGradientEditorPrivate::reset()
+{
+ startLinearXSpinBox = 0;
+ startLinearYSpinBox = 0;
+ endLinearXSpinBox = 0;
+ endLinearYSpinBox = 0;
+ centralRadialXSpinBox = 0;
+ centralRadialYSpinBox = 0;
+ focalRadialXSpinBox = 0;
+ focalRadialYSpinBox = 0;
+ radiusRadialSpinBox = 0;
+ centralConicalXSpinBox = 0;
+ centralConicalYSpinBox = 0;
+ angleConicalSpinBox = 0;
+}
+
+void QtGradientEditorPrivate::setType(QGradient::Type type)
+{
+ if (m_type == type)
+ return;
+
+ m_type = type;
+ m_ui.spinBox1->disconnect(SIGNAL(valueChanged(double)));
+ m_ui.spinBox2->disconnect(SIGNAL(valueChanged(double)));
+ m_ui.spinBox3->disconnect(SIGNAL(valueChanged(double)));
+ m_ui.spinBox4->disconnect(SIGNAL(valueChanged(double)));
+ m_ui.spinBox5->disconnect(SIGNAL(valueChanged(double)));
+
+ reset();
+
+ bool ena = true;
+
+ if (m_gridLayout) {
+ ena = m_gridLayout->isEnabled();
+ m_gridLayout->setEnabled(false);
+ }
+
+ bool spreadEnabled = true;
+
+ if (type == QGradient::LinearGradient) {
+ startLinearXSpinBox = m_ui.spinBox1;
+ setSpinBox(startLinearXSpinBox, SLOT(slotStartLinearXChanged(double)));
+ m_ui.label1->setText(QApplication::translate("QtGradientEditor", "Start X", 0, QApplication::UnicodeUTF8));
+
+ startLinearYSpinBox = m_ui.spinBox2;
+ setSpinBox(startLinearYSpinBox, SLOT(slotStartLinearYChanged(double)));
+ m_ui.label2->setText(QApplication::translate("QtGradientEditor", "Start Y", 0, QApplication::UnicodeUTF8));
+
+ endLinearXSpinBox = m_ui.spinBox3;
+ setSpinBox(endLinearXSpinBox, SLOT(slotEndLinearXChanged(double)));
+ m_ui.label3->setText(QApplication::translate("QtGradientEditor", "Final X", 0, QApplication::UnicodeUTF8));
+
+ endLinearYSpinBox = m_ui.spinBox4;
+ setSpinBox(endLinearYSpinBox, SLOT(slotEndLinearYChanged(double)));
+ m_ui.label4->setText(QApplication::translate("QtGradientEditor", "Final Y", 0, QApplication::UnicodeUTF8));
+
+ setStartLinear(m_ui.gradientWidget->startLinear());
+ setEndLinear(m_ui.gradientWidget->endLinear());
+ } else if (type == QGradient::RadialGradient) {
+ centralRadialXSpinBox = m_ui.spinBox1;
+ setSpinBox(centralRadialXSpinBox, SLOT(slotCentralRadialXChanged(double)));
+ m_ui.label1->setText(QApplication::translate("QtGradientEditor", "Central X", 0, QApplication::UnicodeUTF8));
+
+ centralRadialYSpinBox = m_ui.spinBox2;
+ setSpinBox(centralRadialYSpinBox, SLOT(slotCentralRadialYChanged(double)));
+ m_ui.label2->setText(QApplication::translate("QtGradientEditor", "Central Y", 0, QApplication::UnicodeUTF8));
+
+ focalRadialXSpinBox = m_ui.spinBox3;
+ setSpinBox(focalRadialXSpinBox, SLOT(slotFocalRadialXChanged(double)));
+ m_ui.label3->setText(QApplication::translate("QtGradientEditor", "Focal X", 0, QApplication::UnicodeUTF8));
+
+ focalRadialYSpinBox = m_ui.spinBox4;
+ setSpinBox(focalRadialYSpinBox, SLOT(slotFocalRadialYChanged(double)));
+ m_ui.label4->setText(QApplication::translate("QtGradientEditor", "Focal Y", 0, QApplication::UnicodeUTF8));
+
+ radiusRadialSpinBox = m_ui.spinBox5;
+ setSpinBox(radiusRadialSpinBox, SLOT(slotRadiusRadialChanged(double)), 2.0);
+ m_ui.label5->setText(QApplication::translate("QtGradientEditor", "Radius", 0, QApplication::UnicodeUTF8));
+
+ setCentralRadial(m_ui.gradientWidget->centralRadial());
+ setFocalRadial(m_ui.gradientWidget->focalRadial());
+ setRadiusRadial(m_ui.gradientWidget->radiusRadial());
+ } else if (type == QGradient::ConicalGradient) {
+ centralConicalXSpinBox = m_ui.spinBox1;
+ setSpinBox(centralConicalXSpinBox, SLOT(slotCentralConicalXChanged(double)));
+ m_ui.label1->setText(QApplication::translate("QtGradientEditor", "Central X", 0, QApplication::UnicodeUTF8));
+
+ centralConicalYSpinBox = m_ui.spinBox2;
+ setSpinBox(centralConicalYSpinBox, SLOT(slotCentralConicalYChanged(double)));
+ m_ui.label2->setText(QApplication::translate("QtGradientEditor", "Central Y", 0, QApplication::UnicodeUTF8));
+
+ angleConicalSpinBox = m_ui.spinBox3;
+ setSpinBox(angleConicalSpinBox, SLOT(slotAngleConicalChanged(double)), 360.0, 1.0, 1);
+ m_ui.label3->setText(QApplication::translate("QtGradientEditor", "Angle", 0, QApplication::UnicodeUTF8));
+
+ setCentralConical(m_ui.gradientWidget->centralConical());
+ setAngleConical(m_ui.gradientWidget->angleConical());
+
+ spreadEnabled = false;
+ }
+ m_ui.spreadComboBox->setEnabled(spreadEnabled);
+ m_ui.padButton->setEnabled(spreadEnabled);
+ m_ui.repeatButton->setEnabled(spreadEnabled);
+ m_ui.reflectButton->setEnabled(spreadEnabled);
+
+ m_ui.label4->setVisible(row4Visible());
+ m_ui.spinBox4->setVisible(row4Visible());
+ m_ui.label5->setVisible(row5Visible());
+ m_ui.spinBox5->setVisible(row5Visible());
+
+ if (m_gridLayout) {
+ m_gridLayout->setEnabled(ena);
+ }
+}
+
+void QtGradientEditorPrivate::slotGradientStopsChanged(const QGradientStops &stops)
+{
+ m_ui.gradientWidget->setGradientStops(stops);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::slotTypeChanged(int idx)
+{
+ QGradient::Type type = QGradient::NoGradient;
+ if (idx == 0)
+ type = QGradient::LinearGradient;
+ else if (idx == 1)
+ type = QGradient::RadialGradient;
+ else if (idx == 2)
+ type = QGradient::ConicalGradient;
+ setType(type);
+ m_ui.typeComboBox->setCurrentIndex(idx);
+ m_typeGroup->button(idx)->setChecked(true);
+ m_ui.gradientWidget->setGradientType(type);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::slotSpreadChanged(int spread)
+{
+ if (spread == 0) {
+ m_ui.gradientWidget->setGradientSpread(QGradient::PadSpread);
+ } else if (spread == 1) {
+ m_ui.gradientWidget->setGradientSpread(QGradient::RepeatSpread);
+ } else if (spread == 2) {
+ m_ui.gradientWidget->setGradientSpread(QGradient::ReflectSpread);
+ }
+ m_ui.spreadComboBox->setCurrentIndex(spread);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::slotStartLinearXChanged(double value)
+{
+ QPointF point = m_ui.gradientWidget->startLinear();
+ point.setX(value);
+ m_ui.gradientWidget->setStartLinear(point);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::slotStartLinearYChanged(double value)
+{
+ QPointF point = m_ui.gradientWidget->startLinear();
+ point.setY(value);
+ m_ui.gradientWidget->setStartLinear(point);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::slotEndLinearXChanged(double value)
+{
+ QPointF point = m_ui.gradientWidget->endLinear();
+ point.setX(value);
+ m_ui.gradientWidget->setEndLinear(point);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::slotEndLinearYChanged(double value)
+{
+ QPointF point = m_ui.gradientWidget->endLinear();
+ point.setY(value);
+ m_ui.gradientWidget->setEndLinear(point);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::slotCentralRadialXChanged(double value)
+{
+ QPointF point = m_ui.gradientWidget->centralRadial();
+ point.setX(value);
+ m_ui.gradientWidget->setCentralRadial(point);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::slotCentralRadialYChanged(double value)
+{
+ QPointF point = m_ui.gradientWidget->centralRadial();
+ point.setY(value);
+ m_ui.gradientWidget->setCentralRadial(point);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::slotFocalRadialXChanged(double value)
+{
+ QPointF point = m_ui.gradientWidget->focalRadial();
+ point.setX(value);
+ m_ui.gradientWidget->setFocalRadial(point);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::slotFocalRadialYChanged(double value)
+{
+ QPointF point = m_ui.gradientWidget->focalRadial();
+ point.setY(value);
+ m_ui.gradientWidget->setFocalRadial(point);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::slotRadiusRadialChanged(double value)
+{
+ m_ui.gradientWidget->setRadiusRadial(value);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::slotCentralConicalXChanged(double value)
+{
+ QPointF point = m_ui.gradientWidget->centralConical();
+ point.setX(value);
+ m_ui.gradientWidget->setCentralConical(point);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::slotCentralConicalYChanged(double value)
+{
+ QPointF point = m_ui.gradientWidget->centralConical();
+ point.setY(value);
+ m_ui.gradientWidget->setCentralConical(point);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::slotAngleConicalChanged(double value)
+{
+ m_ui.gradientWidget->setAngleConical(value);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::startLinearChanged(const QPointF &point)
+{
+ setStartLinear(point);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::endLinearChanged(const QPointF &point)
+{
+ setEndLinear(point);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::centralRadialChanged(const QPointF &point)
+{
+ setCentralRadial(point);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::focalRadialChanged(const QPointF &point)
+{
+ setFocalRadial(point);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::radiusRadialChanged(qreal radius)
+{
+ setRadiusRadial(radius);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::centralConicalChanged(const QPointF &point)
+{
+ setCentralConical(point);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::angleConicalChanged(qreal angle)
+{
+ setAngleConical(angle);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::setStartLinear(const QPointF &point)
+{
+ if (startLinearXSpinBox)
+ startLinearXSpinBox->setValue(point.x());
+ if (startLinearYSpinBox)
+ startLinearYSpinBox->setValue(point.y());
+}
+
+void QtGradientEditorPrivate::setEndLinear(const QPointF &point)
+{
+ if (endLinearXSpinBox)
+ endLinearXSpinBox->setValue(point.x());
+ if (endLinearYSpinBox)
+ endLinearYSpinBox->setValue(point.y());
+}
+
+void QtGradientEditorPrivate::setCentralRadial(const QPointF &point)
+{
+ if (centralRadialXSpinBox)
+ centralRadialXSpinBox->setValue(point.x());
+ if (centralRadialYSpinBox)
+ centralRadialYSpinBox->setValue(point.y());
+}
+
+void QtGradientEditorPrivate::setFocalRadial(const QPointF &point)
+{
+ if (focalRadialXSpinBox)
+ focalRadialXSpinBox->setValue(point.x());
+ if (focalRadialYSpinBox)
+ focalRadialYSpinBox->setValue(point.y());
+}
+
+void QtGradientEditorPrivate::setRadiusRadial(qreal radius)
+{
+ if (radiusRadialSpinBox)
+ radiusRadialSpinBox->setValue(radius);
+}
+
+void QtGradientEditorPrivate::setCentralConical(const QPointF &point)
+{
+ if (centralConicalXSpinBox)
+ centralConicalXSpinBox->setValue(point.x());
+ if (centralConicalYSpinBox)
+ centralConicalYSpinBox->setValue(point.y());
+}
+
+void QtGradientEditorPrivate::setAngleConical(qreal angle)
+{
+ if (angleConicalSpinBox)
+ angleConicalSpinBox->setValue(angle);
+}
+
+QtGradientEditor::QtGradientEditor(QWidget *parent)
+ : QWidget(parent), d_ptr(new QtGradientEditorPrivate())
+{
+ d_ptr->q_ptr = this;
+ d_ptr->m_type = QGradient::RadialGradient;
+ d_ptr->m_ui.setupUi(this);
+ d_ptr->m_gridLayout = 0;
+ d_ptr->m_hiddenLayout = 0;
+ d_ptr->m_hiddenWidget = 0;
+ bool detailsDefault = false;
+ d_ptr->m_details = !detailsDefault;
+ d_ptr->m_detailsButtonVisible = true;
+ bool checkeredDefault = true;
+ d_ptr->m_backgroundCheckered = !checkeredDefault;
+ d_ptr->m_gradientStopsController = new QtGradientStopsController(this);
+ d_ptr->m_gradientStopsController->setUi(&d_ptr->m_ui);
+ d_ptr->reset();
+ d_ptr->setType(QGradient::LinearGradient);
+ d_ptr->m_combos = true;
+ d_ptr->setCombos(!d_ptr->m_combos);
+
+ d_ptr->showDetails(detailsDefault);
+ setBackgroundCheckered(checkeredDefault);
+
+ d_ptr->setStartLinear(QPointF(0, 0));
+ d_ptr->setEndLinear(QPointF(1, 1));
+ d_ptr->setCentralRadial(QPointF(0.5, 0.5));
+ d_ptr->setFocalRadial(QPointF(0.5, 0.5));
+ d_ptr->setRadiusRadial(0.5);
+ d_ptr->setCentralConical(QPointF(0.5, 0.5));
+ d_ptr->setAngleConical(0);
+
+ QIcon icon;
+ icon.addPixmap(style()->standardPixmap(QStyle::SP_ArrowRight), QIcon::Normal, QIcon::Off);
+ icon.addPixmap(style()->standardPixmap(QStyle::SP_ArrowLeft), QIcon::Normal, QIcon::On);
+ d_ptr->m_ui.detailsButton->setIcon(icon);
+
+ connect(d_ptr->m_ui.detailsButton, SIGNAL(clicked(bool)), this, SLOT(slotDetailsChanged(bool)));
+ connect(d_ptr->m_gradientStopsController, SIGNAL(gradientStopsChanged(QGradientStops)),
+ this, SLOT(slotGradientStopsChanged(QGradientStops)));
+
+ QIcon iconLinear(QLatin1String(":/trolltech/qtgradienteditor/images/typelinear.png"));
+ QIcon iconRadial(QLatin1String(":/trolltech/qtgradienteditor/images/typeradial.png"));
+ QIcon iconConical(QLatin1String(":/trolltech/qtgradienteditor/images/typeconical.png"));
+
+ d_ptr->m_ui.typeComboBox->addItem(iconLinear, tr("Linear"));
+ d_ptr->m_ui.typeComboBox->addItem(iconRadial, tr("Radial"));
+ d_ptr->m_ui.typeComboBox->addItem(iconConical, tr("Conical"));
+
+ d_ptr->m_ui.linearButton->setIcon(iconLinear);
+ d_ptr->m_ui.radialButton->setIcon(iconRadial);
+ d_ptr->m_ui.conicalButton->setIcon(iconConical);
+
+ d_ptr->m_typeGroup = new QButtonGroup(this);
+ d_ptr->m_typeGroup->addButton(d_ptr->m_ui.linearButton, 0);
+ d_ptr->m_typeGroup->addButton(d_ptr->m_ui.radialButton, 1);
+ d_ptr->m_typeGroup->addButton(d_ptr->m_ui.conicalButton, 2);
+
+ connect(d_ptr->m_typeGroup, SIGNAL(buttonClicked(int)),
+ this, SLOT(slotTypeChanged(int)));
+ connect(d_ptr->m_ui.typeComboBox, SIGNAL(activated(int)),
+ this, SLOT(slotTypeChanged(int)));
+
+ QIcon iconPad(QLatin1String(":/trolltech/qtgradienteditor/images/spreadpad.png"));
+ QIcon iconRepeat(QLatin1String(":/trolltech/qtgradienteditor/images/spreadrepeat.png"));
+ QIcon iconReflect(QLatin1String(":/trolltech/qtgradienteditor/images/spreadreflect.png"));
+
+ d_ptr->m_ui.spreadComboBox->addItem(iconPad, tr("Pad"));
+ d_ptr->m_ui.spreadComboBox->addItem(iconRepeat, tr("Repeat"));
+ d_ptr->m_ui.spreadComboBox->addItem(iconReflect, tr("Reflect"));
+
+ d_ptr->m_ui.padButton->setIcon(iconPad);
+ d_ptr->m_ui.repeatButton->setIcon(iconRepeat);
+ d_ptr->m_ui.reflectButton->setIcon(iconReflect);
+
+ d_ptr->m_spreadGroup = new QButtonGroup(this);
+ d_ptr->m_spreadGroup->addButton(d_ptr->m_ui.padButton, 0);
+ d_ptr->m_spreadGroup->addButton(d_ptr->m_ui.repeatButton, 1);
+ d_ptr->m_spreadGroup->addButton(d_ptr->m_ui.reflectButton, 2);
+ connect(d_ptr->m_spreadGroup, SIGNAL(buttonClicked(int)),
+ this, SLOT(slotSpreadChanged(int)));
+ connect(d_ptr->m_ui.spreadComboBox, SIGNAL(activated(int)),
+ this, SLOT(slotSpreadChanged(int)));
+
+ connect(d_ptr->m_ui.gradientWidget, SIGNAL(startLinearChanged(QPointF)),
+ this, SLOT(startLinearChanged(QPointF)));
+ connect(d_ptr->m_ui.gradientWidget, SIGNAL(endLinearChanged(QPointF)),
+ this, SLOT(endLinearChanged(QPointF)));
+ connect(d_ptr->m_ui.gradientWidget, SIGNAL(centralRadialChanged(QPointF)),
+ this, SLOT(centralRadialChanged(QPointF)));
+ connect(d_ptr->m_ui.gradientWidget, SIGNAL(focalRadialChanged(QPointF)),
+ this, SLOT(focalRadialChanged(QPointF)));
+ connect(d_ptr->m_ui.gradientWidget, SIGNAL(radiusRadialChanged(qreal)),
+ this, SLOT(radiusRadialChanged(qreal)));
+ connect(d_ptr->m_ui.gradientWidget, SIGNAL(centralConicalChanged(QPointF)),
+ this, SLOT(centralConicalChanged(QPointF)));
+ connect(d_ptr->m_ui.gradientWidget, SIGNAL(angleConicalChanged(qreal)),
+ this, SLOT(angleConicalChanged(qreal)));
+
+ QGradientStops stops = gradient().stops();
+ d_ptr->m_gradientStopsController->setGradientStops(stops);
+ d_ptr->m_ui.gradientWidget->setGradientStops(stops);
+}
+
+QtGradientEditor::~QtGradientEditor()
+{
+ if (d_ptr->m_hiddenWidget)
+ delete d_ptr->m_hiddenWidget;
+}
+
+void QtGradientEditor::setGradient(const QGradient &grad)
+{
+ if (grad == gradient())
+ return;
+
+ QGradient::Type type = grad.type();
+ int idx = 0;
+ switch (type) {
+ case QGradient::LinearGradient: idx = 0; break;
+ case QGradient::RadialGradient: idx = 1; break;
+ case QGradient::ConicalGradient: idx = 2; break;
+ default: return;
+ }
+ d_ptr->setType(type);
+ d_ptr->m_ui.typeComboBox->setCurrentIndex(idx);
+ d_ptr->m_ui.gradientWidget->setGradientType(type);
+ d_ptr->m_typeGroup->button(idx)->setChecked(true);
+
+ QGradient::Spread spread = grad.spread();
+ switch (spread) {
+ case QGradient::PadSpread: idx = 0; break;
+ case QGradient::RepeatSpread: idx = 1; break;
+ case QGradient::ReflectSpread: idx = 2; break;
+ default: idx = 0; break;
+ }
+ d_ptr->m_ui.spreadComboBox->setCurrentIndex(idx);
+ d_ptr->m_ui.gradientWidget->setGradientSpread(spread);
+ d_ptr->m_spreadGroup->button(idx)->setChecked(true);
+
+ if (type == QGradient::LinearGradient) {
+ QLinearGradient *gr = (QLinearGradient *)(&grad);
+ d_ptr->setStartLinear(gr->start());
+ d_ptr->setEndLinear(gr->finalStop());
+ d_ptr->m_ui.gradientWidget->setStartLinear(gr->start());
+ d_ptr->m_ui.gradientWidget->setEndLinear(gr->finalStop());
+ } else if (type == QGradient::RadialGradient) {
+ QRadialGradient *gr = (QRadialGradient *)(&grad);
+ d_ptr->setCentralRadial(gr->center());
+ d_ptr->setFocalRadial(gr->focalPoint());
+ d_ptr->setRadiusRadial(gr->radius());
+ d_ptr->m_ui.gradientWidget->setCentralRadial(gr->center());
+ d_ptr->m_ui.gradientWidget->setFocalRadial(gr->focalPoint());
+ d_ptr->m_ui.gradientWidget->setRadiusRadial(gr->radius());
+ } else if (type == QGradient::ConicalGradient) {
+ QConicalGradient *gr = (QConicalGradient *)(&grad);
+ d_ptr->setCentralConical(gr->center());
+ d_ptr->setAngleConical(gr->angle());
+ d_ptr->m_ui.gradientWidget->setCentralConical(gr->center());
+ d_ptr->m_ui.gradientWidget->setAngleConical(gr->angle());
+ }
+
+ d_ptr->m_gradientStopsController->setGradientStops(grad.stops());
+ d_ptr->m_ui.gradientWidget->setGradientStops(grad.stops());
+ d_ptr->updateGradient(false);
+}
+
+QGradient QtGradientEditor::gradient() const
+{
+ return d_ptr->m_gradient;
+}
+
+bool QtGradientEditor::isBackgroundCheckered() const
+{
+ return d_ptr->m_backgroundCheckered;
+}
+
+void QtGradientEditor::setBackgroundCheckered(bool checkered)
+{
+ if (d_ptr->m_backgroundCheckered == checkered)
+ return;
+
+ d_ptr->m_backgroundCheckered = checkered;
+ d_ptr->m_ui.hueColorLine->setBackgroundCheckered(checkered);
+ d_ptr->m_ui.saturationColorLine->setBackgroundCheckered(checkered);
+ d_ptr->m_ui.valueColorLine->setBackgroundCheckered(checkered);
+ d_ptr->m_ui.alphaColorLine->setBackgroundCheckered(checkered);
+ d_ptr->m_ui.gradientWidget->setBackgroundCheckered(checkered);
+ d_ptr->m_ui.gradientStopsWidget->setBackgroundCheckered(checkered);
+ d_ptr->m_ui.colorButton->setBackgroundCheckered(checkered);
+}
+
+bool QtGradientEditor::detailsVisible() const
+{
+ return d_ptr->m_details;
+}
+
+void QtGradientEditor::setDetailsVisible(bool visible)
+{
+ d_ptr->showDetails(visible);
+}
+
+bool QtGradientEditor::isDetailsButtonVisible() const
+{
+ return d_ptr->m_detailsButtonVisible;
+}
+
+void QtGradientEditor::setDetailsButtonVisible(bool visible)
+{
+ if (d_ptr->m_detailsButtonVisible == visible)
+ return;
+
+ d_ptr->m_detailsButtonVisible = visible;
+ d_ptr->m_ui.detailsButton->setVisible(visible);
+}
+
+QColor::Spec QtGradientEditor::spec() const
+{
+ return d_ptr->m_gradientStopsController->spec();
+}
+
+void QtGradientEditor::setSpec(QColor::Spec spec)
+{
+ d_ptr->m_gradientStopsController->setSpec(spec);
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qtgradienteditor.cpp"
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradienteditor.h b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradienteditor.h
new file mode 100644
index 0000000000..5aaba5d148
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradienteditor.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTGRADIENTEDITOR_H
+#define QTGRADIENTEDITOR_H
+
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class QtGradientEditor : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(QGradient gradient READ gradient WRITE setGradient)
+ Q_PROPERTY(bool backgroundCheckered READ isBackgroundCheckered WRITE setBackgroundCheckered)
+ Q_PROPERTY(bool detailsVisible READ detailsVisible WRITE setDetailsVisible)
+ Q_PROPERTY(bool detailsButtonVisible READ isDetailsButtonVisible WRITE setDetailsButtonVisible)
+public:
+ QtGradientEditor(QWidget *parent = 0);
+ ~QtGradientEditor();
+
+ void setGradient(const QGradient &gradient);
+ QGradient gradient() const;
+
+ bool isBackgroundCheckered() const;
+ void setBackgroundCheckered(bool checkered);
+
+ bool detailsVisible() const;
+ void setDetailsVisible(bool visible);
+
+ bool isDetailsButtonVisible() const;
+ void setDetailsButtonVisible(bool visible);
+
+ QColor::Spec spec() const;
+ void setSpec(QColor::Spec spec);
+
+signals:
+
+ void gradientChanged(const QGradient &gradient);
+ void aboutToShowDetails(bool details, int extenstionWidthHint);
+
+private:
+ QScopedPointer<class QtGradientEditorPrivate> d_ptr;
+ Q_DECLARE_PRIVATE(QtGradientEditor)
+ Q_DISABLE_COPY(QtGradientEditor)
+ Q_PRIVATE_SLOT(d_func(), void slotGradientStopsChanged(const QGradientStops &stops))
+ Q_PRIVATE_SLOT(d_func(), void slotTypeChanged(int type))
+ Q_PRIVATE_SLOT(d_func(), void slotSpreadChanged(int type))
+ Q_PRIVATE_SLOT(d_func(), void slotStartLinearXChanged(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotStartLinearYChanged(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotEndLinearXChanged(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotEndLinearYChanged(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotCentralRadialXChanged(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotCentralRadialYChanged(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotFocalRadialXChanged(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotFocalRadialYChanged(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotRadiusRadialChanged(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotCentralConicalXChanged(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotCentralConicalYChanged(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotAngleConicalChanged(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotDetailsChanged(bool details))
+ Q_PRIVATE_SLOT(d_func(), void startLinearChanged(const QPointF &))
+ Q_PRIVATE_SLOT(d_func(), void endLinearChanged(const QPointF &))
+ Q_PRIVATE_SLOT(d_func(), void centralRadialChanged(const QPointF &))
+ Q_PRIVATE_SLOT(d_func(), void focalRadialChanged(const QPointF &))
+ Q_PRIVATE_SLOT(d_func(), void radiusRadialChanged(qreal))
+ Q_PRIVATE_SLOT(d_func(), void centralConicalChanged(const QPointF &))
+ Q_PRIVATE_SLOT(d_func(), void angleConicalChanged(qreal))
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradienteditor.pri b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradienteditor.pri
new file mode 100644
index 0000000000..4cf059e1f2
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradienteditor.pri
@@ -0,0 +1,33 @@
+INCLUDEPATH += $$PWD
+DEPENDPATH += $$PWD
+FORMS += $$PWD/qtgradienteditor.ui \
+ $$PWD/qtgradientdialog.ui \
+ $$PWD/qtgradientview.ui \
+ $$PWD/qtgradientviewdialog.ui
+SOURCES += $$PWD/qtgradientstopsmodel.cpp \
+ $$PWD/qtgradientstopswidget.cpp \
+ $$PWD/qtgradientstopscontroller.cpp \
+ $$PWD/qtgradientwidget.cpp \
+ $$PWD/qtgradienteditor.cpp \
+ $$PWD/qtgradientdialog.cpp \
+ $$PWD/qtcolorbutton.cpp \
+ $$PWD/qtcolorline.cpp \
+ $$PWD/qtgradientview.cpp \
+ $$PWD/qtgradientviewdialog.cpp \
+ $$PWD/qtgradientmanager.cpp \
+ $$PWD/qtgradientutils.cpp
+HEADERS += $$PWD/qtgradientstopsmodel.h \
+ $$PWD/qtgradientstopswidget.h \
+ $$PWD/qtgradientstopscontroller.h \
+ $$PWD/qtgradientwidget.h \
+ $$PWD/qtgradienteditor.h \
+ $$PWD/qtgradientdialog.h \
+ $$PWD/qtcolorbutton.h \
+ $$PWD/qtcolorline.h \
+ $$PWD/qtgradientview.h \
+ $$PWD/qtgradientviewdialog.h \
+ $$PWD/qtgradientmanager.h \
+ $$PWD/qtgradientutils.h
+RESOURCES += $$PWD/qtgradienteditor.qrc
+
+QT += xml
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradienteditor.qrc b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradienteditor.qrc
new file mode 100644
index 0000000000..cce7ba6224
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradienteditor.qrc
@@ -0,0 +1,18 @@
+<!DOCTYPE RCC><RCC version="1.0">
+ <qresource prefix="/trolltech/qtgradienteditor">
+ <file>images/edit.png</file>
+ <file>images/zoomin.png</file>
+ <file>images/zoomout.png</file>
+ <file>images/up.png</file>
+ <file>images/down.png</file>
+ <file>images/plus.png</file>
+ <file>images/minus.png</file>
+ <file>images/editdelete.png</file>
+ <file>images/spreadpad.png</file>
+ <file>images/spreadrepeat.png</file>
+ <file>images/spreadreflect.png</file>
+ <file>images/typelinear.png</file>
+ <file>images/typeradial.png</file>
+ <file>images/typeconical.png</file>
+ </qresource>
+</RCC>
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradienteditor.ui b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradienteditor.ui
new file mode 100644
index 0000000000..60d6fb6f22
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradienteditor.ui
@@ -0,0 +1,1377 @@
+<ui version="4.0" >
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <class>QtGradientEditor</class>
+ <widget class="QWidget" name="QtGradientEditor" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>364</width>
+ <height>518</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Form</string>
+ </property>
+ <widget class="QFrame" name="frame" >
+ <property name="geometry" >
+ <rect>
+ <x>10</x>
+ <y>69</y>
+ <width>193</width>
+ <height>150</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape" >
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QtGradientWidget" native="1" name="gradientWidget" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip" >
+ <string>Gradient Editor</string>
+ </property>
+ <property name="whatsThis" >
+ <string>This area shows a preview of the gradient being edited. It also allows you to edit parameters specific to the gradient's type such as start and final point, radius, etc. by drag &amp; drop.</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QLabel" name="label1" >
+ <property name="geometry" >
+ <rect>
+ <x>209</x>
+ <y>69</y>
+ <width>64</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="text" >
+ <string>1</string>
+ </property>
+ </widget>
+ <widget class="QDoubleSpinBox" name="spinBox1" >
+ <property name="geometry" >
+ <rect>
+ <x>279</x>
+ <y>69</y>
+ <width>73</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="keyboardTracking" >
+ <bool>false</bool>
+ </property>
+ <property name="decimals" >
+ <number>3</number>
+ </property>
+ <property name="maximum" >
+ <double>1.000000000000000</double>
+ </property>
+ <property name="singleStep" >
+ <double>0.010000000000000</double>
+ </property>
+ </widget>
+ <widget class="QLabel" name="label2" >
+ <property name="geometry" >
+ <rect>
+ <x>209</x>
+ <y>99</y>
+ <width>64</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="text" >
+ <string>2</string>
+ </property>
+ </widget>
+ <widget class="QDoubleSpinBox" name="spinBox2" >
+ <property name="geometry" >
+ <rect>
+ <x>279</x>
+ <y>99</y>
+ <width>73</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="keyboardTracking" >
+ <bool>false</bool>
+ </property>
+ <property name="decimals" >
+ <number>3</number>
+ </property>
+ <property name="maximum" >
+ <double>1.000000000000000</double>
+ </property>
+ <property name="singleStep" >
+ <double>0.010000000000000</double>
+ </property>
+ </widget>
+ <widget class="QLabel" name="label3" >
+ <property name="geometry" >
+ <rect>
+ <x>209</x>
+ <y>129</y>
+ <width>64</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="text" >
+ <string>3</string>
+ </property>
+ </widget>
+ <widget class="QDoubleSpinBox" name="spinBox3" >
+ <property name="geometry" >
+ <rect>
+ <x>279</x>
+ <y>129</y>
+ <width>73</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="keyboardTracking" >
+ <bool>false</bool>
+ </property>
+ <property name="decimals" >
+ <number>3</number>
+ </property>
+ <property name="maximum" >
+ <double>1.000000000000000</double>
+ </property>
+ <property name="singleStep" >
+ <double>0.010000000000000</double>
+ </property>
+ </widget>
+ <widget class="QLabel" name="label4" >
+ <property name="geometry" >
+ <rect>
+ <x>209</x>
+ <y>159</y>
+ <width>64</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="text" >
+ <string>4</string>
+ </property>
+ </widget>
+ <widget class="QDoubleSpinBox" name="spinBox4" >
+ <property name="geometry" >
+ <rect>
+ <x>279</x>
+ <y>159</y>
+ <width>73</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="keyboardTracking" >
+ <bool>false</bool>
+ </property>
+ <property name="decimals" >
+ <number>3</number>
+ </property>
+ <property name="maximum" >
+ <double>1.000000000000000</double>
+ </property>
+ <property name="singleStep" >
+ <double>0.010000000000000</double>
+ </property>
+ </widget>
+ <widget class="QLabel" name="label5" >
+ <property name="geometry" >
+ <rect>
+ <x>209</x>
+ <y>189</y>
+ <width>64</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="text" >
+ <string>5</string>
+ </property>
+ </widget>
+ <widget class="QDoubleSpinBox" name="spinBox5" >
+ <property name="geometry" >
+ <rect>
+ <x>279</x>
+ <y>189</y>
+ <width>73</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="keyboardTracking" >
+ <bool>false</bool>
+ </property>
+ <property name="decimals" >
+ <number>3</number>
+ </property>
+ <property name="maximum" >
+ <double>1.000000000000000</double>
+ </property>
+ <property name="singleStep" >
+ <double>0.010000000000000</double>
+ </property>
+ </widget>
+ <widget class="QtGradientStopsWidget" native="1" name="gradientStopsWidget" >
+ <property name="geometry" >
+ <rect>
+ <x>10</x>
+ <y>225</y>
+ <width>193</width>
+ <height>67</height>
+ </rect>
+ </property>
+ <property name="toolTip" >
+ <string>Gradient Stops Editor</string>
+ </property>
+ <property name="whatsThis" >
+ <string>This area allows you to edit gradient stops. Double click on the existing stop handle to duplicate it. Double click outside of the existing stop handles to create a new stop. Drag &amp; drop the handle to reposition it. Use right mouse button to popup context menu with extra actions.</string>
+ </property>
+ </widget>
+ <widget class="QLabel" name="zoomLabel" >
+ <property name="geometry" >
+ <rect>
+ <x>209</x>
+ <y>231</y>
+ <width>64</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="text" >
+ <string>Zoom</string>
+ </property>
+ </widget>
+ <widget class="QToolButton" name="zoomAllButton" >
+ <property name="geometry" >
+ <rect>
+ <x>279</x>
+ <y>260</y>
+ <width>72</width>
+ <height>26</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip" >
+ <string>Reset Zoom</string>
+ </property>
+ <property name="text" >
+ <string>Reset Zoom</string>
+ </property>
+ </widget>
+ <widget class="QLabel" name="positionLabel" >
+ <property name="geometry" >
+ <rect>
+ <x>209</x>
+ <y>304</y>
+ <width>64</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="text" >
+ <string>Position</string>
+ </property>
+ </widget>
+ <widget class="QLabel" name="hLabel" >
+ <property name="geometry" >
+ <rect>
+ <x>10</x>
+ <y>335</y>
+ <width>32</width>
+ <height>18</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip" >
+ <string>Hue</string>
+ </property>
+ <property name="text" >
+ <string>H</string>
+ </property>
+ </widget>
+ <widget class="QFrame" name="frame_2" >
+ <property name="geometry" >
+ <rect>
+ <x>48</x>
+ <y>333</y>
+ <width>155</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Ignored" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape" >
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QHBoxLayout" >
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QtColorLine" native="1" name="hueColorLine" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Expanding" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip" >
+ <string>Hue</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QLabel" name="hueLabel" >
+ <property name="geometry" >
+ <rect>
+ <x>209</x>
+ <y>335</y>
+ <width>64</width>
+ <height>18</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Hue</string>
+ </property>
+ </widget>
+ <widget class="QLabel" name="sLabel" >
+ <property name="geometry" >
+ <rect>
+ <x>10</x>
+ <y>364</y>
+ <width>32</width>
+ <height>18</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip" >
+ <string>Saturation</string>
+ </property>
+ <property name="text" >
+ <string>S</string>
+ </property>
+ </widget>
+ <widget class="QFrame" name="frame_5" >
+ <property name="geometry" >
+ <rect>
+ <x>48</x>
+ <y>362</y>
+ <width>155</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Ignored" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape" >
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QHBoxLayout" >
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QtColorLine" native="1" name="saturationColorLine" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Expanding" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip" >
+ <string>Saturation</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QLabel" name="saturationLabel" >
+ <property name="geometry" >
+ <rect>
+ <x>209</x>
+ <y>364</y>
+ <width>64</width>
+ <height>18</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Sat</string>
+ </property>
+ </widget>
+ <widget class="QLabel" name="vLabel" >
+ <property name="geometry" >
+ <rect>
+ <x>10</x>
+ <y>393</y>
+ <width>32</width>
+ <height>18</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip" >
+ <string>Value</string>
+ </property>
+ <property name="text" >
+ <string>V</string>
+ </property>
+ </widget>
+ <widget class="QFrame" name="frame_3" >
+ <property name="geometry" >
+ <rect>
+ <x>48</x>
+ <y>391</y>
+ <width>155</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Ignored" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape" >
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QHBoxLayout" >
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QtColorLine" native="1" name="valueColorLine" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Expanding" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip" >
+ <string>Value</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QLabel" name="valueLabel" >
+ <property name="geometry" >
+ <rect>
+ <x>209</x>
+ <y>393</y>
+ <width>64</width>
+ <height>18</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Val</string>
+ </property>
+ </widget>
+ <widget class="QLabel" name="aLabel" >
+ <property name="geometry" >
+ <rect>
+ <x>10</x>
+ <y>422</y>
+ <width>32</width>
+ <height>18</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip" >
+ <string>Alpha</string>
+ </property>
+ <property name="text" >
+ <string>A</string>
+ </property>
+ </widget>
+ <widget class="QFrame" name="frame_4" >
+ <property name="geometry" >
+ <rect>
+ <x>48</x>
+ <y>420</y>
+ <width>155</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Ignored" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape" >
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QHBoxLayout" >
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QtColorLine" native="1" name="alphaColorLine" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Expanding" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip" >
+ <string>Alpha</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QLabel" name="alphaLabel" >
+ <property name="geometry" >
+ <rect>
+ <x>209</x>
+ <y>422</y>
+ <width>64</width>
+ <height>18</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Alpha</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" name="typeComboBox" >
+ <property name="geometry" >
+ <rect>
+ <x>10</x>
+ <y>40</y>
+ <width>79</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="toolTip" >
+ <string>Type</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" name="spreadComboBox" >
+ <property name="geometry" >
+ <rect>
+ <x>96</x>
+ <y>40</y>
+ <width>72</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="toolTip" >
+ <string>Spread</string>
+ </property>
+ </widget>
+ <widget class="QLabel" name="colorLabel" >
+ <property name="geometry" >
+ <rect>
+ <x>10</x>
+ <y>298</y>
+ <width>32</width>
+ <height>29</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Fixed" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Color</string>
+ </property>
+ </widget>
+ <widget class="QtColorButton" name="colorButton" >
+ <property name="geometry" >
+ <rect>
+ <x>48</x>
+ <y>300</y>
+ <width>26</width>
+ <height>25</height>
+ </rect>
+ </property>
+ <property name="toolTip" >
+ <string>Current stop's color</string>
+ </property>
+ <property name="text" >
+ <string/>
+ </property>
+ </widget>
+ <widget class="QRadioButton" name="hsvRadioButton" >
+ <property name="geometry" >
+ <rect>
+ <x>80</x>
+ <y>301</y>
+ <width>49</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip" >
+ <string>Show HSV specification</string>
+ </property>
+ <property name="text" >
+ <string>HSV</string>
+ </property>
+ <property name="checked" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QRadioButton" name="rgbRadioButton" >
+ <property name="geometry" >
+ <rect>
+ <x>135</x>
+ <y>301</y>
+ <width>49</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip" >
+ <string>Show RGB specification</string>
+ </property>
+ <property name="text" >
+ <string>RGB</string>
+ </property>
+ </widget>
+ <widget class="QWidget" native="1" name="positionWidget" >
+ <property name="geometry" >
+ <rect>
+ <x>279</x>
+ <y>304</y>
+ <width>73</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QDoubleSpinBox" name="positionSpinBox" >
+ <property name="toolTip" >
+ <string>Current stop's position</string>
+ </property>
+ <property name="keyboardTracking" >
+ <bool>false</bool>
+ </property>
+ <property name="decimals" >
+ <number>3</number>
+ </property>
+ <property name="minimum" >
+ <double>0.000000000000000</double>
+ </property>
+ <property name="maximum" >
+ <double>1.000000000000000</double>
+ </property>
+ <property name="singleStep" >
+ <double>0.010000000000000</double>
+ </property>
+ <property name="value" >
+ <double>0.000000000000000</double>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" native="1" name="hueWidget" >
+ <property name="geometry" >
+ <rect>
+ <x>279</x>
+ <y>333</y>
+ <width>73</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QSpinBox" name="hueSpinBox" >
+ <property name="keyboardTracking" >
+ <bool>false</bool>
+ </property>
+ <property name="maximum" >
+ <number>359</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" native="1" name="saturationWidget" >
+ <property name="geometry" >
+ <rect>
+ <x>279</x>
+ <y>362</y>
+ <width>73</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QSpinBox" name="saturationSpinBox" >
+ <property name="keyboardTracking" >
+ <bool>false</bool>
+ </property>
+ <property name="maximum" >
+ <number>255</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" native="1" name="valueWidget" >
+ <property name="geometry" >
+ <rect>
+ <x>279</x>
+ <y>391</y>
+ <width>73</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QSpinBox" name="valueSpinBox" >
+ <property name="keyboardTracking" >
+ <bool>false</bool>
+ </property>
+ <property name="maximum" >
+ <number>255</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" native="1" name="alphaWidget" >
+ <property name="geometry" >
+ <rect>
+ <x>279</x>
+ <y>420</y>
+ <width>73</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QSpinBox" name="alphaSpinBox" >
+ <property name="keyboardTracking" >
+ <bool>false</bool>
+ </property>
+ <property name="maximum" >
+ <number>255</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" native="1" name="zoomWidget" >
+ <property name="geometry" >
+ <rect>
+ <x>279</x>
+ <y>231</y>
+ <width>73</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QSpinBox" name="zoomSpinBox" >
+ <property name="keyboardTracking" >
+ <bool>false</bool>
+ </property>
+ <property name="suffix" >
+ <string>%</string>
+ </property>
+ <property name="minimum" >
+ <number>100</number>
+ </property>
+ <property name="maximum" >
+ <number>10000</number>
+ </property>
+ <property name="singleStep" >
+ <number>100</number>
+ </property>
+ <property name="value" >
+ <number>100</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" native="1" name="line1Widget" >
+ <property name="geometry" >
+ <rect>
+ <x>209</x>
+ <y>219</y>
+ <width>143</width>
+ <height>16</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="Line" name="line1" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" native="1" name="line2Widget" >
+ <property name="geometry" >
+ <rect>
+ <x>209</x>
+ <y>292</y>
+ <width>143</width>
+ <height>16</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="Line" name="line2" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" native="1" name="zoomButtonsWidget" >
+ <property name="geometry" >
+ <rect>
+ <x>209</x>
+ <y>260</y>
+ <width>64</width>
+ <height>26</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Maximum" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <layout class="QHBoxLayout" >
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QToolButton" name="zoomInButton" >
+ <property name="toolTip" >
+ <string>Zoom In</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="zoomOutButton" >
+ <property name="toolTip" >
+ <string>Zoom Out</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QToolButton" name="detailsButton" >
+ <property name="geometry" >
+ <rect>
+ <x>176</x>
+ <y>40</y>
+ <width>25</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Ignored" hsizetype="Fixed" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip" >
+ <string>Toggle details extension</string>
+ </property>
+ <property name="text" >
+ <string>></string>
+ </property>
+ <property name="checkable" >
+ <bool>true</bool>
+ </property>
+ <property name="autoRaise" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QToolButton" name="linearButton" >
+ <property name="geometry" >
+ <rect>
+ <x>10</x>
+ <y>10</y>
+ <width>30</width>
+ <height>26</height>
+ </rect>
+ </property>
+ <property name="toolTip" >
+ <string>Linear Type</string>
+ </property>
+ <property name="text" >
+ <string>...</string>
+ </property>
+ <property name="checkable" >
+ <bool>true</bool>
+ </property>
+ <property name="autoRaise" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QToolButton" name="radialButton" >
+ <property name="geometry" >
+ <rect>
+ <x>40</x>
+ <y>10</y>
+ <width>30</width>
+ <height>26</height>
+ </rect>
+ </property>
+ <property name="toolTip" >
+ <string>Radial Type</string>
+ </property>
+ <property name="text" >
+ <string>...</string>
+ </property>
+ <property name="checkable" >
+ <bool>true</bool>
+ </property>
+ <property name="autoRaise" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QToolButton" name="conicalButton" >
+ <property name="geometry" >
+ <rect>
+ <x>70</x>
+ <y>10</y>
+ <width>30</width>
+ <height>26</height>
+ </rect>
+ </property>
+ <property name="toolTip" >
+ <string>Conical Type</string>
+ </property>
+ <property name="text" >
+ <string>...</string>
+ </property>
+ <property name="checkable" >
+ <bool>true</bool>
+ </property>
+ <property name="autoRaise" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QToolButton" name="padButton" >
+ <property name="geometry" >
+ <rect>
+ <x>110</x>
+ <y>10</y>
+ <width>30</width>
+ <height>26</height>
+ </rect>
+ </property>
+ <property name="toolTip" >
+ <string>Pad Spread</string>
+ </property>
+ <property name="text" >
+ <string>...</string>
+ </property>
+ <property name="checkable" >
+ <bool>true</bool>
+ </property>
+ <property name="autoRaise" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QToolButton" name="repeatButton" >
+ <property name="geometry" >
+ <rect>
+ <x>140</x>
+ <y>10</y>
+ <width>30</width>
+ <height>26</height>
+ </rect>
+ </property>
+ <property name="toolTip" >
+ <string>Repeat Spread</string>
+ </property>
+ <property name="text" >
+ <string>...</string>
+ </property>
+ <property name="checkable" >
+ <bool>true</bool>
+ </property>
+ <property name="autoRaise" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QToolButton" name="reflectButton" >
+ <property name="geometry" >
+ <rect>
+ <x>170</x>
+ <y>10</y>
+ <width>30</width>
+ <height>26</height>
+ </rect>
+ </property>
+ <property name="toolTip" >
+ <string>Reflect Spread</string>
+ </property>
+ <property name="text" >
+ <string>...</string>
+ </property>
+ <property name="checkable" >
+ <bool>true</bool>
+ </property>
+ <property name="autoRaise" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>QtColorButton</class>
+ <extends>QToolButton</extends>
+ <header>qtcolorbutton.h</header>
+ </customwidget>
+ <customwidget>
+ <class>QtColorLine</class>
+ <extends>QWidget</extends>
+ <header>qtcolorline.h</header>
+ <container>1</container>
+ </customwidget>
+ <customwidget>
+ <class>QtGradientStopsWidget</class>
+ <extends>QWidget</extends>
+ <header>qtgradientstopswidget.h</header>
+ <container>1</container>
+ </customwidget>
+ <customwidget>
+ <class>QtGradientWidget</class>
+ <extends>QWidget</extends>
+ <header>qtgradientwidget.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <tabstops>
+ <tabstop>typeComboBox</tabstop>
+ <tabstop>spreadComboBox</tabstop>
+ <tabstop>detailsButton</tabstop>
+ <tabstop>spinBox1</tabstop>
+ <tabstop>spinBox2</tabstop>
+ <tabstop>spinBox3</tabstop>
+ <tabstop>spinBox4</tabstop>
+ <tabstop>spinBox5</tabstop>
+ <tabstop>zoomSpinBox</tabstop>
+ <tabstop>zoomInButton</tabstop>
+ <tabstop>zoomOutButton</tabstop>
+ <tabstop>zoomAllButton</tabstop>
+ <tabstop>colorButton</tabstop>
+ <tabstop>hsvRadioButton</tabstop>
+ <tabstop>rgbRadioButton</tabstop>
+ <tabstop>positionSpinBox</tabstop>
+ <tabstop>hueSpinBox</tabstop>
+ <tabstop>saturationSpinBox</tabstop>
+ <tabstop>valueSpinBox</tabstop>
+ <tabstop>alphaSpinBox</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientmanager.cpp b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientmanager.cpp
new file mode 100644
index 0000000000..10c10c7391
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientmanager.cpp
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtgradientmanager.h"
+#include <QtGui/QPixmap>
+#include <QtCore/QMetaEnum>
+
+QT_BEGIN_NAMESPACE
+
+QtGradientManager::QtGradientManager(QObject *parent)
+ : QObject(parent)
+{
+}
+
+QMap<QString, QGradient> QtGradientManager::gradients() const
+{
+ return m_idToGradient;
+}
+
+QString QtGradientManager::uniqueId(const QString &id) const
+{
+ if (!m_idToGradient.contains(id))
+ return id;
+
+ QString base = id;
+ while (base.count() > 0 && base.at(base.count() - 1).isDigit())
+ base = base.left(base.count() - 1);
+ QString newId = base;
+ int counter = 0;
+ while (m_idToGradient.contains(newId)) {
+ ++counter;
+ newId = base + QString::number(counter);
+ }
+ return newId;
+}
+
+QString QtGradientManager::addGradient(const QString &id, const QGradient &gradient)
+{
+ QString newId = uniqueId(id);
+
+ m_idToGradient[newId] = gradient;
+
+ emit gradientAdded(newId, gradient);
+
+ return newId;
+}
+
+void QtGradientManager::removeGradient(const QString &id)
+{
+ if (!m_idToGradient.contains(id))
+ return;
+
+ emit gradientRemoved(id);
+
+ m_idToGradient.remove(id);
+}
+
+void QtGradientManager::renameGradient(const QString &id, const QString &newId)
+{
+ if (!m_idToGradient.contains(id))
+ return;
+
+ if (newId == id)
+ return;
+
+ QString changedId = uniqueId(newId);
+ QGradient gradient = m_idToGradient.value(id);
+
+ emit gradientRenamed(id, changedId);
+
+ m_idToGradient.remove(id);
+ m_idToGradient[changedId] = gradient;
+}
+
+void QtGradientManager::changeGradient(const QString &id, const QGradient &newGradient)
+{
+ if (!m_idToGradient.contains(id))
+ return;
+
+ if (m_idToGradient.value(id) == newGradient)
+ return;
+
+ emit gradientChanged(id, newGradient);
+
+ m_idToGradient[id] = newGradient;
+}
+
+void QtGradientManager::clear()
+{
+ QMap<QString, QGradient> grads = gradients();
+ QMapIterator<QString, QGradient> itGrad(grads);
+ while (itGrad.hasNext()) {
+ removeGradient(itGrad.next().key());
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientmanager.h b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientmanager.h
new file mode 100644
index 0000000000..b14e732278
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientmanager.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GRADIENTMANAGER_H
+#define GRADIENTMANAGER_H
+
+#include <QtCore/QObject>
+#include <QtCore/QMap>
+#include <QtCore/QSize>
+#include <QtXml/QDomDocument>
+#include <QtXml/QDomElement>
+#include <QtGui/QGradient>
+
+QT_BEGIN_NAMESPACE
+
+class QGradient;
+class QPixmap;
+class QColor;
+
+class QtGradientManager : public QObject
+{
+ Q_OBJECT
+public:
+ QtGradientManager(QObject *parent = 0);
+
+ QMap<QString, QGradient> gradients() const;
+
+ QString uniqueId(const QString &id) const;
+
+public slots:
+
+ QString addGradient(const QString &id, const QGradient &gradient);
+ void renameGradient(const QString &id, const QString &newId);
+ void changeGradient(const QString &id, const QGradient &newGradient);
+ void removeGradient(const QString &id);
+
+ //utils
+ void clear();
+
+signals:
+
+ void gradientAdded(const QString &id, const QGradient &gradient);
+ void gradientRenamed(const QString &id, const QString &newId);
+ void gradientChanged(const QString &id, const QGradient &newGradient);
+ void gradientRemoved(const QString &id);
+
+private:
+
+ QMap<QString, QGradient> m_idToGradient;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientstopscontroller.cpp b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientstopscontroller.cpp
new file mode 100644
index 0000000000..b2765b5a57
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientstopscontroller.cpp
@@ -0,0 +1,724 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtgradientstopscontroller.h"
+#include "ui_qtgradienteditor.h"
+#include "qtgradientstopsmodel.h"
+
+#include <QtCore/QTimer>
+
+QT_BEGIN_NAMESPACE
+
+class QtGradientStopsControllerPrivate
+{
+ QtGradientStopsController *q_ptr;
+ Q_DECLARE_PUBLIC(QtGradientStopsController)
+public:
+ typedef QMap<qreal, QColor> PositionColorMap;
+ typedef QMap<qreal, QtGradientStop *> PositionStopMap;
+
+ void slotHsvClicked();
+ void slotRgbClicked();
+
+ void slotCurrentStopChanged(QtGradientStop *stop);
+ void slotStopMoved(QtGradientStop *stop, qreal newPos);
+ void slotStopsSwapped(QtGradientStop *stop1, QtGradientStop *stop2);
+ void slotStopChanged(QtGradientStop *stop, const QColor &newColor);
+ void slotStopSelected(QtGradientStop *stop, bool selected);
+ void slotStopAdded(QtGradientStop *stop);
+ void slotStopRemoved(QtGradientStop *stop);
+ void slotUpdatePositionSpinBox();
+
+ void slotChangeColor(const QColor &color);
+ void slotChangeHue(const QColor &color);
+ void slotChangeSaturation(const QColor &color);
+ void slotChangeValue(const QColor &color);
+ void slotChangeAlpha(const QColor &color);
+ void slotChangeHue(int color);
+ void slotChangeSaturation(int color);
+ void slotChangeValue(int color);
+ void slotChangeAlpha(int color);
+ void slotChangePosition(double value);
+
+ void slotChangeZoom(int value);
+ void slotZoomIn();
+ void slotZoomOut();
+ void slotZoomAll();
+ void slotZoomChanged(double zoom);
+
+ void enableCurrent(bool enable);
+ void setColorSpinBoxes(const QColor &color);
+ PositionColorMap stopsData(const PositionStopMap &stops) const;
+ QGradientStops makeGradientStops(const PositionColorMap &data) const;
+ void updateZoom(double zoom);
+
+ QtGradientStopsModel *m_model;
+ QColor::Spec m_spec;
+
+ Ui::QtGradientEditor *m_ui;
+};
+
+void QtGradientStopsControllerPrivate::enableCurrent(bool enable)
+{
+ m_ui->positionLabel->setEnabled(enable);
+ m_ui->colorLabel->setEnabled(enable);
+ m_ui->hLabel->setEnabled(enable);
+ m_ui->sLabel->setEnabled(enable);
+ m_ui->vLabel->setEnabled(enable);
+ m_ui->aLabel->setEnabled(enable);
+ m_ui->hueLabel->setEnabled(enable);
+ m_ui->saturationLabel->setEnabled(enable);
+ m_ui->valueLabel->setEnabled(enable);
+ m_ui->alphaLabel->setEnabled(enable);
+
+ m_ui->positionSpinBox->setEnabled(enable);
+ m_ui->colorButton->setEnabled(enable);
+
+ m_ui->hueColorLine->setEnabled(enable);
+ m_ui->saturationColorLine->setEnabled(enable);
+ m_ui->valueColorLine->setEnabled(enable);
+ m_ui->alphaColorLine->setEnabled(enable);
+
+ m_ui->hueSpinBox->setEnabled(enable);
+ m_ui->saturationSpinBox->setEnabled(enable);
+ m_ui->valueSpinBox->setEnabled(enable);
+ m_ui->alphaSpinBox->setEnabled(enable);
+}
+
+QtGradientStopsControllerPrivate::PositionColorMap QtGradientStopsControllerPrivate::stopsData(const PositionStopMap &stops) const
+{
+ PositionColorMap data;
+ PositionStopMap::ConstIterator itStop = stops.constBegin();
+ while (itStop != stops.constEnd()) {
+ QtGradientStop *stop = itStop.value();
+ data[stop->position()] = stop->color();
+
+ ++itStop;
+ }
+ return data;
+}
+
+QGradientStops QtGradientStopsControllerPrivate::makeGradientStops(const PositionColorMap &data) const
+{
+ QGradientStops stops;
+ PositionColorMap::ConstIterator itData = data.constBegin();
+ while (itData != data.constEnd()) {
+ stops << QPair<qreal, QColor>(itData.key(), itData.value());
+
+ ++itData;
+ }
+ return stops;
+}
+
+void QtGradientStopsControllerPrivate::updateZoom(double zoom)
+{
+ m_ui->gradientStopsWidget->setZoom(zoom);
+ m_ui->zoomSpinBox->blockSignals(true);
+ m_ui->zoomSpinBox->setValue(qRound(zoom * 100));
+ m_ui->zoomSpinBox->blockSignals(false);
+ bool zoomInEnabled = true;
+ bool zoomOutEnabled = true;
+ bool zoomAllEnabled = true;
+ if (zoom <= 1) {
+ zoomAllEnabled = false;
+ zoomOutEnabled = false;
+ } else if (zoom >= 100) {
+ zoomInEnabled = false;
+ }
+ m_ui->zoomInButton->setEnabled(zoomInEnabled);
+ m_ui->zoomOutButton->setEnabled(zoomOutEnabled);
+ m_ui->zoomAllButton->setEnabled(zoomAllEnabled);
+}
+
+void QtGradientStopsControllerPrivate::slotHsvClicked()
+{
+ QString h = QApplication::translate("qdesigner_internal::QtGradientStopsController", "H", 0, QApplication::UnicodeUTF8);
+ QString s = QApplication::translate("qdesigner_internal::QtGradientStopsController", "S", 0, QApplication::UnicodeUTF8);
+ QString v = QApplication::translate("qdesigner_internal::QtGradientStopsController", "V", 0, QApplication::UnicodeUTF8);
+
+ m_ui->hLabel->setText(h);
+ m_ui->sLabel->setText(s);
+ m_ui->vLabel->setText(v);
+
+ h = QApplication::translate("qdesigner_internal::QtGradientStopsController", "Hue", 0, QApplication::UnicodeUTF8);
+ s = QApplication::translate("qdesigner_internal::QtGradientStopsController", "Sat", 0, QApplication::UnicodeUTF8);
+ v = QApplication::translate("qdesigner_internal::QtGradientStopsController", "Val", 0, QApplication::UnicodeUTF8);
+
+ const QString hue = QApplication::translate("qdesigner_internal::QtGradientStopsController", "Hue", 0, QApplication::UnicodeUTF8);
+ const QString saturation = QApplication::translate("qdesigner_internal::QtGradientStopsController", "Saturation", 0, QApplication::UnicodeUTF8);
+ const QString value = QApplication::translate("qdesigner_internal::QtGradientStopsController", "Value", 0, QApplication::UnicodeUTF8);
+
+ m_ui->hLabel->setToolTip(hue);
+ m_ui->hueLabel->setText(h);
+ m_ui->hueColorLine->setToolTip(hue);
+ m_ui->hueColorLine->setColorComponent(QtColorLine::Hue);
+
+ m_ui->sLabel->setToolTip(saturation);
+ m_ui->saturationLabel->setText(s);
+ m_ui->saturationColorLine->setToolTip(saturation);
+ m_ui->saturationColorLine->setColorComponent(QtColorLine::Saturation);
+
+ m_ui->vLabel->setToolTip(value);
+ m_ui->valueLabel->setText(v);
+ m_ui->valueColorLine->setToolTip(value);
+ m_ui->valueColorLine->setColorComponent(QtColorLine::Value);
+
+ setColorSpinBoxes(m_ui->colorButton->color());
+}
+
+void QtGradientStopsControllerPrivate::slotRgbClicked()
+{
+ QString r = QApplication::translate("qdesigner_internal::QtGradientStopsController", "R", 0, QApplication::UnicodeUTF8);
+ QString g = QApplication::translate("qdesigner_internal::QtGradientStopsController", "G", 0, QApplication::UnicodeUTF8);
+ QString b = QApplication::translate("qdesigner_internal::QtGradientStopsController", "B", 0, QApplication::UnicodeUTF8);
+
+ m_ui->hLabel->setText(r);
+ m_ui->sLabel->setText(g);
+ m_ui->vLabel->setText(b);
+
+ QString red = QApplication::translate("qdesigner_internal::QtGradientStopsController", "Red", 0, QApplication::UnicodeUTF8);
+ QString green = QApplication::translate("qdesigner_internal::QtGradientStopsController", "Green", 0, QApplication::UnicodeUTF8);
+ QString blue = QApplication::translate("qdesigner_internal::QtGradientStopsController", "Blue", 0, QApplication::UnicodeUTF8);
+
+ m_ui->hLabel->setToolTip(red);
+ m_ui->hueLabel->setText(red);
+ m_ui->hueColorLine->setToolTip(red);
+ m_ui->hueColorLine->setColorComponent(QtColorLine::Red);
+
+ m_ui->sLabel->setToolTip(green);
+ m_ui->saturationLabel->setText(green);
+ m_ui->saturationColorLine->setToolTip(green);
+ m_ui->saturationColorLine->setColorComponent(QtColorLine::Green);
+
+ m_ui->vLabel->setToolTip(blue);
+ m_ui->valueLabel->setText(blue);
+ m_ui->valueColorLine->setToolTip(blue);
+ m_ui->valueColorLine->setColorComponent(QtColorLine::Blue);
+
+ setColorSpinBoxes(m_ui->colorButton->color());
+}
+
+void QtGradientStopsControllerPrivate::setColorSpinBoxes(const QColor &color)
+{
+ m_ui->hueSpinBox->blockSignals(true);
+ m_ui->saturationSpinBox->blockSignals(true);
+ m_ui->valueSpinBox->blockSignals(true);
+ m_ui->alphaSpinBox->blockSignals(true);
+ if (m_ui->hsvRadioButton->isChecked()) {
+ if (m_ui->hueSpinBox->maximum() != 359)
+ m_ui->hueSpinBox->setMaximum(359);
+ if (m_ui->hueSpinBox->value() != color.hue())
+ m_ui->hueSpinBox->setValue(color.hue());
+ if (m_ui->saturationSpinBox->value() != color.saturation())
+ m_ui->saturationSpinBox->setValue(color.saturation());
+ if (m_ui->valueSpinBox->value() != color.value())
+ m_ui->valueSpinBox->setValue(color.value());
+ } else {
+ if (m_ui->hueSpinBox->maximum() != 255)
+ m_ui->hueSpinBox->setMaximum(255);
+ if (m_ui->hueSpinBox->value() != color.red())
+ m_ui->hueSpinBox->setValue(color.red());
+ if (m_ui->saturationSpinBox->value() != color.green())
+ m_ui->saturationSpinBox->setValue(color.green());
+ if (m_ui->valueSpinBox->value() != color.blue())
+ m_ui->valueSpinBox->setValue(color.blue());
+ }
+ m_ui->alphaSpinBox->setValue(color.alpha());
+ m_ui->hueSpinBox->blockSignals(false);
+ m_ui->saturationSpinBox->blockSignals(false);
+ m_ui->valueSpinBox->blockSignals(false);
+ m_ui->alphaSpinBox->blockSignals(false);
+}
+
+void QtGradientStopsControllerPrivate::slotCurrentStopChanged(QtGradientStop *stop)
+{
+ if (!stop) {
+ enableCurrent(false);
+ return;
+ }
+ enableCurrent(true);
+
+ QTimer::singleShot(0, q_ptr, SLOT(slotUpdatePositionSpinBox()));
+
+ m_ui->colorButton->setColor(stop->color());
+ m_ui->hueColorLine->setColor(stop->color());
+ m_ui->saturationColorLine->setColor(stop->color());
+ m_ui->valueColorLine->setColor(stop->color());
+ m_ui->alphaColorLine->setColor(stop->color());
+ setColorSpinBoxes(stop->color());
+}
+
+void QtGradientStopsControllerPrivate::slotStopMoved(QtGradientStop *stop, qreal newPos)
+{
+ QTimer::singleShot(0, q_ptr, SLOT(slotUpdatePositionSpinBox()));
+
+ PositionColorMap stops = stopsData(m_model->stops());
+ stops.remove(stop->position());
+ stops[newPos] = stop->color();
+
+ QGradientStops gradStops = makeGradientStops(stops);
+ emit q_ptr->gradientStopsChanged(gradStops);
+}
+
+void QtGradientStopsControllerPrivate::slotStopsSwapped(QtGradientStop *stop1, QtGradientStop *stop2)
+{
+ QTimer::singleShot(0, q_ptr, SLOT(slotUpdatePositionSpinBox()));
+
+ PositionColorMap stops = stopsData(m_model->stops());
+ const qreal pos1 = stop1->position();
+ const qreal pos2 = stop2->position();
+ stops[pos1] = stop2->color();
+ stops[pos2] = stop1->color();
+
+ QGradientStops gradStops = makeGradientStops(stops);
+ emit q_ptr->gradientStopsChanged(gradStops);
+}
+
+void QtGradientStopsControllerPrivate::slotStopAdded(QtGradientStop *stop)
+{
+ PositionColorMap stops = stopsData(m_model->stops());
+ stops[stop->position()] = stop->color();
+
+ QGradientStops gradStops = makeGradientStops(stops);
+ emit q_ptr->gradientStopsChanged(gradStops);
+}
+
+void QtGradientStopsControllerPrivate::slotStopRemoved(QtGradientStop *stop)
+{
+ PositionColorMap stops = stopsData(m_model->stops());
+ stops.remove(stop->position());
+
+ QGradientStops gradStops = makeGradientStops(stops);
+ emit q_ptr->gradientStopsChanged(gradStops);
+}
+
+void QtGradientStopsControllerPrivate::slotStopChanged(QtGradientStop *stop, const QColor &newColor)
+{
+ if (m_model->currentStop() == stop) {
+ m_ui->colorButton->setColor(newColor);
+ m_ui->hueColorLine->setColor(newColor);
+ m_ui->saturationColorLine->setColor(newColor);
+ m_ui->valueColorLine->setColor(newColor);
+ m_ui->alphaColorLine->setColor(newColor);
+ setColorSpinBoxes(newColor);
+ }
+
+ PositionColorMap stops = stopsData(m_model->stops());
+ stops[stop->position()] = newColor;
+
+ QGradientStops gradStops = makeGradientStops(stops);
+ emit q_ptr->gradientStopsChanged(gradStops);
+}
+
+void QtGradientStopsControllerPrivate::slotStopSelected(QtGradientStop *stop, bool selected)
+{
+ Q_UNUSED(stop)
+ Q_UNUSED(selected)
+ QTimer::singleShot(0, q_ptr, SLOT(slotUpdatePositionSpinBox()));
+}
+
+void QtGradientStopsControllerPrivate::slotUpdatePositionSpinBox()
+{
+ QtGradientStop *current = m_model->currentStop();
+ if (!current)
+ return;
+
+ qreal min = 0.0;
+ qreal max = 1.0;
+ const qreal pos = current->position();
+
+ QtGradientStop *first = m_model->firstSelected();
+ QtGradientStop *last = m_model->lastSelected();
+
+ if (first && last) {
+ const qreal minPos = pos - first->position() - 0.0004999;
+ const qreal maxPos = pos + 1.0 - last->position() + 0.0004999;
+
+ if (max > maxPos)
+ max = maxPos;
+ if (min < minPos)
+ min = minPos;
+
+ if (first->position() == 0.0)
+ min = pos;
+ if (last->position() == 1.0)
+ max = pos;
+ }
+
+ const int spinMin = qRound(m_ui->positionSpinBox->minimum() * 1000);
+ const int spinMax = qRound(m_ui->positionSpinBox->maximum() * 1000);
+
+ const int newMin = qRound(min * 1000);
+ const int newMax = qRound(max * 1000);
+
+ m_ui->positionSpinBox->blockSignals(true);
+ if (spinMin != newMin || spinMax != newMax) {
+ m_ui->positionSpinBox->setRange((double)newMin / 1000, (double)newMax / 1000);
+ }
+ if (m_ui->positionSpinBox->value() != pos)
+ m_ui->positionSpinBox->setValue(pos);
+ m_ui->positionSpinBox->blockSignals(false);
+}
+
+void QtGradientStopsControllerPrivate::slotChangeColor(const QColor &color)
+{
+ QtGradientStop *stop = m_model->currentStop();
+ if (!stop)
+ return;
+ m_model->changeStop(stop, color);
+ QList<QtGradientStop *> stops = m_model->selectedStops();
+ QListIterator<QtGradientStop *> itStop(stops);
+ while (itStop.hasNext()) {
+ QtGradientStop *s = itStop.next();
+ if (s != stop)
+ m_model->changeStop(s, color);
+ }
+}
+
+void QtGradientStopsControllerPrivate::slotChangeHue(const QColor &color)
+{
+ QtGradientStop *stop = m_model->currentStop();
+ if (!stop)
+ return;
+ m_model->changeStop(stop, color);
+ QList<QtGradientStop *> stops = m_model->selectedStops();
+ QListIterator<QtGradientStop *> itStop(stops);
+ while (itStop.hasNext()) {
+ QtGradientStop *s = itStop.next();
+ if (s != stop) {
+ QColor c = s->color();
+ if (m_ui->hsvRadioButton->isChecked())
+ c.setHsvF(color.hueF(), c.saturationF(), c.valueF(), c.alphaF());
+ else
+ c.setRgbF(color.redF(), c.greenF(), c.blueF(), c.alphaF());
+ m_model->changeStop(s, c);
+ }
+ }
+}
+
+void QtGradientStopsControllerPrivate::slotChangeHue(int color)
+{
+ QColor c = m_ui->hueColorLine->color();
+ if (m_ui->hsvRadioButton->isChecked())
+ c.setHsvF((qreal)color / 360.0, c.saturationF(), c.valueF(), c.alphaF());
+ else
+ c.setRed(color);
+ slotChangeHue(c);
+}
+
+void QtGradientStopsControllerPrivate::slotChangeSaturation(const QColor &color)
+{
+ QtGradientStop *stop = m_model->currentStop();
+ if (!stop)
+ return;
+ m_model->changeStop(stop, color);
+ QList<QtGradientStop *> stops = m_model->selectedStops();
+ QListIterator<QtGradientStop *> itStop(stops);
+ while (itStop.hasNext()) {
+ QtGradientStop *s = itStop.next();
+ if (s != stop) {
+ QColor c = s->color();
+ if (m_ui->hsvRadioButton->isChecked()) {
+ c.setHsvF(c.hueF(), color.saturationF(), c.valueF(), c.alphaF());
+ int hue = c.hue();
+ if (hue == 360 || hue == -1)
+ c.setHsvF(0.0, c.saturationF(), c.valueF(), c.alphaF());
+ } else {
+ c.setRgbF(c.redF(), color.greenF(), c.blueF(), c.alphaF());
+ }
+ m_model->changeStop(s, c);
+ }
+ }
+}
+
+void QtGradientStopsControllerPrivate::slotChangeSaturation(int color)
+{
+ QColor c = m_ui->saturationColorLine->color();
+ if (m_ui->hsvRadioButton->isChecked())
+ c.setHsvF(c.hueF(), (qreal)color / 255, c.valueF(), c.alphaF());
+ else
+ c.setGreen(color);
+ slotChangeSaturation(c);
+}
+
+void QtGradientStopsControllerPrivate::slotChangeValue(const QColor &color)
+{
+ QtGradientStop *stop = m_model->currentStop();
+ if (!stop)
+ return;
+ m_model->changeStop(stop, color);
+ QList<QtGradientStop *> stops = m_model->selectedStops();
+ QListIterator<QtGradientStop *> itStop(stops);
+ while (itStop.hasNext()) {
+ QtGradientStop *s = itStop.next();
+ if (s != stop) {
+ QColor c = s->color();
+ if (m_ui->hsvRadioButton->isChecked()) {
+ c.setHsvF(c.hueF(), c.saturationF(), color.valueF(), c.alphaF());
+ int hue = c.hue();
+ if (hue == 360 || hue == -1)
+ c.setHsvF(0.0, c.saturationF(), c.valueF(), c.alphaF());
+ } else {
+ c.setRgbF(c.redF(), c.greenF(), color.blueF(), c.alphaF());
+ }
+ m_model->changeStop(s, c);
+ }
+ }
+}
+
+void QtGradientStopsControllerPrivate::slotChangeValue(int color)
+{
+ QColor c = m_ui->valueColorLine->color();
+ if (m_ui->hsvRadioButton->isChecked())
+ c.setHsvF(c.hueF(), c.saturationF(), (qreal)color / 255, c.alphaF());
+ else
+ c.setBlue(color);
+ slotChangeValue(c);
+}
+
+void QtGradientStopsControllerPrivate::slotChangeAlpha(const QColor &color)
+{
+ QtGradientStop *stop = m_model->currentStop();
+ if (!stop)
+ return;
+ m_model->changeStop(stop, color);
+ QList<QtGradientStop *> stops = m_model->selectedStops();
+ QListIterator<QtGradientStop *> itStop(stops);
+ while (itStop.hasNext()) {
+ QtGradientStop *s = itStop.next();
+ if (s != stop) {
+ QColor c = s->color();
+ if (m_ui->hsvRadioButton->isChecked()) {
+ c.setHsvF(c.hueF(), c.saturationF(), c.valueF(), color.alphaF());
+ int hue = c.hue();
+ if (hue == 360 || hue == -1)
+ c.setHsvF(0.0, c.saturationF(), c.valueF(), c.alphaF());
+ } else {
+ c.setRgbF(c.redF(), c.greenF(), c.blueF(), color.alphaF());
+ }
+ m_model->changeStop(s, c);
+ }
+ }
+}
+
+void QtGradientStopsControllerPrivate::slotChangeAlpha(int color)
+{
+ QColor c = m_ui->alphaColorLine->color();
+ if (m_ui->hsvRadioButton->isChecked())
+ c.setHsvF(c.hueF(), c.saturationF(), c.valueF(), (qreal)color / 255);
+ else
+ c.setAlpha(color);
+ slotChangeAlpha(c);
+}
+
+void QtGradientStopsControllerPrivate::slotChangePosition(double value)
+{
+ QtGradientStop *stop = m_model->currentStop();
+ if (!stop)
+ return;
+
+ m_model->moveStops(value);
+}
+
+void QtGradientStopsControllerPrivate::slotChangeZoom(int value)
+{
+ updateZoom(value / 100.0);
+}
+
+void QtGradientStopsControllerPrivate::slotZoomIn()
+{
+ double newZoom = m_ui->gradientStopsWidget->zoom() * 2;
+ if (newZoom > 100)
+ newZoom = 100;
+ updateZoom(newZoom);
+}
+
+void QtGradientStopsControllerPrivate::slotZoomOut()
+{
+ double newZoom = m_ui->gradientStopsWidget->zoom() / 2;
+ if (newZoom < 1)
+ newZoom = 1;
+ updateZoom(newZoom);
+}
+
+void QtGradientStopsControllerPrivate::slotZoomAll()
+{
+ updateZoom(1);
+}
+
+void QtGradientStopsControllerPrivate::slotZoomChanged(double zoom)
+{
+ updateZoom(zoom);
+}
+
+QtGradientStopsController::QtGradientStopsController(QObject *parent)
+ : QObject(parent), d_ptr(new QtGradientStopsControllerPrivate())
+{
+ d_ptr->q_ptr = this;
+
+ d_ptr->m_spec = QColor::Hsv;
+}
+
+void QtGradientStopsController::setUi(Ui::QtGradientEditor *ui)
+{
+ d_ptr->m_ui = ui;
+
+ d_ptr->m_ui->hueColorLine->setColorComponent(QtColorLine::Hue);
+ d_ptr->m_ui->saturationColorLine->setColorComponent(QtColorLine::Saturation);
+ d_ptr->m_ui->valueColorLine->setColorComponent(QtColorLine::Value);
+ d_ptr->m_ui->alphaColorLine->setColorComponent(QtColorLine::Alpha);
+
+ d_ptr->m_model = new QtGradientStopsModel(this);
+ d_ptr->m_ui->gradientStopsWidget->setGradientStopsModel(d_ptr->m_model);
+ connect(d_ptr->m_model, SIGNAL(currentStopChanged(QtGradientStop*)),
+ this, SLOT(slotCurrentStopChanged(QtGradientStop*)));
+ connect(d_ptr->m_model, SIGNAL(stopMoved(QtGradientStop*,qreal)),
+ this, SLOT(slotStopMoved(QtGradientStop*,qreal)));
+ connect(d_ptr->m_model, SIGNAL(stopsSwapped(QtGradientStop*,QtGradientStop*)),
+ this, SLOT(slotStopsSwapped(QtGradientStop*,QtGradientStop*)));
+ connect(d_ptr->m_model, SIGNAL(stopChanged(QtGradientStop*,QColor)),
+ this, SLOT(slotStopChanged(QtGradientStop*,QColor)));
+ connect(d_ptr->m_model, SIGNAL(stopSelected(QtGradientStop*,bool)),
+ this, SLOT(slotStopSelected(QtGradientStop*,bool)));
+ connect(d_ptr->m_model, SIGNAL(stopAdded(QtGradientStop*)),
+ this, SLOT(slotStopAdded(QtGradientStop*)));
+ connect(d_ptr->m_model, SIGNAL(stopRemoved(QtGradientStop*)),
+ this, SLOT(slotStopRemoved(QtGradientStop*)));
+
+ connect(d_ptr->m_ui->hueColorLine, SIGNAL(colorChanged(QColor)),
+ this, SLOT(slotChangeHue(QColor)));
+ connect(d_ptr->m_ui->saturationColorLine, SIGNAL(colorChanged(QColor)),
+ this, SLOT(slotChangeSaturation(QColor)));
+ connect(d_ptr->m_ui->valueColorLine, SIGNAL(colorChanged(QColor)),
+ this, SLOT(slotChangeValue(QColor)));
+ connect(d_ptr->m_ui->alphaColorLine, SIGNAL(colorChanged(QColor)),
+ this, SLOT(slotChangeAlpha(QColor)));
+ connect(d_ptr->m_ui->colorButton, SIGNAL(colorChanged(QColor)),
+ this, SLOT(slotChangeColor(QColor)));
+
+ connect(d_ptr->m_ui->hueSpinBox, SIGNAL(valueChanged(int)),
+ this, SLOT(slotChangeHue(int)));
+ connect(d_ptr->m_ui->saturationSpinBox, SIGNAL(valueChanged(int)),
+ this, SLOT(slotChangeSaturation(int)));
+ connect(d_ptr->m_ui->valueSpinBox, SIGNAL(valueChanged(int)),
+ this, SLOT(slotChangeValue(int)));
+ connect(d_ptr->m_ui->alphaSpinBox, SIGNAL(valueChanged(int)),
+ this, SLOT(slotChangeAlpha(int)));
+
+ connect(d_ptr->m_ui->positionSpinBox, SIGNAL(valueChanged(double)),
+ this, SLOT(slotChangePosition(double)));
+
+ connect(d_ptr->m_ui->zoomSpinBox, SIGNAL(valueChanged(int)),
+ this, SLOT(slotChangeZoom(int)));
+ connect(d_ptr->m_ui->zoomInButton, SIGNAL(clicked()),
+ this, SLOT(slotZoomIn()));
+ connect(d_ptr->m_ui->zoomOutButton, SIGNAL(clicked()),
+ this, SLOT(slotZoomOut()));
+ connect(d_ptr->m_ui->zoomAllButton, SIGNAL(clicked()),
+ this, SLOT(slotZoomAll()));
+ connect(d_ptr->m_ui->gradientStopsWidget, SIGNAL(zoomChanged(double)),
+ this, SLOT(slotZoomChanged(double)));
+
+ connect(d_ptr->m_ui->hsvRadioButton, SIGNAL(clicked()),
+ this, SLOT(slotHsvClicked()));
+ connect(d_ptr->m_ui->rgbRadioButton, SIGNAL(clicked()),
+ this, SLOT(slotRgbClicked()));
+
+ d_ptr->enableCurrent(false);
+ d_ptr->m_ui->zoomInButton->setIcon(QIcon(QLatin1String(":/trolltech/qtgradienteditor/images/zoomin.png")));
+ d_ptr->m_ui->zoomOutButton->setIcon(QIcon(QLatin1String(":/trolltech/qtgradienteditor/images/zoomout.png")));
+ d_ptr->updateZoom(1);
+}
+
+QtGradientStopsController::~QtGradientStopsController()
+{
+}
+
+void QtGradientStopsController::setGradientStops(const QGradientStops &stops)
+{
+ d_ptr->m_model->clear();
+ QVectorIterator<QPair<qreal, QColor> > it(stops);
+ QtGradientStop *first = 0;
+ while (it.hasNext()) {
+ QPair<qreal, QColor> pair = it.next();
+ QtGradientStop *stop = d_ptr->m_model->addStop(pair.first, pair.second);
+ if (!first)
+ first = stop;
+ }
+ if (first)
+ d_ptr->m_model->setCurrentStop(first);
+}
+
+QGradientStops QtGradientStopsController::gradientStops() const
+{
+ QGradientStops stops;
+ QList<QtGradientStop *> stopsList = d_ptr->m_model->stops().values();
+ QListIterator<QtGradientStop *> itStop(stopsList);
+ while (itStop.hasNext()) {
+ QtGradientStop *stop = itStop.next();
+ stops << QPair<qreal, QColor>(stop->position(), stop->color());
+ }
+ return stops;
+}
+
+QColor::Spec QtGradientStopsController::spec() const
+{
+ return d_ptr->m_spec;
+}
+
+void QtGradientStopsController::setSpec(QColor::Spec spec)
+{
+ if (d_ptr->m_spec == spec)
+ return;
+
+ d_ptr->m_spec = spec;
+ if (d_ptr->m_spec == QColor::Rgb) {
+ d_ptr->m_ui->rgbRadioButton->setChecked(true);
+ d_ptr->slotRgbClicked();
+ } else {
+ d_ptr->m_ui->hsvRadioButton->setChecked(true);
+ d_ptr->slotHsvClicked();
+ }
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qtgradientstopscontroller.cpp"
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientstopscontroller.h b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientstopscontroller.h
new file mode 100644
index 0000000000..ca818f83e8
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientstopscontroller.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTGRADIENTSTOPSCONTROLLER_H
+#define QTGRADIENTSTOPSCONTROLLER_H
+
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+namespace Ui {
+ class QtGradientEditor;
+}
+
+class QtGradientStopsController : public QObject
+{
+ Q_OBJECT
+public:
+ QtGradientStopsController(QObject *parent = 0);
+ ~QtGradientStopsController();
+
+ void setUi(Ui::QtGradientEditor *editor);
+
+ void setGradientStops(const QGradientStops &stops);
+ QGradientStops gradientStops() const;
+
+ QColor::Spec spec() const;
+ void setSpec(QColor::Spec spec);
+
+signals:
+
+ void gradientStopsChanged(const QGradientStops &stops);
+
+private:
+ QScopedPointer<class QtGradientStopsControllerPrivate> d_ptr;
+ Q_DECLARE_PRIVATE(QtGradientStopsController)
+ Q_DISABLE_COPY(QtGradientStopsController)
+ Q_PRIVATE_SLOT(d_func(), void slotHsvClicked())
+ Q_PRIVATE_SLOT(d_func(), void slotRgbClicked())
+ Q_PRIVATE_SLOT(d_func(), void slotCurrentStopChanged(QtGradientStop *stop))
+ Q_PRIVATE_SLOT(d_func(), void slotStopMoved(QtGradientStop *stop, qreal newPos))
+ Q_PRIVATE_SLOT(d_func(), void slotStopsSwapped(QtGradientStop *stop1, QtGradientStop *stop2))
+ Q_PRIVATE_SLOT(d_func(), void slotStopChanged(QtGradientStop *stop, const QColor &newColor))
+ Q_PRIVATE_SLOT(d_func(), void slotStopSelected(QtGradientStop *stop, bool selected))
+ Q_PRIVATE_SLOT(d_func(), void slotStopAdded(QtGradientStop *stop))
+ Q_PRIVATE_SLOT(d_func(), void slotStopRemoved(QtGradientStop *stop))
+ Q_PRIVATE_SLOT(d_func(), void slotUpdatePositionSpinBox())
+ Q_PRIVATE_SLOT(d_func(), void slotChangeColor(const QColor &color))
+ Q_PRIVATE_SLOT(d_func(), void slotChangeHue(const QColor &color))
+ Q_PRIVATE_SLOT(d_func(), void slotChangeSaturation(const QColor &color))
+ Q_PRIVATE_SLOT(d_func(), void slotChangeValue(const QColor &color))
+ Q_PRIVATE_SLOT(d_func(), void slotChangeAlpha(const QColor &color))
+ Q_PRIVATE_SLOT(d_func(), void slotChangeHue(int))
+ Q_PRIVATE_SLOT(d_func(), void slotChangeSaturation(int))
+ Q_PRIVATE_SLOT(d_func(), void slotChangeValue(int))
+ Q_PRIVATE_SLOT(d_func(), void slotChangeAlpha(int))
+ //Q_PRIVATE_SLOT(d_func(), void slotChangePosition(double newPos))
+ Q_PRIVATE_SLOT(d_func(), void slotChangePosition(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotChangeZoom(int value))
+ Q_PRIVATE_SLOT(d_func(), void slotZoomIn())
+ Q_PRIVATE_SLOT(d_func(), void slotZoomOut())
+ Q_PRIVATE_SLOT(d_func(), void slotZoomAll())
+ Q_PRIVATE_SLOT(d_func(), void slotZoomChanged(double))
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientstopsmodel.cpp b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientstopsmodel.cpp
new file mode 100644
index 0000000000..5a963a8129
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientstopsmodel.cpp
@@ -0,0 +1,477 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtgradientstopsmodel.h"
+#include <QtGui/QColor>
+
+QT_BEGIN_NAMESPACE
+
+class QtGradientStopPrivate
+{
+public:
+ qreal m_position;
+ QColor m_color;
+ QtGradientStopsModel *m_model;
+};
+
+qreal QtGradientStop::position() const
+{
+ return d_ptr->m_position;
+}
+
+QColor QtGradientStop::color() const
+{
+ return d_ptr->m_color;
+}
+
+QtGradientStopsModel *QtGradientStop::gradientModel() const
+{
+ return d_ptr->m_model;
+}
+
+void QtGradientStop::setColor(const QColor &color)
+{
+ d_ptr->m_color = color;
+}
+
+void QtGradientStop::setPosition(qreal position)
+{
+ d_ptr->m_position = position;
+}
+
+QtGradientStop::QtGradientStop(QtGradientStopsModel *model)
+ : d_ptr(new QtGradientStopPrivate())
+{
+ d_ptr->m_position = 0;
+ d_ptr->m_color = Qt::white;
+ d_ptr->m_model = model;
+}
+
+QtGradientStop::~QtGradientStop()
+{
+}
+
+class QtGradientStopsModelPrivate
+{
+ QtGradientStopsModel *q_ptr;
+ Q_DECLARE_PUBLIC(QtGradientStopsModel)
+public:
+ QMap<qreal, QtGradientStop *> m_posToStop;
+ QMap<QtGradientStop *, qreal> m_stopToPos;
+ QMap<QtGradientStop *, bool> m_selection;
+ QtGradientStop *m_current;
+};
+
+
+
+QtGradientStopsModel::QtGradientStopsModel(QObject *parent)
+ : QObject(parent), d_ptr(new QtGradientStopsModelPrivate)
+{
+ d_ptr->q_ptr = this;
+ d_ptr->m_current = 0;
+}
+
+QtGradientStopsModel::~QtGradientStopsModel()
+{
+ clear();
+}
+
+QtGradientStopsModel::PositionStopMap QtGradientStopsModel::stops() const
+{
+ return d_ptr->m_posToStop;
+}
+
+QtGradientStop *QtGradientStopsModel::at(qreal pos) const
+{
+ if (d_ptr->m_posToStop.contains(pos))
+ return d_ptr->m_posToStop[pos];
+ return 0;
+}
+
+QColor QtGradientStopsModel::color(qreal pos) const
+{
+ PositionStopMap gradStops = stops();
+ if (gradStops.isEmpty())
+ return QColor::fromRgbF(pos, pos, pos, 1.0);
+ if (gradStops.contains(pos))
+ return gradStops[pos]->color();
+
+ gradStops[pos] = 0;
+ PositionStopMap::ConstIterator itStop = gradStops.constFind(pos);
+ if (itStop == gradStops.constBegin()) {
+ ++itStop;
+ return itStop.value()->color();
+ }
+ if (itStop == --gradStops.constEnd()) {
+ --itStop;
+ return itStop.value()->color();
+ }
+ PositionStopMap::ConstIterator itPrev = itStop;
+ PositionStopMap::ConstIterator itNext = itStop;
+ --itPrev;
+ ++itNext;
+
+ double prevX = itPrev.key();
+ double nextX = itNext.key();
+
+ double coefX = (pos - prevX) / (nextX - prevX);
+ QColor prevCol = itPrev.value()->color();
+ QColor nextCol = itNext.value()->color();
+
+ QColor newColor;
+ newColor.setRgbF((nextCol.redF() - prevCol.redF() ) * coefX + prevCol.redF(),
+ (nextCol.greenF() - prevCol.greenF()) * coefX + prevCol.greenF(),
+ (nextCol.blueF() - prevCol.blueF() ) * coefX + prevCol.blueF(),
+ (nextCol.alphaF() - prevCol.alphaF()) * coefX + prevCol.alphaF());
+ return newColor;
+}
+
+QList<QtGradientStop *> QtGradientStopsModel::selectedStops() const
+{
+ return d_ptr->m_selection.keys();
+}
+
+QtGradientStop *QtGradientStopsModel::currentStop() const
+{
+ return d_ptr->m_current;
+}
+
+bool QtGradientStopsModel::isSelected(QtGradientStop *stop) const
+{
+ if (d_ptr->m_selection.contains(stop))
+ return true;
+ return false;
+}
+
+QtGradientStop *QtGradientStopsModel::addStop(qreal pos, const QColor &color)
+{
+ qreal newPos = pos;
+ if (pos < 0.0)
+ newPos = 0.0;
+ if (pos > 1.0)
+ newPos = 1.0;
+ if (d_ptr->m_posToStop.contains(newPos))
+ return 0;
+ QtGradientStop *stop = new QtGradientStop();
+ stop->setPosition(newPos);
+ stop->setColor(color);
+
+ d_ptr->m_posToStop[newPos] = stop;
+ d_ptr->m_stopToPos[stop] = newPos;
+
+ emit stopAdded(stop);
+
+ return stop;
+}
+
+void QtGradientStopsModel::removeStop(QtGradientStop *stop)
+{
+ if (!d_ptr->m_stopToPos.contains(stop))
+ return;
+ if (currentStop() == stop)
+ setCurrentStop(0);
+ selectStop(stop, false);
+
+ emit stopRemoved(stop);
+
+ qreal pos = d_ptr->m_stopToPos[stop];
+ d_ptr->m_stopToPos.remove(stop);
+ d_ptr->m_posToStop.remove(pos);
+ delete stop;
+}
+
+void QtGradientStopsModel::moveStop(QtGradientStop *stop, qreal newPos)
+{
+ if (!d_ptr->m_stopToPos.contains(stop))
+ return;
+ if (d_ptr->m_posToStop.contains(newPos))
+ return;
+
+ if (newPos > 1.0)
+ newPos = 1.0;
+ else if (newPos < 0.0)
+ newPos = 0.0;
+
+ emit stopMoved(stop, newPos);
+
+ const qreal oldPos = stop->position();
+ stop->setPosition(newPos);
+ d_ptr->m_stopToPos[stop] = newPos;
+ d_ptr->m_posToStop.remove(oldPos);
+ d_ptr->m_posToStop[newPos] = stop;
+}
+
+void QtGradientStopsModel::swapStops(QtGradientStop *stop1, QtGradientStop *stop2)
+{
+ if (stop1 == stop2)
+ return;
+ if (!d_ptr->m_stopToPos.contains(stop1))
+ return;
+ if (!d_ptr->m_stopToPos.contains(stop2))
+ return;
+
+ emit stopsSwapped(stop1, stop2);
+
+ const qreal pos1 = stop1->position();
+ const qreal pos2 = stop2->position();
+ stop1->setPosition(pos2);
+ stop2->setPosition(pos1);
+ d_ptr->m_stopToPos[stop1] = pos2;
+ d_ptr->m_stopToPos[stop2] = pos1;
+ d_ptr->m_posToStop[pos1] = stop2;
+ d_ptr->m_posToStop[pos2] = stop1;
+}
+
+void QtGradientStopsModel::changeStop(QtGradientStop *stop, const QColor &newColor)
+{
+ if (!d_ptr->m_stopToPos.contains(stop))
+ return;
+ if (stop->color() == newColor)
+ return;
+
+ emit stopChanged(stop, newColor);
+
+ stop->setColor(newColor);
+}
+
+void QtGradientStopsModel::selectStop(QtGradientStop *stop, bool select)
+{
+ if (!d_ptr->m_stopToPos.contains(stop))
+ return;
+ bool selected = d_ptr->m_selection.contains(stop);
+ if (select == selected)
+ return;
+
+ emit stopSelected(stop, select);
+
+ if (select)
+ d_ptr->m_selection[stop] = true;
+ else
+ d_ptr->m_selection.remove(stop);
+}
+
+void QtGradientStopsModel::setCurrentStop(QtGradientStop *stop)
+{
+ if (stop && !d_ptr->m_stopToPos.contains(stop))
+ return;
+ if (stop == currentStop())
+ return;
+
+ emit currentStopChanged(stop);
+
+ d_ptr->m_current = stop;
+}
+
+QtGradientStop *QtGradientStopsModel::firstSelected() const
+{
+ PositionStopMap stopList = stops();
+ PositionStopMap::ConstIterator itStop = stopList.constBegin();
+ while (itStop != stopList.constEnd()) {
+ QtGradientStop *stop = itStop.value();
+ if (isSelected(stop))
+ return stop;
+ ++itStop;
+ };
+ return 0;
+}
+
+QtGradientStop *QtGradientStopsModel::lastSelected() const
+{
+ PositionStopMap stopList = stops();
+ PositionStopMap::ConstIterator itStop = stopList.constEnd();
+ while (itStop != stopList.constBegin()) {
+ --itStop;
+
+ QtGradientStop *stop = itStop.value();
+ if (isSelected(stop))
+ return stop;
+ };
+ return 0;
+}
+
+QtGradientStopsModel *QtGradientStopsModel::clone() const
+{
+ QtGradientStopsModel *model = new QtGradientStopsModel();
+
+ QMap<qreal, QtGradientStop *> stopsToClone = stops();
+ QMapIterator<qreal, QtGradientStop *> it(stopsToClone);
+ while (it.hasNext()) {
+ it.next();
+ model->addStop(it.key(), it.value()->color());
+ }
+ // clone selection and current also
+ return model;
+}
+
+void QtGradientStopsModel::moveStops(double newPosition)
+{
+ QtGradientStop *current = currentStop();
+ if (!current)
+ return;
+
+ double newPos = newPosition;
+
+ if (newPos > 1)
+ newPos = 1;
+ else if (newPos < 0)
+ newPos = 0;
+
+ if (newPos == current->position())
+ return;
+
+ double offset = newPos - current->position();
+
+ QtGradientStop *first = firstSelected();
+ QtGradientStop *last = lastSelected();
+
+ if (first && last) { // multiselection
+ double maxOffset = 1.0 - last->position();
+ double minOffset = -first->position();
+
+ if (offset > maxOffset)
+ offset = maxOffset;
+ else if (offset < minOffset)
+ offset = minOffset;
+
+ }
+
+ if (offset == 0)
+ return;
+
+ bool forward = (offset > 0) ? false : true;
+
+ PositionStopMap stopList;
+
+ QList<QtGradientStop *> selected = selectedStops();
+ QListIterator<QtGradientStop *> it(selected);
+ while (it.hasNext()) {
+ QtGradientStop *stop = it.next();
+ stopList[stop->position()] = stop;
+ }
+ stopList[current->position()] = current;
+
+ PositionStopMap::ConstIterator itStop = forward ? stopList.constBegin() : stopList.constEnd();
+ while (itStop != (forward ? stopList.constEnd() : stopList.constBegin())) {
+ if (!forward)
+ --itStop;
+ QtGradientStop *stop = itStop.value();
+ double pos = stop->position() + offset;
+ if (pos > 1)
+ pos = 1;
+ if (pos < 0)
+ pos = 0;
+
+ if (current == stop)
+ pos = newPos;
+
+ QtGradientStop *oldStop = at(pos);
+ if (oldStop && !stopList.values().contains(oldStop))
+ removeStop(oldStop);
+ moveStop(stop, pos);
+
+ if (forward)
+ ++itStop;
+ }
+}
+
+void QtGradientStopsModel::clear()
+{
+ QList<QtGradientStop *> stopsList = stops().values();
+ QListIterator<QtGradientStop *> it(stopsList);
+ while (it.hasNext())
+ removeStop(it.next());
+}
+
+void QtGradientStopsModel::clearSelection()
+{
+ QList<QtGradientStop *> stopsList = selectedStops();
+ QListIterator<QtGradientStop *> it(stopsList);
+ while (it.hasNext())
+ selectStop(it.next(), false);
+}
+
+void QtGradientStopsModel::flipAll()
+{
+ QMap<qreal, QtGradientStop *> stopsMap = stops();
+ QMapIterator<qreal, QtGradientStop *> itStop(stopsMap);
+ itStop.toBack();
+
+ QMap<QtGradientStop *, bool> swappedList;
+
+ while (itStop.hasPrevious()) {
+ itStop.previous();
+
+ QtGradientStop *stop = itStop.value();
+ if (swappedList.contains(stop))
+ continue;
+ const double newPos = 1.0 - itStop.key();
+ if (stopsMap.contains(newPos)) {
+ QtGradientStop *swapped = stopsMap.value(newPos);
+ swappedList[swapped] = true;
+ swapStops(stop, swapped);
+ } else {
+ moveStop(stop, newPos);
+ }
+ }
+}
+
+void QtGradientStopsModel::selectAll()
+{
+ QList<QtGradientStop *> stopsList = stops().values();
+ QListIterator<QtGradientStop *> it(stopsList);
+ while (it.hasNext())
+ selectStop(it.next(), true);
+}
+
+void QtGradientStopsModel::deleteStops()
+{
+ QList<QtGradientStop *> selected = selectedStops();
+ QListIterator<QtGradientStop *> itSel(selected);
+ while (itSel.hasNext()) {
+ QtGradientStop *stop = itSel.next();
+ removeStop(stop);
+ }
+ QtGradientStop *current = currentStop();
+ if (current)
+ removeStop(current);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientstopsmodel.h b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientstopsmodel.h
new file mode 100644
index 0000000000..0b2dcc6c5d
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientstopsmodel.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTGRADIENTSTOPSMODEL_H
+#define QTGRADIENTSTOPSMODEL_H
+
+#include <QtCore/QObject>
+#include <QtCore/QMap>
+
+QT_BEGIN_NAMESPACE
+
+class QColor;
+
+class QtGradientStopsModel;
+
+class QtGradientStop
+{
+public:
+ qreal position() const;
+ QColor color() const;
+ QtGradientStopsModel *gradientModel() const;
+
+private:
+ void setColor(const QColor &color);
+ void setPosition(qreal position);
+ friend class QtGradientStopsModel;
+ QtGradientStop(QtGradientStopsModel *model = 0);
+ ~QtGradientStop();
+ QScopedPointer<class QtGradientStopPrivate> d_ptr;
+};
+
+class QtGradientStopsModel : public QObject
+{
+ Q_OBJECT
+public:
+ typedef QMap<qreal, QtGradientStop *> PositionStopMap;
+
+ QtGradientStopsModel(QObject *parent = 0);
+ ~QtGradientStopsModel();
+
+ PositionStopMap stops() const;
+ QtGradientStop *at(qreal pos) const;
+ QColor color(qreal pos) const; // calculated between points
+ QList<QtGradientStop *> selectedStops() const;
+ QtGradientStop *currentStop() const;
+ bool isSelected(QtGradientStop *stop) const;
+ QtGradientStop *firstSelected() const;
+ QtGradientStop *lastSelected() const;
+ QtGradientStopsModel *clone() const;
+
+ QtGradientStop *addStop(qreal pos, const QColor &color);
+ void removeStop(QtGradientStop *stop);
+ void moveStop(QtGradientStop *stop, qreal newPos);
+ void swapStops(QtGradientStop *stop1, QtGradientStop *stop2);
+ void changeStop(QtGradientStop *stop, const QColor &newColor);
+ void selectStop(QtGradientStop *stop, bool select);
+ void setCurrentStop(QtGradientStop *stop);
+
+ void moveStops(double newPosition); // moves current stop to newPos and all selected stops are moved accordingly
+ void clear();
+ void clearSelection();
+ void flipAll();
+ void selectAll();
+ void deleteStops();
+
+signals:
+ void stopAdded(QtGradientStop *stop);
+ void stopRemoved(QtGradientStop *stop);
+ void stopMoved(QtGradientStop *stop, qreal newPos);
+ void stopsSwapped(QtGradientStop *stop1, QtGradientStop *stop2);
+ void stopChanged(QtGradientStop *stop, const QColor &newColor);
+ void stopSelected(QtGradientStop *stop, bool selected);
+ void currentStopChanged(QtGradientStop *stop);
+
+private:
+ QScopedPointer<class QtGradientStopsModelPrivate> d_ptr;
+ Q_DECLARE_PRIVATE(QtGradientStopsModel)
+ Q_DISABLE_COPY(QtGradientStopsModel)
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientstopswidget.cpp b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientstopswidget.cpp
new file mode 100644
index 0000000000..411dbed456
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientstopswidget.cpp
@@ -0,0 +1,1154 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtgradientstopswidget.h"
+#include "qtgradientstopsmodel.h"
+
+#include <QtCore/QMap>
+#include <QtGui/QImage>
+#include <QtGui/QPainter>
+#include <QtGui/QScrollBar>
+#include <QtGui/QMouseEvent>
+#include <QtGui/QRubberBand>
+#include <QtGui/QMenu>
+
+QT_BEGIN_NAMESPACE
+
+class QtGradientStopsWidgetPrivate
+{
+ QtGradientStopsWidget *q_ptr;
+ Q_DECLARE_PUBLIC(QtGradientStopsWidget)
+public:
+ typedef QMap<qreal, QColor> PositionColorMap;
+ typedef QMap<QtGradientStop *, qreal> StopPositionMap;
+
+ void slotStopAdded(QtGradientStop *stop);
+ void slotStopRemoved(QtGradientStop *stop);
+ void slotStopMoved(QtGradientStop *stop, qreal newPos);
+ void slotStopsSwapped(QtGradientStop *stop1, QtGradientStop *stop2);
+ void slotStopChanged(QtGradientStop *stop, const QColor &newColor);
+ void slotStopSelected(QtGradientStop *stop, bool selected);
+ void slotCurrentStopChanged(QtGradientStop *stop);
+ void slotNewStop();
+ void slotDelete();
+ void slotFlipAll();
+ void slotSelectAll();
+ void slotZoomIn();
+ void slotZoomOut();
+ void slotResetZoom();
+
+ double fromViewport(int x) const;
+ double toViewport(double x) const;
+ QtGradientStop *stopAt(const QPoint &viewportPos) const;
+ QList<QtGradientStop *> stopsAt(const QPoint &viewportPos) const;
+ void setupMove(QtGradientStop *stop, int x);
+ void ensureVisible(double x); // x = stop position
+ void ensureVisible(QtGradientStop *stop);
+ QtGradientStop *newStop(const QPoint &viewportPos);
+
+ bool m_backgroundCheckered;
+ QtGradientStopsModel *m_model;
+ double m_handleSize;
+ int m_scaleFactor;
+ double m_zoom;
+
+#ifndef QT_NO_DRAGANDDROP
+ QtGradientStop *m_dragStop;
+ QtGradientStop *m_changedStop;
+ QtGradientStop *m_clonedStop;
+ QtGradientStopsModel *m_dragModel;
+ QColor m_dragColor;
+ void clearDrag();
+ void removeClonedStop();
+ void restoreChangedStop();
+ void changeStop(qreal pos);
+ void cloneStop(qreal pos);
+#endif
+
+ QRubberBand *m_rubber;
+ QPoint m_clickPos;
+
+ QList<QtGradientStop *> m_stops;
+
+ bool m_moving;
+ int m_moveOffset;
+ StopPositionMap m_moveStops;
+
+ PositionColorMap m_moveOriginal;
+};
+
+double QtGradientStopsWidgetPrivate::fromViewport(int x) const
+{
+ QSize size = q_ptr->viewport()->size();
+ int w = size.width();
+ int max = q_ptr->horizontalScrollBar()->maximum();
+ int val = q_ptr->horizontalScrollBar()->value();
+ return ((double)x * m_scaleFactor + w * val) / (w * (m_scaleFactor + max));
+}
+
+double QtGradientStopsWidgetPrivate::toViewport(double x) const
+{
+ QSize size = q_ptr->viewport()->size();
+ int w = size.width();
+ int max = q_ptr->horizontalScrollBar()->maximum();
+ int val = q_ptr->horizontalScrollBar()->value();
+ return w * (x * (m_scaleFactor + max) - val) / m_scaleFactor;
+}
+
+QtGradientStop *QtGradientStopsWidgetPrivate::stopAt(const QPoint &viewportPos) const
+{
+ double posY = m_handleSize / 2;
+ QListIterator<QtGradientStop *> itStop(m_stops);
+ while (itStop.hasNext()) {
+ QtGradientStop *stop = itStop.next();
+
+ double posX = toViewport(stop->position());
+
+ double x = viewportPos.x() - posX;
+ double y = viewportPos.y() - posY;
+
+ if ((m_handleSize * m_handleSize / 4) > (x * x + y * y))
+ return stop;
+ }
+ return 0;
+}
+
+QList<QtGradientStop *> QtGradientStopsWidgetPrivate::stopsAt(const QPoint &viewportPos) const
+{
+ QList<QtGradientStop *> stops;
+ double posY = m_handleSize / 2;
+ QListIterator<QtGradientStop *> itStop(m_stops);
+ while (itStop.hasNext()) {
+ QtGradientStop *stop = itStop.next();
+
+ double posX = toViewport(stop->position());
+
+ double x = viewportPos.x() - posX;
+ double y = viewportPos.y() - posY;
+
+ if ((m_handleSize * m_handleSize / 4) > (x * x + y * y))
+ stops.append(stop);
+ }
+ return stops;
+}
+
+void QtGradientStopsWidgetPrivate::setupMove(QtGradientStop *stop, int x)
+{
+ m_model->setCurrentStop(stop);
+
+ int viewportX = qRound(toViewport(stop->position()));
+ m_moveOffset = x - viewportX;
+
+ QList<QtGradientStop *> stops = m_stops;
+ m_stops.clear();
+ QListIterator<QtGradientStop *> itStop(stops);
+ while (itStop.hasNext()) {
+ QtGradientStop *s = itStop.next();
+ if (m_model->isSelected(s) || s == stop) {
+ m_moveStops[s] = s->position() - stop->position();
+ m_stops.append(s);
+ } else {
+ m_moveOriginal[s->position()] = s->color();
+ }
+ }
+ itStop.toFront();
+ while (itStop.hasNext()) {
+ QtGradientStop *s = itStop.next();
+ if (!m_model->isSelected(s))
+ m_stops.append(s);
+ }
+ m_stops.removeAll(stop);
+ m_stops.prepend(stop);
+}
+
+void QtGradientStopsWidgetPrivate::ensureVisible(double x)
+{
+ double viewX = toViewport(x);
+ if (viewX < 0 || viewX > q_ptr->viewport()->size().width()) {
+ int max = q_ptr->horizontalScrollBar()->maximum();
+ int newVal = qRound(x * (max + m_scaleFactor) - m_scaleFactor / 2);
+ q_ptr->horizontalScrollBar()->setValue(newVal);
+ }
+}
+
+void QtGradientStopsWidgetPrivate::ensureVisible(QtGradientStop *stop)
+{
+ if (!stop)
+ return;
+ ensureVisible(stop->position());
+}
+
+QtGradientStop *QtGradientStopsWidgetPrivate::newStop(const QPoint &viewportPos)
+{
+ QtGradientStop *copyStop = stopAt(viewportPos);
+ double posX = fromViewport(viewportPos.x());
+ QtGradientStop *stop = m_model->at(posX);
+ if (!stop) {
+ QColor newColor;
+ if (copyStop)
+ newColor = copyStop->color();
+ else
+ newColor = m_model->color(posX);
+ if (!newColor.isValid())
+ newColor = Qt::white;
+ stop = m_model->addStop(posX, newColor);
+ }
+ return stop;
+}
+
+void QtGradientStopsWidgetPrivate::slotStopAdded(QtGradientStop *stop)
+{
+ m_stops.append(stop);
+ q_ptr->viewport()->update();
+}
+
+void QtGradientStopsWidgetPrivate::slotStopRemoved(QtGradientStop *stop)
+{
+ m_stops.removeAll(stop);
+ q_ptr->viewport()->update();
+}
+
+void QtGradientStopsWidgetPrivate::slotStopMoved(QtGradientStop *stop, qreal newPos)
+{
+ Q_UNUSED(stop)
+ Q_UNUSED(newPos)
+ q_ptr->viewport()->update();
+}
+
+void QtGradientStopsWidgetPrivate::slotStopsSwapped(QtGradientStop *stop1, QtGradientStop *stop2)
+{
+ Q_UNUSED(stop1)
+ Q_UNUSED(stop2)
+ q_ptr->viewport()->update();
+}
+
+void QtGradientStopsWidgetPrivate::slotStopChanged(QtGradientStop *stop, const QColor &newColor)
+{
+ Q_UNUSED(stop)
+ Q_UNUSED(newColor)
+ q_ptr->viewport()->update();
+}
+
+void QtGradientStopsWidgetPrivate::slotStopSelected(QtGradientStop *stop, bool selected)
+{
+ Q_UNUSED(stop)
+ Q_UNUSED(selected)
+ q_ptr->viewport()->update();
+}
+
+void QtGradientStopsWidgetPrivate::slotCurrentStopChanged(QtGradientStop *stop)
+{
+ Q_UNUSED(stop)
+
+ if (!m_model)
+ return;
+ q_ptr->viewport()->update();
+ if (stop) {
+ m_stops.removeAll(stop);
+ m_stops.prepend(stop);
+ }
+}
+
+void QtGradientStopsWidgetPrivate::slotNewStop()
+{
+ if (!m_model)
+ return;
+
+ QtGradientStop *stop = newStop(m_clickPos);
+
+ if (!stop)
+ return;
+
+ m_model->clearSelection();
+ m_model->selectStop(stop, true);
+ m_model->setCurrentStop(stop);
+}
+
+void QtGradientStopsWidgetPrivate::slotDelete()
+{
+ if (!m_model)
+ return;
+
+ m_model->deleteStops();
+}
+
+void QtGradientStopsWidgetPrivate::slotFlipAll()
+{
+ if (!m_model)
+ return;
+
+ m_model->flipAll();
+}
+
+void QtGradientStopsWidgetPrivate::slotSelectAll()
+{
+ if (!m_model)
+ return;
+
+ m_model->selectAll();
+}
+
+void QtGradientStopsWidgetPrivate::slotZoomIn()
+{
+ double newZoom = q_ptr->zoom() * 2;
+ if (newZoom > 100)
+ newZoom = 100;
+ if (newZoom == q_ptr->zoom())
+ return;
+
+ q_ptr->setZoom(newZoom);
+ emit q_ptr->zoomChanged(q_ptr->zoom());
+}
+
+void QtGradientStopsWidgetPrivate::slotZoomOut()
+{
+ double newZoom = q_ptr->zoom() / 2;
+ if (newZoom < 1)
+ newZoom = 1;
+ if (newZoom == q_ptr->zoom())
+ return;
+
+ q_ptr->setZoom(newZoom);
+ emit q_ptr->zoomChanged(q_ptr->zoom());
+}
+
+void QtGradientStopsWidgetPrivate::slotResetZoom()
+{
+ if (1 == q_ptr->zoom())
+ return;
+
+ q_ptr->setZoom(1);
+ emit q_ptr->zoomChanged(1);
+}
+
+QtGradientStopsWidget::QtGradientStopsWidget(QWidget *parent)
+ : QAbstractScrollArea(parent), d_ptr(new QtGradientStopsWidgetPrivate)
+{
+ d_ptr->q_ptr = this;
+ d_ptr->m_backgroundCheckered = true;
+ d_ptr->m_model = 0;
+ d_ptr->m_handleSize = 25.0;
+ d_ptr->m_scaleFactor = 1000;
+ d_ptr->m_moving = false;
+ d_ptr->m_zoom = 1;
+ d_ptr->m_rubber = new QRubberBand(QRubberBand::Rectangle, this);
+#ifndef QT_NO_DRAGANDDROP
+ d_ptr->m_dragStop = 0;
+ d_ptr->m_changedStop = 0;
+ d_ptr->m_clonedStop = 0;
+ d_ptr->m_dragModel = 0;
+#endif
+ setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ horizontalScrollBar()->setRange(0, (int)(d_ptr->m_scaleFactor * (d_ptr->m_zoom - 1) + 0.5));
+ horizontalScrollBar()->setPageStep(d_ptr->m_scaleFactor);
+ horizontalScrollBar()->setSingleStep(4);
+ viewport()->setAutoFillBackground(false);
+
+ setAcceptDrops(true);
+
+ setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred));
+}
+
+QtGradientStopsWidget::~QtGradientStopsWidget()
+{
+}
+
+QSize QtGradientStopsWidget::sizeHint() const
+{
+ return QSize(qRound(2 * d_ptr->m_handleSize), qRound(3 * d_ptr->m_handleSize) + horizontalScrollBar()->sizeHint().height());
+}
+
+QSize QtGradientStopsWidget::minimumSizeHint() const
+{
+ return QSize(qRound(2 * d_ptr->m_handleSize), qRound(3 * d_ptr->m_handleSize) + horizontalScrollBar()->minimumSizeHint().height());
+}
+
+void QtGradientStopsWidget::setBackgroundCheckered(bool checkered)
+{
+ if (d_ptr->m_backgroundCheckered == checkered)
+ return;
+ d_ptr->m_backgroundCheckered = checkered;
+ update();
+}
+
+bool QtGradientStopsWidget::isBackgroundCheckered() const
+{
+ return d_ptr->m_backgroundCheckered;
+}
+
+void QtGradientStopsWidget::setGradientStopsModel(QtGradientStopsModel *model)
+{
+ if (d_ptr->m_model == model)
+ return;
+
+ if (d_ptr->m_model) {
+ disconnect(d_ptr->m_model, SIGNAL(stopAdded(QtGradientStop*)),
+ this, SLOT(slotStopAdded(QtGradientStop*)));
+ disconnect(d_ptr->m_model, SIGNAL(stopRemoved(QtGradientStop*)),
+ this, SLOT(slotStopRemoved(QtGradientStop*)));
+ disconnect(d_ptr->m_model, SIGNAL(stopMoved(QtGradientStop*,qreal)),
+ this, SLOT(slotStopMoved(QtGradientStop*,qreal)));
+ disconnect(d_ptr->m_model, SIGNAL(stopsSwapped(QtGradientStop*,QtGradientStop*)),
+ this, SLOT(slotStopsSwapped(QtGradientStop*,QtGradientStop*)));
+ disconnect(d_ptr->m_model, SIGNAL(stopChanged(QtGradientStop*,QColor)),
+ this, SLOT(slotStopChanged(QtGradientStop*,QColor)));
+ disconnect(d_ptr->m_model, SIGNAL(stopSelected(QtGradientStop*,bool)),
+ this, SLOT(slotStopSelected(QtGradientStop*,bool)));
+ disconnect(d_ptr->m_model, SIGNAL(currentStopChanged(QtGradientStop*)),
+ this, SLOT(slotCurrentStopChanged(QtGradientStop*)));
+
+ d_ptr->m_stops.clear();
+ }
+
+ d_ptr->m_model = model;
+
+ if (d_ptr->m_model) {
+ connect(d_ptr->m_model, SIGNAL(stopAdded(QtGradientStop*)),
+ this, SLOT(slotStopAdded(QtGradientStop*)));
+ connect(d_ptr->m_model, SIGNAL(stopRemoved(QtGradientStop*)),
+ this, SLOT(slotStopRemoved(QtGradientStop*)));
+ connect(d_ptr->m_model, SIGNAL(stopMoved(QtGradientStop*,qreal)),
+ this, SLOT(slotStopMoved(QtGradientStop*,qreal)));
+ connect(d_ptr->m_model, SIGNAL(stopsSwapped(QtGradientStop*,QtGradientStop*)),
+ this, SLOT(slotStopsSwapped(QtGradientStop*,QtGradientStop*)));
+ connect(d_ptr->m_model, SIGNAL(stopChanged(QtGradientStop*,QColor)),
+ this, SLOT(slotStopChanged(QtGradientStop*,QColor)));
+ connect(d_ptr->m_model, SIGNAL(stopSelected(QtGradientStop*,bool)),
+ this, SLOT(slotStopSelected(QtGradientStop*,bool)));
+ connect(d_ptr->m_model, SIGNAL(currentStopChanged(QtGradientStop*)),
+ this, SLOT(slotCurrentStopChanged(QtGradientStop*)));
+
+ QList<QtGradientStop *> stops = d_ptr->m_model->stops().values();
+ QListIterator<QtGradientStop *> itStop(stops);
+ while (itStop.hasNext())
+ d_ptr->slotStopAdded(itStop.next());
+
+ QList<QtGradientStop *> selected = d_ptr->m_model->selectedStops();
+ QListIterator<QtGradientStop *> itSelect(selected);
+ while (itSelect.hasNext())
+ d_ptr->slotStopSelected(itSelect.next(), true);
+
+ d_ptr->slotCurrentStopChanged(d_ptr->m_model->currentStop());
+ }
+}
+
+void QtGradientStopsWidget::mousePressEvent(QMouseEvent *e)
+{
+ typedef QtGradientStopsModel::PositionStopMap PositionStopMap;
+ if (!d_ptr->m_model)
+ return;
+
+ if (e->button() != Qt::LeftButton)
+ return;
+
+ d_ptr->m_moving = true;
+
+ d_ptr->m_moveStops.clear();
+ d_ptr->m_moveOriginal.clear();
+ d_ptr->m_clickPos = e->pos();
+ QtGradientStop *stop = d_ptr->stopAt(e->pos());
+ if (stop) {
+ if (e->modifiers() & Qt::ControlModifier) {
+ d_ptr->m_model->selectStop(stop, !d_ptr->m_model->isSelected(stop));
+ } else if (e->modifiers() & Qt::ShiftModifier) {
+ QtGradientStop *oldCurrent = d_ptr->m_model->currentStop();
+ if (oldCurrent) {
+ PositionStopMap stops = d_ptr->m_model->stops();
+ PositionStopMap::ConstIterator itSt = stops.constFind(oldCurrent->position());
+ if (itSt != stops.constEnd()) {
+ while (itSt != stops.constFind(stop->position())) {
+ d_ptr->m_model->selectStop(itSt.value(), true);
+ if (oldCurrent->position() < stop->position())
+ ++itSt;
+ else
+ --itSt;
+ }
+ }
+ }
+ d_ptr->m_model->selectStop(stop, true);
+ } else {
+ if (!d_ptr->m_model->isSelected(stop)) {
+ d_ptr->m_model->clearSelection();
+ d_ptr->m_model->selectStop(stop, true);
+ }
+ }
+ d_ptr->setupMove(stop, e->pos().x());
+ } else {
+ d_ptr->m_model->clearSelection();
+ d_ptr->m_rubber->setGeometry(QRect(d_ptr->m_clickPos, QSize()));
+ d_ptr->m_rubber->show();
+ }
+ viewport()->update();
+}
+
+void QtGradientStopsWidget::mouseReleaseEvent(QMouseEvent *e)
+{
+ if (!d_ptr->m_model)
+ return;
+
+ if (e->button() != Qt::LeftButton)
+ return;
+
+ d_ptr->m_moving = false;
+ d_ptr->m_rubber->hide();
+ d_ptr->m_moveStops.clear();
+ d_ptr->m_moveOriginal.clear();
+}
+
+void QtGradientStopsWidget::mouseMoveEvent(QMouseEvent *e)
+{
+ typedef QtGradientStopsWidgetPrivate::PositionColorMap PositionColorMap;
+ typedef QtGradientStopsModel::PositionStopMap PositionStopMap;
+ typedef QtGradientStopsWidgetPrivate::StopPositionMap StopPositionMap;
+ if (!d_ptr->m_model)
+ return;
+
+ if (!(e->buttons() & Qt::LeftButton))
+ return;
+
+ if (!d_ptr->m_moving)
+ return;
+
+ if (!d_ptr->m_moveStops.isEmpty()) {
+ double maxOffset = 0.0;
+ double minOffset = 0.0;
+ bool first = true;
+ StopPositionMap::ConstIterator itStop = d_ptr->m_moveStops.constBegin();
+ while (itStop != d_ptr->m_moveStops.constEnd()) {
+ double offset = itStop.value();
+
+ if (first) {
+ maxOffset = offset;
+ minOffset = offset;
+ first = false;
+ } else {
+ if (maxOffset < offset)
+ maxOffset = offset;
+ else if (minOffset > offset)
+ minOffset = offset;
+ }
+ ++itStop;
+ }
+
+ double viewportMin = d_ptr->toViewport(-minOffset);
+ double viewportMax = d_ptr->toViewport(1.0 - maxOffset);
+
+ PositionStopMap newPositions;
+
+ int viewportX = e->pos().x() - d_ptr->m_moveOffset;
+
+ if (viewportX > viewport()->size().width())
+ viewportX = viewport()->size().width();
+ else if (viewportX < 0)
+ viewportX = 0;
+
+ double posX = d_ptr->fromViewport(viewportX);
+
+ if (viewportX > viewportMax)
+ posX = 1.0 - maxOffset;
+ else if (viewportX < viewportMin)
+ posX = -minOffset;
+
+ itStop = d_ptr->m_moveStops.constBegin();
+ while (itStop != d_ptr->m_moveStops.constEnd()) {
+ QtGradientStop *stop = itStop.key();
+
+ newPositions[posX + itStop.value()] = stop;
+
+ ++itStop;
+ }
+
+ bool forward = true;
+ PositionStopMap::ConstIterator itNewPos = newPositions.constBegin();
+ if (itNewPos.value()->position() < itNewPos.key())
+ forward = false;
+
+ itNewPos = forward ? newPositions.constBegin() : newPositions.constEnd();
+ while (itNewPos != (forward ? newPositions.constEnd() : newPositions.constBegin())) {
+ if (!forward)
+ --itNewPos;
+ QtGradientStop *stop = itNewPos.value();
+ double newPos = itNewPos.key();
+ if (newPos > 1)
+ newPos = 1;
+ else if (newPos < 0)
+ newPos = 0;
+
+ QtGradientStop *existingStop = d_ptr->m_model->at(newPos);
+ if (existingStop && !d_ptr->m_moveStops.contains(existingStop))
+ d_ptr->m_model->removeStop(existingStop);
+ d_ptr->m_model->moveStop(stop, newPos);
+
+ if (forward)
+ ++itNewPos;
+ }
+
+ PositionColorMap::ConstIterator itOld = d_ptr->m_moveOriginal.constBegin();
+ while (itOld != d_ptr->m_moveOriginal.constEnd()) {
+ double position = itOld.key();
+ if (!d_ptr->m_model->at(position))
+ d_ptr->m_model->addStop(position, itOld.value());
+
+ ++itOld;
+ }
+
+ } else {
+ QRect r(QRect(d_ptr->m_clickPos, e->pos()).normalized());
+ r.translate(1, 0);
+ d_ptr->m_rubber->setGeometry(r);
+ //d_ptr->m_model->clearSelection();
+
+ int xv1 = d_ptr->m_clickPos.x();
+ int xv2 = e->pos().x();
+ if (xv1 > xv2) {
+ int temp = xv1;
+ xv1 = xv2;
+ xv2 = temp;
+ }
+ int yv1 = d_ptr->m_clickPos.y();
+ int yv2 = e->pos().y();
+ if (yv1 > yv2) {
+ int temp = yv1;
+ yv1 = yv2;
+ yv2 = temp;
+ }
+
+ QPoint p1, p2;
+
+ if (yv2 < d_ptr->m_handleSize / 2) {
+ p1 = QPoint(xv1, yv2);
+ p2 = QPoint(xv2, yv2);
+ } else if (yv1 > d_ptr->m_handleSize / 2) {
+ p1 = QPoint(xv1, yv1);
+ p2 = QPoint(xv2, yv1);
+ } else {
+ p1 = QPoint(xv1, qRound(d_ptr->m_handleSize / 2));
+ p2 = QPoint(xv2, qRound(d_ptr->m_handleSize / 2));
+ }
+
+ QList<QtGradientStop *> beginList = d_ptr->stopsAt(p1);
+ QList<QtGradientStop *> endList = d_ptr->stopsAt(p2);
+
+ double x1 = d_ptr->fromViewport(xv1);
+ double x2 = d_ptr->fromViewport(xv2);
+
+ QListIterator<QtGradientStop *> itStop(d_ptr->m_stops);
+ while (itStop.hasNext()) {
+ QtGradientStop *stop = itStop.next();
+ if ((stop->position() >= x1 && stop->position() <= x2) ||
+ beginList.contains(stop) || endList.contains(stop))
+ d_ptr->m_model->selectStop(stop, true);
+ else
+ d_ptr->m_model->selectStop(stop, false);
+ }
+ }
+}
+
+void QtGradientStopsWidget::mouseDoubleClickEvent(QMouseEvent *e)
+{
+ if (!d_ptr->m_model)
+ return;
+
+ if (e->button() != Qt::LeftButton)
+ return;
+
+ if (d_ptr->m_clickPos != e->pos()) {
+ mousePressEvent(e);
+ return;
+ }
+ d_ptr->m_moving = true;
+ d_ptr->m_moveStops.clear();
+ d_ptr->m_moveOriginal.clear();
+
+ QtGradientStop *stop = d_ptr->newStop(e->pos());
+
+ if (!stop)
+ return;
+
+ d_ptr->m_model->clearSelection();
+ d_ptr->m_model->selectStop(stop, true);
+
+ d_ptr->setupMove(stop, e->pos().x());
+
+ viewport()->update();
+}
+
+void QtGradientStopsWidget::keyPressEvent(QKeyEvent *e)
+{
+ typedef QtGradientStopsModel::PositionStopMap PositionStopMap;
+ if (!d_ptr->m_model)
+ return;
+
+ if (e->key() == Qt::Key_Delete || e->key() == Qt::Key_Backspace) {
+ d_ptr->m_model->deleteStops();
+ } else if (e->key() == Qt::Key_Left || e->key() == Qt::Key_Right ||
+ e->key() == Qt::Key_Home || e->key() == Qt::Key_End) {
+ PositionStopMap stops = d_ptr->m_model->stops();
+ if (stops.isEmpty())
+ return;
+ QtGradientStop *newCurrent = 0;
+ QtGradientStop *current = d_ptr->m_model->currentStop();
+ if (!current || e->key() == Qt::Key_Home || e->key() == Qt::Key_End) {
+ if (e->key() == Qt::Key_Left || e->key() == Qt::Key_Home)
+ newCurrent = stops.constBegin().value();
+ else if (e->key() == Qt::Key_Right || e->key() == Qt::Key_End)
+ newCurrent = (--stops.constEnd()).value();
+ } else {
+ PositionStopMap::ConstIterator itStop = stops.constBegin();
+ while (itStop.value() != current)
+ ++itStop;
+ if (e->key() == Qt::Key_Left && itStop != stops.constBegin())
+ --itStop;
+ else if (e->key() == Qt::Key_Right && itStop != --stops.constEnd())
+ ++itStop;
+ newCurrent = itStop.value();
+ }
+ d_ptr->m_model->clearSelection();
+ d_ptr->m_model->selectStop(newCurrent, true);
+ d_ptr->m_model->setCurrentStop(newCurrent);
+ d_ptr->ensureVisible(newCurrent);
+ } else if (e->key() == Qt::Key_A) {
+ if (e->modifiers() & Qt::ControlModifier)
+ d_ptr->m_model->selectAll();
+ }
+}
+
+void QtGradientStopsWidget::paintEvent(QPaintEvent *e)
+{
+ Q_UNUSED(e)
+ if (!d_ptr->m_model)
+ return;
+
+ QtGradientStopsModel *model = d_ptr->m_model;
+#ifndef QT_NO_DRAGANDDROP
+ if (d_ptr->m_dragModel)
+ model = d_ptr->m_dragModel;
+#endif
+
+ QSize size = viewport()->size();
+ int w = size.width();
+ double h = size.height() - d_ptr->m_handleSize;
+ if (w <= 0)
+ return;
+
+ QPixmap pix(size);
+ QPainter p;
+
+ if (d_ptr->m_backgroundCheckered) {
+ int pixSize = 20;
+ QPixmap pm(2 * pixSize, 2 * pixSize);
+ QPainter pmp(&pm);
+ pmp.fillRect(0, 0, pixSize, pixSize, Qt::white);
+ pmp.fillRect(pixSize, pixSize, pixSize, pixSize, Qt::white);
+ pmp.fillRect(0, pixSize, pixSize, pixSize, Qt::black);
+ pmp.fillRect(pixSize, 0, pixSize, pixSize, Qt::black);
+
+ p.begin(&pix);
+ p.setBrushOrigin((size.width() % pixSize + pixSize) / 2, (size.height() % pixSize + pixSize) / 2);
+ p.fillRect(viewport()->rect(), pm);
+ p.setBrushOrigin(0, 0);
+ } else {
+ p.begin(viewport());
+ }
+
+ double viewBegin = (double)w * horizontalScrollBar()->value() / d_ptr->m_scaleFactor;
+
+ int val = horizontalScrollBar()->value();
+ int max = horizontalScrollBar()->maximum();
+
+ double begin = (double)val / (d_ptr->m_scaleFactor + max);
+ double end = (double)(val + d_ptr->m_scaleFactor) / (d_ptr->m_scaleFactor + max);
+ double width = end - begin;
+
+ if (h > 0) {
+ QLinearGradient lg(0, 0, w, 0);
+ QMap<qreal, QtGradientStop *> stops = model->stops();
+ QMapIterator<qreal, QtGradientStop *> itStop(stops);
+ while (itStop.hasNext()) {
+ QtGradientStop *stop = itStop.next().value();
+ double pos = stop->position();
+ if (pos >= begin && pos <= end) {
+ double gradPos = (pos - begin) / width;
+ QColor c = stop->color();
+ lg.setColorAt(gradPos, c);
+ }
+ //lg.setColorAt(stop->position(), stop->color());
+ }
+ lg.setColorAt(0, model->color(begin));
+ lg.setColorAt(1, model->color(end));
+ QImage img(w, 1, QImage::Format_ARGB32_Premultiplied);
+ QPainter p1(&img);
+ p1.setCompositionMode(QPainter::CompositionMode_Source);
+
+ /*
+ if (viewBegin != 0)
+ p1.translate(-viewBegin, 0);
+ if (d_ptr->m_zoom != 1)
+ p1.scale(d_ptr->m_zoom, 1);
+ */
+ p1.fillRect(0, 0, w, 1, lg);
+
+ p.fillRect(QRectF(0, d_ptr->m_handleSize, w, h), QPixmap::fromImage(img));
+ }
+
+
+ double handleWidth = d_ptr->m_handleSize * d_ptr->m_scaleFactor / (w * (d_ptr->m_scaleFactor + max));
+
+ QColor insideColor = QColor::fromRgb(0x20, 0x20, 0x20, 0xFF);
+ QColor borderColor = QColor(Qt::white);
+ QColor drawColor;
+ QColor back1 = QColor(Qt::lightGray);
+ QColor back2 = QColor(Qt::darkGray);
+ QColor back = QColor::fromRgb((back1.red() + back2.red()) / 2,
+ (back1.green() + back2.green()) / 2,
+ (back1.blue() + back2.blue()) / 2);
+
+ QPen pen;
+ p.setRenderHint(QPainter::Antialiasing);
+ QListIterator<QtGradientStop *> itStop(d_ptr->m_stops);
+ itStop.toBack();
+ while (itStop.hasPrevious()) {
+ QtGradientStop *stop = itStop.previous();
+ double x = stop->position();
+ if (x >= begin - handleWidth / 2 && x <= end + handleWidth / 2) {
+ double viewX = x * w * (d_ptr->m_scaleFactor + max) / d_ptr->m_scaleFactor - viewBegin;
+ p.save();
+ QColor c = stop->color();
+#ifndef QT_NO_DRAGANDDROP
+ if (stop == d_ptr->m_dragStop)
+ c = d_ptr->m_dragColor;
+#endif
+ if ((0.3 * c.redF() + 0.59 * c.greenF() + 0.11 * c.blueF()) * c.alphaF() +
+ (0.3 * back.redF() + 0.59 * back.greenF() + 0.11 * back.blueF()) * (1.0 - c.alphaF()) < 0.5) {
+ drawColor = QColor::fromRgb(0xC0, 0xC0, 0xC0, 0xB0);
+ } else {
+ drawColor = QColor::fromRgb(0x40, 0x40, 0x40, 0x80);
+ }
+ QRectF rect(viewX - d_ptr->m_handleSize / 2, 0, d_ptr->m_handleSize, d_ptr->m_handleSize);
+ rect.adjust(0.5, 0.5, -0.5, -0.5);
+ if (h > 0) {
+ pen.setWidthF(1);
+ QLinearGradient lg(0, d_ptr->m_handleSize, 0, d_ptr->m_handleSize + h / 2);
+ lg.setColorAt(0, drawColor);
+ QColor alphaZero = drawColor;
+ alphaZero.setAlpha(0);
+ lg.setColorAt(1, alphaZero);
+ pen.setBrush(lg);
+ p.setPen(pen);
+ p.drawLine(QPointF(viewX, d_ptr->m_handleSize), QPointF(viewX, d_ptr->m_handleSize + h / 2));
+
+ pen.setWidthF(1);
+ pen.setBrush(drawColor);
+ p.setPen(pen);
+ QRectF r1 = rect.adjusted(0.5, 0.5, -0.5, -0.5);
+ QRectF r2 = rect.adjusted(1.5, 1.5, -1.5, -1.5);
+ QColor inColor = QColor::fromRgb(0x80, 0x80, 0x80, 0x80);
+ if (!d_ptr->m_model->isSelected(stop)) {
+ p.setBrush(c);
+ p.drawEllipse(rect);
+ } else {
+ pen.setBrush(insideColor);
+ pen.setWidthF(2);
+ p.setPen(pen);
+ p.setBrush(Qt::NoBrush);
+ p.drawEllipse(r1);
+
+ pen.setBrush(inColor);
+ pen.setWidthF(1);
+ p.setPen(pen);
+ p.setBrush(c);
+ p.drawEllipse(r2);
+ }
+
+ if (d_ptr->m_model->currentStop() == stop) {
+ p.setBrush(Qt::NoBrush);
+ pen.setWidthF(5);
+ pen.setBrush(drawColor);
+ int corr = 4;
+ if (!d_ptr->m_model->isSelected(stop)) {
+ corr = 3;
+ pen.setWidthF(7);
+ }
+ p.setPen(pen);
+ p.drawEllipse(rect.adjusted(corr, corr, -corr, -corr));
+ }
+
+ }
+ p.restore();
+ }
+ }
+ if (d_ptr->m_backgroundCheckered) {
+ p.end();
+ p.begin(viewport());
+ p.drawPixmap(0, 0, pix);
+ }
+ p.end();
+}
+
+void QtGradientStopsWidget::focusInEvent(QFocusEvent *e)
+{
+ Q_UNUSED(e)
+ viewport()->update();
+}
+
+void QtGradientStopsWidget::focusOutEvent(QFocusEvent *e)
+{
+ Q_UNUSED(e)
+ viewport()->update();
+}
+
+void QtGradientStopsWidget::contextMenuEvent(QContextMenuEvent *e)
+{
+ if (!d_ptr->m_model)
+ return;
+
+ d_ptr->m_clickPos = e->pos();
+
+ QMenu menu(this);
+ QAction *newStopAction = new QAction(tr("New Stop"), &menu);
+ QAction *deleteAction = new QAction(tr("Delete"), &menu);
+ QAction *flipAllAction = new QAction(tr("Flip All"), &menu);
+ QAction *selectAllAction = new QAction(tr("Select All"), &menu);
+ QAction *zoomInAction = new QAction(tr("Zoom In"), &menu);
+ QAction *zoomOutAction = new QAction(tr("Zoom Out"), &menu);
+ QAction *zoomAllAction = new QAction(tr("Reset Zoom"), &menu);
+ if (d_ptr->m_model->selectedStops().isEmpty() && !d_ptr->m_model->currentStop())
+ deleteAction->setEnabled(false);
+ if (zoom() <= 1) {
+ zoomOutAction->setEnabled(false);
+ zoomAllAction->setEnabled(false);
+ } else if (zoom() >= 100) {
+ zoomInAction->setEnabled(false);
+ }
+ connect(newStopAction, SIGNAL(triggered()), this, SLOT(slotNewStop()));
+ connect(deleteAction, SIGNAL(triggered()), this, SLOT(slotDelete()));
+ connect(flipAllAction, SIGNAL(triggered()), this, SLOT(slotFlipAll()));
+ connect(selectAllAction, SIGNAL(triggered()), this, SLOT(slotSelectAll()));
+ connect(zoomInAction, SIGNAL(triggered()), this, SLOT(slotZoomIn()));
+ connect(zoomOutAction, SIGNAL(triggered()), this, SLOT(slotZoomOut()));
+ connect(zoomAllAction, SIGNAL(triggered()), this, SLOT(slotResetZoom()));
+ menu.addAction(newStopAction);
+ menu.addAction(deleteAction);
+ menu.addAction(flipAllAction);
+ menu.addAction(selectAllAction);
+ menu.addSeparator();
+ menu.addAction(zoomInAction);
+ menu.addAction(zoomOutAction);
+ menu.addAction(zoomAllAction);
+ menu.exec(e->globalPos());
+}
+
+void QtGradientStopsWidget::wheelEvent(QWheelEvent *e)
+{
+ int numDegrees = e->delta() / 8;
+ int numSteps = numDegrees / 15;
+
+ int shift = numSteps;
+ if (shift < 0)
+ shift = -shift;
+ int pow = 1 << shift;
+ //const double c = 0.7071067; // 2 steps per doubled value
+ const double c = 0.5946036; // 4 steps pre doubled value
+ // in general c = pow(2, 1 / n) / 2; where n is the step
+ double factor = pow * c;
+
+ double newZoom = zoom();
+ if (numSteps < 0)
+ newZoom /= factor;
+ else
+ newZoom *= factor;
+ if (newZoom > 100)
+ newZoom = 100;
+ if (newZoom < 1)
+ newZoom = 1;
+
+ if (newZoom == zoom())
+ return;
+
+ setZoom(newZoom);
+ emit zoomChanged(zoom());
+}
+
+#ifndef QT_NO_DRAGANDDROP
+void QtGradientStopsWidget::dragEnterEvent(QDragEnterEvent *event)
+{
+ const QMimeData *mime = event->mimeData();
+ if (!mime->hasColor())
+ return;
+ event->accept();
+ d_ptr->m_dragModel = d_ptr->m_model->clone();
+
+ d_ptr->m_dragColor = qvariant_cast<QColor>(mime->colorData());
+ update();
+}
+
+void QtGradientStopsWidget::dragMoveEvent(QDragMoveEvent *event)
+{
+ QRectF rect = viewport()->rect();
+ rect.adjust(0, d_ptr->m_handleSize, 0, 0);
+ double x = d_ptr->fromViewport(event->pos().x());
+ QtGradientStop *dragStop = d_ptr->stopAt(event->pos());
+ if (dragStop) {
+ event->accept();
+ d_ptr->removeClonedStop();
+ d_ptr->changeStop(dragStop->position());
+ } else if (rect.contains(event->pos())) {
+ event->accept();
+ if (d_ptr->m_model->at(x)) {
+ d_ptr->removeClonedStop();
+ d_ptr->changeStop(x);
+ } else {
+ d_ptr->restoreChangedStop();
+ d_ptr->cloneStop(x);
+ }
+ } else {
+ event->ignore();
+ d_ptr->removeClonedStop();
+ d_ptr->restoreChangedStop();
+ }
+
+ update();
+}
+
+void QtGradientStopsWidget::dragLeaveEvent(QDragLeaveEvent *event)
+{
+ event->accept();
+ d_ptr->clearDrag();
+ update();
+}
+
+void QtGradientStopsWidget::dropEvent(QDropEvent *event)
+{
+ event->accept();
+ if (!d_ptr->m_dragModel)
+ return;
+
+ if (d_ptr->m_changedStop)
+ d_ptr->m_model->changeStop(d_ptr->m_model->at(d_ptr->m_changedStop->position()), d_ptr->m_dragColor);
+ else if (d_ptr->m_clonedStop)
+ d_ptr->m_model->addStop(d_ptr->m_clonedStop->position(), d_ptr->m_dragColor);
+
+ d_ptr->clearDrag();
+ update();
+}
+
+void QtGradientStopsWidgetPrivate::clearDrag()
+{
+ removeClonedStop();
+ restoreChangedStop();
+ delete m_dragModel;
+ m_dragModel = 0;
+}
+
+void QtGradientStopsWidgetPrivate::removeClonedStop()
+{
+ if (!m_clonedStop)
+ return;
+ m_dragModel->removeStop(m_clonedStop);
+ m_clonedStop = 0;
+}
+
+void QtGradientStopsWidgetPrivate::restoreChangedStop()
+{
+ if (!m_changedStop)
+ return;
+ m_dragModel->changeStop(m_changedStop, m_model->at(m_changedStop->position())->color());
+ m_changedStop = 0;
+ m_dragStop = 0;
+}
+
+void QtGradientStopsWidgetPrivate::changeStop(qreal pos)
+{
+ QtGradientStop *stop = m_dragModel->at(pos);
+ if (!stop)
+ return;
+
+ m_dragModel->changeStop(stop, m_dragColor);
+ m_changedStop = stop;
+ m_dragStop = m_model->at(stop->position());
+}
+
+void QtGradientStopsWidgetPrivate::cloneStop(qreal pos)
+{
+ if (m_clonedStop) {
+ m_dragModel->moveStop(m_clonedStop, pos);
+ return;
+ }
+ QtGradientStop *stop = m_dragModel->at(pos);
+ if (stop)
+ return;
+
+ m_clonedStop = m_dragModel->addStop(pos, m_dragColor);
+}
+
+#endif
+
+void QtGradientStopsWidget::setZoom(double zoom)
+{
+ double z = zoom;
+ if (z < 1)
+ z = 1;
+ else if (z > 100)
+ z = 100;
+
+ if (d_ptr->m_zoom == z)
+ return;
+
+ d_ptr->m_zoom = z;
+ int oldMax = horizontalScrollBar()->maximum();
+ int oldVal = horizontalScrollBar()->value();
+ horizontalScrollBar()->setRange(0, qRound(d_ptr->m_scaleFactor * (d_ptr->m_zoom - 1)));
+ int newMax = horizontalScrollBar()->maximum();
+ double newVal = (oldVal + (double)d_ptr->m_scaleFactor / 2) * (newMax + d_ptr->m_scaleFactor)
+ / (oldMax + d_ptr->m_scaleFactor) - (double)d_ptr->m_scaleFactor / 2;
+ horizontalScrollBar()->setValue(qRound(newVal));
+ viewport()->update();
+}
+
+double QtGradientStopsWidget::zoom() const
+{
+ return d_ptr->m_zoom;
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qtgradientstopswidget.cpp"
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientstopswidget.h b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientstopswidget.h
new file mode 100644
index 0000000000..8260b3c9e9
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientstopswidget.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTGRADIENTSTOPSWIDGET_H
+#define QTGRADIENTSTOPSWIDGET_H
+
+#include <QtGui/QAbstractScrollArea>
+
+QT_BEGIN_NAMESPACE
+
+class QtGradientStopsModel;
+class QtGradientStopsWidgetPrivate;
+
+class QtGradientStopsWidget : public QAbstractScrollArea
+{
+ Q_OBJECT
+ Q_PROPERTY(bool backgroundCheckered READ isBackgroundCheckered WRITE setBackgroundCheckered)
+public:
+ QtGradientStopsWidget(QWidget *parent = 0);
+ ~QtGradientStopsWidget();
+
+ QSize minimumSizeHint() const;
+ QSize sizeHint() const;
+
+ bool isBackgroundCheckered() const;
+ void setBackgroundCheckered(bool checkered);
+
+ void setGradientStopsModel(QtGradientStopsModel *model);
+
+ void setZoom(double zoom);
+ double zoom() const;
+
+signals:
+
+ void zoomChanged(double zoom);
+
+protected:
+ void paintEvent(QPaintEvent *e);
+ void mousePressEvent(QMouseEvent *e);
+ void mouseReleaseEvent(QMouseEvent *e);
+ void mouseMoveEvent(QMouseEvent *e);
+ void mouseDoubleClickEvent(QMouseEvent *e);
+ void keyPressEvent(QKeyEvent *e);
+ void focusInEvent(QFocusEvent *e);
+ void focusOutEvent(QFocusEvent *e);
+ void contextMenuEvent(QContextMenuEvent *e);
+ void wheelEvent(QWheelEvent *e);
+#ifndef QT_NO_DRAGANDDROP
+ void dragEnterEvent(QDragEnterEvent *event);
+ void dragMoveEvent(QDragMoveEvent *event);
+ void dragLeaveEvent(QDragLeaveEvent *event);
+ void dropEvent(QDropEvent *event);
+#endif
+
+private:
+ QScopedPointer<QtGradientStopsWidgetPrivate> d_ptr;
+ Q_DECLARE_PRIVATE(QtGradientStopsWidget)
+ Q_DISABLE_COPY(QtGradientStopsWidget)
+ Q_PRIVATE_SLOT(d_func(), void slotStopAdded(QtGradientStop *stop))
+ Q_PRIVATE_SLOT(d_func(), void slotStopRemoved(QtGradientStop *stop))
+ Q_PRIVATE_SLOT(d_func(), void slotStopMoved(QtGradientStop *stop, qreal newPos))
+ Q_PRIVATE_SLOT(d_func(), void slotStopsSwapped(QtGradientStop *stop1, QtGradientStop *stop2))
+ Q_PRIVATE_SLOT(d_func(), void slotStopChanged(QtGradientStop *stop, const QColor &newColor))
+ Q_PRIVATE_SLOT(d_func(), void slotStopSelected(QtGradientStop *stop, bool selected))
+ Q_PRIVATE_SLOT(d_func(), void slotCurrentStopChanged(QtGradientStop *stop))
+ Q_PRIVATE_SLOT(d_func(), void slotNewStop())
+ Q_PRIVATE_SLOT(d_func(), void slotDelete())
+ Q_PRIVATE_SLOT(d_func(), void slotFlipAll())
+ Q_PRIVATE_SLOT(d_func(), void slotSelectAll())
+ Q_PRIVATE_SLOT(d_func(), void slotZoomIn())
+ Q_PRIVATE_SLOT(d_func(), void slotZoomOut())
+ Q_PRIVATE_SLOT(d_func(), void slotResetZoom())
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientutils.cpp b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientutils.cpp
new file mode 100644
index 0000000000..dec53332a3
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientutils.cpp
@@ -0,0 +1,420 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtgradientutils.h"
+#include "qtgradientmanager.h"
+#include <QtGui/QLinearGradient>
+#include <QtGui/QRadialGradient>
+#include <QtGui/QConicalGradient>
+#include <QtXml/QDomDocument>
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+static QString gradientTypeToString(QGradient::Type type)
+{
+ if (type == QGradient::LinearGradient)
+ return QLatin1String("LinearGradient");
+ if (type == QGradient::RadialGradient)
+ return QLatin1String("RadialGradient");
+ if (type == QGradient::ConicalGradient)
+ return QLatin1String("ConicalGradient");
+ return QLatin1String("NoGradient");
+}
+
+static QGradient::Type stringToGradientType(const QString &name)
+{
+ if (name == QLatin1String("LinearGradient"))
+ return QGradient::LinearGradient;
+ if (name == QLatin1String("RadialGradient"))
+ return QGradient::RadialGradient;
+ if (name == QLatin1String("ConicalGradient"))
+ return QGradient::ConicalGradient;
+ return QGradient::NoGradient;
+}
+
+static QString gradientSpreadToString(QGradient::Spread spread)
+{
+ if (spread == QGradient::PadSpread)
+ return QLatin1String("PadSpread");
+ if (spread == QGradient::RepeatSpread)
+ return QLatin1String("RepeatSpread");
+ if (spread == QGradient::ReflectSpread)
+ return QLatin1String("ReflectSpread");
+ return QLatin1String("PadSpread");
+}
+
+static QGradient::Spread stringToGradientSpread(const QString &name)
+{
+ if (name == QLatin1String("PadSpread"))
+ return QGradient::PadSpread;
+ if (name == QLatin1String("RepeatSpread"))
+ return QGradient::RepeatSpread;
+ if (name == QLatin1String("ReflectSpread"))
+ return QGradient::ReflectSpread;
+ return QGradient::PadSpread;
+}
+
+static QString gradientCoordinateModeToString(QGradient::CoordinateMode mode)
+{
+ if (mode == QGradient::LogicalMode)
+ return QLatin1String("LogicalMode");
+ if (mode == QGradient::StretchToDeviceMode)
+ return QLatin1String("StretchToDeviceMode");
+ if (mode == QGradient::ObjectBoundingMode)
+ return QLatin1String("ObjectBoundingMode");
+ return QLatin1String("StretchToDeviceMode");
+}
+
+static QGradient::CoordinateMode stringToGradientCoordinateMode(const QString &name)
+{
+ if (name == QLatin1String("LogicalMode"))
+ return QGradient::LogicalMode;
+ if (name == QLatin1String("StretchToDeviceMode"))
+ return QGradient::StretchToDeviceMode;
+ if (name == QLatin1String("ObjectBoundingMode"))
+ return QGradient::ObjectBoundingMode;
+ return QGradient::StretchToDeviceMode;
+}
+
+static QDomElement saveColor(QDomDocument &doc, const QColor &color)
+{
+ QDomElement colorElem = doc.createElement(QLatin1String("colorData"));
+
+ colorElem.setAttribute(QLatin1String("r"), QString::number(color.red()));
+ colorElem.setAttribute(QLatin1String("g"), QString::number(color.green()));
+ colorElem.setAttribute(QLatin1String("b"), QString::number(color.blue()));
+ colorElem.setAttribute(QLatin1String("a"), QString::number(color.alpha()));
+
+ return colorElem;
+}
+
+static QDomElement saveGradientStop(QDomDocument &doc, const QGradientStop &stop)
+{
+ QDomElement stopElem = doc.createElement(QLatin1String("stopData"));
+
+ stopElem.setAttribute(QLatin1String("position"), QString::number(stop.first));
+
+ const QDomElement colorElem = saveColor(doc, stop.second);
+ stopElem.appendChild(colorElem);
+
+ return stopElem;
+}
+
+static QDomElement saveGradient(QDomDocument &doc, const QGradient &gradient)
+{
+ QDomElement gradElem = doc.createElement(QLatin1String("gradientData"));
+
+ const QGradient::Type type = gradient.type();
+ gradElem.setAttribute(QLatin1String("type"), gradientTypeToString(type));
+ gradElem.setAttribute(QLatin1String("spread"), gradientSpreadToString(gradient.spread()));
+ gradElem.setAttribute(QLatin1String("coordinateMode"), gradientCoordinateModeToString(gradient.coordinateMode()));
+
+ QGradientStops stops = gradient.stops();
+ QVectorIterator<QGradientStop > it(stops);
+ while (it.hasNext())
+ gradElem.appendChild(saveGradientStop(doc, it.next()));
+
+ if (type == QGradient::LinearGradient) {
+ const QLinearGradient &g = *static_cast<const QLinearGradient *>(&gradient);
+ gradElem.setAttribute(QLatin1String("startX"), QString::number(g.start().x()));
+ gradElem.setAttribute(QLatin1String("startY"), QString::number(g.start().y()));
+ gradElem.setAttribute(QLatin1String("endX"), QString::number(g.finalStop().x()));
+ gradElem.setAttribute(QLatin1String("endY"), QString::number(g.finalStop().y()));
+ } else if (type == QGradient::RadialGradient) {
+ const QRadialGradient &g = *static_cast<const QRadialGradient *>(&gradient);
+ gradElem.setAttribute(QLatin1String("centerX"), QString::number(g.center().x()));
+ gradElem.setAttribute(QLatin1String("centerY"), QString::number(g.center().y()));
+ gradElem.setAttribute(QLatin1String("focalX"), QString::number(g.focalPoint().x()));
+ gradElem.setAttribute(QLatin1String("focalY"), QString::number(g.focalPoint().y()));
+ gradElem.setAttribute(QLatin1String("radius"), QString::number(g.radius()));
+ } else if (type == QGradient::ConicalGradient) {
+ const QConicalGradient &g = *static_cast<const QConicalGradient*>(&gradient);
+ gradElem.setAttribute(QLatin1String("centerX"), QString::number(g.center().x()));
+ gradElem.setAttribute(QLatin1String("centerY"), QString::number(g.center().y()));
+ gradElem.setAttribute(QLatin1String("angle"), QString::number(g.angle()));
+ }
+
+ return gradElem;
+}
+
+static QColor loadColor(const QDomElement &elem)
+{
+ if (elem.tagName() != QLatin1String("colorData"))
+ return QColor();
+
+ return QColor(elem.attribute(QLatin1String("r")).toInt(),
+ elem.attribute(QLatin1String("g")).toInt(),
+ elem.attribute(QLatin1String("b")).toInt(),
+ elem.attribute(QLatin1String("a")).toInt());
+}
+
+static QGradientStop loadGradientStop(const QDomElement &elem)
+{
+ if (elem.tagName() != QLatin1String("stopData"))
+ return QGradientStop();
+
+ const qreal pos = static_cast<qreal>(elem.attribute(QLatin1String("position")).toDouble());
+ return qMakePair(pos, loadColor(elem.firstChild().toElement()));
+}
+
+static QGradient loadGradient(const QDomElement &elem)
+{
+ if (elem.tagName() != QLatin1String("gradientData"))
+ return QLinearGradient();
+
+ const QGradient::Type type = stringToGradientType(elem.attribute(QLatin1String("type")));
+ const QGradient::Spread spread = stringToGradientSpread(elem.attribute(QLatin1String("spread")));
+ const QGradient::CoordinateMode mode = stringToGradientCoordinateMode(elem.attribute(QLatin1String("coordinateMode")));
+
+ QGradient gradient = QLinearGradient();
+
+ if (type == QGradient::LinearGradient) {
+ QLinearGradient g;
+ g.setStart(elem.attribute(QLatin1String("startX")).toDouble(), elem.attribute(QLatin1String("startY")).toDouble());
+ g.setFinalStop(elem.attribute(QLatin1String("endX")).toDouble(), elem.attribute(QLatin1String("endY")).toDouble());
+ gradient = g;
+ } else if (type == QGradient::RadialGradient) {
+ QRadialGradient g;
+ g.setCenter(elem.attribute(QLatin1String("centerX")).toDouble(), elem.attribute(QLatin1String("centerY")).toDouble());
+ g.setFocalPoint(elem.attribute(QLatin1String("focalX")).toDouble(), elem.attribute(QLatin1String("focalY")).toDouble());
+ g.setRadius(elem.attribute(QLatin1String("radius")).toDouble());
+ gradient = g;
+ } else if (type == QGradient::ConicalGradient) {
+ QConicalGradient g;
+ g.setCenter(elem.attribute(QLatin1String("centerX")).toDouble(), elem.attribute(QLatin1String("centerY")).toDouble());
+ g.setAngle(elem.attribute(QLatin1String("angle")).toDouble());
+ gradient = g;
+ }
+
+ QDomElement stopElem = elem.firstChildElement();
+ while (!stopElem.isNull()) {
+ QGradientStop stop = loadGradientStop(stopElem);
+
+ gradient.setColorAt(stop.first, stop.second);
+
+ stopElem = stopElem.nextSiblingElement();
+ }
+
+ gradient.setSpread(spread);
+ gradient.setCoordinateMode(mode);
+
+ return gradient;
+}
+
+QString QtGradientUtils::saveState(const QtGradientManager *manager)
+{
+ QDomDocument doc;
+
+ QDomElement rootElem = doc.createElement(QLatin1String("gradients"));
+
+ QMap<QString, QGradient> grads = manager->gradients();
+ QMapIterator<QString, QGradient> itGrad(grads);
+ while (itGrad.hasNext()) {
+ itGrad.next();
+ QDomElement idElem = doc.createElement(QLatin1String("gradient"));
+ idElem.setAttribute(QLatin1String("name"), itGrad.key());
+ QDomElement gradElem = saveGradient(doc, itGrad.value());
+ idElem.appendChild(gradElem);
+
+ rootElem.appendChild(idElem);
+ }
+
+ doc.appendChild(rootElem);
+
+ return doc.toString();
+}
+
+void QtGradientUtils::restoreState(QtGradientManager *manager, const QString &state)
+{
+ manager->clear();
+
+ QDomDocument doc;
+ doc.setContent(state);
+
+ QDomElement rootElem = doc.documentElement();
+
+ QDomElement gradElem = rootElem.firstChildElement();
+ while (!gradElem.isNull()) {
+ const QString name = gradElem.attribute(QLatin1String("name"));
+ const QGradient gradient = loadGradient(gradElem.firstChildElement());
+
+ manager->addGradient(name, gradient);
+ gradElem = gradElem.nextSiblingElement();
+ }
+}
+
+QPixmap QtGradientUtils::gradientPixmap(const QGradient &gradient, const QSize &size, bool checkeredBackground)
+{
+ QImage image(size, QImage::Format_ARGB32);
+ QPainter p(&image);
+ p.setCompositionMode(QPainter::CompositionMode_Source);
+
+ if (checkeredBackground) {
+ int pixSize = 20;
+ QPixmap pm(2 * pixSize, 2 * pixSize);
+
+ QPainter pmp(&pm);
+ pmp.fillRect(0, 0, pixSize, pixSize, Qt::lightGray);
+ pmp.fillRect(pixSize, pixSize, pixSize, pixSize, Qt::lightGray);
+ pmp.fillRect(0, pixSize, pixSize, pixSize, Qt::darkGray);
+ pmp.fillRect(pixSize, 0, pixSize, pixSize, Qt::darkGray);
+
+ p.setBrushOrigin((size.width() % pixSize + pixSize) / 2, (size.height() % pixSize + pixSize) / 2);
+ p.fillRect(0, 0, size.width(), size.height(), pm);
+ p.setBrushOrigin(0, 0);
+ p.setCompositionMode(QPainter::CompositionMode_SourceOver);
+ }
+
+ const qreal scaleFactor = 0.999999;
+ p.scale(scaleFactor, scaleFactor);
+ QGradient grad = gradient;
+ grad.setCoordinateMode(QGradient::StretchToDeviceMode);
+ p.fillRect(QRect(0, 0, size.width(), size.height()), grad);
+ p.drawRect(QRect(0, 0, size.width() - 1, size.height() - 1));
+
+ return QPixmap::fromImage(image);
+}
+
+static QString styleSheetFillName(const QGradient &gradient)
+{
+ QString result;
+
+ switch (gradient.type()) {
+ case QGradient::LinearGradient:
+ result += QLatin1String("qlineargradient");
+ break;
+ case QGradient::RadialGradient:
+ result += QLatin1String("qradialgradient");
+ break;
+ case QGradient::ConicalGradient:
+ result += QLatin1String("qconicalgradient");
+ break;
+ default:
+ qWarning() << "QtGradientUtils::styleSheetFillName(): gradient type" << gradient.type() << "not supported!";
+ break;
+ }
+
+ return result;
+}
+
+static QStringList styleSheetParameters(const QGradient &gradient)
+{
+ QStringList result;
+
+ if (gradient.type() != QGradient::ConicalGradient) {
+ QString spread;
+ switch (gradient.spread()) {
+ case QGradient::PadSpread:
+ spread = QLatin1String("pad");
+ break;
+ case QGradient::ReflectSpread:
+ spread = QLatin1String("reflect");
+ break;
+ case QGradient::RepeatSpread:
+ spread = QLatin1String("repeat");
+ break;
+ default:
+ qWarning() << "QtGradientUtils::styleSheetParameters(): gradient spread" << gradient.spread() << "not supported!";
+ break;
+ }
+ result << QLatin1String("spread:") + spread;
+ }
+
+ switch (gradient.type()) {
+ case QGradient::LinearGradient: {
+ const QLinearGradient *linearGradient = static_cast<const QLinearGradient*>(&gradient);
+ result << QLatin1String("x1:") + QString::number(linearGradient->start().x())
+ << QLatin1String("y1:") + QString::number(linearGradient->start().y())
+ << QLatin1String("x2:") + QString::number(linearGradient->finalStop().x())
+ << QLatin1String("y2:") + QString::number(linearGradient->finalStop().y());
+ break;
+ }
+ case QGradient::RadialGradient: {
+ const QRadialGradient *radialGradient = static_cast<const QRadialGradient*>(&gradient);
+ result << QLatin1String("cx:") + QString::number(radialGradient->center().x())
+ << QLatin1String("cy:") + QString::number(radialGradient->center().y())
+ << QLatin1String("radius:") + QString::number(radialGradient->radius())
+ << QLatin1String("fx:") + QString::number(radialGradient->focalPoint().x())
+ << QLatin1String("fy:") + QString::number(radialGradient->focalPoint().y());
+ break;
+ }
+ case QGradient::ConicalGradient: {
+ const QConicalGradient *conicalGradient = static_cast<const QConicalGradient*>(&gradient);
+ result << QLatin1String("cx:") + QString::number(conicalGradient->center().x())
+ << QLatin1String("cy:") + QString::number(conicalGradient->center().y())
+ << QLatin1String("angle:") + QString::number(conicalGradient->angle());
+ break;
+ }
+ default:
+ qWarning() << "QtGradientUtils::styleSheetParameters(): gradient type" << gradient.type() << "not supported!";
+ break;
+ }
+
+ return result;
+}
+
+static QStringList styleSheetStops(const QGradient &gradient)
+{
+ QStringList result;
+ foreach (QGradientStop stop, gradient.stops()) {
+ const QColor color = stop.second;
+
+ const QString stopDescription = QLatin1String("stop:") + QString::number(stop.first) + QLatin1String(" rgba(")
+ + QString::number(color.red()) + QLatin1String(", ")
+ + QString::number(color.green()) + QLatin1String(", ")
+ + QString::number(color.blue()) + QLatin1String(", ")
+ + QString::number(color.alpha()) + QLatin1Char(')');
+ result << stopDescription;
+ }
+
+ return result;
+}
+
+QString QtGradientUtils::styleSheetCode(const QGradient &gradient)
+{
+ QStringList gradientParameters;
+ gradientParameters << styleSheetParameters(gradient) << styleSheetStops(gradient);
+
+ return styleSheetFillName(gradient) + QLatin1Char('(') + gradientParameters.join(QLatin1String(", ")) + QLatin1Char(')');
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientutils.h b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientutils.h
new file mode 100644
index 0000000000..63622b7239
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientutils.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GRADIENTUTILS_H
+#define GRADIENTUTILS_H
+
+#include <QtGui/QGradient>
+#include <QtGui/QPainter>
+
+QT_BEGIN_NAMESPACE
+
+class QtGradientManager;
+
+class QtGradientUtils
+{
+public:
+ static QString styleSheetCode(const QGradient &gradient);
+ // utils methods, they could be outside of this class
+ static QString saveState(const QtGradientManager *manager);
+ static void restoreState(QtGradientManager *manager, const QString &state);
+
+ static QPixmap gradientPixmap(const QGradient &gradient, const QSize &size = QSize(64, 64), bool checkeredBackground = false);
+
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientview.cpp b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientview.cpp
new file mode 100644
index 0000000000..c9d8aac2f4
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientview.cpp
@@ -0,0 +1,292 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtgradientview.h"
+#include "qtgradientmanager.h"
+#include "qtgradientdialog.h"
+#include "qtgradientutils.h"
+#include <QtGui/QPainter>
+#include <QtGui/QMessageBox>
+#include <QtGui/QClipboard>
+
+QT_BEGIN_NAMESPACE
+
+void QtGradientView::slotGradientAdded(const QString &id, const QGradient &gradient)
+{
+ QListWidgetItem *item = new QListWidgetItem(QtGradientUtils::gradientPixmap(gradient), id, m_ui.listWidget);
+ item->setToolTip(id);
+ item->setSizeHint(QSize(72, 84));
+ item->setFlags(item->flags() | Qt::ItemIsEditable);
+
+ m_idToItem[id] = item;
+ m_itemToId[item] = id;
+}
+
+void QtGradientView::slotGradientRenamed(const QString &id, const QString &newId)
+{
+ if (!m_idToItem.contains(id))
+ return;
+
+ QListWidgetItem *item = m_idToItem.value(id);
+ item->setText(newId);
+ item->setToolTip(newId);
+ m_itemToId[item] = newId;
+ m_idToItem.remove(id);
+ m_idToItem[newId] = item;
+}
+
+void QtGradientView::slotGradientChanged(const QString &id, const QGradient &newGradient)
+{
+ if (!m_idToItem.contains(id))
+ return;
+
+ QListWidgetItem *item = m_idToItem.value(id);
+ item->setIcon(QtGradientUtils::gradientPixmap(newGradient));
+}
+
+void QtGradientView::slotGradientRemoved(const QString &id)
+{
+ if (!m_idToItem.contains(id))
+ return;
+
+ QListWidgetItem *item = m_idToItem.value(id);
+ delete item;
+ m_itemToId.remove(item);
+ m_idToItem.remove(id);
+}
+
+void QtGradientView::slotNewGradient()
+{
+ bool ok;
+ QListWidgetItem *item = m_ui.listWidget->currentItem();
+ QGradient grad = QLinearGradient();
+ if (item)
+ grad = m_manager->gradients().value(m_itemToId.value(item));
+ QGradient gradient = QtGradientDialog::getGradient(&ok, grad, this);
+ if (!ok)
+ return;
+
+ QString id = m_manager->addGradient(tr("Grad"), gradient);
+ m_ui.listWidget->setCurrentItem(m_idToItem.value(id));
+}
+
+void QtGradientView::slotEditGradient()
+{
+ bool ok;
+ QListWidgetItem *item = m_ui.listWidget->currentItem();
+ if (!item)
+ return;
+
+ const QString id = m_itemToId.value(item);
+ QGradient grad = m_manager->gradients().value(id);
+ QGradient gradient = QtGradientDialog::getGradient(&ok, grad, this);
+ if (!ok)
+ return;
+
+ m_manager->changeGradient(id, gradient);
+}
+
+void QtGradientView::slotRemoveGradient()
+{
+ QListWidgetItem *item = m_ui.listWidget->currentItem();
+ if (!item)
+ return;
+
+ if (QMessageBox::question(this, tr("Remove Gradient"),
+ tr("Are you sure you want to remove the selected gradient?"),
+ QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel) != QMessageBox::Yes)
+ return;
+
+ const QString id = m_itemToId.value(item);
+ m_manager->removeGradient(id);
+}
+
+void QtGradientView::slotRenameGradient()
+{
+ QListWidgetItem *item = m_ui.listWidget->currentItem();
+ if (!item)
+ return;
+
+ m_ui.listWidget->editItem(item);
+}
+
+void QtGradientView::slotRenameGradient(QListWidgetItem *item)
+{
+ if (!item)
+ return;
+
+ const QString id = m_itemToId.value(item);
+ m_manager->renameGradient(id, item->text());
+}
+
+void QtGradientView::slotCurrentItemChanged(QListWidgetItem *item)
+{
+ m_editAction->setEnabled(item);
+ m_renameAction->setEnabled(item);
+ m_removeAction->setEnabled(item);
+ emit currentGradientChanged(m_itemToId.value(item));
+}
+
+void QtGradientView::slotGradientActivated(QListWidgetItem *item)
+{
+ const QString id = m_itemToId.value(item);
+ if (!id.isEmpty())
+ emit gradientActivated(id);
+}
+
+QtGradientView::QtGradientView(QWidget *parent)
+ : QWidget(parent)
+{
+ m_manager = 0;
+
+ m_ui.setupUi(this);
+
+ m_ui.listWidget->setViewMode(QListView::IconMode);
+ m_ui.listWidget->setMovement(QListView::Static);
+ m_ui.listWidget->setTextElideMode(Qt::ElideRight);
+ m_ui.listWidget->setResizeMode(QListWidget::Adjust);
+ m_ui.listWidget->setIconSize(QSize(64, 64));
+ m_ui.listWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
+
+ QPalette pal = m_ui.listWidget->viewport()->palette();
+ int pixSize = 18;
+ QPixmap pm(2 * pixSize, 2 * pixSize);
+
+ QColor c1 = palette().color(QPalette::Midlight);
+ QColor c2 = palette().color(QPalette::Dark);
+ QPainter pmp(&pm);
+ pmp.fillRect(0, 0, pixSize, pixSize, c1);
+ pmp.fillRect(pixSize, pixSize, pixSize, pixSize, c1);
+ pmp.fillRect(0, pixSize, pixSize, pixSize, c2);
+ pmp.fillRect(pixSize, 0, pixSize, pixSize, c2);
+
+ pal.setBrush(QPalette::Base, QBrush(pm));
+ m_ui.listWidget->viewport()->setPalette(pal);
+
+ connect(m_ui.listWidget, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(slotGradientActivated(QListWidgetItem*)));
+ connect(m_ui.listWidget, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(slotRenameGradient(QListWidgetItem*)));
+ connect(m_ui.listWidget, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)), this, SLOT(slotCurrentItemChanged(QListWidgetItem*)));
+
+ m_newAction = new QAction(QIcon(QLatin1String(":/trolltech/qtgradienteditor/images/plus.png")), tr("New..."), this);
+ m_editAction = new QAction(QIcon(QLatin1String(":/trolltech/qtgradienteditor/images/edit.png")), tr("Edit..."), this);
+ m_renameAction = new QAction(tr("Rename"), this);
+ m_removeAction = new QAction(QIcon(QLatin1String(":/trolltech/qtgradienteditor/images/minus.png")), tr("Remove"), this);
+
+ connect(m_newAction, SIGNAL(triggered()), this, SLOT(slotNewGradient()));
+ connect(m_editAction, SIGNAL(triggered()), this, SLOT(slotEditGradient()));
+ connect(m_removeAction, SIGNAL(triggered()), this, SLOT(slotRemoveGradient()));
+ connect(m_renameAction, SIGNAL(triggered()), this, SLOT(slotRenameGradient()));
+
+ m_ui.listWidget->addAction(m_newAction);
+ m_ui.listWidget->addAction(m_editAction);
+ m_ui.listWidget->addAction(m_renameAction);
+ m_ui.listWidget->addAction(m_removeAction);
+
+ m_ui.newButton->setDefaultAction(m_newAction);
+ m_ui.editButton->setDefaultAction(m_editAction);
+ m_ui.renameButton->setDefaultAction(m_renameAction);
+ m_ui.removeButton->setDefaultAction(m_removeAction);
+
+ m_ui.listWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
+}
+
+void QtGradientView::setGradientManager(QtGradientManager *manager)
+{
+ if (m_manager == manager)
+ return;
+
+ if (m_manager) {
+ disconnect(m_manager, SIGNAL(gradientAdded(QString,QGradient)),
+ this, SLOT(slotGradientAdded(QString,QGradient)));
+ disconnect(m_manager, SIGNAL(gradientRenamed(QString,QString)),
+ this, SLOT(slotGradientRenamed(QString,QString)));
+ disconnect(m_manager, SIGNAL(gradientChanged(QString,QGradient)),
+ this, SLOT(slotGradientChanged(QString,QGradient)));
+ disconnect(m_manager, SIGNAL(gradientRemoved(QString)),
+ this, SLOT(slotGradientRemoved(QString)));
+
+ m_ui.listWidget->clear();
+ m_idToItem.clear();
+ m_itemToId.clear();
+ }
+
+ m_manager = manager;
+
+ if (!m_manager)
+ return;
+
+ QMap<QString, QGradient> gradients = m_manager->gradients();
+ QMapIterator<QString, QGradient> itGrad(gradients);
+ while (itGrad.hasNext()) {
+ itGrad.next();
+ slotGradientAdded(itGrad.key(), itGrad.value());
+ }
+
+ connect(m_manager, SIGNAL(gradientAdded(QString,QGradient)),
+ this, SLOT(slotGradientAdded(QString,QGradient)));
+ connect(m_manager, SIGNAL(gradientRenamed(QString,QString)),
+ this, SLOT(slotGradientRenamed(QString,QString)));
+ connect(m_manager, SIGNAL(gradientChanged(QString,QGradient)),
+ this, SLOT(slotGradientChanged(QString,QGradient)));
+ connect(m_manager, SIGNAL(gradientRemoved(QString)),
+ this, SLOT(slotGradientRemoved(QString)));
+}
+
+QtGradientManager *QtGradientView::gradientManager() const
+{
+ return m_manager;
+}
+
+void QtGradientView::setCurrentGradient(const QString &id)
+{
+ QListWidgetItem *item = m_idToItem.value(id);
+ if (!item)
+ return;
+
+ m_ui.listWidget->setCurrentItem(item);
+}
+
+QString QtGradientView::currentGradient() const
+{
+ return m_itemToId.value(m_ui.listWidget->currentItem());
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientview.h b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientview.h
new file mode 100644
index 0000000000..3f7662abab
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientview.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GRADIENTVIEW_H
+#define GRADIENTVIEW_H
+
+#include <QtGui/QWidget>
+#include <QtCore/QMap>
+#include "ui_qtgradientview.h"
+
+QT_BEGIN_NAMESPACE
+
+class QtGradientManager;
+class QListViewItem;
+class QAction;
+
+class QtGradientView : public QWidget
+{
+ Q_OBJECT
+public:
+ QtGradientView(QWidget *parent = 0);
+
+ void setGradientManager(QtGradientManager *manager);
+ QtGradientManager *gradientManager() const;
+
+ void setCurrentGradient(const QString &id);
+ QString currentGradient() const;
+
+signals:
+ void currentGradientChanged(const QString &id);
+ void gradientActivated(const QString &id);
+
+private slots:
+ void slotGradientAdded(const QString &id, const QGradient &gradient);
+ void slotGradientRenamed(const QString &id, const QString &newId);
+ void slotGradientChanged(const QString &id, const QGradient &newGradient);
+ void slotGradientRemoved(const QString &id);
+ void slotNewGradient();
+ void slotEditGradient();
+ void slotRemoveGradient();
+ void slotRenameGradient();
+ void slotRenameGradient(QListWidgetItem *item);
+ void slotCurrentItemChanged(QListWidgetItem *item);
+ void slotGradientActivated(QListWidgetItem *item);
+
+private:
+ QMap<QString, QListWidgetItem *> m_idToItem;
+ QMap<QListWidgetItem *, QString> m_itemToId;
+
+ QAction *m_newAction;
+ QAction *m_editAction;
+ QAction *m_renameAction;
+ QAction *m_removeAction;
+
+ QtGradientManager *m_manager;
+ Ui::QtGradientView m_ui;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientview.ui b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientview.ui
new file mode 100644
index 0000000000..af7267ea2b
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientview.ui
@@ -0,0 +1,135 @@
+<ui version="4.0" >
+ <class>QtGradientView</class>
+ <widget class="QWidget" name="QtGradientView" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>484</width>
+ <height>228</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Gradient View</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <layout class="QHBoxLayout" >
+ <item>
+ <widget class="QToolButton" name="newButton" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Minimum" hsizetype="Minimum" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>New...</string>
+ </property>
+ <property name="toolButtonStyle" >
+ <enum>Qt::ToolButtonTextBesideIcon</enum>
+ </property>
+ <property name="autoRaise" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="editButton" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Minimum" hsizetype="Minimum" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Edit...</string>
+ </property>
+ <property name="toolButtonStyle" >
+ <enum>Qt::ToolButtonTextBesideIcon</enum>
+ </property>
+ <property name="autoRaise" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="renameButton" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Minimum" hsizetype="Minimum" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Rename</string>
+ </property>
+ <property name="toolButtonStyle" >
+ <enum>Qt::ToolButtonTextBesideIcon</enum>
+ </property>
+ <property name="autoRaise" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="removeButton" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Minimum" hsizetype="Minimum" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Remove</string>
+ </property>
+ <property name="toolButtonStyle" >
+ <enum>Qt::ToolButtonTextBesideIcon</enum>
+ </property>
+ <property name="autoRaise" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>71</width>
+ <height>26</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QListWidget" name="listWidget" />
+ </item>
+ </layout>
+ </widget>
+ <tabstops>
+ <tabstop>listWidget</tabstop>
+ <tabstop>newButton</tabstop>
+ <tabstop>editButton</tabstop>
+ <tabstop>renameButton</tabstop>
+ <tabstop>removeButton</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientviewdialog.cpp b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientviewdialog.cpp
new file mode 100644
index 0000000000..6f3d88a937
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientviewdialog.cpp
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtgradientviewdialog.h"
+#include "qtgradientmanager.h"
+#include <QtGui/QPushButton>
+
+QT_BEGIN_NAMESPACE
+
+QtGradientViewDialog::QtGradientViewDialog(QWidget *parent)
+ : QDialog(parent)
+{
+ m_ui.setupUi(this);
+ m_ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
+ connect(m_ui.gradientView, SIGNAL(currentGradientChanged(QString)),
+ this, SLOT(slotGradientSelected(QString)));
+ connect(m_ui.gradientView, SIGNAL(gradientActivated(QString)),
+ this, SLOT(slotGradientActivated(QString)));
+}
+
+void QtGradientViewDialog::setGradientManager(QtGradientManager *manager)
+{
+ m_ui.gradientView->setGradientManager(manager);
+}
+
+QGradient QtGradientViewDialog::getGradient(bool *ok, QtGradientManager *manager, QWidget *parent, const QString &caption)
+{
+ QtGradientViewDialog dlg(parent);
+ dlg.setGradientManager(manager);
+ dlg.setWindowTitle(caption);
+ QGradient grad = QLinearGradient();
+ const int res = dlg.exec();
+ if (res == QDialog::Accepted)
+ grad = dlg.m_ui.gradientView->gradientManager()->gradients().value(dlg.m_ui.gradientView->currentGradient());
+ if (ok)
+ *ok = res == QDialog::Accepted;
+ return grad;
+}
+
+void QtGradientViewDialog::slotGradientSelected(const QString &id)
+{
+ m_ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!id.isEmpty());
+}
+
+void QtGradientViewDialog::slotGradientActivated(const QString &id)
+{
+ Q_UNUSED(id)
+ accept();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientviewdialog.h b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientviewdialog.h
new file mode 100644
index 0000000000..f30799b5d1
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientviewdialog.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GRADIENTVIEWDIALOG_H
+#define GRADIENTVIEWDIALOG_H
+
+#include <QtGui/QWidget>
+#include <QtCore/QMap>
+#include "ui_qtgradientviewdialog.h"
+
+QT_BEGIN_NAMESPACE
+
+class QtGradientManager;
+
+class QtGradientViewDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ QtGradientViewDialog(QWidget *parent = 0);
+
+ void setGradientManager(QtGradientManager *manager);
+ QtGradientManager *gradientManager() const;
+
+ static QGradient getGradient(bool *ok, QtGradientManager *manager, QWidget *parent = 0, const QString &caption = tr("Select Gradient", 0));
+
+private slots:
+ void slotGradientSelected(const QString &id);
+ void slotGradientActivated(const QString &id);
+
+private:
+ Ui::QtGradientViewDialog m_ui;
+};
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientviewdialog.ui b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientviewdialog.ui
new file mode 100644
index 0000000000..6b3bebbb0c
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientviewdialog.ui
@@ -0,0 +1,121 @@
+<ui version="4.0" >
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <class>QtGradientViewDialog</class>
+ <widget class="QDialog" name="QtGradientViewDialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>178</width>
+ <height>72</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Select Gradient</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <item>
+ <widget class="QtGradientView" name="gradientView" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="MinimumExpanding" hsizetype="MinimumExpanding" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>QtGradientView</class>
+ <extends>QFrame</extends>
+ <header>qtgradientview.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>QtGradientViewDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>72</x>
+ <y>224</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>21</x>
+ <y>243</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>QtGradientViewDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>168</x>
+ <y>233</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>152</x>
+ <y>251</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientwidget.cpp b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientwidget.cpp
new file mode 100644
index 0000000000..779126f735
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientwidget.cpp
@@ -0,0 +1,815 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtgradientwidget.h"
+#include <QtCore/QMap>
+#include <QtGui/QImage>
+#include <QtGui/QPainter>
+#include <QtGui/QScrollBar>
+#include <QtGui/QMouseEvent>
+
+#define _USE_MATH_DEFINES
+
+
+#include "math.h"
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QtGradientWidgetPrivate
+{
+ QtGradientWidget *q_ptr;
+ Q_DECLARE_PUBLIC(QtGradientWidget)
+public:
+ QPointF fromViewport(const QPointF &point) const;
+ QPointF toViewport(const QPointF &point) const;
+// void setupDrag(QtGradientStop *stop, int x);
+
+ QPointF checkRange(const QPointF &point) const;
+ QRectF pointRect(const QPointF &point, double size) const;
+
+ double correctAngle(double angle) const;
+ void setAngleConical(double angle);
+
+ void paintPoint(QPainter *painter, const QPointF &point, double size) const;
+
+ double m_handleSize;
+ bool m_backgroundCheckered;
+
+ QGradientStops m_gradientStops;
+ QGradient::Type m_gradientType;
+ QGradient::Spread m_gradientSpread;
+ QPointF m_startLinear;
+ QPointF m_endLinear;
+ QPointF m_centralRadial;
+ QPointF m_focalRadial;
+ qreal m_radiusRadial;
+ QPointF m_centralConical;
+ qreal m_angleConical;
+
+ enum Handle {
+ NoHandle,
+ StartLinearHandle,
+ EndLinearHandle,
+ CentralRadialHandle,
+ FocalRadialHandle,
+ RadiusRadialHandle,
+ CentralConicalHandle,
+ AngleConicalHandle
+ };
+
+ Handle m_dragHandle;
+ QPointF m_dragOffset;
+ //double m_radiusOffset;
+ double m_radiusFactor;
+ double m_dragRadius;
+ double m_angleOffset;
+ double m_dragAngle;
+};
+
+double QtGradientWidgetPrivate::correctAngle(double angle) const
+{
+ double a = angle;
+ while (a >= 360)
+ a -= 360;
+ while (a < 0)
+ a += 360;
+ return a;
+}
+
+void QtGradientWidgetPrivate::setAngleConical(double angle)
+{
+ double a = correctAngle(angle);
+ if (m_angleConical == a)
+ return;
+ m_angleConical = a;
+ emit q_ptr->angleConicalChanged(m_angleConical);
+}
+
+QRectF QtGradientWidgetPrivate::pointRect(const QPointF &point, double size) const
+{
+ return QRectF(point.x() - size / 2, point.y() - size / 2, size, size);
+}
+
+QPointF QtGradientWidgetPrivate::checkRange(const QPointF &point) const
+{
+ QPointF p = point;
+ if (p.x() > 1)
+ p.setX(1);
+ else if (p.x() < 0)
+ p.setX(0);
+ if (p.y() > 1)
+ p.setY(1);
+ else if (p.y() < 0)
+ p.setY(0);
+ return p;
+}
+
+QPointF QtGradientWidgetPrivate::fromViewport(const QPointF &point) const
+{
+ QSize size = q_ptr->size();
+ return QPointF(point.x() / size.width(), point.y() / size.height());
+}
+
+QPointF QtGradientWidgetPrivate::toViewport(const QPointF &point) const
+{
+ QSize size = q_ptr->size();
+ return QPointF(point.x() * size.width(), point.y() * size.height());
+}
+
+void QtGradientWidgetPrivate::paintPoint(QPainter *painter, const QPointF &point, double size) const
+{
+ QPointF pf = toViewport(point);
+ QRectF rf = pointRect(pf, size);
+
+ QPen pen;
+ pen.setWidthF(1);
+ QColor alphaZero = Qt::white;
+ alphaZero.setAlpha(0);
+
+ painter->save();
+ painter->drawEllipse(rf);
+
+ /*
+ painter->save();
+
+ QLinearGradient lgV(0, rf.top(), 0, rf.bottom());
+ lgV.setColorAt(0, alphaZero);
+ lgV.setColorAt(0.25, Qt::white);
+ lgV.setColorAt(0.25, Qt::white);
+ lgV.setColorAt(1, alphaZero);
+ pen.setBrush(lgV);
+ painter->setPen(pen);
+
+ painter->drawLine(QPointF(pf.x(), rf.top()), QPointF(pf.x(), rf.bottom()));
+
+ QLinearGradient lgH(rf.left(), 0, rf.right(), 0);
+ lgH.setColorAt(0, alphaZero);
+ lgH.setColorAt(0.5, Qt::white);
+ lgH.setColorAt(1, alphaZero);
+ pen.setBrush(lgH);
+ painter->setPen(pen);
+
+ painter->drawLine(QPointF(rf.left(), pf.y()), QPointF(rf.right(), pf.y()));
+
+ painter->restore();
+ */
+
+ painter->restore();
+}
+
+/*
+void QtGradientWidgetPrivate::setupDrag(QtGradientStop *stop, int x)
+{
+ m_model->setCurrentStop(stop);
+
+ int viewportX = qRound(toViewport(stop->position()));
+ m_dragOffset = x - viewportX;
+
+ QList<QtGradientStop *> stops = m_stops;
+ m_stops.clear();
+ QListIterator<QtGradientStop *> itStop(stops);
+ while (itStop.hasNext()) {
+ QtGradientStop *s = itStop.next();
+ if (m_model->isSelected(s) || s == stop) {
+ m_dragStops[s] = s->position() - stop->position();
+ m_stops.append(s);
+ } else {
+ m_dragOriginal[s->position()] = s->color();
+ }
+ }
+ itStop.toFront();
+ while (itStop.hasNext()) {
+ QtGradientStop *s = itStop.next();
+ if (!m_model->isSelected(s))
+ m_stops.append(s);
+ }
+ m_stops.removeAll(stop);
+ m_stops.prepend(stop);
+}
+*/
+////////////////////////////
+
+QtGradientWidget::QtGradientWidget(QWidget *parent)
+ : QWidget(parent), d_ptr(new QtGradientWidgetPrivate)
+{
+ d_ptr->q_ptr = this;
+ d_ptr->m_backgroundCheckered = true;
+ d_ptr->m_handleSize = 20.0;
+ d_ptr->m_gradientType = QGradient::LinearGradient;
+ d_ptr->m_startLinear = QPointF(0, 0);
+ d_ptr->m_endLinear = QPointF(1, 1);
+ d_ptr->m_centralRadial = QPointF(0.5, 0.5);
+ d_ptr->m_focalRadial = QPointF(0.5, 0.5);
+ d_ptr->m_radiusRadial = 0.5;
+ d_ptr->m_centralConical = QPointF(0.5, 0.5);
+ d_ptr->m_angleConical = 0;
+ d_ptr->m_dragHandle = QtGradientWidgetPrivate::NoHandle;
+
+ setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred));
+}
+
+QtGradientWidget::~QtGradientWidget()
+{
+}
+
+QSize QtGradientWidget::sizeHint() const
+{
+ return QSize(176, 176);
+}
+
+QSize QtGradientWidget::minimumSizeHint() const
+{
+ return QSize(128, 128);
+}
+
+int QtGradientWidget::heightForWidth(int w) const
+{
+ return w;
+}
+
+void QtGradientWidget::setBackgroundCheckered(bool checkered)
+{
+ if (d_ptr->m_backgroundCheckered == checkered)
+ return;
+ d_ptr->m_backgroundCheckered = checkered;
+ update();
+}
+
+bool QtGradientWidget::isBackgroundCheckered() const
+{
+ return d_ptr->m_backgroundCheckered;
+}
+
+void QtGradientWidget::mousePressEvent(QMouseEvent *e)
+{
+ if (e->button() != Qt::LeftButton)
+ return;
+
+ QPoint p = e->pos();
+ if (d_ptr->m_gradientType == QGradient::LinearGradient) {
+ QPointF startPoint = d_ptr->toViewport(d_ptr->m_startLinear);
+ double x = p.x() - startPoint.x();
+ double y = p.y() - startPoint.y();
+
+ if ((d_ptr->m_handleSize * d_ptr->m_handleSize / 4) > (x * x + y * y)) {
+ d_ptr->m_dragHandle = QtGradientWidgetPrivate::StartLinearHandle;
+ d_ptr->m_dragOffset = QPointF(x, y);
+ update();
+ return;
+ }
+
+ QPointF endPoint = d_ptr->toViewport(d_ptr->m_endLinear);
+ x = p.x() - endPoint.x();
+ y = p.y() - endPoint.y();
+
+ if ((d_ptr->m_handleSize * d_ptr->m_handleSize / 4) > (x * x + y * y)) {
+ d_ptr->m_dragHandle = QtGradientWidgetPrivate::EndLinearHandle;
+ d_ptr->m_dragOffset = QPointF(x, y);
+ update();
+ return;
+ }
+ } else if (d_ptr->m_gradientType == QGradient::RadialGradient) {
+ QPointF focalPoint = d_ptr->toViewport(d_ptr->m_focalRadial);
+ double x = p.x() - focalPoint.x();
+ double y = p.y() - focalPoint.y();
+
+ if ((d_ptr->m_handleSize * d_ptr->m_handleSize / 9) > (x * x + y * y)) {
+ d_ptr->m_dragHandle = QtGradientWidgetPrivate::FocalRadialHandle;
+ d_ptr->m_dragOffset = QPointF(x, y);
+ update();
+ return;
+ }
+
+ QPointF centralPoint = d_ptr->toViewport(d_ptr->m_centralRadial);
+ x = p.x() - centralPoint.x();
+ y = p.y() - centralPoint.y();
+
+ if ((d_ptr->m_handleSize * d_ptr->m_handleSize / 4) > (x * x + y * y)) {
+ d_ptr->m_dragHandle = QtGradientWidgetPrivate::CentralRadialHandle;
+ d_ptr->m_dragOffset = QPointF(x, y);
+ update();
+ return;
+ }
+
+ QPointF central = d_ptr->toViewport(d_ptr->m_centralRadial);
+ QRectF r = d_ptr->pointRect(central, 2 * d_ptr->m_handleSize / 3);
+ QRectF r1(0, r.y(), size().width(), r.height());
+ QRectF r2(r.x(), 0, r.width(), r.y());
+ QRectF r3(r.x(), r.y() + r.height(), r.width(), size().height() - r.y() - r.height());
+ QPointF pF(p.x(), p.y());
+ if (r1.contains(pF) || r2.contains(pF) || r3.contains(pF)) {
+ x = pF.x() / size().width() - d_ptr->m_centralRadial.x();
+ y = pF.y() / size().height() - d_ptr->m_centralRadial.y();
+ double clickRadius = sqrt(x * x + y * y);
+ //d_ptr->m_radiusOffset = d_ptr->m_radiusRadial - clickRadius;
+ d_ptr->m_radiusFactor = d_ptr->m_radiusRadial / clickRadius;
+ if (d_ptr->m_radiusFactor == 0)
+ d_ptr->m_radiusFactor = 1;
+ d_ptr->m_dragRadius = d_ptr->m_radiusRadial;
+ d_ptr->m_dragHandle = QtGradientWidgetPrivate::RadiusRadialHandle;
+ mouseMoveEvent(e);
+ update();
+ return;
+ }
+ } else if (d_ptr->m_gradientType == QGradient::ConicalGradient) {
+ QPointF centralPoint = d_ptr->toViewport(d_ptr->m_centralConical);
+ double x = p.x() - centralPoint.x();
+ double y = p.y() - centralPoint.y();
+
+ if ((d_ptr->m_handleSize * d_ptr->m_handleSize / 4) > (x * x + y * y)) {
+ d_ptr->m_dragHandle = QtGradientWidgetPrivate::CentralConicalHandle;
+ d_ptr->m_dragOffset = QPointF(x, y);
+ update();
+ return;
+ }
+ double radius = size().width();
+ if (size().height() < radius)
+ radius = size().height();
+ radius /= 2;
+ double corr = d_ptr->m_handleSize / 3;
+ radius -= corr;
+ QPointF vp = d_ptr->toViewport(d_ptr->m_centralConical);
+ x = p.x() - vp.x();
+ y = p.y() - vp.y();
+ if (((radius - corr) * (radius - corr) < (x * x + y * y)) &&
+ ((radius + corr) * (radius + corr) > (x * x + y * y))) {
+ QPointF central = d_ptr->toViewport(d_ptr->m_centralConical);
+ QPointF current(e->pos().x(), e->pos().y());
+ x = current.x() - central.x();
+ y = current.y() - central.y();
+ x /= size().width() / 2;
+ y /= size().height() / 2;
+ double r = sqrt(x * x + y * y);
+
+ double arcSin = asin(y / r);
+ double arcCos = acos(x / r);
+
+ double angle = arcCos * 180 / M_PI;
+ if (arcSin > 0) {
+ angle = -angle;
+ }
+
+ d_ptr->m_angleOffset = d_ptr->m_angleConical - angle;
+ d_ptr->m_dragAngle = d_ptr->m_angleConical;
+ d_ptr->m_dragHandle = QtGradientWidgetPrivate::AngleConicalHandle;
+ update();
+ return;
+ }
+ }
+}
+
+void QtGradientWidget::mouseReleaseEvent(QMouseEvent *e)
+{
+ Q_UNUSED(e)
+ d_ptr->m_dragHandle = QtGradientWidgetPrivate::NoHandle;
+ update();
+}
+
+void QtGradientWidget::mouseMoveEvent(QMouseEvent *e)
+{
+ if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::NoHandle)
+ return;
+
+ QPointF newPos = QPointF((double)e->pos().x() - d_ptr->m_dragOffset.x(),
+ (double)e->pos().y() - d_ptr->m_dragOffset.y());
+ QPointF newPoint = d_ptr->fromViewport(newPos);
+ if (newPoint.x() < 0)
+ newPoint.setX(0);
+ else if (newPoint.x() > 1)
+ newPoint.setX(1);
+ if (newPoint.y() < 0)
+ newPoint.setY(0);
+ else if (newPoint.y() > 1)
+ newPoint.setY(1);
+
+ if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::StartLinearHandle) {
+ d_ptr->m_startLinear = newPoint;
+ emit startLinearChanged(newPoint);
+ } else if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::EndLinearHandle) {
+ d_ptr->m_endLinear = newPoint;
+ emit endLinearChanged(newPoint);
+ } else if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::CentralRadialHandle) {
+ d_ptr->m_centralRadial = newPoint;
+ emit centralRadialChanged(newPoint);
+ } else if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::FocalRadialHandle) {
+ d_ptr->m_focalRadial = newPoint;
+ emit focalRadialChanged(newPoint);
+ } else if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::RadiusRadialHandle) {
+ QPointF centralPoint = d_ptr->toViewport(d_ptr->m_centralRadial);
+ QPointF pF(e->pos().x(), e->pos().y());
+ double x = pF.x() - centralPoint.x();
+ double y = pF.y() - centralPoint.y();
+
+ if ((d_ptr->m_handleSize * d_ptr->m_handleSize / 4) > (x * x + y * y)) {
+ if (d_ptr->m_radiusRadial != d_ptr->m_dragRadius) {
+ d_ptr->m_radiusRadial = d_ptr->m_dragRadius;
+ emit radiusRadialChanged(d_ptr->m_radiusRadial);
+ }
+ } else {
+ x = pF.x() / size().width() - d_ptr->m_centralRadial.x();
+ y = pF.y() / size().height() - d_ptr->m_centralRadial.y();
+ double moveRadius = sqrt(x * x + y * y);
+ //double newRadius = moveRadius + d_ptr->m_radiusOffset;
+ double newRadius = moveRadius * d_ptr->m_radiusFactor;
+ if (newRadius > 2)
+ newRadius = 2;
+ d_ptr->m_radiusRadial = newRadius;
+ emit radiusRadialChanged(d_ptr->m_radiusRadial);
+ }
+ } else if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::CentralConicalHandle) {
+ d_ptr->m_centralConical = newPoint;
+ emit centralConicalChanged(newPoint);
+ } else if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::AngleConicalHandle) {
+ QPointF centralPoint = d_ptr->toViewport(d_ptr->m_centralConical);
+ QPointF pF(e->pos().x(), e->pos().y());
+ double x = pF.x() - centralPoint.x();
+ double y = pF.y() - centralPoint.y();
+
+ if ((d_ptr->m_handleSize * d_ptr->m_handleSize / 4) > (x * x + y * y)) {
+ if (d_ptr->m_angleConical != d_ptr->m_dragAngle) {
+ d_ptr->m_angleConical = d_ptr->m_dragAngle;
+ emit angleConicalChanged(d_ptr->m_angleConical);
+ }
+ } else {
+ QPointF central = d_ptr->toViewport(d_ptr->m_centralConical);
+ QPointF current = pF;
+ x = current.x() - central.x();
+ y = current.y() - central.y();
+ x /= size().width() / 2;
+ y /= size().height() / 2;
+ double r = sqrt(x * x + y * y);
+
+ double arcSin = asin(y / r);
+ double arcCos = acos(x / r);
+
+ double angle = arcCos * 180 / M_PI;
+ if (arcSin > 0) {
+ angle = -angle;
+ }
+
+ angle += d_ptr->m_angleOffset;
+
+ d_ptr->setAngleConical(angle);
+ }
+ }
+ update();
+}
+
+void QtGradientWidget::mouseDoubleClickEvent(QMouseEvent *e)
+{
+ mousePressEvent(e);
+}
+
+void QtGradientWidget::paintEvent(QPaintEvent *e)
+{
+ Q_UNUSED(e)
+
+ QPainter p(this);
+
+ if (d_ptr->m_backgroundCheckered) {
+ int pixSize = 40;
+ QPixmap pm(2 * pixSize, 2 * pixSize);
+
+ QPainter pmp(&pm);
+ pmp.fillRect(0, 0, pixSize, pixSize, Qt::white);
+ pmp.fillRect(pixSize, pixSize, pixSize, pixSize, Qt::white);
+ pmp.fillRect(0, pixSize, pixSize, pixSize, Qt::black);
+ pmp.fillRect(pixSize, 0, pixSize, pixSize, Qt::black);
+
+ p.setBrushOrigin((size().width() % pixSize + pixSize) / 2, (size().height() % pixSize + pixSize) / 2);
+ p.fillRect(rect(), pm);
+ p.setBrushOrigin(0, 0);
+ }
+
+ QGradient *gradient = 0;
+ switch (d_ptr->m_gradientType) {
+ case QGradient::LinearGradient:
+ gradient = new QLinearGradient(d_ptr->m_startLinear, d_ptr->m_endLinear);
+ break;
+ case QGradient::RadialGradient:
+ gradient = new QRadialGradient(d_ptr->m_centralRadial, d_ptr->m_radiusRadial, d_ptr->m_focalRadial);
+ break;
+ case QGradient::ConicalGradient:
+ gradient = new QConicalGradient(d_ptr->m_centralConical, d_ptr->m_angleConical);
+ break;
+ default:
+ break;
+ }
+ if (!gradient)
+ return;
+
+ gradient->setStops(d_ptr->m_gradientStops);
+ gradient->setSpread(d_ptr->m_gradientSpread);
+
+ p.save();
+ p.scale(size().width(), size().height());
+ p.fillRect(QRect(0, 0, 1, 1), *gradient);
+ p.restore();
+
+ p.setRenderHint(QPainter::Antialiasing);
+
+ QColor c = QColor::fromRgbF(0.5, 0.5, 0.5, 0.5);
+ QBrush br(c);
+ p.setBrush(br);
+ QPen pen(Qt::white);
+ pen.setWidthF(1);
+ p.setPen(pen);
+ QPen dragPen = pen;
+ dragPen.setWidthF(2);
+ if (d_ptr->m_gradientType == QGradient::LinearGradient) {
+ p.save();
+ if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::StartLinearHandle)
+ p.setPen(dragPen);
+ d_ptr->paintPoint(&p, d_ptr->m_startLinear, d_ptr->m_handleSize);
+ p.restore();
+
+ p.save();
+ if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::EndLinearHandle)
+ p.setPen(dragPen);
+ d_ptr->paintPoint(&p, d_ptr->m_endLinear, d_ptr->m_handleSize);
+ p.restore();
+ } else if (d_ptr->m_gradientType == QGradient::RadialGradient) {
+ QPointF central = d_ptr->toViewport(d_ptr->m_centralRadial);
+
+ p.save();
+ QRectF r = d_ptr->pointRect(central, 2 * d_ptr->m_handleSize / 3);
+ QRectF r1(0, r.y(), size().width(), r.height());
+ QRectF r2(r.x(), 0, r.width(), r.y());
+ QRectF r3(r.x(), r.y() + r.height(), r.width(), size().height() - r.y() - r.height());
+ p.fillRect(r1, c);
+ p.fillRect(r2, c);
+ p.fillRect(r3, c);
+ p.setBrush(Qt::NoBrush);
+ p.save();
+ if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::CentralRadialHandle)
+ p.setPen(dragPen);
+ d_ptr->paintPoint(&p, d_ptr->m_centralRadial, d_ptr->m_handleSize);
+ p.restore();
+
+ QRectF rect = QRectF(central.x() - d_ptr->m_radiusRadial * size().width(),
+ central.y() - d_ptr->m_radiusRadial * size().height(),
+ 2 * d_ptr->m_radiusRadial * size().width(),
+ 2 * d_ptr->m_radiusRadial * size().height());
+ p.setClipRect(r1);
+ p.setClipRect(r2, Qt::UniteClip);
+ p.setClipRect(r3, Qt::UniteClip);
+ p.drawEllipse(rect);
+ if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::RadiusRadialHandle) {
+ p.save();
+ p.setPen(dragPen);
+ QRectF rect = QRectF(central.x() - d_ptr->m_radiusRadial / d_ptr->m_radiusFactor * size().width(),
+ central.y() - d_ptr->m_radiusRadial / d_ptr->m_radiusFactor * size().height(),
+ 2 * d_ptr->m_radiusRadial / d_ptr->m_radiusFactor * size().width(),
+ 2 * d_ptr->m_radiusRadial / d_ptr->m_radiusFactor * size().height());
+ p.drawEllipse(rect);
+
+ p.restore();
+ }
+ p.restore();
+
+ p.save();
+ if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::FocalRadialHandle)
+ p.setPen(dragPen);
+ d_ptr->paintPoint(&p, d_ptr->m_focalRadial, 2 * d_ptr->m_handleSize / 3);
+ p.restore();
+ } else if (d_ptr->m_gradientType == QGradient::ConicalGradient) {
+ double radius = size().width();
+ if (size().height() < radius)
+ radius = size().height();
+ radius /= 2;
+ double corr = d_ptr->m_handleSize / 3;
+ radius -= corr;
+ QPointF central = d_ptr->toViewport(d_ptr->m_centralConical);
+
+ p.save();
+ p.setBrush(Qt::NoBrush);
+ QPen pen2(c);
+ pen2.setWidthF(2 * d_ptr->m_handleSize / 3);
+ p.setPen(pen2);
+ p.drawEllipse(d_ptr->pointRect(central, 2 * radius));
+ p.restore();
+
+ p.save();
+ p.setBrush(Qt::NoBrush);
+ int pointCount = 2;
+ for (int i = 0; i < pointCount; i++) {
+ QPointF ang(cos(M_PI * (i * 180.0 / pointCount + d_ptr->m_angleConical) / 180) * size().width() / 2,
+ -sin(M_PI * (i * 180.0 / pointCount + d_ptr->m_angleConical) / 180) * size().height() / 2);
+ double mod = sqrt(ang.x() * ang.x() + ang.y() * ang.y());
+ p.drawLine(QPointF(central.x() + ang.x() * (radius - corr) / mod,
+ central.y() + ang.y() * (radius - corr) / mod),
+ QPointF(central.x() + ang.x() * (radius + corr) / mod,
+ central.y() + ang.y() * (radius + corr) / mod));
+ p.drawLine(QPointF(central.x() - ang.x() * (radius - corr) / mod,
+ central.y() - ang.y() * (radius - corr) / mod),
+ QPointF(central.x() - ang.x() * (radius + corr) / mod,
+ central.y() - ang.y() * (radius + corr) / mod));
+ }
+ if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::AngleConicalHandle) {
+ p.save();
+ p.setPen(dragPen);
+ QPointF ang(cos(M_PI * (d_ptr->m_angleConical - d_ptr->m_angleOffset) / 180) * size().width() / 2,
+ -sin(M_PI * (d_ptr->m_angleConical - d_ptr->m_angleOffset) / 180) * size().height() / 2);
+ double mod = sqrt(ang.x() * ang.x() + ang.y() * ang.y());
+ p.drawLine(QPointF(central.x() + ang.x() * (radius - corr) / mod,
+ central.y() + ang.y() * (radius - corr) / mod),
+ QPointF(central.x() + ang.x() * (radius + corr) / mod,
+ central.y() + ang.y() * (radius + corr) / mod));
+ p.restore();
+ }
+
+ p.restore();
+
+ p.save();
+ if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::CentralConicalHandle)
+ p.setPen(dragPen);
+ d_ptr->paintPoint(&p, d_ptr->m_centralConical, d_ptr->m_handleSize);
+ p.restore();
+
+ }
+
+ delete gradient;
+}
+
+void QtGradientWidget::setGradientStops(const QGradientStops &stops)
+{
+ d_ptr->m_gradientStops = stops;
+ update();
+}
+
+QGradientStops QtGradientWidget::gradientStops() const
+{
+ return d_ptr->m_gradientStops;
+}
+
+void QtGradientWidget::setGradientType(QGradient::Type type)
+{
+ if (type == QGradient::NoGradient)
+ return;
+ if (d_ptr->m_gradientType == type)
+ return;
+
+ d_ptr->m_gradientType = type;
+ update();
+}
+
+QGradient::Type QtGradientWidget::gradientType() const
+{
+ return d_ptr->m_gradientType;
+}
+
+void QtGradientWidget::setGradientSpread(QGradient::Spread spread)
+{
+ if (d_ptr->m_gradientSpread == spread)
+ return;
+
+ d_ptr->m_gradientSpread = spread;
+ update();
+}
+
+QGradient::Spread QtGradientWidget::gradientSpread() const
+{
+ return d_ptr->m_gradientSpread;
+}
+
+void QtGradientWidget::setStartLinear(const QPointF &point)
+{
+ if (d_ptr->m_startLinear == point)
+ return;
+
+ d_ptr->m_startLinear = d_ptr->checkRange(point);
+ update();
+}
+
+QPointF QtGradientWidget::startLinear() const
+{
+ return d_ptr->m_startLinear;
+}
+
+void QtGradientWidget::setEndLinear(const QPointF &point)
+{
+ if (d_ptr->m_endLinear == point)
+ return;
+
+ d_ptr->m_endLinear = d_ptr->checkRange(point);
+ update();
+}
+
+QPointF QtGradientWidget::endLinear() const
+{
+ return d_ptr->m_endLinear;
+}
+
+void QtGradientWidget::setCentralRadial(const QPointF &point)
+{
+ if (d_ptr->m_centralRadial == point)
+ return;
+
+ d_ptr->m_centralRadial = point;
+ update();
+}
+
+QPointF QtGradientWidget::centralRadial() const
+{
+ return d_ptr->m_centralRadial;
+}
+
+void QtGradientWidget::setFocalRadial(const QPointF &point)
+{
+ if (d_ptr->m_focalRadial == point)
+ return;
+
+ d_ptr->m_focalRadial = point;
+ update();
+}
+
+QPointF QtGradientWidget::focalRadial() const
+{
+ return d_ptr->m_focalRadial;
+}
+
+void QtGradientWidget::setRadiusRadial(qreal radius)
+{
+ if (d_ptr->m_radiusRadial == radius)
+ return;
+
+ d_ptr->m_radiusRadial = radius;
+ update();
+}
+
+qreal QtGradientWidget::radiusRadial() const
+{
+ return d_ptr->m_radiusRadial;
+}
+
+void QtGradientWidget::setCentralConical(const QPointF &point)
+{
+ if (d_ptr->m_centralConical == point)
+ return;
+
+ d_ptr->m_centralConical = point;
+ update();
+}
+
+QPointF QtGradientWidget::centralConical() const
+{
+ return d_ptr->m_centralConical;
+}
+
+void QtGradientWidget::setAngleConical(qreal angle)
+{
+ if (d_ptr->m_angleConical == angle)
+ return;
+
+ d_ptr->m_angleConical = angle;
+ update();
+}
+
+qreal QtGradientWidget::angleConical() const
+{
+ return d_ptr->m_angleConical;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientwidget.h b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientwidget.h
new file mode 100644
index 0000000000..afb98bf764
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientwidget.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTGRADIENTWIDGET_H
+#define QTGRADIENTWIDGET_H
+
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class QtGradientWidget : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(bool backgroundCheckered READ isBackgroundCheckered WRITE setBackgroundCheckered)
+public:
+ QtGradientWidget(QWidget *parent = 0);
+ ~QtGradientWidget();
+
+ QSize minimumSizeHint() const;
+ QSize sizeHint() const;
+ int heightForWidth(int w) const;
+
+ bool isBackgroundCheckered() const;
+ void setBackgroundCheckered(bool checkered);
+
+ QGradientStops gradientStops() const;
+
+ void setGradientType(QGradient::Type type);
+ QGradient::Type gradientType() const;
+
+ void setGradientSpread(QGradient::Spread spread);
+ QGradient::Spread gradientSpread() const;
+
+ void setStartLinear(const QPointF &point);
+ QPointF startLinear() const;
+
+ void setEndLinear(const QPointF &point);
+ QPointF endLinear() const;
+
+ void setCentralRadial(const QPointF &point);
+ QPointF centralRadial() const;
+
+ void setFocalRadial(const QPointF &point);
+ QPointF focalRadial() const;
+
+ void setRadiusRadial(qreal radius);
+ qreal radiusRadial() const;
+
+ void setCentralConical(const QPointF &point);
+ QPointF centralConical() const;
+
+ void setAngleConical(qreal angle);
+ qreal angleConical() const;
+
+public slots:
+ void setGradientStops(const QGradientStops &stops);
+signals:
+
+ void startLinearChanged(const QPointF &point);
+ void endLinearChanged(const QPointF &point);
+ void centralRadialChanged(const QPointF &point);
+ void focalRadialChanged(const QPointF &point);
+ void radiusRadialChanged(qreal radius);
+ void centralConicalChanged(const QPointF &point);
+ void angleConicalChanged(qreal angle);
+
+protected:
+ void paintEvent(QPaintEvent *e);
+ void mousePressEvent(QMouseEvent *e);
+ void mouseReleaseEvent(QMouseEvent *e);
+ void mouseMoveEvent(QMouseEvent *e);
+ void mouseDoubleClickEvent(QMouseEvent *e);
+
+private:
+ QScopedPointer<class QtGradientWidgetPrivate> d_ptr;
+ Q_DECLARE_PRIVATE(QtGradientWidget)
+ Q_DISABLE_COPY(QtGradientWidget)
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qmldesigner/components/propertyeditor/resetwidget.cpp b/src/plugins/qmldesigner/components/propertyeditor/resetwidget.cpp
new file mode 100644
index 0000000000..3d74b2815e
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/resetwidget.cpp
@@ -0,0 +1,129 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+
+#include "qml.h"
+#include "resetwidget.h"
+#include <QVBoxLayout>
+#include <QHBoxLayout>
+#include <QStringList>
+#include <QTableWidget>
+#include <QHeaderView>
+#include <QPushButton>
+
+#include <QDebug>
+#include <QApplication>
+
+QML_DECLARE_TYPE(QmlDesigner::ResetWidget);
+QML_DEFINE_TYPE(Bauhaus, 1, 0, ResetWidget, QmlDesigner::ResetWidget);
+
+
+namespace QmlDesigner {
+
+
+ResetWidget::ResetWidget(QWidget *parent) : QGroupBox(parent), m_backendObject(0)
+{
+ m_vlayout = new QVBoxLayout(this);
+ m_vlayout->setContentsMargins(2,2,2,2);
+
+ QPushButton *b = new QPushButton(this);
+ b->setText("reset all properties");
+ m_vlayout->addWidget(b);
+
+ setLayout(m_vlayout);
+}
+
+void ResetWidget::resetView()
+{
+ m_tableWidget->clear();
+ delete m_tableWidget;
+ setupView();
+}
+
+void ResetWidget::setupView()
+{
+ m_tableWidget = new QTableWidget(this);
+ m_vlayout->addWidget(m_tableWidget);
+
+ m_tableWidget->setAlternatingRowColors(true);
+ m_tableWidget->horizontalHeader()->hide();
+ m_tableWidget->verticalHeader()->hide();
+ m_tableWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ m_tableWidget->setShowGrid(false);
+ m_tableWidget->setSortingEnabled(true);
+ m_tableWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+
+ const QMetaObject *metaObject = m_backendObject->metaObject();
+ int count = metaObject->propertyCount();
+
+ m_tableWidget->setColumnCount(3);
+ m_tableWidget->setRowCount(count);
+ for (int i=0;i<count;i++) {
+ QMetaProperty metaProperty = metaObject->property(i);
+ addPropertyItem(metaProperty.name(), i);
+ }
+ m_tableWidget->resizeRowsToContents();
+ m_tableWidget->resizeColumnsToContents();
+ m_tableWidget->sortItems(0);
+ m_tableWidget->setColumnWidth(2, 40);
+ parentWidget()->resize(parentWidget()->width(), count * 28);
+ qApp->processEvents();
+
+}
+
+void ResetWidget::addPropertyItem(const QString &name, int row)
+{
+ QTableWidgetItem *newItem = new QTableWidgetItem(name);
+ m_tableWidget->setItem(row, 0, newItem);
+ ResetWidgetPushButton *b = new ResetWidgetPushButton(m_tableWidget);
+ b->setName(name);
+ b->setText("reset");
+ connect(b, SIGNAL(pressed(const QString &)), this, SLOT(buttonPressed(const QString &)));
+ b->setMaximumHeight(15);
+ b->setMinimumHeight(10);
+ m_tableWidget->setCellWidget(row, 2, b);
+}
+
+void ResetWidget::buttonPressed(const QString &)
+{
+}
+
+ResetWidgetPushButton::ResetWidgetPushButton(QWidget *parent) : QPushButton(parent)
+{
+ connect(this, SIGNAL(pressed()), this, SLOT(myPressed()));
+}
+
+void ResetWidgetPushButton::myPressed()
+{
+ emit pressed(m_name);
+}
+
+
+}
+
diff --git a/src/plugins/qmldesigner/components/propertyeditor/resetwidget.h b/src/plugins/qmldesigner/components/propertyeditor/resetwidget.h
new file mode 100644
index 0000000000..ddc4c5c1de
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/resetwidget.h
@@ -0,0 +1,102 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef ResetWidget_h
+#define ResetWidget_h
+
+#include <QtGui/QGroupBox>
+#include <QtGui/QPushButton>
+
+class QListWidget;
+class QVBoxLayout;
+class QTableWidget;
+
+namespace QmlDesigner {
+
+class ResetWidget : public QGroupBox
+{
+
+ Q_OBJECT
+
+ Q_PROPERTY(QObject *backendObject READ backendObject WRITE setBackendObject)
+
+public slots:
+ void resetView();
+
+public:
+ ResetWidget(QWidget *parent = 0);
+ QObject* backendObject()
+ {
+ return m_backendObject;
+ }
+
+ void setBackendObject(QObject* backendObject)
+ {
+ m_backendObject = backendObject;
+ setupView();
+ }
+
+public slots:
+ void buttonPressed(const QString &name);
+
+
+private:
+ void setupView();
+
+ void addPropertyItem(const QString &name, int row);
+
+ QObject* m_backendObject;
+ QVBoxLayout *m_vlayout;
+ QTableWidget *m_tableWidget;
+
+};
+
+class ResetWidgetPushButton : public QPushButton
+{
+ Q_OBJECT
+
+public slots:
+ void myPressed();
+ void setName(const QString &name)
+ { m_name = name; }
+
+signals:
+ void pressed(const QString &name);
+
+public:
+ ResetWidgetPushButton(QWidget *parent = 0);
+private:
+ QString m_name;
+
+};
+
+}
+
+#endif //ResetWidget_h
+
diff --git a/src/plugins/qmldesigner/components/resources/images/checkbox_checked.png b/src/plugins/qmldesigner/components/resources/images/checkbox_checked.png
new file mode 100644
index 0000000000..18d7f6f011
--- /dev/null
+++ b/src/plugins/qmldesigner/components/resources/images/checkbox_checked.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/resources/images/checkbox_checked_hover.png b/src/plugins/qmldesigner/components/resources/images/checkbox_checked_hover.png
new file mode 100644
index 0000000000..14cc4c7d66
--- /dev/null
+++ b/src/plugins/qmldesigner/components/resources/images/checkbox_checked_hover.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/resources/images/checkbox_checked_pressed.png b/src/plugins/qmldesigner/components/resources/images/checkbox_checked_pressed.png
new file mode 100644
index 0000000000..25e4bde1d2
--- /dev/null
+++ b/src/plugins/qmldesigner/components/resources/images/checkbox_checked_pressed.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/resources/images/checkbox_unchecked.png b/src/plugins/qmldesigner/components/resources/images/checkbox_unchecked.png
new file mode 100644
index 0000000000..688c1a82d4
--- /dev/null
+++ b/src/plugins/qmldesigner/components/resources/images/checkbox_unchecked.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/resources/images/checkbox_unchecked_hover.png b/src/plugins/qmldesigner/components/resources/images/checkbox_unchecked_hover.png
new file mode 100644
index 0000000000..118c5896be
--- /dev/null
+++ b/src/plugins/qmldesigner/components/resources/images/checkbox_unchecked_hover.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/resources/images/checkbox_unchecked_pressed.png b/src/plugins/qmldesigner/components/resources/images/checkbox_unchecked_pressed.png
new file mode 100644
index 0000000000..670fc43ca7
--- /dev/null
+++ b/src/plugins/qmldesigner/components/resources/images/checkbox_unchecked_pressed.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/resources/images/down_arrow.png b/src/plugins/qmldesigner/components/resources/images/down_arrow.png
new file mode 100644
index 0000000000..20f3aa2436
--- /dev/null
+++ b/src/plugins/qmldesigner/components/resources/images/down_arrow.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/resources/images/down_arrow_disabled.png b/src/plugins/qmldesigner/components/resources/images/down_arrow_disabled.png
new file mode 100644
index 0000000000..d5b3655e49
--- /dev/null
+++ b/src/plugins/qmldesigner/components/resources/images/down_arrow_disabled.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/resources/images/frame.png b/src/plugins/qmldesigner/components/resources/images/frame.png
new file mode 100644
index 0000000000..302dae3962
--- /dev/null
+++ b/src/plugins/qmldesigner/components/resources/images/frame.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/resources/images/pushbutton.png b/src/plugins/qmldesigner/components/resources/images/pushbutton.png
new file mode 100644
index 0000000000..be3d533622
--- /dev/null
+++ b/src/plugins/qmldesigner/components/resources/images/pushbutton.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/resources/images/pushbutton_hover.png b/src/plugins/qmldesigner/components/resources/images/pushbutton_hover.png
new file mode 100644
index 0000000000..bba1b6d97c
--- /dev/null
+++ b/src/plugins/qmldesigner/components/resources/images/pushbutton_hover.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/resources/images/pushbutton_pressed.png b/src/plugins/qmldesigner/components/resources/images/pushbutton_pressed.png
new file mode 100644
index 0000000000..0644f6890d
--- /dev/null
+++ b/src/plugins/qmldesigner/components/resources/images/pushbutton_pressed.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/resources/images/radiobutton_checked.png b/src/plugins/qmldesigner/components/resources/images/radiobutton_checked.png
new file mode 100644
index 0000000000..8ab9157578
--- /dev/null
+++ b/src/plugins/qmldesigner/components/resources/images/radiobutton_checked.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/resources/images/radiobutton_checked_hover.png b/src/plugins/qmldesigner/components/resources/images/radiobutton_checked_hover.png
new file mode 100644
index 0000000000..d68cb009a7
--- /dev/null
+++ b/src/plugins/qmldesigner/components/resources/images/radiobutton_checked_hover.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/resources/images/radiobutton_checked_pressed.png b/src/plugins/qmldesigner/components/resources/images/radiobutton_checked_pressed.png
new file mode 100644
index 0000000000..e3cd5a59e4
--- /dev/null
+++ b/src/plugins/qmldesigner/components/resources/images/radiobutton_checked_pressed.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/resources/images/radiobutton_unchecked.png b/src/plugins/qmldesigner/components/resources/images/radiobutton_unchecked.png
new file mode 100644
index 0000000000..321a9a1558
--- /dev/null
+++ b/src/plugins/qmldesigner/components/resources/images/radiobutton_unchecked.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/resources/images/radiobutton_unchecked_hover.png b/src/plugins/qmldesigner/components/resources/images/radiobutton_unchecked_hover.png
new file mode 100644
index 0000000000..666a3b0bdd
--- /dev/null
+++ b/src/plugins/qmldesigner/components/resources/images/radiobutton_unchecked_hover.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/resources/images/radiobutton_unchecked_pressed.png b/src/plugins/qmldesigner/components/resources/images/radiobutton_unchecked_pressed.png
new file mode 100644
index 0000000000..c4b0567aa9
--- /dev/null
+++ b/src/plugins/qmldesigner/components/resources/images/radiobutton_unchecked_pressed.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/resources/images/sizegrip.png b/src/plugins/qmldesigner/components/resources/images/sizegrip.png
new file mode 100644
index 0000000000..350583aaac
--- /dev/null
+++ b/src/plugins/qmldesigner/components/resources/images/sizegrip.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/resources/images/spindown.png b/src/plugins/qmldesigner/components/resources/images/spindown.png
new file mode 100644
index 0000000000..9283d40d6c
--- /dev/null
+++ b/src/plugins/qmldesigner/components/resources/images/spindown.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/resources/images/spindown_hover.png b/src/plugins/qmldesigner/components/resources/images/spindown_hover.png
new file mode 100644
index 0000000000..851d0af2b1
--- /dev/null
+++ b/src/plugins/qmldesigner/components/resources/images/spindown_hover.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/resources/images/spindown_off.png b/src/plugins/qmldesigner/components/resources/images/spindown_off.png
new file mode 100644
index 0000000000..a90ab3f038
--- /dev/null
+++ b/src/plugins/qmldesigner/components/resources/images/spindown_off.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/resources/images/spindown_pressed.png b/src/plugins/qmldesigner/components/resources/images/spindown_pressed.png
new file mode 100644
index 0000000000..cab3eae28f
--- /dev/null
+++ b/src/plugins/qmldesigner/components/resources/images/spindown_pressed.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/resources/images/spinup.png b/src/plugins/qmldesigner/components/resources/images/spinup.png
new file mode 100644
index 0000000000..9250c0c3b8
--- /dev/null
+++ b/src/plugins/qmldesigner/components/resources/images/spinup.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/resources/images/spinup_hover.png b/src/plugins/qmldesigner/components/resources/images/spinup_hover.png
new file mode 100644
index 0000000000..8793a9890e
--- /dev/null
+++ b/src/plugins/qmldesigner/components/resources/images/spinup_hover.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/resources/images/spinup_off.png b/src/plugins/qmldesigner/components/resources/images/spinup_off.png
new file mode 100644
index 0000000000..02dad1fb29
--- /dev/null
+++ b/src/plugins/qmldesigner/components/resources/images/spinup_off.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/resources/images/spinup_pressed.png b/src/plugins/qmldesigner/components/resources/images/spinup_pressed.png
new file mode 100644
index 0000000000..8acb9c176e
--- /dev/null
+++ b/src/plugins/qmldesigner/components/resources/images/spinup_pressed.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/resources/images/up_arrow.png b/src/plugins/qmldesigner/components/resources/images/up_arrow.png
new file mode 100644
index 0000000000..048b2fd2ff
--- /dev/null
+++ b/src/plugins/qmldesigner/components/resources/images/up_arrow.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/resources/images/up_arrow_disabled.png b/src/plugins/qmldesigner/components/resources/images/up_arrow_disabled.png
new file mode 100644
index 0000000000..5fe22ba043
--- /dev/null
+++ b/src/plugins/qmldesigner/components/resources/images/up_arrow_disabled.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/resources/resources.pri b/src/plugins/qmldesigner/components/resources/resources.pri
new file mode 100644
index 0000000000..f2ad9b0f6b
--- /dev/null
+++ b/src/plugins/qmldesigner/components/resources/resources.pri
@@ -0,0 +1,3 @@
+VPATH += $$PWD
+INCLUDEPATH += $$PWD
+RESOURCES += resources.qrc \ No newline at end of file
diff --git a/src/plugins/qmldesigner/components/resources/resources.qrc b/src/plugins/qmldesigner/components/resources/resources.qrc
new file mode 100644
index 0000000000..9968a0971e
--- /dev/null
+++ b/src/plugins/qmldesigner/components/resources/resources.qrc
@@ -0,0 +1,37 @@
+<RCC>
+ <qresource prefix="/qmldesigner">
+ <file>templates/Standard/Form.xml</file>
+ <file>stylesheet.css</file>
+ <file>toolbutton.css</file>
+ <file>scrollbar.css</file>
+ <file>images/checkbox_checked.png</file>
+ <file>images/checkbox_checked_hover.png</file>
+ <file>images/checkbox_checked_pressed.png</file>
+ <file>images/checkbox_unchecked.png</file>
+ <file>images/checkbox_unchecked_hover.png</file>
+ <file>images/checkbox_unchecked_pressed.png</file>
+ <file>images/down_arrow.png</file>
+ <file>images/down_arrow_disabled.png</file>
+ <file>images/frame.png</file>
+ <file>images/pushbutton.png</file>
+ <file>images/pushbutton_hover.png</file>
+ <file>images/pushbutton_pressed.png</file>
+ <file>images/radiobutton_checked.png</file>
+ <file>images/radiobutton_checked_hover.png</file>
+ <file>images/radiobutton_checked_pressed.png</file>
+ <file>images/radiobutton_unchecked.png</file>
+ <file>images/radiobutton_unchecked_hover.png</file>
+ <file>images/radiobutton_unchecked_pressed.png</file>
+ <file>images/sizegrip.png</file>
+ <file>images/spindown.png</file>
+ <file>images/spindown_hover.png</file>
+ <file>images/spindown_off.png</file>
+ <file>images/spindown_pressed.png</file>
+ <file>images/spinup.png</file>
+ <file>images/spinup_hover.png</file>
+ <file>images/spinup_off.png</file>
+ <file>images/spinup_pressed.png</file>
+ <file>images/up_arrow.png</file>
+ <file>images/up_arrow_disabled.png</file>
+ </qresource>
+</RCC>
diff --git a/src/plugins/qmldesigner/components/resources/scrollbar.css b/src/plugins/qmldesigner/components/resources/scrollbar.css
new file mode 100644
index 0000000000..a540b67b71
--- /dev/null
+++ b/src/plugins/qmldesigner/components/resources/scrollbar.css
@@ -0,0 +1,42 @@
+ QScrollBar:vertical {
+ border: 1px solid #8F8F8F;
+ background: #707070;
+ width: 10px;
+ margin: 2px 0 2px 0;
+ }
+
+ QScrollBar::handle:vertical {
+ background: qlineargradient(x1: 0, y1: 0, x2: 0.5, y2: 0, x3: 0.8, y3: 0,
+ stop: 0 #cEcEcE,
+ stop: 1 #8E8E8E,
+ stop: 2 #101010);
+ min-height: 20px;
+ border-radius: 10px;
+ }
+
+ QScrollBar::add-line:vertical {
+ border: 0px solid grey;
+ background: #808080;
+ height: 0px;
+ subcontrol-position: bottom;
+ subcontrol-origin: margin;
+ }
+
+ QScrollBar::sub-line:vertical {
+ border: 0px solid grey;
+ background: #32CC99;
+ height: 0px;
+ subcontrol-position: top;
+ subcontrol-origin: margin;
+ }
+ QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical {
+ border: 2px solid grey;
+ width: 3px;
+ height: 3px;
+ background: white;
+ }
+
+ QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {
+ background: none;
+ }
+ \ No newline at end of file
diff --git a/src/plugins/qmldesigner/components/resources/stylesheet.css b/src/plugins/qmldesigner/components/resources/stylesheet.css
new file mode 100644
index 0000000000..b660897c29
--- /dev/null
+++ b/src/plugins/qmldesigner/components/resources/stylesheet.css
@@ -0,0 +1,72 @@
+QFrame {
+ border: 2px;
+ background-color: #707070;
+}
+
+QLabel {
+ border: none;
+ border-image: none;
+ padding: 0;
+ background: none;
+ color: #E1E1E1;
+}
+
+QScrollArea {
+ border: 0px;
+ background-color: #707070;
+}
+
+QStackedWidget {
+ border: 0px;
+ background-color: #707070;
+}
+
+
+QGraphicsView {
+ border: 0px;
+ background-color: #707070;
+}
+
+QTabWidget {
+ border: 0px;
+ background-color: #707070;
+}
+
+QTabWidget::pane { /* The tab widget frame */
+ border: 0px;
+ background-color: #707070;
+}
+
+QLineEdit
+{
+ border: 2px solid #8F8F8F;
+ border-radius: 4px;
+ padding: 0 8px;
+ background-color: white;
+ selection-background-color: darkgray;
+}
+
+ QTreeView {
+ color: white;
+ selection-color: white
+ }
+
+ QTreeView::item:selected {
+ color: white;
+ }
+
+ QListView {
+ color: white;
+ selection-color: white
+ }
+
+ QListView::item:selected {
+ color: white;
+ }
+
+QComboBox QAbstractItemView {
+ color: black;
+ border: 2px solid darkgray;
+ selection-background-color: lightgray;
+ }
+ \ No newline at end of file
diff --git a/src/plugins/qmldesigner/components/resources/templates/Standard/Form.xml b/src/plugins/qmldesigner/components/resources/templates/Standard/Form.xml
new file mode 100644
index 0000000000..4a9aa660d5
--- /dev/null
+++ b/src/plugins/qmldesigner/components/resources/templates/Standard/Form.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<QWidget objectName="Form" width="186" height="141">
+ <windowTitle><?i18n?>Form</windowTitle>
+ <QVBoxLayout objectName="verticalLayout">
+ <!--Start of QLayoutItem 1--><QLabel objectName="label">
+ <text><?i18n?>Hello world</text>
+ </QLabel>
+ <!--End of QLayoutItem 1--><!--Start of QLayoutItem 1--><QPlainTextEdit objectName="plainTextEdit"/>
+ <!--End of QLayoutItem 1--></QVBoxLayout>
+</QWidget>
diff --git a/src/plugins/qmldesigner/components/resources/toolbutton.css b/src/plugins/qmldesigner/components/resources/toolbutton.css
new file mode 100644
index 0000000000..ccae16b91a
--- /dev/null
+++ b/src/plugins/qmldesigner/components/resources/toolbutton.css
@@ -0,0 +1,23 @@
+QToolButton {
+ border-image: url(:/qmldesigner/images/pushbutton.png) 3;
+ border-width: 3;
+ border-radius: 6px;
+ margin: 4px 4px 4px 4px;
+ color: white;
+}
+
+QToolButton:hover {
+ border-image: url(:/qmldesigner/images/pushbutton_hover.png) 3;
+ border-width: 3;
+}
+
+QToolButton:pressed {
+ border-image: url(:/qmldesigner/images/pushbutton_pressed.png) 3;
+ border-width: 3;
+}
+
+QToolButton:checked
+{
+ border-image: url(:/qmldesigner/images/pushbutton_pressed.png) 3;
+ border-width: 3;
+}
diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditor.pri b/src/plugins/qmldesigner/components/stateseditor/stateseditor.pri
new file mode 100644
index 0000000000..4905aec4af
--- /dev/null
+++ b/src/plugins/qmldesigner/components/stateseditor/stateseditor.pri
@@ -0,0 +1,10 @@
+VPATH += $$PWD
+INCLUDEPATH += $$PWD
+SOURCES += stateseditorwidget.cpp \
+ stateseditormodel.cpp \
+ stateseditorview.cpp
+HEADERS += stateseditorwidget.h \
+ stateseditormodel.h \
+ stateseditorview.h
+RESOURCES += $$PWD/stateseditor.qrc
+OTHER_FILES +=$$PWD/stateslist.qml
diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditor.qrc b/src/plugins/qmldesigner/components/stateseditor/stateseditor.qrc
new file mode 100644
index 0000000000..d23bab446d
--- /dev/null
+++ b/src/plugins/qmldesigner/components/stateseditor/stateseditor.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/stateseditor" >
+ <file>stateslist.qml</file>
+ </qresource>
+</RCC>
diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.cpp b/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.cpp
new file mode 100644
index 0000000000..e9b4302899
--- /dev/null
+++ b/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.cpp
@@ -0,0 +1,147 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "stateseditormodel.h"
+#include "stateseditorview.h"
+
+#include <QtCore/QDebug>
+
+enum {
+ debug = false
+};
+
+
+namespace QmlDesigner {
+namespace Internal {
+
+StatesEditorModel::StatesEditorModel(QObject *parent) :
+ QAbstractListModel(parent)
+{
+
+ QHash<int, QByteArray> roleNames;
+ roleNames.insert(StateNameRole, "stateName");
+ roleNames.insert(StatesPixmapRole, "statePixmap");
+ setRoleNames(roleNames);
+}
+
+
+int StatesEditorModel::count() const
+{
+ return m_stateNames.count();
+}
+
+int StatesEditorModel::rowCount(const QModelIndex &parent) const
+{
+ if (parent.isValid())
+ return 0;
+ return m_stateNames.count();
+}
+
+QVariant StatesEditorModel::data(const QModelIndex &index, int role) const
+{
+ if (index.parent().isValid() || index.column() != 0)
+ return QVariant();
+
+ QVariant result;
+ switch (role) {
+ case StateNameRole: {
+ if ((index.row()==0) && (m_stateNames.at(index.row())==""))
+ result = QString("base state");
+ else
+ result = m_stateNames.at(index.row());
+ break;
+ }
+ case StatesPixmapRole: {
+ // TODO: Maybe cache this?
+ if (!m_statesView.isNull()) {
+ result = m_statesView->renderState(index.row());
+ }
+ break;
+ }
+ }
+
+ return result;
+}
+
+void StatesEditorModel::insertState(int i, const QString &name)
+{
+ beginInsertRows(QModelIndex(), i, i);
+
+ m_stateNames.insert(i, name);
+
+ endInsertRows();
+
+ emit dataChanged(createIndex(i, 0), createIndex(i, 0));
+ emit countChanged();
+}
+
+void StatesEditorModel::removeState(int i)
+{
+ beginRemoveRows(QModelIndex(), i, i);
+
+ m_stateNames.removeAt(i);
+
+ endRemoveRows();
+
+ emit dataChanged(createIndex(i, 0), createIndex(i, 0));
+ emit countChanged();
+}
+
+void StatesEditorModel::renameState(int i, const QString &newName)
+{
+ Q_ASSERT(i > 0 && i < m_stateNames.count());
+
+ if (m_stateNames[i] != newName) {
+ m_stateNames.replace(i, newName);
+ m_statesView->renameState(i,newName);
+
+ emit dataChanged(createIndex(i, 0), createIndex(i, 0));
+ }
+}
+
+void StatesEditorModel::updateState(int i)
+{
+ Q_ASSERT(i >= 0 && i < m_stateNames.count());
+
+ emit dataChanged(createIndex(i, 0), createIndex(i, 0));
+ emit countChanged();
+}
+
+void StatesEditorModel::setStatesEditorView(StatesEditorView *statesView)
+{
+ m_statesView = statesView;
+}
+
+void StatesEditorModel::emitChangedToState(int n)
+{
+ emit changedToState(n);
+}
+
+} // namespace Internal
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.h b/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.h
new file mode 100644
index 0000000000..13fe4b9d58
--- /dev/null
+++ b/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.h
@@ -0,0 +1,79 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef STATESEDITORMODEL_H
+#define STATESEDITORMODEL_H
+
+#include <QAbstractListModel>
+#include <QWeakPointer>
+
+#include <stateseditorview.h>
+
+namespace QmlDesigner {
+
+namespace Internal {
+
+class StatesEditorModel : public QAbstractListModel
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+
+ enum {
+ StateNameRole = Qt::DisplayRole,
+ StatesPixmapRole = Qt::UserRole
+ };
+
+public:
+ StatesEditorModel(QObject *parent);
+
+ int count() const;
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+
+ void insertState(int i, const QString &name);
+ void removeState(int i);
+ Q_INVOKABLE void renameState(int i, const QString &newName);
+ void updateState(int i);
+ void setStatesEditorView(StatesEditorView *statesView);
+ void emitChangedToState(int n);
+
+signals:
+ void countChanged();
+ void changedToState(int n);
+
+private:
+ QList<QString> m_stateNames;
+ QWeakPointer<StatesEditorView> m_statesView;
+};
+
+} // namespace Itnernal
+} // namespace QmlDesigner
+
+#endif // STATESEDITORMODEL_H
diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp
new file mode 100644
index 0000000000..a53c967e54
--- /dev/null
+++ b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp
@@ -0,0 +1,438 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "stateseditorview.h"
+#include "stateseditormodel.h"
+#include <customnotifications.h>
+
+#include <QPainter>
+#include <QTimerEvent>
+#include <QDebug>
+
+enum {
+ debug = false
+};
+
+namespace QmlDesigner {
+namespace Internal {
+
+/**
+ We always have 'one' current state, where we get updates from (see sceneChanged()). In case
+ the current state is the base state, we render the base state + all other states.
+ */
+StatesEditorView::StatesEditorView(StatesEditorModel *editorModel, QObject *parent) :
+ QmlModelView(parent),
+ m_editorModel(editorModel)
+{
+ Q_ASSERT(m_editorModel);
+
+
+ connect(nodeInstanceView(), SIGNAL(instanceRemoved(NodeInstance)), this, SLOT(sceneChanged()));
+ connect(nodeInstanceView(), SIGNAL(transformPropertyChanged(NodeInstance)), this, SLOT(sceneChanged()));
+ connect(nodeInstanceView(), SIGNAL(parentPropertyChanged(NodeInstance)), this, SLOT(sceneChanged()));
+ connect(nodeInstanceView(), SIGNAL(otherPropertyChanged(NodeInstance)), this, SLOT(sceneChanged()));
+ connect(nodeInstanceView(), SIGNAL(updateItem(NodeInstance)), this, SLOT(sceneChanged()));
+}
+
+void StatesEditorView::setCurrentStateSilent(int index)
+{
+ // TODO
+ QmlModelState state(m_modelStates.at(index));
+ if (!state.isValid())
+ return;
+ if (state == currentState())
+ return;
+ QmlModelView::stateChanged(state, currentState());
+}
+
+void StatesEditorView::setCurrentState(int index)
+{
+ // TODO
+ if (m_modelStates.indexOf(currentState()) == index)
+ return;
+
+ if (index >= m_modelStates.count())
+ return;
+
+ QmlModelState state(m_modelStates.at(index));
+ Q_ASSERT(state.isValid());
+ QmlModelView::setCurrentState(state);
+}
+
+
+void StatesEditorView::setBackCurrentState(int index, const QmlModelState &oldState)
+{
+ // TODO
+ QmlModelState state(m_modelStates.at(index));
+ if (!state.isValid())
+ return;
+ if (state == oldState)
+ return;
+ QmlModelView::stateChanged(oldState, state);
+}
+
+void StatesEditorView::createState(const QString &name)
+{
+ stateRootNode().states().addState(name);
+}
+
+void StatesEditorView::removeState(int index)
+{
+ Q_ASSERT(index > 0 && index < m_modelStates.size());
+ QmlModelState state = m_modelStates.at(index);
+ Q_ASSERT(state.isValid());
+ m_modelStates.removeAll(state);
+ m_editorModel->removeState(index);
+ QmlModelView::setCurrentState(baseState());
+ state.destroy();
+}
+
+void StatesEditorView::renameState(int index,const QString &newName)
+{
+ Q_ASSERT(index > 0 && index < m_modelStates.size());
+ QmlModelState state = m_modelStates.at(index);
+ Q_ASSERT(state.isValid());
+ if (state.name() != newName) {
+ // Jump to base state for the change
+ QmlModelState oldState = currentState();
+ setCurrentStateSilent(0);
+ state.setName(newName);
+ setBackCurrentState(0, oldState);
+ }
+}
+
+void StatesEditorView::duplicateCurrentState(int index)
+{
+ Q_ASSERT(index > 0 && index < m_modelStates.size());
+ QmlModelState state = m_modelStates.at(index);
+ Q_ASSERT(state.isValid());
+ QString newName = state.name();
+
+ // Strip out numbers at the end of the string
+ QRegExp regEx(QString("[0-9]+$"));
+ int numberIndex = newName.indexOf(regEx);
+ if ((numberIndex != -1) && (numberIndex+regEx.matchedLength()==newName.length()))
+ newName = newName.left(numberIndex);
+
+ int i = 1;
+ QStringList stateNames = state.stateGroup().names();
+ while (stateNames.contains(newName + QString::number(i)))
+ i++;
+ state.duplicate(newName + QString::number(i));
+}
+
+void StatesEditorView::modelAttached(Model *model)
+{
+ if (model == QmlModelView::model())
+ return;
+
+ Q_ASSERT(model);
+ QmlModelView::modelAttached(model);
+ Q_ASSERT(m_editorModel->rowCount(QModelIndex()) == 0);
+
+ // find top level states
+ m_stateRootNode = QmlItemNode(rootModelNode());
+ if (!m_stateRootNode.isValid())
+ return;
+
+ clearModelStates();
+
+ // Add base state
+ m_modelStates.insert(0, baseState());
+ m_editorModel->insertState(0, baseState().name());
+
+ // Add custom states
+ for (int i = 0; i < m_stateRootNode.states().allStates().size(); ++i) {
+ QmlModelState state = QmlItemNode(rootModelNode()).states().allStates().at(i);
+ insertModelState(i, state);
+ }
+}
+
+void StatesEditorView::modelAboutToBeDetached(Model *model)
+{
+ if (debug)
+ qDebug() << __FUNCTION__;
+
+ clearModelStates();
+
+ QmlModelView::modelAboutToBeDetached(model);
+}
+
+void StatesEditorView::propertiesAboutToBeRemoved(const QList<AbstractProperty>& propertyList)
+{
+ foreach (const AbstractProperty &property, propertyList) {
+ // remove all states except base state
+ if ((property.name()=="states") && (property.parentModelNode().isRootNode())) {
+ foreach (const QmlModelState &state, m_modelStates) {
+ if (!state.isBaseState())
+ removeModelState(state);
+ }
+ }
+ }
+}
+
+void StatesEditorView::propertiesRemoved(const QList<AbstractProperty>& propertyList)
+{
+ QmlModelView::propertiesRemoved(propertyList);
+ foreach (const AbstractProperty &property, propertyList) {
+ ModelNode node (property.parentModelNode().parentProperty().parentModelNode());
+ if (QmlModelState(node).isValid()) {
+ startUpdateTimer(modelStateIndex(node) + 1, 0);
+ }
+ }
+}
+
+void StatesEditorView::variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags propertyChange)
+{
+ QmlModelView::variantPropertiesChanged(propertyList, propertyChange);
+ foreach (const VariantProperty &property, propertyList) {
+ ModelNode node (property.parentModelNode());
+ if (QmlModelState(node).isValid() && (property.name() == QLatin1String("name"))) {
+ int index = m_modelStates.indexOf(node);
+ if (index != -1)
+ m_editorModel->renameState(index, property.value().toString());
+ }
+ }
+ foreach (const AbstractProperty &property, propertyList) {
+ ModelNode node (property.parentModelNode().parentProperty().parentModelNode());
+ if (QmlModelState(node).isValid()) {
+ startUpdateTimer(modelStateIndex(node) + 1, 0);
+ } else { //a change to the base state update all
+ for (int i = 0; i < m_modelStates.count(); ++i)
+ startUpdateTimer(i, 0);
+ }
+ }
+}
+
+void StatesEditorView::nodeAboutToBeRemoved(const ModelNode &removedNode)
+{
+ if (removedNode.parentProperty().parentModelNode() == m_stateRootNode
+ && QmlModelState(removedNode).isValid()) {
+ removeModelState(removedNode);
+ }
+ QmlModelView::nodeAboutToBeRemoved(removedNode);
+}
+
+
+void StatesEditorView::nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange)
+{
+ QmlModelView::nodeReparented(node, newPropertyParent, oldPropertyParent, propertyChange);
+
+ // this would be sliding
+ Q_ASSERT(newPropertyParent != oldPropertyParent);
+
+ if (QmlModelState(node).isValid()) {
+ if (oldPropertyParent.parentModelNode() == m_stateRootNode) {
+ if (oldPropertyParent.isNodeListProperty()
+ && oldPropertyParent.name() == "states") {
+ removeModelState(node);
+ } else {
+ qWarning() << "States Editor: Reparented model state was not in states property list";
+ }
+ }
+
+ if (newPropertyParent.parentModelNode() == m_stateRootNode) {
+ if (newPropertyParent.isNodeListProperty()
+ && newPropertyParent.name() == "states") {
+ NodeListProperty statesProperty = newPropertyParent.toNodeListProperty();
+ int index = statesProperty.toModelNodeList().indexOf(node);
+ Q_ASSERT(index >= 0);
+ insertModelState(index, node);
+ } else {
+ qWarning() << "States Editor: Reparented model state is not in the states property list";
+ }
+ }
+ }
+}
+
+void StatesEditorView::nodeSlidedToIndex(const NodeListProperty &listProperty, int newIndex, int oldIndex)
+{
+ QmlModelView::nodeSlidedToIndex(listProperty, newIndex, oldIndex);
+ if (listProperty.parentModelNode() == m_stateRootNode
+ && listProperty.name() == "states") {
+ int index = newIndex;
+ if (oldIndex < newIndex)
+ --index;
+ QmlModelState state = listProperty.toModelNodeList().at(index);
+ if (state.isValid()) {
+ Q_ASSERT(oldIndex == modelStateIndex(state));
+ removeModelState(state);
+ insertModelState(newIndex, state);
+ Q_ASSERT(newIndex == modelStateIndex(state));
+ }
+ }
+}
+
+void StatesEditorView::stateChanged(const QmlModelState &newQmlModelState, const QmlModelState &oldQmlModelState)
+{
+ QmlModelView::stateChanged(newQmlModelState, oldQmlModelState);
+
+ if (newQmlModelState.isBaseState())
+ m_editorModel->emitChangedToState(0);
+ else
+ m_editorModel->emitChangedToState(m_modelStates.indexOf(newQmlModelState));
+}
+
+void StatesEditorView::customNotification(const AbstractView *view, const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> &data)
+{
+ QmlModelView::customNotification(view, identifier, nodeList, data);
+ if (identifier == StartRewriterAmend) {
+ m_oldRewriterAmendState = currentState();
+ QmlModelView::setCurrentState(baseState());
+ } else if (identifier == EndRewriterAmend) {
+ if (m_oldRewriterAmendState.isValid())
+ QmlModelView::setCurrentState(m_oldRewriterAmendState);
+ }
+}
+
+QPixmap StatesEditorView::renderState(int i)
+{
+ Q_ASSERT(i >= 0 && i < m_modelStates.size());
+ nodeInstanceView()->setBlockChangeSignal(true);
+ QmlModelState oldState = currentState();
+ setCurrentStateSilent(i);
+
+ Q_ASSERT(nodeInstanceView());
+
+ const int checkerbordSize= 10;
+ QPixmap tilePixmap(checkerbordSize * 2, checkerbordSize * 2);
+ tilePixmap.fill(Qt::white);
+ QPainter tilePainter(&tilePixmap);
+ QColor color(220, 220, 220);
+ tilePainter.fillRect(0, 0, checkerbordSize, checkerbordSize, color);
+ tilePainter.fillRect(checkerbordSize, checkerbordSize, checkerbordSize, checkerbordSize, color);
+ tilePainter.end();
+
+
+ QSize pixmapSize(nodeInstanceView()->sceneRect().size().toSize());
+ if (pixmapSize.width() > 150 || pixmapSize.height() > 150) // sensible maximum size
+ pixmapSize.scale(QSize(150, 150), Qt::KeepAspectRatio);
+ QPixmap pixmap(pixmapSize);
+
+ QPainter painter(&pixmap);
+ painter.drawTiledPixmap(pixmap.rect(), tilePixmap);
+ nodeInstanceView()->render(&painter, pixmap.rect(), nodeInstanceView()->sceneRect());
+
+ setBackCurrentState(i, oldState);
+ nodeInstanceView()->setBlockChangeSignal(false);
+ Q_ASSERT(oldState == currentState());
+
+ return pixmap;
+}
+
+void StatesEditorView::sceneChanged()
+{
+ // If we are in base state we have to update the pixmaps of all states
+ // otherwise only the pixmpap for the current state
+
+ if (currentState().isValid()) { //during setup we might get sceneChanged signals with an invalid currentState()
+ if (currentState().isBaseState()) {
+ for (int i = 0; i < m_modelStates.count(); ++i)
+ startUpdateTimer(i, i * 80);
+ } else {
+ startUpdateTimer(modelStateIndex(currentState()) + 1, 0);
+ }
+ }
+}
+
+void StatesEditorView::startUpdateTimer(int i, int offset) {
+ if (i < m_updateTimerIdList.size() && m_updateTimerIdList.at(i) != 0)
+ return;
+ // TODO: Add an offset so not all states are rendered at once
+ Q_ASSERT(i >= 0 && i < m_modelStates.count());
+ if (i < m_updateTimerIdList.size() && i > 0)
+ if (m_updateTimerIdList.at(i))
+ killTimer(m_updateTimerIdList.at(i));
+ int j = i;
+
+ while (m_updateTimerIdList.size() <= i) {
+ m_updateTimerIdList.insert(j, 0);
+ j++;
+ }
+ m_updateTimerIdList[i] = startTimer(100 + offset);
+}
+
+// index without base state
+void StatesEditorView::insertModelState(int i, const QmlModelState &state)
+{
+ Q_ASSERT(state.isValid());
+ Q_ASSERT(!state.isBaseState());
+ // For m_modelStates / m_editorModel, i=0 is base state
+ m_modelStates.insert(i+1, state);
+ m_editorModel->insertState(i+1, state.name());
+}
+
+void StatesEditorView::removeModelState(const QmlModelState &state)
+{
+ Q_ASSERT(state.isValid());
+ Q_ASSERT(!state.isBaseState());
+ int index = m_modelStates.indexOf(state);
+ if (index != -1) {
+ m_modelStates.removeOne(state);
+
+ if (m_updateTimerIdList.contains(index)) {
+ killTimer(m_updateTimerIdList[index]);
+ m_updateTimerIdList[index] = 0;
+ }
+ m_editorModel->removeState(index);
+ }
+}
+
+void StatesEditorView::clearModelStates()
+{
+ // For m_modelStates / m_editorModel, i=0 is base state
+ while (m_modelStates.size()) {
+ m_modelStates.removeFirst();
+ m_editorModel->removeState(0);
+ }
+}
+
+// index without base state
+int StatesEditorView::modelStateIndex(const QmlModelState &state)
+{
+ return m_modelStates.indexOf(state) - 1;
+}
+
+void StatesEditorView::timerEvent(QTimerEvent *event)
+{
+ int index = m_updateTimerIdList.indexOf(event->timerId());
+ if (index > -1) {
+ event->accept();
+ Q_ASSERT(index >= 0);
+ if (index < m_modelStates.count()) //there might be updates for a state already deleted 100ms are long
+ m_editorModel->updateState(index);
+ killTimer(m_updateTimerIdList[index]);
+ m_updateTimerIdList[index] = 0;
+ } else {
+ QmlModelView::timerEvent(event);
+ }
+}
+
+} // namespace Internal
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditorview.h b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.h
new file mode 100644
index 0000000000..284d939fb0
--- /dev/null
+++ b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.h
@@ -0,0 +1,100 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef STATESEDITORVIEW_H
+#define STATESEDITORVIEW_H
+
+#include <qmlmodelview.h>
+
+namespace QmlDesigner {
+
+namespace Internal {
+
+class StatesEditorModel;
+
+class StatesEditorView : public QmlModelView {
+ Q_OBJECT
+
+public:
+ StatesEditorView(StatesEditorModel *model, QObject *parent = 0);
+
+ void setCurrentState(int index);
+ void setCurrentStateSilent(int index);
+ void setBackCurrentState(int index, const QmlModelState &oldState);
+ void createState(const QString &name);
+ void removeState(int index);
+ void renameState(int index,const QString &newName);
+ void duplicateCurrentState(int index);
+
+ QPixmap renderState(int i);
+ QmlItemNode stateRootNode() { return m_stateRootNode; }
+
+ // AbstractView
+ void modelAttached(Model *model);
+ void modelAboutToBeDetached(Model *model);
+ void propertiesAboutToBeRemoved(const QList<AbstractProperty>& propertyList);
+ void propertiesRemoved(const QList<AbstractProperty>& propertyList);
+ void variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags propertyChange);
+
+ void nodeAboutToBeRemoved(const ModelNode &removedNode);
+ void nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange);
+ void nodeSlidedToIndex(const NodeListProperty &listProperty, int newIndex, int oldIndex);
+
+ // QmlModelView
+ void stateChanged(const QmlModelState &newQmlModelState, const QmlModelState &oldQmlModelState);
+
+ void customNotification(const AbstractView *view, const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> &data);
+
+
+protected:
+ void timerEvent(QTimerEvent*);
+
+private slots:
+ void sceneChanged();
+
+private:
+ void insertModelState(int i, const QmlModelState &state);
+ void removeModelState(const QmlModelState &state);
+ void clearModelStates();
+ int modelStateIndex(const QmlModelState &state);
+
+ void startUpdateTimer(int i, int offset);
+
+ QList<QmlModelState> m_modelStates;
+ StatesEditorModel *m_editorModel;
+ QmlItemNode m_stateRootNode;
+
+ QList<int> m_updateTimerIdList;
+ QmlModelState m_oldRewriterAmendState;
+};
+
+} // namespace Internal
+} // namespace QmlDesigner
+
+#endif // STATESEDITORVIEW_H
diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.cpp b/src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.cpp
new file mode 100644
index 0000000000..d2950d9a15
--- /dev/null
+++ b/src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.cpp
@@ -0,0 +1,218 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "stateseditorwidget.h"
+#include "stateseditormodel.h"
+#include "stateseditorview.h"
+
+#include <qmlitemnode.h>
+#include <invalidargumentexception.h>
+#include <invalidqmlsourceexception.h>
+
+#include <QtCore/QFile>
+#include <qapplication.h>
+
+#include <QtGui/QBoxLayout>
+#include <QtGui/QListWidget>
+#include <QtGui/QPushButton>
+#include <QtGui/QMessageBox>
+
+#include <QtDeclarative/QmlView>
+#include <QtDeclarative/QmlContext>
+#include <QtDeclarative/QmlEngine>
+#include <QtDeclarative/QmlGraphicsItem>
+
+enum {
+ debug = false
+};
+
+namespace QmlDesigner {
+
+namespace Internal {
+
+class StatesEditorWidgetPrivate : QObject
+{
+ Q_OBJECT
+
+private:
+ StatesEditorWidgetPrivate(StatesEditorWidget *q);
+
+ int currentIndex() const;
+ void setCurrentIndex(int i);
+
+ bool validStateName(const QString &name) const;
+
+private slots:
+ void currentStateChanged();
+ void addState();
+ void removeState();
+ void duplicateCurrentState();
+
+private:
+ StatesEditorWidget *m_q;
+ QWeakPointer<Model> model;
+ QWeakPointer<QmlView> listView;
+ QWeakPointer<Internal::StatesEditorModel> statesEditorModel;
+ QWeakPointer<Internal::StatesEditorView> statesEditorView;
+ friend class QmlDesigner::StatesEditorWidget;
+};
+
+StatesEditorWidgetPrivate::StatesEditorWidgetPrivate(StatesEditorWidget *q) :
+ QObject(q),
+ m_q(q)
+{
+}
+
+int StatesEditorWidgetPrivate::currentIndex() const
+{
+ Q_ASSERT(listView->root());
+ Q_ASSERT(listView->root()->property("currentStateIndex").isValid());
+ return listView->root()->property("currentStateIndex").toInt();
+}
+
+void StatesEditorWidgetPrivate::setCurrentIndex(int i)
+{
+ listView->root()->setProperty("currentStateIndex", i);
+}
+
+bool StatesEditorWidgetPrivate::validStateName(const QString &name) const
+{
+ if (name == tr("base state"))
+ return false;
+ QList<QmlModelState> modelStates = statesEditorView->stateRootNode().states().allStates();
+ foreach (const QmlModelState &state, modelStates) {
+ if (state.name() == name)
+ return false;
+ }
+ return true;
+}
+
+void StatesEditorWidgetPrivate::currentStateChanged()
+{
+ statesEditorView->setCurrentState(currentIndex());
+}
+
+void StatesEditorWidgetPrivate::addState()
+{
+ QStringList modelStateNames = statesEditorView->stateRootNode().states().names();
+
+ QString newStateName;
+ int index = 1;
+ while (1) {
+ newStateName = tr("State%1").arg(index++);
+ if (!modelStateNames.contains(newStateName))
+ break;
+ }
+ statesEditorView->createState(newStateName);
+}
+
+void StatesEditorWidgetPrivate::removeState()
+{
+ statesEditorView->removeState(currentIndex());
+}
+
+void StatesEditorWidgetPrivate::duplicateCurrentState()
+{
+ statesEditorView->duplicateCurrentState(currentIndex());
+}
+
+} // namespace Internal
+
+StatesEditorWidget::StatesEditorWidget(QWidget *parent):
+ QWidget(parent),
+ m_d(new Internal::StatesEditorWidgetPrivate(this))
+{
+ QFile qmlFile(":/stateseditor/stateslist.qml");
+ qmlFile.open(QFile::ReadOnly);
+ Q_ASSERT(qmlFile.isOpen());
+
+ m_d->statesEditorModel = new Internal::StatesEditorModel(this);
+ m_d->listView = new QmlView(this);
+
+ m_d->listView->setAcceptDrops(false);
+
+ QVBoxLayout *layout = new QVBoxLayout(this);
+ layout->setMargin(0);
+ layout->setSpacing(0);
+ layout->addWidget(m_d->listView.data());
+
+ QString qmlSource(qmlFile.readAll());
+ m_d->listView->setQml(qmlSource,":/stateseditor/stateslist.qml");
+
+
+ m_d->listView->setContentResizable(true);
+
+ m_d->listView->rootContext()->setContextProperty(QLatin1String("statesEditorModel"), m_d->statesEditorModel.data());
+
+ m_d->listView->execute();
+
+ if (!m_d->listView->root())
+ throw InvalidQmlSourceException(__LINE__, __FUNCTION__, __FILE__, qmlSource);
+
+ m_d->listView->setFocusPolicy(Qt::ClickFocus);
+ QApplication::sendEvent(m_d->listView->scene(), new QEvent(QEvent::WindowActivate));
+
+ connect(m_d->listView->root(), SIGNAL(currentStateIndexChanged()), m_d, SLOT(currentStateChanged()));
+ connect(m_d->listView->root(), SIGNAL(createNewState()), m_d, SLOT(addState()));
+ connect(m_d->listView->root(), SIGNAL(duplicateCurrentState()), m_d, SLOT(duplicateCurrentState()));
+ connect(m_d->listView->root(), SIGNAL(deleteCurrentState()), m_d, SLOT(removeState()));
+
+ setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred));
+
+ setWindowTitle(tr("States", "Title of Editor widget"));
+}
+
+StatesEditorWidget::~StatesEditorWidget()
+{
+ delete m_d;
+}
+
+void StatesEditorWidget::setup(Model *model)
+{
+ m_d->model = model;
+ if (m_d->statesEditorView.isNull())
+ m_d->statesEditorView = new Internal::StatesEditorView(m_d->statesEditorModel.data(), this);
+ m_d->statesEditorModel->setStatesEditorView(m_d->statesEditorView.data());
+
+ m_d->model->attachView(m_d->statesEditorView.data());
+
+ // select first state (which is the base state)
+ m_d->currentStateChanged();
+}
+
+
+
+QSize StatesEditorWidget::sizeHint() const
+{
+ return QSize(9999, 188);
+}
+
+}
+
+#include "stateseditorwidget.moc"
diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.h b/src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.h
new file mode 100644
index 0000000000..902ebb53dd
--- /dev/null
+++ b/src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.h
@@ -0,0 +1,65 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef STATESEDITORWIDGET_H
+#define STATESEDITORWIDGET_H
+
+#include <QtGui/QWidget>
+#include <QtGui/QListWidgetItem>
+
+namespace QmlDesigner {
+
+class FormWindow;
+class Model;
+class ModelState;
+
+namespace Internal {
+class StatesEditorWidgetPrivate;
+}
+
+class StatesEditorWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ StatesEditorWidget(QWidget *parent = 0);
+ virtual ~StatesEditorWidget();
+
+ void setup(Model *model);
+
+ QSize sizeHint() const;
+
+private:
+ friend class Internal::StatesEditorWidgetPrivate;
+ class Internal::StatesEditorWidgetPrivate *m_d;
+};
+
+}
+
+#endif // STATESEDITORWIDGET_H
diff --git a/src/plugins/qmldesigner/components/stateseditor/stateslist.qml b/src/plugins/qmldesigner/components/stateseditor/stateslist.qml
new file mode 100644
index 0000000000..8486a0d69b
--- /dev/null
+++ b/src/plugins/qmldesigner/components/stateseditor/stateslist.qml
@@ -0,0 +1,337 @@
+import Qt 4.6
+
+// Shows list of states
+// the model has to expose the path through an iconUrl property
+Rectangle {
+ id: root
+ property int currentStateIndex : 0
+ signal createNewState
+ signal deleteCurrentState
+ signal duplicateCurrentState
+
+ color: "#707070";
+
+ function adjustCurrentStateIndex() {
+ if (currentStateIndex >= statesEditorModel.count)
+ currentStateIndex = statesEditorModel.count-1;
+ }
+
+ Connection {
+ sender: statesEditorModel
+ signal: "countChanged()"
+ script: adjustCurrentStateIndex();
+ }
+
+ Connection {
+ sender: statesEditorModel
+ signal: "changedToState(n)"
+ script: {root.currentStateIndex = n}
+ }
+
+
+ Flickable {
+ id: listView
+
+ anchors.fill: root;
+
+ anchors.bottomMargin: 10;
+ anchors.topMargin: 2;
+ anchors.leftMargin: 29;
+ anchors.rightMargin: 40;
+
+ viewportHeight: height
+ viewportWidth: listViewRow.width
+
+ Row {
+ id: listViewRow
+ spacing: 4
+ Repeater {
+ model: statesEditorModel
+ delegate: Delegate
+ }
+ }
+
+ focus: true;
+ clip: true;
+ overShoot: false;
+ interactive:false;
+
+ }
+
+ Component {
+ id: Delegate
+ Item {
+ id: container
+ width: Math.max(img.width, txt.width) + 4
+ height: img.height + txt.height + 4
+
+ Rectangle {
+ id: Highlight
+ anchors.fill: parent
+ color: "#0303e0"
+ radius: 4
+ opacity: (index==root.currentStateIndex);
+ onOpacityChanged: if (opacity) {
+ // If the current item becomes selected, check if it is in the viewport
+ if (container.x < listView.viewportX)
+ horizontalScrollbar.viewPosition = container.x;
+ if (container.x+container.width > listView.viewportX + listView.width)
+ horizontalScrollbar.viewPosition = container.x+container.width - listView.width;
+ }
+ }
+
+ Image {
+ id: img
+ pixmap: statePixmap
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.top: parent.top
+ anchors.topMargin: 2
+ }
+
+ MouseRegion {
+ id: itemRegion
+ anchors.fill: container
+ onClicked: {
+ root.currentStateIndex = index
+ focus=true; // steal focus from textinput
+ }
+ }
+
+ TextInput {
+ anchors.top: img.bottom
+ anchors.horizontalCenter: img.horizontalCenter
+ id: txt
+ text: stateName
+ color: "#E1E1E1";
+ onAccepted: {
+ // force focus to move to another item, otherwise this one will be reactivated at mode change
+ focus=false;
+ itemRegion.focus=true;
+ }
+ onFocusChanged: if (!focus) {
+ txtRegion.enabled=true
+ statesEditorModel.renameState(index, text)
+ }
+ MouseRegion {
+ id: txtRegion
+ anchors.fill:parent
+ property bool wasDoubleClicked:false
+ onClicked: {
+ root.currentStateIndex = index;
+ itemRegion.focus=true;
+ }
+ onDoubleClicked: if (index!=0) { // base state not editable
+ parent.focus=true;
+ enabled=false;
+ }
+ }
+ }
+ }
+ }
+
+ // The add button
+ Rectangle {
+ id: addState
+
+ anchors.left: root.left
+ anchors.top: root.top
+ anchors.topMargin: 4;
+ anchors.leftMargin: 4;
+
+ width: 20
+ height: 50
+
+ // Appearance
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "#909090" }
+ GradientStop { position: 1.0; color: "#AEAEAE" }
+ }
+ border.width : 1
+ border.color : "#4F4F4F"
+ radius: 4
+
+ // "clicked" overlay
+ Rectangle {
+ anchors.fill:parent
+ opacity:parent.state=="Pressed"
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "#727272" }
+ GradientStop { position: 1.0; color: "#909090" }
+ }
+ border.width : 1
+ border.color : "#4F4F4F"
+ radius: 4
+ }
+
+ states: State{ name: "Pressed"; }
+
+ // "plus" sign
+ Rectangle {
+ width:12
+ height:2
+ color:"black"
+ anchors.centerIn:parent
+ effect: Blur { blurRadius: 1; }
+ }
+ Rectangle {
+ width:2
+ height:12
+ color:"black"
+ anchors.centerIn:parent
+ effect: Blur { blurRadius: 1; }
+ }
+
+ MouseRegion {
+ anchors.fill:parent
+ onClicked: {
+ if (root.currentStateIndex == 0)
+ root.createNewState(); //create new state
+ else
+ root.duplicateCurrentState(); //duplicate current state
+
+ listView.viewportX = horizontalScrollbar.viewPosition;
+ // select the newly created state
+ root.currentStateIndex=statesEditorModel.count - 1;
+ }
+ onPressed: {parent.state="Pressed"}
+ onReleased: {parent.state=""}
+ }
+ }
+
+ // The erase button
+ Rectangle {
+ id: removeState
+
+ anchors.left: root.left
+ anchors.top: addState.bottom
+ anchors.topMargin: 4;
+ anchors.leftMargin: 4;
+
+ width: 20
+ height: 50
+
+ // Appearance
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "#909090" }
+ GradientStop { position: 1.0; color: "#AEAEAE" }
+ }
+ border.width : 1
+ border.color : "#4F4F4F"
+ radius: 4
+
+ // "clicked" overlay
+ Rectangle {
+ anchors.fill:parent
+ opacity:parent.state=="Pressed"
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "#727272" }
+ GradientStop { position: 1.0; color: "#909090" }
+ }
+ border.width : 1
+ border.color : "#4F4F4F"
+ radius: 4
+ }
+
+ states: State{ name: "Pressed"; }
+
+ // "minus" sign
+ Rectangle {
+ width:12
+ height:2
+ color:"black"
+ anchors.centerIn:parent
+ effect: Blur { blurRadius: 1; }
+ }
+
+ visible: { root.currentStateIndex != 0 }
+
+ MouseRegion {
+ anchors.fill:parent
+ onClicked: {
+ root.deleteCurrentState();
+ if (root.currentStateIndex >= statesEditorModel.count)
+ root.currentStateIndex = root.currentStateIndex-1;
+ horizontalScrollbar.totalLengthDecreased();
+ }
+ onPressed: {parent.state="Pressed"}
+ onReleased: {parent.state=""}
+ enabled: { root.currentStateIndex != 0 }
+ }
+ }
+
+ Item {
+ id: horizontalScrollbar
+ // Current listView implementation sometimes has negative width or viewportWidth
+ property int viewPosition: 0;
+ property int viewLength: ( listView.width>=0 ? listView.width : 0 );
+ property int totalLength: ( listView.viewportWidth>=0 ? listView.viewportWidth : 0 );
+
+
+ onViewPositionChanged: listView.viewportX=viewPosition;
+ onViewLengthChanged: {
+ if ((totalLength>viewLength) && (viewPosition > totalLength-viewLength))
+ viewPosition = totalLength-viewLength;
+ }
+
+ function totalLengthDecreased() {
+ if ((totalLength>viewLength) && (viewPosition > totalLength-viewLength))
+ viewPosition = totalLength-viewLength;
+ }
+
+ opacity: viewLength < totalLength;
+
+ anchors.left : listView.left
+ anchors.right : listView.right
+ anchors.bottom : root.bottom
+ anchors.bottomMargin: 4
+
+ height: 10;
+
+ // the bar itself
+ Item {
+ id: draggableBar
+ width: if (horizontalScrollbar.viewLength>horizontalScrollbar.totalLength) parent.width;
+ else horizontalScrollbar.viewLength/horizontalScrollbar.totalLength * parent.width;
+ height: parent.height;
+ x: horizontalScrollbar.viewPosition*horizontalScrollbar.width/horizontalScrollbar.totalLength;
+
+
+ Rectangle {
+ height:parent.height-1
+ width:parent.width
+ y:1
+
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "#C6C6C6" }
+ GradientStop { position: 1.0; color: "#7E7E7E" }
+ }
+ }
+
+ MouseRegion {
+ anchors.fill:parent
+ property int dragging:0;
+ property int originalX:0;
+ onPressed: { dragging = 1; originalX = mouse.x; }
+ onReleased: { dragging = 0; }
+ onPositionChanged: if (dragging)
+ {
+ var newX = mouse.x - originalX + parent.x;
+ if (newX<0) newX=0;
+ if (newX>horizontalScrollbar.width-draggableBar.width)
+ newX=horizontalScrollbar.width-draggableBar.width;
+ horizontalScrollbar.viewPosition = newX*horizontalScrollbar.totalLength/horizontalScrollbar.width;
+ }
+ }
+ }
+
+ // border
+ Rectangle {
+ anchors.fill:parent;
+ color:"Transparent";
+ border.width:1;
+ border.color:"#8F8F8F";
+ }
+
+ }
+
+}
diff --git a/src/plugins/qmldesigner/components/themeloader/qts60stylethemeio.cpp b/src/plugins/qmldesigner/components/themeloader/qts60stylethemeio.cpp
new file mode 100644
index 0000000000..2ad3e7c884
--- /dev/null
+++ b/src/plugins/qmldesigner/components/themeloader/qts60stylethemeio.cpp
@@ -0,0 +1,357 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+/****************************************************************************
+**
+** 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 "qts60stylethemeio.h"
+
+#if !defined(QT_NO_STYLE_S60)
+
+#include "qs60style.h"
+#include "qapplication.h"
+#include "qwebview.h"
+#include "qwebframe.h"
+#include "qeventloop.h"
+#include "qpicture.h"
+#include "qpicture.h"
+#include "qpainter.h"
+#include "qfile.h"
+#include "qdir.h"
+#include "qfileinfo.h"
+#include "qxmlstream.h"
+#include "qbuffer.h"
+
+#include "qdebug.h"
+
+static const quint32 blobVersion = 1;
+static const int pictureSize = 256;
+
+void dumpPartPictures(const QHash<QString, QPicture> &partPictures) {
+ foreach (const QString &partKey, partPictures.keys()) {
+ QPicture partPicture = partPictures.value(partKey);
+ qDebug() << partKey << partPicture.boundingRect();
+ QImage image(partPicture.boundingRect().size(), QImage::Format_ARGB32);
+ image.fill(Qt::transparent);
+ QPainter p(&image);
+ partPicture.play(&p);
+ image.save(partKey + QString::fromLatin1(".png"));
+ }
+}
+
+void dumpColors(const QHash<QPair<QString, int>, QColor> &colors) {
+ foreach (const QColor &color, colors.values()) {
+ const QPair<QString, int> key = colors.key(color);
+ qDebug() << key << color;
+ }
+}
+
+bool setS60Theme(QHash<QString, QPicture> &partPictures,
+ QHash<QPair<QString, int>, QColor> &colors,
+ QS60Style *s60Style)
+{
+ if (!s60Style)
+ s60Style = qobject_cast<QS60Style *>(QApplication::style());
+ if (!s60Style || !qobject_cast<QS60Style *>(s60Style)) {
+ qWarning() << __FUNCTION__ << ": No QS60Style found.";
+ return false;
+ }
+ s60Style->setS60Theme(partPictures, colors);
+ return true;
+}
+
+#ifndef QT_NO_WEBKIT
+class WebKitSVGRenderer : public QWebView
+{
+ Q_OBJECT
+
+public:
+ WebKitSVGRenderer(QWidget *parent = 0);
+ QPicture svgToQPicture(const QString &svgFileName);
+
+private slots:
+ void loadFinishedSlot(bool ok);
+
+private:
+ QEventLoop m_loop;
+ QPicture m_result;
+};
+
+WebKitSVGRenderer::WebKitSVGRenderer(QWidget *parent)
+ : QWebView(parent)
+{
+ connect(this, SIGNAL(loadFinished(bool)), SLOT(loadFinishedSlot(bool)));
+ setFixedSize(pictureSize, pictureSize);
+ QPalette pal = palette();
+ pal.setColor(QPalette::Base, Qt::transparent);
+ setPalette(pal);
+}
+
+QPicture WebKitSVGRenderer::svgToQPicture(const QString &svgFileName)
+{
+ load(QUrl::fromLocalFile(svgFileName));
+ m_loop.exec();
+ return m_result;
+}
+
+void WebKitSVGRenderer::loadFinishedSlot(bool ok)
+{
+ // crude error-checking
+ if (!ok)
+ qDebug() << "Failed loading " << qPrintable(url().toString());
+
+ page()->mainFrame()->evaluateJavaScript(
+ "document.rootElement.preserveAspectRatio.baseVal.align = SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_NONE;"
+ "document.rootElement.style.width = '100%';"
+ "document.rootElement.style.height = '100%';"
+ "document.rootElement.width.baseVal.newValueSpecifiedUnits(SVGLength.SVG_LENGTHTYPE_PERCENTAGE, 100);"
+ "document.rootElement.height.baseVal.newValueSpecifiedUnits(SVGLength.SVG_LENGTHTYPE_PERCENTAGE, 100);"
+ );
+
+ m_result = QPicture(); // "Clear"
+ QPainter p(&m_result);
+ page()->mainFrame()->render(&p);
+ p.end();
+ m_result.setBoundingRect(QRect(0, 0, pictureSize, pictureSize));
+
+ m_loop.exit();
+}
+
+bool parseTdfFile(const QString &tdfFile,
+ QHash<QString, QString> &partSvgs,
+ QHash<QPair<QString, int>, QColor> &colors)
+{
+ const QLatin1String elementKey("element");
+ const QLatin1String partKey("part");
+ const QLatin1String elementIdKey("id");
+ const QLatin1String layerKey("layer");
+ const QLatin1String layerFileNameKey("filename");
+ const QLatin1String layerColourrgbKey("colourrgb");
+ const QString annoyingPrefix("S60_2_6%");
+ QFile file(tdfFile);
+ if (!file.open(QIODevice::ReadOnly))
+ return false;
+ QXmlStreamReader reader(&file);
+ QString partId;
+ QPair<QString, int> colorId;
+ // Somebody with a sense of aesthetics may implement proper XML parsing, here.
+ while (!reader.atEnd()) {
+ const QXmlStreamReader::TokenType token = reader.readNext();
+ switch (token) {
+ case QXmlStreamReader::StartElement:
+ if (reader.name() == elementKey || reader.name() == partKey) {
+ QString id = reader.attributes().value(elementIdKey).toString();
+ if (QS60Style::partKeys().contains(id)) {
+ partId = id;
+ } else if (!id.isEmpty() && id.at(id.length()-1).isDigit()) {
+ QString idText = id;
+ idText.remove(QRegExp("[0-9]"));
+ if (QS60Style::colorListKeys().contains(idText)) {
+ QString idNumber = id;
+ idNumber.remove(QRegExp("[a-zA-Z]"));
+ colorId = QPair<QString, int>(idText, idNumber.toInt());
+ }
+ } else if (QS60Style::partKeys().contains(id.mid(annoyingPrefix.length()))) {
+ partId = id.mid(annoyingPrefix.length());
+ }
+ } else if (reader.name() == layerKey) {
+ if (!partId.isEmpty()) {
+ const QString svgFile = reader.attributes().value(layerFileNameKey).toString();
+ partSvgs.insert(partId, svgFile);
+ partId.clear();
+ } else if (!colorId.first.isEmpty()) {
+ const QColor colorValue(reader.attributes().value(layerColourrgbKey).toString().toInt(NULL, 16));
+ colors.insert(colorId, colorValue);
+ colorId.first.clear();
+ }
+ }
+ break;
+ case QXmlStreamReader::EndElement:
+ if (reader.tokenString() == elementKey || reader.name() == partKey)
+ partId.clear();
+ break;
+ default:
+ break;
+ }
+ }
+ return true;
+}
+
+bool loadThemeFromTdf(const QString &tdfFile,
+ QHash<QString, QPicture> &partPictures,
+ QHash<QPair<QString, int>, QColor> &colors)
+{
+ QHash<QString, QString> parsedPartSvgs;
+ QHash<QString, QPicture> parsedPartPictures;
+ QHash<QPair<QString, int>, QColor> parsedColors;
+ bool success = parseTdfFile(tdfFile, parsedPartSvgs, parsedColors);
+ if (!success)
+ return false;
+ const QString tdfBasePath = QFileInfo(tdfFile).absolutePath();
+ WebKitSVGRenderer renderer;
+ foreach(const QString& partKey, parsedPartSvgs.keys()) {
+ const QString tdfFullName =
+ tdfBasePath + QDir::separator() + parsedPartSvgs.value(partKey);
+ if (!QFile(tdfFullName).exists())
+ qWarning() << "Could not load part " << tdfFullName;
+ const QPicture partPicture = renderer.svgToQPicture(tdfFullName);
+ parsedPartPictures.insert(partKey, partPicture);
+ }
+// dumpPartPictures(parsedPartPictures);
+// dumpColors(colors);
+ partPictures = parsedPartPictures;
+ colors = parsedColors;
+ return true;
+}
+
+bool QtS60StyleThemeIO::loadThemeFromTdf(const QString &themeTdf, QS60Style *s60Style)
+{
+ QHash<QString, QPicture> partPictures;
+ QHash<QPair<QString, int>, QColor> colors;
+
+ if (!::loadThemeFromTdf(themeTdf, partPictures, colors))
+ return false;
+
+ return ::setS60Theme(partPictures, colors, s60Style);
+}
+
+bool QtS60StyleThemeIO::convertTdfToBlob(const QString &themeTdf, const QString &themeBlob)
+{
+ QHash<QString, QPicture> partPictures;
+ QHash<QPair<QString, int>, QColor> colors;
+
+ if (!::loadThemeFromTdf(themeTdf, partPictures, colors))
+ return false;
+
+ QFile blob(themeBlob);
+ if (!blob.open(QIODevice::WriteOnly)) {
+ qWarning() << __FUNCTION__ << ": Could not create blob: " << themeBlob;
+ return false;
+ }
+
+ QByteArray data;
+ QBuffer dataBuffer(&data);
+ dataBuffer.open(QIODevice::WriteOnly);
+ QDataStream dataOut(&dataBuffer);
+
+ const int colorsCount = colors.count();
+ dataOut << colorsCount;
+ const QList<QPair<QString, int> > colorKeys = colors.keys();
+ for (int i = 0; i < colorsCount; ++i) {
+ const QPair<QString, int> &key = colorKeys.at(i);
+ dataOut << key;
+ const QColor color = colors.value(key);
+ dataOut << color;
+ }
+
+ const int picturesCount = partPictures.count();
+ dataOut << picturesCount;
+ foreach (const QString &key, partPictures.keys()) {
+ const QPicture picture = partPictures.value(key);
+ dataOut << key;
+ dataOut << picture;
+ }
+
+ QDataStream blobOut(&blob);
+ blobOut << blobVersion;
+ blobOut << qCompress(data);
+ return blobOut.status() == QDataStream::Ok;
+}
+#endif // !QT_NO_WEBKIT
+
+bool QtS60StyleThemeIO::loadThemeFromBlob(const QString &themeBlob, QS60Style *s60Style)
+{
+ QHash<QString, QPicture> partPictures;
+ QHash<QPair<QString, int>, QColor> colors;
+
+ QFile blob(themeBlob);
+ if (!blob.open(QIODevice::ReadOnly)) {
+ qWarning() << __FUNCTION__ << ": Could not read blob: " << themeBlob;
+ return false;
+ }
+ QDataStream blobIn(&blob);
+
+ quint32 version;
+ blobIn >> version;
+
+ if (version != blobVersion) {
+ qWarning() << __FUNCTION__ << ": Invalid blob version: " << version << " ...expected: " << blobVersion;
+ return false;
+ }
+
+ QByteArray data;
+ blobIn >> data;
+ data = qUncompress(data);
+ QBuffer dataBuffer(&data);
+ dataBuffer.open(QIODevice::ReadOnly);
+ QDataStream dataIn(&dataBuffer);
+
+ int colorsCount;
+ dataIn >> colorsCount;
+ for (int i = 0; i < colorsCount; ++i) {
+ QPair<QString, int> key;
+ dataIn >> key;
+ QColor value;
+ dataIn >> value;
+ colors.insert(key, value);
+ }
+
+ int picturesCount;
+ dataIn >> picturesCount;
+ for (int i = 0; i < picturesCount; ++i) {
+ QString key;
+ dataIn >> key;
+ QPicture value;
+ dataIn >> value;
+ value.setBoundingRect(QRect(0, 0, pictureSize, pictureSize)); // Bug? The forced bounding rect was not deserialized.
+ partPictures.insert(key, value);
+ }
+
+ if (dataIn.status() != QDataStream::Ok) {
+ qWarning() << __FUNCTION__ << ": Invalid data blob: " << themeBlob;
+ return false;
+ }
+
+// dumpPartPictures(partPictures);
+// dumpColors(colors);
+
+ return ::setS60Theme(partPictures, colors, s60Style);
+}
+
+#include "qts60stylethemeio.moc"
+
+#endif // QT_NO_STYLE_S60
diff --git a/src/plugins/qmldesigner/components/themeloader/qts60stylethemeio.h b/src/plugins/qmldesigner/components/themeloader/qts60stylethemeio.h
new file mode 100644
index 0000000000..40cc0c5da2
--- /dev/null
+++ b/src/plugins/qmldesigner/components/themeloader/qts60stylethemeio.h
@@ -0,0 +1,58 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+/****************************************************************************
+**
+** 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 QTS60STYLETHEMEIO_H
+#define QTS60STYLETHEMEIO_H
+
+#include "qstring.h"
+
+class QS60Style;
+
+class QtS60StyleThemeIO
+{
+public:
+ static bool loadThemeFromBlob(const QString &themeBlob, QS60Style *s60Style = 0);
+#ifndef QT_NO_WEBKIT
+ static bool loadThemeFromTdf(const QString &themeTdf, QS60Style *s60Style = 0);
+ static bool convertTdfToBlob(const QString &themeTdf, const QString &themeBlob);
+#endif
+};
+
+#endif // QTS60STYLETHEMEIO_H
diff --git a/src/plugins/qmldesigner/components/themeloader/qts60stylethemeio.pri b/src/plugins/qmldesigner/components/themeloader/qts60stylethemeio.pri
new file mode 100644
index 0000000000..ec800883be
--- /dev/null
+++ b/src/plugins/qmldesigner/components/themeloader/qts60stylethemeio.pri
@@ -0,0 +1,6 @@
+contains(QT_CONFIG, webkit) {
+ QT += webkit
+}
+#SOURCES += $$PWD/qts60stylethemeio.cpp
+#INCLUDE += $$PWD/qts60stylethemeio.h
+#INCLUDEPATH += $$PWD
diff --git a/src/plugins/qmldesigner/config.pri b/src/plugins/qmldesigner/config.pri
new file mode 100644
index 0000000000..c96394ccd4
--- /dev/null
+++ b/src/plugins/qmldesigner/config.pri
@@ -0,0 +1,27 @@
+contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols
+
+# MOC_DIR = moc
+DEFINES += QT_NO_STYLE_S60
+
+debug {
+ DEFINES += VIEWLOGGER
+}
+
+linux-g++-64 {
+ // note that -Werror = return-type \
+ is \
+ only \
+ supported \
+ with \
+ gcc \
+ >4.3
+ QMAKE_CXXFLAGS += "-Werror=return-type -Werror=init-self"
+ QMAKE_LFLAGS += "-rdynamic"
+}
+TMP_BAUHAUS_NO_OUTPUT = $$[BAUHAUS_NO_OUTPUT]
+equals(TMP_BAUHAUS_NO_OUTPUT, true):DEFINES += QT_NO_DEBUG_OUTPUT \
+ QT_NO_WARNING_OUTPUT
+DEFINES += ENABLE_TEXT_VIEW \
+ QWEAKPOINTER_ENABLE_ARROW
+
+isEmpty($$(BAUHAUS_OUTPUT_IN_TEST)):DEFINES += QDEBUG_IN_TESTS WARNINGS_IN_TESTS
diff --git a/src/plugins/qmldesigner/core/core.pri b/src/plugins/qmldesigner/core/core.pri
new file mode 100644
index 0000000000..0768c58fd7
--- /dev/null
+++ b/src/plugins/qmldesigner/core/core.pri
@@ -0,0 +1,183 @@
+include($$PWD/filemanager/filemanager.pri)
+include (../config.pri)
+QT += script \
+ declarative \
+ opengl
+DEFINES += TEST_EXPORTS
+INCLUDEPATH += $$PWD \
+ $$PWD/include
+DEPENDPATH += $$PWD $$PWD/include
+INCLUDEPATH += $$QT_SOURCE_TREE/src/declarative/qml
+SOURCES += $$PWD/model/abstractview.cpp \
+ $$PWD/instances/nodeinstanceview.cpp \
+ $$PWD/model/rewriterview.cpp \
+ $$PWD/metainfo/enumeratormetainfo.cpp \
+ $$PWD/metainfo/metainfo.cpp \
+ $$PWD/metainfo/metainfoparser.cpp \
+ $$PWD/metainfo/propertymetainfo.cpp \
+ $$PWD/metainfo/nodemetainfo.cpp \
+ $$PWD/metainfo/itemlibraryinfo.cpp \
+ $$PWD/metainfo/subcomponentmanager.cpp \
+ $$PWD/model/internalproperty.cpp \
+ $$PWD/model/model.cpp \
+ $$PWD/model/modelnode.cpp \
+ $$PWD/model/painteventfilter.cpp \
+ $$PWD/model/internalnode.cpp \
+ $$PWD/model/propertyparser.cpp \
+ $$PWD/model/propertycontainer.cpp \
+ $$PWD/pluginmanager/widgetpluginmanager.cpp \
+ $$PWD/pluginmanager/widgetpluginpath.cpp \
+ $$PWD/instances/nodeinstance.cpp \
+ $$PWD/instances/objectnodeinstance.cpp \
+ $$PWD/instances/widgetnodeinstance.cpp \
+ $$PWD/instances/graphicswidgetnodeinstance.cpp \
+ $$PWD/instances/qmlgraphicsitemnodeinstance.cpp \
+ $$PWD/instances/graphicsscenenodeinstance.cpp \
+ $$PWD/instances/graphicsviewnodeinstance.cpp \
+ $$PWD/instances/proxywidgetnodeinstance.cpp \
+ $$PWD/instances/qmlviewnodeinstance.cpp \
+ $$PWD/instances/dummynodeinstance.cpp \
+ $$PWD/instances/qmlpropertychangesnodeinstance.cpp \
+ $$PWD/instances/qmlstatenodeinstance.cpp \
+ $$PWD/exceptions/exception.cpp \
+ $$PWD/exceptions/invalidnodeinstanceexception.cpp \
+ $$PWD/exceptions/invalidpropertyexception.cpp \
+ $$PWD/exceptions/invalidmodelnodeexception.cpp \
+ $$PWD/exceptions/invalidreparentingexception.cpp \
+ $$PWD/exceptions/invalidmetainfoexception.cpp \
+ $$PWD/exceptions/invalidargumentexception.cpp \
+ $$PWD/exceptions/noanchoringpossibleexception.cpp \
+ $$PWD/exceptions/notimplementedexception.cpp \
+ $$PWD/exceptions/invalidnodestateexception.cpp \
+ $$PWD/model/variantparser.cpp \
+ $$PWD/exceptions/invalidmodelstateexception.cpp \
+ $$PWD/exceptions/removebasestateexception.cpp \
+ $$PWD/exceptions/invalididexception.cpp \
+ $$PWD/model/propertynode.cpp \
+ $$PWD/exceptions/invalidslideindexexception.cpp \
+ $$PWD/instances/graphicsobjectnodeinstance.cpp \
+ $$PWD/model/import.cpp \
+ $$PWD/instances/componentnodeinstance.cpp \
+ $$PWD/exceptions/invalidqmlsourceexception.cpp \
+ $$PWD/model/viewlogger.cpp \
+ $$PWD/model/internalvariantproperty.cpp \
+ $$PWD/model/internalnodelistproperty.cpp \
+ $$PWD/model/variantproperty.cpp \
+ $$PWD/model/nodelistproperty.cpp \
+ $$PWD/model/abstractproperty.cpp \
+ $$PWD/model/internalbindingproperty.cpp \
+ $$PWD/model/bindingproperty.cpp \
+ $$PWD/model/internalnodeproperty.cpp \
+ $$PWD/model/internalnodeabstractproperty.cpp \
+ $$PWD/model/nodeabstractproperty.cpp \
+ $$PWD/model/nodeproperty.cpp \
+ $$PWD/model/modeltotextmerger.cpp \
+ $$PWD/model/texttomodelmerger.cpp \
+ $$PWD/model/plaintexteditmodifier.cpp \
+ $$PWD/model/componenttextmodifier.cpp \
+ $$PWD/model/textmodifier.cpp \
+ $$PWD/model/qmlmodelview.cpp \
+ $$PWD/model/qmlitemnode.cpp \
+ $$PWD/model/qmlstate.cpp \
+ $$PWD/model/qmlchangeset.cpp \
+ $$PWD/model/qmlmodelnodefacade.cpp \
+ $$PWD/model/qmlobjectnode.cpp \
+ $$PWD/model/qmlanchors.cpp \
+ $$PWD/rewritertransaction.cpp \
+ $$PWD/model/rewriteaction.cpp \
+ $$PWD/model/modelnodepositionstorage.cpp \
+ $$PWD/model/modelnodepositionrecalculator.cpp \
+ $$PWD/model/rewriteactioncompressor.cpp \
+ $$PWD/model/qmltextgenerator.cpp \
+ $$PWD/model/modelmerger.cpp \
+ $$PWD/instances/qmltransitionnodeinstance.cpp
+HEADERS += $$PWD/include/corelib_global.h \
+ $$PWD/include/abstractview.h \
+ $$PWD/include/nodeinstanceview.h \
+ $$PWD/include/rewriterview.h \
+ $$PWD/include/enumeratormetainfo.h \
+ $$PWD/include/metainfo.h \
+ $$PWD/include/metainfoparser.h \
+ $$PWD/include/nodemetainfo.h \
+ $$PWD/include/propertymetainfo.h \
+ $$PWD/include/itemlibraryinfo.h \
+ $$PWD/model/internalproperty.h \
+ $$PWD/include/modelnode.h \
+ $$PWD/include/model.h \
+ $$PWD/include/nodeproperty.h \
+ $$PWD/include/widgetqueryview.h \
+ $$PWD/include/subcomponentmanager.h \
+ $$PWD/include/propertycontainer.h \
+ $$PWD/model/internalnode_p.h \
+ $$PWD/model/model_p.h \
+ $$PWD/model/painteventfilter_p.h \
+ $$PWD/model/propertyparser.h \
+ $$PWD/pluginmanager/widgetpluginmanager.h \
+ $$PWD/pluginmanager/widgetpluginpath.h \
+ $$PWD/include/nodeinstance.h \
+ $$PWD/instances/objectnodeinstance.h \
+ $$PWD/instances/widgetnodeinstance.h \
+ $$PWD/instances/graphicswidgetnodeinstance.h \
+ $$PWD/instances/qmlgraphicsitemnodeinstance.h \
+ $$PWD/instances/graphicsscenenodeinstance.h \
+ $$PWD/instances/graphicsviewnodeinstance.h \
+ $$PWD/instances/proxywidgetnodeinstance.h \
+ $$PWD/instances/qmlviewnodeinstance.h \
+ $$PWD/instances/dummynodeinstance.h \
+ $$PWD/instances/qmlpropertychangesnodeinstance.h \
+ $$PWD/instances/qmlstatenodeinstance.h \
+ $$PWD/include/exception.h \
+ $$PWD/include/invalidnodeinstanceexception.h \
+ $$PWD/include/invalidmodelnodeexception.h \
+ $$PWD/include/invalidreparentingexception.h \
+ $$PWD/include/invalidmetainfoexception.h \
+ $$PWD/include/invalidargumentexception.h \
+ $$PWD/include/notimplementedexception.h \
+ $$PWD/include/invalidpropertyexception.h \
+ $$PWD/include/invalidmodelstateexception.h \
+ $$PWD/include/removebasestateexception.h \
+ $$PWD/include/invalididexception.h \
+ $$PWD/model/variantparser.h \
+ $$PWD/include/propertynode.h \
+ $$PWD/include/invalidslideindexexception.h \
+ $$PWD/instances/graphicsobjectnodeinstance.h \
+ $$PWD/include/import.h \
+ $$PWD/instances/componentnodeinstance.h \
+ $$PWD/include/invalidqmlsourceexception.h \
+ $$PWD/model/viewlogger.h \
+ $$PWD/model/internalvariantproperty.h \
+ $$PWD/model/internalnodelistproperty.h \
+ $$PWD/include/variantproperty.h \
+ $$PWD/include/nodelistproperty.h \
+ $$PWD/include/abstractproperty.h \
+ $$PWD/model/internalbindingproperty.h \
+ $$PWD/include/bindingproperty.h \
+ $$PWD/model/internalnodeproperty.h \
+ $$PWD/model/internalnodeabstractproperty.h \
+ $$PWD/include/nodeabstractproperty.h \
+ $$PWD/include/plaintexteditmodifier.h \
+ $$PWD/include/componenttextmodifier.h \
+ $$PWD/include/textmodifier.h \
+ $$PWD/model/modeltotextmerger.h \
+ $$PWD/model/texttomodelmerger.h \
+ $$PWD/include/qmlmodelview.h \
+ $$PWD/include/qmlitemnode.h \
+ $$PWD/include/qmlstate.h \
+ $$PWD/include/qmlchangeset.h \
+ $$PWD/include/qmlmodelnodefacade.h \
+ $$PWD/include/forwardview.h \
+ $$PWD/include/qmlobjectnode.h \
+ $$PWD/include/qmlanchors.h \
+ $$PWD/rewritertransaction.h \
+ $$PWD/model/rewriteaction.h \
+ $$PWD/include/modelnodepositionstorage.h \
+ $$PWD/model/modelnodepositionrecalculator.h \
+ $$PWD/model/rewriteactioncompressor.h \
+ $$PWD/model/qmltextgenerator.h \
+ $$PWD/include/modelmerger.h \
+ $$PWD/include/mathutils.h \
+ $$PWD/instances/qmltransitionnodeinstance.h \
+ $$PWD/include/customnotifications.h
+DISTFILES += $$PWD/metafile/widget.metafile
+RESOURCES += $$PWD/core.qrc
+OTHER_FILES += $$PWD/metainfo/gui.metainfo
diff --git a/src/plugins/qmldesigner/core/core.qrc b/src/plugins/qmldesigner/core/core.qrc
new file mode 100644
index 0000000000..d79916781d
--- /dev/null
+++ b/src/plugins/qmldesigner/core/core.qrc
@@ -0,0 +1,6 @@
+ <!DOCTYPE RCC>
+<RCC version="1.0">
+ <qresource>
+ <file>metainfo/gui.metainfo</file>
+ </qresource>
+ </RCC>
diff --git a/src/plugins/qmldesigner/core/depend_paths.pri b/src/plugins/qmldesigner/core/depend_paths.pri
new file mode 100644
index 0000000000..c2059ccbec
--- /dev/null
+++ b/src/plugins/qmldesigner/core/depend_paths.pri
@@ -0,0 +1 @@
+DEPENDPATH += $$PWD/qtpropertybrowser/src/ \ No newline at end of file
diff --git a/src/plugins/qmldesigner/core/exceptions/exception.cpp b/src/plugins/qmldesigner/core/exceptions/exception.cpp
new file mode 100644
index 0000000000..309da4d9ce
--- /dev/null
+++ b/src/plugins/qmldesigner/core/exceptions/exception.cpp
@@ -0,0 +1,192 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "exception.h"
+
+#ifdef Q_OS_LINUX
+#include <execinfo.h>
+#include <cxxabi.h>
+#endif
+
+#include <QRegExp>
+
+/*!
+\defgroup CoreExceptions
+*/
+/*!
+\class QmlDesigner::Exception
+\ingroup CoreExceptions
+\brief This is the abstract base class for all excetions.
+ Exceptions should be used in cases there is no other way to say something goes wrong. For example
+ the result would be a inconsistent model or a crash.
+*/
+
+
+namespace QmlDesigner {
+
+#ifdef Q_OS_LINUX
+const char* demangle(const char* name)
+{
+ char buf[1024];
+ size_t size = 1024;
+ int status;
+ char* res;
+ res = abi::__cxa_demangle(name,
+ buf,
+ &size,
+ &status);
+ return res;
+}
+#else
+const char* demangle(const char* name)
+{
+ return name;
+}
+#endif
+
+
+bool Exception::s_shouldAssert = true;
+
+void Exception::setShouldAssert(bool assert)
+{
+ s_shouldAssert = assert;
+}
+
+bool Exception::shouldAssert()
+{
+ return s_shouldAssert;
+}
+
+/*!
+\brief Constructor
+
+\param line use the __LINE__ macro
+\param function use the __FUNCTION__ or the Q_FUNC_INFO macro
+\param file use the __FILE__ macro
+*/
+Exception::Exception(int line,
+ const QString &function,
+ const QString &file)
+ : m_line(line),
+ m_function(function),
+ m_file(file)
+{
+#ifdef Q_OS_LINUX
+ void * array[50];
+ int nSize = backtrace(array, 50);
+ char ** symbols = backtrace_symbols(array, nSize);
+
+ for (int i = 0; i < nSize; i++)
+ {
+ m_backTrace.append(QString("%1\n").arg(symbols[i]));
+ }
+
+ free(symbols);
+#endif
+
+if (s_shouldAssert)
+ Q_ASSERT_X(false, function.toLatin1(), QString("%1:%2 - %3").arg(file).arg(line).arg(function).toLatin1());
+}
+
+Exception::~Exception()
+{
+}
+
+/*!
+\brief Returns the unmangled backtrace of this exception
+
+\returns the backtrace as a string
+*/
+QString Exception::backTrace() const
+{
+ return m_backTrace;
+}
+
+/*!
+\brief Returns the optional description of this exception
+
+\returns the description as string
+*/
+QString Exception::description() const
+{
+ return QString();
+}
+
+/*!
+\brief Returns the line number where this exception was thrown
+
+\returns the line number as integer
+*/
+int Exception::line() const
+{
+ return m_line;
+}
+
+/*!
+\brief Returns the function name where this exception was thrown
+
+\returns the function name as string
+*/
+QString Exception::function() const
+{
+ return m_function;
+}
+
+/*!
+\brief Returns the file name where this exception was thrown
+
+\returns the file name as string
+*/
+QString Exception::file() const
+{
+ return m_file;
+}
+
+QDebug operator<<(QDebug debug, const Exception &exception)
+{
+ debug.nospace() << "Exception: " << exception.type() << "\n"
+ "Function: " << exception.function() << "\n"
+ "File: " << exception.file() << "\n"
+ "Line: " << exception.line() << "\n";
+ if (!exception.description().isEmpty())
+ debug.nospace() << exception.description();
+
+ if (!exception.backTrace().isEmpty())
+ debug.nospace() << exception.backTrace();
+
+ return debug.space();
+}
+
+/*!
+\fn QString Exception::type() const
+\brief Returns the type of this exception
+
+\returns the type as a string
+*/
+}
diff --git a/src/plugins/qmldesigner/core/exceptions/invalidargumentexception.cpp b/src/plugins/qmldesigner/core/exceptions/invalidargumentexception.cpp
new file mode 100644
index 0000000000..e85149640e
--- /dev/null
+++ b/src/plugins/qmldesigner/core/exceptions/invalidargumentexception.cpp
@@ -0,0 +1,75 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "invalidargumentexception.h"
+
+/*!
+\class QmlDesigner::InvalidArgumentException
+\ingroup CoreExceptions
+\brief Exception for a invalid argument
+
+*/
+namespace QmlDesigner {
+
+/*!
+\brief Constructor
+
+\param line use the __LINE__ macro
+\param function use the __FUNCTION__ or the Q_FUNC_INFO macro
+\param file use the __FILE__ macro
+*/
+InvalidArgumentException::InvalidArgumentException(int line,
+ const QString &function,
+ const QString &file,
+ const QString &argument)
+ : Exception(line, function, file), m_argument(argument)
+{
+}
+
+/*!
+\brief Returns the type of this exception
+
+\returns the type as a string
+*/
+QString InvalidArgumentException::type() const
+{
+ return "InvalidArgumentException";
+}
+
+/*!
+\brief Returns the argument of this exception
+
+\returns the argument as a string
+*/
+QString InvalidArgumentException::argument() const
+{
+ return m_argument;
+}
+
+}
diff --git a/src/plugins/qmldesigner/core/exceptions/invalididexception.cpp b/src/plugins/qmldesigner/core/exceptions/invalididexception.cpp
new file mode 100644
index 0000000000..e94145a74c
--- /dev/null
+++ b/src/plugins/qmldesigner/core/exceptions/invalididexception.cpp
@@ -0,0 +1,45 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "invalididexception.h"
+
+namespace QmlDesigner {
+
+InvalidIdException::InvalidIdException(int line,
+ const QString &function,
+ const QString &file):
+ InvalidArgumentException(line, function, file, "id")
+{
+}
+
+QString InvalidIdException::type() const
+{
+ return "InvalidIdException";
+}
+}
diff --git a/src/plugins/qmldesigner/core/exceptions/invalidmetainfoexception.cpp b/src/plugins/qmldesigner/core/exceptions/invalidmetainfoexception.cpp
new file mode 100644
index 0000000000..d102339cac
--- /dev/null
+++ b/src/plugins/qmldesigner/core/exceptions/invalidmetainfoexception.cpp
@@ -0,0 +1,64 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "invalidmetainfoexception.h"
+
+/*!
+\class QmlDesigner::InvalidMetaInfoException
+\ingroup CoreExceptions
+\brief Exception for a invalid meta info
+
+\see NodeMetaInfo PropertyMetaInfo MetaInfo
+*/
+namespace QmlDesigner {
+/*!
+\brief Constructor
+
+\param line use the __LINE__ macro
+\param function use the __FUNCTION__ or the Q_FUNC_INFO macro
+\param file use the __FILE__ macro
+*/
+InvalidMetaInfoException::InvalidMetaInfoException(int line,
+ const QString &function,
+ const QString &file)
+ : Exception(line, function, file)
+{
+}
+
+/*!
+\brief Returns the type of this exception
+
+\returns the type as a string
+*/
+QString InvalidMetaInfoException::type() const
+{
+ return "InvalidMetaInfoException";
+}
+
+}
diff --git a/src/plugins/qmldesigner/core/exceptions/invalidmodelnodeexception.cpp b/src/plugins/qmldesigner/core/exceptions/invalidmodelnodeexception.cpp
new file mode 100644
index 0000000000..7b85bc103c
--- /dev/null
+++ b/src/plugins/qmldesigner/core/exceptions/invalidmodelnodeexception.cpp
@@ -0,0 +1,64 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "invalidmodelnodeexception.h"
+
+/*!
+\class QmlDesigner::InvalidModelNodeException
+\ingroup CoreExceptions
+\brief Exception for a invalid model node
+
+\see ModelNode
+*/
+namespace QmlDesigner {
+/*!
+\brief Constructor
+
+\param line use the __LINE__ macro
+\param function use the __FUNCTION__ or the Q_FUNC_INFO macro
+\param file use the __FILE__ macro
+*/
+InvalidModelNodeException::InvalidModelNodeException(int line,
+ const QString &function,
+ const QString &file)
+ : Exception(line, function, file)
+{
+}
+
+/*!
+\brief Returns the type of this exception
+
+\returns the type as a string
+*/
+QString InvalidModelNodeException::type() const
+{
+ return "InvalidModelNodeException";
+}
+
+}
diff --git a/src/plugins/qmldesigner/core/exceptions/invalidmodelstateexception.cpp b/src/plugins/qmldesigner/core/exceptions/invalidmodelstateexception.cpp
new file mode 100644
index 0000000000..adb0905f86
--- /dev/null
+++ b/src/plugins/qmldesigner/core/exceptions/invalidmodelstateexception.cpp
@@ -0,0 +1,65 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "invalidmodelstateexception.h"
+
+/*!
+\class QmlDesigner::InvalidModelStateException
+\ingroup CoreExceptions
+\brief Exception for a invalid model state
+
+
+\see ModelState
+*/
+namespace QmlDesigner {
+/*!
+\brief Constructor
+
+\param line use the __LINE__ macro
+\param function use the __FUNCTION__ or the Q_FUNC_INFO macro
+\param file use the __FILE__ macro
+*/
+InvalidModelStateException::InvalidModelStateException(int line,
+ const QString &function,
+ const QString &file)
+ : Exception(line, function, file)
+{
+}
+
+/*!
+\brief Returns the type of this exception
+
+\returns the type as a string
+*/
+QString InvalidModelStateException::type() const
+{
+ return "InvalidModelStateException";
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/core/exceptions/invalidnodeinstanceexception.cpp b/src/plugins/qmldesigner/core/exceptions/invalidnodeinstanceexception.cpp
new file mode 100644
index 0000000000..44c2641a00
--- /dev/null
+++ b/src/plugins/qmldesigner/core/exceptions/invalidnodeinstanceexception.cpp
@@ -0,0 +1,65 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "invalidnodeinstanceexception.h"
+
+/*!
+\class QmlDesigner::InvalidNodeInstanceException
+\ingroup CoreExceptions
+\brief Exception for a invalid ndoe instance
+
+
+\see NodeInstance
+*/
+namespace QmlDesigner {
+/*!
+\brief Constructor
+
+\param line use the __LINE__ macro
+\param function use the __FUNCTION__ or the Q_FUNC_INFO macro
+\param file use the __FILE__ macro
+*/
+InvalidNodeInstanceException::InvalidNodeInstanceException(int line,
+ const QString &function,
+ const QString &file)
+ : Exception(line, function, file)
+{
+}
+
+/*!
+\brief Returns the type of this exception
+
+\returns the type as a string
+*/
+QString InvalidNodeInstanceException::type() const
+{
+ return "InvalidNodeInstanceException";
+}
+
+}
diff --git a/src/plugins/qmldesigner/core/exceptions/invalidnodestateexception.cpp b/src/plugins/qmldesigner/core/exceptions/invalidnodestateexception.cpp
new file mode 100644
index 0000000000..d2323abe64
--- /dev/null
+++ b/src/plugins/qmldesigner/core/exceptions/invalidnodestateexception.cpp
@@ -0,0 +1,65 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "invalidnodestateexception.h"
+
+/*!
+\class QmlDesigner::InvalidNodeStateException
+\ingroup CoreExceptions
+\brief Exception for a invalid node states
+
+
+/see NodeState
+*/
+namespace QmlDesigner {
+/*!
+\brief Constructor
+
+\param line use the __LINE__ macro
+\param function use the __FUNCTION__ or the Q_FUNC_INFO macro
+\param file use the __FILE__ macro
+*/
+InvalidNodeStateException::InvalidNodeStateException(int line,
+ const QString &function,
+ const QString &file)
+ : Exception(line, function, file)
+{
+}
+
+/*!
+\brief Returns the type of this exception
+
+\returns the type as a string
+*/
+QString InvalidNodeStateException::type() const
+{
+ return "InvalidNodeStateException";
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/core/exceptions/invalidpropertyexception.cpp b/src/plugins/qmldesigner/core/exceptions/invalidpropertyexception.cpp
new file mode 100644
index 0000000000..3d95399f65
--- /dev/null
+++ b/src/plugins/qmldesigner/core/exceptions/invalidpropertyexception.cpp
@@ -0,0 +1,74 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "invalidpropertyexception.h"
+/*!
+\class QmlDesigner::InvalidPropertyException
+\ingroup CoreExceptions
+\brief Exception for a invalid property
+
+\see AbstractProperty
+*/
+namespace QmlDesigner {
+/*!
+\brief Constructor
+
+\param line use the __LINE__ macro
+\param function use the __FUNCTION__ or the Q_FUNC_INFO macro
+\param file use the __FILE__ macro
+*/
+InvalidPropertyException::InvalidPropertyException(int line,
+ const QString &function,
+ const QString &file,
+ const QString &argument)
+ : Exception(line, function, file), m_argument(argument)
+{
+}
+
+/*!
+\brief Returns the type of this exception
+
+\returns the type as a string
+*/
+QString InvalidPropertyException::type() const
+{
+ return "InvalidPropertyException";
+}
+
+/*!
+\brief Returns the argument of the property of this exception
+
+\returns the argument as a string
+*/
+QString InvalidPropertyException::argument() const
+{
+ return m_argument;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/core/exceptions/invalidqmlsourceexception.cpp b/src/plugins/qmldesigner/core/exceptions/invalidqmlsourceexception.cpp
new file mode 100644
index 0000000000..ab3f680e0a
--- /dev/null
+++ b/src/plugins/qmldesigner/core/exceptions/invalidqmlsourceexception.cpp
@@ -0,0 +1,71 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "invalidqmlsourceexception.h"
+
+/*!
+\class QmlDesigner::InvalidQmlSourceException
+\ingroup CoreExceptions
+\brief Exception for invalid qml source code
+
+*/
+namespace QmlDesigner {
+/*!
+\brief Constructor
+
+\param line use the __LINE__ macro
+\param function use the __FUNCTION__ or the Q_FUNC_INFO macro
+\param file use the __FILE__ macro
+\param qmlSource qml source string
+*/
+InvalidQmlSourceException::InvalidQmlSourceException(int line,
+ const QString &function,
+ const QString &file,
+ const QString &qmlSource)
+ : Exception(line, function, file),
+ m_qmlSource(qmlSource)
+{
+}
+
+/*!
+\brief Returns the type of this exception
+
+\returns the type as a string
+*/
+QString InvalidQmlSourceException::type() const
+{
+ return "InvalidQmlSourceException";
+}
+
+QString InvalidQmlSourceException::description() const
+{
+ return m_qmlSource;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/core/exceptions/invalidreparentingexception.cpp b/src/plugins/qmldesigner/core/exceptions/invalidreparentingexception.cpp
new file mode 100644
index 0000000000..529b7e08c3
--- /dev/null
+++ b/src/plugins/qmldesigner/core/exceptions/invalidreparentingexception.cpp
@@ -0,0 +1,62 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "invalidreparentingexception.h"
+/*!
+\class QmlDesigner::InvalidReparentingException
+\ingroup CoreExceptions
+\brief Exception for a invalid reparinting
+
+\see ModelNode
+*/
+namespace QmlDesigner {
+/*!
+\brief Constructor
+
+\param line use the __LINE__ macro
+\param function use the __FUNCTION__ or the Q_FUNC_INFO macro
+\param file use the __FILE__ macro
+*/
+InvalidReparentingException::InvalidReparentingException(int line,
+ const QString &function,
+ const QString &file)
+ : Exception(line, function, file)
+{
+}
+
+/*!
+\brief Returns the type of this exception
+
+\returns the type as a string
+*/
+QString InvalidReparentingException::type() const
+{
+ return "InvalidReparentingException";
+}
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/core/exceptions/invalidslideindexexception.cpp b/src/plugins/qmldesigner/core/exceptions/invalidslideindexexception.cpp
new file mode 100644
index 0000000000..64e07942fb
--- /dev/null
+++ b/src/plugins/qmldesigner/core/exceptions/invalidslideindexexception.cpp
@@ -0,0 +1,64 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "invalidslideindexexception.h"
+
+/*!
+\class QmlDesigner::InvalidSlideIndexException
+\ingroup CoreExceptions
+\brief Exception for a invalid index for s slide
+
+\see ModelNode
+*/
+namespace QmlDesigner {
+/*!
+\brief Constructor
+
+\param line use the __LINE__ macro
+\param function use the __FUNCTION__ or the Q_FUNC_INFO macro
+\param file use the __FILE__ macro
+*/
+InvalidSlideIndexException::InvalidSlideIndexException(int line,
+ const QString &function,
+ const QString &file)
+ : Exception(line, function, file)
+{
+}
+
+/*!
+\brief Returns the type of this exception
+
+\returns the type as a string
+*/
+QString InvalidSlideIndexException::type() const
+{
+ return "InvalidSlideIndexException";
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/core/exceptions/modificationgroupexception.cpp b/src/plugins/qmldesigner/core/exceptions/modificationgroupexception.cpp
new file mode 100644
index 0000000000..6a8c679c2b
--- /dev/null
+++ b/src/plugins/qmldesigner/core/exceptions/modificationgroupexception.cpp
@@ -0,0 +1,63 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "modificationgroupexception.h"
+
+/*!
+\class QmlDesigner::ModificationGroupException
+\ingroup CoreExceptions
+\brief Exception for a modification group
+
+*/
+namespace QmlDesigner {
+/*!
+\brief Constructor
+
+\param line use the __LINE__ macro
+\param function use the __FUNCTION__ or the Q_FUNC_INFO macro
+\param file use the __FILE__ macro
+*/
+ModificationGroupException::ModificationGroupException(int line,
+ const QString &function,
+ const QString &file)
+ : Exception(line, function, file)
+{
+}
+
+/*!
+\brief Returns the type of this exception
+
+\returns the type as a string
+*/
+QString ModificationGroupException::type() const
+{
+ return "ModificationGroupException";
+}
+
+}
diff --git a/src/plugins/qmldesigner/core/exceptions/noanchoringpossibleexception.cpp b/src/plugins/qmldesigner/core/exceptions/noanchoringpossibleexception.cpp
new file mode 100644
index 0000000000..10dab894fe
--- /dev/null
+++ b/src/plugins/qmldesigner/core/exceptions/noanchoringpossibleexception.cpp
@@ -0,0 +1,46 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "noanchoringpossibleexception.h"
+
+namespace QmlDesigner {
+
+NoAnchoringPossibleException::NoAnchoringPossibleException(int line,
+ const QString &function,
+ const QString &file)
+ : Exception(line,function, file)
+{
+}
+
+
+QString NoAnchoringPossibleException::type() const
+{
+ return "NoAnchoringPossibleException";
+}
+} // namespace QKinecticDesigner
diff --git a/src/plugins/qmldesigner/core/exceptions/notimplementedexception.cpp b/src/plugins/qmldesigner/core/exceptions/notimplementedexception.cpp
new file mode 100644
index 0000000000..15c01605af
--- /dev/null
+++ b/src/plugins/qmldesigner/core/exceptions/notimplementedexception.cpp
@@ -0,0 +1,45 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "notimplementedexception.h"
+
+namespace QmlDesigner {
+
+NotImplementedException::NotImplementedException(int line,
+ const QString &function,
+ const QString &file):
+ Exception(line, function, file)
+{
+}
+
+QString NotImplementedException::type() const
+{
+ return "NotImplementedException";
+}
+}
diff --git a/src/plugins/qmldesigner/core/exceptions/removebasestateexception.cpp b/src/plugins/qmldesigner/core/exceptions/removebasestateexception.cpp
new file mode 100644
index 0000000000..93ebbdd1d1
--- /dev/null
+++ b/src/plugins/qmldesigner/core/exceptions/removebasestateexception.cpp
@@ -0,0 +1,64 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "removebasestateexception.h"
+
+/*!
+\class QmlDesigner::RemoveBaseStateException
+\ingroup CoreExceptions
+\brief Exception if you try to remove a BaseState
+
+/see NodeState ModelState
+*/
+namespace QmlDesigner {
+/*!
+\brief Constructor
+
+\param line use the __LINE__ macro
+\param function use the __FUNCTION__ or the Q_FUNC_INFO macro
+\param file use the __FILE__ macro
+*/
+RemoveBaseStateException::RemoveBaseStateException(int line,
+ const QString &function,
+ const QString &file)
+ : Exception(line, function, file)
+{
+}
+
+/*!
+\brief Returns the type of this exception
+
+\returns the type as a string
+*/
+QString RemoveBaseStateException::type() const
+{
+ return "RemoveBaseStateException";
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/core/filemanager/addarraymembervisitor.cpp b/src/plugins/qmldesigner/core/filemanager/addarraymembervisitor.cpp
new file mode 100644
index 0000000000..026591f85f
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/addarraymembervisitor.cpp
@@ -0,0 +1,118 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <qmljsast_p.h>
+#include <qmljsengine_p.h>
+
+#include "addarraymembervisitor.h"
+
+using namespace QmlEditor;
+using namespace QmlEditor::Internal;
+using namespace QmlJS;
+using namespace QmlJS::AST;
+
+AddArrayMemberVisitor::AddArrayMemberVisitor(QmlDesigner::TextModifier &modifier,
+ quint32 parentLocation,
+ const QString &propertyName,
+ const QString &content):
+ QMLRewriter(modifier),
+ m_parentLocation(parentLocation),
+ m_propertyName(propertyName),
+ m_content(content),
+ m_convertObjectBindingIntoArrayBinding(false)
+{
+}
+
+void AddArrayMemberVisitor::findArrayBindingAndInsert(const QString &m_propertyName, UiObjectMemberList *ast)
+{
+ for (UiObjectMemberList *iter = ast; iter; iter = iter->next) {
+ if (UiArrayBinding *arrayBinding = cast<UiArrayBinding*>(iter->member)) {
+ if (flatten(arrayBinding->qualifiedId) == m_propertyName)
+ insertInto(arrayBinding);
+ } else if (UiObjectBinding *objectBinding = cast<UiObjectBinding*>(iter->member)) {
+ if (flatten(objectBinding->qualifiedId) == m_propertyName && willConvertObjectBindingIntoArrayBinding())
+ convertAndAdd(objectBinding);
+ }
+ }
+}
+
+bool AddArrayMemberVisitor::visit(QmlJS::AST::UiObjectBinding *ast)
+{
+ if (didRewriting())
+ return false;
+
+ if (ast->firstSourceLocation().offset == m_parentLocation)
+ findArrayBindingAndInsert(m_propertyName, ast->initializer->members);
+
+ return !didRewriting();
+}
+
+bool AddArrayMemberVisitor::visit(QmlJS::AST::UiObjectDefinition *ast)
+{
+ if (didRewriting())
+ return false;
+
+ if (ast->firstSourceLocation().offset == m_parentLocation)
+ findArrayBindingAndInsert(m_propertyName, ast->initializer->members);
+
+ return !didRewriting();
+}
+
+void AddArrayMemberVisitor::insertInto(QmlJS::AST::UiArrayBinding *arrayBinding)
+{
+ UiObjectMember *lastMember = 0;
+ for (UiArrayMemberList *iter = arrayBinding->members; iter; iter = iter->next)
+ if (iter->member)
+ lastMember = iter->member;
+
+ if (!lastMember)
+ return; // an array binding cannot be empty, so there will (or should) always be a last member.
+
+ const int insertionPoint = lastMember->lastSourceLocation().end();
+ const int indentDepth = calculateIndentDepth(lastMember->firstSourceLocation());
+
+ replace(insertionPoint, 0, QLatin1String(",\n") + addIndentation(m_content, indentDepth));
+
+ setDidRewriting(true);
+}
+
+void AddArrayMemberVisitor::convertAndAdd(QmlJS::AST::UiObjectBinding *objectBinding)
+{
+ const int indentDepth = calculateIndentDepth(objectBinding->firstSourceLocation());
+ const QString arrayPrefix = QLatin1String("[\n") + addIndentation(QLatin1String(""), indentDepth);
+ replace(objectBinding->qualifiedTypeNameId->identifierToken.offset, 0, arrayPrefix);
+ const int insertionPoint = objectBinding->lastSourceLocation().end();
+ replace(insertionPoint, 0,
+ QLatin1String(",\n")
+ + addIndentation(m_content, indentDepth) + QLatin1Char('\n')
+ + addIndentation(QLatin1String("]"), indentDepth)
+ );
+
+ setDidRewriting(true);
+}
diff --git a/src/plugins/qmldesigner/core/filemanager/addarraymembervisitor.h b/src/plugins/qmldesigner/core/filemanager/addarraymembervisitor.h
new file mode 100644
index 0000000000..2b59521574
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/addarraymembervisitor.h
@@ -0,0 +1,72 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef ADDARRAYMEMBERVISITOR_H
+#define ADDARRAYMEMBERVISITOR_H
+
+#include "qmlrewriter.h"
+
+namespace QmlEditor {
+namespace Internal {
+
+class AddArrayMemberVisitor: public QMLRewriter
+{
+public:
+ AddArrayMemberVisitor(QmlDesigner::TextModifier &modifier,
+ quint32 parentLocation,
+ const QString &propertyName,
+ const QString &content);
+
+ bool willConvertObjectBindingIntoArrayBinding() const
+ { return m_convertObjectBindingIntoArrayBinding; }
+
+ void setConvertObjectBindingIntoArrayBinding(bool convertObjectBindingIntoArrayBinding)
+ { m_convertObjectBindingIntoArrayBinding = convertObjectBindingIntoArrayBinding; }
+
+protected:
+ virtual bool visit(QmlJS::AST::UiObjectBinding *ast);
+ virtual bool visit(QmlJS::AST::UiObjectDefinition *ast);
+
+private:
+ void findArrayBindingAndInsert(const QString &m_propertyName, QmlJS::AST::UiObjectMemberList *ast);
+
+ void insertInto(QmlJS::AST::UiArrayBinding *arrayBinding);
+ void convertAndAdd(QmlJS::AST::UiObjectBinding *objectBinding);
+
+private:
+ quint32 m_parentLocation;
+ QString m_propertyName;
+ QString m_content;
+ bool m_convertObjectBindingIntoArrayBinding;
+};
+
+} // namespace Internal
+} // namespace QmlEditor
+
+#endif // ADDARRAYMEMBERVISITOR_H
diff --git a/src/plugins/qmldesigner/core/filemanager/addobjectvisitor.cpp b/src/plugins/qmldesigner/core/filemanager/addobjectvisitor.cpp
new file mode 100644
index 0000000000..a9b5c9ad32
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/addobjectvisitor.cpp
@@ -0,0 +1,93 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <qmljsast_p.h>
+#include <qmljsengine_p.h>
+
+#include "addobjectvisitor.h"
+
+using namespace QmlEditor;
+using namespace QmlEditor::Internal;
+using namespace QmlJS;
+using namespace QmlJS::AST;
+
+AddObjectVisitor::AddObjectVisitor(QmlDesigner::TextModifier &modifier,
+ quint32 parentLocation,
+ const QString &content,
+ const QStringList &propertyOrder):
+ QMLRewriter(modifier),
+ m_parentLocation(parentLocation),
+ m_content(content),
+ m_propertyOrder(propertyOrder)
+{
+}
+
+bool AddObjectVisitor::visit(QmlJS::AST::UiObjectBinding *ast)
+{
+ if (didRewriting())
+ return false;
+
+ if (ast->qualifiedTypeNameId->identifierToken.offset == m_parentLocation)
+ insertInto(ast->initializer);
+
+ return !didRewriting();
+}
+
+bool AddObjectVisitor::visit(QmlJS::AST::UiObjectDefinition *ast)
+{
+ if (didRewriting())
+ return false;
+
+ if (ast->firstSourceLocation().offset == m_parentLocation)
+ insertInto(ast->initializer);
+
+ return !didRewriting();
+}
+
+void AddObjectVisitor::insertInto(QmlJS::AST::UiObjectInitializer *ast)
+{
+ UiObjectMemberList *insertAfter = searchMemberToInsertAfter(ast->members, QString::null, m_propertyOrder);
+
+ int insertionPoint;
+ int indentDepth;
+ QString textToInsert;
+ if (insertAfter && insertAfter->member) {
+ insertionPoint = insertAfter->member->lastSourceLocation().end();
+ indentDepth = calculateIndentDepth(insertAfter->member->lastSourceLocation());
+ textToInsert += QLatin1String("\n");
+ } else {
+ insertionPoint = ast->lbraceToken.end();
+ indentDepth = calculateIndentDepth(ast->lbraceToken) + 4;
+ }
+
+ textToInsert += addIndentation(m_content, indentDepth);
+ replace(insertionPoint, 0, QLatin1String("\n") + textToInsert);
+
+ setDidRewriting(true);
+}
diff --git a/src/plugins/qmldesigner/core/filemanager/addobjectvisitor.h b/src/plugins/qmldesigner/core/filemanager/addobjectvisitor.h
new file mode 100644
index 0000000000..4a3097ffa5
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/addobjectvisitor.h
@@ -0,0 +1,62 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef ADDOBJECTVISITOR_H
+#define ADDOBJECTVISITOR_H
+
+#include "qmlrewriter.h"
+
+namespace QmlEditor {
+namespace Internal {
+
+class AddObjectVisitor: public QMLRewriter
+{
+public:
+ AddObjectVisitor(QmlDesigner::TextModifier &modifier,
+ quint32 parentLocation,
+ const QString &content,
+ const QStringList &propertyOrder);
+
+protected:
+ virtual bool visit(QmlJS::AST::UiObjectBinding *ast);
+ virtual bool visit(QmlJS::AST::UiObjectDefinition *ast);
+
+private:
+ void insertInto(QmlJS::AST::UiObjectInitializer *ast);
+
+private:
+ quint32 m_parentLocation;
+ QString m_content;
+ QStringList m_propertyOrder;
+};
+
+} // namespace Internal
+} // namespace QmlEditor
+
+#endif // ADDOBJECTVISITOR_H
diff --git a/src/plugins/qmldesigner/core/filemanager/addpropertyvisitor.cpp b/src/plugins/qmldesigner/core/filemanager/addpropertyvisitor.cpp
new file mode 100644
index 0000000000..b93792e563
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/addpropertyvisitor.cpp
@@ -0,0 +1,136 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <qmljsast_p.h>
+#include <qmljsengine_p.h>
+
+#include "addpropertyvisitor.h"
+
+using namespace QmlEditor;
+using namespace QmlEditor::Internal;
+using namespace QmlJS;
+using namespace QmlJS::AST;
+
+AddPropertyVisitor::AddPropertyVisitor(QmlDesigner::TextModifier &modifier,
+ quint32 parentLocation,
+ const QString &name,
+ const QString &value,
+ QmlRefactoring::PropertyType propertyType,
+ const QStringList &propertyOrder):
+ QMLRewriter(modifier),
+ m_parentLocation(parentLocation),
+ m_name(name),
+ m_value(value),
+ m_propertyType(propertyType),
+ m_propertyOrder(propertyOrder)
+{
+}
+
+bool AddPropertyVisitor::visit(QmlJS::AST::UiObjectDefinition *ast)
+{
+ if (didRewriting())
+ return false;
+
+ if (ast->firstSourceLocation().offset == m_parentLocation) {
+ addInMembers(ast->initializer);
+ return false;
+ }
+
+ return !didRewriting();
+}
+
+bool AddPropertyVisitor::visit(QmlJS::AST::UiObjectBinding *ast)
+{
+ if (didRewriting())
+ return false;
+
+ if (ast->qualifiedTypeNameId->identifierToken.offset == m_parentLocation) {
+ addInMembers(ast->initializer);
+ return false;
+ }
+
+ return !didRewriting();
+}
+
+void AddPropertyVisitor::addInMembers(QmlJS::AST::UiObjectInitializer *initializer)
+{
+ UiObjectMemberList *insertAfter = searchMemberToInsertAfter(initializer->members, m_name, m_propertyOrder);
+ SourceLocation endOfPreviousMember;
+ SourceLocation startOfNextMember;
+ unsigned indentDepth;
+
+ if (insertAfter == 0 || insertAfter->member == 0) {
+ // insert as first member
+ endOfPreviousMember = initializer->lbraceToken;
+
+ if (initializer->members && initializer->members->member)
+ startOfNextMember = initializer->members->member->firstSourceLocation();
+ else
+ startOfNextMember = initializer->rbraceToken;
+
+ indentDepth = calculateIndentDepth(endOfPreviousMember) + 4;
+ } else {
+ endOfPreviousMember = insertAfter->member->lastSourceLocation();
+
+ if (insertAfter->next && insertAfter->next->member)
+ startOfNextMember = insertAfter->next->member->firstSourceLocation();
+ else
+ startOfNextMember = initializer->rbraceToken;
+
+ indentDepth = calculateIndentDepth(endOfPreviousMember);
+ }
+
+ QString newPropertyTemplate;
+ switch (m_propertyType) {
+ case QmlRefactoring::ArrayBinding:
+ newPropertyTemplate = QLatin1String("%1: [\n%2\n]");
+ m_value = addIndentation(m_value, 4);
+ break;
+
+ case QmlRefactoring::ObjectBinding:
+ newPropertyTemplate = QLatin1String("%1: %2");
+ break;
+
+ case QmlRefactoring::ScriptBinding:
+ newPropertyTemplate = QLatin1String("%1: %2");
+ break;
+
+ default:
+ Q_ASSERT(!"unknown property type");
+ }
+
+ const bool isOneLiner = endOfPreviousMember.startLine == startOfNextMember.startLine;
+ if (isOneLiner)
+ newPropertyTemplate += QLatin1Char('\n');
+
+ const QString newPropertyText = addIndentation(newPropertyTemplate.arg(m_name, m_value), indentDepth);
+ replace(endOfPreviousMember.end(), 0, QLatin1Char('\n') + newPropertyText);
+
+ setDidRewriting(true);
+}
diff --git a/src/plugins/qmldesigner/core/filemanager/addpropertyvisitor.h b/src/plugins/qmldesigner/core/filemanager/addpropertyvisitor.h
new file mode 100644
index 0000000000..a375698a08
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/addpropertyvisitor.h
@@ -0,0 +1,68 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef ADDPROPERTYVISITOR_H
+#define ADDPROPERTYVISITOR_H
+
+#include "qmlrefactoring.h"
+#include "qmlrewriter.h"
+
+namespace QmlEditor {
+namespace Internal {
+
+class AddPropertyVisitor: public QMLRewriter
+{
+public:
+public:
+ AddPropertyVisitor(QmlDesigner::TextModifier &modifier,
+ quint32 parentLocation,
+ const QString &name,
+ const QString &value,
+ QmlEditor::QmlRefactoring::PropertyType propertyType,
+ const QStringList &propertyOrder);
+
+protected:
+ virtual bool visit(QmlJS::AST::UiObjectDefinition *ast);
+ virtual bool visit(QmlJS::AST::UiObjectBinding *ast);
+
+private:
+ void addInMembers(QmlJS::AST::UiObjectInitializer *initializer);
+
+private:
+ quint32 m_parentLocation;
+ QString m_name;
+ QString m_value;
+ QmlEditor::QmlRefactoring::PropertyType m_propertyType;
+ QStringList m_propertyOrder;
+};
+
+} // namespace Internal
+} // namespace QmlEditor
+
+#endif // ADDPROPERTYVISITOR_H
diff --git a/src/plugins/qmldesigner/core/filemanager/astobjecttextextractor.cpp b/src/plugins/qmldesigner/core/filemanager/astobjecttextextractor.cpp
new file mode 100644
index 0000000000..e7b7590418
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/astobjecttextextractor.cpp
@@ -0,0 +1,75 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "astobjecttextextractor.h"
+#include "qmljsast_p.h"
+
+using namespace QmlEditor;
+using namespace QmlJS::AST;
+
+ASTObjectTextExtractor::ASTObjectTextExtractor(const QString &text):
+ m_document(QmlDocument::create("<ASTObjectTextExtractor>"))
+{
+ m_document->setSource(text);
+ m_document->parse();
+}
+
+QString ASTObjectTextExtractor::operator ()(int location)
+{
+ Q_ASSERT(location >= 0);
+
+ m_location = location;
+ m_text.clear();
+
+ Node::accept(m_document->program(), this);
+
+ return m_text;
+}
+
+bool ASTObjectTextExtractor::visit(QmlJS::AST::UiObjectBinding *ast)
+{
+ if (!m_text.isEmpty())
+ return false;
+
+ if (ast->qualifiedTypeNameId->identifierToken.offset == m_location)
+ m_text = m_document->source().mid(m_location, ast->lastSourceLocation().end() - m_location);
+
+ return m_text.isEmpty();
+}
+
+bool ASTObjectTextExtractor::visit(QmlJS::AST::UiObjectDefinition *ast)
+{
+ if (!m_text.isEmpty())
+ return false;
+
+ if (ast->firstSourceLocation().offset == m_location)
+ m_text = m_document->source().mid(m_location, ast->lastSourceLocation().end() - m_location);
+
+ return m_text.isEmpty();
+}
diff --git a/src/plugins/qmldesigner/core/filemanager/astobjecttextextractor.h b/src/plugins/qmldesigner/core/filemanager/astobjecttextextractor.h
new file mode 100644
index 0000000000..029106f440
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/astobjecttextextractor.h
@@ -0,0 +1,59 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef ASTOBJECTTEXTEXTRACTOR_H
+#define ASTOBJECTTEXTEXTRACTOR_H
+
+#include <QtCore/QString>
+
+#include "qmldocument.h"
+#include "qmljsastvisitor_p.h"
+
+namespace QmlEditor {
+
+class ASTObjectTextExtractor: public QmlJS::AST::Visitor
+{
+public:
+ ASTObjectTextExtractor(const QString &text);
+
+ QString operator()(int location);
+
+protected:
+ virtual bool visit(QmlJS::AST::UiObjectBinding *ast);
+ virtual bool visit(QmlJS::AST::UiObjectDefinition *ast);
+
+private:
+ QmlDocument::Ptr m_document;
+ quint32 m_location;
+ QString m_text;
+};
+
+} // namespace QmlEditor
+
+#endif // ASTOBJECTTEXTEXTRACTOR_H
diff --git a/src/plugins/qmldesigner/core/filemanager/changeimportsvisitor.cpp b/src/plugins/qmldesigner/core/filemanager/changeimportsvisitor.cpp
new file mode 100644
index 0000000000..5ecac14e1a
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/changeimportsvisitor.cpp
@@ -0,0 +1,80 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <qmljsast_p.h>
+#include <qmljsengine_p.h>
+
+#include "changeimportsvisitor.h"
+
+using namespace QmlJS;
+using namespace QmlJS::AST;
+
+using namespace QmlDesigner;
+using namespace QmlDesigner::Internal;
+using namespace QmlEditor::Internal;
+
+ChangeImportsVisitor::ChangeImportsVisitor(TextModifier &textModifier, const QSet<Import> &addedImports, const QSet<Import> &removedImports, const QString &source):
+ QMLRewriter(textModifier),
+ CopyPasteUtil(source),
+ m_addedImports(addedImports),
+ m_removedImports(removedImports)
+{
+}
+
+bool ChangeImportsVisitor::visit(QmlJS::AST::UiProgram *ast)
+{
+ if (ast->imports)
+ accept(ast->imports);
+
+ return false;
+}
+
+bool ChangeImportsVisitor::visit(QmlJS::AST::UiImportList *ast)
+{
+ if (!ast)
+ return false;
+
+ quint32 prevEnd = 0;
+ for (UiImportList *it = ast; it; it = it->next) {
+ UiImport *imp = it->import;
+ if (!imp)
+ continue;
+
+ if (m_removedImports.remove(createImport(imp)))
+ replace(prevEnd, imp->lastSourceLocation().end() - prevEnd, "");
+
+ prevEnd = imp->lastSourceLocation().end();
+ }
+
+ foreach (const Import &i, m_addedImports) {
+ replace(prevEnd, 0, i.toString(false) + "\n");
+ }
+
+ return false;
+}
diff --git a/src/plugins/qmldesigner/core/filemanager/changeimportsvisitor.h b/src/plugins/qmldesigner/core/filemanager/changeimportsvisitor.h
new file mode 100644
index 0000000000..9237799415
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/changeimportsvisitor.h
@@ -0,0 +1,61 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef CHANGEIMPORTSVISITOR_H
+#define CHANGEIMPORTSVISITOR_H
+
+#include <QtCore/QSet>
+
+#include <model/copypasteutil.h>
+#include "import.h"
+#include "qmlrewriter.h"
+
+namespace QmlEditor {
+namespace Internal {
+
+class ChangeImportsVisitor: public QMLRewriter, protected QmlDesigner::Internal::CopyPasteUtil
+{
+public:
+ ChangeImportsVisitor(QmlDesigner::TextModifier &textModifier,
+ const QSet<QmlDesigner::Import> &addedImports,
+ const QSet<QmlDesigner::Import> &removedImports, const QString &source);
+
+protected:
+ virtual bool visit(QmlJS::AST::UiProgram *ast);
+ virtual bool visit(QmlJS::AST::UiImportList *ast);
+
+private:
+ QSet<QmlDesigner::Import> m_addedImports;
+ QSet<QmlDesigner::Import> m_removedImports;
+};
+
+} // namespace Internal
+} // namespace QmlEditor
+
+#endif // CHANGEIMPORTSVISITOR_H
diff --git a/src/plugins/qmldesigner/core/filemanager/changeobjecttypevisitor.cpp b/src/plugins/qmldesigner/core/filemanager/changeobjecttypevisitor.cpp
new file mode 100644
index 0000000000..d0624f6ab8
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/changeobjecttypevisitor.cpp
@@ -0,0 +1,81 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "changeobjecttypevisitor.h"
+#include <qmljsast_p.h>
+#include <qmljsengine_p.h>
+
+using namespace QmlJS;
+using namespace QmlJS::AST;
+using namespace QmlEditor::Internal;
+
+ChangeObjectTypeVisitor::ChangeObjectTypeVisitor(QmlDesigner::TextModifier &modifier,
+ quint32 nodeLocation,
+ const QString &newType):
+ QMLRewriter(modifier),
+ m_nodeLocation(nodeLocation),
+ m_newType(newType)
+{
+}
+
+bool ChangeObjectTypeVisitor::visit(UiObjectDefinition *ast)
+{
+ if (ast->firstSourceLocation().offset == m_nodeLocation) {
+ replaceType(ast->qualifiedTypeNameId);
+ return false;
+ }
+
+ return !didRewriting();
+}
+
+bool ChangeObjectTypeVisitor::visit(UiObjectBinding *ast)
+{
+ const quint32 start = ast->qualifiedTypeNameId->identifierToken.offset;
+
+ if (start == m_nodeLocation) {
+ replaceType(ast->qualifiedTypeNameId);
+ return false;
+ }
+
+ return !didRewriting();
+}
+
+void ChangeObjectTypeVisitor::replaceType(UiQualifiedId *typeId)
+{
+ Q_ASSERT(typeId);
+
+ const int startOffset = typeId->identifierToken.offset;
+ int endOffset = typeId->identifierToken.end();
+ for (UiQualifiedId *iter = typeId->next; iter; iter = iter->next)
+ if (!iter->next)
+ endOffset = iter->identifierToken.end();
+
+ replace(startOffset, endOffset - startOffset, m_newType);
+ setDidRewriting(true);
+}
diff --git a/src/plugins/qmldesigner/core/filemanager/changeobjecttypevisitor.h b/src/plugins/qmldesigner/core/filemanager/changeobjecttypevisitor.h
new file mode 100644
index 0000000000..01c2e360a7
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/changeobjecttypevisitor.h
@@ -0,0 +1,60 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef CHANGEOBJECTTYPEVISITOR_H
+#define CHANGEOBJECTTYPEVISITOR_H
+
+#include "qmlrewriter.h"
+
+namespace QmlEditor {
+namespace Internal {
+
+class ChangeObjectTypeVisitor: public QMLRewriter
+{
+public:
+ ChangeObjectTypeVisitor(QmlDesigner::TextModifier &modifier,
+ quint32 nodeLocation,
+ const QString &newType);
+
+protected:
+ virtual bool visit(QmlJS::AST::UiObjectDefinition *ast);
+ virtual bool visit(QmlJS::AST::UiObjectBinding *ast);
+
+private:
+ void replaceType(QmlJS::AST::UiQualifiedId *typeId);
+
+private:
+ quint32 m_nodeLocation;
+ QString m_newType;
+};
+
+} // namespace Internal
+} // namespace QmlEditor
+
+#endif // CHANGEOBJECTTYPEVISITOR_H
diff --git a/src/plugins/qmldesigner/core/filemanager/changepropertyvisitor.cpp b/src/plugins/qmldesigner/core/filemanager/changepropertyvisitor.cpp
new file mode 100644
index 0000000000..885671d183
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/changepropertyvisitor.cpp
@@ -0,0 +1,191 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <qmljsast_p.h>
+#include <qmljsengine_p.h>
+
+#include "changepropertyvisitor.h"
+
+using namespace QmlJS;
+using namespace QmlJS::AST;
+using namespace QmlEditor;
+using namespace QmlEditor::Internal;
+
+ChangePropertyVisitor::ChangePropertyVisitor(QmlDesigner::TextModifier &modifier,
+ quint32 parentLocation,
+ const QString &name,
+ const QString &value,
+ QmlRefactoring::PropertyType propertyType):
+ QMLRewriter(modifier),
+ m_parentLocation(parentLocation),
+ m_name(name),
+ m_value(value),
+ m_propertyType(propertyType)
+{
+}
+
+bool ChangePropertyVisitor::visit(QmlJS::AST::UiObjectDefinition *ast)
+{
+ if (didRewriting())
+ return false;
+
+ const quint32 objectStart = ast->firstSourceLocation().offset;
+
+ if (objectStart == m_parentLocation) {
+ replaceInMembers(ast->initializer);
+ return false;
+ }
+
+ return !didRewriting();
+}
+
+bool ChangePropertyVisitor::visit(QmlJS::AST::UiObjectBinding *ast)
+{
+ if (didRewriting())
+ return false;
+
+ const quint32 objectStart = ast->qualifiedTypeNameId->identifierToken.offset;
+
+ if (objectStart == m_parentLocation) {
+ replaceInMembers(ast->initializer);
+ return false;
+ }
+
+ return !didRewriting();
+}
+
+void ChangePropertyVisitor::replaceInMembers(UiObjectInitializer *initializer)
+{
+ for (UiObjectMemberList *members = initializer->members; members; members = members->next) {
+ UiObjectMember *propertyMember = members->member;
+
+ if (isMatchingPropertyMember(propertyMember)) {
+ switch (m_propertyType) {
+ case QmlRefactoring::ArrayBinding:
+ insertIntoArray(cast<UiArrayBinding*>(propertyMember));
+ break;
+
+ case QmlRefactoring::ObjectBinding:
+ replaceMemberValue(propertyMember, false);
+ break;
+
+ case QmlRefactoring::ScriptBinding:
+ replaceMemberValue(propertyMember, nextMemberOnSameLine(members));
+ break;
+
+ default:
+ Q_ASSERT(!"Unhandled QmlRefactoring::PropertyType");
+ }
+
+ break;
+ }
+ }
+}
+
+void ChangePropertyVisitor::replaceMemberValue(UiObjectMember *propertyMember, bool needsSemicolon)
+{
+ QString replacement = m_value;
+ int startOffset = -1;
+ int endOffset = -1;
+ if (UiObjectBinding *objectBinding = AST::cast<UiObjectBinding *>(propertyMember)) {
+ startOffset = objectBinding->qualifiedTypeNameId->identifierToken.offset;
+ endOffset = objectBinding->initializer->rbraceToken.end();
+ } else if (UiScriptBinding *scriptBinding = AST::cast<UiScriptBinding *>(propertyMember)) {
+ startOffset = scriptBinding->statement->firstSourceLocation().offset;
+ endOffset = scriptBinding->statement->lastSourceLocation().end();
+ } else if (UiArrayBinding *arrayBinding = AST::cast<UiArrayBinding *>(propertyMember)) {
+ startOffset = arrayBinding->lbracketToken.offset;
+ endOffset = arrayBinding->rbracketToken.end();
+ } else if (UiPublicMember *publicMember = AST::cast<UiPublicMember*>(propertyMember)) {
+ if (publicMember->expression) {
+ startOffset = publicMember->expression->firstSourceLocation().offset;
+ if (publicMember->semicolonToken.isValid())
+ endOffset = publicMember->semicolonToken.end();
+ else
+ endOffset = publicMember->expression->lastSourceLocation().offset;
+ } else {
+ startOffset = publicMember->lastSourceLocation().end();
+ endOffset = startOffset;
+ if (publicMember->semicolonToken.isValid())
+ startOffset = publicMember->semicolonToken.offset;
+ replacement.prepend(QLatin1String(": "));
+ }
+ } else {
+ return;
+ }
+
+ if (needsSemicolon)
+ replacement += ';';
+
+ replace(startOffset, endOffset - startOffset, replacement);
+ setDidRewriting(true);
+}
+
+bool ChangePropertyVisitor::isMatchingPropertyMember(QmlJS::AST::UiObjectMember *member) const
+{
+ if (UiObjectBinding *objectBinding = AST::cast<UiObjectBinding *>(member)) {
+ return m_name == flatten(objectBinding->qualifiedId);
+ } else if (UiScriptBinding *scriptBinding = AST::cast<UiScriptBinding *>(member)) {
+ return m_name == flatten(scriptBinding->qualifiedId);
+ } else if (UiArrayBinding *arrayBinding = AST::cast<UiArrayBinding *>(member)) {
+ return m_name == flatten(arrayBinding->qualifiedId);
+ } else if (UiPublicMember *publicMember = AST::cast<UiPublicMember *>(member)) {
+ return m_name == publicMember->name->asString();
+ } else {
+ return false;
+ }
+}
+
+bool ChangePropertyVisitor::nextMemberOnSameLine(UiObjectMemberList *members)
+{
+ if (members && members->next && members->next->member) {
+ return members->next->member->firstSourceLocation().startLine == members->member->lastSourceLocation().startLine;
+ } else {
+ return false;
+ }
+}
+
+void ChangePropertyVisitor::insertIntoArray(QmlJS::AST::UiArrayBinding *ast)
+{
+ if (!ast)
+ return;
+
+ UiObjectMember *lastMember = 0;
+ for (UiArrayMemberList *iter = ast->members; iter; iter = iter->next) {
+ }
+
+ if (!lastMember)
+ return;
+
+ const int insertionPoint = lastMember->lastSourceLocation().end();
+ const int indentDepth = calculateIndentDepth(lastMember->firstSourceLocation());
+ const QString indentedArrayMember = addIndentation(m_value, indentDepth);
+ replace(insertionPoint, 0, QLatin1String(",\n") + indentedArrayMember);
+ setDidRewriting(true);
+}
diff --git a/src/plugins/qmldesigner/core/filemanager/changepropertyvisitor.h b/src/plugins/qmldesigner/core/filemanager/changepropertyvisitor.h
new file mode 100644
index 0000000000..6cc41d8f91
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/changepropertyvisitor.h
@@ -0,0 +1,70 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef CHANGEPROPERTYVISITOR_H
+#define CHANGEPROPERTYVISITOR_H
+
+#include "qmlrefactoring.h"
+#include "qmlrewriter.h"
+
+namespace QmlEditor {
+namespace Internal {
+
+class ChangePropertyVisitor: public QMLRewriter
+{
+public:
+ ChangePropertyVisitor(QmlDesigner::TextModifier &modifier,
+ quint32 parentLocation,
+ const QString &name,
+ const QString &value,
+ QmlRefactoring::PropertyType propertyType);
+
+protected:
+ virtual bool visit(QmlJS::AST::UiObjectDefinition *ast);
+ virtual bool visit(QmlJS::AST::UiObjectBinding *ast);
+
+private:
+ void replaceInMembers(QmlJS::AST::UiObjectInitializer *initializer);
+ void replaceMemberValue(QmlJS::AST::UiObjectMember *propertyMember, bool needsSemicolon);
+ bool isMatchingPropertyMember(QmlJS::AST::UiObjectMember *member) const;
+ static bool nextMemberOnSameLine(QmlJS::AST::UiObjectMemberList *members);
+
+ void insertIntoArray(QmlJS::AST::UiArrayBinding* ast);
+
+private:
+ quint32 m_parentLocation;
+ QString m_name;
+ QString m_value;
+ QmlRefactoring::PropertyType m_propertyType;
+};
+
+} // namespace Internal
+} // namespace QmlEditor
+
+#endif // CHANGEPROPERTYVISITOR_H
diff --git a/src/plugins/qmldesigner/core/filemanager/changeset.cpp b/src/plugins/qmldesigner/core/filemanager/changeset.cpp
new file mode 100644
index 0000000000..b006106a16
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/changeset.cpp
@@ -0,0 +1,359 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "changeset.h"
+
+namespace Utils {
+
+ChangeSet::ChangeSet()
+ : m_string(0), m_cursor(0), m_error(false)
+{
+}
+
+static bool overlaps(int posA, int lengthA, int posB, int lengthB) {
+ if (lengthB > 0) {
+ return
+ // right edge of B contained in A
+ (posA < posB + lengthB && posA + lengthA >= posB + lengthB)
+ // left edge of B contained in A
+ || (posA <= posB && posA + lengthA > posB)
+ // A contained in B
+ || (posB < posA && posB + lengthB > posA + lengthA);
+ } else {
+ return (posB > posA && posB < posA + lengthA);
+ }
+}
+
+bool ChangeSet::hasOverlap(int pos, int length)
+{
+ QListIterator<EditOp> i(m_operationList);
+ while (i.hasNext()) {
+ const EditOp &cmd = i.next();
+
+ switch (cmd.type) {
+ case EditOp::Replace:
+ if (overlaps(pos, length, cmd.pos1, cmd.length1))
+ return true;
+ break;
+
+ case EditOp::Move:
+ if (overlaps(pos, length, cmd.pos1, cmd.length1))
+ return true;
+ if (cmd.pos2 > pos && cmd.pos2 < pos + length)
+ return true;
+ break;
+
+ case EditOp::Insert:
+ if (cmd.pos1 > pos && cmd.pos1 < pos + length)
+ return true;
+ break;
+
+ case EditOp::Remove:
+ if (overlaps(pos, length, cmd.pos1, cmd.length1))
+ return true;
+ break;
+
+ case EditOp::Flip:
+ if (overlaps(pos, length, cmd.pos1, cmd.length1))
+ return true;
+ if (overlaps(pos, length, cmd.pos2, cmd.length2))
+ return true;
+ break;
+
+ case EditOp::Copy:
+ if (overlaps(pos, length, cmd.pos1, cmd.length1))
+ return true;
+ if (cmd.pos2 > pos && cmd.pos2 < pos + length)
+ return true;
+ break;
+
+ case EditOp::Unset:
+ break;
+ }
+ }
+
+ return false;
+}
+
+bool ChangeSet::isEmpty() const
+{
+ return m_operationList.isEmpty();
+}
+
+QList<ChangeSet::EditOp> ChangeSet::operationList() const
+{
+ return m_operationList;
+}
+
+void ChangeSet::clear()
+{
+ m_string = 0;
+ m_cursor = 0;
+ m_operationList.clear();
+ m_error = false;
+}
+
+bool ChangeSet::replace(int pos, int length, const QString &replacement)
+{
+ if (hasOverlap(pos, length))
+ m_error = true;
+
+ EditOp cmd(EditOp::Replace);
+ cmd.pos1 = pos;
+ cmd.length1 = length;
+ cmd.text = replacement;
+ m_operationList += cmd;
+
+ return !m_error;
+}
+
+bool ChangeSet::move(int pos, int length, int to)
+{
+ if (hasOverlap(pos, length)
+ || hasOverlap(to, 0)
+ || overlaps(pos, length, to, 0))
+ m_error = true;
+
+ EditOp cmd(EditOp::Move);
+ cmd.pos1 = pos;
+ cmd.length1 = length;
+ cmd.pos2 = to;
+ m_operationList += cmd;
+
+ return !m_error;
+}
+
+bool ChangeSet::insert(int pos, const QString &text)
+{
+ if (hasOverlap(pos, 0))
+ m_error = true;
+
+ EditOp cmd(EditOp::Insert);
+ cmd.pos1 = pos;
+ cmd.text = text;
+ m_operationList += cmd;
+
+ return !m_error;
+}
+
+bool ChangeSet::remove(int pos, int length)
+{
+ if (hasOverlap(pos, length))
+ m_error = true;
+
+ EditOp cmd(EditOp::Remove);
+ cmd.pos1 = pos;
+ cmd.length1 = length;
+ m_operationList += cmd;
+
+ return !m_error;
+}
+
+bool ChangeSet::flip(int pos1, int length1, int pos2, int length2)
+{
+ if (hasOverlap(pos1, length1)
+ || hasOverlap(pos2, length2)
+ || overlaps(pos1, length1, pos2, length2))
+ m_error = true;
+
+ EditOp cmd(EditOp::Flip);
+ cmd.pos1 = pos1;
+ cmd.length1 = length1;
+ cmd.pos2 = pos2;
+ cmd.length2 = length2;
+ m_operationList += cmd;
+
+ return !m_error;
+}
+
+bool ChangeSet::copy(int pos, int length, int to)
+{
+ if (hasOverlap(pos, length)
+ || hasOverlap(to, 0)
+ || overlaps(pos, length, to, 0))
+ m_error = true;
+
+ EditOp cmd(EditOp::Copy);
+ cmd.pos1 = pos;
+ cmd.length1 = length;
+ cmd.pos2 = to;
+ m_operationList += cmd;
+
+ return !m_error;
+}
+
+void ChangeSet::doReplace(const EditOp &replace, QList<EditOp> *replaceList)
+{
+ Q_ASSERT(replace.type == EditOp::Replace);
+
+ {
+ QMutableListIterator<EditOp> i(*replaceList);
+ while (i.hasNext()) {
+ EditOp &c = i.next();
+ if (replace.pos1 <= c.pos1)
+ c.pos1 += replace.text.size();
+ if (replace.pos1 < c.pos1)
+ c.pos1 -= replace.length1;
+ }
+ }
+
+ if (m_string) {
+ m_string->replace(replace.pos1, replace.length1, replace.text);
+ } else if (m_cursor) {
+ m_cursor->setPosition(replace.pos1);
+ m_cursor->setPosition(replace.pos1 + replace.length1, QTextCursor::KeepAnchor);
+ m_cursor->insertText(replace.text);
+ }
+}
+
+void ChangeSet::convertToReplace(const EditOp &op, QList<EditOp> *replaceList)
+{
+ EditOp replace1(EditOp::Replace);
+ EditOp replace2(EditOp::Replace);
+
+ switch (op.type) {
+ case EditOp::Replace:
+ replaceList->append(op);
+ break;
+
+ case EditOp::Move:
+ replace1.pos1 = op.pos1;
+ replace1.length1 = op.length1;
+ replaceList->append(replace1);
+
+ replace2.pos1 = op.pos2;
+ replace2.text = textAt(op.pos1, op.length1);
+ replaceList->append(replace2);
+ break;
+
+ case EditOp::Insert:
+ replace1.pos1 = op.pos1;
+ replace1.text = op.text;
+ replaceList->append(replace1);
+ break;
+
+ case EditOp::Remove:
+ replace1.pos1 = op.pos1;
+ replace1.length1 = op.length1;
+ replaceList->append(replace1);
+ break;
+
+ case EditOp::Flip:
+ replace1.pos1 = op.pos1;
+ replace1.length1 = op.length1;
+ replace1.text = textAt(op.pos2, op.length2);
+ replaceList->append(replace1);
+
+ replace2.pos1 = op.pos2;
+ replace2.length1 = op.length2;
+ replace2.text = textAt(op.pos1, op.length1);
+ replaceList->append(replace2);
+ break;
+
+ case EditOp::Copy:
+ replace1.pos1 = op.pos2;
+ replace1.text = textAt(op.pos1, op.length1);
+ replaceList->append(replace1);
+ break;
+
+ case EditOp::Unset:
+ break;
+ }
+}
+
+bool ChangeSet::hadErrors()
+{
+ return m_error;
+}
+
+void ChangeSet::apply(QString *s)
+{
+ m_string = s;
+ apply_helper();
+ m_string = 0;
+}
+
+void ChangeSet::apply(QTextCursor *textCursor)
+{
+ m_cursor = textCursor;
+ apply_helper();
+ m_cursor = 0;
+}
+
+QString ChangeSet::textAt(int pos, int length)
+{
+ if (m_string) {
+ return m_string->mid(pos, length);
+ } else if (m_cursor) {
+ m_cursor->setPosition(pos);
+ m_cursor->setPosition(pos + length, QTextCursor::KeepAnchor);
+ return m_cursor->selectedText();
+ }
+ return QString();
+}
+
+void ChangeSet::apply_helper()
+{
+ // convert all ops to replace
+ QList<EditOp> replaceList;
+ {
+ while (!m_operationList.isEmpty()) {
+ const EditOp cmd(m_operationList.first());
+ m_operationList.removeFirst();
+ convertToReplace(cmd, &replaceList);
+ }
+ }
+
+ // execute replaces
+ if (m_cursor)
+ m_cursor->beginEditBlock();
+
+ while (!replaceList.isEmpty()) {
+ const EditOp cmd(replaceList.first());
+ replaceList.removeFirst();
+ doReplace(cmd, &replaceList);
+ }
+
+ if (m_cursor)
+ m_cursor->endEditBlock();
+}
+
+} // end namespace Utils
diff --git a/src/plugins/qmldesigner/core/filemanager/changeset.h b/src/plugins/qmldesigner/core/filemanager/changeset.h
new file mode 100644
index 0000000000..2f46bd835d
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/changeset.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CHANGESET_H
+#define CHANGESET_H
+
+#include "utils_global.h"
+
+#include <QtCore/QString>
+#include <QtCore/QList>
+#include <QtCore/QSharedPointer>
+#include <QtGui/QTextCursor>
+
+namespace Utils {
+
+class QTCREATOR_UTILS_EXPORT ChangeSet
+{
+public:
+ struct EditOp {
+ enum Type
+ {
+ Unset,
+ Replace,
+ Move,
+ Insert,
+ Remove,
+ Flip,
+ Copy
+ };
+
+ EditOp(): type(Unset), pos1(0), pos2(0), length1(0), length2(0) {}
+ EditOp(Type t): type(t), pos1(0), pos2(0), length1(0), length2(0) {}
+
+ Type type;
+ int pos1;
+ int pos2;
+ int length1;
+ int length2;
+ QString text;
+ };
+
+public:
+ ChangeSet();
+
+ bool isEmpty() const;
+
+ QList<EditOp> operationList() const;
+
+ void clear();
+
+ bool replace(int pos, int length, const QString &replacement);
+ bool move(int pos, int length, int to);
+ bool insert(int pos, const QString &text);
+ bool remove(int pos, int length);
+ bool flip(int pos1, int length1, int pos2, int length2);
+ bool copy(int pos, int length, int to);
+
+ bool hadErrors();
+
+ void apply(QString *s);
+ void apply(QTextCursor *textCursor);
+
+private:
+ bool hasOverlap(int pos, int length);
+ QString textAt(int pos, int length);
+
+ void doReplace(const EditOp &replace, QList<EditOp> *replaceList);
+ void convertToReplace(const EditOp &op, QList<EditOp> *replaceList);
+
+ void apply_helper();
+
+private:
+ QString *m_string;
+ QTextCursor *m_cursor;
+
+ QList<EditOp> m_operationList;
+ bool m_error;
+};
+
+} // namespace Utils
+
+#endif // CHANGESET_H
diff --git a/src/plugins/qmldesigner/core/filemanager/filemanager.pri b/src/plugins/qmldesigner/core/filemanager/filemanager.pri
new file mode 100644
index 0000000000..fb51eda8d5
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/filemanager.pri
@@ -0,0 +1,41 @@
+include($$PWD/parser/parser.pri)
+SOURCES += $$PWD/qmldocument.cpp \
+ $$PWD/idcollector.cpp \
+ $$PWD/qmlsymbol.cpp \
+ $$PWD/qmlrewriter.cpp \
+ $$PWD/qmlrefactoring.cpp \
+ $$PWD/changeobjecttypevisitor.cpp \
+ $$PWD/changepropertyvisitor.cpp \
+ $$PWD/removeuiobjectmembervisitor.cpp \
+ $$PWD/removepropertyvisitor.cpp \
+ $$PWD/addpropertyvisitor.cpp \
+ $$PWD/moveobjectvisitor.cpp \
+ $$PWD/addobjectvisitor.cpp \
+ $$PWD/addarraymembervisitor.cpp \
+ $$PWD/astobjecttextextractor.cpp \
+ $$PWD/indenter.cpp \
+ $$PWD/changeset.cpp \
+ $$PWD/objectlengthcalculator.cpp \
+ $$PWD/firstdefinitionfinder.cpp \
+ $$PWD/moveobjectbeforeobjectvisitor.cpp
+HEADERS += $$PWD/qmldocument.h \
+ $$PWD/idcollector.h \
+ $$PWD/qmleditor_global.h \
+ $$PWD/qmlsymbol.h \
+ $$PWD/qmlrewriter.h \
+ $$PWD/qmlrefactoring.h \
+ $$PWD/changeobjecttypevisitor.h \
+ $$PWD/changepropertyvisitor.h \
+ $$PWD/removeuiobjectmembervisitor.h \
+ $$PWD/removepropertyvisitor.h \
+ $$PWD/addpropertyvisitor.h \
+ $$PWD/moveobjectvisitor.h \
+ $$PWD/addobjectvisitor.h \
+ $$PWD/addarraymembervisitor.h \
+ $$PWD/astobjecttextextractor.h \
+ $$PWD/indenter.h \
+ $$PWD/changeset.h \
+ $$PWD/utils_global.h \
+ $$PWD/objectlengthcalculator.h \
+ $$PWD/firstdefinitionfinder.h \
+ $$PWD/moveobjectbeforeobjectvisitor.h
diff --git a/src/plugins/qmldesigner/core/filemanager/firstdefinitionfinder.cpp b/src/plugins/qmldesigner/core/filemanager/firstdefinitionfinder.cpp
new file mode 100644
index 0000000000..64905c35aa
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/firstdefinitionfinder.cpp
@@ -0,0 +1,98 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "firstdefinitionfinder.h"
+
+#include <qmljsast_p.h>
+
+using namespace QmlDesigner;
+using namespace QmlEditor;
+using namespace QmlJS::AST;
+
+FirstDefinitionFinder::FirstDefinitionFinder(const QString &text):
+ m_doc(QmlDocument::create("<internal>"))
+{
+ m_doc->setSource(text);
+ bool ok = m_doc->parse();
+
+ Q_ASSERT(ok);
+}
+
+/*!
+ \brief Finds the first object definition inside the object given by offset
+
+
+ \arg the offset of the object to search in
+ \return the offset of the first object definition
+ */
+quint32 FirstDefinitionFinder::operator()(quint32 offset)
+{
+ m_offset = offset;
+ m_firstObjectDefinition = 0;
+
+ Node::accept(m_doc->program(), this);
+
+ return m_firstObjectDefinition->firstSourceLocation().offset;
+}
+
+void FirstDefinitionFinder::extractFirstObjectDefinition(UiObjectInitializer* ast)
+{
+ if (!ast)
+ return;
+
+ for (UiObjectMemberList *iter = ast->members; iter; iter = iter->next) {
+ if (UiObjectDefinition *def = cast<UiObjectDefinition*>(iter->member)) {
+ m_firstObjectDefinition = def;
+ }
+ }
+}
+
+bool FirstDefinitionFinder::visit(QmlJS::AST::UiObjectBinding *ast)
+{
+ if (ast->qualifiedTypeNameId && ast->qualifiedTypeNameId->identifierToken.isValid()) {
+ const quint32 start = ast->qualifiedTypeNameId->identifierToken.offset;
+
+ if (start == m_offset) {
+ extractFirstObjectDefinition(ast->initializer);
+ return false;
+ }
+ }
+ return true;
+}
+
+bool FirstDefinitionFinder::visit(QmlJS::AST::UiObjectDefinition *ast)
+{
+ const quint32 start = ast->firstSourceLocation().offset;
+
+ if (start == m_offset) {
+ extractFirstObjectDefinition(ast->initializer);
+ return false;
+ }
+ return true;
+}
diff --git a/src/plugins/qmldesigner/core/filemanager/firstdefinitionfinder.h b/src/plugins/qmldesigner/core/filemanager/firstdefinitionfinder.h
new file mode 100644
index 0000000000..170b7a2381
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/firstdefinitionfinder.h
@@ -0,0 +1,63 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef FIRSTDEFINITIONFINDER_H
+#define FIRSTDEFINITIONFINDER_H
+
+#include "qmldocument.h"
+
+#include <qmljsastvisitor_p.h>
+
+namespace QmlDesigner {
+
+class FirstDefinitionFinder: protected QmlJS::AST::Visitor
+{
+public:
+ FirstDefinitionFinder(const QString &text);
+
+ quint32 operator()(quint32 offset);
+
+protected:
+ using QmlJS::AST::Visitor::visit;
+
+ virtual bool visit(QmlJS::AST::UiObjectBinding *ast);
+ virtual bool visit(QmlJS::AST::UiObjectDefinition *ast);
+
+ void extractFirstObjectDefinition(QmlJS::AST::UiObjectInitializer* ast);
+
+private:
+ QmlEditor::QmlDocument::Ptr m_doc;
+ quint32 m_offset;
+ QmlJS::AST::UiObjectDefinition *m_firstObjectDefinition;
+
+};
+
+} // namespace QmlDesigner
+
+#endif // FIRSTDEFINITIONFINDER_H
diff --git a/src/plugins/qmldesigner/core/filemanager/idcollector.cpp b/src/plugins/qmldesigner/core/filemanager/idcollector.cpp
new file mode 100644
index 0000000000..54284a9fad
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/idcollector.cpp
@@ -0,0 +1,93 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "idcollector.h"
+#include "qmljsast_p.h"
+#include "qmljsengine_p.h"
+
+using namespace QmlJS;
+using namespace QmlJS::AST;
+using namespace QmlEditor;
+using namespace QmlEditor::Internal;
+
+QMap<QString, QmlIdSymbol*> IdCollector::operator()(const QString &fileName, QmlJS::AST::UiProgram *ast)
+{
+ _fileName = fileName;
+ _ids.clear();
+
+ Node::accept(ast, this);
+
+ return _ids;
+}
+
+bool IdCollector::visit(QmlJS::AST::UiObjectBinding *ast)
+{
+ _scopes.push(ast);
+ return true;
+}
+
+bool IdCollector::visit(QmlJS::AST::UiObjectDefinition *ast)
+{
+ _scopes.push(ast);
+ return true;
+}
+
+void IdCollector::endVisit(QmlJS::AST::UiObjectBinding *)
+{
+ _scopes.pop();
+}
+
+void IdCollector::endVisit(QmlJS::AST::UiObjectDefinition *)
+{
+ _scopes.pop();
+}
+
+bool IdCollector::visit(QmlJS::AST::UiScriptBinding *ast)
+{
+ if (!(ast->qualifiedId->next) && ast->qualifiedId->name->asString() == "id")
+ if (ExpressionStatement *e = cast<ExpressionStatement*>(ast->statement))
+ if (IdentifierExpression *i = cast<IdentifierExpression*>(e->expression))
+ addId(i->name->asString(), ast);
+
+ return false;
+}
+
+void IdCollector::addId(const QString &id, QmlJS::AST::UiScriptBinding *ast)
+{
+ if (!_ids.contains(id)) {
+ Node *parent = _scopes.top();
+
+ if (UiObjectBinding *binding = cast<UiObjectBinding*>(parent))
+ _ids[id] = new QmlIdSymbol(_fileName, ast, QmlSymbolFromFile(_fileName, binding));
+ else if (UiObjectDefinition *definition = cast<UiObjectDefinition*>(parent))
+ _ids[id] = new QmlIdSymbol(_fileName, ast, QmlSymbolFromFile(_fileName, definition));
+ else
+ Q_ASSERT(!"Unknown parent for id");
+ }
+}
diff --git a/src/plugins/qmldesigner/core/filemanager/idcollector.h b/src/plugins/qmldesigner/core/filemanager/idcollector.h
new file mode 100644
index 0000000000..b9f3211e9e
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/idcollector.h
@@ -0,0 +1,69 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef IDCOLLECTOR_H
+#define IDCOLLECTOR_H
+
+#include <QMap>
+#include <QPair>
+#include <QStack>
+#include <QString>
+
+#include "qmljsastvisitor_p.h"
+#include "qmlsymbol.h"
+
+namespace QmlEditor {
+namespace Internal {
+
+class IdCollector: protected QmlJS::AST::Visitor
+{
+public:
+ QMap<QString, QmlIdSymbol*> operator()(const QString &fileName, QmlJS::AST::UiProgram *ast);
+
+protected:
+ virtual bool visit(QmlJS::AST::UiObjectBinding *ast);
+ virtual bool visit(QmlJS::AST::UiObjectDefinition *ast);
+ virtual bool visit(QmlJS::AST::UiScriptBinding *ast);
+
+ virtual void endVisit(QmlJS::AST::UiObjectBinding *);
+ virtual void endVisit(QmlJS::AST::UiObjectDefinition *);
+
+private:
+ void addId(const QString &id, QmlJS::AST::UiScriptBinding *ast);
+
+private:
+ QString _fileName;
+ QMap<QString, QmlIdSymbol*> _ids;
+ QStack<QmlJS::AST::Node *> _scopes;
+};
+
+} // namespace Internal
+} // namespace QmlEditor
+
+#endif // IDCOLLECTOR_H
diff --git a/src/plugins/qmldesigner/core/filemanager/indenter.cpp b/src/plugins/qmldesigner/core/filemanager/indenter.cpp
new file mode 100644
index 0000000000..55e709d7f2
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/indenter.cpp
@@ -0,0 +1,90 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "indenter.h"
+
+using namespace QmlEditor;
+
+Indenter::Indenter()
+{
+}
+
+//static int blockStartState(const QTextBlock &block)
+//{
+// int state = block.userState();
+//
+// if (state == -1)
+// return 0;
+// else
+// return state & 0xff;
+//}
+//
+//void ScriptEditor::indentBlock(QTextDocument *, QTextBlock block, QChar typedChar)
+//{
+// TextEditor::TabSettings ts = tabSettings();
+//
+// QTextCursor tc(block);
+//
+// const QString blockText = block.text();
+// int startState = blockStartState(block.previous());
+//
+// QScriptIncrementalScanner scanner;
+// const QList<QScriptIncrementalScanner::Token> tokens = scanner(blockText, startState);
+//
+// if (! tokens.isEmpty()) {
+// const QScriptIncrementalScanner::Token tk = tokens.first();
+//
+// if (tk.is(QScriptIncrementalScanner::Token::RightBrace)
+// || tk.is(QScriptIncrementalScanner::Token::RightBracket)) {
+// if (TextEditor::TextBlockUserData::findPreviousBlockOpenParenthesis(&tc)) {
+// const QString text = tc.block().text();
+// int indent = ts.columnAt(text, ts.firstNonSpace(text));
+// ts.indentLine(block, indent);
+// return;
+// }
+// }
+// }
+//
+// int initialIndent = 0;
+// for (QTextBlock it = block.previous(); it.isValid(); it = it.previous()) {
+// const QString text = it.text();
+//
+// if (! text.isEmpty()) {
+// initialIndent = ts.columnAt(text, ts.firstNonSpace(text));
+// break;
+// }
+// }
+//
+// const int braceDepth = blockBraceDepth(block.previous());
+// const int previousBraceDepth = blockBraceDepth(block.previous().previous());
+// const int delta = qMax(0, braceDepth - previousBraceDepth);
+// int indent = initialIndent + (delta * ts.m_indentSize);
+// ts.indentLine(block, indent);
+//}
+//
diff --git a/src/plugins/qmldesigner/core/filemanager/indenter.h b/src/plugins/qmldesigner/core/filemanager/indenter.h
new file mode 100644
index 0000000000..b862003b2c
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/indenter.h
@@ -0,0 +1,43 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef INDENTER_H
+#define INDENTER_H
+
+namespace QmlEditor {
+
+class Indenter
+{
+public:
+ Indenter();
+};
+
+} // namespace QmlEditor
+
+#endif // INDENTER_H
diff --git a/src/plugins/qmldesigner/core/filemanager/moveobjectbeforeobjectvisitor.cpp b/src/plugins/qmldesigner/core/filemanager/moveobjectbeforeobjectvisitor.cpp
new file mode 100644
index 0000000000..62a8ed5429
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/moveobjectbeforeobjectvisitor.cpp
@@ -0,0 +1,158 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <QtCore/QDebug>
+
+#include <qmljsast_p.h>
+#include <qmljsengine_p.h>
+
+#include "moveobjectbeforeobjectvisitor.h"
+#include "textmodifier.h"
+
+using namespace QmlJS;
+using namespace QmlJS::AST;
+using namespace QmlEditor::Internal;
+using namespace QmlDesigner;
+
+MoveObjectBeforeObjectVisitor::MoveObjectBeforeObjectVisitor(TextModifier &modifier,
+ quint32 movingObjectLocation):
+ QMLRewriter(modifier),
+ movingObjectLocation(movingObjectLocation),
+ toEnd(true),
+ beforeObjectLocation(0)
+{}
+
+MoveObjectBeforeObjectVisitor::MoveObjectBeforeObjectVisitor(TextModifier &modifier,
+ quint32 movingObjectLocation,
+ quint32 beforeObjectLocation):
+ QMLRewriter(modifier),
+ movingObjectLocation(movingObjectLocation),
+ toEnd(false),
+ beforeObjectLocation(beforeObjectLocation)
+{}
+
+bool MoveObjectBeforeObjectVisitor::operator ()(QmlJS::AST::UiProgram *ast)
+{
+ movingObject = 0;
+ beforeObject = 0;
+ movingObjectParents.clear();
+
+ QMLRewriter::operator ()(ast);
+
+ if (foundEverything()) {
+ doMove();
+ }
+
+ return didRewriting();
+}
+
+bool MoveObjectBeforeObjectVisitor::preVisit(Node *ast)
+{ if (ast) parents.push(ast); return true; }
+
+void MoveObjectBeforeObjectVisitor::postVisit(Node *ast)
+{ if (ast) parents.pop(); }
+
+bool MoveObjectBeforeObjectVisitor::visit(UiObjectDefinition *ast)
+{
+ if (foundEverything())
+ return false;
+
+ const quint32 start = ast->firstSourceLocation().offset;
+ if (start == movingObjectLocation) {
+ movingObject = ast;
+ movingObjectParents = parents;
+ movingObjectParents.pop();
+ } else if (!toEnd && start == beforeObjectLocation) {
+ beforeObject = ast;
+ }
+
+ if (movingObjectLocation < start)
+ return false;
+ else if (!toEnd && beforeObjectLocation < start)
+ return false;
+ else if (foundEverything())
+ return false;
+ else
+ return true;
+}
+
+void MoveObjectBeforeObjectVisitor::doMove()
+{
+ Q_ASSERT(movingObject);
+ Q_ASSERT(!movingObjectParents.isEmpty());
+
+ TextModifier::MoveInfo moveInfo;
+
+ int start = movingObject->firstSourceLocation().offset;
+ int end = movingObject->lastSourceLocation().end();
+
+ moveInfo.objectStart = start;
+ moveInfo.objectEnd = end;
+
+ includeSurroundingWhitespace(start, end);
+ moveInfo.leadingCharsToRemove = moveInfo.objectStart - start;
+ moveInfo.trailingCharsToRemove = end - moveInfo.objectEnd;
+
+ if (beforeObject) {
+ moveInfo.destination = beforeObject->firstSourceLocation().offset;
+ int dummy = -1;
+ includeSurroundingWhitespace(moveInfo.destination, dummy);
+
+ moveInfo.prefixToInsert = QString(moveInfo.leadingCharsToRemove, QLatin1Char(' '));
+ moveInfo.suffixToInsert = QLatin1String("\n\n");
+ } else {
+ const SourceLocation insertionPoint = lastParentLocation();
+ Q_ASSERT(insertionPoint.isValid());
+ moveInfo.destination = insertionPoint.offset;
+ int dummy = -1;
+ includeSurroundingWhitespace(moveInfo.destination, dummy);
+
+ moveInfo.prefixToInsert = QString(moveInfo.leadingCharsToRemove, QLatin1Char(' '));
+ moveInfo.suffixToInsert = QLatin1String("\n");
+ }
+
+ move(moveInfo);
+ setDidRewriting(true);
+}
+
+SourceLocation MoveObjectBeforeObjectVisitor::lastParentLocation() const
+{
+ dump(movingObjectParents);
+
+ Node *parent;
+ if (movingObjectParents.size() > 1)
+ parent = movingObjectParents.at(movingObjectParents.size() - 2);
+ else
+ parent = 0;
+
+ if (UiObjectInitializer *initializer = cast<UiObjectInitializer*>(parent))
+ return initializer->rbraceToken;
+ else
+ return SourceLocation();
+}
diff --git a/src/plugins/qmldesigner/core/filemanager/moveobjectbeforeobjectvisitor.h b/src/plugins/qmldesigner/core/filemanager/moveobjectbeforeobjectvisitor.h
new file mode 100644
index 0000000000..4b405dd306
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/moveobjectbeforeobjectvisitor.h
@@ -0,0 +1,79 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef MOVEOBJECTBEFOREOBJECTVISITOR_H
+#define MOVEOBJECTBEFOREOBJECTVISITOR_H
+
+#include "qmlrewriter.h"
+
+#include <QtCore/QStack>
+
+namespace QmlEditor {
+namespace Internal {
+
+class MoveObjectBeforeObjectVisitor: public QMLRewriter
+{
+public:
+ MoveObjectBeforeObjectVisitor(QmlDesigner::TextModifier &modifier,
+ quint32 movingObjectLocation);
+ MoveObjectBeforeObjectVisitor(QmlDesigner::TextModifier &modifier,
+ quint32 movingObjectLocation,
+ quint32 beforeObjectLocation);
+
+ bool operator ()(QmlJS::AST::UiProgram *ast);
+
+protected:
+ virtual bool preVisit(QmlJS::AST::Node *ast);
+ virtual void postVisit(QmlJS::AST::Node *ast);
+
+ virtual bool visit(QmlJS::AST::UiObjectDefinition *ast);
+
+private:
+ bool foundEverything() const
+ { return movingObject != 0 && !movingObjectParents.isEmpty() && (toEnd || beforeObject != 0); }
+
+ void doMove();
+
+ QmlJS::AST::SourceLocation lastParentLocation() const;
+
+private:
+ QStack<QmlJS::AST::Node *> parents;
+ quint32 movingObjectLocation;
+ bool toEnd;
+ quint32 beforeObjectLocation;
+
+ QmlJS::AST::UiObjectDefinition *movingObject;
+ QmlJS::AST::UiObjectDefinition *beforeObject;
+ ASTPath movingObjectParents;
+};
+
+} // namespace Internal
+} // namespace QmlEditor
+
+#endif // MOVEOBJECTBEFOREOBJECTVISITOR_H
diff --git a/src/plugins/qmldesigner/core/filemanager/moveobjectvisitor.cpp b/src/plugins/qmldesigner/core/filemanager/moveobjectvisitor.cpp
new file mode 100644
index 0000000000..ce95b03bad
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/moveobjectvisitor.cpp
@@ -0,0 +1,293 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <QtCore/QDebug>
+
+#include <qmljsast_p.h>
+#include <qmljsengine_p.h>
+
+#include "moveobjectvisitor.h"
+#include "textmodifier.h"
+
+using namespace QmlJS;
+using namespace QmlJS::AST;
+using namespace QmlEditor::Internal;
+using namespace QmlDesigner;
+
+class Inserter: public QMLRewriter
+{
+public:
+ Inserter(QmlDesigner::TextModifier &modifier,
+ quint32 targetParentObjectLocation,
+ const QString &targetPropertyName,
+ bool targetIsArrayBinding,
+ TextModifier::MoveInfo moveInfo,
+ const QStringList &propertyOrder):
+ QMLRewriter(modifier),
+ targetParentObjectLocation(targetParentObjectLocation),
+ targetPropertyName(targetPropertyName),
+ targetIsArrayBinding(targetIsArrayBinding),
+ moveInfo(moveInfo),
+ propertyOrder(propertyOrder)
+ {}
+
+protected:
+ virtual bool visit(UiObjectBinding *ast)
+ {
+ if (didRewriting())
+ return false;
+
+ if (ast->qualifiedTypeNameId->identifierToken.offset == targetParentObjectLocation) {
+ insertInto(ast->initializer);
+ }
+
+ return !didRewriting();
+ }
+
+ virtual bool visit(UiObjectDefinition *ast)
+ {
+ if (didRewriting())
+ return false;
+
+ if (ast->firstSourceLocation().offset == targetParentObjectLocation) {
+ insertInto(ast->initializer);
+ }
+
+ return !didRewriting();
+ }
+
+private:
+ void insertInto(UiObjectInitializer *ast)
+ {
+ if (targetPropertyName.isEmpty()) {
+ // insert as UiObjectDefinition:
+ UiObjectMemberList *insertAfter = searchMemberToInsertAfter(ast->members, QString::null, propertyOrder);
+
+ if (insertAfter && insertAfter->member) {
+ moveInfo.destination = insertAfter->member->lastSourceLocation().end();
+ moveInfo.prefixToInsert = QLatin1String("\n\n");
+ } else {
+ moveInfo.destination = ast->lbraceToken.end();
+ moveInfo.prefixToInsert = QLatin1String("\n");
+ }
+
+ move(moveInfo);
+
+ setDidRewriting(true);
+ return;
+ }
+
+ // see if we need to insert into an UiArrayBinding:
+ for (UiObjectMemberList *iter = ast->members; iter; iter = iter->next) {
+ UiObjectMember *member = iter->member;
+
+ if (UiArrayBinding *arrayBinding = cast<UiArrayBinding*>(member)) {
+ if (flatten(arrayBinding->qualifiedId) == targetPropertyName) {
+ appendToArray(arrayBinding);
+
+ setDidRewriting(true);
+ return;
+ }
+ }
+ }
+
+ { // insert (create) a UiObjectBinding:
+ UiObjectMemberList *insertAfter = searchMemberToInsertAfter(ast->members, targetPropertyName, propertyOrder);
+ moveInfo.prefixToInsert = QLatin1String("\n") + targetPropertyName + (targetIsArrayBinding ? QLatin1String(": [") : QLatin1String(": "));
+ moveInfo.suffixToInsert = targetIsArrayBinding ? QLatin1String("\n]") : QLatin1String("");
+
+ if (insertAfter && insertAfter->member) {
+ moveInfo.destination = insertAfter->member->lastSourceLocation().end();
+ } else {
+ moveInfo.destination = ast->lbraceToken.end();
+ }
+
+ setDidRewriting(true);
+ }
+ }
+
+ void appendToArray(UiArrayBinding *ast)
+ {
+ UiObjectMember *lastMember = 0;
+
+ for (UiArrayMemberList *iter = ast->members; iter; iter = iter->next) {
+ if (iter->member)
+ lastMember = iter->member;
+ }
+
+ if (!lastMember)
+ Q_ASSERT(!"Invalid QML: empty array found.");
+
+ moveInfo.destination = lastMember->lastSourceLocation().end();
+ moveInfo.suffixToInsert = QLatin1String(",\n");
+ move(moveInfo);
+ }
+
+private:
+ quint32 targetParentObjectLocation;
+ QString targetPropertyName;
+ bool targetIsArrayBinding;
+ TextModifier::MoveInfo moveInfo;
+ QStringList propertyOrder;
+};
+
+MoveObjectVisitor::MoveObjectVisitor(QmlDesigner::TextModifier &modifier,
+ quint32 objectLocation,
+ const QString &targetPropertyName,
+ bool targetIsArrayBinding,
+ quint32 targetParentObjectLocation,
+ const QStringList &propertyOrder):
+ QMLRewriter(modifier),
+ objectLocation(objectLocation),
+ targetPropertyName(targetPropertyName),
+ targetIsArrayBinding(targetIsArrayBinding),
+ targetParentObjectLocation(targetParentObjectLocation),
+ propertyOrder(propertyOrder)
+{
+}
+
+bool MoveObjectVisitor::operator()(UiProgram *ast)
+{
+ program = ast;
+
+ return QMLRewriter::operator()(ast);
+}
+
+bool MoveObjectVisitor::visit(UiArrayBinding *ast)
+{
+ if (didRewriting())
+ return false;
+
+ UiArrayMemberList *currentMember = 0;
+
+ for (UiArrayMemberList *it = ast->members; it; it = it->next) {
+ if (it->member->firstSourceLocation().offset == objectLocation) {
+ currentMember = it;
+ break;
+ }
+ }
+
+ if (currentMember) {
+ TextModifier::MoveInfo moveInfo;
+ moveInfo.objectEnd = currentMember->member->lastSourceLocation().end();
+
+ if (currentMember == ast->members && !currentMember->next) {
+ // array with 1 element, which is moved away, so also remove the array binding
+ int start = ast->firstSourceLocation().offset;
+ int end = ast->lastSourceLocation().end();
+ includeSurroundingWhitespace(start, end);
+ moveInfo.leadingCharsToRemove = objectLocation - start;
+ moveInfo.trailingCharsToRemove = end - moveInfo.objectEnd;
+ } else if (currentMember->next) {
+ // we're not the last element, so remove the trailing comma too
+ Q_ASSERT(currentMember->next->commaToken.isValid());
+
+ int start = objectLocation;
+ int end = currentMember->next->commaToken.end();
+ includeSurroundingWhitespace(start, end);
+ moveInfo.leadingCharsToRemove = objectLocation - start;
+ moveInfo.trailingCharsToRemove = end - moveInfo.objectEnd;
+ } else {
+ // we're the last member, but not the only member, so remove the preceeding comma too
+ Q_ASSERT(currentMember->commaToken.isValid());
+
+ int start = currentMember->commaToken.offset;
+ int end = moveInfo.objectEnd;
+ includeSurroundingWhitespace(start, end);
+ moveInfo.leadingCharsToRemove = objectLocation - start;
+ moveInfo.trailingCharsToRemove = end - moveInfo.objectEnd;
+ }
+
+ doMove(moveInfo);
+ }
+
+ return !didRewriting();
+}
+
+bool MoveObjectVisitor::visit(UiObjectBinding *ast)
+{
+ if (didRewriting())
+ return false;
+
+ if (ast->qualifiedTypeNameId->identifierToken.offset == objectLocation) {
+ TextModifier::MoveInfo moveInfo;
+ moveInfo.objectEnd = ast->lastSourceLocation().end();
+
+ // remove leading indentation and property name:
+ int start = ast->firstSourceLocation().offset;
+ int end = moveInfo.objectEnd;
+ includeSurroundingWhitespace(start, end);
+ includeLeadingEmptyLine(start);
+ moveInfo.leadingCharsToRemove = objectLocation - start;
+
+ // remove trailing indentation
+ moveInfo.trailingCharsToRemove = end - moveInfo.objectEnd;
+
+ doMove(moveInfo);
+ }
+
+ return !didRewriting();
+}
+
+bool MoveObjectVisitor::visit(UiObjectDefinition *ast)
+{
+ if (didRewriting())
+ return false;
+
+ if (ast->qualifiedTypeNameId->identifierToken.offset == objectLocation) {
+ TextModifier::MoveInfo moveInfo;
+ moveInfo.objectStart = objectLocation;
+ moveInfo.objectEnd = ast->lastSourceLocation().end();
+
+ // remove leading indentation:
+ int start = objectLocation;
+ int end = moveInfo.objectEnd;
+ includeSurroundingWhitespace(start, end);
+ includeLeadingEmptyLine(start);
+ moveInfo.leadingCharsToRemove = objectLocation - start;
+ moveInfo.trailingCharsToRemove = end - moveInfo.objectEnd;
+
+ doMove(moveInfo);
+ }
+
+ return !didRewriting();
+}
+
+void MoveObjectVisitor::doMove(TextModifier::MoveInfo moveInfo)
+{
+ if (moveInfo.objectEnd > moveInfo.objectStart) {
+ Inserter findTargetAndInsert(*textModifier(),
+ targetParentObjectLocation,
+ targetPropertyName,
+ targetIsArrayBinding,
+ moveInfo,
+ propertyOrder);
+ setDidRewriting(findTargetAndInsert(program));
+ }
+}
diff --git a/src/plugins/qmldesigner/core/filemanager/moveobjectvisitor.h b/src/plugins/qmldesigner/core/filemanager/moveobjectvisitor.h
new file mode 100644
index 0000000000..5ec981cdb8
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/moveobjectvisitor.h
@@ -0,0 +1,72 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef MOVEOBJECTVISITOR_H
+#define MOVEOBJECTVISITOR_H
+
+#include "qmlrewriter.h"
+
+namespace QmlEditor {
+namespace Internal {
+
+class MoveObjectVisitor: public QMLRewriter
+{
+public:
+ MoveObjectVisitor(QmlDesigner::TextModifier &modifier,
+ quint32 objectLocation,
+ const QString &targetPropertyName,
+ bool targetIsArrayBinding,
+ quint32 targetParentObjectLocation,
+ const QStringList &propertyOrder);
+
+ bool operator ()(QmlJS::AST::UiProgram *ast);
+
+protected:
+ virtual bool visit(QmlJS::AST::UiArrayBinding *ast);
+ virtual bool visit(QmlJS::AST::UiObjectBinding *ast);
+ virtual bool visit(QmlJS::AST::UiObjectDefinition *ast);
+
+private:
+ void doMove(QmlDesigner::TextModifier::MoveInfo moveInfo);
+
+private:
+ QList<QmlJS::AST::Node *> parents;
+ quint32 objectLocation;
+ QString targetPropertyName;
+ bool targetIsArrayBinding;
+ quint32 targetParentObjectLocation;
+ QStringList propertyOrder;
+
+ QmlJS::AST::UiProgram *program;
+};
+
+} // namespace Internal
+} // namespace QmlEditor
+
+#endif // MOVEOBJECTVISITOR_H
diff --git a/src/plugins/qmldesigner/core/filemanager/objectlengthcalculator.cpp b/src/plugins/qmldesigner/core/filemanager/objectlengthcalculator.cpp
new file mode 100644
index 0000000000..cc9f229e14
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/objectlengthcalculator.cpp
@@ -0,0 +1,91 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "objectlengthcalculator.h"
+
+#include <qmljsast_p.h>
+
+using namespace QmlDesigner;
+using namespace QmlEditor;
+using namespace QmlJS::AST;
+
+ObjectLengthCalculator::ObjectLengthCalculator(const QString &text):
+ m_doc(QmlDocument::create("<internal>"))
+{
+ m_doc->setSource(text);
+ bool ok = m_doc->parse();
+
+ Q_ASSERT(ok);
+}
+
+quint32 ObjectLengthCalculator::operator()(quint32 offset)
+{
+ m_offset = offset;
+ m_length = 0;
+
+ Node::accept(m_doc->program(), this);
+
+ return m_length;
+}
+
+bool ObjectLengthCalculator::visit(QmlJS::AST::UiObjectBinding *ast)
+{
+ if (m_length > 0)
+ return false;
+
+ if (ast->qualifiedTypeNameId && ast->qualifiedTypeNameId->identifierToken.isValid()) {
+ const quint32 start = ast->qualifiedTypeNameId->identifierToken.offset;
+ const quint32 end = ast->lastSourceLocation().end();
+
+ if (start == m_offset) {
+ m_length = end - start;
+ return false;
+ }
+
+ return m_offset < end;
+ } else {
+ return true;
+ }
+}
+
+bool ObjectLengthCalculator::visit(QmlJS::AST::UiObjectDefinition *ast)
+{
+ if (m_length > 0)
+ return false;
+
+ const quint32 start = ast->firstSourceLocation().offset;
+ const quint32 end = ast->lastSourceLocation().end();
+
+ if (start == m_offset) {
+ m_length = end - start;
+ return false;
+ }
+
+ return m_offset < end;
+}
diff --git a/src/plugins/qmldesigner/core/filemanager/objectlengthcalculator.h b/src/plugins/qmldesigner/core/filemanager/objectlengthcalculator.h
new file mode 100644
index 0000000000..a49352c8b7
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/objectlengthcalculator.h
@@ -0,0 +1,60 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef OBJECTLENGTHCALCULATOR_H
+#define OBJECTLENGTHCALCULATOR_H
+
+#include "qmldocument.h"
+
+#include <qmljsastvisitor_p.h>
+
+namespace QmlDesigner {
+
+class ObjectLengthCalculator: protected QmlJS::AST::Visitor
+{
+public:
+ ObjectLengthCalculator(const QString &text);
+
+ quint32 operator()(quint32 offset);
+
+protected:
+ using QmlJS::AST::Visitor::visit;
+
+ virtual bool visit(QmlJS::AST::UiObjectBinding *ast);
+ virtual bool visit(QmlJS::AST::UiObjectDefinition *ast);
+
+private:
+ QmlEditor::QmlDocument::Ptr m_doc;
+ quint32 m_offset;
+ quint32 m_length;
+};
+
+} // namespace QmlDesigner
+
+#endif // OBJECTLENGTHCALCULATOR_H
diff --git a/src/plugins/qmldesigner/core/filemanager/parser/parser.pri b/src/plugins/qmldesigner/core/filemanager/parser/parser.pri
new file mode 100644
index 0000000000..986b14673c
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/parser/parser.pri
@@ -0,0 +1,22 @@
+
+INCLUDEPATH += $$PWD
+DEPENDPATH += $$PWD
+
+HEADERS += $$PWD/qmljsast_p.h \
+ $$PWD/qmljsastfwd_p.h \
+ $$PWD/qmljsastvisitor_p.h \
+ $$PWD/qmljsengine_p.h \
+ $$PWD/qmljsgrammar_p.h \
+ $$PWD/qmljslexer_p.h \
+ $$PWD/qmljsmemorypool_p.h \
+ $$PWD/qmljsnodepool_p.h \
+ $$PWD/qmljsparser_p.h \
+ $$PWD/qmljsglobal_p.h
+
+SOURCES += $$PWD/qmljsast.cpp \
+ $$PWD/qmljsastvisitor.cpp \
+ $$PWD/qmljsengine_p.cpp \
+ $$PWD/qmljsgrammar.cpp \
+ $$PWD/qmljslexer.cpp \
+ $$PWD/qmljsparser.cpp
+
diff --git a/src/plugins/qmldesigner/core/filemanager/parser/qmljs.g b/src/plugins/qmldesigner/core/filemanager/parser/qmljs.g
new file mode 100644
index 0000000000..8531ed5107
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/parser/qmljs.g
@@ -0,0 +1,3029 @@
+----------------------------------------------------------------------------
+--
+-- This file is part of Qt Creator
+--
+-- Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+--
+-- Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+--
+----------------------------------------------------------------------------
+
+%parser QmlJSGrammar
+%decl qmljsparser_p.h
+%impl qmljsparser.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" T_READONLY "readonly"
+%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"
+%token T_COMMENT "comment"
+
+--- context keywords.
+%token T_PUBLIC "public"
+%token T_IMPORT "import"
+%token T_AS "as"
+
+--- feed tokens
+%token T_FEED_UI_PROGRAM
+%token T_FEED_UI_OBJECT_MEMBER
+%token T_FEED_JS_STATEMENT
+%token T_FEED_JS_EXPRESSION
+
+%nonassoc SHIFT_THERE
+%nonassoc T_IDENTIFIER T_COLON T_SIGNAL T_PROPERTY T_READONLY
+%nonassoc REDUCE_HERE
+
+%start TopLevel
+
+/.
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <QtCore/QtDebug>
+
+#include <string.h>
+
+#include "qmljsengine_p.h"
+#include "qmljslexer_p.h"
+#include "qmljsast_p.h"
+#include "qmljsnodepool_p.h"
+
+./
+
+/:
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+//
+// 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 qmljs.g.
+// Changes will be lost.
+//
+
+#ifndef QMLJSPARSER_P_H
+#define QMLJSPARSER_P_H
+
+#include "qmljsglobal_p.h"
+#include "qmljsgrammar_p.h"
+#include "qmljsast_p.h"
+#include "qmljsengine_p.h"
+
+#include <QtCore/QList>
+#include <QtCore/QString>
+
+QT_QML_BEGIN_NAMESPACE
+
+namespace QmlJS {
+
+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::UiParameterList *UiParameterList;
+ 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::UiArrayMemberList *UiArrayMemberList;
+ AST::UiQualifiedId *UiQualifiedId;
+ AST::UiSignature *UiSignature;
+ AST::UiFormalList *UiFormalList;
+ AST::UiFormal *UiFormal;
+ };
+
+public:
+ Parser(Engine *engine);
+ ~Parser();
+
+ // parse a UI program
+ bool parse() { return parse(T_FEED_UI_PROGRAM); }
+ bool parseStatement() { return parse(T_FEED_JS_STATEMENT); }
+ bool parseExpression() { return parse(T_FEED_JS_EXPRESSION); }
+ bool parseUiObjectMember() { return parse(T_FEED_UI_OBJECT_MEMBER); }
+
+ AST::UiProgram *ast() const
+ { return AST::cast<AST::UiProgram *>(program); }
+
+ AST::Statement *statement() const
+ {
+ if (! program)
+ return 0;
+
+ return program->statementCast();
+ }
+
+ AST::ExpressionNode *expression() const
+ {
+ if (! program)
+ return 0;
+
+ return program->expressionCast();
+ }
+
+ AST::UiObjectMember *uiObjectMember() const
+ {
+ if (! program)
+ return 0;
+
+ return program->uiObjectMemberCast();
+ }
+
+ 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:
+ bool parse(int startToken);
+
+ 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::Node *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 QmlJS
+
+
+:/
+
+
+/.
+
+#include "qmljsparser_p.h"
+#include <QVarLengthArray>
+
+//
+// This file is automatically generated from qmljs.g.
+// Changes will be lost.
+//
+
+using namespace QmlJS;
+
+QT_QML_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(int startToken)
+{
+ Lexer *lexer = driver->lexer();
+ bool hadErrors = false;
+ int yytoken = -1;
+ int action = 0;
+
+ token_buffer[0].token = startToken;
+ first_token = &token_buffer[0];
+ last_token = &token_buffer[1];
+
+ 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
+--------------------------------------------------------------------------------------------------------
+
+TopLevel: T_FEED_UI_PROGRAM UiProgram ;
+/.
+case $rule_number: {
+ sym(1).Node = sym(2).Node;
+ program = sym(1).Node;
+} break;
+./
+
+TopLevel: T_FEED_JS_STATEMENT Statement ;
+/.
+case $rule_number: {
+ sym(1).Node = sym(2).Node;
+ program = sym(1).Node;
+} break;
+./
+
+TopLevel: T_FEED_JS_EXPRESSION Expression ;
+/.
+case $rule_number: {
+ sym(1).Node = sym(2).Node;
+ program = sym(1).Node;
+} break;
+./
+
+TopLevel: T_FEED_UI_OBJECT_MEMBER UiObjectMember ;
+/.
+case $rule_number: {
+ sym(1).Node = sym(2).Node;
+ program = sym(1).Node;
+} break;
+./
+
+UiProgram: UiImportListOpt UiRootMember ;
+/.
+case $rule_number: {
+ sym(1).UiProgram = makeAstNode<AST::UiProgram> (driver->nodePool(), sym(1).UiImportList,
+ sym(2).UiObjectMemberList->finish());
+} 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;
+./
+
+ImportId: MemberExpression ;
+
+UiImport: UiImportHead T_AUTOMATIC_SEMICOLON ;
+UiImport: UiImportHead T_SEMICOLON ;
+/.
+case $rule_number: {
+ sym(1).UiImport->semicolonToken = loc(2);
+} break;
+./
+
+UiImport: UiImportHead T_NUMERIC_LITERAL T_AUTOMATIC_SEMICOLON ;
+UiImport: UiImportHead T_NUMERIC_LITERAL T_SEMICOLON ;
+/.
+case $rule_number: {
+ sym(1).UiImport->versionToken = loc(2);
+ sym(1).UiImport->semicolonToken = loc(3);
+} break;
+./
+
+UiImport: UiImportHead T_NUMERIC_LITERAL T_AS JsIdentifier T_AUTOMATIC_SEMICOLON ;
+UiImport: UiImportHead T_NUMERIC_LITERAL T_AS JsIdentifier T_SEMICOLON ;
+/.
+case $rule_number: {
+ sym(1).UiImport->versionToken = loc(2);
+ sym(1).UiImport->asToken = loc(3);
+ sym(1).UiImport->importIdToken = loc(4);
+ sym(1).UiImport->importId = sym(4).sval;
+ sym(1).UiImport->semicolonToken = loc(5);
+} break;
+./
+
+UiImport: UiImportHead T_AS JsIdentifier T_AUTOMATIC_SEMICOLON ;
+UiImport: UiImportHead T_AS JsIdentifier T_SEMICOLON ;
+/.
+case $rule_number: {
+ sym(1).UiImport->asToken = loc(2);
+ sym(1).UiImport->importIdToken = loc(3);
+ sym(1).UiImport->importId = sym(3).sval;
+ sym(1).UiImport->semicolonToken = loc(4);
+} break;
+./
+
+
+UiImportHead: T_IMPORT ImportId ;
+/.
+case $rule_number: {
+ AST::UiImport *node = 0;
+
+ if (AST::StringLiteral *importIdLiteral = AST::cast<AST::StringLiteral *>(sym(2).Expression)) {
+ node = makeAstNode<AST::UiImport>(driver->nodePool(), importIdLiteral->value);
+ node->fileNameToken = loc(2);
+ } else if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(2).Expression)) {
+ QString text;
+ for (AST::UiQualifiedId *q = qualifiedId; q; q = q->next) {
+ text += q->name->asString();
+ if (q->next) text += QLatin1String(".");
+ }
+ node = makeAstNode<AST::UiImport>(driver->nodePool(), qualifiedId);
+ node->fileNameToken = loc(2);
+ }
+
+ sym(1).Node = node;
+
+ if (! node) {
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1),
+ QLatin1String("Expected a qualified name id or a string literal")));
+
+ return false; // ### remove me
+ }
+} 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::UiArrayMemberList> (driver->nodePool(), sym(1).UiObjectMember);
+} break;
+./
+
+UiArrayMemberList: UiArrayMemberList T_COMMA UiObjectDefinition ;
+/.
+case $rule_number: {
+ AST::UiArrayMemberList *node = makeAstNode<AST::UiArrayMemberList> (driver->nodePool(),
+ sym(1).UiArrayMemberList, sym(3).UiObjectMember);
+ node->commaToken = loc(2);
+ 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,
+ 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, sym(4).UiArrayMemberList->finish());
+ node->colonToken = loc(2);
+ node->lbracketToken = loc(3);
+ node->rbracketToken = loc(5);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: UiQualifiedId T_COLON UiQualifiedId UiObjectInitializer ;
+/.
+case $rule_number: {
+ AST::UiObjectBinding *node = makeAstNode<AST::UiObjectBinding> (driver->nodePool(),
+ sym(1).UiQualifiedId, sym(3).UiQualifiedId, sym(4).UiObjectInitializer);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} 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 IfStatement ; --- ### do we really want if statement in a binding?
+/.case $rule_number:./
+
+/.
+{
+ AST::UiScriptBinding *node = makeAstNode<AST::UiScriptBinding> (driver->nodePool(),
+ sym(1).UiQualifiedId, 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 ;
+
+UiParameterListOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+UiParameterListOpt: UiParameterList ;
+/.
+case $rule_number: {
+ sym(1).Node = sym(1).UiParameterList->finish ();
+} break;
+./
+
+UiParameterList: UiPropertyType JsIdentifier ;
+/.
+case $rule_number: {
+ AST::UiParameterList *node = makeAstNode<AST::UiParameterList> (driver->nodePool(), sym(1).sval, sym(2).sval);
+ node->identifierToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+UiParameterList: UiParameterList T_COMMA UiPropertyType JsIdentifier ;
+/.
+case $rule_number: {
+ AST::UiParameterList *node = makeAstNode<AST::UiParameterList> (driver->nodePool(), sym(1).UiParameterList, sym(3).sval, sym(4).sval);
+ node->commaToken = loc(2);
+ node->identifierToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: T_SIGNAL T_IDENTIFIER T_LPAREN UiParameterListOpt T_RPAREN T_AUTOMATIC_SEMICOLON ;
+UiObjectMember: T_SIGNAL T_IDENTIFIER T_LPAREN UiParameterListOpt T_RPAREN T_SEMICOLON ;
+/.
+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(2);
+ node->parameters = sym(4).UiParameterList;
+ node->semicolonToken = loc(6);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: T_SIGNAL T_IDENTIFIER T_AUTOMATIC_SEMICOLON ;
+UiObjectMember: T_SIGNAL T_IDENTIFIER T_SEMICOLON ;
+/.
+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(2);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT T_IDENTIFIER T_AUTOMATIC_SEMICOLON ;
+UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT T_IDENTIFIER T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(4).sval, sym(6).sval);
+ node->typeModifier = sym(2).sval;
+ node->propertyToken = loc(1);
+ node->typeModifierToken = loc(2);
+ node->typeToken = loc(4);
+ node->identifierToken = loc(6);
+ node->semicolonToken = loc(7);
+ 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_READONLY T_PROPERTY UiPropertyType T_IDENTIFIER T_COLON Expression T_AUTOMATIC_SEMICOLON ;
+UiObjectMember: T_READONLY 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->isReadonlyMember = true;
+ node->readonlyToken = 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: 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;
+./
+
+JsIdentifier: T_IDENTIFIER;
+
+JsIdentifier: T_PROPERTY ;
+/.
+case $rule_number: {
+ QString s = QLatin1String(QmlJSGrammar::spell[T_PROPERTY]);
+ sym(1).sval = driver->intern(s.constData(), s.length());
+ break;
+}
+./
+
+JsIdentifier: T_SIGNAL ;
+/.
+case $rule_number: {
+ QString s = QLatin1String(QmlJSGrammar::spell[T_SIGNAL]);
+ sym(1).sval = driver->intern(s.constData(), s.length());
+ break;
+}
+./
+
+JsIdentifier: T_READONLY ;
+/.
+case $rule_number: {
+ QString s = QLatin1String(QmlJSGrammar::spell[T_READONLY]);
+ 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);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_MULTILINE_STRING_LITERAL ;
+/.case $rule_number:./
+
+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: MemberExpression ;
+/.
+case $rule_number: {
+ if (AST::ArrayMemberExpression *mem = AST::cast<AST::ArrayMemberExpression *>(sym(1).Expression)) {
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, mem->lbracketToken,
+ QLatin1String("Ignored annotation")));
+
+ sym(1).Expression = mem->base;
+ }
+
+ if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(1).Expression)) {
+ sym(1).UiQualifiedId = qualifiedId;
+ } else {
+ sym(1).UiQualifiedId = 0;
+
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1),
+ QLatin1String("Expected a qualified name id")));
+
+ return false; // ### recover
+ }
+} 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;
+./
+
+--QmlJSProgram: 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 || tk == T_FEED_UI_PROGRAM ||
+ tk == T_FEED_JS_STATEMENT || tk == T_FEED_JS_EXPRESSION)
+ 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_QML_END_NAMESPACE
+
+
+./
+/:
+QT_QML_END_NAMESPACE
+
+
+
+#endif // QMLJSPARSER_P_H
+:/
diff --git a/src/plugins/qmldesigner/core/filemanager/parser/qmljsast.cpp b/src/plugins/qmldesigner/core/filemanager/parser/qmljsast.cpp
new file mode 100644
index 0000000000..ec199e80ae
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/parser/qmljsast.cpp
@@ -0,0 +1,943 @@
+/****************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "qmljsast_p.h"
+#include "qmljsastvisitor_p.h"
+
+QT_QML_BEGIN_NAMESPACE
+
+namespace QmlJS { namespace AST {
+
+void Node::accept(Visitor *visitor)
+{
+ if (visitor->preVisit(this)) {
+ accept0(visitor);
+ }
+ visitor->postVisit(this);
+}
+
+void Node::accept(Node *node, Visitor *visitor)
+{
+ if (node)
+ node->accept(visitor);
+}
+
+ExpressionNode *Node::expressionCast()
+{
+ return 0;
+}
+
+BinaryExpression *Node::binaryExpressionCast()
+{
+ return 0;
+}
+
+Statement *Node::statementCast()
+{
+ return 0;
+}
+
+UiObjectMember *Node::uiObjectMemberCast()
+{
+ return 0;
+}
+
+ExpressionNode *ExpressionNode::expressionCast()
+{
+ return this;
+}
+
+BinaryExpression *BinaryExpression::binaryExpressionCast()
+{
+ return this;
+}
+
+Statement *Statement::statementCast()
+{
+ return this;
+}
+
+UiObjectMember *UiObjectMember::uiObjectMemberCast()
+{
+ return this;
+}
+
+void NestedExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(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)) {
+ accept(elements, visitor);
+ accept(elision, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ObjectLiteral::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(properties, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ElementList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (ElementList *it = this; it; it = it->next) {
+ accept(it->elision, visitor);
+ accept(it->expression, visitor);
+ }
+ }
+
+ visitor->endVisit(this);
+}
+
+void Elision::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ // ###
+ }
+
+ visitor->endVisit(this);
+}
+
+void PropertyNameAndValueList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (PropertyNameAndValueList *it = this; it; it = it->next) {
+ accept(it->name, visitor);
+ accept(it->value, visitor);
+ }
+ }
+
+ 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)) {
+ accept(base, visitor);
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void FieldMemberExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(base, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void NewMemberExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(base, visitor);
+ accept(arguments, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void NewExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void CallExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(base, visitor);
+ accept(arguments, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ArgumentList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (ArgumentList *it = this; it; it = it->next) {
+ accept(it->expression, visitor);
+ }
+ }
+
+ visitor->endVisit(this);
+}
+
+void PostIncrementExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(base, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void PostDecrementExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(base, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void DeleteExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void VoidExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void TypeOfExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void PreIncrementExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void PreDecrementExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UnaryPlusExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UnaryMinusExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void TildeExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void NotExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void BinaryExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(left, visitor);
+ accept(right, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ConditionalExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ accept(ok, visitor);
+ accept(ko, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void Expression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(left, visitor);
+ accept(right, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void Block::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(statements, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void StatementList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (StatementList *it = this; it; it = it->next) {
+ accept(it->statement, visitor);
+ }
+ }
+
+ visitor->endVisit(this);
+}
+
+void VariableStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(declarations, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void VariableDeclarationList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (VariableDeclarationList *it = this; it; it = it->next) {
+ accept(it->declaration, visitor);
+ }
+ }
+
+ visitor->endVisit(this);
+}
+
+void VariableDeclaration::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(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)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void IfStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ accept(ok, visitor);
+ accept(ko, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void DoWhileStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(statement, visitor);
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void WhileStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ accept(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ForStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(initialiser, visitor);
+ accept(condition, visitor);
+ accept(expression, visitor);
+ accept(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void LocalForStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(declarations, visitor);
+ accept(condition, visitor);
+ accept(expression, visitor);
+ accept(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ForEachStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(initialiser, visitor);
+ accept(expression, visitor);
+ accept(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void LocalForEachStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(declaration, visitor);
+ accept(expression, visitor);
+ accept(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)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void WithStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ accept(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void SwitchStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ accept(block, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void CaseBlock::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(clauses, visitor);
+ accept(defaultClause, visitor);
+ accept(moreClauses, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void CaseClauses::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (CaseClauses *it = this; it; it = it->next) {
+ accept(it->clause, visitor);
+ }
+ }
+
+ visitor->endVisit(this);
+}
+
+void CaseClause::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ accept(statements, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void DefaultClause::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(statements, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void LabelledStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ThrowStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void TryStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(statement, visitor);
+ accept(catchExpression, visitor);
+ accept(finallyExpression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void Catch::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void Finally::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void FunctionDeclaration::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(formals, visitor);
+ accept(body, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void FunctionExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(formals, visitor);
+ accept(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)) {
+ accept(elements, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void Program::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(elements, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void SourceElements::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (SourceElements *it = this; it; it = it->next) {
+ accept(it->element, visitor);
+ }
+ }
+
+ visitor->endVisit(this);
+}
+
+void FunctionSourceElement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(declaration, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void StatementSourceElement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(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)) {
+ accept(imports, visitor);
+ accept(members, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiSignature::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(formals, visitor);
+ }
+ visitor->endVisit(this);
+}
+
+void UiFormalList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (UiFormalList *it = this; it; it = it->next) {
+ accept(it->formal, visitor);
+ }
+ }
+ visitor->endVisit(this);
+}
+
+void UiFormal::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+ visitor->endVisit(this);
+}
+
+void UiPublicMember::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiObjectDefinition::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(qualifiedTypeNameId, visitor);
+ accept(initializer, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiObjectInitializer::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(members, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiObjectBinding::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(qualifiedId, visitor);
+ accept(qualifiedTypeNameId, visitor);
+ accept(initializer, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiScriptBinding::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(qualifiedId, visitor);
+ accept(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiArrayBinding::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(qualifiedId, visitor);
+ accept(members, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiObjectMemberList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (UiObjectMemberList *it = this; it; it = it->next)
+ accept(it->member, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiArrayMemberList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (UiArrayMemberList *it = this; it; it = it->next)
+ accept(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)) {
+ accept(importUri, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiImportList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(import, visitor);
+ accept(next, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiSourceElement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(sourceElement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+} } // namespace QmlJS::AST
+
+QT_QML_END_NAMESPACE
+
+
diff --git a/src/plugins/qmldesigner/core/filemanager/parser/qmljsast_p.h b/src/plugins/qmldesigner/core/filemanager/parser/qmljsast_p.h
new file mode 100644
index 0000000000..3ad1f0de82
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/parser/qmljsast_p.h
@@ -0,0 +1,2665 @@
+/****************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef QMLJSAST_P_H
+#define QMLJSAST_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 "qmljsastvisitor_p.h"
+#include "qmljsglobal_p.h"
+#include <QtCore/QString>
+
+QT_QML_BEGIN_NAMESPACE
+
+#define QMLJS_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 QmlJS {
+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_UiArrayMemberList,
+ Kind_UiProgram,
+ Kind_UiParameterList,
+ Kind_UiPublicMember,
+ Kind_UiQualifiedId,
+ Kind_UiScriptBinding,
+ Kind_UiSourceElement,
+ Kind_UiFormal,
+ Kind_UiFormalList,
+ Kind_UiSignature
+ };
+
+ inline Node()
+ : kind(Kind_Undefined) {}
+
+ virtual ~Node() {}
+
+ virtual ExpressionNode *expressionCast();
+ virtual BinaryExpression *binaryExpressionCast();
+ virtual Statement *statementCast();
+ virtual UiObjectMember *uiObjectMemberCast();
+
+ void accept(Visitor *visitor);
+ static void accept(Node *node, Visitor *visitor);
+
+ inline static void acceptChild(Node *node, Visitor *visitor)
+ { return accept(node, visitor); } // ### remove
+
+ 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 UiFormal: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiFormal)
+
+ UiFormal(NameId *name, NameId *alias = 0)
+ : name(name), alias(alias)
+ { }
+
+ virtual SourceLocation firstSourceLocation() const
+ { return SourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return SourceLocation(); }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ NameId *name;
+ NameId *alias;
+ SourceLocation identifierToken;
+ SourceLocation asToken;
+ SourceLocation aliasToken;
+};
+
+class UiFormalList: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiFormalList)
+
+ UiFormalList(UiFormal *formal)
+ : formal(formal), next(this) {}
+
+ UiFormalList(UiFormalList *previous, UiFormal *formal)
+ : formal(formal)
+ {
+ next = previous->next;
+ previous->next = this;
+ }
+
+ UiFormalList *finish()
+ {
+ UiFormalList *head = next;
+ next = 0;
+ return head;
+ }
+
+ virtual SourceLocation firstSourceLocation() const
+ { return SourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return SourceLocation(); }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ UiFormal *formal;
+ UiFormalList *next;
+};
+
+class UiSignature: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiSignature)
+
+ UiSignature(UiFormalList *formals = 0)
+ : formals(formals)
+ { }
+
+ virtual SourceLocation firstSourceLocation() const
+ { return SourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return SourceLocation(); }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ SourceLocation lparenToken;
+ UiFormalList *formals;
+ SourceLocation rparenToken;
+};
+
+class NestedExpression: public ExpressionNode
+{
+public:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_DECLARE_AST_NODE(NumericLiteral)
+
+ NumericLiteral(double v):
+ value(v) { kind = K; }
+ virtual ~NumericLiteral() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return literalToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return literalToken; }
+
+// attributes:
+ double value;
+ SourceLocation literalToken;
+};
+
+class StringLiteral: public ExpressionNode
+{
+public:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_DECLARE_AST_NODE(PropertyName)
+
+ PropertyName() { kind = K; }
+ virtual ~PropertyName() {}
+
+// attributes
+ SourceLocation propertyNameToken;
+};
+
+class IdentifierPropertyName: public PropertyName
+{
+public:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_DECLARE_AST_NODE(SourceElement)
+
+ inline SourceElement()
+ { kind = K; }
+
+ virtual ~SourceElement() {}
+};
+
+class FunctionSourceElement: public SourceElement
+{
+public:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_DECLARE_AST_NODE(UiImport)
+
+ UiImport(NameId *fileName)
+ : fileName(fileName), importUri(0), importId(0)
+ { kind = K; }
+
+ UiImport(UiQualifiedId *uri)
+ : fileName(0), importUri(uri), importId(0)
+ { kind = K; }
+
+ virtual SourceLocation firstSourceLocation() const
+ { return importToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ NameId *fileName;
+ UiQualifiedId *importUri;
+ NameId *importId;
+ SourceLocation importToken;
+ SourceLocation fileNameToken;
+ SourceLocation versionToken;
+ SourceLocation asToken;
+ SourceLocation importIdToken;
+ SourceLocation semicolonToken;
+};
+
+class UiImportList: public Node
+{
+public:
+ QMLJS_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;
+ }
+
+ virtual SourceLocation firstSourceLocation() const
+ {
+ if (import) return import->firstSourceLocation();
+ else return SourceLocation();
+ }
+
+ virtual SourceLocation lastSourceLocation() const
+ {
+ for (const UiImportList *it = this; it; it = it->next)
+ if (!it->next && it->import)
+ return it->import->lastSourceLocation();
+
+ return SourceLocation();
+ }
+
+ 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;
+
+ virtual UiObjectMember *uiObjectMemberCast();
+};
+
+class UiObjectMemberList: public Node
+{
+public:
+ QMLJS_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 UiArrayMemberList: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiArrayMemberList)
+
+ UiArrayMemberList(UiObjectMember *member)
+ : next(this), member(member)
+ { kind = K; }
+
+ UiArrayMemberList(UiArrayMemberList *previous, UiObjectMember *member)
+ : member(member)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual void accept0(Visitor *visitor);
+
+ UiArrayMemberList *finish()
+ {
+ UiArrayMemberList *head = next;
+ next = 0;
+ return head;
+ }
+
+// attributes
+ UiArrayMemberList *next;
+ UiObjectMember *member;
+ SourceLocation commaToken;
+};
+
+class UiObjectInitializer: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiObjectInitializer)
+
+ UiObjectInitializer(UiObjectMemberList *members)
+ : members(members)
+ { kind = K; }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ SourceLocation lbraceToken;
+ UiObjectMemberList *members;
+ SourceLocation rbraceToken;
+};
+
+class UiParameterList: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiParameterList)
+
+ UiParameterList(NameId *t, NameId *n):
+ type (t), name (n), next (this)
+ { kind = K; }
+
+ UiParameterList(UiParameterList *previous, NameId *t, NameId *n):
+ type (t), name (n)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~UiParameterList() {}
+
+ virtual void accept0(Visitor *) {}
+
+ inline UiParameterList *finish ()
+ {
+ UiParameterList *front = next;
+ next = 0;
+ return front;
+ }
+
+// attributes
+ NameId *type;
+ NameId *name;
+ UiParameterList *next;
+ SourceLocation commaToken;
+ SourceLocation identifierToken;
+};
+
+class UiPublicMember: public UiObjectMember
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiPublicMember)
+
+ UiPublicMember(NameId *memberType,
+ NameId *name)
+ : type(Property), typeModifier(0), memberType(memberType), name(name), expression(0), isDefaultMember(false), isReadonlyMember(false), parameters(0)
+ { kind = K; }
+
+ UiPublicMember(NameId *memberType,
+ NameId *name,
+ ExpressionNode *expression)
+ : type(Property), typeModifier(0), memberType(memberType), name(name), expression(expression), isDefaultMember(false), isReadonlyMember(false), parameters(0)
+ { kind = K; }
+
+ virtual SourceLocation firstSourceLocation() const
+ {
+ if (defaultToken.isValid())
+ return defaultToken;
+ else if (readonlyToken.isValid())
+ return readonlyToken;
+
+ return propertyToken;
+ }
+
+ virtual SourceLocation lastSourceLocation() const
+ {
+ return semicolonToken;
+ }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ enum { Signal, Property } type;
+ NameId *typeModifier;
+ NameId *memberType;
+ NameId *name;
+ ExpressionNode *expression;
+ bool isDefaultMember;
+ bool isReadonlyMember;
+ UiParameterList *parameters;
+ SourceLocation defaultToken;
+ SourceLocation readonlyToken;
+ SourceLocation propertyToken;
+ SourceLocation typeModifierToken;
+ SourceLocation typeToken;
+ SourceLocation identifierToken;
+ SourceLocation colonToken;
+ SourceLocation semicolonToken;
+};
+
+class UiObjectDefinition: public UiObjectMember
+{
+public:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_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:
+ QMLJS_DECLARE_AST_NODE(UiArrayBinding)
+
+ UiArrayBinding(UiQualifiedId *qualifiedId,
+ UiArrayMemberList *members)
+ : qualifiedId(qualifiedId),
+ members(members)
+ { kind = K; }
+
+ virtual SourceLocation firstSourceLocation() const
+ { return qualifiedId->identifierToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return rbracketToken; }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ UiQualifiedId *qualifiedId;
+ UiArrayMemberList *members;
+ SourceLocation colonToken;
+ SourceLocation lbracketToken;
+ SourceLocation rbracketToken;
+};
+
+} } // namespace AST
+
+
+
+QT_QML_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qmldesigner/core/filemanager/parser/qmljsastfwd_p.h b/src/plugins/qmldesigner/core/filemanager/parser/qmljsastfwd_p.h
new file mode 100644
index 0000000000..dd164e9e3c
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/parser/qmljsastfwd_p.h
@@ -0,0 +1,176 @@
+/****************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef QMLJSAST_FWD_P_H
+#define QMLJSAST_FWD_P_H
+
+#include <QtCore/qglobal.h>
+#include "qmljsglobal_p.h"
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_QML_BEGIN_NAMESPACE
+
+namespace QmlJS { namespace AST {
+
+class SourceLocation
+{
+public:
+ SourceLocation(quint32 offset = 0, quint32 length = 0, quint32 line = 0, quint32 column = 0)
+ : offset(offset), length(length),
+ startLine(line), startColumn(column)
+ { }
+
+ 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 UiArrayMemberList;
+class UiQualifiedId;
+class UiFormalList;
+class UiFormal;
+class UiSignature;
+
+} } // namespace AST
+
+QT_QML_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qmldesigner/core/filemanager/parser/qmljsastvisitor.cpp b/src/plugins/qmldesigner/core/filemanager/parser/qmljsastvisitor.cpp
new file mode 100644
index 0000000000..6a0d55a4f1
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/parser/qmljsastvisitor.cpp
@@ -0,0 +1,46 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "qmljsastvisitor_p.h"
+
+QT_QML_BEGIN_NAMESPACE
+
+namespace QmlJS { namespace AST {
+
+Visitor::Visitor()
+{
+}
+
+Visitor::~Visitor()
+{
+}
+
+} } // namespace QmlJS::AST
+
+QT_QML_END_NAMESPACE
diff --git a/src/plugins/qmldesigner/core/filemanager/parser/qmljsastvisitor_p.h b/src/plugins/qmldesigner/core/filemanager/parser/qmljsastvisitor_p.h
new file mode 100644
index 0000000000..09714ee0a0
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/parser/qmljsastvisitor_p.h
@@ -0,0 +1,323 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef QMLJSASTVISITOR_P_H
+#define QMLJSASTVISITOR_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 "qmljsastfwd_p.h"
+#include "qmljsglobal_p.h"
+
+QT_QML_BEGIN_NAMESPACE
+
+namespace QmlJS { 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(UiArrayMemberList *) { return true; }
+ virtual bool visit(UiQualifiedId *) { return true; }
+ virtual bool visit(UiSignature *) { return true; }
+ virtual bool visit(UiFormalList *) { return true; }
+ virtual bool visit(UiFormal *) { 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(UiArrayMemberList *) {}
+ virtual void endVisit(UiQualifiedId *) {}
+ virtual void endVisit(UiSignature *) {}
+ virtual void endVisit(UiFormalList *) {}
+ virtual void endVisit(UiFormal *) {}
+
+ // QmlJS
+ 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_QML_END_NAMESPACE
+
+#endif // QMLJSASTVISITOR_P_H
diff --git a/src/plugins/qmldesigner/core/filemanager/parser/qmljsengine_p.cpp b/src/plugins/qmldesigner/core/filemanager/parser/qmljsengine_p.cpp
new file mode 100644
index 0000000000..6e7a45a506
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/parser/qmljsengine_p.cpp
@@ -0,0 +1,198 @@
+/****************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "qmljsglobal_p.h"
+#include "qmljsengine_p.h"
+#include "qmljsnodepool_p.h"
+#include <qnumeric.h>
+#include <QHash>
+
+QT_QML_BEGIN_NAMESPACE
+
+namespace QmlJS {
+
+uint qHash(const QmlJS::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; }
+
+void Engine::addComment(int pos, int len, int line, int col)
+{ if (len > 0) _comments.append(QmlJS::AST::SourceLocation(pos, len, line, col)); }
+
+QList<QmlJS::AST::SourceLocation> Engine::comments() const
+{ return _comments; }
+
+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 QmlJS
+
+QT_QML_END_NAMESPACE
diff --git a/src/plugins/qmldesigner/core/filemanager/parser/qmljsengine_p.h b/src/plugins/qmldesigner/core/filemanager/parser/qmljsengine_p.h
new file mode 100644
index 0000000000..98e71c8879
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/parser/qmljsengine_p.h
@@ -0,0 +1,161 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef QMLJSENGINE_P_H
+#define QMLJSENGINE_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 <QString>
+#include <QSet>
+
+#include "qmljsglobal_p.h"
+#include "qmljsastfwd_p.h"
+
+QT_QML_BEGIN_NAMESPACE
+
+namespace QmlJS {
+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 QmlJS::NameId &id);
+
+} // end of namespace QmlJS
+
+#if defined(Q_CC_MSVC) && _MSC_VER <= 1300
+//this ensures that code outside QmlJS can use the hash function
+//it also a workaround for some compilers
+inline uint qHash(const QmlJS::NameId &nameId) { return QmlJS::qHash(nameId); }
+#endif
+
+namespace QmlJS {
+
+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;
+ QList<QmlJS::AST::SourceLocation> _comments;
+
+public:
+ Engine();
+ ~Engine();
+
+ QSet<NameId> literals() const;
+
+ void addComment(int pos, int len, int line, int col);
+ QList<QmlJS::AST::SourceLocation> comments() 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 QmlJS
+
+QT_QML_END_NAMESPACE
+
+#endif // QMLJSENGINE_P_H
diff --git a/src/plugins/qmldesigner/core/filemanager/parser/qmljsglobal_p.h b/src/plugins/qmldesigner/core/filemanager/parser/qmljsglobal_p.h
new file mode 100644
index 0000000000..96f1ced266
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/parser/qmljsglobal_p.h
@@ -0,0 +1,43 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef QMLJSGLOBAL_P_H
+#define QMLJSGLOBAL_P_H
+
+#include <QtCore/qglobal.h>
+
+#ifdef QT_CREATOR
+#define QT_QML_BEGIN_NAMESPACE
+#define QT_QML_END_NAMESPACE
+#else // !QT_CREATOR
+#define QT_QML_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
+#define QT_QML_END_NAMESPACE QT_END_NAMESPACE
+#endif // QT_CREATOR
+
+#endif // QMLJSGLOBAL_P_H
diff --git a/src/plugins/qmldesigner/core/filemanager/parser/qmljsgrammar.cpp b/src/plugins/qmldesigner/core/filemanager/parser/qmljsgrammar.cpp
new file mode 100644
index 0000000000..c71b759a35
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/parser/qmljsgrammar.cpp
@@ -0,0 +1,960 @@
+// This file was generated by qlalr - DO NOT EDIT!
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmljsgrammar_p.h"
+
+const char *const QmlJSGrammar::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", "readonly", "switch",
+ "this", "throw", "~", "try", "typeof", "var", "void", "while", "with", "^",
+ "^=", "null", "true", "false", "const", "debugger", "reserved word", "multiline string literal", "comment", "public",
+ "import", "as", 0, 0, 0, 0, 0, 0};
+
+const int QmlJSGrammar::lhs [] = {
+ 98, 98, 98, 98, 99, 103, 103, 106, 106, 108,
+ 107, 107, 107, 107, 107, 107, 107, 107, 110, 105,
+ 104, 113, 113, 114, 114, 115, 115, 112, 102, 102,
+ 102, 102, 102, 102, 102, 121, 121, 121, 122, 122,
+ 123, 123, 102, 102, 102, 102, 102, 102, 102, 102,
+ 102, 102, 102, 102, 102, 102, 102, 102, 102, 102,
+ 111, 111, 111, 111, 126, 126, 126, 126, 126, 126,
+ 126, 126, 126, 126, 126, 126, 126, 126, 126, 126,
+ 126, 126, 116, 128, 128, 128, 128, 127, 127, 130,
+ 130, 132, 132, 132, 132, 132, 132, 133, 133, 133,
+ 133, 133, 133, 133, 133, 133, 133, 133, 133, 133,
+ 133, 133, 133, 133, 133, 133, 133, 133, 133, 133,
+ 133, 133, 133, 133, 133, 133, 133, 133, 134, 134,
+ 109, 109, 109, 109, 109, 137, 137, 138, 138, 138,
+ 138, 136, 136, 139, 139, 140, 140, 141, 141, 141,
+ 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+ 143, 143, 143, 143, 144, 144, 144, 145, 145, 145,
+ 145, 146, 146, 146, 146, 146, 146, 146, 147, 147,
+ 147, 147, 147, 147, 148, 148, 148, 148, 148, 149,
+ 149, 149, 149, 149, 150, 150, 151, 151, 152, 152,
+ 153, 153, 154, 154, 155, 155, 156, 156, 157, 157,
+ 158, 158, 159, 159, 160, 160, 161, 161, 131, 131,
+ 162, 162, 163, 163, 163, 163, 163, 163, 163, 163,
+ 163, 163, 163, 163, 101, 101, 164, 164, 165, 165,
+ 166, 166, 100, 100, 100, 100, 100, 100, 100, 100,
+ 100, 100, 100, 100, 100, 100, 100, 117, 178, 178,
+ 177, 177, 125, 125, 179, 179, 180, 180, 182, 182,
+ 181, 183, 186, 184, 184, 187, 185, 185, 118, 119,
+ 119, 120, 120, 167, 167, 167, 167, 167, 167, 167,
+ 168, 168, 168, 168, 169, 169, 169, 169, 170, 170,
+ 171, 173, 188, 188, 191, 191, 189, 189, 192, 190,
+ 172, 172, 172, 174, 174, 175, 175, 175, 193, 194,
+ 176, 176, 124, 135, 198, 198, 195, 195, 196, 196,
+ 199, 200, 200, 201, 201, 197, 197, 129, 129, 202};
+
+const int QmlJSGrammar:: rhs[] = {
+ 2, 2, 2, 2, 2, 1, 1, 1, 2, 1,
+ 2, 2, 3, 3, 5, 5, 4, 4, 2, 0,
+ 1, 1, 2, 1, 3, 2, 3, 2, 1, 5,
+ 4, 3, 3, 3, 3, 1, 1, 1, 0, 1,
+ 2, 4, 6, 6, 3, 3, 7, 7, 4, 4,
+ 5, 5, 6, 6, 7, 7, 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, 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 QmlJSGrammar::action_default [] = {
+ 0, 0, 0, 0, 20, 0, 168, 235, 199, 207,
+ 203, 147, 219, 195, 3, 132, 66, 148, 211, 215,
+ 136, 165, 146, 151, 131, 185, 172, 0, 73, 74,
+ 69, 336, 61, 338, 0, 0, 0, 0, 71, 0,
+ 0, 67, 70, 0, 0, 62, 64, 63, 72, 65,
+ 0, 68, 0, 0, 161, 0, 0, 148, 167, 150,
+ 149, 0, 0, 0, 163, 164, 162, 166, 0, 196,
+ 0, 0, 0, 0, 186, 0, 0, 0, 0, 0,
+ 0, 176, 0, 0, 0, 170, 171, 169, 174, 178,
+ 177, 175, 173, 188, 187, 189, 0, 204, 0, 200,
+ 0, 0, 142, 129, 141, 130, 98, 99, 100, 125,
+ 101, 126, 102, 103, 104, 105, 106, 107, 108, 109,
+ 110, 111, 112, 113, 114, 127, 115, 116, 117, 118,
+ 119, 120, 121, 122, 123, 124, 128, 0, 0, 140,
+ 236, 143, 0, 144, 0, 145, 139, 0, 232, 225,
+ 223, 230, 231, 229, 228, 234, 227, 226, 224, 233,
+ 220, 0, 208, 0, 0, 212, 0, 0, 216, 0,
+ 0, 142, 134, 0, 133, 0, 138, 152, 0, 337,
+ 327, 328, 0, 325, 0, 326, 0, 329, 243, 250,
+ 249, 257, 245, 0, 246, 330, 0, 335, 247, 248,
+ 253, 251, 332, 331, 334, 254, 0, 265, 0, 0,
+ 0, 0, 336, 61, 0, 338, 62, 237, 279, 63,
+ 0, 0, 0, 266, 0, 0, 255, 256, 0, 244,
+ 252, 280, 281, 324, 333, 0, 295, 296, 297, 298,
+ 0, 291, 292, 293, 294, 321, 322, 0, 0, 0,
+ 0, 0, 284, 285, 241, 239, 201, 209, 205, 221,
+ 197, 242, 0, 148, 213, 217, 190, 179, 0, 0,
+ 198, 0, 0, 0, 0, 191, 0, 0, 0, 0,
+ 0, 183, 181, 184, 182, 180, 193, 192, 194, 0,
+ 206, 0, 202, 0, 240, 148, 0, 222, 237, 238,
+ 0, 237, 0, 0, 287, 0, 0, 0, 289, 0,
+ 210, 0, 0, 214, 0, 0, 218, 277, 0, 269,
+ 278, 272, 0, 276, 0, 237, 270, 0, 237, 0,
+ 0, 288, 0, 0, 0, 290, 337, 327, 0, 0,
+ 329, 0, 323, 0, 313, 0, 0, 0, 283, 0,
+ 282, 0, 339, 0, 97, 259, 262, 0, 98, 265,
+ 101, 126, 103, 104, 69, 108, 109, 61, 110, 113,
+ 67, 70, 62, 237, 63, 72, 116, 65, 118, 68,
+ 120, 121, 266, 123, 124, 128, 0, 90, 0, 0,
+ 92, 96, 94, 81, 93, 95, 0, 91, 80, 260,
+ 258, 136, 137, 142, 0, 135, 0, 312, 0, 299,
+ 300, 0, 311, 0, 0, 0, 302, 307, 305, 308,
+ 0, 0, 306, 307, 0, 303, 0, 304, 261, 310,
+ 0, 261, 309, 0, 314, 315, 0, 261, 316, 317,
+ 0, 0, 318, 0, 0, 0, 319, 320, 154, 153,
+ 0, 0, 0, 286, 0, 0, 0, 301, 274, 267,
+ 0, 275, 271, 0, 273, 263, 0, 264, 268, 84,
+ 0, 0, 88, 75, 0, 77, 86, 0, 78, 87,
+ 89, 79, 85, 76, 0, 82, 158, 156, 160, 157,
+ 155, 159, 2, 59, 83, 0, 0, 62, 64, 63,
+ 29, 4, 0, 60, 0, 38, 37, 36, 0, 0,
+ 51, 0, 52, 0, 57, 58, 0, 38, 0, 0,
+ 0, 0, 0, 47, 48, 0, 49, 0, 50, 0,
+ 53, 54, 0, 0, 0, 0, 0, 55, 56, 0,
+ 45, 39, 46, 40, 0, 0, 0, 0, 42, 0,
+ 43, 44, 41, 0, 0, 28, 32, 33, 34, 35,
+ 136, 261, 0, 0, 98, 265, 101, 126, 103, 104,
+ 69, 108, 109, 61, 110, 113, 67, 70, 62, 237,
+ 63, 72, 116, 65, 118, 68, 120, 121, 266, 123,
+ 124, 128, 136, 0, 24, 0, 0, 30, 25, 31,
+ 26, 22, 0, 27, 23, 6, 0, 8, 0, 7,
+ 0, 1, 19, 10, 0, 11, 0, 12, 0, 17,
+ 18, 0, 13, 14, 0, 15, 16, 9, 21, 5,
+ 340};
+
+const int QmlJSGrammar::goto_default [] = {
+ 5, 611, 355, 193, 501, 610, 629, 605, 609, 607,
+ 612, 20, 608, 16, 500, 602, 593, 555, 502, 188,
+ 192, 194, 198, 518, 544, 543, 197, 229, 24, 471,
+ 470, 353, 352, 7, 351, 354, 104, 15, 142, 22,
+ 11, 141, 17, 23, 54, 21, 6, 26, 25, 266,
+ 13, 260, 8, 256, 10, 258, 9, 257, 18, 264,
+ 19, 265, 12, 259, 255, 296, 408, 261, 262, 199,
+ 190, 189, 201, 230, 200, 205, 226, 227, 191, 357,
+ 356, 228, 460, 459, 318, 319, 462, 321, 461, 320,
+ 416, 420, 423, 419, 418, 438, 439, 182, 196, 178,
+ 181, 195, 203, 202, 0};
+
+const int QmlJSGrammar::action_index [] = {
+ 251, 1237, 2238, 974, -45, 51, 122, -98, 52, -11,
+ -39, 182, -98, 389, 36, -98, -98, 628, 58, 75,
+ 246, 228, -98, -98, -98, 438, 309, 1237, -98, -98,
+ -98, 348, -98, 2050, 1772, 1237, 1237, 1237, -98, 800,
+ 1237, -98, -98, 1237, 1237, -98, -98, -98, -98, -98,
+ 1237, -98, 1237, 1237, -98, 1237, 1237, 97, 226, -98,
+ -98, 1237, 1237, 1237, -98, -98, -98, 200, 1237, 389,
+ 1237, 1237, 1237, 1237, 418, 1237, 1237, 1237, 1237, 1237,
+ 1237, 212, 1237, 1237, 1237, 144, 121, 71, 309, 309,
+ 164, 156, 179, 448, 428, 408, 1237, -51, 1237, 101,
+ 1956, 1237, 1237, -98, -98, -98, -98, -98, -98, -98,
+ -98, -98, -98, -98, -98, -98, -98, -98, -98, -98,
+ -98, -98, -98, -98, -98, -98, -98, -98, -98, -98,
+ -98, -98, -98, -98, -98, -98, -98, 236, 1237, -98,
+ -98, 31, 16, -98, 1237, -98, -98, 1237, -98, -98,
+ -98, -98, -98, -98, -98, -98, -98, -98, -98, -98,
+ -98, 1237, 2, 1237, 1237, 41, 35, 1237, -98, 1956,
+ 1237, 1237, -98, 102, -98, 6, -98, -98, 20, -98,
+ 299, 53, 14, -98, 321, -98, -22, 2332, -98, -98,
+ -98, -98, -98, 216, -98, -98, -28, -98, -98, -98,
+ -98, -98, -98, 2332, -98, -98, 469, -98, 533, 115,
+ 2238, -2, 335, -3, -36, 2520, 50, 1237, -98, 64,
+ 33, 1237, 21, -98, 5, -14, -98, -98, 306, -98,
+ -98, -98, -98, -98, -98, 74, -98, -98, -98, -98,
+ 117, -98, -98, -98, -98, -98, -98, -57, -18, 1237,
+ 140, 109, -98, -98, 1324, -98, 104, 67, 27, -98,
+ 330, 84, 29, 585, 80, 92, 464, 171, 295, 1237,
+ 314, 1237, 1237, 1237, 1237, 346, 1237, 1237, 1237, 1237,
+ 1237, 309, 309, 309, 309, 309, 386, 464, 464, 1237,
+ 27, 1237, 87, 1237, -98, 529, 1237, -98, 1237, 83,
+ 38, 1237, 48, 2238, -98, 1237, 143, 2238, -98, 1237,
+ 30, 1237, 1237, 81, 77, 1237, -98, 56, 126, 90,
+ -98, -98, 1237, -98, 290, 1237, -98, 42, 1237, 44,
+ 2238, -98, 1237, 133, 2238, -98, 22, 285, -37, -9,
+ 2332, -30, -98, 2238, -98, 1237, 141, 2238, 10, 2238,
+ -98, 26, 24, -24, -98, -98, 2238, 25, 453, 23,
+ 533, 106, 1237, 2238, 9, -29, 361, -4, -31, 800,
+ -6, 55, -98, 1415, -98, -1, -23, 8, 1237, 7,
+ -21, 1237, 1, 1237, -27, -19, 1237, -98, 2144, 28,
+ -98, -98, -98, -98, -98, -98, 1237, -98, -98, -98,
+ -98, 211, -98, 1237, 17, -98, 2238, -98, 98, -98,
+ -98, 2238, -98, 1237, 105, 37, -98, 63, -98, 62,
+ 99, 1237, -98, 60, 57, -98, 4, -98, 2238, -98,
+ 116, 2238, -98, 180, -98, -98, 112, 2238, 18, -98,
+ 11, 13, -98, 325, 3, 19, -98, -98, -98, -98,
+ 1237, 132, 2238, -98, 1237, 139, 2238, -98, 32, -98,
+ 174, -98, -98, 1237, -98, -98, 229, -98, -98, -98,
+ 108, 1682, -98, -98, 1862, -98, -98, 1505, -98, -98,
+ -98, -98, -98, -98, 125, -98, -98, -98, -98, -98,
+ -98, -98, -98, -98, 111, 46, 792, 184, 34, 85,
+ -98, -98, 136, -98, 185, -98, -98, -98, 65, 204,
+ -98, 1237, -98, 207, -98, -98, 193, 61, 43, 225,
+ 73, 88, 66, -98, -98, 214, -98, 1237, -98, 158,
+ -98, -98, 181, 91, 72, 1237, 172, -98, -98, 187,
+ -98, 157, -98, 47, -50, 274, 178, 250, -98, 113,
+ -98, -98, -98, 1592, 1062, -98, -98, -98, -98, -98,
+ 271, 2426, 1772, 15, 461, 146, 445, 76, 1237, 2238,
+ -5, 0, 370, 12, -15, 706, 89, 78, -98, 1415,
+ -98, 100, 59, 82, 1237, 86, 54, 1237, 79, 1237,
+ 45, 39, 279, 149, -98, 68, 617, -98, -98, -98,
+ -98, -98, 1150, -98, -98, -98, 886, -98, 240, -61,
+ 714, -98, -98, 129, 259, -98, 190, -98, 69, -98,
+ -98, 255, -98, -98, 94, -98, -98, -98, -98, -98,
+ -98,
+
+ -105, 23, 25, 216, -105, -105, -105, -105, -105, -105,
+ -105, -105, -105, -105, -105, -105, -105, -44, -105, -105,
+ -105, -105, -105, -105, -105, -105, -105, 70, -105, -105,
+ -105, 28, -105, -105, 20, 39, 97, 163, -105, 178,
+ 159, -105, -105, 156, 164, -105, -105, -105, -105, -105,
+ 132, -105, 153, 135, -105, 139, 140, -105, -105, -105,
+ -105, 103, 92, 144, -105, -105, -105, -105, 125, -105,
+ 154, 162, 83, 84, -105, 88, 82, 81, 75, 66,
+ 122, -105, 116, 98, 104, -105, -105, -105, -105, -105,
+ -105, -105, -105, -105, -105, -105, 106, -105, 113, -105,
+ 86, 80, 52, -105, -105, -105, -105, -105, -105, -105,
+ -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+ -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+ -105, -105, -105, -105, -105, -105, -105, -105, 34, -105,
+ -105, -105, -105, -105, 38, -105, -105, 43, -105, -105,
+ -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+ -105, 136, -105, 91, -29, -105, -105, 3, -105, 225,
+ 37, 71, -105, -105, -105, -105, -105, -105, -105, -105,
+ -3, -105, -105, -105, 18, -105, -105, 27, -105, -105,
+ -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+ -105, -105, -105, 87, -105, -105, 62, -105, 56, -105,
+ 50, -105, 31, -105, -105, -105, -105, 59, -105, -105,
+ -105, 47, 69, -105, -105, -105, -105, -105, 67, -105,
+ -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+ -105, -105, -105, -105, -105, -105, -105, -105, -105, 30,
+ -105, -105, -105, -105, 96, -105, -105, -105, -105, -105,
+ -105, -105, -105, -105, -105, -105, -105, -105, 10, 184,
+ -105, 222, 226, 232, 202, -105, 124, 114, 112, 110,
+ 95, -105, -105, -105, -105, -105, -105, -105, -105, 212,
+ -105, 192, -105, 177, -105, -105, 208, -105, 107, -105,
+ -105, 255, -105, 11, -105, 13, -105, 44, -105, 206,
+ -105, 169, 176, -105, -105, 183, -105, -105, -105, -105,
+ -105, -105, 173, -105, 167, 117, -105, -105, 191, -105,
+ 54, -105, 55, -105, 58, -105, -105, 102, -105, -105,
+ 89, -105, -105, 57, -105, 46, -105, 45, -105, 49,
+ -105, -105, -105, -105, -105, -105, 77, -105, 64, -105,
+ 51, -105, 109, 61, -105, -105, 48, -105, -105, 152,
+ -105, -105, -105, 79, -105, -105, -105, -105, 4, -105,
+ -16, 153, -105, 74, -105, -105, -11, -105, 0, -105,
+ -105, -105, -105, -105, -105, -105, -5, -105, -105, -105,
+ -105, -105, -105, 68, -105, -105, 41, -105, -105, -105,
+ -105, 90, -105, -1, -105, -105, -105, -105, -105, -93,
+ -105, 32, -105, -4, -105, -105, -105, -105, -22, -105,
+ -105, -14, -105, -105, -105, -105, -105, -105, -26, -105,
+ -105, -2, -105, 60, -105, 53, -105, -105, -105, -105,
+ 65, -105, 76, -105, 78, -105, 72, -105, -105, -105,
+ -105, -105, -105, 21, -105, -105, 85, -105, -105, -105,
+ -105, 22, -105, -105, 180, -105, -105, 33, -105, -105,
+ -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+ -105, -105, -105, -105, -105, -105, 73, -105, -105, -105,
+ -105, -105, -105, -105, 63, -105, -105, -105, -105, -105,
+ -105, 12, -105, -105, -105, -105, -105, -105, -105, -12,
+ -105, -105, -105, -105, -105, -105, -105, 6, -105, -105,
+ -105, -105, -15, -105, -105, 9, -105, -105, -105, -105,
+ -105, -9, -105, -105, -105, -7, -18, -13, -105, -105,
+ -105, -105, -105, 277, 266, -105, -105, -105, -105, -105,
+ -105, -105, 269, 2, 26, -105, 24, -105, 170, 16,
+ -105, -105, 19, -105, -105, 182, -105, -105, -105, 35,
+ -105, -105, -105, -105, 42, -105, 29, 153, -105, 128,
+ -105, -105, -105, -105, -105, -105, 349, -105, -105, -105,
+ -105, -105, 274, -105, -105, -105, 14, -105, -105, 15,
+ 218, -105, -105, -105, 7, -105, -105, -105, -105, -105,
+ -105, 17, -105, -105, -105, -105, -105, -105, -105, -105,
+ -105};
+
+const int QmlJSGrammar::action_info [] = {
+ 345, -114, -106, -92, 343, 345, -95, 254, -122, 450,
+ 549, 187, 437, 413, -119, -117, -106, 454, 249, -92,
+ 248, 345, 454, 339, 340, 342, 349, 233, 98, 606,
+ -125, 398, 388, 386, 254, 396, 254, 96, 441, 144,
+ 98, 450, 167, 161, 138, 606, 437, 443, 554, 463,
+ 96, 630, 437, 68, 437, 546, 180, 406, 337, 427,
+ 161, 184, -96, 445, 428, 421, 176, 421, 421, 413,
+ 417, 411, 525, 322, 186, 454, 146, 405, 289, 535,
+ 400, 450, 309, 309, 315, -96, -122, 437, 269, -117,
+ 298, 138, 293, -119, 509, 413, -114, 521, 519, 301,
+ 532, 554, 68, 328, 330, 269, 291, -95, 303, 424,
+ 138, 55, 504, 138, 539, 289, 474, 522, 440, 0,
+ 534, 332, 56, 431, 138, 163, 169, 524, 523, 164,
+ 620, 619, 441, 138, 324, 239, 238, 246, 245, 59,
+ 138, 138, 311, 553, 169, 170, 312, 138, 138, 138,
+ 60, 138, 0, -125, 425, 626, 625, 596, 174, 410,
+ 409, 55, 55, 170, 475, 415, 138, 246, 245, 554,
+ 253, 252, 56, 56, 551, 550, 246, 245, 244, 243,
+ 138, 82, 466, 83, 55, 485, 505, 325, 138, 82,
+ 0, 83, 452, 334, 84, 56, 82, 100, 83, 456,
+ 251, 347, 84, 307, 82, 597, 83, 505, 169, 84,
+ 505, 511, 61, 517, 505, 138, 101, 84, 102, 531,
+ 530, 527, 0, 541, 138, 0, 169, 170, 0, 403,
+ 0, 0, 507, 538, 537, 467, 465, 82, 61, 83,
+ 61, 435, 434, 506, 138, 170, 0, 403, 542, 540,
+ 84, 623, 622, 507, 505, 0, 507, 62, 32, 507,
+ 507, 169, 0, 63, 506, 512, 510, 506, 515, 514,
+ 506, 506, 0, 0, 0, 528, 526, 232, 231, 32,
+ 170, 621, 171, 62, 32, 62, 169, 616, 32, 63,
+ 0, 63, 139, 0, 169, 45, 47, 46, 0, 0,
+ 507, 617, 615, 32, -83, 170, 0, 171, 0, 0,
+ 0, 506, -83, 170, 32, 171, 45, 47, 46, 32,
+ 0, 45, 47, 46, 32, 45, 47, 46, 32, 0,
+ 0, 614, 271, 272, 82, 32, 83, 0, 0, 0,
+ 45, 47, 46, 4, 3, 2, 1, 84, 271, 272,
+ 32, 45, 47, 46, 32, 0, 45, 47, 46, 273,
+ 274, 45, 47, 46, 32, 45, 47, 46, 0, 276,
+ 277, 0, 45, 47, 46, 273, 274, 32, 278, 0,
+ 0, 279, 0, 280, 0, 0, 0, 45, 47, 46,
+ 32, 45, 47, 46, 0, 0, 0, -336, 0, 32,
+ 0, 45, 47, 46, 0, 0, -336, 70, 71, 276,
+ 277, 0, 0, 0, 45, 47, 46, 0, 278, 0,
+ 0, 279, 0, 280, 0, 0, 0, 45, 47, 46,
+ 0, 75, 76, 0, 72, 73, 45, 47, 46, 77,
+ 78, 75, 76, 79, 0, 80, 0, 0, 0, 77,
+ 78, 75, 76, 79, 0, 80, 0, 0, 0, 77,
+ 78, 75, 76, 79, 0, 80, 0, 0, 0, 77,
+ 78, 75, 76, 79, 32, 80, 0, 0, 0, 77,
+ 78, 0, 32, 79, 0, 80, 0, 276, 277, 0,
+ 32, 0, 0, 0, 0, 0, 278, 0, 32, 279,
+ 0, 280, 0, 0, 0, 0, 242, 241, 0, 0,
+ 0, 45, 47, 46, 237, 236, 0, 0, 0, 45,
+ 47, 46, 237, 236, 0, 0, 0, 45, 47, 46,
+ 237, 236, 148, 0, 0, 45, 47, 46, 0, 0,
+ 0, 0, 149, 0, 0, 0, 150, 0, 0, 0,
+ 0, 0, 0, 0, 0, 151, 0, 152, 0, 0,
+ 0, 0, 32, 0, 0, 0, 0, 0, 153, 0,
+ 154, 59, 0, 0, 0, 0, 0, 0, 155, 0,
+ 0, 156, 60, 0, 0, 0, 0, 157, 148, 0,
+ 0, 0, 0, 158, 242, 241, 0, 0, 149, 45,
+ 47, 46, 150, 0, 0, 0, 0, 0, 0, 159,
+ 0, 151, 0, 152, 0, 0, 305, 0, 0, 0,
+ 0, 0, 0, 0, 153, 0, 154, 59, 0, 28,
+ 29, 148, 0, 0, 155, 0, 0, 156, 60, 31,
+ 0, 149, 0, 157, 0, 150, 32, 0, 0, 158,
+ 33, 34, 0, 35, 151, 0, 152, 0, 0, 0,
+ 496, 0, 0, 0, 42, 159, 0, 153, 0, 154,
+ 59, 0, 0, 0, 0, 0, 0, 155, 0, 0,
+ 156, 60, 48, 45, 47, 46, 157, 49, 0, 0,
+ 0, 0, 158, 0, 0, 0, 0, 0, 41, 51,
+ 30, 0, 0, 0, 38, 0, 0, 0, 159, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 28, 29,
+ 0, 0, 0, 0, 0, 0, 28, 29, 31, 0,
+ 0, 0, 0, 0, 0, 32, 31, 0, 0, 33,
+ 34, 0, 35, 32, 0, 0, 0, 33, 34, 39,
+ 35, 0, 0, 42, 0, 0, 0, 496, 0, 0,
+ 0, 42, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 48, 45, 47, 46, 0, 49, 0, 0, 48,
+ 45, 47, 46, 0, 49, 0, 0, 41, 51, 30,
+ 0, 0, 0, 38, 0, 41, 51, 30, 0, 0,
+ 0, 38, 0, 0, 28, 29, 0, 0, 0, 0,
+ 0, 0, 28, 29, 31, 0, 0, 0, 0, 0,
+ 0, 32, 31, 0, 0, 33, 34, 0, 35, 32,
+ 0, 0, 0, 33, 34, 496, 35, 0, 0, 42,
+ 0, 0, 0, 39, 0, 0, 0, 42, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 48, 45, 47,
+ 46, 0, 49, 0, 0, 48, 45, 47, 46, 0,
+ 49, 0, 0, 41, 51, 30, 0, 0, 0, 38,
+ 0, 41, 51, 30, 0, 0, 0, 38, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 28, 29,
+ 0, 0, 0, 0, 0, 0, 0, 0, 31, 0,
+ 0, 0, 0, 0, 0, 32, 0, 0, 0, 33,
+ 34, 0, 35, 0, 0, 0, 0, 0, 0, 496,
+ 0, 0, 0, 42, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 48, 45, 47, 46, 0, 49, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 41, 51, 30,
+ 0, 0, 0, 38, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 495, 0, 28, 29, 0, 0,
+ 0, 0, 0, 0, 0, 0, 212, 0, 0, 0,
+ 0, 0, 0, 32, 0, 0, 0, 33, 34, 0,
+ 35, 0, 0, 0, 0, 0, 0, 496, 0, 0,
+ 0, 42, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 48,
+ 497, 499, 498, 0, 49, 0, 0, 0, 0, 223,
+ 0, 0, 0, 0, 0, 41, 51, 30, 207, 0,
+ 0, 38, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 495, 0, 28, 29, 0, 0, 0, 0,
+ 0, 0, 0, 0, 212, 0, 0, 0, 0, 0,
+ 0, 32, 0, 0, 0, 33, 34, 0, 35, 0,
+ 0, 0, 0, 0, 0, 496, 0, 0, 0, 42,
+ 0, 0, 0, 0, 0, 0, 0, 600, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 48, 497, 499,
+ 498, 0, 49, 0, 0, 0, 0, 223, 0, 0,
+ 0, 0, 0, 41, 51, 30, 207, 0, 0, 38,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 495, 0, 28, 29, 0, 0, 0, 0, 0, 0,
+ 0, 0, 212, 0, 0, 0, 0, 0, 0, 32,
+ 0, 0, 0, 33, 34, 0, 35, 0, 0, 0,
+ 0, 0, 0, 496, 0, 0, 0, 42, 0, 0,
+ 0, 0, 0, 0, 0, 603, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 48, 497, 499, 498, 0,
+ 49, 0, 0, 0, 0, 223, 0, 0, 0, 0,
+ 0, 41, 51, 30, 207, 0, 0, 38, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 27, 28,
+ 29, 0, 0, 0, 0, 0, 0, 0, 0, 31,
+ 0, 0, 0, 0, 0, 0, 32, 0, 0, 0,
+ 33, 34, 0, 35, 0, 0, 0, 36, 0, 37,
+ 39, 40, 0, 0, 42, 0, 0, 0, 43, 0,
+ 44, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 48, 45, 47, 46, 0, 49, 0, 50,
+ 0, 52, 0, 53, 0, 0, 0, 0, 41, 51,
+ 30, 0, 0, 0, 38, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 27, 28, 29, 0, 0,
+ 0, 0, 0, 0, 0, 0, 31, 0, 0, 0,
+ 0, 0, 0, 32, 0, 0, 0, 33, 34, 0,
+ 35, 0, 0, 0, 36, 0, 37, 39, 40, 0,
+ 0, 42, 0, 0, 0, 43, 0, 44, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 48,
+ 45, 47, 46, 0, 49, 0, 50, 0, 52, 268,
+ 53, 0, 0, 0, 0, 41, 51, 30, 0, 0,
+ 0, 38, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, -115, 0, 0, 0, 27, 28, 29, 0,
+ 0, 0, 0, 0, 0, 0, 0, 31, 0, 0,
+ 0, 0, 0, 0, 32, 0, 0, 0, 33, 34,
+ 0, 35, 0, 0, 0, 36, 0, 37, 39, 40,
+ 0, 0, 42, 0, 0, 0, 43, 0, 44, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 48, 45, 47, 46, 0, 49, 0, 50, 0, 52,
+ 0, 53, 0, 0, 0, 0, 41, 51, 30, 0,
+ 0, 0, 38, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 480, 0, 0, 27, 28, 29, 0,
+ 0, 0, 0, 0, 0, 0, 0, 31, 0, 0,
+ 0, 0, 0, 0, 32, 0, 0, 0, 33, 34,
+ 0, 35, 0, 0, 0, 36, 0, 37, 39, 40,
+ 0, 0, 42, 0, 0, 0, 43, 0, 44, 0,
+ 0, 481, 0, 0, 0, 0, 0, 0, 0, 0,
+ 48, 45, 47, 46, 0, 49, 0, 50, 0, 52,
+ 0, 53, 0, 0, 0, 0, 41, 51, 30, 0,
+ 0, 0, 38, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 27, 28, 29, 0, 0, 0, 0,
+ 0, 0, 0, 0, 31, 0, 0, 0, 0, 0,
+ 0, 32, 214, 0, 0, 561, 562, 0, 35, 0,
+ 0, 0, 36, 0, 37, 39, 40, 0, 0, 42,
+ 0, 0, 0, 43, 0, 44, 0, 0, 0, 0,
+ 0, 0, 0, 218, 0, 0, 0, 48, 45, 47,
+ 46, 0, 49, 0, 50, 0, 52, 0, 53, 0,
+ 0, 0, 0, 41, 51, 30, 0, 0, 0, 38,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 480, 0, 0, 27, 28, 29, 0, 0, 0, 0,
+ 0, 0, 0, 0, 31, 0, 0, 0, 0, 0,
+ 0, 32, 0, 0, 0, 33, 34, 0, 35, 0,
+ 0, 0, 36, 0, 37, 39, 40, 0, 0, 42,
+ 0, 0, 0, 43, 0, 44, 0, 0, 483, 0,
+ 0, 0, 0, 0, 0, 0, 0, 48, 45, 47,
+ 46, 0, 49, 0, 50, 0, 52, 0, 53, 0,
+ 0, 0, 0, 41, 51, 30, 0, 0, 0, 38,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 472, 0, 0, 27, 28, 29, 0, 0, 0, 0,
+ 0, 0, 0, 0, 31, 0, 0, 0, 0, 0,
+ 0, 32, 0, 0, 0, 33, 34, 0, 35, 0,
+ 0, 0, 36, 0, 37, 39, 40, 0, 0, 42,
+ 0, 0, 0, 43, 0, 44, 0, 0, 473, 0,
+ 0, 0, 0, 0, 0, 0, 0, 48, 45, 47,
+ 46, 0, 49, 0, 50, 0, 52, 0, 53, 0,
+ 0, 0, 0, 41, 51, 30, 0, 0, 0, 38,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 472, 0, 0, 27, 28, 29, 0, 0, 0, 0,
+ 0, 0, 0, 0, 31, 0, 0, 0, 0, 0,
+ 0, 32, 0, 0, 0, 33, 34, 0, 35, 0,
+ 0, 0, 36, 0, 37, 39, 40, 0, 0, 42,
+ 0, 0, 0, 43, 0, 44, 0, 0, 478, 0,
+ 0, 0, 0, 0, 0, 0, 0, 48, 45, 47,
+ 46, 0, 49, 0, 50, 0, 52, 0, 53, 0,
+ 0, 0, 0, 41, 51, 30, 0, 0, 0, 38,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 106, 107, 108, 0, 0, 110, 112, 113, 0, 0,
+ 114, 0, 115, 0, 0, 0, 117, 118, 119, 0,
+ 0, 0, 0, 0, 0, 32, 120, 121, 122, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 123,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 126, 0, 0, 0, 0,
+ 0, 0, 45, 47, 46, 127, 128, 129, 0, 131,
+ 132, 133, 134, 135, 136, 0, 0, 124, 130, 116,
+ 109, 111, 125, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 106, 107, 108, 0, 0, 110,
+ 112, 113, 0, 0, 114, 0, 115, 0, 0, 0,
+ 117, 118, 119, 0, 0, 0, 0, 0, 0, 390,
+ 120, 121, 122, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 123, 0, 0, 0, 391, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 126,
+ 0, 0, 0, 0, 0, 395, 392, 394, 0, 127,
+ 128, 129, 0, 131, 132, 133, 134, 135, 136, 0,
+ 0, 124, 130, 116, 109, 111, 125, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 106, 107,
+ 108, 0, 0, 110, 112, 113, 0, 0, 114, 0,
+ 115, 0, 0, 0, 117, 118, 119, 0, 0, 0,
+ 0, 0, 0, 390, 120, 121, 122, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 123, 0, 0,
+ 0, 391, 0, 0, 0, 0, 0, 0, 0, 393,
+ 0, 0, 0, 126, 0, 0, 0, 0, 0, 395,
+ 392, 394, 0, 127, 128, 129, 0, 131, 132, 133,
+ 134, 135, 136, 0, 0, 124, 130, 116, 109, 111,
+ 125, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 206, 0, 0, 0, 0, 208, 0, 27,
+ 28, 29, 210, 0, 0, 0, 0, 0, 0, 211,
+ 31, 0, 0, 0, 0, 0, 0, 213, 214, 0,
+ 0, 215, 34, 0, 35, 0, 0, 0, 36, 0,
+ 37, 39, 40, 0, 0, 42, 0, 0, 0, 43,
+ 0, 44, 0, 0, 0, 0, 0, 217, 0, 218,
+ 0, 0, 0, 48, 216, 219, 46, 220, 49, 221,
+ 50, 222, 52, 223, 53, 224, 225, 0, 0, 41,
+ 51, 30, 207, 209, 0, 38, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 206, 0, 0, 0,
+ 0, 208, 0, 27, 28, 29, 210, 0, 0, 0,
+ 0, 0, 0, 211, 212, 0, 0, 0, 0, 0,
+ 0, 213, 214, 0, 0, 215, 34, 0, 35, 0,
+ 0, 0, 36, 0, 37, 39, 40, 0, 0, 42,
+ 0, 0, 0, 43, 0, 44, 0, 0, 0, 0,
+ 0, 217, 0, 218, 0, 0, 0, 48, 216, 219,
+ 46, 220, 49, 221, 50, 222, 52, 223, 53, 224,
+ 225, 0, 0, 41, 51, 30, 207, 209, 0, 38,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 564, 107, 108, 0, 0, 566, 112, 568, 28, 29,
+ 569, 0, 115, 0, 0, 0, 117, 571, 572, 0,
+ 0, 0, 0, 0, 0, 573, 574, 121, 122, 215,
+ 34, 0, 35, 0, 0, 0, 36, 0, 37, 575,
+ 40, 0, 0, 577, 0, 0, 0, 43, 0, 44,
+ 0, 0, 0, 0, 0, 579, 0, 218, 0, 0,
+ 0, 581, 578, 580, 46, 582, 583, 584, 50, 586,
+ 587, 588, 589, 590, 591, 0, 0, 576, 585, 570,
+ 565, 567, 125, 38, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 358, 107, 108, 0, 0, 360,
+ 112, 362, 28, 29, 363, 0, 115, 0, 0, 0,
+ 117, 365, 366, 0, 0, 0, 0, 0, 0, 367,
+ 368, 121, 122, 215, 34, 0, 35, 0, 0, 0,
+ 36, 0, 37, 369, 40, 0, 0, 371, 0, 0,
+ 0, 43, 0, 44, 0, -261, 0, 0, 0, 373,
+ 0, 218, 0, 0, 0, 375, 372, 374, 46, 376,
+ 377, 378, 50, 380, 381, 382, 383, 384, 385, 0,
+ 0, 370, 379, 364, 359, 361, 125, 38, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ 548, 422, 414, 436, 166, 547, 552, 433, 533, 529,
+ 183, 520, 536, 304, 545, 513, 306, 447, 247, 599,
+ 618, 147, 387, 317, 627, 613, 14, 492, 397, 204,
+ 624, 185, 179, 250, 389, 430, 168, 240, 299, 235,
+ 173, 179, 484, 407, 336, 433, 308, 348, 436, 346,
+ 433, 350, 247, 469, 464, 482, 331, 429, 333, 344,
+ 335, 179, 299, 247, 240, 432, 479, 140, 451, 240,
+ 442, 145, 446, 444, 457, 235, 160, 235, 453, 399,
+ 458, 455, 299, 137, 516, 143, 508, 426, 436, 204,
+ 0, 204, 412, 0, 0, 0, 0, 0, 458, 103,
+ 0, 143, 0, 0, 143, 0, 404, 0, 57, 175,
+ 299, 0, 57, 91, 177, 183, 57, 57, 449, 0,
+ 299, 105, 90, 57, 57, 57, 57, 0, 89, 88,
+ 57, 94, 95, 57, 57, 81, 65, 57, 263, 57,
+ 57, 486, 285, 267, 86, 57, 57, 64, 57, 165,
+ 87, 57, 57, 177, 57, 57, 57, 284, 57, 283,
+ 97, 282, 85, 401, 57, 99, 57, 57, 468, 92,
+ 57, 281, 449, 300, 57, 69, 491, 57, 57, 449,
+ 317, 57, 57, 327, 58, 67, 57, 341, 66, 401,
+ 234, 402, 162, 401, 299, 57, 57, 448, 57, 338,
+ 489, 57, 74, 488, 57, 57, 57, 487, 490, 477,
+ 93, 57, 57, 476, 177, 295, 267, 402, 295, 295,
+ 267, 402, 0, 267, 267, 295, 57, 494, 313, 494,
+ 267, 267, 628, 0, 57, 270, 595, 323, 103, 267,
+ 314, 294, 493, 503, 57, 292, 0, 316, 57, 267,
+ 295, 288, 326, 267, 57, 267, 0, 329, 299, 267,
+ 105, 172, 0, 310, 57, 0, 0, 290, 57, 267,
+ 601, 275, 297, 267, 57, 286, 0, 494, 604, 267,
+ 592, 287, 0, 594, 0, 494, 0, 595, 560, 0,
+ 0, 0, 493, 503, 0, 563, 556, 557, 558, 559,
+ 493, 503, 469, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 302, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 494, 0, 0, 598, 0, 0, 0, 595, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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 QmlJSGrammar::action_check [] = {
+ 36, 7, 7, 7, 7, 36, 7, 36, 7, 36,
+ 60, 33, 33, 36, 7, 7, 7, 36, 36, 7,
+ 77, 36, 36, 60, 33, 55, 16, 55, 79, 90,
+ 7, 55, 8, 7, 36, 7, 36, 48, 20, 8,
+ 79, 36, 7, 2, 8, 90, 33, 36, 33, 17,
+ 48, 0, 33, 1, 33, 8, 36, 7, 36, 55,
+ 2, 8, 7, 60, 7, 5, 60, 5, 5, 36,
+ 33, 7, 29, 17, 60, 36, 60, 60, 48, 7,
+ 55, 36, 2, 2, 7, 7, 7, 33, 1, 7,
+ 61, 8, 8, 7, 29, 36, 7, 24, 37, 61,
+ 66, 33, 1, 61, 60, 1, 79, 7, 60, 10,
+ 8, 40, 66, 8, 29, 48, 8, 29, 6, -1,
+ 29, 31, 51, 7, 8, 50, 15, 61, 62, 54,
+ 61, 62, 20, 8, 8, 61, 62, 61, 62, 42,
+ 8, 8, 50, 7, 15, 34, 54, 8, 8, 8,
+ 53, 8, -1, 7, 55, 61, 62, 8, 56, 61,
+ 62, 40, 40, 34, 56, 60, 8, 61, 62, 33,
+ 61, 62, 51, 51, 61, 62, 61, 62, 61, 62,
+ 8, 25, 8, 27, 40, 60, 29, 61, 8, 25,
+ -1, 27, 60, 60, 38, 51, 25, 15, 27, 60,
+ 60, 60, 38, 60, 25, 56, 27, 29, 15, 38,
+ 29, 7, 12, 29, 29, 8, 34, 38, 36, 61,
+ 62, 7, -1, 36, 8, -1, 15, 34, -1, 36,
+ -1, -1, 75, 61, 62, 61, 62, 25, 12, 27,
+ 12, 61, 62, 86, 8, 34, -1, 36, 61, 62,
+ 38, 61, 62, 75, 29, -1, 75, 57, 29, 75,
+ 75, 15, -1, 63, 86, 61, 62, 86, 61, 62,
+ 86, 86, -1, -1, -1, 61, 62, 61, 62, 29,
+ 34, 91, 36, 57, 29, 57, 15, 47, 29, 63,
+ -1, 63, 56, -1, 15, 66, 67, 68, -1, -1,
+ 75, 61, 62, 29, 33, 34, -1, 36, -1, -1,
+ -1, 86, 33, 34, 29, 36, 66, 67, 68, 29,
+ -1, 66, 67, 68, 29, 66, 67, 68, 29, -1,
+ -1, 91, 18, 19, 25, 29, 27, -1, -1, -1,
+ 66, 67, 68, 92, 93, 94, 95, 38, 18, 19,
+ 29, 66, 67, 68, 29, -1, 66, 67, 68, 45,
+ 46, 66, 67, 68, 29, 66, 67, 68, -1, 23,
+ 24, -1, 66, 67, 68, 45, 46, 29, 32, -1,
+ -1, 35, -1, 37, -1, -1, -1, 66, 67, 68,
+ 29, 66, 67, 68, -1, -1, -1, 36, -1, 29,
+ -1, 66, 67, 68, -1, -1, 36, 18, 19, 23,
+ 24, -1, -1, -1, 66, 67, 68, -1, 32, -1,
+ -1, 35, -1, 37, -1, -1, -1, 66, 67, 68,
+ -1, 23, 24, -1, 45, 46, 66, 67, 68, 31,
+ 32, 23, 24, 35, -1, 37, -1, -1, -1, 31,
+ 32, 23, 24, 35, -1, 37, -1, -1, -1, 31,
+ 32, 23, 24, 35, -1, 37, -1, -1, -1, 31,
+ 32, 23, 24, 35, 29, 37, -1, -1, -1, 31,
+ 32, -1, 29, 35, -1, 37, -1, 23, 24, -1,
+ 29, -1, -1, -1, -1, -1, 32, -1, 29, 35,
+ -1, 37, -1, -1, -1, -1, 61, 62, -1, -1,
+ -1, 66, 67, 68, 61, 62, -1, -1, -1, 66,
+ 67, 68, 61, 62, -1, -1, -1, 66, 67, 68,
+ 61, 62, 3, -1, -1, 66, 67, 68, -1, -1,
+ -1, -1, 13, -1, -1, -1, 17, -1, -1, -1,
+ -1, -1, -1, -1, -1, 26, -1, 28, -1, -1,
+ -1, -1, 29, -1, -1, -1, -1, -1, 39, -1,
+ 41, 42, -1, -1, -1, -1, -1, -1, 49, -1,
+ -1, 52, 53, -1, -1, -1, -1, 58, 3, -1,
+ -1, -1, -1, 64, 61, 62, -1, -1, 13, 66,
+ 67, 68, 17, -1, -1, -1, -1, -1, -1, 80,
+ -1, 26, -1, 28, -1, -1, 31, -1, -1, -1,
+ -1, -1, -1, -1, 39, -1, 41, 42, -1, 12,
+ 13, 3, -1, -1, 49, -1, -1, 52, 53, 22,
+ -1, 13, -1, 58, -1, 17, 29, -1, -1, 64,
+ 33, 34, -1, 36, 26, -1, 28, -1, -1, -1,
+ 43, -1, -1, -1, 47, 80, -1, 39, -1, 41,
+ 42, -1, -1, -1, -1, -1, -1, 49, -1, -1,
+ 52, 53, 65, 66, 67, 68, 58, 70, -1, -1,
+ -1, -1, 64, -1, -1, -1, -1, -1, 81, 82,
+ 83, -1, -1, -1, 87, -1, -1, -1, 80, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 12, 13,
+ -1, -1, -1, -1, -1, -1, 12, 13, 22, -1,
+ -1, -1, -1, -1, -1, 29, 22, -1, -1, 33,
+ 34, -1, 36, 29, -1, -1, -1, 33, 34, 43,
+ 36, -1, -1, 47, -1, -1, -1, 43, -1, -1,
+ -1, 47, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 65, 66, 67, 68, -1, 70, -1, -1, 65,
+ 66, 67, 68, -1, 70, -1, -1, 81, 82, 83,
+ -1, -1, -1, 87, -1, 81, 82, 83, -1, -1,
+ -1, 87, -1, -1, 12, 13, -1, -1, -1, -1,
+ -1, -1, 12, 13, 22, -1, -1, -1, -1, -1,
+ -1, 29, 22, -1, -1, 33, 34, -1, 36, 29,
+ -1, -1, -1, 33, 34, 43, 36, -1, -1, 47,
+ -1, -1, -1, 43, -1, -1, -1, 47, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 65, 66, 67,
+ 68, -1, 70, -1, -1, 65, 66, 67, 68, -1,
+ 70, -1, -1, 81, 82, 83, -1, -1, -1, 87,
+ -1, 81, 82, 83, -1, -1, -1, 87, -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, 68, -1, 70, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 81, 82, 83,
+ -1, -1, -1, 87, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 10, -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, 68, -1, 70, -1, -1, -1, -1, 75,
+ -1, -1, -1, -1, -1, 81, 82, 83, 84, -1,
+ -1, 87, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 10, -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, 55, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 65, 66, 67,
+ 68, -1, 70, -1, -1, -1, -1, 75, -1, -1,
+ -1, -1, -1, 81, 82, 83, 84, -1, -1, 87,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 10, -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, 55, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 65, 66, 67, 68, -1,
+ 70, -1, -1, -1, -1, 75, -1, -1, -1, -1,
+ -1, 81, 82, 83, 84, -1, -1, 87, -1, -1,
+ -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, 68, -1, 70, -1, 72,
+ -1, 74, -1, 76, -1, -1, -1, -1, 81, 82,
+ 83, -1, -1, -1, 87, -1, -1, -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, 68, -1, 70, -1, 72, -1, 74, 75,
+ 76, -1, -1, -1, -1, 81, 82, 83, -1, -1,
+ -1, 87, -1, -1, -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, 68, -1, 70, -1, 72, -1, 74,
+ -1, 76, -1, -1, -1, -1, 81, 82, 83, -1,
+ -1, -1, 87, -1, -1, -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, 68, -1, 70, -1, 72, -1, 74,
+ -1, 76, -1, -1, -1, -1, 81, 82, 83, -1,
+ -1, -1, 87, -1, -1, -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, 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,
+ 68, -1, 70, -1, 72, -1, 74, -1, 76, -1,
+ -1, -1, -1, 81, 82, 83, -1, -1, -1, 87,
+ -1, -1, -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,
+ 68, -1, 70, -1, 72, -1, 74, -1, 76, -1,
+ -1, -1, -1, 81, 82, 83, -1, -1, -1, 87,
+ -1, -1, -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,
+ 68, -1, 70, -1, 72, -1, 74, -1, 76, -1,
+ -1, -1, -1, 81, 82, 83, -1, -1, -1, 87,
+ -1, -1, -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,
+ 68, -1, 70, -1, 72, -1, 74, -1, 76, -1,
+ -1, -1, -1, 81, 82, 83, -1, -1, -1, 87,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 4, 5, 6, -1, -1, 9, 10, 11, -1, -1,
+ 14, -1, 16, -1, -1, -1, 20, 21, 22, -1,
+ -1, -1, -1, -1, -1, 29, 30, 31, 32, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 43,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 59, -1, -1, -1, -1,
+ -1, -1, 66, 67, 68, 69, 70, 71, -1, 73,
+ 74, 75, 76, 77, 78, -1, -1, 81, 82, 83,
+ 84, 85, 86, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4, 5, 6, -1, -1, 9,
+ 10, 11, -1, -1, 14, -1, 16, -1, -1, -1,
+ 20, 21, 22, -1, -1, -1, -1, -1, -1, 29,
+ 30, 31, 32, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 43, -1, -1, -1, 47, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 59,
+ -1, -1, -1, -1, -1, 65, 66, 67, -1, 69,
+ 70, 71, -1, 73, 74, 75, 76, 77, 78, -1,
+ -1, 81, 82, 83, 84, 85, 86, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 4, 5,
+ 6, -1, -1, 9, 10, 11, -1, -1, 14, -1,
+ 16, -1, -1, -1, 20, 21, 22, -1, -1, -1,
+ -1, -1, -1, 29, 30, 31, 32, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 43, -1, -1,
+ -1, 47, -1, -1, -1, -1, -1, -1, -1, 55,
+ -1, -1, -1, 59, -1, -1, -1, -1, -1, 65,
+ 66, 67, -1, 69, 70, 71, -1, 73, 74, 75,
+ 76, 77, 78, -1, -1, 81, 82, 83, 84, 85,
+ 86, -1, -1, -1, -1, -1, -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, 78, -1, -1, 81,
+ 82, 83, 84, 85, -1, 87, -1, -1, -1, -1,
+ -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,
+ 78, -1, -1, 81, 82, 83, 84, 85, -1, 87,
+ -1, -1, -1, -1, -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, 78, -1, -1, 81, 82, 83,
+ 84, 85, 86, 87, -1, -1, -1, -1, -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, 55, -1, -1, -1, 59,
+ -1, 61, -1, -1, -1, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, -1,
+ -1, 81, 82, 83, 84, 85, 86, 87, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+
+ 13, 94, 3, 19, 33, 23, 13, 3, 23, 3,
+ 13, 23, 3, 2, 23, 3, 3, 19, 2, 17,
+ 13, 65, 33, 13, 9, 11, 3, 2, 33, 2,
+ 13, 13, 13, 3, 34, 3, 33, 13, 3, 13,
+ 3, 13, 3, 2, 13, 3, 2, 2, 19, 3,
+ 3, 2, 2, 33, 33, 33, 2, 79, 3, 2,
+ 2, 13, 3, 2, 13, 79, 33, 33, 3, 13,
+ 96, 33, 19, 13, 2, 13, 33, 13, 2, 2,
+ 13, 3, 3, 3, 11, 33, 23, 91, 19, 2,
+ -1, 2, 2, -1, -1, -1, -1, -1, 13, 13,
+ -1, 33, -1, -1, 33, -1, 38, -1, 42, 38,
+ 3, -1, 42, 47, 44, 13, 42, 42, 44, -1,
+ 3, 35, 47, 42, 42, 42, 42, -1, 47, 47,
+ 42, 48, 48, 42, 42, 47, 44, 42, 42, 42,
+ 42, 44, 47, 47, 46, 42, 42, 44, 42, 58,
+ 46, 42, 42, 44, 42, 42, 42, 47, 42, 47,
+ 54, 47, 46, 11, 42, 52, 42, 42, 83, 47,
+ 42, 47, 44, 66, 42, 50, 44, 42, 42, 44,
+ 13, 42, 42, 66, 45, 45, 42, 98, 44, 11,
+ 103, 39, 56, 11, 3, 42, 42, 44, 42, 97,
+ 44, 42, 48, 44, 42, 42, 42, 44, 44, 29,
+ 48, 42, 42, 33, 44, 42, 47, 39, 42, 42,
+ 47, 39, -1, 47, 47, 42, 42, 11, 59, 11,
+ 47, 47, 14, -1, 42, 51, 18, 64, 13, 47,
+ 64, 64, 26, 27, 42, 53, -1, 64, 42, 47,
+ 42, 49, 85, 47, 42, 47, -1, 66, 3, 47,
+ 35, 36, -1, 57, 42, -1, -1, 55, 42, 47,
+ 4, 49, 64, 47, 42, 49, -1, 11, 4, 47,
+ 11, 49, -1, 14, -1, 11, -1, 18, 11, -1,
+ -1, -1, 26, 27, -1, 18, 19, 20, 21, 22,
+ 26, 27, 33, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 66, -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,
+ 11, -1, -1, 14, -1, -1, -1, 18, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1};
+
diff --git a/src/plugins/qmldesigner/core/filemanager/parser/qmljsgrammar_p.h b/src/plugins/qmldesigner/core/filemanager/parser/qmljsgrammar_p.h
new file mode 100644
index 0000000000..7de77c03a0
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/parser/qmljsgrammar_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).
+** All rights reserved.
+** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@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 QMLJSGRAMMAR_P_H
+#define QMLJSGRAMMAR_P_H
+
+class QmlJSGrammar
+{
+public:
+ enum {
+ EOF_SYMBOL = 0,
+ REDUCE_HERE = 97,
+ SHIFT_THERE = 96,
+ T_AND = 1,
+ T_AND_AND = 2,
+ T_AND_EQ = 3,
+ T_AS = 91,
+ T_AUTOMATIC_SEMICOLON = 62,
+ T_BREAK = 4,
+ T_CASE = 5,
+ T_CATCH = 6,
+ T_COLON = 7,
+ T_COMMA = 8,
+ T_COMMENT = 88,
+ T_CONST = 84,
+ T_CONTINUE = 9,
+ T_DEBUGGER = 85,
+ 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 = 83,
+ T_FEED_JS_EXPRESSION = 95,
+ T_FEED_JS_STATEMENT = 94,
+ T_FEED_UI_OBJECT_MEMBER = 93,
+ T_FEED_UI_PROGRAM = 92,
+ 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 = 90,
+ 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 = 87,
+ T_NEW = 43,
+ T_NOT = 44,
+ T_NOT_EQ = 45,
+ T_NOT_EQ_EQ = 46,
+ T_NULL = 81,
+ 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 = 89,
+ T_QUESTION = 54,
+ T_RBRACE = 55,
+ T_RBRACKET = 56,
+ T_READONLY = 68,
+ T_REMAINDER = 57,
+ T_REMAINDER_EQ = 58,
+ T_RESERVED_WORD = 86,
+ 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 = 69,
+ T_THIS = 70,
+ T_THROW = 71,
+ T_TILDE = 72,
+ T_TRUE = 82,
+ T_TRY = 73,
+ T_TYPEOF = 74,
+ T_VAR = 75,
+ T_VOID = 76,
+ T_WHILE = 77,
+ T_WITH = 78,
+ T_XOR = 79,
+ T_XOR_EQ = 80,
+
+ ACCEPT_STATE = 630,
+ RULE_COUNT = 340,
+ STATE_COUNT = 631,
+ TERMINAL_COUNT = 98,
+ NON_TERMINAL_COUNT = 105,
+
+ GOTO_INDEX_OFFSET = 631,
+ GOTO_INFO_OFFSET = 2618,
+ GOTO_CHECK_OFFSET = 2618
+ };
+
+ 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 // QMLJSGRAMMAR_P_H
+
diff --git a/src/plugins/qmldesigner/core/filemanager/parser/qmljslexer.cpp b/src/plugins/qmldesigner/core/filemanager/parser/qmljslexer.cpp
new file mode 100644
index 0000000000..a52ea7c089
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/parser/qmljslexer.cpp
@@ -0,0 +1,1141 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "qmljsglobal_p.h"
+#include "qmljsengine_p.h"
+#include "qmljslexer_p.h"
+#include "qmljsgrammar_p.h"
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+QT_QML_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 QmlJS {
+extern double integerFromString(const char *buf, int size, int radix);
+}
+
+using namespace QmlJS;
+
+Lexer::Lexer(Engine *eng, bool tokenizeComments)
+ : 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),
+ tokenizeComments(tokenizeComments)
+{
+ 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 QmlJSGrammar::T_DO;
+ else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('f'))
+ return QmlJSGrammar::T_IF;
+ else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n'))
+ return QmlJSGrammar::T_IN;
+ else if (c[0] == QLatin1Char('a') && c[1] == QLatin1Char('s'))
+ return QmlJSGrammar::T_AS;
+ } break;
+
+ case 3: {
+ if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('o') && c[2] == QLatin1Char('r'))
+ return QmlJSGrammar::T_FOR;
+ else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('e') && c[2] == QLatin1Char('w'))
+ return QmlJSGrammar::T_NEW;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r') && c[2] == QLatin1Char('y'))
+ return QmlJSGrammar::T_TRY;
+ else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('a') && c[2] == QLatin1Char('r'))
+ return QmlJSGrammar::T_VAR;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n') && c[2] == QLatin1Char('t'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 4: {
+ if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('a')
+ && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('e'))
+ return QmlJSGrammar::T_CASE;
+ else if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('l')
+ && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('e'))
+ return QmlJSGrammar::T_ELSE;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('s'))
+ return QmlJSGrammar::T_THIS;
+ else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('d'))
+ return QmlJSGrammar::T_VOID;
+ else if (c[0] == QLatin1Char('w') && c[1] == QLatin1Char('i')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('h'))
+ return QmlJSGrammar::T_WITH;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r')
+ && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('e'))
+ return QmlJSGrammar::T_TRUE;
+ else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('u')
+ && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('l'))
+ return QmlJSGrammar::T_NULL;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('n')
+ && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('m'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('y')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('l') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('g'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('r'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('g') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('o'))
+ return QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::T_PROPERTY;
+ else if (c[0] == QLatin1Char('r') && c[1] == QLatin1Char('e')
+ && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('d')
+ && c[4] == QLatin1Char('o') && c[5] == QLatin1Char('n')
+ && c[6] == QLatin1Char('l') && c[7] == QLatin1Char('y'))
+ return QmlJSGrammar::T_READONLY;
+ 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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 QmlJSGrammar::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 = QmlJSGrammar::T_SEMICOLON;
+ stackToken = 0;
+ setDone(Other);
+ } else {
+ setDone(Eof);
+ }
+ } else if (isLineTerminator()) {
+ shiftWindowsLineBreak();
+ yylineno++;
+ yycolumn = 0;
+ bol = true;
+ terminator = true;
+ syncProhibitAutomaticSemicolon();
+ if (restrKeyword) {
+ token = QmlJSGrammar::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 == QmlJSGrammar::T_PLUS_PLUS
+ || token == QmlJSGrammar::T_MINUS_MINUS)) {
+ // automatic semicolon insertion
+ stackToken = token;
+ token = QmlJSGrammar::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 = QmlJSGrammar::T_SEMICOLON;
+ setDone(Other);
+ } else
+ state = Start;
+ driver->addComment(startpos, tokenLength(), startlineno, startcolumn);
+ } else if (current == 0) {
+ driver->addComment(startpos, tokenLength(), startlineno, startcolumn);
+ setDone(Eof);
+ }
+
+ break;
+ case InMultiLineComment:
+ if (current == 0) {
+ setDone(Bad);
+ err = UnclosedComment;
+ errmsg = QLatin1String("Unclosed comment at end of file");
+ driver->addComment(startpos, tokenLength(), startlineno, startcolumn);
+ } else if (isLineTerminator()) {
+ shiftWindowsLineBreak();
+ yylineno++;
+ } else if (current == '*' && next1 == '/') {
+ state = Start;
+ shift(1);
+ driver->addComment(startpos, tokenLength(), startlineno, startcolumn);
+ }
+
+ break;
+ case InIdentifier:
+ if (isIdentLetter(current) || isDecimalDigit(current)) {
+ record16(current);
+ break;
+ }
+ setDone(Identifier);
+ break;
+ case InNum0:
+ if (current == 'x' || current == 'X') {
+ record8(current);
+ state = InHex;
+ } else if (current == '.') {
+ record8(current);
+ state = InDecimal;
+ } else if (current == 'e' || current == 'E') {
+ record8(current);
+ state = InExponentIndicator;
+ } else if (isOctalDigit(current)) {
+ record8(current);
+ state = InOctal;
+ } else if (isDecimalDigit(current)) {
+ record8(current);
+ state = InDecimal;
+ } else {
+ setDone(Number);
+ }
+ break;
+ case InHex:
+ if (isHexDigit(current))
+ record8(current);
+ else
+ setDone(Hex);
+ break;
+ case InOctal:
+ if (isOctalDigit(current)) {
+ record8(current);
+ } else if (isDecimalDigit(current)) {
+ record8(current);
+ state = InDecimal;
+ } else {
+ setDone(Octal);
+ }
+ break;
+ case InNum:
+ if (isDecimalDigit(current)) {
+ record8(current);
+ } else if (current == '.') {
+ record8(current);
+ state = InDecimal;
+ } else if (current == 'e' || current == 'E') {
+ record8(current);
+ state = InExponentIndicator;
+ } else {
+ setDone(Number);
+ }
+ break;
+ case InDecimal:
+ if (isDecimalDigit(current)) {
+ record8(current);
+ } else if (current == 'e' || current == 'E') {
+ record8(current);
+ state = InExponentIndicator;
+ } else {
+ setDone(Number);
+ }
+ break;
+ case InExponentIndicator:
+ if (current == '+' || current == '-') {
+ record8(current);
+ } else if (isDecimalDigit(current)) {
+ record8(current);
+ state = InExponent;
+ } else {
+ setDone(Bad);
+ err = IllegalExponentIndicator;
+ errmsg = QLatin1String("Illegal syntax for exponential number");
+ }
+ break;
+ case InExponent:
+ if (isDecimalDigit(current)) {
+ record8(current);
+ } else {
+ setDone(Number);
+ }
+ break;
+ default:
+ Q_ASSERT_X(0, "Lexer::lex", "Unhandled state in switch statement");
+ }
+
+ // move on to the next character
+ if (!done)
+ shift(1);
+ if (state != Start && state != InSingleLineComment)
+ bol = false;
+ }
+
+ // no identifiers allowed directly after numeric literal, e.g. "3in" is bad
+ if ((state == Number || state == Octal || state == Hex)
+ && isIdentLetter(current)) {
+ state = Bad;
+ err = IllegalIdentifier;
+ errmsg = QLatin1String("Identifier cannot start with numeric literal");
+ }
+
+ // terminate string
+ buffer8[pos8] = '\0';
+
+ double dval = 0;
+ if (state == Number) {
+ dval = qstrtod(buffer8, 0, 0);
+ } else if (state == Hex) { // scan hex numbers
+ dval = 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 == QmlJSGrammar::T_RPAREN) {
+ --parenthesesCount;
+ if (parenthesesCount == 0)
+ parenthesesState = BalancedParentheses;
+ } else if (token == QmlJSGrammar::T_LPAREN) {
+ ++parenthesesCount;
+ }
+ break;
+ case BalancedParentheses:
+ parenthesesState = IgnoreParentheses;
+ break;
+ }
+
+ switch (state) {
+ case Eof:
+ return 0;
+ case Other:
+ if (token == QmlJSGrammar::T_RBRACE || token == QmlJSGrammar::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 QmlJSGrammar::T_IDENTIFIER;
+ }
+ if (token == QmlJSGrammar::T_CONTINUE || token == QmlJSGrammar::T_BREAK
+ || token == QmlJSGrammar::T_RETURN || token == QmlJSGrammar::T_THROW) {
+ restrKeyword = true;
+ } else if (token == QmlJSGrammar::T_IF || token == QmlJSGrammar::T_FOR
+ || token == QmlJSGrammar::T_WHILE || token == QmlJSGrammar::T_WITH) {
+ parenthesesState = CountParentheses;
+ parenthesesCount = 0;
+ } else if (token == QmlJSGrammar::T_DO) {
+ parenthesesState = BalancedParentheses;
+ }
+ return token;
+ case String:
+ if (driver)
+ qsyylval.ustr = driver->intern(buffer16, pos16);
+ else
+ qsyylval.ustr = 0;
+ return multiLineString?QmlJSGrammar::T_MULTILINE_STRING_LITERAL:QmlJSGrammar::T_STRING_LITERAL;
+ case Number:
+ qsyylval.dval = dval;
+ return QmlJSGrammar::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 QmlJSGrammar::T_GT_GT_GT_EQ;
+ } else if (c1 == '=' && c2 == '=' && c3 == '=') {
+ shift(3);
+ return QmlJSGrammar::T_EQ_EQ_EQ;
+ } else if (c1 == '!' && c2 == '=' && c3 == '=') {
+ shift(3);
+ return QmlJSGrammar::T_NOT_EQ_EQ;
+ } else if (c1 == '>' && c2 == '>' && c3 == '>') {
+ shift(3);
+ return QmlJSGrammar::T_GT_GT_GT;
+ } else if (c1 == '<' && c2 == '<' && c3 == '=') {
+ shift(3);
+ return QmlJSGrammar::T_LT_LT_EQ;
+ } else if (c1 == '>' && c2 == '>' && c3 == '=') {
+ shift(3);
+ return QmlJSGrammar::T_GT_GT_EQ;
+ } else if (c1 == '<' && c2 == '=') {
+ shift(2);
+ return QmlJSGrammar::T_LE;
+ } else if (c1 == '>' && c2 == '=') {
+ shift(2);
+ return QmlJSGrammar::T_GE;
+ } else if (c1 == '!' && c2 == '=') {
+ shift(2);
+ return QmlJSGrammar::T_NOT_EQ;
+ } else if (c1 == '+' && c2 == '+') {
+ shift(2);
+ return QmlJSGrammar::T_PLUS_PLUS;
+ } else if (c1 == '-' && c2 == '-') {
+ shift(2);
+ return QmlJSGrammar::T_MINUS_MINUS;
+ } else if (c1 == '=' && c2 == '=') {
+ shift(2);
+ return QmlJSGrammar::T_EQ_EQ;
+ } else if (c1 == '+' && c2 == '=') {
+ shift(2);
+ return QmlJSGrammar::T_PLUS_EQ;
+ } else if (c1 == '-' && c2 == '=') {
+ shift(2);
+ return QmlJSGrammar::T_MINUS_EQ;
+ } else if (c1 == '*' && c2 == '=') {
+ shift(2);
+ return QmlJSGrammar::T_STAR_EQ;
+ } else if (c1 == '/' && c2 == '=') {
+ shift(2);
+ return QmlJSGrammar::T_DIVIDE_EQ;
+ } else if (c1 == '&' && c2 == '=') {
+ shift(2);
+ return QmlJSGrammar::T_AND_EQ;
+ } else if (c1 == '^' && c2 == '=') {
+ shift(2);
+ return QmlJSGrammar::T_XOR_EQ;
+ } else if (c1 == '%' && c2 == '=') {
+ shift(2);
+ return QmlJSGrammar::T_REMAINDER_EQ;
+ } else if (c1 == '|' && c2 == '=') {
+ shift(2);
+ return QmlJSGrammar::T_OR_EQ;
+ } else if (c1 == '<' && c2 == '<') {
+ shift(2);
+ return QmlJSGrammar::T_LT_LT;
+ } else if (c1 == '>' && c2 == '>') {
+ shift(2);
+ return QmlJSGrammar::T_GT_GT;
+ } else if (c1 == '&' && c2 == '&') {
+ shift(2);
+ return QmlJSGrammar::T_AND_AND;
+ } else if (c1 == '|' && c2 == '|') {
+ shift(2);
+ return QmlJSGrammar::T_OR_OR;
+ }
+
+ switch(c1) {
+ case '=': shift(1); return QmlJSGrammar::T_EQ;
+ case '>': shift(1); return QmlJSGrammar::T_GT;
+ case '<': shift(1); return QmlJSGrammar::T_LT;
+ case ',': shift(1); return QmlJSGrammar::T_COMMA;
+ case '!': shift(1); return QmlJSGrammar::T_NOT;
+ case '~': shift(1); return QmlJSGrammar::T_TILDE;
+ case '?': shift(1); return QmlJSGrammar::T_QUESTION;
+ case ':': shift(1); return QmlJSGrammar::T_COLON;
+ case '.': shift(1); return QmlJSGrammar::T_DOT;
+ case '+': shift(1); return QmlJSGrammar::T_PLUS;
+ case '-': shift(1); return QmlJSGrammar::T_MINUS;
+ case '*': shift(1); return QmlJSGrammar::T_STAR;
+ case '/': shift(1); return QmlJSGrammar::T_DIVIDE_;
+ case '&': shift(1); return QmlJSGrammar::T_AND;
+ case '|': shift(1); return QmlJSGrammar::T_OR;
+ case '^': shift(1); return QmlJSGrammar::T_XOR;
+ case '%': shift(1); return QmlJSGrammar::T_REMAINDER;
+ case '(': shift(1); return QmlJSGrammar::T_LPAREN;
+ case ')': shift(1); return QmlJSGrammar::T_RPAREN;
+ case '{': shift(1); return QmlJSGrammar::T_LBRACE;
+ case '}': shift(1); return QmlJSGrammar::T_RBRACE;
+ case '[': shift(1); return QmlJSGrammar::T_LBRACKET;
+ case ']': shift(1); return QmlJSGrammar::T_RBRACKET;
+ case ';': shift(1); return QmlJSGrammar::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_QML_END_NAMESPACE
+
+
diff --git a/src/plugins/qmldesigner/core/filemanager/parser/qmljslexer_p.h b/src/plugins/qmldesigner/core/filemanager/parser/qmljslexer_p.h
new file mode 100644
index 0000000000..1be466c3e6
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/parser/qmljslexer_p.h
@@ -0,0 +1,237 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef QMLJSLEXER_P_H
+#define QMLJSLEXER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/QString>
+
+#include "qmljsglobal_p.h"
+
+QT_QML_BEGIN_NAMESPACE
+
+namespace QmlJS {
+
+class Engine;
+class NameId;
+
+class Lexer
+{
+public:
+ Lexer(Engine *eng, bool tokenizeComments = false);
+ ~Lexer();
+
+ void setCode(const QString &c, int lineno);
+ int lex();
+
+ int currentLineNo() const { return yylineno; }
+ int currentColumnNo() const { return yycolumn; }
+
+ int tokenOffset() const { return startpos; }
+ int tokenLength() const { return pos - startpos; }
+
+ int startLineNo() const { return startlineno; }
+ int startColumnNo() const { return startcolumn; }
+
+ int endLineNo() const { return currentLineNo(); }
+ int endColumnNo() const
+ { int col = currentColumnNo(); return (col > 0) ? col - 1 : col; }
+
+ bool prevTerminator() const { return terminator; }
+
+ enum State { Start,
+ Identifier,
+ InIdentifier,
+ InSingleLineComment,
+ InMultiLineComment,
+ InNum,
+ InNum0,
+ InHex,
+ InOctal,
+ InDecimal,
+ InExponentIndicator,
+ InExponent,
+ Hex,
+ Octal,
+ Number,
+ String,
+ Eof,
+ InString,
+ InEscapeSequence,
+ InHexEscape,
+ InUnicodeEscape,
+ Other,
+ Bad };
+
+ enum Error {
+ NoError,
+ IllegalCharacter,
+ UnclosedStringLiteral,
+ IllegalEscapeSequence,
+ IllegalUnicodeEscapeSequence,
+ UnclosedComment,
+ IllegalExponentIndicator,
+ IllegalIdentifier
+ };
+
+ enum ParenthesesState {
+ IgnoreParentheses,
+ CountParentheses,
+ BalancedParentheses
+ };
+
+ enum RegExpBodyPrefix {
+ NoPrefix,
+ EqualPrefix
+ };
+
+ bool scanRegExp(RegExpBodyPrefix prefix = NoPrefix);
+
+ 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;
+ bool tokenizeComments;
+};
+
+} // namespace QmlJS
+
+QT_QML_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qmldesigner/core/filemanager/parser/qmljsmemorypool_p.h b/src/plugins/qmldesigner/core/filemanager/parser/qmljsmemorypool_p.h
new file mode 100644
index 0000000000..4b79f174fb
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/parser/qmljsmemorypool_p.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef QMLJSMEMORYPOOL_P_H
+#define QMLJSMEMORYPOOL_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>
+
+#include "qmljsglobal_p.h"
+
+QT_QML_BEGIN_NAMESPACE
+
+namespace QmlJS {
+
+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 QmlJS
+
+QT_QML_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qmldesigner/core/filemanager/parser/qmljsnodepool_p.h b/src/plugins/qmldesigner/core/filemanager/parser/qmljsnodepool_p.h
new file mode 100644
index 0000000000..ba0c3678ef
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/parser/qmljsnodepool_p.h
@@ -0,0 +1,127 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef QMLJSNODEPOOL_P_H
+#define QMLJSNODEPOOL_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 "qmljsglobal_p.h"
+#include "qmljsmemorypool_p.h"
+
+QT_QML_BEGIN_NAMESPACE
+
+namespace QmlJS {
+
+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 QmlJS
+
+QT_QML_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qmldesigner/core/filemanager/parser/qmljsparser.cpp b/src/plugins/qmldesigner/core/filemanager/parser/qmljsparser.cpp
new file mode 100644
index 0000000000..f5fab00f4c
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/parser/qmljsparser.cpp
@@ -0,0 +1,1812 @@
+// This file was generated by qlalr - DO NOT EDIT!
+
+/****************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <QtCore/QtDebug>
+
+#include <string.h>
+
+#include "qmljsengine_p.h"
+#include "qmljslexer_p.h"
+#include "qmljsast_p.h"
+#include "qmljsnodepool_p.h"
+
+
+
+#include "qmljsparser_p.h"
+#include <QVarLengthArray>
+
+//
+// This file is automatically generated from qmljs.g.
+// Changes will be lost.
+//
+
+using namespace QmlJS;
+
+QT_QML_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 == QmlJSGrammar::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(int startToken)
+{
+ Lexer *lexer = driver->lexer();
+ bool hadErrors = false;
+ int yytoken = -1;
+ int action = 0;
+
+ token_buffer[0].token = startToken;
+ first_token = &token_buffer[0];
+ last_token = &token_buffer[1];
+
+ 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: {
+ sym(1).Node = sym(2).Node;
+ program = sym(1).Node;
+} break;
+
+case 1: {
+ sym(1).Node = sym(2).Node;
+ program = sym(1).Node;
+} break;
+
+case 2: {
+ sym(1).Node = sym(2).Node;
+ program = sym(1).Node;
+} break;
+
+case 3: {
+ sym(1).Node = sym(2).Node;
+ program = sym(1).Node;
+} break;
+
+case 4: {
+ sym(1).UiProgram = makeAstNode<AST::UiProgram> (driver->nodePool(), sym(1).UiImportList,
+ sym(2).UiObjectMemberList->finish());
+} break;
+
+case 6: {
+ sym(1).Node = sym(1).UiImportList->finish();
+} break;
+
+case 7: {
+ sym(1).Node = makeAstNode<AST::UiImportList> (driver->nodePool(), sym(1).UiImport);
+} break;
+
+case 8: {
+ sym(1).Node = makeAstNode<AST::UiImportList> (driver->nodePool(),
+ sym(1).UiImportList, sym(2).UiImport);
+} break;
+
+case 11: {
+ sym(1).UiImport->semicolonToken = loc(2);
+} break;
+
+case 13: {
+ sym(1).UiImport->versionToken = loc(2);
+ sym(1).UiImport->semicolonToken = loc(3);
+} break;
+
+case 15: {
+ sym(1).UiImport->versionToken = loc(2);
+ sym(1).UiImport->asToken = loc(3);
+ sym(1).UiImport->importIdToken = loc(4);
+ sym(1).UiImport->importId = sym(4).sval;
+ sym(1).UiImport->semicolonToken = loc(5);
+} break;
+
+case 17: {
+ sym(1).UiImport->asToken = loc(2);
+ sym(1).UiImport->importIdToken = loc(3);
+ sym(1).UiImport->importId = sym(3).sval;
+ sym(1).UiImport->semicolonToken = loc(4);
+} break;
+
+case 18: {
+ AST::UiImport *node = 0;
+
+ if (AST::StringLiteral *importIdLiteral = AST::cast<AST::StringLiteral *>(sym(2).Expression)) {
+ node = makeAstNode<AST::UiImport>(driver->nodePool(), importIdLiteral->value);
+ node->fileNameToken = loc(2);
+ } else if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(2).Expression)) {
+ QString text;
+ for (AST::UiQualifiedId *q = qualifiedId; q; q = q->next) {
+ text += q->name->asString();
+ if (q->next) text += QLatin1String(".");
+ }
+ node = makeAstNode<AST::UiImport>(driver->nodePool(), qualifiedId);
+ node->fileNameToken = loc(2);
+ }
+
+ sym(1).Node = node;
+
+ if (! node) {
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1),
+ QLatin1String("Expected a qualified name id or a string literal")));
+
+ return false; // ### remove me
+ }
+} break;
+
+case 19: {
+ sym(1).Node = 0;
+} break;
+
+case 20: {
+ sym(1).Node = makeAstNode<AST::UiObjectMemberList> (driver->nodePool(), sym(1).UiObjectMember);
+} break;
+
+case 21: {
+ sym(1).Node = makeAstNode<AST::UiObjectMemberList> (driver->nodePool(), sym(1).UiObjectMember);
+} break;
+
+case 22: {
+ AST::UiObjectMemberList *node = makeAstNode<AST:: UiObjectMemberList> (driver->nodePool(),
+ sym(1).UiObjectMemberList, sym(2).UiObjectMember);
+ sym(1).Node = node;
+} break;
+
+case 23: {
+ sym(1).Node = makeAstNode<AST::UiArrayMemberList> (driver->nodePool(), sym(1).UiObjectMember);
+} break;
+
+case 24: {
+ AST::UiArrayMemberList *node = makeAstNode<AST::UiArrayMemberList> (driver->nodePool(),
+ sym(1).UiArrayMemberList, sym(3).UiObjectMember);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 25: {
+ 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 26: {
+ 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 27: {
+ AST::UiObjectDefinition *node = makeAstNode<AST::UiObjectDefinition> (driver->nodePool(), sym(1).UiQualifiedId,
+ sym(2).UiObjectInitializer);
+ sym(1).Node = node;
+} break;
+
+case 29: {
+ AST::UiArrayBinding *node = makeAstNode<AST::UiArrayBinding> (driver->nodePool(),
+ sym(1).UiQualifiedId, sym(4).UiArrayMemberList->finish());
+ node->colonToken = loc(2);
+ node->lbracketToken = loc(3);
+ node->rbracketToken = loc(5);
+ sym(1).Node = node;
+} break;
+
+case 30: {
+ AST::UiObjectBinding *node = makeAstNode<AST::UiObjectBinding> (driver->nodePool(),
+ sym(1).UiQualifiedId, sym(3).UiQualifiedId, sym(4).UiObjectInitializer);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+case 31:case 32:case 33:case 34:
+{
+ AST::UiScriptBinding *node = makeAstNode<AST::UiScriptBinding> (driver->nodePool(),
+ sym(1).UiQualifiedId, sym(3).Statement);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 35:
+
+case 36: {
+ sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount());
+ break;
+}
+
+case 38: {
+ sym(1).Node = 0;
+} break;
+
+case 39: {
+ sym(1).Node = sym(1).UiParameterList->finish ();
+} break;
+
+case 40: {
+ AST::UiParameterList *node = makeAstNode<AST::UiParameterList> (driver->nodePool(), sym(1).sval, sym(2).sval);
+ node->identifierToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 41: {
+ AST::UiParameterList *node = makeAstNode<AST::UiParameterList> (driver->nodePool(), sym(1).UiParameterList, sym(3).sval, sym(4).sval);
+ node->commaToken = loc(2);
+ node->identifierToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 43: {
+ 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(2);
+ node->parameters = sym(4).UiParameterList;
+ node->semicolonToken = loc(6);
+ sym(1).Node = node;
+} break;
+
+case 45: {
+ 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(2);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 47: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(4).sval, sym(6).sval);
+ node->typeModifier = sym(2).sval;
+ node->propertyToken = loc(1);
+ node->typeModifierToken = loc(2);
+ node->typeToken = loc(4);
+ node->identifierToken = loc(6);
+ node->semicolonToken = loc(7);
+ sym(1).Node = node;
+} break;
+
+case 49: {
+ 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 51: {
+ 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 53: {
+ 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 55: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval,
+ sym(6).Expression);
+ node->isReadonlyMember = true;
+ node->readonlyToken = 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 57: {
+ 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 58: {
+ sym(1).Node = makeAstNode<AST::UiSourceElement>(driver->nodePool(), sym(1).Node);
+} break;
+
+case 59: {
+ sym(1).Node = makeAstNode<AST::UiSourceElement>(driver->nodePool(), sym(1).Node);
+} break;
+
+case 61: {
+ QString s = QLatin1String(QmlJSGrammar::spell[T_PROPERTY]);
+ sym(1).sval = driver->intern(s.constData(), s.length());
+ break;
+}
+
+case 62: {
+ QString s = QLatin1String(QmlJSGrammar::spell[T_SIGNAL]);
+ sym(1).sval = driver->intern(s.constData(), s.length());
+ break;
+}
+
+case 63: {
+ QString s = QLatin1String(QmlJSGrammar::spell[T_READONLY]);
+ sym(1).sval = driver->intern(s.constData(), s.length());
+ break;
+}
+
+case 64: {
+ AST::ThisExpression *node = makeAstNode<AST::ThisExpression> (driver->nodePool());
+ node->thisToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 65: {
+ AST::IdentifierExpression *node = makeAstNode<AST::IdentifierExpression> (driver->nodePool(), sym(1).sval);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 66: {
+ AST::NullExpression *node = makeAstNode<AST::NullExpression> (driver->nodePool());
+ node->nullToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 67: {
+ AST::TrueLiteral *node = makeAstNode<AST::TrueLiteral> (driver->nodePool());
+ node->trueToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 68: {
+ AST::FalseLiteral *node = makeAstNode<AST::FalseLiteral> (driver->nodePool());
+ node->falseToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 69: {
+ AST::NumericLiteral *node = makeAstNode<AST::NumericLiteral> (driver->nodePool(), sym(1).dval);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+case 70:
+case 71: {
+ AST::StringLiteral *node = makeAstNode<AST::StringLiteral> (driver->nodePool(), sym(1).sval);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 72: {
+ 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 73: {
+ 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 74: {
+ 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 75: {
+ 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 76: {
+ 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 77: {
+ 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 78: {
+ 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 79: {
+ 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 80: {
+ 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 81: {
+ 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 82: {
+ if (AST::ArrayMemberExpression *mem = AST::cast<AST::ArrayMemberExpression *>(sym(1).Expression)) {
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, mem->lbracketToken,
+ QLatin1String("Ignored annotation")));
+
+ sym(1).Expression = mem->base;
+ }
+
+ if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(1).Expression)) {
+ sym(1).UiQualifiedId = qualifiedId;
+ } else {
+ sym(1).UiQualifiedId = 0;
+
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1),
+ QLatin1String("Expected a qualified name id")));
+
+ return false; // ### recover
+ }
+} break;
+
+case 83: {
+ sym(1).Node = makeAstNode<AST::ElementList> (driver->nodePool(), (AST::Elision *) 0, sym(1).Expression);
+} break;
+
+case 84: {
+ sym(1).Node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).Elision->finish(), sym(2).Expression);
+} break;
+
+case 85: {
+ 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 86: {
+ 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 87: {
+ AST::Elision *node = makeAstNode<AST::Elision> (driver->nodePool());
+ node->commaToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 88: {
+ AST::Elision *node = makeAstNode<AST::Elision> (driver->nodePool(), sym(1).Elision);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 89: {
+ AST::PropertyNameAndValueList *node = makeAstNode<AST::PropertyNameAndValueList> (driver->nodePool(),
+ sym(1).PropertyName, sym(3).Expression);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 90: {
+ 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 91: {
+ AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), sym(1).sval);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+case 92:
+case 93: {
+ AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount()));
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 94: {
+ AST::StringLiteralPropertyName *node = makeAstNode<AST::StringLiteralPropertyName> (driver->nodePool(), sym(1).sval);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 95: {
+ AST::NumericLiteralPropertyName *node = makeAstNode<AST::NumericLiteralPropertyName> (driver->nodePool(), sym(1).dval);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 96: {
+ AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), sym(1).sval);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+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:
+
+case 111:
+
+case 112:
+
+case 113:
+
+case 114:
+
+case 115:
+
+case 116:
+
+case 117:
+
+case 118:
+
+case 119:
+
+case 120:
+
+case 121:
+
+case 122:
+
+case 123:
+
+case 124:
+
+case 125:
+
+case 126:
+
+case 127:
+{
+ sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount());
+} break;
+
+case 132: {
+ 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 133: {
+ 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 134: {
+ 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 136: {
+ AST::NewExpression *node = makeAstNode<AST::NewExpression> (driver->nodePool(), sym(2).Expression);
+ node->newToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 137: {
+ 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 138: {
+ 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 139: {
+ 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 140: {
+ 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 141: {
+ sym(1).Node = 0;
+} break;
+
+case 142: {
+ sym(1).Node = sym(1).ArgumentList->finish();
+} break;
+
+case 143: {
+ sym(1).Node = makeAstNode<AST::ArgumentList> (driver->nodePool(), sym(1).Expression);
+} break;
+
+case 144: {
+ AST::ArgumentList *node = makeAstNode<AST::ArgumentList> (driver->nodePool(), sym(1).ArgumentList, sym(3).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 148: {
+ AST::PostIncrementExpression *node = makeAstNode<AST::PostIncrementExpression> (driver->nodePool(), sym(1).Expression);
+ node->incrementToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 149: {
+ AST::PostDecrementExpression *node = makeAstNode<AST::PostDecrementExpression> (driver->nodePool(), sym(1).Expression);
+ node->decrementToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 151: {
+ AST::DeleteExpression *node = makeAstNode<AST::DeleteExpression> (driver->nodePool(), sym(2).Expression);
+ node->deleteToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 152: {
+ AST::VoidExpression *node = makeAstNode<AST::VoidExpression> (driver->nodePool(), sym(2).Expression);
+ node->voidToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 153: {
+ AST::TypeOfExpression *node = makeAstNode<AST::TypeOfExpression> (driver->nodePool(), sym(2).Expression);
+ node->typeofToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 154: {
+ AST::PreIncrementExpression *node = makeAstNode<AST::PreIncrementExpression> (driver->nodePool(), sym(2).Expression);
+ node->incrementToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 155: {
+ AST::PreDecrementExpression *node = makeAstNode<AST::PreDecrementExpression> (driver->nodePool(), sym(2).Expression);
+ node->decrementToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 156: {
+ AST::UnaryPlusExpression *node = makeAstNode<AST::UnaryPlusExpression> (driver->nodePool(), sym(2).Expression);
+ node->plusToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 157: {
+ AST::UnaryMinusExpression *node = makeAstNode<AST::UnaryMinusExpression> (driver->nodePool(), sym(2).Expression);
+ node->minusToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 158: {
+ AST::TildeExpression *node = makeAstNode<AST::TildeExpression> (driver->nodePool(), sym(2).Expression);
+ node->tildeToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 159: {
+ AST::NotExpression *node = makeAstNode<AST::NotExpression> (driver->nodePool(), sym(2).Expression);
+ node->notToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 161: {
+ 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 162: {
+ 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 163: {
+ 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 165: {
+ 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 166: {
+ 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 168: {
+ 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 169: {
+ 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 170: {
+ 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 172: {
+ 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 173: {
+ 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 174: {
+ 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 175: {
+ 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 176: {
+ 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 177: {
+ 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 179: {
+ 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 180: {
+ 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 181: {
+ 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 182: {
+ 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 183: {
+ 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 185: {
+ 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 186: {
+ 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 187: {
+ 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 188: {
+ 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 190: {
+ 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 191: {
+ 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 192: {
+ 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 193: {
+ 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 195: {
+ 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 197: {
+ 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 199: {
+ 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 201: {
+ 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 203: {
+ 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 205: {
+ 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 207: {
+ 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 209: {
+ 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 211: {
+ 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 213: {
+ 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 215: {
+ 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 217: {
+ 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 219: {
+ 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 221: {
+ 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 222: {
+ sym(1).ival = QSOperator::Assign;
+} break;
+
+case 223: {
+ sym(1).ival = QSOperator::InplaceMul;
+} break;
+
+case 224: {
+ sym(1).ival = QSOperator::InplaceDiv;
+} break;
+
+case 225: {
+ sym(1).ival = QSOperator::InplaceMod;
+} break;
+
+case 226: {
+ sym(1).ival = QSOperator::InplaceAdd;
+} break;
+
+case 227: {
+ sym(1).ival = QSOperator::InplaceSub;
+} break;
+
+case 228: {
+ sym(1).ival = QSOperator::InplaceLeftShift;
+} break;
+
+case 229: {
+ sym(1).ival = QSOperator::InplaceRightShift;
+} break;
+
+case 230: {
+ sym(1).ival = QSOperator::InplaceURightShift;
+} break;
+
+case 231: {
+ sym(1).ival = QSOperator::InplaceAnd;
+} break;
+
+case 232: {
+ sym(1).ival = QSOperator::InplaceXor;
+} break;
+
+case 233: {
+ sym(1).ival = QSOperator::InplaceOr;
+} break;
+
+case 235: {
+ AST::Expression *node = makeAstNode<AST::Expression> (driver->nodePool(), sym(1).Expression, sym(3).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 236: {
+ sym(1).Node = 0;
+} break;
+
+case 239: {
+ AST::Expression *node = makeAstNode<AST::Expression> (driver->nodePool(), sym(1).Expression, sym(3).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 240: {
+ sym(1).Node = 0;
+} break;
+
+case 257: {
+ 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 258: {
+ sym(1).Node = makeAstNode<AST::StatementList> (driver->nodePool(), sym(1).Statement);
+} break;
+
+case 259: {
+ sym(1).Node = makeAstNode<AST::StatementList> (driver->nodePool(), sym(1).StatementList, sym(2).Statement);
+} break;
+
+case 260: {
+ sym(1).Node = 0;
+} break;
+
+case 261: {
+ sym(1).Node = sym(1).StatementList->finish ();
+} break;
+
+case 263: {
+ 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 264: {
+ sym(1).ival = T_CONST;
+} break;
+
+case 265: {
+ sym(1).ival = T_VAR;
+} break;
+
+case 266: {
+ sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclaration);
+} break;
+
+case 267: {
+ AST::VariableDeclarationList *node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(),
+ sym(1).VariableDeclarationList, sym(3).VariableDeclaration);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 268: {
+ sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclaration);
+} break;
+
+case 269: {
+ sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclarationList, sym(3).VariableDeclaration);
+} break;
+
+case 270: {
+ AST::VariableDeclaration *node = makeAstNode<AST::VariableDeclaration> (driver->nodePool(), sym(1).sval, sym(2).Expression);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 271: {
+ AST::VariableDeclaration *node = makeAstNode<AST::VariableDeclaration> (driver->nodePool(), sym(1).sval, sym(2).Expression);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 272: {
+ // ### TODO: AST for initializer
+ sym(1) = sym(2);
+} break;
+
+case 273: {
+ sym(1).Node = 0;
+} break;
+
+case 275: {
+ // ### TODO: AST for initializer
+ sym(1) = sym(2);
+} break;
+
+case 276: {
+ sym(1).Node = 0;
+} break;
+
+case 278: {
+ AST::EmptyStatement *node = makeAstNode<AST::EmptyStatement> (driver->nodePool());
+ node->semicolonToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 280: {
+ AST::ExpressionStatement *node = makeAstNode<AST::ExpressionStatement> (driver->nodePool(), sym(1).Expression);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 281: {
+ 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 282: {
+ 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 284: {
+ 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 285: {
+ 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 286: {
+ 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 287: {
+ 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 288: {
+ 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 289: {
+ 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 291: {
+ AST::ContinueStatement *node = makeAstNode<AST::ContinueStatement> (driver->nodePool());
+ node->continueToken = loc(1);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 293: {
+ 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 295: {
+ AST::BreakStatement *node = makeAstNode<AST::BreakStatement> (driver->nodePool());
+ node->breakToken = loc(1);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 297: {
+ 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 299: {
+ 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 300: {
+ 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 301: {
+ 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 302: {
+ 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 303: {
+ 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 304: {
+ sym(1).Node = makeAstNode<AST::CaseClauses> (driver->nodePool(), sym(1).CaseClause);
+} break;
+
+case 305: {
+ sym(1).Node = makeAstNode<AST::CaseClauses> (driver->nodePool(), sym(1).CaseClauses, sym(2).CaseClause);
+} break;
+
+case 306: {
+ sym(1).Node = 0;
+} break;
+
+case 307: {
+ sym(1).Node = sym(1).CaseClauses->finish ();
+} break;
+
+case 308: {
+ 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 309: {
+ 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 310:
+case 311: {
+ 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 312: {
+ 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 314: {
+ 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 315: {
+ AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Catch);
+ node->tryToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 316: {
+ AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Finally);
+ node->tryToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 317: {
+ 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 318: {
+ 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 319: {
+ AST::Finally *node = makeAstNode<AST::Finally> (driver->nodePool(), sym(2).Block);
+ node->finallyToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 321: {
+ AST::DebuggerStatement *node = makeAstNode<AST::DebuggerStatement> (driver->nodePool());
+ node->debuggerToken = loc(1);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 322: {
+ 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 323: {
+ 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 324: {
+ AST::FormalParameterList *node = makeAstNode<AST::FormalParameterList> (driver->nodePool(), sym(1).sval);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 325: {
+ 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 326: {
+ sym(1).Node = 0;
+} break;
+
+case 327: {
+ sym(1).Node = sym(1).FormalParameterList->finish ();
+} break;
+
+case 328: {
+ sym(1).Node = 0;
+} break;
+
+case 330: {
+ sym(1).Node = makeAstNode<AST::FunctionBody> (driver->nodePool(), sym(1).SourceElements->finish ());
+} break;
+
+case 331: {
+ sym(1).Node = makeAstNode<AST::SourceElements> (driver->nodePool(), sym(1).SourceElement);
+} break;
+
+case 332: {
+ sym(1).Node = makeAstNode<AST::SourceElements> (driver->nodePool(), sym(1).SourceElements, sym(2).SourceElement);
+} break;
+
+case 333: {
+ sym(1).Node = makeAstNode<AST::StatementSourceElement> (driver->nodePool(), sym(1).Statement);
+} break;
+
+case 334: {
+ sym(1).Node = makeAstNode<AST::FunctionSourceElement> (driver->nodePool(), sym(1).FunctionDeclaration);
+} break;
+
+case 335: {
+ sym(1).sval = 0;
+} break;
+
+case 337: {
+ 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 || tk == T_FEED_UI_PROGRAM ||
+ tk == T_FEED_JS_STATEMENT || tk == T_FEED_JS_EXPRESSION)
+ 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_QML_END_NAMESPACE
+
+
diff --git a/src/plugins/qmldesigner/core/filemanager/parser/qmljsparser_p.h b/src/plugins/qmldesigner/core/filemanager/parser/qmljsparser_p.h
new file mode 100644
index 0000000000..7ee69a57d5
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/parser/qmljsparser_p.h
@@ -0,0 +1,230 @@
+// This file was generated by qlalr - DO NOT EDIT!
+
+/****************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+//
+// 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 qmljs.g.
+// Changes will be lost.
+//
+
+#ifndef QMLJSPARSER_P_H
+#define QMLJSPARSER_P_H
+
+#include "qmljsglobal_p.h"
+#include "qmljsgrammar_p.h"
+#include "qmljsast_p.h"
+#include "qmljsengine_p.h"
+
+#include <QtCore/QList>
+#include <QtCore/QString>
+
+QT_QML_BEGIN_NAMESPACE
+
+namespace QmlJS {
+
+class Engine;
+class NameId;
+
+class Parser: protected QmlJSGrammar
+{
+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::UiParameterList *UiParameterList;
+ 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::UiArrayMemberList *UiArrayMemberList;
+ AST::UiQualifiedId *UiQualifiedId;
+ AST::UiSignature *UiSignature;
+ AST::UiFormalList *UiFormalList;
+ AST::UiFormal *UiFormal;
+ };
+
+public:
+ Parser(Engine *engine);
+ ~Parser();
+
+ // parse a UI program
+ bool parse() { return parse(T_FEED_UI_PROGRAM); }
+ bool parseStatement() { return parse(T_FEED_JS_STATEMENT); }
+ bool parseExpression() { return parse(T_FEED_JS_EXPRESSION); }
+ bool parseUiObjectMember() { return parse(T_FEED_UI_OBJECT_MEMBER); }
+
+ AST::UiProgram *ast() const
+ { return AST::cast<AST::UiProgram *>(program); }
+
+ AST::Statement *statement() const
+ {
+ if (! program)
+ return 0;
+
+ return program->statementCast();
+ }
+
+ AST::ExpressionNode *expression() const
+ {
+ if (! program)
+ return 0;
+
+ return program->expressionCast();
+ }
+
+ AST::UiObjectMember *uiObjectMember() const
+ {
+ if (! program)
+ return 0;
+
+ return program->uiObjectMemberCast();
+ }
+
+ 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:
+ bool parse(int startToken);
+
+ 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::Node *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 QmlJS
+
+
+
+#define J_SCRIPT_REGEXPLITERAL_RULE1 72
+
+#define J_SCRIPT_REGEXPLITERAL_RULE2 73
+
+QT_QML_END_NAMESPACE
+
+
+
+#endif // QMLJSPARSER_P_H
diff --git a/src/plugins/qmldesigner/core/filemanager/qmldocument.cpp b/src/plugins/qmldesigner/core/filemanager/qmldocument.cpp
new file mode 100644
index 0000000000..d89e69609f
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/qmldocument.cpp
@@ -0,0 +1,165 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "idcollector.h"
+#include "qmldocument.h"
+#include "qmljsast_p.h"
+#include "qmljslexer_p.h"
+#include "qmljsparser_p.h"
+#include "qmljsengine_p.h"
+#include "qmljsnodepool_p.h"
+
+using namespace QmlEditor;
+using namespace QmlJS;
+
+QmlDocument::QmlDocument(const QString &fileName)
+ : _engine(0)
+ , _pool(0)
+ , _program(0)
+ , _fileName(fileName)
+ , _parsedCorrectly(false)
+{
+ const int slashIdx = fileName.lastIndexOf('/');
+ if (slashIdx != -1)
+ _path = fileName.left(slashIdx);
+
+ if (fileName.toLower().endsWith(".qml"))
+ _componentName = fileName.mid(slashIdx + 1, fileName.size() - (slashIdx + 1) - 4);
+}
+
+QmlDocument::~QmlDocument()
+{
+ if (_engine)
+ delete _engine;
+
+ if (_pool)
+ delete _pool;
+
+ qDeleteAll(_ids.values());
+}
+
+QmlDocument::Ptr QmlDocument::create(const QString &fileName)
+{
+ QmlDocument::Ptr doc(new QmlDocument(fileName));
+ return doc;
+}
+
+AST::UiProgram *QmlDocument::program() const
+{
+ return _program;
+}
+
+QList<DiagnosticMessage> QmlDocument::diagnosticMessages() const
+{
+ return _diagnosticMessages;
+}
+
+QString QmlDocument::source() const
+{
+ return _source;
+}
+
+void QmlDocument::setSource(const QString &source)
+{
+ _source = source;
+}
+
+bool QmlDocument::parse()
+{
+ Q_ASSERT(! _engine);
+ Q_ASSERT(! _pool);
+ Q_ASSERT(! _program);
+
+ _engine = new Engine();
+ _pool = new NodePool(_fileName, _engine);
+ _ids.clear();
+
+ Lexer lexer(_engine);
+ Parser parser(_engine);
+
+ lexer.setCode(_source, /*line = */ 1);
+
+ _parsedCorrectly = parser.parse();
+ _program = parser.ast();
+ _diagnosticMessages = parser.diagnosticMessages();
+
+ if (_parsedCorrectly && _program) {
+ Internal::IdCollector collect;
+ _ids = collect(_fileName, _program);
+ }
+
+ return _parsedCorrectly;
+}
+
+Snapshot::Snapshot()
+{
+}
+
+Snapshot::~Snapshot()
+{
+}
+
+void Snapshot::insert(const QmlDocument::Ptr &document)
+{
+ QMap<QString, QmlDocument::Ptr>::insert(document->fileName(), document);
+}
+
+QmlDocument::PtrList Snapshot::importedDocuments(const QmlDocument::Ptr &doc, const QString &importPath) const
+{
+ QmlDocument::PtrList result;
+
+ const QString docPath = doc->path() + '/' + importPath;
+
+ foreach (QmlDocument::Ptr candidate, *this) {
+ if (candidate == doc)
+ continue;
+
+ if (candidate->path() == doc->path() || candidate->path() == docPath)
+ result.append(candidate);
+ }
+
+ return result;
+}
+
+QMap<QString, QmlDocument::Ptr> Snapshot::componentsDefinedByImportedDocuments(const QmlDocument::Ptr &doc, const QString &importPath) const
+{
+ QMap<QString, QmlDocument::Ptr> result;
+
+ const QString docPath = doc->path() + '/' + importPath;
+
+ foreach (QmlDocument::Ptr candidate, *this) {
+ if (candidate == doc)
+ continue;
+
+ if (candidate->path() == doc->path() || candidate->path() == docPath)
+ result.insert(candidate->componentName(), candidate);
+ }
+
+ return result;
+}
diff --git a/src/plugins/qmldesigner/core/filemanager/qmldocument.h b/src/plugins/qmldesigner/core/filemanager/qmldocument.h
new file mode 100644
index 0000000000..4e712d8327
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/qmldocument.h
@@ -0,0 +1,109 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+#ifndef QMLDOCUMENT_H
+#define QMLDOCUMENT_H
+
+#include <corelib_global.h>
+
+#include <QtCore/QList>
+#include <QtCore/QMap>
+#include <QtCore/QPair>
+#include <QtCore/QSharedPointer>
+#include <QtCore/QString>
+
+#include "qmleditor_global.h"
+#include "qmljsengine_p.h"
+#include "qmljsastfwd_p.h"
+#include "qmlsymbol.h"
+
+namespace QmlEditor {
+
+class CORESHARED_EXPORT QmlDocument
+{
+public:
+ typedef QSharedPointer<QmlDocument> Ptr;
+ typedef QList<QmlDocument::Ptr> PtrList;
+ typedef QMap<QString, QmlIdSymbol*> IdTable;
+
+protected:
+ QmlDocument(const QString &fileName);
+
+public:
+ ~QmlDocument();
+
+ static QmlDocument::Ptr create(const QString &fileName);
+
+ QmlJS::AST::UiProgram *program() const;
+ QList<QmlJS::DiagnosticMessage> diagnosticMessages() const;
+
+ QString source() const;
+ void setSource(const QString &source);
+
+ bool parse();
+
+ bool isParsedCorrectly() const
+ { return _parsedCorrectly; }
+
+ IdTable ids() const { return _ids; }
+
+ QString fileName() const { return _fileName; }
+ QString path() const { return _path; }
+ QString componentName() const { return _componentName; }
+
+private:
+ QmlJS::Engine *_engine;
+ QmlJS::NodePool *_pool;
+ QmlJS::AST::UiProgram *_program;
+ QList<QmlJS::DiagnosticMessage> _diagnosticMessages;
+ QString _fileName;
+ QString _path;
+ QString _componentName;
+ QString _source;
+ bool _parsedCorrectly;
+ IdTable _ids;
+};
+
+class CORESHARED_EXPORT Snapshot: public QMap<QString, QmlDocument::Ptr>
+{
+public:
+ Snapshot();
+ ~Snapshot();
+
+ void insert(const QmlDocument::Ptr &document);
+
+ QmlDocument::Ptr document(const QString &fileName) const
+ { return value(fileName); }
+
+ QmlDocument::PtrList importedDocuments(const QmlDocument::Ptr &doc, const QString &importPath) const;
+ QMap<QString, QmlDocument::Ptr> componentsDefinedByImportedDocuments(const QmlDocument::Ptr &doc, const QString &importPath) const;
+};
+
+} // emd of namespace QmlEditor
+
+#endif // QMLDOCUMENT_H
diff --git a/src/plugins/qmldesigner/core/filemanager/qmleditor_global.h b/src/plugins/qmldesigner/core/filemanager/qmleditor_global.h
new file mode 100644
index 0000000000..81eacd75b4
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/qmleditor_global.h
@@ -0,0 +1,41 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef QMLEDITOR_GLOBAL_H
+#define QMLEDITOR_GLOBAL_H
+
+#include <QtGlobal>
+
+#if defined(QMLEDITOR_LIBRARY)
+# define QMLEDITOR_EXPORT Q_DECL_EXPORT
+#else
+# define QMLEDITOR_EXPORT Q_DECL_IMPORT
+#endif
+
+#endif // QMLEDITOR_GLOBAL_H
diff --git a/src/plugins/qmldesigner/core/filemanager/qmlrefactoring.cpp b/src/plugins/qmldesigner/core/filemanager/qmlrefactoring.cpp
new file mode 100644
index 0000000000..530c1a9ebc
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/qmlrefactoring.cpp
@@ -0,0 +1,160 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <QDebug>
+
+#include "addarraymembervisitor.h"
+#include "addobjectvisitor.h"
+#include "addpropertyvisitor.h"
+#include "changeobjecttypevisitor.h"
+#include "changepropertyvisitor.h"
+#include "moveobjectvisitor.h"
+#include "moveobjectbeforeobjectvisitor.h"
+#include "qmlrefactoring.h"
+#include "removepropertyvisitor.h"
+#include "removeuiobjectmembervisitor.h"
+
+using namespace QmlEditor;
+using namespace QmlEditor::Internal;
+
+QmlRefactoring::QmlRefactoring(const QmlDocument::Ptr &doc, QmlDesigner::TextModifier &modifier, const QStringList &propertyOrder):
+ qmlDocument(doc),
+ textModifier(&modifier),
+ m_propertyOrder(propertyOrder)
+{
+}
+
+bool QmlRefactoring::reparseDocument()
+{
+ const QString newSource = textModifier->text();
+
+// qDebug() << "QmlRefactoring::reparseDocument() new QML source:" << newSource;
+
+ QmlEditor::QmlDocument::Ptr tmpDocument(QmlEditor::QmlDocument::create("<ModelToTextMerger>"));
+ tmpDocument->setSource(newSource);
+
+ if (tmpDocument->parse()) {
+ qmlDocument = tmpDocument;
+ return true;
+ } else {
+ qWarning() << "*** Possible problem: QML file wasn't parsed correctly.";
+ qDebug() << "*** QML text:" << textModifier->text();
+ return false;
+ }
+}
+
+bool QmlRefactoring::changeImports(const QSet<QmlDesigner::Import> &/*addedImports*/, const QSet<QmlDesigner::Import> &/*removedImports*/)
+{
+// ChangeImportsVisitor visit(*textModifier, addedImports, removedImports, qmlDocument->source());
+// visit(qmlDocument->program());
+ return false;
+}
+
+bool QmlRefactoring::addToArrayMemberList(int parentLocation, const QString &propertyName, const QString &content)
+{
+ Q_ASSERT(parentLocation >= 0);
+
+ AddArrayMemberVisitor visit(*textModifier, (quint32) parentLocation, propertyName, content);
+ visit.setConvertObjectBindingIntoArrayBinding(true);
+ return visit(qmlDocument->program());
+}
+
+bool QmlRefactoring::addToObjectMemberList(int parentLocation, const QString &content)
+{
+ Q_ASSERT(parentLocation >= 0);
+
+ AddObjectVisitor visit(*textModifier, (quint32) parentLocation, content, m_propertyOrder);
+ return visit(qmlDocument->program());
+}
+
+bool QmlRefactoring::addProperty(int parentLocation, const QString &name, const QString &value, PropertyType propertyType)
+{
+ Q_ASSERT(parentLocation >= 0);
+
+ AddPropertyVisitor visit(*textModifier, (quint32) parentLocation, name, value, propertyType, m_propertyOrder);
+ return visit(qmlDocument->program());
+}
+
+bool QmlRefactoring::changeProperty(int parentLocation, const QString &name, const QString &value, PropertyType propertyType)
+{
+ Q_ASSERT(parentLocation >= 0);
+
+ ChangePropertyVisitor visit(*textModifier, (quint32) parentLocation, name, value, propertyType);
+ return visit(qmlDocument->program());
+}
+
+bool QmlRefactoring::changeObjectType(int nodeLocation, const QString &newType)
+{
+ Q_ASSERT(nodeLocation >= 0);
+ Q_ASSERT(!newType.isEmpty());
+
+ ChangeObjectTypeVisitor visit(*textModifier, (quint32) nodeLocation, newType);
+ return visit(qmlDocument->program());
+}
+
+bool QmlRefactoring::moveObject(int objectLocation, const QString &targetPropertyName, bool targetIsArrayBinding, int targetParentObjectLocation)
+{
+ Q_ASSERT(objectLocation >= 0);
+ Q_ASSERT(targetParentObjectLocation >= 0);
+
+ MoveObjectVisitor visit(*textModifier, (quint32) objectLocation, targetPropertyName, targetIsArrayBinding, (quint32) targetParentObjectLocation, m_propertyOrder);
+ return visit(qmlDocument->program());
+}
+
+bool QmlRefactoring::moveObjectBeforeObject(int movingObjectLocation, int beforeObjectLocation)
+{
+ Q_ASSERT(movingObjectLocation >= 0);
+ Q_ASSERT(beforeObjectLocation >= -1);
+
+ if (beforeObjectLocation == -1) {
+ MoveObjectBeforeObjectVisitor visit(*textModifier, movingObjectLocation);
+ return visit(qmlDocument->program());
+ } else {
+ MoveObjectBeforeObjectVisitor visit(*textModifier, movingObjectLocation, beforeObjectLocation);
+ return visit(qmlDocument->program());
+ }
+ return false;
+}
+
+bool QmlRefactoring::removeObject(int nodeLocation)
+{
+ Q_ASSERT(nodeLocation >= 0);
+
+ RemoveUIObjectMemberVisitor visit(*textModifier, (quint32) nodeLocation);
+ return visit(qmlDocument->program());
+}
+
+bool QmlRefactoring::removeProperty(int parentLocation, const QString &name)
+{
+ Q_ASSERT(parentLocation >= 0);
+ Q_ASSERT(!name.isEmpty());
+
+ RemovePropertyVisitor visit(*textModifier, (quint32) parentLocation, name);
+ return visit(qmlDocument->program());
+}
diff --git a/src/plugins/qmldesigner/core/filemanager/qmlrefactoring.h b/src/plugins/qmldesigner/core/filemanager/qmlrefactoring.h
new file mode 100644
index 0000000000..9739230aa3
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/qmlrefactoring.h
@@ -0,0 +1,80 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef QMLREFACTORING_H
+#define QMLREFACTORING_H
+
+#include <import.h>
+#include <textmodifier.h>
+#include <filemanager/qmldocument.h>
+#include <QSet>
+#include <QString>
+
+namespace QmlEditor {
+
+class QmlRefactoring
+{
+ QmlRefactoring(const QmlRefactoring &);
+ QmlRefactoring &operator=(const QmlRefactoring &);
+
+public:
+ enum PropertyType {
+ ArrayBinding = 1,
+ ObjectBinding = 2,
+ ScriptBinding = 3
+ };
+
+public:
+ QmlRefactoring(const QmlDocument::Ptr &doc, QmlDesigner::TextModifier &modifier, const QStringList &propertyOrder);
+
+ bool reparseDocument();
+
+ bool changeImports(const QSet<QmlDesigner::Import> &addedImports, const QSet<QmlDesigner::Import> &removedImports);
+
+ bool addToArrayMemberList(int parentLocation, const QString &propertyName, const QString &content);
+ bool addToObjectMemberList(int parentLocation, const QString &content);
+ bool addProperty(int parentLocation, const QString &name, const QString &value, PropertyType propertyType);
+ bool changeProperty(int parentLocation, const QString &name, const QString &value, PropertyType propertyType);
+ bool changeObjectType(int nodeLocation, const QString &newType);
+
+ bool moveObject(int objectLocation, const QString &targetPropertyName, bool targetIsArray, int targetParentObjectLocation);
+ bool moveObjectBeforeObject(int movingObjectLocation, int beforeObjectLocation);
+
+ bool removeObject(int nodeLocation);
+ bool removeProperty(int parentLocation, const QString &name);
+
+private:
+ QmlDocument::Ptr qmlDocument;
+ QmlDesigner::TextModifier *textModifier;
+ QStringList m_propertyOrder;
+};
+
+} // namespace QmlEditor
+
+#endif // QMLREFACTORING_H
diff --git a/src/plugins/qmldesigner/core/filemanager/qmlrewriter.cpp b/src/plugins/qmldesigner/core/filemanager/qmlrewriter.cpp
new file mode 100644
index 0000000000..3d10930685
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/qmlrewriter.cpp
@@ -0,0 +1,317 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <QDebug>
+#include <QTextBlock>
+
+#include <qmljsast_p.h>
+#include <qmljsengine_p.h>
+
+#include "qmlrewriter.h"
+
+#include <typeinfo>
+
+using namespace QmlJS;
+using namespace QmlJS::AST;
+using namespace QmlEditor::Internal;
+
+QMLRewriter::QMLRewriter(QmlDesigner::TextModifier &textModifier):
+ m_textModifier(&textModifier),
+ m_didRewriting(false)
+{
+}
+
+bool QMLRewriter::operator()(QmlJS::AST::UiProgram *ast)
+{
+ setDidRewriting(false);
+
+ Node::accept(ast, this);
+
+ return didRewriting();
+}
+
+void QMLRewriter::replace(int offset, int length, const QString &text)
+{
+ m_textModifier->replace(offset, length, text);
+}
+
+void QMLRewriter::move(const QmlDesigner::TextModifier::MoveInfo &moveInfo)
+{
+ m_textModifier->move(moveInfo);
+}
+
+QString QMLRewriter::textBetween(int startPosition, int endPosition) const
+{
+ return m_textModifier->text().mid(startPosition, endPosition - startPosition);
+}
+
+QString QMLRewriter::textAt(const QmlJS::AST::SourceLocation &location) const
+{
+ return m_textModifier->text().mid(location.offset, location.length);
+}
+
+unsigned QMLRewriter::calculateIndentDepth(const SourceLocation &position) const
+{
+ QTextDocument *doc = m_textModifier->textDocument();
+ QTextCursor tc(doc);
+ tc.setPosition(position.offset);
+ const int lineOffset = tc.block().position();
+ unsigned indentDepth = 0;
+
+ forever {
+ const QChar ch = doc->characterAt(lineOffset + indentDepth);
+
+ if (ch.isNull() || !ch.isSpace())
+ break;
+ else
+ ++indentDepth;
+ }
+
+ return indentDepth;
+}
+
+QString QMLRewriter::addIndentation(const QString &text, unsigned depth)
+{
+ const QString indentation(depth, QLatin1Char(' '));
+
+ if (text.isEmpty())
+ return indentation;
+
+ const QLatin1Char lineSep('\n');
+ const QStringList lines = text.split(lineSep);
+ QString result;
+
+ for (int i = 0; i < lines.size(); ++i) {
+ if (i > 0)
+ result += lineSep;
+ const QString &line = lines.at(i);
+ if (!line.isEmpty()) {
+ result += indentation;
+ result += line;
+ }
+ }
+
+ return result;
+}
+
+QString QMLRewriter::removeIndentationFromLine(const QString &text, int depth)
+{
+ int charsToRemove = 0;
+ for (int i = 0; i < depth && i < text.length(); ++i) {
+ if (text.at(i).isSpace())
+ charsToRemove++;
+ else
+ break;
+ }
+
+ if (charsToRemove == 0)
+ return text;
+ else
+ return text.mid(charsToRemove);
+}
+
+QString QMLRewriter::removeIndentation(const QString &text, unsigned depth)
+{
+ const QLatin1Char lineSep('\n');
+ const QStringList lines = text.split(lineSep);
+ QString result;
+
+ for (int i = 0; i < lines.size(); ++i) {
+ if (i > 0)
+ result += lineSep;
+ result += removeIndentationFromLine(lines.at(i), depth);
+ }
+
+ return result;
+}
+
+QmlJS::AST::SourceLocation QMLRewriter::calculateLocation(QmlJS::AST::UiQualifiedId *id)
+{
+ Q_ASSERT(id != 0);
+
+ const SourceLocation startLocation = id->identifierToken;
+
+ UiQualifiedId *nextId = id;
+ while (nextId->next) {
+ nextId = nextId->next;
+ }
+
+ const SourceLocation endLocation = nextId->identifierToken;
+
+ return SourceLocation(startLocation.offset, endLocation.end() - startLocation.offset);
+}
+
+bool QMLRewriter::isMissingSemicolon(QmlJS::AST::UiObjectMember *member)
+{
+ UiScriptBinding *binding = AST::cast<UiScriptBinding *>(member);
+ if (binding)
+ return isMissingSemicolon(binding->statement);
+ else
+ return false;
+}
+
+bool QMLRewriter::isMissingSemicolon(QmlJS::AST::Statement *stmt)
+{
+ if (ExpressionStatement *eStmt = AST::cast<ExpressionStatement *>(stmt)) {
+ return !eStmt->semicolonToken.isValid();
+ } else if (IfStatement *iStmt = AST::cast<IfStatement *>(stmt)) {
+ if (iStmt->elseToken.isValid())
+ return isMissingSemicolon(iStmt->ko);
+ else
+ return isMissingSemicolon(iStmt->ok);
+ } else if (DebuggerStatement *dStmt = AST::cast<DebuggerStatement *>(stmt)) {
+ return !dStmt->semicolonToken.isValid();
+ } else {
+ return false;
+ }
+}
+
+QString QMLRewriter::flatten(UiQualifiedId *first)
+{
+ QString flatId;
+
+ for (UiQualifiedId* current = first; current; current = current->next) {
+ if (current != first)
+ flatId += '.';
+
+ flatId += current->name->asString();
+ }
+
+ return flatId;
+}
+
+bool QMLRewriter::includeSurroundingWhitespace(int &start, int &end) const
+{
+ QTextDocument *doc = m_textModifier->textDocument();
+ bool includeStartingWhitespace = true;
+ bool paragraphFound = false;
+
+ if (end >= 0) {
+ QChar c = doc->characterAt(end);
+ while (c.isSpace()) {
+ ++end;
+
+ if (c == QChar::ParagraphSeparator) {
+ paragraphFound = true;
+ break;
+ } else if (end == doc->characterCount()) {
+ break;
+ }
+
+ c = doc->characterAt(end);
+ }
+
+ includeStartingWhitespace = paragraphFound;
+ }
+
+ if (includeStartingWhitespace) {
+ while (start > 0) {
+ const QChar c = doc->characterAt(start - 1);
+
+ if (!c.isSpace())
+ break;
+ else if (c == QChar::ParagraphSeparator)
+ break;
+
+ --start;
+ }
+ }
+
+ return paragraphFound;
+}
+
+void QMLRewriter::includeLeadingEmptyLine(int &start) const
+{
+ QTextDocument *doc = textModifier()->textDocument();
+
+ if (start == 0)
+ return;
+
+ if (doc->characterAt(start - 1) != QChar::ParagraphSeparator)
+ return;
+
+ QTextCursor tc(doc);
+ tc.setPosition(start);
+ const int blockNr = tc.blockNumber();
+ if (blockNr == 0)
+ return;
+
+ const QTextBlock prevBlock = tc.block().previous();
+ const QString trimmedPrevBlockText = prevBlock.text().trimmed();
+ if (!trimmedPrevBlockText.isEmpty())
+ return;
+
+ start = prevBlock.position();
+}
+
+UiObjectMemberList *QMLRewriter::searchMemberToInsertAfter(UiObjectMemberList *members, const QString &propertyName, const QStringList &propertyOrder)
+{
+ if (!members)
+ return 0; // empty members
+
+ QHash<QString, UiObjectMemberList *> orderedMembers;
+
+ for (UiObjectMemberList *iter = members; iter; iter = iter->next) {
+ UiObjectMember *member = iter->member;
+
+ if (UiArrayBinding *arrayBinding = cast<UiArrayBinding*>(member))
+ orderedMembers[flatten(arrayBinding->qualifiedId)] = iter;
+ else if (UiObjectBinding *objectBinding = cast<UiObjectBinding*>(member))
+ orderedMembers[flatten(objectBinding->qualifiedId)] = iter;
+ else if (cast<UiObjectDefinition*>(member))
+ orderedMembers[QString::null] = iter;
+ else if (UiScriptBinding *scriptBinding = cast<UiScriptBinding*>(member))
+ orderedMembers[flatten(scriptBinding->qualifiedId)] = iter;
+ else if (cast<UiPublicMember*>(member))
+ orderedMembers[QLatin1String("property")] = iter;
+ }
+
+ int idx = propertyOrder.indexOf(propertyName);
+ if (idx == -1)
+ idx = propertyOrder.indexOf(QString::null);
+ if (idx == -1)
+ idx = propertyOrder.size() - 1;
+
+ for (; idx >= 0; --idx) {
+ const QString prop = propertyOrder.at(idx);
+ UiObjectMemberList *candidate = orderedMembers[prop];
+ if (candidate != 0)
+ return candidate;
+ }
+
+ return 0;
+}
+
+void QMLRewriter::dump(const ASTPath &path)
+{
+ qDebug() << "AST path with" << path.size() << "node(s):";
+ for (int i = 0; i < path.size(); ++i) {
+ qDebug() << qPrintable(QString(i + 1, QLatin1Char('-'))) << typeid(*path.at(i)).name();
+ }
+}
diff --git a/src/plugins/qmldesigner/core/filemanager/qmlrewriter.h b/src/plugins/qmldesigner/core/filemanager/qmlrewriter.h
new file mode 100644
index 0000000000..ab58a07770
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/qmlrewriter.h
@@ -0,0 +1,97 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef QMLREWRITER_H
+#define QMLREWRITER_H
+
+#include <QtCore/QStack>
+#include <QtCore/QString>
+
+#include <qmljsastvisitor_p.h>
+
+#include "textmodifier.h"
+
+namespace QmlEditor {
+namespace Internal {
+
+class QMLRewriter: protected QmlJS::AST::Visitor
+{
+public:
+ typedef QStack<QmlJS::AST::Node *> ASTPath;
+
+public:
+ QMLRewriter(QmlDesigner::TextModifier &textModifier);
+
+ virtual bool operator()(QmlJS::AST::UiProgram *ast);
+
+ static void dump(const ASTPath &path);
+
+protected:
+ using QmlJS::AST::Visitor::visit;
+
+ virtual void replace(int offset, int length, const QString &text);
+ virtual void move(const QmlDesigner::TextModifier::MoveInfo &moveInfo);
+
+ QString textBetween(int startPosition, int endPosition) const;
+ QString textAt(const QmlJS::AST::SourceLocation &location) const;
+
+ unsigned calculateIndentDepth(const QmlJS::AST::SourceLocation &position) const;
+ static QString addIndentation(const QString &text, unsigned depth);
+ static QString removeIndentation(const QString &text, unsigned depth);
+ static QString removeIndentationFromLine(const QString &text, int depth);
+
+ static QmlJS::AST::SourceLocation calculateLocation(QmlJS::AST::UiQualifiedId *id);
+ static bool isMissingSemicolon(QmlJS::AST::UiObjectMember *member);
+ static bool isMissingSemicolon(QmlJS::AST::Statement *stmt);
+ static QString flatten(QmlJS::AST::UiQualifiedId *first);
+
+ QmlDesigner::TextModifier *textModifier() const
+ { return m_textModifier; }
+
+ bool includeSurroundingWhitespace(int &start, int &end) const;
+ void includeLeadingEmptyLine(int &start) const;
+
+ static QmlJS::AST::UiObjectMemberList *searchMemberToInsertAfter(QmlJS::AST::UiObjectMemberList *members, const QString &propertyName, const QStringList &propertyOrder);
+
+protected:
+ bool didRewriting() const
+ { return m_didRewriting; }
+
+ void setDidRewriting(bool didRewriting)
+ { m_didRewriting = didRewriting; }
+
+private:
+ QmlDesigner::TextModifier *m_textModifier;
+ bool m_didRewriting;
+};
+
+} // namespace Internal
+} // namespace QmlEditor
+
+#endif // QMLREWRITER_H
diff --git a/src/plugins/qmldesigner/core/filemanager/qmlsymbol.cpp b/src/plugins/qmldesigner/core/filemanager/qmlsymbol.cpp
new file mode 100644
index 0000000000..baa1c1195a
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/qmlsymbol.cpp
@@ -0,0 +1,116 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "qmljsast_p.h"
+#include "qmlsymbol.h"
+
+using namespace QmlEditor;
+using namespace QmlJS;
+using namespace QmlJS::AST;
+
+QmlSymbol::~QmlSymbol()
+{
+}
+
+bool QmlSymbol::isBuildInSymbol() const
+{ return asBuildInSymbol() != 0; }
+
+bool QmlSymbol::isSymbolFromFile() const
+{ return asSymbolFromFile() != 0; }
+
+bool QmlSymbol::isIdSymbol() const
+{ return asIdSymbol() != 0; }
+
+QmlBuildInSymbol const *QmlSymbol::asBuildInSymbol() const
+{ return 0; }
+
+QmlSymbolFromFile const *QmlSymbol::asSymbolFromFile() const
+{ return 0; }
+
+QmlIdSymbol const *QmlSymbol::asIdSymbol() const
+{ return 0; }
+
+QmlBuildInSymbol::~QmlBuildInSymbol()
+{}
+
+QmlBuildInSymbol const* QmlBuildInSymbol::asBuildInSymbol() const
+{ return this; }
+
+QmlSymbolFromFile::QmlSymbolFromFile(const QString &fileName, QmlJS::AST::UiObjectMember *node):
+ _fileName(fileName),
+ _node(node)
+{}
+
+QmlSymbolFromFile::~QmlSymbolFromFile()
+{}
+
+const QmlSymbolFromFile *QmlSymbolFromFile::asSymbolFromFile() const
+{ return this; }
+
+int QmlSymbolFromFile::line() const
+{ return _node->firstSourceLocation().startLine; }
+
+int QmlSymbolFromFile::column() const
+{ return _node->firstSourceLocation().startColumn; }
+
+QmlIdSymbol::QmlIdSymbol(const QString &fileName, QmlJS::AST::UiScriptBinding *idNode, const QmlSymbolFromFile &parentNode):
+ QmlSymbolFromFile(fileName, idNode),
+ _parentNode(parentNode)
+{}
+
+QmlIdSymbol::~QmlIdSymbol()
+{}
+
+QmlIdSymbol const *QmlIdSymbol::asIdSymbol() const
+{ return this; }
+
+int QmlIdSymbol::line() const
+{ return idNode()->statement->firstSourceLocation().startLine; }
+
+int QmlIdSymbol::column() const
+{ return idNode()->statement->firstSourceLocation().startColumn; }
+
+QmlJS::AST::UiScriptBinding *QmlIdSymbol::idNode() const
+{ return cast<UiScriptBinding*>(node()); }
+
+QmlPropertyDefinitionSymbol::QmlPropertyDefinitionSymbol(const QString &fileName, QmlJS::AST::UiPublicMember *propertyNode):
+ QmlSymbolFromFile(fileName, propertyNode)
+{}
+
+QmlPropertyDefinitionSymbol::~QmlPropertyDefinitionSymbol()
+{}
+
+int QmlPropertyDefinitionSymbol::line() const
+{ return propertyNode()->identifierToken.startLine; }
+
+int QmlPropertyDefinitionSymbol::column() const
+{ return propertyNode()->identifierToken.startColumn; }
+
+QmlJS::AST::UiPublicMember *QmlPropertyDefinitionSymbol::propertyNode() const
+{ return cast<UiPublicMember*>(node()); }
diff --git a/src/plugins/qmldesigner/core/filemanager/qmlsymbol.h b/src/plugins/qmldesigner/core/filemanager/qmlsymbol.h
new file mode 100644
index 0000000000..1c1aa21192
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/qmlsymbol.h
@@ -0,0 +1,121 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef QMLSYMBOL_H
+#define QMLSYMBOL_H
+
+#include <QString>
+
+#include "qmljsastfwd_p.h"
+
+namespace QmlEditor {
+
+class QmlSymbol
+{
+public:
+ virtual ~QmlSymbol() = 0;
+
+ bool isBuildInSymbol() const;
+ bool isSymbolFromFile() const;
+ bool isIdSymbol() const;
+
+ virtual class QmlBuildInSymbol const *asBuildInSymbol() const;
+ virtual class QmlSymbolFromFile const *asSymbolFromFile() const;
+ virtual class QmlIdSymbol const *asIdSymbol() const;
+};
+
+class QmlBuildInSymbol: public QmlSymbol
+{
+public:
+ virtual ~QmlBuildInSymbol();
+
+ virtual QmlBuildInSymbol const *asBuildInSymbol() const;
+
+private:
+};
+
+class QmlSymbolFromFile: public QmlSymbol
+{
+public:
+ QmlSymbolFromFile(const QString &fileName, QmlJS::AST::UiObjectMember *node);
+ virtual ~QmlSymbolFromFile();
+
+ virtual QmlSymbolFromFile const *asSymbolFromFile() const;
+
+ QString fileName() const
+ { return _fileName; }
+
+ virtual int line() const;
+ virtual int column() const;
+
+ QmlJS::AST::UiObjectMember *node() const
+ { return _node; }
+
+private:
+ QString _fileName;
+ QmlJS::AST::UiObjectMember *_node;
+};
+
+class QmlIdSymbol: public QmlSymbolFromFile
+{
+public:
+ QmlIdSymbol(const QString &fileName, QmlJS::AST::UiScriptBinding *idNode, const QmlSymbolFromFile &parentNode);
+ virtual ~QmlIdSymbol();
+
+ QmlIdSymbol const *asIdSymbol() const;
+
+ virtual int line() const;
+ virtual int column() const;
+
+ QmlSymbolFromFile const *parentNode() const
+ { return &_parentNode; }
+
+private:
+ QmlJS::AST::UiScriptBinding *idNode() const;
+
+private:
+ QmlSymbolFromFile _parentNode;
+};
+
+class QmlPropertyDefinitionSymbol: public QmlSymbolFromFile
+{
+public:
+ QmlPropertyDefinitionSymbol(const QString &fileName, QmlJS::AST::UiPublicMember *propertyNode);
+ virtual ~QmlPropertyDefinitionSymbol();
+
+ virtual int line() const;
+ virtual int column() const;
+
+private:
+ QmlJS::AST::UiPublicMember *propertyNode() const;
+};
+
+} // namespace QmlEditor
+
+#endif // QMLSYMBOL_H
diff --git a/src/plugins/qmldesigner/core/filemanager/removepropertyvisitor.cpp b/src/plugins/qmldesigner/core/filemanager/removepropertyvisitor.cpp
new file mode 100644
index 0000000000..5c38e7f4cd
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/removepropertyvisitor.cpp
@@ -0,0 +1,108 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <qmljsast_p.h>
+#include <qmljsengine_p.h>
+
+#include "removepropertyvisitor.h"
+
+using namespace QmlEditor::Internal;
+using namespace QmlJS;
+using namespace QmlJS::AST;
+
+RemovePropertyVisitor::RemovePropertyVisitor(QmlDesigner::TextModifier &modifier,
+ quint32 parentLocation,
+ const QString &propertyName):
+ QMLRewriter(modifier),
+ parentLocation(parentLocation),
+ propertyName(propertyName)
+{
+}
+
+bool RemovePropertyVisitor::visit(QmlJS::AST::UiObjectBinding *ast)
+{
+ if (ast->firstSourceLocation().offset == parentLocation) {
+ removeFrom(ast->initializer);
+ }
+
+ return !didRewriting();
+}
+
+bool RemovePropertyVisitor::visit(QmlJS::AST::UiObjectDefinition *ast)
+{
+ if (ast->firstSourceLocation().offset == parentLocation) {
+ removeFrom(ast->initializer);
+ }
+
+ return !didRewriting();
+}
+
+void RemovePropertyVisitor::removeFrom(QmlJS::AST::UiObjectInitializer *ast)
+{
+ UiObjectMember *previousMember = 0, *wantedMember = 0, *nextMember = 0;
+
+ for (UiObjectMemberList *it = ast->members; it; it = it->next) {
+ if (memberNameMatchesPropertyName(it->member)) {
+ wantedMember = it->member;
+
+ if (it->next)
+ nextMember = it->next->member;
+
+ break;
+ }
+
+ previousMember = it->member;
+ }
+
+ if (!wantedMember)
+ return;
+
+ int start = wantedMember->firstSourceLocation().offset;
+ int end = wantedMember->lastSourceLocation().end();
+
+ includeSurroundingWhitespace(start, end);
+
+ replace(start, end - start, QLatin1String(""));
+
+ setDidRewriting(true);
+}
+
+bool RemovePropertyVisitor::memberNameMatchesPropertyName(QmlJS::AST::UiObjectMember *ast) const
+{
+ if (UiPublicMember *publicMember = cast<UiPublicMember*>(ast))
+ return publicMember->name->asString() == propertyName;
+ else if (UiObjectBinding *objectBinding = cast<UiObjectBinding*>(ast))
+ return flatten(objectBinding->qualifiedId) == propertyName;
+ else if (UiScriptBinding *scriptBinding = cast<UiScriptBinding*>(ast))
+ return flatten(scriptBinding->qualifiedId) == propertyName;
+ else if (UiArrayBinding *arrayBinding = cast<UiArrayBinding*>(ast))
+ return flatten(arrayBinding->qualifiedId) == propertyName;
+ else
+ return false;
+}
diff --git a/src/plugins/qmldesigner/core/filemanager/removepropertyvisitor.h b/src/plugins/qmldesigner/core/filemanager/removepropertyvisitor.h
new file mode 100644
index 0000000000..a396b8bac0
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/removepropertyvisitor.h
@@ -0,0 +1,63 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef REMOVEPROPERTYVISITOR_H
+#define REMOVEPROPERTYVISITOR_H
+
+#include <QString>
+
+#include "qmlrewriter.h"
+
+namespace QmlEditor {
+namespace Internal {
+
+class RemovePropertyVisitor: public QMLRewriter
+{
+public:
+ RemovePropertyVisitor(QmlDesigner::TextModifier &modifier,
+ quint32 parentLocation,
+ const QString &name);
+
+protected:
+ virtual bool visit(QmlJS::AST::UiObjectBinding *ast);
+ virtual bool visit(QmlJS::AST::UiObjectDefinition *ast);
+
+private:
+ void removeFrom(QmlJS::AST::UiObjectInitializer *ast);
+ bool memberNameMatchesPropertyName(QmlJS::AST::UiObjectMember *ast) const;
+
+private:
+ quint32 parentLocation;
+ QString propertyName;
+};
+
+} // namespace Internal
+} // namespace QmlEditor
+
+#endif // REMOVEPROPERTYVISITOR_H
diff --git a/src/plugins/qmldesigner/core/filemanager/removeuiobjectmembervisitor.cpp b/src/plugins/qmldesigner/core/filemanager/removeuiobjectmembervisitor.cpp
new file mode 100644
index 0000000000..bf0bcfb5ef
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/removeuiobjectmembervisitor.cpp
@@ -0,0 +1,139 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <QDebug>
+#include <qmljsast_p.h>
+#include <qmljsengine_p.h>
+
+#include "removeuiobjectmembervisitor.h"
+
+using namespace QmlEditor;
+using namespace QmlEditor::Internal;
+using namespace QmlJS;
+using namespace QmlJS::AST;
+
+RemoveUIObjectMemberVisitor::RemoveUIObjectMemberVisitor(QmlDesigner::TextModifier &modifier,
+ quint32 objectLocation):
+ QMLRewriter(modifier),
+ objectLocation(objectLocation)
+{
+}
+
+bool RemoveUIObjectMemberVisitor::preVisit(Node *ast)
+{
+ parents.push(ast);
+
+ return true;
+}
+
+void RemoveUIObjectMemberVisitor::postVisit(Node *)
+{
+ parents.pop();
+}
+
+bool RemoveUIObjectMemberVisitor::visit(QmlJS::AST::UiPublicMember *ast) { return visitObjectMember(ast); }
+bool RemoveUIObjectMemberVisitor::visit(QmlJS::AST::UiObjectDefinition *ast) { return visitObjectMember(ast); }
+bool RemoveUIObjectMemberVisitor::visit(QmlJS::AST::UiSourceElement *ast) { return visitObjectMember(ast); }
+bool RemoveUIObjectMemberVisitor::visit(QmlJS::AST::UiObjectBinding *ast) { return visitObjectMember(ast); }
+bool RemoveUIObjectMemberVisitor::visit(QmlJS::AST::UiScriptBinding *ast) { return visitObjectMember(ast); }
+bool RemoveUIObjectMemberVisitor::visit(QmlJS::AST::UiArrayBinding *ast) { return visitObjectMember(ast); }
+
+bool RemoveUIObjectMemberVisitor::visitObjectMember(QmlJS::AST::UiObjectMember *ast)
+{
+ const quint32 memberStart = ast->firstSourceLocation().offset;
+
+ if (memberStart == objectLocation) {
+ // found it
+ int start = objectLocation;
+ int end = ast->lastSourceLocation().end();
+
+ if (UiArrayBinding *parentArray = containingArray()) {
+ extendToLeadingOrTrailingComma(parentArray, ast, start, end);
+ } else {
+ includeSurroundingWhitespace(start, end);
+ }
+
+ includeLeadingEmptyLine(start);
+ replace(start, end - start, QLatin1String(""));
+
+ setDidRewriting(true);
+
+ return false;
+ } else if (ast->lastSourceLocation().end() <= objectLocation) {
+ // optimization: if the location of the object-to-be-removed is not inside the current member, skip any children
+ return false;
+ } else {
+ // only visit children if the rewriting isn't done yet.
+ return !didRewriting();
+ }
+}
+
+UiArrayBinding *RemoveUIObjectMemberVisitor::containingArray() const
+{
+ if (parents.size() > 2) {
+ if (cast<UiArrayMemberList*>(parents[parents.size() - 2])) {
+ return cast<UiArrayBinding*>(parents[parents.size() - 3]);
+ }
+ }
+
+ return 0;
+}
+
+void RemoveUIObjectMemberVisitor::extendToLeadingOrTrailingComma(QmlJS::AST::UiArrayBinding *parentArray,
+ QmlJS::AST::UiObjectMember *ast,
+ int &start,
+ int &end) const
+{
+ UiArrayMemberList *currentMember = 0;
+ for (UiArrayMemberList *it = parentArray->members; it; it = it->next) {
+ if (it->member == ast) {
+ currentMember = it;
+ break;
+ }
+ }
+
+ if (!currentMember)
+ return;
+
+ if (currentMember->commaToken.isValid()) {
+ // leading comma
+ start = currentMember->commaToken.offset;
+ if (includeSurroundingWhitespace(start, end))
+ --end;
+ } else if (currentMember->next && currentMember->next->commaToken.isValid()) {
+ // trailing comma
+ end = currentMember->next->commaToken.end();
+ includeSurroundingWhitespace(start, end);
+ } else {
+ // array with 1 element, so remove the complete binding
+ start = parentArray->firstSourceLocation().offset;
+ end = parentArray->lastSourceLocation().end();
+ includeSurroundingWhitespace(start, end);
+ }
+}
diff --git a/src/plugins/qmldesigner/core/filemanager/removeuiobjectmembervisitor.h b/src/plugins/qmldesigner/core/filemanager/removeuiobjectmembervisitor.h
new file mode 100644
index 0000000000..85816f197a
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/removeuiobjectmembervisitor.h
@@ -0,0 +1,75 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef REMOVEUIOBJECTMEMBERVISITOR_H
+#define REMOVEUIOBJECTMEMBERVISITOR_H
+
+#include <QStack>
+
+#include "qmlrewriter.h"
+
+namespace QmlEditor {
+namespace Internal {
+
+class RemoveUIObjectMemberVisitor: public QMLRewriter
+{
+public:
+ RemoveUIObjectMemberVisitor(QmlDesigner::TextModifier &modifier,
+ quint32 objectLocation);
+
+protected:
+ virtual bool preVisit(QmlJS::AST::Node *ast);
+ virtual void postVisit(QmlJS::AST::Node *);
+
+ virtual bool visit(QmlJS::AST::UiPublicMember *ast);
+ virtual bool visit(QmlJS::AST::UiObjectDefinition *ast);
+ virtual bool visit(QmlJS::AST::UiSourceElement *ast);
+ virtual bool visit(QmlJS::AST::UiObjectBinding *ast);
+ virtual bool visit(QmlJS::AST::UiScriptBinding *ast);
+ virtual bool visit(QmlJS::AST::UiArrayBinding *ast);
+
+private:
+ bool visitObjectMember(QmlJS::AST::UiObjectMember *ast);
+
+ QmlJS::AST::UiArrayBinding *containingArray() const;
+
+ void extendToLeadingOrTrailingComma(QmlJS::AST::UiArrayBinding *parentArray,
+ QmlJS::AST::UiObjectMember *ast,
+ int &start,
+ int &end) const;
+
+private:
+ quint32 objectLocation;
+ QStack<QmlJS::AST::Node*> parents;
+};
+
+} // namespace Internal
+} // namespace QmlEditor
+
+#endif // REMOVEUIOBJECTMEMBERVISITOR_H
diff --git a/src/plugins/qmldesigner/core/filemanager/utils_global.h b/src/plugins/qmldesigner/core/filemanager/utils_global.h
new file mode 100644
index 0000000000..a97322e5c9
--- /dev/null
+++ b/src/plugins/qmldesigner/core/filemanager/utils_global.h
@@ -0,0 +1,37 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef UTILS_GLOBAL_H
+#define UTILS_GLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+#define QTCREATOR_UTILS_EXPORT
+
+#endif // UTILS_GLOBAL_H
diff --git a/src/plugins/qmldesigner/core/include/abstractproperty.h b/src/plugins/qmldesigner/core/include/abstractproperty.h
new file mode 100644
index 0000000000..3cd457bd68
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/abstractproperty.h
@@ -0,0 +1,127 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef ABSTRACTROPERTY_H
+#define ABSTRACTROPERTY_H
+
+#include <QtCore/QVariant>
+#include <QWeakPointer>
+#include <QSharedPointer>
+#include "corelib_global.h"
+
+class QTextStream;
+
+namespace QmlDesigner {
+ namespace Internal {
+ class InternalNode;
+ class InternalProperty;
+
+ typedef QSharedPointer<InternalNode> InternalNodePointer;
+ typedef QSharedPointer<InternalProperty> InternalPropertyPointer;
+ typedef QWeakPointer<InternalNode> InternalNodeWeakPointer;
+ }
+
+class Model;
+class ModelNode;
+class AbstractView;
+class PropertyMetaInfo;
+class CORESHARED_EXPORT VariantProperty;
+class CORESHARED_EXPORT NodeListProperty;
+class CORESHARED_EXPORT NodeAbstractProperty;
+class CORESHARED_EXPORT BindingProperty;
+class CORESHARED_EXPORT NodeProperty;
+class QmlObjectNode;
+
+
+namespace Internal {
+ class InternalNode;
+ class ModelPrivate;
+}
+
+class CORESHARED_EXPORT AbstractProperty
+{
+ friend class QmlDesigner::ModelNode;
+ friend class QmlDesigner::Internal::ModelPrivate;
+
+ friend CORESHARED_EXPORT bool operator ==(const AbstractProperty &property1, const AbstractProperty &property2);
+ friend CORESHARED_EXPORT bool operator !=(const AbstractProperty &property1, const AbstractProperty &property2);
+ friend CORESHARED_EXPORT uint qHash(const AbstractProperty& property);
+
+public:
+ AbstractProperty();
+ ~AbstractProperty();
+ AbstractProperty(const AbstractProperty &other);
+ AbstractProperty& operator=(const AbstractProperty &other);
+ AbstractProperty(const AbstractProperty &property, AbstractView *view);
+
+ QString name() const;
+
+ bool isValid() const;
+ ModelNode parentModelNode() const;
+ QmlObjectNode parentQmlObjectNode() const;
+
+ PropertyMetaInfo metaInfo() const;
+ bool isDefaultProperty() const;
+ VariantProperty toVariantProperty() const;
+ NodeListProperty toNodeListProperty() const;
+ NodeAbstractProperty toNodeAbstractProperty() const;
+ BindingProperty toBindingProperty() const;
+ NodeProperty toNodeProperty() const;
+
+ bool isVariantProperty() const;
+ bool isNodeListProperty() const;
+ bool isNodeAbstractProperty() const;
+ bool isBindingProperty() const;
+ bool isNodeProperty() const;
+
+ bool isDynamic() const;
+ QString dynamicTypeName() const;
+
+protected:
+ AbstractProperty(const QString &propertyName, const Internal::InternalNodePointer &internalNode, Model* model, AbstractView *view);
+ AbstractProperty(const Internal::InternalPropertyPointer &property, Model* model, AbstractView *view);
+ Internal::InternalNodePointer internalNode() const;
+ Model *model() const;
+ AbstractView *view() const;
+
+private:
+ QString m_propertyName;
+ Internal::InternalNodePointer m_internalNode;
+ QWeakPointer<Model> m_model;
+ QWeakPointer<AbstractView> m_view;
+};
+
+CORESHARED_EXPORT bool operator ==(const AbstractProperty &property1, const AbstractProperty &property2);
+CORESHARED_EXPORT bool operator !=(const AbstractProperty &property1, const AbstractProperty &property2);
+CORESHARED_EXPORT uint qHash(const AbstractProperty& property);
+CORESHARED_EXPORT QTextStream& operator<<(QTextStream &stream, const AbstractProperty &property);
+CORESHARED_EXPORT QDebug operator<<(QDebug debug, const AbstractProperty &AbstractProperty);
+}
+
+#endif //ABSTRACTPROPERTY_H
diff --git a/src/plugins/qmldesigner/core/include/abstractview.h b/src/plugins/qmldesigner/core/include/abstractview.h
new file mode 100644
index 0000000000..9f58522657
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/abstractview.h
@@ -0,0 +1,148 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef ABSTRACTVIEW_H
+#define ABSTRACTVIEW_H
+
+#include <corelib_global.h>
+
+#include <model.h>
+#include <modelnode.h>
+#include <abstractproperty.h>
+#include <rewritertransaction.h>
+
+#include <QObject>
+
+class QStyle;
+
+namespace QmlDesigner {
+ namespace Internal {
+ class InternalNode;
+ typedef QSharedPointer<InternalNode> InternalNodePointer;
+ typedef QWeakPointer<InternalNode> InternalNodeWeakPointer;
+ }
+}
+
+namespace QmlDesigner {
+
+class QmlModelView;
+
+class CORESHARED_EXPORT AbstractView : public QObject
+{
+ Q_OBJECT
+public:
+ Q_FLAGS(PropertyChangeFlag PropertyChangeFlags);
+ typedef QWeakPointer<AbstractView> Pointer;
+
+ enum PropertyChangeFlag {
+ NoAdditionalChanges = 0x0,
+ PropertiesAdded = 0x1,
+ EmptyPropertiesRemoved = 0x2,
+ };
+ Q_DECLARE_FLAGS(PropertyChangeFlags, PropertyChangeFlag);
+ AbstractView(QObject *parent = 0)
+ : QObject(parent) {}
+
+ virtual ~AbstractView();
+
+ Model* model() const;
+
+ RewriterTransaction beginRewriterTransaction();
+
+ ModelNode createModelNode(const QString &typeString,
+ int majorVersion,
+ int minorVersion,
+ const PropertyListType &propertyList = PropertyListType());
+
+ const ModelNode rootModelNode() const;
+ ModelNode rootModelNode();
+
+ void setSelectedModelNodes(const QList<ModelNode> &selectedNodeList);
+ void selectModelNode(const ModelNode &node);
+ void deselectModelNode(const ModelNode &node);
+ void clearSelectedModelNodes();
+
+ QList<ModelNode> selectedModelNodes() const;
+
+ ModelNode modelNodeForId(const QString &id);
+ bool hasId(const QString &id) const;
+
+ QList<ModelNode> allModelNodes();
+
+ void emitCustomNotification(const QString &identifier);
+ void emitCustomNotification(const QString &identifier, const QList<ModelNode> &nodeList);
+ void emitCustomNotification(const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> &data);
+
+ virtual void modelAttached(Model *model);
+ virtual void modelAboutToBeDetached(Model *model);
+
+ virtual void nodeCreated(const ModelNode &createdNode) = 0;
+ virtual void nodeAboutToBeRemoved(const ModelNode &removedNode) = 0;
+ virtual void nodeRemoved(const ModelNode &removedNode, const NodeAbstractProperty &parentProperty, PropertyChangeFlags propertyChange) = 0;
+ virtual void nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange) = 0;
+ virtual void nodeIdChanged(const ModelNode& node, const QString& newId, const QString& oldId) = 0;
+ virtual void propertiesAboutToBeRemoved(const QList<AbstractProperty>& propertyList) = 0;
+ virtual void propertiesRemoved(const QList<AbstractProperty>& propertyList) = 0;
+ virtual void variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags propertyChange) = 0;
+ virtual void bindingPropertiesChanged(const QList<BindingProperty>& propertyList, PropertyChangeFlags propertyChange) = 0;
+ virtual void nodeTypeChanged(const ModelNode &node,const QString &type, int majorVersion, int minorVersion) = 0;
+
+ virtual void selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
+ const QList<ModelNode> &lastSelectedNodeList) = 0;
+
+ virtual void fileUrlChanged(const QUrl &oldUrl, const QUrl &newUrl);
+
+ virtual void nodeSlidedToIndex(const NodeListProperty &listProperty, int newIndex, int oldIndex) = 0;
+
+ virtual void importsChanged();
+
+ virtual void auxiliaryDataChanged(const ModelNode &node, const QString &name, const QVariant &data);
+
+ virtual void customNotification(const AbstractView *view, const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> &data);
+
+ QmlModelView *toQmlModelView();
+
+protected:
+ void setModel(Model * model);
+ void removeModel();
+
+private: //functions
+ QList<ModelNode> toModelNodeList(const QList<Internal::InternalNodePointer> &nodeList) const;
+
+
+private:
+ QWeakPointer<Model> m_model;
+};
+
+CORESHARED_EXPORT QList<Internal::InternalNodePointer> toInternalNodeList(const QList<ModelNode> &nodeList);
+CORESHARED_EXPORT QList<ModelNode> toModelNodeList(const QList<Internal::InternalNodePointer> &nodeList, AbstractView *view);
+
+}
+
+#endif // ABSTRACTVIEW_H
diff --git a/src/plugins/qmldesigner/core/include/anchorline.h b/src/plugins/qmldesigner/core/include/anchorline.h
new file mode 100644
index 0000000000..5cc2793e78
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/anchorline.h
@@ -0,0 +1,118 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef ANCHORLINE_H
+#define ANCHORLINE_H
+
+#include <QMetaType>
+#include <QSharedPointer>
+#include <QWeakPointer>
+#include <QVariant>
+
+#include "corelib_global.h"
+
+namespace QmlDesigner {
+
+namespace Internal {
+ class ModelPrivate;
+ class InternalNode;
+ typedef QSharedPointer<InternalNode> InternalNodePointer;
+ typedef QWeakPointer<InternalNode> InternalNodeWeakPointer;
+
+ class InternalNodeAnchors;
+
+ class InternalNodeState;
+ typedef QSharedPointer<InternalNodeState> InternalNodeStatePointer;
+ typedef QWeakPointer<InternalNodeState> InternalNodeStateWeakPointer;
+
+ class TextToModelMerger;
+}
+
+class NodeAnchors;
+class ModelNode;
+class NodeState;
+class Model;
+
+class CORESHARED_EXPORT AnchorLine
+{
+public:
+ friend class NodeAnchors;
+ friend class Internal::InternalNodeAnchors;
+ friend class Internal::ModelPrivate;
+ friend class Internal::TextToModelMerger;
+
+ enum Type {
+ Invalid = 0x0,
+ NoAnchor = Invalid,
+ Left = 0x01,
+ Right = 0x02,
+ Top = 0x04,
+ Bottom = 0x08,
+ HorizontalCenter = 0x10,
+ VerticalCenter = 0x20,
+ Baseline = 0x40,
+
+ HorizontalMask = Left | Right | HorizontalCenter,
+ VerticalMask = Top | Bottom | VerticalCenter | Baseline,
+ AllMask = VerticalMask | HorizontalMask
+ };
+
+ AnchorLine();
+ AnchorLine(const NodeState &nodeState, Type type);
+ ~AnchorLine();
+ AnchorLine(const AnchorLine &other);
+ AnchorLine &operator =(const AnchorLine &AnchorLine);
+
+ ModelNode modelNode() const;
+ Type type() const;
+ bool isValid() const;
+
+ QVariant toVariant() const;
+
+protected:
+ Internal::InternalNodeStatePointer internalNodeState() const;
+ Internal::InternalNodePointer internalNode() const;
+
+private:
+ AnchorLine(const Internal::InternalNodeStatePointer &internalNodeState,
+ const Internal::InternalNodePointer &internalNode,
+ Model* model,
+ Type type);
+
+ Internal::InternalNodeStateWeakPointer m_internalNodeState;
+ Internal::InternalNodeWeakPointer m_internalNode;
+ QWeakPointer<Model> m_model;
+ Type m_anchorType;
+};
+
+} // namespace QmlDesigner
+
+Q_DECLARE_METATYPE(QmlDesigner::AnchorLine);
+
+#endif // ANCHORLINE_H
diff --git a/src/plugins/qmldesigner/core/include/bindingproperty.h b/src/plugins/qmldesigner/core/include/bindingproperty.h
new file mode 100644
index 0000000000..9b38930b25
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/bindingproperty.h
@@ -0,0 +1,64 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef BINDINGPROPERTY_H
+#define BINDINGPROPERTY_H
+
+#include "corelib_global.h"
+#include "abstractproperty.h"
+
+namespace QmlDesigner {
+
+class CORESHARED_EXPORT BindingProperty : public QmlDesigner::AbstractProperty
+{
+ friend class QmlDesigner::ModelNode;
+ friend class QmlDesigner::Internal::ModelPrivate;
+ friend class QmlDesigner::AbstractProperty;
+
+public:
+ void setExpression(const QString &expression);
+ QString expression() const;
+ BindingProperty& operator= (const QString &expression);
+
+ BindingProperty();
+ BindingProperty(const BindingProperty &property, AbstractView *view);
+
+ void setDynamicTypeNameAndExpression(const QString &type, const QString &expression);
+ BindingProperty& operator= (const QPair<QString, QString> &typeExpressionPair);
+
+ ModelNode resolveToModelNode() const;
+ AbstractProperty resolveToProperty() const;
+
+protected:
+ BindingProperty(const QString &propertyName, const Internal::InternalNodePointer &internalNode, Model* model, AbstractView *view);
+};
+
+} // namespace QmlDesigner
+
+#endif // BINDINGPROPERTY_H
diff --git a/src/plugins/qmldesigner/core/include/bytearraymodifier.h b/src/plugins/qmldesigner/core/include/bytearraymodifier.h
new file mode 100644
index 0000000000..31d7613289
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/bytearraymodifier.h
@@ -0,0 +1,58 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef BYTEARRAYMODIFIER_H
+#define BYTEARRAYMODIFIER_H
+
+#include <QPlainTextEdit>
+
+#include "plaintexteditmodifier.h"
+
+namespace QmlDesigner {
+
+class CORESHARED_EXPORT ByteArrayModifier: public PlainTextEditModifier
+{
+public:
+ static ByteArrayModifier* create(const QString& data);
+
+ ByteArrayModifier(QPlainTextEdit* textEdit);
+ ~ByteArrayModifier();
+
+ void setText(const QString& text);
+
+ void undo();
+ void redo();
+
+private:
+ QPlainTextEdit* m_textEdit;
+};
+
+}
+
+#endif // BYTEARRAYMODIFIER_H
diff --git a/src/plugins/qmldesigner/core/include/componenttextmodifier.h b/src/plugins/qmldesigner/core/include/componenttextmodifier.h
new file mode 100644
index 0000000000..723425531e
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/componenttextmodifier.h
@@ -0,0 +1,69 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef COMPONENTTEXTMODIFIER_H
+#define COMPONENTTEXTMODIFIER_H
+
+#include "textmodifier.h"
+
+namespace QmlDesigner {
+
+class ComponentTextModifier: public TextModifier
+{
+ Q_OBJECT
+public:
+ ComponentTextModifier(TextModifier *originalModifier, int componentStartOffset, int componentEndOffset, int rootStartOffset);
+ ~ComponentTextModifier();
+
+ virtual void replace(int offset, int length, const QString& replacement);
+ virtual void move(const MoveInfo &moveInfo);
+ virtual void startGroup();
+ virtual void flushGroup();
+ virtual void commitGroup();
+
+ virtual QTextDocument *textDocument() const;
+ virtual QString text() const;
+ virtual QTextCursor textCursor() const;
+
+ virtual void deactivateChangeSignals();
+ virtual void reactivateChangeSignals();
+
+public slots:
+ void contentsChange(int position, int charsRemoved, int charsAdded);
+
+private:
+ TextModifier *m_originalModifier;
+ int m_componentStartOffset;
+ int m_componentEndOffset;
+ int m_rootStartOffset;
+};
+
+} // namespace QmlDesigner
+
+#endif // COMPONENTTEXTMODIFIER_H
diff --git a/src/plugins/qmldesigner/core/include/corelib_global.h b/src/plugins/qmldesigner/core/include/corelib_global.h
new file mode 100644
index 0000000000..8e2ae37e9f
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/corelib_global.h
@@ -0,0 +1,56 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef CORELIB_GLOBAL_H
+#define CORELIB_GLOBAL_H
+
+// Unnecessary since core isn't a dll any more.
+
+#define CORESHARED_EXPORT
+#define TEST_CORESHARED_EXPORT
+
+//#if defined(CORE_LIBRARY)
+//# define CORESHARED_EXPORT Q_DECL_EXPORT
+//#else
+//# define CORESHARED_EXPORT Q_DECL_IMPORT
+//#endif
+//
+//#if defined(TEST_EXPORTS)
+//#if defined(CORE_LIBRARY)
+//# define TEST_CORESHARED_EXPORT Q_DECL_EXPORT
+//#else
+//# define TEST_CORESHARED_EXPORT Q_DECL_IMPORT
+//#endif
+//#else
+//# define TEST_CORESHARED_EXPORT
+//#endif
+
+#include <QtCore/qglobal.h>
+
+#endif // CORELIB_GLOBAL_H
diff --git a/src/plugins/qmldesigner/core/include/customnotifications.h b/src/plugins/qmldesigner/core/include/customnotifications.h
new file mode 100644
index 0000000000..7fcaf1e8f4
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/customnotifications.h
@@ -0,0 +1,42 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef CUSTOMNOTIFICATIONS_H
+#define CUSTOMNOTIFICATIONS_H
+
+#include <QLatin1String>
+
+namespace QmlDesigner {
+
+const QLatin1String StartRewriterAmend("__start rewriter amend__");
+const QLatin1String EndRewriterAmend("__end rewriter amend__");
+
+}
+
+#endif //CUSTOMNOTIFICATIONS_H
diff --git a/src/plugins/qmldesigner/core/include/enumeratormetainfo.h b/src/plugins/qmldesigner/core/include/enumeratormetainfo.h
new file mode 100644
index 0000000000..b7ddf090ff
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/enumeratormetainfo.h
@@ -0,0 +1,85 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef ENUMERATORMETAINFO_H
+#define ENUMERATORMETAINFO_H
+
+#include "corelib_global.h"
+
+#include <QExplicitlySharedDataPointer>
+#include <QList>
+#include <QString>
+
+
+namespace QmlDesigner {
+
+class MetaInfo;
+
+namespace Internal {
+
+class MetaInfoParser;
+class MetaInfoPrivate;
+class EnumeratorMetaInfoData;
+
+}
+
+class CORESHARED_EXPORT EnumeratorMetaInfo
+{
+ friend class QmlDesigner::MetaInfo;
+ friend class QmlDesigner::Internal::MetaInfoPrivate;
+ friend class QmlDesigner::Internal::MetaInfoParser;
+public:
+ EnumeratorMetaInfo();
+ ~EnumeratorMetaInfo();
+
+ EnumeratorMetaInfo(const EnumeratorMetaInfo &other);
+ EnumeratorMetaInfo& operator=(const EnumeratorMetaInfo &other);
+
+ QString name() const;
+ QString scope() const;
+ bool isFlagType() const;
+ bool isValid() const;
+ QString scopeAndName(const QString &combiner = QString("::")) const;
+ QList<QString> elementNames() const;
+ int elementValue(const QString &enumeratorName) const;
+
+private:
+ void setScope(const QString &scope);
+ void setName(const QString &name);
+ void setIsFlagType(bool isFlagType);
+ void setValid(bool valid);
+ void addElement(const QString &enumeratorName, int enumeratorValue);
+
+private:
+ QExplicitlySharedDataPointer<Internal::EnumeratorMetaInfoData> m_data;
+};
+
+}
+
+#endif // ENUMERATORMETAINFO_H
diff --git a/src/plugins/qmldesigner/core/include/exception.h b/src/plugins/qmldesigner/core/include/exception.h
new file mode 100644
index 0000000000..0c003242c2
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/exception.h
@@ -0,0 +1,72 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef EXCEPTION_H
+#define EXCEPTION_H
+
+#include <corelib_global.h>
+
+#include <QString>
+#include <QtDebug>
+
+namespace QmlDesigner {
+
+class CORESHARED_EXPORT Exception
+{
+public:
+ Exception(int line,
+ const QString &function,
+ const QString &file);
+ virtual ~Exception();
+
+ virtual QString type() const=0;
+ virtual QString description() const;
+
+ int line() const;
+ QString function() const;
+ QString file() const;
+ QString backTrace() const;
+
+ static void setShouldAssert(bool assert);
+ static bool shouldAssert();
+
+private:
+ int m_line;
+ QString m_function;
+ QString m_file;
+ QString m_backTrace;
+ static bool s_shouldAssert;
+};
+
+CORESHARED_EXPORT QDebug operator<<(QDebug debug, const Exception &exception);
+
+}
+
+
+#endif // EXCEPTION_H
diff --git a/src/plugins/qmldesigner/core/include/forwardview.h b/src/plugins/qmldesigner/core/include/forwardview.h
new file mode 100644
index 0000000000..a69dd6ea8c
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/forwardview.h
@@ -0,0 +1,272 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef FORWARDVIEW_H
+#define FORWARDVIEW_H
+
+#include <abstractview.h>
+
+#include <nodeabstractproperty.h>
+#include <nodelistproperty.h>
+#include <variantproperty.h>
+#include <bindingproperty.h>
+#include <QtDebug>
+
+namespace QmlDesigner {
+class NodeInstanceView;
+
+template <class ViewType>
+class ForwardView : public AbstractView
+{
+public:
+ typedef QWeakPointer<ForwardView> Pointer;
+ typedef typename ViewType::Pointer ViewTypePointer;
+
+ ForwardView(QObject *parent);
+
+ void modelAttached(Model *model);
+ void modelAboutToBeDetached(Model *model);
+
+ void nodeCreated(const ModelNode &createdNode);
+ void nodeAboutToBeRemoved(const ModelNode &removedNode);
+ void nodeRemoved(const ModelNode &removedNode, const NodeAbstractProperty &parentProperty, PropertyChangeFlags propertyChange);
+ void nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange);
+ void nodeIdChanged(const ModelNode& node, const QString& newId, const QString& oldId);
+ void propertiesAboutToBeRemoved(const QList<AbstractProperty>& propertyList);
+ void propertiesRemoved(const QList<AbstractProperty>& propertyList);
+ void variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags propertyChange);
+ void bindingPropertiesChanged(const QList<BindingProperty>& propertyList, PropertyChangeFlags propertyChange);
+ void nodeTypeChanged(const ModelNode &node,const QString &type, int majorVersion, int minorVersion);
+
+ void selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
+ const QList<ModelNode> &lastSelectedNodeList);
+
+ void fileUrlChanged(const QUrl &oldUrl, const QUrl &newUrl);
+
+ void nodeSlidedToIndex(const NodeListProperty &listProperty, int newIndex, int oldIndex);
+
+ void importsChanged();
+
+ void auxiliaryDataChanged(const ModelNode &node, const QString &name, const QVariant &data);
+
+
+protected:
+ void appendView(ViewType *view);
+ void removeView(ViewType *view);
+ QList<ViewType*> viewList() const;
+ ViewType *firstView() const;
+
+private:
+ QList<ViewTypePointer> m_targetViewList;
+};
+
+template <class ViewType>
+ForwardView<ViewType>::ForwardView(QObject *parent)
+ : AbstractView(parent)
+{
+}
+
+template <class ViewType>
+void ForwardView<ViewType>::modelAttached(Model *model)
+{
+ AbstractView::modelAttached(model);
+ foreach (const ViewTypePointer &view, m_targetViewList)
+ view->modelAttached(model);
+}
+
+template <class ViewType>
+void ForwardView<ViewType>::modelAboutToBeDetached(Model *model)
+{
+ foreach (const ViewTypePointer &view, m_targetViewList)
+ view->modelAboutToBeDetached(model);
+
+ AbstractView::modelAboutToBeDetached(model);
+}
+
+template <class ViewType>
+void ForwardView<ViewType>::nodeCreated(const ModelNode &createdNode)
+{
+ foreach (const ViewTypePointer &view, m_targetViewList)
+ view->nodeCreated(ModelNode(createdNode, view.data()));
+}
+
+template <class ViewType>
+void ForwardView<ViewType>::nodeAboutToBeRemoved(const ModelNode &removedNode)
+{
+ foreach (const ViewTypePointer &view, m_targetViewList)
+ view->nodeAboutToBeRemoved(ModelNode(removedNode, view.data()));
+}
+
+template <class ViewType>
+void ForwardView<ViewType>::nodeRemoved(const ModelNode &removedNode, const NodeAbstractProperty &parentProperty, PropertyChangeFlags propertyChange)
+{
+ foreach (const ViewTypePointer &view, m_targetViewList)
+ view->nodeRemoved(ModelNode(removedNode, view.data()), NodeAbstractProperty(parentProperty, view.data()), propertyChange);
+}
+
+template <class ViewType>
+void ForwardView<ViewType>::nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, PropertyChangeFlags propertyChange)
+{
+ foreach (const ViewTypePointer &view, m_targetViewList)
+ view->nodeReparented(ModelNode(node, view.data()), NodeAbstractProperty(newPropertyParent, view.data()), NodeAbstractProperty(oldPropertyParent, view.data()), propertyChange);
+}
+
+template <class ViewType>
+void ForwardView<ViewType>::nodeIdChanged(const ModelNode& node, const QString& newId, const QString& oldId)
+{
+ foreach (const ViewTypePointer &view, m_targetViewList)
+ view->nodeIdChanged(ModelNode(node, view.data()), newId, oldId);
+}
+
+template <class T>
+static QList<T> adjustedList(const QList<T>& oldList, AbstractView *view)
+{
+ QList<T> newList;
+
+ foreach (const T &item, oldList)
+ {
+ newList.append(T(item, view));
+ }
+
+ return newList;
+}
+
+template <class ViewType>
+void ForwardView<ViewType>::propertiesAboutToBeRemoved(const QList<AbstractProperty>& propertyList)
+{
+ foreach (const ViewTypePointer &view, m_targetViewList)
+ view->propertiesAboutToBeRemoved(adjustedList(propertyList, view.data()));
+}
+
+template <class ViewType>
+void ForwardView<ViewType>::propertiesRemoved(const QList<AbstractProperty>& propertyList)
+{
+ foreach (const ViewTypePointer &view, m_targetViewList)
+ view->propertiesRemoved(adjustedList(propertyList, view.data()));
+}
+
+template <class ViewType>
+void ForwardView<ViewType>::variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags propertyChange)
+{
+ foreach (const ViewTypePointer &view, m_targetViewList)
+ view->variantPropertiesChanged(adjustedList(propertyList, view.data()), propertyChange);
+}
+
+template <class ViewType>
+void ForwardView<ViewType>::bindingPropertiesChanged(const QList<BindingProperty>& propertyList, PropertyChangeFlags propertyChange)
+{
+ foreach (const ViewTypePointer &view, m_targetViewList)
+ view->bindingPropertiesChanged(adjustedList(propertyList, view.data()), propertyChange);
+}
+
+template <class ViewType>
+void ForwardView<ViewType>::nodeTypeChanged(const ModelNode &node,const QString &type, int majorVersion, int minorVersion)
+{
+ foreach (const ViewTypePointer &view, m_targetViewList)
+ view->nodeTypeChanged(ModelNode(node, view.data()), type, majorVersion, minorVersion);
+}
+
+template <class ViewType>
+void ForwardView<ViewType>::selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
+ const QList<ModelNode> &lastSelectedNodeList)
+{
+ foreach (const ViewTypePointer &view, m_targetViewList)
+ view->selectedNodesChanged(adjustedList(selectedNodeList, view.data()), adjustedList(lastSelectedNodeList, view.data()));
+}
+
+template <class ViewType>
+void ForwardView<ViewType>::fileUrlChanged(const QUrl &oldUrl, const QUrl &newUrl)
+{
+ AbstractView::fileUrlChanged(oldUrl, newUrl);
+
+ foreach (const ViewTypePointer &view, m_targetViewList)
+ view->fileUrlChanged(oldUrl, newUrl);
+}
+
+template <class ViewType>
+void ForwardView<ViewType>::nodeSlidedToIndex(const NodeListProperty &listProperty, int newIndex, int oldIndex)
+{
+ foreach (const ViewTypePointer &view, m_targetViewList)
+ view->nodeSlidedToIndex(NodeListProperty(listProperty, view.data()), newIndex, oldIndex);
+}
+
+template <class ViewType>
+void ForwardView<ViewType>::importsChanged()
+{
+ AbstractView::importsChanged();
+
+ foreach (const ViewTypePointer &view, m_targetViewList)
+ view->importsChanged();
+}
+
+template <class ViewType>
+void ForwardView<ViewType>::auxiliaryDataChanged(const ModelNode &node, const QString &name, const QVariant &data)
+{
+ AbstractView::auxiliaryDataChanged(node, name, data);
+
+ foreach (const ViewTypePointer &view, m_targetViewList)
+ view->auxiliaryDataChanged(ModelNode(node, view.data()), name, data);
+}
+
+template <class ViewType>
+void ForwardView<ViewType>::appendView(ViewType *view)
+{
+ m_targetViewList.append(view);
+}
+
+template <class ViewType>
+void ForwardView<ViewType>::removeView(ViewType *view)
+{
+ m_targetViewList.append(view);
+}
+
+template <class ViewType>
+QList<ViewType*> ForwardView<ViewType>::viewList() const
+{
+ QList<ViewType*> newList;
+
+ foreach (const ViewTypePointer &view, m_targetViewList)
+ newList.append(view.data());
+
+ return newList;
+}
+
+template <class ViewType>
+ViewType *ForwardView<ViewType>::firstView() const
+{
+ if (m_targetViewList.isEmpty())
+ return 0;
+
+ return m_targetViewList.first().data();
+}
+
+
+} // namespace QmlDesigner
+
+#endif // FORWARDVIEW_H
diff --git a/src/plugins/qmldesigner/core/include/import.h b/src/plugins/qmldesigner/core/include/import.h
new file mode 100644
index 0000000000..f10f89b5f4
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/import.h
@@ -0,0 +1,76 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef IMPORT_H
+#define IMPORT_H
+
+#include <QtCore/QString>
+#include <QtCore/QUrl>
+
+#include "corelib_global.h"
+
+namespace QmlDesigner {
+
+class CORESHARED_EXPORT Import
+{
+public:
+ static Import createLibraryImport(const QUrl &url, const QString &version = QString(), const QString &alias = QString());
+ static Import createFileImport(const QString &file, const QString &version = QString(), const QString &alias = QString());
+ static Import empty();
+
+ bool isEmpty() const { return m_url.isEmpty() && m_file.isEmpty(); }
+ bool isFileImport() const { return m_url.isEmpty() && !m_file.isEmpty(); }
+ bool isLibraryImport() const { return !m_url.isEmpty() && m_file.isEmpty(); }
+ bool hasVersion() const { return !m_version.isEmpty(); }
+ bool hasAlias() const { return !m_alias.isEmpty(); }
+
+ QUrl url() const { return m_url; }
+ QString file() const { return m_file; }
+ QString version() const { return m_version; }
+ QString alias() const { return m_alias; }
+
+ QString toString(bool addSemicolon = false) const;
+
+ bool operator==(const Import &other) const;
+
+private:
+ Import(const QUrl &url, const QString &file, const QString &version, const QString &alias);
+
+private:
+ QUrl m_url;
+ QString m_file;
+ QString m_version;
+ QString m_alias;
+};
+
+CORESHARED_EXPORT uint qHash(const Import &import);
+
+} // namespace QmlDesigner
+
+#endif // IMPORT_H
diff --git a/src/plugins/qmldesigner/core/include/invalidargumentexception.h b/src/plugins/qmldesigner/core/include/invalidargumentexception.h
new file mode 100644
index 0000000000..f18480cb80
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/invalidargumentexception.h
@@ -0,0 +1,55 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef INVALIDARGUMENTEXCEPTION_H
+#define INVALIDARGUMENTEXCEPTION_H
+
+#include "exception.h"
+
+
+namespace QmlDesigner {
+
+class CORESHARED_EXPORT InvalidArgumentException : public Exception
+{
+public:
+ InvalidArgumentException(int line,
+ const QString &function,
+ const QString &file,
+ const QString &argument);
+
+ QString type() const;
+ QString argument() const;
+
+private:
+ const QString m_argument;
+};
+
+}
+
+#endif // INVALIDARGUMENTEXCEPTION_H
diff --git a/src/plugins/qmldesigner/core/include/invalididexception.h b/src/plugins/qmldesigner/core/include/invalididexception.h
new file mode 100644
index 0000000000..fd045bc32a
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/invalididexception.h
@@ -0,0 +1,50 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef INVALIDIDEXCEPTION_H
+#define INVALIDIDEXCEPTION_H
+
+#include "invalidargumentexception.h"
+
+namespace QmlDesigner {
+
+class CORESHARED_EXPORT InvalidIdException : public InvalidArgumentException
+{
+public:
+ InvalidIdException(int line,
+ const QString &function,
+ const QString &file);
+
+ QString type() const;
+
+};
+
+}
+
+#endif // INVALIDIDEXCEPTION_H
diff --git a/src/plugins/qmldesigner/core/include/invalidmetainfoexception.h b/src/plugins/qmldesigner/core/include/invalidmetainfoexception.h
new file mode 100644
index 0000000000..619b3bc101
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/invalidmetainfoexception.h
@@ -0,0 +1,50 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef INVALIDMETAINFOEXCEPTION_H
+#define INVALIDMETAINFOEXCEPTION_H
+
+#include "exception.h"
+
+namespace QmlDesigner {
+
+class CORESHARED_EXPORT InvalidMetaInfoException : public Exception
+{
+public:
+ InvalidMetaInfoException(int line,
+ const QString &function,
+ const QString &file);
+
+ QString type() const;
+
+};
+
+}
+
+#endif // INVALIDMETAINFOEXCEPTION_H
diff --git a/src/plugins/qmldesigner/core/include/invalidmodelnodeexception.h b/src/plugins/qmldesigner/core/include/invalidmodelnodeexception.h
new file mode 100644
index 0000000000..b3e73cae22
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/invalidmodelnodeexception.h
@@ -0,0 +1,50 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef INVALIDMODELNODEEXCEPTION_H
+#define INVALIDMODELNODEEXCEPTION_H
+
+#include "exception.h"
+
+namespace QmlDesigner {
+
+class CORESHARED_EXPORT InvalidModelNodeException : public Exception
+{
+public:
+ InvalidModelNodeException(int line,
+ const QString &function,
+ const QString &file);
+
+ QString type() const;
+
+};
+
+}
+
+#endif // INVALIDMODELNODEEXCEPTION_H
diff --git a/src/plugins/qmldesigner/core/include/invalidmodelstateexception.h b/src/plugins/qmldesigner/core/include/invalidmodelstateexception.h
new file mode 100644
index 0000000000..bafc3aa740
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/invalidmodelstateexception.h
@@ -0,0 +1,50 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef INVALIDMODELSTATEEXCEPTION_H
+#define INVALIDMODELSTATEEXCEPTION_H
+
+#include "exception.h"
+
+namespace QmlDesigner {
+
+class CORESHARED_EXPORT InvalidModelStateException : public Exception
+{
+public:
+ InvalidModelStateException(int line,
+ const QString &function,
+ const QString &file);
+
+
+ QString type() const;
+};
+
+} // namespace QmlDesigner
+
+#endif // INVALIDMODELSTATEEXCEPTION_H
diff --git a/src/plugins/qmldesigner/core/include/invalidnodeinstanceexception.h b/src/plugins/qmldesigner/core/include/invalidnodeinstanceexception.h
new file mode 100644
index 0000000000..f6cc1ba733
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/invalidnodeinstanceexception.h
@@ -0,0 +1,48 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef INVALIDNODEINSTANCEEXCEPTION_H
+#define INVALIDNODEINSTANCEEXCEPTION_H
+
+#include "exception.h"
+
+namespace QmlDesigner {
+
+class CORESHARED_EXPORT InvalidNodeInstanceException : public Exception
+{
+public:
+ InvalidNodeInstanceException(int line,
+ const QString &function,
+ const QString &file);
+ QString type() const;
+};
+
+}
+
+#endif // INVALIDNODEINSTANCEEXCEPTION_H
diff --git a/src/plugins/qmldesigner/core/include/invalidnodestateexception.h b/src/plugins/qmldesigner/core/include/invalidnodestateexception.h
new file mode 100644
index 0000000000..826f6644b7
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/invalidnodestateexception.h
@@ -0,0 +1,50 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef INVALIDNODESTATEEXCEPTION_H
+#define INVALIDNODESTATEEXCEPTION_H
+
+#include <exception.h>
+
+namespace QmlDesigner {
+
+class CORESHARED_EXPORT InvalidNodeStateException : public Exception
+{
+public:
+ InvalidNodeStateException(int line,
+ const QString &function,
+ const QString &file);
+
+ QString type() const;
+
+};
+
+} // namespace QmlDesigner
+
+#endif // INVALIDNODESTATEEXCEPTION_H
diff --git a/src/plugins/qmldesigner/core/include/invalidpropertyexception.h b/src/plugins/qmldesigner/core/include/invalidpropertyexception.h
new file mode 100644
index 0000000000..db5dc01621
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/invalidpropertyexception.h
@@ -0,0 +1,54 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef INVALIDPROPERTYEXCEPTION_H
+#define INVALIDPROPERTYEXCEPTION_H
+
+#include "exception.h"
+
+namespace QmlDesigner {
+
+class CORESHARED_EXPORT InvalidPropertyException : public Exception
+{
+public:
+ InvalidPropertyException(int line,
+ const QString &function,
+ const QString &file,
+ const QString &argument);
+
+ QString type() const;
+ QString argument() const;
+
+private:
+ const QString m_argument;
+};
+
+} // namespace QmlDesigner
+
+#endif // INVALIDPROPERTYEXCEPTION_H
diff --git a/src/plugins/qmldesigner/core/include/invalidqmlsourceexception.h b/src/plugins/qmldesigner/core/include/invalidqmlsourceexception.h
new file mode 100644
index 0000000000..63918dda7e
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/invalidqmlsourceexception.h
@@ -0,0 +1,54 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef INVALIDQMLSOURCEEXCEPTION_H
+#define INVALIDQMLSOURCEEXCEPTION_H
+
+#include <exception.h>
+
+namespace QmlDesigner {
+
+class CORESHARED_EXPORT InvalidQmlSourceException : public QmlDesigner::Exception
+{
+public:
+ InvalidQmlSourceException(int line,
+ const QString &function,
+ const QString &file,
+ const QString &qmlSource = QString());
+
+ QString type() const;
+ QString description() const;
+
+private:
+ QString m_qmlSource;
+};
+
+} // namespace QmlDesigner
+
+#endif // INVALIDQMLSOURCEEXCEPTION_H
diff --git a/src/plugins/qmldesigner/core/include/invalidreparentingexception.h b/src/plugins/qmldesigner/core/include/invalidreparentingexception.h
new file mode 100644
index 0000000000..e3f4237c2b
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/invalidreparentingexception.h
@@ -0,0 +1,49 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef INVALIDREPARENTINGEXCEPTION_H
+#define INVALIDREPARENTINGEXCEPTION_H
+
+#include "exception.h"
+
+namespace QmlDesigner {
+
+class CORESHARED_EXPORT InvalidReparentingException : public Exception
+{
+public:
+ InvalidReparentingException(int line,
+ const QString &function,
+ const QString &file);
+
+ QString type() const;
+};
+
+} // namespace QmlDesigner
+
+#endif // INVALIDREPARENTINGEXCEPTION_H
diff --git a/src/plugins/qmldesigner/core/include/invalidslideindexexception.h b/src/plugins/qmldesigner/core/include/invalidslideindexexception.h
new file mode 100644
index 0000000000..dd41c4a284
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/invalidslideindexexception.h
@@ -0,0 +1,48 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef INVALIDSLIDEINDEXEXCEPTION_H
+#define INVALIDSLIDEINDEXEXCEPTION_H
+
+#include "exception.h"
+
+namespace QmlDesigner {
+
+class CORESHARED_EXPORT InvalidSlideIndexException : public Exception
+{
+public:
+ InvalidSlideIndexException(int line,
+ const QString &function,
+ const QString &file);
+ QString type() const;
+};
+
+} // namespace QmlDesigner
+
+#endif // INVALIDSLIDEINDEXEXCEPTION_H
diff --git a/src/plugins/qmldesigner/core/include/itemlibraryinfo.h b/src/plugins/qmldesigner/core/include/itemlibraryinfo.h
new file mode 100644
index 0000000000..05ef252ec2
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/itemlibraryinfo.h
@@ -0,0 +1,100 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef ItemLibraryINFO_H
+#define ItemLibraryINFO_H
+
+#include "corelib_global.h"
+
+#include <QExplicitlySharedDataPointer>
+#include <QList>
+#include <QString>
+#include <QIcon>
+#include "propertycontainer.h"
+#include <qml.h>
+
+namespace QmlDesigner {
+
+class NodeMetaInfo;
+
+namespace Internal {
+
+class ItemLibraryInfoData;
+}
+
+class ItemLibraryInfo;
+
+CORESHARED_EXPORT QDataStream& operator<<(QDataStream& stream, const ItemLibraryInfo& ItemLibraryInfo);
+CORESHARED_EXPORT QDataStream& operator>>(QDataStream& stream, ItemLibraryInfo& ItemLibraryInfo);
+
+class CORESHARED_EXPORT ItemLibraryInfo
+{
+ friend class QmlDesigner::MetaInfo;
+ friend class QmlDesigner::Internal::MetaInfoParser;
+ friend CORESHARED_EXPORT QDataStream& QmlDesigner::operator<<(QDataStream& stream, const ItemLibraryInfo& image);
+ friend CORESHARED_EXPORT QDataStream& QmlDesigner::operator>>(QDataStream& stream, ItemLibraryInfo& image);
+public:
+ ItemLibraryInfo();
+ ~ItemLibraryInfo();
+
+ QString name() const;
+ QString typeName() const;
+ QIcon icon() const;
+ int majorVersion() const;
+ int minorVersion() const;
+ QString category() const;
+ QIcon dragIcon() const;
+ QString qml() const;
+
+ ItemLibraryInfo(const ItemLibraryInfo &other);
+ ItemLibraryInfo& operator=(const ItemLibraryInfo &other);
+
+ typedef QmlDesigner::PropertyContainer Property;
+
+ QList<Property> properties() const;
+
+ void setTypeName(const QString &typeName);
+ void setMajorVersion(int majorNumber);
+ void setMinorVersion(int minorNumber);
+ void setName(const QString &name);
+ void setIcon(const QIcon &icon);
+ void addProperty(const Property &p);
+ void addProperty(QString &name, QString &type, QString &value);
+ void setDragIcon(const QIcon &icon);
+ void setCategory(const QString &category);
+ void setQml(const QString &qml);
+private:
+ QExplicitlySharedDataPointer<Internal::ItemLibraryInfoData> m_data;
+};
+
+}
+
+Q_DECLARE_METATYPE(QmlDesigner::ItemLibraryInfo)
+
+#endif // ItemLibraryINFO_H
diff --git a/src/plugins/qmldesigner/core/include/iwidgetplugin.h b/src/plugins/qmldesigner/core/include/iwidgetplugin.h
new file mode 100644
index 0000000000..c151aaa948
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/iwidgetplugin.h
@@ -0,0 +1,52 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef IWIDGETPLUGIN_H
+#define IWIDGETPLUGIN_H
+
+#include <QtCore/QObject>
+
+#define QMLDESIGNER_WIDGETPLUGIN_INTERFACE "com.Nokia.QmlDesigner.IWidgetPlugin.v10"
+
+namespace QmlDesigner {
+
+class IWidgetPlugin
+{
+public:
+ virtual ~IWidgetPlugin() {}
+
+ virtual QString metaInfo() = 0;
+ virtual QString pluginName() = 0;
+};
+
+} // namespace QmlDesigner
+
+Q_DECLARE_INTERFACE(QmlDesigner::IWidgetPlugin, QMLDESIGNER_WIDGETPLUGIN_INTERFACE)
+
+#endif // IWIDGETPLUGIN_H
diff --git a/src/plugins/qmldesigner/core/include/mathutils.h b/src/plugins/qmldesigner/core/include/mathutils.h
new file mode 100644
index 0000000000..62ece009fa
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/mathutils.h
@@ -0,0 +1,46 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef MATHUTILS_H
+#define MATHUTILS_H
+
+#include <QtGlobal>
+
+namespace QmlDesigner {
+
+inline double round(double value, int digits)
+{
+ double factor = digits * 10.;
+ return double(qRound64(value * factor)) / factor;
+}
+
+
+}
+
+#endif // MATHUTILS_H
diff --git a/src/plugins/qmldesigner/core/include/metainfo.h b/src/plugins/qmldesigner/core/include/metainfo.h
new file mode 100644
index 0000000000..329dc1c0f3
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/metainfo.h
@@ -0,0 +1,123 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef METAINFO_H
+#define METAINFO_H
+
+#include "corelib_global.h"
+
+#include <QMultiHash>
+#include <QString>
+#include <QStringList>
+#include <QtCore/QSharedPointer>
+
+#include <nodemetainfo.h>
+#include "propertymetainfo.h"
+#include "itemlibraryinfo.h"
+#include "enumeratormetainfo.h"
+
+
+namespace QmlDesigner {
+
+class ModelNode;
+class AbstractProperty;
+
+namespace Internal {
+ class MetaInfoPrivate;
+ class ModelPrivate;
+ class SubComponentManagerPrivate;
+ typedef QSharedPointer<MetaInfoPrivate> MetaInfoPrivatePointer;
+}
+
+CORESHARED_EXPORT bool operator==(const MetaInfo &first, const MetaInfo &second);
+CORESHARED_EXPORT bool operator!=(const MetaInfo &first, const MetaInfo &second);
+
+class CORESHARED_EXPORT MetaInfo
+{
+ friend class QmlDesigner::Internal::MetaInfoPrivate;
+ friend class QmlDesigner::Internal::ModelPrivate;
+ friend class QmlDesigner::Internal::MetaInfoParser;
+ friend class QmlDesigner::Internal::SubComponentManagerPrivate;
+ friend class QmlDesigner::NodeMetaInfo;
+ friend bool QmlDesigner::operator==(const MetaInfo &, const MetaInfo &);
+
+public:
+ MetaInfo(const MetaInfo &metaInfo);
+ ~MetaInfo();
+ MetaInfo& operator=(const MetaInfo &other);
+
+ bool hasNodeMetaInfo(const QString &typeName, int majorVersion = 4, int minorVersion = 6) const;
+ NodeMetaInfo nodeMetaInfo(const QString &typeName, int majorVersion = 4, int minorVersion = 6) const;
+
+ // TODO: Move these to private
+ bool isSubclassOf(const QString &className, const QString &superClassName) const;
+ bool isSubclassOf(const ModelNode &modelNode, const QString &superClassName) const;
+
+ bool hasEnumerator(const QString &enumeratorName) const;
+ EnumeratorMetaInfo enumerator(const QString &enumeratorName) const;
+
+ QStringList itemLibraryItems() const;
+ QList<ItemLibraryInfo> itemLibraryRepresentations(const NodeMetaInfo &nodeMetaInfo) const;
+ ItemLibraryInfo itemLibraryRepresentation(const QString &name) const;
+
+public:
+ static MetaInfo global();
+ static void clearGlobal();
+
+ static void setPluginPaths(const QStringList &paths);
+
+private:
+ QStringList superClasses(const QString &className) const;
+ QStringList directSuperClasses(const QString &className) const;
+ QList<NodeMetaInfo> superClasses(const NodeMetaInfo &nodeMetaInfo) const;
+ QList<NodeMetaInfo> directSuperClasses(const NodeMetaInfo &nodeMetaInfo) const;
+
+ void addSuperClassRelationship(const QString &superClassName, const QString &className);
+
+ void addNodeInfo(NodeMetaInfo &info, const QString &baseType);
+ void removeNodeInfo(NodeMetaInfo &info);
+ void replaceNodeInfo(NodeMetaInfo &oldInfo, NodeMetaInfo &newInfo, const QString &baseType);
+
+ EnumeratorMetaInfo addEnumerator(const QString &enumeratorScope, const QString &enumeratorName);
+ EnumeratorMetaInfo addFlag(const QString &enumeratorScope, const QString &enumeratorName);
+ ItemLibraryInfo addItemLibraryInfo(const NodeMetaInfo &nodeMetaInfo, const QString &itemLibraryRepresentationName);
+
+ bool isGlobal() const;
+
+private:
+ MetaInfo();
+
+ Internal::MetaInfoPrivatePointer m_p;
+ static MetaInfo s_global;
+ static QStringList s_pluginDirs;
+};
+
+} //namespace QmlDesigner
+
+#endif // METAINFO_H
diff --git a/src/plugins/qmldesigner/core/include/metainfoparser.h b/src/plugins/qmldesigner/core/include/metainfoparser.h
new file mode 100644
index 0000000000..757806a939
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/metainfoparser.h
@@ -0,0 +1,77 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef METAINFOPARSER_H
+#define METAINFOPARSER_H
+
+#include "corelib_global.h"
+#include <QtCore/QXmlStreamReader>
+#include <QtCore/QString>
+#include <QtCore/QFile>
+#include <metainfo.h>
+
+namespace QmlDesigner {
+
+class NodeMetaInfo;
+class EnumeratorMetaInfo;
+class ItemLibraryInfo;
+
+namespace Internal {
+
+
+class TEST_CORESHARED_EXPORT MetaInfoParser
+{
+public:
+ MetaInfoParser(const MetaInfo &metaInfo);
+
+ void parseFile(const QString &path);
+
+protected:
+ void errorHandling(QXmlStreamReader &reader, QFile &file);
+ void tokenHandler(QXmlStreamReader &reader);
+ void metaInfoHandler(QXmlStreamReader &reader);
+ void handleMetaInfoElement(QXmlStreamReader &reader);
+ void handleEnumElement(QXmlStreamReader &reader);
+ void handleEnumElementElement(QXmlStreamReader &reader, EnumeratorMetaInfo &enumeratorMetaInfo);
+ void handleFlagElement(QXmlStreamReader &reader);
+ void handleFlagElementElement(QXmlStreamReader &reader, EnumeratorMetaInfo &enumeratorMetaInfo);
+ void handleNodeElement(QXmlStreamReader &reader);
+ void handleNodeInheritElement(QXmlStreamReader &reader, const QString &className);
+ void handleNodeItemLibraryRepresentationElement(QXmlStreamReader &reader, const QString &className);
+ void handleAbstractPropertyElement(QXmlStreamReader &reader, NodeMetaInfo &nodeMetaInfo);
+ void handleAbstractPropertyDefaultValueElement(QXmlStreamReader &reader, NodeMetaInfo &nodeMetaInfo);
+ void handleItemLibraryInfoPropertyElement(QXmlStreamReader &reader, ItemLibraryInfo &ItemLibraryInfo);
+
+private:
+ MetaInfo m_metaInfo;
+};
+
+}
+}
+#endif // METAINFOPARSER_H
diff --git a/src/plugins/qmldesigner/core/include/model.h b/src/plugins/qmldesigner/core/include/model.h
new file mode 100644
index 0000000000..ce6715433d
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/model.h
@@ -0,0 +1,109 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef DESIGNERMODEL_H
+#define DESIGNERMODEL_H
+
+#include <corelib_global.h>
+#include <QtCore/QObject>
+#include <QtCore/QMimeData>
+#include <QtCore/QPair>
+#include <QtDeclarative/QmlError>
+
+#include <import.h>
+
+class QUrl;
+
+namespace QmlDesigner {
+
+namespace Internal {
+ class ModelPrivate;
+}
+
+class AnchorLine;
+class ModelNode;
+class NodeState;
+class AbstractView;
+class WidgetQueryView;
+class NodeStateChangeSet;
+class MetaInfo;
+class ModelState;
+class NodeAnchors;
+class AbstractProperty;
+
+typedef QList<QPair<QString, QVariant> > PropertyListType;
+
+class CORESHARED_EXPORT Model : public QObject
+{
+ friend class QmlDesigner::ModelNode;
+ friend class QmlDesigner::NodeState;
+ friend class QmlDesigner::ModelState;
+ friend class QmlDesigner::NodeAnchors;
+ friend class QmlDesigner::AbstractProperty;
+ friend class QmlDesigner::AbstractView;
+ friend class Internal::ModelPrivate;
+
+ Q_DISABLE_COPY(Model)
+ Q_OBJECT
+public:
+ enum ViewNotification { NotifyView, DoNotNotifyView };
+
+ virtual ~Model();
+
+ static Model *create(QString type, int major = 4, int minor = 6);
+
+ Model *masterModel() const;
+ void setMasterModel(Model *model);
+
+ QUrl fileUrl() const;
+ void setFileUrl(const QUrl &url);
+
+ const MetaInfo metaInfo() const;
+ MetaInfo metaInfo();
+
+ void attachView(AbstractView *view);
+ void detachView(AbstractView *view, ViewNotification emitDetachNotify = NotifyView);
+
+ // Editing sub-components:
+
+ // Imports:
+ QSet<Import> imports() const;
+ void addImport(const Import &import);
+ void removeImport(const Import &import);
+
+protected:
+ Model();
+
+public:
+ Internal::ModelPrivate *m_d;
+};
+
+}
+
+#endif // DESIGNERMODEL_H
diff --git a/src/plugins/qmldesigner/core/include/modelmerger.h b/src/plugins/qmldesigner/core/include/modelmerger.h
new file mode 100644
index 0000000000..39c96f799e
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/modelmerger.h
@@ -0,0 +1,59 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef MODELMERGER_H
+#define MODELMERGER_H
+
+
+#include <QWeakPointer>
+
+namespace QmlDesigner {
+
+class AbstractView;
+class ModelNode;
+
+class ModelMerger
+{
+public:
+ ModelMerger(AbstractView *view) : m_view(view) {}
+
+ ModelNode insertModel(const ModelNode &modelNode);
+ void replaceModel(const ModelNode &modelNode);
+
+protected:
+ AbstractView *view() const
+ { return m_view.data(); }
+
+private:
+ QWeakPointer<AbstractView> m_view;
+};
+
+} //namespace QmlDesigner
+
+#endif // MODELMERGER_H
diff --git a/src/plugins/qmldesigner/core/include/modelnode.h b/src/plugins/qmldesigner/core/include/modelnode.h
new file mode 100644
index 0000000000..843af5f859
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/modelnode.h
@@ -0,0 +1,186 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef DESIGNERNODE_H
+#define DESIGNERNODE_H
+
+#include "corelib_global.h"
+#include <QWeakPointer>
+#include <QtCore/QList>
+#include <QtCore/QMetaType>
+#include <QVariant>
+
+class QTextStream;
+
+namespace QmlDesigner {
+
+namespace Internal {
+ class InternalNode;
+ class ModelPrivate;
+ class InternalNode;
+ class InternalProperty;
+
+ typedef QSharedPointer<InternalNode> InternalNodePointer;
+ typedef QSharedPointer<InternalProperty> InternalPropertyPointer;
+ typedef QWeakPointer<InternalNode> InternalNodeWeakPointer;
+}
+class NodeMetaInfo;
+class AbstractProperty;
+class BindingProperty;
+class VariantProperty;
+class Model;
+class AbstractView;
+class NodeListProperty;
+class NodeProperty;
+class NodeAbstractProperty;
+class NodeInstance;
+class ModelNode;
+
+CORESHARED_EXPORT QList<Internal::InternalNodePointer> toInternalNodeList(const QList<ModelNode> &nodeList);
+
+typedef QList<QPair<QString, QVariant> > PropertyListType;
+
+class CORESHARED_EXPORT ModelNode
+{
+ friend CORESHARED_EXPORT bool operator ==(const ModelNode &firstNode, const ModelNode &secondNode);
+ friend CORESHARED_EXPORT bool operator !=(const ModelNode &firstNode, const ModelNode &secondNode);
+ friend CORESHARED_EXPORT uint qHash(const ModelNode & node);
+ friend CORESHARED_EXPORT QDebug operator<<(QDebug debug, const ModelNode &modelNode);
+ friend CORESHARED_EXPORT bool operator <(const ModelNode &firstNode, const ModelNode &secondNode);
+ friend CORESHARED_EXPORT QList<Internal::InternalNodePointer> QmlDesigner::toInternalNodeList(const QList<ModelNode> &nodeList);
+ friend class QmlDesigner::Model;
+ friend class QmlDesigner::AbstractView;
+ friend class QmlDesigner::NodeListProperty;
+ friend class QmlDesigner::Internal::ModelPrivate;
+ friend class QmlDesigner::NodeAbstractProperty;
+ friend class QmlDesigner::NodeProperty;
+
+public:
+ ModelNode();
+ ModelNode(const Internal::InternalNodePointer &internalNode, Model *model, AbstractView *view);
+ ModelNode(const ModelNode modelNode, AbstractView *view);
+ ModelNode(const ModelNode &other);
+ ~ModelNode();
+
+ ModelNode& operator=(const ModelNode &other);
+ QString type() const;
+ void changeType(const QString &type, int majorVersion, int minorVersion);
+ QString simplifiedTypeName() const;
+ int minorVersion() const;
+ int majorVersion() const;
+
+ bool isValid() const;
+ bool isInHierarchy() const;
+
+
+ NodeAbstractProperty parentProperty() const;
+ void setParentProperty(NodeAbstractProperty parent);
+ void setParentProperty(const ModelNode &newParentNode, const QString &propertyName);
+ bool hasParentProperty() const;
+
+ ModelNode addChildNode(const QString &nodeTypeString, int majorVersion, int minorVersion, const QString &propertyName, const PropertyListType &propertyList = PropertyListType());
+ const QList<ModelNode> allDirectSubModelNodes() const;
+ const QList<ModelNode> allSubModelNodes() const;
+ bool hasAnySubModelNodes() const;
+
+ //###
+
+ AbstractProperty property(const QString &name) const;
+ VariantProperty variantProperty(const QString &name) const;
+ BindingProperty bindingProperty(const QString &name) const;
+ NodeListProperty nodeListProperty(const QString &name) const;
+ NodeProperty nodeProperty(const QString &name) const;
+ NodeAbstractProperty nodeAbstractProperty(const QString &name) const;
+
+ void removeProperty(const QString &name); //### also implement in AbstractProperty
+ QList<AbstractProperty> properties() const;
+ QList<VariantProperty> variantProperties() const;
+ QList<NodeAbstractProperty> nodeAbstractProperties() const;
+ QList<NodeProperty> nodeProperties() const;
+ QList<NodeListProperty> nodeListProperties() const;
+ QList<BindingProperty> bindingProperties() const;
+ QStringList propertyNames() const;
+
+ bool hasProperties() const;
+ bool hasProperty(const QString &name) const;
+ bool hasVariantProperty(const QString &name) const;
+ bool hasBindingProperty(const QString &name) const;
+ bool hasNodeAbstracProperty(const QString &name) const;
+ bool hasNodeProperty(const QString &name) const;
+ bool hasNodeListProperty(const QString &name) const;
+
+ //###
+ void destroy();
+
+ QString id() const;
+ QString validId();
+ void setId(const QString &id);
+ static bool isValidId(const QString &id);
+
+ Model *model() const;
+ AbstractView *view() const;
+
+ const NodeMetaInfo metaInfo() const;
+
+ bool isSelected() const;
+ bool isRootNode() const;
+
+ bool isAncestorOf(const ModelNode &node) const;
+ void selectNode();
+ void deselectNode();
+
+ static int variantUserType();
+ QVariant toVariant() const;
+
+ QVariant auxiliaryData(const QString &name) const;
+ void setAuxiliaryData(const QString &name, const QVariant &data);
+ bool hasAuxiliaryData(const QString &name) const;
+
+private: // functions
+ Internal::InternalNodePointer internalNode() const;
+ QString generateNewId() const;
+
+private: // variables
+ Internal::InternalNodePointer m_internalNode;
+ QWeakPointer<Model> m_model;
+ QWeakPointer<AbstractView> m_view;
+};
+
+CORESHARED_EXPORT bool operator ==(const ModelNode &firstNode, const ModelNode &secondNode);
+CORESHARED_EXPORT bool operator !=(const ModelNode &firstNode, const ModelNode &secondNode);
+CORESHARED_EXPORT uint qHash(const ModelNode & node);
+CORESHARED_EXPORT bool operator <(const ModelNode &firstNode, const ModelNode &secondNode);
+CORESHARED_EXPORT QDebug operator<<(QDebug debug, const ModelNode &modelNode);
+CORESHARED_EXPORT QTextStream& operator<<(QTextStream &stream, const ModelNode &modelNode);
+}
+
+Q_DECLARE_METATYPE(QmlDesigner::ModelNode)
+Q_DECLARE_METATYPE(QList<QmlDesigner::ModelNode>)
+
+#endif // DESIGNERNODE_H
diff --git a/src/plugins/qmldesigner/core/include/modelnodepositionstorage.h b/src/plugins/qmldesigner/core/include/modelnodepositionstorage.h
new file mode 100644
index 0000000000..c9b93805d1
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/modelnodepositionstorage.h
@@ -0,0 +1,82 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef MODELNODEPOSITIONSTORAGE_H
+#define MODELNODEPOSITIONSTORAGE_H
+
+#include "modelnode.h"
+
+namespace QmlDesigner {
+namespace Internal {
+
+class ModelNodePositionStorage
+{
+public:
+ void clear()
+ { m_rewriterData.clear(); }
+
+ int nodeOffset(const ModelNode &modelNode);
+ void setNodeOffset(const ModelNode &modelNode, int fileOffset);
+ void cleanupInvalidOffsets();
+ void removeNodeOffset(const ModelNode &node)
+ { m_rewriterData.remove(node); }
+
+ QList<ModelNode> modelNodes() const;
+
+public:
+ static const int INVALID_LOCATION = -1;
+
+private:
+ class RewriterData { //custom rewriter data for each node can be kept here
+ public:
+ RewriterData(int offset = INVALID_LOCATION)
+ : _offset(offset)
+ {}
+
+ bool isValid() const
+ { return _offset != INVALID_LOCATION; }
+
+ int offset() const
+ { return _offset; }
+
+ void setOffset(int offset)
+ { _offset = offset; }
+
+ private:
+ int _offset;
+ };
+
+private:
+ QHash<ModelNode, RewriterData> m_rewriterData;
+};
+
+} // namespace Internal
+} // namespace QmlDesigner
+
+#endif // MODELNODEPOSITIONSTORAGE_H
diff --git a/src/plugins/qmldesigner/core/include/modelutilities.h b/src/plugins/qmldesigner/core/include/modelutilities.h
new file mode 100644
index 0000000000..2dd369c4f3
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/modelutilities.h
@@ -0,0 +1,51 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef MODELUTILITIES_H
+#define MODELUTILITIES_H
+
+#include "corelib_global.h"
+#include <modelnode.h>
+#include <nodeinstance.h>
+
+namespace QmlDesigner {
+namespace ModelUtilities {
+
+CORESHARED_EXPORT bool canReparent(const ModelNode &child, const ModelNode &parent);
+CORESHARED_EXPORT bool isGraphicsItem(const ModelNode &node);
+CORESHARED_EXPORT bool isQWidget(const ModelNode &node);
+CORESHARED_EXPORT QVariant parseProperty(const QString &className, const QString &propertyName, const QString &value);
+CORESHARED_EXPORT void setAbsolutePosition(ModelNode node, QPointF position);
+CORESHARED_EXPORT QList<ModelNode> descendantNodes(const ModelNode &parent);
+
+CORESHARED_EXPORT NodeInstance instanceForNode(const ModelNode &node);
+} //namespace ModelUtilities
+} //namespace QmlDesigner
+
+#endif //MODELUTILITIES_H
diff --git a/src/plugins/qmldesigner/core/include/modificationgroupexception.h b/src/plugins/qmldesigner/core/include/modificationgroupexception.h
new file mode 100644
index 0000000000..e9709eed01
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/modificationgroupexception.h
@@ -0,0 +1,47 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef MODIFICATIONGROUPEXCEPTION_H
+#define MODIFICATIONGROUPEXCEPTION_H
+
+#include "exception.h"
+
+namespace QmlDesigner {
+
+class CORESHARED_EXPORT ModificationGroupException: public Exception
+{
+public:
+ ModificationGroupException(int line, const QString &function, const QString &file);
+
+ QString type() const;
+};
+
+}
+
+#endif // MODIFICATIONGROUPEXCEPTION_H
diff --git a/src/plugins/qmldesigner/core/include/modificationgrouptoken.h b/src/plugins/qmldesigner/core/include/modificationgrouptoken.h
new file mode 100644
index 0000000000..9110e1ab51
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/modificationgrouptoken.h
@@ -0,0 +1,75 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef MODIFICATIONGROUPTOKEN_H
+#define MODIFICATIONGROUPTOKEN_H
+
+#include <corelib_global.h>
+
+namespace QmlDesigner {
+
+namespace Internal {
+ class ModelRewriter;
+ class ModelPrivate;
+}
+
+/*!
+\class QmlDesigner::ModificationGroupToken
+\ingroup CoreModel
+\brief TBD
+*/
+
+class CORESHARED_EXPORT ModificationGroupToken
+{
+ friend class Internal::ModelRewriter;
+ friend class Internal::ModelPrivate;
+
+public:
+ ModificationGroupToken(): m_depth(0), m_uniqueNumber(-1) {}
+
+ unsigned depth() const { return m_depth; }
+ bool isValid() const { return m_uniqueNumber != -1; }
+
+ bool operator==(const ModificationGroupToken& token) const { return m_uniqueNumber == token.m_uniqueNumber; }
+ bool operator!=(const ModificationGroupToken& token) const { return m_uniqueNumber != token.m_uniqueNumber; }
+
+private:
+ void makeInvalid() { m_uniqueNumber = -1; }
+ ModificationGroupToken(unsigned depth);
+
+private:
+ static long uniqueNumberCounter;
+
+ unsigned m_depth;
+ long m_uniqueNumber;
+};
+
+}
+
+#endif // MODIFICATIONGROUPTOKEN_H
diff --git a/src/plugins/qmldesigner/core/include/noanchoringpossibleexception.h b/src/plugins/qmldesigner/core/include/noanchoringpossibleexception.h
new file mode 100644
index 0000000000..3ece337bbc
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/noanchoringpossibleexception.h
@@ -0,0 +1,50 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef NOANCHORINGPOSSIBLEEXCEPTION_H
+#define NOANCHORINGPOSSIBLEEXCEPTION_H
+
+#include "exception.h"
+
+namespace QmlDesigner {
+
+class CORESHARED_EXPORT NoAnchoringPossibleException : public Exception
+{
+public:
+ NoAnchoringPossibleException(int line,
+ const QString &function,
+ const QString &file);
+
+ QString type() const;
+
+};
+
+} // namespace QKinecticDesigner
+
+#endif // NOANCHORINGPOSSIBLEEXCEPTION_H
diff --git a/src/plugins/qmldesigner/core/include/nodeabstractproperty.h b/src/plugins/qmldesigner/core/include/nodeabstractproperty.h
new file mode 100644
index 0000000000..33fec654c1
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/nodeabstractproperty.h
@@ -0,0 +1,63 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef NODEABSTRACTPROPERTY_H
+#define NODEABSTRACTPROPERTY_H
+
+#include "abstractproperty.h"
+
+namespace QmlDesigner {
+
+namespace Internal {
+ class InternalNodeAbstractProperty;
+ typedef QSharedPointer<InternalNodeAbstractProperty> InternalNodeAbstractPropertyPointer;
+}
+
+class NodeAbstractProperty : public AbstractProperty
+{
+ friend class QmlDesigner::ModelNode;
+ friend class QmlDesigner::Internal::ModelPrivate;
+ friend class QmlDesigner::AbstractProperty;
+public:
+ NodeAbstractProperty();
+ NodeAbstractProperty(const NodeAbstractProperty &property, AbstractView *view);
+ void reparentHere(const ModelNode &modelNode);
+ bool isEmpty() const;
+
+ QList<ModelNode> allSubNodes();
+
+protected:
+ NodeAbstractProperty(const QString &propertyName, const Internal::InternalNodePointer &internalNode, Model *model, AbstractView *view);
+ NodeAbstractProperty(const Internal::InternalNodeAbstractPropertyPointer &property, Model *model, AbstractView *view);
+ void reparentHere(const ModelNode &modelNode, bool isNodeList);
+};
+
+} // namespace QmlDesigner
+
+#endif // NODEABSTRACTPROPERTY_H
diff --git a/src/plugins/qmldesigner/core/include/nodeanchors.h b/src/plugins/qmldesigner/core/include/nodeanchors.h
new file mode 100644
index 0000000000..763d2044a7
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/nodeanchors.h
@@ -0,0 +1,114 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef NODEANCHORS_H
+#define NODEANCHORS_H
+
+
+#include <QWeakPointer>
+#include <QSharedPointer>
+#include "corelib_global.h"
+#include <anchorline.h>
+#include <nodestate.h>
+
+namespace QmlDesigner {
+ class Model;
+ class NodeState;
+
+ namespace Internal {
+ class InternalNode;
+ typedef QSharedPointer<InternalNode> InternalNodePointer;
+ typedef QWeakPointer<InternalNode> InternalNodeWeakPointer;
+
+ class InternalNodeState;
+ typedef QSharedPointer<InternalNodeState> InternalNodeStatePointer;
+
+ class TextToModelMerger;
+ }
+}
+
+namespace QmlDesigner {
+
+class CORESHARED_EXPORT NodeAnchors
+{
+ friend class NodeState;
+ friend class ModelNode;
+ friend class Internal::TextToModelMerger;
+
+public:
+ explicit NodeAnchors(const NodeState &nodeState);
+
+ NodeAnchors(const NodeAnchors &other);
+ NodeAnchors& operator=(const NodeAnchors &other);
+ ~NodeAnchors();
+
+ ModelNode modelNode() const;
+ NodeState nodeState() const;
+
+ bool isValid() const;
+
+ void setAnchor(AnchorLine::Type sourceAnchorLineType,
+ const ModelNode &targetModelNode,
+ AnchorLine::Type targetAnchorLineType);
+ bool canAnchor(AnchorLine::Type sourceAnchorLineType,
+ const ModelNode &targetModelNode,
+ AnchorLine::Type targetAnchorLineType) const;
+ bool canAnchor(const ModelNode &targetModelNode) const;
+ AnchorLine::Type possibleAnchorLines(AnchorLine::Type sourceAnchorLineType,
+ const ModelNode &targetModelNode) const;
+ AnchorLine localAnchor(AnchorLine::Type anchorLineType) const;
+ AnchorLine anchor(AnchorLine::Type anchorLineType) const;
+ void removeAnchor(AnchorLine::Type sourceAnchorLineType);
+ void removeAnchors();
+ bool hasLocalAnchor(AnchorLine::Type sourceAnchorLineType) const;
+ bool hasAnchor(AnchorLine::Type sourceAnchorLineType) const;
+ bool hasLocalAnchors() const;
+ bool hasAnchors() const;
+ void setMargin(AnchorLine::Type sourceAnchorLineType, double margin) const;
+ bool hasMargin(AnchorLine::Type sourceAnchorLineType) const;
+ double localMargin(AnchorLine::Type sourceAnchorLineType) const;
+ double margin(AnchorLine::Type sourceAnchorLineType) const;
+ void removeMargin(AnchorLine::Type sourceAnchorLineType);
+ void removeMargins();
+
+private: // functions
+ NodeAnchors(const Internal::InternalNodeStatePointer &internalNodeState, Model *model);
+
+private: //variables
+ Internal::InternalNodePointer m_internalNode;
+ Internal::InternalNodeStatePointer m_internalNodeState;
+ QWeakPointer<Model> m_model;
+};
+
+CORESHARED_EXPORT QDebug operator<<(QDebug debug, const NodeAnchors &anchors);
+CORESHARED_EXPORT QTextStream& operator<<(QTextStream &stream, const NodeAnchors &anchors);
+
+} // namespace QmlDesigner
+
+#endif // NODEANCHORS_H
diff --git a/src/plugins/qmldesigner/core/include/nodeinstance.h b/src/plugins/qmldesigner/core/include/nodeinstance.h
new file mode 100644
index 0000000000..d417b0eef9
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/nodeinstance.h
@@ -0,0 +1,166 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef NODEINSTANCE_H
+#define NODEINSTANCE_H
+
+#include "corelib_global.h"
+#include <QSharedPointer>
+#include <QHash>
+#include <QRectF>
+#include <propertymetainfo.h>
+#include <qmlanchors.h>
+
+class QPainter;
+class QStyleOptionGraphicsItem;
+class QmlContext;
+class QGraphicsItem;
+class QGraphicsTransform;
+
+namespace QmlDesigner {
+
+class ModelNode;
+class NodeInstanceView;
+class Preview;
+class NodeMetaInfo;
+class NodeState;
+class WidgetQueryView;
+
+
+namespace Internal {
+ class ObjectNodeInstance;
+ class QmlGraphicsItemNodeInstance;
+}
+
+class CORESHARED_EXPORT NodeInstance
+{
+ friend class CORESHARED_EXPORT QmlDesigner::WidgetQueryView;
+ friend CORESHARED_EXPORT class Preview;
+ friend CORESHARED_EXPORT class NodeInstanceView;
+ friend class QHash<ModelNode, NodeInstance>;
+ friend CORESHARED_EXPORT uint qHash(const NodeInstance &instance);
+ friend CORESHARED_EXPORT bool operator==(const NodeInstance &first, const NodeInstance &second);
+ friend CORESHARED_EXPORT class NodeMetaInfo;
+ friend class QmlDesigner::Internal::QmlGraphicsItemNodeInstance;
+ friend class QmlDesigner::Internal::ObjectNodeInstance;
+public:
+ NodeInstance();
+ ~NodeInstance();
+ NodeInstance(const NodeInstance &other);
+ NodeInstance& operator=(const NodeInstance &other);
+
+ void paint(QPainter *painter) const;
+
+ NodeInstance parent() const;
+ bool hasParent() const;
+ ModelNode modelNode() const;
+ void setModelNode(const ModelNode &node);
+
+ bool isTopLevel() const;
+
+ bool isQmlGraphicsItem() const;
+ bool isGraphicsScene() const;
+ bool isGraphicsView() const;
+ bool isGraphicsWidget() const;
+ bool isProxyWidget() const;
+ bool isWidget() const;
+ bool isQmlView() const;
+ bool isGraphicsObject() const;
+ bool isTransition() const;
+
+ bool equalGraphicsItem(QGraphicsItem *item) const;
+
+ QRectF boundingRect() const;
+ QPointF position() const;
+ QSizeF size() const;
+ QTransform transform() const;
+ QTransform customTransform() const;
+ QTransform sceneTransform() const;
+ double rotation() const;
+ double scale() const;
+ QList<QGraphicsTransform *> transformations() const;
+ QPointF transformOriginPoint() const;
+ double zValue() const;
+
+ double opacity() const;
+ QVariant property(const QString &name) const;
+ QVariant defaultValue(const QString &name) const;
+
+ bool isVisible() const;
+ bool isValid() const;
+ void makeInvalid();
+ bool hasContent() const;
+
+ const QObject *testHandle() const;
+
+ void setPropertyVariant(const QString &name, const QVariant &value);
+ void setPropertyDynamicVariant(const QString &name, const QString &typeName, const QVariant &value);
+
+ void setPropertyBinding(const QString &name, const QString &expression);
+ void setPropertyDynamicBinding(const QString &name, const QString &typeName, const QString &expression);
+
+ bool hasAnchor(const QString &name) const;
+ bool isAnchoredBy() const;
+ QPair<QString, NodeInstance> anchor(const QString &name) const;
+
+private: // functions
+ NodeInstance(const QSharedPointer<Internal::ObjectNodeInstance> &abstractInstance);
+
+ static NodeInstance create(NodeInstanceView *nodeInstanceView, const ModelNode &node, QObject *objectToBeWrapped);
+ static NodeInstance create(NodeInstanceView *nodeInstanceView, const NodeMetaInfo &metaInfo, QmlContext *context);
+
+ void setDeleteHeldInstance(bool deleteInstance);
+ void reparent(const NodeInstance &oldParentInstance, const QString &oldParentProperty, const NodeInstance &newParentInstance, const QString &newParentProperty);
+
+ void resetProperty(const QString &name);
+
+ void setId(const QString &id);
+
+ static QSharedPointer<Internal::ObjectNodeInstance> createInstance(const NodeMetaInfo &metaInfo, QmlContext *context, QObject *objectToBeWrapped);
+ QSharedPointer<Internal::QmlGraphicsItemNodeInstance> qmlGraphicsItemNodeInstance() const;
+
+ void paintUpdate();
+
+ void show();
+ void hide();
+
+
+ QObject *internalObject() const; // should be not used outside of the nodeinstances!!!!
+
+private: // variables
+ QSharedPointer<Internal::ObjectNodeInstance> m_nodeInstance;
+};
+
+CORESHARED_EXPORT uint qHash(const NodeInstance &instance);
+CORESHARED_EXPORT bool operator==(const NodeInstance &first, const NodeInstance &second);
+}
+
+Q_DECLARE_METATYPE(QmlDesigner::NodeInstance);
+
+#endif // NODEINSTANCE_H
diff --git a/src/plugins/qmldesigner/core/include/nodeinstanceview.h b/src/plugins/qmldesigner/core/include/nodeinstanceview.h
new file mode 100644
index 0000000000..17cec2c1be
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/nodeinstanceview.h
@@ -0,0 +1,153 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef ABSTRACTNODEINSTANCEVIEW_H
+#define ABSTRACTNODEINSTANCEVIEW_H
+
+#include "corelib_global.h"
+#include "abstractview.h"
+#include <QtGui/QWidget>
+#include <QtCore/QHash>
+#include <QtScript/QScriptEngine>
+#include <QWeakPointer>
+#include <QtCore/QHash>
+
+#include <modelnode.h>
+#include <nodeinstance.h>
+
+class QmlEngine;
+class QGraphicsScene;
+class QGraphicsView;
+
+namespace QmlDesigner {
+
+namespace Internal {
+ class ChildrenChangeEventFilter;
+}
+
+class CORESHARED_EXPORT NodeInstanceView : public AbstractView
+{
+ Q_OBJECT
+
+ friend class NodeInstance;
+ friend class Internal::ObjectNodeInstance;
+public:
+ typedef QWeakPointer<NodeInstanceView> Pointer;
+
+ NodeInstanceView(QObject *parent = 0);
+ ~NodeInstanceView();
+
+ void modelAttached(Model *model);
+ void modelAboutToBeDetached(Model *model);
+ void nodeCreated(const ModelNode &createdNode);
+ void nodeAboutToBeRemoved(const ModelNode &removedNode);
+ void nodeRemoved(const ModelNode &removedNode, const NodeAbstractProperty &parentProperty, PropertyChangeFlags propertyChange);
+ void propertiesAdded(const ModelNode &node, const QList<AbstractProperty>& propertyList);
+ void propertiesAboutToBeRemoved(const QList<AbstractProperty>& propertyList);
+ void propertiesRemoved(const QList<AbstractProperty>& propertyList);
+ void variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags propertyChange);
+ void bindingPropertiesChanged(const QList<BindingProperty>& propertyList, PropertyChangeFlags propertyChange);
+ void nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange);
+ void nodeTypeChanged(const ModelNode &node,const QString &type, int majorVersion, int minorVersion);
+
+ void fileUrlChanged(const QUrl &oldUrl, const QUrl &newUrl);
+ void nodeIdChanged(const ModelNode& node, const QString& newId, const QString& oldId);
+
+ void modelStateAboutToBeRemoved(const ModelState &modelState);
+ void modelStateAdded(const ModelState &modelState);
+
+ void nodeStatesAboutToBeRemoved(const QList<ModelNode> &nodeStateList);
+ void nodeStatesAdded(const QList<ModelNode> &nodeStateList);
+
+ void nodeSlidedToIndex(const NodeListProperty &listProperty, int newIndex, int oldIndex);
+
+ NodeInstance rootNodeInstance() const;
+ NodeInstance viewNodeInstance() const;
+
+ void selectedNodesChanged(const QList<ModelNode> &selectedNodeList, const QList<ModelNode> &lastSelectedNodeList);
+
+ QList<NodeInstance> instances() const;
+ NodeInstance instanceForNode(const ModelNode &node);
+ bool hasInstanceForNode(const ModelNode &node);
+
+ NodeInstance instanceForObject(QObject *object);
+ bool hasInstanceForObject(QObject *object);
+
+ void anchorsChanged(const ModelNode &nodeState);
+
+ void render(QPainter *painter, const QRectF &target=QRectF(), const QRectF &source=QRect(), Qt::AspectRatioMode aspectRatioMode=Qt::KeepAspectRatio);
+
+ QRectF boundingRect() const;
+ QRectF sceneRect() const;
+ void setBlockChangeSignal(bool block);
+
+signals:
+ void instanceRemoved(const NodeInstance &nodeInstance);
+ void transformPropertyChanged(const NodeInstance &nodeInstance);
+ void parentPropertyChanged(const NodeInstance &nodeInstance);
+ void otherPropertyChanged(const NodeInstance &nodeInstance);
+ void updateItem(const NodeInstance &nodeInstance);
+
+private slots:
+ void emitOtherPropertyChanged();
+ void emitParentPropertyChanged();
+ void emitTransformPropertyChanged();
+ void emitUpdateItem(QObject *object);
+
+private: // functions
+ NodeInstance loadNode(const ModelNode &rootNode, QObject *objectToBeWrapped = 0);
+ void loadModel(Model *model);
+ void loadNodes(const QList<ModelNode> &nodeList);
+
+ void removeAllInstanceNodeRelationships();
+
+ void removeRecursiveChildRelationship(const ModelNode &removedNode);
+
+ void insertInstanceNodeRelationship(const ModelNode &node, const NodeInstance &instance);
+ void removeInstanceNodeRelationship(const ModelNode &node);
+
+ QmlEngine *engine() const;
+ Internal::ChildrenChangeEventFilter *childrenChangeEventFilter();
+ void removeInstanceAndSubInstances(const ModelNode &node);
+
+private: //variables
+ NodeInstance m_rootNodeInstance;
+ QScopedPointer<QGraphicsView> m_graphicsView;
+
+ QHash<ModelNode, NodeInstance> m_nodeInstanceHash;
+ QHash<QObject*, NodeInstance> m_objectInstanceHash; // This is purely internal. Might contain dangling pointers!
+ QWeakPointer<QmlEngine> m_engine;
+ QWeakPointer<Internal::ChildrenChangeEventFilter> m_childrenChangeEventFilter;
+
+ bool m_blockChangeSignal;
+};
+
+}
+
+#endif // ABSTRACTNODEINSTANCEVIEW_H
diff --git a/src/plugins/qmldesigner/core/include/nodelistproperty.h b/src/plugins/qmldesigner/core/include/nodelistproperty.h
new file mode 100644
index 0000000000..061c911f60
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/nodelistproperty.h
@@ -0,0 +1,71 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef NODELISTPROPERTY_H
+#define NODELISTPROPERTY_H
+
+
+#include "corelib_global.h"
+#include "nodeabstractproperty.h"
+#include <QList>
+
+
+namespace QmlDesigner {
+
+namespace Internal {
+ class ModelPrivate;
+ class InternalNodeListProperty;
+ typedef QSharedPointer<InternalNodeListProperty> InternalNodeListPropertyPointer;
+}
+
+
+class CORESHARED_EXPORT NodeListProperty : public NodeAbstractProperty
+{
+ friend class QmlDesigner::ModelNode;
+ friend class QmlDesigner::AbstractProperty;
+ friend class QmlDesigner::Internal::ModelPrivate;
+public:
+ NodeListProperty& operator= (const QVariant &value);
+
+ NodeListProperty();
+ NodeListProperty(const NodeListProperty &nodeListProperty, AbstractView *view);
+ const QList<ModelNode> toModelNodeList() const;
+ const QList<QmlObjectNode> toQmlObjectNodeList() const;
+ void slide(int, int) const;
+ void reparentHere(const ModelNode &modelNode);
+
+ bool isEmpty() const;
+
+protected:
+ NodeListProperty(const QString &propertyName, const Internal::InternalNodePointer &internalNode, Model* model, AbstractView *view);
+ NodeListProperty(const Internal::InternalNodeListPropertyPointer &internalNodeListProperty, Model* model, AbstractView *view);
+};
+}
+
+#endif //NODELISTROPERTY_H
diff --git a/src/plugins/qmldesigner/core/include/nodemetainfo.h b/src/plugins/qmldesigner/core/include/nodemetainfo.h
new file mode 100644
index 0000000000..7b80ef0707
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/nodemetainfo.h
@@ -0,0 +1,139 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef NODEMETAINFO_H
+#define NODEMETAINFO_H
+
+#include <QList>
+#include <QString>
+#include <QExplicitlySharedDataPointer>
+#include <QIcon>
+
+#include "corelib_global.h"
+#include "invalidmetainfoexception.h"
+
+class QmlContext;
+
+namespace QmlDesigner {
+
+class MetaInfo;
+class AbstractProperty;
+
+namespace Internal {
+ class MetaInfoPrivate;
+ class MetaInfoParser;
+ class NodeMetaInfoData;
+ class SubComponentManagerPrivate;
+ class ItemLibraryInfoData;
+}
+
+class PropertyMetaInfo;
+
+class CORESHARED_EXPORT NodeMetaInfo
+{
+ friend class QmlDesigner::MetaInfo;
+ friend class QmlDesigner::Internal::ItemLibraryInfoData;
+ friend class QmlDesigner::Internal::MetaInfoPrivate;
+ friend class QmlDesigner::Internal::MetaInfoParser;
+ friend class QmlDesigner::Internal::SubComponentManagerPrivate;
+ friend class QmlDesigner::AbstractProperty;
+ friend CORESHARED_EXPORT uint qHash(const NodeMetaInfo &nodeMetaInfo);
+ friend CORESHARED_EXPORT bool operator ==(const NodeMetaInfo &firstNodeInfo, const NodeMetaInfo &secondNodeInfo);
+
+public:
+ ~NodeMetaInfo();
+
+ NodeMetaInfo(const NodeMetaInfo &other);
+ NodeMetaInfo &operator=(const NodeMetaInfo &other);
+
+ bool isValid() const;
+ MetaInfo metaInfo() const;
+
+ QObject *createInstance(QmlContext *parentContext) const;
+
+ PropertyMetaInfo property(const QString &propertyName, bool resolveDotSyntax = false) const;
+
+ QList<NodeMetaInfo> superClasses() const;
+ QList<NodeMetaInfo> directSuperClasses() const;
+ QHash<QString,PropertyMetaInfo> properties(bool resolveDotSyntax = false) const;
+
+
+ QString typeName() const;
+ int majorVersion() const;
+ int minorVersion() const;
+
+ bool hasDefaultProperty() const;
+ QString defaultProperty() const;
+
+ bool hasProperty(const QString &propertyName, bool resolveDotSyntax = false) const;
+ bool isContainer() const;
+ bool isVisibleToItemLibrary() const;
+
+ bool isWidget() const;
+ bool isGraphicsWidget() const;
+ bool isGraphicsObject() const;
+ bool isQmlGraphicsItem() const;
+ bool isComponent() const;
+ bool isSubclassOf(const QString& type, int majorVersion = 4, int minorVersion = 6) const;
+
+ QIcon icon() const;
+ QString category() const;
+
+private:
+ NodeMetaInfo();
+ NodeMetaInfo(const MetaInfo &metaInfo);
+
+ void setInvalid();
+ void setTypeName(const QString &typeName);
+ void addProperty(const PropertyMetaInfo &property);
+ void setIsContainer(bool isContainer);
+ void setIsVisibleToItemLibrary(bool isVisibleToItemLibrary);
+ void setIcon(const QIcon &icon);
+ void setCategory(const QString &category);
+ void setQmlFile(const QString &filePath);
+ void setDefaultProperty(const QString &defaultProperty);
+ void setMajorVersion(int version);
+ void setMinorVersion(int version);
+
+ bool hasLocalProperty(const QString &propertyName, bool resolveDotSyntax = false) const;
+ QHash<QString,PropertyMetaInfo> dotProperties() const;
+
+private:
+ QExplicitlySharedDataPointer<Internal::NodeMetaInfoData> m_data;
+};
+
+CORESHARED_EXPORT uint qHash(const NodeMetaInfo &nodeMetaInfo);
+CORESHARED_EXPORT bool operator ==(const NodeMetaInfo &firstNodeInfo,
+ const NodeMetaInfo &secondNodeInfo);
+
+//QDataStream& operator<<(QDataStream& stream, const NodeMetaInfo& nodeMetaInfo);
+//QDataStream& operator>>(QDataStream& stream, NodeMetaInfo& nodeMetaInfo);
+}
+
+#endif // NODEMETAINFO_H
diff --git a/src/plugins/qmldesigner/core/include/nodeproperty.h b/src/plugins/qmldesigner/core/include/nodeproperty.h
new file mode 100644
index 0000000000..61ac97143b
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/nodeproperty.h
@@ -0,0 +1,62 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef NODEPROPERTY_H
+#define NODEPROPERTY_H
+
+#include "corelib_global.h"
+#include "nodeabstractproperty.h"
+
+namespace QmlDesigner {
+
+namespace Internal {
+ class ModelPrivate;
+}
+
+class CORESHARED_EXPORT NodeProperty : public NodeAbstractProperty
+{
+ friend class QmlDesigner::ModelNode;
+ friend class QmlDesigner::Internal::ModelPrivate;
+ friend class QmlDesigner::AbstractProperty;
+
+public:
+ void setModelNode(const ModelNode &modelNode);
+ ModelNode modelNode() const;
+ QmlObjectNode fxObjectNode() const;
+
+ void reparentHere(const ModelNode &modelNode);
+
+ NodeProperty();
+protected:
+ NodeProperty(const QString &propertyName, const Internal::InternalNodePointer &internalNode, Model* model, AbstractView *view);
+};
+
+} // namespace QmlDesigner
+
+#endif // NODEPROPERTY_H
diff --git a/src/plugins/qmldesigner/core/include/notimplementedexception.h b/src/plugins/qmldesigner/core/include/notimplementedexception.h
new file mode 100644
index 0000000000..1711c2864d
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/notimplementedexception.h
@@ -0,0 +1,50 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef NOTIMPLEMENTEDEXCEPTION_H
+#define NOTIMPLEMENTEDEXCEPTION_H
+
+#include "exception.h"
+
+namespace QmlDesigner {
+
+class CORESHARED_EXPORT NotImplementedException : public Exception
+{
+public:
+ NotImplementedException(int line,
+ const QString &function,
+ const QString &file);
+
+ QString type() const;
+
+};
+
+}
+
+#endif // NOTIMPLEMENTEDEXCEPTION_H
diff --git a/src/plugins/qmldesigner/core/include/objectpropertybinding.h b/src/plugins/qmldesigner/core/include/objectpropertybinding.h
new file mode 100644
index 0000000000..cfb613a4d2
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/objectpropertybinding.h
@@ -0,0 +1,55 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef OBJECTPROPERTYBINDING_H
+#define OBJECTPROPERTYBINDING_H
+
+#include <modelnode.h>
+
+namespace QmlDesigner {
+
+class CORESHARED_EXPORT ObjectPropertyBinding
+{
+public:
+ ObjectPropertyBinding();
+ ObjectPropertyBinding(const ModelNode &node);
+
+
+ ModelNode modelNode() const;
+ bool isValid() const;
+
+private:
+ ModelNode m_node;
+};
+
+} // namespace QmlDesigner
+
+Q_DECLARE_METATYPE(QmlDesigner::ObjectPropertyBinding);
+
+#endif // OBJECTPROPERTYBINDING_H
diff --git a/src/plugins/qmldesigner/core/include/plaintexteditmodifier.h b/src/plugins/qmldesigner/core/include/plaintexteditmodifier.h
new file mode 100644
index 0000000000..29a33b5725
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/plaintexteditmodifier.h
@@ -0,0 +1,90 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef PLAINTEXTEDITMODIFIER_H
+#define PLAINTEXTEDITMODIFIER_H
+
+#include "corelib_global.h"
+#include "textmodifier.h"
+
+QT_BEGIN_NAMESPACE
+class QIODevice;
+class QPlainTextEdit;
+QT_END_NAMESPACE
+
+namespace Utils {
+ class ChangeSet;
+}
+
+namespace QmlDesigner {
+
+class CORESHARED_EXPORT PlainTextEditModifier: public TextModifier
+{
+ Q_OBJECT
+
+private:
+ PlainTextEditModifier(const PlainTextEditModifier &);
+ PlainTextEditModifier &operator=(const PlainTextEditModifier &);
+
+public:
+ PlainTextEditModifier(QPlainTextEdit *textEdit);
+ ~PlainTextEditModifier();
+
+ virtual void save(QIODevice *device);
+
+ virtual QTextDocument *textDocument() const;
+ virtual QString text() const;
+ virtual QTextCursor textCursor() const;
+
+ virtual void replace(int offset, int length, const QString &replacement);
+ virtual void move(const MoveInfo &moveInfo);
+ virtual void startGroup();
+ virtual void flushGroup();
+ virtual void commitGroup();
+
+ virtual void deactivateChangeSignals();
+ virtual void reactivateChangeSignals();
+
+private slots:
+ void textEditChanged();
+
+private:
+ void runRewriting(Utils::ChangeSet *writer);
+
+private:
+ Utils::ChangeSet *m_changeSet;
+ QPlainTextEdit *m_textEdit;
+ bool m_changeSignalsEnabled;
+ bool m_pendingChangeSignal;
+ bool m_ongoingTextChange;
+};
+
+}
+
+#endif // PLAINTEXTEDITMODIFIER_H
diff --git a/src/plugins/qmldesigner/core/include/propertybinding.h b/src/plugins/qmldesigner/core/include/propertybinding.h
new file mode 100644
index 0000000000..8b826db6e3
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/propertybinding.h
@@ -0,0 +1,62 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef PROPERTYBINDING_H
+#define PROPERTYBINDING_H
+
+#include <QtCore/QMetaType>
+#include <QtCore/QSharedPointer>
+#include <QtCore/QString>
+
+#include "corelib_global.h"
+#include "modelnode.h"
+
+namespace QmlDesigner {
+
+class CORESHARED_EXPORT PropertyBinding
+{
+public:
+ PropertyBinding();
+ PropertyBinding(const QString &value);
+ PropertyBinding(const PropertyBinding &other);
+
+ PropertyBinding &operator=(const PropertyBinding &other);
+
+ bool isValid() const;
+ QString value() const;
+
+private:
+ QString m_value;
+};
+
+} // namespace QmlDesigner
+
+Q_DECLARE_METATYPE(QmlDesigner::PropertyBinding);
+
+#endif // PROPERTYBINDING_H
diff --git a/src/plugins/qmldesigner/core/include/propertycontainer.h b/src/plugins/qmldesigner/core/include/propertycontainer.h
new file mode 100644
index 0000000000..9fee3a5f0d
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/propertycontainer.h
@@ -0,0 +1,82 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef PROPERTYCONTAINER_H
+#define PROPERTYCONTAINER_H
+
+#include "corelib_global.h"
+
+#include <QString>
+#include <QExplicitlySharedDataPointer>
+#include <QDataStream>
+#include <QVariant>
+
+#include <enumeratormetainfo.h>
+
+namespace QmlDesigner {
+
+class PropertyContainer;
+
+CORESHARED_EXPORT QDataStream &operator<<(QDataStream &stream, const PropertyContainer &propertyContainer);
+CORESHARED_EXPORT QDataStream &operator>>(QDataStream &stream, PropertyContainer &propertyContainer);
+
+class CORESHARED_EXPORT PropertyContainer
+{
+ friend CORESHARED_EXPORT QDataStream &QmlDesigner::operator<<(QDataStream &stream, const PropertyContainer &propertyContainer);
+ friend CORESHARED_EXPORT QDataStream &QmlDesigner::operator>>(QDataStream &stream, PropertyContainer &propertyContainer);
+
+public:
+ PropertyContainer();
+ PropertyContainer(const QString &name, const QString &type, const QVariant &value);
+
+ bool isValid() const;
+
+ QString name() const;
+ QVariant value() const;
+ QString type() const;
+
+
+ void setValue(const QVariant &value);
+ void set(const QString &name, const QString &type, const QVariant &value);
+
+
+private:
+ QString m_name;
+ QString m_type;
+ mutable QVariant m_value;
+};
+
+CORESHARED_EXPORT QDataStream &operator<<(QDataStream &stream, const QList<PropertyContainer> &propertyContainerList);
+CORESHARED_EXPORT QDataStream &operator>>(QDataStream &stream, QList<PropertyContainer> &propertyContainerList);
+
+} //namespace QmlDesigner
+
+
+
+#endif //PROPERTYCONTAINER_H
diff --git a/src/plugins/qmldesigner/core/include/propertymetainfo.h b/src/plugins/qmldesigner/core/include/propertymetainfo.h
new file mode 100644
index 0000000000..7157975ed6
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/propertymetainfo.h
@@ -0,0 +1,123 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef PROPERTYMETAINFO_H
+#define PROPERTYMETAINFO_H
+
+#include "corelib_global.h"
+
+#include <QString>
+#include <QExplicitlySharedDataPointer>
+#include <QVariant>
+
+#include <enumeratormetainfo.h>
+
+namespace QmlDesigner {
+
+class AbstractProperty;
+class MetaInfo;
+class NodeMetaInfo;
+
+namespace Internal {
+
+class MetaInfoPrivate;
+class MetaInfoParser;
+class PropertyMetaInfoData;
+class ObjectNodeInstance;
+class SubComponentManagerPrivate;
+
+}
+
+class CORESHARED_EXPORT PropertyMetaInfo
+{
+ friend class QmlDesigner::Internal::MetaInfoPrivate;
+ friend class QmlDesigner::Internal::MetaInfoParser;
+ friend class QmlDesigner::Internal::ObjectNodeInstance;
+ friend class QmlDesigner::Internal::SubComponentManagerPrivate;
+ friend class QmlDesigner::MetaInfo;
+ friend class QmlDesigner::AbstractProperty;
+ friend class QmlDesigner::NodeMetaInfo;
+public:
+ PropertyMetaInfo();
+ ~PropertyMetaInfo();
+
+ PropertyMetaInfo(const PropertyMetaInfo &other);
+ PropertyMetaInfo& operator=(const PropertyMetaInfo &other);
+
+ bool isValid() const;
+
+ QString name() const;
+ QString type() const;
+
+ QVariant::Type variantTypeId() const;
+
+ bool isReadable() const;
+ bool isWriteable() const;
+ bool isResettable() const;
+ bool isValueType() const;
+ bool isListProperty() const;
+
+ bool isEnumType() const;
+ bool isFlagType() const;
+
+ QVariant defaultValue(const NodeMetaInfo &nodeMetaInfo) const;
+ bool isVisibleToPropertyEditor() const;
+
+ const EnumeratorMetaInfo enumerator() const;
+
+ QVariant castedValue(const QVariant &variant) const;
+
+private:
+ void setName(const QString &name);
+ void setType(const QString &type);
+ void setValid(bool isValid);
+
+ void setReadable(bool isReadable);
+ void setWritable(bool isWritable);
+ void setResettable(bool isRessetable);
+
+ void setEnumType(bool isEnumType);
+ void setFlagType(bool isFlagType);
+
+ void setDefaultValue(const NodeMetaInfo &nodeMetaInfo, const QVariant &value);
+ void setIsVisibleToPropertyEditor(bool isVisible);
+
+ void setEnumerator(const EnumeratorMetaInfo &info);
+
+ bool hasDotSubProperties() const;
+
+
+private:
+ QExplicitlySharedDataPointer<Internal::PropertyMetaInfoData> m_data;
+};
+
+}
+
+
+#endif // PROPERTYMETAINFO_H
diff --git a/src/plugins/qmldesigner/core/include/propertynode.h b/src/plugins/qmldesigner/core/include/propertynode.h
new file mode 100644
index 0000000000..419b97cfa0
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/propertynode.h
@@ -0,0 +1,48 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef PROPERTYNODE_H
+#define PROPERTYNODE_H
+
+#include "corelib_global.h"
+
+namespace QmlDesigner {
+
+class CORESHARED_EXPORT PropertyNode // : public BaseModelNode
+{
+public:
+ PropertyNode();
+
+// static int variantUserType() { return qMetaTypeId<InternalNode::Pointer>(); }
+// static QVariant toVariant(const InternalNode::Pointer &internalNodePointer) { return QVariant::fromValue(internalNodePointer); }
+};
+
+} // namespace QmlDesigner
+
+#endif // PROPERTYNODE_H
diff --git a/src/plugins/qmldesigner/core/include/qmlanchors.h b/src/plugins/qmldesigner/core/include/qmlanchors.h
new file mode 100644
index 0000000000..5bbb759bd8
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/qmlanchors.h
@@ -0,0 +1,113 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef QmlAnchors_H
+#define QmlAnchors_H
+
+#include <corelib_global.h>
+#include <qmlitemnode.h>
+
+
+namespace QmlDesigner {
+
+class CORESHARED_EXPORT AnchorLine
+{
+public:
+ enum Type {
+ Invalid = 0x0,
+ NoAnchor = Invalid,
+ Left = 0x01,
+ Right = 0x02,
+ Top = 0x04,
+ Bottom = 0x08,
+ HorizontalCenter = 0x10,
+ VerticalCenter = 0x20,
+ Baseline = 0x40,
+
+ Fill = Left | Right | Top | Bottom,
+ Center = VerticalCenter | HorizontalCenter,
+ HorizontalMask = Left | Right | HorizontalCenter,
+ VerticalMask = Top | Bottom | VerticalCenter | Baseline,
+ AllMask = VerticalMask | HorizontalMask
+ };
+
+ AnchorLine() : m_qmlItemNode(QmlItemNode()), m_type(Invalid) {}
+ AnchorLine(const QmlItemNode &fxItemNode, Type type) : m_qmlItemNode(fxItemNode), m_type(type) {}
+ Type type() const { return m_type; }
+ bool isValid() const { return m_type != Invalid && m_qmlItemNode.isValid(); }
+
+ static bool isHorizontalAnchorLine(Type anchorline);
+ static bool isVerticalAnchorLine(Type anchorline);
+
+ QmlItemNode qmlItemNode() const;
+
+private:
+ QmlItemNode m_qmlItemNode;
+ Type m_type;
+};
+
+
+class CORESHARED_EXPORT QmlAnchors
+{
+public:
+ QmlAnchors(const QmlItemNode &fxItemNode);
+
+ bool isValid() const;
+
+ void setAnchor(AnchorLine::Type sourceAnchorLineType,
+ const QmlItemNode &targetModelNode,
+ AnchorLine::Type targetAnchorLineType);
+ bool canAnchor(const QmlItemNode &targetModelNode) const;
+ AnchorLine::Type possibleAnchorLines(AnchorLine::Type sourceAnchorLineType,
+ const QmlItemNode &targetModelNode) const;
+ AnchorLine instanceAnchor(AnchorLine::Type sourceAnchorLineType) const;
+
+ void removeAnchor(AnchorLine::Type sourceAnchorLineType);
+ void removeAnchors();
+ bool instanceHasAnchor(AnchorLine::Type sourceAnchorLineType) const;
+ bool instanceHasAnchors() const;
+ void setMargin(AnchorLine::Type sourceAnchorLineType, double margin) const;
+ bool instanceHasMargin(AnchorLine::Type sourceAnchorLineType) const;
+ double instanceMargin(AnchorLine::Type sourceAnchorLineType) const;
+ void removeMargin(AnchorLine::Type sourceAnchorLineType);
+ void removeMargins();
+
+ void fill();
+ void centerIn();
+
+protected:
+ QmlItemNode qmlItemNode() const;
+
+private:
+ QmlItemNode m_qmlItemNode;
+};
+
+} //QmlDesigner
+
+#endif // QmlAnchors_H
diff --git a/src/plugins/qmldesigner/core/include/qmlchangeset.h b/src/plugins/qmldesigner/core/include/qmlchangeset.h
new file mode 100644
index 0000000000..643cf57ecc
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/qmlchangeset.h
@@ -0,0 +1,61 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef QMLCHANGESET_H
+#define QMLCHANGESET_H
+
+#include <corelib_global.h>
+#include <modelnode.h>
+#include "qmlmodelnodefacade.h"
+
+namespace QmlDesigner {
+
+class CORESHARED_EXPORT QmlModelStateOperation : public QmlModelNodeFacade
+{
+public:
+ QmlModelStateOperation() : QmlModelNodeFacade() {}
+ QmlModelStateOperation(const ModelNode &modelNode) : QmlModelNodeFacade(modelNode) {}
+ ModelNode target() const;
+ void setTarget(const ModelNode &target);
+ bool isValid() const;
+};
+
+
+class CORESHARED_EXPORT QmlPropertyChanges : public QmlModelStateOperation
+{
+public:
+ QmlPropertyChanges() : QmlModelStateOperation() {}
+ QmlPropertyChanges(const ModelNode &modelNode) : QmlModelStateOperation(modelNode) {}
+ bool isValid() const;
+ void removeProperty(const QString &name);
+};
+
+} //QmlDesigner
+
+#endif // QMLCHANGESET_H
diff --git a/src/plugins/qmldesigner/core/include/qmlitemnode.h b/src/plugins/qmldesigner/core/include/qmlitemnode.h
new file mode 100644
index 0000000000..643dea042e
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/qmlitemnode.h
@@ -0,0 +1,120 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef QmlItemNode_H
+#define QmlItemNode_H
+
+#include <corelib_global.h>
+#include <modelnode.h>
+#include "qmlobjectnode.h"
+#include "qmlstate.h"
+
+#include <QStringList>
+#include <QRectF>
+#include <QTransform>
+
+namespace QmlDesigner {
+
+class QmlModelStateGroup;
+class QmlAnchors;
+
+class CORESHARED_EXPORT QmlItemNode : public QmlObjectNode
+{
+ friend class CORESHARED_EXPORT QmlAnchors;
+public:
+ QmlItemNode() : QmlObjectNode() {}
+ QmlItemNode(const ModelNode &modelNode) : QmlObjectNode(modelNode) {}
+ bool isValid() const;
+ bool isRootNode() const;
+
+ QmlModelStateGroup states() const;
+ QList<QmlItemNode> children() const;
+ QList<QmlObjectNode> resources() const;
+ QmlAnchors anchors() const;
+
+ bool hasChildren() const;
+ bool hasResources() const;
+ bool instanceHasAnchors() const;
+ bool hasShowContent() const;
+
+ bool canReparent() const;
+ bool instanceIsAnchoredBy() const;
+
+ QRectF instanceBoundingRect() const;
+ QTransform instanceTransform() const;
+ QTransform instanceSceneTransform() const;
+ QPointF instancePosition() const;
+ QSizeF instanceSize() const;
+
+ void paintInstance(QPainter *painter) const;
+
+ void setSize(const QSizeF &size);
+ void setPosition(const QPointF &position);
+
+ void selectNode();
+ void deselectNode();
+ bool isSelected() const;
+
+ QString simplfiedTypeName() const;
+
+ const QList<QmlItemNode> allDirectSubModelNodes() const;
+ const QList<QmlItemNode> allSubModelNodes() const;
+ bool hasAnySubModelNodes() const;
+};
+
+CORESHARED_EXPORT uint qHash(const QmlItemNode &node);
+
+class CORESHARED_EXPORT QmlModelStateGroup
+{
+ friend class QmlItemNode;
+public:
+
+ QmlModelStateGroup() : m_modelNode(ModelNode()) {}
+
+ ModelNode modelNode() const { return m_modelNode; }
+ QStringList names() const;
+ QList<QmlModelState> allStates() const;
+ QmlModelState state(const QString &name) const;
+ QmlModelState addState(const QString &name);
+ void removeState(const QString &name);
+
+protected:
+ QmlModelStateGroup(const ModelNode &modelNode) : m_modelNode(modelNode) {}
+
+private:
+ ModelNode m_modelNode;
+};
+
+CORESHARED_EXPORT QList<ModelNode> toModelNodeList(const QList<QmlItemNode> &fxItemNodeList);
+CORESHARED_EXPORT QList<QmlItemNode> toQmlItemNodeList(const QList<ModelNode> &modelNodeList);
+
+} //QmlDesigner
+
+
+#endif // QmlItemNode_H
diff --git a/src/plugins/qmldesigner/core/include/qmlmodelnodefacade.h b/src/plugins/qmldesigner/core/include/qmlmodelnodefacade.h
new file mode 100644
index 0000000000..0f5393bd30
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/qmlmodelnodefacade.h
@@ -0,0 +1,61 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef FXMODELNODEFACADE_H
+#define FXMODELNODEFACADE_H
+
+#include <corelib_global.h>
+#include <modelnode.h>
+
+namespace QmlDesigner {
+
+class QmlModelView;
+
+class CORESHARED_EXPORT QmlModelNodeFacade
+{
+public:
+ operator ModelNode() const { return m_modelNode; }
+ ModelNode modelNode() const { return m_modelNode; }
+ virtual bool isValid() const;
+ virtual ~QmlModelNodeFacade();
+ QmlModelNodeFacade();
+
+ bool isRootNode() const;
+
+protected:
+ QmlModelNodeFacade(const ModelNode &modelNode);
+ QmlModelView* qmlModelView() const;
+
+private:
+ ModelNode m_modelNode;
+};
+
+} //QmlDesigner
+
+#endif // FXMODELNODEFACADE_H
diff --git a/src/plugins/qmldesigner/core/include/qmlmodelview.h b/src/plugins/qmldesigner/core/include/qmlmodelview.h
new file mode 100644
index 0000000000..4aacd47eef
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/qmlmodelview.h
@@ -0,0 +1,114 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef QMLMODELVIEW_H
+#define QMLMODELVIEW_H
+
+#include <corelib_global.h>
+#include <forwardview.h>
+#include <abstractview.h>
+#include "qmlitemnode.h"
+#include "qmlstate.h"
+#include "nodeinstanceview.h"
+
+
+namespace QmlDesigner {
+
+class ItemLibraryInfo;
+
+class CORESHARED_EXPORT QmlModelView : public ForwardView<NodeInstanceView>
+{
+ Q_OBJECT
+ friend CORESHARED_EXPORT class QmlObjectNode;
+ friend CORESHARED_EXPORT class QmlModelNodeFacade;
+
+public:
+ QmlModelView(QObject *parent) ;
+
+ void setCurrentState(const QmlModelState &state);
+ QmlModelState currentState() const;
+
+ QmlModelState baseState() const;
+
+ QmlObjectNode createQmlObjectNode(const QString &typeString,
+ int majorVersion,
+ int minorVersion,
+ const PropertyListType &propertyList = PropertyListType());
+
+ QmlItemNode createQmlItemNode(const QString &typeString,
+ int majorVersion,
+ int minorVersion,
+ const PropertyListType &propertyList = PropertyListType());
+
+ QmlItemNode createQmlItemNode(const ItemLibraryInfo &ItemLibraryRepresentation, const QPointF &position, QmlItemNode parentNode);
+ QmlItemNode createQmlItemNodeFromImage(const QString &imageName, const QPointF &position, QmlItemNode parentNode);
+
+ QmlObjectNode rootQmlObjectNode() const;
+ QmlItemNode rootQmlItemNode() const;
+
+
+ void setSelectedQmlObjectNodes(const QList<QmlObjectNode> &selectedNodeList);
+ void setSelectedQmlItemNodes(const QList<QmlItemNode> &selectedNodeList);
+ void selectQmlObjectNode(const QmlObjectNode &node);
+ void deselectQmlObjectNode(const QmlObjectNode &node);
+
+ QList<QmlObjectNode> selectedQmlObjectNodes() const;
+ QList<QmlItemNode> selectedQmlItemNodes() const;
+
+ QmlObjectNode fxObjectNodeForId(const QString &id);
+
+ void customNotification(const AbstractView *view, const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> &data);
+
+ void modelAttached(Model *model);
+ void modelAboutToBeDetached(Model *model);
+
+protected:
+ NodeInstance instanceForModelNode(const ModelNode &modelNode);
+ bool hasInstanceForModelNode(const ModelNode &modelNode);
+ NodeInstanceView *nodeInstanceView() const;
+ virtual void transformChanged(const QmlObjectNode &qmlObjectNode) ;
+ virtual void parentChanged(const QmlObjectNode &qmlObjectNode);
+ virtual void otherPropertyChanged(const QmlObjectNode &qmlObjectNode);
+ virtual void stateChanged(const QmlModelState &newQmlModelState, const QmlModelState &oldQmlModelState);
+ virtual void updateItem(const QmlObjectNode &qmlObjectNode);
+
+
+private slots:
+ void notifyTransformChanged(const NodeInstance &nodeInstance);
+ void notifyParentChanged(const NodeInstance &nodeInstance);
+ void notifyOtherPropertyChanged(const NodeInstance &nodeInstance);
+ void notifyUpdateItem(const NodeInstance &nodeInstance);
+
+private:
+ QmlModelState m_state;
+};
+
+} //QmlDesigner
+
+#endif // QMLMODELVIEW_H
diff --git a/src/plugins/qmldesigner/core/include/qmlobjectnode.h b/src/plugins/qmldesigner/core/include/qmlobjectnode.h
new file mode 100644
index 0000000000..7dc37f322a
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/qmlobjectnode.h
@@ -0,0 +1,103 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef FXOBJECTNODE_H
+#define FXOBJECTNODE_H
+
+#include <corelib_global.h>
+#include "qmlmodelnodefacade.h"
+#include "qmlstate.h"
+#include "qmlchangeset.h"
+
+namespace QmlDesigner {
+
+class QmlItemNode;
+class QmlPropertyChanges;
+
+class CORESHARED_EXPORT QmlObjectNode : public QmlModelNodeFacade
+{
+public:
+ QmlObjectNode() : QmlModelNodeFacade() {}
+ QmlObjectNode(const ModelNode &modelNode) : QmlModelNodeFacade(modelNode) {}
+
+ bool hasNodeParent() const;
+ bool hasInstanceParent() const;
+ void setParentProperty(const NodeAbstractProperty &parentProeprty);
+ QmlObjectNode instanceParent() const;
+
+ void setId(const QString &id);
+ QString id() const;
+ QString validId();
+
+ QmlModelState currentState() const;
+ void setVariantProperty(const QString &name, const QVariant &value);
+ void setBindingProperty(const QString &name, const QString &expression);
+ NodeAbstractProperty nodeAbstractProperty(const QString &name) const;
+ NodeProperty nodeProperty(const QString &name) const;
+ NodeListProperty nodeListProperty(const QString &name) const;
+
+ QVariant instanceValue(const QString &name) const;
+
+ bool hasProperty(const QString &name) const;
+ bool propertyAffectedByCurrentState(const QString &name) const;
+ QVariant modelValue(const QString &name) const;
+ bool isInBaseState() const;
+ QmlPropertyChanges propertyChangeForCurrentState() const;
+
+ virtual bool canReparent() const;
+
+ bool isRootModelNode() const;
+
+ void destroy();
+
+ QList<QmlModelState> allAffectingStates() const;
+ QList<QmlModelStateOperation> allAffectingStatesOperations() const;
+
+ void removeVariantProperty(const QString &name);
+
+ void setParent(QmlObjectNode newParent);
+
+ QmlItemNode toQmlItemNode() const;
+
+ bool isAncestorOf(const QmlObjectNode &objectNode) const;
+
+protected:
+ NodeInstance nodeInstance() const;
+ QmlObjectNode nodeForInstance(const NodeInstance &instance) const;
+
+protected:
+ QList<QmlModelState> allDefinedStates() const;
+};
+
+CORESHARED_EXPORT uint qHash(const QmlObjectNode &node);
+CORESHARED_EXPORT QList<ModelNode> toModelNodeList(const QList<QmlObjectNode> &fxObjectNodeList);
+CORESHARED_EXPORT QList<QmlObjectNode> toQmlObjectNodeList(const QList<ModelNode> &modelNodeList);
+}// QmlDesigner
+
+#endif // FXOBJECTNODE_H
diff --git a/src/plugins/qmldesigner/core/include/qmlstate.h b/src/plugins/qmldesigner/core/include/qmlstate.h
new file mode 100644
index 0000000000..80e5bb58a7
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/qmlstate.h
@@ -0,0 +1,82 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef FXSTATE_H
+#define FXSTATE_H
+
+#include <corelib_global.h>
+#include "qmlmodelnodefacade.h"
+#include "qmlchangeset.h"
+
+namespace QmlDesigner {
+
+class QmlModelView;
+class QmlModelStateGroup;
+
+class CORESHARED_EXPORT QmlModelState : public QmlModelNodeFacade
+{
+ friend class CORESHARED_EXPORT QmlModelView;
+
+public:
+ QmlModelState();
+ QmlModelState(const ModelNode &modelNode);
+
+ QmlPropertyChanges propertyChanges(const ModelNode &node);
+ QList<QmlModelStateOperation> stateOperations(const ModelNode &node) const;
+ QList<QmlPropertyChanges> propertyChanges() const;
+ QList<QmlModelStateOperation> stateOperations() const;
+
+ bool hasPropertyChanges(const ModelNode &node) const;
+
+ bool hasStateOperation(const ModelNode &node) const;
+
+ void removePropertyChanges(const ModelNode &node);
+
+ bool affectsModelNode(const ModelNode &node) const;
+ QString name() const;
+ void setName(const QString &name);
+ bool isValid() const;
+ void destroy();
+
+ bool isBaseState() const;
+ QmlModelState duplicate(const QString &name) const;
+ QmlModelStateGroup stateGroup() const;
+
+protected:
+ void addChangeSetIfNotExists(const ModelNode &node);
+ static QmlModelState createBaseState(const QmlModelView *view);
+
+private:
+ bool m_isBaseState;
+};
+
+} //QmlDesigner
+
+
+#endif // FXSTATE_H
diff --git a/src/plugins/qmldesigner/core/include/removebasestateexception.h b/src/plugins/qmldesigner/core/include/removebasestateexception.h
new file mode 100644
index 0000000000..38446aa88d
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/removebasestateexception.h
@@ -0,0 +1,49 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef REMOVEBASESTATEEXCEPTION_H
+#define REMOVEBASESTATEEXCEPTION_H
+
+#include <exception.h>
+
+namespace QmlDesigner {
+
+class CORESHARED_EXPORT RemoveBaseStateException : public Exception
+{
+public:
+ RemoveBaseStateException(int line,
+ const QString &function,
+ const QString &file);
+
+ QString type() const;
+
+};
+} // namespace QmlDesigner
+
+#endif // REMOVEBASESTATEEXCEPTION_H
diff --git a/src/plugins/qmldesigner/core/include/replaceallobjectdefinitionsvisitor.h b/src/plugins/qmldesigner/core/include/replaceallobjectdefinitionsvisitor.h
new file mode 100644
index 0000000000..2da2bb73ad
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/replaceallobjectdefinitionsvisitor.h
@@ -0,0 +1,59 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef REPLACEALLOBJECTDEFINITIONSVISITOR_H
+#define REPLACEALLOBJECTDEFINITIONSVISITOR_H
+
+#include "qmlrewriter.h"
+
+namespace QmlDesigner {
+namespace Internal {
+
+class ReplaceAllObjectDefinitionsVisitor: public QMLRewriter
+{
+public:
+ ReplaceAllObjectDefinitionsVisitor(TextModifier &textModifier,
+ const TextLocation &objectLocation,
+ const QString &newContent);
+
+protected:
+ virtual bool visit(QmlJS::AST::UiObjectDefinition *ast);
+ virtual bool visit(QmlJS::AST::UiObjectBinding *ast);
+
+private:
+ void replaceMembers(QmlJS::AST::UiObjectInitializer *initializer);
+
+private:
+ QString m_newContent;
+};
+
+} // namespace Internal
+} // namespace QmlDesigner
+
+#endif // REPLACEALLOBJECTDEFINITIONSVISITOR_H
diff --git a/src/plugins/qmldesigner/core/include/rewriterview.h b/src/plugins/qmldesigner/core/include/rewriterview.h
new file mode 100644
index 0000000000..4806bf41b9
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/rewriterview.h
@@ -0,0 +1,177 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef REWRITERVIEW_H
+#define REWRITERVIEW_H
+
+#include "corelib_global.h"
+#include "abstractview.h"
+#include "exception.h"
+#include <modelnodepositionstorage.h>
+#include <QtCore/QHash>
+#include <QtCore/QMap>
+#include <QPointer>
+#include <QWeakPointer>
+#include <QtCore/QHash>
+
+#include <modelnode.h>
+#include <QScopedPointer>
+
+
+namespace QmlDesigner {
+
+class CORESHARED_EXPORT TextModifier;
+
+namespace Internal {
+
+class TextToModelMerger;
+class ModelToTextMerger;
+class ModelNodePositionStorage;
+
+} //Internal
+
+
+class CORESHARED_EXPORT RewriterView : public AbstractView
+{
+ Q_OBJECT
+
+public:
+ enum DifferenceHandling {
+ Validate,
+ Amend
+ };
+
+ class Error {
+ public:
+ enum Type {
+ NoError = 0,
+ InternalError = 1,
+ ParseError = 2
+ };
+
+ public:
+ Error();
+ Error(const QmlError &qmlError);
+ Error(const Exception &exception);
+
+ Type type() const
+ { return m_type; }
+
+ int line() const
+ { return m_line; }
+
+ int column() const
+ { return m_column; }
+
+ QString description() const
+ { return m_description; }
+
+ QUrl url() const
+ { return m_url; }
+
+ QString toString() const;
+
+ private:
+ Type m_type;
+ int m_line;
+ int m_column;
+ QString m_description;
+ QUrl m_url;
+ };
+
+public:
+ RewriterView(DifferenceHandling differenceHandling, QObject *parent);
+ ~RewriterView();
+
+ void modelAttached(Model *model);
+ void modelAboutToBeDetached(Model *model);
+ void nodeCreated(const ModelNode &createdNode);
+ void nodeAboutToBeRemoved(const ModelNode &removedNode);
+ void nodeRemoved(const ModelNode &removedNode, const NodeAbstractProperty &parentProperty, PropertyChangeFlags propertyChange);
+ void propertiesAdded(const ModelNode &node, const QList<AbstractProperty>& propertyList);
+ void propertiesAboutToBeRemoved(const QList<AbstractProperty>& propertyList);
+ void propertiesRemoved(const QList<AbstractProperty>& propertyList);
+ void variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags propertyChange);
+ void bindingPropertiesChanged(const QList<BindingProperty>& propertyList, PropertyChangeFlags propertyChange);
+ void nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange);
+ void nodeIdChanged(const ModelNode& node, const QString& newId, const QString& oldId);
+ void nodeSlidedToIndex(const NodeListProperty &listProperty, int newIndex, int /*oldIndex*/);
+ void nodeTypeChanged(const ModelNode &node,const QString &type, int majorVersion, int minorVersion);
+ void customNotification(const AbstractView *view, const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> &data);
+
+ void fileUrlChanged(const QUrl &oldUrl, const QUrl &newUrl);
+
+ void selectedNodesChanged(const QList<ModelNode> &selectedNodeList, const QList<ModelNode> &lastSelectedNodeList);
+
+ TextModifier *textModifier() const;
+ void setTextModifier(TextModifier *textModifier);
+
+ Internal::ModelNodePositionStorage *positionStorage() const
+ { return m_positionStorage; }
+
+ QList<Error> errors() const;
+ void clearErrors();
+ void addErrors(const QList<Error> &errors);
+ void addError(const Error &error);
+
+ QMap<ModelNode, QString> extractText(const QList<ModelNode> &nodes) const;
+ int nodeOffset(const ModelNode &node) const;
+ int nodeLength(const ModelNode &node) const;
+ int firstDefinitionInsideOffset(const ModelNode &node) const;
+ int firstDefinitionInsideLength(const ModelNode &node) const;
+
+signals:
+ void errorsChanged(const QList<RewriterView::Error> &errors);
+
+public slots:
+ void qmlTextChanged();
+
+protected: // functions
+ Internal::ModelToTextMerger *modelToTextMerger() const;
+ Internal::TextToModelMerger *textToModelMerger() const;
+ bool isModificationGroupActive() const;
+ void setModificationGroupActive(bool active);
+ void applyModificationGroupChanges();
+ void setupComponent(const ModelNode &node);
+
+private: //variables
+ DifferenceHandling m_differenceHandling;
+ bool m_modificationGroupActive;
+ Internal::ModelNodePositionStorage *m_positionStorage;
+ QScopedPointer<Internal::ModelToTextMerger> m_modelToTextMerger;
+ QScopedPointer<Internal::TextToModelMerger> m_textToModelMerger;
+ TextModifier *m_textModifier;
+ QList<Error> m_errors;
+ int transactionLevel;
+ RewriterTransaction m_removeDefaultPropertyTransaction;
+};
+
+} //QmlDesigner
+
+#endif // REWRITERVIEW_H
diff --git a/src/plugins/qmldesigner/core/include/stylemanager.h b/src/plugins/qmldesigner/core/include/stylemanager.h
new file mode 100644
index 0000000000..a68c8d4bd2
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/stylemanager.h
@@ -0,0 +1,68 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef STYLEMANAGER_H
+#define STYLEMANAGER_H
+
+#include "corelib_global.h"
+#include <nodeinstanceview.h>
+#include <QList>
+#include <QStringList>
+
+namespace QmlDesigner {
+
+namespace Internal {
+class StyleManagerGuard;
+}
+
+class CORESHARED_EXPORT StyleManager {
+public:
+ static QStringList styles();
+ static void setStyle(const QString &styleName);
+ static QString applicationStyle();
+
+private:
+ StyleManager() {}
+ static StyleManager* instance();
+ static StyleManager* m_instance;
+ QList<NodeInstanceView*> m_views;
+ static void addView(NodeInstanceView* view);
+ static void removeView(NodeInstanceView* view);
+
+ friend class Internal::StyleManagerGuard;
+ friend class NodeInstanceView;
+};
+
+
+} //namespace QmlDesigner
+
+#endif //STYLEMANAGER_H
+
+
+
diff --git a/src/plugins/qmldesigner/core/include/subcomponentmanager.h b/src/plugins/qmldesigner/core/include/subcomponentmanager.h
new file mode 100644
index 0000000000..517e79072c
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/subcomponentmanager.h
@@ -0,0 +1,68 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef SUBCOMPONENTMANAGER_H
+#define SUBCOMPONENTMANAGER_H
+
+#include "corelib_global.h"
+
+#include <QObject>
+#include <QString>
+#include <QUrl>
+#include <QmlDomImport>
+
+#include <metainfo.h>
+
+namespace QmlDesigner {
+
+class CORESHARED_EXPORT SubComponentManager : public QObject
+{
+ Q_OBJECT
+public:
+ SubComponentManager(MetaInfo metaInfo, QObject *parent = 0);
+ ~SubComponentManager();
+
+ void update(const QUrl &fileUrl, const QByteArray &data);
+ void update(const QUrl &fileUrl, const QList<QmlDomImport> &imports);
+
+ QStringList qmlFiles() const;
+ QStringList directories() const;
+
+signals:
+ void qmlFilesChanged(const QStringList &oldPathList, const QStringList &newPathList);
+
+private:
+ friend class Internal::SubComponentManagerPrivate;
+ class Internal::SubComponentManagerPrivate *m_d;
+};
+
+} // namespace QmlDesigner
+
+
+#endif // SUBCOMPONENTMANAGER_H
diff --git a/src/plugins/qmldesigner/core/include/textmodifier.h b/src/plugins/qmldesigner/core/include/textmodifier.h
new file mode 100644
index 0000000000..79092e3836
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/textmodifier.h
@@ -0,0 +1,91 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef TEXTMODIFIER_H
+#define TEXTMODIFIER_H
+
+#include <QtCore/QByteArray>
+#include <QtCore/QObject>
+
+#include <QTextCursor>
+#include <QTextDocument>
+
+#include "corelib_global.h"
+
+namespace QmlDesigner {
+
+class CORESHARED_EXPORT TextModifier: public QObject
+{
+ Q_OBJECT
+
+private:
+ TextModifier(const TextModifier &);
+ TextModifier &operator=(const TextModifier &);
+
+public:
+ struct MoveInfo {
+ int objectStart;
+ int objectEnd;
+ int leadingCharsToRemove;
+ int trailingCharsToRemove;
+
+ int destination;
+ QString prefixToInsert;
+ QString suffixToInsert;
+
+ MoveInfo(): objectStart(-1), objectEnd(-1), leadingCharsToRemove(0), trailingCharsToRemove(0), destination(-1) {}
+ };
+
+public:
+ TextModifier() {}
+ virtual ~TextModifier() = 0;
+
+ virtual void replace(int offset, int length, const QString& replacement) = 0;
+ virtual void move(const MoveInfo &moveInfo) = 0;
+ virtual void startGroup() = 0;
+ virtual void flushGroup() = 0;
+ virtual void commitGroup() = 0;
+
+ virtual QTextDocument *textDocument() const = 0;
+ virtual QString text() const = 0;
+ virtual QTextCursor textCursor() const = 0;
+
+ virtual void deactivateChangeSignals() = 0;
+ virtual void reactivateChangeSignals() = 0;
+
+signals:
+ void textChanged();
+
+ void replaced(int offset, int oldLength, int newLength);
+ void moved(const TextModifier::MoveInfo &moveInfo);
+};
+
+}
+
+#endif // TEXTMODIFIER_H
diff --git a/src/plugins/qmldesigner/core/include/variantproperty.h b/src/plugins/qmldesigner/core/include/variantproperty.h
new file mode 100644
index 0000000000..76a93c5662
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/variantproperty.h
@@ -0,0 +1,70 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef VARIANTROPERTY_H
+#define VARIANTROPERTY_H
+
+#include "corelib_global.h"
+#include "abstractproperty.h"
+
+
+namespace QmlDesigner {
+
+class AbstractView;
+
+namespace Internal {
+ class ModelPrivate;
+}
+
+class CORESHARED_EXPORT VariantProperty : public AbstractProperty
+{
+ friend class QmlDesigner::ModelNode;
+ friend class QmlDesigner::Internal::ModelPrivate;
+ friend class QmlDesigner::AbstractProperty;
+
+public:
+ void setValue(const QVariant &value);
+ QVariant value() const;
+ VariantProperty& operator= (const QVariant &value);
+
+ void setDynamicTypeNameAndValue(const QString &type, const QVariant &value);
+ VariantProperty& operator= (const QPair<QString, QVariant> &typeValuePair);
+
+ VariantProperty();
+ VariantProperty(const VariantProperty &property, AbstractView *view);
+protected:
+ VariantProperty(const QString &propertyName, const Internal::InternalNodePointer &internalNode, Model* model, AbstractView *view);
+};
+
+CORESHARED_EXPORT QTextStream& operator<<(QTextStream &stream, const VariantProperty &property);
+CORESHARED_EXPORT QDebug operator<<(QDebug debug, const VariantProperty &VariantProperty);
+
+}
+
+#endif //VARIANTPROPERTY_H
diff --git a/src/plugins/qmldesigner/core/include/widgetplugin_helper.h b/src/plugins/qmldesigner/core/include/widgetplugin_helper.h
new file mode 100644
index 0000000000..1d305b0ada
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/widgetplugin_helper.h
@@ -0,0 +1,37 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef WIDGETPLUGIN_HELPER_H
+#define WIDGETPLUGIN_HELPER_H
+
+#define QMLDESIGNER_REGISTER_WIDGET(TYPE) uiEngine->addObjectCreator(new QUiWidgetCreator<TYPE>(QLatin1String(#TYPE)));
+#define QMLDESIGNER_REGISTER_GRAPHICSWIDGET(TYPE) uiEngine->addObjectCreator(new QUiGraphicsWidgetCreator<TYPE>(QLatin1String(#TYPE)));
+
+#endif //WIDGETPLUGIN_HELPER
+
diff --git a/src/plugins/qmldesigner/core/include/widgetqueryview.h b/src/plugins/qmldesigner/core/include/widgetqueryview.h
new file mode 100644
index 0000000000..bba8d8cc27
--- /dev/null
+++ b/src/plugins/qmldesigner/core/include/widgetqueryview.h
@@ -0,0 +1,56 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef WIDGETQUERYVIEW_H
+#define WIDGETQUERYVIEW_H
+
+#include "corelib_global.h"
+#include "nodeinstanceview.h"
+#include "propertycontainer.h"
+#include <QtCore/QHash>
+#include <QtCore/QList>
+#include <QtCore/QString>
+#include <QtCore/QVariant>
+#include <QtGui/QImage>
+
+namespace QmlDesigner {
+
+class CORESHARED_EXPORT WidgetQueryView : public NodeInstanceView
+{
+ Q_OBJECT
+public:
+ WidgetQueryView(QObject *parent);
+
+ QImage paintObject(const NodeMetaInfo &metaInfo);
+ QImage paintObject(const NodeMetaInfo &metaInfo, const QList<PropertyContainer> &properties);
+};
+
+} //namespace QmlDesigner
+
+#endif // WIDGETQUERYVIEW_H
diff --git a/src/plugins/qmldesigner/core/instances/componentnodeinstance.cpp b/src/plugins/qmldesigner/core/instances/componentnodeinstance.cpp
new file mode 100644
index 0000000000..83301f5f4d
--- /dev/null
+++ b/src/plugins/qmldesigner/core/instances/componentnodeinstance.cpp
@@ -0,0 +1,100 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "componentnodeinstance.h"
+
+#include <invalidnodeinstanceexception.h>
+#include <QmlComponent>
+#include <QmlContext>
+
+namespace QmlDesigner {
+namespace Internal {
+
+
+ComponentNodeInstance::ComponentNodeInstance(QmlComponent *component)
+ : ObjectNodeInstance(component)
+{
+}
+
+QmlComponent *ComponentNodeInstance::component() const
+{
+ Q_ASSERT(qobject_cast<QmlComponent*>(object()));
+ return static_cast<QmlComponent*>(object());
+}
+
+ComponentNodeInstance::Pointer ComponentNodeInstance::create(const NodeMetaInfo &/*metaInfo*/, QmlContext *context, QObject *objectToBeWrapped)
+{
+ QmlComponent *component = 0;
+ if (objectToBeWrapped)
+ component = qobject_cast<QmlComponent *>(objectToBeWrapped);
+ else
+ component = new QmlComponent(context->engine());
+
+ if (component == 0)
+ throw InvalidNodeInstanceException(__LINE__, __FUNCTION__, __FILE__);
+
+
+ Pointer instance(new ComponentNodeInstance(component));
+
+ if (objectToBeWrapped)
+ instance->setDeleteHeldInstance(false); // the object isn't owned
+
+ instance->populateResetValueHash();
+
+ return instance;
+}
+
+bool ComponentNodeInstance::hasContent() const
+{
+ return true;
+}
+
+void ComponentNodeInstance::setPropertyVariant(const QString &name, const QVariant &value)
+{
+ if (name == "__component_data") {
+ QByteArray data(value.toByteArray());
+ QByteArray imports;
+ foreach(const Import &import, modelNode().model()->imports()) {
+ imports.append(import.toString(true).toLatin1());
+ }
+
+ data.prepend(imports);
+
+ component()->setData(data, nodeInstanceView()->model()->fileUrl());
+
+ }
+ if (component()->isError()) {
+ qDebug() << value;
+ foreach(const QmlError &error, component()->errors())
+ qDebug() << error;
+ }
+
+}
+} // Internal
+} // QmlDesigner
diff --git a/src/plugins/qmldesigner/core/instances/componentnodeinstance.h b/src/plugins/qmldesigner/core/instances/componentnodeinstance.h
new file mode 100644
index 0000000000..4554e57ad5
--- /dev/null
+++ b/src/plugins/qmldesigner/core/instances/componentnodeinstance.h
@@ -0,0 +1,60 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef COMPONENTNODEINSTANCE_H
+#define COMPONENTNODEINSTANCE_H
+
+#include "objectnodeinstance.h"
+
+class QmlComponent;
+
+namespace QmlDesigner {
+namespace Internal {
+
+class ComponentNodeInstance : public ObjectNodeInstance
+{
+public:
+ typedef QSharedPointer<ComponentNodeInstance> Pointer;
+ typedef QWeakPointer<ComponentNodeInstance> WeakPointer;
+ ComponentNodeInstance(QmlComponent *component);
+ static Pointer create(const NodeMetaInfo &metaInfo, QmlContext *context, QObject *objectToBeWrapped);
+
+ void setPropertyVariant(const QString &name, const QVariant &value);
+
+ bool hasContent() const;
+
+private: //function
+ QmlComponent *component() const;
+
+};
+
+} // Internal
+} // QmlDesigner
+
+#endif // COMPONENTNODEINSTANCE_H
diff --git a/src/plugins/qmldesigner/core/instances/dummynodeinstance.cpp b/src/plugins/qmldesigner/core/instances/dummynodeinstance.cpp
new file mode 100644
index 0000000000..5c1ba815f0
--- /dev/null
+++ b/src/plugins/qmldesigner/core/instances/dummynodeinstance.cpp
@@ -0,0 +1,121 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "dummynodeinstance.h"
+
+#include <QmlMetaType>
+#include <nodemetainfo.h>
+
+#include <invalidnodeinstanceexception.h>
+#include <propertymetainfo.h>
+
+namespace QmlDesigner {
+namespace Internal {
+
+DummyNodeInstance::DummyNodeInstance()
+ : ObjectNodeInstance(0)
+{
+}
+
+DummyNodeInstance::Pointer DummyNodeInstance::create(const NodeMetaInfo & metaInfo, QmlContext *context)
+{
+ Q_UNUSED(context);
+ qWarning() << "DummyNodeInstance created" << metaInfo.typeName();
+ foreach(const NodeMetaInfo &metaInfo, metaInfo.superClasses())
+ qWarning() << "\t" << metaInfo.typeName();
+ return Pointer(new DummyNodeInstance);
+}
+
+void DummyNodeInstance::paint(QPainter * /*painter*/) const
+{
+}
+
+bool DummyNodeInstance::isTopLevel() const
+{
+ return false;
+}
+
+QRectF DummyNodeInstance::boundingRect() const
+{
+ return QRectF();
+}
+
+QPointF DummyNodeInstance::position() const
+{
+ return QPointF();
+}
+
+QSizeF DummyNodeInstance::size() const
+{
+ return QSizeF();
+}
+
+QTransform DummyNodeInstance::transform() const
+{
+ return QTransform();
+}
+
+double DummyNodeInstance::opacity() const
+{
+ return 0.0;
+}
+
+void DummyNodeInstance::setPropertyVariant(const QString &/*name*/, const QVariant &/*value*/)
+{
+}
+
+QVariant DummyNodeInstance::property(const QString &/*name*/) const
+{
+ return QVariant();
+}
+
+QStringList DummyNodeInstance::properties()
+{
+ return QStringList();
+}
+
+QStringList DummyNodeInstance::localProperties()
+{
+ return QStringList();
+}
+
+bool DummyNodeInstance::isVisible() const
+{
+ return false;
+}
+
+void DummyNodeInstance::setVisible(bool /*isVisible*/)
+{
+ Q_ASSERT_X(0, Q_FUNC_INFO, "Cannot set a dummy node instance to visible/non-visible");
+ throw InvalidNodeInstanceException(__LINE__, __FUNCTION__, __FILE__);
+}
+
+
+} // namespace Internal
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/core/instances/dummynodeinstance.h b/src/plugins/qmldesigner/core/instances/dummynodeinstance.h
new file mode 100644
index 0000000000..e1b9c7917d
--- /dev/null
+++ b/src/plugins/qmldesigner/core/instances/dummynodeinstance.h
@@ -0,0 +1,73 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef DUMMYNODEINSTANCE_H
+#define DUMMYNODEINSTANCE_H
+
+#include <QWeakPointer>
+
+#include "objectnodeinstance.h"
+
+namespace QmlDesigner {
+namespace Internal {
+
+class DummyNodeInstance : public ObjectNodeInstance
+{
+public:
+ typedef QSharedPointer<DummyNodeInstance> Pointer;
+ typedef QWeakPointer<DummyNodeInstance> WeakPointer;
+
+ static Pointer create(const NodeMetaInfo &metaInfo, QmlContext *context);
+
+ void paint(QPainter *painter) const;
+
+ bool isTopLevel() const;
+
+ QRectF boundingRect() const;
+ QPointF position() const;
+ QSizeF size() const;
+ QTransform transform() const;
+ double opacity() const;
+
+ void setPropertyVariant(const QString &name, const QVariant &value);
+ QVariant property(const QString &name) const;
+ QStringList properties();
+ QStringList localProperties();
+
+ bool isVisible() const;
+ void setVisible(bool isVisible);
+
+protected:
+ DummyNodeInstance();
+
+};
+
+}
+}
+#endif // DUMMYNODEINSTANCE_H
diff --git a/src/plugins/qmldesigner/core/instances/graphicsobjectnodeinstance.cpp b/src/plugins/qmldesigner/core/instances/graphicsobjectnodeinstance.cpp
new file mode 100644
index 0000000000..973ec1029e
--- /dev/null
+++ b/src/plugins/qmldesigner/core/instances/graphicsobjectnodeinstance.cpp
@@ -0,0 +1,226 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "graphicsobjectnodeinstance.h"
+
+#include "invalidnodeinstanceexception.h"
+#include <QGraphicsObject>
+#include "nodemetainfo.h"
+
+namespace QmlDesigner {
+namespace Internal {
+
+GraphicsObjectNodeInstance::GraphicsObjectNodeInstance(QGraphicsObject *graphicsObject, bool hasContent)
+ : ObjectNodeInstance(graphicsObject),
+ m_isVisible(true),
+ m_hasContent(hasContent)
+{
+}
+
+QGraphicsObject *GraphicsObjectNodeInstance::graphicsObject() const
+{
+ Q_ASSERT(qobject_cast<QGraphicsObject*>(object()));
+ return static_cast<QGraphicsObject*>(object());
+}
+
+bool GraphicsObjectNodeInstance::hasContent() const
+{
+ return m_hasContent;
+}
+
+bool GraphicsObjectNodeInstance::isVisible() const
+{
+ return m_isVisible;
+}
+
+void GraphicsObjectNodeInstance::setVisible(bool isVisible)
+{
+ m_isVisible = isVisible;
+}
+
+QPointF GraphicsObjectNodeInstance::position() const
+{
+ return graphicsObject()->pos();
+}
+
+QSizeF GraphicsObjectNodeInstance::size() const
+{
+ return graphicsObject()->boundingRect().size();
+}
+
+QTransform GraphicsObjectNodeInstance::transform() const
+{
+ if (graphicsObject()->parentItem())
+ return graphicsObject()->itemTransform(graphicsObject()->parentItem());
+ else
+ return sceneTransform();
+}
+
+QTransform GraphicsObjectNodeInstance::customTransform() const
+{
+ return graphicsObject()->transform();
+}
+
+QTransform GraphicsObjectNodeInstance::sceneTransform() const
+{
+ return graphicsObject()->sceneTransform();
+}
+
+double GraphicsObjectNodeInstance::rotation() const
+{
+ return graphicsObject()->rotation();
+}
+
+double GraphicsObjectNodeInstance::scale() const
+{
+ return graphicsObject()->scale();
+}
+
+QList<QGraphicsTransform *> GraphicsObjectNodeInstance::transformations() const
+{
+ return graphicsObject()->transformations();
+}
+
+QPointF GraphicsObjectNodeInstance::transformOriginPoint() const
+{
+ return graphicsObject()->transformOriginPoint();
+}
+
+double GraphicsObjectNodeInstance::zValue() const
+{
+ return graphicsObject()->zValue();
+}
+
+double GraphicsObjectNodeInstance::opacity() const
+{
+ return graphicsObject()->opacity();
+}
+
+QObject *GraphicsObjectNodeInstance::parent() const
+{
+ if (!graphicsObject() || !graphicsObject()->parentItem())
+ return 0;
+
+ return graphicsObject()->parentItem()->toGraphicsObject();
+}
+
+QRectF GraphicsObjectNodeInstance::boundingRect() const
+{
+ return graphicsObject()->boundingRect();
+}
+
+bool GraphicsObjectNodeInstance::isTopLevel() const
+{
+ Q_ASSERT(graphicsObject());
+ return !graphicsObject()->parentItem();
+}
+
+bool GraphicsObjectNodeInstance::isGraphicsObject() const
+{
+ return true;
+}
+
+void GraphicsObjectNodeInstance::setPropertyVariant(const QString &name, const QVariant &value)
+{
+ if (name == "visible") {
+ setVisible(value.toBool());
+ return;
+ }
+
+ ObjectNodeInstance::setPropertyVariant(name, value);
+}
+
+QVariant GraphicsObjectNodeInstance::property(const QString &name) const
+{
+ if (name == "visible")
+ return isVisible();
+
+ return ObjectNodeInstance::property(name);
+}
+
+bool GraphicsObjectNodeInstance::equalGraphicsItem(QGraphicsItem *item) const
+{
+ return item == graphicsObject();
+}
+
+void GraphicsObjectNodeInstance::paintRecursively(QGraphicsItem *graphicsItem, QPainter *painter) const
+{
+ if (graphicsItem->isVisible()) {
+ painter->save();
+ painter->setTransform(graphicsItem->itemTransform(graphicsItem->parentItem()), true);
+ painter->setOpacity(graphicsItem->opacity() * painter->opacity());
+ graphicsItem->paint(painter, 0);
+ foreach(QGraphicsItem *childItem, graphicsItem->childItems()) {
+ paintRecursively(childItem, painter);
+ }
+ painter->restore();
+ }
+}
+
+void GraphicsObjectNodeInstance::paint(QPainter *painter) const
+{
+ painter->save();
+ Q_ASSERT(graphicsObject());
+ if (isVisible()) {
+ if (hasContent())
+ graphicsObject()->paint(painter, 0);
+
+ foreach(QGraphicsItem *graphicsItem, graphicsObject()->childItems()) {
+ QGraphicsObject *graphicsObject = qgraphicsitem_cast<QGraphicsObject*>(graphicsItem);
+ if (graphicsObject && !graphicsObject->property("HasFormEditorItem").toBool())
+ paintRecursively(graphicsItem, painter);
+ }
+ }
+
+ painter->restore();
+}
+
+QPair<QGraphicsObject*, bool> GraphicsObjectNodeInstance::createGraphicsObject(const NodeMetaInfo &metaInfo, QmlContext *context)
+{
+ QObject *object = ObjectNodeInstance::createObject(metaInfo, context);
+ QGraphicsObject *graphicsObject = qobject_cast<QGraphicsObject*>(object);
+
+ if (graphicsObject == 0)
+ throw InvalidNodeInstanceException(__LINE__, __FUNCTION__, __FILE__);
+
+// graphicsObject->setCacheMode(QGraphicsItem::ItemCoordinateCache);
+ bool hasContent = !graphicsObject->flags().testFlag(QGraphicsItem::ItemHasNoContents) || metaInfo.isComponent();
+ graphicsObject->setFlag(QGraphicsItem::ItemHasNoContents, false);
+
+ graphicsObject->setProperty("HasFormEditorItem", true);
+
+ return qMakePair(graphicsObject, hasContent);
+}
+
+void GraphicsObjectNodeInstance::paintUpdate()
+{
+ graphicsObject()->update();
+}
+} // namespace Internal
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/core/instances/graphicsobjectnodeinstance.h b/src/plugins/qmldesigner/core/instances/graphicsobjectnodeinstance.h
new file mode 100644
index 0000000000..797b064f67
--- /dev/null
+++ b/src/plugins/qmldesigner/core/instances/graphicsobjectnodeinstance.h
@@ -0,0 +1,90 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef GRAPHICSOBJECTNODEINSTANCE_H
+#define GRAPHICSOBJECTNODEINSTANCE_H
+
+#include "objectnodeinstance.h"
+
+class QGraphicsObject;
+
+namespace QmlDesigner {
+namespace Internal {
+
+class GraphicsObjectNodeInstance : public ObjectNodeInstance
+{
+public:
+ GraphicsObjectNodeInstance(QGraphicsObject *graphicsObject, bool hasContent);
+
+ void paint(QPainter *painter) const;
+
+ bool isTopLevel() const;
+ bool isGraphicsObject() const;
+
+ QRectF boundingRect() const;
+ QPointF position() const;
+ QSizeF size() const;
+ QTransform transform() const;
+ QTransform customTransform() const;
+ QTransform sceneTransform() const;
+ double opacity() const;
+
+ QObject *parent() const;
+
+ double rotation() const;
+ double scale() const;
+ QList<QGraphicsTransform *> transformations() const;
+ QPointF transformOriginPoint() const;
+ double zValue() const;
+
+ bool equalGraphicsItem(QGraphicsItem *item) const;
+
+ bool isVisible() const;
+ void setVisible(bool isVisible);
+
+ void setPropertyVariant(const QString &name, const QVariant &value);
+ QVariant property(const QString &name) const;
+
+ bool hasContent() const;
+
+ void paintUpdate();
+
+protected:
+ QGraphicsObject *graphicsObject() const;
+ void paintRecursively(QGraphicsItem *graphicsItem, QPainter *painter) const;
+ static QPair<QGraphicsObject*, bool> createGraphicsObject(const NodeMetaInfo &metaInfo, QmlContext *context);
+private: // variables
+ bool m_isVisible;
+ bool m_hasContent;
+};
+
+} // namespace Internal
+} // namespace QmlDesigner
+
+#endif // GRAPHICSOBJECTNODEINSTANCE_H
diff --git a/src/plugins/qmldesigner/core/instances/graphicsscenenodeinstance.cpp b/src/plugins/qmldesigner/core/instances/graphicsscenenodeinstance.cpp
new file mode 100644
index 0000000000..41e919b947
--- /dev/null
+++ b/src/plugins/qmldesigner/core/instances/graphicsscenenodeinstance.cpp
@@ -0,0 +1,158 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "graphicsscenenodeinstance.h"
+
+#include <QmlMetaType>
+
+#include "graphicsviewnodeinstance.h"
+
+#include <invalidnodeinstanceexception.h>
+#include <propertymetainfo.h>
+
+namespace QmlDesigner {
+namespace Internal {
+
+GraphicsSceneNodeInstance::GraphicsSceneNodeInstance(QGraphicsScene *scene)
+ :ObjectNodeInstance(scene)
+{
+}
+
+GraphicsSceneNodeInstance::~GraphicsSceneNodeInstance()
+{
+}
+
+GraphicsSceneNodeInstance::Pointer GraphicsSceneNodeInstance::create(const NodeMetaInfo &nodeMetaInfo, QmlContext *context, QObject *objectToBeWrapped)
+{
+ QObject *object = 0;
+ if (objectToBeWrapped)
+ object = objectToBeWrapped;
+ else
+ object = createObject(nodeMetaInfo, context);
+
+ QGraphicsScene* scene = qobject_cast<QGraphicsScene*>(object);
+ if (scene == 0)
+ throw InvalidNodeInstanceException(__LINE__, __FUNCTION__, __FILE__);
+
+ Pointer instance(new GraphicsSceneNodeInstance(scene));
+
+ if (objectToBeWrapped)
+ instance->setDeleteHeldInstance(false); // the object isn't owned
+
+ instance->populateResetValueHash();
+
+ return instance;
+}
+
+void GraphicsSceneNodeInstance::paint(QPainter *) const
+{
+ Q_ASSERT(graphicsScene());
+}
+
+bool GraphicsSceneNodeInstance::isTopLevel() const
+{
+ Q_ASSERT(graphicsScene());
+ return graphicsScene()->views().isEmpty();
+}
+
+
+void GraphicsSceneNodeInstance::addItem(QGraphicsItem *item)
+{
+ graphicsScene()->addItem(item);
+}
+
+bool GraphicsSceneNodeInstance::isGraphicsScene() const
+{
+ return true;
+}
+
+QRectF GraphicsSceneNodeInstance::boundingRect() const
+{
+ return graphicsScene()->sceneRect();
+}
+
+QPointF GraphicsSceneNodeInstance::position() const
+{
+ return graphicsScene()->sceneRect().topLeft();
+}
+
+QSizeF GraphicsSceneNodeInstance::size() const
+{
+ return graphicsScene()->sceneRect().size();
+}
+
+QGraphicsScene *GraphicsSceneNodeInstance::graphicsScene() const
+{
+ Q_ASSERT(qobject_cast<QGraphicsScene*>(object()));
+ return static_cast<QGraphicsScene*>(object());
+}
+
+bool GraphicsSceneNodeInstance::isVisible() const
+{
+ return false;
+}
+
+void GraphicsSceneNodeInstance::setVisible(bool /*isVisible*/)
+{
+
+}
+
+
+QList<NodeInstance> GraphicsSceneNodeInstance::instancesInRegions(const QList<QRectF> &regions)
+{
+ QRectF combinedRect;
+ foreach (const QRectF &rect, regions) {
+ combinedRect = combinedRect.united(rect);
+ }
+
+ QList<QGraphicsItem*> itemList;
+ // collect list of possibly changed items
+ // (actually QGraphicsScene could export this)
+
+ foreach (QGraphicsItem *item, graphicsScene()->items(combinedRect.adjusted(0, 0, 1, 1), Qt::ContainsItemBoundingRect)) {
+ if (!itemList.contains(item))
+ itemList.append(item);
+ }
+
+ QList<NodeInstance> instances;
+ if (!itemList.isEmpty()) {
+ foreach (const NodeInstance &nodeInstance, nodeInstanceView()->instances()) {
+ foreach (QGraphicsItem *gvItem, itemList) {
+ if (nodeInstance.equalGraphicsItem(gvItem)) {
+ instances += nodeInstance;
+ }
+ }
+ }
+ }
+
+ return instances;
+}
+
+}
+}
diff --git a/src/plugins/qmldesigner/core/instances/graphicsscenenodeinstance.h b/src/plugins/qmldesigner/core/instances/graphicsscenenodeinstance.h
new file mode 100644
index 0000000000..0c92e731a2
--- /dev/null
+++ b/src/plugins/qmldesigner/core/instances/graphicsscenenodeinstance.h
@@ -0,0 +1,75 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef GRAPHICSSCENENODEINSTANCE_H
+#define GRAPHICSSCENENODEINSTANCE_H
+
+#include "objectnodeinstance.h"
+#include <QGraphicsScene>
+#include <QWeakPointer>
+
+namespace QmlDesigner {
+namespace Internal {
+
+class GraphicsSceneNodeInstance : public ObjectNodeInstance
+{
+public:
+ typedef QSharedPointer<GraphicsSceneNodeInstance> Pointer;
+ typedef QWeakPointer<GraphicsSceneNodeInstance> WeakPointer;
+
+ ~GraphicsSceneNodeInstance();
+
+ static Pointer create(const NodeMetaInfo &metaInfo, QmlContext *context, QObject *objectToBeWrapped);
+
+ void paint(QPainter *painter) const;
+
+ bool isTopLevel() const;
+
+ void addItem(QGraphicsItem *item);
+
+ bool isGraphicsScene() const;
+
+ QRectF boundingRect() const;
+ QPointF position() const;
+ QSizeF size() const;
+
+
+ bool isVisible() const;
+ void setVisible(bool isVisible);
+
+ QList<NodeInstance> instancesInRegions(const QList<QRectF> &region);
+
+protected:
+ GraphicsSceneNodeInstance(QGraphicsScene *scene);
+ QGraphicsScene *graphicsScene() const;
+};
+
+}
+}
+#endif // GRAPHICSSCENENODEINSTANCE_H
diff --git a/src/plugins/qmldesigner/core/instances/graphicsviewnodeinstance.cpp b/src/plugins/qmldesigner/core/instances/graphicsviewnodeinstance.cpp
new file mode 100644
index 0000000000..be32b0b813
--- /dev/null
+++ b/src/plugins/qmldesigner/core/instances/graphicsviewnodeinstance.cpp
@@ -0,0 +1,111 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "graphicsviewnodeinstance.h"
+
+#include <QmlMetaType>
+#include <QmlEngine>
+#include <invalidnodeinstanceexception.h>
+
+#include <QtOpenGL/QGLWidget>
+
+namespace QmlDesigner {
+namespace Internal {
+
+GraphicsViewNodeInstance::GraphicsViewNodeInstance(QGraphicsView *view)
+ : WidgetNodeInstance(view)
+{
+}
+
+
+GraphicsViewNodeInstance::Pointer GraphicsViewNodeInstance::create(const NodeMetaInfo &nodeMetaInfo,
+ QmlContext *context,
+ QObject *objectToBeWrapped)
+{
+ QObject *object = 0;
+ if (objectToBeWrapped)
+ object = objectToBeWrapped;
+ else
+ object = createObject(nodeMetaInfo, context);
+
+ QGraphicsView* view = qobject_cast<QGraphicsView*>(object);
+ if (view == 0)
+ throw InvalidNodeInstanceException(__LINE__, __FUNCTION__, __FILE__);
+
+ Pointer instance(new GraphicsViewNodeInstance(view));
+
+ if (objectToBeWrapped)
+ instance->setDeleteHeldInstance(false); // the object isn't owned
+
+ instance->populateResetValueHash();
+
+ return instance;
+}
+
+QGraphicsView* GraphicsViewNodeInstance::graphicsView() const
+{
+ QGraphicsView* view = qobject_cast<QGraphicsView*>(widget());
+ Q_ASSERT(view);
+ return view;
+}
+
+void GraphicsViewNodeInstance::setScene(QGraphicsScene *scene)
+{
+ graphicsView()->setScene(scene);
+}
+
+bool GraphicsViewNodeInstance::isGraphicsView() const
+{
+ return true;
+}
+
+QSizeF GraphicsViewNodeInstance::size() const
+{
+ return graphicsView()->scene()->itemsBoundingRect().size();
+}
+
+QTransform GraphicsViewNodeInstance::transform() const
+{
+ return graphicsView()->transform();
+}
+
+void GraphicsViewNodeInstance::paint(QPainter *painter) const
+{
+ painter->save();
+ painter->setRenderHint(QPainter::Antialiasing, true);
+ painter->setRenderHint(QPainter::TextAntialiasing, true);
+ painter->setRenderHint(QPainter::SmoothPixmapTransform, true);
+ painter->setRenderHint(QPainter::HighQualityAntialiasing, true);
+ painter->setRenderHint(QPainter::NonCosmeticDefaultPen, true);
+ graphicsView()->render(painter, QRectF(), graphicsView()->scene()->itemsBoundingRect().toRect());
+ painter->restore();
+}
+
+}
+}
diff --git a/src/plugins/qmldesigner/core/instances/graphicsviewnodeinstance.h b/src/plugins/qmldesigner/core/instances/graphicsviewnodeinstance.h
new file mode 100644
index 0000000000..3a55007beb
--- /dev/null
+++ b/src/plugins/qmldesigner/core/instances/graphicsviewnodeinstance.h
@@ -0,0 +1,67 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef GRAPHICSVIEWNODEINSTANCE_H
+#define GRAPHICSVIEWNODEINSTANCE_H
+
+#include <QWeakPointer>
+#include <QGraphicsView>
+
+#include "widgetnodeinstance.h"
+
+namespace QmlDesigner {
+namespace Internal {
+
+class GraphicsViewNodeInstance : public WidgetNodeInstance
+{
+public:
+ typedef QSharedPointer<GraphicsViewNodeInstance> Pointer;
+ typedef QWeakPointer<GraphicsViewNodeInstance> WeakPointer;
+
+ static Pointer create(const NodeMetaInfo &metaInfo, QmlContext *context, QObject *objectToBeWrapped);
+
+ void setScene(QGraphicsScene *scene);
+
+ bool isGraphicsView() const;
+
+ QTransform transform() const;
+ QSizeF size() const;
+
+
+ void paint(QPainter *painter) const;
+
+protected:
+ GraphicsViewNodeInstance(QGraphicsView *view);
+
+ QGraphicsView* graphicsView() const;
+};
+
+}
+}
+#endif // GRAPHICSVIEWNODEINSTANCE_H
diff --git a/src/plugins/qmldesigner/core/instances/graphicswidgetnodeinstance.cpp b/src/plugins/qmldesigner/core/instances/graphicswidgetnodeinstance.cpp
new file mode 100644
index 0000000000..9cd44efdf8
--- /dev/null
+++ b/src/plugins/qmldesigner/core/instances/graphicswidgetnodeinstance.cpp
@@ -0,0 +1,185 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "graphicswidgetnodeinstance.h"
+#include "graphicsscenenodeinstance.h"
+
+#include "objectnodeinstance.h"
+
+#include <QmlMetaType>
+
+#include <invalidnodeinstanceexception.h>
+#include <propertymetainfo.h>
+
+namespace QmlDesigner {
+namespace Internal {
+
+GraphicsWidgetNodeInstance::GraphicsWidgetNodeInstance(QGraphicsWidget *widget)
+ : ObjectNodeInstance(widget)
+{
+}
+
+GraphicsWidgetNodeInstance::~GraphicsWidgetNodeInstance()
+{
+}
+
+GraphicsWidgetNodeInstance::Pointer GraphicsWidgetNodeInstance::create(const NodeMetaInfo &nodeMetaInfo, QmlContext *context, QObject *objectToBeWrapped)
+{
+ QObject *object = 0;
+ if (objectToBeWrapped)
+ object = objectToBeWrapped;
+ else
+ object = createObject(nodeMetaInfo, context);
+
+ QGraphicsWidget* graphicsWidget = qobject_cast<QGraphicsWidget*>(object);
+ if (graphicsWidget == 0)
+ throw InvalidNodeInstanceException(__LINE__, __FUNCTION__, __FILE__);
+
+ Pointer instance(new GraphicsWidgetNodeInstance(graphicsWidget));
+
+ if (objectToBeWrapped)
+ instance->setDeleteHeldInstance(false); // the object isn't owned
+
+ instance->populateResetValueHash();
+
+ return instance;
+}
+
+void GraphicsWidgetNodeInstance::paint(QPainter *painter) const
+{
+ graphicsWidget()->show();
+ graphicsWidget()->paint(painter, 0);
+
+ paintChildren(painter, graphicsWidget());
+}
+
+bool GraphicsWidgetNodeInstance::isTopLevel() const
+{
+ return !graphicsWidget()->parentItem();
+}
+
+
+bool isChildNode(QGraphicsItem *item)
+{
+ // there should be a better implementation
+ if (qgraphicsitem_cast<QGraphicsWidget*>(item))
+ return false;
+ else
+ return true;
+}
+
+void GraphicsWidgetNodeInstance::paintChildren(QPainter *painter, QGraphicsItem *item) const
+{
+ foreach (QGraphicsItem *childItem, item->childItems()) {
+ if (!isChildNode(childItem)) {
+ painter->save();
+ painter->setTransform(item->transform(), true);
+ item->paint(painter, 0);
+ paintChildren(painter, childItem);
+ painter->restore();
+ }
+ }
+}
+
+void GraphicsWidgetNodeInstance::setParentItem(QGraphicsItem *item)
+{
+ graphicsWidget()->setParentItem(item);
+}
+
+QGraphicsWidget* GraphicsWidgetNodeInstance::graphicsWidget() const
+{
+ return static_cast<QGraphicsWidget*>(object());
+}
+
+bool GraphicsWidgetNodeInstance::isGraphicsWidget() const
+{
+ return true;
+}
+
+bool GraphicsWidgetNodeInstance::isGraphicsItem(QGraphicsItem *item) const
+{
+ return graphicsWidget() == item;
+}
+
+QRectF GraphicsWidgetNodeInstance::boundingRect() const
+{
+ return graphicsWidget()->boundingRect();
+}
+
+void GraphicsWidgetNodeInstance::setPropertyVariant(const QString &name, const QVariant &value)
+{
+ if (name == "x")
+ graphicsWidget()->setPos(value.toDouble(), graphicsWidget()->y());
+ else if (name == "y")
+ graphicsWidget()->setPos(graphicsWidget()->x(), value.toDouble());
+ else if (name == "width")
+ graphicsWidget()->resize(value.toDouble(), graphicsWidget()->size().height());
+ else if (name == "height")
+ graphicsWidget()->resize(graphicsWidget()->size().width(), value.toDouble());
+ else
+ graphicsWidget()->setProperty(name.toLatin1(), value);
+}
+
+QVariant GraphicsWidgetNodeInstance::property(const QString &name) const
+{
+ return graphicsWidget()->property(name.toLatin1());
+}
+
+bool GraphicsWidgetNodeInstance::isVisible() const
+{
+ return graphicsWidget()->isVisible();
+}
+
+void GraphicsWidgetNodeInstance::setVisible(bool isVisible)
+{
+ graphicsWidget()->setVisible(isVisible);
+}
+
+QPointF GraphicsWidgetNodeInstance::position() const
+{
+ return graphicsWidget()->pos();
+}
+
+QSizeF GraphicsWidgetNodeInstance::size() const
+{
+ return graphicsWidget()->size();
+}
+
+QTransform GraphicsWidgetNodeInstance::transform() const
+{
+ return graphicsWidget()->transform();
+}
+
+double GraphicsWidgetNodeInstance::opacity() const
+{
+ return graphicsWidget()->opacity();
+}
+
+}
+}
diff --git a/src/plugins/qmldesigner/core/instances/graphicswidgetnodeinstance.h b/src/plugins/qmldesigner/core/instances/graphicswidgetnodeinstance.h
new file mode 100644
index 0000000000..7bbcf96def
--- /dev/null
+++ b/src/plugins/qmldesigner/core/instances/graphicswidgetnodeinstance.h
@@ -0,0 +1,80 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef GRAPHICSWIDGETNODEINSTANCE_H
+#define GRAPHICSWIDGETNODEINSTANCE_H
+
+#include <QWeakPointer>
+#include <QGraphicsWidget>
+
+#include "objectnodeinstance.h"
+
+namespace QmlDesigner {
+namespace Internal {
+
+class GraphicsWidgetNodeInstance : public ObjectNodeInstance
+{
+public:
+ typedef QSharedPointer<GraphicsWidgetNodeInstance> Pointer;
+ typedef QWeakPointer<GraphicsWidgetNodeInstance> WeakPointer;
+
+ ~GraphicsWidgetNodeInstance();
+
+ static Pointer create(const NodeMetaInfo &metaInfo, QmlContext *context, QObject *objectToBeWrapped);
+
+ void paint(QPainter *painter) const;
+
+ bool isTopLevel() const;
+
+ bool isGraphicsWidget() const;
+ bool isGraphicsItem(QGraphicsItem *item) const;
+
+ QRectF boundingRect() const;
+ QPointF position() const;
+ QSizeF size() const;
+ QTransform transform() const;
+ double opacity() const;
+
+ void setPropertyVariant(const QString &name, const QVariant &value);
+ QVariant property(const QString &name) const;
+
+ bool isVisible() const;
+ void setVisible(bool isVisible);
+
+protected:
+ GraphicsWidgetNodeInstance(QGraphicsWidget *widget);
+ void paintChildren(QPainter *painter, QGraphicsItem *item) const;
+ void setParentItem(QGraphicsItem *item);
+ QGraphicsWidget* graphicsWidget() const;
+
+};
+
+}
+}
+#endif // GRAPHICSWIDGETNODEINSTANCE_H
diff --git a/src/plugins/qmldesigner/core/instances/nodeinstance.cpp b/src/plugins/qmldesigner/core/instances/nodeinstance.cpp
new file mode 100644
index 0000000000..00c4d556e4
--- /dev/null
+++ b/src/plugins/qmldesigner/core/instances/nodeinstance.cpp
@@ -0,0 +1,589 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "nodeinstance.h"
+
+#include "objectnodeinstance.h"
+#include "metainfo.h"
+#include "graphicswidgetnodeinstance.h"
+#include "widgetnodeinstance.h"
+#include "qmlgraphicsitemnodeinstance.h"
+#include "graphicsscenenodeinstance.h"
+#include "graphicsviewnodeinstance.h"
+#include "nodeinstanceview.h"
+#include "qmlviewnodeinstance.h"
+#include "dummynodeinstance.h"
+#include "componentnodeinstance.h"
+#include "qmltransitionnodeinstance.h"
+#include "qmlpropertychangesnodeinstance.h"
+#include "qmlstatenodeinstance.h"
+#include "nodeabstractproperty.h"
+#include "variantproperty.h"
+
+#include <invalidnodeinstanceexception.h>
+
+#include <QHash>
+#include <QSet>
+
+#include <QtDeclarative/QmlEngine>
+
+/*!
+ \class QmlDesigner::NodeInstance
+ \ingroup CoreInstance
+ \brief NodeInstance is a common handle for the actual object representation of a ModelNode.
+
+ NodeInstance abstracts away the differences e.g. in terms of position and size
+ for QWidget, QGraphicsView, QLayout etc objects. Multiple NodeInstance objects can share
+ the pointer to the same instance object. The actual instance will be deleted when
+ the last NodeInstance object referencing to it is deleted. This can be disabled by
+ setDeleteHeldInstance().
+
+ \see QmlDesigner::NodeInstanceView
+*/
+
+namespace QmlDesigner {
+
+/*!
+\brief Constructor - creates a invalid NodeInstance
+
+
+\see NodeInstanceView
+*/
+NodeInstance::NodeInstance()
+{
+}
+
+/*!
+\brief Destructor
+
+*/
+NodeInstance::~NodeInstance()
+{
+}
+
+/*!
+\brief Constructor - creates a valid NodeInstance
+
+*/
+NodeInstance::NodeInstance(const Internal::ObjectNodeInstance::Pointer &abstractInstance)
+ : m_nodeInstance(abstractInstance)
+{
+
+}
+
+
+NodeInstance::NodeInstance(const NodeInstance &other)
+ : m_nodeInstance(other.m_nodeInstance)
+{
+}
+
+NodeInstance &NodeInstance::operator=(const NodeInstance &other)
+{
+ m_nodeInstance = other.m_nodeInstance;
+ return *this;
+}
+
+/*!
+\brief Paints the NodeInstance with this painter.
+\param painter used QPainter
+*/
+void NodeInstance::paint(QPainter *painter) const
+{
+ m_nodeInstance->paint(painter);
+}
+
+/*!
+\brief Creates a new NodeInstace for this NodeMetaInfo
+
+\param metaInfo MetaInfo for which a Instance should be created
+\param context QmlContext which should be used
+\returns Internal Pointer of a NodeInstance
+\see NodeMetaInfo
+*/
+Internal::ObjectNodeInstance::Pointer NodeInstance::createInstance(const NodeMetaInfo &metaInfo,
+ QmlContext *context, QObject *objectToBeWrapped)
+{
+ Internal::ObjectNodeInstance::Pointer instance;
+
+ if (metaInfo.isSubclassOf("Qt/QGraphicsView", 4, 6))
+ instance = Internal::GraphicsViewNodeInstance::create(metaInfo, context, objectToBeWrapped);
+ else if (metaInfo.isSubclassOf("Qt/QmlView", 4, 6))
+ instance = Internal::QmlViewNodeInstance::create(metaInfo, context, objectToBeWrapped);
+ else if (metaInfo.isSubclassOf("Qt/QGraphicsWidget", 4, 6))
+ instance = Internal::GraphicsWidgetNodeInstance::create(metaInfo, context, objectToBeWrapped);
+ else if (metaInfo.isSubclassOf("Qt/Item", 4, 6))
+ instance = Internal::QmlGraphicsItemNodeInstance::create(metaInfo, context, objectToBeWrapped);
+ else if (metaInfo.isSubclassOf("Qt/QWidget", 4, 6))
+ instance = Internal::WidgetNodeInstance::create(metaInfo, context, objectToBeWrapped);
+ else if (metaInfo.isSubclassOf("Qt/QGraphicsScene", 4, 6))
+ instance = Internal::GraphicsSceneNodeInstance::create(metaInfo, context, objectToBeWrapped);
+ else if (metaInfo.isSubclassOf("Qt/Component", 4, 6))
+ instance = Internal::ComponentNodeInstance::create(metaInfo, context, objectToBeWrapped);
+ else if (metaInfo.isSubclassOf("Qt/PropertyChanges", 4, 6))
+ instance = Internal::QmlPropertyChangesNodeInstance::create(metaInfo, context, objectToBeWrapped);
+ else if (metaInfo.isSubclassOf("Qt/State", 4, 6))
+ instance = Internal::QmlStateNodeInstance::create(metaInfo, context, objectToBeWrapped);
+ else if (metaInfo.isSubclassOf("Qt/Transition", 4, 6))
+ instance = Internal::QmlTransitionNodeInstance::create(metaInfo, context, objectToBeWrapped);
+ else if (metaInfo.isSubclassOf("Qt/QtObject", 4, 6))
+ instance = Internal::ObjectNodeInstance::create(metaInfo, context, objectToBeWrapped);
+
+ if (instance.isNull()) {
+ instance = Internal::DummyNodeInstance::create(metaInfo, context);
+ }
+
+ return instance;
+}
+
+
+
+NodeInstance NodeInstance::create(NodeInstanceView *nodeInstanceView, const ModelNode &node, QObject *objectToBeWrapped)
+{
+ Q_ASSERT(node.isValid());
+ Q_ASSERT(nodeInstanceView);
+
+ // For the moment just use the root context of the engine
+ // for all items. However, this is a hack ... ideally we should
+ // rebuild the same context hierarchy as the qml compiler does
+
+ QmlContext *context = nodeInstanceView->engine()->rootContext();
+
+ NodeInstance instance(createInstance(node.metaInfo(), context, objectToBeWrapped));
+
+ instance.m_nodeInstance->setModelNode(node);
+
+ instance.m_nodeInstance->setNodeInstance(nodeInstanceView);
+
+ instance.setId(node.id());
+
+ foreach (const VariantProperty &property, node.variantProperties()) {
+ if (property.isDynamic())
+ instance.setPropertyDynamicVariant(property.name(), property.dynamicTypeName(), property.value());
+ else
+ instance.setPropertyVariant(property.name(), property.value());
+ }
+
+ return instance;
+}
+
+NodeInstance NodeInstance::create(NodeInstanceView *nodeInstanceView, const NodeMetaInfo &metaInfo, QmlContext *context)
+{
+ NodeInstance instance(createInstance(metaInfo, context, 0));
+ instance.m_nodeInstance->setNodeInstance(nodeInstanceView);
+
+ return instance;
+}
+
+/*!
+\brief Returns the ModelNode of this NodeInstance.
+\returns ModelNode of this NodeState
+*/
+ModelNode NodeInstance::modelNode() const
+{
+ if (m_nodeInstance.isNull())
+ return ModelNode();
+
+ return m_nodeInstance->modelNode();
+}
+
+
+/*!
+\brief Changes the NodeState of the ModelNode of this NodeInstance.
+ All properties are updated.
+\param state NodeState of this NodeInstance
+*/
+void NodeInstance::setModelNode(const ModelNode &node)
+{
+ Q_ASSERT(node.isValid());
+ if (m_nodeInstance->modelNode() == node)
+ return;
+
+ m_nodeInstance->setModelNode(node);
+}
+
+/*!
+\brief Returns if the NodeInstance is a top level item.
+\returns true if this NodeInstance is a top level item
+*/
+bool NodeInstance::isTopLevel() const
+{
+ return m_nodeInstance->isTopLevel();
+}
+
+void NodeInstance::reparent(const NodeInstance &oldParentInstance, const QString &oldParentProperty, const NodeInstance &newParentInstance, const QString &newParentProperty)
+{
+ m_nodeInstance->reparent(oldParentInstance, oldParentProperty, newParentInstance, newParentProperty);
+}
+
+
+/*!
+\brief Returns the parent NodeInstance of this NodeInstance.
+
+ If there is not parent than the parent is invalid.
+
+\returns Parent NodeInstance.
+*/
+NodeInstance NodeInstance::parent() const
+{
+ return m_nodeInstance->nodeInstanceView()->instanceForObject(m_nodeInstance->parent());
+}
+
+bool NodeInstance::hasParent() const
+{
+ return m_nodeInstance->object()->parent();
+}
+
+/*!
+\brief Returns if the NodeInstance is a QmlGraphicsItem.
+\returns true if this NodeInstance is a QmlGraphicsItem
+*/
+bool NodeInstance::isQmlGraphicsItem() const
+{
+ return m_nodeInstance->isQmlGraphicsItem();
+}
+
+/*!
+\brief Returns if the NodeInstance is a QGraphicsScene.
+\returns true if this NodeInstance is a QGraphicsScene
+*/
+bool NodeInstance::isGraphicsScene() const
+{
+ return m_nodeInstance->isGraphicsScene();
+}
+
+/*!
+\brief Returns if the NodeInstance is a QGraphicsView.
+\returns true if this NodeInstance is a QGraphicsView
+*/
+bool NodeInstance::isGraphicsView() const
+{
+ return m_nodeInstance->isGraphicsView();
+}
+
+/*!
+\brief Returns if the NodeInstance is a QGraphicsWidget.
+\returns true if this NodeInstance is a QGraphicsWidget
+*/
+bool NodeInstance::isGraphicsWidget() const
+{
+ return m_nodeInstance->isGraphicsWidget();
+}
+
+/*!
+\brief Returns if the NodeInstance is a QGraphicsProxyWidget.
+\returns true if this NodeInstance is a QGraphicsProxyWidget
+*/
+bool NodeInstance::isProxyWidget() const
+{
+ return m_nodeInstance->isProxyWidget();
+}
+
+/*!
+\brief Returns if the NodeInstance is a QWidget.
+\returns true if this NodeInstance is a QWidget
+*/
+bool NodeInstance::isWidget() const
+{
+ return m_nodeInstance->isWidget();
+}
+
+/*!
+\brief Returns if the NodeInstance is a QmlView.
+\returns true if this NodeInstance is a QmlView
+*/
+bool NodeInstance::isQmlView() const
+{
+ return m_nodeInstance->isQmlView();
+}
+
+bool NodeInstance::isGraphicsObject() const
+{
+ return m_nodeInstance->isGraphicsObject();
+}
+
+bool NodeInstance::isTransition() const
+{
+ return m_nodeInstance->isTransition();
+}
+
+/*!
+\brief Returns if the NodeInstance is a QGraphicsItem.
+\returns true if this NodeInstance is a QGraphicsItem
+*/
+bool NodeInstance::equalGraphicsItem(QGraphicsItem *item) const
+{
+ return m_nodeInstance->equalGraphicsItem(item);
+}
+
+/*!
+\brief Returns the bounding rect of the NodeInstance.
+\returns QRectF of the NodeInstance
+*/
+QRectF NodeInstance::boundingRect() const
+{
+ QRectF boundingRect(m_nodeInstance->boundingRect());
+
+//
+// if (modelNode().isValid()) { // TODO implement recursiv stuff
+// if (qFuzzyIsNull(boundingRect.width()))
+// boundingRect.setWidth(nodeState().property("width").value().toDouble());
+//
+// if (qFuzzyIsNull(boundingRect.height()))
+// boundingRect.setHeight(nodeState().property("height").value().toDouble());
+// }
+
+ return boundingRect;
+}
+
+void NodeInstance::setPropertyVariant(const QString &name, const QVariant &value)
+{
+ m_nodeInstance->setPropertyVariant(name, value);
+}
+
+void NodeInstance::setPropertyDynamicVariant(const QString &/*name*/, const QString &/*typeName*/, const QVariant &/*value*/)
+{
+// m_nodeInstance->createDynamicProperty(name, typeName);
+// m_nodeInstance->setPropertyVariant(name, value);
+}
+
+void NodeInstance::setPropertyBinding(const QString &name, const QString &expression)
+{
+ m_nodeInstance->setPropertyBinding(name, expression);
+}
+
+void NodeInstance::setPropertyDynamicBinding(const QString &/*name*/, const QString &/*typeName*/, const QString &/*expression*/)
+{
+// m_nodeInstance->createDynamicProperty(name, typeName);
+// m_nodeInstance->setPropertyBinding(name, value);
+}
+
+void NodeInstance::resetProperty(const QString &name)
+{
+ m_nodeInstance->resetProperty(name);
+}
+
+void NodeInstance::setId(const QString &id)
+{
+ m_nodeInstance->setId(id);
+}
+
+/*!
+\brief Returns the property value of the property of this NodeInstance.
+\returns QVariant value
+*/
+QVariant NodeInstance::property(const QString &name) const
+{
+ return m_nodeInstance->property(name);
+}
+
+/*!
+\brief Returns the property default value of the property of this NodeInstance.
+\returns QVariant default value which is the reset value to
+*/
+QVariant NodeInstance::defaultValue(const QString &name) const
+{
+ return m_nodeInstance->resetValue(name);
+}
+
+/*!
+\brief Returns if the NodeInstance is visible.
+\returns true if the NodeInstance is visible
+*/
+bool NodeInstance::isVisible() const
+{
+ return m_nodeInstance->isVisible();
+}
+
+void NodeInstance::show()
+{
+ m_nodeInstance->setVisible(true);
+}
+void NodeInstance::hide()
+{
+ m_nodeInstance->setVisible(false);
+}
+
+/*!
+\brief Returns if the NodeInstance is valid.
+\returns true if the NodeInstance is valid
+*/
+bool NodeInstance::isValid() const
+{
+ return m_nodeInstance && internalObject();
+}
+
+void NodeInstance::makeInvalid()
+{
+ if (m_nodeInstance)
+ m_nodeInstance->destroy();
+ m_nodeInstance.clear();
+}
+
+bool NodeInstance::hasContent() const
+{
+ return m_nodeInstance->hasContent();
+}
+
+bool NodeInstance::hasAnchor(const QString &name) const
+{
+ return m_nodeInstance->hasAnchor(name);
+}
+
+bool NodeInstance::isAnchoredBy() const
+{
+ return m_nodeInstance->isAnchoredBy();
+}
+
+QPair<QString, NodeInstance> NodeInstance::anchor(const QString &name) const
+{
+ return m_nodeInstance->anchor(name);
+}
+
+uint qHash(const NodeInstance &instance)
+{
+ return ::qHash(instance.m_nodeInstance.data());
+}
+
+bool operator==(const NodeInstance &first, const NodeInstance &second)
+{
+ return first.m_nodeInstance.data() == second.m_nodeInstance.data();
+}
+
+const QObject *NodeInstance::testHandle() const
+{
+ return internalObject();
+}
+
+/*!
+\brief Returns the position in parent coordiantes.
+\returns QPointF of the position of the instance.
+*/
+QPointF NodeInstance::position() const
+{
+ return m_nodeInstance->position();
+}
+
+/*!
+\brief Returns the size in local coordiantes.
+\returns QSizeF of the size of the instance.
+*/
+QSizeF NodeInstance::size() const
+{
+ QSizeF instanceSize = m_nodeInstance->size();
+
+// if (nodeState().isValid()) {
+// if (qFuzzyIsNull(instanceSize.width()))
+// instanceSize.setWidth(nodeState().property("width").value().toDouble());
+//
+// if (qFuzzyIsNull(instanceSize.height()))
+// instanceSize.setHeight(nodeState().property("height").value().toDouble());
+// }
+ return instanceSize;
+}
+
+QTransform NodeInstance::transform() const
+{
+ return m_nodeInstance->transform();
+}
+
+/*!
+\brief Returns the transform matrix of the instance.
+\returns QTransform of the instance.
+*/
+QTransform NodeInstance::customTransform() const
+{
+ return m_nodeInstance->customTransform();
+}
+
+QTransform NodeInstance::sceneTransform() const
+{
+ return m_nodeInstance->sceneTransform();
+}
+
+double NodeInstance::rotation() const
+{
+ return m_nodeInstance->rotation();
+}
+
+double NodeInstance::scale() const
+{
+ return m_nodeInstance->scale();
+}
+
+QList<QGraphicsTransform *> NodeInstance::transformations() const
+{
+ return m_nodeInstance->transformations();
+}
+
+QPointF NodeInstance::transformOriginPoint() const
+{
+ return m_nodeInstance->transformOriginPoint();
+}
+
+double NodeInstance::zValue() const
+{
+ return m_nodeInstance->zValue();
+}
+
+/*!
+\brief Returns the opacity of the instance.
+\returns 0.0 mean transparent and 1.0 opaque.
+*/
+double NodeInstance::opacity() const
+{
+ return m_nodeInstance->opacity();
+}
+
+
+void NodeInstance::setDeleteHeldInstance(bool deleteInstance)
+{
+ m_nodeInstance->setDeleteHeldInstance(deleteInstance);
+}
+
+
+void NodeInstance::paintUpdate()
+{
+ m_nodeInstance->paintUpdate();
+}
+
+
+Internal::QmlGraphicsItemNodeInstance::Pointer NodeInstance::qmlGraphicsItemNodeInstance() const
+{
+ return m_nodeInstance.dynamicCast<Internal::QmlGraphicsItemNodeInstance>();
+}
+
+QObject *NodeInstance::internalObject() const
+{
+ if (m_nodeInstance.isNull())
+ return 0;
+
+ return m_nodeInstance->object();
+}
+
+}
diff --git a/src/plugins/qmldesigner/core/instances/nodeinstanceview.cpp b/src/plugins/qmldesigner/core/instances/nodeinstanceview.cpp
new file mode 100644
index 0000000000..8e75d82160
--- /dev/null
+++ b/src/plugins/qmldesigner/core/instances/nodeinstanceview.cpp
@@ -0,0 +1,610 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "nodeinstanceview.h"
+
+#include <QtDeclarative/QmlEngine>
+#include <QtDeclarative/QmlContext>
+
+#include <QtDebug>
+#include <QUrl>
+#include <QGraphicsView>
+#include <QGraphicsScene>
+#include <QGraphicsObject>
+
+#include <model.h>
+#include <modelnode.h>
+#include <propertymetainfo.h>
+#include <metainfo.h>
+#include <nodeinstance.h>
+
+#include <typeinfo>
+#include <iwidgetplugin.h>
+
+#include "abstractproperty.h"
+#include "variantproperty.h"
+#include "bindingproperty.h"
+#include "nodeabstractproperty.h"
+#include "nodelistproperty.h"
+
+#include "objectnodeinstance.h"
+
+enum {
+ debug = false
+};
+
+/*!
+\defgroup CoreInstance
+*/
+/*!
+\class QmlDesigner::NodeInstanceView
+\ingroup CoreInstance
+\brief Central class to create and manage instances of a ModelNode.
+
+This view is used to instance the ModelNodes. Many AbstractViews hold a
+NodeInstanceView to get values from tghe NodeInstances back.
+For this purpose this view can be rendered offscreen.
+
+\see NodeInstance ModelNode
+*/
+
+namespace QmlDesigner {
+
+/*! \brief Constructor
+
+ The class will be rendered offscreen if not setted otherwise.
+
+\param Parent of this object. If this parent is deleted this instance is
+deleted too.
+
+\see ~NodeInstanceView setRenderOffScreen
+*/
+NodeInstanceView::NodeInstanceView(QObject *parent)
+ : AbstractView(parent),
+ m_graphicsView(new QGraphicsView),
+ m_engine(new QmlEngine(this)),
+ m_blockChangeSignal(false)
+{
+ m_graphicsView->setAttribute(Qt::WA_DontShowOnScreen, true);
+ m_graphicsView->setViewportUpdateMode(QGraphicsView::NoViewportUpdate);
+ m_graphicsView->setScene(new QGraphicsScene(m_graphicsView.data()));
+}
+
+
+/*! \brief Destructor
+
+*/
+NodeInstanceView::~NodeInstanceView()
+{
+ removeAllInstanceNodeRelationships();
+}
+
+/*! \name Overloaded Notifiers
+ * This methodes notify the view that something has happen in the model
+ */
+//\{
+/*! \brief Notifing the view that it was attached to a model.
+
+ For every ModelNode in the model a NodeInstance will be created.
+\param model Model to which the view is attached
+*/
+void NodeInstanceView::modelAttached(Model *model)
+{
+ AbstractView::modelAttached(model);
+ engine()->setBaseUrl(model->fileUrl());
+ loadModel(model);
+}
+
+void NodeInstanceView::modelAboutToBeDetached(Model * model)
+{
+ removeAllInstanceNodeRelationships();
+ AbstractView::modelAboutToBeDetached(model);
+}
+
+
+/*! \brief Notifing the view that a node was created.
+ A NodeInstance will be created for the new created ModelNode.
+\param createdNode New created ModelNode.
+*/
+void NodeInstanceView::nodeCreated(const ModelNode &createdNode)
+{
+ NodeInstance instance(loadNode(createdNode));
+ instance.show();
+}
+
+/*! \brief Notifing the view that a node was created.
+\param removedNode
+*/
+void NodeInstanceView::nodeAboutToBeRemoved(const ModelNode &removedNode)
+{
+ removeInstanceAndSubInstances(removedNode);
+}
+
+void NodeInstanceView::nodeRemoved(const ModelNode &/*removedNode*/, const NodeAbstractProperty &/*parentProperty*/, PropertyChangeFlags /*propertyChange*/)
+{
+
+}
+
+/*! \brief Notifing the view that a AbstractProperty was added to a ModelNode.
+
+ The property will be setted for the NodeInstance.
+
+\param state ModelNode to wich the Property belongs
+\param property AbstractProperty which was added
+\see AbstractProperty NodeInstance ModelNode
+*/
+
+void NodeInstanceView::propertiesAboutToBeRemoved(const QList<AbstractProperty>& propertyList)
+{
+ foreach (const AbstractProperty &property, propertyList) {
+ if (hasInstanceForNode(property.parentModelNode())) { // TODO ugly workaround
+ NodeInstance instance = instanceForNode(property.parentModelNode());
+ instance.resetProperty(property.name());
+ }
+
+ if (property.isNodeAbstractProperty()) {
+ foreach (const ModelNode &subNode, property.toNodeAbstractProperty().allSubNodes())
+ removeInstanceNodeRelationship(subNode);
+ }
+ }
+}
+
+void NodeInstanceView::propertiesRemoved(const QList<AbstractProperty>& /*propertyList*/)
+{
+}
+
+void NodeInstanceView::removeInstanceAndSubInstances(const ModelNode &node)
+{
+ if (hasInstanceForNode(node))
+ removeInstanceNodeRelationship(node);
+
+ foreach(const ModelNode &subNode, node.allSubModelNodes()) {
+ if (hasInstanceForNode(subNode))
+ removeInstanceNodeRelationship(subNode);
+ }
+}
+
+void NodeInstanceView::nodeTypeChanged(const ModelNode &node, const QString &/*type*/, int /*majorVersion*/, int /*minorVersion*/)
+{
+ removeInstanceAndSubInstances(node);
+
+ QList<ModelNode> nodeList;
+
+ nodeList.append(node.allSubModelNodes());
+ nodeList.append(node);
+
+ loadNodes(nodeList);
+}
+
+void NodeInstanceView::bindingPropertiesChanged(const QList<BindingProperty>& propertyList, PropertyChangeFlags /*propertyChange*/)
+{
+ foreach (const BindingProperty &property, propertyList) {
+ NodeInstance instance = instanceForNode(property.parentModelNode());
+
+ if (property.isDynamic())
+ instance.setPropertyDynamicBinding(property.name(), property.dynamicTypeName(), property.expression());
+ else
+ instance.setPropertyBinding(property.name(), property.expression());
+
+ if (property.parentModelNode().isRootNode()
+ && (property.name() == "width" || property.name() == "height")) {
+ QGraphicsObject *rootGraphicsObject = qobject_cast<QGraphicsObject*>(instance.internalObject());
+ m_graphicsView->setSceneRect(rootGraphicsObject->boundingRect());
+ }
+
+ instance.paintUpdate();
+ }
+}
+
+/*! \brief Notifing the view that a AbstractProperty value was changed to a ModelNode.
+
+ The property will be setted for the NodeInstance.
+
+\param state ModelNode to wich the Property belongs
+\param property AbstractProperty which was changed
+\param newValue New Value of the property
+\param oldValue Old Value of the property
+\see AbstractProperty NodeInstance ModelNode
+*/
+
+void NodeInstanceView::variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags /*propertyChange*/)
+{
+ foreach (const VariantProperty &property, propertyList) {
+ NodeInstance instance = instanceForNode(property.parentModelNode());
+
+ if (property.isDynamic())
+ instance.setPropertyDynamicVariant(property.name(), property.dynamicTypeName(), property.value());
+ else
+ instance.setPropertyVariant(property.name(), property.value());
+
+ if (property.parentModelNode().isRootNode()
+ && (property.name() == "width" || property.name() == "height")) {
+ QGraphicsObject *rootGraphicsObject = qobject_cast<QGraphicsObject*>(instance.internalObject());
+ if (rootGraphicsObject) {
+ m_graphicsView->setSceneRect(rootGraphicsObject->boundingRect());
+ }
+ }
+
+ instance.paintUpdate();
+ }
+}
+/*! \brief Notifing the view that a ModelNode has a new Parent.
+
+ Note that also the ModelNode::childNodes() list was changed. The
+ NodeInstance tree will be changed to reflect the ModelNode tree change.
+
+\param node ModelNode which parent was changed.
+\param oldParent Old parent of the node.
+\param newParent New parent of the node.
+
+\see NodeInstance ModelNode
+*/
+
+void NodeInstanceView::nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags /*propertyChange*/)
+{
+ NodeInstance nodeInstance(instanceForNode(node));
+ NodeInstance oldParentInstance;
+ if (hasInstanceForNode(oldPropertyParent.parentModelNode()))
+ oldParentInstance = instanceForNode(oldPropertyParent.parentModelNode());
+ NodeInstance newParentInstance;
+ if (hasInstanceForNode(newPropertyParent.parentModelNode()))
+ newParentInstance = instanceForNode(newPropertyParent.parentModelNode());
+ nodeInstance.reparent(oldParentInstance, oldPropertyParent.name(), newParentInstance, newPropertyParent.name());
+}
+
+void NodeInstanceView::fileUrlChanged(const QUrl &/*oldUrl*/, const QUrl &/*newUrl*/)
+{
+ // TODO: We have to probably reload everything, so that images etc are updated!!!
+ engine()->setBaseUrl(model()->fileUrl());
+}
+
+void NodeInstanceView::nodeIdChanged(const ModelNode& node, const QString& newId, const QString& /*oldId*/)
+{
+ if (hasInstanceForNode(node)) {
+ NodeInstance instance = instanceForNode(node);
+
+ instance.setId(newId);
+ }
+}
+
+void NodeInstanceView::nodeSlidedToIndex(const NodeListProperty &listProperty, int /*newIndex*/, int /*oldIndex*/)
+{
+ QList<ModelNode> newOrderModelNodeList = listProperty.toModelNodeList();
+ foreach(const ModelNode &node, newOrderModelNodeList) {
+ NodeInstance instance = instanceForNode(node);
+ instance.reparent(instance.parent(), listProperty.name(), instance.parent(), listProperty.name());
+ }
+}
+
+/*! \brief Notifing the view that the selection has been changed.
+
+ Do nothing.
+
+\param selectedNodeList List of ModelNode which has been selected
+\param lastSelectedNodeList List of ModelNode which was selected
+
+\see ModelNode NodeInstance
+*/
+void NodeInstanceView::selectedNodesChanged(const QList<ModelNode> &/*selectedNodeList*/,
+ const QList<ModelNode> &/*lastSelectedNodeList*/)
+{
+}
+
+
+//\}
+
+void NodeInstanceView::loadNodes(const QList<ModelNode> &nodeList)
+{
+ foreach (const ModelNode &node, nodeList)
+ loadNode(node);
+
+ foreach (const ModelNode &node, nodeList) {
+ if (node.hasParentProperty())
+ instanceForNode(node).reparent(NodeInstance(), QString(), instanceForNode(node.parentProperty().parentModelNode()), node.parentProperty().name());
+ }
+
+ foreach (const ModelNode &node, nodeList) {
+ foreach (const BindingProperty &property, node.bindingProperties())
+ instanceForNode(node).setPropertyBinding(property.name(), property.expression());
+ }
+}
+
+// TODO: Set base state as current model state
+void NodeInstanceView::loadModel(Model *model)
+{
+ Q_ASSERT(rootModelNode().isValid());
+
+ removeAllInstanceNodeRelationships();
+
+ engine()->rootContext()->setBaseUrl(model->fileUrl());
+
+ loadNodes(allModelNodes());
+}
+
+void NodeInstanceView::removeAllInstanceNodeRelationships()
+{
+ // prevent destroyed() signals calling back
+
+ //first delete the root object
+ if (rootNodeInstance().internalObject())
+ rootNodeInstance().internalObject()->disconnect();
+
+ rootNodeInstance().makeInvalid();
+
+
+ foreach (NodeInstance instance, m_objectInstanceHash.values()) {
+ if (instance.internalObject())
+ instance.internalObject()->disconnect();
+ instance.makeInvalid();
+ }
+
+ m_nodeInstanceHash.clear();
+ m_objectInstanceHash.clear();
+}
+
+/*! \brief Returns a List of all NodeInstances
+
+\see NodeInstance
+*/
+
+QList<NodeInstance> NodeInstanceView::instances() const
+{
+ return m_nodeInstanceHash.values();
+}
+
+/*! \brief Returns the NodeInstance for this ModelNode
+
+ Returns a invalid NodeInstance if no NodeInstance for this ModelNode exists.
+
+\param node ModelNode must be valid.
+\returns NodeStance for ModelNode.
+\see NodeInstance
+*/
+NodeInstance NodeInstanceView::instanceForNode(const ModelNode &node)
+{
+ Q_ASSERT(node.isValid());
+ Q_ASSERT(m_nodeInstanceHash.contains(node));
+ Q_ASSERT(m_nodeInstanceHash.value(node).modelNode() == node);
+ return m_nodeInstanceHash.value(node);
+}
+
+bool NodeInstanceView::hasInstanceForNode(const ModelNode &node)
+{
+ return m_nodeInstanceHash.contains(node);
+}
+
+NodeInstance NodeInstanceView::instanceForObject(QObject *object)
+{
+ if (object == 0)
+ return NodeInstance();
+
+ return m_objectInstanceHash.value(object);
+}
+
+bool NodeInstanceView::hasInstanceForObject(QObject *object)
+{
+ if (object == 0)
+ return false;
+
+ return m_objectInstanceHash.contains(object);
+}
+
+
+/*! \brief Returns the root NodeInstance of this view.
+
+
+\returns Root NodeIntance for this view.
+\see NodeInstance
+*/
+NodeInstance NodeInstanceView::rootNodeInstance() const
+{
+ return m_rootNodeInstance;
+}
+
+/*! \brief Returns the view NodeInstance of this view.
+
+ This can be the root NodeInstance if it is specified in the qml file.
+\code
+ QGraphicsView {
+ QGraphicsScene {
+ Item {}
+ }
+ }
+\endcode
+
+ If there is node view in the qml file:
+ \code
+
+ Item {}
+
+\endcode
+ Than there will be a new NodeInstance for this QGraphicsView
+ generated which is not the root instance of this NodeInstanceView.
+
+ This is the way to get this QGraphicsView NodeInstance.
+
+\returns Root NodeIntance for this view.
+\see NodeInstance
+*/
+
+static bool isTransformProperty(const QString &name)
+{
+ static QStringList transformProperties(QStringList() << "xChanged()" << "yChanged()" << "zChanged()" << "rotationChanged()" << "scaleChanged()" << "widthChanged()" << "heightChanged()");
+
+ return transformProperties.contains(name);
+}
+
+void NodeInstanceView::insertInstanceNodeRelationship(const ModelNode &node, const NodeInstance &instance)
+{
+ // connect with every signal of the object to get the formeditor updated
+ int otherPropertuChangedSlotIndex = staticMetaObject.indexOfSlot("emitOtherPropertyChanged()");
+ int transformPropertuChangedSlotIndex = staticMetaObject.indexOfSlot("emitTransformPropertyChanged()");
+ int parentPropertuChangedSlotIndex = staticMetaObject.indexOfSlot("emitParentPropertyChanged()");
+ for (int index = QObject::staticMetaObject.methodCount();
+ index < instance.internalObject()->metaObject()->methodCount();
+ index++) {
+ QMetaMethod metaMethod = instance.internalObject()->metaObject()->method(index);
+ if (metaMethod.methodType() == QMetaMethod::Signal) {
+ if (isTransformProperty(metaMethod.signature())) {
+ staticMetaObject.connect(instance.internalObject(),index, this, transformPropertuChangedSlotIndex);
+ } else if (QByteArray(metaMethod.signature()) == QByteArray("parentChanged()")) {
+ staticMetaObject.connect(instance.internalObject(),index, this, parentPropertuChangedSlotIndex);
+ } else {
+ staticMetaObject.connect(instance.internalObject(),index, this, otherPropertuChangedSlotIndex);
+ }
+ }
+ }
+
+ instance.internalObject()->installEventFilter(childrenChangeEventFilter());
+
+ Q_ASSERT(!m_nodeInstanceHash.contains(node));
+ m_nodeInstanceHash.insert(node, instance);
+ m_objectInstanceHash.insert(instance.internalObject(), instance);
+}
+
+QmlEngine *NodeInstanceView::engine() const
+{
+ return m_engine.data();
+}
+
+Internal::ChildrenChangeEventFilter *NodeInstanceView::childrenChangeEventFilter()
+{
+ if (m_childrenChangeEventFilter.isNull()) {
+ m_childrenChangeEventFilter = new Internal::ChildrenChangeEventFilter(this);
+ connect(m_childrenChangeEventFilter.data(), SIGNAL(childrenChanged(QObject*)), this, SLOT(emitUpdateItem(QObject*)));
+ }
+
+ return m_childrenChangeEventFilter.data();
+}
+
+void NodeInstanceView::removeInstanceNodeRelationship(const ModelNode &node)
+{
+ Q_ASSERT(m_nodeInstanceHash.contains(node));
+ NodeInstance instance = instanceForNode(node);
+ m_objectInstanceHash.remove(instanceForNode(node).internalObject());
+ m_nodeInstanceHash.remove(node);
+ emit instanceRemoved(instance);
+ instance.makeInvalid();
+}
+
+void NodeInstanceView::emitOtherPropertyChanged()
+{
+ if (m_blockChangeSignal)
+ return;
+ if (hasInstanceForObject(sender()))
+ emit otherPropertyChanged(instanceForObject(sender()));
+}
+
+void NodeInstanceView::emitParentPropertyChanged()
+{
+ if (m_blockChangeSignal)
+ return;
+ if (hasInstanceForObject(sender()))
+ emit parentPropertyChanged(instanceForObject(sender()));
+}
+
+void NodeInstanceView::emitTransformPropertyChanged()
+{
+ if (m_blockChangeSignal)
+ return;
+ if (hasInstanceForObject(sender()))
+ emit transformPropertyChanged(instanceForObject(sender()));
+}
+
+void NodeInstanceView::emitUpdateItem(QObject *object)
+{
+ if (m_blockChangeSignal)
+ return;
+ if (hasInstanceForObject(object))
+ emit updateItem(instanceForObject(object));
+}
+
+
+NodeInstance NodeInstanceView::loadNode(const ModelNode &node, QObject *objectToBeWrapped)
+{
+ Q_ASSERT(node.isValid());
+ NodeInstance instance(NodeInstance::create(this, node, objectToBeWrapped));
+
+ insertInstanceNodeRelationship(node, instance);
+
+ if (node.isRootNode()) {
+ m_rootNodeInstance = instance;
+ QGraphicsObject *rootGraphicsObject = qobject_cast<QGraphicsObject*>(instance.internalObject());
+ if (rootGraphicsObject) {
+ m_graphicsView->scene()->addItem(rootGraphicsObject);
+ m_graphicsView->setSceneRect(rootGraphicsObject->boundingRect());
+ }
+ }
+
+ return instance;
+}
+
+void NodeInstanceView::removeRecursiveChildRelationship(const ModelNode &removedNode)
+{
+ foreach (const ModelNode &childNode, removedNode.allDirectSubModelNodes())
+ removeRecursiveChildRelationship(childNode);
+
+ removeInstanceNodeRelationship(removedNode);
+}
+
+void NodeInstanceView::render(QPainter * painter, const QRectF &target, const QRectF &source, Qt::AspectRatioMode aspectRatioMode)
+{
+ if (m_graphicsView) {
+ painter->save();
+ painter->setRenderHint(QPainter::Antialiasing, true);
+ painter->setRenderHint(QPainter::TextAntialiasing, true);
+ painter->setRenderHint(QPainter::SmoothPixmapTransform, true);
+ painter->setRenderHint(QPainter::HighQualityAntialiasing, true);
+ painter->setRenderHint(QPainter::NonCosmeticDefaultPen, true);
+ m_graphicsView->scene()->render(painter, target, source, aspectRatioMode);
+ painter->restore();
+ }
+}
+
+QRectF NodeInstanceView::boundingRect() const
+{
+ if (m_graphicsView)
+ return m_graphicsView->scene()->itemsBoundingRect();
+
+ return QRectF();
+}
+QRectF NodeInstanceView::sceneRect() const
+{
+ if (m_graphicsView)
+ return m_graphicsView->sceneRect();
+
+ return QRectF();
+}
+
+void NodeInstanceView::setBlockChangeSignal(bool block)
+{
+ m_blockChangeSignal = block;
+}
+
+}
diff --git a/src/plugins/qmldesigner/core/instances/objectnodeinstance.cpp b/src/plugins/qmldesigner/core/instances/objectnodeinstance.cpp
new file mode 100644
index 0000000000..6ebcc111da
--- /dev/null
+++ b/src/plugins/qmldesigner/core/instances/objectnodeinstance.cpp
@@ -0,0 +1,690 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "objectnodeinstance.h"
+
+#include <invalidreparentingexception.h>
+#include <invalidnodeinstanceexception.h>
+#include <notimplementedexception.h>
+#include <noanchoringpossibleexception.h>
+
+#include <QmlContext>
+#include <QtDeclarative/private/qmlcontext_p.h>
+#include <QmlList>
+#include <QmlBinding>
+#include <private/qmllistaccessor_p.h>
+
+#include <metainfo.h>
+#include <propertymetainfo.h>
+#include <qmlmetaproperty.h>
+#include <QmlMetaType>
+#include <QmlEngine>
+#include <private/qmlgraphicsanchors_p.h>
+#include <private/qmlgraphicsrectangle_p.h>
+
+#include "qmlgraphicsitemnodeinstance.h"
+#include "graphicsobjectnodeinstance.h"
+#include "graphicsviewnodeinstance.h"
+#include "graphicsscenenodeinstance.h"
+#include "graphicswidgetnodeinstance.h"
+#include "qmlviewnodeinstance.h"
+#include "widgetnodeinstance.h"
+#include "proxywidgetnodeinstance.h"
+#include "variantproperty.h"
+#include <nodelistproperty.h>
+
+namespace QmlDesigner {
+namespace Internal {
+
+ChildrenChangeEventFilter::ChildrenChangeEventFilter(QObject *parent)
+ : QObject(parent)
+{
+}
+
+
+bool ChildrenChangeEventFilter::eventFilter(QObject *object, QEvent *event)
+{
+ switch (event->type()) {
+ case QEvent::ChildAdded:
+ case QEvent::ChildRemoved: emit childrenChanged(object); break;
+ default: break;
+ }
+
+ return false;
+}
+
+ObjectNodeInstance::ObjectNodeInstance(QObject *object)
+ : m_deleteHeldInstance(true),
+ m_object(object)
+{
+}
+
+ObjectNodeInstance::~ObjectNodeInstance()
+{
+ destroy();
+}
+
+static bool isChildrenProperty(const QString &name)
+{
+ return name == "data" || name == "children" || name == "resources";
+}
+
+static void specialRemoveParentForQmlGraphicsItemChildren(QObject *object)
+{
+ QmlGraphicsItem *item = qobject_cast<QmlGraphicsItem*>(object);
+ if (item && item->scene())
+ item->scene()->removeItem(item);
+
+ object->setParent(0);
+}
+
+void ObjectNodeInstance::destroy()
+{
+ // Remove from old property
+ if (object() && modelNode().isValid() && modelNode().parentProperty().isValid()) {
+ NodeAbstractProperty parentProperty = modelNode().parentProperty();
+ ModelNode parentNode = parentProperty.parentModelNode();
+ if (parentNode.isValid() && nodeInstanceView()->hasInstanceForNode(parentNode)) {
+ NodeInstance parentInstance = nodeInstanceView()->instanceForNode(parentNode);
+ if (parentInstance.isQmlGraphicsItem() && isChildrenProperty(parentProperty.name())) {
+ specialRemoveParentForQmlGraphicsItemChildren(object());
+ } else {
+ removeFromOldProperty(object(), parentInstance.internalObject(), parentProperty.name());
+ }
+ }
+ }
+
+ if (deleteHeldInstance() && object()) {
+ if (!object()->objectName().isEmpty()) {
+ context()->engine()->rootContext()->setContextProperty(object()->objectName(), 0);
+ }
+ QObject *obj = object();
+ m_object.clear();
+ delete obj;
+ }
+}
+
+ModelNode ObjectNodeInstance::modelNode() const
+{
+ return m_modelNode;
+}
+
+void ObjectNodeInstance::setModelNode(const ModelNode &node)
+{
+ m_modelNode = node;
+}
+
+NodeInstanceView *ObjectNodeInstance::nodeInstanceView() const
+{
+ return m_nodeInstanceView.data();
+}
+
+void ObjectNodeInstance::setNodeInstance(NodeInstanceView *view)
+{
+ m_nodeInstanceView = view;
+}
+
+void ObjectNodeInstance::setId(const QString &id)
+{
+ object()->setObjectName(id);
+
+ if (!id.isEmpty()) {
+ context()->engine()->rootContext()->setContextProperty(id, object()); // will also force refresh of all bindings
+ } else {
+ context()->engine()->rootContext()->setContextProperty(id, 0);
+ }
+}
+
+bool ObjectNodeInstance::isQmlGraphicsItem() const
+{
+ return false;
+}
+
+bool ObjectNodeInstance::isGraphicsScene() const
+{
+ return false;
+}
+
+bool ObjectNodeInstance::isGraphicsView() const
+{
+ return false;
+}
+
+bool ObjectNodeInstance::isGraphicsWidget() const
+{
+ return false;
+}
+
+bool ObjectNodeInstance::isProxyWidget() const
+{
+ return false;
+}
+
+bool ObjectNodeInstance::isWidget() const
+{
+ return false;
+}
+
+bool ObjectNodeInstance::isQmlView() const
+{
+ return false;
+}
+
+bool ObjectNodeInstance::isGraphicsObject() const
+{
+ return false;
+}
+
+bool ObjectNodeInstance::isTransition() const
+{
+ return false;
+}
+
+bool ObjectNodeInstance::equalGraphicsItem(QGraphicsItem * /*item*/) const
+{
+ return false;
+}
+
+QTransform ObjectNodeInstance::transform() const
+{
+ return QTransform();
+}
+
+QTransform ObjectNodeInstance::customTransform() const
+{
+ return QTransform();
+}
+
+QTransform ObjectNodeInstance::sceneTransform() const
+{
+ return QTransform();
+}
+
+double ObjectNodeInstance::rotation() const
+{
+ return 0.0;
+}
+
+double ObjectNodeInstance::scale() const
+{
+ return 1.0;
+}
+
+QList<QGraphicsTransform *> ObjectNodeInstance::transformations() const
+{
+ QList<QGraphicsTransform *> transformationsList;
+
+ return transformationsList;
+}
+
+QPointF ObjectNodeInstance::transformOriginPoint() const
+{
+ return QPoint();
+}
+
+double ObjectNodeInstance::zValue() const
+{
+ return 0.0;
+}
+
+double ObjectNodeInstance::opacity() const
+{
+ return 1.0;
+}
+
+bool ObjectNodeInstance::hasAnchor(const QString &/*name*/) const
+{
+ return false;
+}
+
+bool ObjectNodeInstance::isAnchoredBy() const
+{
+ return false;
+}
+
+QPair<QString, NodeInstance> ObjectNodeInstance::anchor(const QString &/*name*/) const
+{
+ return qMakePair(QString(), NodeInstance());
+}
+
+
+static bool isList(const QmlMetaProperty &metaProperty)
+{
+ return metaProperty.propertyCategory() == QmlMetaProperty::List || metaProperty.propertyCategory() == QmlMetaProperty::QmlList;
+}
+
+static bool isObject(const QmlMetaProperty &metaProperty)
+{
+ return metaProperty.propertyCategory() == QmlMetaProperty::Object;
+}
+
+static QVariant objectToVariant(QObject *object)
+{
+ const QMetaObject *metaObject = object->metaObject();
+ QmlType *qmlType = QmlMetaType::qmlType(metaObject);
+
+ return qmlType->fromObject(object);
+}
+
+static void removeObjectFromList(const QmlMetaProperty &metaProperty, QObject *object, QmlEngine *engine)
+{
+ QmlListAccessor listAccessor;
+ listAccessor.setList(metaProperty.read(), engine);
+
+ for (int i = 0; i < listAccessor.count(); ++i) {
+ if (QmlMetaType::toQObject(listAccessor.at(i)) == object) {
+ listAccessor.removeAt(i);
+ break;
+ }
+ }
+}
+
+void ObjectNodeInstance::removeFromOldProperty(QObject *object, QObject *oldParent, const QString &oldParentProperty)
+{
+ QmlMetaProperty metaProperty = QmlMetaProperty::createProperty(oldParent, oldParentProperty, context());
+
+ if (isList(metaProperty)) {
+ removeObjectFromList(metaProperty, object, nodeInstanceView()->engine());
+ } else if (isObject(metaProperty)) {
+ resetProperty(object, oldParentProperty);
+ }
+
+ object->setParent(0);
+}
+
+void ObjectNodeInstance::addToNewProperty(QObject *object, QObject *newParent, const QString &newParentProperty)
+{
+ QmlMetaProperty metaProperty = QmlMetaProperty::createProperty(newParent, newParentProperty, context());
+
+ if (isList(metaProperty)) {
+ QmlListAccessor listAccessor;
+ listAccessor.setList(metaProperty.read(), nodeInstanceView()->engine());
+ listAccessor.append(objectToVariant(object));
+ } else if (isObject(metaProperty)) {
+ metaProperty.write(objectToVariant(object));
+ }
+ object->setParent(newParent);
+
+ Q_ASSERT(objectToVariant(object).isValid());
+}
+
+static void specialSetParentForQmlGraphicsItemChildren(QObject *object, QmlGraphicsItem *parent)
+{
+ QmlGraphicsItem *item = qobject_cast<QmlGraphicsItem*>(object);
+ if (item)
+ item->setParentItem(parent);
+ else
+ object->setParent(parent);
+}
+
+void ObjectNodeInstance::reparent(const NodeInstance &oldParentInstance, const QString &oldParentProperty, const NodeInstance &newParentInstance, const QString &newParentProperty)
+{
+ if (oldParentInstance.isValid()) {
+ if (oldParentInstance.isQmlGraphicsItem() && isChildrenProperty(oldParentProperty))
+ specialRemoveParentForQmlGraphicsItemChildren(object());
+ else
+ removeFromOldProperty(object(), oldParentInstance.internalObject(), oldParentProperty);
+ }
+
+ if (newParentInstance.isValid()) {
+ if (newParentInstance.isQmlGraphicsItem() && isChildrenProperty(newParentProperty))
+ specialSetParentForQmlGraphicsItemChildren(object(), qobject_cast<QmlGraphicsItem*>(newParentInstance.internalObject()));
+ else
+ addToNewProperty(object(), newParentInstance.internalObject(), newParentProperty);
+ }
+
+ refreshBindings(context()->engine()->rootContext());
+}
+
+void ObjectNodeInstance::setPropertyVariant(const QString &name, const QVariant &valueArg)
+{
+ QVariant value = valueArg;
+
+ QmlMetaProperty qmlMetaProperty = QmlMetaProperty::createProperty(object(), name, context());
+
+// if (qmlMetaProperty.propertyType() == QVariant::Url) {
+// QUrl url = value.toUrl();
+// if (url.isRelative()) {
+// QUrl baseUrl(nodeInstanceView()->model()->fileUrl());
+// value.setValue(baseUrl.resolved(url));
+// }
+// }
+
+ qmlMetaProperty.write(value);
+}
+
+void ObjectNodeInstance::setPropertyBinding(const QString &name, const QString &expression)
+{
+ QmlContext *qmlContext = QmlEngine::contextForObject(object());
+
+ QmlMetaProperty metaProperty = QmlMetaProperty::createProperty(object(), name, context());
+ if (metaProperty.isValid() && metaProperty.isProperty()) {
+ QmlBinding *qmlBinding = new QmlBinding(expression, object(), qmlContext);
+ qmlBinding->setTarget(metaProperty);
+ qmlBinding->setTrackChange(true);
+ QmlAbstractBinding *oldBinding = metaProperty.setBinding(qmlBinding);
+ delete oldBinding;
+ qmlBinding->update();
+ } else {
+ qWarning() << "Cannot set binding for property" << name << ": property is unknown for type"
+ << (modelNode().isValid() ? modelNode().type() : "unknown");
+ }
+}
+
+void ObjectNodeInstance::deleteObjectsInList(const QmlMetaProperty &metaProperty)
+{
+ QObjectList objectList;
+ QmlListAccessor listAccessor;
+ listAccessor.setList(metaProperty.read());
+
+ for(int i = 0; i < listAccessor.count(); i++) {
+ objectList += QmlMetaType::toQObject(listAccessor.at(i));
+ }
+
+ listAccessor.clear();
+}
+
+void ObjectNodeInstance::resetProperty(const QString &name)
+{
+ resetProperty(object(), name);
+
+ if (name == "font.pixelSize")
+ resetProperty(object(), "font.pointSize");
+
+ if (name == "font.pointSize")
+ resetProperty(object(), "font.pixelSize");
+}
+
+NodeInstance ObjectNodeInstance::instanceForNode(const ModelNode &node, const QString &fullname)
+{
+ if (nodeInstanceView()->hasInstanceForNode(node)) {
+ return nodeInstanceView()->instanceForNode(node);
+ } else {
+ NodeInstance instance(nodeInstanceView()->loadNode(node));
+ m_modelAbstractPropertyHash.insert(fullname, instance);
+ return instance;
+ }
+}
+
+void ObjectNodeInstance::resetProperty(QObject *object, const QString &propertyName)
+{
+ m_modelAbstractPropertyHash.remove(propertyName);
+
+ QmlMetaProperty qmlMetaProperty = QmlMetaProperty::createProperty(object, propertyName, context());
+ QMetaProperty metaProperty = qmlMetaProperty.property();
+
+ QmlAbstractBinding *binding = qmlMetaProperty.binding();
+ if (binding) {
+ binding->setEnabled(false, 0);
+ delete binding;
+ }
+
+ if (metaProperty.isResettable()) {
+ metaProperty.reset(object);
+ } else if (qmlMetaProperty.isWritable()) {
+ if (qmlMetaProperty.read() == resetValue(propertyName))
+ return;
+ qmlMetaProperty.write(resetValue(propertyName));
+ } else if (QmlMetaType::isList(qmlMetaProperty.propertyType()) ||
+ QmlMetaType::isQmlList(qmlMetaProperty.propertyType())) {
+ QmlMetaType::clear(object->property(propertyName.toLatin1()));
+ }
+}
+
+QVariant ObjectNodeInstance::property(const QString &name) const
+{
+ if (m_modelAbstractPropertyHash.contains(name))
+ return QVariant::fromValue(m_modelAbstractPropertyHash.value(name));
+
+
+ // TODO: handle model nodes
+
+ QmlMetaProperty metaProperty = QmlMetaProperty::createProperty(object(), name, context());
+ if (metaProperty.property().isEnumType()) {
+ QVariant value = object()->property(name.toLatin1());
+ return metaProperty.property().enumerator().valueToKey(value.toInt());
+ }
+
+ if (metaProperty.propertyType() == QVariant::Url) {
+ QUrl url = metaProperty.read().toUrl();
+ if (url.isEmpty())
+ return QVariant();
+
+ if (url.scheme() == "file") {
+ int basePathLength = nodeInstanceView()->model()->fileUrl().toLocalFile().lastIndexOf("/");
+ return QUrl(url.toLocalFile().mid(basePathLength + 1));
+ }
+ }
+
+ return metaProperty.read();
+}
+
+
+void ObjectNodeInstance::setDeleteHeldInstance(bool deleteInstance)
+{
+ m_deleteHeldInstance = deleteInstance;
+}
+
+bool ObjectNodeInstance::deleteHeldInstance() const
+{
+ return m_deleteHeldInstance;
+}
+
+ObjectNodeInstance::Pointer ObjectNodeInstance::create(const NodeMetaInfo &nodeMetaInfo, QmlContext *context, QObject *objectToBeWrapped)
+{
+ QObject *object = 0;
+ if (objectToBeWrapped)
+ object = objectToBeWrapped;
+ else
+ object = createObject(nodeMetaInfo, context);
+
+ Pointer instance(new ObjectNodeInstance(object));
+
+ if (objectToBeWrapped)
+ instance->setDeleteHeldInstance(false); // the object isn't owned
+
+ instance->populateResetValueHash();
+
+ return instance;
+}
+
+void ObjectNodeInstance::updateObjectSignals(QObject *object)
+{
+ // iterates over all properties and find the QObjects.
+ // connect all signal of this property objects to the visibleChanged signal of this object
+ // to get updates of this item
+ int visibleSignalIndex = QGraphicsObject::staticMetaObject.indexOfSignal("visibleChanged()");
+ int transformSignalIndex = QGraphicsObject::staticMetaObject.indexOfSignal("xChanged()");
+ // iterate over all proeprties and find the object
+ for(int propertyIndex = QObject::staticMetaObject.propertyCount(); propertyIndex < object->metaObject()->propertyCount(); propertyIndex++) {
+ if (QmlMetaType::isObject(object->metaObject()->property(propertyIndex).userType())) {
+ QObject *propertyObject = QmlMetaType::toQObject(object->metaObject()->property(propertyIndex).read(object));
+ if (propertyObject) {
+ int signalIndex = -1;
+ if (qobject_cast<QmlGraphicsAnchors*>(propertyObject)
+ || qobject_cast<QmlGraphicsPen*>(propertyObject)) // test if this is a anchor and use the tranform signal instead
+ signalIndex = transformSignalIndex;
+ else
+ signalIndex = visibleSignalIndex;
+
+ // connect with every signal of the object to get the formeditor updated
+
+ for (int methodIndex = QObject::staticMetaObject.methodCount();
+ methodIndex < propertyObject->metaObject()->methodCount();
+ methodIndex++) {
+ QMetaMethod metaMethod = propertyObject->metaObject()->method(methodIndex);
+ if (metaMethod.methodType() == QMetaMethod::Signal) {
+ QObject::staticMetaObject.connect(propertyObject, methodIndex, object, signalIndex);
+ }
+ }
+
+ }
+ }
+ }
+}
+
+QObject* ObjectNodeInstance::createObject(const NodeMetaInfo &metaInfo, QmlContext *context)
+{
+ QObject *object = metaInfo.createInstance(context);
+
+ if (object == 0)
+ throw InvalidNodeInstanceException(__LINE__, __FUNCTION__, __FILE__);
+
+ updateObjectSignals(object);
+
+ return object;
+}
+
+QObject *ObjectNodeInstance::object() const
+{
+ return m_object.data();
+}
+
+bool ObjectNodeInstance::hasContent() const
+{
+ return false;
+}
+
+void ObjectNodeInstance::updateAnchors()
+{
+}
+
+QmlContext *ObjectNodeInstance::context() const
+{
+ QmlContext *context = QmlEngine::contextForObject(object());
+ if (context)
+ return context;
+ else if (nodeInstanceView())
+ return nodeInstanceView()->engine()->rootContext();
+
+ return 0;
+}
+
+void ObjectNodeInstance::paintUpdate()
+{
+}
+
+QStringList propertyNameForWritableProperties(QObject *object, const QString &baseName = QString())
+{
+ QStringList propertyNameList;
+
+ const QMetaObject *metaObject = object->metaObject();
+ for (int index = 0; index < metaObject->propertyCount(); ++index) {
+ QMetaProperty metaProperty = metaObject->property(index);
+ if (metaProperty.isReadable() && !metaProperty.isWritable()) {
+ QObject *childObject = QmlMetaType::toQObject(metaProperty.read(object));
+ if (childObject)
+ propertyNameList.append(propertyNameForWritableProperties(childObject, baseName + QString::fromUtf8(metaProperty.name()) + "."));
+ } else if (QmlValueTypeFactory::valueType(metaProperty.userType())) {
+ QmlValueType *valueType = QmlValueTypeFactory::valueType(metaProperty.userType());
+ valueType->setValue(metaProperty.read(object));
+ propertyNameList.append(propertyNameForWritableProperties(valueType, baseName + QString::fromUtf8(metaProperty.name()) + "."));
+ } else if (metaProperty.isReadable() && metaProperty.isWritable()) {
+ propertyNameList.append(baseName + QString::fromUtf8(metaProperty.name()));
+ }
+ }
+
+ return propertyNameList;
+}
+
+void ObjectNodeInstance::populateResetValueHash()
+{
+ QStringList propertyNameList = propertyNameForWritableProperties(object());
+
+ foreach(const QString &propertyName, propertyNameList) {
+ QmlMetaProperty metaProperty = QmlMetaProperty::createProperty(object(), propertyName, context());
+ if (metaProperty.isWritable())
+ m_resetValueHash.insert(propertyName, metaProperty.read());
+ }
+}
+
+QVariant ObjectNodeInstance::resetValue(const QString &propertyName) const
+{
+ return m_resetValueHash.value(propertyName);
+}
+
+void ObjectNodeInstance::paint(QPainter * /*painter*/) const
+{
+}
+
+bool ObjectNodeInstance::isTopLevel() const
+{
+ return false;
+}
+
+QObject *ObjectNodeInstance::parent() const
+{
+ if (!object())
+ return 0;
+
+ return object()->parent();
+}
+
+QRectF ObjectNodeInstance::boundingRect() const
+{
+ return QRect();
+}
+
+QPointF ObjectNodeInstance::position() const
+{
+ return QPointF();
+}
+
+QSizeF ObjectNodeInstance::size() const
+{
+ return QSizeF();
+}
+
+bool ObjectNodeInstance::isVisible() const
+{
+ return false;
+}
+
+void ObjectNodeInstance::setVisible(bool /*isVisible*/)
+{
+}
+
+void ObjectNodeInstance::createDynamicProperty(const QString &/*name*/, const QString &/*typeName*/)
+{
+ //todo not implemented at all
+
+}
+
+/**
+ Force all bindings in this or a sub context to be re-evaluated.
+ */
+void ObjectNodeInstance::refreshBindings(QmlContext *context)
+{
+ // TODO: Maybe do this via a timer to prevent update flooding
+ QmlContextPrivate::get(context)->refreshExpressions();
+}
+
+}
+}
+
diff --git a/src/plugins/qmldesigner/core/instances/objectnodeinstance.h b/src/plugins/qmldesigner/core/instances/objectnodeinstance.h
new file mode 100644
index 0000000000..16b6af3a42
--- /dev/null
+++ b/src/plugins/qmldesigner/core/instances/objectnodeinstance.h
@@ -0,0 +1,185 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef ABSTRACTNODEINSTANCE_H
+#define ABSTRACTNODEINSTANCE_H
+
+#include <QPainter>
+#include <QStyleOptionGraphicsItem>
+#include "modelnode.h"
+#include <QSharedPointer>
+#include <QWeakPointer>
+#include <propertymetainfo.h>
+#include <nodeinstanceview.h>
+
+class QGraphicsItem;
+class QmlContext;
+class QmlMetaProperty;
+class QmlContext;
+class QmlBinding;
+
+namespace QmlDesigner {
+
+
+namespace Internal {
+
+class QmlGraphicsItemNodeInstance;
+class GraphicsWidgetNodeInstance;
+class GraphicsViewNodeInstance;
+class GraphicsSceneNodeInstance;
+class ProxyWidgetNodeInstance;
+class WidgetNodeInstance;
+class QmlViewNodeInstance;
+
+class ChildrenChangeEventFilter : public QObject
+{
+ Q_OBJECT
+public:
+ ChildrenChangeEventFilter(QObject *parent);
+
+
+signals:
+ void childrenChanged(QObject *object);
+
+protected:
+ bool eventFilter(QObject *object, QEvent *event);
+
+};
+
+class ObjectNodeInstance
+{
+public:
+ typedef QSharedPointer<ObjectNodeInstance> Pointer;
+ typedef QWeakPointer<ObjectNodeInstance> WeakPointer;
+ ObjectNodeInstance(QObject *object);
+
+ virtual ~ObjectNodeInstance();
+ void destroy();
+ //void setModelNode(const ModelNode &node);
+
+ static Pointer create(const NodeMetaInfo &metaInfo, QmlContext *context, QObject *objectToBeWrapped);
+
+ ModelNode modelNode() const;
+ void setModelNode(const ModelNode &node);
+
+ NodeInstanceView *nodeInstanceView() const;
+ void setNodeInstance(NodeInstanceView *view);
+
+ virtual void paint(QPainter *painter) const;
+
+ virtual bool isTopLevel() const;
+
+ virtual QObject *parent() const;
+
+ void reparent(const NodeInstance &oldParentInstance, const QString &oldParentProperty, const NodeInstance &newParentInstance, const QString &newParentProperty);
+
+ void setId(const QString &id);
+
+ virtual bool isQmlGraphicsItem() const;
+ virtual bool isGraphicsScene() const;
+ virtual bool isGraphicsView() const;
+ virtual bool isGraphicsWidget() const;
+ virtual bool isProxyWidget() const;
+ virtual bool isWidget() const;
+ virtual bool isQmlView() const;
+ virtual bool isGraphicsObject() const;
+ virtual bool isTransition() const;
+
+ virtual bool equalGraphicsItem(QGraphicsItem *item) const;
+
+ virtual QRectF boundingRect() const;
+
+ virtual QPointF position() const;
+ virtual QSizeF size() const;
+ virtual QTransform transform() const;
+ virtual QTransform customTransform() const;
+ virtual QTransform sceneTransform() const;
+ virtual double opacity() const;
+
+ virtual bool hasAnchor(const QString &name) const;
+ virtual QPair<QString, NodeInstance> anchor(const QString &name) const;
+ virtual bool isAnchoredBy() const;
+
+ virtual double rotation() const;
+ virtual double scale() const;
+ virtual QList<QGraphicsTransform *> transformations() const;
+ virtual QPointF transformOriginPoint() const;
+ virtual double zValue() const;
+
+ virtual void setPropertyVariant(const QString &name, const QVariant &value);
+ virtual void setPropertyBinding(const QString &name, const QString &expression);
+ virtual QVariant property(const QString &name) const;
+ virtual void resetProperty(const QString &name);
+ virtual bool isVisible() const;
+ virtual void setVisible(bool isVisible);
+
+ void createDynamicProperty(const QString &name, const QString &typeName);
+ void setDeleteHeldInstance(bool deleteInstance);
+ bool deleteHeldInstance() const;
+
+ virtual void updateAnchors();
+ virtual void paintUpdate();
+
+ void populateResetValueHash();
+ QVariant resetValue(const QString &propertyName) const;
+
+ QObject *object() const;
+
+ virtual bool hasContent() const;
+
+ QmlContext *context() const;
+
+protected:
+ static QObject* createObject(const NodeMetaInfo &metaInfo, QmlContext *context);
+
+ void resetProperty(QObject *object, const QString &propertyName);
+ static void updateObjectSignals(QObject *object);
+ NodeInstance instanceForNode(const ModelNode &node, const QString &fullname);
+
+ void removeFromOldProperty(QObject *object, QObject *oldParent, const QString &oldParentProperty);
+ void addToNewProperty(QObject *object, QObject *newParent, const QString &newParentProperty);
+ void deleteObjectsInList(const QmlMetaProperty &metaProperty);
+
+private:
+ static void refreshBindings(QmlContext *context);
+
+ QHash<QString, QVariant> m_resetValueHash;
+ QHash<QString, NodeInstance> m_modelAbstractPropertyHash;
+ ModelNode m_modelNode;
+
+ QWeakPointer<NodeInstanceView> m_nodeInstanceView;
+ bool m_deleteHeldInstance;
+ QWeakPointer<QObject> m_object;
+};
+
+
+} // namespace Internal
+} // namespace QmlDesigner
+
+#endif // ABSTRACTNODEINSTANCE_H
diff --git a/src/plugins/qmldesigner/core/instances/proxywidgetnodeinstance.cpp b/src/plugins/qmldesigner/core/instances/proxywidgetnodeinstance.cpp
new file mode 100644
index 0000000000..1749e7304b
--- /dev/null
+++ b/src/plugins/qmldesigner/core/instances/proxywidgetnodeinstance.cpp
@@ -0,0 +1,82 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "proxywidgetnodeinstance.h"
+
+#include <QmlMetaType>
+
+#include <QGraphicsProxyWidget>
+
+namespace QmlDesigner {
+namespace Internal {
+
+
+ProxyWidgetNodeInstance::ProxyWidgetNodeInstance(QGraphicsProxyWidget *widget)
+ : GraphicsWidgetNodeInstance(widget)
+{
+}
+
+
+ProxyWidgetNodeInstance::Pointer ProxyWidgetNodeInstance::create(const QString &typeName)
+{
+ QObject *object = QmlMetaType::qmlType(typeName.toLatin1(), 4, 6)->create();
+ Q_ASSERT(object);
+ if (object == 0)
+ return Pointer();
+
+ QGraphicsProxyWidget* widget = qobject_cast<QGraphicsProxyWidget*>(object);
+ Q_ASSERT(widget);
+ if (widget == 0)
+ return Pointer();
+
+ return Pointer(new ProxyWidgetNodeInstance(widget));
+}
+
+QGraphicsProxyWidget* ProxyWidgetNodeInstance::proxyWidget() const
+{
+ QGraphicsProxyWidget* proxyWidget = qobject_cast<QGraphicsProxyWidget*>(graphicsWidget());
+ Q_ASSERT(proxyWidget);
+
+ return proxyWidget;
+}
+
+
+void ProxyWidgetNodeInstance::setWidget(QWidget *widget)
+{
+ proxyWidget()->setWidget(widget);
+}
+
+bool ProxyWidgetNodeInstance::isProxyWidget() const
+{
+ return true;
+}
+
+
+}
+}
diff --git a/src/plugins/qmldesigner/core/instances/proxywidgetnodeinstance.h b/src/plugins/qmldesigner/core/instances/proxywidgetnodeinstance.h
new file mode 100644
index 0000000000..1c0ff8133d
--- /dev/null
+++ b/src/plugins/qmldesigner/core/instances/proxywidgetnodeinstance.h
@@ -0,0 +1,59 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef PROXYWIDGETNODEINSTANCE_H
+#define PROXYWIDGETNODEINSTANCE_H
+
+
+#include "graphicswidgetnodeinstance.h"
+
+namespace QmlDesigner {
+namespace Internal {
+
+class ProxyWidgetNodeInstance : public GraphicsWidgetNodeInstance
+{
+public:
+ typedef QSharedPointer<ProxyWidgetNodeInstance> Pointer;
+ typedef QWeakPointer<ProxyWidgetNodeInstance> WeakPointer;
+
+ static Pointer create(const QString &typeName);
+
+ void setWidget(QWidget *widget);
+
+ bool isProxyWidget() const;
+
+protected:
+ ProxyWidgetNodeInstance(QGraphicsProxyWidget *widget);
+
+ QGraphicsProxyWidget* proxyWidget() const;
+};
+
+}
+}
+#endif // PROXYWIDGETNODEINSTANCE_H
diff --git a/src/plugins/qmldesigner/core/instances/qmlgraphicsitemnodeinstance.cpp b/src/plugins/qmldesigner/core/instances/qmlgraphicsitemnodeinstance.cpp
new file mode 100644
index 0000000000..d2abed4752
--- /dev/null
+++ b/src/plugins/qmldesigner/core/instances/qmlgraphicsitemnodeinstance.cpp
@@ -0,0 +1,562 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "qmlgraphicsitemnodeinstance.h"
+#include "qmlviewnodeinstance.h"
+#include "graphicsscenenodeinstance.h"
+
+
+#include <invalidnodeinstanceexception.h>
+#include <propertymetainfo.h>
+
+#include "bindingproperty.h"
+#include "variantproperty.h"
+
+#include <private/qmlgraphicsanchors_p.h>
+#include <private/qmlgraphicsanchors_p_p.h>
+
+#include <private/qmlexpression_p.h>
+
+#include <cmath>
+
+#include <QHash>
+
+namespace QmlDesigner {
+namespace Internal {
+
+QmlGraphicsItemNodeInstance::QmlGraphicsItemNodeInstance(QmlGraphicsItem *item, bool hasContent)
+ : GraphicsObjectNodeInstance(item, hasContent),
+ m_hasHeight(false),
+ m_hasWidth(false)
+{
+}
+
+QmlGraphicsItemNodeInstance::~QmlGraphicsItemNodeInstance()
+{
+}
+
+QmlGraphicsItemNodeInstance::Pointer QmlGraphicsItemNodeInstance::create(const NodeMetaInfo &metaInfo, QmlContext *context, QObject *objectToBeWrapped)
+{
+ QPair<QGraphicsObject*, bool> objectPair;
+
+ if (objectToBeWrapped)
+ objectPair = qMakePair(qobject_cast<QGraphicsObject*>(objectToBeWrapped), false);
+ else
+ objectPair = GraphicsObjectNodeInstance::createGraphicsObject(metaInfo, context);
+
+ QmlGraphicsItem *qmlGraphicsItem = dynamic_cast<QmlGraphicsItem*>(objectPair.first);
+
+ if (qmlGraphicsItem == 0)
+ throw InvalidNodeInstanceException(__LINE__, __FUNCTION__, __FILE__);
+
+ Pointer instance(new QmlGraphicsItemNodeInstance(qmlGraphicsItem, objectPair.second));
+
+ if (objectToBeWrapped)
+ instance->setDeleteHeldInstance(false); // the object isn't owned
+
+ instance->populateResetValueHash();
+
+ return instance;
+}
+
+bool QmlGraphicsItemNodeInstance::isQmlGraphicsItem() const
+{
+ return true;
+}
+
+QSizeF QmlGraphicsItemNodeInstance::size() const
+{
+ if (modelNode().isValid()) {
+ double implicitWidth = qmlGraphicsItem()->implicitWidth();
+ if (!m_hasWidth
+ && implicitWidth // WORKAROUND
+ && implicitWidth != qmlGraphicsItem()->width())
+ qmlGraphicsItem()->setWidth(implicitWidth);
+
+ double implicitHeight = qmlGraphicsItem()->implicitHeight();
+ if (!m_hasHeight
+ && implicitWidth // WORKAROUND
+ && implicitHeight != qmlGraphicsItem()->height())
+ qmlGraphicsItem()->setHeight(implicitHeight);
+
+ }
+
+ return QSizeF(qmlGraphicsItem()->width(), qmlGraphicsItem()->height());
+}
+
+QRectF QmlGraphicsItemNodeInstance::boundingRect() const
+{
+ if (modelNode().isValid()) {
+ double implicitWidth = qmlGraphicsItem()->implicitWidth();
+ if (!m_hasWidth
+ && implicitWidth // WORKAROUND
+ && implicitWidth != qmlGraphicsItem()->width())
+ qmlGraphicsItem()->setWidth(implicitWidth);
+
+ double implicitHeight = qmlGraphicsItem()->implicitHeight();
+ if (!m_hasHeight
+ && implicitWidth // WORKAROUND
+ && implicitHeight != qmlGraphicsItem()->height())
+ qmlGraphicsItem()->setHeight(implicitHeight);
+
+ }
+
+ return qmlGraphicsItem()->boundingRect();
+}
+
+//QVariant anchorLineFor(QmlGraphicsItem *item, const AnchorLine &anchorLine)
+//{
+// switch(anchorLine.type()) {
+// case AnchorLine::Top : return item->property("top");
+// case AnchorLine::Bottom : return item->property("bottom");
+// case AnchorLine::Left : return item->property("left");
+// case AnchorLine::Right : return item->property("right");
+// case AnchorLine::HorizontalCenter : return item->property("horizontalCenter");
+// case AnchorLine::VerticalCenter : return item->property("verticalCenter");
+// case AnchorLine::Baseline : return item->property("baseline");
+// default: QVariant();
+// }
+//
+// Q_ASSERT_X(false, Q_FUNC_INFO, QString::number(anchorLine.type()).toLatin1());
+// return QVariant();
+//}
+
+void QmlGraphicsItemNodeInstance::setPropertyVariant(const QString &name, const QVariant &value)
+{
+ if (name == "height") {
+ if (value.isValid())
+ m_hasHeight = true;
+ else
+ m_hasHeight = false;
+ }
+
+ if (name == "width") {
+ if (value.isValid())
+ m_hasWidth = true;
+ else
+ m_hasWidth = false;
+ }
+
+ GraphicsObjectNodeInstance::setPropertyVariant(name, value);
+}
+
+void QmlGraphicsItemNodeInstance::setPropertyBinding(const QString &name, const QString &expression)
+{
+ GraphicsObjectNodeInstance::setPropertyBinding(name, expression);
+}
+
+QVariant QmlGraphicsItemNodeInstance::property(const QString &name) const
+{
+ if (name == "width" && modelNode().isValid()) {
+ double implicitWidth = qmlGraphicsItem()->implicitWidth();
+ if (!m_hasWidth
+ && implicitWidth // WORKAROUND
+ && implicitWidth != qmlGraphicsItem()->width())
+ qmlGraphicsItem()->setWidth(implicitWidth);
+ }
+
+ if (name == "height" && modelNode().isValid()) {
+ double implicitHeight = qmlGraphicsItem()->implicitHeight();
+ if (!m_hasHeight
+ && implicitHeight // WORKAROUND
+ && implicitHeight != qmlGraphicsItem()->height())
+ qmlGraphicsItem()->setHeight(implicitHeight);
+ }
+
+ return GraphicsObjectNodeInstance::property(name);
+}
+
+void QmlGraphicsItemNodeInstance::resetHorizontal()
+ {
+ if (modelNode().hasBindingProperty("x"))
+ setPropertyBinding("x", modelNode().bindingProperty("x").expression());
+ else if (modelNode().hasVariantProperty("x"))
+ setPropertyVariant("x", modelNode().variantProperty("x").value());
+ else
+ setPropertyVariant("x", 0.0);
+
+ if (modelNode().hasBindingProperty("width"))
+ setPropertyBinding("width", modelNode().bindingProperty("width").expression());
+ else if (modelNode().hasVariantProperty("width"))
+ setPropertyVariant("width", modelNode().variantProperty("width").value());
+ else
+ setPropertyVariant("width", qmlGraphicsItem()->implicitWidth());
+}
+
+void QmlGraphicsItemNodeInstance::resetVertical()
+ {
+ if (modelNode().hasBindingProperty("y"))
+ setPropertyBinding("y", modelNode().bindingProperty("y").expression());
+ else if (modelNode().hasVariantProperty("y"))
+ setPropertyVariant("y", modelNode().variantProperty("y").value());
+ else
+ setPropertyVariant("y", 0.0);
+
+ if (modelNode().hasBindingProperty("height"))
+ setPropertyBinding("height", modelNode().bindingProperty("height").expression());
+ else if (modelNode().hasVariantProperty("height"))
+ setPropertyVariant("height", modelNode().variantProperty("height").value());
+ else
+ setPropertyVariant("height", qmlGraphicsItem()->implicitHeight());
+}
+
+
+void QmlGraphicsItemNodeInstance::resetProperty(const QString &name)
+{
+ GraphicsObjectNodeInstance::resetProperty(name);
+ if (name == "anchors.fill") {
+ qmlGraphicsItem()->anchors()->resetFill();
+ resetHorizontal();
+ resetVertical();
+ } else if (name == "anchors.centerIn") {
+ qmlGraphicsItem()->anchors()->resetCenterIn();
+ resetHorizontal();
+ resetVertical();
+ } else if (name == "anchors.top") {
+ qmlGraphicsItem()->anchors()->resetTop();
+ resetVertical();
+ } else if (name == "anchors.left") {
+ qmlGraphicsItem()->anchors()->resetLeft();
+ resetHorizontal();
+ } else if (name == "anchors.right") {
+ qmlGraphicsItem()->anchors()->resetRight();
+ resetHorizontal();
+ } else if (name == "anchors.bottom") {
+ qmlGraphicsItem()->anchors()->resetBottom();
+ resetVertical();
+ } else if (name == "anchors.horizontalCenter") {
+ qmlGraphicsItem()->anchors()->resetHorizontalCenter();
+ resetHorizontal();
+ } else if (name == "anchors.verticalCenter") {
+ qmlGraphicsItem()->anchors()->resetVerticalCenter();
+ resetVertical();
+ } else if (name == "anchors.baseline") {
+ qmlGraphicsItem()->anchors()->resetBaseline();
+ resetVertical();
+ }
+}
+
+//void QmlGraphicsItemNodeInstance::updateAnchors()
+//{
+// NodeAnchors anchors(modelNode());
+//
+// if (anchors.hasAnchor(AnchorLine::Top)) {
+// AnchorLine anchorLine(anchors.anchor(AnchorLine::Top));
+// NodeInstance instance(nodeInstanceView()->instanceForNode(anchorLine.modelNode()));
+//
+// if (instance.isQmlGraphicsItem()) {
+// Pointer qmlGraphicsItemInstance(instance.QmlGraphicsItemNodeInstance());
+// qmlGraphicsItem()->anchors()->setProperty("top", anchorLineFor(qmlGraphicsItemInstance->qmlGraphicsItem(), anchorLine));
+// }
+// } else {
+// if (qmlGraphicsItem()->anchors()->usedAnchors().testFlag(QmlGraphicsAnchors::HasTopAnchor)) {
+// qmlGraphicsItem()->anchors()->resetTop();
+// setPropertyValue("y", modelNode().property("y").value());
+// setPropertyValue("height", modelNode().property("height").value());
+// }
+// }
+//
+//
+// if (anchors.hasAnchor(AnchorLine::Left)) {
+// AnchorLine anchorLine(anchors.anchor(AnchorLine::Left));
+// NodeInstance instance(nodeInstanceView()->instanceForNode(anchorLine.modelNode()));
+//
+// if (instance.isQmlGraphicsItem()) {
+// Pointer qmlGraphicsItemInstance(instance.QmlGraphicsItemNodeInstance());
+// qmlGraphicsItem()->anchors()->setProperty("left", anchorLineFor(qmlGraphicsItemInstance->qmlGraphicsItem(), anchorLine));
+// }
+// } else {
+// if (qmlGraphicsItem()->anchors()->usedAnchors().testFlag(QmlGraphicsAnchors::HasLeftAnchor)) {
+// qmlGraphicsItem()->anchors()->resetLeft();
+// setPropertyValue("x", modelNode().property("x").value());
+// setPropertyValue("width", modelNode().property("width").value());
+// }
+// }
+//
+//
+// if (anchors.hasAnchor(AnchorLine::Right)) {
+// AnchorLine anchorLine(anchors.anchor(AnchorLine::Right));
+// NodeInstance instance(nodeInstanceView()->instanceForNode(anchorLine.modelNode()));
+//
+// if (instance.isQmlGraphicsItem()) {
+// Pointer qmlGraphicsItemInstance(instance.QmlGraphicsItemNodeInstance());
+// qmlGraphicsItem()->anchors()->setProperty("right", anchorLineFor(qmlGraphicsItemInstance->qmlGraphicsItem(), anchorLine));
+// }
+// } else {
+// if (qmlGraphicsItem()->anchors()->usedAnchors().testFlag(QmlGraphicsAnchors::HasRightAnchor)) {
+// qmlGraphicsItem()->anchors()->resetRight();
+// setPropertyValue("x", modelNode().property("x").value());
+// setPropertyValue("width", modelNode().property("width").value());
+// }
+// }
+//
+//
+// if (anchors.hasAnchor(AnchorLine::Bottom)) {
+// AnchorLine anchorLine(anchors.anchor(AnchorLine::Bottom));
+// NodeInstance instance(nodeInstanceView()->instanceForNode(anchorLine.modelNode()));
+//
+// if (instance.isQmlGraphicsItem()) {
+// Pointer qmlGraphicsItemInstance(instance.QmlGraphicsItemNodeInstance());
+// qmlGraphicsItem()->anchors()->setProperty("bottom", anchorLineFor(qmlGraphicsItemInstance->qmlGraphicsItem(), anchorLine));
+// }
+// } else {
+// if (qmlGraphicsItem()->anchors()->usedAnchors().testFlag(QmlGraphicsAnchors::HasBottomAnchor)) {
+// qmlGraphicsItem()->anchors()->resetBottom();
+// setPropertyValue("y", modelNode().property("y").value());
+// setPropertyValue("height", modelNode().property("height").value());
+// }
+// }
+//
+//
+// if (anchors.hasAnchor(AnchorLine::HorizontalCenter)) {
+// AnchorLine anchorLine(anchors.anchor(AnchorLine::HorizontalCenter));
+// NodeInstance instance(nodeInstanceView()->instanceForNode(anchorLine.modelNode()));
+//
+// if (instance.isQmlGraphicsItem()) {
+// Pointer qmlGraphicsItemInstance(instance.QmlGraphicsItemNodeInstance());
+// qmlGraphicsItem()->anchors()->setProperty("horizontalCenter", anchorLineFor(qmlGraphicsItemInstance->qmlGraphicsItem(), anchorLine));
+// }
+// } else {
+// if (qmlGraphicsItem()->anchors()->usedAnchors().testFlag(QmlGraphicsAnchors::HasHCenterAnchor)) {
+// qmlGraphicsItem()->anchors()->resetHorizontalCenter();
+// setPropertyValue("x", modelNode().property("x").value());
+// setPropertyValue("width", modelNode().property("width").value());
+// }
+// }
+//
+//
+// if (anchors.hasAnchor(AnchorLine::VerticalCenter)) {
+// AnchorLine anchorLine(anchors.anchor(AnchorLine::VerticalCenter));
+// NodeInstance instance(nodeInstanceView()->instanceForNode(anchorLine.modelNode()));
+//
+// if (instance.isQmlGraphicsItem()) {
+// Pointer qmlGraphicsItemInstance(instance.QmlGraphicsItemNodeInstance());
+// qmlGraphicsItem()->anchors()->setProperty("verticalCenter",anchorLineFor(qmlGraphicsItemInstance->qmlGraphicsItem(), anchorLine));
+// }
+// } else {
+// if (qmlGraphicsItem()->anchors()->usedAnchors().testFlag(QmlGraphicsAnchors::HasVCenterAnchor)) {
+// qmlGraphicsItem()->anchors()->resetVerticalCenter();
+// setPropertyValue("y", modelNode().property("y").value());
+// setPropertyValue("height", modelNode().property("height").value());
+// }
+// }
+//
+//
+// qmlGraphicsItem()->anchors()->setTopMargin(anchors.margin(AnchorLine::Top));
+// qmlGraphicsItem()->anchors()->setLeftMargin(anchors.margin(AnchorLine::Left));
+// qmlGraphicsItem()->anchors()->setBottomMargin(anchors.margin(AnchorLine::Bottom));
+// qmlGraphicsItem()->anchors()->setRightMargin(anchors.margin(AnchorLine::Right));
+// qmlGraphicsItem()->anchors()->setHorizontalCenterOffset(anchors.margin(AnchorLine::HorizontalCenter));
+// qmlGraphicsItem()->anchors()->setVerticalCenterOffset(anchors.margin(AnchorLine::VerticalCenter));
+//}
+
+QmlGraphicsAnchors::UsedAnchor anchorLineFlagForName(const QString &name)
+{
+ if (name == "anchors.top")
+ return QmlGraphicsAnchors::HasTopAnchor;
+
+ if (name == "anchors.left")
+ return QmlGraphicsAnchors::HasLeftAnchor;
+
+ if (name == "anchors.bottom")
+ return QmlGraphicsAnchors::HasBottomAnchor;
+
+ if (name == "anchors.right")
+ return QmlGraphicsAnchors::HasRightAnchor;
+
+ if (name == "anchors.horizontalCenter")
+ return QmlGraphicsAnchors::HasHCenterAnchor;
+
+ if (name == "anchors.verticalCenter")
+ return QmlGraphicsAnchors::HasVCenterAnchor;
+
+ if (name == "anchors.baseline")
+ return QmlGraphicsAnchors::HasBaselineAnchor;
+
+
+ Q_ASSERT_X(false, Q_FUNC_INFO, "wrong anchor name - this should never happen");
+ return QmlGraphicsAnchors::HasLeftAnchor;
+}
+
+QString propertyNameForAnchorLine(const QmlGraphicsAnchorLine::AnchorLine &anchorLine)
+{
+ switch(anchorLine) {
+ case QmlGraphicsAnchorLine::Left: return "left";
+ case QmlGraphicsAnchorLine::Right: return "right";
+ case QmlGraphicsAnchorLine::Top: return "top";
+ case QmlGraphicsAnchorLine::Bottom: return "bottom";
+ case QmlGraphicsAnchorLine::HCenter: return "horizontalCenter";
+ case QmlGraphicsAnchorLine::VCenter: return "verticalCenter";
+ case QmlGraphicsAnchorLine::Baseline: return "baseline";
+ case QmlGraphicsAnchorLine::Invalid:
+ default: return QString();
+ }
+}
+
+bool isValidAnchorName(const QString &name)
+{
+ static QStringList anchorNameList(QStringList() << "anchors.top"
+ << "anchors.left"
+ << "anchors.right"
+ << "anchors.bottom"
+ << "anchors.verticalCenter"
+ << "anchors.horizontalCenter"
+ << "anchors.fill"
+ << "anchors.centerIn"
+ << "anchors.baseline");
+
+ return anchorNameList.contains(name);
+}
+
+QPair<QString, NodeInstance> QmlGraphicsItemNodeInstance::anchor(const QString &name) const
+{
+ if (!isValidAnchorName(name) || !hasAnchor(name))
+ return GraphicsObjectNodeInstance::anchor(name);
+
+ QObject *targetObject = 0;
+ QString targetName;
+
+ if (name == "anchors.fill") {
+ targetObject = qmlGraphicsItem()->anchors()->fill();
+ } else if (name == "anchors.centerIn") {
+ targetObject = qmlGraphicsItem()->anchors()->centerIn();
+ } else {
+ QmlMetaProperty metaProperty = QmlMetaProperty::createProperty(object(), name, context());
+ QmlGraphicsAnchorLine anchorLine = metaProperty.read().value<QmlGraphicsAnchorLine>();
+ if (anchorLine.anchorLine != QmlGraphicsAnchorLine::Invalid) {
+ targetObject = anchorLine.item;
+ targetName = propertyNameForAnchorLine(anchorLine.anchorLine);
+ }
+
+ }
+
+ if (targetObject && nodeInstanceView()->hasInstanceForObject(targetObject)) {
+ return qMakePair(targetName, nodeInstanceView()->instanceForObject(targetObject));
+ } else {
+ return GraphicsObjectNodeInstance::anchor(name);
+ }
+}
+
+bool QmlGraphicsItemNodeInstance::hasAnchor(const QString &name) const
+{
+ if (!isValidAnchorName(name))
+ return false;
+
+ if (name == "anchors.fill")
+ return qmlGraphicsItem()->anchors()->fill() != 0;
+
+ if (name == "anchors.centerIn")
+ return qmlGraphicsItem()->anchors()->centerIn() != 0;
+
+ if (name == "anchors.right")
+ return qmlGraphicsItem()->anchors()->right().item != 0;
+
+ if (name == "anchors.top")
+ return qmlGraphicsItem()->anchors()->top().item != 0;
+
+ if (name == "anchors.left")
+ return qmlGraphicsItem()->anchors()->left().item != 0;
+
+ if (name == "anchors.bottom")
+ return qmlGraphicsItem()->anchors()->bottom().item != 0;
+
+ if (name == "anchors.horizontalCenter")
+ return qmlGraphicsItem()->anchors()->horizontalCenter().item != 0;
+
+ if (name == "anchors.verticalCenter")
+ return qmlGraphicsItem()->anchors()->verticalCenter().item != 0;
+
+ if (name == "anchors.baseline")
+ return qmlGraphicsItem()->anchors()->baseline().item != 0;
+
+ return qmlGraphicsItem()->anchors()->usedAnchors().testFlag(anchorLineFlagForName(name));
+}
+
+bool isAnchoredTo(QmlGraphicsItem *fromItem, QmlGraphicsItem *toItem)
+{
+ return fromItem->anchors()->fill() == toItem
+ || fromItem->anchors()->centerIn() == toItem
+ || fromItem->anchors()->bottom().item == toItem
+ || fromItem->anchors()->top().item == toItem
+ || fromItem->anchors()->left().item == toItem
+ || fromItem->anchors()->right().item == toItem
+ || fromItem->anchors()->verticalCenter().item == toItem
+ || fromItem->anchors()->horizontalCenter().item == toItem
+ || fromItem->anchors()->baseline().item == toItem;
+}
+
+bool areChildrenAnchoredTo(QmlGraphicsItem *fromItem, QmlGraphicsItem *toItem)
+{
+ foreach(QObject *childObject, fromItem->children()) {
+ QmlGraphicsItem *childItem = qobject_cast<QmlGraphicsItem*>(childObject);
+ if (childItem) {
+ if (isAnchoredTo(childItem, toItem))
+ return true;
+
+ if (areChildrenAnchoredTo(childItem, toItem))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool QmlGraphicsItemNodeInstance::isAnchoredBy() const
+{
+ if (areChildrenAnchoredTo(qmlGraphicsItem(), qmlGraphicsItem())) // search in children for a anchor to this item
+ return true;
+
+ if (qmlGraphicsItem()->parent()) {
+ foreach(QObject *siblingObject, qmlGraphicsItem()->parent()->children()) { // search in siblings for a anchor to this item
+ QmlGraphicsItem *siblingItem = qobject_cast<QmlGraphicsItem*>(siblingObject);
+ if (siblingItem) {
+ if (isAnchoredTo(siblingItem, qmlGraphicsItem()))
+ return true;
+
+ if (areChildrenAnchoredTo(siblingItem, qmlGraphicsItem()))
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+
+
+QmlGraphicsItem *QmlGraphicsItemNodeInstance::qmlGraphicsItem() const
+{
+ if (object() == 0)
+ return 0;
+
+ Q_ASSERT(qobject_cast<QmlGraphicsItem*>(object()));
+ return static_cast<QmlGraphicsItem*>(object());
+}
+}
+}
diff --git a/src/plugins/qmldesigner/core/instances/qmlgraphicsitemnodeinstance.h b/src/plugins/qmldesigner/core/instances/qmlgraphicsitemnodeinstance.h
new file mode 100644
index 0000000000..da1275b282
--- /dev/null
+++ b/src/plugins/qmldesigner/core/instances/qmlgraphicsitemnodeinstance.h
@@ -0,0 +1,79 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef QMLGRAPHICSITEMNODEINSTANCE_H
+#define QMLGRAPHICSITEMNODEINSTANCE_H
+
+#include "graphicsobjectnodeinstance.h"
+#include <QmlGraphicsItem>
+#include <QWeakPointer>
+
+
+namespace QmlDesigner {
+namespace Internal {
+
+class QmlGraphicsItemNodeInstance : public GraphicsObjectNodeInstance
+{
+public:
+ typedef QSharedPointer<QmlGraphicsItemNodeInstance> Pointer;
+ typedef QWeakPointer<QmlGraphicsItemNodeInstance> WeakPointer;
+
+ ~QmlGraphicsItemNodeInstance();
+
+ static Pointer create(const NodeMetaInfo &metaInfo, QmlContext *context, QObject *objectToBeWrapped);
+
+ bool isQmlGraphicsItem() const;
+
+ QSizeF size() const;
+ QRectF boundingRect() const;
+// void updateAnchors();
+
+ void setPropertyVariant(const QString &name, const QVariant &value);
+ void setPropertyBinding(const QString &name, const QString &expression);
+
+ QVariant property(const QString &name) const;
+ void resetProperty(const QString &name);
+
+ bool hasAnchor(const QString &name) const;
+ QPair<QString, NodeInstance> anchor(const QString &name) const;
+ bool isAnchoredBy() const;
+protected:
+ QmlGraphicsItemNodeInstance(QmlGraphicsItem *item, bool hasContent);
+ QmlGraphicsItem *qmlGraphicsItem() const;
+ void resetHorizontal();
+ void resetVertical();
+
+private: //variables
+ bool m_hasHeight;
+ bool m_hasWidth;
+};
+
+}
+}
+#endif // QMLGRAPHICSITEMNODEINSTANCE_H
diff --git a/src/plugins/qmldesigner/core/instances/qmlpropertychangesnodeinstance.cpp b/src/plugins/qmldesigner/core/instances/qmlpropertychangesnodeinstance.cpp
new file mode 100644
index 0000000000..35cb232230
--- /dev/null
+++ b/src/plugins/qmldesigner/core/instances/qmlpropertychangesnodeinstance.cpp
@@ -0,0 +1,205 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "qmlpropertychangesnodeinstance.h"
+#include "qmlstatenodeinstance.h"
+#include <QmlEngine>
+#include <QmlContext>
+#include <QmlExpression>
+#include <QmlBinding>
+#include <metainfo.h>
+
+namespace QmlDesigner {
+namespace Internal {
+
+QmlPropertyChangesObject::QmlPropertyChangesObject() :
+ QmlStateOperation(),
+ m_restoreEntryValues(true),
+ m_isExplicit(false)
+{
+}
+
+QmlStateOperation::ActionList QmlPropertyChangesObject::actions()
+{
+ ActionList list;
+
+ foreach (const QString &property, m_properties.keys()) {
+ Action a(m_targetObject.data(), property, m_properties.value(property));
+
+ if (a.property.isValid()) {
+ a.restore = restoreEntryValues();
+
+ if (a.property.propertyType() == QVariant::Url &&
+ (a.toValue.type() == QVariant::String || a.toValue.type() == QVariant::ByteArray) && !a.toValue.isNull())
+ a.toValue.setValue(qmlContext(this)->resolvedUrl(QUrl(a.toValue.toString())));
+
+ list << a;
+ }
+ }
+
+// for (int ii = 0; ii < d->signalReplacements.count(); ++ii) {
+//
+// QmlReplaceSignalHandler *handler = d->signalReplacements.at(ii);
+//
+// if (handler->property.isValid()) {
+// Action a;
+// a.event = handler;
+// list << a;
+// }
+// }
+
+ foreach (const QString &property, m_expressions.keys()) {
+ QmlMetaProperty mProperty = metaProperty(property);
+
+ if (mProperty.isValid()) {
+ Action a;
+ a.restore = restoreEntryValues();
+ a.property = mProperty;
+ a.fromValue = a.property.read();
+ a.specifiedObject = m_targetObject.data();
+ a.specifiedProperty = property;
+
+ if (m_isExplicit) {
+ a.toValue = QmlExpression(qmlContext(object()), m_expressions.value(property), object()).value();
+ } else {
+ QmlBinding *newBinding = new QmlBinding(m_expressions.value(property), object(), qmlContext(object()));
+ newBinding->setTarget(mProperty);
+ a.toBinding = newBinding;
+ a.deletableToBinding = true;
+ }
+
+ list << a;
+ }
+ }
+
+ return list;
+}
+
+QmlMetaProperty QmlPropertyChangesObject::metaProperty(const QString &property)
+{
+ QmlMetaProperty prop = QmlMetaProperty::createProperty(m_targetObject.data(), property);
+ if (!prop.isValid()) {
+ qWarning() << "Cannot assign to non-existant property" << property;
+ return QmlMetaProperty();
+ } else if (!prop.isWritable()) {
+ qWarning() << "Cannot assign to read-only property" << property;
+ return QmlMetaProperty();
+ }
+ return prop;
+}
+
+QmlPropertyChangesNodeInstance::QmlPropertyChangesNodeInstance(QmlPropertyChangesObject *propertyChangesObject) :
+ ObjectNodeInstance(propertyChangesObject)
+{
+}
+
+QmlPropertyChangesNodeInstance::Pointer
+ QmlPropertyChangesNodeInstance::create(const NodeMetaInfo & /*metaInfo*/,
+ QmlContext *context,
+ QObject *objectToBeWrapped)
+{
+ Q_ASSERT(!objectToBeWrapped);
+
+ QmlPropertyChangesObject *object = new QmlPropertyChangesObject;
+ QmlEngine::setContextForObject(object, context);
+ Pointer instance(new QmlPropertyChangesNodeInstance(object));
+ return instance;
+}
+
+void QmlPropertyChangesNodeInstance::setPropertyVariant(const QString &name, const QVariant &value)
+{
+ QmlMetaProperty metaProperty = QmlMetaProperty::createProperty(object(), name, context());
+ if (metaProperty.isValid()) { // 'restoreEntryValues', 'explicit'
+ ObjectNodeInstance::setPropertyVariant(name, value);
+ return;
+ }
+ changesObject()->m_properties.insert(name, value);
+
+ updateStateInstance();
+}
+
+void QmlPropertyChangesNodeInstance::setPropertyBinding(const QString &name, const QString &expression)
+{
+ QmlMetaProperty metaProperty = QmlMetaProperty::createProperty(object(), name, context());
+ if (metaProperty.isValid()) { // 'target'
+ ObjectNodeInstance::setPropertyBinding(name, expression);
+ return;
+ }
+ changesObject()->m_expressions.insert(name, expression);
+
+ updateStateInstance();
+}
+
+QVariant QmlPropertyChangesNodeInstance::property(const QString &name) const
+{
+ if (changesObject()->m_properties.contains(name))
+ return changesObject()->m_properties.value(name);
+ if (changesObject()->m_expressions.contains(name))
+ return changesObject()->m_expressions.value(name);
+
+ return QVariant();
+}
+
+void QmlPropertyChangesNodeInstance::resetProperty(const QString &name)
+{
+ if (changesObject()->m_properties.contains(name))
+ changesObject()->m_properties.remove(name);
+ else if (changesObject()->m_expressions.contains(name))
+ changesObject()->m_expressions.remove(name);
+ // TODO: How to force states object to update?
+
+ updateStateInstance();
+}
+
+QmlPropertyChangesObject *QmlPropertyChangesNodeInstance::changesObject() const
+{
+ Q_ASSERT(qobject_cast<QmlPropertyChangesObject*>(object()));
+ return static_cast<QmlPropertyChangesObject*>(object());
+}
+
+void QmlPropertyChangesNodeInstance::updateStateInstance() const
+{
+ if (!nodeInstanceView()->hasInstanceForNode(modelNode()))
+ return;
+
+ NodeInstance myInstance = nodeInstanceView()->instanceForNode(modelNode());
+ Q_ASSERT(myInstance.isValid());
+
+ NodeInstance qmlStateInstance = myInstance.parent();
+ if (!qmlStateInstance.isValid()
+ || !qmlStateInstance.modelNode().isValid())
+ return;
+
+ qmlStateInstance.setPropertyVariant(PROPERTY_STATEACTIONSCHANGED, true);
+}
+
+} // namespace Internal
+} // namespace QmlDesigner
+
+QML_DEFINE_NOCREATE_TYPE(QmlDesigner::Internal::QmlPropertyChangesObject)
diff --git a/src/plugins/qmldesigner/core/instances/qmlpropertychangesnodeinstance.h b/src/plugins/qmldesigner/core/instances/qmlpropertychangesnodeinstance.h
new file mode 100644
index 0000000000..a928621ce6
--- /dev/null
+++ b/src/plugins/qmldesigner/core/instances/qmlpropertychangesnodeinstance.h
@@ -0,0 +1,103 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef QMLPROPERTYCHANGESNODEINSTANCE_H
+#define QMLPROPERTYCHANGESNODEINSTANCE_H
+
+#include "objectnodeinstance.h"
+#include <private/qmlstateoperations_p.h>
+
+namespace QmlDesigner {
+
+namespace Internal {
+
+class QmlPropertyChangesNodeInstance;
+
+// Original QmlPropertyChanges class requires a custom parser
+// work around this by writing a replacement class
+class QmlPropertyChangesObject : public QmlStateOperation
+{
+ Q_OBJECT
+ Q_PROPERTY(QObject *target READ object WRITE setObject)
+ Q_PROPERTY(bool restoreEntryValues READ restoreEntryValues WRITE setRestoreEntryValues)
+ Q_PROPERTY(bool explicit READ isExplicit WRITE setIsExplicit)
+
+public:
+ QObject *object() const { return m_targetObject.data(); }
+ void setObject(QObject *object) {m_targetObject = object; }
+
+ bool restoreEntryValues() const { return m_restoreEntryValues; }
+ void setRestoreEntryValues(bool restore) { m_restoreEntryValues = restore; }
+
+ bool isExplicit() const { return m_isExplicit; }
+ void setIsExplicit(bool isExplicit) { m_isExplicit = isExplicit; }
+
+ virtual ActionList actions();
+
+private:
+ friend class QmlPropertyChangesNodeInstance;
+
+ QmlPropertyChangesObject();
+ QmlMetaProperty metaProperty(const QString &property);
+
+ QWeakPointer<QObject> m_targetObject;
+ bool m_restoreEntryValues;
+ bool m_isExplicit;
+
+ QHash<QString, QVariant> m_properties;
+ QHash<QString, QString> m_expressions;
+// QList<QmlReplaceSignalHandler*> signalReplacements;
+};
+
+class QmlPropertyChangesNodeInstance : public ObjectNodeInstance
+{
+public:
+ typedef QSharedPointer<QmlPropertyChangesNodeInstance> Pointer;
+ typedef QWeakPointer<QmlPropertyChangesNodeInstance> WeakPointer;
+
+ static Pointer create(const NodeMetaInfo &metaInfo, QmlContext *context, QObject *objectToBeWrapped);
+
+ virtual void setPropertyVariant(const QString &name, const QVariant &value);
+ virtual void setPropertyBinding(const QString &name, const QString &expression);
+ virtual QVariant property(const QString &name) const;
+ virtual void resetProperty(const QString &name);
+
+ void updateStateInstance() const;
+
+protected:
+ QmlPropertyChangesNodeInstance(QmlPropertyChangesObject *object);
+ QmlPropertyChangesObject *changesObject() const;
+};
+
+} // namespace Internal
+} // namespace QmlDesigner
+
+QML_DECLARE_TYPE(QmlDesigner::Internal::QmlPropertyChangesObject)
+
+#endif // QMLPROPERTYCHANGESNODEINSTANCE_H
diff --git a/src/plugins/qmldesigner/core/instances/qmlstatenodeinstance.cpp b/src/plugins/qmldesigner/core/instances/qmlstatenodeinstance.cpp
new file mode 100644
index 0000000000..615b5f7be7
--- /dev/null
+++ b/src/plugins/qmldesigner/core/instances/qmlstatenodeinstance.cpp
@@ -0,0 +1,134 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "qmlstatenodeinstance.h"
+#include <private/qmlstategroup_p.h>
+
+namespace QmlDesigner {
+namespace Internal {
+
+const char * const ACTIVATESTATEPROPERTY = "__activateState";
+const char * const STATEACTIONSCHANGED = "__stateActionsChanged";
+
+/**
+ \class QmlStateNodeInstance
+
+ QmlStateNodeInstance manages a QmlState object. One can activate / deactivate a state
+ by setting/unsetting the special "__activateState" boolean property.
+ */
+
+QmlStateNodeInstance::QmlStateNodeInstance(QmlState *object) :
+ ObjectNodeInstance(object)
+{
+}
+
+QmlStateNodeInstance::Pointer
+ QmlStateNodeInstance::create(const NodeMetaInfo &metaInfo,
+ QmlContext *context,
+ QObject *objectToBeWrapped)
+{
+ Q_ASSERT(!objectToBeWrapped);
+ QObject *object = createObject(metaInfo, context);
+ QmlState *stateObject = qobject_cast<QmlState*>(object);
+ Q_ASSERT(stateObject);
+
+ Pointer instance(new QmlStateNodeInstance(stateObject));
+
+ instance->populateResetValueHash();
+
+ return instance;
+}
+
+void QmlStateNodeInstance::setPropertyVariant(const QString &name, const QVariant &value)
+{
+ if (name == ACTIVATESTATEPROPERTY) {
+ Q_ASSERT(value.type() == QVariant::Bool);
+ bool shouldActivate = value.toBool();
+
+ if (shouldActivate != isStateActive()) {
+ if (shouldActivate) {
+// QmlState *currentState = stateGroup()->findState(stateGroup()->state());
+// stateObject()->apply(stateGroup(), 0, currentState);
+
+ // TODO: Will this activate transitions????
+ stateGroup()->setState(property("name").toString());
+ } else {
+ resetProperty(name);
+ }
+ }
+ } else if (name == PROPERTY_STATEACTIONSCHANGED) {
+ if (isStateActive()) {
+ stateGroup()->setState(QString());
+ stateGroup()->setState(property("name").toString());
+ }
+ } else {
+ ObjectNodeInstance::setPropertyVariant(name, value);
+ }
+}
+
+QVariant QmlStateNodeInstance::property(const QString &name) const
+{
+ if (name == ACTIVATESTATEPROPERTY) {
+ return isStateActive();
+ } else {
+ return ObjectNodeInstance::property(name);
+ }
+}
+
+void QmlStateNodeInstance::resetProperty(const QString &name)
+{
+ if (name == ACTIVATESTATEPROPERTY) {
+ if (isStateActive()) {
+ // TODO: Will this activate transitions????
+ stateGroup()->setState(QString());
+ }
+ } else {
+ ObjectNodeInstance::resetProperty(name);
+ }
+}
+
+QmlState *QmlStateNodeInstance::stateObject() const
+{
+ Q_ASSERT(object());
+ Q_ASSERT(qobject_cast<QmlState*>(object()));
+ return static_cast<QmlState*>(object());
+}
+
+QmlStateGroup *QmlStateNodeInstance::stateGroup() const
+{
+ return stateObject()->stateGroup();
+}
+
+bool QmlStateNodeInstance::isStateActive() const
+{
+ return (stateGroup()->state() == property("name"));
+}
+
+} // namespace Internal
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/core/instances/qmlstatenodeinstance.h b/src/plugins/qmldesigner/core/instances/qmlstatenodeinstance.h
new file mode 100644
index 0000000000..f5ef1a40bf
--- /dev/null
+++ b/src/plugins/qmldesigner/core/instances/qmlstatenodeinstance.h
@@ -0,0 +1,66 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef QMLSTATENODEINSTANCE_H
+#define QMLSTATENODEINSTANCE_H
+
+#include "objectnodeinstance.h"
+#include <private/qmlstate_p.h>
+
+namespace QmlDesigner {
+
+namespace Internal {
+
+const char * const PROPERTY_STATEACTIONSCHANGED = "__stateActionsChanged";
+
+class QmlStateNodeInstance : public ObjectNodeInstance
+{
+public:
+ typedef QSharedPointer<QmlStateNodeInstance> Pointer;
+ typedef QWeakPointer<QmlStateNodeInstance> WeakPointer;
+
+ static Pointer create(const NodeMetaInfo &metaInfo, QmlContext *context, QObject *objectToBeWrapped);
+
+ virtual void setPropertyVariant(const QString &name, const QVariant &value);
+ virtual QVariant property(const QString &name) const;
+ virtual void resetProperty(const QString &name);
+
+protected:
+ QmlStateNodeInstance(QmlState *object);
+
+ bool isStateActive() const;
+
+ QmlState *stateObject() const;
+ QmlStateGroup *stateGroup() const;
+};
+
+} // namespace Internal
+} // namespace QmlDesigner
+
+#endif // QMLSTATENODEINSTANCE_H
diff --git a/src/plugins/qmldesigner/core/instances/qmltransitionnodeinstance.cpp b/src/plugins/qmldesigner/core/instances/qmltransitionnodeinstance.cpp
new file mode 100644
index 0000000000..0cc5388156
--- /dev/null
+++ b/src/plugins/qmldesigner/core/instances/qmltransitionnodeinstance.cpp
@@ -0,0 +1,87 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "qmltransitionnodeinstance.h"
+#include <private/qmltransition_p.h>
+#include <nodemetainfo.h>
+#include "invalidnodeinstanceexception.h"
+
+namespace QmlDesigner {
+namespace Internal {
+
+QmlTransitionNodeInstance::QmlTransitionNodeInstance(QmlTransition *transition)
+ : ObjectNodeInstance(transition)
+{
+}
+
+QmlTransitionNodeInstance::Pointer QmlTransitionNodeInstance::create(const NodeMetaInfo &nodeMetaInfo, QmlContext *context, QObject *objectToBeWrapped)
+{
+ QObject *object = 0;
+ if (objectToBeWrapped)
+ object = objectToBeWrapped;
+ else
+ object = createObject(nodeMetaInfo, context);
+
+ QmlTransition *transition = qobject_cast<QmlTransition*>(object);
+ if (transition == 0)
+ throw InvalidNodeInstanceException(__LINE__, __FUNCTION__, __FILE__);
+
+ Pointer instance(new QmlTransitionNodeInstance(transition));
+
+ if (objectToBeWrapped)
+ instance->setDeleteHeldInstance(false); // the object isn't owned
+
+ instance->populateResetValueHash();
+
+ transition->setToState("invalidState");
+ transition->setFromState("invalidState");
+
+ return instance;
+}
+
+bool QmlTransitionNodeInstance::isTransition() const
+{
+ return true;
+}
+
+void QmlTransitionNodeInstance::setPropertyVariant(const QString &name, const QVariant &value)
+{
+ if (name == "from" || name == "to")
+ return;
+
+ ObjectNodeInstance::setPropertyVariant(name, value);
+}
+
+QmlTransition *QmlTransitionNodeInstance::qmlTransition() const
+{
+ Q_ASSERT(qobject_cast<QmlTransition*>(object()));
+ return static_cast<QmlTransition*>(object());
+}
+}
+}
diff --git a/src/plugins/qmldesigner/core/instances/qmltransitionnodeinstance.h b/src/plugins/qmldesigner/core/instances/qmltransitionnodeinstance.h
new file mode 100644
index 0000000000..4202549efa
--- /dev/null
+++ b/src/plugins/qmldesigner/core/instances/qmltransitionnodeinstance.h
@@ -0,0 +1,60 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef QMLTRANSITIONNODEINSTANCE_H
+#define QMLTRANSITIONNODEINSTANCE_H
+
+#include "objectnodeinstance.h"
+
+class QmlTransition;
+
+namespace QmlDesigner {
+namespace Internal {
+
+class QmlTransitionNodeInstance : public ObjectNodeInstance
+{
+public:
+ typedef QSharedPointer<QmlTransitionNodeInstance> Pointer;
+ typedef QWeakPointer<QmlTransitionNodeInstance> WeakPointer;
+
+ static Pointer create(const NodeMetaInfo &metaInfo, QmlContext *context, QObject *objectToBeWrapped);
+
+ void setPropertyVariant(const QString &name, const QVariant &value);
+
+ bool isTransition() const;
+
+protected:
+ QmlTransition *qmlTransition() const;
+
+private:
+ QmlTransitionNodeInstance(QmlTransition *transition);
+};
+}
+}
+#endif // QMLTRANSITIONNODEINSTANCE_H
diff --git a/src/plugins/qmldesigner/core/instances/qmlviewnodeinstance.cpp b/src/plugins/qmldesigner/core/instances/qmlviewnodeinstance.cpp
new file mode 100644
index 0000000000..ca8b50b716
--- /dev/null
+++ b/src/plugins/qmldesigner/core/instances/qmlviewnodeinstance.cpp
@@ -0,0 +1,88 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "qmlviewnodeinstance.h"
+
+
+#include <QmlMetaType>
+#include <QmlView>
+#include <QmlGraphicsItem>
+
+#include <invalidnodeinstanceexception.h>
+
+namespace QmlDesigner {
+namespace Internal {
+
+QmlViewNodeInstance::QmlViewNodeInstance(QmlView *view)
+ : GraphicsViewNodeInstance(view)
+{
+}
+
+
+QmlViewNodeInstance::Pointer QmlViewNodeInstance::create(const NodeMetaInfo &nodeMetaInfo, QmlContext *context, QObject *objectToBeWrapped)
+{
+ QObject *object = 0;
+ if (objectToBeWrapped)
+ object = objectToBeWrapped;
+ else
+ createObject(nodeMetaInfo, context);
+
+ QmlView* view = qobject_cast<QmlView*>(object);
+ if (view == 0)
+ throw InvalidNodeInstanceException(__LINE__, __FUNCTION__, __FILE__);
+
+ Pointer instance(new QmlViewNodeInstance(view));
+
+ if (objectToBeWrapped)
+ instance->setDeleteHeldInstance(false); // the object isn't owned
+
+ instance->populateResetValueHash();
+
+ return instance;
+}
+
+QmlView* QmlViewNodeInstance::view() const
+{
+ QmlView* view = qobject_cast<QmlView*>(widget());
+ Q_ASSERT(view);
+ return view;
+}
+
+bool QmlViewNodeInstance::isQmlView() const
+{
+ return true;
+}
+
+void QmlViewNodeInstance::addItem(QmlGraphicsItem *item)
+{
+ item->setParent(view()->root());
+}
+
+}
+}
diff --git a/src/plugins/qmldesigner/core/instances/qmlviewnodeinstance.h b/src/plugins/qmldesigner/core/instances/qmlviewnodeinstance.h
new file mode 100644
index 0000000000..42bfee1f42
--- /dev/null
+++ b/src/plugins/qmldesigner/core/instances/qmlviewnodeinstance.h
@@ -0,0 +1,61 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef QMLVIEWNODEINSTANCE_H
+#define QMLVIEWNODEINSTANCE_H
+
+#include <QWeakPointer>
+#include <QmlView>
+
+#include "graphicsviewnodeinstance.h"
+
+namespace QmlDesigner {
+namespace Internal {
+
+class QmlViewNodeInstance : public GraphicsViewNodeInstance
+{
+public:
+ typedef QSharedPointer<QmlViewNodeInstance> Pointer;
+ typedef QWeakPointer<QmlViewNodeInstance> WeakPointer;
+
+ static Pointer create(const NodeMetaInfo &metaInfo, QmlContext *context, QObject *objectToBeWrapped);
+
+ bool isQmlView() const;
+
+ void addItem(QmlGraphicsItem *item);
+
+protected:
+ QmlViewNodeInstance(QmlView *view);
+
+ QmlView* view() const;
+};
+
+}
+}
+#endif // QMLVIEWNODEINSTANCE_H
diff --git a/src/plugins/qmldesigner/core/instances/widgetnodeinstance.cpp b/src/plugins/qmldesigner/core/instances/widgetnodeinstance.cpp
new file mode 100644
index 0000000000..71863afa71
--- /dev/null
+++ b/src/plugins/qmldesigner/core/instances/widgetnodeinstance.cpp
@@ -0,0 +1,154 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "widgetnodeinstance.h"
+
+#include <QmlMetaType>
+
+#include "proxywidgetnodeinstance.h"
+#include <invalidnodeinstanceexception.h>
+
+#include <propertymetainfo.h>
+
+namespace QmlDesigner {
+namespace Internal {
+
+WidgetNodeInstance::WidgetNodeInstance(QWidget* widget)
+ : ObjectNodeInstance(widget)
+{
+}
+
+WidgetNodeInstance::~WidgetNodeInstance()
+{
+}
+
+WidgetNodeInstance::Pointer WidgetNodeInstance::create(const NodeMetaInfo &nodeMetaInfo, QmlContext *context, QObject *objectToBeWrapped)
+{
+ QObject *object = 0;
+ if (objectToBeWrapped)
+ object = objectToBeWrapped;
+ else
+ object = createObject(nodeMetaInfo, context);
+
+
+ QWidget* widget = qobject_cast<QWidget*>(object);
+ if (widget == 0)
+ throw InvalidNodeInstanceException(__LINE__, __FUNCTION__, __FILE__);
+
+ Pointer instance(new WidgetNodeInstance(widget));
+
+ if (objectToBeWrapped)
+ instance->setDeleteHeldInstance(false); // the object isn't owned
+
+ instance->populateResetValueHash();
+
+ return instance;
+}
+
+void WidgetNodeInstance::paint(QPainter *painter) const
+{
+ Q_ASSERT(widget());
+
+ QWidget::RenderFlags flags;
+ if (!widget()->children().isEmpty())
+ flags = QWidget::DrawChildren;
+ else
+ flags = 0;
+
+ if (isTopLevel() && modelNode().isValid())
+ widget()->render(painter, QPoint(), QRegion(), QWidget::DrawWindowBackground);
+ else
+ widget()->render(painter, QPoint(), QRegion(), flags);
+}
+
+bool WidgetNodeInstance::isTopLevel() const
+{
+ Q_ASSERT(widget());
+ return widget()->isTopLevel();
+}
+
+QWidget* WidgetNodeInstance::widget() const
+{
+ return static_cast<QWidget*>(object());
+}
+
+bool WidgetNodeInstance::isWidget() const
+{
+ return true;
+}
+
+QRectF WidgetNodeInstance::boundingRect() const
+{
+ return widget()->frameGeometry();
+}
+
+void WidgetNodeInstance::setPropertyVariant(const QString &name, const QVariant &value)
+{
+ if (name == "x")
+ widget()->move(value.toInt(), widget()->y());
+ else if (name == "y")
+ widget()->move(widget()->x(), value.toInt());
+ else if (name == "width")
+ widget()->resize(value.toInt(), widget()->height());
+ else if (name == "height")
+ widget()->resize(widget()->width(), value.toInt());
+ else {
+ widget()->setProperty(name.toLatin1(), value);
+ }
+
+ widget()->update();
+}
+
+QVariant WidgetNodeInstance::property(const QString &name) const
+{
+ return widget()->property(name.toLatin1());
+}
+
+bool WidgetNodeInstance::isVisible() const
+{
+ return widget()->isVisible();
+}
+
+void WidgetNodeInstance::setVisible(bool isVisible)
+{
+ widget()->setVisible(isVisible);
+}
+
+QPointF WidgetNodeInstance::position() const
+{
+ return widget()->pos();
+}
+
+QSizeF WidgetNodeInstance::size() const
+{
+ return widget()->size();
+}
+
+}
+}
diff --git a/src/plugins/qmldesigner/core/instances/widgetnodeinstance.h b/src/plugins/qmldesigner/core/instances/widgetnodeinstance.h
new file mode 100644
index 0000000000..88c6a6ced1
--- /dev/null
+++ b/src/plugins/qmldesigner/core/instances/widgetnodeinstance.h
@@ -0,0 +1,75 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef WIDGETNODEINSTANCE_H
+#define WIDGETNODEINSTANCE_H
+
+#include "objectnodeinstance.h"
+#include <QWeakPointer>
+
+namespace QmlDesigner {
+namespace Internal {
+
+class WidgetNodeInstance : public ObjectNodeInstance
+{
+public:
+ ~WidgetNodeInstance();
+ typedef QSharedPointer<WidgetNodeInstance> Pointer;
+ typedef QWeakPointer<WidgetNodeInstance> WeakPointer;
+
+ static Pointer create(const NodeMetaInfo &metaInfo, QmlContext *context, QObject *objectToBeWrapped);
+
+ void paint(QPainter *painter) const;
+
+ bool isTopLevel() const;
+
+ bool isWidget() const;
+
+ QRectF boundingRect() const;
+ QPointF position() const;
+ QSizeF size() const;
+
+ void setPropertyVariant(const QString &name, const QVariant &value);
+ QVariant property(const QString &name) const;
+
+ bool isVisible() const;
+ void setVisible(bool isVisible);
+
+ QWidget *widget() const;
+
+ void updateProperties();
+
+protected:
+ WidgetNodeInstance(QWidget* widget);
+
+};
+
+}
+}
+#endif // WIDGETNODEINSTANCE_H
diff --git a/src/plugins/qmldesigner/core/iwidgetplugin.pri b/src/plugins/qmldesigner/core/iwidgetplugin.pri
new file mode 100644
index 0000000000..8dceea3244
--- /dev/null
+++ b/src/plugins/qmldesigner/core/iwidgetplugin.pri
@@ -0,0 +1 @@
+INCLUDEPATH += $$PWD/include
diff --git a/src/plugins/qmldesigner/core/metainfo/enumeratormetainfo.cpp b/src/plugins/qmldesigner/core/metainfo/enumeratormetainfo.cpp
new file mode 100644
index 0000000000..35924bc30f
--- /dev/null
+++ b/src/plugins/qmldesigner/core/metainfo/enumeratormetainfo.cpp
@@ -0,0 +1,153 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "enumeratormetainfo.h"
+
+#include <QSharedData>
+#include <QString>
+#include <QMap>
+#include <QtDebug>
+
+namespace QmlDesigner {
+
+namespace Internal {
+
+class EnumeratorMetaInfoData : public QSharedData
+{
+public:
+ QString name;
+ QString scope;
+ bool isFlagType;
+ bool isValid;
+ QMap<QString, int> elements;
+};
+
+}
+
+/*!
+\class QmlDesigner::EnumeratorMetaInfo
+\ingroup CoreModel
+\brief The EnumeratorMetaInfo class provides meta information about an enumerator type.
+
+TODO
+
+\see QmlDesigner::MetaInfo, QmlDesigner::NodeMetaInfo, QmlDesigner::PropertyMetaInfo
+*/
+
+EnumeratorMetaInfo::EnumeratorMetaInfo()
+ : m_data(new Internal::EnumeratorMetaInfoData)
+{
+ m_data->isFlagType = false;
+ m_data->isValid = false;
+}
+
+EnumeratorMetaInfo::~EnumeratorMetaInfo()
+{}
+
+EnumeratorMetaInfo::EnumeratorMetaInfo(const EnumeratorMetaInfo &other)
+ : m_data(other.m_data)
+{
+}
+
+EnumeratorMetaInfo& EnumeratorMetaInfo::operator=(const EnumeratorMetaInfo &other)
+{
+ if (this !=&other)
+ m_data = other.m_data;
+
+ return *this;
+}
+
+QString EnumeratorMetaInfo::name() const
+{
+ return m_data->name;
+}
+
+QString EnumeratorMetaInfo::scope() const
+{
+ return m_data->scope;
+}
+
+bool EnumeratorMetaInfo::isValid() const
+{
+ return m_data->isValid;
+}
+
+QString EnumeratorMetaInfo::scopeAndName(const QString &combiner) const
+{
+ return m_data->scope + combiner + m_data->name;
+}
+
+QList<QString> EnumeratorMetaInfo::elementNames() const
+{
+ return m_data->elements.keys();
+}
+
+int EnumeratorMetaInfo::elementValue(const QString &enumeratorName) const
+{
+ QString possibleScope = scope();
+ if (!possibleScope.isEmpty())
+ possibleScope.append("::");
+ QString unscoped = enumeratorName;
+ unscoped.remove(possibleScope);
+ return m_data->elements.value(unscoped, -1);
+}
+
+void EnumeratorMetaInfo::setScope(const QString &scope)
+{
+ Q_ASSERT(!scope.isEmpty());
+ m_data->scope = scope;
+}
+
+void EnumeratorMetaInfo::setName(const QString &name)
+{
+ Q_ASSERT(!name.isEmpty());
+ m_data->name = name;
+}
+
+void EnumeratorMetaInfo::addElement(const QString &enumeratorName, int enumeratorValue)
+{
+ m_data->elements.insert(enumeratorName, enumeratorValue);
+}
+
+bool EnumeratorMetaInfo::isFlagType() const
+{
+ return m_data->isFlagType;
+}
+
+void EnumeratorMetaInfo::setIsFlagType(bool isFlagType)
+{
+ m_data->isFlagType = isFlagType;
+}
+
+void EnumeratorMetaInfo::setValid(bool valid)
+{
+ m_data->isValid = valid;
+}
+
+}
diff --git a/src/plugins/qmldesigner/core/metainfo/gui.metainfo b/src/plugins/qmldesigner/core/metainfo/gui.metainfo
new file mode 100644
index 0000000000..7aa8673171
--- /dev/null
+++ b/src/plugins/qmldesigner/core/metainfo/gui.metainfo
@@ -0,0 +1,184 @@
+<!-- Metadata that is general to Qt and cannot be put into a separate plugin -->
+<metainfo>
+ <enumerator name="Orientation" scope="Qt">
+ <element name="Horizontal" value="1" />
+ <element name="Vertical" value="2" />
+ </enumerator>
+ <enumerator name="ContextMenuPolicy" scope="Qt">
+ <element name="DefaultContextMenu" value="1" />
+ <element name="PreventContextMenu" value="4" />
+ <element name="ActionsContextMenu" value="2" />
+ <element name="NoContextMenu" value="0" />
+ <element name="CustomContextMenu" value="3" />
+ </enumerator>
+ <enumerator name="LayoutDirection" scope="Qt">
+ <element name="RightToLeft" value="1" />
+ <element name="LeftToRight" value="0" />
+ </enumerator>
+ <enumerator name="ArrowType" scope="Qt">
+ <element name="RightArrow" value="4" />
+ <element name="NoArrow" value="0" />
+ <element name="UpArrow" value="1" />
+ <element name="DownArrow" value="2" />
+ <element name="LeftArrow" value="3" />
+ </enumerator>
+ <enumerator name="PenStyle" scope="Qt">
+ <element name="DashLine" value="2" />
+ <element name="NoPen" value="0" />
+ <element name="DashDotLine" value="4" />
+ <element name="DashDotDotLine" value="5" />
+ <element name="SolidLine" value="1" />
+ <element name="DotLine" value="3" />
+ <element name="CustomDashLine" value="6" />
+ </enumerator>
+ <enumerator name="CaseSensitivity" scope="Qt">
+ <element name="CaseSensitive" value="1" />
+ <element name="CaseInsensitive" value="0" />
+ </enumerator>
+ <enumerator name="WritingSystem" scope="QFontDatabase">
+ <element name="Thaana" value="8" />
+ <element name="Telugu" value="15" />
+ <element name="Cyrillic" value="3" />
+ <element name="Oriya" value="13" />
+ <element name="Gujarati" value="12" />
+ <element name="Other" value="30" />
+ <element name="Any" value="0" />
+ <element name="Korean" value="28" />
+ <element name="Khmer" value="24" />
+ <element name="Latin" value="1" />
+ <element name="Georgian" value="23" />
+ <element name="Vietnamese" value="29" />
+ <element name="TraditionalChinese" value="26" />
+ <element name="Armenian" value="4" />
+ <element name="Devanagari" value="9" />
+ <element name="Thai" value="19" />
+ <element name="Tibetan" value="21" />
+ <element name="Bengali" value="10" />
+ <element name="Symbol" value="30" />
+ <element name="WritingSystemsCount" value="33" />
+ <element name="Greek" value="2" />
+ <element name="Lao" value="20" />
+ <element name="Gurmukhi" value="11" />
+ <element name="Malayalam" value="17" />
+ <element name="Ogham" value="31" />
+ <element name="Myanmar" value="22" />
+ <element name="Tamil" value="14" />
+ <element name="Japanese" value="27" />
+ <element name="SimplifiedChinese" value="25" />
+ <element name="Kannada" value="16" />
+ <element name="Syriac" value="7" />
+ <element name="Runic" value="32" />
+ <element name="Hebrew" value="5" />
+ <element name="Arabic" value="6" />
+ <element name="Sinhala" value="18" />
+ </enumerator>
+ <enumerator name="ToolButtonStyle" scope="Qt">
+ <element name="ToolButtonIconOnly" value="0" />
+ <element name="ToolButtonTextBesideIcon" value="2" />
+ <element name="ToolButtonTextOnly" value="1" />
+ <element name="ToolButtonTextUnderIcon" value="3" />
+ </enumerator>
+ <enumerator name="ItemSelectionMode" scope="Qt">
+ <element name="ContainsItemBoundingRect" value="2" />
+ <element name="IntersectsItemBoundingRect" value="3" />
+ <element name="ContainsItemShape" value="0" />
+ <element name="IntersectsItemShape" value="1" />
+ </enumerator>
+ <enumerator name="TextElideMode" scope="Qt">
+ <element name="ElideMiddle" value="2" />
+ <element name="ElideRight" value="1" />
+ <element name="ElideNone" value="3" />
+ <element name="ElideLeft" value="0" />
+ </enumerator>
+ <enumerator name="TimeSpec" scope="Qt">
+ <element name="OffsetFromUTC" value="2" />
+ <element name="UTC" value="1" />
+ <element name="LocalTime" value="0" />
+ </enumerator>
+ <enumerator name="FocusPolicy" scope="Qt">
+ <element name="StrongFocus" value="11" />
+ <element name="WheelFocus" value="15" />
+ <element name="ClickFocus" value="2" />
+ <element name="TabFocus" value="1" />
+ <element name="NoFocus" value="0" />
+ </enumerator>
+ <enumerator name="ScrollBarPolicy" scope="Qt">
+ <element name="ScrollBarAsNeeded" value="0" />
+ <element name="ScrollBarAlwaysOff" value="1" />
+ <element name="ScrollBarAlwaysOn" value="2" />
+ </enumerator>
+ <enumerator name="TextFormat" scope="Qt">
+ <element name="PlainText" value="0" />
+ <element name="AutoText" value="2" />
+ <element name="LogText" value="3" />
+ <element name="RichText" value="1" />
+ </enumerator>
+ <enumerator name="DayOfWeek" scope="Qt">
+ <element name="Monday" value="1" />
+ <element name="Tuesday" value="2" />
+ <element name="Friday" value="5" />
+ <element name="Wednesday" value="3" />
+ <element name="Thursday" value="4" />
+ <element name="Sunday" value="7" />
+ <element name="Saturday" value="6" />
+ </enumerator>
+ <enumerator name="WindowModality" scope="Qt">
+ <element name="WindowModal" value="1" />
+ <element name="NonModal" value="0" />
+ <element name="ApplicationModal" value="2" />
+ </enumerator>
+ <flag name="Alignment" scope="Qt">
+ <element name="AlignLeft" value="1" />
+ <element name="AlignTrailing" value="2" />
+ <element name="AlignAbsolute" value="16" />
+ <element name="AlignHCenter" value="4" />
+ <element name="AlignCenter" value="132" />
+ <element name="AlignJustify" value="8" />
+ <element name="AlignHorizontal_Mask" value="31" />
+ <element name="AlignTop" value="32" />
+ <element name="AlignRight" value="2" />
+ <element name="AlignLeading" value="1" />
+ <element name="AlignVCenter" value="128" />
+ <element name="AlignBottom" value="64" />
+ <element name="AlignVertical_Mask" value="224" />
+ </flag>
+ <flag name="DockWidgetAreas" scope="Qt">
+ <element name="AllDockWidgetAreas" value="15" />
+ <element name="LeftDockWidgetArea" value="1" />
+ <element name="DockWidgetArea_Mask" value="15" />
+ <element name="NoDockWidgetArea" value="0" />
+ <element name="TopDockWidgetArea" value="4" />
+ <element name="RightDockWidgetArea" value="2" />
+ <element name="BottomDockWidgetArea" value="8" />
+ </flag>
+ <flag name="ToolBarAreas" scope="Qt">
+ <element name="RightToolBarArea" value="2" />
+ <element name="TopToolBarArea" value="4" />
+ <element name="ToolBarArea_Mask" value="15" />
+ <element name="NoToolBarArea" value="0" />
+ <element name="LeftToolBarArea" value="1" />
+ <element name="AllToolBarAreas" value="15" />
+ <element name="BottomToolBarArea" value="8" />
+ </flag>
+ <flag name="RenderHints" scope="QPainter">
+ <element name="Antialiasing" value="1" />
+ <element name="TextAntialiasing" value="2" />
+ <element name="SmoothPixmapTransform" value="4" />
+ <element name="HighQualityAntialiasing" value="8" />
+ <element name="NonCosmeticDefaultPen" value="16" />
+ </flag>
+ <flag name="TextInteractionFlags" scope="Qt">
+ <element name="TextEditable" value="16" />
+ <element name="TextSelectableByKeyboard" value="2" />
+ <element name="NoTextInteraction" value="0" />
+ <element name="TextSelectableByMouse" value="1" />
+ <element name="TextBrowserInteraction" value="13" />
+ <element name="LinksAccessibleByKeyboard" value="8" />
+ <element name="LinksAccessibleByMouse" value="4" />
+ <element name="TextEditorInteraction" value="19" />
+ </flag>
+
+ <node name="Object">
+ <property index="0" isEnumType="False" isFlagType="False" isReadable="True" isResettable="False" isWritable="True" name="objectName" type="QString" showInPropertyEditor="true"/>
+ </node>
+</metainfo>
diff --git a/src/plugins/qmldesigner/core/metainfo/itemlibraryinfo.cpp b/src/plugins/qmldesigner/core/metainfo/itemlibraryinfo.cpp
new file mode 100644
index 0000000000..e7981e99a8
--- /dev/null
+++ b/src/plugins/qmldesigner/core/metainfo/itemlibraryinfo.cpp
@@ -0,0 +1,208 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "itemlibraryinfo.h"
+#include "model/internalproperty.h"
+
+#include <QSharedData>
+#include <QString>
+#include <QList>
+#include <QtDebug>
+#include <QIcon>
+
+namespace QmlDesigner {
+
+namespace Internal {
+
+class ItemLibraryInfoData : public QSharedData
+{
+public:
+ ItemLibraryInfoData() : majorVersion(-1), minorVersion(-1)
+ { }
+ QString name;
+ QString typeName;
+ QString category;
+ int majorVersion;
+ int minorVersion;
+ QIcon icon;
+ QIcon dragIcon;
+ QList<PropertyContainer> properties;
+ QString qml;
+};
+}
+
+ItemLibraryInfo::ItemLibraryInfo(const ItemLibraryInfo &other)
+ : m_data(other.m_data)
+{
+}
+
+ItemLibraryInfo& ItemLibraryInfo::operator=(const ItemLibraryInfo &other)
+{
+ if (this !=&other)
+ m_data = other.m_data;
+
+ return *this;
+}
+
+void ItemLibraryInfo::setDragIcon(const QIcon &icon)
+{
+ m_data->dragIcon = icon;
+}
+
+QIcon ItemLibraryInfo::dragIcon() const
+{
+ return m_data->dragIcon;
+}
+
+void ItemLibraryInfo::addProperty(const Property &property)
+{
+ m_data->properties.append(property);
+}
+
+QList<ItemLibraryInfo::Property> ItemLibraryInfo::properties() const
+{
+ return m_data->properties;
+}
+
+ItemLibraryInfo::ItemLibraryInfo() : m_data(new Internal::ItemLibraryInfoData)
+{
+ m_data->name = QString();
+}
+
+ItemLibraryInfo::~ItemLibraryInfo()
+{
+}
+
+QString ItemLibraryInfo::name() const
+{
+ return m_data->name;
+}
+
+QString ItemLibraryInfo::typeName() const
+{
+ return m_data->typeName;
+}
+
+QString ItemLibraryInfo::qml() const
+{
+ return m_data->qml;
+}
+
+int ItemLibraryInfo::majorVersion() const
+{
+ return m_data->majorVersion;
+}
+
+int ItemLibraryInfo::minorVersion() const
+{
+ return m_data->minorVersion;
+}
+
+QString ItemLibraryInfo::category() const
+{
+ return m_data->category;
+}
+
+void ItemLibraryInfo::setCategory(const QString &category)
+{
+ m_data->category = category;
+}
+
+QIcon ItemLibraryInfo::icon() const
+{
+ return m_data->icon;
+}
+
+void ItemLibraryInfo::setName(const QString &name)
+{
+ m_data->name = name;
+}
+
+void ItemLibraryInfo::setTypeName(const QString &typeName)
+{
+ m_data->typeName = typeName;
+}
+
+void ItemLibraryInfo::setIcon(const QIcon &icon)
+{
+ m_data->icon = icon;
+}
+
+void ItemLibraryInfo::setMajorVersion(int majorVersion)
+{
+ m_data->majorVersion = majorVersion;
+}
+
+void ItemLibraryInfo::setMinorVersion(int minorVersion)
+{
+ m_data->minorVersion = minorVersion;
+}
+
+void ItemLibraryInfo::setQml(const QString &qml)
+{
+ m_data->qml = qml;
+}
+
+void ItemLibraryInfo::addProperty(QString &name, QString &type, QString &value)
+{
+ Property property;
+ property.set(name, type, value);
+ addProperty(property);
+}
+
+QDataStream& operator<<(QDataStream& stream, const ItemLibraryInfo& itemLibraryInfo)
+{
+ stream << itemLibraryInfo.name();
+ stream << itemLibraryInfo.typeName();
+ stream << itemLibraryInfo.majorVersion();
+ stream << itemLibraryInfo.minorVersion();
+ stream << itemLibraryInfo.icon();
+ stream << itemLibraryInfo.category();
+ stream << itemLibraryInfo.dragIcon();
+ stream << itemLibraryInfo.m_data->properties;
+
+ return stream;
+}
+
+QDataStream& operator>>(QDataStream& stream, ItemLibraryInfo& itemLibraryInfo)
+{
+ stream >> itemLibraryInfo.m_data->name;
+ stream >> itemLibraryInfo.m_data->typeName;
+ stream >> itemLibraryInfo.m_data->majorVersion;
+ stream >> itemLibraryInfo.m_data->minorVersion;
+ stream >> itemLibraryInfo.m_data->icon;
+ stream >> itemLibraryInfo.m_data->category;
+ stream >> itemLibraryInfo.m_data->dragIcon;
+ stream >> itemLibraryInfo.m_data->properties;
+
+ return stream;
+}
+
+
+}
diff --git a/src/plugins/qmldesigner/core/metainfo/metainfo.cpp b/src/plugins/qmldesigner/core/metainfo/metainfo.cpp
new file mode 100644
index 0000000000..71448ab336
--- /dev/null
+++ b/src/plugins/qmldesigner/core/metainfo/metainfo.cpp
@@ -0,0 +1,678 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "metainfo.h"
+
+#include "abstractproperty.h"
+#include "modelnode.h"
+#include "invalidmodelnodeexception.h"
+#include "invalidargumentexception.h"
+#include "propertymetainfo.h"
+#include "metainfoparser.h"
+#include "iwidgetplugin.h"
+
+#include "model/variantparser.h"
+#include "pluginmanager/widgetpluginmanager.h"
+
+#include <QtDebug>
+#include <QPair>
+#include <QtAlgorithms>
+#include <QMetaProperty>
+#include <QmlMetaType>
+#include <private/qmlgraphicsanchors_p.h>
+
+enum {
+ debug = false
+};
+
+namespace QmlDesigner {
+namespace Internal {
+
+class MetaInfoPrivate
+{
+ Q_DISABLE_COPY(MetaInfoPrivate)
+public:
+ typedef QSharedPointer<MetaInfoPrivate> Pointer;
+ typedef QWeakPointer<MetaInfoPrivate> WeakPointer;
+
+
+ MetaInfoPrivate(MetaInfo *q);
+ void clear();
+
+ void initialize();
+ void parseQmlTypes();
+ void parseNonQmlTypes();
+ void parseValueTypes();
+ void parseNonQmlClassRecursively(const QMetaObject *qMetaObject);
+ void parseProperties(NodeMetaInfo &nodeMetaInfo, const QMetaObject *qMetaObject) const;
+ void parseClassInfo(NodeMetaInfo &nodeMetaInfo, const QMetaObject *qMetaObject) const;
+
+ QString typeName(const QMetaObject *qMetaObject) const;
+
+ void parseXmlFiles();
+
+ QMultiHash<QString, QString> m_superClassHash; // the list of direct superclasses
+ QHash<QString, NodeMetaInfo> m_nodeMetaInfoHash;
+ QHash<QString, EnumeratorMetaInfo> m_enumeratorMetaInfoHash;
+ QMultiHash<NodeMetaInfo, ItemLibraryInfo> m_itemLibraryInfoHash;
+ QHash<QString, ItemLibraryInfo> m_itemLibraryInfoHashAll;
+ QHash<QString, QString> m_QtTypesToQmlTypes;
+
+ MetaInfo *m_q;
+ bool m_isInitialized;
+};
+
+MetaInfoPrivate::MetaInfoPrivate(MetaInfo *q) :
+ m_q(q),
+ m_isInitialized(false)
+{
+}
+
+void MetaInfoPrivate::clear()
+{
+ m_superClassHash.clear();
+ m_nodeMetaInfoHash.clear();
+ m_enumeratorMetaInfoHash.clear();
+ m_itemLibraryInfoHash.clear();
+ m_itemLibraryInfoHashAll.clear();
+ m_isInitialized = false;
+}
+
+void MetaInfoPrivate::initialize()
+{
+ parseQmlTypes();
+ parseNonQmlTypes();
+ parseValueTypes();
+ parseXmlFiles();
+
+ m_isInitialized = true;
+}
+
+
+
+void MetaInfoPrivate::parseProperties(NodeMetaInfo &nodeMetaInfo, const QMetaObject *qMetaObject) const
+{
+ Q_ASSERT_X(qMetaObject, Q_FUNC_INFO, "invalid QMetaObject");
+ Q_ASSERT_X(nodeMetaInfo.isValid(), Q_FUNC_INFO, "invalid NodeMetaInfo");
+
+ for (int i = qMetaObject->propertyOffset(); i < qMetaObject->propertyCount(); ++i) {
+ QMetaProperty qProperty = qMetaObject->property(i);
+
+ PropertyMetaInfo propertyInfo;
+
+ propertyInfo.setName(QLatin1String(qProperty.name()));
+
+ QString typeName(qProperty.typeName());
+ QString noStar = typeName;
+ bool star = false;
+ while (noStar.contains('*')) {//strip star
+ noStar.chop(1);
+ star = true;
+ }
+ if (m_QtTypesToQmlTypes.contains(noStar)) {
+ typeName = star ? m_QtTypesToQmlTypes.value(noStar) + '*' : m_QtTypesToQmlTypes.value(noStar);
+ //### versions
+ }
+ propertyInfo.setType(typeName);
+ propertyInfo.setValid(true);
+ propertyInfo.setReadable(qProperty.isReadable());
+ propertyInfo.setWritable(qProperty.isWritable());
+ propertyInfo.setResettable(qProperty.isResettable());
+ propertyInfo.setEnumType(qProperty.isEnumType());
+ propertyInfo.setFlagType(qProperty.isFlagType());
+
+ if (propertyInfo.isEnumType()) {
+ EnumeratorMetaInfo enumerator;
+
+ QMetaEnum qEnumerator = qProperty.enumerator();
+ enumerator.setValid(qEnumerator.isValid());
+ enumerator.setIsFlagType(qEnumerator.isFlag());
+ enumerator.setScope(qEnumerator.scope());
+ enumerator.setName(qEnumerator.name());
+ for (int i = 0 ;i < qEnumerator.keyCount(); i++)
+ {
+ enumerator.addElement(qEnumerator.valueToKey(i), i);
+ }
+
+ propertyInfo.setEnumerator(enumerator);
+ }
+
+ nodeMetaInfo.addProperty(propertyInfo);
+ }
+}
+
+void MetaInfoPrivate::parseClassInfo(NodeMetaInfo &nodeMetaInfo, const QMetaObject *qMetaObject) const
+{
+ Q_ASSERT_X(qMetaObject, Q_FUNC_INFO, "invalid QMetaObject");
+ Q_ASSERT_X(nodeMetaInfo.isValid(), Q_FUNC_INFO, "invalid NodeMetaInfo");
+ for (int index = qMetaObject->classInfoCount() - 1 ; index >= 0 ; --index) {
+ QMetaClassInfo classInfo = qMetaObject->classInfo(index);
+ if (QLatin1String(classInfo.name()) == QLatin1String("DefaultProperty")) {
+ nodeMetaInfo.setDefaultProperty(classInfo.value());
+ return;
+ }
+ }
+}
+
+void MetaInfoPrivate::parseNonQmlClassRecursively(const QMetaObject *qMetaObject)
+{
+ Q_ASSERT_X(qMetaObject, Q_FUNC_INFO, "invalid QMetaObject");
+ const QString className = qMetaObject->className();
+ if ( !m_q->hasNodeMetaInfo(className)
+ && !QmlMetaType::qmlTypeNames().contains(typeName(qMetaObject).toAscii()) ) {
+ NodeMetaInfo nodeMetaInfo(*m_q);
+ nodeMetaInfo.setTypeName(typeName(qMetaObject));
+ parseProperties(nodeMetaInfo, qMetaObject);
+ parseClassInfo(nodeMetaInfo, qMetaObject);
+
+ if (debug)
+ qDebug() << "adding non qml type" << className << typeName(qMetaObject) << ", parent type" << typeName(qMetaObject->superClass());
+ m_q->addNodeInfo(nodeMetaInfo, typeName(qMetaObject->superClass()));
+ }
+
+ if (const QMetaObject *superClass = qMetaObject->superClass()) {
+ parseNonQmlClassRecursively(superClass);
+ }
+}
+
+
+QString MetaInfoPrivate::typeName(const QMetaObject *qMetaObject) const
+{
+ if (!qMetaObject)
+ return QString();
+ QString className = qMetaObject->className();
+ if (QmlType *qmlType = QmlMetaType::qmlType(qMetaObject)) {
+ QString qmlClassName(qmlType->qmlTypeName());
+ if (!qmlClassName.isEmpty())
+ className = qmlType->qmlTypeName(); // Ensure that we always use the qml name,
+ // if available.
+ }
+ return className;
+}
+
+void MetaInfoPrivate::parseValueTypes()
+{
+ QStringList valueTypes;
+ //there is no global list of all supported value types
+ valueTypes << "QFont"
+ << "QPoint"
+ << "QPointF"
+ << "QRect"
+ << "QRectF"
+ << "QSize"
+ << "QSizeF"
+ << "QVector3D";
+
+ foreach (const QString &type, valueTypes) {
+ NodeMetaInfo nodeMetaInfo(*m_q);
+ nodeMetaInfo.setTypeName(type);
+ foreach (const QString &propertyName, VariantParser::create(type).properties()) {
+ PropertyMetaInfo propertyInfo;
+ propertyInfo.setName(propertyName);
+ propertyInfo.setType("real");
+ if (type == ("QFont")) {
+ if (propertyName == "bold")
+ propertyInfo.setType("bool");
+ else if (propertyName == "italic")
+ propertyInfo.setType("bool");
+ else if (propertyName == "family")
+ propertyInfo.setType("string");
+ else if (propertyName == "pixelSize")
+ propertyInfo.setType("int");
+ } else if (type == ("QPoint")) {
+ propertyInfo.setType("int");
+ } else if (type == ("QSize")) {
+ propertyInfo.setType("int");
+ } else if (type == ("QRect")) {
+ propertyInfo.setType("int");
+ }
+ propertyInfo.setValid(true);
+ propertyInfo.setReadable(true);
+ propertyInfo.setWritable(true);
+ nodeMetaInfo.addProperty(propertyInfo);
+ }
+ if (debug)
+ qDebug() << "adding value type" << nodeMetaInfo.typeName();
+ m_q->addNodeInfo(nodeMetaInfo, QString());
+ }
+}
+
+void MetaInfoPrivate::parseQmlTypes()
+{
+ foreach (QmlType *qmlType, QmlMetaType::qmlTypes()) {
+ const QString qtTypeName(qmlType->typeName());
+ const QString qmlTypeName(qmlType->qmlTypeName());
+ m_QtTypesToQmlTypes.insert(qtTypeName, qmlTypeName);
+ }
+ foreach (QmlType *qmlType, QmlMetaType::qmlTypes()) {
+ const QMetaObject *qMetaObject = qmlType->metaObject();
+
+ // parseQmlTypes is called iteratively e.g. when plugins are loaded
+ if (m_q->hasNodeMetaInfo(qmlType->qmlTypeName(), qmlType->majorVersion(), qmlType->minorVersion()))
+ continue;
+
+ NodeMetaInfo nodeMetaInfo(*m_q);
+ nodeMetaInfo.setTypeName(qmlType->qmlTypeName());
+ nodeMetaInfo.setMajorVersion(qmlType->majorVersion());
+ nodeMetaInfo.setMinorVersion(qmlType->minorVersion());
+
+ parseProperties(nodeMetaInfo, qMetaObject);
+ parseClassInfo(nodeMetaInfo, qMetaObject);
+
+ QString superTypeName = typeName(qMetaObject->superClass());
+ if (qmlType->baseMetaObject() != qMetaObject) {
+ // type is declared with Q_DECLARE_EXTENDED_TYPE
+ // also parse properties of original type
+ parseProperties(nodeMetaInfo, qmlType->baseMetaObject());
+ superTypeName = typeName(qmlType->baseMetaObject()->superClass());
+ }
+
+ m_q->addNodeInfo(nodeMetaInfo, superTypeName);
+ }
+}
+
+void MetaInfoPrivate::parseNonQmlTypes()
+{
+ foreach (QmlType *qmlType, QmlMetaType::qmlTypes()) {
+ parseNonQmlClassRecursively(qmlType->metaObject());
+ }
+
+ parseNonQmlClassRecursively(&QmlGraphicsAnchors::staticMetaObject);
+}
+
+
+void MetaInfoPrivate::parseXmlFiles()
+{
+ Internal::MetaInfoParser(*m_q).parseFile(":/metainfo/gui.metainfo");
+
+ Internal::WidgetPluginManager pluginManager;
+ foreach (const QString &pluginDir, m_q->s_pluginDirs)
+ pluginManager.addPath(pluginDir);
+ QList<IWidgetPlugin *> widgetPluginList = pluginManager.instances();
+ foreach (IWidgetPlugin *plugin, widgetPluginList) {
+ parseQmlTypes();
+ Internal::MetaInfoParser parser(*m_q);
+ parser.parseFile(plugin->metaInfo());
+ }
+}
+
+} // namespace Internal
+
+using QmlDesigner::Internal::MetaInfoPrivate;
+
+MetaInfo MetaInfo::s_global;
+QStringList MetaInfo::s_pluginDirs;
+
+
+/*!
+\class QmlDesigner::MetaInfo
+\ingroup CoreModel
+\brief The MetaInfo class provides meta information about qml types and properties.
+
+The MetaInfo, NodeMetaInfo, PropertyMetaInfo and EnumeratorMetaInfo
+classes provide information about the (static and dynamic) qml types available in
+a specific model. Just like their Model, ModelNode and AbstractProperty counterparts,
+objects of these classes are handles - that means, they are implicitly shared, and
+should be created on the stack.
+
+The MetaInfo object should always be accessed via the model (see Model::metaInfo()).
+Otherwise types specific to a model (like sub components) might
+be missed.
+
+\see Model::metaInfo(), QmlDesigner::NodeMetaInfo, QmlDesigner::PropertyMetaInfo, QmlDesigner::EnumeratorMetaInfo
+*/
+
+/*!
+ \brief Constructs a copy of the given meta info.
+ */
+MetaInfo::MetaInfo(const MetaInfo &metaInfo) :
+ m_p(metaInfo.m_p)
+{
+}
+
+/*!
+ \brief Creates a meta information object with just the qml types registered statically.
+ You almost always want to use Model::metaInfo() instead!
+
+ You almost certainly want to access the meta information for the model.
+
+ \see Model::metaInfo()
+ */
+MetaInfo::MetaInfo() :
+ m_p(new MetaInfoPrivate(this))
+{
+}
+
+MetaInfo::~MetaInfo()
+{
+}
+
+/*!
+ \brief Assigns other to this meta information and returns a reference to this meta information.
+ */
+MetaInfo& MetaInfo::operator=(const MetaInfo &other)
+{
+ m_p = other.m_p;
+ return *this;
+}
+
+/*!
+ \brief Returns whether a type with the given name is registered in the meta system.
+ */
+bool MetaInfo::hasNodeMetaInfo(const QString &typeName, int /*majorVersion*/, int /*minorVersion*/) const
+{
+ if (m_p->m_nodeMetaInfoHash.contains(typeName))
+ return true;
+ if (!isGlobal())
+ return global().hasNodeMetaInfo(typeName);
+ return false;
+}
+
+/*!
+ \brief Returns meta information for a qml type. An invalid NodeMetaInfo object if the type is unknown.
+ */
+NodeMetaInfo MetaInfo::nodeMetaInfo(const QString &typeName, int /*majorVersion*/, int /*minorVersion*/) const
+{
+ if (m_p->m_nodeMetaInfoHash.contains(typeName))
+ return m_p->m_nodeMetaInfoHash.value(typeName, NodeMetaInfo());
+ if (!isGlobal())
+ return global().nodeMetaInfo(typeName);
+
+ return NodeMetaInfo();
+}
+
+QStringList MetaInfo::superClasses(const QString &className) const
+{
+ QStringList ancestorList = m_p->m_superClassHash.values(className);
+ foreach (const QString &ancestor, ancestorList) {
+ QStringList superClassList = superClasses(ancestor);
+ if (!superClassList.isEmpty())
+ ancestorList += superClassList;
+ }
+ if (!isGlobal())
+ ancestorList += global().superClasses(className);
+ return ancestorList;
+}
+
+QStringList MetaInfo::directSuperClasses(const QString &className) const
+{
+ QStringList directAncestorList = m_p->m_superClassHash.values(className);
+ if (!isGlobal())
+ directAncestorList += global().directSuperClasses(className);
+ return directAncestorList;
+}
+
+QList<NodeMetaInfo> MetaInfo::superClasses(const NodeMetaInfo &nodeInfo) const
+{
+ if (!nodeInfo.isValid()) {
+ Q_ASSERT_X(nodeInfo.isValid(), Q_FUNC_INFO, "Invalid nodeInfo argument");
+ throw InvalidArgumentException(__LINE__, __FUNCTION__, __FILE__, "nodeInfo");
+ }
+
+ QList<NodeMetaInfo> superClassList;
+
+ foreach (const QString &typeName, superClasses(nodeInfo.typeName())) {
+ if (!hasNodeMetaInfo(typeName))
+ continue;
+ const NodeMetaInfo superClass = nodeMetaInfo(typeName);
+ if (!superClassList.contains(superClass))
+ superClassList.append(superClass);
+ }
+ return superClassList;
+}
+
+QList<NodeMetaInfo> MetaInfo::directSuperClasses(const NodeMetaInfo &nodeInfo) const
+{
+ if (!nodeInfo.isValid()) {
+ Q_ASSERT_X(nodeInfo.isValid(), Q_FUNC_INFO, "Invalid nodeInfo argument");
+ throw InvalidArgumentException(__LINE__, __FUNCTION__, __FILE__, "nodeInfo");
+ }
+
+ QList<NodeMetaInfo> superClassList;
+
+ foreach (const QString &typeName, directSuperClasses(nodeInfo.typeName())) {
+ if (!hasNodeMetaInfo(typeName))
+ continue;
+ const NodeMetaInfo superClass = nodeMetaInfo(typeName);
+ if (!superClassList.contains(superClass))
+ superClassList.append(superClass);
+ }
+ return superClassList;
+}
+
+QList<ItemLibraryInfo> MetaInfo::itemLibraryRepresentations(const NodeMetaInfo &nodeMetaInfo) const
+{
+ QList<ItemLibraryInfo> itemLibraryItems = m_p->m_itemLibraryInfoHash.values(nodeMetaInfo);
+ if (!isGlobal())
+ itemLibraryItems += global().itemLibraryRepresentations(nodeMetaInfo);
+ return itemLibraryItems;
+}
+
+ItemLibraryInfo MetaInfo::itemLibraryRepresentation(const QString &name) const
+{
+ if (m_p->m_itemLibraryInfoHashAll.contains(name))
+ return m_p->m_itemLibraryInfoHashAll.value(name);
+ if (!isGlobal())
+ return global().itemLibraryRepresentation(name);
+ return ItemLibraryInfo();
+}
+
+QStringList MetaInfo::itemLibraryItems() const
+{
+ QStringList completeList = m_p->m_nodeMetaInfoHash.keys();
+ QStringList finalList;
+ foreach (const QString &name, completeList) {
+ if (nodeMetaInfo(name).isVisibleToItemLibrary())
+ finalList.append(name);
+ }
+
+ if (!isGlobal())
+ finalList += global().itemLibraryItems();
+
+ return finalList;
+}
+
+/*!
+ \brief Returns whether className is the same type or a type derived from superClassName.
+ */
+bool MetaInfo::isSubclassOf(const QString &className, const QString &superClassName) const
+{
+ return (className == superClassName) || superClasses(className).contains(superClassName);
+}
+
+/*!
+ \brief Returns whether the type of modelNode is the same type or a type derived from superClassName.
+ \throws InvalidModelNode if !modelNode.isValid()
+ */
+bool MetaInfo::isSubclassOf(const ModelNode &modelNode, const QString &superClassName) const
+{
+ if (!modelNode.isValid()) {
+ Q_ASSERT_X(modelNode.isValid(), Q_FUNC_INFO, "Invalid modelNode argument");
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+ }
+ return (modelNode.type() == superClassName) || isSubclassOf(modelNode.type(), superClassName);
+}
+
+/*!
+ \brief Returns whether an enumerator is registered in the meta type system.
+ */
+bool MetaInfo::hasEnumerator(const QString &enumeratorName) const
+{
+ return m_p->m_enumeratorMetaInfoHash.contains(enumeratorName)
+ || (!isGlobal() ? global().hasEnumerator(enumeratorName) : false);
+}
+
+/*!
+ \brief Returns meta information about an enumerator. An invalid EnumeratorMetaInfo object if the enumerator is not known.
+ */
+EnumeratorMetaInfo MetaInfo::enumerator(const QString &enumeratorName) const
+{
+ if (m_p->m_enumeratorMetaInfoHash.contains(enumeratorName))
+ return m_p->m_enumeratorMetaInfoHash.value(enumeratorName);
+ if (!isGlobal())
+ return global().enumerator(enumeratorName);
+ return EnumeratorMetaInfo();
+}
+
+/*!
+ \brief Access to the global meta information object.
+ You almost always want to use Model::metaInfo() instead.
+
+ Internally all meta information objects share this "global" object
+ where static qml type information is stored.
+ */
+MetaInfo MetaInfo::global()
+{
+ if (!s_global.m_p->m_isInitialized) {
+ s_global.m_p = QSharedPointer<MetaInfoPrivate>(new MetaInfoPrivate(&s_global));
+ s_global.m_p->initialize();
+ }
+ return s_global;
+}
+
+/*!
+ \brief Clears the global meta information object.
+
+ This method should be called once on application shutdown to free static data structures.
+ */
+void MetaInfo::clearGlobal()
+{
+ MetaInfo::global().m_p->clear();
+}
+
+void MetaInfo::setPluginPaths(const QStringList &paths)
+{
+ s_pluginDirs = paths;
+}
+
+/*!
+ This bypasses the notifications to the model that the metatype has changed.
+ Use MetaInfo::addNodeInfo() instead
+ */
+void MetaInfo::addSuperClassRelationship(const QString &superClassName, const QString &className)
+{
+ m_p->m_superClassHash.insert(className, superClassName);
+}
+
+void MetaInfo::addNodeInfo(NodeMetaInfo &nodeInfo, const QString &baseType)
+{
+ if (nodeInfo.typeName().isEmpty() || nodeInfo.metaInfo() != *this)
+ throw new InvalidArgumentException(__LINE__, __FUNCTION__, __FILE__, QLatin1String("nodeInfo"));
+
+ if (nodeInfo.typeName() == baseType) // prevent simple recursion
+ throw new InvalidArgumentException(__LINE__, __FUNCTION__, __FILE__, QLatin1String("baseType"));
+
+ m_p->m_nodeMetaInfoHash.insert(nodeInfo.typeName(), nodeInfo);
+
+ if (!baseType.isEmpty()) {
+ m_p->m_superClassHash.insert(nodeInfo.typeName(), baseType);
+ }
+}
+
+void MetaInfo::removeNodeInfo(NodeMetaInfo &info)
+{
+ Q_ASSERT(info.isValid());
+
+ if (m_p->m_nodeMetaInfoHash.contains(info.typeName())) {
+ m_p->m_nodeMetaInfoHash.remove(info.typeName());
+
+ m_p->m_superClassHash.remove(info.typeName());
+ // TODO: Other types might specify type as parent type
+ m_p->m_itemLibraryInfoHash.remove(info);
+ m_p->m_itemLibraryInfoHashAll.remove(info.typeName());
+
+ } else if (!isGlobal()) {
+ global().removeNodeInfo(info);
+ } else {
+ Q_ASSERT_X(0, Q_FUNC_INFO, "Node meta info not in db");
+ }
+
+ info.setInvalid();
+}
+
+void MetaInfo::replaceNodeInfo(NodeMetaInfo & /*oldInfo*/, NodeMetaInfo & /*newInfo*/, const QString & /*baseType*/)
+{
+ // TODO
+}
+
+EnumeratorMetaInfo MetaInfo::addEnumerator(const QString &enumeratorScope, const QString &enumeratorName)
+{
+ Q_ASSERT(!enumeratorName.isEmpty());
+
+ EnumeratorMetaInfo enumeratorMetaInfo;
+ enumeratorMetaInfo.setName(enumeratorName);
+ enumeratorMetaInfo.setScope(enumeratorScope);
+ enumeratorMetaInfo.setIsFlagType(false);
+ enumeratorMetaInfo.setValid(true);
+
+ m_p->m_enumeratorMetaInfoHash.insert(enumeratorMetaInfo.scopeAndName(), enumeratorMetaInfo);
+
+ return enumeratorMetaInfo;
+}
+
+EnumeratorMetaInfo MetaInfo::addFlag(const QString &enumeratorScope, const QString &enumeratorName)
+{
+ Q_ASSERT(!enumeratorName.isEmpty());
+
+ EnumeratorMetaInfo enumeratorMetaInfo;
+ enumeratorMetaInfo.setName(enumeratorName);
+ enumeratorMetaInfo.setScope(enumeratorScope);
+ enumeratorMetaInfo.setIsFlagType(true);
+ m_p->m_enumeratorMetaInfoHash.insert(enumeratorMetaInfo.scopeAndName(), enumeratorMetaInfo);
+
+ return enumeratorMetaInfo;
+}
+
+ItemLibraryInfo MetaInfo::addItemLibraryInfo(const NodeMetaInfo &nodeMetaInfo, const QString &itemLibraryRepresentationName)
+{
+ ItemLibraryInfo itemLibraryInfo;
+ itemLibraryInfo.setName(itemLibraryRepresentationName);
+ itemLibraryInfo.setTypeName(nodeMetaInfo.typeName());
+ itemLibraryInfo.setMajorVersion(nodeMetaInfo.majorVersion());
+ itemLibraryInfo.setMinorVersion(nodeMetaInfo.minorVersion());
+ m_p->m_itemLibraryInfoHash.insert(nodeMetaInfo, itemLibraryInfo);
+ m_p->m_itemLibraryInfoHashAll.insert(itemLibraryRepresentationName, itemLibraryInfo);
+ return itemLibraryInfo;
+}
+
+bool MetaInfo::isGlobal() const
+{
+ return (this->m_p == s_global.m_p);
+}
+
+bool operator==(const MetaInfo &first, const MetaInfo &second)
+{
+ return first.m_p == second.m_p;
+}
+
+bool operator!=(const MetaInfo &first, const MetaInfo &second)
+{
+ return !(first == second);
+}
+} //namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/core/metainfo/metainfoparser.cpp b/src/plugins/qmldesigner/core/metainfo/metainfoparser.cpp
new file mode 100644
index 0000000000..ae1930cbda
--- /dev/null
+++ b/src/plugins/qmldesigner/core/metainfo/metainfoparser.cpp
@@ -0,0 +1,386 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "metainfoparser.h"
+#include "metainfo.h"
+
+#include "propertymetainfo.h"
+#include "model/propertyparser.h"
+#include <QXmlStreamReader>
+#include <QString>
+#include <QFile>
+#include <QtDebug>
+#include <QIcon>
+
+namespace QmlDesigner {
+namespace Internal {
+
+static bool stringToBool(const QString &boolString)
+{
+ QString lowerString(boolString.toLower());
+ if (lowerString == "true" || lowerString == "1")
+ return true;
+
+ return false;
+}
+
+MetaInfoParser::MetaInfoParser(const MetaInfo &metaInfo)
+ : m_metaInfo(metaInfo)
+{
+}
+
+void MetaInfoParser::parseFile(const QString &path)
+{
+ QFile file;
+ file.setFileName(path);
+ if (!file.open(QIODevice::ReadOnly))
+ throw new InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+
+ QXmlStreamReader reader;
+ reader.setDevice(&file);
+
+ while (!reader.atEnd()) {
+ reader.readNext();
+ tokenHandler(reader);
+ }
+ errorHandling(reader, file);
+}
+
+void MetaInfoParser::tokenHandler(QXmlStreamReader &reader)
+{
+ if (reader.isStartElement() && reader.name() == "metainfo")
+ handleMetaInfoElement(reader);
+}
+
+void MetaInfoParser::handleMetaInfoElement(QXmlStreamReader &reader)
+{
+ while (!reader.atEnd() && !(reader.isEndElement() && reader.name() == "metainfo")) {
+ reader.readNext();
+ metaInfoHandler(reader);
+ }
+}
+
+void MetaInfoParser::metaInfoHandler(QXmlStreamReader &reader)
+{
+ if (reader.isStartElement())
+ {
+ if (reader.name() == "enumerator")
+ handleEnumElement(reader);
+
+ if (reader.name() == "flag")
+ handleFlagElement(reader);
+
+ if (reader.name() == "node")
+ handleNodeElement(reader);
+ }
+}
+
+void MetaInfoParser::handleEnumElement(QXmlStreamReader &reader)
+{
+ QString enumeratorName = reader.attributes().value("name").toString();
+ QString enumeratorScope = reader.attributes().value("scope").toString();
+ EnumeratorMetaInfo enumeratorMetaInfo;
+ if (m_metaInfo.hasEnumerator(enumeratorName)) {
+ enumeratorMetaInfo = m_metaInfo.enumerator(enumeratorName);
+ } else {
+ enumeratorMetaInfo = m_metaInfo.addEnumerator(enumeratorScope, enumeratorName);
+ }
+
+ while (!reader.atEnd() && !(reader.isEndElement() && reader.name() == "enumerator")) {
+
+ reader.readNext();
+ handleEnumElementElement(reader, enumeratorMetaInfo);
+ }
+}
+
+void MetaInfoParser::handleFlagElement(QXmlStreamReader &reader)
+{
+ QString enumeratorName = reader.attributes().value("name").toString();
+ QString enumeratorScope = reader.attributes().value("scope").toString();
+ EnumeratorMetaInfo enumeratorMetaInfo = m_metaInfo.addFlag(enumeratorScope, enumeratorName);
+
+ while (!reader.atEnd() && !(reader.isEndElement() && reader.name() == "flag")) {
+
+ reader.readNext();
+ handleFlagElementElement(reader, enumeratorMetaInfo);
+ }
+}
+
+void MetaInfoParser::handleEnumElementElement(QXmlStreamReader &reader, EnumeratorMetaInfo &enumeratorMetaInfo)
+{
+ if (reader.isStartElement() && reader.name() == "element")
+ {
+ bool isIntType;
+ enumeratorMetaInfo.addElement(reader.attributes().value("name").toString(),
+ reader.attributes().value("value").toString().toInt(&isIntType));
+ Q_ASSERT(isIntType);
+ }
+}
+
+void MetaInfoParser::handleFlagElementElement(QXmlStreamReader &reader, EnumeratorMetaInfo &enumeratorMetaInfo)
+{
+ if (reader.isStartElement() && reader.name() == "element")
+ {
+ bool isIntType;
+ enumeratorMetaInfo.addElement(reader.attributes().value("name").toString(),
+ reader.attributes().value("value").toString().toInt(&isIntType));
+ Q_ASSERT(isIntType);
+ }
+}
+
+void MetaInfoParser::handleNodeElement(QXmlStreamReader &reader)
+{
+ const QXmlStreamAttributes attributes = reader.attributes();
+
+ const QString className = attributes.value("name").toString();
+ if (className.isEmpty()) {
+ reader.raiseError("Invalid element 'node' - mandatory attribute 'name' is missing");
+ return;
+ }
+
+ NodeMetaInfo nodeMetaInfo;
+ if (m_metaInfo.hasNodeMetaInfo(className)) {
+ nodeMetaInfo = m_metaInfo.nodeMetaInfo(className);
+ } else {
+ qWarning() << "Metainfo: " << className << " does not exist";
+ while (!reader.atEnd() && !(reader.isEndElement() && reader.name() == "node"))
+ reader.readNext();
+ return;
+ }
+
+ if (attributes.hasAttribute("isContainer")) {
+ const QString isContainer = attributes.value("isContainer").toString();
+ nodeMetaInfo.setIsContainer(stringToBool(isContainer));
+ }
+
+ if (attributes.hasAttribute("showInItemLibrary")) {
+ const QString showInItemLibrary = attributes.value("showInItemLibrary").toString();
+ nodeMetaInfo.setIsVisibleToItemLibrary(stringToBool(showInItemLibrary));
+ }
+
+ if (attributes.hasAttribute("category")) {
+ const QString category = attributes.value("category").toString();
+ nodeMetaInfo.setCategory(category);
+ }
+
+ if (attributes.hasAttribute("icon")) {
+ const QString iconPath = reader.attributes().value("icon").toString();
+ nodeMetaInfo.setIcon(QIcon(iconPath));
+ }
+
+ while (!reader.atEnd() && !(reader.isEndElement() && reader.name() == "node")) {
+ reader.readNext();
+
+ handleNodeInheritElement(reader, className);
+ handleAbstractPropertyElement(reader, nodeMetaInfo);
+ handleAbstractPropertyDefaultValueElement(reader, nodeMetaInfo);
+ handleNodeItemLibraryRepresentationElement(reader, className);
+ }
+}
+
+void MetaInfoParser::handleNodeItemLibraryRepresentationElement(QXmlStreamReader &reader, const QString & className)
+{
+ if (reader.isStartElement() && reader.name() == "itemlibraryrepresentation")
+ {
+ QString name = reader.attributes().value("name").toString();
+ ItemLibraryInfo ItemLibraryInfo = m_metaInfo.addItemLibraryInfo(m_metaInfo.nodeMetaInfo(className), name);
+
+ QString iconPath = reader.attributes().value("icon").toString();
+ if (!iconPath.isEmpty())
+ ItemLibraryInfo.setIcon(QIcon(iconPath));
+
+ while (!reader.atEnd() && !(reader.isEndElement() && reader.name() == "itemlibraryrepresentation")) {
+ reader.readNext();
+ handleItemLibraryInfoPropertyElement(reader, ItemLibraryInfo);
+ }
+ }
+}
+
+void MetaInfoParser::handleNodeInheritElement(QXmlStreamReader &reader, const QString & className)
+{
+ if (reader.isStartElement() && reader.name() == "inherits")
+ {
+ QString superClassName = reader.attributes().value("name").toString();
+ Q_ASSERT(!superClassName.isEmpty());
+ m_metaInfo.addSuperClassRelationship(superClassName, className);
+ reader.readNext();
+ }
+}
+
+void MetaInfoParser::handleItemLibraryInfoPropertyElement(QXmlStreamReader &reader, ItemLibraryInfo &ItemLibraryInfo)
+{
+ if (reader.isStartElement() && reader.name() == "property")
+ {
+ QXmlStreamAttributes attributes(reader.attributes());
+ QString name = attributes.value("name").toString();
+ QString type = attributes.value("type").toString();
+ QString value = attributes.value("value").toString();
+ ItemLibraryInfo.addProperty(name, type, value);
+
+ reader.readNext();
+ }
+}
+
+void MetaInfoParser::handleAbstractPropertyDefaultValueElement(QXmlStreamReader &reader, NodeMetaInfo &nodeMetaInfoArg)
+{
+ if (reader.isStartElement() && reader.name() == "propertyDefaultValue")
+ {
+ const QXmlStreamAttributes attributes(reader.attributes());
+ Q_ASSERT(attributes.hasAttribute("name"));
+ Q_ASSERT(attributes.hasAttribute("type"));
+ Q_ASSERT(attributes.hasAttribute("defaultValue"));
+ const QString propertyName = attributes.value("name").toString();
+ const QString propertyType = attributes.value("type").toString();
+ const QString defaultValueString = attributes.value("defaultValue").toString();
+ QVariant defaultValue = Internal::PropertyParser::read(propertyType,
+ defaultValueString,
+ m_metaInfo);
+
+ QList<NodeMetaInfo> nodeMetaInfoList(nodeMetaInfoArg.superClasses());
+ nodeMetaInfoList.prepend(nodeMetaInfoArg);
+ foreach(const NodeMetaInfo &nodeMetaInfo, nodeMetaInfoList) {
+ if (nodeMetaInfo.hasLocalProperty(propertyName)) {
+ nodeMetaInfo.property(propertyName).setDefaultValue(nodeMetaInfoArg, defaultValue);
+ break;
+ }
+ }
+
+ reader.readNext();
+ }
+}
+
+void MetaInfoParser::handleAbstractPropertyElement(QXmlStreamReader &reader, NodeMetaInfo &nodeMetaInfo)
+{
+ if (reader.isStartElement() && reader.name() == "property")
+ {
+ const QXmlStreamAttributes attributes(reader.attributes());
+
+
+ const QString propertyName = attributes.value("name").toString();
+
+ if (propertyName.isEmpty()) {
+ reader.raiseError("Invalid element 'property' - attribute 'name' is missing or empty");
+ return;
+ }
+
+ PropertyMetaInfo propertyMetaInfo;
+ if (nodeMetaInfo.hasLocalProperty(propertyName)) {
+ propertyMetaInfo = nodeMetaInfo.property(propertyName);
+ } else {
+ propertyMetaInfo.setName(propertyName);
+ }
+ propertyMetaInfo.setValid(true);
+
+ //propertyMetaInfo.setReadable(stringToBool(attributes.value("isReadable").toString()));
+ //propertyMetaInfo.setWritable(stringToBool(attributes.value("isWritable").toString()));
+ //propertyMetaInfo.setResettable(stringToBool(attributes.value("isResetable").toString()));
+ if (attributes.hasAttribute("isEnumType"))
+ propertyMetaInfo.setEnumType(stringToBool(attributes.value("isEnumType").toString()));
+ if (attributes.hasAttribute("isFlagType"))
+ propertyMetaInfo.setFlagType(stringToBool(attributes.value("isFlagType").toString()));
+ if (attributes.hasAttribute("showInPropertyEditor"))
+ propertyMetaInfo.setIsVisibleToPropertyEditor(stringToBool(attributes.value("showInPropertyEditor").toString()));
+
+ if (propertyMetaInfo.isEnumType()) {
+ propertyMetaInfo.setType(QString("%1::%2").arg(attributes.value("enumeratorScope").toString(),
+ attributes.value("enumeratorName").toString()));
+ propertyMetaInfo.setEnumerator(m_metaInfo.enumerator(propertyMetaInfo.type()));
+ } else {
+ const QString type = attributes.value("type").toString();
+ if (type.isEmpty()) {
+ reader.raiseError("Invalid element 'property' - attribute 'type' is missing or empty");
+ return;
+ }
+ propertyMetaInfo.setType(attributes.value("type").toString());
+ }
+
+ if (attributes.hasAttribute("defaultValue")) {
+ QVariant defaultValue = Internal::PropertyParser::read(propertyMetaInfo.type(),
+ attributes.value("defaultValue").toString(),
+ m_metaInfo);
+
+ propertyMetaInfo.setDefaultValue(nodeMetaInfo, defaultValue);
+ }
+
+ nodeMetaInfo.addProperty(propertyMetaInfo);
+
+ reader.readNext();
+ }
+}
+
+void MetaInfoParser::errorHandling(QXmlStreamReader &reader, QFile &file)
+{
+ if (!reader.hasError())
+ return;
+
+ qDebug() << QString("Error at %1, %2:%3: %4")
+ .arg(file.fileName())
+ .arg(reader.lineNumber())
+ .arg(reader.columnNumber())
+ .arg(reader.errorString());
+
+ file.reset();
+
+ QString fileString = file.readAll();
+ QString snippetString;
+ int lineCount = 0;
+ int position = reader.characterOffset();
+ while (position >= 0)
+ {
+ if (fileString[position] == '\n') {
+ if (lineCount > 3)
+ break;
+ lineCount++;
+ }
+
+ snippetString.prepend(fileString[position]);
+ position--;
+ }
+
+ lineCount = 0;
+ position = reader.characterOffset();
+ while (position >= 0)
+ {
+ position++;
+ if (fileString[position] == '\n') {
+ if (lineCount > 1)
+ break;
+ lineCount++;
+ }
+
+ snippetString.append(fileString[position]);
+ }
+
+ qDebug() << snippetString;
+
+}
+
+
+}
+}
diff --git a/src/plugins/qmldesigner/core/metainfo/nodemetainfo.cpp b/src/plugins/qmldesigner/core/metainfo/nodemetainfo.cpp
new file mode 100644
index 0000000000..3498b5c419
--- /dev/null
+++ b/src/plugins/qmldesigner/core/metainfo/nodemetainfo.cpp
@@ -0,0 +1,728 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "nodemetainfo.h"
+#include "model.h"
+#include "widgetqueryview.h"
+#include "nodeinstance.h"
+#include "invalidargumentexception.h"
+
+#include "metainfo.h"
+#include "propertymetainfo.h"
+
+#include <QtCore/QSharedData>
+#include <QtCore/QtDebug>
+#include <QtGui/QIcon>
+#include <QtDeclarative/QmlMetaType>
+#include <QtDeclarative/QmlContext>
+#include <QtDeclarative/QmlEngine>
+#include <QtDeclarative/QmlComponent>
+#include <private/qmlvaluetype_p.h>
+
+namespace QmlDesigner {
+
+namespace Internal {
+
+class NodeMetaInfoData : public QSharedData
+{
+public:
+ typedef enum {
+ No = -1,
+ Unknown = 0,
+ Yes = 1,
+ } TristateBoolean;
+
+public:
+ NodeMetaInfoData(const MetaInfo &metaInfo) :
+ metaInfo(metaInfo),
+ isContainer(false),
+ isVisibleToItemLibrary(false),
+ isFXItem(Unknown),
+ icon(),
+ category("misc")
+ { }
+
+ MetaInfo metaInfo;
+ QString typeName;
+ bool isContainer;
+ bool isVisibleToItemLibrary;
+ TristateBoolean isFXItem;
+ QHash<QString, PropertyMetaInfo> propertyMetaInfoHash;
+ QIcon icon;
+ QString category;
+ QString qmlFile;
+ QString defaultProperty;
+ int majorVersion;
+ int minorVersion;
+};
+
+} // namespace Internal
+
+/*!
+\class QmlDesigner::NodeMetaInfo
+\ingroup CoreModel
+\brief The NodeMetaInfo class provides meta information about a qml type.
+
+A NodeMetaInfo object can be created via ModelNode::metaInfo, or MetaInfo::nodeMetaInfo.
+
+The object can be invalid - you can check this by calling isValid().
+The object is invalid if you ask for meta information for
+an non-existing qml property. Also the node meta info can become invalid
+if the enclosing type is deregistered from the meta type system (e.g.
+a sub component qml file is deleted). Trying to call any accessor methods on an invalid
+NodeMetaInfo object will result in an InvalidMetaInfoException being thrown.
+
+\see QmlDesigner::MetaInfo, QmlDesigner::PropertyMetaInfo, QmlDesigner::EnumeratorMetaInfo
+*/
+
+NodeMetaInfo::NodeMetaInfo()
+ : m_data(0)
+{
+ // create invalid node
+}
+
+NodeMetaInfo::NodeMetaInfo(const MetaInfo &metaInfo)
+ : m_data(new Internal::NodeMetaInfoData(metaInfo))
+{
+}
+
+NodeMetaInfo::~NodeMetaInfo()
+{
+}
+
+/*!
+ \brief Creates a copy of the handle.
+ */
+NodeMetaInfo::NodeMetaInfo(const NodeMetaInfo &other)
+ : m_data(other.m_data)
+{
+}
+
+/*!
+ \brief Copies the handle.
+ */
+NodeMetaInfo &NodeMetaInfo::operator=(const NodeMetaInfo &other)
+{
+ if (this != &other)
+ this->m_data = other.m_data;
+
+ return *this;
+}
+
+/*!
+ \brief Returns whether the meta information system knows about this type.
+ */
+bool NodeMetaInfo::isValid() const
+{
+ return (m_data.data() != 0);
+}
+
+MetaInfo NodeMetaInfo::metaInfo() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+ throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+ }
+
+ return m_data->metaInfo;
+}
+
+/*!
+ \brief Creates an instance of the qml type in the given qml context.
+
+ \throws InvalidArgumentException when the context argument is a null pointer
+ \throws InvalidMetaInfoException if the object is not valid
+ */
+QObject *NodeMetaInfo::createInstance(QmlContext *parentContext) const
+{
+ if (!parentContext) {
+ Q_ASSERT_X(0, Q_FUNC_INFO, "Context cannot be null");
+ throw InvalidArgumentException(__LINE__, __FUNCTION__, __FILE__, "context");
+ }
+
+ if (!isValid()) {
+ Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+ throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+ }
+
+ QObject *object = 0;
+ if (isComponent()) {
+ // qml component
+ // TODO: This is maybe expensive ...
+ QmlComponent component(parentContext->engine(), QUrl::fromLocalFile(m_data->qmlFile));
+ object = component.create(parentContext);
+ } else {
+ // primitive
+ object = QmlMetaType::qmlType(typeName().toAscii(), 4, 6)->create();
+ if (object && parentContext)
+ QmlEngine::setContextForObject(object, new QmlContext(parentContext, object));
+ }
+ return object;
+}
+
+/*!
+ \brief Returns all (direct and indirect) ancestor types.
+
+ \throws InvalidMetaInfoException if the object is not valid
+ */
+QList<NodeMetaInfo> NodeMetaInfo::superClasses() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+ throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+ }
+
+ return m_data->metaInfo.superClasses(*this);
+}
+
+/*!
+ \brief Returns direct ancestor types.
+
+ \throws InvalidMetaInfoException if the object is not valid
+ */
+QList<NodeMetaInfo> NodeMetaInfo::directSuperClasses() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+ throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+ }
+
+ return m_data->metaInfo.directSuperClasses(*this);
+}
+
+/*!
+ \brief Returns meta information for all properties, including properties inherited from base types.
+
+ Returns a Hash with the name of the property as key and property meta information as value. Node
+ In case there are multiple properties with the same name in the hierarchy the property defined
+ in the more concrete subclass is chosen.
+
+ \throws InvalidMetaInfoException if the object is not valid
+ */
+QHash<QString,PropertyMetaInfo> NodeMetaInfo::properties(bool resolveDotSyntax ) const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+ throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+ }
+
+ QHash<QString,PropertyMetaInfo> propertiesInfo;
+ propertiesInfo = m_data->propertyMetaInfoHash;
+ foreach (const NodeMetaInfo &nodeInfo, directSuperClasses()) {
+ QHash<QString,PropertyMetaInfo> superClassProperties = nodeInfo.properties();
+ QHashIterator<QString,PropertyMetaInfo> iter(superClassProperties);
+ while (iter.hasNext()) {
+ iter.next();
+ if (!propertiesInfo.contains(iter.key()))
+ propertiesInfo.insert(iter.key(), iter.value());
+ }
+ }
+ if (resolveDotSyntax) {
+ QHashIterator<QString,PropertyMetaInfo> iter(dotProperties());
+ while (iter.hasNext()) {
+ iter.next();
+ if (!propertiesInfo.contains(iter.key()))
+ propertiesInfo.insert(iter.key(), iter.value());
+ }
+ }
+ return propertiesInfo;
+}
+
+/*!
+ \brief Returns meta information for all dot properties, including properties inherited from base types.
+
+ */
+QHash<QString,PropertyMetaInfo> NodeMetaInfo::dotProperties() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+ throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+ }
+
+ QHash<QString,PropertyMetaInfo> propertiesInfo;
+
+ foreach (const QString &propertyName, properties().keys()) {
+ if (property(propertyName).hasDotSubProperties()) {
+ QString propertyType = property(propertyName).type();
+ if (propertyType.right(1) == "*")
+ propertyType = propertyType.left(propertyType.size() - 1).trimmed();
+ NodeMetaInfo nodeInfo(m_data->metaInfo.nodeMetaInfo(propertyType, majorVersion(), minorVersion()));
+ if (nodeInfo.isValid()) {
+ QHashIterator<QString,PropertyMetaInfo> iter(nodeInfo.properties());
+ while (iter.hasNext()) {
+ iter.next();
+ if (!propertiesInfo.contains(iter.key()) && iter.key() != "objectName")
+ propertiesInfo.insert(propertyName + "." + iter.key(), iter.value());
+ }
+ }
+ }
+ }
+ return propertiesInfo;
+}
+
+/*!
+ \brief Returns meta information for a property. An invalid PropertyMetaInfo object if the given property name is unknown.
+
+ \throws InvalidMetaInfoException if the object is not valid
+ */
+PropertyMetaInfo NodeMetaInfo::property(const QString &propertyName, bool resolveDotSyntax) const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+ throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+ }
+
+ if (resolveDotSyntax && propertyName.contains('.')) {
+ const QStringList nameParts = propertyName.split('.');
+ NodeMetaInfo nodeInfo = *this;
+ const int partCount = nameParts.size();
+ for (int i = 0; i < partCount; ++i) {
+ const QString namePart(nameParts.at(i));
+ const PropertyMetaInfo propInfo = nodeInfo.property(namePart, false);
+
+ if (!propInfo.isValid())
+ break;
+
+ if (i + 1 == partCount)
+ return propInfo;
+
+ QString propertyType = propInfo.type();
+ if (propertyType.right(1) == "*")
+ propertyType = propertyType.left(propertyType.size() - 1).trimmed();
+ nodeInfo = m_data->metaInfo.nodeMetaInfo(propertyType, majorVersion(), minorVersion());
+ if (!nodeInfo.isValid()) {
+ qDebug() << "no type info available for" << propertyType;
+ break;
+ }
+ }
+
+ return PropertyMetaInfo();
+ } else {
+ PropertyMetaInfo propertyMetaInfo;
+
+ if (hasLocalProperty(propertyName)) {
+ propertyMetaInfo = m_data->propertyMetaInfoHash.value(propertyName, PropertyMetaInfo());
+ } else {
+ foreach (const NodeMetaInfo &superTypeMetaInfo, directSuperClasses()) {
+ Q_ASSERT(superTypeMetaInfo.isValid());
+ propertyMetaInfo = superTypeMetaInfo.property(propertyName);
+ if (propertyMetaInfo.isValid())
+ break;
+ }
+ }
+
+ return propertyMetaInfo;
+ }
+}
+
+/*!
+ \brief Returns whether the type has a (not inherited) property.
+
+ \throws InvalidMetaInfoException if the object is not valid
+ */
+bool NodeMetaInfo::hasLocalProperty(const QString &propertyName, bool resolveDotSyntax) const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+ throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+ }
+
+ if (resolveDotSyntax && propertyName.contains('.')) {
+ const QStringList nameParts = propertyName.split('.');
+ NodeMetaInfo nodeInfo = *this;
+ const int partCount = nameParts.size();
+ for (int i = 0; i < partCount; ++i) {
+ QString namePart(nameParts.at(i));
+ const PropertyMetaInfo propInfo = nodeInfo.property(namePart, false);
+
+ if (!propInfo.isValid())
+ break;
+
+ if (i + 1 == partCount)
+ return true;
+
+ QString propertyType = propInfo.type();
+ if (propertyType.right(1) == "*")
+ propertyType = propertyType.left(propertyType.size() - 1).trimmed();
+ nodeInfo = m_data->metaInfo.nodeMetaInfo(propertyType, majorVersion(), minorVersion());
+ if (!nodeInfo.isValid()) {
+ qDebug() << "no type info available for" << propertyType;
+ break;
+ }
+ }
+
+ return false;
+ } else {
+ return m_data->propertyMetaInfoHash.contains(propertyName);
+ }
+}
+
+/*!
+ \brief Returns whether the type has a (inherited or not inherited) property.
+
+ \throws InvalidMetaInfoException if the object is not valid
+ */
+bool NodeMetaInfo::hasProperty(const QString &propertyName, bool resolveDotSyntax) const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+ throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+ }
+
+ if (hasLocalProperty(propertyName, resolveDotSyntax))
+ return true;
+
+ foreach (const NodeMetaInfo &nodeMetaInfo, directSuperClasses()) {
+ if (nodeMetaInfo.hasProperty(propertyName, resolveDotSyntax))
+ return true;
+ }
+
+ return false;
+}
+
+void NodeMetaInfo::addProperty(const PropertyMetaInfo &property)
+{
+ if (!isValid()) {
+ Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+ throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+ }
+ m_data->propertyMetaInfoHash.insert(property.name(), property);
+}
+
+/*!
+ \brief Returns the name of the qml type.
+
+ This is not necessarily the class name: E.g. the class defining "Item" is QmlGraphicsItem.
+
+ \throws InvalidMetaInfoException if the object is not valid
+ */
+QString NodeMetaInfo::typeName() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+ throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+ }
+ return m_data->typeName;
+}
+
+/*!
+ \brief Returns the name of the major number of the qml type.
+
+ \throws InvalidMetaInfoException if the object is not valid
+*/
+int NodeMetaInfo::majorVersion() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+ throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+ }
+
+ return 4;
+}
+
+
+/*!
+ \brief Returns the name of the minor number of the qml type to which the type is used.
+
+ \throws InvalidMetaInfoException if the object is not valid
+*/
+int NodeMetaInfo::minorVersion() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+ throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+ }
+
+ return m_data->minorVersion;
+}
+
+bool NodeMetaInfo::hasDefaultProperty() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+ throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+ }
+
+ return m_data->defaultProperty.isNull();
+}
+
+QString NodeMetaInfo::defaultProperty() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+ throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+ }
+
+ return m_data->defaultProperty;
+}
+
+void NodeMetaInfo::setDefaultProperty(const QString &defaultProperty)
+{
+ if (!isValid()) {
+ Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+ throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+ }
+
+ m_data->defaultProperty = defaultProperty;
+}
+
+void NodeMetaInfo::setMajorVersion(int version)
+{
+ m_data->majorVersion = version;
+}
+
+void NodeMetaInfo::setMinorVersion(int version)
+{
+ m_data->minorVersion = version;
+}
+
+void NodeMetaInfo::setInvalid()
+{
+ if (!isValid())
+ return;
+
+ m_data = 0;
+}
+
+void NodeMetaInfo::setTypeName(const QString &typeName)
+{
+ if (!isValid()) {
+ Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+ throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+ }
+ m_data->typeName = typeName;
+}
+
+uint qHash(const NodeMetaInfo &nodeMetaInfo)
+{
+ if (!nodeMetaInfo.isValid())
+ return 0;
+ return qHash(nodeMetaInfo.m_data->typeName);
+}
+
+bool operator==(const NodeMetaInfo &firstNodeInfo,
+ const NodeMetaInfo &secondNodeInfo)
+{
+ if (!firstNodeInfo.isValid() || !secondNodeInfo.isValid())
+ return false;
+ return firstNodeInfo.m_data->typeName == secondNodeInfo.m_data->typeName;
+}
+
+/*!
+ \brief Returns whether objects of these type can have children.
+
+ \throws InvalidMetaInfoException if the object is not valid
+ */
+bool NodeMetaInfo::isContainer() const
+{
+ // TODO KAI: Is this too generic?
+ if (!isValid()) {
+ Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+ throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+ }
+ return m_data->isContainer;
+}
+
+bool NodeMetaInfo::isVisibleToItemLibrary() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+ throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+ }
+ return m_data->isVisibleToItemLibrary;
+}
+
+void NodeMetaInfo::setIsContainer(bool isContainer)
+{
+ if (!isValid()) {
+ Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+ throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+ }
+ m_data->isContainer = isContainer;
+}
+
+void NodeMetaInfo::setIsVisibleToItemLibrary(bool isVisibleToItemLibrary)
+{
+ if (!isValid()) {
+ Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+ throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+ }
+ m_data->isVisibleToItemLibrary = isVisibleToItemLibrary;
+}
+
+QIcon NodeMetaInfo::icon() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+ throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+ }
+ return m_data->icon;
+}
+
+QString NodeMetaInfo::category() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+ throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+ }
+ return m_data->category;
+}
+
+void NodeMetaInfo::setIcon(const QIcon &icon)
+{
+ if (!isValid()) {
+ Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+ throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+ }
+ m_data->icon = icon;
+}
+
+void NodeMetaInfo::setCategory(const QString &category)
+{
+ if (!isValid()) {
+ Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+ throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+ }
+ m_data->category = category;
+}
+
+/*!
+ \brief Returns whether the type inherits from "QWidget".
+
+ \throws InvalidMetaInfoException if the object is not valid
+ */
+bool NodeMetaInfo::isWidget() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+ throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+ }
+ return m_data->metaInfo.isSubclassOf(m_data->typeName, "Qt/QWidget");
+}
+
+/*!
+ \brief Returns whether the type inherits from "QGraphicsWidget".
+
+ \throws InvalidMetaInfoException if the object is not valid
+ */
+bool NodeMetaInfo::isGraphicsWidget() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+ throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+ }
+ return m_data->metaInfo.isSubclassOf(m_data->typeName, "Qt/QGraphicsWidget");
+}
+
+/*!
+ \brief Returns whether the type inherits from "QGraphicsObject".
+
+ \throws InvalidMetaInfoException if the object is not valid
+ */
+bool NodeMetaInfo::isGraphicsObject() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+ throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+ }
+ return m_data->metaInfo.isSubclassOf(m_data->typeName, "QGraphicsObject");
+}
+
+/*!
+ \brief Returns whether the type inherits from "Item/QmlGraphicsItem".
+
+ \throws InvalidMetaInfoException if the object is not valid
+ */
+bool NodeMetaInfo::isQmlGraphicsItem() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+ throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+ }
+
+ if (m_data->isFXItem == Internal::NodeMetaInfoData::Unknown) {
+ m_data->isFXItem = m_data->metaInfo.isSubclassOf(m_data->typeName, "Qt/Item") ? Internal::NodeMetaInfoData::Yes : Internal::NodeMetaInfoData::No;
+ }
+
+ return m_data->isFXItem == Internal::NodeMetaInfoData::Yes;
+}
+
+bool NodeMetaInfo::isComponent() const
+{
+ return !m_data->qmlFile.isEmpty();
+}
+
+/*!
+ \brief Returns whether the type inherits from a type.
+
+ \throws InvalidMetaInfoException if the object is not valid
+ */
+bool NodeMetaInfo::isSubclassOf(const QString &type, int /*majorVersion*/, int /*minorVersion*/) const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+ throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+ }
+ return m_data->metaInfo.isSubclassOf(m_data->typeName, type);
+}
+
+void NodeMetaInfo::setQmlFile(const QString &filePath)
+{
+ if (!isValid()) {
+ Q_ASSERT_X(0, Q_FUNC_INFO, "Invalid NodeMetaInfo object");
+ throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
+ }
+ m_data->qmlFile = filePath;
+}
+
+//QDataStream& operator<<(QDataStream& stream, const NodeMetaInfo& nodeMetaInfo)
+//{
+// stream << nodeMetaInfo.typeName();
+// stream << nodeMetaInfo.majorVersion();
+// stream << nodeMetaInfo.minorVersionTo();
+//
+// return stream;
+//}
+//
+//QDataStream& operator>>(QDataStream& stream, NodeMetaInfo& nodeMetaInfo)
+//{
+// QString typeName;
+// int minorVersion;
+// int majorVersion;
+//
+// stream >> minorVersion;
+// stream >> majorVersion;
+// stream >> typeName;
+//
+// nodeMetaInfo = MetaInfo::global().nodeMetaInfo(typeName/*, majorVersion ,minorVersion*/);
+//
+// return stream;
+//}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/core/metainfo/propertymetainfo.cpp b/src/plugins/qmldesigner/core/metainfo/propertymetainfo.cpp
new file mode 100644
index 0000000000..5ad6995bff
--- /dev/null
+++ b/src/plugins/qmldesigner/core/metainfo/propertymetainfo.cpp
@@ -0,0 +1,441 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "propertymetainfo.h"
+
+#include <QSharedData>
+
+#include "invalidmetainfoexception.h"
+#include "metainfo.h"
+#include "modelnode.h"
+#include <private/qmlvaluetype_p.h>
+#include <private/qmlstringconverters_p.h>
+
+namespace QmlDesigner {
+
+namespace Internal
+{
+
+class PropertyMetaInfoData : public QSharedData
+{
+public:
+ PropertyMetaInfoData()
+ : QSharedData(),
+ isValid(false),
+ readable(false),
+ writeable(false),
+ resettable(false),
+ enumType(false),
+ flagType(false),
+ isVisible(false)
+ {}
+
+ EnumeratorMetaInfo enumerator;
+
+ QString name;
+ QString type;
+ bool isValid;
+
+ bool readable;
+ bool writeable;
+ bool resettable;
+
+ bool enumType;
+ bool flagType;
+ bool isVisible;
+
+ QHash<QString, QVariant> defaultValueHash;
+};
+
+}
+
+/*!
+\class QmlDesigner::PropertyMetaInfo
+\ingroup CoreModel
+\brief The PropertyMetaInfo class provides meta information about a qml type property.
+
+A PropertyMetaInfo object can be NodeMetaInfo, or AbstractProperty::metaInfo.
+
+The object can be invalid - you can check this by calling isValid().
+The object is invalid if you ask for meta information for
+an non-existing qml type. Also the node meta info can become invalid
+if the type is deregistered from the meta type system (e.g.
+a sub component qml file is deleted). Trying to call any accessor methods on an invalid
+PropertyMetaInfo object will result in an InvalidMetaInfoException being thrown.
+
+
+\see QmlDesigner::MetaInfo, QmlDesigner::NodeMetaInfo, QmlDesigner::EnumeratorMetaInfo
+*/
+
+PropertyMetaInfo::PropertyMetaInfo()
+ : m_data(new Internal::PropertyMetaInfoData)
+{
+}
+
+PropertyMetaInfo::~PropertyMetaInfo()
+{
+}
+
+/*!
+ \brief Creates a copy of the handle.
+ */
+PropertyMetaInfo::PropertyMetaInfo(const PropertyMetaInfo &other)
+ : m_data(other.m_data)
+{
+}
+
+/*!
+ \brief Copies the handle.
+ */
+PropertyMetaInfo &PropertyMetaInfo::operator=(const PropertyMetaInfo &other)
+{
+ if (this != &other)
+ m_data = other.m_data;
+
+ return *this;
+}
+
+/*!
+ \brief Returns whether the meta information system knows about this property.
+ */
+bool PropertyMetaInfo::isValid() const
+{
+ return m_data->isValid;
+}
+
+/*!
+ \brief Returns the name of the property.
+ */
+QString PropertyMetaInfo::name() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(isValid(), Q_FUNC_INFO, "");
+ throw InvalidMetaInfoException(__LINE__, Q_FUNC_INFO, __FILE__);
+ }
+ return m_data->name;
+}
+
+/*!
+ \brief Returns the type name of the property.
+ */
+QString PropertyMetaInfo::type() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(isValid(), Q_FUNC_INFO, "");
+ throw InvalidMetaInfoException(__LINE__, Q_FUNC_INFO, __FILE__);
+ }
+ return m_data->type;
+}
+
+bool PropertyMetaInfo::isVisibleToPropertyEditor() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(isValid(), Q_FUNC_INFO, "");
+ throw InvalidMetaInfoException(__LINE__, Q_FUNC_INFO, __FILE__);
+ }
+ return m_data->isVisible;
+}
+
+void PropertyMetaInfo::setIsVisibleToPropertyEditor(bool isVisible)
+{
+ m_data->isVisible = isVisible;
+}
+
+/*!
+ \brief Returns the QVariant type of the property.
+ */
+QVariant::Type PropertyMetaInfo::variantTypeId() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(isValid(), Q_FUNC_INFO, "");
+ throw InvalidMetaInfoException(__LINE__, Q_FUNC_INFO, __FILE__);
+ }
+ Q_ASSERT(!m_data->type.isEmpty());
+
+ if (m_data->type == "string")
+ return QVariant::String;
+
+ if (m_data->type == "color")
+ return QVariant::Color;
+
+ if (m_data->type == "int")
+ return QVariant::Int;
+
+ if (m_data->type == "url")
+ return QVariant::Url;
+
+ if (m_data->type == "real")
+ return QVariant::Double;
+
+ if (m_data->type == "bool")
+ return QVariant::Bool;
+
+ if (m_data->type == "date")
+ return QVariant::Date;
+
+ if (m_data->type == "alias")
+ return QVariant::UserType;
+
+ if (m_data->type == "var")
+ return QVariant::UserType;
+
+
+ return QVariant::nameToType(m_data->type.toLatin1().data());
+}
+
+/*!
+ \brief Returns whether the propery is readable.
+ */
+bool PropertyMetaInfo::isReadable() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(isValid(), Q_FUNC_INFO, "");
+ throw InvalidMetaInfoException(__LINE__, Q_FUNC_INFO, __FILE__);
+ }
+ return m_data->readable;
+}
+
+/*!
+ \brief Returns whether the propery is writeable.
+ */
+bool PropertyMetaInfo::isWriteable() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(isValid(), Q_FUNC_INFO, "");
+ throw InvalidMetaInfoException(__LINE__, Q_FUNC_INFO, __FILE__);
+ }
+ return m_data->writeable;
+}
+
+/*!
+ \brief Returns whether the propery is resettable.
+ */
+bool PropertyMetaInfo::isResettable() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(isValid(), Q_FUNC_INFO, "");
+ throw InvalidMetaInfoException(__LINE__, Q_FUNC_INFO, __FILE__);
+ }
+ return m_data->resettable;
+}
+
+/*!
+ \brief Returns whether the propery is complex value type.
+ */
+bool PropertyMetaInfo::isValueType() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(isValid(), Q_FUNC_INFO, "");
+ throw InvalidMetaInfoException(__LINE__, Q_FUNC_INFO, __FILE__);
+ }
+
+ QmlValueType *valueType(QmlValueTypeFactory::valueType(variantTypeId()));
+ return valueType;
+}
+
+/*!
+ \brief Returns whether the propery is a QmlList.
+ */
+bool PropertyMetaInfo::isListProperty() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(isValid(), Q_FUNC_INFO, "");
+ throw InvalidMetaInfoException(__LINE__, Q_FUNC_INFO, __FILE__);
+ }
+
+ return type().contains("QmlList");
+}
+
+/*!
+ \brief Returns whether the propery has sub properties with "." syntax e.g. font
+ */
+bool PropertyMetaInfo::hasDotSubProperties() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(isValid(), Q_FUNC_INFO, "");
+ throw InvalidMetaInfoException(__LINE__, Q_FUNC_INFO, __FILE__);
+ }
+
+ return isValueType() || !isWriteable();
+}
+
+/*!
+ \brief Returns whether the propery stores an enum value.
+ */
+bool PropertyMetaInfo::isEnumType() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(isValid(), Q_FUNC_INFO, "");
+ throw InvalidMetaInfoException(__LINE__, Q_FUNC_INFO, __FILE__);
+ }
+ return m_data->enumType;
+}
+
+/*!
+ \brief Returns whether the propery stores a flag value.
+ */
+bool PropertyMetaInfo::isFlagType() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(isValid(), Q_FUNC_INFO, "");
+ throw InvalidMetaInfoException(__LINE__, Q_FUNC_INFO, __FILE__);
+ }
+ return m_data->flagType;
+}
+
+/*!
+ \brief Returns a default value if there is one specified, an invalid QVariant otherwise.
+ */
+QVariant PropertyMetaInfo::defaultValue(const NodeMetaInfo &nodeMetaInfoArg) const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(isValid(), Q_FUNC_INFO, "");
+ throw InvalidMetaInfoException(__LINE__, Q_FUNC_INFO, __FILE__);
+ }
+
+ QList<NodeMetaInfo> nodeMetaInfoList(nodeMetaInfoArg.superClasses());
+ nodeMetaInfoList.prepend(nodeMetaInfoArg);
+ foreach (const NodeMetaInfo &nodeMetaInfo, nodeMetaInfoList) {
+ if (m_data->defaultValueHash.contains(nodeMetaInfo.typeName()))
+ return m_data->defaultValueHash.value(nodeMetaInfo.typeName());
+ }
+
+ return QVariant();
+}
+
+void PropertyMetaInfo::setName(const QString &name)
+{
+ m_data->name = name;
+}
+
+void PropertyMetaInfo::setType(const QString &type)
+{
+ m_data->type = type;
+}
+
+void PropertyMetaInfo::setValid(bool isValid)
+{
+ m_data->isValid = isValid;
+}
+
+void PropertyMetaInfo::setReadable(bool isReadable)
+{
+ m_data->readable = isReadable;
+}
+
+void PropertyMetaInfo::setWritable(bool isWritable)
+{
+ m_data->writeable = isWritable;
+}
+
+void PropertyMetaInfo::setResettable(bool isRessetable)
+{
+ m_data->resettable = isRessetable;
+}
+
+void PropertyMetaInfo::setEnumType(bool isEnumType)
+{
+ m_data->enumType = isEnumType;
+}
+
+void PropertyMetaInfo::setFlagType(bool isFlagType)
+{
+ m_data->flagType = isFlagType;
+}
+
+void PropertyMetaInfo::setDefaultValue(const NodeMetaInfo &nodeMetaInfo, const QVariant &value)
+{
+ m_data->defaultValueHash.insert(nodeMetaInfo.typeName(), value);
+}
+
+void PropertyMetaInfo::setEnumerator(const EnumeratorMetaInfo &info)
+{
+ m_data->enumerator = info;
+}
+
+/*!
+ \brief Returns meta information about the enumerator type, an invalid EnumeratorMetaInfo object if the property does not store enumerator values.
+ */
+const EnumeratorMetaInfo PropertyMetaInfo::enumerator() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(isValid(), Q_FUNC_INFO, "");
+ throw InvalidMetaInfoException(__LINE__, Q_FUNC_INFO, __FILE__);
+ }
+ return m_data->enumerator;
+}
+
+/*!
+ \brief cast value type of QVariant parameter
+
+ If the type of the passed variant does not correspond to type(), the method tries to convert
+ the value according to QVariant::convert(). Returns a new QVariant with casted value type
+ if successful, an invalid QVariant otherwise.
+
+ \param variant the QVariant to take the value from
+ \returns QVariant with aligned value type, or invalid QVariant
+ */
+QVariant PropertyMetaInfo::castedValue(const QVariant &originalVariant) const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(isValid(), Q_FUNC_INFO, "");
+ throw InvalidMetaInfoException(__LINE__, Q_FUNC_INFO, __FILE__);
+ }
+
+ QVariant variant = originalVariant;
+ if (m_data->enumType) {
+ return variant;
+ }
+
+ QVariant::Type typeId = variantTypeId();
+
+ if (variant.type() == QVariant::UserType && variant.userType() == ModelNode::variantUserType()) {
+ return variant;
+ } else if (typeId == QVariant::UserType && m_data->type == QLatin1String("QVariant")) {
+ return variant;
+ } else if (typeId == QVariant::UserType && m_data->type == QLatin1String("variant")) {
+ return variant;
+ } else if (typeId == QVariant::UserType && m_data->type == QLatin1String("var")) {
+ return variant;
+ } else if (variant.type() == QVariant::List && variant.type() == QVariant::List) {
+ // TODO: check the contents of the list
+ return variant;
+ } else if (type() == "var" || type() == "variant") {
+ return variant;
+ } else if (type() == "alias") {
+ // TODO: The Qml compiler resolves the alias type. We probably should do the same.
+ return variant;
+ } else if (variant.convert(typeId)) {
+ return variant;
+ }
+
+ return QmlStringConverters::variantFromString(variant.toString());
+}
+
+}
diff --git a/src/plugins/qmldesigner/core/metainfo/subcomponentmanager.cpp b/src/plugins/qmldesigner/core/metainfo/subcomponentmanager.cpp
new file mode 100644
index 0000000000..2f0de684a3
--- /dev/null
+++ b/src/plugins/qmldesigner/core/metainfo/subcomponentmanager.cpp
@@ -0,0 +1,442 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "subcomponentmanager.h"
+#include "metainfo.h"
+
+#include <QDir>
+#include <QMetaType>
+#include <QUrl>
+#include <QmlDomDocument>
+#include <QmlEngine>
+#include <QmlMetaType>
+#include <QFileSystemWatcher>
+
+enum { debug = false };
+
+
+// Allow usage of QFileInfo in hash / qSort
+
+static bool operator<(const QFileInfo &file1, const QFileInfo &file2)
+{
+ return file1.filePath() < file2.filePath();
+}
+
+static uint qHash(const QFileInfo &fileInfo)
+{
+ return qHash(fileInfo.filePath());
+}
+
+
+namespace QmlDesigner {
+
+namespace Internal {
+
+static const QString QMLFILEPATTERN = QString(QLatin1String("*.qml"));
+
+
+class SubComponentManagerPrivate : QObject {
+ Q_OBJECT
+public:
+ SubComponentManagerPrivate(MetaInfo metaInfo, SubComponentManager *q);
+
+ void addImport(int pos, const QmlDomImport &import);
+ void removeImport(int pos);
+ void parseDirectories();
+
+public slots:
+ void parseDirectory(const QString &dirPath);
+ void parseFile(const QString &filePath);
+
+public:
+ QList<QFileInfo> watchedFiles(const QDir &dirInfo);
+ void unregisterQmlFile(const QFileInfo &fileInfo, const QString &qualifier);
+ void registerQmlFile(const QFileInfo &fileInfo, const QString &qualifier, const QmlDomDocument &document);
+
+ SubComponentManager *m_q;
+
+ MetaInfo m_metaInfo;
+ QmlEngine m_engine;
+
+ QFileSystemWatcher m_watcher;
+
+ QMultiHash<QFileInfo,QString> m_dirToQualifier;
+
+ QUrl m_filePath;
+
+ QList<QmlDomImport> m_imports;
+};
+
+SubComponentManagerPrivate::SubComponentManagerPrivate(MetaInfo metaInfo, SubComponentManager *q) :
+ m_q(q),
+ m_metaInfo(metaInfo)
+{
+ connect(&m_watcher, SIGNAL(directoryChanged(QString)), this, SLOT(parseDirectory(QString)));
+ connect(&m_watcher, SIGNAL(fileChanged(QString)), this, SLOT(parseFile(QString)));
+}
+
+void SubComponentManagerPrivate::addImport(int pos, const QmlDomImport &import)
+{
+ if (debug)
+ qDebug() << Q_FUNC_INFO << pos << import.uri();
+
+ if (import.type() == QmlDomImport::File) {
+ QFileInfo dirInfo = QFileInfo(m_filePath.resolved(import.uri()).toLocalFile());
+ if (dirInfo.exists() && dirInfo.isDir()) {
+ m_watcher.addPath(dirInfo.filePath());
+ m_dirToQualifier.insertMulti(dirInfo, import.qualifier());
+ }
+ } else {
+ // TODO: QmlDomImport::Library
+ }
+
+ m_imports.insert(pos, import);
+}
+
+void SubComponentManagerPrivate::removeImport(int pos)
+{
+ const QmlDomImport import = m_imports.takeAt(pos);
+
+ if (import.type() == QmlDomImport::File) {
+ QFileInfo dirInfo = QFileInfo(m_filePath.resolved(import.uri()).toLocalFile());
+
+ m_dirToQualifier.remove(dirInfo, import.qualifier());
+
+ if (!m_dirToQualifier.contains(dirInfo))
+ m_watcher.removePath(dirInfo.filePath());
+
+ foreach (const QFileInfo &monitoredFile, watchedFiles(dirInfo.filePath())) {
+ if (!m_dirToQualifier.contains(dirInfo))
+ m_watcher.removePath(monitoredFile.filePath());
+ unregisterQmlFile(monitoredFile, import.qualifier());
+ }
+ } else {
+ // TODO: QmlDomImport::Library
+ }
+}
+
+void SubComponentManagerPrivate::parseDirectories()
+{
+ if (!m_filePath.isEmpty()) {
+ const QString file = m_filePath.toLocalFile();
+ QFileInfo dirInfo = QFileInfo(QFileInfo(file).path());
+ if (dirInfo.exists() && dirInfo.isDir())
+ parseDirectory(dirInfo.filePath());
+ }
+
+ foreach (const QmlDomImport &import, m_imports) {
+ if (import.type() == QmlDomImport::File) {
+ QFileInfo dirInfo = QFileInfo(m_filePath.resolved(import.uri()).toLocalFile());
+ if (dirInfo.exists() && dirInfo.isDir()) {
+ parseDirectory(dirInfo.filePath());
+ }
+ }
+ }
+}
+
+void SubComponentManagerPrivate::parseDirectory(const QString &dirPath)
+{
+ if (debug)
+ qDebug() << Q_FUNC_INFO << dirPath;
+
+ QDir dir(dirPath);
+
+ dir.setNameFilters(QStringList(QMLFILEPATTERN));
+ dir.setFilter(QDir::Files | QDir::Readable | QDir::CaseSensitive);
+
+ QList<QFileInfo> monitoredList = watchedFiles(dir);
+ QList<QFileInfo> newList;
+ foreach (const QFileInfo &qmlFile, dir.entryInfoList()) {
+ if (QFileInfo(m_filePath.toLocalFile()) == qmlFile) {
+ // do not parse main file
+ continue;
+ }
+ if (!qmlFile.fileName().at(0).isUpper()) {
+ // Qml sub components must be upper case
+ continue;
+ }
+ newList << qmlFile;
+ }
+
+ qSort(monitoredList);
+ qSort(newList);
+
+ if (debug)
+ qDebug() << "monitored list " << monitoredList.size() << "new list " << newList.size();
+ QList<QFileInfo>::const_iterator oldIter = monitoredList.constBegin();
+ QList<QFileInfo>::const_iterator newIter = newList.constBegin();
+
+ while (oldIter != monitoredList.constEnd() && newIter != newList.constEnd()) {
+ const QFileInfo oldFileInfo = *oldIter;
+ const QFileInfo newFileInfo = *newIter;
+ if (oldFileInfo == newFileInfo) {
+ ++oldIter;
+ ++newIter;
+ continue;
+ }
+ if (oldFileInfo < newFileInfo) {
+ foreach (const QString &qualifier, m_dirToQualifier.value(dirPath))
+ unregisterQmlFile(oldFileInfo, qualifier);
+ m_watcher.removePath(oldFileInfo.filePath());
+ ++oldIter;
+ continue;
+ }
+ // oldFileInfo > newFileInfo
+ parseFile(newFileInfo.filePath());
+ m_watcher.addPath(oldFileInfo.filePath());
+ ++newIter;
+ }
+
+ while (oldIter != monitoredList.constEnd()) {
+ foreach (const QString &qualifier, m_dirToQualifier.value(dirPath))
+ unregisterQmlFile(*oldIter, qualifier);
+ m_watcher.removePath(oldIter->filePath());
+ ++oldIter;
+ }
+
+ while (newIter != newList.constEnd()) {
+ parseFile(newIter->filePath());
+ if (debug)
+ qDebug() << "m_watcher.addPath(" << newIter->filePath() << ")";
+ m_watcher.addPath(newIter->filePath());
+ ++newIter;
+ }
+}
+
+void SubComponentManagerPrivate::parseFile(const QString &filePath)
+{
+ if (debug)
+ qDebug() << Q_FUNC_INFO << filePath;
+
+ QFile file(filePath);
+ if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ return;
+ }
+
+ QmlDomDocument document;
+ if (!document.load(&m_engine, file.readAll(), QUrl::fromLocalFile(filePath))) {
+ // TODO: Put the errors somewhere?
+ qWarning() << "Could not load qml file " << filePath;
+ return;
+ }
+
+ QString dir = QFileInfo(filePath).dir().path();
+ Q_ASSERT(m_dirToQualifier.contains(dir));
+ foreach (const QString &qualifier, m_dirToQualifier.values(dir)) {
+ registerQmlFile(filePath, qualifier, document);
+ }
+}
+
+QList<QFileInfo> SubComponentManagerPrivate::watchedFiles(const QDir &dirInfo)
+{
+ QList<QFileInfo> files;
+
+ const QString dirPath = dirInfo.absolutePath();
+ foreach (const QString &monitoredFile, m_watcher.files()) {
+ QFileInfo fileInfo(monitoredFile);
+ if (fileInfo.dir().absolutePath() == dirPath) {
+ files.append(fileInfo);
+ }
+ }
+ return files;
+}
+
+void SubComponentManagerPrivate::unregisterQmlFile(const QFileInfo &fileInfo, const QString &qualifier)
+{
+ QString componentName = fileInfo.baseName();
+ if (!qualifier.isEmpty())
+ componentName = qualifier + '/' + componentName;
+
+ if (m_metaInfo.hasNodeMetaInfo(componentName)) {
+ NodeMetaInfo nodeInfo = m_metaInfo.nodeMetaInfo(componentName);
+ m_metaInfo.removeNodeInfo(nodeInfo);
+ }
+}
+
+void SubComponentManagerPrivate::registerQmlFile(const QFileInfo &fileInfo, const QString &qualifier, const QmlDomDocument &document)
+{
+ QString componentName = fileInfo.baseName();
+ if (!qualifier.isEmpty())
+ componentName = qualifier + '/' + componentName;
+
+ if (debug)
+ qDebug() << "SubComponentManager" << __FUNCTION__ << componentName;
+
+ if (m_metaInfo.hasNodeMetaInfo(componentName)) {
+ NodeMetaInfo nodeInfo = m_metaInfo.nodeMetaInfo(componentName);
+ m_metaInfo.removeNodeInfo(nodeInfo);
+ }
+
+ const QmlDomObject rootObject = document.rootObject();
+
+ const QString baseType = document.rootObject().objectType();
+ Q_ASSERT_X(!baseType.isEmpty(), Q_FUNC_INFO, "Type of root object cannot be empty");
+
+ NodeMetaInfo nodeInfo(m_metaInfo);
+ nodeInfo.setTypeName(componentName);
+ nodeInfo.setQmlFile(fileInfo.filePath());
+
+ // Add file components to the library
+ nodeInfo.setCategory(tr("Qml Component"));
+ nodeInfo.setIsVisibleToItemLibrary(true);
+
+ m_metaInfo.addItemLibraryInfo(nodeInfo, componentName);
+ m_metaInfo.addNodeInfo(nodeInfo, baseType);
+
+ foreach (const QmlDomDynamicProperty &dynamicProperty, document.rootObject().dynamicProperties()) {
+ Q_ASSERT(!dynamicProperty.propertyName().isEmpty());
+ Q_ASSERT(!dynamicProperty.propertyTypeName().isEmpty());
+
+ PropertyMetaInfo propertyMetaInfo;
+ propertyMetaInfo.setName(dynamicProperty.propertyName());
+ propertyMetaInfo.setType(dynamicProperty.propertyTypeName());
+ propertyMetaInfo.setValid(true);
+ propertyMetaInfo.setReadable(true);
+ propertyMetaInfo.setWritable(true);
+
+ QmlDomProperty defaultValue = dynamicProperty.defaultValue();
+ if (defaultValue.value().isLiteral()) {
+ QVariant defaultValueVariant(defaultValue.value().toLiteral().literal());
+ defaultValueVariant.convert((QVariant::Type) dynamicProperty.propertyType());
+ propertyMetaInfo.setDefaultValue(nodeInfo, defaultValueVariant);
+ }
+
+ nodeInfo.addProperty(propertyMetaInfo);
+ }
+}
+
+} // namespace Internal
+
+/*!
+ \class SubComponentManager
+
+ Detects & monitors (potential) component files in a list of directories, and registers
+ these in the metatype system.
+*/
+
+SubComponentManager::SubComponentManager(MetaInfo metaInfo, QObject *parent) :
+ QObject(parent),
+ m_d(new Internal::SubComponentManagerPrivate(metaInfo, this))
+{
+}
+
+SubComponentManager::~SubComponentManager()
+{
+ delete m_d;
+}
+
+QStringList SubComponentManager::directories() const
+{
+ return m_d->m_watcher.directories();
+}
+
+QStringList SubComponentManager::qmlFiles() const
+{
+ return m_d->m_watcher.files();
+}
+
+static bool importEqual(const QmlDomImport &import1, const QmlDomImport &import2)
+{
+ return import1.type() == import2.type()
+ && import1.uri() == import2.uri()
+ && import1.version() == import2.version()
+ && import1.qualifier() == import2.qualifier();
+}
+
+void SubComponentManager::update(const QUrl &filePath, const QByteArray &data)
+{
+ QmlEngine engine;
+ QmlDomDocument document;
+
+ QList<QmlDomImport> imports;
+ if (document.load(&engine, data, filePath))
+ imports = document.imports();
+
+ update(filePath, imports);
+}
+
+void SubComponentManager::update(const QUrl &filePath, const QList<QmlDomImport> &imports)
+{
+ if (debug)
+ qDebug() << Q_FUNC_INFO << filePath << imports.size();
+
+ QFileInfo oldDir, newDir;
+
+ if (!m_d->m_filePath.isEmpty()) {
+ const QString file = m_d->m_filePath.toLocalFile();
+ oldDir = QFileInfo(QFileInfo(file).path());
+ }
+ if (!filePath.isEmpty()) {
+ const QString file = filePath.toLocalFile();
+ newDir = QFileInfo(QFileInfo(file).path());
+ }
+
+ m_d->m_filePath = filePath;
+
+ //
+ // (implicit) import of local directory
+ //
+ if (oldDir != newDir) {
+ if (!oldDir.filePath().isEmpty()) {
+ m_d->m_dirToQualifier.remove(oldDir, QString());
+ if (!m_d->m_dirToQualifier.contains(oldDir))
+ m_d->m_watcher.removePath(oldDir.filePath());
+ }
+
+ if (!newDir.filePath().isEmpty()) {
+ m_d->m_watcher.addPath(newDir.filePath());
+ m_d->m_dirToQualifier.insertMulti(newDir, QString());
+ }
+ }
+
+ //
+ // Imports
+ //
+
+ // skip first list items until the lists differ
+ int i = 0;
+ while (i < qMin(imports.size(), m_d->m_imports.size())) {
+ if (!importEqual(imports.at(i), m_d->m_imports.at(i)))
+ break;
+ ++i;
+ }
+
+ for (int ii = m_d->m_imports.size() - 1; ii >= i; --ii)
+ m_d->removeImport(ii);
+
+ for (int ii = i; ii < imports.size(); ++ii) {
+ m_d->addImport(ii, imports.at(ii));
+ }
+
+ m_d->parseDirectories();
+}
+
+} // namespace QmlDesigner
+
+#include "subcomponentmanager.moc"
diff --git a/src/plugins/qmldesigner/core/model/abstractproperty.cpp b/src/plugins/qmldesigner/core/model/abstractproperty.cpp
new file mode 100644
index 0000000000..2d7eec926a
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/abstractproperty.cpp
@@ -0,0 +1,429 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "abstractproperty.h"
+#include "internalnode_p.h"
+#include "internalproperty.h"
+#include <model.h>
+#include "model_p.h"
+#include <modelnode.h>
+#include <metainfo.h>
+#include "invalidpropertyexception.h"
+#include "variantproperty.h"
+#include "bindingproperty.h"
+#include "nodeproperty.h"
+#include "nodeabstractproperty.h"
+#include "nodelistproperty.h"
+#include <QTextStream>
+#include <qmlobjectnode.h>
+#include <qmlview.h>
+
+namespace QmlDesigner {
+
+ /*!
+\class QmlDesigner::AbstractProperty
+\ingroup CoreModel
+\brief AbstractProperty is a value holder for a property
+*/
+
+AbstractProperty::AbstractProperty():
+ m_internalNode(new Internal::InternalNode)
+{
+}
+
+AbstractProperty::AbstractProperty(const QString &propertyName, const Internal::InternalNodePointer &internalNode, Model* model, AbstractView *view)
+ : m_propertyName(propertyName),
+ m_internalNode(internalNode),
+ m_model(model),
+ m_view(view)
+{
+ Q_ASSERT(!m_model || m_view);
+}
+
+AbstractProperty::AbstractProperty(const Internal::InternalPropertyPointer &property, Model* model, AbstractView *view)
+ : m_propertyName(property->name()),
+ m_internalNode(property->propertyOwner()),
+ m_model(model),
+ m_view(view)
+{
+ Q_ASSERT(!m_model || m_view);
+}
+
+AbstractProperty::AbstractProperty(const AbstractProperty &property, AbstractView *view)
+ : m_propertyName(property.name()),
+ m_internalNode(property.internalNode()),
+ m_model(property.model()),
+ m_view(view)
+{
+
+}
+
+AbstractProperty::~AbstractProperty()
+{
+}
+
+AbstractProperty::AbstractProperty(const AbstractProperty &other)
+ : m_propertyName(other.m_propertyName),
+ m_internalNode(other.m_internalNode),
+ m_model(other.m_model),
+ m_view(other.m_view)
+{
+}
+
+AbstractProperty& AbstractProperty::operator=(const AbstractProperty &other)
+{
+ m_propertyName = other.m_propertyName;
+ m_internalNode = other.m_internalNode;
+ m_model = other.m_model;
+ m_view = other.m_view;
+
+ return *this;
+}
+
+Internal::InternalNodePointer AbstractProperty::internalNode() const
+{
+ return m_internalNode;
+}
+
+Model *AbstractProperty::model() const
+{
+ return m_model.data();
+}
+
+AbstractView *AbstractProperty::view() const
+{
+ return m_view.data();
+}
+
+ /*!
+ \brief AbstractProperty is a value holder for a property
+ \return the value of the property
+
+ The QVariant is null if the property doesn't exists.
+*/
+QString AbstractProperty::name() const
+{
+ if (m_propertyName == "id") { // the ID for a node is independent of the state, so it has to be set with ModelNode::setId
+ Q_ASSERT_X(0, Q_FUNC_INFO, "id is not a property in the model");
+ throw InvalidPropertyException(__LINE__, __FUNCTION__, __FILE__, name());
+ }
+ return m_propertyName;
+}
+
+ /*!
+ \brief Checks if the property is valid.
+
+ A prooperty is valid if the belonging ModelNode
+ is valid. This function is not overloaded for
+ subclasses.
+
+ \return the property is valid for true return value
+*/
+bool AbstractProperty::isValid() const
+{
+ return !m_internalNode.isNull() &&
+ !m_model.isNull() &&
+ m_internalNode->isValid() &&
+ !m_propertyName.isEmpty();
+}
+
+//bool AbstractProperty::isValueAPropertyBinding() const
+//{
+// const QVariant propertyValue = value();
+//
+// return propertyValue.type() == QVariant::UserType && propertyValue.userType() == qMetaTypeId<QmlDesigner::PropertyBinding>();
+//}
+//
+//PropertyBinding AbstractProperty::valueToPropertyBinding() const
+//{
+// if (isValueAPropertyBinding())
+// return value().value<PropertyBinding>();
+// else
+// return PropertyBinding();
+//}
+//
+//bool AbstractProperty::isValueAModelNode() const
+//{
+// const QVariant propertyValue = value();
+//
+// return propertyValue.type() == QVariant::UserType && propertyValue.userType() == ModelNode::variantUserType();
+//}
+//
+//ModelNode AbstractProperty::valueToModelNode() const
+//{
+// if (isValueAModelNode())
+// return value().value<ModelNode>();
+// else
+// return ModelNode();
+//}
+//
+//bool AbstractProperty::isValueAList() const
+//{
+// const QVariant propertyValue = value();
+//
+// return propertyValue.type() == QVariant::List;
+//}
+//
+//QVariantList AbstractProperty::valueToList() const
+//{
+// if (isValueAList())
+// return value().toList();
+// else
+// return QVariantList();
+//}
+//
+//ModelNode AbstractProperty::addModelNodeToValueList(const QString &type, int majorVersion, int minorVersion, const QList<QPair<QString, QVariant> > &propertyList)
+//{
+// //if (isValueAList())
+// // return m_model->addModelNode(state(), m_propertyName, type, majorVersion, minorVersion, propertyList);
+// //else
+// // throw InvalidPropertyException(__LINE__, __FUNCTION__, __FILE__, m_propertyName);
+// return ModelNode();
+//}
+
+ /*!
+ \brief returns the ModelNode to which the property belongs
+ \return node to which the property belongs
+*/
+ModelNode AbstractProperty::parentModelNode() const
+{
+ return ModelNode(m_internalNode, m_model.data(), view());
+}
+
+/*!
+\brief returns the QmlObjectNode to which the property belongs
+\return node to which the property belongs
+*/
+QmlObjectNode AbstractProperty::parentQmlObjectNode() const
+{
+ return QmlObjectNode(parentModelNode());
+}
+/*!
+ \brief returns the metainfo instance for this property
+ \return metainfo instance for this property
+*/
+PropertyMetaInfo AbstractProperty::metaInfo() const
+{
+ return ModelNode(m_internalNode, m_model.data(), view()).metaInfo().property(m_propertyName);
+}
+
+/*!
+ \brief returns wether the property is the default property for the model node.
+*/
+bool AbstractProperty::isDefaultProperty() const
+{
+ return ModelNode(m_internalNode, m_model.data(), view()).metaInfo().defaultProperty() == m_propertyName;
+}
+
+VariantProperty AbstractProperty::toVariantProperty() const
+{
+ if (!isValid())
+ throw InvalidPropertyException(__LINE__, __FUNCTION__, __FILE__, m_propertyName);
+
+ VariantProperty propertyVariant(name(), internalNode(), model(), view());
+
+ if (propertyVariant.isVariantProperty())
+ return propertyVariant;
+
+ return VariantProperty();
+}
+
+NodeProperty AbstractProperty::toNodeProperty() const
+{
+ if (!isValid())
+ throw InvalidPropertyException(__LINE__, __FUNCTION__, __FILE__, m_propertyName);
+
+ NodeProperty propertyNode(name(), internalNode(), model(), view());
+
+ if (propertyNode.isNodeProperty())
+ return propertyNode;
+
+ return NodeProperty();
+}
+
+NodeListProperty AbstractProperty::toNodeListProperty() const
+{
+ if (!isValid())
+ throw InvalidPropertyException(__LINE__, __FUNCTION__, __FILE__, m_propertyName);
+
+ NodeListProperty propertyNodeList(name(), internalNode(), model(), view());
+
+ if (propertyNodeList.isNodeListProperty())
+ return propertyNodeList;
+
+ return NodeListProperty();
+}
+
+NodeAbstractProperty AbstractProperty::toNodeAbstractProperty() const
+{
+ if (!isValid())
+ throw InvalidPropertyException(__LINE__, __FUNCTION__, __FILE__, m_propertyName);
+
+ NodeAbstractProperty propertyNodeAbstract(name(), internalNode(), model(), view());
+
+ if (propertyNodeAbstract.isNodeAbstractProperty())
+ return propertyNodeAbstract;
+
+ return NodeAbstractProperty();
+}
+
+BindingProperty AbstractProperty::toBindingProperty() const
+{
+ if (!isValid())
+ throw InvalidPropertyException(__LINE__, __FUNCTION__, __FILE__, m_propertyName);
+
+ BindingProperty propertyBinding(name(), internalNode(), model(), view());
+
+ if (propertyBinding.isBindingProperty())
+ return propertyBinding;
+
+ return BindingProperty();
+}
+
+bool AbstractProperty::isVariantProperty() const
+{
+ if (!isValid())
+ throw InvalidPropertyException(__LINE__, __FUNCTION__, __FILE__, m_propertyName);
+
+ if (internalNode()->hasProperty(name())) {
+ Q_ASSERT(internalNode()->property(name()));
+ return internalNode()->property(name())->isVariantProperty();
+ }
+
+ return false;
+}
+
+bool AbstractProperty::isNodeAbstractProperty() const
+{
+ if (!isValid())
+ throw InvalidPropertyException(__LINE__, __FUNCTION__, __FILE__, m_propertyName);
+
+ if (internalNode()->hasProperty(name())) {
+ Q_ASSERT(internalNode()->property(name()));
+ return internalNode()->property(name())->isNodeAbstractProperty();
+ }
+
+ return false;
+}
+
+bool AbstractProperty::isNodeListProperty() const
+{
+ if (!isValid())
+ throw InvalidPropertyException(__LINE__, __FUNCTION__, __FILE__, m_propertyName);
+
+ if (internalNode()->hasProperty(name())) {
+ Q_ASSERT(internalNode()->property(name()));
+ return internalNode()->property(name())->isNodeListProperty();
+ }
+
+ return false;
+}
+
+bool AbstractProperty::isNodeProperty() const
+{
+ if (!isValid())
+ throw InvalidPropertyException(__LINE__, __FUNCTION__, __FILE__, m_propertyName);
+
+ if (internalNode()->hasProperty(name())) {
+ Q_ASSERT(internalNode()->property(name()));
+ return internalNode()->property(name())->isNodeProperty();
+ }
+
+ return false;
+}
+
+
+bool AbstractProperty::isBindingProperty() const
+{
+ if (!isValid())
+ throw InvalidPropertyException(__LINE__, __FUNCTION__, __FILE__, m_propertyName);
+
+ if (internalNode()->hasProperty(name())) {
+ Q_ASSERT(internalNode()->property(name()));
+ return internalNode()->property(name())->isBindingProperty();
+ }
+
+ return false;
+}
+
+bool AbstractProperty::isDynamic() const
+{
+ return !dynamicTypeName().isEmpty();
+}
+
+QString AbstractProperty::dynamicTypeName() const
+{
+ if (!isValid())
+ throw InvalidPropertyException(__LINE__, __FUNCTION__, __FILE__, m_propertyName);
+
+ if (internalNode()->hasProperty(name()))
+ return internalNode()->property(name())->dynamicTypeName();
+
+ return QString();
+}
+
+/*!
+ \brief Returns if the the two property handles reference the same property in the same node
+*/
+bool operator ==(const AbstractProperty &property1, const AbstractProperty &property2)
+{
+ return (property1.m_model == property2.m_model)
+ && (property1.m_internalNode == property2.m_internalNode)
+ && (property1.m_propertyName == property2.m_propertyName);
+}
+
+/*!
+ \brief Returns if the the two property handles do not reference the same property in the same node
+ */
+bool operator !=(const AbstractProperty &property1, const AbstractProperty &property2)
+{
+ return !(property1 == property2);
+}
+
+uint qHash(const AbstractProperty &property)
+{
+ //### to do
+ return ::qHash(property.m_internalNode.data())
+ ^ ::qHash(property.m_propertyName);
+}
+
+QDebug operator<<(QDebug debug, const AbstractProperty &property)
+{
+ return debug.nospace() << "AbstractProperty(" << (property.isValid() ? property.name() : QLatin1String("invalid")) << ")";
+}
+
+QTextStream& operator<<(QTextStream &stream, const AbstractProperty &property)
+{
+ stream << "AbstractProperty(" << property.name() << ")";
+
+ return stream;
+}
+
+} // namespace QmlDesigner
+
diff --git a/src/plugins/qmldesigner/core/model/abstractview.cpp b/src/plugins/qmldesigner/core/model/abstractview.cpp
new file mode 100644
index 0000000000..ff1c3c185f
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/abstractview.cpp
@@ -0,0 +1,354 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "abstractview.h"
+
+#include "model.h"
+#include "model_p.h"
+#include "nodeproperty.h"
+#include "bindingproperty.h"
+#include "internalnode_p.h"
+#include <qmlmodelview.h>
+
+namespace QmlDesigner {
+
+
+/*!
+\class QmlDesigner::AbstractView
+\ingroup CoreModel
+\brief An abstract interface views and editors can implement to be notified about model changes.
+
+\see QmlDesigner::WidgetQueryView, QmlDesigner::NodeInstanceView
+*/
+
+AbstractView::~AbstractView()
+{
+ if (m_model)
+ m_model.data()->detachView(this, Model::DoNotNotifyView);
+}
+
+/*!
+\brief sets the view of the model. this is handled automatically by AbstractView::modelAttached.
+\param model new Model
+*/
+void AbstractView::setModel(Model *model)
+{
+ Q_ASSERT(model != 0);
+ if (model == m_model.data())
+ return;
+
+ if (m_model)
+ m_model.data()->detachView(this);
+
+ m_model = model;
+}
+
+RewriterTransaction AbstractView::beginRewriterTransaction()
+{
+ return RewriterTransaction(this);
+}
+
+ModelNode AbstractView::createModelNode(const QString &typeString,
+ int majorVersion,
+ int minorVersion,
+ const QList<QPair<QString, QVariant> > &propertyList)
+{
+ return ModelNode(model()->m_d->createNode(typeString, majorVersion, minorVersion, propertyList), model(), this);
+}
+
+
+/*! \brief returns the root model node
+\return constant root model node
+
+*/
+
+const ModelNode AbstractView::rootModelNode() const
+{
+ Q_ASSERT(model());
+ return ModelNode(model()->m_d->rootNode(), model(), const_cast<AbstractView*>(this));
+}
+
+
+/*! \brief returns the root model node
+\return root model node
+
+*/
+
+ModelNode AbstractView::rootModelNode()
+{
+ Q_ASSERT(model());
+ return ModelNode(model()->m_d->rootNode(), model(), this);
+}
+
+/*!
+\brief sets the reference to model to a null pointer
+
+*/
+void AbstractView::removeModel()
+{
+ m_model.clear();
+}
+
+/*!
+\name Model related functions
+\{
+*/
+
+/*!
+\brief returns the model
+\return the model of the view
+*/
+Model* AbstractView::model() const
+{
+ return m_model.data();
+}
+
+/*!
+\brief is called if a view is being attached to a model
+\param model which is being attached
+The default implementation is setting the reference of the model to the view.
+\see Model::attachView
+*/
+void AbstractView::modelAttached(Model *model)
+{
+ setModel(model);
+}
+
+/*!
+\brief is called before a view is being detached from a model
+\param model which is being detached
+
+This is not called if Model::detachViewWithOutNotification is used! The default implementation
+is removing the reference to the model from the view.
+
+\see Model::detachView
+*/
+void AbstractView::modelAboutToBeDetached(Model *)
+{
+ removeModel();
+}
+
+//\}
+
+
+/*!
+\name Property related functions
+\{
+ */
+
+/*!
+\fn void QmlDesigner::AbstractView::propertyAdded(const ModelNode &, const AbstractProperty &)
+\brief node notifies about that this property is added
+\param node node to which the property is added
+\param property added property
+*/
+
+
+/*!
+\fn void AbstractView::propertyValueChanged(const ModelNode &, const AbstractProperty& , const QVariant& , const QVariant& )
+\brief this notifies about that the value of this proeprty will be changes
+\param node node of the property
+\param property changed property
+\param newValue the variant of the new value
+\param oldValue the variant of the old value
+*/
+//\}
+
+/*!
+\name Node related functions
+\{
+ */
+
+/*!
+\fn void AbstractView::nodeCreated(const ModelNode &)
+\brief this function is called if a new node was created
+\param createdNode created node
+*/
+
+
+/*!
+\fn AbstractView::fileUrlChanged(const QUrl &oldBaseUrl, const QUrl &newBaseUrl)
+\brief Called when the file url (e.g. needed to to resolve relative paths against) has changed
+\param oldBaseUrl old search path
+\param newBaseUrl new search path
+*/
+void AbstractView::fileUrlChanged(const QUrl &/*oldUrl*/, const QUrl &/*newUrl*/)
+{
+}
+
+/*!
+\fn AbstractView::importsChanged()
+\brief Called when the imports for the model change.
+*/
+void AbstractView::importsChanged()
+{
+}
+
+/*!
+\fn void AbstractView::nodeAboutToBeRemoved(const ModelNode &)
+\brief this is called if a node will be removed
+\param removedNode to be removed node
+*/
+
+/*!
+\brief this is called after a propererty was removed
+\param propertyList removed property list
+*/
+void AbstractView::propertiesRemoved(const QList<AbstractProperty>& /*propertyList*/)
+{
+}
+
+/*!
+\fn void AbstractView::nodeReparented(const ModelNode &, const ModelNode &, const ModelNode &)
+\brief this is called if a node was reparented
+\param node the parent for this node will be changed
+\param oldParent old parent of the node
+\param newParent new parent of the node
+*/
+
+/*!
+\fn void QmlDesigner::AbstractView::selectedNodesChanged(const QList< ModelNode > &, const QList< ModelNode > &)
+\brief this function is called if the selection was changed
+\param selectedNodeList the new selection list
+\param lastSelectedNodeList the old selection list
+*/
+//\}
+
+void AbstractView::auxiliaryDataChanged(const ModelNode &/*node*/, const QString &/*name*/, const QVariant &/*data*/)
+{
+
+}
+
+void AbstractView::customNotification(const AbstractView * /*view*/, const QString & /*identifier*/, const QList<ModelNode> & /*nodeList*/, const QList<QVariant> & /*data*/)
+{
+}
+
+QList<ModelNode> AbstractView::toModelNodeList(const QList<Internal::InternalNode::Pointer> &nodeList) const
+{
+ return QmlDesigner::toModelNodeList(nodeList, const_cast<AbstractView*>(this));
+}
+
+QList<ModelNode> toModelNodeList(const QList<Internal::InternalNode::Pointer> &nodeList, AbstractView *view)
+{
+ QList<ModelNode> newNodeList;
+ foreach(const Internal::InternalNode::Pointer &node, nodeList)
+ newNodeList.append(ModelNode(node, view->model(), view));
+
+ return newNodeList;
+}
+
+QList<Internal::InternalNode::Pointer> toInternalNodeList(const QList<ModelNode> &nodeList)
+{
+ QList<Internal::InternalNode::Pointer> newNodeList;
+ foreach(const ModelNode &node, nodeList)
+ newNodeList.append(node.internalNode());
+
+ return newNodeList;
+}
+
+/*!
+\brief set this list nodes to the actual selected nodes
+\param focusNodeList list the selected nodes
+*/
+void AbstractView::setSelectedModelNodes(const QList<ModelNode> &selectedNodeList)
+{
+ model()->m_d->setSelectedNodes(toInternalNodeList(selectedNodeList));
+}
+
+/*!
+\brief clears the selection
+*/
+void AbstractView::clearSelectedModelNodes()
+{
+ model()->m_d->clearSelectedNodes();
+}
+
+/*!
+\brief set this list nodes to the actual selected nodes
+\return list the selected nodes
+*/
+QList<ModelNode> AbstractView::selectedModelNodes() const
+{
+ return toModelNodeList(model()->m_d->selectedNodes());
+}
+
+/*!
+\brief adds a node to the selection list
+\param node to be added to the selection list
+*/
+void AbstractView::selectModelNode(const ModelNode &node)
+{
+ model()->m_d->selectNode(node.internalNode());
+}
+
+/*!
+\brief removes a node from the selection list
+\param node to be removed from the selection list
+*/
+void AbstractView::deselectModelNode(const ModelNode &node)
+{
+ model()->m_d->deselectNode(node.internalNode());
+}
+
+ModelNode AbstractView::modelNodeForId(const QString &id)
+{
+ return ModelNode(model()->m_d->nodeForId(id), model(), this);
+}
+
+bool AbstractView::hasId(const QString &id) const
+{
+ return model()->m_d->hasId(id);
+}
+
+QmlModelView *AbstractView::toQmlModelView()
+{
+ return qobject_cast<QmlModelView*>(this);
+}
+
+QList<ModelNode> AbstractView::allModelNodes()
+{
+ return toModelNodeList(model()->m_d->allNodes());
+}
+
+void AbstractView::emitCustomNotification(const QString &identifier)
+{
+ emitCustomNotification(identifier, QList<ModelNode>());
+}
+
+void AbstractView::emitCustomNotification(const QString &identifier, const QList<ModelNode> &nodeList)
+{
+ emitCustomNotification(identifier, nodeList, QList<QVariant>());
+}
+
+void AbstractView::emitCustomNotification(const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> &data)
+{
+ model()->m_d->notifyCustomNotification(this, identifier, nodeList, data);
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/core/model/anchorline.cpp b/src/plugins/qmldesigner/core/model/anchorline.cpp
new file mode 100644
index 0000000000..c2f36be59c
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/anchorline.cpp
@@ -0,0 +1,130 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "anchorline.h"
+#include "model.h"
+#include "internalnode_p.h"
+#include "modelnode.h"
+
+namespace QmlDesigner {
+
+AnchorLine::AnchorLine()
+ : m_anchorType(Invalid)
+{
+}
+
+AnchorLine::AnchorLine(const Internal::InternalNodeStatePointer &internalNodeState,
+ const Internal::InternalNodePointer &internalNode,
+ Model* model,
+ Type type)
+ : m_internalNodeState(internalNodeState),
+ m_internalNode(internalNode),
+ m_model(model),
+ m_anchorType(type)
+{
+}
+
+AnchorLine::AnchorLine(const NodeState &nodeState,
+ Type type)
+ : m_internalNodeState(nodeState.internalNodeState()),
+ m_internalNode(nodeState.internalNode()),
+ m_model(nodeState.model()),
+ m_anchorType(type)
+{
+
+}
+
+AnchorLine::~AnchorLine()
+{
+}
+
+AnchorLine::AnchorLine(const AnchorLine &other)
+ : m_internalNodeState(other.m_internalNodeState),
+ m_internalNode(other.m_internalNode),
+ m_model(other.m_model),
+ m_anchorType(other.m_anchorType)
+{
+}
+
+AnchorLine &AnchorLine::operator =(const AnchorLine &other)
+{
+ m_internalNodeState = other.m_internalNodeState;
+ m_internalNode = other.m_internalNode;
+ m_model = other.m_model;
+ m_anchorType = other.m_anchorType;
+
+ return *this;
+}
+
+ModelNode AnchorLine::modelNode() const
+{
+ if (m_internalNode.isNull() || m_internalNodeState.isNull() || m_model.isNull()) {
+ return ModelNode();
+ }
+ return ModelNode(m_internalNode, m_model.data());
+}
+
+
+AnchorLine::Type AnchorLine::type() const
+{
+ return m_anchorType;
+}
+
+bool AnchorLine::isValid() const
+{
+ return m_anchorType != Invalid &&
+ !m_model.isNull() &&
+ !m_internalNode.isNull() &&
+ !m_internalNodeState.isNull() &&
+ m_internalNode.toStrongRef()->isValid() &&
+ m_internalNodeState.toStrongRef()->isValid();
+}
+
+QVariant AnchorLine::toVariant() const
+{
+ return QVariant::fromValue(*this);
+}
+
+Internal::InternalNodeStatePointer AnchorLine::internalNodeState() const
+{
+ if (m_internalNodeState.isNull())
+ return Internal::InternalNodeStatePointer(new Internal::InternalNodeState);
+
+ return m_internalNodeState.toStrongRef();
+}
+
+Internal::InternalNodePointer AnchorLine::internalNode() const
+{
+ if (m_internalNode.isNull())
+ return Internal::InternalNodePointer(new Internal::InternalNode);
+
+ return m_internalNode.toStrongRef();
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/core/model/bindingproperty.cpp b/src/plugins/qmldesigner/core/model/bindingproperty.cpp
new file mode 100644
index 0000000000..b258bb2cdd
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/bindingproperty.cpp
@@ -0,0 +1,200 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "bindingproperty.h"
+#include "nodeabstractproperty.h"
+#include "nodeproperty.h"
+#include "internalproperty.h"
+#include "internalbindingproperty.h"
+#include "invalidmodelnodeexception.h"
+#include "invalidpropertyexception.h"
+#include "invalidargumentexception.h"
+#include "internalnode_p.h"
+#include "model.h"
+#include "model_p.h"
+namespace QmlDesigner {
+
+BindingProperty::BindingProperty()
+{
+}
+
+BindingProperty::BindingProperty(const BindingProperty &property, AbstractView *view)
+ : AbstractProperty(property.name(), property.internalNode(), property.model(), view)
+{
+}
+
+
+BindingProperty::BindingProperty(const QString &propertyName, const Internal::InternalNodePointer &internalNode, Model* model, AbstractView *view)
+ : AbstractProperty(propertyName, internalNode, model, view)
+{
+}
+
+
+void BindingProperty::setExpression(const QString &expression)
+{
+ if (!isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ if (name() == "id") { // the ID for a node is independent of the state, so it has to be set with ModelNode::setId
+ throw InvalidPropertyException(__LINE__, __FUNCTION__, __FILE__, name());
+ }
+
+ if (expression.isEmpty())
+ throw InvalidArgumentException(__LINE__, __FUNCTION__, __FILE__, name());
+
+ if (internalNode()->hasProperty(name())) { //check if oldValue != value
+ Internal::InternalProperty::Pointer internalProperty = internalNode()->property(name());
+ if (internalProperty->isBindingProperty()
+ && internalProperty->toBindingProperty()->expression() == expression)
+
+ return;
+ }
+
+ if (internalNode()->hasProperty(name()) && !internalNode()->property(name())->isBindingProperty())
+ model()->m_d->removeProperty(internalNode()->property(name()));
+
+ model()->m_d->setBindingProperty(internalNode(), name(), expression);
+}
+
+QString BindingProperty::expression() const
+{
+ if (internalNode()->hasProperty(name())
+ && internalNode()->property(name())->isBindingProperty())
+ return internalNode()->bindingProperty(name())->expression();
+
+ return QString();
+}
+
+BindingProperty& BindingProperty::operator= (const QString &expression)
+{
+ setExpression(expression);
+
+ return *this;
+}
+
+static ModelNode resolveBinding(const QString &binding, ModelNode currentNode, AbstractView* view)
+{
+ int i = 0;
+ QString element = binding.split(".").at(0);
+ while (!element.isEmpty())
+ {
+ if (element == "parent") {
+ if (currentNode.hasParentProperty())
+ currentNode = currentNode.parentProperty().toNodeAbstractProperty().parentModelNode();
+ else
+ return ModelNode(); //binding not valid
+ } else if (currentNode.hasProperty(element)) {
+ if (currentNode.property(element).isNodeProperty())
+ currentNode = currentNode.nodeProperty(element).modelNode();
+ else
+ return ModelNode(); //binding not valid
+ } else {
+ currentNode = view->modelNodeForId(element); //id
+ }
+ i++;
+ if (i < binding.split(".").count())
+ element = binding.split(".").at(i);
+ else
+ element = "";
+ }
+ return currentNode;
+
+}
+
+ModelNode BindingProperty::resolveToModelNode() const
+{
+ if (!isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ return resolveBinding(expression(), parentModelNode(), view());
+}
+
+AbstractProperty BindingProperty::resolveToProperty() const
+{
+ if (!isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ QString binding = expression();
+ ModelNode node = parentModelNode();
+ QString element;
+ if (binding.contains(".")) {
+ element = binding.split(".").last();
+ QString nodeBinding = binding;
+ nodeBinding.chop(element.length());
+ node = resolveBinding(nodeBinding, parentModelNode(), view());
+ } else {
+ element = binding;
+ }
+
+ if (node.isValid())
+ return node.property(element);
+ else
+ return AbstractProperty();
+}
+
+void BindingProperty::setDynamicTypeNameAndExpression(const QString &typeName, const QString &expression)
+
+{
+ if (!isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ if (name() == "id") { // the ID for a node is independent of the state, so it has to be set with ModelNode::setId
+ throw InvalidPropertyException(__LINE__, __FUNCTION__, __FILE__, name());
+ }
+
+ if (expression.isEmpty())
+ throw InvalidArgumentException(__LINE__, __FUNCTION__, __FILE__, name());
+
+ if (typeName.isEmpty()) {
+ throw InvalidArgumentException(__LINE__, __FUNCTION__, __FILE__, name());
+ }
+
+ if (internalNode()->hasProperty(name())) { //check if oldValue != value
+ Internal::InternalProperty::Pointer internalProperty = internalNode()->property(name());
+ if (internalProperty->isBindingProperty()
+ && internalProperty->toBindingProperty()->expression() == expression
+ && internalProperty->toBindingProperty()->dynamicTypeName() == typeName)
+
+ return;
+ }
+
+ if (internalNode()->hasProperty(name()) && !internalNode()->property(name())->isBindingProperty())
+ model()->m_d->removeProperty(internalNode()->property(name()));
+
+ model()->m_d->setDynamicBindingProperty(internalNode(), name(), typeName, expression);
+}
+
+BindingProperty& BindingProperty::operator= (const QPair<QString, QString> &typeExpressionPair)
+{
+ setDynamicTypeNameAndExpression(typeExpressionPair.first, typeExpressionPair.second);
+
+ return *this;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/core/model/bytearraymodifier.cpp b/src/plugins/qmldesigner/core/model/bytearraymodifier.cpp
new file mode 100644
index 0000000000..33f0fe905f
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/bytearraymodifier.cpp
@@ -0,0 +1,68 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "bytearraymodifier.h"
+
+namespace QmlDesigner {
+
+ByteArrayModifier::ByteArrayModifier(QPlainTextEdit* textEdit):
+ PlainTextEditModifier(textEdit),
+ m_textEdit(textEdit)
+{
+}
+
+ByteArrayModifier::~ByteArrayModifier()
+{
+ delete m_textEdit;
+}
+
+void ByteArrayModifier::undo()
+{
+ m_textEdit->undo();
+}
+
+void ByteArrayModifier::redo()
+{
+ m_textEdit->redo();
+}
+
+ByteArrayModifier* ByteArrayModifier::create(const QString& data)
+{
+ QPlainTextEdit* edit = new QPlainTextEdit;
+ edit->setPlainText(data);
+ return new ByteArrayModifier(edit);
+}
+
+void ByteArrayModifier::setText(const QString& text)
+{
+ m_textEdit->setPlainText(text);
+ emit textChanged();
+}
+
+}
diff --git a/src/plugins/qmldesigner/core/model/componenttextmodifier.cpp b/src/plugins/qmldesigner/core/model/componenttextmodifier.cpp
new file mode 100644
index 0000000000..98a78bd955
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/componenttextmodifier.cpp
@@ -0,0 +1,127 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "componenttextmodifier.h"
+
+namespace QmlDesigner {
+
+ComponentTextModifier::ComponentTextModifier(TextModifier *originalModifier, int componentStartOffset, int componentEndOffset, int rootStartOffset) :
+ m_originalModifier(originalModifier),
+ m_componentStartOffset(componentStartOffset),
+ m_componentEndOffset(componentEndOffset),
+ m_rootStartOffset(rootStartOffset)
+{
+ connect(m_originalModifier->textDocument(), SIGNAL(contentsChange(int,int,int)), this, SLOT(contentsChange(int,int,int)));
+ connect(m_originalModifier, SIGNAL(textChanged()), this, SIGNAL(textChanged()));
+
+ connect(m_originalModifier, SIGNAL(replaced(int, int, int)), this, SIGNAL(replaced(int, int, int)));
+ connect(m_originalModifier, SIGNAL(moved(const TextModifier::MoveInfo &)), this, SIGNAL(moved(const TextModifier::MoveInfo &)));
+}
+
+ComponentTextModifier::~ComponentTextModifier()
+{
+}
+
+void ComponentTextModifier::replace(int offset, int length, const QString& replacement)
+{
+ m_originalModifier->replace(offset, length, replacement);
+}
+
+void ComponentTextModifier::move(const MoveInfo &moveInfo)
+{
+ m_originalModifier->move(moveInfo);
+}
+
+void ComponentTextModifier::startGroup()
+{
+ m_originalModifier->startGroup();
+}
+
+void ComponentTextModifier::flushGroup()
+{
+ m_originalModifier->flushGroup();
+}
+
+void ComponentTextModifier::commitGroup()
+{
+ m_originalModifier->commitGroup();
+}
+
+QTextDocument *ComponentTextModifier::textDocument() const
+{
+ return m_originalModifier->textDocument();
+}
+
+QString ComponentTextModifier::text() const
+{
+ QString txt(m_originalModifier->text());
+
+ const int leader = m_componentStartOffset - m_rootStartOffset;
+ txt.replace(m_rootStartOffset, leader, QString(leader, ' '));
+
+ const int textLength = txt.size();
+ const int trailer = textLength - m_componentEndOffset;
+ txt.replace(m_componentEndOffset, trailer, QString(trailer, ' '));
+
+ return txt;
+}
+
+QTextCursor ComponentTextModifier::textCursor() const
+{
+ return m_originalModifier->textCursor();
+}
+
+void ComponentTextModifier::deactivateChangeSignals()
+{
+ m_originalModifier->deactivateChangeSignals();
+}
+
+void ComponentTextModifier::reactivateChangeSignals()
+{
+ m_originalModifier->reactivateChangeSignals();
+}
+
+void ComponentTextModifier::contentsChange(int position, int charsRemoved, int charsAdded)
+{
+ const int diff = charsAdded - charsRemoved;
+
+ if (position < m_rootStartOffset) {
+ m_rootStartOffset += diff;
+ }
+
+ if (position < m_componentStartOffset) {
+ m_componentStartOffset += diff;
+ }
+
+ if (position < m_componentEndOffset) {
+ m_componentEndOffset += diff;
+ }
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/core/model/copyhelper.cpp b/src/plugins/qmldesigner/core/model/copyhelper.cpp
new file mode 100644
index 0000000000..0d4f467f1a
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/copyhelper.cpp
@@ -0,0 +1,89 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <QtCore/QBuffer>
+#include <QtCore/QDataStream>
+
+#include "copyhelper.h"
+#include "internalnode_p.h"
+
+namespace QmlDesigner {
+namespace Internal {
+
+CopyHelper::CopyHelper(const QString &source):
+ m_source(source)
+{
+}
+
+QMimeData *CopyHelper::createMimeData(const QList<InternalNodeState::Pointer> &nodeStates)
+{
+ if (nodeStates.isEmpty())
+ return 0;
+
+ m_locations.clear();
+
+ foreach (const InternalNodeState::Pointer &nodeState, nodeStates) {
+ collectLocations(nodeState);
+ }
+
+ if (m_locations.isEmpty())
+ return 0;
+
+ QMimeData *mimeData = new QMimeData;
+ mimeData->setData("application/x-qt-bauhaus", contentsAsByteArray());
+
+ return mimeData;
+}
+
+void CopyHelper::collectLocations(const InternalNodeState::Pointer &nodeState)
+{
+ // TODO: copy way more here.
+ m_locations.insert(nodeState->modelNode()->baseNodeState()->location());
+}
+
+QByteArray CopyHelper::contentsAsByteArray() const
+{
+ QBuffer result;
+ result.open(QIODevice::WriteOnly);
+ QDataStream os(&result);
+
+ os << m_locations.size();
+ foreach (const TextLocation &location, m_locations) {
+ os << location.position();
+ os << location.length();
+ }
+
+ os << m_source;
+
+ result.close();
+ return result.buffer();
+}
+
+} // namespace Internal
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/core/model/copyhelper.h b/src/plugins/qmldesigner/core/model/copyhelper.h
new file mode 100644
index 0000000000..6e143fb7db
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/copyhelper.h
@@ -0,0 +1,63 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef COPYHELPER_H
+#define COPYHELPER_H
+
+#include <QtCore/QByteArray>
+#include <QtCore/QMimeData>
+#include <QtCore/QSet>
+#include <QtCore/QString>
+
+#include "internalnodestate.h"
+#include "textlocation.h"
+
+namespace QmlDesigner {
+namespace Internal {
+
+class CopyHelper
+{
+public:
+ CopyHelper(const QString &source);
+
+ QMimeData *createMimeData(const QList<InternalNodeState::Pointer> &nodeStates);
+
+private:
+ void collectLocations(const InternalNodeState::Pointer &nodeState);
+ QByteArray contentsAsByteArray() const;
+
+private:
+ QString m_source;
+ QSet<TextLocation> m_locations;
+};
+
+} // namespace Internal
+} // namespace QmlDesigner
+
+#endif // COPYHELPER_H
diff --git a/src/plugins/qmldesigner/core/model/copypasteutil.cpp b/src/plugins/qmldesigner/core/model/copypasteutil.cpp
new file mode 100644
index 0000000000..c51c0b3d67
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/copypasteutil.cpp
@@ -0,0 +1,61 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <qmljsast_p.h>
+#include <qmljsengine_p.h>
+
+#include "copypasteutil.h"
+
+using namespace QmlJS;
+using namespace QmlJS::AST;
+
+namespace QmlDesigner {
+namespace Internal {
+
+Import CopyPasteUtil::createImport(QmlJS::AST::UiImport *ast)
+{
+ QString version;
+ if (ast->versionToken.isValid())
+ version = textAt(ast->versionToken);
+
+ QString alias;
+ if (ast->importId)
+ alias = ast->importId->asString();
+
+ if (ast->fileName)
+ return Import::createFileImport(ast->fileName->asString(), version, alias);
+
+ if (ast->importUri && ast->importUri->name)
+ return Import::createLibraryImport(ast->importUri->name->asString(), version, alias);
+
+ return Import::empty();
+}
+
+} // namespace Internal
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/core/model/copypasteutil.h b/src/plugins/qmldesigner/core/model/copypasteutil.h
new file mode 100644
index 0000000000..d44783e267
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/copypasteutil.h
@@ -0,0 +1,63 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef COPYPASTEUTIL_H
+#define COPYPASTEUTIL_H
+
+#include <qmljsastfwd_p.h>
+
+#include "import.h"
+
+namespace QmlDesigner {
+namespace Internal {
+
+class CopyPasteUtil {
+public:
+ CopyPasteUtil(const QString &originalSource): m_originalSource(originalSource)
+ {}
+
+ Import createImport(QmlJS::AST::UiImport *ast);
+
+protected:
+ QString textAt(const QmlJS::AST::SourceLocation &loc) const
+ { return m_originalSource.mid(loc.offset, loc.length); }
+
+ QString textAt(const QmlJS::AST::SourceLocation &firstSourceLocation, const QmlJS::AST::SourceLocation &lastSourceLocation) const
+ { return m_originalSource.mid(firstSourceLocation.offset, lastSourceLocation.end() - firstSourceLocation.offset); }
+
+ QString originalSource() const { return m_originalSource; }
+
+private:
+ QString m_originalSource;
+};
+
+} // namespace Internal
+} // namespace QmlDesigner
+
+#endif // COPYPASTEUTIL_H
diff --git a/src/plugins/qmldesigner/core/model/import.cpp b/src/plugins/qmldesigner/core/model/import.cpp
new file mode 100644
index 0000000000..c7c7abf4eb
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/import.cpp
@@ -0,0 +1,92 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <QtCore/QHash>
+
+#include "import.h"
+
+namespace QmlDesigner {
+
+Import Import::createLibraryImport(const QUrl &url, const QString &version, const QString &alias)
+{
+ return Import(url, QString(), version, alias);
+}
+
+Import Import::createFileImport(const QString &file, const QString &version, const QString &alias)
+{
+ return Import(QUrl(), file, version, alias);
+}
+
+Import Import::empty()
+{
+ return Import(QUrl(), QString(), QString(), QString());
+}
+
+Import::Import(const QUrl &url, const QString &file, const QString &version, const QString &alias):
+ m_url(url),
+ m_file(file),
+ m_version(version),
+ m_alias(alias)
+{
+}
+
+QString Import::toString(bool addSemicolon) const
+{
+ QString result = QLatin1String("import ");
+
+ if (isFileImport())
+ result += '"' + file() + '"';
+ else if (isLibraryImport())
+ result += url().toString();
+ else
+ return QString();
+
+ if (hasVersion())
+ result += ' ' + version();
+
+ if (hasAlias())
+ result += " as " + alias();
+
+ if (addSemicolon)
+ result += ';';
+
+ return result;
+}
+
+bool Import::operator==(const Import &other) const
+{
+ return url() == other.url() && file() == other.file() && version() == other.version() && alias() == other.alias();
+}
+
+uint qHash(const Import &import)
+{
+ return ::qHash(import.url().toString()) ^ ::qHash(import.file()) ^ ::qHash(import.version()) ^ ::qHash(import.alias());
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/core/model/internalbindingproperty.cpp b/src/plugins/qmldesigner/core/model/internalbindingproperty.cpp
new file mode 100644
index 0000000000..e590c8e00b
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/internalbindingproperty.cpp
@@ -0,0 +1,77 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "internalbindingproperty.h"
+
+namespace QmlDesigner {
+namespace Internal {
+
+InternalBindingProperty::InternalBindingProperty(const QString &name, const InternalNodePointer &propertyOwner)
+ : InternalProperty(name, propertyOwner)
+{
+}
+
+
+InternalBindingProperty::Pointer InternalBindingProperty::create(const QString &name, const InternalNodePointer &propertyOwner)
+{
+ InternalBindingProperty *newPointer(new InternalBindingProperty(name, propertyOwner));
+ InternalBindingProperty::Pointer smartPointer(newPointer);
+
+ newPointer->setInternalWeakPointer(smartPointer);
+
+ return smartPointer;
+}
+
+bool InternalBindingProperty::isValid() const
+{
+ return InternalProperty::isValid() && isBindingProperty();
+}
+
+QString InternalBindingProperty::expression() const
+{
+ return m_expression;
+}
+void InternalBindingProperty::setExpression(const QString &expression)
+{
+ m_expression = expression;
+}
+
+bool InternalBindingProperty::isBindingProperty() const
+{
+ return true;
+}
+
+void InternalBindingProperty::setDynamicExpression(const QString &type, const QString &expression)
+{
+ setExpression(expression);
+ setDynamicTypeName(type);
+}
+
+} // namespace Internal
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/core/model/internalbindingproperty.h b/src/plugins/qmldesigner/core/model/internalbindingproperty.h
new file mode 100644
index 0000000000..1fe8fd08bc
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/internalbindingproperty.h
@@ -0,0 +1,65 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef INTERNALBINDINGPROPERTY_H
+#define INTERNALBINDINGPROPERTY_H
+
+#include "internalproperty.h"
+
+namespace QmlDesigner {
+namespace Internal {
+
+class InternalBindingProperty : public InternalProperty
+{
+public:
+ typedef QSharedPointer<InternalBindingProperty> Pointer;
+
+ static Pointer create(const QString &name, const InternalNodePointer &propertyOwner);
+
+ bool isValid() const;
+
+ QString expression() const;
+ void setExpression(const QString &expression);
+
+ void setDynamicExpression(const QString &type, const QString &expression);
+
+
+ bool isBindingProperty() const;
+
+protected:
+ InternalBindingProperty(const QString &name, const InternalNodePointer &propertyOwner);
+
+private:
+ QString m_expression;
+};
+
+} // namespace Internal
+} // namespace QmlDesigner
+
+#endif // INTERNALBINDINGPROPERTY_H
diff --git a/src/plugins/qmldesigner/core/model/internalnode.cpp b/src/plugins/qmldesigner/core/model/internalnode.cpp
new file mode 100644
index 0000000000..a18a1bad9c
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/internalnode.cpp
@@ -0,0 +1,315 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "internalnode_p.h"
+#include "internalproperty.h"
+#include "internalvariantproperty.h"
+#include "internalnodeproperty.h"
+#include "internalnodelistproperty.h"
+#include "invalidmodelnodeexception.h"
+#include "invalidpropertyexception.h"
+
+#include <QtDebug>
+#include <corelib_global.h>
+
+namespace QmlDesigner {
+namespace Internal {
+
+/*!
+ \class QmlDesigner::Internal::InternalNode
+
+ Represents one XML element.
+ */
+
+InternalNode::InternalNode() :
+ m_valid(false)
+{
+}
+
+InternalNode::InternalNode(const QString &typeName,int majorVersion, int minorVersion):
+ m_typeName(typeName),
+ m_majorVersion(majorVersion),
+ m_minorVersion(minorVersion),
+ m_valid(true)
+{
+
+}
+
+InternalNode::Pointer InternalNode::create(const QString &type,int majorVersion, int minorVersion)
+{
+ InternalNode *newPointer(new InternalNode(type, majorVersion, minorVersion));
+ InternalNode::Pointer smartPointer(newPointer);
+
+ newPointer->setInternalWeakPointer(smartPointer);
+
+ return smartPointer;
+}
+
+InternalNode::Pointer InternalNode::internalPointer() const
+{
+ return m_internalPointer.toStrongRef();
+}
+void InternalNode::setInternalWeakPointer(const Pointer &pointer)
+{
+ m_internalPointer = pointer;
+}
+
+QString InternalNode::type() const
+{
+ return m_typeName;
+}
+
+void InternalNode::setType(const QString &newType)
+{
+ m_typeName = newType;
+}
+
+int InternalNode::minorVersion() const
+{
+ return m_minorVersion;
+}
+
+int InternalNode::majorVersion() const
+{
+ return m_majorVersion;
+}
+
+void InternalNode::setMinorVersion(int number)
+{
+ m_minorVersion = number;
+}
+
+void InternalNode::setMajorVersion(int number)
+{
+ m_majorVersion = number;
+}
+
+bool InternalNode::isValid() const
+{
+ return m_valid;
+}
+
+void InternalNode::setValid(bool valid)
+{
+ m_valid = valid;
+}
+
+InternalNodeAbstractProperty::Pointer InternalNode::parentProperty() const
+{
+ return m_parentProperty;
+}
+void InternalNode::setParentProperty(const InternalNodeAbstractProperty::Pointer &parent)
+{
+ if (m_parentProperty)
+ m_parentProperty->remove(internalPointer());
+
+ Q_ASSERT(parent && parent->isValid());
+ m_parentProperty = parent;
+
+ parent->add(internalPointer());
+}
+
+void InternalNode::resetParentProperty()
+{
+ if (m_parentProperty)
+ m_parentProperty->remove(internalPointer());
+
+ m_parentProperty.clear();
+}
+
+QString InternalNode::id() const
+{
+ return m_id;
+}
+
+void InternalNode::setId(const QString& id)
+{
+ m_id = id;
+}
+
+
+uint qHash(const InternalNodePointer& node)
+{
+ return ::qHash(node.data());
+}
+
+QVariant InternalNode::auxiliaryData(const QString &name) const
+{
+ return m_auxiliaryDataHash.value(name);
+}
+
+void InternalNode::setAuxiliaryData(const QString &name, const QVariant &data)
+{
+ m_auxiliaryDataHash.insert(name, data);
+}
+
+bool InternalNode::hasAuxiliaryData(const QString &name) const
+{
+ return m_auxiliaryDataHash.contains(name);
+}
+
+InternalProperty::Pointer InternalNode::property(const QString &name) const
+{
+ return m_namePropertyHash.value(name);
+}
+
+InternalBindingProperty::Pointer InternalNode::bindingProperty(const QString &name) const
+{
+ InternalProperty::Pointer property = m_namePropertyHash.value(name);
+ if (property->isBindingProperty())
+ return property.staticCast<InternalBindingProperty>();
+
+ return InternalBindingProperty::Pointer();
+}
+
+InternalVariantProperty::Pointer InternalNode::variantProperty(const QString &name) const
+{
+ InternalProperty::Pointer property = m_namePropertyHash.value(name);
+ if (property->isVariantProperty())
+ return property.staticCast<InternalVariantProperty>();
+
+ return InternalVariantProperty::Pointer();
+}
+
+void InternalNode::addBindingProperty(const QString &name)
+{
+ InternalProperty::Pointer newProperty(InternalBindingProperty::create(name, internalPointer()));
+ m_namePropertyHash.insert(name, newProperty);
+}
+
+InternalNodeListProperty::Pointer InternalNode::nodeListProperty(const QString &name) const
+{
+ InternalProperty::Pointer property = m_namePropertyHash.value(name);
+ if (property && property->isNodeListProperty())
+ return property.staticCast<InternalNodeListProperty>();
+
+ return InternalNodeListProperty::Pointer();
+}
+
+InternalNodeAbstractProperty::Pointer InternalNode::nodeAbstractProperty(const QString &name) const
+{
+ InternalProperty::Pointer property = m_namePropertyHash.value(name);
+ if (property && property->isNodeAbstractProperty())
+ return property.staticCast<InternalNodeAbstractProperty>();
+
+ return InternalNodeProperty::Pointer();
+}
+
+InternalNodeProperty::Pointer InternalNode::nodeProperty(const QString &name) const
+{
+ InternalProperty::Pointer property = m_namePropertyHash.value(name);
+ if (property->isNodeProperty())
+ return property.staticCast<InternalNodeProperty>();
+
+ return InternalNodeProperty::Pointer();
+}
+
+void InternalNode::addVariantProperty(const QString &name)
+{
+ InternalProperty::Pointer newProperty(InternalVariantProperty::create(name, internalPointer()));
+ m_namePropertyHash.insert(name, newProperty);
+}
+
+void InternalNode::addNodeProperty(const QString &name)
+{
+ InternalProperty::Pointer newProperty(InternalNodeProperty::create(name, internalPointer()));
+ m_namePropertyHash.insert(name, newProperty);
+}
+
+void InternalNode::addNodeListProperty(const QString &name)
+{
+ InternalProperty::Pointer newProperty(InternalNodeListProperty::create(name, internalPointer()));
+ m_namePropertyHash.insert(name, newProperty);
+}
+
+void InternalNode::removeProperty(const QString &name)
+{
+ InternalProperty::Pointer property = m_namePropertyHash.take(name);
+ Q_ASSERT(!property.isNull());
+}
+
+QList<QString> InternalNode::propertyNameList() const
+{
+ return m_namePropertyHash.keys();
+}
+
+bool InternalNode::hasProperties() const
+{
+ return !m_namePropertyHash.isEmpty();
+}
+
+bool InternalNode::hasProperty(const QString &name) const
+{
+ return m_namePropertyHash.contains(name);
+}
+
+QList<InternalProperty::Pointer> InternalNode::propertyList() const
+{
+ return m_namePropertyHash.values();
+}
+
+QList<InternalNodeAbstractProperty::Pointer> InternalNode::nodeAbstractPropertyList() const
+{
+ QList<InternalNodeAbstractProperty::Pointer> abstractPropertyList;
+ foreach(const InternalProperty::Pointer &property, propertyList()) {
+ if (property->isNodeAbstractProperty())
+ abstractPropertyList.append(property->toNodeAbstractProperty());
+ }
+
+ return abstractPropertyList;
+}
+
+
+QList<InternalNode::Pointer> InternalNode::allSubNodes() const
+{
+ QList<InternalNode::Pointer> nodeList;
+ foreach(const InternalNodeAbstractProperty::Pointer &property, nodeAbstractPropertyList()) {
+ nodeList.append(property->allSubNodes());
+ }
+
+ return nodeList;
+}
+
+QList<InternalNode::Pointer> InternalNode::allDirectSubNodes() const
+{
+ QList<InternalNode::Pointer> nodeList;
+ foreach(const InternalNodeAbstractProperty::Pointer &property, nodeAbstractPropertyList()) {
+ nodeList.append(property->allDirectSubNodes());
+ }
+
+ return nodeList;
+}
+
+bool operator <(const InternalNode::Pointer &firstNode, const InternalNode::Pointer &secondNode)
+{
+ return firstNode.data() < secondNode.data();
+}
+
+}
+}
diff --git a/src/plugins/qmldesigner/core/model/internalnode_p.h b/src/plugins/qmldesigner/core/model/internalnode_p.h
new file mode 100644
index 0000000000..417d58f920
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/internalnode_p.h
@@ -0,0 +1,144 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef INTERNALNODE_H
+#define INTERNALNODE_H
+
+#include <QMap>
+#include <QHash>
+#include <QSharedPointer>
+#include <QWeakPointer>
+#include "internalproperty.h"
+#include "internalvariantproperty.h"
+#include "internalbindingproperty.h"
+#include "internalnodelistproperty.h"
+#include "internalnodeproperty.h"
+#include "internalnodeabstractproperty.h"
+
+namespace QmlDesigner {
+
+class Model;
+
+namespace Internal {
+
+class InternalProperty;
+class InternalNode;
+
+typedef QSharedPointer<InternalNode> InternalNodePointer;
+typedef QSharedPointer<InternalProperty> InternalPropertyPointer;
+typedef QWeakPointer<InternalNode> InternalNodeWeakPointer;
+
+class InternalNode
+{
+ friend class InternalProperty;
+public:
+ typedef QSharedPointer<InternalNode> Pointer;
+ typedef QWeakPointer<InternalNode> WeakPointer;
+
+ explicit InternalNode();
+
+ static Pointer create(const QString &typeName, int majorVersion, int minorVersion);
+
+ QString type() const;
+ void setType(const QString &newType);
+
+ int minorVersion() const;
+ int majorVersion() const;
+ void setMinorVersion(int number);
+ void setMajorVersion(int number);
+
+ bool isValid() const;
+ void setValid(bool valid);
+
+ InternalNodeAbstractProperty::Pointer parentProperty() const;
+
+ // Reparent within model
+ void setParentProperty(const InternalNodeAbstractProperty::Pointer &parent);
+ void resetParentProperty();
+
+ QString id() const;
+ void setId(const QString& id);
+
+ QVariant auxiliaryData(const QString &name) const;
+ void setAuxiliaryData(const QString &name, const QVariant &data);
+ bool hasAuxiliaryData(const QString &name) const;
+
+ InternalProperty::Pointer property(const QString &name) const;
+ InternalBindingProperty::Pointer bindingProperty(const QString &name) const;
+ InternalVariantProperty::Pointer variantProperty(const QString &name) const;
+ InternalNodeListProperty::Pointer nodeListProperty(const QString &name) const;
+ InternalNodeAbstractProperty::Pointer nodeAbstractProperty(const QString &name) const;
+ InternalNodeProperty::Pointer nodeProperty(const QString &name) const;
+
+ void addBindingProperty(const QString &name);
+ void addNodeListProperty(const QString &name);
+ void addVariantProperty(const QString &name);
+ void addNodeProperty(const QString &name);
+
+
+ QList<QString> propertyNameList() const;
+
+ bool hasProperties() const;
+ bool hasProperty(const QString &name) const;
+
+ QList<InternalProperty::Pointer> propertyList() const;
+ QList<InternalNodeAbstractProperty::Pointer> nodeAbstractPropertyList() const;
+ QList<InternalNode::Pointer> allSubNodes() const;
+ QList<InternalNode::Pointer> allDirectSubNodes() const;
+
+protected:
+ Pointer internalPointer() const;
+ void setInternalWeakPointer(const Pointer &pointer);
+ void removeProperty(const QString &name);
+ explicit InternalNode(const QString &type, int majorVersion, int minorVersion);
+
+private:
+ QString m_typeName;
+ QString m_id;
+
+ QHash<QString, QVariant> m_auxiliaryDataHash;
+
+ InternalNodeAbstractProperty::WeakPointer m_parentProperty;
+ WeakPointer m_internalPointer;
+
+ int m_majorVersion;
+ int m_minorVersion;
+
+ bool m_valid;
+
+ QHash<QString, InternalPropertyPointer> m_namePropertyHash;
+};
+
+uint qHash(const InternalNodePointer& node);
+bool operator <(const InternalNodePointer &firstNode, const InternalNodePointer &secondNode);
+
+} // Internal
+} // QtQmlDesigner
+
+#endif // INTERNALNODE_H
diff --git a/src/plugins/qmldesigner/core/model/internalnodeabstractproperty.cpp b/src/plugins/qmldesigner/core/model/internalnodeabstractproperty.cpp
new file mode 100644
index 0000000000..848cc578b8
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/internalnodeabstractproperty.cpp
@@ -0,0 +1,52 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "internalnodeabstractproperty.h"
+#include "internalnode_p.h"
+
+namespace QmlDesigner {
+namespace Internal {
+
+InternalNodeAbstractProperty::InternalNodeAbstractProperty(const QString &name, const InternalNode::Pointer &propertyOwner)
+ : InternalProperty(name, propertyOwner)
+{
+}
+
+bool InternalNodeAbstractProperty::isNodeAbstractProperty() const
+{
+ return true;
+}
+
+bool InternalNodeAbstractProperty::isValid() const
+{
+ return InternalProperty::isValid() && isNodeAbstractProperty();
+}
+
+} // namespace Internal
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/core/model/internalnodeabstractproperty.h b/src/plugins/qmldesigner/core/model/internalnodeabstractproperty.h
new file mode 100644
index 0000000000..29b99c03c9
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/internalnodeabstractproperty.h
@@ -0,0 +1,64 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef INTERNALNODEABSTRACTPROPERTY_H
+#define INTERNALNODEABSTRACTPROPERTY_H
+
+#include "internalproperty.h"
+
+
+namespace QmlDesigner {
+namespace Internal {
+
+class InternalNodeAbstractProperty : public InternalProperty
+{
+ friend class InternalNode;
+
+public:
+ typedef QSharedPointer<InternalNodeAbstractProperty> Pointer;
+ typedef QWeakPointer<InternalNodeAbstractProperty> WeakPointer;
+
+ bool isNodeAbstractProperty() const;
+
+ virtual QList<InternalNodePointer> allSubNodes() const = 0;
+ virtual QList<InternalNodePointer> allDirectSubNodes() const = 0;
+
+ virtual bool isEmpty() const = 0;
+
+ virtual bool isValid() const;
+protected:
+ InternalNodeAbstractProperty(const QString &name, const InternalNodePointer &propertyOwner);
+ virtual void remove(const InternalNodePointer &node) = 0;
+ virtual void add(const InternalNodePointer &node) = 0;
+};
+
+} // namespace Internal
+} // namespace QmlDesigner
+
+#endif // INTERNALNODEABSTRACTPROPERTY_H
diff --git a/src/plugins/qmldesigner/core/model/internalnodelistproperty.cpp b/src/plugins/qmldesigner/core/model/internalnodelistproperty.cpp
new file mode 100644
index 0000000000..38b3b56780
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/internalnodelistproperty.cpp
@@ -0,0 +1,107 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "internalnodelistproperty.h"
+#include "internalnode_p.h"
+#include <QList>
+
+namespace QmlDesigner {
+namespace Internal {
+
+InternalNodeListProperty::InternalNodeListProperty(const QString &name, const InternalNodePointer &propertyOwner)
+ : InternalNodeAbstractProperty(name, propertyOwner)
+{
+}
+
+InternalNodeListProperty::Pointer InternalNodeListProperty::create(const QString &name, const InternalNodePointer &propertyOwner)
+{
+ InternalNodeListProperty *newPointer(new InternalNodeListProperty(name, propertyOwner));
+ InternalProperty::Pointer smartPointer(newPointer);
+
+ newPointer->setInternalWeakPointer(smartPointer.toWeakRef());
+
+ return smartPointer.staticCast<InternalNodeListProperty>();
+}
+
+bool InternalNodeListProperty::isValid() const
+{
+ return InternalProperty::isValid() && isNodeListProperty();
+}
+
+bool InternalNodeListProperty::isEmpty() const
+{
+ return m_nodeList.isEmpty();
+}
+
+bool InternalNodeListProperty::isNodeListProperty() const
+{
+ return true;
+}
+
+void InternalNodeListProperty::add(const InternalNode::Pointer &internalNode)
+{
+ Q_ASSERT(!m_nodeList.contains(internalNode));
+ m_nodeList.append(internalNode);
+}
+
+void InternalNodeListProperty::remove(const InternalNodePointer &internalNode)
+{
+ Q_ASSERT(m_nodeList.contains(internalNode));
+ m_nodeList.removeAll(internalNode);
+}
+
+const QList<InternalNode::Pointer> &InternalNodeListProperty::nodeList() const
+{
+ return m_nodeList;
+}
+
+void InternalNodeListProperty::slide(int from, int to)
+{
+ InternalNode::Pointer internalNode = m_nodeList.takeAt(from);
+ m_nodeList.insert(to, internalNode);
+}
+
+QList<InternalNode::Pointer> InternalNodeListProperty::allSubNodes() const
+{
+ QList<InternalNode::Pointer> nodeList;
+ foreach(const InternalNode::Pointer &childNode, m_nodeList) {
+ nodeList.append(childNode->allSubNodes());
+ nodeList.append(childNode);
+ }
+
+ return nodeList;
+}
+
+QList<InternalNodePointer> InternalNodeListProperty::allDirectSubNodes() const
+{
+ return nodeList();
+}
+
+} // namespace Internal
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/core/model/internalnodelistproperty.h b/src/plugins/qmldesigner/core/model/internalnodelistproperty.h
new file mode 100644
index 0000000000..41827a3fce
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/internalnodelistproperty.h
@@ -0,0 +1,71 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef INTERNALNODELISTPROPERTY_H
+#define INTERNALNODELISTPROPERTY_H
+
+#include "internalnodeabstractproperty.h"
+
+#include <QList>
+
+namespace QmlDesigner {
+
+namespace Internal {
+
+class InternalNodeListProperty : public InternalNodeAbstractProperty
+{
+public:
+ typedef QSharedPointer<InternalNodeListProperty> Pointer;
+
+ static Pointer create(const QString &name, const InternalNodePointer &propertyOwner);
+
+ bool isValid() const;
+
+ bool isEmpty() const;
+
+ bool isNodeListProperty() const;
+
+ QList<InternalNodePointer> allSubNodes() const;
+ QList<InternalNodePointer> allDirectSubNodes() const;
+ const QList<InternalNodePointer> &nodeList() const;
+ void slide(int from, int to);
+
+protected:
+ InternalNodeListProperty(const QString &name, const InternalNodePointer &propertyOwner);
+ void add(const InternalNodePointer &node);
+ void remove(const InternalNodePointer &node);
+
+private:
+ QList<InternalNodePointer> m_nodeList;
+};
+
+} // namespace Internal
+} // namespace QmlDesigner
+
+#endif // INTERNALNODELISTPROPERTY_H
diff --git a/src/plugins/qmldesigner/core/model/internalnodeproperty.cpp b/src/plugins/qmldesigner/core/model/internalnodeproperty.cpp
new file mode 100644
index 0000000000..128a02dd8f
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/internalnodeproperty.cpp
@@ -0,0 +1,109 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "internalnodeproperty.h"
+#include "internalnode_p.h"
+
+namespace QmlDesigner {
+namespace Internal {
+
+InternalNodeProperty::InternalNodeProperty(const QString &name, const InternalNode::Pointer &propertyOwner)
+ : InternalNodeAbstractProperty(name, propertyOwner)
+{
+}
+
+InternalNodeProperty::Pointer InternalNodeProperty::create(const QString &name, const InternalNode::Pointer &propertyOwner)
+{
+ InternalNodeProperty *newPointer = new InternalNodeProperty(name, propertyOwner);
+ InternalNodeProperty::Pointer smartPointer(newPointer);
+
+ newPointer->setInternalWeakPointer(smartPointer);
+
+ return smartPointer;
+}
+
+bool InternalNodeProperty::isEmpty() const
+{
+ return m_node.isNull();
+}
+
+bool InternalNodeProperty::isValid() const
+{
+ return InternalProperty::isValid() && isNodeProperty();
+}
+
+bool InternalNodeProperty::isNodeProperty() const
+{
+ return true;
+}
+
+InternalNode::Pointer InternalNodeProperty::node() const
+{
+ return m_node;
+}
+
+void InternalNodeProperty::remove(const InternalNode::Pointer &node)
+{
+ Q_ASSERT(m_node == node);
+ m_node.clear();
+
+}
+
+void InternalNodeProperty::add(const InternalNode::Pointer &node)
+{
+ Q_ASSERT(node);
+ Q_ASSERT(node->parentProperty());
+ m_node = node;
+}
+
+QList<InternalNode::Pointer> InternalNodeProperty::allSubNodes() const
+{
+ QList<InternalNode::Pointer> nodeList;
+
+ if (node()) {
+ nodeList.append(node()->allSubNodes());
+ nodeList.append(node());
+ }
+
+ return nodeList;
+}
+
+QList<InternalNodePointer> InternalNodeProperty::allDirectSubNodes() const
+{
+ QList<InternalNode::Pointer> nodeList;
+
+ if (node()) {
+ nodeList.append(node());
+ }
+
+ return nodeList;
+}
+
+} // namespace Internal
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/core/model/internalnodeproperty.h b/src/plugins/qmldesigner/core/model/internalnodeproperty.h
new file mode 100644
index 0000000000..d1eec719e9
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/internalnodeproperty.h
@@ -0,0 +1,67 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef INTERNALNODEPROPERTY_H
+#define INTERNALNODEPROPERTY_H
+
+#include "internalnodeabstractproperty.h"
+
+namespace QmlDesigner {
+namespace Internal {
+
+class InternalNodeProperty : public InternalNodeAbstractProperty
+{
+public:
+ typedef QSharedPointer<InternalNodeProperty> Pointer;
+
+ static Pointer create(const QString &name, const InternalNodePointer &propertyOwner);
+
+ bool isValid() const;
+ bool isEmpty() const;
+ bool isNodeProperty() const;
+
+ QList<InternalNodePointer> allSubNodes() const;
+ QList<InternalNodePointer> allDirectSubNodes() const;
+
+ InternalNodePointer node() const;
+
+
+protected:
+ InternalNodeProperty(const QString &name, const InternalNodePointer &node);
+ void add(const InternalNodePointer &node);
+ void remove(const InternalNodePointer &node);
+
+private:
+ InternalNodePointer m_node;
+};
+
+} // namespace Internal
+} // namespace QmlDesigner
+
+#endif // INTERNALNODEPROPERTY_H
diff --git a/src/plugins/qmldesigner/core/model/internalproperty.cpp b/src/plugins/qmldesigner/core/model/internalproperty.cpp
new file mode 100644
index 0000000000..afb1831dfe
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/internalproperty.cpp
@@ -0,0 +1,175 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "internalproperty.h"
+#include "internalbindingproperty.h"
+#include "internalvariantproperty.h"
+#include "internalnodelistproperty.h"
+#include "internalnodeproperty.h"
+#include "propertyparser.h"
+#include "internalnode_p.h"
+#include <QVariant>
+#include <QString>
+#include <QRegExp>
+#include <QSize>
+#include <QSizeF>
+#include <QPoint>
+#include <QPointF>
+
+namespace QmlDesigner {
+
+namespace Internal {
+
+// Creates invalid InternalProperty
+InternalProperty::InternalProperty()
+{
+}
+
+InternalProperty::~InternalProperty()
+{
+}
+
+InternalProperty::InternalProperty(const QString &name, const InternalNode::Pointer &propertyOwner)
+ : m_name(name),
+ m_propertyOwner(propertyOwner)
+{
+ Q_ASSERT_X(!name.isEmpty(), Q_FUNC_INFO, "Name of property cannot be empty");
+}
+
+InternalProperty::Pointer InternalProperty::internalPointer() const
+{
+ Q_ASSERT(!m_internalPointer.isNull());
+ return m_internalPointer.toStrongRef();
+}
+
+void InternalProperty::setInternalWeakPointer(const Pointer &pointer)
+{
+ Q_ASSERT(!pointer.isNull());
+ m_internalPointer = pointer;
+}
+
+
+bool InternalProperty::isValid() const
+{
+ return m_propertyOwner && !m_name.isEmpty();
+}
+
+QString InternalProperty::name() const
+{
+ return m_name;
+}
+
+bool InternalProperty::isBindingProperty() const
+{
+ return false;
+}
+
+bool InternalProperty::isVariantProperty() const
+{
+ return false;
+}
+
+QSharedPointer<InternalBindingProperty> InternalProperty::toBindingProperty() const
+{
+ Q_ASSERT(internalPointer().dynamicCast<InternalBindingProperty>());
+ return internalPointer().staticCast<InternalBindingProperty>();
+}
+
+
+bool InternalProperty::isNodeListProperty() const
+{
+ return false;
+}
+
+bool InternalProperty::isNodeProperty() const
+{
+ return false;
+}
+
+bool InternalProperty::isNodeAbstractProperty() const
+{
+ return false;
+}
+
+QSharedPointer<InternalVariantProperty> InternalProperty::toVariantProperty() const
+
+{
+ Q_ASSERT(internalPointer().dynamicCast<InternalVariantProperty>());
+ return internalPointer().staticCast<InternalVariantProperty>();
+}
+
+InternalNode::Pointer InternalProperty::propertyOwner() const
+{
+ return m_propertyOwner.toStrongRef();
+}
+
+QSharedPointer<InternalNodeListProperty> InternalProperty::toNodeListProperty() const
+{
+ Q_ASSERT(internalPointer().dynamicCast<InternalNodeListProperty>());
+ return internalPointer().staticCast<InternalNodeListProperty>();
+}
+
+QSharedPointer<InternalNodeProperty> InternalProperty::toNodeProperty() const
+{
+ Q_ASSERT(internalPointer().dynamicCast<InternalNodeProperty>());
+ return internalPointer().staticCast<InternalNodeProperty>();
+}
+
+QSharedPointer<InternalNodeAbstractProperty> InternalProperty::toNodeAbstractProperty() const
+{
+ Q_ASSERT(internalPointer().dynamicCast<InternalNodeAbstractProperty>());
+ return internalPointer().staticCast<InternalNodeAbstractProperty>();
+}
+
+void InternalProperty::remove()
+{
+ propertyOwner()->removeProperty(name());
+ m_propertyOwner.clear();
+}
+
+QString InternalProperty::dynamicTypeName() const
+{
+ return m_dynamicType;
+}
+
+void InternalProperty::setDynamicTypeName(const QString &name)
+{
+ m_dynamicType = name;
+}
+
+
+void InternalProperty::resetDynamicTypeName()
+{
+ m_dynamicType = QString();
+}
+
+
+} //namespace Internal
+} //namespace QmlDesigner
+
diff --git a/src/plugins/qmldesigner/core/model/internalproperty.h b/src/plugins/qmldesigner/core/model/internalproperty.h
new file mode 100644
index 0000000000..f694569abd
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/internalproperty.h
@@ -0,0 +1,109 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef INTERNALPROPERTY_H
+#define INTERNALPROPERTY_H
+
+#include "corelib_global.h"
+
+#include <QVariant>
+#include <QString>
+#include <QRegExp>
+#include <QSize>
+#include <QSizeF>
+#include <QPoint>
+#include <QPointF>
+#include <QSharedPointer>
+
+namespace QmlDesigner {
+
+namespace Internal {
+
+class InternalBindingProperty;
+class InternalVariantProperty;
+class InternalNodeListProperty;
+class InternalNodeProperty;
+class InternalNodeAbstractProperty;
+class InternalNode;
+
+typedef QSharedPointer<InternalNode> InternalNodePointer;
+typedef QWeakPointer<InternalNode> InternalNodeWeakPointer;
+
+class CORESHARED_EXPORT InternalProperty
+{
+public:
+ typedef QSharedPointer<InternalProperty> Pointer;
+ typedef QWeakPointer<InternalProperty> WeakPointer;
+
+
+ InternalProperty();
+ virtual ~InternalProperty();
+
+ virtual bool isValid() const;
+
+ QString name() const;
+
+ virtual bool isBindingProperty() const;
+ virtual bool isVariantProperty() const;
+ virtual bool isNodeListProperty() const;
+ virtual bool isNodeProperty() const;
+ virtual bool isNodeAbstractProperty() const;
+
+ QSharedPointer<InternalBindingProperty> toBindingProperty() const;
+ QSharedPointer<InternalVariantProperty> toVariantProperty() const;
+ QSharedPointer<InternalNodeListProperty> toNodeListProperty() const;
+ QSharedPointer<InternalNodeProperty> toNodeProperty() const;
+ QSharedPointer<InternalNodeAbstractProperty> toNodeAbstractProperty() const;
+
+ InternalNodePointer propertyOwner() const;
+
+ virtual void remove();
+
+
+ QString dynamicTypeName() const;
+
+ void resetDynamicTypeName();
+
+protected: // functions
+ InternalProperty(const QString &name, const InternalNodePointer &propertyOwner);
+ Pointer internalPointer() const;
+ void setInternalWeakPointer(const Pointer &pointer);
+ void setDynamicTypeName(const QString &name);
+private:
+ WeakPointer m_internalPointer;
+ QString m_name;
+ QString m_dynamicType;
+ InternalNodeWeakPointer m_propertyOwner;
+
+};
+
+} // namespace Internal
+} // namespace QmlDesigner
+
+#endif // INTERNALPROPERTY_H
diff --git a/src/plugins/qmldesigner/core/model/internalvariantproperty.cpp b/src/plugins/qmldesigner/core/model/internalvariantproperty.cpp
new file mode 100644
index 0000000000..95446dcd5b
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/internalvariantproperty.cpp
@@ -0,0 +1,77 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "internalvariantproperty.h"
+
+namespace QmlDesigner {
+namespace Internal {
+
+InternalVariantProperty::InternalVariantProperty(const QString &name, const InternalNodePointer &node)
+ : InternalProperty(name, node)
+{
+}
+
+InternalVariantProperty::Pointer InternalVariantProperty::create(const QString &name, const InternalNodePointer &propertyOwner)
+{
+ InternalVariantProperty *newPointer(new InternalVariantProperty(name, propertyOwner));
+ InternalVariantProperty::Pointer smartPointer(newPointer);
+
+ newPointer->setInternalWeakPointer(smartPointer);
+
+ return smartPointer;
+}
+
+QVariant InternalVariantProperty::value() const
+{
+ return m_value;
+}
+
+void InternalVariantProperty::setValue(const QVariant &value)
+{
+ m_value = value;
+}
+
+bool InternalVariantProperty::isVariantProperty() const
+{
+ return true;
+}
+
+void InternalVariantProperty::setDynamicValue(const QString &type, const QVariant &value)
+{
+ setValue(value);
+ setDynamicTypeName(type);
+}
+
+bool InternalVariantProperty::isValid() const
+{
+ return InternalProperty::isValid() && isVariantProperty();
+}
+
+} // namespace Internal
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/core/model/internalvariantproperty.h b/src/plugins/qmldesigner/core/model/internalvariantproperty.h
new file mode 100644
index 0000000000..e881bb1db0
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/internalvariantproperty.h
@@ -0,0 +1,64 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef INTERNALVARIANTPROPERTY_H
+#define INTERNALVARIANTPROPERTY_H
+
+#include "internalproperty.h"
+
+namespace QmlDesigner {
+namespace Internal {
+
+class InternalVariantProperty : public InternalProperty
+{
+public:
+ typedef QSharedPointer<InternalVariantProperty> Pointer;
+
+ static Pointer create(const QString &name, const InternalNodePointer &propertyOwner);
+
+ bool isValid() const;
+
+ QVariant value() const;
+ void setValue(const QVariant &value);
+
+ void setDynamicValue(const QString &type, const QVariant &value);
+
+ bool isVariantProperty() const;
+
+protected:
+ InternalVariantProperty(const QString &name, const InternalNodePointer &propertyOwner);
+
+private:
+ QVariant m_value;
+};
+
+} // namespace Internal
+} // namespace QmlDesigner
+
+#endif // INTERNALVARIANTPROPERTY_H
diff --git a/src/plugins/qmldesigner/core/model/model.cpp b/src/plugins/qmldesigner/core/model/model.cpp
new file mode 100644
index 0000000000..a837a811e4
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/model.cpp
@@ -0,0 +1,918 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <model.h>
+#include <modelnode.h>
+#include "internalnode_p.h"
+#include "invalidpropertyexception.h"
+#include "invalidargumentexception.h"
+
+#include <QtCore/QFile>
+#include <QtCore/QByteArray>
+#include <QWeakPointer>
+#include <QtCore/QFileInfo>
+
+#include <QtGui/QUndoStack>
+#include <QtXml/QXmlStreamReader>
+#include <QtCore/QDebug>
+#include <QPlainTextEdit>
+
+#include "abstractview.h"
+#include "widgetqueryview.h"
+#include "metainfo.h"
+#include "model_p.h"
+#include "modelutilities.h"
+#include "subcomponentmanager.h"
+#include "variantparser.h"
+#include "internalproperty.h"
+#include "internalnodelistproperty.h"
+#include "internalnodeabstractproperty.h"
+#include "invalidmodelnodeexception.h"
+#include "invalidmodelstateexception.h"
+#include "invalidslideindexexception.h"
+
+#include "abstractproperty.h"
+#include "variantproperty.h"
+#include "bindingproperty.h"
+#include "nodeabstractproperty.h"
+#include "nodelistproperty.h"
+#include "rewritertransaction.h"
+
+/*!
+\defgroup CoreModel
+*/
+/*!
+\class QmlDesigner::Model
+\ingroup CoreModel
+\brief This is the facade for the abstract model data.
+ All write access is running through this interface
+
+The Model is the central place to access a qml files data (see e.g. rootNode() ) and meta data (see metaInfo() ).
+
+Components that want to be informed about changes in the model can register a subclass of AbstractView via attachView().
+
+\see QmlDesigner::ModelNode, QmlDesigner::AbstractProperty, QmlDesigner::AbstractView
+*/
+
+namespace QmlDesigner {
+namespace Internal {
+
+ModelPrivate::ModelPrivate(Model *model) :
+ m_q(model),
+ m_rootInternalNode(createNode("Qt/Rectangle", 4, 6, PropertyListType()))
+{
+}
+
+ModelPrivate::~ModelPrivate()
+{
+
+ detachAllViews();
+}
+
+void ModelPrivate::detachAllViews()
+{
+ foreach (const QWeakPointer<AbstractView> &view, m_viewList)
+ detachView(view.data(), true);
+
+ m_viewList.clear();
+}
+
+Model *ModelPrivate::create(QString type, int major, int minor)
+{
+ Model *model = new Model;
+
+ model->m_d->rootNode()->setType(type);
+ model->m_d->rootNode()->setMajorVersion(major);
+ model->m_d->rootNode()->setMinorVersion(minor);
+
+ return model;
+}
+
+void ModelPrivate::setImports(const QSet<Import> &imports)
+{
+ QList<Import> added = QSet<Import>(imports).subtract(m_imports).toList();
+ QList<Import> removed = QSet<Import>(m_imports).subtract(imports).toList();
+
+ if (added.isEmpty() && removed.isEmpty())
+ return;
+
+ m_imports = imports;
+
+ notifyImportsChanged();
+}
+
+void ModelPrivate::addImport(const Import &import)
+{
+ if (m_imports.contains(import))
+ return;
+
+ m_imports.insert(import);
+ notifyImportsChanged();
+}
+
+void ModelPrivate::removeImport(const Import &import)
+{
+ if (!m_imports.remove(import))
+ return;
+
+ notifyImportsChanged();
+}
+
+void ModelPrivate::notifyImportsChanged() const
+{
+ foreach (const QWeakPointer<AbstractView> &view, m_viewList)
+ view->importsChanged();
+}
+
+QUrl ModelPrivate::fileUrl() const
+{
+ return m_fileUrl;
+}
+
+void ModelPrivate::setFileUrl(const QUrl &fileUrl)
+{
+ QUrl oldPath = m_fileUrl;
+
+ if (oldPath != fileUrl) {
+ m_fileUrl = fileUrl;
+
+ foreach (const QWeakPointer<AbstractView> &view, m_viewList)
+ view->fileUrlChanged(oldPath, fileUrl);
+ }
+}
+
+InternalNode::Pointer ModelPrivate::createNode(const QString &typeString,
+ int majorVersion,
+ int minorVersion,
+ const QList<QPair<QString, QVariant> > &propertyList)
+{
+ if (typeString.isEmpty())
+ throw InvalidArgumentException(__LINE__, __FUNCTION__, __FILE__, "typeString");
+ if (!m_metaInfo.nodeMetaInfo(typeString).isValid())
+ throw InvalidArgumentException(__LINE__, __FUNCTION__, __FILE__, "typeString");
+
+ InternalNode::Pointer newInternalNodePointer = InternalNode::create(typeString, majorVersion, minorVersion);
+
+ typedef QPair<QString, QVariant> PropertyPair;
+
+ foreach (const PropertyPair &propertyPair, propertyList) {
+ newInternalNodePointer->addVariantProperty(propertyPair.first);
+ newInternalNodePointer->variantProperty(propertyPair.first)->setValue(propertyPair.second);
+ }
+
+ m_nodeSet.insert(newInternalNodePointer);
+
+ notifyNodeCreated(newInternalNodePointer);
+
+ return newInternalNodePointer;
+}
+
+void ModelPrivate::removeNodeFromModel(const InternalNodePointer &node)
+{
+ Q_ASSERT(!node.isNull());
+
+ node->resetParentProperty();
+
+ if (!node->id().isEmpty())
+ m_idNodeHash.remove(node->id());
+ node->setValid(false);
+ m_nodeSet.remove(node);
+}
+
+void ModelPrivate::removeAllSubNodes(const InternalNode::Pointer &node)
+{
+ foreach (const InternalNodePointer &subNode, node->allSubNodes()) {
+ removeNodeFromModel(subNode);
+ }
+}
+
+void ModelPrivate::removeNode(const InternalNode::Pointer &node)
+{
+ Q_ASSERT(!node.isNull());
+
+ AbstractView::PropertyChangeFlags propertyChangeFlags = AbstractView::NoAdditionalChanges;
+
+ notifyNodeAboutToBeRemoved(node);
+
+ InternalNodeAbstractProperty::Pointer oldParentProperty(node->parentProperty());
+
+ removeAllSubNodes(node);
+ removeNodeFromModel(node);
+
+ InternalNode::Pointer parentNode;
+ QString parentPropertyName;
+ if (oldParentProperty) {
+ parentNode = oldParentProperty->propertyOwner();
+ parentPropertyName = oldParentProperty->name();
+ }
+
+ if (oldParentProperty && oldParentProperty->isEmpty()) {
+ removePropertyWithoutNotification(oldParentProperty);
+
+ propertyChangeFlags |= AbstractView::EmptyPropertiesRemoved;
+ }
+
+ notifyNodeRemoved(node, parentNode, parentPropertyName, propertyChangeFlags);
+}
+
+InternalNode::Pointer ModelPrivate::rootNode() const
+{
+ return m_rootInternalNode;
+}
+
+MetaInfo ModelPrivate::metaInfo() const
+{
+ return m_metaInfo;
+}
+
+void ModelPrivate::changeNodeId(const InternalNode::Pointer& internalNodePointer, const QString &id)
+{
+ const QString oldId = internalNodePointer->id();
+
+ internalNodePointer->setId(id);
+ if (!oldId.isEmpty())
+ m_idNodeHash.remove(oldId);
+ if (!id.isEmpty())
+ m_idNodeHash.insert(id, internalNodePointer);
+ notifyNodeIdChanged(internalNodePointer, id, oldId);
+}
+
+void ModelPrivate::checkPropertyName(const QString &propertyName)
+{
+ if (propertyName.isEmpty()) {
+ Q_ASSERT_X(propertyName.isEmpty(), Q_FUNC_INFO, "empty property name");
+ throw InvalidPropertyException(__LINE__, __FUNCTION__, __FILE__, "<empty property name>");
+ }
+
+ if (propertyName == "id") {
+ Q_ASSERT_X(propertyName != "id", Q_FUNC_INFO, "cannot add property id");
+ throw InvalidPropertyException(__LINE__, __FUNCTION__, __FILE__, propertyName);
+ }
+}
+
+void ModelPrivate::notifyAuxiliaryDataChanged(const InternalNodePointer &internalNode, const QString &name, const QVariant &data)
+{
+ foreach (const QWeakPointer<AbstractView> &view, m_viewList) {
+ Q_ASSERT(view != 0);
+ ModelNode node(internalNode, model(), view.data());
+ view->auxiliaryDataChanged(node, name, data);
+ }
+}
+
+void ModelPrivate::notifyNodeTypeChanged(const InternalNodePointer &internalNode, const QString &type, int majorVersion, int minorVersion)
+{
+ foreach (const QWeakPointer<AbstractView> &view, m_viewList) {
+ Q_ASSERT(view != 0);
+ ModelNode node(internalNode, model(), view.data());
+ view->nodeTypeChanged(node, type, majorVersion, minorVersion);
+ }
+}
+
+void ModelPrivate::notifyCustomNotification(const AbstractView *senderView, const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> &data)
+{
+ QList<Internal::InternalNode::Pointer> internalList(toInternalNodeList(nodeList));
+ foreach (const QWeakPointer<AbstractView> &view, m_viewList) {
+ Q_ASSERT(view != 0);
+ view->customNotification(senderView, identifier, toModelNodeList(internalList, view.data()), data);
+ }
+}
+
+
+void ModelPrivate::notifyPropertiesRemoved(const QList<PropertyPair> &propertyPairList)
+{
+ foreach (const QWeakPointer<AbstractView> &view, m_viewList) {
+ QList<AbstractProperty> propertyList;
+ Q_ASSERT(view != 0);
+ foreach (const PropertyPair &propertyPair, propertyPairList) {
+ AbstractProperty newProperty(propertyPair.second, propertyPair.first, model(), view.data());
+ propertyList.append(newProperty);
+ }
+ view->propertiesRemoved(propertyList);
+ }
+}
+
+void ModelPrivate::notifyPropertiesAboutToBeRemoved(const QList<InternalProperty::Pointer> &internalPropertyList)
+{
+ foreach (const QWeakPointer<AbstractView> &view, m_viewList) {
+ QList<AbstractProperty> propertyList;
+ Q_ASSERT(view != 0);
+ foreach (const InternalProperty::Pointer &property, internalPropertyList) {
+ AbstractProperty newProperty(property->name(), property->propertyOwner(), model(), view.data());
+ propertyList.append(newProperty);
+ }
+ view->propertiesAboutToBeRemoved(propertyList);
+ }
+}
+
+void ModelPrivate::setAuxiliaryData(const InternalNode::Pointer& node, const QString &name, const QVariant &data)
+{
+ node->setAuxiliaryData(name, data);
+ notifyAuxiliaryDataChanged(node, name,data);
+}
+
+
+void ModelPrivate::attachView(AbstractView *view)
+{
+ if (m_viewList.contains(view))
+ return;
+
+ m_viewList.append(view);
+
+ view->modelAttached(m_q);
+}
+
+void ModelPrivate::detachView(AbstractView *view, bool notifyView)
+{
+ if (notifyView)
+ view->modelAboutToBeDetached(m_q);
+ m_viewList.removeOne(view);
+}
+
+void ModelPrivate::notifyNodeCreated(const InternalNode::Pointer &newInternalNodePointer)
+{
+ Q_ASSERT(newInternalNodePointer->isValid());
+
+ foreach (const QWeakPointer<AbstractView> &view, m_viewList) {
+ Q_ASSERT(view != 0);
+ ModelNode createdNode(newInternalNodePointer, model(), view.data());
+ view->nodeCreated(createdNode);
+ }
+}
+
+void ModelPrivate::notifyNodeAboutToBeRemoved(const InternalNode::Pointer &nodePointer)
+{
+ foreach (const QWeakPointer<AbstractView> &view, m_viewList) {
+ Q_ASSERT(view != 0);
+ ModelNode node(nodePointer, model(), view.data());
+ view->nodeAboutToBeRemoved(node);
+ }
+}
+
+void ModelPrivate::notifyNodeRemoved(const InternalNodePointer &nodePointer, const InternalNodePointer &parentNodePointer, const QString &parentPropertyName, AbstractView::PropertyChangeFlags propertyChange)
+{
+ foreach (const QWeakPointer<AbstractView> &view, m_viewList) {
+ Q_ASSERT(view != 0);
+ ModelNode node(nodePointer, model(), view.data());
+ NodeAbstractProperty parentProperty(parentPropertyName, parentNodePointer, model(), view.data());
+ view->nodeRemoved(node, parentProperty, propertyChange);
+ }
+}
+
+void ModelPrivate::notifyNodeIdChanged(const InternalNode::Pointer& nodePointer, const QString& newId, const QString& oldId)
+{
+ foreach (const QWeakPointer<AbstractView> &view, m_viewList) {
+ Q_ASSERT(view != 0);
+ ModelNode node(nodePointer, model(), view.data());
+ view->nodeIdChanged(node, newId, oldId);
+ }
+}
+
+void ModelPrivate::notifyBindingPropertiesChanged(const QList<InternalBindingPropertyPointer> &internalBropertyList, AbstractView::PropertyChangeFlags propertyChange)
+{
+ foreach (const QWeakPointer<AbstractView> &view, m_viewList) {
+ QList<BindingProperty> propertyList;
+ Q_ASSERT(view != 0);
+ foreach (const InternalBindingPropertyPointer &bindingProperty, internalBropertyList) {
+ propertyList.append(BindingProperty(bindingProperty->name(), bindingProperty->propertyOwner(), model(), view.data()));
+ }
+ view->bindingPropertiesChanged(propertyList, propertyChange);
+ }
+}
+
+void ModelPrivate::notifyVariantPropertiesChanged(const InternalNodePointer &internalNodePointer, const QStringList& propertyNameList, AbstractView::PropertyChangeFlags propertyChange)
+{
+ foreach (const QWeakPointer<AbstractView> &view, m_viewList) {
+ QList<VariantProperty> propertyList;
+ Q_ASSERT(view != 0);
+ foreach (const QString &propertyName, propertyNameList) {
+ Q_ASSERT(internalNodePointer->hasProperty(propertyName));
+ Q_ASSERT(internalNodePointer->property(propertyName)->isVariantProperty());
+ VariantProperty property(propertyName, internalNodePointer, model(), view.data());
+ propertyList.append(property);
+ }
+ ModelNode node(internalNodePointer, model(), view.data());
+ view->variantPropertiesChanged(propertyList, propertyChange);
+ }
+}
+
+void ModelPrivate::notifyNodeReparent(const InternalNode::Pointer &internalNodePointer, const InternalNodeAbstractProperty::Pointer &newPropertyParent, const InternalNodePointer &oldParent, const QString &oldPropertyName, AbstractView::PropertyChangeFlags propertyChange)
+{
+ foreach (const QWeakPointer<AbstractView> &view, m_viewList) {
+ NodeAbstractProperty newProperty;
+ NodeAbstractProperty oldProperty;
+
+ Q_ASSERT(!view.isNull());
+ if (!oldPropertyName.isEmpty() && oldParent->isValid())
+ oldProperty = NodeAbstractProperty(oldPropertyName, oldParent, model(), view.data());
+
+ if (!newPropertyParent.isNull())
+ newProperty = NodeAbstractProperty(newPropertyParent, model(), view.data());
+ ModelNode node(internalNodePointer, model(), view.data());
+ view->nodeReparented(node, newProperty, oldProperty, propertyChange);
+ }
+ }
+
+void ModelPrivate::notifyNodeSlidedToIndex(const InternalNodeListProperty::Pointer &internalNodeListproperty, int newIndex, int oldIndex)
+{
+ foreach (const QWeakPointer<AbstractView> &view, m_viewList) {
+ Q_ASSERT(view != 0);
+ NodeListProperty nodeListproperty(internalNodeListproperty, model(), view.data());
+ view->nodeSlidedToIndex(nodeListproperty, newIndex, oldIndex);
+ }
+}
+
+void ModelPrivate::setSelectedNodes(const QList<InternalNode::Pointer> &selectedNodeList)
+{
+
+ QList<InternalNode::Pointer> sortedSelectedList(selectedNodeList);
+ QMutableListIterator<InternalNode::Pointer> iterator(sortedSelectedList);
+ while (iterator.hasNext()) {
+ InternalNode::Pointer node(iterator.next());
+ if (!node->isValid())
+ iterator.remove();
+ }
+
+ sortedSelectedList = sortedSelectedList.toSet().toList();
+ qSort(sortedSelectedList);
+
+ if (sortedSelectedList == m_selectedNodeList)
+ return;
+
+
+ const QList<InternalNode::Pointer> lastSelectedNodeList = m_selectedNodeList;
+ m_selectedNodeList = sortedSelectedList;
+
+ changeSelectedNodes(sortedSelectedList, lastSelectedNodeList);
+}
+
+
+void ModelPrivate::clearSelectedNodes()
+{
+ const QList<InternalNode::Pointer> lastSelectedNodeList = m_selectedNodeList;
+ m_selectedNodeList.clear();
+ changeSelectedNodes(m_selectedNodeList, lastSelectedNodeList);
+}
+
+QList<ModelNode> ModelPrivate::toModelNodeList(const QList<InternalNode::Pointer> &nodeList, AbstractView *view) const
+{
+ QList<ModelNode> newNodeList;
+ foreach (const Internal::InternalNode::Pointer &node, nodeList)
+ newNodeList.append(ModelNode(node, model(), view));
+
+ return newNodeList;
+}
+
+QList<Internal::InternalNode::Pointer> ModelPrivate::toInternalNodeList(const QList<ModelNode> &nodeList) const
+{
+ QList<Internal::InternalNode::Pointer> newNodeList;
+ foreach (const ModelNode &node, nodeList)
+ newNodeList.append(node.internalNode());
+
+ return newNodeList;
+}
+
+void ModelPrivate::changeSelectedNodes(const QList<InternalNode::Pointer> &newSelectedNodeList,
+ const QList<InternalNode::Pointer> &oldSelectedNodeList)
+{
+ foreach (const QWeakPointer<AbstractView> &view, m_viewList) {
+ Q_ASSERT(view != 0);
+ view->selectedNodesChanged(toModelNodeList(newSelectedNodeList, view.data()), toModelNodeList(oldSelectedNodeList, view.data()));
+ }
+}
+
+QList<InternalNode::Pointer> ModelPrivate::selectedNodes() const
+{
+ foreach (const InternalNode::Pointer &node, m_selectedNodeList) {
+ if (!node->isValid())
+ throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+ }
+
+ return m_selectedNodeList;
+}
+
+void ModelPrivate::selectNode(const InternalNode::Pointer &node)
+{
+ if (selectedNodes().contains(node))
+ return;
+
+ QList<InternalNode::Pointer> selectedNodeList(selectedNodes());
+ selectedNodeList += node;
+ setSelectedNodes(selectedNodeList);
+}
+
+void ModelPrivate::deselectNode(const InternalNode::Pointer &node)
+{
+ QList<InternalNode::Pointer> selectedNodeList(selectedNodes());
+ bool isRemoved = selectedNodeList.removeOne(node);
+
+ if (!isRemoved)
+ return;
+
+ setSelectedNodes(selectedNodeList);
+}
+
+void ModelPrivate::removePropertyWithoutNotification(const InternalPropertyPointer &property)
+{
+ if (property->isNodeAbstractProperty()) {
+ foreach (const InternalNode::Pointer & internalNode, property->toNodeAbstractProperty()->allSubNodes())
+ removeNodeFromModel(internalNode);
+ }
+
+ property->remove();
+}
+
+static QList<PropertyPair> toPropertyPairList(const QList<InternalProperty::Pointer> &propertyList)
+{
+ QList<PropertyPair> propertyPairList;
+
+ foreach (const InternalProperty::Pointer &property, propertyList)
+ propertyPairList.append(qMakePair(property->propertyOwner(), property->name()));
+
+ return propertyPairList;
+
+}
+
+void ModelPrivate::removeProperty(const InternalProperty::Pointer &property)
+{
+ notifyPropertiesAboutToBeRemoved(QList<InternalProperty::Pointer>() << property);
+
+ QList<PropertyPair> propertyPairList = toPropertyPairList(QList<InternalProperty::Pointer>() << property);
+
+ removePropertyWithoutNotification(property);
+
+ notifyPropertiesRemoved(propertyPairList);
+}
+
+void ModelPrivate::setBindingProperty(const InternalNode::Pointer &internalNode, const QString &name, const QString &expression)
+{
+ AbstractView::PropertyChangeFlags propertyChange = AbstractView::NoAdditionalChanges;
+ if (!internalNode->hasProperty(name)) {
+ internalNode->addBindingProperty(name);
+ propertyChange = AbstractView::PropertiesAdded;
+ }
+
+ InternalBindingProperty::Pointer bindingProperty = internalNode->bindingProperty(name);
+ bindingProperty->setExpression(expression);
+ notifyBindingPropertiesChanged(QList<InternalBindingPropertyPointer>() << bindingProperty, propertyChange);
+}
+
+void ModelPrivate::setVariantProperty(const InternalNode::Pointer &internalNode, const QString &name, const QVariant &value)
+{
+ AbstractView::PropertyChangeFlags propertyChange = AbstractView::NoAdditionalChanges;
+ if (!internalNode->hasProperty(name)) {
+ internalNode->addVariantProperty(name);
+ propertyChange = AbstractView::PropertiesAdded;
+ }
+
+ internalNode->variantProperty(name)->setValue(value);
+ internalNode->variantProperty(name)->resetDynamicTypeName();
+ notifyVariantPropertiesChanged(internalNode, QStringList() << name, propertyChange);
+}
+
+void ModelPrivate::setDynamicVariantProperty(const InternalNodePointer &internalNode, const QString &name, const QString &dynamicPropertyType, const QVariant &value)
+{
+ AbstractView::PropertyChangeFlags propertyChange = AbstractView::NoAdditionalChanges;
+ if (!internalNode->hasProperty(name)) {
+ internalNode->addVariantProperty(name);
+ propertyChange = AbstractView::PropertiesAdded;
+ }
+
+ internalNode->variantProperty(name)->setDynamicValue(dynamicPropertyType, value);
+ notifyVariantPropertiesChanged(internalNode, QStringList() << name, propertyChange);
+}
+
+void ModelPrivate::setDynamicBindingProperty(const InternalNodePointer &internalNode, const QString &name, const QString &dynamicPropertyType, const QString &expression)
+{
+ AbstractView::PropertyChangeFlags propertyChange = AbstractView::NoAdditionalChanges;
+ if (!internalNode->hasProperty(name)) {
+ internalNode->addBindingProperty(name);
+ propertyChange = AbstractView::PropertiesAdded;
+ }
+
+ InternalBindingProperty::Pointer bindingProperty = internalNode->bindingProperty(name);
+ bindingProperty->setDynamicExpression(dynamicPropertyType, expression);
+ notifyBindingPropertiesChanged(QList<InternalBindingPropertyPointer>() << bindingProperty, propertyChange);
+}
+
+void ModelPrivate::reparentNode(const InternalNode::Pointer &newParentNode, const QString &name, const InternalNode::Pointer &node, bool list)
+{
+ AbstractView::PropertyChangeFlags propertyChange = AbstractView::NoAdditionalChanges;
+ if (!newParentNode->hasProperty(name)) {
+ if (list)
+ newParentNode->addNodeListProperty(name);
+ else
+ newParentNode->addNodeProperty(name);
+ propertyChange |= AbstractView::PropertiesAdded;
+ }
+
+ InternalNodeAbstractProperty::Pointer oldParentProperty(node->parentProperty());
+ InternalNode::Pointer oldParentNode;
+ QString oldParentPropertyName;
+ if (oldParentProperty && oldParentProperty->isValid()) {
+ oldParentNode = node->parentProperty()->propertyOwner();
+ oldParentPropertyName = node->parentProperty()->name();
+ }
+
+ InternalNodeAbstractProperty::Pointer newParentProperty(newParentNode->nodeAbstractProperty(name));
+ Q_ASSERT(!newParentProperty.isNull());
+ if (newParentProperty)
+ node->setParentProperty(newParentProperty);
+
+
+ if (oldParentProperty && oldParentProperty->isValid() && oldParentProperty->isEmpty()) {
+ removePropertyWithoutNotification(oldParentProperty);
+
+ propertyChange |= AbstractView::EmptyPropertiesRemoved;
+ }
+
+ notifyNodeReparent(node, newParentProperty, oldParentNode, oldParentPropertyName, propertyChange);
+}
+
+void ModelPrivate::clearParent(const InternalNodePointer &node)
+{
+
+ InternalNodeAbstractProperty::Pointer oldParentProperty(node->parentProperty());
+ InternalNode::Pointer oldParentNode;
+ QString oldParentPropertyName;
+ if (oldParentProperty->isValid()) {
+ oldParentNode = node->parentProperty()->propertyOwner();
+ oldParentPropertyName = node->parentProperty()->name();
+ }
+
+ node->resetParentProperty();
+ notifyNodeReparent(node, InternalNodeAbstractProperty::Pointer(), oldParentNode, oldParentPropertyName, AbstractView::NoAdditionalChanges);
+}
+
+void ModelPrivate::changeType(const InternalNodePointer &internalNode, const QString &type, int majorVersion, int minorVersion)
+{
+ Q_ASSERT(!internalNode.isNull());
+ internalNode->setType(type);
+ internalNode->setMajorVersion(majorVersion);
+ internalNode->setMinorVersion(minorVersion);
+ notifyNodeTypeChanged(internalNode, type, majorVersion, minorVersion);
+}
+
+void ModelPrivate::slideNodeList(const InternalNode::Pointer &internalNode, const QString &name, int from, int to)
+{
+ InternalNodeListProperty::Pointer nodeList(internalNode->nodeListProperty(name));
+ Q_ASSERT(!nodeList.isNull());
+ nodeList->slide(from, to);
+ notifyNodeSlidedToIndex(nodeList, to, from);
+}
+
+
+void ModelPrivate::setRootNode(const InternalNode::Pointer& newRootNode)
+{
+ removeNode(m_rootInternalNode);
+ m_rootInternalNode = newRootNode;
+
+ if (!m_rootInternalNode.isNull() && m_rootInternalNode->isValid())
+ notifyNodeCreated(m_rootInternalNode);
+}
+
+
+InternalNodePointer ModelPrivate::nodeForId(const QString &id) const
+{
+ return m_idNodeHash.value(id);
+}
+
+bool ModelPrivate::hasId(const QString &id) const
+{
+ return m_idNodeHash.contains(id);
+}
+
+QList<InternalNodePointer> ModelPrivate::allNodes() const
+{
+ return m_nodeSet.toList();
+}
+
+//static QString anchorLinePropertyValue(const InternalNode::Pointer &sourceNode, const InternalNode::Pointer &targetNode, const AnchorLine::Type &targetType)
+//{
+// if (targetNode.isNull() || !targetNode->isValid())
+// return QString();
+//
+// if (sourceNode.isNull() || !sourceNode->isValid())
+// return QString();
+//
+// if (targetNode == sourceNode)
+// return QString();
+//
+// QString anchorLineType = InternalNodeAnchors::lineTypeToString(targetType);
+//
+// // handle "parent" and "parent.something"
+// if (targetNode == sourceNode->parentNode()) {
+// if (anchorLineType.isNull())
+// return QLatin1String("parent");
+// else
+// return QString("parent.%1").arg(anchorLineType);
+// }
+//
+// if (anchorLineType.isNull())
+// return QString(); // for sibling reference, the type cannot be empty anymore.
+//
+// foreach (const InternalNode::Pointer &sibling, sourceNode->parentNode()->childNodes()) {
+// if (sibling == targetNode) {
+// return QString("%1.%2").arg(sibling->id(), anchorLineType);
+// }
+// }
+//
+// return QString();
+//}
+
+}
+
+
+Model::Model() :
+ QObject(),
+ m_d(new Internal::ModelPrivate(this))
+{
+}
+
+
+Model::~Model()
+{
+ delete m_d;
+}
+
+
+Model *Model::create(QString type, int major, int minor)
+{
+ return Internal::ModelPrivate::create(type, major, minor);
+}
+
+
+/*!
+ \brief Creates a model for a component definition
+
+ Creates a model containing the content of a component node. The component node itself is
+ not part of the newly created model; it's the first item defined after "Component {"
+ that is the root node.
+
+ \arg componentNode must be valid & of type "Qt/Component"
+ \return the newly created model. The caller takes ownership of the object life time.
+ */
+//Model *Model::createComponentModel(const ModelNode &componentNode)
+//{
+//
+// if (!componentNode.isValid() || componentNode.type() != "Qt/Component") {
+// throw new InvalidArgumentException(__LINE__, __FUNCTION__, __FILE__, QString("componentNode"));
+// }
+//
+// // the data property does not include the Component element itself
+// const TextLocation componentRootLocation
+// = componentNode.baseNodeState().m_internalNodeState->propertyLocation("data");
+//
+// TextModifier *textModifier
+// = new Internal::ComponentTextModifier(m_d->m_rewriter->textModifier(),
+// componentRootLocation,
+// m_d->m_rootInternalNode->baseNodeState()->location());
+//
+// QList<QmlError> errors;
+// Model *subModel = create(textModifier, m_d->m_fileUrl, &errors);
+//
+// Q_ASSERT(subModel);
+// Q_ASSERT(errors.size() == 0); // should never happen, after all it was already compiled!
+//
+// textModifier->setParent(subModel);
+//
+// return subModel;
+//}
+
+QSet<Import> Model::imports() const
+{
+ return m_d->imports();
+}
+
+void Model::addImport(const Import &import)
+{
+ m_d->addImport(import);
+}
+
+void Model::removeImport(const Import &import)
+{
+ m_d->removeImport(import);
+}
+
+#if 0
+/*!
+ \brief Creates a new empty model
+ \param uiFilePath path to the ui file
+ \param[out] errorMessage returns a error message
+ \return new created model
+*/
+Model *Model::create(const QString &rootType)
+{
+ return Internal::ModelPrivate::create(rootType);
+}
+#endif
+
+Model *Model::masterModel() const
+{
+ return m_d->m_masterModel.data();
+}
+
+void Model::setMasterModel(Model *model)
+{
+ m_d->m_masterModel = model;
+}
+
+/*!
+ \brief Returns the URL against which relative URLs within the model should be resolved.
+ \return The base URL.
+ */
+QUrl Model::fileUrl() const
+{
+ return m_d->fileUrl();
+}
+
+/*!
+ \brief Sets the URL against which relative URLs within the model should be resolved.
+ \param url the base URL, i.e. the qml file path.
+ */
+void Model::setFileUrl(const QUrl &url)
+{
+ m_d->setFileUrl(url);
+}
+
+/*!
+ \brief Returns list of Qml types available within the model.
+ */
+const MetaInfo Model::metaInfo() const
+{
+ return m_d->metaInfo();
+}
+
+/*!
+ \brief Returns list of Qml types available within the model.
+ */
+MetaInfo Model::metaInfo()
+{
+ return m_d->metaInfo();
+}
+
+/*! \name Undo Redo Interface
+ here you can find a facade to the internal undo redo framework
+*/
+
+
+/*! \name View related functions
+*/
+//\{
+/*!
+\brief Attaches a view to the model
+
+Registers a "view" that from then on will be informed about changes to the model. Different views
+will always be informed in the order in which they registered to the model.
+
+The view is informed that it has been registered within the model by a call to AbstractView::modelAttached .
+
+\param view The view object to register. Must be not null.
+\see detachView
+*/
+void Model::attachView(AbstractView *view)
+{
+ m_d->attachView(view);
+}
+
+/*!
+\brief Detaches a view to the model
+
+\param view The view to unregister. Must be not null.
+\param emitDetachNotify If set to NotifyView (the default), AbstractView::modelAboutToBeDetached() will be called
+
+\see attachView
+*/
+void Model::detachView(AbstractView *view, ViewNotification emitDetachNotify)
+{
+ bool emitNotify = (emitDetachNotify == NotifyView);
+ m_d->detachView(view, emitNotify);
+}
+
+
+}
diff --git a/src/plugins/qmldesigner/core/model/model_p.h b/src/plugins/qmldesigner/core/model/model_p.h
new file mode 100644
index 0000000000..184d10ca3e
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/model_p.h
@@ -0,0 +1,195 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef MODEL_P_H
+#define MODEL_P_H
+
+#include <QtCore/QList>
+#include <QWeakPointer>
+#include <QtCore/QSet>
+#include <QtCore/QUrl>
+
+#include "modelnode.h"
+#include "abstractview.h"
+#include "metainfo.h"
+
+#include "corelib_global.h"
+
+QT_BEGIN_NAMESPACE
+class QPlainTextEdit;
+QT_END_NAMESPACE
+
+namespace QmlDesigner {
+
+class AbstractProperty;
+
+
+namespace Internal {
+
+class InternalNode;
+class InternalProperty;
+class InternalBindingProperty;
+class InternalVariantProperty;
+class InternalNodeAbstractProperty;
+class InternalNodeListProperty;
+
+typedef QSharedPointer<InternalNode> InternalNodePointer;
+typedef QSharedPointer<InternalProperty> InternalPropertyPointer;
+typedef QSharedPointer<InternalBindingProperty> InternalBindingPropertyPointer;
+typedef QSharedPointer<InternalVariantProperty> InternalVariantPropertyPointer;
+typedef QSharedPointer<InternalNodeAbstractProperty> InternalNodeAbstractPropertyPointer;
+typedef QSharedPointer<InternalNodeListProperty> InternalNodeListPropertyPointer;
+typedef QPair<InternalNodePointer, QString> PropertyPair;
+
+class ModelPrivate : QObject {
+ Q_OBJECT
+
+ Q_DISABLE_COPY(ModelPrivate)
+
+ friend class QmlDesigner::Model;
+
+public:
+ ModelPrivate(Model *model);
+ ~ModelPrivate();
+
+ static Model *create(QString type, int major, int minor);
+
+ QUrl fileUrl() const;
+ void setFileUrl(const QUrl &url);
+
+ InternalNodePointer createNode(const QString &typeString,
+ int majorVersion,
+ int minorVersion,
+ const QList<QPair<QString, QVariant> > &propertyList);
+
+
+ /*factory methods for internal use in model and rewriter*/
+
+ void removeNode(const InternalNodePointer &node);
+ void changeNodeId(const InternalNodePointer& internalNodePointer, const QString& id);
+
+ InternalNodePointer rootNode() const;
+ InternalNodePointer findNode(const QString &id) const;
+
+ MetaInfo metaInfo() const;
+
+ void attachView(AbstractView *view);
+ void detachView(AbstractView *view, bool notifyView);
+ void detachAllViews();
+
+
+ Model *model() const { return m_q; }
+ void setModel(Model *q) { m_q = q; }
+
+ void notifyNodeCreated(const InternalNodePointer &newInternalNodePointer);
+ void notifyNodeReparent(const InternalNodePointer &internalNodePointer, const InternalNodeAbstractPropertyPointer &newPropertyParent, const InternalNodePointer &oldParent, const QString &oldPropertyName, AbstractView::PropertyChangeFlags propertyChange);
+ void notifyNodeAboutToBeRemoved(const InternalNodePointer &nodePointer);
+ void notifyNodeRemoved(const InternalNodePointer &nodePointer, const InternalNodePointer &parentNodePointer, const QString &parentPropertyName, AbstractView::PropertyChangeFlags propertyChange);
+ void notifyNodeIdChanged(const InternalNodePointer& nodePointer, const QString& newId, const QString& oldId);
+
+ void notifyPropertiesRemoved(const QList<PropertyPair> &propertyList);
+ void notifyPropertiesAboutToBeRemoved(const QList<InternalPropertyPointer> &propertyList);
+ void notifyBindingPropertiesChanged(const QList<InternalBindingPropertyPointer> &propertyList, AbstractView::PropertyChangeFlags propertyChange);
+ void notifyVariantPropertiesChanged(const InternalNodePointer &internalNodePointer, const QStringList& propertyNameList, AbstractView::PropertyChangeFlags propertyChange);
+
+ void notifyNodeSlidedToIndex(const InternalNodeListPropertyPointer &internalNode, int newIndex, int oldIndex);
+ void notifyAuxiliaryDataChanged(const InternalNodePointer &internalNode, const QString &name, const QVariant &data);
+
+ void notifyNodeTypeChanged(const InternalNodePointer &internalNode, const QString &type, int majorVersion, int minorVersion);
+
+ void notifyCustomNotification(const AbstractView *senderView, const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> &data);
+
+ void setSelectedNodes(const QList<InternalNodePointer> &selectedNodeList);
+ void clearSelectedNodes();
+ QList<InternalNodePointer> selectedNodes() const;
+ void selectNode(const InternalNodePointer &node);
+ void deselectNode(const InternalNodePointer &node);
+ void changeSelectedNodes(const QList<InternalNodePointer> &newSelectedsNodeList,
+ const QList<InternalNodePointer> &oldSelectedsNodeList);
+
+ void setRootNode(const InternalNodePointer& newRootNode);
+ void setAuxiliaryData(const InternalNodePointer& node, const QString &name, const QVariant &data);
+
+
+ // Imports:
+ QSet<Import> imports() const { return m_imports; }
+ void setImports(const QSet<Import> &imports);
+ void addImport(const Import &import);
+ void removeImport(const Import &import);
+ void notifyImportsChanged() const;
+
+
+ //node state property manipulation
+
+ void addProperty(const InternalNodePointer &node, const QString &name);
+ void setPropertyValue(const InternalNodePointer &node,const QString &name, const QVariant &value);
+ void removeProperty(const InternalPropertyPointer &property);
+
+ void setBindingProperty(const InternalNodePointer &internalNode, const QString &name, const QString &expression);
+ void setVariantProperty(const InternalNodePointer &internalNode, const QString &name, const QVariant &value);
+ void setDynamicVariantProperty(const InternalNodePointer &internalNode, const QString &name, const QString &propertyType, const QVariant &value);
+ void setDynamicBindingProperty(const InternalNodePointer &internalNode, const QString &name, const QString &dynamicPropertyType, const QString &expression);
+ void reparentNode(const InternalNodePointer &internalNode, const QString &name, const InternalNodePointer &internalNodeToBeAppended, bool list = true);
+ void slideNodeList(const InternalNodePointer &internalNode, const QString &name, int from, int to);
+ void checkPropertyName(const QString &propertyName);
+ void clearParent(const InternalNodePointer &internalNode);
+ void changeType(const InternalNodePointer & internalNode, const QString &type, int majorVersion, int minorVersion);
+
+ InternalNodePointer nodeForId(const QString &id) const;
+ bool hasId(const QString &id) const;
+
+ QList<InternalNodePointer> allNodes() const;
+
+private: //functions
+ void removePropertyWithoutNotification(const InternalPropertyPointer &property);
+ void removeAllSubNodes(const InternalNodePointer &node);
+ void removeNodeFromModel(const InternalNodePointer &node);
+ QList<InternalNodePointer> toInternalNodeList(const QList<ModelNode> &nodeList) const;
+ QList<ModelNode> toModelNodeList(const QList<InternalNodePointer> &nodeList, AbstractView *view) const;
+
+private:
+ Model *m_q;
+ MetaInfo m_metaInfo;
+
+ QSet<Import> m_imports;
+ QList<QWeakPointer<AbstractView> > m_viewList;
+ QList<InternalNodePointer> m_selectedNodeList;
+ QHash<QString,InternalNodePointer> m_idNodeHash;
+ QSet<InternalNodePointer> m_nodeSet;
+
+ InternalNodePointer m_rootInternalNode;
+
+ QUrl m_fileUrl;
+
+ QWeakPointer<Model> m_masterModel;
+};
+
+}
+}
+#endif // MODEL_P_H
diff --git a/src/plugins/qmldesigner/core/model/modelmerger.cpp b/src/plugins/qmldesigner/core/model/modelmerger.cpp
new file mode 100644
index 0000000000..133fb417e7
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/modelmerger.cpp
@@ -0,0 +1,168 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "modelmerger.h"
+
+#include "modelmerger.h"
+#include "modelnode.h"
+#include "abstractview.h"
+#include "model.h"
+#include "nodeproperty.h"
+#include "nodelistproperty.h"
+#include "bindingproperty.h"
+#include "variantproperty.h"
+#include "rewritertransaction.h"
+
+#include <QSet>
+#include <QStringList>
+
+namespace QmlDesigner {
+
+static ModelNode createNodeFromNode(const ModelNode &modelNode,const QHash<QString, QString> &idRenamingHash, AbstractView *view);
+
+static QString fixExpression(const QString &expression, const QHash<QString, QString> &idRenamingHash)
+{
+ QString newExpression = expression;
+ foreach (const QString &id, idRenamingHash.keys()) {
+ if (newExpression.contains(id))
+ newExpression = newExpression.replace(id, idRenamingHash.value(id));
+ }
+ return newExpression;
+}
+
+static void syncVariantProperties(ModelNode &outputNode, const ModelNode &inputNode)
+{
+ foreach (const VariantProperty &variantProperty, inputNode.variantProperties()) {
+ outputNode.variantProperty(variantProperty.name()) = variantProperty.value();
+ }
+}
+
+static void syncBindingProperties(ModelNode &outputNode, const ModelNode &inputNode, const QHash<QString, QString> &idRenamingHash)
+{
+ foreach (const BindingProperty &bindingProperty, inputNode.bindingProperties()) {
+ outputNode.bindingProperty(bindingProperty.name()).setExpression(fixExpression(bindingProperty.expression(), idRenamingHash));
+ }
+}
+
+static void syncId(ModelNode &outputNode, const ModelNode &inputNode, const QHash<QString, QString> &idRenamingHash)
+{
+ if (!inputNode.id().isNull() && inputNode.id() != "") {
+ outputNode.setId(idRenamingHash.value(inputNode.id()));
+ }
+}
+
+static void setupIdRenamingHash(const ModelNode &modelNode, QHash<QString, QString> &idRenamingHash, AbstractView *view)
+{
+ QList<ModelNode> allNodes(modelNode.allSubModelNodes());
+ allNodes.append(modelNode);
+ foreach (const ModelNode &node, allNodes) {
+ if (!node.id().isNull() && node.id() != "") {
+ QString newId = node.id();
+ int i = 1;
+ while (view->hasId(newId) || idRenamingHash.contains(newId)) {
+ newId = node.id() + QString::number(i).toLower();
+ i++;
+ }
+ idRenamingHash.insert(node.id(), newId);
+ }
+ }
+}
+
+static void syncNodeProperties(ModelNode &outputNode, const ModelNode &inputNode, const QHash<QString, QString> &idRenamingHash, AbstractView *view)
+{
+ foreach (NodeProperty nodeProperty, inputNode.nodeProperties()) {
+ ModelNode newNode = createNodeFromNode(nodeProperty.modelNode(), idRenamingHash, view);
+ outputNode.nodeProperty(nodeProperty.name()).reparentHere(newNode);
+ }
+}
+
+static void syncNodeListProperties(ModelNode &outputNode, const ModelNode &inputNode, const QHash<QString, QString> &idRenamingHash, AbstractView *view)
+{
+ foreach (NodeListProperty nodeListProperty, inputNode.nodeListProperties()) {
+ foreach (const ModelNode &node, nodeListProperty.toModelNodeList()) {
+ ModelNode newNode = createNodeFromNode(node, idRenamingHash, view);
+ outputNode.nodeListProperty(nodeListProperty.name()).reparentHere(newNode);
+ }
+ }
+}
+
+static ModelNode createNodeFromNode(const ModelNode &modelNode,const QHash<QString, QString> &idRenamingHash, AbstractView *view)
+{
+ QList<QPair<QString, QVariant> > propertyList;
+ foreach (const VariantProperty &variantProperty, modelNode.variantProperties()) {
+ propertyList.append(QPair<QString, QVariant>(variantProperty.name(), variantProperty.value()));
+ }
+ ModelNode newNode(view->createModelNode(modelNode.type(),modelNode.majorVersion(),modelNode.minorVersion(), propertyList));
+ syncBindingProperties(newNode, modelNode, idRenamingHash);
+ syncId(newNode, modelNode, idRenamingHash);
+ syncNodeProperties(newNode, modelNode, idRenamingHash, view);
+ syncNodeListProperties(newNode, modelNode, idRenamingHash, view);
+
+ return newNode;
+}
+
+ModelNode ModelMerger::insertModel(const ModelNode &modelNode)
+{
+ RewriterTransaction transaction(view()->beginRewriterTransaction());
+
+ foreach (const Import &import, modelNode.model()->imports())
+ view()->model()->addImport(import);
+
+ QHash<QString, QString> idRenamingHash;
+ setupIdRenamingHash(modelNode, idRenamingHash, view());
+ ModelNode newNode(createNodeFromNode(modelNode, idRenamingHash, view()));
+
+ return newNode;
+}
+
+void ModelMerger::replaceModel(const ModelNode &modelNode)
+{
+ RewriterTransaction transaction(view()->beginRewriterTransaction());
+
+ foreach (const Import &import, modelNode.model()->imports())
+ view()->model()->addImport(import);
+
+ ModelNode rootNode(view()->rootModelNode());
+
+ foreach (const QString &propertyName, rootNode.propertyNames())
+ rootNode.removeProperty(propertyName);
+
+ QHash<QString, QString> idRenamingHash;
+ setupIdRenamingHash(modelNode, idRenamingHash, view());
+
+ syncVariantProperties(rootNode, modelNode);
+ syncBindingProperties(rootNode, modelNode, idRenamingHash);
+ syncId(rootNode, modelNode, idRenamingHash);
+ syncNodeProperties(rootNode, modelNode, idRenamingHash, view());
+ syncNodeListProperties(rootNode, modelNode, idRenamingHash, view());
+ rootNode.changeType(modelNode.type(), modelNode.majorVersion(), modelNode.minorVersion());
+}
+
+} //namespace QmlDesigner
+
diff --git a/src/plugins/qmldesigner/core/model/modelnode.cpp b/src/plugins/qmldesigner/core/model/modelnode.cpp
new file mode 100644
index 0000000000..600977f606
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/modelnode.cpp
@@ -0,0 +1,943 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <modelnode.h>
+#include <abstractproperty.h>
+#include <abstractview.h>
+#include <model.h>
+#include <metainfo.h>
+#include "internalnode_p.h"
+#include <QHash>
+#include <QTextStream>
+#include "invalidargumentexception.h"
+#include "invalididexception.h"
+#include "invalidmodelnodeexception.h"
+#include "invalidpropertyexception.h"
+#include "invalidslideindexexception.h"
+#include "model_p.h"
+#include "abstractview.h"
+#include "abstractproperty.h"
+#include "variantproperty.h"
+#include "bindingproperty.h"
+#include "nodeabstractproperty.h"
+#include "nodelistproperty.h"
+#include "nodeproperty.h"
+
+namespace QmlDesigner {
+using namespace QmlDesigner::Internal;
+
+/*!
+\class QmlDesigner::ModelNode
+\ingroup CoreModel
+\brief The central class to access the node which can represent a widget, layout
+ or other items. A Node is a part of a tree and has properties.
+
+Conceptually ModelNode is an opaque handle to the internal data structures.
+
+There is always a root model node in every QmlDesigner::Model:
+\code
+QmlDesigner::Model *model = QmlDesigner::Model::create();
+QmlDesigner::ModelNode rootNode = model->rootNode();
+QmlDesigner::ModelNode childNode = rootNode.addChildNode("QLineEdit");
+\endcode
+
+You can add a property to a node:
+\code
+childNode.addProperty("pos", QPoint(2, 12));
+\endcode
+
+All the manipulation functions are generating undo commands internally.
+*/
+
+
+
+/*! \brief internal constructor
+
+*/
+ModelNode::ModelNode(const InternalNodePointer &internalNode, Model *model, AbstractView *view):
+ m_internalNode(internalNode),
+ m_model(model),
+ m_view(view)
+{
+ Q_ASSERT(!m_model || m_view);
+}
+
+ModelNode::ModelNode(const ModelNode modelNode, AbstractView *view)
+ : m_internalNode(modelNode.m_internalNode),
+ m_model(modelNode.model()),
+ m_view(view)
+{
+
+}
+
+/*! \brief contructs a invalid model node
+\return invalid node
+\see invalid
+*/
+ModelNode::ModelNode():
+ m_internalNode(new InternalNode)
+{
+
+}
+
+ModelNode::ModelNode(const ModelNode &other):
+ m_internalNode(other.m_internalNode),
+ m_model(other.m_model),
+ m_view(other.m_view)
+{
+}
+
+ModelNode& ModelNode::operator=(const ModelNode &other)
+{
+ this->m_model = other.m_model;
+ this->m_internalNode = other.m_internalNode;
+ this->m_view = other.m_view;
+
+ return *this;
+}
+
+/*! \brief does nothing
+*/
+ModelNode::~ModelNode()
+{
+}
+
+QString ModelNode::generateNewId() const
+{
+ int counter = 1;
+ QString newId = QString("%1%2").arg(simplifiedTypeName().toLower()).arg(counter);
+
+ while(view()->hasId(newId)) {
+ counter += 1;
+ newId = QString("%1%2").arg(simplifiedTypeName().toLower()).arg(counter);
+ }
+
+ return newId;
+}
+
+/*! \brief returns the name of node which is a short cut to a property like objectName
+\return name of the node
+*/
+QString ModelNode::id() const
+{
+ if (!isValid()) {
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+ }
+
+ return m_internalNode->id();
+}
+
+QString ModelNode::validId()
+{
+ if (id().isEmpty())
+ setId(generateNewId());
+
+ return id();
+}
+
+static bool idContainsWrongLetter(const QString& id)
+{
+ static QRegExp idExpr(QLatin1String("[a-zA-Z][a-zA-Z0-9_]*"));
+ return !idExpr.exactMatch(id);
+}
+
+bool ModelNode::isValidId(const QString &id)
+{
+ return !(id.isEmpty() || idContainsWrongLetter(id));
+}
+
+void ModelNode::setId(const QString& id)
+{
+ if (!isValid()) {
+ Q_ASSERT_X(isValid(), Q_FUNC_INFO, "model node is invalid");
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+ }
+
+ if (!isValidId(id))
+ throw InvalidIdException(__LINE__, __FUNCTION__, __FILE__);
+
+ if (id == ModelNode::id())
+ return;
+
+ if (view()->hasId(id))
+ throw InvalidIdException(__LINE__, __FUNCTION__, __FILE__);
+
+ m_model.data()->m_d->changeNodeId(internalNode(), id);
+}
+
+/*! \brief the fully-qualified type name of the node is represented as string
+\return type of the node as a string
+*/
+QString ModelNode::type() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(isValid(), Q_FUNC_INFO, "model node is invalid");
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+ }
+ return m_internalNode->type();
+}
+
+/*! \brief set the fully-qualified type name of the node
+*/
+void ModelNode::changeType(const QString &type, int majorVersion, int minorVersion)
+{
+ if (!isValid()) {
+ Q_ASSERT_X(isValid(), Q_FUNC_INFO, "model node is invalid");
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+ }
+
+ m_model.data()->m_d->changeType(internalNode(), type, majorVersion, minorVersion);
+}
+
+/*! \brief minor number of the Qml Type
+\return minor number
+*/
+int ModelNode::minorVersion() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(isValid(), Q_FUNC_INFO, "model node is invalid");
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+ }
+ return m_internalNode->minorVersion();
+}
+
+/*! \brief major number of the Qml Type
+\return major number
+*/
+int ModelNode::majorVersion() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(isValid(), Q_FUNC_INFO, "model node is invalid");
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+ }
+ return m_internalNode->majorVersion();
+}
+
+
+/*! \return the short-hand type name of the node. */
+QString ModelNode::simplifiedTypeName() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(isValid(), Q_FUNC_INFO, "model node is invalid");
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+ }
+
+ return type().split("/").last();
+}
+
+/*! \brief Returns whether the node is valid
+
+A node is valid if its model still exists, and contains this node.
+Also, the current state must be a valid one.
+
+A node might become invalid if e.g. it or one of its ancestors is deleted.
+
+\return is a node valid(true) or invalid(false)
+*/
+bool ModelNode::isValid() const
+{
+ return !m_model.isNull() && !m_view.isNull() && m_internalNode &&m_internalNode->isValid();
+}
+
+/*!
+ \brief Returns whether the root node of the model is one of the anchestors of this node.
+
+ Will return true also for the root node itself.
+ */
+bool ModelNode::isInHierarchy() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(isValid(), Q_FUNC_INFO, "model node is invalid");
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+ }
+ if (isRootNode())
+ return true;
+ if (!hasParentProperty())
+ return false;
+ return parentProperty().parentModelNode().isInHierarchy();
+}
+
+/*!
+ \brief Returns the property containing this node
+
+ The NodeAbstractProperty is invalid if this ModelNode has no parent.
+ NodeAbstractProperty can be a NodeProperty containing a single ModelNode, or
+ a NodeListProperty.
+
+ \return the property containing this ModelNode
+ */
+NodeAbstractProperty ModelNode::parentProperty() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(isValid(), Q_FUNC_INFO, "model node is invalid");
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+ }
+ if (m_internalNode->parentProperty().isNull())
+ return NodeAbstractProperty();
+
+ return NodeAbstractProperty(m_internalNode->parentProperty()->name(), m_internalNode->parentProperty()->propertyOwner(), m_model.data(), view());
+}
+
+
+/*! \brief the command id is used to compress the some commands together.
+\param newParentNode parent of this node will be set to this node
+\param commandId integer which is used to descripe commands which should compressed together to one command
+
+For example:
+\code
+node.setParentNode(parentNode1);
+node.setParentNode(parentNode2, 212);
+node.setParentNode(parentNode3, 212);
+model->undoStack()->undo();
+ModelNode parentNode4 = node.parentProperty().parentModelNode();
+parentNode4 == parentNode1; -> true
+\endcode
+
+\see parentNode childNodes addChildNode hasChildNodes Model::undo
+
+*/
+
+void ModelNode::setParentProperty(NodeAbstractProperty parent)
+{
+ if (!isValid()) {
+ Q_ASSERT_X(isValid(), Q_FUNC_INFO, "model node is invalid");
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+ }
+
+ if (!parent.parentModelNode().isValid()) {
+ throw InvalidArgumentException(__LINE__, __FUNCTION__, __FILE__, "newParentNode");
+ }
+
+ if (*this == parent.parentModelNode()) {
+ Q_ASSERT_X(*this != parent.parentModelNode(), Q_FUNC_INFO, "cannot set parent to itself");
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+ }
+
+ if (parent == parentProperty())
+ return;
+
+ parent.reparentHere(*this);
+}
+
+void ModelNode::setParentProperty(const ModelNode &newParentNode, const QString &propertyName)
+{
+ setParentProperty(newParentNode.nodeAbstractProperty(propertyName));
+}
+
+/*! \brief test if there is a parent for this node
+\return true is this node has a parent
+\see childNodes parentNode setParentNode addChildNode hasChildNodes Model::undo
+*/
+bool ModelNode::hasParentProperty() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(isValid(), Q_FUNC_INFO, "model node is invalid");
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+ }
+
+ if (m_internalNode->parentProperty().isNull())
+ return false;
+
+ return true;
+}
+
+/*!
+ \brief Returns a BindingProperty
+
+ Note that a valid BindingProperty is returned, if the ModelNode is valid,
+ even if this property does not exist or is not a BindingProperty.
+ Assigning an expression to this BindingProperty will create the property.
+
+ \return BindingProperty named name
+ */
+
+BindingProperty ModelNode::bindingProperty(const QString &name) const
+{
+ if (!isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ return BindingProperty(name, m_internalNode, model(), view());
+}
+
+
+/*!
+ \brief Returns a NodeProperty
+
+ Note that a valid NodeProperty is returned, if the ModelNode is valid,
+ even if this property does not exist or is not a NodeProperty.
+ Assigning a ModelNode to this NodeProperty will create the property.
+
+ \return NodeProperty named name
+ */
+
+NodeProperty ModelNode::nodeProperty(const QString &name) const
+{
+ if (!isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ return NodeProperty(name, m_internalNode, model(), view());
+}
+
+
+/*!
+ \brief Returns a NodeListProperty
+
+ Note that a valid NodeListProperty is returned, if the ModelNode is valid,
+ even if this property does not exist or is not a NodeListProperty.
+ Assigning a ModelNode to this NodeListProperty will create the property.
+
+ \return NodeListProperty named name
+ */
+
+NodeListProperty ModelNode::nodeListProperty(const QString &name) const
+{
+ if (!isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ return NodeListProperty(name, m_internalNode, model(), view());
+}
+
+NodeAbstractProperty ModelNode::nodeAbstractProperty(const QString &name) const
+{
+ if (!isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ return NodeAbstractProperty(name, m_internalNode, model(), view());
+}
+
+
+/*!
+ \brief Returns a VariantProperty
+
+ Note that a valid VariantProperty is returned, if the ModelNode is valid,
+ even if this property does not exist or is not a VariantProperty.
+ Assigning a value to this VariantProperty will create the property.
+
+ \return VariantProperty named name
+ */
+
+VariantProperty ModelNode::variantProperty(const QString &name) const
+{
+ if (!isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ return VariantProperty(name, m_internalNode, model(), view());
+}
+
+AbstractProperty ModelNode::property(const QString &name) const
+{
+ if (!isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ return AbstractProperty(name, m_internalNode, model(), view());
+}
+
+/*! \brief returns a property
+\param name name of the property
+\return returns a node property handle. If the property is not set yet, the node property is still valid (lazy reference).
+
+It is searching only in the local Property.
+
+\see addProperty changePropertyValue removeProperty properties hasProperties
+*/
+
+/*! \brief returns a list of all properties
+\return list of all properties
+
+The list of properties
+
+*/
+QList<AbstractProperty> ModelNode::properties() const
+{
+ if (!isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ QList<AbstractProperty> propertyList;
+
+ foreach (const QString &propertyName, internalNode()->propertyNameList()) {
+ AbstractProperty property(propertyName, internalNode(), model(), view());
+ propertyList.append(property);
+ }
+
+ return propertyList;
+}
+
+
+/*! \brief returns a list of all VariantProperties
+\return list of all VariantProperties
+
+The list of all properties containing just an atomic value.
+
+*/
+QList<VariantProperty> ModelNode::variantProperties() const
+{
+ QList<VariantProperty> propertyList;
+
+ foreach (const AbstractProperty &abstractProperty, properties())
+ if (abstractProperty.isVariantProperty())
+ propertyList.append(abstractProperty.toVariantProperty());
+ return propertyList;
+}
+
+QList<NodeAbstractProperty> ModelNode::nodeAbstractProperties() const
+{
+ QList<NodeAbstractProperty> propertyList;
+
+ foreach (const AbstractProperty &nodeAbstractProperty, properties())
+ if (nodeAbstractProperty.isNodeAbstractProperty())
+ propertyList.append(nodeAbstractProperty.toNodeAbstractProperty());
+ return propertyList;
+}
+
+QList<NodeProperty> ModelNode::nodeProperties() const
+{
+ QList<NodeProperty> propertyList;
+
+ foreach (const AbstractProperty &nodeProperty, properties())
+ if (nodeProperty.isNodeProperty())
+ propertyList.append(nodeProperty.toNodeProperty());
+ return propertyList;
+}
+
+QList<NodeListProperty> ModelNode::nodeListProperties() const
+{
+ QList<NodeListProperty> propertyList;
+
+ foreach (const AbstractProperty &nodeListProperty, properties())
+ if (nodeListProperty.isNodeListProperty())
+ propertyList.append(nodeListProperty.toNodeListProperty());
+ return propertyList;
+}
+
+
+/*! \brief returns a list of all BindingProperties
+\return list of all BindingProperties
+
+The list of all properties containing an expression.
+
+*/
+QList<BindingProperty> ModelNode::bindingProperties() const
+{
+ QList<BindingProperty> propertyList;
+
+ foreach (const AbstractProperty &bindingProperty, properties())
+ if (bindingProperty.isBindingProperty())
+ propertyList.append(bindingProperty.toBindingProperty());
+ return propertyList;
+}
+
+/*!
+\brief removes a property from this node
+\param name name of the property
+
+Does nothing if the node state does not set this property.
+
+\see addProperty property properties hasProperties
+*/
+void ModelNode::removeProperty(const QString &name)
+{
+ if (!isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ model()->m_d->checkPropertyName(name);
+
+ if (internalNode()->hasProperty(name))
+ model()->m_d->removeProperty(internalNode()->property(name));
+}
+
+
+
+/*! \brief creates a new node and add it as child to this node
+\param nodeTypeString type name of the child node
+\param propertyList list of properties
+\return the new created model node
+
+*/
+ModelNode ModelNode::addChildNode(const QString &nodeTypeString, int majorVersion, int minorVersion, const QString &propertyName, const PropertyListType &propertyList)
+{
+ if (!isValid()) {
+ Q_ASSERT_X(isValid(), Q_FUNC_INFO, "model node is invalid");
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+ }
+
+ ModelNode newNode(view()->createModelNode(nodeTypeString, majorVersion, minorVersion, propertyList));
+
+ newNode.setParentProperty(nodeListProperty(propertyName));
+
+ return newNode;
+}
+
+/*! \brief removes this node from the node tree
+*/
+
+static QList<ModelNode> descendantNodes(const ModelNode &parent)
+{
+ QList<ModelNode> descendants(parent.allDirectSubModelNodes());
+ foreach (const ModelNode &child, parent.allDirectSubModelNodes()) {
+ descendants += descendantNodes(child);
+ }
+ return descendants;
+}
+
+static void removeModelNodeFromSelection(const ModelNode &node)
+{
+ { // remove nodes from the active selection:
+ QList<ModelNode> selectedList = node.view()->selectedModelNodes();
+
+ foreach (const ModelNode &childModelNode, descendantNodes(node))
+ selectedList.removeAll(childModelNode);
+ selectedList.removeAll(node);
+
+ node.view()->setSelectedModelNodes(selectedList);
+ }
+}
+
+
+/*! \brief complete removes this ModelNode from the Model
+
+*/
+void ModelNode::destroy()
+{
+ if (!isValid()) {
+ Q_ASSERT_X(isValid(), Q_FUNC_INFO, "model node is invalid");
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+ }
+
+ if (isRootNode()) {
+ throw InvalidArgumentException(__LINE__, __FUNCTION__, __FILE__, "rootNode");
+ }
+
+ removeModelNodeFromSelection(*this);
+ model()->m_d->removeNode(internalNode());
+}
+//\}
+
+/*! \name Property Manipulation
+ * This methodes interact with properties.
+ */
+
+
+/*!
+ \brief Returns if the the two nodes reference the same entity in the same model
+ */
+bool operator ==(const ModelNode &firstNode, const ModelNode &secondNode)
+{
+ if (firstNode.m_internalNode.isNull() || secondNode.m_internalNode.isNull()) {
+ Q_ASSERT_X(0, Q_FUNC_INFO, "model node is invalid");
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+ }
+
+ return firstNode.m_internalNode.data() == secondNode.m_internalNode.data();
+}
+
+/*!
+ \brief Returns if the the two nodes do not reference the same entity in the same model
+ */
+bool operator !=(const ModelNode &firstNode, const ModelNode &secondNode)
+{
+ if (firstNode.m_internalNode.isNull() || secondNode.m_internalNode.isNull()) {
+ Q_ASSERT_X(0, Q_FUNC_INFO, "model node is invalid");
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+ }
+
+ return firstNode.m_internalNode != secondNode.m_internalNode;
+}
+
+bool operator <(const ModelNode &firstNode, const ModelNode &secondNode)
+{
+ if (firstNode.m_internalNode.isNull() || secondNode.m_internalNode.isNull()) {
+ Q_ASSERT_X(0, Q_FUNC_INFO, "model node is invalid");
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+ }
+
+ return firstNode.internalNode().data() < secondNode.internalNode().data();
+}
+
+
+Internal::InternalNodePointer ModelNode::internalNode() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(isValid(), Q_FUNC_INFO, "model node is invalid");
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+ }
+ return m_internalNode;
+}
+
+
+uint qHash(const ModelNode &node)
+{
+// if (!node.isValid()) {
+// Q_ASSERT_X(node.isValid(), Q_FUNC_INFO, "model node is invalid");
+// throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+// }
+ return ::qHash(node.m_internalNode.data());
+}
+
+/*!
+\brief returns the model of the node
+\return returns the model of the node
+*/
+Model *ModelNode::model() const
+{
+ return m_model.data();
+}
+
+/*!
+\brief returns the view of the node
+Each ModelNode belongs to one specific view.
+\return view of the node
+*/
+AbstractView *ModelNode::view() const
+{
+ return m_view.data();
+}
+
+
+/*!
+\brief returns all ModelNodes that are direct children of this ModelNode
+The list contains every ModelNode that belongs to one of this ModelNodes
+properties.
+\return a list of all ModelNodes that are direct children
+*/
+const QList<ModelNode> ModelNode::allDirectSubModelNodes() const
+{
+ return toModelNodeList(internalNode()->allDirectSubNodes(), view());
+}
+
+
+/*!
+\brief returns all ModelNodes that are direct or indirect children of this ModelNode
+The list contains every ModelNode that is a direct or indirect child of this ModelNode.
+All children in this list will be implicitly removed if this ModelNode is destroyed.
+\return a list of all ModelNodes that are direct or indirect children
+*/
+
+const QList<ModelNode> ModelNode::allSubModelNodes() const
+{
+ return toModelNodeList(internalNode()->allSubNodes(), view());
+}
+
+/*!
+\brief returns if this ModelNode has any child ModelNodes.
+
+\return if this ModelNode has any child ModelNodes
+*/
+
+bool ModelNode::hasAnySubModelNodes() const
+{
+ return !nodeAbstractProperties().isEmpty();
+}
+
+/*! \brief returns the meta info of the node
+\return meta info of the node
+*/
+const NodeMetaInfo ModelNode::metaInfo() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(isValid(), Q_FUNC_INFO, "model node is invalid");
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+ }
+ return model()->metaInfo().nodeMetaInfo(type(), majorVersion(), minorVersion());
+}
+
+/*! \brief has a node the selection of the model
+\return true if the node his selection
+*/
+bool ModelNode::isSelected() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(isValid(), Q_FUNC_INFO, "model node is invalid");
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+ }
+ return view()->selectedModelNodes().contains(ModelNode(m_internalNode, m_model.data(), view()));
+}
+
+/*! \briefis this node the root node of the model
+\return true if it is the root node
+*/
+bool ModelNode::isRootNode() const
+{
+ if (!isValid()) {
+ Q_ASSERT_X(isValid(), Q_FUNC_INFO, "model node is invalid");
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+ }
+ return view()->rootModelNode() == *this;
+}
+
+/*! \brief returns the list of all property names
+\return list of all property names set in this state.
+
+The list of properties set in this state.
+
+\see addProperty property changePropertyValue removeProperty hasProperties
+*/
+QStringList ModelNode::propertyNames() const
+{
+ if (!isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+ return internalNode()->propertyNameList();
+}
+
+/*! \brief test a if a property is set for this node
+\return true if property a property ins this or a ancestor state exists
+*/
+bool ModelNode::hasProperty(const QString &name) const
+{
+ if (!isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ return internalNode()->hasProperty(name);
+}
+
+bool ModelNode::hasVariantProperty(const QString &name) const
+{
+ return hasProperty(name) && internalNode()->property(name)->isVariantProperty();
+}
+
+bool ModelNode::hasBindingProperty(const QString &name) const
+{
+ return hasProperty(name) && internalNode()->property(name)->isBindingProperty();
+}
+
+bool ModelNode::hasNodeAbstracProperty(const QString &name) const
+{
+ return hasProperty(name) && internalNode()->property(name)->isNodeAbstractProperty();
+}
+
+bool ModelNode::hasNodeProperty(const QString &name) const
+{
+ return hasProperty(name) && internalNode()->property(name)->isNodeProperty();
+}
+
+bool ModelNode::hasNodeListProperty(const QString &name) const
+{
+ return hasProperty(name) && internalNode()->property(name)->isNodeListProperty();
+}
+
+static bool recursiveAncestor(const ModelNode &possibleAncestor, const ModelNode &node)
+{
+ if (node.hasParentProperty()) {
+ if (node.parentProperty().parentModelNode() == possibleAncestor)
+ return true;
+ return recursiveAncestor(possibleAncestor, node.parentProperty().parentModelNode());
+ }
+
+ return false;
+}
+
+bool ModelNode::isAncestorOf(const ModelNode &node) const
+{
+ return recursiveAncestor(*this, node);
+}
+
+QDebug operator<<(QDebug debug, const ModelNode &modelNode)
+{
+ if (modelNode.isValid()) {
+ debug.nospace() << "ModelNode("
+ << modelNode.internalNode().data() << ", "
+ << modelNode.type() << ", "
+ << modelNode.id() <<")";
+ } else {
+ debug.nospace() << "ModelNode(invalid)";
+ }
+
+ return debug.space();
+}
+
+QTextStream& operator<<(QTextStream &stream, const ModelNode &modelNode)
+{
+ if (modelNode.isValid()) {
+ stream << "ModelNode("
+ << "type: " << modelNode.type() << ", "
+ << "id: " << modelNode.id() <<")";
+ } else {
+ stream << "ModelNode(invalid)";
+ }
+
+ return stream;
+}
+
+void ModelNode::selectNode()
+{
+ if (!isValid()) {
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+ }
+
+ QList<ModelNode> selectedNodeList;
+ selectedNodeList.append(*this);
+
+ view()->setSelectedModelNodes(selectedNodeList);
+}
+
+void ModelNode::deselectNode()
+{
+ if (!isValid()) {
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+ }
+
+ QList<ModelNode> selectedNodeList(view()->selectedModelNodes());
+ selectedNodeList.removeAll(*this);
+
+ view()->setSelectedModelNodes(selectedNodeList);
+}
+
+int ModelNode::variantUserType()
+{
+ return qMetaTypeId<ModelNode>();
+}
+
+QVariant ModelNode::toVariant() const
+{
+ return QVariant::fromValue(*this);
+}
+
+QVariant ModelNode::auxiliaryData(const QString &name) const
+{
+ if (!isValid()) {
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+ }
+
+ return internalNode()->auxiliaryData(name);
+}
+
+void ModelNode::setAuxiliaryData(const QString &name, const QVariant &data)
+{
+ m_model.data()->m_d->setAuxiliaryData(internalNode(), name, data);
+}
+
+bool ModelNode::hasAuxiliaryData(const QString &name) const
+{
+ if (!isValid()) {
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+ }
+
+ return internalNode()->hasAuxiliaryData(name);
+}
+
+}
diff --git a/src/plugins/qmldesigner/core/model/modelnodepositionrecalculator.cpp b/src/plugins/qmldesigner/core/model/modelnodepositionrecalculator.cpp
new file mode 100644
index 0000000000..172409b06a
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/modelnodepositionrecalculator.cpp
@@ -0,0 +1,100 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <QDebug>
+#include "modelnodepositionrecalculator.h"
+
+using namespace QmlDesigner;
+using namespace QmlDesigner::Internal;
+
+void ModelNodePositionRecalculator::connectTo(TextModifier *textModifier)
+{
+ Q_ASSERT(textModifier);
+
+ connect(textModifier, SIGNAL(moved(const TextModifier::MoveInfo &)), this, SLOT(moved(const TextModifier::MoveInfo &)));
+ connect(textModifier, SIGNAL(replaced(int,int,int)), this, SLOT(replaced(int,int,int)));
+}
+
+void ModelNodePositionRecalculator::moved(const TextModifier::MoveInfo &moveInfo)
+{
+ const int from = moveInfo.objectStart;
+ const int to = moveInfo.destination;
+ const int length = moveInfo.objectEnd - moveInfo.objectStart;
+ const int prefixLength = moveInfo.prefixToInsert.length();
+ const int suffixLength = moveInfo.suffixToInsert.length();
+
+ foreach (const ModelNode &node, m_nodesToTrack) {
+ const int nodeLocation = m_positionStore->nodeOffset(node);
+
+ if (nodeLocation == ModelNodePositionStorage::INVALID_LOCATION)
+ continue;
+
+ if (from <= nodeLocation && moveInfo.objectEnd > nodeLocation) {
+ if (to > from)
+ if (length == (to - from))
+ m_positionStore->setNodeOffset(node, nodeLocation + prefixLength - moveInfo.leadingCharsToRemove);
+ else
+ m_positionStore->setNodeOffset(node, to - length + nodeLocation - from + prefixLength - moveInfo.leadingCharsToRemove - moveInfo.trailingCharsToRemove);
+ else
+ m_positionStore->setNodeOffset(node, to + nodeLocation - from + prefixLength);
+ } else if (from < nodeLocation && to > nodeLocation) {
+ m_positionStore->setNodeOffset(node, nodeLocation - length - moveInfo.leadingCharsToRemove - moveInfo.trailingCharsToRemove);
+ } else if (from > nodeLocation && to <= nodeLocation) {
+ m_positionStore->setNodeOffset(node, nodeLocation + length + prefixLength + suffixLength);
+ } else if (from < nodeLocation && to <= nodeLocation) {
+ m_positionStore->setNodeOffset(node, nodeLocation + prefixLength + suffixLength - moveInfo.leadingCharsToRemove - moveInfo.trailingCharsToRemove);
+ }
+ }
+
+ m_dirtyAreas.insert(to - prefixLength, length + prefixLength + suffixLength);
+}
+
+void ModelNodePositionRecalculator::replaced(int offset, int oldLength, int newLength)
+{
+ Q_ASSERT(offset >= 0);
+
+ const int growth = newLength - oldLength;
+ if (growth == 0)
+ return;
+
+ foreach (const ModelNode &node, m_nodesToTrack) {
+ const int nodeLocation = m_positionStore->nodeOffset(node);
+
+ if (nodeLocation == ModelNodePositionStorage::INVALID_LOCATION)
+ continue;
+
+ if (offset < nodeLocation || (offset == nodeLocation && oldLength == 0)) {
+ const int newPosition = nodeLocation + growth;
+ if (newPosition < 0)
+ m_positionStore->removeNodeOffset(node);
+ else
+ m_positionStore->setNodeOffset(node, newPosition);
+ }
+ }
+}
diff --git a/src/plugins/qmldesigner/core/model/modelnodepositionrecalculator.h b/src/plugins/qmldesigner/core/model/modelnodepositionrecalculator.h
new file mode 100644
index 0000000000..abee72afef
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/modelnodepositionrecalculator.h
@@ -0,0 +1,71 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef MODELNODEPOSITIONRECALCULATOR_H
+#define MODELNODEPOSITIONRECALCULATOR_H
+
+#include <QMap>
+#include <QObject>
+#include <QSet>
+
+#include "modelnode.h"
+#include "modelnodepositionstorage.h"
+#include "textmodifier.h"
+
+namespace QmlDesigner {
+namespace Internal {
+
+class ModelNodePositionRecalculator: public QObject
+{
+ Q_OBJECT
+
+public:
+ ModelNodePositionRecalculator(ModelNodePositionStorage *positionStore, const QList<ModelNode> &nodesToTrack):
+ m_positionStore(positionStore), m_nodesToTrack(nodesToTrack)
+ { Q_ASSERT(positionStore); }
+
+ void connectTo(TextModifier *textModifier);
+
+ QMap<int,int> dirtyAreas() const
+ { return m_dirtyAreas; }
+
+public slots:
+ void replaced(int offset, int oldLength, int newLength);
+ void moved(const TextModifier::MoveInfo &moveInfo);
+
+private:
+ ModelNodePositionStorage *m_positionStore;
+ QList<ModelNode> m_nodesToTrack;
+ QMap<int, int> m_dirtyAreas;
+};
+
+} // namespace Internal
+} // namespace QmlDesigner
+
+#endif // MODELNODEPOSITIONRECALCULATOR_H
diff --git a/src/plugins/qmldesigner/core/model/modelnodepositionstorage.cpp b/src/plugins/qmldesigner/core/model/modelnodepositionstorage.cpp
new file mode 100644
index 0000000000..5c80015805
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/modelnodepositionstorage.cpp
@@ -0,0 +1,67 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "invalidmodelnodeexception.h"
+#include "modelnodepositionstorage.h"
+
+using namespace QmlDesigner;
+using namespace QmlDesigner::Internal;
+
+void ModelNodePositionStorage::setNodeOffset(const ModelNode &modelNode, int fileOffset)
+{
+ m_rewriterData[modelNode].setOffset(fileOffset);
+}
+
+void ModelNodePositionStorage::cleanupInvalidOffsets()
+{
+ QHash<ModelNode, RewriterData> validModelNodes;
+
+ QHashIterator<ModelNode, RewriterData> iter(m_rewriterData);
+ while (iter.hasNext()) {
+ iter.next();
+ const ModelNode modelNode = iter.key();
+ if (modelNode.isValid())
+ validModelNodes.insert(modelNode, iter.value());
+ }
+ m_rewriterData = validModelNodes;
+}
+
+int ModelNodePositionStorage::nodeOffset(const ModelNode &modelNode)
+{
+ QHash<ModelNode, RewriterData>::const_iterator iter = m_rewriterData.find(modelNode);
+ if (iter == m_rewriterData.end())
+ return INVALID_LOCATION;
+ else
+ return iter.value().offset();
+}
+
+QList<ModelNode> ModelNodePositionStorage::modelNodes() const
+{
+ return m_rewriterData.keys();
+}
diff --git a/src/plugins/qmldesigner/core/model/modelrewriter.cpp b/src/plugins/qmldesigner/core/model/modelrewriter.cpp
new file mode 100644
index 0000000000..725d45cd69
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/modelrewriter.cpp
@@ -0,0 +1,510 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <QCoreApplication>
+
+#include "copyhelper.h"
+#include "invalidmodelnodeexception.h"
+#include "invalidpropertyexception.h"
+#include "internalnode_p.h"
+#include "modelrewriter.h"
+#include "modificationgroupexception.h"
+#include "nodeproperty.h"
+#include "paster.h"
+#include "textmodifier.h"
+#include "textlocation.h"
+
+/*!
+\defgroup Rewriting
+*/
+/*!
+\class QmlDesigner::Internal::ModelRewriter
+\ingroup Rewriting
+\brief The ModelRewriter class is the facade interface to all rewriting classes for QML files.
+
+The rewriting consists of two phases. First, any changes are applied to the QML source, as held by the TextModifier. This is done by the
+TextToModelMerger. After that, the QTextDocument of the TextModifier will fire a textChanged() signal, which triggers the second phase. In this
+phase, the ModelRewriter will use the ModelToTextMerger to parse the QML (using QmlDocDocument) and change the Model according to the new input.
+
+The strategy of the Model is to first apply the changes to the datastructures itself, and then tell the ModelRewriter to apply the changes to the QML
+source file. By doing it in this order, the second phase of the rewriting will usually not make any changes to the Model.
+
+However, as with any good rule, there are two exceptions. The most common one is that the QTextDocument of the TextModifier is also used by a text
+editor. When the user changes anything in the QML source text using that editor, reparsing will be triggered too, and the Model will be changed to
+reflect the user's changes. The second exception to the rule is that an error can occur while re-parsing the QML. (Note that this can also happen
+due to a change by a text editor.) In this case, the TextToModelMerger will try to revert the model to the last known correct state.
+
+The ModelRewriter has one requirement to do the application of changes to the text correctly. It assumes that every change is coming in separately.
+This means, when, for example, addNode for a rectangle is called, only "Rectangle {}" is added to the QML source text. If the node has properties set,
+the rewriting will not magically decide that these need to be added. So to add a rectangle on a certain position with a certain size, the
+appropriate calls to addProperty will have to be made too. If these changes need to be made in one "bigger" change to the QML source text, then a
+modification group can be created. All the changes in the modification group are applied to the QML source text in such a way that the underlying
+QTextDocument will see it as one single change.
+
+\see QmlDesigner::Model
+*/
+
+namespace QmlDesigner {
+namespace Internal {
+
+ModelRewriter::ModelRewriter(Model* model, TextModifier* textModifier):
+ m_subcomponentManager(model->metaInfo()),
+ m_textModifier(textModifier),
+ m_modelToTextMerger(model),
+ m_textToModelMerger(model, &m_subcomponentManager),
+ m_lastRewriteFailed(false)
+{
+ Q_ASSERT(model);
+ Q_ASSERT(textModifier);
+
+ connect(m_textModifier, SIGNAL(textChanged()), this, SLOT(mergeChanges()));
+}
+
+/*!
+ Starting point for the second phase of the rewriting: this will parse the QML source text, and apply any changes to the Model.
+
+ \param errors A pointer to a list which can hold the QmlError objects which describe errors while parsing the QML source text. Passing
+ <code>null</code> will leave all errors unreported.
+ */
+bool ModelRewriter::reloadAndMerge(QList<QmlError> *errors)
+{
+ if (QCoreApplication::arguments().contains("--no-resync"))
+ return false;
+
+ QByteArray newData = m_textModifier->text().toUtf8();
+
+ if (m_textToModelMerger.reloadAndMerge(newData, errors)) {
+ m_lastCorrectData = newData;
+ return true;
+ } else {
+ m_textToModelMerger.reloadAndMerge(m_lastCorrectData, 0);
+ return false;
+ }
+}
+
+/*!
+ Starting point for the second phase of the rewriting: this will parse the QML source text, and apply any changes to the Model.
+
+ \param url The URL of the input data, used to load any sub-components, and used for reporting parser errors.
+ \param errors A pointer to a list which can hold the QmlError objects which describe errors while parsing the QML source text. Passing
+ <code>null</code> will leave all errors unreported.
+ */
+bool ModelRewriter::load(const QUrl &url, QList<QmlError> *errors)
+{
+ QByteArray newData = m_textModifier->text().toUtf8();
+
+ if (m_textToModelMerger.load(newData, url, errors)) {
+ m_lastCorrectData = newData;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/*!
+ Sets the URL of the input file, which is used to report parser errors, and to load sub-components.
+
+ \note Changing the file URL will force a re-load of all sub-components.
+ */
+void ModelRewriter::setFileUrl(const QUrl& url)
+{
+ m_textToModelMerger.setFileUrl(url);
+}
+
+/**
+ Changes the value of a property in the given state in the QML source text.
+
+ \param state The state for which the property is changed.
+ \param name The name of the property to change.
+ \param value The new value for the property.
+
+ \note Changing a property value can only be done after the property has been added to that state.
+ \see {@link addProperty}
+ */
+void ModelRewriter::changePropertyValue(const InternalNodeState::Pointer& state, const QString& name, const QVariant& value)
+{
+ if (state->modelNode()->isReadOnly())
+ return; //the rewriter ignores read only nodes
+ if (state.isNull() || !state->isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ if (!modificationGroupActive() && !state->location().isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ m_modelToTextMerger.changePropertyValue(state, name, value);
+
+ if (!modificationGroupActive())
+ m_modelToTextMerger.applyChanges(*m_textModifier);
+}
+
+/**
+ Adds a property with the given value to the given state in the QML source text.
+
+ \param state The state to which the property is added.
+ \param name The name of the property.
+ \param value The value for the new property.
+
+ \see {@link changePropertyValue}
+ */
+void ModelRewriter::addProperty(const InternalNodeState::Pointer& state, const QString& name, const QVariant& value)
+{
+ if (state.isNull() || !state->isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+// qDebug() << "add property" << name << "in node" << state->modelNode()->id() << "for state" << state->modelState()->name();
+
+ m_modelToTextMerger.addProperty(state, name, value);
+
+ if (!modificationGroupActive())
+ m_modelToTextMerger.applyChanges(*m_textModifier);
+}
+
+/**
+ Removes a property from the given state in the QML source text.
+
+ \param state The state from which to remove the property.
+ \param name The name of the property to remove.
+ */
+void ModelRewriter::removeProperty(const InternalNodeState::Pointer& state, const QString& name)
+{
+ if (state.isNull() || !state->isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+// qDebug() << "remove property" << name << "in node" << state->modelNode()->id() << "for state" << state->modelState()->name();
+
+ m_modelToTextMerger.removeProperty(state, name);
+
+ if (!modificationGroupActive())
+ m_modelToTextMerger.applyChanges(*m_textModifier);
+}
+
+void ModelRewriter::changeNodeId(const InternalNodePointer& node, const QString& id)
+{
+ if (node.isNull() || !node->isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ m_modelToTextMerger.changeNodeId(node, id);
+
+ if (!modificationGroupActive())
+ m_modelToTextMerger.applyChanges(*m_textModifier);
+}
+
+/**
+ Move the node after the given afterNode.
+
+ \param node the node to move
+ \param afterNode the node before which the node is put. Pass in InternalNodePointer() to move the node to the end.
+ */
+void ModelRewriter::moveNodeBefore(const InternalNodePointer& node, const InternalNodePointer& beforeNode)
+{
+ if (node.isNull() || !node->isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ if (!modificationGroupActive() && !node->baseNodeState()->location().isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ if (!beforeNode.isNull() && beforeNode->isValid())
+ if (!modificationGroupActive() && !beforeNode->baseNodeState()->location().isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ m_modelToTextMerger.moveNodeBefore(node, beforeNode);
+
+ if (!modificationGroupActive())
+ m_modelToTextMerger.applyChanges(*m_textModifier);
+}
+
+void ModelRewriter::addModelState(const InternalModelState::Pointer &state)
+{
+ if (state.isNull() || !state->isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ m_modelToTextMerger.addModelState(state);
+
+ if (!modificationGroupActive())
+ m_modelToTextMerger.applyChanges(*m_textModifier);
+}
+
+void ModelRewriter::removeModelState(const InternalModelState::Pointer &state)
+{
+ m_modelToTextMerger.removeModelState(state);
+
+ if (!modificationGroupActive())
+ m_modelToTextMerger.applyChanges(*m_textModifier);
+}
+
+void ModelRewriter::setStateName(const InternalModelStatePointer &state, const QString &name)
+{
+ if (state.isNull() || !state->isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ if (!modificationGroupActive() && !state->location().isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ m_modelToTextMerger.setStateName(state, name);
+
+ if (!modificationGroupActive())
+ m_modelToTextMerger.applyChanges(*m_textModifier);
+}
+
+void ModelRewriter::setStateWhenCondition(const InternalModelStatePointer &state, const QString &whenCondition)
+{
+ if (state.isNull() || !state->isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ if (!modificationGroupActive() && !state->location().isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ m_modelToTextMerger.setStateWhenCondition(state, whenCondition);
+
+ if (!modificationGroupActive())
+ m_modelToTextMerger.applyChanges(*m_textModifier);
+}
+
+void ModelRewriter::setAnchor(const InternalNodeState::Pointer &state, const QString &propertyName, const QVariant &value)
+{
+ if (state.isNull() || !state->isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ if (state->propertyLocation(propertyName).isValid())
+ m_modelToTextMerger.changePropertyValue(state, propertyName, value);
+ else
+ m_modelToTextMerger.addProperty(state, propertyName, value);
+
+ if (!modificationGroupActive())
+ m_modelToTextMerger.applyChanges(*m_textModifier);
+}
+
+void ModelRewriter::removeAnchor(const InternalNodeState::Pointer &state, const QString &propertyName)
+{
+ if (state.isNull() || !state->isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ m_modelToTextMerger.removeProperty(state, propertyName);
+
+ if (!modificationGroupActive())
+ m_modelToTextMerger.applyChanges(*m_textModifier);
+}
+
+void ModelRewriter::setAnchorMargin(const InternalNodeState::Pointer &state, const QString &propertyName, const QVariant &value)
+{
+ if (state.isNull() || !state->isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ if (state->propertyLocation(propertyName).isValid()) {
+ if (value.toDouble() == 0.0 && state->isBaseState())
+ m_modelToTextMerger.removeProperty(state, propertyName);
+ else
+ m_modelToTextMerger.changePropertyValue(state, propertyName, value);
+ } else {
+ if (value.toDouble() == 0.0 && state->isBaseState()) {
+ // do nothing
+ } else {
+ m_modelToTextMerger.addProperty(state, propertyName, value);
+ }
+ }
+
+ if (!modificationGroupActive())
+ m_modelToTextMerger.applyChanges(*m_textModifier);
+}
+
+void ModelRewriter::addNode(const InternalNodePointer& newNode, const InternalNodePointer& parentNode)
+{
+ if (newNode.isNull() || !newNode->isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ if (!modificationGroupActive() && !parentNode->baseNodeState()->location().isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ m_modelToTextMerger.addNode(newNode, parentNode);
+
+ if (!modificationGroupActive())
+ m_modelToTextMerger.applyChanges(*m_textModifier);
+}
+
+void ModelRewriter::removeNode(const InternalNodePointer &node)
+{
+ if (node.isNull() || !node->isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ if (!modificationGroupActive() && !node->baseNodeState()->location().isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ m_modelToTextMerger.removeNode(node);
+
+ if (!modificationGroupActive())
+ m_modelToTextMerger.applyChanges(*m_textModifier);
+}
+
+void ModelRewriter::reparentNode(const InternalNodePointer &child, const InternalNodePointer &newParent)
+{
+ if (child.isNull() || !child->isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+ if (newParent.isNull() || !newParent->isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ if (!modificationGroupActive() && !newParent->baseNodeState()->location().isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ m_modelToTextMerger.reparentNode(child, newParent);
+
+ if (!modificationGroupActive())
+ m_modelToTextMerger.applyChanges(*m_textModifier);
+}
+
+ModificationGroupToken ModelRewriter::beginModificationGroup()
+{
+ ModificationGroupToken newToken(m_activeModificationGroups.size());
+ m_activeModificationGroups.append(newToken);
+
+ return newToken;
+}
+
+void ModelRewriter::endModificationGroup(const ModificationGroupToken& token)
+{
+ if (m_activeModificationGroups.isEmpty()) {
+ throw ModificationGroupException(__LINE__, Q_FUNC_INFO, __FILE__);
+ }
+
+ if (m_activeModificationGroups.last() != token) {
+ throw ModificationGroupException(__LINE__, Q_FUNC_INFO, __FILE__);
+ }
+
+ if (!m_activeModificationGroups.removeAll(token)) {
+ throw ModificationGroupException(__LINE__, Q_FUNC_INFO, __FILE__);
+ }
+
+ if (!modificationGroupActive()) {
+ m_modelToTextMerger.applyChanges(*m_textModifier);
+ }
+}
+
+bool ModelRewriter::lastRewriteFailed() const
+{
+ return m_lastRewriteFailed;
+}
+
+QMimeData *ModelRewriter::copy(const QList<InternalNodeState::Pointer> &nodeStates) const
+{
+ if (modificationGroupActive())
+ throw ModificationGroupException(__LINE__, Q_FUNC_INFO, __FILE__);
+
+ const QString sourceCode = m_textModifier->text();
+ CopyHelper copyHelper(sourceCode);
+ return copyHelper.createMimeData(nodeStates);
+}
+
+/*!
+ Inserts the copied data into the given node.
+
+ \note The mime-type for the data must be <tt>"application/x-qt-bauhaus"</tt>, otherwise the paste will fail.
+
+ \param transferData The clip-board contents to paste.
+ \param intoNode The node into which the clip-board contents are to be pasted.
+ \return true if successful, false otherwise.
+ */
+bool ModelRewriter::paste(QMimeData *transferData, const InternalNode::Pointer &intoNode)
+{
+ if (!transferData)
+ return false;
+
+ if (intoNode.isNull() || !intoNode->isValid())
+ throw InvalidModelNodeException(__LINE__, Q_FUNC_INFO, __FILE__);
+
+ Paster paster(transferData, intoNode);
+ if (paster.doPaste(m_modelToTextMerger)) {
+ if (!modificationGroupActive()) {
+ m_modelToTextMerger.applyChanges(*m_textModifier);
+ }
+ return true;
+ } else {
+ m_modelToTextMerger.clear();
+ return false;
+ }
+}
+
+/*!
+ Adds the given import to the QML file, if it doesn't already exist.
+
+ \param import The import to add.
+ */
+void ModelRewriter::addImport(const Import &import)
+{
+ m_modelToTextMerger.addImport(import);
+
+ if (!modificationGroupActive())
+ m_modelToTextMerger.applyChanges(*m_textModifier);
+}
+
+/*!
+ Removes the given import from the QML file.
+
+ \param import The import to remove.
+ */
+void ModelRewriter::removeImport(const Import &import)
+{
+ m_modelToTextMerger.removeImport(import);
+
+ if (!modificationGroupActive())
+ m_modelToTextMerger.applyChanges(*m_textModifier);
+}
+
+/*!
+ Slot connected to the textChanged() signal of the underlying QTextDocument. This slot will start the second part of the rewriting phase, being
+ the part where the QML document is parsed and any changes being merged into the Model.
+
+ Any errors that occur during this phase will be reported by emitting the errorDuringRewrite() signal.
+ */
+void ModelRewriter::mergeChanges()
+{
+// qDebug() << "*** Running rewrite...";
+
+ m_lastRewriteFailed = false;
+
+ QList<QmlError> errors;
+ if (reloadAndMerge(&errors)) {
+// qDebug() << "===> Roundtrip done";
+ } else {
+ qDebug() << "===> Error doing round-trip";
+ qDebug() << "new data:" << m_textModifier->text().toUtf8();
+ qDebug() << "old data:" << m_lastCorrectData;
+ m_lastRewriteFailed = true;
+ emit errorDuringRewrite(errors);
+ }
+}
+
+/*!
+ \fn void ModelRewriter::errorDuringRewrite(const QList<QmlError> &errors)
+ Emitted when an error when reading or merging changes back after the underlying text (-document) changed.
+
+ \note This signal can be emitted after a modification by from within the application, or by a change done by a text editor which uses the same
+ QTextDocument.
+ */
+
+}
+}
diff --git a/src/plugins/qmldesigner/core/model/modelrewriter.h b/src/plugins/qmldesigner/core/model/modelrewriter.h
new file mode 100644
index 0000000000..8cb34efd38
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/modelrewriter.h
@@ -0,0 +1,125 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef MODELREWRITER_H
+#define MODELREWRITER_H
+
+#include <QtCore/QByteArray>
+#include <QtCore/QMimeData>
+#include <QtCore/QObject>
+#include <QtCore/QUrl>
+
+#include "anchorline.h"
+#include "import.h"
+#include "modeltotextmerger.h"
+#include "model.h"
+#include "modelnode.h"
+#include "modificationgrouptoken.h"
+#include "subcomponentmanager.h"
+#include "texttomodelmerger.h"
+
+namespace QmlDesigner {
+class TextModifier;
+
+namespace Internal {
+
+class ModelPrivate;
+
+class ModelRewriter: public QObject
+{
+ Q_OBJECT
+
+public:
+ ModelRewriter(Model* model, TextModifier* textModifier);
+
+ TextModifier *textModifier() const { return m_textModifier; }
+
+ bool load(const QUrl &url, QList<QmlError> *errors = 0);
+ bool reloadAndMerge(QList<QmlError> *errors = 0);
+ void setFileUrl(const QUrl& url);
+
+ ModificationGroupToken beginModificationGroup();
+ void endModificationGroup(const ModificationGroupToken& token);
+
+ // Property change actions:
+ void addProperty(const InternalNodeState::Pointer& state, const QString& name, const QVariant& value);
+ void changePropertyValue(const InternalNodeState::Pointer& state, const QString& name, const QVariant& value);
+ void removeProperty(const InternalNodeState::Pointer& state, const QString& name);
+
+ // Node change actions:
+ void addNode(const InternalNodePointer& newNode, const InternalNodePointer& parentNode);
+ void reparentNode(const InternalNodePointer &child, const InternalNodePointer &newParent);
+ void removeNode(const InternalNodePointer &node);
+ void changeNodeId(const InternalNodePointer& node, const QString& id);
+ void moveNodeBefore(const InternalNodePointer& node, const InternalNodePointer& beforeNode);
+
+ // State change actions:
+ void addModelState(const InternalModelState::Pointer &state);
+ void removeModelState(const InternalModelState::Pointer &state);
+ void setStateName(const InternalModelStatePointer &state, const QString &name);
+ void setStateWhenCondition(const InternalModelStatePointer &state, const QString &whenCondition);
+
+ // Anchors:
+ void setAnchor(const InternalNodeState::Pointer &state, const QString &propertyName, const QVariant &value);
+ void removeAnchor(const InternalNodeState::Pointer &state, const QString &propertyName);
+ void setAnchorMargin(const InternalNodeState::Pointer &state, const QString &propertyName, const QVariant &value);
+
+ bool lastRewriteFailed() const;
+
+ // Copy & Paste:
+ QMimeData* copy(const QList<InternalNodeState::Pointer> &nodeStates) const;
+ bool paste(QMimeData *transferData, const InternalNode::Pointer &intoNode);
+
+ // Imports:
+ void addImport(const Import &import);
+ void removeImport(const Import &import);
+
+public slots:
+ void mergeChanges();
+
+signals:
+ void errorDuringRewrite(const QList<QmlError> &errors);
+
+private:
+ bool modificationGroupActive() const { return !m_activeModificationGroups.isEmpty(); }
+
+private:
+ SubComponentManager m_subcomponentManager;
+ QByteArray m_lastCorrectData;
+ QList<ModificationGroupToken> m_activeModificationGroups;
+ TextModifier* m_textModifier;
+ ModelToTextMerger m_modelToTextMerger;
+ TextToModelMerger m_textToModelMerger;
+ bool m_lastRewriteFailed;
+};
+
+}
+}
+
+#endif //MODELREWRITER_H
diff --git a/src/plugins/qmldesigner/core/model/modeltotextmerger.cpp b/src/plugins/qmldesigner/core/model/modeltotextmerger.cpp
new file mode 100644
index 0000000000..204c7b211e
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/modeltotextmerger.cpp
@@ -0,0 +1,319 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "modelnodepositionrecalculator.h"
+#include "modeltotextmerger.h"
+#include "qmltextgenerator.h"
+#include "rewriteactioncompressor.h"
+#include "rewriterview.h"
+#include <filemanager/qmldocument.h>
+#include <QDebug>
+#include <variantproperty.h>
+#include <nodelistproperty.h>
+#include <nodeproperty.h>
+#include <textmodifier.h>
+
+#define INDENT_DEPTH 4
+#undef DUMP_REWRITE_ACTIONS
+
+using namespace QmlDesigner;
+using namespace QmlDesigner::Internal;
+
+ModelToTextMerger::ModelToTextMerger(RewriterView *reWriterView):
+ m_rewriterView(reWriterView)
+{
+}
+
+void ModelToTextMerger::nodeCreated(const ModelNode &/*createdNode*/)
+{
+ //the rewriter ignores model nodes outside of the hierachy
+}
+
+void ModelToTextMerger::nodeRemoved(const ModelNode &removedNode, const NodeAbstractProperty &parentProperty, PropertyChangeFlags propertyChange)
+{
+ if (!isInHierarchy(parentProperty))
+ return;
+
+ if (parentProperty.isDefaultProperty()) {
+ schedule(new RemoveNodeRewriteAction(removedNode));
+ } else if (AbstractView::EmptyPropertiesRemoved == propertyChange) {
+ schedule(new RemovePropertyRewriteAction(parentProperty));
+ } else if (parentProperty.isNodeListProperty()) {
+ schedule(new RemoveNodeRewriteAction(removedNode));
+ }
+}
+
+void ModelToTextMerger::propertiesRemoved(const QList<AbstractProperty>& propertyList)
+{
+ foreach (const AbstractProperty &property, propertyList) {
+ if (isInHierarchy(property) && !property.isDefaultProperty())
+ schedule(new RemovePropertyRewriteAction(property));
+ }
+}
+
+void ModelToTextMerger::propertiesChanged(const QList<AbstractProperty>& propertyList, PropertyChangeFlags propertyChange)
+{
+ foreach (const AbstractProperty &property, propertyList) {
+ if (!isInHierarchy(property))
+ continue;
+
+ ModelNode containedModelNode;
+
+ switch (propertyChange) {
+ case AbstractView::PropertiesAdded:
+ if (property.isNodeProperty())
+ containedModelNode = property.toNodeProperty().modelNode();
+
+ schedule(new AddPropertyRewriteAction(property,
+ QmlTextGenerator(getPropertyOrder(), INDENT_DEPTH)(property),
+ propertyType(property),
+ containedModelNode));
+ break;
+
+ case AbstractView::NoAdditionalChanges:
+ if (property.isNodeProperty())
+ containedModelNode = property.toNodeProperty().modelNode();
+
+ schedule(new ChangePropertyRewriteAction(property,
+ QmlTextGenerator(getPropertyOrder(), INDENT_DEPTH)(property),
+ propertyType(property),
+ containedModelNode));
+ break;
+
+ case AbstractView::EmptyPropertiesRemoved:
+ break;
+
+ default:
+ Q_ASSERT(!"Unknown PropertyChangeFlags");
+ }
+ }
+}
+
+void ModelToTextMerger::nodeTypeChanged(const ModelNode &node,const QString &/*type*/, int /*majorVersion*/, int /*minorVersion*/)
+{
+ if (!node.isInHierarchy())
+ return;
+
+ // TODO: handle the majorVersion and the minorVersion
+
+ schedule(new ChangeTypeRewriteAction(node));
+}
+
+void ModelToTextMerger::nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange)
+{
+ if (isInHierarchy(oldPropertyParent) && isInHierarchy(newPropertyParent)) { // the node is moved
+ schedule(new ReparentNodeRewriteAction(node, newPropertyParent, propertyType(newPropertyParent)));
+ } else if (isInHierarchy(oldPropertyParent) && !isInHierarchy(newPropertyParent)) { // the node is removed from hierarchy
+ if (oldPropertyParent.isNodeProperty()) {
+ // ignore, the subsequent remove property will take care of all
+ } else if (oldPropertyParent.isNodeListProperty()) {
+ if (!oldPropertyParent.isDefaultProperty() && oldPropertyParent.toNodeListProperty().toModelNodeList().size() == 0) {
+ schedule(new RemovePropertyRewriteAction(oldPropertyParent));
+ } else {
+ schedule(new RemoveNodeRewriteAction(node));
+ }
+ } else {
+ schedule(new RemoveNodeRewriteAction(node));
+ }
+ } else if (!isInHierarchy(oldPropertyParent) && isInHierarchy(newPropertyParent)) { // the node is inserted into to hierarchy
+ switch (propertyChange) {
+ case AbstractView::PropertiesAdded:
+ schedule(new AddPropertyRewriteAction(newPropertyParent, QmlTextGenerator(getPropertyOrder())(node), propertyType(newPropertyParent), node));
+ break;
+
+ case AbstractView::NoAdditionalChanges:
+ schedule(new ChangePropertyRewriteAction(newPropertyParent, QmlTextGenerator(getPropertyOrder())(node), propertyType(newPropertyParent), node));
+ break;
+
+ case AbstractView::EmptyPropertiesRemoved:
+ break;
+
+ default:
+ Q_ASSERT(!"Unknown PropertyChange value");
+ }
+ } else {
+ // old is outside of hierarchy, new is outside of hierarchy, so who cares?
+ }
+}
+
+void ModelToTextMerger::nodeIdChanged(const ModelNode& node, const QString& newId, const QString& oldId)
+{
+ if (!node.isInHierarchy())
+ return;
+
+ schedule(new ChangeIdRewriteAction(node, oldId, newId));
+}
+
+void ModelToTextMerger::nodeSlidAround(const ModelNode &movingNode, const ModelNode &inFrontOfNode)
+{
+ if (!inFrontOfNode.isValid() || movingNode.parentProperty() == inFrontOfNode.parentProperty())
+ schedule(new MoveNodeRewriteAction(movingNode, inFrontOfNode));
+ else
+ Q_ASSERT(!"Nodes do not belong to the same containing property");
+}
+
+RewriterView *ModelToTextMerger::view()
+{
+ return m_rewriterView;
+}
+
+void ModelToTextMerger::applyChanges()
+{
+ dumpRewriteActions(QLatin1String("Before compression"));
+ RewriteActionCompressor compress(getPropertyOrder());
+ compress(m_rewriteActions);
+ dumpRewriteActions(QLatin1String("After compression"));
+
+ if (m_rewriteActions.isEmpty())
+ return;
+
+ QmlEditor::QmlDocument::Ptr tmpDocument(QmlEditor::QmlDocument::create(QLatin1String("<ModelToTextMerger>")));
+ tmpDocument->setSource(m_rewriterView->textModifier()->text());
+ if (!tmpDocument->parse()) {
+ qDebug() << "*** Possible problem: QML file wasn't parsed correctly.";
+ qDebug() << "*** QML text:" << m_rewriterView->textModifier()->text();
+ return;
+ }
+
+ TextModifier *textModifier = m_rewriterView->textModifier();
+
+ try {
+ ModelNodePositionRecalculator positionRecalculator(m_rewriterView->positionStorage(), m_rewriterView->positionStorage()->modelNodes());
+ positionRecalculator.connectTo(textModifier);
+
+ QmlEditor::QmlRefactoring refactoring(tmpDocument, *textModifier, getPropertyOrder());
+
+ textModifier->deactivateChangeSignals();
+ textModifier->startGroup();
+
+ for (int i = 0; i < m_rewriteActions.size(); ++i) {
+ if (i != 0) {
+ textModifier->flushGroup();
+ refactoring.reparseDocument();
+ }
+
+ RewriteAction* action = m_rewriteActions.at(i);
+#ifdef DUMP_REWRITE_ACTIONS
+ action->dump("Next rewrite action:");
+#endif // DUMP_REWRITE_ACTIONS
+ ModelNodePositionStorage *positionStore = m_rewriterView->positionStorage();
+ const bool success = action->execute(refactoring, *positionStore);
+ Q_ASSERT(success);
+ }
+ qDeleteAll(m_rewriteActions);
+ m_rewriteActions.clear();
+
+ textModifier->commitGroup();
+
+ reindent(positionRecalculator.dirtyAreas());
+
+ textModifier->reactivateChangeSignals();
+ } catch (...) {
+ textModifier->reactivateChangeSignals();
+
+ throw;
+ }
+}
+
+void ModelToTextMerger::reindent(const QMap<int, int> &dirtyAreas) const
+{
+// QList<int> offsets = dirtyAreas.keys();
+// qSort(offsets);
+//
+// foreach (const int offset, offsets) {
+// const int length = dirtyAreas[offset];
+// xxxx
+// }
+}
+
+void ModelToTextMerger::schedule(RewriteAction *action)
+{
+ Q_ASSERT(action);
+
+ m_rewriteActions.append(action);
+}
+
+QmlEditor::QmlRefactoring::PropertyType ModelToTextMerger::propertyType(const AbstractProperty &property)
+{
+ if (property.isBindingProperty())
+ return QmlEditor::QmlRefactoring::ObjectBinding;
+ else if (property.isNodeListProperty())
+ return QmlEditor::QmlRefactoring::ArrayBinding;
+ else if (property.isNodeProperty())
+ return QmlEditor::QmlRefactoring::ObjectBinding;
+ else if (property.isVariantProperty())
+ return QmlEditor::QmlRefactoring::ScriptBinding;
+
+ Q_ASSERT(!"cannot convert property type");
+ return (QmlEditor::QmlRefactoring::PropertyType) -1;
+}
+
+QStringList ModelToTextMerger::m_propertyOrder;
+
+QStringList ModelToTextMerger::getPropertyOrder()
+{
+ if (m_propertyOrder.isEmpty()) {
+ m_propertyOrder
+ << QLatin1String("property")
+ << QLatin1String("id")
+ << QLatin1String("x")
+ << QLatin1String("y")
+ << QLatin1String("width")
+ << QLatin1String("height")
+ << QLatin1String("position")
+ << QLatin1String("color")
+ << QLatin1String("radius")
+ << QLatin1String("text")
+ << QString::null
+ << QLatin1String("states")
+ << QLatin1String("transitions")
+ ;
+ }
+
+ return m_propertyOrder;
+}
+
+bool ModelToTextMerger::isInHierarchy(const AbstractProperty &property) {
+ return property.isValid() && property.parentModelNode().isInHierarchy();
+}
+
+void ModelToTextMerger::dumpRewriteActions(const QString &msg)
+{
+#ifdef DUMP_REWRITE_ACTIONS
+ qDebug() << "---->" << qPrintable(msg);
+
+ foreach (RewriteAction *action, m_rewriteActions) {
+ action->dump("-----");
+ }
+
+ qDebug() << "<----" << qPrintable(msg);
+#else // DUMP_REWRITE_ACTIONS
+ Q_UNUSED(msg);
+#endif // DUMP_REWRITE_ACTIONS
+}
diff --git a/src/plugins/qmldesigner/core/model/modeltotextmerger.h b/src/plugins/qmldesigner/core/model/modeltotextmerger.h
new file mode 100644
index 0000000000..3511625a78
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/modeltotextmerger.h
@@ -0,0 +1,95 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef MODELTOTEXTMERGER_H
+#define MODELTOTEXTMERGER_H
+
+#include "corelib_global.h"
+#include <modelnode.h>
+#include "abstractview.h"
+#include "nodeabstractproperty.h"
+#include "variantproperty.h"
+#include "nodelistproperty.h"
+#include "bindingproperty.h"
+#include "rewriteaction.h"
+#include <filemanager/qmlrefactoring.h>
+#include <QMap>
+#include <QSet>
+#include <QHash>
+#include <QVariant>
+
+namespace QmlDesigner {
+
+class CORESHARED_EXPORT RewriterView;
+
+namespace Internal {
+
+class ModelToTextMerger
+{
+ typedef AbstractView::PropertyChangeFlags PropertyChangeFlags;
+ static QStringList m_propertyOrder;
+
+public:
+ ModelToTextMerger(RewriterView *reWriterView);
+ void applyChanges();
+
+ void nodeCreated(const ModelNode &createdNode);
+ void nodeRemoved(const ModelNode &removedNode, const NodeAbstractProperty &parentProperty, PropertyChangeFlags propertyChange);
+ void propertiesRemoved(const QList<AbstractProperty>& propertyList);
+ void propertiesChanged(const QList<AbstractProperty>& propertyList, PropertyChangeFlags propertyChange);
+ void nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange);
+ void nodeIdChanged(const ModelNode& node, const QString& newId, const QString& oldId);
+ void nodeSlidAround(const ModelNode &movingNode, const ModelNode &inFrontOfNode);
+ void nodeTypeChanged(const ModelNode &node,const QString &type, int majorVersion, int minorVersion);
+
+protected:
+ RewriterView *view();
+
+ void reindent(const QMap<int,int> &dirtyAreas) const;
+
+ void schedule(RewriteAction *action);
+ QList<RewriteAction *> scheduledRewriteActions() const
+ { return m_rewriteActions; }
+
+ static QmlEditor::QmlRefactoring::PropertyType propertyType(const AbstractProperty &property);
+ static QStringList getPropertyOrder();
+
+ static bool isInHierarchy(const AbstractProperty &property);
+
+ void dumpRewriteActions(const QString &msg);
+
+private:
+ RewriterView *m_rewriterView;
+ QList<RewriteAction *> m_rewriteActions;
+};
+
+} //Internal
+} //QmlDesigner
+
+#endif // MODELTOTEXTMERGER_H
diff --git a/src/plugins/qmldesigner/core/model/modelutilities.cpp b/src/plugins/qmldesigner/core/model/modelutilities.cpp
new file mode 100644
index 0000000000..884d697097
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/modelutilities.cpp
@@ -0,0 +1,125 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "modelutilities.h"
+#include <metainfo.h>
+#include <model.h>
+#include "model/propertyparser.h"
+#include <QtCore/QDebug>
+#include <QtDeclarative/QmlMetaType>
+#include <QtCore/QMetaProperty>
+#include <widgetqueryview.h>
+
+namespace QmlDesigner {
+using namespace Internal;
+namespace ModelUtilities {
+
+
+
+bool mustBeProxied(const ModelNode &child, const ModelNode &parent)
+{
+ return child.metaInfo().isSubclassOf("QWidget") &&
+ (parent.metaInfo().isSubclassOf("QGraphicsItem") ||
+ parent.metaInfo().isSubclassOf("QGraphicsScene"));
+ //if child widget is a QWidget and the target is either
+ //QGraphicsItem or QGraphicsScene return true
+}
+
+//ModelNode reparentAndProxymize(const ModelNode &child, const ModelNode &parent)
+//{
+// ModelNode oldProxy;
+// ModelNode oldParent(parent);
+// if (child.parentNode().type() == "QGraphicsProxyWidget")
+// oldProxy = child.parentNode();
+// if (mustBeProxied(child, parent)) {
+// if (oldProxy.isValid()) {
+// oldProxy.setParentNode(parent);
+// oldProxy = ModelNode();
+// } else {
+// ModelNode proxy = oldParent.addChildNode("QGraphicsProxyWidget");
+// const QString id = child.id() + "_proxy";
+// proxy.setPropertyValue("objectName", id);
+// proxy.setId(id);
+// return proxy;
+// }
+// } else {
+// return parent;
+// }
+// if (oldProxy.isValid())
+// oldProxy.remove();
+//
+// return ModelNode();
+//}
+
+/* \brief Returns the QGraphicsScene for a QGraphicsView,
+ if node is not derived from QGraphicsView it returns node
+*/
+
+QVariant parseProperty(const QString &className, const QString &propertyName, const QString &value)
+{
+ const QMetaObject *metaObject = QmlMetaType::qmlType(className.toAscii().constData(), 4, 6)->metaObject();
+ if (!metaObject) {
+ qWarning() << "Type " << className << "is unknown to the Qml type system";
+ return QVariant();
+ }
+ const int propertyIndex = metaObject->indexOfProperty(propertyName.toAscii().constData());
+ if (propertyIndex < 0) {
+ return QVariant();
+ }
+
+ const QString typeName = QString(metaObject->property(propertyIndex).typeName());
+ Q_ASSERT_X(!typeName.isEmpty(), Q_FUNC_INFO,
+ QString("Type name for class %1 and property %2 is empty").arg(className, propertyName).toAscii().constData());
+// NodeMetaInfo metaInfo = MetaInfo::global().create(className);
+// PropertyMetaInfo property = metaInfo.property(propertyName);
+// QString type = property.type();
+
+ return PropertyParser::read(typeName, value);
+}
+
+//void setAbsolutePosition(ModelNode node, QPointF position)
+//{
+// QPointF newPos = position;
+// ModelNode parentNode;
+// parentNode = node.parentNode();
+// if (parentNode.isValid()) {
+//// NodeInstance nodeInstance = instanceForNode(parentNode);
+//// newPos = nodeInstance.mapFromGlobal(position);
+// Q_ASSERT(false);
+// }
+// node.setPropertyValue("x", newPos.x());
+// node.setPropertyValue("y", newPos.y());
+//}
+
+
+
+
+} //namespace ModelUtilities
+} //namespace QmlDesigner
+
diff --git a/src/plugins/qmldesigner/core/model/modificationgrouptoken.cpp b/src/plugins/qmldesigner/core/model/modificationgrouptoken.cpp
new file mode 100644
index 0000000000..c22408b2f0
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/modificationgrouptoken.cpp
@@ -0,0 +1,42 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "modificationgrouptoken.h"
+
+namespace QmlDesigner {
+
+long ModificationGroupToken::uniqueNumberCounter = 0;
+
+ModificationGroupToken::ModificationGroupToken(unsigned depth):
+ m_depth(depth),
+ m_uniqueNumber(++uniqueNumberCounter)
+{
+}
+
+}
diff --git a/src/plugins/qmldesigner/core/model/nodeabstractproperty.cpp b/src/plugins/qmldesigner/core/model/nodeabstractproperty.cpp
new file mode 100644
index 0000000000..69c9fd6429
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/nodeabstractproperty.cpp
@@ -0,0 +1,120 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "nodeabstractproperty.h"
+#include "nodeproperty.h"
+#include "internalproperty.h"
+#include "internalnodelistproperty.h"
+#include "invalidmodelnodeexception.h"
+#include "invalidpropertyexception.h"
+#include "invalidreparentingexception.h"
+#include "internalnode_p.h"
+#include "model.h"
+#include "model_p.h"
+
+namespace QmlDesigner {
+
+NodeAbstractProperty::NodeAbstractProperty()
+{
+}
+
+NodeAbstractProperty::NodeAbstractProperty(const NodeAbstractProperty &property, AbstractView *view)
+ : AbstractProperty(property.name(), property.internalNode(), property.model(), view)
+{
+}
+
+NodeAbstractProperty::NodeAbstractProperty(const QString &propertyName, const Internal::InternalNodePointer &internalNode, Model *model, AbstractView *view)
+ : AbstractProperty(propertyName, internalNode, model, view)
+{
+}
+
+NodeAbstractProperty::NodeAbstractProperty(const Internal::InternalNodeAbstractProperty::Pointer &property, Model *model, AbstractView *view)
+ : AbstractProperty(property, model, view)
+{}
+
+void NodeAbstractProperty::reparentHere(const ModelNode &modelNode)
+{
+ if (internalNode()->hasProperty(name()) && !internalNode()->property(name())->isNodeAbstractProperty())
+ reparentHere(modelNode, isNodeListProperty());
+ else
+ reparentHere(modelNode, metaInfo().isListProperty()); //we could use the metasystem instead?
+}
+
+void NodeAbstractProperty::reparentHere(const ModelNode &modelNode, bool isNodeList)
+{
+ if (!isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ if (isNodeProperty()) {
+ NodeProperty nodeProperty(toNodeProperty());
+ if (nodeProperty.modelNode().isValid())
+ throw InvalidReparentingException(__LINE__, __FUNCTION__, __FILE__);
+ }
+
+ if (modelNode.isAncestorOf(parentModelNode()))
+ throw InvalidReparentingException(__LINE__, __FUNCTION__, __FILE__);
+
+ if (internalNode()->hasProperty(name()) && !internalNode()->property(name())->isNodeAbstractProperty())
+ model()->m_d->removeProperty(internalNode()->property(name()));
+
+ if (modelNode.hasParentProperty()) {
+ Internal::InternalNodeAbstractProperty::Pointer oldParentProperty = modelNode.internalNode()->parentProperty();
+
+ model()->m_d->reparentNode(internalNode(), name(), modelNode.internalNode(), isNodeList);
+
+ Q_ASSERT(!oldParentProperty.isNull());
+
+
+ } else {
+ model()->m_d->reparentNode(internalNode(), name(), modelNode.internalNode(), isNodeList);
+ }
+}
+
+bool NodeAbstractProperty::isEmpty() const
+{
+ Internal::InternalNodeAbstractProperty::Pointer property = internalNode()->nodeAbstractProperty(name());
+ if (property.isNull())
+ return true;
+ else
+ return property->isEmpty();
+}
+
+QList<ModelNode> NodeAbstractProperty::allSubNodes()
+{
+ if (!internalNode()
+ || !internalNode()->isValid()
+ || !internalNode()->hasProperty(name())
+ || !internalNode()->property(name())->isNodeAbstractProperty())
+ return QList<ModelNode>();
+
+ Internal::InternalNodeAbstractProperty::Pointer property = internalNode()->nodeAbstractProperty(name());
+ return toModelNodeList(property->allSubNodes(), view());
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/core/model/nodeanchors.cpp b/src/plugins/qmldesigner/core/model/nodeanchors.cpp
new file mode 100644
index 0000000000..4cb4d7afea
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/nodeanchors.cpp
@@ -0,0 +1,373 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+//#include "nodeanchors.h"
+//
+//#include <model.h>
+//#include <modelnode.h>
+//
+//#include "internalnode_p.h"
+//#include "internalnodeanchors.h"
+//#include "internalnodestate.h"
+//#include "invalidargumentexception.h"
+//
+//using namespace QmlDesigner::Internal;
+//
+//namespace QmlDesigner {
+//
+///*!
+//\class QmlDesigner::NodeAnchors
+//\ingroup CoreModel
+//\brief NodeAnchors is a value holder for an anchor
+//*/
+//
+//NodeAnchors::NodeAnchors(const NodeState &nodeState):
+// m_internalNode(nodeState.m_internalNode),
+// m_internalNodeState(nodeState.m_internalNodeState),
+// m_model(nodeState.m_model)
+//{
+//}
+//
+//NodeAnchors::~NodeAnchors()
+//{
+//}
+//
+//NodeAnchors::NodeAnchors(const NodeAnchors &other)
+// :m_internalNode(other.m_internalNode),
+// m_model(other.m_model)
+//{
+//
+//}
+//
+//NodeAnchors::NodeAnchors(const Internal::InternalNodeStatePointer &internalNodeState, Model *model):
+// m_internalNode(internalNodeState->modelNode()),
+// m_internalNodeState(internalNodeState),
+// m_model(model)
+//{
+//}
+//
+//NodeAnchors &NodeAnchors::operator=(const NodeAnchors &other)
+//{
+// m_internalNode = other.m_internalNode;
+// m_internalNodeState = other.m_internalNodeState;
+// m_model = other.m_model;
+//
+// return *this;
+//}
+//
+//ModelNode NodeAnchors::modelNode() const
+//{
+// return ModelNode(m_internalNode, m_model.data());
+//}
+//
+//bool NodeAnchors::isValid() const
+//{
+// return m_internalNode->isValid()
+// && m_internalNodeState->isValid() &&
+// m_model;
+//}
+//
+//NodeState NodeAnchors::nodeState() const
+//{
+// return NodeState(m_internalNodeState, m_internalNode, m_model.data());
+//}
+//
+//void NodeAnchors::setAnchor(AnchorLine::Type sourceAnchorLineType,
+// const ModelNode &targetModelNode,
+// AnchorLine::Type targetAnchorLineType)
+//{
+// Q_ASSERT(m_internalNode->isValid());
+// Q_ASSERT(m_internalNodeState->isValid());
+// Q_ASSERT(modelNode().isValid());
+//
+// m_model->setAnchor(AnchorLine(nodeState(), sourceAnchorLineType),
+// AnchorLine(targetModelNode.baseNodeState(), targetAnchorLineType));
+//}
+//
+//bool NodeAnchors::canAnchor(AnchorLine::Type sourceAnchorLineType,
+// const ModelNode & targetModelNode,
+// AnchorLine::Type targetAnchorLineType) const
+//{
+// if (modelNode() == targetModelNode)
+// return false;
+//
+// return InternalNodeAnchors(m_internalNodeState).canAnchor(sourceAnchorLineType, targetModelNode.baseNodeState().internalNodeState(), targetAnchorLineType);
+//}
+//
+//bool NodeAnchors::canAnchor(const ModelNode & targetModelNode) const
+//{
+// if (modelNode() == targetModelNode)
+// return false;
+//
+// if (possibleAnchorLines(AnchorLine::Left, targetModelNode) != AnchorLine::NoAnchor)
+// return true;
+// else if (possibleAnchorLines(AnchorLine::Top, targetModelNode) != AnchorLine::NoAnchor)
+// return true;
+// else if (possibleAnchorLines(AnchorLine::Right, targetModelNode) != AnchorLine::NoAnchor)
+// return true;
+// else if (possibleAnchorLines(AnchorLine::Bottom, targetModelNode) != AnchorLine::NoAnchor)
+// return true;
+// else if (possibleAnchorLines(AnchorLine::HorizontalCenter, targetModelNode) != AnchorLine::NoAnchor)
+// return true;
+// else
+// return possibleAnchorLines(AnchorLine::VerticalCenter, targetModelNode) != AnchorLine::NoAnchor;
+//}
+//
+//AnchorLine::Type NodeAnchors::possibleAnchorLines(AnchorLine::Type sourceAnchorLineType,
+// const ModelNode & targetModelNode) const
+//{
+// if (modelNode() == targetModelNode)
+// return AnchorLine::NoAnchor;
+//
+// int anchorTypes = AnchorLine::NoAnchor;
+// const InternalNodeAnchors anchors(m_internalNodeState);
+//
+// if (sourceAnchorLineType & AnchorLine::HorizontalMask) {
+// if (anchors.canAnchor(sourceAnchorLineType, targetModelNode.baseNodeState().internalNodeState(), AnchorLine::Left))
+// anchorTypes |= AnchorLine::Left;
+// if (anchors.canAnchor(sourceAnchorLineType, targetModelNode.baseNodeState().internalNodeState(), AnchorLine::Right))
+// anchorTypes |= AnchorLine::Right;
+// if (anchors.canAnchor(sourceAnchorLineType, targetModelNode.baseNodeState().internalNodeState(), AnchorLine::HorizontalCenter))
+// anchorTypes |= AnchorLine::HorizontalCenter;
+// } else if (sourceAnchorLineType & AnchorLine::VerticalMask) {
+// if (anchors.canAnchor(sourceAnchorLineType, targetModelNode.baseNodeState().internalNodeState(), AnchorLine::Top))
+// anchorTypes |= AnchorLine::Top;
+// if (anchors.canAnchor(sourceAnchorLineType, targetModelNode.baseNodeState().internalNodeState(), AnchorLine::Bottom))
+// anchorTypes |= AnchorLine::Bottom;
+// if (anchors.canAnchor(sourceAnchorLineType, targetModelNode.baseNodeState().internalNodeState(), AnchorLine::VerticalCenter))
+// anchorTypes |= AnchorLine::VerticalCenter;
+// }
+//
+// return (AnchorLine::Type) anchorTypes;
+//}
+//
+//AnchorLine NodeAnchors::localAnchor(AnchorLine::Type anchorLineType) const
+//{
+// return InternalNodeAnchors(m_internalNodeState).anchor(anchorLineType);
+//}
+//
+//AnchorLine NodeAnchors::anchor(AnchorLine::Type anchorLineType) const
+//{
+// Internal::InternalNodeState::Pointer statePointer(m_internalNodeState);
+// AnchorLine anchorLine = InternalNodeAnchors(statePointer).anchor(anchorLineType);
+//
+// while (!anchorLine.isValid() && statePointer->hasParentState()) {
+// statePointer = statePointer->parentState();
+// anchorLine = InternalNodeAnchors(statePointer).anchor(anchorLineType);
+// }
+//
+// return anchorLine;
+//}
+//
+//bool NodeAnchors::hasAnchor(AnchorLine::Type sourceAnchorLineType) const
+//{
+// Internal::InternalNodeState::Pointer statePointer(m_internalNodeState);
+// InternalNodeAnchors internalNodeAnchors(statePointer);
+// while (!internalNodeAnchors.hasAnchor(sourceAnchorLineType) &&
+// statePointer->hasParentState()) {
+// statePointer = statePointer->parentState();
+// internalNodeAnchors = InternalNodeAnchors(statePointer);
+// }
+//
+// return internalNodeAnchors.hasAnchor(sourceAnchorLineType);
+//}
+//
+//void NodeAnchors::removeAnchor(AnchorLine::Type sourceAnchorLineType)
+//{
+// if (hasLocalAnchor(sourceAnchorLineType))
+// m_model->removeAnchor(AnchorLine(nodeState(), sourceAnchorLineType));
+//}
+//
+//void NodeAnchors::removeMargins()
+//{
+// removeMargin(AnchorLine::Left);
+// removeMargin(AnchorLine::Right);
+// removeMargin(AnchorLine::Top);
+// removeMargin(AnchorLine::Bottom);
+// removeMargin(AnchorLine::HorizontalCenter);
+// removeMargin(AnchorLine::VerticalCenter);
+// removeMargin(AnchorLine::Baseline);
+//}
+//
+//void NodeAnchors::removeAnchors()
+//{
+// removeAnchor(AnchorLine::Left);
+// removeAnchor(AnchorLine::Right);
+// removeAnchor(AnchorLine::Top);
+// removeAnchor(AnchorLine::Bottom);
+// removeAnchor(AnchorLine::HorizontalCenter);
+// removeAnchor(AnchorLine::VerticalCenter);
+// removeAnchor(AnchorLine::Baseline);
+//}
+//
+//bool NodeAnchors::hasLocalAnchor(AnchorLine::Type sourceAnchorLineType) const
+//{
+// return InternalNodeAnchors(m_internalNodeState).hasAnchor(sourceAnchorLineType);
+//}
+//
+//bool NodeAnchors::hasLocalAnchors() const
+//{
+// return hasLocalAnchor(AnchorLine::Top) ||
+// hasLocalAnchor(AnchorLine::Bottom) ||
+// hasLocalAnchor(AnchorLine::Left) ||
+// hasLocalAnchor(AnchorLine::Right) ||
+// hasLocalAnchor(AnchorLine::VerticalCenter) ||
+// hasLocalAnchor(AnchorLine::HorizontalCenter) ||
+// hasLocalAnchor(AnchorLine::Baseline);
+//}
+//
+//bool NodeAnchors::hasAnchors() const
+//{
+// return hasAnchor(AnchorLine::Top) ||
+// hasAnchor(AnchorLine::Bottom) ||
+// hasAnchor(AnchorLine::Left) ||
+// hasAnchor(AnchorLine::Right) ||
+// hasAnchor(AnchorLine::VerticalCenter) ||
+// hasAnchor(AnchorLine::HorizontalCenter) ||
+// hasAnchor(AnchorLine::Baseline);
+//}
+//
+//void NodeAnchors::setMargin(AnchorLine::Type sourceAnchorLineType, double margin) const
+//{
+// m_model->setAnchorMargin(AnchorLine(nodeState(), sourceAnchorLineType), margin);
+//}
+//
+//bool NodeAnchors::hasMargin(AnchorLine::Type sourceAnchorLineType) const
+//{
+// return InternalNodeAnchors(m_internalNodeState).hasMargin(sourceAnchorLineType);
+//}
+//
+//double NodeAnchors::localMargin(AnchorLine::Type sourceAnchorLineType) const
+//{
+// return InternalNodeAnchors(m_internalNodeState).margin(sourceAnchorLineType);
+//}
+//
+//double NodeAnchors::margin(AnchorLine::Type sourceAnchorLineType) const
+//{
+// Internal::InternalNodeState::Pointer statePointer(m_internalNodeState);
+// InternalNodeAnchors internalNodeAnchors(statePointer);
+// while (!internalNodeAnchors.hasMargin(sourceAnchorLineType) &&
+// statePointer->hasParentState()) {
+// statePointer = statePointer->parentState();
+// internalNodeAnchors = InternalNodeAnchors(statePointer);
+// }
+//
+// return internalNodeAnchors.margin(sourceAnchorLineType);
+//}
+//
+//void NodeAnchors::removeMargin(AnchorLine::Type sourceAnchorLineType)
+//{
+// m_model->removeAnchorMargin(AnchorLine(nodeState(), sourceAnchorLineType));
+//
+//}
+//
+//QDebug operator<<(QDebug debug, const NodeAnchors &anchors)
+//{
+// debug.nospace() << "NodeAnchors(";
+// if (anchors.isValid()) {
+// if (anchors.hasAnchor(AnchorLine::Top))
+// debug << "top";
+// if (anchors.hasMargin(AnchorLine::Top))
+// debug.nospace() << "(" << anchors.margin(AnchorLine::Top) << ")";
+// if (anchors.hasAnchor(AnchorLine::Bottom))
+// debug << "bottom";
+// if (anchors.hasMargin(AnchorLine::Bottom))
+// debug.nospace() << "(" << anchors.margin(AnchorLine::Bottom) << ")";
+// if (anchors.hasAnchor(AnchorLine::Left))
+// debug << "left";
+// if (anchors.hasMargin(AnchorLine::Left))
+// debug.nospace() << "(" << anchors.margin(AnchorLine::Left) << ")";
+// if (anchors.hasAnchor(AnchorLine::Right))
+// debug << "right";
+// if (anchors.hasMargin(AnchorLine::Right))
+// debug.nospace() << "(" << anchors.margin(AnchorLine::Right) << ")";
+// if (anchors.hasAnchor(AnchorLine::VerticalCenter))
+// debug << "verticalCenter";
+// if (anchors.hasMargin(AnchorLine::VerticalCenter))
+// debug.nospace() << "(" << anchors.margin(AnchorLine::VerticalCenter) << ")";
+// if (anchors.hasAnchor(AnchorLine::HorizontalCenter))
+// debug << "horizontalCenter";
+// if (anchors.hasMargin(AnchorLine::HorizontalCenter))
+// debug.nospace() << "(" << anchors.margin(AnchorLine::HorizontalCenter) << ")";
+// if (anchors.hasAnchor(AnchorLine::Baseline))
+// debug << "baseline";
+// if (anchors.hasMargin(AnchorLine::Baseline))
+// debug.nospace() << "(" << anchors.margin(AnchorLine::Baseline) << ")";
+// } else {
+// debug.nospace() << "invalid";
+// }
+//
+// debug.nospace() << ")";
+//
+// return debug.space();
+//}
+//
+//QTextStream& operator<<(QTextStream &stream, const NodeAnchors &anchors)
+//{
+// stream << "NodeAnchors(";
+// if (anchors.isValid()) {
+// if (anchors.hasAnchor(AnchorLine::Top))
+// stream << "top";
+// if (anchors.hasMargin(AnchorLine::Top))
+// stream << "(" << anchors.margin(AnchorLine::Top) << ")";
+// if (anchors.hasAnchor(AnchorLine::Bottom))
+// stream << "bottom";
+// if (anchors.hasMargin(AnchorLine::Bottom))
+// stream << "(" << anchors.margin(AnchorLine::Bottom) << ")";
+// if (anchors.hasAnchor(AnchorLine::Left))
+// stream << "left";
+// if (anchors.hasMargin(AnchorLine::Left))
+// stream << "(" << anchors.margin(AnchorLine::Left) << ")";
+// if (anchors.hasAnchor(AnchorLine::Right))
+// stream << "right";
+// if (anchors.hasMargin(AnchorLine::Right))
+// stream << "(" << anchors.margin(AnchorLine::Right) << ")";
+// if (anchors.hasAnchor(AnchorLine::VerticalCenter))
+// stream << "verticalCenter";
+// if (anchors.hasMargin(AnchorLine::VerticalCenter))
+// stream << "(" << anchors.margin(AnchorLine::VerticalCenter) << ")";
+// if (anchors.hasAnchor(AnchorLine::HorizontalCenter))
+// stream << "horizontalCenter";
+// if (anchors.hasMargin(AnchorLine::HorizontalCenter))
+// stream << "(" << anchors.margin(AnchorLine::HorizontalCenter) << ")";
+// if (anchors.hasAnchor(AnchorLine::Baseline))
+// stream << "baseline";
+// if (anchors.hasMargin(AnchorLine::Baseline))
+// stream << "(" << anchors.margin(AnchorLine::Baseline) << ")";
+// } else {
+// stream << "invalid";
+// }
+//
+// stream << ")";
+//
+// return stream;
+//}
+//
+//
+//} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/core/model/nodelistproperty.cpp b/src/plugins/qmldesigner/core/model/nodelistproperty.cpp
new file mode 100644
index 0000000000..70e3826968
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/nodelistproperty.cpp
@@ -0,0 +1,125 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "nodelistproperty.h"
+#include "internalproperty.h"
+#include "internalnodelistproperty.h"
+#include "invalidmodelnodeexception.h"
+#include "invalidpropertyexception.h"
+#include "internalnode_p.h"
+#include "model.h"
+#include "model_p.h"
+#include <qmlobjectnode.h>
+
+
+
+namespace QmlDesigner {
+
+NodeListProperty::NodeListProperty()
+{}
+
+NodeListProperty::NodeListProperty(const NodeListProperty &property, AbstractView *view)
+ : NodeAbstractProperty(property.name(), property.internalNode(), property.model(), view)
+{
+
+}
+
+NodeListProperty::NodeListProperty(const QString &propertyName, const Internal::InternalNodePointer &internalNode, Model* model, AbstractView *view) :
+ NodeAbstractProperty(propertyName, internalNode, model, view)
+{
+}
+
+NodeListProperty::NodeListProperty(const Internal::InternalNodeListProperty::Pointer &internalNodeListProperty, Model* model, AbstractView *view)
+ : NodeAbstractProperty(internalNodeListProperty, model, view)
+{
+}
+
+static QList<ModelNode> internalNodesToModelNodes(const QList<Internal::InternalNode::Pointer> &inputList, Model* model, AbstractView *view)
+{
+ QList<ModelNode> modelNodeList;
+ foreach (const Internal::InternalNode::Pointer &internalNode, inputList) {
+ modelNodeList.append(ModelNode(internalNode, model, view));
+ }
+ return modelNodeList;
+}
+
+const QList<ModelNode> NodeListProperty::toModelNodeList() const
+{
+ if (!isValid())
+ throw InvalidPropertyException(__LINE__, __FUNCTION__, __FILE__, "<invalid node list property>");
+
+ if (internalNode()->hasProperty(name())) {
+ Internal::InternalProperty::Pointer internalProperty = internalNode()->property(name());
+ if (internalProperty->isNodeListProperty()) {
+ return internalNodesToModelNodes(internalProperty->toNodeListProperty()->nodeList(), model(), view());
+ }
+ }
+
+ return QList<ModelNode>();
+}
+
+const QList<QmlObjectNode> NodeListProperty::toQmlObjectNodeList() const
+{
+ QmlModelView *fxView = view()->toQmlModelView();
+
+ if (fxView == 0)
+ return QList<QmlObjectNode>();
+
+ QList<QmlObjectNode> fxObjectNodeList;
+
+ foreach (const ModelNode &modelNode, toModelNodeList())
+ fxObjectNodeList.append(QmlObjectNode(modelNode));
+
+ return fxObjectNodeList;
+}
+
+void NodeListProperty::slide(int from, int to) const
+{
+ if (!isValid())
+ throw InvalidPropertyException(__LINE__, __FUNCTION__, __FILE__, "<invalid node list property>");
+ if (to > toModelNodeList().count())
+ throw InvalidPropertyException(__LINE__, __FUNCTION__, __FILE__, "<invalid node list sliding>");
+
+ model()->m_d->slideNodeList(internalNode(), name(), from, to);
+}
+
+void NodeListProperty::reparentHere(const ModelNode &modelNode)
+{
+ NodeAbstractProperty::reparentHere(modelNode, true);
+}
+
+bool NodeListProperty::isEmpty() const
+{
+ if (!isValid())
+ throw InvalidPropertyException(__LINE__, __FUNCTION__, __FILE__, "<invalid node list property>");
+ return toModelNodeList().empty();
+}
+
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/core/model/nodeproperty.cpp b/src/plugins/qmldesigner/core/model/nodeproperty.cpp
new file mode 100644
index 0000000000..35b7398c2f
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/nodeproperty.cpp
@@ -0,0 +1,91 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "nodeproperty.h"
+#include "internalnodeproperty.h"
+#include "invalidmodelnodeexception.h"
+#include "invalidpropertyexception.h"
+#include "invalidargumentexception.h"
+#include "internalnode_p.h"
+#include "model.h"
+#include "model_p.h"
+
+namespace QmlDesigner {
+
+NodeProperty::NodeProperty()
+{
+}
+
+NodeProperty::NodeProperty(const QString &propertyName, const Internal::InternalNodePointer &internalNode, Model* model, AbstractView *view)
+ : NodeAbstractProperty(propertyName, internalNode, model, view)
+{
+
+}
+
+void NodeProperty::setModelNode(const ModelNode &modelNode)
+{
+ if (!isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ if (!modelNode.isValid())
+ throw InvalidArgumentException(__LINE__, __FUNCTION__, __FILE__, name());
+
+ if (internalNode()->hasProperty(name())) { //check if oldValue != value
+ Internal::InternalProperty::Pointer internalProperty = internalNode()->property(name());
+ if (internalProperty->isNodeProperty()
+ && internalProperty->toNodeProperty()->node() == modelNode.internalNode())
+ return;
+ }
+
+ if (internalNode()->hasProperty(name()) && !internalNode()->property(name())->isNodeProperty())
+ model()->m_d->removeProperty(internalNode()->property(name()));
+
+ model()->m_d->reparentNode(internalNode(), name(), modelNode.internalNode(), false); //### we have to add a flag that this is not a list
+}
+
+ModelNode NodeProperty::modelNode() const
+{
+ if (!isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ if (internalNode()->hasProperty(name())) { //check if oldValue != value
+ Internal::InternalProperty::Pointer internalProperty = internalNode()->property(name());
+ if (internalProperty->isNodeProperty())
+ return ModelNode(internalProperty->toNodeProperty()->node(), model(), view());
+ }
+
+ return ModelNode();
+}
+
+void NodeProperty::reparentHere(const ModelNode &modelNode)
+{
+ NodeAbstractProperty::reparentHere(modelNode, false);
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/core/model/objectpropertybinding.cpp b/src/plugins/qmldesigner/core/model/objectpropertybinding.cpp
new file mode 100644
index 0000000000..6358e83281
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/objectpropertybinding.cpp
@@ -0,0 +1,55 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "objectpropertybinding.h"
+
+namespace QmlDesigner {
+
+ObjectPropertyBinding::ObjectPropertyBinding()
+{
+}
+
+ObjectPropertyBinding::ObjectPropertyBinding(const ModelNode &node)
+ : m_node(node)
+{
+
+}
+
+ModelNode ObjectPropertyBinding::modelNode() const
+{
+ return m_node;
+}
+
+bool ObjectPropertyBinding::isValid() const
+{
+ return m_node.isValid();
+}
+
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/core/model/painteventfilter.cpp b/src/plugins/qmldesigner/core/model/painteventfilter.cpp
new file mode 100644
index 0000000000..c5fc4ec542
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/painteventfilter.cpp
@@ -0,0 +1,73 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "painteventfilter_p.h"
+
+
+#include <QTimer>
+#include <QtDebug>
+#include <QEvent>
+
+namespace QmlDesigner {
+namespace Internal {
+
+PaintEventFilter::PaintEventFilter(QObject *parent)
+ : QObject(parent), m_pushObjectTimer(new QTimer(this))
+{
+ m_pushObjectTimer->start(20);
+ connect(m_pushObjectTimer, SIGNAL(timeout()), SLOT(emitPaintedObjects()));
+}
+
+bool PaintEventFilter::eventFilter(QObject *object, QEvent *event)
+{
+ switch(event->type())
+ {
+ case QEvent::Paint :
+ {
+ m_paintedObjects.append(object);
+ }
+
+ default: return false;
+
+ }
+
+ return false;
+}
+
+void PaintEventFilter::emitPaintedObjects()
+{
+ if (m_paintedObjects.isEmpty())
+ return;
+
+ emit paintedObjects(m_paintedObjects);
+ m_paintedObjects.clear();
+}
+
+}
+}
diff --git a/src/plugins/qmldesigner/core/model/painteventfilter_p.h b/src/plugins/qmldesigner/core/model/painteventfilter_p.h
new file mode 100644
index 0000000000..183ade321b
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/painteventfilter_p.h
@@ -0,0 +1,65 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef PAINTEVENTFILTER_H
+#define PAINTEVENTFILTER_H
+
+#include <QObject>
+#include <QList>
+
+class QTimer;
+
+namespace QmlDesigner {
+namespace Internal {
+
+class PaintEventFilter : public QObject
+{
+ Q_OBJECT
+public:
+ PaintEventFilter(QObject *parent);
+
+signals:
+ void paintedObjects(const QList<QObject*> &paintedObjects);
+
+protected:
+ bool eventFilter(QObject *object, QEvent *event);
+
+private slots:
+ void emitPaintedObjects();
+
+private:
+ QList<QObject*> m_paintedObjects;
+ QTimer *m_pushObjectTimer;
+};
+
+}
+
+}
+
+#endif // PAINTEVENTFILTER_H
diff --git a/src/plugins/qmldesigner/core/model/parsedqml.cpp b/src/plugins/qmldesigner/core/model/parsedqml.cpp
new file mode 100644
index 0000000000..5d42307bcb
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/parsedqml.cpp
@@ -0,0 +1,53 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "parsedqml.h"
+
+namespace QmlDesigner {
+namespace Internal {
+
+ParsedQML::ParsedQML(const QString &sourceCode, const QString &fileName):
+ m_sourceCode(sourceCode),
+ m_engine(),
+ m_nodePool(fileName, &m_engine),
+ m_ast(0)
+{
+ QmlJS::Lexer lexer(&m_engine);
+ QmlJS::Parser parser(&m_engine);
+
+ const QString code = sourceCode;
+ lexer.setCode(code, 1);
+ if (parser.parse())
+ m_ast = parser.ast();
+ else
+ m_ast = 0;
+}
+
+} // namespace Internal
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/core/model/parsedqml.h b/src/plugins/qmldesigner/core/model/parsedqml.h
new file mode 100644
index 0000000000..25cc4950bf
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/parsedqml.h
@@ -0,0 +1,64 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef PARSEDQML_H
+#define PARSEDQML_H
+
+#include <QtCore/QString>
+
+#include <qmljsengine_p.h>
+#include <qmljslexer_p.h>
+#include <qmljsparser_p.h>
+#include <qmljsnodepool_p.h>
+#include <qmljsast_p.h>
+
+namespace QmlDesigner {
+namespace Internal {
+
+class ParsedQML
+{
+public:
+ ParsedQML(const QString &sourceCode, const QString &fileName = QString());
+
+ bool isValid() const { return m_ast != 0; }
+ QmlJS::AST::UiProgram *ast() const { return m_ast; }
+
+ QString sourceCode() const { return m_sourceCode; }
+
+private:
+ QString m_sourceCode;
+ QmlJS::Engine m_engine;
+ QmlJS::NodePool m_nodePool;
+ QmlJS::AST::UiProgram* m_ast;
+};
+
+} // namespace Internal
+} // namespace QmlDesigner
+
+#endif // PARSEDQML_H
diff --git a/src/plugins/qmldesigner/core/model/paster.cpp b/src/plugins/qmldesigner/core/model/paster.cpp
new file mode 100644
index 0000000000..1ad0315a49
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/paster.cpp
@@ -0,0 +1,307 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <QtCore/QByteArray>
+#include <QtCore/QDataStream>
+#include <QtCore/QSet>
+
+#include "changeimportsvisitor.h"
+#include "copypasteutil.h"
+#include "parsedqml.h"
+#include "paster.h"
+#include "qmlrewriter.h"
+
+using namespace QmlJS;
+using namespace QmlJS::AST;
+
+namespace QmlDesigner {
+namespace Internal {
+
+class ASTExtractor: public AST::Visitor, protected CopyPasteUtil
+{
+private:
+ Paster *m_paster;
+ QSet<TextLocation> m_locations;
+ bool m_inStates;
+ QString m_stateName;
+
+private:
+ TextLocation toLocation(quint32 pos, quint32 len) const { return TextLocation((int) pos, (int) len); }
+ TextLocation toLocation(const SourceLocation &firstSourceLocation, const SourceLocation &lastSourceLocation) const
+ { return toLocation(firstSourceLocation.offset, lastSourceLocation.end() - firstSourceLocation.offset); }
+
+public:
+ ASTExtractor(Paster *paster, const QSet<TextLocation> &locations, const QString &sourceCode):
+ CopyPasteUtil(sourceCode),
+ m_paster(paster),
+ m_locations(locations)
+ {}
+
+ bool operator()(QmlJS::AST::UiProgram *sourceAST) {
+ m_inStates = false;
+ m_stateName = QString();
+
+ Node::accept(sourceAST->imports, this);
+
+ if (sourceAST->members && sourceAST->members->member) {
+ visitRootMember(sourceAST->members->member);
+ }
+
+ return m_locations.isEmpty();
+ }
+
+protected:
+ bool switchInStates(bool newInStates) {
+ bool oldInStates = m_inStates;
+ m_inStates = newInStates;
+ return oldInStates;
+ }
+
+ QString switchStateName(const QString &newStateName) {
+ QString oldStateName = m_stateName;
+ m_stateName = newStateName;
+ return oldStateName;
+ }
+
+ bool visit(UiImportList *ast) {
+ for (UiImportList *it = ast; it; it = it->next) {
+ if (it->import) {
+ m_paster->addImports(createImport(it->import));
+
+ m_locations.remove(toLocation(it->import->firstSourceLocation(), it->import->lastSourceLocation()));
+ }
+ }
+
+ return false;
+ }
+
+ void visitRootMember(UiObjectMember *rootMember) {
+ if (UiObjectDefinition* root = AST::cast<UiObjectDefinition*>(rootMember)) {
+ if (m_locations.contains(toLocation(root->firstSourceLocation(), root->lastSourceLocation()))) {
+ m_paster->addNode(textAt(root->firstSourceLocation(), root->lastSourceLocation()));
+ } else if (root->initializer) {
+ for (UiObjectMemberList *it = root->initializer->members; it; it = it->next) {
+ if (!it->member)
+ continue;
+
+ if (UiArrayBinding *array = AST::cast<UiArrayBinding *>(it->member)) {
+ if (array->qualifiedId->name->asString() == "states") {
+ bool prevInStates = switchInStates(true);
+ Node::accept(array->members, this);
+ switchInStates(prevInStates);
+ continue;
+ }
+ }
+
+ Node::accept(it->member, this);
+ }
+ }
+ }
+ }
+
+ bool visit(UiObjectDefinition *ast) {
+ const SourceLocation start = ast->firstSourceLocation();
+ const SourceLocation end = ast->lastSourceLocation();
+
+ if (m_inStates) {
+ if (ast->qualifiedTypeNameId && ast->qualifiedTypeNameId->name && ast->qualifiedTypeNameId->name->asString() == "State") {
+ QString prevStateName = switchStateName(QString());
+ Node::accept(ast->initializer, this);
+ switchStateName(prevStateName);
+ return false;
+ } else if (ast->qualifiedTypeNameId && ast->qualifiedTypeNameId->name && ast->qualifiedTypeNameId->name->asString() == "PropertyChanges") {
+ if (m_locations.remove(toLocation(start, end))) {
+ m_paster->addNodeState(m_stateName, textAt(start, end));
+ }
+
+ return false;
+ } else {
+ return true;
+ }
+ } else {
+ if (m_locations.remove(toLocation(start, end))) {
+ m_paster->addNode(textAt(start, end));
+ }
+
+ return false;
+ }
+
+ return true;
+ }
+
+ bool visit(UiObjectBinding *ast) {
+ const SourceLocation start = ast->firstSourceLocation();
+ const SourceLocation end = ast->lastSourceLocation();
+
+ if (m_locations.remove(toLocation(start, end))) {
+ m_paster->addNode(textAt(start, end));
+
+ return false;
+ }
+
+ return true;
+ }
+
+ bool visit(UiScriptBinding *ast) {
+ if (m_inStates && ast->qualifiedId && ast->qualifiedId->name && ast->qualifiedId->name->asString() == "name") {
+ if (ExpressionStatement *stmt = AST::cast<ExpressionStatement *>(ast->statement)) {
+ if (StringLiteral * str = AST::cast<StringLiteral *>(stmt->expression)) {
+ m_stateName = str->value->asString();
+ }
+ }
+ }
+
+ return true;
+ }
+};
+
+static inline void mergeNestedLocation(const TextLocation &newLocation, QList<TextLocation> &locations)
+{
+ for (int i = 0; i < locations.length(); ++i) {
+ const TextLocation l = locations[i];
+
+ if (l.contains(newLocation))
+ return;
+
+ if (newLocation.contains(l)) {
+ locations.replace(i, newLocation);
+ return;
+ }
+ }
+
+ locations.append(newLocation);
+}
+
+static QList<TextLocation> mergeNestedLocation(const QList<TextLocation> &locations)
+{
+ QList<TextLocation> originals(locations);
+ QList<TextLocation> result;
+
+ if (originals.isEmpty())
+ return result;
+
+ result.append(originals.takeFirst());
+
+ foreach (const TextLocation &l, originals) {
+ mergeNestedLocation(l, result);
+ }
+
+ return result;
+}
+
+Paster::Paster(QMimeData *transferData, const InternalNode::Pointer &intoNode):
+ m_targetNode(intoNode)
+{
+ Q_ASSERT(!intoNode.isNull() && intoNode->isValid());
+
+ QList<TextLocation> locations = extractPasteData(transferData);
+
+ m_pastedLocations = mergeNestedLocation(locations);
+}
+
+bool Paster::canPaste()
+{
+ if (m_pastedLocations.isEmpty() || m_pastedSource.isEmpty())
+ return false;
+
+ ParsedQML pastedQml(m_pastedSource, "<clipboard>");
+ if (!pastedQml.isValid())
+ return false;
+
+ // TODO: expand this by checking if the paste locations can be found (esp. for states)
+ return true;
+}
+
+bool Paster::doPaste(ModelToTextMerger &modelToTextMerger)
+{
+ if (m_pastedLocations.isEmpty() || m_pastedSource.isEmpty())
+ return false;
+
+ ParsedQML pastedQml(m_pastedSource, "<clipboard>");
+ if (!pastedQml.isValid())
+ return false;
+
+ m_modelToTextMerger = &modelToTextMerger;
+
+ ASTExtractor extractor(this, QSet<TextLocation>::fromList(m_pastedLocations), m_pastedSource);
+ bool result = extractor(pastedQml.ast());
+
+ m_modelToTextMerger = 0;
+ return result;
+}
+
+void Paster::addImports(const Import &imports)
+{
+ m_modelToTextMerger->addImport(imports);
+}
+
+void Paster::addNode(const QString &nodeText)
+{
+ m_modelToTextMerger->pasteNode(m_targetNode->baseNodeState()->location(), nodeText);
+}
+
+void Paster::addNodeState(const QString &stateName, const QString &propertyChanges)
+{
+ foreach (const InternalNodeState::Pointer &nodeState, m_targetNode->nodeStates()) {
+ const InternalModelState::Pointer modelState = nodeState->modelState();
+
+ if (modelState->name() == stateName)
+ m_modelToTextMerger->pastePropertyChanges(modelState, propertyChanges);
+ }
+}
+
+QList<TextLocation> Paster::extractPasteData(QMimeData *transferData)
+{
+ QList<TextLocation> locations;
+
+ if (!transferData)
+ return locations;
+
+ QByteArray data = transferData->data("application/x-qt-bauhaus");
+ if (data.isEmpty())
+ return locations;
+
+ QDataStream is(&data, QIODevice::ReadOnly);
+
+ int locationCount = 0;
+ is >> locationCount;
+ for (int i = 0; i < locationCount; ++i) {
+ int position = 0, length = 0;
+ is >> position;
+ is >> length;
+ locations.append(TextLocation(position, length));
+ }
+
+ is >> m_pastedSource;
+
+ return locations;
+}
+
+} // namespace Internal
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/core/model/paster.h b/src/plugins/qmldesigner/core/model/paster.h
new file mode 100644
index 0000000000..6672b1e722
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/paster.h
@@ -0,0 +1,76 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef PASTER_H
+#define PASTER_H
+
+#include <QtCore/QList>
+#include <QtCore/QMimeData>
+#include <QtCore/QSet>
+#include <QtCore/QString>
+
+#include "import.h"
+#include "internalnode_p.h"
+#include "modeltotextmerger.h"
+#include "textlocation.h"
+
+namespace QmlDesigner {
+namespace Internal {
+
+class ASTExtractor;
+
+class Paster
+{
+ friend class ASTExtractor;
+
+public:
+ Paster(QMimeData *transferData, const InternalNode::Pointer &intoNode);
+
+ bool canPaste();
+ bool doPaste(ModelToTextMerger &modelToTextMerger);
+
+protected:
+ void addImports(const Import &imports);
+ void addNode(const QString &nodeText);
+ void addNodeState(const QString &stateName, const QString &propertyChanges);
+
+private:
+ QList<TextLocation> extractPasteData(QMimeData *transferData);
+
+private:
+ InternalNode::Pointer m_targetNode;
+ QList<TextLocation> m_pastedLocations;
+ QString m_pastedSource;
+ ModelToTextMerger *m_modelToTextMerger;
+};
+
+} // namespace Internal
+} // namespace QmlDesigner
+
+#endif // PASTER_H
diff --git a/src/plugins/qmldesigner/core/model/plaintexteditmodifier.cpp b/src/plugins/qmldesigner/core/model/plaintexteditmodifier.cpp
new file mode 100644
index 0000000000..d6ff674cdd
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/plaintexteditmodifier.cpp
@@ -0,0 +1,186 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <QtCore/QDebug>
+
+#include <QtGui/QPlainTextEdit>
+#include <QtGui/QUndoStack>
+
+#include <filemanager/changeset.h>
+
+#include "plaintexteditmodifier.h"
+
+using namespace Utils;
+using namespace QmlDesigner;
+
+PlainTextEditModifier::PlainTextEditModifier(QPlainTextEdit *textEdit):
+ m_changeSet(0),
+ m_textEdit(textEdit),
+ m_changeSignalsEnabled(true),
+ m_pendingChangeSignal(false),
+ m_ongoingTextChange(false)
+{
+ connect(m_textEdit, SIGNAL(textChanged()),
+ this, SLOT(textEditChanged()));
+}
+
+PlainTextEditModifier::~PlainTextEditModifier()
+{
+}
+
+void PlainTextEditModifier::save(QIODevice *device)
+{
+ device->write(m_textEdit->toPlainText().toLatin1());
+}
+
+void PlainTextEditModifier::replace(int offset, int length, const QString &replacement)
+{
+#if 0
+ qDebug() << "Original:" << m_textEdit->toPlainText();
+ qDebug() << "Replacement:" << replacement;
+ qDebug() << " offset:" << offset;
+ qDebug() << " length:" << length;
+#endif
+
+ Q_ASSERT(offset >= 0);
+ Q_ASSERT(length >= 0);
+
+ const int replacementLength = replacement.length();
+
+ if (m_changeSet) {
+ m_changeSet->replace(offset, length, replacement);
+ emit replaced(offset, length, replacementLength);
+ } else {
+ ChangeSet changeSet;
+ changeSet.replace(offset, length, replacement);
+ emit replaced(offset, length, replacementLength);
+ runRewriting(&changeSet);
+ }
+}
+
+void PlainTextEditModifier::move(const MoveInfo &moveInfo)
+{
+ Q_ASSERT(moveInfo.objectStart >= 0);
+ Q_ASSERT(moveInfo.objectEnd > moveInfo.objectStart);
+ Q_ASSERT(moveInfo.destination >= 0);
+ Q_ASSERT(moveInfo.leadingCharsToRemove >= 0);
+ Q_ASSERT(moveInfo.trailingCharsToRemove >= 0);
+ Q_ASSERT(moveInfo.objectStart - moveInfo.leadingCharsToRemove >= 0);
+
+ if (m_changeSet) {
+ m_changeSet->insert(moveInfo.destination, moveInfo.prefixToInsert);
+ m_changeSet->move(moveInfo.objectStart, moveInfo.objectEnd - moveInfo.objectStart, moveInfo.destination);
+ m_changeSet->insert(moveInfo.destination, moveInfo.suffixToInsert);
+ m_changeSet->remove(moveInfo.objectStart - moveInfo.leadingCharsToRemove, moveInfo.leadingCharsToRemove);
+ m_changeSet->remove(moveInfo.objectEnd, moveInfo.trailingCharsToRemove);
+ emit moved(moveInfo);
+ } else {
+ ChangeSet changeSet;
+ changeSet.insert(moveInfo.destination, moveInfo.prefixToInsert);
+ changeSet.move(moveInfo.objectStart, moveInfo.objectEnd - moveInfo.objectStart, moveInfo.destination);
+ changeSet.insert(moveInfo.destination, moveInfo.suffixToInsert);
+ changeSet.remove(moveInfo.objectStart - moveInfo.leadingCharsToRemove, moveInfo.leadingCharsToRemove);
+ changeSet.remove(moveInfo.objectEnd, moveInfo.trailingCharsToRemove);
+ emit moved(moveInfo);
+ runRewriting(&changeSet);
+ }
+}
+
+void PlainTextEditModifier::startGroup()
+{
+ if (!m_changeSet)
+ m_changeSet = new ChangeSet;
+
+ m_textEdit->textCursor().beginEditBlock();
+}
+
+void PlainTextEditModifier::flushGroup()
+{
+ if (m_changeSet)
+ runRewriting(m_changeSet);
+}
+
+void PlainTextEditModifier::commitGroup()
+{
+ if (m_changeSet) {
+ runRewriting(m_changeSet);
+ delete m_changeSet;
+ m_changeSet = 0;
+ }
+
+ m_textEdit->textCursor().endEditBlock();
+}
+
+void PlainTextEditModifier::textEditChanged()
+{
+ if (!m_ongoingTextChange && m_changeSignalsEnabled) {
+ emit textChanged();
+ } else {
+ m_pendingChangeSignal = true;
+ }
+}
+
+void PlainTextEditModifier::runRewriting(ChangeSet *changeSet)
+{
+ m_ongoingTextChange = true;
+ QTextCursor cursor = m_textEdit->textCursor();
+ changeSet->apply(&cursor);
+ m_ongoingTextChange = false;
+ textEditChanged();
+}
+
+QTextDocument *PlainTextEditModifier::textDocument() const
+{
+ return m_textEdit->document();
+}
+
+QString PlainTextEditModifier::text() const
+{
+ return m_textEdit->toPlainText();
+}
+
+QTextCursor PlainTextEditModifier::textCursor() const
+{
+ return m_textEdit->textCursor();
+}
+
+void PlainTextEditModifier::deactivateChangeSignals()
+{
+ m_changeSignalsEnabled = false;
+}
+
+void PlainTextEditModifier::reactivateChangeSignals()
+{
+ m_changeSignalsEnabled = true;
+
+ if (m_pendingChangeSignal) {
+ m_pendingChangeSignal = false;
+ emit textChanged();
+ }
+}
diff --git a/src/plugins/qmldesigner/core/model/propertybinding.cpp b/src/plugins/qmldesigner/core/model/propertybinding.cpp
new file mode 100644
index 0000000000..726c5456bc
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/propertybinding.cpp
@@ -0,0 +1,67 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "invalidpropertyexception.h"
+#include "propertybinding.h"
+
+namespace QmlDesigner {
+
+PropertyBinding::PropertyBinding()
+{
+}
+
+PropertyBinding::PropertyBinding(const QString &value):
+ m_value(value)
+{
+}
+
+PropertyBinding::PropertyBinding(const PropertyBinding &other):
+ m_value(other.m_value)
+{
+}
+
+PropertyBinding &PropertyBinding::operator=(const PropertyBinding &other)
+{
+ m_value = other.m_value;
+
+ return *this;
+}
+
+bool PropertyBinding::isValid() const
+{
+ return !m_value.isEmpty();
+}
+
+QString PropertyBinding::value() const
+{
+ return m_value;
+}
+
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/core/model/propertycontainer.cpp b/src/plugins/qmldesigner/core/model/propertycontainer.cpp
new file mode 100644
index 0000000000..e55e1d2756
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/propertycontainer.cpp
@@ -0,0 +1,143 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "propertycontainer.h"
+#include "propertyparser.h"
+#include <QVariant>
+#include <QString>
+#include <QRegExp>
+#include <QSize>
+#include <QSizeF>
+#include <QPoint>
+#include <QPointF>
+#include <QtDebug>
+
+namespace QmlDesigner {
+
+using namespace QmlDesigner::Internal;
+
+
+// Creates invalid PropertyContainer
+PropertyContainer::PropertyContainer()
+{
+}
+
+PropertyContainer::PropertyContainer(const QString &name, const QString &type, const QVariant &value)
+ : m_name(name), m_type(type), m_value(value)
+{
+ Q_ASSERT_X(!name.isEmpty(), Q_FUNC_INFO, "Name of property cannot be empty");
+ Q_ASSERT_X(!type.isEmpty(), Q_FUNC_INFO, "Type of property cannot be empty");
+}
+
+void PropertyContainer::set(const QString &name, const QString &type, const QVariant &value)
+{
+ m_name = name;
+ m_type = type;
+ m_value = value;
+}
+
+bool PropertyContainer::isValid() const
+{
+ return !m_name.isEmpty() && m_value.isValid();
+}
+
+QString PropertyContainer::name() const
+{
+ return m_name;
+}
+
+QVariant PropertyContainer::value() const
+{
+ if (m_value.type() == QVariant::String)
+ m_value = PropertyParser::read(m_type, m_value.toString());
+ return m_value;
+}
+
+
+void PropertyContainer::setValue(const QVariant &value)
+{
+ m_value = value;
+}
+
+QString PropertyContainer::type() const
+{
+ return m_type;
+}
+
+QDataStream &operator<<(QDataStream &stream, const PropertyContainer &propertyContainer)
+{
+ Q_ASSERT(!propertyContainer.name().isEmpty());
+ Q_ASSERT(!propertyContainer.type().isEmpty());
+ Q_ASSERT(propertyContainer.value().isValid());
+ stream << propertyContainer.name();
+ stream << propertyContainer.type();
+ stream << propertyContainer.value();
+
+
+ return stream;
+}
+
+QDataStream &operator>>(QDataStream &stream, PropertyContainer &propertyContainer)
+{
+
+ stream >> propertyContainer.m_name;
+ stream >> propertyContainer.m_type;
+ stream >> propertyContainer.m_value;
+
+ Q_ASSERT(!propertyContainer.name().isEmpty());
+
+ return stream;
+}
+
+QDataStream &operator<<(QDataStream &stream, const QList<PropertyContainer> &propertyContainerList)
+{
+ stream << propertyContainerList.count();
+ foreach (const PropertyContainer &propertyContainer, propertyContainerList)
+ stream << propertyContainer;
+
+ return stream;
+}
+
+QDataStream &operator>>(QDataStream &stream, QList<PropertyContainer> &propertyContainerList)
+{
+ int count;
+ stream >> count;
+ Q_ASSERT(count >= 0);
+ for( int i = 0; i < count; i++) {
+ PropertyContainer propertyContainer;
+ stream >> propertyContainer;
+ propertyContainerList.append(propertyContainer);
+ }
+
+ return stream;
+}
+
+
+} //namespace QmlDesigner
+
diff --git a/src/plugins/qmldesigner/core/model/propertynode.cpp b/src/plugins/qmldesigner/core/model/propertynode.cpp
new file mode 100644
index 0000000000..063b93c5a6
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/propertynode.cpp
@@ -0,0 +1,38 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "propertynode.h"
+
+namespace QmlDesigner {
+
+PropertyNode::PropertyNode()
+{
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/core/model/propertyparser.cpp b/src/plugins/qmldesigner/core/model/propertyparser.cpp
new file mode 100644
index 0000000000..8dfb88b49b
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/propertyparser.cpp
@@ -0,0 +1,176 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "propertyparser.h"
+#include <QUrl>
+#include <QtCore/QDebug>
+#include <QtDeclarative/private/qmlstringconverters_p.h>
+#include <modelnode.h>
+#include <metainfo.h>
+
+namespace QmlDesigner {
+namespace Internal {
+namespace PropertyParser {
+
+static QVariant fromEnum(const QString &string, const QString &type, const MetaInfo &metaInfo)
+{
+ if (string.isEmpty())
+ return QVariant();
+
+ // TODO Use model metainfo
+ EnumeratorMetaInfo enumerator = metaInfo.enumerator(type);
+ int value = enumerator.elementValue(string);
+ return QVariant(value);
+}
+
+QVariant read(const QString &typeStr, const QString &str, const MetaInfo &metaInfo)
+{
+ if (metaInfo.hasEnumerator(typeStr)) {
+ return fromEnum(str, typeStr, metaInfo);
+ }
+
+ return read(typeStr, str);
+}
+
+QVariant read(const QString &typeStr, const QString &str)
+{
+ QMetaType::Type type = static_cast<QMetaType::Type>(QMetaType::type(typeStr.toAscii().constData()));
+ if (type == 0)
+ qWarning() << "Type " << typeStr
+ << " is unknown to QMetaType system. Cannot create properly typed QVariant for value "
+ << str;
+
+ QVariant value;
+
+ bool conversionOk = true;
+ switch (type) {
+ case QMetaType::QPoint:
+ value = QmlStringConverters::pointFFromString(str, &conversionOk).toPoint();
+ break;
+ case QMetaType::QPointF:
+ value = QmlStringConverters::pointFFromString(str, &conversionOk);
+ break;
+ case QMetaType::QSize:
+ value = QmlStringConverters::sizeFFromString(str, &conversionOk).toSize();
+ break;
+ case QMetaType::QSizeF:
+ value = QmlStringConverters::sizeFFromString(str, &conversionOk);
+ break;
+ case QMetaType::QRect:
+ value = QmlStringConverters::rectFFromString(str, &conversionOk).toRect();
+ break;
+ case QMetaType::QRectF:
+ value = QmlStringConverters::rectFFromString(str, &conversionOk);
+ break;
+ case QMetaType::Bool:
+ value = QmlStringConverters::boolFromString(str, &conversionOk);
+ break;
+ case QMetaType::QUrl:
+ value = QVariant(QUrl(str));
+ break;
+ case QMetaType::QColor:
+ value = QmlStringConverters::colorFromString(str);
+ break;
+ default: {
+ value = QVariant(str);
+ QVariant::Type varType = static_cast<QVariant::Type>(type);
+ value.convert(varType);
+ break;
+ }
+ }
+
+ if (!conversionOk) {
+ value = QVariant();
+ qWarning() << "Could not convert" << str << "to" << QMetaType::typeName(type);
+ }
+
+ return value;
+}
+
+QString write(const QVariant &variant)
+{
+ if (!variant.isValid()) {
+ qWarning() << "Trying to serialize invalid QVariant";
+ return QString();
+ }
+ QString value;
+ switch (variant.type()) {
+ case QMetaType::QPoint:
+ {
+ QPoint p = variant.toPoint();
+ value = QString("%1,%2").arg(QString::number(p.x()), QString::number(p.y()));
+ break;
+ }
+ case QMetaType::QPointF:
+ {
+ QPointF p = variant.toPointF();
+ value = QString("%1,%2").arg(QString::number(p.x(), 'f'), QString::number(p.y(), 'f'));
+ break;
+ }
+ case QMetaType::QSize:
+ {
+ QSize s = variant.toSize();
+ value = QString("%1x%2").arg(QString::number(s.width()), QString::number(s.height()));
+ break;
+ }
+ case QMetaType::QSizeF:
+ {
+ QSizeF s = variant.toSizeF();
+ value = QString("%1x%2").arg(QString::number(s.width(), 'f'), QString::number(s.height(), 'f'));
+ break;
+ }
+ case QMetaType::QRect:
+ {
+ QRect r = variant.toRect();
+ value = QString("%1,%2,%3x%4").arg(QString::number(r.x()), QString::number(r.y()),
+ QString::number(r.width()), QString::number(r.height()));
+ break;
+ }
+ case QMetaType::QRectF:
+ {
+ QRectF r = variant.toRectF();
+ value = QString("%1,%2,%3x%4").arg(QString::number(r.x(), 'f'), QString::number(r.y(), 'f'),
+ QString::number(r.width(), 'f'), QString::number(r.height(), 'f'));
+ break;
+ }
+ default:
+ QVariant strVariant = variant;
+ strVariant.convert(QVariant::String);
+ if (!strVariant.isValid())
+ qWarning() << Q_FUNC_INFO << "cannot serialize type " << QMetaType::typeName(variant.type());
+ value = strVariant.toString();
+ }
+
+ return value;
+}
+
+} // namespace PropertyParser
+} // namespace Internal
+} // namespace Designer
+
diff --git a/src/plugins/qmldesigner/core/model/propertyparser.h b/src/plugins/qmldesigner/core/model/propertyparser.h
new file mode 100644
index 0000000000..25f6a8ef36
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/propertyparser.h
@@ -0,0 +1,49 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+ #ifndef PROPERTYPARSER_H
+#define PROPERTYPARSER_H
+
+#include <QtCore/QVariant>
+
+namespace QmlDesigner {
+class MetaInfo;
+
+namespace Internal {
+namespace PropertyParser {
+
+QVariant read(const QString &typeStr, const QString &str, const MetaInfo &metaInfo);
+QVariant read(const QString &typeStr, const QString &str);
+QString write(const QVariant &variant, const MetaInfo &metaInfo);
+
+} // namespace PropertyParser
+} // namespace Internal
+} // namespace Designer
+
+#endif // PROPERTYPARSER_H
diff --git a/src/plugins/qmldesigner/core/model/qmlanchors.cpp b/src/plugins/qmldesigner/core/model/qmlanchors.cpp
new file mode 100644
index 0000000000..9cb00a5de0
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/qmlanchors.cpp
@@ -0,0 +1,411 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "qmlanchors.h"
+#include "variantproperty.h"
+#include "bindingproperty.h"
+#include "nodeabstractproperty.h"
+#include "nodeinstance.h"
+#include "rewritertransaction.h"
+#include "qmlmodelview.h"
+#include "mathutils.h"
+
+namespace QmlDesigner {
+
+
+static QString lineTypeToString(AnchorLine::Type lineType)
+{
+ QString typeString;
+
+ switch (lineType) {
+ case AnchorLine::Left: return QLatin1String("left");
+ case AnchorLine::Top: return QLatin1String("top");
+ case AnchorLine::Right: return QLatin1String("right");
+ case AnchorLine::Bottom: return QLatin1String("bottom");
+ case AnchorLine::HorizontalCenter: return QLatin1String("horizontalCenter");
+ case AnchorLine::VerticalCenter: return QLatin1String("verticalCenter");
+ case AnchorLine::Baseline: return QLatin1String("baseline");
+ case AnchorLine::Fill: return QLatin1String("fill");
+ case AnchorLine::Center: return QLatin1String("centerIn");
+ default: return QString::null;
+ }
+}
+
+bool AnchorLine::isHorizontalAnchorLine(Type anchorline)
+{
+ return anchorline & HorizontalMask;
+}
+
+bool AnchorLine::isVerticalAnchorLine(Type anchorline)
+{
+ return anchorline & VerticalMask;
+}
+
+static AnchorLine::Type propertyNameToLineType(const QString & string)
+{
+ if (string == QLatin1String("left")) {
+ return AnchorLine::Left;
+ } else if (string == QLatin1String("top")) {
+ return AnchorLine::Top;
+ } else if (string == QLatin1String("right")) {
+ return AnchorLine::Right;
+ } else if (string == QLatin1String("bottom")) {
+ return AnchorLine::Bottom;
+ } else if (string == QLatin1String("horizontalCenter")) {
+ return AnchorLine::HorizontalCenter;
+ } else if (string == QLatin1String("verticalCenter")) {
+ return AnchorLine::VerticalCenter;
+ } else if (string == QLatin1String("baseline")) {
+ return AnchorLine::VerticalCenter;
+ } else if (string == QLatin1String("centerIn")) {
+ return AnchorLine::Center;
+ } else if (string == QLatin1String("fill")) {
+ return AnchorLine::Fill;
+ }
+
+ return AnchorLine::Invalid;
+}
+
+static QString marginPropertyName(AnchorLine::Type lineType)
+{
+ switch (lineType) {
+ case AnchorLine::Left: return QLatin1String("anchors.leftMargin");
+ case AnchorLine::Top: return QLatin1String("anchors.topMargin");
+ case AnchorLine::Right: return QLatin1String("anchors.rightMargin");
+ case AnchorLine::Bottom: return QLatin1String("anchors.bottomMargin");
+ case AnchorLine::HorizontalCenter: return QLatin1String("anchors.horizontalCenterOffset");
+ case AnchorLine::VerticalCenter: return QLatin1String("anchors.verticalCenterOffset");
+ default: return QString::null;
+ }
+}
+
+static QString anchorPropertyName(AnchorLine::Type lineType)
+{
+ const QString typeString = lineTypeToString(lineType);
+
+ if (typeString.isEmpty())
+ return QString();
+ else
+ return QString("anchors.%1").arg(typeString);
+}
+
+
+QmlAnchors::QmlAnchors(const QmlItemNode &fxItemNode) : m_qmlItemNode(fxItemNode)
+{
+}
+
+QmlItemNode QmlAnchors::qmlItemNode() const
+{
+ return m_qmlItemNode;
+}
+
+bool QmlAnchors::isValid() const
+{
+ return m_qmlItemNode.isValid();
+}
+
+void QmlAnchors::setAnchor(AnchorLine::Type sourceAnchorLine,
+ const QmlItemNode &targetQmlItemNode,
+ AnchorLine::Type targetAnchorLine)
+{
+ RewriterTransaction transaction = qmlItemNode().qmlModelView()->beginRewriterTransaction();
+ if (qmlItemNode().isInBaseState()) {
+ if ((qmlItemNode().nodeInstance().hasAnchor("anchors.fill") && (sourceAnchorLine & AnchorLine::Fill))
+ || ((qmlItemNode().nodeInstance().hasAnchor("anchors.centerIn") && (sourceAnchorLine & AnchorLine::Center)))) {
+ removeAnchor(sourceAnchorLine);
+ }
+
+ const QString propertyName = anchorPropertyName(sourceAnchorLine);
+ QString targetExpression = targetQmlItemNode.modelNode().validId();
+ if (targetQmlItemNode.modelNode() == qmlItemNode().modelNode().parentProperty().parentModelNode())
+ targetExpression = "parent";
+ targetExpression = targetExpression + "." + lineTypeToString(targetAnchorLine);
+ qmlItemNode().modelNode().bindingProperty(propertyName).setExpression(targetExpression);
+ }
+}
+
+bool detectHorizontalCycle(const ModelNode &node, QList<ModelNode> knownNodeList)
+{
+ if (knownNodeList.contains(node))
+ return true;
+
+ knownNodeList.append(node);
+
+ static QStringList validAnchorLines(QStringList() << "right" << "left" << "horizontalCenter");
+ static QStringList anchorNames(QStringList() << "anchors.right" << "anchors.left" << "anchors.horizontalCenter");
+
+ foreach (const QString &anchorName, anchorNames) {
+ if (node.hasBindingProperty(anchorName)) {
+ AbstractProperty targetProperty = node.bindingProperty(anchorName).resolveToProperty();
+ if (targetProperty.isValid()) {
+ if (!validAnchorLines.contains(targetProperty.name()))
+ return true;
+
+ if (detectHorizontalCycle(targetProperty.parentModelNode(), knownNodeList))
+ return true;
+ }
+ }
+
+ }
+
+ static QStringList anchorShortcutNames(QStringList() << "anchors.fill" << "anchors.centerIn");
+ foreach (const QString &anchorName, anchorShortcutNames) {
+ if (node.hasBindingProperty(anchorName)) {
+ ModelNode targetNode = node.bindingProperty(anchorName).resolveToModelNode();
+
+ if (targetNode.isValid() && detectHorizontalCycle(targetNode, knownNodeList))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool detectVerticalCycle(const ModelNode &node, QList<ModelNode> knownNodeList)
+{
+ if (!node.isValid())
+ return false;
+
+ if (knownNodeList.contains(node))
+ return true;
+
+ knownNodeList.append(node);
+
+ static QStringList validAnchorLines(QStringList() << "top" << "bottom" << "verticalCenter" << "baseline");
+ static QStringList anchorNames(QStringList() << "anchors.top" << "anchors.bottom" << "anchors.verticalCenter" << "anchors.baseline");
+
+ foreach (const QString &anchorName, anchorNames) {
+ if (node.hasBindingProperty(anchorName)) {
+ AbstractProperty targetProperty = node.bindingProperty(anchorName).resolveToProperty();
+ if (targetProperty.isValid()) {
+ if (!validAnchorLines.contains(targetProperty.name()))
+ return true;
+
+ if (detectVerticalCycle(targetProperty.parentModelNode(), knownNodeList))
+ return true;
+ }
+ }
+
+ }
+
+ static QStringList anchorShortcutNames(QStringList() << "anchors.fill" << "anchors.centerIn");
+ foreach (const QString &anchorName, anchorShortcutNames) {
+ if (node.hasBindingProperty(anchorName)) {
+ ModelNode targetNode = node.bindingProperty(anchorName).resolveToModelNode();
+
+ if (targetNode.isValid() && detectVerticalCycle(targetNode, knownNodeList))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool QmlAnchors::canAnchor(const QmlItemNode &targetModelNode) const
+{
+ if (!qmlItemNode().isInBaseState())
+ return false;
+
+ if (targetModelNode == qmlItemNode().instanceParent())
+ return true;
+
+ if (qmlItemNode().instanceParent() == targetModelNode.instanceParent())
+ return true;
+
+ return false;
+}
+
+AnchorLine::Type QmlAnchors::possibleAnchorLines(AnchorLine::Type sourceAnchorLineType,
+ const QmlItemNode &targetQmlItemNode) const
+{
+ if (!canAnchor(targetQmlItemNode))
+ return AnchorLine::Invalid;
+
+ if (AnchorLine::isHorizontalAnchorLine(sourceAnchorLineType)) {
+ if (!detectHorizontalCycle(targetQmlItemNode, QList<ModelNode>() << qmlItemNode().modelNode()))
+ return AnchorLine::HorizontalMask;
+ }
+
+ if (AnchorLine::isVerticalAnchorLine(sourceAnchorLineType)) {
+ if (!detectVerticalCycle(targetQmlItemNode, QList<ModelNode>() << qmlItemNode().modelNode()))
+ return AnchorLine::VerticalMask;
+ }
+
+ return AnchorLine::Invalid;
+}
+
+AnchorLine QmlAnchors::instanceAnchor(AnchorLine::Type sourceAnchorLine) const
+{
+ QPair<QString, NodeInstance> targetAnchorLinePair;
+ if (qmlItemNode().nodeInstance().hasAnchor("anchors.fill") && (sourceAnchorLine & AnchorLine::Fill)) {
+ targetAnchorLinePair = qmlItemNode().nodeInstance().anchor("anchors.fill");
+ targetAnchorLinePair.first = lineTypeToString(sourceAnchorLine);
+ } else if (qmlItemNode().nodeInstance().hasAnchor("anchors.centerIn") && (sourceAnchorLine & AnchorLine::Center)) {
+ targetAnchorLinePair = qmlItemNode().nodeInstance().anchor("anchors.centerIn");
+ targetAnchorLinePair.first = lineTypeToString(sourceAnchorLine);
+ } else {
+ targetAnchorLinePair = qmlItemNode().nodeInstance().anchor(anchorPropertyName(sourceAnchorLine));
+ }
+
+ AnchorLine::Type targetAnchorLine = propertyNameToLineType(targetAnchorLinePair.first);
+
+ if (targetAnchorLine == AnchorLine::Invalid )
+ return AnchorLine();
+
+ Q_ASSERT(targetAnchorLinePair.second.isValid());
+ return AnchorLine(QmlItemNode(qmlItemNode().nodeForInstance(targetAnchorLinePair.second)), targetAnchorLine);
+}
+
+void QmlAnchors::removeAnchor(AnchorLine::Type sourceAnchorLine)
+{
+ RewriterTransaction transaction = qmlItemNode().qmlModelView()->beginRewriterTransaction();
+ if (qmlItemNode().isInBaseState()) {
+ const QString propertyName = anchorPropertyName(sourceAnchorLine);
+ if (qmlItemNode().nodeInstance().hasAnchor("anchors.fill") && (sourceAnchorLine & AnchorLine::Fill)) {
+ qmlItemNode().modelNode().removeProperty("anchors.fill");
+ qmlItemNode().modelNode().bindingProperty("anchors.top").setExpression("parent.top");
+ qmlItemNode().modelNode().bindingProperty("anchors.left").setExpression("parent.left");
+ qmlItemNode().modelNode().bindingProperty("anchors.bottom").setExpression("parent.bottom");
+ qmlItemNode().modelNode().bindingProperty("anchors.right").setExpression("parent.right");
+
+ } else if (qmlItemNode().nodeInstance().hasAnchor("anchors.centerIn") && (sourceAnchorLine & AnchorLine::Center)) {
+ qmlItemNode().modelNode().removeProperty("anchors.centerIn");
+ qmlItemNode().modelNode().bindingProperty("anchors.horizontalCenter").setExpression("parent.horizontalCenter");
+ qmlItemNode().modelNode().bindingProperty("anchors.verticalCenter").setExpression("parent.verticalCenter");
+ }
+
+ qmlItemNode().modelNode().removeProperty(propertyName);
+ }
+}
+
+void QmlAnchors::removeAnchors()
+{
+ RewriterTransaction transaction = qmlItemNode().qmlModelView()->beginRewriterTransaction();
+ if (qmlItemNode().nodeInstance().hasAnchor("anchors.fill"))
+ qmlItemNode().modelNode().removeProperty("anchors.fill");
+ if (qmlItemNode().nodeInstance().hasAnchor("anchors.centerIn"))
+ qmlItemNode().modelNode().removeProperty("anchors.centerIn");
+ if (qmlItemNode().nodeInstance().hasAnchor("anchors.top"))
+ qmlItemNode().modelNode().removeProperty("anchors.top");
+ if (qmlItemNode().nodeInstance().hasAnchor("anchors.left"))
+ qmlItemNode().modelNode().removeProperty("anchors.left");
+ if (qmlItemNode().nodeInstance().hasAnchor("anchors.right"))
+ qmlItemNode().modelNode().removeProperty("anchors.right");
+ if (qmlItemNode().nodeInstance().hasAnchor("anchors.bottom"))
+ qmlItemNode().modelNode().removeProperty("anchors.bottom");
+ if (qmlItemNode().nodeInstance().hasAnchor("anchors.horizontalCenter"))
+ qmlItemNode().modelNode().removeProperty("anchors.horizontalCenter");
+ if (qmlItemNode().nodeInstance().hasAnchor("anchors.verticalCenter"))
+ qmlItemNode().modelNode().removeProperty("anchors.verticalCenter");
+ if (qmlItemNode().nodeInstance().hasAnchor("anchors.baseline"))
+ qmlItemNode().modelNode().removeProperty("anchors.baseline");
+}
+
+bool QmlAnchors::instanceHasAnchor(AnchorLine::Type sourceAnchorLine) const
+{
+ const QString propertyName = anchorPropertyName(sourceAnchorLine);
+
+ if (sourceAnchorLine & AnchorLine::Fill)
+ return qmlItemNode().nodeInstance().hasAnchor(propertyName) || qmlItemNode().nodeInstance().hasAnchor("anchors.fill");
+
+ if (sourceAnchorLine & AnchorLine::Center)
+ return qmlItemNode().nodeInstance().hasAnchor(propertyName) || qmlItemNode().nodeInstance().hasAnchor("anchors.centerIn");
+
+
+ return qmlItemNode().nodeInstance().hasAnchor(propertyName);
+}
+
+bool QmlAnchors::instanceHasAnchors() const
+{
+ return instanceHasAnchor(AnchorLine::Left) ||
+ instanceHasAnchor(AnchorLine::Right) ||
+ instanceHasAnchor(AnchorLine::Top) ||
+ instanceHasAnchor(AnchorLine::Bottom) ||
+ instanceHasAnchor(AnchorLine::HorizontalCenter) ||
+ instanceHasAnchor(AnchorLine::VerticalCenter) ||
+ instanceHasAnchor(AnchorLine::Baseline);
+}
+
+void QmlAnchors::setMargin(AnchorLine::Type sourceAnchorLineType, double margin) const
+{
+ QString propertyName = marginPropertyName(sourceAnchorLineType);
+ qmlItemNode().setVariantProperty(propertyName, round(margin, 4));
+}
+
+bool QmlAnchors::instanceHasMargin(AnchorLine::Type sourceAnchorLineType) const
+{
+ return !qIsNull(instanceMargin(sourceAnchorLineType));
+}
+
+double QmlAnchors::instanceMargin(AnchorLine::Type sourceAnchorLineType) const
+{
+ return qmlItemNode().nodeInstance().property(marginPropertyName(sourceAnchorLineType)).toDouble();
+}
+
+void QmlAnchors::removeMargin(AnchorLine::Type sourceAnchorLineType)
+{
+ if (qmlItemNode().isInBaseState()) {
+ QString propertyName = marginPropertyName(sourceAnchorLineType);
+ qmlItemNode().modelNode().removeProperty(propertyName);
+ }
+}
+
+void QmlAnchors::removeMargins()
+{
+ RewriterTransaction transaction = qmlItemNode().qmlModelView()->beginRewriterTransaction();
+ removeMargin(AnchorLine::Left);
+ removeMargin(AnchorLine::Right);
+ removeMargin(AnchorLine::Top);
+ removeMargin(AnchorLine::Bottom);
+ removeMargin(AnchorLine::HorizontalCenter);
+ removeMargin(AnchorLine::VerticalCenter);
+}
+
+QmlItemNode AnchorLine::qmlItemNode() const
+{
+ return m_qmlItemNode;
+}
+
+void QmlAnchors::fill()
+{
+ if (instanceHasAnchors())
+ removeAnchors();
+
+ qmlItemNode().modelNode().bindingProperty("anchors.fill").setExpression("parent");
+}
+
+void QmlAnchors::centerIn()
+{
+ if (instanceHasAnchors())
+ removeAnchors();
+
+ qmlItemNode().modelNode().bindingProperty("anchors.centerIn").setExpression("parent");
+}
+
+} //QmlDesigner
diff --git a/src/plugins/qmldesigner/core/model/qmlchangeset.cpp b/src/plugins/qmldesigner/core/model/qmlchangeset.cpp
new file mode 100644
index 0000000000..6637ff6351
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/qmlchangeset.cpp
@@ -0,0 +1,72 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "qmlchangeset.h"
+#include "bindingproperty.h"
+#include "variantproperty.h"
+#include "qmlmodelview.h"
+#include <metainfo.h>
+
+namespace QmlDesigner {
+
+ModelNode QmlModelStateOperation::target() const
+{
+ if (modelNode().property("target").isBindingProperty()) {
+ return modelNode().bindingProperty("target").resolveToModelNode();
+ } else {
+ return ModelNode(); //exception?
+ }
+}
+
+void QmlModelStateOperation::setTarget(const ModelNode &target)
+{
+ modelNode().bindingProperty("target").setExpression(target.id());
+}
+
+bool QmlPropertyChanges::isValid() const
+{
+ return QmlModelNodeFacade::isValid() && modelNode().metaInfo().isSubclassOf("Qt/PropertyChanges", 4, 6);
+}
+
+bool QmlModelStateOperation::isValid() const
+{
+ return QmlModelNodeFacade::isValid() && modelNode().metaInfo().isSubclassOf("Qt/QmlPropertyChanges", 4, 6);
+}
+
+void QmlPropertyChanges::removeProperty(const QString &name)
+{
+ RewriterTransaction transaction(qmlModelView()->beginRewriterTransaction());
+ if (name == "name")
+ return;
+ modelNode().removeProperty(name);
+ if (modelNode().variantProperties().isEmpty() && modelNode().bindingProperties().count() < 2)
+ modelNode().destroy();
+}
+
+} //QmlDesigner
diff --git a/src/plugins/qmldesigner/core/model/qmlitemnode.cpp b/src/plugins/qmldesigner/core/model/qmlitemnode.cpp
new file mode 100644
index 0000000000..303c4ea199
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/qmlitemnode.cpp
@@ -0,0 +1,330 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "qmlitemnode.h"
+#include <metainfo.h>
+#include "qmlview.h"
+#include "qmlchangeset.h"
+#include "variantproperty.h"
+#include "nodelistproperty.h"
+#include "nodeinstance.h"
+#include "qmlanchors.h"
+#include "invalidmodelnodeexception.h"
+#include "rewritertransaction.h"
+#include "qmlmodelview.h"
+#include "mathutils.h"
+
+namespace QmlDesigner {
+
+
+bool QmlItemNode::isValid() const
+{
+ return QmlModelNodeFacade::isValid() && modelNode().metaInfo().isSubclassOf("Qt/Item", 4, 6);
+}
+
+bool QmlItemNode::isRootNode() const
+{
+ return modelNode().isValid() && modelNode().isRootNode();
+}
+
+QStringList QmlModelStateGroup::names() const
+{
+ QStringList returnList;
+
+ if (!modelNode().isValid())
+ throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ if (modelNode().property("states").isNodeListProperty()) {
+ foreach (const ModelNode &node, modelNode().nodeListProperty("states").toModelNodeList()) {
+ if (QmlModelState(node).isValid())
+ returnList.append(QmlModelState(node).name());
+ }
+ }
+ return returnList;
+}
+
+/**
+ \brief Returns list of states (without 'base state').
+ The list contains all states defined by this item.
+ */
+QmlModelStateGroup QmlItemNode::states() const
+{
+ if (isValid())
+ return QmlModelStateGroup(modelNode());
+ else
+ return QmlModelStateGroup();
+}
+
+QList<QmlItemNode> QmlItemNode::children() const
+{
+ QList<QmlItemNode> returnList;
+
+ if (isValid()) {
+
+ QList<ModelNode> modelNodeList;
+
+ if (modelNode().hasProperty("children")) {
+ Q_ASSERT(modelNode().property("children").isNodeListProperty());
+ modelNodeList.append(modelNode().nodeListProperty("children").toModelNodeList());
+ }
+
+ if (modelNode().hasProperty("data")) {
+ Q_ASSERT(modelNode().property("data").isNodeListProperty());
+ modelNodeList.append(modelNode().nodeListProperty("data").toModelNodeList());
+ }
+
+ foreach (const ModelNode &modelNode, modelNodeList) {
+ if (QmlItemNode(modelNode).isValid()) //if ModelNode is FxItem
+ returnList.append(modelNode);
+ }
+ }
+ return returnList;
+}
+
+QList<QmlObjectNode> QmlItemNode::resources() const
+{
+ QList<QmlObjectNode> returnList;
+
+ if (isValid()) {
+ QList<ModelNode> modelNodeList;
+ if (modelNode().hasProperty("resources")) {
+ Q_ASSERT(modelNode().property("resources").isNodeListProperty());
+ modelNodeList.append(modelNode().nodeListProperty("resources").toModelNodeList());
+ }
+
+ if (modelNode().hasProperty("data")) {
+ Q_ASSERT(modelNode().property("data").isNodeListProperty());
+ modelNodeList.append(modelNode().nodeListProperty("data").toModelNodeList());
+ }
+
+ foreach (const ModelNode &node, modelNodeList) {
+ if (!QmlItemNode(node).isValid()) //if ModelNode is no FxItem
+ returnList.append(node);
+ }
+ }
+ return returnList;
+}
+
+QmlAnchors QmlItemNode::anchors() const
+{
+ return QmlAnchors(*this);
+}
+
+bool QmlItemNode::hasChildren() const
+{
+ return !children().isEmpty();
+}
+
+bool QmlItemNode::hasResources() const
+{
+ return !resources().isEmpty();
+}
+
+bool QmlItemNode::instanceHasAnchors() const
+{
+ return anchors().instanceHasAnchors();
+}
+
+bool QmlItemNode::hasShowContent() const
+{
+ return nodeInstance().hasContent();
+}
+
+bool QmlItemNode::canReparent() const
+{
+ return QmlObjectNode::canReparent() && !anchors().instanceHasAnchors() && !instanceIsAnchoredBy();
+}
+
+bool QmlItemNode::instanceIsAnchoredBy() const
+{
+ return nodeInstance().isAnchoredBy();
+}
+
+QRectF QmlItemNode::instanceBoundingRect() const
+{
+ return nodeInstance().boundingRect();
+}
+
+QTransform QmlItemNode::instanceTransform() const
+{
+ return nodeInstance().transform();
+}
+
+QTransform QmlItemNode::instanceSceneTransform() const
+{
+ return nodeInstance().sceneTransform();
+}
+
+QPointF QmlItemNode::instancePosition() const
+{
+ return nodeInstance().position();
+}
+
+QSizeF QmlItemNode::instanceSize() const
+{
+ return nodeInstance().size();
+}
+
+void QmlItemNode::paintInstance(QPainter *painter) const
+{
+ if (nodeInstance().isValid())
+ nodeInstance().paint(painter);
+}
+
+void QmlItemNode::setSize(const QSizeF &size)
+{
+ RewriterTransaction transaction = qmlModelView()->beginRewriterTransaction();
+ setVariantProperty("width", round(size.width(), 4));
+ setVariantProperty("height", round(size.height(), 4));
+}
+
+void QmlItemNode::setPosition(const QPointF &position)
+{
+ RewriterTransaction transaction = qmlModelView()->beginRewriterTransaction();
+ setVariantProperty("x", round(position.x(), 4));
+ setVariantProperty("y", round(position.y(), 4));
+}
+
+void QmlItemNode::selectNode()
+{
+ modelNode().selectNode();
+}
+
+void QmlItemNode::deselectNode()
+{
+ modelNode().deselectNode();
+}
+
+bool QmlItemNode::isSelected() const
+{
+ return modelNode().isSelected();
+}
+
+QList<QmlModelState> QmlModelStateGroup::allStates() const
+{
+ QList<QmlModelState> returnList;
+
+ if (!modelNode().isValid())
+ throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ if (modelNode().property("states").isNodeListProperty()) {
+ foreach (const ModelNode &node, modelNode().nodeListProperty("states").toModelNodeList()) {
+ if (QmlModelState(node).isValid())
+ returnList.append(QmlModelState(node));
+ }
+ }
+ return returnList;
+}
+
+QString QmlItemNode::simplfiedTypeName() const
+{
+ return modelNode().simplifiedTypeName();
+}
+
+uint qHash(const QmlItemNode &node)
+{
+ return qHash(node.modelNode());
+}
+
+QmlModelState QmlModelStateGroup::addState(const QString &name)
+{
+ if (!modelNode().isValid())
+ throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+
+ PropertyListType propertyList;
+ propertyList.append(qMakePair(QString("name"), QVariant(name)));
+
+ ModelNode newState(modelNode().addChildNode("Qt/State", 4, 6, "states", propertyList));
+
+ return newState;
+}
+
+void QmlModelStateGroup::removeState(const QString &name)
+{
+ if (!modelNode().isValid())
+ throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ if (state(name).isValid())
+ state(name).modelNode().destroy();
+}
+
+QmlModelState QmlModelStateGroup::state(const QString &name) const
+{
+ if (!modelNode().isValid())
+ throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ if (modelNode().property("states").isNodeListProperty()) {
+ foreach (const ModelNode &node, modelNode().nodeListProperty("states").toModelNodeList()) {
+ if (QmlModelState(node).name() == name)
+ return node;
+ }
+ }
+ return QmlModelState();
+}
+
+QList<ModelNode> toModelNodeList(const QList<QmlItemNode> &qmlItemNodeList)
+{
+ QList<ModelNode> modelNodeList;
+
+ foreach (const QmlItemNode &qmlItemNode, qmlItemNodeList)
+ modelNodeList.append(qmlItemNode.modelNode());
+
+ return modelNodeList;
+}
+
+QList<QmlItemNode> toQmlItemNodeList(const QList<ModelNode> &modelNodeList)
+{
+ QList<QmlItemNode> qmlItemNodeList;
+
+ foreach (const ModelNode &modelNode, modelNodeList) {
+ QmlItemNode itemNode(modelNode);
+ if (itemNode.isValid())
+ qmlItemNodeList.append(itemNode);
+ }
+
+ return qmlItemNodeList;
+}
+
+const QList<QmlItemNode> QmlItemNode::allDirectSubModelNodes() const
+{
+ return toQmlItemNodeList(modelNode().allDirectSubModelNodes());
+}
+
+const QList<QmlItemNode> QmlItemNode::allSubModelNodes() const
+{
+ return toQmlItemNodeList(modelNode().allSubModelNodes());
+}
+
+bool QmlItemNode::hasAnySubModelNodes() const
+{
+ return modelNode().hasAnySubModelNodes();
+}
+
+} //QmlDesigner
diff --git a/src/plugins/qmldesigner/core/model/qmlmodelnodefacade.cpp b/src/plugins/qmldesigner/core/model/qmlmodelnodefacade.cpp
new file mode 100644
index 0000000000..63e774723d
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/qmlmodelnodefacade.cpp
@@ -0,0 +1,59 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "qmlmodelnodefacade.h"
+#include "qmlmodelview.h"
+#include <QtDebug>
+namespace QmlDesigner {
+
+QmlModelNodeFacade::QmlModelNodeFacade() : m_modelNode(ModelNode())
+{}
+
+
+QmlModelNodeFacade::QmlModelNodeFacade(const ModelNode &modelNode) : m_modelNode(modelNode)
+{}
+
+QmlModelNodeFacade::~QmlModelNodeFacade()
+{}
+
+bool QmlModelNodeFacade::isValid() const
+{
+ return modelNode().isValid() && qmlModelView() && qmlModelView()->hasInstanceForModelNode(modelNode()) && qmlModelView()->instanceForModelNode(modelNode()).isValid();
+}
+
+QmlModelView* QmlModelNodeFacade::qmlModelView() const
+{
+ return modelNode().view()->toQmlModelView();
+}
+
+bool QmlModelNodeFacade::isRootNode() const
+{
+ return modelNode().isRootNode();
+}
+} //QmlDesigner
diff --git a/src/plugins/qmldesigner/core/model/qmlmodelview.cpp b/src/plugins/qmldesigner/core/model/qmlmodelview.cpp
new file mode 100644
index 0000000000..d8103a8a5c
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/qmlmodelview.cpp
@@ -0,0 +1,321 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "qmlmodelview.h"
+#include "qmlobjectnode.h"
+#include "qmlitemnode.h"
+#include "itemlibraryinfo.h"
+#include "modelutilities.h"
+#include "mathutils.h"
+#include <QDir>
+#include <QFileInfo>
+#include <QDebug>
+
+namespace QmlDesigner {
+
+QmlModelView::QmlModelView(QObject *parent)
+ : ForwardView<NodeInstanceView>(parent)
+{
+ appendView(new NodeInstanceView(this));
+ connect(nodeInstanceView(), SIGNAL(transformPropertyChanged(NodeInstance)), SLOT(notifyTransformChanged(NodeInstance)));
+ connect(nodeInstanceView(), SIGNAL(parentPropertyChanged(NodeInstance)), SLOT(notifyParentChanged(NodeInstance)));
+ connect(nodeInstanceView(), SIGNAL(otherPropertyChanged(NodeInstance)), SLOT(notifyOtherPropertyChanged(NodeInstance)));
+ connect(nodeInstanceView(), SIGNAL(updateItem(NodeInstance)), SLOT(notifyUpdateItem(NodeInstance)));
+}
+
+void QmlModelView::setCurrentState(const QmlModelState &state)
+{
+ if (m_state == state)
+ return;
+ QmlModelState oldState = m_state;
+ emitCustomNotification("__state changed__", QList<ModelNode>() << state.modelNode());
+}
+
+QmlModelState QmlModelView::currentState() const
+{
+ return m_state;
+}
+
+QmlModelState QmlModelView::baseState() const
+{
+ return QmlModelState::createBaseState(this);
+}
+
+QmlObjectNode QmlModelView::createQmlObjectNode(const QString &typeString,
+ int majorVersion,
+ int minorVersion,
+ const PropertyListType &propertyList)
+{
+ return QmlObjectNode(createModelNode(typeString, majorVersion, minorVersion, propertyList));
+}
+
+QmlItemNode QmlModelView::createQmlItemNode(const QString &typeString,
+ int majorVersion,
+ int minorVersion,
+ const PropertyListType &propertyList)
+{
+ return createQmlObjectNode(typeString, majorVersion, minorVersion, propertyList).toQmlItemNode();
+}
+
+QmlItemNode QmlModelView::createQmlItemNodeFromImage(const QString &imageName, const QPointF &position, QmlItemNode parentNode)
+{
+ if (!parentNode.isValid())
+ parentNode = rootQmlItemNode();
+
+ if (!parentNode.isValid())
+ return QmlItemNode();
+
+ QmlItemNode newNode;
+ RewriterTransaction transaction = beginRewriterTransaction();
+ {
+ QList<QPair<QString, QVariant> > propertyPairList;
+ propertyPairList.append(qMakePair(QString("x"), QVariant( round(position.x(), 4))));
+ propertyPairList.append(qMakePair(QString("y"), QVariant( round(position.y(), 4))));
+
+ QString relativeImageName = imageName;
+
+ //use relative path
+ if (QFileInfo(model()->fileUrl().toLocalFile()).exists()) {
+ QDir fileDir(QFileInfo(model()->fileUrl().toLocalFile()).absolutePath());
+ relativeImageName = fileDir.relativeFilePath(imageName);
+ }
+
+ propertyPairList.append(qMakePair(QString("source"), QVariant(relativeImageName)));
+ newNode = createQmlItemNode("Qt/Image",4, 6, propertyPairList);
+ parentNode.nodeAbstractProperty("data").reparentHere(newNode);
+
+ Q_ASSERT(newNode.isValid());
+
+ QString id;
+ int i = 1;
+ QString name("image");
+ name.replace(" ", "");
+ do {
+ id = name + QString::number(i);
+ i++;
+ } while (hasId(id)); //If the name already exists count upwards
+
+ newNode.setId(id);
+
+ Q_ASSERT(newNode.isValid());
+ }
+
+ Q_ASSERT(newNode.isValid());
+
+ return newNode;
+}
+
+QmlItemNode QmlModelView::createQmlItemNode(const ItemLibraryInfo &itemLibraryRepresentation, const QPointF &position, QmlItemNode parentNode)
+{
+ if (!parentNode.isValid())
+ parentNode = rootQmlItemNode();
+
+ Q_ASSERT(parentNode.isValid());
+
+
+ QmlItemNode newNode;
+ RewriterTransaction transaction = beginRewriterTransaction();
+ {
+ QList<QPair<QString, QVariant> > propertyPairList;
+ propertyPairList.append(qMakePair(QString("x"), QVariant(round(position.x(), 4))));
+ propertyPairList.append(qMakePair(QString("y"), QVariant(round(position.y(), 4))));
+
+ foreach (const PropertyContainer &property, itemLibraryRepresentation.properties())
+ propertyPairList.append(qMakePair(property.name(), property.value()));
+
+ qDebug() << itemLibraryRepresentation.typeName();
+
+ newNode = createQmlItemNode(itemLibraryRepresentation.typeName(), itemLibraryRepresentation.majorVersion(), itemLibraryRepresentation.minorVersion(), propertyPairList);
+ parentNode.nodeAbstractProperty("data").reparentHere(newNode);
+
+ Q_ASSERT(newNode.isValid());
+
+ QString id;
+ int i = 1;
+ QString name(itemLibraryRepresentation.name());
+ name.replace(" ", "");
+ do {
+ id = name + QString::number(i);
+ i++;
+ } while (hasId(id)); //If the name already exists count upwards
+
+ newNode.setId(id);
+
+ Q_ASSERT(newNode.isValid());
+ }
+
+ Q_ASSERT(newNode.isValid());
+
+ return newNode;
+}
+
+QmlObjectNode QmlModelView::rootQmlObjectNode() const
+{
+ return QmlObjectNode(rootModelNode());
+}
+
+QmlItemNode QmlModelView::rootQmlItemNode() const
+{
+ return rootQmlObjectNode().toQmlItemNode();
+}
+
+void QmlModelView::setSelectedQmlObjectNodes(const QList<QmlObjectNode> &selectedNodeList)
+{
+ setSelectedModelNodes(QmlDesigner::toModelNodeList(selectedNodeList));
+}
+
+void QmlModelView::selectQmlObjectNode(const QmlObjectNode &node)
+{
+ selectModelNode(node.modelNode());
+}
+
+void QmlModelView::deselectQmlObjectNode(const QmlObjectNode &node)
+{
+ deselectModelNode(node.modelNode());
+}
+
+QList<QmlObjectNode> QmlModelView::selectedQmlObjectNodes() const
+{
+ return toQmlObjectNodeList(selectedModelNodes());
+}
+
+QList<QmlItemNode> QmlModelView::selectedQmlItemNodes() const
+{
+ return toQmlItemNodeList(selectedModelNodes());
+}
+
+void QmlModelView::setSelectedQmlItemNodes(const QList<QmlItemNode> &selectedNodeList)
+{
+ return setSelectedModelNodes(QmlDesigner::toModelNodeList(selectedNodeList));
+}
+
+QmlObjectNode QmlModelView::fxObjectNodeForId(const QString &id)
+{
+ return QmlObjectNode(modelNodeForId(id));
+}
+
+
+void QmlModelView::notifyTransformChanged(const NodeInstance &nodeInstance)
+{
+ transformChanged(QmlObjectNode(ModelNode(nodeInstance.modelNode(), this)));
+}
+
+void QmlModelView::notifyParentChanged(const NodeInstance &nodeInstance)
+{
+ parentChanged(QmlObjectNode(ModelNode(nodeInstance.modelNode(), this)));
+}
+
+void QmlModelView::notifyOtherPropertyChanged(const NodeInstance &nodeInstance)
+{
+ otherPropertyChanged(QmlObjectNode(ModelNode(nodeInstance.modelNode(), this)));
+}
+
+void QmlModelView::notifyUpdateItem(const NodeInstance &nodeInstance)
+{
+ updateItem(QmlObjectNode(ModelNode(nodeInstance.modelNode(), this)));
+}
+
+void QmlModelView::customNotification(const AbstractView * /* view */, const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> & /* data */)
+{
+ if (identifier == "__state changed__") {
+ QmlModelState state(nodeList.first());
+ if (state.isValid())
+ stateChanged(state, currentState());
+ else
+ stateChanged(baseState(), currentState());
+ }
+}
+
+NodeInstance QmlModelView::instanceForModelNode(const ModelNode &modelNode)
+{
+ return nodeInstanceView()->instanceForNode(modelNode);
+}
+
+bool QmlModelView::hasInstanceForModelNode(const ModelNode &modelNode)
+{
+ return nodeInstanceView()->hasInstanceForNode(modelNode);
+}
+
+NodeInstanceView *QmlModelView::nodeInstanceView() const
+{
+ return firstView();
+}
+
+void QmlModelView::modelAttached(Model *model)
+{
+ m_state = QmlModelState();
+ ForwardView<NodeInstanceView>::modelAttached(model);
+ m_state = baseState();
+ Q_ASSERT(m_state.isBaseState());
+}
+
+void QmlModelView::modelAboutToBeDetached(Model *model)
+{
+ ForwardView<NodeInstanceView>::modelAboutToBeDetached(model);
+ m_state = QmlModelState();
+}
+
+void QmlModelView::transformChanged(const QmlObjectNode &/*qmlObjectNode*/)
+{
+}
+
+void QmlModelView::parentChanged(const QmlObjectNode &/*qmlObjectNode*/)
+{
+
+}
+
+void QmlModelView::otherPropertyChanged(const QmlObjectNode &/*qmlObjectNode*/)
+{
+
+}
+
+void QmlModelView::updateItem(const QmlObjectNode &/*qmlObjectNode*/)
+{
+
+}
+
+void QmlModelView::stateChanged(const QmlModelState &newQmlModelState, const QmlModelState &oldQmlModelState)
+{
+ m_state = newQmlModelState;
+ if (newQmlModelState.isValid()) {
+ NodeInstance newStateInstance = instanceForModelNode(newQmlModelState.modelNode());
+ Q_ASSERT(newStateInstance.isValid());
+ if (!newQmlModelState.isBaseState())
+ newStateInstance.setPropertyVariant("__activateState", true);
+ }
+
+ if (oldQmlModelState.isValid()) {
+ NodeInstance oldStateInstance = instanceForModelNode(oldQmlModelState.modelNode());
+ Q_ASSERT(oldStateInstance.isValid());
+ if (!oldQmlModelState.isBaseState())
+ oldStateInstance.setPropertyVariant("__activateState", false);
+ }
+}
+
+} //QmlDesigner
diff --git a/src/plugins/qmldesigner/core/model/qmlobjectnode.cpp b/src/plugins/qmldesigner/core/model/qmlobjectnode.cpp
new file mode 100644
index 0000000000..f2a25cca35
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/qmlobjectnode.cpp
@@ -0,0 +1,401 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "qmlobjectnode.h"
+#include "qmlitemnode.h"
+#include "qmlitemnode.h"
+#include "qmlstate.h"
+#include "variantproperty.h"
+#include "nodeproperty.h"
+#include <invalidmodelnodeexception.h>
+#include "qmlmodelview.h"
+#include "nodeinstanceview.h"
+#include "nodeinstance.h"
+
+namespace QmlDesigner {
+
+void QmlObjectNode::setVariantProperty(const QString &name, const QVariant &value)
+{
+ if (!isValid())
+ throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ if (isInBaseState()) {
+ modelNode().variantProperty(name) = value; //basestate
+ } else {
+ modelNode().validId();
+
+ QmlPropertyChanges changeSet(currentState().propertyChanges(modelNode()));
+ Q_ASSERT(changeSet.isValid());
+ changeSet.modelNode().variantProperty(name) = value;
+ }
+}
+
+void QmlObjectNode::setBindingProperty(const QString &name, const QString &expression)
+{
+ if (!isValid())
+ throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ if (isInBaseState()) {
+ modelNode().bindingProperty(name) = expression; //basestate
+ } else {
+ QmlPropertyChanges changeSet(currentState().propertyChanges(modelNode()));
+ Q_ASSERT(changeSet.isValid());
+ changeSet.modelNode().bindingProperty(name) = expression;
+ }
+}
+
+QmlModelState QmlObjectNode::currentState() const
+{
+ if (isValid())
+ return qmlModelView()->currentState();
+ else
+ return QmlModelState();
+}
+
+bool QmlObjectNode::isRootModelNode() const
+{
+ return modelNode().isRootNode();
+}
+
+
+/*! \brief returns the value of a property based on an actual instance
+The return value is not the value in the model, but the value of a real
+instanciated instance of this object.
+\return the value of this property based on the instance
+
+*/
+QVariant QmlObjectNode::instanceValue(const QString &name) const
+{
+ Q_ASSERT(qmlModelView()->hasInstanceForModelNode(modelNode()));
+ return qmlModelView()->instanceForModelNode(modelNode()).property(name);
+}
+
+
+bool QmlObjectNode::hasProperty(const QString &name) const
+{
+ if (!isValid())
+ throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ return modelNode().hasProperty(name);
+}
+
+NodeAbstractProperty QmlObjectNode::nodeAbstractProperty(const QString &name) const
+{
+ return modelNode().nodeAbstractProperty(name);
+}
+
+NodeProperty QmlObjectNode::nodeProperty(const QString &name) const
+{
+ return modelNode().nodeProperty(name);
+}
+
+NodeListProperty QmlObjectNode::nodeListProperty(const QString &name) const
+{
+ return modelNode().nodeListProperty(name);
+}
+
+bool QmlObjectNode::propertyAffectedByCurrentState(const QString &name) const
+{
+ if (!isValid())
+ throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ if (currentState().isBaseState())
+ return modelNode().hasProperty(name);
+
+ if (!currentState().hasPropertyChanges(modelNode()))
+ return false;
+
+ return currentState().propertyChanges(modelNode()).modelNode().hasProperty(name);
+}
+
+QVariant QmlObjectNode::modelValue(const QString &name) const
+{
+ if (!isValid())
+ throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ if (currentState().isBaseState())
+ return modelNode().variantProperty(name).value();
+
+ if (!currentState().hasPropertyChanges(modelNode()))
+ return modelNode().variantProperty(name).value();
+
+ QmlPropertyChanges propertyChanges(currentState().propertyChanges(modelNode()));
+
+ if (!propertyChanges.modelNode().hasProperty(name))
+ return modelNode().variantProperty(name).value();
+
+ return propertyChanges.modelNode().variantProperty(name).value();
+}
+
+/*! \brief returns if ObjectNode is the BaseState
+
+\return true if the ObjectNode is in the BaseState
+
+*/
+bool QmlObjectNode::isInBaseState() const
+{
+ return currentState().isBaseState();
+}
+
+bool QmlObjectNode::canReparent() const
+{
+ return isInBaseState();
+}
+
+QmlPropertyChanges QmlObjectNode::propertyChangeForCurrentState() const
+{
+ if (!isValid())
+ throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ if (currentState().isBaseState())
+ return QmlPropertyChanges();
+
+ if (!currentState().hasPropertyChanges(modelNode()))
+ return QmlPropertyChanges();
+
+ return currentState().propertyChanges(modelNode());
+}
+
+static void removeStateOperationsForChildren(const QmlObjectNode &node)
+{
+ if (node.isValid()) {
+ foreach (QmlModelStateOperation stateOperation, node.allAffectingStatesOperations()) {
+ stateOperation.modelNode().destroy(); //remove of belonging StatesOperations
+ }
+
+ foreach (const QmlObjectNode &childNode, node.modelNode().allDirectSubModelNodes()) {
+ removeStateOperationsForChildren(childNode);
+ }
+ }
+}
+
+
+/*! \brief Deletes this objects ModeNode and its dependencies from the model
+Every thing that belongs to this Object, the ModelNode and ChangeOperations
+are deleted from the model.
+
+*/
+void QmlObjectNode::destroy()
+{
+ if (!isValid())
+ throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ foreach (QmlModelStateOperation stateOperation, allAffectingStatesOperations()) {
+ stateOperation.modelNode().destroy(); //remove of belonging StatesOperations
+ }
+ removeStateOperationsForChildren(modelNode());
+ modelNode().destroy();
+}
+
+/*! \brief Returns a list of all states that are affecting this object.
+
+\return list of states affecting this object
+*/
+
+QList<QmlModelState> QmlObjectNode::allAffectingStates() const
+{
+ if (!isValid())
+ throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ QList<QmlModelState> returnList;
+
+ foreach (const QmlModelState &state, allDefinedStates()) {
+ if (state.affectsModelNode(modelNode()))
+ returnList.append(state);
+ }
+ return returnList;
+}
+
+/*! \brief Returns a list of all state operations that are affecting this object.
+
+\return list of state operations affecting this object
+*/
+
+QList<QmlModelStateOperation> QmlObjectNode::allAffectingStatesOperations() const
+{
+ if (!isValid())
+ throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ QList<QmlModelStateOperation> returnList;
+ foreach (const QmlModelState &state, allDefinedStates()) {
+ if (state.affectsModelNode(modelNode()))
+ returnList.append(state.stateOperations(modelNode()));
+ }
+
+ return returnList;
+}
+
+static QList<QmlItemNode> allFxItemsRecursive(const QmlItemNode &fxNode)
+{
+ QList<QmlItemNode> returnList;
+
+ if (fxNode.isValid()) {
+ returnList.append(fxNode);
+ QList<QmlItemNode> allChildNodes;
+ foreach (const ModelNode &node, fxNode.modelNode().allDirectSubModelNodes()) {
+ if (QmlItemNode(node).isValid())
+ allChildNodes.append(node);
+ }
+ foreach (const QmlItemNode &node, allChildNodes) {
+ returnList.append(allFxItemsRecursive(node));
+ }
+ }
+ return returnList;
+}
+
+QList<QmlModelState> QmlObjectNode::allDefinedStates() const
+{
+ if (!isValid())
+ throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ QList<QmlModelState> returnList;
+
+ QList<QmlItemNode> allFxItems;
+
+ QmlItemNode rootNode(qmlModelView()->rootModelNode());
+
+ if (rootNode.isValid())
+ allFxItems.append(allFxItemsRecursive(rootNode));
+
+ foreach (const QmlItemNode &item, allFxItems) {
+ returnList.append(item.states().allStates());
+ }
+
+ return returnList;
+}
+
+
+/*! \brief Removes a variant property of this object from the model
+
+*/
+
+void QmlObjectNode::removeVariantProperty(const QString &name)
+{
+ if (!isValid())
+ throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ if (isInBaseState()) {
+ modelNode().removeProperty(name); //basestate
+ } else {
+ QmlPropertyChanges changeSet(currentState().propertyChanges(modelNode()));
+ Q_ASSERT(changeSet.isValid());
+ changeSet.removeProperty(name);
+ }
+}
+
+QList<ModelNode> toModelNodeList(const QList<QmlObjectNode> &fxObjectNodeList)
+{
+ QList<ModelNode> modelNodeList;
+
+ foreach(const QmlObjectNode &fxObjectNode, fxObjectNodeList)
+ modelNodeList.append(fxObjectNode.modelNode());
+
+ return modelNodeList;
+}
+
+QList<QmlObjectNode> toQmlObjectNodeList(const QList<ModelNode> &modelNodeList)
+{
+ QList<QmlObjectNode> qmlObjectNodeList;
+
+ foreach(const ModelNode &modelNode, modelNodeList) {
+ QmlObjectNode objectNode(modelNode);
+ if (objectNode.isValid())
+ qmlObjectNodeList.append(objectNode);
+ }
+
+ return qmlObjectNodeList;
+}
+
+bool QmlObjectNode::isAncestorOf(const QmlObjectNode &objectNode) const
+{
+ return modelNode().isAncestorOf(objectNode.modelNode());
+}
+
+NodeInstance QmlObjectNode::nodeInstance() const
+{
+ return qmlModelView()->nodeInstanceView()->instanceForNode(modelNode());
+}
+
+QmlObjectNode QmlObjectNode::nodeForInstance(const NodeInstance &instance) const
+{
+ return QmlObjectNode(ModelNode(instance.modelNode(), qmlModelView()));
+}
+
+bool QmlObjectNode::hasNodeParent() const
+{
+ return modelNode().hasParentProperty();
+}
+
+bool QmlObjectNode::hasInstanceParent() const
+{
+ return nodeInstance().hasParent();
+}
+
+
+void QmlObjectNode::setParentProperty(const NodeAbstractProperty &parentProeprty)
+{
+ return modelNode().setParentProperty(parentProeprty);
+}
+
+QmlObjectNode QmlObjectNode::instanceParent() const
+{
+ return nodeForInstance(nodeInstance().parent());
+}
+
+void QmlObjectNode::setId(const QString &id)
+{
+ modelNode().setId(id);
+}
+
+QString QmlObjectNode::id() const
+{
+ return modelNode().id();
+}
+
+QString QmlObjectNode::validId()
+{
+ return modelNode().validId();
+}
+
+void QmlObjectNode::setParent(QmlObjectNode newParent)
+{
+ newParent.modelNode().nodeListProperty("data").reparentHere(modelNode());
+ //TODO use metasystem for default Property
+}
+
+QmlItemNode QmlObjectNode::toQmlItemNode() const
+{
+ return QmlItemNode(modelNode());
+}
+
+uint qHash(const QmlObjectNode &node)
+{
+ return qHash(node.modelNode());
+}
+} //QmlDesigner
diff --git a/src/plugins/qmldesigner/core/model/qmlstate.cpp b/src/plugins/qmldesigner/core/model/qmlstate.cpp
new file mode 100644
index 0000000000..774fc5ab70
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/qmlstate.cpp
@@ -0,0 +1,288 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "qmlstate.h"
+#include "qmlmodelview.h"
+#include <nodelistproperty.h>
+#include <variantproperty.h>
+#include <metainfo.h>
+#include <invalidmodelnodeexception.h>
+
+
+namespace QmlDesigner {
+
+QmlModelState::QmlModelState()
+ : QmlModelNodeFacade(),
+ m_isBaseState(false)
+{
+}
+
+QmlModelState::QmlModelState(const ModelNode &modelNode)
+ : QmlModelNodeFacade(modelNode),
+ m_isBaseState(false)
+{
+}
+
+QmlPropertyChanges QmlModelState::propertyChanges(const ModelNode &node)
+{
+ //### exception if not valid
+
+ if (isBaseState())
+ return QmlPropertyChanges();
+
+ addChangeSetIfNotExists(node);
+ foreach (const ModelNode &childNode, modelNode().nodeListProperty("changes").toModelNodeList()) {
+ //### exception if not valid QmlModelStateOperation
+ if (QmlPropertyChanges(childNode).target().isValid() && QmlPropertyChanges(childNode).target() == node)
+ return QmlPropertyChanges(childNode); //### exception if not valid(childNode);
+ }
+ return QmlPropertyChanges(); //not found
+}
+
+QList<QmlModelStateOperation> QmlModelState::stateOperations(const ModelNode &node) const
+{
+ QList<QmlModelStateOperation> returnList;
+ //### exception if not valid
+
+ if (isBaseState())
+ return returnList;
+
+ if (!modelNode().hasProperty("changes"))
+ return returnList;
+
+ Q_ASSERT(modelNode().property("changes").isNodeListProperty());
+
+ foreach (const ModelNode &childNode, modelNode().nodeListProperty("changes").toModelNodeList()) {
+ //### exception if not valid QmlModelStateOperation
+ if (QmlModelStateOperation(childNode).target() == node)
+ returnList.append(QmlModelStateOperation(childNode)); //### exception if not valid(childNode);
+ }
+ return returnList; //not found
+}
+
+QList<QmlPropertyChanges> QmlModelState::propertyChanges() const
+{
+ //### exception if not valid
+ QList<QmlPropertyChanges> returnList;
+
+ if (isBaseState())
+ return returnList;
+
+ if (!modelNode().hasProperty("changes"))
+ return returnList;
+
+ Q_ASSERT(modelNode().property("changes").isNodeListProperty());
+
+ foreach (const ModelNode &childNode, modelNode().nodeListProperty("changes").toModelNodeList()) {
+ //### exception if not valid QmlModelStateOperation
+ if (QmlPropertyChanges(childNode).isValid())
+ returnList.append(QmlPropertyChanges(childNode));
+ }
+ return returnList;
+}
+
+
+bool QmlModelState::hasPropertyChanges(const ModelNode &node) const
+{
+ //### exception if not valid
+
+ if (isBaseState())
+ return false;
+
+ foreach(const QmlPropertyChanges &changeSet, propertyChanges()) {
+ if (changeSet.target().isValid() && changeSet.target() == node)
+ return true;
+ }
+ return false;
+}
+
+bool QmlModelState::hasStateOperation(const ModelNode &node) const
+{
+ //### exception if not valid
+
+ if (isBaseState())
+ return false;
+
+ foreach(const QmlModelStateOperation &stateOperation, stateOperations()) {
+ if (stateOperation.target() == node)
+ return true;
+ }
+ return false;
+}
+
+QList<QmlModelStateOperation> QmlModelState::stateOperations() const
+{
+ //### exception if not valid
+ QList<QmlModelStateOperation> returnList;
+
+ if (isBaseState())
+ return returnList;
+
+ if (!modelNode().hasProperty("changes"))
+ return returnList;
+
+ Q_ASSERT(modelNode().property("changes").isNodeListProperty());
+
+ foreach (const ModelNode &childNode, modelNode().nodeListProperty("changes").toModelNodeList()) {
+ //### exception if not valid QmlModelStateOperation
+ if (QmlModelStateOperation(childNode).isValid())
+ returnList.append(QmlModelStateOperation(childNode));
+ }
+ return returnList;
+}
+
+
+/*! \brief Add a ChangeSet for the specified ModelNode to this state
+ The new ChangeSet if only added if no ChangeSet for the ModelNode
+ does not exist, yet.
+*/
+
+void QmlModelState::addChangeSetIfNotExists(const ModelNode &node)
+{
+ //### exception if not valid
+
+ if (!isValid())
+ throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ if (hasPropertyChanges(node)) {
+ return; //changeSet already there
+ }
+
+ ModelNode newChangeSet(modelNode().addChildNode("Qt/PropertyChanges", 4, 6, "changes"));
+ QmlPropertyChanges(newChangeSet).setTarget(node);
+ Q_ASSERT(QmlPropertyChanges(newChangeSet).isValid());
+}
+
+void QmlModelState::removePropertyChanges(const ModelNode &node)
+{
+ //### exception if not valid
+
+ if (isBaseState())
+ return;
+
+ QmlPropertyChanges theChangeSet(propertyChanges(node));
+ if (theChangeSet.isValid())
+ theChangeSet.modelNode().destroy();
+}
+
+
+
+/*! \brief Returns if this state affects the specified ModelNode
+
+\return true if this state affects the specifigied ModelNode
+*/
+bool QmlModelState::affectsModelNode(const ModelNode &node) const
+{
+ if (isBaseState())
+ return false;
+
+ return !stateOperations(node).isEmpty();
+}
+
+QString QmlModelState::name() const
+{
+ if (isBaseState())
+ return QString("");
+
+ return modelNode().variantProperty("name").value().toString();
+}
+
+void QmlModelState::setName(const QString &name)
+{
+ if ((!isBaseState()) && (modelNode().isValid()))
+ modelNode().variantProperty("name").setValue(name);
+}
+
+bool QmlModelState::isValid() const
+{
+ return QmlModelNodeFacade::isValid() &&
+ (modelNode().metaInfo().isSubclassOf("Qt/State", 4, 6) || isBaseState());
+}
+
+/**
+ Removes state node & all subnodes.
+ */
+void QmlModelState::destroy()
+{
+ Q_ASSERT(isValid());
+ modelNode().destroy();
+}
+
+/*! \brief Returns if this state is the base state
+
+\return true if this state is the base state
+*/
+
+bool QmlModelState::isBaseState() const
+{
+ return m_isBaseState && modelNode().isRootNode();
+}
+
+QmlModelState QmlModelState::duplicate(const QString &name) const
+{
+ if (!isValid())
+ throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ QmlItemNode parentNode(modelNode().parentProperty().parentModelNode());
+ if (!parentNode.isValid())
+ throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+// QmlModelState newState(stateGroup().addState(name));
+ PropertyListType propertyList;
+ propertyList.append(qMakePair(QString("name"), QVariant(name)));
+ QmlModelState newState ( qmlModelView()->createModelNode("Qt/State", 4, 6, propertyList) );
+
+ foreach (const ModelNode &childNode, modelNode().nodeListProperty("changes").toModelNodeList()) {
+ ModelNode newModelNode(qmlModelView()->createModelNode(childNode.type(), childNode.majorVersion(), childNode.minorVersion()));
+ foreach (const BindingProperty &bindingProperty, childNode.bindingProperties())
+ newModelNode.bindingProperty(bindingProperty.name()).setExpression(bindingProperty.expression());
+ foreach (const VariantProperty &variantProperty, childNode.variantProperties())
+ newModelNode.variantProperty(variantProperty.name()) = variantProperty.value();
+ newState.modelNode().nodeListProperty("changes").reparentHere(newModelNode);
+ }
+
+ modelNode().parentProperty().reparentHere(newState);
+
+ return newState;
+}
+
+QmlModelStateGroup QmlModelState::stateGroup() const
+{
+ QmlItemNode parentNode(modelNode().parentProperty().parentModelNode());
+ return parentNode.states();
+}
+
+QmlModelState QmlModelState::createBaseState(const QmlModelView *view)
+{
+ QmlModelState fxState(view->rootModelNode());
+ fxState.m_isBaseState = true;
+ return fxState;
+}
+
+} // QmlDesigner
diff --git a/src/plugins/qmldesigner/core/model/qmltextgenerator.cpp b/src/plugins/qmldesigner/core/model/qmltextgenerator.cpp
new file mode 100644
index 0000000000..32c6c00bf2
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/qmltextgenerator.cpp
@@ -0,0 +1,178 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <QtCore/QVariant>
+
+#include "bindingproperty.h"
+#include "nodeproperty.h"
+#include "nodelistproperty.h"
+#include "qmltextgenerator.h"
+#include "variantproperty.h"
+
+using namespace QmlDesigner;
+using namespace QmlDesigner::Internal;
+
+QmlTextGenerator::QmlTextGenerator(const QStringList &propertyOrder, int indentDepth):
+ m_propertyOrder(propertyOrder),
+ m_indentDepth(indentDepth)
+{
+}
+
+QString QmlTextGenerator::toQml(const AbstractProperty &property, int indentDepth) const
+{
+ if (property.isBindingProperty()) {
+ return property.toBindingProperty().expression();
+ } else if (property.isNodeProperty()) {
+ return toQml(property.toNodeProperty().modelNode(), indentDepth);
+ } else if (property.isNodeListProperty()) {
+ const QList<ModelNode> nodes = property.toNodeListProperty().toModelNodeList();
+ if (property.isDefaultProperty()) {
+ QString result;
+ for (int i = 0; i < nodes.length(); ++i) {
+ if (i > 0)
+ result += QLatin1String("\n\n");
+ result += QString(indentDepth, QLatin1Char(' '));
+ result += toQml(nodes.at(i), indentDepth);
+ }
+ return result;
+ } else {
+ QString result = QLatin1String("[");
+ const int arrayContentDepth = indentDepth + 4;
+ const QString arrayContentIndentation(arrayContentDepth, QLatin1Char(' '));
+ for (int i = 0; i < nodes.length(); ++i) {
+ if (i > 0)
+ result += QLatin1Char(',');
+ result += QLatin1Char('\n');
+ result += arrayContentIndentation;
+ result += toQml(nodes.at(i), arrayContentDepth);
+ }
+ return result + QLatin1String("]");
+ }
+ } else if (property.isVariantProperty()) {
+ const VariantProperty variantProperty = property.toVariantProperty();
+ const QVariant value = variantProperty.value();
+ const QString stringValue = value.toString();
+
+ if (property.name() == QLatin1String("id"))
+ return stringValue;
+
+ switch (value.type()) {
+ case QVariant::Bool:
+ if (value.value<bool>())
+ return QLatin1String("true");
+ else
+ return QLatin1String("false");
+
+ case QVariant::Double:
+ case QVariant::Int:
+ case QVariant::LongLong:
+ case QVariant::UInt:
+ case QVariant::ULongLong:
+ return stringValue;
+
+ default:
+ return QString(QLatin1String("\"%1\"")).arg(stringValue);
+ }
+ } else {
+ Q_ASSERT("Unknown property type");
+ return QString::null;
+ }
+}
+
+QString QmlTextGenerator::toQml(const ModelNode &node, int indentDepth) const
+{
+ QString type = node.type();
+ int lastSlashIndex = type.lastIndexOf('/');
+ if (lastSlashIndex != -1)
+ type = type.mid(lastSlashIndex + 1);
+
+ QString result = type;
+ result += QLatin1String(" {\n");
+
+ const int propertyIndentDepth = indentDepth + 4;
+
+ const QString properties = propertiesToQml(node, propertyIndentDepth);
+
+ return result + properties + QString(indentDepth, QLatin1Char(' ')) + QLatin1Char('}');
+}
+
+QString QmlTextGenerator::propertiesToQml(const ModelNode &node, int indentDepth) const
+{
+ QString topPart;
+ QString bottomPart;
+
+ QStringList nodePropertyNames = node.propertyNames();
+ bool addToTop = true;
+
+ foreach (const QString &propertyName, m_propertyOrder) {
+ if (QLatin1String("id") == propertyName) {
+ // the model handles the id property special, so:
+ if (!node.id().isEmpty()) {
+ QString idLine(indentDepth, QLatin1Char(' '));
+ idLine += QLatin1String("id: ");
+ idLine += node.id();
+ idLine += QLatin1Char('\n');
+
+ if (addToTop)
+ topPart.append(idLine);
+ else
+ bottomPart.append(idLine);
+ }
+ } else if (propertyName.isEmpty()) {
+ addToTop = false;
+ } else if (nodePropertyNames.removeAll(propertyName)) {
+ const QString newContent = propertyToQml(node.property(propertyName), indentDepth);
+
+ if (addToTop)
+ topPart.append(newContent);
+ else
+ bottomPart.append(newContent);
+ }
+ }
+
+ foreach (const QString &propertyName, nodePropertyNames) {
+ bottomPart.prepend(propertyToQml(node.property(propertyName), indentDepth));
+ }
+
+ return topPart + bottomPart;
+}
+
+QString QmlTextGenerator::propertyToQml(const AbstractProperty &property, int indentDepth) const
+{
+ QString result;
+
+ if (property.isDefaultProperty())
+ result = toQml(property, indentDepth);
+ else
+ result = QString(indentDepth, QLatin1Char(' ')) + property.name() + QLatin1String(": ") + toQml(property, indentDepth);
+
+ result += QLatin1Char('\n');
+
+ return result;
+}
diff --git a/src/plugins/qmldesigner/core/model/qmltextgenerator.h b/src/plugins/qmldesigner/core/model/qmltextgenerator.h
new file mode 100644
index 0000000000..c8a87ad486
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/qmltextgenerator.h
@@ -0,0 +1,67 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef QMLTEXTGENERATOR_H
+#define QMLTEXTGENERATOR_H
+
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+
+#include "abstractproperty.h"
+#include "modelnode.h"
+
+namespace QmlDesigner {
+namespace Internal {
+
+class QmlTextGenerator
+{
+public:
+ QmlTextGenerator(const QStringList &propertyOrder, int indentDepth = 0);
+
+ QString operator()(const AbstractProperty &property) const
+ { return toQml(property, m_indentDepth); }
+
+ QString operator()(const ModelNode &modelNode) const
+ { return toQml(modelNode, m_indentDepth); }
+
+private:
+ QString toQml(const AbstractProperty &property, int indentDepth) const;
+ QString toQml(const ModelNode &modelNode, int indentDepth) const;
+ QString propertiesToQml(const ModelNode &node, int indentDepth) const;
+ QString propertyToQml(const AbstractProperty &property, int indentDepth) const;
+
+private:
+ QStringList m_propertyOrder;
+ int m_indentDepth;
+};
+
+} // namespace Internal
+} // namespace QmlDesigner
+
+#endif // QMLTEXTGENERATOR_H
diff --git a/src/plugins/qmldesigner/core/model/rewriteaction.cpp b/src/plugins/qmldesigner/core/model/rewriteaction.cpp
new file mode 100644
index 0000000000..363995bbad
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/rewriteaction.cpp
@@ -0,0 +1,256 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <QtCore/QDebug>
+
+#include "nodeabstractproperty.h"
+#include "rewriteaction.h"
+
+using namespace QmlDesigner;
+using namespace QmlDesigner::Internal;
+using namespace QmlEditor;
+
+static inline QString toString(QmlRefactoring::PropertyType type)
+{
+ switch (type) {
+ case QmlRefactoring::ArrayBinding: return QLatin1String("array binding");
+ case QmlRefactoring::ObjectBinding: return QLatin1String("object binding");
+ case QmlRefactoring::ScriptBinding: return QLatin1String("script binding");
+ default: return QLatin1String("UNKNOWN");
+ }
+}
+
+bool AddPropertyRewriteAction::execute(QmlRefactoring &refactoring, ModelNodePositionStorage &positionStore)
+{
+ const int nodeLocation = positionStore.nodeOffset(m_property.parentModelNode());
+ bool result = false;
+
+ if (m_property.isDefaultProperty())
+ result = refactoring.addToObjectMemberList(nodeLocation, m_valueText);
+ else
+ result = refactoring.addProperty(nodeLocation, m_property.name(), m_valueText, m_propertyType);
+
+ Q_ASSERT(result);
+ return result;
+}
+
+void AddPropertyRewriteAction::dump(const QString &prefix) const
+{
+ qDebug() << qPrintable(prefix)
+ << "AddPropertyRewriteAction for property"
+ << m_property.name()
+ << "(" << qPrintable(toString(m_propertyType)) << ")"
+ ;
+}
+
+bool ChangeIdRewriteAction::execute(QmlEditor::QmlRefactoring &refactoring, ModelNodePositionStorage &positionStore)
+{
+ const int nodeLocation = positionStore.nodeOffset(m_node);
+ static const QLatin1String idPropertyName("id");
+ bool result = false;
+
+ if (m_oldId.isEmpty())
+ result = refactoring.addProperty(nodeLocation, idPropertyName, m_newId, QmlRefactoring::ScriptBinding);
+ else if (m_newId.isEmpty())
+ result = refactoring.removeProperty(nodeLocation, idPropertyName);
+ else
+ result = refactoring.changeProperty(nodeLocation, idPropertyName, m_newId, QmlRefactoring::ScriptBinding);
+
+ Q_ASSERT(result);
+ return result;
+}
+
+void ChangeIdRewriteAction::dump(const QString &prefix) const
+{
+ qDebug() << qPrintable(prefix)
+ << "ChangeIdRewriteAction"
+ ;
+}
+
+bool ChangePropertyRewriteAction::execute(QmlEditor::QmlRefactoring &refactoring, ModelNodePositionStorage &positionStore)
+{
+ const int nodeLocation = positionStore.nodeOffset(m_property.parentModelNode());
+ bool result = false;
+
+ if (m_property.isDefaultProperty())
+ result = refactoring.addToObjectMemberList(nodeLocation, m_valueText);
+ else if (m_propertyType == QmlRefactoring::ArrayBinding)
+ result = refactoring.addToArrayMemberList(nodeLocation, m_property.name(), m_valueText);
+ else
+ result = refactoring.changeProperty(nodeLocation, m_property.name(), m_valueText, m_propertyType);
+
+ Q_ASSERT(result);
+ return result;
+}
+
+void ChangePropertyRewriteAction::dump(const QString &prefix) const
+{
+ qDebug() << qPrintable(prefix)
+ << "ChangePropertyRewriteAction for property"
+ << m_property.name()
+ << "(" << qPrintable(toString(m_propertyType)) << ")"
+ << "of node"
+ << (m_property.parentModelNode().isValid() ? m_property.parentModelNode().id() : "(invalid)")
+ << "with new value"
+ << QString(m_valueText).replace('\n', "\\n")
+ << "and contained object"
+ << (m_containedModelNode.isValid() ? m_containedModelNode.id() : "(none)")
+ ;
+}
+
+bool ChangeTypeRewriteAction::execute(QmlEditor::QmlRefactoring &refactoring, ModelNodePositionStorage &positionStore)
+{
+ const int nodeLocation = positionStore.nodeOffset(m_node);
+ bool result = false;
+
+ QString newNodeType = m_node.type();
+ const int slashIdx = newNodeType.lastIndexOf('/');
+ if (slashIdx != -1)
+ newNodeType = newNodeType.mid(slashIdx + 1);
+
+ result = refactoring.changeObjectType(nodeLocation, newNodeType);
+
+ Q_ASSERT(result);
+ return result;
+}
+
+void ChangeTypeRewriteAction::dump(const QString &prefix) const
+{
+ qDebug() << qPrintable(prefix)
+ << "ChangeTypeRewriteAction"
+ ;
+}
+
+bool RemoveNodeRewriteAction::execute(QmlEditor::QmlRefactoring &refactoring, ModelNodePositionStorage &positionStore)
+{
+ const int nodeLocation = positionStore.nodeOffset(m_node);
+ bool result = false;
+
+ result = refactoring.removeObject(nodeLocation);
+
+ Q_ASSERT(result);
+ return result;
+}
+
+void RemoveNodeRewriteAction::dump(const QString &prefix) const
+{
+ qDebug() << qPrintable(prefix)
+ << "RemoveNodeRewriteAction"
+ ;
+}
+
+bool RemovePropertyRewriteAction::execute(QmlEditor::QmlRefactoring &refactoring, ModelNodePositionStorage &positionStore)
+{
+ const int nodeLocation = positionStore.nodeOffset(m_property.parentModelNode());
+ bool result = false;
+
+ result = refactoring.removeProperty(nodeLocation, m_property.name());
+
+ Q_ASSERT(result);
+ return result;
+}
+
+void RemovePropertyRewriteAction::dump(const QString &prefix) const
+{
+ qDebug() << qPrintable(prefix)
+ << "RemovePropertyRewriteAction for property"
+ << m_property.name()
+ ;
+}
+
+bool ReparentNodeRewriteAction::execute(QmlEditor::QmlRefactoring &refactoring, ModelNodePositionStorage &positionStore)
+{
+ const int nodeLocation = positionStore.nodeOffset(m_node);
+ const int targetParentObjectLocation = positionStore.nodeOffset(m_targetProperty.parentModelNode());
+ const bool isArrayBinding = m_targetProperty.isNodeListProperty();
+ bool result = false;
+
+ QString targetPropertyName;
+ if (!m_targetProperty.isDefaultProperty())
+ targetPropertyName = m_targetProperty.name();
+
+ result = refactoring.moveObject(nodeLocation, targetPropertyName, isArrayBinding, targetParentObjectLocation);
+
+ Q_ASSERT(result);
+ return result;
+}
+
+void ReparentNodeRewriteAction::dump(const QString &prefix) const
+{
+ if (m_node.isValid()) {
+ qDebug() << qPrintable(prefix)
+ << "ReparentNodeRewriteAction for node"
+ << m_node.id()
+ << "into property"
+ << m_targetProperty.name()
+ << "of node"
+ << m_targetProperty.parentModelNode().id()
+ ;
+ } else {
+ qDebug() << qPrintable(prefix)
+ << "reparentNodeRewriteAction for an invalid node"
+ ;
+ }
+}
+
+bool MoveNodeRewriteAction::execute(QmlRefactoring &refactoring,
+ ModelNodePositionStorage &positionStore)
+{
+ const int movingNodeLocation = positionStore.nodeOffset(m_movingNode);
+ const int newTrailingNodeLocation = m_newTrailingNode.isValid() ? positionStore.nodeOffset(m_newTrailingNode) : -1;
+ bool result = false;
+
+ result = refactoring.moveObjectBeforeObject(movingNodeLocation, newTrailingNodeLocation);
+
+ Q_ASSERT(result);
+ return result;
+}
+
+void MoveNodeRewriteAction::dump(const QString &prefix) const
+{
+ if (m_movingNode.isValid()) {
+ if (m_newTrailingNode.isValid())
+ qDebug() << qPrintable(prefix)
+ << "MoveNodeRewriteAction for node"
+ << m_movingNode.id()
+ << "before node"
+ << m_newTrailingNode.id()
+ ;
+ else
+ qDebug() << qPrintable(prefix)
+ << "MoveNodeRewriteAction for node"
+ << m_movingNode.id()
+ << "to the end of its containing property"
+ ;
+ } else {
+ qDebug() << qPrintable(prefix)
+ << "MoveNodeRewriteAction for an invalid node"
+ ;
+ }
+}
diff --git a/src/plugins/qmldesigner/core/model/rewriteaction.h b/src/plugins/qmldesigner/core/model/rewriteaction.h
new file mode 100644
index 0000000000..2027d5258a
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/rewriteaction.h
@@ -0,0 +1,261 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef REWRITEACTION_H
+#define REWRITEACTION_H
+
+#include "abstractproperty.h"
+#include "modelnodepositionstorage.h"
+
+#include <filemanager/qmlrefactoring.h>
+
+namespace QmlDesigner {
+namespace Internal {
+
+class AddPropertyRewriteAction;
+class ChangeIdRewriteAction;
+class ChangePropertyRewriteAction;
+class ChangeTypeRewriteAction;
+class RemoveNodeRewriteAction;
+class RemovePropertyRewriteAction;
+class ReparentNodeRewriteAction;
+class MoveNodeRewriteAction;
+
+class RewriteAction
+{
+public:
+ virtual bool execute(QmlEditor::QmlRefactoring &refactoring, ModelNodePositionStorage &positionStore) = 0;
+ virtual void dump(const QString &prefix) const = 0;
+
+ virtual AddPropertyRewriteAction const *asAddPropertyRewriteAction() const { return 0; }
+ virtual ChangeIdRewriteAction const *asChangeIdRewriteAction() const { return 0; }
+ virtual ChangePropertyRewriteAction const *asChangePropertyRewriteAction() const { return 0; }
+ virtual ChangeTypeRewriteAction const *asChangeTypeRewriteAction() const { return 0; }
+ virtual RemoveNodeRewriteAction const *asRemoveNodeRewriteAction() const { return 0; }
+ virtual RemovePropertyRewriteAction const *asRemovePropertyRewriteAction() const { return 0; }
+ virtual ReparentNodeRewriteAction const *asReparentNodeRewriteAction() const { return 0; }
+ virtual MoveNodeRewriteAction const *asMoveNodeRewriteAction() const { return 0; }
+
+protected:
+ RewriteAction()
+ {}
+
+private:
+ RewriteAction(const RewriteAction &);
+ RewriteAction &operator=(const RewriteAction&);
+};
+
+class AddPropertyRewriteAction: public RewriteAction
+{
+public:
+ AddPropertyRewriteAction(const AbstractProperty &property, const QString &valueText, QmlEditor::QmlRefactoring::PropertyType propertyType, const ModelNode &containedModelNode/* = ModelNode()*/):
+ m_property(property), m_valueText(valueText), m_propertyType(propertyType), m_containedModelNode(containedModelNode)
+ {}
+
+ virtual bool execute(QmlEditor::QmlRefactoring &refactoring, ModelNodePositionStorage &positionStore);
+ virtual void dump(const QString &prefix) const;
+
+ virtual AddPropertyRewriteAction const *asAddPropertyRewriteAction() const { return this; }
+
+ AbstractProperty property() const
+ { return m_property; }
+
+ QString valueText() const
+ { return m_valueText; }
+
+ QmlEditor::QmlRefactoring::PropertyType propertyType() const
+ { return m_propertyType; }
+
+ ModelNode containedModelNode() const
+ { return m_containedModelNode; }
+
+private:
+ AbstractProperty m_property;
+ QString m_valueText;
+ QmlEditor::QmlRefactoring::PropertyType m_propertyType;
+ ModelNode m_containedModelNode;
+};
+
+class ChangeIdRewriteAction: public RewriteAction
+{
+public:
+ ChangeIdRewriteAction(const ModelNode &node, const QString &oldId, const QString &newId):
+ m_node(node), m_oldId(oldId), m_newId(newId)
+ {}
+
+ virtual bool execute(QmlEditor::QmlRefactoring &refactoring, ModelNodePositionStorage &positionStore);
+ virtual void dump(const QString &prefix) const;
+
+ virtual ChangeIdRewriteAction const *asChangeIdRewriteAction() const { return this; }
+
+ ModelNode node() const
+ { return m_node; }
+
+private:
+ ModelNode m_node;
+ QString m_oldId;
+ QString m_newId;
+};
+
+class ChangePropertyRewriteAction: public RewriteAction
+{
+public:
+ ChangePropertyRewriteAction(const AbstractProperty &property, const QString &valueText, QmlEditor::QmlRefactoring::PropertyType propertyType, const ModelNode &containedModelNode/* = ModelNode()*/):
+ m_property(property), m_valueText(valueText), m_propertyType(propertyType), m_containedModelNode(containedModelNode)
+ {}
+
+ virtual bool execute(QmlEditor::QmlRefactoring &refactoring, ModelNodePositionStorage &positionStore);
+ virtual void dump(const QString &prefix) const;
+
+ virtual ChangePropertyRewriteAction const *asChangePropertyRewriteAction() const { return this; }
+
+ AbstractProperty property() const
+ { return m_property; }
+
+ QString valueText() const
+ { return m_valueText; }
+
+ QmlEditor::QmlRefactoring::PropertyType propertyType() const
+ { return m_propertyType; }
+
+ ModelNode containedModelNode() const
+ { return m_containedModelNode; }
+
+private:
+ AbstractProperty m_property;
+ QString m_valueText;
+ QmlEditor::QmlRefactoring::PropertyType m_propertyType;
+ ModelNode m_containedModelNode;
+};
+
+class ChangeTypeRewriteAction:public RewriteAction
+{
+public:
+ ChangeTypeRewriteAction(const ModelNode &node):
+ m_node(node)
+ {}
+
+ virtual bool execute(QmlEditor::QmlRefactoring &refactoring, ModelNodePositionStorage &positionStore);
+ virtual void dump(const QString &prefix) const;
+
+ virtual ChangeTypeRewriteAction const *asChangeTypeRewriteAction() const { return this; }
+
+ ModelNode node() const
+ { return m_node; }
+
+private:
+ ModelNode m_node;
+};
+
+class RemoveNodeRewriteAction: public RewriteAction
+{
+public:
+ RemoveNodeRewriteAction(const ModelNode &node):
+ m_node(node)
+ {}
+
+ virtual bool execute(QmlEditor::QmlRefactoring &refactoring, ModelNodePositionStorage &positionStore);
+ virtual void dump(const QString &prefix) const;
+
+ virtual RemoveNodeRewriteAction const *asRemoveNodeRewriteAction() const { return this; }
+
+ ModelNode node() const
+ { return m_node; }
+
+private:
+ ModelNode m_node;
+};
+
+class RemovePropertyRewriteAction: public RewriteAction
+{
+public:
+ RemovePropertyRewriteAction(const AbstractProperty &property):
+ m_property(property)
+ {}
+
+ virtual bool execute(QmlEditor::QmlRefactoring &refactoring, ModelNodePositionStorage &positionStore);
+ virtual void dump(const QString &prefix) const;
+
+ virtual RemovePropertyRewriteAction const *asRemovePropertyRewriteAction() const { return this; }
+
+ AbstractProperty property() const
+ { return m_property; }
+
+private:
+ AbstractProperty m_property;
+};
+
+class ReparentNodeRewriteAction: public RewriteAction
+{
+public:
+ ReparentNodeRewriteAction(const ModelNode &node, const AbstractProperty &targetProperty, QmlEditor::QmlRefactoring::PropertyType propertyType):
+ m_node(node), m_targetProperty(targetProperty), m_propertyType(propertyType)
+ {}
+
+ virtual bool execute(QmlEditor::QmlRefactoring &refactoring, ModelNodePositionStorage &positionStore);
+ virtual void dump(const QString &prefix) const;
+
+ virtual ReparentNodeRewriteAction const *asReparentNodeRewriteAction() const { return this; }
+
+ ModelNode reparentedNode() const
+ { return m_node; }
+
+ AbstractProperty targetProperty() const
+ { return m_targetProperty; }
+
+ QmlEditor::QmlRefactoring::PropertyType propertyType() const
+ { return m_propertyType; }
+
+private:
+ ModelNode m_node;
+ AbstractProperty m_targetProperty;
+ QmlEditor::QmlRefactoring::PropertyType m_propertyType;
+};
+
+class MoveNodeRewriteAction: public RewriteAction
+{
+public:
+ MoveNodeRewriteAction(const ModelNode &movingNode, const ModelNode &newTrailingNode):
+ m_movingNode(movingNode), m_newTrailingNode(newTrailingNode)
+ {}
+
+ virtual bool execute(QmlEditor::QmlRefactoring &refactoring, ModelNodePositionStorage &positionStore);
+ virtual void dump(const QString &prefix) const;
+
+ virtual MoveNodeRewriteAction const *asMoveNodeRewriteAction() const { return this; }
+
+private:
+ ModelNode m_movingNode;
+ ModelNode m_newTrailingNode;
+};
+
+} // namespace Internal
+} // namespace QmlDesigner
+
+#endif // REWRITEACTION_H
diff --git a/src/plugins/qmldesigner/core/model/rewriteactioncompressor.cpp b/src/plugins/qmldesigner/core/model/rewriteactioncompressor.cpp
new file mode 100644
index 0000000000..6ccda0ff2c
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/rewriteactioncompressor.cpp
@@ -0,0 +1,305 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <QtCore/QSet>
+
+#include "modelnode.h"
+#include "nodelistproperty.h"
+#include "nodeproperty.h"
+#include "qmltextgenerator.h"
+#include "rewriteactioncompressor.h"
+
+using namespace QmlDesigner;
+using namespace QmlDesigner::Internal;
+
+static bool nodeOrParentInSet(const ModelNode &node, const QSet<ModelNode> &nodeSet)
+{
+ ModelNode n = node;
+ while (n.isValid()) {
+ if (nodeSet.contains(n))
+ return true;
+
+ if (!n.hasParentProperty())
+ return false;
+
+ n = n.parentProperty().parentModelNode();
+ }
+
+ return false;
+}
+
+void RewriteActionCompressor::operator()(QList<RewriteAction *> &actions) const
+{
+ compressReparentActions(actions);
+ compressPropertyActions(actions);
+ compressAddEditRemoveNodeActions(actions);
+ compressAddEditActions(actions);
+ compressAddReparentActions(actions);
+}
+
+void RewriteActionCompressor::compressReparentActions(QList<RewriteAction *> &actions) const
+{
+ QSet<ModelNode> reparentedNodes;
+
+ QMutableListIterator<RewriteAction*> iter(actions);
+ iter.toBack();
+ while (iter.hasPrevious()) {
+ RewriteAction *action = iter.previous();
+
+ if (ReparentNodeRewriteAction const *reparentAction = action->asReparentNodeRewriteAction()) {
+ const ModelNode reparentedNode = reparentAction->reparentedNode();
+
+ if (reparentedNodes.contains(reparentedNode)) {
+ remove(iter);
+ } else {
+ reparentedNodes.insert(reparentedNode);
+ }
+ }
+ }
+}
+
+void RewriteActionCompressor::compressAddEditRemoveNodeActions(QList<RewriteAction *> &actions) const
+{
+ QHash<ModelNode, RewriteAction *> removedNodes;
+ QSet<RewriteAction *> removeActionsToRemove;
+
+ QMutableListIterator<RewriteAction*> iter(actions);
+ iter.toBack();
+ while (iter.hasPrevious()) {
+ RewriteAction *action = iter.previous();
+
+ if (RemoveNodeRewriteAction const *removeNodeAction = action->asRemoveNodeRewriteAction()) {
+ const ModelNode modelNode = removeNodeAction->node();
+
+ if (removedNodes.contains(modelNode))
+ remove(iter);
+ else
+ removedNodes.insert(modelNode, action);
+ } else if (action->asAddPropertyRewriteAction() || action->asChangePropertyRewriteAction()) {
+ AbstractProperty property;
+ ModelNode containedModelNode;
+ if (action->asAddPropertyRewriteAction()) {
+ property = action->asAddPropertyRewriteAction()->property();
+ containedModelNode = action->asAddPropertyRewriteAction()->containedModelNode();
+ } else {
+ property = action->asChangePropertyRewriteAction()->property();
+ containedModelNode = action->asChangePropertyRewriteAction()->containedModelNode();
+ }
+
+ if (removedNodes.contains(property.parentModelNode()))
+ remove(iter);
+ else if (removedNodes.contains(containedModelNode)) {
+ remove(iter);
+ removeActionsToRemove.insert(removedNodes[containedModelNode]);
+ }
+ } else if (RemovePropertyRewriteAction const *removePropertyAction = action->asRemovePropertyRewriteAction()) {
+ const AbstractProperty property = removePropertyAction->property();
+
+ if (removedNodes.contains(property.parentModelNode()))
+ remove(iter);
+ } else if (ChangeIdRewriteAction const *changeIdAction = action->asChangeIdRewriteAction()) {
+ if (removedNodes.contains(changeIdAction->node()))
+ remove(iter);
+ } else if (ChangeTypeRewriteAction const *changeTypeAction = action->asChangeTypeRewriteAction()) {
+ if (removedNodes.contains(changeTypeAction->node()))
+ remove(iter);
+ } else if (ReparentNodeRewriteAction const *reparentAction = action->asReparentNodeRewriteAction()) {
+ if (removedNodes.contains(reparentAction->reparentedNode()))
+ remove(iter);
+ }
+ }
+
+ foreach (RewriteAction *action, removeActionsToRemove) {
+ actions.removeOne(action);
+ delete action;
+ }
+}
+
+void RewriteActionCompressor::compressPropertyActions(QList<RewriteAction *> &actions) const
+{
+ QHash<AbstractProperty, RewriteAction *> removedProperties;
+ QHash<AbstractProperty, ChangePropertyRewriteAction const*> changedProperties;
+ QSet<AbstractProperty> addedProperties;
+
+ QMutableListIterator<RewriteAction*> iter(actions);
+ iter.toBack();
+ while (iter.hasPrevious()) {
+ RewriteAction *action = iter.previous();
+
+ if (RemovePropertyRewriteAction const *removeAction = action->asRemovePropertyRewriteAction()) {
+ removedProperties.insert(removeAction->property(), action);
+ } else if (ChangePropertyRewriteAction const *changeAction = action->asChangePropertyRewriteAction()) {
+ const AbstractProperty property = changeAction->property();
+
+ if (removedProperties.contains(property)) {
+ remove(iter);
+ } else if (changedProperties.contains(property)) {
+ if (!property.isValid() || !property.isDefaultProperty())
+ remove(iter);
+ } else {
+ changedProperties.insert(property, changeAction);
+ }
+ } else if (AddPropertyRewriteAction const *addAction = action->asAddPropertyRewriteAction()) {
+ const AbstractProperty property = addAction->property();
+
+ if (RewriteAction *removeAction = removedProperties.value(property, 0)) {
+ actions.removeOne(removeAction);
+ removedProperties.remove(property);
+ delete removeAction;
+ remove(iter);
+ } else {
+ if (changedProperties.contains(property))
+ changedProperties.remove(property);
+
+ addedProperties.insert(property);
+ }
+ }
+ }
+}
+
+void RewriteActionCompressor::compressAddEditActions(QList<RewriteAction *> &actions) const
+{
+ QSet<ModelNode> addedNodes;
+ QSet<RewriteAction *> dirtyActions;
+
+ QMutableListIterator<RewriteAction*> iter(actions);
+ while (iter.hasNext()) {
+ RewriteAction *action = iter.next();
+
+ if (action->asAddPropertyRewriteAction() || action->asChangePropertyRewriteAction()) {
+ AbstractProperty property;
+ ModelNode containedNode;
+
+ if (AddPropertyRewriteAction const *addAction = action->asAddPropertyRewriteAction()) {
+ property = addAction->property();
+ containedNode = addAction->containedModelNode();
+ } else if (ChangePropertyRewriteAction const *changeAction = action->asChangePropertyRewriteAction()) {
+ property = changeAction->property();
+ containedNode = changeAction->containedModelNode();
+ }
+
+ if (property.isValid() && addedNodes.contains(property.parentModelNode())) {
+ remove(iter);
+ continue;
+ }
+
+ if (!containedNode.isValid())
+ continue;
+
+ if (nodeOrParentInSet(containedNode, addedNodes)) {
+ remove(iter);
+ } else {
+ addedNodes.insert(containedNode);
+ dirtyActions.insert(action);
+ }
+ } else if (ChangeIdRewriteAction const *changeIdAction = action->asChangeIdRewriteAction()) {
+ if (nodeOrParentInSet(changeIdAction->node(), addedNodes)) {
+ remove(iter);
+ }
+ } else if (ChangeTypeRewriteAction const *changeTypeAction = action->asChangeTypeRewriteAction()) {
+ if (nodeOrParentInSet(changeTypeAction->node(), addedNodes)) {
+ remove(iter);
+ }
+ }
+ }
+
+ QmlTextGenerator gen(m_propertyOrder);
+ foreach (RewriteAction *action, dirtyActions) {
+ RewriteAction *newAction = 0;
+ if (AddPropertyRewriteAction const *addAction = action->asAddPropertyRewriteAction()) {
+ newAction = new AddPropertyRewriteAction(addAction->property(),
+ gen(addAction->containedModelNode()),
+ addAction->propertyType(),
+ addAction->containedModelNode());
+ } else if (ChangePropertyRewriteAction const *changeAction = action->asChangePropertyRewriteAction()) {
+ newAction = new ChangePropertyRewriteAction(changeAction->property(),
+ gen(changeAction->containedModelNode()),
+ changeAction->propertyType(),
+ changeAction->containedModelNode());
+ }
+
+ const int idx = actions.indexOf(action);
+ if (newAction && idx >= 0) {
+ actions[idx] = newAction;
+ }
+ }
+}
+
+void RewriteActionCompressor::compressAddReparentActions(QList<RewriteAction *> &actions) const
+{
+ QMap<ModelNode, RewriteAction*> addedNodes;
+
+ QMutableListIterator<RewriteAction*> iter(actions);
+ while (iter.hasNext()) {
+ RewriteAction *action = iter.next();
+
+ if (action->asAddPropertyRewriteAction() || action->asChangePropertyRewriteAction()) {
+ ModelNode containedNode;
+
+ if (AddPropertyRewriteAction const *addAction = action->asAddPropertyRewriteAction()) {
+ containedNode = addAction->containedModelNode();
+ } else if (ChangePropertyRewriteAction const *changeAction = action->asChangePropertyRewriteAction()) {
+ containedNode = changeAction->containedModelNode();
+ }
+
+ if (!containedNode.isValid())
+ continue;
+
+ addedNodes.insert(containedNode, action);
+ } else if (ReparentNodeRewriteAction const *reparentAction = action->asReparentNodeRewriteAction()) {
+ if (addedNodes.contains(reparentAction->reparentedNode())) {
+ RewriteAction *previousAction = addedNodes[reparentAction->reparentedNode()];
+ actions.removeOne(previousAction);
+
+ RewriteAction *replacementAction = 0;
+ if (AddPropertyRewriteAction const *addAction = previousAction->asAddPropertyRewriteAction()) {
+ replacementAction = new AddPropertyRewriteAction(reparentAction->targetProperty(),
+ addAction->valueText(),
+ reparentAction->propertyType(),
+ addAction->containedModelNode());
+ } else if (ChangePropertyRewriteAction const *changeAction = previousAction->asChangePropertyRewriteAction()) {
+ replacementAction = new AddPropertyRewriteAction(reparentAction->targetProperty(),
+ changeAction->valueText(),
+ reparentAction->propertyType(),
+ changeAction->containedModelNode());
+ }
+
+ iter.setValue(replacementAction);
+ delete previousAction;
+ delete action;
+ }
+ }
+ }
+}
+
+void RewriteActionCompressor::remove(QMutableListIterator<RewriteAction*> &iter) const
+{
+ delete iter.value();
+ iter.remove();
+}
diff --git a/src/plugins/qmldesigner/core/model/rewriteactioncompressor.h b/src/plugins/qmldesigner/core/model/rewriteactioncompressor.h
new file mode 100644
index 0000000000..594d490a5b
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/rewriteactioncompressor.h
@@ -0,0 +1,63 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef REWRITEACTIONCOMPRESSOR_H
+#define REWRITEACTIONCOMPRESSOR_H
+
+#include <QtCore/QStringList>
+
+#include "rewriteaction.h"
+
+namespace QmlDesigner {
+namespace Internal {
+
+class RewriteActionCompressor
+{
+public:
+ RewriteActionCompressor(const QStringList &propertyOrder): m_propertyOrder(propertyOrder) {}
+
+ void operator()(QList<RewriteAction *> &actions) const;
+
+private:
+ void compressReparentActions(QList<RewriteAction *> &actions) const;
+ void compressAddEditRemoveNodeActions(QList<RewriteAction *> &actions) const;
+ void compressPropertyActions(QList<RewriteAction *> &actions) const;
+ void compressAddEditActions(QList<RewriteAction *> &actions) const;
+ void compressAddReparentActions(QList<RewriteAction *> &actions) const;
+
+ void remove(QMutableListIterator<RewriteAction*> &iter) const;
+
+private:
+ QStringList m_propertyOrder;
+};
+
+} // namespace Internal
+} // namespace QmlDesigner
+
+#endif // REWRITEACTIONCOMPRESSOR_H
diff --git a/src/plugins/qmldesigner/core/model/rewriterview.cpp b/src/plugins/qmldesigner/core/model/rewriterview.cpp
new file mode 100644
index 0000000000..ea754e2efa
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/rewriterview.cpp
@@ -0,0 +1,459 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <filemanager/astobjecttextextractor.h>
+#include <filemanager/objectlengthcalculator.h>
+#include <filemanager/firstdefinitionfinder.h>
+#include <customnotifications.h>
+
+#include "rewriterview.h"
+#include "textmodifier.h"
+#include "texttomodelmerger.h"
+#include "modelnodepositionstorage.h"
+#include "modeltotextmerger.h"
+#include "nodelistproperty.h"
+#include "nodeproperty.h"
+#include "invalidmodelnodeexception.h"
+
+using namespace QmlDesigner::Internal;
+
+namespace QmlDesigner {
+
+RewriterView::Error::Error():
+ m_type(NoError),
+ m_line(-1),
+ m_column(-1)
+{
+}
+
+RewriterView::Error::Error(const Exception &exception):
+ m_type(InternalError),
+ m_line(exception.line()),
+ m_column(-1),
+ m_description(exception.description()),
+ m_url(exception.file())
+{
+}
+
+RewriterView::Error::Error(const QmlError &qmlError):
+ m_type(ParseError),
+ m_line(qmlError.line()),
+ m_column(qmlError.column()),
+ m_description(qmlError.description()),
+ m_url(qmlError.url())
+{
+}
+
+QString RewriterView::Error::toString() const
+{
+ QString str;
+
+ if (url().isValid())
+ str = url().toString() + QLatin1Char(':');
+ if (line() != -1)
+ str += QString::number(line()) + QLatin1Char(':');
+ if(column() != -1)
+ str += QString::number(column()) + QLatin1Char(':');
+
+ str += description();
+
+ return str;
+}
+
+RewriterView::RewriterView(DifferenceHandling differenceHandling, QObject *parent):
+ AbstractView(parent),
+ m_differenceHandling(differenceHandling),
+ m_modificationGroupActive(false),
+ m_positionStorage(new ModelNodePositionStorage),
+ m_modelToTextMerger(new Internal::ModelToTextMerger(this)),
+ m_textToModelMerger(new Internal::TextToModelMerger(this)),
+ m_textModifier(0),
+ transactionLevel(0)
+{
+}
+
+RewriterView::~RewriterView()
+{
+ delete m_positionStorage;
+}
+
+Internal::ModelToTextMerger *RewriterView::modelToTextMerger() const
+{
+ return m_modelToTextMerger.data();
+}
+
+Internal::TextToModelMerger *RewriterView::textToModelMerger() const
+{
+ return m_textToModelMerger.data();
+}
+
+void RewriterView::modelAttached(Model *model)
+{
+ AbstractView::modelAttached(model);
+
+ ModelAmender differenceHandler(m_textToModelMerger.data());
+ m_textToModelMerger->load(m_textModifier->text().toUtf8(), differenceHandler);
+}
+
+void RewriterView::modelAboutToBeDetached(Model * /*model*/)
+{
+ m_positionStorage->clear();
+}
+
+void RewriterView::nodeCreated(const ModelNode &createdNode)
+{
+ if (createdNode.type() == QLatin1String("Qt/Component"))
+ setupComponent(createdNode);
+ Q_ASSERT(textModifier());
+ m_positionStorage->setNodeOffset(createdNode, ModelNodePositionStorage::INVALID_LOCATION);
+ if (textToModelMerger()->isActive())
+ return;
+
+ modelToTextMerger()->nodeCreated(createdNode);
+
+ if (!isModificationGroupActive())
+ modelToTextMerger()->applyChanges();
+}
+
+void RewriterView::nodeAboutToBeRemoved(const ModelNode &/*removedNode*/)
+{
+}
+
+void RewriterView::nodeRemoved(const ModelNode &removedNode, const NodeAbstractProperty &parentProperty, PropertyChangeFlags propertyChange)
+{
+ Q_ASSERT(textModifier());
+ if (textToModelMerger()->isActive())
+ return;
+
+ modelToTextMerger()->nodeRemoved(removedNode, parentProperty, propertyChange);
+
+ if (!isModificationGroupActive())
+ modelToTextMerger()->applyChanges();
+}
+
+void RewriterView::propertiesAdded(const ModelNode &/*node*/, const QList<AbstractProperty>& /*propertyList*/)
+{
+ Q_ASSERT(0);
+}
+
+void RewriterView::propertiesAboutToBeRemoved(const QList<AbstractProperty> &propertyList)
+{
+ Q_ASSERT(textModifier());
+ if (textToModelMerger()->isActive())
+ return;
+
+
+ foreach (const AbstractProperty &property, propertyList) {
+ if (property.isDefaultProperty() && property.isNodeListProperty()) {
+ m_removeDefaultPropertyTransaction = beginRewriterTransaction();
+
+ foreach (const ModelNode &node, property.toNodeListProperty().toModelNodeList()) {
+ modelToTextMerger()->nodeRemoved(node, property.toNodeAbstractProperty(), AbstractView::NoAdditionalChanges);
+ }
+ }
+ }
+}
+
+void RewriterView::propertiesRemoved(const QList<AbstractProperty>& propertyList)
+{
+ Q_ASSERT(textModifier());
+ if (textToModelMerger()->isActive())
+ return;
+
+ modelToTextMerger()->propertiesRemoved(propertyList);
+
+ if (m_removeDefaultPropertyTransaction.isValid())
+ m_removeDefaultPropertyTransaction.commit();
+
+ if (!isModificationGroupActive())
+ modelToTextMerger()->applyChanges();
+}
+
+void RewriterView::variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags propertyChange)
+{
+ Q_ASSERT(textModifier());
+ if (textToModelMerger()->isActive())
+ return;
+
+ QList<AbstractProperty> usefulPropertyList;
+ foreach (const VariantProperty &property, propertyList)
+ usefulPropertyList.append(property);
+
+ modelToTextMerger()->propertiesChanged(usefulPropertyList, propertyChange);
+
+ if (!isModificationGroupActive())
+ modelToTextMerger()->applyChanges();
+}
+
+void RewriterView::bindingPropertiesChanged(const QList<BindingProperty>& propertyList, PropertyChangeFlags propertyChange)
+{
+ Q_ASSERT(textModifier());
+ if (textToModelMerger()->isActive())
+ return;
+
+ QList<AbstractProperty> usefulPropertyList;
+ foreach (const BindingProperty &property, propertyList)
+ usefulPropertyList.append(property);
+
+ modelToTextMerger()->propertiesChanged(usefulPropertyList, propertyChange);
+
+ if (!isModificationGroupActive())
+ modelToTextMerger()->applyChanges();
+}
+
+void RewriterView::nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange)
+{
+ if (node.type() == QLatin1String("Qt/Component"))
+ setupComponent(node);
+
+ Q_ASSERT(textModifier());
+ if (textToModelMerger()->isActive())
+ return;
+
+ modelToTextMerger()->nodeReparented(node, newPropertyParent, oldPropertyParent, propertyChange);
+
+ if (!isModificationGroupActive())
+ modelToTextMerger()->applyChanges();
+}
+
+void RewriterView::fileUrlChanged(const QUrl &/*oldUrl*/, const QUrl &/*newUrl*/)
+{
+}
+
+void RewriterView::nodeIdChanged(const ModelNode& node, const QString& newId, const QString& oldId)
+{
+ Q_ASSERT(textModifier());
+ if (textToModelMerger()->isActive())
+ return;
+
+ modelToTextMerger()->nodeIdChanged(node, newId, oldId);
+
+ if (!isModificationGroupActive())
+ modelToTextMerger()->applyChanges();
+}
+
+void RewriterView::nodeSlidedToIndex(const NodeListProperty &listProperty, int newIndex, int /*oldIndex*/)
+{ // FIXME: "slided" ain't no English, probably "slid" or "sliding" is meant...
+ Q_ASSERT(textModifier());
+ if (textToModelMerger()->isActive())
+ return;
+
+ const QList<ModelNode> nodes = listProperty.toModelNodeList();
+ const ModelNode movingNode = nodes.at(newIndex);
+ ModelNode trailingNode;
+ if (newIndex + 1 < nodes.size())
+ trailingNode = nodes.at(newIndex + 1);
+ modelToTextMerger()->nodeSlidAround(movingNode, trailingNode);
+
+ if (!isModificationGroupActive())
+ modelToTextMerger()->applyChanges();
+}
+
+void RewriterView::nodeTypeChanged(const ModelNode &node,const QString &type, int majorVersion, int minorVersion)
+{
+ Q_ASSERT(textModifier());
+ if (textToModelMerger()->isActive())
+ return;
+
+ modelToTextMerger()->nodeTypeChanged(node, type, majorVersion, minorVersion);
+
+ if (!isModificationGroupActive())
+ modelToTextMerger()->applyChanges();
+}
+
+void RewriterView::customNotification(const AbstractView * /*view*/, const QString &identifier, const QList<ModelNode> & /* nodeList */, const QList<QVariant> & /*data */)
+{
+ if (identifier == ("__start rewriter transaction__")) {
+ transactionLevel++;
+ setModificationGroupActive(true);
+ }
+ else if (identifier == ("__end rewriter transaction__")) {
+ transactionLevel--;
+ Q_ASSERT(transactionLevel >= 0);
+
+ }
+ if (transactionLevel == 0)
+ {
+ setModificationGroupActive(false);
+ applyModificationGroupChanges();
+ }
+}
+
+void RewriterView::selectedNodesChanged(const QList<ModelNode> & /* selectedNodeList, */, const QList<ModelNode> & /*lastSelectedNodeList */)
+{
+}
+
+bool RewriterView::isModificationGroupActive() const
+{
+ return m_modificationGroupActive;
+}
+
+void RewriterView::setModificationGroupActive(bool active)
+{
+ m_modificationGroupActive = active;
+}
+
+TextModifier *RewriterView::textModifier() const
+{
+ return m_textModifier;
+}
+
+void RewriterView::setTextModifier(TextModifier *textModifier)
+{
+ if (m_textModifier)
+ disconnect(m_textModifier, SIGNAL(textChanged()), this, SLOT(qmlTextChanged()));
+
+ m_textModifier = textModifier;
+
+ if (m_textModifier)
+ connect(m_textModifier, SIGNAL(textChanged()), this, SLOT(qmlTextChanged()));
+}
+
+void RewriterView::applyModificationGroupChanges()
+{
+ Q_ASSERT(transactionLevel == 0);
+ modelToTextMerger()->applyChanges();
+}
+
+void RewriterView::setupComponent(const ModelNode &node)
+{
+ Q_ASSERT(node.type() == QLatin1String("Qt/Component"));
+
+ QString componentText = extractText(QList<ModelNode>() << node).value(node);
+
+ if (componentText.isEmpty())
+ return;
+
+ QString result = "";
+ if (componentText.contains("Component")) { //explicit component
+ FirstDefinitionFinder firstDefinitionFinder(componentText);
+ int offset = firstDefinitionFinder(0);
+ ObjectLengthCalculator objectLengthCalculator(componentText);
+ int length = objectLengthCalculator(offset);
+ for (int i = offset;i<offset + length;i++)
+ result.append(componentText.at(i));
+ } else {
+ result = componentText; //implicit component
+ }
+
+ node.variantProperty("__component_data") = result;
+}
+
+QList<RewriterView::Error> RewriterView::errors() const
+{
+ return m_errors;
+}
+
+void RewriterView::clearErrors()
+{
+ m_errors.clear();
+ emit errorsChanged(m_errors);
+}
+
+void RewriterView::addErrors(const QList<RewriterView::Error> &errors)
+{
+ m_errors.append(errors);
+ emit errorsChanged(m_errors);
+}
+
+void RewriterView::addError(const RewriterView::Error &error)
+{
+ m_errors.append(error);
+ emit errorsChanged(m_errors);
+}
+
+QMap<ModelNode, QString> RewriterView::extractText(const QList<ModelNode> &nodes) const
+{
+ QmlEditor::ASTObjectTextExtractor extract(m_textModifier->text());
+ QMap<ModelNode, QString> result;
+
+ foreach (const ModelNode &node, nodes) {
+ const int nodeLocation = m_positionStorage->nodeOffset(node);
+
+ if (nodeLocation == ModelNodePositionStorage::INVALID_LOCATION)
+ result.insert(node, QString::null);
+ else
+ result.insert(node, extract(nodeLocation));
+ }
+
+ return result;
+}
+
+int RewriterView::nodeOffset(const ModelNode &node) const
+{
+ return m_positionStorage->nodeOffset(node);
+}
+
+int RewriterView::nodeLength(const ModelNode &node) const
+{
+ ObjectLengthCalculator objectLengthCalculator(m_textModifier->text());
+ return objectLengthCalculator(nodeOffset(node));
+}
+
+int RewriterView::firstDefinitionInsideOffset(const ModelNode &node) const
+{
+ FirstDefinitionFinder firstDefinitionFinder(m_textModifier->text());
+ return firstDefinitionFinder(nodeOffset(node));
+}
+
+int RewriterView::firstDefinitionInsideLength(const ModelNode &node) const
+{
+ FirstDefinitionFinder firstDefinitionFinder(m_textModifier->text());
+ int offset = firstDefinitionFinder(nodeOffset(node));
+ ObjectLengthCalculator objectLengthCalculator(m_textModifier->text());
+ return objectLengthCalculator(offset);
+}
+
+void RewriterView::qmlTextChanged()
+{
+ if (m_textToModelMerger && m_textModifier) {
+ const QString newQmlText = m_textModifier->text();
+
+// qDebug() << "qmlTextChanged:" << newQmlText;
+
+ switch (m_differenceHandling) {
+ case Validate: {
+ ModelValidator differenceHandler(m_textToModelMerger.data());
+ m_textToModelMerger->load(newQmlText.toUtf8(), differenceHandler);
+ break;
+ }
+
+ case Amend:
+ default: {
+ emitCustomNotification(StartRewriterAmend);
+ ModelAmender differenceHandler(m_textToModelMerger.data());
+ m_textToModelMerger->load(newQmlText.toUtf8(), differenceHandler);
+ emitCustomNotification(EndRewriterAmend);
+ break;
+ }
+ }
+ }
+}
+
+} //QmlDesigner
diff --git a/src/plugins/qmldesigner/core/model/textmodifier.cpp b/src/plugins/qmldesigner/core/model/textmodifier.cpp
new file mode 100644
index 0000000000..34365f6763
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/textmodifier.cpp
@@ -0,0 +1,36 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "textmodifier.h"
+
+using namespace QmlDesigner;
+
+TextModifier::~TextModifier()
+{
+}
diff --git a/src/plugins/qmldesigner/core/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/core/model/texttomodelmerger.cpp
new file mode 100644
index 0000000000..107a49e826
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/texttomodelmerger.cpp
@@ -0,0 +1,509 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "abstractproperty.h"
+#include "bindingproperty.h"
+#include "nodemetainfo.h"
+#include "nodeproperty.h"
+#include "propertymetainfo.h"
+#include "texttomodelmerger.h"
+#include "rewriterview.h"
+#include "variantproperty.h"
+#include <QmlDomDocument>
+#include <QmlEngine>
+#include <QSet>
+
+using namespace QmlDesigner;
+using namespace QmlDesigner::Internal;
+
+static inline bool equals(const QVariant &a, const QVariant &b)
+{
+ if (a.type() == QVariant::Double && b.type() == QVariant::Double)
+ return qFuzzyCompare(a.toDouble(), b.toDouble());
+ else
+ return a == b;
+}
+
+TextToModelMerger::TextToModelMerger(RewriterView *reWriterView):
+ m_rewriterView(reWriterView),
+ m_isActive(false)
+{
+}
+
+void TextToModelMerger::setActive(bool active)
+{
+ m_isActive = active;
+}
+
+bool TextToModelMerger::isActive() const
+{
+ return m_isActive;
+}
+
+void TextToModelMerger::setupImports(QmlDomDocument &doc)
+{
+ foreach (const Import &import, m_rewriterView->model()->imports())
+ m_rewriterView->model()->removeImport(import);
+ foreach (const QmlDomImport &qmlImport, doc.imports()) {
+ if (qmlImport.type() == QmlDomImport::Library) {
+ Import import(Import::createLibraryImport(QUrl(qmlImport.uri()), qmlImport.version(), qmlImport.qualifier()));
+ m_rewriterView->model()->addImport(import);
+ }
+ if (qmlImport.type() == QmlDomImport::File) {
+ Import import(Import:: createFileImport(qmlImport.uri(), qmlImport.version(), qmlImport.qualifier()));
+ m_rewriterView->model()->addImport(import);
+ }
+ }
+}
+
+bool TextToModelMerger::load(const QByteArray &data, DifferenceHandler &differenceHandler)
+{
+ setActive(true);
+
+ try {
+ QmlEngine engine;
+ QmlDomDocument doc;
+ const QUrl url = m_rewriterView->model()->fileUrl();
+ const bool success = doc.load(&engine, data, url);
+
+ if (success) {
+ setupImports(doc);
+
+ const QmlDomObject rootDomObject = doc.rootObject();
+ ModelNode modelRootNode = m_rewriterView->rootModelNode();
+ syncNode(modelRootNode, rootDomObject, differenceHandler);
+ m_rewriterView->positionStorage()->cleanupInvalidOffsets();
+ m_rewriterView->clearErrors();
+ } else {
+ QList<RewriterView::Error> errors;
+ foreach (const QmlError &qmlError, doc.errors())
+ errors.append(RewriterView::Error(qmlError));
+ m_rewriterView->addErrors(errors);
+ }
+
+ setActive(false);
+ return success;
+ } catch (Exception &e) {
+ m_rewriterView->addError(RewriterView::Error(e));
+
+ setActive(false);
+
+ throw;
+ }
+}
+
+void TextToModelMerger::syncNode(ModelNode &modelNode, const QmlDomObject &domObject, DifferenceHandler &differenceHandler)
+{
+ m_rewriterView->positionStorage()->setNodeOffset(modelNode, domObject.position());
+
+ if (modelNode.type() != domObject.objectType()
+ || modelNode.majorVersion() != domObject.objectTypeMajorVersion()
+ || modelNode.minorVersion() != domObject.objectTypeMinorVersion()) {
+ differenceHandler.typeDiffers(modelNode, domObject);
+ }
+
+ {
+ const QString domObjectId = domObject.objectId();
+
+ if (!domObjectId.isEmpty()) {
+ if (modelNode.id() != domObjectId)
+ differenceHandler.idsDiffer(modelNode, domObjectId);
+ }
+ }
+
+ QSet<QString> modelPropertyNames = QSet<QString>::fromList(modelNode.propertyNames());
+
+ foreach (const QmlDomProperty &domProperty, domObject.properties()) {
+ const QString domPropertyName = domProperty.propertyName();
+
+ if (isSignalPropertyName(domPropertyName.toUtf8()))
+ continue;
+
+ if (domPropertyName == QLatin1String("id")) {
+ const QmlDomValue domValue = domProperty.value();
+ if (domValue.isLiteral()) {
+ const QString domId = domValue.toLiteral().literal();
+
+ if (modelNode.id() != domId)
+ differenceHandler.idsDiffer(modelNode, domId);
+ } else {
+ qWarning() << "id property found which is not a literal";
+ }
+ } else if (domPropertyName.isEmpty()) {
+ qWarning() << "QML DOM returned an empty property name";
+ continue;
+ } else if (domPropertyName.at(0).isUpper() && domPropertyName.contains('.')) {
+ // An attached property, which we currently don't handle.
+ // So, skipping it.
+ modelPropertyNames.remove(domPropertyName);
+ continue;
+ } else {
+ const QmlDomDynamicProperty dynamicProperty = domObject.dynamicProperty(domProperty.propertyName());
+ if (dynamicProperty.isValid() || modelNode.metaInfo().hasProperty(domPropertyName, true) || modelNode.type() == QLatin1String("Qt/PropertyChanges")) {
+ AbstractProperty modelProperty = modelNode.property(domPropertyName);
+ syncProperty(modelProperty, domProperty, dynamicProperty, differenceHandler);
+ modelPropertyNames.remove(domPropertyName);
+ }
+ }
+ }
+
+ { // for new dynamic properties which have no property definitions:
+ foreach (const QmlDomDynamicProperty &dynamicDomProperty, domObject.dynamicProperties()) {
+ const QByteArray propertyName = dynamicDomProperty.propertyName();
+ if (domObject.property(propertyName).isValid())
+ continue;
+
+ if (dynamicDomProperty.isAlias())
+ continue; // we don't handle alias properties yet.
+
+ AbstractProperty modelProperty = modelNode.property(propertyName);
+ const QString dynamicTypeName = QMetaType::typeName(dynamicDomProperty.propertyType());
+
+ // a dynamic property definition without a value
+ if (modelProperty.isValid() && modelProperty.isVariantProperty()) {
+ VariantProperty modelVariantProperty = modelProperty.toVariantProperty();
+ if (modelVariantProperty.value() != QVariant())
+ differenceHandler.variantValuesDiffer(modelVariantProperty, QVariant(), dynamicTypeName);
+ } else {
+ differenceHandler.shouldBeVariantProperty(modelProperty, QVariant(), dynamicTypeName);
+ }
+ }
+ }
+
+ foreach (const QString &modelPropertyName, modelPropertyNames) {
+ AbstractProperty modelProperty = modelNode.property(modelPropertyName);
+ const QmlDomDynamicProperty dynamicDomProperty = domObject.dynamicProperty(modelPropertyName.toUtf8());
+
+ if (dynamicDomProperty.isValid()) {
+ const QString dynamicTypeName = QMetaType::typeName(dynamicDomProperty.propertyType());
+
+ // a dynamic property definition without a value
+ if (modelProperty.isValid() && modelProperty.isVariantProperty()) {
+ VariantProperty modelVariantProperty = modelProperty.toVariantProperty();
+ if (modelVariantProperty.value() != QVariant())
+ differenceHandler.variantValuesDiffer(modelVariantProperty, QVariant(), dynamicTypeName);
+ } else {
+ differenceHandler.shouldBeVariantProperty(modelProperty, QVariant(), dynamicTypeName);
+ }
+ } else {
+ // property deleted.
+ differenceHandler.propertyAbsentFromQml(modelProperty);
+ }
+ }
+}
+
+void TextToModelMerger::syncProperty(AbstractProperty &modelProperty,
+ const QmlDomProperty &qmlProperty,
+ const QmlDomDynamicProperty &qmlDynamicProperty,
+ DifferenceHandler &differenceHandler)
+{
+ Q_ASSERT(modelProperty.name() == qmlProperty.propertyName());
+
+ const QmlDomValue qmlValue = qmlProperty.value();
+
+ if (qmlValue.isBinding()) {
+ const QString qmlBinding = qmlValue.toBinding().binding();
+ if (modelProperty.isBindingProperty()) {
+ BindingProperty bindingProperty = modelProperty.toBindingProperty();
+ if (bindingProperty.expression() != qmlBinding) {
+ differenceHandler.bindingExpressionsDiffer(bindingProperty, qmlBinding);
+ }
+ } else {
+ differenceHandler.shouldBeBindingProperty(modelProperty, qmlBinding);
+ }
+ } else if (qmlValue.isList()) {
+ if (modelProperty.isNodeListProperty()) {
+ NodeListProperty nodeListProperty = modelProperty.toNodeListProperty();
+ syncNodeListProperty(nodeListProperty, qmlValue.toList(), differenceHandler);
+ } else {
+ differenceHandler.shouldBeNodeListProperty(modelProperty, qmlValue.toList());
+ }
+ } else if (qmlValue.isLiteral()) {
+ const QVariant qmlVariantValue = convertToVariant(modelProperty.parentModelNode(), qmlProperty, qmlDynamicProperty);
+ QString dynamicTypeName;
+ if (qmlDynamicProperty.isValid())
+ dynamicTypeName = QMetaType::typeName(qmlDynamicProperty.propertyType());
+
+ if (modelProperty.isVariantProperty()) {
+ VariantProperty modelVariantProperty = modelProperty.toVariantProperty();
+
+ if (!equals(modelVariantProperty.value(), qmlVariantValue)
+ || qmlDynamicProperty.isValid() != modelVariantProperty.isDynamic()
+ || dynamicTypeName != modelVariantProperty.dynamicTypeName()) {
+ differenceHandler.variantValuesDiffer(modelVariantProperty, qmlVariantValue, dynamicTypeName);
+ }
+ } else {
+ differenceHandler.shouldBeVariantProperty(modelProperty, qmlVariantValue, dynamicTypeName);
+ }
+ } else if (qmlValue.isObject()) {
+ if (modelProperty.isNodeProperty()) {
+ ModelNode nodePropertyNode = modelProperty.toNodeProperty().modelNode();
+ syncNode(nodePropertyNode, qmlValue.toObject(), differenceHandler);
+ } else {
+ differenceHandler.shouldBeNodeProperty(modelProperty, qmlValue.toObject());
+ }
+ } else if (qmlValue.isValueSource()) {
+ if (modelProperty.isNodeProperty()) {
+ ModelNode nodePropertyNode = modelProperty.toNodeProperty().modelNode();
+ syncNode(nodePropertyNode, qmlValue.toValueSource().object(), differenceHandler);
+ } else {
+ differenceHandler.shouldBeNodeProperty(modelProperty, qmlValue.toValueSource().object());
+ }
+ } else if (qmlValue.isInvalid()) {
+ // skip these nodes
+ } else {
+ qWarning() << "Found an unknown qml value!";
+ }
+}
+
+void TextToModelMerger::syncNodeListProperty(NodeListProperty &modelListProperty, const QmlDomList &domList, DifferenceHandler &differenceHandler)
+{
+ QList<ModelNode> modelNodes = modelListProperty.toModelNodeList();
+ QList<QmlDomValue> domValues = domList.values();
+ int i = 0;
+ for (; i < modelNodes.size() && i < domValues.size(); ++i) {
+ QmlDomValue value = domValues.at(i);
+ if (value.isObject()) {
+ ModelNode modelNode = modelNodes.at(i);
+ syncNode(modelNode, value.toObject(), differenceHandler);
+ } else {
+ qDebug() << "*** Oops, we got a non-object item in the list!";
+ }
+ }
+
+ for (int j = i; j < domValues.size(); ++j) {
+ // more elements in the dom-list, so add them to the model
+ QmlDomValue value = domValues.at(j);
+ if (value.isObject()) {
+ differenceHandler.listPropertyMissingModelNode(modelListProperty, value.toObject());
+ } else {
+ qDebug() << "*** Oops, we got a non-object item in the list!";
+ }
+ }
+
+ for (int j = i; j < modelNodes.size(); ++j) {
+ // more elements in the model, so remove them.
+ ModelNode modelNode = modelNodes.at(j);
+ differenceHandler.modelNodeAbsentFromQml(modelNode);
+ }
+}
+
+ModelNode TextToModelMerger::createModelNode(const QmlDomObject &domObject, DifferenceHandler &differenceHandler)
+{
+ ModelNode newNode = m_rewriterView->createModelNode(domObject.objectType(), domObject.objectTypeMajorVersion(), domObject.objectTypeMinorVersion());
+ syncNode(newNode, domObject, differenceHandler);
+ return newNode;
+}
+
+QVariant TextToModelMerger::convertToVariant(const ModelNode &node, const QmlDomProperty &qmlProperty, const QmlDomDynamicProperty &qmlDynamicProperty)
+{
+ QString stringValue = qmlProperty.value().toLiteral().literal();
+
+ if (qmlDynamicProperty.isValid()) {
+ const int type = qmlDynamicProperty.propertyType();
+ QVariant value(stringValue);
+ value.convert(static_cast<QVariant::Type>(type));
+ return value;
+ }
+
+ const NodeMetaInfo nodeMetaInfo = node.metaInfo();
+
+ if (nodeMetaInfo.isValid()) {
+ const PropertyMetaInfo propertyMetaInfo = nodeMetaInfo.property(qmlProperty.propertyName(), true);
+
+ if (propertyMetaInfo.isValid()) {
+ QVariant castedValue = propertyMetaInfo.castedValue(stringValue);
+ if (!castedValue.isValid())
+ qWarning() << "Casting the value" << stringValue << "of property" << propertyMetaInfo.name() << "to the property type" << propertyMetaInfo.type() << "failed";
+ return castedValue;
+ } else if (node.type() == QLatin1String("Qt/PropertyChanges")) {
+ // In the future, we should do the type resolving in a second pass, or delay setting properties until the full file has been parsed.
+ return QVariant(stringValue);
+ } else {
+ qWarning() << "Unknown property" << qmlProperty.propertyName() << "in node" << node.type() << "with value" << stringValue;
+ return QVariant();
+ }
+ } else {
+ qWarning() << "Unknown property" << qmlProperty.propertyName() << "in node" << node.type() << "with value" << stringValue;
+ return QVariant::fromValue(stringValue);
+ }
+}
+
+void ModelValidator::bindingExpressionsDiffer(BindingProperty &modelProperty, const QString &qmlBinding)
+{
+ Q_ASSERT(modelProperty.expression() == qmlBinding);
+ Q_ASSERT(0);
+}
+
+void ModelValidator::shouldBeBindingProperty(AbstractProperty &modelProperty, const QString &/*qmlBinding*/)
+{
+ Q_ASSERT(modelProperty.isBindingProperty());
+ Q_ASSERT(0);
+}
+
+void ModelValidator::shouldBeNodeListProperty(AbstractProperty &modelProperty, const QmlDomList &/*domList*/)
+{
+ Q_ASSERT(modelProperty.isNodeListProperty());
+ Q_ASSERT(0);
+}
+
+void ModelValidator::variantValuesDiffer(VariantProperty &modelProperty, const QVariant &qmlVariantValue, const QString &dynamicTypeName)
+{
+ Q_ASSERT(modelProperty.isDynamic() == !dynamicTypeName.isEmpty());
+ if (modelProperty.isDynamic()) {
+ Q_ASSERT(modelProperty.dynamicTypeName() == dynamicTypeName);
+ }
+
+ Q_ASSERT(equals(modelProperty.value(), qmlVariantValue));
+ Q_ASSERT(0);
+}
+
+void ModelValidator::shouldBeVariantProperty(AbstractProperty &modelProperty, const QVariant &/*qmlVariantValue*/, const QString &/*dynamicTypeName*/)
+{
+ Q_ASSERT(modelProperty.isVariantProperty());
+ Q_ASSERT(0);
+}
+
+void ModelValidator::shouldBeNodeProperty(AbstractProperty &modelProperty, const QmlDomObject &/*qmlObject*/)
+{
+ Q_ASSERT(modelProperty.isNodeProperty());
+ Q_ASSERT(0);
+}
+
+void ModelValidator::modelNodeAbsentFromQml(ModelNode &modelNode)
+{
+ Q_ASSERT(!modelNode.isValid());
+ Q_ASSERT(0);
+}
+
+void ModelValidator::listPropertyMissingModelNode(NodeListProperty &/*modelProperty*/, const QmlDomObject &/*qmlObject*/)
+{
+ Q_ASSERT(0);
+}
+
+void ModelValidator::typeDiffers(ModelNode &modelNode, const QmlDomObject &domObject)
+{
+ Q_ASSERT(modelNode.type() == domObject.objectType());
+ Q_ASSERT(modelNode.majorVersion() == domObject.objectTypeMajorVersion());
+ Q_ASSERT(modelNode.minorVersion() == domObject.objectTypeMinorVersion());
+ Q_ASSERT(0);
+}
+
+void ModelValidator::propertyAbsentFromQml(AbstractProperty &modelProperty)
+{
+ Q_ASSERT(!modelProperty.isValid());
+ Q_ASSERT(0);
+}
+
+void ModelValidator::idsDiffer(ModelNode &modelNode, const QString &qmlId)
+{
+ Q_ASSERT(modelNode.id() == qmlId);
+ Q_ASSERT(0);
+}
+
+void ModelAmender::bindingExpressionsDiffer(BindingProperty &modelProperty, const QString &qmlBinding)
+{
+ modelProperty.toBindingProperty().setExpression(qmlBinding);
+}
+
+void ModelAmender::shouldBeBindingProperty(AbstractProperty &modelProperty, const QString &qmlBinding)
+{
+ ModelNode theNode = modelProperty.parentModelNode();
+ BindingProperty newModelProperty = theNode.bindingProperty(modelProperty.name());
+ newModelProperty.setExpression(qmlBinding);
+}
+
+void ModelAmender::shouldBeNodeListProperty(AbstractProperty &modelProperty, const QmlDomList &domList)
+{
+ ModelNode theNode = modelProperty.parentModelNode();
+ NodeListProperty newNodeListProperty = theNode.nodeListProperty(modelProperty.name());
+ m_merger->syncNodeListProperty(newNodeListProperty, domList, *this);
+}
+
+void ModelAmender::variantValuesDiffer(VariantProperty &modelProperty, const QVariant &qmlVariantValue, const QString &dynamicType)
+{
+ if (dynamicType.isEmpty())
+ modelProperty.setValue(qmlVariantValue);
+ else
+ modelProperty.setDynamicTypeNameAndValue(dynamicType, qmlVariantValue);
+}
+
+void ModelAmender::shouldBeVariantProperty(AbstractProperty &modelProperty, const QVariant &qmlVariantValue, const QString &dynamicTypeName)
+{
+// qDebug() << "property" << modelProperty.name() << "in node" << modelProperty.parentModelNode().id();
+ ModelNode theNode = modelProperty.parentModelNode();
+ VariantProperty newModelProperty = theNode.variantProperty(modelProperty.name());
+
+ if (dynamicTypeName.isEmpty())
+ newModelProperty.setValue(qmlVariantValue);
+ else
+ newModelProperty.setDynamicTypeNameAndValue(dynamicTypeName, qmlVariantValue);
+}
+
+void ModelAmender::shouldBeNodeProperty(AbstractProperty &modelProperty, const QmlDomObject &qmlObject)
+{
+ ModelNode theNode = modelProperty.parentModelNode();
+ NodeProperty newNodeProperty = theNode.nodeProperty(modelProperty.name());
+ newNodeProperty.setModelNode(m_merger->createModelNode(qmlObject, *this));
+}
+
+void ModelAmender::modelNodeAbsentFromQml(ModelNode &modelNode)
+{
+ modelNode.destroy();
+}
+
+void ModelAmender::listPropertyMissingModelNode(NodeListProperty &modelProperty, const QmlDomObject &qmlObject)
+{
+ modelProperty.reparentHere(m_merger->createModelNode(qmlObject, *this));
+}
+
+void ModelAmender::typeDiffers(ModelNode &modelNode, const QmlDomObject &domObject)
+{
+ foreach (const QString &propertyName, modelNode.propertyNames())
+ modelNode.removeProperty(propertyName);
+
+ modelNode.changeType(domObject.objectType(), domObject.objectTypeMajorVersion(), domObject.objectTypeMinorVersion());
+}
+
+void ModelAmender::propertyAbsentFromQml(AbstractProperty &modelProperty)
+{
+ modelProperty.parentModelNode().removeProperty(modelProperty.name());
+}
+
+void ModelAmender::idsDiffer(ModelNode &modelNode, const QString &qmlId)
+{
+ modelNode.setId(qmlId);
+}
+
+bool TextToModelMerger::isSignalPropertyName(const QString &signalName)
+{
+ // see QmlCompiler::isSignalPropertyName
+ return signalName.length() >= 3 && signalName.startsWith(QLatin1String("on")) &&
+ signalName.at(2).isLetter();
+}
diff --git a/src/plugins/qmldesigner/core/model/texttomodelmerger.h b/src/plugins/qmldesigner/core/model/texttomodelmerger.h
new file mode 100644
index 0000000000..b76bff4809
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/texttomodelmerger.h
@@ -0,0 +1,159 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef TEXTTOMODELMERGER_H
+#define TEXTTOMODELMERGER_H
+
+#include "corelib_global.h"
+#include "nodelistproperty.h"
+#include "modelnode.h"
+
+#include <QmlDomObject>
+
+namespace QmlDesigner {
+
+class CORESHARED_EXPORT RewriterView;
+
+namespace Internal {
+
+class DifferenceHandler;
+
+class TextToModelMerger
+{
+ TextToModelMerger(const TextToModelMerger&);
+ TextToModelMerger &operator=(const TextToModelMerger&);
+
+public:
+ TextToModelMerger(RewriterView *reWriterView);
+ bool isActive() const;
+
+ void setupImports(QmlDomDocument &doc);
+ bool load(const QByteArray &data, DifferenceHandler &differenceHandler);
+
+protected:
+ RewriterView *view();
+ void setActive(bool active);
+
+public:
+ void syncNode(ModelNode &modelNode,
+ const QmlDomObject &qmlObject,
+ DifferenceHandler &differenceHandler);
+ void syncProperty(AbstractProperty &modelProperty,
+ const QmlDomProperty &qmlProperty,
+ const QmlDomDynamicProperty &qmlDynamicProperty,
+ DifferenceHandler &differenceHandler);
+ void syncNodeListProperty(NodeListProperty &modelListProperty,
+ const QmlDomList &domList,
+ DifferenceHandler &differenceHandler);
+ ModelNode createModelNode(const QmlDomObject &domObject,
+ DifferenceHandler &differenceHandler);
+ static QVariant convertToVariant(const ModelNode &node,
+ const QmlDomProperty &qmlProperty,
+ const QmlDomDynamicProperty &qmlDynamicProperty);
+
+private:
+ static bool isSignalPropertyName(const QString &signalName);
+
+ RewriterView *m_rewriterView;
+ bool m_isActive;
+};
+
+class DifferenceHandler
+{
+public:
+ DifferenceHandler(TextToModelMerger *textToModelMerger):
+ m_merger(textToModelMerger)
+ {}
+ virtual ~DifferenceHandler()
+ {}
+
+ virtual void bindingExpressionsDiffer(BindingProperty &modelProperty, const QString &qmlBinding) = 0;
+ virtual void shouldBeBindingProperty(AbstractProperty &modelProperty, const QString &qmlBinding) = 0;
+ virtual void shouldBeNodeListProperty(AbstractProperty &modelProperty, const QmlDomList &domList) = 0;
+ virtual void variantValuesDiffer(VariantProperty &modelProperty, const QVariant &qmlVariantValue, const QString &dynamicTypeName) = 0;
+ virtual void shouldBeVariantProperty(AbstractProperty &modelProperty, const QVariant &qmlVariantValue, const QString &dynamicTypeName) = 0;
+ virtual void shouldBeNodeProperty(AbstractProperty &modelProperty, const QmlDomObject &qmlObject) = 0;
+ virtual void modelNodeAbsentFromQml(ModelNode &modelNode) = 0;
+ virtual void listPropertyMissingModelNode(NodeListProperty &modelProperty, const QmlDomObject &qmlObject) = 0;
+ virtual void typeDiffers(ModelNode &modelNode, const QmlDomObject &domObject) = 0;
+ virtual void propertyAbsentFromQml(AbstractProperty &modelProperty) = 0;
+ virtual void idsDiffer(ModelNode &modelNode, const QString &qmlId) = 0;
+
+protected:
+ TextToModelMerger *m_merger;
+};
+
+class ModelValidator: public DifferenceHandler
+{
+public:
+ ModelValidator(TextToModelMerger *textToModelMerger):
+ DifferenceHandler(textToModelMerger)
+ {}
+ ~ModelValidator()
+ {}
+
+ virtual void bindingExpressionsDiffer(BindingProperty &modelProperty, const QString &qmlBinding);
+ virtual void shouldBeBindingProperty(AbstractProperty &modelProperty, const QString &qmlBinding);
+ virtual void shouldBeNodeListProperty(AbstractProperty &modelProperty, const QmlDomList &domList);
+ virtual void variantValuesDiffer(VariantProperty &modelProperty, const QVariant &qmlVariantValue, const QString &dynamicTypeName);
+ virtual void shouldBeVariantProperty(AbstractProperty &modelProperty, const QVariant &qmlVariantValue, const QString &dynamicTypeName);
+ virtual void shouldBeNodeProperty(AbstractProperty &modelProperty, const QmlDomObject &qmlObject);
+ virtual void modelNodeAbsentFromQml(ModelNode &modelNode);
+ virtual void listPropertyMissingModelNode(NodeListProperty &modelProperty, const QmlDomObject &qmlObject);
+ virtual void typeDiffers(ModelNode &modelNode, const QmlDomObject &domObject);
+ virtual void propertyAbsentFromQml(AbstractProperty &modelProperty);
+ virtual void idsDiffer(ModelNode &modelNode, const QString &qmlId);
+};
+
+class ModelAmender: public DifferenceHandler
+{
+public:
+ ModelAmender(TextToModelMerger *textToModelMerger):
+ DifferenceHandler(textToModelMerger)
+ {}
+ ~ModelAmender()
+ {}
+
+ virtual void bindingExpressionsDiffer(BindingProperty &modelProperty, const QString &qmlBinding);
+ virtual void shouldBeBindingProperty(AbstractProperty &modelProperty, const QString &qmlBinding);
+ virtual void shouldBeNodeListProperty(AbstractProperty &modelProperty, const QmlDomList &domList);
+ virtual void variantValuesDiffer(VariantProperty &modelProperty, const QVariant &qmlVariantValue, const QString &dynamicType);
+ virtual void shouldBeVariantProperty(AbstractProperty &modelProperty, const QVariant &qmlVariantValue, const QString &dynamicTypeName);
+ virtual void shouldBeNodeProperty(AbstractProperty &modelProperty, const QmlDomObject &qmlObject);
+ virtual void modelNodeAbsentFromQml(ModelNode &modelNode);
+ virtual void listPropertyMissingModelNode(NodeListProperty &modelProperty, const QmlDomObject &qmlObject);
+ virtual void typeDiffers(ModelNode &modelNode, const QmlDomObject &domObject);
+ virtual void propertyAbsentFromQml(AbstractProperty &modelProperty);
+ virtual void idsDiffer(ModelNode &modelNode, const QString &qmlId);
+};
+
+} //Internal
+} //QmlDesigner
+
+#endif // TEXTTOMODELMERGER_H
diff --git a/src/plugins/qmldesigner/core/model/variantparser.cpp b/src/plugins/qmldesigner/core/model/variantparser.cpp
new file mode 100644
index 0000000000..d50a042e81
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/variantparser.cpp
@@ -0,0 +1,149 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "variantparser.h"
+#include <private/qmlvaluetype_p.h>
+
+#include <QPoint>
+#include <QPointF>
+#include <QFont>
+#include <QRect>
+#include <QRectF>
+#include <QSize>
+#include <QSizeF>
+#include <QVector3D>
+#include <QMetaProperty>
+
+namespace QmlDesigner {
+namespace Internal {
+
+VariantParser::VariantParser(const QVariant &value) : m_valueType(QmlValueTypeFactory::valueType(value.type()))
+{
+ if (m_valueType) {
+ m_valueType->setValue(value);
+ if (!m_valueType->value().isValid())
+ qWarning("VariantParser::VariantParser: value not valid");
+ }
+}
+
+VariantParser::~VariantParser()
+{
+ if (m_valueType)
+ delete m_valueType;
+}
+
+QVariant VariantParser::value() const
+{
+ return m_valueType->value();
+}
+
+QVariant VariantParser::property(QString name) const
+{
+ if (!m_valueType)
+ return QVariant();
+ return m_valueType->property(name.toLatin1());
+}
+
+bool VariantParser::setProperty(const QString &name, const QVariant &value)
+{
+ if (!m_valueType)
+ return false;
+ if (name == "pixelSize" && value.toInt() < 1)
+ return false; //this check we have to harcode
+ return m_valueType->setProperty(name.toLatin1(), value);
+}
+
+bool VariantParser::isValueType(const QString &type)
+{
+ return VariantParser::create(type).isValid();
+}
+
+QStringList VariantParser::properties()
+{
+ if (!m_valueType)
+ return QStringList();
+ QStringList propertyList;
+ for (int i=1; i < m_valueType->metaObject()->propertyCount(); i++) {
+ QMetaProperty metaProperty = m_valueType->metaObject()->property(i);
+ propertyList.append(metaProperty.name());
+ }
+ return propertyList;
+}
+
+VariantParser VariantParser::create(const QString &type)
+{
+ if (type == "QFont")
+ return VariantParser(QVariant(QFont()));
+ if (type == "QPoint")
+ return VariantParser(QVariant(QPoint()));
+ if (type == "QPointF")
+ return VariantParser(QVariant(QPointF()));
+ if (type == "QSize")
+ return VariantParser(QVariant(QSize()));
+ if (type == "QSizeF")
+ return VariantParser(QVariant(QSizeF()));
+ if (type == "QRect")
+ return VariantParser(QVariant(QRect()));
+ if (type == "QRectF")
+ return VariantParser(QVariant(QRectF()));
+ if (type == "QVector3D")
+ return VariantParser(QVariant(QVector3D()));
+
+ return VariantParser(QVariant());
+}
+
+void VariantParser::init(const QString &type)
+{
+ if (type == "QFont")
+ m_valueType = QmlValueTypeFactory::valueType(QVariant::Font);
+ if (type == "QPoint")
+ m_valueType = QmlValueTypeFactory::valueType(QVariant::Point);
+ if (type == "QPointF")
+ m_valueType = QmlValueTypeFactory::valueType(QVariant::PointF);
+ if (type == "QSize")
+ m_valueType = QmlValueTypeFactory::valueType(QVariant::Size);
+ if (type == "QSizeF")
+ m_valueType = QmlValueTypeFactory::valueType(QVariant::SizeF);
+ if (type == "QRect")
+ m_valueType = QmlValueTypeFactory::valueType(QVariant::Rect);
+ if (type == "QRectF")
+ m_valueType = QmlValueTypeFactory::valueType(QVariant::RectF);
+ if (type == "QVector3D")
+ m_valueType = QmlValueTypeFactory::valueType(QVariant::Vector3D);
+}
+
+bool VariantParser::isValid()
+{
+ return m_valueType && m_valueType->value().isValid();
+}
+
+} // namespace Internal
+} // namespace QmlDesigner
+
+
diff --git a/src/plugins/qmldesigner/core/model/variantparser.h b/src/plugins/qmldesigner/core/model/variantparser.h
new file mode 100644
index 0000000000..711e3b8f4b
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/variantparser.h
@@ -0,0 +1,65 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef QVARIANTPARSER_H
+#define QVARIANTPARSER_H
+
+#include <QVariant>
+#include <QString>
+#include <QStringList>
+
+class QmlValueType;
+
+namespace QmlDesigner {
+namespace Internal {
+
+class VariantParser
+{
+public:
+ VariantParser(const QVariant &value);
+ ~VariantParser();
+ QVariant value() const;
+ QVariant property(QString name) const;
+ bool setProperty(const QString &name, const QVariant &value);
+ bool isValid();
+ QStringList properties();
+ void init(const QString &type);
+
+ static bool isValueType(const QString &type);
+ static VariantParser create(const QString &type);
+private:
+ QmlValueType *m_valueType;
+};
+
+
+
+} // namespace Internal
+} // namespace QmlDesigner
+
+#endif // QVARIANTPARSER_H
diff --git a/src/plugins/qmldesigner/core/model/variantproperty.cpp b/src/plugins/qmldesigner/core/model/variantproperty.cpp
new file mode 100644
index 0000000000..051b6fddf7
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/variantproperty.cpp
@@ -0,0 +1,143 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "variantproperty.h"
+#include "internalproperty.h"
+#include "internalvariantproperty.h"
+#include "invalidmodelnodeexception.h"
+#include "invalidpropertyexception.h"
+#include "invalidargumentexception.h"
+#include "internalnode_p.h"
+#include "model.h"
+#include "model_p.h"
+
+
+
+namespace QmlDesigner {
+
+VariantProperty::VariantProperty()
+{}
+
+VariantProperty::VariantProperty(const VariantProperty &property, AbstractView *view)
+ : AbstractProperty(property.name(), property.internalNode(), property.model(), view)
+{
+
+}
+
+VariantProperty::VariantProperty(const QString &propertyName, const Internal::InternalNodePointer &internalNode, Model* model, AbstractView *view) :
+ AbstractProperty(propertyName, internalNode, model, view)
+{
+}
+
+void VariantProperty::setValue(const QVariant &value)
+{
+ if (!isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ if (value.isNull())
+ throw InvalidArgumentException(__LINE__, __FUNCTION__, __FILE__, name());
+
+ if (internalNode()->hasProperty(name())) { //check if oldValue != value
+ Internal::InternalProperty::Pointer internalProperty = internalNode()->property(name());
+ if (internalProperty->isVariantProperty()
+ && internalProperty->toVariantProperty()->value() == value
+ && dynamicTypeName().isEmpty())
+
+ return;
+ }
+
+ if (internalNode()->hasProperty(name()) && !internalNode()->property(name())->isVariantProperty())
+ model()->m_d->removeProperty(internalNode()->property(name()));
+
+ model()->m_d->setVariantProperty(internalNode(), name(), value);
+}
+
+QVariant VariantProperty::value() const
+{
+ if (internalNode()->hasProperty(name())
+ && internalNode()->property(name())->isVariantProperty())
+ return internalNode()->variantProperty(name())->value();
+
+ return QVariant();
+}
+
+VariantProperty& VariantProperty::operator= (const QVariant &value)
+{
+ setValue(value);
+
+ return *this;
+}
+
+void VariantProperty::setDynamicTypeNameAndValue(const QString &type, const QVariant &value)
+{
+ if (!isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+
+ if (type.isEmpty()) {
+ throw InvalidArgumentException(__LINE__, __FUNCTION__, __FILE__, name());
+ }
+
+ if (internalNode()->hasProperty(name())) { //check if oldValue != value
+ Internal::InternalProperty::Pointer internalProperty = internalNode()->property(name());
+ if (internalProperty->isVariantProperty()
+ && internalProperty->toVariantProperty()->value() == value
+ && internalProperty->toVariantProperty()->dynamicTypeName() == type)
+
+ return;
+ }
+
+ if (internalNode()->hasProperty(name()) && !internalNode()->property(name())->isVariantProperty())
+ model()->m_d->removeProperty(internalNode()->property(name()));
+
+ model()->m_d->setDynamicVariantProperty(internalNode(), name(), type, value);
+}
+
+VariantProperty& VariantProperty::operator= (const QPair<QString, QVariant> &typeValuePair)
+{
+ setDynamicTypeNameAndValue(typeValuePair.first, typeValuePair.second);
+ return *this;
+}
+
+
+
+
+
+QDebug operator<<(QDebug debug, const VariantProperty &VariantProperty)
+{
+ return debug.nospace() << "VariantProperty(" << VariantProperty.name() << ")";
+}
+QTextStream& operator<<(QTextStream &stream, const VariantProperty &property)
+{
+ stream << "VariantProperty(" << property.name() << ")";
+
+ return stream;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/core/model/viewlogger.cpp b/src/plugins/qmldesigner/core/model/viewlogger.cpp
new file mode 100644
index 0000000000..2b1c555664
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/viewlogger.cpp
@@ -0,0 +1,200 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "viewlogger.h"
+#include <QDebug>
+#include <QTemporaryFile>
+#include <QDir>
+#include <variantproperty.h>
+#include <bindingproperty.h>
+#include <nodeabstractproperty.h>
+#include <nodelistproperty.h>
+
+namespace QmlDesigner {
+namespace Internal {
+
+static QString serialize(AbstractView::PropertyChangeFlags change)
+{
+ QStringList tokenList;
+
+ if (change.testFlag(AbstractView::PropertiesAdded))
+ tokenList.append(QLatin1String("PropertiesAdded"));
+
+ if (change.testFlag(AbstractView::EmptyPropertiesRemoved))
+ tokenList.append(QLatin1String("EmptyPropertiesRemoved"));
+
+ return tokenList.join(" ");
+
+ return QString();
+}
+
+static QString indent(const QString &name = QString()) {
+ return name.leftJustified(30, ' ');
+}
+
+QString ViewLogger::time() const
+{
+ return QString::number(m_timer.elapsed()).leftJustified(7, ' ');
+}
+
+ViewLogger::ViewLogger(QObject *parent)
+ : AbstractView(parent)
+{
+#ifdef Q_OS_MAC
+ const QLatin1String logPath("Library/Logs/Bauhaus");
+ QDir logDir(QDir::homePath());
+ logDir.mkpath(logPath);
+ const QString tempPath = QDir::homePath() + QDir::separator() + logPath;
+#else
+ const QString tempPath = QDir::tempPath();
+#endif
+
+ QTemporaryFile *temporaryFile = new QTemporaryFile(tempPath + QString("/bauhaus-logger-%1-XXXXXX.txt").arg(QDateTime::currentDateTime().toString(Qt::ISODate)), this);
+ temporaryFile->setAutoRemove(false);
+ if (temporaryFile->open()) {
+ qDebug() << "TemporaryLoggerFile is:" << temporaryFile->fileName();
+
+ m_output.setDevice(temporaryFile);
+ }
+
+ m_timer.start();
+}
+
+void ViewLogger::modelAttached(Model *model)
+{
+ m_output << time() << indent("modelAttached:") << model << endl;
+ AbstractView::modelAttached(model);
+}
+
+void ViewLogger::modelAboutToBeDetached(Model *model)
+{
+ m_output << time() << indent("modelAboutToBeDetached:") << model << endl;
+ AbstractView::modelAboutToBeDetached(model);
+}
+
+void ViewLogger::nodeCreated(const ModelNode &createdNode)
+{
+ m_output << time() << indent("nodeCreated:") << createdNode << endl;
+}
+
+void ViewLogger::nodeAboutToBeRemoved(const ModelNode &removedNode)
+{
+ m_output << time() << indent("nodeAboutToBeRemoved:") << removedNode << endl;
+}
+
+void ViewLogger::nodeRemoved(const ModelNode &removedNode, const NodeAbstractProperty &parentProperty, PropertyChangeFlags propertyChange)
+{
+ m_output << time() << indent("nodeRemoved:") << removedNode << parentProperty << serialize(propertyChange) << endl;
+}
+
+void ViewLogger::nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange)
+{
+ m_output << time() << indent("nodeReparented:") << node << "\t" << newPropertyParent << "\t" << oldPropertyParent << "\t" << serialize(propertyChange) << endl;
+}
+
+void ViewLogger::nodeIdChanged(const ModelNode& node, const QString& newId, const QString& oldId)
+{
+ m_output << time() << indent("nodeIdChanged:") << node << "\t" << newId << "\t" << oldId << endl;
+}
+
+void ViewLogger::propertiesAboutToBeRemoved(const QList<AbstractProperty>& propertyList)
+{
+ m_output << time() << indent("propertiesAboutToBeRemoved:") << endl;
+ foreach (const AbstractProperty &property, propertyList)
+ m_output << time() << indent() << property << endl;
+}
+
+void ViewLogger::propertiesRemoved(const QList<AbstractProperty> &propertyList)
+{
+ m_output << time() << indent("propertiesRemoved:") << endl;
+ foreach (const AbstractProperty &property, propertyList)
+ m_output << time() << indent() << property << endl;
+}
+
+void ViewLogger::variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags propertyChange)
+{
+ m_output << time() << indent("variantPropertiesChanged:") << serialize(propertyChange) << endl;
+ foreach(const VariantProperty &property, propertyList)
+ m_output << time() << indent() << property << endl;
+}
+
+void ViewLogger::bindingPropertiesChanged(const QList<BindingProperty>& propertyList, PropertyChangeFlags propertyChange)
+{
+ m_output << time() << indent("bindingPropertiesChanged:") << serialize(propertyChange) << endl;
+ foreach(const BindingProperty &property, propertyList)
+ m_output << time() << indent() << property << endl;
+}
+
+void ViewLogger::nodeTypeChanged(const ModelNode &node,const QString &type, int majorVersion, int minorVersion)
+{
+ m_output << time() << indent("nodeTypeChanged:") << node << type << majorVersion << minorVersion << endl;
+}
+
+void ViewLogger::selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
+ const QList<ModelNode> &lastSelectedNodeList)
+{
+ m_output << time() << indent("selectedNodesChanged:") << endl;
+ foreach(const ModelNode &node, selectedNodeList)
+ m_output << time() << indent("new: ") << node << endl;
+ foreach(const ModelNode &node, lastSelectedNodeList)
+ m_output << time() << indent("old: ") << node << endl;
+}
+
+void ViewLogger::fileUrlChanged(const QUrl &oldUrl, const QUrl &newUrl)
+{
+ m_output << time() << indent("fileUrlChanged:") << oldUrl.toString() << "\t" << newUrl.toString() << endl;
+}
+
+void ViewLogger::nodeSlidedToIndex(const NodeListProperty &listProperty, int newIndex, int oldIndex)
+{
+ m_output << time() << indent("nodeSlidedToIndex:") << listProperty << newIndex << oldIndex << endl;
+}
+
+void ViewLogger::importsChanged()
+{
+ m_output << time() << indent("importsChanged:") << endl;
+}
+
+void ViewLogger::auxiliaryDataChanged(const ModelNode &node, const QString &name, const QVariant &data)
+{
+ m_output << time() << indent("auxiliaryDataChanged:") << node << "\t" << name << "\t" << data.toString() << endl;
+}
+
+void ViewLogger::customNotification(const AbstractView *view, const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> &data)
+{
+ m_output << time() << indent("customNotification:") << view << identifier << endl;
+ foreach(const ModelNode &node, nodeList)
+ m_output << time() << indent("node: ") << node << endl;
+ foreach(const QVariant &variant, data)
+ m_output << time() << indent("data: ") << variant.toString() << endl;
+}
+
+
+} // namespace Internal
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/core/model/viewlogger.h b/src/plugins/qmldesigner/core/model/viewlogger.h
new file mode 100644
index 0000000000..388c3ab8cc
--- /dev/null
+++ b/src/plugins/qmldesigner/core/model/viewlogger.h
@@ -0,0 +1,85 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef VIEWLOGGER_H
+#define VIEWLOGGER_H
+
+#include "abstractview.h"
+
+#include <QTextStream>
+#include <QTime>
+
+namespace QmlDesigner {
+namespace Internal {
+
+class ViewLogger : public QmlDesigner::AbstractView
+{
+ Q_OBJECT
+public:
+ ViewLogger(QObject *parent);
+
+ void modelAttached(Model *model);
+ void modelAboutToBeDetached(Model *model);
+
+ void nodeCreated(const ModelNode &createdNode);
+ void nodeAboutToBeRemoved(const ModelNode &removedNode);
+ void nodeRemoved(const ModelNode &removedNode, const NodeAbstractProperty &parentProperty, PropertyChangeFlags propertyChange);
+ void nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange);
+ void nodeIdChanged(const ModelNode& node, const QString& newId, const QString& oldId);
+ void propertiesAboutToBeRemoved(const QList<AbstractProperty>& propertyList);
+ void propertiesRemoved(const QList<AbstractProperty>& propertyList);
+ void variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags propertyChange);
+ void bindingPropertiesChanged(const QList<BindingProperty>& propertyList, PropertyChangeFlags propertyChange);
+ void nodeTypeChanged(const ModelNode &node,const QString &type, int majorVersion, int minorVersion);
+
+ void selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
+ const QList<ModelNode> &lastSelectedNodeList);
+
+ void fileUrlChanged(const QUrl &oldUrl, const QUrl &newUrl);
+
+ void nodeSlidedToIndex(const NodeListProperty &listProperty, int newIndex, int oldIndex);
+
+ void importsChanged();
+
+ void auxiliaryDataChanged(const ModelNode &node, const QString &name, const QVariant &data);
+
+ void customNotification(const AbstractView *view, const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> &data);
+
+protected:
+ QString time() const;
+
+private:
+ QTextStream m_output;
+ QTime m_timer;
+};
+
+} // namespace Internal
+} // namespace QmlDesigner
+
+#endif // VIEWLOGGER_H
diff --git a/src/plugins/qmldesigner/core/pluginmanager/widgetpluginmanager.cpp b/src/plugins/qmldesigner/core/pluginmanager/widgetpluginmanager.cpp
new file mode 100644
index 0000000000..72557af669
--- /dev/null
+++ b/src/plugins/qmldesigner/core/pluginmanager/widgetpluginmanager.cpp
@@ -0,0 +1,103 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "widgetpluginmanager.h"
+#include "widgetpluginpath.h"
+#include <iwidgetplugin.h>
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QObject>
+#include <QtCore/QSharedData>
+#include <QtCore/QDir>
+#include <QtCore/QStringList>
+#include <QtCore/QDebug>
+#include <QWeakPointer>
+#include <QtCore/QPluginLoader>
+#include <QtCore/QFileInfo>
+#include <QtCore/QLibraryInfo>
+
+#include <QtGui/QStandardItemModel>
+#include <QtGui/QStandardItem>
+
+enum { debug = 0 };
+
+namespace QmlDesigner {
+
+namespace Internal {
+
+// ---- PluginManager[Private]
+class WidgetPluginManagerPrivate {
+public:
+ typedef QList<WidgetPluginPath> PluginPathList;
+ PluginPathList m_paths;
+};
+
+WidgetPluginManager::WidgetPluginManager() :
+ m_d(new WidgetPluginManagerPrivate)
+{
+}
+
+WidgetPluginManager::~WidgetPluginManager()
+{
+ delete m_d;
+}
+
+WidgetPluginManager::IWidgetPluginList WidgetPluginManager::instances()
+{
+ if (debug)
+ qDebug() << '>' << Q_FUNC_INFO << QLibraryInfo::buildKey();
+ IWidgetPluginList rc;
+ const WidgetPluginManagerPrivate::PluginPathList::iterator end = m_d->m_paths.end();
+ for (WidgetPluginManagerPrivate::PluginPathList::iterator it = m_d->m_paths.begin(); it != end; ++it)
+ it->getInstances(&rc);
+ if (debug)
+ qDebug() << '<' << Q_FUNC_INFO << rc.size();
+ return rc;
+}
+
+bool WidgetPluginManager::addPath(const QString &path)
+{
+ const QDir dir(path);
+ if (!dir.exists())
+ return false;
+ m_d->m_paths.push_back(WidgetPluginPath(dir));
+ return true;
+}
+
+QAbstractItemModel *WidgetPluginManager::createModel(QObject *parent)
+{
+ QStandardItemModel *model = new QStandardItemModel(parent);
+ const WidgetPluginManagerPrivate::PluginPathList::iterator end = m_d->m_paths.end();
+ for (WidgetPluginManagerPrivate::PluginPathList::iterator it = m_d->m_paths.begin(); it != end; ++it)
+ model->appendRow(it->createModelItem());
+ return model;
+}
+
+} // namespace Internal
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/core/pluginmanager/widgetpluginmanager.h b/src/plugins/qmldesigner/core/pluginmanager/widgetpluginmanager.h
new file mode 100644
index 0000000000..d2b4a76569
--- /dev/null
+++ b/src/plugins/qmldesigner/core/pluginmanager/widgetpluginmanager.h
@@ -0,0 +1,76 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef WIDGETPLUGINMANAGER_H
+#define WIDGETPLUGINMANAGER_H
+
+#include <QtCore/QObject>
+#include <QtCore/QList>
+
+QT_BEGIN_NAMESPACE
+class QString;
+class QAbstractItemModel;
+QT_END_NAMESPACE
+
+namespace QmlDesigner {
+
+class IWidgetPlugin;
+
+namespace Internal {
+
+class WidgetPluginManagerPrivate;
+
+// PluginManager: Loads the plugin libraries on demand "as lazy as
+// possible", that is, directories are scanned and
+// instances are created only when instances() is called.
+
+class WidgetPluginManager
+{
+ Q_DISABLE_COPY(WidgetPluginManager)
+public:
+ typedef QList<IWidgetPlugin *> IWidgetPluginList;
+
+ WidgetPluginManager();
+ ~WidgetPluginManager();
+
+ bool addPath(const QString &path);
+
+ IWidgetPluginList instances();
+
+ // Convenience to create a model for an "About Plugins"
+ // dialog. Forces plugin initialization.
+ QAbstractItemModel *createModel(QObject *parent = 0);
+
+private:
+ WidgetPluginManagerPrivate *m_d;
+};
+
+} // namespace Internal
+} // namespace QmlDesigner
+#endif // WIDGETPLUGINMANAGER_H
diff --git a/src/plugins/qmldesigner/core/pluginmanager/widgetpluginpath.cpp b/src/plugins/qmldesigner/core/pluginmanager/widgetpluginpath.cpp
new file mode 100644
index 0000000000..07108fa094
--- /dev/null
+++ b/src/plugins/qmldesigner/core/pluginmanager/widgetpluginpath.cpp
@@ -0,0 +1,206 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "widgetpluginpath.h"
+#include <iwidgetplugin.h>
+#include <QtCore/QLibrary>
+#include <QWeakPointer>
+#include <QtCore/QPluginLoader>
+#include <QtCore/QFileInfo>
+#include <QtCore/QLibraryInfo>
+#include <QtCore/QCoreApplication>
+#include <QtCore/QObject>
+#include <QtCore/QSharedData>
+#include <QDebug>
+
+enum { debug = 1 };
+
+namespace QmlDesigner {
+
+namespace Internal {
+
+// Initialize and create instance of a plugin from scratch,
+// that is, make sure the library is loaded and has an instance
+// of the IPlugin type. Once something fails, mark it as failed
+// ignore it from then on.
+static IWidgetPlugin *instance(WidgetPluginData &p)
+{
+ qWarning() << "START";
+ qWarning() << p.path;
+ // Go stale once something fails
+ if (p.failed)
+ return 0;
+ // Pull up the plugin, retrieve IPlugin instance.
+ if (!p.instanceGuard) {
+ p.instance = 0;
+ QPluginLoader loader(p.path);
+ qWarning() << "guard";
+ qWarning() << p.path;
+ if (!(loader.isLoaded() || loader.load())) {
+ p.failed = true;
+ qWarning() << p.errorMessage;
+ p.errorMessage = loader.errorString();
+ return 0;
+ }
+ QObject *object = loader.instance();
+ if (!object) {
+ p.failed = true;
+ qWarning() << "plugin loading failed";
+ p.errorMessage = QCoreApplication::translate("WidgetPluginManager", "Failed to create instance.");
+ qWarning() << p.errorMessage;
+ return 0;
+ }
+ IWidgetPlugin *iplugin = qobject_cast<IWidgetPlugin *>(object);
+ if (!iplugin) {
+ p.failed = true;
+ p.errorMessage = QCoreApplication::translate("WidgetPluginManager", "Not a QmlDesigner plugin.");
+ qWarning() << "cast failed";
+ qWarning() << p.errorMessage;
+ delete object;
+ return 0;
+ }
+ p.instanceGuard = object;
+ p.instance = iplugin;
+ }
+ // Ensure it is initialized
+ /*if (!p.instance->isInitialized()) {
+ if (!p.instance->initialize(&p.errorMessage)) {
+ p.failed = true;
+ delete p.instance;
+ p.instance = 0;
+ return 0;
+ }
+ }*/
+ qWarning() << "instance created";
+ return p.instance;
+}
+
+WidgetPluginData::WidgetPluginData(const QString &p) :
+ path(p),
+ failed(false),
+ instance(0)
+{
+}
+
+
+WidgetPluginPath::WidgetPluginPath(const QDir &path) :
+ m_path(path),
+ m_loaded(false)
+{
+}
+
+// Determine a unique list of library files in that directory
+QStringList WidgetPluginPath::libraryFilePaths(const QDir &dir)
+{
+ const QFileInfoList infoList = dir.entryInfoList(QDir::Files|QDir::Readable|QDir::NoDotAndDotDot);
+ if (infoList.empty())
+ return QStringList();
+ // Load symbolic links but make sure all file names are unique as not
+ // to fall for something like 'libplugin.so.1 -> libplugin.so'
+ QStringList result;
+ const QFileInfoList::const_iterator icend = infoList.constEnd();
+ for (QFileInfoList::const_iterator it = infoList.constBegin(); it != icend; ++it) {
+ QString fileName;
+ if (it->isSymLink()) {
+ const QFileInfo linkTarget = QFileInfo(it->symLinkTarget());
+ if (linkTarget.exists() && linkTarget.isFile())
+ fileName = linkTarget.absoluteFilePath();
+ } else {
+ fileName = it->absoluteFilePath();
+ }
+ if (!fileName.isEmpty() && QLibrary::isLibrary(fileName) && !result.contains(fileName))
+ result += fileName;
+ }
+
+ qDebug() << "Library file paths: " << result;
+
+ return result;
+}
+
+void WidgetPluginPath::clear()
+{
+ m_loaded = false;
+ m_plugins.clear();
+}
+
+void WidgetPluginPath::ensureLoaded()
+{
+ if (!m_loaded) {
+ const QStringList libraryFiles = libraryFilePaths(m_path);
+ if (debug)
+ qDebug() << "Checking " << libraryFiles.size() << " plugins " << m_path.absolutePath();
+ foreach (const QString &libFile, libraryFiles)
+ m_plugins.push_back(WidgetPluginData(libFile));
+ m_loaded = true;
+ }
+}
+
+void WidgetPluginPath::getInstances(WidgetPluginManager::IWidgetPluginList *list)
+{
+ ensureLoaded();
+ // Compile list of instances
+ if (m_plugins.empty())
+ return;
+ const PluginDataList::iterator end = m_plugins.end();
+ for (PluginDataList::iterator it = m_plugins.begin(); it != end; ++it)
+ if (IWidgetPlugin *i = instance(*it))
+ list->push_back(i);
+}
+
+QStandardItem *WidgetPluginPath::createModelItem()
+{
+ ensureLoaded();
+ // Create a list of plugin lib files with classes.
+ // If there are failed ones, create a separate "Failed"
+ // category at the end
+ QStandardItem *pathItem = new QStandardItem(m_path.absolutePath());
+ QStandardItem *failedCategory = 0;
+ const PluginDataList::iterator end = m_plugins.end();
+ for (PluginDataList::iterator it = m_plugins.begin(); it != end; ++it) {
+ QStandardItem *pluginItem = new QStandardItem(QFileInfo(it->path).fileName());
+ if (instance(*it)) {
+ pluginItem->appendRow(new QStandardItem(QString::fromLatin1(it->instanceGuard->metaObject()->className())));
+ pathItem->appendRow(pluginItem);
+ } else {
+ pluginItem->setToolTip(it->errorMessage);
+ if (!failedCategory) {
+ const QString failed = QCoreApplication::translate("PluginManager", "Failed Plugins");
+ failedCategory = new QStandardItem(failed);
+ }
+ failedCategory->appendRow(pluginItem);
+ }
+ }
+ if (failedCategory)
+ pathItem->appendRow(failedCategory);
+ return pathItem;
+}
+
+} // namespace Internal
+} // namespace QmlDesigner
+
diff --git a/src/plugins/qmldesigner/core/pluginmanager/widgetpluginpath.h b/src/plugins/qmldesigner/core/pluginmanager/widgetpluginpath.h
new file mode 100644
index 0000000000..cba2d94d50
--- /dev/null
+++ b/src/plugins/qmldesigner/core/pluginmanager/widgetpluginpath.h
@@ -0,0 +1,102 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef WIDGETPLUGINPATH_H
+#define WIDGETPLUGINPATH_H
+
+#include "widgetpluginmanager.h"
+
+#include <QtCore/QObject>
+#include <QWeakPointer>
+#include <QtCore/QList>
+#include <QtCore/QDir>
+#include <QtGui/QStandardItem>
+
+QT_BEGIN_NAMESPACE
+class QString;
+class QAbstractItemModel;
+QT_END_NAMESPACE
+
+namespace QmlDesigner {
+class IWidgetPlugin;
+namespace Internal {
+
+
+
+// Dumb plugin data structure. Note that whereas QObjects can
+// casted to an interface, QWeakPointer does not work with the
+// interface class, so, we need a separate QWeakPointer as a guard
+// to detect the deletion of a plugin instance which can happen
+// in theory.
+struct WidgetPluginData {
+ WidgetPluginData(const QString &p = QString());
+
+ QString path;
+ bool failed;
+ QString errorMessage;
+ QWeakPointer<QObject> instanceGuard;
+ IWidgetPlugin *instance;
+};
+
+
+// PluginPath: Manages a plugin directory. It does nothing
+// on construction following the "as lazy as possible" principle.
+// In the "loaded" stage, it scans the directories and creates
+// a list of PluginData for the libraries found.
+// getInstances() will return the fully initialized list of
+// IPlugins.
+
+class WidgetPluginPath {
+public:
+ explicit WidgetPluginPath(const QDir &path);
+
+
+ void getInstances(WidgetPluginManager::IWidgetPluginList *list);
+
+ QDir path() const { return m_path; }
+
+ // Convenience to populate a "About Plugin" dialog with
+ // plugins from that path. Forces initialization.
+ QStandardItem *createModelItem();
+
+private:
+ typedef QList<WidgetPluginData> PluginDataList;
+
+ static QStringList libraryFilePaths(const QDir &dir);
+ void clear();
+ void ensureLoaded();
+
+ QDir m_path;
+ bool m_loaded;
+ PluginDataList m_plugins;
+};
+
+} // namespace Internal
+} // namespace QmlDesigner
+#endif // WIDGETPLUGINPATH_H
diff --git a/src/plugins/qmldesigner/core/preview/stylemanager.cpp b/src/plugins/qmldesigner/core/preview/stylemanager.cpp
new file mode 100644
index 0000000000..de936063fb
--- /dev/null
+++ b/src/plugins/qmldesigner/core/preview/stylemanager.cpp
@@ -0,0 +1,102 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "stylemanager.h"
+#include <QStyleFactory>
+#include <QApplication>
+#include <QStyle>
+
+namespace QmlDesigner {
+
+namespace Internal {
+
+// TODO KAI: REMOVE THIS CLASS
+
+//### if we use this pattern often: make a template out of this!
+class StyleManagerGuard { //This guard destroys the singleton in its destructor
+public: //This should avoid that a memory leak is reported
+ ~StyleManagerGuard() {
+ if (StyleManager::m_instance != 0)
+ delete StyleManager::m_instance;
+ }
+};
+} //namespace Internal
+
+StyleManager* StyleManager::m_instance = 0;
+
+void StyleManager::addView(NodeInstanceView* view)
+{
+ instance()->m_views.append(view);
+}
+
+void StyleManager::removeView(NodeInstanceView* view)
+{
+ instance()->m_views.removeAll(view);
+}
+
+QStringList StyleManager::styles()
+{
+ return QStyleFactory::keys();
+}
+
+void StyleManager::setStyle(const QString &styleName)
+{
+ QStyle *style = QStyleFactory::create(styleName);
+ if (style) {
+ foreach (NodeInstanceView* view, instance()->m_views)
+ view->setStyle(style);
+ }
+}
+
+StyleManager* StyleManager::instance()
+{
+ static Internal::StyleManagerGuard guard; //The destructor destroys the singleton. See above
+ if (m_instance == 0)
+ m_instance = new StyleManager();
+ return m_instance;
+}
+
+QString StyleManager::applicationStyle()
+{
+ QStyle *applicationStyle = qApp->style();
+ QStyle *style;
+ if (applicationStyle)
+ foreach(const QString &name, styles())
+ if ((style = QStyleFactory::create(name)) &&
+ (applicationStyle->metaObject()->className() ==
+ style->metaObject()->className()))
+ return name;
+ return QString();
+}
+
+
+
+
+
+} //namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/core/rewritertransaction.cpp b/src/plugins/qmldesigner/core/rewritertransaction.cpp
new file mode 100644
index 0000000000..6139c4c71f
--- /dev/null
+++ b/src/plugins/qmldesigner/core/rewritertransaction.cpp
@@ -0,0 +1,91 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "rewritertransaction.h"
+#include <abstractview.h>
+
+namespace QmlDesigner {
+
+
+RewriterTransaction::RewriterTransaction() : m_valid(false)
+{
+}
+
+RewriterTransaction::RewriterTransaction(AbstractView *_view) : m_view(_view), m_valid(true)
+{
+ Q_ASSERT(view());
+ view()->emitCustomNotification("__start rewriter transaction__");
+}
+
+RewriterTransaction::~RewriterTransaction()
+{
+ commit();
+}
+
+bool RewriterTransaction::isValid() const
+{
+ return m_valid;
+}
+
+void RewriterTransaction::commit()
+{
+ if (m_valid) {
+ m_valid = false;
+ view()->emitCustomNotification("__end rewriter transaction__");
+ }
+}
+
+AbstractView *RewriterTransaction::view()
+{
+ return m_view.data();
+}
+
+RewriterTransaction::RewriterTransaction(const RewriterTransaction &other)
+ : m_valid(false)
+{
+ if (&other != this) {
+ m_valid = other.m_valid;
+ m_view = other.m_view;
+ other.m_valid = false;
+ }
+}
+
+RewriterTransaction& RewriterTransaction::operator=(const RewriterTransaction &other)
+{
+ if (!m_valid && (&other != this)) {
+ m_valid = other.m_valid;
+ m_view = other.m_view;
+ other.m_valid = false;
+ }
+
+ return *this;
+}
+
+} //QmlDesigner
+
diff --git a/src/plugins/qmldesigner/core/rewritertransaction.h b/src/plugins/qmldesigner/core/rewritertransaction.h
new file mode 100644
index 0000000000..0e535db1a5
--- /dev/null
+++ b/src/plugins/qmldesigner/core/rewritertransaction.h
@@ -0,0 +1,60 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef REWRITERTRANSACTION_H
+#define REWRITERTRANSACTION_H
+
+#include <QWeakPointer>
+
+namespace QmlDesigner {
+
+class AbstractView;
+
+class RewriterTransaction
+{
+public:
+ RewriterTransaction();
+ RewriterTransaction(AbstractView *view);
+ ~RewriterTransaction();
+ void commit();
+ RewriterTransaction(const RewriterTransaction &other);
+ RewriterTransaction& operator=(const RewriterTransaction &other);
+
+ bool isValid() const;
+
+protected:
+ AbstractView *view();
+private:
+ QWeakPointer<AbstractView> m_view;
+ mutable bool m_valid;
+};
+
+} //QmlDesigner
+
+#endif // REWRITERTRANSACTION_H
diff --git a/src/plugins/qmldesigner/designmode.cpp b/src/plugins/qmldesigner/designmode.cpp
new file mode 100644
index 0000000000..fa1e65ce88
--- /dev/null
+++ b/src/plugins/qmldesigner/designmode.cpp
@@ -0,0 +1,287 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "designmode.h"
+#include "qmldesignerconstants.h"
+#include "designmodewidget.h"
+
+#include <coreplugin/icore.h>
+#include <coreplugin/modemanager.h>
+#include <coreplugin/uniqueidmanager.h>
+#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/editormanager/openeditorsmodel.h>
+#include <coreplugin/actionmanager/actionmanager.h>
+#include <coreplugin/actionmanager/command.h>
+#include <coreplugin/coreconstants.h>
+
+#include <extensionsystem/pluginmanager.h>
+
+#include <QAction>
+#include <QDebug>
+#include <QPlainTextEdit>
+#include <QFileInfo>
+
+namespace QmlDesigner {
+namespace Internal {
+
+enum {
+ debug = false
+};
+
+DesignModeCoreListener::DesignModeCoreListener(DesignMode *mode) :
+ m_mode(mode)
+{
+}
+
+bool DesignModeCoreListener::coreAboutToClose()
+{
+ // make sure settings are stored before actual program exit
+ m_mode->currentEditorChanged(0);
+ return true;
+}
+
+DesignMode::DesignMode() :
+ IMode(),
+ m_mainWidget(new DesignModeWidget(this)),
+ m_coreListener(new DesignModeCoreListener(this)),
+ m_isActive(false),
+ m_revertToSavedAction(new QAction(this)),
+ m_saveAction(new QAction(this)),
+ m_saveAsAction(new QAction(this)),
+ m_closeCurrentEditorAction(new QAction(this)),
+ m_closeAllEditorsAction(new QAction(this)),
+ m_closeOtherEditorsAction(new QAction(this))
+{
+ Core::ICore *creatorCore = Core::ICore::instance();
+ Core::ModeManager *modeManager = creatorCore->modeManager();
+
+ connect(modeManager, SIGNAL(currentModeChanged(Core::IMode*)),
+ this, SLOT(modeChanged(Core::IMode*)));
+
+ ExtensionSystem::PluginManager::instance()->addObject(m_coreListener);
+
+ Core::ActionManager *actionManager = creatorCore->actionManager();
+ Core::EditorManager *editorManager = creatorCore->editorManager();
+
+ // Undo / Redo
+ actionManager->registerAction(m_mainWidget->undoAction(), Core::Constants::UNDO, context());
+ actionManager->registerAction(m_mainWidget->redoAction(), Core::Constants::REDO, context());
+
+ // Revert to saved
+ actionManager->registerAction(m_revertToSavedAction,
+ Core::Constants::REVERTTOSAVED, context());
+ connect(m_revertToSavedAction, SIGNAL(triggered()), editorManager, SLOT(revertToSaved()));
+
+ //Save
+ actionManager->registerAction(m_saveAction, Core::Constants::SAVE, context());
+ connect(m_saveAction, SIGNAL(triggered()), editorManager, SLOT(saveFile()));
+
+ //Save As
+ actionManager->registerAction(m_saveAsAction, Core::Constants::SAVEAS, context());
+ connect(m_saveAsAction, SIGNAL(triggered()), editorManager, SLOT(saveFileAs()));
+
+ //Close Editor
+ actionManager->registerAction(m_closeCurrentEditorAction, Core::Constants::CLOSE, context());
+ connect(m_closeCurrentEditorAction, SIGNAL(triggered()), editorManager, SLOT(closeEditor()));
+
+ //Close All
+ actionManager->registerAction(m_closeAllEditorsAction, Core::Constants::CLOSEALL, context());
+ connect(m_closeAllEditorsAction, SIGNAL(triggered()), editorManager, SLOT(closeAllEditors()));
+
+ //Close All Others Action
+ actionManager->registerAction(m_closeOtherEditorsAction, Core::Constants::CLOSEOTHERS, context());
+ connect(m_closeOtherEditorsAction, SIGNAL(triggered()), editorManager, SLOT(closeOtherEditors()));
+
+ connect(editorManager, SIGNAL(currentEditorChanged(Core::IEditor*)),
+ this, SLOT(currentEditorChanged(Core::IEditor*)));
+ connect(editorManager, SIGNAL(editorsClosed(QList<Core::IEditor*>)),
+ this, SLOT(textEditorsClosed(QList<Core::IEditor*>)));
+
+ Core::ActionContainer *editMenu = actionManager->actionContainer(Core::Constants::M_EDIT);
+
+ Core::Command *command;
+ command = actionManager->registerAction(m_mainWidget->deleteAction(),
+ QmlDesigner::Constants::DELETE, context());
+ command->setDefaultKeySequence(QKeySequence::Delete);
+ command->setAttribute(Core::Command::CA_Hide); // don't show delete in other modes
+ editMenu->addAction(command, Core::Constants::G_EDIT_COPYPASTE);
+
+ command = actionManager->registerAction(m_mainWidget->cutAction(),
+ Core::Constants::CUT, context());
+ command->setDefaultKeySequence(QKeySequence::Cut);
+ editMenu->addAction(command, Core::Constants::G_EDIT_COPYPASTE);
+
+ command = actionManager->registerAction(m_mainWidget->copyAction(),
+ Core::Constants::COPY, context());
+ command->setDefaultKeySequence(QKeySequence::Copy);
+ editMenu->addAction(command, Core::Constants::G_EDIT_COPYPASTE);
+
+ command = actionManager->registerAction(m_mainWidget->pasteAction(),
+ Core::Constants::PASTE, context());
+ command->setDefaultKeySequence(QKeySequence::Paste);
+ editMenu->addAction(command, Core::Constants::G_EDIT_COPYPASTE);
+
+ // add second shortcut to trigger delete
+ QAction *deleteAction = new QAction(m_mainWidget);
+ deleteAction->setShortcut(QKeySequence(QLatin1String("Backspace")));
+ connect(deleteAction, SIGNAL(triggered()), m_mainWidget->deleteAction(),
+ SIGNAL(triggered()));
+
+ m_mainWidget->addAction(deleteAction);
+
+ updateActions();
+}
+
+DesignMode::~DesignMode()
+{
+ delete m_mainWidget;
+ ExtensionSystem::PluginManager::instance()->removeObject(m_coreListener);
+ delete m_coreListener;
+}
+
+QList<int> DesignMode::context() const
+{
+ static QList<int> contexts = QList<int>() <<
+ Core::UniqueIDManager::instance()->uniqueIdentifier(Constants::C_DESIGN_MODE);
+ return contexts;
+}
+
+QWidget *DesignMode::widget()
+{
+ return m_mainWidget;
+}
+
+QString DesignMode::name() const
+{
+ return tr(Constants::DESIGN_MODE_NAME);
+}
+
+QIcon DesignMode::icon() const
+{
+ return QIcon(QLatin1String(":/qmldesigner/images/mode_Design.png"));
+}
+
+int DesignMode::priority() const
+{
+ return Constants::DESIGN_MODE_PRIORITY;
+}
+
+const char *DesignMode::uniqueModeName() const
+{
+ return Constants::DESIGN_MODE_NAME;
+}
+
+void DesignMode::textEditorsClosed(QList<Core::IEditor*> editors)
+{
+ m_mainWidget->closeEditors(editors);
+}
+
+void DesignMode::modeChanged(Core::IMode *mode)
+{
+ if (debug)
+ qDebug() << Q_FUNC_INFO << ((mode == this) ? "Design mode" : "other mode");
+ if (mode == this) {
+ m_isActive = true;
+ m_mainWidget->showEditor(m_currentEditor.data());
+ } else {
+ if (m_isActive) {
+ m_isActive = false;
+// m_mainWidget->showEditor(0);
+ }
+ }
+}
+
+void DesignMode::currentEditorChanged(Core::IEditor *editor)
+{
+ if (debug)
+ qDebug() << Q_FUNC_INFO << editor;
+
+ if (m_currentEditor.data() == editor)
+ return;
+
+ if (m_currentEditor)
+ disconnect(m_currentEditor.data(), SIGNAL(changed()), this, SLOT(updateActions()));
+
+ m_currentEditor = QWeakPointer<Core::IEditor>(editor);
+
+ if (m_currentEditor)
+ connect(m_currentEditor.data(), SIGNAL(changed()), this, SLOT(updateActions()));
+
+ updateActions();
+}
+
+void DesignMode::makeCurrentEditorWritable()
+{
+ Core::ICore *creatorCore = Core::ICore::instance();
+ if (m_currentEditor)
+ creatorCore->editorManager()->makeEditorWritable(m_currentEditor.data());
+}
+
+// copied from EditorManager::updateActions
+void DesignMode::updateActions()
+{
+ Core::ICore *creatorCore = Core::ICore::instance();
+ Core::EditorManager *editorManager = creatorCore->editorManager();
+
+ Core::IEditor *curEditor = m_currentEditor.data();
+ int openedCount = editorManager->openedEditors().count()
+ + editorManager->openedEditorsModel()->restoredEditorCount();
+
+ QString fName;
+ if (curEditor) {
+ if (!curEditor->file()->fileName().isEmpty()) {
+ QFileInfo fi(curEditor->file()->fileName());
+ fName = fi.fileName();
+ } else {
+ fName = curEditor->displayName();
+ }
+ }
+
+ m_saveAction->setEnabled(curEditor != 0 && curEditor->file()->isModified());
+ m_saveAsAction->setEnabled(curEditor != 0 && curEditor->file()->isSaveAsAllowed());
+ m_revertToSavedAction->setEnabled(curEditor != 0
+ && !curEditor->file()->fileName().isEmpty()
+ && curEditor->file()->isModified());
+
+ QString quotedName;
+ if (!fName.isEmpty())
+ quotedName = '"' + fName + '"';
+ m_saveAsAction->setText(tr("Save %1 As...").arg(quotedName));
+ m_saveAction->setText(tr("&Save %1").arg(quotedName));
+ m_revertToSavedAction->setText(tr("Revert %1 to Saved").arg(quotedName));
+
+ m_closeCurrentEditorAction->setEnabled(curEditor != 0);
+ m_closeCurrentEditorAction->setText(tr("Close %1").arg(quotedName));
+ m_closeAllEditorsAction->setEnabled(openedCount > 0);
+ m_closeOtherEditorsAction->setEnabled(openedCount > 1);
+ m_closeOtherEditorsAction->setText((openedCount > 1 ? tr("Close All Except %1").arg(quotedName) : tr("Close Others")));
+}
+
+} // namespace Internal
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designmode.h b/src/plugins/qmldesigner/designmode.h
new file mode 100644
index 0000000000..08fea33b2b
--- /dev/null
+++ b/src/plugins/qmldesigner/designmode.h
@@ -0,0 +1,101 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef DESIGNMODE_H
+#define DESIGNMODE_H
+
+#include <coreplugin/imode.h>
+#include <coreplugin/icorelistener.h>
+#include <coreplugin/editormanager/ieditor.h>
+
+#include <QWeakPointer>
+
+class QAction;
+
+namespace QmlDesigner {
+namespace Internal {
+
+class DesignMode;
+class DesignModeWidget;
+
+class DesignModeCoreListener : public Core::ICoreListener
+{
+ Q_OBJECT
+public:
+ DesignModeCoreListener(DesignMode* mode);
+ bool coreAboutToClose();
+private:
+ DesignMode *m_mode;
+};
+
+class DesignMode : public Core::IMode
+{
+ Q_OBJECT
+
+public:
+ DesignMode();
+ ~DesignMode();
+
+ // IContext
+ QList<int> context() const;
+ QWidget *widget();
+
+ // IMode
+ QString name() const;
+ QIcon icon() const;
+ int priority() const;
+ const char *uniqueModeName() const;
+
+private slots:
+ void textEditorsClosed(QList<Core::IEditor *> editors);
+ void modeChanged(Core::IMode *mode);
+ void currentEditorChanged(Core::IEditor *editor);
+ void makeCurrentEditorWritable();
+ void updateActions();
+
+private:
+ DesignModeWidget *m_mainWidget;
+ DesignModeCoreListener *m_coreListener;
+ QWeakPointer<Core::IEditor> m_currentEditor;
+ bool m_isActive;
+
+ QAction *m_revertToSavedAction;
+ QAction *m_saveAction;
+ QAction *m_saveAsAction;
+ QAction *m_closeCurrentEditorAction;
+ QAction *m_closeAllEditorsAction;
+ QAction *m_closeOtherEditorsAction;
+
+ friend class DesignModeCoreListener;
+};
+
+} // namespace Internal
+} // namespace QmlDesigner
+
+#endif // DESIGNMODE_H
diff --git a/src/plugins/qmldesigner/designmodewidget.cpp b/src/plugins/qmldesigner/designmodewidget.cpp
new file mode 100644
index 0000000000..51c4c53981
--- /dev/null
+++ b/src/plugins/qmldesigner/designmodewidget.cpp
@@ -0,0 +1,675 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "designmodewidget.h"
+#include "designmode.h"
+#include "qmldesignerconstants.h"
+
+#include <model.h>
+#include <rewriterview.h>
+
+#include <coreplugin/icore.h>
+#include <coreplugin/minisplitter.h>
+#include <coreplugin/sidebar.h>
+#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/editormanager/openeditorsmodel.h>
+#include <coreplugin/editormanager/ieditor.h>
+#include <coreplugin/modemanager.h>
+
+#include <utils/parameteraction.h>
+#include <utils/qtcassert.h>
+
+#include <QtCore/QSettings>
+#include <QtCore/QEvent>
+#include <QtCore/QDir>
+#include <QtGui/QApplication>
+#include <QtGui/QPlainTextEdit>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QScrollArea>
+#include <QtGui/QTabWidget>
+#include <QtGui/QToolButton>
+#include <QtGui/QMenu>
+#include <QtGui/QClipboard>
+#include <QtGui/QLabel>
+
+using Core::MiniSplitter;
+using Core::IEditor;
+using Core::EditorManager;
+
+using namespace QmlDesigner;
+
+Q_DECLARE_METATYPE(Core::IEditor*)
+
+enum {
+ debug = false
+};
+
+namespace QmlDesigner {
+namespace Internal {
+
+/*!
+ Mimic the look of the text editor toolbar as defined in e.g. EditorView::EditorView
+ */
+DocumentToolBar::DocumentToolBar(DocumentWidget *documentWidget, DesignModeWidget *mainWidget, QWidget *parent) :
+ QWidget(parent),
+ m_mainWidget(mainWidget),
+ m_documentWidget(documentWidget),
+ m_editorList(new QComboBox),
+ m_closeButton(new QToolButton),
+ m_lockButton(new QToolButton)
+{
+ Core::ICore *core = Core::ICore::instance();
+
+ setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
+
+ m_editorsListModel = core->editorManager()->openedEditorsModel();
+
+ // copied from EditorView::EditorView
+ m_editorList->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ m_editorList->setMinimumContentsLength(20);
+ m_editorList->setModel(m_editorsListModel);
+ m_editorList->setMaxVisibleItems(40);
+ m_editorList->setContextMenuPolicy(Qt::CustomContextMenu);
+ m_editorList->setCurrentIndex(m_editorsListModel->indexOf(documentWidget->textEditor()).row());
+
+ QToolBar *editorListToolBar = new QToolBar;
+ editorListToolBar->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Ignored);
+ editorListToolBar->addWidget(m_editorList);
+
+ QToolBar *designToolBar = new QToolBar;
+ designToolBar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Ignored);
+
+ m_lockButton->setAutoRaise(true);
+ m_lockButton->setProperty("type", QLatin1String("dockbutton"));
+
+ m_closeButton->setAutoRaise(true);
+ m_closeButton->setIcon(QIcon(":/core/images/closebutton.png"));
+ m_closeButton->setProperty("type", QLatin1String("dockbutton"));
+
+ QToolBar *rightToolBar = new QToolBar;
+ rightToolBar->setLayoutDirection(Qt::RightToLeft);
+ rightToolBar->addWidget(m_closeButton);
+ rightToolBar->addWidget(m_lockButton);
+
+ QHBoxLayout *toplayout = new QHBoxLayout(this);
+ toplayout->setSpacing(0);
+ toplayout->setMargin(0);
+
+ toplayout->addWidget(editorListToolBar);
+ toplayout->addWidget(designToolBar);
+ toplayout->addWidget(rightToolBar);
+
+ connect(m_editorList, SIGNAL(activated(int)), this, SLOT(listSelectionActivated(int)));
+ connect(m_editorList, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(listContextMenu(QPoint)));
+ connect(m_lockButton, SIGNAL(clicked()), this, SLOT(makeEditorWritable()));
+ connect(m_closeButton, SIGNAL(clicked()), this, SLOT(close()));
+
+ connect(m_documentWidget->textEditor(), SIGNAL(changed()), this, SLOT(updateEditorStatus()));
+
+ updateEditorStatus();
+}
+
+void DocumentToolBar::close()
+{
+ Core::ICore::instance()->editorManager()->closeEditors(QList<IEditor*>() << m_documentWidget->textEditor());
+}
+
+void DocumentToolBar::listSelectionActivated(int row)
+{
+ EditorManager *em = Core::ICore::instance()->editorManager();
+ QAbstractItemModel *model = m_editorList->model();
+
+ const QModelIndex modelIndex = model->index(row, 0);
+ IEditor *editor = model->data(modelIndex, Qt::UserRole).value<IEditor*>();
+ if (editor) {
+ em->activateEditor(editor, EditorManager::NoModeSwitch);
+ } else {
+ QString fileName = model->data(modelIndex, Qt::UserRole + 1).toString();
+ QByteArray kind = model->data(modelIndex, Qt::UserRole + 2).toByteArray();
+ editor = em->openEditor(fileName, kind, EditorManager::NoModeSwitch);
+ }
+ if (editor) {
+ m_mainWidget->showEditor(editor);
+ m_editorList->setCurrentIndex(m_editorsListModel->indexOf(m_documentWidget->textEditor()).row());
+ }
+}
+
+void DocumentToolBar::listContextMenu(QPoint pos)
+{
+ QModelIndex index = m_editorsListModel->index(m_editorList->currentIndex(), 0);
+ QString fileName = m_editorsListModel->data(index, Qt::UserRole + 1).toString();
+ if (fileName.isEmpty())
+ return;
+ QMenu menu;
+ menu.addAction(tr("Copy full path to clipboard"));
+ if (menu.exec(m_editorList->mapToGlobal(pos))) {
+ QApplication::clipboard()->setText(fileName);
+ }
+}
+
+void DocumentToolBar::makeEditorWritable()
+{
+ Core::ICore::instance()->editorManager()->makeEditorWritable(m_documentWidget->textEditor());
+}
+
+void DocumentToolBar::updateEditorStatus()
+{
+ Core::IEditor *editor = m_documentWidget->textEditor();
+
+ static const QIcon lockedIcon(QLatin1String(":/core/images/locked.png"));
+ static const QIcon unlockedIcon(QLatin1String(":/core/images/unlocked.png"));
+
+ if (editor->file()->isReadOnly()) {
+ m_lockButton->setIcon(lockedIcon);
+ m_lockButton->setEnabled(!editor->file()->fileName().isEmpty());
+ m_lockButton->setToolTip(tr("Make writable"));
+ } else {
+ m_lockButton->setIcon(unlockedIcon);
+ m_lockButton->setEnabled(false);
+ m_lockButton->setToolTip(tr("File is writable"));
+ }
+ m_editorList->setToolTip(
+ editor->file()->fileName().isEmpty()
+ ? editor->displayName()
+ : QDir::toNativeSeparators(editor->file()->fileName())
+ );
+}
+
+DocumentWarningWidget::DocumentWarningWidget(DocumentWidget *documentWidget, QWidget *parent) :
+ QFrame(parent),
+ m_errorMessage(new QLabel("Placeholder", this)),
+ m_goToError(new QLabel(this)),
+ m_documentWidget(documentWidget)
+{
+ setFrameStyle(QFrame::Panel | QFrame::Raised);
+ setLineWidth(1);
+ setForegroundRole(QPalette::ToolTipText);
+ setBackgroundRole(QPalette::ToolTipBase);
+ setAutoFillBackground(true);
+
+ m_errorMessage->setForegroundRole(QPalette::ToolTipText);
+ m_goToError->setText(tr("<a href=\"goToError\">Go to error</a>"));
+ m_goToError->setForegroundRole(QPalette::Link);
+ connect(m_goToError, SIGNAL(linkActivated(QString)), this, SLOT(goToError()));
+
+ QVBoxLayout *layout = new QVBoxLayout(this);
+ layout->setMargin(20);
+ layout->setSpacing(5);
+ layout->addWidget(m_errorMessage);
+ layout->addWidget(m_goToError, 1, Qt::AlignRight);
+}
+
+void DocumentWarningWidget::setError(const RewriterView::Error &error)
+{
+ m_error = error;
+ QString str = tr("%3 (%1:%2)").arg(QString::number(error.line()), QString::number(error.column()), error.description());
+
+ m_errorMessage->setText(str);
+ resize(layout()->totalSizeHint());
+}
+
+void DocumentWarningWidget::goToError()
+{
+ m_documentWidget->textEditor()->gotoLine(m_error.line(), m_error.column());
+ Core::EditorManager::instance()->ensureEditorManagerVisible();
+}
+
+DocumentWidget::DocumentWidget(TextEditor::ITextEditor *textEditor, QPlainTextEdit *textEdit, QmlDesigner::DesignDocumentController *document, DesignModeWidget *mainWidget) :
+ QWidget(),
+ m_textEditor(textEditor),
+ m_textBuffer(textEdit),
+ m_document(document),
+ m_mainWidget(mainWidget),
+ m_mainSplitter(0),
+ m_leftSideBar(0),
+ m_rightSideBar(0),
+ m_isDisabled(false),
+ m_warningWidget(0)
+{
+ setup();
+}
+
+DocumentWidget::~DocumentWidget()
+{
+ // Make sure component widgets are deleted first in SideBarItem::~SideBarItem
+ // before the DesignDocumentController runs (and deletes them again).
+ m_document->deleteLater();
+}
+
+QmlDesigner::DesignDocumentController *DocumentWidget::document() const
+{
+ return m_document;
+}
+
+TextEditor::ITextEditor *DocumentWidget::textEditor() const
+{
+ return m_textEditor;
+}
+
+void DocumentWidget::setAutoSynchronization(bool sync)
+{
+ if (debug)
+ qDebug() << Q_FUNC_INFO << sync;
+
+ document()->blockModelSync(!sync);
+
+ if (sync) {
+ // text editor -> visual editor
+ if (!m_document->model()) {
+ QList<RewriterView::Error> errors = m_document->loadMaster(m_textBuffer.data());
+ if (!errors.isEmpty()) {
+ disable(errors);
+ } else {
+ connect(m_document, SIGNAL(qmlErrorsChanged(QList<RewriterView::Error>)),
+ this, SLOT(updateErrorStatus(QList<RewriterView::Error>)));
+ }
+ }
+ if (m_document->model() && m_document->qmlErrors().isEmpty()) {
+ // set selection to text cursor
+ RewriterView *rewriter = m_document->rewriterView();
+ const int cursorPos = m_textBuffer->textCursor().position();
+ ModelNode node = nodeForPosition(cursorPos);
+ if (node.isValid()) {
+ rewriter->setSelectedModelNodes(QList<ModelNode>() << node);
+ }
+ }
+ } else {
+ if (m_document->model() && m_document->qmlErrors().isEmpty()) {
+ RewriterView *rewriter = m_document->rewriterView();
+ // visual editor -> text editor
+ ModelNode selectedNode;
+ if (!rewriter->selectedModelNodes().isEmpty())
+ selectedNode = rewriter->selectedModelNodes().first();
+
+ if (selectedNode.isValid()) {
+ int nodeOffset = rewriter->nodeOffset(selectedNode);
+ QTextCursor editTextCursor = m_textBuffer->textCursor();
+ if (nodeOffset > 0
+ && nodeForPosition(editTextCursor.position()) != selectedNode) {
+ if (debug)
+ qDebug() << "Moving text cursor to " << nodeOffset;
+ editTextCursor.setPosition(nodeOffset);
+ m_textBuffer->setTextCursor(editTextCursor);
+ }
+ }
+ }
+ }
+}
+
+void DocumentWidget::enable()
+{
+ if (debug)
+ qDebug() << Q_FUNC_INFO;
+ m_warningWidget->setVisible(false);
+ m_document->documentWidget()->setEnabled(true);
+ m_leftSideBar->setEnabled(true);
+ m_rightSideBar->setEnabled(true);
+ m_isDisabled = false;
+}
+
+void DocumentWidget::disable(const QList<RewriterView::Error> &errors)
+{
+ if (debug)
+ qDebug() << Q_FUNC_INFO;
+ Q_ASSERT(!errors.isEmpty());
+ m_warningWidget->setError(errors.first());
+ m_warningWidget->setVisible(true);
+ m_document->documentWidget()->setEnabled(false);
+ m_leftSideBar->setEnabled(false);
+ m_rightSideBar->setEnabled(false);
+ m_isDisabled = true;
+}
+
+void DocumentWidget::updateErrorStatus(const QList<RewriterView::Error> &errors)
+{
+ if (m_isDisabled && errors.isEmpty()) {
+ enable();
+ } else if (!m_isDisabled && !errors.isEmpty()) {
+ disable(errors);
+ }
+}
+
+void DocumentWidget::readSettings()
+{
+ QSettings *settings = Core::ICore::instance()->settings();
+
+ settings->beginGroup("Bauhaus");
+ m_leftSideBar->readSettings(settings, QLatin1String("LeftSideBar"));
+ m_rightSideBar->readSettings(settings, QLatin1String("RightSideBar"));
+ if (settings->contains("MainSplitter")) {
+ const QByteArray splitterState = settings->value("MainSplitter").toByteArray();
+ m_mainSplitter->restoreState(splitterState);
+ }
+ settings->endGroup();
+}
+
+void DocumentWidget::saveSettings()
+{
+ QSettings *settings = Core::ICore::instance()->settings();
+
+ settings->beginGroup("Bauhaus");
+ m_leftSideBar->saveSettings(settings, QLatin1String("LeftSideBar"));
+ m_rightSideBar->saveSettings(settings, QLatin1String("RightSideBar"));
+ settings->setValue("MainSplitter", m_mainSplitter->saveState());
+ settings->endGroup();
+}
+
+
+void DocumentWidget::resizeEvent(QResizeEvent *event)
+{
+ m_warningWidget->move(QPoint(event->size().width() / 2,
+ event->size().height() / 2));
+ QWidget::resizeEvent(event);
+}
+
+void DocumentWidget::setup()
+{
+ m_mainSplitter = new MiniSplitter(this);
+ m_mainSplitter->setObjectName("mainSplitter");
+
+ // warning frame should be not in layout, but still child of the widget
+ m_warningWidget = new DocumentWarningWidget(this, this);
+ m_warningWidget->setVisible(false);
+
+ // Left area:
+ Core::SideBarItem *navigatorItem = new Core::SideBarItem(m_document->navigator());
+ Core::SideBarItem *libraryItem = new Core::SideBarItem(m_document->itemLibrary());
+ Core::SideBarItem *propertiesItem = new Core::SideBarItem(m_document->allPropertiesBox());
+
+ QList<Core::SideBarItem*> leftSideBarItems, rightSideBarItems;
+ leftSideBarItems << navigatorItem << libraryItem;
+ rightSideBarItems << propertiesItem;
+
+ m_leftSideBar = new Core::SideBar(leftSideBarItems, QList<Core::SideBarItem*>() << navigatorItem << libraryItem);
+ m_rightSideBar = new Core::SideBar(rightSideBarItems, QList<Core::SideBarItem*>() << propertiesItem);
+
+ // right area:
+ QWidget *centerWidget = new QWidget;
+ {
+ QVBoxLayout *rightLayout = new QVBoxLayout(centerWidget);
+ rightLayout->setMargin(0);
+ rightLayout->setSpacing(0);
+ rightLayout->addWidget(new DocumentToolBar(this, m_mainWidget));
+ rightLayout->addWidget(m_document->statesEditorWidget());
+ rightLayout->addWidget(m_document->documentWidget());
+ }
+
+ // m_mainSplitter area:
+ m_mainSplitter->addWidget(m_leftSideBar);
+ m_mainSplitter->addWidget(centerWidget);
+ m_mainSplitter->addWidget(m_rightSideBar);
+
+ // Finishing touches:
+ m_mainSplitter->setOpaqueResize(false);
+ m_mainSplitter->setStretchFactor(1, 1);
+ m_mainSplitter->setSizes(QList<int>() << 150 << 300 << 150);
+
+ QLayout *mainLayout = new QBoxLayout(QBoxLayout::RightToLeft, this);
+ mainLayout->setMargin(0);
+ mainLayout->setSpacing(0);
+ mainLayout->addWidget(m_mainSplitter);
+}
+
+bool DocumentWidget::isInNodeDefinition(int nodeOffset, int nodeLength, int cursorPos) const {
+ return (nodeOffset <= cursorPos) && (nodeOffset + nodeLength > cursorPos);
+}
+
+ModelNode DocumentWidget::nodeForPosition(int cursorPos) const
+{
+ RewriterView *rewriter = m_document->rewriterView();
+ QList<ModelNode> nodes = rewriter->allModelNodes();
+
+ ModelNode bestNode;
+ int bestNodeOffset = -1;
+
+ foreach (const ModelNode &node, nodes) {
+ const int nodeOffset = rewriter->nodeOffset(node);
+ const int nodeLength = rewriter->nodeLength(node);
+ if (isInNodeDefinition(nodeOffset, nodeLength, cursorPos)
+ && (nodeOffset > bestNodeOffset)) {
+ bestNode = node;
+ bestNodeOffset = nodeOffset;
+ }
+ }
+
+ return bestNode;
+}
+
+// ---------- DesignModeWidget
+DesignModeWidget::DesignModeWidget(DesignMode *designMode, QWidget *parent) :
+ QWidget(parent),
+ m_designMode(designMode),
+ m_documentWidgetStack(new QStackedWidget),
+ m_currentDocumentWidget(0),
+ m_currentTextEdit(0),
+ m_syncWithTextEdit(false)
+{
+ QVBoxLayout *layout = new QVBoxLayout(this);
+ layout->setMargin(0);
+ layout->addWidget(m_documentWidgetStack);
+
+ m_undoAction = new QAction(tr("&Undo"), this);
+ connect(m_undoAction, SIGNAL(triggered()), this, SLOT(undo()));
+ m_redoAction = new QAction(tr("&Redo"), this);
+ connect(m_redoAction, SIGNAL(triggered()), this, SLOT(redo()));
+ m_deleteAction = new Utils::ParameterAction(tr("Delete"), tr("Delete \"%1\""), Utils::ParameterAction::EnabledWithParameter, this);
+ connect(m_deleteAction, SIGNAL(triggered()), this, SLOT(deleteSelected()));
+ m_cutAction = new Utils::ParameterAction(tr("Cu&t"), tr("Cut \"%1\""), Utils::ParameterAction::EnabledWithParameter, this);
+ connect(m_cutAction, SIGNAL(triggered()), this, SLOT(cutSelected()));
+ m_copyAction = new Utils::ParameterAction(tr("&Copy"), tr("Copy \"%1\""), Utils::ParameterAction::EnabledWithParameter, this);
+ connect(m_copyAction, SIGNAL(triggered()), this, SLOT(copySelected()));
+ m_pasteAction = new Utils::ParameterAction(tr("&Paste"), tr("Paste \"%1\""), Utils::ParameterAction::EnabledWithParameter, this);
+ connect(m_pasteAction, SIGNAL(triggered()), this, SLOT(paste()));
+
+ QLabel *defaultBackground = new QLabel(tr("Open/Create a qml file first."));
+ defaultBackground->setAlignment(Qt::AlignCenter);
+
+ m_documentWidgetStack->addWidget(defaultBackground);
+}
+
+DesignModeWidget::~DesignModeWidget()
+{
+};
+
+void DesignModeWidget::showEditor(Core::IEditor *editor)
+{
+ QString fileName;
+ QPlainTextEdit *textEdit = 0;
+ TextEditor::ITextEditor *textEditor = 0;
+
+ if (editor) {
+ fileName = editor->file()->fileName();
+ textEdit = qobject_cast<QPlainTextEdit*>(editor->widget());
+ textEditor = qobject_cast<TextEditor::ITextEditor*>(editor);
+ }
+
+ if (debug)
+ qDebug() << Q_FUNC_INFO << fileName;
+
+ m_currentTextEdit = textEdit;
+ DocumentWidget *documentWidget = 0;
+
+ if (textEdit && textEditor && fileName.endsWith(".qml")) {
+ if (m_documentHash.contains(textEdit)) {
+ documentWidget = m_documentHash.value(textEdit);
+ documentWidget->setAutoSynchronization(true);
+ } else {
+ DesignDocumentController *newDocument = new DesignDocumentController(0);
+ newDocument->setFileName(fileName);
+
+ documentWidget = new DocumentWidget(textEditor, textEdit, newDocument, this);
+ connect(documentWidget->document(), SIGNAL(undoAvailable(bool)),
+ this, SLOT
+(undoAvailable(bool)));
+ connect(documentWidget->document(), SIGNAL(redoAvailable(bool)),
+ this, SLOT(redoAvailable(bool)));
+// connect(documentWidget->document(), SIGNAL(deleteAvailable(bool)),
+// this, SLOT(deleteAvailable(bool)));
+
+ m_documentHash.insert(textEdit, documentWidget);
+ m_documentWidgetStack->addWidget(documentWidget);
+ }
+ }
+
+ setCurrentDocumentWidget(documentWidget);
+}
+
+void DesignModeWidget::closeEditors(QList<Core::IEditor*> editors)
+{
+ foreach (Core::IEditor* editor, editors) {
+ if (QPlainTextEdit *textEdit = qobject_cast<QPlainTextEdit*>(editor->widget())) {
+ if (m_currentTextEdit == textEdit) {
+ setCurrentDocumentWidget(0);
+ }
+ if (m_documentHash.contains(textEdit)) {
+ if (debug)
+ qDebug() << Q_FUNC_INFO << editor->file()->fileName();
+ DocumentWidget *document = m_documentHash.take(textEdit);
+ m_documentWidgetStack->removeWidget(document);
+ delete document;
+ }
+ }
+ }
+}
+
+QAction *DesignModeWidget::undoAction() const
+{
+ return m_undoAction;
+}
+
+QAction *DesignModeWidget::redoAction() const
+{
+ return m_redoAction;
+}
+
+QAction *DesignModeWidget::deleteAction() const
+{
+ return m_deleteAction;
+}
+
+QAction *DesignModeWidget::cutAction() const
+{
+ return m_cutAction;
+}
+
+QAction *DesignModeWidget::copyAction() const
+{
+ return m_copyAction;
+}
+
+QAction *DesignModeWidget::pasteAction() const
+{
+ return m_pasteAction;
+}
+
+DesignMode *DesignModeWidget::designMode() const
+{
+ return m_designMode;
+}
+
+void DesignModeWidget::undo()
+{
+ if (m_currentDocumentWidget)
+ m_currentDocumentWidget->document()->undo();
+}
+
+void DesignModeWidget::redo()
+{
+ if (m_currentDocumentWidget)
+ m_currentDocumentWidget->document()->redo();
+}
+
+void DesignModeWidget::deleteSelected()
+{
+ if (m_currentDocumentWidget)
+ m_currentDocumentWidget->document()->deleteSelected();
+}
+
+void DesignModeWidget::cutSelected()
+{
+ if (m_currentDocumentWidget)
+ m_currentDocumentWidget->document()->cutSelected();
+}
+
+void DesignModeWidget::copySelected()
+{
+ if (m_currentDocumentWidget)
+ m_currentDocumentWidget->document()->copySelected();
+}
+
+void DesignModeWidget::paste()
+{
+ if (m_currentDocumentWidget)
+ m_currentDocumentWidget->document()->paste();
+}
+
+void DesignModeWidget::undoAvailable(bool isAvailable)
+{
+ DesignDocumentController *documentController = qobject_cast<DesignDocumentController*>(sender());
+ if (m_currentDocumentWidget &&
+ m_currentDocumentWidget->document() == documentController) {
+ m_undoAction->setEnabled(isAvailable);
+ }
+}
+
+void DesignModeWidget::redoAvailable(bool isAvailable)
+{
+ DesignDocumentController *documentController = qobject_cast<DesignDocumentController*>(sender());
+ if (m_currentDocumentWidget &&
+ m_currentDocumentWidget->document() == documentController) {
+ m_redoAction->setEnabled(isAvailable);
+ }
+}
+
+void DesignModeWidget::setCurrentDocumentWidget(DocumentWidget *newDocumentWidget)
+{
+ if (debug)
+ qDebug() << Q_FUNC_INFO << newDocumentWidget;
+ if (m_currentDocumentWidget) {
+ m_currentDocumentWidget->setAutoSynchronization(false);
+ m_currentDocumentWidget->saveSettings();
+ }
+
+ m_currentDocumentWidget = newDocumentWidget;
+
+ if (m_currentDocumentWidget) {
+ m_currentDocumentWidget->setAutoSynchronization(true);
+ m_documentWidgetStack->setCurrentWidget(m_currentDocumentWidget);
+ m_currentDocumentWidget->readSettings();
+ m_undoAction->setEnabled(m_currentDocumentWidget->document()->isUndoAvailable());
+ m_redoAction->setEnabled(m_currentDocumentWidget->document()->isRedoAvailable());
+ } else {
+ m_documentWidgetStack->setCurrentIndex(0);
+ m_undoAction->setEnabled(false);
+ m_redoAction->setEnabled(false);
+ }
+}
+
+} // namespace Internal
+} // namespace Designer
diff --git a/src/plugins/qmldesigner/designmodewidget.h b/src/plugins/qmldesigner/designmodewidget.h
new file mode 100644
index 0000000000..e80fb8c1ff
--- /dev/null
+++ b/src/plugins/qmldesigner/designmodewidget.h
@@ -0,0 +1,212 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef DESIGNMODEWIDGET_H
+#define DESIGNMODEWIDGET_H
+
+#include <coreplugin/minisplitter.h>
+#include <coreplugin/editormanager/ieditor.h>
+#include <texteditor/itexteditor.h>
+
+#include <integrationcore.h>
+
+#include <allpropertiesbox.h>
+#include <designdocumentcontroller.h>
+#include <itemlibrary.h>
+#include <navigatorwidget.h>
+#include <stateseditorwidget.h>
+#include <modelnode.h>
+
+
+#include <QWeakPointer>
+#include <QmlError>
+#include <QtCore/QHash>
+#include <QtGui/QWidget>
+#include <QtGui/QToolBar>
+#include <QtGui/QComboBox>
+#include <QtGui/QLabel>
+
+class QStackedWidget;
+class QTabWidget;
+class QVBoxLayout;
+class QToolButton;
+
+namespace Core {
+ class SideBar;
+ class OpenEditorsModel;
+}
+
+namespace QmlDesigner {
+
+namespace Internal {
+
+class DesignMode;
+class DocumentWidget;
+class DesignModeWidget;
+
+class DocumentToolBar : public QWidget
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(DocumentToolBar)
+public:
+ explicit DocumentToolBar(DocumentWidget *documentWidget,
+ DesignModeWidget *mainWidget, QWidget *parent = 0);
+
+private slots:
+ void close();
+ void listSelectionActivated(int row);
+ void listContextMenu(QPoint);
+ void makeEditorWritable();
+ void updateEditorStatus();
+
+private:
+ DesignModeWidget *m_mainWidget;
+ DocumentWidget *m_documentWidget;
+ Core::OpenEditorsModel *m_editorsListModel;
+ QComboBox *m_editorList;
+ QToolButton *m_closeButton;
+ QToolButton *m_lockButton;
+};
+
+class DocumentWarningWidget : public QFrame
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(DocumentWarningWidget)
+public:
+ DocumentWarningWidget(DocumentWidget *documentWidget, QWidget *parent = 0);
+
+ void setError(const RewriterView::Error &error);
+
+private slots:
+ void goToError();
+
+private:
+ QLabel *m_errorMessage;
+ QLabel *m_goToError;
+ DocumentWidget *m_documentWidget;
+ RewriterView::Error m_error;
+};
+
+class DocumentWidget : public QWidget
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(DocumentWidget)
+public:
+ explicit DocumentWidget(TextEditor::ITextEditor *textEditor, QPlainTextEdit *textEdit, QmlDesigner::DesignDocumentController *document, DesignModeWidget *mainWidget);
+ ~DocumentWidget();
+
+ QmlDesigner::DesignDocumentController *document() const;
+ TextEditor::ITextEditor *textEditor() const;
+
+ void setAutoSynchronization(bool sync);
+
+ void readSettings();
+ void saveSettings();
+
+protected:
+ void resizeEvent(QResizeEvent *event);
+
+private slots:
+ void enable();
+ void disable(const QList<RewriterView::Error> &errors);
+ void updateErrorStatus(const QList<RewriterView::Error> &errors);
+
+private:
+ void setup();
+ bool isInNodeDefinition(int nodeOffset, int nodeLength, int cursorPos) const;
+ QmlDesigner::ModelNode nodeForPosition(int cursorPos) const;
+
+ TextEditor::ITextEditor *m_textEditor;
+ QWeakPointer<QPlainTextEdit> m_textBuffer;
+ QmlDesigner::DesignDocumentController *m_document;
+ DesignModeWidget *m_mainWidget;
+ QSplitter *m_mainSplitter;
+ Core::SideBar *m_leftSideBar;
+ Core::SideBar *m_rightSideBar;
+
+ bool m_isDisabled;
+ DocumentWarningWidget *m_warningWidget;
+};
+
+class DesignModeWidget : public QWidget
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(DesignModeWidget)
+public:
+ explicit DesignModeWidget(DesignMode *designMode, QWidget *parent = 0);
+ ~DesignModeWidget();
+
+// void syncWithTextEdit(bool sync);
+ void showEditor(Core::IEditor *editor);
+ void closeEditors(const QList<Core::IEditor*> editors);
+
+ QAction *undoAction() const;
+ QAction *redoAction() const;
+ QAction *deleteAction() const;
+ QAction *cutAction() const;
+ QAction *copyAction() const;
+ QAction *pasteAction() const;
+
+ DesignMode *designMode() const;
+
+private slots:
+ void undo();
+ void redo();
+ void deleteSelected();
+ void cutSelected();
+ void copySelected();
+ void paste();
+
+ void undoAvailable(bool isAvailable);
+ void redoAvailable(bool isAvailable);
+
+private:
+ void setCurrentDocumentWidget(DocumentWidget *newDocumentWidget);
+
+ DesignMode *m_designMode;
+
+ QStackedWidget *m_documentWidgetStack;
+ QHash<QPlainTextEdit*,DocumentWidget*> m_documentHash;
+ DocumentWidget *m_currentDocumentWidget;
+ QPlainTextEdit *m_currentTextEdit;
+
+ QAction *m_undoAction;
+ QAction *m_redoAction;
+ QAction *m_deleteAction;
+ QAction *m_cutAction;
+ QAction *m_copyAction;
+ QAction *m_pasteAction;
+
+ bool m_syncWithTextEdit;
+};
+
+} // namespace Internal
+} // namespace Designer
+
+#endif // DESIGNMODEWIDGET_H
diff --git a/src/plugins/qmldesigner/fxplugin/fx.metainfo b/src/plugins/qmldesigner/fxplugin/fx.metainfo
new file mode 100644
index 0000000000..fbc60236e2
--- /dev/null
+++ b/src/plugins/qmldesigner/fxplugin/fx.metainfo
@@ -0,0 +1,143 @@
+<metainfo>
+ <node name="Qt/Item" showInItemLibrary="true" category="QtFx" isContainer="true">
+ <propertyDefaultValue name="width" type="int" defaultValue="600"/>
+ <propertyDefaultValue name="height" type="int" defaultValue="400"/>
+ <itemlibraryrepresentation name="Item" icon=":/fxplugin/images/item-icon.png">
+ <property name="width" type="int" value="200"/>
+ <property name="height" type="int" value="200"/>
+ </itemlibraryrepresentation>
+ </node>
+ <node name="Qt/Rectangle" showInItemLibrary="true" category="QtFx" isContainer="true">
+ <itemlibraryrepresentation name="Rectangle" icon=":/fxplugin/images/rect-icon.png">
+ <property name="width" type="int" value="100"/>
+ <property name="height" type="int" value="100"/>
+ <property name="color" type="QColor" value="#ffffff"/>
+ </itemlibraryrepresentation>
+ </node>
+ <node name="Qt/Text" showInItemLibrary="true" category="QtFx">
+ <propertyDefaultValue name="width" type="int" defaultValue="80"/>
+ <propertyDefaultValue name="height" type="int" defaultValue="20"/>
+ <itemlibraryrepresentation name="Text" icon=":/fxplugin/images/text-icon.png">
+ <property name="width" type="int" value="80"/>
+ <property name="height" type="int" value="20"/>
+ <property name="text" type="QString" value="text"/>
+ </itemlibraryrepresentation>
+ </node>
+ <node name="Qt/TextEdit" showInItemLibrary="true" category="QtFx" isContainer="false">
+ <propertyDefaultValue name="width" type="int" defaultValue="80"/>
+ <propertyDefaultValue name="height" type="int" defaultValue="20"/>
+ <itemlibraryrepresentation name="Text Edit" icon=":/fxplugin/images/text-edit-icon.png">
+ <property name="width" type="int" value="80"/>
+ <property name="height" type="int" value="20"/>
+ <property name="text" type="QString" value="textEdit"/>
+ </itemlibraryrepresentation>
+ </node>
+ <node name="Qt/TextInput" showInItemLibrary="true" category="QtFx" isContainer="false">
+ <propertyDefaultValue name="width" type="int" defaultValue="80"/>
+ <propertyDefaultValue name="height" type="int" defaultValue="20"/>
+ <itemlibraryrepresentation name="Text Input" icon=":/fxplugin/images/text-edit-icon.png">
+ <property name="width" type="int" value="80"/>
+ <property name="height" type="int" value="20"/>
+ <property name="text" type="QString" value="textInput"/>
+ </itemlibraryrepresentation>
+ </node>
+ <node name="Qt/MouseRegion" showInItemLibrary="true" category="QtFx">
+ <inherits name="Item" />
+ <itemlibraryrepresentation name="Mouse Region" icon=":/fxplugin/images/mouse-region-icon.png">
+ <property name="width" type="int" value="100"/>
+ <property name="height" type="int" value="100"/>
+ </itemlibraryrepresentation>
+ </node>
+ <node name="Qt/Image" showInItemLibrary="true" category="QtFx">
+ <propertyDefaultValue name="width" type="int" defaultValue="200"/>
+ <propertyDefaultValue name="height" type="int" defaultValue="200"/>
+ <itemlibraryrepresentation name="Image" icon=":/fxplugin/images/image-icon.png">
+ <property name="width" type="int" value="100"/>
+ <property name="height" type="int" value="100"/>
+ <property name="source" type="QUrl" value="qrc:/fxplugin/images/template_image.png"/>
+ </itemlibraryrepresentation>
+ </node>
+ <node name="Qt/BorderImage" showInItemLibrary="true" category="QtFx">
+ <propertyDefaultValue name="width" type="int" defaultValue="200"/>
+ <propertyDefaultValue name="height" type="int" defaultValue="200"/>
+ <itemlibraryrepresentation name="Border Image" icon=":/fxplugin/images/image-icon.png">
+ <property name="width" type="int" value="100"/>
+ <property name="height" type="int" value="100"/>
+ <property name="source" type="QUrl" value="qrc:/fxplugin/images/template_image.png"/>
+ </itemlibraryrepresentation>
+ </node>
+ <node name="Qt/Flickable" showInItemLibrary="true" category="QtFx">
+ <propertyDefaultValue name="width" type="int" defaultValue="300"/>
+ <propertyDefaultValue name="height" type="int" defaultValue="300"/>
+ <itemlibraryrepresentation name="Flickable">
+ <property name="width" type="int" value="300"/>
+ <property name="height" type="int" value="300"/>
+ </itemlibraryrepresentation>
+ </node>
+ <node name="Qt/Flipable" showInItemLibrary="true" category="QtFx">
+ <propertyDefaultValue name="width" type="int" defaultValue="300"/>
+ <propertyDefaultValue name="height" type="int" defaultValue="300"/>
+ <itemlibraryrepresentation name="Flipable">
+ <property name="width" type="int" value="300"/>
+ <property name="height" type="int" value="300"/>
+ </itemlibraryrepresentation>
+ </node>
+ <node name="Qt/GridView" showInItemLibrary="true" category="QtFx">
+ <itemlibraryrepresentation name="Grid View" icon=":/fxplugin/images/grid-icon.png">
+ <property name="width" type="int" value="300"/>
+ <property name="height" type="int" value="300"/>
+ </itemlibraryrepresentation>
+ </node>
+ <node name="Qt/ListView" showInItemLibrary="true" category="QtFx">
+ <itemlibraryrepresentation name="List View" icon=":/fxplugin/images/list-icon.png">
+ <property name="width" type="int" value="300"/>
+ <property name="height" type="int" value="300"/>
+ </itemlibraryrepresentation>
+ </node>
+
+ <node name="Qt/FocusScope" showInItemLibrary="true" category="QtFx">
+ <propertyDefaultValue name="width" type="int" defaultValue="100"/>
+ <propertyDefaultValue name="height" type="int" defaultValue="100"/>
+ <itemlibraryrepresentation name="Focus Scope">
+ <property name="width" type="int" value="100"/>
+ <property name="height" type="int" value="100"/>
+ </itemlibraryrepresentation>
+ </node>
+
+ <node name="Qt/Row" showInItemLibrary="true" category="QtFx" isContainer="true">
+ <propertyDefaultValue name="width" type="int" defaultValue="100"/>
+ <propertyDefaultValue name="height" type="int" defaultValue="100"/>
+ <itemlibraryrepresentation name="Row">
+ <property name="width" type="int" value="100"/>
+ <property name="height" type="int" value="100"/>
+ </itemlibraryrepresentation>
+ </node>
+
+ <node name="Qt/Column" showInItemLibrary="true" category="QtFx" isContainer="true">
+ <propertyDefaultValue name="width" type="int" defaultValue="100"/>
+ <propertyDefaultValue name="height" type="int" defaultValue="100"/>
+ <itemlibraryrepresentation name="Column">
+ <property name="width" type="int" value="100"/>
+ <property name="height" type="int" value="100"/>
+ </itemlibraryrepresentation>
+ </node>
+
+ <node name="Qt/Grid" showInItemLibrary="true" category="QtFx" isContainer="true">
+ <propertyDefaultValue name="width" type="int" defaultValue="100"/>
+ <propertyDefaultValue name="height" type="int" defaultValue="100"/>
+ <itemlibraryrepresentation name="Grid">
+ <property name="width" type="int" value="100"/>
+ <property name="height" type="int" value="100"/>
+ </itemlibraryrepresentation>
+ </node>
+
+ <node name="Qt/WebView" showInItemLibrary="true" category="QtFx">
+ <propertyDefaultValue name="width" type="int" defaultValue="300"/>
+ <propertyDefaultValue name="height" type="int" defaultValue="300"/>
+ <itemlibraryrepresentation name="Web View">
+ <property name="width" type="int" value="300"/>
+ <property name="height" type="int" value="300"/>
+ <property name="url" type="QString" value="http://www.trolltech.com"/>
+ </itemlibraryrepresentation>
+ </node>
+</metainfo>
diff --git a/src/plugins/qmldesigner/fxplugin/fxplugin.cpp b/src/plugins/qmldesigner/fxplugin/fxplugin.cpp
new file mode 100644
index 0000000000..38858c22d1
--- /dev/null
+++ b/src/plugins/qmldesigner/fxplugin/fxplugin.cpp
@@ -0,0 +1,49 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "fxplugin.h"
+#include <widgetplugin_helper.h>
+#include <QtCore/QtPlugin>
+
+namespace QmlDesigner {
+
+QString FxPlugin::pluginName()
+{
+ return ("FxPlugin");
+}
+
+QString FxPlugin::metaInfo()
+{
+ return QString(":/fxplugin/fx.metainfo");
+}
+
+}
+
+Q_EXPORT_PLUGIN(QmlDesigner::FxPlugin)
+
diff --git a/src/plugins/qmldesigner/fxplugin/fxplugin.h b/src/plugins/qmldesigner/fxplugin/fxplugin.h
new file mode 100644
index 0000000000..fe73ccc999
--- /dev/null
+++ b/src/plugins/qmldesigner/fxplugin/fxplugin.h
@@ -0,0 +1,58 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef FXPLUGIN_H
+#define FXPLUGIN_H
+
+#include <iwidgetplugin.h>
+#include <QtDeclarative/qml.h>
+
+QT_BEGIN_NAMESPACE
+QT_END_NAMESPACE
+
+namespace QmlDesigner {
+
+class FxPlugin : public QObject, QmlDesigner::IWidgetPlugin
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(FxPlugin)
+ Q_INTERFACES(QmlDesigner::IWidgetPlugin)
+public:
+ FxPlugin() {}
+ ~FxPlugin() {}
+
+ QString metaInfo();
+ QString pluginName();
+
+};
+
+} // namespace QmlDesigner
+
+
+#endif // FXPLUGIN_H
diff --git a/src/plugins/qmldesigner/fxplugin/fxplugin.pri b/src/plugins/qmldesigner/fxplugin/fxplugin.pri
new file mode 100644
index 0000000000..9760d0e722
--- /dev/null
+++ b/src/plugins/qmldesigner/fxplugin/fxplugin.pri
@@ -0,0 +1,17 @@
+TARGET = fxplugin
+TEMPLATE = lib
+CONFIG += plugin
+
+QT += script \
+ declarative
+
+include (../core/iwidgetplugin.pri)
+
+DEFINES += FX_LIBRARY
+SOURCES += $$PWD/fxplugin.cpp
+
+HEADERS += $$PWD/fxplugin.h $$PWD/../core/include/iwidgetplugin.h
+
+RESOURCES += $$PWD/fxplugin.qrc
+
+OTHER_FILES += $$PWD/fx.metainfo
diff --git a/src/plugins/qmldesigner/fxplugin/fxplugin.pro b/src/plugins/qmldesigner/fxplugin/fxplugin.pro
new file mode 100644
index 0000000000..82e1c6503e
--- /dev/null
+++ b/src/plugins/qmldesigner/fxplugin/fxplugin.pro
@@ -0,0 +1,4 @@
+include(../../../../qtcreator.pri)
+
+include(fxplugin.pri)
+include(plugindestdir.pri)
diff --git a/src/plugins/qmldesigner/fxplugin/fxplugin.qrc b/src/plugins/qmldesigner/fxplugin/fxplugin.qrc
new file mode 100644
index 0000000000..886248877b
--- /dev/null
+++ b/src/plugins/qmldesigner/fxplugin/fxplugin.qrc
@@ -0,0 +1,15 @@
+<RCC>
+ <qresource prefix="/fxplugin" >
+ <file>images/blended-image-icon.png</file>
+ <file>images/image-icon.png</file>
+ <file>images/item-icon.png</file>
+ <file>images/mouse-region-icon.png</file>
+ <file>images/rect-icon.png</file>
+ <file>images/text-edit-icon.png</file>
+ <file>images/text-icon.png</file>
+ <file>images/list-icon.png</file>
+ <file>images/grid-icon.png</file>
+ <file>images/template_image.png</file>
+ <file>fx.metainfo</file>
+ </qresource>
+</RCC>
diff --git a/src/plugins/qmldesigner/fxplugin/images/blended-image-icon.png b/src/plugins/qmldesigner/fxplugin/images/blended-image-icon.png
new file mode 100644
index 0000000000..7c0911d63d
--- /dev/null
+++ b/src/plugins/qmldesigner/fxplugin/images/blended-image-icon.png
Binary files differ
diff --git a/src/plugins/qmldesigner/fxplugin/images/default-icon.png b/src/plugins/qmldesigner/fxplugin/images/default-icon.png
new file mode 100644
index 0000000000..a90779f02a
--- /dev/null
+++ b/src/plugins/qmldesigner/fxplugin/images/default-icon.png
Binary files differ
diff --git a/src/plugins/qmldesigner/fxplugin/images/grid-icon.png b/src/plugins/qmldesigner/fxplugin/images/grid-icon.png
new file mode 100644
index 0000000000..113e14c00a
--- /dev/null
+++ b/src/plugins/qmldesigner/fxplugin/images/grid-icon.png
Binary files differ
diff --git a/src/plugins/qmldesigner/fxplugin/images/image-icon.png b/src/plugins/qmldesigner/fxplugin/images/image-icon.png
new file mode 100644
index 0000000000..4dfcae7d47
--- /dev/null
+++ b/src/plugins/qmldesigner/fxplugin/images/image-icon.png
Binary files differ
diff --git a/src/plugins/qmldesigner/fxplugin/images/item-icon.png b/src/plugins/qmldesigner/fxplugin/images/item-icon.png
new file mode 100644
index 0000000000..82587ae0ec
--- /dev/null
+++ b/src/plugins/qmldesigner/fxplugin/images/item-icon.png
Binary files differ
diff --git a/src/plugins/qmldesigner/fxplugin/images/list-icon.png b/src/plugins/qmldesigner/fxplugin/images/list-icon.png
new file mode 100644
index 0000000000..9c96743f0e
--- /dev/null
+++ b/src/plugins/qmldesigner/fxplugin/images/list-icon.png
Binary files differ
diff --git a/src/plugins/qmldesigner/fxplugin/images/mouse-region-icon.png b/src/plugins/qmldesigner/fxplugin/images/mouse-region-icon.png
new file mode 100644
index 0000000000..8c23b6c0fc
--- /dev/null
+++ b/src/plugins/qmldesigner/fxplugin/images/mouse-region-icon.png
Binary files differ
diff --git a/src/plugins/qmldesigner/fxplugin/images/rect-icon.png b/src/plugins/qmldesigner/fxplugin/images/rect-icon.png
new file mode 100644
index 0000000000..4555d886fb
--- /dev/null
+++ b/src/plugins/qmldesigner/fxplugin/images/rect-icon.png
Binary files differ
diff --git a/src/plugins/qmldesigner/fxplugin/images/template_image.png b/src/plugins/qmldesigner/fxplugin/images/template_image.png
new file mode 100644
index 0000000000..a62b3057bc
--- /dev/null
+++ b/src/plugins/qmldesigner/fxplugin/images/template_image.png
Binary files differ
diff --git a/src/plugins/qmldesigner/fxplugin/images/text-edit-icon.png b/src/plugins/qmldesigner/fxplugin/images/text-edit-icon.png
new file mode 100644
index 0000000000..6a064ab07c
--- /dev/null
+++ b/src/plugins/qmldesigner/fxplugin/images/text-edit-icon.png
Binary files differ
diff --git a/src/plugins/qmldesigner/fxplugin/images/text-icon.png b/src/plugins/qmldesigner/fxplugin/images/text-icon.png
new file mode 100644
index 0000000000..9ce62037ba
--- /dev/null
+++ b/src/plugins/qmldesigner/fxplugin/images/text-icon.png
Binary files differ
diff --git a/src/plugins/qmldesigner/fxplugin/images/widget.png b/src/plugins/qmldesigner/fxplugin/images/widget.png
new file mode 100644
index 0000000000..1cf960e61b
--- /dev/null
+++ b/src/plugins/qmldesigner/fxplugin/images/widget.png
Binary files differ
diff --git a/src/plugins/qmldesigner/fxplugin/plugindestdir.pri b/src/plugins/qmldesigner/fxplugin/plugindestdir.pri
new file mode 100644
index 0000000000..9dff900cbd
--- /dev/null
+++ b/src/plugins/qmldesigner/fxplugin/plugindestdir.pri
@@ -0,0 +1,5 @@
+macx {
+ DESTDIR = $$IDE_LIBRARY_PATH/QmlDesigner
+} else {
+ DESTDIR = $$PWD/../../../../lib/qmldesigner
+}
diff --git a/src/plugins/qmldesigner/images/mode_Design.png b/src/plugins/qmldesigner/images/mode_Design.png
new file mode 100644
index 0000000000..b00ca63d83
--- /dev/null
+++ b/src/plugins/qmldesigner/images/mode_Design.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesigner.pro b/src/plugins/qmldesigner/qmldesigner.pro
new file mode 100644
index 0000000000..28abb28999
--- /dev/null
+++ b/src/plugins/qmldesigner/qmldesigner.pro
@@ -0,0 +1,3 @@
+TEMPLATE = subdirs
+
+SUBDIRS = qmldesignerplugin.pro fxplugin
diff --git a/src/plugins/qmldesigner/qmldesigner_dependencies.pri b/src/plugins/qmldesigner/qmldesigner_dependencies.pri
new file mode 100644
index 0000000000..c1fb3fc38b
--- /dev/null
+++ b/src/plugins/qmldesigner/qmldesigner_dependencies.pri
@@ -0,0 +1,3 @@
+include(../../libs/utils/utils.pri)
+include(../coreplugin/coreplugin.pri)
+include(../texteditor/texteditor.pri)
diff --git a/src/plugins/qmldesigner/qmldesignerconstants.h b/src/plugins/qmldesigner/qmldesignerconstants.h
new file mode 100644
index 0000000000..323dfb2192
--- /dev/null
+++ b/src/plugins/qmldesigner/qmldesignerconstants.h
@@ -0,0 +1,58 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef QMLDESIGNERPLUGIN_CONSTANTS_H
+#define QMLDESIGNERPLUGIN_CONSTANTS_H
+
+#include <coreplugin/coreconstants.h>
+
+namespace QmlDesigner {
+namespace Constants {
+
+const char * const DELETE = "QmlDesigner.Delete";
+
+// context
+const char * const C_DESIGN_MODE = "QmlDesigner::DesignMode";
+const char * const C_FORMEDITOR = "QmlDesigner::FormEditor";
+
+// mode
+const char * const DESIGN_MODE_NAME = "Design";
+const int DESIGN_MODE_PRIORITY = Core::Constants::P_MODE_EDIT - 1;
+
+// Wizard type
+const char * const FORM_MIMETYPE = "application/x-qmldesigner";
+
+namespace Internal {
+ enum { debug = 0 };
+}
+
+} // Constants
+} // QmlDesigner
+
+#endif //QMLDESIGNERPLUGIN_CONSTANTS_H
diff --git a/src/plugins/qmldesigner/qmldesignerplugin.cpp b/src/plugins/qmldesigner/qmldesignerplugin.cpp
new file mode 100644
index 0000000000..5d3c397966
--- /dev/null
+++ b/src/plugins/qmldesigner/qmldesignerplugin.cpp
@@ -0,0 +1,100 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "qmldesignerplugin.h"
+#include "designmode.h"
+#include "qmldesignerconstants.h"
+#include "pluginmanager.h"
+
+#include <coreplugin/icore.h>
+#include <coreplugin/dialogs/iwizard.h>
+#include <coreplugin/editormanager/ieditorfactory.h>
+#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/mimedatabase.h>
+#include <coreplugin/coreconstants.h>
+#include <coreplugin/uniqueidmanager.h>
+#include <utils/qtcassert.h>
+
+#include <integrationcore.h>
+
+#include <QtCore/QDebug>
+#include <QtCore/QCoreApplication>
+#include <QtCore/qplugin.h>
+
+namespace QmlDesigner {
+namespace Internal {
+
+BauhausPlugin::BauhausPlugin() :
+ m_designerCore(0)
+{
+}
+
+BauhausPlugin::~BauhausPlugin()
+{
+ delete m_designerCore;
+}
+
+////////////////////////////////////////////////////
+//
+// INHERITED FROM ExtensionSystem::Plugin
+//
+////////////////////////////////////////////////////
+bool BauhausPlugin::initialize(const QStringList & /*arguments*/, QString *error_message/* = 0*/) // =0;
+{
+ Core::ICore *core = Core::ICore::instance();
+
+ const int uid = core->uniqueIDManager()->uniqueIdentifier(QLatin1String(QmlDesigner::Constants::C_FORMEDITOR));
+ const QList<int> context = QList<int>() << uid;
+
+ m_designerCore = new QmlDesigner::IntegrationCore;
+
+#ifdef Q_OS_MAC
+ const QString pluginPath = QCoreApplication::applicationDirPath() + "/../PlugIns/QmlDesigner";
+#else
+ const QString pluginPath = QCoreApplication::applicationDirPath() + "/../"
+ + QLatin1String(IDE_LIBRARY_BASENAME) + "/qmldesigner";
+#endif
+
+ m_designerCore->pluginManager()->setPluginPaths(QStringList() << pluginPath);
+
+ addAutoReleasedObject(new DesignMode);
+
+ error_message->clear();
+
+ return true;
+}
+
+void BauhausPlugin::extensionsInitialized()
+{
+}
+
+}
+}
+
+Q_EXPORT_PLUGIN(QmlDesigner::Internal::BauhausPlugin)
diff --git a/src/plugins/qmldesigner/qmldesignerplugin.h b/src/plugins/qmldesigner/qmldesignerplugin.h
new file mode 100644
index 0000000000..d95386789e
--- /dev/null
+++ b/src/plugins/qmldesigner/qmldesignerplugin.h
@@ -0,0 +1,68 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef QMLDESIGNERPLUGIN_H
+#define QMLDESIGNERPLUGIN_H
+
+#include <extensionsystem/iplugin.h>
+
+namespace Core {
+ class IWizard;
+ class ICore;
+ class IEditorFactory;
+ class IEditor;
+}
+
+namespace QmlDesigner {
+ class IntegrationCore;
+}
+
+namespace QmlDesigner {
+namespace Internal {
+
+class BauhausPlugin : public ExtensionSystem::IPlugin
+{
+ Q_OBJECT
+
+public:
+ BauhausPlugin();
+ virtual ~BauhausPlugin();
+
+ //Plugin
+ virtual bool initialize(const QStringList &arguments, QString *error_message = 0);
+ virtual void extensionsInitialized();
+
+private:
+ QmlDesigner::IntegrationCore *m_designerCore;
+};
+
+} // namespace Internal
+} // namespace QmlDesigner
+
+#endif // QMLDESIGNERPLUGIN_H
diff --git a/src/plugins/qmldesigner/qmldesignerplugin.pro b/src/plugins/qmldesigner/qmldesignerplugin.pro
new file mode 100644
index 0000000000..ad820316be
--- /dev/null
+++ b/src/plugins/qmldesigner/qmldesignerplugin.pro
@@ -0,0 +1,29 @@
+TEMPLATE = lib
+TARGET = QmlDesigner
+
+include(../../qtcreatorplugin.pri)
+include(qmldesigner_dependencies.pri)
+
+include(core/core.pri)
+include(components/integration/integration.pri)
+include(components/propertyeditor/propertyeditor.pri)
+include(components/formeditor/formeditor.pri)
+include(components/itemlibrary/itemlibrary.pri)
+include(components/navigator/navigator.pri)
+include(components/pluginmanager/pluginmanager.pri)
+include(components/themeloader/qts60stylethemeio.pri)
+include(components/stateseditor/stateseditor.pri)
+include(components/resources/resources.pri)
+
+HEADERS += qmldesignerconstants.h \
+ qmldesignerplugin.h \
+ designmode.h \
+ designmodewidget.h \
+ application.h
+SOURCES += qmldesignerplugin.cpp \
+ designmode.cpp \
+ designmodewidget.cpp \
+ application.cpp
+
+OTHER_FILES += QmlDesigner.pluginspec
+RESOURCES += qmldesignerplugin.qrc
diff --git a/src/plugins/qmldesigner/qmldesignerplugin.qrc b/src/plugins/qmldesigner/qmldesignerplugin.qrc
new file mode 100644
index 0000000000..23b9790040
--- /dev/null
+++ b/src/plugins/qmldesigner/qmldesignerplugin.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/qmldesigner">
+ <file>images/mode_Design.png</file>
+ </qresource>
+</RCC>
diff --git a/src/plugins/qmleditor/qmleditor.cpp b/src/plugins/qmleditor/qmleditor.cpp
index 4466ec111f..7bd674f498 100644
--- a/src/plugins/qmleditor/qmleditor.cpp
+++ b/src/plugins/qmleditor/qmleditor.cpp
@@ -655,7 +655,6 @@ TextEditor::BaseTextEditor::Link QmlTextEditor::findLinkAt(const QTextCursor &cu
QTextCursor expressionCursor(cursor);
{
// correct the position by moving to the end of an identifier (if we're hovering over one):
- const QString txt = cursor.block().text();
int pos = cursor.position();
forever {
const QChar ch = characterAt(pos);
diff --git a/src/plugins/qmleditor/qmlhoverhandler.cpp b/src/plugins/qmleditor/qmlhoverhandler.cpp
index 7d9ee7d7c6..799a669b70 100644
--- a/src/plugins/qmleditor/qmlhoverhandler.cpp
+++ b/src/plugins/qmleditor/qmlhoverhandler.cpp
@@ -171,6 +171,7 @@ void QmlHoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, in
}
}
+ QString symbolName = QLatin1String("<unknown>");
if (m_helpId.isEmpty()) {
// Move to the end of a qualified name
bool stop = false;
@@ -194,7 +195,12 @@ void QmlHoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, in
QmlSymbol *resolvedSymbol = resolver.typeOf(expressionUnderCursor.expressionNode());
if (resolvedSymbol) {
- m_helpId = buildHelpId(resolvedSymbol);
+ symbolName = resolvedSymbol->name();
+
+ if (resolvedSymbol->isBuildInSymbol())
+ m_helpId = buildHelpId(resolvedSymbol);
+ else if (QmlSymbolFromFile *symbolFromFile = resolvedSymbol->asSymbolFromFile())
+ m_toolTip = symbolFromFile->fileName();
}
}
@@ -216,6 +222,6 @@ void QmlHoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, in
} else if (!m_toolTip.isEmpty()) {
m_toolTip = QString(QLatin1String("<nobr>%1")).arg(m_toolTip);
} else if (!m_helpId.isEmpty()) {
- m_toolTip = QString(QLatin1String("<nobr>No help available for \"%1\"")).arg(m_helpId);
+ m_toolTip = QString(QLatin1String("<nobr>No help available for \"%1\"")).arg(symbolName);
}
}
diff --git a/src/plugins/qmleditor/qmllookupcontext.cpp b/src/plugins/qmleditor/qmllookupcontext.cpp
index d1e88850e9..ae37b10ace 100644
--- a/src/plugins/qmleditor/qmllookupcontext.cpp
+++ b/src/plugins/qmleditor/qmllookupcontext.cpp
@@ -159,7 +159,7 @@ QmlSymbol *QmlLookupContext::resolveBuildinType(const QString &name)
QmlSymbol *QmlLookupContext::resolveProperty(const QString &name, QmlSymbol *scope, const QString &fileName)
{
foreach (QmlSymbol *symbol, scope->members())
- if (symbol->name() == name)
+ if (symbol->isProperty() && symbol->name() == name)
return symbol;
UiQualifiedId *typeName = 0;
diff --git a/src/plugins/qmlprojectmanager/qmlprojectmanager.cpp b/src/plugins/qmlprojectmanager/qmlprojectmanager.cpp
index 892144522c..4baf42e83b 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectmanager.cpp
+++ b/src/plugins/qmlprojectmanager/qmlprojectmanager.cpp
@@ -33,7 +33,10 @@
#include <coreplugin/icore.h>
#include <coreplugin/uniqueidmanager.h>
+#include <coreplugin/messagemanager.h>
#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/session.h>
#include <QtDebug>
@@ -60,10 +63,23 @@ QString Manager::mimeType() const
ProjectExplorer::Project *Manager::openProject(const QString &fileName)
{
+ Core::MessageManager *messageManager = Core::ICore::instance()->messageManager();
+ messageManager->displayStatusBarMessage(tr("Loading project %1 ...").arg(fileName), 50000);
+
QFileInfo fileInfo(fileName);
+ ProjectExplorer::ProjectExplorerPlugin *projectExplorer = ProjectExplorer::ProjectExplorerPlugin::instance();
+
+ foreach (ProjectExplorer::Project *pi, projectExplorer->session()->projects()) {
+ if (fileName == pi->file()->fileName()) {
+ messageManager->printToOutputPane(tr("Failed opening project '%1': Project already open").arg(QDir::toNativeSeparators(fileName)));
+ messageManager->displayStatusBarMessage(tr("Failed opening project"), 5000);
+ return 0;
+ }
+ }
if (fileInfo.isFile()) {
QmlProject *project = new QmlProject(this, fileName);
+ messageManager->displayStatusBarMessage(tr("Done opening project"), 5000);
return project;
}
diff --git a/src/plugins/qmlprojectmanager/qmltaskmanager.cpp b/src/plugins/qmlprojectmanager/qmltaskmanager.cpp
index ac92b7ce11..041a009d7d 100644
--- a/src/plugins/qmlprojectmanager/qmltaskmanager.cpp
+++ b/src/plugins/qmlprojectmanager/qmltaskmanager.cpp
@@ -50,6 +50,7 @@ void QmlTaskManager::setTaskWindow(ProjectExplorer::TaskWindow *taskWindow)
void QmlTaskManager::documentUpdated(QmlEditor::QmlDocument::Ptr doc)
{
+#if 0 // This will give way too many flickering errors in the build-results pane *when you're typing*
m_taskWindow->clearTasks(Constants::TASK_CATEGORY_QML);
foreach (const QmlJS::DiagnosticMessage &msg, doc->diagnosticMessages()) {
@@ -61,6 +62,7 @@ void QmlTaskManager::documentUpdated(QmlEditor::QmlDocument::Ptr doc)
Constants::TASK_CATEGORY_QML);
m_taskWindow->addTask(task);
}
+#endif
}
} // Internal
diff --git a/src/shared/qml/metatype/QtDeclarativeMetaTypeBackend.cpp b/src/shared/qml/metatype/QtDeclarativeMetaTypeBackend.cpp
index 0a20bb5d03..6ae8739712 100644
--- a/src/shared/qml/metatype/QtDeclarativeMetaTypeBackend.cpp
+++ b/src/shared/qml/metatype/QtDeclarativeMetaTypeBackend.cpp
@@ -98,6 +98,9 @@ public:
return result;
}
+ virtual bool isProperty() const
+ { return false; }
+
public:
static QString key(const NodeMetaInfo &metaInfo)
{
@@ -173,6 +176,9 @@ public:
return members();
}
+ virtual bool isProperty() const
+ { return true; }
+
private:
PropertyMetaInfo m_metaInfo;
};
diff --git a/src/shared/qml/metatype/exception.cpp b/src/shared/qml/metatype/exception.cpp
index f6d966c870..807cbc24bb 100644
--- a/src/shared/qml/metatype/exception.cpp
+++ b/src/shared/qml/metatype/exception.cpp
@@ -41,7 +41,7 @@
\defgroup CoreExceptions
*/
/*!
-\class QKineticDesigner::Exception
+\class QmlDesigner::Exception
\ingroup CoreExceptions
\brief This is the abstract base class for all excetions.
Exceptions should be used in cases there is no other way to say something goes wrong. For example
diff --git a/src/shared/qml/metatype/invalidmetainfoexception.cpp b/src/shared/qml/metatype/invalidmetainfoexception.cpp
index fc991695b6..9d8aa37b0c 100644
--- a/src/shared/qml/metatype/invalidmetainfoexception.cpp
+++ b/src/shared/qml/metatype/invalidmetainfoexception.cpp
@@ -30,7 +30,7 @@
#include "invalidmetainfoexception.h"
/*!
-\class QKineticDesigner::InvalidMetaInfoException
+\class QmlDesigner::InvalidMetaInfoException
\ingroup CoreExceptions
\brief Exception for a invalid meta info
diff --git a/src/shared/qml/metatype/metainfo.cpp b/src/shared/qml/metatype/metainfo.cpp
index f979a064db..f6ace0f95a 100644
--- a/src/shared/qml/metatype/metainfo.cpp
+++ b/src/shared/qml/metatype/metainfo.cpp
@@ -254,7 +254,7 @@ QStringList MetaInfo::s_pluginDirs;
/*!
-\class QKineticDesigner::MetaInfo
+\class QmlDesigner::MetaInfo
\ingroup CoreModel
\brief The MetaInfo class provides meta information about qml types and properties.
@@ -268,7 +268,7 @@ The MetaInfo object should always be accessed via the model (see Model::metaInfo
Otherwise types specific to a model (like sub components) might
be missed.
-\see Model::metaInfo(), QKineticDesigner::NodeMetaInfo, QKineticDesigner::PropertyMetaInfo, QKineticDesigner::EnumeratorMetaInfo
+\see Model::metaInfo(), QmlDesigner::NodeMetaInfo, QmlDesigner::PropertyMetaInfo, QmlDesigner::EnumeratorMetaInfo
*/
/*!
@@ -486,4 +486,4 @@ bool operator!=(const MetaInfo &first, const MetaInfo &second)
{
return !(first == second);
}
-} //namespace QKineticDesigner
+} //namespace QmlDesigner
diff --git a/src/shared/qml/metatype/nodemetainfo.cpp b/src/shared/qml/metatype/nodemetainfo.cpp
index 907083b752..86132aa4e0 100644
--- a/src/shared/qml/metatype/nodemetainfo.cpp
+++ b/src/shared/qml/metatype/nodemetainfo.cpp
@@ -80,7 +80,7 @@ public:
} // namespace Internal
/*!
-\class QKineticDesigner::NodeMetaInfo
+\class QmlDesigner::NodeMetaInfo
\ingroup CoreModel
\brief The NodeMetaInfo class provides meta information about a qml type.
@@ -93,7 +93,7 @@ if the enclosing type is deregistered from the meta type system (e.g.
a sub component qml file is deleted). Trying to call any accessor methods on an invalid
NodeMetaInfo object will result in an InvalidMetaInfoException being thrown.
-\see QKineticDesigner::MetaInfo, QKineticDesigner::PropertyMetaInfo, QKineticDesigner::EnumeratorMetaInfo
+\see QmlDesigner::MetaInfo, QmlDesigner::PropertyMetaInfo, QmlDesigner::EnumeratorMetaInfo
*/
NodeMetaInfo::NodeMetaInfo()
diff --git a/src/shared/qml/metatype/propertymetainfo.cpp b/src/shared/qml/metatype/propertymetainfo.cpp
index 1e2b7276da..6596a9cfa4 100644
--- a/src/shared/qml/metatype/propertymetainfo.cpp
+++ b/src/shared/qml/metatype/propertymetainfo.cpp
@@ -72,7 +72,7 @@ public:
} // namespace Internal
/*!
-\class QKineticDesigner::PropertyMetaInfo
+\class QmlDesigner::PropertyMetaInfo
\ingroup CoreModel
\brief The PropertyMetaInfo class provides meta information about a qml type property.
@@ -86,7 +86,7 @@ a sub component qml file is deleted). Trying to call any accessor methods on an
PropertyMetaInfo object will result in an InvalidMetaInfoException being thrown.
-\see QKineticDesigner::MetaInfo, QKineticDesigner::NodeMetaInfo, QKineticDesigner::EnumeratorMetaInfo
+\see QmlDesigner::MetaInfo, QmlDesigner::NodeMetaInfo, QmlDesigner::EnumeratorMetaInfo
*/
PropertyMetaInfo::PropertyMetaInfo()
diff --git a/src/shared/qml/qml.pri b/src/shared/qml/qml.pri
index fb6165a5bb..9e9bbc0a77 100644
--- a/src/shared/qml/qml.pri
+++ b/src/shared/qml/qml.pri
@@ -1,6 +1,6 @@
include(parser/parser.pri)
-DEPENDPATH += $$PWD
+DEPENDPATH += $$PWD $$PWD/metatype
INCLUDEPATH *= $$PWD/..
HEADERS += \
diff --git a/src/shared/qml/qmlsymbol.cpp b/src/shared/qml/qmlsymbol.cpp
index 677a5ba337..4a8da962e4 100644
--- a/src/shared/qml/qmlsymbol.cpp
+++ b/src/shared/qml/qmlsymbol.cpp
@@ -142,16 +142,16 @@ const QString QmlSymbolFromFile::name() const
const QmlSymbol::List QmlSymbolFromFile::members()
{
if (!todo.isEmpty()) {
- foreach (Node *node, todo) {
- if (UiObjectBinding *objectBinding = cast<UiObjectBinding*>(node))
+ foreach (Node *todoNode, todo) {
+ if (UiObjectBinding *objectBinding = cast<UiObjectBinding*>(todoNode))
_members.append(new QmlSymbolFromFile(fileName(), objectBinding));
- else if (UiObjectDefinition *objectDefinition = cast<UiObjectDefinition*>(node))
+ else if (UiObjectDefinition *objectDefinition = cast<UiObjectDefinition*>(todoNode))
_members.append(new QmlSymbolFromFile(fileName(), objectDefinition));
- else if (UiArrayBinding *arrayBinding = cast<UiArrayBinding*>(node))
+ else if (UiArrayBinding *arrayBinding = cast<UiArrayBinding*>(todoNode))
_members.append(new QmlSymbolFromFile(fileName(), arrayBinding));
- else if (UiPublicMember *publicMember = cast<UiPublicMember*>(node))
+ else if (UiPublicMember *publicMember = cast<UiPublicMember*>(todoNode))
_members.append(new QmlPropertyDefinitionSymbol(fileName(), publicMember));
- else if (UiScriptBinding *scriptBinding = cast<UiScriptBinding*>(node)) {
+ else if (UiScriptBinding *scriptBinding = cast<UiScriptBinding*>(todoNode)) {
if (scriptBinding->qualifiedId && scriptBinding->qualifiedId->name && scriptBinding->qualifiedId->name->asString() == QLatin1String("id") && !scriptBinding->qualifiedId->next)
_members.append(new QmlIdSymbol(fileName(), scriptBinding, this));
else
@@ -165,6 +165,9 @@ const QmlSymbol::List QmlSymbolFromFile::members()
return _members;
}
+bool QmlSymbolFromFile::isProperty() const
+{ return cast<UiObjectDefinition*>(_node) == 0; }
+
QmlSymbolFromFile *QmlSymbolFromFile::findMember(QmlJS::AST::Node *memberNode)
{
List symbols = members();
diff --git a/src/shared/qml/qmlsymbol.h b/src/shared/qml/qmlsymbol.h
index b5bf6f424e..306cd58a89 100644
--- a/src/shared/qml/qmlsymbol.h
+++ b/src/shared/qml/qmlsymbol.h
@@ -48,6 +48,7 @@ public:
virtual const QString name() const = 0;
virtual const List members() = 0;
+ virtual bool isProperty() const = 0;
bool isBuildInSymbol();
bool isSymbolFromFile();
@@ -101,6 +102,7 @@ public:
virtual const QString name() const;
virtual const List members();
+ virtual bool isProperty() const;
virtual QmlSymbolFromFile *findMember(QmlJS::AST::Node *memberNode);
private:
diff --git a/src/tools/qmldesigner/qmldom/main.cpp b/src/tools/qmldesigner/qmldom/main.cpp
new file mode 100644
index 0000000000..d0faf4ac26
--- /dev/null
+++ b/src/tools/qmldesigner/qmldom/main.cpp
@@ -0,0 +1,173 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <QtCore/QDebug>
+#include <QtCore/QtCore>
+#include <QtCore/QCoreApplication>
+
+#include <QtDeclarative/QmlDomDocument>
+#include <QtDeclarative/QmlEngine>
+
+#define SPACING (QString(" "))
+
+const char* getDefault(const QmlDomProperty& prop)
+{
+ if (prop.isDefaultProperty())
+ return " (default property)";
+ else
+ return "";
+}
+
+void dumpList(const QmlDomList& list, const QString& indent);
+void dumpTree(const QmlDomObject& domObject, const QString& indent);
+
+void dumpProperty(const QmlDomProperty& prop, const QString& indent)
+{
+ const QmlDomValue val(prop.value());
+
+ switch (val.type()) {
+ case QmlDomValue::Invalid:
+ qDebug() << indent.toAscii().data() << prop.propertyName() << "(invalid)" << getDefault(prop);
+ break;
+
+ case QmlDomValue::List:
+ qDebug() << indent.toAscii().data() << prop.propertyName() << "(list)" << getDefault(prop);
+ dumpList(val.toList(), indent + SPACING);
+ break;
+
+ case QmlDomValue::Literal:
+ qDebug() << indent.toAscii().data() << prop.propertyName() << "->" << val.toLiteral().literal() << "(literal)" << getDefault(prop);
+ break;
+
+ case QmlDomValue::Object:
+ qDebug() << indent.toAscii().data() << prop.propertyName() << "->" << val.toObject().objectId() << "(object)" << getDefault(prop);
+ dumpTree(val.toObject(), indent + SPACING);
+ break;
+
+ case QmlDomValue::PropertyBinding:
+ qDebug() << indent.toAscii().data() << prop.propertyName() << "->" << val.toBinding().binding() << "(property binding)" << getDefault(prop);
+ break;
+
+ case QmlDomValue::ValueSource:
+ qDebug() << indent.toAscii().data() << prop.propertyName() << "->" << val.toValueSource().object().objectId() << "(value source)" << getDefault(prop);
+ break;
+
+ default:
+ qDebug() << indent.toAscii().data() << prop.propertyName() << "(unknown)" << getDefault(prop);
+ break;
+ }
+}
+
+void dumpList(const QmlDomList& list, const QString& indent)
+{
+ foreach (const QmlDomValue& val, list.values()) {
+ switch (val.type()) {
+ case QmlDomValue::Invalid:
+ qDebug() << indent.toAscii().data() << "(invalid)";
+ break;
+
+ case QmlDomValue::List:
+ qDebug() << indent.toAscii().data() << "(list)";
+ dumpList(val.toList(), indent + SPACING);
+ break;
+
+ case QmlDomValue::Literal:
+ qDebug() << indent.toAscii().data() << val.toLiteral().literal() << "(literal)";
+ break;
+
+ case QmlDomValue::Object:
+ qDebug() << indent.toAscii().data() << val.toObject().objectId() << "(object)";
+ dumpTree(val.toObject(), indent + SPACING);
+ break;
+
+ case QmlDomValue::PropertyBinding:
+ qDebug() << indent.toAscii().data() << val.toBinding().binding() << "(property binding)";
+ break;
+
+ case QmlDomValue::ValueSource:
+ qDebug() << indent.toAscii().data() << val.toValueSource().object().objectId() << "(value source)";
+ break;
+
+ default:
+ qDebug() << indent.toAscii().data() << "(unknown)";
+ break;
+ }
+ }
+}
+
+void dumpTree(const QmlDomObject& domObject, const QString& indent)
+{
+ qDebug() << (indent + "Object ID:").toAscii().data() << domObject.objectId() <<"Type: "<<domObject.objectType()<< "Class: " << domObject.objectClassName() << "Url: " << domObject.url().toString();
+
+ if (domObject.isComponent()) {
+ QString indent2 = indent + SPACING;
+ qDebug() << (indent2 + "isComponent").toAscii().data();
+ QmlDomComponent component = domObject.toComponent();
+ dumpTree(component.componentRoot(), indent2);
+ } else {
+ foreach (const QmlDomProperty& prop, domObject.properties()) {
+ QString indent2 = indent + SPACING;
+ dumpProperty(prop, indent2);
+ }
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication a(argc, argv);
+
+ QByteArray qml;
+
+ QStringList args = a.arguments();
+ args.removeFirst();
+ if (args.size() != 1) {
+ qDebug() << "add file name";
+ return -2;
+ }
+
+ QFile f(args.at(0));
+ if (!f.open(QFile::ReadOnly)) { qDebug() << "cannot open file" << args.at(0); return -3;}
+ qml = f.readAll();
+
+ QmlEngine engine;
+ QmlDomDocument doc;
+ if (!doc.load(&engine, qml, QUrl::fromLocalFile(QFileInfo(f.fileName()).absoluteFilePath()))) {
+ foreach (const QmlError &error, doc.errors())
+ qDebug() << QString("Error in %1, %2:%3: %4").arg(error.url().toString()).arg(error.line()).arg(error.column()).arg(error.description());
+ return -1;
+ }
+
+ qDebug() << "---------------------------";
+
+ foreach (const QmlDomImport &import, doc.imports())
+ qDebug() << "Import type " << (import.type() == QmlDomImport::Library ? "Library" : "File")
+ << "uri" << import.uri() << "qualifier" << import.qualifier() << "version" << import.version();
+ dumpTree(doc.rootObject(), "");
+ return 0;
+}
diff --git a/src/tools/qmldesigner/qmldom/qmldom.pro b/src/tools/qmldesigner/qmldom/qmldom.pro
new file mode 100644
index 0000000000..47b5aa44f2
--- /dev/null
+++ b/src/tools/qmldesigner/qmldom/qmldom.pro
@@ -0,0 +1,21 @@
+#-------------------------------------------------
+#
+# Project created by QtCreator 2009-04-09T15:54:21
+#
+#-------------------------------------------------
+
+!contains(QT_CONFIG, declarative) {
+ error("Qt is not configured with the declarative model.");
+}
+
+QT -= gui
+QT += declarative
+
+TARGET = qmldom
+CONFIG += console
+CONFIG -= app_bundle
+
+TEMPLATE = app
+
+
+SOURCES += main.cpp
diff --git a/src/tools/qmldesigner/standalone/128xBauhaus_Logo.png b/src/tools/qmldesigner/standalone/128xBauhaus_Logo.png
new file mode 100644
index 0000000000..dc680dae3e
--- /dev/null
+++ b/src/tools/qmldesigner/standalone/128xBauhaus_Logo.png
Binary files differ
diff --git a/src/tools/qmldesigner/standalone/16xBauhaus_Logo.png b/src/tools/qmldesigner/standalone/16xBauhaus_Logo.png
new file mode 100644
index 0000000000..851973b30a
--- /dev/null
+++ b/src/tools/qmldesigner/standalone/16xBauhaus_Logo.png
Binary files differ
diff --git a/src/tools/qmldesigner/standalone/256xBauhaus_Logo.png b/src/tools/qmldesigner/standalone/256xBauhaus_Logo.png
new file mode 100644
index 0000000000..9ead12ddf2
--- /dev/null
+++ b/src/tools/qmldesigner/standalone/256xBauhaus_Logo.png
Binary files differ
diff --git a/src/tools/qmldesigner/standalone/32xBauhaus_Logo.png b/src/tools/qmldesigner/standalone/32xBauhaus_Logo.png
new file mode 100644
index 0000000000..81aabba9d0
--- /dev/null
+++ b/src/tools/qmldesigner/standalone/32xBauhaus_Logo.png
Binary files differ
diff --git a/src/tools/qmldesigner/standalone/512xBauhaus_Logo.png b/src/tools/qmldesigner/standalone/512xBauhaus_Logo.png
new file mode 100644
index 0000000000..d0229f9c89
--- /dev/null
+++ b/src/tools/qmldesigner/standalone/512xBauhaus_Logo.png
Binary files differ
diff --git a/src/tools/qmldesigner/standalone/64xBauhaus_Logo.png b/src/tools/qmldesigner/standalone/64xBauhaus_Logo.png
new file mode 100644
index 0000000000..098b823c94
--- /dev/null
+++ b/src/tools/qmldesigner/standalone/64xBauhaus_Logo.png
Binary files differ
diff --git a/src/tools/qmldesigner/standalone/Info.plist b/src/tools/qmldesigner/standalone/Info.plist
new file mode 100644
index 0000000000..ef1502c73c
--- /dev/null
+++ b/src/tools/qmldesigner/standalone/Info.plist
@@ -0,0 +1,189 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDocumentTypes</key>
+ <array>
+ <dict>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ <key>CFBundleTypeIconFile</key>
+ <string>qtcreator.icns</string>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>pro</string>
+ </array>
+ <key>CFBundleTypeName</key>
+ <string>Qt Project File</string>
+ <key>LSHandlerRank</key>
+ <string>Default</string>
+ </dict>
+ <dict>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>pri</string>
+ </array>
+ <key>CFBundleTypeName</key>
+ <string>Qt Project Include File</string>
+ <key>LSHandlerRank</key>
+ <string>Default</string>
+ </dict>
+ <dict>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>qrc</string>
+ </array>
+ <key>CFBundleTypeName</key>
+ <string>Qt Resource File</string>
+ <key>LSHandlerRank</key>
+ <string>Default</string>
+ </dict>
+ <dict>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>pri</string>
+ </array>
+ <key>CFBundleTypeName</key>
+ <string>Qt UI File</string>
+ </dict>
+ <dict>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>h</string>
+ <string>hpp</string>
+ </array>
+ <key>CFBundleTypeName</key>
+ <string>Header File</string>
+ <key>CFBundleTypeOSTypes</key>
+ <array>
+ <string>TEXT</string>
+ <string>utxt</string>
+ </array>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ </dict>
+ <dict>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>cc</string>
+ <string>CC</string>
+ <string>cp</string>
+ <string>CP</string>
+ <string>cpp</string>
+ <string>CPP</string>
+ <string>cxx</string>
+ <string>CXX</string>
+ <string>c++</string>
+ <string>C++</string>
+ </array>
+ <key>CFBundleTypeName</key>
+ <string>C++ Source File</string>
+ <key>CFBundleTypeOSTypes</key>
+ <array>
+ <string>TEXT</string>
+ <string>utxt</string>
+ </array>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ </dict>
+ <dict>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>mm</string>
+ <string>MM</string>
+ </array>
+ <key>CFBundleTypeName</key>
+ <string>Objective-C++ Source File</string>
+ <key>CFBundleTypeOSTypes</key>
+ <array>
+ <string>TEXT</string>
+ <string>utxt</string>
+ </array>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ </dict>
+ <dict>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>m</string>
+ </array>
+ <key>CFBundleTypeName</key>
+ <string>Objective-C Source File</string>
+ <key>CFBundleTypeOSTypes</key>
+ <array>
+ <string>TEXT</string>
+ <string>utxt</string>
+ </array>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ </dict>
+ <dict>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>c</string>
+ <string>C</string>
+ </array>
+ <key>CFBundleTypeName</key>
+ <string>C Source File</string>
+ <key>CFBundleTypeOSTypes</key>
+ <array>
+ <string>TEXT</string>
+ <string>utxt</string>
+ </array>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ </dict>
+ <dict>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>txt</string>
+ <string>text</string>
+ </array>
+ <key>CFBundleTypeName</key>
+ <string>Text File</string>
+ <key>CFBundleTypeOSTypes</key>
+ <array>
+ <string>TEXT</string>
+ </array>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ </dict>
+ <dict>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>*</string>
+ </array>
+ <key>CFBundleTypeName</key>
+ <string>NSStringPboardType</string>
+ <key>CFBundleTypeOSTypes</key>
+ <array>
+ <string>****</string>
+ </array>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ </dict>
+ </array>
+ <key>CFBundleGetInfoString</key>
+ <string>Bauhaus; Copyright Nokia Corporation</string>
+ <key>CFBundleIconFile</key>
+ <string>@ICON@</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleSignature</key>
+ <string>@TYPEINFO@</string>
+ <key>CFBundleExecutable</key>
+ <string>@EXECUTABLE@</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.nokia.bauhaus</string>
+ <key>CFBundleVersion</key>
+ <string>1.0.0</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0.0</string>
+</dict>
+</plist>
diff --git a/src/tools/qmldesigner/standalone/aboutdialog.cpp b/src/tools/qmldesigner/standalone/aboutdialog.cpp
new file mode 100644
index 0000000000..db2b685381
--- /dev/null
+++ b/src/tools/qmldesigner/standalone/aboutdialog.cpp
@@ -0,0 +1,95 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "aboutdialog.h"
+#include "integrationcore.h"
+#include "pluginmanager.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QUrl>
+
+#include <QtGui/QApplication>
+#include <QtGui/QGridLayout>
+#include <QtGui/QTextEdit>
+#include <QtGui/QPushButton>
+
+
+static QString aboutText = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">"
+ "<html><head><style type=\"text/css\">\np, li { white-space: pre-wrap; }\n</style></head><body style=\"font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;\">"
+ "<p align=\"center\"><img src=\"logo\"/></p>"
+ "<h2 align=\"center\">Bauhaus</h2>"
+ "</body></html>";
+
+AboutDialog::AboutDialog(QWidget* parent):
+ QDialog(parent)
+{
+ setWindowFlags(windowFlags() | Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint);
+ setStyleSheet(QString("background-color: #FFFFFF;"));
+
+ QGridLayout* dialogLayout = new QGridLayout;
+ setLayout(dialogLayout);
+
+ QTextEdit* textArea = new QTextEdit(this);
+ textArea->setReadOnly(true);
+ textArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ textArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ textArea->setFrameShape(QFrame::NoFrame);
+ textArea->setLineWidth(0);
+ QImage logoImage = QImage(QString(":/128xBauhaus_Logo.png"));
+ textArea->document()->addResource(QTextDocument::ImageResource, QUrl("logo"), logoImage);
+ textArea->setHtml(aboutText);
+ dialogLayout->addWidget(textArea, 0, 0, 1, 3);
+
+ QPushButton* aboutPluginsButton = new QPushButton("About Plug-ins...", this);
+ dialogLayout->addWidget(aboutPluginsButton, 1, 0, 1, 1);
+ connect(aboutPluginsButton, SIGNAL(clicked()), this, SLOT(doAboutPlugins()));
+
+ QPushButton* aboutQtButton = new QPushButton("About Qt...", this);
+ dialogLayout->addWidget(aboutQtButton, 1, 1, 1, 1);
+ connect(aboutQtButton, SIGNAL(clicked()), qApp, SLOT(aboutQt()));
+
+ QPushButton* closeButton = new QPushButton("Close", this);
+ dialogLayout->addWidget(closeButton, 1, 2, 1, 1);
+ connect(closeButton, SIGNAL(clicked()), this, SLOT(close()));
+}
+
+void AboutDialog::go(QWidget* parent)
+{
+ AboutDialog dialog(parent);
+ dialog.setWindowTitle(tr("About Bauhaus", "AboutDialog"));
+ dialog.exec();
+}
+
+void AboutDialog::doAboutPlugins()
+{
+ QmlDesigner::IntegrationCore *core = QmlDesigner::IntegrationCore::instance();
+ QDialog* dialog = core->pluginManager()->createAboutPluginDialog(this);
+ dialog->setWindowFlags(Qt::Sheet);
+ dialog->exec();
+}
diff --git a/src/tools/qmldesigner/standalone/aboutdialog.h b/src/tools/qmldesigner/standalone/aboutdialog.h
new file mode 100644
index 0000000000..5feb08902e
--- /dev/null
+++ b/src/tools/qmldesigner/standalone/aboutdialog.h
@@ -0,0 +1,53 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef AboutDialog_h
+#define AboutDialog_h
+
+#include <QtGui/QDialog>
+
+
+/*!
+ This dialog could do with some animations and general beautification.
+ */
+class AboutDialog: public QDialog
+{
+ Q_OBJECT
+
+public:
+ static void go(QWidget* parent = 0);
+
+public slots:
+ void doAboutPlugins();
+
+private:
+ AboutDialog(QWidget* parent = 0);
+};
+
+#endif // AboutDialog_h
diff --git a/src/tools/qmldesigner/standalone/application.cpp b/src/tools/qmldesigner/standalone/application.cpp
new file mode 100644
index 0000000000..7c253ef17f
--- /dev/null
+++ b/src/tools/qmldesigner/standalone/application.cpp
@@ -0,0 +1,43 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "application.h"
+#include <QtCore/QCoreApplication>
+#include <QtCore/QFileInfo>
+
+QString Application::sharedDirPath()
+{
+ QString path = QCoreApplication::applicationDirPath();
+
+#ifdef Q_OS_MACX
+ path += "/../../..";
+#endif // Q_OS_MACX
+
+ return QFileInfo(path + "/../../../../share/qtcreator/qmldesigner/").absoluteFilePath();
+}
diff --git a/src/tools/qmldesigner/standalone/application.h b/src/tools/qmldesigner/standalone/application.h
new file mode 100644
index 0000000000..adf7f81001
--- /dev/null
+++ b/src/tools/qmldesigner/standalone/application.h
@@ -0,0 +1,40 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef APPLICATION_H
+#define APPLICATION_H
+
+#include <QtCore/QString>
+
+class Application {
+public:
+ static QString sharedDirPath();
+};
+
+#endif // APPLICATION_H
diff --git a/src/tools/qmldesigner/standalone/bauhaus-logo.icns b/src/tools/qmldesigner/standalone/bauhaus-logo.icns
new file mode 100644
index 0000000000..ab9758015a
--- /dev/null
+++ b/src/tools/qmldesigner/standalone/bauhaus-logo.icns
Binary files differ
diff --git a/src/tools/qmldesigner/standalone/bauhaus-macos.css b/src/tools/qmldesigner/standalone/bauhaus-macos.css
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/tools/qmldesigner/standalone/bauhaus-macos.css
diff --git a/src/tools/qmldesigner/standalone/bauhaus-windows.css b/src/tools/qmldesigner/standalone/bauhaus-windows.css
new file mode 100644
index 0000000000..6c5bf7d2c6
--- /dev/null
+++ b/src/tools/qmldesigner/standalone/bauhaus-windows.css
@@ -0,0 +1,3 @@
+QStatusBar {
+ border-top: 1px solid #b8b9b8;
+}
diff --git a/src/tools/qmldesigner/standalone/bauhaus-x11.css b/src/tools/qmldesigner/standalone/bauhaus-x11.css
new file mode 100644
index 0000000000..6c5bf7d2c6
--- /dev/null
+++ b/src/tools/qmldesigner/standalone/bauhaus-x11.css
@@ -0,0 +1,3 @@
+QStatusBar {
+ border-top: 1px solid #b8b9b8;
+}
diff --git a/src/tools/qmldesigner/standalone/bauhaus.css b/src/tools/qmldesigner/standalone/bauhaus.css
new file mode 100644
index 0000000000..32b97e3651
--- /dev/null
+++ b/src/tools/qmldesigner/standalone/bauhaus.css
@@ -0,0 +1,28 @@
+QTreeView#widgetTreeView {
+ background: #bababa;
+ border: 0px;
+ font-size: 11px;
+ selection-color: #fff;
+ selection-background-color: #3875d7;
+ font-variant: normal;
+}
+
+//QTreeView::item {
+// padding: 3px;
+//}
+//
+//QTreeView::item:selected {
+// border: 3px solid #ff0000;
+// padding: 3px;
+// background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #3c77ad, stop: 1 #003882);
+//}
+
+//QTreeView#widgetTreeView::item {
+// inactive, in favour of the 2 items above (for testing, as the QTreeView seems to contain a bug which prevents border/padding to work correctly
+// border: 1px solid #ff0000;
+//}
+
+QStackedWidget#widgetTreeStack {
+ background: #bababa;
+ border: 0px;
+}
diff --git a/src/tools/qmldesigner/standalone/bauhaus.ico b/src/tools/qmldesigner/standalone/bauhaus.ico
new file mode 100644
index 0000000000..d6e91cc255
--- /dev/null
+++ b/src/tools/qmldesigner/standalone/bauhaus.ico
Binary files differ
diff --git a/src/tools/qmldesigner/standalone/bauhaus.qrc b/src/tools/qmldesigner/standalone/bauhaus.qrc
new file mode 100644
index 0000000000..223d7115a1
--- /dev/null
+++ b/src/tools/qmldesigner/standalone/bauhaus.qrc
@@ -0,0 +1,19 @@
+<RCC>
+ <qresource prefix="/">
+ <file>toolbar-cssedit.png</file>
+ <file>toolbar-edit.png</file>
+ <file>bauhaus-windows.css</file>
+ <file>bauhaus-macos.css</file>
+ <file>bauhaus-x11.css</file>
+ <file>128xBauhaus_Logo.png</file>
+ <file>bauhaus.css</file>
+ <file alias="qmldesigner/templates/General/Empty QWidget">templates/qwidget.qml</file>
+ <file alias="qmldesigner/templates/General/Empty QGraphicsView">templates/qgraphicsview.qml</file>
+ <file>64xBauhaus_Logo.png</file>
+ <file>preview.png</file>
+ <file alias="qmldesigner/templates/General/Empty Fx">templates/fx.qml</file>
+ <file>16xBauhaus_Logo.png</file>
+ <file>256xBauhaus_Logo.png</file>
+ <file>32xBauhaus_Logo.png</file>
+ </qresource>
+</RCC>
diff --git a/src/tools/qmldesigner/standalone/css.png b/src/tools/qmldesigner/standalone/css.png
new file mode 100644
index 0000000000..3a2c2555c4
--- /dev/null
+++ b/src/tools/qmldesigner/standalone/css.png
Binary files differ
diff --git a/src/tools/qmldesigner/standalone/edit.png b/src/tools/qmldesigner/standalone/edit.png
new file mode 100644
index 0000000000..2a55a4576d
--- /dev/null
+++ b/src/tools/qmldesigner/standalone/edit.png
Binary files differ
diff --git a/src/tools/qmldesigner/standalone/main.cpp b/src/tools/qmldesigner/standalone/main.cpp
new file mode 100644
index 0000000000..21eb4f8e81
--- /dev/null
+++ b/src/tools/qmldesigner/standalone/main.cpp
@@ -0,0 +1,162 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <QtDebug>
+#include <QtCore/QFile>
+#include <QtCore/QTextStream>
+
+#include <QtGui/QApplication>
+
+#include <integrationcore.h>
+#include <pluginmanager.h>
+#include <model.h>
+
+#include <exception.h>
+#include "mainwindow.h"
+
+enum {
+ debug = false
+};
+
+static void doStyling(QApplication& app)
+{
+ QString ws;
+#ifdef Q_WS_MAC
+ ws = "macos";
+#endif // Q_WS_MAC
+
+#ifdef Q_WS_WIN
+ ws = "windows";
+#endif // Q_WS_WIN
+
+#ifdef Q_WS_X11
+ ws = "x11";
+#endif // Q_WS_X11
+
+ QFile platformCssFile(QString(":/bauhaus-%1.css").arg(ws));
+ platformCssFile.open(QIODevice::ReadOnly | QIODevice::Text);
+ QTextStream platformCssStream(&platformCssFile);
+ QString styleSheet(platformCssStream.readAll());
+ platformCssFile.close();
+
+ QFile genericCssFile(QLatin1String(":/bauhaus.css"));
+ genericCssFile.open(QIODevice::ReadOnly | QIODevice::Text);
+ QTextStream genericCssStream(&genericCssFile);
+ styleSheet.append(genericCssStream.readAll());
+ genericCssFile.close();
+
+ app.setStyleSheet(styleSheet);
+}
+
+static void parseArguments(const QStringList& argumentList, MainWindow& mainWindow)
+{
+ QStringList passArgumentList;
+ passArgumentList.append("--no-resync");
+ passArgumentList.append("-h");
+ passArgumentList.append("-graphicssystem");
+
+ for (int i = 1; i < argumentList.size(); ++i) {
+ if (argumentList[i].at(0) == QLatin1Char('-')) {
+ if (argumentList[i] == "--file" || argumentList[i] == "-file" || argumentList[i] == "-f") {
+ ++i;
+ if (i < argumentList.size()) {
+ mainWindow.openFile(argumentList[i]);
+ } else {
+ mainWindow.doOpen();
+ }
+ } else if (argumentList[i] == "--help" || argumentList[i] == "-h") {
+ qWarning() << "Usage: bauhaus [OPTION...]\n";
+ qWarning() << " -f, --file open this file";
+ qWarning() << " --no-resync disable rewriter";
+ exit(0);
+ } else if (passArgumentList.contains(argumentList[i].split("=").first())) {
+ } else {
+ qWarning() << "bauhaus: unrecognized option "<< argumentList[i];
+ qWarning() << "Try `bauhaus --help'";
+ exit(1);
+ }
+ } else {
+ mainWindow.openFile(argumentList[i]);
+ }
+ }
+}
+
+static QStringList pluginPaths()
+{
+ QStringList result;
+#ifdef Q_OS_MAC
+ result += QCoreApplication::applicationDirPath() + "/../PlugIns/Bauhaus/ItemLibs";
+#else // Q_OS_MAC
+ result += QCoreApplication::applicationDirPath() + "/../lib/itemlibs";
+#endif // Q_OS_MAC
+
+ return result;
+}
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+ Q_INIT_RESOURCE(bauhaus);
+
+ doStyling(app);
+
+#ifdef Q_WS_X11
+ QIcon applicationIcon;
+ applicationIcon.addFile(":/16xBauhaus_Log");
+ applicationIcon.addFile(":/32xBauhaus_Logo.png");
+ applicationIcon.addFile(":/64xBauhaus_Logo.png");
+ applicationIcon.addFile(":/128xBauhaus_Logo.png");
+ applicationIcon.addFile(":/256xBauhaus_Logo.png");
+ Q_ASSERT(!applicationIcon.isNull());
+ app.setWindowIcon(applicationIcon);
+#endif
+
+ QCoreApplication::setOrganizationName("Nokia");
+ QCoreApplication::setOrganizationDomain("nokia.com");
+ QCoreApplication::setApplicationName("Bauhaus");
+
+ try {
+ QmlDesigner::IntegrationCore core;
+ core.pluginManager()->setPluginPaths(pluginPaths());
+
+ MainWindow mainWindow;
+ mainWindow.show();
+
+ parseArguments(app.arguments(), mainWindow);
+
+// if (mainWindow.documentCount() == 0)
+// mainWindow.showWelcomeScreen();
+//
+ return app.exec();
+
+ } catch (const QmlDesigner::Exception &exception) {
+ qWarning() << exception;
+ return -1;
+ }
+}
diff --git a/src/tools/qmldesigner/standalone/mainwindow.cpp b/src/tools/qmldesigner/standalone/mainwindow.cpp
new file mode 100644
index 0000000000..77fe96551d
--- /dev/null
+++ b/src/tools/qmldesigner/standalone/mainwindow.cpp
@@ -0,0 +1,565 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <QtCore/QtDebug>
+#include <QtCore/QBuffer>
+#include <QtCore/QFileInfo>
+#include <QtCore/QSettings>
+
+#include <QtGui/QAction>
+#include <QtGui/QApplication>
+#include <QtGui/QBoxLayout>
+#include <QtGui/QCloseEvent>
+#include <QtGui/QErrorMessage>
+#include <QtGui/QFrame>
+#include <QtGui/QMessageBox>
+#include <QtGui/QSplitter>
+#include <QtGui/QStackedWidget>
+#include <QtGui/QStatusBar>
+#include <QFile>
+
+#include "aboutdialog.h"
+#include "allpropertiesviewcontroller.h"
+#include "designdocumentcontroller.h"
+#include "multipledocumentscontroller.h"
+#include "mainwindow.h"
+#include "stylemanager.h"
+#include "widgetboxcontroller.h"
+#include "navigatorcontroller.h"
+#include "stateseditorcontroller.h"
+#include "xuifiledialog.h"
+#include "welcomescreen.h"
+
+using namespace QmlDesigner;
+
+class StyleAction: public QAction
+{
+public:
+ StyleAction(const QString& text, const QString& styleName, QObject* parent): QAction(text, parent), m_styleName(styleName) {}
+ StyleAction(const QString& text, QObject* parent): QAction(text, parent), m_styleName(QString::null) {}
+
+ QString styleName() const { return m_styleName; }
+
+private:
+ QString m_styleName;
+};
+
+MainWindow::MainWindow(QWidget* parent):
+ QMainWindow(parent),
+ m_shutdown(false),
+ m_lastPath(QString::null),
+ m_documentCount(0),
+ m_menuBar(new QMenuBar(this)),
+ m_itemLibraryController(new ItemLibraryController(this)),
+ m_navigatorController(new NavigatorController(this)),
+ m_statesEditorController(new StatesEditorController(this)),
+ m_propertiesViewController(new AllPropertiesViewController(this)),
+ m_multipleDocumentsController(new MultipleDocumentsController(this)),
+ m_recentFilesMenu(0),
+ m_mainArea(new QStackedWidget(this)),
+ m_welcomeScreen(new WelcomeScreen(this))
+{
+ // setWindowFlags(Qt::MacWindowToolBarButtonHint);
+// setUnifiedTitleAndToolBarOnMac(true);
+ setObjectName(QLatin1String("mainWindow"));
+ setWindowTitle(tr("Bauhaus", "MainWindowClass"));
+ resize(1046, 700);
+
+ QFile file(":/qmldesigner/stylesheet.css");
+ file.open(QFile::ReadOnly);
+ QString styleSheet = QLatin1String(file.readAll());
+ setStyleSheet(styleSheet);
+
+ setMenuBar(m_menuBar);
+
+ createMenus();
+ createMainArea();
+ createStatusBar();
+
+ updateActions();
+ updateMainArea();
+
+ connect(m_multipleDocumentsController, SIGNAL(documentCountChanged(unsigned)), this, SLOT(documentCountChanged(unsigned)));
+ connect(m_welcomeScreen, SIGNAL(newFile(QString)), this, SLOT(newFile(QString)));
+ connect(m_welcomeScreen, SIGNAL(openFile(QString)), this, SLOT(openFile(QString)));
+}
+
+MainWindow::~MainWindow()
+{
+ m_documentActions.clear();
+}
+
+int MainWindow::documentCount() const
+{
+ return m_documentCount;
+}
+
+void MainWindow::closeEvent(QCloseEvent *event)
+{
+ m_shutdown = true;
+ m_multipleDocumentsController->closeAll(true);
+ event->setAccepted(false);
+}
+
+void MainWindow::doQuit()
+{
+ m_shutdown = true;
+ m_multipleDocumentsController->closeAll(true);
+}
+
+void MainWindow::createMenus()
+{
+ // File menu:
+ QMenu* fileMenu = new QMenu(tr("&File"), m_menuBar);
+ m_menuBar->addMenu(fileMenu);
+
+ QAction* newAction = new QAction(tr("&New..."), fileMenu);
+ newAction->setShortcut(QKeySequence(tr("Ctrl+N")));
+ connect(newAction, SIGNAL(triggered()), this, SLOT(doNew()));
+ fileMenu->addAction(newAction);
+
+ QAction* openAction = new QAction(tr("&Open..."), fileMenu);
+ openAction->setShortcut(QKeySequence(tr("Ctrl+O")));
+ connect(openAction, SIGNAL(triggered()), this, SLOT(doOpen()));
+ fileMenu->addAction(openAction);
+
+ m_recentFilesMenu = new QMenu(tr("Recent Files"), fileMenu);
+ connect(m_recentFilesMenu, SIGNAL(aboutToShow()), this, SLOT(showRecentFilesMenu()));
+ fileMenu->addMenu(m_recentFilesMenu);
+
+ fileMenu->addSeparator();
+
+ QAction* saveAction = new QAction(tr("&Save"), fileMenu);
+ saveAction->setShortcut(QKeySequence(tr("Ctrl+S")));
+ connect(saveAction, SIGNAL(triggered()), m_multipleDocumentsController, SLOT(doSave()));
+ fileMenu->addAction(saveAction);
+ m_documentActions.append(saveAction);
+
+ QAction* saveAsAction = new QAction(tr("Save &As..."), fileMenu);
+ connect(saveAsAction, SIGNAL(triggered()), m_multipleDocumentsController, SLOT(doSaveAs()));
+ fileMenu->addAction(saveAsAction);
+ m_documentActions.append(saveAsAction);
+
+ fileMenu->addSeparator();
+
+ m_previewAction = new QAction(tr("&Preview"), fileMenu);
+ m_previewAction->setShortcut(QKeySequence(tr("Ctrl+R")));
+// m_previewAction->setIcon(QIcon(":/preview.png"));
+ m_previewAction->setCheckable(true);
+ connect(m_previewAction, SIGNAL(toggled(bool)), m_multipleDocumentsController, SLOT(doPreview(bool)));
+ connect(m_multipleDocumentsController, SIGNAL(previewVisibilityChanged(bool)), m_previewAction, SLOT(setChecked(bool)));
+ fileMenu->addAction(m_previewAction);
+ m_documentActions.append(m_previewAction);
+
+ m_previewWithDebugAction = new QAction(tr("&Preview with Debug"), fileMenu);
+ m_previewWithDebugAction->setShortcut(QKeySequence(tr("Ctrl+D")));
+ m_previewWithDebugAction->setCheckable(true);
+ connect(m_previewWithDebugAction, SIGNAL(toggled(bool)), m_multipleDocumentsController, SLOT(doPreviewWithDebug(bool)));
+ connect(m_multipleDocumentsController, SIGNAL(previewWithDebugVisibilityChanged(bool)), m_previewWithDebugAction, SLOT(setChecked(bool)));
+ fileMenu->addAction(m_previewWithDebugAction);
+ m_documentActions.append(m_previewWithDebugAction);
+
+#ifndef Q_WS_MAC
+ fileMenu->addSeparator();
+#endif // !Q_WS_MAC
+
+ QAction* quitAction = new QAction(tr("&Quit"), fileMenu);
+ quitAction->setShortcut(QKeySequence(tr("Ctrl+Q")));
+ fileMenu->addAction(quitAction);
+ connect(quitAction, SIGNAL(triggered()), this, SLOT(doQuit()));
+
+ // Edit menu:
+ QMenu* editMenu = new QMenu(tr("&Edit"), m_menuBar);
+ m_menuBar->addMenu(editMenu);
+
+ QAction* undoAction = m_multipleDocumentsController->undoAction();
+ undoAction->setParent(editMenu);
+ undoAction->setShortcut(tr("Ctrl+Z"));
+ editMenu->addAction(undoAction);
+
+ QAction* redoAction = m_multipleDocumentsController->redoAction();
+ redoAction->setParent(editMenu);
+#ifdef Q_WS_WIN
+ redoAction->setShortcut(tr("Ctrl+Y"));
+#else // !Q_WS_WIN
+ redoAction->setShortcut(tr("Ctrl+Shift+Z"));
+#endif // Q_WS_WIN
+ editMenu->addAction(redoAction);
+
+ editMenu->addSeparator();
+
+ QAction *copyAction = new QAction(tr("&Copy"), editMenu);
+ connect(copyAction, SIGNAL(triggered()), m_multipleDocumentsController, SLOT(doCopy()));
+ copyAction->setShortcuts(QList<QKeySequence>() << QKeySequence(QKeySequence::Copy));
+ editMenu->addAction(copyAction);
+ m_documentActions.append(copyAction);
+
+ QAction *cutAction = new QAction(tr("&Cut"), editMenu);
+ connect(cutAction, SIGNAL(triggered()), m_multipleDocumentsController, SLOT(doCut()));
+ cutAction->setShortcuts(QList<QKeySequence>() << QKeySequence(QKeySequence::Cut));
+ editMenu->addAction(cutAction);
+ m_documentActions.append(cutAction);
+
+ QAction *pasteAction = new QAction(tr("&Paste"), editMenu);
+ connect(pasteAction, SIGNAL(triggered()), m_multipleDocumentsController, SLOT(doPaste()));
+ pasteAction->setShortcuts(QList<QKeySequence>() << QKeySequence(QKeySequence::Paste));
+ editMenu->addAction(pasteAction);
+ m_documentActions.append(pasteAction);
+
+ QAction *deleteAction = new QAction(tr("&Delete"), editMenu);
+ connect(deleteAction, SIGNAL(triggered()), m_multipleDocumentsController, SLOT(doDelete()));
+ deleteAction->setShortcuts(QList<QKeySequence>() << QKeySequence(tr("Del")) << QKeySequence(tr("Backspace")));
+ editMenu->addAction(deleteAction);
+ m_documentActions.append(deleteAction);
+
+ // View menu:
+ QMenu* viewMenu = new QMenu(tr("&View"), m_menuBar);
+ m_menuBar->addMenu(viewMenu);
+//
+// m_showNewLookPropertiesAction = viewMenu->addAction(tr("&New Look Properties"));
+// m_showNewLookPropertiesAction->setCheckable(true);
+// m_showNewLookPropertiesAction->setEnabled(false);
+// connect(m_showNewLookPropertiesAction, SIGNAL(triggered()), m_propertiesViewController, SLOT(showNewLookProperties()));
+// m_documentActions.append(m_showNewLookPropertiesAction);
+//
+// m_showTraditionalPropertiesAction = viewMenu->addAction(tr("&Traditional Properties"));
+// m_showTraditionalPropertiesAction->setCheckable(true);
+// m_showTraditionalPropertiesAction->setEnabled(false);
+// connect(m_showTraditionalPropertiesAction, SIGNAL(triggered()), m_propertiesViewController, SLOT(showTraditionalProperties()));
+// m_documentActions.append(m_showTraditionalPropertiesAction);
+//
+// QActionGroup* propertiesLookGroup = new QActionGroup(this);
+// propertiesLookGroup->addAction(m_showNewLookPropertiesAction);
+// propertiesLookGroup->addAction(m_showTraditionalPropertiesAction);
+// m_showNewLookPropertiesAction->setChecked(true);
+
+// viewMenu->addSeparator();
+
+#ifdef ENABLE_TEXT_VIEW
+ QAction* showFormAction = m_multipleDocumentsController->showFormAction(viewMenu);
+ viewMenu->addAction(showFormAction);
+ QAction* showTextAction = m_multipleDocumentsController->showTextAction(viewMenu);
+ viewMenu->addAction(showTextAction);
+
+ QActionGroup* formTextGroup = new QActionGroup(this);
+ formTextGroup->addAction(showFormAction);
+ formTextGroup->addAction(showTextAction);
+ showFormAction->setChecked(true);
+
+ viewMenu->addSeparator();
+#endif // ENABLE_TEXT_VIEW
+
+ // Style selection:
+// QMenu* styleMenu = viewMenu->addMenu("&Style");
+// QActionGroup* styleGroup = new QActionGroup(this);
+//
+// StyleAction* defaultStyleAction = new StyleAction("&Default", viewMenu);
+// styleMenu->addAction(defaultStyleAction);
+// defaultStyleAction->setCheckable(true);
+// styleGroup->addAction(defaultStyleAction);
+// connect(defaultStyleAction, SIGNAL(triggered()), this, SLOT(styleActionTriggered()));
+//
+// styleMenu->addSeparator();
+//
+// foreach (const QString styleName, StyleManager::styles()) {
+// StyleAction* styleAction = new StyleAction(styleName, styleName, viewMenu);
+// styleMenu->addAction(styleAction);
+// styleAction->setCheckable(true);
+// styleGroup->addAction(styleAction);
+// connect(styleAction, SIGNAL(triggered()), this, SLOT(styleActionTriggered()));
+// }
+//
+// defaultStyleAction->setChecked(true);
+
+ // Help menu:
+ QMenu* helpMenu = new QMenu(tr("&Help"), this);
+ helpMenu->setObjectName(QString::fromAscii("helpMenu"));
+ m_menuBar->addMenu(helpMenu);
+
+ QAction* aboutAppAction = new QAction(tr("&About..."), this);
+ aboutAppAction->setObjectName(QString::fromAscii("aboutAppAction"));
+ connect(aboutAppAction, SIGNAL(triggered()), this, SLOT(doAbout()));
+ helpMenu->addAction(aboutAppAction);
+}
+
+void MainWindow::showRecentFilesMenu()
+{
+ m_recentFilesMenu->clear();
+ foreach (const QString &path, recentFiles()) {
+ QAction *action = m_recentFilesMenu->addAction(path);
+ action->setData(path);
+ connect(action, SIGNAL(triggered()), this, SLOT(doOpen()));
+ }
+}
+
+void MainWindow::styleActionTriggered()
+{
+ //### remove setStyle()
+// StyleAction* source = dynamic_cast<StyleAction*>(sender());
+//
+// if (source) {
+// QString styleName = source->styleName();
+//
+// if (styleName.isNull()) {
+// } else {
+// StyleManager::setStyle(styleName);
+// }
+// }
+}
+
+void MainWindow::createMainArea()
+{
+ QSplitter* mainSplitter = new QSplitter(this);
+ mainSplitter->setObjectName("mainSplitter");
+
+ // Left area:
+ QSplitter* leftSplitter = new QSplitter(mainSplitter);
+ leftSplitter->setObjectName("leftSplitter");
+ leftSplitter->setOrientation(Qt::Vertical);
+ {
+ QSizePolicy policy = leftSplitter->sizePolicy();
+ policy.setHorizontalStretch(0);
+ policy.setHorizontalPolicy(QSizePolicy::Preferred);
+ leftSplitter->setSizePolicy(policy);
+ }
+
+ leftSplitter->addWidget(m_navigatorController->widget());
+
+ QTabWidget *leftBottomTabWidget = new QTabWidget(this);
+ leftBottomTabWidget->addTab(m_itemLibraryController->widget(), "Library");
+ leftBottomTabWidget->addTab(m_propertiesViewController->widget(), tr("Properties"));
+ leftSplitter->addWidget(leftBottomTabWidget);
+
+ // right area:
+ QSplitter *rightSplitter = new QSplitter(mainSplitter);
+ rightSplitter->setObjectName("rightSplitter");
+ rightSplitter->setOrientation(Qt::Vertical);
+
+ rightSplitter->addWidget(m_statesEditorController->widget());
+ rightSplitter->addWidget(m_multipleDocumentsController->tabWidget());
+ {
+ QSizePolicy policy = m_multipleDocumentsController->tabWidget()->sizePolicy();
+ policy.setHorizontalStretch(1);
+ policy.setHorizontalPolicy(QSizePolicy::Expanding);
+ m_multipleDocumentsController->tabWidget()->setSizePolicy(policy);
+ }
+
+ // Finishing touches:
+ mainSplitter->setSizes(QList<int>() << 240 << 530);
+ rightSplitter->setSizes(QList<int>() << 100 << 400);
+ leftSplitter->setSizes(QList<int>() << 300 << 300);
+
+ // Wire everything together:
+ connect(m_multipleDocumentsController, SIGNAL(activeDocumentChanged(DesignDocumentController*)),
+ m_itemLibraryController, SLOT(show(DesignDocumentController*)));
+ connect(m_multipleDocumentsController, SIGNAL(documentClosed(DesignDocumentController*)),
+ m_itemLibraryController, SLOT(close(DesignDocumentController*)));
+
+ connect(m_multipleDocumentsController, SIGNAL(activeDocumentChanged(DesignDocumentController*)),
+ m_navigatorController, SLOT(show(DesignDocumentController*)));
+ connect(m_multipleDocumentsController, SIGNAL(documentClosed(DesignDocumentController*)),
+ m_navigatorController, SLOT(close(DesignDocumentController*)));
+
+ connect(m_multipleDocumentsController, SIGNAL(activeDocumentChanged(DesignDocumentController*)),
+ m_statesEditorController, SLOT(show(DesignDocumentController*)));
+ connect(m_multipleDocumentsController, SIGNAL(documentClosed(DesignDocumentController*)),
+ m_statesEditorController, SLOT(close(DesignDocumentController*)));
+
+ connect(m_multipleDocumentsController, SIGNAL(activeDocumentChanged(DesignDocumentController*)),
+ m_propertiesViewController, SLOT(show(DesignDocumentController*)));
+ connect(m_multipleDocumentsController, SIGNAL(documentClosed(DesignDocumentController*)),
+ m_propertiesViewController, SLOT(close(DesignDocumentController*)));
+
+ m_mainArea->addWidget(m_welcomeScreen);
+ m_mainArea->addWidget(mainSplitter);
+ setCentralWidget(m_mainArea);
+}
+
+void MainWindow::createStatusBar()
+{
+// statusBar();
+}
+
+void MainWindow::doNew()
+{
+// QWizard wizard;
+// Internal::FormTemplateWizardPage page;
+// wizard.addPage(&page);
+// wizard.setWindowTitle("New Component Wizard");
+// if (wizard.exec() != QDialog::Accepted)
+// return;
+
+ QFile file(":/qmldesigner/templates/General/Empty Fx");
+ file.open(QFile::ReadOnly);
+ newFile(file.readAll());
+// newFile(page.templateContents().toLatin1());
+}
+
+void MainWindow::doOpen()
+{
+ if (QAction *senderAction = qobject_cast<QAction*>(sender())) {
+ if (senderAction->data().isValid()) {
+ // from recent files menu
+ QString path = senderAction->data().toString();
+ openFile(path);
+ return;
+ }
+ }
+ XUIFileDialog::runOpenFileDialog(m_lastPath, this, this, SLOT(openFile(QString)));
+}
+
+void MainWindow::openFile(const QString &fileName)
+{
+// qDebug() << "openFile("+fileName+")";
+//
+ if (fileName.isNull())
+ return;
+
+ m_lastPath = QFileInfo(fileName).path();
+
+ QString errorMessage;
+
+ QFile file(fileName);
+ if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ errorMessage = tr("Could not open file <%1>").arg(fileName);
+ } else {
+ DesignDocumentController* controller = new DesignDocumentController(m_multipleDocumentsController);
+ controller->setFileName(fileName);
+ QList<QmlDesigner::RewriterView::Error> errors = controller->loadMaster(file.readAll());
+ if (errors.isEmpty()) {
+ connect(controller, SIGNAL(fileToOpen(QString)), this, SLOT(openFile(QString)));
+ m_multipleDocumentsController->open(controller);
+ addRecentFile(QFileInfo(file).absoluteFilePath());
+ } else {
+ errorMessage = serializeErrors(errors);
+ delete controller;
+ }
+ }
+
+ if (!errorMessage.isEmpty()) {
+ QErrorMessage msgBox(this);
+ msgBox.showMessage(errorMessage);
+ msgBox.exec();
+ }
+}
+
+void MainWindow::newFile(const QString &templateName)
+{
+ if (templateName.isNull())
+ return;
+
+ QFile file(templateName);
+ if (!file.open(QFile::ReadOnly))
+ return;
+
+ newFile(file.readAll());
+}
+
+void MainWindow::doAbout()
+{
+ AboutDialog::go(this);
+}
+
+void MainWindow::documentCountChanged(unsigned newCount)
+{
+ if (m_documentCount == newCount)
+ return;
+ m_documentCount = newCount;
+
+ if (!m_shutdown) {
+ updateActions();
+ updateMainArea();
+ }
+}
+
+void MainWindow::updateActions()
+{
+ bool enable = m_documentCount != 0;
+ foreach (QAction *documentAction, m_documentActions)
+ documentAction->setEnabled(enable);
+}
+
+void MainWindow::updateMainArea()
+{
+ if (m_multipleDocumentsController->activeDocumentCount() == 0) {
+ m_welcomeScreen->setRecentFiles(recentFiles());
+ m_mainArea->setCurrentIndex(0); // welcome screen
+ } else {
+ m_mainArea->setCurrentIndex(1);
+ }
+}
+
+void MainWindow::newFile(const QByteArray &templateContents)
+{
+ DesignDocumentController *controller = new DesignDocumentController(m_multipleDocumentsController);
+ QList<QmlDesigner::RewriterView::Error> errors = controller->loadMaster(templateContents);
+
+ if (errors.isEmpty()) {
+ connect(controller, SIGNAL(fileToOpen(QString)), this, SLOT(openFile(QString)));
+ m_multipleDocumentsController->open(controller);
+ } else {
+ delete controller;
+ QErrorMessage msgBox(this);
+ msgBox.showMessage(serializeErrors(errors));
+ msgBox.exec();
+ }
+}
+
+QStringList MainWindow::recentFiles() const
+{
+ const QSettings settings;
+ return settings.value("recentFiles", QStringList()).toStringList();
+}
+
+void MainWindow::addRecentFile(const QString &path)
+{
+ QSettings settings;
+ QStringList files = settings.value("recentFiles", QStringList()).toStringList();
+
+ files.removeAll(path);
+ if (files.size() > 10)
+ files.removeLast();
+ files.prepend(path);
+
+ settings.setValue("recentFiles", files);
+}
+
+QString MainWindow::serializeErrors(const QList<QmlDesigner::RewriterView::Error> &errors)
+{
+ if (errors.isEmpty())
+ return QString();
+ QString errorMsg = tr("Qml Errors:");
+ foreach (const QmlDesigner::RewriterView::Error &error, errors) {
+ if (!error.url().isEmpty())
+ errorMsg.append(tr("\n%1 %2:%3 - %4").arg(error.url().toString(), QString(error.line()), QString(error.column()), error.description()));
+ else
+ errorMsg.append(tr("\n%1:%2 - %3").arg(QString(error.line()), QString(error.column()), error.description()));
+ }
+ return errorMsg;
+}
diff --git a/src/tools/qmldesigner/standalone/mainwindow.h b/src/tools/qmldesigner/standalone/mainwindow.h
new file mode 100644
index 0000000000..d78a439b30
--- /dev/null
+++ b/src/tools/qmldesigner/standalone/mainwindow.h
@@ -0,0 +1,120 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QtCore/QList>
+#include <QtCore/QString>
+
+#include <QtGui/QMainWindow>
+#include <QtGui/QMenuBar>
+#include <QtGui/QMenu>
+#include <QtGui/QStackedWidget>
+
+#include "rewriterview.h"
+
+class QmlError;
+class WelcomeScreen;
+
+namespace QmlDesigner {
+ class ItemLibraryController;
+ class NavigatorController;
+ class StatesEditorController;
+ class AllPropertiesViewController;
+ class MultipleDocumentsController;
+}
+
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ MainWindow(QWidget* parent = 0);
+ ~MainWindow();
+
+ int documentCount() const;
+
+public slots:
+ void documentCountChanged(unsigned newCount);
+ void openFile(const QString &fileName);
+ void newFile(const QString &fileTemplate);
+
+ void doNew();
+ void doOpen();
+ void doQuit();
+ void doAbout();
+
+protected:
+ void closeEvent(QCloseEvent *event);
+
+private slots:
+ void showRecentFilesMenu();
+ void styleActionTriggered();
+
+private:
+ void createMenus();
+ void createMainArea();
+ void createMainEditArea();
+ void createMainStyleArea();
+ void createStatusBar();
+ void updateActions();
+ void updateMainArea();
+
+ void newFile(const QByteArray &templateContents);
+
+ QStringList recentFiles() const;
+ void addRecentFile(const QString &path);
+
+ QString serializeErrors(const QList<QmlDesigner::RewriterView::Error> &errors);
+
+private:
+ bool m_shutdown;
+ QString m_lastPath;
+ QList<QAction*> m_documentActions;
+ unsigned int m_documentCount;
+
+ QMenuBar* m_menuBar;
+
+ QmlDesigner::ItemLibraryController* m_itemLibraryController;
+ QmlDesigner::NavigatorController* m_navigatorController;
+ QmlDesigner::StatesEditorController* m_statesEditorController;
+ QmlDesigner::AllPropertiesViewController* m_propertiesViewController;
+ QmlDesigner::MultipleDocumentsController* m_multipleDocumentsController;
+ QAction* m_previewAction;
+ QAction* m_previewWithDebugAction;
+ QAction* m_showNewLookPropertiesAction;
+ QAction* m_showTraditionalPropertiesAction;
+ QMenu* m_recentFilesMenu;
+
+ QStackedWidget *m_mainArea;
+ WelcomeScreen *m_welcomeScreen;
+};
+
+#endif // MAINWINDOW_H
diff --git a/src/tools/qmldesigner/standalone/preview.png b/src/tools/qmldesigner/standalone/preview.png
new file mode 100644
index 0000000000..496498ff9a
--- /dev/null
+++ b/src/tools/qmldesigner/standalone/preview.png
Binary files differ
diff --git a/src/tools/qmldesigner/standalone/standalone.pro b/src/tools/qmldesigner/standalone/standalone.pro
new file mode 100644
index 0000000000..f0e8fb093f
--- /dev/null
+++ b/src/tools/qmldesigner/standalone/standalone.pro
@@ -0,0 +1,44 @@
+!contains(QT_CONFIG, declarative) {
+ error("Qt is not configured with the declarative model.");
+}
+
+TEMPLATE = app
+CONFIG(debug, debug|release):CONFIG += console
+TARGET = bauhaus
+macx:TARGET = Bauhaus
+CONFIG += qt
+CONFIG += webkit
+QT += gui opengl
+
+HEADERS += \
+ aboutdialog.h \
+ mainwindow.h \
+ application.h \
+ welcomescreen.h
+
+SOURCES += \
+ aboutdialog.cpp \
+ main.cpp \
+ mainwindow.cpp \
+ application.cpp \
+ welcomescreen.cpp
+
+include(../../../plugins/qmldesigner/config.pri)
+include(../../../plugins/qmldesigner/components/integration/integration.pri)
+include(../../../plugins/qmldesigner/components/propertyeditor/propertyeditor.pri)
+include(../../../plugins/qmldesigner/components/formeditor/formeditor.pri)
+include(../../../plugins/qmldesigner/components/navigator/navigator.pri)
+include(../../../plugins/qmldesigner/components/stateseditor/stateseditor.pri)
+include(../../../plugins/qmldesigner/components/itemlibrary/itemlibrary.pri)
+include(../../../plugins/qmldesigner/components/resources/resources.pri)
+include(../../../plugins/qmldesigner/components/pluginmanager/pluginmanager.pri)
+include(../../../plugins/qmldesigner/components/themeloader/qts60stylethemeio.pri)
+include (../../../plugins/qmldesigner/core/core.pri)
+RESOURCES += bauhaus.qrc
+win32:RC_FILE = bauhaus.rc
+macx {
+ ICON = bauhaus-logo.icns
+ QMAKE_INFO_PLIST = Info.plist
+}
+QMAKE_CXXFLAGS_HIDESYMS=""
+
diff --git a/src/tools/qmldesigner/standalone/templates/fx.qml b/src/tools/qmldesigner/standalone/templates/fx.qml
new file mode 100644
index 0000000000..0732fa811b
--- /dev/null
+++ b/src/tools/qmldesigner/standalone/templates/fx.qml
@@ -0,0 +1,7 @@
+import Qt 4.6
+
+Item {
+ id: RootItem
+ width: 640
+ height: 480
+}
diff --git a/src/tools/qmldesigner/standalone/templates/qgraphicsview.qml b/src/tools/qmldesigner/standalone/templates/qgraphicsview.qml
new file mode 100644
index 0000000000..f85b2cf238
--- /dev/null
+++ b/src/tools/qmldesigner/standalone/templates/qgraphicsview.qml
@@ -0,0 +1,10 @@
+import Qt 4.6
+
+QGraphicsView {
+ objectName: "view"
+ width: 300
+ height: 300
+ scene: QGraphicsScene {
+ objectName: "scene"
+ }
+}
diff --git a/src/tools/qmldesigner/standalone/templates/qwidget.qml b/src/tools/qmldesigner/standalone/templates/qwidget.qml
new file mode 100644
index 0000000000..568eedce10
--- /dev/null
+++ b/src/tools/qmldesigner/standalone/templates/qwidget.qml
@@ -0,0 +1,9 @@
+import Qt 4.6
+
+QWidget {
+ objectName: "Form"
+ x: 300
+ y: 200
+ width: 455
+ height: 376
+}
diff --git a/src/tools/qmldesigner/standalone/toolbar-cssedit.png b/src/tools/qmldesigner/standalone/toolbar-cssedit.png
new file mode 100644
index 0000000000..423d1b04b3
--- /dev/null
+++ b/src/tools/qmldesigner/standalone/toolbar-cssedit.png
Binary files differ
diff --git a/src/tools/qmldesigner/standalone/toolbar-edit.png b/src/tools/qmldesigner/standalone/toolbar-edit.png
new file mode 100644
index 0000000000..8c2f4c1209
--- /dev/null
+++ b/src/tools/qmldesigner/standalone/toolbar-edit.png
Binary files differ
diff --git a/src/tools/qmldesigner/standalone/welcomescreen.cpp b/src/tools/qmldesigner/standalone/welcomescreen.cpp
new file mode 100644
index 0000000000..778f7e1ed6
--- /dev/null
+++ b/src/tools/qmldesigner/standalone/welcomescreen.cpp
@@ -0,0 +1,150 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "welcomescreen.h"
+#include "application.h"
+
+#include <QtGui/QBoxLayout>
+#include <QtDeclarative/QmlView>
+#include <QtDeclarative/QmlGraphicsItem>
+#include <QtDeclarative/QmlContext>
+#include <QtCore/QCoreApplication>
+
+RecentFileModel::RecentFileModel(QObject *parent) :
+ QListModelInterface(parent)
+{
+}
+
+void RecentFileModel::setRecentFiles(const QStringList &filePaths)
+{
+ QStringList oldPaths = m_paths;
+ m_paths.clear();
+ if (oldPaths.size() > 0) {
+ emit itemsRemoved(0, oldPaths.size());
+ }
+
+ m_paths = filePaths;
+
+ if (m_paths.size() > 0) {
+ emit itemsInserted(0, m_paths.size());
+ }
+}
+
+int RecentFileModel::count() const
+{
+ return m_paths.size();
+}
+
+QHash<int, QVariant> RecentFileModel::data(int index, const QList<int> &/*roles*/) const
+{
+ QHash<int,QVariant> dataHash;
+
+ dataHash.insert(NameRole, displayPath(m_paths.at(index)));
+ dataHash.insert(FileNameRole, m_paths.at(index));
+ return dataHash;
+}
+
+QVariant RecentFileModel::data(int index, int role) const
+{
+ if (role == NameRole)
+ return displayPath(m_paths.at(index));
+ if (role == FileNameRole)
+ return m_paths.at(index);
+ return QVariant();
+}
+
+QList<int> RecentFileModel::roles() const
+{
+ return QList<int>() << NameRole << FileNameRole;
+}
+
+QString RecentFileModel::toString(int role) const
+{
+ switch (role) {
+ case NameRole: return "name"; break;
+ case FileNameRole: return "fileName"; break;
+ default: Q_ASSERT_X(0, Q_FUNC_INFO, "Unknown role");
+ }
+ return QString();
+}
+
+QString RecentFileModel::displayPath(const QString &filePath) const
+{
+ QString displayPath = filePath;
+ while (displayPath.length() > 25 && displayPath.contains('/')) {
+ displayPath.remove(0, displayPath.indexOf('/') + 1);
+ }
+
+ if (displayPath != filePath)
+ displayPath.prepend("../");
+
+ return displayPath;
+}
+
+WelcomeScreen::WelcomeScreen(QWidget *parent) :
+ QWidget(parent),
+ m_view(new QmlView(this)),
+ m_recentFileModel(new RecentFileModel(this))
+{
+ m_view->setUrl(QUrl::fromLocalFile(Application::sharedDirPath() + "welcomescreen.qml"));
+ m_view->setContentResizable(true);
+
+ QmlContext *context = m_view->rootContext();
+ context->setContextProperty(QLatin1String("recentFiles"), m_recentFileModel);
+
+ m_view->execute();
+
+ QObject *rootItem = m_view->root();
+ connect(rootItem, SIGNAL(openFile()), this, SLOT(openFile()));
+
+ QBoxLayout *layout = new QBoxLayout(QBoxLayout::LeftToRight, this);
+ layout->setMargin(0);
+ layout->addWidget(m_view);
+
+ QPalette palette;
+ palette.setColor(QPalette::Window, QColor(0x2e, 0x2e, 0x2e));
+ setPalette(palette);
+ setBackgroundRole(QPalette::Window);
+ setAutoFillBackground(true);
+}
+
+void WelcomeScreen::setRecentFiles(const QStringList &files)
+{
+ m_recentFileModel->setRecentFiles(files);
+}
+
+void WelcomeScreen::openFile()
+{
+ QString filePath = m_view->root()->property("selectedFile").toString();
+ if (filePath.startsWith(':')) {
+ emit newFile(filePath);
+ } else {
+ emit openFile(filePath);
+ }
+}
diff --git a/src/tools/qmldesigner/standalone/welcomescreen.h b/src/tools/qmldesigner/standalone/welcomescreen.h
new file mode 100644
index 0000000000..07debdfbd3
--- /dev/null
+++ b/src/tools/qmldesigner/standalone/welcomescreen.h
@@ -0,0 +1,77 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include <QtCore/QMetaType>
+#include <QtGui/QDialog>
+#include <private/qlistmodelinterface_p.h>
+
+class QmlView;
+
+class RecentFileModel : public QListModelInterface {
+ Q_OBJECT
+public:
+ enum Roles {
+ NameRole,
+ FileNameRole
+ };
+
+ RecentFileModel(QObject *parent = 0);
+ void setRecentFiles(const QStringList &filePaths);
+
+ int count() const;
+ QHash<int, QVariant> data(int index, const QList<int> &roles = QList<int>()) const;
+ QVariant data(int index, int role) const;
+ QList<int> roles() const;
+ QString toString(int role) const;
+private:
+ QString displayPath(const QString &filePath) const;
+
+ QStringList m_paths;
+};
+
+class WelcomeScreen : public QWidget {
+ Q_OBJECT
+
+public:
+ WelcomeScreen(QWidget *parent);
+ void setRecentFiles(const QStringList &recentFiles);
+
+signals:
+ void appExit();
+ void openFile(const QString &filePath);
+ void newFile(const QString &templatePath);
+
+private slots:
+ void openFile();
+
+private:
+ QmlView *m_view;
+ RecentFileModel *m_recentFileModel;
+};
+
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro
index 28111c1bd3..502e14c741 100644
--- a/tests/auto/auto.pro
+++ b/tests/auto/auto.pro
@@ -6,4 +6,5 @@ SUBDIRS += \
fakevim \
# profilereader \
aggregation \
- changeset
+ changeset \
+ qml
diff --git a/tests/auto/qml/qml.pro b/tests/auto/qml/qml.pro
new file mode 100644
index 0000000000..cc8224d5e7
--- /dev/null
+++ b/tests/auto/qml/qml.pro
@@ -0,0 +1,3 @@
+TEMPLATE = subdirs
+
+SUBDIRS += qmldesigner
diff --git a/tests/auto/qml/qmldesigner/bauhaustests/bauhaustests.pro b/tests/auto/qml/qmldesigner/bauhaustests/bauhaustests.pro
new file mode 100644
index 0000000000..19398348f9
--- /dev/null
+++ b/tests/auto/qml/qmldesigner/bauhaustests/bauhaustests.pro
@@ -0,0 +1,18 @@
+include(../../../../../src/plugins/qmldesigner/config.pri)
+QT += testlib
+
+DESTDIR = $$DESIGNER_BINARY_DIRECTORY
+include(../../../../../src/plugins/qmldesigner/core/core.pri)
+
+##DEFINES += DONT_MESS_WITH_QDEBUG
+
+DEPENDPATH += ..
+DEPENDPATH += ../../../../../src/plugins/qmldesigner/core/include
+
+TARGET = tst_bauhaus
+CONFIG += console
+CONFIG -= app_bundle
+TEMPLATE = app
+SOURCES += testbauhaus.cpp
+HEADERS += testbauhaus.h
+DEFINES += WORKDIR=\\\"$$DESTDIR\\\"
diff --git a/tests/auto/qml/qmldesigner/bauhaustests/testbauhaus.cpp b/tests/auto/qml/qmldesigner/bauhaustests/testbauhaus.cpp
new file mode 100644
index 0000000000..f400025552
--- /dev/null
+++ b/tests/auto/qml/qmldesigner/bauhaustests/testbauhaus.cpp
@@ -0,0 +1,122 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "testbauhaus.h"
+
+#include <QProcess>
+#include <QFileInfo>
+#include <QDir>
+#include <QDebug>
+
+QStringList failures;
+
+
+TestBauhaus::TestBauhaus()
+ : QObject()
+{
+}
+
+void TestBauhaus::initTestCase()
+{
+}
+
+void loadFile(const QString &fileName)
+{
+ QProcess process;
+ qDebug() << "starting: " << fileName;
+ QVERIFY(QFileInfo(fileName).exists());
+#ifdef Q_OS_WIN
+ const QString bauhausExecutable = "bauhaus.exe";
+#else
+ const QString bauhausExecutable = QDir::current().absoluteFilePath("bauhaus");
+#endif
+ QVERIFY(QFileInfo(bauhausExecutable).isExecutable());
+ process.start(bauhausExecutable, QStringList() << fileName);
+ if (!process.waitForStarted())
+ QFAIL(fileName.toLatin1());
+ if (!QProcess::Running == process.state()) {
+ QFAIL(fileName.toLatin1());
+ failures << fileName;
+ }
+ QTest::qWait(5000);
+ if (!QProcess::Running == process.state()) {
+ QFAIL(fileName.toLatin1());
+ failures << fileName;
+ }
+}
+
+void loadAllFiles(const QString &path)
+{
+ QDir::setCurrent(WORKDIR);
+ QVERIFY(QFileInfo(path).exists());
+ QDir dir(path);
+ foreach (const QString &file, dir.entryList(QStringList() << "*.qml", QDir::Files))
+ loadFile(path + "/" + file);
+ foreach (const QString &directory, dir.entryList(QStringList(), QDir::AllDirs | QDir::NoDotAndDotDot))
+ loadAllFiles(path + "/" + directory);
+}
+
+void TestBauhaus::cleanupTestCase()
+{
+}
+
+void TestBauhaus::loadExamples()
+{
+ failures.clear();
+ QString qtdir;
+ foreach (const QString &string, QProcess::systemEnvironment())
+ if (string.contains("qtdir", Qt::CaseInsensitive))
+ qtdir = string.split("=").last();
+ if (qtdir.isEmpty())
+ qWarning() << "QTDIR has to be set";
+ QVERIFY(!qtdir.isEmpty());
+ QVERIFY(QFileInfo(qtdir + "/examples/declarative").exists());
+ loadAllFiles(qtdir + "/examples/declarative");
+ qDebug() << failures;
+ QVERIFY(failures.isEmpty());
+}
+
+void TestBauhaus::loadDemos()
+{
+ failures.clear();
+ QString qtdir;
+ foreach (const QString &string, QProcess::systemEnvironment())
+ if (string.contains("qtdir", Qt::CaseInsensitive))
+ qtdir = string.split("=").last();
+ if (qtdir.isEmpty())
+ qWarning() << "QTDIR has to be set";
+ QVERIFY(!qtdir.isEmpty());
+ QVERIFY(QFileInfo(qtdir + "/demos/declarative").exists());
+ loadAllFiles(qtdir + "/demos/declarative");
+ qDebug() << failures;
+ QVERIFY(failures.isEmpty());
+}
+
+
+QTEST_MAIN(TestBauhaus);
diff --git a/tests/auto/qml/qmldesigner/bauhaustests/testbauhaus.h b/tests/auto/qml/qmldesigner/bauhaustests/testbauhaus.h
new file mode 100644
index 0000000000..f501917b38
--- /dev/null
+++ b/tests/auto/qml/qmldesigner/bauhaustests/testbauhaus.h
@@ -0,0 +1,51 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef TESTBAUHAUS_H
+#define TESTBAUHAUS_H
+
+#include <QObject>
+
+#include <QtTest>
+
+
+class TestBauhaus : public QObject
+{
+ Q_OBJECT
+public:
+ TestBauhaus();
+
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void loadExamples();
+ void loadDemos();
+};
+
+#endif // TESTBAUHAUS_H
diff --git a/tests/auto/qml/qmldesigner/common/statichelpers.cpp b/tests/auto/qml/qmldesigner/common/statichelpers.cpp
new file mode 100644
index 0000000000..02a36031d7
--- /dev/null
+++ b/tests/auto/qml/qmldesigner/common/statichelpers.cpp
@@ -0,0 +1,174 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+static QStringList pluginPaths()
+{
+ QStringList result;
+#ifdef Q_OS_MAC
+ result += QCoreApplication::applicationDirPath() + "/Bauhaus.app/Contents/PlugIns/Bauhaus/ItemLibs";
+#else // Q_OS_MAC
+ result += QCoreApplication::applicationDirPath() + "/../lib/itemlibs";
+#endif // Q_OS_MAC
+
+ return result;
+}
+
+static void testMessageOutput(QtMsgType type, const char *msg)
+ {
+ switch (type) {
+ case QtDebugMsg:
+#ifdef QDEBUG_IN_TESTS
+ std::fprintf(stderr, "Debug: %s\n", msg);
+#endif // QDEBUG_IN_TESTS
+ break;
+ case QtWarningMsg:
+#ifdef WARNINGS_IN_TESTS
+ std::fprintf(stderr, "Warning: %s\n", msg);
+#endif // WARNINGS_IN_TESTS
+ break;
+ case QtCriticalMsg:
+ std::fprintf(stderr, "Critical: %s\n", msg);
+ break;
+ case QtFatalMsg:
+ std::fprintf(stderr, "Fatal: %s\n", msg);
+ break;
+ }
+ }
+
+static QString bareTemplate("import Qt 4.6\n"
+ "Item { id: parentItem;"
+ " %1"
+ "}");
+static QString contentsTemplate(bareTemplate.arg("Text { id: textChild; x:10; y: 10; text: \"%1\"; %2 }"));
+
+
+void printErrors(const QList<QmlError> &errors, const QString &fileName)
+{
+ if (errors.isEmpty())
+ return;
+
+ qDebug() << "Error loading file \"" << fileName << "\":";
+
+ foreach (const QmlError &error, errors) {
+ qDebug() << error.line() << ":" << error.column() << ": " << error.description();
+ }
+}
+
+// TODO: this need to e updated for states
+static bool compareProperty(const AbstractProperty &property1, const AbstractProperty &property2)
+{
+ return (property1.name() == property2.name());
+// && (property1.value().type() == property2.value().type());
+// && (property1.value() == property2.value()));
+}
+
+// TODO: this need to e updated for states
+static bool compareTree(const ModelNode &node1, const ModelNode &node2)
+{
+ if (!node1.isValid() || !node2.isValid()) {
+ return false;
+ }
+
+ if (node1.type() != node2.type()) {
+ return false;
+ }
+
+ // Compare properties
+ {
+ const QList<AbstractProperty> propList1 = node1.properties();
+ const QList<AbstractProperty> propList2 = node2.properties();
+
+ QList<AbstractProperty>::const_iterator iter1 = propList1.constBegin();
+ QList<AbstractProperty>::const_iterator iter2 = propList2.constBegin();
+ for (;
+ iter1 != propList1.constEnd() && iter2 != propList2.constEnd();
+ iter1++, iter2++) {
+ if (!compareProperty(*iter1, *iter2))
+ return false;
+ }
+
+ if (iter1 != propList1.constEnd() || iter2 != propList2.constEnd())
+ return false;
+ }
+
+ // Compare list of childs
+ {
+ const QList<ModelNode> childList1 = node1.allDirectSubModelNodes();
+ const QList<ModelNode> childList2 = node2.allDirectSubModelNodes();
+
+ QList<ModelNode>::const_iterator iter1;
+ QList<ModelNode>::const_iterator iter2;
+ for (iter1 = childList1.constBegin(), iter2 = childList2.constBegin();
+ iter1 != childList1.constEnd() && iter2 != childList2.constEnd();
+ iter1++, iter2++) {
+ if (!compareTree((*iter1), (*iter2)))
+ return false;
+ }
+
+ if (iter1 != childList1.constEnd() || iter2 != childList2.constEnd())
+ return false;
+ }
+ return true;
+}
+
+//void load(const QString &data, Model *&model, ByteArrayModifier *&modifier)
+//{
+// model = 0;
+// QByteArray bytes = data.toLatin1();
+// QBuffer file(&bytes, 0);
+// QVERIFY(file.open(QIODevice::ReadOnly));
+// QList<QmlError> errors;
+// QString fileText(file.readAll());
+// modifier = ByteArrayModifier::create(QString(fileText));
+// model = Model::create(modifier, QUrl(), &errors);
+//
+// if (!errors.isEmpty()) {
+// printErrors(errors, "<inline>");
+// }
+//
+// file.close();
+//}
+
+//void reload(const QString &data, ByteArrayModifier *modifier)
+//{
+// modifier->setText(data);
+//}
+
+//static Model* create(const QString& document)
+//{
+// ByteArrayModifier* modifier = 0;
+// Model *model = 0;
+//
+// load(document, model, modifier);
+//
+// if (modifier && model)
+// modifier->setParent(model);
+//
+// return model;
+//}
diff --git a/tests/auto/qml/qmldesigner/coretests/coretests.pro b/tests/auto/qml/qmldesigner/coretests/coretests.pro
new file mode 100644
index 0000000000..9ed993bb04
--- /dev/null
+++ b/tests/auto/qml/qmldesigner/coretests/coretests.pro
@@ -0,0 +1,22 @@
+include(../../../../../src/plugins/qmldesigner/config.pri)
+QT += testlib \
+ script \
+ declarative
+DESTDIR = $$DESIGNER_BINARY_DIRECTORY
+include(../../../../../src/plugins/qmldesigner/core/core.pri)
+DEFINES+=QTCREATOR_UTILS_STATIC_LIB
+
+DEPENDPATH += ..
+DEPENDPATH += ../../../../../src/plugins/qmldesigner/core/include
+
+TARGET = tst_qmldesigner_core
+CONFIG += console
+CONFIG -= app_bundle
+TEMPLATE = app
+SOURCES += testcore.cpp \
+ ../testview.cpp \
+ testrewriterview.cpp
+HEADERS += testcore.h \
+ ../testview.h \
+ testrewriterview.h
+RESOURCES += ../data/testfiles.qrc
diff --git a/tests/auto/qml/qmldesigner/coretests/testcore.cpp b/tests/auto/qml/qmldesigner/coretests/testcore.cpp
new file mode 100644
index 0000000000..54974e8328
--- /dev/null
+++ b/tests/auto/qml/qmldesigner/coretests/testcore.cpp
@@ -0,0 +1,6485 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "testcore.h"
+
+#include <QScopedPointer>
+#include <QLatin1String>
+
+#include <metainfo.h>
+#include <model.h>
+#include <modelmerger.h>
+#include <modelnode.h>
+#include <qmlanchors.h>
+#include <invalididexception.h>
+#include <invalidmodelnodeexception.h>
+#include <nodeinstanceview.h>
+#include <nodeinstance.h>
+#include <QDebug>
+
+#include "../testview.h"
+#include <variantproperty.h>
+#include <abstractproperty.h>
+#include <bindingproperty.h>
+#include <nodeproperty.h>
+
+#include <nodelistproperty.h>
+#include <nodeabstractproperty.h>
+#include <plaintexteditmodifier.h>
+#include <componenttextmodifier.h>
+
+#include <bytearraymodifier.h>
+#include "testrewriterview.h"
+
+#include <QPlainTextEdit>
+#include <private/qmlstate_p.h>
+
+
+using namespace QmlDesigner;
+#include <cstdio>
+#include "../common/statichelpers.cpp"
+
+TestCore::TestCore()
+ : QObject()
+{
+}
+
+void TestCore::initTestCase()
+{
+#ifndef QDEBUG_IN_TESTS
+ qInstallMsgHandler(testMessageOutput);
+#endif
+ MetaInfo::setPluginPaths(pluginPaths());
+ Exception::setShouldAssert(false);
+}
+
+void TestCore::cleanupTestCase()
+{
+ MetaInfo::clearGlobal();
+}
+
+void TestCore::testModelCreateCoreModel()
+{
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> testView(new TestView);
+ QVERIFY(testView.data());
+ model->attachView(testView.data());
+
+ QVERIFY(testView->rootModelNode().isValid());
+ NodeInstanceView *nodeInstanceView = new NodeInstanceView(model.data());
+ model->attachView(nodeInstanceView);
+ model->detachView(nodeInstanceView);
+}
+
+// TODO: this need to e updated for states
+void TestCore::loadEmptyCoreModel()
+{
+ QList<QmlError> errors;
+ QFile file(":/fx/empty.qml");
+ QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));
+
+ QPlainTextEdit textEdit1;
+ textEdit1.setPlainText(file.readAll());
+ PlainTextEditModifier modifier1(&textEdit1);
+
+ QScopedPointer<Model> model1(Model::create("Qt/Item"));
+
+ QScopedPointer<TestRewriterView> testRewriterView1(new TestRewriterView());
+ testRewriterView1->setTextModifier(&modifier1);
+ model1->attachView(testRewriterView1.data());
+
+ QPlainTextEdit textEdit2;
+ textEdit2.setPlainText("import Qt 4.6; Item{}");
+ PlainTextEditModifier modifier2(&textEdit2);
+
+ QScopedPointer<Model> model2(Model::create("Qt/item"));
+
+ QScopedPointer<TestRewriterView> testRewriterView2(new TestRewriterView());
+ testRewriterView2->setTextModifier(&modifier2);
+ model2->attachView(testRewriterView2.data());
+
+ QVERIFY(compareTree(testRewriterView1->rootModelNode(), testRewriterView2->rootModelNode()));
+}
+
+void TestCore::testRewriterView()
+{
+ try {
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText("import Qt 4.6;\n\nItem {\n}\n");
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ ModelNode rootModelNode(view->rootModelNode());
+ QVERIFY(rootModelNode.isValid());
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+ model->attachView(testRewriterView.data());
+
+ ModelNode childNode(rootModelNode.addChildNode("Qt/Item", 4, 6, "data"));
+ QVERIFY(childNode.isValid());
+
+ childNode.changeType("Qt/Rectangle", 4, 6);
+ childNode.setId("childNode");
+
+ ModelNode childNode2(childNode.addChildNode("Qt/Rectangle", 4, 6, "data"));
+ childNode2.setId("childNode2");
+ ModelNode childNode3(childNode2.addChildNode("Qt/Rectangle", 4, 6, "data"));
+ childNode3.setId("childNode3");
+ ModelNode childNode4(childNode3.addChildNode("Qt/Rectangle", 4, 6, "data"));
+ childNode4.setId("childNode4");
+
+ QVERIFY(childNode.isValid());
+ QVERIFY(childNode2.isValid());
+ QVERIFY(childNode3.isValid());
+ QVERIFY(childNode4.isValid());
+
+ testRewriterView->setModificationGroupActive(true);
+
+ childNode.destroy();
+
+ QVERIFY(!childNode.isValid());
+ QVERIFY(!childNode2.isValid());
+ QVERIFY(!childNode3.isValid());
+ QVERIFY(!childNode4.isValid());
+
+ QVERIFY(testRewriterView->modelToTextMerger()->isNodeScheduledForRemoval(childNode));
+ QVERIFY(!testRewriterView->modelToTextMerger()->isNodeScheduledForRemoval(childNode2));
+ QVERIFY(!testRewriterView->modelToTextMerger()->isNodeScheduledForRemoval(childNode3));
+ QVERIFY(!testRewriterView->modelToTextMerger()->isNodeScheduledForRemoval(childNode4));
+
+ QVERIFY(!rootModelNode.hasProperty(QLatin1String("data")));
+
+ testRewriterView->modelToTextMerger()->applyChanges();
+
+ childNode = rootModelNode.addChildNode("Qt/Rectangle", 4, 6, "data");
+ QVERIFY(testRewriterView->modelToTextMerger()->isNodeScheduledForAddition(childNode));
+
+ testRewriterView->modelToTextMerger()->applyChanges();
+
+ childNode.variantProperty("x") = 70;
+ childNode.variantProperty("y") = 90;
+
+ QCOMPARE(testRewriterView->modelToTextMerger()->findAddedVariantProperty(childNode.variantProperty("x")).value(), QVariant(70));
+ QCOMPARE(testRewriterView->modelToTextMerger()->findAddedVariantProperty(childNode.variantProperty("y")).value(), QVariant(90));
+
+ model->detachView(testRewriterView.data());
+ } catch (Exception &e) {
+ QFAIL(qPrintable(e.description()));
+ }
+}
+
+void TestCore::testRewriterErrors()
+{
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText("import Qt 4.6;\n\nItem {\n}\n");
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ ModelNode rootModelNode(view->rootModelNode());
+ QVERIFY(rootModelNode.isValid());
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+ model->attachView(testRewriterView.data());
+
+ QVERIFY(testRewriterView->errors().isEmpty());
+ textEdit.setPlainText("import Qt 4.6;\n\nError {\n}\n");
+ QVERIFY(!testRewriterView->errors().isEmpty());
+
+ textEdit.setPlainText("import Qt 4.6;\n\nItem {\n}\n");
+ QVERIFY(testRewriterView->errors().isEmpty());
+}
+
+void TestCore::saveEmptyCoreModel()
+{
+ QList<QmlError> errors;
+ QFile file(":/fx/empty.qml");
+ QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));
+
+ QPlainTextEdit textEdit1;
+ textEdit1.setPlainText(file.readAll());
+ PlainTextEditModifier modifier1(&textEdit1);
+
+ QScopedPointer<Model> model1(Model::create("Qt/Item"));
+
+ QScopedPointer<TestRewriterView> testRewriterView1(new TestRewriterView());
+ testRewriterView1->setTextModifier(&modifier1);
+ model1->attachView(testRewriterView1.data());
+
+
+ QBuffer buffer;
+ buffer.open(QIODevice::ReadWrite | QIODevice::Text);
+ modifier1.save(&buffer);
+
+ QPlainTextEdit textEdit2;
+ textEdit2.setPlainText("import Qt 4.6; Item{}");
+ PlainTextEditModifier modifier2(&textEdit2);
+
+ QScopedPointer<Model> model2(Model::create("Qt/item"));
+
+ QScopedPointer<TestRewriterView> testRewriterView2(new TestRewriterView());
+ testRewriterView2->setTextModifier(&modifier2);
+ model2->attachView(testRewriterView2.data());
+
+ QVERIFY(compareTree(testRewriterView1->rootModelNode(), testRewriterView2->rootModelNode()));
+
+}
+
+void TestCore::loadAttributesInCoreModel()
+{
+ QList<QmlError> errors;
+ QFile file(":/fx/attributes.qml");
+ QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));
+
+ QPlainTextEdit textEdit1;
+ textEdit1.setPlainText(file.readAll());
+ PlainTextEditModifier modifier1(&textEdit1);
+
+ QScopedPointer<Model> model1(Model::create("Qt/Item"));
+
+ QScopedPointer<TestRewriterView> testRewriterView1(new TestRewriterView());
+ testRewriterView1->setTextModifier(&modifier1);
+ model1->attachView(testRewriterView1.data());
+
+ QPlainTextEdit textEdit2;
+ textEdit2.setPlainText("import Qt 4.6; Item{}");
+ PlainTextEditModifier modifier2(&textEdit2);
+
+ QScopedPointer<Model> model2(Model::create("Qt/item"));
+
+ QScopedPointer<TestRewriterView> testRewriterView2(new TestRewriterView());
+ testRewriterView2->setTextModifier(&modifier2);
+ model2->attachView(testRewriterView2.data());
+
+ ModelNode rootModelNode = testRewriterView2->rootModelNode();
+
+ rootModelNode.setId("theItem");
+ rootModelNode.variantProperty("x").setValue(QVariant(300));
+ rootModelNode.variantProperty("visible").setValue(true);
+ rootModelNode.variantProperty("scale").setValue(0.5);
+
+ QVERIFY(compareTree(testRewriterView1->rootModelNode(), testRewriterView2->rootModelNode()));
+}
+
+void TestCore::saveAttributesInCoreModel()
+{
+ QFile file(":/fx/attributes.qml");
+ QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));
+
+ QPlainTextEdit textEdit1;
+ textEdit1.setPlainText(file.readAll());
+ PlainTextEditModifier modifier1(&textEdit1);
+
+ QScopedPointer<Model> model1(Model::create("Qt/Item"));
+
+ QScopedPointer<TestRewriterView> testRewriterView1(new TestRewriterView());
+ testRewriterView1->setTextModifier(&modifier1);
+ model1->attachView(testRewriterView1.data());
+
+ QVERIFY(testRewriterView1->errors().isEmpty());
+
+ QBuffer buffer;
+ buffer.open(QIODevice::ReadWrite | QIODevice::Text);
+ modifier1.save(&buffer);
+
+ QPlainTextEdit textEdit2;
+ textEdit2.setPlainText(buffer.data());
+ PlainTextEditModifier modifier2(&textEdit2);
+
+ QScopedPointer<Model> model2(Model::create("Qt/Item"));
+
+ QScopedPointer<TestRewriterView> testRewriterView2(new TestRewriterView());
+ testRewriterView2->setTextModifier(&modifier2);
+ model2->attachView(testRewriterView2.data());
+
+ QVERIFY(testRewriterView2->errors().isEmpty());
+
+ QVERIFY(compareTree(testRewriterView1->rootModelNode(), testRewriterView2->rootModelNode()));
+}
+
+void TestCore::testModelCreateRect()
+{
+ try {
+
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ QVERIFY(view->rootModelNode().isValid());
+ ModelNode childNode = view->rootModelNode().addChildNode("Qt/Rectangle", 4, 6, "data");
+ QVERIFY(childNode.isValid());
+ QVERIFY(view->rootModelNode().allDirectSubModelNodes().contains(childNode));
+ QVERIFY(childNode.parentProperty().parentModelNode() == view->rootModelNode());
+ QCOMPARE(childNode.simplifiedTypeName(), QString("Rectangle"));
+
+ QVERIFY(childNode.id().isEmpty());
+
+ childNode.setId("Rect01");
+ QCOMPARE(childNode.id(), QString("Rect01"));
+
+ childNode.variantProperty("x") = 100;
+ childNode.variantProperty("y") = 100;
+ childNode.variantProperty("width") = 100;
+ childNode.variantProperty("height") = 100;
+
+ QCOMPARE(childNode.propertyNames().count(), 4);
+ QCOMPARE(childNode.variantProperty("scale").value(), QVariant());
+
+ } catch (Exception &exception) {
+ QFAIL("Exception thrown");
+ }
+
+}
+
+void TestCore::loadComponentPropertiesInCoreModel()
+{
+ QFile file(":/fx/properties.qml");
+ QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));
+
+ QPlainTextEdit textEdit1;
+ textEdit1.setPlainText(file.readAll());
+ PlainTextEditModifier modifier1(&textEdit1);
+
+ QScopedPointer<Model> model1(Model::create("Qt/Item"));
+
+ QScopedPointer<TestRewriterView> testRewriterView1(new TestRewriterView());
+ testRewriterView1->setTextModifier(&modifier1);
+ model1->attachView(testRewriterView1.data());
+
+ QVERIFY(testRewriterView1->rootModelNode().variantProperty("pushed").isDynamic());
+ QVERIFY(!testRewriterView1->rootModelNode().variantProperty("pushed").value().isValid());
+
+ QPlainTextEdit textEdit2;
+ textEdit2.setPlainText("import Qt 4.6; Item{}");
+ PlainTextEditModifier modifier2(&textEdit2);
+
+ QScopedPointer<Model> model2(Model::create("Qt/Item"));
+
+ QScopedPointer<TestRewriterView> testRewriterView2(new TestRewriterView());
+ testRewriterView2->setTextModifier(&modifier2);
+ model2->attachView(testRewriterView2.data());
+
+ testRewriterView2->rootModelNode().variantProperty("pushed").setDynamicTypeNameAndValue("bool", QVariant());
+
+ QVERIFY(compareTree(testRewriterView1->rootModelNode(), testRewriterView2->rootModelNode()));
+}
+
+void TestCore::loadSubItems()
+{
+ QFile file(QCoreApplication::applicationDirPath() + "/../tests/data/fx/topitem.qml");
+ QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));
+
+ QPlainTextEdit textEdit1;
+ textEdit1.setPlainText(file.readAll());
+ PlainTextEditModifier modifier1(&textEdit1);
+
+ QScopedPointer<Model> model1(Model::create("Qt/Item"));
+
+ QScopedPointer<TestRewriterView> testRewriterView1(new TestRewriterView());
+ testRewriterView1->setTextModifier(&modifier1);
+ model1->attachView(testRewriterView1.data());
+}
+
+
+void TestCore::createInvalidCoreModel()
+{
+ QScopedPointer<Model> invalidModel(Model::create("ItemSUX"));
+ //QVERIFY(!invalidModel.data()); //#no direct ype checking in model atm
+
+ QScopedPointer<Model> invalidModel2(Model::create("InvalidNode"));
+ //QVERIFY(!invalidModel2.data());
+}
+
+void TestCore::testModelCreateSubNode()
+{
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ QList<TestView::MethodCall> expectedCalls;
+ expectedCalls << TestView::MethodCall("modelAttached", QStringList() << QString::number(reinterpret_cast<long>(model.data())));
+ QCOMPARE(view->methodCalls(), expectedCalls);
+
+ QVERIFY(view->rootModelNode().isValid());
+ ModelNode childNode = view->rootModelNode().addChildNode("Qt/Rectangle", 4, 6, "data");
+ QVERIFY(childNode.isValid());
+ QVERIFY(view->rootModelNode().allDirectSubModelNodes().contains(childNode));
+ QVERIFY(childNode.parentProperty().parentModelNode() == view->rootModelNode());
+ QCOMPARE(childNode.simplifiedTypeName(), QString("Rectangle"));
+
+ expectedCalls << TestView::MethodCall("nodeCreated", QStringList() << "");
+ expectedCalls << TestView::MethodCall("nodeReparented", QStringList() << "" << "data" << "" << "PropertiesAdded");
+ QCOMPARE(view->methodCalls(), expectedCalls);
+
+ QVERIFY(childNode.id().isEmpty());
+ childNode.setId("Blah");
+ QCOMPARE(childNode.id(), QString("Blah"));
+
+ expectedCalls << TestView::MethodCall("nodeIdChanged", QStringList() << "Blah" << "Blah" << "");
+ QCOMPARE(view->methodCalls(), expectedCalls);
+
+ try {
+ childNode.setId("");
+ QFAIL("Setting an invalid id does not throw an exception");
+ } catch (Exception &exception) {
+ QCOMPARE(exception.type(), QString("InvalidIdException"));
+ }
+ try {
+ childNode.setId(QString());
+ QFAIL("Setting an invalid id does not throw an exception");
+ } catch (Exception &exception) {
+ QCOMPARE(exception.type(), QString("InvalidIdException"));
+ }
+ try {
+ childNode.setId("invalid id");
+ QFAIL("Setting an invalid id does not throw an excxeption");
+ } catch (Exception &exception) {
+ QCOMPARE(exception.type(), QString("InvalidIdException"));
+ }
+
+ QCOMPARE(childNode.id(), QString("Blah"));
+ QCOMPARE(view->methodCalls(), expectedCalls);
+}
+
+
+void TestCore::testTypicalRewriterOperations()
+{
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ ModelNode rootModelNode = view->rootModelNode();
+ QCOMPARE(rootModelNode.allDirectSubModelNodes().count(), 0);
+
+ QVERIFY(rootModelNode.property("test").isValid());
+ QVERIFY(!rootModelNode.property("test").isVariantProperty());
+ QVERIFY(!rootModelNode.property("test").isBindingProperty());
+
+ QVERIFY(rootModelNode.variantProperty("test").isValid());
+ QVERIFY(!rootModelNode.hasProperty("test"));
+
+ rootModelNode.variantProperty("test") = 70;
+
+ QVERIFY(rootModelNode.hasProperty("test"));
+ QVERIFY(rootModelNode.property("test").isVariantProperty());
+ QCOMPARE(rootModelNode.variantProperty("test").value(), QVariant(70));
+
+ rootModelNode.bindingProperty("test") = "parent.x";
+ QVERIFY(!rootModelNode.property("test").isVariantProperty());
+ QVERIFY(rootModelNode.property("test").isBindingProperty());
+
+ QCOMPARE(rootModelNode.bindingProperty("test").expression(), QString("parent.x"));
+
+ ModelNode childNode(rootModelNode.addChildNode("Qt/Rectangle", 4 ,6, "data"));
+ rootModelNode.nodeListProperty("test").reparentHere(childNode);
+ QCOMPARE(childNode.parentProperty(), rootModelNode.nodeAbstractProperty("test"));
+ QVERIFY(rootModelNode.property("test").isNodeAbstractProperty());
+ QVERIFY(rootModelNode.property("test").isNodeListProperty());
+ QVERIFY(!rootModelNode.property("test").isBindingProperty());
+ QVERIFY(childNode.parentProperty().isNodeListProperty());
+ QCOMPARE(childNode, childNode.parentProperty().toNodeListProperty().toModelNodeList().first());
+ QCOMPARE(rootModelNode, childNode.parentProperty().parentModelNode());
+ QCOMPARE(childNode.parentProperty().name(), QString("test"));
+
+ QVERIFY(!rootModelNode.property("test").isVariantProperty());
+ rootModelNode.variantProperty("test") = 90;
+ QVERIFY(rootModelNode.property("test").isVariantProperty());
+ QCOMPARE(rootModelNode.variantProperty("test").value(), QVariant(90));
+
+}
+
+void TestCore::testBasicStates()
+{
+ char qmlString[] = "import Qt 4.6\n"
+ "Rectangle {\n"
+ "id: root;\n"
+ "Rectangle {\n"
+ "id: rect1;\n"
+ "}\n"
+ "Rectangle {\n"
+ "id: rect2;\n"
+ "}\n"
+ "states: [\n"
+ "State {\n"
+ "name: \"state1\"\n"
+ "PropertyChanges {\n"
+ "target: rect1\n"
+ "}\n"
+ "PropertyChanges {\n"
+ "target: rect2\n"
+ "}\n"
+ "}\n"
+ ","
+ "State {\n"
+ "name: \"state2\"\n"
+ "PropertyChanges {\n"
+ "target: rect1\n"
+ "}\n"
+ "PropertyChanges {\n"
+ "target: rect2;\n"
+ "x: 10;\n"
+ "}\n"
+ "}\n"
+ "]\n"
+ "}\n";
+
+ Exception::setShouldAssert(true);
+
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ ModelNode rootModelNode(view->rootModelNode());
+ QVERIFY(rootModelNode.isValid());
+ QCOMPARE(rootModelNode.type(), QString("Qt/Item"));
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+
+ model->attachView(testRewriterView.data());
+ QVERIFY(rootModelNode.isValid());
+ QCOMPARE(rootModelNode.type(), QString("Qt/Rectangle"));
+
+ QVERIFY(rootModelNode.hasProperty("data"));
+
+ QVERIFY(rootModelNode.property("data").isNodeListProperty());
+
+ QCOMPARE(rootModelNode.nodeListProperty("data").toModelNodeList().count(), 2);
+
+ ModelNode rect1 = rootModelNode.nodeListProperty("data").toModelNodeList().first();
+ ModelNode rect2 = rootModelNode.nodeListProperty("data").toModelNodeList().last();
+
+ QVERIFY(QmlItemNode(rect1).isValid());
+ QVERIFY(QmlItemNode(rect2).isValid());
+
+ QVERIFY(QmlItemNode(rootModelNode).isValid());
+
+ QCOMPARE(QmlItemNode(rootModelNode).states().allStates().count(), 2);
+ QCOMPARE(QmlItemNode(rootModelNode).states().names().count(), 2);
+ QCOMPARE(QmlItemNode(rootModelNode).states().names().first(), QString("state1"));
+ QCOMPARE(QmlItemNode(rootModelNode).states().names().last(), QString("state2"));
+
+ //
+ // QmlModelState API tests
+ //
+ QmlModelState state1 = QmlItemNode(rootModelNode).states().state("state1");
+ QmlModelState state2 = QmlItemNode(rootModelNode).states().state("state2");
+
+ QVERIFY(state1.isValid());
+ QVERIFY(state2.isValid());
+
+ QCOMPARE(state1.propertyChanges().count(), 2);
+ QCOMPARE(state2.propertyChanges().count(), 2);
+
+ QVERIFY(!state1.hasPropertyChanges(rootModelNode));
+
+ QVERIFY(state1.propertyChanges(rect1).isValid());
+ QVERIFY(state1.propertyChanges(rect2).isValid());
+
+ state1.propertyChanges(rect2).modelNode().hasProperty("x");
+
+ QCOMPARE(QmlItemNode(rect1).allAffectingStates().count(), 2);
+ QCOMPARE(QmlItemNode(rect2).allAffectingStates().count(), 2);
+ QCOMPARE(QmlItemNode(rootModelNode).allAffectingStates().count(), 0);
+ QCOMPARE(QmlItemNode(rect1).allAffectingStatesOperations().count(), 2);
+ QCOMPARE(QmlItemNode(rect2).allAffectingStatesOperations().count(), 2);
+
+ //
+ // check real state2 object
+ //
+
+ NodeInstance state2Instance = view->instanceForModelNode(state2.modelNode());
+ QVERIFY(state2Instance.isValid());
+ QmlState *stateObject = qobject_cast<QmlState*>(const_cast<QObject*>(state2Instance.testHandle()));
+ QCOMPARE(stateObject->changes()->count(), 2);
+ QCOMPARE(stateObject->changes()->at(0)->actions().size(), 0);
+ QCOMPARE(stateObject->changes()->at(1)->actions().size(), 1);
+
+
+ //
+ // actual state switching
+ //
+
+ // base state
+ QCOMPARE(view->currentState(), view->baseState());
+ NodeInstance rect2Instance = view->instanceForModelNode(rect2);
+ QVERIFY(rect2Instance.isValid());
+ QCOMPARE(rect2Instance.property("x").toInt(), 0);
+
+ int expectedViewMethodCount = view->methodCalls().count();
+
+ // base state-> state2
+ view->setCurrentState(state2);
+ QCOMPARE(view->currentState(), state2);
+ QCOMPARE(view->methodCalls().size(), ++expectedViewMethodCount);
+ QCOMPARE(view->methodCalls().last(), TestView::MethodCall("stateChanged", QStringList() << "state2" << QString()));
+ QCOMPARE(rect2Instance.property("x").toInt(), 10);
+
+ // state2 -> state1
+ view->setCurrentState(state1);
+ QCOMPARE(view->currentState(), state1);
+ QCOMPARE(view->methodCalls().size(), ++expectedViewMethodCount);
+ QCOMPARE(view->methodCalls().last(), TestView::MethodCall("stateChanged", QStringList() << "state1" << "state2"));
+ QCOMPARE(rect2Instance.property("x").toInt(), 0);
+
+ // state1 -> baseState
+ view->setCurrentState(view->baseState());
+ QCOMPARE(view->currentState(), view->baseState());
+ QCOMPARE(view->methodCalls().size(), ++expectedViewMethodCount);
+ QCOMPARE(view->methodCalls().last(), TestView::MethodCall("stateChanged", QStringList() << QString() << "state1"));
+ QCOMPARE(rect2Instance.property("x").toInt(), 0);
+}
+
+void TestCore::testModelBasicOperations()
+{
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ ModelNode rootModelNode = view->rootModelNode();
+ QCOMPARE(rootModelNode.allDirectSubModelNodes().count(), 0);
+
+ rootModelNode.variantProperty("width").setValue(10);
+ rootModelNode.variantProperty("height").setValue(10);
+
+ QCOMPARE(rootModelNode.variantProperty("width").value().toInt(), 10);
+ QCOMPARE(rootModelNode.variantProperty("height").value().toInt(), 10);
+
+ QVERIFY(rootModelNode.hasProperty("width"));
+ rootModelNode.removeProperty("width");
+ QVERIFY(!rootModelNode.hasProperty("width"));
+
+ QVERIFY(!rootModelNode.hasProperty("children"));
+ ModelNode childNode1(rootModelNode.addChildNode("Qt/Rectangle", 4, 6, "children"));
+ ModelNode childNode2(rootModelNode.addChildNode("Qt/Rectangle", 4, 6, "data"));
+
+ QVERIFY(childNode1.isValid());
+ QVERIFY(childNode2.isValid());
+
+ QVERIFY(childNode1.parentProperty().parentModelNode().isValid());
+ QVERIFY(childNode2.parentProperty().parentModelNode().isValid());
+
+ QVERIFY(rootModelNode.hasProperty("children"));
+ childNode2.setParentProperty(rootModelNode, "children");
+ QVERIFY(!rootModelNode.hasProperty("data"));
+ QCOMPARE(childNode2.parentProperty().parentModelNode(), rootModelNode);
+ QVERIFY(rootModelNode.hasProperty("children"));
+ childNode2.setParentProperty(rootModelNode, "data");
+ childNode1.setParentProperty(rootModelNode, "data");
+ QCOMPARE(childNode2.parentProperty().parentModelNode(), rootModelNode);
+ QVERIFY(!rootModelNode.hasProperty("children"));
+ QVERIFY(rootModelNode.hasProperty("data"));
+
+ QVERIFY(childNode2.isValid());
+ QVERIFY(childNode2.parentProperty().parentModelNode().isValid());
+ QCOMPARE(childNode2.parentProperty().parentModelNode(), rootModelNode);
+
+ childNode1.setParentProperty(rootModelNode, "children");
+ rootModelNode.removeProperty("data");
+ QVERIFY(!childNode2.isValid());
+ QVERIFY(!rootModelNode.hasProperty("data"));
+
+ QVERIFY(childNode1.isValid());
+ rootModelNode.nodeProperty("front").setModelNode(childNode1);
+ QVERIFY(rootModelNode.hasProperty("front"));
+ QCOMPARE(childNode1.parentProperty().parentModelNode(), rootModelNode);
+ rootModelNode.removeProperty("front");
+ QVERIFY(!childNode1.isValid());
+}
+
+void TestCore::testModelResolveIds()
+{
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ ModelNode rootNode = view->rootModelNode();
+ rootNode.setId("rootNode");
+
+ ModelNode childNode1(rootNode.addChildNode("Qt/Rectangle", 4, 6, "children"));
+
+ ModelNode childNode2(childNode1.addChildNode("Qt/Rectangle", 4, 6, "children"));
+ childNode2.setId("childNode2");
+ childNode2.bindingProperty("test").setExpression("parent.parent");
+
+ QCOMPARE(childNode2.bindingProperty("test").resolveToModelNode(), rootNode);
+ childNode1.setId("childNode1");
+ childNode2.bindingProperty("test").setExpression("childNode1.parent");
+ QCOMPARE(childNode2.bindingProperty("test").resolveToModelNode(), rootNode);
+ childNode2.bindingProperty("test").setExpression("rootNode");
+ QCOMPARE(childNode2.bindingProperty("test").resolveToModelNode(), rootNode);
+
+ ModelNode childNode3(childNode2.addChildNode("Qt/Rectangle", 4, 6, "children"));
+ childNode3.setId("childNode3");
+ childNode2.nodeProperty("front").setModelNode(childNode3);
+ childNode2.bindingProperty("test").setExpression("childNode3.parent");
+ QCOMPARE(childNode2.bindingProperty("test").resolveToModelNode(), childNode2);
+ childNode2.bindingProperty("test").setExpression("childNode3.parent.parent");
+ QCOMPARE(childNode2.bindingProperty("test").resolveToModelNode(), childNode1);
+ childNode2.bindingProperty("test").setExpression("childNode3.parent.parent.parent");
+ QCOMPARE(childNode2.bindingProperty("test").resolveToModelNode(), rootNode);
+ childNode2.bindingProperty("test").setExpression("childNode3");
+ QCOMPARE(childNode2.bindingProperty("test").resolveToModelNode(), childNode3);
+ childNode2.bindingProperty("test").setExpression("front");
+ QCOMPARE(childNode2.bindingProperty("test").resolveToModelNode(), childNode3);
+ childNode2.bindingProperty("test").setExpression("back");
+ QVERIFY(!childNode2.bindingProperty("test").resolveToModelNode().isValid());
+ childNode2.bindingProperty("test").setExpression("childNode3.parent.front");
+ QCOMPARE(childNode2.bindingProperty("test").resolveToModelNode(), childNode3);
+
+ childNode2.variantProperty("x") = 10;
+ QCOMPARE(childNode2.variantProperty("x").value().toInt(), 10);
+
+ childNode2.bindingProperty("test").setExpression("childNode3.parent.x");
+ QVERIFY(childNode2.bindingProperty("test").resolveToProperty().isVariantProperty());
+ QCOMPARE(childNode2.bindingProperty("test").resolveToProperty().toVariantProperty().value().toInt(), 10);
+
+ childNode2.bindingProperty("test").setExpression("childNode3.parent.test");
+ QVERIFY(childNode2.bindingProperty("test").resolveToProperty().isBindingProperty());
+ QCOMPARE(childNode2.bindingProperty("test").resolveToProperty().toBindingProperty().expression(), QString("childNode3.parent.test"));
+}
+
+void TestCore::testModelNodeListProperty()
+{
+ QSKIP("Skip this for the time being", SkipAll);
+
+ //
+ // Test NodeListProperty API
+ //
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ ModelNode rootNode = view->rootModelNode();
+
+ //
+ // Item {}
+ //
+ NodeListProperty rootChildren = rootNode.nodeListProperty("children");
+ QVERIFY(!rootNode.hasProperty("children"));
+ QVERIFY(rootChildren.isValid());
+ QVERIFY(!rootChildren.isNodeListProperty());
+ QVERIFY(rootChildren.isEmpty());
+
+ ModelNode rectNode = view->createModelNode("Qt/Rectangle", 4, 6);
+ rootChildren.reparentHere(rectNode);
+
+ //
+ // Item { children: [ Rectangle {} ] }
+ //
+ QVERIFY(rootNode.hasProperty("children"));
+ QVERIFY(rootChildren.isValid());
+ QVERIFY(rootChildren.isNodeListProperty());
+ QVERIFY(!rootChildren.isEmpty());
+
+ ModelNode mouseRegionNode = view->createModelNode("Qt/Item", 4, 6);
+ NodeListProperty rectChildren = rectNode.nodeListProperty("children");
+ rectChildren.reparentHere(mouseRegionNode);
+
+ //
+ // Item { children: [ Rectangle { children : [ MouseRegion {} ] } ] }
+ //
+ QVERIFY(rectNode.hasProperty("children"));
+ QVERIFY(rectChildren.isValid());
+ QVERIFY(rectChildren.isNodeListProperty());
+ QVERIFY(!rectChildren.isEmpty());
+
+ rectNode.destroy();
+
+ //
+ // Item { }
+ //
+ QVERIFY(!rectNode.isValid());
+ QVERIFY(!mouseRegionNode.isValid());
+ QVERIFY(!rootNode.hasProperty("children"));
+ QVERIFY(rootChildren.isValid());
+ QVERIFY(!rootChildren.isNodeListProperty());
+ QVERIFY(rootChildren.isEmpty());
+ QVERIFY(!rectChildren.isValid());
+}
+
+void TestCore::testBasicOperationsWithView()
+{
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ NodeInstanceView *nodeInstanceView = new NodeInstanceView(model.data());
+ model->attachView(nodeInstanceView);
+
+ ModelNode rootModelNode = view->rootModelNode();
+ QCOMPARE(rootModelNode.allDirectSubModelNodes().count(), 0);
+ NodeInstance rootInstance = nodeInstanceView->instanceForNode(rootModelNode);
+
+ QCOMPARE(rootInstance.size().width(), 0.0);
+ QCOMPARE(rootInstance.size().height(), 0.0);
+
+ QVERIFY(rootInstance.isValid());
+ QVERIFY(rootInstance.isQmlGraphicsItem());
+
+ QVERIFY(rootModelNode.isValid());
+
+ rootModelNode.variantProperty("width").setValue(10);
+ rootModelNode.variantProperty("height").setValue(10);
+
+ QCOMPARE(rootModelNode.variantProperty("width").value().toInt(), 10);
+ QCOMPARE(rootModelNode.variantProperty("height").value().toInt(), 10);
+
+ QCOMPARE(rootInstance.size().width(), 10.0);
+ QCOMPARE(rootInstance.size().height(), 10.0);
+
+ ModelNode childNode(rootModelNode.addChildNode("Qt/Rectangle", 4, 6, "data"));
+ ModelNode childNode2(childNode.addChildNode("Qt/Rectangle", 4, 6, "data"));
+ QVERIFY(childNode2.parentProperty().parentModelNode() == childNode);
+
+ QVERIFY(childNode.isValid());
+
+ {
+ NodeInstance childInstance2 = nodeInstanceView->instanceForNode(childNode2);
+ NodeInstance childInstance = nodeInstanceView->instanceForNode(childNode);
+
+ QVERIFY(childInstance.isValid());
+ QVERIFY(childInstance.isQmlGraphicsItem());
+ QVERIFY(childInstance2.testHandle()->parent() == childInstance.testHandle());
+ QVERIFY(childInstance.testHandle()->parent() == rootInstance.testHandle());
+ QCOMPARE(childInstance.size().width(), 0.0);
+ QCOMPARE(childInstance.size().height(), 0.0);
+
+
+ childNode.variantProperty("width").setValue(100);
+ childNode.variantProperty("height").setValue(100);
+
+ QCOMPARE(childNode.variantProperty("width").value().toInt(), 100);
+ QCOMPARE(childNode.variantProperty("height").value().toInt(), 100);
+
+ QCOMPARE(childInstance.size().width(), 100.0);
+ QCOMPARE(childInstance.size().height(), 100.0);
+
+ childNode.destroy();
+ QVERIFY(!childNode.isValid());
+ QVERIFY(!childNode2.isValid());
+ QVERIFY(childInstance.testHandle() == 0);
+ QVERIFY(childInstance2.testHandle() == 0);
+ QVERIFY(!childInstance.isValid());
+ QVERIFY(!childInstance2.isValid());
+ }
+
+ childNode = rootModelNode.addChildNode("Qt/Image", 4, 6, "data");
+ QVERIFY(childNode.isValid());
+ QCOMPARE(childNode.type(), QString("Qt/Image"));
+ childNode2 = childNode.addChildNode("Qt/Rectangle", 4, 6, "data");
+ QVERIFY(childNode2.isValid());
+ childNode2.setParentProperty(rootModelNode, "data");
+ QVERIFY(childNode2.isValid());
+
+ {
+ NodeInstance childInstance2 = nodeInstanceView->instanceForNode(childNode2);
+ NodeInstance childInstance = nodeInstanceView->instanceForNode(childNode);
+
+ QVERIFY(childInstance.isValid());
+ QVERIFY(childInstance.isQmlGraphicsItem());
+ QVERIFY(childInstance2.testHandle()->parent() == rootInstance.testHandle());
+ QVERIFY(childInstance.testHandle()->parent() == rootInstance.testHandle());
+ QCOMPARE(childInstance.size().width(), 0.0);
+ QCOMPARE(childInstance.size().height(), 0.0);
+
+ QCOMPARE(rootModelNode, childNode2.parentProperty().parentModelNode());
+
+ childNode.variantProperty("width").setValue(20);
+ QCOMPARE(childInstance.property("width").toInt(), 20);
+
+ QCOMPARE(childNode.variantProperty("width").value().toInt(), 20);
+ childNode.removeProperty("width");
+ QVERIFY(!childNode.hasProperty("width"));
+
+ rootModelNode.removeProperty("data");
+ QVERIFY(!childNode.isValid());
+ QVERIFY(!childNode2.isValid());
+ QVERIFY(childInstance.testHandle() == 0);
+ QVERIFY(childInstance2.testHandle() == 0);
+ QVERIFY(!childInstance.isValid());
+ QVERIFY(!childInstance2.isValid());
+ }
+
+ model->detachView(nodeInstanceView);
+}
+
+void TestCore::testQmlModelView()
+{
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QmlModelView *view = new TestView(model.data());
+ QVERIFY(view);
+ model->attachView(view);
+ QVERIFY(view->model());
+ QVERIFY(view->rootQmlObjectNode().isValid());
+ QVERIFY(!view->rootQmlObjectNode().hasNodeParent());
+ QVERIFY(!view->rootQmlObjectNode().hasInstanceParent());
+ QVERIFY(view->rootQmlObjectNode().isRootModelNode());
+
+ PropertyListType propertyList;
+ propertyList.append(qMakePair(QString("x"), QVariant(20)));
+ propertyList.append(qMakePair(QString("y"), QVariant(20)));
+ propertyList.append(qMakePair(QString("width"), QVariant(20)));
+ propertyList.append(qMakePair(QString("height"), QVariant(20)));
+
+ QmlObjectNode node1 = view->createQmlObjectNode("Qt/Rectangle", 4, 6, propertyList);
+
+ QVERIFY(node1.isValid());
+ QVERIFY(!node1.hasNodeParent());
+ QVERIFY(!node1.hasInstanceParent());
+
+ QCOMPARE(node1.instanceValue("x").toInt(), 20);
+ QCOMPARE(node1.instanceValue("y").toInt(), 20);
+
+ node1.setParentProperty(view->rootQmlObjectNode().nodeAbstractProperty("children"));
+
+ QVERIFY(node1.hasNodeParent());
+ QVERIFY(node1.hasInstanceParent());
+ QVERIFY(node1.instanceParent() == view->rootQmlObjectNode());
+
+
+ QmlObjectNode node2 = view->createQmlObjectNode("Qt/Rectangle", 4, 6, propertyList);
+
+ QVERIFY(node2.isValid());
+ QVERIFY(!node2.hasNodeParent());
+ QVERIFY(!node2.hasInstanceParent());
+
+ node2.setParentProperty(view->rootQmlObjectNode().nodeAbstractProperty("children"));
+
+ QVERIFY(node2.hasNodeParent());
+ QVERIFY(node2.hasInstanceParent());
+ QVERIFY(node2.instanceParent() == view->rootQmlObjectNode());
+
+
+ node2.setParentProperty(node1.nodeAbstractProperty("children"));
+
+ QVERIFY(node2.hasNodeParent());
+ QVERIFY(node2.hasInstanceParent());
+ QVERIFY(node2.instanceParent() == node1);
+
+ node2.setParentProperty(view->rootQmlObjectNode().nodeAbstractProperty("children"));
+
+ QCOMPARE(node1.instanceValue("x").toInt(), 20);
+
+ node1.setVariantProperty("x", 2);
+
+ QCOMPARE(node1.instanceValue("x").toInt(), 2);
+
+
+ QmlObjectNode node3 = view->createQmlObjectNode("Qt/Rectangle", 4, 6, propertyList);
+ QmlObjectNode node4 = view->createQmlObjectNode("Qt/Rectangle", 4, 6, propertyList);
+ QmlObjectNode node5 = view->createQmlObjectNode("Qt/Rectangle", 4, 6, propertyList);
+ QmlObjectNode node6 = view->createQmlObjectNode("Qt/Rectangle", 4, 6, propertyList);
+ QmlObjectNode node7 = view->createQmlObjectNode("Qt/Rectangle", 4, 6, propertyList);
+ QmlObjectNode node8 = view->createQmlObjectNode("Qt/Rectangle", 4, 6, propertyList);
+
+ node3.setParentProperty(node2.nodeAbstractProperty("children"));
+ node4.setParentProperty(node3.nodeAbstractProperty("children"));
+ node5.setParentProperty(node4.nodeAbstractProperty("children"));
+ node6.setParentProperty(node5.nodeAbstractProperty("children"));
+ node7.setParentProperty(node6.nodeAbstractProperty("children"));
+ node8.setParentProperty(node7.nodeAbstractProperty("children"));
+
+ QCOMPARE(node2.nodeAbstractProperty("children").allSubNodes().count(), 6);
+ QVERIFY(node8.isValid());
+ node3.destroy();
+ QVERIFY(!node8.isValid());
+ QCOMPARE(node2.nodeAbstractProperty("children").allSubNodes().count(), 0);
+
+ node1.setId("node1");
+
+ node2.setVariantProperty("x", 20);
+ node2.setBindingProperty("x", "node1.x");
+ QCOMPARE(node2.instanceValue("x").toInt(), 2);
+ node1.setVariantProperty("x", 10);
+ QCOMPARE(node2.instanceValue("x").toInt(), 10);
+
+ node1.destroy();
+ QVERIFY(!node1.isValid());
+
+ QCOMPARE(node2.instanceValue("x").toInt(), 10); // is this right? or should it be a invalid qvariant?
+
+ node1 = view->createQmlObjectNode("Qt/Rectangle", 4, 6, propertyList);
+ node1.setId("node1");
+
+ QCOMPARE(node2.instanceValue("x").toInt(), 20);
+
+ node3 = view->createQmlObjectNode("Qt/Rectangle", 4, 6, propertyList);
+ node3.setParentProperty(node2.nodeAbstractProperty("children"));
+ QCOMPARE(node3.instanceValue("width").toInt(), 20);
+ node3.setVariantProperty("width", 0);
+ QCOMPARE(node3.instanceValue("width").toInt(), 0);
+
+ QCOMPARE(node3.instanceValue("x").toInt(), 20);
+ QVERIFY(!QmlMetaType::toQObject(node3.instanceValue("anchors.fill")));
+ node3.setBindingProperty("anchors.fill", "parent");
+ QVERIFY(QmlMetaType::toQObject(node3.instanceValue("anchors.fill")));
+ QCOMPARE(node3.instanceValue("x").toInt(), 0);
+ QCOMPARE(node3.instanceValue("width").toInt(), 20);
+
+ node3.setParentProperty(node1.nodeAbstractProperty("children"));
+ node1.setVariantProperty("width", 50);
+ node2.setVariantProperty("width", 100);
+ QCOMPARE(node3.instanceValue("width").toInt(), 50);
+
+}
+
+void TestCore::testModelCreateInvalidSubNode()
+{
+ QSKIP("type checking not in the model", SkipAll);
+ ModelNode node;
+ QVERIFY(!node.isValid());
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ try {
+ ModelNode invalidChildNode = view->rootModelNode().addChildNode("InvalidNode", 0, 0, "data");
+ QFAIL("Adding an invalid typed node should result in an exception");
+ } catch (Exception& exception) {
+ QCOMPARE(exception.type(), QString("InvalidModelNodeException"));
+ }
+}
+
+void TestCore::testModelRemoveNode()
+{
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ NodeInstanceView *nodeInstanceView = new NodeInstanceView(model.data());
+ model->attachView(nodeInstanceView);
+
+ QCOMPARE(view->rootModelNode().allDirectSubModelNodes().count(), 0);
+
+
+ ModelNode childNode = view->rootModelNode().addChildNode("Qt/Rectangle", 4, 6, "data");
+ QVERIFY(childNode.isValid());
+ QCOMPARE(view->rootModelNode().allDirectSubModelNodes().count(), 1);
+ QVERIFY(view->rootModelNode().allDirectSubModelNodes().contains(childNode));
+ QVERIFY(childNode.parentProperty().parentModelNode() == view->rootModelNode());
+
+ {
+ NodeInstance childInstance = nodeInstanceView->instanceForNode(childNode);
+ QVERIFY(childInstance.isValid());
+ QVERIFY(childInstance.parent() == nodeInstanceView->instanceForNode(view->rootModelNode()));
+ }
+
+ ModelNode subChildNode = childNode.addChildNode("Qt/Rectangle", 4, 6, "data");
+ QVERIFY(subChildNode.isValid());
+ QCOMPARE(childNode.allDirectSubModelNodes().count(), 1);
+ QVERIFY(childNode.allDirectSubModelNodes().contains(subChildNode));
+ QVERIFY(subChildNode.parentProperty().parentModelNode() == childNode);
+
+ {
+ NodeInstance subChildInstance = nodeInstanceView->instanceForNode(subChildNode);
+ QVERIFY(subChildInstance.isValid());
+ QVERIFY(subChildInstance.parent() == nodeInstanceView->instanceForNode(childNode));
+ }
+
+ childNode.destroy();
+
+ QVERIFY(!nodeInstanceView->hasInstanceForNode(childNode));
+
+ QCOMPARE(view->rootModelNode().allDirectSubModelNodes().count(), 0);
+ QVERIFY(!view->rootModelNode().allDirectSubModelNodes().contains(childNode));
+ QVERIFY(!childNode.isValid());
+ QVERIFY(!subChildNode.isValid());
+
+ try {
+ view->rootModelNode().destroy();
+ QFAIL("remove the rootModelNode should be throw a exception");
+ } catch (Exception &exception) {
+ QCOMPARE(exception.type(), QString("InvalidArgumentException"));
+ }
+
+ QVERIFY(view->rootModelNode().isValid());
+
+ // delete node not in hierarchy
+ childNode = view->createModelNode("Qt/Item", 4, 6);
+ childNode.destroy();
+
+ model->detachView(nodeInstanceView);
+}
+
+void TestCore::reparentingNode()
+{
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ ModelNode rootModelNode = view->rootModelNode();
+ QVERIFY(rootModelNode.isValid());
+ rootModelNode.setId("rootModelNode");
+ QCOMPARE(rootModelNode.id(), QString("rootModelNode"));
+
+
+ NodeInstanceView *nodeInstanceView = new NodeInstanceView(model.data());
+ model->attachView(nodeInstanceView);
+
+ ModelNode childNode = rootModelNode.addChildNode("Qt/Rectangle", 4, 6, "data");
+ QCOMPARE(childNode.parentProperty().parentModelNode(), rootModelNode);
+ QVERIFY(rootModelNode.allDirectSubModelNodes().contains(childNode));
+
+ {
+ NodeInstance childInstance = nodeInstanceView->instanceForNode(childNode);
+ QVERIFY(childInstance.isValid());
+ QVERIFY(childInstance.parent() == nodeInstanceView->instanceForNode(view->rootModelNode()));
+ }
+
+ ModelNode childNode2 = rootModelNode.addChildNode("Qt/Item", 4, 6, "data");
+ QCOMPARE(childNode2.parentProperty().parentModelNode(), rootModelNode);
+ QVERIFY(rootModelNode.allDirectSubModelNodes().contains(childNode2));
+
+ {
+ NodeInstance childIstance2 = nodeInstanceView->instanceForNode(childNode2);
+ QVERIFY(childIstance2.isValid());
+ QVERIFY(childIstance2.parent() == nodeInstanceView->instanceForNode(view->rootModelNode()));
+ }
+
+ childNode.setParentProperty(childNode2, "data");
+
+ QCOMPARE(childNode.parentProperty().parentModelNode(), childNode2);
+ QVERIFY(childNode2.allDirectSubModelNodes().contains(childNode));
+ QVERIFY(!rootModelNode.allDirectSubModelNodes().contains(childNode));
+ QVERIFY(rootModelNode.allDirectSubModelNodes().contains(childNode2));
+
+ {
+ NodeInstance childIstance = nodeInstanceView->instanceForNode(childNode);
+ QVERIFY(childIstance.isValid());
+ QVERIFY(childIstance.parent() == nodeInstanceView->instanceForNode(childNode2));
+ }
+
+ childNode2.setParentProperty(rootModelNode, "data");
+ QCOMPARE(childNode2.parentProperty().parentModelNode(), rootModelNode);
+ QVERIFY(rootModelNode.allDirectSubModelNodes().contains(childNode2));
+
+ {
+ NodeInstance childIstance2 = nodeInstanceView->instanceForNode(childNode2);
+ QVERIFY(childIstance2.isValid());
+ QVERIFY(childIstance2.parent() == nodeInstanceView->instanceForNode(rootModelNode));
+ }
+
+ QCOMPARE(childNode.parentProperty().parentModelNode(), childNode2);
+
+ model->detachView(nodeInstanceView);
+}
+
+void TestCore::reparentingNodeLikeDragAndDrop()
+{
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText("import Qt 4.6;\n\nItem {\n}\n");
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+ model->attachView(testRewriterView.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ NodeInstanceView *nodeInstanceView = new NodeInstanceView(model.data());
+ model->attachView(nodeInstanceView);
+ view->rootModelNode().setId("rootModelNode");
+ QCOMPARE(view->rootModelNode().id(), QString("rootModelNode"));
+
+ ModelNode rectNode = view->rootModelNode().addChildNode("Qt/Rectangle", 4, 6, "data");
+ rectNode.setId("Rect_1");
+ rectNode.variantProperty("x").setValue(20);
+ rectNode.variantProperty("y").setValue(30);
+ rectNode.variantProperty("width").setValue(40);
+ rectNode.variantProperty("height").setValue(50);
+
+ RewriterTransaction transaction(view->beginRewriterTransaction());
+
+ ModelNode textNode = view->rootModelNode().addChildNode("Qt/Text", 4, 6, "data");
+ QCOMPARE(textNode.parentProperty().parentModelNode(), view->rootModelNode());
+ QVERIFY(view->rootModelNode().allDirectSubModelNodes().contains(textNode));
+
+ textNode.setId("Text_1");
+ textNode.variantProperty("x").setValue(10);
+ textNode.variantProperty("y").setValue(10);
+ textNode.variantProperty("width").setValue(50);
+ textNode.variantProperty("height").setValue(20);
+
+ textNode.variantProperty("x").setValue(30);
+ textNode.variantProperty("y").setValue(30);
+
+ {
+ NodeInstance textInstance = nodeInstanceView->instanceForNode(textNode);
+ QVERIFY(textInstance.isValid());
+ QVERIFY(textInstance.parent() == nodeInstanceView->instanceForNode(view->rootModelNode()));
+ QCOMPARE(textInstance.position().x(), 30.0);
+ QCOMPARE(textInstance.position().y(), 30.0);
+ QCOMPARE(textInstance.size().width(), 50.0);
+ QCOMPARE(textInstance.size().height(), 20.0);
+ }
+
+ textNode.setParentProperty(rectNode, "data");
+ QCOMPARE(textNode.parentProperty().parentModelNode(), rectNode);
+ QVERIFY(rectNode.allDirectSubModelNodes().contains(textNode));
+
+ {
+ NodeInstance textInstance = nodeInstanceView->instanceForNode(textNode);
+ QVERIFY(textInstance.isValid());
+ QVERIFY(textInstance.parent() == nodeInstanceView->instanceForNode(rectNode));
+ QCOMPARE(textInstance.position().x(), 30.0);
+ QCOMPARE(textInstance.position().y(), 30.0);
+ QCOMPARE(textInstance.size().width(), 50.0);
+ QCOMPARE(textInstance.size().height(), 20.0);
+ }
+
+ textNode.setParentProperty(view->rootModelNode(), "data");
+ QCOMPARE(textNode.parentProperty().parentModelNode(), view->rootModelNode());
+ QVERIFY(view->rootModelNode().allDirectSubModelNodes().contains(textNode));
+
+ {
+ NodeInstance textInstance = nodeInstanceView->instanceForNode(textNode);
+ QVERIFY(textInstance.isValid());
+ QVERIFY(textInstance.parent() == nodeInstanceView->instanceForNode(view->rootModelNode()));
+ QCOMPARE(textInstance.position().x(), 30.0);
+ QCOMPARE(textInstance.position().y(), 30.0);
+ QCOMPARE(textInstance.size().width(), 50.0);
+ QCOMPARE(textInstance.size().height(), 20.0);
+ }
+
+ textNode.setParentProperty(rectNode, "data");
+ QCOMPARE(textNode.parentProperty().parentModelNode(), rectNode);
+ QVERIFY(rectNode.allDirectSubModelNodes().contains(textNode));
+
+ {
+ NodeInstance textInstance = nodeInstanceView->instanceForNode(textNode);
+ QVERIFY(textInstance.isValid());
+ QVERIFY(textInstance.parent() == nodeInstanceView->instanceForNode(rectNode));
+ QCOMPARE(textInstance.position().x(), 30.0);
+ QCOMPARE(textInstance.position().y(), 30.0);
+ QCOMPARE(textInstance.size().width(), 50.0);
+ QCOMPARE(textInstance.size().height(), 20.0);
+ }
+
+ {
+ NodeInstance textInstance = nodeInstanceView->instanceForNode(textNode);
+ QVERIFY(textInstance.isValid());
+ QVERIFY(textInstance.parent() == nodeInstanceView->instanceForNode(rectNode));
+ QCOMPARE(textInstance.position().x(), 30.0);
+ QCOMPARE(textInstance.position().y(), 30.0);
+ QCOMPARE(textInstance.size().width(), 50.0);
+ QCOMPARE(textInstance.size().height(), 20.0);
+ }
+
+ transaction.commit();
+
+ if(!textNode.isValid())
+ QFAIL("textnode node is not valid anymore");
+ else
+ QCOMPARE(textNode.parentProperty().parentModelNode(), rectNode);
+ QVERIFY(rectNode.allDirectSubModelNodes().contains(textNode));
+
+ model->detachView(nodeInstanceView);
+}
+
+void TestCore::testModelReorderSiblings()
+{
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ NodeInstanceView *nodeInstanceView = new NodeInstanceView(model.data());
+ model->attachView(nodeInstanceView);
+
+ ModelNode rootModelNode = view->rootModelNode();
+ QVERIFY(rootModelNode.isValid());
+
+ ModelNode a = rootModelNode.addChildNode("Qt/Rectangle", 4, 6, "data");
+ QVERIFY(a.isValid());
+ ModelNode b = rootModelNode.addChildNode("Qt/Rectangle", 4, 6, "data");
+ QVERIFY(b.isValid());
+ ModelNode c = rootModelNode.addChildNode("Qt/Rectangle", 4, 6, "data");
+ QVERIFY(c.isValid());
+
+ {
+ QVERIFY(nodeInstanceView->instanceForNode(a).parent() == nodeInstanceView->instanceForNode(rootModelNode));
+ QVERIFY(nodeInstanceView->instanceForNode(b).parent() == nodeInstanceView->instanceForNode(rootModelNode));
+ QVERIFY(nodeInstanceView->instanceForNode(c).parent() == nodeInstanceView->instanceForNode(rootModelNode));
+ }
+
+ NodeListProperty listProperty(rootModelNode.nodeListProperty("data"));
+
+ listProperty.slide(listProperty.toModelNodeList().indexOf(a), 3); //a.slideToIndex(3);
+
+
+ QVERIFY(a.isValid()); QCOMPARE(listProperty.toModelNodeList().indexOf(a), 2);
+ QVERIFY(b.isValid()); QCOMPARE(listProperty.toModelNodeList().indexOf(b), 0);
+ QVERIFY(c.isValid()); QCOMPARE(listProperty.toModelNodeList().indexOf(c), 1);
+
+
+ listProperty.slide(listProperty.toModelNodeList().indexOf(c), 0); //c.slideToIndex(0);
+
+ QVERIFY(a.isValid()); QCOMPARE(listProperty.toModelNodeList().indexOf(a), 2);
+ QVERIFY(b.isValid()); QCOMPARE(listProperty.toModelNodeList().indexOf(b), 1);
+ QVERIFY(c.isValid()); QCOMPARE(listProperty.toModelNodeList().indexOf(c), 0);
+
+ {
+ QVERIFY(nodeInstanceView->instanceForNode(a).parent() == nodeInstanceView->instanceForNode(rootModelNode));
+ QVERIFY(nodeInstanceView->instanceForNode(b).parent() == nodeInstanceView->instanceForNode(rootModelNode));
+ QVERIFY(nodeInstanceView->instanceForNode(c).parent() == nodeInstanceView->instanceForNode(rootModelNode));
+ }
+
+ model->detachView(nodeInstanceView);
+}
+
+void TestCore::testModelRootNode()
+{
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ try {
+ ModelNode rootModelNode = view->rootModelNode();
+ QVERIFY(rootModelNode.isValid());
+ QVERIFY(rootModelNode.isRootNode());
+ ModelNode topChildNode = rootModelNode.addChildNode("Qt/Rectangle", 4, 6, "data");
+ QVERIFY(topChildNode.isValid());
+ QVERIFY(rootModelNode.isRootNode());
+ ModelNode childNode = rootModelNode.addChildNode("Qt/Rectangle", 4, 6, "data");
+ QVERIFY(childNode.isValid());
+ QVERIFY(rootModelNode.isValid());
+ QVERIFY(rootModelNode.isRootNode());
+ childNode.setParentProperty(topChildNode, "data");
+ QVERIFY(topChildNode.isValid());
+ QVERIFY(childNode.isValid());
+ QVERIFY(rootModelNode.isValid());
+ QVERIFY(rootModelNode.isRootNode());
+ } catch (const QmlDesigner::Exception &exception) {
+ QString errorMsg = tr("Exception: %1 %2 %3:%4").arg(exception.type(), exception.function(), exception.file()).arg(exception.line());
+ QFAIL(errorMsg.toLatin1().constData());
+ }
+}
+
+void TestCore::reparentingNodeInModificationGroup()
+{
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ ModelNode childNode = view->rootModelNode().addChildNode("Qt/Rectangle", 4, 6, "data");
+ ModelNode childNode2 = view->rootModelNode().addChildNode("Qt/Item", 4, 6, "data");
+ childNode.variantProperty("x").setValue(10);
+ childNode.variantProperty("y").setValue(10);
+
+ QCOMPARE(childNode.parentProperty().parentModelNode(), view->rootModelNode());
+ QCOMPARE(childNode2.parentProperty().parentModelNode(), view->rootModelNode());
+ QVERIFY(view->rootModelNode().allDirectSubModelNodes().contains(childNode));
+ QVERIFY(view->rootModelNode().allDirectSubModelNodes().contains(childNode2));
+
+// ModificationGroupToken token = model->beginModificationGroup();
+ childNode.variantProperty("x").setValue(20);
+ childNode.variantProperty("y").setValue(20);
+ childNode.setParentProperty(childNode2, "data");
+ childNode.variantProperty("x").setValue(30);
+ childNode.variantProperty("y").setValue(30);
+ childNode.variantProperty("x").setValue(1000000);
+ childNode.variantProperty("y").setValue(1000000);
+// model->endModificationGroup(token);
+
+ QCOMPARE(childNode.parentProperty().parentModelNode(), childNode2);
+ QVERIFY(childNode2.allDirectSubModelNodes().contains(childNode));
+ QVERIFY(!view->rootModelNode().allDirectSubModelNodes().contains(childNode));
+ QVERIFY(view->rootModelNode().allDirectSubModelNodes().contains(childNode2));
+
+ childNode.setParentProperty(view->rootModelNode(), "data");
+ QVERIFY(childNode.isValid());
+ QCOMPARE(childNode2.parentProperty().parentModelNode(), view->rootModelNode());
+
+ childNode2.setParentProperty(childNode, "data");
+ QCOMPARE(childNode2.parentProperty().parentModelNode(), childNode);
+ QVERIFY(childNode2.isValid());
+ QVERIFY(childNode.allDirectSubModelNodes().contains(childNode2));
+
+ QCOMPARE(childNode2.parentProperty().parentModelNode(), childNode);
+ childNode2.setParentProperty(view->rootModelNode(), "data");
+ QCOMPARE(childNode2.parentProperty().parentModelNode(), view->rootModelNode());
+ QVERIFY(childNode2.isValid());
+ QVERIFY(view->rootModelNode().allDirectSubModelNodes().contains(childNode2));
+}
+
+void TestCore::testModelAddAndRemoveProperty()
+{
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ ModelNode node = view->rootModelNode();
+ QVERIFY(node.isValid());
+
+ NodeInstanceView *nodeInstanceView = new NodeInstanceView(model.data());
+ model->attachView(nodeInstanceView);
+
+ node.variantProperty("blah").setValue(-1);
+ QCOMPARE(node.variantProperty("blah").value().toInt(), -1);
+ QVERIFY(node.hasProperty("blah"));
+ QCOMPARE(node.variantProperty("blah").value().toInt(), -1);
+
+ {
+ NodeInstance nodeInstance = nodeInstanceView->instanceForNode(node);
+// QCOMPARE(nodeInstance.property("blah").toInt(), -1);
+ }
+
+ node.variantProperty("customValue").setValue(42);
+ QCOMPARE(node.variantProperty("customValue").value().toInt(), 42);
+
+ {
+ NodeInstance nodeInstance = nodeInstanceView->instanceForNode(node);
+// QCOMPARE(!nodeInstance.property("customValue").toInt(), 42);
+ }
+
+ node.variantProperty("x").setValue(42);
+ QCOMPARE(node.variantProperty("x").value().toInt(), 42);
+
+ {
+ NodeInstance nodeInstance = nodeInstanceView->instanceForNode(node);
+ QCOMPARE(nodeInstance.property("x").toInt(), 42);
+ }
+
+ node.removeProperty("customValue");
+ QVERIFY(!node.hasProperty("customValue"));
+
+ node.variantProperty("foo").setValue("bar");
+ QVERIFY(node.hasProperty("foo"));
+ QCOMPARE(node.variantProperty("foo").value().toString(), QString("bar"));
+
+ model->detachView(nodeInstanceView);
+}
+
+void TestCore::testModelViewNotification()
+{
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view1(new TestView);
+ QVERIFY(view1.data());
+
+ QScopedPointer<TestView> view2(new TestView);
+ QVERIFY(view2.data());
+
+ model->attachView(view2.data());
+ model->attachView(view1.data());
+
+ QCOMPARE(view1->methodCalls().size(), 1);
+ QCOMPARE(view1->methodCalls().at(0).name,QString("modelAttached"));
+ QCOMPARE(view2->methodCalls().size(), 1);
+ QCOMPARE(view2->methodCalls().at(0).name,QString("modelAttached"));
+
+ QList<TestView::MethodCall> expectedCalls;
+ expectedCalls << TestView::MethodCall("modelAttached", QStringList() << QString::number(reinterpret_cast<long>(model.data())));
+ QCOMPARE(view1->methodCalls(), expectedCalls);
+ QCOMPARE(view2->methodCalls(), expectedCalls);
+
+ ModelNode childNode = view2->rootModelNode().addChildNode("Qt/Rectangle", 4, 6, "data");
+ expectedCalls << TestView::MethodCall("nodeCreated", QStringList() << "");
+ expectedCalls << TestView::MethodCall("nodeReparented", QStringList() << "" << "data" << "" << "PropertiesAdded");
+ QCOMPARE(view1->methodCalls(), expectedCalls);
+ QCOMPARE(view2->methodCalls(), expectedCalls);
+
+ childNode.setId("supernode");
+ expectedCalls << TestView::MethodCall("nodeIdChanged", QStringList() << "supernode" << "supernode" << "");
+ QCOMPARE(view1->methodCalls(), expectedCalls);
+ QCOMPARE(view2->methodCalls(), expectedCalls);
+
+ childNode.variantProperty("visible").setValue(false);
+ expectedCalls << TestView::MethodCall("variantPropertiesChanged", QStringList() << "visible" << "PropertiesAdded");
+ QCOMPARE(view1->methodCalls(), expectedCalls);
+ QCOMPARE(view2->methodCalls(), expectedCalls);
+
+ childNode.setId("supernode2");
+ expectedCalls << TestView::MethodCall("nodeIdChanged", QStringList() << "supernode2" << "supernode2" << "supernode");
+ QCOMPARE(view1->methodCalls(), expectedCalls);
+ QCOMPARE(view2->methodCalls(), expectedCalls);
+
+ childNode.variantProperty("visible").setValue(false); // its tae some value so no notification should be sent
+ QCOMPARE(view1->methodCalls(), expectedCalls);
+ QCOMPARE(view2->methodCalls(), expectedCalls);
+
+ childNode.variantProperty("visible").setValue(true);
+ expectedCalls << TestView::MethodCall("variantPropertiesChanged", QStringList() << "visible" << "");
+ QCOMPARE(view1->methodCalls(), expectedCalls);
+ QCOMPARE(view2->methodCalls(), expectedCalls);
+
+ childNode.bindingProperty("visible").setExpression("false");
+ expectedCalls << TestView::MethodCall("propertiesAboutToBeRemoved", QStringList() << "visible");
+ expectedCalls << TestView::MethodCall("bindingPropertiesChanged", QStringList() << "visible" << "PropertiesAdded");
+ QCOMPARE(view1->methodCalls(), expectedCalls);
+ QCOMPARE(view2->methodCalls(), expectedCalls);
+
+ childNode.destroy();
+ expectedCalls << TestView::MethodCall("nodeAboutToBeRemoved", QStringList() << "supernode2");
+ expectedCalls << TestView::MethodCall("nodeRemoved", QStringList() << QString() << "data" << "EmptyPropertiesRemoved");
+ QCOMPARE(view1->methodCalls(), expectedCalls);
+ QCOMPARE(view2->methodCalls(), expectedCalls);
+
+ model->detachView(view1.data());
+ expectedCalls << TestView::MethodCall("modelAboutToBeDetached", QStringList() << QString::number(reinterpret_cast<long>(model.data())));
+ QCOMPARE(view1->methodCalls(), expectedCalls);
+}
+
+
+void TestCore::testRewriterTransaction()
+{
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ RewriterTransaction transaction = view->beginRewriterTransaction();
+ QVERIFY(transaction.isValid());
+
+ ModelNode childNode = view->rootModelNode().addChildNode("Qt/Rectangle", 4, 6, "data");
+ QVERIFY(childNode.isValid());
+
+ childNode.destroy();
+ QVERIFY(!childNode.isValid());
+
+ {
+ RewriterTransaction transaction2 = view->beginRewriterTransaction();
+ QVERIFY(transaction2.isValid());
+
+ ModelNode childNode = view->rootModelNode().addChildNode("Qt/Rectangle", 4, 6, "data");
+ QVERIFY(childNode.isValid());
+
+ childNode.destroy();
+ QVERIFY(!childNode.isValid());
+
+ RewriterTransaction transaction3(transaction2);
+ QVERIFY(!transaction2.isValid());
+ QVERIFY(transaction3.isValid());
+
+ transaction2 = transaction3;
+ QVERIFY(transaction2.isValid());
+ QVERIFY(!transaction3.isValid());
+
+ transaction3 = transaction3;
+ transaction2 = transaction2;
+ QVERIFY(transaction2.isValid());
+ QVERIFY(!transaction3.isValid());
+ }
+
+ QVERIFY(transaction.isValid());
+ transaction.commit();
+ QVERIFY(!transaction.isValid());
+}
+
+void TestCore::testRewriterId()
+{
+ char qmlString[] = "import Qt 4.6\n"
+ "Rectangle {\n"
+ "}\n";
+
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ ModelNode rootModelNode(view->rootModelNode());
+ QVERIFY(rootModelNode.isValid());
+
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+
+
+ model->attachView(testRewriterView.data());
+ QCOMPARE(rootModelNode.type(), QString("Qt/Rectangle"));
+
+ QVERIFY(rootModelNode.isValid());
+
+ ModelNode newNode(view->createModelNode("Qt/Rectangle", 4, 6));
+ newNode.setId("testId");
+
+ rootModelNode.nodeListProperty("data").reparentHere(newNode);
+
+ const QLatin1String expected("import Qt 4.6\n"
+ "Rectangle {\n"
+ " Rectangle {\n"
+ " id: testId\n"
+ " }\n"
+ "}\n");
+
+ QCOMPARE(textEdit.toPlainText(), expected);
+}
+
+void TestCore::testRewriterNodeReparentingTransaction1()
+{
+ char qmlString[] = "import Qt 4.6\n"
+ "Rectangle {\n"
+ "}\n";
+
+// QSKIP("another asserting test", SkipAll);
+
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ ModelNode rootModelNode(view->rootModelNode());
+ QVERIFY(rootModelNode.isValid());
+ QCOMPARE(rootModelNode.type(), QString("Qt/Item"));
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+
+ model->attachView(testRewriterView.data());
+
+ QVERIFY(rootModelNode.isValid());
+
+ ModelNode childNode1 = rootModelNode.addChildNode("Qt/Rectangle", 4, 6, "data");
+ ModelNode childNode2 = rootModelNode.addChildNode("Qt/Rectangle", 4, 6, "data");
+ ModelNode childNode3 = rootModelNode.addChildNode("Qt/Rectangle", 4, 6, "data");
+ ModelNode childNode4 = rootModelNode.addChildNode("Qt/Rectangle", 4, 6, "data");
+
+ ModelNode reparentNode = childNode1.addChildNode("Qt/Rectangle", 4, 6, "data");
+
+ RewriterTransaction rewriterTransaction = view->beginRewriterTransaction();
+
+ childNode2.nodeListProperty("data").reparentHere(reparentNode);
+ childNode3.nodeListProperty("data").reparentHere(reparentNode);
+ childNode4.nodeListProperty("data").reparentHere(reparentNode);
+
+ reparentNode.destroy();
+
+ rewriterTransaction.commit();
+}
+
+void TestCore::testRewriterNodeReparentingTransaction2()
+{
+ char qmlString[] = "import Qt 4.6\n"
+ "Rectangle {\n"
+ "}\n";
+
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ ModelNode rootModelNode(view->rootModelNode());
+ QVERIFY(rootModelNode.isValid());
+ QCOMPARE(rootModelNode.type(), QString("Qt/Item"));
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+
+ model->attachView(testRewriterView.data());
+
+ QVERIFY(rootModelNode.isValid());
+
+ ModelNode childNode1 = rootModelNode.addChildNode("Qt/Rectangle", 4, 6, "data");
+ ModelNode childNode2 = rootModelNode.addChildNode("Qt/Rectangle", 4, 6, "data");
+
+ childNode2.variantProperty("x") = 200;
+ childNode2.variantProperty("y") = 50;
+ childNode2.variantProperty("color") = QColor(Qt::red);
+ childNode2.setId("childNode2");
+
+ childNode1.variantProperty("x") = 100;
+ childNode1.variantProperty("y") = 10;
+ childNode1.variantProperty("color") = QColor(Qt::blue);
+ childNode1.setId("childNode1");
+
+ RewriterTransaction rewriterTransaction = view->beginRewriterTransaction();
+
+ childNode1.nodeListProperty("data").reparentHere(childNode2);
+ childNode2.variantProperty("x") = 300;
+ childNode2.variantProperty("y") = 150;
+
+ rewriterTransaction.commit();
+
+ rewriterTransaction = view->beginRewriterTransaction();
+
+ rootModelNode.nodeListProperty("data").reparentHere(childNode2);
+ childNode2.variantProperty("x") = 100;
+ childNode2.variantProperty("y") = 200;
+
+ rewriterTransaction.commit();
+
+ rewriterTransaction = view->beginRewriterTransaction();
+
+ rootModelNode.nodeListProperty("data").reparentHere(childNode2);
+ childNode2.variantProperty("x") = 150;
+ childNode2.variantProperty("y") = 250;
+ childNode1.nodeListProperty("data").reparentHere(childNode2);
+
+ rewriterTransaction.commit();
+}
+
+void TestCore::testRewriterNodeReparentingTransaction3()
+{
+ char qmlString[] = "import Qt 4.6\n"
+ "Rectangle {\n"
+ "}\n";
+
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ ModelNode rootModelNode(view->rootModelNode());
+ QVERIFY(rootModelNode.isValid());
+ QCOMPARE(rootModelNode.type(), QString("Qt/Item"));
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+
+ model->attachView(testRewriterView.data());
+
+ QVERIFY(rootModelNode.isValid());
+
+ ModelNode childNode1 = rootModelNode.addChildNode("Qt/Rectangle", 4, 6, "data");
+ ModelNode childNode2 = rootModelNode.addChildNode("Qt/Rectangle", 4, 6, "data");
+ ModelNode childNode3 = rootModelNode.addChildNode("Qt/Rectangle", 4, 6, "data");
+ ModelNode childNode4 = rootModelNode.addChildNode("Qt/Rectangle", 4, 6, "data");
+
+ RewriterTransaction rewriterTransaction = view->beginRewriterTransaction();
+
+ childNode1.nodeListProperty("data").reparentHere(childNode4);
+ childNode4.variantProperty("x") = 151;
+ childNode4.variantProperty("y") = 251;
+ childNode2.nodeListProperty("data").reparentHere(childNode4);
+ childNode4.variantProperty("x") = 152;
+ childNode4.variantProperty("y") = 252;
+ childNode3.nodeListProperty("data").reparentHere(childNode4);
+ childNode4.variantProperty("x") = 153;
+ childNode4.variantProperty("y") = 253;
+ rootModelNode.nodeListProperty("data").reparentHere(childNode4);
+ childNode4.variantProperty("x") = 154;
+ childNode4.variantProperty("y") = 254;
+
+ rewriterTransaction.commit();
+}
+
+void TestCore::testRewriterNodeReparentingTransaction4()
+{
+ char qmlString[] = "import Qt 4.6\n"
+ "Rectangle {\n"
+ "}\n";
+
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ ModelNode rootModelNode(view->rootModelNode());
+ QVERIFY(rootModelNode.isValid());
+ QCOMPARE(rootModelNode.type(), QString("Qt/Item"));
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+
+ model->attachView(testRewriterView.data());
+
+ QVERIFY(rootModelNode.isValid());
+
+ ModelNode childNode1 = rootModelNode.addChildNode("Qt/Rectangle", 4, 6, "data");
+ ModelNode childNode2 = rootModelNode.addChildNode("Qt/Rectangle", 4, 6, "data");
+ ModelNode childNode3 = rootModelNode.addChildNode("Qt/Rectangle", 4, 6, "data");
+ ModelNode childNode4 = rootModelNode.addChildNode("Qt/Rectangle", 4, 6, "data");
+ ModelNode childNode5 = childNode2.addChildNode("Qt/Rectangle", 4, 6, "data");
+
+ RewriterTransaction rewriterTransaction = view->beginRewriterTransaction();
+
+ childNode1.nodeListProperty("data").reparentHere(childNode4);
+ childNode4.variantProperty("x") = 151;
+ childNode4.variantProperty("y") = 251;
+ childNode2.nodeListProperty("data").reparentHere(childNode4);
+ childNode4.variantProperty("x") = 152;
+ childNode4.variantProperty("y") = 252;
+ childNode3.nodeListProperty("data").reparentHere(childNode4);
+ childNode4.variantProperty("x") = 153;
+ childNode4.variantProperty("y") = 253;
+ childNode5.nodeListProperty("data").reparentHere(childNode4);
+ childNode4.variantProperty("x") = 154;
+ childNode4.variantProperty("y") = 254;
+
+ rewriterTransaction.commit();
+}
+
+void TestCore::testRewriterAddNodeTransaction()
+{
+ char qmlString[] = "import Qt 4.6\n"
+ "Rectangle {\n"
+ "}\n";
+
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ ModelNode rootModelNode(view->rootModelNode());
+ QVERIFY(rootModelNode.isValid());
+ QCOMPARE(rootModelNode.type(), QString("Qt/Item"));
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+
+ model->attachView(testRewriterView.data());
+
+ QVERIFY(rootModelNode.isValid());
+
+
+ ModelNode childNode = rootModelNode.addChildNode("Qt/Rectangle", 4, 6, "data");
+
+ RewriterTransaction rewriterTransaction = view->beginRewriterTransaction();
+
+ ModelNode newNode = view->createModelNode("Qt/Rectangle", 4, 6);
+ newNode.variantProperty("x") = 100;
+ newNode.variantProperty("y") = 100;
+
+ rootModelNode.nodeListProperty("data").reparentHere(newNode);
+ childNode.nodeListProperty("data").reparentHere(newNode);
+
+ rewriterTransaction.commit();
+}
+
+void TestCore::testRewriterComponentId()
+{
+ char qmlString[] = "import Qt 4.6\n"
+ "Rectangle {\n"
+ " Component {\n"
+ " id: testComponent\n"
+ " Item {\n"
+ " }\n"
+ " }\n"
+ "}\n";
+
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+ model->attachView(testRewriterView.data());
+
+ ModelNode rootModelNode(view->rootModelNode());
+ QVERIFY(rootModelNode.isValid());
+ QCOMPARE(rootModelNode.type(), QString("Qt/Rectangle"));
+
+ ModelNode component(rootModelNode.allDirectSubModelNodes().first());
+ QVERIFY(component.isValid());
+ QCOMPARE(component.type(), QString("Qt/Component"));
+ QCOMPARE(component.id(), QString("testComponent"));
+}
+
+void TestCore::testRewriterTransactionRewriter()
+{
+ char qmlString[] = "import Qt 4.6\n"
+ "Rectangle {\n"
+ "}\n";
+
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ ModelNode rootModelNode(view->rootModelNode());
+ QVERIFY(rootModelNode.isValid());
+ QCOMPARE(rootModelNode.type(), QString("Qt/Item"));
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+
+ model->attachView(testRewriterView.data());
+
+ QVERIFY(rootModelNode.isValid());
+
+ ModelNode childNode1;
+ ModelNode childNode2;
+
+ {
+ RewriterTransaction transaction = view->beginRewriterTransaction();
+ childNode1 = rootModelNode.addChildNode("Qt/Rectangle", 4, 6, "data");
+ childNode1.variantProperty("x") = "10";
+ childNode1.variantProperty("y") = "10";
+ }
+
+ QVERIFY(childNode1.isValid());
+ QCOMPARE(childNode1.variantProperty("x").value(), QVariant(10));
+ QCOMPARE(childNode1.variantProperty("y").value(), QVariant(10));
+
+
+ {
+ RewriterTransaction transaction = view->beginRewriterTransaction();
+ childNode2 = childNode1.addChildNode("Qt/Rectangle", 4, 6, "data");
+ childNode2.destroy();
+ }
+
+ QVERIFY(!childNode2.isValid());
+ QVERIFY(childNode1.isValid());
+}
+
+void TestCore::testRewriterPropertyDeclarations()
+{
+// QSKIP("Work in progress. See task https://qtrequirements.europe.nokia.com/browse/BAUHAUS-170",
+// SkipAll);
+
+ //
+ // test properties defined in qml
+ //
+ // [default] property <type> <name>[: defaultValue]
+ //
+ // where type is (int | bool | double | real | string | url | color | date | var | variant)
+ //
+
+ // Unsupported:
+ // property var varProperty2: boolProperty
+ // property var myArray: [ Rectangle {} ]
+ // property var someGradient: Gradient {}
+
+ char qmlString[] = "import Qt 4.6\n"
+ "Item {\n"
+ " property int intProperty\n"
+ " property bool boolProperty: true\n"
+ " property var varProperty1\n"
+ " property variant varProperty2: boolProperty\n"
+ " default property url urlProperty\n"
+ " intProperty: 2\n"
+ "}\n";
+
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+ model->attachView(testRewriterView.data());
+
+ //
+ // parsing
+ //
+ ModelNode rootModelNode(view->rootModelNode());
+ QVERIFY(rootModelNode.isValid());
+ QCOMPARE(rootModelNode.type(), QString("Qt/Item"));
+
+ QCOMPARE(rootModelNode.properties().size(), 5);
+
+ VariantProperty intProperty = rootModelNode.property(QLatin1String("intProperty")).toVariantProperty();
+ QVERIFY(intProperty.isValid());
+ QVERIFY(intProperty.isVariantProperty());
+
+ VariantProperty boolProperty = rootModelNode.property(QLatin1String("boolProperty")).toVariantProperty();
+ QVERIFY(boolProperty.isValid());
+ QVERIFY(boolProperty.isVariantProperty());
+ QCOMPARE(boolProperty.value(), QVariant(true));
+
+ VariantProperty varProperty1 = rootModelNode.property(QLatin1String("varProperty1")).toVariantProperty();
+ QVERIFY(varProperty1.isValid());
+ QVERIFY(varProperty1.isVariantProperty());
+ QCOMPARE(varProperty1.value(), QVariant());
+
+ VariantProperty urlProperty = rootModelNode.property(QLatin1String("urlProperty")).toVariantProperty();
+ QVERIFY(urlProperty.isValid());
+ QVERIFY(urlProperty.isVariantProperty());
+ QCOMPARE(urlProperty.value(), QVariant());
+}
+
+void TestCore::testRewriterPropertyAliases()
+{
+ //
+ // test property aliases defined in qml, i.e.
+ //
+ // [default] property alias <name>: <alias reference>
+ //
+ // where type is (int | bool | double | real | string | url | color | date | var | variant)
+ //
+
+ char qmlString[] = "import Qt 4.6\n"
+ "Item {\n"
+ " property alias theText: t.text\n"
+ " default alias property yPos: t.y\n"
+ " Text { id: t; text: \"zoo\"}\n"
+ "}\n";
+
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+ model->attachView(testRewriterView.data());
+
+ ModelNode rootModelNode(view->rootModelNode());
+ QVERIFY(rootModelNode.isValid());
+ QCOMPARE(rootModelNode.type(), QString("Qt/Item"));
+
+ QList<AbstractProperty> properties = rootModelNode.properties();
+ QCOMPARE(properties.size(), 0); // TODO: How to represent alias properties? As Bindings?
+}
+
+void TestCore::testRewriterPositionAndOffset()
+{
+ const QLatin1String qmlString("\n"
+ "import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ " id: Root\n"
+ " x: 10;\n"
+ " y: 10;\n"
+ " Rectangle {\n"
+ " id: Rectangle1\n"
+ " x: 10;\n"
+ " y: 10;\n"
+ " }\n"
+ " Rectangle {\n"
+ " id: Rectangle2\n"
+ " x: 100;\n"
+ " y: 100;\n"
+ " anchors.fill: Root\n"
+ " }\n"
+ " Rectangle {\n"
+ " id: Rectangle3\n"
+ " x: 140;\n"
+ " y: 180;\n"
+ " gradient: Gradient {\n"
+ " GradientStop {\n"
+ " position: 0\n"
+ " color: \"white\"\n"
+ " }\n"
+ " GradientStop {\n"
+ " position: 1\n"
+ " color: \"black\"\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ "}");
+
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item", 4, 6));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ model->attachView(view.data());
+
+ // read in
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+ model->attachView(testRewriterView.data());
+
+ ModelNode rootNode = view->rootModelNode();
+ QVERIFY(rootNode.isValid());
+ QCOMPARE(rootNode.type(), QLatin1String("Qt/Rectangle"));
+
+ QString string;
+ string = "";
+ for (int i=testRewriterView->nodeOffset(rootNode); i < testRewriterView->nodeOffset(rootNode) + testRewriterView->nodeLength(rootNode);i++)
+ string +=QString(qmlString)[i];
+
+ const QString qmlExpected0("Rectangle {\n"
+ " id: Root\n"
+ " x: 10;\n"
+ " y: 10;\n"
+ " Rectangle {\n"
+ " id: Rectangle1\n"
+ " x: 10;\n"
+ " y: 10;\n"
+ " }\n"
+ " Rectangle {\n"
+ " id: Rectangle2\n"
+ " x: 100;\n"
+ " y: 100;\n"
+ " anchors.fill: Root\n"
+ " }\n"
+ " Rectangle {\n"
+ " id: Rectangle3\n"
+ " x: 140;\n"
+ " y: 180;\n"
+ " gradient: Gradient {\n"
+ " GradientStop {\n"
+ " position: 0\n"
+ " color: \"white\"\n"
+ " }\n"
+ " GradientStop {\n"
+ " position: 1\n"
+ " color: \"black\"\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ "}");
+
+ QCOMPARE(string, qmlExpected0);
+
+ ModelNode lastRectNode = rootNode.allDirectSubModelNodes().last();
+ ModelNode gradientNode = lastRectNode.allDirectSubModelNodes().first();
+ ModelNode gradientStop = gradientNode.allDirectSubModelNodes().first();
+
+ string = "";
+ for (int i=testRewriterView->nodeOffset(gradientNode); i < testRewriterView->nodeOffset(gradientNode) + testRewriterView->nodeLength(gradientNode);i++)
+ string +=QString(qmlString)[i];
+
+ const QString qmlExpected1( "Gradient {\n"
+ " GradientStop {\n"
+ " position: 0\n"
+ " color: \"white\"\n"
+ " }\n"
+ " GradientStop {\n"
+ " position: 1\n"
+ " color: \"black\"\n"
+ " }\n"
+ " }");
+
+ QCOMPARE(string, qmlExpected1);
+
+ string = "";
+ for (int i=testRewriterView->nodeOffset(gradientStop); i < testRewriterView->nodeOffset(gradientStop) + testRewriterView->nodeLength(gradientStop);i++)
+ string +=QString(qmlString)[i];
+
+ const QString qmlExpected2( "GradientStop {\n"
+ " position: 0\n"
+ " color: \"white\"\n"
+ " }");
+
+ QCOMPARE(string, qmlExpected2);
+}
+
+void TestCore::testRewriterComponentTextModifier()
+{
+ const QString qmlString("import Qt 4.6\n"
+ "Rectangle {\n"
+ " id: Root\n"
+ " x: 10;\n"
+ " y: 10;\n"
+ " Rectangle {\n"
+ " id: Rectangle1\n"
+ " x: 10;\n"
+ " y: 10;\n"
+ " }\n"
+ " Component {\n"
+ " id: RectangleComponent\n"
+ " Rectangle {\n"
+ " x: 100;\n"
+ " y: 100;\n"
+ " }\n"
+ " }\n"
+ "}");
+
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item", 4, 6));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ model->attachView(view.data());
+
+ // read in
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+ model->attachView(testRewriterView.data());
+
+ ModelNode rootNode = view->rootModelNode();
+ QVERIFY(rootNode.isValid());
+ QCOMPARE(rootNode.type(), QLatin1String("Qt/Rectangle"));
+
+ ModelNode componentNode = rootNode.allDirectSubModelNodes().last();
+
+ int componentStartOffset = testRewriterView->nodeOffset(componentNode);
+ int componentEndOffset = componentStartOffset + testRewriterView->nodeLength(componentNode);
+
+ int rootStartOffset = testRewriterView->nodeOffset(rootNode);
+
+ ComponentTextModifier componentTextModifier(&textModifier, componentStartOffset, componentEndOffset, rootStartOffset);
+
+ const QString qmlExpected("import Qt 4.6\n"
+ " "
+ " "
+ " "
+ " "
+ " "
+ " "
+ " "
+ " "
+ " "
+ " Component {\n"
+ " id: RectangleComponent\n"
+ " Rectangle {\n"
+ " x: 100;\n"
+ " y: 100;\n"
+ " }\n"
+ " } "
+ " ");
+
+ QCOMPARE(componentTextModifier.text(), qmlExpected);
+
+ QScopedPointer<Model> componentModel(Model::create("Qt/Item", 4, 6));
+ QScopedPointer<TestRewriterView> testRewriterViewComponent(new TestRewriterView());
+ testRewriterViewComponent->setTextModifier(&componentTextModifier);
+ componentModel->attachView(testRewriterViewComponent.data());
+
+ ModelNode componentRootNode = testRewriterViewComponent->rootModelNode();
+ QVERIFY(componentRootNode.isValid());
+ QCOMPARE(componentRootNode.type(), QLatin1String("Qt/Component"));
+}
+
+void TestCore::testRewriterPreserveType()
+{
+ const QString qmlString("import Qt 4.6\n"
+ "Rectangle {\n"
+ " id: root\n"
+ " Text {\n"
+ " font.bold: true\n"
+ " font.pointSize: 14\n"
+ " }\n"
+ "}");
+
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item", 4, 6));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ model->attachView(view.data());
+
+ // read in
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+ model->attachView(testRewriterView.data());
+
+ ModelNode rootNode = view->rootModelNode();
+ QVERIFY(rootNode.isValid());
+ QCOMPARE(rootNode.type(), QLatin1String("Qt/Rectangle"));
+
+ ModelNode textNode = rootNode.allDirectSubModelNodes().first();
+ QCOMPARE(QVariant::Bool, textNode.variantProperty("font.bold").value().type());
+ QCOMPARE(QVariant::Double, textNode.variantProperty("font.pointSize").value().type());
+ textNode.variantProperty("font.bold") = QVariant(false);
+ textNode.variantProperty("font.bold") = QVariant(true);
+ textNode.variantProperty("font.pointSize") = QVariant(13.0);
+
+ ModelNode newTextNode = rootNode.addChildNode("Qt/Text", 4, 6, "data");
+
+ newTextNode.variantProperty("font.bold") = QVariant(true);
+ newTextNode.variantProperty("font.pointSize") = QVariant(13.0);
+
+ QCOMPARE(QVariant::Bool, newTextNode.variantProperty("font.bold").value().type());
+ QCOMPARE(QVariant::Double, newTextNode.variantProperty("font.pointSize").value().type());
+}
+
+void TestCore::testRewriterForArrayMagic()
+{
+ const QLatin1String qmlString("import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ " states: State {\n"
+ " name: \"s1\"\n"
+ " }\n"
+ "}\n");
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item", 4, 6));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ model->attachView(view.data());
+
+ // read in
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+ model->attachView(testRewriterView.data());
+
+ ModelNode rootNode = view->rootModelNode();
+ QVERIFY(rootNode.isValid());
+ QCOMPARE(rootNode.type(), QString("Qt/Rectangle"));
+
+ QmlItemNode rootItem(rootNode);
+ QVERIFY(rootItem.isValid());
+
+ QmlModelState state1(rootItem.states().addState("s2"));
+ QCOMPARE(state1.modelNode().type(), QString("Qt/State"));
+
+ const QLatin1String expected("import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ " states: [\n"
+ " State {\n"
+ " name: \"s1\"\n"
+ " },\n"
+ " State {\n"
+ " name: \"s2\"\n"
+ " }\n"
+ " ]\n"
+ "}\n");
+ QCOMPARE(textEdit.toPlainText(), expected);
+}
+
+void TestCore::testRewriterWithSignals()
+{
+ const QLatin1String qmlString("import Qt 4.6\n"
+ "\n"
+ "TextEdit {\n"
+ " onTextChanged: { print(\"foo\"); }\n"
+ "}\n");
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item", 4, 6));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ model->attachView(view.data());
+
+ // read in
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+ model->attachView(testRewriterView.data());
+
+ ModelNode rootNode = view->rootModelNode();
+ QVERIFY(rootNode.isValid());
+ QCOMPARE(rootNode.type(), QString("Qt/TextEdit"));
+
+ QmlItemNode rootItem(rootNode);
+ QVERIFY(rootItem.isValid());
+
+ QCOMPARE(rootNode.properties().count(), 0);
+}
+
+void TestCore::testRewriterNodeSliding()
+{
+ const QLatin1String qmlString("import Qt 4.6\n"
+ "Rectangle {\n"
+ " id: root\n"
+ " Rectangle {\n"
+ " id: rectangle1\n"
+ " x: 10;\n"
+ " y: 10;\n"
+ " }\n"
+ "\n"
+ " Rectangle {\n"
+ " id: rectangle2\n"
+ " x: 100;\n"
+ " y: 100;\n"
+ " }\n"
+ "}");
+
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item", 4, 6));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ model->attachView(view.data());
+
+ // read in
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+ model->attachView(testRewriterView.data());
+
+ ModelNode rootNode = view->rootModelNode();
+ QVERIFY(rootNode.isValid());
+ QCOMPARE(rootNode.type(), QLatin1String("Qt/Rectangle"));
+ QCOMPARE(rootNode.id(), QLatin1String("root"));
+
+ QCOMPARE(rootNode.nodeListProperty(QLatin1String("data")).toModelNodeList().at(0).id(), QLatin1String("rectangle1"));
+ QCOMPARE(rootNode.nodeListProperty(QLatin1String("data")).toModelNodeList().at(1).id(), QLatin1String("rectangle2"));
+
+ rootNode.nodeListProperty(QLatin1String("data")).slide(0, 1);
+
+ QCOMPARE(rootNode.nodeListProperty(QLatin1String("data")).toModelNodeList().at(0).id(), QLatin1String("rectangle2"));
+ QCOMPARE(rootNode.nodeListProperty(QLatin1String("data")).toModelNodeList().at(1).id(), QLatin1String("rectangle1"));
+
+ rootNode.nodeListProperty(QLatin1String("data")).slide(1, 0);
+
+ QCOMPARE(rootNode.nodeListProperty(QLatin1String("data")).toModelNodeList().at(0).id(), QLatin1String("rectangle1"));
+ QCOMPARE(rootNode.nodeListProperty(QLatin1String("data")).toModelNodeList().at(1).id(), QLatin1String("rectangle2"));
+}
+
+void TestCore::testRewriterFirstDefinitionInside()
+{
+ const QString qmlString("import Qt 4.6\n"
+ "Rectangle {\n"
+ " id: Root\n"
+ " x: 10;\n"
+ " y: 10;\n"
+ " Rectangle {\n"
+ " id: Rectangle1\n"
+ " x: 10;\n"
+ " y: 10;\n"
+ " }\n"
+ " Component {\n"
+ " id: RectangleComponent\n"
+ " Rectangle {\n"
+ " x: 100;\n"
+ " y: 100;\n"
+ " }\n"
+ " }\n"
+ "}");
+
+
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item", 4, 6));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ model->attachView(view.data());
+
+ // read in
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+ model->attachView(testRewriterView.data());
+
+ ModelNode rootNode = view->rootModelNode();
+ QVERIFY(rootNode.isValid());
+ QCOMPARE(rootNode.type(), QLatin1String("Qt/Rectangle"));
+
+ ModelNode componentNode = rootNode.allDirectSubModelNodes().last();
+
+ QString string = "";
+ for (int i = testRewriterView->firstDefinitionInsideOffset(componentNode); i < testRewriterView->firstDefinitionInsideOffset(componentNode) + testRewriterView->firstDefinitionInsideLength(componentNode);i++)
+ string +=QString(qmlString)[i];
+
+ const QString qmlExpected("Rectangle {\n"
+ " x: 100;\n"
+ " y: 100;\n"
+ " }");
+ QCOMPARE(string, qmlExpected);
+
+}
+
+void TestCore::testCopyModelRewriter1()
+{
+ const QLatin1String qmlString("\n"
+ "import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ " id: Root\n"
+ " x: 10;\n"
+ " y: 10;\n"
+ " Rectangle {\n"
+ " id: Rectangle1\n"
+ " x: 10;\n"
+ " y: 10;\n"
+ " }\n"
+ " Rectangle {\n"
+ " id: Rectangle2\n"
+ " x: 100;\n"
+ " y: 100;\n"
+ " anchors.fill: Root\n"
+ " }\n"
+ " Rectangle {\n"
+ " id: Rectangle3\n"
+ " x: 140;\n"
+ " y: 180;\n"
+ " gradient: Gradient {\n"
+ " GradientStop {\n"
+ " position: 0\n"
+ " color: \"white\"\n"
+ " }\n"
+ " GradientStop {\n"
+ " position: 1\n"
+ " color: \"black\"\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ "}");
+
+ QPlainTextEdit textEdit1;
+ textEdit1.setPlainText(qmlString);
+ PlainTextEditModifier textModifier1(&textEdit1);
+
+ QScopedPointer<Model> model1(Model::create("Qt/Item", 4, 6));
+ QVERIFY(model1.data());
+
+ QScopedPointer<TestView> view1(new TestView);
+ model1->attachView(view1.data());
+
+ // read in 1
+ QScopedPointer<TestRewriterView> testRewriterView1(new TestRewriterView());
+ testRewriterView1->setTextModifier(&textModifier1);
+ model1->attachView(testRewriterView1.data());
+
+ ModelNode rootNode1 = view1->rootModelNode();
+ QVERIFY(rootNode1.isValid());
+ QCOMPARE(rootNode1.type(), QLatin1String("Qt/Rectangle"));
+
+ QPlainTextEdit textEdit2;
+ textEdit2.setPlainText(qmlString);
+ PlainTextEditModifier textModifier2(&textEdit2);
+
+ QScopedPointer<Model> model2(Model::create("Qt/Item", 4, 6));
+ QVERIFY(model2.data());
+
+ QScopedPointer<TestView> view2(new TestView);
+ model2->attachView(view2.data());
+
+ // read in 2
+ QScopedPointer<TestRewriterView> testRewriterView2(new TestRewriterView());
+ testRewriterView2->setTextModifier(&textModifier2);
+ model2->attachView(testRewriterView2.data());
+
+ ModelNode rootNode2 = view2->rootModelNode();
+ QVERIFY(rootNode2.isValid());
+ QCOMPARE(rootNode2.type(), QLatin1String("Qt/Rectangle"));
+
+
+ //
+
+ ModelNode childNode(rootNode1.allDirectSubModelNodes().first());
+ QVERIFY(childNode.isValid());
+
+ RewriterTransaction transaction(view1->beginRewriterTransaction());
+
+ ModelMerger merger(view1.data());
+
+ ModelNode insertedNode(merger.insertModel(rootNode2));
+ transaction.commit();
+
+ QCOMPARE(insertedNode.id(), QString("Root1"));
+
+ QVERIFY(insertedNode.isValid());
+ childNode.nodeListProperty("data").reparentHere(insertedNode);
+
+
+
+ const QLatin1String expected(
+
+ "\n"
+ "import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ " id: Root\n"
+ " x: 10;\n"
+ " y: 10;\n"
+ " Rectangle {\n"
+ " id: Rectangle1\n"
+ " x: 10;\n"
+ " y: 10;\n"
+ "\n"
+ " Rectangle {\n"
+ " id: Root1\n"
+ " x: 10\n"
+ " y: 10\n"
+ " Rectangle {\n"
+ " id: Rectangle11\n"
+ " x: 10\n"
+ " y: 10\n"
+ " }\n"
+ "\n"
+ " Rectangle {\n"
+ " id: Rectangle21\n"
+ " x: 100\n"
+ " y: 100\n"
+ " anchors.fill: Root1\n"
+ " }\n"
+ "\n"
+ " Rectangle {\n"
+ " id: Rectangle31\n"
+ " x: 140\n"
+ " y: 180\n"
+ " gradient: Gradient {\n"
+ " GradientStop {\n"
+ " position: 0\n"
+ " color: \"#ffffff\"\n"
+ " }\n"
+ "\n"
+ " GradientStop {\n"
+ " position: 1\n"
+ " color: \"#000000\"\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " Rectangle {\n"
+ " id: Rectangle2\n"
+ " x: 100;\n"
+ " y: 100;\n"
+ " anchors.fill: Root\n"
+ " }\n"
+ " Rectangle {\n"
+ " id: Rectangle3\n"
+ " x: 140;\n"
+ " y: 180;\n"
+ " gradient: Gradient {\n"
+ " GradientStop {\n"
+ " position: 0\n"
+ " color: \"white\"\n"
+ " }\n"
+ " GradientStop {\n"
+ " position: 1\n"
+ " color: \"black\"\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ "}");
+
+ QCOMPARE(textEdit1.toPlainText(), expected);
+}
+
+void TestCore::testCopyModelRewriter2()
+{
+ const QLatin1String qmlString1("\n"
+ "import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ " id: Root\n"
+ " x: 10\n"
+ " y: 10\n"
+ "\n"
+ " Rectangle {\n"
+ " id: Rectangle1\n"
+ " x: 10\n"
+ " y: 10\n"
+ " }\n"
+ "\n"
+ " Rectangle {\n"
+ " id: Rectangle2\n"
+ " x: 100\n"
+ " y: 100\n"
+ " anchors.fill: Rectangle1\n"
+ " }\n"
+ "\n"
+ " Rectangle {\n"
+ " id: Rectangle3\n"
+ " x: 140\n"
+ " y: 180\n"
+ " gradient: Gradient {\n"
+ " GradientStop {\n"
+ " position: 0\n"
+ " color: \"#ffffff\"\n"
+ " }\n"
+ "\n"
+ " GradientStop {\n"
+ " position: 1\n"
+ " color: \"#000000\"\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ "}");
+
+
+ const QLatin1String qmlString2("\n"
+ "import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ "}");
+
+ QPlainTextEdit textEdit1;
+ textEdit1.setPlainText(qmlString1);
+ PlainTextEditModifier textModifier1(&textEdit1);
+
+ QScopedPointer<Model> model1(Model::create("Qt/Item", 4, 6));
+ QVERIFY(model1.data());
+
+ QScopedPointer<TestView> view1(new TestView);
+ model1->attachView(view1.data());
+
+ // read in 1
+ QScopedPointer<TestRewriterView> testRewriterView1(new TestRewriterView());
+ testRewriterView1->setTextModifier(&textModifier1);
+ model1->attachView(testRewriterView1.data());
+
+ ModelNode rootNode1 = view1->rootModelNode();
+ QVERIFY(rootNode1.isValid());
+ QCOMPARE(rootNode1.type(), QLatin1String("Qt/Rectangle"));
+
+
+ // read in 2
+
+ QPlainTextEdit textEdit2;
+ textEdit2.setPlainText(qmlString2);
+ PlainTextEditModifier textModifier2(&textEdit2);
+
+ QScopedPointer<Model> model2(Model::create("Qt/Item", 4, 6));
+ QVERIFY(model2.data());
+
+ QScopedPointer<TestView> view2(new TestView);
+ model2->attachView(view2.data());
+
+ QScopedPointer<TestRewriterView> testRewriterView2(new TestRewriterView());
+ testRewriterView2->setTextModifier(&textModifier2);
+ model2->attachView(testRewriterView2.data());
+
+ ModelNode rootNode2 = view2->rootModelNode();
+ QVERIFY(rootNode2.isValid());
+ QCOMPARE(rootNode2.type(), QLatin1String("Qt/Rectangle"));
+
+
+ //
+
+ ModelMerger merger(view2.data());
+
+ merger.replaceModel(rootNode1);
+ QVERIFY(rootNode2.isValid());
+ QCOMPARE(rootNode2.type(), QLatin1String("Qt/Rectangle"));
+
+ QCOMPARE(textEdit2.toPlainText(), qmlString1);
+}
+
+
+void TestCore::loadQml()
+{
+char qmlString[] = "import Qt 4.6\n"
+ "Rectangle {\n"
+ "id: root;\n"
+ "width: 200;\n"
+ "height: 200;\n"
+ "color: \"white\";\n"
+ "Text {\n"
+ "id: text1\n"
+ "text: \"Hello World\"\n"
+ "anchors.centerIn: parent\n"
+ "Item {\n"
+ "id: item\n"
+ "}\n"
+ "}\n"
+ "Rectangle {\n"
+ "id: rectangle;\n"
+ "gradient: Gradient {\n"
+ "GradientStop {\n"
+ "position: 0\n"
+ "color: \"white\"\n"
+ "}\n"
+ "GradientStop {\n"
+ "position: 1\n"
+ "color: \"black\"\n"
+ "}\n"
+ "}\n"
+ "}\n"
+ "Text {\n"
+ "text: \"text\"\n"
+ "x: 66\n"
+ "y: 43\n"
+ "width: 80\n"
+ "height: 20\n"
+ "id: text2\n"
+ "}\n"
+ "}\n";
+
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ ModelNode rootModelNode(view->rootModelNode());
+ QVERIFY(rootModelNode.isValid());
+ QCOMPARE(rootModelNode.type(), QString("Qt/Item"));
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+
+ model->attachView(testRewriterView.data());
+
+ QVERIFY(rootModelNode.isValid());
+ QCOMPARE(rootModelNode.type(), QString("Qt/Rectangle"));
+ QCOMPARE(rootModelNode.id(), QString("root"));
+ QCOMPARE(rootModelNode.variantProperty("width").value().toInt(), 200);
+ QCOMPARE(rootModelNode.variantProperty("height").value().toInt(), 200);
+ QVERIFY(rootModelNode.hasProperty("data"));
+ QVERIFY(rootModelNode.property("data").isNodeListProperty());
+ QVERIFY(!rootModelNode.nodeListProperty("data").toModelNodeList().isEmpty());
+ QCOMPARE(rootModelNode.nodeListProperty("data").toModelNodeList().count(), 3);
+ ModelNode textNode1 = rootModelNode.nodeListProperty("data").toModelNodeList().first();
+ QVERIFY(textNode1.isValid());
+ QCOMPARE(textNode1.type(), QString("Qt/Text"));
+ QCOMPARE(textNode1.id(), QString("text1"));
+ QCOMPARE(textNode1.variantProperty("text").value().toString(), QString("Hello World"));
+ QVERIFY(textNode1.hasProperty("anchors.centerIn"));
+ QVERIFY(textNode1.property("anchors.centerIn").isBindingProperty());
+ QCOMPARE(textNode1.bindingProperty("anchors.centerIn").expression(), QString("parent"));
+ QVERIFY(textNode1.hasProperty("data"));
+ QVERIFY(textNode1.property("data").isNodeListProperty());
+ QVERIFY(!textNode1.nodeListProperty("data").toModelNodeList().isEmpty());
+ ModelNode itemNode = textNode1.nodeListProperty("data").toModelNodeList().first();
+ QVERIFY(itemNode.isValid());
+ QCOMPARE(itemNode.id(), QString("item"));
+ QVERIFY(!itemNode.hasProperty("data"));
+
+ ModelNode rectNode = rootModelNode.nodeListProperty("data").toModelNodeList().at(1);
+ QVERIFY(rectNode.isValid());
+ QCOMPARE(rectNode.type(), QString("Qt/Rectangle"));
+ QCOMPARE(rectNode.id(), QString("rectangle"));
+ QVERIFY(rectNode.hasProperty("gradient"));
+ QVERIFY(rectNode.property("gradient").isNodeProperty());
+ ModelNode gradientNode = rectNode.nodeProperty("gradient").modelNode();
+ QVERIFY(gradientNode.isValid());
+ QCOMPARE(gradientNode.type(), QString("Qt/Gradient"));
+ QVERIFY(gradientNode.hasProperty("stops"));
+ QVERIFY(gradientNode.property("stops").isNodeListProperty());
+ QCOMPARE(gradientNode.nodeListProperty("stops").toModelNodeList().count(), 2);
+
+ ModelNode stop1 = gradientNode.nodeListProperty("stops").toModelNodeList().first();
+ ModelNode stop2 = gradientNode.nodeListProperty("stops").toModelNodeList().last();
+
+ QVERIFY(stop1.isValid());
+ QVERIFY(stop2.isValid());
+
+ QCOMPARE(stop1.type(), QString("Qt/GradientStop"));
+ QCOMPARE(stop2.type(), QString("Qt/GradientStop"));
+
+ QCOMPARE(stop1.variantProperty("position").value().toInt(), 0);
+ QCOMPARE(stop2.variantProperty("position").value().toInt(), 1);
+
+ ModelNode textNode2 = rootModelNode.nodeListProperty("data").toModelNodeList().last();
+ QVERIFY(textNode2.isValid());
+ QCOMPARE(textNode2.type(), QString("Qt/Text"));
+ QCOMPARE(textNode2.id(), QString("text2"));
+ QCOMPARE(textNode2.variantProperty("width").value().toInt(), 80);
+ QCOMPARE(textNode2.variantProperty("height").value().toInt(), 20);
+ QCOMPARE(textNode2.variantProperty("x").value().toInt(), 66);
+ QCOMPARE(textNode2.variantProperty("y").value().toInt(), 43);
+ QCOMPARE(textNode2.variantProperty("text").value().toString(), QString("text"));
+}
+
+void TestCore::testMetaInfo()
+{
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ QVERIFY(model->metaInfo().hasNodeMetaInfo("Qt/Item"));
+ QVERIFY(model->metaInfo().hasNodeMetaInfo("Qt/QtObject"));
+ QVERIFY(model->metaInfo().isSubclassOf("Qt/Text", "Qt/QtObject"));
+ QVERIFY(model->metaInfo().isSubclassOf("Qt/Text", "Qt/Item"));
+ QVERIFY(model->metaInfo().isSubclassOf("Qt/Rectangle", "Qt/QtObject"));
+
+ QVERIFY(!model->metaInfo().isSubclassOf("Fooo", "Qt/QtObject"));
+
+ QVERIFY(model->metaInfo().nodeMetaInfo("Qt/Item", 4, 6).isContainer());
+
+ QCOMPARE(view->rootModelNode().metaInfo().typeName(), QString("Qt/Item"));
+ QVERIFY(view->rootModelNode().metaInfo().hasProperty("x"));
+ QVERIFY(!view->rootModelNode().metaInfo().hasProperty("blah"));
+ QVERIFY(!view->rootModelNode().metaInfo().property("blah").isValid());
+ QVERIFY(view->rootModelNode().metaInfo().isContainer());
+
+ ModelNode rectNode = view->rootModelNode().addChildNode("Qt/Rectangle", 4, 6, "data");
+
+ QVERIFY(rectNode.metaInfo().isSubclassOf("Qt/QtObject"));
+ QVERIFY(rectNode.metaInfo().isSubclassOf("Qt/Item"));
+ QVERIFY(!rectNode.metaInfo().isSubclassOf("Qt/Text"));
+ QVERIFY(rectNode.metaInfo().hasProperty("color"));
+ QVERIFY(rectNode.metaInfo().hasProperty("x"));
+ QVERIFY(!rectNode.metaInfo().hasProperty("blah"));
+ QVERIFY(rectNode.metaInfo().isContainer());
+
+ ModelNode textNode = view->rootModelNode().addChildNode("Qt/TextEdit", 4, 6, "data");
+ NodeMetaInfo textNodeMetaInfo = textNode.metaInfo();
+ QVERIFY(textNodeMetaInfo.hasProperty("text"));
+ QVERIFY(textNodeMetaInfo.property("text").isValid());
+ QVERIFY(textNodeMetaInfo.property("text").isReadable());
+ QVERIFY(textNodeMetaInfo.property("text").isWriteable());
+ QVERIFY(textNodeMetaInfo.property("x").isReadable());
+ QVERIFY(textNodeMetaInfo.property("x").isWriteable());
+ QVERIFY(textNodeMetaInfo.isSubclassOf("Qt/Item", 4, 6));
+ QVERIFY(!textNodeMetaInfo.isSubclassOf("Blah"));
+ QVERIFY(textNodeMetaInfo.isQmlGraphicsItem());
+ QVERIFY(textNodeMetaInfo.isGraphicsObject());
+ QVERIFY(!textNodeMetaInfo.isGraphicsWidget());
+
+ // test types declared with EXTENDED_OBJECT
+ NodeMetaInfo graphicsWidgetInfo = model->metaInfo().nodeMetaInfo("Qt/QGraphicsWidget", 4, 6);
+ QVERIFY(graphicsWidgetInfo.isValid());
+ QVERIFY(graphicsWidgetInfo.hasProperty("layout")); // from QGraphicsWidgetDeclarativeUI
+ QVERIFY(graphicsWidgetInfo.hasProperty("font")); // from QGraphicsWidget
+ QVERIFY(graphicsWidgetInfo.hasProperty("enabled")); // from QGraphicsItem
+}
+
+void TestCore::testMetaInfoDotProperties()
+{
+ QScopedPointer<Model> model(Model::create("Qt/Text"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ QVERIFY(model->metaInfo().hasNodeMetaInfo("Qt/Text"));
+ QCOMPARE(view->rootModelNode().metaInfo().typeName(), QString("Qt/Text"));
+ QVERIFY(!view->rootModelNode().metaInfo().property("text").isValueType());
+ QVERIFY(view->rootModelNode().metaInfo().hasProperty("font"));
+ QVERIFY(view->rootModelNode().metaInfo().property("font").isValueType());
+
+ QVERIFY(view->rootModelNode().metaInfo().hasProperty("font.bold", true));
+ QVERIFY(view->rootModelNode().metaInfo().properties(true).keys().contains("font.bold"));
+ QVERIFY(!view->rootModelNode().metaInfo().properties().keys().contains("font.bold"));
+ QVERIFY(view->rootModelNode().metaInfo().properties(true).keys().contains("font.pointSize"));
+ QVERIFY(view->rootModelNode().metaInfo().hasProperty("font.pointSize", true));
+ QVERIFY(view->rootModelNode().metaInfo().property("font.pointSize", true).isValid());
+
+ ModelNode rectNode(view->rootModelNode().addChildNode("Qt/Rectangle", 4, 6, "data"));
+
+
+ QVERIFY(rectNode.metaInfo().properties(true).keys().contains("pos.x"));
+ QVERIFY(!rectNode.metaInfo().properties().keys().contains("pos.x"));
+ QVERIFY(rectNode.metaInfo().properties(true).keys().contains("pos.y"));
+ QVERIFY(!rectNode.metaInfo().properties().keys().contains("pos.y"));
+ QVERIFY(rectNode.metaInfo().properties(true).keys().contains("border.width"));
+ QVERIFY(rectNode.metaInfo().hasProperty("border"));
+ QVERIFY(!rectNode.metaInfo().property("border").isValueType());
+ QVERIFY(rectNode.metaInfo().hasProperty("border.width", true));
+ QVERIFY(rectNode.metaInfo().property("border.width", true).isValid());
+}
+
+void TestCore::testMetaInfoListProperties()
+{
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ QVERIFY(model->metaInfo().hasNodeMetaInfo("Qt/Item"));
+ QCOMPARE(view->rootModelNode().metaInfo().typeName(), QString("Qt/Item"));
+
+ QVERIFY(view->rootModelNode().metaInfo().hasProperty("states"));
+ QVERIFY(view->rootModelNode().metaInfo().property("states").isListProperty());
+ QVERIFY(view->rootModelNode().metaInfo().hasProperty("children"));
+ QVERIFY(view->rootModelNode().metaInfo().property("children").isListProperty());
+ QVERIFY(view->rootModelNode().metaInfo().hasProperty("data"));
+ QVERIFY(view->rootModelNode().metaInfo().property("data").isListProperty());
+ QVERIFY(view->rootModelNode().metaInfo().hasProperty("resources"));
+ QVERIFY(view->rootModelNode().metaInfo().property("resources").isListProperty());
+ QVERIFY(view->rootModelNode().metaInfo().hasProperty("transitions"));
+ QVERIFY(view->rootModelNode().metaInfo().property("transitions").isListProperty());
+ QVERIFY(view->rootModelNode().metaInfo().hasProperty("transform"));
+ QVERIFY(view->rootModelNode().metaInfo().property("transform").isListProperty());
+
+ QVERIFY(view->rootModelNode().metaInfo().hasProperty("effect"));
+ QVERIFY(!view->rootModelNode().metaInfo().property("effect").isListProperty());
+ QVERIFY(view->rootModelNode().metaInfo().hasProperty("parent"));
+ QVERIFY(!view->rootModelNode().metaInfo().property("parent").isListProperty());
+}
+
+void TestCore::subItemMetaInfo()
+{
+ QSKIP("no rewriter anymore", SkipAll);
+// QFile file(QCoreApplication::applicationDirPath() + "/../tests/data/fx/topitem.qml");
+// QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));
+//
+// QList<QmlError> errors;
+// QScopedPointer<ByteArrayModifier> modifier1(ByteArrayModifier::create(QString(file.readAll())));
+// QScopedPointer<Model> model(Model::create(modifier1.data(), QUrl::fromLocalFile(file.fileName()), &errors));
+// QVERIFY(errors.isEmpty());
+// QVERIFY(model.data());
+//
+// ModelNode firstChild = view->rootModelNode().childNodes().at(0);
+// QVERIFY(firstChild.isValid());
+// QCOMPARE(firstChild.type(), QString("SubItem"));
+// NodeMetaInfo firstMetaInfo = firstChild.metaInfo();
+// QVERIFY(firstMetaInfo.isValid());
+// QList<NodeMetaInfo> superClasses = firstMetaInfo.directSuperClasses();
+// QVERIFY(superClasses.contains(model->metaInfo().nodeMetaInfo("Qt/Rectangle", 4, 6, "data")));
+// QVERIFY(model->metaInfo().nodeMetaInfo("Qt/Rectangle", 4, 6, "data").property("x").isValid());
+// QVERIFY(firstMetaInfo.property("x").isValid());
+//
+//#ifdef CUSTOM_PROPERTIES_SHOW_UP_IN_THE_DOM
+// QVERIFY(firstMetaInfo.property("text").isValid());
+// QCOMPARE(firstMetaInfo.property("text").variantTypeId(), QVariant::String);
+//#endif // CUSTOM_PROPERTIES_SHOW_UP_IN_THE_DOM
+}
+
+void TestCore::testStatesRewriter()
+{
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText("import Qt 4.6; Item {}\n");
+ PlainTextEditModifier modifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ TestRewriterView *testRewriterView = new TestRewriterView(model.data());
+ testRewriterView->setTextModifier(&modifier);
+ model->attachView(testRewriterView);
+
+ QVERIFY(testRewriterView->errors().isEmpty());
+
+ ModelNode rootModelNode(view->rootModelNode());
+
+ QVERIFY(rootModelNode.isValid());
+
+ QVERIFY(QmlItemNode(rootModelNode).isValid());
+
+ QVERIFY(QmlItemNode(rootModelNode).states().allStates().isEmpty());
+
+ QmlModelState state1 = QmlItemNode(rootModelNode).states().addState("state 1");
+ QVERIFY(state1.isValid());
+ QVERIFY(!QmlItemNode(rootModelNode).states().allStates().isEmpty());
+ QCOMPARE(QmlItemNode(rootModelNode).states().allStates().count(), 1);
+
+ QmlModelState state2 = QmlItemNode(rootModelNode).states().addState("state 2");
+ QVERIFY(state2.isValid());
+
+ QCOMPARE(QmlItemNode(rootModelNode).states().allStates().count(), 2);
+
+ QmlItemNode(rootModelNode).states().removeState("state 1");
+ QVERIFY(!state1.isValid());
+
+ QmlItemNode(rootModelNode).states().removeState("state 2");
+ QVERIFY(!state2.isValid());
+
+ QVERIFY(QmlItemNode(rootModelNode).states().allStates().isEmpty());
+
+}
+
+
+void TestCore::testGradientsRewriter()
+{
+// QSKIP("this crashes in the rewriter", SkipAll);
+
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText("\nimport Qt 4.6\n\nItem {\n}\n");
+ PlainTextEditModifier modifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ TestRewriterView *testRewriterView = new TestRewriterView(model.data());
+ testRewriterView->setTextModifier(&modifier);
+ model->attachView(testRewriterView);
+
+ QVERIFY(testRewriterView->errors().isEmpty());
+
+ ModelNode rootModelNode(view->rootModelNode());
+
+ QVERIFY(rootModelNode.isValid());
+
+ ModelNode rectNode(rootModelNode.addChildNode("Qt/Rectangle", 4, 6, "data"));
+
+ const QLatin1String expected1("\nimport Qt 4.6\n"
+ "\n"
+ "Item {\n"
+ " Rectangle {\n"
+ " }\n"
+ "}\n");
+ QCOMPARE(textEdit.toPlainText(), expected1);
+
+ ModelNode gradientNode(rectNode.addChildNode("Qt/Gradient", 4, 6, "gradient"));
+
+ QVERIFY(rectNode.hasNodeProperty("gradient"));
+
+ const QLatin1String expected2("\nimport Qt 4.6\n"
+ "\n"
+ "Item {\n"
+ " Rectangle {\n"
+ " gradient: Gradient {\n"
+ " }\n"
+ " }\n"
+ "}\n");
+ QCOMPARE(textEdit.toPlainText(), expected2);
+
+ NodeListProperty stops(gradientNode.nodeListProperty("stops"));
+
+ QList<QPair<QString, QVariant> > propertyList;
+
+ propertyList.append(qMakePair(QString("position"), QVariant::fromValue(0)));
+ propertyList.append(qMakePair(QString("color"), QVariant::fromValue(QColor(Qt::red))));
+
+ ModelNode gradientStop1(gradientNode.view()->createModelNode("Qt/GradientStop", 4, 6, propertyList));
+ QVERIFY(gradientStop1.isValid());
+ stops.reparentHere(gradientStop1);
+
+ const QLatin1String expected3("\nimport Qt 4.6\n"
+ "\n"
+ "Item {\n"
+ " Rectangle {\n"
+ " gradient: Gradient {\n"
+ " GradientStop {\n"
+ " position: 0\n"
+ " color: \"#ff0000\"\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ "}\n");
+
+ QCOMPARE(textEdit.toPlainText(), expected3);
+
+ propertyList.clear();
+ propertyList.append(qMakePair(QString("position"), QVariant::fromValue(0.5)));
+ propertyList.append(qMakePair(QString("color"), QVariant::fromValue(QColor(Qt::blue))));
+
+ ModelNode gradientStop2(gradientNode.view()->createModelNode("Qt/GradientStop", 4, 6, propertyList));
+ QVERIFY(gradientStop2.isValid());
+ stops.reparentHere(gradientStop2);
+
+ const QLatin1String expected4("\nimport Qt 4.6\n"
+ "\n"
+ "Item {\n"
+ " Rectangle {\n"
+ " gradient: Gradient {\n"
+ " GradientStop {\n"
+ " position: 0\n"
+ " color: \"#ff0000\"\n"
+ " }\n"
+ "\n"
+ " GradientStop {\n"
+ " position: 0.5\n"
+ " color: \"#0000ff\"\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ "}\n");
+
+ QCOMPARE(textEdit.toPlainText(), expected4);
+
+ propertyList.clear();
+ propertyList.append(qMakePair(QString("position"), QVariant::fromValue(0.8)));
+ propertyList.append(qMakePair(QString("color"), QVariant::fromValue(QColor(Qt::yellow))));
+
+ ModelNode gradientStop3(gradientNode.view()->createModelNode("Qt/GradientStop", 4, 6, propertyList));
+ QVERIFY(gradientStop3.isValid());
+ stops.reparentHere(gradientStop3);
+
+ const QLatin1String expected5("\nimport Qt 4.6\n"
+ "\n"
+ "Item {\n"
+ " Rectangle {\n"
+ " gradient: Gradient {\n"
+ " GradientStop {\n"
+ " position: 0\n"
+ " color: \"#ff0000\"\n"
+ " }\n"
+ "\n"
+ " GradientStop {\n"
+ " position: 0.5\n"
+ " color: \"#0000ff\"\n"
+ " }\n"
+ "\n"
+ " GradientStop {\n"
+ " position: 0.8\n"
+ " color: \"#ffff00\"\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ "}\n");
+
+ QCOMPARE(textEdit.toPlainText(), expected5);
+
+ gradientNode.removeProperty("stops");
+
+ const QLatin1String expected6("\nimport Qt 4.6\n"
+ "\n"
+ "Item {\n"
+ " Rectangle {\n"
+ " gradient: Gradient {\n"
+ " }\n"
+ " }\n"
+ "}\n");
+
+ QCOMPARE(textEdit.toPlainText(), expected6);
+
+ QVERIFY(!gradientNode.hasProperty(QLatin1String("stops")));
+
+ propertyList.clear();
+ propertyList.append(qMakePair(QString("position"), QVariant::fromValue(0)));
+ propertyList.append(qMakePair(QString("color"), QVariant::fromValue(QColor(Qt::blue))));
+
+ gradientStop1 = gradientNode.view()->createModelNode("Qt/GradientStop", 4, 6, propertyList);
+ QVERIFY(gradientStop1.isValid());
+
+ stops.reparentHere(gradientStop1);
+}
+
+void TestCore::testQmlModelStates()
+{
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+
+
+ ModelNode rootModelNode(view->rootModelNode());
+
+ QVERIFY(rootModelNode.isValid());
+
+ QVERIFY(QmlItemNode(rootModelNode).isValid());
+
+ QVERIFY(QmlItemNode(rootModelNode).states().allStates().isEmpty());
+
+ QmlModelState newState = QmlItemNode(rootModelNode).states().addState("testState");
+ QVERIFY(newState.isValid());
+ QVERIFY(!QmlItemNode(rootModelNode).states().allStates().isEmpty());
+ QCOMPARE(QmlItemNode(rootModelNode).states().allStates().count(), 1);
+
+ QCOMPARE(newState.name(), QString("testState"));
+ QCOMPARE(newState, QmlItemNode(rootModelNode).states().state("testState"));
+
+ QmlItemNode(rootModelNode).states().removeState("testState");
+ QVERIFY(!newState.isValid());
+ QVERIFY(QmlItemNode(rootModelNode).states().allStates().isEmpty());
+
+}
+
+void TestCore::testInstancesStates()
+{
+//
+// import Qt 4.6
+//
+// Rectangle {
+// Text {
+// id: targetObject
+// text: "base state"
+// }
+//
+// states: [
+// State {
+// name: "state1"
+// PropertyChanges {
+// target: targetObj
+// x: 10
+// text: "state1"
+// }
+// }
+// State {
+// name: "state2"
+// PropertyChanges {
+// target: targetObj
+// text: "state2"
+// }
+// }
+// ]
+// }
+//
+
+ QScopedPointer<Model> model(Model::create("Qt/Rectangle", 4, 6));
+ QVERIFY(model.data());
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ //
+ // build up model
+ //
+ ModelNode rootNode = view->rootModelNode();
+
+ ModelNode textNode = view->createModelNode("Qt/Text", 4, 6);
+ textNode.setId("targetObject");
+ textNode.variantProperty("text").setValue("base state");
+
+ rootNode.nodeListProperty("data").reparentHere(textNode);
+
+ ModelNode propertyChanges1Node = view->createModelNode("Qt/PropertyChanges", 4, 6);
+ propertyChanges1Node.bindingProperty("target").setExpression("targetObject");
+ propertyChanges1Node.variantProperty("x").setValue(10);
+ propertyChanges1Node.variantProperty("text").setValue("state1");
+
+ ModelNode state1Node = view->createModelNode("Qt/State", 4, 6);
+ state1Node.variantProperty("name").setValue("state1");
+ state1Node.nodeListProperty("changes").reparentHere(propertyChanges1Node);
+
+ rootNode.nodeListProperty("states").reparentHere(state1Node);
+
+ ModelNode propertyChanges2Node = view->createModelNode("Qt/PropertyChanges", 4, 6);
+ propertyChanges2Node.bindingProperty("target").setExpression("targetObject");
+ propertyChanges2Node.variantProperty("text").setValue("state2");
+
+ ModelNode state2Node = view->createModelNode("Qt/State", 4, 6);
+ state2Node.variantProperty("name").setValue("state2");
+ state2Node.nodeListProperty("changes").reparentHere(propertyChanges2Node);
+
+ rootNode.nodeListProperty("states").reparentHere(state2Node);
+
+ //
+ // load into instance view
+ //
+ QScopedPointer<NodeInstanceView> instanceView(new NodeInstanceView);
+
+ model->attachView(instanceView.data());
+
+ //
+ // check that list of actions is not empty (otherwise the CustomParser has not been run properly)
+ //
+ NodeInstance state1Instance = instanceView->instanceForNode(state1Node);
+ QVERIFY(state1Instance.isValid());
+ QmlState *state1 = const_cast<QmlState*>(qobject_cast<const QmlState*>(state1Instance.testHandle()));
+ QVERIFY(state1);
+ QCOMPARE(state1->changes()->count(), 1);
+ QCOMPARE(state1->changes()->at(0)->actions().size(), 2);
+
+ NodeInstance state2Instance = instanceView->instanceForNode(state2Node);
+ QVERIFY(state2Instance.isValid());
+ QmlState *state2 = const_cast<QmlState*>(qobject_cast<const QmlState*>(state1Instance.testHandle()));
+ QVERIFY(state2);
+ QCOMPARE(state2->changes()->count(), 1);
+ QCOMPARE(state2->changes()->at(0)->actions().size(), 2);
+
+ NodeInstance textInstance = instanceView->instanceForNode(textNode);
+
+ //
+ // State switching
+ //
+
+ // base state
+ QVERIFY(textInstance.isValid());
+ QCOMPARE(state1Instance.property("__activateState").toBool(), false);
+ QCOMPARE(state2Instance.property("__activateState").toBool(), false);
+ QCOMPARE(textInstance.property("x").toInt(), 0);
+ QCOMPARE(textInstance.property("text").toString(), QString("base state"));
+
+ // base state -> state 1
+ state1Instance.setPropertyVariant("__activateState", true);
+ QCOMPARE(state1Instance.property("__activateState").toBool(), true);
+ QCOMPARE(state2Instance.property("__activateState").toBool(), false);
+ QCOMPARE(textInstance.property("x").toInt(), 10);
+ QCOMPARE(textInstance.property("text").toString(), QString("state1"));
+
+ // state 1 -> state 2
+ state2Instance.setPropertyVariant("__activateState", true);
+ QCOMPARE(state1Instance.property("__activateState").toBool(), false);
+ QCOMPARE(state2Instance.property("__activateState").toBool(), true);
+ QCOMPARE(textInstance.property("x").toInt(), 0);
+ QCOMPARE(textInstance.property("text").toString(), QString("state2"));
+
+ // state 1 -> base state
+ state2Instance.setPropertyVariant("__activateState", false);
+ QCOMPARE(state1Instance.property("__activateState").toBool(), false);
+ QCOMPARE(state2Instance.property("__activateState").toBool(), false);
+ QCOMPARE(textInstance.property("x").toInt(), 0);
+ QCOMPARE(textInstance.property("text").toString(), QString("base state"));
+
+ //
+ // Add/Change/Remove properties in current state
+ //
+ state1Instance.setPropertyVariant("__activateState", true);
+
+ propertyChanges1Node.variantProperty("x").setValue(20);
+ QCOMPARE(textInstance.property("x").toInt(), 20);
+ propertyChanges1Node.variantProperty("x").setValue(10); // undo
+ QCOMPARE(textInstance.property("x").toInt(), 10);
+
+ QCOMPARE(textInstance.property("y").toInt(), 0);
+ propertyChanges1Node.variantProperty("y").setValue(50);
+ QCOMPARE(textInstance.property("y").toInt(), 50);
+ propertyChanges1Node.removeProperty("y");
+ QCOMPARE(textInstance.property("y").toInt(), 0);
+
+ QCOMPARE(textInstance.property("text").toString(), QString("state1"));
+ propertyChanges1Node.removeProperty("text");
+ QCOMPARE(textInstance.property("text").toString(), QString("base state"));
+ propertyChanges1Node.variantProperty("text").setValue("state1"); // undo
+ QCOMPARE(textInstance.property("text").toString(), QString("state1"));
+
+//// Following is not supported. We work around this
+//// by _always_ changing to the base state before doing any changes to the
+//// state structure.
+
+ //
+ // Reparenting state actions (while state is active)
+ //
+
+// state1Instance.setPropertyVariant("__activateState", true);
+// // move property changes of current state out of state
+// ModelNode state3Node = view->createModelNode("Qt/State", 4, 6);
+// state3Node.nodeListProperty("changes").reparentHere(propertyChanges1Node);
+//
+// QCOMPARE(state1->changes()->count(), 0);
+// QCOMPARE(textInstance.property("text").toString(), QString("base state"));
+//
+// // undo
+// state1Node.nodeListProperty("changes").reparentHere(propertyChanges1Node);
+// QCOMPARE(state1->changes()->count(), 1);
+// QCOMPARE(textInstance.property("text").toString(), QString("state 1"));
+
+ //
+ // Removing state actions (while state is active)
+ //
+
+// state1Instance.setPropertyVariant("__activateState", true);
+// QCOMPARE(textInstance.property("text").toString(), QString("state1"));
+// propertyChanges1Node.destroy();
+// QCOMPARE(state1->changes()->count(), 0);
+// QCOMPARE(textInstance.property("text").toString(), QString("base state"));
+
+ //
+ // Removing state (while active)
+ //
+
+// state2Instance.setPropertyVariant("__activateState", true);
+// QCOMPARE(textInstance.property("text").toString(), QString("state2"));
+// state2Node.destroy();
+// QCOMPARE(textInstance.property("text").toString(), QString("base state"));
+}
+
+void TestCore::testStates()
+{
+//
+// import Qt 4.6
+//
+// Rectangle {
+// Text {
+// id: targetObject
+// text: "base state"
+// }
+// states: [
+// State {
+// name: "state 1"
+// PropertyChanges {
+// target: targetObj
+// text: "state 1"
+// }
+// }
+// ]
+// }
+//
+
+ QScopedPointer<Model> model(Model::create("Qt/Rectangle", 4, 6));
+ QVERIFY(model.data());
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ // build up model
+ ModelNode rootNode = view->rootModelNode();
+
+ ModelNode textNode = view->createModelNode("Qt/Text", 4, 6);
+ textNode.setId("targetObject");
+ textNode.variantProperty("text").setValue("base state");
+
+ rootNode.nodeListProperty("data").reparentHere(textNode);
+
+ QVERIFY(rootNode.isValid());
+ QVERIFY(textNode.isValid());
+
+ QmlItemNode rootItem(rootNode);
+ QmlItemNode textItem(textNode);
+
+ QVERIFY(rootItem.isValid());
+ QVERIFY(textItem.isValid());
+
+ QmlModelState state1(rootItem.states().addState("state 1")); //add state "state 1"
+ QCOMPARE(state1.modelNode().type(), QString("Qt/State"));
+
+ QVERIFY(view->currentState().isBaseState());
+
+ NodeInstance textInstance = view->nodeInstanceView()->instanceForNode(textNode);
+ QVERIFY(textInstance.isValid());
+
+ NodeInstance state1Instance = view->nodeInstanceView()->instanceForNode(state1);
+ QVERIFY(state1Instance.isValid());
+ QCOMPARE(state1Instance.property("__activateState").toBool(), false);
+ QCOMPARE(state1Instance.property("name").toString(), QString("state 1"));
+
+ view->setCurrentState(state1); //set currentState "state 1"
+
+ QCOMPARE(view->currentState(), state1);
+
+ QCOMPARE(state1Instance.property("__activateState").toBool(), true);
+
+ QVERIFY(!textItem.propertyAffectedByCurrentState("text"));
+
+ textItem.setVariantProperty("text", QVariant("state 1")); //set text in state !
+
+ QmlState *qmlState1 = const_cast<QmlState*>(qobject_cast<const QmlState*>(state1Instance.testHandle()));
+ QVERIFY(qmlState1);
+ QCOMPARE(qmlState1->changes()->count(), 1);
+ QCOMPARE(qmlState1->changes()->at(0)->actions().size(), 1);
+
+ QmlPropertyChanges changes(state1.propertyChanges(textNode));
+ QVERIFY(changes.modelNode().hasProperty("text"));
+ QCOMPARE(changes.modelNode().variantProperty("text").value(), QVariant("state 1"));
+ QCOMPARE(changes.modelNode().bindingProperty("target").expression(), QString("targetObject"));
+ QCOMPARE(changes.target(), textNode);
+ QCOMPARE(changes.modelNode().type(), QString("Qt/PropertyChanges"));
+
+ QCOMPARE(changes.modelNode().parentProperty().name(), QString("changes"));
+ QCOMPARE(changes.modelNode().parentProperty().parentModelNode(), state1.modelNode());
+
+ QCOMPARE(state1Instance.property("__activateState").toBool(), true);
+
+ QVERIFY(textItem.propertyAffectedByCurrentState("text"));
+
+ QCOMPARE(textInstance.property("text").toString(), QString("state 1"));
+ QCOMPARE(textItem.instanceValue("text"), QVariant("state 1"));
+
+ QVERIFY(textNode.hasProperty("text"));
+ QCOMPARE(textNode.variantProperty("text").value(), QVariant("base state"));
+}
+
+void TestCore::testStatesBaseState()
+{
+//
+// import Qt 4.6
+//
+// Rectangle {
+// Text {
+// id: targetObject
+// text: "base state"
+// }
+// states: [
+// State {
+// name: "state 1"
+// PropertyChanges {
+// target: targetObj
+// text: "state 1"
+// }
+// }
+// ]
+// }
+//
+
+ QScopedPointer<Model> model(Model::create("Qt/Rectangle", 4, 6));
+ QVERIFY(model.data());
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ // build up model
+ ModelNode rootNode = view->rootModelNode();
+
+ ModelNode textNode = view->createModelNode("Qt/Text", 4, 6);
+ textNode.setId("targetObject");
+ textNode.variantProperty("text").setValue("base state");
+
+ rootNode.nodeListProperty("data").reparentHere(textNode);
+
+ QVERIFY(rootNode.isValid());
+ QVERIFY(textNode.isValid());
+
+ QmlItemNode rootItem(rootNode);
+ QmlItemNode textItem(textNode);
+
+ QVERIFY(rootItem.isValid());
+ QVERIFY(textItem.isValid());
+
+ QmlModelState state1(rootItem.states().addState("state 1")); //add state "state 1"
+ QCOMPARE(state1.modelNode().type(), QString("Qt/State"));
+
+ QVERIFY(view->currentState().isBaseState());
+
+ view->setCurrentState(state1); //set currentState "state 1"
+ QCOMPARE(view->currentState(), state1);
+ textItem.setVariantProperty("text", QVariant("state 1")); //set text in state !
+ QVERIFY(textItem.propertyAffectedByCurrentState("text"));
+ QCOMPARE(textItem.instanceValue("text"), QVariant("state 1"));
+
+ view->setCurrentState(view->baseState()); //set currentState base state
+ QVERIFY(view->currentState().isBaseState());
+
+ textNode.variantProperty("text").setValue("base state changed");
+
+ view->setCurrentState(state1); //set currentState "state 1"
+ QCOMPARE(view->currentState(), state1);
+ QCOMPARE(textItem.instanceValue("text"), QVariant("state 1"));
+
+ view->setCurrentState(view->baseState()); //set currentState base state
+ QVERIFY(view->currentState().isBaseState());
+
+ QCOMPARE(textItem.instanceValue("text"), QVariant("base state changed"));
+}
+
+
+void TestCore::testInstancesIdResolution()
+{
+ QScopedPointer<Model> model(Model::create("Qt/Rectangle", 4, 6));
+ QVERIFY(model.data());
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ // import Qt 4.6
+ //
+ // Rectangle {
+ // id: root
+ // width: 100
+ // height: 100
+ // Rectangle {
+ // id: item1
+ // width: root.width
+ // height: item2.height
+ // }
+ // }
+
+ ModelNode rootNode = view->rootModelNode();
+ rootNode.setId("root");
+ rootNode.variantProperty("width").setValue(100);
+ rootNode.variantProperty("height").setValue(100);
+
+ ModelNode item1Node = view->createModelNode("Qt/Rectangle", 4, 6);
+ item1Node.setId("item1");
+ item1Node.bindingProperty("width").setExpression("root.width");
+ item1Node.bindingProperty("height").setExpression("item2.height");
+
+ rootNode.nodeListProperty("data").reparentHere(item1Node);
+
+ NodeInstance item1Instance = view->instanceForModelNode(item1Node);
+ QVERIFY(item1Instance.isValid());
+
+ QCOMPARE(item1Instance.property("width").toInt(), 100);
+ QCOMPARE(item1Instance.property("height").toInt(), 0); // item2 is still unknown
+
+ // Add item2:
+ // Rectangle {
+ // id: item2
+ // width: root.width / 2
+ // height: root.height
+ // }
+
+ ModelNode item2Node = view->createModelNode("Qt/Rectangle", 4, 6);
+ item2Node.setId("item2");
+ item2Node.bindingProperty("width").setExpression("root.width / 2");
+ item2Node.bindingProperty("height").setExpression("root.height");
+
+ rootNode.nodeListProperty("data").reparentHere(item2Node);
+
+ NodeInstance item2Instance = view->instanceForModelNode(item2Node);
+ QVERIFY(item2Instance.isValid());
+
+ QCOMPARE(item2Instance.property("width").toInt(), 50);
+ QCOMPARE(item2Instance.property("height").toInt(), 100);
+ QCOMPARE(item1Instance.property("height").toInt(), 100);
+
+ // Remove item2 again
+ item2Node.destroy();
+ QVERIFY(!item2Instance.isValid());
+ QVERIFY(!item2Instance.testHandle());
+
+ // Add item3:
+ // Rectangle {
+ // id: item3
+ // height: 80
+ // }
+
+ ModelNode item3Node = view->createModelNode("Qt/Rectangle", 4, 6);
+ item3Node.setId("item3");
+ item3Node.variantProperty("height").setValue(80);
+ rootNode.nodeListProperty("data").reparentHere(item3Node);
+
+ // Change item1.height: item3.height
+
+ item1Node.bindingProperty("height").setExpression("item3.height");
+ QCOMPARE(item1Instance.property("height").toInt(), 80);
+}
+
+
+void TestCore::testInstancesNotInScene()
+{
+ //
+ // test whether deleting an instance which is not in the scene crashes
+ //
+
+ QScopedPointer<Model> model(Model::create("Qt/Rectangle", 4, 6));
+ QVERIFY(model.data());
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ ModelNode node1 = view->createModelNode("Qt/Item", 4, 6);
+ node1.setId("node1");
+
+ ModelNode node2 = view->createModelNode("Qt/Item", 4, 6);
+ node2.setId("node2");
+
+ node1.nodeListProperty("children").reparentHere(node2);
+
+ node1.destroy();
+}
+
+void TestCore::testQmlModelStatesInvalidForRemovedNodes()
+{
+ QScopedPointer<Model> model(Model::create("Qt/Rectangle", 4, 6));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ ModelNode rootModelNode(view->rootModelNode());
+ QVERIFY(rootModelNode.isValid());
+ QVERIFY(QmlItemNode(rootModelNode).isValid());
+
+ rootModelNode.setId("rootModelNode");
+
+ QmlModelState state1 = QmlItemNode(rootModelNode).states().addState("state1");
+ QVERIFY(state1.isValid());
+ QCOMPARE(state1.name(), QString("state1"));
+
+ ModelNode childNode = rootModelNode.addChildNode("Qt/Rectangle", 4, 6, "data");
+ QVERIFY(childNode.isValid());
+ childNode.setId("childNode");
+
+ ModelNode subChildNode = childNode.addChildNode("Qt/Rectangle", 4, 6, "data");
+ QVERIFY(subChildNode.isValid());
+ subChildNode.setId("subChildNode");
+
+ QVERIFY(!state1.hasPropertyChanges(subChildNode));
+ QmlPropertyChanges changeSet = state1.propertyChanges(subChildNode);
+ QVERIFY(changeSet.isValid());
+
+ QmlItemNode(childNode).destroy();
+ QVERIFY(!childNode.isValid());
+ QVERIFY(!subChildNode.isValid());
+ QVERIFY(!changeSet.isValid());
+}
+
+void TestCore::testInstancesAttachToExistingModel()
+{
+ //
+ // Test attaching nodeinstanceview to an existing model
+ //
+
+ QScopedPointer<Model> model(Model::create("Qt/Item", 4, 6));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ ModelNode rootNode = view->rootModelNode();
+ ModelNode rectangleNode = rootNode.addChildNode("Qt/Rectangle", 4, 6, "data");
+
+ rectangleNode.variantProperty("width").setValue(100);
+
+ QVERIFY(rectangleNode.isValid());
+ QVERIFY(rectangleNode.hasProperty("width"));
+
+ // Attach NodeInstanceView
+
+ QScopedPointer<NodeInstanceView> instanceView(new NodeInstanceView);
+ QVERIFY(instanceView.data());
+ model->attachView(instanceView.data());
+
+ NodeInstance rootInstance = instanceView->instanceForNode(rootNode);
+ NodeInstance rectangleInstance = instanceView->instanceForNode(rectangleNode);
+ QVERIFY(rootInstance.isValid());
+ QVERIFY(rectangleInstance.isValid());
+ QCOMPARE(QVariant(100), rectangleInstance.property("width"));
+ QVERIFY(rootInstance.testHandle());
+ QVERIFY(rectangleInstance.testHandle());
+ QCOMPARE(rootInstance.testHandle(), rectangleInstance.testHandle()->parent());
+}
+
+void TestCore::testQmlModelAddMultipleStates()
+{
+ QScopedPointer<Model> model(Model::create("Qt/Rectangle", 4, 6));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ ModelNode rootModelNode(view->rootModelNode());
+ QVERIFY(rootModelNode.isValid());
+ QVERIFY(QmlItemNode(rootModelNode).isValid());
+
+ QmlModelState state1 = QmlItemNode(rootModelNode).states().addState("state1");
+ QVERIFY(state1.isValid());
+ QCOMPARE(state1.name(), QString("state1"));
+
+ QmlModelState state2 = QmlItemNode(rootModelNode).states().addState("state2");
+ QVERIFY(state2.isValid());
+ QCOMPARE(state1.name(), QString("state1"));
+ QCOMPARE(state2.name(), QString("state2"));
+
+ QmlModelState state3 = QmlItemNode(rootModelNode).states().addState("state3");
+ QVERIFY(state3.isValid());
+ QCOMPARE(state1.name(), QString("state1"));
+ QCOMPARE(state2.name(), QString("state2"));
+ QCOMPARE(state3.name(), QString("state3"));
+
+ QCOMPARE(QmlItemNode(rootModelNode).states().allStates().count(), 3);
+}
+
+void TestCore::testQmlModelRemoveStates()
+{
+ QScopedPointer<Model> model(Model::create("Qt/Rectangle", 4, 6));
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ ModelNode rootModelNode(view->rootModelNode());
+ QVERIFY(rootModelNode.isValid());
+ QVERIFY(QmlItemNode(rootModelNode).isValid());
+
+ QmlModelState state1 = QmlItemNode(rootModelNode).states().addState("state1");
+ QmlModelState state2 = QmlItemNode(rootModelNode).states().addState("state2");
+ QmlModelState state3 = QmlItemNode(rootModelNode).states().addState("state3");
+
+ QCOMPARE(QmlItemNode(rootModelNode).states().allStates().count(), 3);
+
+ QmlItemNode(rootModelNode).states().removeState("state2");
+ QVERIFY(!state2.isValid());
+ QCOMPARE(QmlItemNode(rootModelNode).states().allStates().count(), 2);
+
+ QmlItemNode(rootModelNode).states().removeState("state3");
+ QVERIFY(!state3.isValid());
+ state1.modelNode().destroy();
+ QVERIFY(!state1.isValid());
+ QCOMPARE(QmlItemNode(rootModelNode).states().allStates().count(), 0);
+}
+
+void TestCore::testQmlModelStateWithName()
+{
+ QPlainTextEdit textEdit1;
+ textEdit1.setPlainText("import Qt 4.6; Rectangle { id: theRect; width: 100; states: [ State { name: \"a\"; PropertyChanges { target: theRect; width: 200; } } ] }\n");
+ PlainTextEditModifier modifier1(&textEdit1);
+
+ QScopedPointer<Model> model1(Model::create("Qt/Item"));
+
+ TestRewriterView *testRewriterView1 = new TestRewriterView(model1.data());
+ testRewriterView1->setTextModifier(&modifier1);
+ model1->attachView(testRewriterView1);
+
+ QVERIFY(testRewriterView1->errors().isEmpty());
+
+ TestView *view = new TestView(model1.data());
+ model1->attachView(view);
+ QmlItemNode rootNode = view->rootModelNode();
+ QCOMPARE(rootNode.states().allStates().size(), 1);
+
+ QmlModelState modelState = rootNode.states().allStates().at(0);
+ QVERIFY(!modelState.isBaseState());
+ QCOMPARE(rootNode.instanceValue("width").toInt(), 100);
+
+ QVERIFY(rootNode.isInBaseState());
+ QVERIFY(rootNode.propertyAffectedByCurrentState("width"));
+ view->setCurrentState(rootNode.states().allStates().at(0));
+ rootNode.setVariantProperty("width", 112);
+
+ const QLatin1String expected1("import Qt 4.6; Rectangle { id: theRect; width: 100; states: [ State { name: \"a\"; PropertyChanges { target: theRect; width: 112 } } ] }\n");
+ QCOMPARE(textEdit1.toPlainText(), expected1);
+
+ QVERIFY(!rootNode.isInBaseState());
+ QCOMPARE(rootNode.instanceValue("width").toInt(), 112);
+
+ view->setCurrentState(view->baseState());
+ QCOMPARE(rootNode.instanceValue("width").toInt(), 100);
+
+ view->setCurrentState(rootNode.states().allStates().at(0));
+ QCOMPARE(rootNode.instanceValue("width").toInt(), 112);
+
+
+ modelState.destroy();
+ QCOMPARE(rootNode.states().allStates().size(), 0);
+}
+
+void TestCore::testRewriterAutomaticSemicolonAfterChangedProperty()
+{
+ QPlainTextEdit textEdit1;
+ textEdit1.setPlainText("import Qt 4.6; Rectangle {\n width: 640\n height: 480\n}\n");
+ PlainTextEditModifier modifier1(&textEdit1);
+
+ QScopedPointer<Model> model1(Model::create("Qt/Item"));
+
+ TestRewriterView *testRewriterView1 = new TestRewriterView(model1.data());
+ testRewriterView1->setTextModifier(&modifier1);
+ model1->attachView(testRewriterView1);
+
+ QVERIFY(testRewriterView1->errors().isEmpty());
+
+ ModelNode rootModelNode = testRewriterView1->rootModelNode();
+ rootModelNode.variantProperty("height").setValue(1480);
+ QCOMPARE(rootModelNode.variantProperty("height").value().toInt(), 1480);
+
+ QVERIFY(testRewriterView1->errors().isEmpty());
+}
+
+void TestCore::attributeChangeSynchronizer()
+{
+ QSKIP("no rewriter anymore", SkipAll);
+// ByteArrayModifier* modifier;
+// Model* model = 0;
+// const QString originalQml = contentsTemplate.arg("text", "");
+// load(originalQml, model, modifier);
+// QVERIFY(model);
+// QCOMPARE(view->rootModelNode().childNodes().size(), 1);
+// ModelNode textChild = view->rootModelNode().childNodes().first();
+// QVERIFY(textChild.id() == "textChild");
+// QVERIFY(textChild.property("text").value() == "text");
+//
+// reload(contentsTemplate.arg("changed text", ""), modifier);
+//
+// QVERIFY2(textChild.property("text").value() == "changed text", QString("text was: \"%1\", expected \"changed text\"").arg(textChild.property("text").value().toString()).toLatin1().data());
+//
+// textChild = view->rootModelNode().childNodes().first();
+// QVERIFY(textChild.property("text").value() == "changed text");
+//
+// delete model;
+// delete modifier;
+}
+
+void TestCore::attributeAdditionSynchronizer()
+{
+ QSKIP("no rewriter anymore", SkipAll);
+// ByteArrayModifier* modifier;
+// Model* model = 0;
+// load(contentsTemplate.arg("text", ""), model, modifier);
+// QVERIFY(model);
+//
+// ModelNode textChild = view->rootModelNode().childNodes().first();
+// QVERIFY(textChild.id() == "textChild");
+// QVERIFY(textChild.property("text").value() == "text");
+// QVERIFY(!textChild.propertyNames().contains("width"));
+//
+// reload(contentsTemplate.arg("text", "width: 100;"), modifier);
+//
+// QVERIFY(textChild.property("text").value() == "text");
+// QVERIFY(textChild.property("width").value() == "100");
+//
+// delete model;
+// delete modifier;
+}
+
+void TestCore::attributeRemovalSynchronizer()
+{
+ QSKIP("no rewriter anymore", SkipAll);
+// ByteArrayModifier* modifier;
+// Model* model = 0;
+// load(contentsTemplate.arg("text", "width: 50;"), model, modifier);
+// QVERIFY(model);
+//
+// ModelNode textChild = view->rootModelNode().childNodes().first();
+// QVERIFY(textChild.id() == "textChild");
+// QVERIFY(textChild.property("text").value() == "text");
+// QVERIFY(textChild.property("width").value() == "50");
+//
+// reload(contentsTemplate.arg("text", ""), modifier);
+//
+// QVERIFY(textChild.property("text").value() == "text");
+// QVERIFY(!textChild.propertyNames().contains("width"));
+//
+// delete model;
+// delete modifier;
+}
+
+void TestCore::childAddedSynchronizer()
+{
+ QSKIP("no rewriter anymore", SkipAll);
+// ByteArrayModifier* modifier;
+// Model* model = 0;
+// load(bareTemplate.arg(""), model, modifier);
+// QVERIFY(model);
+// QVERIFY(view->rootModelNode().childNodes().isEmpty());
+//
+// reload(contentsTemplate.arg("text", ""), modifier);
+//
+// QVERIFY(view->rootModelNode().childNodes().size() == 1);
+// QVERIFY(view->rootModelNode().childNodes().first().id() == "textChild");
+//
+// delete model;
+// delete modifier;
+}
+
+void TestCore::childRemovedSynchronizer()
+{
+ QSKIP("no rewriter anymore", SkipAll);
+// ByteArrayModifier* modifier;
+// Model* model = 0;
+// load(contentsTemplate.arg("text", ""), model, modifier);
+// QVERIFY(model);
+// QVERIFY(view->rootModelNode().childNodes().size() == 1);
+// QVERIFY(view->rootModelNode().childNodes().first().id() == "textChild");
+//
+// reload(bareTemplate.arg(""), modifier);
+//
+// QVERIFY(view->rootModelNode().childNodes().isEmpty());
+//
+// delete model;
+// delete modifier;
+}
+
+void TestCore::childReplacedSynchronizer()
+{
+ QSKIP("no rewriter anymore", SkipAll);
+// ByteArrayModifier* modifier;
+// Model *model = 0;
+// load(contentsTemplate.arg("text", ""), model, modifier);
+// QVERIFY(model);
+// QVERIFY(view->rootModelNode().childNodes().size() == 1);
+// QVERIFY(view->rootModelNode().childNodes().first().id() == "textChild");
+//
+// reload(bareTemplate.arg("Item { id:\"someOtherItem\"; }"), modifier);
+//
+// QVERIFY(view->rootModelNode().childNodes().size() == 1);
+// QVERIFY(view->rootModelNode().childNodes().first().id() == "someOtherItem");
+//
+// delete model;
+// delete modifier;
+}
+
+void TestCore::defaultPropertyValues()
+{
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ QCOMPARE(view->rootModelNode().variantProperty("x").value().toDouble(), 0.0);
+ QCOMPARE(view->rootModelNode().variantProperty("width").value().toDouble(), 0.0);
+
+ ModelNode rectNode(view->rootModelNode().addChildNode("Qt/Rectangle", 4, 6, "data"));
+
+ QCOMPARE(rectNode.variantProperty("y").value().toDouble(), 0.0);
+ QCOMPARE(rectNode.variantProperty("width").value().toDouble(), 0.0);
+
+ ModelNode imageNode(view->rootModelNode().addChildNode("Qt/Image", 4, 6, "data"));
+
+ QCOMPARE(imageNode.variantProperty("y").value().toDouble(), 0.0);
+ QCOMPARE(imageNode.variantProperty("width").value().toDouble(), 0.0);
+}
+
+void TestCore::testModelPropertyValueTypes()
+{
+ QPlainTextEdit textEdit1;
+ textEdit1.setPlainText("import Qt 4.6; Rectangle { width: 100; radius: 1.5; color: \"red\"; }");
+ PlainTextEditModifier modifier1(&textEdit1);
+
+ QScopedPointer<Model> model1(Model::create("Qt/Item"));
+
+ QScopedPointer<TestRewriterView> testRewriterView1(new TestRewriterView());
+ testRewriterView1->setTextModifier(&modifier1);
+ model1->attachView(testRewriterView1.data());
+
+ QVERIFY(testRewriterView1->errors().isEmpty());
+
+ ModelNode rootModelNode(testRewriterView1->rootModelNode());
+ QVERIFY(rootModelNode.isValid());
+
+ QCOMPARE(rootModelNode.variantProperty("width").value().type(), QVariant::Double);
+ QCOMPARE(rootModelNode.variantProperty("radius").value().type(), QVariant::Double);
+ QCOMPARE(rootModelNode.variantProperty("color").value().type(), QVariant::Color);
+}
+
+void TestCore::testModelNodeInHierarchy()
+{
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ QVERIFY(view->rootModelNode().isInHierarchy());
+ ModelNode node1 = view->rootModelNode().addChildNode("Qt/Item", 4, 6, "data");
+ QVERIFY(node1.isInHierarchy());
+ ModelNode node2 = view->createModelNode("Qt/Item", 4, 6);
+ QVERIFY(!node2.isInHierarchy());
+ node2.nodeListProperty("data").reparentHere(node1);
+ QVERIFY(!node2.isInHierarchy());
+ view->rootModelNode().nodeListProperty("data").reparentHere(node2);
+ QVERIFY(node1.isInHierarchy());
+ QVERIFY(node2.isInHierarchy());
+}
+
+void TestCore::testModelDefaultProperties()
+{
+ QScopedPointer<Model> model(Model::create("Qt/Rectangle"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ ModelNode rootModelNode(view->rootModelNode());
+ QVERIFY(rootModelNode.isValid());
+
+ QCOMPARE(rootModelNode.metaInfo().defaultProperty(), QString("data"));
+}
+
+void TestCore::loadAnchors()
+{
+ QPlainTextEdit textEdit1;
+ textEdit1.setPlainText("import Qt 4.6; Item { width: 100; height: 100; Rectangle { anchors.left: parent.left; anchors.horizontalCenter: parent.horizontalCenter; anchors.rightMargin: 20; }}");
+ PlainTextEditModifier modifier1(&textEdit1);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+
+ QScopedPointer<TestRewriterView> testRewriterView1(new TestRewriterView());
+ testRewriterView1->setTextModifier(&modifier1);
+ model->attachView(testRewriterView1.data());
+
+ TestView *testView = new TestView(model.data());
+ model->attachView(testView);
+
+ QmlItemNode rootQmlItemNode(testView->rootQmlItemNode());
+ QmlItemNode anchoredNode(rootQmlItemNode.children().first());
+ QVERIFY(anchoredNode.isValid());
+
+ QmlAnchors anchors(anchoredNode.anchors());
+ QVERIFY(anchors.instanceHasAnchor(AnchorLine::Left));
+ QVERIFY(!anchors.instanceHasAnchor(AnchorLine::Top));
+ QVERIFY(!anchors.instanceHasAnchor(AnchorLine::Right));
+ QVERIFY(!anchors.instanceHasAnchor(AnchorLine::Bottom));
+ QVERIFY(anchors.instanceHasAnchor(AnchorLine::HorizontalCenter));
+ QVERIFY(!anchors.instanceHasAnchor(AnchorLine::VerticalCenter));
+
+ QCOMPARE(anchors.instanceMargin(AnchorLine::Right), 20.0);
+
+
+ QCOMPARE(anchoredNode.instancePosition().x(), 0.0);
+ QCOMPARE(anchoredNode.instancePosition().y(), 0.0);
+ QCOMPARE(anchoredNode.instanceBoundingRect().width(), 100.0);
+ QCOMPARE(anchoredNode.instanceBoundingRect().height(), 0.0);
+
+
+ model->detachView(testView);
+}
+
+void TestCore::changeAnchors()
+{
+ QPlainTextEdit textEdit1;
+ textEdit1.setPlainText("import Qt 4.6; Item { width: 100; height: 100; Rectangle { anchors.left: parent.left; anchors.horizontalCenter: parent.horizontalCenter; anchors.rightMargin: 20; }}");
+ PlainTextEditModifier modifier1(&textEdit1);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+
+ QScopedPointer<TestRewriterView> testRewriterView1(new TestRewriterView());
+ testRewriterView1->setTextModifier(&modifier1);
+ model->attachView(testRewriterView1.data());
+
+ TestView *testView = new TestView(model.data());
+ model->attachView(testView);
+
+ QmlItemNode rootQmlItemNode(testView->rootQmlItemNode());
+ QmlItemNode anchoredNode(rootQmlItemNode.children().first());
+ QVERIFY(anchoredNode.isValid());
+
+ QmlAnchors anchors(anchoredNode.anchors());
+ QVERIFY(anchors.instanceHasAnchor(AnchorLine::Left));
+ QVERIFY(!anchors.instanceHasAnchor(AnchorLine::Top));
+ QVERIFY(!anchors.instanceHasAnchor(AnchorLine::Right));
+ QVERIFY(!anchors.instanceHasAnchor(AnchorLine::Bottom));
+ QVERIFY(anchors.instanceHasAnchor(AnchorLine::HorizontalCenter));
+ QVERIFY(!anchors.instanceHasAnchor(AnchorLine::VerticalCenter));
+ QCOMPARE(anchors.instanceMargin(AnchorLine::Right), 20.0);
+
+
+ QCOMPARE(anchoredNode.instancePosition().x(), 0.0);
+ QCOMPARE(anchoredNode.instancePosition().y(), 0.0);
+ QCOMPARE(anchoredNode.instanceBoundingRect().width(), 100.0);
+ QCOMPARE(anchoredNode.instanceBoundingRect().height(), 0.0);
+
+
+ anchors.removeAnchor(AnchorLine::Top);
+
+ anchoredNode.setBindingProperty("anchors.bottom", "parent.bottom");
+ QVERIFY(anchors.instanceHasAnchor(AnchorLine::Bottom));
+ anchors.setAnchor(AnchorLine::Right, rootQmlItemNode, AnchorLine::Right);
+ QVERIFY(!anchors.instanceHasAnchor(AnchorLine::Right));
+ QCOMPARE(anchors.instanceAnchor(AnchorLine::Right).type(), AnchorLine::Invalid);
+ QVERIFY(!anchors.instanceAnchor(AnchorLine::Right).qmlItemNode().isValid());
+
+ anchors.setMargin(AnchorLine::Right, 10.0);
+ QCOMPARE(anchors.instanceMargin(AnchorLine::Right), 10.0);
+
+ anchors.setMargin(AnchorLine::Right, 0.0);
+ QCOMPARE(anchors.instanceMargin(AnchorLine::Right), 0.0);
+
+ anchors.setMargin(AnchorLine::Right, 20.0);
+ QCOMPARE(anchors.instanceMargin(AnchorLine::Right), 20.0);
+
+ QCOMPARE(anchoredNode.instancePosition().x(), 0.0);
+ QCOMPARE(anchoredNode.instancePosition().y(), 100.0);
+ QCOMPARE(anchoredNode.instanceBoundingRect().width(), 100.0);
+ QCOMPARE(anchoredNode.instanceBoundingRect().height(), 0.0);
+
+ model->detachView(testView);
+}
+
+void TestCore::anchorToSibling()
+{
+ QPlainTextEdit textEdit1;
+ textEdit1.setPlainText("import Qt 4.6; Item { Rectangle {} Rectangle { id: secondChild } }");
+ PlainTextEditModifier modifier1(&textEdit1);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+
+ QScopedPointer<TestRewriterView> testRewriterView1(new TestRewriterView());
+ testRewriterView1->setTextModifier(&modifier1);
+ model->attachView(testRewriterView1.data());
+
+ TestView *testView = new TestView(model.data());
+ model->attachView(testView);
+
+ QmlItemNode rootQmlItemNode(testView->rootQmlItemNode());
+ QmlItemNode anchoredNode(rootQmlItemNode.children().first());
+ QVERIFY(anchoredNode.isValid());
+
+ QmlAnchors anchors(anchoredNode.anchors());
+
+ QmlItemNode firstChild(rootQmlItemNode.children().first());
+ QVERIFY(firstChild.isValid());
+ QCOMPARE(firstChild.validId(), QString("rectangle1"));
+
+ QmlItemNode secondChild(rootQmlItemNode.children().at(1));
+ QVERIFY(secondChild.isValid());
+ QCOMPARE(secondChild.validId(), QString("secondChild"));
+
+ secondChild.anchors().setAnchor(AnchorLine::Top, firstChild, AnchorLine::Bottom);
+
+ QmlItemNode secondChildTopAnchoredNode = secondChild.anchors().instanceAnchor(AnchorLine::Top).qmlItemNode();
+ QVERIFY(secondChildTopAnchoredNode.isValid());
+ QVERIFY2(secondChildTopAnchoredNode == firstChild, QString("expected %1 got %2").arg(firstChild.id(), secondChildTopAnchoredNode.id()).toLatin1().data());
+
+ secondChild.anchors().setMargin(AnchorLine::Top, 10.0);
+ QCOMPARE(secondChild.anchors().instanceMargin(AnchorLine::Top), 10.0);
+
+ QVERIFY(firstChild.anchors().possibleAnchorLines(AnchorLine::Bottom, secondChild) == AnchorLine::Invalid);
+ QVERIFY(firstChild.anchors().possibleAnchorLines(AnchorLine::Left, secondChild) == AnchorLine::HorizontalMask);
+ QVERIFY(secondChild.anchors().possibleAnchorLines(AnchorLine::Top, firstChild) == AnchorLine::VerticalMask);
+ QVERIFY(secondChild.anchors().possibleAnchorLines(AnchorLine::Left, firstChild) == AnchorLine::HorizontalMask);
+}
+
+void TestCore::anchorsAndStates()
+{
+ QSKIP("no anchor support anymore", SkipAll);
+
+// QScopedPointer<Model> model(create("import Qt 4.6; Item { id:rootModelNode }"));
+// QVERIFY(model.data());
+//
+// ModelNode childNode(view->rootModelNode().addChildNode("Qt/Rectangle", 4, 6, "data"));
+// childNode.setId("childNode");
+// ModelState modelState(model->createModelState("anchoreteststate"));
+//
+// childNode.setId("childNode");
+// NodeState nodeState(modelState.nodeState(childNode));
+// NodeAnchors(nodeState).setAnchor(AnchorLine::Top, view->rootModelNode(), AnchorLine::Top);
+}
+
+void TestCore::removeFillAnchorByDetaching()
+{
+ QPlainTextEdit textEdit1;
+ textEdit1.setPlainText("import Qt 4.6; Item { width: 100; height: 100; Rectangle { id: child; anchors.fill: parent } }");
+ PlainTextEditModifier modifier1(&textEdit1);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+
+ QScopedPointer<TestRewriterView> testRewriterView1(new TestRewriterView());
+ testRewriterView1->setTextModifier(&modifier1);
+ model->attachView(testRewriterView1.data());
+
+ TestView *testView = new TestView(model.data());
+ model->attachView(testView);
+
+ QmlItemNode rootQmlItemNode(testView->rootQmlItemNode());
+
+ QmlItemNode firstChild(rootQmlItemNode.children().first());
+ QVERIFY(firstChild.isValid());
+ QCOMPARE(firstChild.id(), QString("child"));
+
+ // Verify the synthesized anchors:
+ QmlAnchors anchors(firstChild);
+ QVERIFY(anchors.instanceHasAnchor(AnchorLine::Left));
+ QVERIFY(anchors.instanceAnchor(AnchorLine::Left).isValid());
+ QCOMPARE(anchors.instanceAnchor(AnchorLine::Left).qmlItemNode(), rootQmlItemNode);
+ QCOMPARE(anchors.instanceAnchor(AnchorLine::Left).type(), AnchorLine::Left);
+
+ QVERIFY(anchors.instanceAnchor(AnchorLine::Top).isValid());
+ QCOMPARE(anchors.instanceAnchor(AnchorLine::Top).qmlItemNode(), rootQmlItemNode);
+ QCOMPARE(anchors.instanceAnchor(AnchorLine::Top).type(), AnchorLine::Top);
+
+ QVERIFY(anchors.instanceAnchor(AnchorLine::Right).isValid());
+ QCOMPARE(anchors.instanceAnchor(AnchorLine::Right).qmlItemNode(), rootQmlItemNode);
+ QCOMPARE(anchors.instanceAnchor(AnchorLine::Right).type(), AnchorLine::Right);
+
+ QVERIFY(anchors.instanceAnchor(AnchorLine::Bottom).isValid());
+ QCOMPARE(anchors.instanceAnchor(AnchorLine::Bottom).qmlItemNode(), rootQmlItemNode);
+ QCOMPARE(anchors.instanceAnchor(AnchorLine::Bottom).type(), AnchorLine::Bottom);
+
+ QVERIFY(!anchors.instanceAnchor(AnchorLine::HorizontalCenter).isValid());
+ QVERIFY(!anchors.instanceAnchor(AnchorLine::VerticalCenter).isValid());
+
+ QCOMPARE(firstChild.instancePosition().x(), 0.0);
+ QCOMPARE(firstChild.instancePosition().y(), 0.0);
+ QCOMPARE(firstChild.instanceBoundingRect().width(), 100.0);
+ QCOMPARE(firstChild.instanceBoundingRect().height(), 100.0);
+
+ // Remove 2 anchors:
+ RewriterTransaction transaction = testView->beginRewriterTransaction();
+ anchors.removeAnchor(AnchorLine::Bottom);
+ anchors.removeAnchor(AnchorLine::Top);
+ transaction.commit();
+
+ // Verify again:
+ QVERIFY(anchors.instanceAnchor(AnchorLine::Left).isValid());
+ QCOMPARE(anchors.instanceAnchor(AnchorLine::Left).qmlItemNode(), rootQmlItemNode);
+ QCOMPARE(anchors.instanceAnchor(AnchorLine::Left).type(), AnchorLine::Left);
+
+ QVERIFY(!anchors.instanceHasAnchor(AnchorLine::Top));
+ QVERIFY(!anchors.instanceAnchor(AnchorLine::Top).isValid());
+
+ QVERIFY(anchors.instanceAnchor(AnchorLine::Right).isValid());
+ QCOMPARE(anchors.instanceAnchor(AnchorLine::Right).qmlItemNode(), rootQmlItemNode);
+ QCOMPARE(anchors.instanceAnchor(AnchorLine::Right).type(), AnchorLine::Right);
+
+ QVERIFY(!anchors.instanceAnchor(AnchorLine::Bottom).isValid());
+
+ QVERIFY(!anchors.instanceAnchor(AnchorLine::HorizontalCenter).isValid());
+ QVERIFY(!anchors.instanceAnchor(AnchorLine::VerticalCenter).isValid());
+
+ QCOMPARE(firstChild.instancePosition().x(), 0.0);
+ QCOMPARE(firstChild.instancePosition().y(), 0.0);
+ QCOMPARE(firstChild.instanceBoundingRect().width(), 100.0);
+ QSKIP("is this intended", SkipAll);
+ QCOMPARE(firstChild.instanceBoundingRect().height(), 0.0);
+
+
+ model->detachView(testView);
+}
+
+void TestCore::removeFillAnchorByChanging()
+{
+ QPlainTextEdit textEdit1;
+ textEdit1.setPlainText("import Qt 4.6; Item { width: 100; height: 100; Rectangle { id: child; anchors.fill: parent } }");
+ PlainTextEditModifier modifier1(&textEdit1);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+
+ QScopedPointer<TestRewriterView> testRewriterView1(new TestRewriterView());
+ testRewriterView1->setTextModifier(&modifier1);
+ model->attachView(testRewriterView1.data());
+
+ TestView *testView = new TestView(model.data());
+ model->attachView(testView);
+
+ QmlItemNode rootQmlItemNode(testView->rootQmlItemNode());
+
+ QmlItemNode firstChild(rootQmlItemNode.children().first());
+ QVERIFY(firstChild.isValid());
+ QCOMPARE(firstChild.id(), QString("child"));
+
+ // Verify the synthesized anchors:
+ QmlAnchors anchors(firstChild);
+ QVERIFY(anchors.instanceAnchor(AnchorLine::Left).isValid());
+ QCOMPARE(anchors.instanceAnchor(AnchorLine::Left).qmlItemNode(), rootQmlItemNode);
+ QCOMPARE(anchors.instanceAnchor(AnchorLine::Left).type(), AnchorLine::Left);
+
+ QVERIFY(anchors.instanceAnchor(AnchorLine::Top).isValid());
+ QCOMPARE(anchors.instanceAnchor(AnchorLine::Top).qmlItemNode(), rootQmlItemNode);
+ QCOMPARE(anchors.instanceAnchor(AnchorLine::Top).type(), AnchorLine::Top);
+
+ QVERIFY(anchors.instanceAnchor(AnchorLine::Right).isValid());
+ QCOMPARE(anchors.instanceAnchor(AnchorLine::Right).qmlItemNode(), rootQmlItemNode);
+ QCOMPARE(anchors.instanceAnchor(AnchorLine::Right).type(), AnchorLine::Right);
+
+ QVERIFY(anchors.instanceAnchor(AnchorLine::Bottom).isValid());
+ QCOMPARE(anchors.instanceAnchor(AnchorLine::Bottom).qmlItemNode(), rootQmlItemNode);
+ QCOMPARE(anchors.instanceAnchor(AnchorLine::Bottom).type(), AnchorLine::Bottom);
+
+ QVERIFY(!anchors.instanceAnchor(AnchorLine::HorizontalCenter).isValid());
+ QVERIFY(!anchors.instanceAnchor(AnchorLine::VerticalCenter).isValid());
+
+ QCOMPARE(firstChild.instancePosition().x(), 0.0);
+ QCOMPARE(firstChild.instancePosition().y(), 0.0);
+ QCOMPARE(firstChild.instanceBoundingRect().width(), 100.0);
+ QCOMPARE(firstChild.instanceBoundingRect().height(), 100.0);
+
+ // Change 2 anchors:
+ anchors.setAnchor(AnchorLine::Bottom, rootQmlItemNode, AnchorLine::Top);
+ anchors.setAnchor(AnchorLine::Top, rootQmlItemNode, AnchorLine::Bottom);
+
+ // Verify again:
+ QVERIFY(anchors.instanceAnchor(AnchorLine::Left).isValid());
+ QCOMPARE(anchors.instanceAnchor(AnchorLine::Left).qmlItemNode(), rootQmlItemNode);
+ QCOMPARE(anchors.instanceAnchor(AnchorLine::Left).type(), AnchorLine::Left);
+
+ QVERIFY(anchors.instanceAnchor(AnchorLine::Top).isValid());
+ QCOMPARE(anchors.instanceAnchor(AnchorLine::Top).qmlItemNode(), rootQmlItemNode);
+ QCOMPARE(anchors.instanceAnchor(AnchorLine::Top).type(), AnchorLine::Bottom);
+
+ QVERIFY(anchors.instanceAnchor(AnchorLine::Right).isValid());
+ QCOMPARE(anchors.instanceAnchor(AnchorLine::Right).qmlItemNode(), rootQmlItemNode);
+ QCOMPARE(anchors.instanceAnchor(AnchorLine::Right).type(), AnchorLine::Right);
+
+ QVERIFY(anchors.instanceAnchor(AnchorLine::Bottom).isValid());
+ QCOMPARE(anchors.instanceAnchor(AnchorLine::Bottom).qmlItemNode(), rootQmlItemNode);
+ QCOMPARE(anchors.instanceAnchor(AnchorLine::Bottom).type(), AnchorLine::Top);
+
+ QVERIFY(!anchors.instanceAnchor(AnchorLine::HorizontalCenter).isValid());
+ QVERIFY(!anchors.instanceAnchor(AnchorLine::VerticalCenter).isValid());
+
+
+ QCOMPARE(firstChild.instancePosition().x(), 0.0);
+ QCOMPARE(firstChild.instancePosition().y(), 100.0);
+ QCOMPARE(firstChild.instanceBoundingRect().width(), 100.0);
+ QCOMPARE(firstChild.instanceBoundingRect().height(), -100.0);
+
+
+ model->detachView(testView);
+}
+
+void TestCore::testModelBindings()
+{
+ QScopedPointer<Model> model(Model::create("Qt/Item", 4, 6));
+ QVERIFY(model.data());
+
+ NodeInstanceView *nodeInstanceView = new NodeInstanceView(model.data());
+ model->attachView(nodeInstanceView);
+
+ ModelNode rootModelNode = nodeInstanceView->rootModelNode();
+ QCOMPARE(rootModelNode.allDirectSubModelNodes().count(), 0);
+ NodeInstance rootInstance = nodeInstanceView->instanceForNode(rootModelNode);
+
+ QCOMPARE(rootInstance.size().width(), 0.0);
+ QCOMPARE(rootInstance.size().height(), 0.0);
+
+ rootModelNode.variantProperty("width") = 200;
+ rootModelNode.variantProperty("height") = 100;
+
+ QCOMPARE(rootInstance.size().width(), 200.0);
+ QCOMPARE(rootInstance.size().height(), 100.0);
+
+ ModelNode childNode = rootModelNode.addChildNode("Qt/Rectangle", 4, 6, "data");
+
+ childNode.variantProperty("width") = 100;
+ childNode.variantProperty("height") = 100;
+
+ childNode.variantProperty("x") = 10;
+ childNode.variantProperty("y") = 10;
+
+ NodeInstance childInstance = nodeInstanceView->instanceForNode(childNode);
+
+ QCOMPARE(childInstance.size().width(), 100.0);
+ QCOMPARE(childInstance.size().height(), 100.0);
+
+ QCOMPARE(childInstance.position().x(), 10.0);
+ QCOMPARE(childInstance.position().y(), 10.0);
+
+ childNode.bindingProperty("width").setExpression("parent.width");
+
+ QCOMPARE(childInstance.size().width(), 200.0);
+
+ rootModelNode.setId("root");
+ QCOMPARE(rootModelNode.id(), QString("root"));
+ QCOMPARE(rootInstance.testHandle()->objectName(), QString("root"));
+
+ childNode.setId("child");
+ QCOMPARE(childNode.id(), QString("child"));
+ QCOMPARE(childInstance.testHandle()->objectName(), QString("child"));
+ childNode.variantProperty("width") = 100;
+
+ QCOMPARE(childInstance.size().width(), 100.0);
+
+ childNode.bindingProperty("width").setExpression("child.height");
+ QCOMPARE(childInstance.size().width(), 100.0);
+
+ childNode.bindingProperty("width").setExpression("root.width");
+ QCOMPARE(childInstance.size().width(), 200.0);
+}
+
+void TestCore::testDynamicProperties()
+{
+ QScopedPointer<Model> model(Model::create("Qt/Item", 4, 6));
+ QVERIFY(model.data());
+
+ TestView *testView = new TestView(model.data());
+ model->attachView(testView);
+
+ QmlItemNode rootQmlItemNode(testView->rootQmlItemNode());
+ ModelNode rootModelNode = rootQmlItemNode.modelNode();
+
+ rootModelNode.variantProperty("x") = 10;
+ rootModelNode.variantProperty("myDouble") = qMakePair(QString("real"), QVariant(10));
+ rootModelNode.variantProperty("myColor").setDynamicTypeNameAndValue("color", Qt::red);
+
+ QVERIFY(!rootModelNode.property("x").isDynamic());
+ QVERIFY(rootModelNode.property("myColor").isDynamic());
+ QVERIFY(rootModelNode.property("myDouble").isDynamic());
+
+ QCOMPARE(rootModelNode.property("myColor").dynamicTypeName(), QString("color"));
+ QCOMPARE(rootModelNode.variantProperty("myColor").value(), QVariant(Qt::red));
+ //QCOMPARE(rootQmlItemNode.instanceValue("myColor"), QVariant(Qt::red)); //not working yet
+ QCOMPARE(rootModelNode.property("myDouble").dynamicTypeName(), QString("real"));
+ QCOMPARE(rootModelNode.variantProperty("myDouble").value(), QVariant(10));
+ //QCOMPARE(rootQmlItemNode.instanceValue("myDouble"), QVariant(10)); //not working yet
+
+ QCOMPARE(rootModelNode.property("x").dynamicTypeName(), QString());
+
+ rootModelNode.variantProperty("myDouble") = QVariant(10);
+ QVERIFY(!rootModelNode.property("myDouble").isDynamic());
+
+ rootModelNode.bindingProperty("myBindingDouble") = qMakePair(QString("real"), QString("myDouble"));
+ rootModelNode.bindingProperty("myBindingColor").setDynamicTypeNameAndExpression("color", "myColor");
+
+ QCOMPARE(rootModelNode.property("myBindingColor").dynamicTypeName(), QString("color"));
+ QCOMPARE(rootModelNode.property("myBindingDouble").dynamicTypeName(), QString("real"));
+
+ QVERIFY(rootModelNode.property("myBindingDouble").isDynamic());
+ QVERIFY(rootModelNode.property("myBindingColor").isDynamic());
+
+ QCOMPARE(rootModelNode.bindingProperty("myBindingDouble").expression(), QString("myDouble"));
+ QCOMPARE(rootModelNode.bindingProperty("myBindingColor").expression(), QString("myColor"));
+}
+
+void TestCore::sideIndex()
+{
+ QSKIP("not anymore needed", SkipAll);
+// QList<QmlError> errors;
+//
+// char qmlString[] = "import Qt 4.6\n"
+// "Rectangle {\n"
+// " width: 200\n"
+// " height: 200\n"
+// " color: \"white\"\n"
+// "Text {\n"
+// " text: \"Hello World\"\n"
+// " anchors.centerIn: parent\n"
+// "}\n"
+// " Text {\n"
+// " text: \"text\"\n"
+// " x: 66\n"
+// " y: 43\n"
+// " width: 80\n"
+// " height: 20\n"
+// " id: Text1;\n"
+// "}\n"
+// " Text {\n"
+// " text: \"text\"\n"
+// " width: 80\n"
+// " height: 20\n"
+// " x: 66\n"
+// " y: 141\n"
+// " id: Text2;\n"
+// "}\n"
+// " Text {\n"
+// " height: 20\n"
+// " text: \"text\"\n"
+// " x: 74\n"
+// " width: 80\n"
+// " y: 68\n"
+// " id: Text3;\n"
+// "}\n"
+// "}\n";
+//
+// QScopedPointer<ByteArrayModifier> modifier1(ByteArrayModifier::create(QLatin1String(qmlString)));
+// QScopedPointer<Model> model(Model::create(modifier1.data(), QUrl(), &errors));
+// foreach(QmlError error, errors) {
+// QFAIL((QString("Line %1: %2").arg(error.line()).arg(error.description())).toLatin1());
+// }
+//
+// QVERIFY(model.data());
+//
+// QCOMPARE(view->rootModelNode().childNodes().at(0).property("text").value().toString(), QString("Hello World"));
+// QCOMPARE(view->rootModelNode().childNodes().at(1).id(), QString("Text1"));
+// QCOMPARE(view->rootModelNode().childNodes().at(2).id(), QString("Text2"));
+// QCOMPARE(view->rootModelNode().childNodes().at(3).id(), QString("Text3"));
+//
+//
+// ModelNode childModelNode(view->rootModelNode().childNodes().at(2));
+// ModelNode childModelNode2(view->rootModelNode().childNodes().at(1));
+//
+// QCOMPARE(childModelNode.id(), QString("Text2"));
+// QCOMPARE(childModelNode2.id(), QString("Text1"));
+//
+// childModelNode.slideToIndex(0);
+// QCOMPARE(childModelNode.id(), QString("Text2"));
+// QCOMPARE(childModelNode2.id(), QString("Text1"));
+// QCOMPARE(view->rootModelNode().childNodes().at(0).id(), QString("Text2"));
+// QCOMPARE(view->rootModelNode().childNodes().at(1).property("text").value().toString(), QString("Hello World"));
+// QCOMPARE(view->rootModelNode().childNodes().at(2).id(), QString("Text1"));
+// QCOMPARE(view->rootModelNode().childNodes().at(3).id(), QString("Text3"));
+
+}
+
+void TestCore::testModelSliding()
+{
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ ModelNode rootModelNode(view->rootModelNode());
+
+ ModelNode rect00(rootModelNode.addChildNode("Qt/Rectangle", 4, 6, "data"));
+ ModelNode rect01(rootModelNode.addChildNode("Qt/Rectangle", 4, 6, "data"));
+ ModelNode rect02(rootModelNode.addChildNode("Qt/Rectangle", 4, 6, "data"));
+ ModelNode rect03(rootModelNode.addChildNode("Qt/Rectangle", 4, 6, "data"));
+
+ QVERIFY(rect00.isValid());
+ QVERIFY(rect01.isValid());
+ QVERIFY(rect02.isValid());
+ QVERIFY(rect03.isValid());
+
+ NodeListProperty listProperty(rootModelNode.nodeListProperty("data"));
+ QVERIFY(!listProperty.isEmpty());
+
+ QList<ModelNode> nodeList(listProperty.toModelNodeList());
+
+ QCOMPARE(rect00, nodeList.at(0));
+ QCOMPARE(rect01, nodeList.at(1));
+ QCOMPARE(rect02, nodeList.at(2));
+ QCOMPARE(rect03, nodeList.at(3));
+
+ listProperty.slide(3,0);
+
+ nodeList = listProperty.toModelNodeList();
+
+ QCOMPARE(rect03, nodeList.at(0));
+ QCOMPARE(rect00, nodeList.at(1));
+ QCOMPARE(rect01, nodeList.at(2));
+ QCOMPARE(rect02, nodeList.at(3));
+
+ NodeListProperty childrenProperty(rootModelNode.nodeListProperty("children"));
+
+ childrenProperty.reparentHere(rect00);
+ childrenProperty.reparentHere(rect01);
+ childrenProperty.reparentHere(rect02);
+ childrenProperty.reparentHere(rect03);
+
+ QVERIFY(listProperty.isEmpty());
+
+ QVERIFY(!childrenProperty.isEmpty());
+
+ nodeList = childrenProperty.toModelNodeList();
+
+ QCOMPARE(rect00, nodeList.at(0));
+ QCOMPARE(rect01, nodeList.at(1));
+ QCOMPARE(rect02, nodeList.at(2));
+ QCOMPARE(rect03, nodeList.at(3));
+
+ childrenProperty.slide(0,3);
+
+ nodeList = childrenProperty.toModelNodeList();
+
+ QCOMPARE(rect01, nodeList.at(0));
+ QCOMPARE(rect02, nodeList.at(1));
+ QCOMPARE(rect03, nodeList.at(2));
+ QCOMPARE(rect00, nodeList.at(3));
+}
+
+void TestCore::testRewriterChangeId()
+{
+ const char* qmlString = "import Qt 4.6\nRectangle { }";
+
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+ model->attachView(testRewriterView.data());
+
+ ModelNode rootModelNode(view->rootModelNode());
+ QVERIFY(rootModelNode.isValid());
+ QCOMPARE(rootModelNode.id(), QString());
+
+ rootModelNode.setId("rectId");
+
+ QCOMPARE(rootModelNode.id(), QString("rectId"));
+
+ QString expected = "import Qt 4.6\n"
+ "Rectangle {\n"
+ " id: rectId\n"
+ " }";
+
+ QCOMPARE(textEdit.toPlainText(), expected);
+
+ // change id for node outside of hierarchy
+ ModelNode node = view->createModelNode("Qt/Item", 4, 6);
+ node.setId("myId");
+}
+
+void TestCore::testRewriterChangeValueProperty()
+{
+ const char* qmlString = "import Qt 4.6\nRectangle { x: 10; y: 10 }";
+
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+ model->attachView(testRewriterView.data());
+
+ ModelNode rootModelNode(view->rootModelNode());
+ QVERIFY(rootModelNode.isValid());
+
+ QCOMPARE(rootModelNode.property("x").toVariantProperty().value().toInt(), 10);
+
+ rootModelNode.property("x").toVariantProperty().setValue(2);
+
+ QCOMPARE(textEdit.toPlainText(), QString(QLatin1String(qmlString)).replace("x: 10;", "x: 2;"));
+
+ // change property for node outside of hierarchy
+ PropertyListType properties;
+ properties.append(QPair<QString,QVariant>("x", 10));
+ ModelNode node = view->createModelNode("Qt/Item", 4, 6, properties);
+ node.variantProperty("x").setValue(20);
+}
+
+void TestCore::testRewriterRemoveValueProperty()
+{
+ const QLatin1String qmlString("\n"
+ "import Qt 4.6\n"
+ "Rectangle {\n"
+ " x: 10\n"
+ " y: 10;\n"
+ "}\n");
+
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+ model->attachView(testRewriterView.data());
+
+ ModelNode rootModelNode(view->rootModelNode());
+ QVERIFY(rootModelNode.isValid());
+
+ QCOMPARE(rootModelNode.property("x").toVariantProperty().value().toInt(), 10);
+
+ rootModelNode.property("x").toVariantProperty().setValue(2);
+
+ rootModelNode.removeProperty("x");
+
+ const QLatin1String expected("\n"
+ "import Qt 4.6\n"
+ "Rectangle {\n"
+ " y: 10;\n"
+ "}\n");
+ QCOMPARE(textEdit.toPlainText(), expected);
+
+ // remove property for node outside of hierarchy
+ PropertyListType properties;
+ properties.append(QPair<QString,QVariant>("x", 10));
+ ModelNode node = view->createModelNode("Qt/Item", 4, 6, properties);
+ node.removeProperty("x");
+}
+
+void TestCore::testRewriterSignalProperty()
+{
+ const char* qmlString = "import Qt 4.6\nRectangle { onColorChanged: {} }";
+
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+ model->attachView(testRewriterView.data());
+
+ ModelNode rootModelNode(view->rootModelNode());
+ QVERIFY(rootModelNode.isValid());
+
+ // Signal properties are ignored for the time being
+ QCOMPARE(rootModelNode.properties().size(), 0);
+}
+
+void TestCore::testRewriterObjectTypeProperty()
+{
+ const char* qmlString = "import Qt 4.6\nRectangle { x: 10; y: 10 }";
+
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+ model->attachView(testRewriterView.data());
+
+ ModelNode rootModelNode(view->rootModelNode());
+ QVERIFY(rootModelNode.isValid());
+
+ QCOMPARE(rootModelNode.type(), QLatin1String("Qt/Rectangle"));
+
+ rootModelNode.changeType(QLatin1String("Qt/Text"), 4, 6);
+
+ QCOMPARE(rootModelNode.type(), QLatin1String("Qt/Text"));
+
+ // change type outside of hierarchy
+ ModelNode node = view->createModelNode("Qt/Rectangle", 4, 6);
+ node.changeType(QLatin1String("Qt/Item"), 4, 6);
+}
+
+void TestCore::testRewriterPropertyChanges()
+{
+ try {
+ // PropertyChanges uses a custom parser
+
+ // Use a slightly more complicated example so that target properties are not resolved in default scope
+ const char* qmlString
+ = "import Qt 4.6\n"
+ "Rectangle {\n"
+ " Text {\n"
+ " id: targetObj\n"
+ " text: \"base State\"\n"
+ " }\n"
+ " states: [\n"
+ " State {\n"
+ " PropertyChanges {\n"
+ " target: targetObj\n"
+ " text: \"State 1\"\n"
+ " }\n"
+ " }\n"
+ " ]\n"
+ "}\n";
+
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item", 4, 6));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ model->attachView(view.data());
+
+ // read in
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+ model->attachView(testRewriterView.data());
+
+ ModelNode rootNode = view->rootModelNode();
+ QVERIFY(rootNode.isValid());
+ QCOMPARE(rootNode.type(), QString("Qt/Rectangle"));
+ QVERIFY(rootNode.propertyNames().contains(QLatin1String("data")));
+ QVERIFY(rootNode.propertyNames().contains(QLatin1String("states")));
+ QCOMPARE(rootNode.propertyNames().count(), 2);
+
+ NodeListProperty statesProperty = rootNode.nodeListProperty("states");
+ QVERIFY(statesProperty.isValid());
+ QCOMPARE(statesProperty.toModelNodeList().size(), 1);
+
+ ModelNode stateNode = statesProperty.toModelNodeList().first();
+ QVERIFY(stateNode.isValid());
+ QCOMPARE(stateNode.type(), QString("Qt/State"));
+ QCOMPARE(stateNode.propertyNames(), QStringList("changes"));
+
+ NodeListProperty stateChangesProperty = stateNode.property("changes").toNodeListProperty();
+ QVERIFY(stateChangesProperty.isValid());
+
+ ModelNode propertyChangesNode = stateChangesProperty.toModelNodeList().first();
+ QVERIFY(propertyChangesNode.isValid());
+ QCOMPARE(propertyChangesNode.properties().size(), 2);
+
+ BindingProperty targetProperty = propertyChangesNode.bindingProperty("target");
+ QVERIFY(targetProperty.isValid());
+
+ VariantProperty textProperty = propertyChangesNode.variantProperty("text");
+ QVERIFY(textProperty.isValid());
+ QCOMPARE(textProperty.value().toString(), QLatin1String("State 1"));
+ } catch (Exception &e) {
+ QFAIL(e.description().toAscii().data());
+ }
+}
+
+void TestCore::testRewriterListModel()
+{
+ QSKIP("See BAUHAUS-157", SkipAll);
+
+ try {
+ // ListModel uses a custom parser
+ const char* qmlString = "import Qt 4.6; ListModel {\n ListElement {\n age: 12\n} \n}";
+
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item", 4, 6));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+ model->attachView(testRewriterView.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ model->attachView(view.data());
+
+ ModelNode listModelNode = view->rootModelNode();
+ QCOMPARE(listModelNode.propertyNames(), QStringList() << "__elements"); // TODO: what should be the name?
+
+ NodeListProperty elementListProperty = listModelNode.nodeListProperty("__elements");
+ QCOMPARE(elementListProperty.toModelNodeList().size(), 1);
+
+ ModelNode elementNode = elementListProperty.toModelNodeList().at(0);
+ QVERIFY(elementNode.isValid());
+ QCOMPARE(elementNode.properties().size(), 1);
+ QVERIFY(elementNode.variantProperty("age").isValid());
+ QCOMPARE(elementNode.variantProperty("age").value().toInt(), 12);
+ } catch (Exception &e) {
+ QFAIL(qPrintable(e.description()));
+ }
+}
+
+void TestCore::testRewriterAddProperty()
+{
+ const QLatin1String qmlString("\n"
+ "import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ "}");
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item", 4, 6));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ model->attachView(view.data());
+
+ // read in
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+ model->attachView(testRewriterView.data());
+
+ ModelNode rootNode = view->rootModelNode();
+ QVERIFY(rootNode.isValid());
+ QCOMPARE(rootNode.type(), QString("Qt/Rectangle"));
+
+ rootNode.variantProperty(QLatin1String("x")).setValue(123);
+
+ QVERIFY(rootNode.hasProperty(QLatin1String("x")));
+ QVERIFY(rootNode.property(QLatin1String("x")).isVariantProperty());
+ QCOMPARE(rootNode.variantProperty(QLatin1String("x")).value(), QVariant(123));
+
+ const QLatin1String expected("\n"
+ "import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ " x: 123\n"
+ "}");
+ QCOMPARE(textEdit.toPlainText(), expected);
+}
+
+void TestCore::testRewriterAddPropertyInNestedObject()
+{
+ const QLatin1String qmlString("\n"
+ "import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ " Rectangle {\n"
+ " id: Rectangle1\n"
+ " }\n"
+ "}");
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item", 4, 6));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ model->attachView(view.data());
+
+ // read in
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+ model->attachView(testRewriterView.data());
+
+ ModelNode rootNode = view->rootModelNode();
+ QVERIFY(rootNode.isValid());
+ QCOMPARE(rootNode.type(), QLatin1String("Qt/Rectangle"));
+
+ ModelNode childNode = rootNode.nodeListProperty(QLatin1String("data")).toModelNodeList().at(0);
+ QVERIFY(childNode.isValid());
+ QCOMPARE(childNode.type(), QLatin1String("Qt/Rectangle"));
+ QCOMPARE(childNode.id(), QLatin1String("Rectangle1"));
+
+ childNode.variantProperty(QLatin1String("x")).setValue(10);
+ childNode.variantProperty(QLatin1String("y")).setValue(10);
+
+ const QLatin1String expected("\n"
+ "import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ " Rectangle {\n"
+ " id: Rectangle1\n"
+ " x: 10\n"
+ " y: 10\n"
+ " }\n"
+ "}");
+ QCOMPARE(textEdit.toPlainText(), expected);
+}
+
+void TestCore::testRewriterAddObjectDefinition()
+{
+ const QLatin1String qmlString("import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ "}");
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item", 4, 6));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ model->attachView(view.data());
+
+ // read in
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+ model->attachView(testRewriterView.data());
+
+ ModelNode rootNode = view->rootModelNode();
+ QVERIFY(rootNode.isValid());
+ QCOMPARE(rootNode.type(), QString("Qt/Rectangle"));
+
+ ModelNode childNode = view->createModelNode("Qt/MouseRegion", 4, 6);
+ rootNode.nodeAbstractProperty(QLatin1String("data")).reparentHere(childNode);
+
+ QCOMPARE(rootNode.nodeProperty(QLatin1String("data")).toNodeListProperty().toModelNodeList().size(), 1);
+ childNode = rootNode.nodeProperty(QLatin1String("data")).toNodeListProperty().toModelNodeList().at(0);
+ QCOMPARE(childNode.type(), QString(QLatin1String("Qt/MouseRegion")));
+}
+
+void TestCore::testRewriterAddStatesArray()
+{
+ const QLatin1String qmlString("\n"
+ "import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ "}");
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item", 4, 6));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ model->attachView(view.data());
+
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+ model->attachView(testRewriterView.data());
+
+ ModelNode rootNode = view->rootModelNode();
+ QVERIFY(rootNode.isValid());
+ QCOMPARE(rootNode.type(), QString("Qt/Rectangle"));
+
+ ModelNode stateNode = view->createModelNode("Qt/State", 4, 6);
+ rootNode.nodeListProperty(QLatin1String("states")).reparentHere(stateNode);
+
+ const QString expected1 = QLatin1String("\n"
+ "import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ " states: [\n"
+ " State {\n"
+ " }\n"
+ " ]\n"
+ "}");
+ QCOMPARE(textEdit.toPlainText(), expected1);
+
+ ModelNode stateNode2 = view->createModelNode("Qt/State", 4, 6);
+ rootNode.nodeListProperty(QLatin1String("states")).reparentHere(stateNode2);
+
+ const QString expected2 = QLatin1String("\n"
+ "import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ " states: [\n"
+ " State {\n"
+ " },\n"
+ " State {\n"
+ " }\n"
+ " ]\n"
+ "}");
+ QCOMPARE(textEdit.toPlainText(), expected2);
+}
+
+void TestCore::testRewriterRemoveStates()
+{
+ const QLatin1String qmlString("\n"
+ "import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ " states: [\n"
+ " State {\n"
+ " },\n"
+ " State {\n"
+ " }\n"
+ " ]\n"
+ "}");
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item", 4, 6));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ model->attachView(view.data());
+
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+ model->attachView(testRewriterView.data());
+
+ ModelNode rootNode = view->rootModelNode();
+ QVERIFY(rootNode.isValid());
+ QCOMPARE(rootNode.type(), QString("Qt/Rectangle"));
+
+ NodeListProperty statesProperty = rootNode.nodeListProperty(QLatin1String("states"));
+ QVERIFY(statesProperty.isValid());
+ QCOMPARE(statesProperty.toModelNodeList().size(), 2);
+
+ ModelNode state = statesProperty.toModelNodeList().at(1);
+ state.destroy();
+
+ const QLatin1String expected1("\n"
+ "import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ " states: [\n"
+ " State {\n"
+ " }\n"
+ " ]\n"
+ "}");
+ QCOMPARE(textEdit.toPlainText(), expected1);
+
+ state = statesProperty.toModelNodeList().at(0);
+ state.destroy();
+
+ const QLatin1String expected2("\n"
+ "import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ "}");
+ QCOMPARE(textEdit.toPlainText(), expected2);
+}
+
+void TestCore::testRewriterRemoveObjectDefinition()
+{
+ const QLatin1String qmlString("\n"
+ "import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ " MouseRegion {\n"
+ " }\n"
+ " MouseRegion {\n"
+ " } // some comment here\n"
+ "}");
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item", 4, 6));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ model->attachView(view.data());
+
+ // read in
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+ model->attachView(testRewriterView.data());
+
+ ModelNode rootNode = view->rootModelNode();
+ QVERIFY(rootNode.isValid());
+ QCOMPARE(rootNode.type(), QString("Qt/Rectangle"));
+
+ QCOMPARE(rootNode.nodeProperty(QLatin1String("data")).toNodeListProperty().toModelNodeList().size(), 2);
+ ModelNode childNode = rootNode.nodeProperty(QLatin1String("data")).toNodeListProperty().toModelNodeList().at(1);
+ QCOMPARE(childNode.type(), QString(QLatin1String("Qt/MouseRegion")));
+
+ childNode.destroy();
+
+ QCOMPARE(rootNode.nodeProperty(QLatin1String("data")).toNodeListProperty().toModelNodeList().size(), 1);
+ childNode = rootNode.nodeProperty(QLatin1String("data")).toNodeListProperty().toModelNodeList().at(0);
+ QCOMPARE(childNode.type(), QString(QLatin1String("Qt/MouseRegion")));
+
+ childNode.destroy();
+
+ QVERIFY(!rootNode.hasProperty(QLatin1String("data")));
+
+ const QString expected = QLatin1String("\n"
+ "import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ " // some comment here\n"
+ "}");
+ QCOMPARE(textEdit.toPlainText(), expected);
+
+ // don't crash when deleting nodes not in any hierarchy
+ ModelNode node1 = view->createModelNode("Qt/Rectangle", 4, 6);
+ ModelNode node2 = node1.addChildNode("Qt/Item", 4, 6, "data");
+ ModelNode node3 = node2.addChildNode("Qt/Item", 4, 6, "data");
+
+ node3.destroy();
+ node1.destroy();
+}
+
+void TestCore::testRewriterRemoveScriptBinding()
+{
+ const QLatin1String qmlString("\n"
+ "import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ " x: 10; // some comment\n"
+ " y: 20\n"
+ "}");
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item", 4, 6));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ model->attachView(view.data());
+
+ // read in
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+ model->attachView(testRewriterView.data());
+
+ ModelNode rootNode = view->rootModelNode();
+ QVERIFY(rootNode.isValid());
+ QCOMPARE(rootNode.type(), QString("Qt/Rectangle"));
+
+ QCOMPARE(rootNode.properties().size(), 2);
+ QVERIFY(rootNode.hasProperty(QLatin1String("x")));
+ QVERIFY(rootNode.hasProperty(QLatin1String("y")));
+
+ rootNode.removeProperty(QLatin1String("y"));
+
+ QCOMPARE(rootNode.properties().size(), 1);
+ QVERIFY(rootNode.hasProperty(QLatin1String("x")));
+ QVERIFY(!rootNode.hasProperty(QLatin1String("y")));
+
+ rootNode.removeProperty(QLatin1String("x"));
+
+ QCOMPARE(rootNode.properties().size(), 0);
+
+ const QString expected = QLatin1String("\n"
+ "import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ " // some comment\n"
+ "}");
+ QCOMPARE(textEdit.toPlainText(), expected);
+}
+
+void TestCore::testRewriterNodeReparenting()
+{
+ const QLatin1String qmlString("\n"
+ "import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ " Item {\n"
+ " MouseRegion {\n"
+ " }\n"
+ " }\n"
+ "}");
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item", 4, 6));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ model->attachView(view.data());
+
+ // read in
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+ model->attachView(testRewriterView.data());
+
+ ModelNode rootNode = view->rootModelNode();
+ QVERIFY(rootNode.isValid());
+ QCOMPARE(rootNode.type(), QString("Qt/Rectangle"));
+
+ ModelNode itemNode = rootNode.nodeListProperty("data").toModelNodeList().at(0);
+ QVERIFY(itemNode.isValid());
+ QCOMPARE(itemNode.type(), QLatin1String("Qt/Item"));
+
+ ModelNode mouseRegion = itemNode.nodeListProperty("data").toModelNodeList().at(0);
+ QVERIFY(mouseRegion.isValid());
+ QCOMPARE(mouseRegion.type(), QLatin1String("Qt/MouseRegion"));
+
+ rootNode.nodeListProperty("data").reparentHere(mouseRegion);
+
+ QVERIFY(mouseRegion.isValid());
+ QCOMPARE(rootNode.nodeListProperty("data").toModelNodeList().size(), 2);
+
+ QString expected = "\n"
+ "import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ " Item {\n"
+ " }\n"
+ "\n"
+ "MouseRegion {\n"
+ " }\n"
+ "}";
+ QCOMPARE(textEdit.toPlainText(), expected);
+
+ // reparenting outside of the hierarchy
+ ModelNode node1 = view->createModelNode("Qt/Rectangle", 4, 6);
+ ModelNode node2 = view->createModelNode("Qt/Item", 4, 6);
+ ModelNode node3 = view->createModelNode("Qt/Item", 4, 6);
+ node2.nodeListProperty("data").reparentHere(node3);
+ node1.nodeListProperty("data").reparentHere(node2);
+
+ // reparent into the hierarchy
+ rootNode.nodeListProperty("data").reparentHere(node1);
+
+ expected = "\n"
+ "import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ " Item {\n"
+ " }\n"
+ "\n"
+ "MouseRegion {\n"
+ " }\n"
+ "\n"
+ " Rectangle {\n"
+ " Item {\n"
+ " Item {\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ "}";
+
+ QCOMPARE(textEdit.toPlainText(), expected);
+
+ // reparent out of the hierarchy
+ ModelNode node4 = view->createModelNode("Qt/Rectangle", 4, 6);
+ node4.nodeListProperty("data").reparentHere(node1);
+
+ expected = "\n"
+ "import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ " Item {\n"
+ " }\n"
+ "\n"
+ "MouseRegion {\n"
+ " }\n"
+ "}";
+
+ QCOMPARE(textEdit.toPlainText(), expected);
+}
+
+void TestCore::testRewriterNodeReparentingWithTransaction()
+{
+ const QLatin1String qmlString("\n"
+ "import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ " id: rootItem\n"
+ " Item {\n"
+ " id: firstItem\n"
+ " x: 10\n"
+ " }\n"
+ " Item {\n"
+ " id: secondItem\n"
+ " x: 20\n"
+ " }\n"
+ "}");
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item", 4, 6));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ model->attachView(view.data());
+
+ // read in
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+ model->attachView(testRewriterView.data());
+
+ ModelNode rootNode = view->rootModelNode();
+ QVERIFY(rootNode.isValid());
+ QCOMPARE(rootNode.type(), QLatin1String("Qt/Rectangle"));
+ QCOMPARE(rootNode.id(), QLatin1String("rootItem"));
+
+ ModelNode item1Node = rootNode.nodeListProperty("data").toModelNodeList().at(0);
+ QVERIFY(item1Node.isValid());
+ QCOMPARE(item1Node.type(), QLatin1String("Qt/Item"));
+ QCOMPARE(item1Node.id(), QLatin1String("firstItem"));
+
+ ModelNode item2Node = rootNode.nodeListProperty("data").toModelNodeList().at(1);
+ QVERIFY(item2Node.isValid());
+ QCOMPARE(item2Node.type(), QLatin1String("Qt/Item"));
+ QCOMPARE(item2Node.id(), QLatin1String("secondItem"));
+
+ RewriterTransaction transaction = testRewriterView->beginRewriterTransaction();
+
+ item1Node.nodeListProperty(QLatin1String("data")).reparentHere(item2Node);
+ item2Node.variantProperty(QLatin1String("x")).setValue(0);
+
+ transaction.commit();
+
+ const QLatin1String expected("\n"
+ "import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ " id: rootItem\n"
+ " Item {\n"
+ " id: firstItem\n"
+ " x: 10\n"
+ "\n"
+ "Item {\n"
+ " id: secondItem\n"
+ " x: 0\n"
+ " }\n"
+ " }\n"
+ "}");
+ QCOMPARE(textEdit.toPlainText(), expected);
+}
+void TestCore::testRewriterMovingInOut()
+{
+ const QLatin1String qmlString("\n"
+ "import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ "}");
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item", 4, 6));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ model->attachView(view.data());
+
+ // read in
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+ model->attachView(testRewriterView.data());
+
+ ModelNode rootNode = view->rootModelNode();
+ QVERIFY(rootNode.isValid());
+ QCOMPARE(rootNode.type(), QString("Qt/Rectangle"));
+
+ ModelNode newNode = view->createModelNode("Qt/MouseRegion", 4, 6);
+ rootNode.nodeListProperty(QLatin1String("data")).reparentHere(newNode);
+
+ const QLatin1String expected1("\n"
+ "import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ " MouseRegion {\n"
+ " }\n"
+ "}");
+ QCOMPARE(textEdit.toPlainText(), expected1);
+
+#define move(node, x, y) {\
+ node.variantProperty(QLatin1String("x")).setValue(x);\
+ node.variantProperty(QLatin1String("y")).setValue(y);\
+}
+ move(newNode, 1, 1);
+ move(newNode, 2, 2);
+ move(newNode, 3, 3);
+#undef move
+ newNode.destroy();
+
+ const QLatin1String expected2("\n"
+ "import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ "}");
+ QCOMPARE(textEdit.toPlainText(), expected2);
+}
+
+void TestCore::testRewriterMovingInOutWithTransaction()
+{
+ const QLatin1String qmlString("\n"
+ "import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ "}");
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item", 4, 6));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ model->attachView(view.data());
+
+ // read in
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+ model->attachView(testRewriterView.data());
+
+ ModelNode rootNode = view->rootModelNode();
+ QVERIFY(rootNode.isValid());
+ QCOMPARE(rootNode.type(), QString("Qt/Rectangle"));
+
+ RewriterTransaction transaction = view->beginRewriterTransaction();
+
+ ModelNode newNode = view->createModelNode("Qt/MouseRegion", 4, 6);
+ rootNode.nodeListProperty(QLatin1String("data")).reparentHere(newNode);
+
+#define move(node, x, y) {\
+ node.variantProperty(QLatin1String("x")).setValue(x);\
+ node.variantProperty(QLatin1String("y")).setValue(y);\
+}
+ move(newNode, 1, 1);
+ move(newNode, 2, 2);
+ move(newNode, 3, 3);
+#undef move
+ newNode.destroy();
+
+ transaction.commit();
+
+ const QLatin1String expected2("\n"
+ "import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ "}");
+ QCOMPARE(textEdit.toPlainText(), expected2);
+}
+
+void TestCore::testRewriterComplexMovingInOut()
+{
+ const QLatin1String qmlString("\n"
+ "import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ " Item {\n"
+ " }\n"
+ "}");
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item", 4, 6));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ model->attachView(view.data());
+
+ // read in
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+ model->attachView(testRewriterView.data());
+
+ ModelNode rootNode = view->rootModelNode();
+ QVERIFY(rootNode.isValid());
+ QCOMPARE(rootNode.type(), QString("Qt/Rectangle"));
+ ModelNode itemNode = rootNode.nodeListProperty(QLatin1String("data")).toModelNodeList().at(0);
+
+ ModelNode newNode = view->createModelNode("Qt/MouseRegion", 4, 6);
+ rootNode.nodeListProperty(QLatin1String("data")).reparentHere(newNode);
+
+ const QLatin1String expected1("\n"
+ "import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ " Item {\n"
+ " }\n"
+ "\n"
+ " MouseRegion {\n"
+ " }\n"
+ "}");
+ QCOMPARE(textEdit.toPlainText(), expected1);
+
+#define move(node, x, y) {\
+ node.variantProperty(QLatin1String("x")).setValue(x);\
+ node.variantProperty(QLatin1String("y")).setValue(y);\
+}
+ move(newNode, 1, 1);
+ move(newNode, 2, 2);
+ move(newNode, 3, 3);
+
+ const QLatin1String expected2("\n"
+ "import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ " Item {\n"
+ " }\n"
+ "\n"
+ " MouseRegion {\n"
+ " x: 3\n"
+ " y: 3\n"
+ " }\n"
+ "}");
+ QCOMPARE(textEdit.toPlainText(), expected2);
+
+ itemNode.nodeListProperty(QLatin1String("data")).reparentHere(newNode);
+
+ const QLatin1String expected3("\n"
+ "import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ " Item {\n"
+ "MouseRegion {\n"
+ " x: 3\n"
+ " y: 3\n"
+ " }\n"
+ " }\n"
+ "}");
+ QCOMPARE(textEdit.toPlainText(), expected3);
+
+ move(newNode, 0, 0);
+ move(newNode, 1, 1);
+ move(newNode, 2, 2);
+ move(newNode, 3, 3);
+#undef move
+ newNode.destroy();
+
+ const QLatin1String expected4("\n"
+ "import Qt 4.6\n"
+ "\n"
+ "Rectangle {\n"
+ " Item {\n"
+ " }\n"
+ "}");
+ QCOMPARE(textEdit.toPlainText(), expected4);
+}
+
+void TestCore::removeCenteredInAnchorByDetaching()
+{
+ QPlainTextEdit textEdit1;
+ textEdit1.setPlainText("import Qt 4.6; Item { Rectangle { id: child; anchors.centerIn: parent } }");
+ PlainTextEditModifier modifier1(&textEdit1);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+
+ QScopedPointer<TestRewriterView> testRewriterView1(new TestRewriterView());
+ testRewriterView1->setTextModifier(&modifier1);
+ model->attachView(testRewriterView1.data());
+
+ TestView *testView = new TestView(model.data());
+ model->attachView(testView);
+
+ QmlItemNode rootQmlItemNode(testView->rootQmlItemNode());
+
+
+ QmlItemNode firstChild(rootQmlItemNode.children().first());
+ QVERIFY(firstChild.isValid());
+ QCOMPARE(firstChild.id(), QString("child"));
+
+ // Verify the synthesized anchors:
+ QmlAnchors anchors(firstChild);
+ QVERIFY(!anchors.instanceAnchor(AnchorLine::Left).isValid());
+ QVERIFY(!anchors.instanceAnchor(AnchorLine::Top).isValid());
+ QVERIFY(!anchors.instanceAnchor(AnchorLine::Right).isValid());
+ QVERIFY(!anchors.instanceAnchor(AnchorLine::Bottom).isValid());
+
+ QVERIFY(anchors.instanceAnchor(AnchorLine::HorizontalCenter).isValid());
+ QCOMPARE(anchors.instanceAnchor(AnchorLine::HorizontalCenter).qmlItemNode(), rootQmlItemNode);
+ QCOMPARE(anchors.instanceAnchor(AnchorLine::HorizontalCenter).type(), AnchorLine::HorizontalCenter);
+
+ QVERIFY(anchors.instanceAnchor(AnchorLine::VerticalCenter).isValid());
+ QCOMPARE(anchors.instanceAnchor(AnchorLine::VerticalCenter).qmlItemNode(), rootQmlItemNode);
+ QCOMPARE(anchors.instanceAnchor(AnchorLine::VerticalCenter).type(), AnchorLine::VerticalCenter);
+ QSKIP("transaction are crashing", SkipAll);
+ // Remove horizontal anchor:
+ anchors.removeAnchor(AnchorLine::HorizontalCenter);
+
+ // Verify again:
+ QVERIFY(!anchors.instanceAnchor(AnchorLine::Left).isValid());
+ QVERIFY(!anchors.instanceAnchor(AnchorLine::Top).isValid());
+ QVERIFY(!anchors.instanceAnchor(AnchorLine::Right).isValid());
+ QVERIFY(!anchors.instanceAnchor(AnchorLine::Bottom).isValid());
+
+ QVERIFY(!anchors.instanceAnchor(AnchorLine::HorizontalCenter).isValid());
+
+ QVERIFY(anchors.instanceAnchor(AnchorLine::VerticalCenter).isValid());
+ QCOMPARE(anchors.instanceAnchor(AnchorLine::VerticalCenter).qmlItemNode(), rootQmlItemNode);
+ QCOMPARE(anchors.instanceAnchor(AnchorLine::VerticalCenter).type(), AnchorLine::VerticalCenter);
+}
+
+void TestCore::loadPropertyBinding()
+{
+ QSKIP("property bindings are disabled", SkipAll);
+// QScopedPointer<Model> model(Model::create("Qt/Item"));
+// QVERIFY(model.data());
+// ModelNode rootModelNode(view->rootModelNode());
+//
+//
+// ModelNode firstChild = rootModelNode.addChildNode("Qt/Rectangle", 4, 6, "data");
+// firstChild.addProperty("width", QString("parent.width"));
+// QVERIFY(firstChild.isValid());
+// QVERIFY(firstChild.hasProperty("width"));
+// QVERIFY(firstChild.property("width").isValueAPropertyBinding());
+//
+// AbstractProperty width = firstChild.property("width");
+// QVERIFY(width.isValueAPropertyBinding());
+//
+// QVERIFY(width.value().isValid() && !width.value().isNull());
+// QCOMPARE(width.value().type(), QVariant::UserType);
+// QCOMPARE(width.value().userType(), qMetaTypeId<QmlDesigner::PropertyBinding>());
+//
+// PropertyBinding widthBinding = width.valueToPropertyBinding();
+// QVERIFY(widthBinding.isValid());
+// QCOMPARE(widthBinding.value(), QString("parent.width"));
+}
+
+void TestCore::changePropertyBinding()
+{
+
+ QScopedPointer<Model> model(Model::create("Qt/Item"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ model->attachView(view.data());
+
+ ModelNode rootModelNode(view->rootModelNode());
+ rootModelNode.variantProperty("width") = 20;
+
+ ModelNode firstChild = rootModelNode.addChildNode("Qt/Rectangle", 4, 6, "data");
+ firstChild.bindingProperty("width").setExpression(QString("parent.width"));
+ firstChild.variantProperty("height")= 10;
+ QVERIFY(firstChild.isValid());
+
+ {
+ QVERIFY(firstChild.hasProperty("width"));
+
+ BindingProperty widthBinding = firstChild.bindingProperty("width");
+ QVERIFY(widthBinding.isValid());
+ QCOMPARE(widthBinding.expression(), QString("parent.width"));
+ QVERIFY(firstChild.variantProperty("height").value().toInt() == 10);
+ }
+
+ firstChild.variantProperty("width") = 400;
+ firstChild.bindingProperty("height").setExpression("parent.width / 2");
+
+ {
+ QVERIFY(firstChild.hasProperty("width"));
+ QVariant width = firstChild.variantProperty("width").value();
+ QVERIFY(width.isValid() && !width.isNull());
+ QVERIFY(width == 400);
+ QVERIFY(firstChild.hasProperty("height"));
+ BindingProperty heightBinding = firstChild.bindingProperty("height");
+ QVERIFY(heightBinding.isValid());
+ QCOMPARE(heightBinding.expression(), QString("parent.width / 2"));
+ }
+}
+
+void TestCore::loadObjectPropertyBinding()
+{
+ QSKIP("will be changed", SkipAll);
+
+// QList<QmlError> errors;
+// QScopedPointer<ByteArrayModifier> modifier1(ByteArrayModifier::create(QString("import Qt 4.6; Item { ListView { delegate:componentId } Component { id:componentId;Rectangle {} } }")));
+//
+// QVERIFY(model.data());
+// ModelNode rootModelNode(view->rootModelNode());
+//
+//
+// QVERIFY(rootModelNode.childNodes().at(1).id() == "componentId");
+// QVERIFY(rootModelNode.childNodes().first().property("delegate").value().canConvert<ObjectPropertyBinding>());
+}
+
+void TestCore::loadWelcomeScreen()
+{
+ QSKIP("there is no rewriter anymore", SkipAll);
+// QFile file(QCoreApplication::applicationDirPath() + "/../shared/welcomescreen.qml");
+// QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));
+//
+// QList<QmlError> errors;
+// QScopedPointer<ByteArrayModifier> modifier1(ByteArrayModifier::create(QString(file.readAll())));
+// QScopedPointer<Model> model1(Model::create(modifier1.data(), QUrl::fromLocalFile(file.fileName()), &errors));
+// if (!errors.isEmpty()) {
+// printErrors(errors, file.fileName());
+// QVERIFY(errors.isEmpty());
+// }
+// QVERIFY(model1.data());
+}
+
+static QString rectWithGradient = "import Qt 4.6\n"
+ "Rectangle {\n"
+ " gradient: Gradient {\n"
+ " id: pGradient\n"
+ " GradientStop { id: pOne; position: 0.0; color: \"lightsteelblue\" }\n"
+ " GradientStop { id: pTwo; position: 1.0; color: \"blue\" }\n"
+ " }\n"
+ " Gradient {\n"
+ " id: secondGradient\n"
+ " GradientStop { id: nOne; position: 0.0; color: \"blue\" }\n"
+ " GradientStop { id: nTwo; position: 1.0; color: \"lightsteelblue\" }\n"
+ " }\n"
+ "}";
+
+void TestCore::loadGradient()
+{
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(rectWithGradient);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item", 4, 6));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+ model->attachView(testRewriterView.data());
+
+
+ QVERIFY(model.data());
+ ModelNode rootModelNode(testRewriterView->rootModelNode());
+ QVERIFY(rootModelNode.isValid());
+ QCOMPARE(rootModelNode.allDirectSubModelNodes().size(), 2);
+
+ {
+ QVERIFY(rootModelNode.hasProperty("gradient"));
+ AbstractProperty gradientProperty = rootModelNode.property("gradient");
+ QVERIFY(gradientProperty.isNodeProperty());
+ ModelNode gradientPropertyModelNode = gradientProperty.toNodeProperty().modelNode();
+ QVERIFY(gradientPropertyModelNode.isValid());
+ QCOMPARE(gradientPropertyModelNode.type(), QString("Qt/Gradient"));
+ QCOMPARE(gradientPropertyModelNode.allDirectSubModelNodes().size(), 2);
+
+ AbstractProperty stopsProperty = gradientPropertyModelNode.property("stops");
+ QVERIFY(stopsProperty.isValid());
+
+ QVERIFY(stopsProperty.isNodeListProperty());
+ QList<ModelNode> stops = stopsProperty.toNodeListProperty().toModelNodeList();
+ QCOMPARE(stops.size(), 2);
+
+ ModelNode pOne = stops.first();
+ ModelNode pTwo = stops.last();
+
+ QCOMPARE(pOne.type(), QString("Qt/GradientStop"));
+ QCOMPARE(pOne.id(), QString("pOne"));
+ QCOMPARE(pOne.allDirectSubModelNodes().size(), 0);
+ QCOMPARE(pOne.propertyNames().size(), 2);
+ QCOMPARE(pOne.variantProperty("position").value().type(), QVariant::Double);
+ QCOMPARE(pOne.variantProperty("position").value().toDouble(), 0.0);
+ QCOMPARE(pOne.variantProperty("color").value().type(), QVariant::Color);
+ QCOMPARE(pOne.variantProperty("color").value().value<QColor>(), QColor("lightsteelblue"));
+
+ QCOMPARE(pTwo.type(), QString("Qt/GradientStop"));
+ QCOMPARE(pTwo.id(), QString("pTwo"));
+ QCOMPARE(pTwo.allDirectSubModelNodes().size(), 0);
+ QCOMPARE(pTwo.propertyNames().size(), 2);
+ QCOMPARE(pTwo.variantProperty("position").value().type(), QVariant::Double);
+ QCOMPARE(pTwo.variantProperty("position").value().toDouble(), 1.0);
+ QCOMPARE(pTwo.variantProperty("color").value().type(), QVariant::Color);
+ QCOMPARE(pTwo.variantProperty("color").value().value<QColor>(), QColor("blue"));
+ }
+
+ {
+ ModelNode gradientNode = rootModelNode.allDirectSubModelNodes().last();
+ QVERIFY(gradientNode.isValid());
+ QVERIFY(!gradientNode.metaInfo().isQmlGraphicsItem());
+ QCOMPARE(gradientNode.type(), QString("Qt/Gradient"));
+ QCOMPARE(gradientNode.id(), QString("secondGradient"));
+ QCOMPARE(gradientNode.allDirectSubModelNodes().size(), 2);
+
+ AbstractProperty stopsProperty = gradientNode.property("stops");
+ QVERIFY(stopsProperty.isValid());
+
+ QVERIFY(stopsProperty.isNodeListProperty());
+ QList<ModelNode> stops = stopsProperty.toNodeListProperty().toModelNodeList();
+ QCOMPARE(stops.size(), 2);
+
+ ModelNode nOne = stops.first();
+ ModelNode nTwo = stops.last();
+
+ QCOMPARE(nOne.type(), QString("Qt/GradientStop"));
+ QCOMPARE(nOne.id(), QString("nOne"));
+ QCOMPARE(nOne.allDirectSubModelNodes().size(), 0);
+ QCOMPARE(nOne.propertyNames().size(), 2);
+ QCOMPARE(nOne.variantProperty("position").value().type(), QVariant::Double);
+ QCOMPARE(nOne.variantProperty("position").value().toDouble(), 0.0);
+ QCOMPARE(nOne.variantProperty("color").value().type(), QVariant::Color);
+ QCOMPARE(nOne.variantProperty("color").value().value<QColor>(), QColor("blue"));
+
+ QCOMPARE(nTwo.type(), QString("Qt/GradientStop"));
+ QCOMPARE(nTwo.id(), QString("nTwo"));
+ QCOMPARE(nTwo.allDirectSubModelNodes().size(), 0);
+ QCOMPARE(nTwo.propertyNames().size(), 2);
+ QCOMPARE(nTwo.variantProperty("position").value().type(), QVariant::Double);
+ QCOMPARE(nTwo.variantProperty("position").value().toDouble(), 1.0);
+ QCOMPARE(nTwo.variantProperty("color").value().type(), QVariant::Color);
+ QCOMPARE(nTwo.variantProperty("color").value().value<QColor>(), QColor("lightsteelblue"));
+ }
+}
+
+void TestCore::changeGradientId()
+{
+ try {
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(rectWithGradient);
+ PlainTextEditModifier textModifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("Qt/Item", 4, 6));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&textModifier);
+ model->attachView(testRewriterView.data());
+
+ QVERIFY(model.data());
+ ModelNode rootModelNode(testRewriterView->rootModelNode());
+ QVERIFY(rootModelNode.isValid());
+ QCOMPARE(rootModelNode.allDirectSubModelNodes().size(), 2);
+
+ AbstractProperty gradientProperty = rootModelNode.property("gradient");
+ QVERIFY(gradientProperty.isNodeProperty());
+ ModelNode gradientNode = gradientProperty.toNodeProperty().modelNode();
+ QVERIFY(gradientNode.isValid());
+ QCOMPARE(gradientNode.id(), QString("pGradient"));
+
+ gradientNode.setId("firstGradient");
+ QCOMPARE(gradientNode.id(), QString("firstGradient"));
+
+ AbstractProperty stopsProperty = gradientNode.property("stops");
+ QVERIFY(stopsProperty.isValid());
+
+ QVERIFY(stopsProperty.isNodeListProperty());
+ QList<ModelNode> stops = stopsProperty.toNodeListProperty().toModelNodeList();
+ QCOMPARE(stops.size(), 2);
+
+ ModelNode firstStop = stops.at(0);
+ QVERIFY(firstStop.isValid());
+ firstStop.destroy();
+ QVERIFY(!firstStop.isValid());
+
+ ModelNode gradientStop = gradientNode.addChildNode("Qt/GradientStop", 4, 6, "stops");
+ gradientStop.variantProperty("position") = 0.5;
+ gradientStop.variantProperty("color") = QColor("yellow");
+
+ gradientStop.setId("newGradientStop");
+
+ QCOMPARE(gradientNode.allDirectSubModelNodes().size(), 2);
+ QCOMPARE(gradientNode.nodeListProperty("stops").toModelNodeList().size(), 2);
+ QCOMPARE(gradientStop.id(), QString("newGradientStop"));
+ QCOMPARE(gradientStop.variantProperty("position").value().toDouble(), 0.5);
+ QCOMPARE(gradientStop.variantProperty("color").value().value<QColor>(), QColor("yellow"));
+
+ } catch (Exception &e) {
+ qDebug() << e;
+ QFAIL(e.description().toLatin1().data());
+ }
+}
+
+void TestCore::copyAndPasteInSingleModel()
+{
+ QSKIP("no anchor support anymore", SkipAll);
+
+// try {
+// QScopedPointer<Model> model(create("import Qt 4.6; Item { width: 100; height: 200; Rectangle { x: 10; y: 20; width: 30; height: 40; color: \"red\"}}"));
+// QVERIFY(model.data());
+// ModelNode rootModelNode(view->rootModelNode());
+// QVERIFY(rootModelNode.isValid());
+// ModelNode rectNode(rootModelNode.childNodes().at(0));
+// QVERIFY(rectNode.isValid());
+//
+// QMimeData *transfer = model->copy(QList<NodeState>() << rectNode);
+// QVERIFY(rectNode.isValid());
+// QCOMPARE(rectNode.childNodes().size(), 0);
+//
+// QVERIFY(transfer != 0);
+// model->paste(transfer, rectNode);
+// QVERIFY(rectNode.isValid());
+// QCOMPARE(rectNode.childNodes().size(), 1);
+//
+// QCOMPARE(rectNode.property("x").value().toDouble(), 10.0);
+// QCOMPARE(rectNode.property("y").value().toDouble(), 20.0);
+// QCOMPARE(rectNode.property("width").value().toDouble(), 30.0);
+// QCOMPARE(rectNode.property("height").value().toDouble(), 40.0);
+// QCOMPARE(rectNode.property("color").value().value<QColor>(), QColor("red"));
+//
+// ModelNode rectChild = rectNode.childNodes().at(0);
+// QCOMPARE(rectChild.property("x").value().toDouble(), 10.0);
+// QCOMPARE(rectChild.property("y").value().toDouble(), 20.0);
+// QCOMPARE(rectChild.property("width").value().toDouble(), 30.0);
+// QCOMPARE(rectChild.property("height").value().toDouble(), 40.0);
+// QCOMPARE(rectChild.property("color").value().value<QColor>(), QColor("red"));
+// } catch (Exception &e) {
+// qDebug() << e;
+// QFAIL(e.description().toLatin1().data());
+// }
+}
+
+void TestCore::copyAndPasteBetweenModels()
+{
+ QSKIP("no anchor support anymore", SkipAll);
+
+// try {
+// QScopedPointer<Model> model1(create("import Qt 4.6; Item { width: 100; height: 200; Rectangle { x: 10; y: 20; width: 30; height: 40; color: \"red\"}}"));
+// QVERIFY(model1.data());
+// ModelNode rootModelNode1(model1->rootModelNode());
+// QVERIFY(rootModelNode1.isValid());
+// ModelNode rectNode1(rootModelNode1.childNodes().at(0));
+// QVERIFY(rectNode1.isValid());
+//
+// QScopedPointer<Model> model2(create("import Qt 4.6; Item { width: 100; height: 200}"));
+// QVERIFY(model2.data());
+// ModelNode rootModelNode2(model2->rootModelNode());
+// QVERIFY(rootModelNode2.isValid());
+// QCOMPARE(rootModelNode2.childNodes().size(), 0);
+//
+// QMimeData *transfer = model1->copy(QList<NodeState>() << rectNode1);
+// QVERIFY(rectNode1.isValid());
+//
+// QVERIFY(transfer != 0);
+// model2->paste(transfer, rootModelNode2);
+// QCOMPARE(rootModelNode2.childNodes().size(), 1);
+//
+// ModelNode rectNode2 = rootModelNode2.childNodes().at(0);
+// QCOMPARE(rectNode2.property("x").value().toDouble(), 10.0);
+// QCOMPARE(rectNode2.property("y").value().toDouble(), 20.0);
+// QCOMPARE(rectNode2.property("width").value().toDouble(), 30.0);
+// QCOMPARE(rectNode2.property("height").value().toDouble(), 40.0);
+// QCOMPARE(rectNode2.property("color").value().value<QColor>(), QColor("red"));
+// } catch (Exception &e) {
+// qDebug() << e;
+// QFAIL(e.description().toLatin1().data());
+// }
+}
+
+void TestCore::changeSubModel()
+{
+ QSKIP("must be refactored", SkipAll);
+// // create the orignal model:
+// QScopedPointer<Model> model1(create("import Qt 4.6; Rectangle { id: rootRect; Rectangle { id: rect2 }}"));
+// QVERIFY(model1.data());
+//
+// // get the model node for the component from the "original" model
+// ModelNode modelNode = model1->rootModelNode().childNodes().at(0);
+// QVERIFY(modelNode.isValid());
+// QCOMPARE(modelNode.id(), QString("rect2"));
+//
+// QList<QmlError> errors;
+// // Create a model on top of the component node:
+// TextModifier *subModifier = model1->createTextModifier(modelNode);
+// QScopedPointer<Model> subModel(Model::create(subModifier, model1->fileUrl(), &errors));
+// // Handle errors:
+// if (!errors.isEmpty()) {
+// printErrors(errors, "<sub model>");
+// qDebug() << "Data:";
+// qDebug() << subModifier->text();
+// QVERIFY(errors.isEmpty());
+// }
+//
+// // Check that changes in the model for the Component are reflected in both the model for the component, and the original model:
+// ModelNode subModelNode = subview->rootModelNode();
+// Q_ASSERT(subModelNode.isValid());
+// subModelNode.setId("AnotherId");
+// QCOMPARE(subModelNode.id(), QString("AnotherId"));
+// QCOMPARE(modelNode.id(), QString("AnotherId"));
+//
+// // Check that changes in the original model are reflected in the model for the component:
+// modelNode.setId("YetAnotherId");
+// QCOMPARE(subModelNode.id(), QString("YetAnotherId"));
+// QCOMPARE(modelNode.id(), QString("YetAnotherId"));
+}
+
+
+void TestCore::changeInlineComponent()
+{
+ // create the orignal model:
+ QSKIP("must be refactored", SkipAll);
+// QScopedPointer<Model> model1(create("import Qt 4.6; Rectangle { id: rootRect; Component { id: MyComponent; Rectangle { id: myComponentRect }}}"));
+// QVERIFY(model1.data());
+//
+// // get the model node for the component from the "original" model
+// ModelNode componentNode = model1->rootModelNode().childNodes().at(0);
+// QVERIFY(componentNode.isValid());
+// QCOMPARE(componentNode.id(), QString("MyComponent"));
+// QVERIFY(!componentNode.hasChildNodes()); // top model shouldn't go into subcomponents
+//
+// QScopedPointer<Model> componentModel(model1->createComponentModel(componentNode));
+//
+// ModelNode componentRootNode = componentview->rootModelNode();
+// QVERIFY(componentRootNode.isValid());
+// QCOMPARE(componentRootNode.type(), QString("Qt/Rectangle"));
+//
+// ModificationGroupToken token = componentModel->beginModificationGroup();
+// ModelNode childNode(componentRootNode.addChildNode("Qt/Rectangle", 4, 6, "data"));
+// QVERIFY(childNode.isValid());
+// componentModel->endModificationGroup(token);
+// QVERIFY(childNode.isValid());
+// QVERIFY(!componentRootNode.childNodes().isEmpty());
+// QVERIFY(componentRootNode.childNodes().first() == childNode);
+
+}
+
+void TestCore::changeImports()
+{
+ QSKIP("imports are disabled", SkipAll);
+// QScopedPointer<Model> model(Model::create("Qt/Rectangle"));
+// QVERIFY(model.data());
+// QVERIFY(view->rootModelNode().isValid());
+//
+// QSet<Import> imports = model->imports();
+// QCOMPARE(imports.size(), 1);
+// const Import import = imports.toModelNodeList().at(0);
+// QVERIFY(import.isLibraryImport());
+// QCOMPARE(import.url(), QUrl("Qt"));
+// QVERIFY(import.file().isEmpty());
+// QCOMPARE(import.version(), QString("4.6"));
+// QVERIFY(import.alias().isEmpty());
+//
+// Import newImport = Import::createFileImport("Namespaces_the_final_frontier", QString(), "MySpace");
+// model->addImport(newImport);
+// imports = model->imports();
+// QCOMPARE(imports.size(), 2);
+// QVERIFY(imports.contains(import));
+// QVERIFY(imports.contains(newImport));
+//
+// model->removeImport(newImport);
+// imports = model->imports();
+// QCOMPARE(imports.size(), 1);
+// QVERIFY(imports.contains(import));
+// QVERIFY(!imports.contains(newImport));
+}
+
+void TestCore::testIfChangePropertyIsRemoved()
+{
+ QSKIP("Fix me!!! See task BAUHAUS-139", SkipAll);
+// QScopedPointer<Model> model(create("import Qt 4.6; Item { Rectangle { x: 10; y: 10; } }"));
+// QVERIFY(model.data());
+// ModelNode rootModelNode(view->rootModelNode());
+// QVERIFY(rootModelNode.isValid());
+// ModelNode rectNode(rootModelNode.childNodes().at(0));
+// QVERIFY(rectNode.isValid());
+// ModelState newState = model->createModelState("new state");
+// QVERIFY(newState.isValid());
+// NodeState rectNodeState = newState.nodeState(rectNode);
+// QVERIFY(newState.isValid());
+// try {
+// rectNodeState.setPropertyValue("x", 100);
+// QVERIFY(rectNodeState.hasProperty("x"));
+// } catch (Exception &e) {
+// // ok.
+// }
+// rectNode.setPropertyValue("x", 15);
+// QVERIFY(newState.isValid());
+// NodeState rectNodeState2 = newState.nodeState(rectNode);
+// QVERIFY(rectNodeState2.isValid());
+// QVERIFY(rectNodeState.isValid());
+//
+// rectNode.setId("rect");
+// QVERIFY(rectNodeState2.isValid());
+// QVERIFY(rectNodeState.isValid());
+//
+// rectNodeState.setPropertyValue("x", 105);
+//
+// QVERIFY(rectNodeState2.isValid());
+// QVERIFY(rectNodeState.isValid());
+//
+// QCOMPARE(rectNodeState.property("x").value().toInt(), 105);
+//
+// rectNode.destroy();
+//
+// QVERIFY(!rectNodeState2.isValid());
+// QVERIFY(!rectNodeState.isValid());
+// QVERIFY(!rectNode.isValid());
+//
+// rectNode = rootModelNode.addChildNode("Qt/Rectangle", 4, 6, "data");
+// rectNode.setId("rect");
+// rectNodeState = newState.nodeState(rectNode);
+// rectNode.setPropertyValue("x", 10);
+//
+// QCOMPARE(rectNodeState.property("x").value().toInt(), 10);
+}
+
+void TestCore::testAnchorsAndStates()
+{
+ QSKIP("no states anymore", SkipAll);
+// QScopedPointer<Model> model(create("import Qt 4.6; Item { Rectangle { x: 10; y: 10; } }"));
+// QVERIFY(model.data());
+// ModelNode rootModelNode(view->rootModelNode());
+// QVERIFY(rootModelNode.isValid());
+// ModelNode rectNode(rootModelNode.childNodes().at(0));
+// QVERIFY(rectNode.isValid());
+//
+// NodeAnchors anchors(rectNode);
+// QVERIFY(!anchors.instanceHasAnchor(AnchorLine::Left));
+// QVERIFY(!anchors.instanceHasAnchor(AnchorLine::Top));
+// QVERIFY(!anchors.instanceHasAnchor(AnchorLine::Right));
+// QVERIFY(!anchors.instanceHasAnchor(AnchorLine::Bottom));
+// QVERIFY(!anchors.instanceHasAnchor(AnchorLine::HorizontalCenter));
+// QVERIFY(!anchors.instanceHasAnchor(AnchorLine::VerticalCenter));
+//
+// anchors.setAnchor(AnchorLine::Right, rootModelNode, AnchorLine::Right);
+// QVERIFY(anchors.instanceHasAnchor(AnchorLine::Right));
+// QCOMPARE(anchors.instanceAnchor(AnchorLine::Right).type(), AnchorLine::Right);
+// QCOMPARE(anchors.instanceAnchor(AnchorLine::Right).modelNode(), rootModelNode);
+//
+// anchors.setMargin(AnchorLine::Right, 10.0);
+// QCOMPARE(anchors.instanceMargin(AnchorLine::Right), 10.0);
+//
+// anchors.setMargin(AnchorLine::Right, 0.0);
+// QCOMPARE(anchors.instanceMargin(AnchorLine::Right), 0.0);
+//
+// anchors.setMargin(AnchorLine::Right, 20.0);
+//
+// QCOMPARE(1, rectNode.nodeStates().count());
+//
+// ModelState newState = model->createModelState("new state");
+//
+// QCOMPARE(2, rectNode.nodeStates().count());
+//
+// QCOMPARE(2, model->baseModelState().nodeStates().count());
+// QCOMPARE(2, newState.nodeStates().count());
+//
+// QVERIFY(newState.isValid());
+// QVERIFY(rectNode.isValid());
+// NodeState rectNodeState = newState.nodeState(rectNode);
+// QVERIFY(rectNodeState.isValid());
+}
+
+
+void TestCore::testStatesWithAnonymousTargets()
+{
+ QSKIP("no states anymore", SkipAll);
+ //QScopedPointer<Model> model(create("import Qt 4.6; Rectangle { states:[State{name:\"s1\";PropertyChanges{target:;x:20}}]Rectangle{x:10} } "));
+// ByteArrayModifier* modifier = 0;
+// Model *model_p = 0;
+// load("import Qt 4.6; Rectangle { states:[State{name:\"s1\";PropertyChanges{target:;x:20}}]Rectangle{x:10} } ",model_p,modifier);
+//
+// QScopedPointer<Model> model(model_p);
+// QVERIFY(model.data());
+// ModelNode rootModelNode(view->rootModelNode());
+// QVERIFY(rootModelNode.isValid());
+// ModelNode rectNode(rootModelNode.childNodes().at(0));
+// QVERIFY(rectNode.isValid());
+// // check item is anonymous
+// QVERIFY(rectNode.id().isEmpty());
+//
+// NodeState newState = model->modelStates().at(1).nodeStates().at(1);
+// QVERIFY(newState.isValid());
+// // check target is anonymous
+// QVERIFY(newState.modelNode().id().isEmpty());
+// // check base state has x=0
+// QCOMPARE(model->modelStates().at(0).nodeStates().at(1).property("x").value().toInt(),10);
+//
+// // now we "move" the rectangle, the model should force an id and generate a new propertychange
+// NodeStateChangeSet change( newState );
+// change.setPropertyValue("x",QVariant(30));
+// QList <NodeStateChangeSet> changeList;
+// changeList.append(change);
+// model->changeNodeStates(changeList);
+//
+// QCOMPARE(newState.modelNode().id(),QString("Rectangle1"));
+// QCOMPARE(rectNode.id(),QString("Rectangle1"));
+// QCOMPARE(newState.property("x").value().toInt(),30);
+//
+// // now we manually erase the new id and target
+// QString Text = modifier->text();
+// Text.remove(Text.indexOf(QString("id: Rectangle1;")),QString("id: Rectangle1;").length());
+// Text.remove(Text.indexOf(QString("Rectangle1")),QString("Rectangle1").length());
+//
+// // text2model again
+// reload(Text,modifier);
+//
+// // repeat checks
+// QVERIFY(model.data());
+// QVERIFY(rootModelNode.isValid());
+// QVERIFY(rectNode.isValid());
+// QVERIFY(rectNode.id().isEmpty());
+// QCOMPARE(model->modelStates().at(0).nodeStates().at(1).property("x").value().toInt(),10);
+//
+// // see what happened with the new state
+// QVERIFY(newState.isValid());
+// QVERIFY(newState.modelNode().id().isEmpty());
+
+}
+
+QTEST_MAIN(TestCore);
diff --git a/tests/auto/qml/qmldesigner/coretests/testcore.h b/tests/auto/qml/qmldesigner/coretests/testcore.h
new file mode 100644
index 0000000000..8c62f8427d
--- /dev/null
+++ b/tests/auto/qml/qmldesigner/coretests/testcore.h
@@ -0,0 +1,233 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef TESTCORE_H
+#define TESTCORE_H
+
+#include <QObject>
+
+#include <QtTest>
+
+
+class TestCore : public QObject
+{
+ Q_OBJECT
+public:
+ TestCore();
+
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+ //
+ // unit tests Model, ModelNode, NodeProperty, AbstractView
+ //
+ void testModelViewNotification();
+ void testModelCreateSubNode();
+ void testModelCreateCoreModel();
+ void testModelCreateInvalidSubNode();
+ void testModelCreateRect();
+ void testModelRemoveNode();
+ void testModelRootNode();
+ void testModelReorderSiblings();
+ void testModelAddAndRemoveProperty();
+ void testModelSliding();
+ void testModelBindings();
+ void testDynamicProperties();
+ void testModelDefaultProperties();
+ void testModelBasicOperations();
+ void testModelResolveIds();
+ void testModelNodeListProperty();
+ void testModelPropertyValueTypes();
+ void testModelNodeInHierarchy();
+
+ //
+ // unit tests MetaInfo, NodeMetaInfo, PropertyMetaInfo
+ //
+ void testMetaInfo();
+ void testMetaInfoDotProperties();
+ void testMetaInfoListProperties();
+
+ //
+ // unit tests Rewriter
+ //
+ void testRewriterView();
+ void testRewriterErrors();
+ void testRewriterChangeId();
+ void testRewriterChangeValueProperty();
+ void testRewriterRemoveValueProperty();
+ void testRewriterSignalProperty();
+ void testRewriterObjectTypeProperty();
+ void testRewriterPropertyChanges();
+ void testRewriterListModel();
+ void testRewriterAddProperty();
+ void testRewriterAddPropertyInNestedObject();
+ void testRewriterAddObjectDefinition();
+ void testRewriterAddStatesArray();
+ void testRewriterRemoveStates();
+ void testRewriterRemoveObjectDefinition();
+ void testRewriterRemoveScriptBinding();
+ void testRewriterNodeReparenting();
+ void testRewriterNodeReparentingWithTransaction();
+ void testRewriterMovingInOut();
+ void testRewriterMovingInOutWithTransaction();
+ void testRewriterComplexMovingInOut();
+ void testRewriterAutomaticSemicolonAfterChangedProperty();
+ void testRewriterTransaction();
+ void testRewriterId();
+ void testRewriterNodeReparentingTransaction1();
+ void testRewriterNodeReparentingTransaction2();
+ void testRewriterNodeReparentingTransaction3();
+ void testRewriterNodeReparentingTransaction4();
+ void testRewriterAddNodeTransaction();
+ void testRewriterComponentId();
+ void testRewriterPropertyDeclarations();
+ void testRewriterPropertyAliases();
+ void testRewriterPositionAndOffset();
+ void testRewriterFirstDefinitionInside();
+ void testRewriterComponentTextModifier();
+ void testRewriterPreserveType();
+ void testRewriterForArrayMagic();
+ void testRewriterWithSignals();
+ void testRewriterNodeSliding();
+
+ //
+ // unit tests QmlModelNodeFacade/QmlModelState
+ //
+
+ void testQmlModelStates();
+ void testQmlModelAddMultipleStates();
+ void testQmlModelRemoveStates();
+ void testQmlModelStatesInvalidForRemovedNodes();
+ void testQmlModelStateWithName();
+
+ //
+ // unit tests Instances
+ //
+ void testInstancesAttachToExistingModel();
+ void testInstancesStates();
+ void testInstancesIdResolution();
+ void testInstancesNotInScene();
+
+ //
+ // integration tests
+ //
+ void testBasicStates();
+ void testStates();
+ void testStatesBaseState();
+ void testStatesRewriter();
+ void testGradientsRewriter();
+ void testTypicalRewriterOperations();
+ void testBasicOperationsWithView();
+ void testQmlModelView();
+ void reparentingNode();
+ void reparentingNodeInModificationGroup();
+ void testRewriterTransactionRewriter();
+ void testCopyModelRewriter1();
+ void testCopyModelRewriter2();
+
+ //
+ // regression tests
+ //
+
+ void reparentingNodeLikeDragAndDrop();
+
+ //
+ // old tests
+ //
+
+ void loadEmptyCoreModel();
+ void saveEmptyCoreModel();
+ void loadAttributesInCoreModel();
+ void saveAttributesInCoreModel();
+ void loadComponentPropertiesInCoreModel();
+ void loadSubItems();
+
+ void attributeChangeSynchronizer();
+ void attributeAdditionSynchronizer();
+ void attributeRemovalSynchronizer();
+ void childAddedSynchronizer();
+ void childRemovedSynchronizer();
+ void childReplacedSynchronizer();
+
+ void createInvalidCoreModel();
+
+ void loadQml();
+ void subItemMetaInfo();
+
+
+
+
+ void defaultPropertyValues();
+
+ // Detailed tests for the rewriting:
+
+ // Anchor tests:
+ void loadAnchors();
+ void changeAnchors();
+ void anchorToSibling();
+ void anchorsAndStates();
+ void removeFillAnchorByDetaching();
+ void removeFillAnchorByChanging();
+ void removeCenteredInAnchorByDetaching();
+
+ void sideIndex();
+
+ // Property bindings:
+ void loadPropertyBinding();
+ void changePropertyBinding();
+
+ void loadObjectPropertyBinding();
+
+ // Bigger tests:
+ void loadWelcomeScreen();
+
+ // Object bindings as properties:
+ void loadGradient();
+ void changeGradientId();
+
+ // Copy & Paste:
+ void copyAndPasteInSingleModel();
+ void copyAndPasteBetweenModels();
+
+ // Editing inline Components
+ void changeSubModel();
+ void changeInlineComponent();
+
+ // Testing imports
+ void changeImports();
+
+ void testIfChangePropertyIsRemoved();
+ void testAnchorsAndStates();
+
+ // Testing states
+ void testStatesWithAnonymousTargets();
+};
+
+#endif // TESTCORE_H
diff --git a/tests/auto/qml/qmldesigner/coretests/testrewriterview.cpp b/tests/auto/qml/qmldesigner/coretests/testrewriterview.cpp
new file mode 100644
index 0000000000..5a3dae01d2
--- /dev/null
+++ b/tests/auto/qml/qmldesigner/coretests/testrewriterview.cpp
@@ -0,0 +1,113 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "abstractproperty.h"
+#include "nodeproperty.h"
+#include "testrewriterview.h"
+#include <QObject>
+
+using namespace QmlDesigner;
+using namespace QmlDesigner::Internal;
+
+bool TestModelToTextMerger::isNodeScheduledForRemoval(const ModelNode &node) const
+{
+ foreach (const RewriteAction *action, scheduledRewriteActions()) {
+ if (RemoveNodeRewriteAction const *removeAction = action->asRemoveNodeRewriteAction()) {
+ if (removeAction->node() == node)
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool TestModelToTextMerger::isNodeScheduledForAddition(const ModelNode &node) const
+{
+ foreach (const RewriteAction *action, scheduledRewriteActions()) {
+ if (AddPropertyRewriteAction const *addPropertyAction = action->asAddPropertyRewriteAction()) {
+ const AbstractProperty property = addPropertyAction->property();
+ if (property.isNodeProperty() && property.toNodeProperty().modelNode() == node)
+ return true;
+ else if (property.isNodeListProperty() && property.toNodeListProperty().toModelNodeList().contains(node))
+ return true;
+ } else if (ChangePropertyRewriteAction const *changePropertyAction = action->asChangePropertyRewriteAction()) {
+ const AbstractProperty property = changePropertyAction->property();
+ if (property.isNodeProperty() && property.toNodeProperty().modelNode() == node)
+ return true;
+ else if (property.isNodeListProperty() && property.toNodeListProperty().toModelNodeList().contains(node))
+ return true;
+ }
+
+ }
+
+ return false;
+}
+
+VariantProperty TestModelToTextMerger::findAddedVariantProperty(const VariantProperty &property) const
+{
+ foreach (const RewriteAction *action, scheduledRewriteActions()) {
+ if (AddPropertyRewriteAction const * addPropertyAction = action->asAddPropertyRewriteAction()) {
+ const AbstractProperty candidate = addPropertyAction->property();
+
+ if (property.isVariantProperty() && property.toVariantProperty() == property)
+ return property.toVariantProperty();
+ }
+ }
+
+ return VariantProperty();
+}
+
+TestRewriterView::TestRewriterView(QObject *parent) : RewriterView(RewriterView::Validate, parent)
+{
+}
+
+bool TestRewriterView::isModificationGroupActive() const
+{
+ return RewriterView::isModificationGroupActive();
+}
+
+void TestRewriterView::setModificationGroupActive(bool active)
+{
+ RewriterView::setModificationGroupActive(active);
+}
+
+void TestRewriterView::applyModificationGroupChanges()
+{
+ RewriterView::applyModificationGroupChanges();
+}
+
+Internal::TestModelToTextMerger *TestRewriterView::modelToTextMerger() const
+{
+ return static_cast<Internal::TestModelToTextMerger*> (RewriterView::modelToTextMerger());
+}
+
+Internal::TextToModelMerger *TestRewriterView::textToModelMerger() const
+{
+ return RewriterView::textToModelMerger();
+}
diff --git a/tests/auto/qml/qmldesigner/coretests/testrewriterview.h b/tests/auto/qml/qmldesigner/coretests/testrewriterview.h
new file mode 100644
index 0000000000..2483a37950
--- /dev/null
+++ b/tests/auto/qml/qmldesigner/coretests/testrewriterview.h
@@ -0,0 +1,68 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef TESTREWRITERVIEW_H
+#define TESTREWRITERVIEW_H
+
+#include <rewriterview.h>
+#include <model/modeltotextmerger.h>
+
+namespace QmlDesigner {
+
+namespace Internal {
+
+class TestModelToTextMerger : public ModelToTextMerger
+{
+public:
+ bool isNodeScheduledForRemoval(const ModelNode &node) const;
+ bool isNodeScheduledForAddition(const ModelNode &node) const;
+ VariantProperty findAddedVariantProperty(const VariantProperty &property) const;
+};
+
+} // Internal
+
+class TestRewriterView : public RewriterView
+{
+
+Q_OBJECT
+
+public:
+ TestRewriterView(QObject *parent = 0);
+
+ Internal::TestModelToTextMerger *modelToTextMerger() const;
+ Internal::TextToModelMerger *textToModelMerger() const;
+
+ bool isModificationGroupActive() const;
+ void setModificationGroupActive(bool active);
+ void applyModificationGroupChanges();
+};
+
+} // QmlDesigner
+
+#endif // TESTREWRITERVIEW_H
diff --git a/tests/auto/qml/qmldesigner/data/fx/attributes.qml b/tests/auto/qml/qmldesigner/data/fx/attributes.qml
new file mode 100644
index 0000000000..79738ef98c
--- /dev/null
+++ b/tests/auto/qml/qmldesigner/data/fx/attributes.qml
@@ -0,0 +1,8 @@
+import Qt 4.6
+
+Item {
+ id: id;
+ x: 300;
+ visible: true;
+ scale: 0.5
+}
diff --git a/tests/auto/qml/qmldesigner/data/fx/bigtest.qml b/tests/auto/qml/qmldesigner/data/fx/bigtest.qml
new file mode 100644
index 0000000000..8f19af47d4
--- /dev/null
+++ b/tests/auto/qml/qmldesigner/data/fx/bigtest.qml
@@ -0,0 +1,78 @@
+import Qt 4.6
+
+Item {
+ width: 640;
+ height: 480;
+ Rectangle {
+ width: 295;
+ height: 264;
+ color: "#009920";
+ x: 22;
+ y: 31;
+ id: Rectangle_1;
+ Rectangle {
+ width: 299;
+ color: "#009920";
+ x: 109;
+ height: 334;
+ y: 42;
+ id: Rectangle_3;
+ Rectangle {
+ color: "#009920";
+ height: 209;
+ width: 288;
+ x: 98;
+ y: 152;
+ id: Rectangle_5;
+ }
+
+
+ Image {
+ source: "qrc:/fxplugin/images/template_image.png";
+ height: 379;
+ x: -154;
+ width: 330;
+ y: -31;
+ id: Image_1;
+ }Image {
+ width: 293;
+ x: 33;
+ height: 172;
+ y: 39;
+ source: "qrc:/fxplugin/images/template_image.png";
+ id: Image_2;
+ }}
+
+ }
+ Rectangle {
+ width: 238;
+ height: 302;
+ x: 360;
+ y: 42;
+ color: "#009920";
+ id: Rectangle_2;
+ Image {
+ source: "qrc:/fxplugin/images/template_image.png";
+ x: -40;
+ y: 12;
+ width: 281;
+ height: 280;
+ id: Image_3;
+ }}
+ Rectangle {
+ height: 206;
+ width: 276;
+ color: "#009920";
+ x: 4;
+ y: 234;
+ id: Rectangle_4;
+ }
+ Text {
+ text: "text";
+ width: 80;
+ height: 20;
+ x: 71;
+ y: 15;
+ id: Text_1;
+ }
+}
diff --git a/tests/auto/qml/qmldesigner/data/fx/components.qml b/tests/auto/qml/qmldesigner/data/fx/components.qml
new file mode 100644
index 0000000000..4e0bd8ae4e
--- /dev/null
+++ b/tests/auto/qml/qmldesigner/data/fx/components.qml
@@ -0,0 +1,26 @@
+import Qt 4.6
+
+Rectangle {
+ width: 100
+ height: 100
+
+
+ Component {
+ id: componentOne
+ Rectangle { width: 80; height: 80; color: "lightsteelblue" }
+ }
+
+ Component {
+ id: componentTwo
+ Rectangle { width: 80; height: 80; color: "lightsteelblue" }
+ }
+
+ Loader {
+ x: 40
+ y: 40
+ width: 20
+ height: 20
+ sourceComponent: componentTwo
+ }
+
+ } \ No newline at end of file
diff --git a/tests/auto/qml/qmldesigner/data/fx/empty.qml b/tests/auto/qml/qmldesigner/data/fx/empty.qml
new file mode 100644
index 0000000000..1472f01bfc
--- /dev/null
+++ b/tests/auto/qml/qmldesigner/data/fx/empty.qml
@@ -0,0 +1,4 @@
+import Qt 4.6
+
+Item {
+}
diff --git a/tests/auto/qml/qmldesigner/data/fx/helloworld.qml b/tests/auto/qml/qmldesigner/data/fx/helloworld.qml
new file mode 100644
index 0000000000..0c1ea91939
--- /dev/null
+++ b/tests/auto/qml/qmldesigner/data/fx/helloworld.qml
@@ -0,0 +1,76 @@
+import Qt 4.6
+
+Rectangle {
+ width: 300
+ height: 300
+ id: Page
+ color: "#ffff00"
+ Rectangle {
+ width: 183
+ x: 31
+ objectName: "Rectangle_1"
+ y: 76
+ rotation: -20
+ height: 193
+ color: "#ffaa00"
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "#ffaa00" }
+ GradientStop { position: 1.0; color: "#ffaa7f" }
+ }
+ Text {
+ width: 78
+ x: 11
+ y: 10
+ height: 20
+ id: HelloText2
+ text: "Hello QmlGraphics!"
+ }
+ Text {
+ width: 85
+ x: 11
+ objectName: "xt5"
+ y: 165
+ height: 18
+ id: HelloText5
+ text: "blah!!!!!"
+ }
+ Image {
+ width: 422
+ x: 47
+ objectName: "Image_1"
+ opacity: 0.6
+ y: 45.2
+ rotation: 0
+ scale: 0.2
+ height: 498
+ source: "http://farm4.static.flickr.com/3002/2722850010_02b62a030f_m.jpg"
+ smooth: true
+ fillMode: "Tile"
+ }
+ Text {
+ width: 100
+ x: 178
+ y: 11.64
+ rotation: 90
+ height: 20
+ id: HelloText11
+ text: "Hello QmlGraphics!"
+ }
+ }
+ Text {
+ width: 100
+ x: 10
+ y: 13
+ height: 20
+ id: HelloText3
+ text: "Hello QmlGraphics!"
+ }
+ Text {
+ width: 127
+ x: 163
+ y: 184
+ height: 106
+ id: HelloText4
+ text: "Hello QmlGraphics!"
+ }
+}
diff --git a/tests/auto/qml/qmldesigner/data/fx/image.qml b/tests/auto/qml/qmldesigner/data/fx/image.qml
new file mode 100644
index 0000000000..1db0d811c2
--- /dev/null
+++ b/tests/auto/qml/qmldesigner/data/fx/image.qml
@@ -0,0 +1,10 @@
+import Qt 4.6
+
+Rectangle {
+ color: "blue";
+ width: 640;
+ height: 480;
+ Image {
+ source: "../qt-logo.png"
+ }
+}
diff --git a/tests/auto/qml/qmldesigner/data/fx/properties.qml b/tests/auto/qml/qmldesigner/data/fx/properties.qml
new file mode 100644
index 0000000000..03d8ca5063
--- /dev/null
+++ b/tests/auto/qml/qmldesigner/data/fx/properties.qml
@@ -0,0 +1,5 @@
+import Qt 4.6
+
+Item {
+ property bool pushed
+}
diff --git a/tests/auto/qml/qmldesigner/data/fx/selectiontest.qml b/tests/auto/qml/qmldesigner/data/fx/selectiontest.qml
new file mode 100644
index 0000000000..631a0b6999
--- /dev/null
+++ b/tests/auto/qml/qmldesigner/data/fx/selectiontest.qml
@@ -0,0 +1,39 @@
+import Qt 4.6
+
+Item {
+ id: RootItem
+ width: 640
+ height: 480
+Rectangle {
+ height: 100;
+ x: 104;
+ y: 178;
+ color: "#ffffff";
+ width: 100;
+ id: Rectangle_1;
+ }
+Rectangle {
+ x: 110;
+ y: 44;
+ color: "#ffffff";
+ height: 100;
+ width: 100;
+ id: Rectangle_2;
+ }
+Rectangle {
+ width: 100;
+ color: "#ffffff";
+ height: 100;
+ x: 323;
+ y: 160;
+ id: Rectangle_3;
+ }
+Rectangle {
+ color: "#ffffff";
+ width: 100;
+ height: 100;
+ x: 233;
+ y: 293;
+ id: Rectangle_4;
+ }
+}
diff --git a/tests/auto/qml/qmldesigner/data/fx/states.qml b/tests/auto/qml/qmldesigner/data/fx/states.qml
new file mode 100644
index 0000000000..6c35f4ee2d
--- /dev/null
+++ b/tests/auto/qml/qmldesigner/data/fx/states.qml
@@ -0,0 +1,59 @@
+import Qt 4.6
+
+Item {
+ id: theRootItem;
+ width: 400;
+ height: 400;
+ Rectangle {
+ width: 157;
+ height: 120;
+ x: 145;
+ y: 157;
+ id: Rectangle_1;
+ }
+
+ Rectangle {
+ x: 49;
+ y: 6;
+ width: 100;
+ id: Rectangle_2;
+ color: "#009920";
+ height: 100;
+ }
+
+ states: [
+ State {
+ name: "State1";
+ when: destination === "one";
+
+ PropertyChanges {
+ target: Rectangle_2;
+ height: 200
+ width: 300
+ }
+ },
+ State {
+ name: "State2";
+ when: false == true;
+ },
+ State {
+ name: "State3";
+ PropertyChanges {
+ target: Rectangle_2;
+ x: 200
+ y: 300
+ }
+ }
+ ]
+
+ transitions: [
+ Transition {
+ NumberAnimation {
+ properties: "width, height"
+ easing: "OutQuad"
+ duration: 500
+ }
+ }
+ ]
+}
+
diff --git a/tests/auto/qml/qmldesigner/data/fx/subitems/SubItem.qml b/tests/auto/qml/qmldesigner/data/fx/subitems/SubItem.qml
new file mode 100644
index 0000000000..97b14f6ef4
--- /dev/null
+++ b/tests/auto/qml/qmldesigner/data/fx/subitems/SubItem.qml
@@ -0,0 +1,14 @@
+import Qt 4.6
+
+Rectangle {
+ property string text
+
+ width : {toprect.width}
+ height : 20
+ color : "blue"
+ Text {
+ width : 100
+ color : "white"
+ text : parent.text
+ }
+}
diff --git a/tests/auto/qml/qmldesigner/data/fx/topitem.qml b/tests/auto/qml/qmldesigner/data/fx/topitem.qml
new file mode 100644
index 0000000000..dc5f10bc4d
--- /dev/null
+++ b/tests/auto/qml/qmldesigner/data/fx/topitem.qml
@@ -0,0 +1,17 @@
+import Qt 4.6
+import Qt 4.6 as Qt46
+import "subitems"
+import "subitems" as Subdir
+
+Qt46.Rectangle {
+ id : "toprect"
+ width : 100
+ height : 50
+ SubItem {
+ text: "item1"
+ }
+ Subdir.SubItem {
+ text : "item2"
+ y: 25
+ }
+}
diff --git a/tests/auto/qml/qmldesigner/data/qt-logo.png b/tests/auto/qml/qmldesigner/data/qt-logo.png
new file mode 100644
index 0000000000..5ab3a1b0c4
--- /dev/null
+++ b/tests/auto/qml/qmldesigner/data/qt-logo.png
Binary files differ
diff --git a/tests/auto/qml/qmldesigner/data/qwidget/test.qml b/tests/auto/qml/qmldesigner/data/qwidget/test.qml
new file mode 100644
index 0000000000..6f0fb82554
--- /dev/null
+++ b/tests/auto/qml/qmldesigner/data/qwidget/test.qml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<QWidget id="Form" x="300" y="200" width="455" height="376">
+ <QPushButton id="pushButton" x="10" y="30" width="75" height="25">
+ <text><?i18n?>PushButton</text>
+ </QPushButton>
+ <QPushButton id="toolButton" x="20" y="170" width="27" height="23">
+ <text><?i18n?>...</text>
+ </QPushButton>
+ <QPushButton id="pushButton_2" x="180" y="170" width="75" height="25">
+ <text><?i18n?>PushButton</text>
+ </QPushButton>
+ <QPushButton id="pushButton_3" x="180" y="200" width="75" height="25">
+ <text><?i18n?>PushButton</text>
+ </QPushButton>
+ <QPushButton id="pushButton_4" x="180" y="230" width="75" height="25">
+ <text><?i18n?>PushButton</text>
+ </QPushButton>
+ <QPushButton id="pushButton_5" x="180" y="260" width="75" height="25">
+ <text><?i18n?>PushButton</text>
+ </QPushButton>
+ <QPushButton id="pushButton_6" x="180" y="290" width="75" height="25">
+ <text><?i18n?>PushButton</text>
+ </QPushButton>
+ <QPushButton id="pushButton_7" x="180" y="330" width="75" height="25">
+ <text><?i18n?>PushButton</text>
+ </QPushButton>
+</QWidget>
diff --git a/tests/auto/qml/qmldesigner/data/testfiles.qrc b/tests/auto/qml/qmldesigner/data/testfiles.qrc
new file mode 100644
index 0000000000..b607beb73f
--- /dev/null
+++ b/tests/auto/qml/qmldesigner/data/testfiles.qrc
@@ -0,0 +1,11 @@
+<RCC>
+ <qresource prefix="/" >
+ <file>fx/attributes.qml</file>
+ <file>fx/empty.qml</file>
+ <file>fx/helloworld.qml</file>
+ <file>fx/properties.qml</file>
+ <file>qwidget/test.qml</file>
+ <file>fx/topitem.qml</file>
+ <file>fx/subitems/SubItem.qml</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/qml/qmldesigner/propertyeditortests/propertyeditortests.pro b/tests/auto/qml/qmldesigner/propertyeditortests/propertyeditortests.pro
new file mode 100644
index 0000000000..9daa18c38f
--- /dev/null
+++ b/tests/auto/qml/qmldesigner/propertyeditortests/propertyeditortests.pro
@@ -0,0 +1,24 @@
+include(../../../../../src/plugins/qmldesigner/config.pri)
+include(../../../../../src/plugins/qmldesigner/components/propertyeditor/propertyeditor.pri)
+
+QT += testlib \
+ script \
+ declarative
+DESTDIR = $$DESIGNER_BINARY_DIRECTORY
+include(../../../../../src/plugins/qmldesigner/core/core.pri)
+
+DEPENDPATH += ../../../../../src/plugins/qmldesigner/core/include
+DEPENDPATH += ..
+
+TARGET = tst_propertyeditor
+CONFIG += console
+CONFIG -= app_bundle
+TEMPLATE = app
+SOURCES += testpropertyeditor.cpp
+SOURCES += ../testview.cpp
+HEADERS += testpropertyeditor.h
+HEADERS += ../testview.h
+RESOURCES += ../data/testfiles.qrc
+
+HEADERS -= allpropertiesbox.h
+SOURCES -= allpropertiesbox.cpp
diff --git a/tests/auto/qml/qmldesigner/propertyeditortests/testpropertyeditor.cpp b/tests/auto/qml/qmldesigner/propertyeditortests/testpropertyeditor.cpp
new file mode 100644
index 0000000000..b8c3166f2c
--- /dev/null
+++ b/tests/auto/qml/qmldesigner/propertyeditortests/testpropertyeditor.cpp
@@ -0,0 +1,370 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "testpropertyeditor.h"
+#include "../testview.h"
+
+#include <memory>
+#include <cstdio>
+
+#include <metainfo.h>
+#include <model.h>
+#include <modelnode.h>
+#include <variantproperty.h>
+#include <bytearraymodifier.h>
+#include <invalididexception.h>
+#include <invalidmodelnodeexception.h>
+#include <propertyeditor.h>
+#include <QDebug>
+#include <QDir>
+#include <QSpinBox>
+#include <QLineEdit>
+#include <QStackedWidget>
+#include <QmlView>
+#include <QVariant>
+
+using namespace QmlDesigner;
+
+#include "../common/statichelpers.cpp"
+
+
+static void inspectPropertyEditor(ModelNode node, QWidget* propWidget)
+{
+ if (!propWidget)
+ return;
+
+ QStackedWidget * stackedWidget = qobject_cast<QStackedWidget *> (propWidget);
+ QVERIFY(stackedWidget);
+ QmlView *view = qobject_cast<QmlView*>(stackedWidget->currentWidget());
+ QVERIFY(view);
+
+ QLineEdit * idLineEdit = view->findChild<QLineEdit* >("IdLineEdit");
+
+ if (!idLineEdit)
+ return ;
+
+ QCOMPARE(idLineEdit->text(), node.id());
+
+ if (node.hasProperty("width")) {
+ QSpinBox * widthSpinBox = view->findChild<QSpinBox* >("WidthSpinBox");
+ QVERIFY(widthSpinBox);
+ QCOMPARE(widthSpinBox->value(), node.variantProperty("width").value().toInt());
+ }
+
+ if (node.hasProperty("height")) {
+ QSpinBox * heightSpinBox = view->findChild<QSpinBox* >("HeightSpinBox");
+ QVERIFY(heightSpinBox);
+ QCOMPARE(heightSpinBox->value(), node.variantProperty("height").value().toInt());// this can be dangerous
+ }
+
+ if (node.hasProperty("x")) {
+ QSpinBox * xSpinBox = view->findChild<QSpinBox* >("XSpinBox");
+ QVERIFY(xSpinBox);
+ QCOMPARE(xSpinBox->value(), node.variantProperty("x").value().toInt()); // this can be dangerous
+ }
+
+ if (node.hasProperty("y")) {
+ QSpinBox * ySpinBox = view->findChild<QSpinBox* >("YSpinBox");
+ QVERIFY(ySpinBox);
+ QCOMPARE(ySpinBox->value(), node.variantProperty("y").value().toInt());
+ }
+}
+static void selectThrough(ModelNode node, QWidget* propWidget = 0)
+{
+ QVERIFY(node.isValid());
+ int numberOfProperties = node.propertyNames().count();
+ QList<AbstractProperty> properties = node.properties();
+ node.view()->clearSelectedModelNodes();
+ node.view()->selectModelNode(node);
+ QString name = node.id();
+ qApp->processEvents();
+ QTest::qSleep(100);
+ qApp->processEvents();
+ QTest::qSleep(100);
+ qApp->processEvents();
+ inspectPropertyEditor(node, propWidget);
+ //selecting should not effect any properties at all!
+ QCOMPARE(node.propertyNames().count(), numberOfProperties);
+ foreach (const AbstractProperty &property, properties)
+ if (property.isVariantProperty()) {
+ QCOMPARE(property.toVariantProperty().value(), node.variantProperty(property.name()).value());
+ }
+ QList<ModelNode> childNodes = node.allDirectSubModelNodes();
+ foreach (const ModelNode &childNode, childNodes)
+ selectThrough(childNode, propWidget);
+}
+
+static QWidget * setupPropertyEditor(QWidget *widget, Model *model)
+{
+ PropertyEditor *properties = new PropertyEditor(widget);
+
+ QString qmlDir = QDir::cleanPath(qApp->applicationDirPath() + QString("/../shared/propertyeditor/"));
+ qDebug() << qmlDir;
+ properties->setQmlDir(qmlDir);
+ model->attachView(properties);
+ QWidget *pane = properties->createPropertiesPage();
+ pane->setParent(widget);
+ widget->show();
+ widget->resize(300, 800);
+ qApp->processEvents();
+ pane->resize(300, 800);
+ pane->move(0,0);
+ qApp->processEvents();
+ QTest::qSleep(100);
+
+ return pane;
+}
+
+static void loadFileAndTest(const QString &fileName)
+{
+ QFile file(fileName);
+ QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));
+
+ QList<QmlError> errors;
+ //std::auto_ptr<ByteArrayModifier> modifier1(ByteArrayModifier::create(QString(file.readAll())));
+ //std::auto_ptr<Model> model1(Model::create(modifier1.get(), QUrl::fromLocalFile(file.fileName()), &errors));
+
+ QScopedPointer<Model> model1(Model::create("Item"));
+ QVERIFY(model1.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model1->attachView(view.data());
+
+
+ QVERIFY(model1.data());
+
+ std::auto_ptr<QWidget> widget(new QWidget());
+ QWidget *propWidget = setupPropertyEditor(widget.get(), model1.data());
+
+ selectThrough(view->rootModelNode(), propWidget);
+}
+
+TestPropertyEditor::TestPropertyEditor()
+ : QObject()
+{
+}
+
+void TestPropertyEditor::initTestCase()
+{
+ qInstallMsgHandler(testMessageOutput);
+ MetaInfo::setPluginPaths(pluginPaths());
+ Exception::setShouldAssert(false);
+}
+
+
+void TestPropertyEditor::createCoreModel()
+{
+ try {
+ std::auto_ptr<QWidget> widget(new QWidget());
+
+ QScopedPointer<Model> model(Model::create("import Qt 4.6\n Item {}"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ QVERIFY(model.data());
+ setupPropertyEditor(widget.get(), model.data());
+
+ QVERIFY(view->rootModelNode().isValid());
+ int numberOfProperties = view->rootModelNode().propertyNames().count();
+ selectThrough(view->rootModelNode());
+ QCOMPARE(view->rootModelNode().propertyNames().count(), numberOfProperties);
+ } catch (Exception &exception) {
+ QFAIL("Exception thrown");
+ }
+}
+
+void TestPropertyEditor::loadEmptyCoreModel()
+{
+ /* QList<QmlError> errors;
+ QFile file(":/fx/empty.qml");
+ QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));
+
+ std::auto_ptr<QWidget> widget(new QWidget());
+ std::auto_ptr<ByteArrayModifier> modifier1(ByteArrayModifier::create(QString(file.readAll())));
+ std::auto_ptr<Model> model1(Model::create(modifier1.get(), QUrl(), &errors));
+ foreach (const QmlError &error, errors)
+ QFAIL(error.toString().toLatin1());
+ QVERIFY(model1.get());
+ setupPropertyEditor(widget.get(), model1.get());
+
+ selectThrough(model1->rootNode());
+
+ std::auto_ptr<ByteArrayModifier> modifier2(ByteArrayModifier::create("import Qt 4.6\n Item{}"));
+ std::auto_ptr<Model> model2(Model::create(modifier2.get(), QUrl(), &errors));
+ foreach (const QmlError &error, errors)
+ QFAIL(error.toString().toLatin1());
+ QVERIFY(model2.get());
+
+ QVERIFY(compareTree(model1->rootNode(), model2->rootNode()));*/
+}
+
+void TestPropertyEditor::createSubNode()
+{
+ std::auto_ptr<QWidget> widget(new QWidget());
+
+ QScopedPointer<Model> model(Model::create("import Qt 4.6\n Item {}"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ setupPropertyEditor(widget.get(), model.data());
+ QVERIFY(view->rootModelNode().isValid());
+ selectThrough(view->rootModelNode());
+ ModelNode childNode = view->rootModelNode().addChildNode("Qt/Rectangle", 4, 6, "data");
+ QVERIFY(childNode.isValid());
+ QVERIFY(view->rootModelNode().allDirectSubModelNodes().contains(childNode));
+ QVERIFY(childNode.parentProperty().parentModelNode() == view->rootModelNode());
+ QCOMPARE(childNode.type(), QString("Qt/Rectangle"));
+
+ selectThrough(childNode);
+
+ QVERIFY(childNode.id().isEmpty());
+
+ childNode.setId("Blah");
+ QCOMPARE(childNode.id(), QString("Blah"));
+
+
+ QCOMPARE(childNode.id(), QString("Blah"));
+}
+
+void TestPropertyEditor::createRect()
+{
+ try {
+
+ std::auto_ptr<QWidget> widget(new QWidget());
+
+ QScopedPointer<Model> model(Model::create("import Qt 4.6\n Item {}"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ setupPropertyEditor(widget.get(), model.data());
+
+ QVERIFY(view->rootModelNode().isValid());
+
+ //selectThrough(view->rootModelNode());
+
+ ModelNode childNode = view->rootModelNode().addChildNode("Qt/Rectangle", 4, 6, "data");
+ QVERIFY(childNode.isValid());
+ QVERIFY(view->rootModelNode().allDirectSubModelNodes().contains(childNode));
+ QVERIFY(childNode.parentProperty().parentModelNode() == view->rootModelNode());
+ QCOMPARE(childNode.type(), QString("Qt/Rectangle"));
+
+ QVERIFY(childNode.id().isEmpty());
+
+ childNode.setId("Rect01");
+ QCOMPARE(childNode.id(), QString("Rect01"));
+
+ childNode.variantProperty("x") = 100;
+ QCOMPARE(QmlObjectNode(childNode).instanceValue("x").toInt(), 100);
+ childNode.variantProperty("y") = 100;
+ QCOMPARE(QmlObjectNode(childNode).instanceValue("y").toInt(), 100);
+ childNode.variantProperty("width") = 100;
+ QCOMPARE(QmlObjectNode(childNode).instanceValue("width").toInt(), 100);
+ childNode.variantProperty("height") = 100;
+ QCOMPARE(QmlObjectNode(childNode).instanceValue("height").toInt(), 100);
+
+ selectThrough(childNode);
+
+ QCOMPARE(childNode.propertyNames().count(), 4);
+ QCOMPARE(childNode.variantProperty("scale").value(), QVariant());
+
+ } catch (Exception &exception) {
+ QFAIL("Exception thrown");
+ }
+}
+
+void TestPropertyEditor::removeNode()
+{
+ std::auto_ptr<QWidget> widget(new QWidget());
+
+ QScopedPointer<Model> model(Model::create("import Qt 4.6\n Item {}"));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView);
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ setupPropertyEditor(widget.get(), model.data());
+
+ QCOMPARE(view->rootModelNode().allDirectSubModelNodes().count(), 0);
+
+ selectThrough(view->rootModelNode());
+
+ ModelNode childNode = view->rootModelNode().addChildNode("Qt/Rectangle", 4, 6, "data");
+ QVERIFY(childNode.isValid());
+ QCOMPARE(view->rootModelNode().allDirectSubModelNodes().count(), 1);
+ QVERIFY(view->rootModelNode().allDirectSubModelNodes().contains(childNode));
+ QVERIFY(childNode.parentProperty().parentModelNode() == view->rootModelNode());
+
+ selectThrough(childNode);
+
+ ModelNode subChildNode = childNode.addChildNode("Qt/Rectangle", 4, 6, "data");
+ QVERIFY(subChildNode.isValid());
+ QCOMPARE(childNode.allDirectSubModelNodes().count(), 1);
+ QVERIFY(childNode.allDirectSubModelNodes().contains(subChildNode));
+ QVERIFY(subChildNode.parentProperty().parentModelNode() == childNode);
+
+ selectThrough(subChildNode);
+
+ childNode.destroy();
+
+ QCOMPARE(view->rootModelNode().allDirectSubModelNodes().count(), 0);
+ QVERIFY(!view->rootModelNode().allDirectSubModelNodes().contains(childNode));
+ QVERIFY(!childNode.isValid());
+ QVERIFY(!subChildNode.isValid());
+}
+
+void TestPropertyEditor::loadWelcomeScreen()
+{
+ loadFileAndTest(QCoreApplication::applicationDirPath() + "/../shared/welcomescreen.qml");
+}
+
+void TestPropertyEditor::loadHelloWorld()
+{
+ loadFileAndTest(":/fx/helloworld.qml");
+}
+
+
+
+void TestPropertyEditor::cleanupTestCase()
+{
+ MetaInfo::clearGlobal();
+}
+
+
+QTEST_MAIN(TestPropertyEditor);
diff --git a/tests/auto/qml/qmldesigner/propertyeditortests/testpropertyeditor.h b/tests/auto/qml/qmldesigner/propertyeditortests/testpropertyeditor.h
new file mode 100644
index 0000000000..bb1e3dfd37
--- /dev/null
+++ b/tests/auto/qml/qmldesigner/propertyeditortests/testpropertyeditor.h
@@ -0,0 +1,57 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef TESTPROPERTYEDITOR_H
+#define TESTPROPERTYEDITOR_H
+
+#include <QObject>
+
+#include <QtTest>
+
+
+class TestPropertyEditor : public QObject
+{
+ Q_OBJECT
+public:
+ TestPropertyEditor();
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+ void createCoreModel();
+ void loadEmptyCoreModel();
+
+ void createSubNode();
+ void createRect();
+ void removeNode();
+ void loadWelcomeScreen();
+ void loadHelloWorld();
+};
+
+#endif // TESTPROPERTYEDITOR_H
diff --git a/tests/auto/qml/qmldesigner/qmldesigner.pro b/tests/auto/qml/qmldesigner/qmldesigner.pro
new file mode 100644
index 0000000000..eaeb28fdae
--- /dev/null
+++ b/tests/auto/qml/qmldesigner/qmldesigner.pro
@@ -0,0 +1,5 @@
+TEMPLATE = subdirs
+
+SUBDIRS += coretests
+SUBDIRS += propertyeditortests
+SUBDIRS += bauhaustests
diff --git a/tests/auto/qml/qmldesigner/testview.cpp b/tests/auto/qml/qmldesigner/testview.cpp
new file mode 100644
index 0000000000..b1e424d9db
--- /dev/null
+++ b/tests/auto/qml/qmldesigner/testview.cpp
@@ -0,0 +1,213 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "testview.h"
+
+#include <QtDebug>
+#include <modelnode.h>
+#include <model.h>
+#include <modelnode.h>
+#include <nodeabstractproperty.h>
+#include <nodelistproperty.h>
+#include <qtestcase.h>
+
+TestView::TestView(QObject *parent)
+ : QmlDesigner::QmlModelView(parent)
+{
+}
+
+void TestView::modelAttached(QmlDesigner::Model *model)
+{
+ QmlDesigner::QmlModelView::modelAttached(model);
+ m_methodCalls += MethodCall("modelAttached", QStringList() << QString::number(reinterpret_cast<long>(model)));
+}
+
+void TestView::modelAboutToBeDetached(QmlDesigner::Model *model)
+{
+ QmlDesigner::QmlModelView::modelAboutToBeDetached(model);
+ m_methodCalls += MethodCall("modelAboutToBeDetached", QStringList() << QString::number(reinterpret_cast<long>(model)));
+}
+
+void TestView::nodeIdChanged(const QmlDesigner::ModelNode &node, const QString& newId, const QString &oldId)
+{
+ QmlDesigner::QmlModelView::nodeIdChanged(node, newId, oldId);
+ m_methodCalls += MethodCall("nodeIdChanged", QStringList() << node.id() << newId << oldId);
+}
+
+void TestView::nodeTypeChanged(const QmlDesigner::ModelNode &node,const QString &type, int majorVersion, int minorVersion)
+{
+ QmlDesigner::QmlModelView::nodeTypeChanged(node, type, majorVersion, minorVersion);
+ m_methodCalls += MethodCall("nodeTypeChanged", QStringList() << node.id() << type << QString::number(majorVersion) << QString::number(minorVersion));
+}
+
+void TestView::fileUrlChanged(const QUrl & oldBaseUrl, const QUrl &newBaseUrl)
+{
+ QmlDesigner::QmlModelView::fileUrlChanged(oldBaseUrl, newBaseUrl);
+ m_methodCalls += MethodCall("fileUrlChanged", QStringList() << oldBaseUrl.toString() << newBaseUrl.toString());
+}
+
+void TestView::propertiesAboutToBeRemoved(const QList<QmlDesigner::AbstractProperty>& propertyList)
+{
+ QmlDesigner::QmlModelView::propertiesAboutToBeRemoved(propertyList);
+ QStringList propertyNames;
+ foreach (const QmlDesigner::AbstractProperty &property, propertyList)
+ propertyNames += property.name();
+ m_methodCalls += MethodCall("propertiesAboutToBeRemoved", QStringList() << propertyNames.join(", "));
+}
+
+void TestView::nodeCreated(const QmlDesigner::ModelNode &createdNode)
+{
+ QmlDesigner::QmlModelView::nodeCreated(createdNode);
+ m_methodCalls += MethodCall("nodeCreated", QStringList() << createdNode.id());
+}
+
+void TestView::nodeAboutToBeRemoved(const QmlDesigner::ModelNode &removedNode)
+{
+ QmlDesigner::QmlModelView::nodeAboutToBeRemoved(removedNode);
+ m_methodCalls += MethodCall("nodeAboutToBeRemoved", QStringList() << removedNode.id());
+}
+
+void TestView::nodeRemoved(const QmlDesigner::ModelNode &removedNode, const QmlDesigner::NodeAbstractProperty &parentProperty, AbstractView::PropertyChangeFlags propertyChange)
+{
+ QmlDesigner::QmlModelView::nodeRemoved(removedNode, parentProperty, propertyChange);
+ const QString parentPropertyName = parentProperty.isValid() ? parentProperty.name() : "";
+
+ m_methodCalls += MethodCall("nodeRemoved", QStringList() << QString() << parentPropertyName << serialize(propertyChange));
+}
+
+
+void TestView::nodeReparented(const QmlDesigner::ModelNode & node, const QmlDesigner::NodeAbstractProperty &newPropertyParent, const QmlDesigner::NodeAbstractProperty & oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange)
+{
+ QmlDesigner::QmlModelView::nodeReparented(node, newPropertyParent, oldPropertyParent, propertyChange);
+ m_methodCalls += MethodCall("nodeReparented", QStringList() << node.id() << newPropertyParent.name() << oldPropertyParent.name() << serialize(propertyChange));
+}
+
+void TestView::bindingPropertiesChanged(const QList<QmlDesigner::BindingProperty>& propertyList, PropertyChangeFlags propertyChange)
+{
+ QmlDesigner::QmlModelView::bindingPropertiesChanged(propertyList, propertyChange);
+ QStringList propertyNames;
+ foreach (const QmlDesigner::BindingProperty &property, propertyList)
+ propertyNames += property.name();
+ m_methodCalls += MethodCall("bindingPropertiesChanged", QStringList() << propertyNames.join(", ") << serialize(propertyChange));
+}
+
+void TestView::variantPropertiesChanged(const QList<QmlDesigner::VariantProperty>& propertyList, PropertyChangeFlags propertyChange)
+{
+ QmlDesigner::QmlModelView::variantPropertiesChanged(propertyList, propertyChange);
+ QStringList propertyNames;
+ foreach (const QmlDesigner::VariantProperty &property, propertyList)
+ propertyNames += property.name();
+
+ m_methodCalls += MethodCall("variantPropertiesChanged", QStringList() << propertyNames.join(", ") << serialize(propertyChange));
+}
+
+void TestView::selectedNodesChanged(const QList<QmlDesigner::ModelNode> &selectedNodeList,
+ const QList<QmlDesigner::ModelNode> &lastSelectedNodeList)
+{
+ QmlDesigner::QmlModelView::selectedNodesChanged(selectedNodeList, lastSelectedNodeList);
+ QStringList selectedNodes;
+ foreach (const QmlDesigner::ModelNode &node, selectedNodeList)
+ selectedNodes += node.id();
+ QStringList lastSelectedNodes;
+ foreach (const QmlDesigner::ModelNode &node, lastSelectedNodeList)
+ lastSelectedNodes += node.id();
+ m_methodCalls += MethodCall("selectedNodesChanged", QStringList() << selectedNodes.join(", ") << lastSelectedNodes.join(", "));
+}
+
+void TestView::nodeSlidedToIndex(const QmlDesigner::NodeListProperty &listProperty, int newIndex, int oldIndex)
+{
+ QmlDesigner::QmlModelView::nodeSlidedToIndex(listProperty, newIndex, oldIndex);
+ m_methodCalls += MethodCall("nodeSlidedToIndex", QStringList() << listProperty.name() << QString::number(newIndex) << QString::number(oldIndex));
+}
+
+void TestView::stateChanged(const QmlDesigner::QmlModelState &newQmlModelState, const QmlDesigner::QmlModelState &oldQmlModelState)
+{
+ QmlDesigner::QmlModelView::stateChanged(newQmlModelState, oldQmlModelState);
+ m_methodCalls += MethodCall("stateChanged", QStringList() << newQmlModelState.name() << oldQmlModelState.name());
+}
+
+QList<TestView::MethodCall> &TestView::methodCalls()
+{
+ return m_methodCalls;
+}
+
+QString TestView::lastFunction() const
+{
+ return m_methodCalls.last().name;
+}
+
+QmlDesigner::NodeInstanceView *TestView::nodeInstanceView() const
+{
+ return QmlDesigner::QmlModelView::nodeInstanceView();
+
+}
+
+QmlDesigner::NodeInstance TestView::instanceForModelNode(const QmlDesigner::ModelNode &modelNode)
+{
+ return QmlDesigner::QmlModelView::instanceForModelNode(modelNode);
+}
+
+
+QString TestView::serialize(AbstractView::PropertyChangeFlags change)
+{
+ QStringList tokenList;
+
+ if (change.testFlag(PropertiesAdded))
+ tokenList.append(QLatin1String("PropertiesAdded"));
+
+ if (change.testFlag(EmptyPropertiesRemoved))
+ tokenList.append(QLatin1String("EmptyPropertiesRemoved"));
+
+ return tokenList.join(" ");
+}
+
+
+bool operator==(TestView::MethodCall call1, TestView::MethodCall call2)
+{
+ if (call1.name != call2.name)
+ return false;
+// if (call1.arguments != call2.arguments)
+// return false;
+ if (call1.arguments.size() != call2.arguments.size()) {
+ qWarning() << "different method names:" << call1.arguments.size() << call2.arguments.size();
+ return false;
+ }
+ for (int i = 0; i < call1.arguments.size(); ++i)
+ if (call1.arguments.at(i) != call2.arguments.at(i)) {
+ qDebug() << "different argument values:" << call1.arguments.at(i) << call2.arguments.at(i);
+ return false;
+ }
+ return true;
+}
+
+QDebug operator<<(QDebug debug, TestView::MethodCall call)
+{
+ return debug.nospace() << call.name << "(" << call.arguments.join(", ") << ")";
+}
+
diff --git a/tests/auto/qml/qmldesigner/testview.h b/tests/auto/qml/qmldesigner/testview.h
new file mode 100644
index 0000000000..c667f8b041
--- /dev/null
+++ b/tests/auto/qml/qmldesigner/testview.h
@@ -0,0 +1,93 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef TESTVIEW_H
+#define TESTVIEW_H
+
+#include <modelnode.h>
+#include <qmlmodelview.h>
+#include <QVariant>
+#include <QStringList>
+
+class TestView : public QmlDesigner::QmlModelView
+{
+ Q_OBJECT
+public:
+ struct MethodCall {
+ MethodCall(const QString &n, const QStringList &args) :
+ name(n), arguments(args)
+ {
+ }
+
+ QString name;
+ QStringList arguments;
+ };
+
+ TestView(QObject *parent = 0);
+
+ void modelAttached(QmlDesigner::Model *model);
+ void modelAboutToBeDetached(QmlDesigner::Model *model);
+ void nodeCreated(const QmlDesigner::ModelNode &createdNode);
+ void nodeAboutToBeRemoved(const QmlDesigner::ModelNode &removedNode);
+ void nodeRemoved(const QmlDesigner::ModelNode &removedNode, const QmlDesigner::NodeAbstractProperty &parentProperty, AbstractView::PropertyChangeFlags propertyChange);
+ void nodeReparented(const QmlDesigner::ModelNode &node, const QmlDesigner::NodeAbstractProperty &newPropertyParent, const QmlDesigner::NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange);
+ void nodeIdChanged(const QmlDesigner::ModelNode& node, const QString& newId, const QString& oldId);
+ void nodeTypeChanged(const QmlDesigner::ModelNode &node,const QString &type, int majorVersion, int minorVersion);
+
+ void bindingPropertiesChanged(const QList<QmlDesigner::BindingProperty>& propertyList, PropertyChangeFlags propertyChange);
+ void variantPropertiesChanged(const QList<QmlDesigner::VariantProperty>& propertyList, PropertyChangeFlags propertyChange);
+ void propertiesAboutToBeRemoved(const QList<QmlDesigner::AbstractProperty> &propertyList);
+
+
+
+ void fileUrlChanged(const QUrl &oldBaseUrl, const QUrl &newBaseUrl);
+ void selectedNodesChanged(const QList<QmlDesigner::ModelNode> &selectedNodeList,
+ const QList<QmlDesigner::ModelNode> &lastSelectedNodeList);
+
+ void nodeSlidedToIndex(const QmlDesigner::NodeListProperty &listProperty, int newIndex, int oldIndex);
+
+ void stateChanged(const QmlDesigner::QmlModelState &newQmlModelState, const QmlDesigner::QmlModelState &oldQmlModelState);
+
+ QList<MethodCall> &methodCalls();
+
+ QString lastFunction() const;
+
+ QmlDesigner::NodeInstanceView *nodeInstanceView() const;
+
+ QmlDesigner::NodeInstance instanceForModelNode(const QmlDesigner::ModelNode &modelNode);
+
+private:
+ QList<MethodCall> m_methodCalls;
+ static QString serialize(AbstractView::PropertyChangeFlags change);
+};
+
+bool operator==(TestView::MethodCall call1, TestView::MethodCall call2);
+QDebug operator<<(QDebug debug, TestView::MethodCall call);
+
+#endif // TESTVIEW_H