summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore14
-rw-r--r--README9
-rw-r--r--dist/changes-2.2.046
-rw-r--r--doc/doc.pri8
-rw-r--r--doc/examples/batteryindicator/deployment.pri2
-rw-r--r--doc/pluginhowto/examples/dirmodelplugin/dirnavigationfactory.cpp2
-rw-r--r--doc/qt-html-templates.qdocconf4
-rw-r--r--doc/qtcreator.qdoc32
-rw-r--r--doc/qtcreator.qdocconf10
-rw-r--r--qtcreator.pri7
-rwxr-xr-xscripts/krazy2tasks.pl24
-rw-r--r--scripts/mytasks.pl59
-rwxr-xr-xscripts/replaceVersion.sh138
-rw-r--r--share/qtcreator/gdbmacros/dumper.py244
-rw-r--r--share/qtcreator/gdbmacros/gdbmacros.cpp42
-rw-r--r--share/qtcreator/gdbmacros/gdbmacros.py570
-rw-r--r--share/qtcreator/glsl/glsl_120.frag56
-rw-r--r--share/qtcreator/glsl/glsl_120.vert74
-rw-r--r--share/qtcreator/glsl/glsl_120_common.glsl459
-rw-r--r--share/qtcreator/glsl/glsl_es_100.frag35
-rw-r--r--share/qtcreator/glsl/glsl_es_100.vert38
-rw-r--r--share/qtcreator/glsl/glsl_es_100_common.glsl292
-rw-r--r--share/qtcreator/qml-type-descriptions/qml-builtin-types.xml2000
-rw-r--r--share/qtcreator/qml-type-descriptions/qmlproject-types.xml12
-rw-r--r--share/qtcreator/qml/qmldump/main.cpp10
-rw-r--r--share/qtcreator/qml/qmljsdebugger/editor/abstractformeditortool.cpp25
-rw-r--r--share/qtcreator/qml/qmljsdebugger/editor/abstractformeditortool.h1
-rw-r--r--share/qtcreator/qml/qmljsdebugger/editor/boundingrecthighlighter.cpp6
-rw-r--r--share/qtcreator/qml/qmljsdebugger/editor/boundingrecthighlighter.h3
-rw-r--r--share/qtcreator/qml/qmljsdebugger/editor/colorpickertool.cpp2
-rw-r--r--share/qtcreator/qml/qmljsdebugger/editor/editor.pri40
-rw-r--r--share/qtcreator/qml/qmljsdebugger/editor/layeritem.cpp5
-rw-r--r--share/qtcreator/qml/qmljsdebugger/editor/layeritem.h5
-rw-r--r--share/qtcreator/qml/qmljsdebugger/editor/qmltoolbar.cpp30
-rw-r--r--share/qtcreator/qml/qmljsdebugger/editor/rubberbandselectionmanipulator.cpp52
-rw-r--r--share/qtcreator/qml/qmljsdebugger/editor/rubberbandselectionmanipulator.h5
-rw-r--r--share/qtcreator/qml/qmljsdebugger/editor/selectionindicator.cpp16
-rw-r--r--share/qtcreator/qml/qmljsdebugger/editor/selectionrectangle.cpp10
-rw-r--r--share/qtcreator/qml/qmljsdebugger/editor/selectiontool.cpp151
-rw-r--r--share/qtcreator/qml/qmljsdebugger/editor/selectiontool.h4
-rw-r--r--share/qtcreator/qml/qmljsdebugger/editor/singleselectionmanipulator.cpp54
-rw-r--r--share/qtcreator/qml/qmljsdebugger/editor/singleselectionmanipulator.h3
-rw-r--r--share/qtcreator/qml/qmljsdebugger/editor/subcomponenteditortool.cpp21
-rw-r--r--share/qtcreator/qml/qmljsdebugger/editor/subcomponentmasklayeritem.cpp3
-rw-r--r--share/qtcreator/qml/qmljsdebugger/editor/subcomponentmasklayeritem.h3
-rw-r--r--share/qtcreator/qml/qmljsdebugger/editor/toolbarcolorbox.cpp10
-rw-r--r--share/qtcreator/qml/qmljsdebugger/editor/zoomtool.cpp35
-rw-r--r--share/qtcreator/qml/qmljsdebugger/editor/zoomtool.h2
-rw-r--r--share/qtcreator/qml/qmljsdebugger/include/jsdebuggeragent.h48
-rw-r--r--share/qtcreator/qml/qmljsdebugger/include/qdeclarativeobserverservice.h3
-rw-r--r--share/qtcreator/qml/qmljsdebugger/include/qdeclarativeviewobserver.h6
-rw-r--r--share/qtcreator/qml/qmljsdebugger/jsdebuggeragent.cpp396
-rw-r--r--share/qtcreator/qml/qmljsdebugger/qdeclarativeobserverservice.cpp20
-rw-r--r--share/qtcreator/qml/qmljsdebugger/qdeclarativeviewobserver.cpp306
-rw-r--r--share/qtcreator/qml/qmljsdebugger/qdeclarativeviewobserver_p.h2
-rw-r--r--share/qtcreator/qml/qmljsdebugger/qmljsdebugger-lib.pri45
-rw-r--r--share/qtcreator/qml/qmlobserver/Info_mac.plist31
-rw-r--r--share/qtcreator/qml/qmlobserver/browser/Browser.qml318
-rw-r--r--share/qtcreator/qml/qmlobserver/browser/browser.qrc9
-rw-r--r--share/qtcreator/qml/qmlobserver/browser/images/folder.png (renamed from share/qtcreator/qml/qmlobserver/content/images/folder.png)bin1841 -> 1841 bytes
-rw-r--r--share/qtcreator/qml/qmlobserver/browser/images/titlebar.png (renamed from share/qtcreator/qml/qmlobserver/content/images/titlebar.png)bin1436 -> 1436 bytes
-rw-r--r--share/qtcreator/qml/qmlobserver/browser/images/titlebar.sci (renamed from share/qtcreator/qml/qmlobserver/content/images/titlebar.sci)0
-rw-r--r--share/qtcreator/qml/qmlobserver/browser/images/up.png (renamed from share/qtcreator/qml/qmlobserver/content/images/up.png)bin662 -> 662 bytes
-rw-r--r--share/qtcreator/qml/qmlobserver/content/Browser.qml284
-rw-r--r--share/qtcreator/qml/qmlobserver/deviceorientation.cpp5
-rw-r--r--share/qtcreator/qml/qmlobserver/deviceorientation.h3
-rw-r--r--share/qtcreator/qml/qmlobserver/deviceorientation_harmattan.cpp161
-rw-r--r--share/qtcreator/qml/qmlobserver/deviceorientation_maemo5.cpp53
-rw-r--r--share/qtcreator/qml/qmlobserver/deviceorientation_symbian.cpp192
-rw-r--r--share/qtcreator/qml/qmlobserver/main.cpp540
-rw-r--r--share/qtcreator/qml/qmlobserver/qdeclarativetester.cpp62
-rw-r--r--share/qtcreator/qml/qmlobserver/qdeclarativetester.h5
-rw-r--r--share/qtcreator/qml/qmlobserver/qml.pri29
-rw-r--r--share/qtcreator/qml/qmlobserver/qmlobserver.pro41
-rw-r--r--share/qtcreator/qml/qmlobserver/qmlruntime.cpp414
-rw-r--r--share/qtcreator/qml/qmlobserver/qmlruntime.h16
-rw-r--r--share/qtcreator/qml/qmlobserver/qmlruntime.qrc9
-rw-r--r--share/qtcreator/qml/qmlobserver/startup/Logo.qml179
-rw-r--r--share/qtcreator/qml/qmlobserver/startup/qt-back.pngbin0 -> 3549 bytes
-rw-r--r--share/qtcreator/qml/qmlobserver/startup/qt-blue.jpgbin0 -> 20900 bytes
-rw-r--r--share/qtcreator/qml/qmlobserver/startup/qt-front.pngbin0 -> 3318 bytes
-rw-r--r--share/qtcreator/qml/qmlobserver/startup/qt-sketch.jpgbin0 -> 17048 bytes
-rw-r--r--share/qtcreator/qml/qmlobserver/startup/qt-text.pngbin0 -> 14565 bytes
-rw-r--r--share/qtcreator/qml/qmlobserver/startup/quick-blur.pngbin0 -> 2826 bytes
-rw-r--r--share/qtcreator/qml/qmlobserver/startup/quick-regular.pngbin0 -> 1399 bytes
-rw-r--r--share/qtcreator/qml/qmlobserver/startup/shadow.pngbin0 -> 1592 bytes
-rw-r--r--share/qtcreator/qml/qmlobserver/startup/startup.qml173
-rw-r--r--share/qtcreator/qml/qmlobserver/startup/startup.qrc16
-rw-r--r--share/qtcreator/qml/qmlobserver/startup/white-star.pngbin0 -> 2651 bytes
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/ExtendedFunctionButton.qml13
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/StandardTextGroupBox.qml16
-rw-r--r--share/qtcreator/qmldesigner/propertyeditor/Qt/Visibility.qml9
-rw-r--r--share/qtcreator/snippets/cpp.xml91
-rw-r--r--share/qtcreator/snippets/qml.xml123
-rw-r--r--share/qtcreator/snippets/text.xml4
-rw-r--r--share/qtcreator/static.pro5
-rw-r--r--share/qtcreator/styles/inkpot.xml44
-rw-r--r--share/qtcreator/templates/mobileapp/app.pro7
-rw-r--r--share/qtcreator/templates/qmlapp/app.pro7
-rw-r--r--share/qtcreator/templates/shared/deployment.pri2
-rw-r--r--share/qtcreator/templates/wizards/qtcreatorplugin/MyPlugin.pluginspec10
-rw-r--r--share/qtcreator/templates/wizards/qtcreatorplugin/MyPlugin.pluginspec.in10
-rw-r--r--share/qtcreator/templates/wizards/qtcreatorplugin/myplugin.cpp26
-rw-r--r--share/qtcreator/templates/wizards/qtcreatorplugin/myplugin.h6
-rw-r--r--share/qtcreator/templates/wizards/qtcreatorplugin/myplugin.pro7
-rw-r--r--share/qtcreator/templates/wizards/qtcreatorplugin/mypluginconstants.h13
-rw-r--r--share/qtcreator/templates/wizards/qtcreatorplugin/wizard.xml7
-rw-r--r--src/app/Info.plist219
-rw-r--r--src/app/Info.plist.in219
-rw-r--r--src/app/app.pro15
-rw-r--r--src/app/main.cpp43
-rw-r--r--src/libs/3rdparty/botan/botan.pri2
-rw-r--r--src/libs/aggregation/aggregation.pri2
-rw-r--r--src/libs/cplusplus/CppDocument.cpp41
-rw-r--r--src/libs/cplusplus/CppRewriter.cpp186
-rw-r--r--src/libs/cplusplus/CppRewriter.h5
-rw-r--r--src/libs/cplusplus/LookupContext.cpp4
-rw-r--r--src/libs/cplusplus/ResolveExpression.cpp102
-rw-r--r--src/libs/cplusplus/ResolveExpression.h9
-rw-r--r--src/libs/cplusplus/SnapshotSymbolVisitor.cpp60
-rw-r--r--src/libs/cplusplus/SnapshotSymbolVisitor.h57
-rw-r--r--src/libs/cplusplus/SymbolNameVisitor.cpp55
-rw-r--r--src/libs/cplusplus/SymbolNameVisitor.h52
-rw-r--r--src/libs/cplusplus/TypeOfExpression.cpp35
-rw-r--r--src/libs/cplusplus/TypeOfExpression.h8
-rw-r--r--src/libs/cplusplus/cplusplus-lib.pri4
-rw-r--r--src/libs/cplusplus/cplusplus.pri4
-rw-r--r--src/libs/extensionsystem/extensionsystem.pri2
-rw-r--r--src/libs/extensionsystem/iplugin.cpp2
-rw-r--r--src/libs/extensionsystem/pluginmanager.cpp52
-rw-r--r--src/libs/extensionsystem/pluginmanager.h5
-rw-r--r--src/libs/extensionsystem/pluginmanager_p.h5
-rw-r--r--src/libs/extensionsystem/pluginview.cpp4
-rw-r--r--src/libs/extensionsystem/test/auto/auto.pro3
-rw-r--r--src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin1/plugin1.cpp56
-rw-r--r--src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin1/plugin1.pro8
-rw-r--r--src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin2/plugin2.pro8
-rw-r--r--src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin3/plugin3.pro8
-rw-r--r--src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin1/plugin1.pro15
-rw-r--r--src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin2/plugin2.pro12
-rw-r--r--src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin3/plugin3.pro15
-rw-r--r--src/libs/extensionsystem/test/auto/pluginmanager/test.pro14
-rwxr-xr-xsrc/libs/extensionsystem/test/auto/pluginmanager/test.sh5
-rw-r--r--src/libs/extensionsystem/test/auto/pluginmanager/tst_pluginmanager.cpp269
-rw-r--r--src/libs/extensionsystem/test/auto/pluginspec/test.pro14
-rwxr-xr-xsrc/libs/extensionsystem/test/auto/pluginspec/test.sh5
-rw-r--r--src/libs/extensionsystem/test/auto/pluginspec/testplugin/testplugin.h63
-rw-r--r--src/libs/extensionsystem/test/auto/pluginspec/testplugin/testplugin.pro13
-rw-r--r--src/libs/extensionsystem/test/auto/pluginspec/tst_pluginspec.cpp290
-rw-r--r--src/libs/extensionsystem/test/extensionsystem_test.pri12
-rw-r--r--src/libs/extensionsystem/test/manual/pluginview/plugins/plugin1/plugin1.pro7
-rw-r--r--src/libs/extensionsystem/test/manual/pluginview/plugins/plugin2/plugin2.pro3
-rw-r--r--src/libs/extensionsystem/test/manual/pluginview/plugins/plugin3/plugin3.pro7
-rw-r--r--src/libs/extensionsystem/test/manual/pluginview/test.pro1
-rw-r--r--src/libs/glsl/glsl-lib.pri9
-rw-r--r--src/libs/glsl/glsl.g3008
-rw-r--r--src/libs/glsl/glsl.h83
-rw-r--r--src/libs/glsl/glsl.pri6
-rw-r--r--src/libs/glsl/glsl.pro8
-rw-r--r--src/libs/glsl/glslast.cpp427
-rw-r--r--src/libs/glsl/glslast.h994
-rw-r--r--src/libs/glsl/glslastdump.cpp68
-rw-r--r--src/libs/glsl/glslastdump.h57
-rw-r--r--src/libs/glsl/glslastvisitor.cpp46
-rw-r--r--src/libs/glsl/glslastvisitor.h158
-rw-r--r--src/libs/glsl/glslengine.cpp291
-rw-r--r--src/libs/glsl/glslengine.h150
-rw-r--r--src/libs/glsl/glslkeywords.cpp1873
-rw-r--r--src/libs/glsl/glsllexer.cpp419
-rw-r--r--src/libs/glsl/glsllexer.h137
-rw-r--r--src/libs/glsl/glslmemorypool.cpp120
-rw-r--r--src/libs/glsl/glslmemorypool.h110
-rw-r--r--src/libs/glsl/glslparser.cpp2270
-rw-r--r--src/libs/glsl/glslparser.h207
-rw-r--r--src/libs/glsl/glslparsertable.cpp1296
-rw-r--r--src/libs/glsl/glslparsertable_p.h284
-rw-r--r--src/libs/glsl/glslsemantic.cpp876
-rw-r--r--src/libs/glsl/glslsemantic.h132
-rw-r--r--src/libs/glsl/glslsymbol.cpp82
-rw-r--r--src/libs/glsl/glslsymbol.h85
-rw-r--r--src/libs/glsl/glslsymbols.cpp141
-rw-r--r--src/libs/glsl/glslsymbols.h110
-rw-r--r--src/libs/glsl/glsltype.cpp37
-rw-r--r--src/libs/glsl/glsltype.h67
-rw-r--r--src/libs/glsl/glsltypes.cpp525
-rw-r--r--src/libs/glsl/glsltypes.h297
-rwxr-xr-xsrc/libs/glsl/make-parser.sh5
-rw-r--r--src/libs/glsl/specs/glsl.keywords134
-rw-r--r--src/libs/glsl/specs/grammar.txt312
-rw-r--r--src/libs/glsl/tests/main.cpp92
-rw-r--r--src/libs/glsl/tests/test.pro14
-rw-r--r--src/libs/glsl/tools/kwgen.cpp406
-rwxr-xr-xsrc/libs/glsl/tools/mkvisitor.py85
-rw-r--r--src/libs/libs.pro3
-rw-r--r--src/libs/qmleditorwidgets/colorbox.h2
-rw-r--r--src/libs/qmleditorwidgets/colorbutton.h2
-rw-r--r--src/libs/qmleditorwidgets/colorwidget.cpp51
-rw-r--r--src/libs/qmleditorwidgets/colorwidget.h62
-rw-r--r--src/libs/qmleditorwidgets/colorwidgets.cpp51
-rw-r--r--src/libs/qmleditorwidgets/colorwidgets.h58
-rw-r--r--src/libs/qmleditorwidgets/contextpanewidget.cpp1
-rw-r--r--src/libs/qmleditorwidgets/contextpanewidgetimage.cpp9
-rw-r--r--src/libs/qmleditorwidgets/gradientline.cpp4
-rw-r--r--src/libs/qmleditorwidgets/gradientline.h4
-rw-r--r--src/libs/qmleditorwidgets/huecontrol.h2
-rw-r--r--src/libs/qmleditorwidgets/qmleditorwidgets-lib.pri4
-rw-r--r--src/libs/qmljs/qmljs.pri2
-rw-r--r--src/libs/qmljs/qmljsbind.cpp93
-rw-r--r--src/libs/qmljs/qmljsbind.h7
-rw-r--r--src/libs/qmljs/qmljscheck.cpp552
-rw-r--r--src/libs/qmljs/qmljscheck.h62
-rw-r--r--src/libs/qmljs/qmljscodeformatter.cpp2
-rw-r--r--src/libs/qmljs/qmljscodeformatter.h4
-rw-r--r--src/libs/qmljs/qmljscompletioncontextfinder.cpp116
-rw-r--r--src/libs/qmljs/qmljscompletioncontextfinder.h6
-rw-r--r--src/libs/qmljs/qmljscomponentversion.cpp10
-rw-r--r--src/libs/qmljs/qmljscomponentversion.h7
-rw-r--r--src/libs/qmljs/qmljsdocument.cpp8
-rw-r--r--src/libs/qmljs/qmljsdocument.h25
-rw-r--r--src/libs/qmljs/qmljsevaluate.cpp2
-rw-r--r--src/libs/qmljs/qmljsinterpreter.cpp426
-rw-r--r--src/libs/qmljs/qmljsinterpreter.h113
-rw-r--r--src/libs/qmljs/qmljslineinfo.cpp34
-rw-r--r--src/libs/qmljs/qmljslink.cpp17
-rw-r--r--src/libs/qmljs/qmljslink.h1
-rw-r--r--src/libs/qmljs/qmljsmodelmanagerinterface.cpp2
-rw-r--r--src/libs/qmljs/qmljsscanner.cpp24
-rw-r--r--src/libs/qmljs/qmljsscanner.h4
-rw-r--r--src/libs/qmljs/qmljsscopebuilder.cpp47
-rw-r--r--src/libs/qmljsdebugclient/qdeclarativedebug.cpp5
-rw-r--r--src/libs/qmljsdebugclient/qdeclarativedebugclient.cpp43
-rw-r--r--src/libs/qmljsdebugclient/qdeclarativedebugclient_p.h2
-rw-r--r--src/libs/qmljsdebugclient/qpacketprotocol.cpp2
-rw-r--r--src/libs/qtconcurrent/qtconcurrent.pri2
-rw-r--r--src/libs/qtcreatorcdbext/base64.cpp106
-rw-r--r--src/libs/qtcreatorcdbext/base64.h42
-rw-r--r--src/libs/qtcreatorcdbext/cdb_detect.pri16
-rw-r--r--src/libs/qtcreatorcdbext/common.cpp120
-rw-r--r--src/libs/qtcreatorcdbext/common.h84
-rw-r--r--src/libs/qtcreatorcdbext/containers.cpp694
-rw-r--r--src/libs/qtcreatorcdbext/containers.h53
-rw-r--r--src/libs/qtcreatorcdbext/eventcallback.cpp297
-rw-r--r--src/libs/qtcreatorcdbext/eventcallback.h157
-rw-r--r--src/libs/qtcreatorcdbext/extensioncontext.cpp319
-rw-r--r--src/libs/qtcreatorcdbext/extensioncontext.h135
-rw-r--r--src/libs/qtcreatorcdbext/gdbmihelpers.cpp618
-rw-r--r--src/libs/qtcreatorcdbext/gdbmihelpers.h158
-rw-r--r--src/libs/qtcreatorcdbext/iinterfacepointer.h88
-rw-r--r--src/libs/qtcreatorcdbext/knowntype.h158
-rw-r--r--src/libs/qtcreatorcdbext/outputcallback.cpp98
-rw-r--r--src/libs/qtcreatorcdbext/outputcallback.h64
-rw-r--r--src/libs/qtcreatorcdbext/qtcreatorcdbext.def20
-rw-r--r--src/libs/qtcreatorcdbext/qtcreatorcdbext.pro14
-rw-r--r--src/libs/qtcreatorcdbext/qtcreatorcdbext_build.pro73
-rw-r--r--src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp723
-rw-r--r--src/libs/qtcreatorcdbext/stringutils.cpp267
-rw-r--r--src/libs/qtcreatorcdbext/stringutils.h154
-rw-r--r--src/libs/qtcreatorcdbext/symbolgroup.cpp525
-rw-r--r--src/libs/qtcreatorcdbext/symbolgroup.h128
-rw-r--r--src/libs/qtcreatorcdbext/symbolgroupnode.cpp1188
-rw-r--r--src/libs/qtcreatorcdbext/symbolgroupnode.h393
-rw-r--r--src/libs/qtcreatorcdbext/symbolgroupvalue.cpp1218
-rw-r--r--src/libs/qtcreatorcdbext/symbolgroupvalue.h128
-rw-r--r--src/libs/qtcreatorcdbext/test32.bat24
-rw-r--r--src/libs/qtcreatorcdbext/test64.bat23
-rw-r--r--src/libs/symbianutils/symbianutils.pri2
-rw-r--r--src/libs/utils/abstractprocess.h13
-rw-r--r--src/libs/utils/abstractprocess_win.cpp78
-rw-r--r--src/libs/utils/annotateditemdelegate.cpp123
-rw-r--r--src/libs/utils/annotateditemdelegate.h66
-rw-r--r--src/libs/utils/buildablehelperlibrary.cpp17
-rw-r--r--src/libs/utils/consoleprocess.h2
-rw-r--r--src/libs/utils/consoleprocess_unix.cpp44
-rw-r--r--src/libs/utils/consoleprocess_win.cpp20
-rw-r--r--src/libs/utils/crumblepath.h2
-rw-r--r--src/libs/utils/debuggerlanguagechooser.h6
-rw-r--r--src/libs/utils/detailsbutton.cpp5
-rw-r--r--src/libs/utils/detailsbutton.h1
-rw-r--r--src/libs/utils/detailswidget.cpp3
-rw-r--r--src/libs/utils/environment.cpp233
-rw-r--r--src/libs/utils/environment.h9
-rw-r--r--src/libs/utils/fileinprojectfinder.cpp122
-rw-r--r--src/libs/utils/fileinprojectfinder.h61
-rw-r--r--src/libs/utils/filesearch.cpp179
-rw-r--r--src/libs/utils/filesearch.h11
-rw-r--r--src/libs/utils/historycompleter.cpp9
-rw-r--r--src/libs/utils/historycompleter.h2
-rw-r--r--src/libs/utils/htmldocextractor.cpp23
-rw-r--r--src/libs/utils/htmldocextractor.h3
-rw-r--r--src/libs/utils/pathchooser.cpp3
-rw-r--r--src/libs/utils/projectintropage.cpp1
-rw-r--r--src/libs/utils/qtcprocess.cpp1391
-rw-r--r--src/libs/utils/qtcprocess.h149
-rw-r--r--src/libs/utils/stringutils.cpp38
-rw-r--r--src/libs/utils/stringutils.h25
-rw-r--r--src/libs/utils/submiteditorwidget.cpp12
-rw-r--r--src/libs/utils/submiteditorwidget.h4
-rw-r--r--src/libs/utils/unixutils.h2
-rw-r--r--src/libs/utils/utils-lib.pri11
-rw-r--r--src/libs/utils/winutils.cpp37
-rw-r--r--src/libs/utils/winutils.h5
-rw-r--r--src/libs/utils/wizard.cpp53
-rw-r--r--src/libs/utils/wizard.h8
-rw-r--r--src/plugins/bineditor/BinEditor.pluginspec20
-rw-r--r--src/plugins/bineditor/BinEditor.pluginspec.in20
-rw-r--r--src/plugins/bineditor/bineditor.cpp226
-rw-r--r--src/plugins/bineditor/bineditor.h26
-rw-r--r--src/plugins/bineditor/bineditor.pro2
-rw-r--r--src/plugins/bineditor/bineditorplugin.cpp1
-rw-r--r--src/plugins/bookmarks/Bookmarks.pluginspec21
-rw-r--r--src/plugins/bookmarks/Bookmarks.pluginspec.in21
-rw-r--r--src/plugins/bookmarks/bookmarks.pro2
-rw-r--r--src/plugins/bookmarks/bookmarksplugin.cpp1
-rw-r--r--src/plugins/classview/ClassView.pluginspec22
-rw-r--r--src/plugins/classview/ClassView.pluginspec.in22
-rw-r--r--src/plugins/classview/classview.pro3
-rw-r--r--src/plugins/classview/classviewmanager.cpp2
-rw-r--r--src/plugins/classview/classviewparser.cpp2
-rw-r--r--src/plugins/classview/classviewparsertreeitem.cpp4
-rw-r--r--src/plugins/cmakeprojectmanager/CMakeProjectManager.pluginspec22
-rw-r--r--src/plugins/cmakeprojectmanager/CMakeProjectManager.pluginspec.in22
-rw-r--r--src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp10
-rw-r--r--src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h8
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeeditor.cpp3
-rw-r--r--src/plugins/cmakeprojectmanager/cmakehighlighter.cpp2
-rw-r--r--src/plugins/cmakeprojectmanager/cmakehighlighter.h1
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.cpp60
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.h14
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeproject.cpp215
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeproject.h24
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp15
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeprojectmanager.h13
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeprojectmanager.pro9
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeprojectmanager_dependencies.pri2
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp2
-rw-r--r--src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp26
-rw-r--r--src/plugins/cmakeprojectmanager/cmakerunconfiguration.h5
-rw-r--r--src/plugins/cmakeprojectmanager/cmaketarget.cpp12
-rw-r--r--src/plugins/cmakeprojectmanager/cmaketarget.h4
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeuicodemodelsupport.cpp64
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeuicodemodelsupport.h61
-rw-r--r--src/plugins/cmakeprojectmanager/makestep.cpp55
-rw-r--r--src/plugins/cmakeprojectmanager/makestep.h6
-rw-r--r--src/plugins/coreplugin/Core.pluginspec19
-rw-r--r--src/plugins/coreplugin/Core.pluginspec.in19
-rw-r--r--src/plugins/coreplugin/actionmanager/actioncontainer.cpp65
-rw-r--r--src/plugins/coreplugin/actionmanager/actioncontainer.h12
-rw-r--r--src/plugins/coreplugin/actionmanager/actioncontainer_p.h6
-rw-r--r--src/plugins/coreplugin/actionmanager/actionmanager.cpp47
-rw-r--r--src/plugins/coreplugin/actionmanager/actionmanager.h9
-rw-r--r--src/plugins/coreplugin/actionmanager/actionmanager_p.h2
-rw-r--r--src/plugins/coreplugin/actionmanager/command.cpp46
-rw-r--r--src/plugins/coreplugin/actionmanager/command_p.h7
-rw-r--r--src/plugins/coreplugin/actionmanager/commandmappings.cpp16
-rw-r--r--src/plugins/coreplugin/actionmanager/commandmappings.h1
-rw-r--r--src/plugins/coreplugin/basemode.cpp91
-rw-r--r--src/plugins/coreplugin/basemode.h91
-rw-r--r--src/plugins/coreplugin/coreconstants.h6
-rw-r--r--src/plugins/coreplugin/coreimpl.cpp8
-rw-r--r--src/plugins/coreplugin/coreimpl.h3
-rw-r--r--src/plugins/coreplugin/coreplugin.pri5
-rw-r--r--src/plugins/coreplugin/coreplugin.pro10
-rw-r--r--src/plugins/coreplugin/designmode.cpp1
-rw-r--r--src/plugins/coreplugin/dialogs/ioptionspage.cpp17
-rw-r--r--src/plugins/coreplugin/dialogs/ioptionspage.h23
-rw-r--r--src/plugins/coreplugin/dialogs/saveitemsdialog.cpp2
-rw-r--r--src/plugins/coreplugin/dialogs/settingsdialog.cpp89
-rw-r--r--src/plugins/coreplugin/dialogs/settingsdialog.h2
-rw-r--r--src/plugins/coreplugin/dialogs/shortcutsettings.cpp22
-rw-r--r--src/plugins/coreplugin/dialogs/shortcutsettings.h4
-rw-r--r--src/plugins/coreplugin/editmode.cpp5
-rw-r--r--src/plugins/coreplugin/editormanager/editormanager.cpp317
-rw-r--r--src/plugins/coreplugin/editormanager/editormanager.h32
-rw-r--r--src/plugins/coreplugin/editormanager/editorview.cpp28
-rw-r--r--src/plugins/coreplugin/editormanager/ieditor.h3
-rw-r--r--src/plugins/coreplugin/editormanager/openeditorsmodel.cpp2
-rw-r--r--src/plugins/coreplugin/editormanager/openeditorsview.cpp3
-rw-r--r--src/plugins/coreplugin/editortoolbar.cpp4
-rw-r--r--src/plugins/coreplugin/fancyactionbar.cpp1
-rw-r--r--src/plugins/coreplugin/filemanager.cpp774
-rw-r--r--src/plugins/coreplugin/filemanager.h45
-rw-r--r--src/plugins/coreplugin/generalsettings.cpp56
-rw-r--r--src/plugins/coreplugin/generalsettings.h1
-rw-r--r--src/plugins/coreplugin/generalsettings.ui100
-rw-r--r--src/plugins/coreplugin/icontext.h2
-rw-r--r--src/plugins/coreplugin/icore.cpp2
-rw-r--r--src/plugins/coreplugin/icore.h18
-rw-r--r--src/plugins/coreplugin/ide_version.h.in32
-rw-r--r--src/plugins/coreplugin/ifile.h6
-rw-r--r--src/plugins/coreplugin/iversioncontrol.h2
-rw-r--r--src/plugins/coreplugin/mainwindow.cpp94
-rw-r--r--src/plugins/coreplugin/mainwindow.h18
-rw-r--r--src/plugins/coreplugin/mimedatabase.cpp34
-rw-r--r--src/plugins/coreplugin/mimedatabase.h2
-rw-r--r--src/plugins/coreplugin/modemanager.cpp6
-rw-r--r--src/plugins/coreplugin/navigationwidget.cpp65
-rw-r--r--src/plugins/coreplugin/outputpane.cpp7
-rw-r--r--src/plugins/coreplugin/rssfetcher.cpp7
-rw-r--r--src/plugins/coreplugin/rssfetcher.h6
-rw-r--r--src/plugins/coreplugin/scriptmanager/metatypedeclarations.h1
-rw-r--r--src/plugins/coreplugin/scriptmanager/qworkbench_wrapper.cpp365
-rw-r--r--src/plugins/coreplugin/scriptmanager/qworkbench_wrapper.h232
-rw-r--r--src/plugins/coreplugin/scriptmanager/scriptmanager.cpp16
-rw-r--r--src/plugins/coreplugin/ssh/sftpchannel.cpp11
-rw-r--r--src/plugins/coreplugin/ssh/sftpchannel.h3
-rw-r--r--src/plugins/coreplugin/ssh/sshchannel_p.h2
-rw-r--r--src/plugins/coreplugin/ssh/sshpacket_p.h2
-rw-r--r--src/plugins/coreplugin/ssh/sshremoteprocessrunner.cpp210
-rw-r--r--src/plugins/coreplugin/ssh/sshremoteprocessrunner.h44
-rw-r--r--src/plugins/coreplugin/variablemanager.cpp32
-rw-r--r--src/plugins/coreplugin/variablemanager.h6
-rw-r--r--src/plugins/coreplugin/vcsmanager.cpp66
-rw-r--r--src/plugins/coreplugin/vcsmanager.h23
-rw-r--r--src/plugins/cpaster/CodePaster.pluginspec20
-rw-r--r--src/plugins/cpaster/CodePaster.pluginspec.in19
-rw-r--r--src/plugins/cpaster/cpaster_dependencies.pri1
-rw-r--r--src/plugins/cpaster/cpasterplugin.cpp1
-rw-r--r--src/plugins/cpaster/fileshareprotocolsettingspage.cpp4
-rw-r--r--src/plugins/cpaster/settingspage.cpp5
-rw-r--r--src/plugins/cppeditor/CppEditor.pluginspec21
-rw-r--r--src/plugins/cppeditor/CppEditor.pluginspec.in21
-rw-r--r--src/plugins/cppeditor/cppautocompleter.cpp138
-rw-r--r--src/plugins/cppeditor/cppautocompleter.h58
-rw-r--r--src/plugins/cppeditor/cppcompleteswitch.cpp212
-rw-r--r--src/plugins/cppeditor/cppcompleteswitch.h52
-rw-r--r--src/plugins/cppeditor/cppeditor.cpp477
-rw-r--r--src/plugins/cppeditor/cppeditor.h28
-rw-r--r--src/plugins/cppeditor/cppeditor.pri2
-rw-r--r--src/plugins/cppeditor/cppeditor.pro21
-rw-r--r--src/plugins/cppeditor/cppeditorconstants.h2
-rw-r--r--src/plugins/cppeditor/cppinsertdecldef.cpp1
-rw-r--r--src/plugins/cppeditor/cppinsertqtpropertymembers.cpp194
-rw-r--r--src/plugins/cppeditor/cppinsertqtpropertymembers.h101
-rw-r--r--src/plugins/cppeditor/cppplugin.cpp8
-rw-r--r--src/plugins/cppeditor/cppqtstyleindenter.cpp140
-rw-r--r--src/plugins/cppeditor/cppqtstyleindenter.h59
-rw-r--r--src/plugins/cppeditor/cppquickfix.cpp65
-rw-r--r--src/plugins/cppeditor/cppquickfix.h39
-rw-r--r--src/plugins/cppeditor/cppquickfixcollector.cpp97
-rw-r--r--src/plugins/cppeditor/cppquickfixcollector.h65
-rw-r--r--src/plugins/cppeditor/cppquickfixes.cpp179
-rw-r--r--src/plugins/cppeditor/cppsnippetprovider.cpp74
-rw-r--r--src/plugins/cppeditor/cppsnippetprovider.h53
-rw-r--r--src/plugins/cppeditor/cpptypehierarchy.cpp102
-rw-r--r--src/plugins/cppeditor/cpptypehierarchy.h38
-rw-r--r--src/plugins/cpptools/CppTools.pluginspec22
-rw-r--r--src/plugins/cpptools/CppTools.pluginspec.in22
-rw-r--r--src/plugins/cpptools/completionsettingspage.cpp13
-rw-r--r--src/plugins/cpptools/completionsettingspage.h2
-rw-r--r--src/plugins/cpptools/cppcodecompletion.cpp45
-rw-r--r--src/plugins/cpptools/cppcodecompletion.h4
-rw-r--r--src/plugins/cpptools/cppcodeformatter.cpp74
-rw-r--r--src/plugins/cpptools/cppcodeformatter.h5
-rw-r--r--src/plugins/cpptools/cppfilesettingspage.cpp17
-rw-r--r--src/plugins/cpptools/cpptools.pri2
-rw-r--r--src/plugins/cpptools/cpptools.pro4
-rw-r--r--src/plugins/cpptools/cpptoolsplugin.cpp3
-rw-r--r--src/plugins/cpptools/insertionpointlocator.h2
-rw-r--r--src/plugins/cpptools/uicodecompletionsupport.cpp197
-rw-r--r--src/plugins/cpptools/uicodecompletionsupport.h70
-rw-r--r--src/plugins/cvs/CVS.pluginspec22
-rw-r--r--src/plugins/cvs/CVS.pluginspec.in22
-rw-r--r--src/plugins/cvs/cvs.pro2
-rw-r--r--src/plugins/cvs/cvsplugin.cpp1
-rw-r--r--src/plugins/cvs/settingspage.cpp15
-rw-r--r--src/plugins/cvs/settingspage.ui6
-rw-r--r--src/plugins/debugger/Debugger.pluginspec30
-rw-r--r--src/plugins/debugger/Debugger.pluginspec.in30
-rw-r--r--src/plugins/debugger/breakhandler.cpp1338
-rw-r--r--src/plugins/debugger/breakhandler.h192
-rw-r--r--src/plugins/debugger/breakpoint.cpp408
-rw-r--r--src/plugins/debugger/breakpoint.h145
-rw-r--r--src/plugins/debugger/breakpoint.ui50
-rw-r--r--src/plugins/debugger/breakpointmarker.cpp85
-rw-r--r--src/plugins/debugger/breakpointmarker.h62
-rw-r--r--src/plugins/debugger/breakwindow.cpp545
-rw-r--r--src/plugins/debugger/breakwindow.h19
-rw-r--r--src/plugins/debugger/cdb/cdb.pri2
-rw-r--r--src/plugins/debugger/cdb/cdbassembler.cpp43
-rw-r--r--src/plugins/debugger/cdb/cdbassembler.h18
-rw-r--r--src/plugins/debugger/cdb/cdbbreakpoint.cpp132
-rw-r--r--src/plugins/debugger/cdb/cdbbreakpoint.h19
-rw-r--r--src/plugins/debugger/cdb/cdbdebugeventcallback.cpp5
-rw-r--r--src/plugins/debugger/cdb/cdbengine.cpp328
-rw-r--r--src/plugins/debugger/cdb/cdbengine.h11
-rw-r--r--src/plugins/debugger/cdb/cdbengine_p.h2
-rw-r--r--src/plugins/debugger/cdb/cdbexceptionutils.cpp122
-rw-r--r--src/plugins/debugger/cdb/cdbexceptionutils.h15
-rw-r--r--src/plugins/debugger/cdb/cdbmodules.cpp18
-rw-r--r--src/plugins/debugger/cdb/cdbmodules.h7
-rw-r--r--src/plugins/debugger/cdb/cdboptions.cpp29
-rw-r--r--src/plugins/debugger/cdb/cdboptions.h1
-rw-r--r--src/plugins/debugger/cdb/cdbstackframecontext.cpp2
-rw-r--r--src/plugins/debugger/cdb/cdbstacktracecontext.cpp12
-rw-r--r--src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp3
-rw-r--r--src/plugins/debugger/cdb/cdbsymbolpathlisteditor.cpp138
-rw-r--r--src/plugins/debugger/cdb/cdbsymbolpathlisteditor.h89
-rw-r--r--src/plugins/debugger/cdb/corebreakpoint.cpp9
-rw-r--r--src/plugins/debugger/cdb/coreengine.cpp12
-rw-r--r--src/plugins/debugger/cdb/coreengine.h6
-rw-r--r--src/plugins/debugger/cdb2/bytearrayinputstream.cpp122
-rw-r--r--src/plugins/debugger/cdb2/bytearrayinputstream.h108
-rw-r--r--src/plugins/debugger/cdb2/cdb2.pri16
-rw-r--r--src/plugins/debugger/cdb2/cdbengine2.cpp1916
-rw-r--r--src/plugins/debugger/cdb2/cdbengine2.h209
-rw-r--r--src/plugins/debugger/cdb2/cdboptions2.cpp227
-rw-r--r--src/plugins/debugger/cdb2/cdboptions2.h78
-rw-r--r--src/plugins/debugger/cdb2/cdboptionspage2.cpp446
-rw-r--r--src/plugins/debugger/cdb2/cdboptionspage2.h138
-rw-r--r--src/plugins/debugger/cdb2/cdboptionspagewidget2.ui143
-rw-r--r--src/plugins/debugger/cdb2/cdbparsehelpers.cpp272
-rw-r--r--src/plugins/debugger/cdb2/cdbparsehelpers.h88
-rw-r--r--src/plugins/debugger/commonoptionspage.ui2
-rw-r--r--src/plugins/debugger/consolewindow.cpp48
-rw-r--r--src/plugins/debugger/debugger.pri2
-rw-r--r--src/plugins/debugger/debugger.pro28
-rw-r--r--src/plugins/debugger/debugger.qrc1
-rw-r--r--src/plugins/debugger/debuggeractions.cpp365
-rw-r--r--src/plugins/debugger/debuggeractions.h31
-rw-r--r--src/plugins/debugger/debuggeragents.cpp430
-rw-r--r--src/plugins/debugger/debuggeragents.h115
-rw-r--r--src/plugins/debugger/debuggerconstants.h125
-rw-r--r--src/plugins/debugger/debuggercore.h127
-rw-r--r--src/plugins/debugger/debuggerdialogs.cpp166
-rw-r--r--src/plugins/debugger/debuggerdialogs.h43
-rw-r--r--src/plugins/debugger/debuggerengine.cpp1000
-rw-r--r--src/plugins/debugger/debuggerengine.h179
-rw-r--r--src/plugins/debugger/debuggermainwindow.cpp700
-rw-r--r--src/plugins/debugger/debuggermainwindow.h52
-rw-r--r--src/plugins/debugger/debuggerplugin.cpp2941
-rw-r--r--src/plugins/debugger/debuggerplugin.h79
-rw-r--r--src/plugins/debugger/debuggerrunner.cpp660
-rw-r--r--src/plugins/debugger/debuggerrunner.h48
-rw-r--r--src/plugins/debugger/debuggerstreamops.cpp293
-rw-r--r--src/plugins/debugger/debuggerstreamops.h67
-rw-r--r--src/plugins/debugger/debuggertooltip.cpp62
-rw-r--r--src/plugins/debugger/debuggertooltip.h6
-rw-r--r--src/plugins/debugger/debuggeruiswitcher.cpp730
-rw-r--r--src/plugins/debugger/debuggeruiswitcher.h165
-rw-r--r--src/plugins/debugger/disassembleragent.cpp354
-rw-r--r--src/plugins/debugger/disassembleragent.h88
-rw-r--r--src/plugins/debugger/disassemblerlines.cpp86
-rw-r--r--src/plugins/debugger/disassemblerlines.h71
-rw-r--r--src/plugins/debugger/dumperoptionpage.ui10
-rw-r--r--src/plugins/debugger/gdb/abstractgdbadapter.cpp54
-rw-r--r--src/plugins/debugger/gdb/abstractgdbadapter.h26
-rw-r--r--src/plugins/debugger/gdb/abstractplaingdbadapter.cpp8
-rw-r--r--src/plugins/debugger/gdb/attachgdbadapter.cpp6
-rw-r--r--src/plugins/debugger/gdb/attachgdbadapter.h3
-rw-r--r--src/plugins/debugger/gdb/classicgdbengine.cpp24
-rw-r--r--src/plugins/debugger/gdb/coregdbadapter.cpp8
-rw-r--r--src/plugins/debugger/gdb/coregdbadapter.h4
-rw-r--r--src/plugins/debugger/gdb/gdbchooserwidget.cpp108
-rw-r--r--src/plugins/debugger/gdb/gdbchooserwidget.h18
-rw-r--r--src/plugins/debugger/gdb/gdbengine.cpp1503
-rw-r--r--src/plugins/debugger/gdb/gdbengine.h107
-rw-r--r--src/plugins/debugger/gdb/gdbmi.cpp2
-rw-r--r--src/plugins/debugger/gdb/gdbmi.h6
-rw-r--r--src/plugins/debugger/gdb/gdboptionspage.cpp212
-rw-r--r--src/plugins/debugger/gdb/gdboptionspage.h9
-rw-r--r--src/plugins/debugger/gdb/localplaingdbadapter.cpp12
-rw-r--r--src/plugins/debugger/gdb/localplaingdbadapter.h4
-rw-r--r--src/plugins/debugger/gdb/pythongdbengine.cpp7
-rw-r--r--src/plugins/debugger/gdb/remotegdbprocess.cpp136
-rw-r--r--src/plugins/debugger/gdb/remotegdbprocess.h14
-rw-r--r--src/plugins/debugger/gdb/remotegdbserveradapter.cpp78
-rw-r--r--src/plugins/debugger/gdb/remotegdbserveradapter.h11
-rw-r--r--src/plugins/debugger/gdb/remoteplaingdbadapter.cpp19
-rw-r--r--src/plugins/debugger/gdb/remoteplaingdbadapter.h7
-rw-r--r--src/plugins/debugger/gdb/symbian.cpp90
-rw-r--r--src/plugins/debugger/gdb/symbian.h14
-rw-r--r--src/plugins/debugger/gdb/tcftrkgdbadapter.cpp78
-rw-r--r--src/plugins/debugger/gdb/tcftrkgdbadapter.h5
-rw-r--r--src/plugins/debugger/gdb/termgdbadapter.cpp13
-rw-r--r--src/plugins/debugger/gdb/termgdbadapter.h5
-rw-r--r--src/plugins/debugger/gdb/trkgdbadapter.cpp79
-rw-r--r--src/plugins/debugger/gdb/trkgdbadapter.h6
-rw-r--r--src/plugins/debugger/images/tracepoint.pngbin0 -> 641 bytes
-rw-r--r--src/plugins/debugger/lldb/guest/README31
-rw-r--r--src/plugins/debugger/lldb/guest/lldbengineguest.cpp768
-rw-r--r--src/plugins/debugger/lldb/guest/lldbengineguest.h136
-rw-r--r--src/plugins/debugger/lldb/guest/main.cpp121
-rw-r--r--src/plugins/debugger/lldb/guest/qtcreator-lldb.plist21
-rw-r--r--src/plugins/debugger/lldb/guest/qtcreator-lldb.pri2
-rw-r--r--src/plugins/debugger/lldb/guest/qtcreator-lldb.pro61
-rw-r--r--src/plugins/debugger/lldb/ipcengineguest.cpp637
-rw-r--r--src/plugins/debugger/lldb/ipcengineguest.h191
-rw-r--r--src/plugins/debugger/lldb/ipcenginehost.cpp655
-rw-r--r--src/plugins/debugger/lldb/ipcenginehost.h139
-rw-r--r--src/plugins/debugger/lldb/lldbenginehost.cpp232
-rw-r--r--src/plugins/debugger/lldb/lldbenginehost.h87
-rw-r--r--src/plugins/debugger/lldb/lldbhost.pri20
-rw-r--r--src/plugins/debugger/lldb/lldboptionspage.cpp132
-rw-r--r--src/plugins/debugger/lldb/lldboptionspage.h88
-rw-r--r--src/plugins/debugger/lldb/lldboptionspagewidget.ui59
-rw-r--r--src/plugins/debugger/logwindow.cpp65
-rw-r--r--src/plugins/debugger/logwindow.h2
-rw-r--r--src/plugins/debugger/memoryagent.cpp174
-rw-r--r--src/plugins/debugger/memoryagent.h82
-rw-r--r--src/plugins/debugger/moduleshandler.cpp85
-rw-r--r--src/plugins/debugger/moduleshandler.h66
-rw-r--r--src/plugins/debugger/moduleswindow.cpp105
-rw-r--r--src/plugins/debugger/moduleswindow.h3
-rw-r--r--src/plugins/debugger/pdb/pdbengine.cpp95
-rw-r--r--src/plugins/debugger/pdb/pdbengine.h7
-rw-r--r--src/plugins/debugger/qml/qmladapter.cpp13
-rw-r--r--src/plugins/debugger/qml/qmladapter.h4
-rw-r--r--src/plugins/debugger/qml/qmlcppengine.cpp523
-rw-r--r--src/plugins/debugger/qml/qmlcppengine.h32
-rw-r--r--src/plugins/debugger/qml/qmlengine.cpp577
-rw-r--r--src/plugins/debugger/qml/qmlengine.h50
-rw-r--r--src/plugins/debugger/qml/scriptconsole.cpp1
-rw-r--r--src/plugins/debugger/registerhandler.cpp94
-rw-r--r--src/plugins/debugger/registerhandler.h16
-rw-r--r--src/plugins/debugger/registerwindow.cpp98
-rw-r--r--src/plugins/debugger/registerwindow.h5
-rw-r--r--src/plugins/debugger/script/scriptengine.cpp81
-rw-r--r--src/plugins/debugger/script/scriptengine.h7
-rw-r--r--src/plugins/debugger/sessionengine.cpp82
-rw-r--r--src/plugins/debugger/sessionengine.h70
-rw-r--r--src/plugins/debugger/shared/cdbsymbolpathlisteditor.cpp207
-rw-r--r--src/plugins/debugger/shared/cdbsymbolpathlisteditor.h99
-rw-r--r--src/plugins/debugger/shared/dbgwinutils.cpp154
-rw-r--r--src/plugins/debugger/shared/dbgwinutils.h32
-rw-r--r--src/plugins/debugger/shared/shared.pri13
-rw-r--r--src/plugins/debugger/snapshothandler.cpp116
-rw-r--r--src/plugins/debugger/snapshothandler.h19
-rw-r--r--src/plugins/debugger/snapshotwindow.cpp58
-rw-r--r--src/plugins/debugger/snapshotwindow.h13
-rw-r--r--src/plugins/debugger/sourceagent.cpp187
-rw-r--r--src/plugins/debugger/sourceagent.h62
-rw-r--r--src/plugins/debugger/sourcefileshandler.cpp27
-rw-r--r--src/plugins/debugger/sourcefileshandler.h8
-rw-r--r--src/plugins/debugger/sourcefileswindow.cpp36
-rw-r--r--src/plugins/debugger/sourcefileswindow.h4
-rw-r--r--src/plugins/debugger/stackframe.cpp36
-rw-r--r--src/plugins/debugger/stackframe.h10
-rw-r--r--src/plugins/debugger/stackhandler.cpp78
-rw-r--r--src/plugins/debugger/stackhandler.h21
-rw-r--r--src/plugins/debugger/stackwindow.cpp89
-rw-r--r--src/plugins/debugger/stackwindow.h6
-rw-r--r--src/plugins/debugger/startremotedialog.ui39
-rw-r--r--src/plugins/debugger/startremoteenginedialog.ui110
-rw-r--r--src/plugins/debugger/tcf/json.h4
-rw-r--r--src/plugins/debugger/tcf/tcfengine.h4
-rw-r--r--src/plugins/debugger/threaddata.h94
-rw-r--r--src/plugins/debugger/threadshandler.cpp113
-rw-r--r--src/plugins/debugger/threadshandler.h58
-rw-r--r--src/plugins/debugger/threadswindow.cpp25
-rw-r--r--src/plugins/debugger/threadswindow.h2
-rw-r--r--src/plugins/debugger/watchdata.cpp124
-rw-r--r--src/plugins/debugger/watchdata.h112
-rw-r--r--src/plugins/debugger/watchhandler.cpp356
-rw-r--r--src/plugins/debugger/watchhandler.h28
-rw-r--r--src/plugins/debugger/watchutils.cpp183
-rw-r--r--src/plugins/debugger/watchutils.h4
-rw-r--r--src/plugins/debugger/watchwindow.cpp344
-rw-r--r--src/plugins/debugger/watchwindow.h7
-rw-r--r--src/plugins/designer/Designer.pluginspec21
-rw-r--r--src/plugins/designer/Designer.pluginspec.in22
-rw-r--r--src/plugins/designer/designer.pri2
-rw-r--r--src/plugins/designer/designer.pro2
-rw-r--r--src/plugins/designer/designer_dependencies.pri4
-rw-r--r--src/plugins/designer/formeditorplugin.cpp14
-rw-r--r--src/plugins/designer/formeditorplugin.h3
-rw-r--r--src/plugins/designer/formeditorstack.h2
-rw-r--r--src/plugins/designer/formeditorw.cpp17
-rw-r--r--src/plugins/designer/formeditorw.h12
-rw-r--r--src/plugins/designer/formwindoweditor.cpp1
-rw-r--r--src/plugins/designer/qtcreatorintegration.cpp60
-rw-r--r--src/plugins/designer/settingspage.cpp44
-rw-r--r--src/plugins/designer/settingspage.h19
-rw-r--r--src/plugins/fakevim/FakeVim.pluginspec21
-rw-r--r--src/plugins/fakevim/FakeVim.pluginspec.in21
-rw-r--r--src/plugins/fakevim/fakevim.pro1
-rw-r--r--src/plugins/fakevim/fakevimhandler.cpp89
-rw-r--r--src/plugins/fakevim/fakevimhandler.h4
-rw-r--r--src/plugins/fakevim/fakevimoptions.ui6
-rw-r--r--src/plugins/fakevim/fakevimplugin.cpp180
-rw-r--r--src/plugins/find/Find.pluginspec19
-rw-r--r--src/plugins/find/Find.pluginspec.in19
-rw-r--r--src/plugins/find/find.pri2
-rw-r--r--src/plugins/find/find.pro2
-rw-r--r--src/plugins/genericprojectmanager/GenericProjectManager.pluginspec22
-rw-r--r--src/plugins/genericprojectmanager/GenericProjectManager.pluginspec.in21
-rw-r--r--src/plugins/genericprojectmanager/genericbuildconfiguration.cpp6
-rw-r--r--src/plugins/genericprojectmanager/genericbuildconfiguration.h1
-rw-r--r--src/plugins/genericprojectmanager/genericmakestep.cpp62
-rw-r--r--src/plugins/genericprojectmanager/genericmakestep.h4
-rw-r--r--src/plugins/genericprojectmanager/genericproject.cpp52
-rw-r--r--src/plugins/genericprojectmanager/genericproject.h20
-rw-r--r--src/plugins/genericprojectmanager/genericprojectmanager.h1
-rw-r--r--src/plugins/genericprojectmanager/genericprojectmanager.pro1
-rw-r--r--src/plugins/genericprojectmanager/genericprojectmanager_dependencies.pri1
-rw-r--r--src/plugins/genericprojectmanager/genericprojectplugin.cpp2
-rw-r--r--src/plugins/genericprojectmanager/generictarget.cpp10
-rw-r--r--src/plugins/genericprojectmanager/generictarget.h4
-rw-r--r--src/plugins/git/ScmGit.pluginspec22
-rw-r--r--src/plugins/git/ScmGit.pluginspec.in22
-rw-r--r--src/plugins/git/changeselectiondialog.cpp4
-rw-r--r--src/plugins/git/changeselectiondialog.ui6
-rw-r--r--src/plugins/git/clonewizardpage.cpp2
-rw-r--r--src/plugins/git/git.pro1
-rw-r--r--src/plugins/git/gitclient.cpp498
-rw-r--r--src/plugins/git/gitclient.h43
-rw-r--r--src/plugins/git/giteditor.cpp2
-rw-r--r--src/plugins/git/giteditor.h2
-rw-r--r--src/plugins/git/gitorious/gitorious.h2
-rw-r--r--src/plugins/git/gitplugin.cpp7
-rw-r--r--src/plugins/git/gitsettings.cpp24
-rw-r--r--src/plugins/git/gitsettings.h4
-rw-r--r--src/plugins/git/gitsubmiteditor.cpp19
-rw-r--r--src/plugins/git/gitsubmiteditor.h2
-rw-r--r--src/plugins/git/gitsubmiteditorwidget.cpp25
-rw-r--r--src/plugins/git/gitsubmiteditorwidget.h1
-rw-r--r--src/plugins/git/gitutils.cpp16
-rw-r--r--src/plugins/git/gitutils.h3
-rw-r--r--src/plugins/git/gitversioncontrol.cpp2
-rw-r--r--src/plugins/git/settingspage.cpp26
-rw-r--r--src/plugins/git/settingspage.ui23
-rw-r--r--src/plugins/glsleditor/GLSLEditor.mimetypes.xml36
-rw-r--r--src/plugins/glsleditor/GLSLEditor.pluginspec.in21
-rw-r--r--src/plugins/glsleditor/glslautocompleter.cpp137
-rw-r--r--src/plugins/glsleditor/glslautocompleter.h62
-rw-r--r--src/plugins/glsleditor/glslcodecompletion.cpp726
-rw-r--r--src/plugins/glsleditor/glslcodecompletion.h126
-rw-r--r--src/plugins/glsleditor/glsleditor.cpp419
-rw-r--r--src/plugins/glsleditor/glsleditor.h129
-rw-r--r--src/plugins/glsleditor/glsleditor.pri3
-rw-r--r--src/plugins/glsleditor/glsleditor.pro39
-rw-r--r--src/plugins/glsleditor/glsleditor.qrc15
-rw-r--r--src/plugins/glsleditor/glsleditor_dependencies.pri7
-rw-r--r--src/plugins/glsleditor/glsleditor_global.h41
-rw-r--r--src/plugins/glsleditor/glsleditoractionhandler.cpp57
-rw-r--r--src/plugins/glsleditor/glsleditoractionhandler.h51
-rw-r--r--src/plugins/glsleditor/glsleditorconstants.h64
-rw-r--r--src/plugins/glsleditor/glsleditoreditable.cpp59
-rw-r--r--src/plugins/glsleditor/glsleditoreditable.h62
-rw-r--r--src/plugins/glsleditor/glsleditorfactory.cpp104
-rw-r--r--src/plugins/glsleditor/glsleditorfactory.h71
-rw-r--r--src/plugins/glsleditor/glsleditorplugin.cpp316
-rw-r--r--src/plugins/glsleditor/glsleditorplugin.h126
-rw-r--r--src/plugins/glsleditor/glslfilewizard.cpp160
-rw-r--r--src/plugins/glsleditor/glslfilewizard.h73
-rw-r--r--src/plugins/glsleditor/glslhighlighter.cpp404
-rw-r--r--src/plugins/glsleditor/glslhighlighter.h82
-rw-r--r--src/plugins/glsleditor/glslhoverhandler.cpp77
-rw-r--r--src/plugins/glsleditor/glslhoverhandler.h64
-rw-r--r--src/plugins/glsleditor/glslindenter.cpp116
-rw-r--r--src/plugins/glsleditor/glslindenter.h63
-rw-r--r--src/plugins/glsleditor/images/attribute.pngbin0 -> 583 bytes
-rw-r--r--src/plugins/glsleditor/images/const.pngbin0 -> 478 bytes
-rw-r--r--src/plugins/glsleditor/images/func.pngbin0 -> 583 bytes
-rw-r--r--src/plugins/glsleditor/images/glslfile.pngbin0 -> 321 bytes
-rw-r--r--src/plugins/glsleditor/images/keyword.pngbin0 -> 341 bytes
-rw-r--r--src/plugins/glsleditor/images/other.pngbin0 -> 377 bytes
-rw-r--r--src/plugins/glsleditor/images/type.pngbin0 -> 573 bytes
-rw-r--r--src/plugins/glsleditor/images/uniform.pngbin0 -> 583 bytes
-rw-r--r--src/plugins/glsleditor/images/var.pngbin0 -> 530 bytes
-rw-r--r--src/plugins/glsleditor/images/varying.pngbin0 -> 585 bytes
-rw-r--r--src/plugins/helloworld/HelloWorld.pluginspec18
-rw-r--r--src/plugins/helloworld/HelloWorld.pluginspec.in18
-rw-r--r--src/plugins/helloworld/helloworld.pro2
-rw-r--r--src/plugins/helloworld/helloworldplugin.cpp44
-rw-r--r--src/plugins/helloworld/helloworldplugin.h2
-rw-r--r--src/plugins/helloworld/helloworldwindow.h2
-rw-r--r--src/plugins/help/Help.pluginspec21
-rw-r--r--src/plugins/help/Help.pluginspec.in21
-rw-r--r--src/plugins/help/centralwidget.cpp2
-rw-r--r--src/plugins/help/generalsettingspage.cpp113
-rw-r--r--src/plugins/help/generalsettingspage.h4
-rw-r--r--src/plugins/help/help.pro8
-rw-r--r--src/plugins/help/helpconstants.h1
-rw-r--r--src/plugins/help/helpindexfilter.cpp2
-rw-r--r--src/plugins/help/helpmanager.cpp115
-rw-r--r--src/plugins/help/helpmode.cpp15
-rw-r--r--src/plugins/help/helpmode.h28
-rw-r--r--src/plugins/help/helpplugin.cpp71
-rw-r--r--src/plugins/help/helpplugin.h4
-rw-r--r--src/plugins/help/helpviewer.cpp9
-rw-r--r--src/plugins/help/helpviewer_qtb.cpp2
-rw-r--r--src/plugins/help/helpviewer_qwv.cpp2
-rw-r--r--src/plugins/help/localhelpmanager.cpp115
-rw-r--r--src/plugins/help/localhelpmanager.h (renamed from src/plugins/help/helpmanager.h)0
-rw-r--r--src/plugins/help/openpagesmanager.cpp2
-rw-r--r--src/plugins/help/searchwidget.cpp2
-rw-r--r--src/plugins/imageviewer/ImageViewer.pluginspec19
-rw-r--r--src/plugins/imageviewer/ImageViewer.pluginspec.in19
-rw-r--r--src/plugins/imageviewer/imageviewer.pro1
-rw-r--r--src/plugins/locator/Locator.pluginspec19
-rw-r--r--src/plugins/locator/Locator.pluginspec.in19
-rw-r--r--src/plugins/locator/locator.pri2
-rw-r--r--src/plugins/locator/locator.pro2
-rw-r--r--src/plugins/locator/locatorfiltersfilter.cpp2
-rw-r--r--src/plugins/locator/locatorplugin.cpp12
-rw-r--r--src/plugins/locator/locatorwidget.cpp44
-rw-r--r--src/plugins/locator/locatorwidget.h1
-rw-r--r--src/plugins/locator/opendocumentsfilter.cpp2
-rw-r--r--src/plugins/mercurial/Mercurial.pluginspec22
-rw-r--r--src/plugins/mercurial/Mercurial.pluginspec.in22
-rw-r--r--src/plugins/mercurial/mercurial.pro1
-rw-r--r--src/plugins/mercurial/mercurialplugin.cpp2
-rw-r--r--src/plugins/mercurial/optionspage.cpp18
-rw-r--r--src/plugins/mercurial/optionspage.ui8
-rw-r--r--src/plugins/perforce/Perforce.pluginspec22
-rw-r--r--src/plugins/perforce/Perforce.pluginspec.in22
-rw-r--r--src/plugins/perforce/perforce.pro2
-rw-r--r--src/plugins/perforce/perforceplugin.cpp5
-rw-r--r--src/plugins/perforce/perforcesettings.cpp2
-rw-r--r--src/plugins/perforce/perforcesettings.h2
-rw-r--r--src/plugins/perforce/perforceversioncontrol.cpp2
-rw-r--r--src/plugins/perforce/settingspage.cpp18
-rw-r--r--src/plugins/perforce/settingspage.ui16
-rw-r--r--src/plugins/plugins.pro31
-rw-r--r--src/plugins/projectexplorer/ProjectExplorer.pluginspec26
-rw-r--r--src/plugins/projectexplorer/ProjectExplorer.pluginspec.in26
-rw-r--r--src/plugins/projectexplorer/abstractprocessstep.cpp81
-rw-r--r--src/plugins/projectexplorer/abstractprocessstep.h43
-rw-r--r--src/plugins/projectexplorer/allprojectsfilter.h1
-rw-r--r--src/plugins/projectexplorer/allprojectsfind.cpp37
-rw-r--r--src/plugins/projectexplorer/allprojectsfind.h7
-rw-r--r--src/plugins/projectexplorer/applicationlauncher.h8
-rw-r--r--src/plugins/projectexplorer/applicationlauncher_win.cpp4
-rw-r--r--src/plugins/projectexplorer/applicationlauncher_x11.cpp11
-rw-r--r--src/plugins/projectexplorer/applicationrunconfiguration.cpp120
-rw-r--r--src/plugins/projectexplorer/applicationrunconfiguration.h46
-rw-r--r--src/plugins/projectexplorer/baseprojectwizarddialog.cpp13
-rw-r--r--src/plugins/projectexplorer/baseprojectwizarddialog.h4
-rw-r--r--src/plugins/projectexplorer/buildconfigdialog.cpp124
-rw-r--r--src/plugins/projectexplorer/buildconfigdialog.h77
-rw-r--r--src/plugins/projectexplorer/buildconfiguration.cpp26
-rw-r--r--src/plugins/projectexplorer/buildconfiguration.h23
-rw-r--r--src/plugins/projectexplorer/buildsettingspropertiespage.cpp2
-rw-r--r--src/plugins/projectexplorer/buildsettingspropertiespage.h1
-rw-r--r--src/plugins/projectexplorer/buildsteplist.h2
-rw-r--r--src/plugins/projectexplorer/buildstepspage.cpp5
-rw-r--r--src/plugins/projectexplorer/buildstepspage.h6
-rw-r--r--src/plugins/projectexplorer/copytaskhandler.cpp9
-rw-r--r--src/plugins/projectexplorer/copytaskhandler.h4
-rw-r--r--src/plugins/projectexplorer/currentprojectfilter.cpp4
-rw-r--r--src/plugins/projectexplorer/currentprojectfilter.h2
-rw-r--r--src/plugins/projectexplorer/currentprojectfind.cpp55
-rw-r--r--src/plugins/projectexplorer/currentprojectfind.h13
-rw-r--r--src/plugins/projectexplorer/customexecutableconfigurationwidget.cpp265
-rw-r--r--src/plugins/projectexplorer/customexecutableconfigurationwidget.h95
-rw-r--r--src/plugins/projectexplorer/customexecutablerunconfiguration.cpp260
-rw-r--r--src/plugins/projectexplorer/customexecutablerunconfiguration.h73
-rw-r--r--src/plugins/projectexplorer/customwizard/customwizard.cpp4
-rw-r--r--src/plugins/projectexplorer/customwizard/customwizard.h2
-rw-r--r--src/plugins/projectexplorer/customwizard/customwizardparameters.cpp11
-rw-r--r--src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.h2
-rw-r--r--src/plugins/projectexplorer/debugginghelper.h1
-rw-r--r--src/plugins/projectexplorer/deployconfiguration.h4
-rw-r--r--src/plugins/projectexplorer/editorconfiguration.cpp2
-rw-r--r--src/plugins/projectexplorer/environmenteditmodel.cpp9
-rw-r--r--src/plugins/projectexplorer/filewatcher.h1
-rw-r--r--src/plugins/projectexplorer/foldernavigationwidget.cpp5
-rw-r--r--src/plugins/projectexplorer/gccparser.cpp6
-rw-r--r--src/plugins/projectexplorer/gnumakeparser.cpp15
-rw-r--r--src/plugins/projectexplorer/gnumakeparser.h6
-rw-r--r--src/plugins/projectexplorer/ioutputparser.cpp15
-rw-r--r--src/plugins/projectexplorer/ioutputparser.h8
-rw-r--r--src/plugins/projectexplorer/iprojectmanager.h4
-rw-r--r--src/plugins/projectexplorer/iprojectproperties.h4
-rw-r--r--src/plugins/projectexplorer/ldparser.cpp4
-rw-r--r--src/plugins/projectexplorer/linuxiccparser.cpp6
-rw-r--r--src/plugins/projectexplorer/localapplicationruncontrol.cpp141
-rw-r--r--src/plugins/projectexplorer/localapplicationruncontrol.h76
-rw-r--r--src/plugins/projectexplorer/miniprojecttargetselector.cpp4
-rw-r--r--src/plugins/projectexplorer/msvcparser.cpp2
-rw-r--r--src/plugins/projectexplorer/outputformatter.cpp4
-rw-r--r--src/plugins/projectexplorer/outputformatter.h9
-rw-r--r--src/plugins/projectexplorer/outputwindow.cpp34
-rw-r--r--src/plugins/projectexplorer/outputwindow.h3
-rw-r--r--src/plugins/projectexplorer/pluginfilefactory.h1
-rw-r--r--src/plugins/projectexplorer/processparameters.cpp149
-rw-r--r--src/plugins/projectexplorer/processparameters.h109
-rw-r--r--src/plugins/projectexplorer/processstep.cpp45
-rw-r--r--src/plugins/projectexplorer/processstep.h6
-rw-r--r--src/plugins/projectexplorer/project.cpp19
-rw-r--r--src/plugins/projectexplorer/project.h3
-rw-r--r--src/plugins/projectexplorer/projectconfiguration.cpp4
-rw-r--r--src/plugins/projectexplorer/projectexplorer.cpp404
-rw-r--r--src/plugins/projectexplorer/projectexplorer.h17
-rw-r--r--src/plugins/projectexplorer/projectexplorer.pri2
-rw-r--r--src/plugins/projectexplorer/projectexplorer.pro23
-rw-r--r--src/plugins/projectexplorer/projectexplorerconstants.h19
-rw-r--r--src/plugins/projectexplorer/projectexplorersettingspage.cpp18
-rw-r--r--src/plugins/projectexplorer/projectexplorersettingspage.h1
-rw-r--r--src/plugins/projectexplorer/projectmodels.cpp77
-rw-r--r--src/plugins/projectexplorer/projectmodels.h2
-rw-r--r--src/plugins/projectexplorer/projectnodes.cpp12
-rw-r--r--src/plugins/projectexplorer/projectnodes.h6
-rw-r--r--src/plugins/projectexplorer/projecttreewidget.cpp15
-rw-r--r--src/plugins/projectexplorer/projecttreewidget.h4
-rw-r--r--src/plugins/projectexplorer/projectwelcomepagewidget.cpp2
-rw-r--r--src/plugins/projectexplorer/projectwindow.cpp29
-rw-r--r--src/plugins/projectexplorer/projectwindow.h1
-rw-r--r--src/plugins/projectexplorer/publishing/ipublishingwizardfactory.h96
-rw-r--r--src/plugins/projectexplorer/publishing/publishingwizardselectiondialog.cpp89
-rw-r--r--src/plugins/projectexplorer/publishing/publishingwizardselectiondialog.h68
-rw-r--r--src/plugins/projectexplorer/publishing/publishingwizardselectiondialog.ui98
-rw-r--r--src/plugins/projectexplorer/runconfiguration.h4
-rw-r--r--src/plugins/projectexplorer/runsettingspropertiespage.cpp2
-rw-r--r--src/plugins/projectexplorer/runsettingspropertiespage.h1
-rw-r--r--src/plugins/projectexplorer/session.cpp87
-rw-r--r--src/plugins/projectexplorer/session.h22
-rw-r--r--src/plugins/projectexplorer/sessionnodeimpl.cpp59
-rw-r--r--src/plugins/projectexplorer/sessionnodeimpl.h61
-rw-r--r--src/plugins/projectexplorer/showineditortaskhandler.cpp1
-rw-r--r--src/plugins/projectexplorer/showineditortaskhandler.h4
-rw-r--r--src/plugins/projectexplorer/showoutputtaskhandler.h4
-rw-r--r--src/plugins/projectexplorer/target.cpp7
-rw-r--r--src/plugins/projectexplorer/target.h5
-rw-r--r--src/plugins/projectexplorer/targetsettingspanel.cpp36
-rw-r--r--src/plugins/projectexplorer/targetsettingspanel.h3
-rw-r--r--src/plugins/projectexplorer/taskwindow.cpp229
-rw-r--r--src/plugins/projectexplorer/toolchain.cpp76
-rw-r--r--src/plugins/projectexplorer/toolchain.h25
-rw-r--r--src/plugins/projectexplorer/toolchaintype.h59
-rw-r--r--src/plugins/projectexplorer/userfileaccessor.cpp485
-rw-r--r--src/plugins/projectexplorer/vcsannotatetaskhandler.h4
-rw-r--r--src/plugins/projectexplorer/winguiprocess.cpp13
-rw-r--r--src/plugins/projectexplorer/winguiprocess.h4
-rw-r--r--src/plugins/qmldesigner/QmlDesigner.pluginspec27
-rw-r--r--src/plugins/qmldesigner/QmlDesigner.pluginspec.in27
-rw-r--r--src/plugins/qmldesigner/components/formeditor/abstractformeditortool.h2
-rw-r--r--src/plugins/qmldesigner/components/formeditor/anchortool.cpp4
-rw-r--r--src/plugins/qmldesigner/components/formeditor/anchortool.h2
-rw-r--r--src/plugins/qmldesigner/components/formeditor/dragtool.cpp83
-rw-r--r--src/plugins/qmldesigner/components/formeditor/dragtool.h29
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp11
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp16
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditorview.cpp104
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditorview.h9
-rw-r--r--src/plugins/qmldesigner/components/formeditor/itemcreatortool.cpp9
-rw-r--r--src/plugins/qmldesigner/components/formeditor/itemcreatortool.h2
-rw-r--r--src/plugins/qmldesigner/components/formeditor/itemutilfunctions.cpp1
-rw-r--r--src/plugins/qmldesigner/components/formeditor/movetool.cpp5
-rw-r--r--src/plugins/qmldesigner/components/formeditor/movetool.h4
-rw-r--r--src/plugins/qmldesigner/components/formeditor/resizetool.cpp4
-rw-r--r--src/plugins/qmldesigner/components/formeditor/resizetool.h2
-rw-r--r--src/plugins/qmldesigner/components/formeditor/scaleitem.h2
-rw-r--r--src/plugins/qmldesigner/components/formeditor/selectiontool.cpp4
-rw-r--r--src/plugins/qmldesigner/components/formeditor/selectiontool.h2
-rw-r--r--src/plugins/qmldesigner/components/formeditor/zoomaction.cpp1
-rw-r--r--src/plugins/qmldesigner/components/integration/componentview.cpp6
-rw-r--r--src/plugins/qmldesigner/components/integration/componentview.h4
-rw-r--r--src/plugins/qmldesigner/components/integration/designdocumentcontroller.cpp33
-rw-r--r--src/plugins/qmldesigner/components/integration/designdocumentcontroller.h8
-rw-r--r--src/plugins/qmldesigner/components/integration/designdocumentcontrollerview.cpp30
-rw-r--r--src/plugins/qmldesigner/components/integration/designdocumentcontrollerview.h3
-rw-r--r--src/plugins/qmldesigner/components/integration/integrationcore.cpp2
-rw-r--r--src/plugins/qmldesigner/components/integration/integrationcore.h2
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/images/item-default-icon.pngbin590 -> 317 bytes
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/images/item-invalid-icon.pngbin0 -> 603 bytes
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrary.cpp335
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrary.h82
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrary.pri4
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrary.qrc1
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrarycomponents.cpp207
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrarycomponents.h (renamed from src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidgets.h)0
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp82
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.h5
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp136
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.h90
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp487
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h107
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidgets.cpp208
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp48
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigatortreeview.cpp114
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigatorview.cpp19
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigatorview.h6
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/basiclayouts.h6
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/basicwidgets.cpp49
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/basicwidgets.h68
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/behaviordialog.cpp2
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/behaviordialog.h4
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/colorwidget.cpp993
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/colorwidget.h322
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/fontwidget.h2
-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/gradientlineqmladaptor.cpp153
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/gradientlineqmladaptor.h39
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditor.cpp72
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditor.h5
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditor.pri9
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditortransaction.cpp2
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp13
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.h8
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qlayoutobject.h2
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qmlanchorbindingproxy.h2
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qproxylayoutitem.h4
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/down.pngbin594 -> 0 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/edit.pngbin503 -> 0 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/editdelete.pngbin831 -> 0 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/minus.pngbin250 -> 0 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/plus.pngbin462 -> 0 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/spreadpad.pngbin151 -> 0 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/spreadreflect.pngbin165 -> 0 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/spreadrepeat.pngbin156 -> 0 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/typeconical.pngbin937 -> 0 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/typelinear.pngbin145 -> 0 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/typeradial.pngbin583 -> 0 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/up.pngbin692 -> 0 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/zoomin.pngbin1208 -> 0 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/zoomout.pngbin1226 -> 0 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.cpp2
-rw-r--r--src/plugins/qmldesigner/components/stateseditor/stateseditorimageprovider.cpp44
-rw-r--r--src/plugins/qmldesigner/components/stateseditor/stateseditorimageprovider.h12
-rw-r--r--src/plugins/qmldesigner/components/stateseditor/stateseditormodel.cpp152
-rw-r--r--src/plugins/qmldesigner/components/stateseditor/stateseditormodel.h22
-rw-r--r--src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp601
-rw-r--r--src/plugins/qmldesigner/components/stateseditor/stateseditorview.h54
-rw-r--r--src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.cpp150
-rw-r--r--src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.h21
-rw-r--r--src/plugins/qmldesigner/components/stateseditor/stateslist.qml48
-rw-r--r--src/plugins/qmldesigner/designercore/designercore.pri103
-rw-r--r--src/plugins/qmldesigner/designercore/designercore.qrc6
-rw-r--r--src/plugins/qmldesigner/designercore/exceptions/exceptions.pri2
-rw-r--r--src/plugins/qmldesigner/designercore/include/abstractproperty.h2
-rw-r--r--src/plugins/qmldesigner/designercore/include/abstractview.h13
-rw-r--r--src/plugins/qmldesigner/designercore/include/commondefines.h31
-rw-r--r--src/plugins/qmldesigner/designercore/include/enumeratormetainfo.h90
-rw-r--r--src/plugins/qmldesigner/designercore/include/import.h9
-rw-r--r--src/plugins/qmldesigner/designercore/include/itemlibraryinfo.h7
-rw-r--r--src/plugins/qmldesigner/designercore/include/metainfo.h20
-rw-r--r--src/plugins/qmldesigner/designercore/include/metainfoparser.h10
-rw-r--r--src/plugins/qmldesigner/designercore/include/model.h5
-rw-r--r--src/plugins/qmldesigner/designercore/include/modelnode.h3
-rw-r--r--src/plugins/qmldesigner/designercore/include/modelutilities.h55
-rw-r--r--src/plugins/qmldesigner/designercore/include/nodeabstractproperty.h2
-rw-r--r--src/plugins/qmldesigner/designercore/include/nodeinstance.h183
-rw-r--r--src/plugins/qmldesigner/designercore/include/nodeinstanceclientinterface.h32
-rw-r--r--src/plugins/qmldesigner/designercore/include/nodeinstanceserverinterface.h52
-rw-r--r--src/plugins/qmldesigner/designercore/include/nodeinstanceview.h115
-rw-r--r--src/plugins/qmldesigner/designercore/include/nodelistproperty.h3
-rw-r--r--src/plugins/qmldesigner/designercore/include/nodemetainfo.h73
-rw-r--r--src/plugins/qmldesigner/designercore/include/propertyabstractcontainer.h40
-rw-r--r--src/plugins/qmldesigner/designercore/include/propertybindingcontainer.h38
-rw-r--r--src/plugins/qmldesigner/designercore/include/propertycontainer.h2
-rw-r--r--src/plugins/qmldesigner/designercore/include/propertymetainfo.h127
-rw-r--r--src/plugins/qmldesigner/designercore/include/propertyvaluecontainer.h42
-rw-r--r--src/plugins/qmldesigner/designercore/include/qmlitemnode.h4
-rw-r--r--src/plugins/qmldesigner/designercore/include/qmlmodelview.h3
-rw-r--r--src/plugins/qmldesigner/designercore/include/qmlobjectnode.h2
-rw-r--r--src/plugins/qmldesigner/designercore/include/rewriterview.h15
-rw-r--r--src/plugins/qmldesigner/designercore/instances/addimportcommand.cpp65
-rw-r--r--src/plugins/qmldesigner/designercore/instances/addimportcommand.h39
-rw-r--r--src/plugins/qmldesigner/designercore/instances/behaviornodeinstance.cpp12
-rw-r--r--src/plugins/qmldesigner/designercore/instances/behaviornodeinstance.h2
-rw-r--r--src/plugins/qmldesigner/designercore/instances/changebindingscommand.cpp32
-rw-r--r--src/plugins/qmldesigner/designercore/instances/changebindingscommand.h32
-rw-r--r--src/plugins/qmldesigner/designercore/instances/changefileurlcommand.cpp33
-rw-r--r--src/plugins/qmldesigner/designercore/instances/changefileurlcommand.h30
-rw-r--r--src/plugins/qmldesigner/designercore/instances/changeidscommand.cpp33
-rw-r--r--src/plugins/qmldesigner/designercore/instances/changeidscommand.h32
-rw-r--r--src/plugins/qmldesigner/designercore/instances/changestatecommand.cpp34
-rw-r--r--src/plugins/qmldesigner/designercore/instances/changestatecommand.h32
-rw-r--r--src/plugins/qmldesigner/designercore/instances/changevaluescommand.cpp33
-rw-r--r--src/plugins/qmldesigner/designercore/instances/changevaluescommand.h32
-rw-r--r--src/plugins/qmldesigner/designercore/instances/childrenchangedcommand.cpp42
-rw-r--r--src/plugins/qmldesigner/designercore/instances/childrenchangedcommand.h32
-rw-r--r--src/plugins/qmldesigner/designercore/instances/childrenchangeeventfilter.cpp29
-rw-r--r--src/plugins/qmldesigner/designercore/instances/childrenchangeeventfilter.h27
-rw-r--r--src/plugins/qmldesigner/designercore/instances/clearscenecommand.cpp19
-rw-r--r--src/plugins/qmldesigner/designercore/instances/clearscenecommand.h21
-rw-r--r--src/plugins/qmldesigner/designercore/instances/completecomponentcommand.cpp33
-rw-r--r--src/plugins/qmldesigner/designercore/instances/completecomponentcommand.h30
-rw-r--r--src/plugins/qmldesigner/designercore/instances/componentcompletedcommand.cpp34
-rw-r--r--src/plugins/qmldesigner/designercore/instances/componentcompletedcommand.h29
-rw-r--r--src/plugins/qmldesigner/designercore/instances/componentnodeinstance.cpp24
-rw-r--r--src/plugins/qmldesigner/designercore/instances/componentnodeinstance.h2
-rw-r--r--src/plugins/qmldesigner/designercore/instances/createinstancescommand.cpp35
-rw-r--r--src/plugins/qmldesigner/designercore/instances/createinstancescommand.h32
-rw-r--r--src/plugins/qmldesigner/designercore/instances/createscenecommand.cpp19
-rw-r--r--src/plugins/qmldesigner/designercore/instances/createscenecommand.h23
-rw-r--r--src/plugins/qmldesigner/designercore/instances/declarativedesignercommunicationinterface.cpp6
-rw-r--r--src/plugins/qmldesigner/designercore/instances/declarativedesignercommunicationinterface.h18
-rw-r--r--src/plugins/qmldesigner/designercore/instances/dummynodeinstance.cpp6
-rw-r--r--src/plugins/qmldesigner/designercore/instances/dummynodeinstance.h2
-rw-r--r--src/plugins/qmldesigner/designercore/instances/graphicsobjectnodeinstance.cpp102
-rw-r--r--src/plugins/qmldesigner/designercore/instances/graphicsobjectnodeinstance.h13
-rw-r--r--src/plugins/qmldesigner/designercore/instances/graphicsscenenodeinstance.cpp130
-rw-r--r--src/plugins/qmldesigner/designercore/instances/graphicsscenenodeinstance.h77
-rw-r--r--src/plugins/qmldesigner/designercore/instances/graphicsviewnodeinstance.cpp112
-rw-r--r--src/plugins/qmldesigner/designercore/instances/graphicsviewnodeinstance.h71
-rw-r--r--src/plugins/qmldesigner/designercore/instances/graphicswidgetnodeinstance.cpp187
-rw-r--r--src/plugins/qmldesigner/designercore/instances/graphicswidgetnodeinstance.h84
-rw-r--r--src/plugins/qmldesigner/designercore/instances/idcontainer.cpp41
-rw-r--r--src/plugins/qmldesigner/designercore/instances/idcontainer.h34
-rw-r--r--src/plugins/qmldesigner/designercore/instances/imagecontainer.cpp62
-rw-r--r--src/plugins/qmldesigner/designercore/instances/imagecontainer.h31
-rw-r--r--src/plugins/qmldesigner/designercore/instances/informationchangedcommand.cpp37
-rw-r--r--src/plugins/qmldesigner/designercore/instances/informationchangedcommand.h32
-rw-r--r--src/plugins/qmldesigner/designercore/instances/informationcontainer.cpp72
-rw-r--r--src/plugins/qmldesigner/designercore/instances/informationcontainer.h47
-rw-r--r--src/plugins/qmldesigner/designercore/instances/instancecontainer.cpp62
-rw-r--r--src/plugins/qmldesigner/designercore/instances/instancecontainer.h39
-rw-r--r--src/plugins/qmldesigner/designercore/instances/instances.pri93
-rw-r--r--src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp735
-rw-r--r--src/plugins/qmldesigner/designercore/instances/nodeinstanceclientproxy.cpp183
-rw-r--r--src/plugins/qmldesigner/designercore/instances/nodeinstanceclientproxy.h49
-rw-r--r--src/plugins/qmldesigner/designercore/instances/nodeinstancemetaobject.cpp48
-rw-r--r--src/plugins/qmldesigner/designercore/instances/nodeinstancemetaobject.h1
-rw-r--r--src/plugins/qmldesigner/designercore/instances/nodeinstanceserver.cpp827
-rw-r--r--src/plugins/qmldesigner/designercore/instances/nodeinstanceserver.h137
-rw-r--r--src/plugins/qmldesigner/designercore/instances/nodeinstanceserverinterface.cpp130
-rw-r--r--src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp226
-rw-r--r--src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.h66
-rw-r--r--src/plugins/qmldesigner/designercore/instances/nodeinstancesignalspy.cpp8
-rw-r--r--src/plugins/qmldesigner/designercore/instances/nodeinstancesignalspy.h3
-rw-r--r--src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp778
-rw-r--r--src/plugins/qmldesigner/designercore/instances/objectnodeinstance.cpp413
-rw-r--r--src/plugins/qmldesigner/designercore/instances/objectnodeinstance.h81
-rw-r--r--src/plugins/qmldesigner/designercore/instances/pixmapchangedcommand.cpp37
-rw-r--r--src/plugins/qmldesigner/designercore/instances/pixmapchangedcommand.h29
-rw-r--r--src/plugins/qmldesigner/designercore/instances/positionernodeinstance.cpp25
-rw-r--r--src/plugins/qmldesigner/designercore/instances/positionernodeinstance.h4
-rw-r--r--src/plugins/qmldesigner/designercore/instances/propertyabstractcontainer.cpp55
-rw-r--r--src/plugins/qmldesigner/designercore/instances/propertybindingcontainer.cpp64
-rw-r--r--src/plugins/qmldesigner/designercore/instances/propertyvaluecontainer.cpp63
-rw-r--r--src/plugins/qmldesigner/designercore/instances/proxywidgetnodeinstance.cpp85
-rw-r--r--src/plugins/qmldesigner/designercore/instances/proxywidgetnodeinstance.h63
-rw-r--r--src/plugins/qmldesigner/designercore/instances/qmlgraphicsitemnodeinstance.cpp271
-rw-r--r--src/plugins/qmldesigner/designercore/instances/qmlgraphicsitemnodeinstance.h13
-rw-r--r--src/plugins/qmldesigner/designercore/instances/qmlpropertychangesnodeinstance.cpp27
-rw-r--r--src/plugins/qmldesigner/designercore/instances/qmlpropertychangesnodeinstance.h4
-rw-r--r--src/plugins/qmldesigner/designercore/instances/qmlstatenodeinstance.cpp45
-rw-r--r--src/plugins/qmldesigner/designercore/instances/qmlstatenodeinstance.h8
-rw-r--r--src/plugins/qmldesigner/designercore/instances/qmltransitionnodeinstance.cpp11
-rw-r--r--src/plugins/qmldesigner/designercore/instances/qmltransitionnodeinstance.h2
-rw-r--r--src/plugins/qmldesigner/designercore/instances/qmlviewnodeinstance.cpp92
-rw-r--r--src/plugins/qmldesigner/designercore/instances/qmlviewnodeinstance.h66
-rw-r--r--src/plugins/qmldesigner/designercore/instances/removeinstancescommand.cpp33
-rw-r--r--src/plugins/qmldesigner/designercore/instances/removeinstancescommand.h32
-rw-r--r--src/plugins/qmldesigner/designercore/instances/removepropertiescommand.cpp33
-rw-r--r--src/plugins/qmldesigner/designercore/instances/removepropertiescommand.h31
-rw-r--r--src/plugins/qmldesigner/designercore/instances/reparentcontainer.cpp72
-rw-r--r--src/plugins/qmldesigner/designercore/instances/reparentcontainer.h38
-rw-r--r--src/plugins/qmldesigner/designercore/instances/reparentinstancescommand.cpp34
-rw-r--r--src/plugins/qmldesigner/designercore/instances/reparentinstancescommand.h32
-rw-r--r--src/plugins/qmldesigner/designercore/instances/servernodeinstance.cpp596
-rw-r--r--src/plugins/qmldesigner/designercore/instances/servernodeinstance.h193
-rw-r--r--src/plugins/qmldesigner/designercore/instances/statepreviewimagechangedcommand.cpp32
-rw-r--r--src/plugins/qmldesigner/designercore/instances/statepreviewimagechangedcommand.h30
-rw-r--r--src/plugins/qmldesigner/designercore/instances/valueschangedcommand.cpp33
-rw-r--r--src/plugins/qmldesigner/designercore/instances/valueschangedcommand.h33
-rw-r--r--src/plugins/qmldesigner/designercore/instances/widgetnodeinstance.cpp156
-rw-r--r--src/plugins/qmldesigner/designercore/instances/widgetnodeinstance.h79
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/enumeratormetainfo.cpp162
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/gui.metainfo229
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/itemlibraryinfo.cpp46
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/metainfo.cpp474
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/metainfoparser.cpp216
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp1154
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/propertymetainfo.cpp447
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp71
-rw-r--r--src/plugins/qmldesigner/designercore/model/abstractproperty.cpp11
-rw-r--r--src/plugins/qmldesigner/designercore/model/abstractview.cpp16
-rw-r--r--src/plugins/qmldesigner/designercore/model/basetexteditmodifier.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/model/bindingproperty.cpp1
-rw-r--r--src/plugins/qmldesigner/designercore/model/import.cpp15
-rw-r--r--src/plugins/qmldesigner/designercore/model/internalnode.cpp30
-rw-r--r--src/plugins/qmldesigner/designercore/model/internalnode_p.h8
-rw-r--r--src/plugins/qmldesigner/designercore/model/internalnodeabstractproperty.h2
-rw-r--r--src/plugins/qmldesigner/designercore/model/internalnodelistproperty.cpp19
-rw-r--r--src/plugins/qmldesigner/designercore/model/internalnodelistproperty.h3
-rw-r--r--src/plugins/qmldesigner/designercore/model/internalnodeproperty.cpp16
-rw-r--r--src/plugins/qmldesigner/designercore/model/internalnodeproperty.h2
-rw-r--r--src/plugins/qmldesigner/designercore/model/internalproperty.cpp1
-rw-r--r--src/plugins/qmldesigner/designercore/model/model.cpp179
-rw-r--r--src/plugins/qmldesigner/designercore/model/model_p.h16
-rw-r--r--src/plugins/qmldesigner/designercore/model/modelnode.cpp29
-rw-r--r--src/plugins/qmldesigner/designercore/model/modelutilities.cpp129
-rw-r--r--src/plugins/qmldesigner/designercore/model/nodeabstractproperty.cpp20
-rw-r--r--src/plugins/qmldesigner/designercore/model/nodelistproperty.cpp11
-rw-r--r--src/plugins/qmldesigner/designercore/model/propertyparser.cpp17
-rw-r--r--src/plugins/qmldesigner/designercore/model/qmlanchors.cpp8
-rw-r--r--src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp4
-rw-r--r--src/plugins/qmldesigner/designercore/model/qmlmodelview.cpp55
-rw-r--r--src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp9
-rw-r--r--src/plugins/qmldesigner/designercore/model/qmltextgenerator.cpp9
-rw-r--r--src/plugins/qmldesigner/designercore/model/rewriteaction.cpp3
-rw-r--r--src/plugins/qmldesigner/designercore/model/rewriterview.cpp33
-rw-r--r--src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp143
-rw-r--r--src/plugins/qmldesigner/designercore/model/texttomodelmerger.h29
-rw-r--r--src/plugins/qmldesigner/designercore/model/viewlogger.cpp14
-rw-r--r--src/plugins/qmldesigner/designercore/model/viewlogger.h3
-rw-r--r--src/plugins/qmldesigner/designmodewidget.cpp64
-rw-r--r--src/plugins/qmldesigner/designmodewidget.h16
-rw-r--r--src/plugins/qmldesigner/meegoplugin/images/button.pngbin0 -> 452 bytes
-rw-r--r--src/plugins/qmldesigner/meegoplugin/images/button16.pngbin0 -> 392 bytes
-rw-r--r--src/plugins/qmldesigner/meegoplugin/images/checkbox.pngbin0 -> 850 bytes
-rw-r--r--src/plugins/qmldesigner/meegoplugin/images/checkbox16.pngbin0 -> 709 bytes
-rw-r--r--src/plugins/qmldesigner/meegoplugin/images/item-icon.pngbin0 -> 396 bytes
-rw-r--r--src/plugins/qmldesigner/meegoplugin/images/item-icon16.pngbin0 -> 312 bytes
-rw-r--r--src/plugins/qmldesigner/meegoplugin/images/label.pngbin0 -> 1134 bytes
-rw-r--r--src/plugins/qmldesigner/meegoplugin/images/label16.pngbin0 -> 750 bytes
-rw-r--r--src/plugins/qmldesigner/meegoplugin/images/lineedit.pngbin0 -> 430 bytes
-rw-r--r--src/plugins/qmldesigner/meegoplugin/images/lineedit16.pngbin0 -> 358 bytes
-rw-r--r--src/plugins/qmldesigner/meegoplugin/images/progressbar.pngbin0 -> 590 bytes
-rw-r--r--src/plugins/qmldesigner/meegoplugin/images/progressbar16.pngbin0 -> 448 bytes
-rw-r--r--src/plugins/qmldesigner/meegoplugin/images/radiobutton.pngbin0 -> 600 bytes
-rw-r--r--src/plugins/qmldesigner/meegoplugin/images/radiobutton16.pngbin0 -> 501 bytes
-rw-r--r--src/plugins/qmldesigner/meegoplugin/images/slider.pngbin0 -> 753 bytes
-rw-r--r--src/plugins/qmldesigner/meegoplugin/images/slider16.pngbin0 -> 644 bytes
-rw-r--r--src/plugins/qmldesigner/meegoplugin/meego.metainfo27
-rw-r--r--src/plugins/qmldesigner/meegoplugin/meegoplugin.cpp54
-rw-r--r--src/plugins/qmldesigner/meegoplugin/meegoplugin.h58
-rw-r--r--src/plugins/qmldesigner/meegoplugin/meegoplugin.pri17
-rw-r--r--src/plugins/qmldesigner/meegoplugin/meegoplugin.pro4
-rw-r--r--src/plugins/qmldesigner/meegoplugin/meegoplugin.qrc21
-rw-r--r--src/plugins/qmldesigner/meegoplugin/plugindestdir.pri5
-rw-r--r--src/plugins/qmldesigner/qmldesigner.pro2
-rw-r--r--src/plugins/qmldesigner/qmldesignerplugin.cpp1
-rw-r--r--src/plugins/qmldesigner/qmldesignerplugin.pro2
-rw-r--r--src/plugins/qmldesigner/qtquickplugin/qtquickplugin.cpp1
-rw-r--r--src/plugins/qmldesigner/qtquickplugin/quick.metainfo91
-rw-r--r--src/plugins/qmldesigner/settingspage.cpp6
-rw-r--r--src/plugins/qmldesigner/symbianplugin/images/button.pngbin0 -> 452 bytes
-rw-r--r--src/plugins/qmldesigner/symbianplugin/images/button16.pngbin0 -> 392 bytes
-rw-r--r--src/plugins/qmldesigner/symbianplugin/images/checkbox.pngbin0 -> 850 bytes
-rw-r--r--src/plugins/qmldesigner/symbianplugin/images/checkbox16.pngbin0 -> 709 bytes
-rw-r--r--src/plugins/qmldesigner/symbianplugin/images/item-icon.pngbin0 -> 396 bytes
-rw-r--r--src/plugins/qmldesigner/symbianplugin/images/item-icon16.pngbin0 -> 312 bytes
-rw-r--r--src/plugins/qmldesigner/symbianplugin/images/label.pngbin0 -> 1134 bytes
-rw-r--r--src/plugins/qmldesigner/symbianplugin/images/label16.pngbin0 -> 750 bytes
-rw-r--r--src/plugins/qmldesigner/symbianplugin/images/lineedit.pngbin0 -> 430 bytes
-rw-r--r--src/plugins/qmldesigner/symbianplugin/images/lineedit16.pngbin0 -> 358 bytes
-rw-r--r--src/plugins/qmldesigner/symbianplugin/images/progressbar.pngbin0 -> 590 bytes
-rw-r--r--src/plugins/qmldesigner/symbianplugin/images/progressbar16.pngbin0 -> 448 bytes
-rw-r--r--src/plugins/qmldesigner/symbianplugin/images/radiobutton.pngbin0 -> 600 bytes
-rw-r--r--src/plugins/qmldesigner/symbianplugin/images/radiobutton16.pngbin0 -> 501 bytes
-rw-r--r--src/plugins/qmldesigner/symbianplugin/images/slider.pngbin0 -> 753 bytes
-rw-r--r--src/plugins/qmldesigner/symbianplugin/images/slider16.pngbin0 -> 644 bytes
-rw-r--r--src/plugins/qmldesigner/symbianplugin/plugindestdir.pri5
-rw-r--r--src/plugins/qmldesigner/symbianplugin/symbian.metainfo49
-rw-r--r--src/plugins/qmldesigner/symbianplugin/symbianplugin.cpp54
-rw-r--r--src/plugins/qmldesigner/symbianplugin/symbianplugin.h62
-rw-r--r--src/plugins/qmldesigner/symbianplugin/symbianplugin.pri17
-rw-r--r--src/plugins/qmldesigner/symbianplugin/symbianplugin.pro4
-rw-r--r--src/plugins/qmldesigner/symbianplugin/symbianplugin.qrc21
-rw-r--r--src/plugins/qmljseditor/QmlJSEditor.pluginspec21
-rw-r--r--src/plugins/qmljseditor/QmlJSEditor.pluginspec.in22
-rw-r--r--src/plugins/qmljseditor/jsfilewizard.cpp140
-rw-r--r--src/plugins/qmljseditor/jsfilewizard.h60
-rw-r--r--src/plugins/qmljseditor/qmljsautocompleter.cpp291
-rw-r--r--src/plugins/qmljseditor/qmljsautocompleter.h62
-rw-r--r--src/plugins/qmljseditor/qmljscodecompletion.cpp161
-rw-r--r--src/plugins/qmljseditor/qmljscodecompletion.h10
-rw-r--r--src/plugins/qmljseditor/qmljscomponentfromobjectdef.cpp17
-rw-r--r--src/plugins/qmljseditor/qmljseditor.cpp518
-rw-r--r--src/plugins/qmljseditor/qmljseditor.h132
-rw-r--r--src/plugins/qmljseditor/qmljseditor.pri2
-rw-r--r--src/plugins/qmljseditor/qmljseditor.pro24
-rw-r--r--src/plugins/qmljseditor/qmljseditor_dependencies.pri2
-rw-r--r--src/plugins/qmljseditor/qmljseditorcodeformatter.cpp363
-rw-r--r--src/plugins/qmljseditor/qmljseditorcodeformatter.h78
-rw-r--r--src/plugins/qmljseditor/qmljseditorconstants.h2
-rw-r--r--src/plugins/qmljseditor/qmljseditoreditable.cpp92
-rw-r--r--src/plugins/qmljseditor/qmljseditoreditable.h60
-rw-r--r--src/plugins/qmljseditor/qmljseditorfactory.cpp4
-rw-r--r--src/plugins/qmljseditor/qmljseditorplugin.cpp53
-rw-r--r--src/plugins/qmljseditor/qmljseditorplugin.h6
-rw-r--r--src/plugins/qmljseditor/qmljsfindreferences.cpp38
-rw-r--r--src/plugins/qmljseditor/qmljshighlighter.cpp27
-rw-r--r--src/plugins/qmljseditor/qmljshoverhandler.cpp132
-rw-r--r--src/plugins/qmljseditor/qmljshoverhandler.h8
-rw-r--r--src/plugins/qmljseditor/qmljsindenter.cpp74
-rw-r--r--src/plugins/qmljseditor/qmljsindenter.h54
-rw-r--r--src/plugins/qmljseditor/qmljsmodelmanager.cpp575
-rw-r--r--src/plugins/qmljseditor/qmljsmodelmanager.h122
-rw-r--r--src/plugins/qmljseditor/qmljsoutline.cpp1
-rw-r--r--src/plugins/qmljseditor/qmljsoutline.h2
-rw-r--r--src/plugins/qmljseditor/qmljsoutlinetreeview.cpp74
-rw-r--r--src/plugins/qmljseditor/qmljsoutlinetreeview.h11
-rw-r--r--src/plugins/qmljseditor/qmljspreviewrunner.cpp5
-rw-r--r--src/plugins/qmljseditor/qmljsquickfix.cpp2
-rw-r--r--src/plugins/qmljseditor/qmljsquickfix.h11
-rw-r--r--src/plugins/qmljseditor/qmljsquickfixes.cpp3
-rw-r--r--src/plugins/qmljseditor/qmljsrefactoringchanges.cpp147
-rw-r--r--src/plugins/qmljseditor/qmljsrefactoringchanges.h95
-rw-r--r--src/plugins/qmljseditor/qmljssemantichighlighter.cpp152
-rw-r--r--src/plugins/qmljseditor/qmljssemantichighlighter.h113
-rw-r--r--src/plugins/qmljseditor/qmljssnippetprovider.cpp72
-rw-r--r--src/plugins/qmljseditor/qmljssnippetprovider.h53
-rw-r--r--src/plugins/qmljseditor/qmloutlinemodel.cpp10
-rw-r--r--src/plugins/qmljseditor/qmloutlinemodel.h2
-rw-r--r--src/plugins/qmljseditor/quicktoolbar.cpp34
-rw-r--r--src/plugins/qmljseditor/quicktoolbarsettingspage.cpp6
-rw-r--r--src/plugins/qmljsinspector/QmlJSInspector.pluginspec30
-rw-r--r--src/plugins/qmljsinspector/QmlJSInspector.pluginspec.in30
-rw-r--r--src/plugins/qmljsinspector/images/app-on-top.pngbin0 -> 2902 bytes
-rw-r--r--src/plugins/qmljsinspector/qmlinspectortoolbar.cpp153
-rw-r--r--src/plugins/qmljsinspector/qmlinspectortoolbar.h21
-rw-r--r--src/plugins/qmljsinspector/qmljsclientproxy.cpp140
-rw-r--r--src/plugins/qmljsinspector/qmljsclientproxy.h10
-rw-r--r--src/plugins/qmljsinspector/qmljsinspector.cpp311
-rw-r--r--src/plugins/qmljsinspector/qmljsinspector.h23
-rw-r--r--src/plugins/qmljsinspector/qmljsinspector.pro1
-rw-r--r--src/plugins/qmljsinspector/qmljsinspector.qrc1
-rw-r--r--src/plugins/qmljsinspector/qmljsinspectorconstants.h2
-rw-r--r--src/plugins/qmljsinspector/qmljsinspectorplugin.cpp44
-rw-r--r--src/plugins/qmljsinspector/qmljsinspectorplugin.h18
-rw-r--r--src/plugins/qmljsinspector/qmljsinspectorsettings.h2
-rw-r--r--src/plugins/qmljsinspector/qmljslivetextpreview.cpp16
-rw-r--r--src/plugins/qmljsinspector/qmljslivetextpreview.h4
-rw-r--r--src/plugins/qmljsinspector/qmljsobserverclient.cpp174
-rw-r--r--src/plugins/qmljsinspector/qmljsobserverclient.h19
-rw-r--r--src/plugins/qmljsinspector/qmljstoolbarcolorbox.h4
-rw-r--r--src/plugins/qmljstools/QmlJSTools.pluginspec.in21
-rw-r--r--src/plugins/qmljstools/qmljsfunctionfilter.cpp115
-rw-r--r--src/plugins/qmljstools/qmljsfunctionfilter.h61
-rw-r--r--src/plugins/qmljstools/qmljslocatordata.cpp218
-rw-r--r--src/plugins/qmljstools/qmljslocatordata.h78
-rw-r--r--src/plugins/qmljstools/qmljsmodelmanager.cpp539
-rw-r--r--src/plugins/qmljstools/qmljsmodelmanager.h122
-rw-r--r--src/plugins/qmljstools/qmljsplugindumper.cpp386
-rw-r--r--src/plugins/qmljstools/qmljsplugindumper.h98
-rw-r--r--src/plugins/qmljstools/qmljsqtstylecodeformatter.cpp363
-rw-r--r--src/plugins/qmljstools/qmljsqtstylecodeformatter.h78
-rw-r--r--src/plugins/qmljstools/qmljsrefactoringchanges.cpp147
-rw-r--r--src/plugins/qmljstools/qmljsrefactoringchanges.h97
-rw-r--r--src/plugins/qmljstools/qmljstools-lib.pri26
-rw-r--r--src/plugins/qmljstools/qmljstools.pri6
-rw-r--r--src/plugins/qmljstools/qmljstools.pro10
-rw-r--r--src/plugins/qmljstools/qmljstools_dependencies.pri3
-rw-r--r--src/plugins/qmljstools/qmljstools_global.h43
-rw-r--r--src/plugins/qmljstools/qmljstoolsconstants.h46
-rw-r--r--src/plugins/qmljstools/qmljstoolsplugin.cpp95
-rw-r--r--src/plugins/qmljstools/qmljstoolsplugin.h73
-rw-r--r--src/plugins/qmlprojectmanager/QmlProjectManager.pluginspec23
-rw-r--r--src/plugins/qmlprojectmanager/QmlProjectManager.pluginspec.in23
-rw-r--r--src/plugins/qmlprojectmanager/fileformat/filefilteritems.cpp62
-rw-r--r--src/plugins/qmlprojectmanager/fileformat/filefilteritems.h17
-rw-r--r--src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp6
-rw-r--r--src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.cpp16
-rw-r--r--src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.h14
-rw-r--r--src/plugins/qmlprojectmanager/qmlproject.cpp25
-rw-r--r--src/plugins/qmlprojectmanager/qmlproject.h5
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectapplicationwizard.cpp10
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectmanager.h1
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectmanager.pri2
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectmanager.pro9
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectmanagerconstants.h2
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectplugin.cpp1
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp330
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h65
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectrunconfigurationwidget.cpp317
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectrunconfigurationwidget.h93
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp50
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectruncontrol.h2
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojecttarget.cpp18
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojecttarget.h3
-rw-r--r--src/plugins/qt4projectmanager/Qt4ProjectManager.pluginspec24
-rw-r--r--src/plugins/qt4projectmanager/Qt4ProjectManager.pluginspec.in23
-rw-r--r--src/plugins/qt4projectmanager/addlibrarywizard.cpp114
-rw-r--r--src/plugins/qt4projectmanager/addlibrarywizard.h18
-rw-r--r--src/plugins/qt4projectmanager/externaleditors.cpp6
-rw-r--r--src/plugins/qt4projectmanager/gettingstartedwelcomepagewidget.cpp17
-rw-r--r--src/plugins/qt4projectmanager/gettingstartedwelcomepagewidget.h14
-rw-r--r--src/plugins/qt4projectmanager/librarydetailscontroller.cpp89
-rw-r--r--src/plugins/qt4projectmanager/librarydetailscontroller.h17
-rw-r--r--src/plugins/qt4projectmanager/librarydetailswidget.ui18
-rw-r--r--src/plugins/qt4projectmanager/makestep.cpp128
-rw-r--r--src/plugins/qt4projectmanager/makestep.h12
-rw-r--r--src/plugins/qt4projectmanager/profilecompletion.cpp189
-rw-r--r--src/plugins/qt4projectmanager/profilecompletion.h45
-rw-r--r--src/plugins/qt4projectmanager/profileeditor.cpp96
-rw-r--r--src/plugins/qt4projectmanager/profileeditor.h4
-rw-r--r--src/plugins/qt4projectmanager/profileeditorfactory.cpp11
-rw-r--r--src/plugins/qt4projectmanager/profilehighlighter.cpp128
-rw-r--r--src/plugins/qt4projectmanager/profilekeywords.cpp167
-rw-r--r--src/plugins/qt4projectmanager/profilekeywords.h24
-rw-r--r--src/plugins/qt4projectmanager/qmakeparser.cpp126
-rw-r--r--src/plugins/qt4projectmanager/qmakeparser.h5
-rw-r--r--src/plugins/qt4projectmanager/qmakestep.cpp105
-rw-r--r--src/plugins/qt4projectmanager/qmakestep.h12
-rw-r--r--src/plugins/qt4projectmanager/qmldumptool.cpp2
-rw-r--r--src/plugins/qt4projectmanager/qmlobservertool.cpp93
-rw-r--r--src/plugins/qt4projectmanager/qmlobservertool.h3
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoconfigtestdialog.cpp124
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoconfigtestdialog.h21
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoconfigtestdialog.ui4
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoconstants.h15
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodebugsupport.cpp204
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodebugsupport.h30
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeployablelistmodel.cpp288
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeployablelistmodel.h27
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeployables.cpp22
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeployables.h9
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeploystep.cpp585
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeploystep.h36
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeploystepwidget.cpp83
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeploystepwidget.h2
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeploystepwidget.ui107
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurations.cpp11
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurations.h19
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurationssettingswidget.cpp507
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurationssettingswidget.h121
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurationssettingswidget.ui816
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeviceenvreader.cpp82
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeviceenvreader.h7
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoglobal.cpp93
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoglobal.h32
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemomanager.cpp36
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemomanager.h11
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationstep.cpp216
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationstep.h23
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.cpp90
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.h14
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.ui135
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoprofilesupdatedialog.ui4
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoprofilewrapper.cpp302
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoprofilewrapper.h81
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopublishedprojectmodel.cpp144
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopublishedprojectmodel.h77
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopublisherfremantlefree.cpp634
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopublisherfremantlefree.h122
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopublishingbuildsettingspagefremantlefree.cpp108
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopublishingbuildsettingspagefremantlefree.h72
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopublishingbuildsettingspagefremantlefree.ui75
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopublishingfileselectiondialog.cpp74
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopublishingfileselectiondialog.h74
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopublishingfileselectiondialog.ui78
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopublishingresultpagefremantlefree.cpp105
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopublishingresultpagefremantlefree.h78
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopublishingresultpagefremantlefree.ui33
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopublishinguploadsettingspagefremantlefree.cpp71
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopublishinguploadsettingspagefremantlefree.h63
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopublishinguploadsettingspagefremantlefree.ui95
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopublishingwizardfactories.cpp95
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopublishingwizardfactories.h57
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopublishingwizardfremantlefree.cpp91
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopublishingwizardfremantlefree.h77
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoqemumanager.cpp233
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoqemumanager.h37
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoqemuruntime.h87
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoqemuruntimeparser.cpp432
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoqemuruntimeparser.h58
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoqemusettings.cpp73
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoqemusettings.h58
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoqemusettingswidget.cpp95
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoqemusettingswidget.h72
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoqemusettingswidget.ui64
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoremotemounter.cpp72
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoremotemounter.h35
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoremotemountsmodel.h3
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoremoteprocessesdialog.cpp134
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoremoteprocessesdialog.h84
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoremoteprocessesdialog.ui145
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoremoteprocesslist.cpp248
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoremoteprocesslist.h108
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.cpp61
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.h18
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemorunconfigurationwidget.cpp28
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemorunconfigurationwidget.h9
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoruncontrol.cpp59
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoruncontrol.h5
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemorunfactories.cpp7
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemosettingspage.cpp113
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemosettingspage.h77
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemosettingspages.cpp238
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemosettingspages.h102
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemosettingswidget.cpp491
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemosettingswidget.h123
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemosettingswidget.ui760
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemosshconfigdialog.ui17
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemosshrunner.cpp125
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemosshrunner.h26
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemotemplatesmanager.cpp164
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemotemplatesmanager.h18
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemotoolchain.cpp4
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemotoolchain.h7
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemousedportsgatherer.cpp170
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemousedportsgatherer.h87
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/qt-maemo.pri53
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/abldparser.cpp6
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/certificatepathchooser.cpp60
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/certificatepathchooser.h51
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/gccetoolchain.cpp20
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/gccetoolchain.h8
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/passphraseforkeydialog.cpp76
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/passphraseforkeydialog.h14
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/qt-s60.pri19
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/rvctparser.cpp5
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/rvcttoolchain.cpp247
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/rvcttoolchain.h74
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60certificatedetailsdialog.cpp58
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60certificatedetailsdialog.h57
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60certificatedetailsdialog.ui31
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60certificateinfo.cpp231
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60certificateinfo.h101
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60createpackageparser.cpp130
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60createpackageparser.h70
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.cpp554
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.h40
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.ui25
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60deployconfiguration.cpp40
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60deployconfiguration.h15
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60deployconfigurationwidget.cpp10
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60deployconfigurationwidget.h4
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60deploystep.cpp47
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60deploystep.h17
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp169
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h51
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp26
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.h4
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60devices.cpp9
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60devicespreferencepane.cpp4
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.cpp74
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.h13
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60manager.cpp39
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60manager.h11
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60projectchecker.cpp20
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60runconfigbluetoothstarter.cpp6
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60runconfigbluetoothstarter.h4
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60symbiancertificate.cpp848
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60symbiancertificate.h72
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/sbsv2parser.cpp7
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/signsisparser.cpp74
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/signsisparser.h27
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/winscwparser.cpp8
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/winscwtoolchain.cpp4
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/winscwtoolchain.h2
-rw-r--r--src/plugins/qt4projectmanager/qt4buildconfiguration.cpp141
-rw-r--r--src/plugins/qt4projectmanager/qt4buildconfiguration.h30
-rw-r--r--src/plugins/qt4projectmanager/qt4nodes.cpp199
-rw-r--r--src/plugins/qt4projectmanager/qt4nodes.h34
-rw-r--r--src/plugins/qt4projectmanager/qt4project.cpp54
-rw-r--r--src/plugins/qt4projectmanager/qt4project.h13
-rw-r--r--src/plugins/qt4projectmanager/qt4projectconfigwidget.cpp102
-rw-r--r--src/plugins/qt4projectmanager/qt4projectconfigwidget.h9
-rw-r--r--src/plugins/qt4projectmanager/qt4projectmanager.pri2
-rw-r--r--src/plugins/qt4projectmanager/qt4projectmanager.pro18
-rw-r--r--src/plugins/qt4projectmanager/qt4projectmanager_dependencies.pri1
-rw-r--r--src/plugins/qt4projectmanager/qt4projectmanagerconstants.h12
-rw-r--r--src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp58
-rw-r--r--src/plugins/qt4projectmanager/qt4projectmanagerplugin.h9
-rw-r--r--src/plugins/qt4projectmanager/qt4runconfiguration.cpp127
-rw-r--r--src/plugins/qt4projectmanager/qt4runconfiguration.h27
-rw-r--r--src/plugins/qt4projectmanager/qt4target.cpp63
-rw-r--r--src/plugins/qt4projectmanager/qt4target.h40
-rw-r--r--src/plugins/qt4projectmanager/qtmodulesinfo.cpp6
-rw-r--r--src/plugins/qt4projectmanager/qtoptionspage.cpp52
-rw-r--r--src/plugins/qt4projectmanager/qtoutputformatter.cpp75
-rw-r--r--src/plugins/qt4projectmanager/qtoutputformatter.h9
-rw-r--r--src/plugins/qt4projectmanager/qtuicodemodelsupport.cpp153
-rw-r--r--src/plugins/qt4projectmanager/qtuicodemodelsupport.h24
-rw-r--r--src/plugins/qt4projectmanager/qtversionmanager.cpp250
-rw-r--r--src/plugins/qt4projectmanager/qtversionmanager.h32
-rw-r--r--src/plugins/qt4projectmanager/wizards/abstractmobileapp.cpp10
-rw-r--r--src/plugins/qt4projectmanager/wizards/abstractmobileapp.h4
-rw-r--r--src/plugins/qt4projectmanager/wizards/abstractmobileappwizard.cpp127
-rw-r--r--src/plugins/qt4projectmanager/wizards/abstractmobileappwizard.h29
-rw-r--r--src/plugins/qt4projectmanager/wizards/emptyprojectwizard.cpp2
-rw-r--r--src/plugins/qt4projectmanager/wizards/librarywizarddialog.cpp14
-rw-r--r--src/plugins/qt4projectmanager/wizards/mobileapp.cpp2
-rw-r--r--src/plugins/qt4projectmanager/wizards/mobileapp.h4
-rw-r--r--src/plugins/qt4projectmanager/wizards/mobileappwizardgenericoptionspage.ui57
-rw-r--r--src/plugins/qt4projectmanager/wizards/mobileappwizardmaemooptionspage.ui53
-rw-r--r--src/plugins/qt4projectmanager/wizards/mobileappwizardoptionspage.ui233
-rw-r--r--src/plugins/qt4projectmanager/wizards/mobileappwizardpages.cpp172
-rw-r--r--src/plugins/qt4projectmanager/wizards/mobileappwizardpages.h52
-rw-r--r--src/plugins/qt4projectmanager/wizards/mobileappwizardsymbianoptionspage.ui126
-rw-r--r--src/plugins/qt4projectmanager/wizards/mobilelibraryparameters.cpp5
-rw-r--r--src/plugins/qt4projectmanager/wizards/qmlstandaloneapp.cpp3
-rw-r--r--src/plugins/qt4projectmanager/wizards/qmlstandaloneapp.h2
-rw-r--r--src/plugins/qt4projectmanager/wizards/qmlstandaloneappwizard.cpp4
-rw-r--r--src/plugins/qt4projectmanager/wizards/qtwizard.cpp2
-rw-r--r--src/plugins/qt4projectmanager/wizards/subdirsprojectwizard.cpp95
-rw-r--r--src/plugins/qt4projectmanager/wizards/subdirsprojectwizard.h62
-rw-r--r--src/plugins/qt4projectmanager/wizards/subdirsprojectwizarddialog.cpp68
-rw-r--r--src/plugins/qt4projectmanager/wizards/subdirsprojectwizarddialog.h55
-rw-r--r--src/plugins/qt4projectmanager/wizards/targetsetuppage.cpp36
-rw-r--r--src/plugins/qt4projectmanager/wizards/targetsetuppage.h4
-rw-r--r--src/plugins/regexp/RegExp.pluginspec18
-rw-r--r--src/plugins/regexp/RegExp.pluginspec.in18
-rw-r--r--src/plugins/resourceeditor/ResourceEditor.pluginspec19
-rw-r--r--src/plugins/resourceeditor/ResourceEditor.pluginspec.in19
-rw-r--r--src/plugins/resourceeditor/resourceeditor.pro2
-rw-r--r--src/plugins/resourceeditor/resourceeditorw.h2
-rw-r--r--src/plugins/snippets/QMLSNIPPETS.TXT96
-rw-r--r--src/plugins/snippets/README1
-rw-r--r--src/plugins/snippets/Snippets.pluginspec20
-rw-r--r--src/plugins/snippets/images/dir.pngbin862 -> 0 bytes
-rw-r--r--src/plugins/snippets/images/diropen.pngbin931 -> 0 bytes
-rw-r--r--src/plugins/snippets/images/file.pngbin452 -> 0 bytes
-rw-r--r--src/plugins/snippets/images/snippets.pngbin908 -> 0 bytes
-rw-r--r--src/plugins/snippets/inputwidget.cpp135
-rw-r--r--src/plugins/snippets/inputwidget.h71
-rw-r--r--src/plugins/snippets/snippets.pro24
-rw-r--r--src/plugins/snippets/snippets.qrc8
-rw-r--r--src/plugins/snippets/snippetscompletion.cpp168
-rw-r--r--src/plugins/snippets/snippetscompletion.h97
-rw-r--r--src/plugins/snippets/snippetspec.cpp101
-rw-r--r--src/plugins/snippets/snippetspec.h69
-rw-r--r--src/plugins/snippets/snippetsplugin.cpp126
-rw-r--r--src/plugins/snippets/snippetsplugin.h84
-rw-r--r--src/plugins/snippets/snippetswindow.cpp433
-rw-r--r--src/plugins/snippets/snippetswindow.h124
-rw-r--r--src/plugins/subversion/Subversion.pluginspec22
-rw-r--r--src/plugins/subversion/Subversion.pluginspec.in22
-rw-r--r--src/plugins/subversion/settingspage.cpp18
-rw-r--r--src/plugins/subversion/subversion.pro2
-rw-r--r--src/plugins/subversion/subversionplugin.cpp20
-rw-r--r--src/plugins/tasklist/TaskList.pluginspec19
-rw-r--r--src/plugins/tasklist/TaskList.pluginspec.in19
-rw-r--r--src/plugins/tasklist/tasklist.pro3
-rw-r--r--src/plugins/tasklist/tasklistplugin.cpp2
-rw-r--r--src/plugins/texteditor/TextEditor.pluginspec21
-rw-r--r--src/plugins/texteditor/TextEditor.pluginspec.in21
-rw-r--r--src/plugins/texteditor/autocompleter.cpp348
-rw-r--r--src/plugins/texteditor/autocompleter.h93
-rw-r--r--src/plugins/texteditor/basefilefind.cpp2
-rw-r--r--src/plugins/texteditor/basefilefind.h2
-rw-r--r--src/plugins/texteditor/basetextdocument.cpp325
-rw-r--r--src/plugins/texteditor/basetextdocument.h97
-rw-r--r--src/plugins/texteditor/basetextdocumentlayout.h9
-rw-r--r--src/plugins/texteditor/basetexteditor.cpp1060
-rw-r--r--src/plugins/texteditor/basetexteditor.h93
-rw-r--r--src/plugins/texteditor/basetexteditor_p.h29
-rw-r--r--src/plugins/texteditor/basetextmark.cpp51
-rw-r--r--src/plugins/texteditor/basetextmark.h60
-rw-r--r--src/plugins/texteditor/behaviorsettingspage.cpp157
-rw-r--r--src/plugins/texteditor/behaviorsettingspage.h4
-rw-r--r--src/plugins/texteditor/behaviorsettingspage.ui137
-rw-r--r--src/plugins/texteditor/completionsupport.cpp124
-rw-r--r--src/plugins/texteditor/completionsupport.h16
-rw-r--r--src/plugins/texteditor/completionwidget.h2
-rw-r--r--src/plugins/texteditor/displaysettingspage.cpp83
-rw-r--r--src/plugins/texteditor/displaysettingspage.h2
-rw-r--r--src/plugins/texteditor/findincurrentfile.cpp15
-rw-r--r--src/plugins/texteditor/findincurrentfile.h4
-rw-r--r--src/plugins/texteditor/findinfiles.cpp7
-rw-r--r--src/plugins/texteditor/findinfiles.h2
-rw-r--r--src/plugins/texteditor/fontsettingspage.cpp109
-rw-r--r--src/plugins/texteditor/fontsettingspage.ui4
-rw-r--r--src/plugins/texteditor/generichighlighter/highlightdefinition.cpp9
-rw-r--r--src/plugins/texteditor/generichighlighter/highlightdefinition.h5
-rw-r--r--src/plugins/texteditor/generichighlighter/highlightersettings.cpp2
-rw-r--r--src/plugins/texteditor/generichighlighter/highlightersettingspage.cpp102
-rw-r--r--src/plugins/texteditor/generichighlighter/highlightersettingspage.h2
-rw-r--r--src/plugins/texteditor/generichighlighter/managedefinitionsdialog.ui4
-rw-r--r--src/plugins/texteditor/generichighlighter/progressdata.cpp12
-rw-r--r--src/plugins/texteditor/generichighlighter/progressdata.h6
-rw-r--r--src/plugins/texteditor/generichighlighter/rule.cpp5
-rw-r--r--src/plugins/texteditor/generichighlighter/rule.h10
-rw-r--r--src/plugins/texteditor/generichighlighter/specificrules.cpp79
-rw-r--r--src/plugins/texteditor/generichighlighter/specificrules.h43
-rw-r--r--src/plugins/texteditor/helpitem.cpp7
-rw-r--r--src/plugins/texteditor/helpitem.h3
-rw-r--r--src/plugins/texteditor/indenter.cpp66
-rw-r--r--src/plugins/texteditor/indenter.h26
-rw-r--r--src/plugins/texteditor/itexteditor.cpp15
-rw-r--r--src/plugins/texteditor/itexteditor.h1
-rw-r--r--src/plugins/texteditor/linenumberfilter.cpp2
-rw-r--r--src/plugins/texteditor/normalindenter.cpp10
-rw-r--r--src/plugins/texteditor/normalindenter.h9
-rw-r--r--src/plugins/texteditor/plaintexteditor.cpp9
-rw-r--r--src/plugins/texteditor/plaintexteditor.h2
-rw-r--r--src/plugins/texteditor/refactoroverlay.cpp42
-rw-r--r--src/plugins/texteditor/refactoroverlay.h39
-rw-r--r--src/plugins/texteditor/snippets/isnippetprovider.cpp38
-rw-r--r--src/plugins/texteditor/snippets/isnippetprovider.h59
-rw-r--r--src/plugins/texteditor/snippets/plaintextsnippetprovider.cpp56
-rw-r--r--src/plugins/texteditor/snippets/plaintextsnippetprovider.h57
-rw-r--r--src/plugins/texteditor/snippets/reuse.h59
-rw-r--r--src/plugins/texteditor/snippets/snippet.cpp144
-rw-r--r--src/plugins/texteditor/snippets/snippet.h82
-rw-r--r--src/plugins/texteditor/snippets/snippetcollector.cpp76
-rw-r--r--src/plugins/texteditor/snippets/snippetcollector.h58
-rw-r--r--src/plugins/texteditor/snippets/snippeteditor.cpp79
-rw-r--r--src/plugins/texteditor/snippets/snippeteditor.h87
-rw-r--r--src/plugins/texteditor/snippets/snippetscollection.cpp433
-rw-r--r--src/plugins/texteditor/snippets/snippetscollection.h147
-rw-r--r--src/plugins/texteditor/snippets/snippetssettings.cpp81
-rw-r--r--src/plugins/texteditor/snippets/snippetssettings.h70
-rw-r--r--src/plugins/texteditor/snippets/snippetssettingspage.cpp574
-rw-r--r--src/plugins/texteditor/snippets/snippetssettingspage.h65
-rw-r--r--src/plugins/texteditor/snippets/snippetssettingspage.ui130
-rw-r--r--src/plugins/texteditor/snippetsparser.cpp148
-rw-r--r--src/plugins/texteditor/snippetsparser.h64
-rw-r--r--src/plugins/texteditor/texteditor.pri2
-rw-r--r--src/plugins/texteditor/texteditor.pro32
-rw-r--r--src/plugins/texteditor/texteditoractionhandler.cpp17
-rw-r--r--src/plugins/texteditor/texteditoractionhandler.h4
-rw-r--r--src/plugins/texteditor/texteditorconstants.h8
-rw-r--r--src/plugins/texteditor/texteditoroverlay.cpp109
-rw-r--r--src/plugins/texteditor/texteditoroverlay.h54
-rw-r--r--src/plugins/texteditor/texteditorplugin.cpp4
-rw-r--r--src/plugins/texteditor/texteditorsettings.cpp7
-rw-r--r--src/plugins/texteditor/texteditorsettings.h4
-rw-r--r--src/plugins/vcsbase/VCSBase.pluginspec21
-rw-r--r--src/plugins/vcsbase/VCSBase.pluginspec.in21
-rw-r--r--src/plugins/vcsbase/basecheckoutwizard.cpp1
-rw-r--r--src/plugins/vcsbase/basecheckoutwizardpage.cpp4
-rw-r--r--src/plugins/vcsbase/basecheckoutwizardpage.ui7
-rw-r--r--src/plugins/vcsbase/commonsettingspage.cpp11
-rw-r--r--src/plugins/vcsbase/diffhighlighter.cpp92
-rw-r--r--src/plugins/vcsbase/diffhighlighter.h6
-rw-r--r--src/plugins/vcsbase/vcsbase.pri2
-rw-r--r--src/plugins/vcsbase/vcsbase.pro2
-rw-r--r--src/plugins/vcsbase/vcsbaseeditor.cpp34
-rw-r--r--src/plugins/vcsbase/vcsbaseeditor.h4
-rw-r--r--src/plugins/vcsbase/vcsbaseplugin.cpp149
-rw-r--r--src/plugins/vcsbase/vcsbaseplugin.h4
-rw-r--r--src/plugins/vcsbase/vcsbasesubmiteditor.cpp36
-rw-r--r--src/plugins/vcsbase/vcsbasesubmiteditor.h3
-rw-r--r--src/plugins/welcome/Welcome.pluginspec19
-rw-r--r--src/plugins/welcome/Welcome.pluginspec.in19
-rw-r--r--src/plugins/welcome/communitywelcomepagewidget.cpp4
-rw-r--r--src/plugins/welcome/communitywelcomepagewidget.h6
-rw-r--r--src/plugins/welcome/welcome.pro1
-rw-r--r--src/qtcreatorlibrary.pri2
-rw-r--r--src/qtcreatorplugin.pri29
-rw-r--r--src/rpath.pri7
-rw-r--r--src/shared/cplusplus/AST.cpp4
-rw-r--r--src/shared/cplusplus/AST.h2
-rw-r--r--src/shared/cplusplus/ASTClone.cpp1
-rw-r--r--src/shared/cplusplus/ASTMatcher.cpp2
-rw-r--r--src/shared/cplusplus/Bind.cpp16
-rw-r--r--src/shared/cplusplus/Control.cpp25
-rw-r--r--src/shared/cplusplus/Control.h5
-rw-r--r--src/shared/cplusplus/Parser.cpp3
-rw-r--r--src/shared/cplusplus/Symbols.cpp26
-rw-r--r--src/shared/cplusplus/Symbols.h2
-rw-r--r--src/shared/help/bookmarkmanager.cpp2
-rw-r--r--src/shared/help/contentwindow.cpp2
-rw-r--r--src/shared/help/indexwindow.cpp2
-rw-r--r--src/shared/proparser/ioutils.cpp127
-rw-r--r--src/shared/proparser/profileevaluator.cpp39
-rw-r--r--src/shared/proparser/profileevaluator.h8
-rw-r--r--src/shared/symbianutils/json.cpp27
-rw-r--r--src/shared/symbianutils/json.h2
-rw-r--r--src/shared/symbianutils/launcher.cpp15
-rw-r--r--src/shared/symbianutils/launcher.h4
-rw-r--r--src/shared/symbianutils/tcftrkdevice.cpp364
-rw-r--r--src/shared/symbianutils/tcftrkdevice.h93
-rw-r--r--src/shared/symbianutils/tcftrkmessage.cpp15
-rw-r--r--src/shared/symbianutils/tcftrkmessage.h5
-rw-r--r--src/shared/symbianutils/trkdevice.cpp4
-rw-r--r--src/shared/symbianutils/trkutils.h4
-rw-r--r--src/tools/qml/qmldom/main.cpp177
-rw-r--r--src/tools/qml/qmldom/qmldom.pro21
-rw-r--r--src/tools/qml/qmlmetatype/main.cpp82
-rw-r--r--src/tools/qml/qmlmetatype/qmlmetatype.pro17
-rw-r--r--src/tools/qmlpuppet/main.cpp51
-rw-r--r--src/tools/qmlpuppet/qmlpuppet.pro19
-rw-r--r--src/tools/qtpromaker/main.cpp396
-rw-r--r--src/tools/qtpromaker/qtpromaker.pro15
-rw-r--r--src/tools/tools.pro10
-rw-r--r--tests/auto/aggregation/aggregation.pro6
-rw-r--r--tests/auto/auto.pro15
-rw-r--r--tests/auto/changeset/changeset.pro4
-rw-r--r--tests/auto/cplusplus/ast/ast.pro5
-rw-r--r--tests/auto/cplusplus/codeformatter/codeformatter.pro16
-rw-r--r--tests/auto/cplusplus/codeformatter/tst_codeformatter.cpp113
-rw-r--r--tests/auto/cplusplus/codegen/codegen.pro8
-rw-r--r--tests/auto/cplusplus/codegen/tst_codegen.cpp49
-rw-r--r--tests/auto/cplusplus/cplusplus.pro4
-rw-r--r--tests/auto/cplusplus/findusages/findusages.pro5
-rw-r--r--tests/auto/cplusplus/lookup/lookup.pro5
-rw-r--r--tests/auto/cplusplus/preprocessor/preprocessor.pro4
-rw-r--r--tests/auto/cplusplus/semantic/semantic.pro6
-rw-r--r--tests/auto/cplusplus/shared/shared.pri7
-rw-r--r--tests/auto/cplusplus/simplifytypes/simplifytypes.pro3
-rw-r--r--tests/auto/cplusplus/simplifytypes/tst_simplifytypestest.cpp139
-rw-r--r--tests/auto/cplusplus/typeprettyprinter/typeprettyprinter.pro5
-rw-r--r--tests/auto/debugger/dumpers.pro8
-rw-r--r--tests/auto/debugger/gdb.pro7
-rw-r--r--tests/auto/debugger/plugin.pro5
-rw-r--r--tests/auto/debugger/tst_gdb.cpp10
-rw-r--r--tests/auto/debugger/version.pro5
-rw-r--r--tests/auto/environment/environment.pro17
-rw-r--r--tests/auto/environment/tst_environment.cpp107
-rw-r--r--tests/auto/extensionsystem/copy.pri12
-rw-r--r--tests/auto/extensionsystem/extensionsystem.pro4
-rw-r--r--tests/auto/extensionsystem/pluginmanager/circularplugins/circularplugins.pro (renamed from src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/circularplugins.pro)0
-rw-r--r--tests/auto/extensionsystem/pluginmanager/circularplugins/plugin1/plugin.xml (renamed from src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin1/plugin.xml)0
-rw-r--r--tests/auto/extensionsystem/pluginmanager/circularplugins/plugin1/plugin1.cpp57
-rw-r--r--tests/auto/extensionsystem/pluginmanager/circularplugins/plugin1/plugin1.h (renamed from src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin1/plugin1.h)0
-rw-r--r--tests/auto/extensionsystem/pluginmanager/circularplugins/plugin1/plugin1.pro19
-rw-r--r--tests/auto/extensionsystem/pluginmanager/circularplugins/plugin2/plugin.xml (renamed from src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin2/plugin.xml)0
-rw-r--r--tests/auto/extensionsystem/pluginmanager/circularplugins/plugin2/plugin2.cpp (renamed from src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin2/plugin2.cpp)0
-rw-r--r--tests/auto/extensionsystem/pluginmanager/circularplugins/plugin2/plugin2.h (renamed from src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin2/plugin2.h)0
-rw-r--r--tests/auto/extensionsystem/pluginmanager/circularplugins/plugin2/plugin2.pro19
-rw-r--r--tests/auto/extensionsystem/pluginmanager/circularplugins/plugin3/plugin.xml (renamed from src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin3/plugin.xml)0
-rw-r--r--tests/auto/extensionsystem/pluginmanager/circularplugins/plugin3/plugin3.cpp (renamed from src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin3/plugin3.cpp)0
-rw-r--r--tests/auto/extensionsystem/pluginmanager/circularplugins/plugin3/plugin3.h (renamed from src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin3/plugin3.h)0
-rw-r--r--tests/auto/extensionsystem/pluginmanager/circularplugins/plugin3/plugin3.pro19
-rw-r--r--tests/auto/extensionsystem/pluginmanager/correctplugins1/correctplugins1.pro (renamed from src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/correctplugins1.pro)0
-rw-r--r--tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin1/plugin.spec (renamed from src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin1/plugin.spec)0
-rw-r--r--tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin1/plugin1.cpp (renamed from src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin1/plugin1.cpp)0
-rw-r--r--tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin1/plugin1.h (renamed from src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin1/plugin1.h)0
-rw-r--r--tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin1/plugin1.pro26
-rw-r--r--tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin2/plugin.spec (renamed from src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin2/plugin.spec)0
-rw-r--r--tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin2/plugin2.cpp (renamed from src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin2/plugin2.cpp)0
-rw-r--r--tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin2/plugin2.h (renamed from src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin2/plugin2.h)0
-rw-r--r--tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin2/plugin2.pro24
-rw-r--r--tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin3/plugin.spec (renamed from src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin3/plugin.spec)0
-rw-r--r--tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin3/plugin3.cpp (renamed from src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin3/plugin3.cpp)0
-rw-r--r--tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin3/plugin3.h (renamed from src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin3/plugin3.h)0
-rw-r--r--tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin3/plugin3.pro26
-rw-r--r--tests/auto/extensionsystem/pluginmanager/pluginmanager.pro (renamed from src/libs/extensionsystem/test/auto/pluginmanager/pluginmanager.pro)0
-rw-r--r--tests/auto/extensionsystem/pluginmanager/plugins/myplug/myplug.xml (renamed from src/libs/extensionsystem/test/auto/pluginmanager/plugins/myplug/myplug.xml)0
-rw-r--r--tests/auto/extensionsystem/pluginmanager/plugins/otherplugin.xml (renamed from src/libs/extensionsystem/test/auto/pluginmanager/plugins/otherplugin.xml)0
-rw-r--r--tests/auto/extensionsystem/pluginmanager/plugins/plugin1.xml (renamed from src/libs/extensionsystem/test/auto/pluginmanager/plugins/plugin1.xml)0
-rw-r--r--tests/auto/extensionsystem/pluginmanager/test.pro20
-rw-r--r--tests/auto/extensionsystem/pluginmanager/tst_pluginmanager.cpp249
-rw-r--r--tests/auto/extensionsystem/pluginspec/pluginspec.pro (renamed from src/libs/extensionsystem/test/auto/pluginspec/pluginspec.pro)0
-rw-r--r--tests/auto/extensionsystem/pluginspec/test.pro28
-rw-r--r--tests/auto/extensionsystem/pluginspec/testdependencies/spec1.xml (renamed from src/libs/extensionsystem/test/auto/pluginspec/testdependencies/spec1.xml)0
-rw-r--r--tests/auto/extensionsystem/pluginspec/testdependencies/spec2.xml (renamed from src/libs/extensionsystem/test/auto/pluginspec/testdependencies/spec2.xml)0
-rw-r--r--tests/auto/extensionsystem/pluginspec/testdependencies/spec3.xml (renamed from src/libs/extensionsystem/test/auto/pluginspec/testdependencies/spec3.xml)0
-rw-r--r--tests/auto/extensionsystem/pluginspec/testdependencies/spec4.xml (renamed from src/libs/extensionsystem/test/auto/pluginspec/testdependencies/spec4.xml)0
-rw-r--r--tests/auto/extensionsystem/pluginspec/testdependencies/spec5.xml (renamed from src/libs/extensionsystem/test/auto/pluginspec/testdependencies/spec5.xml)0
-rw-r--r--tests/auto/extensionsystem/pluginspec/testdir/spec.xml (renamed from src/libs/extensionsystem/test/auto/pluginspec/testdir/spec.xml)0
-rw-r--r--tests/auto/extensionsystem/pluginspec/testplugin/testplugin.cpp (renamed from src/libs/extensionsystem/test/auto/pluginspec/testplugin/testplugin.cpp)0
-rw-r--r--tests/auto/extensionsystem/pluginspec/testplugin/testplugin.h65
-rw-r--r--tests/auto/extensionsystem/pluginspec/testplugin/testplugin.pro16
-rw-r--r--tests/auto/extensionsystem/pluginspec/testplugin/testplugin.xml (renamed from src/libs/extensionsystem/test/auto/pluginspec/testplugin/testplugin.xml)0
-rw-r--r--tests/auto/extensionsystem/pluginspec/testplugin/testplugin_global.h (renamed from src/libs/extensionsystem/test/auto/pluginspec/testplugin/testplugin_global.h)0
-rw-r--r--tests/auto/extensionsystem/pluginspec/testspecs/simplespec.xml (renamed from src/libs/extensionsystem/test/auto/pluginspec/testspecs/simplespec.xml)0
-rw-r--r--tests/auto/extensionsystem/pluginspec/testspecs/simplespec_experimental.xml (renamed from src/libs/extensionsystem/test/auto/pluginspec/testspecs/simplespec_experimental.xml)0
-rw-r--r--tests/auto/extensionsystem/pluginspec/testspecs/spec1.xml (renamed from src/libs/extensionsystem/test/auto/pluginspec/testspecs/spec1.xml)0
-rw-r--r--tests/auto/extensionsystem/pluginspec/testspecs/spec2.xml (renamed from src/libs/extensionsystem/test/auto/pluginspec/testspecs/spec2.xml)0
-rw-r--r--tests/auto/extensionsystem/pluginspec/testspecs/spec_wrong1.xml (renamed from src/libs/extensionsystem/test/auto/pluginspec/testspecs/spec_wrong1.xml)0
-rw-r--r--tests/auto/extensionsystem/pluginspec/testspecs/spec_wrong2.xml (renamed from src/libs/extensionsystem/test/auto/pluginspec/testspecs/spec_wrong2.xml)0
-rw-r--r--tests/auto/extensionsystem/pluginspec/testspecs/spec_wrong3.xml (renamed from src/libs/extensionsystem/test/auto/pluginspec/testspecs/spec_wrong3.xml)0
-rw-r--r--tests/auto/extensionsystem/pluginspec/testspecs/spec_wrong4.xml (renamed from src/libs/extensionsystem/test/auto/pluginspec/testspecs/spec_wrong4.xml)0
-rw-r--r--tests/auto/extensionsystem/pluginspec/testspecs/spec_wrong5.xml (renamed from src/libs/extensionsystem/test/auto/pluginspec/testspecs/spec_wrong5.xml)0
-rw-r--r--tests/auto/extensionsystem/pluginspec/tst_pluginspec.cpp295
-rw-r--r--tests/auto/fakevim/fakevim.pro24
-rw-r--r--tests/auto/filesearch/filesearch.pro22
-rw-r--r--tests/auto/filesearch/testfile.txt5
-rw-r--r--tests/auto/filesearch/tst_filesearch.cpp102
-rw-r--r--tests/auto/filesearch/tst_filesearch.qrc5
-rw-r--r--tests/auto/generichighlighter/highlighterengine/highlighterengine.pro2
-rw-r--r--tests/auto/generichighlighter/highlighterengine/syntaxhighlighter.h17
-rw-r--r--tests/auto/generichighlighter/specificrules/specificrules.pro4
-rw-r--r--tests/auto/generichighlighter/specificrules/tst_specificrules.cpp50
-rw-r--r--tests/auto/icheckbuild/parsemanager.h2
-rw-r--r--tests/auto/ioutils/ioutils.pro13
-rw-r--r--tests/auto/ioutils/tst_ioutils.cpp87
-rw-r--r--tests/auto/profilereader/data/includefiles/pri.cpp0
-rw-r--r--tests/auto/profilereader/data/includefiles/pro.cpp0
-rw-r--r--tests/auto/profilereader/data/includefiles/test.pri1
-rw-r--r--tests/auto/profilereader/data/includefiles/test.pro6
-rw-r--r--tests/auto/profilereader/profilecache.h52
-rw-r--r--tests/auto/profilereader/profilereader.pro12
-rw-r--r--tests/auto/profilereader/qtversionmanager.h47
-rwxr-xr-xtests/auto/profilereader/sync114
-rw-r--r--tests/auto/profilereader/tst_profilereader.cpp78
-rw-r--r--tests/auto/qml/codemodel/basic/basic.pro45
-rw-r--r--tests/auto/qml/codemodel/basic/tst_basic.cpp244
-rw-r--r--tests/auto/qml/codemodel/codemodel.pro3
-rw-r--r--tests/auto/qml/qml.pro3
-rw-r--r--tests/auto/qml/qmldesigner/common/statichelpers.cpp2
-rw-r--r--tests/auto/qml/qmldesigner/coretests/coretests.pro12
-rw-r--r--tests/auto/qml/qmldesigner/data/fx/MyButton.qml3
-rw-r--r--tests/auto/qml/qmldesigner/propertyeditortests/propertyeditortests.pro2
-rw-r--r--tests/auto/qml/qmleditor/qmlcodeformatter/qmlcodeformatter.pro6
-rw-r--r--tests/auto/qml/qmleditor/qmlcodeformatter/tst_qmlcodeformatter.cpp35
-rw-r--r--tests/auto/qml/qmlprojectmanager/fileformat/fileformat.pro8
-rw-r--r--tests/auto/qml/qmlprojectmanager/fileformat/tst_fileformat.cpp89
-rw-r--r--tests/auto/qtcprocess/qtcprocess.pro22
-rw-r--r--tests/auto/qtcprocess/tst_qtcprocess.cpp698
-rw-r--r--tests/auto/qttest.pri17
-rw-r--r--tests/auto/qttestrpath.pri11
-rw-r--r--tests/auto/utils_stringutils/tst_stringutils.cpp86
-rw-r--r--tests/auto/utils_stringutils/utils_stringutils.pro8
-rw-r--r--tests/manual/ccdb/ccdb.pro29
-rw-r--r--tests/manual/ccdb/main.cpp53
-rw-r--r--tests/manual/cplusplus-dump/cplusplus-dump.pro19
-rw-r--r--tests/manual/cplusplus-dump/dumpers.inc1619
-rw-r--r--tests/manual/cplusplus-frontend/cplusplus-frontend.pro4
-rw-r--r--tests/manual/cplusplus-tools/cplusplus-tools.pro24
-rw-r--r--tests/manual/cplusplus-tools/detail/header.h30
-rw-r--r--tests/manual/cplusplus-tools/detail/source.cpp19
-rw-r--r--tests/manual/cplusplus-tools/dummy.cpp32
-rw-r--r--tests/manual/cplusplus-tools/dummy.h50
-rw-r--r--tests/manual/cplusplus-tools/main.cpp175
-rw-r--r--tests/manual/cppquickfix/convertnumericliteral.cpp2
-rw-r--r--tests/manual/fakevim/README2
-rw-r--r--tests/manual/fakevim/fakevim.pro33
-rw-r--r--tests/manual/gdbdebugger/gui/mainwindow.cpp66
-rw-r--r--tests/manual/gdbdebugger/gui/mainwindow.h4
-rw-r--r--tests/manual/gdbdebugger/gui/mainwindow.ui14
-rw-r--r--tests/manual/gdbdebugger/simple/simple_gdbtest_app.cpp117
-rw-r--r--tests/manual/gdbdebugger/simple/simple_gdbtest_app.pro8
-rw-r--r--tests/manual/manual.pro9
-rw-r--r--tests/manual/preprocessor/preprocessor.pro3
-rw-r--r--tests/manual/process/process.pro10
-rw-r--r--tests/manual/qml-ast2dot/main.cpp367
-rw-r--r--tests/manual/qml-ast2dot/qml-ast2dot.pro22
-rw-r--r--tests/manual/qmlstandalone/helpers.cpp33
-rw-r--r--tests/manual/qmlstandalone/main.cpp28
-rw-r--r--tests/manual/qmlstandalone/qmlstandalone.pro3
-rw-r--r--tests/manual/search/latin1.txt1
-rw-r--r--tests/manual/search/search.pro1
-rw-r--r--tests/manual/ssh/errorhandling/main.cpp8
-rw-r--r--tests/manual/ssh/remoteprocess/argumentscollector.cpp129
-rw-r--r--tests/manual/ssh/remoteprocess/argumentscollector.h31
-rw-r--r--tests/manual/ssh/remoteprocess/main.cpp26
-rw-r--r--tests/manual/ssh/remoteprocess/remoteprocess.pro6
-rw-r--r--tests/manual/ssh/remoteprocess/remoteprocesstest.cpp184
-rw-r--r--tests/manual/ssh/remoteprocess/remoteprocesstest.h37
-rw-r--r--tests/manual/ssh/ssh.pri16
-rw-r--r--tests/manual/ssh/ssh.pro2
-rw-r--r--tests/manual/trk/README47
-rwxr-xr-xtests/manual/trk/run.pl164
-rwxr-xr-xtests/manual/trk/runner.cpp245
-rw-r--r--tests/manual/trk/runner.pro24
-rw-r--r--tests/manual/trk/swapendian.cpp23
-rw-r--r--tests/manual/trk/swapendian.pro9
-rw-r--r--tests/manual/trk/trk.pro7
-rw-r--r--tests/manual/trk/trklauncher.pri15
-rw-r--r--tests/manual/trk/trkolddevice.cpp694
-rw-r--r--tests/manual/trk/trkolddevice.h206
-rw-r--r--tests/manual/trk/trkserver.cpp517
-rw-r--r--tests/manual/trk/trkserver.pro10
-rw-r--r--tests/manual/trklauncher/main.cpp208
-rw-r--r--tests/tests.pro3
-rw-r--r--tests/tools/ccdb/README (renamed from tests/manual/ccdb/README)0
-rw-r--r--tests/tools/ccdb/ccdb.pro32
-rw-r--r--tests/tools/ccdb/cdbapplication.cpp (renamed from tests/manual/ccdb/cdbapplication.cpp)0
-rw-r--r--tests/tools/ccdb/cdbapplication.h (renamed from tests/manual/ccdb/cdbapplication.h)0
-rw-r--r--tests/tools/ccdb/cdbpromptthread.cpp (renamed from tests/manual/ccdb/cdbpromptthread.cpp)0
-rw-r--r--tests/tools/ccdb/cdbpromptthread.h (renamed from tests/manual/ccdb/cdbpromptthread.h)0
-rw-r--r--tests/tools/ccdb/debugeventcallback.cpp (renamed from tests/manual/ccdb/debugeventcallback.cpp)0
-rw-r--r--tests/tools/ccdb/debugeventcallback.h (renamed from tests/manual/ccdb/debugeventcallback.h)0
-rw-r--r--tests/tools/ccdb/main.cpp49
-rw-r--r--tests/tools/codaclient/codaclient.pro15
-rw-r--r--tests/tools/codaclient/codaclientapplication.cpp593
-rw-r--r--tests/tools/codaclient/codaclientapplication.h105
-rw-r--r--tests/tools/codaclient/main.cpp59
-rwxr-xr-xtests/tools/cplusplus-dump/c++ (renamed from tests/manual/cplusplus-dump/c++)0
-rw-r--r--tests/tools/cplusplus-dump/conf.c++ (renamed from tests/manual/cplusplus-dump/conf.c++)0
-rw-r--r--tests/tools/cplusplus-dump/cplusplus-dump.pro20
-rw-r--r--tests/tools/cplusplus-dump/dumpers.inc1621
-rw-r--r--tests/tools/cplusplus-dump/main.cpp (renamed from tests/manual/cplusplus-dump/main.cpp)0
-rw-r--r--tests/tools/cplusplus-dump/tests/templ01.cpp (renamed from tests/manual/cplusplus-dump/tests/templ01.cpp)0
-rw-r--r--tests/tools/qml-ast2dot/main.cpp367
-rw-r--r--tests/tools/qml-ast2dot/qml-ast2dot.pro21
-rw-r--r--tests/tools/qtquickappblaster/main.cpp102
-rw-r--r--tests/tools/qtquickappblaster/qtquickappblaster.pro17
-rw-r--r--tests/tools/qtquickappblaster/qtquickappblaster.qrc5
-rw-r--r--tests/tools/qtquickappblaster/qtquickapps.xml268
-rw-r--r--tests/tools/tools.pro7
-rw-r--r--tests/tools/trklauncher/main.cpp208
-rw-r--r--tests/tools/trklauncher/trklauncher.pro (renamed from tests/manual/trklauncher/trklauncher.pro)0
1989 files changed, 108326 insertions, 57457 deletions
diff --git a/.gitignore b/.gitignore
index ba6fcc2827..23e0601135 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,6 +30,9 @@ Thumbs.db
# qtcreator generated files
*.pro.user*
+*.pluginspec
+src/app/Info.plist
+src/plugins/coreplugin/ide_version.h
# xemacs temporary files
*.flc
@@ -75,6 +78,10 @@ bin/*.dll
bin/qtcreator
bin/qtcreator_process_stub*
bin/qtcreator.exe
+bin/qmlpuppet
+bin/qmlpuppet.exe
+bin/qtpromaker
+bin/qtpromaker.exe
share/doc/qtcreator/qtcreator.qch
src/tools/gen-cpp-ast/generate-ast
src/tools/mkvisitor/cplusplus0
@@ -89,6 +96,13 @@ tests/manual/gdbdebugger/simple/libsimple_gdbtest_plugin.*dylib
tests/manual/plain-cplusplus/plain-c++
tests/manual/preprocessor/pp
tests/auto/cplusplus/codegen/tst_codegen
+tests/auto/cplusplus/ast/tst_ast
+tests/auto/cplusplus/codeformatter/tst_codeformatter
+tests/auto/cplusplus/findusages/tst_findusages
+tests/auto/cplusplus/lookup/tst_lookup
+tests/auto/cplusplus/preprocessor/tst_preprocessor
+tests/auto/cplusplus/semantic/tst_semantic
+tests/auto/cplusplus/typeprettyprinter/tst_typeprettyprinter
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/README b/README
index f088185ad4..973534fdd5 100644
--- a/README
+++ b/README
@@ -1,5 +1,5 @@
-Qt Creator 2.0.95
-===============
+Qt Creator
+==========
Qt Creator is a crossplatform C++ IDE for development with the Qt framework.
Supported Platforms
@@ -8,7 +8,7 @@ The binary packages support the following platforms:
Windows XP SP2, Windows Vista
(K)Ubuntu Linux 7.04 32bit and 64bit
-Mac OS 10.4 and later
+Mac OS 10.5 and later
Building the sources requires Qt 4.7.0 or later.
@@ -17,7 +17,8 @@ Compiling Qt Creator
Prerequisites:
* Qt 4.7
* On Windows: mingw 4.4 or later, Visual Studio 2008 or later
- * On Mac: XCode 2.5 or later
+ * On Mac: XCode 2.5 or later, compiling on 10.4 requires to set the
+ environment variable QTC_TIGER_COMPAT before running qmake
We recommend that you build Qt Creator not in the source directory, but in a
separate directory. To do that, use the following commands:
diff --git a/dist/changes-2.2.0 b/dist/changes-2.2.0
new file mode 100644
index 0000000000..0e23053f4e
--- /dev/null
+++ b/dist/changes-2.2.0
@@ -0,0 +1,46 @@
+The QtCreator 2.2 release contains bug fixes and new features.
+
+Below is a list of relevant changes. You can find a complete list of changes
+within the logs of Qt Creator sources. Simply check it out from the public git
+repository. For example:
+
+git clone git://gitorious.org/qt-creator/qt-creator.git
+git log --cherry-pick --pretty=oneline origin/master...origin/2.1
+
+General
+
+Editing
+ * Add new Inkpot color scheme
+
+Project Support
+
+Debugging
+
+Help
+
+QML/JS Support
+
+FakeVim:
+
+Platform Specific
+
+Mac
+
+Linux (GNOME and KDE)
+
+Windows
+
+Symbian Target
+
+Maemo Target
+
+Designer
+
+Version control plugins
+
+Wizards
+
+Additional credits go to:
+ * The Inkpot color scheme was based on the Vim color scheme by
+ Ciaran McCreesh, adapted for Qt Creator by Jan Kundrát and
+ subsequently updated by Campbell Barton.
diff --git a/doc/doc.pri b/doc/doc.pri
index d148962273..605ae9192b 100644
--- a/doc/doc.pri
+++ b/doc/doc.pri
@@ -1,14 +1,18 @@
QDOC_BIN = $$targetPath($$[QT_INSTALL_BINS]/qdoc3)
HELPGENERATOR = $$targetPath($$[QT_INSTALL_BINS]/qhelpgenerator)
+VERSION_TAG = $$replace(QTCREATOR_VERSION, "[-.]", )
+
equals(QMAKE_DIR_SEP, /) { # unix, mingw+msys
- QDOC = SRCDIR=$$PWD OUTDIR=$$OUT_PWD/doc/html $$QDOC_BIN
+ QDOC = SRCDIR=$$PWD OUTDIR=$$OUT_PWD/doc/html QTC_VERSION=$$QTCREATOR_VERSION QTC_VERSION_TAG=$$VERSION_TAG $$QDOC_BIN
} else:win32-g++* { # just mingw
# The lack of spaces in front of the && is necessary!
- QDOC = set SRCDIR=$$PWD&& set OUTDIR=$$OUT_PWD/doc/html&& $$QDOC_BIN
+ QDOC = set SRCDIR=$$PWD&& set OUTDIR=$$OUT_PWD/doc/html&& set QTC_VERSION=$$QTCREATOR_VERSION&& set QTC_VERSION_TAG=$$VERSION_TAG&& $$QDOC_BIN
} else { # nmake
QDOC = set SRCDIR=$$PWD $$escape_expand(\\n\\t) \
set OUTDIR=$$OUT_PWD/doc/html $$escape_expand(\\n\\t) \
+ set QTC_VERSION=$$QTCREATOR_VERSION $$escape_expand(\\n\\t) \
+ set QTC_VERSION_TAG=$$VERSION_TAG $$escape_expand(\\n\\t) \
$$QDOC_BIN
}
diff --git a/doc/examples/batteryindicator/deployment.pri b/doc/examples/batteryindicator/deployment.pri
index 7b7f7280fa..853feec5f3 100644
--- a/doc/examples/batteryindicator/deployment.pri
+++ b/doc/examples/batteryindicator/deployment.pri
@@ -41,7 +41,7 @@ symbian {
installPrefix = /opt/usr
desktopfile.path = /usr/share/applications/hildon
} else {
- installPrefix = /usr/local
+ installPrefix = /usr
desktopfile.path = /usr/share/applications
!isEqual(PWD,$$OUT_PWD) {
copyCommand = @echo Copying application data...
diff --git a/doc/pluginhowto/examples/dirmodelplugin/dirnavigationfactory.cpp b/doc/pluginhowto/examples/dirmodelplugin/dirnavigationfactory.cpp
index 49546074d6..f279012f33 100644
--- a/doc/pluginhowto/examples/dirmodelplugin/dirnavigationfactory.cpp
+++ b/doc/pluginhowto/examples/dirmodelplugin/dirnavigationfactory.cpp
@@ -12,7 +12,7 @@ Core::NavigationView DirNavigationFactory::createWidget()
{
Core::NavigationView view;
- // Create FileSystemModel and set the defauls path as home path
+ // Create FileSystemModel and set the default path as home path
FileSystemModel* model = new FileSystemModel;
model->setRootPath(QDir::homePath());
diff --git a/doc/qt-html-templates.qdocconf b/doc/qt-html-templates.qdocconf
index 96864cd3ab..ac94225b46 100644
--- a/doc/qt-html-templates.qdocconf
+++ b/doc/qt-html-templates.qdocconf
@@ -21,7 +21,7 @@ HTML.postheader = " <div class=\"header\" id=\"qtdocheader\">\n" \
" </div>\n" \
" <div id=\"shortCut\">\n" \
" <ul>\n" \
- " <li class=\"shortCut-topleft-inactive\"><span><a href=\"index.html\">Qt Creator 2.0.95 </a></span></li>\n" \
+ " <li class=\"shortCut-topleft-inactive\"><span><a href=\"index.html\">Qt Creator 2.1.81 </a></span></li>\n" \
" <li class=\"shortCut-topleft-active\"><a href=\"http://doc.qt.nokia.com\">ALL VERSIONS" \
" </a></li>\n" \
" </ul>\n" \
@@ -144,4 +144,4 @@ HTML.footer = "" \
" </form>\n" \
" </div>\n" \
" <div id=\"blurpage\">\n" \
- " </div>\n"
+ " </div>\n" \ No newline at end of file
diff --git a/doc/qtcreator.qdoc b/doc/qtcreator.qdoc
index d92bb248fa..dbb95860a2 100644
--- a/doc/qtcreator.qdoc
+++ b/doc/qtcreator.qdoc
@@ -39,7 +39,7 @@
\title Qt Creator Manual
- \section1 Version 2.0.95
+ \section1 Version \qtcversion
Qt Creator provides a cross-platform, complete integrated development
environment (IDE) for application developers to create applications for
@@ -3576,8 +3576,9 @@
\image qtcreator-build-steps.png "Build steps"
You can use any environment variables as values in the fields. For a list
- of variable names, click \gui {Build Environment > Details}. You can specify
- variables as ${VARNAME} or %VARNAME%. For example, ${BUILDDIR} or %BUILDDIR%.
+ of variable names, click \gui {Build Environment > Details}. Variables are
+ referenced using the platform's native syntax: $VARNAME or ${VARNAME} on
+ Unix and %VARNAME% on Windows.
\section2 Adding Custom Build Steps
@@ -3589,9 +3590,6 @@
\image qtcreator-build-steps-custom.png "Custom Process Step"
- \note Qt Creator sets SOURCEDIR and BUILDDIR as part of the build environment.
- For more information, see \l{Build Environment}.
-
\section1 Clean Steps
You can use the cleaning process to remove intermediate files. This process
@@ -6722,7 +6720,7 @@
p = gdb.Value(p_ptr["array"]).cast(innerType.pointer())
with Children(d, [size, 2000], innerType)
for i in d.childRange():
- d.putItem(Item(p.dereference(), item.iname, i))
+ d.putSubItem(Item(p.dereference(), item.iname, i))
p += 1
\endcode
@@ -6896,18 +6894,18 @@
not available when debugging core dumps and it is not available
on the Symbian platform due to restrictions imposed by AppTRK.
- \o \gui{putItemHelper(self, item)} - The "master function", handling
+ \o \gui{putItem(self, item)} - The "master function", handling
basic types, references, pointers and enums directly, iterates
over base classes and class members of compound types and calls
\c qdump__* functions whenever appropriate.
- \o \gui{putItem(self, item)} - Equivalent to:
+ \o \gui{putSubItem(self, item)} - Equivalent to:
\code
with SubItem(self):
- self.putItemHelper(item)
+ self.putItem(item)
\endcode
Exceptions raised by nested function calls are caught and all
- output produced by \c putItemHelper is replaced by the output of:
+ output produced by \c putItem is replaced by the output of:
\code
...
except RuntimeError:
@@ -6940,10 +6938,10 @@
with Children(d):
with SubItem(d):
d.putName("key")
- d.putItemHelper(Item(key, item.iname, "key"))
+ d.putItem(Item(key, item.iname, "key"))
with SubItem(d):
d.putName("value")
- d.putItemHelper(Item(value, item.iname, "value"))
+ d.putItem(Item(value, item.iname, "value"))
\endcode
\section1 Debugging Helpers for QML
@@ -8661,6 +8659,8 @@
\list 1
\o \c %YEAR%: Year
+ \o \c %MONTH%: Month
+ \o \c %DAY%: Day of the month
\o \c %DATE%: Date
\o \c %USER%: User name
\o \c %FILENAME%: File name
@@ -9539,7 +9539,11 @@
\row
\o -profile
- \o Load profile plugin.
+ \o Output plugin start up and shut down profiling data.
+
+ \row
+ \o -settingspath <path>
+ \o Override the default path where user settings are stored.
\row
\o -color <color>
diff --git a/doc/qtcreator.qdocconf b/doc/qtcreator.qdocconf
index 4ade11b3c4..d78705e23e 100644
--- a/doc/qtcreator.qdocconf
+++ b/doc/qtcreator.qdocconf
@@ -20,12 +20,12 @@ sources.fileextensions = "qtcreator.qdoc maemodev.qdoc symbiandev.qdoc addressb
qhp.projects = QtCreator
qhp.QtCreator.file = qtcreator.qhp
-qhp.QtCreator.namespace = com.nokia.qtcreator.2095
+qhp.QtCreator.namespace = com.nokia.qtcreator.$QTC_VERSION_TAG
qhp.QtCreator.virtualFolder = doc
qhp.QtCreator.indexTitle = Qt Creator
-qhp.QtCreator.filterAttributes = qtcreator 2.0.95
-qhp.QtCreator.customFilters.QtCreator.name = Qt Creator 2.0.95
-qhp.QtCreator.customFilters.QtCreator.filterAttributes = qtcreator 2.0.95
+qhp.QtCreator.filterAttributes = qtcreator $QTC_VERSION
+qhp.QtCreator.customFilters.QtCreator.name = Qt Creator $QTC_VERSION
+qhp.QtCreator.customFilters.QtCreator.filterAttributes = qtcreator $QTC_VERSION
qhp.QtCreator.indexRoot =
qhp.QtCreator.extraFiles = style/style.css \
style/style_ie6.css \
@@ -66,6 +66,8 @@ qhp.QtCreator.subprojects.manual.type = manual
# macros.qdocconf
+macro.qtcversion = $QTC_VERSION
+
macro.aring.HTML = "&aring;"
macro.Auml.HTML = "&Auml;"
macro.author = "\\bold{Author:}"
diff --git a/qtcreator.pri b/qtcreator.pri
index 2994770571..45949bb8cd 100644
--- a/qtcreator.pri
+++ b/qtcreator.pri
@@ -1,6 +1,8 @@
!isEmpty(QTCREATOR_PRI_INCLUDED):error("qtcreator.pri already included")
QTCREATOR_PRI_INCLUDED = 1
+QTCREATOR_VERSION = 2.1.81
+
defineReplace(cleanPath) {
win32:1 ~= s|\\\\|/|g
contains(1, ^/.*):pfx = /
@@ -99,6 +101,11 @@ macx {
IDE_BIN_PATH = $$IDE_APP_PATH/$${IDE_APP_TARGET}.app/Contents/MacOS
contains(QT_CONFIG, ppc):CONFIG += ppc x86
copydata = 1
+ isEmpty(TIGER_COMPAT_MODE):TIGER_COMPAT_MODE=$$(QTC_TIGER_COMPAT)
+ isEmpty(TIGER_COMPAT_MODE) {
+ QMAKE_CXXFLAGS *= -mmacosx-version-min=10.5
+ QMAKE_LFLAGS *= -mmacosx-version-min=10.5
+ }
} else {
win32 {
contains(TEMPLATE, vc.*)|contains(TEMPLATE_PREFIX, vc):vcproj = 1
diff --git a/scripts/krazy2tasks.pl b/scripts/krazy2tasks.pl
new file mode 100755
index 0000000000..0f42efc058
--- /dev/null
+++ b/scripts/krazy2tasks.pl
@@ -0,0 +1,24 @@
+#!/usr/bin/perl -w
+
+use strict;
+
+my $file = shift;
+die "No .tasks file given to save data into." unless ($file);
+
+open(PIPE, "krazy2all . --export textedit |") or
+ die "Could not start krazy2all, please make sure it is in your PATH.";
+open(FILE, ">$file") or die "Failed to open \"$file\" for writing.";
+
+while (<PIPE>) {
+ my $line = $_;
+ chomp $line;
+ next unless $line =~ /^(.*):(\d+):(.*)$/;
+
+ my $file = $1;
+ my $lineno = $2;
+ my $description = $3;
+ next if $file =~ /\/3rdparty\//;
+
+ print FILE "$file\t$lineno\tWARN\tKrazy: $description\n";
+}
+
diff --git a/scripts/mytasks.pl b/scripts/mytasks.pl
index 1cceedb964..a1ca52a2fc 100644
--- a/scripts/mytasks.pl
+++ b/scripts/mytasks.pl
@@ -20,27 +20,70 @@ sub checkLine {
$file = escape($file);
$row = escape($row);
- if ($line =~ /(FIXME|TODO)(.*)$/) {
+ if ($file =~ /(.cpp|.c|.cxx|.h)$/ && $line =~ /(FIXME|TODO)(.*)$/) {
print "$file\t$row\tWARNING\t$1$2\n";
}
- if ($line =~ /(qDebug|QDebug>|QtDebug>|<debug>)/) {
- print "$file\t$row\tWARNING\tRemove debug code\n";
+ if ($file =~ /(.cpp|.c|.cxx|.h)$/ && $line =~ /(qDebug|QDebug>|QtDebug>|<debug>)/) {
+ print "$file\t$row\tWARNING\tRemove debug code.\n";
}
if ($line =~ /^(<<<<|====|>>>>)/) {
- print "$file\n$row\tERROR\tResolve conflict!\n";
+ print "$file\n$row\tERROR\tResolved conflict.\n";
}
- if ($line =~ /(Q_SIGNALS|Q_SLOTS)/) {
- print "$file\t$row\tWARNING\tPrefer signals and slots over Q_SIGNALS and Q_SLOTS\n";
+ if ($file =~ /(.cpp|.c|.cxx|.h)$/ && $line =~ /(Q_SIGNALS|Q_SLOTS)/) {
+ print "$file\t$row\tWARNING\tPrefer signals and slots over Q_SIGNALS and Q_SLOTS.\n";
}
if ($line =~ /^#\s*(warning|error) (.*)$/) {
- print "$file\t$row\t$1\tClean up preprocessor $1:$2\n";
+ print "$file\t$row\t$1\tClean up preprocessor $1:$2.\n";
+ }
+ if ($file =~ /(.cpp|.c|.cxx|.h)$/ && $line =~ /\s+$/) {
+ print "$file\t$row\tWARNING\tTrailing whitespaces found.\n";
+ }
+ if ($file =~ /(.cpp|.c|.cxx|.h)$/ && $line =~ /^ *\t */) {
+ print "$file\t$row\tWARNING\tTabs used to indent.\n";
+ }
+ if ($file =~ /(.cpp|.c|.cxx|.h)$/ && $line =~ /^\s*{$/) {
+ print "$file\t$row\tWARNING\tOpening bracket found all alone on a line.\n";
+ }
+ if ($file =~ /(.cpp|.c|.cxx|.h)$/ && $line =~ /{.*[^\s].*$/) {
+ if ($line !~ /{\s+\/\*/)
+ { print "$file\t$row\tWARNING\tText found after opening bracket.\n"; }
+ }
+ if ($file =~ /(.cpp|.c|.cxx|.h)$/ && $line =~ /[a-zA-Z0-9_]([*&])[^\/]/) {
+ print "$file\t$row\tWARNING\tUse \"TYPE ${1}NAME\" (currently the space between TYPE and $1 is missing).\n";
+ }
+ if ($file =~ /(.cpp|.c|.cxx|.h)$/ && $line =~ /[*&]\s+/) {
+ next if ($line =~ /^\s*\*\s+/);
+ next if ($line =~ /\/\*/);
+ print "$file\t$row\tWARNING\tUse \"TYPE ${1}NAME\" (currently there is a space between $1 and NAME).\n";
}
}
my $filename = "";
my $pos = 0;
-open(PIPE, "git diff origin/master|");
+sub getDiffOrigin {
+ my $currentBranch = `git branch | grep "^* "`;
+ chop $currentBranch;
+ $currentBranch =~ s/^* //;
+
+ my $remoteRepo = `git config --local --get branch.$currentBranch.remote`;
+ chop $remoteRepo;
+
+ return "HEAD" if (!$remoteRepo);
+
+ my $remoteBranch = `git config --local --get branch.$currentBranch.merge`;
+ chop $remoteBranch;
+ $remoteBranch =~ s!^refts/heads/!!;
+
+ return "HEAD" if (!$remoteBranch);
+
+ return "$remoteRepo/$remoteBranch";
+}
+
+my $origin = getDiffOrigin;
+print "# running: git diff $origin ...\n";
+
+open(PIPE, "git diff $origin|");
while (<PIPE>) {
chomp;
my $line = $_;
diff --git a/scripts/replaceVersion.sh b/scripts/replaceVersion.sh
deleted file mode 100755
index 0e7dc87ebe..0000000000
--- a/scripts/replaceVersion.sh
+++ /dev/null
@@ -1,138 +0,0 @@
-#! /usr/bin/env bash
-
-## Command line parameters
-if [[ $# != 2 ]]; then
- cat <<USAGE
-usage:
- $0 <old> <new>
-example:
- $0 '1.2.3' '1.2.4'
-USAGE
- exit 1
-fi
-
-
-## Process and show version
-OLD=`sed 's/\./\\\\./g' <<<"$1"`
-NEW=`sed 's/\./\\\\./g' <<<"$2"`
-
-OLD_MAJOR=`sed 's/^\([0-9]*\)\.[0-9]*\.[0-9]*/\1/' <<<"$1"`
-NEW_MAJOR=`sed 's/^\([0-9]*\)\.[0-9]*\.[0-9]*/\1/' <<<"$2"`
-
-OLD_MINOR=`sed 's/^[0-9]*\.\([0-9]*\)\.[0-9]*/\1/' <<<"$1"`
-NEW_MINOR=`sed 's/^[0-9]*\.\([0-9]*\)\.[0-9]*/\1/' <<<"$2"`
-
-OLD_RELEASE=`sed 's/^[0-9]*\.[0-9]*\.\([0-9]*\)/\1/' <<<"$1"`
-NEW_RELEASE=`sed 's/^[0-9]*\.[0-9]*\.\([0-9]*\)/\1/' <<<"$2"`
-
-OLD_THREE="${OLD_MAJOR}${OLD_MINOR}${OLD_RELEASE}"
-NEW_THREE="${NEW_MAJOR}${NEW_MINOR}${NEW_RELEASE}"
-
-OLD_DOT_THREE="${OLD_MAJOR}\\.${OLD_MINOR}\\.${OLD_RELEASE}"
-NEW_DOT_THREE="${NEW_MAJOR}\\.${NEW_MINOR}\\.${NEW_RELEASE}"
-
-OLD_DOT_FOUR="${OLD_MAJOR}\\.${OLD_MINOR}\\.${OLD_RELEASE}\\.0"
-NEW_DOT_FOUR="${NEW_MAJOR}\\.${NEW_MINOR}\\.${NEW_RELEASE}\\.0"
-
-OLD_COMMA_FOUR="${OLD_MAJOR},${OLD_MINOR},${OLD_RELEASE},0"
-NEW_COMMA_FOUR="${NEW_MAJOR},${NEW_MINOR},${NEW_RELEASE},0"
-
-echo "#==============================================="
-echo "# Plain '${OLD}' -> '${NEW}'"
-echo "#-----------------------------------------------"
-echo "# Major '${OLD_MAJOR}' -> '${NEW_MAJOR}'"
-echo "# Minor '${OLD_MINOR}' -> '${NEW_MINOR}'"
-echo "# Release '${OLD_RELEASE}' -> '${NEW_RELEASE}'"
-echo "#-----------------------------------------------"
-echo "# 3 '${OLD_THREE}' -> '${NEW_THREE}'"
-echo "# Dot 3 '${OLD_DOT_THREE}' -> '${NEW_DOT_THREE}'"
-echo "# Dot 4 '${OLD_DOT_FOUR}' -> '${NEW_DOT_FOUR}'"
-echo "# Comma 4 '${OLD_COMMA_FOUR}' -> '${NEW_COMMA_FOUR}'"
-echo "#==============================================="
-echo
-
-
-## Make script safe to call from anywhere by going home first
-SCRIPT_DIR=`dirname "${PWD}/$0"`/..
-echo "Entering directory \`${SCRIPT_DIR}'"
-pushd "${SCRIPT_DIR}" &>/dev/null || exit 1
-
-
-## Patch *.pluginspec
-while read i ; do
- echo "Patching \`$i'"
- TMPFILE=`mktemp versionPatch.XXXXXX`
- sed -e 's/version="'"${OLD}"'"/version="'"${NEW}"'"/' \
- -e 's/compatVersion="'"${OLD}"'"/compatVersion="'"${NEW}"'"/' \
- "${i}" > "${TMPFILE}"
- mv -f "${TMPFILE}" "${i}"
-done < <(find . -name '*.pluginspec')
-
-
-## Patch coreconstants.h
-TMPFILE=`mktemp versionPatch.XXXXXX`
-CORE_CONSTANT_H="${SCRIPT_DIR}/src/plugins/coreplugin/coreconstants.h"
-echo "Patching \`${CORE_CONSTANT_H}'"
-sed \
- -e 's/^\(#define IDE_VERSION_MAJOR \)'"${OLD_MAJOR}"'/\1'"${NEW_MAJOR}"'/' \
- -e 's/^\(#define IDE_VERSION_MINOR \)'"${OLD_MINOR}"'/\1'"${NEW_MINOR}"'/' \
- -e 's/^\(#define IDE_VERSION_RELEASE \)'"${OLD_RELEASE}"'/\1'"${NEW_RELEASE}"'/' \
- "${CORE_CONSTANT_H}" > "${TMPFILE}"
-mv -f "${TMPFILE}" "${CORE_CONSTANT_H}"
-
-
-## Patch Info.plist
-TMPFILE=`mktemp versionPatch.XXXXXX`
-INFO_PLIST="${SCRIPT_DIR}/src/app/Info.plist"
-echo "Patching \`${INFO_PLIST}'"
-sed \
- -e "s/"${OLD}"/"${NEW}"/" \
- "${INFO_PLIST}" > "${TMPFILE}"
-mv -f "${TMPFILE}" "${INFO_PLIST}"
-
-
-## Patch qtcreator.qdocconf
-TMPFILE=`mktemp versionPatch.XXXXXX`
-QDOCCONF="${SCRIPT_DIR}/doc/qtcreator.qdocconf"
-echo "Patching \`${QDOCCONF}'"
-sed \
- -e "s/"${OLD_DOT_THREE}"/"${NEW_DOT_THREE}"/" \
- -e "s/"${OLD_THREE}"/"${NEW_THREE}"/" \
- "${QDOCCONF}" > "${TMPFILE}"
-mv -f "${TMPFILE}" "${QDOCCONF}"
-
-## Patch qt-html-templates.qdocconf
-TMPFILE=`mktemp versionPatch.XXXXXX`
-QDOCCONF="${SCRIPT_DIR}/doc/qt-html-templates.qdocconf"
-echo "Patching \`${QDOCCONF}'"
-sed \
- -e "s/"${OLD_DOT_THREE}"/"${NEW_DOT_THREE}"/" \
- -e "s/"${OLD_THREE}"/"${NEW_THREE}"/" \
- "${QDOCCONF}" > "${TMPFILE}"
-mv -f "${TMPFILE}" "${QDOCCONF}"
-
-
-## Patch qtcreator.qdoc
-TMPFILE=`mktemp versionPatch.XXXXXX`
-QDOC="${SCRIPT_DIR}/doc/qtcreator.qdoc"
-echo "Patching \`${QDOC}'"
-sed \
- -e 's/'${OLD_DOT_THREE}'/'${NEW_DOT_THREE}'/' \
- "${QDOC}" > "${TMPFILE}"
-mv -f "${TMPFILE}" "${QDOC}"
-
-
-## Patch README
-TMPFILE=`mktemp versionPatch.XXXXXX`
-README="${SCRIPT_DIR}/README"
-echo "Patching \`${README}'"
-sed \
- -e 's/'${OLD_DOT_THREE}'/'${NEW_DOT_THREE}'/' \
- "${README}" > "${TMPFILE}"
-mv -f "${TMPFILE}" "${README}"
-
-
-## Go back to original $PWD
-echo "Leaving directory \`${SCRIPT_DIR}'"
-popd &>/dev/null || exit 1
-exit 0
diff --git a/share/qtcreator/gdbmacros/dumper.py b/share/qtcreator/gdbmacros/dumper.py
index d6d5e519d8..3699fc3844 100644
--- a/share/qtcreator/gdbmacros/dumper.py
+++ b/share/qtcreator/gdbmacros/dumper.py
@@ -144,6 +144,11 @@ def lookupType(typestring):
#if not type is None:
# warn(" FIELDS: '%s'" % type.fields())
typeCache[typestring] = type
+ if type is None and typestring.endswith('*'):
+ type = lookupType(typestring[0:-1])
+ if not type is None:
+ type = type.pointer()
+ typeCache[typestring] = type
if type is None:
# could be gdb.lookup_type("char[3]") generating
# "RuntimeError: No type named char[3]"
@@ -157,6 +162,44 @@ def cleanAddress(addr):
# that might trigger Unicode encoding errors.
return addr.cast(lookupType("void").pointer())
+def extractTemplateArgument(type, position):
+ level = 0
+ skipSpace = False
+ inner = ""
+ type = str(type)
+ for c in type[type.find('<') + 1 : -1]:
+ if c == '<':
+ inner += c
+ level += 1
+ elif c == '>':
+ level -= 1
+ inner += c
+ elif c == ',':
+ if level == 0:
+ if position == 0:
+ return inner
+ position -= 1
+ inner = ""
+ else:
+ inner += c
+ skipSpace = True
+ else:
+ if skipSpace and c == ' ':
+ pass
+ else:
+ inner += c
+ skipSpace = False
+ return inner
+
+def templateArgument(type, position):
+ try:
+ # This fails on stock 7.2 with
+ # "RuntimeError: No type named myns::QObject.\n"
+ return type.template_argument(position)
+ except:
+ # That's something like "myns::QList<...>"
+ return lookupType(extractTemplateArgument(type.strip_typedefs(), position))
+
# Workaround for gdb < 7.1
def numericTemplateArgument(type, position):
try:
@@ -474,6 +517,7 @@ def listOfLocals(varList):
warn("BLOCK NOT ACCESSIBLE FOR UNKNOWN REASONS")
return items
+ shadowed = {}
while True:
if block is None:
warn("UNEXPECTED 'None' BLOCK")
@@ -488,16 +532,27 @@ def listOfLocals(varList):
# Python scripts."
#warn("SYMBOL %s: " % symbol.value)
#warn("SYMBOL %s (%s): " % (symbol, name))
- item = Item(0, "local", name, name)
+ if name in shadowed:
+ level = shadowed[name]
+ name1 = "%s <shadowed %s>" % (name, level)
+ shadowed[name] = level + 1
+ else:
+ name1 = name
+ shadowed[name] = 1
+ #warn("SYMBOL %s (%s, %s)): " % (symbol, name, symbol.name))
+ item = Item(0, "local", name1, name1)
try:
- item.value = frame.read_var(name) # this is a gdb value
+ item.value = frame.read_var(name, block) # this is a gdb value
except:
- # RuntimeError: happens for
- # void foo() { std::string s; std::wstring w; }
- # ValueError: happens for (as of 2010/11/4)
- # a local struct as found e.g. in
- # gcc sources in gcc.c, int execute()
- continue
+ try:
+ item.value = frame.read_var(name) # this is a gdb value
+ except:
+ # RuntimeError: happens for
+ # void foo() { std::string s; std::wstring w; }
+ # ValueError: happens for (as of 2010/11/4)
+ # a local struct as found e.g. in
+ # gcc sources in gcc.c, int execute()
+ continue
#warn("ITEM %s: " % item.value)
items.append(item)
# The outermost block in a function has the function member
@@ -676,13 +731,24 @@ def checkPointerRange(p, n):
checkPointer(p)
++p
-def call(value, func):
- #warn("CALL: %s -> %s" % (value, func))
+def call2(value, func, args):
+ # args is a tuple.
+ arg = ""
+ for i in range(len(args)):
+ if i:
+ arg += ','
+ a = args[i]
+ if (':' in a) and not ("'" in a):
+ arg = "'%s'" % a
+ else:
+ arg += a
+
+ #warn("CALL: %s -> %s(%s)" % (value, func, arg))
type = stripClassTag(str(value.type))
if type.find(":") >= 0:
type = "'" + type + "'"
# 'class' is needed, see http://sourceware.org/bugzilla/show_bug.cgi?id=11912
- exp = "((class %s*)%s)->%s" % (type, value.address, func)
+ exp = "((class %s*)%s)->%s(%s)" % (type, value.address, func, arg)
#warn("CALL: %s" % exp)
result = None
try:
@@ -692,6 +758,9 @@ def call(value, func):
#warn(" -> %s" % result)
return result
+def call(value, func, *args):
+ return call2(value, func, args)
+
def makeValue(type, init):
type = stripClassTag(type)
if type.find(":") >= 0:
@@ -859,6 +928,9 @@ def extractFields(type):
# This seems to work.
#warn("TYPE 0: %s" % type)
type = stripTypedefs(type)
+ fields = type.fields()
+ if len(fields):
+ return fields
#warn("TYPE 1: %s" % type)
# This fails for arrays. See comment in lookupType.
type0 = lookupType(str(type))
@@ -956,19 +1028,17 @@ class FrameCommand(gdb.Command):
super(FrameCommand, self).__init__("bb", gdb.COMMAND_OBSCURE)
def invoke(self, args, from_tty):
- if args.startswith("options:profile"):
- if False:
- import cProfile
- cProfile.run('bb("%s")' % args, "/tmp/bbprof")
- # Examine with:
- # import bstats
- # pstats.Stats('bbprof').sort_stats('time').print_stats()
- if True:
- import timeit
- print timeit.repeat('bb("%s")' % args,
- 'from __main__ import bb', number=100)
+ if args.startswith("options:p1"):
+ import cProfile
+ cProfile.run('bb("%s")' % args, "/tmp/bbprof")
+ import pstats
+ pstats.Stats('/tmp/bbprof').sort_stats('time').print_stats()
+ elif args.startswith("options:p2"):
+ import timeit
+ print timeit.repeat('bb("%s")' % args,
+ 'from __main__ import bb', number=10)
else:
- output = bb(args)
+ output = bb(args)
try:
print(output)
except:
@@ -1079,6 +1149,10 @@ class Dumper:
self.partialUpdate = "partial" in options
#self.ns = qqNs
self.ns = qtNamespace()
+ try:
+ self.alienSource = catchCliOutput("info source")[0][-3:-1]==".d"
+ except:
+ self.alienSource = False
#warn("NAMESPACE: '%s'" % self.ns)
#warn("VARIABLES: %s" % varList)
@@ -1163,7 +1237,7 @@ class Dumper:
with SubItem(self):
self.put('iname="%s",' % item.iname)
self.putName(item.name)
- self.putItemCount(select(n <= 100, n, "> 100"))
+ self.putItemCount(n, 100)
self.putType(type)
self.putNumChild(n)
if self.isExpanded(item):
@@ -1171,7 +1245,7 @@ class Dumper:
with Children(self, n):
for i in xrange(n):
value = p.dereference()
- self.putItem(Item(value, item.iname, i, None))
+ self.putSubItem(Item(value, item.iname, i, None))
p += 1
if n > 100:
self.putEllipsis()
@@ -1183,7 +1257,7 @@ class Dumper:
with SubItem(self):
self.put('iname="%s",' % item.iname)
self.put('addr="%s",' % addr)
- self.putItemHelper(item)
+ self.putItem(item)
except AttributeError:
# Thrown by cleanAddress with message "'NoneType' object
# has no attribute 'cast'" for optimized-out values.
@@ -1278,7 +1352,7 @@ class Dumper:
item = Item(value, iname, None, None)
if not value is None:
self.putAddress(value.address)
- self.putItemHelper(item)
+ self.putItem(item)
except RuntimeError:
self.currentType = " "
self.currentValue = "<no such value>"
@@ -1297,9 +1371,12 @@ class Dumper:
return xrange(qmin(self.currentMaxNumChilds, self.currentNumChilds))
# Convenience function.
- def putItemCount(self, count):
+ def putItemCount(self, count, maximum = 1000000000):
# This needs to override the default value, so don't use 'put' directly.
- self.putValue('<%s items>' % count)
+ if count > maximum:
+ self.putValue('<>%s items>' % maximum)
+ else:
+ self.putValue('<%s items>' % count)
def putEllipsis(self):
self.put('{name="<incomplete>",value="",type="",numchild="0"},')
@@ -1406,15 +1483,15 @@ class Dumper:
format = self.typeformats.get(stripClassTag(str(item.value.type)))
return format
- def putItem(self, item):
+ def putSubItem(self, item):
with SubItem(self):
- self.putItemHelper(item)
+ self.putItem(item)
- def putCallItem(self, name, item, func):
- result = call(item.value, func)
- self.putItem(Item(result, item.iname, name, name))
+ def putCallItem(self, name, item, func, *args):
+ result = call2(item.value, func, args)
+ self.putSubItem(Item(result, item.iname, name, name))
- def putItemHelper(self, item):
+ def putItem(self, item):
name = getattr(item, "name", None)
if not name is None:
self.putName(name)
@@ -1460,6 +1537,66 @@ class Dumper:
value = item.value
type = value.type
+ if type.code == gdb.TYPE_CODE_STRUCT and self.alienSource:
+ try:
+ # Check whether it's an array.
+ arraylen = value["length"]
+ arrayptr = value["ptr"]
+ self.putType(type)
+ self.putAddress(value.address)
+ if str(type) == "struct char[]":
+ self.putValue(encodeCharArray(arrayptr, 100, arraylen),
+ Hex2EncodedLatin1)
+ self.putNumChild(0)
+ else:
+ self.putNumChild(arraylen)
+ self.putItemCount(arraylen)
+ if self.isExpanded(item):
+ with Children(self):
+ for i in range(arraylen):
+ v = arrayptr.dereference()
+ self.putSubItem(Item(v, item.iname))
+ arrayptr += 1
+ return
+ except:
+ pass
+
+ if type.code == gdb.TYPE_CODE_INT:
+ if self.alienSource and str(type) == "unsigned long long":
+ strlen = value % (1L<<32)
+ strptr = value / (1L<<32)
+ self.putType("string")
+ self.putAddress(value.address)
+ self.putValue(encodeCharArray(strptr, 100, strlen), Hex2EncodedLatin1)
+ self.putNumChild(0)
+ return
+ self.putType(realtype)
+ self.putValue(int(value))
+ self.putNumChild(0)
+ return
+
+ if type.code == gdb.TYPE_CODE_CHAR:
+ self.putType(realtype)
+ self.putValue(int(value))
+ self.putNumChild(0)
+ return
+
+ if value.type.code == gdb.TYPE_CODE_ARRAY:
+ self.putType(realtype)
+ self.putNumChild(1)
+ baseptr = value.cast(realtype.pointer())
+ self.putValue("%s" % baseptr)
+ if self.isExpanded(item):
+ charptr = lookupType("unsigned char").pointer()
+ addr1 = (baseptr+1).cast(charptr)
+ addr0 = baseptr.cast(charptr)
+ self.put('addrbase="%s",' % cleanAddress(addr0))
+ self.put('addrstep="%s",' % (addr1 - addr0))
+ with Children(self, 1, realtype.target()):
+ child = Item(value, item.iname, None, item.name)
+ self.putFields(child)
+ return
+
typedefStrippedType = stripTypedefs(type)
if isSimpleType(typedefStrippedType):
@@ -1481,12 +1618,16 @@ class Dumper:
if self.useFancy \
and ((format is None) or (format >= 1)) \
- and ((nsStrippedType in qqDumpers) or isQObjectDerived):
+ and ((nsStrippedType in qqDumpers) \
+ or (str(type) in qqDumpers) \
+ or isQObjectDerived):
#warn("IS DUMPABLE: %s " % type)
#self.putAddress(value.address)
self.putType(realtype)
if nsStrippedType in qqDumpers:
qqDumpers[nsStrippedType](self, item)
+ if str(type) in qqDumpers:
+ qqDumpers[str(type)](self, item)
elif isQObjectDerived:
# value has references stripped off item.value.
item1 = Item(value, item.iname)
@@ -1521,7 +1662,7 @@ class Dumper:
if self.isExpanded(item):
with Children(self):
with SubItem(self):
- self.putItemHelper(Item(item.value.dereference(),
+ self.putItem(Item(item.value.dereference(),
item.iname, "*", "*"))
self.putAddress(item.value)
return
@@ -1572,7 +1713,7 @@ class Dumper:
self.putType(innerType)
savedCurrentChildType = self.currentChildType
self.currentChildType = stripClassTag(str(innerType))
- self.putItemHelper(
+ self.putItem(
Item(item.value.dereference(), item.iname, None, None))
self.currentChildType = savedCurrentChildType
self.putPointerValue(value.address)
@@ -1586,7 +1727,7 @@ class Dumper:
if self.isExpanded(item):
with Children(self):
with SubItem(self):
- self.putItemHelper(Item(item.value.dereference(),
+ self.putItem(Item(item.value.dereference(),
item.iname, "*", "*"))
self.putAddress(item.value)
self.putPointerValue(value.address)
@@ -1625,15 +1766,8 @@ class Dumper:
numfields = len(fields)
self.putNumChild(numfields)
- if self.isExpanded(item):
- if value.type.code == gdb.TYPE_CODE_ARRAY:
- baseptr = value.cast(value.type.target().pointer())
- charptr = lookupType("unsigned char").pointer()
- addr1 = (baseptr+1).cast(charptr)
- addr0 = baseptr.cast(charptr)
- self.put('addrbase="%s",' % cleanAddress(addr0))
- self.put('addrstep="%s",' % (addr1 - addr0))
+ if self.isExpanded(item):
innerType = None
if len(fields) == 1 and fields[0].name is None:
innerType = value.type.target()
@@ -1641,6 +1775,14 @@ class Dumper:
child = Item(value, item.iname, None, item.name)
self.putFields(child)
+ def putPlainChildren(self, item):
+ self.putValue(" ", None, -99)
+ self.putNumChild(1)
+ self.putAddress(item.value.address)
+ if self.isExpanded(item):
+ with Children(self):
+ self.putFields(item)
+
def putFields(self, item):
value = item.value
type = stripTypedefs(value.type)
@@ -1658,7 +1800,7 @@ class Dumper:
innerType = type.target()
p = value.cast(innerType.pointer())
for i in xrange(type.sizeof / innerType.sizeof):
- self.putItem(Item(p.dereference(), item.iname, i, None))
+ self.putSubItem(Item(p.dereference(), item.iname, i, None))
p = p + 1
continue
@@ -1683,7 +1825,7 @@ class Dumper:
baseNumber += 1
with SubItem(self):
self.put('iname="%s",' % child.iname)
- self.putItemHelper(child)
+ self.putItem(child)
elif len(field.name) == 0:
# Anonymous union. We need a dummy name to distinguish
# multiple anonymous unions in the struct.
@@ -1695,7 +1837,7 @@ class Dumper:
with SubItem(self):
child = Item(value[field.name],
item.iname, field.name, field.name)
- self.putItemHelper(child)
+ self.putItem(child)
def listAnonymous(self, item, name, type):
@@ -1706,7 +1848,7 @@ class Dumper:
child = Item(value, item.iname, field.name, field.name)
with SubItem(self):
self.putAddress(value.address)
- self.putItemHelper(child)
+ self.putItem(child)
else:
# Further nested.
self.anonNumber += 1
diff --git a/share/qtcreator/gdbmacros/gdbmacros.cpp b/share/qtcreator/gdbmacros/gdbmacros.cpp
index 8b49c8479d..a66d53b302 100644
--- a/share/qtcreator/gdbmacros/gdbmacros.cpp
+++ b/share/qtcreator/gdbmacros/gdbmacros.cpp
@@ -494,8 +494,10 @@ struct QDumper
void beginItem(const char *name); // start of named item, ready to accept value
void endItem(); // end of named item, used after value output is complete
- // convienience for putting "<n items>"
+ // convenience for putting "<n items>"
void putItemCount(const char *name, int count);
+ // convenience for putting "<>n items>" (more than X items)
+ void putTruncatedItemCount(const char *name, int count);
void putCommaIfNeeded();
// convienience function for writing the last item of an abbreviated list
void putEllipsis();
@@ -757,6 +759,11 @@ void QDumper::putItemCount(const char *name, int count)
put(name).put("=\"<").put(count).put(" items>\"");
}
+void QDumper::putTruncatedItemCount(const char *name, int count)
+{
+ putCommaIfNeeded();
+ put(name).put("=\"<>").put(count).put(" items>\"");
+}
//
// Some helpers to keep the dumper code short
@@ -1193,26 +1200,30 @@ static void qDumpQByteArray(QDumper &d)
qCheckAccess(deref(d.data)); // is the d-ptr de-referenceable and valid
const QByteArray &ba = *reinterpret_cast<const QByteArray *>(d.data);
+ const int size = ba.size();
+ if (size < 0)
+ return;
+
if (!ba.isEmpty()) {
qCheckAccess(ba.constData());
- qCheckAccess(ba.constData() + ba.size());
+ qCheckAccess(ba.constData() + size);
}
d.beginItem("value");
- if (ba.size() <= 100)
+ if (size <= 100)
d.put(ba);
else
- d.put(ba.left(100)).put(" <size: ").put(ba.size()).put(", cut...>");
+ d.put(ba.left(100)).put(" <size: ").put(size).put(", cut...>");
d.endItem();
d.putItem("valueencoded", "1");
d.putItem("type", NS"QByteArray");
- d.putItem("numchild", ba.size());
+ d.putItem("numchild", size);
if (d.dumpChildren) {
d.putItem("childtype", "char");
d.putItem("childnumchild", "0");
d.beginChildren();
char buf[20];
- for (int i = 0; i != ba.size(); ++i) {
+ for (int i = 0; i != size; ++i) {
unsigned char c = ba.at(i);
unsigned char u = (isprint(c) && c != '\'' && c != '"') ? c : '?';
sprintf(buf, "%02x (%u '%c')", c, c, u);
@@ -2454,7 +2465,7 @@ static const char *qConnectionType(uint type)
#endif
};
return output;
-};
+}
#if QT_VERSION >= 0x040400
static const ConnectionList &qConnectionList(const QObject *ob, int signalNumber)
@@ -3152,16 +3163,18 @@ static void qDumpStdList(QDumper &d)
p = deref(addOffset(p, sizeof(void*)));
qCheckAccess(p);
#endif
- int nn = 0;
+ std::list<int>::size_type nn = 0;
+ const std::list<int>::size_type maxItems = 100;
std::list<int>::const_iterator it = list.begin();
const std::list<int>::const_iterator cend = list.end();
- for (; nn < 101 && it != cend; ++nn, ++it)
+ for (; nn < maxItems && it != cend; ++nn, ++it)
qCheckAccess(it.operator->());
- if (nn > 100)
- d.putItem("value", "<more than 100 items>");
- else
+ if (it != cend) {
+ d.putTruncatedItemCount("value", nn);
+ } else {
d.putItemCount("value", nn);
+ }
d.putItem("numchild", nn);
d.putItem("valueeditable", "false");
@@ -3171,7 +3184,7 @@ static void qDumpStdList(QDumper &d)
isPointerType(d.innerType) ? strippedInnerType.data() : 0;
d.beginChildren(d.innerType);
it = list.begin();
- for (int i = 0; i < 1000 && it != cend; ++i, ++it) {
+ for (std::list<int>::size_type i = 0; i < maxItems && it != cend; ++i, ++it) {
d.beginHash();
qDumpInnerValueOrPointer(d, d.innerType, stripped, it.operator->());
d.endHash();
@@ -3254,7 +3267,6 @@ static void qDumpStdMapHelper(QDumper &d)
for (int i = 0; i < nn && i < 10 && it != cend; ++i, ++it)
qCheckAccess(it.operator->());
- const QByteArray strippedInnerType = stripPointerType(d.innerType);
d.putItem("numchild", nn);
d.putItemCount("value", nn);
d.putItem("valueeditable", "false");
@@ -3403,7 +3415,7 @@ static void qDumpStdSet(QDumper &d)
#ifdef Q_CC_MSVC
// As the set implementation inherits from a base class
// depending on the key, use something equivalent to iterate it.
- const int innerSize = d.extraInt[0];
+ const size_t innerSize = d.extraInt[0];
if (innerSize == sizeof(int)) {
qDumpStdSetHelper<int>(d);
return;
diff --git a/share/qtcreator/gdbmacros/gdbmacros.py b/share/qtcreator/gdbmacros/gdbmacros.py
index 3c5a182053..9c64dd1e50 100644
--- a/share/qtcreator/gdbmacros/gdbmacros.py
+++ b/share/qtcreator/gdbmacros/gdbmacros.py
@@ -32,7 +32,7 @@ def qdump__QByteArray(d, item):
data = d_ptr['data']
p = gdb.Value(data.cast(innerType.pointer()))
for i in d.childRange():
- d.putItem(Item(p.dereference(), item.iname, i))
+ d.putSubItem(Item(p.dereference(), item.iname, i))
p += 1
@@ -42,48 +42,18 @@ def qdump__QChar(d, item):
d.putNumChild(0)
-def qdump__QAbstractItem(d, item):
- r = item.value["r"]
- c = item.value["c"]
- p = item.value["p"]
- m = item.value["m"]
- rowCount = call(m, "rowCount(mi)")
- if rowCount < 0:
- return
- columnCount = call(m, "columnCount(mi)")
- if columnCount < 0:
- return
- d.putStringValue(call(m, "data(mi, Qt::DisplayRole).toString()"))
- d.putNumChild(rowCount * columnCount)
- if d.isExpanded(item):
- with Children(d):
- innerType = lookupType(d.ns + "QAbstractItem")
- for row in xrange(rowCount):
- for column in xrange(columnCount):
- with SubItem(d):
- child = call(m, "index(row, column, mi)")
- d.putName("[%s,%s]" % (row, column))
- rr = call(m, "rowCount(child)")
- cc = call(m, "columnCount(child)")
- d.putNumChild(rr * cc)
- d.putValue(
- call(m, "data(child, Qt::DisplayRole).toString())"), 6)
-
- #with SubItem(d):
- # d.putNumChild(1)
- # d.putName(d.ns + "QObject")
- # d.putStringValue(call(item.value, "objectName()"))
- # d.putType(d.ns + "QObject")
- # d.put('addr="%s",' % cleanAddress(item.value.address))
-
def qdump__QAbstractItemModel(d, item):
# Create a default-constructed QModelIndex on the stack.
ri = makeValue(d.ns + "QModelIndex", "-1, -1, 0, 0")
this_ = makeExpression(item.value)
ri_ = makeExpression(ri)
- rowCount = int(parseAndEvaluate("%s.rowCount(%s)" % (this_, ri_)))
- columnCount = int(parseAndEvaluate("%s.columnCount(%s)" % (this_, ri_)))
+ try:
+ rowCount = int(parseAndEvaluate("%s.rowCount(%s)" % (this_, ri_)))
+ columnCount = int(parseAndEvaluate("%s.columnCount(%s)" % (this_, ri_)))
+ except:
+ d.putPlainChildren(item)
+ return
d.putValue("%d x %d" % (rowCount, columnCount))
d.putNumChild(rowCount * columnCount)
if d.isExpanded(item):
@@ -99,7 +69,7 @@ def qdump__QAbstractItemModel(d, item):
#warn("MI: %s " % mi)
#name = "[%d,%d]" % (row, column)
#d.putValue("%s" % mi)
- d.putItemHelper(Item(mi, item.iname, i))
+ d.putItem(Item(mi, item.iname, i))
i = i + 1
#warn("MI: %s " % mi)
#d.putName("[%d,%d]" % (row, column))
@@ -118,8 +88,12 @@ def qdump__QModelIndex(d, item):
mi = makeValue(d.ns + "QModelIndex", "%s,%s,%s,%s" % (r, c, p, m))
mm_ = makeExpression(mm)
mi_ = makeExpression(mi)
- rowCount = int(parseAndEvaluate("%s.rowCount(%s)" % (mm_, mi_)))
- columnCount = int(parseAndEvaluate("%s.columnCount(%s)" % (mm_, mi_)))
+ try:
+ rowCount = int(parseAndEvaluate("%s.rowCount(%s)" % (mm_, mi_)))
+ columnCount = int(parseAndEvaluate("%s.columnCount(%s)" % (mm_, mi_)))
+ except:
+ d.putPlainChildren(item)
+ return
try:
# Access DisplayRole as value
@@ -141,9 +115,9 @@ def qdump__QModelIndex(d, item):
d.putName("[%s, %s]" % (row, column))
mi2 = parseAndEvaluate("%s.index(%d,%d,%s)"
% (mm_, row, column, mi_))
- d.putItemHelper(Item(mi2, item.iname, i))
+ d.putItem(Item(mi2, item.iname, i))
i = i + 1
- #d.putCallItem("parent", item, "parent()")
+ #d.putCallItem("parent", item, "parent")
#with SubItem(d):
# d.putName("model")
# d.putValue(m)
@@ -163,24 +137,17 @@ def qdump__QDate(d, item):
d.putValue("(null)")
d.putNumChild(0)
return
- d.putStringValue(call(item.value, "toString('%sQt::TextDate')" % d.ns))
+ qt = d.ns + "Qt::"
+ d.putStringValue(call(item.value, "toString", qt + "TextDate"))
d.putNumChild(1)
if d.isExpanded(item):
# FIXME: This improperly uses complex return values.
- with Children(d, 8):
- d.putCallItem("toTime_t", item, "toTime_t()")
- d.putCallItem("toString",
- item, "toString('%sQt::TextDate')" % d.ns)
- d.putCallItem("(ISO)",
- item, "toString('%sQt::ISODate')" % d.ns)
- d.putCallItem("(SystemLocale)",
- item, "toString('%sQt::SystemLocaleDate')" % d.ns)
- d.putCallItem("(Locale)",
- item, "toString('%sQt::LocaleDate')" % d.ns)
- d.putCallItem("toUTC",
- item, "toTimeSpec('%sQt::UTC')" % d.ns)
- d.putCallItem("toLocalTime",
- item, "toTimeSpec('%sQt::LocalTime')" % d.ns)
+ with Children(d, 4):
+ d.putCallItem("toString", item, "toString", qt + "TextDate")
+ d.putCallItem("(ISO)", item, "toString", qt + "ISODate")
+ d.putCallItem("(SystemLocale)", item, "toString",
+ qt + "SystemLocaleDate")
+ d.putCallItem("(Locale)", item, "toString", qt + "LocaleDate")
def qdump__QTime(d, item):
@@ -188,48 +155,43 @@ def qdump__QTime(d, item):
d.putValue("(null)")
d.putNumChild(0)
return
- d.putStringValue(call(item.value, "toString('%sQt::TextDate')" % d.ns))
+ qt = d.ns + "Qt::"
+ d.putStringValue(call(item.value, "toString", qt + "TextDate"))
d.putNumChild(1)
if d.isExpanded(item):
# FIXME: This improperly uses complex return values.
with Children(d, 8):
- d.putCallItem("toString",
- item, "toString('%sQt::TextDate')" % d.ns)
- d.putCallItem("(ISO)",
- item, "toString('%sQt::ISODate')" % d.ns)
- d.putCallItem("(SystemLocale)",
- item, "toString('%sQt::SystemLocaleDate')" % d.ns)
- d.putCallItem("(Locale)",
- item, "toString('%sQt::LocaleDate')" % d.ns)
- d.putCallItem("toUTC",
- item, "toTimeSpec('%sQt::UTC')" % d.ns)
- #d.putCallItem("toLocalTime",
- # item, "toTimeSpec('%sQt::LocalTime')" % d.ns)
+ d.putCallItem("toString", item, "toString", qt + "TextDate")
+ d.putCallItem("(ISO)", item, "toString", qt + "ISODate")
+ d.putCallItem("(SystemLocale)", item, "toString",
+ qt + "SystemLocaleDate")
+ d.putCallItem("(Locale)", item, "toString", qt + "LocaleDate")
+ d.putCallItem("toUTC", item, "toTimeSpec", qt + "UTC")
def qdump__QDateTime(d, item):
- if int(item.value["d"]["d"].dereference()["time"]["mds"]) == -1:
- d.putValue("(null)")
- d.putNumChild(0)
+ try:
+ # Fails without debug info.
+ if int(item.value["d"]["d"].dereference()["time"]["mds"]) == -1:
+ d.putValue("(null)")
+ d.putNumChild(0)
+ return
+ except:
+ d.putPlainChildren(item)
return
- d.putStringValue(call(item.value, "toString('%sQt::TextDate')" % d.ns))
+ qt = d.ns + "Qt::"
+ d.putStringValue(call(item.value, "toString", qt + "TextDate"))
d.putNumChild(1)
if d.isExpanded(item):
# FIXME: This improperly uses complex return values.
with Children(d, 8):
- d.putCallItem("toTime_t", item, "toTime_t()")
- d.putCallItem("toString",
- item, "toString('%sQt::TextDate')" % d.ns)
- d.putCallItem("(ISO)",
- item, "toString('%sQt::ISODate')" % d.ns)
- d.putCallItem("(SystemLocale)",
- item, "toString('%sQt::SystemLocaleDate')" % d.ns)
- d.putCallItem("(Locale)",
- item, "toString('%sQt::LocaleDate')" % d.ns)
- d.putCallItem("toUTC",
- item, "toTimeSpec('%sQt::UTC')" % d.ns)
- #d.putCallItem("toLocalTime",
- # item, "toTimeSpec('%sQt::LocalTime')" % d.ns)
+ d.putCallItem("toTime_t", item, "toTime_t")
+ d.putCallItem("toString", item, "toString", qt + "TextDate")
+ d.putCallItem("(ISO)", item, "toString", qt + "ISODate")
+ d.putCallItem("(SystemLocale)", item, "toString", qt + "SystemLocaleDate")
+ d.putCallItem("(Locale)", item, "toString", qt + "LocaleDate")
+ d.putCallItem("toUTC", item, "toTimeSpec", qt + "UTC")
+ d.putCallItem("toLocalTime", item, "toTimeSpec", qt + "LocalTime")
def qdump__QDir(d, item):
@@ -237,8 +199,8 @@ def qdump__QDir(d, item):
d.putNumChild(2)
if d.isExpanded(item):
with Children(d, 2):
- d.putCallItem("absolutePath", item, "absolutePath()")
- d.putCallItem("canonicalPath", item, "canonicalPath()")
+ d.putCallItem("absolutePath", item, "absolutePath")
+ d.putCallItem("canonicalPath", item, "canonicalPath")
def qdump__QFile(d, item):
@@ -252,33 +214,37 @@ def qdump__QFile(d, item):
def qdump__QFileInfo(d, item):
- d.putStringValue(item.value["d_ptr"]["d"].dereference()["fileName"])
+ try:
+ d.putStringValue(item.value["d_ptr"]["d"].dereference()["fileName"])
+ except:
+ d.putPlainChildren(item)
+ return
d.putNumChild(3)
if d.isExpanded(item):
with Children(d, 10, lookupType(d.ns + "QString")):
- d.putCallItem("absolutePath", item, "absolutePath()")
- d.putCallItem("absoluteFilePath", item, "absoluteFilePath()")
- d.putCallItem("canonicalPath", item, "canonicalPath()")
- d.putCallItem("canonicalFilePath", item, "canonicalFilePath()")
- d.putCallItem("completeBaseName", item, "completeBaseName()")
- d.putCallItem("completeSuffix", item, "completeSuffix()")
- d.putCallItem("baseName", item, "baseName()")
+ d.putCallItem("absolutePath", item, "absolutePath")
+ d.putCallItem("absoluteFilePath", item, "absoluteFilePath")
+ d.putCallItem("canonicalPath", item, "canonicalPath")
+ d.putCallItem("canonicalFilePath", item, "canonicalFilePath")
+ d.putCallItem("completeBaseName", item, "completeBaseName")
+ d.putCallItem("completeSuffix", item, "completeSuffix")
+ d.putCallItem("baseName", item, "baseName")
if False:
#ifdef Q_OS_MACX
- d.putCallItem("isBundle", item, "isBundle()")
- d.putCallItem("bundleName", item, "bundleName()")
- d.putCallItem("fileName", item, "fileName()")
- d.putCallItem("filePath", item, "filePath()")
+ d.putCallItem("isBundle", item, "isBundle")
+ d.putCallItem("bundleName", item, "bundleName")
+ d.putCallItem("fileName", item, "fileName")
+ d.putCallItem("filePath", item, "filePath")
# Crashes gdb (archer-tromey-python, at dad6b53fe)
- #d.putCallItem("group", item, "group()")
- #d.putCallItem("owner", item, "owner()")
- d.putCallItem("path", item, "path()")
+ #d.putCallItem("group", item, "group")
+ #d.putCallItem("owner", item, "owner")
+ d.putCallItem("path", item, "path")
- d.putCallItem("groupid", item, "groupId()")
- d.putCallItem("ownerid", item, "ownerId()")
+ d.putCallItem("groupid", item, "groupId")
+ d.putCallItem("ownerid", item, "ownerId")
#QFile::Permissions permissions () const
- perms = call(item.value, "permissions()")
+ perms = call(item.value, "permissions")
if perms is None:
d.putValue("<not available>")
else:
@@ -305,21 +271,21 @@ def qdump__QFileInfo(d, item):
#QDir absoluteDir () const
#QDir dir () const
- d.putCallItem("caching", item, "caching()")
- d.putCallItem("exists", item, "exists()")
- d.putCallItem("isAbsolute", item, "isAbsolute()")
- d.putCallItem("isDir", item, "isDir()")
- d.putCallItem("isExecutable", item, "isExecutable()")
- d.putCallItem("isFile", item, "isFile()")
- d.putCallItem("isHidden", item, "isHidden()")
- d.putCallItem("isReadable", item, "isReadable()")
- d.putCallItem("isRelative", item, "isRelative()")
- d.putCallItem("isRoot", item, "isRoot()")
- d.putCallItem("isSymLink", item, "isSymLink()")
- d.putCallItem("isWritable", item, "isWritable()")
- d.putCallItem("created", item, "created()")
- d.putCallItem("lastModified", item, "lastModified()")
- d.putCallItem("lastRead", item, "lastRead()")
+ d.putCallItem("caching", item, "caching")
+ d.putCallItem("exists", item, "exists")
+ d.putCallItem("isAbsolute", item, "isAbsolute")
+ d.putCallItem("isDir", item, "isDir")
+ d.putCallItem("isExecutable", item, "isExecutable")
+ d.putCallItem("isFile", item, "isFile")
+ d.putCallItem("isHidden", item, "isHidden")
+ d.putCallItem("isReadable", item, "isReadable")
+ d.putCallItem("isRelative", item, "isRelative")
+ d.putCallItem("isRoot", item, "isRoot")
+ d.putCallItem("isSymLink", item, "isSymLink")
+ d.putCallItem("isWritable", item, "isWritable")
+ d.putCallItem("created", item, "created")
+ d.putCallItem("lastModified", item, "lastModified")
+ d.putCallItem("lastRead", item, "lastRead")
def qdump__QFixed(d, item):
@@ -352,7 +318,7 @@ def qdump__QFixed(d, item):
def qdump__QFlags(d, item):
i = item.value["i"]
try:
- enumType = item.value.type.unqualified().template_argument(0)
+ enumType = templateArgument(item.value.type.unqualified(), 0)
d.putValue("%s (%s)" % (i.cast(enumType), i))
except:
d.putValue("%s" % i)
@@ -388,8 +354,8 @@ def qdump__QHash(d, item):
bucket += 1
return node
- keyType = item.value.type.template_argument(0)
- valueType = item.value.type.template_argument(1)
+ keyType = templateArgument(item.value.type, 0)
+ valueType = templateArgument(item.value.type, 1)
d_ptr = item.value["d"]
e_ptr = item.value["e"]
@@ -418,21 +384,21 @@ def qdump__QHash(d, item):
value = it["value"]
if isSimpleKey and isSimpleValue:
d.putName(key)
- d.putItemHelper(Item(value, item.iname, i))
+ d.putItem(Item(value, item.iname, i))
d.putType(valueType)
else:
- d.putItemHelper(Item(it, item.iname, i))
+ d.putItem(Item(it, item.iname, i))
node = hashDataNextNode(node)
def qdump__QHashNode(d, item):
- keyType = item.value.type.template_argument(0)
- valueType = item.value.type.template_argument(1)
+ keyType = templateArgument(item.value.type, 0)
+ valueType = templateArgument(item.value.type, 1)
key = item.value["key"]
value = item.value["value"]
if isSimpleType(keyType) and isSimpleType(valueType):
- d.putItemHelper(Item(value, "data", item.iname))
+ d.putItem(Item(value, "data", item.iname))
else:
d.putValue(" ")
@@ -441,10 +407,10 @@ def qdump__QHashNode(d, item):
with Children(d):
with SubItem(d):
d.putName("key")
- d.putItemHelper(Item(key, item.iname, "key"))
+ d.putItem(Item(key, item.iname, "key"))
with SubItem(d):
d.putName("value")
- d.putItemHelper(Item(value, item.iname, "value"))
+ d.putItem(Item(value, item.iname, "value"))
def qdump__QHostAddress(d, item):
@@ -470,7 +436,7 @@ def qdump__QList(d, item):
checkRef(d_ptr["ref"])
# Additional checks on pointer arrays.
- innerType = item.value.type.template_argument(0)
+ innerType = templateArgument(item.value.type, 0)
innerTypeIsPointer = innerType.code == gdb.TYPE_CODE_PTR \
and str(innerType.target().unqualified()) != "char"
if innerTypeIsPointer:
@@ -499,17 +465,21 @@ def qdump__QList(d, item):
for i in d.childRange():
if isInternal:
pp = p.cast(innerTypePointer).dereference();
- d.putItem(Item(pp, item.iname, i))
+ d.putSubItem(Item(pp, item.iname, i))
else:
pp = p.cast(innerTypePointer.pointer()).dereference()
- d.putItem(Item(pp, item.iname, i))
+ d.putSubItem(Item(pp, item.iname, i))
p += 1
def qform__QImage():
return "Normal,Displayed"
def qdump__QImage(d, item):
- painters = item.value["painters"]
+ try:
+ painters = item.value["painters"]
+ except:
+ d.putPlainChildren(item)
+ return
check(0 <= painters and painters < 1000)
d_ptr = item.value["d"]
if isNull(d_ptr):
@@ -565,34 +535,35 @@ def qdump__QLinkedList(d, item):
d.putItemCount(n)
d.putNumChild(n)
if d.isExpanded(item):
- with Children(d, [n, 1000], item.value.type.template_argument(0)):
+ innerType = templateArgument(item.value.type, 0)
+ with Children(d, [n, 1000], innerType):
p = e_ptr["n"]
for i in d.childRange():
- d.putItem(Item(p["t"], item.iname, i))
+ d.putSubItem(Item(p["t"], item.iname, i))
p = p["n"]
def qdump__QLocale(d, item):
- d.putStringValue(call(item.value, "name()"))
+ d.putStringValue(call(item.value, "name"))
d.putNumChild(0)
return
# FIXME: Poke back for variants.
if d.isExpanded(item):
with Children(d, 1, lookupType(d.ns + "QChar"), 0):
- d.putCallItem("country", item, "country()")
- d.putCallItem("language", item, "language()")
- d.putCallItem("measurementSystem", item, "measurementSystem()")
- d.putCallItem("numberOptions", item, "numberOptions()")
+ d.putCallItem("country", item, "country")
+ d.putCallItem("language", item, "language")
+ d.putCallItem("measurementSystem", item, "measurementSystem")
+ d.putCallItem("numberOptions", item, "numberOptions")
d.putCallItem("timeFormat_(short)", item,
- "timeFormat('" + d.ns + "QLocale::ShortFormat')")
+ "timeFormat", d.ns + "QLocale::ShortFormat")
d.putCallItem("timeFormat_(long)", item,
- "timeFormat('" + d.ns + "QLocale::LongFormat')")
- d.putCallItem("decimalPoint", item, "decimalPoint()")
- d.putCallItem("exponential", item, "exponential()")
- d.putCallItem("percent", item, "percent()")
- d.putCallItem("zeroDigit", item, "zeroDigit()")
- d.putCallItem("groupSeparator", item, "groupSeparator()")
- d.putCallItem("negativeSign", item, "negativeSign()")
+ "timeFormat", d.ns + "QLocale::LongFormat")
+ d.putCallItem("decimalPoint", item, "decimalPoint")
+ d.putCallItem("exponential", item, "exponential")
+ d.putCallItem("percent", item, "percent")
+ d.putCallItem("zeroDigit", item, "zeroDigit")
+ d.putCallItem("groupSeparator", item, "groupSeparator")
+ d.putCallItem("negativeSign", item, "negativeSign")
def qdump__QMapNode(d, item):
@@ -602,13 +573,13 @@ def qdump__QMapNode(d, item):
with Children(d, 2):
with SubItem(d):
d.putName("key")
- d.putItemHelper(Item(item.value["key"], item.iname, "name"))
+ d.putItem(Item(item.value["key"], item.iname, "name"))
with SubItem(d):
d.putName("value")
- d.putItemHelper(Item(item.value["value"], item.iname, "value"))
+ d.putItem(Item(item.value["value"], item.iname, "value"))
-def qdump__QMap(d, item):
+def qdumpHelper__QMap(d, item, forceLong):
d_ptr = item.value["d"].dereference()
e_ptr = item.value["e"].dereference()
n = d_ptr["size"]
@@ -621,8 +592,8 @@ def qdump__QMap(d, item):
if n > 1000:
n = 1000
- keyType = item.value.type.template_argument(0)
- valueType = item.value.type.template_argument(1)
+ keyType = templateArgument(item.value.type, 0)
+ valueType = templateArgument(item.value.type, 1)
isSimpleKey = isSimpleType(keyType)
isSimpleValue = isSimpleType(valueType)
@@ -649,15 +620,21 @@ def qdump__QMap(d, item):
#if isSimpleType(item.value.type): # or isStringType(d, item.value.type):
if isSimpleKey and isSimpleValue:
#d.putType(valueType)
- d.putName(key)
- d.putItemHelper(Item(value, item.iname, i))
+ if forceLong:
+ d.putName("[%s] %s" % (i, key))
+ else:
+ d.putName(key)
+ d.putItem(Item(value, item.iname, i))
else:
- d.putItemHelper(Item(node, item.iname, i))
+ d.putItem(Item(node, item.iname, i))
it = it.dereference()["forward"].dereference()
-def qdump__MultiMap(d, item):
- qdump__Map(d, item)
+def qdump__QMap(d, item):
+ qdumpHelper__QMap(d, item, False)
+
+def qdump__QMultiMap(d, item):
+ qdumpHelper__QMap(d, item, True)
def extractCString(table, offset):
@@ -673,7 +650,15 @@ def extractCString(table, offset):
def qdump__QObject(d, item):
#warn("OBJECT: %s " % item.value)
- staticMetaObject = item.value["staticMetaObject"]
+ try:
+ privateType = lookupType(d.ns + "QObjectPrivate")
+ staticMetaObject = item.value["staticMetaObject"]
+ d_ptr = item.value["d_ptr"]["d"].cast(privateType.pointer()).dereference()
+ #warn("D_PTR: %s " % d_ptr)
+ objectName = d_ptr["objectName"]
+ except:
+ d.putPlainChildren(item)
+ return
#warn("SMO: %s " % staticMetaObject)
#warn("SMO DATA: %s " % staticMetaObject["d"]["stringdata"])
superData = staticMetaObject["d"]["superdata"]
@@ -682,7 +667,6 @@ def qdump__QObject(d, item):
# superData = superData.dereference()["d"]["superdata"]
# warn("SUPERDATA: %s" % superData)
- privateType = lookupType(d.ns + "QObjectPrivate")
if privateType is None:
d.putNumChild(4)
#d.putValue(cleanAddress(item.value.address))
@@ -690,9 +674,6 @@ def qdump__QObject(d, item):
with Children(d):
d.putFields(item)
return
- d_ptr = item.value["d_ptr"]["d"].cast(privateType.pointer()).dereference()
- #warn("D_PTR: %s " % d_ptr)
- objectName = d_ptr["objectName"]
#warn("OBJECTNAME: %s " % objectName)
#warn("D_PTR: %s " % d_ptr)
mo = d_ptr["metaObject"]
@@ -717,8 +698,8 @@ def qdump__QObject(d, item):
d.putFields(item)
# Parent and children.
if stripClassTag(str(item.value.type)) == d.ns + "QObject":
- d.putItem(Item(d_ptr["parent"], item.iname, "parent", "parent"))
- d.putItem(Item(d_ptr["children"], item.iname, "children", "children"))
+ d.putSubItem(Item(d_ptr["parent"], item.iname, "parent", "parent"))
+ d.putSubItem(Item(d_ptr["children"], item.iname, "children", "children"))
# Properties.
with SubItem(d):
@@ -739,7 +720,7 @@ def qdump__QObject(d, item):
namesArray = names["d"]["array"]
dynamicPropertyCount = namesEnd - namesBegin
- #staticPropertyCount = call(mo, "propertyCount()")
+ #staticPropertyCount = call(mo, "propertyCount")
staticPropertyCount = metaData[6]
#warn("PROPERTY COUNT: %s" % staticPropertyCount)
propertyCount = staticPropertyCount + dynamicPropertyCount
@@ -799,8 +780,8 @@ def qdump__QObject(d, item):
# % (d.ns, item.value.address, propertyName)
#exp = '"((\'%sQObject\'*)%s)"' % (d.ns, item.value.address,)
#warn("EXPRESSION: %s" % exp)
- value = call(item.value, 'property(%s)'
- % cleanAddress(metaStringData + metaData[offset]))
+ value = call(item.value, "property",
+ str(cleanAddress(metaStringData + metaData[offset])))
value1 = value["d"]
#warn(" CODE: %s" % value1["type"])
# Type 1 and 2 are bool and int. Try to save a few cycles in this case:
@@ -815,7 +796,7 @@ def qdump__QObject(d, item):
# Build-in types.
d.putType(inner)
name = "%s.properties.%d" % (item.iname, i + dynamicPropertyCount)
- d.putItemHelper(Item(val, item.iname + ".properties",
+ d.putItem(Item(val, item.iname + ".properties",
propertyName, propertyName))
else:
@@ -824,14 +805,14 @@ def qdump__QObject(d, item):
# type = str(call(item.value, func))
# type = type[type.find('"') + 1 : type.rfind('"')]
# type = type.replace("Q", d.ns + "Q") # HACK!
- # data = call(item.value, "constData()")
+ # data = call(item.value, "constData")
# tdata = data.cast(lookupType(type).pointer()).dereference()
# d.putValue("(%s)" % tdata.type)
# d.putType(tdata.type)
# d.putNumChild(1)
# if d.isExpanded(item):
# with Children(d):
- # d.putItem(Item(tdata, item.iname, "data", "data"))
+ # d.putSubItem(Item(tdata, item.iname, "data", "data"))
warn("FIXME: CUSTOM QOBJECT PROPERTIES NOT IMPLEMENTED: %s %s"
% (propertyType, innert))
d.putType(propertyType)
@@ -846,19 +827,19 @@ def qdump__QObject(d, item):
connectionListCount = 0
if not isNull(connections):
connectionListCount = connections["d"]["size"]
- d.putItemCount(connectionListCount)
+ d.putItemCount(connectionListCount, 0)
d.putNumChild(connectionListCount)
if d.isExpandedIName(item.iname + ".connections"):
with Children(d):
vectorType = connections.type.target().fields()[0].type
- innerType = vectorType.template_argument(0)
+ innerType = templateArgument(vectorType, 0)
# Should check: innerType == ns::QObjectPrivate::ConnectionList
p = gdb.Value(connections["p"]["array"]).cast(innerType.pointer())
pp = 0
for i in xrange(connectionListCount):
first = p.dereference()["first"]
while not isNull(first):
- d.putItem(Item(first.dereference(), item.iname + ".connections", pp))
+ d.putSubItem(Item(first.dereference(), item.iname + ".connections", pp))
first = first["next"]
# We need to enforce some upper limit.
pp += 1
@@ -924,7 +905,7 @@ def qdump__QObject(d, item):
if d.isExpandedIName(iname):
with Children(d):
# Sending object
- d.putItem(Item(sender["sender"], iname, "object", "object"))
+ d.putSubItem(Item(sender["sender"], iname, "object", "object"))
# Signal in sending object
with SubItem(d):
d.putName("signal")
@@ -1079,7 +1060,7 @@ def qdump__QObject(d, item):
# with SubItem(d):
# d.putName("parent")
# if isSimpleType(item.value.type):
-# d.putItemHelper(d, ns + "QObject *", ob->parent())
+# d.putItem(d, ns + "QObject *", ob->parent())
# #if 1
# with SubItem(d):
# d.putName("className")
@@ -1259,7 +1240,7 @@ def qdump__QObject(d, item):
# d.putField("addr", owner)
# } else {
# if isSimpleType(item.value.type):
-# d.putItemHelper(ns + "QObject *", partner)
+# d.putItem(ns + "QObject *", partner)
#
# static void dumpQObjectSignal(QDumper &d)
# {
@@ -1464,8 +1445,8 @@ def qdump__QPoint(d, item):
d.putNumChild(2)
if d.isExpanded(item):
with Children(d, 2, x.type.strip_typedefs()):
- d.putItem(Item(x, None, None, "x"))
- d.putItem(Item(y, None, None, "y"))
+ d.putSubItem(Item(x, None, None, "x"))
+ d.putSubItem(Item(y, None, None, "y"))
def qdump__QPointF(d, item):
@@ -1484,10 +1465,10 @@ def qdump__QRect(d, item):
d.putNumChild(4)
if d.isExpanded(item):
with Children(d, 4, x1.type.strip_typedefs()):
- d.putItem(Item(x1, None, None, "x1"))
- d.putItem(Item(y1, None, None, "y1"))
- d.putItem(Item(x2, None, None, "x2"))
- d.putItem(Item(y2, None, None, "y2"))
+ d.putSubItem(Item(x1, None, None, "x1"))
+ d.putSubItem(Item(y1, None, None, "y1"))
+ d.putSubItem(Item(x2, None, None, "x2"))
+ d.putSubItem(Item(y2, None, None, "y2"))
def qdump__QRectF(d, item):
@@ -1505,10 +1486,10 @@ def qdump__QRectF(d, item):
d.putNumChild(4)
if d.isExpanded(item):
with Children(d, 4, x.type.strip_typedefs()):
- d.putItem(Item(x, None, None, "x"))
- d.putItem(Item(y, None, None, "y"))
- d.putItem(Item(w, None, None, "w"))
- d.putItem(Item(h, None, None, "h"))
+ d.putSubItem(Item(x, None, None, "x"))
+ d.putSubItem(Item(y, None, None, "y"))
+ d.putSubItem(Item(w, None, None, "w"))
+ d.putSubItem(Item(h, None, None, "h"))
def qdump__QRegion(d, item):
@@ -1517,19 +1498,24 @@ def qdump__QRegion(d, item):
d.putValue("<empty>")
d.putNumChild(0)
else:
- n = str(p.dereference()["numRects"])
- d.putItemCount(n)
- d.putNumChild(n)
- if d.isExpanded(item):
- with Children(d):
- d.putFields(Item(p.dereference(), item.iname))
+ try:
+ # Fails without debug info.
+ n = str(p.dereference()["numRects"])
+ d.putItemCount(n)
+ d.putNumChild(n)
+ if d.isExpanded(item):
+ with Children(d):
+ d.putFields(Item(p.dereference(), item.iname))
+ except:
+ d.putValue(p)
+ d.putPlainChildren(item)
# qt_rgn might be 0
# gdb.parse_and_eval("region")["d"].dereference()["qt_rgn"].dereference()
def qdump__QScopedPointer(d, item):
d.putType(d.currentType, d.currentTypePriority + 1)
- d.putItemHelper(Item(item.value["d"], item.iname, None, None))
+ d.putItem(Item(item.value["d"], item.iname, None, None))
def qdump__QSet(d, item):
@@ -1561,7 +1547,7 @@ def qdump__QSet(d, item):
bucket += 1
return node
- keyType = item.value.type.template_argument(0)
+ keyType = templateArgument(item.value.type, 0)
d_ptr = item.value["q_hash"]["d"]
e_ptr = item.value["q_hash"]["e"]
@@ -1586,9 +1572,9 @@ def qdump__QSet(d, item):
key = it["key"]
if isSimpleKey:
d.putType(keyType)
- d.putItemHelper(Item(key, None, None))
+ d.putItem(Item(key, None, None))
else:
- d.putItemHelper(Item(key, item.iname, i))
+ d.putItem(Item(key, item.iname, i))
node = hashDataNextNode(node)
@@ -1605,10 +1591,15 @@ def qdump__QSharedDataPointer(d, item):
else:
# This replaces the pointer by the pointee, making the
# pointer transparent.
- innerType = item.value.type.template_argument(0)
+ try:
+ innerType = templateArgument(item.value.type, 0)
+ except:
+ d.putValue(d_ptr)
+ d.putPlainChildren(item)
+ return
value = gdb.Value(d_ptr.cast(innerType.pointer()))
d.putType(d.currentType, d.currentTypePriority + 1)
- d.putItemHelper(Item(value.dereference(), item.iname, None))
+ d.putItem(Item(value.dereference(), item.iname, None))
def qdump__QSharedPointer(d, item):
@@ -1622,8 +1613,8 @@ def qdump__QSize(d, item):
d.putNumChild(2)
if d.isExpanded(item):
with Children(d, 2, w.type):
- d.putItem(Item(w, item.iname, "w", "w"))
- d.putItem(Item(h, item.iname, "h", "h"))
+ d.putSubItem(Item(w, item.iname, "w", "w"))
+ d.putSubItem(Item(h, item.iname, "h", "h"))
def qdump__QSizeF(d, item):
@@ -1636,7 +1627,10 @@ def qdump__QStack(d, item):
def qdump__QStandardItem(d, item):
d.putType(d.currentType, d.currentTypePriority + 1)
- d.putItemHelper(Item(item.value["d_ptr"], item.iname, None, None))
+ try:
+ d.putItem(Item(item.value["d_ptr"], item.iname, None, None))
+ except:
+ d.putPlainChildren(item)
def qform__QString():
@@ -1672,7 +1666,7 @@ def qdump__QStringList(d, item):
ptr += d_ptr["begin"]
with Children(d, [size, 1000], innerType):
for i in d.childRange():
- d.putItem(Item(ptr.dereference(), item.iname, i))
+ d.putSubItem(Item(ptr.dereference(), item.iname, i))
ptr += 1
@@ -1681,13 +1675,13 @@ def qdump__QTemporaryFile(d, item):
def qdump__QTextCodec(d, item):
- value = call(item.value, "name()")
+ value = call(item.value, "name")
d.putValue(encodeByteArray(value), 6)
d.putNumChild(2)
if d.isExpanded(item):
with Children(d):
- d.putCallItem("name", item, "name()")
- d.putCallItem("mibEnum", item, "mibEnum()")
+ d.putCallItem("name", item, "name")
+ d.putCallItem("mibEnum", item, "mibEnum")
def qdump__QTextCursor(d, item):
@@ -1696,14 +1690,18 @@ def qdump__QTextCursor(d, item):
d.putValue("(invalid)")
d.putNumChild(0)
else:
- p = dd.dereference()
- d.putValue(p["position"])
+ try:
+ p = dd.dereference()
+ d.putValue(p["position"])
+ except:
+ d.putPlainChildren(item)
+ return
d.putNumChild(1)
if d.isExpanded(item):
with Children(d):
d.putIntItem("position", p["position"])
d.putIntItem("anchor", p["anchor"])
- d.putCallItem("selected", item, "selectedText()")
+ d.putCallItem("selected", item, "selectedText")
def qdump__QTextDocument(d, item):
@@ -1711,16 +1709,20 @@ def qdump__QTextDocument(d, item):
d.putNumChild(1)
if d.isExpanded(item):
with Children(d):
- d.putCallItem("blockCount", item, "blockCount()")
- d.putCallItem("characterCount", item, "characterCount()")
- d.putCallItem("lineCount", item, "lineCount()")
- d.putCallItem("revision", item, "revision()")
- d.putCallItem("toPlainText", item, "toPlainText()")
+ d.putCallItem("blockCount", item, "blockCount")
+ d.putCallItem("characterCount", item, "characterCount")
+ d.putCallItem("lineCount", item, "lineCount")
+ d.putCallItem("revision", item, "revision")
+ d.putCallItem("toPlainText", item, "toPlainText")
def qdump__QUrl(d, item):
- data = item.value["d"].dereference()
- d.putStringValue(data["encodedOriginal"])
+ try:
+ data = item.value["d"].dereference()
+ d.putStringValue(data["encodedOriginal"])
+ except:
+ d.putPlainChildren(item)
+ return
d.putNumChild(1)
if d.isExpanded(item):
with Children(d):
@@ -1882,24 +1884,31 @@ def qdump__QVariant(d, item):
.cast(innerType.pointer()).dereference()
else:
v = item.value["d"]["data"].cast(innerType)
- d.putItemHelper(Item(v, item.iname))
+ d.putValue(" ", None, -99)
+ d.putItem(Item(v, item.iname))
d.putType("%sQVariant (%s)" % (d.ns, innert), d.currentTypePriority + 1)
return innert
- else:
- # User types.
- d_member = item.value["d"]
- func = "typeToName(('%sQVariant::Type')%d)" % (d.ns, d_member["type"])
- type = str(call(item.value, func))
- type = type[type.find('"') + 1 : type.rfind('"')]
- type = type.replace("Q", d.ns + "Q") # HACK!
- data = call(item.value, "constData()")
- tdata = data.cast(lookupType(type).pointer()).dereference()
- d.putType("%sQVariant (%s)" % (d.ns, tdata.type))
- d.putNumChild(1)
- if d.isExpanded(item):
- with Children(d):
- d.putItem(Item(tdata, item.iname, "data", "data"))
- return tdata.type
+
+ # User types.
+ d_member = item.value["d"]
+ type = str(call(item.value, "typeToName",
+ "('%sQVariant::Type')%d" % (d.ns, d_member["type"])))
+ type = type[type.find('"') + 1 : type.rfind('"')]
+ type = type.replace("Q", d.ns + "Q") # HACK!
+ type = type.replace("uint", "unsigned int") # HACK!
+ type = type.replace("COMMA", ",") # HACK!
+ #warn("TYPE: %s" % type)
+ data = call(item.value, "constData")
+ #warn("DATA: %s" % data)
+ d.putValue(" ", None, -99)
+ d.putType("%sQVariant (%s)" % (d.ns, type))
+ d.putNumChild(1)
+ if d.isExpanded(item):
+ with Children(d):
+ tdata = data.cast(lookupType(type).pointer()).dereference()
+ #warn("TDATA: %s" % tdata)
+ d.putSubItem(Item(tdata, item.iname, "data", "data"))
+ return tdata.type
def qdump__QVector(d, item):
@@ -1911,7 +1920,7 @@ def qdump__QVector(d, item):
check(0 <= size and size <= alloc and alloc <= 1000 * 1000 * 1000)
checkRef(d_ptr["ref"])
- innerType = item.value.type.template_argument(0)
+ innerType = templateArgument(item.value.type, 0)
d.putItemCount(size)
d.putNumChild(size)
if d.isExpanded(item):
@@ -1922,7 +1931,7 @@ def qdump__QVector(d, item):
d.putField("addrstep", (p+1).cast(charPtr) - p.cast(charPtr))
with Children(d, [size, 2000], innerType):
for i in d.childRange():
- d.putItem(Item(p.dereference(), item.iname, i))
+ d.putSubItem(Item(p.dereference(), item.iname, i))
p += 1
@@ -1943,16 +1952,16 @@ def qdump__QWeakPointer(d, item):
check(int(strongref) <= int(weakref))
check(int(weakref) <= 10*1000*1000)
- innerType = item.value.type.template_argument(0)
+ innerType = templateArgument(item.value.type, 0)
if isSimpleType(value.dereference().type):
- d.putItemHelper(Item(value.dereference(), item.iname, None))
+ d.putItem(Item(value.dereference(), item.iname, None))
else:
d.putValue("")
d.putNumChild(3)
if d.isExpanded(item):
with Children(d, 3):
- d.putItem(Item(value.dereference(), item.iname, "data", "data"))
+ d.putSubItem(Item(value.dereference(), item.iname, "data", "data"))
d.putIntItem("weakref", weakref)
d.putIntItem("strongref", strongref)
@@ -1972,7 +1981,7 @@ def qdump__std__deque(d, item):
d.putItemCount(size)
d.putNumChild(size)
if d.isExpanded(item):
- innerType = item.value.type.template_argument(0)
+ innerType = templateArgument(item.value.type, 0)
innerSize = innerType.sizeof
bufsize = select(innerSize < 512, 512 / innerSize, 1)
with Children(d, [size, 2000], innerType):
@@ -1981,7 +1990,7 @@ def qdump__std__deque(d, item):
plast = start["_M_last"]
pnode = start["_M_node"]
for i in d.childRange():
- d.putItem(Item(pcur.dereference(), item.iname, i))
+ d.putSubItem(Item(pcur.dereference(), item.iname, i))
pcur += 1
if pcur == plast:
newnode = pnode + 1
@@ -2001,17 +2010,17 @@ def qdump__std__list(d, item):
size += 1
p = p["_M_next"]
- d.putItemCount(select(size <= 1000, size, "> 1000"))
+ d.putItemCount(size, 1000)
d.putNumChild(size)
if d.isExpanded(item):
p = node["_M_next"]
- innerType = item.value.type.template_argument(0)
+ innerType = templateArgument(item.value.type, 0)
with Children(d, [size, 1000], innerType):
for i in d.childRange():
innerPointer = innerType.pointer()
value = (p + 1).cast(innerPointer).dereference()
- d.putItem(Item(value, item.iname, i))
+ d.putSubItem(Item(value, item.iname, i))
p = p["_M_next"]
@@ -2023,9 +2032,9 @@ def qdump__std__map(d, item):
d.putNumChild(size)
if d.isExpanded(item):
- keyType = item.value.type.template_argument(0)
- valueType = item.value.type.template_argument(1)
- pairType = item.value.type.template_argument(3).template_argument(0)
+ keyType = templateArgument(item.value.type, 0)
+ valueType = templateArgument(item.value.type, 1)
+ pairType = templateArgument(templateArgument(item.value.type, 3), 0)
isSimpleKey = isSimpleType(keyType)
isSimpleValue = isSimpleType(valueType)
innerType = select(isSimpleKey and isSimpleValue, valueType, pairType)
@@ -2039,7 +2048,7 @@ def qdump__std__map(d, item):
with SubItem(d):
if isSimpleKey and isSimpleValue:
d.putName(str(pair["first"]))
- d.putItemHelper(Item(pair["second"], item.iname, i))
+ d.putItem(Item(pair["second"], item.iname, i))
else:
d.putValue(" ")
if d.isExpandedIName("%s.%d" % (item.iname, i)):
@@ -2047,8 +2056,8 @@ def qdump__std__map(d, item):
iname = "%s.%d" % (item.iname, i)
keyItem = Item(pair["first"], iname, "first", "first")
valueItem = Item(pair["second"], iname, "second", "second")
- d.putItem(keyItem)
- d.putItem(valueItem)
+ d.putSubItem(keyItem)
+ d.putSubItem(valueItem)
if isNull(node["_M_right"]):
parent = node["_M_parent"]
@@ -2070,12 +2079,12 @@ def qdump__std__set(d, item):
d.putItemCount(size)
d.putNumChild(size)
if d.isExpanded(item):
- valueType = item.value.type.template_argument(0)
+ valueType = templateArgument(item.value.type, 0)
node = impl["_M_header"]["_M_left"]
with Children(d, [size, 1000], valueType):
for i in d.childRange():
element = (node + 1).cast(valueType.pointer()).dereference()
- d.putItem(Item(element, item.iname, i))
+ d.putSubItem(Item(element, item.iname, i))
if isNull(node["_M_right"]):
parent = node["_M_parent"]
@@ -2107,7 +2116,7 @@ def qdump__std__string(d, item):
elif str(baseType) == 'std::wstring':
charType = lookupType("wchar_t")
else:
- charType = baseType.template_argument(0)
+ charType = templateArgument(baseType, 0)
repType = lookupType("%s::_Rep" % baseType).pointer()
rep = (data.cast(repType) - 1).dereference()
size = rep['_M_length']
@@ -2153,7 +2162,7 @@ def qdump__std__string(d, item):
def qdump__std__vector(d, item):
impl = item.value["_M_impl"]
- type = item.value.type.template_argument(0)
+ type = templateArgument(item.value.type, 0)
alloc = impl["_M_end_of_storage"]
isBool = str(type) == 'bool'
if isBool:
@@ -2188,7 +2197,7 @@ def qdump__std__vector(d, item):
with Children(d, [size, 10000], type):
p = start
for i in d.childRange():
- d.putItem(Item(p.dereference(), item.iname, i))
+ d.putSubItem(Item(p.dereference(), item.iname, i))
p += 1
@@ -2211,7 +2220,7 @@ def qdump____gnu_cxx__hash_set(d, item):
check(0 <= size and size <= 1000 * 1000 * 1000)
d.putItemCount(size)
d.putNumChild(size)
- type = item.value.type.template_argument(0)
+ type = templateArgument(item.value.type, 0)
d.putType("__gnu__cxx::hash_set<%s>" % type)
if d.isExpanded(item):
with Children(d, [size, 1000], type):
@@ -2243,13 +2252,13 @@ def qdump__boost__optional(d, item):
d.putNumChild(0)
else:
d.putType(item.value.type, d.currentTypePriority + 1)
- type = item.value.type.template_argument(0)
+ type = templateArgument(item.value.type, 0)
storage = item.value["m_storage"]
if type.code == gdb.TYPE_CODE_REF:
value = storage.cast(type.target().pointer()).dereference()
else:
value = storage.cast(type)
- d.putItemHelper(Item(value, item.iname))
+ d.putItem(Item(value, item.iname))
#######################################################################
@@ -2287,6 +2296,33 @@ def qdump__TLitC(d, item):
#######################################################################
#
+# SSE
+#
+#######################################################################
+
+def qform____m128():
+ return "As Floats,As Doubles"
+
+def qdump____m128(d, item):
+ d.putValue(" ")
+ d.putNumChild(1)
+ if d.isExpanded(item):
+ format = d.itemFormat(item)
+ if format == 2: # As Double
+ innerType = lookupType("double")
+ count = 2
+ else: # Default, As float
+ innerType = lookupType("float")
+ count = 4
+ p = item.value.address.cast(innerType.pointer())
+ with Children(d, count, innerType):
+ for i in xrange(count):
+ d.putSubItem(Item(p.dereference(), item.iname))
+ p += 1
+
+
+#######################################################################
+#
# Display Test
#
#######################################################################
@@ -2299,10 +2335,10 @@ if False:
d.putValue("(%s, %s, %s; %s)" % (v["r"], v["g"], v["b"], v["a"]))
if d.isExpanded(item):
with Children(d):
- d.putItem(Item(v["r"], item.iname, "0", "r"))
- d.putItem(Item(v["g"], item.iname, "1", "g"))
- d.putItem(Item(v["b"], item.iname, "2", "b"))
- d.putItem(Item(v["a"], item.iname, "3", "a"))
+ d.putSubItem(Item(v["r"], item.iname, "0", "r"))
+ d.putSubItem(Item(v["g"], item.iname, "1", "g"))
+ d.putSubItem(Item(v["b"], item.iname, "2", "b"))
+ d.putSubItem(Item(v["a"], item.iname, "3", "a"))
def qdump__Color_(d, item):
v = item.value
@@ -2311,16 +2347,16 @@ if False:
with Children(d):
with SubItem(d):
d.putField("iname", item.iname + ".0")
- d.putItemHelper(Item(v["r"], item.iname, "0", "r"))
+ d.putItem(Item(v["r"], item.iname, "0", "r"))
with SubItem(d):
d.putField("iname", item.iname + ".1")
- d.putItemHelper(Item(v["g"], item.iname, "1", "g"))
+ d.putItem(Item(v["g"], item.iname, "1", "g"))
with SubItem(d):
d.putField("iname", item.iname + ".2")
- d.putItemHelper(Item(v["b"], item.iname, "2", "b"))
+ d.putItem(Item(v["b"], item.iname, "2", "b"))
with SubItem(d):
d.putField("iname", item.iname + ".3")
- d.putItemHelper(Item(v["a"], item.iname, "3", "a"))
+ d.putItem(Item(v["a"], item.iname, "3", "a"))
def qdump__Function(d, item):
diff --git a/share/qtcreator/glsl/glsl_120.frag b/share/qtcreator/glsl/glsl_120.frag
new file mode 100644
index 0000000000..2e78e382bf
--- /dev/null
+++ b/share/qtcreator/glsl/glsl_120.frag
@@ -0,0 +1,56 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+// Fragment shader special variables.
+vec4 gl_FragCoord;
+bool gl_FrontFacing;
+vec4 gl_FragColor;
+vec4 gl_FragData[gl_MaxDrawBuffers];
+float gl_FragDepth;
+
+// Varying variables.
+varying vec4 gl_Color;
+varying vec4 gl_SecondaryColor;
+varying vec4 gl_TexCoord[];
+varying float gl_FogFragCoord;
+varying vec2 gl_PointCoord;
+
+// Fragment processing functions.
+float dFdx(float p);
+vec2 dFdx(vec2 p);
+vec3 dFdx(vec3 p);
+vec4 dFdx(vec4 p);
+float dFdy(float p);
+vec2 dFdy(vec2 p);
+vec3 dFdy(vec3 p);
+vec4 dFdy(vec4 p);
+float fwidth(float p);
+vec2 fwidth(vec2 p);
+vec3 fwidth(vec3 p);
+vec4 fwidth(vec4 p);
diff --git a/share/qtcreator/glsl/glsl_120.vert b/share/qtcreator/glsl/glsl_120.vert
new file mode 100644
index 0000000000..af8d4d8378
--- /dev/null
+++ b/share/qtcreator/glsl/glsl_120.vert
@@ -0,0 +1,74 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+// Vertex shader special variables.
+vec4 gl_Position;
+float gl_PointSize;
+vec4 gl_ClipVertex;
+
+// Vertex shader built-in attributes.
+attribute vec4 gl_Color;
+attribute vec4 gl_SecondaryColor;
+attribute vec3 gl_Normal;
+attribute vec4 gl_Vertex;
+attribute vec4 gl_MultiTexCoord0;
+attribute vec4 gl_MultiTexCoord1;
+attribute vec4 gl_MultiTexCoord2;
+attribute vec4 gl_MultiTexCoord3;
+attribute vec4 gl_MultiTexCoord4;
+attribute vec4 gl_MultiTexCoord5;
+attribute vec4 gl_MultiTexCoord6;
+attribute vec4 gl_MultiTexCoord7;
+attribute float gl_FogCoord;
+
+// Varying variables.
+varying vec4 gl_FrontColor;
+varying vec4 gl_BackColor;
+varying vec4 gl_FrontSecondaryColor;
+varying vec4 gl_BackSecondaryColor;
+varying vec4 gl_TexCoord[];
+varying float gl_FogFragCoord;
+
+// Common functions.
+vec4 ftransform();
+
+// Texture level-of-detail functions.
+vec4 texture1DLod(sampler1D sampler, float coord, float lod);
+vec4 texture1DProjLod(sampler1D sampler, vec2 coord, float lod);
+vec4 texture1DProjLod(sampler1D sampler, vec4 coord, float lod);
+vec4 texture2DLod(sampler2D sampler, vec2 coord, float lod);
+vec4 texture2DProjLod(sampler2D sampler, vec3 coord, float lod);
+vec4 texture2DProjLod(sampler2D sampler, vec4 coord, float lod);
+vec4 texture3DLod(sampler3D sampler, vec3 coord, float lod);
+vec4 texture3DProjLod(sampler3D sampler, vec4 coord, float lod);
+vec4 textureCubeLod(samplerCube sampler, vec3 coord, float lod);
+vec4 shadow1DLod(sampler1DShadow sampler, vec3 coord, float lod);
+vec4 shadow2DLod(sampler2DShadow sampler, vec3 coord, float lod);
+vec4 shadow1DProjLod(sampler1DShadow sampler, vec4 coord, float lod);
+vec4 shadow2DProjLod(sampler2DShadow sampler, vec4 coord, float lod);
diff --git a/share/qtcreator/glsl/glsl_120_common.glsl b/share/qtcreator/glsl/glsl_120_common.glsl
new file mode 100644
index 0000000000..6ed3791a13
--- /dev/null
+++ b/share/qtcreator/glsl/glsl_120_common.glsl
@@ -0,0 +1,459 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+// Built-in constants.
+const int gl_MaxLights = 8;
+const int gl_MaxClipPlanes = 6;
+const int gl_MaxTextureUnits = 2;
+const int gl_MaxTextureCoords = 2;
+const int gl_MaxVertexAttribs = 16;
+const int gl_MaxVertexUniformComponents = 512;
+const int gl_MaxVaryingFloats = 32;
+const int gl_MaxVertexTextureImageUnits = 0;
+const int gl_MaxCombinedTextureImageUnits = 2;
+const int gl_MaxTextureImageUnits = 2;
+const int gl_MaxFragmentUniformComponents = 64;
+const int gl_MaxDrawBuffers = 1;
+
+// Built-in uniform state.
+uniform mat4 gl_ModelViewMatrix;
+uniform mat4 gl_ProjectionMatrix;
+uniform mat4 gl_ModelViewProjectionMatrix;
+uniform mat4 gl_TextureMatrix[gl_MaxTextureCoords];
+uniform mat3 gl_NormalMatrix;
+
+uniform mat4 gl_ModelViewMatrixInverse;
+uniform mat4 gl_ProjectionMatrixInverse;
+uniform mat4 gl_ModelViewProjectionMatrixInverse;
+uniform mat4 gl_TextureMatrixInverse[gl_MaxTextureCoords];
+
+uniform mat4 gl_ModelViewMatrixTranspose;
+uniform mat4 gl_ProjectionMatrixTranspose;
+uniform mat4 gl_ModelViewProjectionMatrixTranspose;
+uniform mat4 gl_TextureMatrixTranspose[gl_MaxTextureCoords];
+
+uniform mat4 gl_ModelViewMatrixInverseTranspose;
+uniform mat4 gl_ProjectionMatrixInverseTranspose;
+uniform mat4 gl_ModelViewProjectionMatrixInverseTranspose;
+uniform mat4 gl_TextureMatrixInverseTranspose[gl_MaxTextureCoords];
+
+uniform float gl_NormalScale;
+
+struct gl_DepthRangeParameters {
+ float near;
+ float far;
+ float diff;
+};
+uniform gl_DepthRangeParameters gl_DepthRange;
+
+uniform vec4 gl_ClipPlane[gl_MaxClipPlanes];
+
+struct gl_PointParameters {
+ float size;
+ float sizeMin;
+ float sizeMax;
+ float fadeThresholdSize;
+ float distanceConstantAttenuation;
+ float distanceLinearAttenuation;
+ float distanceQuadraticAttenuation;
+};
+uniform gl_PointParameters gl_Point;
+
+struct gl_MaterialParameters {
+ vec4 emission;
+ vec4 ambient;
+ vec4 diffuse;
+ vec4 specular;
+ float shininess;
+};
+uniform gl_MaterialParameters gl_FrontMaterial;
+uniform gl_MaterialParameters gl_BackMaterial;
+
+struct gl_LightSourceParameters {
+ vec4 ambient;
+ vec4 diffuse;
+ vec4 specular;
+ vec4 position;
+ vec4 halfVector;
+ vec3 spotDirection;
+ float spotExponent;
+ float spotCutoff;
+ float spotCosCutoff;
+ float constantAttenuation;
+ float linearAttenuation;
+ float quadraticAttenuation;
+};
+uniform gl_LightSourceParameters gl_LightSource[gl_MaxLights];
+
+struct gl_LightModelParameters {
+ vec4 ambient;
+};
+uniform gl_LightModelParameters gl_LightModel;
+
+struct gl_LightModelProducts {
+ vec4 sceneColor;
+};
+uniform gl_LightModelProducts gl_FrontLightModelProduct;
+uniform gl_LightModelProducts gl_BackLightModelProduct;
+
+struct gl_LightProducts {
+ vec4 ambient;
+ vec4 diffuse;
+ vec4 specular;
+};
+uniform gl_LightProducts gl_FrontLightProduct[gl_MaxLights];
+uniform gl_LightProducts gl_BackLightProduct[gl_MaxLights];
+
+uniform vec4 gl_TextureEnvColor[gl_MaxTextureUnits];
+uniform vec4 gl_EyePlaneS[gl_MaxTextureUnits];
+uniform vec4 gl_EyePlaneT[gl_MaxTextureUnits];
+uniform vec4 gl_EyePlaneR[gl_MaxTextureUnits];
+uniform vec4 gl_EyePlaneQ[gl_MaxTextureUnits];
+uniform vec4 gl_ObjectPlaneS[gl_MaxTextureUnits];
+uniform vec4 gl_ObjectPlaneT[gl_MaxTextureUnits];
+uniform vec4 gl_ObjectPlaneR[gl_MaxTextureUnits];
+uniform vec4 gl_ObjectPlaneQ[gl_MaxTextureUnits];
+
+struct gl_FogParameters {
+ vec4 color;
+ float density;
+ float start;
+ float end;
+ float scale;
+};
+uniform gl_FogParameters gl_Fog;
+
+// Angle and trigonometry functions.
+float radians(float degress);
+vec2 radians(vec2 degress);
+vec3 radians(vec3 degress);
+vec4 radians(vec4 degress);
+float degrees(float radians);
+vec2 degrees(vec2 radians);
+vec3 degrees(vec3 radians);
+vec4 degrees(vec4 radians);
+float sin(float angle);
+vec2 sin(vec2 angle);
+vec3 sin(vec3 angle);
+vec4 sin(vec4 angle);
+float cos(float angle);
+vec2 cos(vec2 angle);
+vec3 cos(vec3 angle);
+vec4 cos(vec4 angle);
+float tan(float angle);
+vec2 tan(vec2 angle);
+vec3 tan(vec3 angle);
+vec4 tan(vec4 angle);
+float asin(float x);
+vec2 asin(vec2 x);
+vec3 asin(vec3 x);
+vec4 asin(vec4 x);
+float acos(float x);
+vec2 acos(vec2 x);
+vec3 acos(vec3 x);
+vec4 acos(vec4 x);
+float atan(float y, float x);
+vec2 atan(vec2 y, vec2 x);
+vec3 atan(vec3 y, vec3 x);
+vec4 atan(vec4 y, vec4 x);
+float atan(float y_over_x);
+vec2 atan(vec2 y_over_x);
+vec3 atan(vec3 y_over_x);
+vec4 atan(vec4 y_over_x);
+
+// Exponential functions.
+float pow(float x, float y);
+vec2 pow(vec2 x, vec2 y);
+vec3 pow(vec3 x, vec3 y);
+vec4 pow(vec4 x, vec4 y);
+float exp(float x);
+vec2 exp(vec2 x);
+vec3 exp(vec3 x);
+vec4 exp(vec4 x);
+float log(float x);
+vec2 log(vec2 x);
+vec3 log(vec3 x);
+vec4 log(vec4 x);
+float exp2(float x);
+vec2 exp2(vec2 x);
+vec3 exp2(vec3 x);
+vec4 exp2(vec4 x);
+float log2(float x);
+vec2 log2(vec2 x);
+vec3 log2(vec3 x);
+vec4 log2(vec4 x);
+float sqrt(float x);
+vec2 sqrt(vec2 x);
+vec3 sqrt(vec3 x);
+vec4 sqrt(vec4 x);
+float inversesqrt(float x);
+vec2 inversesqrt(vec2 x);
+vec3 inversesqrt(vec3 x);
+vec4 inversesqrt(vec4 x);
+
+// Common functions.
+float abs(float x);
+vec2 abs(vec2 x);
+vec3 abs(vec3 x);
+vec4 abs(vec4 x);
+float sign(float x);
+vec2 sign(vec2 x);
+vec3 sign(vec3 x);
+vec4 sign(vec4 x);
+float floor(float x);
+vec2 floor(vec2 x);
+vec3 floor(vec3 x);
+vec4 floor(vec4 x);
+float ceil(float x);
+vec2 ceil(vec2 x);
+vec3 ceil(vec3 x);
+vec4 ceil(vec4 x);
+float fract(float x);
+vec2 fract(vec2 x);
+vec3 fract(vec3 x);
+vec4 fract(vec4 x);
+float mod(float x, float y);
+vec2 mod(vec2 x, float y);
+vec3 mod(vec3 x, float y);
+vec4 mod(vec4 x, float y);
+float mod(float x, float y);
+vec2 mod(vec2 x, vec2 y);
+vec3 mod(vec3 x, vec3 y);
+vec4 mod(vec4 x, vec4 y);
+float min(float x, float y);
+vec2 min(vec2 x, float y);
+vec3 min(vec3 x, float y);
+vec4 min(vec4 x, float y);
+float min(float x, float y);
+vec2 min(vec2 x, vec2 y);
+vec3 min(vec3 x, vec3 y);
+vec4 min(vec4 x, vec4 y);
+float max(float x, float y);
+vec2 max(vec2 x, float y);
+vec3 max(vec3 x, float y);
+vec4 max(vec4 x, float y);
+float max(float x, float y);
+vec2 max(vec2 x, vec2 y);
+vec3 max(vec3 x, vec3 y);
+vec4 max(vec4 x, vec4 y);
+float clamp(float x, float minVal, float maxVal);
+vec2 clamp(vec2 x, vec2 minVal, vec2 maxVal);
+vec3 clamp(vec3 x, vec3 minVal, vec3 maxVal);
+vec4 clamp(vec4 x, vec4 minVal, vec4 maxVal);
+float clamp(float x, float minVal, float maxVal);
+vec2 clamp(vec2 x, float minVal, float maxVal);
+vec3 clamp(vec3 x, float minVal, float maxVal);
+vec4 clamp(vec4 x, float minVal, float maxVal);
+float mix(float x, float y, float a);
+vec2 mix(vec2 x, vec2 y, vec2 a);
+vec3 mix(vec3 x, vec3 y, vec3 a);
+vec4 mix(vec4 x, vec4 y, vec4 a);
+float mix(float x, float y, float a);
+vec2 mix(vec2 x, vec2 y, float a);
+vec3 mix(vec3 x, vec3 y, float a);
+vec4 mix(vec4 x, vec4 y, float a);
+float step(float edge, float x);
+vec2 step(vec2 edge, vec2 x);
+vec3 step(vec3 edge, vec3 x);
+vec4 step(vec4 edge, vec4 x);
+float step(float edge, float x);
+vec2 step(float edge, vec2 x);
+vec3 step(float edge, vec3 x);
+vec4 step(float edge, vec4 x);
+float smoothstep(float edge0, float edge1, float x);
+vec2 smoothstep(vec2 edge0, vec2 edge1, vec2 x);
+vec3 smoothstep(vec3 edge0, vec3 edge1, vec3 x);
+vec4 smoothstep(vec4 edge0, vec4 edge1, vec4 x);
+float smoothstep(float edge0, float edge1, float x);
+vec2 smoothstep(float edge0, float edge1, vec2 x);
+vec3 smoothstep(float edge0, float edge1, vec3 x);
+vec4 smoothstep(float edge0, float edge1, vec4 x);
+
+// Geometric functions.
+float length(float x);
+float length(vec2 x);
+float length(vec3 x);
+float length(vec4 x);
+float distance(float p0, float p1);
+float distance(vec2 p0, vec2 p1);
+float distance(vec3 p0, vec3 p1);
+float distance(vec4 p0, vec4 p1);
+float dot(float x, float y);
+float dot(vec2 x, vec2 y);
+float dot(vec3 x, vec3 y);
+float dot(vec4 x, vec4 y);
+vec3 cross(vec3 x, vec3 y);
+float normalize(float x);
+vec2 normalize(vec2 x);
+vec3 normalize(vec3 x);
+vec4 normalize(vec4 x);
+float faceforward(float N, float I, float Nref);
+vec2 faceforward(vec2 N, vec2 I, vec2 Nref);
+vec3 faceforward(vec3 N, vec3 I, vec3 Nref);
+vec4 faceforward(vec4 N, vec4 I, vec4 Nref);
+float reflect(float I, float N);
+vec2 reflect(vec2 I, vec2 N);
+vec3 reflect(vec3 I, vec3 N);
+vec4 reflect(vec4 I, vec4 N);
+float refract(float I, float N, float eta);
+vec2 refract(vec2 I, vec2 N, float eta);
+vec3 refract(vec3 I, vec3 N, float eta);
+vec4 refract(vec4 I, vec4 N, float eta);
+
+// Matrix functions.
+mat2 matrixCompMult(mat2 x, mat2 y);
+mat3 matrixCompMult(mat3 x, mat3 y);
+mat4 matrixCompMult(mat4 x, mat4 y);
+mat2x4 matrixCompMult(mat2x4 x, mat2x4 y);
+mat4x2 matrixCompMult(mat4x2 x, mat4x2 y);
+mat2x3 matrixCompMult(mat2x3 x, mat2x3 y);
+mat3x2 matrixCompMult(mat3x2 x, mat3x2 y);
+mat3x4 matrixCompMult(mat3x4 x, mat3x4 y);
+mat4x3 matrixCompMult(mat4x3 x, mat4x3 y);
+mat2 outerProduct(vec2 c, vec2 r);
+mat3 outerProduct(vec3 c, vec3 r);
+mat4 outerProduct(vec4 c, vec4 r);
+mat2x3 outerProduct(vec3 c, vec2 r);
+mat3x2 outerProduct(vec2 c, vec3 r);
+mat2x4 outerProduct(vec4 c, vec2 r);
+mat4x2 outerProduct(vec2 c, vec4 r);
+mat3x4 outerProduct(vec4 c, vec3 r);
+mat4x3 outerProduct(vec3 c, vec4 r);
+mat2 transpose(mat2 m);
+mat3 transpose(mat3 m);
+mat4 transpose(mat4 m);
+mat2x3 transpose(mat3x2 m);
+mat3x2 transpose(mat2x3 m);
+mat2x4 transpose(mat4x2 m);
+mat4x2 transpose(mat2x4 m);
+mat3x4 transpose(mat4x3 m);
+mat4x3 transpose(mat3x4 m);
+
+// Vector relational functions.
+bvec2 lessThan(vec2 x, vec2 y);
+bvec2 lessThan(ivec2 x, ivec2 y);
+bvec3 lessThan(vec3 x, vec3 y);
+bvec3 lessThan(ivec3 x, ivec3 y);
+bvec4 lessThan(vec4 x, vec4 y);
+bvec4 lessThan(ivec4 x, ivec4 y);
+bvec2 lessThanEqual(vec2 x, vec2 y);
+bvec2 lessThanEqual(ivec2 x, ivec2 y);
+bvec3 lessThanEqual(vec3 x, vec3 y);
+bvec3 lessThanEqual(ivec3 x, ivec3 y);
+bvec4 lessThanEqual(vec4 x, vec4 y);
+bvec4 lessThanEqual(ivec4 x, ivec4 y);
+bvec2 greaterThan(vec2 x, vec2 y);
+bvec2 greaterThan(ivec2 x, ivec2 y);
+bvec3 greaterThan(vec3 x, vec3 y);
+bvec3 greaterThan(ivec3 x, ivec3 y);
+bvec4 greaterThan(vec4 x, vec4 y);
+bvec4 greaterThan(ivec4 x, ivec4 y);
+bvec2 greaterThanEqual(vec2 x, vec2 y);
+bvec2 greaterThanEqual(ivec2 x, ivec2 y);
+bvec3 greaterThanEqual(vec3 x, vec3 y);
+bvec3 greaterThanEqual(ivec3 x, ivec3 y);
+bvec4 greaterThanEqual(vec4 x, vec4 y);
+bvec4 greaterThanEqual(ivec4 x, ivec4 y);
+bvec2 equal(vec2 x, vec2 y);
+bvec2 equal(ivec2 x, ivec2 y);
+bvec2 equal(bvec2 x, bvec2 y);
+bvec3 equal(vec3 x, vec3 y);
+bvec3 equal(ivec3 x, ivec3 y);
+bvec3 equal(bvec3 x, bvec3 y);
+bvec4 equal(vec4 x, vec4 y);
+bvec4 equal(ivec4 x, ivec4 y);
+bvec4 equal(bvec4 x, bvec4 y);
+bvec2 notEqual(vec2 x, vec2 y);
+bvec2 notEqual(ivec2 x, ivec2 y);
+bvec2 notEqual(bvec2 x, bvec2 y);
+bvec3 notEqual(vec3 x, vec3 y);
+bvec3 notEqual(ivec3 x, ivec3 y);
+bvec3 notEqual(bvec3 x, bvec3 y);
+bvec4 notEqual(vec4 x, vec4 y);
+bvec4 notEqual(ivec4 x, ivec4 y);
+bvec4 notEqual(bvec4 x, bvec4 y);
+bool any(bvec2 x);
+bool any(bvec3 x);
+bool any(bvec4 x);
+bool all(bvec2 x);
+bool all(bvec3 x);
+bool all(bvec4 x);
+bvec2 not(bvec2 x);
+bvec3 not(bvec3 x);
+bvec4 not(bvec4 x);
+
+// Texture lookup functions.
+vec4 texture1D(sampler1D sampler, float coord);
+vec4 texture1D(sampler1D sampler, float coord, float bias);
+vec4 texture1DProj(sampler1D sampler, vec2 coord);
+vec4 texture1DProj(sampler1D sampler, vec2 coord, float bias);
+vec4 texture1DProj(sampler1D sampler, vec4 coord);
+vec4 texture1DProj(sampler1D sampler, vec4 coord, float bias);
+
+vec4 texture2D(sampler2D sampler, vec2 coord);
+vec4 texture2D(sampler2D sampler, vec2 coord, float bias);
+vec4 texture2DProj(sampler2D sampler, vec3 coord);
+vec4 texture2DProj(sampler2D sampler, vec3 coord, float bias);
+vec4 texture2DProj(sampler2D sampler, vec4 coord);
+vec4 texture2DProj(sampler2D sampler, vec4 coord, float bias);
+
+vec4 texture3D(sampler3D sampler, vec3 coord);
+vec4 texture3D(sampler3D sampler, vec3 coord, float bias);
+vec4 texture3DProj(sampler3D sampler, vec4 coord);
+vec4 texture3DProj(sampler3D sampler, vec4 coord, float bias);
+
+vec4 textureCube(samplerCube sampler, vec3 coord);
+vec4 textureCube(samplerCube sampler, vec3 coord, float bias);
+
+vec4 shadow1D(sampler1DShadow sampler, vec3 coord);
+vec4 shadow1D(sampler1DShadow sampler, vec3 coord, float bias);
+vec4 shadow2D(sampler2DShadow sampler, vec3 coord);
+vec4 shadow2D(sampler2DShadow sampler, vec3 coord, float bias);
+vec4 shadow1DProj(sampler1DShadow sampler, vec4 coord);
+vec4 shadow1DProj(sampler1DShadow sampler, vec4 coord, float bias);
+vec4 shadow2DProj(sampler2DShadow sampler, vec4 coord);
+vec4 shadow2DProj(sampler2DShadow sampler, vec4 coord, float bias);
+
+// Noise functions.
+float noise1(float x);
+float noise1(vec2 x);
+float noise1(vec3 x);
+float noise1(vec4 x);
+vec2 noise2(float x);
+vec2 noise2(vec2 x);
+vec2 noise2(vec3 x);
+vec2 noise2(vec4 x);
+vec3 noise3(float x);
+vec3 noise3(vec2 x);
+vec3 noise3(vec3 x);
+vec3 noise3(vec4 x);
+vec4 noise4(float x);
+vec4 noise4(vec2 x);
+vec4 noise4(vec3 x);
+vec4 noise4(vec4 x);
diff --git a/share/qtcreator/glsl/glsl_es_100.frag b/share/qtcreator/glsl/glsl_es_100.frag
new file mode 100644
index 0000000000..c2453ed5d2
--- /dev/null
+++ b/share/qtcreator/glsl/glsl_es_100.frag
@@ -0,0 +1,35 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+// Fragment shader special variables.
+mediump vec4 gl_FragCoord;
+ bool gl_FrontFacing;
+mediump vec4 gl_FragColor;
+mediump vec4 gl_FragData[gl_MaxDrawBuffers];
+mediump vec2 gl_PointCoord;
diff --git a/share/qtcreator/glsl/glsl_es_100.vert b/share/qtcreator/glsl/glsl_es_100.vert
new file mode 100644
index 0000000000..9bbc18c3b7
--- /dev/null
+++ b/share/qtcreator/glsl/glsl_es_100.vert
@@ -0,0 +1,38 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+// Vertex shader special variables.
+highp vec4 gl_Position;
+mediump float gl_PointSize;
+
+// Texture level-of-detail functions.
+vec4 texture2DLod(sampler2D sampler, vec2 coord, float lod);
+vec4 texture2DProjLod(sampler2D sampler, vec3 coord, float lod);
+vec4 texture2DProjLod(sampler2D sampler, vec4 coord, float lod);
+vec4 textureCubeLod(samplerCube sampler, vec3 coord, float lod);
diff --git a/share/qtcreator/glsl/glsl_es_100_common.glsl b/share/qtcreator/glsl/glsl_es_100_common.glsl
new file mode 100644
index 0000000000..6c2054d8cf
--- /dev/null
+++ b/share/qtcreator/glsl/glsl_es_100_common.glsl
@@ -0,0 +1,292 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+// Built-in constants.
+const mediump int gl_MaxVertexAttribs = 8;
+const mediump int gl_MaxVertexUniformVectors = 128;
+const mediump int gl_MaxVaryingVectors = 8;
+const mediump int gl_MaxVertexTextureImageUnits = 0;
+const mediump int gl_MaxCombinedTextureImageUnits = 8;
+const mediump int gl_MaxTextureImageUnits = 8;
+const mediump int gl_MaxFragmentUniformVectors = 16;
+const mediump int gl_MaxDrawBuffers = 1;
+
+// Built-in uniform state.
+struct gl_DepthRangeParameters {
+ highp float near;
+ highp float far;
+ highp float diff;
+};
+uniform gl_DepthRangeParameters gl_DepthRange;
+
+// Angle and trigonometry functions.
+float radians(float degress);
+vec2 radians(vec2 degress);
+vec3 radians(vec3 degress);
+vec4 radians(vec4 degress);
+float degrees(float radians);
+vec2 degrees(vec2 radians);
+vec3 degrees(vec3 radians);
+vec4 degrees(vec4 radians);
+float sin(float angle);
+vec2 sin(vec2 angle);
+vec3 sin(vec3 angle);
+vec4 sin(vec4 angle);
+float cos(float angle);
+vec2 cos(vec2 angle);
+vec3 cos(vec3 angle);
+vec4 cos(vec4 angle);
+float tan(float angle);
+vec2 tan(vec2 angle);
+vec3 tan(vec3 angle);
+vec4 tan(vec4 angle);
+float asin(float x);
+vec2 asin(vec2 x);
+vec3 asin(vec3 x);
+vec4 asin(vec4 x);
+float acos(float x);
+vec2 acos(vec2 x);
+vec3 acos(vec3 x);
+vec4 acos(vec4 x);
+float atan(float y, float x);
+vec2 atan(vec2 y, vec2 x);
+vec3 atan(vec3 y, vec3 x);
+vec4 atan(vec4 y, vec4 x);
+float atan(float y_over_x);
+vec2 atan(vec2 y_over_x);
+vec3 atan(vec3 y_over_x);
+vec4 atan(vec4 y_over_x);
+
+// Exponential functions.
+float pow(float x, float y);
+vec2 pow(vec2 x, vec2 y);
+vec3 pow(vec3 x, vec3 y);
+vec4 pow(vec4 x, vec4 y);
+float exp(float x);
+vec2 exp(vec2 x);
+vec3 exp(vec3 x);
+vec4 exp(vec4 x);
+float log(float x);
+vec2 log(vec2 x);
+vec3 log(vec3 x);
+vec4 log(vec4 x);
+float exp2(float x);
+vec2 exp2(vec2 x);
+vec3 exp2(vec3 x);
+vec4 exp2(vec4 x);
+float log2(float x);
+vec2 log2(vec2 x);
+vec3 log2(vec3 x);
+vec4 log2(vec4 x);
+float sqrt(float x);
+vec2 sqrt(vec2 x);
+vec3 sqrt(vec3 x);
+vec4 sqrt(vec4 x);
+float inversesqrt(float x);
+vec2 inversesqrt(vec2 x);
+vec3 inversesqrt(vec3 x);
+vec4 inversesqrt(vec4 x);
+
+// Common functions.
+float abs(float x);
+vec2 abs(vec2 x);
+vec3 abs(vec3 x);
+vec4 abs(vec4 x);
+float sign(float x);
+vec2 sign(vec2 x);
+vec3 sign(vec3 x);
+vec4 sign(vec4 x);
+float floor(float x);
+vec2 floor(vec2 x);
+vec3 floor(vec3 x);
+vec4 floor(vec4 x);
+float ceil(float x);
+vec2 ceil(vec2 x);
+vec3 ceil(vec3 x);
+vec4 ceil(vec4 x);
+float fract(float x);
+vec2 fract(vec2 x);
+vec3 fract(vec3 x);
+vec4 fract(vec4 x);
+float mod(float x, float y);
+vec2 mod(vec2 x, float y);
+vec3 mod(vec3 x, float y);
+vec4 mod(vec4 x, float y);
+float mod(float x, float y);
+vec2 mod(vec2 x, vec2 y);
+vec3 mod(vec3 x, vec3 y);
+vec4 mod(vec4 x, vec4 y);
+float min(float x, float y);
+vec2 min(vec2 x, float y);
+vec3 min(vec3 x, float y);
+vec4 min(vec4 x, float y);
+float min(float x, float y);
+vec2 min(vec2 x, vec2 y);
+vec3 min(vec3 x, vec3 y);
+vec4 min(vec4 x, vec4 y);
+float max(float x, float y);
+vec2 max(vec2 x, float y);
+vec3 max(vec3 x, float y);
+vec4 max(vec4 x, float y);
+float max(float x, float y);
+vec2 max(vec2 x, vec2 y);
+vec3 max(vec3 x, vec3 y);
+vec4 max(vec4 x, vec4 y);
+float clamp(float x, float minVal, float maxVal);
+vec2 clamp(vec2 x, vec2 minVal, vec2 maxVal);
+vec3 clamp(vec3 x, vec3 minVal, vec3 maxVal);
+vec4 clamp(vec4 x, vec4 minVal, vec4 maxVal);
+float clamp(float x, float minVal, float maxVal);
+vec2 clamp(vec2 x, float minVal, float maxVal);
+vec3 clamp(vec3 x, float minVal, float maxVal);
+vec4 clamp(vec4 x, float minVal, float maxVal);
+float mix(float x, float y, float a);
+vec2 mix(vec2 x, vec2 y, vec2 a);
+vec3 mix(vec3 x, vec3 y, vec3 a);
+vec4 mix(vec4 x, vec4 y, vec4 a);
+float mix(float x, float y, float a);
+vec2 mix(vec2 x, vec2 y, float a);
+vec3 mix(vec3 x, vec3 y, float a);
+vec4 mix(vec4 x, vec4 y, float a);
+float step(float edge, float x);
+vec2 step(vec2 edge, vec2 x);
+vec3 step(vec3 edge, vec3 x);
+vec4 step(vec4 edge, vec4 x);
+float step(float edge, float x);
+vec2 step(float edge, vec2 x);
+vec3 step(float edge, vec3 x);
+vec4 step(float edge, vec4 x);
+float smoothstep(float edge0, float edge1, float x);
+vec2 smoothstep(vec2 edge0, vec2 edge1, vec2 x);
+vec3 smoothstep(vec3 edge0, vec3 edge1, vec3 x);
+vec4 smoothstep(vec4 edge0, vec4 edge1, vec4 x);
+float smoothstep(float edge0, float edge1, float x);
+vec2 smoothstep(float edge0, float edge1, vec2 x);
+vec3 smoothstep(float edge0, float edge1, vec3 x);
+vec4 smoothstep(float edge0, float edge1, vec4 x);
+
+// Geometric functions.
+float length(float x);
+float length(vec2 x);
+float length(vec3 x);
+float length(vec4 x);
+float distance(float p0, float p1);
+float distance(vec2 p0, vec2 p1);
+float distance(vec3 p0, vec3 p1);
+float distance(vec4 p0, vec4 p1);
+float dot(float x, float y);
+float dot(vec2 x, vec2 y);
+float dot(vec3 x, vec3 y);
+float dot(vec4 x, vec4 y);
+vec3 cross(vec3 x, vec3 y);
+float normalize(float x);
+vec2 normalize(vec2 x);
+vec3 normalize(vec3 x);
+vec4 normalize(vec4 x);
+float faceforward(float N, float I, float Nref);
+vec2 faceforward(vec2 N, vec2 I, vec2 Nref);
+vec3 faceforward(vec3 N, vec3 I, vec3 Nref);
+vec4 faceforward(vec4 N, vec4 I, vec4 Nref);
+float reflect(float I, float N);
+vec2 reflect(vec2 I, vec2 N);
+vec3 reflect(vec3 I, vec3 N);
+vec4 reflect(vec4 I, vec4 N);
+float refract(float I, float N, float eta);
+vec2 refract(vec2 I, vec2 N, float eta);
+vec3 refract(vec3 I, vec3 N, float eta);
+vec4 refract(vec4 I, vec4 N, float eta);
+
+// Matrix functions.
+mat2 matrixCompMult(mat2 x, mat2 y);
+mat3 matrixCompMult(mat3 x, mat3 y);
+mat4 matrixCompMult(mat4 x, mat4 y);
+
+// Vector relational functions.
+bvec2 lessThan(vec2 x, vec2 y);
+bvec2 lessThan(ivec2 x, ivec2 y);
+bvec3 lessThan(vec3 x, vec3 y);
+bvec3 lessThan(ivec3 x, ivec3 y);
+bvec4 lessThan(vec4 x, vec4 y);
+bvec4 lessThan(ivec4 x, ivec4 y);
+bvec2 lessThanEqual(vec2 x, vec2 y);
+bvec2 lessThanEqual(ivec2 x, ivec2 y);
+bvec3 lessThanEqual(vec3 x, vec3 y);
+bvec3 lessThanEqual(ivec3 x, ivec3 y);
+bvec4 lessThanEqual(vec4 x, vec4 y);
+bvec4 lessThanEqual(ivec4 x, ivec4 y);
+bvec2 greaterThan(vec2 x, vec2 y);
+bvec2 greaterThan(ivec2 x, ivec2 y);
+bvec3 greaterThan(vec3 x, vec3 y);
+bvec3 greaterThan(ivec3 x, ivec3 y);
+bvec4 greaterThan(vec4 x, vec4 y);
+bvec4 greaterThan(ivec4 x, ivec4 y);
+bvec2 greaterThanEqual(vec2 x, vec2 y);
+bvec2 greaterThanEqual(ivec2 x, ivec2 y);
+bvec3 greaterThanEqual(vec3 x, vec3 y);
+bvec3 greaterThanEqual(ivec3 x, ivec3 y);
+bvec4 greaterThanEqual(vec4 x, vec4 y);
+bvec4 greaterThanEqual(ivec4 x, ivec4 y);
+bvec2 equal(vec2 x, vec2 y);
+bvec2 equal(ivec2 x, ivec2 y);
+bvec2 equal(bvec2 x, bvec2 y);
+bvec3 equal(vec3 x, vec3 y);
+bvec3 equal(ivec3 x, ivec3 y);
+bvec3 equal(bvec3 x, bvec3 y);
+bvec4 equal(vec4 x, vec4 y);
+bvec4 equal(ivec4 x, ivec4 y);
+bvec4 equal(bvec4 x, bvec4 y);
+bvec2 notEqual(vec2 x, vec2 y);
+bvec2 notEqual(ivec2 x, ivec2 y);
+bvec2 notEqual(bvec2 x, bvec2 y);
+bvec3 notEqual(vec3 x, vec3 y);
+bvec3 notEqual(ivec3 x, ivec3 y);
+bvec3 notEqual(bvec3 x, bvec3 y);
+bvec4 notEqual(vec4 x, vec4 y);
+bvec4 notEqual(ivec4 x, ivec4 y);
+bvec4 notEqual(bvec4 x, bvec4 y);
+bool any(bvec2 x);
+bool any(bvec3 x);
+bool any(bvec4 x);
+bool all(bvec2 x);
+bool all(bvec3 x);
+bool all(bvec4 x);
+bvec2 not(bvec2 x);
+bvec3 not(bvec3 x);
+bvec4 not(bvec4 x);
+
+// Texture lookup functions.
+vec4 texture2D(sampler2D sampler, vec2 coord);
+vec4 texture2D(sampler2D sampler, vec2 coord, float bias);
+vec4 texture2DProj(sampler2D sampler, vec3 coord);
+vec4 texture2DProj(sampler2D sampler, vec3 coord, float bias);
+vec4 texture2DProj(sampler2D sampler, vec4 coord);
+vec4 texture2DProj(sampler2D sampler, vec4 coord, float bias);
+
+vec4 textureCube(samplerCube sampler, vec3 coord);
+vec4 textureCube(samplerCube sampler, vec3 coord, float bias);
diff --git a/share/qtcreator/qml-type-descriptions/qml-builtin-types.xml b/share/qtcreator/qml-type-descriptions/qml-builtin-types.xml
index 554cba84e1..c4fb76004a 100644
--- a/share/qtcreator/qml-type-descriptions/qml-builtin-types.xml
+++ b/share/qtcreator/qml-type-descriptions/qml-builtin-types.xml
@@ -120,24 +120,24 @@
<enumerator name="NormalPriority" value="128"/>
<enumerator name="HighPriority" value="256"/>
</enum>
- <property name="checkable" type="bool"/>
- <property name="checked" type="bool"/>
- <property name="enabled" type="bool"/>
- <property name="icon" type="QIcon"/>
- <property name="text" type="string"/>
- <property name="iconText" type="string"/>
- <property name="toolTip" type="string"/>
- <property name="statusTip" type="string"/>
- <property name="whatsThis" type="string"/>
- <property name="font" type="QFont"/>
- <property name="shortcut" type="QKeySequence"/>
- <property name="shortcutContext" type="Qt.ShortcutContext"/>
- <property name="autoRepeat" type="bool"/>
- <property name="visible" type="bool"/>
- <property name="menuRole" type="MenuRole"/>
- <property name="softKeyRole" type="SoftKeyRole"/>
- <property name="iconVisibleInMenu" type="bool"/>
- <property name="priority" type="Priority"/>
+ <property name="checkable" type="bool" isWritable="true"/>
+ <property name="checked" type="bool" isWritable="true"/>
+ <property name="enabled" type="bool" isWritable="true"/>
+ <property name="icon" type="QIcon" isWritable="true"/>
+ <property name="text" type="string" isWritable="true"/>
+ <property name="iconText" type="string" isWritable="true"/>
+ <property name="toolTip" type="string" isWritable="true"/>
+ <property name="statusTip" type="string" isWritable="true"/>
+ <property name="whatsThis" type="string" isWritable="true"/>
+ <property name="font" type="QFont" isWritable="true"/>
+ <property name="shortcut" type="QKeySequence" isWritable="true"/>
+ <property name="shortcutContext" type="Qt.ShortcutContext" isWritable="true"/>
+ <property name="autoRepeat" type="bool" isWritable="true"/>
+ <property name="visible" type="bool" isWritable="true"/>
+ <property name="menuRole" type="MenuRole" isWritable="true"/>
+ <property name="softKeyRole" type="SoftKeyRole" isWritable="true"/>
+ <property name="iconVisibleInMenu" type="bool" isWritable="true"/>
+ <property name="priority" type="Priority" isWritable="true"/>
<signal name="changed"/>
<signal name="triggered">
<param name="checked" type="bool"/>
@@ -202,10 +202,10 @@
<enum name="Loops">
<enumerator name="Infinite" value="-2"/>
</enum>
- <property name="running" type="bool"/>
- <property name="paused" type="bool"/>
- <property name="alwaysRunToEnd" type="bool"/>
- <property name="loops" type="int"/>
+ <property name="running" type="bool" isWritable="true"/>
+ <property name="paused" type="bool" isWritable="true"/>
+ <property name="alwaysRunToEnd" type="bool" isWritable="true"/>
+ <property name="loops" type="int" isWritable="true"/>
<signal name="started"/>
<signal name="completed"/>
<signal name="runningChanged">
@@ -233,8 +233,8 @@
<export module="Qt" version="4.7" type="AnchorAnimation"/>
</exports>
<property name="targets" type="QDeclarativeItem" isList="true"/>
- <property name="duration" type="int"/>
- <property name="easing" type="QEasingCurve"/>
+ <property name="duration" type="int" isWritable="true"/>
+ <property name="easing" type="QEasingCurve" isWritable="true"/>
<signal name="durationChanged">
<param type="int"/>
</signal>
@@ -247,36 +247,36 @@
<export module="QtQuick" version="1.0" type="AnchorChanges"/>
<export module="Qt" version="4.7" type="AnchorChanges"/>
</exports>
- <property name="target" type="QDeclarativeItem"/>
- <property name="anchors" type="QDeclarativeAnchorSet"/>
+ <property name="target" type="QDeclarativeItem" isWritable="true" isPointer="true"/>
+ <property name="anchors" type="QDeclarativeAnchorSet" isPointer="true"/>
</type>
<type name="QDeclarativeAnchorSet" extends="QObject">
- <property name="left" type="QDeclarativeScriptString"/>
- <property name="right" type="QDeclarativeScriptString"/>
- <property name="horizontalCenter" type="QDeclarativeScriptString"/>
- <property name="top" type="QDeclarativeScriptString"/>
- <property name="bottom" type="QDeclarativeScriptString"/>
- <property name="verticalCenter" type="QDeclarativeScriptString"/>
- <property name="baseline" type="QDeclarativeScriptString"/>
+ <property name="left" type="QDeclarativeScriptString" isWritable="true"/>
+ <property name="right" type="QDeclarativeScriptString" isWritable="true"/>
+ <property name="horizontalCenter" type="QDeclarativeScriptString" isWritable="true"/>
+ <property name="top" type="QDeclarativeScriptString" isWritable="true"/>
+ <property name="bottom" type="QDeclarativeScriptString" isWritable="true"/>
+ <property name="verticalCenter" type="QDeclarativeScriptString" isWritable="true"/>
+ <property name="baseline" type="QDeclarativeScriptString" isWritable="true"/>
</type>
<type name="QDeclarativeAnchors" extends="QObject">
- <property name="left" type="QDeclarativeAnchorLine"/>
- <property name="right" type="QDeclarativeAnchorLine"/>
- <property name="horizontalCenter" type="QDeclarativeAnchorLine"/>
- <property name="top" type="QDeclarativeAnchorLine"/>
- <property name="bottom" type="QDeclarativeAnchorLine"/>
- <property name="verticalCenter" type="QDeclarativeAnchorLine"/>
- <property name="baseline" type="QDeclarativeAnchorLine"/>
- <property name="margins" type="qreal"/>
- <property name="leftMargin" type="qreal"/>
- <property name="rightMargin" type="qreal"/>
- <property name="horizontalCenterOffset" type="qreal"/>
- <property name="topMargin" type="qreal"/>
- <property name="bottomMargin" type="qreal"/>
- <property name="verticalCenterOffset" type="qreal"/>
- <property name="baselineOffset" type="qreal"/>
- <property name="fill" type="QGraphicsObject"/>
- <property name="centerIn" type="QGraphicsObject"/>
+ <property name="left" type="QDeclarativeAnchorLine" isWritable="true"/>
+ <property name="right" type="QDeclarativeAnchorLine" isWritable="true"/>
+ <property name="horizontalCenter" type="QDeclarativeAnchorLine" isWritable="true"/>
+ <property name="top" type="QDeclarativeAnchorLine" isWritable="true"/>
+ <property name="bottom" type="QDeclarativeAnchorLine" isWritable="true"/>
+ <property name="verticalCenter" type="QDeclarativeAnchorLine" isWritable="true"/>
+ <property name="baseline" type="QDeclarativeAnchorLine" isWritable="true"/>
+ <property name="margins" type="qreal" isWritable="true"/>
+ <property name="leftMargin" type="qreal" isWritable="true"/>
+ <property name="rightMargin" type="qreal" isWritable="true"/>
+ <property name="horizontalCenterOffset" type="qreal" isWritable="true"/>
+ <property name="topMargin" type="qreal" isWritable="true"/>
+ <property name="bottomMargin" type="qreal" isWritable="true"/>
+ <property name="verticalCenterOffset" type="qreal" isWritable="true"/>
+ <property name="baselineOffset" type="qreal" isWritable="true"/>
+ <property name="fill" type="QGraphicsObject" isWritable="true" isPointer="true"/>
+ <property name="centerIn" type="QGraphicsObject" isWritable="true" isPointer="true"/>
<signal name="leftChanged"/>
<signal name="rightChanged"/>
<signal name="topChanged"/>
@@ -300,9 +300,9 @@
<export module="Qt" version="4.7" type="AnimatedImage"/>
<export module="QtQuick" version="1.0" type="AnimatedImage"/>
</exports>
- <property name="playing" type="bool"/>
- <property name="paused" type="bool"/>
- <property name="currentFrame" type="int"/>
+ <property name="playing" type="bool" isWritable="true"/>
+ <property name="paused" type="bool" isWritable="true"/>
+ <property name="currentFrame" type="int" isWritable="true"/>
<property name="frameCount" type="int"/>
<property name="sourceSize" type="QSize"/>
<signal name="playingChanged"/>
@@ -336,21 +336,21 @@
<enumerator name="AccessDenied" value="4"/>
<enumerator name="ServiceMissing" value="5"/>
</enum>
- <property name="source" type="QUrl"/>
- <property name="autoLoad" type="bool"/>
- <property name="playing" type="bool"/>
- <property name="paused" type="bool"/>
+ <property name="source" type="QUrl" isWritable="true"/>
+ <property name="autoLoad" type="bool" isWritable="true"/>
+ <property name="playing" type="bool" isWritable="true"/>
+ <property name="paused" type="bool" isWritable="true"/>
<property name="status" type="Status"/>
<property name="duration" type="int"/>
- <property name="position" type="int"/>
- <property name="volume" type="qreal"/>
- <property name="muted" type="bool"/>
+ <property name="position" type="int" isWritable="true"/>
+ <property name="volume" type="qreal" isWritable="true"/>
+ <property name="muted" type="bool" isWritable="true"/>
<property name="bufferProgress" type="int"/>
<property name="seekable" type="bool"/>
- <property name="playbackRate" type="qreal"/>
+ <property name="playbackRate" type="qreal" isWritable="true"/>
<property name="error" type="Error"/>
<property name="errorString" type="string"/>
- <property name="metaData" type="QDeclarativeMediaMetaData"/>
+ <property name="metaData" type="QDeclarativeMediaMetaData" isPointer="true"/>
<signal name="sourceChanged"/>
<signal name="autoLoadChanged"/>
<signal name="playingChanged"/>
@@ -377,9 +377,9 @@
<method name="stop"/>
</type>
<type name="QDeclarativeBasePositioner" defaultProperty="data" extends="QDeclarativeItem">
- <property name="spacing" type="int"/>
- <property name="move" type="QDeclarativeTransition"/>
- <property name="add" type="QDeclarativeTransition"/>
+ <property name="spacing" type="int" isWritable="true"/>
+ <property name="move" type="QDeclarativeTransition" isWritable="true" isPointer="true"/>
+ <property name="add" type="QDeclarativeTransition" isWritable="true" isPointer="true"/>
<signal name="spacingChanged"/>
<signal name="moveChanged"/>
<signal name="addChanged"/>
@@ -389,8 +389,8 @@
<export module="Qt" version="4.7" type="Behavior"/>
<export module="QtQuick" version="1.0" type="Behavior"/>
</exports>
- <property name="animation" type="QDeclarativeAbstractAnimation"/>
- <property name="enabled" type="bool"/>
+ <property name="animation" type="QDeclarativeAbstractAnimation" isWritable="true" isPointer="true"/>
+ <property name="enabled" type="bool" isWritable="true"/>
<signal name="enabledChanged"/>
</type>
<type name="QDeclarativeBind" extends="QObject">
@@ -398,10 +398,10 @@
<export module="Qt" version="4.7" type="Binding"/>
<export module="QtQuick" version="1.0" type="Binding"/>
</exports>
- <property name="target" type="QObject"/>
- <property name="property" type="string"/>
- <property name="value" type="QVariant"/>
- <property name="when" type="bool"/>
+ <property name="target" type="QObject" isWritable="true" isPointer="true"/>
+ <property name="property" type="string" isWritable="true"/>
+ <property name="value" type="QVariant" isWritable="true"/>
+ <property name="when" type="bool" isWritable="true"/>
</type>
<type name="QDeclarativeBorderImage" defaultProperty="data" extends="QDeclarativeImageBase">
<exports>
@@ -413,9 +413,9 @@
<enumerator name="Repeat" value="1"/>
<enumerator name="Round" value="2"/>
</enum>
- <property name="border" type="QDeclarativeScaleGrid"/>
- <property name="horizontalTileMode" type="TileMode"/>
- <property name="verticalTileMode" type="TileMode"/>
+ <property name="border" type="QDeclarativeScaleGrid" isPointer="true"/>
+ <property name="horizontalTileMode" type="TileMode" isWritable="true"/>
+ <property name="verticalTileMode" type="TileMode" isWritable="true"/>
<signal name="horizontalTileModeChanged"/>
<signal name="verticalTileModeChanged"/>
</type>
@@ -478,22 +478,22 @@
<enumerator name="WhiteBalanceSunset" value="9"/>
<enumerator name="WhiteBalanceVendor" value="1000"/>
</enum>
- <property name="cameraState" type="State"/>
+ <property name="cameraState" type="State" isWritable="true"/>
<property name="lockStatus" type="LockStatus"/>
<property name="errorString" type="string"/>
<property name="capturedImagePath" type="string"/>
- <property name="iso" type="int"/>
+ <property name="iso" type="int" isWritable="true"/>
<property name="shutterSpeed" type="qreal"/>
<property name="aperture" type="qreal"/>
- <property name="exposureCompensation" type="qreal"/>
- <property name="exposureMode" type="ExposureMode"/>
- <property name="flashMode" type="int"/>
- <property name="whiteBalanceMode" type="WhiteBalanceMode"/>
- <property name="manualWhiteBalance" type="int"/>
- <property name="captureResolution" type="QSize"/>
- <property name="opticalZoom" type="qreal"/>
+ <property name="exposureCompensation" type="qreal" isWritable="true"/>
+ <property name="exposureMode" type="ExposureMode" isWritable="true"/>
+ <property name="flashMode" type="int" isWritable="true"/>
+ <property name="whiteBalanceMode" type="WhiteBalanceMode" isWritable="true"/>
+ <property name="manualWhiteBalance" type="int" isWritable="true"/>
+ <property name="captureResolution" type="QSize" isWritable="true"/>
+ <property name="opticalZoom" type="qreal" isWritable="true"/>
<property name="maximumOpticalZoom" type="qreal"/>
- <property name="digitalZoom" type="qreal"/>
+ <property name="digitalZoom" type="qreal" isWritable="true"/>
<property name="maximumDigitalZoom" type="qreal"/>
<signal name="errorChanged"/>
<signal name="error">
@@ -593,8 +593,8 @@
<export module="Qt" version="4.7" type="ColorAnimation"/>
<export module="QtQuick" version="1.0" type="ColorAnimation"/>
</exports>
- <property name="from" type="QColor"/>
- <property name="to" type="QColor"/>
+ <property name="from" type="QColor" isWritable="true"/>
+ <property name="to" type="QColor" isWritable="true"/>
</type>
<type name="QDeclarativeColumn" defaultProperty="data" extends="QDeclarativeBasePositioner">
<exports>
@@ -631,8 +631,8 @@
<export module="Qt" version="4.7" type="Connections"/>
<export module="Qt" version="4.7" type="Connections"/>
</exports>
- <property name="target" type="QObject"/>
- <property name="ignoreUnknownSignals" type="bool"/>
+ <property name="target" type="QObject" isWritable="true" isPointer="true"/>
+ <property name="ignoreUnknownSignals" type="bool" isWritable="true"/>
<signal name="targetChanged"/>
</type>
<type name="QDeclarativeContact" defaultProperty="details" extends="QObject">
@@ -646,32 +646,32 @@
<property name="contactId" type="QContactLocalId"/>
<property name="manager" type="string"/>
<property name="details" type="QDeclarativeContactDetail" isList="true"/>
- <property name="address" type="QDeclarativeContactAddress"/>
- <property name="anniversary" type="QDeclarativeContactAnniversary"/>
- <property name="avatar" type="QDeclarativeContactAvatar"/>
- <property name="birthday" type="QDeclarativeContactBirthday"/>
+ <property name="address" type="QDeclarativeContactAddress" isPointer="true"/>
+ <property name="anniversary" type="QDeclarativeContactAnniversary" isPointer="true"/>
+ <property name="avatar" type="QDeclarativeContactAvatar" isPointer="true"/>
+ <property name="birthday" type="QDeclarativeContactBirthday" isPointer="true"/>
<property name="displayLabel" type="string"/>
- <property name="email" type="QDeclarativeContactEmailAddress"/>
- <property name="family" type="QDeclarativeContactFamily"/>
- <property name="favorite" type="QDeclarativeContactFavorite"/>
- <property name="gender" type="QDeclarativeContactGender"/>
- <property name="geolocation" type="QDeclarativeContactGeoLocation"/>
- <property name="globalPresence" type="QDeclarativeContactGlobalPresence"/>
- <property name="guid" type="QDeclarativeContactGuid"/>
- <property name="name" type="QDeclarativeContactName"/>
- <property name="nickname" type="QDeclarativeContactNickname"/>
- <property name="note" type="QDeclarativeContactNote"/>
- <property name="onlineAccount" type="QDeclarativeContactOnlineAccount"/>
- <property name="organization" type="QDeclarativeContactOrganization"/>
- <property name="phoneNumber" type="QDeclarativeContactPhoneNumber"/>
- <property name="presence" type="QDeclarativeContactPresence"/>
- <property name="ringtone" type="QDeclarativeContactRingtone"/>
- <property name="syncTarget" type="QDeclarativeContactSyncTarget"/>
- <property name="tag" type="QDeclarativeContactTag"/>
- <property name="thumbnail" type="QUrl"/>
- <property name="type" type="ContactType"/>
- <property name="url" type="QDeclarativeContactUrl"/>
- <property name="hobby" type="QDeclarativeContactHobby"/>
+ <property name="email" type="QDeclarativeContactEmailAddress" isPointer="true"/>
+ <property name="family" type="QDeclarativeContactFamily" isPointer="true"/>
+ <property name="favorite" type="QDeclarativeContactFavorite" isPointer="true"/>
+ <property name="gender" type="QDeclarativeContactGender" isPointer="true"/>
+ <property name="geolocation" type="QDeclarativeContactGeoLocation" isPointer="true"/>
+ <property name="globalPresence" type="QDeclarativeContactGlobalPresence" isPointer="true"/>
+ <property name="guid" type="QDeclarativeContactGuid" isPointer="true"/>
+ <property name="name" type="QDeclarativeContactName" isPointer="true"/>
+ <property name="nickname" type="QDeclarativeContactNickname" isPointer="true"/>
+ <property name="note" type="QDeclarativeContactNote" isPointer="true"/>
+ <property name="onlineAccount" type="QDeclarativeContactOnlineAccount" isPointer="true"/>
+ <property name="organization" type="QDeclarativeContactOrganization" isPointer="true"/>
+ <property name="phoneNumber" type="QDeclarativeContactPhoneNumber" isPointer="true"/>
+ <property name="presence" type="QDeclarativeContactPresence" isPointer="true"/>
+ <property name="ringtone" type="QDeclarativeContactRingtone" isPointer="true"/>
+ <property name="syncTarget" type="QDeclarativeContactSyncTarget" isPointer="true"/>
+ <property name="tag" type="QDeclarativeContactTag" isPointer="true"/>
+ <property name="thumbnail" type="QUrl" isWritable="true"/>
+ <property name="type" type="ContactType" isWritable="true"/>
+ <property name="url" type="QDeclarativeContactUrl" isPointer="true"/>
+ <property name="hobby" type="QDeclarativeContactHobby" isPointer="true"/>
<property name="modified" type="bool"/>
<signal name="contactIdChanged"/>
<signal name="managerChanged"/>
@@ -685,14 +685,14 @@
<param name="name" type="QVariant"/>
</method>
<method name="removeDetail" type="bool">
- <param name="detail" type="QDeclarativeContactDetail"/>
+ <param name="detail" type="QDeclarativeContactDetail" isPointer="true"/>
</method>
</type>
<type name="QDeclarativeContactActionFilter" defaultProperty="actionName" extends="QDeclarativeContactFilter">
<exports>
<export module="QtMobility.contacts" version="1.1" type="ActionFilter"/>
</exports>
- <property name="actionName" type="string"/>
+ <property name="actionName" type="string" isWritable="true"/>
<signal name="valueChanged"/>
</type>
<type name="QDeclarativeContactAddress" extends="QDeclarativeContactDetail">
@@ -714,13 +714,13 @@
<enumerator name="Domestic" value="2"/>
<enumerator name="International" value="3"/>
</enum>
- <property name="street" type="string"/>
- <property name="locality" type="string"/>
- <property name="region" type="string"/>
- <property name="postcode" type="string"/>
- <property name="country" type="string"/>
- <property name="subTypes" type="QVariantList"/>
- <property name="postOfficeBox" type="string"/>
+ <property name="street" type="string" isWritable="true"/>
+ <property name="locality" type="string" isWritable="true"/>
+ <property name="region" type="string" isWritable="true"/>
+ <property name="postcode" type="string" isWritable="true"/>
+ <property name="country" type="string" isWritable="true"/>
+ <property name="subTypes" type="QVariantList" isWritable="true"/>
+ <property name="postOfficeBox" type="string" isWritable="true"/>
<signal name="fieldsChanged"/>
</type>
<type name="QDeclarativeContactAnniversary" extends="QDeclarativeContactDetail">
@@ -741,11 +741,11 @@
<enumerator name="Employment" value="4"/>
<enumerator name="Memorial" value="5"/>
</enum>
- <property name="calendarId" type="string"/>
- <property name="originalDate" type="QDate"/>
- <property name="originalDateTime" type="QDateTime"/>
- <property name="event" type="string"/>
- <property name="subType" type="AnniversarySubType"/>
+ <property name="calendarId" type="string" isWritable="true"/>
+ <property name="originalDate" type="QDate" isWritable="true"/>
+ <property name="originalDateTime" type="QDateTime" isWritable="true"/>
+ <property name="event" type="string" isWritable="true"/>
+ <property name="subType" type="AnniversarySubType" isWritable="true"/>
<signal name="fieldsChanged"/>
</type>
<type name="QDeclarativeContactAvatar" extends="QDeclarativeContactDetail">
@@ -756,8 +756,8 @@
<enumerator name="ImageUrl" value="0"/>
<enumerator name="VideoUrl" value="1"/>
</enum>
- <property name="imageUrl" type="QUrl"/>
- <property name="videoUrl" type="QUrl"/>
+ <property name="imageUrl" type="QUrl" isWritable="true"/>
+ <property name="videoUrl" type="QUrl" isWritable="true"/>
<signal name="fieldsChanged"/>
</type>
<type name="QDeclarativeContactBirthday" extends="QDeclarativeContactDetail">
@@ -767,7 +767,7 @@
<enum name="FieldType">
<enumerator name="Birthday" value="0"/>
</enum>
- <property name="birthday" type="QDateTime"/>
+ <property name="birthday" type="QDateTime" isWritable="true"/>
<signal name="fieldsChanged"/>
</type>
<type name="QDeclarativeContactChangeLogFilter" extends="QDeclarativeContactFilter">
@@ -779,8 +779,8 @@
<enumerator name="EventChanged" value="1"/>
<enumerator name="EventRemoved" value="2"/>
</enum>
- <property name="since" type="QDateTime"/>
- <property name="eventType" type="EventType"/>
+ <property name="since" type="QDateTime" isWritable="true"/>
+ <property name="eventType" type="EventType" isWritable="true"/>
<signal name="valueChanged"/>
</type>
<type name="QDeclarativeContactDetail" extends="QObject">
@@ -817,9 +817,9 @@
</enum>
<property name="type" type="ContactDetailType"/>
<property name="definitionName" type="string"/>
- <property name="contexts" type="QStringList"/>
- <property name="detailUri" type="string"/>
- <property name="linkedDetailUris" type="QStringList"/>
+ <property name="contexts" type="QStringList" isWritable="true"/>
+ <property name="detailUri" type="string" isWritable="true"/>
+ <property name="linkedDetailUris" type="QStringList" isWritable="true"/>
<property name="fieldNames" type="QStringList"/>
<property name="readOnly" type="bool"/>
<property name="removable" type="bool"/>
@@ -836,10 +836,10 @@
<exports>
<export module="QtMobility.contacts" version="1.1" type="DetailFilter"/>
</exports>
- <property name="detail" type="QDeclarativeContactDetail.ContactDetailType"/>
- <property name="field" type="int"/>
- <property name="value" type="QVariant"/>
- <property name="matchFlags" type="MatchFlags"/>
+ <property name="detail" type="QDeclarativeContactDetail.ContactDetailType" isWritable="true"/>
+ <property name="field" type="int" isWritable="true"/>
+ <property name="value" type="QVariant" isWritable="true"/>
+ <property name="matchFlags" type="MatchFlags" isWritable="true"/>
<signal name="valueChanged"/>
</type>
<type name="QDeclarativeContactDetailRangeFilter" extends="QDeclarativeContactFilter">
@@ -852,12 +852,12 @@
<enumerator name="ExcludeLower" value="2"/>
<enumerator name="ExcludeUpper" value="0"/>
</enum>
- <property name="detail" type="QDeclarativeContactDetail.ContactDetailType"/>
- <property name="field" type="int"/>
- <property name="min" type="QVariant"/>
- <property name="max" type="QVariant"/>
- <property name="matchFlags" type="MatchFlags"/>
- <property name="rangeFlags" type="RangeFlags"/>
+ <property name="detail" type="QDeclarativeContactDetail.ContactDetailType" isWritable="true"/>
+ <property name="field" type="int" isWritable="true"/>
+ <property name="min" type="QVariant" isWritable="true"/>
+ <property name="max" type="QVariant" isWritable="true"/>
+ <property name="matchFlags" type="MatchFlags" isWritable="true"/>
+ <property name="rangeFlags" type="RangeFlags" isWritable="true"/>
<signal name="valueChanged"/>
</type>
<type name="QDeclarativeContactDisplayLabel" defaultProperty="label" extends="QDeclarativeContactDetail">
@@ -877,7 +877,7 @@
<enum name="FieldType">
<enumerator name="EmailAddress" value="0"/>
</enum>
- <property name="emailAddress" type="string"/>
+ <property name="emailAddress" type="string" isWritable="true"/>
<signal name="fieldsChanged"/>
</type>
<type name="QDeclarativeContactFamily" extends="QDeclarativeContactDetail">
@@ -888,8 +888,8 @@
<enumerator name="Spouse" value="0"/>
<enumerator name="Children" value="1"/>
</enum>
- <property name="spouse" type="string"/>
- <property name="children" type="QStringList"/>
+ <property name="spouse" type="string" isWritable="true"/>
+ <property name="children" type="QStringList" isWritable="true"/>
<signal name="fieldsChanged"/>
</type>
<type name="QDeclarativeContactFavorite" defaultProperty="index" extends="QDeclarativeContactDetail">
@@ -900,8 +900,8 @@
<enumerator name="Favorite" value="0"/>
<enumerator name="Index" value="1"/>
</enum>
- <property name="favorite" type="bool"/>
- <property name="index" type="int"/>
+ <property name="favorite" type="bool" isWritable="true"/>
+ <property name="index" type="int" isWritable="true"/>
<signal name="fieldsChanged"/>
</type>
<type name="QDeclarativeContactFetchHint" extends="QObject">
@@ -914,10 +914,10 @@
<enumerator name="NoActionPreferences" value="2"/>
<enumerator name="NoBinaryBlobs" value="4"/>
</enum>
- <property name="detailDefinitionsHint" type="QStringList"/>
- <property name="relationshipTypesHint" type="QStringList"/>
- <property name="optimizationHints" type="OptimizationHints"/>
- <property name="optimizationHints" type="QSize"/>
+ <property name="detailDefinitionsHint" type="QStringList" isWritable="true"/>
+ <property name="relationshipTypesHint" type="QStringList" isWritable="true"/>
+ <property name="optimizationHints" type="OptimizationHints" isWritable="true"/>
+ <property name="optimizationHints" type="QSize" isWritable="true"/>
<signal name="fetchHintChanged"/>
</type>
<type name="QDeclarativeContactFilter" extends="QObject">
@@ -961,7 +961,7 @@
<enumerator name="Male" value="0"/>
<enumerator name="Female" value="1"/>
</enum>
- <property name="gender" type="GenderType"/>
+ <property name="gender" type="GenderType" isWritable="true"/>
<signal name="fieldsChanged"/>
</type>
<type name="QDeclarativeContactGeoLocation" defaultProperty="label" extends="QDeclarativeContactDetail">
@@ -979,15 +979,15 @@
<enumerator name="Speed" value="7"/>
<enumerator name="Timestamp" value="8"/>
</enum>
- <property name="label" type="string"/>
- <property name="latitude" type="double"/>
- <property name="longitude" type="double"/>
- <property name="accuracy" type="double"/>
- <property name="altitude" type="double"/>
- <property name="altitudeAccuracy" type="double"/>
- <property name="heading" type="double"/>
- <property name="speed" type="double"/>
- <property name="timestamp" type="QDateTime"/>
+ <property name="label" type="string" isWritable="true"/>
+ <property name="latitude" type="double" isWritable="true"/>
+ <property name="longitude" type="double" isWritable="true"/>
+ <property name="accuracy" type="double" isWritable="true"/>
+ <property name="altitude" type="double" isWritable="true"/>
+ <property name="altitudeAccuracy" type="double" isWritable="true"/>
+ <property name="heading" type="double" isWritable="true"/>
+ <property name="speed" type="double" isWritable="true"/>
+ <property name="timestamp" type="QDateTime" isWritable="true"/>
<signal name="fieldsChanged"/>
</type>
<type name="QDeclarativeContactGlobalPresence" defaultProperty="state" extends="QDeclarativeContactDetail">
@@ -1002,12 +1002,12 @@
<enumerator name="ImageUrl" value="4"/>
<enumerator name="CustomMessage" value="5"/>
</enum>
- <property name="timestamp" type="QDateTime"/>
- <property name="nickname" type="string"/>
- <property name="state" type="QDeclarativeContactPresence.PresenceStateType"/>
- <property name="stateText" type="string"/>
- <property name="imageUrl" type="QUrl"/>
- <property name="customMessage" type="string"/>
+ <property name="timestamp" type="QDateTime" isWritable="true"/>
+ <property name="nickname" type="string" isWritable="true"/>
+ <property name="state" type="QDeclarativeContactPresence.PresenceStateType" isWritable="true"/>
+ <property name="stateText" type="string" isWritable="true"/>
+ <property name="imageUrl" type="QUrl" isWritable="true"/>
+ <property name="customMessage" type="string" isWritable="true"/>
<signal name="fieldsChanged"/>
</type>
<type name="QDeclarativeContactGuid" defaultProperty="guid" extends="QDeclarativeContactDetail">
@@ -1017,7 +1017,7 @@
<enum name="FieldType">
<enumerator name="Guid" value="0"/>
</enum>
- <property name="guid" type="string"/>
+ <property name="guid" type="string" isWritable="true"/>
<signal name="fieldsChanged"/>
</type>
<type name="QDeclarativeContactHobby" defaultProperty="hobby" extends="QDeclarativeContactDetail">
@@ -1027,7 +1027,7 @@
<enum name="FieldType">
<enumerator name="Hobby" value="0"/>
</enum>
- <property name="hobby" type="string"/>
+ <property name="hobby" type="string" isWritable="true"/>
<signal name="fieldsChanged"/>
</type>
<type name="QDeclarativeContactIntersectionFilter" defaultProperty="filters" extends="QDeclarativeContactFilter">
@@ -1042,19 +1042,19 @@
<exports>
<export module="QtMobility.contacts" version="1.1" type="IdFilter"/>
</exports>
- <property name="ids" type="QStringList"/>
+ <property name="ids" type="QStringList" isWritable="true"/>
<signal name="valueChanged"/>
</type>
<type name="QDeclarativeContactModel" extends="QAbstractListModel">
<exports>
<export module="QtMobility.contacts" version="1.1" type="ContactModel"/>
</exports>
- <property name="manager" type="string"/>
+ <property name="manager" type="string" isWritable="true"/>
<property name="availableManagers" type="QStringList"/>
<property name="error" type="string"/>
- <property name="autoUpdate" type="bool"/>
- <property name="filter" type="QDeclarativeContactFilter"/>
- <property name="fetchHint" type="QDeclarativeContactFetchHint"/>
+ <property name="autoUpdate" type="bool" isWritable="true"/>
+ <property name="filter" type="QDeclarativeContactFilter" isWritable="true" isPointer="true"/>
+ <property name="fetchHint" type="QDeclarativeContactFetchHint" isWritable="true" isPointer="true"/>
<property name="contacts" type="QDeclarativeContact" isList="true"/>
<property name="sortOrders" type="QDeclarativeContactSortOrder" isList="true"/>
<signal name="managerChanged"/>
@@ -1090,7 +1090,7 @@
<param name="id" type="QContactLocalId"/>
</method>
<method name="saveContact">
- <param name="dc" type="QDeclarativeContact"/>
+ <param name="dc" type="QDeclarativeContact" isPointer="true"/>
</method>
</type>
<type name="QDeclarativeContactName" defaultProperty="firstName" extends="QDeclarativeContactDetail">
@@ -1105,12 +1105,12 @@
<enumerator name="Suffix" value="4"/>
<enumerator name="CustomLabel" value="5"/>
</enum>
- <property name="prefix" type="string"/>
- <property name="firstName" type="string"/>
- <property name="middleName" type="string"/>
- <property name="lastName" type="string"/>
- <property name="suffix" type="string"/>
- <property name="customLabel" type="string"/>
+ <property name="prefix" type="string" isWritable="true"/>
+ <property name="firstName" type="string" isWritable="true"/>
+ <property name="middleName" type="string" isWritable="true"/>
+ <property name="lastName" type="string" isWritable="true"/>
+ <property name="suffix" type="string" isWritable="true"/>
+ <property name="customLabel" type="string" isWritable="true"/>
<signal name="fieldsChanged"/>
</type>
<type name="QDeclarativeContactNickname" defaultProperty="nickname" extends="QDeclarativeContactDetail">
@@ -1120,7 +1120,7 @@
<enum name="FieldType">
<enumerator name="NickName" value="0"/>
</enum>
- <property name="nickname" type="string"/>
+ <property name="nickname" type="string" isWritable="true"/>
<signal name="fieldsChanged"/>
</type>
<type name="QDeclarativeContactNote" defaultProperty="note" extends="QDeclarativeContactDetail">
@@ -1130,7 +1130,7 @@
<enum name="FieldType">
<enumerator name="Note" value="0"/>
</enum>
- <property name="note" type="string"/>
+ <property name="note" type="string" isWritable="true"/>
<signal name="fieldsChanged"/>
</type>
<type name="QDeclarativeContactOnlineAccount" defaultProperty="accountUri" extends="QDeclarativeContactDetail">
@@ -1150,10 +1150,10 @@
<enumerator name="Impp" value="3"/>
<enumerator name="VideoShare" value="4"/>
</enum>
- <property name="accountUri" type="string"/>
- <property name="serviceProvider" type="string"/>
- <property name="capabilities" type="QStringList"/>
- <property name="subTypes" type="QVariantList"/>
+ <property name="accountUri" type="string" isWritable="true"/>
+ <property name="serviceProvider" type="string" isWritable="true"/>
+ <property name="capabilities" type="QStringList" isWritable="true"/>
+ <property name="subTypes" type="QVariantList" isWritable="true"/>
<signal name="fieldsChanged"/>
</type>
<type name="QDeclarativeContactOrganization" defaultProperty="name" extends="QDeclarativeContactDetail">
@@ -1169,13 +1169,13 @@
<enumerator name="Title" value="5"/>
<enumerator name="AssistantName" value="6"/>
</enum>
- <property name="name" type="string"/>
- <property name="logoUrl" type="QUrl"/>
- <property name="department" type="QStringList"/>
- <property name="location" type="string"/>
- <property name="role" type="string"/>
- <property name="title" type="string"/>
- <property name="assistantName" type="string"/>
+ <property name="name" type="string" isWritable="true"/>
+ <property name="logoUrl" type="QUrl" isWritable="true"/>
+ <property name="department" type="QStringList" isWritable="true"/>
+ <property name="location" type="string" isWritable="true"/>
+ <property name="role" type="string" isWritable="true"/>
+ <property name="title" type="string" isWritable="true"/>
+ <property name="assistantName" type="string" isWritable="true"/>
<signal name="fieldsChanged"/>
</type>
<type name="QDeclarativeContactPhoneNumber" defaultProperty="number" extends="QDeclarativeContactDetail">
@@ -1201,8 +1201,8 @@
<enumerator name="Assistant" value="11"/>
<enumerator name="DtmfMenu" value="12"/>
</enum>
- <property name="number" type="string"/>
- <property name="subTypes" type="QVariantList"/>
+ <property name="number" type="string" isWritable="true"/>
+ <property name="subTypes" type="QVariantList" isWritable="true"/>
<signal name="fieldsChanged"/>
</type>
<type name="QDeclarativeContactPresence" defaultProperty="state" extends="QDeclarativeContactDetail">
@@ -1226,12 +1226,12 @@
<enumerator name="ExtendedAway" value="5"/>
<enumerator name="Offline" value="6"/>
</enum>
- <property name="timestamp" type="QDateTime"/>
- <property name="nickname" type="string"/>
- <property name="state" type="PresenceStateType"/>
- <property name="stateText" type="string"/>
- <property name="imageUrl" type="QUrl"/>
- <property name="customMessage" type="string"/>
+ <property name="timestamp" type="QDateTime" isWritable="true"/>
+ <property name="nickname" type="string" isWritable="true"/>
+ <property name="state" type="PresenceStateType" isWritable="true"/>
+ <property name="stateText" type="string" isWritable="true"/>
+ <property name="imageUrl" type="QUrl" isWritable="true"/>
+ <property name="customMessage" type="string" isWritable="true"/>
<signal name="fieldsChanged"/>
</type>
<type name="QDeclarativeContactRelationship" extends="QObject">
@@ -1252,18 +1252,18 @@
<enumerator name="HasManager" value="5"/>
<enumerator name="HasSpouse" value="6"/>
</enum>
- <property name="first" type="QContactLocalId"/>
- <property name="second" type="QContactLocalId"/>
- <property name="type" type="QVariant"/>
+ <property name="first" type="QContactLocalId" isWritable="true"/>
+ <property name="second" type="QContactLocalId" isWritable="true"/>
+ <property name="type" type="QVariant" isWritable="true"/>
<signal name="valueChanged"/>
</type>
<type name="QDeclarativeContactRelationshipFilter" extends="QDeclarativeContactFilter">
<exports>
<export module="QtMobility.contacts" version="1.1" type="RelationshipFilter"/>
</exports>
- <property name="relationshipType" type="QVariant"/>
- <property name="relatedContactId" type="QContactLocalId"/>
- <property name="relatedContactRole" type="QDeclarativeContactRelationship.RelationshipRole"/>
+ <property name="relationshipType" type="QVariant" isWritable="true"/>
+ <property name="relatedContactId" type="QContactLocalId" isWritable="true"/>
+ <property name="relatedContactRole" type="QDeclarativeContactRelationship.RelationshipRole" isWritable="true"/>
<signal name="valueChanged"/>
</type>
<type name="QDeclarativeContactRingtone" defaultProperty="audioRingtoneUrl" extends="QDeclarativeContactDetail">
@@ -1275,9 +1275,9 @@
<enumerator name="VideoRingtoneUrl" value="1"/>
<enumerator name="VibrationRingtoneUrl" value="2"/>
</enum>
- <property name="audioRingtoneUrl" type="QUrl"/>
- <property name="videoRingtoneUrl" type="QUrl"/>
- <property name="vibrationRingtoneUrl" type="QUrl"/>
+ <property name="audioRingtoneUrl" type="QUrl" isWritable="true"/>
+ <property name="videoRingtoneUrl" type="QUrl" isWritable="true"/>
+ <property name="vibrationRingtoneUrl" type="QUrl" isWritable="true"/>
<signal name="fieldsChanged"/>
</type>
<type name="QDeclarativeContactSortOrder" extends="QObject">
@@ -1288,11 +1288,11 @@
<enumerator name="BlanksFirst" value="0"/>
<enumerator name="BlanksLast" value="1"/>
</enum>
- <property name="detail" type="QDeclarativeContactDetail.ContactDetailType"/>
- <property name="field" type="int"/>
- <property name="direction" type="Qt.SortOrder"/>
- <property name="blankPolicy" type="BlankPolicy"/>
- <property name="caseSensitivity" type="Qt.CaseSensitivity"/>
+ <property name="detail" type="QDeclarativeContactDetail.ContactDetailType" isWritable="true"/>
+ <property name="field" type="int" isWritable="true"/>
+ <property name="direction" type="Qt.SortOrder" isWritable="true"/>
+ <property name="blankPolicy" type="BlankPolicy" isWritable="true"/>
+ <property name="caseSensitivity" type="Qt.CaseSensitivity" isWritable="true"/>
<signal name="sortOrderChanged"/>
</type>
<type name="QDeclarativeContactSyncTarget" defaultProperty="syncTarget" extends="QDeclarativeContactDetail">
@@ -1302,7 +1302,7 @@
<enum name="FieldType">
<enumerator name="SyncTarget" value="0"/>
</enum>
- <property name="syncTarget" type="string"/>
+ <property name="syncTarget" type="string" isWritable="true"/>
<signal name="fieldsChanged"/>
</type>
<type name="QDeclarativeContactTag" defaultProperty="tag" extends="QDeclarativeContactDetail">
@@ -1312,7 +1312,7 @@
<enum name="FieldType">
<enumerator name="Tag" value="0"/>
</enum>
- <property name="tag" type="string"/>
+ <property name="tag" type="string" isWritable="true"/>
<signal name="fieldsChanged"/>
</type>
<type name="QDeclarativeContactTimestamp" defaultProperty="lastModified" extends="QDeclarativeContactDetail">
@@ -1323,8 +1323,8 @@
<enumerator name="LastModified" value="0"/>
<enumerator name="Created" value="1"/>
</enum>
- <property name="lastModified" type="QDateTime"/>
- <property name="created" type="QDateTime"/>
+ <property name="lastModified" type="QDateTime" isWritable="true"/>
+ <property name="created" type="QDateTime" isWritable="true"/>
<signal name="fieldsChanged"/>
</type>
<type name="QDeclarativeContactUnionFilter" defaultProperty="filters" extends="QDeclarativeContactFilter">
@@ -1348,17 +1348,17 @@
<enumerator name="HomePage" value="1"/>
<enumerator name="Favourite" value="2"/>
</enum>
- <property name="url" type="string"/>
- <property name="subType" type="UrlSubType"/>
+ <property name="url" type="string" isWritable="true"/>
+ <property name="subType" type="UrlSubType" isWritable="true"/>
<signal name="fieldsChanged"/>
</type>
<type name="QDeclarativeCoordinate" extends="QObject">
<exports>
<export module="QtMobility.location" version="1.1" type="Coordinate"/>
</exports>
- <property name="latitude" type="double"/>
- <property name="longitude" type="double"/>
- <property name="altitude" type="double"/>
+ <property name="latitude" type="double" isWritable="true"/>
+ <property name="longitude" type="double" isWritable="true"/>
+ <property name="altitude" type="double" isWritable="true"/>
<signal name="latitudeChanged">
<param name="latitude" type="double"/>
</signal>
@@ -1369,12 +1369,12 @@
<param name="altitude" type="double"/>
</signal>
<method name="distanceTo" type="qreal">
- <param name="coordinate" type="QObject"/>
+ <param name="coordinate" type="QObject" isPointer="true"/>
</method>
</type>
<type name="QDeclarativeCurve" extends="QDeclarativePathElement">
- <property name="x" type="qreal"/>
- <property name="y" type="qreal"/>
+ <property name="x" type="qreal" isWritable="true"/>
+ <property name="y" type="qreal" isWritable="true"/>
<signal name="xChanged"/>
<signal name="yChanged"/>
</type>
@@ -1435,14 +1435,14 @@
<exports>
<export module="QtMobility.gallery" version="1.1" type="DocumentGalleryModel"/>
</exports>
- <property name="rootType" type="QDeclarativeDocumentGallery.ItemType"/>
+ <property name="rootType" type="QDeclarativeDocumentGallery.ItemType" isWritable="true"/>
<signal name="rootTypeChanged"/>
</type>
<type name="QDeclarativeDocumentGalleryType" extends="QDeclarativeGalleryType">
<exports>
<export module="QtMobility.gallery" version="1.1" type="DocumentGalleryType"/>
</exports>
- <property name="itemType" type="QDeclarativeDocumentGallery.ItemType"/>
+ <property name="itemType" type="QDeclarativeDocumentGallery.ItemType" isWritable="true"/>
<signal name="itemTypeChanged"/>
</type>
<type name="QDeclarativeDrag" extends="QObject">
@@ -1455,14 +1455,14 @@
<enumerator name="YAxis" value="2"/>
<enumerator name="XandYAxis" value="3"/>
</enum>
- <property name="target" type="QGraphicsObject"/>
- <property name="axis" type="Axis"/>
- <property name="minimumX" type="qreal"/>
- <property name="maximumX" type="qreal"/>
- <property name="minimumY" type="qreal"/>
- <property name="maximumY" type="qreal"/>
+ <property name="target" type="QGraphicsObject" isWritable="true" isPointer="true"/>
+ <property name="axis" type="Axis" isWritable="true"/>
+ <property name="minimumX" type="qreal" isWritable="true"/>
+ <property name="maximumX" type="qreal" isWritable="true"/>
+ <property name="minimumY" type="qreal" isWritable="true"/>
+ <property name="maximumY" type="qreal" isWritable="true"/>
<property name="active" type="bool"/>
- <property name="filterChildren" type="bool"/>
+ <property name="filterChildren" type="bool" isWritable="true"/>
<signal name="targetChanged"/>
<signal name="axisChanged"/>
<signal name="minimumXChanged"/>
@@ -1524,10 +1524,10 @@
<enumerator name="SineCurve" value="43"/>
<enumerator name="CosineCurve" value="44"/>
</enum>
- <property name="type" type="Type"/>
- <property name="amplitude" type="qreal"/>
- <property name="overshoot" type="qreal"/>
- <property name="period" type="qreal"/>
+ <property name="type" type="Type" isWritable="true"/>
+ <property name="amplitude" type="qreal" isWritable="true"/>
+ <property name="overshoot" type="qreal" isWritable="true"/>
+ <property name="period" type="qreal" isWritable="true"/>
</type>
<type name="QDeclarativeFeedback" extends="QObject">
<exports>
@@ -1551,8 +1551,8 @@
<exports>
<export module="QtMobility.feedback" version="1.1" type="FileEffect"/>
</exports>
- <property name="running" type="bool"/>
- <property name="paused" type="bool"/>
+ <property name="running" type="bool" isWritable="true"/>
+ <property name="paused" type="bool" isWritable="true"/>
<signal name="runningChanged"/>
<signal name="pausedChanged"/>
<method name="updateState"/>
@@ -1573,30 +1573,30 @@
<enumerator name="VerticalFlick" value="2"/>
<enumerator name="HorizontalAndVerticalFlick" value="3"/>
</enum>
- <property name="contentWidth" type="qreal"/>
- <property name="contentHeight" type="qreal"/>
- <property name="contentX" type="qreal"/>
- <property name="contentY" type="qreal"/>
- <property name="contentItem" type="QDeclarativeItem"/>
+ <property name="contentWidth" type="qreal" isWritable="true"/>
+ <property name="contentHeight" type="qreal" isWritable="true"/>
+ <property name="contentX" type="qreal" isWritable="true"/>
+ <property name="contentY" type="qreal" isWritable="true"/>
+ <property name="contentItem" type="QDeclarativeItem" isPointer="true"/>
<property name="horizontalVelocity" type="qreal"/>
<property name="verticalVelocity" type="qreal"/>
- <property name="boundsBehavior" type="BoundsBehavior"/>
- <property name="maximumFlickVelocity" type="qreal"/>
- <property name="flickDeceleration" type="qreal"/>
+ <property name="boundsBehavior" type="BoundsBehavior" isWritable="true"/>
+ <property name="maximumFlickVelocity" type="qreal" isWritable="true"/>
+ <property name="flickDeceleration" type="qreal" isWritable="true"/>
<property name="moving" type="bool"/>
<property name="movingHorizontally" type="bool"/>
<property name="movingVertically" type="bool"/>
<property name="flicking" type="bool"/>
<property name="flickingHorizontally" type="bool"/>
<property name="flickingVertically" type="bool"/>
- <property name="flickableDirection" type="FlickableDirection"/>
- <property name="interactive" type="bool"/>
- <property name="pressDelay" type="int"/>
+ <property name="flickableDirection" type="FlickableDirection" isWritable="true"/>
+ <property name="interactive" type="bool" isWritable="true"/>
+ <property name="pressDelay" type="int" isWritable="true"/>
<property name="atXEnd" type="bool"/>
<property name="atYEnd" type="bool"/>
<property name="atXBeginning" type="bool"/>
<property name="atYBeginning" type="bool"/>
- <property name="visibleArea" type="QDeclarativeFlickableVisibleArea"/>
+ <property name="visibleArea" type="QDeclarativeFlickableVisibleArea" isPointer="true"/>
<property name="flickableData" type="QObject" isList="true"/>
<property name="flickableChildren" type="QGraphicsObject" isList="true"/>
<signal name="contentWidthChanged"/>
@@ -1640,8 +1640,8 @@
<enumerator name="Front" value="0"/>
<enumerator name="Back" value="1"/>
</enum>
- <property name="front" type="QGraphicsObject"/>
- <property name="back" type="QGraphicsObject"/>
+ <property name="front" type="QGraphicsObject" isWritable="true" isPointer="true"/>
+ <property name="back" type="QGraphicsObject" isWritable="true" isPointer="true"/>
<property name="side" type="Side"/>
<signal name="sideChanged"/>
</type>
@@ -1654,7 +1654,7 @@
<enumerator name="LeftToRight" value="0"/>
<enumerator name="TopToBottom" value="1"/>
</enum>
- <property name="flow" type="Flow"/>
+ <property name="flow" type="Flow" isWritable="true"/>
<signal name="flowChanged"/>
</type>
<type name="QDeclarativeFocusPanel" defaultProperty="data" extends="QDeclarativeItem">
@@ -1662,7 +1662,7 @@
<export module="Qt" version="4.7" type="FocusPanel"/>
<export module="QtQuick" version="1.0" type="FocusPanel"/>
</exports>
- <property name="active" type="bool"/>
+ <property name="active" type="bool" isWritable="true"/>
<signal name="activeChanged"/>
</type>
<type name="QDeclarativeFocusScope" defaultProperty="data" extends="QDeclarativeItem">
@@ -1682,14 +1682,14 @@
<enumerator name="Size" value="3"/>
<enumerator name="Type" value="4"/>
</enum>
- <property name="folder" type="QUrl"/>
+ <property name="folder" type="QUrl" isWritable="true"/>
<property name="parentFolder" type="QUrl"/>
- <property name="nameFilters" type="QStringList"/>
- <property name="sortField" type="SortField"/>
- <property name="sortReversed" type="bool"/>
- <property name="showDirs" type="bool"/>
- <property name="showDotAndDotDot" type="bool"/>
- <property name="showOnlyReadable" type="bool"/>
+ <property name="nameFilters" type="QStringList" isWritable="true"/>
+ <property name="sortField" type="SortField" isWritable="true"/>
+ <property name="sortReversed" type="bool" isWritable="true"/>
+ <property name="showDirs" type="bool" isWritable="true"/>
+ <property name="showDotAndDotDot" type="bool" isWritable="true"/>
+ <property name="showOnlyReadable" type="bool" isWritable="true"/>
<property name="count" type="int"/>
<signal name="folderChanged"/>
<method name="isFolder" type="bool">
@@ -1707,8 +1707,8 @@
<enumerator name="Loading" value="2"/>
<enumerator name="Error" value="3"/>
</enum>
- <property name="source" type="QUrl"/>
- <property name="name" type="string"/>
+ <property name="source" type="QUrl" isWritable="true"/>
+ <property name="name" type="string" isWritable="true"/>
<property name="status" type="Status"/>
<signal name="sourceChanged"/>
<signal name="nameChanged"/>
@@ -1733,18 +1733,18 @@
<enumerator name="SmallCaps" value="3"/>
<enumerator name="Capitalize" value="4"/>
</enum>
- <property name="family" type="string"/>
- <property name="bold" type="bool"/>
- <property name="weight" type="FontWeight"/>
- <property name="italic" type="bool"/>
- <property name="underline" type="bool"/>
- <property name="overline" type="bool"/>
- <property name="strikeout" type="bool"/>
- <property name="pointSize" type="qreal"/>
- <property name="pixelSize" type="int"/>
- <property name="capitalization" type="Capitalization"/>
- <property name="letterSpacing" type="qreal"/>
- <property name="wordSpacing" type="qreal"/>
+ <property name="family" type="string" isWritable="true"/>
+ <property name="bold" type="bool" isWritable="true"/>
+ <property name="weight" type="FontWeight" isWritable="true"/>
+ <property name="italic" type="bool" isWritable="true"/>
+ <property name="underline" type="bool" isWritable="true"/>
+ <property name="overline" type="bool" isWritable="true"/>
+ <property name="strikeout" type="bool" isWritable="true"/>
+ <property name="pointSize" type="qreal" isWritable="true"/>
+ <property name="pixelSize" type="int" isWritable="true"/>
+ <property name="capitalization" type="Capitalization" isWritable="true"/>
+ <property name="letterSpacing" type="qreal" isWritable="true"/>
+ <property name="wordSpacing" type="qreal" isWritable="true"/>
</type>
<type name="QDeclarativeGalleryContainsFilter" extends="QDeclarativeGalleryStringFilter">
<exports>
@@ -1799,12 +1799,12 @@
</enum>
<property name="status" type="Status"/>
<property name="progress" type="qreal"/>
- <property name="properties" type="QStringList"/>
- <property name="autoUpdate" type="bool"/>
- <property name="item" type="QVariant"/>
+ <property name="properties" type="QStringList" isWritable="true"/>
+ <property name="autoUpdate" type="bool" isWritable="true"/>
+ <property name="item" type="QVariant" isWritable="true"/>
<property name="available" type="bool"/>
<property name="itemUrl" type="QUrl"/>
- <property name="metaData" type="QObject"/>
+ <property name="metaData" type="QObject" isPointer="true"/>
<signal name="statusChanged"/>
<signal name="progressChanged"/>
<signal name="availableChanged"/>
@@ -1843,15 +1843,15 @@
</enum>
<property name="status" type="Status"/>
<property name="progress" type="qreal"/>
- <property name="properties" type="QStringList"/>
- <property name="sortProperties" type="QStringList"/>
- <property name="autoUpdate" type="bool"/>
- <property name="rootItem" type="QVariant"/>
- <property name="scope" type="Scope"/>
- <property name="offset" type="int"/>
- <property name="limit" type="int"/>
+ <property name="properties" type="QStringList" isWritable="true"/>
+ <property name="sortProperties" type="QStringList" isWritable="true"/>
+ <property name="autoUpdate" type="bool" isWritable="true"/>
+ <property name="rootItem" type="QVariant" isWritable="true"/>
+ <property name="scope" type="Scope" isWritable="true"/>
+ <property name="offset" type="int" isWritable="true"/>
+ <property name="limit" type="int" isWritable="true"/>
<property name="count" type="int"/>
- <property name="filter" type="QDeclarativeGalleryFilterBase"/>
+ <property name="filter" type="QDeclarativeGalleryFilterBase" isWritable="true" isPointer="true"/>
<signal name="statusChanged"/>
<signal name="progressChanged"/>
<signal name="propertyNamesChanged"/>
@@ -1889,9 +1889,9 @@
</exports>
</type>
<type name="QDeclarativeGalleryStringFilter" extends="QDeclarativeGalleryFilterBase">
- <property name="property" type="string"/>
- <property name="value" type="string"/>
- <property name="negated" type="bool"/>
+ <property name="property" type="string" isWritable="true"/>
+ <property name="value" type="string" isWritable="true"/>
+ <property name="negated" type="bool" isWritable="true"/>
<signal name="propertyNameChanged"/>
<signal name="valueChanged"/>
<signal name="negatedChanged"/>
@@ -1908,10 +1908,10 @@
</enum>
<property name="status" type="Status"/>
<property name="progress" type="qreal"/>
- <property name="properties" type="QStringList"/>
- <property name="autoUpdate" type="bool"/>
+ <property name="properties" type="QStringList" isWritable="true"/>
+ <property name="autoUpdate" type="bool" isWritable="true"/>
<property name="available" type="bool"/>
- <property name="metaData" type="QObject"/>
+ <property name="metaData" type="QObject" isPointer="true"/>
<signal name="statusChanged"/>
<signal name="progressChanged"/>
<signal name="availableChanged"/>
@@ -1924,9 +1924,9 @@
<method name="clear"/>
</type>
<type name="QDeclarativeGalleryValueFilter" extends="QDeclarativeGalleryFilterBase">
- <property name="property" type="string"/>
- <property name="value" type="QVariant"/>
- <property name="negated" type="bool"/>
+ <property name="property" type="string" isWritable="true"/>
+ <property name="value" type="QVariant" isWritable="true"/>
+ <property name="negated" type="bool" isWritable="true"/>
<signal name="propertyNameChanged"/>
<signal name="valueChanged"/>
<signal name="negatedChanged"/>
@@ -1949,14 +1949,14 @@
<exports>
<export module="QtMobility.location" version="1.1" type="Address"/>
</exports>
- <property name="country" type="string"/>
- <property name="countryCode" type="string"/>
- <property name="state" type="string"/>
- <property name="county" type="string"/>
- <property name="city" type="string"/>
- <property name="district" type="string"/>
- <property name="street" type="string"/>
- <property name="postcode" type="string"/>
+ <property name="country" type="string" isWritable="true"/>
+ <property name="countryCode" type="string" isWritable="true"/>
+ <property name="state" type="string" isWritable="true"/>
+ <property name="county" type="string" isWritable="true"/>
+ <property name="city" type="string" isWritable="true"/>
+ <property name="district" type="string" isWritable="true"/>
+ <property name="street" type="string" isWritable="true"/>
+ <property name="postcode" type="string" isWritable="true"/>
<signal name="countryChanged"/>
<signal name="countryCodeChanged"/>
<signal name="stateChanged"/>
@@ -1970,13 +1970,13 @@
<exports>
<export module="QtMobility.location" version="1.1" type="BoundingBox"/>
</exports>
- <property name="bottomLeft" type="QDeclarativeCoordinate"/>
- <property name="bottomRight" type="QDeclarativeCoordinate"/>
- <property name="topLeft" type="QDeclarativeCoordinate"/>
- <property name="topRight" type="QDeclarativeCoordinate"/>
- <property name="center" type="QDeclarativeCoordinate"/>
- <property name="height" type="double"/>
- <property name="width" type="double"/>
+ <property name="bottomLeft" type="QDeclarativeCoordinate" isWritable="true" isPointer="true"/>
+ <property name="bottomRight" type="QDeclarativeCoordinate" isWritable="true" isPointer="true"/>
+ <property name="topLeft" type="QDeclarativeCoordinate" isWritable="true" isPointer="true"/>
+ <property name="topRight" type="QDeclarativeCoordinate" isWritable="true" isPointer="true"/>
+ <property name="center" type="QDeclarativeCoordinate" isWritable="true" isPointer="true"/>
+ <property name="height" type="double" isWritable="true"/>
+ <property name="width" type="double" isWritable="true"/>
<signal name="bottomLeftChanged"/>
<signal name="bottomRightChanged"/>
<signal name="topLeftChanged"/>
@@ -1989,11 +1989,11 @@
<exports>
<export module="QtMobility.location" version="1.1" type="MapCircle"/>
</exports>
- <property name="center" type="QDeclarativeCoordinate"/>
- <property name="color" type="QColor"/>
- <property name="border" type="QDeclarativeGeoMapObjectBorder"/>
+ <property name="center" type="QDeclarativeCoordinate" isWritable="true" isPointer="true"/>
+ <property name="color" type="QColor" isWritable="true"/>
+ <property name="border" type="QDeclarativeGeoMapObjectBorder" isPointer="true"/>
<signal name="declarativeCenterChanged">
- <param name="center" type="const QDeclarativeCoordinate"/>
+ <param name="center" type="const QDeclarativeCoordinate" isPointer="true"/>
</signal>
<signal name="colorChanged">
<param name="color" type="QColor"/>
@@ -2006,8 +2006,8 @@
<property name="objects" type="QGeoMapObject" isList="true"/>
</type>
<type name="QDeclarativeGeoMapObjectBorder" extends="QObject">
- <property name="color" type="QColor"/>
- <property name="width" type="int"/>
+ <property name="color" type="QColor" isWritable="true"/>
+ <property name="width" type="int" isWritable="true"/>
<signal name="colorChanged">
<param name="color" type="QColor"/>
</signal>
@@ -2025,11 +2025,11 @@
<enumerator name="Loading" value="2"/>
<enumerator name="Error" value="3"/>
</enum>
- <property name="coordinate" type="QDeclarativeCoordinate"/>
- <property name="source" type="QUrl"/>
+ <property name="coordinate" type="QDeclarativeCoordinate" isWritable="true" isPointer="true"/>
+ <property name="source" type="QUrl" isWritable="true"/>
<property name="status" type="Status"/>
<signal name="declarativeCoordinateChanged">
- <param name="coordinate" type="const QDeclarativeCoordinate"/>
+ <param name="coordinate" type="const QDeclarativeCoordinate" isPointer="true"/>
</signal>
<signal name="sourceChanged">
<param name="source" type="QUrl"/>
@@ -2043,8 +2043,8 @@
<export module="QtMobility.location" version="1.1" type="MapPolygon"/>
</exports>
<property name="path" type="QDeclarativeCoordinate" isList="true"/>
- <property name="color" type="QColor"/>
- <property name="border" type="QDeclarativeGeoMapObjectBorder"/>
+ <property name="color" type="QColor" isWritable="true"/>
+ <property name="border" type="QDeclarativeGeoMapObjectBorder" isPointer="true"/>
<signal name="colorChanged">
<param name="color" type="QColor"/>
</signal>
@@ -2054,21 +2054,21 @@
<export module="QtMobility.location" version="1.1" type="MapPolyline"/>
</exports>
<property name="path" type="QDeclarativeCoordinate" isList="true"/>
- <property name="border" type="QDeclarativeGeoMapObjectBorder"/>
+ <property name="border" type="QDeclarativeGeoMapObjectBorder" isPointer="true"/>
</type>
<type name="QDeclarativeGeoMapRectangleObject" extends="QGeoMapRectangleObject">
<exports>
<export module="QtMobility.location" version="1.1" type="MapRectangle"/>
</exports>
- <property name="topLeft" type="QDeclarativeCoordinate"/>
- <property name="bottomRight" type="QDeclarativeCoordinate"/>
- <property name="color" type="QColor"/>
- <property name="border" type="QDeclarativeGeoMapObjectBorder"/>
+ <property name="topLeft" type="QDeclarativeCoordinate" isWritable="true" isPointer="true"/>
+ <property name="bottomRight" type="QDeclarativeCoordinate" isWritable="true" isPointer="true"/>
+ <property name="color" type="QColor" isWritable="true"/>
+ <property name="border" type="QDeclarativeGeoMapObjectBorder" isPointer="true"/>
<signal name="declarativeTopLeftChanged">
- <param name="center" type="const QDeclarativeCoordinate"/>
+ <param name="center" type="const QDeclarativeCoordinate" isPointer="true"/>
</signal>
<signal name="declarativeBottomRightChanged">
- <param name="center" type="const QDeclarativeCoordinate"/>
+ <param name="center" type="const QDeclarativeCoordinate" isPointer="true"/>
</signal>
<signal name="colorChanged">
<param name="color" type="QColor"/>
@@ -2088,12 +2088,12 @@
<enumerator name="AlignTop" value="32"/>
<enumerator name="AlignBottom" value="64"/>
</enum>
- <property name="coordinate" type="QDeclarativeCoordinate"/>
- <property name="color" type="QColor"/>
- <property name="horizontalAlignment" type="HorizontalAlignment"/>
- <property name="verticalAlignment" type="VerticalAlignment"/>
+ <property name="coordinate" type="QDeclarativeCoordinate" isWritable="true" isPointer="true"/>
+ <property name="color" type="QColor" isWritable="true"/>
+ <property name="horizontalAlignment" type="HorizontalAlignment" isWritable="true"/>
+ <property name="verticalAlignment" type="VerticalAlignment" isWritable="true"/>
<signal name="declarativeCoordinateChanged">
- <param name="coordinate" type="const QDeclarativeCoordinate"/>
+ <param name="coordinate" type="const QDeclarativeCoordinate" isPointer="true"/>
</signal>
<signal name="colorChanged">
<param name="color" type="QColor"/>
@@ -2109,18 +2109,18 @@
<exports>
<export module="QtMobility.location" version="1.1" type="Place"/>
</exports>
- <property name="viewport" type="QDeclarativeGeoBoundingBox"/>
- <property name="coordinate" type="QDeclarativeCoordinate"/>
- <property name="address" type="QDeclarativeGeoAddress"/>
+ <property name="viewport" type="QDeclarativeGeoBoundingBox" isWritable="true" isPointer="true"/>
+ <property name="coordinate" type="QDeclarativeCoordinate" isWritable="true" isPointer="true"/>
+ <property name="address" type="QDeclarativeGeoAddress" isWritable="true" isPointer="true"/>
<signal name="viewportChanged"/>
<signal name="coordinateChanged"/>
<signal name="addressChanged"/>
</type>
<type name="QDeclarativeGeoSearchModel" extends="QAbstractListModel">
- <property name="plugin" type="QDeclarativeGeoServiceProvider"/>
+ <property name="plugin" type="QDeclarativeGeoServiceProvider" isWritable="true" isPointer="true"/>
<property name="error" type="string"/>
<signal name="pluginChanged">
- <param name="plugin" type="QDeclarativeGeoServiceProvider"/>
+ <param name="plugin" type="QDeclarativeGeoServiceProvider" isPointer="true"/>
</signal>
<signal name="errorChanged">
<param name="error" type="string"/>
@@ -2131,7 +2131,7 @@
<exports>
<export module="QtMobility.location" version="1.1" type="Plugin"/>
</exports>
- <property name="name" type="string"/>
+ <property name="name" type="string" isWritable="true"/>
<property name="parameters" type="QDeclarativeGeoServiceProviderParameter" isList="true"/>
<signal name="nameChanged">
<param name="name" type="string"/>
@@ -2141,8 +2141,8 @@
<exports>
<export module="QtMobility.location" version="1.1" type="PluginParameter"/>
</exports>
- <property name="name" type="string"/>
- <property name="value" type="QVariant"/>
+ <property name="name" type="string" isWritable="true"/>
+ <property name="value" type="QVariant" isWritable="true"/>
<signal name="nameChanged">
<param name="name" type="string"/>
</signal>
@@ -2154,16 +2154,16 @@
<exports>
<export module="QtMobility.location" version="1.1" type="GeocodeModel"/>
</exports>
- <property name="address" type="QDeclarativeGeoAddress"/>
+ <property name="address" type="QDeclarativeGeoAddress" isWritable="true" isPointer="true"/>
<signal name="addressChanged">
- <param name="address" type="QDeclarativeGeoAddress"/>
+ <param name="address" type="QDeclarativeGeoAddress" isPointer="true"/>
</signal>
</type>
<type name="QDeclarativeGestureArea" defaultProperty="data" extends="QDeclarativeItem">
<exports>
<export module="Qt.labs.gestures" version="1.0" type="GestureArea"/>
</exports>
- <property name="gesture" type="QGesture"/>
+ <property name="gesture" type="QGesture" isPointer="true"/>
</type>
<type name="QDeclarativeGradient" defaultProperty="stops" extends="QObject">
<exports>
@@ -2178,8 +2178,8 @@
<export module="Qt" version="4.7" type="GradientStop"/>
<export module="QtQuick" version="1.0" type="GradientStop"/>
</exports>
- <property name="position" type="qreal"/>
- <property name="color" type="QColor"/>
+ <property name="position" type="qreal" isWritable="true"/>
+ <property name="color" type="QColor" isWritable="true"/>
</type>
<type name="QDeclarativeGraphicsGeoMap" defaultProperty="objects" extends="QDeclarativeItem">
<exports>
@@ -2198,17 +2198,17 @@
<enumerator name="OnlineMode" value="2"/>
<enumerator name="HybridMode" value="3"/>
</enum>
- <property name="plugin" type="QDeclarativeGeoServiceProvider"/>
- <property name="size" type="QSizeF"/>
+ <property name="plugin" type="QDeclarativeGeoServiceProvider" isWritable="true" isPointer="true"/>
+ <property name="size" type="QSizeF" isWritable="true"/>
<property name="minimumZoomLevel" type="qreal"/>
<property name="maximumZoomLevel" type="qreal"/>
- <property name="zoomLevel" type="qreal"/>
- <property name="mapType" type="MapType"/>
- <property name="center" type="QDeclarativeCoordinate"/>
- <property name="connectivityMode" type="ConnectivityMode"/>
+ <property name="zoomLevel" type="qreal" isWritable="true"/>
+ <property name="mapType" type="MapType" isWritable="true"/>
+ <property name="center" type="QDeclarativeCoordinate" isWritable="true" isPointer="true"/>
+ <property name="connectivityMode" type="ConnectivityMode" isWritable="true"/>
<property name="objects" type="QGeoMapObject" isList="true"/>
<signal name="pluginChanged">
- <param name="plugin" type="QDeclarativeGeoServiceProvider"/>
+ <param name="plugin" type="QDeclarativeGeoServiceProvider" isPointer="true"/>
</signal>
<signal name="sizeChanged">
<param name="size" type="QSizeF"/>
@@ -2217,7 +2217,7 @@
<param name="zoomLevel" type="qreal"/>
</signal>
<signal name="declarativeCenterChanged">
- <param name="coordinate" type="const QDeclarativeCoordinate"/>
+ <param name="coordinate" type="const QDeclarativeCoordinate" isPointer="true"/>
</signal>
<signal name="mapTypeChanged">
<param name="mapType" type="QDeclarativeGraphicsGeoMap.MapType"/>
@@ -2233,7 +2233,7 @@
<param name="screenPosition" type="QPointF"/>
</method>
<method name="toScreenPosition" type="QPointF">
- <param name="coordinate" type="QDeclarativeCoordinate"/>
+ <param name="coordinate" type="QDeclarativeCoordinate" isPointer="true"/>
</method>
</type>
<type name="QDeclarativeGrid" defaultProperty="data" extends="QDeclarativeBasePositioner">
@@ -2245,9 +2245,9 @@
<enumerator name="LeftToRight" value="0"/>
<enumerator name="TopToBottom" value="1"/>
</enum>
- <property name="rows" type="int"/>
- <property name="columns" type="int"/>
- <property name="flow" type="Flow"/>
+ <property name="rows" type="int" isWritable="true"/>
+ <property name="columns" type="int" isWritable="true"/>
+ <property name="flow" type="Flow" isWritable="true"/>
<signal name="rowsChanged"/>
<signal name="columnsChanged"/>
<signal name="flowChanged"/>
@@ -2278,26 +2278,26 @@
<enumerator name="Visible" value="3"/>
<enumerator name="Contain" value="4"/>
</enum>
- <property name="model" type="QVariant"/>
- <property name="delegate" type="QDeclarativeComponent"/>
- <property name="currentIndex" type="int"/>
- <property name="currentItem" type="QDeclarativeItem"/>
+ <property name="model" type="QVariant" isWritable="true"/>
+ <property name="delegate" type="QDeclarativeComponent" isWritable="true" isPointer="true"/>
+ <property name="currentIndex" type="int" isWritable="true"/>
+ <property name="currentItem" type="QDeclarativeItem" isPointer="true"/>
<property name="count" type="int"/>
- <property name="highlight" type="QDeclarativeComponent"/>
- <property name="highlightItem" type="QDeclarativeItem"/>
- <property name="highlightFollowsCurrentItem" type="bool"/>
- <property name="highlightMoveDuration" type="int"/>
- <property name="preferredHighlightBegin" type="qreal"/>
- <property name="preferredHighlightEnd" type="qreal"/>
- <property name="highlightRangeMode" type="HighlightRangeMode"/>
- <property name="flow" type="Flow"/>
- <property name="keyNavigationWraps" type="bool"/>
- <property name="cacheBuffer" type="int"/>
- <property name="cellWidth" type="int"/>
- <property name="cellHeight" type="int"/>
- <property name="snapMode" type="SnapMode"/>
- <property name="header" type="QDeclarativeComponent"/>
- <property name="footer" type="QDeclarativeComponent"/>
+ <property name="highlight" type="QDeclarativeComponent" isWritable="true" isPointer="true"/>
+ <property name="highlightItem" type="QDeclarativeItem" isPointer="true"/>
+ <property name="highlightFollowsCurrentItem" type="bool" isWritable="true"/>
+ <property name="highlightMoveDuration" type="int" isWritable="true"/>
+ <property name="preferredHighlightBegin" type="qreal" isWritable="true"/>
+ <property name="preferredHighlightEnd" type="qreal" isWritable="true"/>
+ <property name="highlightRangeMode" type="HighlightRangeMode" isWritable="true"/>
+ <property name="flow" type="Flow" isWritable="true"/>
+ <property name="keyNavigationWraps" type="bool" isWritable="true"/>
+ <property name="cacheBuffer" type="int" isWritable="true"/>
+ <property name="cellWidth" type="int" isWritable="true"/>
+ <property name="cellHeight" type="int" isWritable="true"/>
+ <property name="snapMode" type="SnapMode" isWritable="true"/>
+ <property name="header" type="QDeclarativeComponent" isWritable="true" isPointer="true"/>
+ <property name="footer" type="QDeclarativeComponent" isWritable="true" isPointer="true"/>
<signal name="countChanged"/>
<signal name="currentIndexChanged"/>
<signal name="cellWidthChanged"/>
@@ -2334,8 +2334,8 @@
<export module="QtMobility.feedback" version="1.1" type="HapticsEffect"/>
</exports>
<property name="actuators" type="QFeedbackActuator" isList="true"/>
- <property name="running" type="bool"/>
- <property name="paused" type="bool"/>
+ <property name="running" type="bool" isWritable="true"/>
+ <property name="paused" type="bool" isWritable="true"/>
<signal name="runningChanged"/>
<signal name="pausedChanged"/>
<signal name="actuatorsChanged"/>
@@ -2354,7 +2354,7 @@
<enumerator name="TileVertically" value="4"/>
<enumerator name="TileHorizontally" value="5"/>
</enum>
- <property name="fillMode" type="FillMode"/>
+ <property name="fillMode" type="FillMode" isWritable="true"/>
<property name="paintedWidth" type="qreal"/>
<property name="paintedHeight" type="qreal"/>
<signal name="fillModeChanged"/>
@@ -2368,10 +2368,10 @@
<enumerator name="Error" value="3"/>
</enum>
<property name="status" type="Status"/>
- <property name="source" type="QUrl"/>
+ <property name="source" type="QUrl" isWritable="true"/>
<property name="progress" type="qreal"/>
- <property name="asynchronous" type="bool"/>
- <property name="sourceSize" type="QSize"/>
+ <property name="asynchronous" type="bool" isWritable="true"/>
+ <property name="sourceSize" type="QSize" isWritable="true"/>
<signal name="sourceChanged">
<param type="QUrl"/>
</signal>
@@ -2400,14 +2400,14 @@
<enumerator name="Bottom" value="7"/>
<enumerator name="BottomRight" value="8"/>
</enum>
- <property name="parent" type="QDeclarativeItem"/>
+ <property name="parent" type="QDeclarativeItem" isWritable="true" isPointer="true"/>
<property name="data" type="QObject" isList="true"/>
<property name="resources" type="QObject" isList="true"/>
<property name="states" type="QDeclarativeState" isList="true"/>
<property name="transitions" type="QDeclarativeTransition" isList="true"/>
- <property name="state" type="string"/>
+ <property name="state" type="string" isWritable="true"/>
<property name="childrenRect" type="QRectF"/>
- <property name="anchors" type="QDeclarativeAnchors"/>
+ <property name="anchors" type="QDeclarativeAnchors" isPointer="true"/>
<property name="left" type="QDeclarativeAnchorLine"/>
<property name="right" type="QDeclarativeAnchorLine"/>
<property name="horizontalCenter" type="QDeclarativeAnchorLine"/>
@@ -2415,14 +2415,14 @@
<property name="bottom" type="QDeclarativeAnchorLine"/>
<property name="verticalCenter" type="QDeclarativeAnchorLine"/>
<property name="baseline" type="QDeclarativeAnchorLine"/>
- <property name="baselineOffset" type="qreal"/>
- <property name="clip" type="bool"/>
- <property name="focus" type="bool"/>
+ <property name="baselineOffset" type="qreal" isWritable="true"/>
+ <property name="clip" type="bool" isWritable="true"/>
+ <property name="focus" type="bool" isWritable="true"/>
<property name="activeFocus" type="bool"/>
<property name="transform" type="QGraphicsTransform" isList="true"/>
- <property name="transformOrigin" type="TransformOrigin"/>
+ <property name="transformOrigin" type="TransformOrigin" isWritable="true"/>
<property name="transformOriginPoint" type="QPointF"/>
- <property name="smooth" type="bool"/>
+ <property name="smooth" type="bool" isWritable="true"/>
<signal name="childrenRectChanged">
<param type="QRectF"/>
</signal>
@@ -2439,7 +2439,7 @@
<param type="bool"/>
</signal>
<signal name="parentChanged">
- <param type="QDeclarativeItem"/>
+ <param type="QDeclarativeItem" isPointer="true"/>
</signal>
<signal name="transformOriginChanged">
<param type="TransformOrigin"/>
@@ -2475,13 +2475,13 @@
<enumerator name="BeforeItem" value="0"/>
<enumerator name="AfterItem" value="1"/>
</enum>
- <property name="left" type="QDeclarativeItem"/>
- <property name="right" type="QDeclarativeItem"/>
- <property name="up" type="QDeclarativeItem"/>
- <property name="down" type="QDeclarativeItem"/>
- <property name="tab" type="QDeclarativeItem"/>
- <property name="backtab" type="QDeclarativeItem"/>
- <property name="priority" type="Priority"/>
+ <property name="left" type="QDeclarativeItem" isWritable="true" isPointer="true"/>
+ <property name="right" type="QDeclarativeItem" isWritable="true" isPointer="true"/>
+ <property name="up" type="QDeclarativeItem" isWritable="true" isPointer="true"/>
+ <property name="down" type="QDeclarativeItem" isWritable="true" isPointer="true"/>
+ <property name="tab" type="QDeclarativeItem" isWritable="true" isPointer="true"/>
+ <property name="backtab" type="QDeclarativeItem" isWritable="true" isPointer="true"/>
+ <property name="priority" type="Priority" isWritable="true"/>
<signal name="leftChanged"/>
<signal name="rightChanged"/>
<signal name="upChanged"/>
@@ -2499,142 +2499,142 @@
<enumerator name="BeforeItem" value="0"/>
<enumerator name="AfterItem" value="1"/>
</enum>
- <property name="enabled" type="bool"/>
+ <property name="enabled" type="bool" isWritable="true"/>
<property name="forwardTo" type="QDeclarativeItem" isList="true"/>
- <property name="priority" type="Priority"/>
+ <property name="priority" type="Priority" isWritable="true"/>
<signal name="enabledChanged"/>
<signal name="priorityChanged"/>
<signal name="pressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="released">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="digit0Pressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="digit1Pressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="digit2Pressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="digit3Pressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="digit4Pressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="digit5Pressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="digit6Pressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="digit7Pressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="digit8Pressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="digit9Pressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="leftPressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="rightPressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="upPressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="downPressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="tabPressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="backtabPressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="asteriskPressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="numberSignPressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="escapePressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="returnPressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="enterPressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="deletePressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="spacePressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="backPressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="cancelPressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="selectPressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="yesPressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="noPressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="context1Pressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="context2Pressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="context3Pressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="context4Pressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="callPressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="hangupPressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="flipPressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="menuPressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="volumeUpPressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
<signal name="volumeDownPressed">
- <param name="event" type="QDeclarativeKeyEvent"/>
+ <param name="event" type="QDeclarativeKeyEvent" isPointer="true"/>
</signal>
</type>
<type name="QDeclarativeLandmark" extends="QDeclarativeGeoPlace">
<exports>
<export module="QtMobility.location" version="1.1" type="Landmark"/>
</exports>
- <property name="name" type="string"/>
- <property name="phoneNumber" type="string"/>
- <property name="description" type="string"/>
- <property name="radius" type="double"/>
- <property name="iconSource" type="QUrl"/>
- <property name="url" type="QUrl"/>
+ <property name="name" type="string" isWritable="true"/>
+ <property name="phoneNumber" type="string" isWritable="true"/>
+ <property name="description" type="string" isWritable="true"/>
+ <property name="radius" type="double" isWritable="true"/>
+ <property name="iconSource" type="QUrl" isWritable="true"/>
+ <property name="url" type="QUrl" isWritable="true"/>
<signal name="nameChanged"/>
<signal name="phoneNumberChanged"/>
<signal name="descriptionChanged"/>
@@ -2656,12 +2656,12 @@
<enumerator name="NoSort" value="0"/>
<enumerator name="NameSort" value="1"/>
</enum>
- <property name="limit" type="int"/>
- <property name="offset" type="int"/>
- <property name="autoUpdate" type="bool"/>
+ <property name="limit" type="int" isWritable="true"/>
+ <property name="offset" type="int" isWritable="true"/>
+ <property name="autoUpdate" type="bool" isWritable="true"/>
<property name="error" type="string"/>
- <property name="sortBy" type="SortKey"/>
- <property name="sortOrder" type="SortOrder"/>
+ <property name="sortBy" type="SortKey" isWritable="true"/>
+ <property name="sortOrder" type="SortOrder" isWritable="true"/>
<signal name="sortByChanged"/>
<signal name="sortOrderChanged"/>
<signal name="errorChanged"/>
@@ -2679,8 +2679,8 @@
<exports>
<export module="QtMobility.location" version="1.1" type="LandmarkBoxFilter"/>
</exports>
- <property name="topLeft" type="QDeclarativeCoordinate"/>
- <property name="bottomRight" type="QDeclarativeCoordinate"/>
+ <property name="topLeft" type="QDeclarativeCoordinate" isWritable="true" isPointer="true"/>
+ <property name="bottomRight" type="QDeclarativeCoordinate" isWritable="true" isPointer="true"/>
<signal name="topLeftChanged"/>
<signal name="bottomRightChanged"/>
</type>
@@ -2688,8 +2688,8 @@
<exports>
<export module="QtMobility.location" version="1.1" type="LandmarkCategory"/>
</exports>
- <property name="name" type="string"/>
- <property name="iconSource" type="QUrl"/>
+ <property name="name" type="string" isWritable="true"/>
+ <property name="iconSource" type="QUrl" isWritable="true"/>
<signal name="nameChanged"/>
<signal name="iconSourceChanged"/>
</type>
@@ -2697,7 +2697,7 @@
<exports>
<export module="QtMobility.location" version="1.1" type="LandmarkCategoryFilter"/>
</exports>
- <property name="category" type="QDeclarativeLandmarkCategory"/>
+ <property name="category" type="QDeclarativeLandmarkCategory" isWritable="true" isPointer="true"/>
<signal name="categoryChanged"/>
</type>
<type name="QDeclarativeLandmarkCategoryModel" extends="QDeclarativeLandmarkAbstractModel">
@@ -2705,7 +2705,7 @@
<export module="QtMobility.location" version="1.1" type="LandmarkCategoryModel"/>
</exports>
<property name="count" type="int"/>
- <property name="landmark" type="QDeclarativeLandmark"/>
+ <property name="landmark" type="QDeclarativeLandmark" isWritable="true" isPointer="true"/>
<property name="categories" type="QDeclarativeLandmarkCategory" isList="true"/>
<signal name="countChanged"/>
<signal name="landmarkChanged"/>
@@ -2730,9 +2730,9 @@
<export module="QtMobility.location" version="1.1" type="LandmarkModel"/>
</exports>
<property name="count" type="int"/>
- <property name="filter" type="QDeclarativeLandmarkFilterBase"/>
+ <property name="filter" type="QDeclarativeLandmarkFilterBase" isWritable="true" isPointer="true"/>
<property name="landmarks" type="QDeclarativeLandmark" isList="true"/>
- <property name="importFile" type="string"/>
+ <property name="importFile" type="string" isWritable="true"/>
<signal name="countChanged"/>
<signal name="filterChanged"/>
<signal name="landmarksChanged"/>
@@ -2743,15 +2743,15 @@
<exports>
<export module="QtMobility.location" version="1.1" type="LandmarkNameFilter"/>
</exports>
- <property name="name" type="string"/>
+ <property name="name" type="string" isWritable="true"/>
<signal name="nameChanged"/>
</type>
<type name="QDeclarativeLandmarkProximityFilter" extends="QDeclarativeLandmarkFilterBase">
<exports>
<export module="QtMobility.location" version="1.1" type="LandmarkProximityFilter"/>
</exports>
- <property name="center" type="QDeclarativeCoordinate"/>
- <property name="radius" type="double"/>
+ <property name="center" type="QDeclarativeCoordinate" isWritable="true" isPointer="true"/>
+ <property name="radius" type="double" isWritable="true"/>
<signal name="radiusChanged"/>
<signal name="centerChanged"/>
</type>
@@ -2765,9 +2765,9 @@
<export module="Qt" version="4.7" type="LayoutItem"/>
<export module="QtQuick" version="1.0" type="LayoutItem"/>
</exports>
- <property name="maximumSize" type="QSizeF"/>
- <property name="minimumSize" type="QSizeF"/>
- <property name="preferredSize" type="QSizeF"/>
+ <property name="maximumSize" type="QSizeF" isWritable="true"/>
+ <property name="minimumSize" type="QSizeF" isWritable="true"/>
+ <property name="preferredSize" type="QSizeF" isWritable="true"/>
<signal name="maximumSizeChanged"/>
<signal name="minimumSizeChanged"/>
<signal name="preferredSizeChanged"/>
@@ -2841,30 +2841,30 @@
<enumerator name="Visible" value="3"/>
<enumerator name="Contain" value="4"/>
</enum>
- <property name="model" type="QVariant"/>
- <property name="delegate" type="QDeclarativeComponent"/>
- <property name="currentIndex" type="int"/>
- <property name="currentItem" type="QDeclarativeItem"/>
+ <property name="model" type="QVariant" isWritable="true"/>
+ <property name="delegate" type="QDeclarativeComponent" isWritable="true" isPointer="true"/>
+ <property name="currentIndex" type="int" isWritable="true"/>
+ <property name="currentItem" type="QDeclarativeItem" isPointer="true"/>
<property name="count" type="int"/>
- <property name="highlight" type="QDeclarativeComponent"/>
- <property name="highlightItem" type="QDeclarativeItem"/>
- <property name="highlightFollowsCurrentItem" type="bool"/>
- <property name="highlightMoveSpeed" type="qreal"/>
- <property name="highlightMoveDuration" type="int"/>
- <property name="highlightResizeSpeed" type="qreal"/>
- <property name="highlightResizeDuration" type="int"/>
- <property name="preferredHighlightBegin" type="qreal"/>
- <property name="preferredHighlightEnd" type="qreal"/>
- <property name="highlightRangeMode" type="HighlightRangeMode"/>
- <property name="spacing" type="qreal"/>
- <property name="orientation" type="Orientation"/>
- <property name="keyNavigationWraps" type="bool"/>
- <property name="cacheBuffer" type="int"/>
- <property name="section" type="QDeclarativeViewSection"/>
+ <property name="highlight" type="QDeclarativeComponent" isWritable="true" isPointer="true"/>
+ <property name="highlightItem" type="QDeclarativeItem" isPointer="true"/>
+ <property name="highlightFollowsCurrentItem" type="bool" isWritable="true"/>
+ <property name="highlightMoveSpeed" type="qreal" isWritable="true"/>
+ <property name="highlightMoveDuration" type="int" isWritable="true"/>
+ <property name="highlightResizeSpeed" type="qreal" isWritable="true"/>
+ <property name="highlightResizeDuration" type="int" isWritable="true"/>
+ <property name="preferredHighlightBegin" type="qreal" isWritable="true"/>
+ <property name="preferredHighlightEnd" type="qreal" isWritable="true"/>
+ <property name="highlightRangeMode" type="HighlightRangeMode" isWritable="true"/>
+ <property name="spacing" type="qreal" isWritable="true"/>
+ <property name="orientation" type="Orientation" isWritable="true"/>
+ <property name="keyNavigationWraps" type="bool" isWritable="true"/>
+ <property name="cacheBuffer" type="int" isWritable="true"/>
+ <property name="section" type="QDeclarativeViewSection" isPointer="true"/>
<property name="currentSection" type="string"/>
- <property name="snapMode" type="SnapMode"/>
- <property name="header" type="QDeclarativeComponent"/>
- <property name="footer" type="QDeclarativeComponent"/>
+ <property name="snapMode" type="SnapMode" isWritable="true"/>
+ <property name="header" type="QDeclarativeComponent" isWritable="true" isPointer="true"/>
+ <property name="footer" type="QDeclarativeComponent" isWritable="true" isPointer="true"/>
<signal name="countChanged"/>
<signal name="spacingChanged"/>
<signal name="orientationChanged"/>
@@ -2909,9 +2909,9 @@
<enumerator name="Loading" value="2"/>
<enumerator name="Error" value="3"/>
</enum>
- <property name="source" type="QUrl"/>
- <property name="sourceComponent" type="QDeclarativeComponent"/>
- <property name="item" type="QGraphicsObject"/>
+ <property name="source" type="QUrl" isWritable="true"/>
+ <property name="sourceComponent" type="QDeclarativeComponent" isWritable="true" isPointer="true"/>
+ <property name="item" type="QGraphicsObject" isPointer="true"/>
<property name="status" type="Status"/>
<property name="progress" type="qreal"/>
<signal name="itemChanged"/>
@@ -2966,9 +2966,9 @@
<enumerator name="Incoming" value="4"/>
<enumerator name="Removed" value="8"/>
</enum>
- <property name="type" type="FilterType"/>
- <property name="value" type="QVariant"/>
- <property name="comparator" type="Comparator"/>
+ <property name="type" type="FilterType" isWritable="true"/>
+ <property name="value" type="QVariant" isWritable="true"/>
+ <property name="comparator" type="Comparator" isWritable="true"/>
<signal name="typeChanged"/>
<signal name="valueChanged"/>
<signal name="comparatorChanged"/>
@@ -2977,7 +2977,7 @@
<exports>
<export module="QtMobility.messaging" version="1.1" type="MessageFilterBase"/>
</exports>
- <property name="negated" type="bool"/>
+ <property name="negated" type="bool" isWritable="true"/>
<signal name="negatedChanged"/>
</type>
<type name="QDeclarativeMessageIntersectionFilter" defaultProperty="filters" extends="QDeclarativeMessageFilterBase">
@@ -3006,11 +3006,11 @@
<enumerator name="AscendingOrder" value="0"/>
<enumerator name="DescendingOrder" value="1"/>
</enum>
- <property name="filter" type="QDeclarativeMessageFilterBase"/>
- <property name="sortBy" type="SortKey"/>
- <property name="sortOrder" type="SortOrder"/>
+ <property name="filter" type="QDeclarativeMessageFilterBase" isWritable="true" isPointer="true"/>
+ <property name="sortBy" type="SortKey" isWritable="true"/>
+ <property name="sortOrder" type="SortOrder" isWritable="true"/>
<property name="count" type="int"/>
- <property name="limit" type="int"/>
+ <property name="limit" type="int" isWritable="true"/>
<signal name="filterChanged"/>
<signal name="sortByChanged"/>
<signal name="sortOrderChanged"/>
@@ -3039,36 +3039,36 @@
<property name="mouseY" type="qreal"/>
<property name="containsMouse" type="bool"/>
<property name="pressed" type="bool"/>
- <property name="enabled" type="bool"/>
+ <property name="enabled" type="bool" isWritable="true"/>
<property name="pressedButtons" type="Qt.MouseButtons"/>
- <property name="acceptedButtons" type="Qt.MouseButtons"/>
- <property name="hoverEnabled" type="bool"/>
- <property name="drag" type="QDeclarativeDrag"/>
+ <property name="acceptedButtons" type="Qt.MouseButtons" isWritable="true"/>
+ <property name="hoverEnabled" type="bool" isWritable="true"/>
+ <property name="drag" type="QDeclarativeDrag" isPointer="true"/>
<signal name="hoveredChanged"/>
<signal name="pressedChanged"/>
<signal name="enabledChanged"/>
<signal name="acceptedButtonsChanged"/>
<signal name="hoverEnabledChanged"/>
<signal name="positionChanged">
- <param name="mouse" type="QDeclarativeMouseEvent"/>
+ <param name="mouse" type="QDeclarativeMouseEvent" isPointer="true"/>
</signal>
<signal name="mousePositionChanged">
- <param name="mouse" type="QDeclarativeMouseEvent"/>
+ <param name="mouse" type="QDeclarativeMouseEvent" isPointer="true"/>
</signal>
<signal name="pressed">
- <param name="mouse" type="QDeclarativeMouseEvent"/>
+ <param name="mouse" type="QDeclarativeMouseEvent" isPointer="true"/>
</signal>
<signal name="pressAndHold">
- <param name="mouse" type="QDeclarativeMouseEvent"/>
+ <param name="mouse" type="QDeclarativeMouseEvent" isPointer="true"/>
</signal>
<signal name="released">
- <param name="mouse" type="QDeclarativeMouseEvent"/>
+ <param name="mouse" type="QDeclarativeMouseEvent" isPointer="true"/>
</signal>
<signal name="clicked">
- <param name="mouse" type="QDeclarativeMouseEvent"/>
+ <param name="mouse" type="QDeclarativeMouseEvent" isPointer="true"/>
</signal>
<signal name="doubleClicked">
- <param name="mouse" type="QDeclarativeMouseEvent"/>
+ <param name="mouse" type="QDeclarativeMouseEvent" isPointer="true"/>
</signal>
<signal name="entered"/>
<signal name="exited"/>
@@ -3082,7 +3082,7 @@
<property name="networkName" type="string"/>
<property name="networkSignalStrength" type="int"/>
<property name="macAddress" type="string"/>
- <property name="mode" type="QSystemNetworkInfo.NetworkMode"/>
+ <property name="mode" type="QSystemNetworkInfo.NetworkMode" isWritable="true"/>
<property name="availableModes" type="QList&lt;QSystemNetworkInfo.NetworkMode&gt;"/>
<signal name="statusChanged">
<param name="newStatus" type="string"/>
@@ -3114,18 +3114,18 @@
<export module="QtQuick" version="1.0" type="NumberAnimation"/>
<export module="Qt" version="4.7" type="NumberAnimation"/>
</exports>
- <property name="from" type="qreal"/>
- <property name="to" type="qreal"/>
+ <property name="from" type="qreal" isWritable="true"/>
+ <property name="to" type="qreal" isWritable="true"/>
</type>
<type name="QDeclarativeOrganizerCollection" extends="QObject">
<exports>
<export module="QtMobility.organizer" version="1.1" type="Collection"/>
</exports>
<property name="collectionId" type="uint"/>
- <property name="name" type="string"/>
- <property name="description" type="string"/>
- <property name="color" type="QColor"/>
- <property name="image" type="QUrl"/>
+ <property name="name" type="string" isWritable="true"/>
+ <property name="description" type="string" isWritable="true"/>
+ <property name="color" type="QColor" isWritable="true"/>
+ <property name="image" type="QUrl" isWritable="true"/>
<signal name="valueChanged"/>
<method name="setMetaData">
<param name="key" type="string"/>
@@ -3139,33 +3139,33 @@
<exports>
<export module="QtMobility.organizer" version="1.1" type="Event"/>
</exports>
- <property name="startDateTime" type="QDateTime"/>
- <property name="endDateTime" type="QDateTime"/>
- <property name="allDay" type="bool"/>
- <property name="location" type="string"/>
- <property name="priority" type="QDeclarativeOrganizerItemPriority.PriorityType"/>
- <property name="recurrence" type="QDeclarativeOrganizerItemRecurrence"/>
+ <property name="startDateTime" type="QDateTime" isWritable="true"/>
+ <property name="endDateTime" type="QDateTime" isWritable="true"/>
+ <property name="allDay" type="bool" isWritable="true"/>
+ <property name="location" type="string" isWritable="true"/>
+ <property name="priority" type="QDeclarativeOrganizerItemPriority.PriorityType" isWritable="true"/>
+ <property name="recurrence" type="QDeclarativeOrganizerItemRecurrence" isPointer="true"/>
<signal name="valueChanged"/>
</type>
<type name="QDeclarativeOrganizerEventOccurrence" defaultProperty="details" extends="QDeclarativeOrganizerItem">
<exports>
<export module="QtMobility.organizer" version="1.1" type="EventOccurrence"/>
</exports>
- <property name="startDateTime" type="QDateTime"/>
- <property name="endDateTime" type="QDateTime"/>
- <property name="location" type="string"/>
- <property name="priority" type="QDeclarativeOrganizerItemPriority.PriorityType"/>
- <property name="parentId" type="uint"/>
- <property name="originalDate" type="QDate"/>
+ <property name="startDateTime" type="QDateTime" isWritable="true"/>
+ <property name="endDateTime" type="QDateTime" isWritable="true"/>
+ <property name="location" type="string" isWritable="true"/>
+ <property name="priority" type="QDeclarativeOrganizerItemPriority.PriorityType" isWritable="true"/>
+ <property name="parentId" type="uint" isWritable="true"/>
+ <property name="originalDate" type="QDate" isWritable="true"/>
<signal name="valueChanged"/>
</type>
<type name="QDeclarativeOrganizerEventTime" extends="QDeclarativeOrganizerItemDetail">
<exports>
<export module="QtMobility.organizer" version="1.1" type="EventTime"/>
</exports>
- <property name="startDateTime" type="QDateTime"/>
- <property name="endDateTime" type="QDateTime"/>
- <property name="isAllDay" type="bool"/>
+ <property name="startDateTime" type="QDateTime" isWritable="true"/>
+ <property name="endDateTime" type="QDateTime" isWritable="true"/>
+ <property name="isAllDay" type="bool" isWritable="true"/>
<signal name="valueChanged"/>
</type>
<type name="QDeclarativeOrganizerItem" defaultProperty="details" extends="QObject">
@@ -3185,9 +3185,9 @@
<property name="manager" type="string"/>
<property name="itemId" type="uint"/>
<property name="type" type="string"/>
- <property name="displayLabel" type="string"/>
- <property name="description" type="string"/>
- <property name="guid" type="string"/>
+ <property name="displayLabel" type="string" isWritable="true"/>
+ <property name="description" type="string" isWritable="true"/>
+ <property name="guid" type="string" isWritable="true"/>
<property name="modified" type="bool"/>
<signal name="itemChanged"/>
<method name="save"/>
@@ -3203,7 +3203,7 @@
<param name="comment" type="string"/>
</method>
<method name="removeDetail" type="bool">
- <param name="detail" type="QDeclarativeOrganizerItemDetail"/>
+ <param name="detail" type="QDeclarativeOrganizerItemDetail" isPointer="true"/>
</method>
</type>
<type name="QDeclarativeOrganizerItemAudibleReminder" extends="QDeclarativeOrganizerItemReminder">
@@ -3213,7 +3213,7 @@
<enum name="FieldType">
<enumerator name="DataUrl" value="0"/>
</enum>
- <property name="dataUrl" type="QUrl"/>
+ <property name="dataUrl" type="QUrl" isWritable="true"/>
<signal name="valueChanged"/>
</type>
<type name="QDeclarativeOrganizerItemChangelogFilter" extends="QDeclarativeOrganizerItemFilter">
@@ -3225,15 +3225,15 @@
<enumerator name="EventChanged" value="1"/>
<enumerator name="EventRemoved" value="2"/>
</enum>
- <property name="since" type="QDateTime"/>
- <property name="eventType" type="EventType"/>
+ <property name="since" type="QDateTime" isWritable="true"/>
+ <property name="eventType" type="EventType" isWritable="true"/>
<signal name="valueChanged"/>
</type>
<type name="QDeclarativeOrganizerItemCollectionFilter" extends="QDeclarativeOrganizerItemFilter">
<exports>
<export module="QtMobility.organizer" version="1.1" type="CollectionFilter"/>
</exports>
- <property name="ids" type="QVariantList"/>
+ <property name="ids" type="QVariantList" isWritable="true"/>
<signal name="valueChanged"/>
</type>
<type name="QDeclarativeOrganizerItemDescription" extends="QDeclarativeOrganizerItemDetail">
@@ -3243,7 +3243,7 @@
<enum name="FieldType">
<enumerator name="Description" value="0"/>
</enum>
- <property name="description" type="string"/>
+ <property name="description" type="string" isWritable="true"/>
<signal name="valueChanged"/>
</type>
<type name="QDeclarativeOrganizerItemDetail" extends="QObject">
@@ -3293,10 +3293,10 @@
<exports>
<export module="QtMobility.organizer" version="1.1" type="DetailFilter"/>
</exports>
- <property name="value" type="QVariant"/>
- <property name="matchFlags" type="QDeclarativeOrganizerItemFilter.MatchFlags"/>
- <property name="detailFieldName" type="string"/>
- <property name="detailDefinitionName" type="string"/>
+ <property name="value" type="QVariant" isWritable="true"/>
+ <property name="matchFlags" type="QDeclarativeOrganizerItemFilter.MatchFlags" isWritable="true"/>
+ <property name="detailFieldName" type="string" isWritable="true"/>
+ <property name="detailDefinitionName" type="string" isWritable="true"/>
<signal name="valueChanged"/>
</type>
<type name="QDeclarativeOrganizerItemDetailRangeFilter" extends="QDeclarativeOrganizerItemFilter">
@@ -3315,12 +3315,12 @@
<enumerator name="ExcludeLower" value="2"/>
<enumerator name="ExcludeUpper" value="0"/>
</enum>
- <property name="min" type="QVariant"/>
- <property name="max" type="QVariant"/>
- <property name="matchFlags" type="QDeclarativeOrganizerItemFilter.MatchFlags"/>
- <property name="rangeFlags" type="RangeFlags"/>
- <property name="detailFieldName" type="string"/>
- <property name="detailDefinitionName" type="string"/>
+ <property name="min" type="QVariant" isWritable="true"/>
+ <property name="max" type="QVariant" isWritable="true"/>
+ <property name="matchFlags" type="QDeclarativeOrganizerItemFilter.MatchFlags" isWritable="true"/>
+ <property name="rangeFlags" type="RangeFlags" isWritable="true"/>
+ <property name="detailFieldName" type="string" isWritable="true"/>
+ <property name="detailDefinitionName" type="string" isWritable="true"/>
<signal name="valueChanged"/>
</type>
<type name="QDeclarativeOrganizerItemDisplayLabel" extends="QDeclarativeOrganizerItemDetail">
@@ -3330,7 +3330,7 @@
<enum name="FieldType">
<enumerator name="Label" value="0"/>
</enum>
- <property name="label" type="string"/>
+ <property name="label" type="string" isWritable="true"/>
<signal name="valueChanged"/>
</type>
<type name="QDeclarativeOrganizerItemEmailReminder" extends="QDeclarativeOrganizerItemReminder">
@@ -3343,10 +3343,10 @@
<enumerator name="Recipients" value="2"/>
<enumerator name="Attachments" value="3"/>
</enum>
- <property name="subject" type="string"/>
- <property name="body" type="string"/>
- <property name="recipients" type="QStringList"/>
- <property name="attachments" type="QVariantList"/>
+ <property name="subject" type="string" isWritable="true"/>
+ <property name="body" type="string" isWritable="true"/>
+ <property name="recipients" type="QStringList" isWritable="true"/>
+ <property name="attachments" type="QVariantList" isWritable="true"/>
<signal name="valueChanged"/>
</type>
<type name="QDeclarativeOrganizerItemFetchHint" extends="QObject">
@@ -3363,7 +3363,7 @@
<enumerator name="NoActionPreferences" value="2"/>
<enumerator name="NoBinaryBlobs" value="4"/>
</enum>
- <property name="optimizationHints" type="OptimizationHints"/>
+ <property name="optimizationHints" type="OptimizationHints" isWritable="true"/>
<signal name="valueChanged"/>
</type>
<type name="QDeclarativeOrganizerItemFilter" extends="QObject">
@@ -3400,14 +3400,14 @@
<enum name="FieldType">
<enumerator name="Guid" value="0"/>
</enum>
- <property name="guid" type="string"/>
+ <property name="guid" type="string" isWritable="true"/>
<signal name="valueChanged"/>
</type>
<type name="QDeclarativeOrganizerItemIdFilter" extends="QDeclarativeOrganizerItemFilter">
<exports>
<export module="QtMobility.organizer" version="1.1" type="IdFilter"/>
</exports>
- <property name="ids" type="QVariantList"/>
+ <property name="ids" type="QVariantList" isWritable="true"/>
<signal name="valueChanged"/>
</type>
<type name="QDeclarativeOrganizerItemIntersectionFilter" defaultProperty="subFilters" extends="QDeclarativeOrganizerItemFilter">
@@ -3431,9 +3431,9 @@
<enumerator name="Longitude" value="1"/>
<enumerator name="Label" value="2"/>
</enum>
- <property name="latitude" type="double"/>
- <property name="longitude" type="double"/>
- <property name="label" type="string"/>
+ <property name="latitude" type="double" isWritable="true"/>
+ <property name="longitude" type="double" isWritable="true"/>
+ <property name="label" type="string" isWritable="true"/>
<signal name="valueChanged"/>
</type>
<type name="QDeclarativeOrganizerItemParent" extends="QDeclarativeOrganizerItemDetail">
@@ -3444,8 +3444,8 @@
<enumerator name="ParentId" value="0"/>
<enumerator name="OriginalDate" value="1"/>
</enum>
- <property name="parentId" type="uint"/>
- <property name="originalDate" type="QDate"/>
+ <property name="parentId" type="uint" isWritable="true"/>
+ <property name="originalDate" type="QDate" isWritable="true"/>
<signal name="valueChanged"/>
</type>
<type name="QDeclarativeOrganizerItemPriority" extends="QDeclarativeOrganizerItemDetail">
@@ -3467,7 +3467,7 @@
<enumerator name="ExtremelyLow" value="8"/>
<enumerator name="Lowest" value="9"/>
</enum>
- <property name="priority" type="PriorityType"/>
+ <property name="priority" type="PriorityType" isWritable="true"/>
<signal name="valueChanged"/>
</type>
<type name="QDeclarativeOrganizerItemRecurrence" extends="QDeclarativeOrganizerItemDetail">
@@ -3482,8 +3482,8 @@
</enum>
<property name="recurrenceRules" type="QDeclarativeOrganizerRecurrenceRule" isList="true"/>
<property name="exceptionRules" type="QDeclarativeOrganizerRecurrenceRule" isList="true"/>
- <property name="recurrenceDates" type="QVariantList"/>
- <property name="exceptionDates" type="QVariantList"/>
+ <property name="recurrenceDates" type="QVariantList" isWritable="true"/>
+ <property name="exceptionDates" type="QVariantList" isWritable="true"/>
<signal name="recurrenceRulesChanged"/>
<signal name="exceptionRulesChanged"/>
<signal name="valueChanged"/>
@@ -3505,9 +3505,9 @@
<enumerator name="EmailReminder" value="3"/>
</enum>
<property name="reminderType" type="ReminderType"/>
- <property name="secondsBeforeStart" type="int"/>
- <property name="repetitionCount" type="int"/>
- <property name="repetitionDelay" type="int"/>
+ <property name="secondsBeforeStart" type="int" isWritable="true"/>
+ <property name="repetitionCount" type="int" isWritable="true"/>
+ <property name="repetitionDelay" type="int" isWritable="true"/>
<signal name="valueChanged"/>
</type>
<type name="QDeclarativeOrganizerItemSortOrder" extends="QObject">
@@ -3518,11 +3518,11 @@
<enumerator name="BlanksFirst" value="0"/>
<enumerator name="BlanksLast" value="1"/>
</enum>
- <property name="definitionName" type="string"/>
- <property name="fieldName" type="string"/>
- <property name="blankPolicy" type="BlankPolicy"/>
- <property name="direction" type="Qt.SortOrder"/>
- <property name="sensitivity" type="Qt.CaseSensitivity"/>
+ <property name="definitionName" type="string" isWritable="true"/>
+ <property name="fieldName" type="string" isWritable="true"/>
+ <property name="blankPolicy" type="BlankPolicy" isWritable="true"/>
+ <property name="direction" type="Qt.SortOrder" isWritable="true"/>
+ <property name="sensitivity" type="Qt.CaseSensitivity" isWritable="true"/>
<signal name="valueChanged"/>
</type>
<type name="QDeclarativeOrganizerItemTimestamp" extends="QDeclarativeOrganizerItemDetail">
@@ -3533,8 +3533,8 @@
<enumerator name="LastModified" value="0"/>
<enumerator name="Created" value="1"/>
</enum>
- <property name="lastModified" type="QDateTime"/>
- <property name="created" type="QDateTime"/>
+ <property name="lastModified" type="QDateTime" isWritable="true"/>
+ <property name="created" type="QDateTime" isWritable="true"/>
<signal name="valueChanged"/>
</type>
<type name="QDeclarativeOrganizerItemType" extends="QDeclarativeOrganizerItemDetail">
@@ -3544,7 +3544,7 @@
<enum name="FieldType">
<enumerator name="ItemType" value="0"/>
</enum>
- <property name="itemType" type="OrganizerItemType"/>
+ <property name="itemType" type="OrganizerItemType" isWritable="true"/>
<signal name="valueChanged"/>
</type>
<type name="QDeclarativeOrganizerItemUnionFilter" defaultProperty="subFilters" extends="QDeclarativeOrganizerItemFilter">
@@ -3562,15 +3562,15 @@
<enumerator name="DataUrl" value="0"/>
<enumerator name="Message" value="1"/>
</enum>
- <property name="message" type="string"/>
- <property name="dataUrl" type="QUrl"/>
+ <property name="message" type="string" isWritable="true"/>
+ <property name="dataUrl" type="QUrl" isWritable="true"/>
<signal name="valueChanged"/>
</type>
<type name="QDeclarativeOrganizerJournal" defaultProperty="details" extends="QDeclarativeOrganizerItem">
<exports>
<export module="QtMobility.organizer" version="1.1" type="Journal"/>
</exports>
- <property name="dateTime" type="QDateTime"/>
+ <property name="dateTime" type="QDateTime" isWritable="true"/>
<signal name="valueChanged"/>
</type>
<type name="QDeclarativeOrganizerJournalTime" extends="QDeclarativeOrganizerItemDetail">
@@ -3580,20 +3580,20 @@
<enum name="FieldType">
<enumerator name="EntryDateTime" value="0"/>
</enum>
- <property name="entryDateTime" type="QDateTime"/>
+ <property name="entryDateTime" type="QDateTime" isWritable="true"/>
<signal name="valueChanged"/>
</type>
<type name="QDeclarativeOrganizerModel" extends="QAbstractListModel">
<exports>
<export module="QtMobility.organizer" version="1.1" type="OrganizerModel"/>
</exports>
- <property name="manager" type="string"/>
+ <property name="manager" type="string" isWritable="true"/>
<property name="availableManagers" type="QStringList"/>
- <property name="autoUpdate" type="bool"/>
- <property name="startPeriod" type="QDateTime"/>
- <property name="endPeriod" type="QDateTime"/>
- <property name="filter" type="QDeclarativeOrganizerItemFilter"/>
- <property name="fetchHint" type="QDeclarativeOrganizerItemFetchHint"/>
+ <property name="autoUpdate" type="bool" isWritable="true"/>
+ <property name="startPeriod" type="QDateTime" isWritable="true"/>
+ <property name="endPeriod" type="QDateTime" isWritable="true"/>
+ <property name="filter" type="QDeclarativeOrganizerItemFilter" isWritable="true" isPointer="true"/>
+ <property name="fetchHint" type="QDeclarativeOrganizerItemFetchHint" isWritable="true" isPointer="true"/>
<property name="sortOrders" type="QDeclarativeOrganizerItemSortOrder" isList="true"/>
<property name="items" type="QDeclarativeOrganizerItem" isList="true"/>
<property name="occurrences" type="QDeclarativeOrganizerItem" isList="true"/>
@@ -3628,7 +3628,7 @@
<param name="ids" type="QList&lt;uint&gt;"/>
</method>
<method name="saveItem">
- <param name="item" type="QDeclarativeOrganizerItem"/>
+ <param name="item" type="QDeclarativeOrganizerItem" isPointer="true"/>
</method>
</type>
<type name="QDeclarativeOrganizerNote" defaultProperty="details" extends="QDeclarativeOrganizerItem">
@@ -3662,43 +3662,43 @@
<enumerator name="November" value="11"/>
<enumerator name="December" value="12"/>
</enum>
- <property name="frequency" type="Frequency"/>
- <property name="limit" type="QVariant"/>
- <property name="interval" type="int"/>
- <property name="daysOfWeek" type="QVariantList"/>
- <property name="daysOfMonth" type="QVariantList"/>
- <property name="daysOfYear" type="QVariantList"/>
- <property name="monthsOfYear" type="QVariantList"/>
- <property name="positions" type="QVariantList"/>
- <property name="firstDayOfWeek" type="Qt.DayOfWeek"/>
+ <property name="frequency" type="Frequency" isWritable="true"/>
+ <property name="limit" type="QVariant" isWritable="true"/>
+ <property name="interval" type="int" isWritable="true"/>
+ <property name="daysOfWeek" type="QVariantList" isWritable="true"/>
+ <property name="daysOfMonth" type="QVariantList" isWritable="true"/>
+ <property name="daysOfYear" type="QVariantList" isWritable="true"/>
+ <property name="monthsOfYear" type="QVariantList" isWritable="true"/>
+ <property name="positions" type="QVariantList" isWritable="true"/>
+ <property name="firstDayOfWeek" type="Qt.DayOfWeek" isWritable="true"/>
<signal name="valueChanged"/>
</type>
<type name="QDeclarativeOrganizerTodo" defaultProperty="details" extends="QDeclarativeOrganizerItem">
<exports>
<export module="QtMobility.organizer" version="1.1" type="Todo"/>
</exports>
- <property name="startDateTime" type="QDateTime"/>
- <property name="dueDateTime" type="QDateTime"/>
- <property name="isAllDay" type="bool"/>
- <property name="priority" type="QDeclarativeOrganizerItemPriority.PriorityType"/>
- <property name="progressPercentage" type="int"/>
- <property name="status" type="QDeclarativeOrganizerTodoProgress.StatusType"/>
- <property name="finishedDateTime" type="QDateTime"/>
- <property name="recurrence" type="QDeclarativeOrganizerItemRecurrence"/>
+ <property name="startDateTime" type="QDateTime" isWritable="true"/>
+ <property name="dueDateTime" type="QDateTime" isWritable="true"/>
+ <property name="isAllDay" type="bool" isWritable="true"/>
+ <property name="priority" type="QDeclarativeOrganizerItemPriority.PriorityType" isWritable="true"/>
+ <property name="progressPercentage" type="int" isWritable="true"/>
+ <property name="status" type="QDeclarativeOrganizerTodoProgress.StatusType" isWritable="true"/>
+ <property name="finishedDateTime" type="QDateTime" isWritable="true"/>
+ <property name="recurrence" type="QDeclarativeOrganizerItemRecurrence" isPointer="true"/>
<signal name="valueChanged"/>
</type>
<type name="QDeclarativeOrganizerTodoOccurrence" defaultProperty="details" extends="QDeclarativeOrganizerItem">
<exports>
<export module="QtMobility.organizer" version="1.1" type="TodoOccurrence"/>
</exports>
- <property name="startDateTime" type="QDateTime"/>
- <property name="dueDateTime" type="QDateTime"/>
- <property name="priority" type="QDeclarativeOrganizerItemPriority.PriorityType"/>
- <property name="progressPercentage" type="int"/>
- <property name="status" type="QDeclarativeOrganizerTodoProgress.StatusType"/>
- <property name="finishedDateTime" type="QDateTime"/>
- <property name="parentId" type="uint"/>
- <property name="originalDate" type="QDate"/>
+ <property name="startDateTime" type="QDateTime" isWritable="true"/>
+ <property name="dueDateTime" type="QDateTime" isWritable="true"/>
+ <property name="priority" type="QDeclarativeOrganizerItemPriority.PriorityType" isWritable="true"/>
+ <property name="progressPercentage" type="int" isWritable="true"/>
+ <property name="status" type="QDeclarativeOrganizerTodoProgress.StatusType" isWritable="true"/>
+ <property name="finishedDateTime" type="QDateTime" isWritable="true"/>
+ <property name="parentId" type="uint" isWritable="true"/>
+ <property name="originalDate" type="QDate" isWritable="true"/>
<signal name="valueChanged"/>
</type>
<type name="QDeclarativeOrganizerTodoProgress" extends="QDeclarativeOrganizerItemDetail">
@@ -3715,9 +3715,9 @@
<enumerator name="InProgress" value="1"/>
<enumerator name="Complete" value="2"/>
</enum>
- <property name="status" type="StatusType"/>
- <property name="percentage" type="int"/>
- <property name="finishedDateTime" type="QDateTime"/>
+ <property name="status" type="StatusType" isWritable="true"/>
+ <property name="percentage" type="int" isWritable="true"/>
+ <property name="finishedDateTime" type="QDateTime" isWritable="true"/>
<signal name="valueChanged"/>
</type>
<type name="QDeclarativeOrganizerTodoTime" extends="QDeclarativeOrganizerItemDetail">
@@ -3729,9 +3729,9 @@
<enumerator name="StartDateTime" value="1"/>
<enumerator name="DueDateTime" value="2"/>
</enum>
- <property name="allDay" type="bool"/>
- <property name="startDateTime" type="QDateTime"/>
- <property name="dueDateTime" type="QDateTime"/>
+ <property name="allDay" type="bool" isWritable="true"/>
+ <property name="startDateTime" type="QDateTime" isWritable="true"/>
+ <property name="dueDateTime" type="QDateTime" isWritable="true"/>
<signal name="valueChanged"/>
</type>
<type name="QDeclarativePackage" defaultProperty="data" extends="QObject">
@@ -3742,11 +3742,11 @@
<property name="data" type="QObject" isList="true"/>
</type>
<type name="QDeclarativePaintedItem" defaultProperty="data" extends="QDeclarativeItem">
- <property name="contentsSize" type="QSize"/>
- <property name="fillColor" type="QColor"/>
- <property name="pixelCacheSize" type="int"/>
- <property name="smoothCache" type="bool"/>
- <property name="contentsScale" type="qreal"/>
+ <property name="contentsSize" type="QSize" isWritable="true"/>
+ <property name="fillColor" type="QColor" isWritable="true"/>
+ <property name="pixelCacheSize" type="int" isWritable="true"/>
+ <property name="smoothCache" type="bool" isWritable="true"/>
+ <property name="contentsScale" type="qreal" isWritable="true"/>
<signal name="fillColorChanged"/>
<signal name="contentsSizeChanged"/>
<signal name="contentsScaleChanged"/>
@@ -3762,9 +3762,9 @@
<export module="QtQuick" version="1.0" type="ParentAnimation"/>
<export module="Qt" version="4.7" type="ParentAnimation"/>
</exports>
- <property name="target" type="QDeclarativeItem"/>
- <property name="newParent" type="QDeclarativeItem"/>
- <property name="via" type="QDeclarativeItem"/>
+ <property name="target" type="QDeclarativeItem" isWritable="true" isPointer="true"/>
+ <property name="newParent" type="QDeclarativeItem" isWritable="true" isPointer="true"/>
+ <property name="via" type="QDeclarativeItem" isWritable="true" isPointer="true"/>
<signal name="targetChanged"/>
<signal name="newParentChanged"/>
<signal name="viaChanged"/>
@@ -3774,14 +3774,14 @@
<export module="QtQuick" version="1.0" type="ParentChange"/>
<export module="Qt" version="4.7" type="ParentChange"/>
</exports>
- <property name="target" type="QDeclarativeItem"/>
- <property name="parent" type="QDeclarativeItem"/>
- <property name="x" type="QDeclarativeScriptString"/>
- <property name="y" type="QDeclarativeScriptString"/>
- <property name="width" type="QDeclarativeScriptString"/>
- <property name="height" type="QDeclarativeScriptString"/>
- <property name="scale" type="QDeclarativeScriptString"/>
- <property name="rotation" type="QDeclarativeScriptString"/>
+ <property name="target" type="QDeclarativeItem" isWritable="true" isPointer="true"/>
+ <property name="parent" type="QDeclarativeItem" isWritable="true" isPointer="true"/>
+ <property name="x" type="QDeclarativeScriptString" isWritable="true"/>
+ <property name="y" type="QDeclarativeScriptString" isWritable="true"/>
+ <property name="width" type="QDeclarativeScriptString" isWritable="true"/>
+ <property name="height" type="QDeclarativeScriptString" isWritable="true"/>
+ <property name="scale" type="QDeclarativeScriptString" isWritable="true"/>
+ <property name="rotation" type="QDeclarativeScriptString" isWritable="true"/>
</type>
<type name="QDeclarativeParticleMotion" extends="QObject">
<exports>
@@ -3792,9 +3792,9 @@
<exports>
<export module="Qt.labs.particles" version="1.0" type="ParticleMotionGravity"/>
</exports>
- <property name="xattractor" type="qreal"/>
- <property name="yattractor" type="qreal"/>
- <property name="acceleration" type="qreal"/>
+ <property name="xattractor" type="qreal" isWritable="true"/>
+ <property name="yattractor" type="qreal" isWritable="true"/>
+ <property name="acceleration" type="qreal" isWritable="true"/>
<signal name="xattractorChanged"/>
<signal name="yattractorChanged"/>
<signal name="accelerationChanged"/>
@@ -3808,9 +3808,9 @@
<exports>
<export module="Qt.labs.particles" version="1.0" type="ParticleMotionWander"/>
</exports>
- <property name="xvariance" type="qreal"/>
- <property name="yvariance" type="qreal"/>
- <property name="pace" type="qreal"/>
+ <property name="xvariance" type="qreal" isWritable="true"/>
+ <property name="yvariance" type="qreal" isWritable="true"/>
+ <property name="pace" type="qreal" isWritable="true"/>
<signal name="xvarianceChanged"/>
<signal name="yvarianceChanged"/>
<signal name="paceChanged"/>
@@ -3819,19 +3819,19 @@
<exports>
<export module="Qt.labs.particles" version="1.0" type="Particles"/>
</exports>
- <property name="source" type="QUrl"/>
- <property name="count" type="int"/>
- <property name="emissionRate" type="int"/>
- <property name="emissionVariance" type="qreal"/>
- <property name="lifeSpan" type="int"/>
- <property name="lifeSpanDeviation" type="int"/>
- <property name="fadeInDuration" type="int"/>
- <property name="fadeOutDuration" type="int"/>
- <property name="angle" type="qreal"/>
- <property name="angleDeviation" type="qreal"/>
- <property name="velocity" type="qreal"/>
- <property name="velocityDeviation" type="qreal"/>
- <property name="motion" type="QDeclarativeParticleMotion"/>
+ <property name="source" type="QUrl" isWritable="true"/>
+ <property name="count" type="int" isWritable="true"/>
+ <property name="emissionRate" type="int" isWritable="true"/>
+ <property name="emissionVariance" type="qreal" isWritable="true"/>
+ <property name="lifeSpan" type="int" isWritable="true"/>
+ <property name="lifeSpanDeviation" type="int" isWritable="true"/>
+ <property name="fadeInDuration" type="int" isWritable="true"/>
+ <property name="fadeOutDuration" type="int" isWritable="true"/>
+ <property name="angle" type="qreal" isWritable="true"/>
+ <property name="angleDeviation" type="qreal" isWritable="true"/>
+ <property name="velocity" type="qreal" isWritable="true"/>
+ <property name="velocityDeviation" type="qreal" isWritable="true"/>
+ <property name="motion" type="QDeclarativeParticleMotion" isWritable="true" isPointer="true"/>
<signal name="sourceChanged"/>
<signal name="countChanged"/>
<signal name="emissionRateChanged"/>
@@ -3860,8 +3860,8 @@
<export module="QtQuick" version="1.0" type="Path"/>
</exports>
<property name="pathElements" type="QDeclarativePathElement" isList="true"/>
- <property name="startX" type="qreal"/>
- <property name="startY" type="qreal"/>
+ <property name="startX" type="qreal" isWritable="true"/>
+ <property name="startY" type="qreal" isWritable="true"/>
<property name="closed" type="bool"/>
<signal name="changed"/>
<signal name="startXChanged"/>
@@ -3872,8 +3872,8 @@
<export module="Qt" version="4.7" type="PathAttribute"/>
<export module="QtQuick" version="1.0" type="PathAttribute"/>
</exports>
- <property name="name" type="string"/>
- <property name="value" type="qreal"/>
+ <property name="name" type="string" isWritable="true"/>
+ <property name="value" type="qreal" isWritable="true"/>
<signal name="nameChanged"/>
<signal name="valueChanged"/>
</type>
@@ -3882,10 +3882,10 @@
<export module="Qt" version="4.7" type="PathCubic"/>
<export module="QtQuick" version="1.0" type="PathCubic"/>
</exports>
- <property name="control1X" type="qreal"/>
- <property name="control1Y" type="qreal"/>
- <property name="control2X" type="qreal"/>
- <property name="control2Y" type="qreal"/>
+ <property name="control1X" type="qreal" isWritable="true"/>
+ <property name="control1Y" type="qreal" isWritable="true"/>
+ <property name="control2X" type="qreal" isWritable="true"/>
+ <property name="control2Y" type="qreal" isWritable="true"/>
<signal name="control1XChanged"/>
<signal name="control1YChanged"/>
<signal name="control2XChanged"/>
@@ -3905,7 +3905,7 @@
<export module="QtQuick" version="1.0" type="PathPercent"/>
<export module="Qt" version="4.7" type="PathPercent"/>
</exports>
- <property name="value" type="qreal"/>
+ <property name="value" type="qreal" isWritable="true"/>
<signal name="valueChanged"/>
</type>
<type name="QDeclarativePathQuad" extends="QDeclarativeCurve">
@@ -3913,8 +3913,8 @@
<export module="Qt" version="4.7" type="PathQuad"/>
<export module="QtQuick" version="1.0" type="PathQuad"/>
</exports>
- <property name="controlX" type="qreal"/>
- <property name="controlY" type="qreal"/>
+ <property name="controlX" type="qreal" isWritable="true"/>
+ <property name="controlY" type="qreal" isWritable="true"/>
<signal name="controlXChanged"/>
<signal name="controlYChanged"/>
</type>
@@ -3928,24 +3928,24 @@
<enumerator name="ApplyRange" value="1"/>
<enumerator name="StrictlyEnforceRange" value="2"/>
</enum>
- <property name="model" type="QVariant"/>
- <property name="path" type="QDeclarativePath"/>
- <property name="currentIndex" type="int"/>
- <property name="offset" type="qreal"/>
- <property name="highlight" type="QDeclarativeComponent"/>
- <property name="highlightItem" type="QDeclarativeItem"/>
- <property name="preferredHighlightBegin" type="qreal"/>
- <property name="preferredHighlightEnd" type="qreal"/>
- <property name="highlightRangeMode" type="HighlightRangeMode"/>
- <property name="highlightMoveDuration" type="int"/>
- <property name="dragMargin" type="qreal"/>
- <property name="flickDeceleration" type="qreal"/>
- <property name="interactive" type="bool"/>
+ <property name="model" type="QVariant" isWritable="true"/>
+ <property name="path" type="QDeclarativePath" isWritable="true" isPointer="true"/>
+ <property name="currentIndex" type="int" isWritable="true"/>
+ <property name="offset" type="qreal" isWritable="true"/>
+ <property name="highlight" type="QDeclarativeComponent" isWritable="true" isPointer="true"/>
+ <property name="highlightItem" type="QDeclarativeItem" isPointer="true"/>
+ <property name="preferredHighlightBegin" type="qreal" isWritable="true"/>
+ <property name="preferredHighlightEnd" type="qreal" isWritable="true"/>
+ <property name="highlightRangeMode" type="HighlightRangeMode" isWritable="true"/>
+ <property name="highlightMoveDuration" type="int" isWritable="true"/>
+ <property name="dragMargin" type="qreal" isWritable="true"/>
+ <property name="flickDeceleration" type="qreal" isWritable="true"/>
+ <property name="interactive" type="bool" isWritable="true"/>
<property name="moving" type="bool"/>
<property name="flicking" type="bool"/>
<property name="count" type="int"/>
- <property name="delegate" type="QDeclarativeComponent"/>
- <property name="pathItemCount" type="int"/>
+ <property name="delegate" type="QDeclarativeComponent" isWritable="true" isPointer="true"/>
+ <property name="pathItemCount" type="int" isWritable="true"/>
<signal name="currentIndexChanged"/>
<signal name="offsetChanged"/>
<signal name="modelChanged"/>
@@ -3977,14 +3977,14 @@
<export module="Qt" version="4.7" type="PauseAnimation"/>
<export module="QtQuick" version="1.0" type="PauseAnimation"/>
</exports>
- <property name="duration" type="int"/>
+ <property name="duration" type="int" isWritable="true"/>
<signal name="durationChanged">
<param type="int"/>
</signal>
</type>
<type name="QDeclarativePen" extends="QObject">
- <property name="width" type="int"/>
- <property name="color" type="QColor"/>
+ <property name="width" type="int" isWritable="true"/>
+ <property name="color" type="QColor" isWritable="true"/>
<signal name="penChanged"/>
</type>
<type name="QDeclarativePosition" extends="QObject">
@@ -3994,7 +3994,7 @@
<property name="latitudeValid" type="bool"/>
<property name="longitudeValid" type="bool"/>
<property name="altitudeValid" type="bool"/>
- <property name="coordinate" type="QDeclarativeCoordinate"/>
+ <property name="coordinate" type="QDeclarativeCoordinate" isPointer="true"/>
<property name="timestamp" type="QDateTime"/>
<property name="speed" type="double"/>
<property name="speedValid" type="bool"/>
@@ -4016,10 +4016,10 @@
<enumerator name="NonSatellitePositioningMethod" value="-256"/>
<enumerator name="AllPositioningMethods" value="-1"/>
</enum>
- <property name="position" type="QDeclarativePosition"/>
- <property name="active" type="bool"/>
- <property name="nmeaSource" type="QUrl"/>
- <property name="updateInterval" type="int"/>
+ <property name="position" type="QDeclarativePosition" isPointer="true"/>
+ <property name="active" type="bool" isWritable="true"/>
+ <property name="nmeaSource" type="QUrl" isWritable="true"/>
+ <property name="updateInterval" type="int" isWritable="true"/>
<property name="positioningMethod" type="PositioningMethod"/>
<signal name="positionChanged"/>
<signal name="activeChanged"/>
@@ -4035,12 +4035,12 @@
<export module="QtQuick" version="1.0" type="PropertyAction"/>
<export module="Qt" version="4.7" type="PropertyAction"/>
</exports>
- <property name="target" type="QObject"/>
- <property name="property" type="string"/>
- <property name="properties" type="string"/>
+ <property name="target" type="QObject" isWritable="true" isPointer="true"/>
+ <property name="property" type="string" isWritable="true"/>
+ <property name="properties" type="string" isWritable="true"/>
<property name="targets" type="QObject" isList="true"/>
<property name="exclude" type="QObject" isList="true"/>
- <property name="value" type="QVariant"/>
+ <property name="value" type="QVariant" isWritable="true"/>
<signal name="valueChanged">
<param type="QVariant"/>
</signal>
@@ -4055,13 +4055,13 @@
<export module="QtQuick" version="1.0" type="PropertyAnimation"/>
<export module="Qt" version="4.7" type="PropertyAnimation"/>
</exports>
- <property name="duration" type="int"/>
- <property name="from" type="QVariant"/>
- <property name="to" type="QVariant"/>
- <property name="easing" type="QEasingCurve"/>
- <property name="target" type="QObject"/>
- <property name="property" type="string"/>
- <property name="properties" type="string"/>
+ <property name="duration" type="int" isWritable="true"/>
+ <property name="from" type="QVariant" isWritable="true"/>
+ <property name="to" type="QVariant" isWritable="true"/>
+ <property name="easing" type="QEasingCurve" isWritable="true"/>
+ <property name="target" type="QObject" isWritable="true" isPointer="true"/>
+ <property name="property" type="string" isWritable="true"/>
+ <property name="properties" type="string" isWritable="true"/>
<property name="targets" type="QObject" isList="true"/>
<property name="exclude" type="QObject" isList="true"/>
<signal name="durationChanged">
@@ -4087,9 +4087,9 @@
<export module="QtQuick" version="1.0" type="PropertyChanges"/>
<export module="Qt" version="4.7" type="PropertyChanges"/>
</exports>
- <property name="target" type="QObject"/>
- <property name="restoreEntryValues" type="bool"/>
- <property name="explicit" type="bool"/>
+ <property name="target" type="QObject" isWritable="true" isPointer="true"/>
+ <property name="restoreEntryValues" type="bool" isWritable="true"/>
+ <property name="explicit" type="bool" isWritable="true"/>
</type>
<type name="QDeclarativePropertyMap" extends="QObject">
<signal name="valueChanged">
@@ -4103,10 +4103,10 @@
<export module="QtQuick" version="1.0" type="Rectangle"/>
<export module="Qt" version="4.7" type="Rectangle"/>
</exports>
- <property name="color" type="QColor"/>
- <property name="gradient" type="QDeclarativeGradient"/>
- <property name="border" type="QDeclarativePen"/>
- <property name="radius" type="qreal"/>
+ <property name="color" type="QColor" isWritable="true"/>
+ <property name="gradient" type="QDeclarativeGradient" isWritable="true" isPointer="true"/>
+ <property name="border" type="QDeclarativePen" isPointer="true"/>
+ <property name="radius" type="qreal" isWritable="true"/>
<signal name="colorChanged"/>
<signal name="radiusChanged"/>
</type>
@@ -4115,8 +4115,8 @@
<export module="Qt" version="4.7" type="Repeater"/>
<export module="QtQuick" version="1.0" type="Repeater"/>
</exports>
- <property name="model" type="QVariant"/>
- <property name="delegate" type="QDeclarativeComponent"/>
+ <property name="model" type="QVariant" isWritable="true"/>
+ <property name="delegate" type="QDeclarativeComponent" isWritable="true" isPointer="true"/>
<property name="count" type="int"/>
<signal name="modelChanged"/>
<signal name="delegateChanged"/>
@@ -4126,9 +4126,9 @@
<exports>
<export module="QtMobility.location" version="1.1" type="ReverseGeocodeModel"/>
</exports>
- <property name="coordinate" type="QDeclarativeCoordinate"/>
+ <property name="coordinate" type="QDeclarativeCoordinate" isWritable="true" isPointer="true"/>
<signal name="coordinateChanged">
- <param name="coordinate" type="QDeclarativeCoordinate"/>
+ <param name="coordinate" type="QDeclarativeCoordinate" isPointer="true"/>
</signal>
</type>
<type name="QDeclarativeRotationAnimation" extends="QDeclarativePropertyAnimation">
@@ -4142,9 +4142,9 @@
<enumerator name="Clockwise" value="2"/>
<enumerator name="Counterclockwise" value="3"/>
</enum>
- <property name="from" type="qreal"/>
- <property name="to" type="qreal"/>
- <property name="direction" type="RotationDirection"/>
+ <property name="from" type="qreal" isWritable="true"/>
+ <property name="to" type="qreal" isWritable="true"/>
+ <property name="direction" type="RotationDirection" isWritable="true"/>
<signal name="directionChanged"/>
</type>
<type name="QDeclarativeRow" defaultProperty="data" extends="QDeclarativeBasePositioner">
@@ -4154,17 +4154,17 @@
</exports>
</type>
<type name="QDeclarativeScaleGrid" extends="QObject">
- <property name="left" type="int"/>
- <property name="top" type="int"/>
- <property name="right" type="int"/>
- <property name="bottom" type="int"/>
+ <property name="left" type="int" isWritable="true"/>
+ <property name="top" type="int" isWritable="true"/>
+ <property name="right" type="int" isWritable="true"/>
+ <property name="bottom" type="int" isWritable="true"/>
<signal name="borderChanged"/>
</type>
<type name="QDeclarativeScreenSaver" extends="QObject">
<exports>
<export module="QtMobility.systeminfo" version="1.1" type="ScreenSaver"/>
</exports>
- <property name="screenSaverDelayed" type="bool"/>
+ <property name="screenSaverDelayed" type="bool" isWritable="true"/>
<method name="setScreenSaverDelayed">
<param name="on" type="bool"/>
</method>
@@ -4174,8 +4174,8 @@
<export module="Qt" version="4.7" type="ScriptAction"/>
<export module="QtQuick" version="1.0" type="ScriptAction"/>
</exports>
- <property name="script" type="QDeclarativeScriptString"/>
- <property name="scriptName" type="string"/>
+ <property name="script" type="QDeclarativeScriptString" isWritable="true"/>
+ <property name="scriptName" type="string" isWritable="true"/>
</type>
<type name="QDeclarativeSequentialAnimation" defaultProperty="animations" extends="QDeclarativeAnimationGroup">
<exports>
@@ -4187,12 +4187,12 @@
<exports>
<export module="QtMobility.serviceframework" version="1.1" type="Service"/>
</exports>
- <property name="interfaceName" type="string"/>
+ <property name="interfaceName" type="string" isWritable="true"/>
<property name="serviceName" type="string"/>
<property name="majorVersion" type="int"/>
<property name="minorVersion" type="int"/>
<property name="valid" type="bool"/>
- <property name="serviceObject" type="QObject"/>
+ <property name="serviceObject" type="QObject" isPointer="true"/>
<signal name="validChanged"/>
<signal name="serviceObjectChanged"/>
<signal name="interfaceNameChanged"/>
@@ -4208,12 +4208,12 @@
<enumerator name="Minimum" value="0"/>
<enumerator name="Exact" value="1"/>
</enum>
- <property name="serviceName" type="string"/>
- <property name="interfaceName" type="string"/>
- <property name="majorVersion" type="int"/>
- <property name="minorVersion" type="int"/>
+ <property name="serviceName" type="string" isWritable="true"/>
+ <property name="interfaceName" type="string" isWritable="true"/>
+ <property name="majorVersion" type="int" isWritable="true"/>
+ <property name="minorVersion" type="int" isWritable="true"/>
<property name="services" type="QDeclarativeService" isList="true"/>
- <property name="versionMatch" type="MatchRule"/>
+ <property name="versionMatch" type="MatchRule" isWritable="true"/>
<signal name="servicesChanged">
<param type="QDeclarativeService"/>
</signal>
@@ -4233,9 +4233,9 @@
<enumerator name="Immediate" value="1"/>
<enumerator name="Sync" value="2"/>
</enum>
- <property name="velocity" type="qreal"/>
- <property name="reversingMode" type="ReversingMode"/>
- <property name="maximumEasingTime" type="qreal"/>
+ <property name="velocity" type="qreal" isWritable="true"/>
+ <property name="reversingMode" type="ReversingMode" isWritable="true"/>
+ <property name="maximumEasingTime" type="qreal" isWritable="true"/>
<signal name="velocityChanged"/>
<signal name="reversingModeChanged"/>
<signal name="maximumEasingTimeChanged"/>
@@ -4245,12 +4245,12 @@
<export module="QtQuick" version="1.0" type="SpringAnimation"/>
<export module="Qt" version="4.7" type="SpringAnimation"/>
</exports>
- <property name="velocity" type="qreal"/>
- <property name="spring" type="qreal"/>
- <property name="damping" type="qreal"/>
- <property name="epsilon" type="qreal"/>
- <property name="modulus" type="qreal"/>
- <property name="mass" type="qreal"/>
+ <property name="velocity" type="qreal" isWritable="true"/>
+ <property name="spring" type="qreal" isWritable="true"/>
+ <property name="damping" type="qreal" isWritable="true"/>
+ <property name="epsilon" type="qreal" isWritable="true"/>
+ <property name="modulus" type="qreal" isWritable="true"/>
+ <property name="mass" type="qreal" isWritable="true"/>
<signal name="modulusChanged"/>
<signal name="massChanged"/>
<signal name="syncChanged"/>
@@ -4260,9 +4260,9 @@
<export module="Qt" version="4.7" type="State"/>
<export module="QtQuick" version="1.0" type="State"/>
</exports>
- <property name="name" type="string"/>
- <property name="when" type="QDeclarativeBinding"/>
- <property name="extend" type="string"/>
+ <property name="name" type="string" isWritable="true"/>
+ <property name="when" type="QDeclarativeBinding" isWritable="true" isPointer="true"/>
+ <property name="extend" type="string" isWritable="true"/>
<property name="changes" type="QDeclarativeStateOperation" isList="true"/>
<signal name="completed"/>
</type>
@@ -4271,15 +4271,15 @@
<export module="Qt" version="4.7" type="StateChangeScript"/>
<export module="QtQuick" version="1.0" type="StateChangeScript"/>
</exports>
- <property name="script" type="QDeclarativeScriptString"/>
- <property name="name" type="string"/>
+ <property name="script" type="QDeclarativeScriptString" isWritable="true"/>
+ <property name="name" type="string" isWritable="true"/>
</type>
<type name="QDeclarativeStateGroup" extends="QObject">
<exports>
<export module="Qt" version="4.7" type="StateGroup"/>
<export module="QtQuick" version="1.0" type="StateGroup"/>
</exports>
- <property name="state" type="string"/>
+ <property name="state" type="string" isWritable="true"/>
<property name="states" type="QDeclarativeState" isList="true"/>
<property name="transitions" type="QDeclarativeTransition" isList="true"/>
<signal name="stateChanged">
@@ -4297,7 +4297,7 @@
<enumerator name="Inactive" value="2"/>
<enumerator name="Disabled" value="1"/>
</enum>
- <property name="colorGroup" type="QDeclarativeSystemPalette.ColorGroup"/>
+ <property name="colorGroup" type="QDeclarativeSystemPalette.ColorGroup" isWritable="true"/>
<property name="window" type="QColor"/>
<property name="windowText" type="QColor"/>
<property name="base" type="QColor"/>
@@ -4354,16 +4354,16 @@
<enumerator name="WrapAtWordBoundaryOrAnywhere" value="4"/>
<enumerator name="Wrap" value="4"/>
</enum>
- <property name="text" type="string"/>
- <property name="font" type="QFont"/>
- <property name="color" type="QColor"/>
- <property name="style" type="TextStyle"/>
- <property name="styleColor" type="QColor"/>
- <property name="horizontalAlignment" type="HAlignment"/>
- <property name="verticalAlignment" type="VAlignment"/>
- <property name="wrapMode" type="WrapMode"/>
- <property name="textFormat" type="TextFormat"/>
- <property name="elide" type="TextElideMode"/>
+ <property name="text" type="string" isWritable="true"/>
+ <property name="font" type="QFont" isWritable="true"/>
+ <property name="color" type="QColor" isWritable="true"/>
+ <property name="style" type="TextStyle" isWritable="true"/>
+ <property name="styleColor" type="QColor" isWritable="true"/>
+ <property name="horizontalAlignment" type="HAlignment" isWritable="true"/>
+ <property name="verticalAlignment" type="VAlignment" isWritable="true"/>
+ <property name="wrapMode" type="WrapMode" isWritable="true"/>
+ <property name="textFormat" type="TextFormat" isWritable="true"/>
+ <property name="elide" type="TextElideMode" isWritable="true"/>
<property name="paintedWidth" type="qreal"/>
<property name="paintedHeight" type="qreal"/>
<signal name="textChanged">
@@ -4426,30 +4426,30 @@
<enumerator name="WrapAtWordBoundaryOrAnywhere" value="4"/>
<enumerator name="Wrap" value="4"/>
</enum>
- <property name="text" type="string"/>
- <property name="color" type="QColor"/>
- <property name="selectionColor" type="QColor"/>
- <property name="selectedTextColor" type="QColor"/>
- <property name="font" type="QFont"/>
- <property name="horizontalAlignment" type="HAlignment"/>
- <property name="verticalAlignment" type="VAlignment"/>
- <property name="wrapMode" type="WrapMode"/>
+ <property name="text" type="string" isWritable="true"/>
+ <property name="color" type="QColor" isWritable="true"/>
+ <property name="selectionColor" type="QColor" isWritable="true"/>
+ <property name="selectedTextColor" type="QColor" isWritable="true"/>
+ <property name="font" type="QFont" isWritable="true"/>
+ <property name="horizontalAlignment" type="HAlignment" isWritable="true"/>
+ <property name="verticalAlignment" type="VAlignment" isWritable="true"/>
+ <property name="wrapMode" type="WrapMode" isWritable="true"/>
<property name="paintedWidth" type="qreal"/>
<property name="paintedHeight" type="qreal"/>
- <property name="textFormat" type="TextFormat"/>
- <property name="readOnly" type="bool"/>
- <property name="cursorVisible" type="bool"/>
- <property name="cursorPosition" type="int"/>
+ <property name="textFormat" type="TextFormat" isWritable="true"/>
+ <property name="readOnly" type="bool" isWritable="true"/>
+ <property name="cursorVisible" type="bool" isWritable="true"/>
+ <property name="cursorPosition" type="int" isWritable="true"/>
<property name="cursorRectangle" type="QRect"/>
- <property name="cursorDelegate" type="QDeclarativeComponent"/>
+ <property name="cursorDelegate" type="QDeclarativeComponent" isWritable="true" isPointer="true"/>
<property name="selectionStart" type="int"/>
<property name="selectionEnd" type="int"/>
<property name="selectedText" type="string"/>
- <property name="activeFocusOnPress" type="bool"/>
- <property name="persistentSelection" type="bool"/>
- <property name="textMargin" type="qreal"/>
- <property name="inputMethodHints" type="Qt.InputMethodHints"/>
- <property name="selectByMouse" type="bool"/>
+ <property name="activeFocusOnPress" type="bool" isWritable="true"/>
+ <property name="persistentSelection" type="bool" isWritable="true"/>
+ <property name="textMargin" type="qreal" isWritable="true"/>
+ <property name="inputMethodHints" type="Qt.InputMethodHints" isWritable="true"/>
+ <property name="selectByMouse" type="bool" isWritable="true"/>
<signal name="textChanged">
<param type="string"/>
</signal>
@@ -4538,31 +4538,31 @@
<enumerator name="AlignRight" value="2"/>
<enumerator name="AlignHCenter" value="4"/>
</enum>
- <property name="text" type="string"/>
- <property name="color" type="QColor"/>
- <property name="selectionColor" type="QColor"/>
- <property name="selectedTextColor" type="QColor"/>
- <property name="font" type="QFont"/>
- <property name="horizontalAlignment" type="HAlignment"/>
- <property name="readOnly" type="bool"/>
- <property name="cursorVisible" type="bool"/>
- <property name="cursorPosition" type="int"/>
+ <property name="text" type="string" isWritable="true"/>
+ <property name="color" type="QColor" isWritable="true"/>
+ <property name="selectionColor" type="QColor" isWritable="true"/>
+ <property name="selectedTextColor" type="QColor" isWritable="true"/>
+ <property name="font" type="QFont" isWritable="true"/>
+ <property name="horizontalAlignment" type="HAlignment" isWritable="true"/>
+ <property name="readOnly" type="bool" isWritable="true"/>
+ <property name="cursorVisible" type="bool" isWritable="true"/>
+ <property name="cursorPosition" type="int" isWritable="true"/>
<property name="cursorRectangle" type="QRect"/>
- <property name="cursorDelegate" type="QDeclarativeComponent"/>
+ <property name="cursorDelegate" type="QDeclarativeComponent" isWritable="true" isPointer="true"/>
<property name="selectionStart" type="int"/>
<property name="selectionEnd" type="int"/>
<property name="selectedText" type="string"/>
- <property name="maximumLength" type="int"/>
- <property name="validator" type="QValidator"/>
- <property name="inputMask" type="string"/>
- <property name="inputMethodHints" type="Qt.InputMethodHints"/>
+ <property name="maximumLength" type="int" isWritable="true"/>
+ <property name="validator" type="QValidator" isWritable="true" isPointer="true"/>
+ <property name="inputMask" type="string" isWritable="true"/>
+ <property name="inputMethodHints" type="Qt.InputMethodHints" isWritable="true"/>
<property name="acceptableInput" type="bool"/>
- <property name="echoMode" type="EchoMode"/>
- <property name="activeFocusOnPress" type="bool"/>
- <property name="passwordCharacter" type="string"/>
+ <property name="echoMode" type="EchoMode" isWritable="true"/>
+ <property name="activeFocusOnPress" type="bool" isWritable="true"/>
+ <property name="passwordCharacter" type="string" isWritable="true"/>
<property name="displayText" type="string"/>
- <property name="autoScroll" type="bool"/>
- <property name="selectByMouse" type="bool"/>
+ <property name="autoScroll" type="bool" isWritable="true"/>
+ <property name="selectByMouse" type="bool" isWritable="true"/>
<signal name="textChanged"/>
<signal name="cursorPositionChanged"/>
<signal name="selectionStartChanged"/>
@@ -4676,7 +4676,7 @@
<enumerator name="ThemeUser" value="65535"/>
</enum>
<property name="supported" type="bool"/>
- <property name="effect" type="ThemeEffect"/>
+ <property name="effect" type="ThemeEffect" isWritable="true"/>
<signal name="effectChanged"/>
<method name="play"/>
</type>
@@ -4685,11 +4685,11 @@
<export module="Qt" version="4.7" type="Timer"/>
<export module="QtQuick" version="1.0" type="Timer"/>
</exports>
- <property name="interval" type="int"/>
- <property name="running" type="bool"/>
- <property name="repeat" type="bool"/>
- <property name="triggeredOnStart" type="bool"/>
- <property name="parent" type="QObject"/>
+ <property name="interval" type="int" isWritable="true"/>
+ <property name="running" type="bool" isWritable="true"/>
+ <property name="repeat" type="bool" isWritable="true"/>
+ <property name="triggeredOnStart" type="bool" isWritable="true"/>
+ <property name="parent" type="QObject" isPointer="true"/>
<signal name="triggered"/>
<signal name="runningChanged"/>
<signal name="intervalChanged"/>
@@ -4704,9 +4704,9 @@
<export module="QtQuick" version="1.0" type="Transition"/>
<export module="Qt" version="4.7" type="Transition"/>
</exports>
- <property name="from" type="string"/>
- <property name="to" type="string"/>
- <property name="reversible" type="bool"/>
+ <property name="from" type="string" isWritable="true"/>
+ <property name="to" type="string" isWritable="true"/>
+ <property name="reversible" type="bool" isWritable="true"/>
<property name="animations" type="QDeclarativeAbstractAnimation" isList="true"/>
<signal name="fromChanged"/>
<signal name="toChanged"/>
@@ -4717,8 +4717,8 @@
<export module="QtQuick" version="1.0" type="Translate"/>
<export module="Qt" version="4.7" type="Translate"/>
</exports>
- <property name="x" type="qreal"/>
- <property name="y" type="qreal"/>
+ <property name="x" type="qreal" isWritable="true"/>
+ <property name="y" type="qreal" isWritable="true"/>
<signal name="xChanged"/>
<signal name="yChanged"/>
</type>
@@ -4728,8 +4728,8 @@
<export module="QtQuick" version="1.0" type="Vector3dAnimation"/>
<export module="Qt" version="4.7" type="Vector3dAnimation"/>
</exports>
- <property name="from" type="QVector3D"/>
- <property name="to" type="QVector3D"/>
+ <property name="from" type="QVector3D" isWritable="true"/>
+ <property name="to" type="QVector3D" isWritable="true"/>
</type>
<type name="QDeclarativeVideo" defaultProperty="data" extends="QDeclarativeItem">
<exports>
@@ -4759,24 +4759,24 @@
<enumerator name="AccessDenied" value="4"/>
<enumerator name="ServiceMissing" value="5"/>
</enum>
- <property name="source" type="QUrl"/>
- <property name="autoLoad" type="bool"/>
- <property name="playing" type="bool"/>
- <property name="paused" type="bool"/>
+ <property name="source" type="QUrl" isWritable="true"/>
+ <property name="autoLoad" type="bool" isWritable="true"/>
+ <property name="playing" type="bool" isWritable="true"/>
+ <property name="paused" type="bool" isWritable="true"/>
<property name="status" type="Status"/>
<property name="duration" type="int"/>
- <property name="position" type="int"/>
- <property name="volume" type="qreal"/>
- <property name="muted" type="bool"/>
+ <property name="position" type="int" isWritable="true"/>
+ <property name="volume" type="qreal" isWritable="true"/>
+ <property name="muted" type="bool" isWritable="true"/>
<property name="hasAudio" type="bool"/>
<property name="hasVideo" type="bool"/>
<property name="bufferProgress" type="int"/>
<property name="seekable" type="bool"/>
- <property name="playbackRate" type="qreal"/>
+ <property name="playbackRate" type="qreal" isWritable="true"/>
<property name="error" type="Error"/>
<property name="errorString" type="string"/>
- <property name="fillMode" type="FillMode"/>
- <property name="metaData" type="QDeclarativeMediaMetaData"/>
+ <property name="fillMode" type="FillMode" isWritable="true"/>
+ <property name="metaData" type="QDeclarativeMediaMetaData" isPointer="true"/>
<signal name="sourceChanged"/>
<signal name="autoLoadChanged"/>
<signal name="playingChanged"/>
@@ -4813,9 +4813,9 @@
<enumerator name="FullString" value="0"/>
<enumerator name="FirstCharacter" value="1"/>
</enum>
- <property name="property" type="string"/>
- <property name="criteria" type="SectionCriteria"/>
- <property name="delegate" type="QDeclarativeComponent"/>
+ <property name="property" type="string" isWritable="true"/>
+ <property name="criteria" type="SectionCriteria" isWritable="true"/>
+ <property name="delegate" type="QDeclarativeComponent" isWritable="true" isPointer="true"/>
<signal name="propertyChanged"/>
<signal name="criteriaChanged"/>
<signal name="delegateChanged"/>
@@ -4825,17 +4825,17 @@
<export module="QtQuick" version="1.0" type="VisualDataModel"/>
<export module="Qt" version="4.7" type="VisualDataModel"/>
</exports>
- <property name="model" type="QVariant"/>
- <property name="delegate" type="QDeclarativeComponent"/>
- <property name="part" type="string"/>
- <property name="parts" type="QObject"/>
- <property name="rootIndex" type="QVariant"/>
+ <property name="model" type="QVariant" isWritable="true"/>
+ <property name="delegate" type="QDeclarativeComponent" isWritable="true" isPointer="true"/>
+ <property name="part" type="string" isWritable="true"/>
+ <property name="parts" type="QObject" isPointer="true"/>
+ <property name="rootIndex" type="QVariant" isWritable="true"/>
<signal name="createdPackage">
<param name="index" type="int"/>
- <param name="package" type="QDeclarativePackage"/>
+ <param name="package" type="QDeclarativePackage" isPointer="true"/>
</signal>
<signal name="destroyingPackage">
- <param name="package" type="QDeclarativePackage"/>
+ <param name="package" type="QDeclarativePackage" isPointer="true"/>
</signal>
<signal name="rootIndexChanged"/>
<method name="modelIndex" type="QVariant">
@@ -4871,38 +4871,38 @@
<signal name="modelReset"/>
<signal name="createdItem">
<param name="index" type="int"/>
- <param name="item" type="QDeclarativeItem"/>
+ <param name="item" type="QDeclarativeItem" isPointer="true"/>
</signal>
<signal name="destroyingItem">
- <param name="item" type="QDeclarativeItem"/>
+ <param name="item" type="QDeclarativeItem" isPointer="true"/>
</signal>
</type>
<type name="QDeclarativeWebSettings" extends="QObject">
- <property name="standardFontFamily" type="string"/>
- <property name="fixedFontFamily" type="string"/>
- <property name="serifFontFamily" type="string"/>
- <property name="sansSerifFontFamily" type="string"/>
- <property name="cursiveFontFamily" type="string"/>
- <property name="fantasyFontFamily" type="string"/>
- <property name="minimumFontSize" type="int"/>
- <property name="minimumLogicalFontSize" type="int"/>
- <property name="defaultFontSize" type="int"/>
- <property name="defaultFixedFontSize" type="int"/>
- <property name="autoLoadImages" type="bool"/>
- <property name="javascriptEnabled" type="bool"/>
- <property name="javaEnabled" type="bool"/>
- <property name="pluginsEnabled" type="bool"/>
- <property name="privateBrowsingEnabled" type="bool"/>
- <property name="javascriptCanOpenWindows" type="bool"/>
- <property name="javascriptCanAccessClipboard" type="bool"/>
- <property name="developerExtrasEnabled" type="bool"/>
- <property name="linksIncludedInFocusChain" type="bool"/>
- <property name="zoomTextOnly" type="bool"/>
- <property name="printElementBackgrounds" type="bool"/>
- <property name="offlineStorageDatabaseEnabled" type="bool"/>
- <property name="offlineWebApplicationCacheEnabled" type="bool"/>
- <property name="localStorageDatabaseEnabled" type="bool"/>
- <property name="localContentCanAccessRemoteUrls" type="bool"/>
+ <property name="standardFontFamily" type="string" isWritable="true"/>
+ <property name="fixedFontFamily" type="string" isWritable="true"/>
+ <property name="serifFontFamily" type="string" isWritable="true"/>
+ <property name="sansSerifFontFamily" type="string" isWritable="true"/>
+ <property name="cursiveFontFamily" type="string" isWritable="true"/>
+ <property name="fantasyFontFamily" type="string" isWritable="true"/>
+ <property name="minimumFontSize" type="int" isWritable="true"/>
+ <property name="minimumLogicalFontSize" type="int" isWritable="true"/>
+ <property name="defaultFontSize" type="int" isWritable="true"/>
+ <property name="defaultFixedFontSize" type="int" isWritable="true"/>
+ <property name="autoLoadImages" type="bool" isWritable="true"/>
+ <property name="javascriptEnabled" type="bool" isWritable="true"/>
+ <property name="javaEnabled" type="bool" isWritable="true"/>
+ <property name="pluginsEnabled" type="bool" isWritable="true"/>
+ <property name="privateBrowsingEnabled" type="bool" isWritable="true"/>
+ <property name="javascriptCanOpenWindows" type="bool" isWritable="true"/>
+ <property name="javascriptCanAccessClipboard" type="bool" isWritable="true"/>
+ <property name="developerExtrasEnabled" type="bool" isWritable="true"/>
+ <property name="linksIncludedInFocusChain" type="bool" isWritable="true"/>
+ <property name="zoomTextOnly" type="bool" isWritable="true"/>
+ <property name="printElementBackgrounds" type="bool" isWritable="true"/>
+ <property name="offlineStorageDatabaseEnabled" type="bool" isWritable="true"/>
+ <property name="offlineWebApplicationCacheEnabled" type="bool" isWritable="true"/>
+ <property name="localStorageDatabaseEnabled" type="bool" isWritable="true"/>
+ <property name="localContentCanAccessRemoteUrls" type="bool" isWritable="true"/>
</type>
<type name="QDeclarativeWebView" defaultProperty="data" extends="QDeclarativeItem">
<exports>
@@ -4917,24 +4917,24 @@
<property name="title" type="string"/>
<property name="icon" type="QPixmap"/>
<property name="statusText" type="string"/>
- <property name="html" type="string"/>
- <property name="pressGrabTime" type="int"/>
- <property name="preferredWidth" type="int"/>
- <property name="preferredHeight" type="int"/>
- <property name="url" type="QUrl"/>
+ <property name="html" type="string" isWritable="true"/>
+ <property name="pressGrabTime" type="int" isWritable="true"/>
+ <property name="preferredWidth" type="int" isWritable="true"/>
+ <property name="preferredHeight" type="int" isWritable="true"/>
+ <property name="url" type="QUrl" isWritable="true"/>
<property name="progress" type="qreal"/>
<property name="status" type="Status"/>
- <property name="reload" type="QAction"/>
- <property name="back" type="QAction"/>
- <property name="forward" type="QAction"/>
- <property name="stop" type="QAction"/>
- <property name="settings" type="QDeclarativeWebSettings"/>
+ <property name="reload" type="QAction" isPointer="true"/>
+ <property name="back" type="QAction" isPointer="true"/>
+ <property name="forward" type="QAction" isPointer="true"/>
+ <property name="stop" type="QAction" isPointer="true"/>
+ <property name="settings" type="QDeclarativeWebSettings" isPointer="true"/>
<property name="javaScriptWindowObjects" type="QObject" isList="true"/>
- <property name="newWindowComponent" type="QDeclarativeComponent"/>
- <property name="newWindowParent" type="QDeclarativeItem"/>
- <property name="renderingEnabled" type="bool"/>
+ <property name="newWindowComponent" type="QDeclarativeComponent" isWritable="true" isPointer="true"/>
+ <property name="newWindowParent" type="QDeclarativeItem" isWritable="true" isPointer="true"/>
+ <property name="renderingEnabled" type="bool" isWritable="true"/>
<property name="contentsSize" type="QSize"/>
- <property name="contentsScale" type="qreal"/>
+ <property name="contentsScale" type="qreal" isWritable="true"/>
<signal name="preferredWidthChanged"/>
<signal name="preferredHeightChanged"/>
<signal name="urlChanged"/>
@@ -4985,7 +4985,7 @@
<export module="QtQuick" version="1.0" type="WorkerScript"/>
<export module="Qt" version="4.7" type="WorkerScript"/>
</exports>
- <property name="source" type="QUrl"/>
+ <property name="source" type="QUrl" isWritable="true"/>
<signal name="sourceChanged"/>
<signal name="message">
<param name="messageObject" type="QScriptValue"/>
@@ -5007,10 +5007,10 @@
</enum>
<property name="status" type="Status"/>
<property name="progress" type="qreal"/>
- <property name="source" type="QUrl"/>
- <property name="xml" type="string"/>
- <property name="query" type="string"/>
- <property name="namespaceDeclarations" type="string"/>
+ <property name="source" type="QUrl" isWritable="true"/>
+ <property name="xml" type="string" isWritable="true"/>
+ <property name="query" type="string" isWritable="true"/>
+ <property name="namespaceDeclarations" type="string" isWritable="true"/>
<property name="roles" type="QDeclarativeXmlListModelRole" isList="true"/>
<property name="count" type="int"/>
<signal name="statusChanged">
@@ -5035,9 +5035,9 @@
<export module="QtQuick" version="1.0" type="XmlRole"/>
<export module="Qt" version="4.7" type="XmlRole"/>
</exports>
- <property name="name" type="string"/>
- <property name="query" type="string"/>
- <property name="isKey" type="bool"/>
+ <property name="name" type="string" isWritable="true"/>
+ <property name="query" type="string" isWritable="true"/>
+ <property name="isKey" type="bool" isWritable="true"/>
<signal name="nameChanged"/>
<signal name="queryChanged"/>
<signal name="isKeyChanged"/>
@@ -5051,10 +5051,10 @@
<enumerator name="StandardNotation" value="0"/>
<enumerator name="ScientificNotation" value="1"/>
</enum>
- <property name="bottom" type="double"/>
- <property name="top" type="double"/>
- <property name="decimals" type="int"/>
- <property name="notation" type="Notation"/>
+ <property name="bottom" type="double" isWritable="true"/>
+ <property name="top" type="double" isWritable="true"/>
+ <property name="decimals" type="int" isWritable="true"/>
+ <property name="notation" type="Notation" isWritable="true"/>
</type>
<type name="QFeedbackActuator" extends="QObject">
<exports>
@@ -5073,7 +5073,7 @@
<property name="name" type="string"/>
<property name="state" type="QFeedbackActuator.State"/>
<property name="valid" type="bool"/>
- <property name="enabled" type="bool"/>
+ <property name="enabled" type="bool" isWritable="true"/>
<signal name="enabledChanged"/>
<method name="isCapabilitySupported" type="bool">
<param type="Capability"/>
@@ -5141,24 +5141,24 @@
<method name="pause"/>
</type>
<type name="QFeedbackFileEffect" extends="QFeedbackEffect">
- <property name="loaded" type="bool"/>
- <property name="source" type="QUrl"/>
+ <property name="loaded" type="bool" isWritable="true"/>
+ <property name="source" type="QUrl" isWritable="true"/>
</type>
<type name="QFeedbackHapticsEffect" extends="QFeedbackEffect">
- <property name="duration" type="int"/>
- <property name="intensity" type="qreal"/>
- <property name="attackTime" type="int"/>
- <property name="attackIntensity" type="qreal"/>
- <property name="fadeTime" type="int"/>
- <property name="fadeIntensity" type="int"/>
- <property name="period" type="int"/>
- <property name="actuator" type="QFeedbackActuator"/>
+ <property name="duration" type="int" isWritable="true"/>
+ <property name="intensity" type="qreal" isWritable="true"/>
+ <property name="attackTime" type="int" isWritable="true"/>
+ <property name="attackIntensity" type="qreal" isWritable="true"/>
+ <property name="fadeTime" type="int" isWritable="true"/>
+ <property name="fadeIntensity" type="int" isWritable="true"/>
+ <property name="period" type="int" isWritable="true"/>
+ <property name="actuator" type="QFeedbackActuator" isWritable="true" isPointer="true"/>
</type>
<type name="QGeoMapCircleObject" extends="QGeoMapObject">
- <property name="center" type="QGeoCoordinate"/>
- <property name="radius" type="qreal"/>
- <property name="pen" type="QPen"/>
- <property name="brush" type="QBrush"/>
+ <property name="center" type="QGeoCoordinate" isWritable="true"/>
+ <property name="radius" type="qreal" isWritable="true"/>
+ <property name="pen" type="QPen" isWritable="true"/>
+ <property name="brush" type="QBrush" isWritable="true"/>
<signal name="centerChanged">
<param name="center" type="QGeoCoordinate"/>
</signal>
@@ -5174,19 +5174,19 @@
</type>
<type name="QGeoMapGroupObject" extends="QGeoMapObject">
<signal name="childAdded">
- <param name="childObject" type="QGeoMapObject"/>
+ <param name="childObject" type="QGeoMapObject" isPointer="true"/>
</signal>
<signal name="childRemoved">
- <param name="childObject" type="QGeoMapObject"/>
+ <param name="childObject" type="QGeoMapObject" isPointer="true"/>
</signal>
</type>
<type name="QGeoMapObject" extends="QObject">
<exports>
<export module="QtMobility.location" version="1.1" type="QGeoMapObject"/>
</exports>
- <property name="zValue" type="int"/>
- <property name="visible" type="bool"/>
- <property name="selected" type="bool"/>
+ <property name="zValue" type="int" isWritable="true"/>
+ <property name="visible" type="bool" isWritable="true"/>
+ <property name="selected" type="bool" isWritable="true"/>
<signal name="zValueChanged">
<param name="zValue" type="int"/>
</signal>
@@ -5198,9 +5198,9 @@
</signal>
</type>
<type name="QGeoMapPixmapObject" extends="QGeoMapObject">
- <property name="coordinate" type="QGeoCoordinate"/>
- <property name="pixmap" type="QPixmap"/>
- <property name="offset" type="QPoint"/>
+ <property name="coordinate" type="QGeoCoordinate" isWritable="true"/>
+ <property name="pixmap" type="QPixmap" isWritable="true"/>
+ <property name="offset" type="QPoint" isWritable="true"/>
<signal name="coordinateChanged">
<param name="coordinate" type="QGeoCoordinate"/>
</signal>
@@ -5212,9 +5212,9 @@
</signal>
</type>
<type name="QGeoMapPolygonObject" extends="QGeoMapObject">
- <property name="path" type="QList&lt;QGeoCoordinate&gt;"/>
- <property name="pen" type="QPen"/>
- <property name="brush" type="QBrush"/>
+ <property name="path" type="QList&lt;QGeoCoordinate&gt;" isWritable="true"/>
+ <property name="pen" type="QPen" isWritable="true"/>
+ <property name="brush" type="QBrush" isWritable="true"/>
<signal name="pathChanged">
<param name="path" type="QList&lt;QGeoCoordinate&gt;"/>
</signal>
@@ -5226,8 +5226,8 @@
</signal>
</type>
<type name="QGeoMapPolylineObject" extends="QGeoMapObject">
- <property name="path" type="QList&lt;QGeoCoordinate&gt;"/>
- <property name="pen" type="QPen"/>
+ <property name="path" type="QList&lt;QGeoCoordinate&gt;" isWritable="true"/>
+ <property name="pen" type="QPen" isWritable="true"/>
<signal name="pathChanged">
<param name="path" type="QList&lt;QGeoCoordinate&gt;"/>
</signal>
@@ -5236,10 +5236,10 @@
</signal>
</type>
<type name="QGeoMapRectangleObject" extends="QGeoMapObject">
- <property name="topLeft" type="QGeoCoordinate"/>
- <property name="bottomRight" type="QGeoCoordinate"/>
- <property name="pen" type="QPen"/>
- <property name="brush" type="QBrush"/>
+ <property name="topLeft" type="QGeoCoordinate" isWritable="true"/>
+ <property name="bottomRight" type="QGeoCoordinate" isWritable="true"/>
+ <property name="pen" type="QPen" isWritable="true"/>
+ <property name="brush" type="QBrush" isWritable="true"/>
<signal name="topLeftChanged">
<param name="topLeft" type="QGeoCoordinate"/>
</signal>
@@ -5254,13 +5254,13 @@
</signal>
</type>
<type name="QGeoMapTextObject" extends="QGeoMapObject">
- <property name="coordinate" type="QGeoCoordinate"/>
- <property name="text" type="string"/>
- <property name="font" type="QFont"/>
- <property name="pen" type="QPen"/>
- <property name="brush" type="QBrush"/>
- <property name="offset" type="QPoint"/>
- <property name="alignment" type="Qt.Alignment"/>
+ <property name="coordinate" type="QGeoCoordinate" isWritable="true"/>
+ <property name="text" type="string" isWritable="true"/>
+ <property name="font" type="QFont" isWritable="true"/>
+ <property name="pen" type="QPen" isWritable="true"/>
+ <property name="brush" type="QBrush" isWritable="true"/>
+ <property name="offset" type="QPoint" isWritable="true"/>
+ <property name="alignment" type="Qt.Alignment" isWritable="true"/>
<signal name="coordinateChanged">
<param name="coordinate" type="QGeoCoordinate"/>
</signal>
@@ -5289,26 +5289,26 @@
</exports>
<property name="state" type="Qt.GestureState"/>
<property name="gestureType" type="Qt.GestureType"/>
- <property name="gestureCancelPolicy" type="QGesture.GestureCancelPolicy"/>
- <property name="hotSpot" type="QPointF"/>
+ <property name="gestureCancelPolicy" type="QGesture.GestureCancelPolicy" isWritable="true"/>
+ <property name="hotSpot" type="QPointF" isWritable="true"/>
<property name="hasHotSpot" type="bool"/>
</type>
<type name="QGraphicsObject" defaultProperty="children" extends="QObject">
- <property name="parent" type="QGraphicsObject"/>
- <property name="opacity" type="qreal"/>
- <property name="enabled" type="bool"/>
- <property name="visible" type="bool"/>
- <property name="pos" type="QPointF"/>
- <property name="x" type="qreal"/>
- <property name="y" type="qreal"/>
- <property name="z" type="qreal"/>
- <property name="rotation" type="qreal"/>
- <property name="scale" type="qreal"/>
- <property name="transformOriginPoint" type="QPointF"/>
- <property name="effect" type="QGraphicsEffect"/>
+ <property name="parent" type="QGraphicsObject" isWritable="true" isPointer="true"/>
+ <property name="opacity" type="qreal" isWritable="true"/>
+ <property name="enabled" type="bool" isWritable="true"/>
+ <property name="visible" type="bool" isWritable="true"/>
+ <property name="pos" type="QPointF" isWritable="true"/>
+ <property name="x" type="qreal" isWritable="true"/>
+ <property name="y" type="qreal" isWritable="true"/>
+ <property name="z" type="qreal" isWritable="true"/>
+ <property name="rotation" type="qreal" isWritable="true"/>
+ <property name="scale" type="qreal" isWritable="true"/>
+ <property name="transformOriginPoint" type="QPointF" isWritable="true"/>
+ <property name="effect" type="QGraphicsEffect" isWritable="true" isPointer="true"/>
<property name="children" type="QGraphicsObject" isList="true"/>
- <property name="width" type="qreal"/>
- <property name="height" type="qreal"/>
+ <property name="width" type="qreal" isWritable="true"/>
+ <property name="height" type="qreal" isWritable="true"/>
<signal name="parentChanged"/>
<signal name="opacityChanged"/>
<signal name="visibleChanged"/>
@@ -5327,9 +5327,9 @@
<export module="Qt" version="4.7" type="Rotation"/>
<export module="QtQuick" version="1.0" type="Rotation"/>
</exports>
- <property name="origin" type="QVector3D"/>
- <property name="angle" type="qreal"/>
- <property name="axis" type="QVector3D"/>
+ <property name="origin" type="QVector3D" isWritable="true"/>
+ <property name="angle" type="qreal" isWritable="true"/>
+ <property name="axis" type="QVector3D" isWritable="true"/>
<signal name="originChanged"/>
<signal name="angleChanged"/>
<signal name="axisChanged"/>
@@ -5339,10 +5339,10 @@
<export module="QtQuick" version="1.0" type="Scale"/>
<export module="Qt" version="4.7" type="Scale"/>
</exports>
- <property name="origin" type="QVector3D"/>
- <property name="xScale" type="qreal"/>
- <property name="yScale" type="qreal"/>
- <property name="zScale" type="qreal"/>
+ <property name="origin" type="QVector3D" isWritable="true"/>
+ <property name="xScale" type="qreal" isWritable="true"/>
+ <property name="yScale" type="qreal" isWritable="true"/>
+ <property name="zScale" type="qreal" isWritable="true"/>
<signal name="originChanged"/>
<signal name="xScaleChanged"/>
<signal name="yScaleChanged"/>
@@ -5355,7 +5355,7 @@
<export module="Qt" version="4.7" type="QGraphicsWidget"/>
<export module="QtQuick" version="1.0" type="QGraphicsWidget"/>
</exports>
- <property name="anchors" type="QDeclarativeAnchors"/>
+ <property name="anchors" type="QDeclarativeAnchors" isPointer="true"/>
<property name="left" type="QDeclarativeAnchorLine"/>
<property name="right" type="QDeclarativeAnchorLine"/>
<property name="horizontalCenter" type="QDeclarativeAnchorLine"/>
@@ -5368,8 +5368,8 @@
<export module="Qt" version="4.7" type="IntValidator"/>
<export module="QtQuick" version="1.0" type="IntValidator"/>
</exports>
- <property name="bottom" type="int"/>
- <property name="top" type="int"/>
+ <property name="bottom" type="int" isWritable="true"/>
+ <property name="top" type="int" isWritable="true"/>
</type>
<type name="QListModelInterface" extends="QObject">
<signal name="itemsInserted">
@@ -5410,9 +5410,9 @@
<export module="Qt" version="4.7" type="QtObject"/>
<export module="QtQuick" version="1.0" type="QtObject"/>
</exports>
- <property name="objectName" type="string"/>
+ <property name="objectName" type="string" isWritable="true"/>
<signal name="destroyed">
- <param type="QObject"/>
+ <param type="QObject" isPointer="true"/>
</signal>
<signal name="destroyed"/>
<method name="deleteLater"/>
@@ -5441,12 +5441,12 @@
<exports>
<export module="Qt.labs.gestures" version="1.0" type="PanGesture"/>
</exports>
- <property name="lastOffset" type="QPointF"/>
- <property name="offset" type="QPointF"/>
+ <property name="lastOffset" type="QPointF" isWritable="true"/>
+ <property name="offset" type="QPointF" isWritable="true"/>
<property name="delta" type="QPointF"/>
- <property name="acceleration" type="qreal"/>
- <property name="horizontalVelocity" type="qreal"/>
- <property name="verticalVelocity" type="qreal"/>
+ <property name="acceleration" type="qreal" isWritable="true"/>
+ <property name="horizontalVelocity" type="qreal" isWritable="true"/>
+ <property name="verticalVelocity" type="qreal" isWritable="true"/>
</type>
<type name="QPinchGesture" extends="QGesture">
<exports>
@@ -5462,17 +5462,17 @@
<enumerator name="RotationAngleChanged" value="2"/>
<enumerator name="CenterPointChanged" value="4"/>
</enum>
- <property name="totalChangeFlags" type="ChangeFlags"/>
- <property name="changeFlags" type="ChangeFlags"/>
- <property name="totalScaleFactor" type="qreal"/>
- <property name="lastScaleFactor" type="qreal"/>
- <property name="scaleFactor" type="qreal"/>
- <property name="totalRotationAngle" type="qreal"/>
- <property name="lastRotationAngle" type="qreal"/>
- <property name="rotationAngle" type="qreal"/>
- <property name="startCenterPoint" type="QPointF"/>
- <property name="lastCenterPoint" type="QPointF"/>
- <property name="centerPoint" type="QPointF"/>
+ <property name="totalChangeFlags" type="ChangeFlags" isWritable="true"/>
+ <property name="changeFlags" type="ChangeFlags" isWritable="true"/>
+ <property name="totalScaleFactor" type="qreal" isWritable="true"/>
+ <property name="lastScaleFactor" type="qreal" isWritable="true"/>
+ <property name="scaleFactor" type="qreal" isWritable="true"/>
+ <property name="totalRotationAngle" type="qreal" isWritable="true"/>
+ <property name="lastRotationAngle" type="qreal" isWritable="true"/>
+ <property name="rotationAngle" type="qreal" isWritable="true"/>
+ <property name="startCenterPoint" type="QPointF" isWritable="true"/>
+ <property name="lastCenterPoint" type="QPointF" isWritable="true"/>
+ <property name="centerPoint" type="QPointF" isWritable="true"/>
</type>
<type name="QProximityReading" extends="QSensorReading">
<exports>
@@ -5490,7 +5490,7 @@
<export module="QtQuick" version="1.0" type="RegExpValidator"/>
<export module="Qt" version="4.7" type="RegExpValidator"/>
</exports>
- <property name="regExp" type="QRegExp"/>
+ <property name="regExp" type="QRegExp" isWritable="true"/>
</type>
<type name="QRotationReading" extends="QSensorReading">
<exports>
@@ -5506,16 +5506,16 @@
</exports>
</type>
<type name="QSensor" extends="QObject">
- <property name="sensorid" type="QByteArray"/>
+ <property name="sensorid" type="QByteArray" isWritable="true"/>
<property name="type" type="QByteArray"/>
<property name="connectedToBackend" type="bool"/>
<property name="availableDataRates" type="QtMobility.qrangelist"/>
- <property name="dataRate" type="int"/>
- <property name="reading" type="QSensorReading"/>
+ <property name="dataRate" type="int" isWritable="true"/>
+ <property name="reading" type="QSensorReading" isPointer="true"/>
<property name="busy" type="bool"/>
- <property name="active" type="bool"/>
+ <property name="active" type="bool" isWritable="true"/>
<property name="outputRanges" type="QtMobility.qoutputrangelist"/>
- <property name="outputRange" type="int"/>
+ <property name="outputRange" type="int" isWritable="true"/>
<property name="description" type="string"/>
<property name="error" type="int"/>
<signal name="busyChanged"/>
@@ -5544,10 +5544,10 @@
<enumerator name="Ready" value="2"/>
<enumerator name="Error" value="3"/>
</enum>
- <property name="source" type="QUrl"/>
- <property name="loops" type="int"/>
- <property name="volume" type="qreal"/>
- <property name="muted" type="bool"/>
+ <property name="source" type="QUrl" isWritable="true"/>
+ <property name="loops" type="int" isWritable="true"/>
+ <property name="volume" type="qreal" isWritable="true"/>
+ <property name="muted" type="bool" isWritable="true"/>
<property name="playing" type="bool"/>
<property name="status" type="Status"/>
<signal name="sourceChanged"/>
@@ -5573,8 +5573,8 @@
</enum>
<property name="horizontalDirection" type="SwipeDirection"/>
<property name="verticalDirection" type="SwipeDirection"/>
- <property name="swipeAngle" type="qreal"/>
- <property name="velocity" type="qreal"/>
+ <property name="swipeAngle" type="qreal" isWritable="true"/>
+ <property name="velocity" type="qreal" isWritable="true"/>
</type>
<type name="QSystemDeviceInfo" extends="QObject">
<enum name="BatteryStatus">
@@ -5781,13 +5781,13 @@
<exports>
<export module="Qt.labs.gestures" version="1.0" type="TapAndHoldGesture"/>
</exports>
- <property name="position" type="QPointF"/>
+ <property name="position" type="QPointF" isWritable="true"/>
</type>
<type name="QTapGesture" extends="QGesture">
<exports>
<export module="Qt.labs.gestures" version="1.0" type="TapGesture"/>
</exports>
- <property name="position" type="QPointF"/>
+ <property name="position" type="QPointF" isWritable="true"/>
</type>
<type name="QTapReading" extends="QSensorReading">
<exports>
@@ -5818,7 +5818,7 @@
<exports>
<export module="QtMobility.publishsubscribe" version="1.1" type="ValueSpaceSubscriber"/>
</exports>
- <property name="path" type="string"/>
+ <property name="path" type="string" isWritable="true"/>
<property name="value" type="QVariant"/>
<signal name="contentsChanged"/>
</type>
@@ -6918,20 +6918,24 @@
</enum>
</type>
<type name="__extended__.QGraphicsWidget" defaultProperty="children" extends="QGraphicsObject">
- <property name="palette" type="QPalette"/>
- <property name="font" type="QFont"/>
- <property name="layoutDirection" type="Qt.LayoutDirection"/>
- <property name="size" type="QSizeF"/>
- <property name="minimumSize" type="QSizeF"/>
- <property name="preferredSize" type="QSizeF"/>
- <property name="maximumSize" type="QSizeF"/>
- <property name="sizePolicy" type="QSizePolicy"/>
- <property name="focusPolicy" type="Qt.FocusPolicy"/>
- <property name="windowFlags" type="Qt.WindowFlags"/>
- <property name="windowTitle" type="string"/>
- <property name="geometry" type="QRectF"/>
- <property name="autoFillBackground" type="bool"/>
- <property name="layout" type="QGraphicsLayout"/>
+ <exports>
+ <export module="Qt" version="4.7" type="QGraphicsWidget"/>
+ <export module="QtQuick" version="1.0" type="QGraphicsWidget"/>
+ </exports>
+ <property name="palette" type="QPalette" isWritable="true"/>
+ <property name="font" type="QFont" isWritable="true"/>
+ <property name="layoutDirection" type="Qt.LayoutDirection" isWritable="true"/>
+ <property name="size" type="QSizeF" isWritable="true"/>
+ <property name="minimumSize" type="QSizeF" isWritable="true"/>
+ <property name="preferredSize" type="QSizeF" isWritable="true"/>
+ <property name="maximumSize" type="QSizeF" isWritable="true"/>
+ <property name="sizePolicy" type="QSizePolicy" isWritable="true"/>
+ <property name="focusPolicy" type="Qt.FocusPolicy" isWritable="true"/>
+ <property name="windowFlags" type="Qt.WindowFlags" isWritable="true"/>
+ <property name="windowTitle" type="string" isWritable="true"/>
+ <property name="geometry" type="QRectF" isWritable="true"/>
+ <property name="autoFillBackground" type="bool" isWritable="true"/>
+ <property name="layout" type="QGraphicsLayout" isWritable="true" isPointer="true"/>
<signal name="geometryChanged"/>
<signal name="layoutChanged"/>
<method name="close" type="bool"/>
diff --git a/share/qtcreator/qml-type-descriptions/qmlproject-types.xml b/share/qtcreator/qml-type-descriptions/qmlproject-types.xml
index f8ae4aa1bc..192b45d686 100644
--- a/share/qtcreator/qml-type-descriptions/qmlproject-types.xml
+++ b/share/qtcreator/qml-type-descriptions/qmlproject-types.xml
@@ -3,8 +3,10 @@
<type name="QmlProject.Project">
<exports>
<export module="QmlProject" version="1.0" type="Project"/>
+ <export module="QmlProject" version="1.1" type="Project"/>
</exports>
<property name="sourceDirectory" type="string"/>
+ <property name="mainFile" type="string"/>
<property name="importPaths" type="string" isList="true"/>
<property name="content" type="QmlProjectItem" isList="true"/>
</type>
@@ -19,24 +21,34 @@
<type name="QmlProject.QmlFiles" extends="FileFilterBaseItem">
<exports>
<export module="QmlProject" version="1.0" type="QmlFiles"/>
+ <export module="QmlProject" version="1.1" type="QmlFiles"/>
</exports>
</type>
<type name="QmlProject.JavaScriptFiles" extends="FileFilterBaseItem">
<exports>
<export module="QmlProject" version="1.0" type="JavaScriptFiles"/>
+ <export module="QmlProject" version="1.1" type="JavaScriptFiles"/>
</exports>
<property name="filter" type="string"/>
</type>
<type name="QmlProject.ImageFiles" extends="FileFilterBaseItem">
<exports>
<export module="QmlProject" version="1.0" type="ImageFiles"/>
+ <export module="QmlProject" version="1.1" type="ImageFiles"/>
</exports>
<property name="filter" type="string"/>
</type>
<type name="QmlProject.CssFiles" extends="FileFilterBaseItem">
<exports>
<export module="QmlProject" version="1.0" type="CssFiles"/>
+ <export module="QmlProject" version="1.1" type="CssFiles"/>
</exports>
<property name="filter" type="string"/>
</type>
+ <type name="QmlProject.Files" extends="FileFilterBaseItem">
+ <exports>
+ <export module="QmlProject" version="1.1" type="Files"/>
+ </exports>
+ <property name="filter" type="string"/>
+ </type>
</module>
diff --git a/share/qtcreator/qml/qmldump/main.cpp b/share/qtcreator/qml/qmldump/main.cpp
index 46334c4d37..7f78567ef7 100644
--- a/share/qtcreator/qml/qmldump/main.cpp
+++ b/share/qtcreator/qml/qmldump/main.cpp
@@ -85,13 +85,17 @@ void processDeclarativeType(const QDeclarativeType *ty, QSet<const QMetaObject *
processMetaObject(ty->metaObject(), metas);
}
-void writeType(QXmlStreamAttributes *attrs, QByteArray typeName)
+void writeType(QXmlStreamAttributes *attrs, QByteArray typeName, bool isWritable = false)
{
bool isList = false, isPointer = false;
erasure(&typeName, &isList, &isPointer);
attrs->append(QXmlStreamAttribute("type", typeName));
if (isList)
attrs->append(QXmlStreamAttribute("isList", "true"));
+ if (isWritable)
+ attrs->append(QXmlStreamAttribute("isWritable", "true"));
+ if (isPointer)
+ attrs->append(QXmlStreamAttribute("isPointer", "true"));
}
void dump(const QMetaProperty &prop, QXmlStreamWriter *xml)
@@ -101,7 +105,7 @@ void dump(const QMetaProperty &prop, QXmlStreamWriter *xml)
QXmlStreamAttributes attributes;
attributes.append(QXmlStreamAttribute("name", QString::fromUtf8(prop.name())));
- writeType(&attributes, prop.typeName());
+ writeType(&attributes, prop.typeName(), prop.isWritable());
xml->writeAttributes(attributes);
xml->writeEndElement();
@@ -210,7 +214,7 @@ void dump(const QMetaObject *meta, QXmlStreamWriter *xml)
xml->writeAttributes(attributes);
- QList<const QDeclarativeType *> qmlTypes = qmlTypesByCppName.value(id);
+ QList<const QDeclarativeType *> qmlTypes = qmlTypesByCppName.value(meta->className());
if (!qmlTypes.isEmpty()) {
xml->writeStartElement("exports");
foreach (const QDeclarativeType *qmlTy, qmlTypes) {
diff --git a/share/qtcreator/qml/qmljsdebugger/editor/abstractformeditortool.cpp b/share/qtcreator/qml/qmljsdebugger/editor/abstractformeditortool.cpp
index 35b90ef42d..69e9cd4d18 100644
--- a/share/qtcreator/qml/qmljsdebugger/editor/abstractformeditortool.cpp
+++ b/share/qtcreator/qml/qmljsdebugger/editor/abstractformeditortool.cpp
@@ -90,7 +90,8 @@ bool AbstractFormEditorTool::topItemIsMovable(const QList<QGraphicsItem*> & item
if (firstSelectableItem == 0)
return false;
- QDeclarativeItem *declarativeItem = dynamic_cast<QDeclarativeItem*>(firstSelectableItem->toGraphicsObject());
+ QDeclarativeItem *declarativeItem
+ = dynamic_cast<QDeclarativeItem*>(firstSelectableItem->toGraphicsObject());
if (declarativeItem != 0)
return true;
@@ -106,8 +107,8 @@ bool AbstractFormEditorTool::topSelectedItemIsMovable(const QList<QGraphicsItem*
foreach (QGraphicsItem *item, itemList) {
QDeclarativeItem *declarativeItem = toQDeclarativeItem(item);
if (declarativeItem
- && selectedItems.contains(declarativeItem)
- /*&& (declarativeItem->qmlItemNode().hasShowContent() || selectNonContentItems)*/)
+ && selectedItems.contains(declarativeItem)
+ /*&& (declarativeItem->qmlItemNode().hasShowContent() || selectNonContentItems)*/)
return true;
}
@@ -134,7 +135,8 @@ QGraphicsItem *AbstractFormEditorTool::topMovableGraphicsItem(const QList<QGraph
return 0;
}
-QDeclarativeItem *AbstractFormEditorTool::topMovableDeclarativeItem(const QList<QGraphicsItem*> &itemList)
+QDeclarativeItem *AbstractFormEditorTool::topMovableDeclarativeItem(const QList<QGraphicsItem*>
+ &itemList)
{
foreach (QGraphicsItem *item, itemList) {
QDeclarativeItem *declarativeItem = toQDeclarativeItem(item);
@@ -145,7 +147,8 @@ QDeclarativeItem *AbstractFormEditorTool::topMovableDeclarativeItem(const QList<
return 0;
}
-QList<QGraphicsObject*> AbstractFormEditorTool::toGraphicsObjectList(const QList<QGraphicsItem*> &itemList)
+QList<QGraphicsObject*> AbstractFormEditorTool::toGraphicsObjectList(const QList<QGraphicsItem*>
+ &itemList)
{
QList<QGraphicsObject*> gfxObjects;
foreach(QGraphicsItem *item, itemList) {
@@ -157,18 +160,6 @@ QList<QGraphicsObject*> AbstractFormEditorTool::toGraphicsObjectList(const QList
return gfxObjects;
}
-QList<QObject*> AbstractFormEditorTool::toObjectList(const QList<QGraphicsItem*> &itemList)
-{
- QList<QObject*> objects;
- foreach(QGraphicsItem *item, itemList) {
- QObject *obj = item->toGraphicsObject();
- if (obj)
- objects << obj;
- }
-
- return objects;
-}
-
QString AbstractFormEditorTool::titleForItem(QGraphicsItem *item)
{
QString className("QGraphicsItem");
diff --git a/share/qtcreator/qml/qmljsdebugger/editor/abstractformeditortool.h b/share/qtcreator/qml/qmljsdebugger/editor/abstractformeditortool.h
index 4787584532..52323ebc60 100644
--- a/share/qtcreator/qml/qmljsdebugger/editor/abstractformeditortool.h
+++ b/share/qtcreator/qml/qmljsdebugger/editor/abstractformeditortool.h
@@ -87,7 +87,6 @@ public:
bool topSelectedItemIsMovable(const QList<QGraphicsItem*> &itemList);
static QString titleForItem(QGraphicsItem *item);
- static QList<QObject*> toObjectList(const QList<QGraphicsItem*> &itemList);
static QList<QGraphicsObject*> toGraphicsObjectList(const QList<QGraphicsItem*> &itemList);
static QGraphicsItem* topMovableGraphicsItem(const QList<QGraphicsItem*> &itemList);
static QDeclarativeItem* topMovableDeclarativeItem(const QList<QGraphicsItem*> &itemList);
diff --git a/share/qtcreator/qml/qmljsdebugger/editor/boundingrecthighlighter.cpp b/share/qtcreator/qml/qmljsdebugger/editor/boundingrecthighlighter.cpp
index e35bd34b62..11846b395c 100644
--- a/share/qtcreator/qml/qmljsdebugger/editor/boundingrecthighlighter.cpp
+++ b/share/qtcreator/qml/qmljsdebugger/editor/boundingrecthighlighter.cpp
@@ -47,7 +47,8 @@ const qreal AnimDelta = 0.025f;
const int AnimInterval = 30;
const int AnimFrames = 10;
-BoundingBox::BoundingBox(QGraphicsObject *itemToHighlight, QGraphicsItem *parentItem, QObject *parent)
+BoundingBox::BoundingBox(QGraphicsObject *itemToHighlight, QGraphicsItem *parentItem,
+ QObject *parent)
: QObject(parent),
highlightedObject(itemToHighlight),
highlightPolygon(0),
@@ -247,7 +248,8 @@ void BoundingRectHighlighter::highlightAll(bool animate)
QPolygonF boundingRectInSceneSpace(item->mapToScene(itemAndChildRect));
QPolygonF boundingRectInLayerItemSpace = mapFromScene(boundingRectInSceneSpace);
- QRectF bboxRect = m_view->adjustToScreenBoundaries(boundingRectInLayerItemSpace.boundingRect());
+ QRectF bboxRect
+ = m_view->adjustToScreenBoundaries(boundingRectInLayerItemSpace.boundingRect());
QRectF edgeRect = bboxRect;
edgeRect.adjust(-1, -1, 1, 1);
diff --git a/share/qtcreator/qml/qmljsdebugger/editor/boundingrecthighlighter.h b/share/qtcreator/qml/qmljsdebugger/editor/boundingrecthighlighter.h
index 9d6d752656..b4c89198e9 100644
--- a/share/qtcreator/qml/qmljsdebugger/editor/boundingrecthighlighter.h
+++ b/share/qtcreator/qml/qmljsdebugger/editor/boundingrecthighlighter.h
@@ -88,7 +88,8 @@ class BoundingBox : public QObject
{
Q_OBJECT
public:
- explicit BoundingBox(QGraphicsObject *itemToHighlight, QGraphicsItem *parentItem, QObject *parent = 0);
+ explicit BoundingBox(QGraphicsObject *itemToHighlight, QGraphicsItem *parentItem,
+ QObject *parent = 0);
~BoundingBox();
QWeakPointer<QGraphicsObject> highlightedObject;
QGraphicsPolygonItem *highlightPolygon;
diff --git a/share/qtcreator/qml/qmljsdebugger/editor/colorpickertool.cpp b/share/qtcreator/qml/qmljsdebugger/editor/colorpickertool.cpp
index 995f437bda..66771de68e 100644
--- a/share/qtcreator/qml/qmljsdebugger/editor/colorpickertool.cpp
+++ b/share/qtcreator/qml/qmljsdebugger/editor/colorpickertool.cpp
@@ -45,7 +45,7 @@
namespace QmlJSDebugger {
ColorPickerTool::ColorPickerTool(QDeclarativeViewObserver *view) :
- AbstractFormEditorTool(view)
+ AbstractFormEditorTool(view)
{
m_selectedColor.setRgb(0,0,0);
}
diff --git a/share/qtcreator/qml/qmljsdebugger/editor/editor.pri b/share/qtcreator/qml/qmljsdebugger/editor/editor.pri
deleted file mode 100644
index c54c839f6e..0000000000
--- a/share/qtcreator/qml/qmljsdebugger/editor/editor.pri
+++ /dev/null
@@ -1,40 +0,0 @@
-# This file is part of Qt Creator
-# It enables debugging of Qt Quick applications
-
-INCLUDEPATH += $$PWD
-
-HEADERS += \
- $$PWD/abstractformeditortool.h \
- $$PWD/selectiontool.h \
- $$PWD/layeritem.h \
- $$PWD/singleselectionmanipulator.h \
- $$PWD/rubberbandselectionmanipulator.h \
- $$PWD/selectionrectangle.h \
- $$PWD/selectionindicator.h \
- $$PWD/boundingrecthighlighter.h \
- $$PWD/subcomponenteditortool.h \
- $$PWD/subcomponentmasklayeritem.h \
- $$PWD/zoomtool.h \
- $$PWD/colorpickertool.h \
- $$PWD/qmltoolbar.h \
- $$PWD/toolbarcolorbox.h
-
-SOURCES += \
- $$PWD/abstractformeditortool.cpp \
- $$PWD/selectiontool.cpp \
- $$PWD/layeritem.cpp \
- $$PWD/singleselectionmanipulator.cpp \
- $$PWD/rubberbandselectionmanipulator.cpp \
- $$PWD/selectionrectangle.cpp \
- $$PWD/selectionindicator.cpp \
- $$PWD/boundingrecthighlighter.cpp \
- $$PWD/subcomponenteditortool.cpp \
- $$PWD/subcomponentmasklayeritem.cpp \
- $$PWD/zoomtool.cpp \
- $$PWD/colorpickertool.cpp \
- $$PWD/qmltoolbar.cpp \
- $$PWD/toolbarcolorbox.cpp
-
-RESOURCES += $$PWD/editor.qrc
-
-DEFINES += QWEAKPOINTER_ENABLE_ARROW
diff --git a/share/qtcreator/qml/qmljsdebugger/editor/layeritem.cpp b/share/qtcreator/qml/qmljsdebugger/editor/layeritem.cpp
index 4db35dc78a..1470174f57 100644
--- a/share/qtcreator/qml/qmljsdebugger/editor/layeritem.cpp
+++ b/share/qtcreator/qml/qmljsdebugger/editor/layeritem.cpp
@@ -39,7 +39,7 @@
namespace QmlJSDebugger {
LayerItem::LayerItem(QGraphicsScene* scene)
- : QGraphicsObject()
+ : QGraphicsObject()
{
scene->addItem(this);
setZValue(1);
@@ -50,7 +50,8 @@ LayerItem::~LayerItem()
{
}
-void LayerItem::paint(QPainter * /*painter*/, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/)
+void LayerItem::paint(QPainter * /*painter*/, const QStyleOptionGraphicsItem * /*option*/,
+ QWidget * /*widget*/)
{
}
diff --git a/share/qtcreator/qml/qmljsdebugger/editor/layeritem.h b/share/qtcreator/qml/qmljsdebugger/editor/layeritem.h
index 4a4ed13078..43024837d1 100644
--- a/share/qtcreator/qml/qmljsdebugger/editor/layeritem.h
+++ b/share/qtcreator/qml/qmljsdebugger/editor/layeritem.h
@@ -44,9 +44,10 @@ class FormEditorScene;
class LayerItem : public QGraphicsObject
{
public:
- LayerItem(QGraphicsScene* scene);
+ LayerItem(QGraphicsScene *scene);
~LayerItem();
- void paint ( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0 );
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
+ QWidget *widget = 0);
QRectF boundingRect() const;
int type() const;
diff --git a/share/qtcreator/qml/qmljsdebugger/editor/qmltoolbar.cpp b/share/qtcreator/qml/qmljsdebugger/editor/qmltoolbar.cpp
index 2de969a80d..98be5f2fb3 100644
--- a/share/qtcreator/qml/qmljsdebugger/editor/qmltoolbar.cpp
+++ b/share/qtcreator/qml/qmljsdebugger/editor/qmltoolbar.cpp
@@ -54,14 +54,19 @@ QmlToolbar::QmlToolbar(QWidget *parent)
ui->playIcon = QIcon(QLatin1String(":/qml/images/play-24.png"));
ui->pauseIcon = QIcon(QLatin1String(":/qml/images/pause-24.png"));
- ui->designmode = new QAction(QIcon(QLatin1String(":/qml/images/observermode-24.png")), tr("Observer Mode"), this);
+ ui->designmode = new QAction(QIcon(QLatin1String(":/qml/images/observermode-24.png")),
+ tr("Observer Mode"), this);
ui->play = new QAction(ui->pauseIcon, tr("Play/Pause Animations"), this);
ui->select = new QAction(QIcon(QLatin1String(":/qml/images/select-24.png")), tr("Select"), this);
- ui->selectMarquee = new QAction(QIcon(QLatin1String(":/qml/images/select-marquee-24.png")), tr("Select (Marquee)"), this);
+ ui->selectMarquee = new QAction(QIcon(QLatin1String(":/qml/images/select-marquee-24.png")),
+ tr("Select (Marquee)"), this);
ui->zoom = new QAction(QIcon(QLatin1String(":/qml/images/zoom-24.png")), tr("Zoom"), this);
- ui->colorPicker = new QAction(QIcon(QLatin1String(":/qml/images/color-picker-24.png")), tr("Color Picker"), this);
- ui->toQml = new QAction(QIcon(QLatin1String(":/qml/images/to-qml-24.png")), tr("Apply Changes to QML Viewer"), this);
- ui->fromQml = new QAction(QIcon(QLatin1String(":/qml/images/from-qml-24.png")), tr("Apply Changes to Document"), this);
+ ui->colorPicker = new QAction(QIcon(QLatin1String(":/qml/images/color-picker-24.png")),
+ tr("Color Picker"), this);
+ ui->toQml = new QAction(QIcon(QLatin1String(":/qml/images/to-qml-24.png")),
+ tr("Apply Changes to QML Viewer"), this);
+ ui->fromQml = new QAction(QIcon(QLatin1String(":/qml/images/from-qml-24.png")),
+ tr("Apply Changes to Document"), this);
ui->designmode->setCheckable(true);
ui->designmode->setChecked(false);
@@ -98,24 +103,29 @@ QmlToolbar::QmlToolbar(QWidget *parent)
playSpeedMenuActions->setExclusive(true);
playSpeedMenu->addAction(tr("Animation Speed"));
playSpeedMenu->addSeparator();
- ui->defaultAnimSpeedAction = playSpeedMenu->addAction(tr("1x"), this, SLOT(changeToDefaultAnimSpeed()));
+ ui->defaultAnimSpeedAction = playSpeedMenu->addAction(tr("1x"), this,
+ SLOT(changeToDefaultAnimSpeed()));
ui->defaultAnimSpeedAction->setCheckable(true);
ui->defaultAnimSpeedAction->setChecked(true);
playSpeedMenuActions->addAction(ui->defaultAnimSpeedAction);
- ui->halfAnimSpeedAction = playSpeedMenu->addAction(tr("0.5x"), this, SLOT(changeToHalfAnimSpeed()));
+ ui->halfAnimSpeedAction = playSpeedMenu->addAction(tr("0.5x"), this,
+ SLOT(changeToHalfAnimSpeed()));
ui->halfAnimSpeedAction->setCheckable(true);
playSpeedMenuActions->addAction(ui->halfAnimSpeedAction);
- ui->fourthAnimSpeedAction = playSpeedMenu->addAction(tr("0.25x"), this, SLOT(changeToFourthAnimSpeed()));
+ ui->fourthAnimSpeedAction = playSpeedMenu->addAction(tr("0.25x"), this,
+ SLOT(changeToFourthAnimSpeed()));
ui->fourthAnimSpeedAction->setCheckable(true);
playSpeedMenuActions->addAction(ui->fourthAnimSpeedAction);
- ui->eighthAnimSpeedAction = playSpeedMenu->addAction(tr("0.125x"), this, SLOT(changeToEighthAnimSpeed()));
+ ui->eighthAnimSpeedAction = playSpeedMenu->addAction(tr("0.125x"), this,
+ SLOT(changeToEighthAnimSpeed()));
ui->eighthAnimSpeedAction->setCheckable(true);
playSpeedMenuActions->addAction(ui->eighthAnimSpeedAction);
- ui->tenthAnimSpeedAction = playSpeedMenu->addAction(tr("0.1x"), this, SLOT(changeToTenthAnimSpeed()));
+ ui->tenthAnimSpeedAction = playSpeedMenu->addAction(tr("0.1x"), this,
+ SLOT(changeToTenthAnimSpeed()));
ui->tenthAnimSpeedAction->setCheckable(true);
playSpeedMenuActions->addAction(ui->tenthAnimSpeedAction);
diff --git a/share/qtcreator/qml/qmljsdebugger/editor/rubberbandselectionmanipulator.cpp b/share/qtcreator/qml/qmljsdebugger/editor/rubberbandselectionmanipulator.cpp
index 6be2902523..a3957c41ec 100644
--- a/share/qtcreator/qml/qmljsdebugger/editor/rubberbandselectionmanipulator.cpp
+++ b/share/qtcreator/qml/qmljsdebugger/editor/rubberbandselectionmanipulator.cpp
@@ -38,11 +38,12 @@
namespace QmlJSDebugger {
-RubberBandSelectionManipulator::RubberBandSelectionManipulator(QGraphicsObject *layerItem, QDeclarativeViewObserver *editorView)
+RubberBandSelectionManipulator::RubberBandSelectionManipulator(QGraphicsObject *layerItem,
+ QDeclarativeViewObserver *editorView)
: m_selectionRectangleElement(layerItem),
- m_editorView(editorView),
- m_beginFormEditorItem(0),
- m_isActive(false)
+ m_editorView(editorView),
+ m_beginFormEditorItem(0),
+ m_isActive(false)
{
m_selectionRectangleElement.hide();
}
@@ -56,7 +57,8 @@ void RubberBandSelectionManipulator::clear()
m_oldSelectionList.clear();
}
-QGraphicsItem *RubberBandSelectionManipulator::topFormEditorItem(const QList<QGraphicsItem*> &itemList)
+QGraphicsItem *RubberBandSelectionManipulator::topFormEditorItem(const QList<QGraphicsItem*>
+ &itemList)
{
if (itemList.isEmpty())
return 0;
@@ -70,7 +72,9 @@ void RubberBandSelectionManipulator::begin(const QPointF& beginPoint)
m_selectionRectangleElement.setRect(m_beginPoint, m_beginPoint);
m_selectionRectangleElement.show();
m_isActive = true;
- m_beginFormEditorItem = topFormEditorItem(QDeclarativeViewObserverPrivate::get(m_editorView)->selectableItems(beginPoint));
+ QDeclarativeViewObserverPrivate *observerPrivate
+ = QDeclarativeViewObserverPrivate::get(m_editorView);
+ m_beginFormEditorItem = topFormEditorItem(observerPrivate->selectableItems(beginPoint));
m_oldSelectionList = m_editorView->selectedItems();
}
@@ -88,16 +92,19 @@ void RubberBandSelectionManipulator::end()
void RubberBandSelectionManipulator::select(SelectionType selectionType)
{
- QList<QGraphicsItem*> itemList = QDeclarativeViewObserverPrivate::get(m_editorView)->selectableItems(m_selectionRectangleElement.rect(),
- Qt::IntersectsItemShape);
+ QDeclarativeViewObserverPrivate *observerPrivate
+ = QDeclarativeViewObserverPrivate::get(m_editorView);
+ QList<QGraphicsItem*> itemList
+ = observerPrivate->selectableItems(m_selectionRectangleElement.rect(),
+ Qt::IntersectsItemShape);
QList<QGraphicsItem*> newSelectionList;
foreach (QGraphicsItem* item, itemList) {
if (item
- && item->parentItem()
- && !newSelectionList.contains(item)
- //&& m_beginFormEditorItem->childItems().contains(item) // TODO activate this test
- )
+ && item->parentItem()
+ && !newSelectionList.contains(item)
+ //&& m_beginFormEditorItem->childItems().contains(item) // TODO activate this test
+ )
{
newSelectionList.append(item);
}
@@ -110,19 +117,19 @@ void RubberBandSelectionManipulator::select(SelectionType selectionType)
switch(selectionType) {
case AddToSelection: {
- resultList.append(m_oldSelectionList);
- resultList.append(newSelectionList);
- }
+ resultList.append(m_oldSelectionList);
+ resultList.append(newSelectionList);
+ }
break;
case ReplaceSelection: {
- resultList.append(newSelectionList);
- }
+ resultList.append(newSelectionList);
+ }
break;
case RemoveFromSelection: {
- QSet<QGraphicsItem*> oldSelectionSet(m_oldSelectionList.toSet());
- QSet<QGraphicsItem*> newSelectionSet(newSelectionList.toSet());
- resultList.append(oldSelectionSet.subtract(newSelectionSet).toList());
- }
+ QSet<QGraphicsItem*> oldSelectionSet(m_oldSelectionList.toSet());
+ QSet<QGraphicsItem*> newSelectionSet(newSelectionList.toSet());
+ resultList.append(oldSelectionSet.subtract(newSelectionSet).toList());
+ }
}
m_editorView->setSelectedItems(resultList);
@@ -142,7 +149,6 @@ QPointF RubberBandSelectionManipulator::beginPoint() const
bool RubberBandSelectionManipulator::isActive() const
{
return m_isActive;
-
}
-}
+} // namespace QmlJSDebugger
diff --git a/share/qtcreator/qml/qmljsdebugger/editor/rubberbandselectionmanipulator.h b/share/qtcreator/qml/qmljsdebugger/editor/rubberbandselectionmanipulator.h
index 02cd5ba9c6..a5982795e3 100644
--- a/share/qtcreator/qml/qmljsdebugger/editor/rubberbandselectionmanipulator.h
+++ b/share/qtcreator/qml/qmljsdebugger/editor/rubberbandselectionmanipulator.h
@@ -50,8 +50,8 @@ public:
RemoveFromSelection
};
-
- RubberBandSelectionManipulator(QGraphicsObject *layerItem, QDeclarativeViewObserver *editorView);
+ RubberBandSelectionManipulator(QGraphicsObject *layerItem,
+ QDeclarativeViewObserver *editorView);
void setItems(const QList<QGraphicsItem*> &itemList);
@@ -70,7 +70,6 @@ public:
protected:
QGraphicsItem *topFormEditorItem(const QList<QGraphicsItem*> &itemList);
-
private:
QList<QGraphicsItem*> m_itemList;
QList<QGraphicsItem*> m_oldSelectionList;
diff --git a/share/qtcreator/qml/qmljsdebugger/editor/selectionindicator.cpp b/share/qtcreator/qml/qmljsdebugger/editor/selectionindicator.cpp
index d063c1a81e..b249e25c45 100644
--- a/share/qtcreator/qml/qmljsdebugger/editor/selectionindicator.cpp
+++ b/share/qtcreator/qml/qmljsdebugger/editor/selectionindicator.cpp
@@ -42,7 +42,8 @@
namespace QmlJSDebugger {
-SelectionIndicator::SelectionIndicator(QDeclarativeViewObserver *editorView, QGraphicsObject *layerItem)
+SelectionIndicator::SelectionIndicator(QDeclarativeViewObserver *editorView,
+ QGraphicsObject *layerItem)
: m_layerItem(layerItem), m_view(editorView)
{
}
@@ -70,7 +71,7 @@ void SelectionIndicator::clear()
QHashIterator<QGraphicsItem*, QGraphicsPolygonItem *> iter(m_indicatorShapeHash);
while(iter.hasNext()) {
iter.next();
- m_layerItem->scene()->removeItem(iter.value());
+ m_layerItem.data()->scene()->removeItem(iter.value());
delete iter.value();
}
}
@@ -107,19 +108,22 @@ void SelectionIndicator::setItems(const QList<QWeakPointer<QGraphicsObject> > &i
QGraphicsItem *item = object.data();
- QGraphicsPolygonItem *newSelectionIndicatorGraphicsItem = new QGraphicsPolygonItem(m_layerItem.data());
+ QGraphicsPolygonItem *newSelectionIndicatorGraphicsItem
+ = new QGraphicsPolygonItem(m_layerItem.data());
if (!m_indicatorShapeHash.contains(item)) {
m_indicatorShapeHash.insert(item, newSelectionIndicatorGraphicsItem);
QPolygonF boundingShapeInSceneSpace;
addBoundingRectToPolygon(item, boundingShapeInSceneSpace);
- QRectF boundingRect = m_view->adjustToScreenBoundaries(boundingShapeInSceneSpace.boundingRect());
- QPolygonF boundingRectInLayerItemSpace = m_layerItem->mapFromScene(boundingRect);
+ QRectF boundingRect
+ = m_view->adjustToScreenBoundaries(boundingShapeInSceneSpace.boundingRect());
+ QPolygonF boundingRectInLayerItemSpace = m_layerItem.data()->mapFromScene(boundingRect);
QPen pen;
pen.setColor(QColor(108, 141, 221));
- newSelectionIndicatorGraphicsItem->setData(Constants::EditorItemDataKey, QVariant(true));
+ newSelectionIndicatorGraphicsItem->setData(Constants::EditorItemDataKey,
+ QVariant(true));
newSelectionIndicatorGraphicsItem->setFlag(QGraphicsItem::ItemIsSelectable, false);
newSelectionIndicatorGraphicsItem->setPolygon(boundingRectInLayerItemSpace);
newSelectionIndicatorGraphicsItem->setPen(pen);
diff --git a/share/qtcreator/qml/qmljsdebugger/editor/selectionrectangle.cpp b/share/qtcreator/qml/qmljsdebugger/editor/selectionrectangle.cpp
index b9f877ec21..979760bc3b 100644
--- a/share/qtcreator/qml/qmljsdebugger/editor/selectionrectangle.cpp
+++ b/share/qtcreator/qml/qmljsdebugger/editor/selectionrectangle.cpp
@@ -51,7 +51,7 @@ public:
SelectionRectangle::SelectionRectangle(QGraphicsObject *layerItem)
: m_controlShape(new SelectionRectShape(layerItem)),
- m_layerItem(layerItem)
+ m_layerItem(layerItem)
{
m_controlShape->setPen(QPen(Qt::black));
m_controlShape->setBrush(QColor(128, 128, 128, 50));
@@ -60,7 +60,7 @@ SelectionRectangle::SelectionRectangle(QGraphicsObject *layerItem)
SelectionRectangle::~SelectionRectangle()
{
if (m_layerItem)
- m_layerItem->scene()->removeItem(m_controlShape);
+ m_layerItem.data()->scene()->removeItem(m_controlShape);
}
void SelectionRectangle::clear()
@@ -89,8 +89,10 @@ void SelectionRectangle::setRect(const QPointF &firstPoint,
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);
+ 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/share/qtcreator/qml/qmljsdebugger/editor/selectiontool.cpp b/share/qtcreator/qml/qmljsdebugger/editor/selectiontool.cpp
index 7169d6704e..4393b9c2b4 100644
--- a/share/qtcreator/qml/qmljsdebugger/editor/selectiontool.cpp
+++ b/share/qtcreator/qml/qmljsdebugger/editor/selectiontool.cpp
@@ -52,12 +52,14 @@
namespace QmlJSDebugger {
-SelectionTool::SelectionTool(QDeclarativeViewObserver *editorView)
- : AbstractFormEditorTool(editorView),
+SelectionTool::SelectionTool(QDeclarativeViewObserver *editorView) :
+ AbstractFormEditorTool(editorView),
m_rubberbandSelectionMode(false),
- m_rubberbandSelectionManipulator(QDeclarativeViewObserverPrivate::get(editorView)->manipulatorLayer, editorView),
+ m_rubberbandSelectionManipulator(
+ QDeclarativeViewObserverPrivate::get(editorView)->manipulatorLayer, editorView),
m_singleSelectionManipulator(editorView),
- m_selectionIndicator(editorView, QDeclarativeViewObserverPrivate::get(editorView)->manipulatorLayer),
+ m_selectionIndicator(editorView,
+ QDeclarativeViewObserverPrivate::get(editorView)->manipulatorLayer),
//m_resizeIndicator(editorView->manipulatorLayer()),
m_selectOnlyContentItems(true)
{
@@ -73,9 +75,11 @@ void SelectionTool::setRubberbandSelectionMode(bool value)
m_rubberbandSelectionMode = value;
}
-SingleSelectionManipulator::SelectionType SelectionTool::getSelectionType(Qt::KeyboardModifiers modifiers)
+SingleSelectionManipulator::SelectionType SelectionTool::getSelectionType(Qt::KeyboardModifiers
+ modifiers)
{
- SingleSelectionManipulator::SelectionType selectionType = SingleSelectionManipulator::ReplaceSelection;
+ SingleSelectionManipulator::SelectionType selectionType
+ = SingleSelectionManipulator::ReplaceSelection;
if (modifiers.testFlag(Qt::ControlModifier)) {
selectionType = SingleSelectionManipulator::RemoveFromSelection;
} else if (modifiers.testFlag(Qt::ShiftModifier)) {
@@ -86,7 +90,9 @@ SingleSelectionManipulator::SelectionType SelectionTool::getSelectionType(Qt::Ke
bool SelectionTool::alreadySelected(const QList<QGraphicsItem*> &itemList) const
{
- const QList<QGraphicsItem*> selectedItems = QDeclarativeViewObserverPrivate::get(observer())->selectedItems();
+ QDeclarativeViewObserverPrivate *observerPrivate
+ = QDeclarativeViewObserverPrivate::get(observer());
+ const QList<QGraphicsItem*> selectedItems = observerPrivate->selectedItems();
if (selectedItems.isEmpty())
return false;
@@ -102,7 +108,9 @@ bool SelectionTool::alreadySelected(const QList<QGraphicsItem*> &itemList) const
void SelectionTool::mousePressEvent(QMouseEvent *event)
{
- QList<QGraphicsItem*> itemList = QDeclarativeViewObserverPrivate::get(observer())->selectableItems(event->pos());
+ QDeclarativeViewObserverPrivate *observerPrivate
+ = QDeclarativeViewObserverPrivate::get(observer());
+ QList<QGraphicsItem*> itemList = observerPrivate->selectableItems(event->pos());
SingleSelectionManipulator::SelectionType selectionType = getSelectionType(event->modifiers());
if (event->buttons() & Qt::LeftButton) {
@@ -111,51 +119,9 @@ void SelectionTool::mousePressEvent(QMouseEvent *event)
if (m_rubberbandSelectionMode) {
m_rubberbandSelectionManipulator.begin(event->pos());
} else {
-
- if (itemList.isEmpty()) {
- QDeclarativeViewObserverPrivate::get(observer())->setSelectedItems(itemList);
- return;
- }
-
- if ((selectionType == SingleSelectionManipulator::InvertSelection
- || selectionType == SingleSelectionManipulator::ReplaceSelection)
- && alreadySelected(itemList))
- {
- //view()->changeToMoveTool(event->pos());
- return;
- }
-
- QGraphicsItem* item = itemList.first();
-
- if (item->children().isEmpty()) {
- m_singleSelectionManipulator.begin(event->pos());
- m_singleSelectionManipulator.select(selectionType, m_selectOnlyContentItems);
- } else {
- m_mousePressTimer.start();
-
- if (itemList.isEmpty()) {
- observer()->setSelectedItems(itemList);
- return;
- }
-
- if (item->children().isEmpty()) {
- m_singleSelectionManipulator.begin(event->pos());
- m_singleSelectionManipulator.select(selectionType, m_selectOnlyContentItems);
- } else {
- m_singleSelectionManipulator.begin(event->pos());
- m_singleSelectionManipulator.select(selectionType, m_selectOnlyContentItems);
- m_singleSelectionManipulator.end(event->pos());
- //view()->changeToMoveTool(event->pos());
- }
-
- m_singleSelectionManipulator.begin(event->pos());
- m_singleSelectionManipulator.select(selectionType, m_selectOnlyContentItems);
- m_singleSelectionManipulator.end(event->pos());
- //view()->changeToMoveTool(event->pos());
-
- }
+ m_singleSelectionManipulator.begin(event->pos());
+ m_singleSelectionManipulator.select(selectionType, m_selectOnlyContentItems);
}
-
} else if (event->buttons() & Qt::RightButton) {
createContextMenu(itemList, event->globalPos());
}
@@ -167,7 +133,8 @@ void SelectionTool::createContextMenu(QList<QGraphicsItem*> itemList, QPoint glo
return;
QMenu contextMenu;
- connect(&contextMenu, SIGNAL(hovered(QAction*)), this, SLOT(contextMenuElementHovered(QAction*)));
+ connect(&contextMenu, SIGNAL(hovered(QAction*)),
+ this, SLOT(contextMenuElementHovered(QAction*)));
m_contextMenuItemList = itemList;
@@ -179,7 +146,8 @@ void SelectionTool::createContextMenu(QList<QGraphicsItem*> itemList, QPoint glo
foreach(QGraphicsItem * const item, itemList) {
QString itemTitle = titleForItem(item);
- QAction *elementAction = contextMenu.addAction(itemTitle, this, SLOT(contextMenuElementSelected()));
+ QAction *elementAction = contextMenu.addAction(itemTitle, this,
+ SLOT(contextMenuElementSelected()));
if (observer()->selectedItems().contains(item)) {
QFont boldFont = elementAction->font();
@@ -198,9 +166,9 @@ void SelectionTool::createContextMenu(QList<QGraphicsItem*> itemList, QPoint glo
++i;
}
// add root item separately
-// QString itemTitle = QString(tr("%1")).arg(titleForItem(view()->currentRootItem()));
-// contextMenu.addAction(itemTitle, this, SLOT(contextMenuElementSelected()));
-// m_contextMenuItemList.append(view()->currentRootItem());
+ // QString itemTitle = QString(tr("%1")).arg(titleForItem(view()->currentRootItem()));
+ // contextMenu.addAction(itemTitle, this, SLOT(contextMenuElementSelected()));
+ // m_contextMenuItemList.append(view()->currentRootItem());
contextMenu.exec(globalPos);
m_contextMenuItemList.clear();
@@ -238,7 +206,7 @@ void SelectionTool::mouseMoveEvent(QMouseEvent *event)
QPointF mouseMovementVector = m_singleSelectionManipulator.beginPoint() - event->pos();
if ((mouseMovementVector.toPoint().manhattanLength() > Constants::DragStartDistance)
- && (m_mousePressTimer.elapsed() > Constants::DragStartTime))
+ && (m_mousePressTimer.elapsed() > Constants::DragStartTime))
{
m_singleSelectionManipulator.end(event->pos());
//view()->changeToMoveTool(m_singleSelectionManipulator.beginPoint());
@@ -248,15 +216,18 @@ void SelectionTool::mouseMoveEvent(QMouseEvent *event)
QPointF mouseMovementVector = m_rubberbandSelectionManipulator.beginPoint() - event->pos();
if ((mouseMovementVector.toPoint().manhattanLength() > Constants::DragStartDistance)
- && (m_mousePressTimer.elapsed() > Constants::DragStartTime)) {
+ && (m_mousePressTimer.elapsed() > Constants::DragStartTime)) {
m_rubberbandSelectionManipulator.update(event->pos());
if (event->modifiers().testFlag(Qt::ControlModifier))
- m_rubberbandSelectionManipulator.select(RubberBandSelectionManipulator::RemoveFromSelection);
+ m_rubberbandSelectionManipulator.select(
+ RubberBandSelectionManipulator::RemoveFromSelection);
else if (event->modifiers().testFlag(Qt::ShiftModifier))
- m_rubberbandSelectionManipulator.select(RubberBandSelectionManipulator::AddToSelection);
+ m_rubberbandSelectionManipulator.select(
+ RubberBandSelectionManipulator::AddToSelection);
else
- m_rubberbandSelectionManipulator.select(RubberBandSelectionManipulator::ReplaceSelection);
+ m_rubberbandSelectionManipulator.select(
+ RubberBandSelectionManipulator::ReplaceSelection);
}
}
}
@@ -278,7 +249,10 @@ void SelectionTool::hoverMoveEvent(QMouseEvent * event)
// if (topSelectedItemIsMovable(itemList))
// view()->changeTool(Constants::MoveToolMode);
// }
- QList<QGraphicsItem*> selectableItemList = QDeclarativeViewObserverPrivate::get(observer())->selectableItems(event->pos());
+ QDeclarativeViewObserverPrivate *observerPrivate
+ = QDeclarativeViewObserverPrivate::get(observer());
+
+ QList<QGraphicsItem*> selectableItemList = observerPrivate->selectableItems(event->pos());
if (!selectableItemList.isEmpty()) {
QGraphicsObject *item = selectableItemList.first()->toGraphicsObject();
if (item)
@@ -302,22 +276,28 @@ void SelectionTool::mouseReleaseEvent(QMouseEvent *event)
m_singleSelectionManipulator.begin(event->pos());
if (event->modifiers().testFlag(Qt::ControlModifier))
- m_singleSelectionManipulator.select(SingleSelectionManipulator::RemoveFromSelection, m_selectOnlyContentItems);
+ m_singleSelectionManipulator.select(SingleSelectionManipulator::RemoveFromSelection,
+ m_selectOnlyContentItems);
else if (event->modifiers().testFlag(Qt::ShiftModifier))
- m_singleSelectionManipulator.select(SingleSelectionManipulator::AddToSelection, m_selectOnlyContentItems);
+ m_singleSelectionManipulator.select(SingleSelectionManipulator::AddToSelection,
+ m_selectOnlyContentItems);
else
- m_singleSelectionManipulator.select(SingleSelectionManipulator::InvertSelection, m_selectOnlyContentItems);
+ m_singleSelectionManipulator.select(SingleSelectionManipulator::InvertSelection,
+ m_selectOnlyContentItems);
m_singleSelectionManipulator.end(event->pos());
} else {
m_rubberbandSelectionManipulator.update(event->pos());
if (event->modifiers().testFlag(Qt::ControlModifier))
- m_rubberbandSelectionManipulator.select(RubberBandSelectionManipulator::RemoveFromSelection);
+ m_rubberbandSelectionManipulator.select(
+ RubberBandSelectionManipulator::RemoveFromSelection);
else if (event->modifiers().testFlag(Qt::ShiftModifier))
- m_rubberbandSelectionManipulator.select(RubberBandSelectionManipulator::AddToSelection);
+ m_rubberbandSelectionManipulator.select(
+ RubberBandSelectionManipulator::AddToSelection);
else
- m_rubberbandSelectionManipulator.select(RubberBandSelectionManipulator::ReplaceSelection);
+ m_rubberbandSelectionManipulator.select(
+ RubberBandSelectionManipulator::ReplaceSelection);
m_rubberbandSelectionManipulator.end();
}
@@ -332,14 +312,14 @@ void SelectionTool::mouseDoubleClickEvent(QMouseEvent * /*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:
- // disabled for now, cannot move stuff yet.
- //view()->changeTool(Constants::MoveToolMode);
- //view()->currentTool()->keyPressEvent(event);
- break;
+ case Qt::Key_Left:
+ case Qt::Key_Right:
+ case Qt::Key_Up:
+ case Qt::Key_Down:
+ // disabled for now, cannot move stuff yet.
+ //view()->changeTool(Constants::MoveToolMode);
+ //view()->currentTool()->keyPressEvent(event);
+ break;
}
}
@@ -353,7 +333,9 @@ void SelectionTool::wheelEvent(QWheelEvent *event)
if (event->orientation() == Qt::Horizontal || m_rubberbandSelectionMode)
return;
- QList<QGraphicsItem*> itemList = QDeclarativeViewObserverPrivate::get(observer())->selectableItems(event->pos());
+ QDeclarativeViewObserverPrivate *observerPrivate
+ = QDeclarativeViewObserverPrivate::get(observer());
+ QList<QGraphicsItem*> itemList = observerPrivate->selectableItems(event->pos());
if (itemList.isEmpty())
return;
@@ -399,7 +381,7 @@ void SelectionTool::clear()
{
view()->setCursor(Qt::ArrowCursor);
m_rubberbandSelectionManipulator.clear(),
- m_singleSelectionManipulator.clear();
+ m_singleSelectionManipulator.clear();
m_selectionIndicator.clear();
//m_resizeIndicator.clear();
}
@@ -442,13 +424,16 @@ void SelectionTool::selectUnderPoint(QMouseEvent *event)
m_singleSelectionManipulator.begin(event->pos());
if (event->modifiers().testFlag(Qt::ControlModifier))
- m_singleSelectionManipulator.select(SingleSelectionManipulator::RemoveFromSelection, m_selectOnlyContentItems);
+ m_singleSelectionManipulator.select(SingleSelectionManipulator::RemoveFromSelection,
+ m_selectOnlyContentItems);
else if (event->modifiers().testFlag(Qt::ShiftModifier))
- m_singleSelectionManipulator.select(SingleSelectionManipulator::AddToSelection, m_selectOnlyContentItems);
+ m_singleSelectionManipulator.select(SingleSelectionManipulator::AddToSelection,
+ m_selectOnlyContentItems);
else
- m_singleSelectionManipulator.select(SingleSelectionManipulator::InvertSelection, m_selectOnlyContentItems);
+ m_singleSelectionManipulator.select(SingleSelectionManipulator::InvertSelection,
+ m_selectOnlyContentItems);
m_singleSelectionManipulator.end(event->pos());
}
-}
+} // namespace QmlJSDebugger
diff --git a/share/qtcreator/qml/qmljsdebugger/editor/selectiontool.h b/share/qtcreator/qml/qmljsdebugger/editor/selectiontool.h
index 36ca6e439b..7e7827bd58 100644
--- a/share/qtcreator/qml/qmljsdebugger/editor/selectiontool.h
+++ b/share/qtcreator/qml/qmljsdebugger/editor/selectiontool.h
@@ -68,8 +68,8 @@ public:
void keyReleaseEvent(QKeyEvent *keyEvent);
void wheelEvent(QWheelEvent *event);
- void itemsAboutToRemoved(const QList<QGraphicsItem*> &itemList);
- // QVariant itemChange(const QList<QGraphicsItem*> &itemList,
+ void itemsAboutToRemoved(const QList<QGraphicsItem*> &itemList);
+// QVariant itemChange(const QList<QGraphicsItem*> &itemList,
// QGraphicsItem::GraphicsItemChange change,
// const QVariant &value );
diff --git a/share/qtcreator/qml/qmljsdebugger/editor/singleselectionmanipulator.cpp b/share/qtcreator/qml/qmljsdebugger/editor/singleselectionmanipulator.cpp
index ea97a4b975..54df1f6747 100644
--- a/share/qtcreator/qml/qmljsdebugger/editor/singleselectionmanipulator.cpp
+++ b/share/qtcreator/qml/qmljsdebugger/editor/singleselectionmanipulator.cpp
@@ -40,7 +40,7 @@ namespace QmlJSDebugger {
SingleSelectionManipulator::SingleSelectionManipulator(QDeclarativeViewObserver *editorView)
: m_editorView(editorView),
- m_isActive(false)
+ m_isActive(false)
{
}
@@ -70,7 +70,9 @@ void SingleSelectionManipulator::end(const QPointF &/*updatePoint*/)
m_isActive = false;
}
-void SingleSelectionManipulator::select(SelectionType selectionType, const QList<QGraphicsItem*> &items, bool /*selectOnlyContentItems*/)
+void SingleSelectionManipulator::select(SelectionType selectionType,
+ const QList<QGraphicsItem*> &items,
+ bool /*selectOnlyContentItems*/)
{
QGraphicsItem *selectedItem = 0;
@@ -78,8 +80,8 @@ void SingleSelectionManipulator::select(SelectionType selectionType, const QList
{
//FormEditorItem *formEditorItem = FormEditorItem::fromQGraphicsItem(item);
if (item
- /*&& !formEditorItem->qmlItemNode().isRootNode()
- && (formEditorItem->qmlItemNode().hasShowContent() || !selectOnlyContentItems)*/)
+ /*&& !formEditorItem->qmlItemNode().isRootNode()
+ && (formEditorItem->qmlItemNode().hasShowContent() || !selectOnlyContentItems)*/)
{
selectedItem = item;
break;
@@ -89,38 +91,40 @@ void SingleSelectionManipulator::select(SelectionType selectionType, const QList
QList<QGraphicsItem*> resultList;
switch(selectionType) {
- case AddToSelection: {
- resultList.append(m_oldSelectionList);
- if (selectedItem && !m_oldSelectionList.contains(selectedItem))
- resultList.append(selectedItem);
- }
+ case AddToSelection: {
+ resultList.append(m_oldSelectionList);
+ if (selectedItem && !m_oldSelectionList.contains(selectedItem))
+ resultList.append(selectedItem);
+ }
break;
- case ReplaceSelection: {
- if (selectedItem)
- resultList.append(selectedItem);
- }
+ case ReplaceSelection: {
+ if (selectedItem)
+ resultList.append(selectedItem);
+ }
break;
- case RemoveFromSelection: {
- resultList.append(m_oldSelectionList);
- if (selectedItem)
- resultList.removeAll(selectedItem);
- }
+ case RemoveFromSelection: {
+ resultList.append(m_oldSelectionList);
+ if (selectedItem)
+ resultList.removeAll(selectedItem);
+ }
break;
- case InvertSelection: {
- if (selectedItem
+ case InvertSelection: {
+ if (selectedItem
&& !m_oldSelectionList.contains(selectedItem))
- {
- resultList.append(selectedItem);
- }
+ {
+ resultList.append(selectedItem);
}
}
+ }
m_editorView->setSelectedItems(resultList);
}
void SingleSelectionManipulator::select(SelectionType selectionType, bool selectOnlyContentItems)
{
- QList<QGraphicsItem*> itemList = QDeclarativeViewObserverPrivate::get(m_editorView)->selectableItems(m_beginPoint);
+ QDeclarativeViewObserverPrivate *observerPrivate =
+ QDeclarativeViewObserverPrivate::get(m_editorView);
+ QList<QGraphicsItem*> itemList = observerPrivate->selectableItems(m_beginPoint);
select(selectionType, itemList, selectOnlyContentItems);
}
@@ -135,4 +139,4 @@ QPointF SingleSelectionManipulator::beginPoint() const
return m_beginPoint;
}
-}
+} // namespace QmlJSDebugger
diff --git a/share/qtcreator/qml/qmljsdebugger/editor/singleselectionmanipulator.h b/share/qtcreator/qml/qmljsdebugger/editor/singleselectionmanipulator.h
index 1458c5a8c4..94f57eef79 100644
--- a/share/qtcreator/qml/qmljsdebugger/editor/singleselectionmanipulator.h
+++ b/share/qtcreator/qml/qmljsdebugger/editor/singleselectionmanipulator.h
@@ -59,7 +59,8 @@ public:
void update(const QPointF& updatePoint);
void end(const QPointF& updatePoint);
- void select(SelectionType selectionType, const QList<QGraphicsItem*> &items, bool selectOnlyContentItems);
+ void select(SelectionType selectionType, const QList<QGraphicsItem*> &items,
+ bool selectOnlyContentItems);
void select(SelectionType selectionType, bool selectOnlyContentItems);
void clear();
diff --git a/share/qtcreator/qml/qmljsdebugger/editor/subcomponenteditortool.cpp b/share/qtcreator/qml/qmljsdebugger/editor/subcomponenteditortool.cpp
index 25955be0d7..42f1273eed 100644
--- a/share/qtcreator/qml/qmljsdebugger/editor/subcomponenteditortool.cpp
+++ b/share/qtcreator/qml/qmljsdebugger/editor/subcomponenteditortool.cpp
@@ -51,10 +51,12 @@ const qreal MaxOpacity = 0.5f;
SubcomponentEditorTool::SubcomponentEditorTool(QDeclarativeViewObserver *view)
: AbstractFormEditorTool(view),
- m_animIncrement(0.05f),
- m_animTimer(new QTimer(this))
+ m_animIncrement(0.05f),
+ m_animTimer(new QTimer(this))
{
- m_mask = new SubcomponentMaskLayerItem(view, QDeclarativeViewObserverPrivate::get(view)->manipulatorLayer);
+ QDeclarativeViewObserverPrivate *observerPrivate =
+ QDeclarativeViewObserverPrivate::get(view);
+ m_mask = new SubcomponentMaskLayerItem(view, observerPrivate->manipulatorLayer);
connect(m_animTimer, SIGNAL(timeout()), SLOT(animate()));
m_animTimer->setInterval(20);
}
@@ -80,7 +82,8 @@ bool SubcomponentEditorTool::containsCursor(const QPoint &mousePos) const
return false;
QPointF scenePos = view()->mapToScene(mousePos);
- QRectF itemRect = m_currentContext.top()->boundingRect() | m_currentContext.top()->childrenBoundingRect();
+ QRectF itemRect = m_currentContext.top()->boundingRect()
+ | m_currentContext.top()->childrenBoundingRect();
QRectF polyRect = m_currentContext.top()->mapToScene(itemRect).boundingRect();
return polyRect.contains(scenePos);
@@ -94,8 +97,8 @@ void SubcomponentEditorTool::mouseReleaseEvent(QMouseEvent * /*event*/)
void SubcomponentEditorTool::mouseDoubleClickEvent(QMouseEvent *event)
{
if (event->buttons() & Qt::LeftButton
- && !containsCursor(event->pos())
- && m_currentContext.size() > 1)
+ && !containsCursor(event->pos())
+ && m_currentContext.size() > 1)
{
aboutToPopContext();
}
@@ -182,7 +185,7 @@ void SubcomponentEditorTool::setCurrentItem(QGraphicsItem* contextItem)
bool containsSelectableItems = false;
foreach(QGraphicsItem *item, gfxObject->childItems()) {
if (item->type() == Constants::EditorItemType
- || item->type() == Constants::ResizeHandleItemType)
+ || item->type() == Constants::ResizeHandleItemType)
{
continue;
}
@@ -314,7 +317,8 @@ QGraphicsObject *SubcomponentEditorTool::currentRootItem() const
void SubcomponentEditorTool::contextDestroyed(QObject *contextToDestroy)
{
- disconnect(contextToDestroy, SIGNAL(destroyed(QObject*)), this, SLOT(contextDestroyed(QObject*)));
+ disconnect(contextToDestroy, SIGNAL(destroyed(QObject*)),
+ this, SLOT(contextDestroyed(QObject*)));
// pop out the whole context - it might not be safe anymore.
while (m_currentContext.size() > 1) {
@@ -349,5 +353,4 @@ int SubcomponentEditorTool::contextIndex() const
return m_currentContext.size() - 1;
}
-
} // namespace QmlJSDebugger
diff --git a/share/qtcreator/qml/qmljsdebugger/editor/subcomponentmasklayeritem.cpp b/share/qtcreator/qml/qmljsdebugger/editor/subcomponentmasklayeritem.cpp
index 61a3c1775d..42500dd267 100644
--- a/share/qtcreator/qml/qmljsdebugger/editor/subcomponentmasklayeritem.cpp
+++ b/share/qtcreator/qml/qmljsdebugger/editor/subcomponentmasklayeritem.cpp
@@ -38,7 +38,8 @@
namespace QmlJSDebugger {
-SubcomponentMaskLayerItem::SubcomponentMaskLayerItem(QDeclarativeViewObserver *observer, QGraphicsItem *parentItem) :
+SubcomponentMaskLayerItem::SubcomponentMaskLayerItem(QDeclarativeViewObserver *observer,
+ QGraphicsItem *parentItem) :
QGraphicsPolygonItem(parentItem),
m_observer(observer),
m_currentItem(0),
diff --git a/share/qtcreator/qml/qmljsdebugger/editor/subcomponentmasklayeritem.h b/share/qtcreator/qml/qmljsdebugger/editor/subcomponentmasklayeritem.h
index f726d06ed3..44a297ecd3 100644
--- a/share/qtcreator/qml/qmljsdebugger/editor/subcomponentmasklayeritem.h
+++ b/share/qtcreator/qml/qmljsdebugger/editor/subcomponentmasklayeritem.h
@@ -43,7 +43,8 @@ class QDeclarativeViewObserver;
class SubcomponentMaskLayerItem : public QGraphicsPolygonItem
{
public:
- explicit SubcomponentMaskLayerItem(QDeclarativeViewObserver *observer, QGraphicsItem *parentItem = 0);
+ explicit SubcomponentMaskLayerItem(QDeclarativeViewObserver *observer,
+ QGraphicsItem *parentItem = 0);
int type() const;
void setCurrentItem(QGraphicsItem *item);
void setBoundingBox(const QRectF &boundingBox);
diff --git a/share/qtcreator/qml/qmljsdebugger/editor/toolbarcolorbox.cpp b/share/qtcreator/qml/qmljsdebugger/editor/toolbarcolorbox.cpp
index 827740ed7f..e6574625f1 100644
--- a/share/qtcreator/qml/qmljsdebugger/editor/toolbarcolorbox.cpp
+++ b/share/qtcreator/qml/qmljsdebugger/editor/toolbarcolorbox.cpp
@@ -52,7 +52,8 @@ namespace QmlJSDebugger {
ToolBarColorBox::ToolBarColorBox(QWidget *parent) :
QLabel(parent)
{
- m_copyHexColor = new QAction(QIcon(QLatin1String(":/qml/images/color-picker-hicontrast.png")), tr("Copy"), this);
+ m_copyHexColor = new QAction(QIcon(QLatin1String(":/qml/images/color-picker-hicontrast.png")),
+ tr("Copy"), this);
connect(m_copyHexColor, SIGNAL(triggered()), SLOT(copyColorToClipboard()));
setScaledContents(false);
}
@@ -74,9 +75,11 @@ void ToolBarColorBox::mousePressEvent(QMouseEvent *event)
void ToolBarColorBox::mouseMoveEvent(QMouseEvent *event)
{
+
if (event->buttons() & Qt::LeftButton
- && QPoint(event->pos() - m_dragBeginPoint).manhattanLength() > Constants::DragStartDistance
- && !m_dragStarted)
+ && (QPoint(event->pos() - m_dragBeginPoint).manhattanLength()
+ > Constants::DragStartDistance)
+ && !m_dragStarted)
{
m_dragStarted = true;
QDrag *drag = new QDrag(this);
@@ -125,5 +128,4 @@ void ToolBarColorBox::copyColorToClipboard()
clipboard->setText(m_color.name());
}
-
} // namespace QmlJSDebugger
diff --git a/share/qtcreator/qml/qmljsdebugger/editor/zoomtool.cpp b/share/qtcreator/qml/qmljsdebugger/editor/zoomtool.cpp
index 0ba6a75db5..7bfd5be476 100644
--- a/share/qtcreator/qml/qmljsdebugger/editor/zoomtool.cpp
+++ b/share/qtcreator/qml/qmljsdebugger/editor/zoomtool.cpp
@@ -46,10 +46,10 @@
namespace QmlJSDebugger {
ZoomTool::ZoomTool(QDeclarativeViewObserver *view) :
- AbstractFormEditorTool(view),
- m_rubberbandManipulator(reinterpret_cast<QGraphicsObject *>(QDeclarativeViewObserverPrivate::get(view)->manipulatorLayer), view),
- m_smoothZoomMultiplier(0.05f),
- m_currentScale(1.0f)
+ AbstractFormEditorTool(view),
+ m_rubberbandManipulator(),
+ m_smoothZoomMultiplier(0.05f),
+ m_currentScale(1.0f)
{
m_zoomTo100Action = new QAction(tr("Zoom to &100%"), this);
m_zoomInAction = new QAction(tr("Zoom In"), this);
@@ -57,6 +57,12 @@ ZoomTool::ZoomTool(QDeclarativeViewObserver *view) :
m_zoomInAction->setShortcut(QKeySequence(Qt::Key_Plus));
m_zoomOutAction->setShortcut(QKeySequence(Qt::Key_Minus));
+
+ LayerItem *layerItem = QDeclarativeViewObserverPrivate::get(view)->manipulatorLayer;
+ QGraphicsObject *layerObject = reinterpret_cast<QGraphicsObject *>(layerItem);
+ m_rubberbandManipulator = new RubberBandSelectionManipulator(layerObject, view);
+
+
connect(m_zoomTo100Action, SIGNAL(triggered()), SLOT(zoomTo100()));
connect(m_zoomInAction, SIGNAL(triggered()), SLOT(zoomIn()));
connect(m_zoomOutAction, SIGNAL(triggered()), SLOT(zoomOut()));
@@ -64,7 +70,7 @@ ZoomTool::ZoomTool(QDeclarativeViewObserver *view) :
ZoomTool::~ZoomTool()
{
-
+ delete m_rubberbandManipulator;
}
void ZoomTool::mousePressEvent(QMouseEvent *event)
@@ -93,16 +99,17 @@ void ZoomTool::mouseMoveEvent(QMouseEvent *event)
QPointF scenePos = view()->mapToScene(event->pos());
if (event->buttons() & Qt::LeftButton
- && QPointF(scenePos - m_dragBeginPos).manhattanLength() > Constants::DragStartDistance / 3
- && !m_dragStarted)
+ && (QPointF(scenePos - m_dragBeginPos).manhattanLength()
+ > Constants::DragStartDistance / 3)
+ && !m_dragStarted)
{
m_dragStarted = true;
- m_rubberbandManipulator.begin(m_dragBeginPos);
+ m_rubberbandManipulator->begin(m_dragBeginPos);
return;
}
if (m_dragStarted)
- m_rubberbandManipulator.update(scenePos);
+ m_rubberbandManipulator->update(scenePos);
}
@@ -112,12 +119,12 @@ void ZoomTool::mouseReleaseEvent(QMouseEvent *event)
QPointF scenePos = view()->mapToScene(event->pos());
if (m_dragStarted) {
- m_rubberbandManipulator.end();
+ m_rubberbandManipulator->end();
- int x1 = qMin(scenePos.x(), m_rubberbandManipulator.beginPoint().x());
- int x2 = qMax(scenePos.x(), m_rubberbandManipulator.beginPoint().x());
- int y1 = qMin(scenePos.y(), m_rubberbandManipulator.beginPoint().y());
- int y2 = qMax(scenePos.y(), m_rubberbandManipulator.beginPoint().y());
+ int x1 = qMin(scenePos.x(), m_rubberbandManipulator->beginPoint().x());
+ int x2 = qMax(scenePos.x(), m_rubberbandManipulator->beginPoint().x());
+ int y1 = qMin(scenePos.y(), m_rubberbandManipulator->beginPoint().y());
+ int y2 = qMax(scenePos.y(), m_rubberbandManipulator->beginPoint().y());
QPointF scenePosTopLeft = QPoint(x1, y1);
QPointF scenePosBottomRight = QPoint(x2, y2);
diff --git a/share/qtcreator/qml/qmljsdebugger/editor/zoomtool.h b/share/qtcreator/qml/qmljsdebugger/editor/zoomtool.h
index 954fd50cb8..4cb19533c9 100644
--- a/share/qtcreator/qml/qmljsdebugger/editor/zoomtool.h
+++ b/share/qtcreator/qml/qmljsdebugger/editor/zoomtool.h
@@ -86,7 +86,7 @@ private:
QAction *m_zoomTo100Action;
QAction *m_zoomInAction;
QAction *m_zoomOutAction;
- RubberBandSelectionManipulator m_rubberbandManipulator;
+ RubberBandSelectionManipulator *m_rubberbandManipulator;
qreal m_smoothZoomMultiplier;
qreal m_currentScale;
diff --git a/share/qtcreator/qml/qmljsdebugger/include/jsdebuggeragent.h b/share/qtcreator/qml/qmljsdebugger/include/jsdebuggeragent.h
index 5c0fb01723..774102f0fe 100644
--- a/share/qtcreator/qml/qmljsdebugger/include/jsdebuggeragent.h
+++ b/share/qtcreator/qml/qmljsdebugger/include/jsdebuggeragent.h
@@ -54,25 +54,26 @@
//
#include <QtScript/qscriptengineagent.h>
-#include <QtScript/QScriptValue>
-#include <QtCore/QEventLoop>
-#include <QtCore/QSet>
-#include <QtCore/QStringList>
#include "qt_private/qdeclarativedebugservice_p.h"
#include "qmljsdebugger_global.h"
-QT_FORWARD_DECLARE_CLASS(QScriptContext);
-QT_FORWARD_DECLARE_CLASS(QDeclarativeEngine);
+QT_BEGIN_NAMESPACE
+class QScriptValue;
+class QDeclarativeEngine;
+QT_END_NAMESPACE
namespace QmlJSDebugger {
-class JSAgentWatchData;
+class JSDebuggerAgentPrivate;
-class QMLJSDEBUGGER_EXPORT JSDebuggerAgent : public QDeclarativeDebugService , public QScriptEngineAgent
+class QMLJSDEBUGGER_EXPORT JSDebuggerAgent
+ : public QDeclarativeDebugService
+ , public QScriptEngineAgent
{
Q_OBJECT
+
public:
JSDebuggerAgent(QScriptEngine *engine);
JSDebuggerAgent(QDeclarativeEngine *engine);
@@ -105,39 +106,12 @@ public:
void messageReceived(const QByteArray &);
void statusChanged(Status status);
+ void baseMessageReceived(const QByteArray &message);
public slots:
-// void pauses();
private:
- class SetupExecEnv;
- friend class SetupExecEnv;
-
- enum State {
- NoState,
- SteppingIntoState,
- SteppingOverState,
- SteppingOutState,
- Stopped
- };
- State state;
- int stepDepth;
- int stepCount;
-
- void continueExec();
- void stopped(bool becauseOfException = false, const QScriptValue &exception = QScriptValue());
-
-
- void recordKnownObjects(const QList<JSAgentWatchData> &);
- QList<JSAgentWatchData> getLocals(QScriptContext *);
-
- QEventLoop loop;
- QHash <qint64, QString> filenames;
- QSet< QPair<QString, qint32> > breakpointList;
- QStringList watchExpressions;
- QSet<qint64> knownObjectIds;
-
- Q_DISABLE_COPY(JSDebuggerAgent)
+ JSDebuggerAgentPrivate *d;
};
} // namespace QmlJSDebugger
diff --git a/share/qtcreator/qml/qmljsdebugger/include/qdeclarativeobserverservice.h b/share/qtcreator/qml/qmljsdebugger/include/qdeclarativeobserverservice.h
index 66084cd92c..df4704fa83 100644
--- a/share/qtcreator/qml/qmljsdebugger/include/qdeclarativeobserverservice.h
+++ b/share/qtcreator/qml/qmljsdebugger/include/qdeclarativeobserverservice.h
@@ -68,6 +68,8 @@ public:
void setAnimationSpeed(qreal slowdownFactor);
void setCurrentTool(QmlJSDebugger::Constants::DesignTool toolId);
void reloaded();
+ void setShowAppOnTop(bool showAppOnTop);
+
QString idStringForObject(QObject *obj) const;
void sendMessage(const QByteArray &message);
@@ -81,6 +83,7 @@ Q_SIGNALS:
void currentObjectsChanged(const QList<QObject*> &objects);
void designModeBehaviorChanged(bool inDesignMode);
+ void showAppOnTopChanged(bool showAppOnTop);
void reloadRequested();
void selectToolRequested();
void selectMarqueeToolRequested();
diff --git a/share/qtcreator/qml/qmljsdebugger/include/qdeclarativeviewobserver.h b/share/qtcreator/qml/qmljsdebugger/include/qdeclarativeviewobserver.h
index e58f0a87b0..9347a7158b 100644
--- a/share/qtcreator/qml/qmljsdebugger/include/qdeclarativeviewobserver.h
+++ b/share/qtcreator/qml/qmljsdebugger/include/qdeclarativeviewobserver.h
@@ -65,10 +65,14 @@ public:
static QString idStringForObject(QObject *obj);
QRectF adjustToScreenBoundaries(const QRectF &boundingRectInSceneSpace);
+ bool showAppOnTop() const;
+
public Q_SLOTS:
void setDesignModeBehavior(bool value);
bool designModeBehavior();
+ void setShowAppOnTop(bool appOnTop);
+
void changeAnimationSpeed(qreal slowdownFactor);
void continueExecution(qreal slowdownFactor = 1.0f);
void pauseExecution();
@@ -77,6 +81,7 @@ public Q_SLOTS:
Q_SIGNALS:
void designModeBehaviorChanged(bool inDesignMode);
+ void showAppOnTopChanged(bool showAppOnTop);
void reloadRequested();
void marqueeSelectToolActivated();
void selectToolActivated();
@@ -119,6 +124,7 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_changeToColorPickerTool())
Q_PRIVATE_SLOT(d_func(), void _q_changeContextPathIndex(int index))
Q_PRIVATE_SLOT(d_func(), void _q_clearComponentCache());
+ Q_PRIVATE_SLOT(d_func(), void _q_removeFromSelection(QObject *));
inline QDeclarativeViewObserverPrivate *d_func() { return data.data(); }
QScopedPointer<QDeclarativeViewObserverPrivate> data;
diff --git a/share/qtcreator/qml/qmljsdebugger/jsdebuggeragent.cpp b/share/qtcreator/qml/qmljsdebugger/jsdebuggeragent.cpp
index 00b6ea2748..2af9df33f1 100644
--- a/share/qtcreator/qml/qmljsdebugger/jsdebuggeragent.cpp
+++ b/share/qtcreator/qml/qmljsdebugger/jsdebuggeragent.cpp
@@ -42,101 +42,191 @@
#include "jsdebuggeragent.h"
#include "qt_private/qdeclarativedebughelper_p.h"
+#include <QtCore/qdatetime.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qurl.h>
#include <QtCore/qcoreapplication.h>
#include <QtCore/qset.h>
+#include <QtScript/qscriptcontextinfo.h>
#include <QtScript/qscriptengine.h>
-#include <QtScript/QScriptContextInfo>
-#include <QtCore/QDebug>
-#include <QtCore/QUrl>
-#include <QtCore/QDateTime>
#include <QtScript/qscriptvalueiterator.h>
namespace QmlJSDebugger {
-class JSDebuggerAgent::SetupExecEnv {
- JSDebuggerAgent* agent;
- JSDebuggerAgent::State previousState;
- bool hadException;
+enum JSDebuggerState
+{
+ NoState,
+ SteppingIntoState,
+ SteppingOverState,
+ SteppingOutState,
+ StoppedState
+};
+
+struct JSAgentWatchData
+{
+ QByteArray exp;
+ QByteArray name;
+ QByteArray value;
+ QByteArray type;
+ bool hasChildren;
+ quint64 objectId;
+};
+
+QDataStream &operator<<(QDataStream &s, const JSAgentWatchData &data)
+{
+ return s << data.exp << data.name << data.value
+ << data.type << data.hasChildren << data.objectId;
+}
+
+struct JSAgentStackData
+{
+ QByteArray functionName;
+ QByteArray fileName;
+ qint32 lineNumber;
+};
+
+QDataStream &operator<<(QDataStream &s, const JSAgentStackData &data)
+{
+ return s << data.functionName << data.fileName << data.lineNumber;
+}
+
+struct JSAgentBreakpointData
+{
+ QByteArray functionName;
+ QByteArray fileName;
+ qint32 lineNumber;
+};
+
+typedef QSet<JSAgentBreakpointData> JSAgentBreakpoints;
+
+QDataStream &operator<<(QDataStream &s, const JSAgentBreakpointData &data)
+{
+ return s << data.functionName << data.fileName << data.lineNumber;
+}
+
+QDataStream &operator>>(QDataStream &s, JSAgentBreakpointData &data)
+{
+ return s >> data.functionName >> data.fileName >> data.lineNumber;
+}
+
+bool operator==(const JSAgentBreakpointData &b1, const JSAgentBreakpointData &b2)
+{
+ return b1.lineNumber == b2.lineNumber && b1.fileName == b2.fileName;
+}
+
+uint qHash(const JSAgentBreakpointData &b)
+{
+ return b.lineNumber ^ qHash(b.fileName);
+}
+
+class JSDebuggerAgentPrivate
+{
+public:
+ JSDebuggerAgentPrivate(JSDebuggerAgent *q)
+ : q(q), state(NoState)
+ {}
+
+ void continueExec();
+ void recordKnownObjects(const QList<JSAgentWatchData> &);
+ QList<JSAgentWatchData> getLocals(QScriptContext *);
+ void positionChange(qint64 scriptId, int lineNumber, int columnNumber);
+ QScriptEngine *engine() { return q->engine(); }
+ void stopped();
+ void messageReceived(const QByteArray &message);
+ void sendMessage(const QByteArray &message) { q->sendMessage(message); }
+
public:
- SetupExecEnv(JSDebuggerAgent *a)
+ JSDebuggerAgent *q;
+ JSDebuggerState state;
+ int stepDepth;
+ int stepCount;
+
+ QEventLoop loop;
+ QHash<qint64, QString> filenames;
+ JSAgentBreakpoints breakpoints;
+ QStringList watchExpressions;
+ QSet<qint64> knownObjectIds;
+};
+
+class SetupExecEnv
+{
+public:
+ SetupExecEnv(JSDebuggerAgentPrivate *a)
: agent(a),
previousState(a->state),
hadException(a->engine()->hasUncaughtException())
- {
- agent->state = JSDebuggerAgent::Stopped;
- }
+ {
+ agent->state = StoppedState;
+ }
- ~SetupExecEnv() {
+ ~SetupExecEnv()
+ {
if (!hadException && agent->engine()->hasUncaughtException())
agent->engine()->clearExceptions();
agent->state = previousState;
}
-};
-class JSAgentWatchData {
-public:
- QByteArray exp;
- QString name;
- QString value;
- QString type;
- bool hasChildren;
- quint64 objectId;
-
- static JSAgentWatchData fromScriptValue(const QString &expression, const QScriptValue &value)
- {
- JSAgentWatchData data;
- data.exp = expression.toUtf8();
- data.name = expression;
- data.hasChildren = false;
- data.value = value.toString();
- data.objectId = value.objectId();
- if (value.isArray()) {
- data.type = QLatin1String("Array");
- data.value = QString::fromLatin1("[Array of length %1]").arg(value.property("length").toString());
- data.hasChildren = true;
- } else if (value.isBool()) {
- data.type = QLatin1String("Bool");
-// data.value = value.toBool() ? QLatin1String("true") : QLatin1String("false");
- } else if (value.isDate()) {
- data.type = QLatin1String("Date");
- data.value = value.toDateTime().toString();
- } else if (value.isError()) {
- data.type = QLatin1String("Error");
- } else if (value.isFunction()) {
- data.type = QLatin1String("Function");
- } else if (value.isUndefined()) {
- data.type = QLatin1String("<undefined>");
- } else if (value.isNumber()) {
- data.type = QLatin1String("Number");
- } else if (value.isRegExp()) {
- data.type = QLatin1String("RegExp");
- } else if (value.isString()) {
- data.type = QLatin1String("String");
- } else if (value.isVariant()) {
- data.type = QLatin1String("Variant");
- } else if (value.isQObject()) {
- const QObject *obj = value.toQObject();
- data.value = QString::fromLatin1("[%1]").arg(obj->metaObject()->className());
- data.type = QLatin1String("Object");
- data.hasChildren = true;
- } else if (value.isObject()) {
- data.type = QLatin1String("Object");
- data.hasChildren = true;
- data.type = QLatin1String("Object");
- data.value = QLatin1String("[Object]");
- } else if (value.isNull()) {
- data.type = QLatin1String("<null>");
- } else {
- data.type = QLatin1String("<unknown>");
- }
- return data;
- }
+private:
+ JSDebuggerAgentPrivate *agent;
+ JSDebuggerState previousState;
+ bool hadException;
};
-
-QDataStream& operator<<(QDataStream& s, const JSAgentWatchData& data)
+static JSAgentWatchData fromScriptValue(const QString &expression,
+ const QScriptValue &value)
{
- return s << data.exp << data.name << data.value << data.type << data.hasChildren << data.objectId;
+ static const QString arrayStr = QCoreApplication::translate
+ ("Debugger::JSAgentWatchData", "[Array of length %1]");
+ static const QString undefinedStr = QCoreApplication::translate
+ ("Debugger::JSAgentWatchData", "<undefined>");
+
+ JSAgentWatchData data;
+ data.exp = expression.toUtf8();
+ data.name = data.exp;
+ data.hasChildren = false;
+ data.value = value.toString().toUtf8();
+ data.objectId = value.objectId();
+ if (value.isArray()) {
+ data.type = "Array";
+ data.value = arrayStr.arg(value.property("length").toString()).toUtf8();
+ data.hasChildren = true;
+ } else if (value.isBool()) {
+ data.type = "Bool";
+ // data.value = value.toBool() ? "true" : "false";
+ } else if (value.isDate()) {
+ data.type = "Date";
+ data.value = value.toDateTime().toString().toUtf8();
+ } else if (value.isError()) {
+ data.type = "Error";
+ } else if (value.isFunction()) {
+ data.type = "Function";
+ } else if (value.isUndefined()) {
+ data.type = undefinedStr.toUtf8();
+ } else if (value.isNumber()) {
+ data.type = "Number";
+ } else if (value.isRegExp()) {
+ data.type = "RegExp";
+ } else if (value.isString()) {
+ data.type = "String";
+ } else if (value.isVariant()) {
+ data.type = "Variant";
+ } else if (value.isQObject()) {
+ const QObject *obj = value.toQObject();
+ data.type = "Object";
+ data.value += '[';
+ data.value += obj->metaObject()->className();
+ data.value += ']';
+ data.hasChildren = true;
+ } else if (value.isObject()) {
+ data.type = "Object";
+ data.hasChildren = true;
+ data.value = "[Object]";
+ } else if (value.isNull()) {
+ data.type = "<null>";
+ } else {
+ data.type = "<unknown>";
+ }
+ return data;
}
static QList<JSAgentWatchData> expandObject(const QScriptValue &object)
@@ -148,33 +238,43 @@ static QList<JSAgentWatchData> expandObject(const QScriptValue &object)
it.next();
if (it.flags() & QScriptValue::SkipInEnumeration)
continue;
- if (object.isQObject() && it.value().isFunction()) {
- // cosmetics: skip all signals and slot, there is too many of them,
- // and it is not usefull in the debugger.
+ if (/*object.isQObject() &&*/ it.value().isFunction()) {
+ // Cosmetics: skip all functions and slot, there are too many of them,
+ // and it is not useful information in the debugger.
continue;
}
- JSAgentWatchData data = JSAgentWatchData::fromScriptValue(it.name(), it.value());
+ JSAgentWatchData data = fromScriptValue(it.name(), it.value());
+ data.exp.prepend(expPrefix);
+ result.append(data);
+ }
+ if (result.isEmpty()) {
+ JSAgentWatchData data;
+ data.name = "<no initialized data>";
+ data.hasChildren = false;
+ data.value = " ";
data.exp.prepend(expPrefix);
- result << data;
+ data.objectId = 0;
+ result.append(data);
}
return result;
}
-void JSDebuggerAgent::recordKnownObjects(const QList<JSAgentWatchData>& list)
+void JSDebuggerAgentPrivate::recordKnownObjects(const QList<JSAgentWatchData>& list)
{
foreach (const JSAgentWatchData &data, list)
knownObjectIds << data.objectId;
}
-QList<JSAgentWatchData> JSDebuggerAgent::getLocals(QScriptContext *ctx)
+QList<JSAgentWatchData> JSDebuggerAgentPrivate::getLocals(QScriptContext *ctx)
{
QList<JSAgentWatchData> locals;
if (ctx) {
QScriptValue activationObject = ctx->activationObject();
QScriptValue thisObject = ctx->thisObject();
locals = expandObject(activationObject);
- if (thisObject.isObject() && thisObject.objectId() != engine()->globalObject().objectId())
- locals.prepend(JSAgentWatchData::fromScriptValue("this", thisObject));
+ if (thisObject.isObject()
+ && thisObject.objectId() != engine()->globalObject().objectId())
+ locals.prepend(fromScriptValue("this", thisObject));
recordKnownObjects(locals);
knownObjectIds << activationObject.objectId();
}
@@ -187,30 +287,33 @@ QList<JSAgentWatchData> JSDebuggerAgent::getLocals(QScriptContext *ctx)
\a backend.
*/
JSDebuggerAgent::JSDebuggerAgent(QScriptEngine *engine)
- : QDeclarativeDebugService("JSDebugger"), QScriptEngineAgent(engine)
- , state(NoState)
+ : QDeclarativeDebugService("JSDebugger")
+ , QScriptEngineAgent(engine)
+ , d(new JSDebuggerAgentPrivate(this))
{}
JSDebuggerAgent::JSDebuggerAgent(QDeclarativeEngine *engine)
: QDeclarativeDebugService("JSDebugger")
, QScriptEngineAgent(QDeclarativeDebugHelper::getScriptEngine(engine))
- , state(NoState)
+ , d(new JSDebuggerAgentPrivate(this))
{}
/*!
Destroys this QScriptDebuggerAgent.
*/
JSDebuggerAgent::~JSDebuggerAgent()
-{}
+{
+ delete d;
+}
/*!
\reimp
*/
-void JSDebuggerAgent::scriptLoad(qint64 id, const QString & program,
- const QString &fileName, int )
+void JSDebuggerAgent::scriptLoad(qint64 id, const QString &program,
+ const QString &fileName, int)
{
Q_UNUSED(program);
- filenames.insert(id, QUrl(fileName).toLocalFile());
+ d->filenames.insert(id, QUrl(fileName).toLocalFile());
}
/*!
@@ -218,7 +321,7 @@ void JSDebuggerAgent::scriptLoad(qint64 id, const QString & program,
*/
void JSDebuggerAgent::scriptUnload(qint64 id)
{
- filenames.remove(id);
+ d->filenames.remove(id);
}
/*!
@@ -241,7 +344,7 @@ void JSDebuggerAgent::contextPop()
void JSDebuggerAgent::functionEntry(qint64 scriptId)
{
Q_UNUSED(scriptId);
- stepDepth++;
+ d->stepDepth++;
}
/*!
@@ -251,31 +354,43 @@ void JSDebuggerAgent::functionExit(qint64 scriptId, const QScriptValue &returnVa
{
Q_UNUSED(scriptId);
Q_UNUSED(returnValue);
- stepDepth--;
+ d->stepDepth--;
}
/*!
\reimp
*/
-void JSDebuggerAgent::positionChange(qint64 scriptId,
- int lineNumber, int columnNumber)
+void JSDebuggerAgent::positionChange(qint64 scriptId, int lineNumber, int columnNumber)
+{
+ d->positionChange(scriptId, lineNumber, columnNumber);
+}
+
+void JSDebuggerAgentPrivate::positionChange(qint64 scriptId, int lineNumber, int columnNumber)
{
Q_UNUSED(columnNumber);
- if(state == Stopped)
+ if (state == StoppedState)
return; //no re-entrency
// check breakpoints
- if (!breakpointList.isEmpty()) {
+ if (!breakpoints.isEmpty()) {
QHash<qint64, QString>::const_iterator it = filenames.constFind(scriptId);
+ QScriptContext *ctx = engine()->currentContext();
+ QScriptContextInfo info(ctx);
if (it == filenames.constEnd()) {
// It is possible that the scripts are loaded before the agent is attached
- QString filename = QUrl(QScriptContextInfo(engine()->currentContext()).fileName()).toLocalFile();
+ QString filename = QUrl(info.fileName()).toLocalFile();
+
+ JSAgentStackData frame;
+ frame.functionName = info.functionName().toUtf8();
+
QPair<QString, qint32> key = qMakePair(filename, lineNumber);
it = filenames.insert(scriptId, filename);
}
- QPair<QString, qint32> key = qMakePair(*it, lineNumber);
- if (breakpointList.contains(key)) {
+ JSAgentBreakpointData bp;
+ bp.fileName = it->toUtf8();
+ bp.lineNumber = lineNumber;
+ if (breakpoints.contains(bp)) {
stopped();
return;
}
@@ -283,7 +398,7 @@ void JSDebuggerAgent::positionChange(qint64 scriptId,
switch (state) {
case NoState:
- case Stopped:
+ case StoppedState:
// Do nothing
break;
case SteppingOutState:
@@ -305,15 +420,15 @@ void JSDebuggerAgent::positionChange(qint64 scriptId,
\reimp
*/
void JSDebuggerAgent::exceptionThrow(qint64 scriptId,
- const QScriptValue &exception,
- bool hasHandler)
+ const QScriptValue &exception,
+ bool hasHandler)
{
Q_UNUSED(scriptId);
Q_UNUSED(exception);
Q_UNUSED(hasHandler);
// qDebug() << Q_FUNC_INFO << exception.toString() << hasHandler;
#if 0 //sometimes, we get exceptions that we should just ignore.
- if (!hasHandler && state != Stopped)
+ if (!hasHandler && state != StoppedState)
stopped(true, exception);
#endif
}
@@ -321,36 +436,41 @@ void JSDebuggerAgent::exceptionThrow(qint64 scriptId,
/*!
\reimp
*/
-void JSDebuggerAgent::exceptionCatch(qint64 scriptId,
- const QScriptValue &exception)
+void JSDebuggerAgent::exceptionCatch(qint64 scriptId, const QScriptValue &exception)
{
Q_UNUSED(scriptId);
Q_UNUSED(exception);
}
-bool JSDebuggerAgent::supportsExtension(QScriptEngineAgent::Extension extension) const
+bool JSDebuggerAgent::supportsExtension(Extension extension) const
{
return extension == QScriptEngineAgent::DebuggerInvocationRequest;
}
-QVariant JSDebuggerAgent::extension(QScriptEngineAgent::Extension extension, const QVariant& argument)
+QVariant JSDebuggerAgent::extension(Extension extension, const QVariant &argument)
{
if (extension == QScriptEngineAgent::DebuggerInvocationRequest) {
- stopped();
+ d->stopped();
return QVariant();
}
return QScriptEngineAgent::extension(extension, argument);
}
+void JSDebuggerAgent::messageReceived(const QByteArray &message)
+{
+ d->messageReceived(message);
+}
-
-void JSDebuggerAgent::messageReceived(const QByteArray& message)
+void JSDebuggerAgentPrivate::messageReceived(const QByteArray &message)
{
QDataStream ds(message);
QByteArray command;
ds >> command;
if (command == "BREAKPOINTS") {
- ds >> breakpointList;
+ ds >> breakpoints;
+ //qDebug() << "BREAKPOINTS";
+ //foreach (const JSAgentBreakpointData &bp, breakpoints)
+ // qDebug() << "BREAKPOINT: " << bp.fileName << bp.lineNumber;
} else if (command == "WATCH_EXPRESSIONS") {
ds >> watchExpressions;
} else if (command == "STEPOVER") {
@@ -375,7 +495,7 @@ void JSDebuggerAgent::messageReceived(const QByteArray& message)
QString expr;
ds >> id >> expr;
- JSAgentWatchData data = JSAgentWatchData::fromScriptValue(expr, engine()->evaluate(expr));
+ JSAgentWatchData data = fromScriptValue(expr, engine()->evaluate(expr));
knownObjectIds << data.objectId;
QByteArray reply;
@@ -432,7 +552,7 @@ void JSDebuggerAgent::messageReceived(const QByteArray& message)
QScriptValue object;
object = engine()->objectById(objectId);
- if(object.isObject()) {
+ if (object.isObject()) {
QScriptValue result = engine()->evaluate(value);
object.setProperty(property, result);
}
@@ -450,45 +570,51 @@ void JSDebuggerAgent::messageReceived(const QByteArray& message)
qDebug() << Q_FUNC_INFO << "Unknown command" << command;
}
- QDeclarativeDebugService::messageReceived(message);
+ q->baseMessageReceived(message);
}
-void JSDebuggerAgent::stopped(bool becauseOfException, const QScriptValue& exception)
+void JSDebuggerAgentPrivate::stopped()
{
+ bool becauseOfException = false;
+ const QScriptValue &exception = QScriptValue();
+
knownObjectIds.clear();
- state = Stopped;
- QList<QPair<QString, QPair<QString, qint32> > > backtrace;
+ state = StoppedState;
+ QList<JSAgentStackData> backtrace;
for (QScriptContext* ctx = engine()->currentContext(); ctx; ctx = ctx->parentContext()) {
QScriptContextInfo info(ctx);
- QString functionName = info.functionName();
- if (functionName.isEmpty()) {
+ JSAgentStackData frame;
+ frame.functionName = info.functionName().toUtf8();
+ if (frame.functionName.isEmpty()) {
if (ctx->parentContext()) {
switch (info.functionType()) {
case QScriptContextInfo::ScriptFunction:
- functionName = QLatin1String("<anonymous>");
+ frame.functionName = "<anonymous>";
break;
case QScriptContextInfo::NativeFunction:
- functionName = QLatin1String("<native>");
+ frame.functionName = "<native>";
break;
case QScriptContextInfo::QtFunction:
case QScriptContextInfo::QtPropertyFunction:
- functionName = QLatin1String("<native slot>");
+ frame.functionName = "<native slot>";
break;
}
} else {
- functionName = QLatin1String("<global>");
+ frame.functionName = "<global>";
}
}
- int lineNumber = info.lineNumber();
- if (lineNumber == -1) // if the line number is unknown, fallback to the function line number
- lineNumber = info.functionStartLineNumber();
- backtrace.append(qMakePair(functionName, qMakePair( QUrl(info.fileName()).toLocalFile(), lineNumber ) ) );
+ frame.lineNumber = info.lineNumber();
+ // if the line number is unknown, fallback to the function line number
+ if (frame.lineNumber == -1)
+ frame.lineNumber = info.functionStartLineNumber();
+ frame.fileName = QUrl(info.fileName()).toLocalFile().toUtf8();
+ backtrace.append(frame);
}
QList<JSAgentWatchData> watches;
foreach (const QString &expr, watchExpressions)
- watches << JSAgentWatchData::fromScriptValue(expr, engine()->evaluate(expr));
+ watches << fromScriptValue(expr, engine()->evaluate(expr));
recordKnownObjects(watches);
QList<JSAgentWatchData> locals = getLocals(engine()->currentContext());
@@ -500,13 +626,14 @@ void JSDebuggerAgent::stopped(bool becauseOfException, const QScriptValue& excep
QByteArray reply;
QDataStream rs(&reply, QIODevice::WriteOnly);
- rs << QByteArray("STOPPED") << backtrace << watches << locals << becauseOfException << exception.toString();
+ rs << QByteArray("STOPPED") << backtrace << watches << locals
+ << becauseOfException << exception.toString();
sendMessage(reply);
loop.exec(QEventLoop::ExcludeUserInputEvents);
}
-void JSDebuggerAgent::continueExec()
+void JSDebuggerAgentPrivate::continueExec()
{
loop.quit();
}
@@ -516,4 +643,9 @@ void JSDebuggerAgent::statusChanged(Status status)
engine()->setAgent((status == QDeclarativeDebugService::Enabled) ? this : 0);
}
+void JSDebuggerAgent::baseMessageReceived(const QByteArray &message)
+{
+ QDeclarativeDebugService::messageReceived(message);
+}
+
} // namespace QmlJSDebugger
diff --git a/share/qtcreator/qml/qmljsdebugger/qdeclarativeobserverservice.cpp b/share/qtcreator/qml/qmljsdebugger/qdeclarativeobserverservice.cpp
index 114cd15cf6..38feafd29e 100644
--- a/share/qtcreator/qml/qmljsdebugger/qdeclarativeobserverservice.cpp
+++ b/share/qtcreator/qml/qmljsdebugger/qdeclarativeobserverservice.cpp
@@ -110,6 +110,10 @@ void QDeclarativeObserverService::messageReceived(const QByteArray &message)
bool inDesignMode;
ds >> inDesignMode;
emit designModeBehaviorChanged(inDesignMode);
+ } else if (type == "SHOW_APP_ON_TOP") {
+ bool showOnTop;
+ ds >> showOnTop;
+ emit showAppOnTopChanged(showOnTop);
} else if (type == "CREATE_OBJECT") {
QString qml;
int parentId;
@@ -123,9 +127,9 @@ void QDeclarativeObserverService::messageReceived(const QByteArray &message)
if (QObject* obj = objectForId(debugId))
obj->deleteLater();
} else if (type == "MOVE_OBJECT") {
- int debugId, newParent;
- ds >> debugId >> newParent;
- emit objectReparentRequested(objectForId(debugId), objectForId(newParent));
+ int debugId, newParent;
+ ds >> debugId >> newParent;
+ emit objectReparentRequested(objectForId(debugId), objectForId(newParent));
} else if (type == "OBJECT_ID_LIST") {
int itemCount;
ds >> itemCount;
@@ -207,6 +211,16 @@ void QDeclarativeObserverService::reloaded()
sendMessage(message);
}
+void QDeclarativeObserverService::setShowAppOnTop(bool showAppOnTop)
+{
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+
+ ds << QByteArray("SHOW_APP_ON_TOP") << showAppOnTop;
+
+ sendMessage(message);
+}
+
void QDeclarativeObserverService::selectedColorChanged(const QColor &color)
{
QByteArray message;
diff --git a/share/qtcreator/qml/qmljsdebugger/qdeclarativeviewobserver.cpp b/share/qtcreator/qml/qmljsdebugger/qdeclarativeviewobserver.cpp
index 98f0d21f7c..54b6f47df6 100644
--- a/share/qtcreator/qml/qmljsdebugger/qdeclarativeviewobserver.cpp
+++ b/share/qtcreator/qml/qmljsdebugger/qdeclarativeviewobserver.cpp
@@ -34,13 +34,13 @@
#include "qdeclarativeviewobserver.h"
#include "qdeclarativeviewobserver_p.h"
#include "qdeclarativeobserverservice.h"
-#include "selectiontool.h"
-#include "zoomtool.h"
-#include "colorpickertool.h"
-#include "layeritem.h"
-#include "boundingrecthighlighter.h"
-#include "subcomponenteditortool.h"
-#include "qmltoolbar.h"
+#include "editor/selectiontool.h"
+#include "editor/zoomtool.h"
+#include "editor/colorpickertool.h"
+#include "editor/layeritem.h"
+#include "editor/boundingrecthighlighter.h"
+#include "editor/subcomponenteditortool.h"
+#include "editor/qmltoolbar.h"
#include "qt_private/qdeclarativedebughelper_p.h"
@@ -61,6 +61,7 @@ const int SceneChangeUpdateInterval = 5000;
QDeclarativeViewObserverPrivate::QDeclarativeViewObserverPrivate(QDeclarativeViewObserver *q) :
q(q),
designModeBehavior(false),
+ showAppOnTop(false),
executionPaused(false),
slowdownFactor(1.0f),
toolbar(0)
@@ -89,14 +90,19 @@ QDeclarativeViewObserver::QDeclarativeViewObserver(QDeclarativeView *view, QObje
data->setViewport(data->view->viewport());
data->debugService = QDeclarativeObserverService::instance();
- connect(data->debugService, SIGNAL(designModeBehaviorChanged(bool)), SLOT(setDesignModeBehavior(bool)));
+ connect(data->debugService, SIGNAL(designModeBehaviorChanged(bool)),
+ SLOT(setDesignModeBehavior(bool)));
+ connect(data->debugService, SIGNAL(showAppOnTopChanged(bool)),
+ SLOT(setShowAppOnTop(bool)));
connect(data->debugService, SIGNAL(reloadRequested()), SLOT(_q_reloadView()));
- connect(data->debugService,
- SIGNAL(currentObjectsChanged(QList<QObject*>)),
+ connect(data->debugService, SIGNAL(currentObjectsChanged(QList<QObject*>)),
SLOT(_q_onCurrentObjectsChanged(QList<QObject*>)));
- connect(data->debugService, SIGNAL(animationSpeedChangeRequested(qreal)), SLOT(changeAnimationSpeed(qreal)));
- connect(data->debugService, SIGNAL(colorPickerToolRequested()), SLOT(_q_changeToColorPickerTool()));
- connect(data->debugService, SIGNAL(selectMarqueeToolRequested()), SLOT(_q_changeToMarqueeSelectTool()));
+ connect(data->debugService, SIGNAL(animationSpeedChangeRequested(qreal)),
+ SLOT(changeAnimationSpeed(qreal)));
+ connect(data->debugService, SIGNAL(colorPickerToolRequested()),
+ SLOT(_q_changeToColorPickerTool()));
+ connect(data->debugService, SIGNAL(selectMarqueeToolRequested()),
+ SLOT(_q_changeToMarqueeSelectTool()));
connect(data->debugService, SIGNAL(selectToolRequested()), SLOT(_q_changeToSingleSelectTool()));
connect(data->debugService, SIGNAL(zoomToolRequested()), SLOT(_q_changeToZoomTool()));
connect(data->debugService,
@@ -105,18 +111,25 @@ QDeclarativeViewObserver::QDeclarativeViewObserver(QDeclarativeView *view, QObje
connect(data->debugService,
SIGNAL(objectReparentRequested(QObject *, QObject *)),
SLOT(_q_reparentQmlObject(QObject *, QObject *)));
- connect(data->debugService, SIGNAL(contextPathIndexChanged(int)), SLOT(_q_changeContextPathIndex(int)));
- connect(data->debugService, SIGNAL(clearComponentCacheRequested()), SLOT(_q_clearComponentCache()));
- connect(data->view, SIGNAL(statusChanged(QDeclarativeView::Status)), SLOT(_q_onStatusChanged(QDeclarativeView::Status)));
+ connect(data->debugService, SIGNAL(contextPathIndexChanged(int)),
+ SLOT(_q_changeContextPathIndex(int)));
+ connect(data->debugService, SIGNAL(clearComponentCacheRequested()),
+ SLOT(_q_clearComponentCache()));
+ connect(data->view, SIGNAL(statusChanged(QDeclarativeView::Status)),
+ SLOT(_q_onStatusChanged(QDeclarativeView::Status)));
- connect(data->colorPickerTool, SIGNAL(selectedColorChanged(QColor)), SIGNAL(selectedColorChanged(QColor)));
+ connect(data->colorPickerTool, SIGNAL(selectedColorChanged(QColor)),
+ SIGNAL(selectedColorChanged(QColor)));
connect(data->colorPickerTool, SIGNAL(selectedColorChanged(QColor)),
data->debugService, SLOT(selectedColorChanged(QColor)));
connect(data->subcomponentEditorTool, SIGNAL(cleared()), SIGNAL(inspectorContextCleared()));
- connect(data->subcomponentEditorTool, SIGNAL(contextPushed(QString)), SIGNAL(inspectorContextPushed(QString)));
- connect(data->subcomponentEditorTool, SIGNAL(contextPopped()), SIGNAL(inspectorContextPopped()));
- connect(data->subcomponentEditorTool, SIGNAL(contextPathChanged(QStringList)), data->debugService, SLOT(contextPathUpdated(QStringList)));
+ connect(data->subcomponentEditorTool, SIGNAL(contextPushed(QString)),
+ SIGNAL(inspectorContextPushed(QString)));
+ connect(data->subcomponentEditorTool, SIGNAL(contextPopped()),
+ SIGNAL(inspectorContextPopped()));
+ connect(data->subcomponentEditorTool, SIGNAL(contextPathChanged(QStringList)),
+ data->debugService, SLOT(contextPathUpdated(QStringList)));
data->createToolbar();
@@ -131,8 +144,9 @@ void QDeclarativeViewObserver::setObserverContext(int contextIndex)
{
if (data->subcomponentEditorTool->contextIndex() != contextIndex) {
QGraphicsObject *object = data->subcomponentEditorTool->setContext(contextIndex);
- if (object)
- data->debugService->setCurrentObjects(QList<QObject*>() << object);
+ if (object) {
+ setSelectedItems(QList<QGraphicsItem*>() << object);
+ }
}
}
@@ -149,13 +163,13 @@ void QDeclarativeViewObserverPrivate::setViewport(QWidget *widget)
return;
if (viewport) {
- viewport->removeEventFilter(q);
+ viewport.data()->removeEventFilter(q);
}
viewport = widget;
if (viewport) {
// make sure we get mouse move events
- viewport->setMouseTracking(true);
- viewport->installEventFilter(q);
+ viewport.data()->setMouseTracking(true);
+ viewport.data()->installEventFilter(q);
}
}
@@ -166,66 +180,66 @@ void QDeclarativeViewObserverPrivate::clearEditorItems()
}
bool QDeclarativeViewObserver::eventFilter(QObject *obj, QEvent *event)
- {
- if (obj == data->view) {
- // Event from view
- if (event->type() == QEvent::ChildRemoved) {
- // Might mean that viewport has changed
- if (data->view->viewport() != data->viewport.data())
- data->setViewport(data->view->viewport());
- }
- return QObject::eventFilter(obj, event);
- }
-
- //Event from viewport
- switch (event->type()) {
- case QEvent::Leave: {
- if (leaveEvent(event))
- return true;
- break;
- }
- case QEvent::MouseButtonPress: {
- if (mousePressEvent(static_cast<QMouseEvent*>(event)))
+{
+ if (obj == data->view) {
+ // Event from view
+ if (event->type() == QEvent::ChildRemoved) {
+ // Might mean that viewport has changed
+ if (data->view->viewport() != data->viewport.data())
+ data->setViewport(data->view->viewport());
+ }
+ return QObject::eventFilter(obj, event);
+ }
+
+ //Event from viewport
+ switch (event->type()) {
+ case QEvent::Leave: {
+ if (leaveEvent(event))
+ return true;
+ break;
+ }
+ case QEvent::MouseButtonPress: {
+ if (mousePressEvent(static_cast<QMouseEvent*>(event)))
+ return true;
+ break;
+ }
+ case QEvent::MouseMove: {
+ if (mouseMoveEvent(static_cast<QMouseEvent*>(event)))
+ return true;
+ break;
+ }
+ case QEvent::MouseButtonRelease: {
+ if (mouseReleaseEvent(static_cast<QMouseEvent*>(event)))
return true;
- break;
- }
- case QEvent::MouseMove: {
- if (mouseMoveEvent(static_cast<QMouseEvent*>(event)))
- return true;
- break;
- }
- case QEvent::MouseButtonRelease: {
- if (mouseReleaseEvent(static_cast<QMouseEvent*>(event)))
- return true;
- break;
- }
- case QEvent::KeyPress: {
- if (keyPressEvent(static_cast<QKeyEvent*>(event)))
- return true;
- break;
- }
- case QEvent::KeyRelease: {
- if (keyReleaseEvent(static_cast<QKeyEvent*>(event)))
- return true;
- break;
- }
- case QEvent::MouseButtonDblClick: {
- if (mouseDoubleClickEvent(static_cast<QMouseEvent*>(event)))
- return true;
- break;
- }
- case QEvent::Wheel: {
- if (wheelEvent(static_cast<QWheelEvent*>(event)))
- return true;
- break;
- }
- default: {
- break;
- }
- } //switch
-
- // standard event processing
- return QObject::eventFilter(obj, event);
+ break;
+ }
+ case QEvent::KeyPress: {
+ if (keyPressEvent(static_cast<QKeyEvent*>(event)))
+ return true;
+ break;
+ }
+ case QEvent::KeyRelease: {
+ if (keyReleaseEvent(static_cast<QKeyEvent*>(event)))
+ return true;
+ break;
+ }
+ case QEvent::MouseButtonDblClick: {
+ if (mouseDoubleClickEvent(static_cast<QMouseEvent*>(event)))
+ return true;
+ break;
+ }
+ case QEvent::Wheel: {
+ if (wheelEvent(static_cast<QWheelEvent*>(event)))
+ return true;
+ break;
+ }
+ default: {
+ break;
+ }
+ } //switch
+
+ // standard event processing
+ return QObject::eventFilter(obj, event);
}
bool QDeclarativeViewObserver::leaveEvent(QEvent * /*event*/)
@@ -277,8 +291,6 @@ bool QDeclarativeViewObserver::mouseReleaseEvent(QMouseEvent *event)
data->cursorPos = event->pos();
data->currentTool->mouseReleaseEvent(event);
-
- data->debugService->setCurrentObjects(AbstractFormEditorTool::toObjectList(selectedItems()));
return true;
}
@@ -331,7 +343,9 @@ bool QDeclarativeViewObserver::keyReleaseEvent(QKeyEvent *event)
return true;
}
-void QDeclarativeViewObserverPrivate::_q_createQmlObject(const QString &qml, QObject *parent, const QStringList &importList, const QString &filename)
+void QDeclarativeViewObserverPrivate::_q_createQmlObject(const QString &qml, QObject *parent,
+ const QStringList &importList,
+ const QString &filename)
{
if (!parent)
return;
@@ -375,6 +389,15 @@ void QDeclarativeViewObserverPrivate::_q_clearComponentCache()
view->engine()->clearComponentCache();
}
+void QDeclarativeViewObserverPrivate::_q_removeFromSelection(QObject *obj)
+{
+ QList<QGraphicsItem*> items = selectedItems();
+ if (QGraphicsItem *item = dynamic_cast<QGraphicsItem*>(obj)) {
+ items.removeOne(item);
+ }
+ setSelectedItems(items);
+}
+
QGraphicsItem *QDeclarativeViewObserverPrivate::currentRootItem() const
{
return subcomponentEditorTool->currentRootItem();
@@ -407,8 +430,9 @@ bool QDeclarativeViewObserver::mouseDoubleClickEvent(QMouseEvent *event)
if ((event->buttons() & Qt::LeftButton) && itemToEnter) {
QGraphicsObject *objectToEnter = itemToEnter->toGraphicsObject();
- if (objectToEnter)
- data->debugService->setCurrentObjects(QList<QObject*>() << objectToEnter);
+ if (objectToEnter) {
+ setSelectedItems(QList<QGraphicsItem*>() << objectToEnter);
+ }
}
return true;
@@ -458,7 +482,35 @@ bool QDeclarativeViewObserver::designModeBehavior()
return data->designModeBehavior;
}
-void QDeclarativeViewObserverPrivate::changeTool(Constants::DesignTool tool, Constants::ToolFlags /*flags*/)
+bool QDeclarativeViewObserver::showAppOnTop() const
+{
+ return data->showAppOnTop;
+}
+
+void QDeclarativeViewObserver::setShowAppOnTop(bool appOnTop)
+{
+ if (data->view) {
+ QWidget *rootWidget = data->view;
+ while (rootWidget->parentWidget())
+ rootWidget = rootWidget->parentWidget();
+ Qt::WindowFlags flags = rootWidget->windowFlags();
+ if (appOnTop) {
+ flags |= Qt::WindowStaysOnTopHint;
+ } else {
+ flags &= ~Qt::WindowStaysOnTopHint;
+ }
+ rootWidget->setWindowFlags(flags);
+ rootWidget->show();
+ }
+
+ data->showAppOnTop = appOnTop;
+ data->debugService->setShowAppOnTop(appOnTop);
+
+ emit showAppOnTopChanged(appOnTop);
+}
+
+void QDeclarativeViewObserverPrivate::changeTool(Constants::DesignTool tool,
+ Constants::ToolFlags /*flags*/)
{
switch(tool) {
case Constants::SelectionToolMode:
@@ -473,32 +525,51 @@ void QDeclarativeViewObserverPrivate::changeTool(Constants::DesignTool tool, Con
void QDeclarativeViewObserverPrivate::setSelectedItemsForTools(QList<QGraphicsItem *> items)
{
- currentSelection.clear();
- foreach(QGraphicsItem *item, items) {
+ foreach (QWeakPointer<QGraphicsObject> obj, currentSelection) {
+ if (QGraphicsItem *item = obj.data()) {
+ if (!items.contains(item)) {
+ QObject::disconnect(obj.data(), SIGNAL(destroyed(QObject*)),
+ q, SLOT(_q_removeFromSelection(QObject*)));
+ currentSelection.removeOne(obj);
+ }
+ }
+ }
+
+ foreach (QGraphicsItem *item, items) {
if (item) {
QGraphicsObject *obj = item->toGraphicsObject();
- if (obj)
- currentSelection << obj;
+ if (obj) {
+ QObject::connect(obj, SIGNAL(destroyed(QObject*)),
+ q, SLOT(_q_removeFromSelection(QObject*)));
+ currentSelection.append(obj);
+ }
}
}
+
currentTool->updateSelectedItems();
}
void QDeclarativeViewObserverPrivate::setSelectedItems(QList<QGraphicsItem *> items)
{
+ QList<QWeakPointer<QGraphicsObject> > oldList = currentSelection;
setSelectedItemsForTools(items);
- debugService->setCurrentObjects(AbstractFormEditorTool::toObjectList(items));
+ if (oldList != currentSelection) {
+ QList<QObject*> objectList;
+ foreach (QWeakPointer<QGraphicsObject> graphicsObject, currentSelection) {
+ if (graphicsObject)
+ objectList << graphicsObject.data();
+ }
+
+ debugService->setCurrentObjects(objectList);
+ }
}
QList<QGraphicsItem *> QDeclarativeViewObserverPrivate::selectedItems()
{
QList<QGraphicsItem *> selection;
foreach(const QWeakPointer<QGraphicsObject> &selectedObject, currentSelection) {
- if (selectedObject.isNull()) {
- currentSelection.removeOne(selectedObject);
- } else {
+ if (selectedObject.data())
selection << selectedObject.data();
- }
}
return selection;
@@ -555,7 +626,8 @@ bool QDeclarativeViewObserverPrivate::mouseInsideContextItem() const
return subcomponentEditorTool->containsCursor(cursorPos.toPoint());
}
-QList<QGraphicsItem*> QDeclarativeViewObserverPrivate::selectableItems(const QPointF &scenePos) const
+QList<QGraphicsItem*> QDeclarativeViewObserverPrivate::selectableItems(
+ const QPointF &scenePos) const
{
QList<QGraphicsItem*> itemlist = view->scene()->items(scenePos);
return filterForCurrentContext(itemlist);
@@ -567,7 +639,8 @@ QList<QGraphicsItem*> QDeclarativeViewObserverPrivate::selectableItems(const QPo
return filterForCurrentContext(itemlist);
}
-QList<QGraphicsItem*> QDeclarativeViewObserverPrivate::selectableItems(const QRectF &sceneRect, Qt::ItemSelectionMode selectionMode) const
+QList<QGraphicsItem*> QDeclarativeViewObserverPrivate::selectableItems(
+ const QRectF &sceneRect, Qt::ItemSelectionMode selectionMode) const
{
QList<QGraphicsItem*> itemlist = view->scene()->items(sceneRect, selectionMode);
@@ -681,7 +754,8 @@ void QDeclarativeViewObserverPrivate::_q_applyChangesFromClient()
}
-QList<QGraphicsItem*> QDeclarativeViewObserverPrivate::filterForSelection(QList<QGraphicsItem*> &itemlist) const
+QList<QGraphicsItem*> QDeclarativeViewObserverPrivate::filterForSelection(
+ QList<QGraphicsItem*> &itemlist) const
{
foreach(QGraphicsItem *item, itemlist) {
if (isEditorItem(item) || !subcomponentEditorTool->isChildOfContext(item))
@@ -691,7 +765,8 @@ QList<QGraphicsItem*> QDeclarativeViewObserverPrivate::filterForSelection(QList<
return itemlist;
}
-QList<QGraphicsItem*> QDeclarativeViewObserverPrivate::filterForCurrentContext(QList<QGraphicsItem*> &itemlist) const
+QList<QGraphicsItem*> QDeclarativeViewObserverPrivate::filterForCurrentContext(
+ QList<QGraphicsItem*> &itemlist) const
{
foreach(QGraphicsItem *item, itemlist) {
@@ -718,8 +793,8 @@ QList<QGraphicsItem*> QDeclarativeViewObserverPrivate::filterForCurrentContext(Q
bool QDeclarativeViewObserverPrivate::isEditorItem(QGraphicsItem *item) const
{
return (item->type() == Constants::EditorItemType
- || item->type() == Constants::ResizeHandleItemType
- || item->data(Constants::EditorItemDataKey).toBool());
+ || item->type() == Constants::ResizeHandleItemType
+ || item->data(Constants::EditorItemDataKey).toBool());
}
void QDeclarativeViewObserverPrivate::_q_onStatusChanged(QDeclarativeView::Status status)
@@ -794,18 +869,24 @@ QToolBar *QDeclarativeViewObserver::toolbar() const
void QDeclarativeViewObserverPrivate::createToolbar()
{
toolbar = new QmlToolbar(q->declarativeView());
- QObject::connect(q, SIGNAL(selectedColorChanged(QColor)), toolbar, SLOT(setColorBoxColor(QColor)));
+ QObject::connect(q, SIGNAL(selectedColorChanged(QColor)),
+ toolbar, SLOT(setColorBoxColor(QColor)));
- QObject::connect(q, SIGNAL(designModeBehaviorChanged(bool)), toolbar, SLOT(setDesignModeBehavior(bool)));
+ QObject::connect(q, SIGNAL(designModeBehaviorChanged(bool)),
+ toolbar, SLOT(setDesignModeBehavior(bool)));
- QObject::connect(toolbar, SIGNAL(designModeBehaviorChanged(bool)), q, SLOT(setDesignModeBehavior(bool)));
- QObject::connect(toolbar, SIGNAL(animationSpeedChanged(qreal)), q, SLOT(changeAnimationSpeed(qreal)));
+ QObject::connect(toolbar, SIGNAL(designModeBehaviorChanged(bool)),
+ q, SLOT(setDesignModeBehavior(bool)));
+ QObject::connect(toolbar, SIGNAL(animationSpeedChanged(qreal)),
+ q, SLOT(changeAnimationSpeed(qreal)));
QObject::connect(toolbar, SIGNAL(colorPickerSelected()), q, SLOT(_q_changeToColorPickerTool()));
QObject::connect(toolbar, SIGNAL(zoomToolSelected()), q, SLOT(_q_changeToZoomTool()));
QObject::connect(toolbar, SIGNAL(selectToolSelected()), q, SLOT(_q_changeToSingleSelectTool()));
- QObject::connect(toolbar, SIGNAL(marqueeSelectToolSelected()), q, SLOT(_q_changeToMarqueeSelectTool()));
+ QObject::connect(toolbar, SIGNAL(marqueeSelectToolSelected()),
+ q, SLOT(_q_changeToMarqueeSelectTool()));
- QObject::connect(toolbar, SIGNAL(applyChangesFromQmlFileSelected()), q, SLOT(_q_applyChangesFromClient()));
+ QObject::connect(toolbar, SIGNAL(applyChangesFromQmlFileSelected()),
+ q, SLOT(_q_applyChangesFromClient()));
QObject::connect(q, SIGNAL(executionStarted(qreal)), toolbar, SLOT(setAnimationSpeed(qreal)));
QObject::connect(q, SIGNAL(executionPaused()), toolbar, SLOT(setAnimationSpeed()));
@@ -819,7 +900,8 @@ void QDeclarativeViewObserverPrivate::createToolbar()
QObject::connect(q, SIGNAL(colorPickerActivated()), toolbar, SLOT(activateColorPicker()));
QObject::connect(q, SIGNAL(zoomToolActivated()), toolbar, SLOT(activateZoom()));
- QObject::connect(q, SIGNAL(marqueeSelectToolActivated()), toolbar, SLOT(activateMarqueeSelectTool()));
+ QObject::connect(q, SIGNAL(marqueeSelectToolActivated()),
+ toolbar, SLOT(activateMarqueeSelectTool()));
}
diff --git a/share/qtcreator/qml/qmljsdebugger/qdeclarativeviewobserver_p.h b/share/qtcreator/qml/qmljsdebugger/qdeclarativeviewobserver_p.h
index 1bb3f0b76a..27dcdfc1c4 100644
--- a/share/qtcreator/qml/qmljsdebugger/qdeclarativeviewobserver_p.h
+++ b/share/qtcreator/qml/qmljsdebugger/qdeclarativeviewobserver_p.h
@@ -87,6 +87,7 @@ public:
BoundingRectHighlighter *boundingRectHighlighter;
bool designModeBehavior;
+ bool showAppOnTop;
bool executionPaused;
qreal slowdownFactor;
@@ -137,6 +138,7 @@ public:
void _q_changeToColorPickerTool();
void _q_changeContextPathIndex(int index);
void _q_clearComponentCache();
+ void _q_removeFromSelection(QObject *);
static QDeclarativeViewObserverPrivate *get(QDeclarativeViewObserver *v) { return v->d_func(); }
};
diff --git a/share/qtcreator/qml/qmljsdebugger/qmljsdebugger-lib.pri b/share/qtcreator/qml/qmljsdebugger/qmljsdebugger-lib.pri
index 06b9b4e93e..7165e269bb 100644
--- a/share/qtcreator/qml/qmljsdebugger/qmljsdebugger-lib.pri
+++ b/share/qtcreator/qml/qmljsdebugger/qmljsdebugger-lib.pri
@@ -11,28 +11,57 @@ contains(CONFIG, dll) {
DEFINES += BUILD_QMLJSDEBUGGER_STATIC_LIB
}
-## Input
!contains(DEFINES, NO_JSDEBUGGER) {
-HEADERS += \
- include/jsdebuggeragent.h \
- include/qmljsdebugger_global.h
-SOURCES += \
- jsdebuggeragent.cpp
+ HEADERS += \
+ include/jsdebuggeragent.h \
+ include/qmljsdebugger_global.h
+
+ SOURCES += \
+ jsdebuggeragent.cpp
}
!contains(DEFINES, NO_QMLOBSERVER) {
- include($$PWD/editor/editor.pri)
HEADERS += \
include/qdeclarativeviewobserver.h \
include/qdeclarativeobserverservice.h \
include/qmlobserverconstants.h \
+ editor/abstractformeditortool.h \
+ editor/selectiontool.h \
+ editor/layeritem.h \
+ editor/singleselectionmanipulator.h \
+ editor/rubberbandselectionmanipulator.h \
+ editor/selectionrectangle.h \
+ editor/selectionindicator.h \
+ editor/boundingrecthighlighter.h \
+ editor/subcomponenteditortool.h \
+ editor/subcomponentmasklayeritem.h \
+ editor/zoomtool.h \
+ editor/colorpickertool.h \
+ editor/qmltoolbar.h \
+ editor/toolbarcolorbox.h \
qdeclarativeviewobserver_p.h
SOURCES += \
qdeclarativeviewobserver.cpp \
- qdeclarativeobserverservice.cpp
+ qdeclarativeobserverservice.cpp \
+ editor/abstractformeditortool.cpp \
+ editor/selectiontool.cpp \
+ editor/layeritem.cpp \
+ editor/singleselectionmanipulator.cpp \
+ editor/rubberbandselectionmanipulator.cpp \
+ editor/selectionrectangle.cpp \
+ editor/selectionindicator.cpp \
+ editor/boundingrecthighlighter.cpp \
+ editor/subcomponenteditortool.cpp \
+ editor/subcomponentmasklayeritem.cpp \
+ editor/zoomtool.cpp \
+ editor/colorpickertool.cpp \
+ editor/qmltoolbar.cpp \
+ editor/toolbarcolorbox.cpp
+
+ RESOURCES += editor/editor.qrc
}
OTHER_FILES += qmljsdebugger.pri
diff --git a/share/qtcreator/qml/qmlobserver/Info_mac.plist b/share/qtcreator/qml/qmlobserver/Info_mac.plist
index 80ca6a3526..08775479ba 100644
--- a/share/qtcreator/qml/qmlobserver/Info_mac.plist
+++ b/share/qtcreator/qml/qmlobserver/Info_mac.plist
@@ -14,5 +14,36 @@
<string>@TYPEINFO@</string>
<key>CFBundleExecutable</key>
<string>@EXECUTABLE@</string>
+ <key>UTExportedTypeDeclarations</key>
+ <array>
+ <dict>
+ <key>UTTypeIdentifier</key>
+ <string>com.nokia.qt.qml</string>
+ <key>UTTypeDescription</key>
+ <string>Qt Markup Language</string>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.plain-text</string>
+ </array>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>qml</string>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>CFBundleDocumentTypes</key>
+ <array>
+ <dict>
+ <key>LSItemContentTypes</key>
+ <array>
+ <string>com.nokia.qt.qml</string>
+ </array>
+ <key>CFBundleTypeRole</key>
+ <string>Viewer</string>
+ </dict>
+ </array>
</dict>
</plist>
diff --git a/share/qtcreator/qml/qmlobserver/browser/Browser.qml b/share/qtcreator/qml/qmlobserver/browser/Browser.qml
new file mode 100644
index 0000000000..968d077c4e
--- /dev/null
+++ b/share/qtcreator/qml/qmlobserver/browser/Browser.qml
@@ -0,0 +1,318 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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$
+**
+****************************************************************************/
+
+import QtQuick 1.0
+import Qt.labs.folderlistmodel 1.0
+
+Rectangle {
+ id: root
+ property bool showFocusHighlight: false
+ property variant folders: folders1
+ property variant view: view1
+ width: 320
+ height: 480
+ color: palette.window
+
+ FolderListModel {
+ id: folders1
+ nameFilters: [ "*.qml" ]
+ folder: qmlViewerFolder
+ }
+ FolderListModel {
+ id: folders2
+ nameFilters: [ "*.qml" ]
+ folder: qmlViewerFolder
+ }
+
+ SystemPalette { id: palette }
+
+ function down(path) {
+ if (folders == folders1) {
+ view = view2
+ folders = folders2;
+ view1.state = "exitLeft";
+ } else {
+ view = view1
+ folders = folders1;
+ view2.state = "exitLeft";
+ }
+ view.x = root.width;
+ view.state = "current";
+ view.focus = true;
+ folders.folder = path;
+ }
+ function up() {
+ var path = folders.parentFolder;
+ if (folders == folders1) {
+ view = view2
+ folders = folders2;
+ view1.state = "exitRight";
+ } else {
+ view = view1
+ folders = folders1;
+ view2.state = "exitRight";
+ }
+ view.x = -root.width;
+ view.state = "current";
+ view.focus = true;
+ folders.folder = path;
+ }
+ function keyPressed(key) {
+ switch (key) {
+ case Qt.Key_Up:
+ case Qt.Key_Down:
+ case Qt.Key_Left:
+ case Qt.Key_Right:
+ root.showFocusHighlight = true;
+ break;
+ default:
+ // do nothing
+ break;
+ }
+ }
+
+ Component {
+ id: folderDelegate
+ Rectangle {
+ id: wrapper
+ function launch() {
+ if (folders.isFolder(index)) {
+ down(filePath);
+ } else {
+ qmlViewer.launch(filePath);
+ }
+ }
+ width: root.width
+ height: 52
+ color: "transparent"
+ Rectangle {
+ id: highlight; visible: false
+ anchors.fill: parent
+ color: palette.highlight
+ gradient: Gradient {
+ GradientStop { id: t1; position: 0.0; color: palette.highlight }
+ GradientStop { id: t2; position: 1.0; color: Qt.lighter(palette.highlight) }
+ }
+ }
+ Item {
+ width: 48; height: 48
+ Image { source: "images/folder.png"; anchors.centerIn: parent; visible: folders.isFolder(index)}
+ }
+ Text {
+ id: nameText
+ anchors.fill: parent; verticalAlignment: Text.AlignVCenter
+ text: fileName
+ anchors.leftMargin: 54
+ font.pixelSize: 32
+ color: (wrapper.ListView.isCurrentItem && root.showFocusHighlight) ? palette.highlightedText : palette.windowText
+ elide: Text.ElideRight
+ }
+ MouseArea {
+ id: mouseRegion
+ anchors.fill: parent
+ onPressed: {
+ root.showFocusHighlight = false;
+ wrapper.ListView.view.currentIndex = index;
+ }
+ onClicked: { if (folders == wrapper.ListView.view.model) launch() }
+ }
+ states: [
+ State {
+ name: "pressed"
+ when: mouseRegion.pressed
+ PropertyChanges { target: highlight; visible: true }
+ PropertyChanges { target: nameText; color: palette.highlightedText }
+ }
+ ]
+ }
+ }
+
+ ListView {
+ id: view1
+ anchors.top: titleBar.bottom
+ anchors.bottom: parent.bottom
+ x: 0
+ width: parent.width
+ model: folders1
+ delegate: folderDelegate
+ highlight: Rectangle {
+ color: palette.highlight
+ visible: root.showFocusHighlight && view1.count != 0
+ gradient: Gradient {
+ GradientStop { id: t1; position: 0.0; color: palette.highlight }
+ GradientStop { id: t2; position: 1.0; color: Qt.lighter(palette.highlight) }
+ }
+ width: view1.currentItem == null ? 0 : view1.currentItem.width
+ }
+ highlightMoveSpeed: 1000
+ pressDelay: 100
+ focus: true
+ state: "current"
+ states: [
+ State {
+ name: "current"
+ PropertyChanges { target: view1; x: 0 }
+ },
+ State {
+ name: "exitLeft"
+ PropertyChanges { target: view1; x: -root.width }
+ },
+ State {
+ name: "exitRight"
+ PropertyChanges { target: view1; x: root.width }
+ }
+ ]
+ transitions: [
+ Transition {
+ to: "current"
+ SequentialAnimation {
+ NumberAnimation { properties: "x"; duration: 250 }
+ }
+ },
+ Transition {
+ NumberAnimation { properties: "x"; duration: 250 }
+ NumberAnimation { properties: "x"; duration: 250 }
+ }
+ ]
+ Keys.onPressed: root.keyPressed(event.key)
+ }
+
+ ListView {
+ id: view2
+ anchors.top: titleBar.bottom
+ anchors.bottom: parent.bottom
+ x: parent.width
+ width: parent.width
+ model: folders2
+ delegate: folderDelegate
+ highlight: Rectangle {
+ color: palette.highlight
+ visible: root.showFocusHighlight && view2.count != 0
+ gradient: Gradient {
+ GradientStop { id: t1; position: 0.0; color: palette.highlight }
+ GradientStop { id: t2; position: 1.0; color: Qt.lighter(palette.highlight) }
+ }
+ width: view1.currentItem == null ? 0 : view1.currentItem.width
+ }
+ highlightMoveSpeed: 1000
+ pressDelay: 100
+ states: [
+ State {
+ name: "current"
+ PropertyChanges { target: view2; x: 0 }
+ },
+ State {
+ name: "exitLeft"
+ PropertyChanges { target: view2; x: -root.width }
+ },
+ State {
+ name: "exitRight"
+ PropertyChanges { target: view2; x: root.width }
+ }
+ ]
+ transitions: [
+ Transition {
+ to: "current"
+ SequentialAnimation {
+ NumberAnimation { properties: "x"; duration: 250 }
+ }
+ },
+ Transition {
+ NumberAnimation { properties: "x"; duration: 250 }
+ }
+ ]
+ Keys.onPressed: root.keyPressed(event.key)
+ }
+
+ Keys.onPressed: {
+ root.keyPressed(event.key);
+ if (event.key == Qt.Key_Return || event.key == Qt.Key_Select || event.key == Qt.Key_Right) {
+ view.currentItem.launch();
+ event.accepted = true;
+ } else if (event.key == Qt.Key_Left) {
+ up();
+ }
+ }
+
+ BorderImage {
+ source: "images/titlebar.sci";
+ width: parent.width;
+ height: 52
+ y: -7
+ id: titleBar
+
+ Rectangle {
+ id: upButton
+ width: 48
+ height: titleBar.height - 7
+ color: "transparent"
+
+ Image { anchors.centerIn: parent; source: "images/up.png" }
+ MouseArea { id: upRegion; anchors.centerIn: parent
+ width: 56
+ height: 56
+ onClicked: if (folders.parentFolder != "") up()
+ }
+ states: [
+ State {
+ name: "pressed"
+ when: upRegion.pressed
+ PropertyChanges { target: upButton; color: palette.highlight }
+ }
+ ]
+ }
+ Rectangle {
+ color: "gray"
+ x: 48
+ width: 1
+ height: 44
+ }
+
+ Text {
+ anchors.left: upButton.right; anchors.right: parent.right; height: parent.height
+ anchors.leftMargin: 4; anchors.rightMargin: 4
+ text: folders.folder
+ color: "white"
+ elide: Text.ElideLeft; horizontalAlignment: Text.AlignRight; verticalAlignment: Text.AlignVCenter
+ font.pixelSize: 32
+ }
+ }
+}
diff --git a/share/qtcreator/qml/qmlobserver/browser/browser.qrc b/share/qtcreator/qml/qmlobserver/browser/browser.qrc
new file mode 100644
index 0000000000..9c688e7521
--- /dev/null
+++ b/share/qtcreator/qml/qmlobserver/browser/browser.qrc
@@ -0,0 +1,9 @@
+<RCC>
+ <qresource prefix="/browser">
+ <file>Browser.qml</file>
+ <file>images/up.png</file>
+ <file>images/folder.png</file>
+ <file>images/titlebar.sci</file>
+ <file>images/titlebar.png</file>
+ </qresource>
+</RCC>
diff --git a/share/qtcreator/qml/qmlobserver/content/images/folder.png b/share/qtcreator/qml/qmlobserver/browser/images/folder.png
index e53e2ad464..e53e2ad464 100644
--- a/share/qtcreator/qml/qmlobserver/content/images/folder.png
+++ b/share/qtcreator/qml/qmlobserver/browser/images/folder.png
Binary files differ
diff --git a/share/qtcreator/qml/qmlobserver/content/images/titlebar.png b/share/qtcreator/qml/qmlobserver/browser/images/titlebar.png
index 51c90082d0..51c90082d0 100644
--- a/share/qtcreator/qml/qmlobserver/content/images/titlebar.png
+++ b/share/qtcreator/qml/qmlobserver/browser/images/titlebar.png
Binary files differ
diff --git a/share/qtcreator/qml/qmlobserver/content/images/titlebar.sci b/share/qtcreator/qml/qmlobserver/browser/images/titlebar.sci
index 0418d94cd6..0418d94cd6 100644
--- a/share/qtcreator/qml/qmlobserver/content/images/titlebar.sci
+++ b/share/qtcreator/qml/qmlobserver/browser/images/titlebar.sci
diff --git a/share/qtcreator/qml/qmlobserver/content/images/up.png b/share/qtcreator/qml/qmlobserver/browser/images/up.png
index b05f8025d0..b05f8025d0 100644
--- a/share/qtcreator/qml/qmlobserver/content/images/up.png
+++ b/share/qtcreator/qml/qmlobserver/browser/images/up.png
Binary files differ
diff --git a/share/qtcreator/qml/qmlobserver/content/Browser.qml b/share/qtcreator/qml/qmlobserver/content/Browser.qml
deleted file mode 100644
index ff2bb47647..0000000000
--- a/share/qtcreator/qml/qmlobserver/content/Browser.qml
+++ /dev/null
@@ -1,284 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 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$
-**
-****************************************************************************/
-
-import Qt 4.7
-import Qt.labs.folderlistmodel 1.0
-
-Rectangle {
- id: root
- property bool keyPressed: false
- property variant folders: folders1
- property variant view: view1
- width: 320
- height: 480
- color: palette.window
-
- FolderListModel {
- id: folders1
- nameFilters: [ "*.qml" ]
- folder: qmlViewerFolder
- }
- FolderListModel {
- id: folders2
- nameFilters: [ "*.qml" ]
- folder: qmlViewerFolder
- }
-
- SystemPalette { id: palette }
-
- function down(path) {
- if (folders == folders1) {
- view = view2
- folders = folders2;
- view1.state = "exitLeft";
- } else {
- view = view1
- folders = folders1;
- view2.state = "exitLeft";
- }
- view.x = root.width;
- view.state = "current";
- view.focus = true;
- folders.folder = path;
- }
- function up() {
- var path = folders.parentFolder;
- if (folders == folders1) {
- view = view2
- folders = folders2;
- view1.state = "exitRight";
- } else {
- view = view1
- folders = folders1;
- view2.state = "exitRight";
- }
- view.x = -root.width;
- view.state = "current";
- view.focus = true;
- folders.folder = path;
- }
-
- Component {
- id: folderDelegate
- Rectangle {
- id: wrapper
- function launch() {
- if (folders.isFolder(index)) {
- down(filePath);
- } else {
- qmlViewer.launch(filePath);
- }
- }
- width: root.width
- height: 52
- color: "transparent"
- Rectangle {
- id: highlight; visible: false
- anchors.fill: parent
- gradient: Gradient {
- GradientStop { id: t1; position: 0.0; color: palette.highlight }
- GradientStop { id: t2; position: 1.0; color: Qt.lighter(palette.highlight) }
- }
- }
- Item {
- width: 48; height: 48
- Image { source: "images/folder.png"; anchors.centerIn: parent; visible: folders.isFolder(index)}
- }
- Text {
- id: nameText
- anchors.fill: parent; verticalAlignment: Text.AlignVCenter
- text: fileName
- anchors.leftMargin: 54
- font.pixelSize: 32
- color: (wrapper.ListView.isCurrentItem && root.keyPressed) ? palette.highlightedText : palette.windowText
- elide: Text.ElideRight
- }
- MouseArea {
- id: mouseRegion
- anchors.fill: parent
- onClicked: { if (folders == wrapper.ListView.view.model) launch() }
- }
- states: [
- State {
- name: "pressed"
- when: mouseRegion.pressed
- PropertyChanges { target: highlight; visible: true }
- PropertyChanges { target: nameText; color: palette.highlightedText }
- }
- ]
- }
- }
-
- ListView {
- id: view1
- anchors.top: titleBar.bottom
- anchors.bottom: parent.bottom
- x: 0
- width: parent.width
- model: folders1
- delegate: folderDelegate
- highlight: Rectangle { color: palette.highlight; visible: root.keyPressed && view1.count != 0 }
- highlightMoveSpeed: 1000
- pressDelay: 100
- focus: true
- state: "current"
- states: [
- State {
- name: "current"
- PropertyChanges { target: view1; x: 0 }
- },
- State {
- name: "exitLeft"
- PropertyChanges { target: view1; x: -root.width }
- },
- State {
- name: "exitRight"
- PropertyChanges { target: view1; x: root.width }
- }
- ]
- transitions: [
- Transition {
- to: "current"
- SequentialAnimation {
- NumberAnimation { properties: "x"; duration: 250 }
- }
- },
- Transition {
- NumberAnimation { properties: "x"; duration: 250 }
- NumberAnimation { properties: "x"; duration: 250 }
- }
- ]
- Keys.onPressed: { root.keyPressed = true; }
- }
-
- ListView {
- id: view2
- anchors.top: titleBar.bottom
- anchors.bottom: parent.bottom
- x: parent.width
- width: parent.width
- model: folders2
- delegate: folderDelegate
- highlight: Rectangle { color: palette.highlight; visible: root.keyPressed && view2.count != 0 }
- highlightMoveSpeed: 1000
- pressDelay: 100
- states: [
- State {
- name: "current"
- PropertyChanges { target: view2; x: 0 }
- },
- State {
- name: "exitLeft"
- PropertyChanges { target: view2; x: -root.width }
- },
- State {
- name: "exitRight"
- PropertyChanges { target: view2; x: root.width }
- }
- ]
- transitions: [
- Transition {
- to: "current"
- SequentialAnimation {
- NumberAnimation { properties: "x"; duration: 250 }
- }
- },
- Transition {
- NumberAnimation { properties: "x"; duration: 250 }
- }
- ]
- Keys.onPressed: { root.keyPressed = true; }
- }
-
- Keys.onPressed: {
- root.keyPressed = true;
- if (event.key == Qt.Key_Return || event.key == Qt.Key_Select || event.key == Qt.Key_Right) {
- view.currentItem.launch();
- event.accepted = true;
- } else if (event.key == Qt.Key_Left) {
- up();
- }
- }
-
- BorderImage {
- source: "images/titlebar.sci";
- width: parent.width;
- height: 52
- y: -7
- id: titleBar
-
- Rectangle {
- id: upButton
- width: 48
- height: titleBar.height - 7
- color: "transparent"
-
- Image { anchors.centerIn: parent; source: "images/up.png" }
- MouseArea { id: upRegion; anchors.centerIn: parent
- width: 56
- height: 56
- onClicked: if (folders.parentFolder != "") up()
- }
- states: [
- State {
- name: "pressed"
- when: upRegion.pressed
- PropertyChanges { target: upButton; color: palette.highlight }
- }
- ]
- }
- Rectangle {
- color: "gray"
- x: 48
- width: 1
- height: 44
- }
-
- Text {
- anchors.left: upButton.right; anchors.right: parent.right; height: parent.height
- anchors.leftMargin: 4; anchors.rightMargin: 4
- text: folders.folder
- color: "white"
- elide: Text.ElideLeft; horizontalAlignment: Text.AlignRight; verticalAlignment: Text.AlignVCenter
- font.pixelSize: 32
- }
- }
-}
diff --git a/share/qtcreator/qml/qmlobserver/deviceorientation.cpp b/share/qtcreator/qml/qmlobserver/deviceorientation.cpp
index e7c70d5fde..d3014ad150 100644
--- a/share/qtcreator/qml/qmlobserver/deviceorientation.cpp
+++ b/share/qtcreator/qml/qmlobserver/deviceorientation.cpp
@@ -53,6 +53,11 @@ public:
return m_orientation;
}
+ void pauseListening() {
+ }
+ void resumeListening() {
+ }
+
void setOrientation(Orientation o) {
if (o != m_orientation) {
m_orientation = o;
diff --git a/share/qtcreator/qml/qmlobserver/deviceorientation.h b/share/qtcreator/qml/qmlobserver/deviceorientation.h
index 3bad5bec01..88ceb1bdae 100644
--- a/share/qtcreator/qml/qmlobserver/deviceorientation.h
+++ b/share/qtcreator/qml/qmlobserver/deviceorientation.h
@@ -63,6 +63,9 @@ public:
virtual Orientation orientation() const = 0;
virtual void setOrientation(Orientation) = 0;
+ virtual void pauseListening() = 0;
+ virtual void resumeListening() = 0;
+
static DeviceOrientation *instance();
signals:
diff --git a/share/qtcreator/qml/qmlobserver/deviceorientation_harmattan.cpp b/share/qtcreator/qml/qmlobserver/deviceorientation_harmattan.cpp
new file mode 100644
index 0000000000..22f9f4c51f
--- /dev/null
+++ b/share/qtcreator/qml/qmlobserver/deviceorientation_harmattan.cpp
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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 "deviceorientation.h"
+#include <QtDBus>
+#include <QDebug>
+
+#define ORIENTATION_SERVICE "com.nokia.SensorService"
+#define ORIENTATION_PATH "/org/maemo/contextkit/Screen/TopEdge"
+#define CONTEXT_INTERFACE "org.maemo.contextkit.Property"
+#define CONTEXT_CHANGED "ValueChanged"
+#define CONTEXT_SUBSCRIBE "Subscribe"
+#define CONTEXT_UNSUBSCRIBE "Unsubscribe"
+#define CONTEXT_GET "Get"
+
+
+class HarmattanOrientation : public DeviceOrientation
+{
+ Q_OBJECT
+public:
+ HarmattanOrientation()
+ : o(UnknownOrientation), sensorEnabled(false)
+ {
+ resumeListening();
+ // connect to the orientation change signal
+ bool ok = QDBusConnection::systemBus().connect(ORIENTATION_SERVICE, ORIENTATION_PATH,
+ CONTEXT_INTERFACE,
+ CONTEXT_CHANGED,
+ this,
+ SLOT(deviceOrientationChanged(QList<QVariant>,quint64)));
+// qDebug() << "connection OK" << ok;
+ QDBusMessage reply = QDBusConnection::systemBus().call(
+ QDBusMessage::createMethodCall(ORIENTATION_SERVICE, ORIENTATION_PATH,
+ CONTEXT_INTERFACE, CONTEXT_GET));
+ if (reply.type() != QDBusMessage::ErrorMessage) {
+ QList<QVariant> args;
+ qvariant_cast<QDBusArgument>(reply.arguments().at(0)) >> args;
+ deviceOrientationChanged(args, 0);
+ }
+ }
+
+ ~HarmattanOrientation()
+ {
+ // unsubscribe from the orientation sensor
+ if (sensorEnabled)
+ QDBusConnection::systemBus().call(
+ QDBusMessage::createMethodCall(ORIENTATION_SERVICE, ORIENTATION_PATH,
+ CONTEXT_INTERFACE, CONTEXT_UNSUBSCRIBE));
+ }
+
+ inline Orientation orientation() const
+ {
+ return o;
+ }
+
+ void setOrientation(Orientation)
+ {
+ }
+
+ void pauseListening() {
+ if (sensorEnabled) {
+ // unsubscribe from the orientation sensor
+ QDBusConnection::systemBus().call(
+ QDBusMessage::createMethodCall(ORIENTATION_SERVICE, ORIENTATION_PATH,
+ CONTEXT_INTERFACE, CONTEXT_UNSUBSCRIBE));
+ sensorEnabled = false;
+ }
+ }
+
+ void resumeListening() {
+ if (!sensorEnabled) {
+ // subscribe to the orientation sensor
+ QDBusMessage reply = QDBusConnection::systemBus().call(
+ QDBusMessage::createMethodCall(ORIENTATION_SERVICE, ORIENTATION_PATH,
+ CONTEXT_INTERFACE, CONTEXT_SUBSCRIBE));
+
+ if (reply.type() == QDBusMessage::ErrorMessage) {
+ qWarning("Unable to retrieve device orientation: %s", qPrintable(reply.errorMessage()));
+ } else {
+ sensorEnabled = true;
+ }
+ }
+ }
+
+private Q_SLOTS:
+ void deviceOrientationChanged(QList<QVariant> args,quint64)
+ {
+ if (args.count() == 0)
+ return;
+ Orientation newOrientation = toOrientation(args.at(0).toString());
+ if (newOrientation != o) {
+ o = newOrientation;
+ emit orientationChanged();
+ }
+// qDebug() << "orientation" << args.at(0).toString();
+ }
+
+private:
+ static Orientation toOrientation(const QString &nativeOrientation)
+ {
+ if (nativeOrientation == "top")
+ return Landscape;
+ else if (nativeOrientation == "left")
+ return Portrait;
+ else if (nativeOrientation == "bottom")
+ return LandscapeInverted;
+ else if (nativeOrientation == "right")
+ return PortraitInverted;
+ return UnknownOrientation;
+ }
+
+private:
+ Orientation o;
+ bool sensorEnabled;
+};
+
+DeviceOrientation* DeviceOrientation::instance()
+{
+ static HarmattanOrientation *o = new HarmattanOrientation;
+ return o;
+}
+
+#include "deviceorientation_harmattan.moc"
diff --git a/share/qtcreator/qml/qmlobserver/deviceorientation_maemo5.cpp b/share/qtcreator/qml/qmlobserver/deviceorientation_maemo5.cpp
index e942579b70..a324820d5f 100644
--- a/share/qtcreator/qml/qmlobserver/deviceorientation_maemo5.cpp
+++ b/share/qtcreator/qml/qmlobserver/deviceorientation_maemo5.cpp
@@ -50,23 +50,9 @@ class MaemoOrientation : public DeviceOrientation
Q_OBJECT
public:
MaemoOrientation()
- : o(UnknownOrientation)
+ : o(UnknownOrientation), sensorEnabled(false)
{
- // enable the orientation sensor
- QDBusConnection::systemBus().call(
- QDBusMessage::createMethodCall(MCE_SERVICE, MCE_REQUEST_PATH,
- MCE_REQUEST_IF, MCE_ACCELEROMETER_ENABLE_REQ));
-
- // query the initial orientation
- QDBusMessage reply = QDBusConnection::systemBus().call(
- QDBusMessage::createMethodCall(MCE_SERVICE, MCE_REQUEST_PATH,
- MCE_REQUEST_IF, MCE_DEVICE_ORIENTATION_GET));
- if (reply.type() == QDBusMessage::ErrorMessage) {
- qWarning("Unable to retrieve device orientation: %s", qPrintable(reply.errorMessage()));
- } else {
- o = toOrientation(reply.arguments().value(0).toString());
- }
-
+ resumeListening();
// connect to the orientation change signal
QDBusConnection::systemBus().connect(QString(), MCE_SIGNAL_PATH, MCE_SIGNAL_IF,
MCE_DEVICE_ORIENTATION_SIG,
@@ -91,6 +77,40 @@ public:
{
}
+ void pauseListening() {
+ if (sensorEnabled) {
+ // disable the orientation sensor
+ QDBusConnection::systemBus().call(
+ QDBusMessage::createMethodCall(MCE_SERVICE, MCE_REQUEST_PATH,
+ MCE_REQUEST_IF, MCE_ACCELEROMETER_DISABLE_REQ));
+ sensorEnabled = false;
+ }
+ }
+
+ void resumeListening() {
+ if (!sensorEnabled) {
+ // enable the orientation sensor
+ QDBusConnection::systemBus().call(
+ QDBusMessage::createMethodCall(MCE_SERVICE, MCE_REQUEST_PATH,
+ MCE_REQUEST_IF, MCE_ACCELEROMETER_ENABLE_REQ));
+
+ QDBusMessage reply = QDBusConnection::systemBus().call(
+ QDBusMessage::createMethodCall(MCE_SERVICE, MCE_REQUEST_PATH,
+ MCE_REQUEST_IF, MCE_DEVICE_ORIENTATION_GET));
+
+ if (reply.type() == QDBusMessage::ErrorMessage) {
+ qWarning("Unable to retrieve device orientation: %s", qPrintable(reply.errorMessage()));
+ } else {
+ Orientation orientation = toOrientation(reply.arguments().value(0).toString());
+ if (o != orientation) {
+ o = orientation;
+ emit orientationChanged();
+ }
+ sensorEnabled = true;
+ }
+ }
+ }
+
private Q_SLOTS:
void deviceOrientationChanged(const QString &newOrientation)
{
@@ -116,6 +136,7 @@ private:
private:
Orientation o;
+ bool sensorEnabled;
};
DeviceOrientation* DeviceOrientation::instance()
diff --git a/share/qtcreator/qml/qmlobserver/deviceorientation_symbian.cpp b/share/qtcreator/qml/qmlobserver/deviceorientation_symbian.cpp
new file mode 100644
index 0000000000..7710cf9b19
--- /dev/null
+++ b/share/qtcreator/qml/qmlobserver/deviceorientation_symbian.cpp
@@ -0,0 +1,192 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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 "deviceorientation.h"
+
+#include <e32base.h>
+#include <sensrvchannelfinder.h>
+#include <sensrvdatalistener.h>
+#include <sensrvchannel.h>
+#include <sensrvorientationsensor.h>
+
+class SymbianOrientation : public DeviceOrientation, public MSensrvDataListener
+{
+ Q_OBJECT
+public:
+ SymbianOrientation()
+ : DeviceOrientation(), m_current(UnknownOrientation), m_sensorChannel(0), m_channelOpen(false)
+ {
+ TRAP_IGNORE(initL());
+ if (!m_sensorChannel)
+ qWarning("No valid sensors found.");
+ }
+
+ ~SymbianOrientation()
+ {
+ if (m_sensorChannel) {
+ m_sensorChannel->StopDataListening();
+ m_sensorChannel->CloseChannel();
+ delete m_sensorChannel;
+ }
+ }
+
+ void initL()
+ {
+ CSensrvChannelFinder *channelFinder = CSensrvChannelFinder::NewLC();
+ RSensrvChannelInfoList channelInfoList;
+ CleanupClosePushL(channelInfoList);
+
+ TSensrvChannelInfo searchConditions;
+ searchConditions.iChannelType = KSensrvChannelTypeIdOrientationData;
+ channelFinder->FindChannelsL(channelInfoList, searchConditions);
+
+ for (int i = 0; i < channelInfoList.Count(); ++i) {
+ TRAPD(error, m_sensorChannel = CSensrvChannel::NewL(channelInfoList[i]));
+ if (!error)
+ TRAP(error, m_sensorChannel->OpenChannelL());
+ if (!error) {
+ TRAP(error, m_sensorChannel->StartDataListeningL(this, 1, 1, 0));
+ m_channelOpen = true;
+ break;
+ }
+ if (error) {
+ delete m_sensorChannel;
+ m_sensorChannel = 0;
+ }
+ }
+
+ channelInfoList.Close();
+ CleanupStack::Pop(&channelInfoList);
+ CleanupStack::PopAndDestroy(channelFinder);
+ }
+
+ Orientation orientation() const
+ {
+ return m_current;
+ }
+
+ void setOrientation(Orientation) { }
+
+private:
+ DeviceOrientation::Orientation m_current;
+ CSensrvChannel *m_sensorChannel;
+ bool m_channelOpen;
+ void pauseListening() {
+ if (m_sensorChannel && m_channelOpen) {
+ m_sensorChannel->StopDataListening();
+ m_sensorChannel->CloseChannel();
+ m_channelOpen = false;
+ }
+ }
+
+ void resumeListening() {
+ if (m_sensorChannel && !m_channelOpen) {
+ TRAPD(error, m_sensorChannel->OpenChannelL());
+ if (!error) {
+ TRAP(error, m_sensorChannel->StartDataListeningL(this, 1, 1, 0));
+ if (!error) {
+ m_channelOpen = true;
+ }
+ }
+ if (error) {
+ delete m_sensorChannel;
+ m_sensorChannel = 0;
+ }
+ }
+ }
+
+ void DataReceived(CSensrvChannel &channel, TInt count, TInt dataLost)
+ {
+ Q_UNUSED(dataLost)
+ if (channel.GetChannelInfo().iChannelType == KSensrvChannelTypeIdOrientationData) {
+ TSensrvOrientationData data;
+ for (int i = 0; i < count; ++i) {
+ TPckgBuf<TSensrvOrientationData> dataBuf;
+ channel.GetData(dataBuf);
+ data = dataBuf();
+ Orientation orientation = UnknownOrientation;
+ switch (data.iDeviceOrientation) {
+ case TSensrvOrientationData::EOrientationDisplayUp:
+ orientation = Portrait;
+ break;
+ case TSensrvOrientationData::EOrientationDisplayRightUp:
+ orientation = Landscape;
+ break;
+ case TSensrvOrientationData::EOrientationDisplayLeftUp:
+ orientation = LandscapeInverted;
+ break;
+ case TSensrvOrientationData::EOrientationDisplayDown:
+ orientation = PortraitInverted;
+ break;
+ case TSensrvOrientationData::EOrientationUndefined:
+ case TSensrvOrientationData::EOrientationDisplayUpwards:
+ case TSensrvOrientationData::EOrientationDisplayDownwards:
+ default:
+ break;
+ }
+
+ if (m_current != orientation && orientation != UnknownOrientation) {
+ m_current = orientation;
+ emit orientationChanged();
+ }
+ }
+ }
+ }
+
+ void DataError(CSensrvChannel& /* channel */, TSensrvErrorSeverity /* error */)
+ {
+ }
+
+ void GetDataListenerInterfaceL(TUid /* interfaceUid */, TAny*& /* interface */)
+ {
+ }
+};
+
+
+DeviceOrientation* DeviceOrientation::instance()
+{
+ static SymbianOrientation *o = 0;
+ if (!o)
+ o = new SymbianOrientation;
+ return o;
+}
+
+#include "deviceorientation_symbian.moc"
diff --git a/share/qtcreator/qml/qmlobserver/main.cpp b/share/qtcreator/qml/qmlobserver/main.cpp
index baa0fb948e..9b607e8191 100644
--- a/share/qtcreator/qml/qmlobserver/main.cpp
+++ b/share/qtcreator/qml/qmlobserver/main.cpp
@@ -49,6 +49,7 @@
#include <QTranslator>
#include <QDebug>
#include <QMessageBox>
+#include <QAtomicInt>
#include "qdeclarativetester.h"
#include "qt_private/qdeclarativedebughelper_p.h"
@@ -56,6 +57,9 @@ QT_USE_NAMESPACE
QtMsgHandler systemMsgOutput = 0;
+static QDeclarativeViewer *openFile(const QString &fileName);
+static void showViewer(QDeclarativeViewer *viewer);
+
#if defined (Q_OS_SYMBIAN)
#include <unistd.h>
#include <sys/types.h>
@@ -83,35 +87,50 @@ void myMessageOutput(QtMsgType type, const char *msg)
QWeakPointer<LoggerWidget> logger;
QString warnings;
-void showWarnings()
+void exitApp(int i)
{
+#ifdef Q_OS_WIN
+ // Debugging output is not visible by default on Windows -
+ // therefore show modal dialog with errors instead.
if (!warnings.isEmpty()) {
- int argc = 0; char **argv = 0;
- QApplication application(argc, argv); // QApplication() in main has been destroyed already.
- Q_UNUSED(application)
QMessageBox::warning(0, QApplication::tr("Qt QML Viewer"), warnings);
}
+#endif
+ exit(i);
}
+static QAtomicInt recursiveLock(0);
+
void myMessageOutput(QtMsgType type, const char *msg)
{
- if (!logger.isNull()) {
- QString strMsg = QString::fromAscii(msg);
- QMetaObject::invokeMethod(logger.data(), "append", Q_ARG(QString, strMsg));
- } else {
- warnings += msg;
- warnings += QLatin1Char('\n');
+ QString strMsg = QString::fromLatin1(msg);
+
+ if (!QCoreApplication::closingDown()) {
+ if (!logger.isNull()) {
+ if (recursiveLock.testAndSetOrdered(0, 1)) {
+ QMetaObject::invokeMethod(logger.data(), "append", Q_ARG(QString, strMsg));
+ recursiveLock = 0;
+ }
+ } else {
+ warnings += strMsg;
+ warnings += QLatin1Char('\n');
+ }
}
if (systemMsgOutput) { // Windows
systemMsgOutput(type, msg);
} else { // Unix
- fprintf(stderr, "%s\n",msg);
+ fprintf(stderr, "%s\n", msg);
fflush(stderr);
}
}
#endif
+static QDeclarativeViewer* globalViewer = 0;
+
+// The qml file that is shown if the user didn't specify a QML file
+QString initialFile = "qrc:/startup/startup.qml";
+
void usage()
{
qWarning("Usage: qmlobserver [options] <filename>");
@@ -143,7 +162,11 @@ void usage()
qWarning(" -I <directory> ........................... prepend to the module import search path,");
qWarning(" display path if <directory> is empty");
qWarning(" -P <directory> ........................... prepend to the plugin search path");
+#if defined(Q_WS_MAC)
+ qWarning(" -no-opengl ............................... don't use a QGLWidget for the viewport");
+#else
qWarning(" -opengl .................................. use a QGLWidget for the viewport");
+#endif
#ifndef NO_PRIVATE_HEADERS
qWarning(" -script <path> ........................... set the script to use");
qWarning(" -scriptopts <options>|help ............... set the script options to use");
@@ -151,7 +174,8 @@ void usage()
qWarning(" ");
qWarning(" Press F1 for interactive help");
- exit(1);
+
+ exitApp(1);
}
void scriptOptsUsage()
@@ -162,6 +186,7 @@ void scriptOptsUsage()
qWarning(" play ..................................... playback an existing script");
qWarning(" testimages ............................... record images or compare images on playback");
qWarning(" testerror ................................ test 'error' property of root item on playback");
+ qWarning(" testskip ................................ test 'skip' property of root item on playback");
qWarning(" snapshot ................................. file being recorded is static,");
qWarning(" only one frame will be recorded or tested");
qWarning(" exitoncomplete ........................... cleanly exit the viewer on script completion");
@@ -169,142 +194,213 @@ void scriptOptsUsage()
qWarning(" saveonexit ............................... save recording on viewer exit");
qWarning(" ");
qWarning(" One of record, play or both must be specified.");
- exit(1);
+
+ exitApp(1);
}
enum WarningsConfig { ShowWarnings, HideWarnings, DefaultWarnings };
-int main(int argc, char ** argv)
+struct ViewerOptions
{
-#if defined (Q_OS_SYMBIAN)
- qInstallMsgHandler(myMessageOutput);
-#else
- systemMsgOutput = qInstallMsgHandler(myMessageOutput);
+ ViewerOptions()
+ : frameless(false),
+ fps(0.0),
+ autorecord_from(0),
+ autorecord_to(0),
+ dither("none"),
+ runScript(false),
+ devkeys(false),
+ cache(0),
+ useGL(false),
+ fullScreen(false),
+ stayOnTop(false),
+ maximized(false),
+ useNativeFileBrowser(true),
+ experimentalGestures(false),
+ warningsConfig(DefaultWarnings),
+ sizeToView(true)
+ {
+#if defined(Q_OS_SYMBIAN)
+ maximized = true;
+ useNativeFileBrowser = false;
#endif
-#if defined (Q_OS_WIN)
- // Debugging output is not visible by default on Windows -
- // therefore show modal dialog with errors instead.
-
- // (Disabled in QmlObserver: We're usually running inside QtCreator anyway, see also QTCREATORBUG-2748)
-// atexit(showWarnings);
+#if defined(Q_WS_MAC)
+ useGL = true;
#endif
-
-#if defined (Q_WS_X11) || defined (Q_WS_MAC)
- //### default to using raster graphics backend for now
- bool gsSpecified = false;
- for (int i = 0; i < argc; ++i) {
- QString arg = argv[i];
- if (arg == "-graphicssystem") {
- gsSpecified = true;
- break;
- }
}
- if (!gsSpecified)
- QApplication::setGraphicsSystem("raster");
-#endif
-
- QApplication app(argc, argv);
- app.setApplicationName("QtQmlViewer");
- app.setOrganizationName("Nokia");
- app.setOrganizationDomain("nokia.com");
-
- QDeclarativeViewer::registerTypes();
- QDeclarativeTester::registerTypes();
-
- bool frameless = false;
- QString fileName;
- double fps = 0;
- int autorecord_from = 0;
- int autorecord_to = 0;
- QString dither = "none";
+ bool frameless;
+ double fps;
+ int autorecord_from;
+ int autorecord_to;
+ QString dither;
QString recordfile;
QStringList recordargs;
QStringList imports;
QStringList plugins;
QString script;
QString scriptopts;
- bool runScript = false;
- bool devkeys = false;
- int cache = 0;
+ bool runScript;
+ bool devkeys;
+ int cache;
QString translationFile;
- bool useGL = false;
- bool fullScreen = false;
- bool stayOnTop = false;
- bool maximized = false;
- bool useNativeFileBrowser = true;
- bool experimentalGestures = false;
- bool designModeBehavior = false;
- bool debuggerModeBehavior = false;
-
- WarningsConfig warningsConfig = DefaultWarnings;
- bool sizeToView = true;
+ bool useGL;
+ bool fullScreen;
+ bool stayOnTop;
+ bool maximized;
+ bool useNativeFileBrowser;
+ bool experimentalGestures;
-#if defined(Q_OS_SYMBIAN)
- maximized = true;
- useNativeFileBrowser = false;
-#endif
+ WarningsConfig warningsConfig;
+ bool sizeToView;
-#if defined(Q_WS_MAC)
- useGL = true;
-#endif
+ QDeclarativeViewer::ScriptOptions scriptOptions;
+};
- for (int i = 1; i < argc; ++i) {
- bool lastArg = (i == argc - 1);
- QString arg = argv[i];
+static ViewerOptions opts;
+static QStringList fileNames;
+
+class Application : public QApplication
+{
+ Q_OBJECT
+public:
+ Application(int &argc, char **&argv)
+ : QApplication(argc, argv)
+ {}
+
+protected:
+ bool event(QEvent *ev)
+ {
+ if (ev->type() != QEvent::FileOpen)
+ return QApplication::event(ev);
+
+ QFileOpenEvent *fev = static_cast<QFileOpenEvent *>(ev);
+
+ globalViewer->open(fev->file());
+ if (!globalViewer->isVisible())
+ showViewer(globalViewer);
+
+ return true;
+ }
+
+private Q_SLOTS:
+ void showInitialViewer()
+ {
+ QApplication::processEvents();
+
+ QDeclarativeViewer *viewer = globalViewer;
+ if (!viewer)
+ return;
+ if (viewer->currentFile().isEmpty()) {
+ if(opts.useNativeFileBrowser)
+ viewer->open(initialFile);
+ else
+ viewer->openFile();
+ }
+ if (!viewer->isVisible())
+ showViewer(viewer);
+ }
+};
+
+static void parseScriptOptions()
+{
+ QStringList options =
+ opts.scriptopts.split(QLatin1Char(','), QString::SkipEmptyParts);
+
+ QDeclarativeViewer::ScriptOptions scriptOptions = 0;
+ for (int i = 0; i < options.count(); ++i) {
+ const QString &option = options.at(i);
+ if (option == QLatin1String("help")) {
+ scriptOptsUsage();
+ } else if (option == QLatin1String("play")) {
+ scriptOptions |= QDeclarativeViewer::Play;
+ } else if (option == QLatin1String("record")) {
+ scriptOptions |= QDeclarativeViewer::Record;
+ } else if (option == QLatin1String("testimages")) {
+ scriptOptions |= QDeclarativeViewer::TestImages;
+ } else if (option == QLatin1String("testerror")) {
+ scriptOptions |= QDeclarativeViewer::TestErrorProperty;
+ } else if (option == QLatin1String("testskip")) {
+ scriptOptions |= QDeclarativeViewer::TestSkipProperty;
+ } else if (option == QLatin1String("exitoncomplete")) {
+ scriptOptions |= QDeclarativeViewer::ExitOnComplete;
+ } else if (option == QLatin1String("exitonfailure")) {
+ scriptOptions |= QDeclarativeViewer::ExitOnFailure;
+ } else if (option == QLatin1String("saveonexit")) {
+ scriptOptions |= QDeclarativeViewer::SaveOnExit;
+ } else if (option == QLatin1String("snapshot")) {
+ scriptOptions |= QDeclarativeViewer::Snapshot;
+ } else {
+ scriptOptsUsage();
+ }
+ }
+
+ opts.scriptOptions = scriptOptions;
+}
+
+static void parseCommandLineOptions(const QStringList &arguments)
+{
+ for (int i = 1; i < arguments.count(); ++i) {
+ bool lastArg = (i == arguments.count() - 1);
+ QString arg = arguments.at(i);
if (arg == "-frameless") {
- frameless = true;
+ opts.frameless = true;
} else if (arg == "-maximized") {
- maximized = true;
+ opts.maximized = true;
} else if (arg == "-fullscreen") {
- fullScreen = true;
+ opts.fullScreen = true;
} else if (arg == "-stayontop") {
- stayOnTop = true;
+ opts.stayOnTop = true;
} else if (arg == "-netcache") {
if (lastArg) usage();
- cache = QString(argv[++i]).toInt();
+ opts.cache = arguments.at(++i).toInt();
} else if (arg == "-recordrate") {
if (lastArg) usage();
- fps = QString(argv[++i]).toDouble();
+ opts.fps = arguments.at(++i).toDouble();
} else if (arg == "-recordfile") {
if (lastArg) usage();
- recordfile = QString(argv[++i]);
+ opts.recordfile = arguments.at(++i);
} else if (arg == "-record") {
if (lastArg) usage();
- recordargs << QString(argv[++i]);
+ opts.recordargs << arguments.at(++i);
} else if (arg == "-recorddither") {
if (lastArg) usage();
- dither = QString(argv[++i]);
+ opts.dither = arguments.at(++i);
} else if (arg == "-autorecord") {
if (lastArg) usage();
- QString range = QString(argv[++i]);
+ QString range = arguments.at(++i);
int dash = range.indexOf('-');
if (dash > 0)
- autorecord_from = range.left(dash).toInt();
- autorecord_to = range.mid(dash+1).toInt();
+ opts.autorecord_from = range.left(dash).toInt();
+ opts.autorecord_to = range.mid(dash+1).toInt();
} else if (arg == "-devicekeys") {
- devkeys = true;
+ opts.devkeys = true;
} else if (arg == "-dragthreshold") {
if (lastArg) usage();
- app.setStartDragDistance(QString(argv[++i]).toInt());
+ qApp->setStartDragDistance(arguments.at(++i).toInt());
} else if (arg == QLatin1String("-v") || arg == QLatin1String("-version")) {
qWarning("Qt QML Viewer version %s", QT_VERSION_STR);
- exit(0);
+ exitApp(0);
} else if (arg == "-translation") {
if (lastArg) usage();
- translationFile = argv[++i];
+ opts.translationFile = arguments.at(++i);
+#if defined(Q_WS_MAC)
+ } else if (arg == "-no-opengl") {
+ opts.useGL = false;
+#else
} else if (arg == "-opengl") {
- useGL = true;
+ opts.useGL = true;
+#endif
} else if (arg == "-qmlbrowser") {
- useNativeFileBrowser = false;
+ opts.useNativeFileBrowser = false;
} else if (arg == "-warnings") {
if (lastArg) usage();
- QString warningsStr = QString(argv[++i]);
+ QString warningsStr = arguments.at(++i);
if (warningsStr == QLatin1String("show")) {
- warningsConfig = ShowWarnings;
+ opts.warningsConfig = ShowWarnings;
} else if (warningsStr == QLatin1String("hide")) {
- warningsConfig = HideWarnings;
+ opts.warningsConfig = HideWarnings;
} else {
usage();
}
@@ -315,163 +411,201 @@ int main(int argc, char ** argv)
QDeclarativeEngine tmpEngine;
QString paths = tmpEngine.importPathList().join(QLatin1String(":"));
qWarning("Current search path: %s", paths.toLocal8Bit().constData());
- exit(0);
+ exitApp(0);
}
- imports << QString(argv[++i]);
+ opts.imports << arguments.at(++i);
} else if (arg == "-P") {
if (lastArg) usage();
- plugins << QString(argv[++i]);
+ opts.plugins << arguments.at(++i);
} else if (arg == "-script") {
if (lastArg) usage();
- script = QString(argv[++i]);
+ opts.script = arguments.at(++i);
} else if (arg == "-scriptopts") {
if (lastArg) usage();
- scriptopts = QString(argv[++i]);
+ opts.scriptopts = arguments.at(++i);
} else if (arg == "-savescript") {
if (lastArg) usage();
- script = QString(argv[++i]);
- runScript = false;
+ opts.script = arguments.at(++i);
+ opts.runScript = false;
} else if (arg == "-playscript") {
if (lastArg) usage();
- script = QString(argv[++i]);
- runScript = true;
+ opts.script = arguments.at(++i);
+ opts.runScript = true;
} else if (arg == "-sizeviewtorootobject") {
- sizeToView = false;
+ opts.sizeToView = false;
} else if (arg == "-sizerootobjecttoview") {
- sizeToView = true;
+ opts.sizeToView = true;
} else if (arg == "-experimentalgestures") {
- experimentalGestures = true;
- } else if (arg == "-designmode") {
- designModeBehavior = true;
- } else if (arg == "-debugger") {
- debuggerModeBehavior = true;
- } else if (arg[0] != '-') {
- fileName = arg;
- } else if (1 || arg == "-help") {
+ opts.experimentalGestures = true;
+ } else if (!arg.startsWith('-')) {
+ fileNames.append(arg);
+ } else if (true || arg == "-help") {
usage();
}
}
- QTranslator qmlTranslator;
- if (!translationFile.isEmpty()) {
- qmlTranslator.load(translationFile);
- app.installTranslator(&qmlTranslator);
+ if (!opts.scriptopts.isEmpty()) {
+
+ parseScriptOptions();
+
+ if (opts.script.isEmpty())
+ usage();
+
+ if (!(opts.scriptOptions & QDeclarativeViewer::Record) && !(opts.scriptOptions & QDeclarativeViewer::Play))
+ scriptOptsUsage();
+ } else if (!opts.script.isEmpty()) {
+ usage();
}
- Qt::WFlags wflags = (frameless ? Qt::FramelessWindowHint : Qt::Widget);
- if (stayOnTop)
- wflags |= Qt::WindowStaysOnTopHint;
+}
- // enable remote debugging
- QDeclarativeDebugHelper::enableDebugging();
+static QDeclarativeViewer *createViewer()
+{
+ Qt::WFlags wflags = (opts.frameless ? Qt::FramelessWindowHint : Qt::Widget);
+ if (opts.stayOnTop)
+ wflags |= Qt::WindowStaysOnTopHint;
QDeclarativeViewer *viewer = new QDeclarativeViewer(0, wflags);
viewer->setAttribute(Qt::WA_DeleteOnClose, true);
- if (!scriptopts.isEmpty()) {
- QStringList options =
- scriptopts.split(QLatin1Char(','), QString::SkipEmptyParts);
-
- QDeclarativeViewer::ScriptOptions scriptOptions = 0;
- for (int i = 0; i < options.count(); ++i) {
- const QString &option = options.at(i);
- if (option == QLatin1String("help")) {
- scriptOptsUsage();
- } else if (option == QLatin1String("play")) {
- scriptOptions |= QDeclarativeViewer::Play;
- } else if (option == QLatin1String("record")) {
- scriptOptions |= QDeclarativeViewer::Record;
- } else if (option == QLatin1String("testimages")) {
- scriptOptions |= QDeclarativeViewer::TestImages;
- } else if (option == QLatin1String("testerror")) {
- scriptOptions |= QDeclarativeViewer::TestErrorProperty;
- } else if (option == QLatin1String("exitoncomplete")) {
- scriptOptions |= QDeclarativeViewer::ExitOnComplete;
- } else if (option == QLatin1String("exitonfailure")) {
- scriptOptions |= QDeclarativeViewer::ExitOnFailure;
- } else if (option == QLatin1String("saveonexit")) {
- scriptOptions |= QDeclarativeViewer::SaveOnExit;
- } else if (option == QLatin1String("snapshot")) {
- scriptOptions |= QDeclarativeViewer::Snapshot;
- } else {
- scriptOptsUsage();
- }
- }
-
- if (script.isEmpty())
- usage();
+ viewer->setUseGL(opts.useGL);
- if (!(scriptOptions & QDeclarativeViewer::Record) && !(scriptOptions & QDeclarativeViewer::Play))
- scriptOptsUsage();
- viewer->setScriptOptions(scriptOptions);
- viewer->setScript(script);
- } else if (!script.isEmpty()) {
- usage();
+ if (!opts.scriptopts.isEmpty()) {
+ viewer->setScriptOptions(opts.scriptOptions);
+ viewer->setScript(opts.script);
}
#if !defined(Q_OS_SYMBIAN)
logger = viewer->warningsWidget();
- if (warningsConfig == ShowWarnings) {
+ if (opts.warningsConfig == ShowWarnings) {
logger.data()->setDefaultVisibility(LoggerWidget::ShowWarnings);
logger.data()->show();
- } else if (warningsConfig == HideWarnings){
+ } else if (opts.warningsConfig == HideWarnings){
logger.data()->setDefaultVisibility(LoggerWidget::HideWarnings);
}
#endif
- if (experimentalGestures)
+ if (opts.experimentalGestures)
viewer->enableExperimentalGestures();
- viewer->setDesignModeBehavior(designModeBehavior);
-
- foreach (QString lib, imports)
+ foreach (QString lib, opts.imports)
viewer->addLibraryPath(lib);
- foreach (QString plugin, plugins)
+ foreach (QString plugin, opts.plugins)
viewer->addPluginPath(plugin);
- viewer->setNetworkCacheSize(cache);
- viewer->setRecordFile(recordfile);
- viewer->setSizeToView(sizeToView);
- if (fps>0)
- viewer->setRecordRate(fps);
- if (autorecord_to)
- viewer->setAutoRecord(autorecord_from,autorecord_to);
- if (devkeys)
+ viewer->setNetworkCacheSize(opts.cache);
+ viewer->setRecordFile(opts.recordfile);
+ viewer->setSizeToView(opts.sizeToView);
+ if (opts.fps > 0)
+ viewer->setRecordRate(opts.fps);
+ if (opts.autorecord_to)
+ viewer->setAutoRecord(opts.autorecord_from, opts.autorecord_to);
+ if (opts.devkeys)
viewer->setDeviceKeys(true);
- viewer->setRecordDither(dither);
- if (recordargs.count())
- viewer->setRecordArgs(recordargs);
+ viewer->setRecordDither(opts.dither);
+ if (opts.recordargs.count())
+ viewer->setRecordArgs(opts.recordargs);
+
+ viewer->setUseNativeFileBrowser(opts.useNativeFileBrowser);
+
+ return viewer;
+}
+
+void showViewer(QDeclarativeViewer *viewer)
+{
+ if (opts.fullScreen)
+ viewer->showFullScreen();
+ else if (opts.maximized)
+ viewer->showMaximized();
+ else
+ viewer->show();
+ viewer->raise();
+}
+
+QDeclarativeViewer *openFile(const QString &fileName)
+{
+ QDeclarativeViewer *viewer = globalViewer;
+
+ viewer->open(fileName);
+ showViewer(viewer);
+
+ return viewer;
+}
+
+int main(int argc, char ** argv)
+{
+#if defined (Q_OS_SYMBIAN)
+ qInstallMsgHandler(myMessageOutput);
+#else
+ systemMsgOutput = qInstallMsgHandler(myMessageOutput);
+#endif
+
+#if defined (Q_WS_X11) || defined (Q_WS_MAC)
+ //### default to using raster graphics backend for now
+ bool gsSpecified = false;
+ for (int i = 0; i < argc; ++i) {
+ QString arg = argv[i];
+ if (arg == "-graphicssystem") {
+ gsSpecified = true;
+ break;
+ }
+ }
+
+ if (!gsSpecified)
+ QApplication::setGraphicsSystem("raster");
+#endif
+
+ Application app(argc, argv);
+ app.setApplicationName("QtQmlViewer");
+ app.setOrganizationName("Nokia");
+ app.setOrganizationDomain("nokia.com");
+
+ QDeclarativeViewer::registerTypes();
+ QDeclarativeTester::registerTypes();
+
+ parseCommandLineOptions(app.arguments());
- viewer->setUseNativeFileBrowser(useNativeFileBrowser);
- if (fullScreen && maximized)
+ QTranslator qmlTranslator;
+ if (!opts.translationFile.isEmpty()) {
+ qmlTranslator.load(opts.translationFile);
+ app.installTranslator(&qmlTranslator);
+ }
+
+ if (opts.fullScreen && opts.maximized)
qWarning() << "Both -fullscreen and -maximized specified. Using -fullscreen.";
- if (fileName.isEmpty()) {
+ if (fileNames.isEmpty()) {
QFile qmlapp(QLatin1String("qmlapp"));
if (qmlapp.exists() && qmlapp.open(QFile::ReadOnly)) {
- QString content = QString::fromUtf8(qmlapp.readAll());
- qmlapp.close();
-
- int newline = content.indexOf(QLatin1Char('\n'));
- if (newline >= 0)
- fileName = content.left(newline);
- else
- fileName = content;
- }
+ QString content = QString::fromUtf8(qmlapp.readAll());
+ qmlapp.close();
+
+ int newline = content.indexOf(QLatin1Char('\n'));
+ if (newline >= 0)
+ fileNames += content.left(newline);
+ else
+ fileNames += content;
+ }
}
- if (!fileName.isEmpty()) {
- viewer->open(fileName);
- fullScreen ? viewer->showFullScreen() : maximized ? viewer->showMaximized() : viewer->show();
+ //enable remote debugging
+ QDeclarativeDebugHelper::enableDebugging();
+
+ globalViewer = createViewer();
+
+ if (fileNames.isEmpty()) {
+ // show the initial viewer delayed.
+ // This prevents an initial viewer popping up while there
+ // are FileOpen events coming through the event queue
+ QTimer::singleShot(1, &app, SLOT(showInitialViewer()));
} else {
- if (!useNativeFileBrowser)
- viewer->openFile();
- fullScreen ? viewer->showFullScreen() : maximized ? viewer->showMaximized() : viewer->show();
- if (useNativeFileBrowser)
- viewer->openFile();
+ foreach (const QString &fileName, fileNames)
+ openFile(fileName);
}
- viewer->setUseGL(useGL);
- viewer->raise();
+
+ QObject::connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit()));
return app.exec();
}
+
+#include "main.moc"
diff --git a/share/qtcreator/qml/qmlobserver/qdeclarativetester.cpp b/share/qtcreator/qml/qmlobserver/qdeclarativetester.cpp
index 83e8c06018..c736879a36 100644
--- a/share/qtcreator/qml/qmlobserver/qdeclarativetester.cpp
+++ b/share/qtcreator/qml/qmlobserver/qdeclarativetester.cpp
@@ -48,7 +48,6 @@
#include <QDir>
#include <QCryptographicHash>
#include <QGraphicsObject>
-
#ifndef NO_PRIVATE_HEADERS
#include <private/qabstractanimation_p.h>
#include <private/qdeclarativeitem_p.h>
@@ -56,6 +55,7 @@
QT_BEGIN_NAMESPACE
+extern Q_GUI_EXPORT bool qt_applefontsmoothing_enabled;
QDeclarativeTester::QDeclarativeTester(const QString &script, QDeclarativeViewer::ScriptOptions opts,
QDeclarativeView *parent)
@@ -67,6 +67,12 @@ QDeclarativeTester::QDeclarativeTester(const QString &script, QDeclarativeViewer
#ifndef NO_PRIVATE_HEADERS
QUnifiedTimer::instance()->setConsistentTiming(true);
#endif
+
+ //Font antialiasing makes tests system-specific, so disable it
+ QFont noAA = QApplication::font();
+ noAA.setStyleStrategy(QFont::NoAntialias);
+ QApplication::setFont(noAA);
+
if (options & QDeclarativeViewer::Play)
this->run();
start();
@@ -75,7 +81,7 @@ QDeclarativeTester::QDeclarativeTester(const QString &script, QDeclarativeViewer
QDeclarativeTester::~QDeclarativeTester()
{
if (!hasFailed &&
- options & QDeclarativeViewer::Record &&
+ options & QDeclarativeViewer::Record &&
options & QDeclarativeViewer::SaveOnExit)
save();
}
@@ -142,8 +148,25 @@ void QDeclarativeTester::imagefailure()
{
hasFailed = true;
- if (options & QDeclarativeViewer::ExitOnFailure)
- exit(-1);
+ if (options & QDeclarativeViewer::ExitOnFailure){
+ testSkip();
+ exit(hasFailed?-1:0);
+ }
+}
+
+void QDeclarativeTester::testSkip()
+{
+ if (options & QDeclarativeViewer::TestSkipProperty){
+ QString e = m_view->rootObject()->property("skip").toString();
+ if (!e.isEmpty()) {
+ if(hasFailed){
+ qWarning() << "Test failed, but skipping it: " << e;
+ }else{
+ qWarning() << "Test skipped: " << e;
+ }
+ hasFailed = 0;
+ }
+ }
}
void QDeclarativeTester::complete()
@@ -155,7 +178,10 @@ void QDeclarativeTester::complete()
hasFailed = true;
}
}
- if (options & QDeclarativeViewer::ExitOnComplete)
+
+
+ testSkip();
+ if (options & QDeclarativeViewer::ExitOnComplete)
QApplication::exit(hasFailed?-1:0);
if (hasCompleted)
@@ -207,7 +233,7 @@ void QDeclarativeTester::save()
}
ts << " }\n";
- while (!mouseevents.isEmpty() &&
+ while (!mouseevents.isEmpty() &&
mouseevents.first().msec == fe.msec) {
MouseEvent me = mouseevents.takeFirst();
@@ -255,7 +281,16 @@ void QDeclarativeTester::updateCurrentTime(int msec)
if (options & QDeclarativeViewer::TestImages) {
img.fill(qRgb(255,255,255));
+
+#ifdef Q_WS_MAC
+ bool oldSmooth = qt_applefontsmoothing_enabled;
+ qt_applefontsmoothing_enabled = false;
+#endif
QPainter p(&img);
+#ifdef Q_WS_MAC
+ qt_applefontsmoothing_enabled = oldSmooth;
+#endif
+
m_view->render(&p);
}
@@ -266,7 +301,7 @@ void QDeclarativeTester::updateCurrentTime(int msec)
fe.msec = msec;
if (msec == 0 || !(options & QDeclarativeViewer::TestImages)) {
// Skip first frame, skip if not doing images
- } else if (0 == (m_savedFrameEvents.count() % 60) || snapshot) {
+ } else if (0 == ((m_savedFrameEvents.count()-1) % 60) || snapshot) {
fe.image = img;
} else {
QCryptographicHash hash(QCryptographicHash::Md5);
@@ -317,14 +352,14 @@ void QDeclarativeTester::updateCurrentTime(int msec)
if (QDeclarativeVisualTestFrame *frame = qobject_cast<QDeclarativeVisualTestFrame *>(event)) {
if (frame->msec() < msec) {
if (options & QDeclarativeViewer::TestImages && !(options & QDeclarativeViewer::Record)) {
- qWarning() << "QDeclarativeTester: Extra frame. Seen:"
+ qWarning() << "QDeclarativeTester(" << m_script << "): Extra frame. Seen:"
<< msec << "Expected:" << frame->msec();
imagefailure();
}
} else if (frame->msec() == msec) {
if (!frame->hash().isEmpty() && frame->hash().toUtf8() != fe.hash.toHex()) {
if (options & QDeclarativeViewer::TestImages && !(options & QDeclarativeViewer::Record)) {
- qWarning() << "QDeclarativeTester: Mismatched frame hash at" << msec
+ qWarning() << "QDeclarativeTester(" << m_script << "): Mismatched frame hash at" << msec
<< ". Seen:" << fe.hash.toHex()
<< "Expected:" << frame->hash().toUtf8();
imagefailure();
@@ -336,9 +371,14 @@ void QDeclarativeTester::updateCurrentTime(int msec)
if (options & QDeclarativeViewer::TestImages && !(options & QDeclarativeViewer::Record) && !frame->image().isEmpty()) {
QImage goodImage(frame->image().toLocalFile());
+ if (frame->msec() == 16 && goodImage.size() != img.size()){
+ //Also an image mismatch, but this warning is more informative. Only checked at start though.
+ qWarning() << "QDeclarativeTester(" << m_script << "): Size mismatch. This test must be run at " << goodImage.size();
+ imagefailure();
+ }
if (goodImage != img) {
QString reject(frame->image().toLocalFile() + ".reject.png");
- qWarning() << "QDeclarativeTester: Image mismatch. Reject saved to:"
+ qWarning() << "QDeclarativeTester(" << m_script << "): Image mismatch. Reject saved to:"
<< reject;
img.save(reject);
bool doDiff = (goodImage.size() == img.size());
@@ -391,7 +431,7 @@ void QDeclarativeTester::updateCurrentTime(int msec)
ke.destination = ViewPort;
}
m_savedKeyEvents.append(ke);
- }
+ }
testscriptidx++;
}
diff --git a/share/qtcreator/qml/qmlobserver/qdeclarativetester.h b/share/qtcreator/qml/qmlobserver/qdeclarativetester.h
index 021869d93a..6fdf495c1f 100644
--- a/share/qtcreator/qml/qmlobserver/qdeclarativetester.h
+++ b/share/qtcreator/qml/qmlobserver/qdeclarativetester.h
@@ -122,7 +122,7 @@ public:
int type() const { return m_type; }
void setType(int t) { m_type = t; }
-
+
int button() const { return m_button; }
void setButton(int b) { m_button = b; }
@@ -228,6 +228,7 @@ private:
void imagefailure();
void complete();
+ void testSkip();
enum Destination { View, ViewPort };
void addKeyEvent(Destination, QKeyEvent *);
@@ -236,7 +237,7 @@ private:
struct MouseEvent {
MouseEvent(QMouseEvent *e)
- : type(e->type()), button(e->button()), buttons(e->buttons()),
+ : type(e->type()), button(e->button()), buttons(e->buttons()),
pos(e->pos()), modifiers(e->modifiers()), destination(View) {}
QEvent::Type type;
diff --git a/share/qtcreator/qml/qmlobserver/qml.pri b/share/qtcreator/qml/qmlobserver/qml.pri
index 7e485d3984..5db7678081 100644
--- a/share/qtcreator/qml/qmlobserver/qml.pri
+++ b/share/qtcreator/qml/qmlobserver/qml.pri
@@ -1,14 +1,9 @@
QT += declarative script network sql
-
contains(QT_CONFIG, opengl) {
QT += opengl
DEFINES += GL_SUPPORTED
}
-!exists($$[QT_INSTALL_HEADERS]/QtCore/private/qabstractanimation_p.h) {
- DEFINES += NO_PRIVATE_HEADERS
-}
-
INCLUDEPATH += $$PWD
HEADERS += $$PWD/qmlruntime.h \
@@ -16,25 +11,31 @@ HEADERS += $$PWD/qmlruntime.h \
$$PWD/qdeclarativetester.h \
$$PWD/deviceorientation.h \
$$PWD/loggerwidget.h
-
-
SOURCES += $$PWD/qmlruntime.cpp \
$$PWD/proxysettings.cpp \
$$PWD/qdeclarativetester.cpp \
$$PWD/loggerwidget.cpp
-RESOURCES += $$PWD/qmlruntime.qrc
-
-OTHER_FILES += toolbarstyle.css
+RESOURCES = $$PWD/browser/browser.qrc \
+ $$PWD/startup/startup.qrc
-maemo5 {
+symbian:!contains(S60_VERSION, 3.1):!contains(S60_VERSION, 3.2) {
+ SOURCES += $$PWD/deviceorientation_symbian.cpp
+ FORMS = $$PWD/recopts.ui \
+ $$PWD/proxysettings.ui
+} else:maemo5 {
QT += dbus
HEADERS += $$PWD/texteditautoresizer_maemo5.h
SOURCES += $$PWD/deviceorientation_maemo5.cpp
- FORMS += $$PWD/recopts_maemo5.ui \
+ FORMS = $$PWD/recopts_maemo5.ui \
$$PWD/proxysettings_maemo5.ui
+} else:linux-g++-maemo {
+ QT += dbus
+ SOURCES += $$PWD/deviceorientation_harmattan.cpp
+ FORMS = $$PWD/recopts.ui \
+ $$PWD/proxysettings.ui
} else {
SOURCES += $$PWD/deviceorientation.cpp
- FORMS += $$PWD/recopts.ui \
- $$PWD/proxysettings.ui
+ FORMS = $$PWD/recopts.ui \
+ $$PWD/proxysettings.ui
}
diff --git a/share/qtcreator/qml/qmlobserver/qmlobserver.pro b/share/qtcreator/qml/qmlobserver/qmlobserver.pro
index 379ca5fb04..5e09ed1875 100644
--- a/share/qtcreator/qml/qmlobserver/qmlobserver.pro
+++ b/share/qtcreator/qml/qmlobserver/qmlobserver.pro
@@ -1,5 +1,7 @@
TEMPLATE = app
+CONFIG += qt uic
+
### FIXME: only debug plugins are now supported.
CONFIG -= release
CONFIG += debug
@@ -15,6 +17,44 @@ exists($$PWD/qmljsdebugger/qmljsdebugger-lib.pri) {
include($$PWD/../qmljsdebugger/qmljsdebugger-lib.pri)
}
+#INCLUDEPATH += ../../include/QtDeclarative
+#INCLUDEPATH += ../../src/declarative/util
+#INCLUDEPATH += ../../src/declarative/graphicsitems
+
+target.path = $$[QT_INSTALL_BINS]
+INSTALLS += target
+
+wince* {
+ QT += xml
+
+ contains(QT_CONFIG, scripttools) {
+ QT += scripttools
+ }
+ contains(QT_CONFIG, phonon) {
+ QT += phonon
+ }
+ contains(QT_CONFIG, xmlpatterns) {
+ QT += xmlpatterns
+ }
+ contains(QT_CONFIG, webkit) {
+ QT += webkit
+ }
+}
+maemo5 {
+ QT += maemo5
+}
+symbian {
+ TARGET.UID3 = 0x20021317
+ include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri)
+ TARGET.EPOCHEAPSIZE = 0x20000 0x4000000
+ TARGET.CAPABILITY = NetworkServices ReadUserData
+ !contains(S60_VERSION, 3.1):!contains(S60_VERSION, 3.2) {
+ LIBS += -lsensrvclient -lsensrvutil
+ }
+ contains(QT_CONFIG, s60): {
+ LIBS += -lavkon -lcone
+ }
+}
mac {
QMAKE_INFO_PLIST=Info_mac.plist
TARGET=QMLObserver
@@ -22,4 +62,3 @@ mac {
} else {
TARGET=qmlobserver
}
-
diff --git a/share/qtcreator/qml/qmlobserver/qmlruntime.cpp b/share/qtcreator/qml/qmlobserver/qmlruntime.cpp
index d35c18d4a9..339ec38a43 100644
--- a/share/qtcreator/qml/qmlobserver/qmlruntime.cpp
+++ b/share/qtcreator/qml/qmlobserver/qmlruntime.cpp
@@ -54,9 +54,6 @@
# include "ui_recopts.h"
#endif
-#include <qdeclarativeviewobserver.h>
-#include <qdeclarativeobserverservice.h>
-
#include "qmlruntime.h"
#include <qdeclarativecontext.h>
#include <qdeclarativeengine.h>
@@ -67,6 +64,9 @@
#include <private/qabstractanimation_p.h>
#endif
+#include <qdeclarativeviewobserver.h>
+#include <qdeclarativeobserverservice.h>
+
#include <QSettings>
#include <QXmlStreamReader>
#include <QBuffer>
@@ -90,28 +90,74 @@
#include <QMenu>
#include <QAction>
#include <QFileDialog>
+#include <QInputDialog>
#include <QTimer>
#include <QGraphicsObject>
#include <QNetworkProxyFactory>
#include <QKeyEvent>
-#include <QToolBar>
#include <QMutex>
#include <QMutexLocker>
#include "proxysettings.h"
#include "deviceorientation.h"
-#include <QInputDialog>
#ifdef GL_SUPPORTED
#include <QGLWidget>
#endif
-#include <qt_private/qdeclarativedebughelper_p.h>
+#if defined(Q_WS_S60)
+#include <aknappui.h> // For locking app orientation
+#endif
#include <qdeclarativetester.h>
+
+#include <qt_private/qdeclarativedebughelper_p.h>
#include "jsdebuggeragent.h"
QT_BEGIN_NAMESPACE
+class DragAndDropView : public QDeclarativeView
+{
+ Q_OBJECT
+public:
+ DragAndDropView(QDeclarativeViewer *parent = 0)
+ : QDeclarativeView(parent)
+ {
+ setAcceptDrops(true);
+ }
+
+ void dragEnterEvent(QDragEnterEvent *event)
+ {
+ const QMimeData *mimeData = event->mimeData();
+ if (mimeData->hasUrls())
+ event->acceptProposedAction();
+ }
+
+ void dragMoveEvent(QDragMoveEvent *event)
+ {
+ event->acceptProposedAction();
+ }
+
+ void dragLeaveEvent(QDragLeaveEvent *event)
+ {
+ event->accept();
+ }
+
+ void dropEvent(QDropEvent *event)
+ {
+ const QMimeData *mimeData = event->mimeData();
+ if (!mimeData->hasUrls())
+ return;
+ const QList<QUrl> urlList = mimeData->urls();
+ foreach (const QUrl &url, urlList) {
+ if (url.scheme() == QLatin1String("file")) {
+ static_cast<QDeclarativeViewer *>(parent())->open(url.toLocalFile());
+ event->accept();
+ return;
+ }
+ }
+ }
+};
+
class Runtime : public QObject
{
Q_OBJECT
@@ -166,38 +212,38 @@ public:
QWidget *createWidget(QWidget *parent)
{
- QMaemo5ValueButton *button = new QMaemo5ValueButton(m_text, parent);
- button->setValueLayout(QMaemo5ValueButton::ValueUnderTextCentered);
+ QMaemo5ValueButton *button = new QMaemo5ValueButton(m_text, parent);
+ button->setValueLayout(QMaemo5ValueButton::ValueUnderTextCentered);
QMaemo5ListPickSelector *pick = new QMaemo5ListPickSelector(button);
- button->setPickSelector(pick);
- if (m_actions) {
- QStringList sl;
- int curIdx = -1, idx = 0;
- foreach (QAction *a, m_actions->actions()) {
- sl << a->text();
- if (a->isChecked())
- curIdx = idx;
- idx++;
+ button->setPickSelector(pick);
+ if (m_actions) {
+ QStringList sl;
+ int curIdx = -1, idx = 0;
+ foreach (QAction *a, m_actions->actions()) {
+ sl << a->text();
+ if (a->isChecked())
+ curIdx = idx;
+ idx++;
}
- pick->setModel(new QStringListModel(sl));
- pick->setCurrentIndex(curIdx);
- } else {
- button->setEnabled(false);
- }
- connect(pick, SIGNAL(selected(QString)), this, SLOT(emitTriggered()));
- return button;
+ pick->setModel(new QStringListModel(sl));
+ pick->setCurrentIndex(curIdx);
+ } else {
+ button->setEnabled(false);
+ }
+ connect(pick, SIGNAL(selected(QString)), this, SLOT(emitTriggered()));
+ return button;
}
private slots:
void emitTriggered()
{
- QMaemo5ListPickSelector *pick = qobject_cast<QMaemo5ListPickSelector *>(sender());
- if (!pick)
- return;
- int idx = pick->currentIndex();
+ QMaemo5ListPickSelector *pick = qobject_cast<QMaemo5ListPickSelector *>(sender());
+ if (!pick)
+ return;
+ int idx = pick->currentIndex();
- if (m_actions && idx >= 0 && idx < m_actions->actions().count())
- m_actions->actions().at(idx)->trigger();
+ if (m_actions && idx >= 0 && idx < m_actions->actions().count())
+ m_actions->actions().at(idx)->trigger();
}
private:
@@ -441,65 +487,82 @@ private:
mutable QMutex mutex;
};
-class NetworkAccessManagerFactory : public QDeclarativeNetworkAccessManagerFactory
+class SystemProxyFactory : public QNetworkProxyFactory
{
public:
- NetworkAccessManagerFactory() : cacheSize(0) {}
- ~NetworkAccessManagerFactory() {}
-
- QNetworkAccessManager *create(QObject *parent);
+ SystemProxyFactory() : proxyDirty(true), httpProxyInUse(false) {
+ }
- void setupProxy(QNetworkAccessManager *nam)
+ virtual QList<QNetworkProxy> queryProxy(const QNetworkProxyQuery &query)
{
- class SystemProxyFactory : public QNetworkProxyFactory
- {
- public:
- virtual QList<QNetworkProxy> queryProxy(const QNetworkProxyQuery &query)
- {
- QString protocolTag = query.protocolTag();
- if (httpProxyInUse && (protocolTag == "http" || protocolTag == "https")) {
- QList<QNetworkProxy> ret;
- ret << httpProxy;
- return ret;
- }
+ if (proxyDirty)
+ setupProxy();
+ QString protocolTag = query.protocolTag();
+ if (httpProxyInUse && (protocolTag == "http" || protocolTag == "https")) {
+ QList<QNetworkProxy> ret;
+ ret << httpProxy;
+ return ret;
+ }
#ifdef Q_OS_WIN
- // systemProxyForQuery can take insanely long on Windows (QTBUG-10106)
- return QNetworkProxyFactory::proxyForQuery(query);
+ // systemProxyForQuery can take insanely long on Windows (QTBUG-10106)
+ return QNetworkProxyFactory::proxyForQuery(query);
#else
- return QNetworkProxyFactory::systemProxyForQuery(query);
+ return QNetworkProxyFactory::systemProxyForQuery(query);
#endif
- }
- void setHttpProxy (QNetworkProxy proxy)
- {
- httpProxy = proxy;
- httpProxyInUse = true;
- }
- void unsetHttpProxy ()
- {
- httpProxyInUse = false;
- }
- private:
- bool httpProxyInUse;
- QNetworkProxy httpProxy;
- };
-
- SystemProxyFactory *proxyFactory = new SystemProxyFactory;
- if (ProxySettings::httpProxyInUse())
- proxyFactory->setHttpProxy(ProxySettings::httpProxy());
- else
- proxyFactory->unsetHttpProxy();
- nam->setProxyFactory(proxyFactory);
}
+ void setupProxy() {
+ // Don't bother locking because we know that the proxy only
+ // changes in response to the settings dialog and that
+ // the view will be reloaded.
+ proxyDirty = false;
+ httpProxyInUse = ProxySettings::httpProxyInUse();
+ if (httpProxyInUse)
+ httpProxy = ProxySettings::httpProxy();
+ }
+
+ void proxyChanged() {
+ proxyDirty = true;
+ }
+
+private:
+ volatile bool proxyDirty;
+ bool httpProxyInUse;
+ QNetworkProxy httpProxy;
+};
+
+class NetworkAccessManagerFactory : public QObject, public QDeclarativeNetworkAccessManagerFactory
+{
+ Q_OBJECT
+public:
+ NetworkAccessManagerFactory() : cacheSize(0) {}
+ ~NetworkAccessManagerFactory() {}
+
+ QNetworkAccessManager *create(QObject *parent);
+
void setCacheSize(int size) {
if (size != cacheSize) {
cacheSize = size;
}
}
+ void proxyChanged() {
+ foreach (QNetworkAccessManager *nam, namList) {
+ static_cast<SystemProxyFactory*>(nam->proxyFactory())->proxyChanged();
+ }
+ }
+
static PersistentCookieJar *cookieJar;
+
+private slots:
+ void managerDestroyed(QObject *obj) {
+ namList.removeOne(static_cast<QNetworkAccessManager*>(obj));
+ }
+
+private:
QMutex mutex;
int cacheSize;
+ QList<QNetworkAccessManager*> namList;
};
PersistentCookieJar *NetworkAccessManagerFactory::cookieJar = 0;
@@ -520,7 +583,7 @@ QNetworkAccessManager *NetworkAccessManagerFactory::create(QObject *parent)
}
manager->setCookieJar(cookieJar);
cookieJar->setParent(0);
- setupProxy(manager);
+ manager->setProxyFactory(new SystemProxyFactory);
if (cacheSize > 0) {
QNetworkDiskCache *cache = new QNetworkDiskCache;
cache->setCacheDirectory(QDir::tempPath()+QLatin1String("/qml-viewer-network-cache"));
@@ -529,6 +592,8 @@ QNetworkAccessManager *NetworkAccessManagerFactory::create(QObject *parent)
} else {
manager->setCache(0);
}
+ connect(manager, SIGNAL(destroyed(QObject*)), this, SLOT(managerDestroyed(QObject*)));
+ namList.append(manager);
qDebug() << "created new network access manager for" << parent;
return manager;
}
@@ -548,13 +613,13 @@ QDeclarativeViewer::QDeclarativeViewer(QWidget *parent, Qt::WindowFlags flags)
: QMainWindow(parent, flags)
, loggerWindow(new LoggerWidget(this))
, frame_stream(0)
+ , rotateAction(0)
, orientation(0)
, showWarningsWindow(0)
, designModeBehaviorAction(0)
, m_scriptOptions(0)
, tester(0)
, useQmlFileBrowser(true)
- , m_centralWidget(0)
, translator(0)
{
QDeclarativeViewer::registerTypes();
@@ -589,28 +654,18 @@ QDeclarativeViewer::QDeclarativeViewer(QWidget *parent, Qt::WindowFlags flags)
recdlg->warning->hide();
}
- canvas = new QDeclarativeView(this);
+ canvas = new DragAndDropView(this);
observer = new QmlJSDebugger::QDeclarativeViewObserver(canvas, this);
new QmlJSDebugger::JSDebuggerAgent(canvas->engine());
- m_centralWidget = new QWidget(this);
- QVBoxLayout *layout = new QVBoxLayout(m_centralWidget);
- layout->setMargin(0);
- layout->setSpacing(0);
-
-
- layout->addWidget(canvas);
- m_centralWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
-
canvas->setAttribute(Qt::WA_OpaquePaintEvent);
canvas->setAttribute(Qt::WA_NoSystemBackground);
canvas->setFocus();
- QObject::connect(observer, SIGNAL(reloadRequested()), this, SLOT(reload()));
QObject::connect(canvas, SIGNAL(sceneResized(QSize)), this, SLOT(sceneResized(QSize)));
QObject::connect(canvas, SIGNAL(statusChanged(QDeclarativeView::Status)), this, SLOT(statusChanged()));
- QObject::connect(canvas->engine(), SIGNAL(quit()), QCoreApplication::instance (), SLOT(quit()));
+ QObject::connect(canvas->engine(), SIGNAL(quit()), this, SLOT(close()));
QObject::connect(warningsWidget(), SIGNAL(opened()), this, SLOT(warningsWidgetOpened()));
QObject::connect(warningsWidget(), SIGNAL(closed()), this, SLOT(warningsWidgetClosed()));
@@ -622,7 +677,7 @@ QDeclarativeViewer::QDeclarativeViewer(QWidget *parent, Qt::WindowFlags flags)
setMenuBar(0);
}
- setCentralWidget(m_centralWidget);
+ setCentralWidget(canvas);
namFactory = new NetworkAccessManagerFactory;
canvas->engine()->setNetworkAccessManagerFactory(namFactory);
@@ -655,12 +710,14 @@ void QDeclarativeViewer::setDesignModeBehavior(bool value)
void QDeclarativeViewer::enableExperimentalGestures()
{
+#ifndef QT_NO_GESTURES
canvas->viewport()->grabGesture(Qt::TapGesture,Qt::DontStartGestureOnChildren|Qt::ReceivePartialGestures|Qt::IgnoredGesturesPropagateToParent);
canvas->viewport()->grabGesture(Qt::TapAndHoldGesture,Qt::DontStartGestureOnChildren|Qt::ReceivePartialGestures|Qt::IgnoredGesturesPropagateToParent);
canvas->viewport()->grabGesture(Qt::PanGesture,Qt::DontStartGestureOnChildren|Qt::ReceivePartialGestures|Qt::IgnoredGesturesPropagateToParent);
canvas->viewport()->grabGesture(Qt::PinchGesture,Qt::DontStartGestureOnChildren|Qt::ReceivePartialGestures|Qt::IgnoredGesturesPropagateToParent);
canvas->viewport()->grabGesture(Qt::SwipeGesture,Qt::DontStartGestureOnChildren|Qt::ReceivePartialGestures|Qt::IgnoredGesturesPropagateToParent);
canvas->viewport()->setAttribute(Qt::WA_AcceptTouchEvents);
+#endif
}
QDeclarativeView *QDeclarativeViewer::view() const
@@ -676,11 +733,14 @@ LoggerWidget *QDeclarativeViewer::warningsWidget() const
void QDeclarativeViewer::createMenu()
{
QAction *openAction = new QAction(tr("&Open..."), this);
- openAction->setShortcut(QKeySequence("Ctrl+O"));
+ openAction->setShortcuts(QKeySequence::Open);
connect(openAction, SIGNAL(triggered()), this, SLOT(openFile()));
+ QAction *openUrlAction = new QAction(tr("Open &URL..."), this);
+ connect(openUrlAction, SIGNAL(triggered()), this, SLOT(openUrl()));
+
QAction *reloadAction = new QAction(tr("&Reload"), this);
- reloadAction->setShortcut(QKeySequence("Ctrl+R"));
+ reloadAction->setShortcuts(QKeySequence::Refresh);
connect(reloadAction, SIGNAL(triggered()), this, SLOT(reload()));
QAction *snapshotAction = new QAction(tr("&Take Snapshot"), this);
@@ -690,9 +750,6 @@ void QDeclarativeViewer::createMenu()
recordAction = new QAction(tr("Start Recording &Video"), this);
recordAction->setShortcut(QKeySequence("F9"));
connect(recordAction, SIGNAL(triggered()), this, SLOT(toggleRecordingWithSelection()));
-#ifdef NO_PRIVATE_HEADERS
- recordAction->setEnabled(false);
-#endif
QAction *recordOptions = new QAction(tr("Video &Options..."), this);
connect(recordOptions, SIGNAL(triggered()), this, SLOT(chooseRecordingOptions()));
@@ -715,6 +772,7 @@ void QDeclarativeViewer::createMenu()
speedAction = playSpeedMenu->addAction(tr("0.25x"), this, SLOT(changeAnimationSpeed()));
speedAction->setCheckable(true);
+ speedAction->setCheckable(true);
speedAction->setData(4.0f);
playSpeedMenuActions->addAction(speedAction);
@@ -753,7 +811,15 @@ void QDeclarativeViewer::createMenu()
designModeBehaviorAction->setEnabled(QmlJSDebugger::QDeclarativeObserverService::hasDebuggingClient());
connect(designModeBehaviorAction, SIGNAL(triggered(bool)), this, SLOT(setDesignModeBehavior(bool)));
connect(observer, SIGNAL(designModeBehaviorChanged(bool)), designModeBehaviorAction, SLOT(setChecked(bool)));
- connect(QmlJSDebugger::QDeclarativeObserverService::instance(), SIGNAL(debuggingClientChanged(bool)), designModeBehaviorAction, SLOT(setEnabled(bool)));
+ connect(QmlJSDebugger::QDeclarativeObserverService::instance(), SIGNAL(debuggingClientChanged(bool)),
+ designModeBehaviorAction, SLOT(setEnabled(bool)));
+
+ appOnTopAction = new QAction(tr("Keep Window on Top"), this);
+ appOnTopAction->setCheckable(true);
+ appOnTopAction->setChecked(observer->showAppOnTop());
+
+ connect(appOnTopAction, SIGNAL(triggered(bool)), observer, SLOT(setShowAppOnTop(bool)));
+ connect(observer, SIGNAL(showAppOnTopChanged(bool)), appOnTopAction, SLOT(setChecked(bool)));
QAction *proxyAction = new QAction(tr("HTTP &Proxy..."), this);
connect(proxyAction, SIGNAL(triggered()), this, SLOT(showProxySettings()));
@@ -762,36 +828,49 @@ void QDeclarativeViewer::createMenu()
fullscreenAction->setCheckable(true);
connect(fullscreenAction, SIGNAL(triggered()), this, SLOT(toggleFullScreen()));
- QAction *rotateOrientation = new QAction(tr("Rotate orientation"), this);
- rotateOrientation->setShortcut(QKeySequence("Ctrl+T"));
- connect(rotateOrientation, SIGNAL(triggered()), this, SLOT(rotateOrientation()));
+ rotateAction = new QAction(tr("Rotate orientation"), this);
+ rotateAction->setShortcut(QKeySequence("Ctrl+T"));
+ connect(rotateAction, SIGNAL(triggered()), this, SLOT(rotateOrientation()));
orientation = new QActionGroup(this);
orientation->setExclusive(true);
connect(orientation, SIGNAL(triggered(QAction*)), this, SLOT(changeOrientation(QAction*)));
+#if defined(Q_OS_SYMBIAN)
+ QAction *autoOrientationAction = new QAction(tr("Auto-orientation"), this);
+ autoOrientationAction->setCheckable(true);
+#endif
QAction *portraitAction = new QAction(tr("Portrait"), this);
portraitAction->setCheckable(true);
QAction *landscapeAction = new QAction(tr("Landscape"), this);
landscapeAction->setCheckable(true);
+#if !defined(Q_OS_SYMBIAN)
QAction *portraitInvAction = new QAction(tr("Portrait (inverted)"), this);
portraitInvAction->setCheckable(true);
QAction *landscapeInvAction = new QAction(tr("Landscape (inverted)"), this);
landscapeInvAction->setCheckable(true);
+#endif
QAction *aboutAction = new QAction(tr("&About Qt..."), this);
+ aboutAction->setMenuRole(QAction::AboutQtRole);
connect(aboutAction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
+ QAction *closeAction = new QAction(tr("&Close"), this);
+ closeAction->setShortcuts(QKeySequence::Close);
+ connect(closeAction, SIGNAL(triggered()), this, SLOT(close()));
+
QAction *quitAction = new QAction(tr("&Quit"), this);
- quitAction->setShortcut(QKeySequence("Ctrl+Q"));
+ quitAction->setMenuRole(QAction::QuitRole);
+ quitAction->setShortcuts(QKeySequence::Quit);
connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
QMenuBar *menu = menuBar();
if (!menu)
- return;
+ return;
#if defined(Q_WS_MAEMO_5)
menu->addAction(openAction);
+ menu->addAction(openUrlAction);
menu->addAction(reloadAction);
menu->addAction(snapshotAction);
@@ -812,37 +891,45 @@ void QDeclarativeViewer::createMenu()
QMenu *fileMenu = menu->addMenu(tr("&File"));
fileMenu->addAction(openAction);
+ fileMenu->addAction(openUrlAction);
fileMenu->addAction(reloadAction);
fileMenu->addSeparator();
+ fileMenu->addAction(closeAction);
+#if !defined(Q_OS_SYMBIAN)
fileMenu->addAction(quitAction);
-#if !defined(Q_OS_SYMBIAN)
QMenu *recordMenu = menu->addMenu(tr("&Recording"));
recordMenu->addAction(snapshotAction);
recordMenu->addAction(recordAction);
QMenu *debugMenu = menu->addMenu(tr("&Debugging"));
- debugMenu->addAction(playSpeedAction);
+ debugMenu->addMenu(playSpeedMenu);
debugMenu->addAction(showWarningsWindow);
debugMenu->addAction(designModeBehaviorAction);
+ debugMenu->addAction(appOnTopAction);
#endif // ! Q_OS_SYMBIAN
- QMenu *settingsMenu = menu->addMenu(tr("S&ettings"));
+ QMenu *settingsMenu = menu->addMenu(tr("&Settings"));
settingsMenu->addAction(proxyAction);
-#if !defined(Q_OS_SYMBIAN)
+#if defined(Q_OS_SYMBIAN)
+ settingsMenu->addAction(fullscreenAction);
+#else
settingsMenu->addAction(recordOptions);
settingsMenu->addMenu(loggerWindow->preferencesMenu());
-#else // ! Q_OS_SYMBIAN
- settingsMenu->addAction(fullscreenAction);
-#endif // Q_OS_SYMBIAN
- settingsMenu->addAction(rotateOrientation);
+#endif // !Q_OS_SYMBIAN
+ settingsMenu->addAction(rotateAction);
QMenu *propertiesMenu = settingsMenu->addMenu(tr("Properties"));
+#if defined(Q_OS_SYMBIAN)
+ orientation->addAction(autoOrientationAction);
+#endif
orientation->addAction(portraitAction);
orientation->addAction(landscapeAction);
+#if !defined(Q_OS_SYMBIAN)
orientation->addAction(portraitInvAction);
orientation->addAction(landscapeInvAction);
+#endif
propertiesMenu->addActions(orientation->actions());
QMenu *helpMenu = menu->addMenu(tr("&Help"));
@@ -860,11 +947,29 @@ void QDeclarativeViewer::showProxySettings()
void QDeclarativeViewer::proxySettingsChanged()
{
+ namFactory->proxyChanged();
reload ();
}
void QDeclarativeViewer::rotateOrientation()
{
+#if defined(Q_WS_S60)
+ CAknAppUi *appUi = static_cast<CAknAppUi *>(CEikonEnv::Static()->AppUi());
+ if (appUi) {
+ CAknAppUi::TAppUiOrientation oldOrientation = appUi->Orientation();
+ QString newOrientation;
+ if (oldOrientation == CAknAppUi::EAppUiOrientationPortrait) {
+ newOrientation = QLatin1String("Landscape");
+ } else {
+ newOrientation = QLatin1String("Portrait");
+ }
+ foreach (QAction *action, orientation->actions()) {
+ if (action->text() == newOrientation) {
+ changeOrientation(action);
+ }
+ }
+ }
+#else
QAction *current = orientation->checkedAction();
QList<QAction *> actions = orientation->actions();
int index = actions.indexOf(current);
@@ -873,6 +978,7 @@ void QDeclarativeViewer::rotateOrientation()
QAction *newOrientation = actions[(index + 1) % actions.count()];
changeOrientation(newOrientation);
+#endif
}
void QDeclarativeViewer::toggleFullScreen()
@@ -970,41 +1076,41 @@ void QDeclarativeViewer::toggleRecording()
void QDeclarativeViewer::setAnimationsPaused(bool enable)
{
- if (enable) {
- setAnimationSpeed(0.0);
- } else {
- setAnimationSpeed(animationSpeed);
- }
+ if (enable) {
+ setAnimationSpeed(0.0);
+ } else {
+ setAnimationSpeed(animationSpeed);
+ }
}
void QDeclarativeViewer::pauseAnimations() {
- pauseAnimationsAction->setChecked(true);
- setAnimationsPaused(true);
+ pauseAnimationsAction->setChecked(true);
+ setAnimationsPaused(true);
}
void QDeclarativeViewer::stepAnimations()
{
- setAnimationSpeed(1.0);
- QTimer::singleShot(m_stepSize, this, SLOT(pauseAnimations()));
-}
+ setAnimationSpeed(1.0);
+ QTimer::singleShot(m_stepSize, this, SLOT(pauseAnimations()));
+ }
void QDeclarativeViewer::setAnimationStep()
{
- bool ok;
- int stepSize = QInputDialog::getInt(this, tr("Set animation step duration"),
- tr("Step duration (ms):"), m_stepSize, 20, 10000, 1, &ok);
- if (ok) m_stepSize = stepSize;
+ bool ok;
+ int stepSize = QInputDialog::getInt(this, tr("Set animation step duration"),
+ tr("Step duration (ms):"), m_stepSize, 20, 10000, 1, &ok);
+ if (ok) m_stepSize = stepSize;
}
void QDeclarativeViewer::changeAnimationSpeed()
{
- QAction *action = qobject_cast<QAction*>(sender());
- if (action) {
- float f = action->data().toFloat();
- animationSpeed = f;
- if (!pauseAnimationsAction->isChecked())
- setAnimationSpeed(animationSpeed);
- }
+ QAction *action = qobject_cast<QAction*>(sender());
+ if (action) {
+ float f = action->data().toFloat();
+ animationSpeed = f;
+ if (!pauseAnimationsAction->isChecked())
+ setAnimationSpeed(animationSpeed);
+ }
}
void QDeclarativeViewer::addLibraryPath(const QString& lib)
@@ -1019,15 +1125,14 @@ void QDeclarativeViewer::addPluginPath(const QString& plugin)
void QDeclarativeViewer::reload()
{
- observer->setDesignModeBehavior(false);
- open(currentFileOrUrl);
+ launch(currentFileOrUrl);
}
void QDeclarativeViewer::openFile()
{
QString cur = canvas->source().toLocalFile();
if (useQmlFileBrowser) {
- open("qrc:/content/Browser.qml");
+ open("qrc:/browser/Browser.qml");
} else {
QString fileName = QFileDialog::getOpenFileName(this, tr("Open QML file"), cur, tr("QML Files (*.qml)"));
if (!fileName.isEmpty()) {
@@ -1037,6 +1142,14 @@ void QDeclarativeViewer::openFile()
}
}
+void QDeclarativeViewer::openUrl()
+{
+ QString cur = canvas->source().toLocalFile();
+ QString url= QInputDialog::getText(this, tr("Open QML file"), tr("URL of main QML file:"), QLineEdit::Normal, cur);
+ if (!url.isEmpty())
+ open(url);
+}
+
void QDeclarativeViewer::statusChanged()
{
if (canvas->status() == QDeclarativeView::Error && tester)
@@ -1069,11 +1182,7 @@ void QDeclarativeViewer::loadDummyDataFiles(const QString& directory)
QStringList list = dir.entryList();
for (int i = 0; i < list.size(); ++i) {
QString qml = list.at(i);
- QFile f(dir.filePath(qml));
- f.open(QIODevice::ReadOnly);
- QByteArray data = f.readAll();
- QDeclarativeComponent comp(canvas->engine());
- comp.setData(data, QUrl());
+ QDeclarativeComponent comp(canvas->engine(), dir.filePath(qml));
QObject *dummyData = comp.create();
if(comp.isError()) {
@@ -1212,8 +1321,10 @@ bool QDeclarativeViewer::event(QEvent *event)
{
if (event->type() == QEvent::WindowActivate) {
Runtime::instance()->setActiveWindow(true);
+ DeviceOrientation::instance()->resumeListening();
} else if (event->type() == QEvent::WindowDeactivate) {
Runtime::instance()->setActiveWindow(false);
+ DeviceOrientation::instance()->pauseListening();
}
return QWidget::event(event);
}
@@ -1389,6 +1500,8 @@ void QDeclarativeViewer::appAboutToQuit()
// avoid crashes if messages are received after app has closed
delete loggerWindow;
loggerWindow = 0;
+ delete tester;
+ tester = 0;
}
void QDeclarativeViewer::autoStartRecording()
@@ -1423,9 +1536,24 @@ void QDeclarativeViewer::changeOrientation(QAction *action)
{
if (!action)
return;
- action->setChecked(true);
-
QString o = action->text();
+ action->setChecked(true);
+#if defined(Q_WS_S60)
+ CAknAppUi *appUi = static_cast<CAknAppUi *>(CEikonEnv::Static()->AppUi());
+ if (appUi) {
+ CAknAppUi::TAppUiOrientation orientation = appUi->Orientation();
+ if (o == QLatin1String("Auto-orientation")) {
+ appUi->SetOrientationL(CAknAppUi::EAppUiOrientationAutomatic);
+ rotateAction->setVisible(false);
+ } else if (o == QLatin1String("Portrait")) {
+ appUi->SetOrientationL(CAknAppUi::EAppUiOrientationPortrait);
+ rotateAction->setVisible(true);
+ } else if (o == QLatin1String("Landscape")) {
+ appUi->SetOrientationL(CAknAppUi::EAppUiOrientationLandscape);
+ rotateAction->setVisible(true);
+ }
+ }
+#else
if (o == QLatin1String("Portrait"))
DeviceOrientation::instance()->setOrientation(DeviceOrientation::Portrait);
else if (o == QLatin1String("Landscape"))
@@ -1434,6 +1562,7 @@ void QDeclarativeViewer::changeOrientation(QAction *action)
DeviceOrientation::instance()->setOrientation(DeviceOrientation::PortraitInverted);
else if (o == QLatin1String("Landscape (inverted)"))
DeviceOrientation::instance()->setOrientation(DeviceOrientation::LandscapeInverted);
+#endif
}
void QDeclarativeViewer::orientationChanged()
@@ -1487,6 +1616,11 @@ void QDeclarativeViewer::setSizeToView(bool sizeToView)
}
}
+void QDeclarativeViewer::setStayOnTop(bool stayOnTop)
+{
+ appOnTopAction->setChecked(stayOnTop);
+}
+
void QDeclarativeViewer::setAnimationSpeed(float f)
{
QDeclarativeDebugHelper::setAnimationSlowDownFactor(f);
@@ -1504,7 +1638,6 @@ void QDeclarativeViewer::updateSizeHints(bool initial)
QSize newWindowSize = initial ? initialSize : canvas->sizeHint();
//qWarning() << "USH:" << (initial ? "INIT:" : "V2R:") << "setting fixed size " << newWindowSize;
if (!isFullScreen() && !isMaximized()) {
- m_centralWidget->setFixedSize(newWindowSize.width(), newWindowSize.height() + 32);
canvas->setFixedSize(newWindowSize);
resize(1, 1);
layout()->setSizeConstraint(QLayout::SetFixedSize);
@@ -1514,18 +1647,14 @@ void QDeclarativeViewer::updateSizeHints(bool initial)
//qWarning() << "USH: R2V: setting free size ";
layout()->setSizeConstraint(QLayout::SetNoConstraint);
layout()->activate();
-
+ setMinimumSize(minimumSizeHint());
setMaximumSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
canvas->setMinimumSize(QSize(0,0));
canvas->setMaximumSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
- m_centralWidget->setMinimumSize(QSize(0,0));
- m_centralWidget->setMaximumSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
-
isRecursive = false;
}
-
void QDeclarativeViewer::registerTypes()
{
static bool registered = false;
@@ -1533,6 +1662,7 @@ void QDeclarativeViewer::registerTypes()
if (!registered) {
// registering only for exposing the DeviceOrientation::Orientation enum
qmlRegisterUncreatableType<DeviceOrientation>("Qt",4,7,"Orientation","");
+ qmlRegisterUncreatableType<DeviceOrientation>("QtQuick",1,0,"Orientation","");
registered = true;
}
}
diff --git a/share/qtcreator/qml/qmlobserver/qmlruntime.h b/share/qtcreator/qml/qmlobserver/qmlruntime.h
index 7c30998dfc..7ef1bd1479 100644
--- a/share/qtcreator/qml/qmlobserver/qmlruntime.h
+++ b/share/qtcreator/qml/qmlobserver/qmlruntime.h
@@ -67,7 +67,6 @@ class NetworkAccessManagerFactory;
class QTranslator;
class QActionGroup;
class QMenuBar;
-class QSplitter;
class QDeclarativeViewer
: public QMainWindow
@@ -75,7 +74,7 @@ class QDeclarativeViewer
Q_OBJECT
public:
- explicit QDeclarativeViewer(QWidget *parent = 0, Qt::WindowFlags flags = 0);
+ QDeclarativeViewer(QWidget *parent = 0, Qt::WindowFlags flags = 0);
~QDeclarativeViewer();
static void registerTypes();
@@ -88,7 +87,8 @@ public:
SaveOnExit = 0x00000010,
ExitOnComplete = 0x00000020,
ExitOnFailure = 0x00000040,
- Snapshot = 0x00000080
+ Snapshot = 0x00000080,
+ TestSkipProperty = 0x00000100
};
Q_DECLARE_FLAGS(ScriptOptions, ScriptOption)
void setScript(const QString &s) { m_script = s; }
@@ -107,9 +107,11 @@ public:
void setUseGL(bool use);
void setUseNativeFileBrowser(bool);
void setSizeToView(bool sizeToView);
+ void setStayOnTop(bool stayOnTop);
QDeclarativeView *view() const;
LoggerWidget *warningsWidget() const;
+ QString currentFile() const { return currentFileOrUrl; }
void enableExperimentalGestures();
@@ -118,6 +120,7 @@ public slots:
void sceneResized(QSize size);
bool open(const QString&);
void openFile();
+ void openUrl();
void reload();
void takeSnapShot();
void toggleRecording();
@@ -162,7 +165,6 @@ private:
QString getVideoFileName();
LoggerWidget *loggerWindow;
-
QDeclarativeView *canvas;
QmlJSDebugger::QDeclarativeViewObserver *observer;
QSize initialSize;
@@ -182,8 +184,6 @@ private:
int record_autotime;
bool devicemode;
QAction *recordAction;
- QString currentSkin;
- bool scaleSkin;
RecordingDialog *recdlg;
void senseImageMagick();
@@ -198,9 +198,11 @@ private:
QAction *animationStepAction;
QAction *animationSetStepAction;
+ QAction *rotateAction;
QActionGroup *orientation;
QAction *showWarningsWindow;
QAction *designModeBehaviorAction;
+ QAction *appOnTopAction;
QString m_script;
ScriptOptions m_scriptOptions;
@@ -212,8 +214,6 @@ private:
bool useQmlFileBrowser;
- QWidget *m_centralWidget;
-
QTranslator *translator;
void loadTranslationFile(const QString& directory);
diff --git a/share/qtcreator/qml/qmlobserver/qmlruntime.qrc b/share/qtcreator/qml/qmlobserver/qmlruntime.qrc
deleted file mode 100644
index 4136eafa52..0000000000
--- a/share/qtcreator/qml/qmlobserver/qmlruntime.qrc
+++ /dev/null
@@ -1,9 +0,0 @@
-<RCC>
- <qresource prefix="/">
- <file>content/Browser.qml</file>
- <file>content/images/up.png</file>
- <file>content/images/folder.png</file>
- <file>content/images/titlebar.sci</file>
- <file>content/images/titlebar.png</file>
- </qresource>
-</RCC>
diff --git a/share/qtcreator/qml/qmlobserver/startup/Logo.qml b/share/qtcreator/qml/qmlobserver/startup/Logo.qml
new file mode 100644
index 0000000000..aa5648f5ed
--- /dev/null
+++ b/share/qtcreator/qml/qmlobserver/startup/Logo.qml
@@ -0,0 +1,179 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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$
+**
+****************************************************************************/
+
+import QtQuick 1.0
+
+Rectangle {
+ id: myApp
+ width: 411
+ height: 411
+ color: "transparent"
+ property alias logoState : myApp.state
+ signal animationFinished
+
+ Item {
+ id: sketchBlueHolder
+ width: sketchLogo.width
+ height: sketchLogo.height
+ Image {
+ id: image1
+ x: -44
+ y: -45
+ smooth: true
+ source: "shadow.png"
+ }
+ Item {
+ clip: true
+ width: sketchLogo.width
+ height: sketchLogo.height
+ Image {
+ id: sketchLogo
+ smooth: true
+ source: "qt-sketch.jpg"
+ }
+ Image {
+ id: blueLogo
+ y: -420
+ smooth: true
+ source: "qt-blue.jpg"
+ }
+ }
+ }
+
+ states: [
+ State {
+ name: "showBlueprint"
+ PropertyChanges {
+ target: blueLogo
+ y: 0
+ }
+ PropertyChanges {
+ target: sketchLogo
+ opacity: 0
+ }
+ },
+ State {
+ extend: "showBlueprint"
+ name: "finale"
+ PropertyChanges {
+ target: fullLogo
+ opacity: 1
+ }
+ PropertyChanges {
+ target: backLogo
+ opacity: 1
+ scale: 1
+ }
+ PropertyChanges {
+ target: frontLogo
+ opacity: 1
+ scale: 1
+ }
+ PropertyChanges {
+ target: qtText
+ opacity: 1
+ scale: 1
+ }
+ PropertyChanges {
+ target: sketchBlueHolder
+ opacity: 0
+ scale: 1.4
+ }
+ }
+ ]
+
+ transitions: [
+ Transition {
+ to: "showBlueprint"
+ SequentialAnimation {
+ NumberAnimation { property: "y"; duration: 600; easing.type: "OutBounce" }
+ PropertyAction { target: sketchLogo; property: "opacity" }
+ }
+ },
+ Transition {
+ to: "finale"
+ PropertyAction { target: fullLogo; property: "opacity" }
+ SequentialAnimation {
+ NumberAnimation { target: backLogo; properties: "scale, opacity"; duration: 300 }
+ NumberAnimation { target: frontLogo; properties: "scale, opacity"; duration: 300 }
+ ParallelAnimation {
+ NumberAnimation { target: qtText; properties: "opacity, scale"; duration: 400; easing.type: "OutQuad" }
+ NumberAnimation { target: sketchBlueHolder; property: "opacity"; duration: 300; easing.type: "OutQuad" }
+ NumberAnimation { target: sketchBlueHolder; property: "scale"; duration: 320; easing.type: "OutQuad" }
+ }
+ PauseAnimation { duration: 1000 }
+ ScriptAction { script: myApp.animationFinished() }
+ }
+ }
+ ]
+
+ Item {
+ id: fullLogo
+ opacity: 0
+ Image {
+ id: backLogo
+ x: -16
+ y: -41
+ opacity: 0
+ scale: 0.7
+ smooth: true
+ source: "qt-back.png"
+ }
+ Image {
+ id: frontLogo
+ x: -17
+ y: -41
+ opacity: 0
+ scale: 1.2
+ smooth: true
+ source: "qt-front.png"
+ }
+ Image {
+ id: qtText
+ x: -10
+ y: -41
+ opacity: 0
+ scale: 1.2
+ smooth: true
+ source: "qt-text.png"
+ }
+ }
+}
diff --git a/share/qtcreator/qml/qmlobserver/startup/qt-back.png b/share/qtcreator/qml/qmlobserver/startup/qt-back.png
new file mode 100644
index 0000000000..077215f882
--- /dev/null
+++ b/share/qtcreator/qml/qmlobserver/startup/qt-back.png
Binary files differ
diff --git a/share/qtcreator/qml/qmlobserver/startup/qt-blue.jpg b/share/qtcreator/qml/qmlobserver/startup/qt-blue.jpg
new file mode 100644
index 0000000000..b204896483
--- /dev/null
+++ b/share/qtcreator/qml/qmlobserver/startup/qt-blue.jpg
Binary files differ
diff --git a/share/qtcreator/qml/qmlobserver/startup/qt-front.png b/share/qtcreator/qml/qmlobserver/startup/qt-front.png
new file mode 100644
index 0000000000..dbfb43e374
--- /dev/null
+++ b/share/qtcreator/qml/qmlobserver/startup/qt-front.png
Binary files differ
diff --git a/share/qtcreator/qml/qmlobserver/startup/qt-sketch.jpg b/share/qtcreator/qml/qmlobserver/startup/qt-sketch.jpg
new file mode 100644
index 0000000000..1ede6f079b
--- /dev/null
+++ b/share/qtcreator/qml/qmlobserver/startup/qt-sketch.jpg
Binary files differ
diff --git a/share/qtcreator/qml/qmlobserver/startup/qt-text.png b/share/qtcreator/qml/qmlobserver/startup/qt-text.png
new file mode 100644
index 0000000000..d44995c9b3
--- /dev/null
+++ b/share/qtcreator/qml/qmlobserver/startup/qt-text.png
Binary files differ
diff --git a/share/qtcreator/qml/qmlobserver/startup/quick-blur.png b/share/qtcreator/qml/qmlobserver/startup/quick-blur.png
new file mode 100644
index 0000000000..29ec243387
--- /dev/null
+++ b/share/qtcreator/qml/qmlobserver/startup/quick-blur.png
Binary files differ
diff --git a/share/qtcreator/qml/qmlobserver/startup/quick-regular.png b/share/qtcreator/qml/qmlobserver/startup/quick-regular.png
new file mode 100644
index 0000000000..38321cbf19
--- /dev/null
+++ b/share/qtcreator/qml/qmlobserver/startup/quick-regular.png
Binary files differ
diff --git a/share/qtcreator/qml/qmlobserver/startup/shadow.png b/share/qtcreator/qml/qmlobserver/startup/shadow.png
new file mode 100644
index 0000000000..44f92fee73
--- /dev/null
+++ b/share/qtcreator/qml/qmlobserver/startup/shadow.png
Binary files differ
diff --git a/share/qtcreator/qml/qmlobserver/startup/startup.qml b/share/qtcreator/qml/qmlobserver/startup/startup.qml
new file mode 100644
index 0000000000..35c44c2cf8
--- /dev/null
+++ b/share/qtcreator/qml/qmlobserver/startup/startup.qml
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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$
+**
+****************************************************************************/
+
+import QtQuick 1.0
+
+Rectangle {
+ id: treatsApp
+ width: 800
+ height: 480
+ color: "darkgrey"
+ Component.onCompleted: treatsApp.state = "part1"
+ signal animationFinished
+
+ Item {
+ width: 800
+ height: 480
+ anchors.centerIn: parent
+ clip: true
+
+ Logo {
+ id: logo
+ x: 165
+ y: 35
+ rotation: -15
+ scale: 0.6
+ opacity: 0
+ onAnimationFinished: treatsApp.animationFinished();
+ }
+
+ Item {
+ id: quickblur
+ x: 800//325
+ y: 344
+ Image {
+ id: blurText
+ source: "quick-blur.png"
+ }
+ Image {
+ id: quickregular
+ x: -1
+ y: 0
+ opacity: 0
+ source: "quick-regular.png"
+ }
+ Image {
+ id: star
+ x: -1
+ y: 0
+ opacity: 0
+ source: "white-star.png"
+ smooth: true
+ NumberAnimation on rotation {
+ from: 0
+ to: 360
+ loops: NumberAnimation.Infinite
+ running: true
+ duration: 2000
+ }
+ }
+ }
+ }
+
+ states: [
+ State {
+ name: "part1"
+ PropertyChanges {
+ target: logo
+ scale: 0.8
+ opacity: 1
+ rotation: 0
+ }
+ PropertyChanges {
+ target: treatsApp
+ color: "black"
+ }
+ PropertyChanges {
+ target: logo
+ y: 10
+ }
+ PropertyChanges {
+ target: quickblur
+ x: logo.x + 145
+ }
+ PropertyChanges {
+ target: blurText
+ opacity: 0
+ }
+ PropertyChanges {
+ target: quickregular
+ opacity: 1
+ }
+ PropertyChanges {
+ target: star
+ x: -7
+ y: -37
+ }
+ }
+ ]
+
+ transitions: [
+ Transition {
+ ParallelAnimation {
+ NumberAnimation { target: logo; property: "opacity"; duration: 500 }
+ NumberAnimation { target: logo; property: "scale"; duration: 4000; }
+ NumberAnimation { target: logo; property: "rotation"; duration: 2000; easing.type: "OutBack"}
+ ColorAnimation { duration: 3000}
+ SequentialAnimation {
+ PauseAnimation { duration: 1000 }
+ ScriptAction { script: logo.logoState = "showBlueprint" }
+ PauseAnimation { duration: 800 }
+ ScriptAction { script: logo.logoState = "finale" }
+ PauseAnimation { duration: 800 }
+ ParallelAnimation {
+ NumberAnimation { target: quickblur; property: "x"; duration: 200;}
+ SequentialAnimation {
+ PauseAnimation { duration: 200}
+ ParallelAnimation {
+ NumberAnimation { target: blurText; property: "opacity"; duration: 300;}
+ NumberAnimation { target: quickregular; property: "opacity"; duration: 300;}
+ }
+ NumberAnimation { target: star; property: "opacity"; from: 0; to: 1; duration: 500 }
+ PauseAnimation { duration: 200 }
+ NumberAnimation { target: star; property: "opacity"; from: 1; to: 0; duration: 500 }
+ }
+ SequentialAnimation {
+ PauseAnimation { duration: 150}
+ NumberAnimation { target: logo; property: "y"; duration: 300; easing.type: "OutBounce" }
+ }
+ }
+ }
+ }
+ }
+ ]
+
+} // treatsApp
diff --git a/share/qtcreator/qml/qmlobserver/startup/startup.qrc b/share/qtcreator/qml/qmlobserver/startup/startup.qrc
new file mode 100644
index 0000000000..52e67050d9
--- /dev/null
+++ b/share/qtcreator/qml/qmlobserver/startup/startup.qrc
@@ -0,0 +1,16 @@
+<RCC>
+ <qresource prefix="/startup">
+ <file>Logo.qml</file>
+ <file>qt-back.png</file>
+ <file>qt-blue.jpg</file>
+ <file>qt-front.png</file>
+ <file>qt-sketch.jpg</file>
+ <file>qt-text.png</file>
+ <file>quick-blur.png</file>
+ <file>quick-regular.png</file>
+ <file>shadow.png</file>
+ <file>startup.qml</file>
+ <file>startup.qrc</file>
+ <file>white-star.png</file>
+ </qresource>
+</RCC>
diff --git a/share/qtcreator/qml/qmlobserver/startup/white-star.png b/share/qtcreator/qml/qmlobserver/startup/white-star.png
new file mode 100644
index 0000000000..f467c9480e
--- /dev/null
+++ b/share/qtcreator/qml/qmlobserver/startup/white-star.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/ExtendedFunctionButton.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/ExtendedFunctionButton.qml
index 98a36127a9..3f2956c93a 100644
--- a/share/qtcreator/qmldesigner/propertyeditor/Qt/ExtendedFunctionButton.qml
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/ExtendedFunctionButton.qml
@@ -1,11 +1,13 @@
import Qt 4.7
import Bauhaus 1.0
-QToolButton {
+AnimatedToolButton {
id: extendedFunctionButton
property variant backendValue
+ hoverIconFromFile: "images/submenu.png";
+
function setIcon() {
if (backendValue == null)
extendedFunctionButton.iconFromFile = "images/placeholder.png"
@@ -40,15 +42,6 @@ QToolButton {
styleSheet: "*::down-arrow, *::menu-indicator { image: none; width: 0; height: 0; }";
-
- onMouseOverChanged: {
- if (mouseOver) {
- iconFromFile = "images/submenu.png";
- } else {
- setIcon();
- }
- }
-
onActiveChanged: {
if (active) {
setIcon();
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/StandardTextGroupBox.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/StandardTextGroupBox.qml
index 0cb32e415e..1355dc66ae 100644
--- a/share/qtcreator/qmldesigner/propertyeditor/Qt/StandardTextGroupBox.qml
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/StandardTextGroupBox.qml
@@ -57,20 +57,6 @@ GroupBox {
}
AlignmentVerticalButtons { }
}
- }
- QWidget {
- layout: HorizontalLayout {
- Label {
- text: qsTr("Aliasing")
- }
-
- CheckBox {
- text: qsTr("Smooth")
- backendValue: backendValues.smooth
- baseStateFlag: isBaseState;
- checkable: true;
- }
- }
- }
+ }
}
}
diff --git a/share/qtcreator/qmldesigner/propertyeditor/Qt/Visibility.qml b/share/qtcreator/qmldesigner/propertyeditor/Qt/Visibility.qml
index b15446cd11..9deb7e28a6 100644
--- a/share/qtcreator/qmldesigner/propertyeditor/Qt/Visibility.qml
+++ b/share/qtcreator/qmldesigner/propertyeditor/Qt/Visibility.qml
@@ -20,7 +20,14 @@ GroupBox {
backendValue: backendValues.visible;
baseStateFlag: isBaseState;
checkable: true;
- }
+ }
+ CheckBox {
+ id: smoothCheckBox;
+ text: qsTr("Smooth")
+ backendValue: backendValues.smooth;
+ baseStateFlag: isBaseState;
+ checkable: true;
+ }
}
}
QWidget {
diff --git a/share/qtcreator/snippets/cpp.xml b/share/qtcreator/snippets/cpp.xml
index 14598ff276..8c871d1893 100644
--- a/share/qtcreator/snippets/cpp.xml
+++ b/share/qtcreator/snippets/cpp.xml
@@ -1,78 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<snippets>
-<snippet>class <tab>name</tab>
+<snippet group="C++" trigger="class" id="cpp_genericclass">class $name$
{
public:
- <tab>name</tab>() {}
-};
-</snippet>
-<snippet description="derived from QObject">class <tab>name</tab> : public QObject
+ $name$() {}
+};</snippet>
+<snippet group="C++" trigger="class" id="cpp_qobjectclass" complement="derived from QObject">class $name$ : public QObject
{
Q_OBJECT
public:
- <tab>name</tab>() {}
- virtual ~<tab>name</tab>() {}
-};
-</snippet>
-<snippet description="derived from QWidget">class <tab>name</tab> : public QWidget
+ $name$() {}
+ virtual ~$name$() {}
+};</snippet>
+<snippet group="C++" trigger="class" id="cpp_qwidgetclass" complement="derived from QWidget">class $name$ : public QWidget
{
Q_OBJECT
public:
- <tab>name</tab>() {}
- virtual ~<tab>name</tab>() {}
-};
-</snippet>
-<snippet>do {
+ $name$() {}
+ virtual ~$name$() {}
+};</snippet>
+<snippet group="C++" trigger="class" id="cpp_classtemplate" complement="template">template &lt;typename $T$&gt;
+class $name$
+{
+public:
+ $name$() {}
+};</snippet>
+<snippet group="C++" trigger="do" id="cpp_do">do {
-} while (<tab>condition</tab>);
-</snippet>
-<snippet>else {
+} while ($condition$);</snippet>
+<snippet group="C++" trigger="else" id="cpp_else" >else {
-}
-</snippet>
-<snippet description="with if">else if (<tab>condition</tab>) {
+}</snippet>
+<snippet group="C++" trigger="else" id="cpp_elsewithif" complement="with if">else if ($condition$) {
-}
-</snippet>
-<snippet>for (int <tab>var</tab> = 0; <tab>var</tab> &lt; <tab>total</tab>; ++<tab>var</tab>) {
+}</snippet>
+<snippet group="C++" trigger="for" id="cpp_for">for (int $var$ = 0; $var$ &lt; $total$; ++$var$) {
-}
-</snippet>
-<snippet>foreach (<tab>var</tab>, <tab>container</tab>) {
+}</snippet>
+<snippet group="C++" trigger="foreach" id="cpp_foreach">foreach ($var$, $container$) {
-}
-</snippet>
-<snippet>if (<tab>condition</tab>) {
+}</snippet>
+<snippet group="C++" trigger="if" id="cpp_if">if ($condition$) {
-}
-</snippet>
-<snippet description="and else">if (<tab>condition</tab>) {
+}</snippet>
+<snippet group="C++" trigger="if" id="cpp_ifandelse" complement="and else">if ($condition$) {
} else {
-}
-</snippet>
-<snippet>namespace <tab>name</tab> {
+}</snippet>
+<snippet group="C++" trigger="namespace" id="cpp_namespace">namespace $name$ {
-}
-</snippet>
-<snippet>template &lt;typename <tab>T</tab>&gt;
-class <tab>name</tab>
-{
-public:
- <tab>name</tab>() {}
-};
-</snippet>
-<snippet>try {
+}</snippet>
+<snippet group="C++" trigger="try" id="cpp_trycatch" complement="and catch">try {
} catch (...) {
-}
-</snippet>
-<snippet>using namespace <tab>name</tab>;
-</snippet>
-<snippet>while (<tab>condition</tab>) {
+}</snippet>
+<snippet group="C++" trigger="using" id="cpp_usingnamespace" complement="namespace">using namespace $name$;</snippet>
+<snippet group="C++" trigger="while" id="cpp_while">while ($condition$) {
-}
-</snippet>
+}</snippet>
</snippets>
diff --git a/share/qtcreator/snippets/qml.xml b/share/qtcreator/snippets/qml.xml
index a7f2110caa..0aa17af968 100644
--- a/share/qtcreator/snippets/qml.xml
+++ b/share/qtcreator/snippets/qml.xml
@@ -1,85 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<snippets>
-<snippet>property <tab>type</tab> <tab>name</tab>: <tab>value</tab>
-</snippet>
-<snippet>Item {
- id: <tab>name</tab>
-}
-</snippet>
-<snippet>BorderImage {
- id: <tab>name</tab>
- source: "<tab>file</tab>"
- width: <tab>100</tab>; height: <tab>100</tab>
- border.left: <tab>5</tab>; border.top: <tab>5</tab>
- border.right: <tab>5</tab>; border.bottom: <tab>5</tab>
-}
-</snippet>
-
-<snippet>Image {
- id: <tab>name</tab>
- source: "<tab>file</tab>"
-}
-</snippet>
-
-<snippet>Text {
- id: <tab>name</tab>
- text: "<tab>text</tab>"
-}
-</snippet>
-
-<snippet>states: [
+<snippet group="QML" trigger="property" id="qml_property">property $type$ $name$: $value$</snippet>
+<snippet group="QML" trigger="Item" id="qml_item">Item {
+ id: $name$
+}</snippet>
+<snippet group="QML" trigger="BorderImage" id="qml_borderimage">BorderImage {
+ id: $name$
+ source: "$file$"
+ width: $100$; height: $100$
+ border.left: $5$; border.top: $5$
+ border.right: $5$; border.bottom: $5$
+}</snippet>
+<snippet group="QML" trigger="Image" id="qml_image">Image {
+ id: $name$
+ source: "$file$"
+}</snippet>
+<snippet group="QML" trigger="Text" id="qml_text">Text {
+ id: $name$
+ text: "$text$"
+}</snippet>
+<snippet group="QML" trigger="states" id="qml_states">states: [
State {
- name: "<tab>name</tab>"
+ name: "$name$"
PropertyChanges {
- target: <tab>name</tab>
- <tab/>
+ target: $name$
+ $$
}
}
-]
-</snippet>
-
-<snippet>State {
- name: "<tab>name</tab>"
+]</snippet>
+<snippet group="QML" trigger="State" id="qml_state">State {
+ name: "$name$"
PropertyChanges {
- target: <tab>name</tab>
- <tab/>
+ target: $name$
+ $$
}
-}
-</snippet>
-
-<snippet>transitions: [
+}</snippet>
+<snippet group="QML" trigger="transitions" id="qml_transitions">transitions: [
Transition {
- from: "<tab>name</tab>"
- to: "<tab>name</tab>"
- <tab/>
+ from: "$name$"
+ to: "$name$"
+ $$
}
-]
-</snippet>
-
-<snippet>Transition {
- from: "<tab>name</tab>"
- to: "<tab>name</tab>"
- <tab/>
-}
-</snippet>
-
-<snippet>PropertyChanges {
- target: <tab>name</tab>
- <tab/>
-}
-</snippet>
-
-<snippet description="with targets">NumberAnimation { targets: [<tab>name</tab>]; properties: "<tab>name</tab>"; duration: <tab>200</tab> }
-</snippet>
-<snippet description="with target">NumberAnimation { target: <tab>name</tab>; property: "<tab>name</tab>"; to: <tab>value</tab>; duration: <tab>200</tab> }
-</snippet>
-<snippet description="with targets">PropertyAction { targets: [<tab>name</tab>]; properties: "<tab>name</tab>" }
-</snippet>
-<snippet description="with target">PropertyAction { target: <tab>name</tab>; property: "<tab>name</tab>"; value: <tab>value</tab> }
-</snippet>
-<snippet>PauseAnimation { duration: <tab>200</tab> }
-</snippet>
-<snippet>ColorAnimation { from: <tab>"white"</tab>; to: <tab>"black"</tab>; duration: <tab>200</tab> }
-</snippet>
-
+]</snippet>
+<snippet group="QML" trigger="Transition" id="qml_transition">Transition {
+ from: "$name$"
+ to: "$name$"
+ $$
+}</snippet>
+<snippet group="QML" trigger="PropertyChanges" id="qml_propertychanges">PropertyChanges {
+ target: $name$
+ $$
+}</snippet>
+<snippet group="QML" trigger="NumberAnimation" id="qml_numberanimationwithtargets" complement="with targets">NumberAnimation { targets: [$name$]; properties: "$name$"; duration: $200$ }</snippet>
+<snippet group="QML" trigger="NumberAnimation" id="qml_numberanimationwithtarget" complement="with target">NumberAnimation { target: $name$; property: "$name$"; to: $value$; duration: $200$ }</snippet>
+<snippet group="QML" trigger="PropertyAction" id="qml_propertyactionwithtargets" complement="with targets">PropertyAction { targets: [$name$]; properties: "$name$" }</snippet>
+<snippet group="QML" trigger="PropertyAction" id="qml_propertyactionwithtarget" complement="with target">PropertyAction { target: $name$; property: "$name$"; value: $value$ }</snippet>
+<snippet group="QML" trigger="PauseAnimation" id="qml_pauseanimation">PauseAnimation { duration: $200$ }</snippet>
+<snippet group="QML" trigger="ColorAnimation" id="qml_coloranimation">ColorAnimation { from: $"white"$; to: $"black"$; duration: $200$ }</snippet>
</snippets>
diff --git a/share/qtcreator/snippets/text.xml b/share/qtcreator/snippets/text.xml
new file mode 100644
index 0000000000..a1e3cf45f4
--- /dev/null
+++ b/share/qtcreator/snippets/text.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<snippets>
+<snippet group="Text" trigger="global" id="text_global" complement="example">// This is available in all editors.</snippet>
+</snippets>
diff --git a/share/qtcreator/static.pro b/share/qtcreator/static.pro
index 222fef4dfa..259dc37f68 100644
--- a/share/qtcreator/static.pro
+++ b/share/qtcreator/static.pro
@@ -36,8 +36,8 @@ DATA_DIRS = \
qmlicons \
qml \
qml-type-descriptions \
- qmljsdebugger \
- generic-highlighter
+ generic-highlighter \
+ glsl
!isEmpty(copydata) {
@@ -47,6 +47,7 @@ DATA_DIRS = \
for(file, files):!exists($$file/*):FILES += $$file
}
+ macx:OTHER_FILES += $$FILES
copy2build.input = FILES
copy2build.output = $$IDE_DATA_PATH/${QMAKE_FUNC_FILE_IN_stripSrcDir}
isEmpty(vcproj):copy2build.variable_out = PRE_TARGETDEPS
diff --git a/share/qtcreator/styles/inkpot.xml b/share/qtcreator/styles/inkpot.xml
new file mode 100644
index 0000000000..3634cca394
--- /dev/null
+++ b/share/qtcreator/styles/inkpot.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ This color scheme is based on the vim Inkpot color scheme, originally
+ created by Ciaran McCreesh:
+
+ http://www.vim.org/scripts/script.php?script_id=1143
+
+ It was adapted for use by Qt Creator by Jan Kundrát and subsequently
+ updated by Campbell Barton.
+-->
+<style-scheme version="1.0" name="Inkpot">
+ <style name="AddedLine" foreground="#00aa00"/>
+ <style name="Comment" foreground="#cd8b00"/>
+ <style name="CurrentLine" foreground="#000000" background="#2d2d32"/>
+ <style name="CurrentLineNumber" foreground="#a7a7f5" bold="true"/>
+ <style name="DiffFile" foreground="#8484f3"/>
+ <style name="DiffLocation" foreground="#0084ff"/>
+ <style name="DisabledCode" foreground="#a0a0a4" italic="true"/>
+ <style name="Doxygen.Comment" foreground="#737dd5"/>
+ <style name="Doxygen.Tag" foreground="#4e5ab3"/>
+ <style name="Field" bold="true"/>
+ <style name="Keyword" foreground="#808bed"/>
+ <style name="Label" foreground="#e76000"/>
+ <style name="LineNumber" foreground="#8b8bcd" background="#2e2e2e"/>
+ <style name="Link" foreground="#0000ff"/>
+ <style name="Local"/>
+ <style name="Number" foreground="#506bbd"/>
+ <style name="Occurrences" foreground="#000000" background="#616161"/>
+ <style name="Occurrences.Rename" foreground="#000000" background="#ff6464"/>
+ <style name="Occurrences.Unused" foreground="#808000"/>
+ <style name="Operator" foreground="#409040"/>
+ <style name="Parentheses" foreground="#ffff00"/>
+ <style name="Preprocessor" foreground="#409040"/>
+ <style name="RemovedLine" foreground="#ff0000"/>
+ <style name="SearchResult" foreground="#000000" background="#ffef0b"/>
+ <style name="SearchScope" foreground="#000000" background="#f8fafc"/>
+ <style name="Selection" foreground="#ffffff" background="#678db2"/>
+ <style name="Static" foreground="#cb6ecb"/>
+ <style name="String" foreground="#ffcd8b" background="#404040"/>
+ <style name="Text" foreground="#cfbfad" background="#1e1e27"/>
+ <style name="Type" foreground="#ff8bff"/>
+ <style name="VirtualMethod" italic="true"/>
+ <style name="VisualWhitespace" foreground="#646482"/>
+</style-scheme>
diff --git a/share/qtcreator/templates/mobileapp/app.pro b/share/qtcreator/templates/mobileapp/app.pro
index d5b07cba27..3e62a194b5 100644
--- a/share/qtcreator/templates/mobileapp/app.pro
+++ b/share/qtcreator/templates/mobileapp/app.pro
@@ -15,6 +15,13 @@ DEFINES += NETWORKACCESS
# TARGETUID3 #
symbian:TARGET.UID3 = 0xE1111234
+# Smart Installer package's UID
+# This UID is from the protected range
+# and therefore the package will fail to install if self-signed
+# By default qmake uses the unprotected range value if unprotected UID is defined for the application
+# and 0x2002CCCF value if protected UID is given to the application
+#symbian:DEPLOYMENT.installer_header = 0x2002CCCF
+
# If your application uses the Qt Mobility libraries, uncomment
# the following lines and add the respective components to the
# MOBILITY variable.
diff --git a/share/qtcreator/templates/qmlapp/app.pro b/share/qtcreator/templates/qmlapp/app.pro
index 5dcaeb3f68..bc1019778b 100644
--- a/share/qtcreator/templates/qmlapp/app.pro
+++ b/share/qtcreator/templates/qmlapp/app.pro
@@ -20,6 +20,13 @@ DEFINES += NETWORKACCESS
# TARGETUID3 #
symbian:TARGET.UID3 = 0xE1111234
+# Smart Installer package's UID
+# This UID is from the protected range
+# and therefore the package will fail to install if self-signed
+# By default qmake uses the unprotected range value if unprotected UID is defined for the application
+# and 0x2002CCCF value if protected UID is given to the application
+#symbian:DEPLOYMENT.installer_header = 0x2002CCCF
+
# Define QMLJSDEBUGGER to allow debugging of QML in debug builds
# (This might significantly increase build time)
# DEFINES += QMLJSDEBUGGER
diff --git a/share/qtcreator/templates/shared/deployment.pri b/share/qtcreator/templates/shared/deployment.pri
index a1760b5b98..24a2df2802 100644
--- a/share/qtcreator/templates/shared/deployment.pri
+++ b/share/qtcreator/templates/shared/deployment.pri
@@ -49,7 +49,7 @@ symbian {
installPrefix = /opt/usr
desktopfile.path = /usr/share/applications/hildon
} else {
- installPrefix = /usr/local
+ installPrefix = /usr
desktopfile.path = /usr/share/applications
copyCommand =
for(deploymentfolder, DEPLOYMENTFOLDERS) {
diff --git a/share/qtcreator/templates/wizards/qtcreatorplugin/MyPlugin.pluginspec b/share/qtcreator/templates/wizards/qtcreatorplugin/MyPlugin.pluginspec
deleted file mode 100644
index 4dc2e5f1fb..0000000000
--- a/share/qtcreator/templates/wizards/qtcreatorplugin/MyPlugin.pluginspec
+++ /dev/null
@@ -1,10 +0,0 @@
-<plugin name="%PluginName%" version="0.0.1" compatVersion="0.0.1">
- <vendor>%VendorName%</vendor>
- <copyright>%Copyright%</copyright>
- <license>%License%</license>
- <description>%Description%</description>
- <url>%URL%</url>
- <dependencyList>
- <dependency name="Core" version="2.0.95"/>
- </dependencyList>
-</plugin>
diff --git a/share/qtcreator/templates/wizards/qtcreatorplugin/MyPlugin.pluginspec.in b/share/qtcreator/templates/wizards/qtcreatorplugin/MyPlugin.pluginspec.in
new file mode 100644
index 0000000000..9f2d81fe3f
--- /dev/null
+++ b/share/qtcreator/templates/wizards/qtcreatorplugin/MyPlugin.pluginspec.in
@@ -0,0 +1,10 @@
+<plugin name=\"%PluginName%\" version=\"0.0.1\" compatVersion=\"0.0.1\">
+ <vendor>%VendorName%</vendor>
+ <copyright>%Copyright%</copyright>
+ <license>%License%</license>
+ <description>%Description%</description>
+ <url>%URL%</url>
+ <dependencyList>
+ <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+</plugin>
diff --git a/share/qtcreator/templates/wizards/qtcreatorplugin/myplugin.cpp b/share/qtcreator/templates/wizards/qtcreatorplugin/myplugin.cpp
index 37df03ca12..82df569359 100644
--- a/share/qtcreator/templates/wizards/qtcreatorplugin/myplugin.cpp
+++ b/share/qtcreator/templates/wizards/qtcreatorplugin/myplugin.cpp
@@ -1,4 +1,5 @@
-#include "%PluginName:l%.%CppHeaderSuffix%"
+#include "%PluginName:l%plugin.%CppHeaderSuffix%"
+#include "%PluginName:l%constants.%CppHeaderSuffix%"
#include <QtPlugin>
@@ -15,25 +16,20 @@
#include <QMainWindow>
#include <QMenu>
-namespace {
- const char * const ACTION_ID = "%PluginName%.Action";
- const char * const MENU_ID = "%PluginName%.Menu";
-}
-
using namespace %PluginName%::Internal;
-%PluginName%Impl::%PluginName%Impl()
+%PluginName%Plugin::%PluginName%Plugin()
{
// Create your members
}
-%PluginName%Impl::~%PluginName%Impl()
+%PluginName%Plugin::~%PluginName%Plugin()
{
// Unregister objects from the plugin manager's object pool
// Delete members
}
-bool %PluginName%Impl::initialize(const QStringList &arguments, QString *errorString)
+bool %PluginName%Plugin::initialize(const QStringList &arguments, QString *errorString)
{
// Register objects in the plugin manager's object pool
// Load settings
@@ -47,12 +43,12 @@ bool %PluginName%Impl::initialize(const QStringList &arguments, QString *errorSt
Core::ActionManager *am = Core::ICore::instance()->actionManager();
QAction *action = new QAction(tr("%PluginName% action"), this);
- Core::Command *cmd = am->registerAction(action, ACTION_ID,
+ Core::Command *cmd = am->registerAction(action, Constants::ACTION_ID,
Core::Context(Core::Constants::C_GLOBAL));
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Alt+Meta+A")));
connect(action, SIGNAL(triggered()), this, SLOT(triggerAction()));
- Core::ActionContainer *menu = am->createMenu(MENU_ID);
+ Core::ActionContainer *menu = am->createMenu(Constants::MENU_ID);
menu->menu()->setTitle(tr("%PluginName%"));
menu->addAction(cmd);
am->actionContainer(Core::Constants::M_TOOLS)->addMenu(menu);
@@ -60,14 +56,14 @@ bool %PluginName%Impl::initialize(const QStringList &arguments, QString *errorSt
return true;
}
-void %PluginName%Impl::extensionsInitialized()
+void %PluginName%Plugin::extensionsInitialized()
{
// Retrieve objects from the plugin manager's object pool
// "In the extensionsInitialized method, a plugin can be sure that all
// plugins that depend on it are completely initialized."
}
-ExtensionSystem::IPlugin::ShutdownFlag %PluginName%Impl::aboutToShutdown()
+ExtensionSystem::IPlugin::ShutdownFlag %PluginName%Plugin::aboutToShutdown()
{
// Save settings
// Disconnect from signals that are not needed during shutdown
@@ -75,11 +71,11 @@ ExtensionSystem::IPlugin::ShutdownFlag %PluginName%Impl::aboutToShutdown()
return SynchronousShutdown;
}
-void %PluginName%Impl::triggerAction()
+void %PluginName%Plugin::triggerAction()
{
QMessageBox::information(Core::ICore::instance()->mainWindow(),
tr("Action triggered"),
tr("This is an action from %PluginName%."));
}
-Q_EXPORT_PLUGIN2(%PluginName%, %PluginName%Impl)
+Q_EXPORT_PLUGIN2(%PluginName%, %PluginName%Plugin)
diff --git a/share/qtcreator/templates/wizards/qtcreatorplugin/myplugin.h b/share/qtcreator/templates/wizards/qtcreatorplugin/myplugin.h
index 4e33d3354e..92eaa9d3e8 100644
--- a/share/qtcreator/templates/wizards/qtcreatorplugin/myplugin.h
+++ b/share/qtcreator/templates/wizards/qtcreatorplugin/myplugin.h
@@ -8,13 +8,13 @@
namespace %PluginName% {
namespace Internal {
-class %PluginName%Impl : public ExtensionSystem::IPlugin
+class %PluginName%Plugin : public ExtensionSystem::IPlugin
{
Q_OBJECT
public:
- %PluginName%Impl();
- ~%PluginName%Impl();
+ %PluginName%Plugin();
+ ~%PluginName%Plugin();
bool initialize(const QStringList &arguments, QString *errorString);
void extensionsInitialized();
diff --git a/share/qtcreator/templates/wizards/qtcreatorplugin/myplugin.pro b/share/qtcreator/templates/wizards/qtcreatorplugin/myplugin.pro
index 65e1cefadc..cdd9076242 100644
--- a/share/qtcreator/templates/wizards/qtcreatorplugin/myplugin.pro
+++ b/share/qtcreator/templates/wizards/qtcreatorplugin/myplugin.pro
@@ -5,10 +5,11 @@ DEFINES += %PluginName:u%_LIBRARY
# %PluginName% files
-SOURCES += %PluginName:l%.cpp
+SOURCES += %PluginName:l%plugin.cpp
-HEADERS += %PluginName:l%.h\
- %PluginName:l%_global.h
+HEADERS += %PluginName:l%plugin.h\
+ %PluginName:l%_global.h\
+ %PluginName:l%constants.h
OTHER_FILES = %PluginName%.pluginspec
diff --git a/share/qtcreator/templates/wizards/qtcreatorplugin/mypluginconstants.h b/share/qtcreator/templates/wizards/qtcreatorplugin/mypluginconstants.h
new file mode 100644
index 0000000000..15db6a557c
--- /dev/null
+++ b/share/qtcreator/templates/wizards/qtcreatorplugin/mypluginconstants.h
@@ -0,0 +1,13 @@
+#ifndef %PluginName:u%CONSTANTS_%CppHeaderSuffix:u%
+#define %PluginName:u%CONSTANTS_%CppHeaderSuffix:u%
+
+namespace %PluginName% {
+namespace Constants {
+
+ const char * const ACTION_ID = "%PluginName%.Action";
+ const char * const MENU_ID = "%PluginName%.Menu";
+
+} // namespace %PluginName%
+} // namespace Constants
+
+#endif // %PluginName:u%CONSTANTS_%CppHeaderSuffix:u%
diff --git a/share/qtcreator/templates/wizards/qtcreatorplugin/wizard.xml b/share/qtcreator/templates/wizards/qtcreatorplugin/wizard.xml
index f99c0a2459..5b105818b3 100644
--- a/share/qtcreator/templates/wizards/qtcreatorplugin/wizard.xml
+++ b/share/qtcreator/templates/wizards/qtcreatorplugin/wizard.xml
@@ -47,10 +47,11 @@ leave room for the Qt 4 target page.
<displaycategory>Other Project</displaycategory>
<files>
<file source="myplugin.pro" target="%PluginName:l%.pro" openproject="true"/>
- <file source="MyPlugin.pluginspec" target="%PluginName%.pluginspec" openeditor="true"/>
- <file source="myplugin.h" target="%PluginName:l%.%CppHeaderSuffix%" openeditor="true"/>
- <file source="myplugin.cpp" target="%PluginName:l%.%CppSourceSuffix%" openeditor="true"/>
+ <file source="MyPlugin.pluginspec.in" target="%PluginName%.pluginspec.in" openeditor="true"/>
<file source="myplugin_global.h" target="%PluginName:l%_global.%CppHeaderSuffix%" openeditor="true"/>
+ <file source="mypluginconstants.h" target="%PluginName:l%constants.%CppHeaderSuffix%" openeditor="true"/>
+ <file source="myplugin.h" target="%PluginName:l%plugin.%CppHeaderSuffix%" openeditor="true"/>
+ <file source="myplugin.cpp" target="%PluginName:l%plugin.%CppSourceSuffix%" openeditor="true"/>
</files>
<!-- Create a 2nd wizard page with parameters -->
<fieldpagetitle>Plugin Information</fieldpagetitle>
diff --git a/src/app/Info.plist b/src/app/Info.plist
deleted file mode 100644
index edd65ed5ac..0000000000
--- a/src/app/Info.plist
+++ /dev/null
@@ -1,219 +0,0 @@
-<?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>profile.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>CFBundleTypeIconFile</key>
- <string>prifile.icns</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>CFBundleTypeIconFile</key>
- <string>profile.icns</string>
- <key>CFBundleTypeExtensions</key>
- <array>
- <string>creator</string>
- </array>
- <key>CFBundleTypeName</key>
- <string>Qt Creator Makefile Based Project File</string>
- <key>LSHandlerRank</key>
- <string>Default</string>
- </dict>
- <dict>
- <key>CFBundleTypeRole</key>
- <string>Editor</string>
- <key>CFBundleTypeIconFile</key>
- <string>profile.icns</string>
- <key>CFBundleTypeExtensions</key>
- <array>
- <string>qmlproject</string>
- </array>
- <key>CFBundleTypeName</key>
- <string>Quick Project 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>ui</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>NSHumanReadableCopyright</key>
- <string>(C) 2008-2010 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.qtcreator</string>
- <key>CFBundleVersion</key>
- <string>2.0.95</string>
- <key>CFBundleShortVersionString</key>
- <string>2.0.95</string>
-</dict>
-</plist>
diff --git a/src/app/Info.plist.in b/src/app/Info.plist.in
new file mode 100644
index 0000000000..5f26effe75
--- /dev/null
+++ b/src/app/Info.plist.in
@@ -0,0 +1,219 @@
+<?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>profile.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>CFBundleTypeIconFile</key>
+ <string>prifile.icns</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>CFBundleTypeIconFile</key>
+ <string>profile.icns</string>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>creator</string>
+ </array>
+ <key>CFBundleTypeName</key>
+ <string>Qt Creator Makefile Based Project File</string>
+ <key>LSHandlerRank</key>
+ <string>Default</string>
+ </dict>
+ <dict>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ <key>CFBundleTypeIconFile</key>
+ <string>profile.icns</string>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>qmlproject</string>
+ </array>
+ <key>CFBundleTypeName</key>
+ <string>Quick Project 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>ui</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>NSHumanReadableCopyright</key>
+ <string>(C) 2008-2010 Nokia Corporation</string>
+ <key>CFBundleIconFile</key>
+ <string>$$ICON</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleExecutable</key>
+ <string>Qt Creator</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.nokia.qtcreator</string>
+ <key>CFBundleVersion</key>
+ <string>$$QTCREATOR_VERSION</string>
+ <key>CFBundleShortVersionString</key>
+ <string>$$QTCREATOR_VERSION</string>
+</dict>
+</plist>
diff --git a/src/app/app.pro b/src/app/app.pro
index f46135df84..3b6efe542d 100644
--- a/src/app/app.pro
+++ b/src/app/app.pro
@@ -9,31 +9,28 @@ SOURCES += main.cpp
include(../rpath.pri)
+LIBS *= -l$$qtLibraryName(ExtensionSystem) -l$$qtLibraryName(Aggregation)
+
QT_BREAKPAD_ROOT_PATH = $$(QT_BREAKPAD_ROOT_PATH)
!isEmpty(QT_BREAKPAD_ROOT_PATH) {
include($$QT_BREAKPAD_ROOT_PATH/qtbreakpad.pri)
}
win32 {
- CONFIG(debug, debug|release):LIBS *= -lExtensionSystemd -lAggregationd
- else:LIBS *= -lExtensionSystem -lAggregation
-
RC_FILE = qtcreator.rc
target.path = /bin
INSTALLS += target
} else:macx {
- CONFIG(debug, debug|release):LIBS *= -lExtensionSystem_debug -lAggregation_debug
- else:LIBS *= -lExtensionSystem -lAggregation
LIBS += -framework CoreFoundation
ICON = qtcreator.icns
- QMAKE_INFO_PLIST = Info.plist
FILETYPES.files = profile.icns prifile.icns
FILETYPES.path = Contents/Resources
QMAKE_BUNDLE_DATA += FILETYPES
+ info.input = Info.plist.in
+ info.output = $$IDE_BIN_PATH/../Info.plist
+ QMAKE_SUBSTITUTES = info
} else {
- LIBS *= -lExtensionSystem -lAggregation
-
target.path = /bin
INSTALLS += target
}
-OTHER_FILES += qtcreator.rc Info.plist
+OTHER_FILES += qtcreator.rc Info.plist.in
diff --git a/src/app/main.cpp b/src/app/main.cpp
index e7e01e885b..ece2f8ba33 100644
--- a/src/app/main.cpp
+++ b/src/app/main.cpp
@@ -59,16 +59,17 @@
#include <qtsystemexceptionhandler.h>
#endif
-enum { OptionIndent = 4, DescriptionIndent = 24 };
+enum { OptionIndent = 4, DescriptionIndent = 34 };
static const char *appNameC = "Qt Creator";
static const char *corePluginNameC = "Core";
static const char *fixedOptionsC =
" [OPTION]... [FILE]...\n"
"Options:\n"
-" -help Display this help\n"
-" -version Display program version\n"
-" -client Attempt to connect to already running instance\n";
+" -help Display this help\n"
+" -version Display program version\n"
+" -client Attempt to connect to already running instance\n"
+" -settingspath <path> Override the default path where user settings are stored.\n";
static const char *HELP_OPTION1 = "-h";
static const char *HELP_OPTION2 = "-help";
@@ -76,6 +77,7 @@ static const char *HELP_OPTION3 = "/h";
static const char *HELP_OPTION4 = "--help";
static const char *VERSION_OPTION = "-version";
static const char *CLIENT_OPTION = "-client";
+static const char *SETTINGS_OPTION = "-settingspath";
typedef QList<ExtensionSystem::PluginSpec *> PluginSpecSet;
@@ -202,14 +204,37 @@ int main(int argc, char **argv)
QTranslator qtTranslator;
QString locale = QLocale::system().name();
+ // Manually determine -settingspath command line option
+ // We can't use the regular way of the plugin manager, because that needs to parse pluginspecs
+ // but the settings path can influence which plugins are enabled
+ QString settingsPath;
+ QStringList arguments = app.arguments(); /* adapted arguments list is passed to plugin manager later */
+ QMutableStringListIterator it(arguments);
+ while (it.hasNext()) {
+ const QString &arg = it.next();
+ if (arg == QLatin1String(SETTINGS_OPTION)) {
+ it.remove();
+ if (it.hasNext()) {
+ settingsPath = QDir::fromNativeSeparators(it.next());
+ it.remove();
+ }
+ }
+ }
+ if (!settingsPath.isEmpty())
+ QSettings::setPath(QSettings::IniFormat, QSettings::UserScope, settingsPath);
+
// Must be done before any QSettings class is created
QSettings::setPath(QSettings::IniFormat, QSettings::SystemScope,
QCoreApplication::applicationDirPath()+QLatin1String(SHARE_PATH));
- // keep this in sync with the MainWindow ctor in coreplugin/mainwindow.cpp
- const QSettings settings(QSettings::IniFormat, QSettings::UserScope,
+ // plugin manager takes control of this settings object
+ QSettings *settings = new QSettings(QSettings::IniFormat, QSettings::UserScope,
QLatin1String("Nokia"), QLatin1String("QtCreator"));
- locale = settings.value("General/OverrideLanguage", locale).toString();
+ ExtensionSystem::PluginManager pluginManager;
+ pluginManager.setFileExtension(QLatin1String("pluginspec"));
+ pluginManager.setSettings(settings);
+
+ locale = settings->value("General/OverrideLanguage", locale).toString();
const QString &creatorTrPath = QCoreApplication::applicationDirPath()
+ QLatin1String(SHARE_PATH "/translations");
if (translator.load(QLatin1String("qtcreator_") + locale, creatorTrPath)) {
@@ -237,13 +262,9 @@ int main(int argc, char **argv)
QNetworkProxyFactory::setUseSystemConfiguration(true);
#endif
// Load
- ExtensionSystem::PluginManager pluginManager;
- pluginManager.setFileExtension(QLatin1String("pluginspec"));
-
const QStringList pluginPaths = getPluginPaths();
pluginManager.setPluginPaths(pluginPaths);
- const QStringList arguments = app.arguments();
QMap<QString, QString> foundAppOptions;
if (arguments.size() > 1) {
QMap<QString, bool> appOptions;
diff --git a/src/libs/3rdparty/botan/botan.pri b/src/libs/3rdparty/botan/botan.pri
index b1c924dab6..e2c8f65409 100644
--- a/src/libs/3rdparty/botan/botan.pri
+++ b/src/libs/3rdparty/botan/botan.pri
@@ -1,2 +1,2 @@
INCLUDEPATH *= $$PWD/build
-LIBS *= -l$$qtLibraryTarget(Botan)
+LIBS *= -l$$qtLibraryName(Botan)
diff --git a/src/libs/aggregation/aggregation.pri b/src/libs/aggregation/aggregation.pri
index a6c48c59cb..fc6ddc81f5 100644
--- a/src/libs/aggregation/aggregation.pri
+++ b/src/libs/aggregation/aggregation.pri
@@ -1 +1 @@
-LIBS *= -l$$qtLibraryTarget(Aggregation)
+LIBS *= -l$$qtLibraryName(Aggregation)
diff --git a/src/libs/cplusplus/CppDocument.cpp b/src/libs/cplusplus/CppDocument.cpp
index 53105fd5b4..ef159e9370 100644
--- a/src/libs/cplusplus/CppDocument.cpp
+++ b/src/libs/cplusplus/CppDocument.cpp
@@ -46,6 +46,9 @@
#include <AST.h>
#include <Scope.h>
#include <SymbolVisitor.h>
+#include <NameVisitor.h>
+#include <TypeVisitor.h>
+#include <CoreTypes.h>
#include <QtCore/QByteArray>
#include <QtCore/QBitArray>
@@ -691,11 +694,17 @@ namespace {
class FindMatchingDefinition: public SymbolVisitor
{
Symbol *_declaration;
+ const OperatorNameId *_oper;
QList<Function *> _result;
public:
FindMatchingDefinition(Symbol *declaration)
- : _declaration(declaration) {}
+ : _declaration(declaration)
+ , _oper(0)
+ {
+ if (_declaration->name())
+ _oper = _declaration->name()->asOperatorNameId();
+ }
QList<Function *> result() const { return _result; }
@@ -703,8 +712,15 @@ public:
virtual bool visit(Function *fun)
{
- if (_declaration->identifier()->isEqualTo(fun->identifier()))
- _result.append(fun);
+ if (_oper) {
+ if (const Name *name = fun->unqualifiedName()) {
+ if (_oper->isEqualTo(name))
+ _result.append(fun);
+ }
+ } else if (const Identifier *id = _declaration->identifier()) {
+ if (id->isEqualTo(fun->identifier()))
+ _result.append(fun);
+ }
return false;
}
@@ -718,7 +734,7 @@ public:
Symbol *Snapshot::findMatchingDefinition(Symbol *declaration) const
{
- if (! (declaration && declaration->identifier()))
+ if (!declaration)
return 0;
Document::Ptr thisDocument = document(QString::fromUtf8(declaration->fileName(), declaration->fileNameLength()));
@@ -734,9 +750,19 @@ Symbol *Snapshot::findMatchingDefinition(Symbol *declaration) const
}
foreach (Document::Ptr doc, *this) {
- if (! doc->control()->findIdentifier(declaration->identifier()->chars(),
- declaration->identifier()->size()))
+ const Identifier *id = declaration->identifier();
+ if (id && ! doc->control()->findIdentifier(id->chars(),
+ id->size()))
continue;
+ if (!id) {
+ if (!declaration->name())
+ continue;
+ const OperatorNameId *oper = declaration->name()->asOperatorNameId();
+ if (!oper)
+ continue;
+ if (!doc->control()->findOperatorNameId(oper->kind()))
+ continue;
+ }
FindMatchingDefinition candidates(declaration);
candidates.accept(doc->globalNamespace());
@@ -770,9 +796,8 @@ Symbol *Snapshot::findMatchingDefinition(Symbol *declaration) const
Function *best = 0;
foreach (Function *fun, viableFunctions) {
- if (fun->unqualifiedName()->isEqualTo(declaration->unqualifiedName()))
+ if (! (fun->unqualifiedName() && fun->unqualifiedName()->isEqualTo(declaration->unqualifiedName())))
continue;
-
else if (fun->argumentCount() == declarationTy->argumentCount()) {
if (! best)
best = fun;
diff --git a/src/libs/cplusplus/CppRewriter.cpp b/src/libs/cplusplus/CppRewriter.cpp
index 8c11c03a02..40b360abda 100644
--- a/src/libs/cplusplus/CppRewriter.cpp
+++ b/src/libs/cplusplus/CppRewriter.cpp
@@ -41,11 +41,12 @@
#include <Overview.h>
#include <QtCore/QVarLengthArray>
+#include <QtCore/QRegExp>
#include <QtCore/QDebug>
-using namespace CPlusPlus;
+namespace CPlusPlus {
-class CPlusPlus::Rewrite
+class Rewrite
{
public:
Rewrite(Control *control, SubstitutionEnvironment *env)
@@ -418,18 +419,187 @@ FullySpecifiedType UseQualifiedNames::apply(const Name *name, Rewrite *rewrite)
}
-FullySpecifiedType CPlusPlus::rewriteType(const FullySpecifiedType &type,
- SubstitutionEnvironment *env,
- Control *control)
+FullySpecifiedType rewriteType(const FullySpecifiedType &type,
+ SubstitutionEnvironment *env,
+ Control *control)
{
Rewrite rewrite(control, env);
return rewrite.rewriteType(type);
}
-const Name *CPlusPlus::rewriteName(const Name *name,
- SubstitutionEnvironment *env,
- Control *control)
+const Name *rewriteName(const Name *name,
+ SubstitutionEnvironment *env,
+ Control *control)
{
Rewrite rewrite(control, env);
return rewrite.rewriteName(name);
}
+
+// Simplify complicated STL template types,
+// such as 'std::basic_string<char,std::char_traits<char>,std::allocator<char> >'
+// -> 'std::string' and helpers.
+
+static QString chopConst(QString type)
+{
+ while (1) {
+ if (type.startsWith(QLatin1String("const")))
+ type = type.mid(5);
+ else if (type.startsWith(QLatin1Char(' ')))
+ type = type.mid(1);
+ else if (type.endsWith(QLatin1String("const")))
+ type.chop(5);
+ else if (type.endsWith(QLatin1Char(' ')))
+ type.chop(1);
+ else
+ break;
+ }
+ return type;
+}
+
+static inline QRegExp stdStringRegExp(const QString &charType)
+{
+ QString rc = QLatin1String("basic_string<");
+ rc += charType;
+ rc += QLatin1String(",[ ]?std::char_traits<");
+ rc += charType;
+ rc += QLatin1String(">,[ ]?std::allocator<");
+ rc += charType;
+ rc += QLatin1String("> >");
+ const QRegExp re(rc);
+ Q_ASSERT(re.isValid());
+ return re;
+}
+
+// Simplify string types in a type
+// 'std::set<std::basic_string<char... > >' -> std::set<std::string>'
+static inline void simplifyStdString(const QString &charType, const QString &replacement,
+ QString *type)
+{
+ QRegExp stringRegexp = stdStringRegExp(charType);
+ const int replacementSize = replacement.size();
+ for (int pos = 0; pos < type->size(); ) {
+ // Check next match
+ const int matchPos = stringRegexp.indexIn(*type, pos);
+ if (matchPos == -1)
+ break;
+ const int matchedLength = stringRegexp.matchedLength();
+ type->replace(matchPos, matchedLength, replacement);
+ pos = matchPos + replacementSize;
+ // If we were inside an 'allocator<std::basic_string..char > >'
+ // kill the following blank -> 'allocator<std::string>'
+ if (pos + 1 < type->size() && type->at(pos) == QLatin1Char(' ')
+ && type->at(pos + 1) == QLatin1Char('>'))
+ type->remove(pos, 1);
+ }
+}
+
+// Fix 'std::allocator<std::string >' -> 'std::allocator<std::string>',
+// which can happen when replacing/simplifying
+static inline QString fixNestedTemplates(QString s)
+{
+ const int size = s.size();
+ if (size > 3
+ && s.at(size - 1) == QLatin1Char('>')
+ && s.at(size - 2) == QLatin1Char(' ')
+ && s.at(size - 3) != QLatin1Char('>'))
+ s.remove(size - 2, 1);
+ return s;
+}
+
+CPLUSPLUS_EXPORT QString simplifySTLType(const QString &typeIn)
+{
+ QString type = typeIn;
+ if (type.startsWith("class ")) // MSVC prepends class,struct
+ type.remove(0, 6);
+ if (type.startsWith("struct "))
+ type.remove(0, 7);
+
+ type.replace(QLatin1Char('*'), QLatin1Char('@'));
+
+ for (int i = 0; i < 10; ++i) {
+ int start = type.indexOf("std::allocator<");
+ if (start == -1)
+ break;
+ // search for matching '>'
+ int pos;
+ int level = 0;
+ for (pos = start + 12; pos < type.size(); ++pos) {
+ int c = type.at(pos).unicode();
+ if (c == '<') {
+ ++level;
+ } else if (c == '>') {
+ --level;
+ if (level == 0)
+ break;
+ }
+ }
+ const QString alloc = fixNestedTemplates(type.mid(start, pos + 1 - start).trimmed());
+ const QString inner = fixNestedTemplates(alloc.mid(15, alloc.size() - 16).trimmed());
+ if (inner == QLatin1String("char")) { // std::string
+ simplifyStdString(QLatin1String("char"), QLatin1String("string"), &type);
+ } else if (inner == QLatin1String("wchar_t")) { // std::wstring
+ simplifyStdString(QLatin1String("wchar_t"), QLatin1String("wstring"), &type);
+ } else if (inner == QLatin1String("unsigned short")) { // std::wstring/MSVC
+ simplifyStdString(QLatin1String("unsigned short"), QLatin1String("wstring"), &type);
+ }
+ // std::vector, std::deque, std::list
+ const QRegExp re1(QString::fromLatin1("(vector|list|deque)<%1, ?%2\\s*>").arg(inner, alloc));
+ Q_ASSERT(re1.isValid());
+ if (re1.indexIn(type) != -1)
+ type.replace(re1.cap(0), QString::fromLatin1("%1<%2>").arg(re1.cap(1), inner));
+
+ // std::stack
+ QRegExp stackRE(QString::fromLatin1("stack<%1, ?std::deque<%2> >").arg(inner, inner));
+ stackRE.setMinimal(true);
+ Q_ASSERT(stackRE.isValid());
+ if (stackRE.indexIn(type) != -1)
+ type.replace(stackRE.cap(0), QString::fromLatin1("stack<%1>").arg(inner));
+
+ // std::set
+ QRegExp setRE(QString::fromLatin1("set<%1, ?std::less<%2>, ?%3\\s*>").arg(inner, inner, alloc));
+ setRE.setMinimal(true);
+ Q_ASSERT(setRE.isValid());
+ if (setRE.indexIn(type) != -1)
+ type.replace(setRE.cap(0), QString::fromLatin1("set<%1>").arg(inner));
+
+ // std::map
+ if (inner.startsWith("std::pair<")) {
+ // search for outermost ',', split key and value
+ int pos;
+ int level = 0;
+ for (pos = 10; pos < inner.size(); ++pos) {
+ int c = inner.at(pos).unicode();
+ if (c == '<')
+ ++level;
+ else if (c == '>')
+ --level;
+ else if (c == ',' && level == 0)
+ break;
+ }
+ const QString key = chopConst(inner.mid(10, pos - 10));
+ // Get value: MSVC: 'pair<a const ,b>', gcc: 'pair<const a, b>'
+ if (inner.at(++pos) == QLatin1Char(' '))
+ pos++;
+ QString value = inner.mid(pos, inner.size() - pos - 1).trimmed();
+ QRegExp mapRE1(QString("map<%1, ?%2, ?std::less<%3 ?>, ?%4\\s*>")
+ .arg(key, value, key, alloc));
+ mapRE1.setMinimal(true);
+ Q_ASSERT(mapRE1.isValid());
+ if (mapRE1.indexIn(type) != -1) {
+ type.replace(mapRE1.cap(0), QString("map<%1, %2>").arg(key, value));
+ } else {
+ QRegExp mapRE2(QString("map<const %1, ?%2, ?std::less<const %3>, ?%4\\s*>")
+ .arg(key, value, key, alloc));
+ mapRE2.setMinimal(true);
+ if (mapRE2.indexIn(type) != -1) {
+ type.replace(mapRE2.cap(0), QString("map<const %1, %2>").arg(key, value));
+ }
+ }
+ }
+ }
+ type.replace(QLatin1Char('@'), QLatin1Char('*'));
+ type.replace(QLatin1String(" >"), QLatin1String(">"));
+ return type;
+}
+
+} // namespace CPlusPlus
diff --git a/src/libs/cplusplus/CppRewriter.h b/src/libs/cplusplus/CppRewriter.h
index 93326ffee3..fa5264310c 100644
--- a/src/libs/cplusplus/CppRewriter.h
+++ b/src/libs/cplusplus/CppRewriter.h
@@ -108,6 +108,11 @@ CPLUSPLUS_EXPORT const Name *rewriteName(const Name *name,
SubstitutionEnvironment *env,
Control *control);
+// Simplify complicated STL template types, such as
+// 'std::basic_string<char,std::char_traits<char>,std::allocator<char> > '->
+// 'std::string'.
+CPLUSPLUS_EXPORT QString simplifySTLType(const QString &typeIn);
+
} // end of namespace CPlusPlus
#endif
diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp
index d14413e5b5..cdf95bc9dc 100644
--- a/src/libs/cplusplus/LookupContext.cpp
+++ b/src/libs/cplusplus/LookupContext.cpp
@@ -460,6 +460,8 @@ void ClassOrNamespace::lookup_helper(const Name *name, ClassOrNamespace *binding
foreach (Symbol *s, binding->symbols()) {
if (s->isFriend())
continue;
+ else if (s->isUsingNamespaceDirective())
+ continue;
if (Scope *scope = s->asScope()) {
if (Class *klass = scope->asClass()) {
@@ -513,6 +515,8 @@ void CreateBindings::lookupInScope(const Name *name, Scope *scope,
for (Symbol *s = scope->find(id); s; s = s->next()) {
if (s->isFriend())
continue; // skip friends
+ else if (s->isUsingNamespaceDirective())
+ continue; // skip using namespace directives
else if (! id->isEqualTo(s->identifier()))
continue;
else if (s->name()->isQualifiedNameId())
diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp
index 890ee12c3d..cad552f923 100644
--- a/src/libs/cplusplus/ResolveExpression.cpp
+++ b/src/libs/cplusplus/ResolveExpression.cpp
@@ -79,7 +79,8 @@ ResolveExpression::ResolveExpression(const LookupContext &context)
: ASTVisitor(context.expressionDocument()->translationUnit()),
_scope(0),
_context(context),
- bind(context.expressionDocument()->translationUnit())
+ bind(context.expressionDocument()->translationUnit()),
+ _reference(false)
{ }
ResolveExpression::~ResolveExpression()
@@ -88,19 +89,26 @@ ResolveExpression::~ResolveExpression()
QList<LookupItem> ResolveExpression::operator()(ExpressionAST *ast, Scope *scope)
{ return resolve(ast, scope); }
-QList<LookupItem> ResolveExpression::resolve(ExpressionAST *ast, Scope *scope)
+QList<LookupItem> ResolveExpression::reference(ExpressionAST *ast, Scope *scope)
+{ return resolve(ast, scope, true); }
+
+QList<LookupItem> ResolveExpression::resolve(ExpressionAST *ast, Scope *scope, bool ref)
{
if (! scope)
return QList<LookupItem>();
- Scope *previousVisibleSymbol = _scope;
- _scope = scope;
- const QList<LookupItem> result = resolve(ast);
- _scope = previousVisibleSymbol;
+ std::swap(_scope, scope);
+ std::swap(_reference, ref);
+
+ const QList<LookupItem> result = expression(ast);
+
+ std::swap(_reference, ref);
+ std::swap(_scope, scope);
+
return result;
}
-QList<LookupItem> ResolveExpression::resolve(ExpressionAST *ast)
+QList<LookupItem> ResolveExpression::expression(ExpressionAST *ast)
{
const QList<LookupItem> previousResults = switchResults(QList<LookupItem>());
accept(ast);
@@ -445,27 +453,18 @@ bool ResolveExpression::visit(ConversionFunctionIdAST *)
return false;
}
-bool ResolveExpression::maybeValidPrototype(Function *funTy, unsigned actualArgumentCount) const
+bool ResolveExpression::maybeValidPrototype(Function *funTy, unsigned actualArgumentCount)
{
- unsigned minNumberArguments = 0;
-
- for (; minNumberArguments < funTy->argumentCount(); ++minNumberArguments) {
- Argument *arg = funTy->argumentAt(minNumberArguments)->asArgument();
-
- if (arg->hasInitializer())
- break;
- }
-
- if (actualArgumentCount < minNumberArguments) {
- // not enough arguments.
- return false;
-
- } else if (! funTy->isVariadic() && actualArgumentCount > funTy->argumentCount()) {
- // too many arguments.
- return false;
- }
+ return funTy->maybeValidPrototype(actualArgumentCount);
+}
- return true;
+bool ResolveExpression::implicitConversion(const FullySpecifiedType &sourceTy, const FullySpecifiedType &targetTy) const
+{
+ if (sourceTy.isEqualTo(targetTy))
+ return true;
+ else if (sourceTy.simplified().isEqualTo(targetTy.simplified()))
+ return true;
+ return false;
}
bool ResolveExpression::visit(CallAST *ast)
@@ -473,14 +472,55 @@ bool ResolveExpression::visit(CallAST *ast)
const QList<LookupItem> baseResults = resolve(ast->base_expression, _scope);
// Compute the types of the actual arguments.
- int actualArgumentCount = 0;
+ unsigned actualArgumentCount = 0;
- //QList< QList<Result> > arguments;
+ QList< QList<LookupItem> > arguments;
for (ExpressionListAST *exprIt = ast->expression_list; exprIt; exprIt = exprIt->next) {
- //arguments.append(resolve(exprIt->expression));
+ if (_reference)
+ arguments.append(resolve(exprIt->value, _scope));
+
++actualArgumentCount;
}
+ if (_reference) {
+ _results.clear();
+ foreach (const LookupItem &base, baseResults) {
+ if (Function *funTy = base.type()->asFunctionType()) {
+ if (! maybeValidPrototype(funTy, actualArgumentCount))
+ continue;
+
+ int score = 0;
+
+ for (unsigned i = 0; i < funTy->argumentCount(); ++i) {
+ const FullySpecifiedType formalTy = funTy->argumentAt(i)->type();
+
+ FullySpecifiedType actualTy;
+ if (i < unsigned(arguments.size())) {
+ const QList<LookupItem> actual = arguments.at(i);
+ if (actual.isEmpty())
+ continue;
+
+ actualTy = actual.first().type();
+ } else
+ actualTy = formalTy;
+
+ if (implicitConversion(actualTy, formalTy))
+ ++score;
+ }
+
+ if (score)
+ _results.prepend(base);
+ else
+ _results.append(base);
+ }
+ }
+
+ if (_results.isEmpty())
+ _results = baseResults;
+
+ return false;
+ }
+
const Name *functionCallOp = control()->operatorNameId(OperatorNameId::FunctionCallOp);
foreach (const LookupItem &result, baseResults) {
@@ -517,7 +557,7 @@ bool ResolveExpression::visit(CallAST *ast)
bool ResolveExpression::visit(ArrayAccessAST *ast)
{
const QList<LookupItem> baseResults = resolve(ast->base_expression, _scope);
- const QList<LookupItem> indexResults = resolve(ast->expression);
+ const QList<LookupItem> indexResults = resolve(ast->expression, _scope);
const Name *arrayAccessOp = control()->operatorNameId(OperatorNameId::ArrayAccessOp);
@@ -713,7 +753,7 @@ bool ResolveExpression::visit(PostIncrDecrAST *ast)
bool ResolveExpression::visit(ObjCMessageExpressionAST *ast)
{
- const QList<LookupItem> receiverResults = resolve(ast->receiver_expression);
+ const QList<LookupItem> receiverResults = resolve(ast->receiver_expression, _scope);
foreach (const LookupItem &result, receiverResults) {
FullySpecifiedType ty = result.type().simplified();
diff --git a/src/libs/cplusplus/ResolveExpression.h b/src/libs/cplusplus/ResolveExpression.h
index 49b79e9e38..1c0215462c 100644
--- a/src/libs/cplusplus/ResolveExpression.h
+++ b/src/libs/cplusplus/ResolveExpression.h
@@ -49,7 +49,8 @@ public:
virtual ~ResolveExpression();
QList<LookupItem> operator()(ExpressionAST *ast, Scope *scope);
- QList<LookupItem> resolve(ExpressionAST *ast, Scope *scope);
+ QList<LookupItem> resolve(ExpressionAST *ast, Scope *scope, bool ref = false);
+ QList<LookupItem> reference(ExpressionAST *ast, Scope *scope);
ClassOrNamespace *baseExpression(const QList<LookupItem> &baseResults,
int accessOp,
@@ -60,7 +61,7 @@ public:
protected:
ClassOrNamespace *findClass(const FullySpecifiedType &ty, Scope *scope) const;
- QList<LookupItem> resolve(ExpressionAST *ast);
+ QList<LookupItem> expression(ExpressionAST *ast);
QList<LookupItem> switchResults(const QList<LookupItem> &symbols);
FullySpecifiedType instantiate(const Name *className, Symbol *candidate) const;
@@ -73,7 +74,8 @@ protected:
void addResults(const QList<Symbol *> &symbols);
void addResults(const QList<LookupItem> &items);
- bool maybeValidPrototype(Function *funTy, unsigned actualArgumentCount) const;
+ static bool maybeValidPrototype(Function *funTy, unsigned actualArgumentCount);
+ bool implicitConversion(const FullySpecifiedType &sourceTy, const FullySpecifiedType &targetTy) const;
using ASTVisitor::visit;
@@ -123,6 +125,7 @@ private:
LookupContext _context;
Bind bind;
QList<LookupItem> _results;
+ bool _reference;
};
} // end of namespace CPlusPlus
diff --git a/src/libs/cplusplus/SnapshotSymbolVisitor.cpp b/src/libs/cplusplus/SnapshotSymbolVisitor.cpp
new file mode 100644
index 0000000000..7962d3f928
--- /dev/null
+++ b/src/libs/cplusplus/SnapshotSymbolVisitor.cpp
@@ -0,0 +1,60 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "SnapshotSymbolVisitor.h"
+#include <Symbols.h>
+
+using namespace CPlusPlus;
+
+SnapshotSymbolVisitor::SnapshotSymbolVisitor(const Snapshot &snapshot)
+ : _snapshot(snapshot)
+{
+}
+
+void SnapshotSymbolVisitor::accept(Document::Ptr doc)
+{
+ QSet<QString> processed;
+ accept(doc, &processed);
+}
+
+void SnapshotSymbolVisitor::accept(Document::Ptr doc, QSet<QString> *processed)
+{
+ if (doc && doc->globalNamespace() && ! processed->contains(doc->fileName())) {
+ processed->insert(doc->fileName());
+
+ foreach (const Document::Include &i, doc->includes()) {
+ if (Document::Ptr incl = _snapshot.document(i.fileName()))
+ accept(incl, processed);
+ }
+
+ std::swap(_document, doc);
+ accept(_document->globalNamespace());
+ std::swap(_document, doc);
+ }
+}
diff --git a/src/libs/cplusplus/SnapshotSymbolVisitor.h b/src/libs/cplusplus/SnapshotSymbolVisitor.h
new file mode 100644
index 0000000000..13d639aea1
--- /dev/null
+++ b/src/libs/cplusplus/SnapshotSymbolVisitor.h
@@ -0,0 +1,57 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 CPLUSPLUS_SNAPSHOTSYMBOLVISITOR_H
+#define CPLUSPLUS_SNAPSHOTSYMBOLVISITOR_H
+
+#include "CppDocument.h"
+#include <SymbolVisitor.h>
+#include <QtCore/QSet>
+
+namespace CPlusPlus {
+
+class CPLUSPLUS_EXPORT SnapshotSymbolVisitor : public CPlusPlus::SymbolVisitor
+{
+public:
+ SnapshotSymbolVisitor(const Snapshot &snapshot);
+
+ void accept(Document::Ptr doc);
+ using SymbolVisitor::accept;
+
+protected:
+ void accept(Document::Ptr doc, QSet<QString> *processed);
+
+private:
+ Snapshot _snapshot;
+ Document::Ptr _document;
+};
+
+} // end of namespace CPlusPlus
+
+#endif // CPLUSPLUS_SNAPSHOTSYMBOLVISITOR_H
diff --git a/src/libs/cplusplus/SymbolNameVisitor.cpp b/src/libs/cplusplus/SymbolNameVisitor.cpp
new file mode 100644
index 0000000000..c384e36dcd
--- /dev/null
+++ b/src/libs/cplusplus/SymbolNameVisitor.cpp
@@ -0,0 +1,55 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "SymbolNameVisitor.h"
+#include <Symbols.h>
+#include <Names.h>
+
+using namespace CPlusPlus;
+
+SymbolNameVisitor::SymbolNameVisitor()
+ : _symbol(0)
+{
+}
+
+void SymbolNameVisitor::accept(Symbol *symbol)
+{
+ if (symbol) {
+ if (Scope *scope = symbol->enclosingScope())
+ accept(scope);
+
+ if (! symbol->isTemplate()) {
+ if (const Name *name = symbol->name()) {
+ std::swap(_symbol, symbol);
+ accept(name);
+ std::swap(_symbol, symbol);
+ }
+ }
+ }
+}
diff --git a/src/libs/cplusplus/SymbolNameVisitor.h b/src/libs/cplusplus/SymbolNameVisitor.h
new file mode 100644
index 0000000000..8b41be18c9
--- /dev/null
+++ b/src/libs/cplusplus/SymbolNameVisitor.h
@@ -0,0 +1,52 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 CPLUSPLUS_SYMBOLNAMEVISITOR_H
+#define CPLUSPLUS_SYMBOLNAMEVISITOR_H
+
+#include <NameVisitor.h>
+
+namespace CPlusPlus {
+
+class CPLUSPLUS_EXPORT SymbolNameVisitor : public CPlusPlus::NameVisitor
+{
+public:
+ SymbolNameVisitor();
+
+ void accept(Symbol *symbol);
+
+ using NameVisitor::accept;
+
+private:
+ Symbol *_symbol;
+};
+
+} // end of namespace CPlusPlus
+
+#endif // CPLUSPLUS_SYMBOLNAMEVISITOR_H
diff --git a/src/libs/cplusplus/TypeOfExpression.cpp b/src/libs/cplusplus/TypeOfExpression.cpp
index adf84ae41d..7a268c4402 100644
--- a/src/libs/cplusplus/TypeOfExpression.cpp
+++ b/src/libs/cplusplus/TypeOfExpression.cpp
@@ -88,6 +88,20 @@ QList<LookupItem> TypeOfExpression::operator()(const QString &expression,
scope);
}
+QList<LookupItem> TypeOfExpression::reference(const QString &expression,
+ Scope *scope,
+ PreprocessMode mode)
+{
+ QString code = expression;
+
+ if (mode == Preprocess)
+ code = preprocessedExpression(expression);
+
+ Document::Ptr expressionDoc = documentForExpression(code);
+ expressionDoc->check();
+ return reference(extractExpressionAST(expressionDoc), expressionDoc, scope);
+}
+
QList<LookupItem> TypeOfExpression::operator()(ExpressionAST *expression,
Document::Ptr document,
Scope *scope)
@@ -108,6 +122,26 @@ QList<LookupItem> TypeOfExpression::operator()(ExpressionAST *expression,
return items;
}
+QList<LookupItem> TypeOfExpression::reference(ExpressionAST *expression,
+ Document::Ptr document,
+ Scope *scope)
+{
+ m_ast = expression;
+
+ m_scope = scope;
+
+ m_lookupContext = LookupContext(document, m_thisDocument, m_snapshot);
+ m_lookupContext.setBindings(m_bindings);
+
+ ResolveExpression resolve(m_lookupContext);
+ const QList<LookupItem> items = resolve.reference(m_ast, scope);
+
+ if (! m_bindings)
+ m_lookupContext = resolve.context();
+
+ return items;
+}
+
QString TypeOfExpression::preprocess(const QString &expression) const
{
return preprocessedExpression(expression);
@@ -183,3 +217,4 @@ QString TypeOfExpression::preprocessedExpression(const QString &expression) cons
const QByteArray preprocessedCode = preproc("<expression>", code);
return QString::fromUtf8(preprocessedCode.constData(), preprocessedCode.size());
}
+
diff --git a/src/libs/cplusplus/TypeOfExpression.h b/src/libs/cplusplus/TypeOfExpression.h
index 6ca59f690e..4852baa152 100644
--- a/src/libs/cplusplus/TypeOfExpression.h
+++ b/src/libs/cplusplus/TypeOfExpression.h
@@ -102,6 +102,14 @@ public:
Document::Ptr document,
Scope *scope);
+ QList<LookupItem> reference(const QString &expression,
+ Scope *scope,
+ PreprocessMode mode = NoPreprocess);
+
+ QList<LookupItem> reference(ExpressionAST *expression,
+ Document::Ptr document,
+ Scope *scope);
+
QString preprocess(const QString &expression) const;
/**
diff --git a/src/libs/cplusplus/cplusplus-lib.pri b/src/libs/cplusplus/cplusplus-lib.pri
index 2a718d5712..395636a23c 100644
--- a/src/libs/cplusplus/cplusplus-lib.pri
+++ b/src/libs/cplusplus/cplusplus-lib.pri
@@ -37,6 +37,8 @@ HEADERS += \
$$PWD/LookupContext.h \
$$PWD/ASTParent.h \
$$PWD/ASTPath.h \
+ $$PWD/SnapshotSymbolVisitor.h \
+ $$PWD/SymbolNameVisitor.h \
$$PWD/DeprecatedGenTemplateInstance.h \
$$PWD/FindUsages.h \
$$PWD/DependencyTable.h \
@@ -63,6 +65,8 @@ SOURCES += \
$$PWD/LookupContext.cpp \
$$PWD/ASTParent.cpp \
$$PWD/ASTPath.cpp \
+ $$PWD/SnapshotSymbolVisitor.cpp \
+ $$PWD/SymbolNameVisitor.cpp \
$$PWD/DeprecatedGenTemplateInstance.cpp \
$$PWD/FindUsages.cpp \
$$PWD/DependencyTable.cpp \
diff --git a/src/libs/cplusplus/cplusplus.pri b/src/libs/cplusplus/cplusplus.pri
index 50a03111e9..85cb972095 100644
--- a/src/libs/cplusplus/cplusplus.pri
+++ b/src/libs/cplusplus/cplusplus.pri
@@ -1,3 +1,5 @@
INCLUDEPATH += $$IDE_SOURCE_TREE/src/shared/cplusplus
DEPENDPATH += $$IDE_SOURCE_TREE/src/shared/cplusplus
-LIBS *= -l$$qtLibraryTarget(CPlusPlus)
+INCLUDEPATH += $$IDE_SOURCE_TREE/src/libs/cplusplus
+DEPENDPATH += $$IDE_SOURCE_TREE/src/libs/cplusplus
+LIBS *= -l$$qtLibraryName(CPlusPlus)
diff --git a/src/libs/extensionsystem/extensionsystem.pri b/src/libs/extensionsystem/extensionsystem.pri
index 43855eb168..4c7641b9cb 100644
--- a/src/libs/extensionsystem/extensionsystem.pri
+++ b/src/libs/extensionsystem/extensionsystem.pri
@@ -1,3 +1,3 @@
include(extensionsystem_dependencies.pri)
-LIBS *= -l$$qtLibraryTarget(ExtensionSystem)
+LIBS *= -l$$qtLibraryName(ExtensionSystem)
diff --git a/src/libs/extensionsystem/iplugin.cpp b/src/libs/extensionsystem/iplugin.cpp
index 728f23c583..a15408a1d9 100644
--- a/src/libs/extensionsystem/iplugin.cpp
+++ b/src/libs/extensionsystem/iplugin.cpp
@@ -266,7 +266,7 @@
IPlugin::SynchronousShutdown.
Returns IPlugin::AsynchronousShutdown if the plugin needs to perform
- asynchonous actions before performing the shutdown.
+ asynchronous actions before performing the shutdown.
\sa asynchronousShutdownFinished()
*/
diff --git a/src/libs/extensionsystem/pluginmanager.cpp b/src/libs/extensionsystem/pluginmanager.cpp
index 63a8bb00fd..7373e57bf3 100644
--- a/src/libs/extensionsystem/pluginmanager.cpp
+++ b/src/libs/extensionsystem/pluginmanager.cpp
@@ -315,9 +315,19 @@ void PluginManager::setFileExtension(const QString &extension)
d->extension = extension;
}
-void PluginManager::loadSettings()
+void PluginManager::setSettings(QSettings *settings)
{
- d->loadSettings();
+ d->setSettings(settings);
+}
+
+QSettings *PluginManager::settings() const
+{
+ return d->settings;
+}
+
+void PluginManager::readSettings()
+{
+ d->readSettings();
}
void PluginManager::writeSettings()
@@ -621,6 +631,19 @@ PluginSpec *PluginManagerPrivate::createSpec()
}
/*!
+ \fn void PluginManagerPrivate::setSettings(QSettings *settings)
+ \internal
+*/
+void PluginManagerPrivate::setSettings(QSettings *s)
+{
+ if (settings)
+ delete settings;
+ settings = s;
+ if (settings)
+ settings->setParent(this);
+}
+
+/*!
\fn PluginSpecPrivate *PluginManagerPrivate::privateSpec(PluginSpec *spec)
\internal
*/
@@ -637,6 +660,7 @@ PluginManagerPrivate::PluginManagerPrivate(PluginManager *pluginManager) :
extension(QLatin1String("xml")),
m_profileElapsedMS(0),
m_profilingVerbosity(0),
+ settings(0),
q(pluginManager)
{
}
@@ -658,9 +682,8 @@ PluginManagerPrivate::~PluginManagerPrivate()
*/
void PluginManagerPrivate::writeSettings()
{
- QSettings settings(QSettings::IniFormat, QSettings::UserScope,
- QLatin1String("Nokia"), QLatin1String("QtCreator"));
-
+ if (!settings)
+ return;
QStringList tempDisabledPlugins;
QStringList tempForceEnabledPlugins;
foreach(PluginSpec *spec, pluginSpecs) {
@@ -670,21 +693,20 @@ void PluginManagerPrivate::writeSettings()
tempForceEnabledPlugins.append(spec->name());
}
- settings.setValue(QLatin1String(C_IGNORED_PLUGINS), tempDisabledPlugins);
- settings.setValue(QLatin1String(C_FORCEENABLED_PLUGINS), tempForceEnabledPlugins);
+ settings->setValue(QLatin1String(C_IGNORED_PLUGINS), tempDisabledPlugins);
+ settings->setValue(QLatin1String(C_FORCEENABLED_PLUGINS), tempForceEnabledPlugins);
}
/*!
- \fn void PluginManagerPrivate::loadSettings()
+ \fn void PluginManagerPrivate::readSettings()
\internal
*/
-void PluginManagerPrivate::loadSettings()
+void PluginManagerPrivate::readSettings()
{
- const QSettings settings(QSettings::IniFormat, QSettings::UserScope,
- QLatin1String("Nokia"), QLatin1String("QtCreator"));
-
- disabledPlugins = settings.value(QLatin1String(C_IGNORED_PLUGINS)).toStringList();
- forceEnabledPlugins = settings.value(QLatin1String(C_FORCEENABLED_PLUGINS)).toStringList();
+ if (!settings)
+ return;
+ disabledPlugins = settings->value(QLatin1String(C_IGNORED_PLUGINS)).toStringList();
+ forceEnabledPlugins = settings->value(QLatin1String(C_FORCEENABLED_PLUGINS)).toStringList();
}
/*!
@@ -945,7 +967,7 @@ void PluginManagerPrivate::loadPlugin(PluginSpec *spec, PluginSpec::State destSt
void PluginManagerPrivate::setPluginPaths(const QStringList &paths)
{
pluginPaths = paths;
- loadSettings();
+ readSettings();
readPluginPaths();
}
diff --git a/src/libs/extensionsystem/pluginmanager.h b/src/libs/extensionsystem/pluginmanager.h
index 50ee5cbee1..ee70ecb9bd 100644
--- a/src/libs/extensionsystem/pluginmanager.h
+++ b/src/libs/extensionsystem/pluginmanager.h
@@ -43,6 +43,7 @@
QT_BEGIN_NAMESPACE
class QTextStream;
+class QSettings;
QT_END_NAMESPACE
namespace ExtensionSystem {
@@ -105,7 +106,9 @@ public:
QString fileExtension() const;
// Settings
- void loadSettings();
+ void setSettings(QSettings *settings);
+ QSettings *settings() const;
+ void readSettings();
void writeSettings();
// command line arguments
diff --git a/src/libs/extensionsystem/pluginmanager_p.h b/src/libs/extensionsystem/pluginmanager_p.h
index 5a32d69546..8955fc1419 100644
--- a/src/libs/extensionsystem/pluginmanager_p.h
+++ b/src/libs/extensionsystem/pluginmanager_p.h
@@ -45,6 +45,7 @@
QT_BEGIN_NAMESPACE
class QTime;
+class QSettings;
QT_END_NAMESPACE
namespace ExtensionSystem {
@@ -76,7 +77,8 @@ public:
void resolveDependencies();
void initProfiling();
void profilingReport(const char *what, const PluginSpec *spec = 0);
- void loadSettings();
+ void setSettings(QSettings *settings);
+ void readSettings();
void writeSettings();
void disablePluginIndirectly(PluginSpec *spec);
@@ -95,6 +97,7 @@ public:
QScopedPointer<QTime> m_profileTimer;
int m_profileElapsedMS;
unsigned m_profilingVerbosity;
+ QSettings *settings;
// Look in argument descriptions of the specs for the option.
PluginSpec *pluginForOption(const QString &option, bool *requiresArgument) const;
diff --git a/src/libs/extensionsystem/pluginview.cpp b/src/libs/extensionsystem/pluginview.cpp
index 8294b5a419..38d9d8b824 100644
--- a/src/libs/extensionsystem/pluginview.cpp
+++ b/src/libs/extensionsystem/pluginview.cpp
@@ -71,8 +71,8 @@
using namespace ExtensionSystem;
-Q_DECLARE_METATYPE(ExtensionSystem::PluginSpec*);
-Q_DECLARE_METATYPE(ExtensionSystem::PluginCollection*);
+Q_DECLARE_METATYPE(ExtensionSystem::PluginSpec*)
+Q_DECLARE_METATYPE(ExtensionSystem::PluginCollection*)
/*!
\fn PluginView::PluginView(PluginManager *manager, QWidget *parent)
diff --git a/src/libs/extensionsystem/test/auto/auto.pro b/src/libs/extensionsystem/test/auto/auto.pro
deleted file mode 100644
index 2dd6400212..0000000000
--- a/src/libs/extensionsystem/test/auto/auto.pro
+++ /dev/null
@@ -1,3 +0,0 @@
-TEMPLATE = subdirs
-SUBDIRS = pluginmanager pluginspec
-
diff --git a/src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin1/plugin1.cpp b/src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin1/plugin1.cpp
deleted file mode 100644
index 1e78a51a0a..0000000000
--- a/src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin1/plugin1.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#include "plugin1.h"
-
-#include <QtCore/qplugin.h>
-
-using namespace Plugin1;
-
-MyPlugin1::MyPlugin1()
-{
-}
-
-bool MyPlugin1::initialize(const QStringList &arguments, QString *errorString)
-{
- Q_UNUSED(arguments)
- Q_UNUSED(errorString)
- return true;
-}
-
-void MyPlugin1::extensionsInitialized()
-{
-}
-
-Q_EXPORT_PLUGIN(MyPlugin1)
-
diff --git a/src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin1/plugin1.pro b/src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin1/plugin1.pro
deleted file mode 100644
index 4181188287..0000000000
--- a/src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin1/plugin1.pro
+++ /dev/null
@@ -1,8 +0,0 @@
-TEMPLATE = lib
-TARGET = plugin1
-
-SOURCES += plugin1.cpp
-HEADERS += plugin1.h
-
-include(../../../../extensionsystem_test.pri)
-
diff --git a/src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin2/plugin2.pro b/src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin2/plugin2.pro
deleted file mode 100644
index 58798b54f1..0000000000
--- a/src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin2/plugin2.pro
+++ /dev/null
@@ -1,8 +0,0 @@
-TEMPLATE = lib
-TARGET = plugin2
-
-SOURCES += plugin2.cpp
-HEADERS += plugin2.h
-
-include(../../../../extensionsystem_test.pri)
-
diff --git a/src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin3/plugin3.pro b/src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin3/plugin3.pro
deleted file mode 100644
index f601f06162..0000000000
--- a/src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin3/plugin3.pro
+++ /dev/null
@@ -1,8 +0,0 @@
-TEMPLATE = lib
-TARGET = plugin3
-
-SOURCES += plugin3.cpp
-HEADERS += plugin3.h
-
-include(../../../../extensionsystem_test.pri)
-
diff --git a/src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin1/plugin1.pro b/src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin1/plugin1.pro
deleted file mode 100644
index 9101770f9a..0000000000
--- a/src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin1/plugin1.pro
+++ /dev/null
@@ -1,15 +0,0 @@
-TEMPLATE = lib
-TARGET = plugin1
-
-SOURCES += plugin1.cpp
-HEADERS += plugin1.h
-
-include(../../../../extensionsystem_test.pri)
-
-LIBS += -L$${PWD}/../plugin2 -L$${PWD}/../plugin3 -lplugin2 -lplugin3
-
-macx {
-} else:unix {
- QMAKE_RPATHDIR += $${PWD}/../plugin2
- QMAKE_RPATHDIR += $${PWD}/../plugin3
-}
diff --git a/src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin2/plugin2.pro b/src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin2/plugin2.pro
deleted file mode 100644
index a80f4a5c76..0000000000
--- a/src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin2/plugin2.pro
+++ /dev/null
@@ -1,12 +0,0 @@
-TEMPLATE = lib
-TARGET = plugin2
-
-SOURCES += plugin2.cpp
-HEADERS += plugin2.h
-
-include(../../../../extensionsystem_test.pri)
-
-macx {
- QMAKE_LFLAGS_SONAME = -Wl,-install_name,$${PWD}/
-}
-
diff --git a/src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin3/plugin3.pro b/src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin3/plugin3.pro
deleted file mode 100644
index c5ff581b1b..0000000000
--- a/src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin3/plugin3.pro
+++ /dev/null
@@ -1,15 +0,0 @@
-TEMPLATE = lib
-TARGET = plugin3
-
-SOURCES += plugin3.cpp
-HEADERS += plugin3.h
-
-include(../../../../extensionsystem_test.pri)
-
-LIBS += -L$${PWD}/../plugin2 -lplugin2
-
-macx {
- QMAKE_LFLAGS_SONAME = -Wl,-install_name,$${PWD}/
-} else:unix {
- QMAKE_RPATHDIR += $${PWD}/../plugin2
-}
diff --git a/src/libs/extensionsystem/test/auto/pluginmanager/test.pro b/src/libs/extensionsystem/test/auto/pluginmanager/test.pro
deleted file mode 100644
index c5934b1331..0000000000
--- a/src/libs/extensionsystem/test/auto/pluginmanager/test.pro
+++ /dev/null
@@ -1,14 +0,0 @@
-######################################################################
-# Automatically generated by qmake (2.01a) Fr Jul 27 23:12:52 2007
-######################################################################
-
-CONFIG += qtestlib
-TEMPLATE = app
-CONFIG -= app_bundle
-
-# Input
-
-include(../../extensionsystem_test.pri)
-
-SOURCES += tst_pluginmanager.cpp
-
diff --git a/src/libs/extensionsystem/test/auto/pluginmanager/test.sh b/src/libs/extensionsystem/test/auto/pluginmanager/test.sh
deleted file mode 100755
index 426901ea74..0000000000
--- a/src/libs/extensionsystem/test/auto/pluginmanager/test.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-# -- run the plugin test from this directory.
-
-export LD_LIBRARY_PATH=../../../../../../lib:$LD_LIBRARY_PATH
-export DYLD_LIBRARY_PATH=../../../../../../bin/QtCreator.app/Contents/PlugIns:$DYLD_LIBRARY_PATH # mac
-exec ./test
diff --git a/src/libs/extensionsystem/test/auto/pluginmanager/tst_pluginmanager.cpp b/src/libs/extensionsystem/test/auto/pluginmanager/tst_pluginmanager.cpp
deleted file mode 100644
index b270da44e7..0000000000
--- a/src/libs/extensionsystem/test/auto/pluginmanager/tst_pluginmanager.cpp
+++ /dev/null
@@ -1,269 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#include <extensionsystem/pluginmanager.h>
-#include <extensionsystem/pluginspec.h>
-#include <extensionsystem/iplugin.h>
-
-#include <QtTest/QtTest>
-
-#include <QtCore/QObject>
-
-using namespace ExtensionSystem;
-
-class SignalReceiver;
-
-class tst_PluginManager : public QObject
-{
- Q_OBJECT
-
-private slots:
- void init();
- void cleanup();
- void addRemoveObjects();
- void getObject();
- void getObjects();
- void plugins();
- void circularPlugins();
- void correctPlugins1();
-
-private:
- PluginManager *m_pm;
- SignalReceiver *m_sr;
-};
-
-class SignalReceiver : public QObject
-{
- Q_OBJECT
-
-public:
- SignalReceiver() :
- objectAddedCount(0),
- aboutToRemoveObjectCount(0),
- pluginsChangedCount(0),
- objectAddedObj(0),
- aboutToRemoveObjectObj(0)
- { }
- int objectAddedCount;
- int aboutToRemoveObjectCount;
- int pluginsChangedCount;
- QObject *objectAddedObj;
- QObject *aboutToRemoveObjectObj;
-public slots:
- void objectAdded(QObject *obj) { objectAddedCount++; objectAddedObj = obj; }
- void aboutToRemoveObject(QObject *obj) { aboutToRemoveObjectCount++; aboutToRemoveObjectObj = obj; }
- void pluginsChanged() { pluginsChangedCount++; }
-};
-
-class MyClass1 : public QObject
-{
- Q_OBJECT
-};
-
-class MyClass2 : public QObject
-{
- Q_OBJECT
-};
-
-class MyClass11 : public MyClass1
-{
- Q_OBJECT
-};
-
-void tst_PluginManager::init()
-{
- m_pm = new PluginManager;
- m_sr = new SignalReceiver;
- connect(m_pm, SIGNAL(objectAdded(QObject*)), m_sr, SLOT(objectAdded(QObject*)));
- connect(m_pm, SIGNAL(aboutToRemoveObject(QObject*)), m_sr, SLOT(aboutToRemoveObject(QObject*)));
- connect(m_pm, SIGNAL(pluginsChanged()), m_sr, SLOT(pluginsChanged()));
-}
-
-void tst_PluginManager::cleanup()
-{
- delete m_pm;
- delete m_sr;
-}
-
-void tst_PluginManager::addRemoveObjects()
-{
- QObject *object1 = new QObject;
- QObject *object2 = new QObject;
- QCOMPARE(m_pm->allObjects().size(), 0);
- m_pm->addObject(object1);
- QCOMPARE(m_sr->objectAddedCount, 1);
- QCOMPARE(m_sr->objectAddedObj, object1);
- QCOMPARE(m_sr->aboutToRemoveObjectCount, 0);
- QVERIFY(m_pm->allObjects().contains(object1));
- QVERIFY(!m_pm->allObjects().contains(object2));
- QCOMPARE(m_pm->allObjects().size(), 1);
- m_pm->addObject(object2);
- QCOMPARE(m_sr->objectAddedCount, 2);
- QCOMPARE(m_sr->objectAddedObj, object2);
- QCOMPARE(m_sr->aboutToRemoveObjectCount, 0);
- QVERIFY(m_pm->allObjects().contains(object1));
- QVERIFY(m_pm->allObjects().contains(object2));
- QCOMPARE(m_pm->allObjects().size(), 2);
- m_pm->removeObject(object1);
- QCOMPARE(m_sr->objectAddedCount, 2);
- QCOMPARE(m_sr->aboutToRemoveObjectCount, 1);
- QCOMPARE(m_sr->aboutToRemoveObjectObj, object1);
- QVERIFY(!m_pm->allObjects().contains(object1));
- QVERIFY(m_pm->allObjects().contains(object2));
- QCOMPARE(m_pm->allObjects().size(), 1);
- m_pm->removeObject(object2);
- QCOMPARE(m_sr->objectAddedCount, 2);
- QCOMPARE(m_sr->aboutToRemoveObjectCount, 2);
- QCOMPARE(m_sr->aboutToRemoveObjectObj, object2);
- QVERIFY(!m_pm->allObjects().contains(object1));
- QVERIFY(!m_pm->allObjects().contains(object2));
- QCOMPARE(m_pm->allObjects().size(), 0);
- delete object1;
- delete object2;
-}
-
-void tst_PluginManager::getObject()
-{
- MyClass2 *object2 = new MyClass2;
- MyClass11 *object11 = new MyClass11;
- m_pm->addObject(object2);
- QCOMPARE(m_pm->getObject<MyClass11>(), (MyClass11*)0);
- QCOMPARE(m_pm->getObject<MyClass1>(), (MyClass1*)0);
- QCOMPARE(m_pm->getObject<MyClass2>(), object2);
- m_pm->addObject(object11);
- QCOMPARE(m_pm->getObject<MyClass11>(), object11);
- QCOMPARE(m_pm->getObject<MyClass1>(), qobject_cast<MyClass1*>(object11));
- QCOMPARE(m_pm->getObject<MyClass2>(), object2);
- m_pm->removeObject(object2);
- m_pm->removeObject(object11);
- delete object2;
- delete object11;
-}
-
-void tst_PluginManager::getObjects()
-{
- MyClass1 *object1 = new MyClass1;
- MyClass2 *object2 = new MyClass2;
- MyClass11 *object11 = new MyClass11;
- m_pm->addObject(object2);
- QCOMPARE(m_pm->getObjects<MyClass11>(), QList<MyClass11*>());
- QCOMPARE(m_pm->getObjects<MyClass1>(), QList<MyClass1*>());
- QCOMPARE(m_pm->getObjects<MyClass2>(), QList<MyClass2*>() << object2);
- QCOMPARE(m_pm->allObjects(), QList<QObject*>() << object2);
- m_pm->addObject(object11);
- QCOMPARE(m_pm->getObjects<MyClass11>(), QList<MyClass11*>() << object11);
- QCOMPARE(m_pm->getObjects<MyClass1>(), QList<MyClass1*>() << object11);
- QCOMPARE(m_pm->getObjects<MyClass2>(), QList<MyClass2*>() << object2);
- QCOMPARE(m_pm->allObjects(), QList<QObject*>() << object2 << object11);
- m_pm->addObject(object1);
- QCOMPARE(m_pm->getObjects<MyClass11>(), QList<MyClass11*>() << object11);
- QCOMPARE(m_pm->getObjects<MyClass1>(), QList<MyClass1*>() << object11 << object1);
- QCOMPARE(m_pm->getObjects<MyClass2>(), QList<MyClass2*>() << object2);
- QCOMPARE(m_pm->allObjects(), QList<QObject*>() << object2 << object11 << object1);
- m_pm->removeObject(object2);
- m_pm->removeObject(object11);
- m_pm->removeObject(object1);
- delete object1;
- delete object2;
- delete object11;
-}
-
-void tst_PluginManager::plugins()
-{
- m_pm->setPluginPaths(QStringList() << "plugins");
- QCOMPARE(m_sr->pluginsChangedCount, 1);
- QSet<PluginSpec *> plugins = m_pm->plugins();
- QCOMPARE(plugins.count(), 3);
- foreach (const QString &expected, QStringList() << "helloworld" << "MyPlugin" << "dummyPlugin") {
- bool found = false;
- foreach (PluginSpec *spec, plugins) {
- if (spec->name() == expected) {
- found = true;
- break;
- }
- }
- QVERIFY2(found, QString("plugin '%1' not found").arg(expected).toLocal8Bit().constData());
- }
-}
-
-void tst_PluginManager::circularPlugins()
-{
- m_pm->setPluginPaths(QStringList() << "circularplugins");
- m_pm->loadPlugins();
- foreach (PluginSpec *spec, m_pm->plugins()) {
- if (spec->name() == "plugin1") {
- QVERIFY(spec->hasError());
- QCOMPARE(spec->state(), PluginSpec::Resolved);
- QCOMPARE(spec->plugin(), (IPlugin*)0);
- } else if (spec->name() == "plugin2") {
- QVERIFY(!spec->hasError());
- QCOMPARE(spec->state(), PluginSpec::Running);
- } else if (spec->name() == "plugin3") {
- QVERIFY(spec->hasError());
- QCOMPARE(spec->state(), PluginSpec::Resolved);
- QCOMPARE(spec->plugin(), (IPlugin*)0);
- }
- }
-}
-
-void tst_PluginManager::correctPlugins1()
-{
- m_pm->setFileExtension("spec");
- m_pm->setPluginPaths(QStringList() << "correctplugins1");
- m_pm->loadPlugins();
- foreach (PluginSpec *spec, m_pm->plugins()) {
- if (spec->hasError())
- qDebug() << spec->errorString();
- QVERIFY(!spec->hasError());
- QCOMPARE(spec->state(), PluginSpec::Running);
- }
- bool plugin1running = false;
- bool plugin2running = false;
- bool plugin3running = false;
- foreach (QObject *obj, m_pm->allObjects()) {
- if (obj->objectName() == "MyPlugin1_running")
- plugin1running = true;
- else if (obj->objectName() == "MyPlugin2_running")
- plugin2running = true;
- else if (obj->objectName() == "MyPlugin3_running")
- plugin3running = true;
- }
- QVERIFY(plugin1running);
- QVERIFY(plugin2running);
- QVERIFY(plugin3running);
-}
-
-QTEST_MAIN(tst_PluginManager)
-
-#include "tst_pluginmanager.moc"
-
diff --git a/src/libs/extensionsystem/test/auto/pluginspec/test.pro b/src/libs/extensionsystem/test/auto/pluginspec/test.pro
deleted file mode 100644
index d8fda88917..0000000000
--- a/src/libs/extensionsystem/test/auto/pluginspec/test.pro
+++ /dev/null
@@ -1,14 +0,0 @@
-CONFIG += qtestlib
-TEMPLATE = app
-CONFIG -= app_bundle
-DESTDIR = $${PWD}
-# Input
-SOURCES += tst_pluginspec.cpp
-
-include(../../extensionsystem_test.pri)
-
-LIBS += -L$${PWD}/testplugin -ltest
-macx {
-} else:unix {
- QMAKE_RPATHDIR += $${PWD}/testplugin
-}
diff --git a/src/libs/extensionsystem/test/auto/pluginspec/test.sh b/src/libs/extensionsystem/test/auto/pluginspec/test.sh
deleted file mode 100755
index 426901ea74..0000000000
--- a/src/libs/extensionsystem/test/auto/pluginspec/test.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-# -- run the plugin test from this directory.
-
-export LD_LIBRARY_PATH=../../../../../../lib:$LD_LIBRARY_PATH
-export DYLD_LIBRARY_PATH=../../../../../../bin/QtCreator.app/Contents/PlugIns:$DYLD_LIBRARY_PATH # mac
-exec ./test
diff --git a/src/libs/extensionsystem/test/auto/pluginspec/testplugin/testplugin.h b/src/libs/extensionsystem/test/auto/pluginspec/testplugin/testplugin.h
deleted file mode 100644
index 576a83dc69..0000000000
--- a/src/libs/extensionsystem/test/auto/pluginspec/testplugin/testplugin.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#ifndef TESTPLUGIN_H
-#define TESTPLUGIN_H
-
-#include "testplugin_global.h"
-#include <extensionsystem/iplugin.h>
-
-#include <QtCore/QObject>
-
-namespace MyPlugin {
-
-class MYPLUGIN_EXPORT MyPluginImpl : public ExtensionSystem::IPlugin
-{
- Q_OBJECT
-
-public:
- MyPluginImpl();
-
- bool initialize(const QStringList &arguments, QString *errorString);
- void extensionsInitialized();
-
- bool isInitialized() { return m_isInitialized; }
- bool isExtensionsInitialized() { return m_isExtensionsInitialized; }
-private:
- bool m_isInitialized;
- bool m_isExtensionsInitialized;
-};
-
-} // namespace
-
-#endif // TESTPLUGIN_H
diff --git a/src/libs/extensionsystem/test/auto/pluginspec/testplugin/testplugin.pro b/src/libs/extensionsystem/test/auto/pluginspec/testplugin/testplugin.pro
deleted file mode 100644
index 8b4d81a82a..0000000000
--- a/src/libs/extensionsystem/test/auto/pluginspec/testplugin/testplugin.pro
+++ /dev/null
@@ -1,13 +0,0 @@
-TEMPLATE = lib
-TARGET = test
-DESTDIR = $${PWD}
-DEFINES += MYPLUGIN_LIBRARY
-SOURCES += testplugin.cpp
-HEADERS += testplugin.h testplugin_global.h
-
-include(../../../extensionsystem_test.pri)
-
-macx {
- QMAKE_LFLAGS_SONAME = -Wl,-install_name,$${PWD}/
-}
-
diff --git a/src/libs/extensionsystem/test/auto/pluginspec/tst_pluginspec.cpp b/src/libs/extensionsystem/test/auto/pluginspec/tst_pluginspec.cpp
deleted file mode 100644
index 1dbbce3db7..0000000000
--- a/src/libs/extensionsystem/test/auto/pluginspec/tst_pluginspec.cpp
+++ /dev/null
@@ -1,290 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#include "testplugin/testplugin.h"
-
-#include <extensionsystem/pluginspec.h>
-#include <extensionsystem/pluginspec_p.h>
-#include <extensionsystem/pluginmanager_p.h>
-#include <extensionsystem/pluginmanager.h>
-
-#include <QtCore/QObject>
-#include <QtTest/QtTest>
-
-using namespace ExtensionSystem;
-
-class tst_PluginSpec : public QObject
-{
- Q_OBJECT
-
-private slots:
- void read();
- void readError();
- void isValidVersion();
- void versionCompare();
- void provides();
- void experimental();
- void locationAndPath();
- void resolveDependencies();
- void loadLibrary();
- void initializePlugin();
- void initializeExtensions();
-};
-
-void tst_PluginSpec::read()
-{
- Internal::PluginSpecPrivate spec(0);
- QCOMPARE(spec.state, PluginSpec::Invalid);
- QVERIFY(spec.read("testspecs/spec1.xml"));
- QCOMPARE(spec.state, PluginSpec::Read);
- QVERIFY(!spec.hasError);
- QVERIFY(spec.errorString.isEmpty());
- QCOMPARE(spec.name, QString("test"));
- QCOMPARE(spec.version, QString("1.0.1"));
- QCOMPARE(spec.compatVersion, QString("1.0.0"));
- QCOMPARE(spec.experimental, false);
- QCOMPARE(spec.enabled, true);
- QCOMPARE(spec.vendor, QString("Nokia Corporation"));
- QCOMPARE(spec.copyright, QString("(C) 2007 Nokia Corporation"));
- QCOMPARE(spec.license, QString("This is a default license bla\nblubbblubb\nend of terms"));
- QCOMPARE(spec.description, QString("This plugin is just a test.\n it demonstrates the great use of the plugin spec."));
- QCOMPARE(spec.url, QString("http://qt.noki.com"));
- PluginDependency dep1;
- dep1.name = QString("SomeOtherPlugin");
- dep1.version = QString("2.3.0_2");
- PluginDependency dep2;
- dep2.name = QString("EvenOther");
- dep2.version = QString("1.0.0");
- QCOMPARE(spec.dependencies, QList<PluginDependency>() << dep1 << dep2);
-
- // test missing compatVersion behavior
- QVERIFY(spec.read("testspecs/spec2.xml"));
- QCOMPARE(spec.version, QString("3.1.4_10"));
- QCOMPARE(spec.compatVersion, QString("3.1.4_10"));
-}
-
-void tst_PluginSpec::readError()
-{
- Internal::PluginSpecPrivate spec(0);
- QCOMPARE(spec.state, PluginSpec::Invalid);
- QVERIFY(!spec.read("non-existing-file.xml"));
- QCOMPARE(spec.state, PluginSpec::Invalid);
- QVERIFY(spec.hasError);
- QVERIFY(!spec.errorString.isEmpty());
- QVERIFY(!spec.read("testspecs/spec_wrong1.xml"));
- QCOMPARE(spec.state, PluginSpec::Invalid);
- QVERIFY(spec.hasError);
- QVERIFY(!spec.errorString.isEmpty());
- QVERIFY(!spec.read("testspecs/spec_wrong2.xml"));
- QCOMPARE(spec.state, PluginSpec::Invalid);
- QVERIFY(spec.hasError);
- QVERIFY(!spec.errorString.isEmpty());
- QVERIFY(!spec.read("testspecs/spec_wrong3.xml"));
- QCOMPARE(spec.state, PluginSpec::Invalid);
- QVERIFY(spec.hasError);
- QVERIFY(!spec.errorString.isEmpty());
- QVERIFY(!spec.read("testspecs/spec_wrong4.xml"));
- QCOMPARE(spec.state, PluginSpec::Invalid);
- QVERIFY(spec.hasError);
- QVERIFY(!spec.errorString.isEmpty());
- QVERIFY(!spec.read("testspecs/spec_wrong5.xml"));
- QCOMPARE(spec.state, PluginSpec::Invalid);
- QVERIFY(spec.hasError);
- QVERIFY(!spec.errorString.isEmpty());
-}
-
-void tst_PluginSpec::isValidVersion()
-{
- QVERIFY(Internal::PluginSpecPrivate::isValidVersion("2"));
- QVERIFY(Internal::PluginSpecPrivate::isValidVersion("53"));
- QVERIFY(Internal::PluginSpecPrivate::isValidVersion("52_1"));
- QVERIFY(Internal::PluginSpecPrivate::isValidVersion("3.12"));
- QVERIFY(Internal::PluginSpecPrivate::isValidVersion("31.1_12"));
- QVERIFY(Internal::PluginSpecPrivate::isValidVersion("31.1.0"));
- QVERIFY(Internal::PluginSpecPrivate::isValidVersion("1.0.2_1"));
-
- QVERIFY(!Internal::PluginSpecPrivate::isValidVersion(""));
- QVERIFY(!Internal::PluginSpecPrivate::isValidVersion("1..0"));
- QVERIFY(!Internal::PluginSpecPrivate::isValidVersion("1.0_"));
- QVERIFY(!Internal::PluginSpecPrivate::isValidVersion("1.0.0.0"));
-}
-
-void tst_PluginSpec::versionCompare()
-{
- QVERIFY(Internal::PluginSpecPrivate::versionCompare("3", "3") == 0);
- QVERIFY(Internal::PluginSpecPrivate::versionCompare("3.0.0", "3") == 0);
- QVERIFY(Internal::PluginSpecPrivate::versionCompare("3.0", "3") == 0);
- QVERIFY(Internal::PluginSpecPrivate::versionCompare("3.0.0_1", "3_1") == 0);
- QVERIFY(Internal::PluginSpecPrivate::versionCompare("3.0_21", "3_21") == 0);
-
- QVERIFY(Internal::PluginSpecPrivate::versionCompare("3", "1") > 0);
- QVERIFY(Internal::PluginSpecPrivate::versionCompare("3", "1.0_12") > 0);
- QVERIFY(Internal::PluginSpecPrivate::versionCompare("3_1", "3") > 0);
- QVERIFY(Internal::PluginSpecPrivate::versionCompare("3.1.0_23", "3.1") > 0);
- QVERIFY(Internal::PluginSpecPrivate::versionCompare("3.1_23", "3.1_12") > 0);
-
- QVERIFY(Internal::PluginSpecPrivate::versionCompare("1", "3") < 0);
- QVERIFY(Internal::PluginSpecPrivate::versionCompare("1.0_12", "3") < 0);
- QVERIFY(Internal::PluginSpecPrivate::versionCompare("3", "3_1") < 0);
- QVERIFY(Internal::PluginSpecPrivate::versionCompare("3.1", "3.1.0_23") < 0);
- QVERIFY(Internal::PluginSpecPrivate::versionCompare("3.1_12", "3.1_23") < 0);
-}
-
-void tst_PluginSpec::provides()
-{
- Internal::PluginSpecPrivate spec(0);
- QVERIFY(spec.read("testspecs/simplespec.xml"));
- QVERIFY(!spec.provides("SomeOtherPlugin", "2.2.3_9"));
- QVERIFY(!spec.provides("MyPlugin", "2.2.3_10"));
- QVERIFY(!spec.provides("MyPlugin", "2.2.4"));
- QVERIFY(!spec.provides("MyPlugin", "2.3.11_1"));
- QVERIFY(!spec.provides("MyPlugin", "2.3"));
- QVERIFY(!spec.provides("MyPlugin", "3.0"));
- QVERIFY(!spec.provides("MyPlugin", "1.9.9_99"));
- QVERIFY(!spec.provides("MyPlugin", "1.9"));
- QVERIFY(!spec.provides("MyPlugin", "0.9"));
- QVERIFY(!spec.provides("MyPlugin", "1"));
-
- QVERIFY(spec.provides("myplugin", "2.2.3_9"));
- QVERIFY(spec.provides("MyPlugin", "2.2.3_9"));
- QVERIFY(spec.provides("MyPlugin", "2.2.3_8"));
- QVERIFY(spec.provides("MyPlugin", "2.2.3"));
- QVERIFY(spec.provides("MyPlugin", "2.2.2"));
- QVERIFY(spec.provides("MyPlugin", "2.1.2_10"));
- QVERIFY(spec.provides("MyPlugin", "2.0_10"));
- QVERIFY(spec.provides("MyPlugin", "2"));
-}
-
-void tst_PluginSpec::experimental()
-{
- Internal::PluginSpecPrivate spec(0);
- QVERIFY(spec.read("testspecs/simplespec_experimental.xml"));
- QCOMPARE(spec.experimental, true);
- QCOMPARE(spec.enabled, false);
-}
-
-void tst_PluginSpec::locationAndPath()
-{
- Internal::PluginSpecPrivate spec(0);
- QVERIFY(spec.read("testspecs/simplespec.xml"));
- QCOMPARE(spec.location, QDir::currentPath()+"/testspecs");
- QCOMPARE(spec.filePath, QDir::currentPath()+"/testspecs/simplespec.xml");
- QVERIFY(spec.read("testdir/../testspecs/simplespec.xml"));
- QCOMPARE(spec.location, QDir::currentPath()+"/testspecs");
- QCOMPARE(spec.filePath, QDir::currentPath()+"/testspecs/simplespec.xml");
- QVERIFY(spec.read("testdir/spec.xml"));
- QCOMPARE(spec.location, QDir::currentPath()+"/testdir");
- QCOMPARE(spec.filePath, QDir::currentPath()+"/testdir/spec.xml");
-}
-
-void tst_PluginSpec::resolveDependencies()
-{
- QList<PluginSpec *> specs;
- PluginSpec *spec1 = Internal::PluginManagerPrivate::createSpec();
- specs.append(spec1);
- Internal::PluginSpecPrivate *spec1Priv = Internal::PluginManagerPrivate::privateSpec(spec1);
- spec1Priv->read("testdependencies/spec1.xml");
- PluginSpec *spec2 = Internal::PluginManagerPrivate::createSpec();
- specs.append(spec2);
- Internal::PluginManagerPrivate::privateSpec(spec2)->read("testdependencies/spec2.xml");
- PluginSpec *spec3 = Internal::PluginManagerPrivate::createSpec();
- specs.append(spec3);
- Internal::PluginManagerPrivate::privateSpec(spec3)->read("testdependencies/spec3.xml");
- PluginSpec *spec4 = Internal::PluginManagerPrivate::createSpec();
- specs.append(spec4);
- Internal::PluginSpecPrivate *spec4Priv = Internal::PluginManagerPrivate::privateSpec(spec4);
- spec4Priv->read("testdependencies/spec4.xml");
- PluginSpec *spec5 = Internal::PluginManagerPrivate::createSpec();
- specs.append(spec5);
- Internal::PluginManagerPrivate::privateSpec(spec5)->read("testdependencies/spec5.xml");
- QVERIFY(spec1Priv->resolveDependencies(specs));
- QCOMPARE(spec1Priv->dependencySpecs.size(), 2);
- QVERIFY(spec1Priv->dependencySpecs.contains(spec2));
- QVERIFY(spec1Priv->dependencySpecs.contains(spec3));
- QCOMPARE(spec1Priv->state, PluginSpec::Resolved);
- QVERIFY(!spec4Priv->resolveDependencies(specs));
- QVERIFY(spec4Priv->hasError);
- QCOMPARE(spec4Priv->state, PluginSpec::Read);
-}
-
-void tst_PluginSpec::loadLibrary()
-{
- PluginSpec *ps = Internal::PluginManagerPrivate::createSpec();
- Internal::PluginSpecPrivate *spec = Internal::PluginManagerPrivate::privateSpec(ps);
- PluginManager *manager = new PluginManager();
- QVERIFY(spec->read("testplugin/testplugin.xml"));
- QVERIFY(spec->resolveDependencies(QList<PluginSpec *>()));
- QVERIFY(spec->loadLibrary());
- QVERIFY(qobject_cast<MyPlugin::MyPluginImpl*>(spec->plugin) != 0);
- QCOMPARE(spec->state, PluginSpec::Loaded);
- QVERIFY(!spec->hasError);
- QCOMPARE(spec->plugin->pluginSpec(), ps);
- delete manager;
- delete ps;
-}
-
-void tst_PluginSpec::initializePlugin()
-{
- Internal::PluginSpecPrivate spec(0);
- MyPlugin::MyPluginImpl *impl;
- QVERIFY(spec.read("testplugin/testplugin.xml"));
- QVERIFY(spec.resolveDependencies(QList<PluginSpec *>()));
- QVERIFY(spec.loadLibrary());
- impl = qobject_cast<MyPlugin::MyPluginImpl*>(spec.plugin);
- QVERIFY(impl != 0);
- QVERIFY(!impl->isInitialized());
- QVERIFY(spec.initializePlugin());
- QCOMPARE(spec.state, PluginSpec::Initialized);
- QVERIFY(!spec.hasError);
- QVERIFY(impl->isInitialized());
-}
-
-void tst_PluginSpec::initializeExtensions()
-{
- Internal::PluginSpecPrivate spec(0);
- MyPlugin::MyPluginImpl *impl;
- QVERIFY(spec.read("testplugin/testplugin.xml"));
- QVERIFY(spec.resolveDependencies(QList<PluginSpec *>()));
- QVERIFY(spec.loadLibrary());
- impl = qobject_cast<MyPlugin::MyPluginImpl*>(spec.plugin);
- QVERIFY(impl != 0);
- QVERIFY(spec.initializePlugin());
- QVERIFY(spec.initializeExtensions());
- QCOMPARE(spec.state, PluginSpec::Running);
- QVERIFY(!spec.hasError);
- QVERIFY(impl->isExtensionsInitialized());
-}
-
-QTEST_MAIN(tst_PluginSpec)
-
-#include "tst_pluginspec.moc"
diff --git a/src/libs/extensionsystem/test/extensionsystem_test.pri b/src/libs/extensionsystem/test/extensionsystem_test.pri
deleted file mode 100644
index 6ad874add3..0000000000
--- a/src/libs/extensionsystem/test/extensionsystem_test.pri
+++ /dev/null
@@ -1,12 +0,0 @@
-
-INCLUDEPATH *= $$PWD/../..
-macx {
- LIBPATH*= $$PWD/../../../../bin/QtCreator.app/Contents/PlugIns
-}
-else {
- LIBPATH*= $$PWD/../../../../lib
-}
-
-include(../extensionsystem.pri)
-
-QT *= xml
diff --git a/src/libs/extensionsystem/test/manual/pluginview/plugins/plugin1/plugin1.pro b/src/libs/extensionsystem/test/manual/pluginview/plugins/plugin1/plugin1.pro
index 9101770f9a..242b180022 100644
--- a/src/libs/extensionsystem/test/manual/pluginview/plugins/plugin1/plugin1.pro
+++ b/src/libs/extensionsystem/test/manual/pluginview/plugins/plugin1/plugin1.pro
@@ -4,12 +4,13 @@ TARGET = plugin1
SOURCES += plugin1.cpp
HEADERS += plugin1.h
+RELATIVEPATH = ../../../..
include(../../../../extensionsystem_test.pri)
-LIBS += -L$${PWD}/../plugin2 -L$${PWD}/../plugin3 -lplugin2 -lplugin3
+LIBS += -L$${OUT_PWD}/../plugin2 -L$${OUT_PWD}/../plugin3 -lplugin2 -lplugin3
macx {
} else:unix {
- QMAKE_RPATHDIR += $${PWD}/../plugin2
- QMAKE_RPATHDIR += $${PWD}/../plugin3
+ QMAKE_RPATHDIR += $${OUT_PWD}/../plugin2
+ QMAKE_RPATHDIR += $${OUT_PWD}/../plugin3
}
diff --git a/src/libs/extensionsystem/test/manual/pluginview/plugins/plugin2/plugin2.pro b/src/libs/extensionsystem/test/manual/pluginview/plugins/plugin2/plugin2.pro
index a80f4a5c76..8b33fb4d7e 100644
--- a/src/libs/extensionsystem/test/manual/pluginview/plugins/plugin2/plugin2.pro
+++ b/src/libs/extensionsystem/test/manual/pluginview/plugins/plugin2/plugin2.pro
@@ -4,9 +4,10 @@ TARGET = plugin2
SOURCES += plugin2.cpp
HEADERS += plugin2.h
+RELATIVEPATH = ../../../..
include(../../../../extensionsystem_test.pri)
macx {
- QMAKE_LFLAGS_SONAME = -Wl,-install_name,$${PWD}/
+ QMAKE_LFLAGS_SONAME = -Wl,-install_name,$${OUT_PWD}/
}
diff --git a/src/libs/extensionsystem/test/manual/pluginview/plugins/plugin3/plugin3.pro b/src/libs/extensionsystem/test/manual/pluginview/plugins/plugin3/plugin3.pro
index c5ff581b1b..7fac0e790b 100644
--- a/src/libs/extensionsystem/test/manual/pluginview/plugins/plugin3/plugin3.pro
+++ b/src/libs/extensionsystem/test/manual/pluginview/plugins/plugin3/plugin3.pro
@@ -4,12 +4,13 @@ TARGET = plugin3
SOURCES += plugin3.cpp
HEADERS += plugin3.h
+RELATIVEPATH = ../../../..
include(../../../../extensionsystem_test.pri)
-LIBS += -L$${PWD}/../plugin2 -lplugin2
+LIBS += -L$${OUT_PWD}/../plugin2 -lplugin2
macx {
- QMAKE_LFLAGS_SONAME = -Wl,-install_name,$${PWD}/
+ QMAKE_LFLAGS_SONAME = -Wl,-install_name,$${OUT_PWD}/
} else:unix {
- QMAKE_RPATHDIR += $${PWD}/../plugin2
+ QMAKE_RPATHDIR += $${OUT_PWD}/../plugin2
}
diff --git a/src/libs/extensionsystem/test/manual/pluginview/test.pro b/src/libs/extensionsystem/test/manual/pluginview/test.pro
index 4b9cd21d8a..d4c17967f3 100644
--- a/src/libs/extensionsystem/test/manual/pluginview/test.pro
+++ b/src/libs/extensionsystem/test/manual/pluginview/test.pro
@@ -6,4 +6,5 @@ macx:CONFIG-=app_bundle
HEADERS += plugindialog.h
SOURCES += plugindialog.cpp
+RELATIVEPATH = ../..
include(../../extensionsystem_test.pri)
diff --git a/src/libs/glsl/glsl-lib.pri b/src/libs/glsl/glsl-lib.pri
new file mode 100644
index 0000000000..27dfb2e541
--- /dev/null
+++ b/src/libs/glsl/glsl-lib.pri
@@ -0,0 +1,9 @@
+HEADERS += $$PWD/glsl.h $$PWD/glsllexer.h $$PWD/glslparser.h $$PWD/glslparsertable_p.h $$PWD/glslast.h \
+ $$PWD/glslastvisitor.h $$PWD/glslengine.h $$PWD/glslmemorypool.h $$PWD/glslastdump.h \
+ $$PWD/glslsemantic.h $$PWD/glsltype.h $$PWD/glsltypes.h $$PWD/glslsymbol.h $$PWD/glslsymbols.h
+SOURCES += $$PWD/glslkeywords.cpp $$PWD/glslparser.cpp $$PWD/glslparsertable.cpp \
+ $$PWD/glsllexer.cpp $$PWD/glslast.cpp \
+ $$PWD/glslastvisitor.cpp $$PWD/glslengine.cpp $$PWD/glslmemorypool.cpp $$PWD/glslastdump.cpp \
+ $$PWD/glslsemantic.cpp $$PWD/glsltype.cpp $$PWD/glsltypes.cpp $$PWD/glslsymbol.cpp $$PWD/glslsymbols.cpp
+
+OTHER_FILES = $$PWD/glsl.g
diff --git a/src/libs/glsl/glsl.g b/src/libs/glsl/glsl.g
new file mode 100644
index 0000000000..49bd5ed05d
--- /dev/null
+++ b/src/libs/glsl/glsl.g
@@ -0,0 +1,3008 @@
+---------------------------------------------------------------------------
+--
+-- This file is part of Qt Creator
+--
+-- Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+--
+-- Contact: Nokia Corporation (qt-info@nokia.com)
+--
+-- Commercial Usage
+--
+-- Licensees holding valid Qt Commercial licenses may use this file in
+-- accordance with the Qt Commercial License Agreement provided with the
+-- Software or, alternatively, in accordance with the terms contained in
+-- a written agreement between you and Nokia.
+--
+-- GNU Lesser General Public License Usage
+--
+-- Alternatively, this file may be used under the terms of the GNU Lesser
+-- General Public License version 2.1 as published by the Free Software
+-- Foundation and appearing in the file LICENSE.LGPL included in the
+-- packaging of this file. Please review the following information to
+-- ensure the GNU Lesser General Public License version 2.1 requirements
+-- will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+--
+-- If you are unsure which license is appropriate for your use, please
+-- contact the sales department at http://qt.nokia.com/contact.
+---------------------------------------------------------------------------
+
+%decl glslparser.h
+%impl glslparser.cpp
+%parser GLSLParserTable
+%token_prefix T_
+%expect 1
+
+%token FEED_GLSL "feed GLSL"
+%token FEED_EXPRESSION "feed expression"
+
+%token ADD_ASSIGN "+="
+%token AMPERSAND "&"
+%token AND_ASSIGN "&="
+%token AND_OP "&&"
+%token ATTRIBUTE "attribute"
+%token BANG "!"
+%token BOOL "bool"
+%token BREAK "break"
+%token BVEC2 "bvec2"
+%token BVEC3 "bvec3"
+%token BVEC4 "bvec4"
+%token CARET "^"
+%token CASE "case"
+%token CENTROID "centroid"
+%token COLON ":"
+%token COMMA ","
+%token CONST "const"
+%token CONTINUE "continue"
+%token DASH "-"
+%token DEC_OP "--"
+%token DEFAULT "default"
+%token DISCARD "discard"
+%token DIV_ASSIGN "/="
+%token DMAT2 "dmat2"
+%token DMAT2X2 "dmat2x2"
+%token DMAT2X3 "dmat2x3"
+%token DMAT2X4 "dmat2x4"
+%token DMAT3 "dmat3"
+%token DMAT3X2 "dmat3x2"
+%token DMAT3X3 "dmat3x3"
+%token DMAT3X4 "dmat3x4"
+%token DMAT4 "dmat4"
+%token DMAT4X2 "dmat4x2"
+%token DMAT4X3 "dmat4x3"
+%token DMAT4X4 "dmat4x4"
+%token DO "do"
+%token DOT "."
+%token DOUBLE "double"
+%token DVEC2 "dvec2"
+%token DVEC3 "dvec3"
+%token DVEC4 "dvec4"
+%token ELSE "else"
+%token EQUAL "="
+%token EQ_OP "=="
+%token FLAT "flat"
+%token FLOAT "float"
+%token FOR "for"
+%token GE_OP ">="
+%token HIGHP "highp"
+%token IDENTIFIER "identifier"
+%token IF "if"
+%token IN "in"
+%token INC_OP "++"
+%token INOUT "inout"
+%token INT "int"
+%token INVARIANT "invariant"
+%token ISAMPLER1D "isampler1D"
+%token ISAMPLER1DARRAY "isampler1DArray"
+%token ISAMPLER2D "isampler2D"
+%token ISAMPLER2DARRAY "isampler2DArray"
+%token ISAMPLER2DMS "isampler2DMS"
+%token ISAMPLER2DMSARRAY "isampler2DMSArray"
+%token ISAMPLER2DRECT "isampler2DRect"
+%token ISAMPLER3D "isampler3D"
+%token ISAMPLERBUFFER "isamplerBuffer"
+%token ISAMPLERCUBE "isamplerCube"
+%token ISAMPLERCUBEARRAY "isamplerCubeArray"
+%token IVEC2 "ivec2"
+%token IVEC3 "ivec3"
+%token IVEC4 "ivec4"
+%token LAYOUT "layout"
+%token LEFT_ANGLE "<"
+%token LEFT_ASSIGN "<<="
+%token LEFT_BRACE "{"
+%token LEFT_BRACKET "["
+%token LEFT_OP "<<"
+%token LEFT_PAREN "("
+%token LE_OP "<="
+%token LOWP "lowp"
+%token MAT2 "mat2"
+%token MAT2X2 "mat2x2"
+%token MAT2X3 "mat2x3"
+%token MAT2X4 "mat2x4"
+%token MAT3 "mat3"
+%token MAT3X2 "mat3x2"
+%token MAT3X3 "mat3x3"
+%token MAT3X4 "mat3x4"
+%token MAT4 "mat4"
+%token MAT4X2 "mat4x2"
+%token MAT4X3 "mat4x3"
+%token MAT4X4 "mat4x4"
+%token MEDIUMP "mediump"
+%token MOD_ASSIGN "%="
+%token MUL_ASSIGN "*="
+%token NE_OP "!="
+%token NOPERSPECTIVE "noperspective"
+%token NUMBER "number constant"
+%token OR_ASSIGN "|="
+%token OR_OP "||"
+%token OUT "out"
+%token PATCH "patch"
+%token PERCENT "%"
+%token PLUS "plus"
+%token PRECISION "precision"
+%token QUESTION "?"
+%token RETURN "return"
+%token RIGHT_ANGLE ">"
+%token RIGHT_ASSIGN ">>="
+%token RIGHT_BRACE "}"
+%token RIGHT_BRACKET "]"
+%token RIGHT_OP ">>"
+%token RIGHT_PAREN ")"
+%token SAMPLE "sample"
+%token SAMPLER1D "sampler1D"
+%token SAMPLER1DARRAY "sampler1DArray"
+%token SAMPLER1DARRAYSHADOW "sampler1DArrayShadow"
+%token SAMPLER1DSHADOW "sampler1DShadow"
+%token SAMPLER2D "sampler2D"
+%token SAMPLER2DARRAY "sampler2DArray"
+%token SAMPLER2DARRAYSHADOW "sampler2DArrayShadow"
+%token SAMPLER2DMS "sampler2DMS"
+%token SAMPLER2DMSARRAY "sampler2DMSArray"
+%token SAMPLER2DRECT "sampler2DRect"
+%token SAMPLER2DRECTSHADOW "sampler2DRectShadow"
+%token SAMPLER2DSHADOW "sampler2DShadow"
+%token SAMPLER3D "sampler3D"
+%token SAMPLERBUFFER "samplerBuffer"
+%token SAMPLERCUBE "samplerCube"
+%token SAMPLERCUBEARRAY "samplerCubeArray"
+%token SAMPLERCUBEARRAYSHADOW "samplerCubeArrayShadow"
+%token SAMPLERCUBESHADOW "samplerCubeShadow"
+%token SEMICOLON ";"
+%token SLASH "/"
+%token SMOOTH "smooth"
+%token STAR "*"
+%token STRUCT "struct"
+%token SUBROUTINE "subroutine"
+%token SUB_ASSIGN "-="
+%token SWITCH "switch"
+%token TILDE "~"
+%token TYPE_NAME "type_name"
+%token UINT "uint"
+%token UNIFORM "uniform"
+%token USAMPLER1D "usampler1D"
+%token USAMPLER1DARRAY "usampler1DArray"
+%token USAMPLER2D "usampler2D"
+%token USAMPLER2DARRAY "usampler2DArray"
+%token USAMPLER2DMS "usampler2DMS"
+%token USAMPLER2DMSARRAY "usampler2DMSarray"
+%token USAMPLER2DRECT "usampler2DRect"
+%token USAMPLER3D "usampler3D"
+%token USAMPLERBUFFER "usamplerBuffer"
+%token USAMPLERCUBE "usamplerCube"
+%token USAMPLERCUBEARRAY "usamplerCubeArray"
+%token UVEC2 "uvec2"
+%token UVEC3 "uvec3"
+%token UVEC4 "uvec4"
+%token VARYING "varying"
+%token VEC2 "vec2"
+%token VEC3 "vec3"
+%token VEC4 "vec4"
+%token VERTICAL_BAR "|"
+%token VOID "void"
+%token WHILE "while"
+%token XOR_ASSIGN "^="
+%token XOR_OP "^^"
+%token TRUE "true"
+%token FALSE "false"
+%token PREPROC "preprocessor directive"
+%token COMMENT "comment"
+%token ERROR "error"
+%token RESERVED "reserved word"
+
+%start toplevel
+
+/:
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "$header"
+#include "glsllexer.h"
+#include "glslast.h"
+#include "glslengine.h"
+#include <vector>
+#include <stack>
+
+namespace GLSL {
+
+class GLSL_EXPORT Parser: public $table
+{
+public:
+ union Value {
+ void *ptr;
+ const QString *string;
+ AST *ast;
+ List<AST *> *ast_list;
+ DeclarationAST *declaration;
+ List<DeclarationAST *> *declaration_list;
+ ExpressionAST *expression;
+ List<ExpressionAST *> *expression_list;
+ StatementAST *statement;
+ List<StatementAST *> *statement_list;
+ TypeAST *type;
+ StructTypeAST::Field *field;
+ List<StructTypeAST::Field *> *field_list;
+ TranslationUnitAST *translation_unit;
+ FunctionIdentifierAST *function_identifier;
+ AST::Kind kind;
+ TypeAST::Precision precision;
+ struct {
+ StatementAST *thenClause;
+ StatementAST *elseClause;
+ } ifstmt;
+ struct {
+ ExpressionAST *condition;
+ ExpressionAST *increment;
+ } forstmt;
+ struct {
+ FunctionIdentifierAST *id;
+ List<ExpressionAST *> *arguments;
+ } function;
+ int qualifier;
+ LayoutQualifier *layout;
+ List<LayoutQualifier *> *layout_list;
+ struct {
+ int qualifier;
+ List<LayoutQualifier *> *layout_list;
+ } type_qualifier;
+ struct {
+ TypeAST *type;
+ const QString *name;
+ } param_declarator;
+ ParameterDeclarationAST *param_declaration;
+ FunctionDeclarationAST *function_declaration;
+ };
+
+ Parser(Engine *engine, const char *source, unsigned size, int variant);
+ ~Parser();
+
+ TranslationUnitAST *parse() {
+ if (AST *u = parse(T_FEED_GLSL))
+ return u->asTranslationUnit();
+ return 0;
+ }
+
+ ExpressionAST *parseExpression() {
+ if (AST *u = parse(T_FEED_EXPRESSION))
+ return u->asExpression();
+ return 0;
+ }
+
+ AST *parse(int startToken);
+
+private:
+ // 1-based
+ int &location(int n) { return _locationStack[_tos + n - 1]; }
+ Value &sym(int n) { return _symStack[_tos + n - 1]; }
+ AST *&ast(int n) { return _symStack[_tos + n - 1].ast; }
+ const QString *&string(int n) { return _symStack[_tos + n - 1].string; }
+ ExpressionAST *&expression(int n) { return _symStack[_tos + n - 1].expression; }
+ StatementAST *&statement(int n) { return _symStack[_tos + n - 1].statement; }
+ TypeAST *&type(int n) { return _symStack[_tos + n - 1].type; }
+ FunctionDeclarationAST *&function(int n) { return _symStack[_tos + n - 1].function_declaration; }
+
+ inline int consumeToken() {
+ if (_index < int(_tokens.size()))
+ return _index++;
+ return _tokens.size() - 1;
+ }
+ inline const Token &tokenAt(int index) const {
+ if (index == 0)
+ return _startToken;
+ return _tokens.at(index);
+ }
+ inline int tokenKind(int index) const {
+ if (index == 0)
+ return _startToken.kind;
+ return _tokens.at(index).kind;
+ }
+ void reduce(int ruleno);
+
+ void warning(int line, const QString &message)
+ {
+ _engine->warning(line, message);
+ }
+
+ void error(int line, const QString &message)
+ {
+ _engine->error(line, message);
+ }
+
+ template <typename T>
+ T *makeAstNode()
+ {
+ T *node = new (_engine->pool()) T ();
+ node->lineno = yyloc >= 0 ? (_tokens[yyloc].line + 1) : 0;
+ return node;
+ }
+
+ template <typename T, typename A1>
+ T *makeAstNode(A1 a1)
+ {
+ T *node = new (_engine->pool()) T (a1);
+ node->lineno = yyloc >= 0 ? (_tokens[yyloc].line + 1) : 0;
+ return node;
+ }
+
+ template <typename T, typename A1, typename A2>
+ T *makeAstNode(A1 a1, A2 a2)
+ {
+ T *node = new (_engine->pool()) T (a1, a2);
+ node->lineno = yyloc >= 0 ? (_tokens[yyloc].line + 1) : 0;
+ return node;
+ }
+
+ template <typename T, typename A1, typename A2, typename A3>
+ T *makeAstNode(A1 a1, A2 a2, A3 a3)
+ {
+ T *node = new (_engine->pool()) T (a1, a2, a3);
+ node->lineno = yyloc >= 0 ? (_tokens[yyloc].line + 1) : 0;
+ return node;
+ }
+
+ template <typename T, typename A1, typename A2, typename A3, typename A4>
+ T *makeAstNode(A1 a1, A2 a2, A3 a3, A4 a4)
+ {
+ T *node = new (_engine->pool()) T (a1, a2, a3, a4);
+ node->lineno = yyloc >= 0 ? (_tokens[yyloc].line + 1) : 0;
+ return node;
+ }
+
+ TypeAST *makeBasicType(int token)
+ {
+ TypeAST *type = new (_engine->pool()) BasicTypeAST(token, spell[token]);
+ type->lineno = yyloc >= 0 ? (_tokens[yyloc].line + 1) : 0;
+ return type;
+ }
+
+private:
+ Engine *_engine;
+ int _tos;
+ int _index;
+ int yyloc;
+ int yytoken;
+ int yyrecovering;
+ bool _recovered;
+ Token _startToken;
+ std::vector<int> _stateStack;
+ std::vector<int> _locationStack;
+ std::vector<Value> _symStack;
+ std::vector<Token> _tokens;
+};
+
+} // end of namespace GLSL
+:/
+
+/.
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "glslparser.h"
+#include "glslengine.h"
+#include <iostream>
+#include <cstdio>
+#include <cassert>
+#include <QtCore/QDebug>
+
+using namespace GLSL;
+
+Parser::Parser(Engine *engine, const char *source, unsigned size, int variant)
+ : _engine(engine), _tos(-1), _index(0), yyloc(-1), yytoken(-1), yyrecovering(0), _recovered(false)
+{
+ _tokens.reserve(1024);
+
+ _stateStack.resize(128);
+ _locationStack.resize(128);
+ _symStack.resize(128);
+
+ _tokens.push_back(Token()); // invalid token
+
+ std::stack<int> parenStack;
+ std::stack<int> bracketStack;
+ std::stack<int> braceStack;
+
+ Lexer lexer(engine, source, size);
+ lexer.setVariant(variant);
+ Token tk;
+ do {
+ lexer.yylex(&tk);
+
+ switch (tk.kind) {
+ case T_LEFT_PAREN:
+ parenStack.push(_tokens.size());
+ break;
+ case T_LEFT_BRACKET:
+ bracketStack.push(_tokens.size());
+ break;
+ case T_LEFT_BRACE:
+ braceStack.push(_tokens.size());
+ break;
+
+ case T_RIGHT_PAREN:
+ if (! parenStack.empty()) {
+ _tokens[parenStack.top()].matchingBrace = _tokens.size();
+ parenStack.pop();
+ }
+ break;
+ case T_RIGHT_BRACKET:
+ if (! bracketStack.empty()) {
+ _tokens[bracketStack.top()].matchingBrace = _tokens.size();
+ bracketStack.pop();
+ }
+ break;
+ case T_RIGHT_BRACE:
+ if (! braceStack.empty()) {
+ _tokens[braceStack.top()].matchingBrace = _tokens.size();
+ braceStack.pop();
+ }
+ break;
+ default:
+ break;
+ }
+
+ _tokens.push_back(tk);
+ } while (tk.isNot(EOF_SYMBOL));
+
+ _index = 0;
+}
+
+Parser::~Parser()
+{
+}
+
+AST *Parser::parse(int startToken)
+{
+ int action = 0;
+ yytoken = -1;
+ yyloc = -1;
+ void *yyval = 0; // value of the current token.
+
+ _recovered = false;
+ _tos = -1;
+ _startToken.kind = startToken;
+
+ do {
+ again:
+ if (unsigned(++_tos) == _stateStack.size()) {
+ _stateStack.resize(_tos * 2);
+ _locationStack.resize(_tos * 2);
+ _symStack.resize(_tos * 2);
+ }
+
+ _stateStack[_tos] = action;
+
+ if (yytoken == -1 && -TERMINAL_COUNT != action_index[action]) {
+ yyloc = consumeToken();
+ yytoken = tokenKind(yyloc);
+ if (yyrecovering)
+ --yyrecovering;
+ if (yytoken == T_IDENTIFIER && t_action(action, T_TYPE_NAME) != 0) {
+ const Token &la = tokenAt(_index);
+
+ if (la.is(T_IDENTIFIER)) {
+ yytoken = T_TYPE_NAME;
+ } else if (la.is(T_LEFT_BRACKET) && la.matchingBrace != 0 &&
+ tokenAt(la.matchingBrace + 1).is(T_IDENTIFIER)) {
+ yytoken = T_TYPE_NAME;
+ }
+ }
+ yyval = _tokens.at(yyloc).ptr;
+ }
+
+ action = t_action(action, yytoken);
+ if (action > 0) {
+ if (action == ACCEPT_STATE) {
+ --_tos;
+ return _symStack[0].translation_unit;
+ }
+ _symStack[_tos].ptr = yyval;
+ _locationStack[_tos] = yyloc;
+ yytoken = -1;
+ } else if (action < 0) {
+ const int ruleno = -action - 1;
+ const int N = rhs[ruleno];
+ _tos -= N;
+ reduce(ruleno);
+ action = nt_action(_stateStack[_tos], lhs[ruleno] - TERMINAL_COUNT);
+ } else if (action == 0) {
+ const int line = _tokens[yyloc].line + 1;
+ QString message = QLatin1String("Syntax error");
+ if (yytoken != -1) {
+ const QLatin1String s(spell[yytoken]);
+ message = QString("Unexpected token `%1'").arg(s);
+ }
+
+ for (; _tos; --_tos) {
+ const int state = _stateStack[_tos];
+
+ static int tks[] = {
+ T_RIGHT_BRACE, T_RIGHT_PAREN, T_RIGHT_BRACKET,
+ T_SEMICOLON, T_COMMA, T_COLON,
+ T_NUMBER, T_TYPE_NAME, T_IDENTIFIER,
+ T_LEFT_BRACE, T_LEFT_PAREN, T_LEFT_BRACKET,
+ T_WHILE,
+ 0
+ };
+
+ for (int *tptr = tks; *tptr; ++tptr) {
+ const int next = t_action(state, *tptr);
+ if (next > 0) {
+ if (! yyrecovering && ! _recovered) {
+ _recovered = true;
+ error(line, QString("Expected `%1'").arg(QLatin1String(spell[*tptr])));
+ }
+
+ yyrecovering = 3;
+ if (*tptr == T_IDENTIFIER)
+ yyval = (void *) _engine->identifier(QLatin1String("$identifier"));
+ else if (*tptr == T_NUMBER || *tptr == T_TYPE_NAME)
+ yyval = (void *) _engine->identifier(QLatin1String("$0"));
+ else
+ yyval = 0;
+
+ _symStack[_tos].ptr = yyval;
+ _locationStack[_tos] = yyloc;
+ yytoken = -1;
+
+ action = next;
+ goto again;
+ }
+ }
+ }
+
+ if (! _recovered) {
+ _recovered = true;
+ error(line, message);
+ }
+ }
+
+ } while (action);
+
+ return 0;
+}
+./
+
+
+
+/.
+void Parser::reduce(int ruleno)
+{
+switch(ruleno) {
+./
+
+
+
+variable_identifier ::= IDENTIFIER ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<IdentifierExpressionAST>(string(1));
+} break;
+./
+
+primary_expression ::= NUMBER ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<LiteralExpressionAST>(string(1));
+} break;
+./
+
+primary_expression ::= TRUE ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<LiteralExpressionAST>(_engine->identifier("true", 4));
+} break;
+./
+
+primary_expression ::= FALSE ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<LiteralExpressionAST>(_engine->identifier("false", 5));
+} break;
+./
+
+primary_expression ::= variable_identifier ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+primary_expression ::= LEFT_PAREN expression RIGHT_PAREN ;
+/.
+case $rule_number: {
+ ast(1) = ast(2);
+} break;
+./
+
+postfix_expression ::= primary_expression ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+postfix_expression ::= postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_ArrayAccess, expression(1), expression(3));
+} break;
+./
+
+postfix_expression ::= function_call ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+postfix_expression ::= postfix_expression DOT IDENTIFIER ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<MemberAccessExpressionAST>(expression(1), string(3));
+} break;
+./
+
+postfix_expression ::= postfix_expression INC_OP ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<UnaryExpressionAST>(AST::Kind_PostIncrement, expression(1));
+} break;
+./
+
+postfix_expression ::= postfix_expression DEC_OP ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<UnaryExpressionAST>(AST::Kind_PostDecrement, expression(1));
+} break;
+./
+
+integer_expression ::= expression ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+function_call ::= function_call_or_method ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+function_call_or_method ::= function_call_generic ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<FunctionCallExpressionAST>
+ (sym(1).function.id, sym(1).function.arguments);
+} break;
+./
+
+function_call_or_method ::= postfix_expression DOT function_call_generic ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<FunctionCallExpressionAST>
+ (expression(1), sym(3).function.id, sym(3).function.arguments);
+} break;
+./
+
+function_call_generic ::= function_call_header_with_parameters RIGHT_PAREN ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+function_call_generic ::= function_call_header_no_parameters RIGHT_PAREN ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+function_call_header_no_parameters ::= function_call_header VOID ;
+/.
+case $rule_number: {
+ sym(1).function.id = sym(1).function_identifier;
+ sym(1).function.arguments = 0;
+} break;
+./
+
+function_call_header_no_parameters ::= function_call_header ;
+/.
+case $rule_number: {
+ sym(1).function.id = sym(1).function_identifier;
+ sym(1).function.arguments = 0;
+} break;
+./
+
+function_call_header_with_parameters ::= function_call_header assignment_expression ;
+/.
+case $rule_number: {
+ sym(1).function.id = sym(1).function_identifier;
+ sym(1).function.arguments =
+ makeAstNode< List<ExpressionAST *> >(expression(2));
+} break;
+./
+
+function_call_header_with_parameters ::= function_call_header_with_parameters COMMA assignment_expression ;
+/.
+case $rule_number: {
+ sym(1).function.arguments =
+ makeAstNode< List<ExpressionAST *> >
+ (sym(1).function.arguments, expression(3));
+} break;
+./
+
+function_call_header ::= function_identifier LEFT_PAREN ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+function_identifier ::= type_specifier ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<FunctionIdentifierAST>(type(1));
+} break;
+./
+
+function_identifier ::= IDENTIFIER ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<FunctionIdentifierAST>(string(1));
+} break;
+./
+
+unary_expression ::= postfix_expression ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+unary_expression ::= INC_OP unary_expression ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<UnaryExpressionAST>(AST::Kind_PreIncrement, expression(2));
+} break;
+./
+
+unary_expression ::= DEC_OP unary_expression ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<UnaryExpressionAST>(AST::Kind_PreDecrement, expression(2));
+} break;
+./
+
+unary_expression ::= unary_operator unary_expression ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<UnaryExpressionAST>(sym(1).kind, expression(2));
+} break;
+./
+
+unary_operator ::= PLUS ;
+/.
+case $rule_number: {
+ sym(1).kind = AST::Kind_UnaryPlus;
+} break;
+./
+
+unary_operator ::= DASH ;
+/.
+case $rule_number: {
+ sym(1).kind = AST::Kind_UnaryMinus;
+} break;
+./
+
+unary_operator ::= BANG ;
+/.
+case $rule_number: {
+ sym(1).kind = AST::Kind_LogicalNot;
+} break;
+./
+
+unary_operator ::= TILDE ;
+/.
+case $rule_number: {
+ sym(1).kind = AST::Kind_BitwiseNot;
+} break;
+./
+
+multiplicative_expression ::= unary_expression ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+multiplicative_expression ::= multiplicative_expression STAR unary_expression ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_Multiply, expression(1), expression(3));
+} break;
+./
+
+multiplicative_expression ::= multiplicative_expression SLASH unary_expression ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_Divide, expression(1), expression(3));
+} break;
+./
+
+multiplicative_expression ::= multiplicative_expression PERCENT unary_expression ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_Modulus, expression(1), expression(3));
+} break;
+./
+
+additive_expression ::= multiplicative_expression ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+additive_expression ::= additive_expression PLUS multiplicative_expression ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_Plus, expression(1), expression(3));
+} break;
+./
+
+additive_expression ::= additive_expression DASH multiplicative_expression ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_Minus, expression(1), expression(3));
+} break;
+./
+
+shift_expression ::= additive_expression ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+shift_expression ::= shift_expression LEFT_OP additive_expression ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_ShiftLeft, expression(1), expression(3));
+} break;
+./
+
+shift_expression ::= shift_expression RIGHT_OP additive_expression ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_ShiftRight, expression(1), expression(3));
+} break;
+./
+
+relational_expression ::= shift_expression ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+relational_expression ::= relational_expression LEFT_ANGLE shift_expression ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_LessThan, expression(1), expression(3));
+} break;
+./
+
+relational_expression ::= relational_expression RIGHT_ANGLE shift_expression ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_GreaterThan, expression(1), expression(3));
+} break;
+./
+
+relational_expression ::= relational_expression LE_OP shift_expression ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_LessEqual, expression(1), expression(3));
+} break;
+./
+
+relational_expression ::= relational_expression GE_OP shift_expression ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_GreaterEqual, expression(1), expression(3));
+} break;
+./
+
+equality_expression ::= relational_expression ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+equality_expression ::= equality_expression EQ_OP relational_expression ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_Equal, expression(1), expression(3));
+} break;
+./
+
+equality_expression ::= equality_expression NE_OP relational_expression ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_NotEqual, expression(1), expression(3));
+} break;
+./
+
+and_expression ::= equality_expression ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+and_expression ::= and_expression AMPERSAND equality_expression ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_BitwiseAnd, expression(1), expression(3));
+} break;
+./
+
+exclusive_or_expression ::= and_expression ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+exclusive_or_expression ::= exclusive_or_expression CARET and_expression ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_BitwiseXor, expression(1), expression(3));
+} break;
+./
+
+inclusive_or_expression ::= exclusive_or_expression ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+inclusive_or_expression ::= inclusive_or_expression VERTICAL_BAR exclusive_or_expression ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_BitwiseOr, expression(1), expression(3));
+} break;
+./
+
+logical_and_expression ::= inclusive_or_expression ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+logical_and_expression ::= logical_and_expression AND_OP inclusive_or_expression ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_LogicalAnd, expression(1), expression(3));
+} break;
+./
+
+logical_xor_expression ::= logical_and_expression ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+logical_xor_expression ::= logical_xor_expression XOR_OP logical_and_expression ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_LogicalXor, expression(1), expression(3));
+} break;
+./
+
+logical_or_expression ::= logical_xor_expression ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+logical_or_expression ::= logical_or_expression OR_OP logical_xor_expression ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_LogicalOr, expression(1), expression(3));
+} break;
+./
+
+conditional_expression ::= logical_or_expression ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+conditional_expression ::= logical_or_expression QUESTION expression COLON assignment_expression ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<TernaryExpressionAST>(AST::Kind_Conditional, expression(1), expression(3), expression(5));
+} break;
+./
+
+assignment_expression ::= conditional_expression ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+assignment_expression ::= unary_expression assignment_operator assignment_expression ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<AssignmentExpressionAST>(sym(2).kind, expression(1), expression(3));
+} break;
+./
+
+assignment_operator ::= EQUAL ;
+/.
+case $rule_number: {
+ sym(1).kind = AST::Kind_Assign;
+} break;
+./
+
+assignment_operator ::= MUL_ASSIGN ;
+/.
+case $rule_number: {
+ sym(1).kind = AST::Kind_AssignMultiply;
+} break;
+./
+
+assignment_operator ::= DIV_ASSIGN ;
+/.
+case $rule_number: {
+ sym(1).kind = AST::Kind_AssignDivide;
+} break;
+./
+
+assignment_operator ::= MOD_ASSIGN ;
+/.
+case $rule_number: {
+ sym(1).kind = AST::Kind_AssignModulus;
+} break;
+./
+
+assignment_operator ::= ADD_ASSIGN ;
+/.
+case $rule_number: {
+ sym(1).kind = AST::Kind_AssignPlus;
+} break;
+./
+
+assignment_operator ::= SUB_ASSIGN ;
+/.
+case $rule_number: {
+ sym(1).kind = AST::Kind_AssignMinus;
+} break;
+./
+
+assignment_operator ::= LEFT_ASSIGN ;
+/.
+case $rule_number: {
+ sym(1).kind = AST::Kind_AssignShiftLeft;
+} break;
+./
+
+assignment_operator ::= RIGHT_ASSIGN ;
+/.
+case $rule_number: {
+ sym(1).kind = AST::Kind_AssignShiftRight;
+} break;
+./
+
+assignment_operator ::= AND_ASSIGN ;
+/.
+case $rule_number: {
+ sym(1).kind = AST::Kind_AssignAnd;
+} break;
+./
+
+assignment_operator ::= XOR_ASSIGN ;
+/.
+case $rule_number: {
+ sym(1).kind = AST::Kind_AssignXor;
+} break;
+./
+
+assignment_operator ::= OR_ASSIGN ;
+/.
+case $rule_number: {
+ sym(1).kind = AST::Kind_AssignOr;
+} break;
+./
+
+expression ::= assignment_expression ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+expression ::= expression COMMA assignment_expression ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_Comma, expression(1), expression(3));
+} break;
+./
+
+constant_expression ::= conditional_expression ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+declaration ::= function_prototype SEMICOLON ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+declaration ::= init_declarator_list SEMICOLON ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<InitDeclarationAST>(sym(1).declaration_list);
+} break;
+./
+
+declaration ::= PRECISION precision_qualifier type_specifier_no_prec SEMICOLON ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<PrecisionDeclarationAST>(sym(2).precision, type(3));
+} break;
+./
+
+declaration ::= type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE SEMICOLON ;
+/.
+case $rule_number: {
+ if (sym(1).type_qualifier.qualifier != QualifiedTypeAST::Struct) {
+ // TODO: issue an error if the qualifier is not "struct".
+ }
+ TypeAST *type = makeAstNode<StructTypeAST>(string(2), sym(4).field_list);
+ ast(1) = makeAstNode<TypeDeclarationAST>(type);
+} break;
+./
+
+declaration ::= type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE IDENTIFIER SEMICOLON ;
+/.
+case $rule_number: {
+ if ((sym(1).type_qualifier.qualifier & QualifiedTypeAST::Struct) == 0) {
+ // TODO: issue an error if the qualifier does not contain "struct".
+ }
+ TypeAST *type = makeAstNode<StructTypeAST>(string(2), sym(4).field_list);
+ TypeAST *qualtype = type;
+ if (sym(1).type_qualifier.qualifier != QualifiedTypeAST::Struct) {
+ qualtype = makeAstNode<QualifiedTypeAST>
+ (sym(1).type_qualifier.qualifier & ~QualifiedTypeAST::Struct, qualtype,
+ sym(1).type_qualifier.layout_list);
+ }
+ ast(1) = makeAstNode<TypeAndVariableDeclarationAST>
+ (makeAstNode<TypeDeclarationAST>(type),
+ makeAstNode<VariableDeclarationAST>(qualtype, string(6)));
+} break;
+./
+
+declaration ::= type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE IDENTIFIER LEFT_BRACKET RIGHT_BRACKET SEMICOLON ;
+/.
+case $rule_number: {
+ if ((sym(1).type_qualifier.qualifier & QualifiedTypeAST::Struct) == 0) {
+ // TODO: issue an error if the qualifier does not contain "struct".
+ }
+ TypeAST *type = makeAstNode<StructTypeAST>(string(2), sym(4).field_list);
+ TypeAST *qualtype = type;
+ if (sym(1).type_qualifier.qualifier != QualifiedTypeAST::Struct) {
+ qualtype = makeAstNode<QualifiedTypeAST>
+ (sym(1).type_qualifier.qualifier & ~QualifiedTypeAST::Struct, qualtype,
+ sym(1).type_qualifier.layout_list);
+ }
+ ast(1) = makeAstNode<TypeAndVariableDeclarationAST>
+ (makeAstNode<TypeDeclarationAST>(type),
+ makeAstNode<VariableDeclarationAST>
+ (makeAstNode<ArrayTypeAST>(qualtype), string(6)));
+} break;
+./
+
+declaration ::= type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET SEMICOLON ;
+/.
+case $rule_number: {
+ if ((sym(1).type_qualifier.qualifier & QualifiedTypeAST::Struct) == 0) {
+ // TODO: issue an error if the qualifier does not contain "struct".
+ }
+ TypeAST *type = makeAstNode<StructTypeAST>(string(2), sym(4).field_list);
+ TypeAST *qualtype = type;
+ if (sym(1).type_qualifier.qualifier != QualifiedTypeAST::Struct) {
+ qualtype = makeAstNode<QualifiedTypeAST>
+ (sym(1).type_qualifier.qualifier & ~QualifiedTypeAST::Struct, qualtype,
+ sym(1).type_qualifier.layout_list);
+ }
+ ast(1) = makeAstNode<TypeAndVariableDeclarationAST>
+ (makeAstNode<TypeDeclarationAST>(type),
+ makeAstNode<VariableDeclarationAST>
+ (makeAstNode<ArrayTypeAST>(qualtype, expression(8)), string(6)));
+} break;
+./
+
+declaration ::= type_qualifier SEMICOLON ;
+/.
+case $rule_number: {
+ TypeAST *type = makeAstNode<QualifiedTypeAST>
+ (sym(1).type_qualifier.qualifier, (TypeAST *)0,
+ sym(1).type_qualifier.layout_list);
+ ast(1) = makeAstNode<TypeDeclarationAST>(type);
+} break;
+./
+
+function_prototype ::= function_declarator RIGHT_PAREN ;
+/.
+case $rule_number: {
+ function(1)->finishParams();
+} break;
+./
+
+function_declarator ::= function_header ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+function_declarator ::= function_header_with_parameters ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+function_header_with_parameters ::= function_header parameter_declaration ;
+/.
+case $rule_number: {
+ function(1)->params = makeAstNode< List<ParameterDeclarationAST *> >
+ (sym(2).param_declaration);
+} break;
+./
+
+function_header_with_parameters ::= function_header_with_parameters COMMA parameter_declaration ;
+/.
+case $rule_number: {
+ function(1)->params = makeAstNode< List<ParameterDeclarationAST *> >
+ (function(1)->params, sym(3).param_declaration);
+} break;
+./
+
+function_header ::= fully_specified_type IDENTIFIER LEFT_PAREN ;
+/.
+case $rule_number: {
+ function(1) = makeAstNode<FunctionDeclarationAST>(type(1), string(2));
+} break;
+./
+
+parameter_declarator ::= type_specifier IDENTIFIER ;
+/.
+case $rule_number: {
+ sym(1).param_declarator.type = type(1);
+ sym(1).param_declarator.name = string(2);
+} break;
+./
+
+parameter_declarator ::= type_specifier IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET ;
+/.
+case $rule_number: {
+ sym(1).param_declarator.type = makeAstNode<ArrayTypeAST>(type(1), expression(4));
+ sym(1).param_declarator.name = string(2);
+} break;
+./
+
+parameter_declaration ::= parameter_type_qualifier parameter_qualifier parameter_declarator ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<ParameterDeclarationAST>
+ (makeAstNode<QualifiedTypeAST>
+ (sym(1).qualifier, sym(3).param_declarator.type,
+ (List<LayoutQualifier *> *)0),
+ ParameterDeclarationAST::Qualifier(sym(2).qualifier),
+ sym(3).param_declarator.name);
+} break;
+./
+
+parameter_declaration ::= parameter_qualifier parameter_declarator ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<ParameterDeclarationAST>
+ (sym(2).param_declarator.type,
+ ParameterDeclarationAST::Qualifier(sym(1).qualifier),
+ sym(2).param_declarator.name);
+} break;
+./
+
+parameter_declaration ::= parameter_type_qualifier parameter_qualifier parameter_type_specifier ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<ParameterDeclarationAST>
+ (makeAstNode<QualifiedTypeAST>
+ (sym(1).qualifier, type(3), (List<LayoutQualifier *> *)0),
+ ParameterDeclarationAST::Qualifier(sym(2).qualifier),
+ (const QString *)0);
+} break;
+./
+
+parameter_declaration ::= parameter_qualifier parameter_type_specifier ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<ParameterDeclarationAST>
+ (type(2), ParameterDeclarationAST::Qualifier(sym(1).qualifier),
+ (const QString *)0);
+} break;
+./
+
+parameter_qualifier ::= empty ;
+/.
+case $rule_number: {
+ sym(1).qualifier = ParameterDeclarationAST::In;
+} break;
+./
+
+parameter_qualifier ::= IN ;
+/.
+case $rule_number: {
+ sym(1).qualifier = ParameterDeclarationAST::In;
+} break;
+./
+
+parameter_qualifier ::= OUT ;
+/.
+case $rule_number: {
+ sym(1).qualifier = ParameterDeclarationAST::Out;
+} break;
+./
+
+parameter_qualifier ::= INOUT ;
+/.
+case $rule_number: {
+ sym(1).qualifier = ParameterDeclarationAST::InOut;
+} break;
+./
+
+parameter_type_specifier ::= type_specifier ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+init_declarator_list ::= single_declaration ;
+/.
+case $rule_number: {
+ sym(1).declaration_list = makeAstNode< List<DeclarationAST *> >
+ (sym(1).declaration);
+} break;
+./
+
+init_declarator_list ::= init_declarator_list COMMA IDENTIFIER ;
+/.
+case $rule_number: {
+ TypeAST *type = VariableDeclarationAST::declarationType(sym(1).declaration_list);
+ DeclarationAST *decl = makeAstNode<VariableDeclarationAST>(type, string(3));
+ sym(1).declaration_list = makeAstNode< List<DeclarationAST *> >
+ (sym(1).declaration_list, decl);
+} break;
+./
+
+init_declarator_list ::= init_declarator_list COMMA IDENTIFIER LEFT_BRACKET RIGHT_BRACKET ;
+/.
+case $rule_number: {
+ TypeAST *type = VariableDeclarationAST::declarationType(sym(1).declaration_list);
+ type = makeAstNode<ArrayTypeAST>(type);
+ DeclarationAST *decl = makeAstNode<VariableDeclarationAST>(type, string(3));
+ sym(1).declaration_list = makeAstNode< List<DeclarationAST *> >
+ (sym(1).declaration_list, decl);
+} break;
+./
+
+init_declarator_list ::= init_declarator_list COMMA IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET ;
+/.
+case $rule_number: {
+ TypeAST *type = VariableDeclarationAST::declarationType(sym(1).declaration_list);
+ type = makeAstNode<ArrayTypeAST>(type, expression(5));
+ DeclarationAST *decl = makeAstNode<VariableDeclarationAST>(type, string(3));
+ sym(1).declaration_list = makeAstNode< List<DeclarationAST *> >
+ (sym(1).declaration_list, decl);
+} break;
+./
+
+init_declarator_list ::= init_declarator_list COMMA IDENTIFIER LEFT_BRACKET RIGHT_BRACKET EQUAL initializer ;
+/.
+case $rule_number: {
+ TypeAST *type = VariableDeclarationAST::declarationType(sym(1).declaration_list);
+ type = makeAstNode<ArrayTypeAST>(type);
+ DeclarationAST *decl = makeAstNode<VariableDeclarationAST>
+ (type, string(3), expression(7));
+ sym(1).declaration_list = makeAstNode< List<DeclarationAST *> >
+ (sym(1).declaration_list, decl);
+} break;
+./
+
+init_declarator_list ::= init_declarator_list COMMA IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET EQUAL initializer ;
+/.
+case $rule_number: {
+ TypeAST *type = VariableDeclarationAST::declarationType(sym(1).declaration_list);
+ type = makeAstNode<ArrayTypeAST>(type, expression(5));
+ DeclarationAST *decl = makeAstNode<VariableDeclarationAST>
+ (type, string(3), expression(8));
+ sym(1).declaration_list = makeAstNode< List<DeclarationAST *> >
+ (sym(1).declaration_list, decl);
+} break;
+./
+
+init_declarator_list ::= init_declarator_list COMMA IDENTIFIER EQUAL initializer ;
+/.
+case $rule_number: {
+ TypeAST *type = VariableDeclarationAST::declarationType(sym(1).declaration_list);
+ DeclarationAST *decl = makeAstNode<VariableDeclarationAST>
+ (type, string(3), expression(5));
+ sym(1).declaration_list = makeAstNode< List<DeclarationAST *> >
+ (sym(1).declaration_list, decl);
+} break;
+./
+
+single_declaration ::= fully_specified_type ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<TypeDeclarationAST>(type(1));
+} break;
+./
+
+single_declaration ::= fully_specified_type IDENTIFIER ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<VariableDeclarationAST>(type(1), string(2));
+} break;
+./
+
+single_declaration ::= fully_specified_type IDENTIFIER LEFT_BRACKET RIGHT_BRACKET ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<VariableDeclarationAST>
+ (makeAstNode<ArrayTypeAST>(type(1)), string(2));
+} break;
+./
+
+single_declaration ::= fully_specified_type IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<VariableDeclarationAST>
+ (makeAstNode<ArrayTypeAST>(type(1), expression(4)), string(2));
+} break;
+./
+
+single_declaration ::= fully_specified_type IDENTIFIER LEFT_BRACKET RIGHT_BRACKET EQUAL initializer ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<VariableDeclarationAST>
+ (makeAstNode<ArrayTypeAST>(type(1)), string(2), expression(6));
+} break;
+./
+
+single_declaration ::= fully_specified_type IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET EQUAL initializer ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<VariableDeclarationAST>
+ (makeAstNode<ArrayTypeAST>(type(1), expression(4)),
+ string(2), expression(7));
+} break;
+./
+
+single_declaration ::= fully_specified_type IDENTIFIER EQUAL initializer ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<VariableDeclarationAST>
+ (type(1), string(2), expression(4));
+} break;
+./
+
+single_declaration ::= INVARIANT IDENTIFIER ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<InvariantDeclarationAST>(string(2));
+} break;
+./
+
+fully_specified_type ::= type_specifier ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<QualifiedTypeAST>(0, type(1), (List<LayoutQualifier *> *)0);
+} break;
+./
+
+fully_specified_type ::= type_qualifier type_specifier ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<QualifiedTypeAST>
+ (sym(1).type_qualifier.qualifier, type(2),
+ sym(1).type_qualifier.layout_list);
+} break;
+./
+
+invariant_qualifier ::= INVARIANT ;
+/.
+case $rule_number: {
+ sym(1).qualifier = QualifiedTypeAST::Invariant;
+} break;
+./
+
+interpolation_qualifier ::= SMOOTH ;
+/.
+case $rule_number: {
+ sym(1).qualifier = QualifiedTypeAST::Smooth;
+} break;
+./
+
+interpolation_qualifier ::= FLAT ;
+/.
+case $rule_number: {
+ sym(1).qualifier = QualifiedTypeAST::Flat;
+} break;
+./
+
+interpolation_qualifier ::= NOPERSPECTIVE ;
+/.
+case $rule_number: {
+ sym(1).qualifier = QualifiedTypeAST::NoPerspective;
+} break;
+./
+
+layout_qualifier ::= LAYOUT LEFT_PAREN layout_qualifier_id_list RIGHT_PAREN ;
+/.
+case $rule_number: {
+ sym(1) = sym(3);
+} break;
+./
+
+layout_qualifier_id_list ::= layout_qualifier_id ;
+/.
+case $rule_number: {
+ sym(1).layout_list = makeAstNode< List<LayoutQualifier *> >(sym(1).layout);
+} break;
+./
+
+layout_qualifier_id_list ::= layout_qualifier_id_list COMMA layout_qualifier_id ;
+/.
+case $rule_number: {
+ sym(1).layout_list = makeAstNode< List<LayoutQualifier *> >(sym(1).layout_list, sym(3).layout);
+} break;
+./
+
+layout_qualifier_id ::= IDENTIFIER ;
+/.
+case $rule_number: {
+ sym(1).layout = makeAstNode<LayoutQualifier>(string(1), (const QString *)0);
+} break;
+./
+
+layout_qualifier_id ::= IDENTIFIER EQUAL NUMBER ;
+/.
+case $rule_number: {
+ sym(1).layout = makeAstNode<LayoutQualifier>(string(1), string(3));
+} break;
+./
+
+parameter_type_qualifier ::= CONST ;
+/.
+case $rule_number: {
+ sym(1).qualifier = QualifiedTypeAST::Const;
+} break;
+./
+
+type_qualifier ::= storage_qualifier ;
+/.
+case $rule_number: {
+ sym(1).type_qualifier.qualifier = sym(1).qualifier;
+ sym(1).type_qualifier.layout_list = 0;
+} break;
+./
+
+type_qualifier ::= layout_qualifier ;
+/.
+case $rule_number: {
+ sym(1).type_qualifier.layout_list = sym(1).layout_list;
+ sym(1).type_qualifier.qualifier = 0;
+} break;
+./
+
+type_qualifier ::= layout_qualifier storage_qualifier ;
+/.
+case $rule_number: {
+ sym(1).type_qualifier.layout_list = sym(1).layout_list;
+ sym(1).type_qualifier.qualifier = sym(2).qualifier;
+} break;
+./
+
+type_qualifier ::= interpolation_qualifier storage_qualifier ;
+/.
+case $rule_number: {
+ sym(1).type_qualifier.qualifier = sym(1).qualifier | sym(2).qualifier;
+ sym(1).type_qualifier.layout_list = 0;
+} break;
+./
+
+type_qualifier ::= interpolation_qualifier ;
+/.
+case $rule_number: {
+ sym(1).type_qualifier.qualifier = sym(1).qualifier;
+ sym(1).type_qualifier.layout_list = 0;
+} break;
+./
+
+type_qualifier ::= invariant_qualifier storage_qualifier ;
+/.
+case $rule_number: {
+ sym(1).type_qualifier.qualifier = sym(1).qualifier | sym(2).qualifier;
+ sym(1).type_qualifier.layout_list = 0;
+} break;
+./
+
+type_qualifier ::= invariant_qualifier interpolation_qualifier storage_qualifier ;
+/.
+case $rule_number: {
+ sym(1).type_qualifier.qualifier = sym(1).qualifier | sym(2).qualifier | sym(3).qualifier;
+ sym(1).type_qualifier.layout_list = 0;
+} break;
+./
+
+type_qualifier ::= INVARIANT ;
+/.
+case $rule_number: {
+ sym(1).type_qualifier.qualifier = QualifiedTypeAST::Invariant;
+ sym(1).type_qualifier.layout_list = 0;
+} break;
+./
+
+storage_qualifier ::= CONST ;
+/.
+case $rule_number: {
+ sym(1).qualifier = QualifiedTypeAST::Const;
+} break;
+./
+
+storage_qualifier ::= ATTRIBUTE ;
+/.
+case $rule_number: {
+ sym(1).qualifier = QualifiedTypeAST::Attribute;
+} break;
+./
+
+storage_qualifier ::= VARYING ;
+/.
+case $rule_number: {
+ sym(1).qualifier = QualifiedTypeAST::Varying;
+} break;
+./
+
+storage_qualifier ::= CENTROID VARYING ;
+/.
+case $rule_number: {
+ sym(1).qualifier = QualifiedTypeAST::CentroidVarying;
+} break;
+./
+
+storage_qualifier ::= IN ;
+/.
+case $rule_number: {
+ sym(1).qualifier = QualifiedTypeAST::In;
+} break;
+./
+
+storage_qualifier ::= OUT ;
+/.
+case $rule_number: {
+ sym(1).qualifier = QualifiedTypeAST::Out;
+} break;
+./
+
+storage_qualifier ::= CENTROID IN ;
+/.
+case $rule_number: {
+ sym(1).qualifier = QualifiedTypeAST::CentroidIn;
+} break;
+./
+
+storage_qualifier ::= CENTROID OUT ;
+/.
+case $rule_number: {
+ sym(1).qualifier = QualifiedTypeAST::CentroidOut;
+} break;
+./
+
+storage_qualifier ::= PATCH IN ;
+/.
+case $rule_number: {
+ sym(1).qualifier = QualifiedTypeAST::PatchIn;
+} break;
+./
+
+storage_qualifier ::= PATCH OUT ;
+/.
+case $rule_number: {
+ sym(1).qualifier = QualifiedTypeAST::PatchOut;
+} break;
+./
+
+storage_qualifier ::= SAMPLE IN ;
+/.
+case $rule_number: {
+ sym(1).qualifier = QualifiedTypeAST::SampleIn;
+} break;
+./
+
+storage_qualifier ::= SAMPLE OUT ;
+/.
+case $rule_number: {
+ sym(1).qualifier = QualifiedTypeAST::SampleOut;
+} break;
+./
+
+storage_qualifier ::= UNIFORM ;
+/.
+case $rule_number: {
+ sym(1).qualifier = QualifiedTypeAST::Uniform;
+} break;
+./
+
+type_specifier ::= type_specifier_no_prec ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+type_specifier ::= precision_qualifier type_specifier_no_prec ;
+/.
+case $rule_number: {
+ if (!type(2)->setPrecision(sym(1).precision)) {
+ // TODO: issue an error about precision not allowed on this type.
+ }
+ ast(1) = type(2);
+} break;
+./
+
+type_specifier_no_prec ::= type_specifier_nonarray ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+type_specifier_no_prec ::= type_specifier_nonarray LEFT_BRACKET RIGHT_BRACKET ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<ArrayTypeAST>(type(1));
+} break;
+./
+
+type_specifier_no_prec ::= type_specifier_nonarray LEFT_BRACKET constant_expression RIGHT_BRACKET ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<ArrayTypeAST>(type(1), expression(3));
+} break;
+./
+
+type_specifier_nonarray ::= VOID ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_VOID);
+} break;
+./
+
+type_specifier_nonarray ::= FLOAT ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_FLOAT);
+} break;
+./
+
+type_specifier_nonarray ::= DOUBLE ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_DOUBLE);
+} break;
+./
+
+type_specifier_nonarray ::= INT ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_INT);
+} break;
+./
+
+type_specifier_nonarray ::= UINT ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_UINT);
+} break;
+./
+
+type_specifier_nonarray ::= BOOL ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_BOOL);
+} break;
+./
+
+type_specifier_nonarray ::= VEC2 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_VEC2);
+} break;
+./
+
+type_specifier_nonarray ::= VEC3 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_VEC3);
+} break;
+./
+
+type_specifier_nonarray ::= VEC4 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_VEC4);
+} break;
+./
+
+type_specifier_nonarray ::= DVEC2 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_DVEC2);
+} break;
+./
+
+type_specifier_nonarray ::= DVEC3 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_DVEC3);
+} break;
+./
+
+type_specifier_nonarray ::= DVEC4 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_DVEC4);
+} break;
+./
+
+type_specifier_nonarray ::= BVEC2 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_BVEC2);
+} break;
+./
+
+type_specifier_nonarray ::= BVEC3 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_BVEC3);
+} break;
+./
+
+type_specifier_nonarray ::= BVEC4 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_BVEC4);
+} break;
+./
+
+type_specifier_nonarray ::= IVEC2 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_IVEC2);
+} break;
+./
+
+type_specifier_nonarray ::= IVEC3 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_IVEC3);
+} break;
+./
+
+type_specifier_nonarray ::= IVEC4 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_IVEC4);
+} break;
+./
+
+type_specifier_nonarray ::= UVEC2 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_UVEC2);
+} break;
+./
+
+type_specifier_nonarray ::= UVEC3 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_UVEC3);
+} break;
+./
+
+type_specifier_nonarray ::= UVEC4 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_UVEC4);
+} break;
+./
+
+type_specifier_nonarray ::= MAT2 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_MAT2);
+} break;
+./
+
+type_specifier_nonarray ::= MAT3 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_MAT3);
+} break;
+./
+
+type_specifier_nonarray ::= MAT4 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_MAT4);
+} break;
+./
+
+type_specifier_nonarray ::= MAT2X2 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_MAT2);
+} break;
+./
+
+type_specifier_nonarray ::= MAT2X3 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_MAT2X3);
+} break;
+./
+
+type_specifier_nonarray ::= MAT2X4 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_MAT2X4);
+} break;
+./
+
+type_specifier_nonarray ::= MAT3X2 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_MAT3X2);
+} break;
+./
+
+type_specifier_nonarray ::= MAT3X3 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_MAT3);
+} break;
+./
+
+type_specifier_nonarray ::= MAT3X4 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_MAT3X4);
+} break;
+./
+
+type_specifier_nonarray ::= MAT4X2 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_MAT4X2);
+} break;
+./
+
+type_specifier_nonarray ::= MAT4X3 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_MAT4X3);
+} break;
+./
+
+type_specifier_nonarray ::= MAT4X4 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_MAT4);
+} break;
+./
+
+type_specifier_nonarray ::= DMAT2 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_DMAT2);
+} break;
+./
+
+type_specifier_nonarray ::= DMAT3 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_DMAT3);
+} break;
+./
+
+type_specifier_nonarray ::= DMAT4 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_DMAT4);
+} break;
+./
+
+type_specifier_nonarray ::= DMAT2X2 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_DMAT2);
+} break;
+./
+
+type_specifier_nonarray ::= DMAT2X3 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_DMAT2X3);
+} break;
+./
+
+type_specifier_nonarray ::= DMAT2X4 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_DMAT2X4);
+} break;
+./
+
+type_specifier_nonarray ::= DMAT3X2 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_DMAT3X2);
+} break;
+./
+
+type_specifier_nonarray ::= DMAT3X3 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_DMAT3);
+} break;
+./
+
+type_specifier_nonarray ::= DMAT3X4 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_DMAT3X4);
+} break;
+./
+
+type_specifier_nonarray ::= DMAT4X2 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_DMAT4X2);
+} break;
+./
+
+type_specifier_nonarray ::= DMAT4X3 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_DMAT4X3);
+} break;
+./
+
+type_specifier_nonarray ::= DMAT4X4 ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_DMAT4);
+} break;
+./
+
+type_specifier_nonarray ::= SAMPLER1D ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_SAMPLER1D);
+} break;
+./
+
+type_specifier_nonarray ::= SAMPLER2D ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_SAMPLER2D);
+} break;
+./
+
+type_specifier_nonarray ::= SAMPLER3D ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_SAMPLER3D);
+} break;
+./
+
+type_specifier_nonarray ::= SAMPLERCUBE ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_SAMPLERCUBE);
+} break;
+./
+
+type_specifier_nonarray ::= SAMPLER1DSHADOW ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_SAMPLER1DSHADOW);
+} break;
+./
+
+type_specifier_nonarray ::= SAMPLER2DSHADOW ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_SAMPLER2DSHADOW);
+} break;
+./
+
+type_specifier_nonarray ::= SAMPLERCUBESHADOW ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_SAMPLERCUBESHADOW);
+} break;
+./
+
+type_specifier_nonarray ::= SAMPLER1DARRAY ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_SAMPLER1DARRAY);
+} break;
+./
+
+type_specifier_nonarray ::= SAMPLER2DARRAY ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_SAMPLER2DARRAY);
+} break;
+./
+
+type_specifier_nonarray ::= SAMPLER1DARRAYSHADOW ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_SAMPLER1DARRAYSHADOW);
+} break;
+./
+
+type_specifier_nonarray ::= SAMPLER2DARRAYSHADOW ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_SAMPLER2DARRAYSHADOW);
+} break;
+./
+
+type_specifier_nonarray ::= SAMPLERCUBEARRAY ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_SAMPLERCUBEARRAY);
+} break;
+./
+
+type_specifier_nonarray ::= SAMPLERCUBEARRAYSHADOW ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_SAMPLERCUBEARRAYSHADOW);
+} break;
+./
+
+type_specifier_nonarray ::= ISAMPLER1D ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_ISAMPLER1D);
+} break;
+./
+
+type_specifier_nonarray ::= ISAMPLER2D ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_ISAMPLER2D);
+} break;
+./
+
+type_specifier_nonarray ::= ISAMPLER3D ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_ISAMPLER3D);
+} break;
+./
+
+type_specifier_nonarray ::= ISAMPLERCUBE ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_ISAMPLERCUBE);
+} break;
+./
+
+type_specifier_nonarray ::= ISAMPLER1DARRAY ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_ISAMPLER1DARRAY);
+} break;
+./
+
+type_specifier_nonarray ::= ISAMPLER2DARRAY ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_ISAMPLER2DARRAY);
+} break;
+./
+
+type_specifier_nonarray ::= ISAMPLERCUBEARRAY ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_ISAMPLERCUBEARRAY);
+} break;
+./
+
+type_specifier_nonarray ::= USAMPLER1D ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_USAMPLER1D);
+} break;
+./
+
+type_specifier_nonarray ::= USAMPLER2D ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_USAMPLER2D);
+} break;
+./
+
+type_specifier_nonarray ::= USAMPLER3D ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_USAMPLER3D);
+} break;
+./
+
+type_specifier_nonarray ::= USAMPLERCUBE ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_USAMPLERCUBE);
+} break;
+./
+
+type_specifier_nonarray ::= USAMPLER1DARRAY ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_USAMPLER1DARRAY);
+} break;
+./
+
+type_specifier_nonarray ::= USAMPLER2DARRAY ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_USAMPLER2DARRAY);
+} break;
+./
+
+type_specifier_nonarray ::= USAMPLERCUBEARRAY ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_USAMPLERCUBEARRAY);
+} break;
+./
+
+type_specifier_nonarray ::= SAMPLER2DRECT ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_SAMPLER2DRECT);
+} break;
+./
+
+type_specifier_nonarray ::= SAMPLER2DRECTSHADOW ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_SAMPLER2DRECTSHADOW);
+} break;
+./
+
+type_specifier_nonarray ::= ISAMPLER2DRECT ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_ISAMPLER2DRECT);
+} break;
+./
+
+type_specifier_nonarray ::= USAMPLER2DRECT ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_USAMPLER2DRECT);
+} break;
+./
+
+type_specifier_nonarray ::= SAMPLERBUFFER ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_SAMPLERBUFFER);
+} break;
+./
+
+type_specifier_nonarray ::= ISAMPLERBUFFER ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_ISAMPLERBUFFER);
+} break;
+./
+
+type_specifier_nonarray ::= USAMPLERBUFFER ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_USAMPLERBUFFER);
+} break;
+./
+
+type_specifier_nonarray ::= SAMPLER2DMS ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_SAMPLER2DMS);
+} break;
+./
+
+type_specifier_nonarray ::= ISAMPLER2DMS ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_ISAMPLER2DMS);
+} break;
+./
+
+type_specifier_nonarray ::= USAMPLER2DMS ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_USAMPLER2DMS);
+} break;
+./
+
+type_specifier_nonarray ::= SAMPLER2DMSARRAY ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_SAMPLER2DMSARRAY);
+} break;
+./
+
+type_specifier_nonarray ::= ISAMPLER2DMSARRAY ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_ISAMPLER2DMSARRAY);
+} break;
+./
+
+type_specifier_nonarray ::= USAMPLER2DMSARRAY ;
+/.
+case $rule_number: {
+ ast(1) = makeBasicType(T_USAMPLER2DMSARRAY);
+} break;
+./
+
+type_specifier_nonarray ::= struct_specifier ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+type_specifier_nonarray ::= TYPE_NAME ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<NamedTypeAST>(string(1));
+} break;
+./
+
+precision_qualifier ::= HIGHP ;
+/.
+case $rule_number: {
+ sym(1).precision = TypeAST::Highp;
+} break;
+./
+
+precision_qualifier ::= MEDIUMP ;
+/.
+case $rule_number: {
+ sym(1).precision = TypeAST::Mediump;
+} break;
+./
+
+precision_qualifier ::= LOWP ;
+/.
+case $rule_number: {
+ sym(1).precision = TypeAST::Lowp;
+} break;
+./
+
+struct_specifier ::= STRUCT IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<StructTypeAST>(string(2), sym(4).field_list);
+} break;
+./
+
+struct_specifier ::= STRUCT LEFT_BRACE struct_declaration_list RIGHT_BRACE ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<StructTypeAST>(sym(3).field_list);
+} break;
+./
+
+struct_declaration_list ::= struct_declaration ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+struct_declaration_list ::= struct_declaration_list struct_declaration ;
+/.
+case $rule_number: {
+ sym(1).field_list = appendLists(sym(1).field_list, sym(2).field_list);
+} break;
+./
+
+struct_declaration ::= type_specifier struct_declarator_list SEMICOLON ;
+/.
+case $rule_number: {
+ sym(1).field_list = StructTypeAST::fixInnerTypes(type(1), sym(2).field_list);
+} break;
+./
+
+struct_declaration ::= type_qualifier type_specifier struct_declarator_list SEMICOLON ;
+/.
+case $rule_number: {
+ sym(1).field_list = StructTypeAST::fixInnerTypes
+ (makeAstNode<QualifiedTypeAST>
+ (sym(1).type_qualifier.qualifier, type(2),
+ sym(1).type_qualifier.layout_list), sym(3).field_list);
+} break;
+./
+
+struct_declarator_list ::= struct_declarator ;
+/.
+case $rule_number: {
+ // nothing to do.
+ sym(1).field_list = makeAstNode< List<StructTypeAST::Field *> >(sym(1).field);
+} break;
+./
+
+struct_declarator_list ::= struct_declarator_list COMMA struct_declarator ;
+/.
+case $rule_number: {
+ sym(1).field_list = makeAstNode< List<StructTypeAST::Field *> >(sym(1).field_list, sym(3).field);
+} break;
+./
+
+struct_declarator ::= IDENTIFIER ;
+/.
+case $rule_number: {
+ sym(1).field = makeAstNode<StructTypeAST::Field>(string(1));
+} break;
+./
+
+struct_declarator ::= IDENTIFIER LEFT_BRACKET RIGHT_BRACKET ;
+/.
+case $rule_number: {
+ sym(1).field = makeAstNode<StructTypeAST::Field>
+ (string(1), makeAstNode<ArrayTypeAST>((TypeAST *)0));
+} break;
+./
+
+struct_declarator ::= IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET ;
+/.
+case $rule_number: {
+ sym(1).field = makeAstNode<StructTypeAST::Field>
+ (string(1), makeAstNode<ArrayTypeAST>((TypeAST *)0, expression(3)));
+} break;
+./
+
+initializer ::= assignment_expression ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+declaration_statement ::= declaration ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<DeclarationStatementAST>(sym(1).declaration);
+} break;
+./
+
+statement ::= compound_statement ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+statement ::= simple_statement ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+simple_statement ::= declaration_statement ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+simple_statement ::= expression_statement ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+simple_statement ::= selection_statement ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+simple_statement ::= switch_statement ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+simple_statement ::= case_label ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+simple_statement ::= iteration_statement ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+simple_statement ::= jump_statement ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+compound_statement ::= LEFT_BRACE RIGHT_BRACE ;
+/.
+case $rule_number: {
+ CompoundStatementAST *stmt = makeAstNode<CompoundStatementAST>();
+ stmt->start = tokenAt(location(1)).begin();
+ stmt->end = tokenAt(location(2)).end();
+ ast(1) = stmt;
+} break;
+./
+
+compound_statement ::= LEFT_BRACE statement_list RIGHT_BRACE ;
+/.
+case $rule_number: {
+ CompoundStatementAST *stmt = makeAstNode<CompoundStatementAST>(sym(2).statement_list);
+ stmt->start = tokenAt(location(1)).begin();
+ stmt->end = tokenAt(location(3)).end();
+ ast(1) = stmt;
+} break;
+./
+
+statement_no_new_scope ::= compound_statement_no_new_scope ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+statement_no_new_scope ::= simple_statement ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+compound_statement_no_new_scope ::= LEFT_BRACE RIGHT_BRACE ;
+/.
+case $rule_number: {
+ CompoundStatementAST *stmt = makeAstNode<CompoundStatementAST>();
+ stmt->start = tokenAt(location(1)).begin();
+ stmt->end = tokenAt(location(2)).end();
+ ast(1) = stmt;
+} break;
+./
+
+compound_statement_no_new_scope ::= LEFT_BRACE statement_list RIGHT_BRACE ;
+/.
+case $rule_number: {
+ CompoundStatementAST *stmt = makeAstNode<CompoundStatementAST>(sym(2).statement_list);
+ stmt->start = tokenAt(location(1)).begin();
+ stmt->end = tokenAt(location(3)).end();
+ ast(1) = stmt;
+} break;
+./
+
+statement_list ::= statement ;
+/.
+case $rule_number: {
+ sym(1).statement_list = makeAstNode< List<StatementAST *> >(sym(1).statement);
+} break;
+./
+
+statement_list ::= statement_list statement ;
+/.
+case $rule_number: {
+ sym(1).statement_list = makeAstNode< List<StatementAST *> >(sym(1).statement_list, sym(2).statement);
+} break;
+./
+
+expression_statement ::= SEMICOLON ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<CompoundStatementAST>(); // Empty statement
+} break;
+./
+
+expression_statement ::= expression SEMICOLON ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<ExpressionStatementAST>(expression(1));
+} break;
+./
+
+selection_statement ::= IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<IfStatementAST>(expression(3), sym(5).ifstmt.thenClause, sym(5).ifstmt.elseClause);
+} break;
+./
+
+selection_rest_statement ::= statement ELSE statement ;
+/.
+case $rule_number: {
+ sym(1).ifstmt.thenClause = statement(1);
+ sym(1).ifstmt.elseClause = statement(3);
+} break;
+./
+
+selection_rest_statement ::= statement ;
+/.
+case $rule_number: {
+ sym(1).ifstmt.thenClause = statement(1);
+ sym(1).ifstmt.elseClause = 0;
+} break;
+./
+
+condition ::= expression ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+condition ::= fully_specified_type IDENTIFIER EQUAL initializer ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<DeclarationExpressionAST>
+ (type(1), string(2), expression(4));
+} break;
+./
+
+switch_statement ::= SWITCH LEFT_PAREN expression RIGHT_PAREN LEFT_BRACE switch_statement_list RIGHT_BRACE ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<SwitchStatementAST>(expression(3), statement(6));
+} break;
+./
+
+switch_statement_list ::= empty ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<CompoundStatementAST>();
+} break;
+./
+
+switch_statement_list ::= statement_list ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<CompoundStatementAST>(sym(1).statement_list);
+} break;
+./
+
+case_label ::= CASE expression COLON ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<CaseLabelStatementAST>(expression(2));
+} break;
+./
+
+case_label ::= DEFAULT COLON ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<CaseLabelStatementAST>();
+} break;
+./
+
+iteration_statement ::= WHILE LEFT_PAREN condition RIGHT_PAREN statement_no_new_scope ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<WhileStatementAST>(expression(3), statement(5));
+} break;
+./
+
+iteration_statement ::= DO statement WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<DoStatementAST>(statement(2), expression(5));
+} break;
+./
+
+iteration_statement ::= FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<ForStatementAST>(statement(3), sym(4).forstmt.condition, sym(4).forstmt.increment, statement(6));
+} break;
+./
+
+for_init_statement ::= expression_statement ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+for_init_statement ::= declaration_statement ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+conditionopt ::= empty ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+conditionopt ::= condition ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+for_rest_statement ::= conditionopt SEMICOLON ;
+/.
+case $rule_number: {
+ sym(1).forstmt.condition = expression(1);
+ sym(1).forstmt.increment = 0;
+} break;
+./
+
+for_rest_statement ::= conditionopt SEMICOLON expression ;
+/.
+case $rule_number: {
+ sym(1).forstmt.condition = expression(1);
+ sym(1).forstmt.increment = expression(3);
+} break;
+./
+
+jump_statement ::= CONTINUE SEMICOLON ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<JumpStatementAST>(AST::Kind_Continue);
+} break;
+./
+
+jump_statement ::= BREAK SEMICOLON ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<JumpStatementAST>(AST::Kind_Break);
+} break;
+./
+
+jump_statement ::= RETURN SEMICOLON ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<ReturnStatementAST>();
+} break;
+./
+
+jump_statement ::= RETURN expression SEMICOLON ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<ReturnStatementAST>(expression(2));
+} break;
+./
+
+jump_statement ::= DISCARD SEMICOLON ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<JumpStatementAST>(AST::Kind_Discard);
+} break;
+./
+
+translation_unit ::= external_declaration_list ;
+/.
+case $rule_number: {
+ ast(1) = makeAstNode<TranslationUnitAST>(sym(1).declaration_list);
+} break;
+./
+
+external_declaration_list ::= external_declaration ;
+/.
+case $rule_number: {
+ if (sym(1).declaration) {
+ sym(1).declaration_list = makeAstNode< List<DeclarationAST *> >
+ (sym(1).declaration);
+ } else {
+ sym(1).declaration_list = 0;
+ }
+} break;
+./
+
+external_declaration_list ::= external_declaration_list external_declaration ;
+/.
+case $rule_number: {
+ if (sym(1).declaration_list && sym(2).declaration) {
+ sym(1).declaration_list = makeAstNode< List<DeclarationAST *> >
+ (sym(1).declaration_list, sym(2).declaration);
+ } else if (!sym(1).declaration_list) {
+ if (sym(2).declaration) {
+ sym(1).declaration_list = makeAstNode< List<DeclarationAST *> >
+ (sym(2).declaration);
+ } else {
+ sym(1).declaration_list = 0;
+ }
+ }
+} break;
+./
+
+external_declaration ::= function_definition ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+external_declaration ::= declaration ;
+/.
+case $rule_number: {
+ // nothing to do.
+} break;
+./
+
+external_declaration ::= SEMICOLON ;
+/.
+case $rule_number: {
+ ast(1) = 0;
+} break;
+./
+
+function_definition ::= function_prototype compound_statement_no_new_scope ;
+/.
+case $rule_number: {
+ function(1)->body = statement(2);
+} break;
+./
+
+empty ::= ;
+/.
+case $rule_number: {
+ ast(1) = 0;
+} break;
+./
+
+
+toplevel ::= FEED_GLSL translation_unit ;
+/.
+case $rule_number: {
+ ast(1) = ast(2);
+} break;
+./
+
+toplevel ::= FEED_EXPRESSION expression ;
+/.
+case $rule_number: {
+ ast(1) = ast(2);
+} break;
+./
+
+/.
+} // end switch
+} // end Parser::reduce()
+./
diff --git a/src/libs/glsl/glsl.h b/src/libs/glsl/glsl.h
new file mode 100644
index 0000000000..25a3967590
--- /dev/null
+++ b/src/libs/glsl/glsl.h
@@ -0,0 +1,83 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 GLSL_H
+#define GLSL_H
+
+#include <QtCore/qglobal.h>
+#include <cstdlib>
+#include <cstddef>
+
+#if defined(GLSL_BUILD_LIB)
+# define GLSL_EXPORT Q_DECL_EXPORT
+#elif defined(GLSL_BUILD_STATIC_LIB)
+# define GLSL_EXPORT
+#else
+# define GLSL_EXPORT Q_DECL_IMPORT
+#endif
+
+namespace GLSL {
+class Engine;
+class Lexer;
+class Parser;
+class MemoryPool;
+
+// types
+class Type;
+class UndefinedType;
+class VoidType;
+class ScalarType;
+class BoolType;
+class IntType;
+class UIntType;
+class FloatType;
+class DoubleType;
+class IndexType;
+class VectorType;
+class MatrixType;
+class ArrayType;
+class SamplerType;
+
+// symbols
+class Symbol;
+class Scope;
+class Struct;
+class Function;
+class Argument;
+class Block;
+class Variable;
+class OverloadSet;
+class Namespace;
+
+class AST;
+class TranslationUnitAST;
+template <typename T> class List;
+}
+
+#endif // GLSL_H
diff --git a/src/libs/glsl/glsl.pri b/src/libs/glsl/glsl.pri
new file mode 100644
index 0000000000..112d313ae6
--- /dev/null
+++ b/src/libs/glsl/glsl.pri
@@ -0,0 +1,6 @@
+INCLUDEPATH += $$PWD/../../shared
+INCLUDEPATH += $$PWD/../../shared/glsl $$PWD/../../shared/glsl/parser
+
+DEPENDPATH += $$PWD/../../shared/glsl $$PWD/../../shared/glsl/parser
+LIBS *= -l$$qtLibraryName(GLSL)
+DEFINES += QT_CREATOR
diff --git a/src/libs/glsl/glsl.pro b/src/libs/glsl/glsl.pro
new file mode 100644
index 0000000000..3041ec1d65
--- /dev/null
+++ b/src/libs/glsl/glsl.pro
@@ -0,0 +1,8 @@
+TEMPLATE = lib
+CONFIG += dll
+TARGET = GLSL
+DEFINES += GLSL_BUILD_LIB QT_CREATOR
+
+include(../../qtcreatorlibrary.pri)
+include(glsl-lib.pri)
+include(../utils/utils.pri)
diff --git a/src/libs/glsl/glslast.cpp b/src/libs/glsl/glslast.cpp
new file mode 100644
index 0000000000..5f02b2b07b
--- /dev/null
+++ b/src/libs/glsl/glslast.cpp
@@ -0,0 +1,427 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "glslast.h"
+#include "glslastvisitor.h"
+#include "glslparsertable_p.h"
+
+using namespace GLSL;
+
+void AST::accept(Visitor *visitor)
+{
+ if (visitor->preVisit(this))
+ accept0(visitor);
+ visitor->postVisit(this);
+}
+
+void AST::accept(AST *ast, Visitor *visitor)
+{
+ if (ast)
+ ast->accept(visitor);
+}
+
+void TranslationUnitAST::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(declarations, visitor);
+ }
+ visitor->endVisit(this);
+}
+
+void IdentifierExpressionAST::accept0(Visitor *visitor)
+{
+ visitor->visit(this);
+ visitor->endVisit(this);
+}
+
+void LiteralExpressionAST::accept0(Visitor *visitor)
+{
+ visitor->visit(this);
+ visitor->endVisit(this);
+}
+
+void BinaryExpressionAST::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(left, visitor);
+ accept(right, visitor);
+ }
+ visitor->endVisit(this);
+}
+
+void UnaryExpressionAST::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this))
+ accept(expr, visitor);
+ visitor->endVisit(this);
+}
+
+void TernaryExpressionAST::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(first, visitor);
+ accept(second, visitor);
+ accept(third, visitor);
+ }
+ visitor->endVisit(this);
+}
+
+void AssignmentExpressionAST::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(variable, visitor);
+ accept(value, visitor);
+ }
+ visitor->endVisit(this);
+}
+
+void MemberAccessExpressionAST::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this))
+ accept(expr, visitor);
+ visitor->endVisit(this);
+}
+
+void FunctionCallExpressionAST::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expr, visitor);
+ accept(id, visitor);
+ accept(arguments, visitor);
+ }
+ visitor->endVisit(this);
+}
+
+void FunctionIdentifierAST::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this))
+ accept(type, visitor);
+ visitor->endVisit(this);
+}
+
+void DeclarationExpressionAST::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(type, visitor);
+ accept(initializer, visitor);
+ }
+ visitor->endVisit(this);
+}
+
+void ExpressionStatementAST::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this))
+ accept(expr, visitor);
+ visitor->endVisit(this);
+}
+
+void CompoundStatementAST::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this))
+ accept(statements, visitor);
+ visitor->endVisit(this);
+}
+
+void IfStatementAST::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(condition, visitor);
+ accept(thenClause, visitor);
+ accept(elseClause, visitor);
+ }
+ visitor->endVisit(this);
+}
+
+void WhileStatementAST::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(condition, visitor);
+ accept(body, visitor);
+ }
+ visitor->endVisit(this);
+}
+
+void DoStatementAST::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(body, visitor);
+ accept(condition, visitor);
+ }
+ visitor->endVisit(this);
+}
+
+void ForStatementAST::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(init, visitor);
+ accept(condition, visitor);
+ accept(increment, visitor);
+ accept(body, visitor);
+ }
+ visitor->endVisit(this);
+}
+
+void JumpStatementAST::accept0(Visitor *visitor)
+{
+ visitor->visit(this);
+ visitor->endVisit(this);
+}
+
+void ReturnStatementAST::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this))
+ accept(expr, visitor);
+ visitor->endVisit(this);
+}
+
+void SwitchStatementAST::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expr, visitor);
+ accept(body, visitor);
+ }
+ visitor->endVisit(this);
+}
+
+void CaseLabelStatementAST::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this))
+ accept(expr, visitor);
+ visitor->endVisit(this);
+}
+
+void DeclarationStatementAST::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this))
+ accept(decl, visitor);
+ visitor->endVisit(this);
+}
+
+BasicTypeAST::BasicTypeAST(int _token, const char *_name)
+ : TypeAST(Kind_BasicType), token(_token), name(_name)
+{
+ switch (token) {
+ case GLSLParserTable::T_VOID:
+ case GLSLParserTable::T_BOOL:
+ case GLSLParserTable::T_BVEC2:
+ case GLSLParserTable::T_BVEC3:
+ case GLSLParserTable::T_BVEC4:
+ prec = PrecNotValid;
+ break;
+ default:
+ prec = PrecUnspecified;
+ break;
+ }
+}
+
+void BasicTypeAST::accept0(Visitor *visitor)
+{
+ visitor->visit(this);
+ visitor->endVisit(this);
+}
+
+TypeAST::Precision BasicTypeAST::precision() const
+{
+ return prec;
+}
+
+bool BasicTypeAST::setPrecision(Precision precision)
+{
+ if (prec == PrecNotValid)
+ return false;
+ prec = precision;
+ return true;
+}
+
+void NamedTypeAST::accept0(Visitor *visitor)
+{
+ visitor->visit(this);
+ visitor->endVisit(this);
+}
+
+TypeAST::Precision NamedTypeAST::precision() const
+{
+ // Named types are typically structs, which cannot have their precision set.
+ return PrecNotValid;
+}
+
+bool NamedTypeAST::setPrecision(Precision)
+{
+ return false;
+}
+
+void ArrayTypeAST::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(elementType, visitor);
+ accept(size, visitor);
+ }
+ visitor->endVisit(this);
+}
+
+TypeAST::Precision ArrayTypeAST::precision() const
+{
+ return elementType ? elementType->precision() : PrecNotValid;
+}
+
+bool ArrayTypeAST::setPrecision(Precision precision)
+{
+ if (elementType)
+ return elementType->setPrecision(precision);
+ else
+ return false;
+}
+
+void StructTypeAST::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this))
+ accept(fields, visitor);
+ visitor->endVisit(this);
+}
+
+TypeAST::Precision StructTypeAST::precision() const
+{
+ return PrecNotValid;
+}
+
+bool StructTypeAST::setPrecision(Precision)
+{
+ // Structs cannot have a precision set.
+ return false;
+}
+
+void StructTypeAST::Field::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this))
+ accept(type, visitor);
+ visitor->endVisit(this);
+}
+
+void StructTypeAST::Field::setInnerType(TypeAST *innerType)
+{
+ if (!innerType)
+ return;
+ TypeAST **parent = &type;
+ TypeAST *inner = type;
+ while (inner != 0) {
+ ArrayTypeAST *array = inner->asArrayType();
+ if (!array)
+ break;
+ parent = &(array->elementType);
+ inner = array->elementType;
+ }
+ *parent = innerType;
+}
+
+List<StructTypeAST::Field *> *StructTypeAST::fixInnerTypes(TypeAST *innerType, List<Field *> *fields)
+{
+ if (!fields)
+ return fields;
+ List<Field *> *head = fields->next;
+ List<Field *> *current = head;
+ do {
+ current->value->setInnerType(innerType);
+ current = current->next;
+ } while (current && current != head);
+ return fields;
+}
+
+void QualifiedTypeAST::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this))
+ accept(type, visitor);
+ visitor->endVisit(this);
+}
+
+void PrecisionDeclarationAST::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this))
+ accept(type, visitor);
+ visitor->endVisit(this);
+}
+
+void ParameterDeclarationAST::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this))
+ accept(type, visitor);
+ visitor->endVisit(this);
+}
+
+void VariableDeclarationAST::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(type, visitor);
+ accept(initializer, visitor);
+ }
+ visitor->endVisit(this);
+}
+
+TypeAST *VariableDeclarationAST::declarationType(List<DeclarationAST *> *decls)
+{
+ VariableDeclarationAST *var = decls->value->asVariableDeclaration();
+ return var ? var->type : 0;
+}
+
+void TypeDeclarationAST::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this))
+ accept(type, visitor);
+ visitor->endVisit(this);
+}
+
+void TypeAndVariableDeclarationAST::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(typeDecl, visitor);
+ accept(varDecl, visitor);
+ }
+ visitor->endVisit(this);
+}
+
+void InvariantDeclarationAST::accept0(Visitor *visitor)
+{
+ visitor->visit(this);
+ visitor->endVisit(this);
+}
+
+void InitDeclarationAST::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this))
+ accept(decls, visitor);
+ visitor->endVisit(this);
+}
+
+void FunctionDeclarationAST::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(returnType, visitor);
+ accept(params, visitor);
+ accept(body, visitor);
+ }
+ visitor->endVisit(this);
+}
diff --git a/src/libs/glsl/glslast.h b/src/libs/glsl/glslast.h
new file mode 100644
index 0000000000..db23ab4264
--- /dev/null
+++ b/src/libs/glsl/glslast.h
@@ -0,0 +1,994 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 GLSLAST_H
+#define GLSLAST_H
+
+#include "glsl.h"
+#include "glslmemorypool.h"
+#include <QtCore/qstring.h>
+
+namespace GLSL {
+
+class AST;
+class TranslationUnitAST;
+class ExpressionAST;
+class IdentifierExpressionAST;
+class LiteralExpressionAST;
+class BinaryExpressionAST;
+class UnaryExpressionAST;
+class TernaryExpressionAST;
+class AssignmentExpressionAST;
+class MemberAccessExpressionAST;
+class FunctionCallExpressionAST;
+class FunctionIdentifierAST;
+class DeclarationExpressionAST;
+class StatementAST;
+class ExpressionStatementAST;
+class CompoundStatementAST;
+class IfStatementAST;
+class WhileStatementAST;
+class DoStatementAST;
+class ForStatementAST;
+class JumpStatementAST;
+class ReturnStatementAST;
+class SwitchStatementAST;
+class CaseLabelStatementAST;
+class DeclarationStatementAST;
+class TypeAST;
+class BasicTypeAST;
+class NamedTypeAST;
+class ArrayTypeAST;
+class StructTypeAST;
+class QualifiedTypeAST;
+class DeclarationAST;
+class PrecisionDeclarationAST;
+class ParameterDeclarationAST;
+class VariableDeclarationAST;
+class TypeDeclarationAST;
+class TypeAndVariableDeclarationAST;
+class InvariantDeclarationAST;
+class InitDeclarationAST;
+class FunctionDeclarationAST;
+class Visitor;
+
+template <typename T>
+class GLSL_EXPORT List: public Managed
+{
+public:
+ List(const T &value)
+ : value(value), next(this), lineno(0) {}
+
+ List(List *previous, const T &value)
+ : value(value), lineno(0)
+ {
+ next = previous->next;
+ previous->next = this;
+ }
+
+ List *finish()
+ {
+ List *head = next;
+ next = 0;
+ return head;
+ }
+
+ T value;
+ List *next;
+ int lineno;
+};
+
+// Append two lists, which are assumed to still be circular, pre-finish.
+template <typename T>
+List<T> *appendLists(List<T> *first, List<T> *second)
+{
+ if (!first)
+ return second;
+ else if (!second)
+ return first;
+ List<T> *firstHead = first->next;
+ List<T> *secondHead = second->next;
+ first->next = secondHead;
+ second->next = firstHead;
+ return second;
+}
+
+class GLSL_EXPORT AST: public Managed
+{
+public:
+ enum Kind {
+ Kind_Undefined,
+
+ // Translation unit
+ Kind_TranslationUnit,
+
+ // Primary expressions
+ Kind_Identifier,
+ Kind_Literal,
+
+ // Unary expressions
+ Kind_PreIncrement,
+ Kind_PostIncrement,
+ Kind_PreDecrement,
+ Kind_PostDecrement,
+ Kind_UnaryPlus,
+ Kind_UnaryMinus,
+ Kind_LogicalNot,
+ Kind_BitwiseNot,
+
+ // Binary expressions
+ Kind_Plus,
+ Kind_Minus,
+ Kind_Multiply,
+ Kind_Divide,
+ Kind_Modulus,
+ Kind_ShiftLeft,
+ Kind_ShiftRight,
+ Kind_Equal,
+ Kind_NotEqual,
+ Kind_LessThan,
+ Kind_LessEqual,
+ Kind_GreaterThan,
+ Kind_GreaterEqual,
+ Kind_LogicalAnd,
+ Kind_LogicalOr,
+ Kind_LogicalXor,
+ Kind_BitwiseAnd,
+ Kind_BitwiseOr,
+ Kind_BitwiseXor,
+ Kind_Comma,
+ Kind_ArrayAccess,
+
+ // Other expressions
+ Kind_Conditional,
+ Kind_MemberAccess,
+ Kind_FunctionCall,
+ Kind_MemberFunctionCall,
+ Kind_FunctionIdentifier,
+ Kind_DeclarationExpression,
+
+ // Assignment expressions
+ Kind_Assign,
+ Kind_AssignPlus,
+ Kind_AssignMinus,
+ Kind_AssignMultiply,
+ Kind_AssignDivide,
+ Kind_AssignModulus,
+ Kind_AssignShiftLeft,
+ Kind_AssignShiftRight,
+ Kind_AssignAnd,
+ Kind_AssignOr,
+ Kind_AssignXor,
+
+ // Statements
+ Kind_ExpressionStatement,
+ Kind_CompoundStatement,
+ Kind_If,
+ Kind_While,
+ Kind_Do,
+ Kind_For,
+ Kind_Break,
+ Kind_Continue,
+ Kind_Discard,
+ Kind_Return,
+ Kind_ReturnExpression,
+ Kind_Switch,
+ Kind_CaseLabel,
+ Kind_DefaultLabel,
+ Kind_DeclarationStatement,
+
+ // Types
+ Kind_BasicType,
+ Kind_NamedType,
+ Kind_ArrayType,
+ Kind_OpenArrayType,
+ Kind_StructType,
+ Kind_AnonymousStructType,
+ Kind_StructField,
+ Kind_QualifiedType,
+
+ // Declarations
+ Kind_PrecisionDeclaration,
+ Kind_ParameterDeclaration,
+ Kind_VariableDeclaration,
+ Kind_TypeDeclaration,
+ Kind_TypeAndVariableDeclaration,
+ Kind_InvariantDeclaration,
+ Kind_InitDeclaration,
+ Kind_FunctionDeclaration
+ };
+
+ virtual TranslationUnitAST *asTranslationUnit() { return 0; }
+
+ virtual ExpressionAST *asExpression() { return 0; }
+ virtual IdentifierExpressionAST *asIdentifierExpression() { return 0; }
+ virtual LiteralExpressionAST *asLiteralExpression() { return 0; }
+ virtual BinaryExpressionAST *asBinaryExpression() { return 0; }
+ virtual UnaryExpressionAST *asUnaryExpression() { return 0; }
+ virtual TernaryExpressionAST *asTernaryExpression() { return 0; }
+ virtual AssignmentExpressionAST *asAssignmentExpression() { return 0; }
+ virtual MemberAccessExpressionAST *asMemberAccessExpression() { return 0; }
+ virtual FunctionCallExpressionAST *asFunctionCallExpression() { return 0; }
+ virtual FunctionIdentifierAST *asFunctionIdentifier() { return 0; }
+ virtual DeclarationExpressionAST *asDeclarationExpression() { return 0; }
+
+ virtual StatementAST *asStatement() { return 0; }
+ virtual ExpressionStatementAST *asExpressionStatement() { return 0; }
+ virtual CompoundStatementAST *asCompoundStatement() { return 0; }
+ virtual IfStatementAST *asIfStatement() { return 0; }
+ virtual WhileStatementAST *asWhileStatement() { return 0; }
+ virtual DoStatementAST *asDoStatement() { return 0; }
+ virtual ForStatementAST *asForStatement() { return 0; }
+ virtual JumpStatementAST *asJumpStatement() { return 0; }
+ virtual ReturnStatementAST *asReturnStatement() { return 0; }
+ virtual SwitchStatementAST *asSwitchStatement() { return 0; }
+ virtual CaseLabelStatementAST *asCaseLabelStatement() { return 0; }
+ virtual DeclarationStatementAST *asDeclarationStatement() { return 0; }
+
+ virtual TypeAST *asType() { return 0; }
+ virtual BasicTypeAST *asBasicType() { return 0; }
+ virtual NamedTypeAST *asNamedType() { return 0; }
+ virtual ArrayTypeAST *asArrayType() { return 0; }
+ virtual StructTypeAST *asStructType() { return 0; }
+ virtual QualifiedTypeAST *asQualifiedType() { return 0; }
+
+ virtual DeclarationAST *asDeclaration() { return 0; }
+ virtual PrecisionDeclarationAST *asPrecisionDeclaration() { return 0; }
+ virtual ParameterDeclarationAST *asParameterDeclaration() { return 0; }
+ virtual VariableDeclarationAST *asVariableDeclaration() { return 0; }
+ virtual TypeDeclarationAST *asTypeDeclaration() { return 0; }
+ virtual TypeAndVariableDeclarationAST *asTypeAndVariableDeclaration() { return 0; }
+ virtual InvariantDeclarationAST *asInvariantDeclaration() { return 0; }
+ virtual InitDeclarationAST *asInitDeclaration() { return 0; }
+ virtual FunctionDeclarationAST *asFunctionDeclaration() { return 0; }
+
+ void accept(Visitor *visitor);
+ static void accept(AST *ast, Visitor *visitor);
+
+ template <typename T>
+ static void accept(List<T> *it, Visitor *visitor)
+ {
+ for (; it; it = it->next)
+ accept(it->value, visitor);
+ }
+
+ virtual void accept0(Visitor *visitor) = 0;
+
+protected:
+ AST(Kind _kind) : kind(_kind), lineno(0) {}
+
+ template <typename T>
+ static List<T> *finish(List<T> *list)
+ {
+ if (! list)
+ return 0;
+ return list->finish(); // convert the circular list with a linked list.
+ }
+
+public: // attributes
+ int kind;
+ int lineno;
+
+protected:
+ ~AST() {} // Managed types cannot be deleted.
+};
+
+class GLSL_EXPORT TranslationUnitAST: public AST
+{
+public:
+ TranslationUnitAST(List<DeclarationAST *> *declarations)
+ : AST(Kind_TranslationUnit), declarations(finish(declarations)) {}
+
+ virtual TranslationUnitAST *asTranslationUnit() { return this; }
+
+ virtual void accept0(Visitor *visitor);
+
+public: // attributes
+ List<DeclarationAST *> *declarations;
+};
+
+class GLSL_EXPORT ExpressionAST: public AST
+{
+protected:
+ ExpressionAST(Kind _kind) : AST(_kind) {}
+
+public:
+ virtual ExpressionAST *asExpression() { return this; }
+};
+
+class GLSL_EXPORT IdentifierExpressionAST: public ExpressionAST
+{
+public:
+ IdentifierExpressionAST(const QString *_name)
+ : ExpressionAST(Kind_Identifier), name(_name) {}
+
+ virtual IdentifierExpressionAST *asIdentifierExpression() { return this; }
+
+ virtual void accept0(Visitor *visitor);
+
+public: // attributes
+ const QString *name;
+};
+
+class GLSL_EXPORT LiteralExpressionAST: public ExpressionAST
+{
+public:
+ LiteralExpressionAST(const QString *_value)
+ : ExpressionAST(Kind_Literal), value(_value) {}
+
+ virtual LiteralExpressionAST *asLiteralExpression() { return this; }
+
+ virtual void accept0(Visitor *visitor);
+
+public: // attributes
+ const QString *value;
+};
+
+class GLSL_EXPORT BinaryExpressionAST: public ExpressionAST
+{
+public:
+ BinaryExpressionAST(Kind _kind, ExpressionAST *_left, ExpressionAST *_right)
+ : ExpressionAST(_kind), left(_left), right(_right) {}
+
+ virtual BinaryExpressionAST *asBinaryExpression() { return this; }
+
+ virtual void accept0(Visitor *visitor);
+
+public: // attributes
+ ExpressionAST *left;
+ ExpressionAST *right;
+};
+
+class GLSL_EXPORT UnaryExpressionAST: public ExpressionAST
+{
+public:
+ UnaryExpressionAST(Kind _kind, ExpressionAST *_expr)
+ : ExpressionAST(_kind), expr(_expr) {}
+
+ virtual UnaryExpressionAST *asUnaryExpression() { return this; }
+
+ virtual void accept0(Visitor *visitor);
+
+public: // attributes
+ ExpressionAST *expr;
+};
+
+class GLSL_EXPORT TernaryExpressionAST: public ExpressionAST
+{
+public:
+ TernaryExpressionAST(Kind _kind, ExpressionAST *_first, ExpressionAST *_second, ExpressionAST *_third)
+ : ExpressionAST(_kind), first(_first), second(_second), third(_third) {}
+
+ virtual TernaryExpressionAST *asTernaryExpression() { return this; }
+
+ virtual void accept0(Visitor *visitor);
+
+public: // attributes
+ ExpressionAST *first;
+ ExpressionAST *second;
+ ExpressionAST *third;
+};
+
+class GLSL_EXPORT AssignmentExpressionAST: public ExpressionAST
+{
+public:
+ AssignmentExpressionAST(Kind _kind, ExpressionAST *_variable, ExpressionAST *_value)
+ : ExpressionAST(_kind), variable(_variable), value(_value) {}
+
+ virtual AssignmentExpressionAST *asAssignmentExpression() { return this; }
+
+ virtual void accept0(Visitor *visitor);
+
+public: // attributes
+ ExpressionAST *variable;
+ ExpressionAST *value;
+};
+
+class GLSL_EXPORT MemberAccessExpressionAST: public ExpressionAST
+{
+public:
+ MemberAccessExpressionAST(ExpressionAST *_expr, const QString *_field)
+ : ExpressionAST(Kind_MemberAccess), expr(_expr), field(_field) {}
+
+ virtual MemberAccessExpressionAST *asMemberAccessExpression() { return this; }
+
+ virtual void accept0(Visitor *visitor);
+
+public: // attributes
+ ExpressionAST *expr;
+ const QString *field;
+};
+
+class GLSL_EXPORT FunctionCallExpressionAST: public ExpressionAST
+{
+public:
+ FunctionCallExpressionAST(FunctionIdentifierAST *_id,
+ List<ExpressionAST *> *_arguments)
+ : ExpressionAST(Kind_FunctionCall), expr(0), id(_id)
+ , arguments(finish(_arguments)) {}
+ FunctionCallExpressionAST(ExpressionAST *_expr, FunctionIdentifierAST *_id,
+ List<ExpressionAST *> *_arguments)
+ : ExpressionAST(Kind_MemberFunctionCall), expr(_expr), id(_id)
+ , arguments(finish(_arguments)) {}
+
+ virtual FunctionCallExpressionAST *asFunctionCallExpression() { return this; }
+
+ virtual void accept0(Visitor *visitor);
+
+public: // attributes
+ ExpressionAST *expr;
+ FunctionIdentifierAST *id;
+ List<ExpressionAST *> *arguments;
+};
+
+class GLSL_EXPORT FunctionIdentifierAST: public AST
+{
+public:
+ FunctionIdentifierAST(const QString *_name)
+ : AST(Kind_FunctionIdentifier), name(_name), type(0) {}
+ FunctionIdentifierAST(TypeAST *_type)
+ : AST(Kind_FunctionIdentifier), name(0), type(_type) {}
+
+ virtual FunctionIdentifierAST *asFunctionIdentifier() { return this; }
+
+ virtual void accept0(Visitor *visitor);
+
+public: // attributes
+ const QString *name;
+ TypeAST *type;
+};
+
+class GLSL_EXPORT DeclarationExpressionAST: public ExpressionAST
+{
+public:
+ DeclarationExpressionAST(TypeAST *_type, const QString *_name,
+ ExpressionAST *_initializer)
+ : ExpressionAST(Kind_DeclarationExpression), type(_type)
+ , name(_name), initializer(_initializer) {}
+
+ virtual DeclarationExpressionAST *asDeclarationExpression() { return this; }
+
+ virtual void accept0(Visitor *visitor);
+
+public: // attributes
+ TypeAST *type;
+ const QString *name;
+ ExpressionAST *initializer;
+};
+
+class GLSL_EXPORT StatementAST: public AST
+{
+protected:
+ StatementAST(Kind _kind) : AST(_kind) {}
+
+public:
+ virtual StatementAST *asStatement() { return this; }
+};
+
+class GLSL_EXPORT ExpressionStatementAST: public StatementAST
+{
+public:
+ ExpressionStatementAST(ExpressionAST *_expr)
+ : StatementAST(Kind_ExpressionStatement), expr(_expr) {}
+
+ virtual ExpressionStatementAST *asExpressionStatement() { return this; }
+
+ virtual void accept0(Visitor *visitor);
+
+public: // attributes
+ ExpressionAST *expr;
+};
+
+class GLSL_EXPORT CompoundStatementAST: public StatementAST
+{
+public:
+ CompoundStatementAST()
+ : StatementAST(Kind_CompoundStatement), statements(0)
+ , start(0), end(0), symbol(0) {}
+ CompoundStatementAST(List<StatementAST *> *_statements)
+ : StatementAST(Kind_CompoundStatement), statements(finish(_statements))
+ , start(0), end(0), symbol(0) {}
+
+ virtual CompoundStatementAST *asCompoundStatement() { return this; }
+
+ virtual void accept0(Visitor *visitor);
+
+public: // attributes
+ List<StatementAST *> *statements;
+ int start;
+ int end;
+ Block *symbol; // decoration
+};
+
+class GLSL_EXPORT IfStatementAST: public StatementAST
+{
+public:
+ IfStatementAST(ExpressionAST *_condition, StatementAST *_thenClause, StatementAST *_elseClause)
+ : StatementAST(Kind_If), condition(_condition)
+ , thenClause(_thenClause), elseClause(_elseClause) {}
+
+ virtual IfStatementAST *asIfStatement() { return this; }
+
+ virtual void accept0(Visitor *visitor);
+
+public: // attributes
+ ExpressionAST *condition;
+ StatementAST *thenClause;
+ StatementAST *elseClause;
+};
+
+class GLSL_EXPORT WhileStatementAST: public StatementAST
+{
+public:
+ WhileStatementAST(ExpressionAST *_condition, StatementAST *_body)
+ : StatementAST(Kind_While), condition(_condition), body(_body) {}
+
+ virtual WhileStatementAST *asWhileStatement() { return this; }
+
+ virtual void accept0(Visitor *visitor);
+
+public: // attributes
+ ExpressionAST *condition;
+ StatementAST *body;
+};
+
+class GLSL_EXPORT DoStatementAST: public StatementAST
+{
+public:
+ DoStatementAST(StatementAST *_body, ExpressionAST *_condition)
+ : StatementAST(Kind_Do), body(_body), condition(_condition) {}
+
+ virtual DoStatementAST *asDoStatement() { return this; }
+
+ virtual void accept0(Visitor *visitor);
+
+public: // attributes
+ StatementAST *body;
+ ExpressionAST *condition;
+};
+
+class GLSL_EXPORT ForStatementAST: public StatementAST
+{
+public:
+ ForStatementAST(StatementAST *_init, ExpressionAST *_condition, ExpressionAST *_increment, StatementAST *_body)
+ : StatementAST(Kind_For), init(_init), condition(_condition), increment(_increment), body(_body) {}
+
+ virtual ForStatementAST *asForStatement() { return this; }
+
+ virtual void accept0(Visitor *visitor);
+
+public: // attributes
+ StatementAST *init;
+ ExpressionAST *condition;
+ ExpressionAST *increment;
+ StatementAST *body;
+};
+
+class GLSL_EXPORT JumpStatementAST: public StatementAST
+{
+public:
+ JumpStatementAST(Kind _kind) : StatementAST(_kind) {}
+
+ virtual JumpStatementAST *asJumpStatement() { return this; }
+
+ virtual void accept0(Visitor *visitor);
+};
+
+class GLSL_EXPORT ReturnStatementAST: public StatementAST
+{
+public:
+ ReturnStatementAST() : StatementAST(Kind_Return), expr(0) {}
+ ReturnStatementAST(ExpressionAST *_expr)
+ : StatementAST(Kind_ReturnExpression), expr(_expr) {}
+
+ virtual ReturnStatementAST *asReturnStatement() { return this; }
+
+ virtual void accept0(Visitor *visitor);
+
+public: // attributes
+ ExpressionAST *expr;
+};
+
+class GLSL_EXPORT SwitchStatementAST: public StatementAST
+{
+public:
+ SwitchStatementAST(ExpressionAST *_expr, StatementAST *_body)
+ : StatementAST(Kind_Switch), expr(_expr), body(_body) {}
+
+ virtual SwitchStatementAST *asSwitchStatement() { return this; }
+
+ virtual void accept0(Visitor *visitor);
+
+public: // attributes
+ ExpressionAST *expr;
+ StatementAST *body;
+};
+
+class GLSL_EXPORT CaseLabelStatementAST: public StatementAST
+{
+public:
+ CaseLabelStatementAST() : StatementAST(Kind_DefaultLabel), expr(0) {}
+ CaseLabelStatementAST(ExpressionAST *_expr)
+ : StatementAST(Kind_CaseLabel), expr(_expr) {}
+
+ virtual CaseLabelStatementAST *asCaseLabelStatement() { return this; }
+
+ virtual void accept0(Visitor *visitor);
+
+public: // attributes
+ ExpressionAST *expr;
+};
+
+class GLSL_EXPORT DeclarationStatementAST: public StatementAST
+{
+public:
+ DeclarationStatementAST(DeclarationAST *_decl)
+ : StatementAST(Kind_DeclarationStatement), decl(_decl) {}
+
+ virtual DeclarationStatementAST *asDeclarationStatement() { return this; }
+
+ virtual void accept0(Visitor *visitor);
+
+public: // attributes
+ DeclarationAST *decl;
+};
+
+class GLSL_EXPORT TypeAST: public AST
+{
+protected:
+ TypeAST(Kind _kind) : AST(_kind) {}
+
+public:
+ enum Precision
+ {
+ PrecNotValid, // Precision not valid (e.g. structs).
+ PrecUnspecified, // Precision not known, but can be validly set.
+ Lowp,
+ Mediump,
+ Highp
+ };
+
+ virtual TypeAST *asType() { return this; }
+
+ virtual Precision precision() const = 0;
+
+ // Set the precision for the innermost basic type. Returns false if it
+ // is not valid to set a precision (e.g. structs).
+ virtual bool setPrecision(Precision precision) = 0;
+};
+
+class GLSL_EXPORT BasicTypeAST: public TypeAST
+{
+public:
+ // Pass the parser's token code: T_VOID, T_VEC4, etc.
+ BasicTypeAST(int _token, const char *_name);
+
+ virtual BasicTypeAST *asBasicType() { return this; }
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual Precision precision() const;
+ virtual bool setPrecision(Precision precision);
+
+public: // attributes
+ Precision prec;
+ int token;
+ const char *name;
+};
+
+class GLSL_EXPORT NamedTypeAST: public TypeAST
+{
+public:
+ NamedTypeAST(const QString *_name) : TypeAST(Kind_NamedType), name(_name) {}
+
+ virtual NamedTypeAST *asNamedType() { return this; }
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual Precision precision() const;
+ virtual bool setPrecision(Precision precision);
+
+public: // attributes
+ const QString *name;
+};
+
+class GLSL_EXPORT ArrayTypeAST: public TypeAST
+{
+public:
+ ArrayTypeAST(TypeAST *_elementType)
+ : TypeAST(Kind_OpenArrayType), elementType(_elementType), size(0) {}
+ ArrayTypeAST(TypeAST *_elementType, ExpressionAST *_size)
+ : TypeAST(Kind_ArrayType), elementType(_elementType), size(_size) {}
+
+ virtual ArrayTypeAST *asArrayType() { return this; }
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual Precision precision() const;
+ virtual bool setPrecision(Precision precision);
+
+public: // attributes
+ TypeAST *elementType;
+ ExpressionAST *size;
+};
+
+class GLSL_EXPORT StructTypeAST: public TypeAST
+{
+public:
+ class Field: public AST
+ {
+ public:
+ Field(const QString *_name)
+ : AST(Kind_StructField), name(_name), type(0) {}
+
+ // Takes the outer shell of an array type with the innermost
+ // element type set to null. The fixInnerTypes() method will
+ // set the innermost element type to a meaningful value.
+ Field(const QString *_name, TypeAST *_type)
+ : AST(Kind_StructField), name(_name), type(_type) {}
+
+ virtual void accept0(Visitor *visitor);
+
+ void setInnerType(TypeAST *innerType);
+
+ const QString *name;
+ TypeAST *type;
+ };
+
+ StructTypeAST(List<Field *> *_fields)
+ : TypeAST(Kind_AnonymousStructType), fields(finish(_fields)) {}
+ StructTypeAST(const QString *_name, List<Field *> *_fields)
+ : TypeAST(Kind_StructType), name(_name), fields(finish(_fields)) {}
+
+ virtual StructTypeAST *asStructType() { return this; }
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual Precision precision() const;
+ virtual bool setPrecision(Precision precision);
+
+ // Fix the inner types of a field list. The "innerType" will
+ // be copied into the "array holes" of all fields.
+ static List<Field *> *fixInnerTypes(TypeAST *innerType, List<Field *> *fields);
+
+public: // attributes
+ const QString *name;
+ List<Field *> *fields;
+};
+
+class GLSL_EXPORT LayoutQualifier
+{
+public:
+ LayoutQualifier(const QString *_name, const QString *_number)
+ : name(_name), number(_number), lineno(0) {}
+
+public: // attributes
+ const QString *name;
+ const QString *number;
+ int lineno;
+};
+
+class GLSL_EXPORT QualifiedTypeAST: public TypeAST
+{
+public:
+ QualifiedTypeAST(int _qualifiers, TypeAST *_type, List<LayoutQualifier *> *_layout_list)
+ : TypeAST(Kind_QualifiedType), qualifiers(_qualifiers), type(_type)
+ , layout_list(finish(_layout_list)) {}
+
+ enum
+ {
+ StorageMask = 0x000000FF,
+ NoStorage = 0x00000000,
+ Const = 0x00000001,
+ Attribute = 0x00000002,
+ Varying = 0x00000003,
+ CentroidVarying = 0x00000004,
+ In = 0x00000005,
+ Out = 0x00000006,
+ CentroidIn = 0x00000007,
+ CentroidOut = 0x00000008,
+ PatchIn = 0x00000009,
+ PatchOut = 0x0000000A,
+ SampleIn = 0x0000000B,
+ SampleOut = 0x0000000C,
+ Uniform = 0x0000000D,
+ InterpolationMask = 0x00000F00,
+ NoInterpolation = 0x00000000,
+ Smooth = 0x00000100,
+ Flat = 0x00000200,
+ NoPerspective = 0x00000300,
+ Invariant = 0x00010000,
+ Struct = 0x00020000
+ };
+
+ virtual QualifiedTypeAST *asQualifiedType() { return this; }
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual Precision precision() const { return type->precision(); }
+ virtual bool setPrecision(Precision precision) { return type->setPrecision(precision); }
+
+public: // attributes
+ int qualifiers;
+ TypeAST *type;
+ List<LayoutQualifier *> *layout_list;
+};
+
+class GLSL_EXPORT DeclarationAST: public AST
+{
+protected:
+ DeclarationAST(Kind _kind) : AST(_kind) {}
+
+public:
+ virtual DeclarationAST *asDeclaration() { return this; }
+};
+
+class GLSL_EXPORT PrecisionDeclarationAST: public DeclarationAST
+{
+public:
+ PrecisionDeclarationAST(TypeAST::Precision _precision, TypeAST *_type)
+ : DeclarationAST(Kind_PrecisionDeclaration)
+ , precision(_precision), type(_type) {}
+
+ virtual PrecisionDeclarationAST *asPrecisionDeclaration() { return this; }
+
+ virtual void accept0(Visitor *visitor);
+
+public: // attributes
+ TypeAST::Precision precision;
+ TypeAST *type;
+};
+
+class GLSL_EXPORT ParameterDeclarationAST: public DeclarationAST
+{
+public:
+ enum Qualifier
+ {
+ In,
+ Out,
+ InOut
+ };
+ ParameterDeclarationAST(TypeAST *_type, Qualifier _qualifier,
+ const QString *_name)
+ : DeclarationAST(Kind_ParameterDeclaration), type(_type)
+ , qualifier(_qualifier), name(_name) {}
+
+ virtual ParameterDeclarationAST *asParameterDeclaration() { return this; }
+
+ virtual void accept0(Visitor *visitor);
+
+public: // attributes
+ TypeAST *type;
+ Qualifier qualifier;
+ const QString *name;
+};
+
+class GLSL_EXPORT VariableDeclarationAST: public DeclarationAST
+{
+public:
+ VariableDeclarationAST(TypeAST *_type, const QString *_name,
+ ExpressionAST *_initializer = 0)
+ : DeclarationAST(Kind_VariableDeclaration), type(_type)
+ , name(_name), initializer(_initializer) {}
+
+ virtual VariableDeclarationAST *asVariableDeclaration() { return this; }
+
+ virtual void accept0(Visitor *visitor);
+
+ static TypeAST *declarationType(List<DeclarationAST *> *decls);
+
+public: // attributes
+ TypeAST *type;
+ const QString *name;
+ ExpressionAST *initializer;
+};
+
+class GLSL_EXPORT TypeDeclarationAST: public DeclarationAST
+{
+public:
+ TypeDeclarationAST(TypeAST *_type)
+ : DeclarationAST(Kind_TypeDeclaration), type(_type) {}
+
+ virtual TypeDeclarationAST *asTypeDeclaration() { return this; }
+
+ virtual void accept0(Visitor *visitor);
+
+public: // attributes
+ TypeAST *type;
+};
+
+class GLSL_EXPORT TypeAndVariableDeclarationAST: public DeclarationAST
+{
+public:
+ TypeAndVariableDeclarationAST(TypeDeclarationAST *_typeDecl,
+ VariableDeclarationAST *_varDecl)
+ : DeclarationAST(Kind_TypeAndVariableDeclaration)
+ , typeDecl(_typeDecl), varDecl(_varDecl) {}
+
+ virtual TypeAndVariableDeclarationAST *asTypeAndVariableDeclaration() { return this; }
+
+ virtual void accept0(Visitor *visitor);
+
+public: // attributes
+ TypeDeclarationAST *typeDecl;
+ VariableDeclarationAST *varDecl;
+};
+
+class GLSL_EXPORT InvariantDeclarationAST: public DeclarationAST
+{
+public:
+ InvariantDeclarationAST(const QString *_name)
+ : DeclarationAST(Kind_InvariantDeclaration), name(_name) {}
+
+ virtual InvariantDeclarationAST *asInvariantDeclaration() { return this; }
+
+ virtual void accept0(Visitor *visitor);
+
+public: // attributes
+ const QString *name;
+};
+
+class GLSL_EXPORT InitDeclarationAST: public DeclarationAST
+{
+public:
+ InitDeclarationAST(List<DeclarationAST *> *_decls)
+ : DeclarationAST(Kind_InitDeclaration), decls(finish(_decls)) {}
+
+ virtual InitDeclarationAST *asInitDeclaration() { return this; }
+
+ virtual void accept0(Visitor *visitor);
+
+public: // attributes
+ List<DeclarationAST *> *decls;
+};
+
+class GLSL_EXPORT FunctionDeclarationAST : public DeclarationAST
+{
+public:
+ FunctionDeclarationAST(TypeAST *_returnType, const QString *_name)
+ : DeclarationAST(Kind_FunctionDeclaration), returnType(_returnType)
+ , name(_name), params(0), body(0) {}
+
+ virtual FunctionDeclarationAST *asFunctionDeclaration() { return this; }
+
+ virtual void accept0(Visitor *visitor);
+
+ void finishParams() { params = finish(params); }
+
+ bool isPrototype() const { return body == 0; }
+
+public: // attributes
+ TypeAST *returnType;
+ const QString *name;
+ List<ParameterDeclarationAST *> *params;
+ StatementAST *body;
+};
+
+} // namespace GLSL
+
+#endif // GLSLAST_H
diff --git a/src/libs/glsl/glslastdump.cpp b/src/libs/glsl/glslastdump.cpp
new file mode 100644
index 0000000000..337e120ed8
--- /dev/null
+++ b/src/libs/glsl/glslastdump.cpp
@@ -0,0 +1,68 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "glslastdump.h"
+#include <QtCore/QTextStream>
+
+#ifdef Q_CC_GNU
+# include <cxxabi.h>
+#endif
+
+using namespace GLSL;
+
+ASTDump::ASTDump(QTextStream &out)
+ : out(out), _depth(0)
+{
+}
+
+void ASTDump::operator()(AST *ast)
+{
+ _depth = 0;
+ accept(ast);
+}
+
+bool ASTDump::preVisit(AST *ast)
+{
+ const char *id = typeid(*ast).name();
+#ifdef Q_CC_GNU
+ char *cppId = abi::__cxa_demangle(id, 0, 0, 0);
+ id = cppId;
+#endif
+ out << QByteArray(_depth, ' ') << id << endl;
+#ifdef Q_CC_GNU
+ free(cppId);
+#endif
+ ++_depth;
+ return true;
+}
+
+void ASTDump::postVisit(AST *)
+{
+ --_depth;
+}
diff --git a/src/libs/glsl/glslastdump.h b/src/libs/glsl/glslastdump.h
new file mode 100644
index 0000000000..c1bc249de3
--- /dev/null
+++ b/src/libs/glsl/glslastdump.h
@@ -0,0 +1,57 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 GLSLASTDUMP_H
+#define GLSLASTDUMP_H
+
+#include "glslastvisitor.h"
+
+QT_FORWARD_DECLARE_CLASS(QTextStream)
+
+namespace GLSL {
+
+class GLSL_EXPORT ASTDump: protected Visitor
+{
+public:
+ ASTDump(QTextStream &out);
+
+ void operator()(AST *ast);
+
+protected:
+ virtual bool preVisit(AST *);
+ virtual void postVisit(AST *);
+
+private:
+ QTextStream &out;
+ int _depth;
+};
+
+} // namespace GLSL
+
+#endif // GLSLASTDUMP_H
diff --git a/src/libs/glsl/glslastvisitor.cpp b/src/libs/glsl/glslastvisitor.cpp
new file mode 100644
index 0000000000..c0d5bbbcaa
--- /dev/null
+++ b/src/libs/glsl/glslastvisitor.cpp
@@ -0,0 +1,46 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "glslastvisitor.h"
+
+using namespace GLSL;
+
+Visitor::Visitor()
+{
+}
+
+Visitor::~Visitor()
+{
+}
+
+void Visitor::accept(AST *ast)
+{
+ if (ast)
+ ast->accept(this);
+}
diff --git a/src/libs/glsl/glslastvisitor.h b/src/libs/glsl/glslastvisitor.h
new file mode 100644
index 0000000000..9c96376433
--- /dev/null
+++ b/src/libs/glsl/glslastvisitor.h
@@ -0,0 +1,158 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 GLSLASTVISITOR_H
+#define GLSLASTVISITOR_H
+
+#include "glslast.h"
+
+namespace GLSL {
+
+class GLSL_EXPORT Visitor
+{
+public:
+ Visitor();
+ virtual ~Visitor();
+
+ void accept(AST *ast);
+
+ virtual bool preVisit(AST *) { return true; }
+ virtual void postVisit(AST *) {}
+
+ virtual bool visit(TranslationUnitAST *) { return true; }
+ virtual void endVisit(TranslationUnitAST *) {}
+
+ virtual bool visit(IdentifierExpressionAST *) { return true; }
+ virtual void endVisit(IdentifierExpressionAST *) {}
+
+ virtual bool visit(LiteralExpressionAST *) { return true; }
+ virtual void endVisit(LiteralExpressionAST *) {}
+
+ virtual bool visit(BinaryExpressionAST *) { return true; }
+ virtual void endVisit(BinaryExpressionAST *) {}
+
+ virtual bool visit(UnaryExpressionAST *) { return true; }
+ virtual void endVisit(UnaryExpressionAST *) {}
+
+ virtual bool visit(TernaryExpressionAST *) { return true; }
+ virtual void endVisit(TernaryExpressionAST *) {}
+
+ virtual bool visit(AssignmentExpressionAST *) { return true; }
+ virtual void endVisit(AssignmentExpressionAST *) {}
+
+ virtual bool visit(MemberAccessExpressionAST *) { return true; }
+ virtual void endVisit(MemberAccessExpressionAST *) {}
+
+ virtual bool visit(FunctionCallExpressionAST *) { return true; }
+ virtual void endVisit(FunctionCallExpressionAST *) {}
+
+ virtual bool visit(FunctionIdentifierAST *) { return true; }
+ virtual void endVisit(FunctionIdentifierAST *) {}
+
+ virtual bool visit(DeclarationExpressionAST *) { return true; }
+ virtual void endVisit(DeclarationExpressionAST *) {}
+
+ virtual bool visit(ExpressionStatementAST *) { return true; }
+ virtual void endVisit(ExpressionStatementAST *) {}
+
+ virtual bool visit(CompoundStatementAST *) { return true; }
+ virtual void endVisit(CompoundStatementAST *) {}
+
+ virtual bool visit(IfStatementAST *) { return true; }
+ virtual void endVisit(IfStatementAST *) {}
+
+ virtual bool visit(WhileStatementAST *) { return true; }
+ virtual void endVisit(WhileStatementAST *) {}
+
+ virtual bool visit(DoStatementAST *) { return true; }
+ virtual void endVisit(DoStatementAST *) {}
+
+ virtual bool visit(ForStatementAST *) { return true; }
+ virtual void endVisit(ForStatementAST *) {}
+
+ virtual bool visit(JumpStatementAST *) { return true; }
+ virtual void endVisit(JumpStatementAST *) {}
+
+ virtual bool visit(ReturnStatementAST *) { return true; }
+ virtual void endVisit(ReturnStatementAST *) {}
+
+ virtual bool visit(SwitchStatementAST *) { return true; }
+ virtual void endVisit(SwitchStatementAST *) {}
+
+ virtual bool visit(CaseLabelStatementAST *) { return true; }
+ virtual void endVisit(CaseLabelStatementAST *) {}
+
+ virtual bool visit(DeclarationStatementAST *) { return true; }
+ virtual void endVisit(DeclarationStatementAST *) {}
+
+ virtual bool visit(BasicTypeAST *) { return true; }
+ virtual void endVisit(BasicTypeAST *) {}
+
+ virtual bool visit(NamedTypeAST *) { return true; }
+ virtual void endVisit(NamedTypeAST *) {}
+
+ virtual bool visit(ArrayTypeAST *) { return true; }
+ virtual void endVisit(ArrayTypeAST *) {}
+
+ virtual bool visit(StructTypeAST *) { return true; }
+ virtual void endVisit(StructTypeAST *) {}
+
+ virtual bool visit(StructTypeAST::Field *) { return true; }
+ virtual void endVisit(StructTypeAST::Field *) {}
+
+ virtual bool visit(QualifiedTypeAST *) { return true; }
+ virtual void endVisit(QualifiedTypeAST *) {}
+
+ virtual bool visit(PrecisionDeclarationAST *) { return true; }
+ virtual void endVisit(PrecisionDeclarationAST *) {}
+
+ virtual bool visit(ParameterDeclarationAST *) { return true; }
+ virtual void endVisit(ParameterDeclarationAST *) {}
+
+ virtual bool visit(VariableDeclarationAST *) { return true; }
+ virtual void endVisit(VariableDeclarationAST *) {}
+
+ virtual bool visit(TypeDeclarationAST *) { return true; }
+ virtual void endVisit(TypeDeclarationAST *) {}
+
+ virtual bool visit(TypeAndVariableDeclarationAST *) { return true; }
+ virtual void endVisit(TypeAndVariableDeclarationAST *) {}
+
+ virtual bool visit(InvariantDeclarationAST *) { return true; }
+ virtual void endVisit(InvariantDeclarationAST *) {}
+
+ virtual bool visit(InitDeclarationAST *) { return true; }
+ virtual void endVisit(InitDeclarationAST *) {}
+
+ virtual bool visit(FunctionDeclarationAST *) { return true; }
+ virtual void endVisit(FunctionDeclarationAST *) {}
+};
+
+} // namespace GLSL
+
+#endif // GLSLASTVISITOR_H
diff --git a/src/libs/glsl/glslengine.cpp b/src/libs/glsl/glslengine.cpp
new file mode 100644
index 0000000000..bd30f7a0dc
--- /dev/null
+++ b/src/libs/glsl/glslengine.cpp
@@ -0,0 +1,291 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "glslengine.h"
+#include "glslsymbols.h"
+#include "glsltypes.h"
+#include "glslparser.h"
+
+using namespace GLSL;
+
+DiagnosticMessage::DiagnosticMessage()
+ : _kind(Error), _line(0)
+{
+}
+
+DiagnosticMessage::Kind DiagnosticMessage::kind() const
+{
+ return _kind;
+}
+
+void DiagnosticMessage::setKind(Kind kind)
+{
+ _kind = kind;
+}
+
+QString DiagnosticMessage::fileName() const
+{
+ return _fileName;
+}
+
+void DiagnosticMessage::setFileName(const QString &fileName)
+{
+ _fileName = fileName;
+}
+
+int DiagnosticMessage::line() const
+{
+ return _line;
+}
+
+void DiagnosticMessage::setLine(int line)
+{
+ _line = line;
+}
+
+QString DiagnosticMessage::message() const
+{
+ return _message;
+}
+
+void DiagnosticMessage::setMessage(const QString &message)
+{
+ _message = message;
+}
+
+Engine::Engine()
+ : _blockDiagnosticMessages(false)
+{
+}
+
+Engine::~Engine()
+{
+ qDeleteAll(_symbols);
+}
+
+const QString *Engine::identifier(const QString &s)
+{
+ return &(*_identifiers.insert(s));
+}
+
+const QString *Engine::identifier(const char *s, int n)
+{
+ return &(*_identifiers.insert(QString::fromLatin1(s, n)));
+}
+
+QSet<QString> Engine::identifiers() const
+{
+ return _identifiers;
+}
+
+const QString *Engine::number(const QString &s)
+{
+ return &(*_numbers.insert(s));
+}
+
+const QString *Engine::number(const char *s, int n)
+{
+ return &(*_numbers.insert(QString::fromLatin1(s, n)));
+}
+
+QSet<QString> Engine::numbers() const
+{
+ return _numbers;
+}
+
+MemoryPool *Engine::pool()
+{
+ return &_pool;
+}
+
+const UndefinedType *Engine::undefinedType()
+{
+ static UndefinedType t;
+ return &t;
+}
+
+const VoidType *Engine::voidType()
+{
+ static VoidType t;
+ return &t;
+}
+
+const BoolType *Engine::boolType()
+{
+ static BoolType t;
+ return &t;
+}
+
+const IntType *Engine::intType()
+{
+ static IntType t;
+ return &t;
+}
+
+const UIntType *Engine::uintType()
+{
+ static UIntType t;
+ return &t;
+}
+
+const FloatType *Engine::floatType()
+{
+ static FloatType t;
+ return &t;
+}
+
+const DoubleType *Engine::doubleType()
+{
+ static DoubleType t;
+ return &t;
+}
+
+const SamplerType *Engine::samplerType(int kind)
+{
+ return _samplerTypes.intern(SamplerType(kind));
+}
+
+const VectorType *Engine::vectorType(const Type *elementType, int dimension)
+{
+ VectorType *type = const_cast<VectorType *>
+ (_vectorTypes.intern(VectorType(elementType, dimension)));
+ type->populateMembers(this);
+ return type;
+}
+
+const MatrixType *Engine::matrixType(const Type *elementType, int columns, int rows)
+{
+ return _matrixTypes.intern(MatrixType(elementType, columns, rows,
+ vectorType(elementType, rows)));
+}
+
+const ArrayType *Engine::arrayType(const Type *elementType)
+{
+ return _arrayTypes.intern(ArrayType(elementType));
+}
+
+
+QList<DiagnosticMessage> Engine::diagnosticMessages() const
+{
+ return _diagnosticMessages;
+}
+
+void Engine::clearDiagnosticMessages()
+{
+ _diagnosticMessages.clear();
+}
+
+void Engine::addDiagnosticMessage(const DiagnosticMessage &m)
+{
+ if (! _blockDiagnosticMessages)
+ _diagnosticMessages.append(m);
+}
+
+void Engine::warning(int line, const QString &message)
+{
+ DiagnosticMessage m;
+ m.setKind(DiagnosticMessage::Warning);
+ m.setLine(line);
+ m.setMessage(message);
+ addDiagnosticMessage(m);
+}
+
+void Engine::error(int line, const QString &message)
+{
+ DiagnosticMessage m;
+ m.setKind(DiagnosticMessage::Error);
+ m.setLine(line);
+ m.setMessage(message);
+ addDiagnosticMessage(m);
+}
+
+bool DiagnosticMessage::isError() const
+{
+ return _kind == Error;
+}
+
+bool GLSL::DiagnosticMessage::isWarning() const
+{
+ return _kind == Warning;
+}
+
+Namespace *Engine::newNamespace()
+{
+ Namespace *s = new Namespace();
+ _symbols.append(s);
+ return s;
+}
+
+Struct *Engine::newStruct(Scope *scope)
+{
+ Struct *s = new Struct(scope);
+ _symbols.append(s);
+ return s;
+}
+
+Block *Engine::newBlock(Scope *scope)
+{
+ Block *s = new Block(scope);
+ _symbols.append(s);
+ return s;
+}
+
+Function *Engine::newFunction(Scope *scope)
+{
+ Function *s = new Function(scope);
+ _symbols.append(s);
+ return s;
+}
+
+Argument *Engine::newArgument(Function *function, const QString &name, const Type *type)
+{
+ Argument *a = new Argument(function);
+ a->setName(name);
+ a->setType(type);
+ _symbols.append(a);
+ return a;
+}
+
+Variable *Engine::newVariable(Scope *scope, const QString &name, const Type *type, int qualifiers)
+{
+ Variable *var = new Variable(scope);
+ var->setName(name);
+ var->setType(type);
+ var->setQualifiers(qualifiers);
+ _symbols.append(var);
+ return var;
+}
+
+bool Engine::blockDiagnosticMessages(bool block)
+{
+ bool previous = _blockDiagnosticMessages;
+ _blockDiagnosticMessages = block;
+ return previous;
+}
+
diff --git a/src/libs/glsl/glslengine.h b/src/libs/glsl/glslengine.h
new file mode 100644
index 0000000000..5e1c906509
--- /dev/null
+++ b/src/libs/glsl/glslengine.h
@@ -0,0 +1,150 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 GLSLENGINE_H
+#define GLSLENGINE_H
+
+#include "glsl.h"
+#include "glslmemorypool.h"
+#include "glsltypes.h"
+#include <QtCore/qstring.h>
+#include <QtCore/qset.h>
+#include <functional>
+#include <set>
+
+namespace GLSL {
+
+class GLSL_EXPORT DiagnosticMessage
+{
+public:
+ enum Kind {
+ Warning,
+ Error
+ };
+
+ DiagnosticMessage();
+
+ Kind kind() const;
+ void setKind(Kind kind);
+
+ bool isError() const;
+ bool isWarning() const;
+
+ QString fileName() const;
+ void setFileName(const QString &fileName);
+
+ int line() const;
+ void setLine(int line);
+
+ QString message() const;
+ void setMessage(const QString &message);
+
+private:
+ QString _fileName;
+ QString _message;
+ Kind _kind;
+ int _line;
+};
+
+template <typename _Type>
+class TypeTable
+{
+public:
+ struct Compare: std::binary_function<_Type, _Type, bool> {
+ bool operator()(const _Type &value, const _Type &other) const {
+ return value.isLessThan(&other);
+ }
+ };
+
+ const _Type *intern(const _Type &ty) { return &*_entries.insert(ty).first; }
+
+private:
+ std::set<_Type, Compare> _entries;
+};
+
+class GLSL_EXPORT Engine
+{
+public:
+ Engine();
+ ~Engine();
+
+ const QString *identifier(const QString &s);
+ const QString *identifier(const char *s, int n);
+ QSet<QString> identifiers() const;
+
+ const QString *number(const QString &s);
+ const QString *number(const char *s, int n);
+ QSet<QString> numbers() const;
+
+ // types
+ const UndefinedType *undefinedType();
+ const VoidType *voidType();
+ const BoolType *boolType();
+ const IntType *intType();
+ const UIntType *uintType();
+ const FloatType *floatType();
+ const DoubleType *doubleType();
+ const SamplerType *samplerType(int kind);
+ const VectorType *vectorType(const Type *elementType, int dimension);
+ const MatrixType *matrixType(const Type *elementType, int columns, int rows);
+ const ArrayType *arrayType(const Type *elementType);
+
+ // symbols
+ Namespace *newNamespace();
+ Struct *newStruct(Scope *scope = 0);
+ Block *newBlock(Scope *scope = 0);
+ Function *newFunction(Scope *scope = 0);
+ Argument *newArgument(Function *function, const QString &name, const Type *type);
+ Variable *newVariable(Scope *scope, const QString &name, const Type *type, int qualifiers = 0);
+
+ MemoryPool *pool();
+
+ bool blockDiagnosticMessages(bool block);
+ QList<DiagnosticMessage> diagnosticMessages() const;
+ void clearDiagnosticMessages();
+ void addDiagnosticMessage(const DiagnosticMessage &m);
+ void warning(int line, const QString &message);
+ void error(int line, const QString &message);
+
+private:
+ QSet<QString> _identifiers;
+ QSet<QString> _numbers;
+ TypeTable<VectorType> _vectorTypes;
+ TypeTable<MatrixType> _matrixTypes;
+ TypeTable<ArrayType> _arrayTypes;
+ TypeTable<SamplerType> _samplerTypes;
+ MemoryPool _pool;
+ QList<DiagnosticMessage> _diagnosticMessages;
+ QList<Symbol *> _symbols;
+ bool _blockDiagnosticMessages;
+};
+
+} // namespace GLSL
+
+#endif // GLSLENGINE_H
diff --git a/src/libs/glsl/glslkeywords.cpp b/src/libs/glsl/glslkeywords.cpp
new file mode 100644
index 0000000000..982e0e75a8
--- /dev/null
+++ b/src/libs/glsl/glslkeywords.cpp
@@ -0,0 +1,1873 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "glsllexer.h"
+#include "glslparser.h"
+
+
+using namespace GLSL;
+
+static inline int classify2(const char *s) {
+ if (s[0] == 'd') {
+ if (s[1] == 'o') {
+ return Parser::T_DO;
+ }
+ }
+ else if (s[0] == 'i') {
+ if (s[1] == 'f') {
+ return Parser::T_IF;
+ }
+ else if (s[1] == 'n') {
+ return Parser::T_IN;
+ }
+ }
+ return Parser::T_IDENTIFIER;
+}
+
+static inline int classify3(const char *s) {
+ if (s[0] == 'f') {
+ if (s[1] == 'o') {
+ if (s[2] == 'r') {
+ return Parser::T_FOR;
+ }
+ }
+ }
+ else if (s[0] == 'i') {
+ if (s[1] == 'n') {
+ if (s[2] == 't') {
+ return Parser::T_INT;
+ }
+ }
+ }
+ else if (s[0] == 'o') {
+ if (s[1] == 'u') {
+ if (s[2] == 't') {
+ return Parser::T_OUT;
+ }
+ }
+ }
+ return Parser::T_IDENTIFIER;
+}
+
+static inline int classify4(const char *s) {
+ if (s[0] == 'b') {
+ if (s[1] == 'o') {
+ if (s[2] == 'o') {
+ if (s[3] == 'l') {
+ return Parser::T_BOOL;
+ }
+ }
+ }
+ }
+ else if (s[0] == 'c') {
+ if (s[1] == 'a') {
+ if (s[2] == 's') {
+ if (s[3] == 'e') {
+ return Parser::T_CASE | Lexer::Variant_GLSL_150;
+ }
+ }
+ }
+ }
+ else if (s[0] == 'e') {
+ if (s[1] == 'l') {
+ if (s[2] == 's') {
+ if (s[3] == 'e') {
+ return Parser::T_ELSE;
+ }
+ }
+ }
+ }
+ else if (s[0] == 'f') {
+ if (s[1] == 'l') {
+ if (s[2] == 'a') {
+ if (s[3] == 't') {
+ return Parser::T_FLAT | Lexer::Variant_GLSL_150;
+ }
+ }
+ }
+ }
+ else if (s[0] == 'l') {
+ if (s[1] == 'o') {
+ if (s[2] == 'w') {
+ if (s[3] == 'p') {
+ return Parser::T_LOWP | Lexer::Variant_GLSL_ES_100 | Lexer::Variant_GLSL_400;
+ }
+ }
+ }
+ }
+ else if (s[0] == 'm') {
+ if (s[1] == 'a') {
+ if (s[2] == 't') {
+ if (s[3] == '2') {
+ return Parser::T_MAT2;
+ }
+ else if (s[3] == '3') {
+ return Parser::T_MAT3;
+ }
+ else if (s[3] == '4') {
+ return Parser::T_MAT4;
+ }
+ }
+ }
+ }
+ else if (s[0] == 't') {
+ if (s[1] == 'r') {
+ if (s[2] == 'u') {
+ if (s[3] == 'e') {
+ return Parser::T_TRUE;
+ }
+ }
+ }
+ }
+ else if (s[0] == 'u') {
+ if (s[1] == 'i') {
+ if (s[2] == 'n') {
+ if (s[3] == 't') {
+ return Parser::T_UINT | Lexer::Variant_GLSL_150;
+ }
+ }
+ }
+ }
+ else if (s[0] == 'v') {
+ if (s[1] == 'e') {
+ if (s[2] == 'c') {
+ if (s[3] == '2') {
+ return Parser::T_VEC2;
+ }
+ else if (s[3] == '3') {
+ return Parser::T_VEC3;
+ }
+ else if (s[3] == '4') {
+ return Parser::T_VEC4;
+ }
+ }
+ }
+ else if (s[1] == 'o') {
+ if (s[2] == 'i') {
+ if (s[3] == 'd') {
+ return Parser::T_VOID;
+ }
+ }
+ }
+ }
+ return Parser::T_IDENTIFIER;
+}
+
+static inline int classify5(const char *s) {
+ if (s[0] == 'b') {
+ if (s[1] == 'r') {
+ if (s[2] == 'e') {
+ if (s[3] == 'a') {
+ if (s[4] == 'k') {
+ return Parser::T_BREAK;
+ }
+ }
+ }
+ }
+ else if (s[1] == 'v') {
+ if (s[2] == 'e') {
+ if (s[3] == 'c') {
+ if (s[4] == '2') {
+ return Parser::T_BVEC2;
+ }
+ else if (s[4] == '3') {
+ return Parser::T_BVEC3;
+ }
+ else if (s[4] == '4') {
+ return Parser::T_BVEC4;
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'c') {
+ if (s[1] == 'o') {
+ if (s[2] == 'n') {
+ if (s[3] == 's') {
+ if (s[4] == 't') {
+ return Parser::T_CONST;
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'd') {
+ if (s[1] == 'm') {
+ if (s[2] == 'a') {
+ if (s[3] == 't') {
+ if (s[4] == '2') {
+ return Parser::T_DMAT2 | Lexer::Variant_GLSL_400;
+ }
+ else if (s[4] == '3') {
+ return Parser::T_DMAT3 | Lexer::Variant_GLSL_400;
+ }
+ else if (s[4] == '4') {
+ return Parser::T_DMAT4 | Lexer::Variant_GLSL_400;
+ }
+ }
+ }
+ }
+ else if (s[1] == 'v') {
+ if (s[2] == 'e') {
+ if (s[3] == 'c') {
+ if (s[4] == '2') {
+ return Parser::T_DVEC2 | Lexer::Variant_GLSL_400;
+ }
+ else if (s[4] == '3') {
+ return Parser::T_DVEC3 | Lexer::Variant_GLSL_400;
+ }
+ else if (s[4] == '4') {
+ return Parser::T_DVEC4 | Lexer::Variant_GLSL_400;
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'f') {
+ if (s[1] == 'a') {
+ if (s[2] == 'l') {
+ if (s[3] == 's') {
+ if (s[4] == 'e') {
+ return Parser::T_FALSE;
+ }
+ }
+ }
+ }
+ else if (s[1] == 'l') {
+ if (s[2] == 'o') {
+ if (s[3] == 'a') {
+ if (s[4] == 't') {
+ return Parser::T_FLOAT;
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'h') {
+ if (s[1] == 'i') {
+ if (s[2] == 'g') {
+ if (s[3] == 'h') {
+ if (s[4] == 'p') {
+ return Parser::T_HIGHP | Lexer::Variant_GLSL_ES_100 | Lexer::Variant_GLSL_400;
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'i') {
+ if (s[1] == 'n') {
+ if (s[2] == 'o') {
+ if (s[3] == 'u') {
+ if (s[4] == 't') {
+ return Parser::T_INOUT;
+ }
+ }
+ }
+ }
+ else if (s[1] == 'v') {
+ if (s[2] == 'e') {
+ if (s[3] == 'c') {
+ if (s[4] == '2') {
+ return Parser::T_IVEC2;
+ }
+ else if (s[4] == '3') {
+ return Parser::T_IVEC3;
+ }
+ else if (s[4] == '4') {
+ return Parser::T_IVEC4;
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'p') {
+ if (s[1] == 'a') {
+ if (s[2] == 't') {
+ if (s[3] == 'c') {
+ if (s[4] == 'h') {
+ return Parser::T_PATCH | Lexer::Variant_GLSL_400;
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'u') {
+ if (s[1] == 'v') {
+ if (s[2] == 'e') {
+ if (s[3] == 'c') {
+ if (s[4] == '2') {
+ return Parser::T_UVEC2 | Lexer::Variant_GLSL_150;
+ }
+ else if (s[4] == '3') {
+ return Parser::T_UVEC3 | Lexer::Variant_GLSL_150;
+ }
+ else if (s[4] == '4') {
+ return Parser::T_UVEC4 | Lexer::Variant_GLSL_150;
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'w') {
+ if (s[1] == 'h') {
+ if (s[2] == 'i') {
+ if (s[3] == 'l') {
+ if (s[4] == 'e') {
+ return Parser::T_WHILE;
+ }
+ }
+ }
+ }
+ }
+ return Parser::T_IDENTIFIER;
+}
+
+static inline int classify6(const char *s) {
+ if (s[0] == 'd') {
+ if (s[1] == 'o') {
+ if (s[2] == 'u') {
+ if (s[3] == 'b') {
+ if (s[4] == 'l') {
+ if (s[5] == 'e') {
+ return Parser::T_DOUBLE | Lexer::Variant_GLSL_400;
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'l') {
+ if (s[1] == 'a') {
+ if (s[2] == 'y') {
+ if (s[3] == 'o') {
+ if (s[4] == 'u') {
+ if (s[5] == 't') {
+ return Parser::T_LAYOUT | Lexer::Variant_GLSL_150;
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'm') {
+ if (s[1] == 'a') {
+ if (s[2] == 't') {
+ if (s[3] == '2') {
+ if (s[4] == 'x') {
+ if (s[5] == '2') {
+ return Parser::T_MAT2X2 | Lexer::Variant_GLSL_120;
+ }
+ else if (s[5] == '3') {
+ return Parser::T_MAT2X3 | Lexer::Variant_GLSL_120;
+ }
+ else if (s[5] == '4') {
+ return Parser::T_MAT2X4 | Lexer::Variant_GLSL_120;
+ }
+ }
+ }
+ else if (s[3] == '3') {
+ if (s[4] == 'x') {
+ if (s[5] == '2') {
+ return Parser::T_MAT3X2 | Lexer::Variant_GLSL_120;
+ }
+ else if (s[5] == '3') {
+ return Parser::T_MAT3X3 | Lexer::Variant_GLSL_120;
+ }
+ else if (s[5] == '4') {
+ return Parser::T_MAT3X4 | Lexer::Variant_GLSL_120;
+ }
+ }
+ }
+ else if (s[3] == '4') {
+ if (s[4] == 'x') {
+ if (s[5] == '2') {
+ return Parser::T_MAT4X2 | Lexer::Variant_GLSL_120;
+ }
+ else if (s[5] == '3') {
+ return Parser::T_MAT4X3 | Lexer::Variant_GLSL_120;
+ }
+ else if (s[5] == '4') {
+ return Parser::T_MAT4X4 | Lexer::Variant_GLSL_120;
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'r') {
+ if (s[1] == 'e') {
+ if (s[2] == 't') {
+ if (s[3] == 'u') {
+ if (s[4] == 'r') {
+ if (s[5] == 'n') {
+ return Parser::T_RETURN;
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 's') {
+ if (s[1] == 'a') {
+ if (s[2] == 'm') {
+ if (s[3] == 'p') {
+ if (s[4] == 'l') {
+ if (s[5] == 'e') {
+ return Parser::T_SAMPLE | Lexer::Variant_Reserved;
+ }
+ }
+ }
+ }
+ }
+ else if (s[1] == 'm') {
+ if (s[2] == 'o') {
+ if (s[3] == 'o') {
+ if (s[4] == 't') {
+ if (s[5] == 'h') {
+ return Parser::T_SMOOTH | Lexer::Variant_GLSL_150;
+ }
+ }
+ }
+ }
+ }
+ else if (s[1] == 't') {
+ if (s[2] == 'r') {
+ if (s[3] == 'u') {
+ if (s[4] == 'c') {
+ if (s[5] == 't') {
+ return Parser::T_STRUCT;
+ }
+ }
+ }
+ }
+ }
+ else if (s[1] == 'w') {
+ if (s[2] == 'i') {
+ if (s[3] == 't') {
+ if (s[4] == 'c') {
+ if (s[5] == 'h') {
+ return Parser::T_SWITCH | Lexer::Variant_GLSL_150;
+ }
+ }
+ }
+ }
+ }
+ }
+ return Parser::T_IDENTIFIER;
+}
+
+static inline int classify7(const char *s) {
+ if (s[0] == 'd') {
+ if (s[1] == 'e') {
+ if (s[2] == 'f') {
+ if (s[3] == 'a') {
+ if (s[4] == 'u') {
+ if (s[5] == 'l') {
+ if (s[6] == 't') {
+ return Parser::T_DEFAULT | Lexer::Variant_GLSL_150;
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[1] == 'i') {
+ if (s[2] == 's') {
+ if (s[3] == 'c') {
+ if (s[4] == 'a') {
+ if (s[5] == 'r') {
+ if (s[6] == 'd') {
+ return Parser::T_DISCARD | Lexer::Variant_FragmentShader;
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[1] == 'm') {
+ if (s[2] == 'a') {
+ if (s[3] == 't') {
+ if (s[4] == '2') {
+ if (s[5] == 'x') {
+ if (s[6] == '2') {
+ return Parser::T_DMAT2X2 | Lexer::Variant_GLSL_400;
+ }
+ else if (s[6] == '3') {
+ return Parser::T_DMAT2X3 | Lexer::Variant_GLSL_400;
+ }
+ else if (s[6] == '4') {
+ return Parser::T_DMAT2X4 | Lexer::Variant_GLSL_400;
+ }
+ }
+ }
+ else if (s[4] == '3') {
+ if (s[5] == 'x') {
+ if (s[6] == '2') {
+ return Parser::T_DMAT3X2 | Lexer::Variant_GLSL_400;
+ }
+ else if (s[6] == '3') {
+ return Parser::T_DMAT3X3 | Lexer::Variant_GLSL_400;
+ }
+ else if (s[6] == '4') {
+ return Parser::T_DMAT3X4 | Lexer::Variant_GLSL_400;
+ }
+ }
+ }
+ else if (s[4] == '4') {
+ if (s[5] == 'x') {
+ if (s[6] == '2') {
+ return Parser::T_DMAT4X2 | Lexer::Variant_GLSL_400;
+ }
+ else if (s[6] == '3') {
+ return Parser::T_DMAT4X3 | Lexer::Variant_GLSL_400;
+ }
+ else if (s[6] == '4') {
+ return Parser::T_DMAT4X4 | Lexer::Variant_GLSL_400;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'm') {
+ if (s[1] == 'e') {
+ if (s[2] == 'd') {
+ if (s[3] == 'i') {
+ if (s[4] == 'u') {
+ if (s[5] == 'm') {
+ if (s[6] == 'p') {
+ return Parser::T_MEDIUMP | Lexer::Variant_GLSL_ES_100 | Lexer::Variant_GLSL_400;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'u') {
+ if (s[1] == 'n') {
+ if (s[2] == 'i') {
+ if (s[3] == 'f') {
+ if (s[4] == 'o') {
+ if (s[5] == 'r') {
+ if (s[6] == 'm') {
+ return Parser::T_UNIFORM;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'v') {
+ if (s[1] == 'a') {
+ if (s[2] == 'r') {
+ if (s[3] == 'y') {
+ if (s[4] == 'i') {
+ if (s[5] == 'n') {
+ if (s[6] == 'g') {
+ return Parser::T_VARYING;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return Parser::T_IDENTIFIER;
+}
+
+static inline int classify8(const char *s) {
+ if (s[0] == 'c') {
+ if (s[1] == 'e') {
+ if (s[2] == 'n') {
+ if (s[3] == 't') {
+ if (s[4] == 'r') {
+ if (s[5] == 'o') {
+ if (s[6] == 'i') {
+ if (s[7] == 'd') {
+ return Parser::T_CENTROID | Lexer::Variant_GLSL_120;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[1] == 'o') {
+ if (s[2] == 'n') {
+ if (s[3] == 't') {
+ if (s[4] == 'i') {
+ if (s[5] == 'n') {
+ if (s[6] == 'u') {
+ if (s[7] == 'e') {
+ return Parser::T_CONTINUE;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return Parser::T_IDENTIFIER;
+}
+
+static inline int classify9(const char *s) {
+ if (s[0] == 'a') {
+ if (s[1] == 't') {
+ if (s[2] == 't') {
+ if (s[3] == 'r') {
+ if (s[4] == 'i') {
+ if (s[5] == 'b') {
+ if (s[6] == 'u') {
+ if (s[7] == 't') {
+ if (s[8] == 'e') {
+ return Parser::T_ATTRIBUTE | Lexer::Variant_VertexShader;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'i') {
+ if (s[1] == 'n') {
+ if (s[2] == 'v') {
+ if (s[3] == 'a') {
+ if (s[4] == 'r') {
+ if (s[5] == 'i') {
+ if (s[6] == 'a') {
+ if (s[7] == 'n') {
+ if (s[8] == 't') {
+ return Parser::T_INVARIANT;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'p') {
+ if (s[1] == 'r') {
+ if (s[2] == 'e') {
+ if (s[3] == 'c') {
+ if (s[4] == 'i') {
+ if (s[5] == 's') {
+ if (s[6] == 'i') {
+ if (s[7] == 'o') {
+ if (s[8] == 'n') {
+ return Parser::T_PRECISION | Lexer::Variant_GLSL_ES_100;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 's') {
+ if (s[1] == 'a') {
+ if (s[2] == 'm') {
+ if (s[3] == 'p') {
+ if (s[4] == 'l') {
+ if (s[5] == 'e') {
+ if (s[6] == 'r') {
+ if (s[7] == '1') {
+ if (s[8] == 'D') {
+ return Parser::T_SAMPLER1D | Lexer::Variant_GLSL_120;
+ }
+ }
+ else if (s[7] == '2') {
+ if (s[8] == 'D') {
+ return Parser::T_SAMPLER2D;
+ }
+ }
+ else if (s[7] == '3') {
+ if (s[8] == 'D') {
+ return Parser::T_SAMPLER3D | Lexer::Variant_GLSL_120;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return Parser::T_IDENTIFIER;
+}
+
+static inline int classify10(const char *s) {
+ if (s[0] == 'i') {
+ if (s[1] == 's') {
+ if (s[2] == 'a') {
+ if (s[3] == 'm') {
+ if (s[4] == 'p') {
+ if (s[5] == 'l') {
+ if (s[6] == 'e') {
+ if (s[7] == 'r') {
+ if (s[8] == '1') {
+ if (s[9] == 'D') {
+ return Parser::T_ISAMPLER1D | Lexer::Variant_GLSL_150;
+ }
+ }
+ else if (s[8] == '2') {
+ if (s[9] == 'D') {
+ return Parser::T_ISAMPLER2D | Lexer::Variant_GLSL_150;
+ }
+ }
+ else if (s[8] == '3') {
+ if (s[9] == 'D') {
+ return Parser::T_ISAMPLER3D | Lexer::Variant_GLSL_150;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 's') {
+ if (s[1] == 'u') {
+ if (s[2] == 'b') {
+ if (s[3] == 'r') {
+ if (s[4] == 'o') {
+ if (s[5] == 'u') {
+ if (s[6] == 't') {
+ if (s[7] == 'i') {
+ if (s[8] == 'n') {
+ if (s[9] == 'e') {
+ return Parser::T_SUBROUTINE | Lexer::Variant_GLSL_400;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'u') {
+ if (s[1] == 's') {
+ if (s[2] == 'a') {
+ if (s[3] == 'm') {
+ if (s[4] == 'p') {
+ if (s[5] == 'l') {
+ if (s[6] == 'e') {
+ if (s[7] == 'r') {
+ if (s[8] == '1') {
+ if (s[9] == 'D') {
+ return Parser::T_USAMPLER1D | Lexer::Variant_GLSL_150;
+ }
+ }
+ else if (s[8] == '2') {
+ if (s[9] == 'D') {
+ return Parser::T_USAMPLER2D | Lexer::Variant_GLSL_150;
+ }
+ }
+ else if (s[8] == '3') {
+ if (s[9] == 'D') {
+ return Parser::T_USAMPLER3D | Lexer::Variant_GLSL_150;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return Parser::T_IDENTIFIER;
+}
+
+static inline int classify11(const char *s) {
+ if (s[0] == 's') {
+ if (s[1] == 'a') {
+ if (s[2] == 'm') {
+ if (s[3] == 'p') {
+ if (s[4] == 'l') {
+ if (s[5] == 'e') {
+ if (s[6] == 'r') {
+ if (s[7] == '2') {
+ if (s[8] == 'D') {
+ if (s[9] == 'M') {
+ if (s[10] == 'S') {
+ return Parser::T_SAMPLER2DMS | Lexer::Variant_GLSL_150;
+ }
+ }
+ }
+ }
+ else if (s[7] == 'C') {
+ if (s[8] == 'u') {
+ if (s[9] == 'b') {
+ if (s[10] == 'e') {
+ return Parser::T_SAMPLERCUBE;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return Parser::T_IDENTIFIER;
+}
+
+static inline int classify12(const char *s) {
+ if (s[0] == 'i') {
+ if (s[1] == 's') {
+ if (s[2] == 'a') {
+ if (s[3] == 'm') {
+ if (s[4] == 'p') {
+ if (s[5] == 'l') {
+ if (s[6] == 'e') {
+ if (s[7] == 'r') {
+ if (s[8] == '2') {
+ if (s[9] == 'D') {
+ if (s[10] == 'M') {
+ if (s[11] == 'S') {
+ return Parser::T_ISAMPLER2DMS | Lexer::Variant_GLSL_150;
+ }
+ }
+ }
+ }
+ else if (s[8] == 'C') {
+ if (s[9] == 'u') {
+ if (s[10] == 'b') {
+ if (s[11] == 'e') {
+ return Parser::T_ISAMPLERCUBE | Lexer::Variant_GLSL_150;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'u') {
+ if (s[1] == 's') {
+ if (s[2] == 'a') {
+ if (s[3] == 'm') {
+ if (s[4] == 'p') {
+ if (s[5] == 'l') {
+ if (s[6] == 'e') {
+ if (s[7] == 'r') {
+ if (s[8] == '2') {
+ if (s[9] == 'D') {
+ if (s[10] == 'M') {
+ if (s[11] == 'S') {
+ return Parser::T_USAMPLER2DMS | Lexer::Variant_GLSL_150;
+ }
+ }
+ }
+ }
+ else if (s[8] == 'C') {
+ if (s[9] == 'u') {
+ if (s[10] == 'b') {
+ if (s[11] == 'e') {
+ return Parser::T_USAMPLERCUBE | Lexer::Variant_GLSL_150;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return Parser::T_IDENTIFIER;
+}
+
+static inline int classify13(const char *s) {
+ if (s[0] == 'n') {
+ if (s[1] == 'o') {
+ if (s[2] == 'p') {
+ if (s[3] == 'e') {
+ if (s[4] == 'r') {
+ if (s[5] == 's') {
+ if (s[6] == 'p') {
+ if (s[7] == 'e') {
+ if (s[8] == 'c') {
+ if (s[9] == 't') {
+ if (s[10] == 'i') {
+ if (s[11] == 'v') {
+ if (s[12] == 'e') {
+ return Parser::T_NOPERSPECTIVE | Lexer::Variant_GLSL_150;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 's') {
+ if (s[1] == 'a') {
+ if (s[2] == 'm') {
+ if (s[3] == 'p') {
+ if (s[4] == 'l') {
+ if (s[5] == 'e') {
+ if (s[6] == 'r') {
+ if (s[7] == '2') {
+ if (s[8] == 'D') {
+ if (s[9] == 'R') {
+ if (s[10] == 'e') {
+ if (s[11] == 'c') {
+ if (s[12] == 't') {
+ return Parser::T_SAMPLER2DRECT;
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[7] == 'B') {
+ if (s[8] == 'u') {
+ if (s[9] == 'f') {
+ if (s[10] == 'f') {
+ if (s[11] == 'e') {
+ if (s[12] == 'r') {
+ return Parser::T_SAMPLERBUFFER | Lexer::Variant_GLSL_150;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return Parser::T_IDENTIFIER;
+}
+
+static inline int classify14(const char *s) {
+ if (s[0] == 'i') {
+ if (s[1] == 's') {
+ if (s[2] == 'a') {
+ if (s[3] == 'm') {
+ if (s[4] == 'p') {
+ if (s[5] == 'l') {
+ if (s[6] == 'e') {
+ if (s[7] == 'r') {
+ if (s[8] == '2') {
+ if (s[9] == 'D') {
+ if (s[10] == 'R') {
+ if (s[11] == 'e') {
+ if (s[12] == 'c') {
+ if (s[13] == 't') {
+ return Parser::T_ISAMPLER2DRECT | Lexer::Variant_GLSL_150;
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[8] == 'B') {
+ if (s[9] == 'u') {
+ if (s[10] == 'f') {
+ if (s[11] == 'f') {
+ if (s[12] == 'e') {
+ if (s[13] == 'r') {
+ return Parser::T_ISAMPLERBUFFER | Lexer::Variant_GLSL_150;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 's') {
+ if (s[1] == 'a') {
+ if (s[2] == 'm') {
+ if (s[3] == 'p') {
+ if (s[4] == 'l') {
+ if (s[5] == 'e') {
+ if (s[6] == 'r') {
+ if (s[7] == '1') {
+ if (s[8] == 'D') {
+ if (s[9] == 'A') {
+ if (s[10] == 'r') {
+ if (s[11] == 'r') {
+ if (s[12] == 'a') {
+ if (s[13] == 'y') {
+ return Parser::T_SAMPLER1DARRAY | Lexer::Variant_GLSL_150;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[7] == '2') {
+ if (s[8] == 'D') {
+ if (s[9] == 'A') {
+ if (s[10] == 'r') {
+ if (s[11] == 'r') {
+ if (s[12] == 'a') {
+ if (s[13] == 'y') {
+ return Parser::T_SAMPLER2DARRAY | Lexer::Variant_GLSL_150;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'u') {
+ if (s[1] == 's') {
+ if (s[2] == 'a') {
+ if (s[3] == 'm') {
+ if (s[4] == 'p') {
+ if (s[5] == 'l') {
+ if (s[6] == 'e') {
+ if (s[7] == 'r') {
+ if (s[8] == '2') {
+ if (s[9] == 'D') {
+ if (s[10] == 'R') {
+ if (s[11] == 'e') {
+ if (s[12] == 'c') {
+ if (s[13] == 't') {
+ return Parser::T_USAMPLER2DRECT | Lexer::Variant_GLSL_150;
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[8] == 'B') {
+ if (s[9] == 'u') {
+ if (s[10] == 'f') {
+ if (s[11] == 'f') {
+ if (s[12] == 'e') {
+ if (s[13] == 'r') {
+ return Parser::T_USAMPLERBUFFER | Lexer::Variant_GLSL_150;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return Parser::T_IDENTIFIER;
+}
+
+static inline int classify15(const char *s) {
+ if (s[0] == 'i') {
+ if (s[1] == 's') {
+ if (s[2] == 'a') {
+ if (s[3] == 'm') {
+ if (s[4] == 'p') {
+ if (s[5] == 'l') {
+ if (s[6] == 'e') {
+ if (s[7] == 'r') {
+ if (s[8] == '1') {
+ if (s[9] == 'D') {
+ if (s[10] == 'A') {
+ if (s[11] == 'r') {
+ if (s[12] == 'r') {
+ if (s[13] == 'a') {
+ if (s[14] == 'y') {
+ return Parser::T_ISAMPLER1DARRAY | Lexer::Variant_GLSL_150;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[8] == '2') {
+ if (s[9] == 'D') {
+ if (s[10] == 'A') {
+ if (s[11] == 'r') {
+ if (s[12] == 'r') {
+ if (s[13] == 'a') {
+ if (s[14] == 'y') {
+ return Parser::T_ISAMPLER2DARRAY | Lexer::Variant_GLSL_150;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 's') {
+ if (s[1] == 'a') {
+ if (s[2] == 'm') {
+ if (s[3] == 'p') {
+ if (s[4] == 'l') {
+ if (s[5] == 'e') {
+ if (s[6] == 'r') {
+ if (s[7] == '1') {
+ if (s[8] == 'D') {
+ if (s[9] == 'S') {
+ if (s[10] == 'h') {
+ if (s[11] == 'a') {
+ if (s[12] == 'd') {
+ if (s[13] == 'o') {
+ if (s[14] == 'w') {
+ return Parser::T_SAMPLER1DSHADOW | Lexer::Variant_GLSL_120;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[7] == '2') {
+ if (s[8] == 'D') {
+ if (s[9] == 'S') {
+ if (s[10] == 'h') {
+ if (s[11] == 'a') {
+ if (s[12] == 'd') {
+ if (s[13] == 'o') {
+ if (s[14] == 'w') {
+ return Parser::T_SAMPLER2DSHADOW | Lexer::Variant_GLSL_120;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'u') {
+ if (s[1] == 's') {
+ if (s[2] == 'a') {
+ if (s[3] == 'm') {
+ if (s[4] == 'p') {
+ if (s[5] == 'l') {
+ if (s[6] == 'e') {
+ if (s[7] == 'r') {
+ if (s[8] == '1') {
+ if (s[9] == 'D') {
+ if (s[10] == 'A') {
+ if (s[11] == 'r') {
+ if (s[12] == 'r') {
+ if (s[13] == 'a') {
+ if (s[14] == 'y') {
+ return Parser::T_USAMPLER1DARRAY | Lexer::Variant_GLSL_150;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[8] == '2') {
+ if (s[9] == 'D') {
+ if (s[10] == 'A') {
+ if (s[11] == 'r') {
+ if (s[12] == 'r') {
+ if (s[13] == 'a') {
+ if (s[14] == 'y') {
+ return Parser::T_USAMPLER2DARRAY | Lexer::Variant_GLSL_150;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return Parser::T_IDENTIFIER;
+}
+
+static inline int classify16(const char *s) {
+ if (s[0] == 's') {
+ if (s[1] == 'a') {
+ if (s[2] == 'm') {
+ if (s[3] == 'p') {
+ if (s[4] == 'l') {
+ if (s[5] == 'e') {
+ if (s[6] == 'r') {
+ if (s[7] == '2') {
+ if (s[8] == 'D') {
+ if (s[9] == 'M') {
+ if (s[10] == 'S') {
+ if (s[11] == 'A') {
+ if (s[12] == 'r') {
+ if (s[13] == 'r') {
+ if (s[14] == 'a') {
+ if (s[15] == 'y') {
+ return Parser::T_SAMPLER2DMSARRAY | Lexer::Variant_GLSL_150;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[7] == 'C') {
+ if (s[8] == 'u') {
+ if (s[9] == 'b') {
+ if (s[10] == 'e') {
+ if (s[11] == 'A') {
+ if (s[12] == 'r') {
+ if (s[13] == 'r') {
+ if (s[14] == 'a') {
+ if (s[15] == 'y') {
+ return Parser::T_SAMPLERCUBEARRAY | Lexer::Variant_GLSL_400;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return Parser::T_IDENTIFIER;
+}
+
+static inline int classify17(const char *s) {
+ if (s[0] == 'i') {
+ if (s[1] == 's') {
+ if (s[2] == 'a') {
+ if (s[3] == 'm') {
+ if (s[4] == 'p') {
+ if (s[5] == 'l') {
+ if (s[6] == 'e') {
+ if (s[7] == 'r') {
+ if (s[8] == '2') {
+ if (s[9] == 'D') {
+ if (s[10] == 'M') {
+ if (s[11] == 'S') {
+ if (s[12] == 'A') {
+ if (s[13] == 'r') {
+ if (s[14] == 'r') {
+ if (s[15] == 'a') {
+ if (s[16] == 'y') {
+ return Parser::T_ISAMPLER2DMSARRAY | Lexer::Variant_GLSL_150;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[8] == 'C') {
+ if (s[9] == 'u') {
+ if (s[10] == 'b') {
+ if (s[11] == 'e') {
+ if (s[12] == 'A') {
+ if (s[13] == 'r') {
+ if (s[14] == 'r') {
+ if (s[15] == 'a') {
+ if (s[16] == 'y') {
+ return Parser::T_ISAMPLERCUBEARRAY | Lexer::Variant_GLSL_400;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 's') {
+ if (s[1] == 'a') {
+ if (s[2] == 'm') {
+ if (s[3] == 'p') {
+ if (s[4] == 'l') {
+ if (s[5] == 'e') {
+ if (s[6] == 'r') {
+ if (s[7] == 'C') {
+ if (s[8] == 'u') {
+ if (s[9] == 'b') {
+ if (s[10] == 'e') {
+ if (s[11] == 'S') {
+ if (s[12] == 'h') {
+ if (s[13] == 'a') {
+ if (s[14] == 'd') {
+ if (s[15] == 'o') {
+ if (s[16] == 'w') {
+ return Parser::T_SAMPLERCUBESHADOW | Lexer::Variant_GLSL_400;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'u') {
+ if (s[1] == 's') {
+ if (s[2] == 'a') {
+ if (s[3] == 'm') {
+ if (s[4] == 'p') {
+ if (s[5] == 'l') {
+ if (s[6] == 'e') {
+ if (s[7] == 'r') {
+ if (s[8] == '2') {
+ if (s[9] == 'D') {
+ if (s[10] == 'M') {
+ if (s[11] == 'S') {
+ if (s[12] == 'a') {
+ if (s[13] == 'r') {
+ if (s[14] == 'r') {
+ if (s[15] == 'a') {
+ if (s[16] == 'y') {
+ return Parser::T_USAMPLER2DMSARRAY | Lexer::Variant_GLSL_150;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[8] == 'C') {
+ if (s[9] == 'u') {
+ if (s[10] == 'b') {
+ if (s[11] == 'e') {
+ if (s[12] == 'A') {
+ if (s[13] == 'r') {
+ if (s[14] == 'r') {
+ if (s[15] == 'a') {
+ if (s[16] == 'y') {
+ return Parser::T_USAMPLERCUBEARRAY | Lexer::Variant_GLSL_400;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return Parser::T_IDENTIFIER;
+}
+
+static inline int classify19(const char *s) {
+ if (s[0] == 's') {
+ if (s[1] == 'a') {
+ if (s[2] == 'm') {
+ if (s[3] == 'p') {
+ if (s[4] == 'l') {
+ if (s[5] == 'e') {
+ if (s[6] == 'r') {
+ if (s[7] == '2') {
+ if (s[8] == 'D') {
+ if (s[9] == 'R') {
+ if (s[10] == 'e') {
+ if (s[11] == 'c') {
+ if (s[12] == 't') {
+ if (s[13] == 'S') {
+ if (s[14] == 'h') {
+ if (s[15] == 'a') {
+ if (s[16] == 'd') {
+ if (s[17] == 'o') {
+ if (s[18] == 'w') {
+ return Parser::T_SAMPLER2DRECTSHADOW;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return Parser::T_IDENTIFIER;
+}
+
+static inline int classify20(const char *s) {
+ if (s[0] == 's') {
+ if (s[1] == 'a') {
+ if (s[2] == 'm') {
+ if (s[3] == 'p') {
+ if (s[4] == 'l') {
+ if (s[5] == 'e') {
+ if (s[6] == 'r') {
+ if (s[7] == '1') {
+ if (s[8] == 'D') {
+ if (s[9] == 'A') {
+ if (s[10] == 'r') {
+ if (s[11] == 'r') {
+ if (s[12] == 'a') {
+ if (s[13] == 'y') {
+ if (s[14] == 'S') {
+ if (s[15] == 'h') {
+ if (s[16] == 'a') {
+ if (s[17] == 'd') {
+ if (s[18] == 'o') {
+ if (s[19] == 'w') {
+ return Parser::T_SAMPLER1DARRAYSHADOW | Lexer::Variant_GLSL_150;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[7] == '2') {
+ if (s[8] == 'D') {
+ if (s[9] == 'A') {
+ if (s[10] == 'r') {
+ if (s[11] == 'r') {
+ if (s[12] == 'a') {
+ if (s[13] == 'y') {
+ if (s[14] == 'S') {
+ if (s[15] == 'h') {
+ if (s[16] == 'a') {
+ if (s[17] == 'd') {
+ if (s[18] == 'o') {
+ if (s[19] == 'w') {
+ return Parser::T_SAMPLER2DARRAYSHADOW | Lexer::Variant_GLSL_150;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return Parser::T_IDENTIFIER;
+}
+
+static inline int classify22(const char *s) {
+ if (s[0] == 's') {
+ if (s[1] == 'a') {
+ if (s[2] == 'm') {
+ if (s[3] == 'p') {
+ if (s[4] == 'l') {
+ if (s[5] == 'e') {
+ if (s[6] == 'r') {
+ if (s[7] == 'C') {
+ if (s[8] == 'u') {
+ if (s[9] == 'b') {
+ if (s[10] == 'e') {
+ if (s[11] == 'A') {
+ if (s[12] == 'r') {
+ if (s[13] == 'r') {
+ if (s[14] == 'a') {
+ if (s[15] == 'y') {
+ if (s[16] == 'S') {
+ if (s[17] == 'h') {
+ if (s[18] == 'a') {
+ if (s[19] == 'd') {
+ if (s[20] == 'o') {
+ if (s[21] == 'w') {
+ return Parser::T_SAMPLERCUBEARRAYSHADOW | Lexer::Variant_GLSL_400;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return Parser::T_IDENTIFIER;
+}
+
+int Lexer::classify(const char *s, int n) {
+ switch (n) {
+ case 2: return classify2(s);
+ case 3: return classify3(s);
+ case 4: return classify4(s);
+ case 5: return classify5(s);
+ case 6: return classify6(s);
+ case 7: return classify7(s);
+ case 8: return classify8(s);
+ case 9: return classify9(s);
+ case 10: return classify10(s);
+ case 11: return classify11(s);
+ case 12: return classify12(s);
+ case 13: return classify13(s);
+ case 14: return classify14(s);
+ case 15: return classify15(s);
+ case 16: return classify16(s);
+ case 17: return classify17(s);
+ case 19: return classify19(s);
+ case 20: return classify20(s);
+ case 22: return classify22(s);
+ default: return Parser::T_IDENTIFIER;
+ } // switch
+}
+
+QStringList Lexer::keywords(int variant) {
+ QStringList list;
+ list += QLatin1String("do");
+ list += QLatin1String("if");
+ list += QLatin1String("in");
+ list += QLatin1String("for");
+ list += QLatin1String("int");
+ list += QLatin1String("out");
+ list += QLatin1String("bool");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("case");
+ list += QLatin1String("else");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("flat");
+ if (variant & (Lexer::Variant_GLSL_ES_100 | Lexer::Variant_GLSL_400))
+ list += QLatin1String("lowp");
+ list += QLatin1String("mat2");
+ list += QLatin1String("mat3");
+ list += QLatin1String("mat4");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("uint");
+ list += QLatin1String("vec2");
+ list += QLatin1String("vec3");
+ list += QLatin1String("vec4");
+ list += QLatin1String("void");
+ list += QLatin1String("true");
+ list += QLatin1String("break");
+ list += QLatin1String("bvec2");
+ list += QLatin1String("bvec3");
+ list += QLatin1String("bvec4");
+ list += QLatin1String("const");
+ if (variant & (Lexer::Variant_GLSL_400))
+ list += QLatin1String("dmat2");
+ if (variant & (Lexer::Variant_GLSL_400))
+ list += QLatin1String("dmat3");
+ if (variant & (Lexer::Variant_GLSL_400))
+ list += QLatin1String("dmat4");
+ if (variant & (Lexer::Variant_GLSL_400))
+ list += QLatin1String("dvec2");
+ if (variant & (Lexer::Variant_GLSL_400))
+ list += QLatin1String("dvec3");
+ if (variant & (Lexer::Variant_GLSL_400))
+ list += QLatin1String("dvec4");
+ list += QLatin1String("float");
+ if (variant & (Lexer::Variant_GLSL_ES_100 | Lexer::Variant_GLSL_400))
+ list += QLatin1String("highp");
+ list += QLatin1String("inout");
+ list += QLatin1String("ivec2");
+ list += QLatin1String("ivec3");
+ list += QLatin1String("ivec4");
+ if (variant & (Lexer::Variant_GLSL_400))
+ list += QLatin1String("patch");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("uvec2");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("uvec3");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("uvec4");
+ list += QLatin1String("while");
+ list += QLatin1String("false");
+ if (variant & (Lexer::Variant_GLSL_400))
+ list += QLatin1String("double");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("layout");
+ if (variant & (Lexer::Variant_GLSL_120))
+ list += QLatin1String("mat2x2");
+ if (variant & (Lexer::Variant_GLSL_120))
+ list += QLatin1String("mat2x3");
+ if (variant & (Lexer::Variant_GLSL_120))
+ list += QLatin1String("mat2x4");
+ if (variant & (Lexer::Variant_GLSL_120))
+ list += QLatin1String("mat3x2");
+ if (variant & (Lexer::Variant_GLSL_120))
+ list += QLatin1String("mat3x3");
+ if (variant & (Lexer::Variant_GLSL_120))
+ list += QLatin1String("mat3x4");
+ if (variant & (Lexer::Variant_GLSL_120))
+ list += QLatin1String("mat4x2");
+ if (variant & (Lexer::Variant_GLSL_120))
+ list += QLatin1String("mat4x3");
+ if (variant & (Lexer::Variant_GLSL_120))
+ list += QLatin1String("mat4x4");
+ list += QLatin1String("return");
+ if (variant & (Lexer::Variant_Reserved))
+ list += QLatin1String("sample");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("smooth");
+ list += QLatin1String("struct");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("switch");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("default");
+ if (variant & (Lexer::Variant_FragmentShader))
+ list += QLatin1String("discard");
+ if (variant & (Lexer::Variant_GLSL_400))
+ list += QLatin1String("dmat2x2");
+ if (variant & (Lexer::Variant_GLSL_400))
+ list += QLatin1String("dmat2x3");
+ if (variant & (Lexer::Variant_GLSL_400))
+ list += QLatin1String("dmat2x4");
+ if (variant & (Lexer::Variant_GLSL_400))
+ list += QLatin1String("dmat3x2");
+ if (variant & (Lexer::Variant_GLSL_400))
+ list += QLatin1String("dmat3x3");
+ if (variant & (Lexer::Variant_GLSL_400))
+ list += QLatin1String("dmat3x4");
+ if (variant & (Lexer::Variant_GLSL_400))
+ list += QLatin1String("dmat4x2");
+ if (variant & (Lexer::Variant_GLSL_400))
+ list += QLatin1String("dmat4x3");
+ if (variant & (Lexer::Variant_GLSL_400))
+ list += QLatin1String("dmat4x4");
+ if (variant & (Lexer::Variant_GLSL_ES_100 | Lexer::Variant_GLSL_400))
+ list += QLatin1String("mediump");
+ list += QLatin1String("uniform");
+ list += QLatin1String("varying");
+ if (variant & (Lexer::Variant_GLSL_120))
+ list += QLatin1String("centroid");
+ list += QLatin1String("continue");
+ if (variant & (Lexer::Variant_VertexShader))
+ list += QLatin1String("attribute");
+ list += QLatin1String("invariant");
+ if (variant & (Lexer::Variant_GLSL_ES_100))
+ list += QLatin1String("precision");
+ if (variant & (Lexer::Variant_GLSL_120))
+ list += QLatin1String("sampler1D");
+ list += QLatin1String("sampler2D");
+ if (variant & (Lexer::Variant_GLSL_120))
+ list += QLatin1String("sampler3D");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("isampler1D");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("isampler2D");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("isampler3D");
+ if (variant & (Lexer::Variant_GLSL_400))
+ list += QLatin1String("subroutine");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("usampler1D");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("usampler2D");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("usampler3D");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("sampler2DMS");
+ list += QLatin1String("samplerCube");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("isampler2DMS");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("isamplerCube");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("usampler2DMS");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("usamplerCube");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("noperspective");
+ list += QLatin1String("sampler2DRect");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("samplerBuffer");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("isampler2DRect");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("isamplerBuffer");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("sampler1DArray");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("sampler2DArray");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("usampler2DRect");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("usamplerBuffer");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("isampler1DArray");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("isampler2DArray");
+ if (variant & (Lexer::Variant_GLSL_120))
+ list += QLatin1String("sampler1DShadow");
+ if (variant & (Lexer::Variant_GLSL_120))
+ list += QLatin1String("sampler2DShadow");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("usampler1DArray");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("usampler2DArray");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("sampler2DMSArray");
+ if (variant & (Lexer::Variant_GLSL_400))
+ list += QLatin1String("samplerCubeArray");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("isampler2DMSArray");
+ if (variant & (Lexer::Variant_GLSL_400))
+ list += QLatin1String("isamplerCubeArray");
+ if (variant & (Lexer::Variant_GLSL_400))
+ list += QLatin1String("samplerCubeShadow");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("usampler2DMSarray");
+ if (variant & (Lexer::Variant_GLSL_400))
+ list += QLatin1String("usamplerCubeArray");
+ list += QLatin1String("sampler2DRectShadow");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("sampler1DArrayShadow");
+ if (variant & (Lexer::Variant_GLSL_150))
+ list += QLatin1String("sampler2DArrayShadow");
+ if (variant & (Lexer::Variant_GLSL_400))
+ list += QLatin1String("samplerCubeArrayShadow");
+ return list;
+}
+
diff --git a/src/libs/glsl/glsllexer.cpp b/src/libs/glsl/glsllexer.cpp
new file mode 100644
index 0000000000..e297a7ae92
--- /dev/null
+++ b/src/libs/glsl/glsllexer.cpp
@@ -0,0 +1,419 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "glsllexer.h"
+#include "glslparser.h"
+#include "glslengine.h"
+#include <QtCore/qbytearray.h>
+#include <cctype>
+#include <iostream>
+#include <cstdio>
+
+using namespace GLSL;
+
+Lexer::Lexer(Engine *engine, const char *source, unsigned size)
+ : _engine(engine),
+ _source(source),
+ _it(source),
+ _size(size),
+ _yychar('\n'),
+ _lineno(0),
+ _state(0),
+ _variant(Variant_Mask & ~Variant_Reserved), // everything except reserved
+ _scanKeywords(true),
+ _scanComments(false)
+{
+}
+
+Lexer::~Lexer()
+{
+}
+
+void Lexer::yyinp()
+{
+ _yychar = (unsigned char) *_it++;
+ if (_yychar == '\n')
+ ++_lineno;
+}
+
+int Lexer::yylex(Token *tk)
+{
+ const char *pos = 0;
+ int line = 0;
+ _yyval.ptr = 0;
+ const int kind = yylex_helper(&pos, &line);
+ tk->kind = kind;
+ tk->position = pos - _source;
+ tk->length = _it - pos - 1;
+ tk->line = line;
+ tk->ptr = _yyval.ptr;
+ return kind;
+}
+
+enum {
+ State_normal,
+ State_comment
+};
+
+int Lexer::yylex_helper(const char **position, int *line)
+{
+ again:
+ while (std::isspace(_yychar))
+ yyinp();
+
+ *position = _it - 1;
+ *line = _lineno;
+
+ if (_yychar == 0)
+ return Parser::EOF_SYMBOL;
+
+ if (_state == State_comment) {
+ while (_yychar) {
+ if (_yychar == '*') {
+ yyinp();
+ if (_yychar == '/') {
+ yyinp();
+ _state = State_normal;
+ break;
+ }
+ } else {
+ yyinp();
+ }
+ }
+ return Parser::T_COMMENT;
+ }
+
+ const int ch = _yychar;
+ yyinp();
+
+ switch (ch) {
+ case '#':
+ for (; _yychar; yyinp()) {
+ if (_yychar == '\n')
+ break;
+ }
+ goto again;
+
+ // one of `!', `!='
+ case '!':
+ if (_yychar == '=') {
+ yyinp();
+ return Parser::T_NE_OP;
+ }
+ return Parser::T_BANG;
+
+ // one of
+ // %
+ // %=
+ case '%':
+ if (_yychar == '=') {
+ yyinp();
+ return Parser::T_MOD_ASSIGN;
+ }
+ return Parser::T_PERCENT;
+
+ // one of
+ // &
+ // &&
+ // &=
+ case '&':
+ if (_yychar == '=') {
+ yyinp();
+ return Parser::T_AND_ASSIGN;
+ } else if (_yychar == '&') {
+ yyinp();
+ return Parser::T_AND_OP;
+ }
+ return Parser::T_AMPERSAND;
+
+ // (
+ case '(':
+ return Parser::T_LEFT_PAREN;
+
+ // )
+ case ')':
+ return Parser::T_RIGHT_PAREN;
+
+ // one of
+ // *
+ // *=
+ case '*':
+ if (_yychar == '=') {
+ yyinp();
+ return Parser::T_MUL_ASSIGN;
+ }
+ return Parser::T_STAR;
+
+ // one of
+ // ++
+ // +=
+ // +
+ case '+':
+ if (_yychar == '=') {
+ yyinp();
+ return Parser::T_ADD_ASSIGN;
+ } else if (_yychar == '+') {
+ yyinp();
+ return Parser::T_INC_OP;
+ }
+ return Parser::T_PLUS;
+
+ // ,
+ case ',':
+ return Parser::T_COMMA;
+
+ // one of
+ // -
+ // --
+ // -=
+ case '-':
+ if (_yychar == '=') {
+ yyinp();
+ return Parser::T_SUB_ASSIGN;
+ } else if (_yychar == '-') {
+ yyinp();
+ return Parser::T_DEC_OP;
+ }
+ return Parser::T_DASH;
+
+ // one of
+ // .
+ // float constant
+ case '.':
+ if (std::isdigit(_yychar)) {
+ const char *word = _it - 2;
+ while (std::isalnum(_yychar)) {
+ yyinp();
+ }
+ if (_engine)
+ _yyval.string = _engine->number(word, _it - word - 1);
+ return Parser::T_NUMBER;
+ }
+ return Parser::T_DOT;
+
+ // one of
+ // /
+ // /=
+ // comment
+ case '/':
+ if (_yychar == '/') {
+ for (; _yychar; yyinp()) {
+ if (_yychar == '\n')
+ break;
+ }
+ if (_scanComments)
+ return Parser::T_COMMENT;
+ goto again;
+ } else if (_yychar == '*') {
+ yyinp();
+ while (_yychar) {
+ if (_yychar == '*') {
+ yyinp();
+ if (_yychar == '/') {
+ yyinp();
+ if (_scanComments)
+ return Parser::T_COMMENT;
+ goto again;
+ }
+ } else {
+ yyinp();
+ }
+ }
+ if (_scanComments) {
+ _state = State_comment;
+ return Parser::T_COMMENT;
+ }
+ goto again;
+ } else if (_yychar == '=') {
+ yyinp();
+ return Parser::T_DIV_ASSIGN;
+ }
+ return Parser::T_SLASH;
+
+ // :
+ case ':':
+ return Parser::T_COLON;
+
+ // ;
+ case ';':
+ return Parser::T_SEMICOLON;
+
+ // one of
+ // <
+ // <=
+ // <<
+ // <<=
+ case '<':
+ if (_yychar == '=') {
+ yyinp();
+ return Parser::T_LE_OP;
+ } else if (_yychar == '<') {
+ yyinp();
+ if (_yychar == '=') {
+ yyinp();
+ return Parser::T_LEFT_ASSIGN;
+ }
+ return Parser::T_LEFT_OP;
+ }
+ return Parser::T_LEFT_ANGLE;
+
+ // one of
+ // =
+ // ==
+ case '=':
+ if (_yychar == '=') {
+ yyinp();
+ return Parser::T_EQ_OP;
+ }
+ return Parser::T_EQUAL;
+
+ // one of
+ // >
+ // >=
+ // >>=
+ // >>
+ case '>':
+ if (_yychar == '=') {
+ yyinp();
+ return Parser::T_GE_OP;
+ } else if (_yychar == '>') {
+ yyinp();
+ if (_yychar == '=') {
+ yyinp();
+ return Parser::T_RIGHT_ASSIGN;
+ }
+ return Parser::T_RIGHT_OP;
+ }
+ return Parser::T_RIGHT_ANGLE;
+
+ // ?
+ case '?':
+ return Parser::T_QUESTION;
+
+ // [
+ case '[':
+ return Parser::T_LEFT_BRACKET;
+
+ // ]
+ case ']':
+ return Parser::T_RIGHT_BRACKET;
+
+ // one of
+ // ^
+ // ^=
+ case '^':
+ if (_yychar == '=') {
+ yyinp();
+ return Parser::T_XOR_ASSIGN;
+ } else if (_yychar == '^') {
+ yyinp();
+ return Parser::T_XOR_OP;
+ }
+ return Parser::T_CARET;
+
+ // {
+ case '{':
+ return Parser::T_LEFT_BRACE;
+
+ // one of
+ // |
+ // |=
+ // ||
+ case '|':
+ if (_yychar == '=') {
+ yyinp();
+ return Parser::T_OR_ASSIGN;
+ } else if (_yychar == '|') {
+ yyinp();
+ return Parser::T_OR_OP;
+ }
+ return Parser::T_VERTICAL_BAR;
+
+ // }
+ case '}':
+ return Parser::T_RIGHT_BRACE;
+
+ // ~
+ case '~':
+ return Parser::T_TILDE;
+
+ default:
+ if (std::isalpha(ch) || ch == '_') {
+ const char *word = _it - 2;
+ while (std::isalnum(_yychar) || _yychar == '_') {
+ yyinp();
+ }
+ if (_scanKeywords) {
+ const int k = findKeyword(word, _it - word - 1);
+
+ if (k != Parser::T_IDENTIFIER)
+ return k;
+ }
+ if (_engine)
+ _yyval.string = _engine->identifier(word, _it - word - 1);
+ return Parser::T_IDENTIFIER;
+ } else if (std::isdigit(ch)) {
+ const char *word = _it - 2;
+ while (std::isalnum(_yychar) || _yychar == '.') {
+ yyinp();
+ }
+ if (_engine)
+ _yyval.string = _engine->number(word, _it - word - 1);
+ return Parser::T_NUMBER;
+ }
+
+ } // switch
+
+ return Parser::T_ERROR;
+}
+
+int Lexer::findKeyword(const char *word, int length) const
+{
+ int t = classify(word, length);
+ if (!(t & Variant_Mask))
+ return t;
+ if ((_variant & t & Variant_Mask) == 0) {
+ // Return a "reserved word" token if this keyword is not permitted
+ // in the current language variant so that the syntax highlighter
+ // can warn the user about the word.
+ if (!_scanKeywords)
+ return Parser::T_RESERVED;
+ }
+ return t & ~Variant_Mask;
+}
+
+void Lexer::warning(int line, const QString &message)
+{
+ _engine->warning(line, message);
+}
+
+void Lexer::error(int line, const QString &message)
+{
+ _engine->error(line, message);
+}
diff --git a/src/libs/glsl/glsllexer.h b/src/libs/glsl/glsllexer.h
new file mode 100644
index 0000000000..ebb3dd3528
--- /dev/null
+++ b/src/libs/glsl/glsllexer.h
@@ -0,0 +1,137 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 GLSLLEXER_H
+#define GLSLLEXER_H
+
+#include "glsl.h"
+#include <QtCore/qstring.h>
+#include <QtCore/qstringlist.h>
+
+namespace GLSL {
+
+class GLSL_EXPORT Token
+{
+public:
+ int kind;
+ int position;
+ int length;
+ int line; // ### remove
+
+ union {
+ int matchingBrace;
+ int i; // integer value
+ const QString *string; // string value
+ void *ptr;
+ };
+
+ Token()
+ : kind(0), position(0), length(0), line(0), ptr(0) {}
+
+ bool is(int k) const { return k == kind; }
+ bool isNot(int k) const { return k != kind; }
+
+ int begin() const { return position; }
+ int end() const { return position + length; }
+};
+
+class GLSL_EXPORT Lexer
+{
+public:
+ Lexer(Engine *engine, const char *source, unsigned size);
+ ~Lexer();
+
+ enum
+ {
+ // Extra flag bits added to tokens by Lexer::classify() that
+ // indicate which variant of GLSL the keyword belongs to.
+ Variant_GLSL_120 = 0x00010000, // 1.20 and higher
+ Variant_GLSL_150 = 0x00020000, // 1.50 and higher
+ Variant_GLSL_400 = 0x00040000, // 4.00 and higher
+ Variant_GLSL_ES_100 = 0x00080000, // ES 1.00 and higher
+ Variant_VertexShader = 0x00200000,
+ Variant_FragmentShader = 0x00400000,
+ Variant_Reserved = 0x80000000,
+ Variant_Mask = 0xFFFF0000,
+ Variant_All = 0xFFFF0000
+ };
+
+ union Value {
+ int i;
+ const QString *string;
+ void *ptr;
+ };
+
+ Engine *engine() const { return _engine; }
+
+ int state() const { return _state; }
+ void setState(int state) { _state = state; }
+
+ int variant() const { return _variant; }
+ void setVariant(int flags) { _variant = flags; }
+
+ bool scanKeywords() const { return _scanKeywords; }
+ void setScanKeywords(bool scanKeywords) { _scanKeywords = scanKeywords; }
+
+ bool scanComments() const { return _scanComments; }
+ void setScanComments(bool scanComments) { _scanComments = scanComments; }
+
+ int yylex(Token *tk);
+ int findKeyword(const char *word, int length) const;
+
+ void *yyval() const { return _yyval.ptr; }
+
+ static QStringList keywords(int variant);
+
+private:
+ static int classify(const char *s, int len);
+
+ void yyinp();
+ int yylex_helper(const char **position, int *line);
+
+ void warning(int line, const QString &message);
+ void error(int line, const QString &message);
+
+private:
+ Engine *_engine;
+ const char *_source;
+ const char *_it;
+ int _size;
+ int _yychar;
+ int _lineno;
+ int _state;
+ int _variant;
+ unsigned _scanKeywords: 1;
+ unsigned _scanComments: 1;
+ Value _yyval;
+};
+
+} // end of namespace GLSL
+
+#endif // GLSLLEXER_H
diff --git a/src/libs/glsl/glslmemorypool.cpp b/src/libs/glsl/glslmemorypool.cpp
new file mode 100644
index 0000000000..c2927e888f
--- /dev/null
+++ b/src/libs/glsl/glslmemorypool.cpp
@@ -0,0 +1,120 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "glslmemorypool.h"
+#include <cstring>
+#include <cassert>
+
+using namespace GLSL;
+
+MemoryPool::MemoryPool()
+ : _blocks(0),
+ _allocatedBlocks(0),
+ _blockCount(-1),
+ _ptr(0),
+ _end(0)
+{ }
+
+MemoryPool::~MemoryPool()
+{
+ if (_blocks) {
+ for (int i = 0; i < _allocatedBlocks; ++i) {
+ if (char *b = _blocks[i])
+ std::free(b);
+ }
+
+ std::free(_blocks);
+ }
+}
+
+void MemoryPool::reset()
+{
+ _blockCount = -1;
+ _ptr = _end = 0;
+}
+
+void *MemoryPool::allocate_helper(size_t size)
+{
+ assert(size < BLOCK_SIZE);
+
+ if (++_blockCount == _allocatedBlocks) {
+ if (! _allocatedBlocks)
+ _allocatedBlocks = DEFAULT_BLOCK_COUNT;
+ else
+ _allocatedBlocks *= 2;
+
+ _blocks = (char **) realloc(_blocks, sizeof(char *) * _allocatedBlocks);
+
+ for (int index = _blockCount; index < _allocatedBlocks; ++index)
+ _blocks[index] = 0;
+ }
+
+ char *&block = _blocks[_blockCount];
+
+ if (! block)
+ block = (char *) std::malloc(BLOCK_SIZE);
+
+ _ptr = block;
+ _end = _ptr + BLOCK_SIZE;
+
+ void *addr = _ptr;
+ _ptr += size;
+ return addr;
+}
+
+RecursiveMemoryPool::RecursiveMemoryPool(MemoryPool *pool)
+ : _pool(pool),
+ _blockCount(pool->_blockCount),
+ _ptr(pool->_ptr),
+ _end(pool->_end)
+{
+}
+
+RecursiveMemoryPool::~RecursiveMemoryPool()
+{
+ _pool->_blockCount = _blockCount;
+ _pool->_ptr = _ptr;
+ _pool->_end = _end;
+}
+
+Managed::Managed()
+{ }
+
+Managed::~Managed()
+{ }
+
+void *Managed::operator new(size_t size, MemoryPool *pool)
+{ return pool->allocate(size); }
+
+void Managed::operator delete(void *)
+{ }
+
+void Managed::operator delete(void *, MemoryPool *)
+{ }
+
diff --git a/src/libs/glsl/glslmemorypool.h b/src/libs/glsl/glslmemorypool.h
new file mode 100644
index 0000000000..9f89d6f72c
--- /dev/null
+++ b/src/libs/glsl/glslmemorypool.h
@@ -0,0 +1,110 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 GLSLMEMORYPOOL_H
+#define GLSLMEMORYPOOL_H
+
+#include "glsl.h"
+#include <new>
+
+namespace GLSL {
+
+class MemoryPool;
+class RecursiveMemoryPool;
+
+class GLSL_EXPORT MemoryPool
+{
+ MemoryPool(const MemoryPool &other);
+ void operator =(const MemoryPool &other);
+
+public:
+ MemoryPool();
+ ~MemoryPool();
+
+ void reset();
+
+ inline void *allocate(size_t size)
+ {
+ size = (size + 7) & ~7;
+ if (_ptr && (_ptr + size < _end)) {
+ void *addr = _ptr;
+ _ptr += size;
+ return addr;
+ }
+ return allocate_helper(size);
+ }
+
+private:
+ void *allocate_helper(size_t size);
+
+private:
+ char **_blocks;
+ int _allocatedBlocks;
+ int _blockCount;
+ char *_ptr;
+ char *_end;
+
+ enum
+ {
+ BLOCK_SIZE = 8 * 1024,
+ DEFAULT_BLOCK_COUNT = 8
+ };
+
+ friend class RecursiveMemoryPool;
+};
+
+class GLSL_EXPORT RecursiveMemoryPool
+{
+ MemoryPool *_pool;
+ int _blockCount;
+ char *_ptr;
+ char *_end;
+
+public:
+ RecursiveMemoryPool(MemoryPool *pool);
+ ~RecursiveMemoryPool();
+};
+
+class GLSL_EXPORT Managed
+{
+ Managed(const Managed &other);
+ void operator = (const Managed &other);
+
+public:
+ Managed();
+ virtual ~Managed();
+
+ void *operator new(size_t size, MemoryPool *pool);
+ void operator delete(void *);
+ void operator delete(void *, MemoryPool *);
+};
+
+} // end of namespace GLSL
+
+
+#endif // GLSLMEMORYPOOL_H
diff --git a/src/libs/glsl/glslparser.cpp b/src/libs/glsl/glslparser.cpp
new file mode 100644
index 0000000000..85a190aa52
--- /dev/null
+++ b/src/libs/glsl/glslparser.cpp
@@ -0,0 +1,2270 @@
+
+#line 420 "./glsl.g"
+
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "glslparser.h"
+#include "glslengine.h"
+#include <iostream>
+#include <cstdio>
+#include <cassert>
+#include <QtCore/QDebug>
+
+using namespace GLSL;
+
+Parser::Parser(Engine *engine, const char *source, unsigned size, int variant)
+ : _engine(engine), _tos(-1), _index(0), yyloc(-1), yytoken(-1), yyrecovering(0), _recovered(false)
+{
+ _tokens.reserve(1024);
+
+ _stateStack.resize(128);
+ _locationStack.resize(128);
+ _symStack.resize(128);
+
+ _tokens.push_back(Token()); // invalid token
+
+ std::stack<int> parenStack;
+ std::stack<int> bracketStack;
+ std::stack<int> braceStack;
+
+ Lexer lexer(engine, source, size);
+ lexer.setVariant(variant);
+ Token tk;
+ do {
+ lexer.yylex(&tk);
+
+ switch (tk.kind) {
+ case T_LEFT_PAREN:
+ parenStack.push(_tokens.size());
+ break;
+ case T_LEFT_BRACKET:
+ bracketStack.push(_tokens.size());
+ break;
+ case T_LEFT_BRACE:
+ braceStack.push(_tokens.size());
+ break;
+
+ case T_RIGHT_PAREN:
+ if (! parenStack.empty()) {
+ _tokens[parenStack.top()].matchingBrace = _tokens.size();
+ parenStack.pop();
+ }
+ break;
+ case T_RIGHT_BRACKET:
+ if (! bracketStack.empty()) {
+ _tokens[bracketStack.top()].matchingBrace = _tokens.size();
+ bracketStack.pop();
+ }
+ break;
+ case T_RIGHT_BRACE:
+ if (! braceStack.empty()) {
+ _tokens[braceStack.top()].matchingBrace = _tokens.size();
+ braceStack.pop();
+ }
+ break;
+ default:
+ break;
+ }
+
+ _tokens.push_back(tk);
+ } while (tk.isNot(EOF_SYMBOL));
+
+ _index = 0;
+}
+
+Parser::~Parser()
+{
+}
+
+AST *Parser::parse(int startToken)
+{
+ int action = 0;
+ yytoken = -1;
+ yyloc = -1;
+ void *yyval = 0; // value of the current token.
+
+ _recovered = false;
+ _tos = -1;
+ _startToken.kind = startToken;
+
+ do {
+ again:
+ if (unsigned(++_tos) == _stateStack.size()) {
+ _stateStack.resize(_tos * 2);
+ _locationStack.resize(_tos * 2);
+ _symStack.resize(_tos * 2);
+ }
+
+ _stateStack[_tos] = action;
+
+ if (yytoken == -1 && -TERMINAL_COUNT != action_index[action]) {
+ yyloc = consumeToken();
+ yytoken = tokenKind(yyloc);
+ if (yyrecovering)
+ --yyrecovering;
+ if (yytoken == T_IDENTIFIER && t_action(action, T_TYPE_NAME) != 0) {
+ const Token &la = tokenAt(_index);
+
+ if (la.is(T_IDENTIFIER)) {
+ yytoken = T_TYPE_NAME;
+ } else if (la.is(T_LEFT_BRACKET) && la.matchingBrace != 0 &&
+ tokenAt(la.matchingBrace + 1).is(T_IDENTIFIER)) {
+ yytoken = T_TYPE_NAME;
+ }
+ }
+ yyval = _tokens.at(yyloc).ptr;
+ }
+
+ action = t_action(action, yytoken);
+ if (action > 0) {
+ if (action == ACCEPT_STATE) {
+ --_tos;
+ return _symStack[0].translation_unit;
+ }
+ _symStack[_tos].ptr = yyval;
+ _locationStack[_tos] = yyloc;
+ yytoken = -1;
+ } else if (action < 0) {
+ const int ruleno = -action - 1;
+ const int N = rhs[ruleno];
+ _tos -= N;
+ reduce(ruleno);
+ action = nt_action(_stateStack[_tos], lhs[ruleno] - TERMINAL_COUNT);
+ } else if (action == 0) {
+ const int line = _tokens[yyloc].line + 1;
+ QString message = QLatin1String("Syntax error");
+ if (yytoken != -1) {
+ const QLatin1String s(spell[yytoken]);
+ message = QString("Unexpected token `%1'").arg(s);
+ }
+
+ for (; _tos; --_tos) {
+ const int state = _stateStack[_tos];
+
+ static int tks[] = {
+ T_RIGHT_BRACE, T_RIGHT_PAREN, T_RIGHT_BRACKET,
+ T_SEMICOLON, T_COMMA, T_COLON,
+ T_NUMBER, T_TYPE_NAME, T_IDENTIFIER,
+ T_LEFT_BRACE, T_LEFT_PAREN, T_LEFT_BRACKET,
+ T_WHILE,
+ 0
+ };
+
+ for (int *tptr = tks; *tptr; ++tptr) {
+ const int next = t_action(state, *tptr);
+ if (next > 0) {
+ if (! yyrecovering && ! _recovered) {
+ _recovered = true;
+ error(line, QString("Expected `%1'").arg(QLatin1String(spell[*tptr])));
+ }
+
+ yyrecovering = 3;
+ if (*tptr == T_IDENTIFIER)
+ yyval = (void *) _engine->identifier(QLatin1String("$identifier"));
+ else if (*tptr == T_NUMBER || *tptr == T_TYPE_NAME)
+ yyval = (void *) _engine->identifier(QLatin1String("$0"));
+ else
+ yyval = 0;
+
+ _symStack[_tos].ptr = yyval;
+ _locationStack[_tos] = yyloc;
+ yytoken = -1;
+
+ action = next;
+ goto again;
+ }
+ }
+ }
+
+ if (! _recovered) {
+ _recovered = true;
+ error(line, message);
+ }
+ }
+
+ } while (action);
+
+ return 0;
+}
+
+#line 637 "./glsl.g"
+
+void Parser::reduce(int ruleno)
+{
+switch(ruleno) {
+
+#line 646 "./glsl.g"
+
+case 0: {
+ ast(1) = makeAstNode<IdentifierExpressionAST>(string(1));
+} break;
+
+#line 653 "./glsl.g"
+
+case 1: {
+ ast(1) = makeAstNode<LiteralExpressionAST>(string(1));
+} break;
+
+#line 660 "./glsl.g"
+
+case 2: {
+ ast(1) = makeAstNode<LiteralExpressionAST>(_engine->identifier("true", 4));
+} break;
+
+#line 667 "./glsl.g"
+
+case 3: {
+ ast(1) = makeAstNode<LiteralExpressionAST>(_engine->identifier("false", 5));
+} break;
+
+#line 674 "./glsl.g"
+
+case 4: {
+ // nothing to do.
+} break;
+
+#line 681 "./glsl.g"
+
+case 5: {
+ ast(1) = ast(2);
+} break;
+
+#line 688 "./glsl.g"
+
+case 6: {
+ // nothing to do.
+} break;
+
+#line 695 "./glsl.g"
+
+case 7: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_ArrayAccess, expression(1), expression(3));
+} break;
+
+#line 702 "./glsl.g"
+
+case 8: {
+ // nothing to do.
+} break;
+
+#line 709 "./glsl.g"
+
+case 9: {
+ ast(1) = makeAstNode<MemberAccessExpressionAST>(expression(1), string(3));
+} break;
+
+#line 716 "./glsl.g"
+
+case 10: {
+ ast(1) = makeAstNode<UnaryExpressionAST>(AST::Kind_PostIncrement, expression(1));
+} break;
+
+#line 723 "./glsl.g"
+
+case 11: {
+ ast(1) = makeAstNode<UnaryExpressionAST>(AST::Kind_PostDecrement, expression(1));
+} break;
+
+#line 730 "./glsl.g"
+
+case 12: {
+ // nothing to do.
+} break;
+
+#line 737 "./glsl.g"
+
+case 13: {
+ // nothing to do.
+} break;
+
+#line 744 "./glsl.g"
+
+case 14: {
+ ast(1) = makeAstNode<FunctionCallExpressionAST>
+ (sym(1).function.id, sym(1).function.arguments);
+} break;
+
+#line 752 "./glsl.g"
+
+case 15: {
+ ast(1) = makeAstNode<FunctionCallExpressionAST>
+ (expression(1), sym(3).function.id, sym(3).function.arguments);
+} break;
+
+#line 760 "./glsl.g"
+
+case 16: {
+ // nothing to do.
+} break;
+
+#line 767 "./glsl.g"
+
+case 17: {
+ // nothing to do.
+} break;
+
+#line 774 "./glsl.g"
+
+case 18: {
+ sym(1).function.id = sym(1).function_identifier;
+ sym(1).function.arguments = 0;
+} break;
+
+#line 782 "./glsl.g"
+
+case 19: {
+ sym(1).function.id = sym(1).function_identifier;
+ sym(1).function.arguments = 0;
+} break;
+
+#line 790 "./glsl.g"
+
+case 20: {
+ sym(1).function.id = sym(1).function_identifier;
+ sym(1).function.arguments =
+ makeAstNode< List<ExpressionAST *> >(expression(2));
+} break;
+
+#line 799 "./glsl.g"
+
+case 21: {
+ sym(1).function.arguments =
+ makeAstNode< List<ExpressionAST *> >
+ (sym(1).function.arguments, expression(3));
+} break;
+
+#line 808 "./glsl.g"
+
+case 22: {
+ // nothing to do.
+} break;
+
+#line 815 "./glsl.g"
+
+case 23: {
+ ast(1) = makeAstNode<FunctionIdentifierAST>(type(1));
+} break;
+
+#line 822 "./glsl.g"
+
+case 24: {
+ ast(1) = makeAstNode<FunctionIdentifierAST>(string(1));
+} break;
+
+#line 829 "./glsl.g"
+
+case 25: {
+ // nothing to do.
+} break;
+
+#line 836 "./glsl.g"
+
+case 26: {
+ ast(1) = makeAstNode<UnaryExpressionAST>(AST::Kind_PreIncrement, expression(2));
+} break;
+
+#line 843 "./glsl.g"
+
+case 27: {
+ ast(1) = makeAstNode<UnaryExpressionAST>(AST::Kind_PreDecrement, expression(2));
+} break;
+
+#line 850 "./glsl.g"
+
+case 28: {
+ ast(1) = makeAstNode<UnaryExpressionAST>(sym(1).kind, expression(2));
+} break;
+
+#line 857 "./glsl.g"
+
+case 29: {
+ sym(1).kind = AST::Kind_UnaryPlus;
+} break;
+
+#line 864 "./glsl.g"
+
+case 30: {
+ sym(1).kind = AST::Kind_UnaryMinus;
+} break;
+
+#line 871 "./glsl.g"
+
+case 31: {
+ sym(1).kind = AST::Kind_LogicalNot;
+} break;
+
+#line 878 "./glsl.g"
+
+case 32: {
+ sym(1).kind = AST::Kind_BitwiseNot;
+} break;
+
+#line 885 "./glsl.g"
+
+case 33: {
+ // nothing to do.
+} break;
+
+#line 892 "./glsl.g"
+
+case 34: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_Multiply, expression(1), expression(3));
+} break;
+
+#line 899 "./glsl.g"
+
+case 35: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_Divide, expression(1), expression(3));
+} break;
+
+#line 906 "./glsl.g"
+
+case 36: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_Modulus, expression(1), expression(3));
+} break;
+
+#line 913 "./glsl.g"
+
+case 37: {
+ // nothing to do.
+} break;
+
+#line 920 "./glsl.g"
+
+case 38: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_Plus, expression(1), expression(3));
+} break;
+
+#line 927 "./glsl.g"
+
+case 39: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_Minus, expression(1), expression(3));
+} break;
+
+#line 934 "./glsl.g"
+
+case 40: {
+ // nothing to do.
+} break;
+
+#line 941 "./glsl.g"
+
+case 41: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_ShiftLeft, expression(1), expression(3));
+} break;
+
+#line 948 "./glsl.g"
+
+case 42: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_ShiftRight, expression(1), expression(3));
+} break;
+
+#line 955 "./glsl.g"
+
+case 43: {
+ // nothing to do.
+} break;
+
+#line 962 "./glsl.g"
+
+case 44: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_LessThan, expression(1), expression(3));
+} break;
+
+#line 969 "./glsl.g"
+
+case 45: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_GreaterThan, expression(1), expression(3));
+} break;
+
+#line 976 "./glsl.g"
+
+case 46: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_LessEqual, expression(1), expression(3));
+} break;
+
+#line 983 "./glsl.g"
+
+case 47: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_GreaterEqual, expression(1), expression(3));
+} break;
+
+#line 990 "./glsl.g"
+
+case 48: {
+ // nothing to do.
+} break;
+
+#line 997 "./glsl.g"
+
+case 49: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_Equal, expression(1), expression(3));
+} break;
+
+#line 1004 "./glsl.g"
+
+case 50: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_NotEqual, expression(1), expression(3));
+} break;
+
+#line 1011 "./glsl.g"
+
+case 51: {
+ // nothing to do.
+} break;
+
+#line 1018 "./glsl.g"
+
+case 52: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_BitwiseAnd, expression(1), expression(3));
+} break;
+
+#line 1025 "./glsl.g"
+
+case 53: {
+ // nothing to do.
+} break;
+
+#line 1032 "./glsl.g"
+
+case 54: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_BitwiseXor, expression(1), expression(3));
+} break;
+
+#line 1039 "./glsl.g"
+
+case 55: {
+ // nothing to do.
+} break;
+
+#line 1046 "./glsl.g"
+
+case 56: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_BitwiseOr, expression(1), expression(3));
+} break;
+
+#line 1053 "./glsl.g"
+
+case 57: {
+ // nothing to do.
+} break;
+
+#line 1060 "./glsl.g"
+
+case 58: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_LogicalAnd, expression(1), expression(3));
+} break;
+
+#line 1067 "./glsl.g"
+
+case 59: {
+ // nothing to do.
+} break;
+
+#line 1074 "./glsl.g"
+
+case 60: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_LogicalXor, expression(1), expression(3));
+} break;
+
+#line 1081 "./glsl.g"
+
+case 61: {
+ // nothing to do.
+} break;
+
+#line 1088 "./glsl.g"
+
+case 62: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_LogicalOr, expression(1), expression(3));
+} break;
+
+#line 1095 "./glsl.g"
+
+case 63: {
+ // nothing to do.
+} break;
+
+#line 1102 "./glsl.g"
+
+case 64: {
+ ast(1) = makeAstNode<TernaryExpressionAST>(AST::Kind_Conditional, expression(1), expression(3), expression(5));
+} break;
+
+#line 1109 "./glsl.g"
+
+case 65: {
+ // nothing to do.
+} break;
+
+#line 1116 "./glsl.g"
+
+case 66: {
+ ast(1) = makeAstNode<AssignmentExpressionAST>(sym(2).kind, expression(1), expression(3));
+} break;
+
+#line 1123 "./glsl.g"
+
+case 67: {
+ sym(1).kind = AST::Kind_Assign;
+} break;
+
+#line 1130 "./glsl.g"
+
+case 68: {
+ sym(1).kind = AST::Kind_AssignMultiply;
+} break;
+
+#line 1137 "./glsl.g"
+
+case 69: {
+ sym(1).kind = AST::Kind_AssignDivide;
+} break;
+
+#line 1144 "./glsl.g"
+
+case 70: {
+ sym(1).kind = AST::Kind_AssignModulus;
+} break;
+
+#line 1151 "./glsl.g"
+
+case 71: {
+ sym(1).kind = AST::Kind_AssignPlus;
+} break;
+
+#line 1158 "./glsl.g"
+
+case 72: {
+ sym(1).kind = AST::Kind_AssignMinus;
+} break;
+
+#line 1165 "./glsl.g"
+
+case 73: {
+ sym(1).kind = AST::Kind_AssignShiftLeft;
+} break;
+
+#line 1172 "./glsl.g"
+
+case 74: {
+ sym(1).kind = AST::Kind_AssignShiftRight;
+} break;
+
+#line 1179 "./glsl.g"
+
+case 75: {
+ sym(1).kind = AST::Kind_AssignAnd;
+} break;
+
+#line 1186 "./glsl.g"
+
+case 76: {
+ sym(1).kind = AST::Kind_AssignXor;
+} break;
+
+#line 1193 "./glsl.g"
+
+case 77: {
+ sym(1).kind = AST::Kind_AssignOr;
+} break;
+
+#line 1200 "./glsl.g"
+
+case 78: {
+ // nothing to do.
+} break;
+
+#line 1207 "./glsl.g"
+
+case 79: {
+ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_Comma, expression(1), expression(3));
+} break;
+
+#line 1214 "./glsl.g"
+
+case 80: {
+ // nothing to do.
+} break;
+
+#line 1221 "./glsl.g"
+
+case 81: {
+ // nothing to do.
+} break;
+
+#line 1228 "./glsl.g"
+
+case 82: {
+ ast(1) = makeAstNode<InitDeclarationAST>(sym(1).declaration_list);
+} break;
+
+#line 1235 "./glsl.g"
+
+case 83: {
+ ast(1) = makeAstNode<PrecisionDeclarationAST>(sym(2).precision, type(3));
+} break;
+
+#line 1242 "./glsl.g"
+
+case 84: {
+ if (sym(1).type_qualifier.qualifier != QualifiedTypeAST::Struct) {
+ // TODO: issue an error if the qualifier is not "struct".
+ }
+ TypeAST *type = makeAstNode<StructTypeAST>(string(2), sym(4).field_list);
+ ast(1) = makeAstNode<TypeDeclarationAST>(type);
+} break;
+
+#line 1253 "./glsl.g"
+
+case 85: {
+ if ((sym(1).type_qualifier.qualifier & QualifiedTypeAST::Struct) == 0) {
+ // TODO: issue an error if the qualifier does not contain "struct".
+ }
+ TypeAST *type = makeAstNode<StructTypeAST>(string(2), sym(4).field_list);
+ TypeAST *qualtype = type;
+ if (sym(1).type_qualifier.qualifier != QualifiedTypeAST::Struct) {
+ qualtype = makeAstNode<QualifiedTypeAST>
+ (sym(1).type_qualifier.qualifier & ~QualifiedTypeAST::Struct, qualtype,
+ sym(1).type_qualifier.layout_list);
+ }
+ ast(1) = makeAstNode<TypeAndVariableDeclarationAST>
+ (makeAstNode<TypeDeclarationAST>(type),
+ makeAstNode<VariableDeclarationAST>(qualtype, string(6)));
+} break;
+
+#line 1272 "./glsl.g"
+
+case 86: {
+ if ((sym(1).type_qualifier.qualifier & QualifiedTypeAST::Struct) == 0) {
+ // TODO: issue an error if the qualifier does not contain "struct".
+ }
+ TypeAST *type = makeAstNode<StructTypeAST>(string(2), sym(4).field_list);
+ TypeAST *qualtype = type;
+ if (sym(1).type_qualifier.qualifier != QualifiedTypeAST::Struct) {
+ qualtype = makeAstNode<QualifiedTypeAST>
+ (sym(1).type_qualifier.qualifier & ~QualifiedTypeAST::Struct, qualtype,
+ sym(1).type_qualifier.layout_list);
+ }
+ ast(1) = makeAstNode<TypeAndVariableDeclarationAST>
+ (makeAstNode<TypeDeclarationAST>(type),
+ makeAstNode<VariableDeclarationAST>
+ (makeAstNode<ArrayTypeAST>(qualtype), string(6)));
+} break;
+
+#line 1292 "./glsl.g"
+
+case 87: {
+ if ((sym(1).type_qualifier.qualifier & QualifiedTypeAST::Struct) == 0) {
+ // TODO: issue an error if the qualifier does not contain "struct".
+ }
+ TypeAST *type = makeAstNode<StructTypeAST>(string(2), sym(4).field_list);
+ TypeAST *qualtype = type;
+ if (sym(1).type_qualifier.qualifier != QualifiedTypeAST::Struct) {
+ qualtype = makeAstNode<QualifiedTypeAST>
+ (sym(1).type_qualifier.qualifier & ~QualifiedTypeAST::Struct, qualtype,
+ sym(1).type_qualifier.layout_list);
+ }
+ ast(1) = makeAstNode<TypeAndVariableDeclarationAST>
+ (makeAstNode<TypeDeclarationAST>(type),
+ makeAstNode<VariableDeclarationAST>
+ (makeAstNode<ArrayTypeAST>(qualtype, expression(8)), string(6)));
+} break;
+
+#line 1312 "./glsl.g"
+
+case 88: {
+ TypeAST *type = makeAstNode<QualifiedTypeAST>
+ (sym(1).type_qualifier.qualifier, (TypeAST *)0,
+ sym(1).type_qualifier.layout_list);
+ ast(1) = makeAstNode<TypeDeclarationAST>(type);
+} break;
+
+#line 1322 "./glsl.g"
+
+case 89: {
+ function(1)->finishParams();
+} break;
+
+#line 1329 "./glsl.g"
+
+case 90: {
+ // nothing to do.
+} break;
+
+#line 1336 "./glsl.g"
+
+case 91: {
+ // nothing to do.
+} break;
+
+#line 1343 "./glsl.g"
+
+case 92: {
+ function(1)->params = makeAstNode< List<ParameterDeclarationAST *> >
+ (sym(2).param_declaration);
+} break;
+
+#line 1351 "./glsl.g"
+
+case 93: {
+ function(1)->params = makeAstNode< List<ParameterDeclarationAST *> >
+ (function(1)->params, sym(3).param_declaration);
+} break;
+
+#line 1359 "./glsl.g"
+
+case 94: {
+ function(1) = makeAstNode<FunctionDeclarationAST>(type(1), string(2));
+} break;
+
+#line 1366 "./glsl.g"
+
+case 95: {
+ sym(1).param_declarator.type = type(1);
+ sym(1).param_declarator.name = string(2);
+} break;
+
+#line 1374 "./glsl.g"
+
+case 96: {
+ sym(1).param_declarator.type = makeAstNode<ArrayTypeAST>(type(1), expression(4));
+ sym(1).param_declarator.name = string(2);
+} break;
+
+#line 1382 "./glsl.g"
+
+case 97: {
+ ast(1) = makeAstNode<ParameterDeclarationAST>
+ (makeAstNode<QualifiedTypeAST>
+ (sym(1).qualifier, sym(3).param_declarator.type,
+ (List<LayoutQualifier *> *)0),
+ ParameterDeclarationAST::Qualifier(sym(2).qualifier),
+ sym(3).param_declarator.name);
+} break;
+
+#line 1394 "./glsl.g"
+
+case 98: {
+ ast(1) = makeAstNode<ParameterDeclarationAST>
+ (sym(2).param_declarator.type,
+ ParameterDeclarationAST::Qualifier(sym(1).qualifier),
+ sym(2).param_declarator.name);
+} break;
+
+#line 1404 "./glsl.g"
+
+case 99: {
+ ast(1) = makeAstNode<ParameterDeclarationAST>
+ (makeAstNode<QualifiedTypeAST>
+ (sym(1).qualifier, type(3), (List<LayoutQualifier *> *)0),
+ ParameterDeclarationAST::Qualifier(sym(2).qualifier),
+ (const QString *)0);
+} break;
+
+#line 1415 "./glsl.g"
+
+case 100: {
+ ast(1) = makeAstNode<ParameterDeclarationAST>
+ (type(2), ParameterDeclarationAST::Qualifier(sym(1).qualifier),
+ (const QString *)0);
+} break;
+
+#line 1424 "./glsl.g"
+
+case 101: {
+ sym(1).qualifier = ParameterDeclarationAST::In;
+} break;
+
+#line 1431 "./glsl.g"
+
+case 102: {
+ sym(1).qualifier = ParameterDeclarationAST::In;
+} break;
+
+#line 1438 "./glsl.g"
+
+case 103: {
+ sym(1).qualifier = ParameterDeclarationAST::Out;
+} break;
+
+#line 1445 "./glsl.g"
+
+case 104: {
+ sym(1).qualifier = ParameterDeclarationAST::InOut;
+} break;
+
+#line 1452 "./glsl.g"
+
+case 105: {
+ // nothing to do.
+} break;
+
+#line 1459 "./glsl.g"
+
+case 106: {
+ sym(1).declaration_list = makeAstNode< List<DeclarationAST *> >
+ (sym(1).declaration);
+} break;
+
+#line 1467 "./glsl.g"
+
+case 107: {
+ TypeAST *type = VariableDeclarationAST::declarationType(sym(1).declaration_list);
+ DeclarationAST *decl = makeAstNode<VariableDeclarationAST>(type, string(3));
+ sym(1).declaration_list = makeAstNode< List<DeclarationAST *> >
+ (sym(1).declaration_list, decl);
+} break;
+
+#line 1477 "./glsl.g"
+
+case 108: {
+ TypeAST *type = VariableDeclarationAST::declarationType(sym(1).declaration_list);
+ type = makeAstNode<ArrayTypeAST>(type);
+ DeclarationAST *decl = makeAstNode<VariableDeclarationAST>(type, string(3));
+ sym(1).declaration_list = makeAstNode< List<DeclarationAST *> >
+ (sym(1).declaration_list, decl);
+} break;
+
+#line 1488 "./glsl.g"
+
+case 109: {
+ TypeAST *type = VariableDeclarationAST::declarationType(sym(1).declaration_list);
+ type = makeAstNode<ArrayTypeAST>(type, expression(5));
+ DeclarationAST *decl = makeAstNode<VariableDeclarationAST>(type, string(3));
+ sym(1).declaration_list = makeAstNode< List<DeclarationAST *> >
+ (sym(1).declaration_list, decl);
+} break;
+
+#line 1499 "./glsl.g"
+
+case 110: {
+ TypeAST *type = VariableDeclarationAST::declarationType(sym(1).declaration_list);
+ type = makeAstNode<ArrayTypeAST>(type);
+ DeclarationAST *decl = makeAstNode<VariableDeclarationAST>
+ (type, string(3), expression(7));
+ sym(1).declaration_list = makeAstNode< List<DeclarationAST *> >
+ (sym(1).declaration_list, decl);
+} break;
+
+#line 1511 "./glsl.g"
+
+case 111: {
+ TypeAST *type = VariableDeclarationAST::declarationType(sym(1).declaration_list);
+ type = makeAstNode<ArrayTypeAST>(type, expression(5));
+ DeclarationAST *decl = makeAstNode<VariableDeclarationAST>
+ (type, string(3), expression(8));
+ sym(1).declaration_list = makeAstNode< List<DeclarationAST *> >
+ (sym(1).declaration_list, decl);
+} break;
+
+#line 1523 "./glsl.g"
+
+case 112: {
+ TypeAST *type = VariableDeclarationAST::declarationType(sym(1).declaration_list);
+ DeclarationAST *decl = makeAstNode<VariableDeclarationAST>
+ (type, string(3), expression(5));
+ sym(1).declaration_list = makeAstNode< List<DeclarationAST *> >
+ (sym(1).declaration_list, decl);
+} break;
+
+#line 1534 "./glsl.g"
+
+case 113: {
+ ast(1) = makeAstNode<TypeDeclarationAST>(type(1));
+} break;
+
+#line 1541 "./glsl.g"
+
+case 114: {
+ ast(1) = makeAstNode<VariableDeclarationAST>(type(1), string(2));
+} break;
+
+#line 1548 "./glsl.g"
+
+case 115: {
+ ast(1) = makeAstNode<VariableDeclarationAST>
+ (makeAstNode<ArrayTypeAST>(type(1)), string(2));
+} break;
+
+#line 1556 "./glsl.g"
+
+case 116: {
+ ast(1) = makeAstNode<VariableDeclarationAST>
+ (makeAstNode<ArrayTypeAST>(type(1), expression(4)), string(2));
+} break;
+
+#line 1564 "./glsl.g"
+
+case 117: {
+ ast(1) = makeAstNode<VariableDeclarationAST>
+ (makeAstNode<ArrayTypeAST>(type(1)), string(2), expression(6));
+} break;
+
+#line 1572 "./glsl.g"
+
+case 118: {
+ ast(1) = makeAstNode<VariableDeclarationAST>
+ (makeAstNode<ArrayTypeAST>(type(1), expression(4)),
+ string(2), expression(7));
+} break;
+
+#line 1581 "./glsl.g"
+
+case 119: {
+ ast(1) = makeAstNode<VariableDeclarationAST>
+ (type(1), string(2), expression(4));
+} break;
+
+#line 1589 "./glsl.g"
+
+case 120: {
+ ast(1) = makeAstNode<InvariantDeclarationAST>(string(2));
+} break;
+
+#line 1596 "./glsl.g"
+
+case 121: {
+ ast(1) = makeAstNode<QualifiedTypeAST>(0, type(1), (List<LayoutQualifier *> *)0);
+} break;
+
+#line 1603 "./glsl.g"
+
+case 122: {
+ ast(1) = makeAstNode<QualifiedTypeAST>
+ (sym(1).type_qualifier.qualifier, type(2),
+ sym(1).type_qualifier.layout_list);
+} break;
+
+#line 1612 "./glsl.g"
+
+case 123: {
+ sym(1).qualifier = QualifiedTypeAST::Invariant;
+} break;
+
+#line 1619 "./glsl.g"
+
+case 124: {
+ sym(1).qualifier = QualifiedTypeAST::Smooth;
+} break;
+
+#line 1626 "./glsl.g"
+
+case 125: {
+ sym(1).qualifier = QualifiedTypeAST::Flat;
+} break;
+
+#line 1633 "./glsl.g"
+
+case 126: {
+ sym(1).qualifier = QualifiedTypeAST::NoPerspective;
+} break;
+
+#line 1640 "./glsl.g"
+
+case 127: {
+ sym(1) = sym(3);
+} break;
+
+#line 1647 "./glsl.g"
+
+case 128: {
+ sym(1).layout_list = makeAstNode< List<LayoutQualifier *> >(sym(1).layout);
+} break;
+
+#line 1654 "./glsl.g"
+
+case 129: {
+ sym(1).layout_list = makeAstNode< List<LayoutQualifier *> >(sym(1).layout_list, sym(3).layout);
+} break;
+
+#line 1661 "./glsl.g"
+
+case 130: {
+ sym(1).layout = makeAstNode<LayoutQualifier>(string(1), (const QString *)0);
+} break;
+
+#line 1668 "./glsl.g"
+
+case 131: {
+ sym(1).layout = makeAstNode<LayoutQualifier>(string(1), string(3));
+} break;
+
+#line 1675 "./glsl.g"
+
+case 132: {
+ sym(1).qualifier = QualifiedTypeAST::Const;
+} break;
+
+#line 1682 "./glsl.g"
+
+case 133: {
+ sym(1).type_qualifier.qualifier = sym(1).qualifier;
+ sym(1).type_qualifier.layout_list = 0;
+} break;
+
+#line 1690 "./glsl.g"
+
+case 134: {
+ sym(1).type_qualifier.layout_list = sym(1).layout_list;
+ sym(1).type_qualifier.qualifier = 0;
+} break;
+
+#line 1698 "./glsl.g"
+
+case 135: {
+ sym(1).type_qualifier.layout_list = sym(1).layout_list;
+ sym(1).type_qualifier.qualifier = sym(2).qualifier;
+} break;
+
+#line 1706 "./glsl.g"
+
+case 136: {
+ sym(1).type_qualifier.qualifier = sym(1).qualifier | sym(2).qualifier;
+ sym(1).type_qualifier.layout_list = 0;
+} break;
+
+#line 1714 "./glsl.g"
+
+case 137: {
+ sym(1).type_qualifier.qualifier = sym(1).qualifier;
+ sym(1).type_qualifier.layout_list = 0;
+} break;
+
+#line 1722 "./glsl.g"
+
+case 138: {
+ sym(1).type_qualifier.qualifier = sym(1).qualifier | sym(2).qualifier;
+ sym(1).type_qualifier.layout_list = 0;
+} break;
+
+#line 1730 "./glsl.g"
+
+case 139: {
+ sym(1).type_qualifier.qualifier = sym(1).qualifier | sym(2).qualifier | sym(3).qualifier;
+ sym(1).type_qualifier.layout_list = 0;
+} break;
+
+#line 1738 "./glsl.g"
+
+case 140: {
+ sym(1).type_qualifier.qualifier = QualifiedTypeAST::Invariant;
+ sym(1).type_qualifier.layout_list = 0;
+} break;
+
+#line 1746 "./glsl.g"
+
+case 141: {
+ sym(1).qualifier = QualifiedTypeAST::Const;
+} break;
+
+#line 1753 "./glsl.g"
+
+case 142: {
+ sym(1).qualifier = QualifiedTypeAST::Attribute;
+} break;
+
+#line 1760 "./glsl.g"
+
+case 143: {
+ sym(1).qualifier = QualifiedTypeAST::Varying;
+} break;
+
+#line 1767 "./glsl.g"
+
+case 144: {
+ sym(1).qualifier = QualifiedTypeAST::CentroidVarying;
+} break;
+
+#line 1774 "./glsl.g"
+
+case 145: {
+ sym(1).qualifier = QualifiedTypeAST::In;
+} break;
+
+#line 1781 "./glsl.g"
+
+case 146: {
+ sym(1).qualifier = QualifiedTypeAST::Out;
+} break;
+
+#line 1788 "./glsl.g"
+
+case 147: {
+ sym(1).qualifier = QualifiedTypeAST::CentroidIn;
+} break;
+
+#line 1795 "./glsl.g"
+
+case 148: {
+ sym(1).qualifier = QualifiedTypeAST::CentroidOut;
+} break;
+
+#line 1802 "./glsl.g"
+
+case 149: {
+ sym(1).qualifier = QualifiedTypeAST::PatchIn;
+} break;
+
+#line 1809 "./glsl.g"
+
+case 150: {
+ sym(1).qualifier = QualifiedTypeAST::PatchOut;
+} break;
+
+#line 1816 "./glsl.g"
+
+case 151: {
+ sym(1).qualifier = QualifiedTypeAST::SampleIn;
+} break;
+
+#line 1823 "./glsl.g"
+
+case 152: {
+ sym(1).qualifier = QualifiedTypeAST::SampleOut;
+} break;
+
+#line 1830 "./glsl.g"
+
+case 153: {
+ sym(1).qualifier = QualifiedTypeAST::Uniform;
+} break;
+
+#line 1837 "./glsl.g"
+
+case 154: {
+ // nothing to do.
+} break;
+
+#line 1844 "./glsl.g"
+
+case 155: {
+ if (!type(2)->setPrecision(sym(1).precision)) {
+ // TODO: issue an error about precision not allowed on this type.
+ }
+ ast(1) = type(2);
+} break;
+
+#line 1854 "./glsl.g"
+
+case 156: {
+ // nothing to do.
+} break;
+
+#line 1861 "./glsl.g"
+
+case 157: {
+ ast(1) = makeAstNode<ArrayTypeAST>(type(1));
+} break;
+
+#line 1868 "./glsl.g"
+
+case 158: {
+ ast(1) = makeAstNode<ArrayTypeAST>(type(1), expression(3));
+} break;
+
+#line 1875 "./glsl.g"
+
+case 159: {
+ ast(1) = makeBasicType(T_VOID);
+} break;
+
+#line 1882 "./glsl.g"
+
+case 160: {
+ ast(1) = makeBasicType(T_FLOAT);
+} break;
+
+#line 1889 "./glsl.g"
+
+case 161: {
+ ast(1) = makeBasicType(T_DOUBLE);
+} break;
+
+#line 1896 "./glsl.g"
+
+case 162: {
+ ast(1) = makeBasicType(T_INT);
+} break;
+
+#line 1903 "./glsl.g"
+
+case 163: {
+ ast(1) = makeBasicType(T_UINT);
+} break;
+
+#line 1910 "./glsl.g"
+
+case 164: {
+ ast(1) = makeBasicType(T_BOOL);
+} break;
+
+#line 1917 "./glsl.g"
+
+case 165: {
+ ast(1) = makeBasicType(T_VEC2);
+} break;
+
+#line 1924 "./glsl.g"
+
+case 166: {
+ ast(1) = makeBasicType(T_VEC3);
+} break;
+
+#line 1931 "./glsl.g"
+
+case 167: {
+ ast(1) = makeBasicType(T_VEC4);
+} break;
+
+#line 1938 "./glsl.g"
+
+case 168: {
+ ast(1) = makeBasicType(T_DVEC2);
+} break;
+
+#line 1945 "./glsl.g"
+
+case 169: {
+ ast(1) = makeBasicType(T_DVEC3);
+} break;
+
+#line 1952 "./glsl.g"
+
+case 170: {
+ ast(1) = makeBasicType(T_DVEC4);
+} break;
+
+#line 1959 "./glsl.g"
+
+case 171: {
+ ast(1) = makeBasicType(T_BVEC2);
+} break;
+
+#line 1966 "./glsl.g"
+
+case 172: {
+ ast(1) = makeBasicType(T_BVEC3);
+} break;
+
+#line 1973 "./glsl.g"
+
+case 173: {
+ ast(1) = makeBasicType(T_BVEC4);
+} break;
+
+#line 1980 "./glsl.g"
+
+case 174: {
+ ast(1) = makeBasicType(T_IVEC2);
+} break;
+
+#line 1987 "./glsl.g"
+
+case 175: {
+ ast(1) = makeBasicType(T_IVEC3);
+} break;
+
+#line 1994 "./glsl.g"
+
+case 176: {
+ ast(1) = makeBasicType(T_IVEC4);
+} break;
+
+#line 2001 "./glsl.g"
+
+case 177: {
+ ast(1) = makeBasicType(T_UVEC2);
+} break;
+
+#line 2008 "./glsl.g"
+
+case 178: {
+ ast(1) = makeBasicType(T_UVEC3);
+} break;
+
+#line 2015 "./glsl.g"
+
+case 179: {
+ ast(1) = makeBasicType(T_UVEC4);
+} break;
+
+#line 2022 "./glsl.g"
+
+case 180: {
+ ast(1) = makeBasicType(T_MAT2);
+} break;
+
+#line 2029 "./glsl.g"
+
+case 181: {
+ ast(1) = makeBasicType(T_MAT3);
+} break;
+
+#line 2036 "./glsl.g"
+
+case 182: {
+ ast(1) = makeBasicType(T_MAT4);
+} break;
+
+#line 2043 "./glsl.g"
+
+case 183: {
+ ast(1) = makeBasicType(T_MAT2);
+} break;
+
+#line 2050 "./glsl.g"
+
+case 184: {
+ ast(1) = makeBasicType(T_MAT2X3);
+} break;
+
+#line 2057 "./glsl.g"
+
+case 185: {
+ ast(1) = makeBasicType(T_MAT2X4);
+} break;
+
+#line 2064 "./glsl.g"
+
+case 186: {
+ ast(1) = makeBasicType(T_MAT3X2);
+} break;
+
+#line 2071 "./glsl.g"
+
+case 187: {
+ ast(1) = makeBasicType(T_MAT3);
+} break;
+
+#line 2078 "./glsl.g"
+
+case 188: {
+ ast(1) = makeBasicType(T_MAT3X4);
+} break;
+
+#line 2085 "./glsl.g"
+
+case 189: {
+ ast(1) = makeBasicType(T_MAT4X2);
+} break;
+
+#line 2092 "./glsl.g"
+
+case 190: {
+ ast(1) = makeBasicType(T_MAT4X3);
+} break;
+
+#line 2099 "./glsl.g"
+
+case 191: {
+ ast(1) = makeBasicType(T_MAT4);
+} break;
+
+#line 2106 "./glsl.g"
+
+case 192: {
+ ast(1) = makeBasicType(T_DMAT2);
+} break;
+
+#line 2113 "./glsl.g"
+
+case 193: {
+ ast(1) = makeBasicType(T_DMAT3);
+} break;
+
+#line 2120 "./glsl.g"
+
+case 194: {
+ ast(1) = makeBasicType(T_DMAT4);
+} break;
+
+#line 2127 "./glsl.g"
+
+case 195: {
+ ast(1) = makeBasicType(T_DMAT2);
+} break;
+
+#line 2134 "./glsl.g"
+
+case 196: {
+ ast(1) = makeBasicType(T_DMAT2X3);
+} break;
+
+#line 2141 "./glsl.g"
+
+case 197: {
+ ast(1) = makeBasicType(T_DMAT2X4);
+} break;
+
+#line 2148 "./glsl.g"
+
+case 198: {
+ ast(1) = makeBasicType(T_DMAT3X2);
+} break;
+
+#line 2155 "./glsl.g"
+
+case 199: {
+ ast(1) = makeBasicType(T_DMAT3);
+} break;
+
+#line 2162 "./glsl.g"
+
+case 200: {
+ ast(1) = makeBasicType(T_DMAT3X4);
+} break;
+
+#line 2169 "./glsl.g"
+
+case 201: {
+ ast(1) = makeBasicType(T_DMAT4X2);
+} break;
+
+#line 2176 "./glsl.g"
+
+case 202: {
+ ast(1) = makeBasicType(T_DMAT4X3);
+} break;
+
+#line 2183 "./glsl.g"
+
+case 203: {
+ ast(1) = makeBasicType(T_DMAT4);
+} break;
+
+#line 2190 "./glsl.g"
+
+case 204: {
+ ast(1) = makeBasicType(T_SAMPLER1D);
+} break;
+
+#line 2197 "./glsl.g"
+
+case 205: {
+ ast(1) = makeBasicType(T_SAMPLER2D);
+} break;
+
+#line 2204 "./glsl.g"
+
+case 206: {
+ ast(1) = makeBasicType(T_SAMPLER3D);
+} break;
+
+#line 2211 "./glsl.g"
+
+case 207: {
+ ast(1) = makeBasicType(T_SAMPLERCUBE);
+} break;
+
+#line 2218 "./glsl.g"
+
+case 208: {
+ ast(1) = makeBasicType(T_SAMPLER1DSHADOW);
+} break;
+
+#line 2225 "./glsl.g"
+
+case 209: {
+ ast(1) = makeBasicType(T_SAMPLER2DSHADOW);
+} break;
+
+#line 2232 "./glsl.g"
+
+case 210: {
+ ast(1) = makeBasicType(T_SAMPLERCUBESHADOW);
+} break;
+
+#line 2239 "./glsl.g"
+
+case 211: {
+ ast(1) = makeBasicType(T_SAMPLER1DARRAY);
+} break;
+
+#line 2246 "./glsl.g"
+
+case 212: {
+ ast(1) = makeBasicType(T_SAMPLER2DARRAY);
+} break;
+
+#line 2253 "./glsl.g"
+
+case 213: {
+ ast(1) = makeBasicType(T_SAMPLER1DARRAYSHADOW);
+} break;
+
+#line 2260 "./glsl.g"
+
+case 214: {
+ ast(1) = makeBasicType(T_SAMPLER2DARRAYSHADOW);
+} break;
+
+#line 2267 "./glsl.g"
+
+case 215: {
+ ast(1) = makeBasicType(T_SAMPLERCUBEARRAY);
+} break;
+
+#line 2274 "./glsl.g"
+
+case 216: {
+ ast(1) = makeBasicType(T_SAMPLERCUBEARRAYSHADOW);
+} break;
+
+#line 2281 "./glsl.g"
+
+case 217: {
+ ast(1) = makeBasicType(T_ISAMPLER1D);
+} break;
+
+#line 2288 "./glsl.g"
+
+case 218: {
+ ast(1) = makeBasicType(T_ISAMPLER2D);
+} break;
+
+#line 2295 "./glsl.g"
+
+case 219: {
+ ast(1) = makeBasicType(T_ISAMPLER3D);
+} break;
+
+#line 2302 "./glsl.g"
+
+case 220: {
+ ast(1) = makeBasicType(T_ISAMPLERCUBE);
+} break;
+
+#line 2309 "./glsl.g"
+
+case 221: {
+ ast(1) = makeBasicType(T_ISAMPLER1DARRAY);
+} break;
+
+#line 2316 "./glsl.g"
+
+case 222: {
+ ast(1) = makeBasicType(T_ISAMPLER2DARRAY);
+} break;
+
+#line 2323 "./glsl.g"
+
+case 223: {
+ ast(1) = makeBasicType(T_ISAMPLERCUBEARRAY);
+} break;
+
+#line 2330 "./glsl.g"
+
+case 224: {
+ ast(1) = makeBasicType(T_USAMPLER1D);
+} break;
+
+#line 2337 "./glsl.g"
+
+case 225: {
+ ast(1) = makeBasicType(T_USAMPLER2D);
+} break;
+
+#line 2344 "./glsl.g"
+
+case 226: {
+ ast(1) = makeBasicType(T_USAMPLER3D);
+} break;
+
+#line 2351 "./glsl.g"
+
+case 227: {
+ ast(1) = makeBasicType(T_USAMPLERCUBE);
+} break;
+
+#line 2358 "./glsl.g"
+
+case 228: {
+ ast(1) = makeBasicType(T_USAMPLER1DARRAY);
+} break;
+
+#line 2365 "./glsl.g"
+
+case 229: {
+ ast(1) = makeBasicType(T_USAMPLER2DARRAY);
+} break;
+
+#line 2372 "./glsl.g"
+
+case 230: {
+ ast(1) = makeBasicType(T_USAMPLERCUBEARRAY);
+} break;
+
+#line 2379 "./glsl.g"
+
+case 231: {
+ ast(1) = makeBasicType(T_SAMPLER2DRECT);
+} break;
+
+#line 2386 "./glsl.g"
+
+case 232: {
+ ast(1) = makeBasicType(T_SAMPLER2DRECTSHADOW);
+} break;
+
+#line 2393 "./glsl.g"
+
+case 233: {
+ ast(1) = makeBasicType(T_ISAMPLER2DRECT);
+} break;
+
+#line 2400 "./glsl.g"
+
+case 234: {
+ ast(1) = makeBasicType(T_USAMPLER2DRECT);
+} break;
+
+#line 2407 "./glsl.g"
+
+case 235: {
+ ast(1) = makeBasicType(T_SAMPLERBUFFER);
+} break;
+
+#line 2414 "./glsl.g"
+
+case 236: {
+ ast(1) = makeBasicType(T_ISAMPLERBUFFER);
+} break;
+
+#line 2421 "./glsl.g"
+
+case 237: {
+ ast(1) = makeBasicType(T_USAMPLERBUFFER);
+} break;
+
+#line 2428 "./glsl.g"
+
+case 238: {
+ ast(1) = makeBasicType(T_SAMPLER2DMS);
+} break;
+
+#line 2435 "./glsl.g"
+
+case 239: {
+ ast(1) = makeBasicType(T_ISAMPLER2DMS);
+} break;
+
+#line 2442 "./glsl.g"
+
+case 240: {
+ ast(1) = makeBasicType(T_USAMPLER2DMS);
+} break;
+
+#line 2449 "./glsl.g"
+
+case 241: {
+ ast(1) = makeBasicType(T_SAMPLER2DMSARRAY);
+} break;
+
+#line 2456 "./glsl.g"
+
+case 242: {
+ ast(1) = makeBasicType(T_ISAMPLER2DMSARRAY);
+} break;
+
+#line 2463 "./glsl.g"
+
+case 243: {
+ ast(1) = makeBasicType(T_USAMPLER2DMSARRAY);
+} break;
+
+#line 2470 "./glsl.g"
+
+case 244: {
+ // nothing to do.
+} break;
+
+#line 2477 "./glsl.g"
+
+case 245: {
+ ast(1) = makeAstNode<NamedTypeAST>(string(1));
+} break;
+
+#line 2484 "./glsl.g"
+
+case 246: {
+ sym(1).precision = TypeAST::Highp;
+} break;
+
+#line 2491 "./glsl.g"
+
+case 247: {
+ sym(1).precision = TypeAST::Mediump;
+} break;
+
+#line 2498 "./glsl.g"
+
+case 248: {
+ sym(1).precision = TypeAST::Lowp;
+} break;
+
+#line 2505 "./glsl.g"
+
+case 249: {
+ ast(1) = makeAstNode<StructTypeAST>(string(2), sym(4).field_list);
+} break;
+
+#line 2512 "./glsl.g"
+
+case 250: {
+ ast(1) = makeAstNode<StructTypeAST>(sym(3).field_list);
+} break;
+
+#line 2519 "./glsl.g"
+
+case 251: {
+ // nothing to do.
+} break;
+
+#line 2526 "./glsl.g"
+
+case 252: {
+ sym(1).field_list = appendLists(sym(1).field_list, sym(2).field_list);
+} break;
+
+#line 2533 "./glsl.g"
+
+case 253: {
+ sym(1).field_list = StructTypeAST::fixInnerTypes(type(1), sym(2).field_list);
+} break;
+
+#line 2540 "./glsl.g"
+
+case 254: {
+ sym(1).field_list = StructTypeAST::fixInnerTypes
+ (makeAstNode<QualifiedTypeAST>
+ (sym(1).type_qualifier.qualifier, type(2),
+ sym(1).type_qualifier.layout_list), sym(3).field_list);
+} break;
+
+#line 2550 "./glsl.g"
+
+case 255: {
+ // nothing to do.
+ sym(1).field_list = makeAstNode< List<StructTypeAST::Field *> >(sym(1).field);
+} break;
+
+#line 2558 "./glsl.g"
+
+case 256: {
+ sym(1).field_list = makeAstNode< List<StructTypeAST::Field *> >(sym(1).field_list, sym(3).field);
+} break;
+
+#line 2565 "./glsl.g"
+
+case 257: {
+ sym(1).field = makeAstNode<StructTypeAST::Field>(string(1));
+} break;
+
+#line 2572 "./glsl.g"
+
+case 258: {
+ sym(1).field = makeAstNode<StructTypeAST::Field>
+ (string(1), makeAstNode<ArrayTypeAST>((TypeAST *)0));
+} break;
+
+#line 2580 "./glsl.g"
+
+case 259: {
+ sym(1).field = makeAstNode<StructTypeAST::Field>
+ (string(1), makeAstNode<ArrayTypeAST>((TypeAST *)0, expression(3)));
+} break;
+
+#line 2588 "./glsl.g"
+
+case 260: {
+ // nothing to do.
+} break;
+
+#line 2595 "./glsl.g"
+
+case 261: {
+ ast(1) = makeAstNode<DeclarationStatementAST>(sym(1).declaration);
+} break;
+
+#line 2602 "./glsl.g"
+
+case 262: {
+ // nothing to do.
+} break;
+
+#line 2609 "./glsl.g"
+
+case 263: {
+ // nothing to do.
+} break;
+
+#line 2616 "./glsl.g"
+
+case 264: {
+ // nothing to do.
+} break;
+
+#line 2623 "./glsl.g"
+
+case 265: {
+ // nothing to do.
+} break;
+
+#line 2630 "./glsl.g"
+
+case 266: {
+ // nothing to do.
+} break;
+
+#line 2637 "./glsl.g"
+
+case 267: {
+ // nothing to do.
+} break;
+
+#line 2644 "./glsl.g"
+
+case 268: {
+ // nothing to do.
+} break;
+
+#line 2651 "./glsl.g"
+
+case 269: {
+ // nothing to do.
+} break;
+
+#line 2658 "./glsl.g"
+
+case 270: {
+ // nothing to do.
+} break;
+
+#line 2665 "./glsl.g"
+
+case 271: {
+ CompoundStatementAST *stmt = makeAstNode<CompoundStatementAST>();
+ stmt->start = tokenAt(location(1)).begin();
+ stmt->end = tokenAt(location(2)).end();
+ ast(1) = stmt;
+} break;
+
+#line 2675 "./glsl.g"
+
+case 272: {
+ CompoundStatementAST *stmt = makeAstNode<CompoundStatementAST>(sym(2).statement_list);
+ stmt->start = tokenAt(location(1)).begin();
+ stmt->end = tokenAt(location(3)).end();
+ ast(1) = stmt;
+} break;
+
+#line 2685 "./glsl.g"
+
+case 273: {
+ // nothing to do.
+} break;
+
+#line 2692 "./glsl.g"
+
+case 274: {
+ // nothing to do.
+} break;
+
+#line 2699 "./glsl.g"
+
+case 275: {
+ CompoundStatementAST *stmt = makeAstNode<CompoundStatementAST>();
+ stmt->start = tokenAt(location(1)).begin();
+ stmt->end = tokenAt(location(2)).end();
+ ast(1) = stmt;
+} break;
+
+#line 2709 "./glsl.g"
+
+case 276: {
+ CompoundStatementAST *stmt = makeAstNode<CompoundStatementAST>(sym(2).statement_list);
+ stmt->start = tokenAt(location(1)).begin();
+ stmt->end = tokenAt(location(3)).end();
+ ast(1) = stmt;
+} break;
+
+#line 2719 "./glsl.g"
+
+case 277: {
+ sym(1).statement_list = makeAstNode< List<StatementAST *> >(sym(1).statement);
+} break;
+
+#line 2726 "./glsl.g"
+
+case 278: {
+ sym(1).statement_list = makeAstNode< List<StatementAST *> >(sym(1).statement_list, sym(2).statement);
+} break;
+
+#line 2733 "./glsl.g"
+
+case 279: {
+ ast(1) = makeAstNode<CompoundStatementAST>(); // Empty statement
+} break;
+
+#line 2740 "./glsl.g"
+
+case 280: {
+ ast(1) = makeAstNode<ExpressionStatementAST>(expression(1));
+} break;
+
+#line 2747 "./glsl.g"
+
+case 281: {
+ ast(1) = makeAstNode<IfStatementAST>(expression(3), sym(5).ifstmt.thenClause, sym(5).ifstmt.elseClause);
+} break;
+
+#line 2754 "./glsl.g"
+
+case 282: {
+ sym(1).ifstmt.thenClause = statement(1);
+ sym(1).ifstmt.elseClause = statement(3);
+} break;
+
+#line 2762 "./glsl.g"
+
+case 283: {
+ sym(1).ifstmt.thenClause = statement(1);
+ sym(1).ifstmt.elseClause = 0;
+} break;
+
+#line 2770 "./glsl.g"
+
+case 284: {
+ // nothing to do.
+} break;
+
+#line 2777 "./glsl.g"
+
+case 285: {
+ ast(1) = makeAstNode<DeclarationExpressionAST>
+ (type(1), string(2), expression(4));
+} break;
+
+#line 2785 "./glsl.g"
+
+case 286: {
+ ast(1) = makeAstNode<SwitchStatementAST>(expression(3), statement(6));
+} break;
+
+#line 2792 "./glsl.g"
+
+case 287: {
+ ast(1) = makeAstNode<CompoundStatementAST>();
+} break;
+
+#line 2799 "./glsl.g"
+
+case 288: {
+ ast(1) = makeAstNode<CompoundStatementAST>(sym(1).statement_list);
+} break;
+
+#line 2806 "./glsl.g"
+
+case 289: {
+ ast(1) = makeAstNode<CaseLabelStatementAST>(expression(2));
+} break;
+
+#line 2813 "./glsl.g"
+
+case 290: {
+ ast(1) = makeAstNode<CaseLabelStatementAST>();
+} break;
+
+#line 2820 "./glsl.g"
+
+case 291: {
+ ast(1) = makeAstNode<WhileStatementAST>(expression(3), statement(5));
+} break;
+
+#line 2827 "./glsl.g"
+
+case 292: {
+ ast(1) = makeAstNode<DoStatementAST>(statement(2), expression(5));
+} break;
+
+#line 2834 "./glsl.g"
+
+case 293: {
+ ast(1) = makeAstNode<ForStatementAST>(statement(3), sym(4).forstmt.condition, sym(4).forstmt.increment, statement(6));
+} break;
+
+#line 2841 "./glsl.g"
+
+case 294: {
+ // nothing to do.
+} break;
+
+#line 2848 "./glsl.g"
+
+case 295: {
+ // nothing to do.
+} break;
+
+#line 2855 "./glsl.g"
+
+case 296: {
+ // nothing to do.
+} break;
+
+#line 2862 "./glsl.g"
+
+case 297: {
+ // nothing to do.
+} break;
+
+#line 2869 "./glsl.g"
+
+case 298: {
+ sym(1).forstmt.condition = expression(1);
+ sym(1).forstmt.increment = 0;
+} break;
+
+#line 2877 "./glsl.g"
+
+case 299: {
+ sym(1).forstmt.condition = expression(1);
+ sym(1).forstmt.increment = expression(3);
+} break;
+
+#line 2885 "./glsl.g"
+
+case 300: {
+ ast(1) = makeAstNode<JumpStatementAST>(AST::Kind_Continue);
+} break;
+
+#line 2892 "./glsl.g"
+
+case 301: {
+ ast(1) = makeAstNode<JumpStatementAST>(AST::Kind_Break);
+} break;
+
+#line 2899 "./glsl.g"
+
+case 302: {
+ ast(1) = makeAstNode<ReturnStatementAST>();
+} break;
+
+#line 2906 "./glsl.g"
+
+case 303: {
+ ast(1) = makeAstNode<ReturnStatementAST>(expression(2));
+} break;
+
+#line 2913 "./glsl.g"
+
+case 304: {
+ ast(1) = makeAstNode<JumpStatementAST>(AST::Kind_Discard);
+} break;
+
+#line 2920 "./glsl.g"
+
+case 305: {
+ ast(1) = makeAstNode<TranslationUnitAST>(sym(1).declaration_list);
+} break;
+
+#line 2927 "./glsl.g"
+
+case 306: {
+ if (sym(1).declaration) {
+ sym(1).declaration_list = makeAstNode< List<DeclarationAST *> >
+ (sym(1).declaration);
+ } else {
+ sym(1).declaration_list = 0;
+ }
+} break;
+
+#line 2939 "./glsl.g"
+
+case 307: {
+ if (sym(1).declaration_list && sym(2).declaration) {
+ sym(1).declaration_list = makeAstNode< List<DeclarationAST *> >
+ (sym(1).declaration_list, sym(2).declaration);
+ } else if (!sym(1).declaration_list) {
+ if (sym(2).declaration) {
+ sym(1).declaration_list = makeAstNode< List<DeclarationAST *> >
+ (sym(2).declaration);
+ } else {
+ sym(1).declaration_list = 0;
+ }
+ }
+} break;
+
+#line 2956 "./glsl.g"
+
+case 308: {
+ // nothing to do.
+} break;
+
+#line 2963 "./glsl.g"
+
+case 309: {
+ // nothing to do.
+} break;
+
+#line 2970 "./glsl.g"
+
+case 310: {
+ ast(1) = 0;
+} break;
+
+#line 2977 "./glsl.g"
+
+case 311: {
+ function(1)->body = statement(2);
+} break;
+
+#line 2984 "./glsl.g"
+
+case 312: {
+ ast(1) = 0;
+} break;
+
+#line 2992 "./glsl.g"
+
+case 313: {
+ ast(1) = ast(2);
+} break;
+
+#line 2999 "./glsl.g"
+
+case 314: {
+ ast(1) = ast(2);
+} break;
+
+#line 3005 "./glsl.g"
+
+} // end switch
+} // end Parser::reduce()
diff --git a/src/libs/glsl/glslparser.h b/src/libs/glsl/glslparser.h
new file mode 100644
index 0000000000..45acaf00cd
--- /dev/null
+++ b/src/libs/glsl/glslparser.h
@@ -0,0 +1,207 @@
+
+#line 213 "./glsl.g"
+
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "glslparsertable_p.h"
+#include "glsllexer.h"
+#include "glslast.h"
+#include "glslengine.h"
+#include <vector>
+#include <stack>
+
+namespace GLSL {
+
+class GLSL_EXPORT Parser: public GLSLParserTable
+{
+public:
+ union Value {
+ void *ptr;
+ const QString *string;
+ AST *ast;
+ List<AST *> *ast_list;
+ DeclarationAST *declaration;
+ List<DeclarationAST *> *declaration_list;
+ ExpressionAST *expression;
+ List<ExpressionAST *> *expression_list;
+ StatementAST *statement;
+ List<StatementAST *> *statement_list;
+ TypeAST *type;
+ StructTypeAST::Field *field;
+ List<StructTypeAST::Field *> *field_list;
+ TranslationUnitAST *translation_unit;
+ FunctionIdentifierAST *function_identifier;
+ AST::Kind kind;
+ TypeAST::Precision precision;
+ struct {
+ StatementAST *thenClause;
+ StatementAST *elseClause;
+ } ifstmt;
+ struct {
+ ExpressionAST *condition;
+ ExpressionAST *increment;
+ } forstmt;
+ struct {
+ FunctionIdentifierAST *id;
+ List<ExpressionAST *> *arguments;
+ } function;
+ int qualifier;
+ LayoutQualifier *layout;
+ List<LayoutQualifier *> *layout_list;
+ struct {
+ int qualifier;
+ List<LayoutQualifier *> *layout_list;
+ } type_qualifier;
+ struct {
+ TypeAST *type;
+ const QString *name;
+ } param_declarator;
+ ParameterDeclarationAST *param_declaration;
+ FunctionDeclarationAST *function_declaration;
+ };
+
+ Parser(Engine *engine, const char *source, unsigned size, int variant);
+ ~Parser();
+
+ TranslationUnitAST *parse() {
+ if (AST *u = parse(T_FEED_GLSL))
+ return u->asTranslationUnit();
+ return 0;
+ }
+
+ ExpressionAST *parseExpression() {
+ if (AST *u = parse(T_FEED_EXPRESSION))
+ return u->asExpression();
+ return 0;
+ }
+
+ AST *parse(int startToken);
+
+private:
+ // 1-based
+ int &location(int n) { return _locationStack[_tos + n - 1]; }
+ Value &sym(int n) { return _symStack[_tos + n - 1]; }
+ AST *&ast(int n) { return _symStack[_tos + n - 1].ast; }
+ const QString *&string(int n) { return _symStack[_tos + n - 1].string; }
+ ExpressionAST *&expression(int n) { return _symStack[_tos + n - 1].expression; }
+ StatementAST *&statement(int n) { return _symStack[_tos + n - 1].statement; }
+ TypeAST *&type(int n) { return _symStack[_tos + n - 1].type; }
+ FunctionDeclarationAST *&function(int n) { return _symStack[_tos + n - 1].function_declaration; }
+
+ inline int consumeToken() {
+ if (_index < int(_tokens.size()))
+ return _index++;
+ return _tokens.size() - 1;
+ }
+ inline const Token &tokenAt(int index) const {
+ if (index == 0)
+ return _startToken;
+ return _tokens.at(index);
+ }
+ inline int tokenKind(int index) const {
+ if (index == 0)
+ return _startToken.kind;
+ return _tokens.at(index).kind;
+ }
+ void reduce(int ruleno);
+
+ void warning(int line, const QString &message)
+ {
+ _engine->warning(line, message);
+ }
+
+ void error(int line, const QString &message)
+ {
+ _engine->error(line, message);
+ }
+
+ template <typename T>
+ T *makeAstNode()
+ {
+ T *node = new (_engine->pool()) T ();
+ node->lineno = yyloc >= 0 ? (_tokens[yyloc].line + 1) : 0;
+ return node;
+ }
+
+ template <typename T, typename A1>
+ T *makeAstNode(A1 a1)
+ {
+ T *node = new (_engine->pool()) T (a1);
+ node->lineno = yyloc >= 0 ? (_tokens[yyloc].line + 1) : 0;
+ return node;
+ }
+
+ template <typename T, typename A1, typename A2>
+ T *makeAstNode(A1 a1, A2 a2)
+ {
+ T *node = new (_engine->pool()) T (a1, a2);
+ node->lineno = yyloc >= 0 ? (_tokens[yyloc].line + 1) : 0;
+ return node;
+ }
+
+ template <typename T, typename A1, typename A2, typename A3>
+ T *makeAstNode(A1 a1, A2 a2, A3 a3)
+ {
+ T *node = new (_engine->pool()) T (a1, a2, a3);
+ node->lineno = yyloc >= 0 ? (_tokens[yyloc].line + 1) : 0;
+ return node;
+ }
+
+ template <typename T, typename A1, typename A2, typename A3, typename A4>
+ T *makeAstNode(A1 a1, A2 a2, A3 a3, A4 a4)
+ {
+ T *node = new (_engine->pool()) T (a1, a2, a3, a4);
+ node->lineno = yyloc >= 0 ? (_tokens[yyloc].line + 1) : 0;
+ return node;
+ }
+
+ TypeAST *makeBasicType(int token)
+ {
+ TypeAST *type = new (_engine->pool()) BasicTypeAST(token, spell[token]);
+ type->lineno = yyloc >= 0 ? (_tokens[yyloc].line + 1) : 0;
+ return type;
+ }
+
+private:
+ Engine *_engine;
+ int _tos;
+ int _index;
+ int yyloc;
+ int yytoken;
+ int yyrecovering;
+ bool _recovered;
+ Token _startToken;
+ std::vector<int> _stateStack;
+ std::vector<int> _locationStack;
+ std::vector<Value> _symStack;
+ std::vector<Token> _tokens;
+};
+
+} // end of namespace GLSL
diff --git a/src/libs/glsl/glslparsertable.cpp b/src/libs/glsl/glslparsertable.cpp
new file mode 100644
index 0000000000..61a805dfeb
--- /dev/null
+++ b/src/libs/glsl/glslparsertable.cpp
@@ -0,0 +1,1296 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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$
+**
+****************************************************************************/
+
+// This file was generated by qlalr - DO NOT EDIT!
+#include "glslparsertable_p.h"
+
+QT_BEGIN_NAMESPACE
+
+const char *const GLSLParserTable::spell [] = {
+ "end of file", "feed GLSL", "feed expression", "+=", "&", "&=", "&&", "attribute", "!", "bool",
+ "break", "bvec2", "bvec3", "bvec4", "^", "case", "centroid", ":", ",", "const",
+ "continue", "-", "--", "default", "discard", "/=", "dmat2", "dmat2x2", "dmat2x3", "dmat2x4",
+ "dmat3", "dmat3x2", "dmat3x3", "dmat3x4", "dmat4", "dmat4x2", "dmat4x3", "dmat4x4", "do", ".",
+ "double", "dvec2", "dvec3", "dvec4", "else", "=", "==", "flat", "float", "for",
+ ">=", "highp", "identifier", "if", "in", "++", "inout", "int", "invariant", "isampler1D",
+ "isampler1DArray", "isampler2D", "isampler2DArray", "isampler2DMS", "isampler2DMSArray", "isampler2DRect", "isampler3D", "isamplerBuffer", "isamplerCube", "isamplerCubeArray",
+ "ivec2", "ivec3", "ivec4", "layout", "<", "<<=", "{", "[", "<<", "(",
+ "<=", "lowp", "mat2", "mat2x2", "mat2x3", "mat2x4", "mat3", "mat3x2", "mat3x3", "mat3x4",
+ "mat4", "mat4x2", "mat4x3", "mat4x4", "mediump", "%=", "*=", "!=", "noperspective", "number constant",
+ "|=", "||", "out", "patch", "%", "plus", "precision", "?", "return", ">",
+ ">>=", "}", "]", ">>", ")", "sample", "sampler1D", "sampler1DArray", "sampler1DArrayShadow", "sampler1DShadow",
+ "sampler2D", "sampler2DArray", "sampler2DArrayShadow", "sampler2DMS", "sampler2DMSArray", "sampler2DRect", "sampler2DRectShadow", "sampler2DShadow", "sampler3D", "samplerBuffer",
+ "samplerCube", "samplerCubeArray", "samplerCubeArrayShadow", "samplerCubeShadow", ";", "/", "smooth", "*", "struct", "subroutine",
+ "-=", "switch", "~", "type_name", "uint", "uniform", "usampler1D", "usampler1DArray", "usampler2D", "usampler2DArray",
+ "usampler2DMS", "usampler2DMSarray", "usampler2DRect", "usampler3D", "usamplerBuffer", "usamplerCube", "usamplerCubeArray", "uvec2", "uvec3", "uvec4",
+ "varying", "vec2", "vec3", "vec4", "|", "void", "while", "^=", "^^", "true",
+ "false", "preprocessor directive", "comment", "error", "reserved word"};
+
+const short GLSLParserTable::lhs [] = {
+ 176, 177, 177, 177, 177, 177, 179, 179, 179, 179,
+ 179, 179, 180, 181, 182, 182, 183, 183, 185, 185,
+ 184, 184, 186, 188, 188, 190, 190, 190, 190, 191,
+ 191, 191, 191, 192, 192, 192, 192, 193, 193, 193,
+ 194, 194, 194, 195, 195, 195, 195, 195, 196, 196,
+ 196, 197, 197, 198, 198, 199, 199, 200, 200, 201,
+ 201, 202, 202, 203, 203, 187, 187, 204, 204, 204,
+ 204, 204, 204, 204, 204, 204, 204, 204, 178, 178,
+ 205, 206, 206, 206, 206, 206, 206, 206, 206, 207,
+ 213, 213, 215, 215, 214, 218, 218, 216, 216, 216,
+ 216, 220, 220, 220, 220, 221, 208, 208, 208, 208,
+ 208, 208, 208, 223, 223, 223, 223, 223, 223, 223,
+ 223, 217, 217, 225, 226, 226, 226, 227, 228, 228,
+ 229, 229, 219, 211, 211, 211, 211, 211, 211, 211,
+ 211, 230, 230, 230, 230, 230, 230, 230, 230, 230,
+ 230, 230, 230, 230, 189, 189, 210, 210, 210, 231,
+ 231, 231, 231, 231, 231, 231, 231, 231, 231, 231,
+ 231, 231, 231, 231, 231, 231, 231, 231, 231, 231,
+ 231, 231, 231, 231, 231, 231, 231, 231, 231, 231,
+ 231, 231, 231, 231, 231, 231, 231, 231, 231, 231,
+ 231, 231, 231, 231, 231, 231, 231, 231, 231, 231,
+ 231, 231, 231, 231, 231, 231, 231, 231, 231, 231,
+ 231, 231, 231, 231, 231, 231, 231, 231, 231, 231,
+ 231, 231, 231, 231, 231, 231, 231, 231, 231, 231,
+ 231, 231, 231, 231, 231, 231, 209, 209, 209, 232,
+ 232, 212, 212, 233, 233, 234, 234, 235, 235, 235,
+ 224, 236, 237, 237, 239, 239, 239, 239, 239, 239,
+ 239, 238, 238, 247, 247, 248, 248, 246, 246, 240,
+ 240, 241, 249, 249, 250, 250, 242, 251, 251, 243,
+ 243, 244, 244, 244, 252, 252, 254, 254, 253, 253,
+ 245, 245, 245, 245, 245, 255, 256, 256, 257, 257,
+ 257, 258, 222, 175, 175, 259};
+
+const short GLSLParserTable::rhs [] = {
+ 1, 1, 1, 1, 1, 3, 1, 4, 1, 3,
+ 2, 2, 1, 1, 1, 3, 2, 2, 2, 1,
+ 2, 3, 2, 1, 1, 1, 2, 2, 2, 1,
+ 1, 1, 1, 1, 3, 3, 3, 1, 3, 3,
+ 1, 3, 3, 1, 3, 3, 3, 3, 1, 3,
+ 3, 1, 3, 1, 3, 1, 3, 1, 3, 1,
+ 3, 1, 3, 1, 5, 1, 3, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 3,
+ 1, 2, 2, 4, 6, 7, 9, 10, 2, 2,
+ 1, 1, 2, 3, 3, 2, 5, 3, 2, 3,
+ 2, 1, 1, 1, 1, 1, 1, 3, 5, 6,
+ 7, 8, 5, 1, 2, 4, 5, 6, 7, 4,
+ 2, 1, 2, 1, 1, 1, 1, 4, 1, 3,
+ 1, 3, 1, 1, 1, 2, 2, 1, 2, 3,
+ 1, 1, 1, 1, 2, 1, 1, 2, 2, 2,
+ 2, 2, 2, 1, 1, 2, 1, 3, 4, 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, 1, 1, 1, 1, 5,
+ 4, 1, 2, 3, 4, 1, 3, 1, 3, 4,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 3, 1, 1, 2, 3, 1, 2, 1,
+ 2, 5, 3, 1, 1, 4, 7, 1, 1, 3,
+ 2, 5, 7, 6, 1, 1, 1, 1, 2, 3,
+ 2, 2, 2, 3, 2, 1, 1, 2, 1, 1,
+ 1, 2, 0, 2, 2, 2};
+
+const short GLSLParserTable::action_default [] = {
+ 0, 0, 0, 0, 32, 165, 172, 173, 174, 31,
+ 0, 193, 196, 197, 198, 194, 199, 200, 201, 195,
+ 202, 203, 204, 162, 169, 170, 171, 4, 161, 247,
+ 1, 0, 163, 218, 222, 219, 223, 240, 243, 234,
+ 220, 237, 221, 224, 175, 176, 177, 0, 249, 181,
+ 184, 185, 186, 182, 187, 188, 189, 183, 190, 191,
+ 192, 248, 2, 30, 205, 212, 214, 209, 206, 213,
+ 215, 239, 242, 232, 233, 210, 207, 236, 208, 216,
+ 217, 211, 0, 33, 3, 246, 164, 225, 229, 226,
+ 230, 241, 244, 235, 227, 238, 228, 231, 178, 179,
+ 180, 166, 167, 168, 160, 41, 54, 79, 66, 52,
+ 56, 315, 9, 15, 20, 0, 0, 14, 0, 58,
+ 60, 64, 62, 38, 26, 0, 7, 49, 44, 245,
+ 24, 155, 157, 34, 0, 5, 28, 27, 0, 0,
+ 6, 80, 0, 0, 0, 143, 0, 142, 126, 146,
+ 141, 0, 127, 147, 0, 0, 125, 154, 144, 138,
+ 0, 135, 134, 252, 0, 0, 0, 148, 149, 145,
+ 0, 131, 129, 0, 0, 132, 0, 128, 130, 150,
+ 151, 152, 153, 137, 0, 139, 140, 136, 250, 253,
+ 0, 258, 256, 0, 0, 259, 81, 0, 34, 260,
+ 0, 255, 257, 0, 254, 0, 251, 0, 0, 40,
+ 0, 0, 0, 37, 36, 35, 39, 0, 53, 0,
+ 0, 50, 0, 0, 0, 0, 48, 0, 0, 42,
+ 43, 45, 47, 46, 51, 0, 55, 160, 21, 18,
+ 0, 17, 22, 23, 0, 57, 0, 59, 0, 0,
+ 63, 0, 61, 0, 0, 65, 12, 0, 11, 0,
+ 10, 16, 13, 0, 8, 156, 0, 158, 0, 159,
+ 72, 76, 70, 68, 74, 71, 69, 78, 75, 73,
+ 77, 0, 67, 29, 141, 0, 311, 310, 307, 306,
+ 114, 0, 309, 313, 92, 0, 0, 107, 314, 0,
+ 122, 121, 0, 0, 84, 308, 115, 0, 0, 95,
+ 261, 120, 116, 0, 0, 118, 117, 0, 119, 90,
+ 133, 103, 105, 104, 102, 93, 0, 313, 99, 101,
+ 106, 96, 0, 0, 97, 0, 98, 100, 106, 313,
+ 94, 0, 82, 312, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 276, 280, 0, 0, 269, 263,
+ 262, 265, 0, 266, 0, 270, 271, 267, 264, 278,
+ 0, 268, 122, 302, 0, 290, 301, 291, 305, 0,
+ 0, 0, 0, 0, 293, 0, 296, 295, 313, 122,
+ 298, 0, 297, 285, 0, 0, 0, 299, 300, 0,
+ 274, 275, 294, 0, 0, 286, 123, 0, 0, 0,
+ 282, 284, 0, 283, 272, 0, 273, 279, 303, 0,
+ 304, 0, 0, 0, 313, 288, 289, 0, 287, 0,
+ 0, 0, 292, 281, 277, 0, 83, 108, 0, 0,
+ 113, 109, 0, 0, 111, 110, 0, 112, 0, 89,
+ 0, 0, 0, 0, 85, 0, 86, 0, 0, 87,
+ 0, 88, 316};
+
+const short GLSLParserTable::goto_default [] = {
+ 3, 135, 126, 362, 124, 263, 112, 117, 113, 116,
+ 115, 114, 107, 118, 130, 133, 134, 123, 105, 128,
+ 127, 109, 106, 110, 119, 120, 122, 121, 108, 281,
+ 197, 360, 364, 296, 125, 131, 299, 205, 291, 293,
+ 294, 325, 290, 328, 327, 326, 329, 324, 297, 311,
+ 160, 159, 161, 173, 172, 162, 132, 129, 163, 203,
+ 192, 361, 369, 359, 368, 363, 367, 371, 358, 365,
+ 366, 370, 402, 400, 410, 390, 427, 388, 394, 391,
+ 298, 289, 288, 292, 0};
+
+const short GLSLParserTable::action_index [] = {
+ 96, 1153, 3162, 24, -175, -175, -175, -175, -175, -175,
+ 1153, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+ -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+ -12, 1153, -175, -175, -175, -175, -175, -175, -175, -175,
+ -175, -175, -175, -175, -175, -175, -175, 1153, -175, -175,
+ -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+ -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+ -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+ -175, -175, 47, -175, -175, -175, -175, -175, -175, -175,
+ -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+ -175, -175, -175, -175, -175, 85, 53, -175, -175, 65,
+ 55, 52, -175, -175, 1320, -51, 66, -175, -52, -158,
+ 154, -11, -157, 18, 94, 488, -175, 118, 31, -175,
+ -175, -175, -46, 183, 1153, -175, -175, -175, 71, 1153,
+ -175, -175, -58, 2490, 2490, -175, 77, -175, -175, -175,
+ 198, -65, -175, -175, 39, 32, -175, -175, -175, 322,
+ 200, 322, -175, -175, 2994, 654, -16, -175, -175, -175,
+ 7, 15, -175, 83, -31, -175, 21, -175, -175, -175,
+ -175, -175, -175, -175, 322, -175, -175, -175, -175, -175,
+ -5, -23, -175, 84, 1988, -175, -175, -63, -175, -175,
+ 4, -175, -175, 86, -175, 2826, -175, 1153, 1153, 28,
+ 1153, 1153, 1153, -175, -175, -175, 13, 1153, 61, 1153,
+ 1153, 93, 1153, 1153, 1153, 1153, 27, 1153, 1153, 64,
+ 73, 5, 17, 22, 101, 1153, 35, -64, -175, -175,
+ 1153, -175, -175, -175, 1153, 37, 1153, -116, 1153, 1153,
+ -115, 1153, 154, 74, 1153, -175, -175, 820, -175, 1153,
+ -39, -175, 19, -71, -175, -175, 1654, -175, -66, -175,
+ -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+ -175, 1153, -175, -175, 210, 78, -175, -175, -175, 3162,
+ 10, -53, -175, 147, 48, 11, 70, -175, -175, 986,
+ -175, -175, 488, -125, -175, -175, 75, 1153, 1487, -175,
+ -175, -175, -41, -110, 1153, -175, -17, 1153, -175, -175,
+ -175, -175, -175, -175, -175, -175, 654, 54, -175, -175,
+ -36, -57, 1153, -89, -175, 654, -175, -175, -33, 128,
+ -175, 4170, -175, -175, -117, 1153, -109, 12, -124, 3666,
+ -74, -67, 4506, 1821, -175, -175, -78, -15, -175, -175,
+ -175, -175, 62, -175, -90, -175, -175, -175, -175, -175,
+ 4338, -175, -27, -175, 58, -175, -175, -175, -175, -121,
+ -37, 1153, 63, -62, -175, 3498, -175, -175, 3330, -14,
+ -175, -131, -175, 16, -79, -19, 654, 1153, 8, 3834,
+ -175, -175, -175, -24, 1153, -175, -175, 1153, 60, 3666,
+ -175, -1, 3666, -175, -175, 4002, -175, -175, -175, 59,
+ -175, 1153, 56, -68, 3666, -175, 3666, -111, -175, 3330,
+ -84, 3834, -175, -175, -175, 3, -175, 26, 1153, 2322,
+ -175, -13, -97, 1153, -175, -32, 1153, -175, -69, -175,
+ 2490, 2658, 30, 2, -175, 2155, -175, -96, -54, -175,
+ -112, -175, -175,
+
+ -85, 68, 99, -85, -85, -85, -85, -85, -85, -85,
+ 0, -85, -85, -85, -85, -85, -85, -85, -85, -85,
+ -85, -85, -85, -85, -85, -85, -85, -85, -85, -85,
+ -85, -4, -85, -85, -85, -85, -85, -85, -85, -85,
+ -85, -85, -85, -85, -85, -85, -85, -2, -85, -85,
+ -85, -85, -85, -85, -85, -85, -85, -85, -85, -85,
+ -85, -85, -85, -85, -85, -85, -85, -85, -85, -85,
+ -85, -85, -85, -85, -85, -85, -85, -85, -85, -85,
+ -85, -85, -85, -85, -85, -85, -85, -85, -85, -85,
+ -85, -85, -85, -85, -85, -85, -85, -85, -85, -85,
+ -85, -85, -85, -85, -85, -85, -85, -85, -85, -85,
+ -85, -85, -85, -85, 22, -85, -85, -85, -85, -85,
+ -85, -85, -85, -85, -85, 3, -85, -85, -85, -85,
+ -85, -85, -85, -85, 6, -85, -85, -85, -85, 21,
+ -85, -85, -85, 60, 131, -85, -85, -85, -85, -85,
+ -85, -85, -85, -85, -85, -85, -85, -85, -85, -35,
+ 37, -18, -85, -85, 86, -11, -85, -85, -85, -85,
+ -85, -85, -85, -85, -85, -85, -45, -85, -85, -85,
+ -85, -85, -85, -85, -51, -85, -85, -85, -85, -85,
+ -49, -85, -85, -85, 34, -85, -85, -85, -85, -85,
+ -48, -85, -85, -85, -85, 114, -85, 39, 36, -85,
+ -8, -1, -9, -85, -85, -85, -85, 24, -85, 26,
+ 35, -85, 71, 78, 84, 72, -85, 45, 49, -85,
+ -85, -85, -85, -85, -85, 79, -85, -85, -85, -85,
+ -10, -85, -85, -85, 83, -85, 58, -85, 50, 33,
+ -85, 44, -85, -85, 16, -85, -85, 11, -85, 19,
+ -85, -85, -85, -85, -85, -85, 106, -85, -85, -85,
+ -85, -85, -85, -85, -85, -85, -85, -85, -85, -85,
+ -85, 13, -85, -85, -85, -7, -85, -85, -85, 210,
+ -85, -85, -85, -85, -85, -38, -85, -85, -85, 17,
+ -85, -85, -3, -85, -85, -85, -85, 4, 87, -85,
+ -85, -85, -85, -85, 30, -85, -85, 31, -85, -85,
+ -85, -85, -85, -85, -85, -85, 15, -27, -85, -85,
+ -85, -85, 109, -85, -85, 115, -85, -85, -85, -17,
+ -85, 12, -85, -85, -85, 20, -85, -85, -85, 64,
+ -85, -85, 139, 14, -85, -85, -85, -85, -85, -85,
+ -85, -85, -85, -85, -85, -85, -85, -85, -85, -85,
+ 52, -85, -85, -85, -85, -85, -85, -85, -85, -85,
+ -85, 27, -85, -85, -85, 90, -85, -85, 135, -85,
+ -85, -85, -85, -85, -85, -85, -14, 2, -85, 56,
+ -85, -85, -85, -85, 46, -85, -85, 5, -85, 54,
+ -85, -85, 47, -85, -85, 61, -85, -85, -85, -85,
+ -85, 10, -85, -85, 105, -85, 43, -85, -85, 156,
+ -85, 93, -85, -85, -85, -85, -85, -85, 32, 118,
+ -85, -85, -85, 40, -85, -85, 28, -85, -85, -85,
+ 104, 96, -85, -85, -85, 97, -85, -85, -85, -85,
+ -85, -85, -85};
+
+const short GLSLParserTable::action_info [] = {
+ 428, 421, 316, 397, 314, 385, 244, 450, 424, 304,
+ 378, 251, 407, 446, 170, 445, 331, 373, 144, 331,
+ 332, 404, 461, 334, 462, 376, 139, 243, 317, 377,
+ 431, 266, 443, 403, 139, 399, 191, 139, 459, 217,
+ -25, 264, 381, 412, 342, 380, 269, 191, 244, 199,
+ -19, 235, -24, 251, 194, 437, 191, 217, 460, 171,
+ 174, 319, 306, 239, 429, -24, 339, -25, 175, 235,
+ 139, 438, 384, 171, 139, 375, 139, 139, 139, 455,
+ 139, 139, 453, 227, 240, 207, 181, 341, 435, 139,
+ 248, 254, 139, 179, 207, 227, 249, 2, 1, 142,
+ 227, 176, 200, 439, 200, 227, 207, 219, 321, 227,
+ 322, 219, 0, 0, 0, 0, 256, 210, 228, 0,
+ 307, 0, 210, 143, 0, 0, 0, 0, 0, 29,
+ 228, 167, 210, 257, 182, 228, 456, 0, 0, 0,
+ 228, 180, 0, 222, 228, 342, 0, 320, 211, 258,
+ 212, 222, 308, 211, 309, 212, 323, 0, 220, 48,
+ 246, 0, 220, 211, 454, 212, 320, 223, 222, 208,
+ 423, 259, 61, 224, 409, 223, 0, 383, 208, 168,
+ 241, 224, 321, 0, 322, 140, 270, 0, 271, 0,
+ 208, 0, 223, 420, 0, 0, 433, 177, 224, 0,
+ 0, 321, 225, 322, 436, -124, 0, 145, 272, 0,
+ 225, 0, 0, 0, -124, 0, 146, -124, 201, 147,
+ 204, 0, 0, 0, 0, 0, -124, 225, 273, -124,
+ 323, 0, 0, 0, 0, 0, 0, 169, 0, 0,
+ 0, 0, 0, 0, 0, -124, 0, 148, 0, 323,
+ 0, 0, -124, 0, 149, 0, 0, -124, 274, 0,
+ 0, -91, 301, 0, -124, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 275, 276,
+ 0, 0, 0, 277, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 278, 0, 0, -124, 0, 152, 0,
+ -124, -124, 153, 154, 0, 0, 0, 0, -124, 0,
+ 0, 0, -124, -124, 0, 155, 0, 0, 0, 0,
+ 0, 0, 0, 279, 0, -124, 0, 0, 0, 145,
+ 0, 0, 0, 0, -124, 0, 156, 0, 146, 0,
+ 0, 147, 0, -124, 0, 157, -124, 0, 0, 0,
+ 280, 0, 0, 0, 0, -124, 0, 0, -124, 0,
+ 158, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ -124, 0, 0, 0, 0, 0, 149, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 153, 154, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 155, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 157, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 158, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 5, 0, 6,
+ 7, 8, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 0, 0, 23, 24,
+ 25, 26, 0, 0, 0, 0, 28, 0, 0, 0,
+ 0, 0, 0, 0, 0, 32, 0, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
+ 59, 60, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 0, 0, 0, 0, 82, 0, 0, 0,
+ 0, 85, 86, 0, 87, 88, 89, 90, 91, 92,
+ 93, 94, 95, 96, 97, 98, 99, 100, 0, 101,
+ 102, 103, 0, 104, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 5, 0, 6, 7, 8, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 0, 0, 23, 24, 25, 26, 0, 0,
+ 0, 0, 28, 0, 0, 29, 0, 0, 0, 0,
+ 0, 32, 0, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 0, 0, 0,
+ 0, 0, 0, 0, 0, 48, 49, 50, 51, 52,
+ 53, 54, 55, 56, 57, 58, 59, 60, 61, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, 78, 79, 80, 81, 0, 0,
+ 0, 0, 82, 0, 0, 0, 0, 85, 86, 0,
+ 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
+ 97, 98, 99, 100, 0, 101, 102, 103, 0, 104,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
+ 0, 6, 7, 8, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 0, 0,
+ 23, 24, 25, 26, 0, 0, 0, 0, 28, 0,
+ 0, 29, 260, 0, 0, 0, 0, 32, 0, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 0, 0, 0, 0, 0, 0, 0,
+ 0, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ 57, 58, 59, 60, 61, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 64, 65, 66, 67,
+ 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+ 78, 79, 80, 81, 0, 0, 0, 0, 82, 0,
+ 0, 0, 0, 85, 86, 0, 87, 88, 89, 90,
+ 91, 92, 93, 94, 95, 96, 97, 98, 99, 100,
+ 0, 101, 102, 103, 0, 104, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 5, 0, 6, 7, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 0, 0, 23, 24, 25, 26,
+ 0, 0, 0, 0, 28, 0, 0, 29, 448, 0,
+ 0, 0, 0, 32, 0, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 0,
+ 0, 0, 0, 0, 0, 0, 0, 48, 49, 50,
+ 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+ 61, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+ 449, 0, 0, 0, 82, 0, 0, 0, 0, 85,
+ 86, 0, 87, 88, 89, 90, 91, 92, 93, 94,
+ 95, 96, 97, 98, 99, 100, 0, 101, 102, 103,
+ 0, 104, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 4, 5, 0, 6, 7, 8, 0, 0, 0,
+ 0, 0, 0, 0, 9, 10, 0, 0, 0, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 0, 0, 23, 24, 25, 26, 0, 0, 0,
+ 0, 28, 0, 0, 29, 30, 0, 0, 31, 0,
+ 32, 0, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 0, 0, 0, 0,
+ 0, 0, 47, 0, 48, 49, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 0, 0,
+ 0, 0, 62, 0, 0, 0, 0, 0, 63, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 64,
+ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+ 75, 76, 77, 78, 79, 80, 81, 0, 0, 0,
+ 0, 82, 0, 0, 0, 83, 85, 86, 0, 87,
+ 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
+ 98, 99, 100, 0, 101, 102, 103, 0, 104, 0,
+ 0, 0, 84, 27, 0, 0, 0, 0, 4, 5,
+ 0, 6, 7, 8, 0, 0, 0, 0, 0, 0,
+ 0, 9, 10, 0, 0, 0, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 0, 0,
+ 23, 24, 25, 26, 0, 0, 0, 0, 28, 0,
+ 0, 29, 30, 0, 0, 31, 0, 32, 0, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 0, 0, 0, 0, 0, 0, 47,
+ 0, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ 57, 58, 59, 60, 61, 0, 0, 0, 0, 62,
+ 0, 0, 0, 0, 0, 63, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 64, 65, 66, 67,
+ 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+ 78, 79, 80, 81, 0, 0, 0, 0, 82, 0,
+ 0, 0, 83, 85, 86, 0, 87, 88, 89, 90,
+ 91, 92, 93, 94, 95, 96, 97, 98, 99, 100,
+ 0, 101, 102, 103, 0, 237, 0, 0, 0, 84,
+ 27, 0, 0, 0, 0, 4, 5, 0, 6, 7,
+ 8, 0, 0, 0, 0, 0, 0, 0, 9, 10,
+ 0, 0, 0, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 0, 0, 23, 24, 25,
+ 26, 0, 0, 0, 0, 28, 0, 0, 29, 30,
+ 0, 0, 31, 0, 32, 0, 33, 34, 35, 36,
+ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
+ 0, 0, 0, 0, 0, 0, 47, 0, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 0, 0, 0, 0, 62, 0, 0, 0,
+ 0, 0, 63, 0, 0, 0, 0, 0, 0, 312,
+ 0, 0, 0, 64, 65, 66, 67, 68, 69, 70,
+ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+ 81, 0, 0, 0, 0, 82, 0, 0, 0, 83,
+ 85, 86, 0, 87, 88, 89, 90, 91, 92, 93,
+ 94, 95, 96, 97, 98, 99, 100, 0, 101, 102,
+ 103, 0, 104, 0, 0, 0, 84, 27, 0, 0,
+ 0, 0, 4, 5, 0, 6, 7, 8, 0, 0,
+ 0, 0, 0, 0, 0, 9, 10, 0, 0, 0,
+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 0, 0, 23, 24, 25, 26, 0, 0,
+ 0, 0, 28, 0, 0, 29, 30, 0, 0, 31,
+ 0, 32, 0, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 0, 0, 0,
+ 0, 0, 0, 47, 0, 48, 49, 50, 51, 52,
+ 53, 54, 55, 56, 57, 58, 59, 60, 61, 0,
+ 0, 0, 0, 62, 0, 0, 0, 0, 0, 63,
+ 0, 0, 0, 0, 0, 0, 267, 0, 0, 0,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, 78, 79, 80, 81, 0, 0,
+ 0, 0, 82, 0, 0, 0, 83, 85, 86, 0,
+ 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
+ 97, 98, 99, 100, 0, 101, 102, 103, 0, 104,
+ 0, 0, 0, 84, 27, 0, 0, 0, 0, 4,
+ 5, 0, 6, 7, 8, 0, 0, 0, 0, 0,
+ 0, 0, 9, 10, 0, 0, 0, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 0,
+ 0, 23, 24, 25, 26, 0, 0, 0, 0, 28,
+ 0, 0, 29, 30, 0, 0, 31, 0, 32, 0,
+ 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
+ 43, 44, 45, 46, 0, 0, 0, 0, 0, 0,
+ 47, 0, 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 0, 0, 0, 0,
+ 62, 0, 0, 0, 0, 0, 63, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 64, 65, 66,
+ 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
+ 77, 78, 79, 80, 81, 418, 0, 0, 0, 82,
+ 0, 0, 0, 83, 85, 86, 0, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+ 100, 0, 101, 102, 103, 0, 104, 0, 0, 0,
+ 84, 27, 0, 0, 0, 0, 4, 5, 0, 6,
+ 7, 8, 0, 0, 0, 0, 0, 0, 0, 9,
+ 10, 0, 0, 0, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 0, 0, 23, 24,
+ 25, 26, 0, 0, 0, 0, 28, 0, 0, 29,
+ 30, 0, 0, 31, 0, 32, 0, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 0, 0, 0, 0, 0, 0, 47, 0, 48,
+ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
+ 59, 60, 61, 0, 0, 0, 0, 62, 0, 0,
+ 0, 0, 0, 63, 0, 0, 0, 0, 0, 0,
+ 195, 0, 0, 0, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 0, 0, 0, 0, 82, 0, 0, 0,
+ 83, 85, 86, 0, 87, 88, 89, 90, 91, 92,
+ 93, 94, 95, 96, 97, 98, 99, 100, 0, 101,
+ 102, 103, 0, 104, 0, 0, 0, 84, 27, 0,
+ 0, 0, 0, 4, 5, 0, 6, 7, 8, 0,
+ 0, 0, 0, 0, 0, 0, 9, 10, 0, 0,
+ 0, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 0, 0, 23, 24, 25, 26, 0,
+ 0, 0, 0, 28, 0, 0, 29, 30, 0, 0,
+ 31, 0, 32, 0, 33, 34, 35, 36, 37, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46, 0, 0,
+ 0, 0, 0, 0, 47, 0, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 0, 0, 0, 0, 62, 0, 0, 0, 0, 0,
+ 63, 0, 0, 0, 0, 0, 0, 457, 0, 0,
+ 0, 64, 65, 66, 67, 68, 69, 70, 71, 72,
+ 73, 74, 75, 76, 77, 78, 79, 80, 81, 0,
+ 0, 0, 0, 82, 0, 0, 0, 83, 85, 86,
+ 0, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 0, 101, 102, 103, 0,
+ 104, 0, 0, 0, 84, 27, 0, 0, 0, 0,
+ 4, 5, 0, 6, 7, 8, 0, 0, 0, 0,
+ 0, 0, 0, 9, 10, 0, 0, 0, 11, 12,
+ 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 0, 0, 23, 24, 25, 26, 0, 0, 0, 0,
+ 28, 0, 0, 29, 30, 0, 0, 31, 0, 32,
+ 0, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 0, 0, 0, 0, 0,
+ 0, 47, 0, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, 0, 0, 0,
+ 0, 62, 0, 0, 0, 0, 0, 63, 0, 0,
+ 0, 0, 0, 0, 441, 0, 0, 0, 64, 65,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
+ 76, 77, 78, 79, 80, 81, 0, 0, 0, 0,
+ 82, 0, 0, 0, 83, 85, 86, 0, 87, 88,
+ 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
+ 99, 100, 0, 101, 102, 103, 0, 104, 0, 0,
+ 0, 84, 27, 0, 0, 0, 0, 145, 0, 5,
+ 0, 6, 7, 8, 0, 0, 146, 0, 0, 147,
+ 0, 0, 0, 0, 0, 0, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 0, 0,
+ 23, 24, 25, 26, 0, 0, 0, 148, 28, 0,
+ 0, 29, 0, 0, 149, 0, 0, 32, 150, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 151, 0, 0, 0, 0, 0, 0,
+ 0, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ 57, 58, 59, 60, 61, 0, 0, 0, 152, 0,
+ 0, 0, 153, 154, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 155, 64, 65, 66, 67,
+ 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+ 78, 79, 80, 81, 0, 0, 156, 0, 82, 0,
+ 0, 0, 0, 85, 86, 157, 87, 88, 89, 90,
+ 91, 92, 93, 94, 95, 96, 97, 98, 99, 100,
+ 158, 101, 102, 103, 0, 104, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 145, 0, 5, 0, 6,
+ 7, 8, 0, 0, 146, 0, 0, 147, 0, 0,
+ 0, 0, 0, 0, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 0, 0, 23, 24,
+ 25, 26, 0, 0, 0, 148, 28, 0, 0, 29,
+ 0, 0, 149, 0, 0, 32, 150, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 151, 0, 0, 0, 0, 0, 0, 0, 48,
+ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
+ 59, 60, 61, 0, 0, 0, 152, 0, 0, 0,
+ 153, 154, 0, 0, 0, 0, 0, 0, 0, 452,
+ 0, 0, 0, 155, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 0, 0, 156, 0, 82, 0, 0, 0,
+ 0, 85, 86, 157, 87, 88, 89, 90, 91, 92,
+ 93, 94, 95, 96, 97, 98, 99, 100, 158, 101,
+ 102, 103, 0, 104, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 145, 0, 5, 0, 6, 7, 8,
+ 0, 0, 146, 0, 0, 147, 0, 0, 0, 0,
+ 0, 0, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 0, 0, 23, 24, 25, 26,
+ 0, 0, 0, 148, 28, 0, 0, 29, 0, 0,
+ 149, 0, 0, 32, 150, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 151,
+ 0, 0, 0, 0, 0, 0, 0, 48, 49, 50,
+ 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+ 61, 0, 0, 0, 152, 0, 0, 0, 153, 154,
+ 0, 0, 0, 0, 0, 0, 0, 206, 0, 0,
+ 0, 155, 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+ 0, 0, 156, 0, 82, 0, 0, 0, 0, 85,
+ 86, 157, 87, 88, 89, 90, 91, 92, 93, 94,
+ 95, 96, 97, 98, 99, 100, 158, 101, 102, 103,
+ 0, 104, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 145, 0, 5, 0, 6, 7, 8, 0, 0,
+ 146, 0, 0, 147, 0, 0, 0, 0, 0, 0,
+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 0, 0, 23, 24, 25, 26, 0, 0,
+ 0, 148, 28, 0, 0, 29, 0, 0, 149, 0,
+ 0, 32, 150, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 151, 0, 0,
+ 0, 0, 0, 0, 0, 48, 49, 50, 51, 52,
+ 53, 54, 55, 56, 57, 58, 59, 60, 61, 0,
+ 0, 0, 152, 0, 0, 0, 153, 154, 0, 0,
+ 0, 0, 0, 0, 0, 188, 0, 0, 0, 155,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, 78, 79, 80, 81, 0, 0,
+ 156, 0, 82, 0, 0, 0, 0, 85, 86, 157,
+ 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
+ 97, 98, 99, 100, 158, 101, 102, 103, 0, 104,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 145,
+ 0, 5, 0, 6, 7, 8, 0, 0, 146, 0,
+ 0, 147, 0, 0, 0, 0, 0, 0, 11, 12,
+ 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 0, 0, 23, 24, 25, 26, 0, 0, 0, 148,
+ 28, 0, 0, 29, 0, 0, 149, 0, 0, 32,
+ 284, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 151, 0, 0, 0, 0,
+ 0, 0, 0, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, 0, 0, 0,
+ 152, 0, 0, 0, 153, 154, 0, 0, 285, 0,
+ 0, 0, 0, 0, 0, 0, 0, 155, 64, 65,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
+ 76, 77, 78, 79, 80, 81, 286, 0, 156, 0,
+ 82, 0, 0, 0, 0, 85, 86, 157, 87, 88,
+ 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
+ 99, 100, 158, 101, 102, 103, 0, 104, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 145, 4, 5,
+ 0, 6, 7, 8, 0, 0, 146, 0, 0, 147,
+ 0, 9, 10, 0, 0, 0, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 0, 0,
+ 23, 24, 25, 26, 0, 0, 0, 148, 28, 0,
+ 0, 29, 30, 0, 149, 31, 0, 32, 150, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 151, 0, 0, 0, 0, 0, 47,
+ 0, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ 57, 58, 59, 60, 61, 0, 0, 0, 152, 62,
+ 0, 0, 153, 154, 0, 63, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 155, 64, 65, 66, 67,
+ 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+ 78, 79, 80, 81, 0, 0, 156, 0, 82, 0,
+ 0, 0, 83, 85, 86, 157, 87, 88, 89, 90,
+ 91, 92, 93, 94, 95, 96, 97, 98, 99, 100,
+ 158, 101, 102, 103, 0, 104, 0, 0, 0, 84,
+ 27, 0, 0, 0, 0, 145, 4, 5, 0, 6,
+ 7, 8, 0, 0, 146, 0, 0, 147, 0, 9,
+ 10, 0, 0, 0, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 0, 0, 23, 24,
+ 25, 26, 0, 0, 0, 148, 28, 0, 0, 29,
+ 30, 0, 149, 31, 0, 32, 284, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 151, 0, 0, 0, 0, 0, 47, 0, 48,
+ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
+ 59, 60, 61, 0, 0, 0, 152, 62, 0, 0,
+ 153, 154, 0, 63, 285, 0, 0, 0, 0, 0,
+ 0, 0, 0, 155, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 355, 0, 156, 0, 82, 0, 0, 0,
+ 83, 85, 86, 157, 87, 88, 89, 90, 91, 92,
+ 93, 94, 95, 96, 97, 98, 99, 100, 158, 101,
+ 102, 103, 0, 104, 0, 0, 0, 84, 27, 0,
+ 0, 0, 0, 145, 4, 5, 344, 6, 7, 8,
+ 0, 345, 146, 0, 0, 147, 346, 9, 10, 347,
+ 348, 0, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 349, 0, 23, 24, 25, 26,
+ 0, 0, 0, 148, 28, 350, 0, 29, 30, 351,
+ 149, 31, 0, 32, 284, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 151,
+ 0, 0, 352, 0, 0, 47, 0, 48, 49, 50,
+ 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+ 61, 0, 0, 0, 152, 62, 0, 0, 153, 154,
+ 0, 63, 285, 0, 353, 0, 0, 0, 0, 0,
+ 0, 155, 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+ 355, 0, 156, 0, 82, 0, 0, 356, 83, 85,
+ 86, 157, 87, 88, 89, 90, 91, 92, 93, 94,
+ 95, 96, 97, 98, 99, 100, 158, 101, 102, 103,
+ 0, 104, 357, 0, 0, 84, 27, 0, 0, 0,
+ 0, 145, 4, 5, 344, 6, 7, 8, 0, 345,
+ 146, 0, 0, 147, 346, 9, 10, 347, 348, 0,
+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 349, 0, 23, 24, 25, 26, 0, 0,
+ 0, 148, 28, 350, 0, 29, 30, 351, 149, 31,
+ 0, 32, 284, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 151, 0, 0,
+ 341, 0, 0, 47, 0, 48, 49, 50, 51, 52,
+ 53, 54, 55, 56, 57, 58, 59, 60, 61, 0,
+ 0, 0, 152, 62, 0, 0, 153, 154, 0, 63,
+ 285, 0, 353, 0, 0, 0, 0, 0, 0, 155,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, 78, 79, 80, 81, 355, 0,
+ 156, 0, 82, 0, 0, 356, 83, 85, 86, 157,
+ 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
+ 97, 98, 99, 100, 158, 101, 102, 103, 0, 104,
+ 357, 0, 0, 84, 27, 0, 0, 0, 0, 145,
+ 4, 5, 344, 6, 7, 8, 0, 345, 146, 0,
+ 0, 147, 346, 9, 10, 347, 348, 0, 11, 12,
+ 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 349, 0, 23, 24, 25, 26, 0, 0, 0, 148,
+ 28, 350, 0, 29, 30, 351, 149, 31, 0, 32,
+ 284, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 151, 0, 0, 352, 0,
+ 0, 47, 0, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, 0, 0, 0,
+ 152, 62, 0, 0, 153, 154, 0, 63, 285, 0,
+ 353, 0, 0, 416, 0, 0, 0, 155, 64, 65,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
+ 76, 77, 78, 79, 80, 81, 355, 0, 156, 0,
+ 82, 0, 0, 356, 83, 85, 86, 157, 87, 88,
+ 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
+ 99, 100, 158, 101, 102, 103, 0, 104, 357, 0,
+ 0, 84, 27, 0, 0, 0, 0, 145, 4, 5,
+ 344, 6, 7, 8, 0, 345, 146, 0, 0, 147,
+ 346, 9, 10, 347, 348, 0, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 349, 0,
+ 23, 24, 25, 26, 0, 0, 0, 148, 28, 350,
+ 0, 29, 30, 351, 149, 31, 0, 32, 284, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 151, 0, 0, 352, 0, 0, 47,
+ 0, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ 57, 58, 59, 60, 61, 0, 0, 0, 152, 62,
+ 0, 0, 153, 154, 0, 63, 285, 0, 353, 0,
+ 0, 354, 0, 0, 0, 155, 64, 65, 66, 67,
+ 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+ 78, 79, 80, 81, 355, 0, 156, 0, 82, 0,
+ 0, 356, 83, 85, 86, 157, 87, 88, 89, 90,
+ 91, 92, 93, 94, 95, 96, 97, 98, 99, 100,
+ 158, 101, 102, 103, 0, 104, 357, 0, 0, 84,
+ 27, 0, 0, 0, 0, 145, 4, 5, 344, 6,
+ 7, 8, 0, 345, 146, 0, 0, 147, 346, 9,
+ 10, 347, 348, 0, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 349, 0, 23, 24,
+ 25, 26, 0, 0, 0, 148, 28, 350, 0, 29,
+ 30, 351, 149, 31, 0, 32, 284, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 151, 0, 0, 352, 0, 0, 47, 0, 48,
+ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
+ 59, 60, 61, 0, 0, 0, 152, 62, 0, 0,
+ 153, 154, 0, 63, 285, 0, 353, 0, 0, 434,
+ 0, 0, 0, 155, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 355, 0, 156, 0, 82, 0, 0, 356,
+ 83, 85, 86, 157, 87, 88, 89, 90, 91, 92,
+ 93, 94, 95, 96, 97, 98, 99, 100, 158, 101,
+ 102, 103, 0, 104, 357, 0, 0, 84, 27, 0,
+ 0, 0, 0, 145, 4, 5, 344, 6, 7, 8,
+ 0, 345, 146, 0, 0, 147, 346, 9, 10, 347,
+ 348, 0, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 349, 0, 23, 24, 25, 26,
+ 0, 0, 0, 148, 28, 350, 0, 29, 30, 351,
+ 149, 31, 0, 32, 284, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 151,
+ 0, 0, 352, 0, 0, 47, 0, 48, 49, 50,
+ 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+ 61, 0, 0, 0, 152, 62, 0, 0, 153, 154,
+ 0, 63, 285, 0, 353, 0, 0, 414, 0, 0,
+ 0, 155, 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+ 355, 0, 156, 0, 82, 0, 0, 356, 83, 85,
+ 86, 157, 87, 88, 89, 90, 91, 92, 93, 94,
+ 95, 96, 97, 98, 99, 100, 158, 101, 102, 103,
+ 0, 104, 357, 0, 0, 84, 27, 0, 0, 0,
+ 0,
+
+ 406, 138, 242, 190, 186, 398, 215, 213, 408, 178,
+ 193, 137, 202, 422, 214, 136, 310, 419, 335, 261,
+ 183, 283, 262, 374, 340, 282, 372, 302, 255, 330,
+ 382, 406, 303, 141, 238, 343, 253, 187, 265, 198,
+ 310, 198, 310, 310, 310, 218, 221, 0, 0, 198,
+ 198, 198, 310, 216, 198, 234, 209, 372, 310, 198,
+ 198, 372, 196, 229, 198, 198, 372, 230, 372, 252,
+ 372, 111, 0, 198, 166, 372, 250, 447, 372, 315,
+ 318, 440, 247, 0, 0, 0, 198, 198, 184, 444,
+ 226, 233, 185, 198, 198, 405, 165, 231, 198, 198,
+ 166, 236, 198, 232, 389, 417, 245, 372, 0, 413,
+ 166, 0, 198, 300, 417, 196, 411, 313, 166, 372,
+ 401, 198, 165, 417, 198, 196, 379, 458, 166, 338,
+ 287, 295, 165, 198, 196, 0, 268, 196, 393, 333,
+ 165, 451, 0, 0, 189, 166, 196, 0, 442, 389,
+ 165, 386, 425, 372, 189, 387, 0, 401, 336, 393,
+ 0, 337, 0, 0, 0, 432, 0, 165, 164, 0,
+ 389, 396, 189, 0, 0, 0, 426, 395, 0, 0,
+ 0, 0, 392, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 396, 0, 0, 0, 0, 0, 395, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 415, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 300, 0, 0, 0, 0, 0,
+ 0, 430, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 287, 295, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 305, 0, 0};
+
+const short GLSLParserTable::action_check [] = {
+ 111, 79, 112, 134, 45, 79, 164, 76, 76, 134,
+ 134, 168, 79, 45, 79, 112, 52, 134, 76, 52,
+ 77, 45, 134, 112, 0, 134, 18, 79, 45, 17,
+ 114, 77, 45, 52, 18, 114, 52, 18, 134, 4,
+ 79, 112, 79, 44, 134, 166, 112, 52, 164, 112,
+ 114, 14, 79, 168, 77, 52, 52, 4, 112, 52,
+ 45, 114, 52, 114, 79, 79, 18, 79, 99, 14,
+ 18, 45, 134, 52, 18, 17, 18, 18, 18, 77,
+ 18, 18, 52, 78, 18, 21, 54, 76, 18, 18,
+ 101, 17, 18, 54, 21, 78, 107, 1, 2, 52,
+ 78, 18, 18, 77, 18, 78, 21, 46, 54, 78,
+ 56, 46, -1, -1, -1, -1, 22, 104, 113, -1,
+ 45, -1, 104, 76, -1, -1, -1, -1, -1, 51,
+ 113, 54, 104, 39, 102, 113, 134, -1, -1, -1,
+ 113, 102, -1, 50, 113, 134, -1, 19, 135, 55,
+ 137, 50, 77, 135, 79, 137, 102, -1, 97, 81,
+ 6, -1, 97, 135, 134, 137, 19, 74, 50, 105,
+ 114, 77, 94, 80, 114, 74, -1, 114, 105, 102,
+ 114, 80, 54, -1, 56, 114, 3, -1, 5, -1,
+ 105, -1, 74, 134, -1, -1, 134, 114, 80, -1,
+ -1, 54, 109, 56, 134, 7, -1, 7, 25, -1,
+ 109, -1, -1, -1, 16, -1, 16, 7, 134, 19,
+ 134, -1, -1, -1, -1, -1, 16, 109, 45, 19,
+ 102, -1, -1, -1, -1, -1, -1, 160, -1, -1,
+ -1, -1, -1, -1, -1, 47, -1, 47, -1, 102,
+ -1, -1, 54, -1, 54, -1, -1, 47, 75, -1,
+ -1, 114, 52, -1, 54, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 95, 96,
+ -1, -1, -1, 100, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 110, -1, -1, 98, -1, 98, -1,
+ 102, 103, 102, 103, -1, -1, -1, -1, 98, -1,
+ -1, -1, 102, 103, -1, 115, -1, -1, -1, -1,
+ -1, -1, -1, 140, -1, 115, -1, -1, -1, 7,
+ -1, -1, -1, -1, 136, -1, 136, -1, 16, -1,
+ -1, 19, -1, 145, -1, 145, 136, -1, -1, -1,
+ 167, -1, -1, -1, -1, 145, -1, -1, 160, -1,
+ 160, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 160, -1, -1, -1, -1, -1, 54, -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, 102, 103, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 115, -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, 145, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 160, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 9, -1, 11,
+ 12, 13, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, -1, -1, 40, 41,
+ 42, 43, -1, -1, -1, -1, 48, -1, -1, -1,
+ -1, -1, -1, -1, -1, 57, -1, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
+ 92, 93, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 116, 117, 118, 119, 120, 121,
+ 122, 123, 124, 125, 126, 127, 128, 129, 130, 131,
+ 132, 133, -1, -1, -1, -1, 138, -1, -1, -1,
+ -1, 143, 144, -1, 146, 147, 148, 149, 150, 151,
+ 152, 153, 154, 155, 156, 157, 158, 159, -1, 161,
+ 162, 163, -1, 165, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 9, -1, 11, 12, 13, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, -1, -1, 40, 41, 42, 43, -1, -1,
+ -1, -1, 48, -1, -1, 51, -1, -1, -1, -1,
+ -1, 57, -1, 59, 60, 61, 62, 63, 64, 65,
+ 66, 67, 68, 69, 70, 71, 72, -1, -1, -1,
+ -1, -1, -1, -1, -1, 81, 82, 83, 84, 85,
+ 86, 87, 88, 89, 90, 91, 92, 93, 94, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 116, 117, 118, 119, 120, 121, 122, 123, 124, 125,
+ 126, 127, 128, 129, 130, 131, 132, 133, -1, -1,
+ -1, -1, 138, -1, -1, -1, -1, 143, 144, -1,
+ 146, 147, 148, 149, 150, 151, 152, 153, 154, 155,
+ 156, 157, 158, 159, -1, 161, 162, 163, -1, 165,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 9,
+ -1, 11, 12, 13, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, -1, -1,
+ 40, 41, 42, 43, -1, -1, -1, -1, 48, -1,
+ -1, 51, 52, -1, -1, -1, -1, 57, -1, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, -1, -1, -1, -1, -1, -1, -1,
+ -1, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
+ 130, 131, 132, 133, -1, -1, -1, -1, 138, -1,
+ -1, -1, -1, 143, 144, -1, 146, 147, 148, 149,
+ 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
+ -1, 161, 162, 163, -1, 165, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 9, -1, 11, 12, 13,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, -1, -1, 40, 41, 42, 43,
+ -1, -1, -1, -1, 48, -1, -1, 51, 52, -1,
+ -1, -1, -1, 57, -1, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, -1,
+ -1, -1, -1, -1, -1, -1, -1, 81, 82, 83,
+ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ 94, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 116, 117, 118, 119, 120, 121, 122, 123,
+ 124, 125, 126, 127, 128, 129, 130, 131, 132, 133,
+ 134, -1, -1, -1, 138, -1, -1, -1, -1, 143,
+ 144, -1, 146, 147, 148, 149, 150, 151, 152, 153,
+ 154, 155, 156, 157, 158, 159, -1, 161, 162, 163,
+ -1, 165, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 8, 9, -1, 11, 12, 13, -1, -1, -1,
+ -1, -1, -1, -1, 21, 22, -1, -1, -1, 26,
+ 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
+ 37, -1, -1, 40, 41, 42, 43, -1, -1, -1,
+ -1, 48, -1, -1, 51, 52, -1, -1, 55, -1,
+ 57, -1, 59, 60, 61, 62, 63, 64, 65, 66,
+ 67, 68, 69, 70, 71, 72, -1, -1, -1, -1,
+ -1, -1, 79, -1, 81, 82, 83, 84, 85, 86,
+ 87, 88, 89, 90, 91, 92, 93, 94, -1, -1,
+ -1, -1, 99, -1, -1, -1, -1, -1, 105, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 116,
+ 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
+ 127, 128, 129, 130, 131, 132, 133, -1, -1, -1,
+ -1, 138, -1, -1, -1, 142, 143, 144, -1, 146,
+ 147, 148, 149, 150, 151, 152, 153, 154, 155, 156,
+ 157, 158, 159, -1, 161, 162, 163, -1, 165, -1,
+ -1, -1, 169, 170, -1, -1, -1, -1, 8, 9,
+ -1, 11, 12, 13, -1, -1, -1, -1, -1, -1,
+ -1, 21, 22, -1, -1, -1, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, -1, -1,
+ 40, 41, 42, 43, -1, -1, -1, -1, 48, -1,
+ -1, 51, 52, -1, -1, 55, -1, 57, -1, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, -1, -1, -1, -1, -1, -1, 79,
+ -1, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, -1, -1, -1, -1, 99,
+ -1, -1, -1, -1, -1, 105, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
+ 130, 131, 132, 133, -1, -1, -1, -1, 138, -1,
+ -1, -1, 142, 143, 144, -1, 146, 147, 148, 149,
+ 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
+ -1, 161, 162, 163, -1, 165, -1, -1, -1, 169,
+ 170, -1, -1, -1, -1, 8, 9, -1, 11, 12,
+ 13, -1, -1, -1, -1, -1, -1, -1, 21, 22,
+ -1, -1, -1, 26, 27, 28, 29, 30, 31, 32,
+ 33, 34, 35, 36, 37, -1, -1, 40, 41, 42,
+ 43, -1, -1, -1, -1, 48, -1, -1, 51, 52,
+ -1, -1, 55, -1, 57, -1, 59, 60, 61, 62,
+ 63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
+ -1, -1, -1, -1, -1, -1, 79, -1, 81, 82,
+ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
+ 93, 94, -1, -1, -1, -1, 99, -1, -1, -1,
+ -1, -1, 105, -1, -1, -1, -1, -1, -1, 112,
+ -1, -1, -1, 116, 117, 118, 119, 120, 121, 122,
+ 123, 124, 125, 126, 127, 128, 129, 130, 131, 132,
+ 133, -1, -1, -1, -1, 138, -1, -1, -1, 142,
+ 143, 144, -1, 146, 147, 148, 149, 150, 151, 152,
+ 153, 154, 155, 156, 157, 158, 159, -1, 161, 162,
+ 163, -1, 165, -1, -1, -1, 169, 170, -1, -1,
+ -1, -1, 8, 9, -1, 11, 12, 13, -1, -1,
+ -1, -1, -1, -1, -1, 21, 22, -1, -1, -1,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, -1, -1, 40, 41, 42, 43, -1, -1,
+ -1, -1, 48, -1, -1, 51, 52, -1, -1, 55,
+ -1, 57, -1, 59, 60, 61, 62, 63, 64, 65,
+ 66, 67, 68, 69, 70, 71, 72, -1, -1, -1,
+ -1, -1, -1, 79, -1, 81, 82, 83, 84, 85,
+ 86, 87, 88, 89, 90, 91, 92, 93, 94, -1,
+ -1, -1, -1, 99, -1, -1, -1, -1, -1, 105,
+ -1, -1, -1, -1, -1, -1, 112, -1, -1, -1,
+ 116, 117, 118, 119, 120, 121, 122, 123, 124, 125,
+ 126, 127, 128, 129, 130, 131, 132, 133, -1, -1,
+ -1, -1, 138, -1, -1, -1, 142, 143, 144, -1,
+ 146, 147, 148, 149, 150, 151, 152, 153, 154, 155,
+ 156, 157, 158, 159, -1, 161, 162, 163, -1, 165,
+ -1, -1, -1, 169, 170, -1, -1, -1, -1, 8,
+ 9, -1, 11, 12, 13, -1, -1, -1, -1, -1,
+ -1, -1, 21, 22, -1, -1, -1, 26, 27, 28,
+ 29, 30, 31, 32, 33, 34, 35, 36, 37, -1,
+ -1, 40, 41, 42, 43, -1, -1, -1, -1, 48,
+ -1, -1, 51, 52, -1, -1, 55, -1, 57, -1,
+ 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
+ 69, 70, 71, 72, -1, -1, -1, -1, -1, -1,
+ 79, -1, 81, 82, 83, 84, 85, 86, 87, 88,
+ 89, 90, 91, 92, 93, 94, -1, -1, -1, -1,
+ 99, -1, -1, -1, -1, -1, 105, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 116, 117, 118,
+ 119, 120, 121, 122, 123, 124, 125, 126, 127, 128,
+ 129, 130, 131, 132, 133, 134, -1, -1, -1, 138,
+ -1, -1, -1, 142, 143, 144, -1, 146, 147, 148,
+ 149, 150, 151, 152, 153, 154, 155, 156, 157, 158,
+ 159, -1, 161, 162, 163, -1, 165, -1, -1, -1,
+ 169, 170, -1, -1, -1, -1, 8, 9, -1, 11,
+ 12, 13, -1, -1, -1, -1, -1, -1, -1, 21,
+ 22, -1, -1, -1, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, -1, -1, 40, 41,
+ 42, 43, -1, -1, -1, -1, 48, -1, -1, 51,
+ 52, -1, -1, 55, -1, 57, -1, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, -1, -1, -1, -1, -1, -1, 79, -1, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
+ 92, 93, 94, -1, -1, -1, -1, 99, -1, -1,
+ -1, -1, -1, 105, -1, -1, -1, -1, -1, -1,
+ 112, -1, -1, -1, 116, 117, 118, 119, 120, 121,
+ 122, 123, 124, 125, 126, 127, 128, 129, 130, 131,
+ 132, 133, -1, -1, -1, -1, 138, -1, -1, -1,
+ 142, 143, 144, -1, 146, 147, 148, 149, 150, 151,
+ 152, 153, 154, 155, 156, 157, 158, 159, -1, 161,
+ 162, 163, -1, 165, -1, -1, -1, 169, 170, -1,
+ -1, -1, -1, 8, 9, -1, 11, 12, 13, -1,
+ -1, -1, -1, -1, -1, -1, 21, 22, -1, -1,
+ -1, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, -1, -1, 40, 41, 42, 43, -1,
+ -1, -1, -1, 48, -1, -1, 51, 52, -1, -1,
+ 55, -1, 57, -1, 59, 60, 61, 62, 63, 64,
+ 65, 66, 67, 68, 69, 70, 71, 72, -1, -1,
+ -1, -1, -1, -1, 79, -1, 81, 82, 83, 84,
+ 85, 86, 87, 88, 89, 90, 91, 92, 93, 94,
+ -1, -1, -1, -1, 99, -1, -1, -1, -1, -1,
+ 105, -1, -1, -1, -1, -1, -1, 112, -1, -1,
+ -1, 116, 117, 118, 119, 120, 121, 122, 123, 124,
+ 125, 126, 127, 128, 129, 130, 131, 132, 133, -1,
+ -1, -1, -1, 138, -1, -1, -1, 142, 143, 144,
+ -1, 146, 147, 148, 149, 150, 151, 152, 153, 154,
+ 155, 156, 157, 158, 159, -1, 161, 162, 163, -1,
+ 165, -1, -1, -1, 169, 170, -1, -1, -1, -1,
+ 8, 9, -1, 11, 12, 13, -1, -1, -1, -1,
+ -1, -1, -1, 21, 22, -1, -1, -1, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ -1, -1, 40, 41, 42, 43, -1, -1, -1, -1,
+ 48, -1, -1, 51, 52, -1, -1, 55, -1, 57,
+ -1, 59, 60, 61, 62, 63, 64, 65, 66, 67,
+ 68, 69, 70, 71, 72, -1, -1, -1, -1, -1,
+ -1, 79, -1, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 94, -1, -1, -1,
+ -1, 99, -1, -1, -1, -1, -1, 105, -1, -1,
+ -1, -1, -1, -1, 112, -1, -1, -1, 116, 117,
+ 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
+ 128, 129, 130, 131, 132, 133, -1, -1, -1, -1,
+ 138, -1, -1, -1, 142, 143, 144, -1, 146, 147,
+ 148, 149, 150, 151, 152, 153, 154, 155, 156, 157,
+ 158, 159, -1, 161, 162, 163, -1, 165, -1, -1,
+ -1, 169, 170, -1, -1, -1, -1, 7, -1, 9,
+ -1, 11, 12, 13, -1, -1, 16, -1, -1, 19,
+ -1, -1, -1, -1, -1, -1, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, -1, -1,
+ 40, 41, 42, 43, -1, -1, -1, 47, 48, -1,
+ -1, 51, -1, -1, 54, -1, -1, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, -1, -1, -1, -1, -1, -1,
+ -1, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, -1, -1, -1, 98, -1,
+ -1, -1, 102, 103, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
+ 130, 131, 132, 133, -1, -1, 136, -1, 138, -1,
+ -1, -1, -1, 143, 144, 145, 146, 147, 148, 149,
+ 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
+ 160, 161, 162, 163, -1, 165, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 7, -1, 9, -1, 11,
+ 12, 13, -1, -1, 16, -1, -1, 19, -1, -1,
+ -1, -1, -1, -1, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, -1, -1, 40, 41,
+ 42, 43, -1, -1, -1, 47, 48, -1, -1, 51,
+ -1, -1, 54, -1, -1, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, -1, -1, -1, -1, -1, -1, -1, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
+ 92, 93, 94, -1, -1, -1, 98, -1, -1, -1,
+ 102, 103, -1, -1, -1, -1, -1, -1, -1, 111,
+ -1, -1, -1, 115, 116, 117, 118, 119, 120, 121,
+ 122, 123, 124, 125, 126, 127, 128, 129, 130, 131,
+ 132, 133, -1, -1, 136, -1, 138, -1, -1, -1,
+ -1, 143, 144, 145, 146, 147, 148, 149, 150, 151,
+ 152, 153, 154, 155, 156, 157, 158, 159, 160, 161,
+ 162, 163, -1, 165, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 7, -1, 9, -1, 11, 12, 13,
+ -1, -1, 16, -1, -1, 19, -1, -1, -1, -1,
+ -1, -1, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, -1, -1, 40, 41, 42, 43,
+ -1, -1, -1, 47, 48, -1, -1, 51, -1, -1,
+ 54, -1, -1, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ -1, -1, -1, -1, -1, -1, -1, 81, 82, 83,
+ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ 94, -1, -1, -1, 98, -1, -1, -1, 102, 103,
+ -1, -1, -1, -1, -1, -1, -1, 111, -1, -1,
+ -1, 115, 116, 117, 118, 119, 120, 121, 122, 123,
+ 124, 125, 126, 127, 128, 129, 130, 131, 132, 133,
+ -1, -1, 136, -1, 138, -1, -1, -1, -1, 143,
+ 144, 145, 146, 147, 148, 149, 150, 151, 152, 153,
+ 154, 155, 156, 157, 158, 159, 160, 161, 162, 163,
+ -1, 165, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 7, -1, 9, -1, 11, 12, 13, -1, -1,
+ 16, -1, -1, 19, -1, -1, -1, -1, -1, -1,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, -1, -1, 40, 41, 42, 43, -1, -1,
+ -1, 47, 48, -1, -1, 51, -1, -1, 54, -1,
+ -1, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 66, 67, 68, 69, 70, 71, 72, 73, -1, -1,
+ -1, -1, -1, -1, -1, 81, 82, 83, 84, 85,
+ 86, 87, 88, 89, 90, 91, 92, 93, 94, -1,
+ -1, -1, 98, -1, -1, -1, 102, 103, -1, -1,
+ -1, -1, -1, -1, -1, 111, -1, -1, -1, 115,
+ 116, 117, 118, 119, 120, 121, 122, 123, 124, 125,
+ 126, 127, 128, 129, 130, 131, 132, 133, -1, -1,
+ 136, -1, 138, -1, -1, -1, -1, 143, 144, 145,
+ 146, 147, 148, 149, 150, 151, 152, 153, 154, 155,
+ 156, 157, 158, 159, 160, 161, 162, 163, -1, 165,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 7,
+ -1, 9, -1, 11, 12, 13, -1, -1, 16, -1,
+ -1, 19, -1, -1, -1, -1, -1, -1, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ -1, -1, 40, 41, 42, 43, -1, -1, -1, 47,
+ 48, -1, -1, 51, -1, -1, 54, -1, -1, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
+ 68, 69, 70, 71, 72, 73, -1, -1, -1, -1,
+ -1, -1, -1, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 94, -1, -1, -1,
+ 98, -1, -1, -1, 102, 103, -1, -1, 106, -1,
+ -1, -1, -1, -1, -1, -1, -1, 115, 116, 117,
+ 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
+ 128, 129, 130, 131, 132, 133, 134, -1, 136, -1,
+ 138, -1, -1, -1, -1, 143, 144, 145, 146, 147,
+ 148, 149, 150, 151, 152, 153, 154, 155, 156, 157,
+ 158, 159, 160, 161, 162, 163, -1, 165, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 7, 8, 9,
+ -1, 11, 12, 13, -1, -1, 16, -1, -1, 19,
+ -1, 21, 22, -1, -1, -1, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, -1, -1,
+ 40, 41, 42, 43, -1, -1, -1, 47, 48, -1,
+ -1, 51, 52, -1, 54, 55, -1, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, -1, -1, -1, -1, -1, 79,
+ -1, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, -1, -1, -1, 98, 99,
+ -1, -1, 102, 103, -1, 105, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
+ 130, 131, 132, 133, -1, -1, 136, -1, 138, -1,
+ -1, -1, 142, 143, 144, 145, 146, 147, 148, 149,
+ 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
+ 160, 161, 162, 163, -1, 165, -1, -1, -1, 169,
+ 170, -1, -1, -1, -1, 7, 8, 9, -1, 11,
+ 12, 13, -1, -1, 16, -1, -1, 19, -1, 21,
+ 22, -1, -1, -1, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, -1, -1, 40, 41,
+ 42, 43, -1, -1, -1, 47, 48, -1, -1, 51,
+ 52, -1, 54, 55, -1, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, -1, -1, -1, -1, -1, 79, -1, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
+ 92, 93, 94, -1, -1, -1, 98, 99, -1, -1,
+ 102, 103, -1, 105, 106, -1, -1, -1, -1, -1,
+ -1, -1, -1, 115, 116, 117, 118, 119, 120, 121,
+ 122, 123, 124, 125, 126, 127, 128, 129, 130, 131,
+ 132, 133, 134, -1, 136, -1, 138, -1, -1, -1,
+ 142, 143, 144, 145, 146, 147, 148, 149, 150, 151,
+ 152, 153, 154, 155, 156, 157, 158, 159, 160, 161,
+ 162, 163, -1, 165, -1, -1, -1, 169, 170, -1,
+ -1, -1, -1, 7, 8, 9, 10, 11, 12, 13,
+ -1, 15, 16, -1, -1, 19, 20, 21, 22, 23,
+ 24, -1, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, -1, 40, 41, 42, 43,
+ -1, -1, -1, 47, 48, 49, -1, 51, 52, 53,
+ 54, 55, -1, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ -1, -1, 76, -1, -1, 79, -1, 81, 82, 83,
+ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ 94, -1, -1, -1, 98, 99, -1, -1, 102, 103,
+ -1, 105, 106, -1, 108, -1, -1, -1, -1, -1,
+ -1, 115, 116, 117, 118, 119, 120, 121, 122, 123,
+ 124, 125, 126, 127, 128, 129, 130, 131, 132, 133,
+ 134, -1, 136, -1, 138, -1, -1, 141, 142, 143,
+ 144, 145, 146, 147, 148, 149, 150, 151, 152, 153,
+ 154, 155, 156, 157, 158, 159, 160, 161, 162, 163,
+ -1, 165, 166, -1, -1, 169, 170, -1, -1, -1,
+ -1, 7, 8, 9, 10, 11, 12, 13, -1, 15,
+ 16, -1, -1, 19, 20, 21, 22, 23, 24, -1,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, -1, 40, 41, 42, 43, -1, -1,
+ -1, 47, 48, 49, -1, 51, 52, 53, 54, 55,
+ -1, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 66, 67, 68, 69, 70, 71, 72, 73, -1, -1,
+ 76, -1, -1, 79, -1, 81, 82, 83, 84, 85,
+ 86, 87, 88, 89, 90, 91, 92, 93, 94, -1,
+ -1, -1, 98, 99, -1, -1, 102, 103, -1, 105,
+ 106, -1, 108, -1, -1, -1, -1, -1, -1, 115,
+ 116, 117, 118, 119, 120, 121, 122, 123, 124, 125,
+ 126, 127, 128, 129, 130, 131, 132, 133, 134, -1,
+ 136, -1, 138, -1, -1, 141, 142, 143, 144, 145,
+ 146, 147, 148, 149, 150, 151, 152, 153, 154, 155,
+ 156, 157, 158, 159, 160, 161, 162, 163, -1, 165,
+ 166, -1, -1, 169, 170, -1, -1, -1, -1, 7,
+ 8, 9, 10, 11, 12, 13, -1, 15, 16, -1,
+ -1, 19, 20, 21, 22, 23, 24, -1, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, -1, 40, 41, 42, 43, -1, -1, -1, 47,
+ 48, 49, -1, 51, 52, 53, 54, 55, -1, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
+ 68, 69, 70, 71, 72, 73, -1, -1, 76, -1,
+ -1, 79, -1, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 94, -1, -1, -1,
+ 98, 99, -1, -1, 102, 103, -1, 105, 106, -1,
+ 108, -1, -1, 111, -1, -1, -1, 115, 116, 117,
+ 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
+ 128, 129, 130, 131, 132, 133, 134, -1, 136, -1,
+ 138, -1, -1, 141, 142, 143, 144, 145, 146, 147,
+ 148, 149, 150, 151, 152, 153, 154, 155, 156, 157,
+ 158, 159, 160, 161, 162, 163, -1, 165, 166, -1,
+ -1, 169, 170, -1, -1, -1, -1, 7, 8, 9,
+ 10, 11, 12, 13, -1, 15, 16, -1, -1, 19,
+ 20, 21, 22, 23, 24, -1, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, -1,
+ 40, 41, 42, 43, -1, -1, -1, 47, 48, 49,
+ -1, 51, 52, 53, 54, 55, -1, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, -1, -1, 76, -1, -1, 79,
+ -1, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, -1, -1, -1, 98, 99,
+ -1, -1, 102, 103, -1, 105, 106, -1, 108, -1,
+ -1, 111, -1, -1, -1, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
+ 130, 131, 132, 133, 134, -1, 136, -1, 138, -1,
+ -1, 141, 142, 143, 144, 145, 146, 147, 148, 149,
+ 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
+ 160, 161, 162, 163, -1, 165, 166, -1, -1, 169,
+ 170, -1, -1, -1, -1, 7, 8, 9, 10, 11,
+ 12, 13, -1, 15, 16, -1, -1, 19, 20, 21,
+ 22, 23, 24, -1, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, -1, 40, 41,
+ 42, 43, -1, -1, -1, 47, 48, 49, -1, 51,
+ 52, 53, 54, 55, -1, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, -1, -1, 76, -1, -1, 79, -1, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
+ 92, 93, 94, -1, -1, -1, 98, 99, -1, -1,
+ 102, 103, -1, 105, 106, -1, 108, -1, -1, 111,
+ -1, -1, -1, 115, 116, 117, 118, 119, 120, 121,
+ 122, 123, 124, 125, 126, 127, 128, 129, 130, 131,
+ 132, 133, 134, -1, 136, -1, 138, -1, -1, 141,
+ 142, 143, 144, 145, 146, 147, 148, 149, 150, 151,
+ 152, 153, 154, 155, 156, 157, 158, 159, 160, 161,
+ 162, 163, -1, 165, 166, -1, -1, 169, 170, -1,
+ -1, -1, -1, 7, 8, 9, 10, 11, 12, 13,
+ -1, 15, 16, -1, -1, 19, 20, 21, 22, 23,
+ 24, -1, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, -1, 40, 41, 42, 43,
+ -1, -1, -1, 47, 48, 49, -1, 51, 52, 53,
+ 54, 55, -1, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ -1, -1, 76, -1, -1, 79, -1, 81, 82, 83,
+ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ 94, -1, -1, -1, 98, 99, -1, -1, 102, 103,
+ -1, 105, 106, -1, 108, -1, -1, 111, -1, -1,
+ -1, 115, 116, 117, 118, 119, 120, 121, 122, 123,
+ 124, 125, 126, 127, 128, 129, 130, 131, 132, 133,
+ 134, -1, 136, -1, 138, -1, -1, 141, 142, 143,
+ 144, 145, 146, 147, 148, 149, 150, 151, 152, 153,
+ 154, 155, 156, 157, 158, 159, 160, 161, 162, 163,
+ -1, 165, 166, -1, -1, 169, 170, -1, -1, -1,
+ -1,
+
+ 14, 3, 12, 14, 55, 3, 15, 15, 3, 54,
+ 59, 15, 60, 3, 15, 15, 12, 3, 45, 8,
+ 55, 15, 3, 3, 41, 12, 14, 34, 12, 14,
+ 3, 14, 35, 12, 12, 73, 3, 55, 35, 15,
+ 12, 15, 12, 12, 12, 21, 20, -1, -1, 15,
+ 15, 15, 12, 17, 15, 20, 17, 14, 12, 15,
+ 15, 14, 28, 18, 15, 15, 14, 18, 14, 25,
+ 14, 3, -1, 15, 14, 14, 26, 49, 14, 49,
+ 49, 49, 24, -1, -1, -1, 15, 15, 51, 49,
+ 19, 19, 55, 15, 15, 49, 36, 19, 15, 15,
+ 14, 22, 15, 19, 14, 62, 23, 14, -1, 62,
+ 14, -1, 15, 14, 62, 28, 62, 30, 14, 14,
+ 64, 15, 36, 62, 15, 28, 62, 30, 14, 14,
+ 31, 32, 36, 15, 28, -1, 30, 28, 3, 30,
+ 36, 37, -1, -1, 58, 14, 28, -1, 30, 14,
+ 36, 61, 47, 14, 58, 65, -1, 64, 43, 3,
+ -1, 46, -1, -1, -1, 72, -1, 36, 37, -1,
+ 14, 36, 58, -1, -1, -1, 71, 42, -1, -1,
+ -1, -1, 47, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 36, -1, -1, -1, -1, -1, 42, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 71, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 14, -1, -1, -1, -1, -1,
+ -1, 75, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 31, 32, -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, 82, -1, -1};
+
+QT_END_NAMESPACE
diff --git a/src/libs/glsl/glslparsertable_p.h b/src/libs/glsl/glslparsertable_p.h
new file mode 100644
index 0000000000..892035107c
--- /dev/null
+++ b/src/libs/glsl/glslparsertable_p.h
@@ -0,0 +1,284 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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.
+//
+
+// This file was generated by qlalr - DO NOT EDIT!
+#ifndef GLSLPARSERTABLE_P_H
+#define GLSLPARSERTABLE_P_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class GLSLParserTable
+{
+public:
+ enum VariousConstants {
+ EOF_SYMBOL = 0,
+ T_ADD_ASSIGN = 3,
+ T_AMPERSAND = 4,
+ T_AND_ASSIGN = 5,
+ T_AND_OP = 6,
+ T_ATTRIBUTE = 7,
+ T_BANG = 8,
+ T_BOOL = 9,
+ T_BREAK = 10,
+ T_BVEC2 = 11,
+ T_BVEC3 = 12,
+ T_BVEC4 = 13,
+ T_CARET = 14,
+ T_CASE = 15,
+ T_CENTROID = 16,
+ T_COLON = 17,
+ T_COMMA = 18,
+ T_COMMENT = 172,
+ T_CONST = 19,
+ T_CONTINUE = 20,
+ T_DASH = 21,
+ T_DEC_OP = 22,
+ T_DEFAULT = 23,
+ T_DISCARD = 24,
+ T_DIV_ASSIGN = 25,
+ T_DMAT2 = 26,
+ T_DMAT2X2 = 27,
+ T_DMAT2X3 = 28,
+ T_DMAT2X4 = 29,
+ T_DMAT3 = 30,
+ T_DMAT3X2 = 31,
+ T_DMAT3X3 = 32,
+ T_DMAT3X4 = 33,
+ T_DMAT4 = 34,
+ T_DMAT4X2 = 35,
+ T_DMAT4X3 = 36,
+ T_DMAT4X4 = 37,
+ T_DO = 38,
+ T_DOT = 39,
+ T_DOUBLE = 40,
+ T_DVEC2 = 41,
+ T_DVEC3 = 42,
+ T_DVEC4 = 43,
+ T_ELSE = 44,
+ T_EQUAL = 45,
+ T_EQ_OP = 46,
+ T_ERROR = 173,
+ T_FALSE = 170,
+ T_FEED_EXPRESSION = 2,
+ T_FEED_GLSL = 1,
+ T_FLAT = 47,
+ T_FLOAT = 48,
+ T_FOR = 49,
+ T_GE_OP = 50,
+ T_HIGHP = 51,
+ T_IDENTIFIER = 52,
+ T_IF = 53,
+ T_IN = 54,
+ T_INC_OP = 55,
+ T_INOUT = 56,
+ T_INT = 57,
+ T_INVARIANT = 58,
+ T_ISAMPLER1D = 59,
+ T_ISAMPLER1DARRAY = 60,
+ T_ISAMPLER2D = 61,
+ T_ISAMPLER2DARRAY = 62,
+ T_ISAMPLER2DMS = 63,
+ T_ISAMPLER2DMSARRAY = 64,
+ T_ISAMPLER2DRECT = 65,
+ T_ISAMPLER3D = 66,
+ T_ISAMPLERBUFFER = 67,
+ T_ISAMPLERCUBE = 68,
+ T_ISAMPLERCUBEARRAY = 69,
+ T_IVEC2 = 70,
+ T_IVEC3 = 71,
+ T_IVEC4 = 72,
+ T_LAYOUT = 73,
+ T_LEFT_ANGLE = 74,
+ T_LEFT_ASSIGN = 75,
+ T_LEFT_BRACE = 76,
+ T_LEFT_BRACKET = 77,
+ T_LEFT_OP = 78,
+ T_LEFT_PAREN = 79,
+ T_LE_OP = 80,
+ T_LOWP = 81,
+ T_MAT2 = 82,
+ T_MAT2X2 = 83,
+ T_MAT2X3 = 84,
+ T_MAT2X4 = 85,
+ T_MAT3 = 86,
+ T_MAT3X2 = 87,
+ T_MAT3X3 = 88,
+ T_MAT3X4 = 89,
+ T_MAT4 = 90,
+ T_MAT4X2 = 91,
+ T_MAT4X3 = 92,
+ T_MAT4X4 = 93,
+ T_MEDIUMP = 94,
+ T_MOD_ASSIGN = 95,
+ T_MUL_ASSIGN = 96,
+ T_NE_OP = 97,
+ T_NOPERSPECTIVE = 98,
+ T_NUMBER = 99,
+ T_OR_ASSIGN = 100,
+ T_OR_OP = 101,
+ T_OUT = 102,
+ T_PATCH = 103,
+ T_PERCENT = 104,
+ T_PLUS = 105,
+ T_PRECISION = 106,
+ T_PREPROC = 171,
+ T_QUESTION = 107,
+ T_RESERVED = 174,
+ T_RETURN = 108,
+ T_RIGHT_ANGLE = 109,
+ T_RIGHT_ASSIGN = 110,
+ T_RIGHT_BRACE = 111,
+ T_RIGHT_BRACKET = 112,
+ T_RIGHT_OP = 113,
+ T_RIGHT_PAREN = 114,
+ T_SAMPLE = 115,
+ T_SAMPLER1D = 116,
+ T_SAMPLER1DARRAY = 117,
+ T_SAMPLER1DARRAYSHADOW = 118,
+ T_SAMPLER1DSHADOW = 119,
+ T_SAMPLER2D = 120,
+ T_SAMPLER2DARRAY = 121,
+ T_SAMPLER2DARRAYSHADOW = 122,
+ T_SAMPLER2DMS = 123,
+ T_SAMPLER2DMSARRAY = 124,
+ T_SAMPLER2DRECT = 125,
+ T_SAMPLER2DRECTSHADOW = 126,
+ T_SAMPLER2DSHADOW = 127,
+ T_SAMPLER3D = 128,
+ T_SAMPLERBUFFER = 129,
+ T_SAMPLERCUBE = 130,
+ T_SAMPLERCUBEARRAY = 131,
+ T_SAMPLERCUBEARRAYSHADOW = 132,
+ T_SAMPLERCUBESHADOW = 133,
+ T_SEMICOLON = 134,
+ T_SLASH = 135,
+ T_SMOOTH = 136,
+ T_STAR = 137,
+ T_STRUCT = 138,
+ T_SUBROUTINE = 139,
+ T_SUB_ASSIGN = 140,
+ T_SWITCH = 141,
+ T_TILDE = 142,
+ T_TRUE = 169,
+ T_TYPE_NAME = 143,
+ T_UINT = 144,
+ T_UNIFORM = 145,
+ T_USAMPLER1D = 146,
+ T_USAMPLER1DARRAY = 147,
+ T_USAMPLER2D = 148,
+ T_USAMPLER2DARRAY = 149,
+ T_USAMPLER2DMS = 150,
+ T_USAMPLER2DMSARRAY = 151,
+ T_USAMPLER2DRECT = 152,
+ T_USAMPLER3D = 153,
+ T_USAMPLERBUFFER = 154,
+ T_USAMPLERCUBE = 155,
+ T_USAMPLERCUBEARRAY = 156,
+ T_UVEC2 = 157,
+ T_UVEC3 = 158,
+ T_UVEC4 = 159,
+ T_VARYING = 160,
+ T_VEC2 = 161,
+ T_VEC3 = 162,
+ T_VEC4 = 163,
+ T_VERTICAL_BAR = 164,
+ T_VOID = 165,
+ T_WHILE = 166,
+ T_XOR_ASSIGN = 167,
+ T_XOR_OP = 168,
+
+ ACCEPT_STATE = 462,
+ RULE_COUNT = 316,
+ STATE_COUNT = 463,
+ TERMINAL_COUNT = 175,
+ NON_TERMINAL_COUNT = 85,
+
+ GOTO_INDEX_OFFSET = 463,
+ GOTO_INFO_OFFSET = 4681,
+ GOTO_CHECK_OFFSET = 4681
+ };
+
+ static const char *const spell [];
+ static const short lhs [];
+ static const short rhs [];
+ static const short goto_default [];
+ static const short action_default [];
+ static const short action_index [];
+ static const short action_info [];
+ static const short action_check [];
+
+ static inline int nt_action (int state, int nt)
+ {
+ const int yyn = action_index [GOTO_INDEX_OFFSET + state] + nt;
+ if (yyn < 0 || action_check [GOTO_CHECK_OFFSET + yyn] != nt)
+ return goto_default [nt];
+
+ return action_info [GOTO_INFO_OFFSET + 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];
+ }
+};
+
+
+QT_END_NAMESPACE
+#endif // GLSLPARSERTABLE_P_H
+
diff --git a/src/libs/glsl/glslsemantic.cpp b/src/libs/glsl/glslsemantic.cpp
new file mode 100644
index 0000000000..c01e460be2
--- /dev/null
+++ b/src/libs/glsl/glslsemantic.cpp
@@ -0,0 +1,876 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "glslsemantic.h"
+#include "glslengine.h"
+#include "glslparser.h"
+#include "glslsymbols.h"
+#include "glsltypes.h"
+#include <QtCore/QDebug>
+
+using namespace GLSL;
+
+Semantic::Semantic()
+ : _engine(0)
+ , _scope(0)
+ , _type(0)
+{
+}
+
+Semantic::~Semantic()
+{
+}
+
+Engine *Semantic::switchEngine(Engine *engine)
+{
+ Engine *previousEngine = _engine;
+ _engine = engine;
+ return previousEngine;
+}
+
+Scope *Semantic::switchScope(Scope *scope)
+{
+ Scope *previousScope = _scope;
+ _scope = scope;
+ return previousScope;
+}
+
+Semantic::ExprResult Semantic::expression(ExpressionAST *ast)
+{
+ Semantic::ExprResult r(_engine->undefinedType());
+ std::swap(_expr, r);
+ accept(ast);
+ std::swap(_expr, r);
+ return r;
+}
+
+void Semantic::statement(StatementAST *ast)
+{
+ accept(ast);
+}
+
+const Type *Semantic::type(TypeAST *ast)
+{
+ const Type *t = _engine->undefinedType();
+ std::swap(_type, t);
+ accept(ast);
+ std::swap(_type, t);
+ return t;
+}
+
+void Semantic::declaration(DeclarationAST *ast)
+{
+ accept(ast);
+}
+
+void Semantic::translationUnit(TranslationUnitAST *ast, Scope *globalScope, Engine *engine)
+{
+ Engine *previousEngine = switchEngine(engine);
+ Scope *previousScope = switchScope(globalScope);
+ if (ast) {
+ for (List<DeclarationAST *> *it = ast->declarations; it; it = it->next) {
+ DeclarationAST *decl = it->value;
+ declaration(decl);
+ }
+ }
+ (void) switchScope(previousScope);
+ (void) switchEngine(previousEngine);
+}
+
+Semantic::ExprResult Semantic::expression(ExpressionAST *ast, Scope *scope, Engine *engine)
+{
+ ExprResult result(engine->undefinedType());
+ if (ast && scope) {
+ Engine *previousEngine = switchEngine(engine);
+ Scope *previousScope = switchScope(scope);
+ result = expression(ast);
+ (void) switchScope(previousScope);
+ (void) switchEngine(previousEngine);
+ }
+ return result;
+}
+
+Semantic::ExprResult Semantic::functionIdentifier(FunctionIdentifierAST *ast)
+{
+ ExprResult result;
+ if (ast) {
+ if (ast->name) {
+ if (Symbol *s = _scope->lookup(*ast->name)) {
+ if (s->asOverloadSet() != 0 || s->asFunction() != 0)
+ result.type = s->type();
+ else
+ _engine->error(ast->lineno, QString("`%1' cannot be used as a function").arg(*ast->name));
+ } else {
+ _engine->error(ast->lineno, QString("`%1' was not declared in this scope").arg(*ast->name));
+ }
+ } else if (ast->type) {
+ const Type *ty = type(ast->type);
+ result.type = ty;
+ }
+ }
+
+ return result;
+}
+
+Symbol *Semantic::field(StructTypeAST::Field *ast)
+{
+ // ast->name
+ const Type *ty = type(ast->type);
+ QString name;
+ if (ast->name)
+ name = *ast->name;
+ return _engine->newVariable(_scope, name, ty);
+}
+
+void Semantic::parameterDeclaration(ParameterDeclarationAST *ast, Function *fun)
+{
+ const Type *ty = type(ast->type);
+ QString name;
+ if (ast->name)
+ name = *ast->name;
+ Argument *arg = _engine->newArgument(fun, name, ty);
+ fun->addArgument(arg);
+}
+
+bool Semantic::visit(TranslationUnitAST *ast)
+{
+ Q_UNUSED(ast);
+ Q_ASSERT(!"unreachable");
+ return false;
+}
+
+bool Semantic::visit(FunctionIdentifierAST *ast)
+{
+ Q_UNUSED(ast);
+ Q_ASSERT(!"unreachable");
+ return false;
+}
+
+bool Semantic::visit(StructTypeAST::Field *ast)
+{
+ Q_UNUSED(ast);
+ Q_ASSERT(!"unreachable");
+ return false;
+}
+
+
+// expressions
+bool Semantic::visit(IdentifierExpressionAST *ast)
+{
+ if (ast->name) {
+ if (Symbol *s = _scope->lookup(*ast->name)) {
+ _expr.type = s->type();
+ } else {
+ _engine->error(ast->lineno, QString("`%1' was not declared in this scope").arg(*ast->name));
+ }
+ }
+ return false;
+}
+
+bool Semantic::visit(LiteralExpressionAST *ast)
+{
+ if (ast->value) {
+ _expr.isConstant = true;
+
+ if (ast->value->at(0) == QLatin1Char('t') && *ast->value == QLatin1String("true"))
+ _expr.type = _engine->boolType();
+ else if (ast->value->at(0) == QLatin1Char('f') && *ast->value == QLatin1String("false"))
+ _expr.type = _engine->boolType();
+ else if (ast->value->endsWith(QLatin1Char('u')) || ast->value->endsWith(QLatin1Char('U')))
+ _expr.type = _engine->uintType();
+ else if (ast->value->endsWith(QLatin1String("lf")) || ast->value->endsWith(QLatin1String("LF")))
+ _expr.type = _engine->doubleType();
+ else if (ast->value->endsWith(QLatin1Char('f')) || ast->value->endsWith(QLatin1Char('f')) || ast->value->contains(QLatin1Char('.')))
+ _expr.type = _engine->floatType();
+ else
+ _expr.type = _engine->intType();
+ }
+ return false;
+}
+
+bool Semantic::visit(BinaryExpressionAST *ast)
+{
+ ExprResult left = expression(ast->left);
+ ExprResult right = expression(ast->right);
+ _expr.isConstant = left.isConstant && right.isConstant;
+ switch (ast->kind) {
+ case AST::Kind_ArrayAccess:
+ if (left.type) {
+ if (const IndexType *idxType = left.type->asIndexType())
+ _expr = idxType->indexElementType();
+ else
+ _engine->error(ast->lineno, QString("Invalid type `%1' for array subscript").arg(left.type->toString()));
+ }
+ break;
+
+ case AST::Kind_Modulus:
+ case AST::Kind_Multiply:
+ case AST::Kind_Divide:
+ case AST::Kind_Plus:
+ case AST::Kind_Minus:
+ case AST::Kind_ShiftLeft:
+ case AST::Kind_ShiftRight:
+ _expr.type = left.type; // ### not exactly
+ break;
+
+ case AST::Kind_LessThan:
+ case AST::Kind_GreaterThan:
+ case AST::Kind_LessEqual:
+ case AST::Kind_GreaterEqual:
+ case AST::Kind_Equal:
+ case AST::Kind_NotEqual:
+ case AST::Kind_BitwiseAnd:
+ case AST::Kind_BitwiseXor:
+ case AST::Kind_BitwiseOr:
+ case AST::Kind_LogicalAnd:
+ case AST::Kind_LogicalXor:
+ case AST::Kind_LogicalOr:
+ _expr.type = _engine->boolType();
+ break;
+
+ case AST::Kind_Comma:
+ _expr = right;
+ break;
+ }
+
+ return false;
+}
+
+bool Semantic::visit(UnaryExpressionAST *ast)
+{
+ ExprResult expr = expression(ast->expr);
+ _expr = expr;
+ return false;
+}
+
+bool Semantic::visit(TernaryExpressionAST *ast)
+{
+ ExprResult first = expression(ast->first);
+ ExprResult second = expression(ast->second);
+ ExprResult third = expression(ast->third);
+ _expr.isConstant = first.isConstant && second.isConstant && third.isConstant;
+ _expr.type = second.type;
+ return false;
+}
+
+bool Semantic::visit(AssignmentExpressionAST *ast)
+{
+ ExprResult variable = expression(ast->variable);
+ ExprResult value = expression(ast->value);
+ return false;
+}
+
+bool Semantic::visit(MemberAccessExpressionAST *ast)
+{
+ ExprResult expr = expression(ast->expr);
+ if (expr.type && ast->field) {
+ if (const VectorType *vecTy = expr.type->asVectorType()) {
+ if (Symbol *s = vecTy->find(*ast->field)) {
+ _expr.type = s->type();
+ } else {
+ _engine->error(ast->lineno, QString("`%1' has no member named `%2'").arg(vecTy->name()).arg(*ast->field));
+ }
+ } else if (const Struct *structTy = expr.type->asStructType()) {
+ if (Symbol *s = structTy->find(*ast->field)) {
+ _expr.type = s->type();
+ } else {
+ _engine->error(ast->lineno, QString("`%1' has no member named `%2'").arg(structTy->name()).arg(*ast->field));
+ }
+ } else {
+ _engine->error(ast->lineno, QString("Requested for member `%1', in a non class or vec instance").arg(*ast->field));
+ }
+ }
+ return false;
+}
+
+bool Semantic::implicitCast(const Type *type, const Type *target) const
+{
+ if (! (type && target)) {
+ return false;
+ } else if (type->isEqualTo(target)) {
+ return true;
+ } else if (target->asUIntType() != 0) {
+ return type->asIntType() != 0;
+ } else if (target->asFloatType() != 0) {
+ return type->asIntType() != 0 ||
+ type->asUIntType() != 0;
+ } else if (target->asDoubleType() != 0) {
+ return type->asIntType() != 0 ||
+ type->asUIntType() != 0 ||
+ type->asFloatType() != 0;
+ } else if (const VectorType *targetVecTy = target->asVectorType()) {
+ if (const VectorType *vecTy = type->asVectorType()) {
+ if (targetVecTy->dimension() == vecTy->dimension()) {
+ const Type *targetElementType = targetVecTy->elementType();
+ const Type *elementType = vecTy->elementType();
+
+ if (targetElementType->asUIntType() != 0) {
+ // uvec* -> ivec*
+ return elementType->asIntType() != 0;
+ } else if (targetElementType->asFloatType() != 0) {
+ // vec* -> ivec* | uvec*
+ return elementType->asIntType() != 0 ||
+ elementType->asUIntType() != 0;
+ } else if (targetElementType->asDoubleType() != 0) {
+ // dvec* -> ivec* | uvec* | fvec*
+ return elementType->asIntType() != 0 ||
+ elementType->asUIntType() != 0 ||
+ elementType->asFloatType() != 0;
+ }
+ }
+ }
+ } else if (const MatrixType *targetMatTy = target->asMatrixType()) {
+ if (const MatrixType *matTy = type->asMatrixType()) {
+ if (targetMatTy->columns() == matTy->columns() &&
+ targetMatTy->rows() == matTy->rows()) {
+ const Type *targetElementType = targetMatTy->elementType();
+ const Type *elementType = matTy->elementType();
+
+ if (targetElementType->asDoubleType() != 0) {
+ // dmat* -> mat*
+ return elementType->asFloatType() != 0;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+bool Semantic::visit(FunctionCallExpressionAST *ast)
+{
+ ExprResult expr = expression(ast->expr);
+ ExprResult id = functionIdentifier(ast->id);
+ QVector<ExprResult> actuals;
+ for (List<ExpressionAST *> *it = ast->arguments; it; it = it->next) {
+ ExprResult arg = expression(it->value);
+ actuals.append(arg);
+ }
+ if (id.isValid()) {
+ if (const Function *funTy = id.type->asFunctionType()) {
+ if (actuals.size() < funTy->argumentCount())
+ _engine->error(ast->lineno, QString("not enough arguments"));
+ else if (actuals.size() > funTy->argumentCount())
+ _engine->error(ast->lineno, QString("too many arguments"));
+ _expr.type = funTy->returnType();
+ } else if (const OverloadSet *overloads = id.type->asOverloadSetType()) {
+ QVector<GLSL::Function *> candidates;
+ foreach (GLSL::Function *f, overloads->functions()) {
+ if (f->argumentCount() == actuals.size()) {
+ int argc = 0;
+ for (; argc < actuals.size(); ++argc) {
+ const Type *actualTy = actuals.at(argc).type;
+ const Type *argumentTy = f->argumentAt(argc)->type();
+ if (! implicitCast(actualTy, argumentTy))
+ break;
+ }
+
+ if (argc == actuals.size())
+ candidates.append(f);
+ }
+ }
+
+ if (candidates.isEmpty()) {
+ // ### error, unresolved call.
+ Q_ASSERT(! overloads->functions().isEmpty());
+
+ _expr.type = overloads->functions().first()->returnType();
+ } else {
+ _expr.type = candidates.first()->returnType();
+
+ if (candidates.size() != 1) {
+ // ### error, ambiguous call
+ }
+ }
+ } else {
+ // called as constructor, e.g. vec2(a, b)
+ _expr.type = id.type;
+ }
+ }
+
+ return false;
+}
+
+bool Semantic::visit(DeclarationExpressionAST *ast)
+{
+ const Type *ty = type(ast->type);
+ Q_UNUSED(ty);
+ // ast->name
+ ExprResult initializer = expression(ast->initializer);
+ return false;
+}
+
+
+// statements
+bool Semantic::visit(ExpressionStatementAST *ast)
+{
+ ExprResult expr = expression(ast->expr);
+ return false;
+}
+
+bool Semantic::visit(CompoundStatementAST *ast)
+{
+ Block *block = _engine->newBlock(_scope);
+ Scope *previousScope = switchScope(block);
+ ast->symbol = block;
+ for (List<StatementAST *> *it = ast->statements; it; it = it->next) {
+ StatementAST *stmt = it->value;
+ statement(stmt);
+ }
+ (void) switchScope(previousScope);
+ return false;
+}
+
+bool Semantic::visit(IfStatementAST *ast)
+{
+ ExprResult condition = expression(ast->condition);
+ statement(ast->thenClause);
+ statement(ast->elseClause);
+ return false;
+}
+
+bool Semantic::visit(WhileStatementAST *ast)
+{
+ ExprResult condition = expression(ast->condition);
+ statement(ast->body);
+ return false;
+}
+
+bool Semantic::visit(DoStatementAST *ast)
+{
+ statement(ast->body);
+ ExprResult condition = expression(ast->condition);
+ return false;
+}
+
+bool Semantic::visit(ForStatementAST *ast)
+{
+ statement(ast->init);
+ ExprResult condition = expression(ast->condition);
+ ExprResult increment = expression(ast->increment);
+ statement(ast->body);
+ return false;
+}
+
+bool Semantic::visit(JumpStatementAST *ast)
+{
+ Q_UNUSED(ast);
+ return false;
+}
+
+bool Semantic::visit(ReturnStatementAST *ast)
+{
+ ExprResult expr = expression(ast->expr);
+ return false;
+}
+
+bool Semantic::visit(SwitchStatementAST *ast)
+{
+ ExprResult expr = expression(ast->expr);
+ statement(ast->body);
+ return false;
+}
+
+bool Semantic::visit(CaseLabelStatementAST *ast)
+{
+ ExprResult expr = expression(ast->expr);
+ return false;
+}
+
+bool Semantic::visit(DeclarationStatementAST *ast)
+{
+ declaration(ast->decl);
+ return false;
+}
+
+
+// types
+bool Semantic::visit(BasicTypeAST *ast)
+{
+ switch (ast->token) {
+ case Parser::T_VOID:
+ _type = _engine->voidType();
+ break;
+
+ case Parser::T_BOOL:
+ _type = _engine->boolType();
+ break;
+
+ case Parser::T_INT:
+ _type = _engine->intType();
+ break;
+
+ case Parser::T_UINT:
+ _type = _engine->uintType();
+ break;
+
+ case Parser::T_FLOAT:
+ _type = _engine->floatType();
+ break;
+
+ case Parser::T_DOUBLE:
+ _type = _engine->doubleType();
+ break;
+
+ // bvec
+ case Parser::T_BVEC2:
+ _type = _engine->vectorType(_engine->boolType(), 2);
+ break;
+
+ case Parser::T_BVEC3:
+ _type = _engine->vectorType(_engine->boolType(), 3);
+ break;
+
+ case Parser::T_BVEC4:
+ _type = _engine->vectorType(_engine->boolType(), 4);
+ break;
+
+ // ivec
+ case Parser::T_IVEC2:
+ _type = _engine->vectorType(_engine->intType(), 2);
+ break;
+
+ case Parser::T_IVEC3:
+ _type = _engine->vectorType(_engine->intType(), 3);
+ break;
+
+ case Parser::T_IVEC4:
+ _type = _engine->vectorType(_engine->intType(), 4);
+ break;
+
+ // uvec
+ case Parser::T_UVEC2:
+ _type = _engine->vectorType(_engine->uintType(), 2);
+ break;
+
+ case Parser::T_UVEC3:
+ _type = _engine->vectorType(_engine->uintType(), 3);
+ break;
+
+ case Parser::T_UVEC4:
+ _type = _engine->vectorType(_engine->uintType(), 4);
+ break;
+
+ // vec
+ case Parser::T_VEC2:
+ _type = _engine->vectorType(_engine->floatType(), 2);
+ break;
+
+ case Parser::T_VEC3:
+ _type = _engine->vectorType(_engine->floatType(), 3);
+ break;
+
+ case Parser::T_VEC4:
+ _type = _engine->vectorType(_engine->floatType(), 4);
+ break;
+
+ // dvec
+ case Parser::T_DVEC2:
+ _type = _engine->vectorType(_engine->doubleType(), 2);
+ break;
+
+ case Parser::T_DVEC3:
+ _type = _engine->vectorType(_engine->doubleType(), 3);
+ break;
+
+ case Parser::T_DVEC4:
+ _type = _engine->vectorType(_engine->doubleType(), 4);
+ break;
+
+ // mat2
+ case Parser::T_MAT2:
+ case Parser::T_MAT2X2:
+ _type = _engine->matrixType(_engine->floatType(), 2, 2);
+ break;
+
+ case Parser::T_MAT2X3:
+ _type = _engine->matrixType(_engine->floatType(), 2, 3);
+ break;
+
+ case Parser::T_MAT2X4:
+ _type = _engine->matrixType(_engine->floatType(), 2, 4);
+ break;
+
+ // mat3
+ case Parser::T_MAT3X2:
+ _type = _engine->matrixType(_engine->floatType(), 3, 2);
+ break;
+
+ case Parser::T_MAT3:
+ case Parser::T_MAT3X3:
+ _type = _engine->matrixType(_engine->floatType(), 3, 3);
+ break;
+
+ case Parser::T_MAT3X4:
+ _type = _engine->matrixType(_engine->floatType(), 3, 4);
+ break;
+
+ // mat4
+ case Parser::T_MAT4X2:
+ _type = _engine->matrixType(_engine->floatType(), 4, 2);
+ break;
+
+ case Parser::T_MAT4X3:
+ _type = _engine->matrixType(_engine->floatType(), 4, 3);
+ break;
+
+ case Parser::T_MAT4:
+ case Parser::T_MAT4X4:
+ _type = _engine->matrixType(_engine->floatType(), 4, 4);
+ break;
+
+
+ // dmat2
+ case Parser::T_DMAT2:
+ case Parser::T_DMAT2X2:
+ _type = _engine->matrixType(_engine->doubleType(), 2, 2);
+ break;
+
+ case Parser::T_DMAT2X3:
+ _type = _engine->matrixType(_engine->doubleType(), 2, 3);
+ break;
+
+ case Parser::T_DMAT2X4:
+ _type = _engine->matrixType(_engine->doubleType(), 2, 4);
+ break;
+
+ // dmat3
+ case Parser::T_DMAT3X2:
+ _type = _engine->matrixType(_engine->doubleType(), 3, 2);
+ break;
+
+ case Parser::T_DMAT3:
+ case Parser::T_DMAT3X3:
+ _type = _engine->matrixType(_engine->doubleType(), 3, 3);
+ break;
+
+ case Parser::T_DMAT3X4:
+ _type = _engine->matrixType(_engine->doubleType(), 3, 4);
+ break;
+
+ // dmat4
+ case Parser::T_DMAT4X2:
+ _type = _engine->matrixType(_engine->doubleType(), 4, 2);
+ break;
+
+ case Parser::T_DMAT4X3:
+ _type = _engine->matrixType(_engine->doubleType(), 4, 3);
+ break;
+
+ case Parser::T_DMAT4:
+ case Parser::T_DMAT4X4:
+ _type = _engine->matrixType(_engine->doubleType(), 4, 4);
+ break;
+
+ // samplers
+ case Parser::T_SAMPLER1D:
+ case Parser::T_SAMPLER2D:
+ case Parser::T_SAMPLER3D:
+ case Parser::T_SAMPLERCUBE:
+ case Parser::T_SAMPLER1DSHADOW:
+ case Parser::T_SAMPLER2DSHADOW:
+ case Parser::T_SAMPLERCUBESHADOW:
+ case Parser::T_SAMPLER1DARRAY:
+ case Parser::T_SAMPLER2DARRAY:
+ case Parser::T_SAMPLER1DARRAYSHADOW:
+ case Parser::T_SAMPLER2DARRAYSHADOW:
+ case Parser::T_SAMPLERCUBEARRAY:
+ case Parser::T_SAMPLERCUBEARRAYSHADOW:
+ case Parser::T_SAMPLER2DRECT:
+ case Parser::T_SAMPLER2DRECTSHADOW:
+ case Parser::T_SAMPLERBUFFER:
+ case Parser::T_SAMPLER2DMS:
+ case Parser::T_SAMPLER2DMSARRAY:
+ case Parser::T_ISAMPLER1D:
+ case Parser::T_ISAMPLER2D:
+ case Parser::T_ISAMPLER3D:
+ case Parser::T_ISAMPLERCUBE:
+ case Parser::T_ISAMPLER1DARRAY:
+ case Parser::T_ISAMPLER2DARRAY:
+ case Parser::T_ISAMPLERCUBEARRAY:
+ case Parser::T_ISAMPLER2DRECT:
+ case Parser::T_ISAMPLERBUFFER:
+ case Parser::T_ISAMPLER2DMS:
+ case Parser::T_ISAMPLER2DMSARRAY:
+ case Parser::T_USAMPLER1D:
+ case Parser::T_USAMPLER2D:
+ case Parser::T_USAMPLER3D:
+ case Parser::T_USAMPLERCUBE:
+ case Parser::T_USAMPLER1DARRAY:
+ case Parser::T_USAMPLER2DARRAY:
+ case Parser::T_USAMPLERCUBEARRAY:
+ case Parser::T_USAMPLER2DRECT:
+ case Parser::T_USAMPLERBUFFER:
+ case Parser::T_USAMPLER2DMS:
+ case Parser::T_USAMPLER2DMSARRAY:
+ _type = _engine->samplerType(ast->token);
+ break;
+
+ default:
+ _engine->error(ast->lineno, QString("Unknown type `%1'").arg(QLatin1String(GLSLParserTable::spell[ast->token])));
+ }
+
+ return false;
+}
+
+bool Semantic::visit(NamedTypeAST *ast)
+{
+ if (ast->name) {
+ if (Symbol *s = _scope->lookup(*ast->name)) {
+ if (Struct *ty = s->asStruct()) {
+ _type = ty;
+ return false;
+ }
+ }
+ _engine->error(ast->lineno, QString("Undefined type `%1'").arg(*ast->name));
+ }
+
+ return false;
+}
+
+bool Semantic::visit(ArrayTypeAST *ast)
+{
+ const Type *elementType = type(ast->elementType);
+ Q_UNUSED(elementType);
+ ExprResult size = expression(ast->size);
+ _type = _engine->arrayType(elementType); // ### ignore the size for now
+ return false;
+}
+
+bool Semantic::visit(StructTypeAST *ast)
+{
+ Struct *s = _engine->newStruct(_scope);
+ if (ast->name)
+ s->setName(*ast->name);
+ if (Scope *e = s->scope())
+ e->add(s);
+ Scope *previousScope = switchScope(s);
+ for (List<StructTypeAST::Field *> *it = ast->fields; it; it = it->next) {
+ StructTypeAST::Field *f = it->value;
+ if (Symbol *member = field(f))
+ s->add(member);
+ }
+ (void) switchScope(previousScope);
+ return false;
+}
+
+bool Semantic::visit(QualifiedTypeAST *ast)
+{
+ _type = type(ast->type);
+ for (List<LayoutQualifier *> *it = ast->layout_list; it; it = it->next) {
+ LayoutQualifier *q = it->value;
+ // q->name;
+ // q->number;
+ Q_UNUSED(q);
+ }
+ return false;
+}
+
+
+// declarations
+bool Semantic::visit(PrecisionDeclarationAST *ast)
+{
+ const Type *ty = type(ast->type);
+ Q_UNUSED(ty);
+ return false;
+}
+
+bool Semantic::visit(ParameterDeclarationAST *ast)
+{
+ Q_UNUSED(ast);
+ Q_ASSERT(!"unreachable");
+ return false;
+}
+
+bool Semantic::visit(VariableDeclarationAST *ast)
+{
+ const Type *ty = type(ast->type);
+ ExprResult initializer = expression(ast->initializer);
+ if (ast->name) {
+ QualifiedTypeAST *qtype = ast->type->asQualifiedType();
+ int qualifiers = 0;
+ if (qtype)
+ qualifiers = qtype->qualifiers;
+ Variable *var = _engine->newVariable(_scope, *ast->name, ty, qualifiers);
+ _scope->add(var);
+ }
+ return false;
+}
+
+bool Semantic::visit(TypeDeclarationAST *ast)
+{
+ const Type *ty = type(ast->type);
+ Q_UNUSED(ty);
+ return false;
+}
+
+bool Semantic::visit(TypeAndVariableDeclarationAST *ast)
+{
+ declaration(ast->typeDecl);
+ declaration(ast->varDecl);
+ return false;
+}
+
+bool Semantic::visit(InvariantDeclarationAST *ast)
+{
+ Q_UNUSED(ast);
+ return false;
+}
+
+bool Semantic::visit(InitDeclarationAST *ast)
+{
+ for (List<DeclarationAST *> *it = ast->decls; it; it = it->next) {
+ DeclarationAST *decl = it->value;
+ declaration(decl);
+ }
+ return false;
+}
+
+bool Semantic::visit(FunctionDeclarationAST *ast)
+{
+ Function *fun = _engine->newFunction(_scope);
+ if (ast->name)
+ fun->setName(*ast->name);
+
+ fun->setReturnType(type(ast->returnType));
+
+ for (List<ParameterDeclarationAST *> *it = ast->params; it; it = it->next) {
+ ParameterDeclarationAST *decl = it->value;
+ parameterDeclaration(decl, fun);
+ }
+
+ if (Scope *enclosingScope = fun->scope())
+ enclosingScope->add(fun);
+
+ Scope *previousScope = switchScope(fun);
+ statement(ast->body);
+ (void) switchScope(previousScope);
+ return false;
+}
+
diff --git a/src/libs/glsl/glslsemantic.h b/src/libs/glsl/glslsemantic.h
new file mode 100644
index 0000000000..49bfe67739
--- /dev/null
+++ b/src/libs/glsl/glslsemantic.h
@@ -0,0 +1,132 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 GLSLSEMANTIC_H
+#define GLSLSEMANTIC_H
+
+#include "glslastvisitor.h"
+#include "glsltype.h"
+
+namespace GLSL {
+
+class GLSL_EXPORT Semantic: protected Visitor
+{
+public:
+ Semantic();
+ virtual ~Semantic();
+
+ struct ExprResult {
+ ExprResult(const Type *type = 0, bool isConstant = false)
+ : type(type), isConstant(isConstant) {}
+
+ bool isValid() const {
+ if (! type)
+ return false;
+ else if (type->asUndefinedType() != 0)
+ return false;
+ return true;
+ }
+
+ operator bool() const { return isValid(); }
+
+ const Type *type;
+ bool isConstant;
+ };
+
+ void translationUnit(TranslationUnitAST *ast, Scope *globalScope, Engine *engine);
+ ExprResult expression(ExpressionAST *ast, Scope *scope, Engine *engine);
+
+protected:
+ Engine *switchEngine(Engine *engine);
+ Scope *switchScope(Scope *scope);
+
+ bool implicitCast(const Type *type, const Type *target) const;
+
+ ExprResult expression(ExpressionAST *ast);
+ void statement(StatementAST *ast);
+ const Type *type(TypeAST *ast);
+ void declaration(DeclarationAST *ast);
+ ExprResult functionIdentifier(FunctionIdentifierAST *ast);
+ Symbol *field(StructTypeAST::Field *ast);
+ void parameterDeclaration(ParameterDeclarationAST *ast, Function *fun);
+
+ virtual bool visit(TranslationUnitAST *ast);
+ virtual bool visit(FunctionIdentifierAST *ast);
+ virtual bool visit(StructTypeAST::Field *ast);
+
+ // expressions
+ virtual bool visit(IdentifierExpressionAST *ast);
+ virtual bool visit(LiteralExpressionAST *ast);
+ virtual bool visit(BinaryExpressionAST *ast);
+ virtual bool visit(UnaryExpressionAST *ast);
+ virtual bool visit(TernaryExpressionAST *ast);
+ virtual bool visit(AssignmentExpressionAST *ast);
+ virtual bool visit(MemberAccessExpressionAST *ast);
+ virtual bool visit(FunctionCallExpressionAST *ast);
+ virtual bool visit(DeclarationExpressionAST *ast);
+
+ // statements
+ virtual bool visit(ExpressionStatementAST *ast);
+ virtual bool visit(CompoundStatementAST *ast);
+ virtual bool visit(IfStatementAST *ast);
+ virtual bool visit(WhileStatementAST *ast);
+ virtual bool visit(DoStatementAST *ast);
+ virtual bool visit(ForStatementAST *ast);
+ virtual bool visit(JumpStatementAST *ast);
+ virtual bool visit(ReturnStatementAST *ast);
+ virtual bool visit(SwitchStatementAST *ast);
+ virtual bool visit(CaseLabelStatementAST *ast);
+ virtual bool visit(DeclarationStatementAST *ast);
+
+ // types
+ virtual bool visit(BasicTypeAST *ast);
+ virtual bool visit(NamedTypeAST *ast);
+ virtual bool visit(ArrayTypeAST *ast);
+ virtual bool visit(StructTypeAST *ast);
+ virtual bool visit(QualifiedTypeAST *ast);
+
+ // declarations
+ virtual bool visit(PrecisionDeclarationAST *ast);
+ virtual bool visit(ParameterDeclarationAST *ast);
+ virtual bool visit(VariableDeclarationAST *ast);
+ virtual bool visit(TypeDeclarationAST *ast);
+ virtual bool visit(TypeAndVariableDeclarationAST *ast);
+ virtual bool visit(InvariantDeclarationAST *ast);
+ virtual bool visit(InitDeclarationAST *ast);
+ virtual bool visit(FunctionDeclarationAST *ast);
+
+private:
+ Engine *_engine;
+ Scope *_scope;
+ const Type *_type;
+ ExprResult _expr;
+};
+
+} // namespace GLSL
+
+#endif // GLSLSEMANTIC_H
diff --git a/src/libs/glsl/glslsymbol.cpp b/src/libs/glsl/glslsymbol.cpp
new file mode 100644
index 0000000000..903ff2bb63
--- /dev/null
+++ b/src/libs/glsl/glslsymbol.cpp
@@ -0,0 +1,82 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "glslsymbol.h"
+#include <QtCore/QStringList>
+
+using namespace GLSL;
+
+Symbol::Symbol(Scope *scope)
+ : _scope(scope)
+{
+}
+
+Symbol::~Symbol()
+{
+}
+
+Scope *Symbol::scope() const
+{
+ return _scope;
+}
+
+void Symbol::setScope(Scope *scope)
+{
+ _scope = scope;
+}
+
+QString Symbol::name() const
+{
+ return _name;
+}
+
+void Symbol::setName(const QString &name)
+{
+ _name = name;
+}
+
+Scope::Scope(Scope *enclosingScope)
+ : Symbol(enclosingScope)
+{
+}
+
+Symbol *Scope::lookup(const QString &name) const
+{
+ if (Symbol *s = find(name))
+ return s;
+ else if (Scope *s = scope())
+ return s->lookup(name);
+ else
+ return 0;
+}
+
+QList<Symbol *> Scope::members() const
+{
+ return QList<Symbol *>();
+}
diff --git a/src/libs/glsl/glslsymbol.h b/src/libs/glsl/glslsymbol.h
new file mode 100644
index 0000000000..6782afb584
--- /dev/null
+++ b/src/libs/glsl/glslsymbol.h
@@ -0,0 +1,85 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 GLSLSYMBOL_H
+#define GLSLSYMBOL_H
+
+#include "glsl.h"
+#include <QtCore/QString>
+
+namespace GLSL {
+
+class Symbol;
+class Scope;
+
+class GLSL_EXPORT Symbol
+{
+public:
+ Symbol(Scope *scope = 0);
+ virtual ~Symbol();
+
+ Scope *scope() const;
+ void setScope(Scope *scope);
+
+ QString name() const;
+ void setName(const QString &name);
+
+ virtual Scope *asScope() { return 0; }
+ virtual Struct *asStruct() { return 0; }
+ virtual Function *asFunction() { return 0; }
+ virtual Argument *asArgument() { return 0; }
+ virtual Block *asBlock() { return 0; }
+ virtual Variable *asVariable() { return 0; }
+ virtual OverloadSet *asOverloadSet() { return 0; }
+ virtual Namespace *asNamespace() { return 0; }
+
+ virtual const Type *type() const = 0;
+
+private:
+ Scope *_scope;
+ QString _name;
+};
+
+class GLSL_EXPORT Scope: public Symbol
+{
+public:
+ Scope(Scope *sscope = 0);
+
+ Symbol *lookup(const QString &name) const;
+
+ virtual QList<Symbol *> members() const;
+ virtual void add(Symbol *symbol) = 0;
+ virtual Symbol *find(const QString &name) const = 0;
+
+ virtual Scope *asScope() { return this; }
+};
+
+} // end of namespace GLSL
+
+#endif // GLSLSYMBOL_H
diff --git a/src/libs/glsl/glslsymbols.cpp b/src/libs/glsl/glslsymbols.cpp
new file mode 100644
index 0000000000..2160862917
--- /dev/null
+++ b/src/libs/glsl/glslsymbols.cpp
@@ -0,0 +1,141 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "glsltypes.h"
+#include "glslsymbols.h"
+#include <QtCore/QDebug>
+
+using namespace GLSL;
+
+Argument::Argument(Function *scope)
+ : Symbol(scope)
+ , _type(0)
+{
+}
+
+const Type *Argument::type() const
+{
+ return _type;
+}
+
+void Argument::setType(const Type *type)
+{
+ _type = type;
+}
+
+Block::Block(Scope *enclosingScope)
+ : Scope(enclosingScope)
+{
+}
+
+QList<Symbol *> Block::members() const
+{
+ return _members.values();
+}
+
+void Block::add(Symbol *symbol)
+{
+ _members.insert(symbol->name(), symbol);
+}
+
+const Type *Block::type() const
+{
+ // ### assert?
+ return 0;
+}
+
+Symbol *Block::find(const QString &name) const
+{
+ return _members.value(name);
+}
+
+Variable::Variable(Scope *scope)
+ : Symbol(scope)
+ , _type(0)
+ , _qualifiers(0)
+{
+}
+
+const Type *Variable::type() const
+{
+ return _type;
+}
+
+void Variable::setType(const Type *type)
+{
+ _type = type;
+}
+
+Namespace::Namespace()
+{
+}
+
+Namespace::~Namespace()
+{
+ qDeleteAll(_overloadSets);
+}
+
+QList<Symbol *> Namespace::members() const
+{
+ return _members.values();
+}
+
+void Namespace::add(Symbol *symbol)
+{
+ Symbol *&sym = _members[symbol->name()];
+ if (! sym)
+ sym = symbol;
+ else if (Function *fun = symbol->asFunction()) {
+ if (OverloadSet *o = sym->asOverloadSet()) {
+ o->addFunction(fun);
+ } else if (Function *firstFunction = sym->asFunction()) {
+ OverloadSet *o = new OverloadSet(this);
+ _overloadSets.append(o);
+ o->setName(symbol->name());
+ o->addFunction(firstFunction);
+ o->addFunction(fun);
+ sym = o;
+ }
+ else {
+ // ### warning? return false?
+ }
+ } else {
+ // ### warning? return false?
+ }
+}
+
+const Type *Namespace::type() const
+{
+ return 0;
+}
+
+Symbol *Namespace::find(const QString &name) const
+{
+ return _members.value(name);
+}
diff --git a/src/libs/glsl/glslsymbols.h b/src/libs/glsl/glslsymbols.h
new file mode 100644
index 0000000000..bf610dd3a2
--- /dev/null
+++ b/src/libs/glsl/glslsymbols.h
@@ -0,0 +1,110 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 GLSLSYMBOLS_H
+#define GLSLSYMBOLS_H
+
+#include "glsltype.h"
+#include "glslsymbol.h"
+#include <QtCore/QVector>
+#include <QtCore/QString>
+#include <QtCore/QHash>
+
+namespace GLSL {
+
+class GLSL_EXPORT Argument: public Symbol
+{
+public:
+ Argument(Function *scope);
+
+ virtual const Type *type() const;
+ void setType(const Type *type);
+
+ virtual Argument *asArgument() { return this; }
+
+private:
+ const Type *_type;
+};
+
+class GLSL_EXPORT Variable: public Symbol
+{
+public:
+ Variable(Scope *scope);
+
+ virtual const Type *type() const;
+ void setType(const Type *type);
+
+ int qualifiers() const { return _qualifiers; }
+ void setQualifiers(int qualifiers) { _qualifiers = qualifiers; }
+
+ virtual Variable *asVariable() { return this; }
+
+private:
+ const Type *_type;
+ int _qualifiers;
+};
+
+class GLSL_EXPORT Block: public Scope
+{
+public:
+ Block(Scope *enclosingScope = 0);
+
+ virtual QList<Symbol *> members() const;
+ virtual void add(Symbol *symbol);
+
+ virtual Block *asBlock() { return this; }
+
+ virtual const Type *type() const;
+ virtual Symbol *find(const QString &name) const;
+
+private:
+ QHash<QString, Symbol *> _members;
+};
+
+class GLSL_EXPORT Namespace: public Scope
+{
+public:
+ Namespace();
+ virtual ~Namespace();
+
+ void add(Symbol *symbol);
+
+ virtual Namespace *asNamespace() { return this; }
+
+ virtual QList<Symbol *> members() const;
+ virtual const Type *type() const;
+ virtual Symbol *find(const QString &name) const;
+
+private:
+ QHash<QString, Symbol *> _members;
+ QVector<OverloadSet *> _overloadSets;
+};
+
+} // end of namespace GLSL
+
+#endif // GLSLSYMBOLS_H
diff --git a/src/libs/glsl/glsltype.cpp b/src/libs/glsl/glsltype.cpp
new file mode 100644
index 0000000000..6f0d0afcc9
--- /dev/null
+++ b/src/libs/glsl/glsltype.cpp
@@ -0,0 +1,37 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "glsltype.h"
+
+using namespace GLSL;
+
+Type::~Type()
+{
+}
+
diff --git a/src/libs/glsl/glsltype.h b/src/libs/glsl/glsltype.h
new file mode 100644
index 0000000000..cc9c8ff94e
--- /dev/null
+++ b/src/libs/glsl/glsltype.h
@@ -0,0 +1,67 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 GLSLTYPE_H
+#define GLSLTYPE_H
+
+#include "glsl.h"
+
+namespace GLSL {
+
+class GLSL_EXPORT Type
+{
+public:
+ virtual ~Type();
+
+ virtual QString toString() const = 0;
+
+ virtual const UndefinedType *asUndefinedType() const { return 0; }
+ virtual const VoidType *asVoidType() const { return 0; }
+ virtual const BoolType *asBoolType() const { return 0; }
+ virtual const IntType *asIntType() const { return 0; }
+ virtual const UIntType *asUIntType() const { return 0; }
+ virtual const FloatType *asFloatType() const { return 0; }
+ virtual const DoubleType *asDoubleType() const { return 0; }
+ virtual const ScalarType *asScalarType() const { return 0; }
+ virtual const IndexType *asIndexType() const { return 0; }
+ virtual const VectorType *asVectorType() const { return 0; }
+ virtual const MatrixType *asMatrixType() const { return 0; }
+ virtual const ArrayType *asArrayType() const { return 0; }
+ virtual const SamplerType *asSamplerType() const { return 0; }
+ virtual const OverloadSet *asOverloadSetType() const { return 0; }
+
+ virtual const Struct *asStructType() const { return 0; }
+ virtual const Function *asFunctionType() const { return 0; }
+
+ virtual bool isEqualTo(const Type *other) const = 0;
+ virtual bool isLessThan(const Type *other) const = 0;
+};
+
+} // end of namespace GLSL
+
+#endif // GLSLTYPE_H
diff --git a/src/libs/glsl/glsltypes.cpp b/src/libs/glsl/glsltypes.cpp
new file mode 100644
index 0000000000..fe66540e62
--- /dev/null
+++ b/src/libs/glsl/glsltypes.cpp
@@ -0,0 +1,525 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "glsltypes.h"
+#include "glslsymbols.h"
+#include "glslengine.h"
+#include "glslparser.h"
+
+using namespace GLSL;
+
+bool UndefinedType::isEqualTo(const Type *other) const
+{
+ if (other && other->asUndefinedType() != 0)
+ return true;
+ return false;
+}
+
+bool UndefinedType::isLessThan(const Type *other) const
+{
+ Q_UNUSED(other);
+ Q_ASSERT(other != 0);
+ Q_ASSERT(other->asUndefinedType() != 0);
+ return false;
+}
+
+bool VoidType::isEqualTo(const Type *other) const
+{
+ if (other && other->asVoidType() != 0)
+ return true;
+ return false;
+}
+
+bool VoidType::isLessThan(const Type *other) const
+{
+ Q_UNUSED(other);
+ Q_ASSERT(other != 0);
+ Q_ASSERT(other->asVoidType() != 0);
+ return false;
+}
+
+bool BoolType::isEqualTo(const Type *other) const
+{
+ if (other && other->asBoolType() != 0)
+ return true;
+ return false;
+}
+
+bool BoolType::isLessThan(const Type *other) const
+{
+ Q_UNUSED(other);
+ Q_ASSERT(other != 0);
+ Q_ASSERT(other->asBoolType() != 0);
+ return false;
+}
+
+bool IntType::isEqualTo(const Type *other) const
+{
+ if (other && other->asIntType() != 0)
+ return true;
+ return false;
+}
+
+bool IntType::isLessThan(const Type *other) const
+{
+ Q_UNUSED(other);
+ Q_ASSERT(other != 0);
+ Q_ASSERT(other->asIntType() != 0);
+ return false;
+}
+
+bool UIntType::isEqualTo(const Type *other) const
+{
+ if (other && other->asUIntType() != 0)
+ return true;
+ return false;
+}
+
+bool UIntType::isLessThan(const Type *other) const
+{
+ Q_UNUSED(other);
+ Q_ASSERT(other != 0);
+ Q_ASSERT(other->asUIntType() != 0);
+ return false;
+}
+
+bool FloatType::isEqualTo(const Type *other) const
+{
+ if (other && other->asFloatType() != 0)
+ return true;
+ return false;
+}
+
+bool FloatType::isLessThan(const Type *other) const
+{
+ Q_UNUSED(other);
+ Q_ASSERT(other != 0);
+ Q_ASSERT(other->asFloatType() != 0);
+ return false;
+}
+
+bool DoubleType::isEqualTo(const Type *other) const
+{
+ if (other && other->asDoubleType() != 0)
+ return true;
+ return false;
+}
+
+bool DoubleType::isLessThan(const Type *other) const
+{
+ Q_UNUSED(other);
+ Q_ASSERT(other != 0);
+ Q_ASSERT(other->asDoubleType() != 0);
+ return false;
+}
+
+QString VectorType::toString() const
+{
+ const char *prefix = "";
+ if (elementType()->asBoolType() != 0)
+ prefix = "b";
+ else if (elementType()->asIntType() != 0)
+ prefix = "i'";
+ else if (elementType()->asUIntType() != 0)
+ prefix = "u";
+ else if (elementType()->asDoubleType() != 0)
+ prefix = "d";
+ return QString("%1vec%2").arg(QLatin1String(prefix)).arg(_dimension);
+}
+
+void VectorType::add(Symbol *symbol)
+{
+ _members.insert(symbol->name(), symbol);
+}
+
+Symbol *VectorType::find(const QString &name) const
+{
+ return _members.value(name);
+}
+
+void VectorType::populateMembers(Engine *engine)
+{
+ if (_members.isEmpty()) {
+ populateMembers(engine, "xyzw");
+ populateMembers(engine, "rgba");
+ populateMembers(engine, "stpq");
+ }
+}
+
+void VectorType::populateMembers(Engine *engine, const char *components)
+{
+ // Single component swizzles.
+ for (int x = 0; x < _dimension; ++x) {
+ const QString *name = engine->identifier(components + x, 1);
+ add(engine->newVariable(this, *name, elementType()));
+ }
+
+ // Two component swizzles.
+ const Type *vec2Type;
+ if (_dimension == 2)
+ vec2Type = this;
+ else
+ vec2Type = engine->vectorType(elementType(), 2);
+ for (int x = 0; x < _dimension; ++x) {
+ for (int y = 0; y < _dimension; ++y) {
+ QString name;
+ name += QLatin1Char(components[x]);
+ name += QLatin1Char(components[y]);
+ add(engine->newVariable
+ (this, *engine->identifier(name), vec2Type));
+ }
+ }
+
+ // Three component swizzles.
+ const Type *vec3Type;
+ if (_dimension == 3)
+ vec3Type = this;
+ else if (_dimension < 3)
+ return;
+ else
+ vec3Type = engine->vectorType(elementType(), 3);
+ for (int x = 0; x < _dimension; ++x) {
+ for (int y = 0; y < _dimension; ++y) {
+ for (int z = 0; z < _dimension; ++z) {
+ QString name;
+ name += QLatin1Char(components[x]);
+ name += QLatin1Char(components[y]);
+ name += QLatin1Char(components[z]);
+ add(engine->newVariable
+ (this, *engine->identifier(name), vec3Type));
+ }
+ }
+ }
+
+ // Four component swizzles.
+ if (_dimension != 4)
+ return;
+ for (int x = 0; x < _dimension; ++x) {
+ for (int y = 0; y < _dimension; ++y) {
+ for (int z = 0; z < _dimension; ++z) {
+ for (int w = 0; w < _dimension; ++w) {
+ QString name;
+ name += QLatin1Char(components[x]);
+ name += QLatin1Char(components[y]);
+ name += QLatin1Char(components[z]);
+ name += QLatin1Char(components[w]);
+ add(engine->newVariable
+ (this, *engine->identifier(name), this));
+ }
+ }
+ }
+ }
+}
+
+bool VectorType::isEqualTo(const Type *other) const
+{
+ if (other) {
+ if (const VectorType *v = other->asVectorType()) {
+ if (_dimension != v->dimension())
+ return false;
+ else if (elementType() != v->elementType())
+ return false;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool VectorType::isLessThan(const Type *other) const
+{
+ Q_ASSERT(other != 0);
+ const VectorType *vec = other->asVectorType();
+ Q_ASSERT(vec != 0);
+ if (_dimension < vec->dimension())
+ return true;
+ else if (_dimension == vec->dimension() && elementType() < vec->elementType())
+ return true;
+ return false;
+}
+
+QString MatrixType::toString() const
+{
+ const char *prefix = "";
+ if (elementType()->asBoolType() != 0)
+ prefix = "b";
+ else if (elementType()->asIntType() != 0)
+ prefix = "i";
+ else if (elementType()->asUIntType() != 0)
+ prefix = "u";
+ else if (elementType()->asDoubleType() != 0)
+ prefix = "d";
+ return QString("%1mat%2x%3").arg(QLatin1String(prefix)).arg(_columns).arg(_rows);
+}
+
+bool MatrixType::isEqualTo(const Type *other) const
+{
+ if (other) {
+ if (const MatrixType *v = other->asMatrixType()) {
+ if (_columns != v->columns())
+ return false;
+ else if (_rows != v->rows())
+ return false;
+ else if (_elementType != v->elementType())
+ return false;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool MatrixType::isLessThan(const Type *other) const
+{
+ Q_ASSERT(other != 0);
+ const MatrixType *mat = other->asMatrixType();
+ Q_ASSERT(mat != 0);
+ if (_columns < mat->columns())
+ return true;
+ else if (_columns == mat->columns()) {
+ if (_rows < mat->rows())
+ return true;
+ else if (_rows == mat->rows() && _elementType < mat->elementType())
+ return true;
+ }
+ return false;
+}
+
+QString ArrayType::toString() const
+{
+ return elementType()->toString() + QLatin1String("[]");
+}
+
+bool ArrayType::isEqualTo(const Type *other) const
+{
+ if (other) {
+ if (const ArrayType *array = other->asArrayType())
+ return elementType()->isEqualTo(array->elementType());
+ }
+ return false;
+}
+
+bool ArrayType::isLessThan(const Type *other) const
+{
+ Q_ASSERT(other != 0);
+ const ArrayType *array = other->asArrayType();
+ Q_ASSERT(array != 0);
+ return elementType() < array->elementType();
+}
+
+QList<Symbol *> Struct::members() const
+{
+ QList<Symbol *> m;
+ foreach (Symbol *s, _members) {
+ if (! s->name().isEmpty())
+ m.append(s);
+ }
+ return m;
+}
+
+void Struct::add(Symbol *member)
+{
+ _members.append(member);
+}
+
+Symbol *Struct::find(const QString &name) const
+{
+ foreach (Symbol *s, _members) {
+ if (s->name() == name)
+ return s;
+ }
+ return 0;
+}
+
+bool Struct::isEqualTo(const Type *other) const
+{
+ Q_UNUSED(other);
+ return false;
+}
+
+bool Struct::isLessThan(const Type *other) const
+{
+ Q_UNUSED(other);
+ return false;
+}
+
+
+QString Function::toString() const
+{
+ return prettyPrint(-1);
+}
+
+QString Function::prettyPrint(int currentArgument) const
+{
+ QString proto;
+ proto += _returnType->toString();
+ proto += QLatin1Char(' ');
+ proto += name();
+ proto += QLatin1Char('(');
+ for (int i = 0; i < _arguments.size(); ++i) {
+ if (i != 0)
+ proto += QLatin1String(", ");
+ if (currentArgument == i)
+ proto += QLatin1String("<b>");
+ Argument *arg = _arguments.at(i);
+ proto += arg->type()->toString();
+ proto += QLatin1Char(' ');
+ proto += arg->name();
+ if (currentArgument == i)
+ proto += QLatin1String("</b>");
+ }
+ proto += QLatin1Char(')');
+ return proto;
+}
+
+const Type *Function::returnType() const
+{
+ return _returnType;
+}
+
+void Function::setReturnType(const Type *returnType)
+{
+ _returnType = returnType;
+}
+
+QVector<Argument *> Function::arguments() const
+{
+ return _arguments;
+}
+
+void Function::addArgument(Argument *arg)
+{
+ _arguments.append(arg);
+}
+
+int Function::argumentCount() const
+{
+ return _arguments.size();
+}
+
+Argument *Function::argumentAt(int index) const
+{
+ return _arguments.at(index);
+}
+
+bool Function::isEqualTo(const Type *other) const
+{
+ Q_UNUSED(other);
+ return false;
+}
+
+bool Function::isLessThan(const Type *other) const
+{
+ Q_UNUSED(other);
+ return false;
+}
+
+QList<Symbol *> Function::members() const
+{
+ QList<Symbol *> m;
+ foreach (Argument *arg, _arguments) {
+ if (! arg->name().isEmpty())
+ m.append(arg);
+ }
+ return m;
+}
+
+Symbol *Function::find(const QString &name) const
+{
+ foreach (Argument *arg, _arguments) {
+ if (arg->name() == name)
+ return arg;
+ }
+ return 0;
+}
+
+QString SamplerType::toString() const
+{
+ return QLatin1String(Parser::spell[_kind]);
+}
+
+bool SamplerType::isEqualTo(const Type *other) const
+{
+ if (other) {
+ if (const SamplerType *samp = other->asSamplerType())
+ return _kind == samp->kind();
+ }
+ return false;
+}
+
+bool SamplerType::isLessThan(const Type *other) const
+{
+ Q_ASSERT(other != 0);
+ const SamplerType *samp = other->asSamplerType();
+ Q_ASSERT(samp != 0);
+ return _kind < samp->kind();
+}
+
+OverloadSet::OverloadSet(Scope *enclosingScope)
+ : Scope(enclosingScope)
+{
+}
+
+QVector<Function *> OverloadSet::functions() const
+{
+ return _functions;
+}
+
+void OverloadSet::addFunction(Function *function)
+{
+ _functions.append(function);
+}
+
+const Type *OverloadSet::type() const
+{
+ return this;
+}
+
+Symbol *OverloadSet::find(const QString &) const
+{
+ return 0;
+}
+
+void OverloadSet::add(Symbol *symbol)
+{
+ if (symbol) {
+ if (Function *fun = symbol->asFunction())
+ addFunction(fun);
+ }
+}
+
+bool OverloadSet::isEqualTo(const Type *other) const
+{
+ Q_UNUSED(other);
+ return false;
+}
+
+bool OverloadSet::isLessThan(const Type *other) const
+{
+ Q_UNUSED(other);
+ return false;
+}
diff --git a/src/libs/glsl/glsltypes.h b/src/libs/glsl/glsltypes.h
new file mode 100644
index 0000000000..1b81f20e6e
--- /dev/null
+++ b/src/libs/glsl/glsltypes.h
@@ -0,0 +1,297 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 GLSLTYPES_H
+#define GLSLTYPES_H
+
+#include "glsltype.h"
+#include "glslsymbol.h"
+#include <QtCore/QVector>
+#include <QtCore/QHash>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+
+namespace GLSL {
+
+class GLSL_EXPORT ScalarType: public Type
+{
+public:
+ virtual const ScalarType *asScalarType() const { return this; }
+};
+
+class GLSL_EXPORT UndefinedType: public Type
+{
+public:
+ virtual QString toString() const { return QLatin1String("undefined"); }
+ virtual const UndefinedType *asUndefinedType() const { return this; }
+ virtual bool isEqualTo(const Type *other) const;
+ virtual bool isLessThan(const Type *other) const;
+};
+
+class GLSL_EXPORT VoidType: public Type
+{
+public:
+ virtual QString toString() const { return QLatin1String("void"); }
+ virtual const VoidType *asVoidType() const { return this; }
+ virtual bool isEqualTo(const Type *other) const;
+ virtual bool isLessThan(const Type *other) const;
+};
+
+class GLSL_EXPORT BoolType: public ScalarType
+{
+public:
+ virtual QString toString() const { return QLatin1String("bool"); }
+ virtual const BoolType *asBoolType() const { return this; }
+ virtual bool isEqualTo(const Type *other) const;
+ virtual bool isLessThan(const Type *other) const;
+};
+
+class GLSL_EXPORT IntType: public ScalarType
+{
+public:
+ virtual QString toString() const { return QLatin1String("int"); }
+ virtual const IntType *asIntType() const { return this; }
+ virtual bool isEqualTo(const Type *other) const;
+ virtual bool isLessThan(const Type *other) const;
+};
+
+class GLSL_EXPORT UIntType: public ScalarType
+{
+public:
+ virtual QString toString() const { return QLatin1String("uint"); }
+ virtual const UIntType *asUIntType() const { return this; }
+ virtual bool isEqualTo(const Type *other) const;
+ virtual bool isLessThan(const Type *other) const;
+};
+
+class GLSL_EXPORT FloatType: public ScalarType
+{
+public:
+ virtual QString toString() const { return QLatin1String("float"); }
+ virtual const FloatType *asFloatType() const { return this; }
+ virtual bool isEqualTo(const Type *other) const;
+ virtual bool isLessThan(const Type *other) const;
+};
+
+class GLSL_EXPORT DoubleType: public ScalarType
+{
+public:
+ virtual QString toString() const { return QLatin1String("double"); }
+ virtual const DoubleType *asDoubleType() const { return this; }
+ virtual bool isEqualTo(const Type *other) const;
+ virtual bool isLessThan(const Type *other) const;
+};
+
+// Type that can be indexed with the [] operator.
+class GLSL_EXPORT IndexType: public Type
+{
+public:
+ IndexType(const Type *indexElementType) : _indexElementType(indexElementType) {}
+
+ const Type *indexElementType() const { return _indexElementType; }
+
+ virtual const IndexType *asIndexType() const { return this; }
+
+private:
+ const Type *_indexElementType;
+};
+
+class GLSL_EXPORT VectorType: public IndexType, public Scope
+{
+public:
+ VectorType(const Type *elementType, int dimension)
+ : IndexType(elementType), _dimension(dimension) {}
+
+ virtual QString toString() const;
+ const Type *elementType() const { return indexElementType(); }
+ int dimension() const { return _dimension; }
+
+ QList<Symbol *> members() const { return _members.values(); }
+
+ virtual void add(Symbol *symbol);
+ virtual Symbol *find(const QString &name) const;
+ virtual const Type *type() const { return this; }
+
+ virtual const VectorType *asVectorType() const { return this; }
+ virtual bool isEqualTo(const Type *other) const;
+ virtual bool isLessThan(const Type *other) const;
+
+private:
+ int _dimension;
+ QHash<QString, Symbol *> _members;
+
+ friend class Engine;
+
+ void populateMembers(Engine *engine);
+ void populateMembers(Engine *engine, const char *components);
+};
+
+class GLSL_EXPORT MatrixType: public IndexType
+{
+public:
+ MatrixType(const Type *elementType, int columns, int rows, const Type *columnType)
+ : IndexType(columnType), _elementType(elementType), _columns(columns), _rows(rows) {}
+
+ const Type *elementType() const { return _elementType; }
+ const Type *columnType() const { return indexElementType(); }
+ int columns() const { return _columns; }
+ int rows() const { return _rows; }
+
+ virtual QString toString() const;
+ virtual const MatrixType *asMatrixType() const { return this; }
+ virtual bool isEqualTo(const Type *other) const;
+ virtual bool isLessThan(const Type *other) const;
+
+private:
+ const Type *_elementType;
+ int _columns;
+ int _rows;
+};
+
+class GLSL_EXPORT ArrayType: public IndexType
+{
+public:
+ explicit ArrayType(const Type *elementType)
+ : IndexType(elementType) {}
+
+ const Type *elementType() const { return indexElementType(); }
+
+ virtual QString toString() const;
+ virtual const ArrayType *asArrayType() const { return this; }
+ virtual bool isEqualTo(const Type *other) const;
+ virtual bool isLessThan(const Type *other) const;
+};
+
+class GLSL_EXPORT Struct: public Type, public Scope
+{
+public:
+ Struct(Scope *scope = 0)
+ : Scope(scope) {}
+
+ QList<Symbol *> members() const;
+ virtual void add(Symbol *member);
+ virtual Symbol *find(const QString &name) const;
+
+ // as Type
+ virtual QString toString() const { return name(); }
+ virtual const Struct *asStructType() const { return this; }
+ virtual bool isEqualTo(const Type *other) const;
+ virtual bool isLessThan(const Type *other) const;
+
+ // as Symbol
+ virtual Struct *asStruct() { return this; } // as Symbol
+ virtual const Type *type() const { return this; }
+
+private:
+ QVector<Symbol *> _members;
+};
+
+class GLSL_EXPORT Function: public Type, public Scope
+{
+public:
+ Function(Scope *scope = 0)
+ : Scope(scope) {}
+
+ const Type *returnType() const;
+ void setReturnType(const Type *returnType);
+
+ QVector<Argument *> arguments() const;
+ void addArgument(Argument *arg);
+ int argumentCount() const;
+ Argument *argumentAt(int index) const;
+
+ // as Type
+ QString prettyPrint(int currentArgument) const;
+ virtual QString toString() const;
+ virtual const Function *asFunctionType() const { return this; }
+ virtual bool isEqualTo(const Type *other) const;
+ virtual bool isLessThan(const Type *other) const;
+
+ // as Symbol
+ virtual Function *asFunction() { return this; }
+ virtual const Type *type() const { return this; }
+
+ virtual Symbol *find(const QString &name) const;
+
+ virtual QList<Symbol *> members() const;
+ virtual void add(Symbol *symbol) {
+ if (! symbol)
+ return;
+ else if (Argument *arg = symbol->asArgument())
+ addArgument(arg);
+ }
+
+private:
+ const Type *_returnType;
+ QVector<Argument *> _arguments;
+};
+
+class GLSL_EXPORT SamplerType: public Type
+{
+public:
+ explicit SamplerType(int kind) : _kind(kind) {}
+
+ // Kind of sampler as a token code; e.g. T_SAMPLER2D.
+ int kind() const { return _kind; }
+
+ virtual QString toString() const;
+ virtual const SamplerType *asSamplerType() const { return this; }
+ virtual bool isEqualTo(const Type *other) const;
+ virtual bool isLessThan(const Type *other) const;
+
+private:
+ int _kind;
+};
+
+class GLSL_EXPORT OverloadSet: public Type, public Scope
+{
+public:
+ OverloadSet(Scope *enclosingScope = 0);
+
+ QVector<Function *> functions() const;
+ void addFunction(Function *function);
+
+ // as symbol
+ virtual OverloadSet *asOverloadSet() { return this; }
+ virtual const Type *type() const;
+ virtual Symbol *find(const QString &name) const;
+ virtual void add(Symbol *symbol);
+
+ // as type
+ virtual QString toString() const { return QLatin1String("overload"); }
+ virtual const OverloadSet *asOverloadSetType() const { return this; }
+ virtual bool isEqualTo(const Type *other) const;
+ virtual bool isLessThan(const Type *other) const;
+
+private:
+ QVector<Function *> _functions;
+};
+
+} // end of namespace GLSL
+
+#endif // GLSLTYPES_H
diff --git a/src/libs/glsl/make-parser.sh b/src/libs/glsl/make-parser.sh
new file mode 100755
index 0000000000..bc76b6c0ed
--- /dev/null
+++ b/src/libs/glsl/make-parser.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+me=$(dirname $0)
+qlalr --qt --no-debug $me/glsl.g
+
diff --git a/src/libs/glsl/specs/glsl.keywords b/src/libs/glsl/specs/glsl.keywords
new file mode 100644
index 0000000000..fbbee6cdbf
--- /dev/null
+++ b/src/libs/glsl/specs/glsl.keywords
@@ -0,0 +1,134 @@
+#include "glsllexer.h"
+#include "glslparser.h"
+
+%no-enums
+%token-prefix=T_
+%toupper
+%namespace=Parser
+%lexer-class=Lexer
+%variant-prefix=Lexer::Variant_
+
+using namespace GLSL;
+
+%%
+
+attribute %variant VertexShader
+bool
+break
+bvec2
+bvec3
+bvec4
+case %variant GLSL_150
+centroid %variant GLSL_120
+const
+continue
+default %variant GLSL_150
+discard %variant FragmentShader
+dmat2 %variant GLSL_400
+dmat2x2 %variant GLSL_400
+dmat2x3 %variant GLSL_400
+dmat2x4 %variant GLSL_400
+dmat3 %variant GLSL_400
+dmat3x2 %variant GLSL_400
+dmat3x3 %variant GLSL_400
+dmat3x4 %variant GLSL_400
+dmat4 %variant GLSL_400
+dmat4x2 %variant GLSL_400
+dmat4x3 %variant GLSL_400
+dmat4x4 %variant GLSL_400
+do
+double %variant GLSL_400
+dvec2 %variant GLSL_400
+dvec3 %variant GLSL_400
+dvec4 %variant GLSL_400
+else
+flat %variant GLSL_150
+float
+for
+highp %variant GLSL_ES_100 | GLSL_400
+if
+in
+inout
+int
+invariant
+isampler1D %variant GLSL_150
+isampler1DArray %variant GLSL_150
+isampler2D %variant GLSL_150
+isampler2DArray %variant GLSL_150
+isampler2DMS %variant GLSL_150
+isampler2DMSArray %variant GLSL_150
+isampler2DRect %variant GLSL_150
+isampler3D %variant GLSL_150
+isamplerBuffer %variant GLSL_150
+isamplerCube %variant GLSL_150
+isamplerCubeArray %variant GLSL_400
+ivec2
+ivec3
+ivec4
+layout %variant GLSL_150
+lowp %variant GLSL_ES_100 | GLSL_400
+mat2
+mat2x2 %variant GLSL_120
+mat2x3 %variant GLSL_120
+mat2x4 %variant GLSL_120
+mat3
+mat3x2 %variant GLSL_120
+mat3x3 %variant GLSL_120
+mat3x4 %variant GLSL_120
+mat4
+mat4x2 %variant GLSL_120
+mat4x3 %variant GLSL_120
+mat4x4 %variant GLSL_120
+mediump %variant GLSL_ES_100 | GLSL_400
+noperspective %variant GLSL_150
+out
+patch %variant GLSL_400
+precision %variant GLSL_ES_100
+return
+sample %variant Reserved
+sampler1D %variant GLSL_120
+sampler1DArray %variant GLSL_150
+sampler1DArrayShadow %variant GLSL_150
+sampler1DShadow %variant GLSL_120
+sampler2D
+sampler2DArray %variant GLSL_150
+sampler2DArrayShadow %variant GLSL_150
+sampler2DMS %variant GLSL_150
+sampler2DMSArray %variant GLSL_150
+sampler2DRect %variang GLSL_150
+sampler2DRectShadow %variang GLSL_150
+sampler2DShadow %variant GLSL_120
+sampler3D %variant GLSL_120
+samplerBuffer %variant GLSL_150
+samplerCube
+samplerCubeArray %variant GLSL_400
+samplerCubeArrayShadow %variant GLSL_400
+samplerCubeShadow %variant GLSL_400
+smooth %variant GLSL_150
+struct
+subroutine %variant GLSL_400
+switch %variant GLSL_150
+uint %variant GLSL_150
+uniform
+usampler1D %variant GLSL_150
+usampler1DArray %variant GLSL_150
+usampler2D %variant GLSL_150
+usampler2DArray %variant GLSL_150
+usampler2DMS %variant GLSL_150
+usampler2DMSarray %variant GLSL_150
+usampler2DRect %variant GLSL_150
+usampler3D %variant GLSL_150
+usamplerBuffer %variant GLSL_150
+usamplerCube %variant GLSL_150
+usamplerCubeArray %variant GLSL_400
+uvec2 %variant GLSL_150
+uvec3 %variant GLSL_150
+uvec4 %variant GLSL_150
+varying
+vec2
+vec3
+vec4
+void
+while
+true
+false
diff --git a/src/libs/glsl/specs/grammar.txt b/src/libs/glsl/specs/grammar.txt
new file mode 100644
index 0000000000..751e735fc0
--- /dev/null
+++ b/src/libs/glsl/specs/grammar.txt
@@ -0,0 +1,312 @@
+variable_identifier ::= IDENTIFIER ;
+primary_expression ::= NUMBER ;
+primary_expression ::= TRUE ;
+primary_expression ::= FALSE ;
+primary_expression ::= variable_identifier ;
+primary_expression ::= LEFT_PAREN expression RIGHT_PAREN ;
+postfix_expression ::= primary_expression ;
+postfix_expression ::= postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET ;
+postfix_expression ::= function_call ;
+postfix_expression ::= postfix_expression DOT IDENTIFIER ;
+postfix_expression ::= postfix_expression INC_OP ;
+postfix_expression ::= postfix_expression DEC_OP ;
+integer_expression ::= expression ;
+function_call ::= function_call_or_method ;
+function_call_or_method ::= function_call_generic ;
+function_call_or_method ::= postfix_expression DOT function_call_generic ;
+function_call_generic ::= function_call_header_with_parameters RIGHT_PAREN ;
+function_call_generic ::= function_call_header_no_parameters RIGHT_PAREN ;
+function_call_header_no_parameters ::= function_call_header VOID ;
+function_call_header_no_parameters ::= function_call_header ;
+function_call_header_with_parameters ::= function_call_header assignment_expression ;
+function_call_header_with_parameters ::= function_call_header_with_parameters COMMA assignment_expression ;
+function_call_header ::= function_identifier LEFT_PAREN ;
+function_identifier ::= type_specifier ;
+function_identifier ::= IDENTIFIER ;
+unary_expression ::= postfix_expression ;
+unary_expression ::= INC_OP unary_expression ;
+unary_expression ::= DEC_OP unary_expression ;
+unary_expression ::= unary_operator unary_expression ;
+unary_operator ::= PLUS ;
+unary_operator ::= DASH ;
+unary_operator ::= BANG ;
+unary_operator ::= TILDE ;
+multiplicative_expression ::= unary_expression ;
+multiplicative_expression ::= multiplicative_expression STAR unary_expression ;
+multiplicative_expression ::= multiplicative_expression SLASH unary_expression ;
+multiplicative_expression ::= multiplicative_expression PERCENT unary_expression ;
+additive_expression ::= multiplicative_expression ;
+additive_expression ::= additive_expression PLUS multiplicative_expression ;
+additive_expression ::= additive_expression DASH multiplicative_expression ;
+shift_expression ::= additive_expression ;
+shift_expression ::= shift_expression LEFT_OP additive_expression ;
+shift_expression ::= shift_expression RIGHT_OP additive_expression ;
+relational_expression ::= shift_expression ;
+relational_expression ::= relational_expression LEFT_ANGLE shift_expression ;
+relational_expression ::= relational_expression RIGHT_ANGLE shift_expression ;
+relational_expression ::= relational_expression LE_OP shift_expression ;
+relational_expression ::= relational_expression GE_OP shift_expression ;
+equality_expression ::= relational_expression ;
+equality_expression ::= equality_expression EQ_OP relational_expression ;
+equality_expression ::= equality_expression NE_OP relational_expression ;
+and_expression ::= equality_expression ;
+and_expression ::= and_expression AMPERSAND equality_expression ;
+exclusive_or_expression ::= and_expression ;
+exclusive_or_expression ::= exclusive_or_expression CARET and_expression ;
+inclusive_or_expression ::= exclusive_or_expression ;
+inclusive_or_expression ::= inclusive_or_expression VERTICAL_BAR exclusive_or_expression ;
+logical_and_expression ::= inclusive_or_expression ;
+logical_and_expression ::= logical_and_expression AND_OP inclusive_or_expression ;
+logical_xor_expression ::= logical_and_expression ;
+logical_xor_expression ::= logical_xor_expression XOR_OP logical_and_expression ;
+logical_or_expression ::= logical_xor_expression ;
+logical_or_expression ::= logical_or_expression OR_OP logical_xor_expression ;
+conditional_expression ::= logical_or_expression ;
+conditional_expression ::= logical_or_expression QUESTION expression COLON assignment_expression ;
+assignment_expression ::= conditional_expression ;
+assignment_expression ::= unary_expression assignment_operator assignment_expression ;
+assignment_operator ::= EQUAL ;
+assignment_operator ::= MUL_ASSIGN ;
+assignment_operator ::= DIV_ASSIGN ;
+assignment_operator ::= MOD_ASSIGN ;
+assignment_operator ::= ADD_ASSIGN ;
+assignment_operator ::= SUB_ASSIGN ;
+assignment_operator ::= LEFT_ASSIGN ;
+assignment_operator ::= RIGHT_ASSIGN ;
+assignment_operator ::= AND_ASSIGN ;
+assignment_operator ::= XOR_ASSIGN ;
+assignment_operator ::= OR_ASSIGN ;
+expression ::= assignment_expression ;
+expression ::= expression COMMA assignment_expression ;
+constant_expression ::= conditional_expression ;
+declaration ::= function_prototype SEMICOLON ;
+declaration ::= init_declarator_list SEMICOLON ;
+declaration ::= PRECISION precision_qualifier type_specifier_no_prec SEMICOLON ;
+declaration ::= type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE SEMICOLON ;
+declaration ::= type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE IDENTIFIER SEMICOLON ;
+declaration ::= type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE IDENTIFIER LEFT_BRACKET RIGHT_BRACKET SEMICOLON ;
+declaration ::= type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET SEMICOLON ;
+declaration ::= type_qualifier SEMICOLON ;
+function_prototype ::= function_declarator RIGHT_PAREN ;
+function_declarator ::= function_header ;
+function_declarator ::= function_header_with_parameters ;
+function_header_with_parameters ::= function_header parameter_declaration ;
+function_header_with_parameters ::= function_header_with_parameters COMMA parameter_declaration ;
+function_header ::= fully_specified_type IDENTIFIER LEFT_PAREN ;
+parameter_declarator ::= type_specifier IDENTIFIER ;
+parameter_declarator ::= type_specifier IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET ;
+parameter_declaration ::= parameter_type_qualifier parameter_qualifier parameter_declarator ;
+parameter_declaration ::= parameter_qualifier parameter_declarator ;
+parameter_declaration ::= parameter_type_qualifier parameter_qualifier parameter_type_specifier ;
+parameter_declaration ::= parameter_qualifier parameter_type_specifier ;
+parameter_qualifier ::= empty ;
+parameter_qualifier ::= IN ;
+parameter_qualifier ::= OUT ;
+parameter_qualifier ::= INOUT ;
+parameter_type_specifier ::= type_specifier ;
+init_declarator_list ::= single_declaration ;
+init_declarator_list ::= init_declarator_list COMMA IDENTIFIER ;
+init_declarator_list ::= init_declarator_list COMMA IDENTIFIER LEFT_BRACKET RIGHT_BRACKET ;
+init_declarator_list ::= init_declarator_list COMMA IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET ;
+init_declarator_list ::= init_declarator_list COMMA IDENTIFIER LEFT_BRACKET RIGHT_BRACKET EQUAL initializer ;
+init_declarator_list ::= init_declarator_list COMMA IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET EQUAL initializer ;
+init_declarator_list ::= init_declarator_list COMMA IDENTIFIER EQUAL initializer ;
+single_declaration ::= fully_specified_type ;
+single_declaration ::= fully_specified_type IDENTIFIER ;
+single_declaration ::= fully_specified_type IDENTIFIER LEFT_BRACKET RIGHT_BRACKET ;
+single_declaration ::= fully_specified_type IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET ;
+single_declaration ::= fully_specified_type IDENTIFIER LEFT_BRACKET RIGHT_BRACKET EQUAL initializer ;
+single_declaration ::= fully_specified_type IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET EQUAL initializer ;
+single_declaration ::= fully_specified_type IDENTIFIER EQUAL initializer ;
+single_declaration ::= INVARIANT IDENTIFIER ;
+fully_specified_type ::= type_specifier ;
+fully_specified_type ::= type_qualifier type_specifier ;
+invariant_qualifier ::= INVARIANT ;
+interpolation_qualifier ::= SMOOTH ;
+interpolation_qualifier ::= FLAT ;
+interpolation_qualifier ::= NOPERSPECTIVE ;
+layout_qualifier ::= LAYOUT LEFT_PAREN layout_qualifier_id_list RIGHT_PAREN ;
+layout_qualifier_id_list ::= layout_qualifier_id ;
+layout_qualifier_id_list ::= layout_qualifier_id_list COMMA layout_qualifier_id ;
+layout_qualifier_id ::= IDENTIFIER ;
+layout_qualifier_id ::= IDENTIFIER EQUAL NUMBER ;
+parameter_type_qualifier ::= CONST ;
+type_qualifier ::= storage_qualifier ;
+type_qualifier ::= layout_qualifier ;
+type_qualifier ::= layout_qualifier storage_qualifier ;
+type_qualifier ::= interpolation_qualifier storage_qualifier ;
+type_qualifier ::= interpolation_qualifier ;
+type_qualifier ::= invariant_qualifier storage_qualifier ;
+type_qualifier ::= invariant_qualifier interpolation_qualifier storage_qualifier ;
+type_qualifier ::= INVARIANT ;
+storage_qualifier ::= CONST ;
+storage_qualifier ::= ATTRIBUTE ;
+storage_qualifier ::= VARYING ;
+storage_qualifier ::= CENTROID VARYING ;
+storage_qualifier ::= IN ;
+storage_qualifier ::= OUT ;
+storage_qualifier ::= CENTROID IN ;
+storage_qualifier ::= CENTROID OUT ;
+storage_qualifier ::= PATCH IN ;
+storage_qualifier ::= PATCH OUT ;
+storage_qualifier ::= SAMPLE IN ;
+storage_qualifier ::= SAMPLE OUT ;
+storage_qualifier ::= UNIFORM ;
+type_specifier ::= type_specifier_no_prec ;
+type_specifier ::= precision_qualifier type_specifier_no_prec ;
+type_specifier_no_prec ::= type_specifier_nonarray ;
+type_specifier_no_prec ::= type_specifier_nonarray LEFT_BRACKET RIGHT_BRACKET ;
+type_specifier_no_prec ::= type_specifier_nonarray LEFT_BRACKET constant_expression RIGHT_BRACKET ;
+type_specifier_nonarray ::= VOID ;
+type_specifier_nonarray ::= FLOAT ;
+type_specifier_nonarray ::= DOUBLE ;
+type_specifier_nonarray ::= INT ;
+type_specifier_nonarray ::= UINT ;
+type_specifier_nonarray ::= BOOL ;
+type_specifier_nonarray ::= VEC2 ;
+type_specifier_nonarray ::= VEC3 ;
+type_specifier_nonarray ::= VEC4 ;
+type_specifier_nonarray ::= DVEC2 ;
+type_specifier_nonarray ::= DVEC3 ;
+type_specifier_nonarray ::= DVEC4 ;
+type_specifier_nonarray ::= BVEC2 ;
+type_specifier_nonarray ::= BVEC3 ;
+type_specifier_nonarray ::= BVEC4 ;
+type_specifier_nonarray ::= IVEC2 ;
+type_specifier_nonarray ::= IVEC3 ;
+type_specifier_nonarray ::= IVEC4 ;
+type_specifier_nonarray ::= UVEC2 ;
+type_specifier_nonarray ::= UVEC3 ;
+type_specifier_nonarray ::= UVEC4 ;
+type_specifier_nonarray ::= MAT2 ;
+type_specifier_nonarray ::= MAT3 ;
+type_specifier_nonarray ::= MAT4 ;
+type_specifier_nonarray ::= MAT2X2 ;
+type_specifier_nonarray ::= MAT2X3 ;
+type_specifier_nonarray ::= MAT2X4 ;
+type_specifier_nonarray ::= MAT3X2 ;
+type_specifier_nonarray ::= MAT3X3 ;
+type_specifier_nonarray ::= MAT3X4 ;
+type_specifier_nonarray ::= MAT4X2 ;
+type_specifier_nonarray ::= MAT4X3 ;
+type_specifier_nonarray ::= MAT4X4 ;
+type_specifier_nonarray ::= DMAT2 ;
+type_specifier_nonarray ::= DMAT3 ;
+type_specifier_nonarray ::= DMAT4 ;
+type_specifier_nonarray ::= DMAT2X2 ;
+type_specifier_nonarray ::= DMAT2X3 ;
+type_specifier_nonarray ::= DMAT2X4 ;
+type_specifier_nonarray ::= DMAT3X2 ;
+type_specifier_nonarray ::= DMAT3X3 ;
+type_specifier_nonarray ::= DMAT3X4 ;
+type_specifier_nonarray ::= DMAT4X2 ;
+type_specifier_nonarray ::= DMAT4X3 ;
+type_specifier_nonarray ::= DMAT4X4 ;
+type_specifier_nonarray ::= SAMPLER1D ;
+type_specifier_nonarray ::= SAMPLER2D ;
+type_specifier_nonarray ::= SAMPLER3D ;
+type_specifier_nonarray ::= SAMPLERCUBE ;
+type_specifier_nonarray ::= SAMPLER1DSHADOW ;
+type_specifier_nonarray ::= SAMPLER2DSHADOW ;
+type_specifier_nonarray ::= SAMPLERCUBESHADOW ;
+type_specifier_nonarray ::= SAMPLER1DARRAY ;
+type_specifier_nonarray ::= SAMPLER2DARRAY ;
+type_specifier_nonarray ::= SAMPLER1DARRAYSHADOW ;
+type_specifier_nonarray ::= SAMPLER2DARRAYSHADOW ;
+type_specifier_nonarray ::= SAMPLERCUBEARRAY ;
+type_specifier_nonarray ::= SAMPLERCUBEARRAYSHADOW ;
+type_specifier_nonarray ::= ISAMPLER1D ;
+type_specifier_nonarray ::= ISAMPLER2D ;
+type_specifier_nonarray ::= ISAMPLER3D ;
+type_specifier_nonarray ::= ISAMPLERCUBE ;
+type_specifier_nonarray ::= ISAMPLER1DARRAY ;
+type_specifier_nonarray ::= ISAMPLER2DARRAY ;
+type_specifier_nonarray ::= ISAMPLERCUBEARRAY ;
+type_specifier_nonarray ::= USAMPLER1D ;
+type_specifier_nonarray ::= USAMPLER2D ;
+type_specifier_nonarray ::= USAMPLER3D ;
+type_specifier_nonarray ::= USAMPLERCUBE ;
+type_specifier_nonarray ::= USAMPLER1DARRAY ;
+type_specifier_nonarray ::= USAMPLER2DARRAY ;
+type_specifier_nonarray ::= USAMPLERCUBEARRAY ;
+type_specifier_nonarray ::= SAMPLER2DRECT ;
+type_specifier_nonarray ::= SAMPLER2DRECTSHADOW ;
+type_specifier_nonarray ::= ISAMPLER2DRECT ;
+type_specifier_nonarray ::= USAMPLER2DRECT ;
+type_specifier_nonarray ::= SAMPLERBUFFER ;
+type_specifier_nonarray ::= ISAMPLERBUFFER ;
+type_specifier_nonarray ::= USAMPLERBUFFER ;
+type_specifier_nonarray ::= SAMPLER2DMS ;
+type_specifier_nonarray ::= ISAMPLER2DMS ;
+type_specifier_nonarray ::= USAMPLER2DMS ;
+type_specifier_nonarray ::= SAMPLER2DMSARRAY ;
+type_specifier_nonarray ::= ISAMPLER2DMSARRAY ;
+type_specifier_nonarray ::= USAMPLER2DMSARRAY ;
+type_specifier_nonarray ::= struct_specifier ;
+type_specifier_nonarray ::= TYPE_NAME ;
+precision_qualifier ::= HIGHP ;
+precision_qualifier ::= MEDIUMP ;
+precision_qualifier ::= LOWP ;
+struct_specifier ::= STRUCT IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE ;
+struct_specifier ::= STRUCT LEFT_BRACE struct_declaration_list RIGHT_BRACE ;
+struct_declaration_list ::= struct_declaration ;
+struct_declaration_list ::= struct_declaration_list struct_declaration ;
+struct_declaration ::= type_specifier struct_declarator_list SEMICOLON ;
+struct_declaration ::= type_qualifier type_specifier struct_declarator_list SEMICOLON ;
+struct_declarator_list ::= struct_declarator ;
+struct_declarator_list ::= struct_declarator_list COMMA struct_declarator ;
+struct_declarator ::= IDENTIFIER ;
+struct_declarator ::= IDENTIFIER LEFT_BRACKET RIGHT_BRACKET ;
+struct_declarator ::= IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET ;
+initializer ::= assignment_expression ;
+declaration_statement ::= declaration ;
+statement ::= compound_statement ;
+statement ::= simple_statement ;
+simple_statement ::= declaration_statement ;
+simple_statement ::= expression_statement ;
+simple_statement ::= selection_statement ;
+simple_statement ::= switch_statement ;
+simple_statement ::= case_label ;
+simple_statement ::= iteration_statement ;
+simple_statement ::= jump_statement ;
+compound_statement ::= LEFT_BRACE RIGHT_BRACE ;
+compound_statement ::= LEFT_BRACE statement_list RIGHT_BRACE ;
+statement_no_new_scope ::= compound_statement_no_new_scope ;
+statement_no_new_scope ::= simple_statement ;
+compound_statement_no_new_scope ::= LEFT_BRACE RIGHT_BRACE ;
+compound_statement_no_new_scope ::= LEFT_BRACE statement_list RIGHT_BRACE ;
+statement_list ::= statement ;
+statement_list ::= statement_list statement ;
+expression_statement ::= SEMICOLON ;
+expression_statement ::= expression SEMICOLON ;
+selection_statement ::= IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement ;
+selection_rest_statement ::= statement ELSE statement ;
+selection_rest_statement ::= statement ;
+condition ::= expression ;
+condition ::= fully_specified_type IDENTIFIER EQUAL initializer ;
+switch_statement ::= SWITCH LEFT_PAREN expression RIGHT_PAREN LEFT_BRACE switch_statement_list RIGHT_BRACE ;
+switch_statement_list ::= empty ;
+switch_statement_list ::= statement_list ;
+case_label ::= CASE expression COLON ;
+case_label ::= DEFAULT COLON ;
+iteration_statement ::= WHILE LEFT_PAREN condition RIGHT_PAREN statement_no_new_scope ;
+iteration_statement ::= DO statement WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON ;
+iteration_statement ::= FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope ;
+for_init_statement ::= expression_statement ;
+for_init_statement ::= declaration_statement ;
+conditionopt ::= empty ;
+conditionopt ::= condition ;
+for_rest_statement ::= conditionopt SEMICOLON ;
+for_rest_statement ::= conditionopt SEMICOLON expression ;
+jump_statement ::= CONTINUE SEMICOLON ;
+jump_statement ::= BREAK SEMICOLON ;
+jump_statement ::= RETURN SEMICOLON ;
+jump_statement ::= RETURN expression SEMICOLON ;
+jump_statement ::= DISCARD SEMICOLON ;
+translation_unit ::= external_declaration ;
+translation_unit ::= translation_unit external_declaration ;
+external_declaration ::= function_definition ;
+external_declaration ::= declaration ;
+external_declaration ::= SEMICOLON ;
+function_definition ::= function_prototype compound_statement_no_new_scope ;
+empty ::= ;
diff --git a/src/libs/glsl/tests/main.cpp b/src/libs/glsl/tests/main.cpp
new file mode 100644
index 0000000000..11b929f5d1
--- /dev/null
+++ b/src/libs/glsl/tests/main.cpp
@@ -0,0 +1,92 @@
+
+#include <glslengine.h>
+#include <glslparser.h>
+#include <glsllexer.h>
+#include <glslastdump.h>
+#include <glslsemantic.h>
+#include <glslsymbols.h>
+#include <glsltypes.h>
+
+#include <QtCore/QTextStream>
+
+#include <iostream>
+#include <fstream>
+#include <cstring>
+#include <cassert>
+#include <cstdio>
+
+using namespace GLSL;
+
+#ifndef EXIT_FAILURE
+#define EXIT_FAILURE 1
+#endif
+#ifndef EXIT_SUCCESS
+#define EXIT_SUCCESS 0
+#endif
+
+namespace {
+QTextStream qout(stdout, QIODevice::WriteOnly);
+}
+
+int main(int argc, char *argv[])
+{
+ int variant = 0;
+
+ while (argc > 1 && argv[1][0] == '-' && argv[1][1] == '-') {
+ if (!strcmp(argv[1], "--version=1.20")) {
+ variant |= Lexer::Variant_GLSL_120;
+ } else if (!strcmp(argv[1], "--version=1.50")) {
+ variant |= Lexer::Variant_GLSL_150;
+ } else if (!strcmp(argv[1], "--version=4.00")) {
+ variant |= Lexer::Variant_GLSL_400;
+ } else if (!strcmp(argv[1], "--version=es")) {
+ variant |= Lexer::Variant_GLSL_ES_100;
+ } else if (!strcmp(argv[1], "--shader=vertex")) {
+ variant |= Lexer::Variant_VertexShader;
+ } else if (!strcmp(argv[1], "--shader=fragment")) {
+ variant |= Lexer::Variant_FragmentShader;
+ } else {
+ std::cerr << "glsl: unknown option: " << argv[1] << std::endl;
+ return EXIT_FAILURE;
+ }
+ ++argv;
+ --argc;
+ }
+
+ if (argc != 2) {
+ std::cerr << "glsl: no input file" << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ std::ifstream fin(argv[1]);
+ if (! fin) {
+ std::cerr << "glsl: No such file or directory" << std::endl;
+ return EXIT_FAILURE;
+ }
+ fin.seekg(0, std::ios::end);
+ size_t size = fin.tellg();
+ fin.seekg(0, std::ios::beg);
+ char *source = new char[size];
+ fin.read(source, size);
+ fin.close();
+ if (!variant)
+ variant = Lexer::Variant_Mask & ~Lexer::Variant_Reserved;
+ else if ((variant & (Lexer::Variant_VertexShader | Lexer::Variant_FragmentShader)) == 0)
+ variant |= Lexer::Variant_VertexShader | Lexer::Variant_FragmentShader;
+ Engine engine;
+ Parser parser(&engine, source, size, variant);
+ TranslationUnitAST *ast = parser.parse();
+ std::cout << argv[1] << (ast ? " OK " : " KO ") << std::endl;
+
+ ASTDump dump(qout);
+ dump(ast);
+
+ Semantic sem;
+ Scope *globalScope = engine.newNamespace();
+ sem.translationUnit(ast, globalScope, &engine);
+
+ delete source;
+ delete ast;
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/libs/glsl/tests/test.pro b/src/libs/glsl/tests/test.pro
new file mode 100644
index 0000000000..89ead35061
--- /dev/null
+++ b/src/libs/glsl/tests/test.pro
@@ -0,0 +1,14 @@
+TEMPLATE = app
+CONFIG -= app_bundle
+CONFIG += console
+TARGET = glsl
+DEPENDPATH += .
+INCLUDEPATH += . ..
+
+QT = core
+
+# Input
+SOURCES += main.cpp
+
+include(../glsl-lib.pri)
+
diff --git a/src/libs/glsl/tools/kwgen.cpp b/src/libs/glsl/tools/kwgen.cpp
new file mode 100644
index 0000000000..09db56aa1a
--- /dev/null
+++ b/src/libs/glsl/tools/kwgen.cpp
@@ -0,0 +1,406 @@
+/*
+ Copyright 2007 Roberto Raggi <roberto@kdevelop.org>
+
+ Permission to use, copy, modify, distribute, and sell this software and its
+ documentation for any purpose is hereby granted without fee, provided that
+ the above copyright notice appear in all copies and that both that
+ copyright notice and this permission notice appear in supporting
+ documentation.
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ KDEVELOP TEAM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include <string>
+#include <iostream>
+#include <map>
+#include <list>
+#include <vector>
+#include <set>
+#include <cstdlib>
+#include <cctype>
+#include <functional>
+#include <algorithm>
+
+class State;
+class DottedItem;
+
+typedef std::list<std::string> RuleList;
+typedef RuleList::iterator RulePtr;
+typedef std::list<State> StateList;
+typedef StateList::iterator StatePtr;
+typedef std::string::iterator Dot;
+typedef std::vector<DottedItem>::iterator DottedItemPtr;
+
+class DottedItem {
+public:
+ RulePtr rule;
+ Dot dot;
+
+ DottedItem() {}
+
+ DottedItem(RulePtr rule, Dot dot):
+ rule(rule), dot(dot) {}
+
+ bool operator == (const DottedItem &other) const {
+ return rule == other.rule && dot == other.dot;
+ }
+
+ bool operator != (const DottedItem &other) const {
+ return ! operator == (other);
+ }
+
+ bool terminal() const {
+ return dot == rule->end();
+ }
+
+ DottedItem next() const {
+ DottedItem item;
+ item.rule = rule;
+ item.dot = dot;
+ ++item.dot;
+ return item;
+ }
+};
+
+struct State {
+public:
+ State() {}
+
+ template <typename _ForwardIterator>
+ State(_ForwardIterator first, _ForwardIterator last) {
+ _items.insert(_items.end(), first, last);
+ }
+
+ static State &intern(const State &state) {
+ StatePtr ptr = std::find(first_state(), last_state(), state);
+ if (ptr == last_state())
+ ptr = states().insert(last_state(), state);
+ return *ptr;
+ }
+
+ State &next(char ch) {
+ std::vector<DottedItem> n;
+ for (DottedItemPtr it = first_item(); it != last_item(); ++it) {
+ if (! it->terminal() && *it->dot == ch)
+ n.push_back(it->next());
+ }
+ return intern(State(n.begin(), n.end()));
+ }
+
+ std::set<char> firsts() {
+ std::set<char> s;
+ for (DottedItemPtr it = first_item(); it != last_item(); ++it) {
+ if (! it->terminal())
+ s.insert(*it->dot);
+ }
+ return s;
+ }
+
+ size_t item_count() const { return _items.size(); }
+
+ DottedItemPtr first_item() { return _items.begin(); }
+ DottedItemPtr last_item() { return _items.end(); }
+
+ static StatePtr first_state() { return states().begin(); }
+ static StatePtr last_state() { return states().end(); }
+
+ bool operator == (const State &other) const { return _items == other._items; }
+ bool operator != (const State &other) const { return _items != other._items; }
+
+ template <typename _Iterator>
+ static State &start(_Iterator first, _Iterator last) {
+ std::vector<DottedItem> items;
+ for (; first != last; ++first)
+ items.push_back(DottedItem(first, first->begin()));
+ return intern(State(items.begin(), items.end()));
+ }
+
+ static void reset() {
+ states().clear();
+ }
+
+private:
+ static StateList &states() {
+ static StateList _states;
+ return _states;
+ }
+
+private:
+ std::vector<DottedItem> _items;
+};
+
+static bool option_no_enums = false;
+static bool option_toupper = false;
+static std::string option_namespace_name;
+static std::string option_class_name;
+static std::string option_token_prefix = "Token_";
+static std::string option_variant_prefix = "Variant_";
+static std::string option_char_type = "char";
+static std::string option_unicode_function = "";
+static std::map<std::string, std::string> variants;
+
+std::string token_id(const std::string &id)
+{
+ std::string token = option_token_prefix;
+
+ if (! option_toupper)
+ token += id;
+ else {
+ for (size_t i = 0; i < id.size(); ++i)
+ token += toupper(id[i]);
+ }
+
+ return token;
+}
+
+std::string variant_id(const std::string &id)
+{
+ if (variants.find(id) == variants.end())
+ return "";
+ std::string variant = variants[id];
+ size_t posn = 0;
+ bool sep = true;
+ std::string result;
+ while (posn < variant.size()) {
+ char ch = variant[posn++];
+ if (isalnum(ch) || ch == '_') {
+ if (sep) {
+ result += " | " + option_variant_prefix;
+ sep = false;
+ }
+ result += ch;
+ } else if (!sep) {
+ sep = true;
+ }
+ }
+ return result;
+}
+
+bool starts_with(const std::string &line, const std::string &text) {
+ if (text.length() < line.length()) {
+ return std::equal(line.begin(), line.begin() + text.size(), text.begin());
+ }
+ return false;
+}
+
+void doit(State &state)
+{
+ static int depth = 0;
+
+ ++depth;
+
+ std::string indent(depth * 2, ' ');
+
+ std::set<char> firsts = state.firsts();
+ for (std::set<char>::iterator it = firsts.begin(); it != firsts.end(); ++it) {
+ std::string _else = it == firsts.begin() ? "" : "else ";
+ std::cout << indent << _else << "if (s[" << (depth - 1) << "]" << option_unicode_function << " == '" << *it << "') {" << std::endl;
+ State &next_state = state.next(*it);
+
+ bool found = false;
+ for (DottedItemPtr item = next_state.first_item(); item != next_state.last_item(); ++item) {
+ if (item->terminal()) {
+ if (found) {
+ std::cerr << "*** Error. Too many accepting states" << std::endl;
+ exit(EXIT_FAILURE);
+ }
+ found = true;
+ std::cout << indent << " return " << option_namespace_name << token_id(*item->rule) << variant_id(*item->rule) << ";" << std::endl;
+ }
+ }
+
+ if (! found)
+ doit(next_state);
+
+ std::cout << indent << "}" << std::endl;
+ }
+
+ --depth;
+}
+
+void gen_classify_n(State &start_state, int N)
+{
+ std::cout << "static inline int classify" << N << "(const " << option_char_type << " *s) {" << std::endl;
+ doit(start_state);
+ std::cout << " return " << option_namespace_name << token_id("identifier") << ";" << std::endl
+ << "}" << std::endl << std::endl;
+}
+
+void gen_classify(const std::multimap<size_t, std::string> &keywords)
+{
+ std::cout << "int " << option_class_name << "classify(const " << option_char_type << " *s, int n) {" << std::endl
+ << " switch (n) {" << std::endl;
+ std::multimap<size_t, std::string>::const_iterator it = keywords.begin();
+ while (it != keywords.end()) {
+ size_t size = it->first;
+ std::cout << " case " << size << ": return classify" << size << "(s);" << std::endl;
+ do { ++it; } while (it != keywords.end() && it->first == size);
+ }
+ std::cout << " default: return " << option_namespace_name << token_id("identifier") << ";" << std::endl
+ << " } // switch" << std::endl
+ << "}" << std::endl << std::endl;
+}
+
+void gen_keyword_list(const std::multimap<size_t, std::string> &keywords)
+{
+ std::cout << "QStringList " << option_class_name << "keywords(int variant) {" << std::endl
+ << " QStringList list;" << std::endl;
+ std::multimap<size_t, std::string>::const_iterator it = keywords.begin();
+ for (; it != keywords.end(); ++it) {
+ std::string varid = variant_id(it->second);
+ if (varid.empty()) {
+ std::cout << " list += QLatin1String(\"" << it->second << "\");" << std::endl;
+ } else {
+ varid = varid.substr(3);
+ std::cout << " if (variant & (" << varid << "))" << std::endl;
+ std::cout << " list += QLatin1String(\"" << it->second << "\");" << std::endl;
+ }
+ }
+ std::cout << " return list;" << std::endl
+ << "}" << std::endl << std::endl;
+}
+
+void gen_enums(const std::multimap<size_t, std::string> &keywords)
+{
+ std::cout << "enum {" << std::endl;
+ std::multimap<size_t, std::string>::const_iterator it = keywords.begin();
+ for (; it != keywords.end(); ++it) {
+ std::cout << " " << token_id(it->second) << variant_id(it->second) << "," << std::endl;
+ }
+ std::cout << " " << token_id("identifier") << std::endl
+ << "};" << std::endl << std::endl;
+}
+
+inline bool not_whitespace_p(char ch) {
+ return ! std::isspace(ch);
+}
+
+int main(int argc, char *argv[]) {
+ const std::string ns = "--namespace=";
+
+ for (int i = 0; i < argc; ++i) {
+ const std::string arg(argv[i]);
+ if (arg == "--no-enums")
+ option_no_enums = true;
+ else if (starts_with(arg, ns)) {
+ option_namespace_name.assign(arg.begin() + ns.size(), arg.end());
+ option_namespace_name += "::";
+ }
+ }
+
+ std::multimap<size_t, std::string> keywords;
+ std::string textline;
+
+ bool readKeywords = false;
+
+ const std::string opt_no_enums = "%no-enums";
+ const std::string opt_toupper = "%toupper";
+ const std::string opt_ns = "%namespace=";
+ const std::string opt_class = "%lexer-class=";
+ const std::string opt_tok_prefix = "%token-prefix=";
+ const std::string opt_var_prefix = "%variant-prefix=";
+ const std::string opt_char_type = "%char-type=";
+ const std::string opt_unicode_function = "%unicode-function=";
+
+ while (getline(std::cin, textline)) {
+
+ // remove trailing spaces
+ textline.assign(textline.begin(), std::find_if(textline.rbegin(), textline.rend(), not_whitespace_p).base());
+
+ if (! readKeywords) {
+ if (textline.size() >= 2 && textline[0] == '%') {
+ if (textline[1] == '%') {
+ readKeywords = true;
+ } else if (textline == opt_no_enums) {
+ option_no_enums = true;
+ } else if (textline == opt_toupper) {
+ option_toupper = true;
+ } else if (starts_with(textline, opt_tok_prefix)) {
+ option_token_prefix.assign(textline.begin() + opt_tok_prefix.size(), textline.end());
+ } else if (starts_with(textline, opt_var_prefix)) {
+ option_variant_prefix.assign(textline.begin() + opt_var_prefix.size(), textline.end());
+ } else if (starts_with(textline, opt_char_type)) {
+ option_char_type.assign(textline.begin() + opt_char_type.size(), textline.end());
+ } else if (starts_with(textline, opt_unicode_function)) {
+ option_unicode_function.assign(textline.begin() + opt_unicode_function.size(), textline.end());
+ } else if (starts_with(textline, opt_ns)) {
+ option_namespace_name.assign(textline.begin() + opt_ns.size(), textline.end());
+ option_namespace_name += "::";
+ } else if (starts_with(textline, opt_class)) {
+ option_class_name.assign(textline.begin() + opt_class.size(), textline.end());
+ option_class_name += "::";
+ }
+
+ continue;
+ }
+ std::cout << textline << std::endl;
+ } else {
+ if (textline.empty())
+ continue;
+
+ std::string::iterator start = textline.begin();
+ while (start != textline.end() && std::isspace(*start))
+ ++start;
+
+ std::string::iterator stop = start;
+ while (stop != textline.end() && (std::isalnum(*stop) || *stop == '_'))
+ ++stop;
+
+ if (start != stop) {
+ std::string keyword(start, stop);
+ if (keyword == "identifier") {
+ std::cerr << "*** Error. `identifier' is reserved" << std::endl;
+ exit(EXIT_FAILURE);
+ }
+
+ keywords.insert(std::make_pair(keyword.size(), keyword));
+
+ start = stop;
+ while (start != textline.end() && std::isspace(*start))
+ ++start;
+
+ if (start != textline.end() && *start == '%') {
+ ++start;
+ std::string::iterator stop = start;
+ while (stop != textline.end() && (std::isalnum(*stop) || *stop == '_'))
+ ++stop;
+ std::string directive(start, stop);
+ if (directive == "variant") {
+ while (stop != textline.end() && std::isspace(*stop))
+ ++stop;
+ std::string variant(stop, textline.end());
+ variants.insert(std::make_pair(keyword, variant));
+ }
+ }
+ }
+ }
+ }
+
+ if (option_class_name.empty())
+ option_class_name = option_namespace_name;
+
+ if (! option_no_enums)
+ gen_enums(keywords);
+
+ std::multimap<size_t, std::string>::iterator it = keywords.begin();
+ while (it != keywords.end()) {
+ size_t size = it->first;
+ RuleList rules;
+ do { rules.push_back(it->second); ++it; }
+ while (it != keywords.end() && it->first == size);
+ gen_classify_n(State::start(rules.begin(), rules.end()), size);
+ State::reset();
+ }
+
+ gen_classify(keywords);
+
+ gen_keyword_list(keywords);
+}
diff --git a/src/libs/glsl/tools/mkvisitor.py b/src/libs/glsl/tools/mkvisitor.py
new file mode 100755
index 0000000000..edeb292a05
--- /dev/null
+++ b/src/libs/glsl/tools/mkvisitor.py
@@ -0,0 +1,85 @@
+#!/usr/bin/python
+
+import sys
+
+try:
+ file = open(sys.argv[1], "r")
+ klass = sys.argv[2]
+except:
+ print("Usage: mkvisitor.py grammar.txt classname")
+ exit()
+
+lines = file.readlines()
+ruleno = 0
+print("""
+#include "glslast.h"
+
+namespace GLSL {
+
+class %s
+{
+ typedef void (%s::*dispatch_func)(AST *);
+ static dispatch_func dispatch[];
+
+public:
+ void accept(AST *ast)
+ {
+ if (! ast)
+ return;
+ else if (Operator *op = ast->asOperator())
+ (this->*dispatch[op->ruleno])(ast);
+ }
+
+ template <typename It>
+ void accept(It first, It last)
+ {
+ for (; first != last; ++first)
+ accept(*first);
+ }
+
+private:""" % (klass, klass))
+
+for line in lines:
+ sections = line.split()
+ if len(sections) and sections[1] == "::=":
+ ruleno = ruleno + 1
+ print(" void on_%s_%d(AST *);" % (sections[0], ruleno))
+
+print("};")
+print("} // end of namespace GLSL")
+
+print("""
+#include <iostream>
+
+using namespace GLSL;
+
+namespace {
+bool debug = false;
+}
+
+""")
+
+print("%s::dispatch_func %s::dispatch[] = {" % (klass, klass))
+
+ruleno = 0
+for line in lines:
+ sections = line.split()
+ if len(sections) and sections[1] == "::=":
+ ruleno = ruleno + 1
+ print(" &%s::on_%s_%d," % (klass, sections[0], ruleno))
+
+print("0, };\n")
+
+ruleno = 0
+for line in lines:
+ sections = line.split()
+ if len(sections) and sections[1] == "::=":
+ ruleno = ruleno + 1
+ print("""// %svoid %s::on_%s_%d(AST *ast)
+{
+ if (debug)
+ std::cout << "%s" << std::endl;
+ Operator *op = ast->asOperator();
+ accept(op->begin(), op->end());
+}
+""" % (line, klass, sections[0], ruleno, line[:-3]))
diff --git a/src/libs/libs.pro b/src/libs/libs.pro
index 83db8c18f5..fce7bc63f8 100644
--- a/src/libs/libs.pro
+++ b/src/libs/libs.pro
@@ -10,6 +10,9 @@ SUBDIRS = \
utils/process_stub.pro \
cplusplus \
qmljs \
+ glsl \
qmleditorwidgets \
symbianutils \
3rdparty
+
+win32:SUBDIRS += qtcreatorcdbext
diff --git a/src/libs/qmleditorwidgets/colorbox.h b/src/libs/qmleditorwidgets/colorbox.h
index 1e8f23c6d9..dcdb757351 100644
--- a/src/libs/qmleditorwidgets/colorbox.h
+++ b/src/libs/qmleditorwidgets/colorbox.h
@@ -97,6 +97,6 @@ private:
} //QmlEditorWidgets
-QML_DECLARE_TYPE(QmlEditorWidgets::ColorBox);
+QML_DECLARE_TYPE(QmlEditorWidgets::ColorBox)
#endif //COLORBOX_H
diff --git a/src/libs/qmleditorwidgets/colorbutton.h b/src/libs/qmleditorwidgets/colorbutton.h
index 3d73e45f53..66dac234fd 100644
--- a/src/libs/qmleditorwidgets/colorbutton.h
+++ b/src/libs/qmleditorwidgets/colorbutton.h
@@ -73,6 +73,6 @@ private:
} //QmlEditorWidgets
-QML_DECLARE_TYPE(QmlEditorWidgets::ColorButton);
+QML_DECLARE_TYPE(QmlEditorWidgets::ColorButton)
#endif //COLORBUTTON_H
diff --git a/src/libs/qmleditorwidgets/colorwidget.cpp b/src/libs/qmleditorwidgets/colorwidget.cpp
deleted file mode 100644
index aa814b6a48..0000000000
--- a/src/libs/qmleditorwidgets/colorwidget.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#include "colorwidget.h"
-#include <qdeclarative.h>
-
-#include "colorbox.h"
-#include "colorbutton.h"
-#include "huecontrol.h"
-#include "gradientline.h"
-
-namespace QmlEditorWidgets {
-
-void ColorWidget::registerDeclarativeTypes() {
- qmlRegisterType<QmlEditorWidgets::ColorButton>("Bauhaus",1,0,"ColorButton");
- qmlRegisterType<QmlEditorWidgets::HueControl>("Bauhaus",1,0,"HueControl");
- qmlRegisterType<QmlEditorWidgets::ColorBox>("Bauhaus",1,0,"ColorBox");
- qmlRegisterType<QmlEditorWidgets::GradientLine>("Bauhaus",1,0,"GradientLine");
-}
-
-}
diff --git a/src/libs/qmleditorwidgets/colorwidget.h b/src/libs/qmleditorwidgets/colorwidget.h
deleted file mode 100644
index 6a9e231916..0000000000
--- a/src/libs/qmleditorwidgets/colorwidget.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#ifndef COLORWIDGET_H
-#define COLORWIDGET_H
-
-#include <qmleditorwidgets_global.h>
-#include <QWeakPointer>
-#include <QtGui/QWidget>
-#include <QLabel>
-#include <QToolButton>
-#include <QMouseEvent>
-
-
-QT_BEGIN_NAMESPACE
-class QToolButton;
-QT_END_NAMESPACE
-
-namespace QmlEditorWidgets {
-
-class ColorWidget {
-
-public:
- static void registerDeclarativeTypes();
-
-
-};
-
-
-} //QmlDesigner
-
-#endif //COLORWIDGET_H
diff --git a/src/libs/qmleditorwidgets/colorwidgets.cpp b/src/libs/qmleditorwidgets/colorwidgets.cpp
new file mode 100644
index 0000000000..27e7ee1cea
--- /dev/null
+++ b/src/libs/qmleditorwidgets/colorwidgets.cpp
@@ -0,0 +1,51 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** No Commercial Usage
+**
+** This file 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.
+**
+**************************************************************************/
+
+#include "colorwidgets.h"
+#include <qdeclarative.h>
+
+#include "colorbox.h"
+#include "colorbutton.h"
+#include "huecontrol.h"
+#include "gradientline.h"
+
+namespace QmlEditorWidgets {
+
+void ColorWidgets::registerDeclarativeTypes() {
+ qmlRegisterType<QmlEditorWidgets::ColorButton>("Bauhaus",1,0,"ColorButton");
+ qmlRegisterType<QmlEditorWidgets::HueControl>("Bauhaus",1,0,"HueControl");
+ qmlRegisterType<QmlEditorWidgets::ColorBox>("Bauhaus",1,0,"ColorBox");
+ qmlRegisterType<QmlEditorWidgets::GradientLine>("Bauhaus",1,0,"GradientLine");
+}
+
+}
diff --git a/src/libs/qmleditorwidgets/colorwidgets.h b/src/libs/qmleditorwidgets/colorwidgets.h
new file mode 100644
index 0000000000..df0c413791
--- /dev/null
+++ b/src/libs/qmleditorwidgets/colorwidgets.h
@@ -0,0 +1,58 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 <qmleditorwidgets_global.h>
+#include <QWeakPointer>
+#include <QtGui/QWidget>
+#include <QLabel>
+#include <QToolButton>
+#include <QMouseEvent>
+
+
+QT_BEGIN_NAMESPACE
+class QToolButton;
+QT_END_NAMESPACE
+
+namespace QmlEditorWidgets {
+
+class QMLEDITORWIDGETS_EXPORT ColorWidgets {
+
+public:
+ static void registerDeclarativeTypes();
+
+
+};
+
+
+} //QmlDesigner
+
+#endif //COLORWIDGET_H
diff --git a/src/libs/qmleditorwidgets/contextpanewidget.cpp b/src/libs/qmleditorwidgets/contextpanewidget.cpp
index e1420e2d07..629acf42f8 100644
--- a/src/libs/qmleditorwidgets/contextpanewidget.cpp
+++ b/src/libs/qmleditorwidgets/contextpanewidget.cpp
@@ -43,7 +43,6 @@
#include <QGridLayout>
#include <QToolButton>
#include <QAction>
-#include "colorwidget.h"
#include "contextpanetextwidget.h"
#include "easingcontextpane.h"
#include "contextpanewidgetimage.h"
diff --git a/src/libs/qmleditorwidgets/contextpanewidgetimage.cpp b/src/libs/qmleditorwidgets/contextpanewidgetimage.cpp
index 1d99071e8c..dcbdc3fcd6 100644
--- a/src/libs/qmleditorwidgets/contextpanewidgetimage.cpp
+++ b/src/libs/qmleditorwidgets/contextpanewidgetimage.cpp
@@ -469,10 +469,11 @@ void ContextPaneWidgetImage::setPixmap(const QString &fileName)
if (QFile(fileName).exists()) {
if (fileName.endsWith(QLatin1String("sci"))) {
QString pixmapFileName;
- int left = -1;
- int right = -1;
- int top = -1;
- int bottom = -1;
+ int left = 0;
+ int right = 0;
+ int top = 0;
+ int bottom = 0;
+
Qt::TileRule horizontalTileRule;
Qt::TileRule verticalTileRule;
if (parseSciFile(fileName, pixmapFileName, left, right, top, bottom, horizontalTileRule, verticalTileRule)) {
diff --git a/src/libs/qmleditorwidgets/gradientline.cpp b/src/libs/qmleditorwidgets/gradientline.cpp
index b4707f4dfc..d010629d16 100644
--- a/src/libs/qmleditorwidgets/gradientline.cpp
+++ b/src/libs/qmleditorwidgets/gradientline.cpp
@@ -53,7 +53,7 @@ void GradientLine::setGradient(const QLinearGradient &gradient)
{
m_gradient = gradient;
m_useGradient = true;
- setupGradient();
+ readGradient();
emit gradientChanged();
}
@@ -109,7 +109,7 @@ void GradientLine::setActiveColor(const QColor &newColor)
update();
}
-void GradientLine::setupGradient()
+void GradientLine::readGradient()
{
if (m_useGradient) {
m_colorList.clear();
diff --git a/src/libs/qmleditorwidgets/gradientline.h b/src/libs/qmleditorwidgets/gradientline.h
index 2d817ac270..9d43e8502a 100644
--- a/src/libs/qmleditorwidgets/gradientline.h
+++ b/src/libs/qmleditorwidgets/gradientline.h
@@ -60,9 +60,6 @@ public:
QLinearGradient gradient() const { return m_gradient; }
void setGradient(const QLinearGradient &);
-public slots:
- void setupGradient();
-
signals:
void activeColorChanged();
void itemNodeChanged();
@@ -80,6 +77,7 @@ protected:
private:
void setup();
+ void readGradient();
void updateGradient();
int currentColorIndex() const { return m_colorIndex; }
void setCurrentIndex(int i);
diff --git a/src/libs/qmleditorwidgets/huecontrol.h b/src/libs/qmleditorwidgets/huecontrol.h
index dbea86b38e..a8c45d46d7 100644
--- a/src/libs/qmleditorwidgets/huecontrol.h
+++ b/src/libs/qmleditorwidgets/huecontrol.h
@@ -74,6 +74,6 @@ private:
} //QmlEditorWidgets
-QML_DECLARE_TYPE(QmlEditorWidgets::HueControl);
+QML_DECLARE_TYPE(QmlEditorWidgets::HueControl)
#endif //HUECONTROL_H
diff --git a/src/libs/qmleditorwidgets/qmleditorwidgets-lib.pri b/src/libs/qmleditorwidgets/qmleditorwidgets-lib.pri
index c27e792971..942e9eeb4c 100644
--- a/src/libs/qmleditorwidgets/qmleditorwidgets-lib.pri
+++ b/src/libs/qmleditorwidgets/qmleditorwidgets-lib.pri
@@ -19,7 +19,7 @@ HEADERS += \
contextpanewidgetimage.h \
contextpanewidget.h \
contextpanetextwidget.h \
- colorwidget.h \
+ colorwidgets.h \
colorbutton.h \
colorbox.h \
customcolordialog.h \
@@ -34,7 +34,7 @@ SOURCES += \
contextpanewidgetimage.cpp \
contextpanewidget.cpp \
contextpanetextwidget.cpp \
- colorwidget.cpp \
+ colorwidgets.cpp \
colorbox.cpp \
customcolordialog.cpp \
huecontrol.cpp \
diff --git a/src/libs/qmljs/qmljs.pri b/src/libs/qmljs/qmljs.pri
index 3e78a74a35..af334ef81f 100644
--- a/src/libs/qmljs/qmljs.pri
+++ b/src/libs/qmljs/qmljs.pri
@@ -2,5 +2,5 @@ INCLUDEPATH += $$PWD/../../shared
INCLUDEPATH += $$PWD/../../shared/qmljs $$PWD/../../shared/qmljs/parser
DEPENDPATH += $$PWD/../../shared/qmljs $$PWD/../../shared/qmljs/parser
-LIBS *= -l$$qtLibraryTarget(QmlJS)
+LIBS *= -l$$qtLibraryName(QmlJS)
DEFINES += QT_CREATOR
diff --git a/src/libs/qmljs/qmljsbind.cpp b/src/libs/qmljs/qmljsbind.cpp
index 87d87e82ae..4a9bbf2523 100644
--- a/src/libs/qmljs/qmljsbind.cpp
+++ b/src/libs/qmljs/qmljsbind.cpp
@@ -97,12 +97,71 @@ Interpreter::ObjectValue *Bind::findQmlObject(AST::Node *node) const
bool Bind::usesQmlPrototype(ObjectValue *prototype,
const Context *context) const
{
- // ### This function is disabled for performance reasons.
- return false;
+ if (!prototype)
+ return false;
- foreach (ObjectValue *object, _qmlObjects.values()) {
- const ObjectValue *resolvedPrototype = object->prototype(context);
+ const QString componentName = prototype->className();
+
+ // all component objects have classname set
+ if (componentName.isEmpty())
+ return false;
+
+ // get a list of all the names that may refer to this component
+ // this can only happen for file imports with an 'as' clause
+ // if there aren't any, possibleNames will be left empty
+ QSet<QString> possibleNames;
+ foreach (const ImportInfo &import, imports()) {
+ if (import.type() == ImportInfo::FileImport
+ && !import.id().isEmpty()
+ && import.name().contains(componentName)) {
+ possibleNames.insert(import.id());
+ }
+ }
+ if (!possibleNames.isEmpty())
+ possibleNames.insert(componentName);
+
+ // if there are no renamed imports and the document does not use
+ // the className string anywhere, it's out
+ if (possibleNames.isEmpty()) {
+ NameId nameId(componentName.data(), componentName.size());
+ if (!_doc->engine()->literals().contains(nameId))
+ return false;
+ }
+ QHashIterator<Node *, ObjectValue *> it(_qmlObjects);
+ while (it.hasNext()) {
+ it.next();
+
+ // if the type id does not contain one of the possible names, skip
+ Node *node = it.key();
+ UiQualifiedId *id = 0;
+ if (UiObjectDefinition *n = cast<UiObjectDefinition *>(node)) {
+ id = n->qualifiedTypeNameId;
+ } else if (UiObjectBinding *n = cast<UiObjectBinding *>(node)) {
+ id = n->qualifiedTypeNameId;
+ }
+ if (!id)
+ continue;
+
+ bool skip = false;
+ // optimize the common case of no renamed imports
+ if (possibleNames.isEmpty()) {
+ for (UiQualifiedId *idIt = id; idIt; idIt = idIt->next) {
+ if (!idIt->next && idIt->name->asString() != componentName)
+ skip = true;
+ }
+ } else {
+ for (UiQualifiedId *idIt = id; idIt; idIt = idIt->next) {
+ if (!idIt->next && !possibleNames.contains(idIt->name->asString()))
+ skip = true;
+ }
+ }
+ if (skip)
+ continue;
+
+ // resolve and check the prototype
+ const ObjectValue *object = it.value();
+ const ObjectValue *resolvedPrototype = object->prototype(context);
if (resolvedPrototype == prototype)
return true;
}
@@ -110,7 +169,7 @@ bool Bind::usesQmlPrototype(ObjectValue *prototype,
return false;
}
-Interpreter::ObjectValue *Bind::findFunctionScope(AST::FunctionDeclaration *node) const
+Interpreter::ObjectValue *Bind::findFunctionScope(AST::FunctionExpression *node) const
{
return _functionScopes.value(node);
}
@@ -142,14 +201,6 @@ QString Bind::toString(UiQualifiedId *qualifiedId, QChar delimiter)
return result;
}
-ExpressionNode *Bind::expression(UiScriptBinding *ast) const
-{
- if (ExpressionStatement *statement = cast<ExpressionStatement *>(ast->statement))
- return statement->expression;
-
- return 0;
-}
-
ObjectValue *Bind::bindObject(UiQualifiedId *qualifiedTypeNameId, UiObjectInitializer *initializer)
{
ObjectValue *parentObjectValue = 0;
@@ -282,7 +333,7 @@ bool Bind::visit(UiScriptBinding *ast)
_idEnvironment->setProperty(i->name->asString(), _currentObjectValue);
}
- return false;
+ return true;
}
bool Bind::visit(UiArrayBinding *)
@@ -299,19 +350,18 @@ bool Bind::visit(VariableDeclaration *ast)
ASTVariableReference *ref = new ASTVariableReference(ast, &_engine);
_currentObjectValue->setProperty(ast->name->asString(), ref);
- return false;
+ return true;
}
-bool Bind::visit(FunctionDeclaration *ast)
+bool Bind::visit(FunctionExpression *ast)
{
- if (!ast->name)
- return false;
// ### FIXME: the first declaration counts
//if (_currentObjectValue->property(ast->name->asString(), 0))
// return false;
ASTFunctionValue *function = new ASTFunctionValue(ast, _doc, &_engine);
- _currentObjectValue->setProperty(ast->name->asString(), function);
+ if (ast->name && cast<FunctionDeclaration *>(ast))
+ _currentObjectValue->setProperty(ast->name->asString(), function);
// build function scope
ObjectValue *functionScope = _engine.newObject(/*prototype=*/0);
@@ -345,3 +395,8 @@ bool Bind::visit(FunctionDeclaration *ast)
return false;
}
+
+bool Bind::visit(FunctionDeclaration *ast)
+{
+ return visit(static_cast<FunctionExpression *>(ast));
+}
diff --git a/src/libs/qmljs/qmljsbind.h b/src/libs/qmljs/qmljsbind.h
index 69cf85bead..bebc101e89 100644
--- a/src/libs/qmljs/qmljsbind.h
+++ b/src/libs/qmljs/qmljsbind.h
@@ -66,7 +66,7 @@ public:
bool usesQmlPrototype(Interpreter::ObjectValue *prototype,
const Interpreter::Context *context) const;
- Interpreter::ObjectValue *findFunctionScope(AST::FunctionDeclaration *node) const;
+ Interpreter::ObjectValue *findFunctionScope(AST::FunctionExpression *node) const;
bool isGroupedPropertyBinding(AST::Node *node) const;
static QString toString(AST::UiQualifiedId *qualifiedId, QChar delimiter = QChar('.'));
@@ -89,13 +89,12 @@ protected:
// QML/JS
virtual bool visit(AST::FunctionDeclaration *ast);
+ virtual bool visit(AST::FunctionExpression *ast);
virtual bool visit(AST::VariableDeclaration *ast);
Interpreter::ObjectValue *switchObjectValue(Interpreter::ObjectValue *newObjectValue);
Interpreter::ObjectValue *bindObject(AST::UiQualifiedId *qualifiedTypeNameId, AST::UiObjectInitializer *initializer);
- AST::ExpressionNode *expression(AST::UiScriptBinding *ast) const;
-
private:
Document *_doc;
Interpreter::Engine _engine;
@@ -106,7 +105,7 @@ private:
QHash<AST::Node *, Interpreter::ObjectValue *> _qmlObjects;
QSet<AST::Node *> _groupedPropertyBindings;
- QHash<AST::FunctionDeclaration *, Interpreter::ObjectValue *> _functionScopes;
+ QHash<AST::FunctionExpression *, Interpreter::ObjectValue *> _functionScopes;
QStringList _includedScripts;
QList<Interpreter::ImportInfo> _imports;
diff --git a/src/libs/qmljs/qmljscheck.cpp b/src/libs/qmljs/qmljscheck.cpp
index 436a2e4092..4393710aae 100644
--- a/src/libs/qmljs/qmljscheck.cpp
+++ b/src/libs/qmljs/qmljscheck.cpp
@@ -38,6 +38,7 @@
#include "parser/qmljsast_p.h"
#include <QtCore/QDebug>
+#include <QtCore/QDir>
#include <QtGui/QColor>
#include <QtGui/QApplication>
@@ -75,6 +76,20 @@ SourceLocation QmlJS::locationFromRange(const SourceLocation &start,
start.startColumn);
}
+SourceLocation QmlJS::fullLocationForQualifiedId(AST::UiQualifiedId *qualifiedId)
+{
+ SourceLocation start = qualifiedId->identifierToken;
+ SourceLocation end = qualifiedId->identifierToken;
+
+ for (UiQualifiedId *iter = qualifiedId; iter; iter = iter->next) {
+ if (iter->name)
+ end = iter->identifierToken;
+ }
+
+ return locationFromRange(start, end);
+}
+
+
DiagnosticMessage QmlJS::errorMessage(const AST::SourceLocation &loc, const QString &message)
{
return DiagnosticMessage(DiagnosticMessage::Error, loc, message);
@@ -86,11 +101,13 @@ class AssignmentCheck : public ValueVisitor
{
public:
DiagnosticMessage operator()(
+ const Document::Ptr &document,
const SourceLocation &location,
const Interpreter::Value *lhsValue,
const Interpreter::Value *rhsValue,
ExpressionNode *ast)
{
+ _doc = document;
_message = DiagnosticMessage(DiagnosticMessage::Error, location, QString());
_rhsValue = rhsValue;
_ast = ast;
@@ -110,10 +127,8 @@ public:
if (!enumValue->keys().contains(valueName)) {
_message.message = Check::tr("unknown value for enum");
}
- } else if (_rhsValue->asUndefinedValue()) {
- _message.kind = DiagnosticMessage::Warning;
- _message.message = Check::tr("value might be 'undefined'");
- } else if (! _rhsValue->asStringValue() && ! _rhsValue->asNumberValue()) {
+ } else if (! _rhsValue->asStringValue() && ! _rhsValue->asNumberValue()
+ && ! _rhsValue->asUndefinedValue()) {
_message.message = Check::tr("enum value is not a string or number");
}
} else {
@@ -136,7 +151,7 @@ public:
}
}
- virtual void visit(const StringValue *)
+ virtual void visit(const StringValue *value)
{
UnaryMinusExpression *unaryMinus = cast<UnaryMinusExpression *>(_ast);
@@ -146,6 +161,25 @@ public:
|| _ast->kind == Node::Kind_FalseLiteral) {
_message.message = Check::tr("string value expected");
}
+
+ if (value && value->asUrlValue()) {
+ if (StringLiteral *literal = cast<StringLiteral *>(_ast)) {
+ QUrl url(literal->value->asString());
+ if (!url.isValid() && !url.isEmpty()) {
+ _message.message = Check::tr("not a valid url");
+ } else {
+ QString fileName = url.toLocalFile();
+ if (!fileName.isEmpty()) {
+ if (url.isRelative()) {
+ fileName.prepend(QDir::separator());
+ fileName.prepend(_doc->path());
+ }
+ if (!QFileInfo(fileName).exists())
+ _message.message = Check::tr("file or directory does not exist");
+ }
+ }
+ }
+ }
}
virtual void visit(const ColorValue *)
@@ -164,11 +198,169 @@ public:
_message.message = Check::tr("expected anchor line");
}
+ Document::Ptr _doc;
DiagnosticMessage _message;
const Value *_rhsValue;
ExpressionNode *_ast;
};
+class FunctionBodyCheck : protected Visitor
+{
+public:
+ QList<DiagnosticMessage> operator()(FunctionExpression *function, Check::Options options)
+ {
+ clear();
+ _options = options;
+ for (FormalParameterList *plist = function->formals; plist; plist = plist->next) {
+ if (plist->name)
+ _formalParameterNames += plist->name->asString();
+ }
+
+ Node::accept(function->body, this);
+ return _messages;
+ }
+
+ QList<DiagnosticMessage> operator()(StatementList *statements, Check::Options options)
+ {
+ clear();
+ _options = options;
+ Node::accept(statements, this);
+ return _messages;
+ }
+
+protected:
+ void clear()
+ {
+ _messages.clear();
+ _declaredFunctions.clear();
+ _declaredVariables.clear();
+ _possiblyUndeclaredUses.clear();
+ _seenNonDeclarationStatement = false;
+ _formalParameterNames.clear();
+ }
+
+ void postVisit(Node *ast)
+ {
+ if (!_seenNonDeclarationStatement && ast->statementCast()
+ && !cast<VariableStatement *>(ast)) {
+ _seenNonDeclarationStatement = true;
+ }
+ }
+
+ bool visit(IdentifierExpression *ast)
+ {
+ if (!ast->name)
+ return false;
+ const QString name = ast->name->asString();
+ if (!_declaredFunctions.contains(name) && !_declaredVariables.contains(name))
+ _possiblyUndeclaredUses[name].append(ast->identifierToken);
+ return false;
+ }
+
+ bool visit(VariableStatement *ast)
+ {
+ if (_options & Check::WarnDeclarationsNotStartOfFunction && _seenNonDeclarationStatement) {
+ warning(ast->declarationKindToken, Check::tr("declarations should be at the start of a function"));
+ }
+ return true;
+ }
+
+ bool visit(VariableDeclaration *ast)
+ {
+ if (!ast->name)
+ return true;
+ const QString name = ast->name->asString();
+
+ if (_formalParameterNames.contains(name)) {
+ if (_options & Check::WarnDuplicateDeclaration)
+ warning(ast->identifierToken, Check::tr("already a formal parameter"));
+ return true;
+ }
+ if (_declaredFunctions.contains(name)) {
+ if (_options & Check::WarnDuplicateDeclaration)
+ warning(ast->identifierToken, Check::tr("already declared as function"));
+ return true;
+ }
+ if (_declaredVariables.contains(name)) {
+ if (_options & Check::WarnDuplicateDeclaration)
+ warning(ast->identifierToken, Check::tr("duplicate declaration"));
+ return true;
+ }
+
+ if (_possiblyUndeclaredUses.contains(name)) {
+ if (_options & Check::WarnUseBeforeDeclaration) {
+ foreach (const SourceLocation &loc, _possiblyUndeclaredUses.value(name)) {
+ warning(loc, Check::tr("variable is used before being declared"));
+ }
+ }
+ _possiblyUndeclaredUses.remove(name);
+ }
+ _declaredVariables[name] = ast;
+
+ return true;
+ }
+
+ bool visit(FunctionDeclaration *ast)
+ {
+ if (_options & Check::WarnDeclarationsNotStartOfFunction &&_seenNonDeclarationStatement) {
+ warning(ast->functionToken, Check::tr("declarations should be at the start of a function"));
+ }
+
+ return visit(static_cast<FunctionExpression *>(ast));
+ }
+
+ bool visit(FunctionExpression *ast)
+ {
+ if (!ast->name)
+ return false;
+ const QString name = ast->name->asString();
+
+ if (_formalParameterNames.contains(name)) {
+ if (_options & Check::WarnDuplicateDeclaration)
+ warning(ast->identifierToken, Check::tr("already a formal parameter"));
+ return false;
+ }
+ if (_declaredVariables.contains(name)) {
+ if (_options & Check::WarnDuplicateDeclaration)
+ warning(ast->identifierToken, Check::tr("already declared as var"));
+ return false;
+ }
+ if (_declaredFunctions.contains(name)) {
+ if (_options & Check::WarnDuplicateDeclaration)
+ warning(ast->identifierToken, Check::tr("duplicate declaration"));
+ return false;
+ }
+
+ if (FunctionDeclaration *decl = cast<FunctionDeclaration *>(ast)) {
+ if (_possiblyUndeclaredUses.contains(name)) {
+ if (_options & Check::WarnUseBeforeDeclaration) {
+ foreach (const SourceLocation &loc, _possiblyUndeclaredUses.value(name)) {
+ warning(loc, Check::tr("function is used before being declared"));
+ }
+ }
+ _possiblyUndeclaredUses.remove(name);
+ }
+ _declaredFunctions[name] = decl;
+ }
+
+ return false;
+ }
+
+private:
+ void warning(const SourceLocation &loc, const QString &message)
+ {
+ _messages.append(DiagnosticMessage(DiagnosticMessage::Warning, loc, message));
+ }
+
+ Check::Options _options;
+ QList<DiagnosticMessage> _messages;
+ QStringList _formalParameterNames;
+ QHash<QString, VariableDeclaration *> _declaredVariables;
+ QHash<QString, FunctionDeclaration *> _declaredFunctions;
+ QHash<QString, QList<SourceLocation> > _possiblyUndeclaredUses;
+ bool _seenNonDeclarationStatement;
+};
+
} // end of anonymous namespace
@@ -178,6 +370,11 @@ Check::Check(Document::Ptr doc, const Snapshot &snapshot, const Context *linkedC
, _context(*linkedContextNoScope)
, _scopeBuilder(&_context, doc, snapshot)
, _ignoreTypeErrors(false)
+ , _options(WarnDangerousNonStrictEqualityChecks | WarnBlocks | WarnWith
+ | WarnVoid | WarnCommaExpression | WarnExpressionStatement
+ | WarnAssignInCondition | WarnUseBeforeDeclaration | WarnDuplicateDeclaration
+ | WarnCaseWithoutFlowControlEnd)
+ , _lastValue(0)
{
}
@@ -192,11 +389,59 @@ QList<DiagnosticMessage> Check::operator()()
return _messages;
}
+bool Check::preVisit(Node *ast)
+{
+ _chain.append(ast);
+ return true;
+}
+
+void Check::postVisit(Node *)
+{
+ _chain.removeLast();
+}
+
bool Check::visit(UiProgram *)
{
return true;
}
+bool Check::visit(UiObjectInitializer *)
+{
+ m_propertyStack.push(StringSet());
+ UiObjectDefinition *objectDefinition = cast<UiObjectDefinition *>(parent());
+ if (objectDefinition && objectDefinition->qualifiedTypeNameId->name->asString() == "Component")
+ m_idStack.push(StringSet());
+ UiObjectBinding *objectBinding = cast<UiObjectBinding *>(parent());
+ if (objectBinding && objectBinding->qualifiedTypeNameId->name->asString() == "Component")
+ m_idStack.push(StringSet());
+ if (m_idStack.isEmpty())
+ m_idStack.push(StringSet());
+ return true;
+}
+
+void Check::endVisit(UiObjectInitializer *)
+{
+ m_propertyStack.pop();
+ UiObjectDefinition *objectDenition = cast<UiObjectDefinition *>(parent());
+ if (objectDenition && objectDenition->qualifiedTypeNameId->name->asString() == "Component")
+ m_idStack.pop();
+ UiObjectBinding *objectBinding = cast<UiObjectBinding *>(parent());
+ if (objectBinding && objectBinding->qualifiedTypeNameId->name->asString() == "Component")
+ m_idStack.pop();
+}
+
+void Check::checkProperty(UiQualifiedId *qualifiedId)
+{
+ const QString id = Bind::toString(qualifiedId);
+ if (id.at(0).isLower()) {
+ if (m_propertyStack.top().contains(id)) {
+ error(fullLocationForQualifiedId(qualifiedId),
+ Check::tr("properties can only be assigned once"));
+ }
+ m_propertyStack.top().insert(id);
+ }
+}
+
bool Check::visit(UiObjectDefinition *ast)
{
visitQmlObject(ast, ast->qualifiedTypeNameId, ast->initializer);
@@ -206,6 +451,8 @@ bool Check::visit(UiObjectDefinition *ast)
bool Check::visit(UiObjectBinding *ast)
{
checkScopeObjectMember(ast->qualifiedId);
+ if (!ast->hasOnToken)
+ checkProperty(ast->qualifiedId);
visitQmlObject(ast, ast->qualifiedTypeNameId, ast->initializer);
return false;
@@ -267,12 +514,20 @@ bool Check::visit(UiScriptBinding *ast)
return false;
}
- if (id.isEmpty() || ! id[0].isLower()) {
- error(loc, Check::tr("ids must be lower case"));
+ if (id.isEmpty() || (!id[0].isLower() && id[0] != '_')) {
+ error(loc, Check::tr("ids must be lower case or start with underscore"));
+ return false;
+ }
+
+ if (m_idStack.top().contains(id)) {
+ error(loc, Check::tr("ids must be unique"));
return false;
}
+ m_idStack.top().insert(id);
}
+ checkProperty(ast->qualifiedId);
+
const Value *lhsValue = checkScopeObjectMember(ast->qualifiedId);
if (lhsValue) {
// ### Fix the evaluator to accept statements!
@@ -285,20 +540,265 @@ bool Check::visit(UiScriptBinding *ast)
const SourceLocation loc = locationFromRange(expStmt->firstSourceLocation(),
expStmt->lastSourceLocation());
AssignmentCheck assignmentCheck;
- DiagnosticMessage message = assignmentCheck(loc, lhsValue, rhsValue, expr);
+ DiagnosticMessage message = assignmentCheck(_doc, loc, lhsValue, rhsValue, expr);
if (! message.message.isEmpty())
_messages += message;
}
}
+ if (Block *block = cast<Block *>(ast->statement)) {
+ FunctionBodyCheck bodyCheck;
+ _messages.append(bodyCheck(block->statements, _options));
+ }
+
return true;
}
bool Check::visit(UiArrayBinding *ast)
{
checkScopeObjectMember(ast->qualifiedId);
+ checkProperty(ast->qualifiedId);
+
+ return true;
+}
+
+bool Check::visit(IdentifierExpression *ast)
+{
+ // currently disabled: too many false negatives
+ return true;
+
+ _lastValue = 0;
+ if (ast->name) {
+ Evaluate evaluator(&_context);
+ _lastValue = evaluator.reference(ast);
+ if (!_lastValue)
+ error(ast->identifierToken, tr("unknown identifier"));
+ if (const Reference *ref = value_cast<const Reference *>(_lastValue)) {
+ _lastValue = _context.lookupReference(ref);
+ if (!_lastValue)
+ error(ast->identifierToken, tr("could not resolve"));
+ }
+ }
+ return false;
+}
+
+bool Check::visit(FieldMemberExpression *ast)
+{
+ // currently disabled: too many false negatives
+ return true;
+
+ Node::accept(ast->base, this);
+ if (!_lastValue)
+ return false;
+ const ObjectValue *obj = _lastValue->asObjectValue();
+ if (!obj) {
+ error(locationFromRange(ast->base->firstSourceLocation(), ast->base->lastSourceLocation()),
+ tr("does not have members"));
+ }
+ if (!obj || !ast->name) {
+ _lastValue = 0;
+ return false;
+ }
+ _lastValue = obj->lookupMember(ast->name->asString(), &_context);
+ if (!_lastValue)
+ error(ast->identifierToken, tr("unknown member"));
+ return false;
+}
+
+bool Check::visit(FunctionDeclaration *ast)
+{
+ return visit(static_cast<FunctionExpression *>(ast));
+}
+
+bool Check::visit(FunctionExpression *ast)
+{
+ FunctionBodyCheck bodyCheck;
+ _messages.append(bodyCheck(ast, _options));
+
+ Node::accept(ast->formals, this);
+ _scopeBuilder.push(ast);
+ Node::accept(ast->body, this);
+ _scopeBuilder.pop();
+ return false;
+}
+
+static bool shouldAvoidNonStrictEqualityCheck(ExpressionNode *exp, const Value *other)
+{
+ if (NumericLiteral *literal = cast<NumericLiteral *>(exp)) {
+ if (literal->value == 0 && !other->asNumberValue())
+ return true;
+ } else if ((cast<TrueLiteral *>(exp) || cast<FalseLiteral *>(exp)) && !other->asBooleanValue()) {
+ return true;
+ } else if (cast<NullExpression *>(exp)) {
+ return true;
+ } else if (IdentifierExpression *ident = cast<IdentifierExpression *>(exp)) {
+ if (ident->name && ident->name->asString() == QLatin1String("undefined"))
+ return true;
+ } else if (StringLiteral *literal = cast<StringLiteral *>(exp)) {
+ if ((!literal->value || literal->value->asString().isEmpty()) && !other->asStringValue())
+ return true;
+ }
+ return false;
+}
+
+bool Check::visit(BinaryExpression *ast)
+{
+ if (ast->op == QSOperator::Equal || ast->op == QSOperator::NotEqual) {
+ bool warn = _options & WarnAllNonStrictEqualityChecks;
+ if (!warn && _options & WarnDangerousNonStrictEqualityChecks) {
+ Evaluate eval(&_context);
+ const Value *lhs = eval(ast->left);
+ const Value *rhs = eval(ast->right);
+ warn = shouldAvoidNonStrictEqualityCheck(ast->left, rhs)
+ || shouldAvoidNonStrictEqualityCheck(ast->right, lhs);
+ }
+ if (warn) {
+ warning(ast->operatorToken, tr("== and != perform type coercion, use === or !== instead to avoid"));
+ }
+ }
+ return true;
+}
+
+bool Check::visit(Block *ast)
+{
+ if (Node *p = parent()) {
+ if (_options & WarnBlocks
+ && !cast<UiScriptBinding *>(p)
+ && !cast<TryStatement *>(p)
+ && !cast<Catch *>(p)
+ && !cast<Finally *>(p)
+ && !cast<ForStatement *>(p)
+ && !cast<ForEachStatement *>(p)
+ && !cast<LocalForStatement *>(p)
+ && !cast<LocalForEachStatement *>(p)
+ && !cast<DoWhileStatement *>(p)
+ && !cast<WhileStatement *>(p)
+ && !cast<IfStatement *>(p)
+ && !cast<SwitchStatement *>(p)
+ && !cast<WithStatement *>(p)) {
+ warning(ast->lbraceToken, tr("blocks do not introduce a new scope, avoid"));
+ }
+ }
+ return true;
+}
+
+bool Check::visit(WithStatement *ast)
+{
+ if (_options & WarnWith)
+ warning(ast->withToken, tr("use of the with statement is not recommended, use a var instead"));
+ return true;
+}
+
+bool Check::visit(VoidExpression *ast)
+{
+ if (_options & WarnVoid)
+ warning(ast->voidToken, tr("use of void is usually confusing and not recommended"));
+ return true;
+}
+
+bool Check::visit(Expression *ast)
+{
+ if (_options & WarnCommaExpression && ast->left && ast->right) {
+ Node *p = parent();
+ if (!cast<ForStatement *>(p)
+ && !cast<LocalForStatement *>(p)) {
+ warning(ast->commaToken, tr("avoid comma expressions"));
+ }
+ }
+ return true;
+}
+bool Check::visit(ExpressionStatement *ast)
+{
+ if (_options & WarnExpressionStatement && ast->expression) {
+ bool ok = cast<CallExpression *>(ast->expression)
+ || cast<DeleteExpression *>(ast->expression)
+ || cast<PreDecrementExpression *>(ast->expression)
+ || cast<PreIncrementExpression *>(ast->expression)
+ || cast<PostIncrementExpression *>(ast->expression)
+ || cast<PostDecrementExpression *>(ast->expression);
+ if (BinaryExpression *binary = cast<BinaryExpression *>(ast->expression)) {
+ switch (binary->op) {
+ case QSOperator::Assign:
+ case QSOperator::InplaceAdd:
+ case QSOperator::InplaceAnd:
+ case QSOperator::InplaceDiv:
+ case QSOperator::InplaceLeftShift:
+ case QSOperator::InplaceRightShift:
+ case QSOperator::InplaceMod:
+ case QSOperator::InplaceMul:
+ case QSOperator::InplaceOr:
+ case QSOperator::InplaceSub:
+ case QSOperator::InplaceURightShift:
+ case QSOperator::InplaceXor:
+ ok = true;
+ default: break;
+ }
+ }
+ if (!ok) {
+ for (int i = 0; Node *p = parent(i); ++i) {
+ if (UiScriptBinding *binding = cast<UiScriptBinding *>(p)) {
+ if (!cast<Block *>(binding->statement)) {
+ ok = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (!ok) {
+ warning(locationFromRange(ast->firstSourceLocation(), ast->lastSourceLocation()),
+ tr("expression statements should be assignments, calls or delete expressions only"));
+ }
+ }
+ return true;
+}
+
+bool Check::visit(IfStatement *ast)
+{
+ if (ast->expression)
+ checkAssignInCondition(ast->expression);
+ return true;
+}
+
+bool Check::visit(ForStatement *ast)
+{
+ if (ast->condition)
+ checkAssignInCondition(ast->condition);
+ return true;
+}
+
+bool Check::visit(LocalForStatement *ast)
+{
+ if (ast->condition)
+ checkAssignInCondition(ast->condition);
+ return true;
+}
+
+bool Check::visit(WhileStatement *ast)
+{
+ if (ast->expression)
+ checkAssignInCondition(ast->expression);
+ return true;
+}
+
+bool Check::visit(DoWhileStatement *ast)
+{
+ if (ast->expression)
+ checkAssignInCondition(ast->expression);
+ return true;
+}
+
+bool Check::visit(CaseClause *ast)
+{
+ checkEndsWithControlFlow(ast->statements, ast->caseToken);
+ return true;
+}
+
+bool Check::visit(DefaultClause *ast)
+{
+ checkEndsWithControlFlow(ast->statements, ast->defaultToken);
return true;
}
@@ -380,6 +880,34 @@ const Value *Check::checkScopeObjectMember(const UiQualifiedId *id)
return value;
}
+void Check::checkAssignInCondition(AST::ExpressionNode *condition)
+{
+ if (_options & WarnAssignInCondition) {
+ if (BinaryExpression *binary = cast<BinaryExpression *>(condition)) {
+ if (binary->op == QSOperator::Assign)
+ warning(binary->operatorToken, tr("avoid assignments in conditions"));
+ }
+ }
+}
+
+void Check::checkEndsWithControlFlow(StatementList *statements, SourceLocation errorLoc)
+{
+ // full flow analysis would be neat
+ if (!statements || !(_options & WarnCaseWithoutFlowControlEnd))
+ return;
+
+ Statement *lastStatement = 0;
+ for (StatementList *slist = statements; slist; slist = slist->next)
+ lastStatement = slist->statement;
+
+ if (!cast<ReturnStatement *>(lastStatement)
+ && !cast<ThrowStatement *>(lastStatement)
+ && !cast<BreakStatement *>(lastStatement)
+ && !cast<ContinueStatement *>(lastStatement)) {
+ warning(errorLoc, tr("case does not end with return, break, continue or throw"));
+ }
+}
+
void Check::error(const AST::SourceLocation &loc, const QString &message)
{
_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc, message));
@@ -389,3 +917,11 @@ void Check::warning(const AST::SourceLocation &loc, const QString &message)
{
_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, loc, message));
}
+
+Node *Check::parent(int distance)
+{
+ const int index = _chain.size() - 2 - distance;
+ if (index < 0)
+ return 0;
+ return _chain.at(index);
+}
diff --git a/src/libs/qmljs/qmljscheck.h b/src/libs/qmljs/qmljscheck.h
index 9fe3c1e0d6..9243f9e969 100644
--- a/src/libs/qmljs/qmljscheck.h
+++ b/src/libs/qmljs/qmljscheck.h
@@ -40,6 +40,8 @@
#include <qmljs/parser/qmljsastvisitor_p.h>
#include <QtCore/QCoreApplication>
+#include <QtCore/QSet>
+#include <QtCore/QStack>
#include <QtGui/QColor>
namespace QmlJS {
@@ -48,27 +50,78 @@ class QMLJS_EXPORT Check: protected AST::Visitor
{
Q_DECLARE_TR_FUNCTIONS(QmlJS::Check)
+ typedef QSet<QString> StringSet;
+
public:
Check(Document::Ptr doc, const Snapshot &snapshot, const Interpreter::Context *linkedContextNoScope);
virtual ~Check();
QList<DiagnosticMessage> operator()();
+
+ void setIgnoreTypeErrors(bool ignore)
+ { _ignoreTypeErrors = ignore; }
+
+ enum Option {
+ WarnDangerousNonStrictEqualityChecks = 1 << 0,
+ WarnAllNonStrictEqualityChecks = 1 << 1,
+ WarnBlocks = 1 << 2,
+ WarnWith = 1 << 3,
+ WarnVoid = 1 << 4,
+ WarnCommaExpression = 1 << 5,
+ WarnExpressionStatement = 1 << 6,
+ WarnAssignInCondition = 1 << 7,
+ WarnUseBeforeDeclaration = 1 << 8,
+ WarnDuplicateDeclaration = 1 << 9,
+ WarnDeclarationsNotStartOfFunction = 1 << 10,
+ WarnCaseWithoutFlowControlEnd = 1 << 11
+ };
+ Q_DECLARE_FLAGS(Options, Option)
+
protected:
+ virtual bool preVisit(AST::Node *ast);
+ virtual void postVisit(AST::Node *ast);
+
virtual bool visit(AST::UiProgram *ast);
virtual bool visit(AST::UiObjectDefinition *ast);
virtual bool visit(AST::UiObjectBinding *ast);
virtual bool visit(AST::UiScriptBinding *ast);
virtual bool visit(AST::UiArrayBinding *ast);
+ virtual bool visit(AST::IdentifierExpression *ast);
+ virtual bool visit(AST::FieldMemberExpression *ast);
+ virtual bool visit(AST::FunctionDeclaration *ast);
+ virtual bool visit(AST::FunctionExpression *ast);
+ virtual bool visit(AST::UiObjectInitializer *);
+
+ virtual bool visit(AST::BinaryExpression *ast);
+ virtual bool visit(AST::Block *ast);
+ virtual bool visit(AST::WithStatement *ast);
+ virtual bool visit(AST::VoidExpression *ast);
+ virtual bool visit(AST::Expression *ast);
+ virtual bool visit(AST::ExpressionStatement *ast);
+ virtual bool visit(AST::IfStatement *ast);
+ virtual bool visit(AST::ForStatement *ast);
+ virtual bool visit(AST::LocalForStatement *ast);
+ virtual bool visit(AST::WhileStatement *ast);
+ virtual bool visit(AST::DoWhileStatement *ast);
+ virtual bool visit(AST::CaseClause *ast);
+ virtual bool visit(AST::DefaultClause *ast);
+
+ virtual void endVisit(QmlJS::AST::UiObjectInitializer *);
private:
void visitQmlObject(AST::Node *ast, AST::UiQualifiedId *typeId,
AST::UiObjectInitializer *initializer);
const Interpreter::Value *checkScopeObjectMember(const AST::UiQualifiedId *id);
+ void checkAssignInCondition(AST::ExpressionNode *condition);
+ void checkEndsWithControlFlow(AST::StatementList *statements, AST::SourceLocation errorLoc);
+ void checkProperty(QmlJS::AST::UiQualifiedId *);
void warning(const AST::SourceLocation &loc, const QString &message);
void error(const AST::SourceLocation &loc, const QString &message);
+ AST::Node *parent(int distance = 0);
+
Document::Ptr _doc;
Snapshot _snapshot;
@@ -78,12 +131,21 @@ private:
QList<DiagnosticMessage> _messages;
bool _ignoreTypeErrors;
+ Options _options;
+
+ const Interpreter::Value *_lastValue;
+ QList<AST::Node *> _chain;
+ QStack<StringSet> m_idStack;
+ QStack<StringSet> m_propertyStack;
};
QMLJS_EXPORT QColor toQColor(const QString &qmlColorString);
QMLJS_EXPORT AST::SourceLocation locationFromRange(const AST::SourceLocation &start,
const AST::SourceLocation &end);
+
+QMLJS_EXPORT AST::SourceLocation fullLocationForQualifiedId(AST::UiQualifiedId *);
+
QMLJS_EXPORT DiagnosticMessage errorMessage(const AST::SourceLocation &loc,
const QString &message);
diff --git a/src/libs/qmljs/qmljscodeformatter.cpp b/src/libs/qmljs/qmljscodeformatter.cpp
index 34e85e737a..5fb4a9ebcf 100644
--- a/src/libs/qmljs/qmljscodeformatter.cpp
+++ b/src/libs/qmljs/qmljscodeformatter.cpp
@@ -697,6 +697,8 @@ bool CodeFormatter::tryStatement()
case List:
case Property:
case Function:
+ case Number:
+ case String:
enter(expression);
// look at the token again
m_tokenIndex -= 1;
diff --git a/src/libs/qmljs/qmljscodeformatter.h b/src/libs/qmljs/qmljscodeformatter.h
index 9d1af02d82..30e1bae6f6 100644
--- a/src/libs/qmljs/qmljscodeformatter.h
+++ b/src/libs/qmljs/qmljscodeformatter.h
@@ -173,7 +173,7 @@ public: // must be public to make Q_GADGET introspection work
switch_statement, // After 'switch' token
case_start, // after a 'case' or 'default' token
- case_cont, // after the colon in a case/default
+ case_cont // after the colon in a case/default
};
Q_ENUMS(StateType)
@@ -237,7 +237,7 @@ protected:
Question,
PlusPlus,
- MinusMinus,
+ MinusMinus
};
TokenKind extendedTokenKind(const QmlJS::Token &token) const;
diff --git a/src/libs/qmljs/qmljscompletioncontextfinder.cpp b/src/libs/qmljs/qmljscompletioncontextfinder.cpp
index 424e07dea2..9d0fa94ee7 100644
--- a/src/libs/qmljs/qmljscompletioncontextfinder.cpp
+++ b/src/libs/qmljs/qmljscompletioncontextfinder.cpp
@@ -51,6 +51,8 @@ CompletionContextFinder::CompletionContextFinder(const QTextCursor &cursor)
: m_cursor(cursor)
, m_colonCount(-1)
, m_behaviorBinding(false)
+ , m_inStringLiteral(false)
+ , m_inImport(false)
{
QTextBlock lastBlock = cursor.block();
if (lastBlock.next().isValid())
@@ -61,11 +63,14 @@ CompletionContextFinder::CompletionContextFinder(const QTextCursor &cursor)
// Initialize calls readLine - which skips empty lines. We should only adjust
// the start token index if the linizer still is in the same block as the cursor.
+ const int cursorPos = cursor.positionInBlock();
if (yyLinizerState.iter == cursor.block()) {
for (; m_startTokenIndex >= 0; --m_startTokenIndex) {
const Token &token = yyLinizerState.tokens.at(m_startTokenIndex);
- if (token.end() <= cursor.positionInBlock())
+ if (token.end() <= cursorPos)
break;
+ if (token.begin() < cursorPos && token.is(Token::String))
+ m_inStringLiteral = true;
}
if (m_startTokenIndex == yyLinizerState.tokens.size() - 1 && yyLinizerState.insertedSemicolon)
@@ -74,6 +79,7 @@ CompletionContextFinder::CompletionContextFinder(const QTextCursor &cursor)
getQmlObjectTypeName(m_startTokenIndex);
checkBinding();
+ checkImport();
}
void CompletionContextFinder::getQmlObjectTypeName(int startTokenIndex)
@@ -132,7 +138,6 @@ void CompletionContextFinder::checkBinding()
int i = m_startTokenIndex;
int colonCount = 0;
bool delimiterFound = false;
- bool firstToken = true;
bool identifierExpected = false;
bool dotExpected = false;
while (!delimiterFound) {
@@ -158,19 +163,19 @@ void CompletionContextFinder::checkBinding()
++colonCount;
identifierExpected = true;
dotExpected = false;
+ m_behaviorBinding = false;
m_bindingPropertyName.clear();
break;
case Token::Identifier: {
QStringRef tokenString = yyLine->midRef(token.begin(), token.length);
- if (firstToken && tokenString == QLatin1String("on")) {
- m_behaviorBinding = true;
- } else if (identifierExpected) {
+ dotExpected = false;
+ if (identifierExpected) {
m_bindingPropertyName.prepend(tokenString.toString());
identifierExpected = false;
dotExpected = true;
- } else {
- dotExpected = false;
+ } else if (tokenString == QLatin1String("on")) {
+ m_behaviorBinding = true;
}
} break;
@@ -190,7 +195,6 @@ void CompletionContextFinder::checkBinding()
}
--i;
- firstToken = false;
}
YY_RESTORE();
@@ -198,6 +202,92 @@ void CompletionContextFinder::checkBinding()
m_colonCount = colonCount;
}
+void CompletionContextFinder::checkImport()
+{
+ YY_SAVE();
+
+ //qDebug() << "Start line:" << *yyLine << m_startTokenIndex;
+
+ int i = m_startTokenIndex;
+ bool stop = false;
+ enum State {
+ Unknown,
+ ExpectImport = 1 << 0,
+ ExpectTargetDot = 1 << 1,
+ ExpectTargetIdentifier = 1 << 2,
+ ExpectAnyTarget = 1 << 3,
+ ExpectVersion = 1 << 4,
+ ExpectAs = 1 << 5
+ };
+ State state = Unknown;
+
+ while (!stop) {
+ if (i < 0) {
+ if (!readLine())
+ break;
+ else
+ i = yyLinizerState.tokens.size() - 1;
+ //qDebug() << "New Line" << *yyLine;
+ }
+
+ const Token &token = yyLinizerState.tokens.at(i);
+ //qDebug() << "Token:" << yyLine->mid(token.begin(), token.length);
+
+ switch (token.kind) {
+ case Token::Identifier: {
+ const QStringRef tokenString = yyLine->midRef(token.begin(), token.length);
+ if (tokenString == QLatin1String("as")) {
+ if (state == Unknown) {
+ state = State(ExpectAnyTarget | ExpectVersion);
+ break;
+ }
+ } else if (tokenString == QLatin1String("import")) {
+ if (state == Unknown || (state & ExpectImport)) {
+ m_inImport = true;
+ }
+ } else {
+ if (state == Unknown || (state & ExpectAnyTarget)
+ || (state & ExpectTargetIdentifier)) {
+ state = State(ExpectImport | ExpectTargetDot);
+ break;
+ }
+ }
+ stop = true;
+ break;
+ }
+ case Token::String:
+ if (state == Unknown || (state & ExpectAnyTarget)) {
+ state = ExpectImport;
+ break;
+ }
+ stop = true;
+ break;
+ case Token::Number:
+ if (state == Unknown || (state & ExpectVersion)) {
+ state = ExpectAnyTarget;
+ break;
+ }
+ stop = true;
+ break;
+ case Token::Dot:
+ if (state == Unknown || (state & ExpectTargetDot)) {
+ state = ExpectTargetIdentifier;
+ break;
+ }
+ stop = true;
+ break;
+
+ default:
+ stop = true;
+ break;
+ }
+
+ --i;
+ }
+
+ YY_RESTORE();
+}
+
QStringList CompletionContextFinder::qmlObjectTypeName() const
{
return m_qmlObjectTypeName;
@@ -232,6 +322,16 @@ bool CompletionContextFinder::isAfterOnInLhsOfBinding() const
return isInLhsOfBinding() && m_behaviorBinding;
}
+bool QmlJS::CompletionContextFinder::isInStringLiteral() const
+{
+ return m_inStringLiteral;
+}
+
+bool QmlJS::CompletionContextFinder::isInImport() const
+{
+ return m_inImport;
+}
+
int CompletionContextFinder::findOpeningBrace(int startTokenIndex)
{
YY_SAVE();
diff --git a/src/libs/qmljs/qmljscompletioncontextfinder.h b/src/libs/qmljs/qmljscompletioncontextfinder.h
index dfb07dfcc5..f708c1181b 100644
--- a/src/libs/qmljs/qmljscompletioncontextfinder.h
+++ b/src/libs/qmljs/qmljscompletioncontextfinder.h
@@ -56,10 +56,14 @@ public:
bool isAfterOnInLhsOfBinding() const;
QStringList bindingPropertyName() const;
+ bool isInStringLiteral() const;
+ bool isInImport() const;
+
private:
int findOpeningBrace(int startTokenIndex);
void getQmlObjectTypeName(int startTokenIndex);
void checkBinding();
+ void checkImport();
QTextCursor m_cursor;
QStringList m_qmlObjectTypeName;
@@ -67,6 +71,8 @@ private:
int m_startTokenIndex;
int m_colonCount;
bool m_behaviorBinding;
+ bool m_inStringLiteral;
+ bool m_inImport;
};
} // namespace QmlJS
diff --git a/src/libs/qmljs/qmljscomponentversion.cpp b/src/libs/qmljs/qmljscomponentversion.cpp
index c4151241fd..b74e2b9e3e 100644
--- a/src/libs/qmljs/qmljscomponentversion.cpp
+++ b/src/libs/qmljs/qmljscomponentversion.cpp
@@ -60,19 +60,19 @@ namespace QmlJS {
bool operator<(const ComponentVersion &lhs, const ComponentVersion &rhs)
{
- return lhs.major() < rhs.major()
- || (lhs.major() == rhs.major() && lhs.minor() < rhs.minor());
+ return lhs.majorVersion() < rhs.majorVersion()
+ || (lhs.majorVersion() == rhs.majorVersion() && lhs.minorVersion() < rhs.minorVersion());
}
bool operator<=(const ComponentVersion &lhs, const ComponentVersion &rhs)
{
- return lhs.major() < rhs.major()
- || (lhs.major() == rhs.major() && lhs.minor() <= rhs.minor());
+ return lhs.majorVersion() < rhs.majorVersion()
+ || (lhs.majorVersion() == rhs.majorVersion() && lhs.minorVersion() <= rhs.minorVersion());
}
bool operator==(const ComponentVersion &lhs, const ComponentVersion &rhs)
{
- return lhs.major() == rhs.major() && lhs.minor() == rhs.minor();
+ return lhs.majorVersion() == rhs.majorVersion() && lhs.minorVersion() == rhs.minorVersion();
}
bool operator!=(const ComponentVersion &lhs, const ComponentVersion &rhs)
diff --git a/src/libs/qmljs/qmljscomponentversion.h b/src/libs/qmljs/qmljscomponentversion.h
index 841111c1a3..f537fe6041 100644
--- a/src/libs/qmljs/qmljscomponentversion.h
+++ b/src/libs/qmljs/qmljscomponentversion.h
@@ -50,13 +50,6 @@ public:
ComponentVersion(int major, int minor);
~ComponentVersion();
- int major() const
- { return _major; }
- int minor() const
- { return _minor; }
-
- // something in the GNU headers introduces the major() and minor() defines,
- // use these two to disambiguate when necessary
int majorVersion() const
{ return _major; }
int minorVersion() const
diff --git a/src/libs/qmljs/qmljsdocument.cpp b/src/libs/qmljs/qmljsdocument.cpp
index 1b2c732d1f..0467117a63 100644
--- a/src/libs/qmljs/qmljsdocument.cpp
+++ b/src/libs/qmljs/qmljsdocument.cpp
@@ -163,6 +163,11 @@ AST::Node *Document::ast() const
return _ast;
}
+const QmlJS::Engine *Document::engine() const
+{
+ return _engine;
+}
+
QList<DiagnosticMessage> Document::diagnosticMessages() const
{
return _diagnosticMessages;
@@ -355,6 +360,7 @@ void Document::extractPragmas(QString *source)
LibraryInfo::LibraryInfo()
: _valid(false)
+ , _dumpStatus(DumpNotStartedOrRunning)
{
}
@@ -362,7 +368,7 @@ LibraryInfo::LibraryInfo(const QmlDirParser &parser)
: _valid(true)
, _components(parser.components())
, _plugins(parser.plugins())
- , _dumped(false)
+ , _dumpStatus(DumpNotStartedOrRunning)
{
}
diff --git a/src/libs/qmljs/qmljsdocument.h b/src/libs/qmljs/qmljsdocument.h
index 5b9ab6c4fa..a67ebea8ef 100644
--- a/src/libs/qmljs/qmljsdocument.h
+++ b/src/libs/qmljs/qmljsdocument.h
@@ -75,6 +75,8 @@ public:
AST::ExpressionNode *expression() const;
AST::Node *ast() const;
+ const QmlJS::Engine *engine() const;
+
QList<DiagnosticMessage> diagnosticMessages() const;
QString source() const;
@@ -121,12 +123,22 @@ private:
class QMLJS_EXPORT LibraryInfo
{
+public:
+ enum DumpStatus {
+ DumpNotStartedOrRunning,
+ DumpDone,
+ DumpError
+ };
+
+private:
bool _valid;
QList<QmlDirParser::Component> _components;
QList<QmlDirParser::Plugin> _plugins;
typedef QList<const Interpreter::FakeMetaObject *> FakeMetaObjectList;
FakeMetaObjectList _metaObjects;
- bool _dumped;
+
+ DumpStatus _dumpStatus;
+ QString _dumpError;
public:
LibraryInfo();
@@ -148,11 +160,14 @@ public:
bool isValid() const
{ return _valid; }
- bool isDumped() const
- { return _dumped; }
+ DumpStatus dumpStatus() const
+ { return _dumpStatus; }
+
+ QString dumpError() const
+ { return _dumpError; }
- void setDumped(bool dumped)
- { _dumped = dumped; }
+ void setDumpStatus(DumpStatus dumped, const QString &error = QString())
+ { _dumpStatus = dumped; _dumpError = error; }
};
class QMLJS_EXPORT Snapshot
diff --git a/src/libs/qmljs/qmljsevaluate.cpp b/src/libs/qmljs/qmljsevaluate.cpp
index 0cc4ae8c0e..f9aa3f5319 100644
--- a/src/libs/qmljs/qmljsevaluate.cpp
+++ b/src/libs/qmljs/qmljsevaluate.cpp
@@ -454,7 +454,7 @@ bool Evaluate::visit(AST::EmptyStatement *)
bool Evaluate::visit(AST::ExpressionStatement *)
{
- return false;
+ return true;
}
bool Evaluate::visit(AST::IfStatement *)
diff --git a/src/libs/qmljs/qmljsinterpreter.cpp b/src/libs/qmljs/qmljsinterpreter.cpp
index 7c2c4e8dd4..1c1bb44255 100644
--- a/src/libs/qmljs/qmljsinterpreter.cpp
+++ b/src/libs/qmljs/qmljsinterpreter.cpp
@@ -186,10 +186,12 @@ class FakeMetaProperty {
QString m_propertyName;
QString m_type;
bool m_isList;
+ bool m_isWritable;
+ bool m_isPointer;
public:
- FakeMetaProperty(const QString &name, const QString &type, bool isList)
- : m_propertyName(name), m_type(type), m_isList(isList)
+ FakeMetaProperty(const QString &name, const QString &type, bool isList, bool isWritable, bool isPointer)
+ : m_propertyName(name), m_type(type), m_isList(isList), m_isWritable(isWritable), m_isPointer(isPointer)
{}
QString name() const
@@ -200,6 +202,12 @@ public:
bool isList() const
{ return m_isList; }
+
+ bool isWritable() const
+ { return m_isWritable; }
+
+ bool isPointer() const
+ { return m_isPointer; }
};
class FakeMetaObject {
@@ -494,6 +502,8 @@ private:
QString name, type;
bool isList = false;
+ bool isWritable = false;
+ bool isPointer = false;
foreach (const QXmlStreamAttribute &attr, _xml.attributes()) {
if (attr.name() == QLatin1String("name")) {
name = attr.value().toString();
@@ -505,7 +515,25 @@ private:
} else if (attr.value() == QLatin1String("false")) {
isList = false;
} else {
- invalidAttr(attr.value().toString(), QLatin1String("idList"), tag);
+ invalidAttr(attr.value().toString(), QLatin1String("isList"), tag);
+ return;
+ }
+ } else if (attr.name() == QLatin1String("isWritable")) {
+ if (attr.value() == QLatin1String("true")) {
+ isWritable = true;
+ } else if (attr.value() == QLatin1String("false")) {
+ isWritable = false;
+ } else {
+ invalidAttr(attr.value().toString(), QLatin1String("isWritable"), tag);
+ return;
+ }
+ } else if (attr.name() == QLatin1String("isPointer")) {
+ if (attr.value() == QLatin1String("true")) {
+ isPointer = true;
+ } else if (attr.value() == QLatin1String("false")) {
+ isPointer = false;
+ } else {
+ invalidAttr(attr.value().toString(), QLatin1String("isPointer"), tag);
return;
}
} else {
@@ -518,7 +546,7 @@ private:
else if (type.isEmpty())
noValidAttr(QLatin1String("type"), tag);
else
- createProperty(metaObject, name, type, isList);
+ createProperty(metaObject, name, type, isList, isWritable, isPointer);
while (_xml.readNextStartElement()) {
unexpectedElement(_xml.name(), tag);
@@ -526,10 +554,10 @@ private:
}
void createProperty(FakeMetaObject *metaObject, const QString &name,
- const QString &type, bool isList) {
+ const QString &type, bool isList, bool isWritable, bool isPointer) {
Q_ASSERT(metaObject);
- metaObject->addProperty(FakeMetaProperty(name, type, isList));
+ metaObject->addProperty(FakeMetaProperty(name, type, isList, isWritable, isPointer));
}
void readEnum(FakeMetaObject *metaObject)
@@ -645,6 +673,7 @@ private:
name = attr.value().toString();
} else if (attr.name() == QLatin1String("type")) {
type = attr.value().toString();
+ } else if (attr.name() == QLatin1String("isPointer")) {
} else {
ignoreAttr(attr);
}
@@ -759,12 +788,14 @@ private:
} // end of anonymous namespace
-QmlObjectValue::QmlObjectValue(const FakeMetaObject *metaObject, int exportIndex, Engine *engine)
+QmlObjectValue::QmlObjectValue(const FakeMetaObject *metaObject, const QString &className,
+ const QString &packageName, const QmlJS::ComponentVersion version, Engine *engine)
: ObjectValue(engine),
_metaObject(metaObject),
- _exportIndex(exportIndex)
+ _packageName(packageName),
+ _componentVersion(version)
{
- setClassName(metaObject->exports().at(exportIndex).type); // ### TODO: we probably need to do more than just this...
+ setClassName(className);
}
QmlObjectValue::~QmlObjectValue()
@@ -831,25 +862,30 @@ const Value *QmlObjectValue::propertyValue(const FakeMetaProperty &prop) const
// ### Verify type resolving.
QmlObjectValue *objectValue = engine()->cppQmlTypes().typeForImport(typeName);
- if (objectValue)
+ if (objectValue) {
+ QString packageClassName = objectValue->nameInPackage(packageName());
+ if (!packageClassName.isEmpty())
+ objectValue = engine()->cppQmlTypes().typeForImport(packageName() + '.' + packageClassName);
return objectValue;
+ }
const Value *value = engine()->undefinedValue();
if (typeName == QLatin1String("QByteArray")
|| typeName == QLatin1String("string")
- || typeName == QLatin1String("QString")
- || typeName == QLatin1String("QUrl")) {
+ || typeName == QLatin1String("QString")) {
value = engine()->stringValue();
+ } else if (typeName == QLatin1String("QUrl")) {
+ value = engine()->urlValue();
} else if (typeName == QLatin1String("bool")) {
value = engine()->booleanValue();
} else if (typeName == QLatin1String("int")
- || typeName == QLatin1String("float")
- || typeName == QLatin1String("double")
- || typeName == QLatin1String("qreal")
- || typeName == QLatin1String("long")
- // ### Review: more types here?
- ) {
- value = engine()->numberValue();
+ || typeName == QLatin1String("long")) {
+ value = engine()->intValue();
+ } else if (typeName == QLatin1String("float")
+ || typeName == QLatin1String("double")
+ || typeName == QLatin1String("qreal")) {
+ // ### Review: more types here?
+ value = engine()->realValue();
} else if (typeName == QLatin1String("QFont")) {
value = engine()->qmlFontObject();
} else if (typeName == QLatin1String("QPoint")
@@ -881,10 +917,18 @@ const Value *QmlObjectValue::propertyValue(const FakeMetaProperty &prop) const
}
QString QmlObjectValue::packageName() const
-{ return _metaObject->exports().at(_exportIndex).package; }
+{ return _packageName; }
+
+QString QmlObjectValue::nameInPackage(const QString &packageName) const
+{
+ foreach (const FakeMetaObject::Export &exp, _metaObject->exports())
+ if (exp.package == packageName)
+ return exp.type;
+ return QString();
+}
QmlJS::ComponentVersion QmlObjectValue::version() const
-{ return _metaObject->exports().at(_exportIndex).version; }
+{ return _componentVersion; }
QString QmlObjectValue::defaultPropertyName() const
{ return _metaObject->defaultPropertyName(); }
@@ -892,21 +936,23 @@ QString QmlObjectValue::defaultPropertyName() const
QString QmlObjectValue::propertyType(const QString &propertyName) const
{
for (const FakeMetaObject *iter = _metaObject; iter; iter = iter->superClass()) {
- int propIdx = _metaObject->propertyIndex(propertyName);
+ int propIdx = iter->propertyIndex(propertyName);
if (propIdx != -1) {
- return _metaObject->property(propIdx).typeName();
+ return iter->property(propIdx).typeName();
}
}
return QString();
}
-bool QmlObjectValue::isListProperty(const QString &name) const
+bool QmlObjectValue::isListProperty(const QString &propertyName) const
{
- int idx = _metaObject->propertyIndex(name);
- if (idx == -1)
- return false;
- FakeMetaProperty prop = _metaObject->property(idx);
- return prop.isList();
+ for (const FakeMetaObject *iter = _metaObject; iter; iter = iter->superClass()) {
+ int propIdx = iter->propertyIndex(propertyName);
+ if (propIdx != -1) {
+ return iter->property(propIdx).isList();
+ }
+ }
+ return false;
}
bool QmlObjectValue::isEnum(const QString &typeName) const
@@ -914,6 +960,47 @@ bool QmlObjectValue::isEnum(const QString &typeName) const
return _metaObject->enumeratorIndex(typeName) != -1;
}
+bool QmlObjectValue::isWritable(const QString &propertyName) const
+{
+ for (const FakeMetaObject *iter = _metaObject; iter; iter = iter->superClass()) {
+ int propIdx = iter->propertyIndex(propertyName);
+ if (propIdx != -1) {
+ return iter->property(propIdx).isWritable();
+ }
+ }
+ return false;
+}
+
+bool QmlObjectValue::isPointer(const QString &propertyName) const
+{
+ for (const FakeMetaObject *iter = _metaObject; iter; iter = iter->superClass()) {
+ int propIdx = iter->propertyIndex(propertyName);
+ if (propIdx != -1) {
+ return iter->property(propIdx).isPointer();
+ }
+ }
+ return false;
+}
+
+bool QmlObjectValue::hasLocalProperty(const QString &typeName) const
+{
+ int idx = _metaObject->propertyIndex(typeName);
+ if (idx == -1)
+ return false;
+ return true;
+}
+
+bool QmlObjectValue::hasProperty(const QString &propertyName) const
+{
+ for (const FakeMetaObject *iter = _metaObject; iter; iter = iter->superClass()) {
+ int propIdx = iter->propertyIndex(propertyName);
+ if (propIdx != -1) {
+ return true;
+ }
+ }
+ return false;
+}
+
bool QmlObjectValue::enumContainsKey(const QString &enumName, const QString &enumKeyName) const
{
int idx = _metaObject->enumeratorIndex(enumName);
@@ -927,6 +1014,15 @@ bool QmlObjectValue::enumContainsKey(const QString &enumName, const QString &enu
return false;
}
+QStringList QmlObjectValue::keysForEnum(const QString &enumName) const
+{
+ int idx = _metaObject->enumeratorIndex(enumName);
+ if (idx == -1)
+ return QStringList();
+ const FakeMetaEnum &fme = _metaObject->enumerator(idx);
+ return fme.keys();
+}
+
// Returns true if this object is in a package or if there is an object that
// has this one in its prototype chain and is itself in a package.
bool QmlObjectValue::hasChildInPackage() const
@@ -1269,6 +1365,16 @@ const NumberValue *Value::asNumberValue() const
return 0;
}
+const IntValue *Value::asIntValue() const
+{
+ return 0;
+}
+
+const RealValue *Value::asRealValue() const
+{
+ return 0;
+}
+
const BooleanValue *Value::asBooleanValue() const
{
return 0;
@@ -1279,6 +1385,11 @@ const StringValue *Value::asStringValue() const
return 0;
}
+const UrlValue *Value::asUrlValue() const
+{
+ return 0;
+}
+
const ObjectValue *Value::asObjectValue() const
{
return 0;
@@ -1332,6 +1443,16 @@ const NumberValue *NumberValue::asNumberValue() const
return this;
}
+const RealValue *RealValue::asRealValue() const
+{
+ return this;
+}
+
+const IntValue *IntValue::asIntValue() const
+{
+ return this;
+}
+
void NumberValue::accept(ValueVisitor *visitor) const
{
visitor->visit(this);
@@ -1352,6 +1473,11 @@ const StringValue *StringValue::asStringValue() const
return this;
}
+const UrlValue *UrlValue::asUrlValue() const
+{
+ return this;
+}
+
void StringValue::accept(ValueVisitor *visitor) const
{
visitor->visit(this);
@@ -1462,14 +1588,14 @@ const TypeEnvironment *Context::typeEnvironment(const QmlJS::Document *doc) cons
{
if (!doc)
return 0;
- return _typeEnvironments.value(doc->fileName(), 0);
+ return _typeEnvironments.value(doc, 0);
}
void Context::setTypeEnvironment(const QmlJS::Document *doc, const TypeEnvironment *typeEnvironment)
{
if (!doc)
return;
- _typeEnvironments[doc->fileName()] = typeEnvironment;
+ _typeEnvironments[doc] = typeEnvironment;
}
const Value *Context::lookup(const QString &name, const ObjectValue **foundInScope) const
@@ -1553,7 +1679,9 @@ void Context::setProperty(const ObjectValue *object, const QString &name, const
QString Context::defaultPropertyName(const ObjectValue *object) const
{
- for (const ObjectValue *o = object; o; o = o->prototype(this)) {
+ PrototypeIterator iter(object, this);
+ while (iter.hasNext()) {
+ const ObjectValue *o = iter.next();
if (const ASTObjectValue *astObjValue = dynamic_cast<const ASTObjectValue *>(o)) {
QString defaultProperty = astObjValue->defaultPropertyName();
if (!defaultProperty.isEmpty())
@@ -1747,28 +1875,88 @@ void ObjectValue::processMembers(MemberProcessor *processor) const
}
}
-const Value *ObjectValue::lookupMember(const QString &name, const Context *context, bool examinePrototypes) const
+const Value *ObjectValue::lookupMember(const QString &name, const Context *context,
+ const ObjectValue **foundInObject,
+ bool examinePrototypes) const
{
- if (const Value *m = _members.value(name))
+ if (const Value *m = _members.value(name)) {
+ if (foundInObject)
+ *foundInObject = this;
return m;
- else {
+ } else {
LookupMember slowLookup(name);
processMembers(&slowLookup);
- if (slowLookup.value())
+ if (slowLookup.value()) {
+ if (foundInObject)
+ *foundInObject = this;
return slowLookup.value();
+ }
}
if (examinePrototypes) {
- const ObjectValue *prototypeObject = prototype(context);
- if (prototypeObject) {
- if (const Value *m = prototypeObject->lookupMember(name, context))
+ PrototypeIterator iter(this, context);
+ iter.next(); // skip this
+ while (iter.hasNext()) {
+ const ObjectValue *prototypeObject = iter.next();
+ if (const Value *m = prototypeObject->lookupMember(name, context, foundInObject, false))
return m;
}
}
+ if (foundInObject)
+ *foundInObject = 0;
return 0;
}
+PrototypeIterator::PrototypeIterator(const ObjectValue *start, const Context *context)
+ : m_current(0)
+ , m_next(start)
+ , m_context(context)
+{
+ if (start)
+ m_prototypes.reserve(10);
+}
+
+bool PrototypeIterator::hasNext()
+{
+ if (m_next)
+ return true;
+ if (!m_current)
+ return false;
+ m_next = m_current->prototype(m_context);
+ if (!m_next || m_prototypes.contains(m_next)) {
+ m_next = 0;
+ return false;
+ }
+ return true;
+}
+
+const ObjectValue *PrototypeIterator::next()
+{
+ if (hasNext()) {
+ m_current = m_next;
+ m_prototypes += m_next;
+ m_next = 0;
+ return m_current;
+ }
+ return 0;
+}
+
+const ObjectValue *PrototypeIterator::peekNext()
+{
+ if (hasNext()) {
+ return m_next;
+ }
+ return 0;
+}
+
+QList<const ObjectValue *> PrototypeIterator::all()
+{
+ while (hasNext())
+ next();
+ return m_prototypes;
+}
+
Activation::Activation(Context *parentContext)
: _thisObject(0),
_calledAsFunction(true),
@@ -2035,35 +2223,34 @@ void CppQmlTypes::load(Engine *engine, const QList<const FakeMetaObject *> &obje
if (_typesByFullyQualifiedName.contains(exp.packageNameVersion))
continue;
- QmlObjectValue *objectValue = new QmlObjectValue(metaObject, i, engine);
+ QmlObjectValue *objectValue = new QmlObjectValue(
+ metaObject, exp.type, exp.package, exp.version, engine);
_typesByPackage[exp.package].append(objectValue);
_typesByFullyQualifiedName[exp.packageNameVersion] = objectValue;
}
}
- // set prototype correctly
+ // set prototypes
foreach (const FakeMetaObject *metaObject, objects) {
foreach (const FakeMetaObject::Export &exp, metaObject->exports()) {
QmlObjectValue *objectValue = _typesByFullyQualifiedName.value(exp.packageNameVersion);
if (!objectValue || !metaObject->superClass())
continue;
- bool found = false;
- // try to get a prototype from the library first
- foreach (const FakeMetaObject::Export &superExports, metaObject->superClass()->exports()) {
- if (superExports.package == exp.package) {
- objectValue->setPrototype(_typesByFullyQualifiedName.value(superExports.packageNameVersion));
- found = true;
- break;
- }
- }
- if (found)
- continue;
- // otherwise, just use the first available
- if (!metaObject->superClass()->exports().isEmpty()) {
- objectValue->setPrototype(_typesByFullyQualifiedName.value(metaObject->superClass()->exports().first().packageNameVersion));
- continue;
+
+ // set prototypes for whole chain, creating new QmlObjectValues if necessary
+ // for instance, if an type isn't exported in the package of the super type
+ // Example: QObject (Qt, QtQuick) -> Positioner (not exported) -> Column (Qt, QtQuick)
+ // needs to create Positioner (Qt) and Positioner (QtQuick)
+ bool created = true;
+ QmlObjectValue *v = objectValue;
+ const FakeMetaObject *fmo = metaObject;
+ while (created && fmo->superClass()) {
+ QmlObjectValue *superValue = getOrCreate(exp.package, fmo->superclassName(),
+ fmo->superClass(), engine, &created);
+ v->setPrototype(superValue);
+ v = superValue;
+ fmo = fmo->superClass();
}
- //qWarning() << "Could not find super class for " << exp.packageNameVersion;
}
}
}
@@ -2092,7 +2279,8 @@ QList<QmlObjectValue *> CppQmlTypes::typesForImport(const QString &packageName,
return objectValuesByName.values();
}
-QmlObjectValue *CppQmlTypes::typeForImport(const QString &qualifiedName) const
+QmlObjectValue *CppQmlTypes::typeForImport(const QString &qualifiedName,
+ QmlJS::ComponentVersion version) const
{
QString name = qualifiedName;
QString packageName;
@@ -2107,6 +2295,8 @@ QmlObjectValue *CppQmlTypes::typeForImport(const QString &qualifiedName) const
const QString typeName = qmlObjectValue->className();
if (typeName != name)
continue;
+ if (version.isValid() && version < qmlObjectValue->version())
+ continue;
if (previousCandidate) {
// check if our new candidate is newer than the one we found previously
@@ -2127,6 +2317,51 @@ bool CppQmlTypes::hasPackage(const QString &package) const
return _typesByPackage.contains(package);
}
+QString CppQmlTypes::qualifiedName(const QString &package, const QString &type, QmlJS::ComponentVersion version)
+{
+ return QString("%1.%2 %3.%4").arg(
+ package, type,
+ QString::number(version.majorVersion()),
+ QString::number(version.minorVersion()));
+}
+
+QmlObjectValue *CppQmlTypes::typeByQualifiedName(const QString &name) const
+{
+ return _typesByFullyQualifiedName.value(name);
+}
+
+QmlObjectValue *CppQmlTypes::typeByQualifiedName(const QString &package, const QString &type, QmlJS::ComponentVersion version) const
+{
+ return typeByQualifiedName(qualifiedName(package, type, version));
+}
+
+QmlObjectValue *CppQmlTypes::getOrCreate(const QString &package, const QString &cppName,
+ const FakeMetaObject *metaObject, Engine *engine, bool *created)
+{
+ QString typeName = cppName;
+ ComponentVersion version;
+ foreach (const FakeMetaObject::Export &exp, metaObject->exports()) {
+ if (exp.package == package) {
+ typeName = exp.type;
+ version = exp.version;
+ break;
+ }
+ }
+
+ const QString qName = qualifiedName(package, typeName, version);
+ QmlObjectValue *value = typeByQualifiedName(qName);
+ if (!value) {
+ *created = true;
+ value = new QmlObjectValue(
+ metaObject, typeName, package, QmlJS::ComponentVersion(), engine);
+ _typesByFullyQualifiedName[qName] = value;
+ } else {
+ *created = false;
+ }
+
+ return value;
+}
+
ConvertToNumber::ConvertToNumber(Engine *engine)
: _engine(engine), _result(0)
{
@@ -2433,6 +2668,16 @@ const NumberValue *Engine::numberValue() const
return &_numberValue;
}
+const RealValue *Engine::realValue() const
+{
+ return &_realValue;
+}
+
+const IntValue *Engine::intValue() const
+{
+ return &_intValue;
+}
+
const BooleanValue *Engine::booleanValue() const
{
return &_booleanValue;
@@ -2443,6 +2688,11 @@ const StringValue *Engine::stringValue() const
return &_stringValue;
}
+const UrlValue *Engine::urlValue() const
+{
+ return &_urlValue;
+}
+
const ColorValue *Engine::colorValue() const
{
return &_colorValue;
@@ -2917,10 +3167,10 @@ void Engine::initializePrototypes()
_qmlFontObject->setProperty("underline", booleanValue());
_qmlFontObject->setProperty("overline", booleanValue());
_qmlFontObject->setProperty("strikeout", booleanValue());
- _qmlFontObject->setProperty("pointSize", numberValue());
- _qmlFontObject->setProperty("pixelSize", numberValue());
- _qmlFontObject->setProperty("letterSpacing", numberValue());
- _qmlFontObject->setProperty("wordSpacing", numberValue());
+ _qmlFontObject->setProperty("pointSize", intValue());
+ _qmlFontObject->setProperty("pixelSize", intValue());
+ _qmlFontObject->setProperty("letterSpacing", realValue());
+ _qmlFontObject->setProperty("wordSpacing", realValue());
_qmlPointObject = newObject(/*prototype =*/ 0);
_qmlPointObject->setClassName(QLatin1String("Point"));
@@ -2941,9 +3191,9 @@ void Engine::initializePrototypes()
_qmlVector3DObject = newObject(/*prototype =*/ 0);
_qmlVector3DObject->setClassName(QLatin1String("Vector3D"));
- _qmlVector3DObject->setProperty("x", numberValue());
- _qmlVector3DObject->setProperty("y", numberValue());
- _qmlVector3DObject->setProperty("z", numberValue());
+ _qmlVector3DObject->setProperty("x", realValue());
+ _qmlVector3DObject->setProperty("y", realValue());
+ _qmlVector3DObject->setProperty("z", realValue());
}
const ObjectValue *Engine::qmlKeysObject()
@@ -2978,12 +3228,16 @@ const ObjectValue *Engine::qmlVector3DObject()
const Value *Engine::defaultValueForBuiltinType(const QString &typeName) const
{
- if (typeName == QLatin1String("string") || typeName == QLatin1String("url"))
+ if (typeName == QLatin1String("string"))
return stringValue();
+ else if (typeName == QLatin1String("url"))
+ return urlValue();
else if (typeName == QLatin1String("bool"))
return booleanValue();
- else if (typeName == QLatin1String("int") || typeName == QLatin1String("real"))
- return numberValue();
+ else if (typeName == QLatin1String("int"))
+ return intValue();
+ else if (typeName == QLatin1String("real"))
+ return realValue();
else if (typeName == QLatin1String("color"))
return colorValue();
// ### more types...
@@ -3053,6 +3307,21 @@ QString ASTObjectValue::defaultPropertyName() const
return QString();
}
+UiObjectInitializer *ASTObjectValue::initializer() const
+{
+ return _initializer;
+}
+
+UiQualifiedId *ASTObjectValue::typeName() const
+{
+ return _typeName;
+}
+
+const QmlJS::Document *ASTObjectValue::document() const
+{
+ return _doc;
+}
+
ASTVariableReference::ASTVariableReference(VariableDeclaration *ast, Engine *engine)
: Reference(engine), _ast(ast)
{
@@ -3068,7 +3337,7 @@ const Value *ASTVariableReference::value(const Context *context) const
return check(_ast->expression);
}
-ASTFunctionValue::ASTFunctionValue(FunctionDeclaration *ast, const QmlJS::Document *doc, Engine *engine)
+ASTFunctionValue::ASTFunctionValue(FunctionExpression *ast, const QmlJS::Document *doc, Engine *engine)
: FunctionValue(engine), _ast(ast), _doc(doc)
{
setPrototype(engine->functionPrototype());
@@ -3081,7 +3350,7 @@ ASTFunctionValue::~ASTFunctionValue()
{
}
-FunctionDeclaration *ASTFunctionValue::ast() const
+FunctionExpression *ASTFunctionValue::ast() const
{
return _ast;
}
@@ -3260,7 +3529,8 @@ TypeEnvironment::TypeEnvironment(Engine *engine)
{
}
-const Value *TypeEnvironment::lookupMember(const QString &name, const Context *context, bool) const
+const Value *TypeEnvironment::lookupMember(const QString &name, const Context *context,
+ const ObjectValue **foundInObject, bool) const
{
QHashIterator<const ObjectValue *, ImportInfo> it(_imports);
while (it.hasNext()) {
@@ -3269,19 +3539,27 @@ const Value *TypeEnvironment::lookupMember(const QString &name, const Context *c
const ImportInfo &info = it.value();
if (!info.id().isEmpty()) {
- if (info.id() == name)
+ if (info.id() == name) {
+ if (foundInObject)
+ *foundInObject = this;
return import;
+ }
continue;
}
if (info.type() == ImportInfo::FileImport) {
- if (import->className() == name)
+ if (import->className() == name) {
+ if (foundInObject)
+ *foundInObject = this;
return import;
+ }
} else {
- if (const Value *v = import->property(name, context))
+ if (const Value *v = import->lookupMember(name, context, foundInObject))
return v;
}
}
+ if (foundInObject)
+ *foundInObject = 0;
return 0;
}
diff --git a/src/libs/qmljs/qmljsinterpreter.h b/src/libs/qmljs/qmljsinterpreter.h
index 72fd88a917..c1cff60d92 100644
--- a/src/libs/qmljs/qmljsinterpreter.h
+++ b/src/libs/qmljs/qmljsinterpreter.h
@@ -61,8 +61,11 @@ class Value;
class NullValue;
class UndefinedValue;
class NumberValue;
+class IntValue;
+class RealValue;
class BooleanValue;
class StringValue;
+class UrlValue;
class ObjectValue;
class FunctionValue;
class Reference;
@@ -113,8 +116,11 @@ public:
virtual const NullValue *asNullValue() const;
virtual const UndefinedValue *asUndefinedValue() const;
virtual const NumberValue *asNumberValue() const;
+ virtual const IntValue *asIntValue() const;
+ virtual const RealValue *asRealValue() const;
virtual const BooleanValue *asBooleanValue() const;
virtual const StringValue *asStringValue() const;
+ virtual const UrlValue *asUrlValue() const;
virtual const ObjectValue *asObjectValue() const;
virtual const FunctionValue *asFunctionValue() const;
virtual const Reference *asReference() const;
@@ -146,6 +152,18 @@ template <> Q_INLINE_TEMPLATE const NumberValue *value_cast(const Value *v)
else return 0;
}
+template <> Q_INLINE_TEMPLATE const IntValue *value_cast(const Value *v)
+{
+ if (v) return v->asIntValue();
+ else return 0;
+}
+
+template <> Q_INLINE_TEMPLATE const RealValue *value_cast(const Value *v)
+{
+ if (v) return v->asRealValue();
+ else return 0;
+}
+
template <> Q_INLINE_TEMPLATE const BooleanValue *value_cast(const Value *v)
{
if (v) return v->asBooleanValue();
@@ -158,6 +176,12 @@ template <> Q_INLINE_TEMPLATE const StringValue *value_cast(const Value *v)
else return 0;
}
+template <> Q_INLINE_TEMPLATE const UrlValue *value_cast(const Value *v)
+{
+ if (v) return v->asUrlValue();
+ else return 0;
+}
+
template <> Q_INLINE_TEMPLATE const ObjectValue *value_cast(const Value *v)
{
if (v) return v->asObjectValue();
@@ -212,6 +236,18 @@ public:
virtual void accept(ValueVisitor *visitor) const;
};
+class QMLJS_EXPORT RealValue: public NumberValue
+{
+public:
+ virtual const RealValue *asRealValue() const;
+};
+
+class QMLJS_EXPORT IntValue: public NumberValue
+{
+public:
+ virtual const IntValue *asIntValue() const;
+};
+
class QMLJS_EXPORT BooleanValue: public Value
{
public:
@@ -226,6 +262,12 @@ public:
virtual void accept(ValueVisitor *visitor) const;
};
+class QMLJS_EXPORT UrlValue: public StringValue
+{
+public:
+ virtual const UrlValue *asUrlValue() const;
+};
+
class QMLJS_EXPORT MemberProcessor
{
MemberProcessor(const MemberProcessor &other);
@@ -304,7 +346,7 @@ private:
QSharedPointer<Engine> _engine;
QHash<const ObjectValue *, Properties> _properties;
- QHash<QString, const TypeEnvironment *> _typeEnvironments;
+ QHash<const Document *, const TypeEnvironment *> _typeEnvironments;
ScopeChain _scopeChain;
int _qmlScopeObjectIndex;
bool _qmlScopeObjectSet;
@@ -359,6 +401,7 @@ public:
QString className() const;
void setClassName(const QString &className);
+ // not guaranteed to not recurse, use PrototypeIterator!
const ObjectValue *prototype(const Context *context) const;
void setPrototype(const Value *prototype);
@@ -368,7 +411,9 @@ public:
virtual void setProperty(const QString &name, const Value *value);
virtual void removeProperty(const QString &name);
- virtual const Value *lookupMember(const QString &name, const Context *context, bool examinePrototypes = true) const;
+ virtual const Value *lookupMember(const QString &name, const Context *context,
+ const ObjectValue **foundInObject = 0,
+ bool examinePrototypes = true) const;
// Value interface
virtual const ObjectValue *asObjectValue() const;
@@ -384,22 +429,47 @@ private:
QString _className;
};
+class QMLJS_EXPORT PrototypeIterator
+{
+public:
+ PrototypeIterator(const ObjectValue *start, const Context *context);
+
+ bool hasNext();
+ const ObjectValue *peekNext();
+ const ObjectValue *next();
+
+ QList<const ObjectValue *> all();
+
+private:
+ const ObjectValue *m_current;
+ const ObjectValue *m_next;
+ QList<const ObjectValue *> m_prototypes;
+ const Context *m_context;
+};
+
class QMLJS_EXPORT QmlObjectValue: public ObjectValue
{
public:
- QmlObjectValue(const FakeMetaObject *metaObject, int exportIndex, Engine *engine);
+ QmlObjectValue(const FakeMetaObject *metaObject, const QString &className,
+ const QString &packageName, const ComponentVersion version, Engine *engine);
virtual ~QmlObjectValue();
virtual void processMembers(MemberProcessor *processor) const;
const Value *propertyValue(const FakeMetaProperty &prop) const;
QString packageName() const;
+ QString nameInPackage(const QString &packageName) const;
ComponentVersion version() const;
QString defaultPropertyName() const;
QString propertyType(const QString &propertyName) const;
bool isListProperty(const QString &name) const;
+ bool isWritable(const QString &propertyName) const;
+ bool isPointer(const QString &propertyName) const;
bool isEnum(const QString &typeName) const;
+ bool hasLocalProperty(const QString &typeName) const;
+ bool hasProperty(const QString &typeName) const;
bool enumContainsKey(const QString &enumName, const QString &enumKeyName) const;
+ QStringList keysForEnum(const QString &enumName) const;
bool hasChildInPackage() const;
protected:
@@ -408,7 +478,8 @@ protected:
private:
const FakeMetaObject *_metaObject;
- const int _exportIndex;
+ const QString _packageName;
+ const ComponentVersion _componentVersion;
mutable QHash<int, const Value *> _metaSignature;
};
@@ -531,14 +602,22 @@ public:
void load(Interpreter::Engine *interpreter, const QList<const FakeMetaObject *> &objects);
QList<Interpreter::QmlObjectValue *> typesForImport(const QString &prefix, ComponentVersion version) const;
- Interpreter::QmlObjectValue *typeForImport(const QString &qualifiedName) const;
+ Interpreter::QmlObjectValue *typeForImport(const QString &qualifiedName,
+ ComponentVersion version = ComponentVersion()) const;
bool hasPackage(const QString &package) const;
QHash<QString, QmlObjectValue *> types() const
{ return _typesByFullyQualifiedName; }
+ static QString qualifiedName(const QString &package, const QString &type, ComponentVersion version);
+ QmlObjectValue *typeByQualifiedName(const QString &name) const;
+ QmlObjectValue *typeByQualifiedName(const QString &package, const QString &type, ComponentVersion version) const;
+
private:
+ QmlObjectValue *getOrCreate(const QString &package, const QString &cppName, const FakeMetaObject *metaObject, Engine *engine, bool *created);
+
+
QHash<QString, QList<QmlObjectValue *> > _typesByPackage;
QHash<QString, QmlObjectValue *> _typesByFullyQualifiedName;
};
@@ -612,7 +691,7 @@ private:
const Value *_result;
};
-class TypeId: protected ValueVisitor
+class QMLJS_EXPORT TypeId: protected ValueVisitor
{
QString _result;
@@ -642,8 +721,11 @@ public:
const NullValue *nullValue() const;
const UndefinedValue *undefinedValue() const;
const NumberValue *numberValue() const;
+ const RealValue *realValue() const;
+ const IntValue *intValue() const;
const BooleanValue *booleanValue() const;
const StringValue *stringValue() const;
+ const UrlValue *urlValue() const;
const ColorValue *colorValue() const;
const AnchorLineValue *anchorLineValue() const;
@@ -740,8 +822,11 @@ private:
NullValue _nullValue;
UndefinedValue _undefinedValue;
NumberValue _numberValue;
+ RealValue _realValue;
+ IntValue _intValue;
BooleanValue _booleanValue;
StringValue _stringValue;
+ UrlValue _urlValue;
ColorValue _colorValue;
AnchorLineValue _anchorLineValue;
QList<Value *> _registeredValues;
@@ -787,15 +872,15 @@ private:
class QMLJS_EXPORT ASTFunctionValue: public FunctionValue
{
- AST::FunctionDeclaration *_ast;
+ AST::FunctionExpression *_ast;
const Document *_doc;
QList<NameId *> _argumentNames;
public:
- ASTFunctionValue(AST::FunctionDeclaration *ast, const Document *doc, Engine *engine);
+ ASTFunctionValue(AST::FunctionExpression *ast, const Document *doc, Engine *engine);
virtual ~ASTFunctionValue();
- AST::FunctionDeclaration *ast() const;
+ AST::FunctionExpression *ast() const;
virtual const Value *returnValue() const;
virtual int argumentCount() const;
@@ -864,6 +949,10 @@ public:
virtual void processMembers(MemberProcessor *processor) const;
QString defaultPropertyName() const;
+
+ AST::UiObjectInitializer *initializer() const;
+ AST::UiQualifiedId *typeName() const;
+ const Document *document() const;
};
class QMLJS_EXPORT ImportInfo
@@ -875,7 +964,7 @@ public:
LibraryImport,
FileImport,
DirectoryImport,
- UnknownFileImport // refers a file/directoy that wasn't found
+ UnknownFileImport // refers a file/directory that wasn't found
};
ImportInfo();
@@ -910,7 +999,9 @@ class QMLJS_EXPORT TypeEnvironment: public ObjectValue
public:
TypeEnvironment(Engine *engine);
- virtual const Value *lookupMember(const QString &name, const Context *context, bool examinePrototypes) const;
+ virtual const Value *lookupMember(const QString &name, const Context *context,
+ const ObjectValue **foundInObject = 0,
+ bool examinePrototypes = true) const;
virtual void processMembers(MemberProcessor *processor) const;
void addImport(const ObjectValue *import, const ImportInfo &info);
diff --git a/src/libs/qmljs/qmljslineinfo.cpp b/src/libs/qmljs/qmljslineinfo.cpp
index c172388c39..08386b7ccc 100644
--- a/src/libs/qmljs/qmljslineinfo.cpp
+++ b/src/libs/qmljs/qmljslineinfo.cpp
@@ -195,9 +195,41 @@ QString LineInfo::trimmedCodeLine(const QString &t)
needSemicolon = true;
break;
- case Token::Identifier:
+ case Token::Identifier: {
+ // need to disambiguate
+ // "Rectangle\n{" in a QML context from
+ // "a = Somevar\n{" in a JS context
+ // What's done here does not cover all cases, but goes as far as possible
+ // with the limited information that's available.
+ const QStringRef text = tokenText(last);
+ if (yyLinizerState.leftBraceFollows && !text.isEmpty() && text.at(0).isUpper()) {
+ int i = index;
+
+ // skip any preceeding 'identifier.'; these could appear in both cases
+ while (i >= 2) {
+ const Token &prev = yyLinizerState.tokens.at(i-1);
+ const Token &prevPrev = yyLinizerState.tokens.at(i-2);
+ if (prev.kind == Token::Dot && prevPrev.kind == Token::Identifier) {
+ i -= 2;
+ } else {
+ break;
+ }
+ }
+
+ // it could also be 'a = \n Foo \n {', but that sounds unlikely
+ if (i == 0)
+ break;
+
+ // these indicate a QML context
+ const Token &prev = yyLinizerState.tokens.at(i-1);
+ if (prev.kind == Token::Semicolon || prev.kind == Token::Identifier
+ || prev.kind == Token::RightBrace || prev.kind == Token::RightBracket) {
+ break;
+ }
+ }
needSemicolon = true;
break;
+ }
case Token::Keyword:
if (tokenText(last) != QLatin1String("else"))
diff --git a/src/libs/qmljs/qmljslink.cpp b/src/libs/qmljs/qmljslink.cpp
index dd66d77e16..f4d7cdf6e5 100644
--- a/src/libs/qmljs/qmljslink.cpp
+++ b/src/libs/qmljs/qmljslink.cpp
@@ -260,10 +260,17 @@ ObjectValue *Link::importNonFile(Document::Ptr doc, const ImportInfo &importInfo
importFound = true;
if (!libraryInfo.plugins().isEmpty()) {
- if (libraryInfo.metaObjects().isEmpty()) {
+ if (libraryInfo.dumpStatus() == LibraryInfo::DumpNotStartedOrRunning) {
ModelManagerInterface *modelManager = ModelManagerInterface::instance();
if (modelManager)
modelManager->loadPluginTypes(libraryPath, importPath, packageName);
+ warning(doc, locationFromRange(importInfo.ast()->firstSourceLocation(),
+ importInfo.ast()->lastSourceLocation()),
+ tr("Library contains C++ plugins, type dump is in progress."));
+ } else if (libraryInfo.dumpStatus() == LibraryInfo::DumpError) {
+ error(doc, locationFromRange(importInfo.ast()->firstSourceLocation(),
+ importInfo.ast()->lastSourceLocation()),
+ libraryInfo.dumpError());
} else {
engine()->cppQmlTypes().load(engine(), libraryInfo.metaObjects());
}
@@ -325,3 +332,11 @@ void Link::error(const Document::Ptr &doc, const AST::SourceLocation &loc, const
if (doc->fileName() == d->doc->fileName())
d->diagnosticMessages.append(DiagnosticMessage(DiagnosticMessage::Error, loc, message));
}
+
+void Link::warning(const Document::Ptr &doc, const AST::SourceLocation &loc, const QString &message)
+{
+ Q_D(Link);
+
+ if (doc->fileName() == d->doc->fileName())
+ d->diagnosticMessages.append(DiagnosticMessage(DiagnosticMessage::Warning, loc, message));
+}
diff --git a/src/libs/qmljs/qmljslink.h b/src/libs/qmljs/qmljslink.h
index 98e21050d0..ef1c48fc16 100644
--- a/src/libs/qmljs/qmljslink.h
+++ b/src/libs/qmljs/qmljslink.h
@@ -77,6 +77,7 @@ private:
void importObject(Bind *bind, const QString &name, Interpreter::ObjectValue *object, NameId *targetNamespace);
void error(const Document::Ptr &doc, const AST::SourceLocation &loc, const QString &message);
+ void warning(const Document::Ptr &doc, const AST::SourceLocation &loc, const QString &message);
private:
QScopedPointer<LinkPrivate> d_ptr;
diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp
index 5b857bce6b..a9c286fd02 100644
--- a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp
+++ b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp
@@ -46,6 +46,8 @@ ModelManagerInterface::ModelManagerInterface(QObject *parent)
ModelManagerInterface::~ModelManagerInterface()
{
+ Q_ASSERT(g_instance == this);
+ g_instance = 0;
}
ModelManagerInterface *ModelManagerInterface::instance()
diff --git a/src/libs/qmljs/qmljsscanner.cpp b/src/libs/qmljs/qmljsscanner.cpp
index 75e0070cb0..2569f37ca4 100644
--- a/src/libs/qmljs/qmljsscanner.cpp
+++ b/src/libs/qmljs/qmljsscanner.cpp
@@ -156,6 +156,25 @@ QList<Token> Scanner::operator()(const QString &text, int startState)
if (_scanComments && start != -1)
tokens.append(Token(start, index - start, Token::Comment));
+ } else if (_state == MultiLineStringDQuote || _state == MultiLineStringSQuote) {
+ const QChar quote = (_state == MultiLineStringDQuote ? QLatin1Char('"') : QLatin1Char('\''));
+ const int start = index;
+ while (index < text.length()) {
+ const QChar ch = text.at(index);
+
+ if (ch == quote)
+ break;
+ else if (index + 1 < text.length() && ch == QLatin1Char('\\'))
+ index += 2;
+ else
+ ++index;
+ }
+ if (index < text.length()) {
+ ++index;
+ _state = Normal;
+ }
+ if (start < index)
+ tokens.append(Token(start, index - start, Token::String));
}
while (index < text.length()) {
@@ -216,7 +235,10 @@ QList<Token> Scanner::operator()(const QString &text, int startState)
++index;
// good one
} else {
- // unfinished
+ if (quote.unicode() == '"')
+ _state = MultiLineStringDQuote;
+ else
+ _state = MultiLineStringSQuote;
}
tokens.append(Token(start, index - start, Token::String));
diff --git a/src/libs/qmljs/qmljsscanner.h b/src/libs/qmljs/qmljsscanner.h
index 74e8991579..5974d5db40 100644
--- a/src/libs/qmljs/qmljsscanner.h
+++ b/src/libs/qmljs/qmljsscanner.h
@@ -83,7 +83,9 @@ class QMLJS_EXPORT Scanner
public:
enum {
Normal = 0,
- MultiLineComment = 1
+ MultiLineComment = 1,
+ MultiLineStringDQuote = 2,
+ MultiLineStringSQuote = 3
};
Scanner();
diff --git a/src/libs/qmljs/qmljsscopebuilder.cpp b/src/libs/qmljs/qmljsscopebuilder.cpp
index 82341445c3..80edbcca82 100644
--- a/src/libs/qmljs/qmljsscopebuilder.cpp
+++ b/src/libs/qmljs/qmljsscopebuilder.cpp
@@ -65,8 +65,8 @@ void ScopeBuilder::push(AST::Node *node)
if (qmlObject)
setQmlScopeObject(qmlObject);
- // JS scopes
- if (FunctionDeclaration *fun = cast<FunctionDeclaration *>(node)) {
+ // JS scopes (catch both, FunctionExpression and FunctionDeclaration)
+ if (FunctionExpression *fun = dynamic_cast<FunctionExpression *>(node)) {
ObjectValue *functionScope = _doc->bind()->findFunctionScope(fun);
if (functionScope)
_context->scopeChain().jsScopes += functionScope;
@@ -87,8 +87,10 @@ void ScopeBuilder::pop()
_nodes.removeLast();
// JS scopes
- if (cast<FunctionDeclaration *>(toRemove))
- _context->scopeChain().jsScopes.removeLast();
+ if (FunctionExpression *fun = dynamic_cast<FunctionExpression *>(toRemove)) {
+ if (_doc->bind()->findFunctionScope(fun))
+ _context->scopeChain().jsScopes.removeLast();
+ }
// QML scope object
if (! _nodes.isEmpty()
@@ -101,6 +103,11 @@ void ScopeBuilder::pop()
void ScopeBuilder::initializeScopeChain()
{
ScopeChain &scopeChain = _context->scopeChain();
+ if (scopeChain.qmlComponentScope
+ && scopeChain.qmlComponentScope->document == _doc) {
+ return;
+ }
+
scopeChain = ScopeChain(); // reset
Interpreter::Engine *engine = _context->engine();
@@ -206,8 +213,10 @@ void ScopeBuilder::setQmlScopeObject(Node *node)
// check if the object has a Qt.ListElement or Qt.Connections ancestor
// ### allow only signal bindings for Connections
- const ObjectValue *prototype = scopeObject->prototype(_context);
- while (prototype) {
+ PrototypeIterator iter(scopeObject, _context);
+ iter.next();
+ while (iter.hasNext()) {
+ const ObjectValue *prototype = iter.next();
if (const QmlObjectValue *qmlMetaObject = dynamic_cast<const QmlObjectValue *>(prototype)) {
if ((qmlMetaObject->className() == QLatin1String("ListElement")
|| qmlMetaObject->className() == QLatin1String("Connections")
@@ -217,11 +226,10 @@ void ScopeBuilder::setQmlScopeObject(Node *node)
break;
}
}
- prototype = prototype->prototype(_context);
}
// check if the object has a Qt.PropertyChanges ancestor
- prototype = scopeObject->prototype(_context);
+ const ObjectValue *prototype = scopeObject->prototype(_context);
prototype = isPropertyChangesObject(_context, prototype);
// find the target script binding
if (prototype) {
@@ -236,16 +244,13 @@ void ScopeBuilder::setQmlScopeObject(Node *node)
if (scriptBinding->qualifiedId && scriptBinding->qualifiedId->name
&& scriptBinding->qualifiedId->name->asString() == QLatin1String("target")
&& ! scriptBinding->qualifiedId->next) {
- // ### make Evaluate understand statements.
- if (ExpressionStatement *expStmt = cast<ExpressionStatement *>(scriptBinding->statement)) {
- Evaluate evaluator(_context);
- const Value *targetValue = evaluator(expStmt->expression);
-
- if (const ObjectValue *target = value_cast<const ObjectValue *>(targetValue)) {
- scopeChain.qmlScopeObjects.prepend(target);
- } else {
- scopeChain.qmlScopeObjects.clear();
- }
+ Evaluate evaluator(_context);
+ const Value *targetValue = evaluator(scriptBinding->statement);
+
+ if (const ObjectValue *target = value_cast<const ObjectValue *>(targetValue)) {
+ scopeChain.qmlScopeObjects.prepend(target);
+ } else {
+ scopeChain.qmlScopeObjects.clear();
}
}
}
@@ -285,15 +290,15 @@ const Value *ScopeBuilder::scopeObjectLookup(AST::UiQualifiedId *id)
const ObjectValue *ScopeBuilder::isPropertyChangesObject(const Context *context,
const ObjectValue *object)
{
- const ObjectValue *prototype = object;
- while (prototype) {
+ PrototypeIterator iter(object, context);
+ while (iter.hasNext()) {
+ const ObjectValue *prototype = iter.next();
if (const QmlObjectValue *qmlMetaObject = dynamic_cast<const QmlObjectValue *>(prototype)) {
if (qmlMetaObject->className() == QLatin1String("PropertyChanges")
&& (qmlMetaObject->packageName() == QLatin1String("Qt")
|| qmlMetaObject->packageName() == QLatin1String("QtQuick")))
return prototype;
}
- prototype = prototype->prototype(context);
}
return 0;
}
diff --git a/src/libs/qmljsdebugclient/qdeclarativedebug.cpp b/src/libs/qmljsdebugclient/qdeclarativedebug.cpp
index e3b653008e..e36cd0082e 100644
--- a/src/libs/qmljsdebugclient/qdeclarativedebug.cpp
+++ b/src/libs/qmljsdebugclient/qdeclarativedebug.cpp
@@ -49,6 +49,7 @@ class QDeclarativeEngineDebugClient : public QDeclarativeDebugClient
{
public:
QDeclarativeEngineDebugClient(QDeclarativeDebugConnection *client, QDeclarativeEngineDebugPrivate *p);
+ ~QDeclarativeEngineDebugClient();
protected:
virtual void statusChanged(Status status);
@@ -96,6 +97,10 @@ QDeclarativeEngineDebugClient::QDeclarativeEngineDebugClient(QDeclarativeDebugCo
{
}
+QDeclarativeEngineDebugClient::~QDeclarativeEngineDebugClient()
+{
+}
+
void QDeclarativeEngineDebugClient::statusChanged(Status status)
{
if (priv)
diff --git a/src/libs/qmljsdebugclient/qdeclarativedebugclient.cpp b/src/libs/qmljsdebugclient/qdeclarativedebugclient.cpp
index a78575a54c..4a54541c06 100644
--- a/src/libs/qmljsdebugclient/qdeclarativedebugclient.cpp
+++ b/src/libs/qmljsdebugclient/qdeclarativedebugclient.cpp
@@ -59,7 +59,7 @@ public:
QDeclarativeDebugClientPrivate();
QString name;
- QDeclarativeDebugConnection *client;
+ QDeclarativeDebugConnection *connection;
};
class QDeclarativeDebugConnectionPrivate : public QObject
@@ -199,7 +199,7 @@ QDeclarativeDebugConnection::~QDeclarativeDebugConnection()
{
QHash<QString, QDeclarativeDebugClient*>::iterator iter = d->plugins.begin();
for (; iter != d->plugins.end(); ++iter) {
- iter.value()->d_func()->client = 0;
+ iter.value()->d_func()->connection = 0;
iter.value()->statusChanged(QDeclarativeDebugClient::NotConnected);
}
}
@@ -210,50 +210,54 @@ bool QDeclarativeDebugConnection::isConnected() const
}
QDeclarativeDebugClientPrivate::QDeclarativeDebugClientPrivate()
-: client(0)
+: connection(0)
{
}
QDeclarativeDebugClient::QDeclarativeDebugClient(const QString &name,
QDeclarativeDebugConnection *parent)
-: QObject(parent), d(new QDeclarativeDebugClientPrivate())
+: QObject(parent), d_ptr(new QDeclarativeDebugClientPrivate())
{
+ Q_D(QDeclarativeDebugClient);
d->name = name;
- d->client = parent;
+ d->connection = parent;
- if (!d->client)
+ if (!d->connection)
return;
- if (d->client->d->plugins.contains(name)) {
+ if (d->connection->d->plugins.contains(name)) {
qWarning() << "QDeclarativeDebugClient: Conflicting plugin name" << name;
- d->client = 0;
+ d->connection = 0;
} else {
- d->client->d->plugins.insert(name, this);
- d->client->d->advertisePlugins();
+ d->connection->d->plugins.insert(name, this);
+ d->connection->d->advertisePlugins();
}
}
QDeclarativeDebugClient::~QDeclarativeDebugClient()
{
- if (d->client && d->client->d) {
- d->client->d->plugins.remove(d->name);
- d->client->d->advertisePlugins();
+ Q_D(QDeclarativeDebugClient);
+ if (d->connection && d->connection->d) {
+ d->connection->d->plugins.remove(d->name);
+ d->connection->d->advertisePlugins();
}
}
QString QDeclarativeDebugClient::name() const
{
+ Q_D(const QDeclarativeDebugClient);
return d->name;
}
QDeclarativeDebugClient::Status QDeclarativeDebugClient::status() const
{
- if (!d->client
- || !d->client->isConnected()
- || !d->client->d->gotHello)
+ Q_D(const QDeclarativeDebugClient);
+ if (!d->connection
+ || !d->connection->isConnected()
+ || !d->connection->d->gotHello)
return NotConnected;
- if (d->client->d->serverPlugins.contains(d->name))
+ if (d->connection->d->serverPlugins.contains(d->name))
return Enabled;
return Unavailable;
@@ -261,13 +265,14 @@ QDeclarativeDebugClient::Status QDeclarativeDebugClient::status() const
void QDeclarativeDebugClient::sendMessage(const QByteArray &message)
{
+ Q_D(QDeclarativeDebugClient);
if (status() != Enabled)
return;
QPacket pack;
pack << d->name << message;
- d->client->d->protocol->send(pack);
- d->client->flush();
+ d->connection->d->protocol->send(pack);
+ d->connection->flush();
}
void QDeclarativeDebugClient::statusChanged(Status)
diff --git a/src/libs/qmljsdebugclient/qdeclarativedebugclient_p.h b/src/libs/qmljsdebugclient/qdeclarativedebugclient_p.h
index f29e58a1b2..2ae8bc8e79 100644
--- a/src/libs/qmljsdebugclient/qdeclarativedebugclient_p.h
+++ b/src/libs/qmljsdebugclient/qdeclarativedebugclient_p.h
@@ -90,7 +90,7 @@ protected:
private:
friend class QDeclarativeDebugConnection;
friend class QDeclarativeDebugConnectionPrivate;
- QScopedPointer<QDeclarativeDebugClientPrivate> d;
+ QScopedPointer<QDeclarativeDebugClientPrivate> d_ptr;
};
}
diff --git a/src/libs/qmljsdebugclient/qpacketprotocol.cpp b/src/libs/qmljsdebugclient/qpacketprotocol.cpp
index 270a67c9ba..c35453e084 100644
--- a/src/libs/qmljsdebugclient/qpacketprotocol.cpp
+++ b/src/libs/qmljsdebugclient/qpacketprotocol.cpp
@@ -422,7 +422,7 @@ QPacket::~QPacket()
/*!
Creates a copy of \a other. The initial stream positions are shared, but the
- two packets are otherwise independant.
+ two packets are otherwise independent.
*/
QPacket::QPacket(const QPacket & other)
: QDataStream(), b(other.b), buf(0)
diff --git a/src/libs/qtconcurrent/qtconcurrent.pri b/src/libs/qtconcurrent/qtconcurrent.pri
index 57929a4cf1..141de8ee8e 100644
--- a/src/libs/qtconcurrent/qtconcurrent.pri
+++ b/src/libs/qtconcurrent/qtconcurrent.pri
@@ -1 +1 @@
-LIBS *= -l$$qtLibraryTarget(QtConcurrent)
+LIBS *= -l$$qtLibraryName(QtConcurrent)
diff --git a/src/libs/qtcreatorcdbext/base64.cpp b/src/libs/qtcreatorcdbext/base64.cpp
new file mode 100644
index 0000000000..f7f4d37aac
--- /dev/null
+++ b/src/libs/qtcreatorcdbext/base64.cpp
@@ -0,0 +1,106 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "base64.h"
+
+#include <sstream>
+
+template <class OStream>
+static void base64EncodeTriple(OStream &str, const unsigned char triple[3], size_t length = 3)
+{
+ static const char base64Encoding[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+ // Convert 3 bytes of triplet into 4 bytes, write out 64 bit-wise using a character mapping,
+ // see description of base64.
+ unsigned tripleValue = triple[0] * 256;
+ tripleValue += triple[1];
+ tripleValue *= 256;
+ tripleValue += triple[2];
+
+ char result[4]= {0, 0, 0, 0};
+ for (int i = 3; i >= 0 ; i--) {
+ result[i] = base64Encoding[tripleValue % 64];
+ tripleValue /= 64;
+ }
+
+ // Write out quad and pad if it is a padding triple.
+ const size_t writeLength = length + 1;
+ size_t i = 0;
+ for ( ; i < writeLength; i++)
+ str << result[i];
+ for ( ; i < 4; i++)
+ str << '=';
+}
+
+template <class OStream>
+void base64EncodeHelper(OStream &str, const unsigned char *source, size_t sourcelen)
+{
+ if (!sourcelen) {
+ str << "====";
+ return;
+ }
+ /* Encode triples */
+ const unsigned char *sourceEnd = source + sourcelen;
+ for (const unsigned char *triple = source; triple < sourceEnd; ) {
+ const unsigned char *nextTriple = triple + 3;
+ if (nextTriple <= sourceEnd) { // Encode full triple, including very last one
+ base64EncodeTriple(str, triple);
+ triple = nextTriple;
+ } else { // Past end and some padding required.
+ unsigned char paddingTriple[3] = {0, 0, 0};
+ std::copy(triple, sourceEnd, paddingTriple);
+ base64EncodeTriple(str, paddingTriple, sourceEnd - triple);
+ break;
+ }
+ }
+}
+
+void base64Encode(std::ostream &str, const unsigned char *source, size_t sourcelen)
+{
+ base64EncodeHelper(str, source, sourcelen);
+}
+
+std::string base64EncodeToString(const unsigned char *source, size_t sourcelen)
+{
+ std::ostringstream str;
+ base64Encode(str, source, sourcelen);
+ return str.str();
+}
+
+void base64EncodeW(std::wostream &str, const unsigned char *source, size_t sourcelen)
+{
+ base64EncodeHelper(str, source, sourcelen);
+}
+
+std::wstring base64EncodeToWString(const unsigned char *source, size_t sourcelen)
+{
+ std::wostringstream str;
+ base64EncodeW(str, source, sourcelen);
+ return str.str();
+}
diff --git a/src/libs/qtcreatorcdbext/base64.h b/src/libs/qtcreatorcdbext/base64.h
new file mode 100644
index 0000000000..8954cc06d5
--- /dev/null
+++ b/src/libs/qtcreatorcdbext/base64.h
@@ -0,0 +1,42 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 BASE64_H
+#define BASE64_H
+
+#include <iosfwd>
+#include <string>
+
+// Base 64 encoding helpers
+void base64Encode(std::ostream &str, const unsigned char *source, size_t sourcelen);
+std::string base64EncodeToString(const unsigned char *source, size_t sourcelen);
+void base64EncodeW(std::wostream &str, const unsigned char *source, size_t sourcelen);
+std::wstring base64EncodeToWString(const unsigned char *source, size_t sourcelen);
+
+#endif // BASE64_H
diff --git a/src/libs/qtcreatorcdbext/cdb_detect.pri b/src/libs/qtcreatorcdbext/cdb_detect.pri
new file mode 100644
index 0000000000..ac25ae2a47
--- /dev/null
+++ b/src/libs/qtcreatorcdbext/cdb_detect.pri
@@ -0,0 +1,16 @@
+# Detect presence of "Debugging Tools For Windows"
+# in case MS VS compilers are used.
+
+CDB_PATH=""
+win32 {
+ contains(QMAKE_CXX, cl) {
+ CDB_PATH="$$(CDB_PATH)"
+ isEmpty(CDB_PATH):CDB_PATH="$$(ProgramFiles)/Debugging Tools For Windows/sdk"
+ !exists($$CDB_PATH):CDB_PATH="$$(ProgramFiles)/Debugging Tools For Windows (x86)/sdk"
+ !exists($$CDB_PATH):CDB_PATH="$$(ProgramFiles)/Debugging Tools For Windows (x64)/sdk"
+ !exists($$CDB_PATH):CDB_PATH="$$(ProgramFiles)/Debugging Tools For Windows 64-bit/sdk"
+ !exists($$CDB_PATH):CDB_PATH="$$(ProgramW6432)/Debugging Tools For Windows (x86)/sdk"
+ !exists($$CDB_PATH):CDB_PATH="$$(ProgramW6432)/Debugging Tools For Windows (x64)/sdk"
+ !exists($$CDB_PATH):CDB_PATH="$$(ProgramW6432)/Debugging Tools For Windows 64-bit/sdk"
+ }
+}
diff --git a/src/libs/qtcreatorcdbext/common.cpp b/src/libs/qtcreatorcdbext/common.cpp
new file mode 100644
index 0000000000..309a202b2d
--- /dev/null
+++ b/src/libs/qtcreatorcdbext/common.cpp
@@ -0,0 +1,120 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "common.h"
+#include "iinterfacepointer.h"
+#include <sstream>
+
+std::string winErrorMessage(unsigned long error)
+{
+ char *lpMsgBuf;
+ const int len = FormatMessageA(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, error, 0, (LPSTR)&lpMsgBuf, 0, NULL);
+ if (len) {
+ const std::string rc(lpMsgBuf, len);
+ LocalFree(lpMsgBuf);
+ return rc;
+ }
+ std::ostringstream str;
+ str << "Unknown error " << error;
+ return str.str();
+}
+
+std::string winErrorMessage()
+{
+ return winErrorMessage(GetLastError());
+}
+
+std::string msgDebugEngineComResult(HRESULT hr)
+{
+ switch (hr) {
+ case S_OK:
+ return std::string("S_OK");
+ case S_FALSE:
+ return std::string("S_FALSE");
+ case E_FAIL:
+ break;
+ case E_INVALIDARG:
+ return std::string("E_INVALIDARG");
+ case E_NOINTERFACE:
+ return std::string("E_NOINTERFACE");
+ case E_OUTOFMEMORY:
+ return std::string("E_OUTOFMEMORY");
+ case E_UNEXPECTED:
+ return std::string("E_UNEXPECTED");
+ case E_NOTIMPL:
+ return std::string("E_NOTIMPL");
+ }
+ if (hr == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED))
+ return std::string("ERROR_ACCESS_DENIED");;
+ if (hr == HRESULT_FROM_NT(STATUS_CONTROL_C_EXIT))
+ return std::string("STATUS_CONTROL_C_EXIT");
+ return std::string("E_FAIL ") + winErrorMessage(HRESULT_CODE(hr));
+}
+
+std::string msgDebugEngineComFailed(const char *func, HRESULT hr)
+{
+ std::string rc = func;
+ rc += " failed: ";
+ rc += msgDebugEngineComResult(hr);
+ return rc;
+}
+
+ULONG currentThreadId(IDebugSystemObjects *sysObjects)
+{
+ ULONG id = 0;
+ if (sysObjects->GetCurrentThreadId(&id) == S_OK)
+ return id;
+ return 0;
+}
+
+ULONG currentThreadId(CIDebugClient *client)
+{
+ IInterfacePointer<IDebugSystemObjects> sysObjects(client);
+ if (sysObjects)
+ return currentThreadId(sysObjects.data());
+ return 0;
+}
+
+ULONG currentProcessId(IDebugSystemObjects *sysObjects)
+{
+ ULONG64 handle = 0;
+ if (sysObjects->GetCurrentProcessHandle(&handle) == S_OK)
+ return GetProcessId((HANDLE)handle);
+ return 0;
+}
+
+ULONG currentProcessId(CIDebugClient *client)
+{
+ IInterfacePointer<IDebugSystemObjects> sysObjects(client);
+ if (sysObjects)
+ return currentProcessId(sysObjects.data());
+ return 0;
+}
diff --git a/src/libs/qtcreatorcdbext/common.h b/src/libs/qtcreatorcdbext/common.h
new file mode 100644
index 0000000000..6ee1f03f47
--- /dev/null
+++ b/src/libs/qtcreatorcdbext/common.h
@@ -0,0 +1,84 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 COMMON_H
+#define COMMON_H
+
+// Define KDEXT_64BIT to make all wdbgexts APIs recognize 64 bit addresses
+// It is recommended for extensions to use 64 bit headers from wdbgexts so
+// the extensions could support 64 bit targets.
+
+#include <string>
+#include <sstream>
+
+#include <windows.h>
+#define KDEXT_64BIT
+#include <wdbgexts.h>
+#include <dbgeng.h>
+
+static const char creatorOutputPrefixC[] = "QtCreatorExt: ";
+
+typedef IDebugControl CIDebugControl;
+typedef IDebugSymbols3 CIDebugSymbols;
+typedef IDebugSymbolGroup2 CIDebugSymbolGroup;
+typedef IDebugClient5 CIDebugClient;
+typedef IDebugSystemObjects CIDebugSystemObjects;
+typedef IDebugDataSpaces4 CIDebugDataSpaces;
+typedef IDebugAdvanced2 CIDebugAdvanced;
+typedef IDebugRegisters2 CIDebugRegisters;
+
+// Utility messages
+std::string winErrorMessage(unsigned long error);
+std::string winErrorMessage();
+std::string msgDebugEngineComResult(HRESULT hr);
+std::string msgDebugEngineComFailed(const char *func, HRESULT hr);
+
+// Debug helper for anything streamable as in 'DebugPrint() << object'
+// Derives from std::ostringstream and print out everything accumulated in destructor.
+struct DebugPrint : public std::ostringstream {
+ DebugPrint() {}
+ ~DebugPrint() {
+ dprintf("DEBUG: %s\n", str().c_str());
+ }
+};
+
+ULONG currentThreadId(IDebugSystemObjects *sysObjects);
+ULONG currentThreadId(CIDebugClient *client);
+ULONG currentProcessId(IDebugSystemObjects *sysObjects);
+ULONG currentProcessId(CIDebugClient *client);
+
+#ifdef QTC_TRACE
+# define QTC_TRACE_IN dprintf(">%s\n", __FUNCTION__);
+# define QTC_TRACE_OUT dprintf("<%s\n", __FUNCTION__);
+#else
+# define QTC_TRACE_IN
+# define QTC_TRACE_OUT
+#endif
+
+#endif // COMMON_H
diff --git a/src/libs/qtcreatorcdbext/containers.cpp b/src/libs/qtcreatorcdbext/containers.cpp
new file mode 100644
index 0000000000..f52ee7e53d
--- /dev/null
+++ b/src/libs/qtcreatorcdbext/containers.cpp
@@ -0,0 +1,694 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "containers.h"
+#include "symbolgroupvalue.h"
+#include "symbolgroup.h"
+#include "stringutils.h"
+
+#include <functional>
+#include <iterator>
+
+typedef AbstractSymbolGroupNode::AbstractSymbolGroupNodePtrVector AbstractSymbolGroupNodePtrVector;
+typedef std::vector<SymbolGroupValue> SymbolGroupValueVector;
+typedef std::vector<int>::size_type VectorIndexType;
+
+// Read a pointer array from debuggee memory (ULONG64/32 according pointer size)
+static void *readPointerArray(ULONG64 address, unsigned count, const SymbolGroupValueContext &ctx)
+{
+ const unsigned pointerSize = SymbolGroupValue::pointerSize();
+ const ULONG allocSize = pointerSize * count;
+ ULONG bytesRead = 0;
+ void *data = new unsigned char[allocSize];
+ const HRESULT hr = ctx.dataspaces->ReadVirtual(address, data, allocSize, &bytesRead);
+ if (FAILED(hr) || bytesRead != allocSize) {
+ delete [] data;
+ return 0;
+ }
+ return data;
+}
+
+template <class UInt>
+inline void dumpHexArray(std::ostream &os, const UInt *a, int count)
+{
+ os << std::showbase << std::hex;
+ std::copy(a, a + count, std::ostream_iterator<UInt>(os, ", "));
+ os << std::noshowbase << std::dec;
+}
+
+static inline void dump32bitPointerArray(std::ostream &os, const void *a, int count)
+{
+ dumpHexArray(os, reinterpret_cast<const ULONG32 *>(a), count);
+}
+
+static inline void dump64bitPointerArray(std::ostream &os, const void *a, int count)
+{
+ dumpHexArray(os, reinterpret_cast<const ULONG64 *>(a), count);
+}
+
+// Return size from an STL vector (last/first iterators).
+static inline int msvcStdVectorSize(const SymbolGroupValue &v)
+{
+ if (const SymbolGroupValue myFirstPtrV = v["_Myfirst"]) {
+ if (const SymbolGroupValue myLastPtrV = v["_Mylast"]) {
+ const ULONG64 firstPtr = myFirstPtrV.pointerValue();
+ const ULONG64 lastPtr = myLastPtrV.pointerValue();
+ if (!firstPtr || lastPtr < firstPtr)
+ return -1;
+ if (lastPtr == firstPtr)
+ return 0;
+ // Subtract the pointers: We need to do the pointer arithmetics ourselves
+ // as we get char *pointers.
+ const std::string innerType = SymbolGroupValue::stripPointerType(myFirstPtrV.type());
+ const size_t size = SymbolGroupValue::sizeOf(innerType.c_str());
+ if (size == 0)
+ return -1;
+ return static_cast<int>((lastPtr - firstPtr) / size);
+ }
+ }
+ return -1;
+}
+
+// Return size of container or -1
+int containerSize(KnownType kt, SymbolGroupNode *n, const SymbolGroupValueContext &ctx)
+{
+ QTC_TRACE_IN
+ if ((kt & KT_ContainerType) == 0)
+ return -1;
+ const int ct = containerSize(kt, SymbolGroupValue(n, ctx));
+ QTC_TRACE_OUT
+ return ct;
+}
+
+// Determine size of containers
+int containerSize(KnownType kt, const SymbolGroupValue &v)
+{
+ switch (kt) {
+ case KT_QStringList:
+ if (const SymbolGroupValue base = v[unsigned(0)])
+ return containerSize(KT_QList, base);
+ break;
+ case KT_QList:
+ if (const SymbolGroupValue dV = v["d"]) {
+ if (const SymbolGroupValue beginV = dV["begin"]) {
+ const int begin = beginV.intValue();
+ const int end = dV["end"].intValue();
+ if (begin >= 0 && end >= begin)
+ return end - begin;
+ }
+ }
+ break;
+ case KT_QLinkedList:
+ case KT_QHash:
+ case KT_QMap:
+ case KT_QVector:
+ if (const SymbolGroupValue sizeV = v["d"]["size"])
+ return sizeV.intValue();
+ break;
+ case KT_QMultiHash:
+ if (const SymbolGroupValue qHash = v[unsigned(0)])
+ return containerSize(KT_QHash, qHash);
+ break;
+ case KT_QQueue:
+ if (const SymbolGroupValue qList= v[unsigned(0)])
+ return containerSize(KT_QList, qList);
+ break;
+ case KT_QStack:
+ if (const SymbolGroupValue qVector = v[unsigned(0)])
+ return containerSize(KT_QVector, qVector);
+ break;
+ case KT_QSet:
+ if (const SymbolGroupValue base = v[unsigned(0)])
+ return containerSize(KT_QHash, base);
+ break;
+ case KT_QMultiMap:
+ if (const SymbolGroupValue base = v[unsigned(0)])
+ return containerSize(KT_QMap, base);
+ break;
+ case KT_StdVector: {
+ if (const SymbolGroupValue base = v[unsigned(0)]) {
+ const int msvc10Size = msvcStdVectorSize(base);
+ if (msvc10Size >= 0)
+ return msvc10Size;
+ }
+ const int msvc8Size = msvcStdVectorSize(v);
+ if (msvc8Size >= 0)
+ return msvc8Size;
+ }
+ break;
+ case KT_StdList:
+ if (const SymbolGroupValue sizeV = v["_Mysize"]) // VS 8
+ return sizeV.intValue();
+ if (const SymbolGroupValue sizeV = v[unsigned(0)][unsigned(0)]["_Mysize"]) // VS10
+ return sizeV.intValue();
+ break;
+ case KT_StdDeque: {
+ const SymbolGroupValue msvc10sizeV = v[unsigned(0)]["_Mysize"]; // VS10
+ if (msvc10sizeV)
+ return msvc10sizeV.intValue();
+ const SymbolGroupValue msvc8sizeV = v["_Mysize"]; // VS8
+ if (msvc8sizeV)
+ return msvc8sizeV.intValue();
+ }
+ break;
+ case KT_StdStack:
+ if (const SymbolGroupValue deque = v[unsigned(0)])
+ return containerSize(KT_StdDeque, deque);
+ break;
+ case KT_StdSet:
+ case KT_StdMap:
+ case KT_StdMultiMap:
+ if (const SymbolGroupValue baseV = v[unsigned(0)]) {
+ if (const SymbolGroupValue sizeV = baseV["_Mysize"]) // VS 8
+ return sizeV.intValue();
+ if (const SymbolGroupValue sizeV = baseV[unsigned(0)][unsigned(0)]["_Mysize"]) // VS 10
+ return sizeV.intValue();
+ }
+ break;
+ }
+ return -1;
+}
+
+/* Generate a list of children by invoking the functions to obtain the value
+ * and the next link */
+template <class ValueFunction, class NextFunction>
+AbstractSymbolGroupNodePtrVector linkedListChildList(SymbolGroupValue headNode,
+ int count,
+ ValueFunction valueFunc,
+ NextFunction nextFunc)
+{
+ AbstractSymbolGroupNodePtrVector rc;
+ rc.reserve(count);
+ for (int i =0; i < count && headNode; i++) {
+ if (const SymbolGroupValue value = valueFunc(headNode)) {
+ rc.push_back(ReferenceSymbolGroupNode::createArrayNode(i, value.node()));
+ headNode = nextFunc(headNode);
+ } else {
+ break;
+ }
+ }
+ return rc;
+}
+
+// Helper function for linkedListChildList that returns a member by name
+class MemberByName : public std::unary_function<const SymbolGroupValue &, SymbolGroupValue>
+{
+public:
+ explicit MemberByName(const char *name) : m_name(name) {}
+ SymbolGroupValue operator()(const SymbolGroupValue &v) { return v[m_name]; }
+
+private:
+ const char *m_name;
+};
+
+// std::list<T>: Dummy head node and then a linked list of "_Next", "_Myval".
+static inline AbstractSymbolGroupNodePtrVector stdListChildList(SymbolGroupNode *n, int count,
+ const SymbolGroupValueContext &ctx)
+{
+ if (count)
+ if (const SymbolGroupValue head = SymbolGroupValue(n, ctx)[unsigned(0)][unsigned(0)]["_Myhead"]["_Next"])
+ return linkedListChildList(head, count, MemberByName("_Myval"), MemberByName("_Next"));
+ return AbstractSymbolGroupNodePtrVector();
+}
+
+// QLinkedList<T>: Dummy head node and then a linked list of "n", "t".
+static inline AbstractSymbolGroupNodePtrVector qLinkedListChildList(SymbolGroupNode *n, int count,
+ const SymbolGroupValueContext &ctx)
+{
+ if (count)
+ if (const SymbolGroupValue head = SymbolGroupValue(n, ctx)["e"]["n"])
+ return linkedListChildList(head, count, MemberByName("t"), MemberByName("n"));
+ return AbstractSymbolGroupNodePtrVector();
+}
+
+// Symbol Name/(Expression) of a pointed-to instance ('Foo' at 0x10') ==> '*(Foo *)0x10'
+static inline std::string pointedToSymbolName(ULONG64 address, const std::string &type)
+{
+ std::ostringstream str;
+ str << "*(" << type;
+ if (!endsWith(type, '*'))
+ str << ' ';
+ str << "*)" << std::showbase << std::hex << address;
+ return str.str();
+}
+
+/* Helper for array-type containers:
+ * Add a series of "*(innertype *)0x (address + n * size)" fake child symbols.
+ * for a function generating a sequence of addresses. */
+
+template <class AddressFunc>
+AbstractSymbolGroupNodePtrVector arrayChildList(SymbolGroup *sg, AddressFunc addressFunc,
+ const std::string &innerType, int count)
+{
+ AbstractSymbolGroupNodePtrVector rc;
+ if (!count)
+ return rc;
+ std::string errorMessage;
+ rc.reserve(count);
+ for (int i = 0; i < count; i++) {
+ const std::string name = pointedToSymbolName(addressFunc(), innerType);
+ if (SymbolGroupNode *child = sg->addSymbol(name, std::string(), &errorMessage)) {
+ rc.push_back(ReferenceSymbolGroupNode::createArrayNode(i, child));
+ } else {
+ break;
+ }
+ }
+ return rc;
+}
+
+// Helper function for arrayChildList() taking a reference to an address and simply generating
+// a sequence of address, address + delta, address + 2 * delta...
+class AddressSequence
+{
+public:
+ explicit inline AddressSequence(ULONG64 &address, ULONG delta) : m_address(address), m_delta(delta) {}
+ inline ULONG64 operator()()
+ {
+ const ULONG64 rc = m_address;
+ m_address += m_delta;
+ return rc;
+ }
+
+private:
+ ULONG64 &m_address;
+ const ULONG m_delta;
+};
+
+static inline AbstractSymbolGroupNodePtrVector arrayChildList(SymbolGroup *sg, ULONG64 address,
+ const std::string &innerType, int count)
+{
+ if (const unsigned innerTypeSize = SymbolGroupValue::sizeOf(innerType.c_str()))
+ return arrayChildList(sg, AddressSequence(address, innerTypeSize),
+ innerType, count);
+ return AbstractSymbolGroupNodePtrVector();
+}
+
+// std::vector<T>
+static inline AbstractSymbolGroupNodePtrVector
+ stdVectorChildList(SymbolGroupNode *n, int count, const SymbolGroupValueContext &ctx)
+{
+ if (count) {
+ // std::vector<T>: _Myfirst is a pointer of T*. Get address
+ // element to obtain address.
+ const SymbolGroupValue vec(n, ctx);
+ SymbolGroupValue myFirst = vec[unsigned(0)]["_Myfirst"]; // MSVC2010
+ if (!myFirst)
+ myFirst = vec["_Myfirst"]; // MSVC2008
+ if (myFirst)
+ if (const ULONG64 address = myFirst.pointerValue())
+ return arrayChildList(n->symbolGroup(), address,
+ SymbolGroupValue::stripPointerType(myFirst.type()), count);
+ }
+ return AbstractSymbolGroupNodePtrVector();
+}
+
+// Helper for std::deque<>: From the array of deque blocks, read out the values.
+template<class AddressType>
+AbstractSymbolGroupNodePtrVector
+ stdDequeChildrenHelper(SymbolGroup *sg,
+ const AddressType *blockArray, ULONG64 blockArraySize,
+ const std::string &innerType, ULONG64 innerTypeSize,
+ ULONG64 startOffset, ULONG64 dequeSize, int count)
+{
+ AbstractSymbolGroupNodePtrVector rc;
+ rc.reserve(count);
+ std::string errorMessage;
+ // Determine block number and offset in the block array T[][dequeSize]
+ // and create symbol by address.
+ for (int i = 0; i < count; i++) {
+ // see <deque>-header: std::deque<T>::iterator::operator*
+ const ULONG64 offset = startOffset + i;
+ ULONG64 block = offset / dequeSize;
+ if (block >= blockArraySize)
+ block -= blockArraySize;
+ const ULONG64 blockOffset = offset % dequeSize;
+ const ULONG64 address = blockArray[block] + innerTypeSize * blockOffset;
+ if (SymbolGroupNode *n = sg->addSymbol(pointedToSymbolName(address, innerType), std::string(), &errorMessage)) {
+ rc.push_back(ReferenceSymbolGroupNode::createArrayNode(i, n));
+ } else {
+ return AbstractSymbolGroupNodePtrVector();
+ }
+ }
+ return rc;
+}
+
+// std::deque<>
+static inline AbstractSymbolGroupNodePtrVector
+ stdDequeDirectChildList(const SymbolGroupValue &deque, int count)
+{
+ if (!count)
+ return AbstractSymbolGroupNodePtrVector();
+ // From MSVC10 on, there is an additional base class
+ const ULONG64 arrayAddress = deque["_Map"].pointerValue();
+ const int startOffset = deque["_Myoff"].intValue();
+ const int mapSize = deque["_Mapsize"].intValue();
+ if (!arrayAddress || startOffset < 0 || mapSize <= 0)
+ return AbstractSymbolGroupNodePtrVector();
+ const std::vector<std::string> innerTypes = deque.innerTypes();
+ if (innerTypes.empty())
+ return AbstractSymbolGroupNodePtrVector();
+ // Get the deque size (block size) which is an unavailable static member
+ // (cf <deque> for the actual expression).
+ const unsigned innerTypeSize = SymbolGroupValue::sizeOf(innerTypes.front().c_str());
+ if (!innerTypeSize)
+ return AbstractSymbolGroupNodePtrVector();
+ const int dequeSize = innerTypeSize <= 1 ? 16 : innerTypeSize <= 2 ?
+ 8 : innerTypeSize <= 4 ? 4 : innerTypeSize <= 8 ? 2 : 1;
+ // Read out map array (pointing to the blocks)
+ void *mapArray = readPointerArray(arrayAddress, mapSize, deque.context());
+ if (!mapArray)
+ return AbstractSymbolGroupNodePtrVector();
+ const AbstractSymbolGroupNodePtrVector rc = SymbolGroupValue::pointerSize() == 8 ?
+ stdDequeChildrenHelper(deque.node()->symbolGroup(),
+ reinterpret_cast<const ULONG64 *>(mapArray), mapSize,
+ innerTypes.front(), innerTypeSize, startOffset, dequeSize, count) :
+ stdDequeChildrenHelper(deque.node()->symbolGroup(),
+ reinterpret_cast<const ULONG32 *>(mapArray), mapSize,
+ innerTypes.front(), innerTypeSize, startOffset, dequeSize, count);
+ delete [] mapArray;
+ return rc;
+}
+
+// std::deque<>
+static inline AbstractSymbolGroupNodePtrVector
+ stdDequeChildList(const SymbolGroupValue &v, int count)
+{
+ // MSVC10 has a base class. If that fails, try direct (MSVC2008)
+ const AbstractSymbolGroupNodePtrVector msvc10rc = stdDequeDirectChildList(v[unsigned(0)], count);
+ return msvc10rc.empty() ? stdDequeDirectChildList(v, count) : msvc10rc;
+}
+
+// QVector<T>
+static inline AbstractSymbolGroupNodePtrVector
+ qVectorChildList(SymbolGroupNode *n, int count, const SymbolGroupValueContext &ctx)
+{
+ if (count) {
+ // QVector<T>: p/array is declared as array of T. Dereference first
+ // element to obtain address.
+ const SymbolGroupValue vec(n, ctx);
+ if (const SymbolGroupValue firstElementV = vec["p"]["array"][unsigned(0)])
+ if (const ULONG64 arrayAddress = firstElementV.address())
+ return arrayChildList(n->symbolGroup(), arrayAddress, firstElementV.type(), count);
+ }
+ return AbstractSymbolGroupNodePtrVector();
+}
+
+// Helper function for arrayChildList() for use with QLists of large types that are an
+// array of pointers to allocated elements: Generate a pointer sequence by reading out the array.
+template <class AddressType>
+class AddressArraySequence
+{
+public:
+ explicit inline AddressArraySequence(const AddressType *array) : m_array(array) {}
+ inline ULONG64 operator()() { return *m_array++; }
+
+private:
+ const AddressType *m_array;
+};
+
+// QList<>.
+static inline AbstractSymbolGroupNodePtrVector
+ qListChildList(const SymbolGroupValue &v, int count)
+{
+ // QList<T>: d/array is declared as array of void *[]. Dereference first
+ // element to obtain address.
+ if (!count)
+ return AbstractSymbolGroupNodePtrVector();
+ const SymbolGroupValue dV = v["d"];
+ if (!dV)
+ return AbstractSymbolGroupNodePtrVector();
+ const int begin = dV["begin"].intValue();
+ if (begin < 0)
+ return AbstractSymbolGroupNodePtrVector();
+ const SymbolGroupValue firstElementV = dV["array"][unsigned(0)];
+ if (!firstElementV)
+ return AbstractSymbolGroupNodePtrVector();
+ ULONG64 arrayAddress = firstElementV.address();
+ if (!arrayAddress)
+ return AbstractSymbolGroupNodePtrVector();
+ const std::vector<std::string> innerTypes = v.innerTypes();
+ if (innerTypes.size() != 1)
+ return AbstractSymbolGroupNodePtrVector();
+ const std::string &innerType = innerTypes.front();
+ const unsigned innerTypeSize = SymbolGroupValue::sizeOf(innerType.c_str());
+ if (!innerTypeSize)
+ return AbstractSymbolGroupNodePtrVector();
+ /* QList<> is:
+ * 1) An array of 'void *[]' where T values are coerced into the elements for
+ * POD/pointer types and small, movable or primitive Qt types. That is, smaller
+ * elements are also aligned at 'void *' boundaries.
+ * 2) An array of 'T *[]' (pointer to allocated instances) for anything else
+ * (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic)
+ * isStatic depends on QTypeInfo specializations and hardcoded flags for types. */
+ const unsigned pointerSize = SymbolGroupValue::pointerSize();
+ arrayAddress += begin * pointerSize;
+ if (SymbolGroupValue::isPointerType(innerType)) // Quick check: Any pointer is T[]
+ return arrayChildList(v.node()->symbolGroup(),
+ AddressSequence(arrayAddress, pointerSize),
+ innerType, count);
+ // Check condition for large||static.
+ bool isLargeOrStatic = innerTypeSize > pointerSize;
+ if (!isLargeOrStatic) {
+ const KnownType kt = knownType(innerType, false); // inner type, no 'class ' prefix.
+ if (kt != KT_Unknown && !(knownType(innerType, false) & (KT_Qt_PrimitiveType|KT_Qt_MovableType)))
+ isLargeOrStatic = true;
+ }
+ if (isLargeOrStatic) {
+ // Retrieve the pointer array ourselves to avoid having to evaluate '*(class foo**)'
+ if (void *data = readPointerArray(arrayAddress, count, v.context())) {
+ // Generate sequence of addresses from pointer array
+ const AbstractSymbolGroupNodePtrVector rc = pointerSize == 8 ?
+ arrayChildList(v.node()->symbolGroup(), AddressArraySequence<ULONG64>(reinterpret_cast<const ULONG64 *>(data)), innerType, count) :
+ arrayChildList(v.node()->symbolGroup(), AddressArraySequence<ULONG32>(reinterpret_cast<const ULONG32 *>(data)), innerType, count);
+ delete [] data;
+ return rc;
+ }
+ return AbstractSymbolGroupNodePtrVector();
+ }
+ return arrayChildList(v.node()->symbolGroup(),
+ AddressSequence(arrayAddress, pointerSize),
+ innerType, count);
+}
+
+// Return the list of buckets of a 'QHash<>' as 'QHashData::Node *' values from
+// the list of addresses passed in
+template<class AddressType>
+SymbolGroupValueVector hashBuckets(SymbolGroup *sg, const std::string hashNodeType,
+ const AddressType *pointerArray,
+ int numBuckets,
+ AddressType ePtr,
+ const SymbolGroupValueContext &ctx)
+{
+ SymbolGroupValueVector rc;
+ rc.reserve(numBuckets);
+ const AddressType *end = pointerArray + numBuckets;
+ std::string errorMessage;
+ // Skip 'e' special values as they are used as placeholder for reserve(d)
+ // empty array elements.
+ for (const AddressType *p = pointerArray; p < end; p++) {
+ if (*p != ePtr) {
+ const std::string name = pointedToSymbolName(*p, hashNodeType);
+ if (SymbolGroupNode *child = sg->addSymbol(name, std::string(), &errorMessage)) {
+ rc.push_back(SymbolGroupValue(child, ctx));
+ } else {
+ return std::vector<SymbolGroupValue>();
+ break;
+ }
+ }
+ }
+ return rc;
+}
+
+// Return real node type of a QHash: "class QHash<K,V>" -> [struct] "QHashNode<K,V>";
+static inline std::string qHashNodeType(std::string qHashType)
+{
+ qHashType.erase(0, 6); // Strip "class ";
+ const std::string::size_type pos = qHashType.find('<');
+ if (pos != std::string::npos)
+ qHashType.insert(pos, "Node");
+ return qHashType;
+}
+
+// Return up to count nodes of type "QHashNode<K,V>" of a "class QHash<K,V>".
+SymbolGroupValueVector qHashNodes(const SymbolGroupValue &v,
+ VectorIndexType count)
+{
+ if (!count)
+ return SymbolGroupValueVector();
+ const SymbolGroupValue hashData = v["d"];
+ // 'e' is used as a special value to indicate empty hash buckets in the array.
+ const ULONG64 ePtr = v["e"].pointerValue();
+ if (!hashData || !ePtr)
+ return SymbolGroupValueVector();
+ // Retrieve the array of buckets of 'd'
+ const int numBuckets = hashData["numBuckets"].intValue();
+ const ULONG64 bucketArray = hashData["buckets"].pointerValue();
+ if (numBuckets <= 0 || !bucketArray)
+ return SymbolGroupValueVector();
+ void *bucketPointers = readPointerArray(bucketArray, numBuckets, v.context());
+ if (!bucketPointers)
+ return SymbolGroupValueVector();
+ // Get list of buckets (starting elements of 'QHashData::Node')
+ const std::string dummyNodeType = "QHashData::Node";
+ const SymbolGroupValueVector buckets = SymbolGroupValue::pointerSize() == 8 ?
+ hashBuckets(v.node()->symbolGroup(), dummyNodeType,
+ reinterpret_cast<const ULONG64 *>(bucketPointers), numBuckets,
+ ePtr, v.context()) :
+ hashBuckets(v.node()->symbolGroup(), dummyNodeType,
+ reinterpret_cast<const ULONG32 *>(bucketPointers), numBuckets,
+ ULONG32(ePtr), v.context());
+ delete [] bucketPointers ;
+ // Generate the list 'QHashData::Node *' by iterating over the linked list of
+ // nodes starting at each bucket. Using the 'QHashData::Node *' instead of
+ // the 'QHashNode<K,T>' is much faster. Each list has a trailing, unused
+ // dummy element.
+ SymbolGroupValueVector dummyNodeList;
+ dummyNodeList.reserve(count);
+ bool notEnough = true;
+ const SymbolGroupValueVector::const_iterator ncend = buckets.end();
+ for (SymbolGroupValueVector::const_iterator it = buckets.begin(); notEnough && it != ncend; ++it) {
+ for (SymbolGroupValue l = *it; notEnough && l ; ) {
+ const SymbolGroupValue next = l["next"];
+ if (next && next.pointerValue()) { // Stop at trailing dummy element
+ dummyNodeList.push_back(l);
+ if (dummyNodeList.size() >= count) // Stop at maximum count
+ notEnough = false;
+ } else {
+ break;
+ }
+ }
+ }
+ // Finally convert them into real nodes 'QHashNode<K,V> (potentially expensive)
+ const std::string nodeType = qHashNodeType(v.type());
+ SymbolGroupValueVector nodeList;
+ nodeList.reserve(count);
+ const SymbolGroupValueVector::const_iterator dcend = dummyNodeList.end();
+ for (SymbolGroupValueVector::const_iterator it = dummyNodeList.begin(); it != dcend; ++it) {
+ if (const SymbolGroupValue n = (*it).typeCast(nodeType.c_str())) {
+ nodeList.push_back(n);
+ } else {
+ return SymbolGroupValueVector();
+ }
+ }
+ return nodeList;
+}
+
+// QSet<>: Contains a 'QHash<key, QHashDummyValue>' as member 'q_hash'.
+// Just dump the keys as an array.
+static inline AbstractSymbolGroupNodePtrVector
+ qSetChildList(const SymbolGroupValue &v, VectorIndexType count)
+{
+ const SymbolGroupValue qHash = v["q_hash"];
+ AbstractSymbolGroupNodePtrVector rc;
+ if (!count || !qHash)
+ return rc;
+ const SymbolGroupValueVector nodes = qHashNodes(qHash, count);
+ if (nodes.size() != VectorIndexType(count))
+ return rc;
+ rc.reserve(count);
+ for (int i = 0; i < count; i++) {
+ if (const SymbolGroupValue key = nodes.at(i)["key"]) {
+ rc.push_back(ReferenceSymbolGroupNode::createArrayNode(i, key.node()));
+ } else {
+ return AbstractSymbolGroupNodePtrVector();
+ }
+ }
+ return rc;
+}
+
+// QHash<>: Add with fake map nodes.
+static inline AbstractSymbolGroupNodePtrVector
+ qHashChildList(const SymbolGroupValue &v, VectorIndexType count)
+{
+ AbstractSymbolGroupNodePtrVector rc;
+ if (!count)
+ return rc;
+ const SymbolGroupValueVector nodes = qHashNodes(v, count);
+ if (nodes.size() != count)
+ return rc;
+ rc.reserve(count);
+ for (int i = 0; i < count; i++) {
+ const SymbolGroupValue &mapNode = nodes.at(i);
+ const SymbolGroupValue key = mapNode["key"];
+ const SymbolGroupValue value = mapNode["value"];
+ if (!key || !value)
+ return AbstractSymbolGroupNodePtrVector();
+ rc.push_back(MapNodeSymbolGroupNode::create(i, mapNode.address(),
+ mapNode.type(), key.node(), value.node()));
+ }
+ return rc;
+}
+
+AbstractSymbolGroupNodePtrVector containerChildren(SymbolGroupNode *node, int type,
+ int size, const SymbolGroupValueContext &ctx)
+{
+ if (!size)
+ return AbstractSymbolGroupNodePtrVector();
+ if (size > 100)
+ size = 100;
+ switch (type) {
+ case KT_QVector:
+ return qVectorChildList(node, size, ctx);
+ case KT_StdVector:
+ return stdVectorChildList(node, size, ctx);
+ case KT_QLinkedList:
+ return qLinkedListChildList(node, size, ctx);
+ case KT_QList:
+ return qListChildList(SymbolGroupValue(node, ctx), size);
+ case KT_QQueue:
+ if (const SymbolGroupValue qList = SymbolGroupValue(node, ctx)[unsigned(0)])
+ return qListChildList(qList, size);
+ break;
+ case KT_QStack:
+ if (const SymbolGroupValue qVector = SymbolGroupValue(node, ctx)[unsigned(0)])
+ return qVectorChildList(qVector.node(), size, ctx);
+ break;
+ case KT_QHash:
+ return qHashChildList(SymbolGroupValue(node, ctx), size);
+ case KT_QMultiHash:
+ if (const SymbolGroupValue hash = SymbolGroupValue(node, ctx)[unsigned(0)])
+ return qHashChildList(hash, size);
+ break;
+ case KT_QSet:
+ return qSetChildList(SymbolGroupValue(node, ctx), size);
+ case KT_QStringList:
+ if (const SymbolGroupValue qList = SymbolGroupValue(node, ctx)[unsigned(0)])
+ return qListChildList(qList, size);
+ break;
+ case KT_StdList:
+ return stdListChildList(node, size , ctx);
+ case KT_StdDeque:
+ return stdDequeChildList(SymbolGroupValue(node, ctx), size);
+ case KT_StdStack:
+ if (const SymbolGroupValue deque = SymbolGroupValue(node, ctx)[unsigned(0)])
+ return stdDequeChildList(deque, size);
+ break;
+ }
+ return AbstractSymbolGroupNodePtrVector();
+}
diff --git a/src/libs/qtcreatorcdbext/containers.h b/src/libs/qtcreatorcdbext/containers.h
new file mode 100644
index 0000000000..9ea9a81f38
--- /dev/null
+++ b/src/libs/qtcreatorcdbext/containers.h
@@ -0,0 +1,53 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 CONTAINERS_H
+#define CONTAINERS_H
+
+struct SymbolGroupValueContext;
+class AbstractSymbolGroupNode;
+class SymbolGroupNode;
+class SymbolGroupValue;
+
+#include "common.h"
+#include "knowntype.h"
+
+#include <vector>
+
+// Determine size of containers
+int containerSize(KnownType kt, const SymbolGroupValue &v);
+int containerSize(KnownType kt, SymbolGroupNode *n, const SymbolGroupValueContext &ctx);
+
+/* Create a list of children of containers. */
+std::vector<AbstractSymbolGroupNode *> containerChildren(SymbolGroupNode *node,
+ int type,
+ int size,
+ const SymbolGroupValueContext &ctx);
+
+#endif // CONTAINERS_H
diff --git a/src/libs/qtcreatorcdbext/eventcallback.cpp b/src/libs/qtcreatorcdbext/eventcallback.cpp
new file mode 100644
index 0000000000..2eb7344a0a
--- /dev/null
+++ b/src/libs/qtcreatorcdbext/eventcallback.cpp
@@ -0,0 +1,297 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "eventcallback.h"
+#include "extensioncontext.h"
+#include "stringutils.h"
+#include "gdbmihelpers.h"
+
+static const char eventContextC[] = "event";
+
+// Special exception codes (see dbgwinutils.cpp).
+enum { winExceptionCppException = 0xe06d7363,
+ winExceptionStartupCompleteTrap = 0x406d1388,
+ winExceptionRpcServerUnavailable = 0x6ba,
+ winExceptionRpcServerInvalid = 0x6a6,
+ winExceptionDllNotFound = 0xc0000135,
+ winExceptionDllEntryPointNoFound = 0xc0000139,
+ winExceptionDllInitFailed = 0xc0000142,
+ winExceptionMissingSystemFile = 0xc0000143,
+ winExceptionAppInitFailed = 0xc0000143
+};
+
+EventCallback::EventCallback(IDebugEventCallbacks *wrapped) :
+ m_wrapped(wrapped)
+{
+}
+
+EventCallback::~EventCallback()
+{
+}
+
+STDMETHODIMP EventCallback::QueryInterface(
+ THIS_
+ IN REFIID InterfaceId,
+ OUT PVOID* Interface)
+{
+ *Interface = NULL;
+
+ if (IsEqualIID(InterfaceId, __uuidof(IUnknown)) ||
+ IsEqualIID(InterfaceId, __uuidof(IDebugOutputCallbacks))) {
+ *Interface = (IDebugOutputCallbacks *)this;
+ AddRef();
+ return S_OK;
+ } else {
+ return E_NOINTERFACE;
+ }
+}
+
+STDMETHODIMP_(ULONG) EventCallback::AddRef(THIS)
+{
+ // This class is designed to be static so
+ // there's no true refcount.
+ return 1;
+}
+
+STDMETHODIMP_(ULONG) EventCallback::Release(THIS)
+{
+ // This class is designed to be static so
+ // there's no true refcount.
+ return 0;
+}
+
+STDMETHODIMP EventCallback::GetInterestMask(THIS_ __out PULONG mask)
+{
+ if (m_wrapped)
+ m_wrapped->GetInterestMask(mask);
+
+ *mask |= DEBUG_EVENT_CREATE_PROCESS | DEBUG_EVENT_EXIT_PROCESS
+ | DEBUG_EVENT_BREAKPOINT
+ | DEBUG_EVENT_EXCEPTION | DEBUG_EVENT_LOAD_MODULE | DEBUG_EVENT_UNLOAD_MODULE;
+ return S_OK;
+}
+
+STDMETHODIMP EventCallback::Breakpoint(THIS_ __in PDEBUG_BREAKPOINT b)
+{
+ // Breakpoint hit - Set the stop reason parameters on the extension context.
+ typedef ExtensionContext::StopReasonMap StopReasonMap;
+ typedef ExtensionContext::StopReasonMap::value_type StopReasonMapValue;
+
+ ULONG id = 0;
+ ULONG64 address = 0;
+ b->GetId(&id);
+ b->GetOffset(&address);
+
+ StopReasonMap stopReason;
+ stopReason.insert(StopReasonMapValue(std::string("breakpointId"), toString(id)));
+ if (address)
+ stopReason.insert(StopReasonMapValue(std::string("breakpointAddress"), toString(address)));
+ ExtensionContext::instance().setStopReason(stopReason, "breakpoint");
+ return m_wrapped ? m_wrapped->Breakpoint(b) : S_OK;
+}
+
+static inline ExtensionContext::StopReasonMap exceptionParameters(const EXCEPTION_RECORD64 &e,
+ unsigned firstChance)
+{
+ typedef ExtensionContext::StopReasonMap StopReasonMap;
+ typedef ExtensionContext::StopReasonMap::value_type StopReasonMapValue;
+ // Fill exception record
+ StopReasonMap parameters;
+ parameters.insert(StopReasonMapValue(std::string("firstChance"), toString(firstChance)));
+ parameters.insert(StopReasonMapValue(std::string("exceptionAddress"),
+ toString(e.ExceptionAddress)));
+ parameters.insert(StopReasonMapValue(std::string("exceptionCode"),
+ toString(e.ExceptionCode)));
+ parameters.insert(StopReasonMapValue(std::string("exceptionFlags"),
+ toString(e.ExceptionFlags)));
+ // Hard code some parameters (used for access violations)
+ if (e.NumberParameters >= 1)
+ parameters.insert(StopReasonMapValue(std::string("exceptionInformation0"),
+ toString(e.ExceptionInformation[0])));
+ if (e.NumberParameters >= 2)
+ parameters.insert(StopReasonMapValue(std::string("exceptionInformation1"),
+ toString(e.ExceptionInformation[1])));
+ // Add top stack frame if possible
+ StackFrame frame;
+ std::string errorMessage;
+ // If it is a C++ exception, get frame #2 (first outside MSVC runtime)
+ const unsigned frameNumber = e.ExceptionCode == winExceptionCppException ? 2 : 0;
+ if (getFrame(frameNumber, &frame, &errorMessage)) {
+ if (!frame.fullPathName.empty()) {
+ parameters.insert(StopReasonMapValue(std::string("exceptionFile"),
+ wStringToString(frame.fullPathName)));
+ parameters.insert(StopReasonMapValue(std::string("exceptionLine"),
+ toString(frame.line)));
+ }
+ if (!frame.function.empty())
+ parameters.insert(StopReasonMapValue(std::string("exceptionFunction"),
+ wStringToString(frame.function)));
+ } // getCurrentFrame
+ return parameters;
+}
+
+STDMETHODIMP EventCallback::Exception(
+ THIS_
+ __in PEXCEPTION_RECORD64 Ex,
+ __in ULONG FirstChance
+ )
+{
+ // Report the exception as GBMI and set potential stop reason
+ const ExtensionContext::StopReasonMap parameters =
+ exceptionParameters(*Ex, FirstChance);
+
+ std::ostringstream str;
+ formatGdbmiHash(str, parameters);
+ ExtensionContext::instance().setStopReason(parameters, "exception");
+ ExtensionContext::instance().report('E', 0, "exception", "%s", str.str().c_str());
+ return m_wrapped ? m_wrapped->Exception(Ex, FirstChance) : S_OK;
+}
+
+STDMETHODIMP EventCallback::CreateThread(
+ THIS_
+ __in ULONG64 Handle,
+ __in ULONG64 DataOffset,
+ __in ULONG64 StartOffset
+ )
+{
+ return m_wrapped ? m_wrapped->CreateThread(Handle, DataOffset, StartOffset) : S_OK;
+}
+
+STDMETHODIMP EventCallback::ExitThread(
+ THIS_
+ __in ULONG ExitCode
+ )
+{
+ return m_wrapped ? m_wrapped->ExitThread(ExitCode) : S_OK;
+}
+
+STDMETHODIMP EventCallback::CreateProcess(
+ THIS_
+ __in ULONG64 ImageFileHandle,
+ __in ULONG64 Handle,
+ __in ULONG64 BaseOffset,
+ __in ULONG ModuleSize,
+ __in_opt PCSTR ModuleName,
+ __in_opt PCSTR ImageName,
+ __in ULONG CheckSum,
+ __in ULONG TimeDateStamp,
+ __in ULONG64 InitialThreadHandle,
+ __in ULONG64 ThreadDataOffset,
+ __in ULONG64 StartOffset
+ )
+{
+ return m_wrapped ? m_wrapped->CreateProcess(ImageFileHandle, Handle,
+ BaseOffset, ModuleSize, ModuleName,
+ ImageName, CheckSum, TimeDateStamp,
+ InitialThreadHandle, ThreadDataOffset,
+ StartOffset) : S_OK;
+}
+
+STDMETHODIMP EventCallback::ExitProcess(
+ THIS_
+ __in ULONG ExitCode
+ )
+{
+ ExtensionContext::instance().report('E', 0, eventContextC, "Process exited (%lu)",
+ ExitCode);
+ const HRESULT hr = m_wrapped ? m_wrapped->ExitProcess(ExitCode) : S_OK;
+ // Remotely debugged process exited, there is no session-inactive notification.
+ // Note: We get deleted here, so, order is important.
+ ExtensionContext::instance().unhookCallbacks();
+ return hr;
+}
+
+STDMETHODIMP EventCallback::LoadModule(
+ THIS_
+ __in ULONG64 ImageFileHandle,
+ __in ULONG64 BaseOffset,
+ __in ULONG ModuleSize,
+ __in_opt PCSTR ModuleName,
+ __in_opt PCSTR ImageName,
+ __in ULONG CheckSum,
+ __in ULONG TimeDateStamp
+ )
+{
+ return m_wrapped ? m_wrapped->LoadModule(ImageFileHandle, BaseOffset,
+ ModuleSize, ModuleName, ImageName,
+ CheckSum, TimeDateStamp) : S_OK;
+}
+
+STDMETHODIMP EventCallback::UnloadModule(
+ THIS_
+ __in_opt PCSTR ImageBaseName,
+ __in ULONG64 BaseOffset
+ )
+{
+ return m_wrapped ? m_wrapped->UnloadModule(ImageBaseName, BaseOffset) : S_OK;
+}
+
+STDMETHODIMP EventCallback::SystemError(
+ THIS_
+ __in ULONG Error,
+ __in ULONG Level
+ )
+{
+ return m_wrapped ? m_wrapped->SystemError(Error, Level) : S_OK;
+}
+
+STDMETHODIMP EventCallback::SessionStatus(
+ THIS_
+ __in ULONG Status
+ )
+{
+ return m_wrapped ? m_wrapped->SessionStatus(Status) : S_OK;
+}
+
+STDMETHODIMP EventCallback::ChangeDebuggeeState(
+ THIS_
+ __in ULONG Flags,
+ __in ULONG64 Argument
+ )
+{
+ return m_wrapped ? m_wrapped->ChangeDebuggeeState(Flags, Argument) : S_OK;
+}
+
+STDMETHODIMP EventCallback::ChangeEngineState(
+ THIS_
+ __in ULONG Flags,
+ __in ULONG64 Argument
+ )
+{
+ return m_wrapped ? m_wrapped->ChangeEngineState(Flags, Argument) : S_OK;
+}
+
+STDMETHODIMP EventCallback::ChangeSymbolState(
+ THIS_
+ __in ULONG Flags,
+ __in ULONG64 Argument
+ )
+{
+ return m_wrapped ? m_wrapped->ChangeSymbolState(Flags, Argument) : S_OK;
+}
diff --git a/src/libs/qtcreatorcdbext/eventcallback.h b/src/libs/qtcreatorcdbext/eventcallback.h
new file mode 100644
index 0000000000..579bb7c138
--- /dev/null
+++ b/src/libs/qtcreatorcdbext/eventcallback.h
@@ -0,0 +1,157 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 DEBUGEVENTHANDLER_H
+#define DEBUGEVENTHANDLER_H
+
+#include "common.h"
+#include "extensioncontext.h"
+
+/* IDebugEventCallbacks event handler wrapping IDebugEventCallbacks to catch some output */
+
+class EventCallback : public IDebugEventCallbacks
+{
+public:
+ explicit EventCallback(IDebugEventCallbacks *wrapped);
+ virtual ~EventCallback();
+ // IUnknown.
+ STDMETHOD(QueryInterface)(
+ THIS_
+ IN REFIID InterfaceId,
+ OUT PVOID* Interface
+ );
+ STDMETHOD_(ULONG, AddRef)(
+ THIS
+ );
+ STDMETHOD_(ULONG, Release)(
+ THIS
+ );
+
+ // IDebugEventCallbacks.
+
+ STDMETHOD(GetInterestMask)(
+ THIS_
+ __out PULONG mask
+ );
+
+
+ STDMETHOD(Breakpoint)(
+ THIS_
+ __in PDEBUG_BREAKPOINT Bp
+ );
+
+ STDMETHOD(Exception)(
+ THIS_
+ __in PEXCEPTION_RECORD64 Exception,
+ __in ULONG FirstChance
+ );
+
+ STDMETHOD(CreateThread)(
+ THIS_
+ __in ULONG64 Handle,
+ __in ULONG64 DataOffset,
+ __in ULONG64 StartOffset
+ );
+ STDMETHOD(ExitThread)(
+ THIS_
+ __in ULONG ExitCode
+ );
+
+ STDMETHOD(CreateProcess)(
+ THIS_
+ __in ULONG64 ImageFileHandle,
+ __in ULONG64 Handle,
+ __in ULONG64 BaseOffset,
+ __in ULONG ModuleSize,
+ __in_opt PCSTR ModuleName,
+ __in_opt PCSTR ImageName,
+ __in ULONG CheckSum,
+ __in ULONG TimeDateStamp,
+ __in ULONG64 InitialThreadHandle,
+ __in ULONG64 ThreadDataOffset,
+ __in ULONG64 StartOffset
+ );
+
+ STDMETHOD(ExitProcess)(
+ THIS_
+ __in ULONG ExitCode
+ );
+
+ // Call handleModuleLoad() when reimplementing this
+ STDMETHOD(LoadModule)(
+ THIS_
+ __in ULONG64 ImageFileHandle,
+ __in ULONG64 BaseOffset,
+ __in ULONG ModuleSize,
+ __in_opt PCSTR ModuleName,
+ __in_opt PCSTR ImageName,
+ __in ULONG CheckSum,
+ __in ULONG TimeDateStamp
+ );
+
+ // Call handleModuleUnload() when reimplementing this
+ STDMETHOD(UnloadModule)(
+ THIS_
+ __in_opt PCSTR ImageBaseName,
+ __in ULONG64 BaseOffset
+ );
+
+ STDMETHOD(SystemError)(
+ THIS_
+ __in ULONG Error,
+ __in ULONG Level
+ );
+
+ STDMETHOD(SessionStatus)(
+ THIS_
+ __in ULONG Status
+ );
+
+ STDMETHOD(ChangeDebuggeeState)(
+ THIS_
+ __in ULONG Flags,
+ __in ULONG64 Argument
+ );
+
+ STDMETHOD(ChangeEngineState)(
+ THIS_
+ __in ULONG Flags,
+ __in ULONG64 Argument
+ );
+
+ STDMETHOD(ChangeSymbolState)(
+ THIS_
+ __in ULONG Flags,
+ __in ULONG64 Argument
+ );
+
+ private:
+ IDebugEventCallbacks *m_wrapped;
+};
+#endif // DEBUGEVENTHANDLER_H
diff --git a/src/libs/qtcreatorcdbext/extensioncontext.cpp b/src/libs/qtcreatorcdbext/extensioncontext.cpp
new file mode 100644
index 0000000000..b393752d89
--- /dev/null
+++ b/src/libs/qtcreatorcdbext/extensioncontext.cpp
@@ -0,0 +1,319 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "extensioncontext.h"
+#include "symbolgroup.h"
+#include "eventcallback.h"
+#include "outputcallback.h"
+#include "stringutils.h"
+
+// wdbgexts.h declares 'extern WINDBG_EXTENSION_APIS ExtensionApis;'
+// and it's inline functions rely on its existence.
+WINDBG_EXTENSION_APIS ExtensionApis = {sizeof(WINDBG_EXTENSION_APIS), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+const char *ExtensionContext::stopReasonKeyC = "reason";
+
+ExtensionContext::ExtensionContext() :
+ m_hookedClient(0),
+ m_oldEventCallback(0), m_oldOutputCallback(0),
+ m_creatorEventCallback(0), m_creatorOutputCallback(0)
+{
+}
+
+ExtensionContext::~ExtensionContext()
+{
+ unhookCallbacks();
+}
+
+ExtensionContext &ExtensionContext::instance()
+{
+ static ExtensionContext extContext;
+ return extContext;
+}
+
+// Redirect the event/output callbacks
+void ExtensionContext::hookCallbacks(CIDebugClient *client)
+{
+ if (!client || m_hookedClient || m_creatorEventCallback)
+ return;
+ // Store the hooked client. Any other client obtained
+ // is invalid for unhooking
+ m_hookedClient = client;
+ if (client->GetEventCallbacks(&m_oldEventCallback) == S_OK) {
+ m_creatorEventCallback = new EventCallback(m_oldEventCallback);
+ client->SetEventCallbacks(m_creatorEventCallback);
+ }
+ if (client->GetOutputCallbacksWide(&m_oldOutputCallback) == S_OK) {
+ m_creatorOutputCallback = new OutputCallback(m_oldOutputCallback);
+ client->SetOutputCallbacksWide(m_creatorOutputCallback);
+ }
+}
+
+void ExtensionContext::setStopReason(const StopReasonMap &r, const std::string &reason)
+{
+ m_stopReason = r;
+ if (!reason.empty())
+ m_stopReason.insert(StopReasonMap::value_type(stopReasonKeyC, reason));
+}
+
+// Restore the callbacks.
+void ExtensionContext::unhookCallbacks()
+{
+ if (!m_hookedClient || (!m_creatorEventCallback && !m_creatorOutputCallback))
+ return;
+
+ if (m_creatorEventCallback) {
+ m_hookedClient->SetEventCallbacks(m_oldEventCallback);
+ delete m_creatorEventCallback;
+ m_creatorEventCallback = 0;
+ m_oldEventCallback = 0;
+ }
+
+ if (m_creatorOutputCallback) {
+ m_hookedClient->SetOutputCallbacksWide(m_oldOutputCallback);
+ delete m_creatorOutputCallback;
+ m_creatorOutputCallback = 0;
+ m_oldOutputCallback = 0;
+ }
+ m_hookedClient = 0;
+}
+
+HRESULT ExtensionContext::initialize(PULONG Version, PULONG Flags)
+{
+ if (isInitialized())
+ return S_OK;
+
+ *Version = DEBUG_EXTENSION_VERSION(1, 0);
+ *Flags = 0;
+
+ IInterfacePointer<CIDebugClient> client;
+ if (!client.create())
+ return client.hr();
+ m_control.create(client.data());
+ if (!m_control)
+ return m_control.hr();
+ return m_control->GetWindbgExtensionApis64(&ExtensionApis);
+}
+
+bool ExtensionContext::isInitialized() const
+{
+ return ExtensionApis.lpOutputRoutine != 0;
+}
+
+ULONG ExtensionContext::executionStatus() const
+{
+ ULONG ex = 0;
+ return (m_control && SUCCEEDED(m_control->GetExecutionStatus(&ex))) ? ex : ULONG(0);
+}
+
+// Complete stop parameters with common parameters and report
+static inline ExtensionContext::StopReasonMap
+ completeStopReasons(ExtensionContext::StopReasonMap stopReasons, ULONG ex)
+{
+ typedef ExtensionContext::StopReasonMap::value_type StopReasonMapValue;
+
+ stopReasons.insert(StopReasonMapValue(std::string("executionStatus"), toString(ex)));
+
+ IInterfacePointer<CIDebugClient> client;
+ if (client.create()) {
+ if (const ULONG processId = currentProcessId(client.data()))
+ stopReasons.insert(StopReasonMapValue(std::string("processId"), toString(processId)));
+ const ULONG threadId = currentThreadId(client.data());
+ stopReasons.insert(StopReasonMapValue(std::string("threadId"), toString(threadId)));
+ }
+ // Any reason?
+ const std::string reasonKey = std::string(ExtensionContext::stopReasonKeyC);
+ if (stopReasons.find(reasonKey) == stopReasons.end())
+ stopReasons.insert(StopReasonMapValue(reasonKey, "unknown"));
+ return stopReasons;
+}
+
+void ExtensionContext::notifyIdle()
+{
+ discardSymbolGroup();
+
+ const StopReasonMap stopReasons = completeStopReasons(m_stopReason, executionStatus());
+ m_stopReason.clear();
+ // Format
+ std::ostringstream str;
+ formatGdbmiHash(str, stopReasons);
+ report('E', 0, "session_idle", "%s", str.str().c_str());
+ m_stopReason.clear();
+}
+
+void ExtensionContext::notifyState(ULONG Notify)
+{
+ const ULONG ex = executionStatus();
+ switch (Notify) {
+ case DEBUG_NOTIFY_SESSION_ACTIVE:
+ report('E', 0, "session_active", "%u", ex);
+ break;
+ case DEBUG_NOTIFY_SESSION_ACCESSIBLE: // Meaning, commands accepted
+ report('E', 0, "session_accessible", "%u", ex);
+ break;
+ case DEBUG_NOTIFY_SESSION_INACCESSIBLE:
+ report('E', 0, "session_inaccessible", "%u", ex);
+ break;
+ case DEBUG_NOTIFY_SESSION_INACTIVE:
+ report('E', 0, "session_inactive", "%u", ex);
+ discardSymbolGroup();
+ // We lost the debuggee, at this point restore output.
+ if (ex & DEBUG_STATUS_NO_DEBUGGEE)
+ unhookCallbacks();
+ break;
+ }
+}
+
+SymbolGroup *ExtensionContext::symbolGroup(CIDebugSymbols *symbols, ULONG threadId, int frame, std::string *errorMessage)
+{
+ if (m_symbolGroup.get() && m_symbolGroup->frame() == frame && m_symbolGroup->threadId() == threadId)
+ return m_symbolGroup.get();
+ SymbolGroup *newSg = SymbolGroup::create(m_control.data(), symbols, threadId, frame, errorMessage);
+ if (!newSg)
+ return 0;
+ m_symbolGroup.reset(newSg);
+ return newSg;
+}
+
+int ExtensionContext::symbolGroupFrame() const
+{
+ if (m_symbolGroup.get())
+ return m_symbolGroup->frame();
+ return -1;
+}
+
+void ExtensionContext::discardSymbolGroup()
+{
+ if (m_symbolGroup.get())
+ m_symbolGroup.reset();
+}
+
+bool ExtensionContext::report(char code, int token, const char *serviceName, PCSTR Format, ...)
+{
+ if (!isInitialized())
+ return false;
+ // '<qtcreatorcdbext>|R|<token>|<serviceName>|<one-line-output>'.
+ m_control->Output(DEBUG_OUTPUT_NORMAL, "<qtcreatorcdbext>|%c|%d|%s|", code, token, serviceName);
+ va_list Args;
+ va_start(Args, Format);
+ m_control->OutputVaList(DEBUG_OUTPUT_NORMAL, Format, Args);
+ va_end(Args);
+ m_control->Output(DEBUG_OUTPUT_NORMAL, "\n");
+ return true;
+}
+
+// Exported C-functions
+extern "C" {
+
+HRESULT CALLBACK DebugExtensionInitialize(PULONG Version, PULONG Flags)
+{
+ return ExtensionContext::instance().initialize(Version, Flags);
+}
+
+void CALLBACK DebugExtensionUninitialize(void)
+{
+}
+
+void CALLBACK DebugExtensionNotify(ULONG Notify, ULONG64)
+{
+ ExtensionContext::instance().notifyState(Notify);
+}
+
+} // extern "C"
+
+// -------- ExtensionCommandContext
+
+ExtensionCommandContext *ExtensionCommandContext::m_instance = 0;
+
+ExtensionCommandContext::ExtensionCommandContext(CIDebugClient *client) : m_client(client)
+{
+ ExtensionCommandContext::m_instance = this;
+}
+
+ExtensionCommandContext::~ExtensionCommandContext()
+{
+ ExtensionCommandContext::m_instance = 0;
+}
+
+CIDebugControl *ExtensionCommandContext::control()
+{
+ if (!m_control)
+ m_control.create(m_client);
+ return m_control.data();
+}
+
+ExtensionCommandContext *ExtensionCommandContext::instance()
+{
+ return m_instance;
+}
+
+CIDebugSymbols *ExtensionCommandContext::symbols()
+{
+ if (!m_symbols)
+ m_symbols.create(m_client);
+ return m_symbols.data();
+}
+
+CIDebugSystemObjects *ExtensionCommandContext::systemObjects()
+{
+ if (!m_systemObjects)
+ m_systemObjects.create(m_client);
+ return m_systemObjects.data();
+}
+
+CIDebugAdvanced *ExtensionCommandContext::advanced()
+{
+ if (!m_advanced)
+ m_advanced.create(m_client);
+ return m_advanced.data();
+}
+
+CIDebugRegisters *ExtensionCommandContext::registers()
+{
+ if (!m_registers)
+ m_registers.create(m_client);
+ return m_registers.data();
+}
+
+CIDebugDataSpaces *ExtensionCommandContext::dataSpaces()
+{
+ if (!m_dataSpaces)
+ m_dataSpaces.create(m_client);
+ return m_dataSpaces.data();
+}
+
+ULONG ExtensionCommandContext::threadId()
+{
+ if (CIDebugSystemObjects *so = systemObjects()) {
+ ULONG threadId = 0;
+ if (SUCCEEDED(so->GetCurrentThreadId(&threadId)))
+ return threadId;
+ }
+ return 0;
+}
diff --git a/src/libs/qtcreatorcdbext/extensioncontext.h b/src/libs/qtcreatorcdbext/extensioncontext.h
new file mode 100644
index 0000000000..a299f9dde3
--- /dev/null
+++ b/src/libs/qtcreatorcdbext/extensioncontext.h
@@ -0,0 +1,135 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 EXTENSIONCONTEXT_H
+#define EXTENSIONCONTEXT_H
+
+#include "common.h"
+#include "iinterfacepointer.h"
+
+#include <memory>
+#include <map>
+
+class SymbolGroup;
+
+// Global singleton with context.
+// Caches a symbolgroup per frame and thread as long as the session is accessible.
+class ExtensionContext {
+ ExtensionContext(const ExtensionContext&);
+ ExtensionContext& operator=(const ExtensionContext&);
+
+ ExtensionContext();
+public:
+ // Key used to report stop reason in StopReasonMap
+ static const char *stopReasonKeyC;
+ // Map of parameters reported with the next stop as GDBMI
+ typedef std::map<std::string, std::string> StopReasonMap;
+
+ ~ExtensionContext();
+
+ static ExtensionContext &instance();
+ // Call from DLL initialization.
+ HRESULT initialize(PULONG Version, PULONG Flags);
+
+ // Hook up our Event and Output callbacks that report exceptions and events.
+ // Call this from the first extension command that gets a client.
+ // Does not work when called from initialization.
+ void hookCallbacks(CIDebugClient *client);
+ // Undo hooking.
+ void unhookCallbacks();
+
+ // Report output in standardized format understood by Qt Creator.
+ // '<qtcreatorcdbext>|R|<token>|<serviceName>|<one-line-output>'.
+ // Char code is 'R' command reply, 'N' command fail, 'E' event notification
+ bool report(char code, int token, const char *serviceName, PCSTR Format, ...);
+
+ ULONG executionStatus() const;
+ // Call from notify handler, tell engine about state.
+ void notifyState(ULONG Notify);
+ // register as '.idle_cmd' to notify creator about stop
+ void notifyIdle();
+
+ // Return symbol group for frame (cache as long as frame does not change).
+ SymbolGroup *symbolGroup(CIDebugSymbols *symbols, ULONG threadId, int frame, std::string *errorMessage);
+ int symbolGroupFrame() const;
+
+ // Stop reason is reported with the next idle notification
+ void setStopReason(const StopReasonMap &, const std::string &reason = std::string());
+
+private:
+ bool isInitialized() const;
+ void discardSymbolGroup();
+
+ IInterfacePointer<CIDebugControl> m_control;
+ std::auto_ptr<SymbolGroup> m_symbolGroup;
+
+ CIDebugClient *m_hookedClient;
+ IDebugEventCallbacks *m_oldEventCallback;
+ IDebugOutputCallbacksWide *m_oldOutputCallback;
+ IDebugEventCallbacks *m_creatorEventCallback;
+ IDebugOutputCallbacksWide *m_creatorOutputCallback;
+
+ StopReasonMap m_stopReason;
+};
+
+// Context for extension commands to be instantiated on stack in a command handler.
+class ExtensionCommandContext
+{
+ ExtensionCommandContext(const ExtensionCommandContext&);
+ ExtensionCommandContext &operator=(const ExtensionCommandContext&);
+public:
+ explicit ExtensionCommandContext(CIDebugClient *Client);
+ ~ExtensionCommandContext();
+
+ // For accessing outside commands. Might return 0, based on the
+ // assumption that there is only once instance active.
+ static ExtensionCommandContext *instance();
+
+ CIDebugControl *control();
+ CIDebugSymbols *symbols();
+ CIDebugSystemObjects *systemObjects();
+ CIDebugAdvanced *advanced();
+ CIDebugRegisters *registers();
+ CIDebugDataSpaces *dataSpaces();
+
+ ULONG threadId();
+
+private:
+ static ExtensionCommandContext *m_instance;
+
+ CIDebugClient *m_client;
+ IInterfacePointer<CIDebugControl> m_control;
+ IInterfacePointer<CIDebugSymbols> m_symbols;
+ IInterfacePointer<CIDebugAdvanced> m_advanced;
+ IInterfacePointer<CIDebugSystemObjects> m_systemObjects;
+ IInterfacePointer<CIDebugRegisters> m_registers;
+ IInterfacePointer<CIDebugDataSpaces> m_dataSpaces;
+};
+
+#endif // EXTENSIONCONTEXT_H
diff --git a/src/libs/qtcreatorcdbext/gdbmihelpers.cpp b/src/libs/qtcreatorcdbext/gdbmihelpers.cpp
new file mode 100644
index 0000000000..af6f59442c
--- /dev/null
+++ b/src/libs/qtcreatorcdbext/gdbmihelpers.cpp
@@ -0,0 +1,618 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "gdbmihelpers.h"
+#include "stringutils.h"
+#include "iinterfacepointer.h"
+#include "base64.h"
+
+#include <vector>
+
+StackFrame::StackFrame(ULONG64 a) : address(a), line(0) {}
+
+std::wstring StackFrame::fileName() const
+{
+ std::wstring::size_type lastSlash = fullPathName.rfind(L'\\');
+ if (lastSlash == std::wstring::npos)
+ return fullPathName;
+ return fullPathName.substr(lastSlash + 1, fullPathName.size() - lastSlash - 1);
+}
+
+void StackFrame::formatGDBMI(std::ostream &str, unsigned level) const
+{
+ str << "frame={level=\"" << level << "\",addr=\"0x"
+ << std::hex << address << std::dec << '"';
+ if (!function.empty()) {
+ // Split into module/function
+ const std::wstring::size_type exclPos = function.find('!');
+ if (exclPos == std::wstring::npos) {
+ str << ",func=\"" << gdbmiWStringFormat(function) << '"';
+ } else {
+ const std::wstring module = function.substr(0, exclPos);
+ const std::wstring fn = function.substr(exclPos + 1, function.size() - exclPos - 1);
+ str << ",func=\"" << gdbmiWStringFormat(fn)
+ << "\",from=\"" << gdbmiWStringFormat(module) << '"';
+ }
+ }
+ if (!fullPathName.empty()) { // Creator/gdbmi expects 'clean paths'
+ std::wstring cleanPath = fullPathName;
+ replace(cleanPath, L'\\', L'/');
+ str << ",fullname=\"" << gdbmiWStringFormat(fullPathName)
+ << "\",file=\"" << gdbmiWStringFormat(fileName()) << "\",line=\"" << line << '"';
+ }
+ str << '}';
+}
+
+Thread::Thread(ULONG i, ULONG sysId) : id(i), systemId(sysId) {}
+
+void Thread::formatGDBMI(std::ostream &str) const
+{
+ str << "{id=\"" << id << "\",target-id=\"" << systemId << "\",";
+ frame.formatGDBMI(str);
+ if (!name.empty())
+ str << ",name=\"" << gdbmiWStringFormat(name) << '"';
+ if (!state.empty())
+ str << ",state=\"" << state << '"';
+ str << '}';
+}
+
+static inline std::string msgGetThreadsFailed(const std::string &why)
+{
+ return std::string("Unable to determine the thread information: ") + why;
+}
+
+static inline bool setCurrentThread(CIDebugSystemObjects *debugSystemObjects,
+ ULONG id, std::string *errorMessage)
+{
+ const HRESULT hr = debugSystemObjects->SetCurrentThreadId(id);
+ if (FAILED(hr)) {
+ *errorMessage = msgDebugEngineComFailed("SetCurrentThreadId", hr);
+ return false;
+ }
+ return true;
+}
+
+// Fill in stack frame info
+void getFrame(CIDebugSymbols *debugSymbols,
+ const DEBUG_STACK_FRAME &s, StackFrame *f)
+{
+ WCHAR wBuf[MAX_PATH];
+ f->address = s.InstructionOffset;
+ HRESULT hr = debugSymbols->GetNameByOffsetWide(f->address, wBuf, MAX_PATH, 0, 0);
+ if (SUCCEEDED(hr)) {
+ f->function = wBuf;
+ } else {
+ f->function.clear();
+ }
+ ULONG64 ul64Displacement = 0;
+ hr = debugSymbols->GetLineByOffsetWide(f->address, &(f->line), wBuf, MAX_PATH, 0, &ul64Displacement);
+ if (SUCCEEDED(hr)) {
+ f->fullPathName = wBuf;
+ } else {
+ f->fullPathName.clear();
+ f->line = 0;
+ }
+}
+
+// Determine the frames of the threads.
+// Note: Current thread is switched as a side effect!
+static bool getThreadFrames(CIDebugSymbols *debugSymbols,
+ CIDebugSystemObjects *debugSystemObjects,
+ CIDebugControl *debugControl,
+ Threads *threads, std::string *errorMessage)
+{
+ enum { MaxFrames = 1 };
+
+ DEBUG_STACK_FRAME frames[MaxFrames];
+ const Threads::iterator end = threads->end();
+ for (Threads::iterator it = threads->begin(); it != end; ++it) {
+ if (!setCurrentThread(debugSystemObjects, it->id, errorMessage))
+ return false;
+ ULONG frameCount;
+ const HRESULT hr = debugControl->GetStackTrace(0, 0, 0, frames, MaxFrames, &frameCount);
+ if (SUCCEEDED(hr))
+ getFrame(debugSymbols, frames[0], &(it->frame));
+ }
+ return true;
+}
+
+bool getFrame(unsigned n, StackFrame *f, std::string *errorMessage)
+{
+ IInterfacePointer<CIDebugClient> client;
+ if (!client.create()) {
+ *errorMessage = "Cannot obtain client.";
+ return false;
+ }
+ IInterfacePointer<CIDebugSymbols> symbols(client.data());
+ IInterfacePointer<CIDebugControl> control(client.data());
+ if (!symbols || !control) {
+ *errorMessage = "Cannot obtain required objects.";
+ return false;
+ }
+ return getFrame(symbols.data(), control.data(), n, f, errorMessage);
+}
+
+bool getFrame(CIDebugSymbols *debugSymbols,
+ CIDebugControl *debugControl,
+ unsigned n, StackFrame *f, std::string *errorMessage)
+{
+ DEBUG_STACK_FRAME *frames = new DEBUG_STACK_FRAME[n + 1];
+ ULONG frameCount;
+ const HRESULT hr = debugControl->GetStackTrace(0, 0, 0, frames, n + 1, &frameCount);
+ if (FAILED(hr)) {
+ delete [] frames;
+ *errorMessage = msgDebugEngineComFailed("GetStackTrace", hr);
+ return false;
+ }
+ getFrame(debugSymbols, frames[n], f);
+ delete [] frames;
+ return true;
+}
+
+bool threadList(CIDebugSystemObjects *debugSystemObjects,
+ CIDebugSymbols *debugSymbols,
+ CIDebugControl *debugControl,
+ CIDebugAdvanced *debugAdvanced,
+ Threads* threads, ULONG *currentThreadId,
+ std::string *errorMessage)
+{
+ threads->clear();
+ ULONG threadCount;
+ *currentThreadId = 0;
+ // Get count
+ HRESULT hr= debugSystemObjects->GetNumberThreads(&threadCount);
+ if (FAILED(hr)) {
+ *errorMessage= msgGetThreadsFailed(msgDebugEngineComFailed("GetNumberThreads", hr));
+ return false;
+ }
+ // Get index of current
+ if (!threadCount)
+ return true;
+ hr = debugSystemObjects->GetCurrentThreadId(currentThreadId);
+ if (FAILED(hr)) {
+ *errorMessage= msgGetThreadsFailed(msgDebugEngineComFailed("GetCurrentThreadId", hr));
+ return false;
+ }
+ // Get Identifiers
+ threads->reserve(threadCount);
+ ULONG *ids = new ULONG[threadCount];
+ ULONG *systemIds = new ULONG[threadCount];
+ hr = debugSystemObjects->GetThreadIdsByIndex(0, threadCount, ids, systemIds);
+ if (FAILED(hr)) {
+ *errorMessage= msgGetThreadsFailed(msgDebugEngineComFailed("GetThreadIdsByIndex", hr));
+ return false;
+ }
+ // Create entries
+ static WCHAR name[256];
+ for (ULONG i= 0; i < threadCount ; i++) {
+ const ULONG id = ids[i];
+ Thread thread(id, systemIds[i]);
+ // Thread name
+ ULONG bytesReceived = 0;
+ hr = debugAdvanced->GetSystemObjectInformation(DEBUG_SYSOBJINFO_THREAD_NAME_WIDE,
+ 0, id, name,
+ sizeof(name), &bytesReceived);
+ if (SUCCEEDED(hr) && bytesReceived)
+ thread.name = name;
+ threads->push_back(thread);
+ }
+ delete [] ids;
+ delete [] systemIds;
+ // Get frames and at all events,
+ // restore current thread after switching frames.
+ const bool framesOk = getThreadFrames(debugSymbols,
+ debugSystemObjects,
+ debugControl,
+ threads, errorMessage);
+ const bool restoreOk =setCurrentThread(debugSystemObjects, *currentThreadId, errorMessage);
+ return framesOk && restoreOk;
+}
+
+/* Format as: \code
+
+52^done,threads=[{id="1",target-id="Thread 4740.0xb30",
+frame={level="0",addr="0x00403487",func="foo",
+args=[{name="this",value="0x27fee4"}],file="mainwindow.cpp",fullname="c:\\qt\\projects\\gitguim\\app/mainwindow.cpp",line="298"},state="stopped"}],
+current-thread-id="1"
+*/
+
+std::string gdbmiThreadList(CIDebugSystemObjects *debugSystemObjects,
+ CIDebugSymbols *debugSymbols,
+ CIDebugControl *debugControl,
+ CIDebugAdvanced *debugAdvanced,
+ std::string *errorMessage)
+{
+ Threads threads;
+ ULONG currentThreadId;
+ if (!threadList(debugSystemObjects, debugSymbols, debugControl,
+ debugAdvanced, &threads, &currentThreadId, errorMessage))
+ return std::string();
+ std::ostringstream str;
+ str << "{threads=[";
+ const Threads::const_iterator cend = threads.end();
+ for (Threads::const_iterator it = threads.begin(); it != cend; ++it)
+ it->formatGDBMI(str);
+ str << "],current-thread-id=\"" << currentThreadId << "\"}";
+ return str.str();
+}
+
+Module::Module() : deferred(false), base(0), size(0)
+{
+}
+
+Modules getModules(CIDebugSymbols *syms, std::string *errorMessage)
+{
+ enum { BufSize = 1024 };
+
+ char nameBuf[BufSize];
+ char fileBuf[BufSize];
+
+ ULONG Loaded;
+ ULONG Unloaded;
+ HRESULT hr = syms->GetNumberModules(&Loaded, &Unloaded);
+ if (FAILED(hr)) {
+ *errorMessage = msgDebugEngineComFailed("GetNumberModules", hr);
+ return Modules();
+ }
+ const ULONG count = Loaded + Unloaded;
+ Modules rc;
+ rc.reserve(count);
+ DEBUG_MODULE_PARAMETERS *parameters = new DEBUG_MODULE_PARAMETERS[count];
+ hr = syms->GetModuleParameters(count, NULL, 0, parameters);
+ if (FAILED(hr)) {
+ delete [] parameters;
+ *errorMessage = msgDebugEngineComFailed("GetModuleParameters", hr);
+ return Modules();
+ }
+
+ for (ULONG m = 0; m < count; m++) {
+ Module module;
+ module.base = parameters[m].Base;
+ module.size = parameters[m].Size;
+ module.deferred = parameters[m].Flags == DEBUG_SYMTYPE_DEFERRED;
+ hr = syms->GetModuleNames(m, 0, fileBuf, BufSize, NULL,
+ nameBuf, BufSize, NULL, NULL, NULL, NULL);
+ if (FAILED(hr))
+ break; // Fail silently should unloaded modules not work.
+ module.name = nameBuf;
+ module.image = fileBuf;
+ rc.push_back(module);
+ }
+ return rc;
+}
+
+std::string gdbmiModules(CIDebugSymbols *syms, bool humanReadable, std::string *errorMessage)
+{
+ const Modules modules = getModules(syms, errorMessage);
+ if (modules.empty())
+ return std::string();
+
+ std::ostringstream str;
+ str << '[' << std::hex << std::showbase;
+ const Modules::size_type size = modules.size();
+ for (Modules::size_type m = 0; m < size; m++) {
+ const Module &module = modules.at(m);
+ if (m)
+ str << ',';
+ str << "{name=\"" << module.name
+ << "\",image=\"" << gdbmiStringFormat(module.image)
+ << "\",start=\"" << module.base << "\",end=\""
+ << (module.base + module.size - 1) << '"';
+ if (module.deferred)
+ str << "{deferred=\"true\"";
+ str << '}';
+ if (humanReadable)
+ str << '\n';
+ }
+ str << ']';
+ return str.str();
+}
+
+// Description of a DEBUG_VALUE type field
+const wchar_t *valueType(ULONG type)
+{
+ switch (type) {
+ case DEBUG_VALUE_INT8:
+ return L"I8";
+ case DEBUG_VALUE_INT16:
+ return L"I16";
+ case DEBUG_VALUE_INT32:
+ return L"I32";
+ case DEBUG_VALUE_INT64:
+ return L"I64";
+ case DEBUG_VALUE_FLOAT32:
+ return L"F32";
+ case DEBUG_VALUE_FLOAT64:
+ return L"F64";
+ case DEBUG_VALUE_FLOAT80:
+ return L"F80";
+ case DEBUG_VALUE_FLOAT128:
+ return L"F128";
+ case DEBUG_VALUE_VECTOR64:
+ return L"V64";
+ case DEBUG_VALUE_VECTOR128:
+ return L"V128";
+ }
+ return L"";
+}
+
+// Format a 128bit vector register by adding digits in reverse order
+void formatVectorRegister(std::ostream &str, const unsigned char *array, int size)
+{
+ const char oldFill = str.fill('0');
+
+ str << "0x" << std::hex;
+ for (int i = size - 1; i >= 0; i--) {
+ str.width(2);
+ str << unsigned(array[i]);
+ }
+ str << std::dec;
+
+ str.fill(oldFill);
+}
+
+void formatDebugValue(std::ostream &str, const DEBUG_VALUE &dv, CIDebugControl *ctl)
+{
+ const std::ios::fmtflags savedState = str.flags();
+ switch (dv.Type) {
+ // Do not use showbase to get the hex prefix as this omits it for '0'. Grmpf.
+ case DEBUG_VALUE_INT8:
+ str << std::hex << "0x" << unsigned(dv.I8);
+ break;
+ case DEBUG_VALUE_INT16:
+ str << std::hex << "0x" << dv.I16;
+ break;
+ case DEBUG_VALUE_INT32:
+ str << std::hex << "0x" << dv.I32;
+ break;
+ case DEBUG_VALUE_INT64:
+ str << std::hex << "0x" << dv.I64;
+ break;
+ case DEBUG_VALUE_FLOAT32:
+ str << dv.F32;
+ break;
+ case DEBUG_VALUE_FLOAT64:
+ str << dv.F64;
+ break;
+ case DEBUG_VALUE_FLOAT80:
+ case DEBUG_VALUE_FLOAT128: { // Convert to double
+ DEBUG_VALUE doubleValue;
+ if (ctl && SUCCEEDED(ctl->CoerceValue(const_cast<DEBUG_VALUE*>(&dv), DEBUG_VALUE_FLOAT64, &doubleValue)))
+ str << dv.F64;
+ }
+ break;
+ case DEBUG_VALUE_VECTOR64:
+ formatVectorRegister(str, dv.VI8, 8);
+ break;
+ case DEBUG_VALUE_VECTOR128:
+ formatVectorRegister(str, dv.VI8, 16);
+ break;
+ }
+ str.flags(savedState);
+}
+
+Register::Register() : subRegister(false), pseudoRegister(false)
+{
+ value.Type = DEBUG_VALUE_INT32;
+ value.I32 = 0;
+}
+
+static inline std::wstring registerDescription(const DEBUG_REGISTER_DESCRIPTION &d)
+{
+ std::wostringstream str;
+ str << valueType(d.Type);
+ if (d.Flags & DEBUG_REGISTER_SUB_REGISTER)
+ str << ", sub-register of " << d.SubregMaster;
+ return str.str();
+}
+
+Registers getRegisters(CIDebugRegisters *regs,
+ unsigned flags,
+ std::string *errorMessage)
+{
+ enum { bufSize= 128 };
+ WCHAR buf[bufSize];
+
+ ULONG registerCount = 0;
+ HRESULT hr = regs->GetNumberRegisters(&registerCount);
+ if (FAILED(hr)) {
+ *errorMessage = msgDebugEngineComFailed("GetNumberRegisters", hr);
+ return Registers();
+ }
+ ULONG pseudoRegisterCount = 0;
+ if (flags & IncludePseudoRegisters) {
+ hr = regs->GetNumberPseudoRegisters(&pseudoRegisterCount);
+ if (FAILED(hr)) {
+ *errorMessage = msgDebugEngineComFailed("GetNumberPseudoRegisters", hr);
+ return Registers();
+ }
+ }
+
+ Registers rc;
+ rc.reserve(registerCount + pseudoRegisterCount);
+
+ // Standard registers
+ DEBUG_REGISTER_DESCRIPTION description;
+ DEBUG_VALUE value;
+ for (ULONG r = 0; r < registerCount; r++) {
+ hr = regs->GetDescriptionWide(r, buf, bufSize, NULL, &description);
+ if (FAILED(hr)) {
+ *errorMessage = msgDebugEngineComFailed("GetDescription", hr);
+ return Registers();
+ }
+ hr = regs->GetValue(r, &value);
+ if (FAILED(hr)) {
+ *errorMessage = msgDebugEngineComFailed("GetValue", hr);
+ return Registers();
+ }
+ const bool isSubRegister = (description.Flags & DEBUG_REGISTER_SUB_REGISTER);
+ if (!isSubRegister || (flags & IncludeSubRegisters)) {
+ Register reg;
+ reg.name = buf;
+ reg.description = registerDescription(description);
+ reg.subRegister = isSubRegister;
+ reg.value = value;
+ rc.push_back(reg);
+ }
+ }
+
+ // Pseudo
+ for (ULONG r = 0; r < pseudoRegisterCount; r++) {
+ ULONG type;
+ hr = regs->GetPseudoDescriptionWide(r, buf, bufSize, NULL, NULL, &type);
+ if (FAILED(hr))
+ continue; // Fails for some pseudo registers
+ hr = regs->GetValue(r, &value);
+ if (FAILED(hr))
+ continue; // Fails for some pseudo registers
+ Register reg;
+ reg.pseudoRegister = true;
+ reg.name = buf;
+ reg.description = valueType(type);
+ reg.value = value;
+ rc.push_back(reg);
+ }
+ return rc;
+}
+
+std::string gdbmiRegisters(CIDebugRegisters *regs,
+ CIDebugControl *control,
+ bool humanReadable,
+ unsigned flags,
+ std::string *errorMessage)
+{
+ if (regs == 0 || control == 0) {
+ *errorMessage = "Required interfaces missing for registers dump.";
+ return std::string();
+ }
+
+ const Registers registers = getRegisters(regs, flags, errorMessage);
+ if (registers.empty())
+ return std::string();
+
+ std::ostringstream str;
+ str << '[';
+ if (humanReadable)
+ str << '\n';
+ const Registers::size_type size = registers.size();
+ for (Registers::size_type r = 0; r < size; r++) {
+ const Register &reg = registers.at(r);
+ if (r)
+ str << ',';
+ str << "{number=\"" << r << "\",name=\"" << gdbmiWStringFormat(reg.name) << '"';
+ if (!reg.description.empty())
+ str << ",description=\"" << gdbmiWStringFormat(reg.description) << '"';
+ if (reg.subRegister)
+ str << ",subregister=\"true\"";
+ if (reg.pseudoRegister)
+ str << ",pseudoregister=\"true\"";
+ str << ",value=\"";
+ formatDebugValue(str, reg.value, control);
+ str << "\"}";
+ if (humanReadable)
+ str << '\n';
+ }
+ str << ']';
+ if (humanReadable)
+ str << '\n';
+ return str.str();
+}
+
+std::string memoryToBase64(CIDebugDataSpaces *ds, ULONG64 address, ULONG length, std::string *errorMessage)
+{
+ unsigned char *buffer = new unsigned char[length];
+ std::fill(buffer, buffer + length, 0);
+ ULONG received = 0;
+ const HRESULT hr = ds->ReadVirtual(address, buffer, length, &received);
+ if (FAILED(hr)) {
+ delete [] buffer;
+ std::ostringstream estr;
+ estr << "Cannot read " << length << " bytes from " << address << ": "
+ << msgDebugEngineComFailed("ReadVirtual", hr);
+ *errorMessage = estr.str();
+ return std::string();
+ }
+ if (received < length) {
+ std::ostringstream estr;
+ estr << "Warning: Received only " << received << " bytes of " << length << " requested at " << address << '.';
+ *errorMessage = estr.str();
+ }
+
+ std::ostringstream str;
+ base64Encode(str, buffer, length);
+ delete [] buffer;
+ return str.str();
+}
+
+// Format stack as GDBMI
+static StackFrames getStackTrace(CIDebugControl *debugControl,
+ CIDebugSymbols *debugSymbols,
+ unsigned maxFrames,
+ std::string *errorMessage)
+{
+
+ if (!maxFrames)
+ return StackFrames();
+ DEBUG_STACK_FRAME *frames = new DEBUG_STACK_FRAME[maxFrames];
+ ULONG frameCount = 0;
+ const HRESULT hr = debugControl->GetStackTrace(0, 0, 0, frames, maxFrames, &frameCount);
+ if (FAILED(hr)) {
+ delete [] frames;
+ *errorMessage = msgDebugEngineComFailed("GetStackTrace", hr);
+ }
+ StackFrames rc(frameCount, StackFrame());
+ for (ULONG f = 0; f < frameCount; f++)
+ getFrame(debugSymbols, frames[f], &(rc[f]));
+ delete [] frames;
+ return rc;
+}
+
+std::string gdbmiStack(CIDebugControl *debugControl,
+ CIDebugSymbols *debugSymbols,
+ unsigned maxFrames,
+ bool humanReadable, std::string *errorMessage)
+{
+ const StackFrames frames = getStackTrace(debugControl, debugSymbols,
+ maxFrames, errorMessage);
+ if (frames.empty() && maxFrames > 0)
+ return std::string();
+
+ std::ostringstream str;
+ str << '[';
+ const StackFrames::size_type size = frames.size();
+ for (StackFrames::size_type i = 0; i < size; i++) {
+ if (i)
+ str << ',';
+ frames.at(i).formatGDBMI(str, (int)i);
+ if (humanReadable)
+ str << '\n';
+ }
+ str << ']';
+ return str.str();
+}
diff --git a/src/libs/qtcreatorcdbext/gdbmihelpers.h b/src/libs/qtcreatorcdbext/gdbmihelpers.h
new file mode 100644
index 0000000000..19e1a59321
--- /dev/null
+++ b/src/libs/qtcreatorcdbext/gdbmihelpers.h
@@ -0,0 +1,158 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 THREADLIST_H
+#define THREADLIST_H
+
+#include "common.h"
+#include <vector>
+
+/* Various helpers to the extension commands to retrieve debuggee information
+ * in suitable formats for the debugger engine. */
+
+/* Helpers to retrieve threads and their top stack frame
+ * in one roundtrip, conveniently in GDBMI format. */
+
+struct StackFrame
+{
+ StackFrame(ULONG64 a = 0);
+ void formatGDBMI(std::ostream &str, unsigned level = 0) const;
+ std::wstring fileName() const;
+
+ ULONG64 address;
+ std::wstring function;
+ std::wstring fullPathName;
+ ULONG line;
+};
+
+typedef std::vector<StackFrame> StackFrames;
+
+bool getFrame(unsigned n, StackFrame *f, std::string *errorMessage);
+bool getFrame(CIDebugSymbols *debugSymbols, CIDebugControl *debugControl,
+ unsigned n, StackFrame *f, std::string *errorMessage);
+
+struct Thread
+{
+ Thread(ULONG i = 0, ULONG sysId = 0);
+ void formatGDBMI(std::ostream &str) const;
+
+ ULONG id;
+ ULONG systemId;
+ ULONG64 address;
+ std::string state;
+ std::wstring name;
+ StackFrame frame;
+};
+
+typedef std::vector<Thread> Threads;
+
+// Get list of threads.
+bool threadList(CIDebugSystemObjects *debugSystemObjects,
+ CIDebugSymbols *debugSymbols,
+ CIDebugControl *debugControl,
+ CIDebugAdvanced *debugAdvanced,
+ Threads* threads, ULONG *currentThreadId,
+ std::string *errorMessage);
+
+// Convenience formatting as GDBMI
+std::string gdbmiThreadList(CIDebugSystemObjects *debugSystemObjects,
+ CIDebugSymbols *debugSymbols,
+ CIDebugControl *debugControl,
+ CIDebugAdvanced *debugAdvanced,
+ std::string *errorMessage);
+
+/* Helpers for retrieving module lists */
+
+struct Module {
+ Module();
+
+ std::string name;
+ std::string image;
+ bool deferred;
+ ULONG64 base;
+ ULONG64 size;
+};
+
+typedef std::vector<Module> Modules;
+
+// Retrieve modules info
+Modules getModules(CIDebugSymbols *syms, std::string *errorMessage);
+
+// Format modules as GDBMI
+std::string gdbmiModules(CIDebugSymbols *syms, bool humanReadable, std::string *errorMessage);
+
+/* Helpers for registers */
+struct Register
+{
+ Register();
+
+ std::wstring name;
+ std::wstring description;
+ bool subRegister;
+ bool pseudoRegister;
+ DEBUG_VALUE value;
+};
+
+typedef std::vector<Register> Registers;
+
+// Description of a DEBUG_VALUE type field
+const wchar_t *valueType(ULONG type);
+// Helper to format a DEBUG_VALUE
+void formatDebugValue(std::ostream &str, const DEBUG_VALUE &dv, CIDebugControl *ctl = 0);
+
+enum RegisterFlags {
+ IncludePseudoRegisters = 0x1,
+ IncludeSubRegisters = 0x2
+};
+
+// Retrieve current register snapshot using RegisterFlags
+Registers getRegisters(CIDebugRegisters *regs,
+ unsigned flags,
+ std::string *errorMessage);
+
+// Format current register snapshot using RegisterFlags as GDBMI
+// This is not exactly using the actual GDB formatting as this is
+// to verbose (names and values separated)
+std::string gdbmiRegisters(CIDebugRegisters *regs,
+ CIDebugControl *control,
+ bool humanReadable,
+ unsigned flags,
+ std::string *errorMessage);
+
+std::string memoryToBase64(CIDebugDataSpaces *ds, ULONG64 address, ULONG length, std::string *errorMessage);
+
+// Stack helpers
+StackFrames getStackTrace(CIDebugControl *debugControl, CIDebugSymbols *debugSymbols,
+ unsigned maxFrames, std::string *errorMessage);
+
+std::string gdbmiStack(CIDebugControl *debugControl, CIDebugSymbols *debugSymbols,
+ unsigned maxFrames, bool humanReadable,
+ std::string *errorMessage);
+
+#endif // THREADLIST_H
diff --git a/src/libs/qtcreatorcdbext/iinterfacepointer.h b/src/libs/qtcreatorcdbext/iinterfacepointer.h
new file mode 100644
index 0000000000..558d27b2dc
--- /dev/null
+++ b/src/libs/qtcreatorcdbext/iinterfacepointer.h
@@ -0,0 +1,88 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 IINTERFACEPOINTER_H
+#define IINTERFACEPOINTER_H
+
+#include "common.h"
+
+/* AutoPtr for a IDebugInterface */
+template <class IInterface>
+class IInterfacePointer
+{
+ explicit IInterfacePointer(const IInterfacePointer&);
+ IInterfacePointer& operator=(const IInterfacePointer&);
+
+public:
+ inline IInterfacePointer() : m_instance(0), m_hr(S_OK) {}
+
+ // IDebugClient4 does not inherit IDebugClient.
+ inline explicit IInterfacePointer(IDebugClient *client) : m_instance(0), m_hr(S_OK) { create(client); }
+ inline explicit IInterfacePointer(CIDebugClient *client) : m_instance(0), m_hr(S_OK) { create(client); }
+ inline ~IInterfacePointer() { release(); }
+
+ inline IInterface *operator->() const { return m_instance; }
+ inline IInterface *data() const { return m_instance; }
+ inline bool isNull() const { return m_instance == 0; }
+ inline operator bool() const { return !isNull(); }
+ inline HRESULT hr() const { return m_hr; }
+
+ // This is for creating a IDebugClient from scratch. Not matches by a constructor,
+ // unfortunately
+ inline bool create() {
+ release();
+ m_hr = DebugCreate(__uuidof(IInterface), (void **)&m_instance);
+ return m_hr == S_OK;
+ }
+
+ inline bool create(IDebugClient *client) {
+ release();
+ m_hr = client->QueryInterface(__uuidof(IInterface), (void **)&m_instance);
+ return m_hr == S_OK;
+ }
+ inline bool create(CIDebugClient *client) {
+ release();
+ m_hr = client->QueryInterface(__uuidof(IInterface), (void **)&m_instance);
+ return m_hr == S_OK;
+ }
+
+
+private:
+ void release() {
+ if (m_instance) {
+ m_instance->Release();
+ m_instance = 0;
+ m_hr = S_OK;
+ }
+ }
+ IInterface *m_instance;
+ HRESULT m_hr;
+};
+
+#endif // IINTERFACEPOINTER_H
diff --git a/src/libs/qtcreatorcdbext/knowntype.h b/src/libs/qtcreatorcdbext/knowntype.h
new file mode 100644
index 0000000000..6736cd508b
--- /dev/null
+++ b/src/libs/qtcreatorcdbext/knowntype.h
@@ -0,0 +1,158 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 KNOWNTYPE_H
+#define KNOWNTYPE_H
+
+// Helpers for detecting types
+enum KnownType
+{
+ KT_Unknown =0,
+ KT_Qt_Type = 0x10000,
+ KT_Qt_PrimitiveType = 0x20000,
+ KT_Qt_MovableType = 0x40000,
+ KT_STL_Type = 0x80000,
+ KT_ContainerType = 0x100000,
+ KT_HasSimpleDumper = 0x200000,
+ // Qt Basic
+ KT_QChar = KT_Qt_Type + KT_Qt_MovableType + KT_HasSimpleDumper + 1,
+ KT_QByteArray = KT_Qt_Type + KT_Qt_MovableType + KT_HasSimpleDumper + 2,
+ KT_QString = KT_Qt_Type + KT_Qt_MovableType + KT_HasSimpleDumper + 3,
+ KT_QColor = KT_Qt_Type + KT_HasSimpleDumper + 4,
+ KT_QFlags = KT_Qt_Type + KT_HasSimpleDumper + 5,
+ KT_QDate = KT_Qt_Type + KT_Qt_MovableType + KT_HasSimpleDumper + 6,
+ KT_QTime = KT_Qt_Type + KT_Qt_MovableType + KT_HasSimpleDumper + 7,
+ KT_QPoint = KT_Qt_Type + KT_Qt_MovableType + KT_HasSimpleDumper + 8,
+ KT_QPointF = KT_Qt_Type +KT_Qt_MovableType + KT_HasSimpleDumper + 9,
+ KT_QSize = KT_Qt_Type + KT_Qt_MovableType + KT_HasSimpleDumper + 11,
+ KT_QSizeF = KT_Qt_Type + KT_Qt_MovableType + KT_HasSimpleDumper + 12,
+ KT_QLine = KT_Qt_Type + KT_Qt_MovableType + KT_HasSimpleDumper + 13,
+ KT_QLineF = KT_Qt_Type + KT_Qt_MovableType + KT_HasSimpleDumper + 14,
+ KT_QRect = KT_Qt_Type + KT_Qt_MovableType + KT_HasSimpleDumper + 15,
+ KT_QRectF = KT_Qt_Type + KT_Qt_MovableType + KT_HasSimpleDumper + 16,
+ KT_QVariant = KT_Qt_Type + KT_Qt_MovableType + KT_HasSimpleDumper + 17,
+ KT_QBasicAtomicInt = KT_Qt_Type + KT_HasSimpleDumper + 18,
+ KT_QAtomicInt = KT_Qt_Type + KT_HasSimpleDumper + 19,
+ KT_QObject = KT_Qt_Type + KT_HasSimpleDumper + 20,
+ KT_QWidget = KT_Qt_Type + KT_HasSimpleDumper + 21,
+ // Various QT movable types
+ KT_QPen = KT_Qt_Type + KT_Qt_MovableType + 30,
+ KT_QUrl = KT_Qt_Type + KT_Qt_MovableType + 31,
+ KT_QIcon = KT_Qt_Type + KT_Qt_MovableType + 32,
+ KT_QBrush = KT_Qt_Type + KT_Qt_MovableType + 33,
+ KT_QImage = KT_Qt_Type + KT_Qt_MovableType + 35,
+ KT_QLocale = KT_Qt_Type + KT_Qt_MovableType + 36,
+ KT_QMatrix = KT_Qt_Type + KT_Qt_MovableType + 37,
+ KT_QRegExp = KT_Qt_Type + KT_Qt_MovableType + 38,
+ KT_QMargins = KT_Qt_Type + KT_Qt_MovableType + 39,
+ KT_QXmltem = KT_Qt_Type + KT_Qt_MovableType + 40,
+ KT_QXmlName = KT_Qt_Type + KT_Qt_MovableType + 41,
+ KT_QBitArray = KT_Qt_Type + KT_Qt_MovableType + 42,
+ KT_QDateTime = KT_Qt_Type + KT_Qt_MovableType + 43,
+ KT_QFileInfo = KT_Qt_Type + KT_Qt_MovableType + 44,
+ KT_QMetaEnum = KT_Qt_Type + KT_Qt_MovableType + 45,
+ KT_QVector2D = KT_Qt_Type + KT_Qt_MovableType + 46,
+ KT_QVector3D = KT_Qt_Type + KT_Qt_MovableType + 47,
+ KT_QVector4D = KT_Qt_Type + KT_Qt_MovableType + 48,
+ KT_QMatrix4x4 = KT_Qt_Type + KT_Qt_MovableType + 49,
+ KT_QTextBlock = KT_Qt_Type + KT_Qt_MovableType + 50,
+ KT_QTransform = KT_Qt_Type + KT_Qt_MovableType + 51,
+ KT_QBasicTimer = KT_Qt_Type + KT_Qt_MovableType + 52,
+ KT_QMetaMethod = KT_Qt_Type + KT_Qt_MovableType + 53,
+ KT_QModelIndex = KT_Qt_Type + KT_Qt_MovableType + 54,
+ KT_QQuaternion = KT_Qt_Type + KT_Qt_MovableType + 55,
+ KT_QScriptItem = KT_Qt_Type + KT_Qt_MovableType + 56,
+ KT_QKeySequence = KT_Qt_Type + KT_Qt_MovableType + 57,
+ KT_QTextFragment = KT_Qt_Type + KT_Qt_MovableType + 58,
+ KT_QTreeViewItem = KT_Qt_Type + KT_Qt_MovableType + 59,
+ KT_QMetaClassInfo = KT_Qt_Type + KT_Qt_MovableType + 60,
+ KT_QNetworkCookie = KT_Qt_Type + KT_Qt_MovableType + 61,
+ KT_QHashDummyValue = KT_Qt_Type + KT_Qt_MovableType + 62,
+ KT_QSourceLocation = KT_Qt_Type + KT_Qt_MovableType + 63,
+ KT_QNetworkProxyQuery = KT_Qt_Type + KT_Qt_MovableType + 64,
+ KT_QXmlNodeModelIndex = KT_Qt_Type + KT_Qt_MovableType + 65,
+ KT_QItemSelectionRange = KT_Qt_Type + KT_Qt_MovableType + 66,
+ KT_QPaintBufferCommand = KT_Qt_Type + KT_Qt_MovableType + 67,
+ KT_QTextHtmlParserNode = KT_Qt_Type + KT_Qt_MovableType + 68,
+ KT_QXmlStreamAttribute = KT_Qt_Type + KT_Qt_MovableType + 69,
+ KT_QTextBlock_iterator = KT_Qt_Type + KT_Qt_MovableType + 70,
+ KT_QTextFrame_iterator = KT_Qt_Type + KT_Qt_MovableType + 71,
+ KT_QPersistentModelIndex = KT_Qt_Type + KT_Qt_MovableType + 72,
+ KT_QObjectPrivate_Sender = KT_Qt_Type + KT_Qt_MovableType + 73,
+ KT_QPatternist_AtomicValue = KT_Qt_Type + KT_Qt_MovableType + 74,
+ KT_QPatternist_Cardinality = KT_Qt_Type + KT_Qt_MovableType + 75,
+ KT_QObjectPrivate_Connection = KT_Qt_Type + KT_Qt_MovableType + 76,
+ KT_QPatternist_ItemCacheCell = KT_Qt_Type + KT_Qt_MovableType + 77,
+ KT_QPatternist_ItemType_Ptr = KT_Qt_Type + KT_Qt_MovableType + 78,
+ KT_QPatternist_NamePool_Ptr = KT_Qt_Type + KT_Qt_MovableType + 79,
+ KT_QXmlStreamEntityDeclaration = KT_Qt_Type + KT_Qt_MovableType + 80,
+ KT_QPatternist_Expression_Ptr = KT_Qt_Type + KT_Qt_MovableType + 81,
+ KT_QXmlStreamNotationDeclaration = KT_Qt_Type + KT_Qt_MovableType + 82,
+ KT_QPatternist_SequenceType_Ptr = KT_Qt_Type + KT_Qt_MovableType + 83,
+ KT_QXmlStreamNamespaceDeclaration = KT_Qt_Type + KT_Qt_MovableType + 84,
+ KT_QPatternist_Item_Iterator_Ptr = KT_Qt_Type + KT_Qt_MovableType + 85,
+ KT_QPatternist_ItemSequenceCacheCell = KT_Qt_Type + KT_Qt_MovableType + 86,
+ KT_QNetworkHeadersPrivate_RawHeaderPair = KT_Qt_Type + KT_Qt_MovableType + 87,
+ KT_QPatternist_AccelTree_BasicNodeData = KT_Qt_Type + KT_Qt_MovableType + 88,
+ // Qt primitive types
+ KT_QFixed = KT_Qt_Type + KT_Qt_PrimitiveType + 90,
+ KT_QTextItem = KT_Qt_Type + KT_Qt_PrimitiveType + 91,
+ KT_QFixedSize = KT_Qt_Type + KT_Qt_PrimitiveType + 92,
+ KT_QFixedPoint = KT_Qt_Type + KT_Qt_PrimitiveType + 93,
+ KT_QScriptLine = KT_Qt_Type + KT_Qt_PrimitiveType + 94,
+ KT_QScriptAnalysis = KT_Qt_Type + KT_Qt_PrimitiveType + 95,
+ KT_QTextUndoCommand = KT_Qt_Type + KT_Qt_PrimitiveType + 96,
+ KT_QGlyphJustification = KT_Qt_Type + KT_Qt_PrimitiveType + 97,
+ KT_QPainterPath_Element = KT_Qt_Type + KT_Qt_PrimitiveType + 98,
+ // Qt Containers
+ KT_QStringList = KT_Qt_Type + KT_ContainerType + KT_HasSimpleDumper + 1,
+ KT_QList = KT_Qt_Type + KT_ContainerType + KT_HasSimpleDumper + 2,
+ KT_QLinkedList = KT_Qt_Type + KT_ContainerType + KT_HasSimpleDumper + 3,
+ KT_QVector = KT_Qt_Type + KT_ContainerType + KT_HasSimpleDumper + 4,
+ KT_QStack = KT_Qt_Type + KT_ContainerType + KT_HasSimpleDumper + 5,
+ KT_QQueue = KT_Qt_Type + KT_ContainerType + KT_HasSimpleDumper + 6,
+ KT_QSet = KT_Qt_Type + KT_ContainerType + KT_HasSimpleDumper + 7,
+ KT_QHash = KT_Qt_Type + KT_ContainerType + KT_HasSimpleDumper + 8,
+ KT_QMultiHash = KT_Qt_Type + KT_ContainerType + KT_HasSimpleDumper + 9,
+ KT_QMap = KT_Qt_Type + KT_ContainerType + KT_HasSimpleDumper + 10,
+ KT_QMultiMap = KT_Qt_Type + KT_ContainerType + KT_HasSimpleDumper + 11,
+ // STL
+ KT_StdString = KT_STL_Type + KT_HasSimpleDumper + 1,
+ KT_StdWString = KT_STL_Type + KT_HasSimpleDumper + 2,
+ // STL containers
+ KT_StdVector = KT_STL_Type + KT_ContainerType + KT_HasSimpleDumper + 1,
+ KT_StdList = KT_STL_Type + KT_ContainerType + KT_HasSimpleDumper + 2,
+ KT_StdStack = KT_STL_Type + KT_ContainerType + KT_HasSimpleDumper + 3,
+ KT_StdDeque = KT_STL_Type + KT_ContainerType + KT_HasSimpleDumper + 4,
+ KT_StdSet = KT_STL_Type + KT_ContainerType + KT_HasSimpleDumper + 5,
+ KT_StdMap = KT_STL_Type + KT_ContainerType + KT_HasSimpleDumper + 6,
+ KT_StdMultiMap = KT_STL_Type + KT_ContainerType + KT_HasSimpleDumper + 7,
+};
+
+#endif // KNOWNTYPE_H
diff --git a/src/libs/qtcreatorcdbext/outputcallback.cpp b/src/libs/qtcreatorcdbext/outputcallback.cpp
new file mode 100644
index 0000000000..026d2ab3a1
--- /dev/null
+++ b/src/libs/qtcreatorcdbext/outputcallback.cpp
@@ -0,0 +1,98 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "outputcallback.h"
+#include "stringutils.h"
+#include "extensioncontext.h"
+#include "base64.h"
+
+#include <cstring>
+
+OutputCallback::OutputCallback(IDebugOutputCallbacksWide *wrapped) : m_wrapped(wrapped)
+{
+}
+
+OutputCallback::~OutputCallback() // must be present to avoid exit crashes
+{
+}
+
+STDMETHODIMP OutputCallback::QueryInterface(
+ THIS_
+ IN REFIID InterfaceId,
+ OUT PVOID* Interface
+ )
+{
+ *Interface = NULL;
+
+ if (IsEqualIID(InterfaceId, __uuidof(IUnknown)) ||
+ IsEqualIID(InterfaceId, __uuidof(IDebugOutputCallbacksWide)))
+ {
+ *Interface = (IDebugOutputCallbacksWide*)this;
+ AddRef();
+ return S_OK;
+ } else {
+ return E_NOINTERFACE;
+ }
+}
+
+STDMETHODIMP_(ULONG) OutputCallback::AddRef(THIS)
+{
+ // This class is designed to be static so
+ // there's no true refcount.
+ return 1;
+}
+
+STDMETHODIMP_(ULONG) OutputCallback::Release(THIS)
+{
+ // This class is designed to be static so
+ // there's no true refcount.
+ return 0;
+}
+
+STDMETHODIMP OutputCallback::Output(
+ THIS_
+ IN ULONG mask,
+ IN PCWSTR text
+ )
+{
+ // Do not unconditionally output ourselves here, as this causes an endless
+ // recursion. Suppress prompts (note that sequences of prompts may mess parsing up)
+ if (!m_wrapped || mask == DEBUG_OUTPUT_PROMPT)
+ return S_OK;
+ // Wrap debuggee output in gdbmi such that creator recognizes it
+ if (mask != DEBUG_OUTPUT_DEBUGGEE) {
+ m_wrapped->Output(mask, text);
+ return S_OK;
+ }
+ // Base encode as GDBMI is not really made for wide chars
+ std::ostringstream str;
+ base64Encode(str, reinterpret_cast<const unsigned char *>(text), sizeof(wchar_t) * std::wcslen(text));
+ ExtensionContext::instance().report('E', 0, "debuggee_output", str.str().c_str());
+ return S_OK;
+}
diff --git a/src/libs/qtcreatorcdbext/outputcallback.h b/src/libs/qtcreatorcdbext/outputcallback.h
new file mode 100644
index 0000000000..76f73ad3c4
--- /dev/null
+++ b/src/libs/qtcreatorcdbext/outputcallback.h
@@ -0,0 +1,64 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 DEBUGEVENTOUTPUT_H
+#define DEBUGEVENTOUTPUT_H
+
+#include "common.h"
+
+class OutputCallback : public IDebugOutputCallbacksWide
+{
+public:
+ explicit OutputCallback(IDebugOutputCallbacksWide *wrapped);
+ virtual ~OutputCallback();
+ // IUnknown.
+ STDMETHOD(QueryInterface)(
+ THIS_
+ IN REFIID InterfaceId,
+ OUT PVOID* Interface
+ );
+ STDMETHOD_(ULONG, AddRef)(
+ THIS
+ );
+ STDMETHOD_(ULONG, Release)(
+ THIS
+ );
+
+ // IDebugOutputCallbacks.
+ STDMETHOD(Output)(
+ THIS_
+ IN ULONG mask,
+ IN PCWSTR text
+ );
+
+private:
+ IDebugOutputCallbacksWide *m_wrapped;
+};
+
+#endif // DEBUGEVENTOUTPUT_H
diff --git a/src/libs/qtcreatorcdbext/qtcreatorcdbext.def b/src/libs/qtcreatorcdbext/qtcreatorcdbext.def
new file mode 100644
index 0000000000..6bd14850ed
--- /dev/null
+++ b/src/libs/qtcreatorcdbext/qtcreatorcdbext.def
@@ -0,0 +1,20 @@
+EXPORTS
+DebugExtensionInitialize
+DebugExtensionUninitialize
+DebugExtensionNotify
+pid
+expandlocals
+locals
+dumplocal
+typecast
+addsymbol
+assign
+threads
+registers
+modules
+idle
+help
+memory
+shutdownex
+stack
+KnownStructOutput
diff --git a/src/libs/qtcreatorcdbext/qtcreatorcdbext.pro b/src/libs/qtcreatorcdbext/qtcreatorcdbext.pro
new file mode 100644
index 0000000000..5012a427d3
--- /dev/null
+++ b/src/libs/qtcreatorcdbext/qtcreatorcdbext.pro
@@ -0,0 +1,14 @@
+TEMPLATE = subdirs
+
+# Build the Qt Creator CDB extension depending on whether
+# CDB is actually detected.
+# In order to do detection and building in one folder,
+# use a subdir profile in '.'.
+
+include(cdb_detect.pri)
+
+!isEmpty(CDB_PATH) {
+ SUBDIRS += lib_qtcreator_cdbext
+
+ lib_qtcreator_cdbext.file = qtcreatorcdbext_build.pro
+}
diff --git a/src/libs/qtcreatorcdbext/qtcreatorcdbext_build.pro b/src/libs/qtcreatorcdbext/qtcreatorcdbext_build.pro
new file mode 100644
index 0000000000..eab2af0e99
--- /dev/null
+++ b/src/libs/qtcreatorcdbext/qtcreatorcdbext_build.pro
@@ -0,0 +1,73 @@
+# Build the Qt Creator CDB extension
+TEMPLATE = lib
+
+include(../../../qtcreator.pri)
+include(cdb_detect.pri)
+
+CONFIG -= precompile_header
+CONFIG += hide_symbols
+
+# Switch to statically linked CRT. Note: There will be only one
+# global state of the CRT, reconsider if other DLLs are required!
+# TODO: No effect, currently?
+QMAKE_CXXFLAGS_RELEASE -= -MD
+QMAKE_CXXFLAGS_DEBUG -= -MDd
+QMAKE_CXXFLAGS_RELEASE += -MT
+QMAKE_CXXFLAGS_DEBUG += -MTd
+
+BASENAME=qtcreatorcdbext
+
+DEF_FILE=$$PWD/qtcreatorcdbext.def
+
+IDE_BASE_PATH=$$dirname(IDE_APP_PATH)
+
+# Find out 64/32bit and determine target directories accordingly.
+# TODO: This is an ugly hack. Better check compiler (stderr) or something?
+ENV_LIB_PATH=$$(LIBPATH)
+
+
+contains(ENV_LIB_PATH, ^.*amd64.*$) {
+ DESTDIR=$$IDE_BASE_PATH/lib/$${BASENAME}64
+ CDB_PLATFORM=amd64
+} else {
+ DESTDIR=$$IDE_BASE_PATH/lib/$${BASENAME}32
+ CDB_PLATFORM=i386
+}
+
+TARGET = $$BASENAME
+
+message("Compiling Qt Creator CDB extension $$TARGET $$DESTDIR for $$CDB_PLATFORM using $$CDB_PATH")
+
+INCLUDEPATH += $$CDB_PATH/inc
+LIBS+= -L$$CDB_PATH/lib/$$CDB_PLATFORM -ldbgeng
+
+CONFIG -= qt
+QT -= gui
+QT -= core
+
+SOURCES += qtcreatorcdbextension.cpp \
+ extensioncontext.cpp \
+ eventcallback.cpp \
+ symbolgroupnode.cpp \
+ symbolgroup.cpp \
+ common.cpp \
+ stringutils.cpp \
+ gdbmihelpers.cpp \
+ outputcallback.cpp \
+ base64.cpp \
+ symbolgroupvalue.cpp \
+ containers.cpp
+
+HEADERS += extensioncontext.h \
+ common.h \
+ iinterfacepointer.h \
+ eventcallback.h \
+ symbolgroup.h \
+ stringutils.h \
+ gdbmihelpers.h \
+ outputcallback.h \
+ base64.h \
+ symbolgroupvalue.h \
+ containers.h \
+ knowntype.h \
+ symbolgroupnode.h
diff --git a/src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp b/src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp
new file mode 100644
index 0000000000..ecfcc9e76c
--- /dev/null
+++ b/src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp
@@ -0,0 +1,723 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "extensioncontext.h"
+#include "outputcallback.h"
+#include "eventcallback.h"
+#include "symbolgroup.h"
+#include "symbolgroupvalue.h"
+#include "stringutils.h"
+#include "gdbmihelpers.h"
+
+#include <cstdio>
+#include <sstream>
+#include <list>
+#include <iterator>
+
+/* QtCreatorCDB ext is an extension loaded into CDB.exe (see cdbengine2.cpp):
+ * - Notification about the state of the debugging session:
+ * + idle: (hooked with .idle_cmd) debuggee stopped
+ * + accessible: Debuggee stopped, cdb.exe accepts commands
+ * + inaccessible: Debuggee runs, no way to post commands
+ * + session active/inactive: Lost debuggee, terminating.
+ * - Hook up with output/event callbacks and produce formatted output
+ * - Provide some extension commands that produce output in a standardized (GDBMI)
+ * format that ends up in handleExtensionMessage().
+ */
+
+// Data struct and helpers for formatting help
+struct CommandDescription {
+ const char *name;
+ const char *description;
+ const char *usage;
+};
+
+// Single line of usage: For reporting usage errors back as a single line
+static std::string singleLineUsage(const CommandDescription &d)
+{
+ std::string rc = "Usage: ";
+ const char *endOfLine = strchr(d.usage, '\n');
+ rc += endOfLine ? std::string(d.usage, endOfLine - d.usage) : std::string(d.usage);
+ return rc;
+}
+
+// Format description of a command
+std::ostream &operator<<(std::ostream &str, const CommandDescription &d)
+{
+ str << "Command '" << d.name << "': " << d.description << '\n';
+ if (d.usage[0])
+ str << "Usage: " << d.name << ' ' << d.usage << '\n';
+ str << '\n';
+ return str;
+}
+
+enum Command {
+ CmdPid,
+ CmdExpandlocals,
+ CmdLocals,
+ CmdDumplocal,
+ CmdTypecast,
+ CmdAddsymbol,
+ CmdAssign,
+ CmdThreads,
+ CmdRegisters,
+ CmdModules,
+ CmdIdle,
+ CmdHelp,
+ CmdMemory,
+ CmdStack,
+ CmdShutdownex
+};
+
+static const CommandDescription commandDescriptions[] = {
+{"pid",
+ "Prints inferior process id and hooks up output callbacks.",
+ "[-t token]"},
+{"expandlocals", "Expands local variables by iname in symbol group.",
+ "[-t token] [-c] <frame-number> <iname1-list>\n"
+ "iname1-list: Comma-separated list of inames\n"
+ "-c complex dumpers"},
+{"locals",
+ "Prints local variables of symbol group in GDBMI or debug format",
+ "[-t token] [T formats] [-I formats] [-c] [-h] [-d] [-e expand-list] [-u uninitialized-list]\n<frame-number> [iname]\n"
+ "-h human-readable ouput\n"
+ "-d debug output\n"
+ "-c complex dumpers\n"
+ "-e expand-list Comma-separated list of inames to be expanded beforehand\n"
+ "-u uninitialized-list Comma-separated list of uninitialized inames\n"
+ "-I formatmap map of 'hex-encoded-iname=typecode'\n"
+ "-T formatmap map of 'hex-encoded-type-name=typecode'"},
+{"dumplocal", "Dumps local variable using simple dumpers (testing command).",
+ "[-t token] <frame-number> <iname>"},
+{"typecast","Performs a type cast on an unexpanded iname of symbol group.",
+ "[-t token] <frame-number> <iname> <desired-type>"},
+{"addsymbol","Adds a symbol to symbol group (testing command).",
+ "[-t token] <frame-number> <name-expression> [optional-iname]"},
+{"assign","Assigns a value to a variable in current symbol group.",
+ "[-t token] <iname=value>"},
+{"threads","Lists threads in GDBMI format.","[-t token]"},
+{"registers","Lists registers in GDBMI format","[-t token]"},
+{"modules","Lists modules in GDBMI format.","[-t token]"},
+{"idle",
+ "Reports stop reason in GDBMI format.\n"
+ "Intended to be used with .idle_cmd to obtain proper stop notification.",""},
+{"help","Prints help.",""},
+{"memory","Prints memory contents in Base64 encoding.","[-t token] <address> <length>"},
+{"stack","Prints stack in GDBMI format.","[-t token] [max-frames]"},
+{"shutdownex","Unhooks output callbacks.\nNeeds to be called explicitly only in case of remote debugging.",""}
+};
+
+typedef std::vector<std::string> StringVector;
+typedef std::list<std::string> StringList;
+
+// Helper for commandTokens() below:
+// Simple splitting of command lines allowing for '"'-quoted tokens
+// 'typecast local.i "class QString *"' -> ('typecast','local.i','class QString *')
+template<class Inserter>
+static inline void splitCommand(PCSTR args, Inserter it)
+{
+ enum State { WhiteSpace, WithinToken, WithinQuoted };
+
+ State state = WhiteSpace;
+ std::string current;
+ for (PCSTR p = args; *p; p++) {
+ char c = *p;
+ switch (state) {
+ case WhiteSpace:
+ switch (c) {
+ case ' ':
+ break;
+ case '"':
+ state = WithinQuoted;
+ current.clear();
+ break;
+ default:
+ state = WithinToken;
+ current.clear();
+ current.push_back(c);
+ break;
+ }
+ break;
+ case WithinToken:
+ switch (c) {
+ case ' ':
+ state = WhiteSpace;
+ *it = current;
+ ++it;
+ break;
+ default:
+ current.push_back(c);
+ break;
+ }
+ break;
+ case WithinQuoted:
+ switch (c) {
+ case '"':
+ state = WhiteSpace;
+ *it = current;
+ ++it;
+ break;
+ default:
+ current.push_back(c);
+ break;
+ }
+ break;
+ }
+ }
+ if (state == WithinToken) {
+ *it = current;
+ ++it;
+ }
+}
+
+// Split & Parse the arguments of a command and extract the
+// optional first integer token argument ('command -t <number> remaining arguments')
+// Each command takes the 'token' argument and includes it in its output
+// so that the calling CDB engine in Qt Creator can match the callback.
+
+template<class StringContainer>
+static inline StringContainer commandTokens(PCSTR args, int *token = 0)
+{
+ typedef StringContainer::iterator ContainerIterator;
+
+ if (token)
+ *token = -1; // Handled as 'display' in engine, so that user can type commands
+ StringContainer tokens;
+ splitCommand(args, std::back_inserter(tokens));
+ // Check for token
+ ContainerIterator it = tokens.begin();
+ if (it != tokens.end() && *it == "-t" && ++it != tokens.end()) {
+ if (token)
+ std::istringstream(*it) >> *token;
+ tokens.erase(tokens.begin(), ++it);
+ }
+ return tokens;
+}
+
+// Extension command 'pid':
+// Report back PID so that Qt Creator engine knows whom to DebugBreakProcess.
+extern "C" HRESULT CALLBACK pid(CIDebugClient *client, PCSTR args)
+{
+ ExtensionContext::instance().hookCallbacks(client);
+
+ int token;
+ commandTokens<StringList>(args, &token);
+
+ if (const ULONG pid = currentProcessId(client)) {
+ ExtensionContext::instance().report('R', token, "pid", "%u", pid);
+ } else {
+ ExtensionContext::instance().report('N', token, "pid", "0");
+ }
+ return S_OK;
+}
+
+// Extension command 'expandlocals':
+// Expand a comma-separated iname-list of local variables.
+
+extern "C" HRESULT CALLBACK expandlocals(CIDebugClient *client, PCSTR args)
+{
+ ExtensionCommandContext exc(client);
+ unsigned frame = 0;
+ SymbolGroup *symGroup = 0;
+ std::string errorMessage;
+
+ int token;
+ StringList tokens = commandTokens<StringList>(args, &token);
+ StringVector inames;
+ bool runComplexDumpers = false;
+ do {
+ if (!tokens.empty() && tokens.front() == "-c") {
+ runComplexDumpers = true;
+ tokens.pop_front();
+ }
+ if (tokens.empty() || !integerFromString(tokens.front(), &frame)) {
+ errorMessage = singleLineUsage(commandDescriptions[CmdExpandlocals]);
+ break;
+ }
+ tokens.pop_front();
+ if (tokens.empty()) {
+ errorMessage = singleLineUsage(commandDescriptions[CmdExpandlocals]);
+ break;
+ }
+ split(tokens.front(), ',', std::back_inserter(inames));
+ } while (false);
+
+ if (errorMessage.empty())
+ symGroup = ExtensionContext::instance().symbolGroup(exc.symbols(), exc.threadId(), frame, &errorMessage);
+
+ if (!symGroup) {
+ ExtensionContext::instance().report('N', token, "expandlocals", errorMessage.c_str());
+ return S_OK;
+ }
+
+ const unsigned succeeded = runComplexDumpers ?
+ symGroup->expandListRunComplexDumpers(inames, SymbolGroupValueContext(exc.dataSpaces()), &errorMessage) :
+ symGroup->expandList(inames, &errorMessage);
+
+ ExtensionContext::instance().report('R', token, "expandlocals", "%u/%u %s",
+ succeeded, unsigned(inames.size()), errorMessage.c_str());
+ return S_OK;
+}
+
+// Extension command 'locals':
+// Display local variables of symbol group in GDBMI or debug output form.
+// Takes an optional iname which is expanded before displaying (for updateWatchData)
+
+static std::string commmandLocals(ExtensionCommandContext &exc,PCSTR args, int *token, std::string *errorMessage)
+{
+ // Parse the command
+ unsigned debugOutput = 0;
+ std::string iname;
+ StringList tokens = commandTokens<StringList>(args, token);
+ StringVector expandedInames;
+ StringVector uninitializedInames;
+ DumpParameters parameters;
+ // Parse away options
+ while (!tokens.empty() && tokens.front().size() == 2 && tokens.front().at(0) == '-') {
+ const char option = tokens.front().at(1);
+ tokens.pop_front();
+ switch (option) {
+ case 'd':
+ debugOutput++;
+ break;
+ case 'h':
+ parameters.dumpFlags |= DumpParameters::DumpHumanReadable;
+ break;
+ case 'c':
+ parameters.dumpFlags |= DumpParameters::DumpComplexDumpers;
+ break;
+ case 'u':
+ if (tokens.empty()) {
+ *errorMessage = singleLineUsage(commandDescriptions[CmdLocals]);
+ return std::string();
+ }
+ split(tokens.front(), ',', std::back_inserter(uninitializedInames));
+ tokens.pop_front();
+ break;
+ case 'e':
+ if (tokens.empty()) {
+ *errorMessage = singleLineUsage(commandDescriptions[CmdLocals]);
+ return std::string();
+ }
+ split(tokens.front(), ',', std::back_inserter(expandedInames));
+ tokens.pop_front();
+ break;
+ case 'T': // typeformats: 'hex'ed name = formatnumber,...'
+ if (tokens.empty()) {
+ *errorMessage = singleLineUsage(commandDescriptions[CmdLocals]);
+ return std::string();
+ }
+ parameters.typeFormats = DumpParameters::decodeFormatArgument(tokens.front());
+ tokens.pop_front();
+ break;
+ case 'I': // individual formats: 'hex'ed name = formatnumber,...'
+ if (tokens.empty()) {
+ *errorMessage = singleLineUsage(commandDescriptions[CmdLocals]);
+ return std::string();
+ }
+ parameters.individualFormats = DumpParameters::decodeFormatArgument(tokens.front());
+ tokens.pop_front();
+ break;
+ } // case option
+ } // for options
+
+ // Frame and iname
+ unsigned frame;
+ if (tokens.empty() || !integerFromString(tokens.front(), &frame)) {
+ *errorMessage = singleLineUsage(commandDescriptions[CmdLocals]);
+ return std::string();
+ }
+
+ tokens.pop_front();
+ if (!tokens.empty())
+ iname = tokens.front();
+
+ const SymbolGroupValueContext dumpContext(exc.dataSpaces());
+ SymbolGroup * const symGroup = ExtensionContext::instance().symbolGroup(exc.symbols(), exc.threadId(), frame, errorMessage);
+ if (!symGroup)
+ return std::string();
+
+ if (!uninitializedInames.empty())
+ symGroup->markUninitialized(uninitializedInames);
+
+ if (!expandedInames.empty()) {
+ if (parameters.dumpFlags & DumpParameters::DumpComplexDumpers) {
+ symGroup->expandListRunComplexDumpers(expandedInames, dumpContext, errorMessage);
+ } else {
+ symGroup->expandList(expandedInames, errorMessage);
+ }
+ }
+
+ if (debugOutput)
+ return symGroup->debug(iname, debugOutput - 1);
+
+ return iname.empty() ?
+ symGroup->dump(dumpContext, parameters) :
+ symGroup->dump(iname, dumpContext, parameters, errorMessage);
+}
+
+extern "C" HRESULT CALLBACK locals(CIDebugClient *client, PCSTR args)
+{
+ ExtensionCommandContext exc(client);
+ std::string errorMessage;
+ int token;
+ const std::string output = commmandLocals(exc, args, &token, &errorMessage);
+ if (output.empty()) {
+ ExtensionContext::instance().report('N', token, "locals", errorMessage.c_str());
+ } else {
+ ExtensionContext::instance().report('R', token, "locals", "%s", output.c_str());
+ }
+ return S_OK;
+}
+
+// Extension command 'dumplocal':
+// Dump a local variable using dumpers (testing command).
+
+static std::string dumplocalHelper(ExtensionCommandContext &exc,PCSTR args, int *token, std::string *errorMessage)
+{
+ // Parse the command
+ StringList tokens = commandTokens<StringList>(args, token);
+ // Frame and iname
+ unsigned frame;
+ if (tokens.empty() || integerFromString(tokens.front(), &frame)) {
+ *errorMessage = singleLineUsage(commandDescriptions[CmdDumplocal]);
+ return std::string();
+ }
+ tokens.pop_front();
+ if (tokens.empty()) {
+ *errorMessage = singleLineUsage(commandDescriptions[CmdDumplocal]);
+ return std::string();
+ }
+ const std::string iname = tokens.front();
+
+ SymbolGroup * const symGroup = ExtensionContext::instance().symbolGroup(exc.symbols(), exc.threadId(), frame, errorMessage);
+ if (!symGroup)
+ return std::string();
+
+ AbstractSymbolGroupNode *n = symGroup->find(iname);
+ if (!n || !n->asSymbolGroupNode()) {
+ *errorMessage = "No such iname " + iname;
+ return std::string();
+ }
+ std::wstring value;
+ if (!dumpSimpleType(n->asSymbolGroupNode(), SymbolGroupValueContext(exc.dataSpaces()), &value)) {
+ *errorMessage = "Cannot dump " + iname;
+ return std::string();
+ }
+ return wStringToString(value);
+}
+
+extern "C" HRESULT CALLBACK dumplocal(CIDebugClient *client, PCSTR argsIn)
+{
+ ExtensionCommandContext exc(client);
+ std::string errorMessage;
+ int token = 0;
+ const std::string value = dumplocalHelper(exc,argsIn, &token, &errorMessage);
+ if (value.empty()) {
+ ExtensionContext::instance().report('N', token, "dumplocal", errorMessage.c_str());
+ } else {
+ ExtensionContext::instance().report('R', token, "dumplocal", value.c_str());
+ }
+ return S_OK;
+}
+
+// Extension command 'typecast':
+// Change the type of a symbol group entry (testing purposes)
+
+extern "C" HRESULT CALLBACK typecast(CIDebugClient *client, PCSTR args)
+{
+ ExtensionCommandContext exc(client);
+ unsigned frame = 0;
+ SymbolGroup *symGroup = 0;
+ std::string errorMessage;
+
+ int token;
+ const StringVector tokens = commandTokens<StringVector>(args, &token);
+ std::string iname;
+ std::string desiredType;
+ if (tokens.size() == 3u && integerFromString(tokens.front(), &frame)) {
+ symGroup = ExtensionContext::instance().symbolGroup(exc.symbols(), exc.threadId(), frame, &errorMessage);
+ iname = tokens.at(1);
+ desiredType = tokens.at(2);
+ } else {
+ errorMessage = singleLineUsage(commandDescriptions[CmdTypecast]);
+ }
+ if (symGroup != 0 && symGroup->typeCast(iname, desiredType, &errorMessage)) {
+ ExtensionContext::instance().report('R', token, "typecast", "OK");
+ } else {
+ ExtensionContext::instance().report('N', token, "typecast", errorMessage.c_str());
+ }
+ return S_OK;
+}
+
+// Extension command 'addsymbol':
+// Adds a symbol to a symbol group by name (testing purposes)
+
+extern "C" HRESULT CALLBACK addsymbol(CIDebugClient *client, PCSTR args)
+{
+ ExtensionCommandContext exc(client);
+ unsigned frame = 0;
+ SymbolGroup *symGroup = 0;
+ std::string errorMessage;
+
+ int token;
+ const StringVector tokens = commandTokens<StringVector>(args, &token);
+ std::string name;
+ std::string iname;
+ if (tokens.size() >= 2u && integerFromString(tokens.front(), &frame)) {
+ symGroup = ExtensionContext::instance().symbolGroup(exc.symbols(), exc.threadId(), frame, &errorMessage);
+ name = tokens.at(1);
+ if (tokens.size() >= 3)
+ iname = tokens.at(2);
+ } else {
+ errorMessage = singleLineUsage(commandDescriptions[CmdAddsymbol]);
+ }
+ if (symGroup != 0 && symGroup->addSymbol(name, iname, &errorMessage)) {
+ ExtensionContext::instance().report('R', token, "addsymbol", "OK");
+ } else {
+ ExtensionContext::instance().report('N', token, "addsymbol", errorMessage.c_str());
+ }
+ return S_OK;
+}
+
+// Extension command 'assign':
+// Assign locals by iname: 'assign locals.x=5'
+
+extern "C" HRESULT CALLBACK assign(CIDebugClient *client, PCSTR argsIn)
+{
+ ExtensionCommandContext exc(client);
+
+ std::string errorMessage;
+ bool success = false;
+
+ int token = 0;
+ do {
+ const StringList tokens = commandTokens<StringList>(argsIn, &token);
+ // Parse 'assign locals.x=5'
+ const std::string::size_type equalsPos = tokens.size() == 1 ? tokens.front().find('=') : std::string::npos;
+ if (equalsPos == std::string::npos) {
+ errorMessage = singleLineUsage(commandDescriptions[CmdAssign]);
+ break;
+ }
+ const std::string iname = tokens.front().substr(0, equalsPos);
+ const std::string value = tokens.front().substr(equalsPos + 1, tokens.front().size() - equalsPos - 1);
+ // get the symbolgroup
+ const int currentFrame = ExtensionContext::instance().symbolGroupFrame();
+ if (currentFrame < 0) {
+ errorMessage = "No current frame.";
+ break;
+ }
+ SymbolGroup *symGroup = ExtensionContext::instance().symbolGroup(exc.symbols(), exc.threadId(), currentFrame, &errorMessage);
+ if (!symGroup)
+ break;
+ success = symGroup->assign(iname, value, &errorMessage);
+ } while (false);
+
+ if (success) {
+ ExtensionContext::instance().report('R', token, "assign", "Ok");
+ } else {
+ ExtensionContext::instance().report('N', token, "assign", errorMessage.c_str());
+ }
+ return S_OK;
+}
+
+// Extension command 'threads':
+// List all thread info in GDBMI syntax
+
+extern "C" HRESULT CALLBACK threads(CIDebugClient *client, PCSTR argsIn)
+{
+ ExtensionCommandContext exc(client);
+ std::string errorMessage;
+
+ int token;
+ commandTokens<StringList>(argsIn, &token);
+
+ const std::string gdbmi = gdbmiThreadList(exc.systemObjects(),
+ exc.symbols(),
+ exc.control(),
+ exc.advanced(),
+ &errorMessage);
+ if (gdbmi.empty()) {
+ ExtensionContext::instance().report('N', token, "threads", errorMessage.c_str());
+ } else {
+ ExtensionContext::instance().report('R', token, "threads", gdbmi.c_str());
+ }
+ return S_OK;
+}
+
+// Extension command 'registers':
+// List all registers in GDBMI syntax
+
+extern "C" HRESULT CALLBACK registers(CIDebugClient *Client, PCSTR argsIn)
+{
+ ExtensionCommandContext exc(Client);
+ std::string errorMessage;
+
+ int token;
+ const StringList tokens = commandTokens<StringList>(argsIn, &token);
+ const bool humanReadable = !tokens.empty() && tokens.front() == "-h";
+ const std::string regs = gdbmiRegisters(exc.registers(), exc.control(), humanReadable, IncludePseudoRegisters, &errorMessage);
+ if (regs.empty()) {
+ ExtensionContext::instance().report('N', token, "registers", errorMessage.c_str());
+ } else {
+ ExtensionContext::instance().report('R', token, "registers", regs.c_str());
+ }
+ return S_OK;
+}
+
+// Extension command 'modules':
+// List all modules in GDBMI syntax
+
+extern "C" HRESULT CALLBACK modules(CIDebugClient *Client, PCSTR argsIn)
+{
+ ExtensionCommandContext exc(Client);
+ std::string errorMessage;
+
+ int token;
+ const StringList tokens = commandTokens<StringList>(argsIn, &token);
+ const bool humanReadable = !tokens.empty() && tokens.front() == "-h";
+ const std::string modules = gdbmiModules(exc.symbols(), humanReadable, &errorMessage);
+ if (modules.empty()) {
+ ExtensionContext::instance().report('N', token, "modules", errorMessage.c_str());
+ } else {
+ ExtensionContext::instance().report('R', token, "modules", modules.c_str());
+ }
+ return S_OK;
+}
+
+// Report stop of debuggee to Creator. This is hooked up as .idle_cmd command
+// by the Creator engine to reliably get notified about stops.
+extern "C" HRESULT CALLBACK idle(CIDebugClient *, PCSTR)
+{
+ ExtensionContext::instance().notifyIdle();
+ return S_OK;
+}
+
+// Extension command 'help':
+// Display version
+
+extern "C" HRESULT CALLBACK help(CIDebugClient *, PCSTR)
+{
+ std::ostringstream str;
+ str << "### Qt Creator CDB extension built " << __DATE__ << "\n\n";
+
+ const size_t commandCount = sizeof(commandDescriptions)/sizeof(CommandDescription);
+ std::copy(commandDescriptions, commandDescriptions + commandCount,
+ std::ostream_iterator<CommandDescription>(str));
+ dprintf("%s\n", str.str().c_str());
+ return S_OK;
+}
+
+// Extension command 'memory':
+// Display memory as base64
+
+extern "C" HRESULT CALLBACK memory(CIDebugClient *Client, PCSTR argsIn)
+{
+ ExtensionCommandContext exc(Client);
+ std::string errorMessage;
+ std::string memory;
+
+ int token;
+ ULONG64 address = 0;
+ ULONG length = 0;
+
+ const StringVector tokens = commandTokens<StringVector>(argsIn, &token);
+ if (tokens.size() == 2
+ && integerFromString(tokens.front(), &address)
+ && integerFromString(tokens.at(1), &length)) {
+ memory = memoryToBase64(exc.dataSpaces(), address, length, &errorMessage);
+ } else {
+ errorMessage = singleLineUsage(commandDescriptions[CmdMemory]);
+ }
+
+ if (memory.empty()) {
+ ExtensionContext::instance().report('N', token, "memory", errorMessage.c_str());
+ } else {
+ ExtensionContext::instance().report('R', token, "memory", memory.c_str());
+ if (!errorMessage.empty())
+ ExtensionContext::instance().report('W', token, "memory", errorMessage.c_str());
+ }
+ return S_OK;
+}
+
+// Extension command 'stack'
+// Report stack correctly as 'k' does not list instruction pointer
+// correctly.
+extern "C" HRESULT CALLBACK stack(CIDebugClient *Client, PCSTR argsIn)
+{
+ ExtensionCommandContext exc(Client);
+ std::string errorMessage;
+
+ int token;
+ bool humanReadable = false;
+ unsigned maxFrames = 1000;
+
+ StringList tokens = commandTokens<StringList>(argsIn, &token);
+ if (!tokens.empty() && tokens.front() == "-h") {
+ humanReadable = true;
+ tokens.pop_front();
+ }
+ if (!tokens.empty())
+ integerFromString(tokens.front(), &maxFrames);
+
+ const std::string stack = gdbmiStack(exc.control(), exc.symbols(),
+ maxFrames, humanReadable, &errorMessage);
+
+ if (stack.empty()) {
+ ExtensionContext::instance().report('N', token, "stack", errorMessage.c_str());
+ } else {
+ ExtensionContext::instance().report('R', token, "stack", stack.c_str());
+ }
+ return S_OK;
+}
+
+// Extension command 'shutdownex' (shutdown is reserved):
+// Unhook the output callbacks. This is normally done by the session
+// inaccessible notification, however, this does not work for remote-controlled sessions.
+extern "C" HRESULT CALLBACK shutdownex(CIDebugClient *, PCSTR)
+{
+ ExtensionContext::instance().unhookCallbacks();
+ return S_OK;
+}
+
+// Hook for dumping Known Structs. Not currently used.
+// Shows up in 'dv' as well as IDebugSymbolGroup::GetValueText.
+
+extern "C" HRESULT CALLBACK KnownStructOutput(ULONG Flag, ULONG64 Address, PSTR StructName, PSTR Buffer, PULONG /* BufferSize */)
+{
+ if (Flag == DEBUG_KNOWN_STRUCT_GET_NAMES) {
+ memcpy(Buffer, "\0\0", 2);
+ return S_OK;
+ }
+ // Usually 260 chars buf
+ std::ostringstream str;
+ str << " KnownStructOutput 0x" << std::hex << Address << ' '<< StructName;
+ strcpy(Buffer, str.str().c_str());
+ return S_OK;
+}
diff --git a/src/libs/qtcreatorcdbext/stringutils.cpp b/src/libs/qtcreatorcdbext/stringutils.cpp
new file mode 100644
index 0000000000..5491f218ef
--- /dev/null
+++ b/src/libs/qtcreatorcdbext/stringutils.cpp
@@ -0,0 +1,267 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "stringutils.h"
+
+#include <cctype>
+#include <iostream>
+#include <sstream>
+
+static const char whiteSpace[] = " \t\r\n";
+
+void trimFront(std::string &s)
+{
+ if (s.empty())
+ return;
+ std::string::size_type pos = s.find_first_not_of(whiteSpace);
+ if (pos == 0)
+ return;
+ if (pos == std::string::npos) { // All blanks?!
+ s.clear();
+ } else {
+ s.erase(0, pos);
+ }
+}
+
+void trimBack(std::string &s)
+{
+ if (s.empty())
+ return;
+ std::string::size_type pos = s.find_last_not_of(whiteSpace);
+ if (pos == std::string::npos) { // All blanks?!
+ s.clear();
+ } else {
+ if (++pos != s.size())
+ s.erase(pos, s.size() - pos);
+ }
+}
+
+void simplify(std::string &s)
+{
+ trimFront(s);
+ trimBack(s);
+ if (s.empty())
+ return;
+
+ // 1) All blanks
+ const std::string::size_type size1 = s.size();
+ std::string::size_type pos = 0;
+ for ( ; pos < size1; pos++)
+ if (std::isspace(s.at(pos)))
+ s[pos] = ' ';
+ // 2) Simplify
+ for (pos = 0; pos < s.size(); ) {
+ std::string::size_type blankpos = s.find(' ', pos);
+ if (blankpos == std::string::npos)
+ break;
+ std::string::size_type tokenpos = blankpos + 1;
+ while (tokenpos < s.size() && s.at(tokenpos) == ' ')
+ tokenpos++;
+ if (tokenpos - blankpos > 1)
+ s.erase(blankpos, tokenpos - blankpos - 1);
+ pos = blankpos + 1;
+ }
+}
+
+void replace(std::wstring &s, wchar_t before, wchar_t after)
+{
+ const std::wstring::size_type size = s.size();
+ for (std::wstring::size_type i = 0; i < size; i++)
+ if (s.at(i) == before)
+ s[i] = after;
+}
+
+bool endsWith(const std::string &haystack, const char *needle)
+{
+ const size_t needleLen = strlen(needle);
+ const size_t haystackLen = haystack.size();
+ if (needleLen > haystackLen)
+ return false;
+ return haystack.compare(haystackLen - needleLen, needleLen, needle) == 0;
+}
+
+static inline void formatGdbmiChar(std::ostream &str, wchar_t c)
+{
+ switch (c) {
+ case L'\n':
+ str << "\\n";
+ break;
+ case L'\t':
+ str << "\\t";
+ break;
+ case L'\r':
+ str << "\\r";
+ break;
+ case L'\\':
+ case L'"':
+ str << '\\' << char(c);
+ break;
+ default:
+ if (c < 128) {
+ str << char(c);
+ } else {
+ // Always pad up to 3 digits in case a digit follows
+ const char oldFill = str.fill('0');
+ str << '\\' << std::oct;
+ str.width(3);
+ str << unsigned(c) << std::dec;
+ str.fill(oldFill);
+ }
+ break;
+ }
+}
+
+// Stream a wstring onto a char stream doing octal escaping
+// suitable for GDBMI.
+
+void gdbmiStringFormat::format(std::ostream &str) const
+{
+ const std::string::size_type size = m_s.size();
+ for (std::string::size_type i = 0; i < size; i++)
+ formatGdbmiChar(str, wchar_t(m_s.at(i)));
+}
+
+void gdbmiWStringFormat::format(std::ostream &str) const
+{
+ const std::wstring::size_type size = m_w.size();
+ for (std::wstring::size_type i = 0; i < size; i++)
+ formatGdbmiChar(str, m_w.at(i));
+}
+
+std::string wStringToGdbmiString(const std::wstring &w)
+{
+ std::ostringstream str;
+ str << gdbmiWStringFormat(w);
+ return str.str();
+}
+
+std::string wStringToString(const std::wstring &w)
+{
+ if (w.empty())
+ return std::string();
+ const std::string::size_type size = w.size();
+ std::string rc;
+ rc.reserve(size);
+ for (std::string::size_type i = 0; i < size; i++)
+ rc.push_back(char(w.at(i)));
+ return rc;
+}
+
+std::wstring stringToWString(const std::string &w)
+{
+ if (w.empty())
+ return std::wstring();
+ const std::wstring::size_type size = w.size();
+ std::wstring rc;
+ rc.reserve(size);
+ for (std::wstring::size_type i = 0; i < size; i++)
+ rc.push_back(w.at(i));
+ return rc;
+}
+
+// Convert an ASCII hex digit to its value 'A'->10
+inline unsigned hexDigit(char c)
+{
+ if (c <= '9')
+ return c - '0';
+ if (c <= 'F')
+ return c - 'A' + 10;
+ return c - 'a' + 10;
+}
+
+// Convert an ASCII hex digit to its value 'A'->10
+inline char toHexDigit(unsigned v)
+{
+ if (v < 10)
+ return char(v) + '0';
+ return char(v - 10) + 'a';
+}
+
+// String from hex "414A" -> "AJ".
+std::string stringFromHex(const char *p, const char *end)
+{
+ if (p == end)
+ return std::string();
+
+ std::string rc;
+ rc.reserve((end - p) / 2);
+ for ( ; p < end; p++) {
+ unsigned c = 16 * hexDigit(*p);
+ c += hexDigit(*++p);
+ rc.push_back(char(c));
+ }
+ return rc;
+}
+
+std::wstring dataToHexW(const unsigned char *p, const unsigned char *end)
+{
+ if (p == end)
+ return std::wstring();
+
+ std::wstring rc;
+ rc.reserve(2 * (end - p));
+ for ( ; p < end ; p++) {
+ const unsigned c = *p;
+ rc.push_back(toHexDigit(c / 16));
+ rc.push_back(toHexDigit(c &0xF));
+ }
+ return rc;
+}
+
+// Readable hex: '0xAA 0xBB'..
+std::wstring dataToReadableHexW(const unsigned char *begin, const unsigned char *end)
+{
+ if (begin == end)
+ return std::wstring();
+
+ std::wstring rc;
+ rc.reserve(5 * (end - begin));
+ for (const unsigned char *p = begin; p < end ; p++) {
+ rc.append(p == begin ? L"0x" : L" 0x");
+ const unsigned c = *p;
+ rc.push_back(toHexDigit(c / 16));
+ rc.push_back(toHexDigit(c &0xF));
+ }
+ return rc;
+}
+
+// Format a map as a GDBMI hash {key="value",..}
+void formatGdbmiHash(std::ostream &os, const std::map<std::string, std::string> &m)
+{
+ typedef std::map<std::string, std::string>::const_iterator It;
+ const It begin = m.begin();
+ const It cend = m.end();
+ os << '{';
+ for (It it = begin; it != cend; ++it) {
+ if (it != begin)
+ os << ',';
+ os << it->first << "=\"" << gdbmiStringFormat(it->second) << '"';
+ }
+ os << '}';
+}
diff --git a/src/libs/qtcreatorcdbext/stringutils.h b/src/libs/qtcreatorcdbext/stringutils.h
new file mode 100644
index 0000000000..30db251cdb
--- /dev/null
+++ b/src/libs/qtcreatorcdbext/stringutils.h
@@ -0,0 +1,154 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 SPLIT_H
+#define SPLIT_H
+
+#include <string>
+#include <sstream>
+#include <map>
+
+void trimFront(std::string &s);
+void trimBack(std::string &s);
+void simplify(std::string &s);
+
+// Split by character separator.
+template <class Iterator>
+void split(const std::string &s, char sep, Iterator it)
+{
+ const std::string::size_type size = s.size();
+ for (std::string::size_type pos = 0; pos < size; ) {
+ std::string::size_type nextpos = s.find(sep, pos);
+ if (nextpos == std::string::npos)
+ nextpos = size;
+ const std::string token = s.substr(pos, nextpos - pos);
+ *it = token;
+ ++it;
+ pos = nextpos + 1;
+ }
+}
+
+// Format numbers, etc, as a string.
+template <class Streamable>
+std::string toString(const Streamable s)
+{
+ std::ostringstream str;
+ str << s;
+ return str.str();
+}
+
+// Format numbers, etc, as a wstring.
+template <class Streamable>
+std::wstring toWString(const Streamable s)
+{
+ std::wostringstream str;
+ str << s;
+ return str.str();
+}
+
+bool endsWith(const std::string &haystack, const char *needle);
+inline bool endsWith(const std::string &haystack, char needle)
+ { return !haystack.empty() && haystack.at(haystack.size() - 1) == needle; }
+
+// Read an integer from a string as '10' or '0xA'
+template <class Integer>
+bool integerFromString(const std::string &s, Integer *v)
+{
+ const bool isHex = s.compare(0, 2, "0x") == 0;
+ std::istringstream str(isHex ? s.substr(2, s.size() - 2) : s);
+ if (isHex)
+ str >> std::hex;
+ str >> *v;
+ return !str.fail();
+}
+
+// Read an integer from a wstring as '10' or '0xA'
+template <class Integer>
+bool integerFromWString(const std::wstring &s, Integer *v)
+{
+ const bool isHex = s.compare(0, 2, L"0x") == 0;
+ std::wistringstream str(isHex ? s.substr(2, s.size() - 2) : s);
+ if (isHex)
+ str >> std::hex;
+ str >> *v;
+ return !str.fail();
+}
+
+void replace(std::wstring &s, wchar_t before, wchar_t after);
+
+// Stream a string onto a char stream doing backslash & octal escaping
+// suitable for GDBMI usable as 'str << gdbmiStringFormat(wstring)'
+class gdbmiStringFormat {
+public:
+ explicit gdbmiStringFormat(const std::string &s) : m_s(s) {}
+
+ void format(std::ostream &) const;
+
+private:
+ const std::string &m_s;
+};
+
+// Stream a wstring onto a char stream doing backslash & octal escaping
+// suitable for GDBMI usable as 'str << gdbmiWStringFormat(wstring)'
+class gdbmiWStringFormat {
+public:
+ explicit gdbmiWStringFormat(const std::wstring &w) : m_w(w) {}
+
+ void format(std::ostream &) const;
+
+private:
+ const std::wstring &m_w;
+};
+
+inline std::ostream &operator<<(std::ostream &str, const gdbmiStringFormat &sf)
+{
+ sf.format(str);
+ return str;
+}
+
+inline std::ostream &operator<<(std::ostream &str, const gdbmiWStringFormat &wsf)
+{
+ wsf.format(str);
+ return str;
+}
+
+std::string wStringToGdbmiString(const std::wstring &w);
+std::string wStringToString(const std::wstring &w);
+std::wstring stringToWString(const std::string &w);
+
+// String from hex "414A" -> "AJ".
+std::string stringFromHex(const char *begin, const char *end);
+std::wstring dataToHexW(const unsigned char *begin, const unsigned char *end);
+// Create readable hex: '0xAA 0xBB'..
+std::wstring dataToReadableHexW(const unsigned char *begin, const unsigned char *end);
+
+// Format a map as a GDBMI hash {key="value",..}
+void formatGdbmiHash(std::ostream &os, const std::map<std::string, std::string> &);
+
+#endif // SPLIT_H
diff --git a/src/libs/qtcreatorcdbext/symbolgroup.cpp b/src/libs/qtcreatorcdbext/symbolgroup.cpp
new file mode 100644
index 0000000000..e1d6bc334d
--- /dev/null
+++ b/src/libs/qtcreatorcdbext/symbolgroup.cpp
@@ -0,0 +1,525 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "symbolgroup.h"
+#include "stringutils.h"
+
+#include <set>
+#include <algorithm>
+#include <iterator>
+
+typedef std::vector<int>::size_type VectorIndexType;
+typedef std::vector<std::string> StringVector;
+
+enum { debug = 0 };
+const char rootNameC[] = "local";
+
+// ------------- SymbolGroup
+SymbolGroup::SymbolGroup(IDebugSymbolGroup2 *sg,
+ const SymbolParameterVector &vec,
+ ULONG threadId,
+ unsigned frame) :
+ m_symbolGroup(sg),
+ m_threadId(threadId),
+ m_frame(frame),
+ m_root(0)
+{
+ m_root = SymbolGroupNode::create(this, rootNameC, vec);
+}
+
+SymbolGroup::~SymbolGroup()
+{
+ m_symbolGroup->Release();
+ delete m_root;
+}
+
+static inline bool getSymbolCount(CIDebugSymbolGroup *symbolGroup,
+ ULONG *count,
+ std::string *errorMessage)
+{
+ const HRESULT hr = symbolGroup->GetNumberSymbols(count);
+ if (FAILED(hr)) {
+ *errorMessage = msgDebugEngineComFailed("GetNumberSymbols", hr);
+ return false;
+ }
+ return true;
+}
+
+bool SymbolGroup::getSymbolParameters(CIDebugSymbolGroup *symbolGroup,
+ SymbolParameterVector *vec,
+ std::string *errorMessage)
+{
+ ULONG count;
+ return getSymbolCount(symbolGroup, &count, errorMessage)
+ && getSymbolParameters(symbolGroup, 0, count, vec, errorMessage);
+}
+
+bool SymbolGroup::getSymbolParameters(CIDebugSymbolGroup *symbolGroup,
+ unsigned long start,
+ unsigned long count,
+ SymbolParameterVector *vec,
+ std::string *errorMessage)
+{
+ if (!count) {
+ vec->clear();
+ return true;
+ }
+ // Trim the count to the maximum count available. When expanding elements
+ // and passing SubElements as count, SubElements might be an estimate that
+ // is too large and triggers errors.
+ ULONG totalCount;
+ if (!getSymbolCount(symbolGroup, &totalCount, errorMessage))
+ return false;
+ if (start >= totalCount) {
+ std::ostringstream str;
+ str << "SymbolGroup::getSymbolParameters: Start parameter "
+ << start << " beyond total " << totalCount << '.';
+ *errorMessage = str.str();
+ return false;
+ }
+ if (start + count > totalCount)
+ count = totalCount - start;
+ // Get parameters.
+ vec->resize(count);
+ const HRESULT hr = symbolGroup->GetSymbolParameters(start, count, &(*vec->begin()));
+ if (FAILED(hr)) {
+ std::ostringstream str;
+ str << "SymbolGroup::getSymbolParameters failed for index=" << start << ", count=" << count
+ << ": " << msgDebugEngineComFailed("GetSymbolParameters", hr);
+ *errorMessage = str.str();
+ return false;
+ }
+ return true;
+}
+
+SymbolGroup *SymbolGroup::create(CIDebugControl *control, CIDebugSymbols *debugSymbols,
+ ULONG threadId, unsigned frame,
+ std::string *errorMessage)
+{
+ errorMessage->clear();
+
+ ULONG obtainedFrameCount = 0;
+ const ULONG frameCount = frame + 1;
+
+ DEBUG_STACK_FRAME *frames = new DEBUG_STACK_FRAME[frameCount];
+ IDebugSymbolGroup2 *idebugSymbols = 0;
+ bool success = false;
+ SymbolParameterVector parameters;
+
+ // Obtain symbol group at stack frame.
+ do {
+ HRESULT hr = control->GetStackTrace(0, 0, 0, frames, frameCount, &obtainedFrameCount);
+ if (FAILED(hr)) {
+ *errorMessage = msgDebugEngineComFailed("GetStackTrace", hr);
+ break;
+ }
+ if (obtainedFrameCount < frameCount ) {
+ std::ostringstream str;
+ str << "Unable to obtain frame " << frame << " (" << obtainedFrameCount << ").";
+ *errorMessage = str.str();
+ break;
+ }
+ hr = debugSymbols->GetScopeSymbolGroup2(DEBUG_SCOPE_GROUP_LOCALS, NULL, &idebugSymbols);
+ if (FAILED(hr)) {
+ *errorMessage = msgDebugEngineComFailed("GetScopeSymbolGroup2", hr);
+ break;
+ }
+ hr = debugSymbols->SetScope(0, frames + frame, NULL, 0);
+ if (FAILED(hr)) {
+ *errorMessage = msgDebugEngineComFailed("SetScope", hr);
+ break;
+ }
+ // refresh with current frame
+ hr = debugSymbols->GetScopeSymbolGroup2(DEBUG_SCOPE_GROUP_LOCALS, idebugSymbols, &idebugSymbols);
+ if (FAILED(hr)) {
+ *errorMessage = msgDebugEngineComFailed("GetScopeSymbolGroup2", hr);
+ break;
+ }
+ if (!SymbolGroup::getSymbolParameters(idebugSymbols, &parameters, errorMessage))
+ break;
+
+ success = true;
+ } while (false);
+ delete [] frames;
+ if (!success) {
+ if (idebugSymbols)
+ idebugSymbols->Release();
+ return 0;
+ }
+ return new SymbolGroup(idebugSymbols, parameters, threadId, frame);
+}
+
+static inline std::string msgNotFound(const std::string &nodeName)
+{
+ std::ostringstream str;
+ str << "Node '" << nodeName << "' not found.";
+ return str.str();
+}
+
+std::string SymbolGroup::dump(const SymbolGroupValueContext &ctx,
+ const DumpParameters &p) const
+{
+ QTC_TRACE_IN
+ if (symbolGroupDebug)
+ DebugPrint() << "<SymbolGroup::dump()";
+ std::ostringstream str;
+ DumpSymbolGroupNodeVisitor visitor(str, ctx, p);
+ if (p.humanReadable())
+ str << '\n';
+ str << '[';
+ accept(visitor);
+ str << ']';
+ QTC_TRACE_OUT
+ if (symbolGroupDebug)
+ DebugPrint() << "<SymbolGroup::dump()";
+ return str.str();
+}
+
+// Dump a node, potentially expand
+std::string SymbolGroup::dump(const std::string &iname,
+ const SymbolGroupValueContext &ctx,
+ const DumpParameters &p,
+ std::string *errorMessage)
+{
+ if (symbolGroupDebug)
+ DebugPrint() << ">SymbolGroup::dump(" << iname << ")";
+ QTC_TRACE_IN
+ AbstractSymbolGroupNode *const aNode = find(iname);
+ if (!aNode) {
+ *errorMessage = msgNotFound(iname);
+ return std::string();
+ }
+
+ // Real nodes: Expand and complex dumpers
+ if (SymbolGroupNode *node = aNode->resolveReference()->asSymbolGroupNode()) {
+ if (node->isExpanded()) { // Mark expand request by watch model
+ node->clearFlags(SymbolGroupNode::ExpandedByDumper);
+ } else {
+ if (node->canExpand() && !node->expand(errorMessage))
+ return false;
+ }
+ // After expansion, run the complex dumpers
+ if (p.dumpFlags & DumpParameters::DumpComplexDumpers)
+ node->runComplexDumpers(ctx);
+ }
+
+ std::ostringstream str;
+ if (p.humanReadable())
+ str << '\n';
+ DumpSymbolGroupNodeVisitor visitor(str, ctx, p);
+ str << '[';
+ aNode->accept(visitor, SymbolGroupNodeVisitor::parentIname(iname), 0, 0);
+ str << ']';
+ QTC_TRACE_OUT
+ if (symbolGroupDebug)
+ DebugPrint() << "<SymbolGroup::dump(" << iname << ")";
+ return str.str();
+}
+
+std::string SymbolGroup::debug(const std::string &iname, unsigned verbosity) const
+{
+ std::ostringstream str;
+ str << '\n';
+ DebugSymbolGroupNodeVisitor visitor(str, verbosity);
+ if (iname.empty()) {
+ accept(visitor);
+ } else {
+ if (AbstractSymbolGroupNode *const node = find(iname)) {
+ node->accept(visitor, SymbolGroupNodeVisitor::parentIname(iname), 0, 0);
+ } else {
+ str << msgNotFound(iname);
+ }
+ }
+ return str.str();
+}
+
+/* expandList: Expand a list of inames with a 'mkdir -p'-like behaviour, that is,
+ * expand all sub-paths. The list of inames has thus to be reordered to expand the
+ * parent items first, for example "locals.this.i1.data,locals.this.i2" --->:
+ * "locals, locals.this, locals.this.i1, locals.this.i2, locals.this.i1.data".
+ * This is done here by creating a set of name parts keyed by level and name
+ * (thus purging duplicates). */
+
+typedef std::pair<unsigned, std::string> InamePathEntry;
+
+struct InamePathEntryLessThan : public std::binary_function<InamePathEntry, InamePathEntry, bool> {
+ bool operator()(const InamePathEntry &i1, const InamePathEntry& i2) const
+ {
+ if (i1.first < i2.first)
+ return true;
+ if (i1.first != i2.first)
+ return false;
+ return i1.second < i2.second;
+ }
+};
+
+typedef std::set<InamePathEntry, InamePathEntryLessThan> InamePathEntrySet;
+
+static inline InamePathEntrySet expandEntrySet(const std::vector<std::string> &nodes)
+{
+ InamePathEntrySet pathEntries;
+ const VectorIndexType nodeCount = nodes.size();
+ for (VectorIndexType i= 0; i < nodeCount; i++) {
+ const std::string &iname = nodes.at(i);
+ std::string::size_type pos = 0;
+ // Split a path 'local.foo' and insert (0,'local'), (1,'local.foo') (see above)
+ for (unsigned level = 0; pos < iname.size(); level++) {
+ std::string::size_type dotPos = iname.find(SymbolGroupNodeVisitor::iNamePathSeparator, pos);
+ if (dotPos == std::string::npos)
+ dotPos = iname.size();
+ pathEntries.insert(InamePathEntry(level, iname.substr(0, dotPos)));
+ pos = dotPos + 1;
+ }
+ }
+ return pathEntries;
+}
+
+// Expand a node list "locals.i1,locals.i2"
+unsigned SymbolGroup::expandList(const std::vector<std::string> &nodes, std::string *errorMessage)
+{
+ if (symbolGroupDebug)
+ DebugPrint() << ">SymbolGroup::expandList" << nodes.size();
+ if (nodes.empty())
+ return 0;
+ // Create a set with a key <level, name>. Also required for 1 node (see above).
+ const InamePathEntrySet pathEntries = expandEntrySet(nodes);
+ // Now expand going by level.
+ unsigned succeeded = 0;
+ std::string nodeError;
+ InamePathEntrySet::const_iterator cend = pathEntries.end();
+ for (InamePathEntrySet::const_iterator it = pathEntries.begin(); it != cend; ++it)
+ if (expand(it->second, &nodeError)) {
+ succeeded++;
+ } else {
+ if (!errorMessage->empty())
+ errorMessage->append(", ");
+ errorMessage->append(nodeError);
+ }
+ if (symbolGroupDebug)
+ DebugPrint() << "<SymbolGroup::expandList returns " << succeeded;
+ return succeeded;
+}
+
+unsigned SymbolGroup::expandListRunComplexDumpers(const std::vector<std::string> &nodes,
+ const SymbolGroupValueContext &ctx,
+ std::string *errorMessage)
+{
+ if (symbolGroupDebug)
+ DebugPrint() << ">SymbolGroup::expandListRunComplexDumpers" << nodes.size();
+ QTC_TRACE_IN
+ if (nodes.empty())
+ return 0;
+ // Create a set with a key <level, name>. Also required for 1 node (see above).
+ const InamePathEntrySet pathEntries = expandEntrySet(nodes);
+ // Now expand going by level.
+ unsigned succeeded = 0;
+ std::string nodeError;
+ InamePathEntrySet::const_iterator cend = pathEntries.end();
+ for (InamePathEntrySet::const_iterator it = pathEntries.begin(); it != cend; ++it)
+ if (expandRunComplexDumpers(it->second, ctx, &nodeError)) {
+ succeeded++;
+ } else {
+ if (!errorMessage->empty())
+ errorMessage->append(", ");
+ errorMessage->append(nodeError);
+ }
+ QTC_TRACE_OUT
+ if (symbolGroupDebug)
+ DebugPrint() << "<SymbolGroup::expandListRunComplexDumpers returns " << succeeded;
+ return succeeded;
+}
+
+// Find a node for expansion, skipping reference nodes.
+static inline SymbolGroupNode *
+ findNodeForExpansion(const SymbolGroup *sg,
+ const std::string &nodeName,
+ std::string *errorMessage)
+{
+ AbstractSymbolGroupNode *aNode = sg->find(nodeName);
+ if (!aNode) {
+ *errorMessage = msgNotFound(nodeName);
+ return 0;
+ }
+
+ SymbolGroupNode *node = aNode->resolveReference()->asSymbolGroupNode();
+ if (!node) {
+ *errorMessage = "Node type error in expand: " + nodeName;
+ return 0;
+ }
+ return node;
+}
+
+bool SymbolGroup::expand(const std::string &nodeName, std::string *errorMessage)
+{
+ if (SymbolGroupNode *node = findNodeForExpansion(this, nodeName, errorMessage))
+ return node == m_root ? true : node->expand(errorMessage);
+ return false;
+}
+
+bool SymbolGroup::expandRunComplexDumpers(const std::string &nodeName, const SymbolGroupValueContext &ctx, std::string *errorMessage)
+{
+ if (SymbolGroupNode *node = findNodeForExpansion(this, nodeName, errorMessage))
+ return node == m_root ? true : node->expandRunComplexDumpers(ctx, errorMessage);
+ return false;
+}
+
+// Cast an (unexpanded) node
+bool SymbolGroup::typeCast(const std::string &iname, const std::string &desiredType, std::string *errorMessage)
+{
+ AbstractSymbolGroupNode *aNode = find(iname);
+ if (!aNode) {
+ *errorMessage = msgNotFound(iname);
+ return false;
+ }
+ if (aNode == m_root) {
+ *errorMessage = "Cannot cast root node";
+ return false;
+ }
+ SymbolGroupNode *node = aNode->asSymbolGroupNode();
+ if (!node) {
+ *errorMessage = "Node type error in typeCast: " + iname;
+ return false;
+ }
+ return node->typeCast(desiredType, errorMessage);
+}
+
+SymbolGroupNode *SymbolGroup::addSymbol(const std::string &name, const std::string &iname, std::string *errorMessage)
+{
+ return m_root->addSymbolByName(name, iname, errorMessage);
+}
+
+// Mark uninitialized (top level only)
+void SymbolGroup::markUninitialized(const std::vector<std::string> &uniniNodes)
+{
+ if (m_root && !m_root->children().empty() && !uniniNodes.empty()) {
+ const std::vector<std::string>::const_iterator unIniNodesBegin = uniniNodes.begin();
+ const std::vector<std::string>::const_iterator unIniNodesEnd = uniniNodes.end();
+
+ const AbstractSymbolGroupNodePtrVector::const_iterator childrenEnd = m_root->children().end();
+ for (AbstractSymbolGroupNodePtrVector::const_iterator it = m_root->children().begin(); it != childrenEnd; ++it) {
+ if (std::find(unIniNodesBegin, unIniNodesEnd, (*it)->absoluteFullIName()) != unIniNodesEnd)
+ (*it)->addFlags(SymbolGroupNode::Uninitialized);
+ }
+ }
+}
+
+static inline std::string msgAssignError(const std::string &nodeName,
+ const std::string &value,
+ const std::string &why)
+{
+ std::ostringstream str;
+ str << "Unable to assign '" << value << "' to '" << nodeName << "': " << why;
+ return str.str();
+}
+
+bool SymbolGroup::assign(const std::string &nodeName, const std::string &value,
+ std::string *errorMessage)
+{
+ AbstractSymbolGroupNode *aNode = find(nodeName);
+ if (aNode == 0) {
+ *errorMessage = msgAssignError(nodeName, value, "No such node");
+ return false;
+ }
+ SymbolGroupNode *node = aNode->asSymbolGroupNode();
+ if (node == 0) {
+ *errorMessage = msgAssignError(nodeName, value, "Invalid node type");
+ return false;
+ }
+
+ const HRESULT hr = m_symbolGroup->WriteSymbol(node->index(), const_cast<char *>(value.c_str()));
+ if (FAILED(hr)) {
+ *errorMessage = msgAssignError(nodeName, value, msgDebugEngineComFailed("WriteSymbol", hr));
+ return false;
+ }
+ return true;
+}
+
+bool SymbolGroup::accept(SymbolGroupNodeVisitor &visitor) const
+{
+ if (!m_root || m_root->children().empty())
+ return false;
+ return m_root->accept(visitor, std::string(), 0, 0);
+}
+
+// Find "locals.this.i1" and move index recursively
+static AbstractSymbolGroupNode *findNodeRecursion(const std::vector<std::string> &iname,
+ unsigned depth,
+ std::vector<AbstractSymbolGroupNode *> nodes)
+{
+ typedef std::vector<AbstractSymbolGroupNode *>::const_iterator ConstIt;
+
+ if (debug > 1) {
+ DebugPrint() <<"findNodeRecursion: Looking for " << iname.back() << " (" << iname.size()
+ << "),depth=" << depth << ",matching=" << iname.at(depth) << " in " << nodes.size();
+ }
+
+ if (nodes.empty())
+ return 0;
+ // Find the child that matches the iname part at depth
+ const ConstIt cend = nodes.end();
+ for (ConstIt it = nodes.begin(); it != cend; ++it) {
+ AbstractSymbolGroupNode *c = *it;
+ if (c->iName() == iname.at(depth)) {
+ if (depth == iname.size() - 1) { // Complete iname matched->happy.
+ return c;
+ } else {
+ // Sub-part of iname matched. Forward index and check children.
+ return findNodeRecursion(iname, depth + 1, c->children());
+ }
+ }
+ }
+ return 0;
+}
+
+AbstractSymbolGroupNode *SymbolGroup::findI(const std::string &iname) const
+{
+ if (iname.empty())
+ return 0;
+ // Match the root element only: Shouldn't happen, still, all happy
+ if (iname == m_root->name())
+ return m_root;
+
+ std::vector<std::string> inameTokens;
+ split(iname, SymbolGroupNodeVisitor::iNamePathSeparator, std::back_inserter(inameTokens));
+
+ // Must begin with root
+ if (inameTokens.front() != m_root->name())
+ return 0;
+
+ // Start with index = 0 at root's children
+ return findNodeRecursion(inameTokens, 1, m_root->children());
+}
+
+AbstractSymbolGroupNode *SymbolGroup::find(const std::string &iname) const
+{
+ AbstractSymbolGroupNode *rc = findI(iname);
+ if (::debug > 1)
+ DebugPrint() << "SymbolGroup::find " << iname << ' ' << rc;
+ return rc;
+}
diff --git a/src/libs/qtcreatorcdbext/symbolgroup.h b/src/libs/qtcreatorcdbext/symbolgroup.h
new file mode 100644
index 0000000000..67be5b52e0
--- /dev/null
+++ b/src/libs/qtcreatorcdbext/symbolgroup.h
@@ -0,0 +1,128 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 SYMBOLGROUP_H
+#define SYMBOLGROUP_H
+
+#include "common.h"
+#include "symbolgroupnode.h"
+
+/* A symbol group storing a tree of expanded symbols rooted on
+ * a fake "locals" root element.
+ * Provides a find() method based on inames ("locals.this.i1.data") and
+ * dump() methods used for GDBMI-format dumping and debug helpers.
+ * Qt Creator's WatchModel is fed from this class. It basically represents the
+ * symbol group tree with some additional node types (Reference and Map Node
+ * types. */
+
+class SymbolGroup {
+public:
+ typedef std::vector<DEBUG_SYMBOL_PARAMETERS> SymbolParameterVector;
+
+private:
+ SymbolGroup(const SymbolGroup &);
+ SymbolGroup &operator=(const SymbolGroup &);
+
+ explicit SymbolGroup(CIDebugSymbolGroup *,
+ const SymbolParameterVector &vec,
+ ULONG threadId, unsigned frame);
+
+public:
+ typedef AbstractSymbolGroupNode::AbstractSymbolGroupNodePtrVector AbstractSymbolGroupNodePtrVector;
+
+ static SymbolGroup *create(CIDebugControl *control,
+ CIDebugSymbols *,
+ ULONG threadId,
+ unsigned frame,
+ std::string *errorMessage);
+ ~SymbolGroup();
+
+ // Dump all
+ std::string dump(const SymbolGroupValueContext &ctx,
+ const DumpParameters &p = DumpParameters()) const;
+ // Expand node and dump
+ std::string dump(const std::string &iname, const SymbolGroupValueContext &ctx,
+ const DumpParameters &p, std::string *errorMessage);
+ std::string debug(const std::string &iname = std::string(), unsigned verbosity = 0) const;
+
+ unsigned frame() const { return m_frame; }
+ ULONG threadId() const { return m_threadId; }
+ SymbolGroupNode *root() { return m_root; }
+ const SymbolGroupNode *root() const { return m_root; }
+ AbstractSymbolGroupNode *find(const std::string &iname) const;
+
+ // Expand a single node "locals.A.B" requiring that "locals.A.B" is already visible
+ // (think mkdir without -p).
+ bool expand(const std::string &node, std::string *errorMessage);
+ bool expandRunComplexDumpers(const std::string &node, const SymbolGroupValueContext &ctx, std::string *errorMessage);
+ // Expand a node list "locals.i1,locals.i2", expanding all nested child nodes
+ // (think mkdir -p).
+ unsigned expandList(const std::vector<std::string> &nodes, std::string *errorMessage);
+ unsigned expandListRunComplexDumpers(const std::vector<std::string> &nodes,
+ const SymbolGroupValueContext &ctx,
+ std::string *errorMessage);
+
+ // Mark uninitialized (top level only)
+ void markUninitialized(const std::vector<std::string> &nodes);
+
+ // Cast an (unexpanded) node
+ bool typeCast(const std::string &iname, const std::string &desiredType, std::string *errorMessage);
+ // Add a symbol by name expression
+ SymbolGroupNode *addSymbol(const std::string &name, // Expression like 'myarray[1]'
+ const std::string &iname, // Desired iname, defaults to name
+ std::string *errorMessage);
+
+ bool accept(SymbolGroupNodeVisitor &visitor) const;
+
+ // Assign a value by iname
+ bool assign(const std::string &node,
+ const std::string &value,
+ std::string *errorMessage);
+
+ CIDebugSymbolGroup *debugSymbolGroup() const { return m_symbolGroup; }
+
+ static bool getSymbolParameters(CIDebugSymbolGroup *m_symbolGroup,
+ unsigned long start,
+ unsigned long count,
+ SymbolParameterVector *vec,
+ std::string *errorMessage);
+
+private:
+ inline AbstractSymbolGroupNode *findI(const std::string &iname) const;
+ static bool getSymbolParameters(CIDebugSymbolGroup *m_symbolGroup,
+ SymbolParameterVector *vec,
+ std::string *errorMessage);
+
+ CIDebugSymbolGroup * const m_symbolGroup;
+ const unsigned m_frame;
+ const ULONG m_threadId;
+ SymbolGroupNode *m_root;
+};
+
+#endif // SYMBOLGROUP_H
diff --git a/src/libs/qtcreatorcdbext/symbolgroupnode.cpp b/src/libs/qtcreatorcdbext/symbolgroupnode.cpp
new file mode 100644
index 0000000000..64755c50e3
--- /dev/null
+++ b/src/libs/qtcreatorcdbext/symbolgroupnode.cpp
@@ -0,0 +1,1188 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "symbolgroupnode.h"
+#include "symbolgroup.h"
+#include "symbolgroupvalue.h"
+#include "stringutils.h"
+#include "base64.h"
+#include "containers.h"
+
+#include <algorithm>
+
+typedef std::vector<int>::size_type VectorIndexType;
+typedef std::vector<std::string> StringVector;
+
+enum { BufSize = 2048 };
+
+static inline void indentStream(std::ostream &str, unsigned depth)
+{
+ for (unsigned d = 0; d < depth; d++)
+ str << " ";
+}
+
+static inline void debugNodeFlags(std::ostream &str, unsigned f)
+{
+ if (!f)
+ return;
+ str << " node-flags=" << f;
+ if (f & SymbolGroupNode::Uninitialized)
+ str << " UNINITIALIZED";
+ if (f & SymbolGroupNode::SimpleDumperNotApplicable)
+ str << " DumperNotApplicable";
+ if (f & SymbolGroupNode::SimpleDumperOk)
+ str << " DumperOk";
+ if (f & SymbolGroupNode::SimpleDumperFailed)
+ str << " DumperFailed";
+ if (f & SymbolGroupNode::ExpandedByDumper)
+ str << " ExpandedByDumper";
+ if (f & SymbolGroupNode::AdditionalSymbol)
+ str << " AdditionalSymbol";
+ if (f & SymbolGroupNode::Obscured)
+ str << " Obscured";
+ if (f & SymbolGroupNode::ComplexDumperOk)
+ str << " ComplexDumperOk";
+ str << ' ';
+}
+
+// Some helper to conveniently dump flags to a stream
+struct DebugNodeFlags
+{
+ DebugNodeFlags(unsigned f) : m_f(f) {}
+ const unsigned m_f;
+};
+
+inline std::ostream &operator<<(std::ostream &str, const DebugNodeFlags &f)
+{
+ debugNodeFlags(str, f.m_f);
+ return str;
+}
+
+// -------------- AbstractSymbolGroupNode
+
+AbstractSymbolGroupNode::AbstractSymbolGroupNode(const std::string &name,
+ const std::string &iname) :
+ m_name(name), m_iname(iname), m_parent(0), m_flags(0)
+{
+}
+
+AbstractSymbolGroupNode::~AbstractSymbolGroupNode()
+{
+}
+
+std::string AbstractSymbolGroupNode::absoluteFullIName() const
+{
+ std::string rc = iName();
+ for (const AbstractSymbolGroupNode *p = m_parent; p; p = p->m_parent) {
+ rc.insert(0, 1, SymbolGroupNodeVisitor::iNamePathSeparator);
+ rc.insert(0, p->iName());
+ }
+ return rc;
+}
+
+AbstractSymbolGroupNode *AbstractSymbolGroupNode::childAt(unsigned i) const
+{
+ const AbstractSymbolGroupNodePtrVector &c = children();
+ return i < c.size() ? c.at(i) : static_cast<AbstractSymbolGroupNode *>(0);
+}
+
+unsigned AbstractSymbolGroupNode::indexByIName(const char *n) const
+{
+ const AbstractSymbolGroupNodePtrVector &c = children();
+ const VectorIndexType size = c.size();
+ for (VectorIndexType i = 0; i < size; i++)
+ if ( c.at(i)->iName() == n )
+ return unsigned(i);
+ return unsigned(-1);
+}
+
+AbstractSymbolGroupNode *AbstractSymbolGroupNode::childByIName(const char *n) const
+{
+ const unsigned index = indexByIName(n);
+ if (index != unsigned(-1))
+ return children().at(index);
+ return 0;
+}
+
+bool AbstractSymbolGroupNode::accept(SymbolGroupNodeVisitor &visitor,
+ const std::string &parentIname,
+ unsigned child, unsigned depth)
+{
+ // If we happen to be the root node, just skip over
+ const bool invisibleRoot = !m_parent;
+ const unsigned childDepth = invisibleRoot ? 0 : depth + 1;
+
+ std::string fullIname = parentIname;
+ if (!fullIname.empty())
+ fullIname.push_back(SymbolGroupNodeVisitor::iNamePathSeparator);
+ fullIname += m_iname;
+
+ const SymbolGroupNodeVisitor::VisitResult vr =
+ invisibleRoot ? SymbolGroupNodeVisitor::VisitContinue :
+ visitor.visit(this, fullIname, child, depth);
+ switch (vr) {
+ case SymbolGroupNodeVisitor::VisitStop:
+ return true;
+ case SymbolGroupNodeVisitor::VisitSkipChildren:
+ break;
+ case SymbolGroupNodeVisitor::VisitContinue: {
+ const AbstractSymbolGroupNodePtrVector &c = children();
+ const unsigned childCount = unsigned(c.size());
+ for (unsigned i = 0; i < childCount; i++)
+ if (c.at(i)->accept(visitor, fullIname, i, childDepth))
+ return true;
+ if (!invisibleRoot)
+ visitor.childrenVisited(this, depth);
+ }
+ break;
+ }
+ return false;
+}
+
+void AbstractSymbolGroupNode::debug(std::ostream &str, const std::string &visitingFullIname,
+ unsigned /* verbosity */, unsigned depth) const
+{
+ indentStream(str, 2 * depth);
+ str << "AbstractSymbolGroupNode " << visitingFullIname
+ << " with " << children().size() << " children\n";
+}
+
+void AbstractSymbolGroupNode::dumpBasicData(std::ostream &str, const std::string &aName,
+ const std::string &aFullIname,
+ const std::string &type /* = "" */,
+ const std::string &expression /* = "" */)
+{
+ str << "iname=\"" << aFullIname << "\",name=\"" << aName << '"';
+ if (!type.empty())
+ str << ",type=\"" << type << '"';
+ if (!expression.empty())
+ str << ",exp=\"" << expression << '"';
+}
+
+void AbstractSymbolGroupNode::setParent(AbstractSymbolGroupNode *n)
+{
+ if (m_parent)
+ dprintf("Internal error: Attempt to change non-null parent of %s", m_name.c_str());
+ m_parent = n;
+}
+
+// -------- BaseSymbolGroupNode
+BaseSymbolGroupNode::BaseSymbolGroupNode(const std::string &name, const std::string &iname) :
+ AbstractSymbolGroupNode(name, iname)
+{
+}
+
+BaseSymbolGroupNode::~BaseSymbolGroupNode()
+{
+ removeChildren();
+}
+
+void BaseSymbolGroupNode::removeChildren()
+{
+ if (!m_children.empty()) {
+ const AbstractSymbolGroupNodePtrVectorIterator end = m_children.end();
+ for (AbstractSymbolGroupNodePtrVectorIterator it = m_children.begin(); it != end; ++it)
+ delete *it;
+ m_children.clear();
+ }
+}
+
+void BaseSymbolGroupNode::addChild(AbstractSymbolGroupNode *c)
+{
+ c->setParent(this);
+ m_children.push_back(c);
+}
+
+// ----------- Helpers: Stream DEBUG_SYMBOL_PARAMETERS
+
+std::ostream &operator<<(std::ostream &str, const DEBUG_SYMBOL_PARAMETERS &parameters)
+{
+ str << "parent=";
+ if (parameters.ParentSymbol == DEBUG_ANY_ID) {
+ str << "DEBUG_ANY_ID";
+ } else {
+ str << parameters.ParentSymbol ;
+ }
+ if (parameters.Flags != 0 && parameters.Flags != 1)
+ str << " flags=" << parameters.Flags;
+ // Detailed flags:
+ if (parameters.Flags & DEBUG_SYMBOL_EXPANDED)
+ str << " EXPANDED";
+ if (parameters.Flags & DEBUG_SYMBOL_READ_ONLY)
+ str << " READONLY";
+ if (parameters.Flags & DEBUG_SYMBOL_IS_ARRAY)
+ str << " ARRAY";
+ if (parameters.Flags & DEBUG_SYMBOL_IS_FLOAT)
+ str << " FLOAT";
+ if (parameters.Flags & DEBUG_SYMBOL_IS_ARGUMENT)
+ str << " ARGUMENT";
+ if (parameters.Flags & DEBUG_SYMBOL_IS_LOCAL)
+ str << " LOCAL";
+ str << " typeId=" << parameters.TypeId;
+ if (parameters.SubElements)
+ str << " subElements=" << parameters.SubElements;
+ return str;
+}
+
+// --------------- DumpParameters
+DumpParameters::DumpParameters() : dumpFlags(0)
+{
+}
+
+// typeformats: decode hex-encoded name, value pairs:
+// '414A=2,...' -> map of "AB:2".
+DumpParameters::FormatMap DumpParameters::decodeFormatArgument(const std::string &f)
+{
+ FormatMap rc;
+ const std::string::size_type size = f.size();
+ // Split 'hexname=4,'
+ for (std::string::size_type pos = 0; pos < size ; ) {
+ // Cut out key
+ const std::string::size_type equalsPos = f.find('=', pos);
+ if (equalsPos == std::string::npos)
+ return rc;
+ const std::string name = stringFromHex(f.c_str() + pos, f.c_str() + equalsPos);
+ // Search for number
+ const std::string::size_type numberPos = equalsPos + 1;
+ std::string::size_type nextPos = f.find(',', numberPos);
+ if (nextPos == std::string::npos)
+ nextPos = size;
+ int format;
+ if (!integerFromString(f.substr(numberPos, nextPos - numberPos), &format))
+ return rc;
+ rc.insert(FormatMap::value_type(name, format));
+ pos = nextPos + 1;
+ }
+ return rc;
+}
+
+int DumpParameters::format(const std::string &type, const std::string &iname) const
+{
+ if (!individualFormats.empty()) {
+ const FormatMap::const_iterator iit = individualFormats.find(iname);
+ if (iit != individualFormats.end())
+ return iit->second;
+ }
+ if (!typeFormats.empty()) {
+ const FormatMap::const_iterator tit = typeFormats.find(type);
+ if (tit != typeFormats.end())
+ return tit->second;
+ }
+ return -1;
+}
+
+enum PointerFormats // Watch data pointer format requests
+{
+ FormatAuto = 0,
+ FormatLatin1String = 1,
+ FormatUtf8String = 2,
+ FormatUtf16String = 3,
+ FormatUcs4String = 4
+};
+
+enum DumpEncoding // WatchData encoding of GDBMI values
+{
+ DumpEncodingAscii = 0,
+ DumpEncodingBase64 = 1,
+ DumpEncodingBase64_Utf16 = 2,
+ DumpEncodingBase64_Ucs4 = 3,
+ DumpEncodingHex_Latin1 = 6,
+ DumpEncodingHex_Utf16 = 7,
+ DumpEncodingHex_Ucs4_LittleEndian = 8,
+ DumpEncodingHex_Utf8_LittleEndian = 9,
+ DumpEncodingHex_Ucs4_BigEndian = 10,
+ DumpEncodingHex_Utf16_BigEndian = 11,
+ DumpEncodingHex_Utf16_LittleEndian = 12
+};
+
+/* Recode arrays/pointers of char*, wchar_t according to users
+ * sepcification. Handles char formats for 'char *', '0x834478 "hallo.."'
+ * and 'wchar_t *', '0x834478 "hallo.."'.
+ * This is done by retrieving the address and the length (in characters)
+ * of the CDB output, converting it to memory size, fetching the data
+ * from memory, zero-terminating and recoding it using the encoding
+ * defined in watchutils.cpp.
+ * As a special case, if there is no user-defined format and the
+ * CDB output contains '?' indicating non-printable characters,
+ * append a hex dump of the memory (auto-format). */
+
+bool DumpParameters::recode(const std::string &type,
+ const std::string &iname,
+ const SymbolGroupValueContext &ctx,
+ std::wstring *value, int *encoding) const
+{
+ // We basically handle char formats for 'char *', '0x834478 "hallo.."'
+ // and 'wchar_t *', '0x834478 "hallo.."'
+ // Determine address and length from the pointer value output,
+ // read the raw memory and recode if that is possible.
+ if (type.empty() || type.at(type.size() - 1) != '*')
+ return false;
+ const int newFormat = format(type, iname);
+ if (value->compare(0, 2, L"0x"))
+ return false;
+ const std::wstring::size_type quote1 = value->find(L'"', 2);
+ if (quote1 == std::wstring::npos)
+ return false;
+ // The user did not specify any format, still, there are '?'
+ // (indicating non-printable) in what the debugger prints. In that case,
+ // append a hex dump to the normal output. If there are no '?'-> all happy.
+ if (newFormat < FormatLatin1String && value->find(L'?', quote1 + 1) == std::wstring::npos)
+ return false;
+ const std::wstring::size_type quote2 = value->find(L'"', quote1 + 1);
+ if (quote2 == std::wstring::npos)
+ return false;
+ std::wstring::size_type length = quote2 - quote1 - 1;
+ if (!length)
+ return false;
+ // Get address from value
+ ULONG64 address = 0;
+ if (!integerFromWString(value->substr(0, quote1 - 1), &address) || !address)
+ return false;
+ // Get real size if this is for example a wchar_t *.
+ const unsigned elementSize = SymbolGroupValue::sizeOf(SymbolGroupValue::stripPointerType(type).c_str());
+ if (!elementSize)
+ return false;
+ length *= elementSize;
+ // Allocate real length + 8 bytes ('\0') for largest format (Ucs4).
+ // '\0' is not listed in the CDB output.
+ const std::wstring::size_type allocLength = length + 8;
+ unsigned char *buffer = new unsigned char[allocLength];
+ std::fill(buffer, buffer + allocLength, 0);
+ ULONG obtained = 0;
+ if (FAILED(ctx.dataspaces->ReadVirtual(address, buffer, ULONG(length), &obtained))) {
+ delete [] buffer;
+ return false;
+ }
+ // Recode raw memory
+ switch (newFormat) {
+ case FormatLatin1String:
+ *value = dataToHexW(buffer, buffer + length + 1); // Latin1 + 0
+ *encoding = DumpEncodingHex_Latin1;
+ break;
+ case FormatUtf8String:
+ *value = dataToHexW(buffer, buffer + length + 1); // UTF8 + 0
+ *encoding = DumpEncodingHex_Utf8_LittleEndian;
+ break;
+ case FormatUtf16String: // Paranoia: make sure buffer is terminated at 2 byte borders
+ if (length % 2) {
+ length &= ~1;
+ buffer[length] = '\0';
+ buffer[length + 1] = '\0';
+ }
+ *value = base64EncodeToWString(buffer, length + 2);
+ *encoding = DumpEncodingBase64_Utf16;
+ break;
+ case FormatUcs4String: // Paranoia: make sure buffer is terminated at 4 byte borders
+ if (length % 4) {
+ length &= ~3;
+ std::fill(buffer + length, buffer + length + 4, 0);
+ }
+ *value = dataToHexW(buffer, buffer + length + 2); // UTF16 + 0
+ *encoding = DumpEncodingHex_Ucs4_LittleEndian;
+ break;
+ default: // See above, append hex dump
+ value->push_back(' ');
+ value->append(dataToReadableHexW(buffer, buffer + length));
+ *encoding = DumpEncodingAscii;
+ break;
+ }
+ delete [] buffer;
+ return true;
+}
+
+// ------- SymbolGroupNode
+
+SymbolGroupNode::SymbolGroupNode(SymbolGroup *symbolGroup,
+ ULONG index,
+ const std::string &name,
+ const std::string &iname) :
+ BaseSymbolGroupNode(name, iname),
+ m_symbolGroup(symbolGroup),
+ m_index(index), m_dumperType(-1), m_dumperContainerSize(-1)
+{
+ memset(&m_parameters, 0, sizeof(DEBUG_SYMBOL_PARAMETERS));
+ m_parameters.ParentSymbol = DEBUG_ANY_ID;
+}
+
+const SymbolGroupNode *SymbolGroupNode::symbolGroupNodeParent() const
+{
+ if (const AbstractSymbolGroupNode *p = parent())
+ return p->asSymbolGroupNode();
+ return 0;
+}
+
+bool SymbolGroupNode::isArrayElement() const
+{
+ if (const SymbolGroupNode *p = symbolGroupNodeParent())
+ return (p->m_parameters.Flags & DEBUG_SYMBOL_IS_ARRAY) != 0;
+ return false;
+}
+
+// Notify about expansion of a node:
+// Adapt our index and those of our children if we are behind it.
+// Return true if a modification was required to be able to terminate the
+// recursion.
+bool SymbolGroupNode::notifyExpanded(ULONG index, ULONG insertedCount)
+{
+ typedef AbstractSymbolGroupNodePtrVector::const_reverse_iterator ReverseIt;
+ // Looping backwards over the children. If a subtree has no modifications,
+ // (meaning all other indexes are smaller) we can stop.
+ const ReverseIt rend = children().rend();
+ for (ReverseIt it = children().rbegin(); it != rend; ++it) {
+ if (SymbolGroupNode *c = (*it)->asSymbolGroupNode())
+ if (!c->notifyExpanded(index, insertedCount))
+ return false;
+ }
+
+ // Correct our own + parent index if applicable.
+ if (m_index == DEBUG_ANY_ID || m_index < index)
+ return false;
+
+ m_index += insertedCount;
+ if (m_parameters.ParentSymbol != DEBUG_ANY_ID && m_parameters.ParentSymbol >= index)
+ m_parameters.ParentSymbol += insertedCount;
+ return true;
+}
+
+// Fix names: fix complicated template base names
+static inline void fixName(std::string *name)
+{
+ // Long template base classes 'std::tree_base<Key....>' -> 'std::tree<>'
+ // for nice display
+ const std::string::size_type templatePos = name->find('<');
+ if (templatePos != std::string::npos) {
+ name->erase(templatePos + 1, name->size() - templatePos - 1);
+ name->push_back('>');
+ }
+}
+
+// Fix inames: arrays and long, complicated template base names
+static inline void fixIname(unsigned &id, std::string *iname)
+{
+ // Fix array iname "[0]" -> "0" for sorting to work correctly
+ if (!iname->empty() && iname->at(0) == '[') {
+ const std::string::size_type last = iname->size() - 1;
+ if (iname->at(last) == ']') {
+ iname->erase(last, 1);
+ iname->erase(0, 1);
+ return;
+ }
+ }
+ // Long template base classes 'std::tree_base<Key....' -> 'tree@t1',
+ // usable as identifier and command line parameter
+ const std::string::size_type templatePos = iname->find('<');
+ if (templatePos != std::string::npos) {
+ iname->erase(templatePos, iname->size() - templatePos);
+ if (iname->compare(0, 5, "std::") == 0)
+ iname->erase(0, 5);
+ iname->append("@t");
+ iname->append(toString(id++));
+ }
+}
+
+// Fix up names and inames
+static inline void fixNames(bool isTopLevel, StringVector *names, StringVector *inames)
+{
+ if (names->empty())
+ return;
+ unsigned unnamedId = 1;
+ unsigned templateId = 1;
+ /* 1) Fix name="__formal", which occurs when someone writes "void foo(int /* x * /)..."
+ * 2) Fix array inames for sorting: "[6]" -> name="[6]",iname="6"
+ * 3) For toplevels: Fix shadowed variables in the order the debugger expects them:
+ \code
+ int x; // Occurrence (1), should be reported as name="x <shadowed 1>"/iname="x#1"
+ if (true) {
+ int x = 5; (2) // Occurrence (2), should be reported as name="x"/iname="x"
+ }
+ \endcode */
+ StringVector::iterator nameIt = names->begin();
+ const StringVector::iterator namesEnd = names->end();
+ for (StringVector::iterator iNameIt = inames->begin(); nameIt != namesEnd ; ++nameIt, ++iNameIt) {
+ std::string &name = *nameIt;
+ std::string &iname = *iNameIt;
+ if (name.empty() || name == "__formal") {
+ const std::string number = toString(unnamedId++);
+ name = "<unnamed " + number + '>';
+ iname = "unnamed#" + number;
+ } else {
+ fixName(&name);
+ fixIname(templateId, &iname);
+ }
+ if (isTopLevel) {
+ if (const StringVector::size_type shadowCount = std::count(nameIt + 1, namesEnd, name)) {
+ const std::string number = toString(shadowCount);
+ name += " <shadowed ";
+ name += number;
+ name += '>';
+ iname += '#';
+ iname += number;
+ }
+ }
+ }
+}
+
+// Index: Index of symbol, parameterOffset: Looking only at a part of the symbol array, offset
+void SymbolGroupNode::parseParameters(VectorIndexType index,
+ VectorIndexType parameterOffset,
+ const SymbolGroup::SymbolParameterVector &vec)
+{
+ static char buf[BufSize];
+ ULONG obtainedSize;
+
+ const bool isTopLevel = index == DEBUG_ANY_ID;
+ if (isTopLevel) {
+ m_parameters.Flags |= DEBUG_SYMBOL_EXPANDED;
+ } else {
+ m_parameters = vec.at(index - parameterOffset);
+ if (m_parameters.SubElements == 0 || !(m_parameters.Flags & DEBUG_SYMBOL_EXPANDED))
+ return; // No children
+ }
+ if (m_parameters.SubElements > 1)
+ reserveChildren(m_parameters.SubElements);
+
+ const VectorIndexType size = vec.size();
+ // Scan the top level elements
+ StringVector names;
+ names.reserve(size);
+ // Pass 1) Determine names. We need the complete set first in order to do some corrections.
+ const VectorIndexType startIndex = isTopLevel ? 0 : index + 1;
+ for (VectorIndexType pos = startIndex - parameterOffset; pos < size ; pos++ ) {
+ if (vec.at(pos).ParentSymbol == index) {
+ const VectorIndexType symbolGroupIndex = pos + parameterOffset;
+ if (FAILED(m_symbolGroup->debugSymbolGroup()->GetSymbolName(ULONG(symbolGroupIndex), buf, BufSize, &obtainedSize)))
+ buf[0] = '\0';
+ names.push_back(std::string(buf));
+ }
+ }
+ // 2) Fix names
+ StringVector inames = names;
+ fixNames(isTopLevel, &names, &inames);
+ // Pass 3): Add nodes with fixed names
+ StringVector::size_type nameIndex = 0;
+ for (VectorIndexType pos = startIndex - parameterOffset; pos < size ; pos++ ) {
+ if (vec.at(pos).ParentSymbol == index) {
+ const VectorIndexType symbolGroupIndex = pos + parameterOffset;
+ SymbolGroupNode *child = new SymbolGroupNode(m_symbolGroup,
+ ULONG(symbolGroupIndex),
+ names.at(nameIndex),
+ inames.at(nameIndex));
+ child->parseParameters(symbolGroupIndex, parameterOffset, vec);
+ addChild(child);
+ nameIndex++;
+ }
+ }
+ if (isTopLevel)
+ m_parameters.SubElements = ULONG(children().size());
+}
+
+SymbolGroupNode *SymbolGroupNode::create(SymbolGroup *sg, const std::string &name, const SymbolGroup::SymbolParameterVector &vec)
+{
+ SymbolGroupNode *rc = new SymbolGroupNode(sg, DEBUG_ANY_ID, name, name);
+ rc->parseParameters(DEBUG_ANY_ID, 0, vec);
+ return rc;
+}
+
+// Fix some oddities in CDB values
+
+static inline bool isHexDigit(wchar_t c)
+{
+ return (c >= L'0' && c <= L'9') || (c >= L'a' && c <= L'f') || (c >= L'A' && c <= L'F');
+}
+
+static void fixValue(const std::string &type, std::wstring *value)
+{
+ // Pointers/Unsigned integers: fix '0x00000000`00000AD bla' ... to "0xAD bla"
+ const bool isHexNumber = value->size() > 3 && value->compare(0, 2, L"0x") == 0 && isHexDigit(value->at(2));
+ if (isHexNumber) {
+ // Remove dumb 64bit separator
+ if (value->size() > 10 && value->at(10) == L'`')
+ value->erase(10, 1);
+ const std::string::size_type firstNonNullDigit = value->find_first_not_of(L"0", 2);
+ // No on-null digits: plain null ptr.
+ if (firstNonNullDigit == std::string::npos || value->at(firstNonNullDigit) == ' ') {
+ *value = L"0x0";
+ } else {
+ // Strip
+ if (firstNonNullDigit > 2)
+ value->erase(2, firstNonNullDigit - 2);
+ }
+ }
+
+ // Pointers: fix '0x00000000`00000AD class bla' ... to "0xAD", but leave
+ // 'const char *' values as is ('0x00000000`00000AD "hallo").
+ if (!type.empty() && type.at(type.size() - 1) == L'*') {
+ // Strip ' Class bla"
+ std::wstring::size_type classPos = value->find(L" struct", 2);
+ if (classPos == std::string::npos)
+ classPos = value->find(L" class", 2);
+ if (classPos != std::string::npos)
+ value->erase(classPos, value->size() - classPos);
+ return;
+ }
+
+ // unsigned hex ints that are not pointers: Convert to decimal as not to confuse watch model:
+ if (isHexNumber) {
+ ULONG64 uv;
+ std::wistringstream str(*value);
+ str >> std::hex >> uv;
+ if (!str.fail()) {
+ *value = toWString(uv);
+ return;
+ }
+ }
+
+ // Integers: fix '0n10' -> '10'
+ if (value->size() >= 3 && value->compare(0, 2, L"0n") == 0
+ && (isdigit(value->at(2)) || value->at(2) == L'-')) {
+ value->erase(0, 2);
+ return;
+ }
+ // Fix long class names on std containers 'class std::tree<...>' -> 'class std::tree<>'
+ if (value->compare(0, 6, L"class ") == 0 || value->compare(0, 7, L"struct ") == 0) {
+ const std::string::size_type openTemplate = value->find(L'<');
+ if (openTemplate != std::string::npos) {
+ value->erase(openTemplate + 1, value->size() - openTemplate - 2);
+ return;
+ }
+ }
+}
+
+// Check for ASCII-encode-able stuff. Plain characters + tabs at the most, no newline.
+static bool isSevenBitClean(const wchar_t *buf, size_t size)
+{
+ const wchar_t *bufEnd = buf + size;
+ for (const wchar_t *bufPtr = buf; bufPtr < bufEnd; bufPtr++) {
+ const wchar_t c = *bufPtr;
+ if (c > 127 || (c < 32 && c != 9))
+ return false;
+ }
+ return true;
+}
+
+std::string SymbolGroupNode::type() const
+{
+ static char buf[BufSize];
+ const HRESULT hr = m_symbolGroup->debugSymbolGroup()->GetSymbolTypeName(m_index, buf, BufSize, NULL);
+ return SUCCEEDED(hr) ? std::string(buf) : std::string();
+}
+
+unsigned SymbolGroupNode::size() const
+{
+ DEBUG_SYMBOL_ENTRY entry;
+ if (SUCCEEDED(m_symbolGroup->debugSymbolGroup()->GetSymbolEntryInformation(m_index, &entry)))
+ return entry.Size;
+ return 0;
+}
+
+ULONG64 SymbolGroupNode::address() const
+{
+ ULONG64 address = 0;
+ const HRESULT hr = m_symbolGroup->debugSymbolGroup()->GetSymbolOffset(m_index, &address);
+ if (SUCCEEDED(hr))
+ return address;
+ return 0;
+}
+
+std::wstring SymbolGroupNode::symbolGroupRawValue() const
+{
+ // Determine size and return allocated buffer
+ const ULONG maxValueSize = 262144;
+ ULONG obtainedSize = 0;
+ HRESULT hr = m_symbolGroup->debugSymbolGroup()->GetSymbolValueTextWide(m_index, NULL, maxValueSize, &obtainedSize);
+ if (FAILED(hr))
+ return std::wstring();
+ if (obtainedSize > maxValueSize)
+ obtainedSize = maxValueSize;
+ wchar_t *buffer = new wchar_t[obtainedSize];
+ hr = m_symbolGroup->debugSymbolGroup()->GetSymbolValueTextWide(m_index, buffer, obtainedSize, &obtainedSize);
+ if (FAILED(hr)) // Whoops, should not happen
+ buffer[0] = 0;
+ const std::wstring rc(buffer);
+ delete [] buffer;
+ return rc;
+}
+
+std::wstring SymbolGroupNode::symbolGroupFixedValue() const
+{
+ std::wstring value = symbolGroupRawValue();
+ fixValue(type(), &value);
+ return value;
+}
+
+// A quick check if symbol is valid by checking for inaccessible value
+bool SymbolGroupNode::isMemoryAccessible() const
+{
+ static const char notAccessibleValueC[] = "<Memory access error>";
+ char buffer[sizeof(notAccessibleValueC)];
+ ULONG obtained = 0;
+ if (FAILED(symbolGroup()->debugSymbolGroup()->GetSymbolValueText(m_index, buffer, sizeof(notAccessibleValueC), &obtained)))
+ return false;
+ if (obtained < sizeof(notAccessibleValueC))
+ return true;
+ return strcmp(buffer, notAccessibleValueC) != 0;
+}
+
+// Complex dumpers: Get container/fake children
+void SymbolGroupNode::runComplexDumpers(const SymbolGroupValueContext &ctx)
+{
+ if (symbolGroupDebug)
+ DebugPrint() << "SymbolGroupNode::runComplexDumpers " << name() << '/'
+ << absoluteFullIName() << ' ' << m_index << DebugNodeFlags(flags());
+
+ if (m_dumperContainerSize <= 0 || (testFlags(ComplexDumperOk) || !testFlags(SimpleDumperOk)))
+ return;
+ addFlags(ComplexDumperOk);
+ const AbstractSymbolGroupNodePtrVector ctChildren =
+ containerChildren(this, m_dumperType, m_dumperContainerSize, ctx);
+ m_dumperContainerSize = int(ctChildren.size()); // Just in case...
+ if (ctChildren.empty())
+ return;
+
+ clearFlags(ExpandedByDumper);
+ // Mark current children as obscured. We cannot show both currently
+ // as this would upset the numerical sorting of the watch model
+ AbstractSymbolGroupNodePtrVectorConstIterator cend = children().end();
+ for (AbstractSymbolGroupNodePtrVectorConstIterator it = children().begin(); it != cend; ++it)
+ (*it)->addFlags(Obscured);
+ // Add children and mark them as referenced by us.
+ cend = ctChildren.end();
+ for (AbstractSymbolGroupNodePtrVectorConstIterator it = ctChildren.begin(); it != cend; ++it)
+ addChild(*it);
+}
+
+// Run dumpers, format simple in-line dumper value and retrieve fake children
+bool SymbolGroupNode::runSimpleDumpers(const SymbolGroupValueContext &ctx)
+{
+ if (symbolGroupDebug)
+ DebugPrint() << "SymbolGroupNode::runSimpleDumpers " << name() << '/'
+ << absoluteFullIName() << ' ' << m_index << DebugNodeFlags(flags());
+ if (testFlags(Uninitialized))
+ return false;
+ if (testFlags(SimpleDumperOk))
+ return true;
+ if (testFlags(SimpleDumperMask))
+ return false;
+ addFlags(dumpSimpleType(this , ctx, &m_dumperValue,
+ &m_dumperType, &m_dumperContainerSize));
+ if (symbolGroupDebug)
+ DebugPrint() << "-> '" << wStringToString(m_dumperValue) << "' Type="
+ << m_dumperType << ' ' << DebugNodeFlags(flags());
+ return testFlags(SimpleDumperOk);
+}
+
+std::wstring SymbolGroupNode::simpleDumpValue(const SymbolGroupValueContext &ctx)
+{
+ if (testFlags(Uninitialized))
+ return L"<not in scope>";
+ if (runSimpleDumpers(ctx))
+ return m_dumperValue;
+ return symbolGroupFixedValue();
+}
+
+void SymbolGroupNode::dump(std::ostream &str, const std::string &visitingFullIname,
+ const DumpParameters &p, const SymbolGroupValueContext &ctx)
+{
+ dumpNode(str, name(), visitingFullIname, p, ctx);
+}
+
+void SymbolGroupNode::dumpNode(std::ostream &str,
+ const std::string &aName,
+ const std::string &aFullIName,
+ const DumpParameters &dumpParameters,
+ const SymbolGroupValueContext &ctx)
+{
+ const std::string t = type();
+ SymbolGroupNode::dumpBasicData(str, aName, aFullIName, t, aFullIName);
+
+ if (const ULONG64 addr = address())
+ str << ",addr=\"" << std::hex << std::showbase << addr << std::noshowbase << std::dec
+ << '"';
+
+ const bool uninitialized = flags() & Uninitialized;
+ bool valueEditable = !uninitialized;
+ bool valueEnabled = !uninitialized;
+
+ // Shall it be recoded?
+ std::wstring value = simpleDumpValue(ctx);
+ int encoding = 0;
+ if (dumpParameters.recode(t, aFullIName, ctx, &value, &encoding)) {
+ str << ",valueencoded=\"" << encoding
+ << "\",value=\"" << gdbmiWStringFormat(value) <<'"';
+ } else { // As is: ASCII or base64?
+ if (isSevenBitClean(value.c_str(), value.size())) {
+ str << ",valueencoded=\"" << DumpEncodingAscii << "\",value=\""
+ << gdbmiWStringFormat(value) << '"';
+ } else {
+ str << ",valueencoded=\"" << DumpEncodingBase64_Utf16 << "\",value=\"";
+ base64Encode(str, reinterpret_cast<const unsigned char *>(value.c_str()), value.size() * sizeof(wchar_t));
+ str << '"';
+ }
+ }
+ // Children: Dump all known non-obscured or subelements
+ unsigned childCountGuess = 0;
+ if (!uninitialized) {
+ if (m_dumperContainerSize > 0) {
+ childCountGuess = m_dumperContainerSize; // See Obscured handling
+ } else {
+ if (children().empty()) {
+ childCountGuess = m_parameters.SubElements; // Guess
+ } else {
+ childCountGuess = unsigned(children().size());
+ }
+ }
+ }
+ // No children..suppose we are editable and enabled
+ if (childCountGuess != 0)
+ valueEditable = false;
+ str << ",valueenabled=\"" << (valueEnabled ? "true" : "false") << '"'
+ << ",valueeditable=\"" << (valueEditable ? "true" : "false") << '"'
+ << ",numchild=\"" << childCountGuess << '"';
+}
+
+void SymbolGroupNode::debug(std::ostream &str,
+ const std::string &visitingFullIname,
+ unsigned verbosity, unsigned depth) const
+{
+ indentStream(str, depth);
+ const std::string fullIname = absoluteFullIName();
+ str << "AbsIname=" << fullIname << '"';
+ if (fullIname != visitingFullIname)
+ str << ",VisitIname=\"" <<visitingFullIname;
+ str << "\",index=" << m_index;
+ if (const VectorIndexType childCount = children().size())
+ str << ", Children=" << childCount;
+ str << ' ' << m_parameters << DebugNodeFlags(flags());
+ if (verbosity) {
+ str << ",name=\"" << name() << "\", Address=0x" << std::hex << address() << std::dec
+ << " Type=\"" << type() << '"';
+ if (m_dumperType >= 0) {
+ str << " ,dumperType=" << m_dumperType;
+ if (m_dumperType & KT_Qt_Type)
+ str << " qt";
+ if (m_dumperType & KT_STL_Type)
+ str << " STL";
+ if (m_dumperType & KT_ContainerType)
+ str << " container(" << m_dumperContainerSize << ')';
+ }
+ if (!testFlags(Uninitialized))
+ str << " Value=\"" << gdbmiWStringFormat(symbolGroupRawValue()) << '"';
+ str << '\n'; // Potentially multiline
+ }
+ str << '\n';
+}
+
+static inline std::string msgCannotCast(const std::string &nodeName,
+ const std::string &fromType,
+ const std::string &toType,
+ const std::string &why)
+{
+ std::ostringstream str;
+ str << "Cannot cast node '" << nodeName << "' from '" << fromType
+ << "' to '" << toType << "': " << why;
+ return str.str();
+}
+
+// Expand!
+bool SymbolGroupNode::expand(std::string *errorMessage)
+{
+ if (symbolGroupDebug)
+ DebugPrint() << "SymbolGroupNode::expand " << name()
+ <<'/' << absoluteFullIName() << ' '
+ << m_index << DebugNodeFlags(flags());
+ if (isExpanded()) {
+ // Clear the flag indication dumper expansion on a second, explicit request
+ clearFlags(ExpandedByDumper);
+ return true;
+ }
+ if (!canExpand()) {
+ *errorMessage = "No subelements to expand in node: " + absoluteFullIName();
+ return false;
+ }
+ if (flags() & Uninitialized) {
+ *errorMessage = "Refusing to expand uninitialized node: " + absoluteFullIName();
+ return false;
+ }
+
+ const HRESULT hr = m_symbolGroup->debugSymbolGroup()->ExpandSymbol(m_index, TRUE);
+
+ if (FAILED(hr)) {
+ *errorMessage = msgDebugEngineComFailed("ExpandSymbol", hr);
+ return false;
+ }
+ SymbolGroup::SymbolParameterVector parameters;
+ // Retrieve parameters (including self, re-retrieve symbol parameters to get new 'expanded' flag
+ // and corrected SubElement count (might be estimate))
+ if (!SymbolGroup::getSymbolParameters(m_symbolGroup->debugSymbolGroup(),
+ m_index, m_parameters.SubElements + 1,
+ &parameters, errorMessage))
+ return false;
+ // Before inserting children, correct indexes on whole group
+ m_symbolGroup->root()->notifyExpanded(m_index + 1, parameters.at(0).SubElements);
+ // Parse parameters, correct our own) and create child nodes.
+ parseParameters(m_index, m_index, parameters);
+ return true;
+}
+
+bool SymbolGroupNode::expandRunComplexDumpers(const SymbolGroupValueContext &ctx,
+ std::string *errorMessage)
+{
+ if (isExpanded() || testFlags(ComplexDumperOk))
+ return true;
+ if (!expand(errorMessage))
+ return false;
+ // Run simple dumpers to obtain type and run complex dumpers
+ if (runSimpleDumpers(ctx) && testFlags(SimpleDumperOk))
+ runComplexDumpers(ctx);
+ return true;
+}
+
+bool SymbolGroupNode::typeCast(const std::string &desiredType, std::string *errorMessage)
+{
+ const std::string fromType = type();
+ if (fromType == desiredType)
+ return true;
+ if (isExpanded()) {
+ *errorMessage = msgCannotCast(absoluteFullIName(), fromType, desiredType, "Already expanded");
+ return false;
+ }
+ HRESULT hr = m_symbolGroup->debugSymbolGroup()->OutputAsType(m_index, desiredType.c_str());
+ if (FAILED(hr)) {
+ *errorMessage = msgCannotCast(absoluteFullIName(), fromType, desiredType, msgDebugEngineComFailed("OutputAsType", hr));
+ return false;
+ }
+ hr = m_symbolGroup->debugSymbolGroup()->GetSymbolParameters(m_index, 1, &m_parameters);
+ if (FAILED(hr)) { // Should never fail
+ *errorMessage = msgCannotCast(absoluteFullIName(), fromType, desiredType, msgDebugEngineComFailed("GetSymbolParameters", hr));
+ return false;
+ }
+ return true;
+}
+
+static inline std::string msgCannotAddSymbol(const std::string &name, const std::string &why)
+{
+ std::ostringstream str;
+ str << "Cannot add symbol '" << name << "': " << why;
+ return str.str();
+}
+
+// For root nodes, only: Add a new symbol by name
+SymbolGroupNode *SymbolGroupNode::addSymbolByName(const std::string &name,
+ const std::string &iname,
+ std::string *errorMessage)
+{
+ ULONG index = DEBUG_ANY_ID; // Append
+ HRESULT hr = m_symbolGroup->debugSymbolGroup()->AddSymbol(name.c_str(), &index);
+ if (FAILED(hr)) {
+ *errorMessage = msgCannotAddSymbol(name, msgDebugEngineComFailed("AddSymbol", hr));
+ return 0;
+ }
+ SymbolParameterVector parameters(1, DEBUG_SYMBOL_PARAMETERS());
+ hr = m_symbolGroup->debugSymbolGroup()->GetSymbolParameters(index, 1, &(*parameters.begin()));
+ if (FAILED(hr)) { // Should never fail
+ *errorMessage = msgCannotAddSymbol(name, msgDebugEngineComFailed("GetSymbolParameters", hr));
+ return 0;
+ }
+ // Paranoia: Check for cuckoo's eggs (which should not happen)
+ if (parameters.front().ParentSymbol != m_index) {
+ *errorMessage = msgCannotAddSymbol(name, "Parent id mismatch");
+ return 0;
+ }
+ SymbolGroupNode *node = new SymbolGroupNode(m_symbolGroup, index,
+ name, iname.empty() ? name : iname);
+ node->parseParameters(0, 0, parameters);
+ node->addFlags(AdditionalSymbol);
+ addChild(node);
+ return node;
+}
+
+// --------- ReferenceSymbolGroupNode
+
+// Utility returning a pair ('[42]','42') as name/iname pair
+// for a node representing an array index
+typedef std::pair<std::string, std::string> StringStringPair;
+
+static inline StringStringPair arrayIndexNameIname(int index)
+{
+ StringStringPair rc(std::string(), toString(index));
+ rc.first = std::string(1, '[');
+ rc.first += rc.second;
+ rc.first.push_back(']');
+ return rc;
+}
+
+ReferenceSymbolGroupNode::ReferenceSymbolGroupNode(const std::string &name,
+ const std::string &iname,
+ SymbolGroupNode *referencedNode) :
+ AbstractSymbolGroupNode(name, iname), m_referencedNode(referencedNode)
+{
+}
+
+// Convenience to create a node name name='[1]', iname='1' for arrays
+ReferenceSymbolGroupNode *ReferenceSymbolGroupNode::createArrayNode(int index,
+ SymbolGroupNode *referencedNode)
+{
+ const StringStringPair nameIname = arrayIndexNameIname(index);
+ return new ReferenceSymbolGroupNode(nameIname.first, nameIname.second, referencedNode);
+}
+
+void ReferenceSymbolGroupNode::dump(std::ostream &str, const std::string &visitingFullIname,
+ const DumpParameters &p, const SymbolGroupValueContext &ctx)
+{
+ // Let the referenced node dump with our iname/name
+ m_referencedNode->dumpNode(str, name(), visitingFullIname, p, ctx);
+}
+
+void ReferenceSymbolGroupNode::debug(std::ostream &str, const std::string &visitingFullIname,
+ unsigned verbosity, unsigned depth) const
+{
+ indentStream(str, 2 * depth);
+ str << "Node " << name() << '/' << visitingFullIname << " referencing\n";
+ m_referencedNode->debug(str, visitingFullIname, verbosity, depth);
+}
+
+// ---------------- MapNodeSymbolGroupNode
+MapNodeSymbolGroupNode::MapNodeSymbolGroupNode(const std::string &name,
+ const std::string &iname,
+ ULONG64 address,
+ const std::string &type,
+ AbstractSymbolGroupNode *key,
+ AbstractSymbolGroupNode *value) :
+ BaseSymbolGroupNode(name, iname), m_address(address), m_type(type)
+{
+ addChild(key);
+ addChild(value);
+}
+
+MapNodeSymbolGroupNode
+ *MapNodeSymbolGroupNode::create(int index, ULONG64 address,
+ const std::string &type,
+ SymbolGroupNode *key, SymbolGroupNode *value)
+{
+ const StringStringPair nameIname = arrayIndexNameIname(index);
+ const std::string keyName = "key";
+ ReferenceSymbolGroupNode *keyRN = new ReferenceSymbolGroupNode(keyName, keyName, key);
+ const std::string valueName = "value";
+ ReferenceSymbolGroupNode *valueRN = new ReferenceSymbolGroupNode(valueName, valueName, value);
+ return new MapNodeSymbolGroupNode(nameIname.first, nameIname.second, address, type, keyRN, valueRN);
+}
+
+void MapNodeSymbolGroupNode::dump(std::ostream &str, const std::string &visitingFullIname,
+ const DumpParameters &, const SymbolGroupValueContext &)
+{
+ SymbolGroupNode::dumpBasicData(str, name(), visitingFullIname);
+ if (m_address)
+ str << ",address=\"0x" << std::hex << m_address << '"';
+ str << ",type=\"" << m_type << "\",valueencoded=\"0\",value=\"\",valueenabled=\"false\""
+ ",valueeditable=\"false\",numchild=\"2\"";
+}
+
+void MapNodeSymbolGroupNode::debug(std::ostream &os, const std::string &visitingFullIname,
+ unsigned /* verbosity */, unsigned depth) const
+{
+ indentStream(os, 2 * depth);
+ os << "MapNode " << name() << '/' << visitingFullIname << '\n';
+}
+
+// --------- DebugSymbolGroupNodeVisitor
+
+// "local.vi" -> "local"
+std::string SymbolGroupNodeVisitor::parentIname(const std::string &iname)
+{
+ const std::string::size_type lastSep = iname.rfind(SymbolGroupNodeVisitor::iNamePathSeparator);
+ return lastSep == std::string::npos ? std::string() : iname.substr(0, lastSep);
+}
+
+DebugSymbolGroupNodeVisitor::DebugSymbolGroupNodeVisitor(std::ostream &os, unsigned verbosity) :
+ m_os(os), m_verbosity(verbosity)
+{
+}
+
+SymbolGroupNodeVisitor::VisitResult
+ DebugSymbolGroupNodeVisitor::visit(AbstractSymbolGroupNode *node,
+ const std::string &aFullIname,
+ unsigned /* child */, unsigned depth)
+{
+ node->debug(m_os, aFullIname, m_verbosity, depth);
+ return VisitContinue;
+}
+
+// --------------------- DumpSymbolGroupNodeVisitor
+DumpSymbolGroupNodeVisitor::DumpSymbolGroupNodeVisitor(std::ostream &os,
+ const SymbolGroupValueContext &context,
+ const DumpParameters &parameters) :
+ m_os(os), m_context(context), m_parameters(parameters),
+ m_visitChildren(false),m_lastDepth(unsigned(-1))
+{
+}
+
+SymbolGroupNodeVisitor::VisitResult
+ DumpSymbolGroupNodeVisitor::visit(AbstractSymbolGroupNode *node,
+ const std::string &fullIname,
+ unsigned /* child */, unsigned depth)
+{
+ // Show container children only, no additional symbol below root.
+ const unsigned flags = node->flags();
+ if (flags & (SymbolGroupNode::Obscured|SymbolGroupNode::AdditionalSymbol))
+ return VisitSkipChildren;
+ // Recurse to children only if expanded by explicit watchmodel request
+ // and initialized.
+ m_visitChildren = true;
+ // Visit children of a SymbolGroupNode only if not expanded by its dumpers
+ if (SymbolGroupNode *snode = node->asSymbolGroupNode())
+ m_visitChildren = snode->isExpanded()
+ && (flags & (SymbolGroupNode::Uninitialized|SymbolGroupNode::ExpandedByDumper)) == 0;
+ // Comma between same level children given obscured children
+ if (depth == m_lastDepth) {
+ m_os << ',';
+ } else {
+ m_lastDepth = depth;
+ }
+ if (m_parameters.humanReadable()) {
+ m_os << '\n';
+ indentStream(m_os, depth * 2);
+ }
+ m_os << '{';
+ node->dump(m_os, fullIname, m_parameters, m_context);
+ if (m_visitChildren) { // open children array
+ m_os << ",children=[";
+ } else { // No children, close array.
+ m_os << '}';
+ }
+ if (m_parameters.humanReadable())
+ m_os << '\n';
+ return m_visitChildren ? VisitContinue : VisitSkipChildren;
+}
+
+void DumpSymbolGroupNodeVisitor::childrenVisited(const AbstractSymbolGroupNode *n, unsigned)
+{
+ m_os << "]}"; // Close children array and self
+ if (m_parameters.humanReadable())
+ m_os << " /* end of '" << n->absoluteFullIName() << "' */\n";
+}
diff --git a/src/libs/qtcreatorcdbext/symbolgroupnode.h b/src/libs/qtcreatorcdbext/symbolgroupnode.h
new file mode 100644
index 0000000000..dcb457c9ea
--- /dev/null
+++ b/src/libs/qtcreatorcdbext/symbolgroupnode.h
@@ -0,0 +1,393 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 SYMBOLGROUPNODE_H
+#define SYMBOLGROUPNODE_H
+
+#include "common.h"
+
+#include <vector>
+#include <string>
+#include <map>
+#include <iosfwd>
+
+enum { symbolGroupDebug = 0 };
+
+std::ostream &operator<<(std::ostream &, const DEBUG_SYMBOL_PARAMETERS&p);
+
+class SymbolGroupNodeVisitor;
+class SymbolGroup;
+struct SymbolGroupValueContext;
+class SymbolGroupNode;
+
+// All parameters for GDBMI dumping in one struct.
+struct DumpParameters
+{
+ typedef std::map<std::string, int> FormatMap; // type or iname to format
+ enum DumpFlags
+ {
+ DumpHumanReadable = 0x1,
+ DumpComplexDumpers = 0x2
+ };
+
+ DumpParameters();
+ bool humanReadable() const { return dumpFlags & DumpHumanReadable; }
+ // Helper to decode format option arguments.
+ static FormatMap decodeFormatArgument(const std::string &f);
+
+ bool recode(const std::string &type, const std::string &iname,
+ const SymbolGroupValueContext &ctx,
+ std::wstring *value, int *encoding) const;
+ int format(const std::string &type, const std::string &iname) const;
+
+ unsigned dumpFlags;
+ FormatMap typeFormats;
+ FormatMap individualFormats;
+};
+
+// Base class for a node of SymbolGroup, handling the list of children.
+class AbstractSymbolGroupNode
+{
+ AbstractSymbolGroupNode(const AbstractSymbolGroupNode&);
+ AbstractSymbolGroupNode& operator=(const AbstractSymbolGroupNode&);
+
+public:
+ typedef std::vector<AbstractSymbolGroupNode *> AbstractSymbolGroupNodePtrVector;
+ typedef AbstractSymbolGroupNodePtrVector::iterator AbstractSymbolGroupNodePtrVectorIterator;
+ typedef AbstractSymbolGroupNodePtrVector::const_iterator AbstractSymbolGroupNodePtrVectorConstIterator;
+
+ virtual ~AbstractSymbolGroupNode();
+
+ // Name to appear in watchwindow
+ const std::string &name() const { return m_name; }
+ // 'iname' used as an internal id.
+ const std::string &iName() const { return m_iname; }
+ // Full iname 'local.x.foo': WARNING: this returns the absolute path not
+ // taking reference nodes into account.
+ std::string absoluteFullIName() const;
+
+ virtual const AbstractSymbolGroupNodePtrVector &children() const = 0;
+ AbstractSymbolGroupNode *childAt(unsigned) const;
+
+ unsigned indexByIName(const char *) const; // (unsigned(-1) on failure
+ AbstractSymbolGroupNode *childByIName(const char *) const;
+
+ const AbstractSymbolGroupNode *parent() const { return m_parent; }
+
+ unsigned flags() const { return m_flags; }
+ bool testFlags(unsigned f) const { return (m_flags & f) != 0; }
+ void addFlags(unsigned f) { m_flags |= f; }
+ void clearFlags(unsigned f) { m_flags &= ~f; }
+
+ virtual SymbolGroupNode *asSymbolGroupNode() { return 0; }
+ virtual const SymbolGroupNode *asSymbolGroupNode() const { return 0; }
+ virtual const AbstractSymbolGroupNode *resolveReference() const { return this; }
+ virtual AbstractSymbolGroupNode *resolveReference() { return this; }
+
+ bool accept(SymbolGroupNodeVisitor &visitor,
+ const std::string &visitingParentIname,
+ unsigned child, unsigned depth);
+
+ // I/O: GDBMI dump for Visitors
+ virtual void dump(std::ostream &str, const std::string &visitingFullIname,
+ const DumpParameters &p, const SymbolGroupValueContext &ctx) = 0;
+ // I/O: debug output for Visitors
+ virtual void debug(std::ostream &os, const std::string &visitingFullIname,
+ unsigned verbosity, unsigned depth) const;
+
+ // For BaseSymbolGroupNode only.
+ void setParent(AbstractSymbolGroupNode *n);
+
+protected:
+ explicit AbstractSymbolGroupNode(const std::string &name, const std::string &iname);
+
+ // Basic GDBMI dumping
+ static inline void dumpBasicData(std::ostream &str, const std::string &aName,
+ const std::string &aFullIname,
+ const std::string &type = std::string(),
+ const std::string &expression = std::string());
+
+private:
+ const std::string m_name;
+ const std::string m_iname;
+ AbstractSymbolGroupNode *m_parent;
+ unsigned m_flags;
+};
+
+// Base class for a node of SymbolGroup with a flat list of children.
+class BaseSymbolGroupNode : public AbstractSymbolGroupNode
+{
+public:
+ virtual const AbstractSymbolGroupNodePtrVector &children() const { return m_children; }
+
+protected:
+ explicit BaseSymbolGroupNode(const std::string &name, const std::string &iname);
+ virtual ~BaseSymbolGroupNode();
+
+ void reserveChildren(AbstractSymbolGroupNodePtrVector::size_type s) { m_children.reserve(s); }
+ void addChild(AbstractSymbolGroupNode *c);
+
+private:
+ AbstractSymbolGroupNodePtrVector m_children;
+
+ void removeChildren();
+};
+
+/* SymbolGroupNode: 'Real' node within a symbol group, identified by its index
+ * in IDebugSymbolGroup.
+ * Provides accessors for fixed-up symbol group value and a dumping facility
+ * consisting of:
+ * - 'Simple' dumping done when running the DumpVisitor. This produces one
+ * line of formatted output shown for the class. These values
+ * values should are displayed, while still allowing for expansion of the structure
+ * in the debugger.
+ * It also pre-determines some information for complex dumping (type, container).
+ * - 'Complex' dumping: Obscures the symbol group children by fake children, for
+ * example container children, run when calling SymbolGroup::dump with an iname.
+ * The fake children are appended to the child list (other children are just marked as
+ * obscured for GDBMI dumping so that SymbolGroupValue expressions still work as before).
+ * The dumping is mostly based on SymbolGroupValue expressions.
+ * in the debugger. Evaluating those dumpers might expand symbol nodes, which are
+ * then marked as 'ExpandedByDumper'. This stops the dump recursion to prevent
+ * outputting data that were not explicitly expanded by the watch handler. */
+
+class SymbolGroupNode : public BaseSymbolGroupNode
+{
+ explicit SymbolGroupNode(SymbolGroup *symbolGroup,
+ ULONG index,
+ const std::string &name,
+ const std::string &iname);
+
+public:
+ enum Flags
+ {
+ Uninitialized = 0x1,
+ SimpleDumperNotApplicable = 0x2, // No dumper available for type
+ SimpleDumperOk = 0x4, // Internal dumper ran, value set
+ SimpleDumperFailed = 0x8, // Internal dumper failed
+ SimpleDumperMask = SimpleDumperNotApplicable|SimpleDumperOk|SimpleDumperFailed,
+ ExpandedByDumper = 0x10,
+ AdditionalSymbol = 0x20, // Introduced by addSymbol, should not be visible
+ Obscured = 0x40, // Symbol is obscured by (for example) fake container children
+ ComplexDumperOk = 0x80
+ };
+
+ typedef std::vector<DEBUG_SYMBOL_PARAMETERS> SymbolParameterVector;
+
+ void parseParameters(SymbolParameterVector::size_type index,
+ SymbolParameterVector::size_type parameterOffset,
+ const SymbolParameterVector &vec);
+
+ static SymbolGroupNode *create(SymbolGroup *sg, const std::string &name, const SymbolParameterVector &vec);
+ // For root nodes, only: Add a new symbol by name
+ SymbolGroupNode *addSymbolByName(const std::string &name, // Expression like 'myarray[1]'
+ const std::string &iname, // Desired iname, defaults to name
+ std::string *errorMessage);
+
+ SymbolGroup *symbolGroup() const { return m_symbolGroup; }
+
+ // I/O: Gdbmi dump for Visitors
+ virtual void dump(std::ostream &str, const std::string &fullIname,
+ const DumpParameters &p, const SymbolGroupValueContext &ctx);
+ // Dumper functionality for reference nodes.
+ void dumpNode(std::ostream &str, const std::string &aName, const std::string &aFullIName,
+ const DumpParameters &p, const SymbolGroupValueContext &ctx);
+
+ // I/O: debug for Visitors
+ virtual void debug(std::ostream &os, const std::string &visitingFullIname,
+ unsigned verbosity, unsigned depth) const;
+
+ std::wstring symbolGroupRawValue() const;
+ std::wstring symbolGroupFixedValue() const;
+ // A quick check if symbol is valid by checking for inaccessible value
+ bool isMemoryAccessible() const;
+
+ std::string type() const;
+ int dumperType() const { return m_dumperType; } // Valid after dumper run
+ int dumperContainerSize() { return m_dumperContainerSize; } // Valid after dumper run
+ unsigned size() const; // Size of value
+ ULONG64 address() const;
+
+ bool expand(std::string *errorMessage);
+ bool expandRunComplexDumpers(const SymbolGroupValueContext &ctx, std::string *errorMessage);
+ bool isExpanded() const { return !children().empty(); }
+ bool canExpand() const { return m_parameters.SubElements > 0; }
+ void runComplexDumpers(const SymbolGroupValueContext &ctx);
+ // Cast to a different type. Works only on unexpanded nodes
+ bool typeCast(const std::string &desiredType, std::string *errorMessage);
+
+ ULONG subElements() const { return m_parameters.SubElements; }
+ ULONG index() const { return m_index; }
+
+ virtual SymbolGroupNode *asSymbolGroupNode() { return this; }
+ virtual const SymbolGroupNode *asSymbolGroupNode() const { return this; }
+
+private:
+ const SymbolGroupNode *symbolGroupNodeParent() const;
+ bool isArrayElement() const;
+ // Notify about expansion of a node, shift indexes
+ bool notifyExpanded(ULONG index, ULONG insertedCount);
+ bool runSimpleDumpers(const SymbolGroupValueContext &ctx);
+ std::wstring simpleDumpValue(const SymbolGroupValueContext &ctx);
+
+ SymbolGroup *const m_symbolGroup;
+ ULONG m_index;
+ DEBUG_SYMBOL_PARAMETERS m_parameters; // Careful when using ParentSymbol. It might not be correct.
+ std::wstring m_dumperValue;
+ int m_dumperType;
+ int m_dumperContainerSize;
+};
+
+// Artificial node referencing another (real) SymbolGroupNode (added symbol or
+// symbol from within a linked list structure. Forwards dumping to referenced node
+// using its own name.
+class ReferenceSymbolGroupNode : public AbstractSymbolGroupNode
+{
+public:
+ explicit ReferenceSymbolGroupNode(const std::string &name,
+ const std::string &iname,
+ SymbolGroupNode *referencedNode);
+ // Convenience to create a node name name='[1]', iname='1' for arrays
+ static ReferenceSymbolGroupNode *createArrayNode(int index,
+ SymbolGroupNode *referencedNode);
+
+ virtual void dump(std::ostream &str, const std::string &visitingFullIname,
+ const DumpParameters &p, const SymbolGroupValueContext &ctx);
+ virtual void debug(std::ostream &os, const std::string &visitingFullIname,
+ unsigned verbosity, unsigned depth) const;
+
+ virtual const AbstractSymbolGroupNodePtrVector &children() const { return m_referencedNode->children(); }
+
+ virtual const AbstractSymbolGroupNode *resolveReference() const { return m_referencedNode; }
+ virtual AbstractSymbolGroupNode *resolveReference() { return m_referencedNode; }
+
+private:
+ SymbolGroupNode * const m_referencedNode;
+};
+
+// Base class for a [fake] map node with a fake array index and key/value entries.
+class MapNodeSymbolGroupNode : public BaseSymbolGroupNode
+{
+private:
+ explicit MapNodeSymbolGroupNode(const std::string &name,
+ const std::string &iname,
+ ULONG64 address /* = 0 */,
+ const std::string &type,
+ AbstractSymbolGroupNode *key,
+ AbstractSymbolGroupNode *value);
+
+public:
+ static MapNodeSymbolGroupNode *
+ create(int i, ULONG64 address /* = 0 */, const std::string &type,
+ SymbolGroupNode *key, SymbolGroupNode *value);
+
+ virtual void dump(std::ostream &str, const std::string &visitingFullIname,
+ const DumpParameters &p, const SymbolGroupValueContext &ctx);
+ virtual void debug(std::ostream &os, const std::string &visitingFullIname,
+ unsigned verbosity, unsigned depth) const;
+
+private:
+ const ULONG64 m_address;
+ const std::string m_type;
+};
+
+/* Visitor that takes care of iterating over the nodes and
+ * building the full iname path ('local.foo.bar') that is required for
+ * GDBMI dumping. The full name depends on the path on which a node was reached
+ * for referenced nodes (a linked list element can be reached via array index
+ * or by expanding the whole structure).
+ * visit() is not called for the (invisible) root node, but starting with the
+ * root's children with depth=0.
+ * Return true from visit() to terminate the recursion. */
+
+class SymbolGroupNodeVisitor {
+ SymbolGroupNodeVisitor(const SymbolGroupNodeVisitor&);
+ SymbolGroupNodeVisitor& operator=(const SymbolGroupNodeVisitor&);
+
+ friend class AbstractSymbolGroupNode;
+protected:
+ SymbolGroupNodeVisitor() {}
+public:
+ virtual ~SymbolGroupNodeVisitor() {}
+
+ // "local.vi" -> "local"
+ static std::string parentIname(const std::string &iname);
+ static const char iNamePathSeparator = '.';
+
+protected:
+ enum VisitResult
+ {
+ VisitContinue,
+ VisitSkipChildren,
+ VisitStop
+ };
+
+private:
+ virtual VisitResult visit(AbstractSymbolGroupNode *node,
+ const std::string &fullIname,
+ unsigned child, unsigned depth) = 0;
+ // Helper for formatting output.
+ virtual void childrenVisited(const AbstractSymbolGroupNode * /* node */, unsigned /* depth */) {}
+};
+
+// Debug output visitor.
+class DebugSymbolGroupNodeVisitor : public SymbolGroupNodeVisitor {
+public:
+ explicit DebugSymbolGroupNodeVisitor(std::ostream &os, unsigned verbosity = 0);
+
+private:
+ virtual VisitResult visit(AbstractSymbolGroupNode *node,
+ const std::string &fullIname,
+ unsigned child, unsigned depth);
+
+ std::ostream &m_os;
+ const unsigned m_verbosity;
+};
+
+// GDBMI dump output visitor.
+class DumpSymbolGroupNodeVisitor : public SymbolGroupNodeVisitor {
+public:
+ explicit DumpSymbolGroupNodeVisitor(std::ostream &os,
+ const SymbolGroupValueContext &context,
+ const DumpParameters &parameters = DumpParameters());
+
+private:
+ virtual VisitResult visit(AbstractSymbolGroupNode *node,
+ const std::string &fullIname,
+ unsigned child, unsigned depth);
+ virtual void childrenVisited(const AbstractSymbolGroupNode * node, unsigned depth);
+
+ std::ostream &m_os;
+ const SymbolGroupValueContext &m_context;
+ const DumpParameters &m_parameters;
+ bool m_visitChildren;
+ unsigned m_lastDepth;
+};
+
+#endif // SYMBOLGROUPNODE_H
diff --git a/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp b/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp
new file mode 100644
index 0000000000..c2513670a5
--- /dev/null
+++ b/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp
@@ -0,0 +1,1218 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "symbolgroupvalue.h"
+#include "symbolgroup.h"
+#include "stringutils.h"
+#include "containers.h"
+
+#include <iomanip>
+
+SymbolGroupValue::SymbolGroupValue(SymbolGroupNode *node,
+ const SymbolGroupValueContext &ctx) :
+ m_node(node), m_context(ctx)
+{
+ if (m_node && !m_node->isMemoryAccessible()) // Invalid if no value
+ m_node = 0;
+}
+
+SymbolGroupValue::SymbolGroupValue() :
+ m_node(0), m_errorMessage("Invalid")
+{
+}
+
+bool SymbolGroupValue::isValid() const
+{
+ return m_node != 0 && m_context.dataspaces != 0;
+}
+
+SymbolGroupValue SymbolGroupValue::operator[](unsigned index) const
+{
+ if (ensureExpanded())
+ if (index < m_node->children().size())
+ if (SymbolGroupNode *n = m_node->childAt(index)->asSymbolGroupNode())
+ return SymbolGroupValue(n, m_context);
+ return SymbolGroupValue();
+}
+
+bool SymbolGroupValue::ensureExpanded() const
+{
+ if (!isValid() || !m_node->canExpand())
+ return false;
+
+ if (m_node->isExpanded())
+ return true;
+
+ // Set a flag indicating the node was expanded by SymbolGroupValue
+ // and not by an explicit request from the watch model.
+ if (m_node->expand(&m_errorMessage)) {
+ m_node->addFlags(SymbolGroupNode::ExpandedByDumper);
+ return true;
+ }
+ return false;
+}
+
+SymbolGroupValue SymbolGroupValue::operator[](const char *name) const
+{
+ if (ensureExpanded())
+ if (AbstractSymbolGroupNode *child = m_node->childByIName(name))
+ if (SymbolGroupNode *n = child->asSymbolGroupNode())
+ return SymbolGroupValue(n, m_context);
+ return SymbolGroupValue();
+}
+
+std::string SymbolGroupValue::type() const
+{
+ return isValid() ? m_node->type() : std::string();
+}
+
+std::string SymbolGroupValue::name() const
+{
+ return isValid() ? m_node->name() : std::string();
+}
+
+unsigned SymbolGroupValue::size() const
+{
+ return isValid() ? m_node->size() : 0;
+}
+
+std::wstring SymbolGroupValue::value() const
+{
+ return isValid() ? m_node->symbolGroupFixedValue() : std::wstring();
+}
+
+double SymbolGroupValue::floatValue(double defaultValue) const
+{
+ double f = defaultValue;
+ if (isValid()) {
+ std::wistringstream str(value());
+ str >> f;
+ if (str.fail())
+ f = defaultValue;
+ }
+ return f;
+}
+
+int SymbolGroupValue::intValue(int defaultValue) const
+{
+ if (isValid()) {
+ int rc = 0;
+ // Is this an enumeration "EnumValue (0n12)", -> convert to integer
+ std::wstring v = value();
+ const std::wstring::size_type enPos = v.find(L"(0n");
+ if (enPos != std::wstring::npos && v.at(v.size() - 1) == L')')
+ v = v.substr(enPos + 3, v.size() - 4);
+ if (integerFromString(wStringToString(v), &rc))
+ return rc;
+ }
+ return defaultValue;
+}
+
+ULONG64 SymbolGroupValue::pointerValue(ULONG64 defaultValue) const
+{
+ if (isValid()) {
+ ULONG64 rc = 0;
+ if (integerFromString(wStringToString(value()), &rc))
+ return rc;
+ }
+ return defaultValue;
+}
+
+// Return allocated array of data
+unsigned char *SymbolGroupValue::pointerData(unsigned length) const
+{
+ if (isValid()) {
+ if (const ULONG64 ptr = pointerValue()) {
+ unsigned char *data = new unsigned char[length];
+ std::fill(data, data + length, 0);
+ const HRESULT hr = m_context.dataspaces->ReadVirtual(ptr, data, length, NULL);
+ if (FAILED(hr)) {
+ delete [] data;
+ return 0;
+ }
+ return data;
+ }
+ }
+ return 0;
+}
+
+ULONG64 SymbolGroupValue::address() const
+{
+ if (isValid())
+ return m_node->address();
+ return 0;
+}
+
+// Temporary iname
+static inline std::string additionalSymbolIname(const SymbolGroup *g)
+{
+ std::ostringstream str;
+ str << "__additional" << g->root()->children().size();
+ return str.str();
+}
+
+SymbolGroupValue SymbolGroupValue::typeCast(const char *type) const
+{
+ return typeCastedValue(address(), type);
+}
+
+SymbolGroupValue SymbolGroupValue::pointerTypeCast(const char *type) const
+{
+ return typeCastedValue(pointerValue(), type);
+}
+
+SymbolGroupValue SymbolGroupValue::typeCastedValue(ULONG64 address, const char *type) const
+{
+ if (!address)
+ return SymbolGroupValue();
+ const size_t len = strlen(type);
+ if (!len)
+ return SymbolGroupValue();
+ const bool nonPointer = type[len - 1] != '*';
+ SymbolGroup *sg = m_node->symbolGroup();
+ // A bit of magic: For desired pointer types, we can do
+ // 'Foo *' -> '(Foo *)(address)'.
+ // For non-pointers, we need to de-reference:
+ // 'Foo' -> '*(Foo *)(address)'
+ std::ostringstream str;
+ if (nonPointer)
+ str << '*';
+ str << '(' << type;
+ if (nonPointer)
+ str << " *";
+ str << ")(" << std::showbase << std::hex << address << ')';
+ if (SymbolGroupNode *node = sg->addSymbol(str.str(),
+ additionalSymbolIname(sg),
+ &m_errorMessage))
+ return SymbolGroupValue(node, m_context);
+ return SymbolGroupValue();
+}
+
+std::wstring SymbolGroupValue::wcharPointerData(unsigned charCount, unsigned maxCharCount) const
+{
+ const bool truncated = charCount > maxCharCount;
+ if (truncated)
+ charCount = maxCharCount;
+ if (const unsigned char *ucData = pointerData(charCount * sizeof(wchar_t))) {
+ const wchar_t *utf16Data = reinterpret_cast<const wchar_t *>(ucData);
+ // Be smart about terminating 0-character
+ if (charCount && utf16Data[charCount - 1] == 0)
+ charCount--;
+ std::wstring rc = std::wstring(utf16Data, charCount);
+ if (truncated)
+ rc += L"...";
+ delete [] ucData;
+ return rc;
+ }
+ return std::wstring();
+}
+
+std::string SymbolGroupValue::error() const
+{
+ return m_errorMessage;
+}
+
+bool SymbolGroupValue::isPointerType(const std::string &t)
+{
+ return endsWith(t, " *");
+}
+
+unsigned SymbolGroupValue::pointerSize()
+{
+ static const unsigned ps = SymbolGroupValue::sizeOf("char *");
+ return ps;
+}
+
+std::string SymbolGroupValue::stripPointerType(const std::string &t)
+{
+ return isPointerType(t) ? t.substr(0, t.size() - 2) : t;
+}
+
+std::string SymbolGroupValue::addPointerType(const std::string &t)
+{
+ // 'char' -> 'char *' -> 'char **'
+ std::string rc = t;
+ if (!endsWith(rc, '*'))
+ rc.push_back(' ');
+ rc.push_back('*');
+ return rc;
+}
+
+std::string SymbolGroupValue::stripArrayType(const std::string &t)
+{
+ const std::string::size_type bracket = t.rfind('[');
+ if (bracket != std::string::npos) {
+ std::string rc = t.substr(0, bracket);
+ trimBack(rc);
+ return rc;
+ }
+ return t;
+}
+
+// get the inner types: "QMap<int, double>" -> "int", "double"
+std::vector<std::string> SymbolGroupValue::innerTypesOf(const std::string &t)
+{
+ std::vector<std::string> rc;
+
+ std::string::size_type pos = t.find('<');
+ if (pos == std::string::npos)
+ return rc;
+
+ rc.reserve(5);
+ const std::string::size_type size = t.size();
+ // Record all elements of level 1 to work correctly for
+ // 'std::map<std::basic_string< .. > >'
+ unsigned level = 0;
+ std::string::size_type start = 0;
+ for ( ; pos < size ; pos++) {
+ const char c = t.at(pos);
+ switch (c) {
+ case '<':
+ if (++level == 1)
+ start = pos + 1;
+ break;
+ case '>':
+ if (--level == 0) { // last element
+ std::string innerType = t.substr(start, pos - start);
+ trimFront(innerType);
+ trimBack(innerType);
+ rc.push_back(innerType);
+ return rc;
+ }
+ break;
+ case ',':
+ if (level == 1) { // std::map<a, b>: start anew at ','.
+ std::string innerType = t.substr(start, pos - start);
+ trimFront(innerType);
+ trimBack(innerType);
+ rc.push_back(innerType);
+ start = pos + 1;
+ }
+ break;
+ }
+ }
+ return rc;
+}
+
+std::ostream &operator<<(std::ostream &str, const SymbolGroupValue &v)
+{
+ if (v) {
+ str << '\'' << v.name() << "' 0x" << std::showbase << std::hex << v.address() <<
+ std::dec << ' ' << v.type() << ": '" << wStringToString(v.value()) << '\'';
+ } else {
+ str << "Invalid value '" << v.error() << '\'';
+ }
+ return str;
+}
+
+// -------------------- Simple dumping helpers
+
+// Courtesy of qdatetime.cpp
+static inline void getDateFromJulianDay(unsigned julianDay, int *year, int *month, int *day)
+{
+ int y, m, d;
+
+ if (julianDay >= 2299161) {
+ typedef unsigned long long qulonglong;
+ // Gregorian calendar starting from October 15, 1582
+ // This algorithm is from Henry F. Fliegel and Thomas C. Van Flandern
+ qulonglong ell, n, i, j;
+ ell = qulonglong(julianDay) + 68569;
+ n = (4 * ell) / 146097;
+ ell = ell - (146097 * n + 3) / 4;
+ i = (4000 * (ell + 1)) / 1461001;
+ ell = ell - (1461 * i) / 4 + 31;
+ j = (80 * ell) / 2447;
+ d = int(ell - (2447 * j) / 80);
+ ell = j / 11;
+ m = int(j + 2 - (12 * ell));
+ y = int(100 * (n - 49) + i + ell);
+ } else {
+ // Julian calendar until October 4, 1582
+ // Algorithm from Frequently Asked Questions about Calendars by Claus Toendering
+ julianDay += 32082;
+ int dd = (4 * julianDay + 3) / 1461;
+ int ee = julianDay - (1461 * dd) / 4;
+ int mm = ((5 * ee) + 2) / 153;
+ d = ee - (153 * mm + 2) / 5 + 1;
+ m = mm + 3 - 12 * (mm / 10);
+ y = dd - 4800 + (mm / 10);
+ if (y <= 0)
+ --y;
+ }
+ if (year)
+ *year = y;
+ if (month)
+ *month = m;
+ if (day)
+ *day = d;
+}
+
+// Convert and format Julian Date as used in QDate
+static inline void formatJulianDate(std::wostream &str, unsigned julianDate)
+{
+ int y, m, d;
+ getDateFromJulianDay(julianDate, &y, &m, &d);
+ str << d << '.' << m << '.' << y;
+}
+
+// Format time in milliseconds as "hh:dd:ss:mmm"
+static inline void formatMilliSeconds(std::wostream &str, int milliSecs)
+{
+ const int hourFactor = 1000 * 3600;
+ const int hours = milliSecs / hourFactor;
+ milliSecs = milliSecs % hourFactor;
+ const int minFactor = 1000 * 60;
+ const int minutes = milliSecs / minFactor;
+ milliSecs = milliSecs % minFactor;
+ const int secs = milliSecs / 1000;
+ milliSecs = milliSecs % 1000;
+ str.fill('0');
+ str << std::setw(2) << hours << ':' << std::setw(2)
+ << minutes << ':' << std::setw(2) << secs
+ << '.' << std::setw(3) << milliSecs;
+}
+
+static const char stdStringTypeC[] = "std::basic_string<char,std::char_traits<char>,std::allocator<char> >";
+static const char stdWStringTypeC[] = "std::basic_string<unsigned short,std::char_traits<unsigned short>,std::allocator<unsigned short> >";
+
+// Determine type starting from a position (with/without 'class '/'struct ' prefix).
+static KnownType knownTypeHelper(const std::string &type, std::string::size_type pos)
+{
+ // Strip pointer types.
+ const std::wstring::size_type compareLen =
+ endsWith(type, " *") ? type.size() -2 : type.size();
+ // STL ?
+ const std::wstring::size_type templatePos = type.find('<', pos);
+ static const std::wstring::size_type stlClassLen = 5;
+ if (!type.compare(pos, stlClassLen, "std::")) {
+ // STL containers
+ const std::wstring::size_type hPos = pos + stlClassLen;
+ if (templatePos != std::string::npos) {
+ switch (templatePos - stlClassLen - pos) {
+ case 3:
+ if (!type.compare(hPos, 3, "set"))
+ return KT_StdSet;
+ if (!type.compare(hPos, 3, "map"))
+ return KT_StdMap;
+ break;
+ case 4:
+ if (!type.compare(hPos, 4, "list"))
+ return KT_StdList;
+ break;
+ case 5:
+ if (!type.compare(hPos, 5, "stack"))
+ return KT_StdStack;
+ if (!type.compare(hPos, 5, "deque"))
+ return KT_StdDeque;
+ break;
+ case 6:
+ if (!type.compare(hPos, 6, "vector"))
+ return KT_StdVector;
+ break;
+ case 8:
+ if (!type.compare(hPos, 8, "multimap"))
+ return KT_StdMultiMap;
+ break;
+ }
+ }
+ // STL strings
+ if (!type.compare(pos, compareLen - pos, stdStringTypeC))
+ return KT_StdString;
+ if (!type.compare(pos, compareLen - pos, stdWStringTypeC))
+ return KT_StdWString;
+ return KT_Unknown;
+ } // std::sth
+ // Check for a 'Q' past the last namespace (beware of namespaced Qt:
+ // 'nsp::QString').
+ const std::wstring::size_type lastNameSpacePos = type.rfind(':', templatePos);
+ const std::wstring::size_type qPos =
+ lastNameSpacePos == std::string::npos ? type.find('Q', pos) : lastNameSpacePos + 1;
+ if (qPos == std::string::npos || qPos >= type.size() || type.at(qPos) != 'Q')
+ return KT_Unknown;
+ // Qt types (templates)
+ if (templatePos != std::string::npos) {
+ switch (templatePos - qPos) {
+ case 4:
+ if (!type.compare(qPos, 4, "QSet"))
+ return KT_QSet;
+ if (!type.compare(qPos, 4, "QMap"))
+ return KT_QMap;
+ break;
+ case 5:
+ if (!type.compare(qPos, 5, "QHash"))
+ return KT_QHash;
+ if (!type.compare(qPos, 5, "QList"))
+ return KT_QList;
+ break;
+ case 6:
+ if (!type.compare(qPos, 6, "QFlags"))
+ return KT_QFlags;
+ if (!type.compare(qPos, 6, "QStack"))
+ return KT_QStack;
+ if (!type.compare(qPos, 6, "QQueue"))
+ return KT_QQueue;
+ break;
+ case 7:
+ if (!type.compare(qPos, 7, "QVector"))
+ return KT_QVector;
+ break;
+ case 9:
+ if (!type.compare(qPos, 9, "QMultiMap"))
+ return KT_QMultiMap;
+ break;
+ case 10:
+ if (!type.compare(qPos, 10, "QMultiHash"))
+ return KT_QMultiHash;
+ break;
+ case 11:
+ if (!type.compare(qPos, 11, "QLinkedList"))
+ return KT_QLinkedList;
+ break;
+ }
+ }
+ // Remaining non-template types
+ switch (compareLen - qPos) {
+
+ case 4:
+ if (!type.compare(qPos, 4, "QPen"))
+ return KT_QPen;
+ if (!type.compare(qPos, 4, "QUrl"))
+ return KT_QUrl;
+ break;
+ case 5:
+ if (!type.compare(qPos, 5, "QChar"))
+ return KT_QChar;
+ if (!type.compare(qPos, 5, "QDate"))
+ return KT_QDate;
+ if (!type.compare(qPos, 5, "QTime"))
+ return KT_QTime;
+ if (!type.compare(qPos, 5, "QSize"))
+ return KT_QSize;
+ if (!type.compare(qPos, 5, "QLine"))
+ return KT_QLine;
+ if (!type.compare(qPos, 5, "QRect"))
+ return KT_QRect;
+ if (!type.compare(qPos, 5, "QIcon"))
+ return KT_QIcon;
+ break;
+ case 6:
+ if (!type.compare(qPos, 6, "QColor"))
+ return KT_QColor;
+ if (!type.compare(qPos, 6, "QSizeF"))
+ return KT_QSizeF;
+ if (!type.compare(qPos, 6, "QPoint"))
+ return KT_QPoint;
+ if (!type.compare(qPos, 6, "QLineF"))
+ return KT_QLineF;
+ if (!type.compare(qPos, 6, "QRectF"))
+ return KT_QRectF;
+ if (!type.compare(qPos, 6, "QBrush"))
+ return KT_QBrush;
+ if (!type.compare(qPos, 6, "QImage"))
+ return KT_QImage;
+ if (!type.compare(qPos, 6, "QFixed"))
+ return KT_QFixed;
+ break;
+ case 7:
+ if (!type.compare(qPos, 7, "QString"))
+ return KT_QString;
+ if (!type.compare(qPos, 7, "QPointF"))
+ return KT_QPointF;
+ if (!type.compare(qPos, 7, "QObject"))
+ return KT_QObject;
+ if (!type.compare(qPos, 7, "QWidget"))
+ return KT_QWidget;
+ if (!type.compare(qPos, 7, "QLocale"))
+ return KT_QLocale;
+ if (!type.compare(qPos, 7, "QMatrix"))
+ return KT_QMatrix;
+ if (!type.compare(qPos, 7, "QRegExp"))
+ return KT_QRegExp;
+ break;
+ case 8:
+ if (!type.compare(qPos, 8, "QVariant"))
+ return KT_QVariant;
+ if (!type.compare(qPos, 8, "QMargins"))
+ return KT_QMargins;
+ if (!type.compare(qPos, 8, "QXmlItem"))
+ return KT_QXmltem;
+ if (!type.compare(qPos, 8, "QXmlName"))
+ return KT_QXmlName;
+ break;
+ case 9:
+ if (!type.compare(qPos, 9, "QBitArray"))
+ return KT_QBitArray;
+ if (!type.compare(qPos, 9, "QDateTime"))
+ return KT_QDateTime;
+ if (!type.compare(qPos, 9, "QFileInfo"))
+ return KT_QFileInfo;
+ if (!type.compare(qPos, 9, "QMetaEnum"))
+ return KT_QMetaEnum;
+ if (!type.compare(qPos, 9, "QTextItem"))
+ return KT_QTextItem;
+ if (!type.compare(qPos, 9, "QVector2D"))
+ return KT_QVector2D;
+ if (!type.compare(qPos, 9, "QVector3D"))
+ return KT_QVector3D;
+ if (!type.compare(qPos, 9, "QVector4D"))
+ return KT_QVector4D;
+ break;
+ case 10:
+ if (!type.compare(qPos, 10, "QAtomicInt"))
+ return KT_QAtomicInt;
+ if (!type.compare(qPos, 10, "QByteArray"))
+ return KT_QByteArray;
+ if (!type.compare(qPos, 10, "QMatrix4x4"))
+ return KT_QMatrix4x4;
+ if (!type.compare(qPos, 10, "QTextBlock"))
+ return KT_QTextBlock;
+ if (!type.compare(qPos, 10, "QTransform"))
+ return KT_QTransform;
+ if (!type.compare(qPos, 10, "QFixedSize"))
+ return KT_QFixedSize;
+ break;
+ case 11:
+ if (!type.compare(qPos, 11, "QStringList"))
+ return KT_QStringList;
+ if (!type.compare(qPos, 11, "QBasicTimer"))
+ return KT_QBasicTimer;
+ if (!type.compare(qPos, 11, "QMetaMethod"))
+ return KT_QMetaMethod;
+ if (!type.compare(qPos, 11, "QModelIndex"))
+ return KT_QModelIndex;
+ if (!type.compare(qPos, 11, "QQuaternion"))
+ return KT_QQuaternion;
+ if (!type.compare(qPos, 11, "QScriptItem"))
+ return KT_QScriptItem;
+ if (!type.compare(qPos, 11, "QFixedPoint"))
+ return KT_QFixedPoint;
+ if (!type.compare(qPos, 11, "QScriptLine"))
+ return KT_QScriptLine;
+ break;
+ case 12:
+ if (!type.compare(qPos, 12, "QKeySequence"))
+ return KT_QKeySequence;
+ break;
+ case 13:
+ if (!type.compare(qPos, 13, "QTextFragment"))
+ return KT_QTextFragment;
+ if (!type.compare(qPos, 13, "QTreeViewItem"))
+ return KT_QTreeViewItem;
+ break;
+ case 14:
+ if (!type.compare(qPos, 14, "QMetaClassInfo"))
+ return KT_QMetaClassInfo;
+ if (!type.compare(qPos, 14, "QNetworkCookie"))
+ return KT_QNetworkCookie;
+ break;
+ case 15:
+ if (!type.compare(qPos, 15, "QBasicAtomicInt"))
+ return KT_QBasicAtomicInt;
+ if (!type.compare(qPos, 15, "QHashDummyValue"))
+ return KT_QHashDummyValue;
+ if (!type.compare(qPos, 15, "QSourceLocation"))
+ return KT_QSourceLocation;
+ if (!type.compare(qPos, 15, "QScriptAnalysis"))
+ return KT_QScriptAnalysis;
+ break;
+ case 16:
+ if (!type.compare(qPos, 16, "QTextUndoCommand"))
+ return KT_QTextUndoCommand;
+ break;
+ case 18:
+ if (!type.compare(qPos, 18, "QNetworkProxyQuery"))
+ return KT_QNetworkProxyQuery;
+ if (!type.compare(qPos, 18, "QXmlNodeModelIndex"))
+ return KT_QXmlNodeModelIndex;
+ break;
+ case 19:
+ if (!type.compare(qPos, 19, "QItemSelectionRange"))
+ return KT_QItemSelectionRange;
+ if (!type.compare(qPos, 19, "QPaintBufferCommand"))
+ return KT_QPaintBufferCommand;
+ if (!type.compare(qPos, 19, "QTextHtmlParserNode"))
+ return KT_QTextHtmlParserNode;
+ if (!type.compare(qPos, 19, "QXmlStreamAttribute"))
+ return KT_QXmlStreamAttribute;
+ if (!type.compare(qPos, 19, "QGlyphJustification"))
+ return KT_QGlyphJustification;
+ break;
+ case 20:
+ if (!type.compare(qPos, 20, "QTextBlock::iterator"))
+ return KT_QTextBlock_iterator;
+ if (!type.compare(qPos, 20, "QTextFrame::iterator"))
+ return KT_QTextFrame_iterator;
+ break;
+ case 21:
+ if (!type.compare(qPos, 21, "QPersistentModelIndex"))
+ return KT_QPersistentModelIndex;
+ if (!type.compare(qPos, 21, "QPainterPath::Element"))
+ return KT_QPainterPath_Element;
+ break;
+ case 22:
+ if (!type.compare(qPos, 22, "QObjectPrivate::Sender"))
+ return KT_QObjectPrivate_Sender;
+ break;
+ case 24:
+ if (!type.compare(qPos, 24, "QPatternist::AtomicValue"))
+ return KT_QPatternist_AtomicValue;
+ if (!type.compare(qPos, 24, "QPatternist::Cardinality"))
+ return KT_QPatternist_Cardinality;
+ break;
+ case 26:
+ if (!type.compare(qPos, 26, "QObjectPrivate::Connection"))
+ return KT_QObjectPrivate_Connection;
+ if (!type.compare(qPos, 26, "QPatternist::ItemCacheCell"))
+ return KT_QPatternist_ItemCacheCell;
+ if (!type.compare(qPos, 26, "QPatternist::ItemType::Ptr"))
+ return KT_QPatternist_ItemType_Ptr;
+ if (!type.compare(qPos, 26, "QPatternist::NamePool::Ptr"))
+ return KT_QPatternist_NamePool_Ptr;
+ break;
+ case 27:
+ if (!type.compare(qPos, 27, "QXmlStreamEntityDeclaration"))
+ return KT_QXmlStreamEntityDeclaration;
+ break;
+ case 28:
+ if (!type.compare(qPos, 28, "QPatternist::Expression::Ptr"))
+ return KT_QPatternist_Expression_Ptr;
+ break;
+ case 29:
+ if (!type.compare(qPos, 29, "QXmlStreamNotationDeclaration"))
+ return KT_QXmlStreamNotationDeclaration;
+ case 30:
+ if (!type.compare(qPos, 30, "QPatternist::SequenceType::Ptr"))
+ return KT_QPatternist_SequenceType_Ptr;
+ if (!type.compare(qPos, 30, "QXmlStreamNamespaceDeclaration"))
+ return KT_QXmlStreamNamespaceDeclaration;
+ break;
+ case 32:
+ break;
+ if (!type.compare(qPos, 32, "QPatternist::Item::Iterator::Ptr"))
+ return KT_QPatternist_Item_Iterator_Ptr;
+ case 34:
+ break;
+ if (!type.compare(qPos, 34, "QPatternist::ItemSequenceCacheCell"))
+ return KT_QPatternist_ItemSequenceCacheCell;
+ case 37:
+ break;
+ if (!type.compare(qPos, 37, "QNetworkHeadersPrivate::RawHeaderPair"))
+ return KT_QNetworkHeadersPrivate_RawHeaderPair;
+ if (!type.compare(qPos, 37, "QPatternist::AccelTree::BasicNodeData"))
+ return KT_QPatternist_AccelTree_BasicNodeData;
+ break;
+ }
+ return KT_Unknown;
+}
+
+KnownType knownType(const std::string &type, bool hasClassPrefix)
+{
+ if (type.empty())
+ return KT_Unknown;
+ if (hasClassPrefix) {
+ switch (type.at(0)) { // Check 'class X' or 'struct X'
+ case 'c':
+ if (!type.compare(0, 6, "class "))
+ return knownTypeHelper(type, 6);
+ break;
+ case 's':
+ if (!type.compare(0, 7, "struct "))
+ return knownTypeHelper(type, 7);
+ break;
+ }
+ } else {
+ // No prefix, full check
+ return knownTypeHelper(type, 0);
+ }
+ return KT_Unknown;
+}
+
+static inline bool dumpQString(const SymbolGroupValue &v, std::wostream &str)
+{
+ if (const SymbolGroupValue d = v["d"]) {
+ if (const SymbolGroupValue sizeValue = d["size"]) {
+ const int size = sizeValue.intValue();
+ if (size >= 0) {
+ str << d["data"].wcharPointerData(size);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+// Dump QColor
+static bool dumpQColor(const SymbolGroupValue &v, std::wostream &str)
+{
+ const SymbolGroupValue specV = v["cspec"];
+ if (!specV)
+ return false;
+ const int spec = specV.intValue();
+ if (spec == 0) {
+ str << L"<Invalid color>";
+ return true;
+ }
+ if (spec < 1 || spec > 4)
+ return false;
+ const SymbolGroupValue arrayV = v["ct"]["array"];
+ if (!arrayV)
+ return false;
+ const int a0 = arrayV["0"].intValue();
+ const int a1 = arrayV["1"].intValue();
+ const int a2 = arrayV["2"].intValue();
+ const int a3 = arrayV["3"].intValue();
+ const int a4 = arrayV["4"].intValue();
+ if (a0 < 0 || a1 < 0 || a2 < 0 || a3 < 0 || a4 < 0)
+ return false;
+ switch (spec) {
+ case 1: // Rgb
+ str << L"RGB alpha=" << (a0 / 0x101) << L", red=" << (a1 / 0x101)
+ << L", green=" << (a2 / 0x101) << ", blue=" << (a3 / 0x101);
+ break;
+ case 2: // Hsv
+ str << L"HSV alpha=" << (a0 / 0x101) << L", hue=" << (a1 / 100)
+ << L", sat=" << (a2 / 0x101) << ", value=" << (a3 / 0x101);
+ break;
+ case 3: // Cmyk
+ str << L"CMYK alpha=" << (a0 / 0x101) << L", cyan=" << (a1 / 100)
+ << L", magenta=" << (a2 / 0x101) << ", yellow=" << (a3 / 0x101)
+ << ", black=" << (a4 / 0x101);
+ break;
+ case 4: // Hsl
+ str << L"HSL alpha=" << (a0 / 0x101) << L", hue=" << (a1 / 100)
+ << L", sat=" << (a2 / 0x101) << ", lightness=" << (a3 / 0x101);
+ break;
+ }
+ return true;
+}
+
+// Dump Qt's core types
+
+static inline bool dumpQBasicAtomicInt(const SymbolGroupValue &v, std::wostream &str)
+{
+ if (const SymbolGroupValue iValue = v["_q_value"]) {
+ str << iValue.value();
+ return true;
+ }
+ return false;
+}
+
+static inline bool dumpQAtomicInt(const SymbolGroupValue &v, std::wostream &str)
+{
+ if (const SymbolGroupValue base = v[unsigned(0)])
+ return dumpQBasicAtomicInt(base, str);
+ return false;
+}
+
+static bool dumpQChar(const SymbolGroupValue &v, std::wostream &str)
+{
+ if (SymbolGroupValue cValue = v["ucs"]) {
+ const int utf16 = cValue.intValue();
+ if (utf16 >= 0) {
+ // Print code = character,
+ // exclude control characters and Pair indicator
+ str << utf16;
+ if (utf16 >= 32 && (utf16 < 0xD800 || utf16 > 0xDBFF))
+ str << " '" << wchar_t(utf16) << '\'';
+ }
+ return true;
+ }
+ return false;
+}
+
+static inline bool dumpQFlags(const SymbolGroupValue &v, std::wostream &str)
+{
+ if (SymbolGroupValue iV = v["i"]) {
+ const int i = iV.intValue();
+ if (i >= 0) {
+ str << i;
+ return true;
+ }
+ }
+ return false;
+}
+
+static inline bool dumpQDate(const SymbolGroupValue &v, std::wostream &str)
+{
+ if (const SymbolGroupValue julianDayV = v["jd"]) {
+ const int julianDay = julianDayV.intValue();
+ if (julianDay > 0) {
+ formatJulianDate(str, julianDay);
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool dumpQTime(const SymbolGroupValue &v, std::wostream &str)
+{
+ if (const SymbolGroupValue milliSecsV = v["mds"]) {
+ const int milliSecs = milliSecsV.intValue();
+ if (milliSecs >= 0) {
+ formatMilliSeconds(str, milliSecs);
+ return true;
+ }
+ }
+ return false;
+}
+
+// Dump a QByteArray
+static inline bool dumpQByteArray(const SymbolGroupValue &v, std::wostream &str)
+{
+ // TODO: More sophisticated dumping of binary data?
+ if (const SymbolGroupValue data = v["d"]["data"]) {
+ str << data.value();
+ return true;
+ }
+ return false;
+}
+
+// Dump a rectangle in X11 syntax
+template <class T>
+inline void dumpRect(std::wostream &str, T x, T y, T width, T height)
+{
+ str << width << 'x' << height;
+ if (x >= 0)
+ str << '+';
+ str << x;
+ if (y >= 0)
+ str << '+';
+ str << y;
+}
+
+template <class T>
+inline void dumpRectPoints(std::wostream &str, T x1, T y1, T x2, T y2)
+{
+ dumpRect(str, x1, y1, (x2 - x1), (y2 - y1));
+}
+
+// Dump Qt's simple geometrical types
+static inline bool dumpQSize_F(const SymbolGroupValue &v, std::wostream &str)
+{
+ str << '(' << v["wd"].value() << ", " << v["ht"].value() << ')';
+ return true;
+}
+
+static inline bool dumpQPoint_F(const SymbolGroupValue &v, std::wostream &str)
+{
+ str << '(' << v["xp"].value() << ", " << v["yp"].value() << ')';
+ return true;
+}
+
+static inline bool dumpQLine_F(const SymbolGroupValue &v, std::wostream &str)
+{
+ const SymbolGroupValue p1 = v["pt1"];
+ const SymbolGroupValue p2 = v["pt2"];
+ if (p1 && p2) {
+ str << '(' << p1["xp"].value() << ", " << p1["yp"].value() << ") ("
+ << p2["xp"].value() << ", " << p2["yp"].value() << ')';
+ return true;
+ }
+ return false;
+}
+
+static inline bool dumpQRect(const SymbolGroupValue &v, std::wostream &str)
+{
+ dumpRectPoints(str, v["x1"].intValue(), v["y1"].intValue(), v["x2"].intValue(), v["y2"].intValue());
+ return true;
+}
+
+static inline bool dumpQRectF(const SymbolGroupValue &v, std::wostream &str)
+{
+ dumpRect(str, v["xp"].floatValue(), v["yp"].floatValue(), v["w"].floatValue(), v["h"].floatValue());
+ return true;
+}
+
+// Dump the object name
+static inline bool dumpQObject(const SymbolGroupValue &v, std::wostream &str)
+{
+ if (SymbolGroupValue oName = v["d_ptr"]["d"].pointerTypeCast("QObjectPrivate *")["objectName"]) {
+ str << L'"';
+ dumpQString(oName, str);
+ str << L'"';
+ return true;
+ }
+ return false;
+}
+
+// Dump a std::string.
+static bool dumpStd_W_String(const SymbolGroupValue &v, std::wostream &str)
+{
+ // MSVC 2010: Access Bx/_Buf in base class
+ SymbolGroupValue buf = v[unsigned(0)]["_Bx"]["_Buf"];
+ if (!buf) // MSVC2008: Bx/Buf are members
+ buf = v["_Bx"]["_Buf"];
+ if (buf) {
+ str << buf.value();
+ return true;
+ }
+ return false;
+}
+
+// QVariant employs a template for storage where anything bigger than the data union
+// is pointed to by data.shared.ptr, else it is put into the data struct (pointer size)
+// itself (notably Qt types consisting of a d-ptr only).
+// The layout can vary between 32 /64 bit for some types: QPoint/QSize (of 2 ints) is bigger
+// as a pointer only on 32 bit.
+
+static inline SymbolGroupValue qVariantCast(const SymbolGroupValue &variantData, const char *type)
+{
+ const ULONG typeSize = SymbolGroupValue::sizeOf(type);
+ const std::string ptrType = std::string(type) + " *";
+ if (typeSize > variantData.size())
+ return variantData["shared"]["ptr"].pointerTypeCast(ptrType.c_str());
+ return variantData.typeCast(ptrType.c_str());
+}
+
+static bool dumpQVariant(const SymbolGroupValue &v, std::wostream &str)
+{
+ const SymbolGroupValue dV = v["d"];
+ if (!dV)
+ return false;
+ const SymbolGroupValue typeV = dV["type"];
+ const SymbolGroupValue dataV = dV["data"];
+ if (!typeV || !dataV)
+ return false;
+ const int typeId = typeV.intValue();
+ if (typeId <= 0) {
+ str << L"<Invalid>";
+ return true;
+ }
+ switch (typeId) {
+ case 1: // Bool
+ str << L"(bool) " << dataV["b"].value();
+ break;
+ case 2: // Int
+ str << L"(int) " << dataV["i"].value();
+ break;
+ case 3: // UInt
+ str << L"(unsigned) " << dataV["u"].value();
+ break;
+ case 4: // LongLong
+ str << L"(long long) " << dataV["ll"].value();
+ break;
+ case 5: // LongLong
+ str << L"(unsigned long long) " << dataV["ull"].value();
+ break;
+ case 6: // Double
+ str << L"(double) " << dataV["d"].value();
+ break;
+ case 7: // Char
+ str << L"(char) " << dataV["c"].value();
+ break;
+ case 10: // String
+ str << L"(QString) \"";
+ if (const SymbolGroupValue sv = dataV.typeCast("QString *")) {
+ dumpQString(sv, str);
+ str << L'"';
+ }
+ break;
+ case 12: //ByteArray
+ str << L"(QByteArray) ";
+ if (const SymbolGroupValue sv = dataV.typeCast("QByteArray *"))
+ dumpQByteArray(sv, str);
+ break;
+ case 13: // BitArray
+ str << L"(QBitArray)";
+ break;
+ case 14: // Date
+ str << L"(QDate) ";
+ if (const SymbolGroupValue sv = dataV.typeCast("QDate *"))
+ dumpQDate(sv, str);
+ break;
+ case 15: // Time
+ str << L"(QTime) ";
+ if (const SymbolGroupValue sv = dataV.typeCast("QTime *"))
+ dumpQTime(sv, str);
+ break;
+ case 16: // DateTime
+ str << L"(QDateTime)";
+ break;
+ case 17: // Url
+ str << L"(QUrl)";
+ break;
+ case 18: // Locale
+ str << L"(QLocale)";
+ break;
+ case 19: // Rect:
+ str << L"(QRect) ";
+ if (const SymbolGroupValue sv = dataV["shared"]["ptr"].pointerTypeCast("QRect *"))
+ dumpQRect(sv, str);
+ break;
+ case 20: // RectF
+ str << L"(QRectF) ";
+ if (const SymbolGroupValue sv = dataV["shared"]["ptr"].pointerTypeCast("QRectF *"))
+ dumpQRectF(sv, str);
+ break;
+ case 21: // Size
+ // Anything bigger than the data union is a pointer, else the data union is used
+ str << L"(QSize) ";
+ if (const SymbolGroupValue sv = qVariantCast(dataV, "QSize"))
+ dumpQSize_F(sv, str);
+ break;
+ case 22: // SizeF
+ str << L"(QSizeF) ";
+ if (const SymbolGroupValue sv = dataV["shared"]["ptr"].pointerTypeCast("QSizeF *"))
+ dumpQSize_F(sv, str);
+ break;
+ case 23: // Line
+ str << L"(QLine) ";
+ if (const SymbolGroupValue sv = dataV["shared"]["ptr"].pointerTypeCast("QLine *"))
+ dumpQLine_F(sv, str);
+ break;
+ case 24: // LineF
+ str << L"(QLineF) ";
+ if (const SymbolGroupValue sv = dataV["shared"]["ptr"].pointerTypeCast("QLineF *"))
+ dumpQLine_F(sv, str);
+ break;
+ case 25: // Point
+ str << L"(QPoint) ";
+ if (const SymbolGroupValue sv = qVariantCast(dataV, "QPoint"))
+ dumpQPoint_F(sv, str);
+ break;
+ case 26: // PointF
+ str << L"(QPointF) ";
+ if (const SymbolGroupValue sv = dataV["shared"]["ptr"].pointerTypeCast("QPointF *"))
+ dumpQPoint_F(sv, str);
+ break;
+ default:
+ str << L"Type " << typeId;
+ break;
+ }
+ return true;
+}
+
+static inline std::wstring msgContainerSize(int s)
+{
+ std::wostringstream str;
+ str << L'<' << s << L" items>";
+ return str.str();
+}
+
+// Dump builtin simple types using SymbolGroupValue expressions.
+unsigned dumpSimpleType(SymbolGroupNode *n, const SymbolGroupValueContext &ctx,
+ std::wstring *s, int *knownTypeIn /* = 0 */,
+ int *containerSizeIn /* = 0 */)
+{
+ QTC_TRACE_IN
+ if (containerSizeIn)
+ *containerSizeIn = -1;
+ // Check for class types and strip pointer types (references appear as pointers as well)
+ s->clear();
+ const KnownType kt = knownType(n->type());
+ if (knownTypeIn)
+ *knownTypeIn = kt;
+
+ if (kt == KT_Unknown || !(kt & KT_HasSimpleDumper)) {
+ QTC_TRACE_OUT
+ return SymbolGroupNode::SimpleDumperNotApplicable;
+ }
+
+ const SymbolGroupValue v(n, ctx);
+ // Simple dump of size for containers
+ if (kt & KT_ContainerType) {
+ const int size = containerSize(kt, v);
+ if (containerSizeIn)
+ *containerSizeIn = size;
+ if (size >= 0) {
+ *s = msgContainerSize(size);
+ return SymbolGroupNode::SimpleDumperOk;
+ }
+ return SymbolGroupNode::SimpleDumperFailed;
+ }
+ std::wostringstream str;
+ unsigned rc = SymbolGroupNode::SimpleDumperNotApplicable;
+ switch (kt) {
+ case KT_QChar:
+ rc = dumpQChar(v, str) ? SymbolGroupNode::SimpleDumperOk : SymbolGroupNode::SimpleDumperFailed;
+ break;
+ case KT_QByteArray:
+ rc = dumpQByteArray(v, str) ? SymbolGroupNode::SimpleDumperOk : SymbolGroupNode::SimpleDumperFailed;
+ break;
+ case KT_QString:
+ rc = dumpQString(v, str) ? SymbolGroupNode::SimpleDumperOk : SymbolGroupNode::SimpleDumperFailed;
+ break;
+ case KT_QColor:
+ rc = dumpQColor(v, str) ? SymbolGroupNode::SimpleDumperOk : SymbolGroupNode::SimpleDumperFailed;
+ break;
+ case KT_QFlags:
+ rc = dumpQFlags(v, str) ? SymbolGroupNode::SimpleDumperOk : SymbolGroupNode::SimpleDumperFailed;
+ break;
+ case KT_QDate:
+ rc = dumpQDate(v, str) ? SymbolGroupNode::SimpleDumperOk : SymbolGroupNode::SimpleDumperFailed;
+ break;
+ case KT_QTime:
+ rc = dumpQTime(v, str) ? SymbolGroupNode::SimpleDumperOk : SymbolGroupNode::SimpleDumperFailed;
+ break;
+ case KT_QPoint:
+ case KT_QPointF:
+ rc = dumpQPoint_F(v, str) ? SymbolGroupNode::SimpleDumperOk : SymbolGroupNode::SimpleDumperFailed;
+ break;
+ case KT_QSize:
+ case KT_QSizeF:
+ rc = dumpQSize_F(v, str) ? SymbolGroupNode::SimpleDumperOk : SymbolGroupNode::SimpleDumperFailed;
+ break;
+ case KT_QLine:
+ case KT_QLineF:
+ rc = dumpQLine_F(v, str) ? SymbolGroupNode::SimpleDumperOk : SymbolGroupNode::SimpleDumperFailed;
+ break;
+ case KT_QRect:
+ rc = dumpQRect(v, str) ? SymbolGroupNode::SimpleDumperOk : SymbolGroupNode::SimpleDumperFailed;
+ break;
+ case KT_QRectF:
+ rc = dumpQRectF(v, str) ? SymbolGroupNode::SimpleDumperOk : SymbolGroupNode::SimpleDumperFailed;
+ break;
+ case KT_QVariant:
+ rc = dumpQVariant(v, str) ? SymbolGroupNode::SimpleDumperOk : SymbolGroupNode::SimpleDumperFailed;
+ break;
+ case KT_QAtomicInt:
+ rc = dumpQAtomicInt(v, str) ? SymbolGroupNode::SimpleDumperOk : SymbolGroupNode::SimpleDumperFailed;
+ break;
+ case KT_QBasicAtomicInt:
+ rc = dumpQBasicAtomicInt(v, str) ? SymbolGroupNode::SimpleDumperOk : SymbolGroupNode::SimpleDumperFailed;
+ break;
+ case KT_QObject:
+ rc = dumpQObject(v, str) ? SymbolGroupNode::SimpleDumperOk : SymbolGroupNode::SimpleDumperFailed;
+ break;
+ case KT_QWidget:
+ rc = dumpQObject(v[unsigned(0)], str) ? SymbolGroupNode::SimpleDumperOk : SymbolGroupNode::SimpleDumperFailed;
+ break;
+ case KT_StdString:
+ case KT_StdWString:
+ rc = dumpStd_W_String(v, str) ? SymbolGroupNode::SimpleDumperOk : SymbolGroupNode::SimpleDumperFailed;
+ break;
+ default:
+ break;
+ }
+ if (rc == SymbolGroupNode::SimpleDumperOk)
+ *s = str.str();
+ QTC_TRACE_OUT
+ return rc;
+}
diff --git a/src/libs/qtcreatorcdbext/symbolgroupvalue.h b/src/libs/qtcreatorcdbext/symbolgroupvalue.h
new file mode 100644
index 0000000000..6e1f3339f5
--- /dev/null
+++ b/src/libs/qtcreatorcdbext/symbolgroupvalue.h
@@ -0,0 +1,128 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 SYMBOLGROUPVALUE_H
+#define SYMBOLGROUPVALUE_H
+
+#include "common.h"
+#include "knowntype.h"
+
+#include <string>
+#include <vector>
+
+class SymbolGroupNode;
+
+// Structure to pass all IDebug interfaces used for SymbolGroupValue
+struct SymbolGroupValueContext
+{
+ SymbolGroupValueContext(CIDebugDataSpaces *ds) : dataspaces(ds) {}
+ SymbolGroupValueContext::SymbolGroupValueContext() : dataspaces(0) {}
+
+ CIDebugDataSpaces *dataspaces;
+};
+
+/* SymbolGroupValue: Flyweight tied to a SymbolGroupNode
+ * providing a convenient operator[] + value getters for notation of dumpers.
+ * Inaccesible members return a SymbolGroupValue in state 'invalid'. */
+
+class SymbolGroupValue
+{
+public:
+ explicit SymbolGroupValue(SymbolGroupNode *node, const SymbolGroupValueContext &c);
+ SymbolGroupValue();
+
+ operator bool() const { return isValid(); }
+ bool isValid() const;
+
+ // Access children by name or index (0-based)
+ SymbolGroupValue operator[](const char *name) const;
+ SymbolGroupValue operator[](unsigned) const;
+ // take address and cast to desired (pointer) type
+ SymbolGroupValue typeCast(const char *type) const;
+ // take pointer value and cast to desired (pointer) type
+ SymbolGroupValue pointerTypeCast(const char *type) const;
+
+ std::string name() const;
+ std::string type() const;
+ std::vector<std::string> innerTypes() const { return innerTypesOf(type()); }
+ std::wstring value() const;
+ unsigned size() const;
+
+ SymbolGroupNode *node() const { return m_node; }
+ SymbolGroupValueContext context() const { return m_context; }
+
+ int intValue(int defaultValue = -1) const;
+ double floatValue(double defaultValue = -999) const;
+ ULONG64 pointerValue(ULONG64 defaultValue = 0) const;
+ ULONG64 address() const;
+ // Return allocated array of data pointed to
+ unsigned char *pointerData(unsigned length) const;
+ // Return data pointed to as wchar_t/std::wstring (UTF16)
+ std::wstring wcharPointerData(unsigned charCount, unsigned maxCharCount = 512) const;
+
+ std::string error() const;
+
+ // Some helpers for manipulating types.
+ static inline unsigned sizeOf(const char *type) { return GetTypeSize(type); }
+ static std::string stripPointerType(const std::string &);
+ static std::string addPointerType(const std::string &);
+ static std::string stripArrayType(const std::string &);
+ static bool isPointerType(const std::string &);
+ static unsigned pointerSize();
+
+ // get the inner types: "QMap<int, double>" -> "int", "double"
+ static std::vector<std::string> innerTypesOf(const std::string &t);
+
+private:
+ bool ensureExpanded() const;
+ SymbolGroupValue typeCastedValue(ULONG64 address, const char *type) const;
+
+ SymbolGroupNode *m_node;
+ SymbolGroupValueContext m_context;
+ mutable std::string m_errorMessage;
+};
+
+// For debugging purposes
+std::ostream &operator<<(std::ostream &, const SymbolGroupValue &v);
+
+/* Helpers for detecting types reported from IDebugSymbolGroup
+ * 1) Class prefix==true is applicable to outer types obtained from
+ * from IDebugSymbolGroup: 'class foo' or 'struct foo'.
+ * 2) Class prefix==false is for inner types of templates, etc, doing
+ * a more expensive check: 'foo' */
+KnownType knownType(const std::string &type, bool hasClassPrefix = true);
+
+// Dump builtin simple types using SymbolGroupValue expressions,
+// returning SymbolGroupNode dumper flags.
+unsigned dumpSimpleType(SymbolGroupNode *n, const SymbolGroupValueContext &ctx,
+ std::wstring *s,
+ int *knownType = 0,
+ int *containerSizeIn = 0);
+
+#endif // SYMBOLGROUPVALUE_H
diff --git a/src/libs/qtcreatorcdbext/test32.bat b/src/libs/qtcreatorcdbext/test32.bat
new file mode 100644
index 0000000000..00693f786d
--- /dev/null
+++ b/src/libs/qtcreatorcdbext/test32.bat
@@ -0,0 +1,24 @@
+@echo off
+
+REM test.bat: Test script to launch CDB.exe using the extension
+REM with the tests/manual demo project.
+
+REM !qtcreatorcdbext.help
+REM !qtcreatorcdbext.assign local.this.m_w=44
+REM !qtcreatorcdbext.locals 0
+
+set ROOT=d:\dev\qt4.7-vs8\creator
+
+set _NT_DEBUGGER_EXTENSION_PATH=%ROOT%\lib\qtcreatorcdbext32
+set EXT=qtcreatorcdbext.dll
+set EXE=%ROOT%\tests\manual\gdbdebugger\gui\debug\gui.exe
+
+set CDB=D:\Programme\Debugging Tools for Windows (x86)\cdb.exe
+
+echo %CDB%
+echo %EXT% %_NT_DEBUGGER_EXTENSION_PATH%
+
+echo "!qtcreatorcdbext.pid"
+
+REM Launch emulating cdbengine's setup with idle reporting
+"%CDB%" -G -a%EXT% -c ".idle_cmd !qtcreatorcdbext.idle" %EXE%
diff --git a/src/libs/qtcreatorcdbext/test64.bat b/src/libs/qtcreatorcdbext/test64.bat
new file mode 100644
index 0000000000..0185785f17
--- /dev/null
+++ b/src/libs/qtcreatorcdbext/test64.bat
@@ -0,0 +1,23 @@
+@echo off
+
+REM test.bat: Test script to launch CDB.exe using the extension
+REM with the tests/manual demo project.
+
+REM !qtcreatorcdbext.help
+REM !qtcreatorcdbext.assign local.this.m_w=44
+REM !qtcreatorcdbext.locals 0
+
+set ROOT=c:\qt\4.7-vs8\creator
+
+set _NT_DEBUGGER_EXTENSION_PATH=%ROOT%\lib\qtcreatorcdbext64
+set EXT=qtcreatorcdbext.dll
+set EXE=%ROOT%\tests\manual\gdbdebugger\gui\debug\gui.exe
+
+set CDB=C:\PROGRA~1\DEBUGG~1\cdb.exe
+
+echo %CDB%
+
+echo "!qtcreatorcdbext.pid"
+
+REM Launch emulating cdbengine's setup with idle reporting
+%CDB% -G -a%EXT% -c ".idle_cmd ^!qtcreatorcdbext.idle" %EXE%
diff --git a/src/libs/symbianutils/symbianutils.pri b/src/libs/symbianutils/symbianutils.pri
index 6d3b9b3122..c90d4da432 100644
--- a/src/libs/symbianutils/symbianutils.pri
+++ b/src/libs/symbianutils/symbianutils.pri
@@ -1,3 +1,3 @@
INCLUDEPATH *= $$PWD/../../shared/symbianutils
DEPENDPATH += $$PWD/../../shared/symbianutils
-LIBS *= -l$$qtLibraryTarget(symbianutils)
+LIBS *= -l$$qtLibraryName(symbianutils)
diff --git a/src/libs/utils/abstractprocess.h b/src/libs/utils/abstractprocess.h
index 4df6e196c6..14fbe50ed5 100644
--- a/src/libs/utils/abstractprocess.h
+++ b/src/libs/utils/abstractprocess.h
@@ -36,6 +36,8 @@
#include "utils_global.h"
+#include "environment.h"
+
#include <QtCore/QStringList>
namespace Utils {
@@ -49,10 +51,10 @@ public:
QString workingDirectory() const { return m_workingDir; }
void setWorkingDirectory(const QString &dir) { m_workingDir = dir; }
- QStringList environment() const { return m_environment; }
- void setEnvironment(const QStringList &env) { m_environment = env; }
+ void setEnvironment(const Environment &env) { m_environment = env; }
+ Environment environment() const { return m_environment; }
- virtual bool start(const QString &program, const QStringList &args) = 0;
+ virtual bool start(const QString &program, const QString &args) = 0;
virtual void stop() = 0;
virtual bool isRunning() const = 0;
@@ -67,14 +69,15 @@ public:
static QStringList fixWinEnvironment(const QStringList &env);
// Quote a Windows command line correctly for the "CreateProcess" API
static QString createWinCommandline(const QString &program, const QStringList &args);
+ static QString createWinCommandline(const QString &program, const QString &args);
// Create a bytearray suitable to be passed on as environment
// to the "CreateProcess" API (0-terminated UTF 16 strings).
static QByteArray createWinEnvironment(const QStringList &env);
#endif
-private:
+protected:
QString m_workingDir;
- QStringList m_environment;
+ Environment m_environment;
};
} //namespace Utils
diff --git a/src/libs/utils/abstractprocess_win.cpp b/src/libs/utils/abstractprocess_win.cpp
index c7f8348adb..0c61beb142 100644
--- a/src/libs/utils/abstractprocess_win.cpp
+++ b/src/libs/utils/abstractprocess_win.cpp
@@ -55,49 +55,57 @@ QStringList AbstractProcess::fixWinEnvironment(const QStringList &env)
return envStrings;
}
-QString AbstractProcess::createWinCommandline(const QString &program, const QStringList &args)
+static QString quoteWinCommand(const QString &program)
{
const QChar doubleQuote = QLatin1Char('"');
- const QChar blank = QLatin1Char(' ');
- const QChar backSlash = QLatin1Char('\\');
+ // add the programm as the first arg ... it works better
QString programName = program;
- if (!programName.startsWith(doubleQuote) && !programName.endsWith(doubleQuote) && programName.contains(blank)) {
- programName.insert(0, doubleQuote);
+ programName.replace(QLatin1Char('/'), QLatin1Char('\\'));
+ if (!programName.startsWith(doubleQuote) && !programName.endsWith(doubleQuote)
+ && programName.contains(QLatin1Char(' '))) {
+ programName.prepend(doubleQuote);
programName.append(doubleQuote);
}
- // add the prgram as the first arrg ... it works better
- programName.replace(QLatin1Char('/'), backSlash);
- QString cmdLine = programName;
- if (args.empty())
- return cmdLine;
+ return programName;
+}
+
+static QString quoteWinArgument(const QString &arg)
+{
+ if (!arg.length())
+ return QString::fromLatin1("\"\"");
+
+ QString ret(arg);
+ // Quotes are escaped and their preceding backslashes are doubled.
+ ret.replace(QRegExp(QLatin1String("(\\\\*)\"")), QLatin1String("\\1\\1\\\""));
+ if (ret.contains(QRegExp(QLatin1String("\\s")))) {
+ // The argument must not end with a \ since this would be interpreted
+ // as escaping the quote -- rather put the \ behind the quote: e.g.
+ // rather use "foo"\ than "foo\"
+ ret.replace(QRegExp(QLatin1String("(\\\\*)$")), QLatin1String("\"\\1"));
+ ret.prepend(QLatin1Char('"'));
+ }
+ return ret;
+}
- cmdLine += blank;
- for (int i = 0; i < args.size(); ++i) {
- QString tmp = args.at(i);
- // in the case of \" already being in the string the \ must also be escaped
- tmp.replace(QLatin1String("\\\""), QLatin1String("\\\\\""));
- // escape a single " because the arguments will be parsed
- tmp.replace(QString(doubleQuote), QLatin1String("\\\""));
- if (tmp.isEmpty() || tmp.contains(blank) || tmp.contains('\t')) {
- // The argument must not end with a \ since this would be interpreted
- // as escaping the quote -- rather put the \ behind the quote: e.g.
- // rather use "foo"\ than "foo\"
- QString endQuote(doubleQuote);
- int i = tmp.length();
- while (i > 0 && tmp.at(i - 1) == backSlash) {
- --i;
- endQuote += backSlash;
- }
- cmdLine += QLatin1String(" \"");
- cmdLine += tmp.left(i);
- cmdLine += endQuote;
- } else {
- cmdLine += blank;
- cmdLine += tmp;
- }
+QString AbstractProcess::createWinCommandline(const QString &program, const QStringList &args)
+{
+ QString programName = quoteWinCommand(program);
+ foreach (const QString &arg, args) {
+ programName += QLatin1Char(' ');
+ programName += quoteWinArgument(arg);
+ }
+ return programName;
+}
+
+QString AbstractProcess::createWinCommandline(const QString &program, const QString &args)
+{
+ QString programName = quoteWinCommand(program);
+ if (!args.isEmpty()) {
+ programName += QLatin1Char(' ');
+ programName += args;
}
- return cmdLine;
+ return programName;
}
QByteArray AbstractProcess::createWinEnvironment(const QStringList &env)
diff --git a/src/libs/utils/annotateditemdelegate.cpp b/src/libs/utils/annotateditemdelegate.cpp
new file mode 100644
index 0000000000..f4334b07c3
--- /dev/null
+++ b/src/libs/utils/annotateditemdelegate.cpp
@@ -0,0 +1,123 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "annotateditemdelegate.h"
+
+#include <QtCore/QSize>
+#include <QtCore/QModelIndex>
+#include <QtGui/QStandardItemModel>
+#include <QtGui/QPainter>
+#include <QtGui/QStyle>
+#include <QtGui/QStyleOptionViewItemV4>
+#include <QtGui/QApplication>
+
+using namespace Utils;
+
+AnnotatedItemDelegate::AnnotatedItemDelegate(QObject *parent) : QStyledItemDelegate(parent)
+{}
+
+AnnotatedItemDelegate::~AnnotatedItemDelegate()
+{}
+
+void AnnotatedItemDelegate::setAnnotationRole(int role)
+{
+ m_annotationRole = role;
+}
+
+int AnnotatedItemDelegate::annotationRole() const
+{
+ return m_annotationRole;
+}
+
+void AnnotatedItemDelegate::setDelimiter(const QString &delimiter)
+{
+ m_delimiter = delimiter;
+}
+
+const QString &AnnotatedItemDelegate::delimiter() const
+{
+ return m_delimiter;
+}
+
+void AnnotatedItemDelegate::paint(QPainter *painter,
+ const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ QStyleOptionViewItemV4 opt = option;
+ initStyleOption(&opt, index);
+
+ QStyle *style = QApplication::style();
+ style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, opt.widget);
+ style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, opt.widget);
+
+ QString annotation = index.data(m_annotationRole).toString();
+ if (!annotation.isEmpty()) {
+
+ int newlinePos = annotation.indexOf(QLatin1Char('\n'));
+ if (newlinePos != -1) {
+ // print first line with '...' at end
+ const QChar ellipsisChar(0x2026);
+ annotation = annotation.left(newlinePos) + ellipsisChar;
+ }
+
+ QPalette disabled(opt.palette);
+ disabled.setCurrentColorGroup(QPalette::Disabled);
+
+ painter->save();
+ painter->setPen(disabled.color(QPalette::WindowText));
+
+ static int extra = opt.fontMetrics.width(m_delimiter) + 10;
+ const QPixmap &pixmap = opt.icon.pixmap(opt.decorationSize);
+ const QRect &iconRect = style->itemPixmapRect(opt.rect, opt.decorationAlignment, pixmap);
+ const QRect &displayRect = style->itemTextRect(opt.fontMetrics, opt.rect,
+ opt.displayAlignment, true, index.data(Qt::DisplayRole).toString());
+ QRect annotationRect = style->itemTextRect(opt.fontMetrics, opt.rect,
+ opt.displayAlignment, true, annotation);
+ annotationRect.adjust(iconRect.width() + displayRect.width() + extra, 0,
+ iconRect.width() + displayRect.width() + extra, 0);
+
+ QApplication::style()->drawItemText(painter, annotationRect,
+ Qt::AlignLeft | Qt::AlignBottom, disabled, true, annotation);
+
+ painter->restore();
+ }
+}
+
+QSize AnnotatedItemDelegate::sizeHint(const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ QStyleOptionViewItemV4 opt = option;
+ initStyleOption(&opt, index);
+
+ const QString &annotation = index.data(m_annotationRole).toString();
+ if (!annotation.isEmpty())
+ opt.text += m_delimiter + annotation;
+
+ return QApplication::style()->sizeFromContents(QStyle::CT_ItemViewItem, &opt, QSize(), 0);
+}
diff --git a/src/libs/utils/annotateditemdelegate.h b/src/libs/utils/annotateditemdelegate.h
new file mode 100644
index 0000000000..77c403f295
--- /dev/null
+++ b/src/libs/utils/annotateditemdelegate.h
@@ -0,0 +1,66 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 ANNOTATEDITEMDELEGATE_H
+#define ANNOTATEDITEMDELEGATE_H
+
+#include "utils_global.h"
+
+#include <QtCore/QString>
+#include <QtCore/QSize>
+#include <QtGui/QStyledItemDelegate>
+
+namespace Utils {
+
+class QTCREATOR_UTILS_EXPORT AnnotatedItemDelegate : public QStyledItemDelegate
+{
+public:
+ AnnotatedItemDelegate(QObject *parent = 0);
+ virtual ~AnnotatedItemDelegate();
+
+ void setAnnotationRole(int role);
+ int annotationRole() const;
+
+ void setDelimiter(const QString &delimiter);
+ const QString &delimiter() const;
+
+protected:
+ virtual void paint(QPainter *painter,
+ const QStyleOptionViewItem &option,
+ const QModelIndex &index) const;
+ virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
+
+private:
+ int m_annotationRole;
+ QString m_delimiter;
+};
+
+} // Utils
+
+#endif // ANNOTATEDITEMDELEGATE_H
diff --git a/src/libs/utils/buildablehelperlibrary.cpp b/src/libs/utils/buildablehelperlibrary.cpp
index 37ae7f5b36..ce0da7769c 100644
--- a/src/libs/utils/buildablehelperlibrary.cpp
+++ b/src/libs/utils/buildablehelperlibrary.cpp
@@ -52,8 +52,11 @@ QString BuildableHelperLibrary::findSystemQt(const Utils::Environment &env)
{
QStringList paths = env.path();
foreach (const QString &path, paths) {
+ QString prefix = path;
+ if (!prefix.endsWith(QLatin1Char('/')))
+ prefix.append(QLatin1Char('/'));
foreach (const QString &possibleCommand, possibleQMakeCommands()) {
- const QFileInfo qmake(path + QLatin1Char('/') + possibleCommand);
+ const QFileInfo qmake(prefix + possibleCommand);
if (qmake.exists()) {
if (!qtVersionForQMake(qmake.absoluteFilePath()).isNull()) {
return qmake.absoluteFilePath();
@@ -94,10 +97,12 @@ QString BuildableHelperLibrary::qtVersionForQMake(const QString &qmakePath)
return QString();
}
const QString output = QString::fromLocal8Bit(qmake.readAllStandardOutput());
- QRegExp regexp(QLatin1String("(QMake version|QMake version:)[\\s]*([\\d.]*)"), Qt::CaseInsensitive);
+ static QRegExp regexp(QLatin1String("(QMake version|QMake version:)[\\s]*([\\d.]*)"),
+ Qt::CaseInsensitive);
regexp.indexIn(output);
if (regexp.cap(2).startsWith(QLatin1String("2."))) {
- QRegExp regexp2(QLatin1String("Using Qt version[\\s]*([\\d\\.]*)"), Qt::CaseInsensitive);
+ static QRegExp regexp2(QLatin1String("Using Qt version[\\s]*([\\d\\.]*)"),
+ Qt::CaseInsensitive);
regexp2.indexIn(output);
const QString version = regexp2.cap(1);
return version;
@@ -112,7 +117,7 @@ bool BuildableHelperLibrary::checkMinimumQtVersion(const QString &qtVersionStrin
int patch = -1;
// check format
- QRegExp qtVersionRegex(QLatin1String("^\\d+\\.\\d+\\.\\d+$"));
+ static QRegExp qtVersionRegex(QLatin1String("^\\d+\\.\\d+\\.\\d+$"));
if (!qtVersionRegex.exactMatch(qtVersionString))
return false;
@@ -167,6 +172,10 @@ bool BuildableHelperLibrary::copyFiles(const QString &sourcePath,
return false;
}
}
+ if (!destInfo.dir().exists()) {
+ QDir().mkpath(destInfo.dir().absolutePath());
+ }
+
if (!QFile::copy(source, dest)) {
*errorMessage = QCoreApplication::translate("ProjectExplorer::DebuggingHelperLibrary", "The file %1 could not be copied to %2.").arg(source, dest);
return false;
diff --git a/src/libs/utils/consoleprocess.h b/src/libs/utils/consoleprocess.h
index 4cd4879feb..899d31e299 100644
--- a/src/libs/utils/consoleprocess.h
+++ b/src/libs/utils/consoleprocess.h
@@ -58,7 +58,7 @@ public:
ConsoleProcess(QObject *parent = 0);
~ConsoleProcess();
- bool start(const QString &program, const QStringList &args);
+ bool start(const QString &program, const QString &args);
void stop();
void setMode(Mode m);
diff --git a/src/libs/utils/consoleprocess_unix.cpp b/src/libs/utils/consoleprocess_unix.cpp
index 8d27f310da..fc79741ac2 100644
--- a/src/libs/utils/consoleprocess_unix.cpp
+++ b/src/libs/utils/consoleprocess_unix.cpp
@@ -33,6 +33,9 @@
#include "consoleprocess.h"
+#include "environment.h"
+#include "qtcprocess.h"
+
#include <QtCore/QCoreApplication>
#include <QtCore/QDir>
#include <QtCore/QSettings>
@@ -70,6 +73,7 @@ ConsoleProcessPrivate::ConsoleProcessPrivate() :
m_mode(ConsoleProcess::Run),
m_appPid(0),
m_stubSocket(0),
+ m_tempFile(0),
m_settings(0)
{
}
@@ -118,18 +122,49 @@ void ConsoleProcess::setSettings(QSettings *settings)
d->m_settings = settings;
}
-bool ConsoleProcess::start(const QString &program, const QStringList &args)
+bool ConsoleProcess::start(const QString &program, const QString &args)
{
if (isRunning())
return false;
+ QtcProcess::SplitError perr;
+ QStringList pargs = QtcProcess::prepareArgs(args, &perr, &m_environment, &m_workingDir);
+ QString pcmd;
+ if (perr == QtcProcess::SplitOk) {
+ pcmd = program;
+ } else {
+ if (perr != QtcProcess::FoundMeta) {
+ emit processMessage(tr("Quoting error in command."), true);
+ return false;
+ }
+ if (d->m_mode == Debug) {
+ // FIXME: QTCREATORBUG-2809
+ emit processMessage(tr("Debugging complex shell commands in a terminal"
+ " is currently not supported."), true);
+ return false;
+ }
+ pcmd = QLatin1String("/bin/sh");
+ pargs << QLatin1String("-c") << (QtcProcess::quoteArg(program) + QLatin1Char(' ') + args);
+ }
+
+ QtcProcess::SplitError qerr;
+ QStringList xtermArgs = QtcProcess::prepareArgs(terminalEmulator(d->m_settings), &qerr,
+ &m_environment, &m_workingDir);
+ if (qerr != QtcProcess::SplitOk) {
+ emit processMessage(qerr == QtcProcess::BadQuoting
+ ? tr("Quoting error in terminal command.")
+ : tr("Terminal command may not be a shell command."), true);
+ return false;
+ }
+
const QString err = stubServerListen();
if (!err.isEmpty()) {
emit processMessage(msgCommChannelFailed(err), true);
return false;
}
- if (!environment().isEmpty()) {
+ QStringList env = m_environment.toStringList();
+ if (!env.isEmpty()) {
d->m_tempFile = new QTemporaryFile();
if (!d->m_tempFile->open()) {
stubServerShutdown();
@@ -138,14 +173,13 @@ bool ConsoleProcess::start(const QString &program, const QStringList &args)
d->m_tempFile = 0;
return false;
}
- foreach (const QString &var, environment()) {
+ foreach (const QString &var, env) {
d->m_tempFile->write(var.toLocal8Bit());
d->m_tempFile->write("", 1);
}
d->m_tempFile->flush();
}
- QStringList xtermArgs = terminalEmulator(d->m_settings).split(QLatin1Char(' ')); // FIXME: quoting
xtermArgs
#ifdef Q_OS_MAC
<< (QCoreApplication::applicationDirPath() + QLatin1String("/../Resources/qtcreator_process_stub"))
@@ -157,7 +191,7 @@ bool ConsoleProcess::start(const QString &program, const QStringList &args)
<< msgPromptToClose()
<< workingDirectory()
<< (d->m_tempFile ? d->m_tempFile->fileName() : QString())
- << program << args;
+ << pcmd << pargs;
QString xterm = xtermArgs.takeFirst();
d->m_process.start(xterm, xtermArgs);
diff --git a/src/libs/utils/consoleprocess_win.cpp b/src/libs/utils/consoleprocess_win.cpp
index 1e1cf10dfd..29572f5bbe 100644
--- a/src/libs/utils/consoleprocess_win.cpp
+++ b/src/libs/utils/consoleprocess_win.cpp
@@ -32,6 +32,8 @@
**************************************************************************/
#include "consoleprocess.h"
+#include "environment.h"
+#include "qtcprocess.h"
#include "winutils.h"
#include <windows.h>
@@ -119,18 +121,28 @@ QProcess::ExitStatus ConsoleProcess::exitStatus() const
return d->m_appStatus;
}
-bool ConsoleProcess::start(const QString &program, const QStringList &args)
+bool ConsoleProcess::start(const QString &program, const QString &args)
{
if (isRunning())
return false;
+ QString pcmd;
+ QString pargs;
+ if (d->m_mode != Run) { // The debugger engines already pre-process the arguments.
+ pcmd = program;
+ pargs = args;
+ } else {
+ QtcProcess::prepareCommand(program, args, &pcmd, &pargs, &m_environment, &m_workingDir);
+ }
+
const QString err = stubServerListen();
if (!err.isEmpty()) {
emit processMessage(msgCommChannelFailed(err), true);
return false;
}
- if (!environment().isEmpty()) {
+ QStringList env = m_environment.toStringList();
+ if (!env.isEmpty()) {
d->m_tempFile = new QTemporaryFile();
if (!d->m_tempFile->open()) {
stubServerShutdown();
@@ -142,7 +154,7 @@ bool ConsoleProcess::start(const QString &program, const QStringList &args)
QTextStream out(d->m_tempFile);
out.setCodec("UTF-16LE");
out.setGenerateByteOrderMark(false);
- foreach (const QString &var, fixWinEnvironment(environment()))
+ foreach (const QString &var, fixWinEnvironment(env))
out << var << QChar(0);
out << QChar(0);
}
@@ -163,7 +175,7 @@ bool ConsoleProcess::start(const QString &program, const QStringList &args)
<< d->m_stubServer.fullServerName()
<< workDir
<< (d->m_tempFile ? d->m_tempFile->fileName() : 0)
- << createWinCommandline(program, args)
+ << createWinCommandline(pcmd, pargs)
<< msgPromptToClose();
const QString cmdLine = createWinCommandline(
diff --git a/src/libs/utils/crumblepath.h b/src/libs/utils/crumblepath.h
index 2a53431f10..fd72b09b56 100644
--- a/src/libs/utils/crumblepath.h
+++ b/src/libs/utils/crumblepath.h
@@ -38,7 +38,7 @@
#include <QtGui/QWidget>
-QT_FORWARD_DECLARE_CLASS(QResizeEvent);
+QT_FORWARD_DECLARE_CLASS(QResizeEvent)
namespace Utils {
diff --git a/src/libs/utils/debuggerlanguagechooser.h b/src/libs/utils/debuggerlanguagechooser.h
index 9cbba1e519..434c6484c3 100644
--- a/src/libs/utils/debuggerlanguagechooser.h
+++ b/src/libs/utils/debuggerlanguagechooser.h
@@ -5,9 +5,9 @@
#include <QtGui/QWidget>
-QT_FORWARD_DECLARE_CLASS(QCheckBox);
-QT_FORWARD_DECLARE_CLASS(QLabel);
-QT_FORWARD_DECLARE_CLASS(QSpinBox);
+QT_FORWARD_DECLARE_CLASS(QCheckBox)
+QT_FORWARD_DECLARE_CLASS(QLabel)
+QT_FORWARD_DECLARE_CLASS(QSpinBox)
namespace Utils {
diff --git a/src/libs/utils/detailsbutton.cpp b/src/libs/utils/detailsbutton.cpp
index 9b1d24e2f4..11d313a499 100644
--- a/src/libs/utils/detailsbutton.cpp
+++ b/src/libs/utils/detailsbutton.cpp
@@ -58,6 +58,11 @@ FadingPanel::FadingPanel(QWidget *parent) :
setPalette(pal);
}
+void FadingPanel::setOpacity(qreal value)
+{
+ m_opacityEffect->setOpacity(value);
+}
+
void FadingPanel::fadeTo(float value)
{
QPropertyAnimation *animation = new QPropertyAnimation(m_opacityEffect, "opacity");
diff --git a/src/libs/utils/detailsbutton.h b/src/libs/utils/detailsbutton.h
index eb8a1e49e4..2795304e76 100644
--- a/src/libs/utils/detailsbutton.h
+++ b/src/libs/utils/detailsbutton.h
@@ -47,6 +47,7 @@ class QTCREATOR_UTILS_EXPORT FadingPanel : public QWidget
{
public:
FadingPanel(QWidget *parent = 0);
+ void setOpacity(qreal value);
void fadeTo(float value);
protected:
QGraphicsOpacityEffect *m_opacityEffect;
diff --git a/src/libs/utils/detailswidget.cpp b/src/libs/utils/detailswidget.cpp
index 2500d73672..d8efdf6ac0 100644
--- a/src/libs/utils/detailswidget.cpp
+++ b/src/libs/utils/detailswidget.cpp
@@ -228,6 +228,9 @@ namespace Utils {
d->m_toolWidget->adjustSize();
d->m_grid->addWidget(d->m_toolWidget, 0, 1, 1, 1, Qt::AlignRight);
+#ifdef Q_WS_MAC
+ d->m_toolWidget->setOpacity(1.0);
+#endif
changeHoverState(d->m_hovered);
}
diff --git a/src/libs/utils/environment.cpp b/src/libs/utils/environment.cpp
index f25bc4bf40..8531b9777b 100644
--- a/src/libs/utils/environment.cpp
+++ b/src/libs/utils/environment.cpp
@@ -186,41 +186,56 @@ void Environment::clear()
}
QString Environment::searchInPath(const QString &executable,
- const QStringList & additionalDirs) const
+ const QStringList &additionalDirs) const
{
- QString exec = expandVariables(executable);
+ QStringList execs;
+ execs << executable;
+#ifdef Q_OS_WIN
+ // Check all the executable extensions on windows:
+ QStringList extensions = value(QLatin1String("PATHEXT")).split(QLatin1Char(';'));
- if (exec.isEmpty() || QFileInfo(exec).isAbsolute())
- return QDir::toNativeSeparators(exec);
+ // .exe.bat is legal (and run when starting new.exe), so always go through the complete list once:
+ foreach (const QString &ext, extensions)
+ execs << executable + ext.toLower();
+#endif
+ return searchInPath(execs, additionalDirs);
+}
- // Check in directories:
- foreach (const QString &dir, additionalDirs) {
- if (dir.isEmpty())
+QString Environment::searchInPath(const QStringList &executables,
+ const QStringList &additionalDirs) const
+{
+ foreach (const QString &executable, executables) {
+ QString exec = expandVariables(executable);
+
+ if (exec.isEmpty())
continue;
- QFileInfo fi(dir + QLatin1Char('/') + exec);
- if (fi.isFile() && fi.isExecutable())
- return fi.absoluteFilePath();
- }
- // Check in path:
- if (exec.indexOf(QChar('/')) != -1)
- return QString();
- const QChar slash = QLatin1Char('/');
- foreach (const QString &p, path()) {
- QString fp = p;
- fp += slash;
- fp += exec;
- const QFileInfo fi(fp);
- if (fi.exists())
- return fi.absoluteFilePath();
- }
+ QFileInfo baseFi(exec);
+ if (baseFi.isAbsolute() && baseFi.exists())
+ return QDir::toNativeSeparators(exec);
+
+ // Check in directories:
+ foreach (const QString &dir, additionalDirs) {
+ if (dir.isEmpty())
+ continue;
+ QFileInfo fi(dir + QLatin1Char('/') + exec);
+ if (fi.isFile() && fi.isExecutable())
+ return fi.absoluteFilePath();
+ }
-#ifdef Q_OS_WIN
- if (!exec.endsWith(QLatin1String(".exe"))) {
- exec.append(QLatin1String(".exe"));
- return searchInPath(exec, additionalDirs);
+ // Check in path:
+ const QChar slash = QLatin1Char('/');
+ if (exec.indexOf(slash) != -1)
+ continue;
+ foreach (const QString &p, path()) {
+ QString fp = p;
+ fp += slash;
+ fp += exec;
+ const QFileInfo fi(fp);
+ if (fi.exists())
+ return fi.absoluteFilePath();
+ }
}
-#endif
return QString();
}
@@ -259,7 +274,7 @@ Environment::const_iterator Environment::constEnd() const
return m_values.constEnd();
}
-Environment::const_iterator Environment::find(const QString &name)
+Environment::const_iterator Environment::constFind(const QString &name) const
{
QMap<QString, QString>::const_iterator it = m_values.constFind(name);
if (it == m_values.constEnd())
@@ -293,7 +308,7 @@ void Environment::modify(const QList<EnvironmentItem> & list)
end = value.indexOf('}', i);
if (end != -1) {
const QString &name = value.mid(i+2, end-i-2);
- Environment::const_iterator it = find(name);
+ Environment::const_iterator it = constFind(name);
if (it != constEnd())
value.replace(i, end-i+1, it.value());
}
@@ -321,125 +336,79 @@ bool Environment::operator==(const Environment &other) const
return m_values == other.m_values;
}
-QStringList Environment::parseCombinedArgString(const QString &program)
-{
- QStringList args;
- QString tmp;
- int quoteCount = 0;
- bool inQuote = false;
-
- // handle quoting. tokens can be surrounded by double quotes
- // "hello world". three consecutive double quotes represent
- // the quote character itself.
- for (int i = 0; i < program.size(); ++i) {
- if (program.at(i) == QLatin1Char('"')) {
- ++quoteCount;
- if (quoteCount == 3) {
- // third consecutive quote
- quoteCount = 0;
- tmp += program.at(i);
- }
- continue;
- }
- if (quoteCount) {
- if (quoteCount == 1)
- inQuote = !inQuote;
- quoteCount = 0;
- }
- if (!inQuote && program.at(i).isSpace()) {
- if (!tmp.isEmpty()) {
- args += tmp;
- tmp.clear();
- }
- } else {
- tmp += program.at(i);
- }
- }
- if (!tmp.isEmpty())
- args += tmp;
- return args;
-}
-
-QString Environment::joinArgumentList(const QStringList &arguments)
-{
- QString result;
- const QChar doubleQuote = QLatin1Char('"');
- foreach (QString arg, arguments) {
- if (!result.isEmpty())
- result += QLatin1Char(' ');
- arg.replace(QString(doubleQuote), QLatin1String("\"\"\""));
- if (arg.contains(QLatin1Char(' '))) {
- arg.insert(0, doubleQuote);
- arg += doubleQuote;
- }
- result += arg;
- }
- return result;
-}
-
-enum State { BASE, VARIABLE, OPTIONALVARIABLEBRACE, STRING };
-
/** Expand environment variables in a string.
*
* Environment variables are accepted in the following forms:
- * $SOMEVAR, ${SOMEVAR} and %SOMEVAR%.
- *
- * Strings enclosed in '"' characters do not get varaibles
- * substituted.
+ * $SOMEVAR, ${SOMEVAR} on Unix and %SOMEVAR% on Windows.
+ * No escapes and quoting are supported.
+ * If a variable is not found, it is not substituted.
*/
QString Environment::expandVariables(const QString &input) const
{
- QString result;
- QString variable;
- QChar endVariable;
- State state = BASE;
-
- int length = input.count();
- for (int i = 0; i < length; ++i) {
- QChar c = input.at(i);
+ QString result = input;
+
+#ifdef Q_OS_WIN
+ for (int vStart = -1, i = 0; i < result.length(); ) {
+ if (result.at(i++) == QLatin1Char('%')) {
+ if (vStart > 0) {
+ const_iterator it = m_values.constFind(result.mid(vStart, i - vStart - 1).toUpper());
+ if (it != m_values.constEnd()) {
+ result.replace(vStart - 1, i - vStart + 1, *it);
+ i = vStart - 1 + it->length();
+ vStart = -1;
+ } else {
+ vStart = i;
+ }
+ } else {
+ vStart = i;
+ }
+ }
+ }
+#else
+ enum { BASE, OPTIONALVARIABLEBRACE, VARIABLE, BRACEDVARIABLE } state = BASE;
+ int vStart = -1;
+
+ for (int i = 0; i < result.length();) {
+ QChar c = result.at(i++);
if (state == BASE) {
- if (c == '$') {
+ if (c == QLatin1Char('$'))
state = OPTIONALVARIABLEBRACE;
- variable.clear();
- endVariable = QChar(0);
- } else if (c == '%') {
+ } else if (state == OPTIONALVARIABLEBRACE) {
+ if (c == QLatin1Char('{')) {
+ state = BRACEDVARIABLE;
+ vStart = i;
+ } else if (c.isLetterOrNumber() || c == QLatin1Char('_')) {
state = VARIABLE;
- variable.clear();
- endVariable = '%';
- } else if (c == '\"') {
- state = STRING;
- result += c;
+ vStart = i - 1;
} else {
- result += c;
- }
- } else if (state == VARIABLE) {
- if (c == endVariable) {
- result += value(variable);
state = BASE;
- } else if (c.isLetterOrNumber() || c == '_') {
- variable += c;
- } else {
- result += value(variable);
- result += c;
+ }
+ } else if (state == BRACEDVARIABLE) {
+ if (c == QLatin1Char('}')) {
+ const_iterator it = m_values.constFind(result.mid(vStart, i - 1 - vStart));
+ if (it != constEnd()) {
+ result.replace(vStart - 2, i - vStart + 2, *it);
+ i = vStart - 2 + it->length();
+ }
state = BASE;
}
- } else if (state == OPTIONALVARIABLEBRACE) {
- if (c == '{')
- endVariable = '}';
- else
- variable = c;
- state = VARIABLE;
- } else if (state == STRING) {
- if (c == '\"') {
+ } else if (state == VARIABLE) {
+ if (!c.isLetterOrNumber() && c != QLatin1Char('_')) {
+ const_iterator it = m_values.constFind(result.mid(vStart, i - vStart - 1));
+ if (it != constEnd()) {
+ result.replace(vStart - 1, i - vStart, *it);
+ i = vStart - 1 + it->length();
+ }
state = BASE;
- result += c;
- } else {
- result += c;
}
}
}
- if (state == VARIABLE)
- result += value(variable);
+ if (state == VARIABLE) {
+ const_iterator it = m_values.constFind(result.mid(vStart));
+ if (it != constEnd())
+ result.replace(vStart - 1, result.length() - vStart + 1, *it);
+ }
+#endif
return result;
}
diff --git a/src/libs/utils/environment.h b/src/libs/utils/environment.h
index b1fc1486ed..6964b5ee38 100644
--- a/src/libs/utils/environment.h
+++ b/src/libs/utils/environment.h
@@ -54,7 +54,7 @@ public:
QString value;
bool unset;
- bool operator==(const EnvironmentItem &other)
+ bool operator==(const EnvironmentItem &other) const
{
return (unset == other.unset) && (name == other.name) && (value == other.value);
}
@@ -87,26 +87,25 @@ public:
void clear();
int size() const;
- Environment::const_iterator find(const QString &name);
QString key(Environment::const_iterator it) const;
QString value(Environment::const_iterator it) const;
Environment::const_iterator constBegin() const;
Environment::const_iterator constEnd() const;
+ Environment::const_iterator constFind(const QString &name) const;
QString searchInPath(const QString &executable,
const QStringList & additionalDirs = QStringList()) const;
QStringList path() const;
- static QStringList parseCombinedArgString(const QString &program);
- static QString joinArgumentList(const QStringList &arguments);
-
QString expandVariables(const QString &) const;
QStringList expandVariables(const QStringList &) const;
bool operator!=(const Environment &other) const;
bool operator==(const Environment &other) const;
private:
+ QString searchInPath(const QStringList &executables,
+ const QStringList & additionalDirs = QStringList()) const;
QMap<QString, QString> m_values;
};
diff --git a/src/libs/utils/fileinprojectfinder.cpp b/src/libs/utils/fileinprojectfinder.cpp
new file mode 100644
index 0000000000..141c78e732
--- /dev/null
+++ b/src/libs/utils/fileinprojectfinder.cpp
@@ -0,0 +1,122 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "fileinprojectfinder.h"
+#include <utils/qtcassert.h>
+
+#include <QFileInfo>
+
+namespace Utils {
+
+/**
+ \class FileInProjectFinder
+
+ Helper class to find the 'original' file in the project directory for a given file path.
+
+ Often files are copied in the build + deploy process. findFile() searches for an existing file
+ in the project directory for a given file path:
+
+ E.g. following file paths:
+ C:/app-build-desktop/qml/app/main.qml (shadow build directory)
+ C:/Private/e3026d63/qml/app/main.qml (Application data folder on Symbian device)
+ /Users/x/app-build-desktop/App.app/Contents/Resources/qml/App/main.qml (folder on Mac OS X)
+ should all be mapped to
+ $PROJECTDIR/qml/app/main.qml
+ */
+FileInProjectFinder::FileInProjectFinder()
+{
+}
+
+void FileInProjectFinder::setProjectDirectory(const QString &absoluteProjectPath)
+{
+ QTC_ASSERT(QFileInfo(absoluteProjectPath).exists()
+ && QFileInfo(absoluteProjectPath).isAbsolute(), return);
+
+ if (absoluteProjectPath == m_projectDir)
+ return;
+
+ m_projectDir = absoluteProjectPath;
+ while (m_projectDir.endsWith(QLatin1Char('/')))
+ m_projectDir.remove(m_projectDir.length() - 1, 1);
+
+ m_cache.clear();
+}
+
+QString FileInProjectFinder::projectDirectory() const
+{
+ return m_projectDir;
+}
+
+/**
+ Returns the best match for the given originalPath in the project directory.
+
+ The method first checks whether the originalPath inside the project directory exists.
+ If not, the leading directory in the path is stripped, and the - now shorter - path is
+ checked for existence. This continues until either the file is found, or the relative path
+ does not contain any directories any more: In this case the originalPath is returned.
+ */
+QString FileInProjectFinder::findFile(const QString &originalPath, bool *success) const
+{
+ if (m_projectDir.isEmpty())
+ return originalPath;
+
+ const QChar separator = QLatin1Char('/');
+ if (originalPath.startsWith(m_projectDir + separator)) {
+ return originalPath;
+ }
+
+ if (m_cache.contains(originalPath))
+ return m_cache.value(originalPath);
+
+ // Strip directories one by one from the beginning of the path,
+ // and see if the new relative path exists in the build directory.
+ if (originalPath.contains(separator)) {
+ for (int pos = originalPath.indexOf(separator); pos != -1;
+ pos = originalPath.indexOf(separator, pos + 1)) {
+ QString candidate = originalPath;
+ candidate.remove(0, pos);
+ candidate.prepend(m_projectDir);
+ QFileInfo candidateInfo(candidate);
+ if (candidateInfo.exists() && candidateInfo.isFile()) {
+ if (success)
+ *success = true;
+
+ m_cache.insert(originalPath, candidate);
+ return candidate;
+ }
+ }
+ }
+
+ if (success)
+ *success = false;
+
+ return originalPath;
+}
+
+} // namespace Utils
diff --git a/src/libs/utils/fileinprojectfinder.h b/src/libs/utils/fileinprojectfinder.h
new file mode 100644
index 0000000000..552ae494fa
--- /dev/null
+++ b/src/libs/utils/fileinprojectfinder.h
@@ -0,0 +1,61 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** No Commercial Usage
+**
+** This file 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.
+**
+**************************************************************************/
+
+#ifndef FILEINPROJECTFINDER_H
+#define FILEINPROJECTFINDER_H
+
+#include <utils/utils_global.h>
+
+#include <QtCore/QHash>
+#include <QtCore/QString>
+
+namespace Utils {
+
+class QTCREATOR_UTILS_EXPORT FileInProjectFinder
+{
+public:
+ FileInProjectFinder();
+
+ void setProjectDirectory(const QString &absoluteProjectPath);
+ QString projectDirectory() const;
+
+ QString findFile(const QString &originalPath, bool *success = 0) const;
+
+private:
+ QString m_projectDir;
+ mutable QHash<QString,QString> m_cache;
+};
+
+} // namespace Utils
+
+#endif // FILEINPROJECTFINDER_H
diff --git a/src/libs/utils/filesearch.cpp b/src/libs/utils/filesearch.cpp
index 7f76401bc3..a3ddb6d2a2 100644
--- a/src/libs/utils/filesearch.cpp
+++ b/src/libs/utils/filesearch.cpp
@@ -83,23 +83,21 @@ void runFileSearch(QFutureInterface<FileSearchResultList> &future,
future.setProgressRange(0, files->maxProgress());
future.setProgressValueAndText(files->currentProgress(), msgFound(searchTerm, numMatches, numFilesSearched));
- bool caseInsensitive = !(flags & QTextDocument::FindCaseSensitively);
- bool wholeWord = (flags & QTextDocument::FindWholeWords);
+ const bool caseInsensitive = !(flags & QTextDocument::FindCaseSensitively);
+ const bool wholeWord = (flags & QTextDocument::FindWholeWords);
- QByteArray sa = searchTerm.toUtf8();
- int scMaxIndex = sa.length()-1;
- const char *sc = sa.constData();
+ const QString searchTermLower = searchTerm.toLower();
+ const QString searchTermUpper = searchTerm.toUpper();
- QByteArray sal = searchTerm.toLower().toUtf8();
- const char *scl = sal.constData();
-
- QByteArray sau = searchTerm.toUpper().toUtf8();
- const char *scu = sau.constData();
-
- int chunkSize = qMax(100000, sa.length());
+ const int termLength = searchTerm.length();
+ const int termMaxIndex = termLength - 1;
+ const QChar *termData = searchTerm.constData();
+ const QChar *termDataLower = searchTermLower.constData();
+ const QChar *termDataUpper = searchTermUpper.constData();
QFile file;
- QBuffer buffer;
+ QString str;
+ QTextStream stream;
FileSearchResultList results;
while (files->hasNext()) {
const QString &s = files->next();
@@ -109,83 +107,76 @@ void runFileSearch(QFutureInterface<FileSearchResultList> &future,
future.setProgressValueAndText(files->currentProgress(), msgCanceled(searchTerm, numMatches, numFilesSearched));
break;
}
- QIODevice *device;
+
+ bool needsToCloseFile = false;
if (fileToContentsMap.contains(s)) {
- buffer.setData(fileToContentsMap.value(s).toUtf8());
- device = &buffer;
+ str = fileToContentsMap.value(s);
+ stream.setString(&str);
} else {
file.setFileName(s);
- device = &file;
+ if (!file.open(QIODevice::ReadOnly))
+ continue;
+ needsToCloseFile = true;
+ stream.setDevice(&file);
+ stream.setCodec(files->encoding());
}
- if (!device->open(QIODevice::ReadOnly))
- continue;
- int lineNr = 1;
- const char *startOfLastLine = NULL;
-
- bool firstChunk = true;
- while (!device->atEnd()) {
- if (!firstChunk)
- device->seek(device->pos()-sa.length()+1);
-
- const QByteArray chunk = device->read(chunkSize);
- const char *chunkPtr = chunk.constData();
- startOfLastLine = chunkPtr;
- for (const char *regionPtr = chunkPtr; regionPtr < chunkPtr + chunk.length()-scMaxIndex; ++regionPtr) {
- const char *regionEnd = regionPtr + scMaxIndex;
-
- if (*regionPtr == '\n') {
- startOfLastLine = regionPtr + 1;
- ++lineNr;
- }
- else if (
+
+ int lineNr = 0;
+ while (!stream.atEnd()) {
+ ++lineNr;
+ const QString chunk = stream.readLine();
+ int chunkLength = chunk.length();
+ const QChar *chunkPtr = chunk.constData();
+ const QChar *chunkEnd = chunkPtr + chunkLength - 1;
+ for (const QChar *regionPtr = chunkPtr;
+ regionPtr + termMaxIndex <= chunkEnd;
+ ++regionPtr) {
+ const QChar *regionEnd = regionPtr + termMaxIndex;
+ if ( /* optimization check for start and end of region */
// case sensitive
- (!caseInsensitive && *regionPtr == sc[0] && *regionEnd == sc[scMaxIndex])
+ (!caseInsensitive && *regionPtr == termData[0] && *regionEnd == termData[termMaxIndex])
||
// case insensitive
- (caseInsensitive && (*regionPtr == scl[0] || *regionPtr == scu[0])
- && (*regionEnd == scl[scMaxIndex] || *regionEnd == scu[scMaxIndex]))
+ (caseInsensitive && (*regionPtr == termDataLower[0] || *regionPtr == termDataUpper[0])
+ && (*regionEnd == termDataLower[termMaxIndex] || *regionEnd == termDataUpper[termMaxIndex]))
) {
- const char *afterRegion = regionEnd + 1;
- const char *beforeRegion = regionPtr - 1;
bool equal = true;
- if (wholeWord &&
- ( isalnum((unsigned char)*beforeRegion)
- || (*beforeRegion == '_')
- || isalnum((unsigned char)*afterRegion)
- || (*afterRegion == '_'))) {
+
+ // whole word check
+ const QChar *beforeRegion = regionPtr - 1;
+ const QChar *afterRegion = regionEnd + 1;
+ if (wholeWord && (
+ ((beforeRegion >= chunkPtr) && (beforeRegion->isLetterOrNumber() || ((*beforeRegion) == QLatin1Char('_')))) ||
+ ((afterRegion <= chunkEnd) && (afterRegion->isLetterOrNumber() || ((*afterRegion) == QLatin1Char('_'))))
+ )) {
equal = false;
}
- int regionIndex = 1;
- for (const char *regionCursor = regionPtr + 1; regionCursor < regionEnd; ++regionCursor, ++regionIndex) {
- if ( // case sensitive
- (!caseInsensitive && equal && *regionCursor != sc[regionIndex])
- ||
- // case insensitive
- (caseInsensitive && equal && *regionCursor != sc[regionIndex] && *regionCursor != scl[regionIndex] && *regionCursor != scu[regionIndex])
- ) {
- equal = false;
+ if (equal) {
+ // check all chars
+ int regionIndex = 1;
+ for (const QChar *regionCursor = regionPtr + 1; regionCursor < regionEnd; ++regionCursor, ++regionIndex) {
+ if ( // case sensitive
+ (!caseInsensitive && *regionCursor != termData[regionIndex])
+ ||
+ // case insensitive
+ (caseInsensitive && *regionCursor != termData[regionIndex]
+ && *regionCursor != termDataLower[regionIndex] && *regionCursor != termDataUpper[regionIndex])
+ ) {
+ equal = false;
+ }
}
}
if (equal) {
- int textLength = chunk.length() - (startOfLastLine - chunkPtr);
- if (textLength > 0) {
- QByteArray res;
- res.reserve(256);
- int i = 0;
- int n = 0;
- while (startOfLastLine[i] != '\n' && startOfLastLine[i] != '\r' && i < textLength && n++ < 256)
- res.append(startOfLastLine[i++]);
- results << FileSearchResult(s, lineNr, QString::fromUtf8(res),
- regionPtr - startOfLastLine, sa.length(),
- QStringList());
- ++numMatches;
- }
+ results << FileSearchResult(s, lineNr, chunk,
+ regionPtr - chunkPtr, termLength,
+ QStringList());
+ ++numMatches;
}
}
}
- firstChunk = false;
}
+
++numFilesSearched;
if (future.isProgressUpdateNeeded()) {
if (!results.isEmpty()) {
@@ -195,7 +186,11 @@ void runFileSearch(QFutureInterface<FileSearchResultList> &future,
future.setProgressRange(0, files->maxProgress());
future.setProgressValueAndText(files->currentProgress(), msgFound(searchTerm, numMatches, numFilesSearched));
}
- device->close();
+
+ // clean up
+ if (needsToCloseFile)
+ file.close();
+
}
if (!results.isEmpty()) {
future.reportResult(results);
@@ -244,6 +239,7 @@ void runFileSearchRegExp(QFutureInterface<FileSearchResultList> &future,
continue;
needsToCloseFile = true;
stream.setDevice(&file);
+ stream.setCodec(files->encoding());
}
int lineNr = 1;
QString line;
@@ -299,8 +295,9 @@ QFuture<FileSearchResultList> Utils::findInFilesRegExp(const QString &searchTerm
QString Utils::expandRegExpReplacement(const QString &replaceText, const QStringList &capturedTexts)
{
+ // handles \1 \\ \& & \t \n
QString result;
- int numCaptures = capturedTexts.size() - 1;
+ const int numCaptures = capturedTexts.size() - 1;
for (int i = 0; i < replaceText.length(); ++i) {
QChar c = replaceText.at(i);
if (c == QLatin1Char('\\') && i < replaceText.length() - 1) {
@@ -309,6 +306,10 @@ QString Utils::expandRegExpReplacement(const QString &replaceText, const QString
result += QLatin1Char('\\');
} else if (c == QLatin1Char('&')) {
result += QLatin1Char('&');
+ } else if (c == QLatin1Char('t')) {
+ result += QLatin1Char('\t');
+ } else if (c == QLatin1Char('n')) {
+ result += QLatin1Char('\n');
} else if (c.isDigit()) {
int index = c.unicode()-'1';
if (index < numCaptures) {
@@ -335,14 +336,16 @@ QString Utils::expandRegExpReplacement(const QString &replaceText, const QString
FileIterator::FileIterator()
: m_list(QStringList()),
m_iterator(0),
- m_index(0)
+ m_index(-1)
{
}
-FileIterator::FileIterator(const QStringList &fileList)
+FileIterator::FileIterator(const QStringList &fileList,
+ const QList<QTextCodec *> encodings)
: m_list(fileList),
- m_iterator(new QStringListIterator(m_list)),
- m_index(0)
+ m_iterator(new QStringListIterator(m_list)),
+ m_encodings(encodings),
+ m_index(-1)
{
}
@@ -372,7 +375,14 @@ int FileIterator::maxProgress() const
int FileIterator::currentProgress() const
{
- return m_index;
+ return m_index + 1;
+}
+
+QTextCodec * FileIterator::encoding() const
+{
+ if (m_index >= 0 && m_index < m_encodings.size())
+ return m_encodings.at(m_index);
+ return QTextCodec::codecForLocale();
}
// #pragma mark -- SubDirFileIterator
@@ -381,9 +391,11 @@ namespace {
const int MAX_PROGRESS = 1000;
}
-SubDirFileIterator::SubDirFileIterator(const QStringList &directories, const QStringList &filters)
+SubDirFileIterator::SubDirFileIterator(const QStringList &directories, const QStringList &filters,
+ QTextCodec *encoding)
: m_filters(filters), m_progress(0)
{
+ m_encoding = (encoding == 0 ? QTextCodec::codecForLocale() : encoding);
qreal maxPer = MAX_PROGRESS/directories.count();
foreach (const QString &directoryEntry, directories) {
if (!directoryEntry.isEmpty()) {
@@ -400,8 +412,8 @@ bool SubDirFileIterator::hasNext() const
return true;
while(!m_dirs.isEmpty() && m_currentFiles.isEmpty()) {
QDir dir = m_dirs.pop();
- qreal dirProgressMax = m_progressValues.pop();
- bool processed = m_processedValues.pop();
+ const qreal dirProgressMax = m_progressValues.pop();
+ const bool processed = m_processedValues.pop();
if (dir.exists()) {
QStringList subDirs;
if (!processed) {
@@ -458,3 +470,8 @@ int SubDirFileIterator::currentProgress() const
{
return qMin(qRound(m_progress), MAX_PROGRESS);
}
+
+QTextCodec * SubDirFileIterator::encoding() const
+{
+ return m_encoding;
+}
diff --git a/src/libs/utils/filesearch.h b/src/libs/utils/filesearch.h
index b62e953642..578aad3261 100644
--- a/src/libs/utils/filesearch.h
+++ b/src/libs/utils/filesearch.h
@@ -41,6 +41,7 @@
#include <QtCore/QMap>
#include <QtCore/QStack>
#include <QtCore/QDir>
+#include <QtCore/QTextCodec>
#include <QtGui/QTextDocument>
namespace Utils {
@@ -49,32 +50,38 @@ class QTCREATOR_UTILS_EXPORT FileIterator
{
public:
FileIterator();
- explicit FileIterator(const QStringList &fileList);
+ explicit FileIterator(const QStringList &fileList,
+ const QList<QTextCodec *> encodings);
~FileIterator();
virtual bool hasNext() const;
virtual QString next();
+ virtual QTextCodec *encoding() const;
virtual int maxProgress() const;
virtual int currentProgress() const;
private:
QStringList m_list;
QStringListIterator *m_iterator;
+ QList<QTextCodec *> m_encodings;
int m_index;
};
class QTCREATOR_UTILS_EXPORT SubDirFileIterator : public FileIterator
{
public:
- SubDirFileIterator(const QStringList &directories, const QStringList &filters);
+ SubDirFileIterator(const QStringList &directories, const QStringList &filters,
+ QTextCodec *encoding = 0);
bool hasNext() const;
QString next();
+ QTextCodec *encoding() const;
int maxProgress() const;
int currentProgress() const;
private:
QStringList m_filters;
+ QTextCodec *m_encoding;
mutable QStack<QDir> m_dirs;
mutable QStack<qreal> m_progressValues;
mutable QStack<bool> m_processedValues;
diff --git a/src/libs/utils/historycompleter.cpp b/src/libs/utils/historycompleter.cpp
index 6a3ac070b9..dd68809699 100644
--- a/src/libs/utils/historycompleter.cpp
+++ b/src/libs/utils/historycompleter.cpp
@@ -69,7 +69,7 @@ public:
HistoryCompleterPrivate(HistoryCompleter *parent);
HistoryCompleter *q_ptr;
HistoryListModel *model;
- Q_DECLARE_PUBLIC(HistoryCompleter);
+ Q_DECLARE_PUBLIC(HistoryCompleter)
};
class HistoryLineDelegate : public QItemDelegate
@@ -202,7 +202,7 @@ HistoryCompleter::HistoryCompleter(QObject *parent)
// make an assumption to allow pressing of the down
// key, before the first model run:
// parent is likely the lineedit
- QWidget *p = qobject_cast<QWidget*>(parent);
+ QWidget *p = qobject_cast<QWidget *>(parent);
if (p) {
p->installEventFilter(d_ptr->model);
QString objectName = p->objectName();
@@ -210,6 +210,11 @@ HistoryCompleter::HistoryCompleter(QObject *parent)
return;
d_ptr->model->list = d_ptr->model->settings->value(objectName).toStringList();
}
+
+ QLineEdit *l = qobject_cast<QLineEdit *>(parent);
+ if (l && d_ptr->model->list.count())
+ l->setText(d_ptr->model->list.at(0));
+
setModel(d_ptr->model);
HistoryLineDelegate *delegate = new HistoryLineDelegate;
HistoryLineView *view = new HistoryLineView(d_ptr, delegate->pixmap.width());
diff --git a/src/libs/utils/historycompleter.h b/src/libs/utils/historycompleter.h
index ced544dfe6..3dd426c564 100644
--- a/src/libs/utils/historycompleter.h
+++ b/src/libs/utils/historycompleter.h
@@ -63,7 +63,7 @@ protected:
HistoryCompleterPrivate *d_ptr;
private:
- Q_DECLARE_PRIVATE(HistoryCompleter);
+ Q_DECLARE_PRIVATE(HistoryCompleter)
};
} // namespace Utils
diff --git a/src/libs/utils/htmldocextractor.cpp b/src/libs/utils/htmldocextractor.cpp
index 6e1e395bc6..9027bc11f4 100644
--- a/src/libs/utils/htmldocextractor.cpp
+++ b/src/libs/utils/htmldocextractor.cpp
@@ -141,11 +141,32 @@ QString HtmlDocExtractor::getFunctionDescription(const QString &html,
return contents;
}
-QString HtmlDocExtractor::getQMLItemDescription(const QString &html, const QString &mark) const
+QString HtmlDocExtractor::getQmlComponentDescription(const QString &html, const QString &mark) const
{
return getClassOrNamespaceDescription(html, mark);
}
+QString HtmlDocExtractor::getQmlPropertyDescription(const QString &html, const QString &mark) const
+{
+ QString startMark = QString("<a name=\"%1-prop\">").arg(mark);
+ int index = html.indexOf(startMark);
+ if (index == -1) {
+ startMark = QString("<a name=\"%1-signal\">").arg(mark);
+ index = html.indexOf(startMark);
+ }
+ if (index == -1)
+ return QString();
+
+ QString contents = html.mid(index + startMark.size());
+ index = contents.indexOf(QLatin1String("<p>"));
+ if (index == -1)
+ return QString();
+ contents = contents.mid(index);
+ processOutput(&contents);
+
+ return contents;
+}
+
QString HtmlDocExtractor::getClassOrNamespaceMemberDescription(const QString &html,
const QString &startMark,
const QString &endMark) const
diff --git a/src/libs/utils/htmldocextractor.h b/src/libs/utils/htmldocextractor.h
index 32e33175ce..c4fcf9665b 100644
--- a/src/libs/utils/htmldocextractor.h
+++ b/src/libs/utils/htmldocextractor.h
@@ -61,7 +61,8 @@ public:
QString getFunctionDescription(const QString &html,
const QString &mark,
const bool mainOverload = true) const;
- QString getQMLItemDescription(const QString &html, const QString &mark) const;
+ QString getQmlComponentDescription(const QString &html, const QString &mark) const;
+ QString getQmlPropertyDescription(const QString &html, const QString &mark) const;
private:
QString getClassOrNamespaceMemberDescription(const QString &html,
diff --git a/src/libs/utils/pathchooser.cpp b/src/libs/utils/pathchooser.cpp
index 8f668e0c4b..010168ef64 100644
--- a/src/libs/utils/pathchooser.cpp
+++ b/src/libs/utils/pathchooser.cpp
@@ -200,7 +200,7 @@ void PathChooser::setEnvironment(const Utils::Environment &env)
QString PathChooser::path() const
{
- return QDir::cleanPath(m_d->expandedPath(QDir::fromNativeSeparators(m_d->m_lineEdit->text())));
+ return m_d->expandedPath(QDir::fromNativeSeparators(m_d->m_lineEdit->text()));
}
QString PathChooser::rawPath() const
@@ -274,6 +274,7 @@ void PathChooser::slotBrowse()
}
emit browsingFinished();
+ m_d->m_lineEdit->triggerChanged();
}
bool PathChooser::isValid() const
diff --git a/src/libs/utils/projectintropage.cpp b/src/libs/utils/projectintropage.cpp
index 81c3da50d6..57a91fb511 100644
--- a/src/libs/utils/projectintropage.cpp
+++ b/src/libs/utils/projectintropage.cpp
@@ -70,6 +70,7 @@ ProjectIntroPage::ProjectIntroPage(QWidget *parent) :
m_d->m_ui.nameLineEdit->setFocus();
connect(m_d->m_ui.pathChooser, SIGNAL(changed(QString)), this, SLOT(slotChanged()));
connect(m_d->m_ui.nameLineEdit, SIGNAL(textChanged(QString)), this, SLOT(slotChanged()));
+ connect(m_d->m_ui.pathChooser, SIGNAL(validChanged()), this, SLOT(slotChanged()));
connect(m_d->m_ui.pathChooser, SIGNAL(returnPressed()), this, SLOT(slotActivated()));
connect(m_d->m_ui.nameLineEdit, SIGNAL(validReturnPressed()), this, SLOT(slotActivated()));
}
diff --git a/src/libs/utils/qtcprocess.cpp b/src/libs/utils/qtcprocess.cpp
new file mode 100644
index 0000000000..59f3460cbc
--- /dev/null
+++ b/src/libs/utils/qtcprocess.cpp
@@ -0,0 +1,1391 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "qtcprocess.h"
+#include "stringutils.h"
+
+#ifdef Q_OS_WIN
+#include <QtCore/QDir>
+#endif
+
+using namespace Utils;
+
+/**
+ * \fn QStringList QtcProcess::splitArgs(
+ * const QString &args, bool abortOnMeta, SplitError *err, const Environment *env)
+ *
+ * Splits \a args according to system shell word splitting and quoting rules.
+ *
+ * \section Unix
+ *
+ * The behavior is based on the POSIX shell and bash:
+ * \list
+ * \li Whitespace splits tokens
+ * \li The backslash quotes the following character
+ * \li A string enclosed in single quotes is not split. No shell meta
+ * characters are interpreted.
+ * \li A string enclosed in double quotes is not split. Within the string,
+ * the backslash quotes shell meta characters - if it is followed
+ * by a "meaningless" character, the backslash is output verbatim.
+ * \list
+ * If \a abortOnMeta is \c false, only the splitting and quoting rules apply,
+ * while other meta characters (substitutions, redirections, etc.) are ignored.
+ * If \a abortOnMeta is \c true, encounters of unhandled meta characters are
+ * treated as errors.
+ *
+ * \section Windows
+ *
+ * The behavior is defined by the Microsoft C runtime:
+ * \list
+ * \li Whitespace splits tokens
+ * \li A string enclosed in double quotes is not split
+ * \list
+ * \li 3N double quotes within a quoted string yield N literal quotes.
+ * This is not documented on MSDN.
+ * \endlist
+ * \li Backslashes have special semantics iff they are followed by a double
+ * quote:
+ * \list
+ * \li 2N backslashes + double quote => N backslashes and begin/end quoting
+ * \li 2N+1 backslashes + double quote => N backslashes + literal quote
+ * \endlist
+ * \endlist
+ * Qt and many other implementations comply with this standard, but many do not.
+ *
+ * If \a abortOnMeta is \c true, cmd shell semantics are applied before
+ * proceeding with word splitting:
+ * \list
+ * \li Cmd ignores \em all special chars between double quotes.
+ * Note that the quotes are \em not removed at this stage - the
+ * tokenization rules described above still apply.
+ * \li The \c circumflex is the escape char for everything including itself.
+ * \endlist
+ * As the quoting levels are independent from each other and have different
+ * semantics, you need a command line like \c{"foo "\^"" bar"} to get
+ * \c{foo " bar}.
+ *
+ * \param cmd the command to split
+ * \param abortOnMeta see above
+ * \param err if not NULL, a status code will be stored at the pointer
+ * target, see \ref SplitError
+ * \param env if not NULL, perform variable substitution with the
+ * given environment.
+ * \return a list of unquoted words or an empty list if an error occurred
+ */
+
+#ifdef Q_OS_WIN
+
+inline static bool isMetaChar(ushort c)
+{
+ static const uchar iqm[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0x03, 0x00, 0x50,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10
+ }; // &()<>|
+
+ return (c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7)));
+}
+
+static void envExpand(QString &args, const Environment *env, const QString *pwd)
+{
+ static const QString cdName = QLatin1String("CD");
+ int off = 0;
+ next:
+ for (int prev = -1, that;
+ (that = args.indexOf(QLatin1Char('%'), off)) >= 0;
+ prev = that, off = that + 1) {
+ if (prev >= 0) {
+ const QString var = args.mid(prev + 1, that - prev - 1).toUpper();
+ const QString val = (var == cdName && pwd && !pwd->isEmpty())
+ ? QDir::toNativeSeparators(*pwd) : env->value(var);
+ if (!val.isEmpty()) { // Empty values are impossible, so this is an existence check
+ args.replace(prev, that - prev + 1, val);
+ off = prev + val.length();
+ goto next;
+ }
+ }
+ }
+}
+
+QString QtcProcess::prepareArgs(const QString &_args, SplitError *err,
+ const Environment *env, const QString *pwd)
+{
+ QString args(_args);
+
+ if (env) {
+ envExpand(args, env, pwd);
+ } else {
+ if (args.indexOf(QLatin1Char('%')) >= 0) {
+ if (err)
+ *err = FoundMeta;
+ return QString();
+ }
+ }
+
+ if (!args.isEmpty() && args.unicode()[0].unicode() == '@')
+ args.remove(0, 1);
+
+ for (int p = 0; p < args.length(); p++) {
+ ushort c = args.unicode()[p].unicode();
+ if (c == '^') {
+ args.remove(p, 1);
+ } else if (c == '"') {
+ do {
+ if (++p == args.length())
+ break; // For cmd, this is no error.
+ } while (args.unicode()[p].unicode() != '"');
+ } else if (isMetaChar(c)) {
+ if (err)
+ *err = FoundMeta;
+ return QString();
+ }
+ }
+
+ if (err)
+ *err = SplitOk;
+ return args;
+}
+
+inline static bool isWhiteSpace(ushort c)
+{
+ return c == ' ' || c == '\t';
+}
+
+static QStringList doSplitArgs(const QString &args, QtcProcess::SplitError *err)
+{
+ QStringList ret;
+
+ if (err)
+ *err = QtcProcess::SplitOk;
+
+ int p = 0;
+ const int length = args.length();
+ forever {
+ forever {
+ if (p == length)
+ return ret;
+ if (!isWhiteSpace(args.unicode()[p].unicode()))
+ break;
+ ++p;
+ }
+
+ QString arg;
+ bool inquote = false;
+ forever {
+ bool copy = true; // copy this char
+ int bslashes = 0; // number of preceding backslashes to insert
+ while (p < length && args.unicode()[p] == QLatin1Char('\\')) {
+ ++p;
+ ++bslashes;
+ }
+ if (p < length && args.unicode()[p] == QLatin1Char('"')) {
+ if (!(bslashes & 1)) {
+ // Even number of backslashes, so the quote is not escaped.
+ if (inquote) {
+ if (p + 1 < length && args.unicode()[p + 1] == QLatin1Char('"')) {
+ // This is not documented on MSDN.
+ // Two consecutive quotes make a literal quote. Brain damage:
+ // this still closes the quoting, so a 3rd quote is required,
+ // which makes the runtime's quoting run out of sync with the
+ // shell's one unless the 2nd quote is escaped.
+ ++p;
+ } else {
+ // Closing quote
+ copy = false;
+ }
+ inquote = false;
+ } else {
+ // Opening quote
+ copy = false;
+ inquote = true;
+ }
+ }
+ bslashes >>= 1;
+ }
+
+ while (--bslashes >= 0)
+ arg.append(QLatin1Char('\\'));
+
+ if (p == length || (!inquote && isWhiteSpace(args.unicode()[p].unicode()))) {
+ ret.append(arg);
+ if (inquote) {
+ if (err)
+ *err = QtcProcess::BadQuoting;
+ return QStringList();
+ }
+ break;
+ }
+
+ if (copy)
+ arg.append(args.unicode()[p]);
+ ++p;
+ }
+ }
+ //not reached
+}
+
+QStringList QtcProcess::splitArgs(const QString &_args, bool abortOnMeta, SplitError *err,
+ const Environment *env, const QString *pwd)
+{
+ if (abortOnMeta) {
+ SplitError perr;
+ if (!err)
+ err = &perr;
+ QString args = prepareArgs(_args, &perr, env, pwd);
+ if (*err != SplitOk)
+ return QStringList();
+ return doSplitArgs(args, err);
+ } else {
+ QString args = _args;
+ if (env)
+ envExpand(args, env, pwd);
+ return doSplitArgs(args, err);
+ }
+}
+
+#else // Q_OS_WIN
+
+inline static bool isQuoteMeta(QChar cUnicode)
+{
+ char c = cUnicode.toAscii();
+ return c == '\\' || c == '\'' || c == '"' || c == '$';
+}
+
+inline static bool isMeta(QChar cUnicode)
+{
+ static const uchar iqm[] = {
+ 0x00, 0x00, 0x00, 0x00, 0xdc, 0x07, 0x00, 0xd8,
+ 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x38
+ }; // \'"$`<>|;&(){}*?#[]
+
+ uint c = cUnicode.unicode();
+
+ return (c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7)));
+}
+
+QStringList QtcProcess::splitArgs(const QString &args, bool abortOnMeta, SplitError *err,
+ const Environment *env, const QString *pwd)
+{
+ static const QString pwdName = QLatin1String("PWD");
+ QStringList ret;
+
+ for (int pos = 0; ; ) {
+ QChar c;
+ do {
+ if (pos >= args.length())
+ goto okret;
+ c = args.unicode()[pos++];
+ } while (c.isSpace());
+ QString cret;
+ bool hadWord = false;
+ do {
+ if (c == QLatin1Char('\'')) {
+ int spos = pos;
+ do {
+ if (pos >= args.length())
+ goto quoteerr;
+ c = args.unicode()[pos++];
+ } while (c != QLatin1Char('\''));
+ cret += args.mid(spos, pos-spos-1);
+ hadWord = true;
+ } else if (c == QLatin1Char('"')) {
+ for (;;) {
+ if (pos >= args.length())
+ goto quoteerr;
+ c = args.unicode()[pos++];
+ nextq:
+ if (c == QLatin1Char('"'))
+ break;
+ if (c == QLatin1Char('\\')) {
+ if (pos >= args.length())
+ goto quoteerr;
+ c = args.unicode()[pos++];
+ if (c != QLatin1Char('"') &&
+ c != QLatin1Char('\\') &&
+ !(abortOnMeta &&
+ (c == QLatin1Char('$') ||
+ c == QLatin1Char('`'))))
+ cret += QLatin1Char('\\');
+ } else if (c == QLatin1Char('$') && env) {
+ if (pos >= args.length())
+ goto quoteerr;
+ c = args.unicode()[pos++];
+ bool braced = false;
+ if (c == QLatin1Char('{')) {
+ if (pos >= args.length())
+ goto quoteerr;
+ c = args.unicode()[pos++];
+ braced = true;
+ }
+ QString var;
+ while (c.isLetterOrNumber() || c == QLatin1Char('_')) {
+ var += c;
+ if (pos >= args.length())
+ goto quoteerr;
+ c = args.unicode()[pos++];
+ }
+ if (var == pwdName && pwd && !pwd->isEmpty()) {
+ cret += *pwd;
+ } else {
+ Environment::const_iterator vit = env->constFind(var);
+ if (vit == env->constEnd()) {
+ if (abortOnMeta)
+ goto metaerr; // Assume this is a shell builtin
+ } else {
+ cret += *vit;
+ }
+ }
+ if (!braced)
+ goto nextq;
+ if (c != QLatin1Char('}')) {
+ if (abortOnMeta)
+ goto metaerr; // Assume this is a complex expansion
+ goto quoteerr; // Otherwise it's just garbage
+ }
+ continue;
+ } else if (abortOnMeta &&
+ (c == QLatin1Char('$') ||
+ c == QLatin1Char('`'))) {
+ goto metaerr;
+ }
+ cret += c;
+ }
+ hadWord = true;
+ } else if (c == QLatin1Char('$') && env) {
+ if (pos >= args.length())
+ goto quoteerr; // Bash just takes it verbatim, but whatever
+ c = args.unicode()[pos++];
+ bool braced = false;
+ if (c == QLatin1Char('{')) {
+ if (pos >= args.length())
+ goto quoteerr;
+ c = args.unicode()[pos++];
+ braced = true;
+ }
+ QString var;
+ while (c.isLetterOrNumber() || c == QLatin1Char('_')) {
+ var += c;
+ if (pos >= args.length()) {
+ if (braced)
+ goto quoteerr;
+ c = QLatin1Char(' ');
+ break;
+ }
+ c = args.unicode()[pos++];
+ }
+ QString val;
+ if (var == pwdName && pwd && !pwd->isEmpty()) {
+ val = *pwd;
+ } else {
+ Environment::const_iterator vit = env->constFind(var);
+ if (vit == env->constEnd()) {
+ if (abortOnMeta)
+ goto metaerr; // Assume this is a shell builtin
+ } else {
+ val = *vit;
+ }
+ }
+ for (int i = 0; i < val.length(); i++) {
+ QChar cc = val.unicode()[i];
+ if (cc == 9 || cc == 10 || cc == 32) {
+ if (hadWord) {
+ ret += cret;
+ cret.clear();
+ hadWord = false;
+ }
+ } else {
+ cret += cc;
+ hadWord = true;
+ }
+ }
+ if (!braced)
+ goto nextc;
+ if (c != QLatin1Char('}')) {
+ if (abortOnMeta)
+ goto metaerr; // Assume this is a complex expansion
+ goto quoteerr; // Otherwise it's just garbage
+ }
+ } else {
+ if (c == QLatin1Char('\\')) {
+ if (pos >= args.length())
+ goto quoteerr;
+ c = args.unicode()[pos++];
+ } else if (abortOnMeta && isMeta(c)) {
+ goto metaerr;
+ }
+ cret += c;
+ hadWord = true;
+ }
+ if (pos >= args.length())
+ break;
+ c = args.unicode()[pos++];
+ nextc: ;
+ } while (!c.isSpace());
+ if (hadWord)
+ ret += cret;
+ }
+
+ okret:
+ if (err)
+ *err = SplitOk;
+ return ret;
+
+ quoteerr:
+ if (err)
+ *err = BadQuoting;
+ return QStringList();
+
+ metaerr:
+ if (err)
+ *err = FoundMeta;
+ return QStringList();
+}
+
+#endif // Q_OS_WIN
+
+inline static bool isSpecialCharUnix(ushort c)
+{
+ // Chars that should be quoted (TM). This includes:
+ static const uchar iqm[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xdf, 0x07, 0x00, 0xd8,
+ 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x78
+ }; // 0-32 \'"$`<>|;&(){}*?#!~[]
+
+ return (c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7)));
+}
+
+inline static bool hasSpecialCharsUnix(const QString &arg)
+{
+ for (int x = arg.length() - 1; x >= 0; --x)
+ if (isSpecialCharUnix(arg.unicode()[x].unicode()))
+ return true;
+ return false;
+}
+
+QString QtcProcess::quoteArgUnix(const QString &arg)
+{
+ if (!arg.length())
+ return QString::fromLatin1("''");
+
+ QString ret(arg);
+ if (hasSpecialCharsUnix(ret)) {
+ ret.replace(QLatin1Char('\''), QLatin1String("'\\''"));
+ ret.prepend(QLatin1Char('\''));
+ ret.append(QLatin1Char('\''));
+ }
+ return ret;
+}
+
+void QtcProcess::addArgUnix(QString *args, const QString &arg)
+{
+ if (!args->isEmpty())
+ *args += QLatin1Char(' ');
+ *args += quoteArgUnix(arg);
+}
+
+QString QtcProcess::joinArgsUnix(const QStringList &args)
+{
+ QString ret;
+ foreach (const QString &arg, args)
+ addArgUnix(&ret, arg);
+ return ret;
+}
+
+#ifdef Q_OS_WIN
+inline static bool isSpecialChar(ushort c)
+{
+ // Chars that should be quoted (TM). This includes:
+ // - control chars & space
+ // - the shell meta chars "&()<>^|
+ // - the potential separators ,;=
+ static const uchar iqm[] = {
+ 0xff, 0xff, 0xff, 0xff, 0x45, 0x13, 0x00, 0x78,
+ 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10
+ };
+
+ return (c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7)));
+}
+
+inline static bool hasSpecialChars(const QString &arg)
+{
+ for (int x = arg.length() - 1; x >= 0; --x)
+ if (isSpecialChar(arg.unicode()[x].unicode()))
+ return true;
+ return false;
+}
+
+QString QtcProcess::quoteArg(const QString &arg)
+{
+ if (!arg.length())
+ return QString::fromLatin1("\"\"");
+
+ QString ret(arg);
+ if (hasSpecialChars(ret)) {
+ // Quotes are escaped and their preceding backslashes are doubled.
+ // It's impossible to escape anything inside a quoted string on cmd
+ // level, so the outer quoting must be "suspended".
+ ret.replace(QRegExp(QLatin1String("(\\\\*)\"")), QLatin1String("\"\\1\\1\\^\"\""));
+ // The argument must not end with a \ since this would be interpreted
+ // as escaping the quote -- rather put the \ behind the quote: e.g.
+ // rather use "foo"\ than "foo\"
+ ret.replace(QRegExp(QLatin1String("(\\\\*)$")), QLatin1String("\"\\1"));
+ ret.prepend(QLatin1Char('"'));
+ }
+ // FIXME: Without this, quoting is not foolproof. But it needs support in the process setup, etc.
+ //ret.replace('%', QLatin1String("%PERCENT_SIGN%"));
+ return ret;
+}
+
+void QtcProcess::addArg(QString *args, const QString &arg)
+{
+ if (!args->isEmpty())
+ *args += QLatin1Char(' ');
+ *args += quoteArg(arg);
+}
+
+QString QtcProcess::joinArgs(const QStringList &args)
+{
+ QString ret;
+ foreach (const QString &arg, args)
+ addArg(&ret, arg);
+ return ret;
+}
+#endif
+
+void QtcProcess::addArgs(QString *args, const QString &inArgs)
+{
+ if (!inArgs.isEmpty()) {
+ if (!args->isEmpty())
+ *args += QLatin1Char(' ');
+ *args += inArgs;
+ }
+}
+
+void QtcProcess::addArgs(QString *args, const QStringList &inArgs)
+{
+ foreach (const QString &arg, inArgs)
+ addArg(args, arg);
+}
+
+#ifdef Q_OS_WIN
+void QtcProcess::prepareCommand(const QString &command, const QString &arguments,
+ QString *outCmd, QString *outArgs,
+ const Environment *env, const QString *pwd)
+{
+ QtcProcess::SplitError err;
+ *outArgs = QtcProcess::prepareArgs(arguments, &err, env, pwd);
+ if (err == QtcProcess::SplitOk) {
+ *outCmd = command;
+ } else {
+ *outCmd = QString::fromLatin1(qgetenv("COMSPEC"));
+ *outArgs = QLatin1String("/v:off /s /c \"")
+ + quoteArg(QDir::toNativeSeparators(command)) + QLatin1Char(' ') + arguments
+ + QLatin1Char('"');
+ }
+}
+#else
+bool QtcProcess::prepareCommand(const QString &command, const QString &arguments,
+ QString *outCmd, QStringList *outArgs,
+ const Environment *env, const QString *pwd)
+{
+ QtcProcess::SplitError err;
+ *outArgs = QtcProcess::prepareArgs(arguments, &err, env, pwd);
+ if (err == QtcProcess::SplitOk) {
+ *outCmd = command;
+ } else {
+ if (err != QtcProcess::FoundMeta)
+ return false;
+ *outCmd = QLatin1String("/bin/sh");
+ *outArgs << QLatin1String("-c") << (quoteArg(command) + QLatin1Char(' ') + arguments);
+ }
+ return true;
+}
+#endif
+
+void QtcProcess::start()
+{
+ Environment env;
+ if (m_haveEnv) {
+ env = m_environment;
+ QProcess::setEnvironment(env.toStringList());
+ } else {
+ env = Environment::systemEnvironment();
+ }
+
+ const QString &workDir = workingDirectory();
+ QString command;
+#ifdef Q_OS_WIN
+ QString arguments;
+ prepareCommand(m_command, m_arguments, &command, &arguments, &env, &workDir);
+ setNativeArguments(arguments);
+ QProcess::start(command, QStringList());
+#else
+ QStringList arguments;
+ if (!prepareCommand(m_command, m_arguments, &command, &arguments, &env, &workDir)) {
+ setErrorString(tr("Error in command line."));
+ // Should be FailedToStart, but we cannot set the process error from the outside,
+ // so it would be inconsistent.
+ emit error(QProcess::UnknownError);
+ return;
+ }
+ QProcess::start(command, arguments);
+#endif
+}
+
+#ifdef Q_OS_WIN
+
+// This function assumes that the resulting string will be quoted.
+// That's irrelevant if it does not contain quotes itself.
+static int quoteArgInternal(QString &ret, int bslashes)
+{
+ // Quotes are escaped and their preceding backslashes are doubled.
+ // It's impossible to escape anything inside a quoted string on cmd
+ // level, so the outer quoting must be "suspended".
+ const QChar bs(QLatin1Char('\\')), dq(QLatin1Char('"'));
+ for (int p = 0; p < ret.length(); p++) {
+ if (ret.at(p) == bs) {
+ bslashes++;
+ } else {
+ if (ret.at(p) == dq) {
+ if (bslashes) {
+ ret.insert(p, QString(bslashes, bs));
+ p += bslashes;
+ }
+ ret.insert(p, QLatin1String("\"\\^\""));
+ p += 4;
+ }
+ bslashes = 0;
+ }
+ }
+ return bslashes;
+}
+
+#else
+
+// The main state of the Unix shell parser
+enum MxQuoting { MxBasic, MxSingleQuote, MxDoubleQuote, MxParen, MxSubst, MxGroup, MxMath };
+typedef struct {
+ MxQuoting current;
+ // Bizarrely enough, double quoting has an impact on the behavior of some
+ // complex expressions within the quoted string.
+ bool dquote;
+} MxState;
+QT_BEGIN_NAMESPACE
+Q_DECLARE_TYPEINFO(MxState, Q_PRIMITIVE_TYPE);
+QT_END_NAMESPACE
+
+// Pushed state for the case where a $(()) expansion turns out bogus
+typedef struct {
+ QString str;
+ int pos, varPos;
+} MxSave;
+QT_BEGIN_NAMESPACE
+Q_DECLARE_TYPEINFO(MxSave, Q_MOVABLE_TYPE);
+QT_END_NAMESPACE
+
+#include <QtCore/QStack>
+
+#endif
+
+// TODO: This documentation is relevant for end-users. Where to put it?
+/**
+ * Perform safe macro expansion (substitution) on a string for use
+ * in shell commands.
+ *
+ * \section Unix notes
+ *
+ * Explicitly supported shell constructs:
+ * \\ '' "" {} () $(()) ${} $() ``
+ *
+ * Implicitly supported shell constructs:
+ * (())
+ *
+ * Unsupported shell constructs that will cause problems:
+ * \list
+ * \li Shortened \c{case $v in pat)} syntax. Use \c{case $v in (pat)} instead.
+ * \li Bash-style \c{$""} and \c{$''} string quoting syntax.
+ * \endlist
+ *
+ * The rest of the shell (incl. bash) syntax is simply ignored,
+ * as it is not expected to cause problems.
+ *
+ * Security considerations:
+ * \list
+ * \li Backslash-escaping an expando is treated as a quoting error
+ * \li Do not put expandos into double quoted substitutions:
+ * \badcode
+ * "${VAR:-%{macro}}"
+ * \endcode
+ * \li Do not put expandos into command line arguments which are nested
+ * shell commands:
+ * \badcode
+ * sh -c 'foo \%{file}'
+ * \endcode
+ * \goodcode
+ * file=\%{file} sh -c 'foo "$file"'
+ * \endcode
+ * \endlist
+ *
+ * \section Windows notes
+ *
+ * All quoting syntax supported by splitArgs() is supported here as well.
+ * Additionally, command grouping via parentheses is recognized - note
+ * however, that the parser is much stricter about unquoted parentheses
+ * than cmd itself.
+ * The rest of the cmd syntax is simply ignored, as it is not expected
+ * to cause problems.
+ *
+ * Security considerations:
+ * \list
+ * \li Circumflex-escaping an expando is treated as a quoting error
+ * \li Closing double quotes right before expandos and opening double quotes
+ * right after expandos are treated as quoting errors
+ * \li Do not put expandos into nested commands:
+ * \badcode
+ * for /f "usebackq" \%v in (`foo \%{file}`) do \@echo \%v
+ * \endcode
+ * \li A macro's value must not contain anything which may be interpreted
+ * as an environment variable expansion. A solution is replacing any
+ * percent signs with a fixed string like \c{\%PERCENT_SIGN\%} and
+ * injecting \c{PERCENT_SIGN=\%} into the shell's environment.
+ * \li Enabling delayed environment variable expansion (cmd /v:on) should have
+ * no security implications, but may still wreak havoc due to the
+ * need for doubling circumflexes if any exclamation marks are present,
+ * and the need to circumflex-escape the exclamation marks themselves.
+ * \endlist
+ *
+ * \param cmd pointer to the string in which macros are expanded in-place
+ * \param mx pointer to a macro expander instance
+ * \return false if the string could not be parsed and therefore no safe
+ * substitution was possible
+ */
+bool QtcProcess::expandMacros(QString *cmd, AbstractMacroExpander *mx)
+{
+ QString str = *cmd;
+ if (str.isEmpty())
+ return true;
+
+ QString rsts;
+ int varLen;
+ int varPos = 0;
+ if (!(varLen = mx->findMacro(str, &varPos, &rsts)))
+ return true;
+
+ int pos = 0;
+
+#ifdef Q_OS_WIN
+ enum { // cmd.exe parsing state
+ ShellBasic, // initial state
+ ShellQuoted, // double-quoted state => *no* other meta chars are interpreted
+ ShellEscaped // circumflex-escaped state => next char is not interpreted
+ } shellState = ShellBasic;
+ enum { // CommandLineToArgv() parsing state and some more
+ CrtBasic, // initial state
+ CrtNeedWord, // after empty expando; insert empty argument if whitespace follows
+ CrtInWord, // in non-whitespace
+ CrtClosed, // previous char closed the double-quoting
+ CrtHadQuote, // closed double-quoting after an expando
+ // The remaining two need to be numerically higher
+ CrtQuoted, // double-quoted state => spaces don't split tokens
+ CrtNeedQuote // expando opened quote; close if no expando follows
+ } crtState = CrtBasic;
+ int bslashes = 0; // previous chars were manual backslashes
+ int rbslashes = 0; // trailing backslashes in replacement
+
+ forever {
+ if (pos == varPos) {
+ if (shellState == ShellEscaped)
+ return false; // Circumflex'd quoted expando would be Bad (TM).
+ if ((shellState == ShellQuoted) != (crtState == CrtQuoted))
+ return false; // CRT quoting out of sync with shell quoting. Ahoy to Redmond.
+ rbslashes += bslashes;
+ bslashes = 0;
+ if (crtState < CrtQuoted) {
+ if (rsts.isEmpty()) {
+ if (crtState == CrtBasic) {
+ // Outside any quoting and the string is empty, so put
+ // a pair of quotes. Delaying that is just pedantry.
+ crtState = CrtNeedWord;
+ }
+ } else {
+ if (hasSpecialChars(rsts)) {
+ if (crtState == CrtClosed) {
+ // Quoted expando right after closing quote. Can't do that.
+ return false;
+ }
+ int tbslashes = quoteArgInternal(rsts, 0);
+ rsts.prepend(QLatin1Char('"'));
+ if (rbslashes)
+ rsts.prepend(QString(rbslashes, QLatin1Char('\\')));
+ crtState = CrtNeedQuote;
+ rbslashes = tbslashes;
+ } else {
+ crtState = CrtInWord; // We know that this string contains no spaces.
+ // We know that this string contains no quotes,
+ // so the function won't make a mess.
+ rbslashes = quoteArgInternal(rsts, rbslashes);
+ }
+ }
+ } else {
+ rbslashes = quoteArgInternal(rsts, rbslashes);
+ }
+ str.replace(pos, varLen, rsts);
+ pos += rsts.length();
+ varPos = pos;
+ if (!(varLen = mx->findMacro(str, &varPos, &rsts))) {
+ // Don't leave immediately, as we may be in CrtNeedWord state which could
+ // be still resolved, or we may have inserted trailing backslashes.
+ varPos = INT_MAX;
+ }
+ continue;
+ }
+ if (crtState == CrtNeedQuote) {
+ if (rbslashes) {
+ str.insert(pos, QString(rbslashes, QLatin1Char('\\')));
+ pos += rbslashes;
+ varPos += rbslashes;
+ rbslashes = 0;
+ }
+ str.insert(pos, QLatin1Char('"'));
+ pos++;
+ varPos++;
+ crtState = CrtHadQuote;
+ }
+ ushort cc = str.unicode()[pos].unicode();
+ if (shellState == ShellBasic && cc == '^') {
+ shellState = ShellEscaped;
+ } else {
+ if (!cc || cc == ' ' || cc == '\t') {
+ if (crtState < CrtQuoted) {
+ if (crtState == CrtNeedWord) {
+ str.insert(pos, QLatin1String("\"\""));
+ pos += 2;
+ varPos += 2;
+ }
+ crtState = CrtBasic;
+ }
+ if (!cc)
+ break;
+ bslashes = 0;
+ rbslashes = 0;
+ } else {
+ if (cc == '\\') {
+ bslashes++;
+ if (crtState < CrtQuoted)
+ crtState = CrtInWord;
+ } else {
+ if (cc == '"') {
+ if (shellState != ShellEscaped)
+ shellState = (shellState == ShellQuoted) ? ShellBasic : ShellQuoted;
+ if (rbslashes) {
+ // Offset -1: skip possible circumflex. We have at least
+ // one backslash, so a fixed offset is ok.
+ str.insert(pos - 1, QString(rbslashes, QLatin1Char('\\')));
+ pos += rbslashes;
+ varPos += rbslashes;
+ }
+ if (!(bslashes & 1)) {
+ // Even number of backslashes, so the quote is not escaped.
+ switch (crtState) {
+ case CrtQuoted:
+ // Closing quote
+ crtState = CrtClosed;
+ break;
+ case CrtClosed:
+ // Two consecutive quotes make a literal quote - and
+ // still close quoting. See QtcProcess::quoteArg().
+ crtState = CrtInWord;
+ break;
+ case CrtHadQuote:
+ // Opening quote right after quoted expando. Can't do that.
+ return false;
+ default:
+ // Opening quote
+ crtState = CrtQuoted;
+ break;
+ }
+ } else if (crtState < CrtQuoted) {
+ crtState = CrtInWord;
+ }
+ } else if (crtState < CrtQuoted) {
+ crtState = CrtInWord;
+ }
+ bslashes = 0;
+ rbslashes = 0;
+ }
+ }
+ if (varPos == INT_MAX && !rbslashes)
+ break;
+ if (shellState == ShellEscaped)
+ shellState = ShellBasic;
+ }
+ pos++;
+ }
+#else
+ MxState state = { MxBasic, false };
+ QStack<MxState> sstack;
+ QStack<MxSave> ostack;
+
+ while (pos < str.length()) {
+ if (pos == varPos) {
+ // Our expansion rules trigger in any context
+ if (state.dquote) {
+ // We are within a double-quoted string. Escape relevant meta characters.
+ rsts.replace(QRegExp(QLatin1String("([$`\"\\\\])")), QLatin1String("\\\\1"));
+ } else if (state.current == MxSingleQuote) {
+ // We are within a single-quoted string. "Suspend" single-quoting and put a
+ // single escaped quote for each single quote inside the string.
+ rsts.replace(QLatin1Char('\''), QLatin1String("'\\''"));
+ } else if (rsts.isEmpty() || hasSpecialCharsUnix(rsts)) {
+ // String contains "quote-worthy" characters. Use single quoting - but
+ // that choice is arbitrary.
+ rsts.replace(QLatin1Char('\''), QLatin1String("'\\''"));
+ rsts.prepend(QLatin1Char('\''));
+ rsts.append(QLatin1Char('\''));
+ } // Else just use the string verbatim.
+ str.replace(pos, varLen, rsts);
+ pos += rsts.length();
+ varPos = pos;
+ if (!(varLen = mx->findMacro(str, &varPos, &rsts)))
+ break;
+ continue;
+ }
+ ushort cc = str.unicode()[pos].unicode();
+ if (state.current == MxSingleQuote) {
+ // Single quoted context - only the single quote has any special meaning.
+ if (cc == '\'')
+ state = sstack.pop();
+ } else if (cc == '\\') {
+ // In any other context, the backslash starts an escape.
+ pos += 2;
+ if (varPos < pos)
+ return false; // Backslash'd quoted expando would be Bad (TM).
+ continue;
+ } else if (cc == '$') {
+ cc = str.unicode()[++pos].unicode();
+ if (cc == '(') {
+ sstack.push(state);
+ if (str.unicode()[pos + 1].unicode() == '(') {
+ // $(( starts a math expression. This may also be a $( ( in fact,
+ // so we push the current string and offset on a stack so we can retry.
+ MxSave sav = { str, pos + 2, varPos };
+ ostack.push(sav);
+ state.current = MxMath;
+ pos += 2;
+ continue;
+ } else {
+ // $( starts a command substitution. This actually "opens a new context"
+ // which overrides surrounding double quoting.
+ state.current = MxParen;
+ state.dquote = false;
+ }
+ } else if (cc == '{') {
+ // ${ starts a "braced" variable substitution.
+ sstack.push(state);
+ state.current = MxSubst;
+ } // Else assume that a "bare" variable substitution has started
+ } else if (cc == '`') {
+ // Backticks are evil, as every shell interprets escapes within them differently,
+ // which is a danger for the quoting of our own expansions.
+ // So we just apply *our* rules (which match bash) and transform it into a POSIX
+ // command substitution which has clear semantics.
+ str.replace(pos, 1, QLatin1String("$( " )); // add space -> avoid creating $((
+ varPos += 2;
+ int pos2 = pos += 3;
+ forever {
+ if (pos2 >= str.length())
+ return false; // Syntax error - unterminated backtick expression.
+ cc = str.unicode()[pos2].unicode();
+ if (cc == '`')
+ break;
+ if (cc == '\\') {
+ cc = str.unicode()[++pos2].unicode();
+ if (cc == '$' || cc == '`' || cc == '\\' ||
+ (cc == '"' && state.dquote))
+ {
+ str.remove(pos2 - 1, 1);
+ if (varPos >= pos2)
+ varPos--;
+ continue;
+ }
+ }
+ pos2++;
+ }
+ str[pos2] = QLatin1Char(')');
+ sstack.push(state);
+ state.current = MxParen;
+ state.dquote = false;
+ continue;
+ } else if (state.current == MxDoubleQuote) {
+ // (Truly) double quoted context - only remaining special char is the closing quote.
+ if (cc == '"')
+ state = sstack.pop();
+ } else if (cc == '\'') {
+ // Start single quote if we are not in "inherited" double quoted context.
+ if (!state.dquote) {
+ sstack.push(state);
+ state.current = MxSingleQuote;
+ }
+ } else if (cc == '"') {
+ // Same for double quoting.
+ if (!state.dquote) {
+ sstack.push(state);
+ state.current = MxDoubleQuote;
+ state.dquote = true;
+ }
+ } else if (state.current == MxSubst) {
+ // "Braced" substitution context - only remaining special char is the closing brace.
+ if (cc == '}')
+ state = sstack.pop();
+ } else if (cc == ')') {
+ if (state.current == MxMath) {
+ if (str.unicode()[pos + 1].unicode() == ')') {
+ state = sstack.pop();
+ pos += 2;
+ } else {
+ // False hit: the $(( was a $( ( in fact.
+ // ash does not care (and will complain), but bash actually parses it.
+ varPos = ostack.top().varPos;
+ pos = ostack.top().pos;
+ str = ostack.top().str;
+ ostack.pop();
+ state.current = MxParen;
+ state.dquote = false;
+ sstack.push(state);
+ }
+ continue;
+ } else if (state.current == MxParen) {
+ state = sstack.pop();
+ } else {
+ break; // Syntax error - excess closing parenthesis.
+ }
+ } else if (cc == '}') {
+ if (state.current == MxGroup)
+ state = sstack.pop();
+ else
+ break; // Syntax error - excess closing brace.
+ } else if (cc == '(') {
+ // Context-saving command grouping.
+ sstack.push(state);
+ state.current = MxParen;
+ } else if (cc == '{') {
+ // Plain command grouping.
+ sstack.push(state);
+ state.current = MxGroup;
+ }
+ pos++;
+ }
+ // FIXME? May complain if (!sstack.empty()), but we don't really care anyway.
+#endif
+
+ *cmd = str;
+ return true;
+}
+
+QString QtcProcess::expandMacros(const QString &str, AbstractMacroExpander *mx)
+{
+ QString ret = str;
+ expandMacros(&ret, mx);
+ return ret;
+}
+
+bool QtcProcess::ArgIterator::next()
+{
+ // We delay the setting of m_prev so we can still delete the last argument
+ // after we find that there are no more arguments. It's a bit of a hack ...
+ int prev = m_pos;
+
+ m_simple = true;
+ m_value.clear();
+
+#ifdef Q_OS_WIN
+ enum { // cmd.exe parsing state
+ ShellBasic, // initial state
+ ShellQuoted, // double-quoted state => *no* other meta chars are interpreted
+ ShellEscaped // circumflex-escaped state => next char is not interpreted
+ } shellState = ShellBasic;
+ enum { // CommandLineToArgv() parsing state and some more
+ CrtBasic, // initial state
+ CrtInWord, // in non-whitespace
+ CrtClosed, // previous char closed the double-quoting
+ CrtQuoted // double-quoted state => spaces don't split tokens
+ } crtState = CrtBasic;
+ enum { NoVar, NewVar, FullVar } varState = NoVar; // inside a potential env variable expansion
+ int bslashes = 0; // number of preceding backslashes
+
+ for (;; m_pos++) {
+ ushort cc = m_pos < m_str->length() ? m_str->unicode()[m_pos].unicode() : 0;
+ if (shellState == ShellBasic && cc == '^') {
+ varState = NoVar;
+ shellState = ShellEscaped;
+ } else if ((shellState == ShellBasic && isMetaChar(cc)) || !cc) { // A "bit" simplistic ...
+ // We ignore crtQuote state here. Whatever ...
+ doReturn:
+ if (m_simple)
+ while (--bslashes >= 0)
+ m_value += QLatin1Char('\\');
+ else
+ m_value.clear();
+ if (crtState != CrtBasic) {
+ m_prev = prev;
+ return true;
+ }
+ return false;
+ } else {
+ if (crtState != CrtQuoted && (cc == ' ' || cc == '\t')) {
+ if (crtState != CrtBasic) {
+ // We'll lose shellQuote state here. Whatever ...
+ goto doReturn;
+ }
+ } else {
+ if (cc == '\\') {
+ bslashes++;
+ if (crtState != CrtQuoted)
+ crtState = CrtInWord;
+ varState = NoVar;
+ } else {
+ if (cc == '"') {
+ varState = NoVar;
+ if (shellState != ShellEscaped)
+ shellState = (shellState == ShellQuoted) ? ShellBasic : ShellQuoted;
+ int obslashes = bslashes;
+ bslashes >>= 1;
+ if (!(obslashes & 1)) {
+ // Even number of backslashes, so the quote is not escaped.
+ switch (crtState) {
+ case CrtQuoted:
+ // Closing quote
+ crtState = CrtClosed;
+ continue;
+ case CrtClosed:
+ // Two consecutive quotes make a literal quote - and
+ // still close quoting. See quoteArg().
+ crtState = CrtInWord;
+ break;
+ default:
+ // Opening quote
+ crtState = CrtQuoted;
+ continue;
+ }
+ } else if (crtState != CrtQuoted) {
+ crtState = CrtInWord;
+ }
+ } else {
+ if (cc == '%') {
+ if (varState == FullVar) {
+ m_simple = false;
+ varState = NoVar;
+ } else {
+ varState = NewVar;
+ }
+ } else if (varState != NoVar) {
+ // This check doesn't really reflect cmd reality, but it is an
+ // approximation of what would be sane.
+ varState = (cc == '_' || cc == '-' || cc == '.'
+ || QChar(cc).isLetterOrNumber()) ? FullVar : NoVar;
+
+ }
+ if (crtState != CrtQuoted)
+ crtState = CrtInWord;
+ }
+ for (; bslashes > 0; bslashes--)
+ m_value += QLatin1Char('\\');
+ m_value += QChar(cc);
+ }
+ }
+ if (shellState == ShellEscaped)
+ shellState = ShellBasic;
+ }
+ }
+#else
+ MxState state = { MxBasic, false };
+ QStack<MxState> sstack;
+ QStack<int> ostack;
+ bool hadWord = false;
+
+ for (; m_pos < m_str->length(); m_pos++) {
+ ushort cc = m_str->unicode()[m_pos].unicode();
+ if (state.current == MxSingleQuote) {
+ if (cc == '\'') {
+ state = sstack.pop();
+ continue;
+ }
+ } else if (cc == '\\') {
+ if (++m_pos >= m_str->length())
+ break;
+ cc = m_str->unicode()[m_pos].unicode();
+ if (state.dquote && cc != '"' && cc != '\\' && cc != '$' && cc != '`')
+ m_value += QLatin1Char('\\');
+ } else if (cc == '$') {
+ if (++m_pos >= m_str->length())
+ break;
+ cc = m_str->unicode()[m_pos].unicode();
+ if (cc == '(') {
+ sstack.push(state);
+ if (++m_pos >= m_str->length())
+ break;
+ if (m_str->unicode()[m_pos].unicode() == '(') {
+ ostack.push(m_pos);
+ state.current = MxMath;
+ } else {
+ state.dquote = false;
+ state.current = MxParen;
+ // m_pos too far by one now - whatever.
+ }
+ } else if (cc == '{') {
+ sstack.push(state);
+ state.current = MxSubst;
+ } else {
+ // m_pos too far by one now - whatever.
+ }
+ m_simple = false;
+ hadWord = true;
+ continue;
+ } else if (cc == '`') {
+ forever {
+ if (++m_pos >= m_str->length()) {
+ m_simple = false;
+ m_prev = prev;
+ return true;
+ }
+ cc = m_str->unicode()[m_pos].unicode();
+ if (cc == '`')
+ break;
+ if (cc == '\\')
+ m_pos++; // m_pos may be too far by one now - whatever.
+ }
+ m_simple = false;
+ hadWord = true;
+ continue;
+ } else if (state.current == MxDoubleQuote) {
+ if (cc == '"') {
+ state = sstack.pop();
+ continue;
+ }
+ } else if (cc == '\'') {
+ if (!state.dquote) {
+ sstack.push(state);
+ state.current = MxSingleQuote;
+ hadWord = true;
+ continue;
+ }
+ } else if (cc == '"') {
+ if (!state.dquote) {
+ sstack.push(state);
+ state.dquote = true;
+ state.current = MxDoubleQuote;
+ hadWord = true;
+ continue;
+ }
+ } else if (state.current == MxSubst) {
+ if (cc == '}')
+ state = sstack.pop();
+ continue; // Not simple anyway
+ } else if (cc == ')') {
+ if (state.current == MxMath) {
+ if (++m_pos >= m_str->length())
+ break;
+ if (m_str->unicode()[m_pos].unicode() == ')') {
+ ostack.pop();
+ state = sstack.pop();
+ } else {
+ // false hit: the $(( was a $( ( in fact.
+ // ash does not care, but bash does.
+ m_pos = ostack.pop();
+ state.current = MxParen;
+ state.dquote = false;
+ sstack.push(state);
+ }
+ continue;
+ } else if (state.current == MxParen) {
+ state = sstack.pop();
+ continue;
+ } else {
+ break;
+ }
+#if 0 // MxGroup is impossible, see below.
+ } else if (cc == '}') {
+ if (state.current == MxGroup) {
+ state = sstack.pop();
+ continue;
+ }
+#endif
+ } else if (cc == '(') {
+ sstack.push(state);
+ state.current = MxParen;
+ m_simple = false;
+ hadWord = true;
+#if 0 // Should match only at the beginning of a command, which we never have currently.
+ } else if (cc == '{') {
+ sstack.push(state);
+ state.current = MxGroup;
+ m_simple = false;
+ hadWord = true;
+ continue;
+#endif
+ } else if (cc == '<' || cc == '>' || cc == '&' || cc == '|' || cc == ';') {
+ if (sstack.isEmpty())
+ break;
+ } else if (cc == ' ' || cc == '\t') {
+ if (!hadWord)
+ continue;
+ if (sstack.isEmpty())
+ break;
+ }
+ m_value += QChar(cc);
+ hadWord = true;
+ }
+ // TODO: Possibly complain here if (!sstack.empty())
+ if (!m_simple)
+ m_value.clear();
+ if (hadWord) {
+ m_prev = prev;
+ return true;
+ }
+ return false;
+#endif
+}
+
+void QtcProcess::ArgIterator::deleteArg()
+{
+ if (!m_prev)
+ while (m_pos < m_str->length() && m_str->at(m_pos).isSpace())
+ m_pos++;
+ m_str->remove(m_prev, m_pos - m_prev);
+ m_pos = m_prev;
+}
+
+void QtcProcess::ArgIterator::appendArg(const QString &str)
+{
+ const QString qstr = quoteArg(str);
+ if (!m_pos)
+ m_str->insert(0, qstr + QLatin1Char(' '));
+ else
+ m_str->insert(m_pos, QLatin1Char(' ') + qstr);
+ m_pos += qstr.length() + 1;
+}
diff --git a/src/libs/utils/qtcprocess.h b/src/libs/utils/qtcprocess.h
new file mode 100644
index 0000000000..e7439d8c27
--- /dev/null
+++ b/src/libs/utils/qtcprocess.h
@@ -0,0 +1,149 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 QTCPROCESS_H
+#define QTCPROCESS_H
+
+#include <QProcess>
+
+#include "utils_global.h"
+
+#include "environment.h"
+
+namespace Utils {
+class AbstractMacroExpander;
+
+/*!
+ This class provides functionality for dealing with shell-quoted process arguments.
+*/
+class QTCREATOR_UTILS_EXPORT QtcProcess : public QProcess
+{
+ Q_OBJECT
+
+public:
+ QtcProcess(QObject *parent = 0) : QProcess(parent), m_haveEnv(false) {}
+ void setEnvironment(const Environment &env)
+ { m_environment = env; m_haveEnv = true; }
+ void setCommand(const QString &command, const QString &arguments)
+ { m_command = command; m_arguments = arguments; }
+ void start();
+
+ enum SplitError {
+ SplitOk = 0, //! All went just fine
+ BadQuoting, //! Command contains quoting errors
+ FoundMeta //! Command contains complex shell constructs
+ };
+
+ //! Quote a single argument for usage in a unix shell command
+ static QString quoteArgUnix(const QString &arg);
+ //! Quote a single argument and append it to a unix shell command
+ static void addArgUnix(QString *args, const QString &arg);
+ //! Join an argument list into a unix shell command
+ static QString joinArgsUnix(const QStringList &args);
+#ifdef Q_OS_WIN
+ //! Quote a single argument for usage in a shell command
+ static QString quoteArg(const QString &arg);
+ //! Quote a single argument and append it to a shell command
+ static void addArg(QString *args, const QString &arg);
+ //! Join an argument list into a shell command
+ static QString joinArgs(const QStringList &args);
+ //! Prepare argument of a shell command for feeding into QProcess
+ static QString prepareArgs(const QString &cmd, SplitError *err,
+ const Environment *env = 0, const QString *pwd = 0);
+ //! Prepare a shell command for feeding into QProcess
+ static void prepareCommand(const QString &command, const QString &arguments,
+ QString *outCmd, QString *outArgs,
+ const Environment *env = 0, const QString *pwd = 0);
+#else
+ static QString quoteArg(const QString &arg) { return quoteArgUnix(arg); }
+ static void addArg(QString *args, const QString &arg) { addArgUnix(args, arg); }
+ static QString joinArgs(const QStringList &args) { return joinArgsUnix(args); }
+ static QStringList prepareArgs(const QString &cmd, SplitError *err,
+ const Environment *env = 0, const QString *pwd = 0)
+ { return splitArgs(cmd, true, err, env, pwd); }
+ static bool prepareCommand(const QString &command, const QString &arguments,
+ QString *outCmd, QStringList *outArgs,
+ const Environment *env = 0, const QString *pwd = 0);
+#endif
+ //! Quote and append each argument to a shell command
+ static void addArgs(QString *args, const QStringList &inArgs);
+ //! Append already quoted arguments to a shell command
+ static void addArgs(QString *args, const QString &inArgs);
+ //! Split a shell command into separate arguments. ArgIterator is usually a better choice.
+ static QStringList splitArgs(const QString &cmd, bool abortOnMeta = false, SplitError *err = 0,
+ const Environment *env = 0, const QString *pwd = 0);
+ //! Safely replace the expandos in a shell command
+ static bool expandMacros(QString *cmd, AbstractMacroExpander *mx);
+ static QString expandMacros(const QString &str, AbstractMacroExpander *mx);
+
+ /*! Iterate over arguments from a command line.
+ * Assumes that the name of the actual command is *not* part of the line.
+ * Terminates after the first command if the command line is complex.
+ */
+ class QTCREATOR_UTILS_EXPORT ArgIterator {
+ public:
+ ArgIterator(QString *str) : m_str(str), m_pos(0), m_prev(-1) {}
+ //! Get the next argument. Returns false on encountering end of first command.
+ bool next();
+ //! True iff the argument is a plain string, possibly after unquoting.
+ bool isSimple() const { return m_simple; }
+ //! Return the string value of the current argument if it is simple, otherwise empty.
+ QString value() const { return m_value; }
+ //! Delete the last argument fetched via next() from the command line.
+ void deleteArg();
+ //! Insert argument into the command line after the last one fetched via next().
+ //! This may be used before the first call to next() to insert at the front.
+ void appendArg(const QString &str);
+ private:
+ QString *m_str, m_value;
+ int m_pos, m_prev;
+ bool m_simple;
+ };
+
+ class QTCREATOR_UTILS_EXPORT ConstArgIterator {
+ public:
+ ConstArgIterator(const QString &str) : m_str(str), m_ait(&m_str) {}
+ bool next() { return m_ait.next(); }
+ bool isSimple() const { return m_ait.isSimple(); }
+ QString value() const { return m_ait.value(); }
+ private:
+ QString m_str;
+ ArgIterator m_ait;
+ };
+
+private:
+ QString m_command;
+ QString m_arguments;
+ Environment m_environment;
+ bool m_haveEnv;
+};
+
+}
+
+#endif // QTCPROCESS_H
diff --git a/src/libs/utils/stringutils.cpp b/src/libs/utils/stringutils.cpp
index b4045a35cd..ae39c7f067 100644
--- a/src/libs/utils/stringutils.cpp
+++ b/src/libs/utils/stringutils.cpp
@@ -123,4 +123,42 @@ QTCREATOR_UTILS_EXPORT QString withTildeHomePath(const QString &path)
return outPath;
}
+int AbstractQtcMacroExpander::findMacro(const QString &str, int *pos, QString *ret)
+{
+ forever {
+ int openPos = str.indexOf(QLatin1String("%{"), *pos);
+ if (openPos < 0)
+ return 0;
+ int varPos = openPos + 2;
+ int closePos = str.indexOf(QLatin1Char('}'), varPos);
+ if (closePos < 0)
+ return 0;
+ int varLen = closePos - varPos;
+ if (resolveMacro(str.mid(varPos, varLen), ret)) {
+ *pos = openPos;
+ return varLen + 3;
+ }
+ // An actual expansion may be nested into a "false" one,
+ // so we continue right after the last %{.
+ *pos = varPos;
+ }
+}
+
+QTCREATOR_UTILS_EXPORT void expandMacros(QString *str, AbstractMacroExpander *mx)
+{
+ QString rsts;
+
+ for (int pos = 0; int len = mx->findMacro(*str, &pos, &rsts); ) {
+ str->replace(pos, len, rsts);
+ pos += rsts.length();
+ }
+}
+
+QTCREATOR_UTILS_EXPORT QString expandMacros(const QString &str, AbstractMacroExpander *mx)
+{
+ QString ret = str;
+ expandMacros(&ret, mx);
+ return ret;
+}
+
} // namespace Utils
diff --git a/src/libs/utils/stringutils.h b/src/libs/utils/stringutils.h
index a0610052ce..9fd2adf574 100644
--- a/src/libs/utils/stringutils.h
+++ b/src/libs/utils/stringutils.h
@@ -59,6 +59,31 @@ QTCREATOR_UTILS_EXPORT QString commonPath(const QStringList &files);
// If path is not sub of home path, or when running on Windows, returns the input
QTCREATOR_UTILS_EXPORT QString withTildeHomePath(const QString &path);
+class QTCREATOR_UTILS_EXPORT AbstractMacroExpander {
+public:
+ virtual ~AbstractMacroExpander() {}
+ // Not const, as it may change the state of the expander.
+ //! Find an expando to replace and provide a replacement string.
+ //! \param str The string to scan
+ //! \param pos Position to start scan on input, found position on output
+ //! \param ret Replacement string on output
+ //! \return Length of string part to replace, zero if no (further) matches found
+ virtual int findMacro(const QString &str, int *pos, QString *ret) = 0;
+};
+
+class QTCREATOR_UTILS_EXPORT AbstractQtcMacroExpander : public AbstractMacroExpander {
+public:
+ virtual int findMacro(const QString &str, int *pos, QString *ret);
+ //! Provide a replacement string for an expando
+ //! \param name The name of the expando
+ //! \param ret Replacement string on output
+ //! \return True if the expando was found
+ virtual bool resolveMacro(const QString &name, QString *ret) = 0;
+};
+
+QTCREATOR_UTILS_EXPORT void expandMacros(QString *str, AbstractMacroExpander *mx);
+QTCREATOR_UTILS_EXPORT QString expandMacros(const QString &str, AbstractMacroExpander *mx);
+
} // namespace Utils
#endif // SETTINGSTUTILS_H
diff --git a/src/libs/utils/submiteditorwidget.cpp b/src/libs/utils/submiteditorwidget.cpp
index 9c0b7e880e..eca9340d29 100644
--- a/src/libs/utils/submiteditorwidget.cpp
+++ b/src/libs/utils/submiteditorwidget.cpp
@@ -176,6 +176,8 @@ SubmitEditorWidget::SubmitEditorWidget(QWidget *parent) :
m_d->m_ui.description->setWordWrapMode(QTextOption::WordWrap);
connect(m_d->m_ui.description, SIGNAL(customContextMenuRequested(QPoint)),
this, SLOT(editorCustomContextMenuRequested(QPoint)));
+ connect(m_d->m_ui.description, SIGNAL(textChanged()),
+ this, SLOT(updateSubmitAction()));
// File List
m_d->m_ui.fileView->setContextMenuPolicy(Qt::CustomContextMenu);
@@ -295,11 +297,12 @@ static QString wrappedText(const QTextEdit *e)
QString SubmitEditorWidget::descriptionText() const
{
- QString rc = trimMessageText(lineWrap() ? wrappedText(m_d->m_ui.description) : m_d->m_ui.description->toPlainText());
+ QString rc = trimMessageText(lineWrap() ? wrappedText(m_d->m_ui.description) :
+ m_d->m_ui.description->toPlainText());
// append field entries
foreach(const SubmitFieldWidget *fw, m_d->m_fieldWidgets)
rc += fw->fieldValues();
- return rc;
+ return cleanupDescription(rc);
}
void SubmitEditorWidget::setDescriptionText(const QString &text)
@@ -499,6 +502,11 @@ unsigned SubmitEditorWidget::checkedFilesCount() const
return checkedCount;
}
+QString SubmitEditorWidget::cleanupDescription(const QString &input) const
+{
+ return input;
+}
+
void SubmitEditorWidget::changeEvent(QEvent *e)
{
QWidget::changeEvent(e);
diff --git a/src/libs/utils/submiteditorwidget.h b/src/libs/utils/submiteditorwidget.h
index 740b5963a4..88926c7aaf 100644
--- a/src/libs/utils/submiteditorwidget.h
+++ b/src/libs/utils/submiteditorwidget.h
@@ -130,6 +130,8 @@ public:
void addSubmitFieldWidget(SubmitFieldWidget *f);
QList<SubmitFieldWidget *> submitFieldWidgets() const;
+ virtual bool canSubmit() const;
+
signals:
void diffSelected(const QStringList &);
void fileSelectionChanged(bool someFileSelected);
@@ -141,9 +143,9 @@ public slots:
void uncheckAll();
protected:
+ virtual QString cleanupDescription(const QString &) const;
virtual void changeEvent(QEvent *e);
void insertTopWidget(QWidget *w);
- virtual bool canSubmit() const;
protected slots:
void updateSubmitAction();
diff --git a/src/libs/utils/unixutils.h b/src/libs/utils/unixutils.h
index 7acf43fd9b..d9d5a6860c 100644
--- a/src/libs/utils/unixutils.h
+++ b/src/libs/utils/unixutils.h
@@ -55,6 +55,6 @@ public:
const QString &file);
};
-};
+}
#endif // UNIXUTILS_H
diff --git a/src/libs/utils/utils-lib.pri b/src/libs/utils/utils-lib.pri
index 4cbc17d329..857844aa2b 100644
--- a/src/libs/utils/utils-lib.pri
+++ b/src/libs/utils/utils-lib.pri
@@ -5,8 +5,10 @@ dll {
}
INCLUDEPATH += $$PWD
+QT += network
SOURCES += $$PWD/environment.cpp \
+ $$PWD/qtcprocess.cpp \
$$PWD/reloadpromptutils.cpp \
$$PWD/stringutils.cpp \
$$PWD/filesearch.cpp \
@@ -49,7 +51,9 @@ SOURCES += $$PWD/environment.cpp \
$$PWD/crumblepath.cpp \
$$PWD/debuggerlanguagechooser.cpp \
$$PWD/historycompleter.cpp \
- $$PWD/buildablehelperlibrary.cpp
+ $$PWD/buildablehelperlibrary.cpp \
+ $$PWD/annotateditemdelegate.cpp \
+ $$PWD/fileinprojectfinder.cpp
win32 {
SOURCES += $$PWD/abstractprocess_win.cpp \
@@ -64,6 +68,7 @@ unix:!macx {
SOURCES += $$PWD/unixutils.cpp
}
HEADERS += $$PWD/environment.h \
+ $$PWD/qtcprocess.h \
$$PWD/utils_global.h \
$$PWD/reloadpromptutils.h \
$$PWD/stringutils.h \
@@ -110,7 +115,9 @@ HEADERS += $$PWD/environment.h \
$$PWD/crumblepath.h \
$$PWD/debuggerlanguagechooser.h \
$$PWD/historycompleter.h \
- $$PWD/buildablehelperlibrary.h
+ $$PWD/buildablehelperlibrary.h \
+ $$PWD/annotateditemdelegate.h \
+ $$PWD/fileinprojectfinder.h
FORMS += $$PWD/filewizardpage.ui \
$$PWD/projectintropage.ui \
diff --git a/src/libs/utils/winutils.cpp b/src/libs/utils/winutils.cpp
index ae62b9c6a1..b4cbf6bc40 100644
--- a/src/libs/utils/winutils.cpp
+++ b/src/libs/utils/winutils.cpp
@@ -32,6 +32,10 @@
**************************************************************************/
#include "winutils.h"
+#include "qtcassert.h"
+
+// Enable WinAPI Windows XP and later
+#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <QtCore/QString>
@@ -39,6 +43,7 @@
#include <QtCore/QDebug>
#include <QtCore/QLibrary>
#include <QtCore/QTextStream>
+#include <QtCore/QDir>
namespace Utils {
@@ -109,8 +114,9 @@ QTCREATOR_UTILS_EXPORT QString winGetDLLVersion(WinDLLVersionType t,
return QString();
}
VS_FIXEDFILEINFO *versionInfo;
+ const LPCWSTR backslash = TEXT("\\");
UINT len = 0;
- if (!(*verQueryValueW)(data, TEXT("\\"), &versionInfo, &len)) {
+ if (!(*verQueryValueW)(data, const_cast<LPWSTR>(backslash), &versionInfo, &len)) {
*errorMessage = QString::fromLatin1("Unable to determine version string of %1: %2").arg(name, winErrorMessage(GetLastError()));
return QString();
}
@@ -159,10 +165,37 @@ QTCREATOR_UTILS_EXPORT QString getShortPathName(const QString &name, QString *er
return rc;
}
-unsigned long winQPidToPid(const Q_PID qpid)
+QTCREATOR_UTILS_EXPORT unsigned long winQPidToPid(const Q_PID qpid)
{
const PROCESS_INFORMATION *processInfo = reinterpret_cast<const PROCESS_INFORMATION*>(qpid);
return processInfo->dwProcessId;
}
+QTCREATOR_UTILS_EXPORT bool winIs64BitSystem()
+{
+ SYSTEM_INFO systemInfo;
+ GetNativeSystemInfo(&systemInfo);
+ return systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64
+ || systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64;
+}
+
+QTCREATOR_UTILS_EXPORT bool winIs64BitBinary(const QString &binaryIn)
+{
+ QTC_ASSERT(!binaryIn.isEmpty(), return false; )
+#ifdef Q_OS_WIN32
+# ifdef __GNUC__ // MinGW lacking some definitions/winbase.h
+# define SCS_64BIT_BINARY 6
+# endif
+ bool isAmd64 = false;
+ DWORD binaryType = 0;
+ const QString binary = QDir::toNativeSeparators(binaryIn);
+ bool success = GetBinaryTypeW(reinterpret_cast<const TCHAR*>(binary.utf16()), &binaryType) != 0;
+ if (success && binaryType == SCS_64BIT_BINARY)
+ isAmd64=true;
+ return isAmd64;
+#else
+ return false;
+#endif
+}
+
} // namespace Utils
diff --git a/src/libs/utils/winutils.h b/src/libs/utils/winutils.h
index a5c1577dab..3ad9eabf5c 100644
--- a/src/libs/utils/winutils.h
+++ b/src/libs/utils/winutils.h
@@ -60,5 +60,10 @@ QTCREATOR_UTILS_EXPORT QString getShortPathName(const QString &name,
QTCREATOR_UTILS_EXPORT unsigned long winQPidToPid(const Q_PID qpid);
+QTCREATOR_UTILS_EXPORT bool winIs64BitSystem();
+
+// Check for a 64bit binary.
+QTCREATOR_UTILS_EXPORT bool winIs64BitBinary(const QString &binary);
+
} // namespace Utils
#endif // WINUTILS_H
diff --git a/src/libs/utils/wizard.cpp b/src/libs/utils/wizard.cpp
index 8cfabed5cc..465af19416 100644
--- a/src/libs/utils/wizard.cpp
+++ b/src/libs/utils/wizard.cpp
@@ -93,6 +93,7 @@ private slots:
void slotItemRemoved(WizardProgressItem *item);
void slotItemChanged(WizardProgressItem *item);
void slotNextItemsChanged(WizardProgressItem *item, const QList<WizardProgressItem *> &nextItems);
+ void slotNextShownItemChanged(WizardProgressItem *item, WizardProgressItem *nextItem);
void slotStartItemChanged(WizardProgressItem *item);
void slotCurrentItemChanged(WizardProgressItem *item);
@@ -139,6 +140,8 @@ LinearProgressWidget::LinearProgressWidget(WizardProgress *progress, QWidget *pa
this, SLOT(slotItemChanged(WizardProgressItem *)));
connect(m_wizardProgress, SIGNAL(nextItemsChanged(WizardProgressItem *, const QList<WizardProgressItem *> &)),
this, SLOT(slotNextItemsChanged(WizardProgressItem *, const QList<WizardProgressItem *> &)));
+ connect(m_wizardProgress, SIGNAL(nextShownItemChanged(WizardProgressItem *, WizardProgressItem *)),
+ this, SLOT(slotNextShownItemChanged(WizardProgressItem *, WizardProgressItem *)));
connect(m_wizardProgress, SIGNAL(startItemChanged(WizardProgressItem *)),
this, SLOT(slotStartItemChanged(WizardProgressItem *)));
connect(m_wizardProgress, SIGNAL(currentItemChanged(WizardProgressItem *)),
@@ -192,6 +195,13 @@ void LinearProgressWidget::slotNextItemsChanged(WizardProgressItem *item, const
recreateLayout();
}
+void LinearProgressWidget::slotNextShownItemChanged(WizardProgressItem *item, WizardProgressItem *nextItem)
+{
+ Q_UNUSED(nextItem)
+ if (m_visibleItems.contains(item))
+ recreateLayout();
+}
+
void LinearProgressWidget::slotStartItemChanged(WizardProgressItem *item)
{
Q_UNUSED(item)
@@ -341,6 +351,12 @@ WizardProgress *Wizard::wizardProgress() const
return d->m_wizardProgress;
}
+bool Wizard::validateCurrentPage()
+{
+ emit nextClicked();
+ return QWizard::validateCurrentPage();
+}
+
void Wizard::_q_currentPageChanged(int pageId)
{
Q_D(Wizard);
@@ -469,6 +485,7 @@ public:
QList<int> m_pages;
QList<WizardProgressItem *> m_nextItems;
QList<WizardProgressItem *> m_prevItems;
+ WizardProgressItem *m_nextShownItem;
};
bool WizardProgressPrivate::isNextItem(WizardProgressItem *item, WizardProgressItem *nextItem) const
@@ -551,8 +568,8 @@ void WizardProgressPrivate::updateReachableItems()
}
if (!item)
return;
- while (item->nextItems().count() == 1) {
- item = item->nextItems().first();
+ while (item->nextShownItem()) {
+ item = item->nextShownItem();
m_reachableItems.append(item);
}
}
@@ -772,6 +789,7 @@ WizardProgressItem::WizardProgressItem(WizardProgress *progress, const QString &
d_ptr->m_title = title;
d_ptr->m_titleWordWrap = false;
d_ptr->m_wizardProgress = progress;
+ d_ptr->m_nextShownItem = 0;
}
WizardProgressItem::~WizardProgressItem()
@@ -814,6 +832,9 @@ void WizardProgressItem::setNextItems(const QList<WizardProgressItem *> &items)
if (d->m_nextItems == items) // nothing changes
return;
+ if (!items.contains(d->m_nextShownItem))
+ setNextShownItem(0);
+
// update prev items (remove this item from the old next items)
for (int i = 0; i < d->m_nextItems.count(); i++) {
WizardProgressItem *nextItem = d->m_nextItems.at(i);
@@ -827,9 +848,13 @@ void WizardProgressItem::setNextItems(const QList<WizardProgressItem *> &items)
WizardProgressItem *nextItem = d->m_nextItems.at(i);
nextItem->d_ptr->m_prevItems.append(this);
}
+
d->m_wizardProgress->d_ptr->updateReachableItems();
emit d->m_wizardProgress->nextItemsChanged(this, items);
+
+ if (items.count() == 1)
+ setNextShownItem(items.first());
}
QList<WizardProgressItem *> WizardProgressItem::nextItems() const
@@ -839,6 +864,30 @@ QList<WizardProgressItem *> WizardProgressItem::nextItems() const
return d->m_nextItems;
}
+void WizardProgressItem::setNextShownItem(WizardProgressItem *item)
+{
+ Q_D(WizardProgressItem);
+
+ if (d->m_nextShownItem == item) // nothing changes
+ return;
+
+ if (item && !d->m_nextItems.contains(item)) // the "item" is not a one of next items
+ return;
+
+ d->m_nextShownItem = item;
+
+ d->m_wizardProgress->d_ptr->updateReachableItems();
+
+ emit d->m_wizardProgress->nextShownItemChanged(this, item);
+}
+
+WizardProgressItem *WizardProgressItem::nextShownItem() const
+{
+ Q_D(const WizardProgressItem);
+
+ return d->m_nextShownItem;
+}
+
bool WizardProgressItem::isFinalItem() const
{
return nextItems().isEmpty();
diff --git a/src/libs/utils/wizard.h b/src/libs/utils/wizard.h
index 2db72e23b6..d990312715 100644
--- a/src/libs/utils/wizard.h
+++ b/src/libs/utils/wizard.h
@@ -61,6 +61,11 @@ public:
void setStartId(int pageId);
WizardProgress *wizardProgress() const;
+ virtual bool validateCurrentPage();
+
+signals:
+ void nextClicked(); /* workaround for QWizard behavior where page->initialize is
+ called before currentIdChanged */
private slots:
void _q_currentPageChanged(int pageId);
@@ -111,6 +116,7 @@ Q_SIGNALS:
void itemAdded(WizardProgressItem *item);
void itemRemoved(WizardProgressItem *item);
void nextItemsChanged(WizardProgressItem *item, const QList<WizardProgressItem *> &items);
+ void nextShownItemChanged(WizardProgressItem *item, WizardProgressItem *nextShownItem);
void startItemChanged(WizardProgressItem *item);
private:
@@ -137,6 +143,8 @@ public:
QList<int> pages() const;
void setNextItems(const QList<WizardProgressItem *> &items);
QList<WizardProgressItem *> nextItems() const;
+ void setNextShownItem(WizardProgressItem *item);
+ WizardProgressItem *nextShownItem() const;
bool isFinalItem() const; // return nextItems().isEmpty();
void setTitle(const QString &title);
diff --git a/src/plugins/bineditor/BinEditor.pluginspec b/src/plugins/bineditor/BinEditor.pluginspec
deleted file mode 100644
index 74586944ba..0000000000
--- a/src/plugins/bineditor/BinEditor.pluginspec
+++ /dev/null
@@ -1,20 +0,0 @@
-<plugin name="BinEditor" version="2.0.95" compatVersion="2.0.95">
- <vendor>Nokia Corporation</vendor>
- <copyright>(C) 2010 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>
- <category>Qt Creator</category>
- <description>Binary editor component.</description>
- <url>http://qt.nokia.com</url>
- <dependencyList>
- <dependency name="Core" version="2.0.95"/>
- <dependency name="TextEditor" version="2.0.95"/>
- </dependencyList>
-</plugin>
diff --git a/src/plugins/bineditor/BinEditor.pluginspec.in b/src/plugins/bineditor/BinEditor.pluginspec.in
new file mode 100644
index 0000000000..c6d211c956
--- /dev/null
+++ b/src/plugins/bineditor/BinEditor.pluginspec.in
@@ -0,0 +1,20 @@
+<plugin name=\"BinEditor\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2010 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>
+ <category>Qt Creator</category>
+ <description>Binary editor component.</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"TextEditor\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/bineditor/bineditor.cpp b/src/plugins/bineditor/bineditor.cpp
index 11f95d2c09..2bb7d710a2 100644
--- a/src/plugins/bineditor/bineditor.cpp
+++ b/src/plugins/bineditor/bineditor.cpp
@@ -37,6 +37,7 @@
#include <texteditor/texteditorconstants.h>
#include <QtCore/QByteArrayMatcher>
+#include <QtCore/QDebug>
#include <QtCore/QFile>
#include <QtCore/QTemporaryFile>
@@ -52,8 +53,6 @@
#include <QtGui/QToolTip>
#include <QtGui/QWheelEvent>
-using namespace BINEditor;
-
// QByteArray::toLower() is broken, it stops at the first \0
static void lower(QByteArray &ba)
{
@@ -84,6 +83,8 @@ static QByteArray calculateHexPattern(const QByteArray &pattern)
return result;
}
+namespace BINEditor {
+
BinEditor::BinEditor(QWidget *parent)
: QAbstractScrollArea(parent)
{
@@ -185,27 +186,34 @@ bool BinEditor::requestDataAt(int pos, bool synchronous) const
if (it != m_modifiedData.constEnd())
return true;
it = m_lazyData.find(block);
- if (it == m_lazyData.end()) {
- if (!m_lazyRequests.contains(block)) {
- m_lazyRequests.insert(block);
- emit const_cast<BinEditor*>(this)->
- lazyDataRequested(editorInterface(), m_baseAddr / m_blockSize + block,
- synchronous);
- if (!m_lazyRequests.contains(block))
- return true; // synchronous data source
- }
- return false;
+ if (it != m_lazyData.end())
+ return true;
+ if (!m_lazyRequests.contains(block)) {
+ m_lazyRequests.insert(block);
+ emit const_cast<BinEditor*>(this)->
+ lazyDataRequested(editorInterface(), m_baseAddr / m_blockSize + block,
+ synchronous);
+ if (!m_lazyRequests.contains(block))
+ return true; // synchronous data source
}
+ return false;
+}
- return true;
+bool BinEditor::requestOldDataAt(int pos) const
+{
+ if (!m_inLazyMode)
+ return false;
+ int block = pos / m_blockSize;
+ QMap<int, QByteArray>::const_iterator it = m_oldLazyData.find(block);
+ return it != m_oldLazyData.end();
}
-char BinEditor::dataAt(int pos) const
+char BinEditor::dataAt(int pos, bool old) const
{
if (!m_inLazyMode)
return m_data.at(pos);
int block = pos / m_blockSize;
- return blockData(block).at(pos - (block*m_blockSize));
+ return blockData(block, old).at(pos - (block*m_blockSize));
}
void BinEditor::changeDataAt(int pos, char c)
@@ -228,7 +236,7 @@ void BinEditor::changeDataAt(int pos, char c)
}
}
-QByteArray BinEditor::dataMid(int from, int length) const
+QByteArray BinEditor::dataMid(int from, int length, bool old) const
{
if (!m_inLazyMode)
return m_data.mid(from, length);
@@ -239,14 +247,19 @@ QByteArray BinEditor::dataMid(int from, int length) const
QByteArray data;
data.reserve(length);
do {
- data += blockData(block++);
+ data += blockData(block++, old);
} while (block * m_blockSize < end);
return data.mid(from - ((from / m_blockSize) * m_blockSize), length);
}
-QByteArray BinEditor::blockData(int block) const
+QByteArray BinEditor::blockData(int block, bool old) const
{
+ if (old) {
+ QMap<int, QByteArray>::const_iterator it = m_modifiedData.find(block);
+ return it != m_modifiedData.constEnd()
+ ? it.value() : m_oldLazyData.value(block, m_emptyBlock);
+ }
if (!m_inLazyMode) {
QByteArray data = m_data.mid(block * m_blockSize, m_blockSize);
if (data.size() < m_blockSize)
@@ -258,7 +271,6 @@ QByteArray BinEditor::blockData(int block) const
? it.value() : m_lazyData.value(block, m_emptyBlock);
}
-
void BinEditor::setFontSettings(const TextEditor::FontSettings &fs)
{
setFont(fs.toTextCharFormat(QLatin1String(TextEditor::Constants::C_TEXT)).font());
@@ -291,10 +303,13 @@ void BinEditor::timerEvent(QTimerEvent *e)
QPoint pos;
const QPoint globalPos = QCursor::pos();
pos = viewport()->mapFromGlobal(globalPos);
- QMouseEvent ev(QEvent::MouseMove, pos, globalPos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
+ QMouseEvent ev(QEvent::MouseMove, pos, globalPos,
+ Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
mouseMoveEvent(&ev);
- int deltaY = qMax(pos.y() - visible.top(), visible.bottom() - pos.y()) - visible.height();
- int deltaX = qMax(pos.x() - visible.left(), visible.right() - pos.x()) - visible.width();
+ int deltaY = qMax(pos.y() - visible.top(),
+ visible.bottom() - pos.y()) - visible.height();
+ int deltaX = qMax(pos.x() - visible.left(),
+ visible.right() - pos.x()) - visible.width();
int delta = qMax(deltaX, deltaY);
if (delta >= 0) {
if (delta < 7)
@@ -348,6 +363,7 @@ void BinEditor::setData(const QByteArray &data)
m_inLazyMode = false;
m_baseAddr = 0;
m_lazyData.clear();
+ m_oldLazyData.clear();
m_modifiedData.clear();
m_lazyRequests.clear();
m_data = data;
@@ -423,7 +439,6 @@ void BinEditor::setLazyData(quint64 startAddr, int range, int blockSize)
Q_ASSERT((blockSize/16) * 16 == blockSize);
m_emptyBlock = QByteArray(blockSize, '\0');
m_data.clear();
- m_lazyData.clear();
m_modifiedData.clear();
m_lazyRequests.clear();
@@ -501,9 +516,10 @@ QRect BinEditor::cursorRect() const
int y = (line - topLine) * m_lineHeight;
int xoffset = horizontalScrollBar()->value();
int column = m_cursorPosition % 16;
- int x = m_hexCursor ?
- (-xoffset + m_margin + m_labelWidth + column * m_columnWidth)
- : (-xoffset + m_margin + m_labelWidth + 16 * m_columnWidth + m_charWidth + column * m_charWidth);
+ int x = m_hexCursor
+ ? (-xoffset + m_margin + m_labelWidth + column * m_columnWidth)
+ : (-xoffset + m_margin + m_labelWidth + 16 * m_columnWidth
+ + m_charWidth + column * m_charWidth);
int w = m_hexCursor ? m_columnWidth : m_charWidth;
return QRect(x, y, w, m_lineHeight);
}
@@ -667,12 +683,15 @@ int BinEditor::find(const QByteArray &pattern_arg, int from,
return pos;
}
-int BinEditor::findPattern(const QByteArray &data, const QByteArray &dataHex, int from, int offset, int *match)
+int BinEditor::findPattern(const QByteArray &data, const QByteArray &dataHex,
+ int from, int offset, int *match)
{
if (m_searchPattern.isEmpty())
return -1;
- int normal = m_searchPattern.isEmpty()? -1 : data.indexOf(m_searchPattern, from - offset);
- int hex = m_searchPatternHex.isEmpty()? -1 : dataHex.indexOf(m_searchPatternHex, from - offset);
+ int normal = m_searchPattern.isEmpty()
+ ? -1 : data.indexOf(m_searchPattern, from - offset);
+ int hex = m_searchPatternHex.isEmpty()
+ ? -1 : dataHex.indexOf(m_searchPatternHex, from - offset);
if (normal >= 0 && (hex < 0 || normal < hex)) {
if (match)
@@ -699,6 +718,17 @@ void BinEditor::drawItems(QPainter *painter, int x, int y, const QString &itemSt
}
}
+void BinEditor::drawChanges(QPainter *painter, int x, int y, const char *changes)
+{
+ const QBrush red(QColor(250, 150, 150));
+ for (int i = 0; i < 16; ++i) {
+ if (changes[i]) {
+ painter->fillRect(x + i*m_columnWidth, y - m_ascent,
+ 2*m_charWidth, m_lineHeight, red);
+ }
+ }
+}
+
QString BinEditor::addressString(quint64 address)
{
QChar *addressStringData = m_addressString.data();
@@ -751,11 +781,18 @@ void BinEditor::paintEvent(QPaintEvent *e)
int foundPatternAt = findPattern(patternData, patternDataHex, patternOffset, patternOffset, &matchLength);
- int selStart = qMin(m_cursorPosition, m_anchorPosition);
- int selEnd = qMax(m_cursorPosition, m_anchorPosition);
+ int selStart, selEnd;
+ if (m_cursorPosition >= m_anchorPosition) {
+ selStart = m_anchorPosition;
+ selEnd = m_cursorPosition;
+ } else {
+ selStart = m_cursorPosition;
+ selEnd = m_anchorPosition + 1;
+ }
QString itemString(16*3, QLatin1Char(' '));
QChar *itemStringData = itemString.data();
+ char changedString[16] = { false };
const char *hex = "0123456789abcdef";
painter.setPen(palette().text().color());
@@ -773,22 +810,24 @@ void BinEditor::paintEvent(QPaintEvent *e)
painter.drawText(-xoffset, i * m_lineHeight + m_ascent,
- addressString(m_baseAddr + ((uint) line) * 16));
+ addressString(m_baseAddr + uint(line) * 16));
int cursor = -1;
if (line * 16 <= m_cursorPosition && m_cursorPosition < line * 16 + 16)
cursor = m_cursorPosition - line * 16;
bool hasData = requestDataAt(line * 16);
+ bool hasOldData = requestOldDataAt(line * 16);
+ bool isOld = hasOldData && !hasData;
QString printable;
- if (hasData) {
+ if (hasData || hasOldData) {
for (int c = 0; c < 16; ++c) {
int pos = line * 16 + c;
if (pos >= m_size)
break;
- QChar qc(QLatin1Char(dataAt(pos)));
+ QChar qc(QLatin1Char(dataAt(pos, isOld)));
if (qc.unicode() >= 127 || !qc.isPrint())
qc = 0xB7;
printable += qc;
@@ -801,8 +840,9 @@ void BinEditor::paintEvent(QPaintEvent *e)
QRect printableSelectionRect;
bool isFullySelected = (selStart < selEnd && selStart <= line*16 && (line+1)*16 <= selEnd);
+ bool somethingChanged = false;
- if (hasData) {
+ if (hasData || hasOldData) {
for (int c = 0; c < 16; ++c) {
int pos = line * 16 + c;
if (pos >= m_size) {
@@ -817,9 +857,13 @@ void BinEditor::paintEvent(QPaintEvent *e)
foundPatternAt = findPattern(patternData, patternDataHex, foundPatternAt + matchLength, patternOffset, &matchLength);
- uchar value = (uchar)dataAt(pos);
+ const uchar value = uchar(dataAt(pos, isOld));
itemStringData[c*3] = hex[value >> 4];
itemStringData[c*3+1] = hex[value & 0xf];
+ if (hasOldData && !isOld && value != uchar(dataAt(pos, true))) {
+ changedString[c] = true;
+ somethingChanged = true;
+ }
int item_x = -xoffset + m_margin + c * m_columnWidth + m_labelWidth;
@@ -844,6 +888,7 @@ void BinEditor::paintEvent(QPaintEvent *e)
}
int x = -xoffset + m_margin + m_labelWidth;
+ bool cursorWanted = m_cursorPosition == m_anchorPosition;
if (isFullySelected) {
painter.save();
@@ -852,6 +897,8 @@ void BinEditor::paintEvent(QPaintEvent *e)
drawItems(&painter, x, y, itemString);
painter.restore();
} else {
+ if (somethingChanged)
+ drawChanges(&painter, x, y, changedString);
drawItems(&painter, x, y, itemString);
if (!selectionRect.isEmpty()) {
painter.save();
@@ -864,7 +911,7 @@ void BinEditor::paintEvent(QPaintEvent *e)
}
- if (cursor >= 0) {
+ if (cursor >= 0 && cursorWanted) {
int w = fm.boundingRect(itemString.mid(cursor*3, 2)).width();
QRect cursorRect(x + cursor * m_columnWidth, y - m_ascent, w + 1, m_lineHeight);
painter.save();
@@ -892,7 +939,7 @@ void BinEditor::paintEvent(QPaintEvent *e)
painter.setPen(palette().highlightedText().color());
painter.drawText(text_x, y, printable);
painter.restore();
- }else {
+ } else {
painter.drawText(text_x, y, printable);
if (!printableSelectionRect.isEmpty()) {
painter.save();
@@ -904,7 +951,7 @@ void BinEditor::paintEvent(QPaintEvent *e)
}
}
- if (cursor >= 0 && !printable.isEmpty()) {
+ if (cursor >= 0 && !printable.isEmpty() && cursorWanted) {
QRect cursorRect(text_x + fm.width(printable.left(cursor)),
y-m_ascent,
fm.width(printable.at(cursor)),
@@ -1037,12 +1084,14 @@ bool BinEditor::event(QEvent *e) {
default:;
}
} else if (e->type() == QEvent::ToolTip) {
+ const QHelpEvent * const helpEvent = static_cast<QHelpEvent *>(e);
bool hide = true;
int selStart = selectionStart();
int selEnd = selectionEnd();
int byteCount = selEnd - selStart;
if (byteCount <= 0) {
selStart = m_cursorPosition;
+ selStart = posAt(helpEvent->pos());
selEnd = selStart + 1;
byteCount = 1;
}
@@ -1052,40 +1101,68 @@ bool BinEditor::event(QEvent *e) {
const QPoint expandedEndPoint
= QPoint(endPoint.x(), endPoint.y() + m_lineHeight);
const QRect selRect(startPoint, expandedEndPoint);
- const QHelpEvent * const helpEvent = static_cast<QHelpEvent *>(e);
const QPoint &mousePos = helpEvent->pos();
if (selRect.contains(mousePos)) {
quint64 beValue, leValue;
+ quint64 beValueOld, leValueOld;
asIntegers(selStart, byteCount, beValue, leValue);
+ asIntegers(selStart, byteCount, beValueOld, leValueOld, true);
QString leSigned;
QString beSigned;
+ QString leSignedOld;
+ QString beSignedOld;
switch (byteCount) {
case 8: case 7: case 6: case 5:
leSigned = QString::number(static_cast<qint64>(leValue));
beSigned = QString::number(static_cast<qint64>(beValue));
+ leSignedOld = QString::number(static_cast<qint64>(leValueOld));
+ beSignedOld = QString::number(static_cast<qint64>(beValueOld));
break;
case 4: case 3:
leSigned = QString::number(static_cast<qint32>(leValue));
beSigned = QString::number(static_cast<qint32>(beValue));
+ leSignedOld = QString::number(static_cast<qint32>(leValueOld));
+ beSignedOld = QString::number(static_cast<qint32>(beValueOld));
break;
case 2:
leSigned = QString::number(static_cast<qint16>(leValue));
beSigned = QString::number(static_cast<qint16>(beValue));
+ leSignedOld = QString::number(static_cast<qint16>(leValueOld));
+ beSignedOld = QString::number(static_cast<qint16>(beValueOld));
break;
case 1:
leSigned = QString::number(static_cast<qint8>(leValue));
beSigned = QString::number(static_cast<qint8>(beValue));
+ leSignedOld = QString::number(static_cast<qint8>(leValueOld));
+ beSignedOld = QString::number(static_cast<qint8>(beValueOld));
break;
}
hide = false;
- QToolTip::showText(helpEvent->globalPos(),
+ //int pos = posAt(mousePos);
+ //uchar old = dataAt(pos, true);
+ //uchar current = dataAt(pos, false);
+
+ QString msg =
tr("Decimal unsigned value (little endian): %1\n"
"Decimal unsigned value (big endian): %2\n"
"Decimal signed value (little endian): %3\n"
"Decimal signed value (big endian): %4")
.arg(QString::number(leValue))
.arg(QString::number(beValue))
- .arg(leSigned).arg(beSigned));
+ .arg(leSigned)
+ .arg(beSigned);
+ if (beValue != beValueOld) {
+ msg += QLatin1Char('\n');
+ msg += tr("Previous decimal unsigned value (little endian): %1\n"
+ "Previous decimal unsigned value (big endian): %2\n"
+ "Previous decimal signed value (little endian): %3\n"
+ "Previous decimal signed value (big endian): %4")
+ .arg(QString::number(leValueOld))
+ .arg(QString::number(beValueOld))
+ .arg(leSignedOld)
+ .arg(beSignedOld);
+ }
+ QToolTip::showText(helpEvent->globalPos(), msg, this);
}
}
if (hide)
@@ -1217,30 +1294,31 @@ void BinEditor::zoomOut(int range)
void BinEditor::copy(bool raw)
{
- const int selStart = selectionStart();
- const int selEnd = selectionEnd();
- if (selStart < selEnd) {
- const int selectionLength = selEnd - selStart;
- if (selectionLength >> 22) {
- QMessageBox::warning(this, tr("Copying Failed"),
- tr("You cannot copy more than 4 MB of binary data."));
- return;
- }
- const QByteArray &data = dataMid(selStart, selectionLength);
- if (raw) {
- QApplication::clipboard()->setText(data);
- return;
- }
- QString hexString;
- const char * const hex = "0123456789abcdef";
- hexString.reserve(3 * data.size());
- for (int i = 0; i < data.size(); ++i) {
- const uchar val = static_cast<uchar>(data[i]);
- hexString.append(hex[val >> 4]).append(hex[val & 0xf]).append(' ');
- }
- hexString.chop(1);
- QApplication::clipboard()->setText(hexString);
+ int selStart = selectionStart();
+ int selEnd = selectionEnd();
+ if (selStart >= selEnd)
+ qSwap(selStart, selEnd);
+
+ const int selectionLength = selEnd - selStart;
+ if (selectionLength >> 22) {
+ QMessageBox::warning(this, tr("Copying Failed"),
+ tr("You cannot copy more than 4 MB of binary data."));
+ return;
+ }
+ const QByteArray &data = dataMid(selStart, selectionLength);
+ if (raw) {
+ QApplication::clipboard()->setText(data);
+ return;
+ }
+ QString hexString;
+ const char * const hex = "0123456789abcdef";
+ hexString.reserve(3 * data.size());
+ for (int i = 0; i < data.size(); ++i) {
+ const uchar val = static_cast<uchar>(data[i]);
+ hexString.append(hex[val >> 4]).append(hex[val & 0xf]).append(' ');
}
+ hexString.chop(1);
+ QApplication::clipboard()->setText(hexString);
}
void BinEditor::highlightSearchResults(const QByteArray &pattern, QTextDocument::FindFlags findFlags)
@@ -1268,7 +1346,10 @@ void BinEditor::changeData(int position, uchar character, bool highNibble)
cmd.character = (uchar) dataAt(position);
cmd.highNibble = highNibble;
- if (!highNibble && !m_undoStack.isEmpty() && m_undoStack.top().position == position && m_undoStack.top().highNibble) {
+ if (!highNibble
+ && !m_undoStack.isEmpty()
+ && m_undoStack.top().position == position
+ && m_undoStack.top().highNibble) {
// compress
cmd.character = m_undoStack.top().character;
m_undoStack.pop();
@@ -1404,6 +1485,13 @@ void BinEditor::setNewWindowRequestAllowed()
m_canRequestNewWindow = true;
}
+void BinEditor::updateContents()
+{
+ m_oldLazyData = m_lazyData;
+ m_lazyData.clear();
+ setLazyData(baseAddress() + cursorPosition(), dataSize(), m_blockSize);
+}
+
QPoint BinEditor::offsetToPos(int offset)
{
const int x = m_labelWidth + (offset % 16) * m_columnWidth;
@@ -1412,13 +1500,15 @@ QPoint BinEditor::offsetToPos(int offset)
}
void BinEditor::asIntegers(int offset, int count, quint64 &beValue,
- quint64 &leValue)
+ quint64 &leValue, bool old)
{
beValue = leValue = 0;
- const QByteArray &data = dataMid(offset, count);
+ const QByteArray &data = dataMid(offset, count, old);
for (int pos = 0; pos < count; ++pos) {
const quint64 val = static_cast<quint64>(data.at(pos)) & 0xff;
beValue += val << (pos * 8);
leValue += val << ((count - pos - 1) * 8);
}
}
+
+} // namespace BINEditor
diff --git a/src/plugins/bineditor/bineditor.h b/src/plugins/bineditor/bineditor.h
index 2bd16b8ad4..799b546192 100644
--- a/src/plugins/bineditor/bineditor.h
+++ b/src/plugins/bineditor/bineditor.h
@@ -61,8 +61,8 @@ class BinEditor : public QAbstractScrollArea
Q_OBJECT
Q_PROPERTY(bool modified READ isModified WRITE setModified DESIGNABLE false)
Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly DESIGNABLE false)
-public:
+public:
BinEditor(QWidget *parent = 0);
~BinEditor();
@@ -77,6 +77,7 @@ public:
inline int lazyDataBlockSize() const { return m_blockSize; }
Q_INVOKABLE void addLazyData(quint64 block, const QByteArray &data);
Q_INVOKABLE void setNewWindowRequestAllowed();
+ Q_INVOKABLE void updateContents();
bool save(const QString &oldFileName, const QString &newFileName);
void zoomIn(int range = 1);
@@ -124,7 +125,8 @@ public:
public Q_SLOTS:
void setFontSettings(const TextEditor::FontSettings &fs);
- void highlightSearchResults(const QByteArray &pattern, QTextDocument::FindFlags findFlags = 0);
+ void highlightSearchResults(const QByteArray &pattern,
+ QTextDocument::FindFlags findFlags = 0);
void copy(bool raw = false);
Q_SIGNALS:
@@ -158,9 +160,10 @@ protected:
private:
bool m_inLazyMode;
QByteArray m_data;
- QMap <int, QByteArray> m_lazyData;
+ QMap<int, QByteArray> m_lazyData;
+ QMap<int, QByteArray> m_oldLazyData;
int m_blockSize;
- QMap <int, QByteArray> m_modifiedData;
+ QMap<int, QByteArray> m_modifiedData;
mutable QSet<int> m_lazyRequests;
QByteArray m_emptyBlock;
QByteArray m_lowerBlock;
@@ -170,13 +173,16 @@ private:
int dataLastIndexOf(const QByteArray &pattern, int from, bool caseSensitive = true) const;
bool requestDataAt(int pos, bool synchronous = false) const;
- char dataAt(int pos) const;
+ bool requestOldDataAt(int pos) const;
+ char dataAt(int pos, bool old = false) const;
+ char oldDataAt(int pos) const;
void changeDataAt(int pos, char c);
- QByteArray dataMid(int from, int length) const;
- QByteArray blockData(int block) const;
+ QByteArray dataMid(int from, int length, bool old = false) const;
+ QByteArray blockData(int block, bool old = false) const;
QPoint offsetToPos(int offset);
- void asIntegers(int offset, int count, quint64 &beValue, quint64 &leValue);
+ void asIntegers(int offset, int count, quint64 &beValue, quint64 &leValue,
+ bool old = false);
int m_unmodifiedState;
int m_readOnly;
@@ -217,8 +223,10 @@ private:
void changeData(int position, uchar character, bool highNibble = false);
- int findPattern(const QByteArray &data, const QByteArray &dataHex, int from, int offset, int *match);
+ int findPattern(const QByteArray &data, const QByteArray &dataHex,
+ int from, int offset, int *match);
void drawItems(QPainter *painter, int x, int y, const QString &itemString);
+ void drawChanges(QPainter *painter, int x, int y, const char *changes);
void setupJumpToMenuAction(QMenu *menu, QAction *actionHere, QAction *actionNew,
quint64 addr);
diff --git a/src/plugins/bineditor/bineditor.pro b/src/plugins/bineditor/bineditor.pro
index e7986d27b6..0ccd430829 100644
--- a/src/plugins/bineditor/bineditor.pro
+++ b/src/plugins/bineditor/bineditor.pro
@@ -11,5 +11,3 @@ SOURCES += bineditorplugin.cpp \
bineditor.cpp
RESOURCES +=
-
-OTHER_FILES += BinEditor.pluginspec
diff --git a/src/plugins/bineditor/bineditorplugin.cpp b/src/plugins/bineditor/bineditorplugin.cpp
index c45ed746ef..fa9f5546bd 100644
--- a/src/plugins/bineditor/bineditorplugin.cpp
+++ b/src/plugins/bineditor/bineditorplugin.cpp
@@ -49,6 +49,7 @@
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/coreconstants.h>
+#include <coreplugin/uniqueidmanager.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/icore.h>
diff --git a/src/plugins/bookmarks/Bookmarks.pluginspec b/src/plugins/bookmarks/Bookmarks.pluginspec
deleted file mode 100644
index 8b62efc136..0000000000
--- a/src/plugins/bookmarks/Bookmarks.pluginspec
+++ /dev/null
@@ -1,21 +0,0 @@
-<plugin name="Bookmarks" version="2.0.95" compatVersion="2.0.95">
- <vendor>Nokia Corporation</vendor>
- <copyright>(C) 2010 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>
- <category>Qt Creator</category>
- <description>Bookmarks in text editors.</description>
- <url>http://qt.nokia.com</url>
- <dependencyList>
- <dependency name="TextEditor" version="2.0.95"/>
- <dependency name="ProjectExplorer" version="2.0.95"/>
- <dependency name="Core" version="2.0.95"/>
- </dependencyList>
-</plugin>
diff --git a/src/plugins/bookmarks/Bookmarks.pluginspec.in b/src/plugins/bookmarks/Bookmarks.pluginspec.in
new file mode 100644
index 0000000000..1d62cd7554
--- /dev/null
+++ b/src/plugins/bookmarks/Bookmarks.pluginspec.in
@@ -0,0 +1,21 @@
+<plugin name=\"Bookmarks\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2010 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>
+ <category>Qt Creator</category>
+ <description>Bookmarks in text editors.</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name=\"TextEditor\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"ProjectExplorer\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/bookmarks/bookmarks.pro b/src/plugins/bookmarks/bookmarks.pro
index 9d3ca71865..ec84fb7511 100644
--- a/src/plugins/bookmarks/bookmarks.pro
+++ b/src/plugins/bookmarks/bookmarks.pro
@@ -16,5 +16,3 @@ SOURCES += bookmarksplugin.cpp \
bookmarkmanager.cpp
RESOURCES += bookmarks.qrc
-
-OTHER_FILES += Bookmarks.pluginspec
diff --git a/src/plugins/bookmarks/bookmarksplugin.cpp b/src/plugins/bookmarks/bookmarksplugin.cpp
index c84e68df69..25cc7792c0 100644
--- a/src/plugins/bookmarks/bookmarksplugin.cpp
+++ b/src/plugins/bookmarks/bookmarksplugin.cpp
@@ -42,6 +42,7 @@
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/command.h>
+#include <coreplugin/uniqueidmanager.h>
#include <extensionsystem/pluginmanager.h>
#include <texteditor/itexteditor.h>
#include <texteditor/texteditorconstants.h>
diff --git a/src/plugins/classview/ClassView.pluginspec b/src/plugins/classview/ClassView.pluginspec
deleted file mode 100644
index abf5ccc953..0000000000
--- a/src/plugins/classview/ClassView.pluginspec
+++ /dev/null
@@ -1,22 +0,0 @@
-<plugin name="ClassView" version="2.0.95" compatVersion="2.0.95">
- <vendor>Nokia Corporation</vendor>
- <copyright>(C) 2010 Denis Mingulov</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>
- <category>C++</category>
- <description>Class View component.</description>
- <url>http://qt.nokia.com</url>
- <dependencyList>
- <dependency name="Core" version="2.0.95"/>
- <dependency name="CppTools" version="2.0.95"/>
- <dependency name="ProjectExplorer" version="2.0.95"/>
- <dependency name="TextEditor" version="2.0.95"/>
- </dependencyList>
-</plugin>
diff --git a/src/plugins/classview/ClassView.pluginspec.in b/src/plugins/classview/ClassView.pluginspec.in
new file mode 100644
index 0000000000..1eab2b9ab4
--- /dev/null
+++ b/src/plugins/classview/ClassView.pluginspec.in
@@ -0,0 +1,22 @@
+<plugin name=\"ClassView\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2010 Denis Mingulov</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>
+ <category>C++</category>
+ <description>Class View component.</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"CppTools\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"ProjectExplorer\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"TextEditor\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/classview/classview.pro b/src/plugins/classview/classview.pro
index 944ca84927..145bbc227f 100644
--- a/src/plugins/classview/classview.pro
+++ b/src/plugins/classview/classview.pro
@@ -28,9 +28,6 @@ SOURCES += \
classviewutils.cpp \
classviewtreeitemmodel.cpp
-OTHER_FILES += \
- ClassView.pluginspec
-
FORMS += \
classviewnavigationwidget.ui
diff --git a/src/plugins/classview/classviewmanager.cpp b/src/plugins/classview/classviewmanager.cpp
index 3c555b14ed..9c5e96ce24 100644
--- a/src/plugins/classview/classviewmanager.cpp
+++ b/src/plugins/classview/classviewmanager.cpp
@@ -150,7 +150,7 @@ void Manager::initialize()
// internal manager state is changed
connect(this, SIGNAL(stateChanged(bool)), SLOT(onStateChanged(bool)), Qt::QueuedConnection);
- // connections to enable/disbale navi widget factory
+ // connections to enable/disable navi widget factory
ProjectExplorer::SessionManager *sessionManager =
ProjectExplorer::ProjectExplorerPlugin::instance()->session();
connect(sessionManager, SIGNAL(projectAdded(ProjectExplorer::Project*)),
diff --git a/src/plugins/classview/classviewparser.cpp b/src/plugins/classview/classviewparser.cpp
index c75a829ab1..ce48dee7fe 100644
--- a/src/plugins/classview/classviewparser.cpp
+++ b/src/plugins/classview/classviewparser.cpp
@@ -577,7 +577,7 @@ void Parser::resetDataToCurrentState()
void Parser::onResetDataDone()
{
- // internal data is resetted, update a tree and send it back
+ // internal data is reset, update a tree and send it back
emitCurrentTree();
}
diff --git a/src/plugins/classview/classviewparsertreeitem.cpp b/src/plugins/classview/classviewparsertreeitem.cpp
index 80f416ef9b..79660de2f9 100644
--- a/src/plugins/classview/classviewparsertreeitem.cpp
+++ b/src/plugins/classview/classviewparsertreeitem.cpp
@@ -62,7 +62,7 @@ struct ParserTreeItemPrivate
//! symbol locations
QSet<SymbolLocation> symbolLocations;
- //! symbol informations
+ //! symbol information
QHash<SymbolInformation, ParserTreeItem::Ptr> symbolInformations;
//! An icon
@@ -194,7 +194,7 @@ void ParserTreeItem::add(const ParserTreeItem::ConstPtr &target)
// add locations
d_ptr->symbolLocations = d_ptr->symbolLocations.unite(target->d_ptr->symbolLocations);
- // add childs
+ // add children
// every target child
QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator cur =
target->d_ptr->symbolInformations.constBegin();
diff --git a/src/plugins/cmakeprojectmanager/CMakeProjectManager.pluginspec b/src/plugins/cmakeprojectmanager/CMakeProjectManager.pluginspec
deleted file mode 100644
index 9dc3b6cd7c..0000000000
--- a/src/plugins/cmakeprojectmanager/CMakeProjectManager.pluginspec
+++ /dev/null
@@ -1,22 +0,0 @@
-<plugin name="CMakeProjectManager" version="2.0.95" compatVersion="2.0.95">
- <vendor>Nokia Corporation</vendor>
- <copyright>(C) 2010 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>
- <category>Build Systems</category>
- <description>CMake support</description>
- <url>http://qt.nokia.com</url>
- <dependencyList>
- <dependency name="TextEditor" version="2.0.95"/>
- <dependency name="ProjectExplorer" version="2.0.95"/>
- <dependency name="CppTools" version="2.0.95"/>
- <dependency name="CppEditor" version="2.0.95"/>
- </dependencyList>
-</plugin>
diff --git a/src/plugins/cmakeprojectmanager/CMakeProjectManager.pluginspec.in b/src/plugins/cmakeprojectmanager/CMakeProjectManager.pluginspec.in
new file mode 100644
index 0000000000..325ab90e23
--- /dev/null
+++ b/src/plugins/cmakeprojectmanager/CMakeProjectManager.pluginspec.in
@@ -0,0 +1,22 @@
+<plugin name=\"CMakeProjectManager\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2010 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>
+ <category>Build Systems</category>
+ <description>CMake support</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name=\"TextEditor\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"ProjectExplorer\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"CppTools\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"Designer\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp
index 56f662b734..79711c1d4a 100644
--- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp
@@ -38,6 +38,7 @@
#include "cmaketarget.h"
#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/toolchain.h>
#include <projectexplorer/buildsteplist.h>
#include <utils/qtcassert.h>
@@ -86,8 +87,6 @@ bool CMakeBuildConfiguration::fromMap(const QVariantMap &map)
m_msvcVersion = map.value(QLatin1String(MSVC_VERSION_KEY)).toString();
m_buildDirectory = map.value(QLatin1String(BUILD_DIRECTORY_KEY), cmakeTarget()->defaultBuildDirectory()).toString();
- environment().set("BUILDDIR", m_buildDirectory);
-
return true;
}
@@ -106,11 +105,11 @@ QString CMakeBuildConfiguration::buildDirectory() const
return m_buildDirectory;
}
-ProjectExplorer::ToolChain::ToolChainType CMakeBuildConfiguration::toolChainType() const
+ProjectExplorer::ToolChainType CMakeBuildConfiguration::toolChainType() const
{
if (m_toolChain)
return m_toolChain->type();
- return ProjectExplorer::ToolChain::UNKNOWN;
+ return ProjectExplorer::ToolChain_UNKNOWN;
}
ProjectExplorer::ToolChain *CMakeBuildConfiguration::toolChain() const
@@ -146,7 +145,6 @@ void CMakeBuildConfiguration::setBuildDirectory(const QString &buildDirectory)
if (m_buildDirectory == buildDirectory)
return;
m_buildDirectory = buildDirectory;
- environment().set("BUILDDIR", m_buildDirectory);
emit buildDirectoryChanged();
emit environmentChanged();
}
@@ -246,7 +244,7 @@ CMakeBuildConfiguration *CMakeBuildConfigurationFactory::create(ProjectExplorer:
MakeStep *cleanMakeStep = new MakeStep(cleanSteps);
cleanSteps->insertStep(0, cleanMakeStep);
- cleanMakeStep->setAdditionalArguments(QStringList() << "clean");
+ cleanMakeStep->setAdditionalArguments("clean");
cleanMakeStep->setClean(true);
CMakeOpenProjectWizard copw(cmtarget->cmakeProject()->projectManager(),
diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h
index d4c772c177..c694f40280 100644
--- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h
+++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h
@@ -35,7 +35,11 @@
#define CMAKEBUILDCONFIGURATION_H
#include <projectexplorer/buildconfiguration.h>
-#include <projectexplorer/toolchain.h>
+#include <projectexplorer/toolchaintype.h>
+
+namespace ProjectExplorer {
+class ToolChain;
+}
namespace CMakeProjectManager {
namespace Internal {
@@ -56,7 +60,7 @@ public:
virtual QString buildDirectory() const;
- ProjectExplorer::ToolChain::ToolChainType toolChainType() const;
+ ProjectExplorer::ToolChainType toolChainType() const;
ProjectExplorer::ToolChain *toolChain() const;
void setBuildDirectory(const QString &buildDirectory);
diff --git a/src/plugins/cmakeprojectmanager/cmakeeditor.cpp b/src/plugins/cmakeprojectmanager/cmakeeditor.cpp
index 48f5236e4a..259cc0af7c 100644
--- a/src/plugins/cmakeprojectmanager/cmakeeditor.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeeditor.cpp
@@ -113,7 +113,8 @@ void CMakeEditor::setFontSettings(const TextEditor::FontSettings &fs)
categories << QLatin1String(TextEditor::Constants::C_LABEL) // variables
<< QLatin1String(TextEditor::Constants::C_LINK) // functions
<< QLatin1String(TextEditor::Constants::C_COMMENT)
- << QLatin1String(TextEditor::Constants::C_STRING);
+ << QLatin1String(TextEditor::Constants::C_STRING)
+ << QLatin1String(TextEditor::Constants::C_VISUAL_WHITESPACE);
}
const QVector<QTextCharFormat> formats = fs.toTextCharFormats(categories);
diff --git a/src/plugins/cmakeprojectmanager/cmakehighlighter.cpp b/src/plugins/cmakeprojectmanager/cmakehighlighter.cpp
index ad94771f6b..d713ddd305 100644
--- a/src/plugins/cmakeprojectmanager/cmakehighlighter.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakehighlighter.cpp
@@ -133,5 +133,7 @@ void CMakeHighlighter::highlightBlock(const QString &text)
} else {
setCurrentBlockState(0);
}
+
+ applyFormatToSpaces(text, m_formats[CMakeVisualWhiteSpaceFormat]);
}
diff --git a/src/plugins/cmakeprojectmanager/cmakehighlighter.h b/src/plugins/cmakeprojectmanager/cmakehighlighter.h
index ad884d9dd6..cf342f2b6e 100644
--- a/src/plugins/cmakeprojectmanager/cmakehighlighter.h
+++ b/src/plugins/cmakeprojectmanager/cmakehighlighter.h
@@ -54,6 +54,7 @@ public:
CMakeFunctionFormat,
CMakeCommentFormat,
CMakeStringFormat,
+ CMakeVisualWhiteSpaceFormat,
NumCMakeFormats
};
diff --git a/src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.cpp b/src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.cpp
index 587d86eace..84d0c3d114 100644
--- a/src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.cpp
@@ -206,12 +206,12 @@ void CMakeOpenProjectWizard::setMsvcVersion(const QString &version)
m_msvcVersion = version;
}
-QStringList CMakeOpenProjectWizard::arguments() const
+QString CMakeOpenProjectWizard::arguments() const
{
return m_arguments;
}
-void CMakeOpenProjectWizard::setArguments(const QStringList &args)
+void CMakeOpenProjectWizard::setArguments(const QString &args)
{
m_arguments = args;
}
@@ -332,6 +332,11 @@ void CMakeRunPage::initWidgets()
pl.setVerticalStretch(1);
m_output->setSizePolicy(pl);
fl->addRow(m_output);
+
+ m_exitCodeLabel = new QLabel(this);
+ m_exitCodeLabel->setVisible(false);
+ fl->addRow(m_exitCodeLabel);
+
setTitle(tr("Run CMake"));
}
@@ -425,7 +430,6 @@ void CMakeRunPage::runCMake()
{
m_runCMake->setEnabled(false);
m_argumentsLineEdit->setEnabled(false);
- QStringList arguments = Utils::Environment::parseCombinedArgString(m_argumentsLineEdit->text());
CMakeManager *cmakeManager = m_cmakeWizard->cmakeManager();
#ifdef Q_OS_WIN
@@ -463,10 +467,11 @@ void CMakeRunPage::runCMake()
m_output->clear();
if (m_cmakeWizard->cmakeManager()->isCMakeExecutableValid()) {
- m_cmakeProcess = new QProcess();
- connect(m_cmakeProcess, SIGNAL(readyRead()), this, SLOT(cmakeReadyRead()));
+ m_cmakeProcess = new Utils::QtcProcess();
+ connect(m_cmakeProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(cmakeReadyReadStandardOutput()));
+ connect(m_cmakeProcess, SIGNAL(readyReadStandardError()), this, SLOT(cmakeReadyReadStandardError()));
connect(m_cmakeProcess, SIGNAL(finished(int)), this, SLOT(cmakeFinished()));
- cmakeManager->createXmlFile(m_cmakeProcess, arguments, m_cmakeWizard->sourceDirectory(), m_buildDirectory, env, generator);
+ cmakeManager->createXmlFile(m_cmakeProcess, m_argumentsLineEdit->text(), m_cmakeWizard->sourceDirectory(), m_buildDirectory, env, generator);
} else {
m_runCMake->setEnabled(true);
m_argumentsLineEdit->setEnabled(true);
@@ -474,20 +479,54 @@ void CMakeRunPage::runCMake()
}
}
-void CMakeRunPage::cmakeReadyRead()
+static QColor mix_colors(QColor a, QColor b)
+{
+ return QColor((a.red() + 2 * b.red()) / 3, (a.green() + 2 * b.green()) / 3,
+ (a.blue() + 2* b.blue()) / 3, (a.alpha() + 2 * b.alpha()) / 3);
+}
+
+void CMakeRunPage::cmakeReadyReadStandardOutput()
+{
+ QTextCursor cursor(m_output->document());
+ QTextCharFormat tf;
+
+ QFont font = m_output->font();
+ tf.setFont(font);
+ tf.setForeground(m_output->palette().color(QPalette::Text));
+
+ cursor.insertText(m_cmakeProcess->readAllStandardOutput(), tf);
+}
+
+void CMakeRunPage::cmakeReadyReadStandardError()
{
- m_output->appendPlainText(m_cmakeProcess->readAll());
+ QTextCursor cursor(m_output->document());
+ QTextCharFormat tf;
+
+ QFont font = m_output->font();
+ QFont boldFont = font;
+ boldFont.setBold(true);
+ tf.setFont(boldFont);
+ tf.setForeground(mix_colors(m_output->palette().color(QPalette::Text), QColor(Qt::red)));
+
+ cursor.insertText(m_cmakeProcess->readAllStandardError(), tf);
}
void CMakeRunPage::cmakeFinished()
{
m_runCMake->setEnabled(true);
m_argumentsLineEdit->setEnabled(true);
+ if (m_cmakeProcess->exitCode() != 0) {
+ m_exitCodeLabel->setVisible(true);
+ m_exitCodeLabel->setText(tr("CMake exited with errors. Please check cmake output."));
+ m_complete = false;
+ } else {
+ m_exitCodeLabel->setVisible(false);
+ m_complete = true;
+ }
m_cmakeProcess->deleteLater();
m_cmakeProcess = 0;
- m_cmakeWizard->setArguments(Utils::Environment::parseCombinedArgString(m_argumentsLineEdit->text()));
+ m_cmakeWizard->setArguments(m_argumentsLineEdit->text());
//TODO Actually test that running cmake was finished, for setting this bool
- m_complete = true;
emit completeChanged();
}
@@ -495,6 +534,7 @@ void CMakeRunPage::cleanupPage()
{
m_output->clear();
m_complete = false;
+ m_exitCodeLabel->setVisible(false);
emit completeChanged();
}
diff --git a/src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.h b/src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.h
index b5b393ce20..e24c626283 100644
--- a/src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.h
+++ b/src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.h
@@ -36,8 +36,8 @@
#include <utils/environment.h>
#include <utils/wizard.h>
+#include <utils/qtcprocess.h>
-#include <QtCore/QProcess>
#include <QtGui/QPushButton>
#include <QtGui/QComboBox>
#include <QtGui/QLineEdit>
@@ -85,8 +85,8 @@ public:
QString sourceDirectory() const;
void setBuildDirectory(const QString &directory);
CMakeManager *cmakeManager() const;
- QStringList arguments() const;
- void setArguments(const QStringList &args);
+ QString arguments() const;
+ void setArguments(const QString &args);
Utils::Environment environment() const;
QString msvcVersion() const;
void setMsvcVersion(const QString &version);
@@ -97,7 +97,7 @@ private:
CMakeManager *m_cmakeManager;
QString m_buildDirectory;
QString m_sourceDirectory;
- QStringList m_arguments;
+ QString m_arguments;
QString m_msvcVersion;
bool m_creatingCbpFiles;
Utils::Environment m_environment;
@@ -137,17 +137,19 @@ public:
private slots:
void runCMake();
void cmakeFinished();
- void cmakeReadyRead();
+ void cmakeReadyReadStandardOutput();
+ void cmakeReadyReadStandardError();
private:
void initWidgets();
CMakeOpenProjectWizard *m_cmakeWizard;
QPlainTextEdit *m_output;
QPushButton *m_runCMake;
- QProcess *m_cmakeProcess;
+ Utils::QtcProcess *m_cmakeProcess;
QLineEdit *m_argumentsLineEdit;
Utils::PathChooser *m_cmakeExecutable;
QComboBox *m_generatorComboBox;
QLabel *m_descriptionLabel;
+ QLabel *m_exitCodeLabel;
bool m_complete;
Mode m_mode;
QString m_buildDirectory;
diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp
index 5d63fbd419..3b3d947cf1 100644
--- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp
@@ -39,14 +39,20 @@
#include "makestep.h"
#include "cmakeopenprojectwizard.h"
#include "cmakebuildconfiguration.h"
+#include "cmakeuicodemodelsupport.h"
#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/buildenvironmentwidget.h>
#include <projectexplorer/buildsteplist.h>
+#include <projectexplorer/buildmanager.h>
+#include <projectexplorer/toolchain.h>
#include <cpptools/cppmodelmanagerinterface.h>
#include <extensionsystem/pluginmanager.h>
+#include <designer/formwindoweditor.h>
#include <utils/qtcassert.h>
#include <coreplugin/icore.h>
+#include <coreplugin/editormanager/editormanager.h>
#include <QtCore/QMap>
#include <QtCore/QDebug>
@@ -78,7 +84,7 @@ CMakeProject::CMakeProject(CMakeManager *manager, const QString &fileName)
m_fileName(fileName),
m_rootNode(new CMakeProjectNode(m_fileName)),
m_insideFileChanged(false),
- m_targetFactory(new CMakeTargetFactory(this))
+ m_lastEditor(0)
{
m_file = new CMakeFile(this, fileName);
@@ -88,6 +94,17 @@ CMakeProject::CMakeProject(CMakeManager *manager, const QString &fileName)
CMakeProject::~CMakeProject()
{
+ // Remove CodeModel support
+ CppTools::CppModelManagerInterface *modelManager
+ = ExtensionSystem::PluginManager::instance()->getObject<CppTools::CppModelManagerInterface>();
+ QMap<QString, CMakeUiCodeModelSupport *>::const_iterator it, end;
+ it = m_uiCodeModelSupport.constBegin();
+ end = m_uiCodeModelSupport.constEnd();
+ for (; it!=end; ++it) {
+ modelManager->removeEditorSupport(it.value());
+ delete it.value();
+ }
+
m_codeModelFuture.cancel();
delete m_rootNode;
}
@@ -233,7 +250,24 @@ bool CMakeProject::parseCMakeLists()
// qDebug()<<"";
// }
+
+ // TOOD this code ain't very pretty ...
+ m_uicCommand.clear();
+ QFile cmakeCache(activeBC->buildDirectory() + "/CMakeCache.txt");
+ cmakeCache.open(QIODevice::ReadOnly);
+ while (!cmakeCache.atEnd()) {
+ QString line = cmakeCache.readLine();
+ if (line.startsWith("QT_UIC_EXECUTABLE")) {
+ if (int pos = line.indexOf('=')) {
+ m_uicCommand = line.mid(pos + 1).trimmed();
+ }
+ break;
+ }
+ }
+ cmakeCache.close();
+
//qDebug()<<"Updating CodeModel";
+ createUiCodeModelSupport();
QStringList allIncludePaths;
QStringList allFrameworkPaths;
@@ -423,11 +457,6 @@ Core::IFile *CMakeProject::file() const
return m_file;
}
-CMakeTargetFactory *CMakeProject::targetFactory() const
-{
- return m_targetFactory;
-}
-
CMakeManager *CMakeProject::projectManager() const
{
return m_manager;
@@ -443,11 +472,6 @@ QList<ProjectExplorer::Project *> CMakeProject::dependsOn()
return QList<Project *>();
}
-ProjectExplorer::BuildConfigWidget *CMakeProject::createConfigWidget()
-{
- return new CMakeBuildSettingsWidget(this);
-}
-
QList<ProjectExplorer::BuildConfigWidget*> CMakeProject::subConfigWidgets()
{
QList<ProjectExplorer::BuildConfigWidget*> list;
@@ -474,7 +498,10 @@ bool CMakeProject::fromMap(const QVariantMap &map)
bool hasUserFile = activeTarget();
if (!hasUserFile) {
- CMakeTarget *t = targetFactory()->create(this, QLatin1String(DEFAULT_CMAKE_TARGET_ID));
+ CMakeTargetFactory *factory =
+ ExtensionSystem::PluginManager::instance()->getObject<CMakeTargetFactory>();
+ CMakeTarget *t = factory->create(this, QLatin1String(DEFAULT_CMAKE_TARGET_ID));
+
Q_ASSERT(t);
Q_ASSERT(t->activeBuildConfiguration());
@@ -537,6 +564,16 @@ bool CMakeProject::fromMap(const QVariantMap &map)
connect(t, SIGNAL(environmentChanged()),
this, SLOT(changeEnvironment()));
}
+
+ connect(Core::EditorManager::instance(), SIGNAL(editorAboutToClose(Core::IEditor*)),
+ this, SLOT(editorAboutToClose(Core::IEditor*)));
+
+ connect(Core::EditorManager::instance(), SIGNAL(currentEditorChanged(Core::IEditor*)),
+ this, SLOT(editorChanged(Core::IEditor*)));
+
+ connect(ProjectExplorer::ProjectExplorerPlugin::instance()->buildManager(), SIGNAL(buildStateChanged(ProjectExplorer::Project*)),
+ this, SLOT(buildStateChanged(ProjectExplorer::Project*)));
+
return true;
}
@@ -548,6 +585,140 @@ CMakeBuildTarget CMakeProject::buildTargetForTitle(const QString &title)
return CMakeBuildTarget();
}
+QString CMakeProject::uicCommand() const
+{
+ return m_uicCommand;
+}
+
+QString CMakeProject::uiHeaderFile(const QString &uiFile)
+{
+ QDir srcDirRoot = QDir(projectDirectory());
+ QString relativePath = srcDirRoot.relativeFilePath(uiFile);
+ QDir buildDir = QDir(activeTarget()->activeBuildConfiguration()->buildDirectory());
+ QString uiHeaderFilePath = buildDir.absoluteFilePath(relativePath);
+
+ QFileInfo fi(uiHeaderFilePath);
+ uiHeaderFilePath = fi.absolutePath();
+ uiHeaderFilePath += QLatin1String("/ui_");
+ uiHeaderFilePath += fi.completeBaseName();
+ uiHeaderFilePath += QLatin1String(".h");
+ return QDir::cleanPath(uiHeaderFilePath);
+}
+
+void CMakeProject::createUiCodeModelSupport()
+{
+// qDebug()<<"creatUiCodeModelSupport()";
+ CppTools::CppModelManagerInterface *modelManager
+ = ExtensionSystem::PluginManager::instance()->getObject<CppTools::CppModelManagerInterface>();
+
+ // First move all to
+ QMap<QString, CMakeUiCodeModelSupport *> oldCodeModelSupport;
+ oldCodeModelSupport = m_uiCodeModelSupport;
+ m_uiCodeModelSupport.clear();
+
+ // Find all ui files
+ foreach (const QString &uiFile, m_files) {
+ if (uiFile.endsWith(".ui")) {
+ // UI file, not convert to
+ QString uiHeaderFilePath = uiHeaderFile(uiFile);
+ QMap<QString, CMakeUiCodeModelSupport *>::iterator it
+ = oldCodeModelSupport.find(uiFile);
+ if (it != oldCodeModelSupport.end()) {
+ // qDebug()<<"updated old codemodelsupport";
+ CMakeUiCodeModelSupport *cms = it.value();
+ cms->setFileName(uiHeaderFilePath);
+ m_uiCodeModelSupport.insert(it.key(), cms);
+ oldCodeModelSupport.erase(it);
+ } else {
+ // qDebug()<<"adding new codemodelsupport";
+ CMakeUiCodeModelSupport *cms = new CMakeUiCodeModelSupport(modelManager, this, uiFile, uiHeaderFilePath);
+ m_uiCodeModelSupport.insert(uiFile, cms);
+ modelManager->addEditorSupport(cms);
+ }
+ }
+ }
+
+ // Remove old
+ QMap<QString, CMakeUiCodeModelSupport *>::const_iterator it, end;
+ end = oldCodeModelSupport.constEnd();
+ for (it = oldCodeModelSupport.constBegin(); it!=end; ++it) {
+ modelManager->removeEditorSupport(it.value());
+ delete it.value();
+ }
+}
+
+void CMakeProject::updateCodeModelSupportFromEditor(const QString &uiFileName,
+ const QString &contents)
+{
+ const QMap<QString, CMakeUiCodeModelSupport *>::const_iterator it =
+ m_uiCodeModelSupport.constFind(uiFileName);
+ if (it != m_uiCodeModelSupport.constEnd())
+ it.value()->updateFromEditor(contents);
+}
+
+void CMakeProject::editorChanged(Core::IEditor *editor)
+{
+ // Handle old editor
+ Designer::FormWindowEditor *lastFormEditor = qobject_cast<Designer::FormWindowEditor *>(m_lastEditor);
+ if (lastFormEditor) {
+ disconnect(lastFormEditor, SIGNAL(changed()), this, SLOT(uiEditorContentsChanged()));
+
+ if (m_dirtyUic) {
+ const QString contents = lastFormEditor->contents();
+ updateCodeModelSupportFromEditor(lastFormEditor->file()->fileName(), contents);
+ m_dirtyUic = false;
+ }
+ }
+
+ m_lastEditor = editor;
+
+ // Handle new editor
+ if (Designer::FormWindowEditor *fw = qobject_cast<Designer::FormWindowEditor *>(editor))
+ connect(fw, SIGNAL(changed()), this, SLOT(uiEditorContentsChanged()));
+}
+
+void CMakeProject::editorAboutToClose(Core::IEditor *editor)
+{
+ if (m_lastEditor == editor) {
+ // Oh no our editor is going to be closed
+ // get the content first
+ Designer::FormWindowEditor *lastEditor = qobject_cast<Designer::FormWindowEditor *>(m_lastEditor);
+ if (lastEditor) {
+ disconnect(lastEditor, SIGNAL(changed()), this, SLOT(uiEditorContentsChanged()));
+ if (m_dirtyUic) {
+ const QString contents = lastEditor->contents();
+ updateCodeModelSupportFromEditor(lastEditor->file()->fileName(), contents);
+ m_dirtyUic = false;
+ }
+ }
+ m_lastEditor = 0;
+ }
+}
+
+void CMakeProject::uiEditorContentsChanged()
+{
+ // cast sender, get filename
+ if (m_dirtyUic)
+ return;
+ Designer::FormWindowEditor *fw = qobject_cast<Designer::FormWindowEditor *>(sender());
+ if (!fw)
+ return;
+ m_dirtyUic = true;
+}
+
+void CMakeProject::buildStateChanged(ProjectExplorer::Project *project)
+{
+ if (project == this) {
+ if (!ProjectExplorer::ProjectExplorerPlugin::instance()->buildManager()->isBuilding(this)) {
+ QMap<QString, CMakeUiCodeModelSupport *>::const_iterator it, end;
+ end = m_uiCodeModelSupport.constEnd();
+ for (it = m_uiCodeModelSupport.constBegin(); it != end; ++it) {
+ it.value()->updateFromBuild();
+ }
+ }
+ }
+}
+
// CMakeFile
CMakeFile::CMakeFile(CMakeProject *parent, QString fileName)
@@ -620,8 +791,8 @@ void CMakeFile::reload(ReloadFlag flag, ChangeType type)
Q_UNUSED(type)
}
-CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeProject *project)
- : m_project(project), m_buildConfiguration(0)
+CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeTarget *target)
+ : m_target(target), m_buildConfiguration(0)
{
QFormLayout *fl = new QFormLayout(this);
fl->setContentsMargins(20, -1, 0, -1);
@@ -657,7 +828,7 @@ void CMakeBuildSettingsWidget::init(BuildConfiguration *bc)
{
m_buildConfiguration = static_cast<CMakeBuildConfiguration *>(bc);
m_pathLineEdit->setText(m_buildConfiguration->buildDirectory());
- if (m_buildConfiguration->buildDirectory() == m_project->projectDirectory())
+ if (m_buildConfiguration->buildDirectory() == m_target->cmakeProject()->projectDirectory())
m_changeButton->setEnabled(false);
else
m_changeButton->setEnabled(true);
@@ -665,12 +836,13 @@ void CMakeBuildSettingsWidget::init(BuildConfiguration *bc)
void CMakeBuildSettingsWidget::openChangeBuildDirectoryDialog()
{
- CMakeOpenProjectWizard copw(m_project->projectManager(),
- m_project->projectDirectory(),
+ CMakeProject *project = m_target->cmakeProject();
+ CMakeOpenProjectWizard copw(project->projectManager(),
+ project->projectDirectory(),
m_buildConfiguration->buildDirectory(),
m_buildConfiguration->environment());
if (copw.exec() == QDialog::Accepted) {
- m_project->changeBuildDirectory(m_buildConfiguration, copw.buildDirectory());
+ project->changeBuildDirectory(m_buildConfiguration, copw.buildDirectory());
m_pathLineEdit->setText(m_buildConfiguration->buildDirectory());
}
}
@@ -678,13 +850,14 @@ void CMakeBuildSettingsWidget::openChangeBuildDirectoryDialog()
void CMakeBuildSettingsWidget::runCMake()
{
// TODO skip build directory
- CMakeOpenProjectWizard copw(m_project->projectManager(),
- m_project->projectDirectory(),
+ CMakeProject *project = m_target->cmakeProject();
+ CMakeOpenProjectWizard copw(project->projectManager(),
+ project->projectDirectory(),
m_buildConfiguration->buildDirectory(),
CMakeOpenProjectWizard::WantToUpdate,
m_buildConfiguration->environment());
if (copw.exec() == QDialog::Accepted) {
- m_project->parseCMakeLists();
+ project->parseCMakeLists();
}
}
diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.h b/src/plugins/cmakeprojectmanager/cmakeproject.h
index 1c71386532..e787336123 100644
--- a/src/plugins/cmakeprojectmanager/cmakeproject.h
+++ b/src/plugins/cmakeprojectmanager/cmakeproject.h
@@ -43,10 +43,10 @@
#include <projectexplorer/project.h>
#include <projectexplorer/projectnodes.h>
#include <projectexplorer/buildstep.h>
-#include <projectexplorer/toolchain.h>
#include <projectexplorer/filewatcher.h>
#include <projectexplorer/buildconfiguration.h>
#include <coreplugin/ifile.h>
+#include <coreplugin/editormanager/ieditor.h>
#include <QtCore/QXmlStreamReader>
#include <QtGui/QPushButton>
@@ -57,6 +57,7 @@ namespace Internal {
class CMakeFile;
class CMakeBuildSettingsWidget;
+class CMakeUiCodeModelSupport;
struct CMakeBuildTarget
{
@@ -81,14 +82,12 @@ public:
QString displayName() const;
QString id() const;
Core::IFile *file() const;
- CMakeTargetFactory *targetFactory() const;
CMakeManager *projectManager() const;
CMakeTarget *activeTarget() const;
QList<ProjectExplorer::Project *> dependsOn(); //NBS TODO implement dependsOn
- ProjectExplorer::BuildConfigWidget *createConfigWidget();
QList<ProjectExplorer::BuildConfigWidget*> subConfigWidgets();
ProjectExplorer::ProjectNode *rootProjectNode() const;
@@ -104,6 +103,8 @@ public:
bool parseCMakeLists();
+ QString uicCommand() const;
+
signals:
/// emitted after parsing
void buildTargetsChanged();
@@ -119,15 +120,23 @@ private slots:
void changeActiveBuildConfiguration(ProjectExplorer::BuildConfiguration*);
void targetAdded(ProjectExplorer::Target *);
+ void editorChanged(Core::IEditor *editor);
+ void editorAboutToClose(Core::IEditor *editor);
+ void uiEditorContentsChanged();
+ void buildStateChanged(ProjectExplorer::Project *project);
private:
void buildTree(CMakeProjectNode *rootNode, QList<ProjectExplorer::FileNode *> list);
void gatherFileNodes(ProjectExplorer::FolderNode *parent, QList<ProjectExplorer::FileNode *> &list);
ProjectExplorer::FolderNode *findOrCreateFolder(CMakeProjectNode *rootNode, QString directory);
+ void updateCodeModelSupportFromEditor(const QString &uiFileName, const QString &contents);
+ void createUiCodeModelSupport();
+ QString uiHeaderFile(const QString &uiFile);
CMakeManager *m_manager;
QString m_fileName;
CMakeFile *m_file;
QString m_projectName;
+ QString m_uicCommand;
// TODO probably need a CMake specific node structure
CMakeProjectNode *m_rootNode;
@@ -136,8 +145,11 @@ private:
ProjectExplorer::FileWatcher *m_watcher;
bool m_insideFileChanged;
QSet<QString> m_watchedFiles;
- CMakeTargetFactory *m_targetFactory;
QFuture<void> m_codeModelFuture;
+
+ QMap<QString, CMakeUiCodeModelSupport *> m_uiCodeModelSupport;
+ Core::IEditor *m_lastEditor;
+ bool m_dirtyUic;
};
class CMakeCbpParser : public QXmlStreamReader
@@ -211,7 +223,7 @@ class CMakeBuildSettingsWidget : public ProjectExplorer::BuildConfigWidget
{
Q_OBJECT
public:
- explicit CMakeBuildSettingsWidget(CMakeProject *project);
+ explicit CMakeBuildSettingsWidget(CMakeTarget *target);
QString displayName() const;
// This is called to set up the config widget before showing it
@@ -221,7 +233,7 @@ private slots:
void openChangeBuildDirectoryDialog();
void runCMake();
private:
- CMakeProject *m_project;
+ CMakeTarget *m_target;
QLineEdit *m_pathLineEdit;
QPushButton *m_changeButton;
CMakeBuildConfiguration *m_buildConfiguration;
diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp
index f956ca25fd..f401732ebd 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp
@@ -36,6 +36,7 @@
#include "cmakeproject.h"
#include <utils/synchronousprocess.h>
+#include <utils/qtcprocess.h>
#include <coreplugin/icore.h>
#include <coreplugin/uniqueidmanager.h>
@@ -106,7 +107,7 @@ bool CMakeManager::hasCodeBlocksMsvcGenerator() const
// we probably want the process instead of this function
// cmakeproject then could even run the cmake process in the background, adding the files afterwards
// sounds like a plan
-void CMakeManager::createXmlFile(QProcess *proc, const QStringList &arguments,
+void CMakeManager::createXmlFile(Utils::QtcProcess *proc, const QString &arguments,
const QString &sourceDirectory, const QDir &buildDirectory,
const Utils::Environment &env, const QString &generator)
{
@@ -121,12 +122,16 @@ void CMakeManager::createXmlFile(QProcess *proc, const QStringList &arguments,
QString buildDirectoryPath = buildDirectory.absolutePath();
buildDirectory.mkpath(buildDirectoryPath);
proc->setWorkingDirectory(buildDirectoryPath);
- proc->setProcessChannelMode(QProcess::MergedChannels);
- proc->setEnvironment(env.toStringList());
+ proc->setEnvironment(env);
const QString srcdir = buildDirectory.exists(QLatin1String("CMakeCache.txt")) ?
QString(QLatin1Char('.')) : sourceDirectory;
- proc->start(cmakeExecutable(), QStringList() << srcdir << arguments << generator);
+ QString args;
+ Utils::QtcProcess::addArg(&args, srcdir);
+ Utils::QtcProcess::addArgs(&args, arguments);
+ Utils::QtcProcess::addArg(&args, generator);
+ proc->setCommand(cmakeExecutable(), args);
+ proc->start();
}
QString CMakeManager::findCbpFile(const QDir &directory)
@@ -314,6 +319,8 @@ void CMakeSettingsPage::saveSettings() const
void CMakeSettingsPage::apply()
{
+ if (!m_pathchooser) // page was never shown
+ return;
if (m_cmakeExecutable == m_pathchooser->path())
return;
m_cmakeExecutable = m_pathchooser->path();
diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h
index 7838df11aa..82b0ec327e 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h
+++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h
@@ -34,10 +34,13 @@
#ifndef CMAKEPROJECTMANAGER_H
#define CMAKEPROJECTMANAGER_H
-#include <coreplugin/dialogs/ioptionspage.h>
#include <projectexplorer/iprojectmanager.h>
+#include <coreplugin/dialogs/ioptionspage.h>
+#include <coreplugin/icontext.h>
+
#include <utils/environment.h>
#include <utils/pathchooser.h>
+
#include <QtCore/QFuture>
#include <QtCore/QStringList>
#include <QtCore/QDir>
@@ -45,6 +48,10 @@
QT_FORWARD_DECLARE_CLASS(QProcess)
QT_FORWARD_DECLARE_CLASS(QLabel)
+namespace Utils {
+class QtcProcess;
+}
+
namespace CMakeProjectManager {
namespace Internal {
@@ -67,8 +74,8 @@ public:
void setCMakeExecutable(const QString &executable);
- void createXmlFile(QProcess *process,
- const QStringList &arguments,
+ void createXmlFile(Utils::QtcProcess *process,
+ const QString &arguments,
const QString &sourceDirectory,
const QDir &buildDirectory,
const Utils::Environment &env,
diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.pro b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.pro
index 8a94e4a77a..370330860e 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.pro
+++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.pro
@@ -14,7 +14,8 @@ HEADERS = cmakeproject.h \
cmakebuildconfiguration.h \
cmakeeditorfactory.h \
cmakeeditor.h \
- cmakehighlighter.h
+ cmakehighlighter.h \
+ cmakeuicodemodelsupport.h
SOURCES = cmakeproject.cpp \
cmakeprojectplugin.cpp \
cmakeprojectmanager.cpp \
@@ -26,9 +27,9 @@ SOURCES = cmakeproject.cpp \
cmakebuildconfiguration.cpp \
cmakeeditorfactory.cpp \
cmakeeditor.cpp \
- cmakehighlighter.cpp
+ cmakehighlighter.cpp \
+ cmakeuicodemodelsupport.cpp
RESOURCES += cmakeproject.qrc
FORMS +=
-OTHER_FILES += CMakeProjectManager.pluginspec \
- CMakeProject.mimetypes.xml
+OTHER_FILES += CMakeProject.mimetypes.xml
diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager_dependencies.pri b/src/plugins/cmakeprojectmanager/cmakeprojectmanager_dependencies.pri
index 80118ad122..7785312ea5 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager_dependencies.pri
+++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager_dependencies.pri
@@ -1,4 +1,4 @@
include(../../plugins/projectexplorer/projectexplorer.pri)
include(../../plugins/cpptools/cpptools.pri)
-include(../../plugins/cppeditor/cppeditor.pri)
include(../../plugins/texteditor/texteditor.pri)
+include(../../plugins/designer/designer.pri)
diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp
index d300b3c428..d7b5c5ac93 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp
@@ -37,6 +37,7 @@
#include "cmakeeditorfactory.h"
#include "makestep.h"
#include "cmakeprojectconstants.h"
+#include "cmaketarget.h"
#include <coreplugin/icore.h>
#include <coreplugin/mimedatabase.h>
@@ -71,6 +72,7 @@ bool CMakeProjectPlugin::initialize(const QStringList & /*arguments*/, QString *
= new TextEditor::TextEditorActionHandler(CMakeProjectManager::Constants::C_CMAKEEDITOR);
addAutoReleasedObject(new CMakeEditorFactory(manager, editorHandler));
+ addAutoReleasedObject(new CMakeTargetFactory);
return true;
}
diff --git a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp
index b96f69a3c8..7512408ab0 100644
--- a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp
@@ -56,8 +56,6 @@ namespace {
const char * const CMAKE_RC_ID("CMakeProjectManager.CMakeRunConfiguration");
const char * const CMAKE_RC_PREFIX("CMakeProjectManager.CMakeRunConfiguration.");
-const char * const TARGET_KEY("CMakeProjectManager.CMakeRunConfiguration.Target");
-const char * const WORKING_DIRECTORY_KEY("CMakeProjectManager.CMakeRunConfiguration.WorkingDirectory");
const char * const USER_WORKING_DIRECTORY_KEY("CMakeProjectManager.CMakeRunConfiguration.UserWorkingDirectory");
const char * const USE_TERMINAL_KEY("CMakeProjectManager.CMakeRunConfiguration.UseTerminal");
const char * const TITLE_KEY("CMakeProjectManager.CMakeRunConfiguation.Title");
@@ -137,7 +135,8 @@ ProjectExplorer::LocalApplicationRunConfiguration::RunMode CMakeRunConfiguration
QString CMakeRunConfiguration::workingDirectory() const
{
- return environment().expandVariables(baseWorkingDirectory());
+ return QDir::cleanPath(environment().expandVariables(
+ Utils::expandMacros(baseWorkingDirectory(), macroExpander())));
}
QString CMakeRunConfiguration::baseWorkingDirectory() const
@@ -147,14 +146,9 @@ QString CMakeRunConfiguration::baseWorkingDirectory() const
return m_workingDirectory;
}
-QStringList CMakeRunConfiguration::commandLineArguments() const
+QString CMakeRunConfiguration::commandLineArguments() const
{
- return environment().expandVariables(baseCommandLineArguments());
-}
-
-QStringList CMakeRunConfiguration::baseCommandLineArguments() const
-{
- return Utils::Environment::parseCombinedArgString(m_arguments);
+ return Utils::QtcProcess::expandMacros(m_arguments, macroExpander());
}
QString CMakeRunConfiguration::title() const
@@ -193,8 +187,6 @@ QVariantMap CMakeRunConfiguration::toMap() const
{
QVariantMap map(ProjectExplorer::LocalApplicationRunConfiguration::toMap());
- map.insert(QLatin1String(TARGET_KEY), m_buildTarget);
- map.insert(QLatin1String(WORKING_DIRECTORY_KEY), m_workingDirectory);
map.insert(QLatin1String(USER_WORKING_DIRECTORY_KEY), m_userWorkingDirectory);
map.insert(QLatin1String(USE_TERMINAL_KEY), m_runMode == Console);
map.insert(QLatin1String(TITLE_KEY), m_title);
@@ -207,8 +199,6 @@ QVariantMap CMakeRunConfiguration::toMap() const
bool CMakeRunConfiguration::fromMap(const QVariantMap &map)
{
- m_buildTarget = map.value(QLatin1String(TARGET_KEY)).toString();
- m_workingDirectory = map.value(QLatin1String(WORKING_DIRECTORY_KEY)).toString();
m_userWorkingDirectory = map.value(QLatin1String(USER_WORKING_DIRECTORY_KEY)).toString();
m_runMode = map.value(QLatin1String(USE_TERMINAL_KEY)).toBool() ? Console : Gui;
m_title = map.value(QLatin1String(TITLE_KEY)).toString();
@@ -309,11 +299,11 @@ void CMakeRunConfiguration::setUserEnvironmentChanges(const QList<Utils::Environ
}
}
-ProjectExplorer::ToolChain::ToolChainType CMakeRunConfiguration::toolChainType() const
+ProjectExplorer::ToolChainType CMakeRunConfiguration::toolChainType() const
{
CMakeBuildConfiguration *bc = activeBuildConfiguration();
if (!bc)
- return ProjectExplorer::ToolChain::UNKNOWN;
+ return ProjectExplorer::ToolChain_UNKNOWN;
return bc->toolChainType();
}
@@ -335,12 +325,11 @@ bool CMakeRunConfiguration::isEnabled(ProjectExplorer::BuildConfiguration *bc) c
CMakeRunConfigurationWidget::CMakeRunConfigurationWidget(CMakeRunConfiguration *cmakeRunConfiguration, QWidget *parent)
: QWidget(parent), m_ignoreChange(false), m_cmakeRunConfiguration(cmakeRunConfiguration)
{
-
QFormLayout *fl = new QFormLayout();
fl->setMargin(0);
fl->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
QLineEdit *argumentsLineEdit = new QLineEdit();
- argumentsLineEdit->setText(Utils::Environment::joinArgumentList(cmakeRunConfiguration->baseCommandLineArguments()));
+ argumentsLineEdit->setText(cmakeRunConfiguration->commandLineArguments());
connect(argumentsLineEdit, SIGNAL(textChanged(QString)),
this, SLOT(setArguments(QString)));
fl->addRow(tr("Arguments:"), argumentsLineEdit);
@@ -442,6 +431,7 @@ CMakeRunConfigurationWidget::CMakeRunConfigurationWidget(CMakeRunConfiguration *
connect(m_cmakeRunConfiguration, SIGNAL(userEnvironmentChangesChanged(QList<Utils::EnvironmentItem>)),
this, SLOT(userEnvironmentChangesChanged()));
+ setEnabled(m_cmakeRunConfiguration->isEnabled());
}
void CMakeRunConfigurationWidget::setWorkingDirectory()
diff --git a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.h b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.h
index 7aed18c8b9..cd7d18c05f 100644
--- a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.h
+++ b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.h
@@ -72,7 +72,7 @@ public:
QString executable() const;
RunMode runMode() const;
QString workingDirectory() const;
- QStringList commandLineArguments() const;
+ QString commandLineArguments() const;
Utils::Environment environment() const;
QWidget *createConfigurationWidget();
@@ -83,7 +83,7 @@ public:
QString dumperLibrary() const;
QStringList dumperLibraryLocations() const;
- ProjectExplorer::ToolChain::ToolChainType toolChainType() const;
+ ProjectExplorer::ToolChainType toolChainType() const;
QVariantMap toMap() const;
@@ -108,7 +108,6 @@ protected:
private:
void setUserWorkingDirectory(const QString &workingDirectory);
QString baseWorkingDirectory() const;
- QStringList baseCommandLineArguments() const;
void ctor();
enum BaseEnvironmentBase { CleanEnvironmentBase = 0,
diff --git a/src/plugins/cmakeprojectmanager/cmaketarget.cpp b/src/plugins/cmakeprojectmanager/cmaketarget.cpp
index bbd8509924..045cbb70c0 100644
--- a/src/plugins/cmakeprojectmanager/cmaketarget.cpp
+++ b/src/plugins/cmakeprojectmanager/cmaketarget.cpp
@@ -82,6 +82,16 @@ CMakeProject *CMakeTarget::cmakeProject() const
return static_cast<CMakeProject *>(project());
}
+ProjectExplorer::BuildConfigWidget *CMakeTarget::createConfigWidget()
+{
+ return new CMakeBuildSettingsWidget(this);
+}
+
+bool CMakeTargetFactory::supportsTargetId(const QString &id) const
+{
+ return id == DEFAULT_CMAKE_TARGET_ID;
+}
+
CMakeBuildConfiguration *CMakeTarget::activeBuildConfiguration() const
{
return static_cast<CMakeBuildConfiguration *>(Target::activeBuildConfiguration());
@@ -213,7 +223,7 @@ CMakeTarget *CMakeTargetFactory::create(ProjectExplorer::Project *parent, const
MakeStep *cleanMakeStep = new MakeStep(cleanSteps);
cleanSteps->insertStep(0, cleanMakeStep);
- cleanMakeStep->setAdditionalArguments(QStringList() << "clean");
+ cleanMakeStep->setAdditionalArguments("clean");
cleanMakeStep->setClean(true);
t->addBuildConfiguration(bc);
diff --git a/src/plugins/cmakeprojectmanager/cmaketarget.h b/src/plugins/cmakeprojectmanager/cmaketarget.h
index d917b11ff0..f8f73b4bca 100644
--- a/src/plugins/cmakeprojectmanager/cmaketarget.h
+++ b/src/plugins/cmakeprojectmanager/cmaketarget.h
@@ -58,6 +58,8 @@ public:
CMakeTarget(CMakeProject *parent);
~CMakeTarget();
+ ProjectExplorer::BuildConfigWidget *createConfigWidget();
+
CMakeProject *cmakeProject() const;
CMakeBuildConfiguration *activeBuildConfiguration() const;
@@ -85,6 +87,8 @@ public:
CMakeTargetFactory(QObject *parent = 0);
~CMakeTargetFactory();
+ bool supportsTargetId(const QString &id) const;
+
QStringList availableCreationIds(ProjectExplorer::Project *parent) const;
QString displayNameForId(const QString &id) const;
diff --git a/src/plugins/cmakeprojectmanager/cmakeuicodemodelsupport.cpp b/src/plugins/cmakeprojectmanager/cmakeuicodemodelsupport.cpp
new file mode 100644
index 0000000000..e6736f54ce
--- /dev/null
+++ b/src/plugins/cmakeprojectmanager/cmakeuicodemodelsupport.cpp
@@ -0,0 +1,64 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "cmakeuicodemodelsupport.h"
+#include "cmakeproject.h"
+#include "cmaketarget.h"
+#include "cmakebuildconfiguration.h"
+
+#include <QtCore/QProcess>
+
+using namespace CMakeProjectManager;
+using namespace Internal;
+
+CMakeUiCodeModelSupport::CMakeUiCodeModelSupport(CppTools::CppModelManagerInterface *modelmanager,
+ CMakeProject *project,
+ const QString &source,
+ const QString &uiHeaderFile)
+ : CppTools::UiCodeModelSupport(modelmanager, source, uiHeaderFile),
+ m_project(project)
+{
+
+}
+
+CMakeUiCodeModelSupport::~CMakeUiCodeModelSupport()
+{
+
+}
+
+QString CMakeUiCodeModelSupport::uicCommand() const
+{
+ return m_project->uicCommand();
+}
+
+QStringList CMakeUiCodeModelSupport::environment() const
+{
+ CMakeBuildConfiguration *bc = m_project->activeTarget()->activeBuildConfiguration();
+ return bc->environment().toStringList();
+}
diff --git a/src/plugins/cmakeprojectmanager/cmakeuicodemodelsupport.h b/src/plugins/cmakeprojectmanager/cmakeuicodemodelsupport.h
new file mode 100644
index 0000000000..dc297d39b7
--- /dev/null
+++ b/src/plugins/cmakeprojectmanager/cmakeuicodemodelsupport.h
@@ -0,0 +1,61 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 CMAKEUICODEMODELSUPPORT_H
+#define CMAKEUICODEMODELSUPPORT_H
+
+#include <cpptools/cppmodelmanagerinterface.h>
+#include <cpptools/uicodecompletionsupport.h>
+
+#include <QtCore/QDateTime>
+
+namespace CMakeProjectManager {
+namespace Internal {
+
+class CMakeProject;
+
+class CMakeUiCodeModelSupport : public CppTools::UiCodeModelSupport
+{
+public:
+ CMakeUiCodeModelSupport(CppTools::CppModelManagerInterface *modelmanager,
+ CMakeProject *project,
+ const QString &sourceFile,
+ const QString &uiHeaderFile);
+ ~CMakeUiCodeModelSupport();
+protected:
+ virtual QString uicCommand() const;
+ virtual QStringList environment() const;
+private:
+ CMakeProject *m_project;
+};
+
+
+} // Internal
+} // Qt4ProjectManager
+#endif // CMAKEUICODEMODELSUPPORT_H
diff --git a/src/plugins/cmakeprojectmanager/makestep.cpp b/src/plugins/cmakeprojectmanager/makestep.cpp
index 615de57c59..4ca671fdb6 100644
--- a/src/plugins/cmakeprojectmanager/makestep.cpp
+++ b/src/plugins/cmakeprojectmanager/makestep.cpp
@@ -39,9 +39,12 @@
#include "cmakebuildconfiguration.h"
#include <projectexplorer/buildsteplist.h>
+#include <projectexplorer/toolchain.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/gnumakeparser.h>
+#include <utils/qtcprocess.h>
+
#include <QtGui/QFormLayout>
#include <QtGui/QGroupBox>
#include <QtGui/QCheckBox>
@@ -81,7 +84,7 @@ MakeStep::MakeStep(BuildStepList *bsl, MakeStep *bs) :
m_clean(bs->m_clean),
m_futureInterface(0),
m_buildTargets(bs->m_buildTargets),
- m_additionalArguments(bs->m_buildTargets)
+ m_additionalArguments(Utils::QtcProcess::joinArgs(bs->m_buildTargets))
{
ctor();
}
@@ -120,7 +123,7 @@ bool MakeStep::fromMap(const QVariantMap &map)
{
m_clean = map.value(QLatin1String(CLEAN_KEY)).toBool();
m_buildTargets = map.value(QLatin1String(BUILD_TARGETS_KEY)).toStringList();
- m_additionalArguments = map.value(QLatin1String(ADDITIONAL_ARGUMENTS_KEY)).toStringList();
+ m_additionalArguments = map.value(QLatin1String(ADDITIONAL_ARGUMENTS_KEY)).toString();
return BuildStep::fromMap(map);
}
@@ -130,20 +133,23 @@ bool MakeStep::init()
{
CMakeBuildConfiguration *bc = cmakeBuildConfiguration();
- setEnabled(true);
- setWorkingDirectory(bc->buildDirectory());
-
- setCommand(bc->toolChain()->makeCommand());
+ QString arguments = Utils::QtcProcess::joinArgs(m_buildTargets);
+ Utils::QtcProcess::addArgs(&arguments, additionalArguments());
- QStringList arguments = m_buildTargets;
- arguments << additionalArguments();
- setArguments(arguments);
- setEnvironment(bc->environment());
+ setEnabled(true);
setIgnoreReturnValue(m_clean);
- setOutputParser(new ProjectExplorer::GnuMakeParser(workingDirectory()));
+ ProcessParameters *pp = processParameters();
+ pp->setMacroExpander(bc->macroExpander());
+ pp->setEnvironment(bc->environment());
+ pp->setWorkingDirectory(bc->buildDirectory());
+ pp->setCommand(bc->toolChain()->makeCommand());
+ pp->setArguments(arguments);
+
+ setOutputParser(new ProjectExplorer::GnuMakeParser());
if (bc->toolChain())
appendOutputParser(bc->toolChain()->outputParser());
+ outputParser()->setWorkingDirectory(pp->effectiveWorkingDirectory());
return AbstractProcessStep::init();
}
@@ -194,12 +200,12 @@ void MakeStep::setBuildTarget(const QString &buildTarget, bool on)
m_buildTargets = old;
}
-QStringList MakeStep::additionalArguments() const
+QString MakeStep::additionalArguments() const
{
return m_additionalArguments;
}
-void MakeStep::setAdditionalArguments(const QStringList &list)
+void MakeStep::setAdditionalArguments(const QString &list)
{
m_additionalArguments = list;
}
@@ -242,7 +248,7 @@ MakeStepConfigWidget::MakeStepConfigWidget(MakeStep *makeStep)
void MakeStepConfigWidget::additionalArgumentsEdited()
{
- m_makeStep->setAdditionalArguments(Utils::Environment::parseCombinedArgString(m_additionalArguments->text()));
+ m_makeStep->setAdditionalArguments(m_additionalArguments->text());
updateDetails();
}
@@ -269,7 +275,7 @@ void MakeStepConfigWidget::init()
// and connect again
connect(m_buildTargetsList, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(itemChanged(QListWidgetItem*)));
- m_additionalArguments->setText(Utils::Environment::joinArgumentList(m_makeStep->additionalArguments()));
+ m_additionalArguments->setText(m_makeStep->additionalArguments());
updateDetails();
CMakeProject *pro = m_makeStep->cmakeBuildConfiguration()->cmakeTarget()->cmakeProject();
@@ -293,15 +299,22 @@ void MakeStepConfigWidget::buildTargetsChanged()
void MakeStepConfigWidget::updateDetails()
{
- QStringList arguments = m_makeStep->m_buildTargets;
- arguments << m_makeStep->additionalArguments();
-
CMakeBuildConfiguration *bc = m_makeStep->cmakeBuildConfiguration();
ProjectExplorer::ToolChain *tc = bc->toolChain();
- if (tc)
- m_summaryText = tr("<b>Make:</b> %1 %2").arg(tc->makeCommand(), arguments.join(QString(QLatin1Char(' '))));
- else
+ if (tc) {
+ QString arguments = Utils::QtcProcess::joinArgs(m_makeStep->m_buildTargets);
+ Utils::QtcProcess::addArgs(&arguments, m_makeStep->additionalArguments());
+
+ ProcessParameters param;
+ param.setMacroExpander(bc->macroExpander());
+ param.setEnvironment(bc->environment());
+ param.setWorkingDirectory(bc->buildDirectory());
+ param.setCommand(tc->makeCommand());
+ param.setArguments(arguments);
+ m_summaryText = param.summary(displayName());
+ } else {
m_summaryText = tr("<b>Unknown Toolchain</b>");
+ }
emit updateSummary();
}
diff --git a/src/plugins/cmakeprojectmanager/makestep.h b/src/plugins/cmakeprojectmanager/makestep.h
index 304c51d5b0..a19cb0f5c0 100644
--- a/src/plugins/cmakeprojectmanager/makestep.h
+++ b/src/plugins/cmakeprojectmanager/makestep.h
@@ -69,8 +69,8 @@ public:
virtual bool immutable() const;
bool buildsBuildTarget(const QString &target) const;
void setBuildTarget(const QString &target, bool on);
- QStringList additionalArguments() const;
- void setAdditionalArguments(const QStringList &list);
+ QString additionalArguments() const;
+ void setAdditionalArguments(const QString &list);
void setClean(bool clean);
@@ -92,7 +92,7 @@ private:
QRegExp m_percentProgress;
QFutureInterface<bool> *m_futureInterface;
QStringList m_buildTargets;
- QStringList m_additionalArguments;
+ QString m_additionalArguments;
};
class MakeStepConfigWidget :public ProjectExplorer::BuildStepConfigWidget
diff --git a/src/plugins/coreplugin/Core.pluginspec b/src/plugins/coreplugin/Core.pluginspec
deleted file mode 100644
index 65c7b470b9..0000000000
--- a/src/plugins/coreplugin/Core.pluginspec
+++ /dev/null
@@ -1,19 +0,0 @@
-<plugin name="Core" version="2.0.95" compatVersion="2.0.95">
- <vendor>Nokia Corporation</vendor>
- <copyright>(C) 2010 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>
- <category>Qt Creator</category>
- <description>The core plugin for the Qt IDE.</description>
- <url>http://qt.nokia.com</url>
- <argumentList>
- <argument name="-color" parameter="color">Override selected UI color</argument>
- </argumentList>
-</plugin>
diff --git a/src/plugins/coreplugin/Core.pluginspec.in b/src/plugins/coreplugin/Core.pluginspec.in
new file mode 100644
index 0000000000..64acea4e8a
--- /dev/null
+++ b/src/plugins/coreplugin/Core.pluginspec.in
@@ -0,0 +1,19 @@
+<plugin name=\"Core\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2010 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>
+ <category>Qt Creator</category>
+ <description>The core plugin for the Qt IDE.</description>
+ <url>http://qt.nokia.com</url>
+ <argumentList>
+ <argument name=\"-color\" parameter=\"color\">Override selected UI color</argument>
+ </argumentList>
+</plugin>
diff --git a/src/plugins/coreplugin/actionmanager/actioncontainer.cpp b/src/plugins/coreplugin/actionmanager/actioncontainer.cpp
index 68b1d59c21..f88384e1b2 100644
--- a/src/plugins/coreplugin/actionmanager/actioncontainer.cpp
+++ b/src/plugins/coreplugin/actionmanager/actioncontainer.cpp
@@ -69,26 +69,37 @@ using namespace Core::Internal;
You can define if the menu represented by this action container should automatically disable
or hide whenever it only contains disabled items and submenus by setting the corresponding
- \l{ActionContainer::setEmptyAction()}{EmptyAction}.
+ \l{ActionContainer::setOnAllDisabledBehavior()}{OnAllDisabledBehavior}. The default is
+ ActionContainer::Disable for menus, and ActionContainer::Show for menu bars.
*/
/*!
- \enum ActionContainer::EmptyAction
+ \enum ActionContainer::OnAllDisabledBehavior
Defines what happens when the represented menu is empty or contains only disabled/invisible items.
- \omitvalue EA_Mask
- \value EA_None
- The menu will still be visible and active.
- \value EA_Disable
+ \value Disable
The menu will be visible but disabled.
- \value EA_Hide
+ \value Hide
The menu will not be visible until the state of the subitems change.
+ \value Show
+ The menu will still be visible and active.
*/
/*!
- \fn ActionContainer::setEmptyAction(EmptyAction disableOrHide)
- Defines if the menu represented by this action container should automatically \a disableOrHide
+ \fn ActionContainer::setOnAllDisabledBehavior(OnAllDisabledBehavior behavior)
+ Defines the \a behavior of the menu represented by this action container for the case
whenever it only contains disabled items and submenus.
- \sa ActionContainer::EmptyAction
+ The default is ActionContainer::Disable for menus, and ActionContainer::Show for menu bars.
+ \sa ActionContainer::OnAllDisabledBehavior
+ \sa ActionContainer::onAllDisabledBehavior()
+*/
+
+/*!
+ \fn ActionContainer::onAllDisabledBehavior() const
+ Returns the \a behavior of the menu represented by this action container for the case
+ whenever it only contains disabled items and submenus.
+ The default is ActionContainer::Disable for menus, and ActionContainer::Show for menu bars.
+ \sa ActionContainer::OnAllDisabledBehavior
+ \sa ActionContainer::setOnAllDisabledBehavior()
*/
/*!
@@ -152,19 +163,19 @@ using namespace Core::Internal;
*/
ActionContainerPrivate::ActionContainerPrivate(int id)
- : m_data(0), m_id(id), m_updateRequested(false)
+ : m_onAllDisabledBehavior(Disable), m_id(id), m_updateRequested(false)
{
-
+ scheduleUpdate();
}
-void ActionContainerPrivate::setEmptyAction(EmptyAction ea)
+void ActionContainerPrivate::setOnAllDisabledBehavior(OnAllDisabledBehavior behavior)
{
- m_data = ((m_data & ~EA_Mask) | ea);
+ m_onAllDisabledBehavior = behavior;
}
-bool ActionContainerPrivate::hasEmptyAction(EmptyAction ea) const
+ActionContainer::OnAllDisabledBehavior ActionContainerPrivate::onAllDisabledBehavior() const
{
- return (m_data & EA_Mask) == ea;
+ return m_onAllDisabledBehavior;
}
void ActionContainerPrivate::appendGroup(const QString &group)
@@ -255,6 +266,7 @@ void ActionContainerPrivate::addAction(Command *action, int pos, bool setpos)
m_posmap.insert(pos, action->id());
connect(action, SIGNAL(activeStateChanged()), this, SLOT(scheduleUpdate()));
insertAction(ba, a->action());
+ scheduleUpdate();
}
void ActionContainerPrivate::addMenu(ActionContainer *menu, int pos, bool setpos)
@@ -275,6 +287,7 @@ void ActionContainerPrivate::addMenu(ActionContainer *menu, int pos, bool setpos
m_subContainers.append(menu);
m_posmap.insert(pos, menu->id());
insertMenu(ba, mc->menu());
+ scheduleUpdate();
}
QAction *ActionContainerPrivate::beforeAction(int pos, int *prevKey) const
@@ -345,7 +358,7 @@ void ActionContainerPrivate::update()
MenuActionContainer::MenuActionContainer(int id)
: ActionContainerPrivate(id), m_menu(0)
{
- setEmptyAction(EA_Disable);
+ setOnAllDisabledBehavior(Disable);
}
void MenuActionContainer::setMenu(QMenu *menu)
@@ -385,7 +398,7 @@ CommandLocation MenuActionContainer::location() const
bool MenuActionContainer::updateInternal()
{
- if (hasEmptyAction(EA_None))
+ if (onAllDisabledBehavior() == Show)
return true;
bool hasitems = false;
@@ -421,10 +434,10 @@ bool MenuActionContainer::updateInternal()
}
}
- if (hasEmptyAction(EA_Hide))
- m_menu->setVisible(hasitems);
- else if (hasEmptyAction(EA_Disable))
- m_menu->setEnabled(hasitems);
+ if (onAllDisabledBehavior() == Hide)
+ m_menu->menuAction()->setVisible(hasitems);
+ else if (onAllDisabledBehavior() == Disable)
+ m_menu->menuAction()->setEnabled(hasitems);
return hasitems;
}
@@ -445,7 +458,7 @@ bool MenuActionContainer::canBeAddedToMenu() const
MenuBarActionContainer::MenuBarActionContainer(int id)
: ActionContainerPrivate(id), m_menuBar(0)
{
- setEmptyAction(EA_None);
+ setOnAllDisabledBehavior(Show);
}
void MenuBarActionContainer::setMenuBar(QMenuBar *menuBar)
@@ -470,7 +483,7 @@ void MenuBarActionContainer::insertMenu(QAction *before, QMenu *menu)
bool MenuBarActionContainer::updateInternal()
{
- if (hasEmptyAction(EA_None))
+ if (onAllDisabledBehavior() == Show)
return true;
bool hasitems = false;
@@ -482,9 +495,9 @@ bool MenuBarActionContainer::updateInternal()
}
}
- if (hasEmptyAction(EA_Hide))
+ if (onAllDisabledBehavior() == Hide)
m_menuBar->setVisible(hasitems);
- else if (hasEmptyAction(EA_Disable))
+ else if (onAllDisabledBehavior() == Disable)
m_menuBar->setEnabled(hasitems);
return hasitems;
diff --git a/src/plugins/coreplugin/actionmanager/actioncontainer.h b/src/plugins/coreplugin/actionmanager/actioncontainer.h
index 6cacd3a334..94bd894d95 100644
--- a/src/plugins/coreplugin/actionmanager/actioncontainer.h
+++ b/src/plugins/coreplugin/actionmanager/actioncontainer.h
@@ -51,14 +51,14 @@ class ActionContainer : public QObject
Q_OBJECT
public:
- enum EmptyAction {
- EA_Mask = 0xFF00,
- EA_None = 0x0100,
- EA_Hide = 0x0200,
- EA_Disable = 0x0300
+ enum OnAllDisabledBehavior {
+ Disable,
+ Hide,
+ Show
};
- virtual void setEmptyAction(EmptyAction ea) = 0;
+ virtual void setOnAllDisabledBehavior(OnAllDisabledBehavior behavior) = 0;
+ virtual ActionContainer::OnAllDisabledBehavior onAllDisabledBehavior() const = 0;
virtual int id() const = 0;
diff --git a/src/plugins/coreplugin/actionmanager/actioncontainer_p.h b/src/plugins/coreplugin/actionmanager/actioncontainer_p.h
index 7e499e1c72..02f062ecd6 100644
--- a/src/plugins/coreplugin/actionmanager/actioncontainer_p.h
+++ b/src/plugins/coreplugin/actionmanager/actioncontainer_p.h
@@ -50,8 +50,8 @@ public:
ActionContainerPrivate(int id);
virtual ~ActionContainerPrivate() {}
- void setEmptyAction(EmptyAction ea);
- bool hasEmptyAction(EmptyAction ea) const;
+ void setOnAllDisabledBehavior(OnAllDisabledBehavior behavior);
+ ActionContainer::OnAllDisabledBehavior onAllDisabledBehavior() const;
QAction *insertLocation(const QString &group) const;
void appendGroup(const QString &group);
@@ -88,7 +88,7 @@ private:
int calcPosition(int pos, int prevKey) const;
QList<int> m_groups;
- int m_data;
+ OnAllDisabledBehavior m_onAllDisabledBehavior;
int m_id;
QMap<int, int> m_posmap;
QList<ActionContainer *> m_subContainers;
diff --git a/src/plugins/coreplugin/actionmanager/actionmanager.cpp b/src/plugins/coreplugin/actionmanager/actionmanager.cpp
index 7a12736596..97b7bca13e 100644
--- a/src/plugins/coreplugin/actionmanager/actionmanager.cpp
+++ b/src/plugins/coreplugin/actionmanager/actionmanager.cpp
@@ -39,6 +39,7 @@
#include <coreplugin/coreconstants.h>
#include <coreplugin/icore.h>
+#include <utils/qtcassert.h>
#include <QtCore/QDebug>
#include <QtCore/QSettings>
@@ -202,6 +203,17 @@ namespace {
\sa ActionManager::createMenu()
\sa ActionManager::createMenuBar()
*/
+
+/*!
+ \fn Command *ActionManager::unregisterAction(QAction *action, const QString &id)
+ \brief Removes the knowledge about an \a action under the specified string \a id.
+
+ Usually you do not need to unregister actions. The only valid use case for unregistering
+ actions, is for actions that represent user definable actions, like for the custom Locator
+ filters. If the user removes such an action, it also has to be unregistered from the action manager,
+ to make it disappear from shortcut settings etc.
+*/
+
/*!
\fn ActionManager::ActionManager(QObject *parent)
\internal
@@ -259,11 +271,6 @@ QList<Command *> ActionManagerPrivate::commands() const
return result;
}
-QList<ActionContainerPrivate *> ActionManagerPrivate::containers() const
-{
- return m_idContainerMap.values();
-}
-
bool ActionManagerPrivate::hasContext(int context) const
{
return m_context.contains(context);
@@ -341,6 +348,7 @@ Command *ActionManagerPrivate::registerAction(QAction *action, const Id &id, con
a = static_cast<Action *>(c);
if (a)
a->addOverrideAction(action, context);
+ emit commandListChanged();
return a;
}
@@ -381,15 +389,34 @@ Command *ActionManagerPrivate::registerOverridableAction(QAction *action, const
#endif
a->setAction(baseAction);
m_mainWnd->addAction(baseAction);
- a->setKeySequence(a->keySequence());
- a->setDefaultKeySequence(QKeySequence());
} else if (checkUnique) {
qWarning() << "registerOverridableAction: id" << id << "is already registered.";
}
-
return a;
}
+void ActionManagerPrivate::unregisterAction(QAction *action, const Id &id)
+{
+ Action *a = 0;
+ const int uid = UniqueIDManager::instance()->uniqueIdentifier(id);
+ CommandPrivate *c = m_idCmdMap.value(uid, 0);
+ QTC_ASSERT(c, return);
+ a = qobject_cast<Action *>(c);
+ if (!a) {
+ qWarning() << "registerAction: id" << id << "is registered with a different command type.";
+ return;
+ }
+ a->removeOverrideAction(action);
+ if (a->isEmpty()) {
+ // clean up
+ m_mainWnd->removeAction(a->action());
+ delete a->action();
+ m_idCmdMap.remove(uid);
+ delete a;
+ }
+ emit commandListChanged();
+}
+
Command *ActionManagerPrivate::registerShortcut(QShortcut *shortcut, const Id &id, const Context &context)
{
Shortcut *sc = 0;
@@ -421,9 +448,7 @@ Command *ActionManagerPrivate::registerShortcut(QShortcut *shortcut, const Id &i
else
sc->setContext(context);
- sc->setKeySequence(shortcut->key());
- sc->setDefaultKeySequence(QKeySequence());
-
+ emit commandListChanged();
return sc;
}
diff --git a/src/plugins/coreplugin/actionmanager/actionmanager.h b/src/plugins/coreplugin/actionmanager/actionmanager.h
index 91bec64af3..3242f7d792 100644
--- a/src/plugins/coreplugin/actionmanager/actionmanager.h
+++ b/src/plugins/coreplugin/actionmanager/actionmanager.h
@@ -35,6 +35,8 @@
#define ACTIONMANAGER_H
#include "coreplugin/core_global.h"
+#include "coreplugin/uniqueidmanager.h"
+#include "coreplugin/icontext.h"
#include <QtCore/QObject>
#include <QtCore/QList>
@@ -49,8 +51,6 @@ namespace Core {
class ActionContainer;
class Command;
-class Context;
-class Id;
class CORE_EXPORT ActionManager : public QObject
{
@@ -69,6 +69,11 @@ public:
virtual ActionContainer *actionContainer(const Id &id) const = 0;
virtual QList<Command *> commands() const = 0;
+
+ virtual void unregisterAction(QAction *action, const Id &id) = 0;
+
+signals:
+ void commandListChanged();
};
} // namespace Core
diff --git a/src/plugins/coreplugin/actionmanager/actionmanager_p.h b/src/plugins/coreplugin/actionmanager/actionmanager_p.h
index fffeaf37d3..2f5186a82b 100644
--- a/src/plugins/coreplugin/actionmanager/actionmanager_p.h
+++ b/src/plugins/coreplugin/actionmanager/actionmanager_p.h
@@ -76,7 +76,6 @@ public:
QList<int> defaultGroups() const;
QList<Command *> commands() const;
- QList<ActionContainerPrivate *> containers() const;
bool hasContext(int context) const;
@@ -96,6 +95,7 @@ public:
Core::Command *command(const Id &id) const;
Core::ActionContainer *actionContainer(const Id &id) const;
+ void unregisterAction(QAction *action, const Id &id);
private:
bool hasContext(const Context &context) const;
diff --git a/src/plugins/coreplugin/actionmanager/command.cpp b/src/plugins/coreplugin/actionmanager/command.cpp
index 3c313f5ac3..bfb4c2be54 100644
--- a/src/plugins/coreplugin/actionmanager/command.cpp
+++ b/src/plugins/coreplugin/actionmanager/command.cpp
@@ -204,12 +204,14 @@ using namespace Core::Internal;
*/
CommandPrivate::CommandPrivate(int id)
- : m_attributes(0), m_id(id)
+ : m_attributes(0), m_id(id), m_isKeyInitialized(false)
{
}
void CommandPrivate::setDefaultKeySequence(const QKeySequence &key)
{
+ if (!m_isKeyInitialized)
+ setKeySequence(key);
m_defaultKey = key;
}
@@ -218,6 +220,12 @@ QKeySequence CommandPrivate::defaultKeySequence() const
return m_defaultKey;
}
+void CommandPrivate::setKeySequence(const QKeySequence &key)
+{
+ Q_UNUSED(key)
+ m_isKeyInitialized = true;
+}
+
void CommandPrivate::setDefaultText(const QString &text)
{
m_defaultText = text;
@@ -310,15 +318,9 @@ Core::Context Shortcut::context() const
return m_context;
}
-void Shortcut::setDefaultKeySequence(const QKeySequence &key)
-{
- if (m_shortcut->key().isEmpty())
- setKeySequence(key);
- CommandPrivate::setDefaultKeySequence(key);
-}
-
void Shortcut::setKeySequence(const QKeySequence &key)
{
+ CommandPrivate::setKeySequence(key);
m_shortcut->setKey(key);
emit keySequenceChanged();
}
@@ -409,15 +411,9 @@ QList<CommandLocation> Action::locations() const
return m_locations;
}
-void Action::setDefaultKeySequence(const QKeySequence &key)
-{
- if (m_action->shortcut().isEmpty())
- setKeySequence(key);
- CommandPrivate::setDefaultKeySequence(key);
-}
-
void Action::setKeySequence(const QKeySequence &key)
{
+ CommandPrivate::setKeySequence(key);
m_action->setShortcut(key);
updateToolTipWithKeySequence();
emit keySequenceChanged();
@@ -503,6 +499,20 @@ void Action::addOverrideAction(QAction *action, const Core::Context &context)
}
}
+void Action::removeOverrideAction(QAction *action)
+{
+ QMutableMapIterator<int, QPointer<QAction> > it(m_contextActionMap);
+ while (it.hasNext()) {
+ it.next();
+ if (it.value() == 0) {
+ it.remove();
+ } else if (it.value() == action) {
+ it.remove();
+ }
+ }
+ setCurrentContext(m_context);
+}
+
void Action::actionChanged()
{
if (hasAttribute(CA_UpdateIcon)) {
@@ -542,3 +552,9 @@ void Action::setActive(bool state)
emit activeStateChanged();
}
}
+
+bool Action::isEmpty() const
+{
+ return m_contextActionMap.isEmpty();
+}
+
diff --git a/src/plugins/coreplugin/actionmanager/command_p.h b/src/plugins/coreplugin/actionmanager/command_p.h
index 9a2dd33bc6..1922be731c 100644
--- a/src/plugins/coreplugin/actionmanager/command_p.h
+++ b/src/plugins/coreplugin/actionmanager/command_p.h
@@ -57,6 +57,8 @@ public:
void setDefaultKeySequence(const QKeySequence &key);
QKeySequence defaultKeySequence() const;
+ void setKeySequence(const QKeySequence &key);
+
void setDefaultText(const QString &text);
QString defaultText() const;
@@ -82,6 +84,7 @@ protected:
int m_id;
QKeySequence m_defaultKey;
QString m_defaultText;
+ bool m_isKeyInitialized;
};
class Shortcut : public CommandPrivate
@@ -92,7 +95,6 @@ public:
QString name() const;
- void setDefaultKeySequence(const QKeySequence &key);
void setKeySequence(const QKeySequence &key);
QKeySequence keySequence() const;
@@ -120,7 +122,6 @@ public:
QString name() const;
- void setDefaultKeySequence(const QKeySequence &key);
void setKeySequence(const QKeySequence &key);
QKeySequence keySequence() const;
@@ -133,6 +134,8 @@ public:
bool setCurrentContext(const Context &context);
bool isActive() const;
void addOverrideAction(QAction *action, const Context &context);
+ void removeOverrideAction(QAction *action);
+ bool isEmpty() const;
protected:
void updateToolTipWithKeySequence();
diff --git a/src/plugins/coreplugin/actionmanager/commandmappings.cpp b/src/plugins/coreplugin/actionmanager/commandmappings.cpp
index d6ba978f66..98245c0a17 100644
--- a/src/plugins/coreplugin/actionmanager/commandmappings.cpp
+++ b/src/plugins/coreplugin/actionmanager/commandmappings.cpp
@@ -52,13 +52,13 @@
#include <QtCore/QCoreApplication>
#include <QtDebug>
-Q_DECLARE_METATYPE(Core::Internal::ShortcutItem*);
+Q_DECLARE_METATYPE(Core::Internal::ShortcutItem*)
using namespace Core;
using namespace Core::Internal;
CommandMappings::CommandMappings(QObject *parent)
- : IOptionsPage(parent)
+ : IOptionsPage(parent), m_page(0)
{
}
@@ -144,7 +144,10 @@ void CommandMappings::setTargetHeader(const QString &s)
void CommandMappings::finish()
{
+ if (!m_page) // page was never shown
+ return;
delete m_page;
+ m_page = 0;
}
void CommandMappings::commandChanged(QTreeWidgetItem *current)
@@ -159,6 +162,8 @@ void CommandMappings::commandChanged(QTreeWidgetItem *current)
void CommandMappings::filterChanged(const QString &f)
{
+ if (!m_page)
+ return;
for (int i=0; i<m_page->commandList->topLevelItemCount(); ++i) {
QTreeWidgetItem *item = m_page->commandList->topLevelItem(i);
item->setHidden(filter(f, item));
@@ -204,3 +209,10 @@ void CommandMappings::setModified(QTreeWidgetItem *item , bool modified)
f.setBold(modified);
item->setFont(2, f);
}
+
+QString CommandMappings::filterText() const
+{
+ if (!m_page)
+ return QString();
+ return m_page->filterEdit->text();
+}
diff --git a/src/plugins/coreplugin/actionmanager/commandmappings.h b/src/plugins/coreplugin/actionmanager/commandmappings.h
index bb960ea5cc..7dd2003b53 100644
--- a/src/plugins/coreplugin/actionmanager/commandmappings.h
+++ b/src/plugins/coreplugin/actionmanager/commandmappings.h
@@ -84,6 +84,7 @@ protected:
void setImportExportEnabled(bool enabled);
QTreeWidget *commandList() const;
QLineEdit *targetEdit() const;
+ QString filterText() const;
void setPageTitle(const QString &s);
void setTargetLabelText(const QString &s);
void setTargetEditTitle(const QString &s);
diff --git a/src/plugins/coreplugin/basemode.cpp b/src/plugins/coreplugin/basemode.cpp
deleted file mode 100644
index b46f682786..0000000000
--- a/src/plugins/coreplugin/basemode.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#include "basemode.h"
-
-#include <extensionsystem/pluginmanager.h>
-
-#include <QtGui/QWidget>
-#include <QtGui/QIcon>
-
-using namespace Core;
-
-/*!
- \class BaseMode
- \mainclass
- \inheaderfile basemode.h
- \brief A base implementation of the mode interface IMode.
-
- The BaseMode class can be used directly for most IMode implementations. It has setter functions
- for the mode properties and a convenience constructor.
-
- The ownership of the widget is given to the BaseMode, so when the BaseMode is destroyed it
- deletes its widget.
-
- A typical use case is to do the following in the init method of a plugin:
- \code
- bool MyPlugin::init(QString *error_message)
- {
- [...]
- addObject(new Core::BaseMode("mymode",
- "MyPlugin.ModeId",
- icon,
- 50, // priority
- new MyWidget));
- [...]
- }
- \endcode
-*/
-
-/*!
- \fn BaseMode::BaseMode(QObject *parent)
-
- Creates a mode with empty display name, no icon, lowest priority and no widget. You should use the
- setter functions to give the mode a meaning.
-
- \a parent
-*/
-BaseMode::BaseMode(QObject *parent):
- IMode(parent),
- m_priority(0),
- m_widget(0)
-{
-}
-
-/*!
- \fn BaseMode::~BaseMode()
-*/
-BaseMode::~BaseMode()
-{
- delete m_widget;
-}
diff --git a/src/plugins/coreplugin/basemode.h b/src/plugins/coreplugin/basemode.h
deleted file mode 100644
index 7e438e204e..0000000000
--- a/src/plugins/coreplugin/basemode.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#ifndef BASEMODE_H
-#define BASEMODE_H
-
-#include "core_global.h"
-#include "imode.h"
-
-#include <QtCore/QObject>
-
-#include <QtGui/QIcon>
-
-QT_BEGIN_NAMESPACE
-class QWidget;
-QT_END_NAMESPACE
-
-namespace Core {
-
-class CORE_EXPORT BaseMode
- : public IMode
-{
- Q_OBJECT
-
-public:
- BaseMode(QObject *parent = 0);
- ~BaseMode();
-
- // IMode
- QString displayName() const { return m_displayName; }
- QIcon icon() const { return m_icon; }
- int priority() const { return m_priority; }
- QWidget *widget() { return m_widget; }
- QString id() const { return m_id; }
- QString type() const { return m_type; }
- Context context() const { return m_context; }
- QString contextHelpId() const { return m_helpId; }
-
- void setDisplayName(const QString &name) { m_displayName = name; }
- void setIcon(const QIcon &icon) { m_icon = icon; }
- void setPriority(int priority) { m_priority = priority; }
- void setWidget(QWidget *widget) { m_widget = widget; }
- void setId(const QString &id) { m_id = id; }
- void setType(const QString &type) { m_type = type; }
- void setContextHelpId(const QString &helpId) { m_helpId = helpId; }
- void setContext(const Context &context) { m_context = context; }
-
-private:
- QString m_displayName;
- QIcon m_icon;
- int m_priority;
- QWidget *m_widget;
- QString m_id;
- QString m_type;
- QString m_helpId;
- Context m_context;
-};
-
-} // namespace Core
-
-#endif // BASEMODE_H
diff --git a/src/plugins/coreplugin/coreconstants.h b/src/plugins/coreplugin/coreconstants.h
index fee30ba7a5..45f575cf0f 100644
--- a/src/plugins/coreplugin/coreconstants.h
+++ b/src/plugins/coreplugin/coreconstants.h
@@ -39,9 +39,7 @@
namespace Core {
namespace Constants {
-#define IDE_VERSION_MAJOR 2
-#define IDE_VERSION_MINOR 0
-#define IDE_VERSION_RELEASE 95
+#include "ide_version.h"
#define STRINGIFY_INTERNAL(x) #x
#define STRINGIFY(x) STRINGIFY_INTERNAL(x)
@@ -253,6 +251,8 @@ const char * const SETTINGS_CATEGORY_CORE_ICON = ":/core/images/category_core.pn
const char * const SETTINGS_TR_CATEGORY_CORE = QT_TRANSLATE_NOOP("Core", "Environment");
const char * const SETTINGS_ID_ENVIRONMENT = "A.General";
+const char * const SETTINGS_DEFAULTTEXTENCODING = "General/DefaultFileEncoding";
+
const char * const ALL_FILES_FILTER = QT_TRANSLATE_NOOP("Core", "All Files (*)");
const int TARGET_ICON_SIZE = 32;
diff --git a/src/plugins/coreplugin/coreimpl.cpp b/src/plugins/coreplugin/coreimpl.cpp
index 5a21508be7..b6e1f8c43a 100644
--- a/src/plugins/coreplugin/coreimpl.cpp
+++ b/src/plugins/coreplugin/coreimpl.cpp
@@ -36,7 +36,6 @@
#include <QtCore/QDir>
#include <QtCore/QCoreApplication>
-#include <QtCore/QSettings>
#include <QtCore/QDebug>
#include <QtGui/QStatusBar>
@@ -134,7 +133,7 @@ VariableManager *CoreImpl::variableManager() const
return m_mainwindow->variableManager();
}
-VCSManager *CoreImpl::vcsManager() const
+VcsManager *CoreImpl::vcsManager() const
{
return m_mainwindow->vcsManager();
}
@@ -169,6 +168,11 @@ QPrinter *CoreImpl::printer() const
return m_mainwindow->printer();
}
+QString CoreImpl::userInterfaceLanguage() const
+{
+ return qApp->property("qtc_locale").toString();
+}
+
#ifdef Q_OS_MAC
# define SHARE_PATH "/../Resources"
#else
diff --git a/src/plugins/coreplugin/coreimpl.h b/src/plugins/coreplugin/coreimpl.h
index 57c8a81d8d..775f5b86c1 100644
--- a/src/plugins/coreplugin/coreimpl.h
+++ b/src/plugins/coreplugin/coreimpl.h
@@ -68,7 +68,7 @@ public:
ProgressManager *progressManager() const;
ScriptManager *scriptManager() const;
VariableManager *variableManager() const;
- VCSManager *vcsManager() const;
+ VcsManager *vcsManager() const;
ModeManager *modeManager() const;
MimeDatabase *mimeDatabase() const;
HelpManager *helpManager() const;
@@ -76,6 +76,7 @@ public:
QSettings *settings(QSettings::Scope scope = QSettings::UserScope) const;
SettingsDatabase *settingsDatabase() const;
QPrinter *printer() const;
+ QString userInterfaceLanguage() const;
QString resourcePath() const;
QString userResourcePath() const;
diff --git a/src/plugins/coreplugin/coreplugin.pri b/src/plugins/coreplugin/coreplugin.pri
index fc5fc7aae6..7db79341c3 100644
--- a/src/plugins/coreplugin/coreplugin.pri
+++ b/src/plugins/coreplugin/coreplugin.pri
@@ -1,2 +1,5 @@
include(coreplugin_dependencies.pri)
-LIBS *= -l$$qtLibraryTarget(Core)
+LIBS *= -l$$qtLibraryName(Core)
+# for ide_version.h
+INCLUDEPATH *= $$IDE_BUILD_TREE/src/plugins/coreplugin
+DEPENDPATH *= $$IDE_BUILD_TREE/src/plugins/coreplugin
diff --git a/src/plugins/coreplugin/coreplugin.pro b/src/plugins/coreplugin/coreplugin.pro
index d5c54c3908..dd416a7cc0 100644
--- a/src/plugins/coreplugin/coreplugin.pro
+++ b/src/plugins/coreplugin/coreplugin.pro
@@ -56,8 +56,6 @@ SOURCES += mainwindow.cpp \
progressmanager/progressbar.cpp \
progressmanager/futureprogress.cpp \
scriptmanager/scriptmanager.cpp \
- scriptmanager/qworkbench_wrapper.cpp \
- basemode.cpp \
statusbarwidget.cpp \
coreplugin.cpp \
variablemanager.cpp \
@@ -105,6 +103,7 @@ SOURCES += mainwindow.cpp \
ssh/sftpincomingpacket.cpp \
ssh/sftpdefs.cpp \
ssh/sftpchannel.cpp \
+ ssh/sshremoteprocessrunner.cpp \
outputpanemanager.cpp \
navigationsubwidget.cpp \
sidebarwidget.cpp \
@@ -164,11 +163,9 @@ HEADERS += mainwindow.h \
icorelistener.h \
versiondialog.h \
scriptmanager/metatypedeclarations.h \
- scriptmanager/qworkbench_wrapper.h \
scriptmanager/scriptmanager.h \
scriptmanager/scriptmanager_p.h \
core_global.h \
- basemode.h \
statusbarwidget.h \
coreplugin.h \
variablemanager.h \
@@ -217,6 +214,7 @@ HEADERS += mainwindow.h \
ssh/sftpdefs.h \
ssh/sftpchannel.h \
ssh/sftpchannel_p.h \
+ ssh/sshremoteprocessrunner.h \
outputpanemanager.h \
navigationsubwidget.h \
sidebarwidget.h \
@@ -246,4 +244,6 @@ else:unix {
images.path = /share/pixmaps
INSTALLS += images
}
-OTHER_FILES += Core.pluginspec editormanager/BinFiles.mimetypes.xml
+OTHER_FILES += editormanager/BinFiles.mimetypes.xml ide_version.h.in
+
+QMAKE_SUBSTITUTES += ide_version.h.in
diff --git a/src/plugins/coreplugin/designmode.cpp b/src/plugins/coreplugin/designmode.cpp
index 199dbb2e6b..eaa67feafa 100644
--- a/src/plugins/coreplugin/designmode.cpp
+++ b/src/plugins/coreplugin/designmode.cpp
@@ -118,6 +118,7 @@ DesignModePrivate::DesignModePrivate(DesignMode *q, EditorManager *editorManager
DesignMode::DesignMode(EditorManager *editorManager) :
IMode(), d(new DesignModePrivate(this, editorManager))
{
+ setObjectName(QLatin1String("DesignMode"));
setEnabled(false);
ExtensionSystem::PluginManager::instance()->addObject(d->m_coreListener);
diff --git a/src/plugins/coreplugin/dialogs/ioptionspage.cpp b/src/plugins/coreplugin/dialogs/ioptionspage.cpp
index e1dcd6f04b..f42a9295df 100644
--- a/src/plugins/coreplugin/dialogs/ioptionspage.cpp
+++ b/src/plugins/coreplugin/dialogs/ioptionspage.cpp
@@ -38,14 +38,19 @@
\mainclass
\brief The IOptionsPage is an interface for providing options pages.
+ You need to subclass this interface and put an instance of your subclass
+ into the plugin manager object pool (e.g. ExtensionSystem::PluginManager::addObject).
Guidelines for implementing:
\list
- \o id() is an id used for filtering when calling ICore:: showOptionsDialog()
- \o displayName() is the (translated) name for display.
- \o category() is the category used for filtering when calling ICore:: showOptionsDialog()
- \o displayCategory() is the translated category
+ \o id() is a unique identifier for referencing this page
+ \o displayName() is the (translated) name for display
+ \o category() is the unique id for the category that the page should be displayed in
+ \o displayCategory() is the translated name of the category
+ \o createPage() is called to retrieve the widget to show in the preferences dialog
+ The widget will be destroyed by the widget hierarchy when the dialog closes
\o apply() is called to store the settings. It should detect if any changes have been
- made and store those.
- \o matches() is used for the options dialog search filter.
+ made and store those
+ \o finish() is called directly before the preferences dialog closes
+ \o matches() is used for the options dialog search filter
\endlist
*/
diff --git a/src/plugins/coreplugin/dialogs/ioptionspage.h b/src/plugins/coreplugin/dialogs/ioptionspage.h
index 7cd4c1010e..df7cfe29fb 100644
--- a/src/plugins/coreplugin/dialogs/ioptionspage.h
+++ b/src/plugins/coreplugin/dialogs/ioptionspage.h
@@ -64,6 +64,29 @@ public:
virtual void finish() = 0;
};
+/*
+ Alternative way for providing option pages instead of adding IOptionsPage
+ objects into the plugin manager pool. Should only be used if creation of the
+ actual option pages is not possible or too expensive at Qt Creator startup.
+ (Like the designer integration, which needs to initialize designer plugins
+ before the options pages get available.)
+*/
+
+class CORE_EXPORT IOptionsPageProvider : public QObject
+{
+ Q_OBJECT
+
+public:
+ IOptionsPageProvider(QObject *parent = 0) : QObject(parent) {}
+ virtual ~IOptionsPageProvider() {}
+
+ virtual QString category() const = 0;
+ virtual QString displayCategory() const = 0;
+ virtual QIcon categoryIcon() const = 0;
+
+ virtual QList<IOptionsPage *> pages() const = 0;
+};
+
} // namespace Core
#endif // IOPTIONSPAGE_H
diff --git a/src/plugins/coreplugin/dialogs/saveitemsdialog.cpp b/src/plugins/coreplugin/dialogs/saveitemsdialog.cpp
index 6c8fb222d0..166d858a02 100644
--- a/src/plugins/coreplugin/dialogs/saveitemsdialog.cpp
+++ b/src/plugins/coreplugin/dialogs/saveitemsdialog.cpp
@@ -44,7 +44,7 @@
#include <QtGui/QHeaderView>
#include <QtGui/QCheckBox>
-Q_DECLARE_METATYPE(Core::IFile*);
+Q_DECLARE_METATYPE(Core::IFile*)
using namespace Core;
using namespace Core::Internal;
diff --git a/src/plugins/coreplugin/dialogs/settingsdialog.cpp b/src/plugins/coreplugin/dialogs/settingsdialog.cpp
index aaf6b09c82..90c2c55aa3 100644
--- a/src/plugins/coreplugin/dialogs/settingsdialog.cpp
+++ b/src/plugins/coreplugin/dialogs/settingsdialog.cpp
@@ -76,7 +76,8 @@ public:
QString id;
QString displayName;
QIcon icon;
- QList<IOptionsPage*> pages;
+ QList<IOptionsPage *> pages;
+ QList<IOptionsPageProvider *> providers;
int index;
QTabWidget *tabWidget;
};
@@ -90,7 +91,8 @@ public:
int rowCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
- void setPages(const QList<IOptionsPage*> &pages);
+ void setPages(const QList<IOptionsPage*> &pages,
+ const QList<IOptionsPageProvider *> &providers);
const QList<Category*> &categories() const { return m_categories; }
private:
@@ -134,7 +136,8 @@ QVariant CategoryModel::data(const QModelIndex &index, int role) const
return QVariant();
}
-void CategoryModel::setPages(const QList<IOptionsPage*> &pages)
+void CategoryModel::setPages(const QList<IOptionsPage*> &pages,
+ const QList<IOptionsPageProvider *> &providers)
{
// Clear any previous categories
qDeleteAll(m_categories);
@@ -147,13 +150,32 @@ void CategoryModel::setPages(const QList<IOptionsPage*> &pages)
if (!category) {
category = new Category;
category->id = categoryId;
+ category->tabWidget = 0;
+ category->index = -1;
+ m_categories.append(category);
+ }
+ if (category->displayName.isEmpty())
category->displayName = page->displayCategory();
+ if (category->icon.isNull())
category->icon = page->categoryIcon();
- category->pages.append(page);
+ category->pages.append(page);
+ }
+
+ foreach (IOptionsPageProvider *provider, providers) {
+ const QString &categoryId = provider->category();
+ Category *category = findCategoryById(categoryId);
+ if (!category) {
+ category = new Category;
+ category->id = categoryId;
+ category->tabWidget = 0;
+ category->index = -1;
m_categories.append(category);
- } else {
- category->pages.append(page);
}
+ if (category->displayName.isEmpty())
+ category->displayName = provider->displayCategory();
+ if (category->icon.isNull())
+ category->icon = provider->categoryIcon();
+ category->providers.append(provider);
}
reset();
@@ -281,26 +303,8 @@ SettingsDialog::SettingsDialog(QWidget *parent) :
setWindowTitle(tr("Options"));
#endif
- m_model->setPages(m_pages);
-
- // Create the tab widgets with the pages in each category
- const QList<Category*> &categories = m_model->categories();
- for (int i = 0; i < categories.size(); ++i) {
- Category *category = categories.at(i);
-
- QTabWidget *tabWidget = new QTabWidget;
- for (int j = 0; j < category->pages.size(); ++j) {
- IOptionsPage *page = category->pages.at(j);
- QWidget *widget = page->createPage(0);
- tabWidget->addTab(widget, page->displayName());
- }
-
- connect(tabWidget, SIGNAL(currentChanged(int)),
- this, SLOT(currentTabChanged(int)));
-
- category->tabWidget = tabWidget;
- category->index = m_stackedLayout->addWidget(tabWidget);
- }
+ m_model->setPages(m_pages,
+ ExtensionSystem::PluginManager::instance()->getObjects<IOptionsPageProvider>());
m_proxyModel->setSourceModel(m_model);
m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
@@ -387,6 +391,7 @@ void SettingsDialog::createGui()
mainGridLayout->addWidget(buttonBox, 2, 0, 1, 2);
mainGridLayout->setColumnStretch(1, 4);
setLayout(mainGridLayout);
+ setMinimumSize(1070, 680);
}
SettingsDialog::~SettingsDialog()
@@ -396,7 +401,7 @@ SettingsDialog::~SettingsDialog()
void SettingsDialog::showCategory(int index)
{
Category *category = m_model->categories().at(index);
-
+ ensureCategoryWidget(category);
// Update current category and page
m_currentCategory = category->id;
const int currentTabIndex = category->tabWidget->currentIndex();
@@ -412,6 +417,35 @@ void SettingsDialog::showCategory(int index)
updateEnabledTabs(category, m_filterLineEdit->text());
}
+void SettingsDialog::ensureCategoryWidget(Category *category)
+{
+ if (category->tabWidget != 0)
+ return;
+ foreach (const IOptionsPageProvider *provider, category->providers) {
+ category->pages += provider->pages();
+ }
+ qStableSort(category->pages.begin(), category->pages.end(), optionsPageLessThan);
+
+ QTabWidget *tabWidget = new QTabWidget;
+ for (int j = 0; j < category->pages.size(); ++j) {
+ IOptionsPage *page = category->pages.at(j);
+ QWidget *widget = page->createPage(0);
+ tabWidget->addTab(widget, page->displayName());
+ }
+
+ connect(tabWidget, SIGNAL(currentChanged(int)),
+ this, SLOT(currentTabChanged(int)));
+
+ category->tabWidget = tabWidget;
+ category->index = m_stackedLayout->addWidget(tabWidget);
+}
+
+void SettingsDialog::ensureAllCategoryWidgets()
+{
+ foreach (Category *category, m_model->categories())
+ ensureCategoryWidget(category);
+}
+
void SettingsDialog::updateEnabledTabs(Category *category, const QString &searchText)
{
for (int i = 0; i < category->pages.size(); ++i) {
@@ -448,6 +482,7 @@ void SettingsDialog::currentTabChanged(int index)
void SettingsDialog::filter(const QString &text)
{
+ ensureAllCategoryWidgets();
// When there is no current index, select the first one when possible
if (!m_categoryList->currentIndex().isValid() && m_model->rowCount() > 0)
m_categoryList->setCurrentIndex(m_proxyModel->index(0, 0));
diff --git a/src/plugins/coreplugin/dialogs/settingsdialog.h b/src/plugins/coreplugin/dialogs/settingsdialog.h
index bcae1ab739..a9b35f8eb4 100644
--- a/src/plugins/coreplugin/dialogs/settingsdialog.h
+++ b/src/plugins/coreplugin/dialogs/settingsdialog.h
@@ -97,6 +97,8 @@ private:
void showCategory(int index);
void showPage(const QString &categoryId, const QString &pageId);
void updateEnabledTabs(Category *category, const QString &searchText);
+ void ensureCategoryWidget(Category *category);
+ void ensureAllCategoryWidgets();
const QList<Core::IOptionsPage*> m_pages;
diff --git a/src/plugins/coreplugin/dialogs/shortcutsettings.cpp b/src/plugins/coreplugin/dialogs/shortcutsettings.cpp
index 9f20bc02d3..c88c7baa1c 100644
--- a/src/plugins/coreplugin/dialogs/shortcutsettings.cpp
+++ b/src/plugins/coreplugin/dialogs/shortcutsettings.cpp
@@ -54,14 +54,16 @@
#include <QtCore/QCoreApplication>
#include <QtDebug>
-Q_DECLARE_METATYPE(Core::Internal::ShortcutItem*);
+Q_DECLARE_METATYPE(Core::Internal::ShortcutItem*)
using namespace Core;
using namespace Core::Internal;
ShortcutSettings::ShortcutSettings(QObject *parent)
- : CommandMappings(parent)
+ : CommandMappings(parent), m_initialized(false)
{
+ Core::Internal::ActionManagerPrivate *am = ActionManagerPrivate::instance();
+ connect(am, SIGNAL(commandListChanged()), this, SLOT(initialize()));
}
ShortcutSettings::~ShortcutSettings()
@@ -98,6 +100,7 @@ QIcon ShortcutSettings::categoryIcon() const
QWidget *ShortcutSettings::createPage(QWidget *parent)
{
+ m_initialized = true;
m_keyNum = m_key[0] = m_key[1] = m_key[2] = m_key[3] = 0;
QWidget *w = CommandMappings::createPage(parent);
@@ -132,6 +135,7 @@ void ShortcutSettings::finish()
m_scitems.clear();
CommandMappings::finish();
+ m_initialized = false;
}
bool ShortcutSettings::matches(const QString &s) const
@@ -275,8 +279,21 @@ void ShortcutSettings::exportAction()
}
}
+void ShortcutSettings::clear()
+{
+ QTreeWidget *tree = commandList();
+ for (int i = tree->topLevelItemCount()-1; i >= 0 ; --i) {
+ delete tree->takeTopLevelItem(i);
+ }
+ qDeleteAll(m_scitems);
+ m_scitems.clear();
+}
+
void ShortcutSettings::initialize()
{
+ if (!m_initialized)
+ return;
+ clear();
Core::Internal::ActionManagerPrivate *am = ActionManagerPrivate::instance();
UniqueIDManager *uidm = UniqueIDManager::instance();
@@ -329,6 +346,7 @@ void ShortcutSettings::initialize()
markPossibleCollisions(s);
}
+ filterChanged(filterText());
}
void ShortcutSettings::handleKeyEvent(QKeyEvent *e)
diff --git a/src/plugins/coreplugin/dialogs/shortcutsettings.h b/src/plugins/coreplugin/dialogs/shortcutsettings.h
index 4fef4c1060..e19f6711e3 100644
--- a/src/plugins/coreplugin/dialogs/shortcutsettings.h
+++ b/src/plugins/coreplugin/dialogs/shortcutsettings.h
@@ -90,10 +90,11 @@ private slots:
void importAction();
void exportAction();
void defaultAction();
+ void initialize();
private:
void setKeySequence(const QKeySequence &key);
- void initialize();
+ void clear();
void handleKeyEvent(QKeyEvent *e);
int translateModifiers(Qt::KeyboardModifiers state, const QString &text);
@@ -105,6 +106,7 @@ private:
int m_key[4], m_keyNum;
QString m_searchKeywords;
+ bool m_initialized;
};
} // namespace Internal
diff --git a/src/plugins/coreplugin/editmode.cpp b/src/plugins/coreplugin/editmode.cpp
index 8cb284bef8..5d629c1a36 100644
--- a/src/plugins/coreplugin/editmode.cpp
+++ b/src/plugins/coreplugin/editmode.cpp
@@ -57,6 +57,7 @@ EditMode::EditMode(EditorManager *editorManager) :
m_splitter(new MiniSplitter),
m_rightSplitWidgetLayout(new QVBoxLayout)
{
+ setObjectName(QLatin1String("EditMode"));
m_rightSplitWidgetLayout->setSpacing(0);
m_rightSplitWidgetLayout->setMargin(0);
QWidget *rightSplitWidget = new QWidget;
@@ -72,7 +73,9 @@ EditMode::EditMode(EditorManager *editorManager) :
MiniSplitter *splitter = new MiniSplitter;
splitter->setOrientation(Qt::Vertical);
splitter->insertWidget(0, rightPaneSplitter);
- splitter->insertWidget(1, new Core::OutputPanePlaceHolder(this, splitter));
+ QWidget *outputPane = new Core::OutputPanePlaceHolder(this, splitter);
+ outputPane->setObjectName(QLatin1String("EditModeOutputPanePlaceHolder"));
+ splitter->insertWidget(1, outputPane);
splitter->setStretchFactor(0, 3);
splitter->setStretchFactor(1, 0);
diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp
index 655b766748..3d12695e50 100644
--- a/src/plugins/coreplugin/editormanager/editormanager.cpp
+++ b/src/plugins/coreplugin/editormanager/editormanager.cpp
@@ -70,6 +70,7 @@
#include <QtCore/QProcess>
#include <QtCore/QSet>
#include <QtCore/QSettings>
+#include <QtCore/QTextCodec>
#include <QtGui/QAction>
#include <QtGui/QShortcut>
@@ -83,10 +84,6 @@
#include <QtGui/QSplitter>
#include <QtGui/QStackedLayout>
-#include <algorithm>
-
-Q_DECLARE_METATYPE(Core::IEditor*)
-
enum { debugEditorManager=0 };
static inline ExtensionSystem::PluginManager *pluginManager()
@@ -220,6 +217,9 @@ struct EditorManagerPrivate {
QString m_externalEditor;
IFile::ReloadSetting m_reloadSetting;
+ IFile::Utf8BomSetting m_utf8BomSetting;
+
+ QString m_titleAddition;
};
}
@@ -240,7 +240,8 @@ EditorManagerPrivate::EditorManagerPrivate(ICore *core, QWidget *parent) :
m_openInExternalEditorAction(new QAction(EditorManager::tr("Open in External Editor"), parent)),
m_windowPopup(0),
m_coreListener(0),
- m_reloadSetting(IFile::AlwaysAsk)
+ m_reloadSetting(IFile::AlwaysAsk),
+ m_utf8BomSetting(IFile::OnlyKeep)
{
m_editorModel = new OpenEditorsModel(parent);
}
@@ -538,6 +539,7 @@ void EditorManager::setCurrentEditor(IEditor *editor, bool ignoreNavigationHisto
m_d->m_view->updateEditorHistory(editor); // the global view should have a complete history
}
updateActions();
+ updateWindowTitle();
emit currentEditorChanged(editor);
}
@@ -579,9 +581,9 @@ Core::Internal::EditorView *EditorManager::currentEditorView() const
QList<IEditor *> EditorManager::editorsForFileName(const QString &filename) const
{
QList<IEditor *> found;
- QString fixedname = FileManager::fixFileName(filename);
+ QString fixedname = FileManager::fixFileName(filename, FileManager::KeepLinks);
foreach (IEditor *editor, openedEditors()) {
- if (fixedname == FileManager::fixFileName(editor->file()->fileName()))
+ if (fixedname == FileManager::fixFileName(editor->file()->fileName(), FileManager::KeepLinks))
found << editor;
}
return found;
@@ -772,7 +774,7 @@ bool EditorManager::closeEditors(const QList<IEditor*> &editorsToClose, bool ask
foreach (ICoreListener *listener, listeners) {
if (!listener->editorAboutToClose(editor)) {
editorAccepted = false;
- closingFailed = false;
+ closingFailed = true;
break;
}
}
@@ -806,7 +808,8 @@ bool EditorManager::closeEditors(const QList<IEditor*> &editorsToClose, bool ask
// remove the editors
foreach (IEditor *editor, acceptedEditors) {
emit editorAboutToClose(editor);
- if (!editor->file()->fileName().isEmpty()) {
+ if (!editor->file()->fileName().isEmpty()
+ && !editor->isTemporary()) {
QByteArray state = editor->saveState();
if (!state.isEmpty())
m_d->m_editorStates.insert(editor->file()->fileName(), QVariant(state));
@@ -847,6 +850,7 @@ bool EditorManager::closeEditors(const QList<IEditor*> &editorsToClose, bool ask
if (!currentEditor()) {
emit currentEditorChanged(0);
updateActions();
+ updateWindowTitle();
}
return !closingFailed;
@@ -1093,7 +1097,7 @@ IEditor *EditorManager::createEditor(const QString &editorId,
IEditor *editor = factories.front()->createEditor(this);
if (editor)
- connect(editor, SIGNAL(changed()), this, SLOT(updateActions()));
+ connect(editor, SIGNAL(changed()), this, SLOT(handleEditorStateChange()));
if (editor)
emit editorCreated(editor, fileName);
return editor;
@@ -1111,7 +1115,8 @@ void EditorManager::addEditor(IEditor *editor, bool isDuplicate)
const bool addWatcher = !isTemporary;
m_d->m_core->fileManager()->addFile(editor->file(), addWatcher);
if (!isTemporary)
- m_d->m_core->fileManager()->addToRecentFiles(editor->file()->fileName());
+ m_d->m_core->fileManager()->addToRecentFiles(editor->file()->fileName(),
+ editor->id());
}
emit editorOpened(editor);
}
@@ -1154,30 +1159,6 @@ QString EditorManager::getOpenWithEditorId(const QString &fileName,
return selectedId;
}
-static QString formatFileFilters(const Core::ICore *core, QString *selectedFilter = 0)
-{
- if (selectedFilter)
- selectedFilter->clear();
-
- // Compile list of filter strings, sort, and remove duplicates (different mime types might
- // generate the same filter).
- QStringList filters = core->mimeDatabase()->filterStrings();
- if (filters.empty())
- return QString();
- filters.sort();
- filters.erase(std::unique(filters.begin(), filters.end()), filters.end());
-
- static const QString allFilesFilter =
- QCoreApplication::translate("Core", Constants::ALL_FILES_FILTER);
- if (selectedFilter)
- *selectedFilter = allFilesFilter;
-
- // Prepend all files filter (instead of appending to work around a bug in Qt/Mac).
- filters.prepend(allFilesFilter);
-
- return filters.join(QLatin1String(";;"));
-}
-
IEditor *EditorManager::openEditor(const QString &fileName, const QString &editorId,
OpenEditorFlags flags, bool *newEditor)
{
@@ -1219,8 +1200,12 @@ IEditor *EditorManager::openEditor(Core::Internal::EditorView *view, const QStri
*newEditor = false;
const QList<IEditor *> editors = editorsForFileName(fn);
- if (!editors.isEmpty())
- return activateEditor(view, editors.first(), flags);
+ if (!editors.isEmpty()) {
+ IEditor *editor = editors.first();
+ if (flags && EditorManager::CanContainLineNumber)
+ editor->gotoLine(lineNumber, -1);
+ return activateEditor(view, editor, flags);
+ }
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
IEditor *editor = createEditor(editorId, fn);
@@ -1268,7 +1253,7 @@ bool EditorManager::openExternalEditor(const QString &fileName, const QString &e
QStringList EditorManager::getOpenFileNames() const
{
QString selectedFilter;
- const QString &fileFilters = formatFileFilters(m_d->m_core, &selectedFilter);
+ const QString &fileFilters = m_d->m_core->mimeDatabase()->allFiltersString(&selectedFilter);
return ICore::instance()->fileManager()->getOpenFileNames(fileFilters,
QString(), &selectedFilter);
}
@@ -1280,16 +1265,14 @@ QStringList EditorManager::getOpenFileNames() const
void EditorManager::switchToPreferedMode()
{
QString preferedMode;
- // Figure out prefered mode for editor
+ // Figure out preferred mode for editor
if (m_d->m_currentEditor)
preferedMode = m_d->m_currentEditor->preferredModeType();
if (preferedMode.isEmpty())
preferedMode = Constants::MODE_EDIT_TYPE;
- if (m_d->m_core->modeManager()->currentMode()->type() != preferedMode) {
- m_d->m_core->modeManager()->activateModeType(preferedMode);
- }
+ m_d->m_core->modeManager()->activateModeType(preferedMode);
}
IEditor *EditorManager::openEditorWithContents(const QString &editorId,
@@ -1299,28 +1282,11 @@ IEditor *EditorManager::openEditorWithContents(const QString &editorId,
if (debugEditorManager)
qDebug() << Q_FUNC_INFO << editorId << titlePattern << contents;
- if (editorId.isEmpty())
- return 0;
-
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
- IEditor *edt = createEditor(editorId);
- if (!edt) {
- QApplication::restoreOverrideCursor();
- return 0;
- }
-
- if (!edt->createNew(contents)) {
- QApplication::restoreOverrideCursor();
- delete edt;
- edt = 0;
- return 0;
- }
-
- QString title = edt->displayName();
+ QString title;
if (titlePattern) {
const QChar dollar = QLatin1Char('$');
- const QChar dot = QLatin1Char('.');
QString base = *titlePattern;
if (base.isEmpty())
@@ -1332,7 +1298,6 @@ IEditor *EditorManager::openEditorWithContents(const QString &editorId,
QString name = editor->file()->fileName();
if (name.isEmpty()) {
name = editor->displayName();
- name.remove(QLatin1Char('*'));
} else {
name = QFileInfo(name).completeBaseName();
}
@@ -1348,6 +1313,23 @@ IEditor *EditorManager::openEditorWithContents(const QString &editorId,
}
*titlePattern = title;
}
+
+ IEditor *edt = createEditor(editorId, title);
+ if (!edt) {
+ QApplication::restoreOverrideCursor();
+ return 0;
+ }
+
+ if (!edt->createNew(contents)) {
+ QApplication::restoreOverrideCursor();
+ delete edt;
+ edt = 0;
+ return 0;
+ }
+
+ if (title.isEmpty())
+ title = edt->displayName();
+
edt->setDisplayName(title);
addEditor(edt);
QApplication::restoreOverrideCursor();
@@ -1368,23 +1350,23 @@ void EditorManager::restoreEditorState(IEditor *editor)
bool EditorManager::saveEditor(IEditor *editor)
{
- return saveFile(editor);
+ return saveFile(editor->file());
}
-bool EditorManager::saveFile(IEditor *editor)
+bool EditorManager::saveFile(IFile *fileParam)
{
- if (!editor)
- editor = currentEditor();
- if (!editor)
+ IFile *file = fileParam;
+ if (!file && currentEditor())
+ file = currentEditor()->file();
+ if (!file)
return false;
- IFile *file = editor->file();
file->checkPermissions();
const QString &fileName = file->fileName();
if (fileName.isEmpty())
- return saveFileAs(editor);
+ return saveFileAs(file);
bool success = false;
@@ -1395,7 +1377,7 @@ bool EditorManager::saveFile(IEditor *editor)
if (!success) {
MakeWritableResult answer =
- makeEditorWritable(editor);
+ makeFileWritable(file);
if (answer == Failed)
return false;
if (answer == SavedAs)
@@ -1408,74 +1390,31 @@ bool EditorManager::saveFile(IEditor *editor)
m_d->m_core->fileManager()->unblockFileChange(file);
}
- if (success && !editor->isTemporary())
- m_d->m_core->fileManager()->addToRecentFiles(editor->file()->fileName());
-
- return success;
-}
-
-EditorManager::ReadOnlyAction
- EditorManager::promptReadOnlyFile(const QString &fileName,
- const IVersionControl *versionControl,
- QWidget *parent,
- bool displaySaveAsButton)
-{
- // Version Control: If automatic open is desired, open right away.
- bool promptVCS = false;
- if (versionControl && versionControl->supportsOperation(IVersionControl::OpenOperation)) {
- if (versionControl->settingsFlags() & IVersionControl::AutoOpen)
- return RO_OpenVCS;
- promptVCS = true;
+ if (success) {
+ addFileToRecentFiles(file);
}
- // Create message box.
- QMessageBox msgBox(QMessageBox::Question, tr("File is Read Only"),
- tr("The file <i>%1</i> is read only.").arg(QDir::toNativeSeparators(fileName)),
- QMessageBox::Cancel, parent);
-
- QPushButton *vcsButton = 0;
- if (promptVCS)
- vcsButton = msgBox.addButton(tr("Open with VCS (%1)").arg(versionControl->displayName()), QMessageBox::AcceptRole);
-
- QPushButton *makeWritableButton = msgBox.addButton(tr("Make writable"), QMessageBox::AcceptRole);
-
- QPushButton *saveAsButton = 0;
- if (displaySaveAsButton)
- saveAsButton = msgBox.addButton(tr("Save as ..."), QMessageBox::ActionRole);
-
- msgBox.setDefaultButton(vcsButton ? vcsButton : makeWritableButton);
- msgBox.exec();
-
- QAbstractButton *clickedButton = msgBox.clickedButton();
- if (clickedButton == vcsButton)
- return RO_OpenVCS;
- if (clickedButton == makeWritableButton)
- return RO_MakeWriteable;
- if (clickedButton == saveAsButton)
- return RO_SaveAs;
- return RO_Cancel;
+ return success;
}
-
MakeWritableResult
-EditorManager::makeEditorWritable(IEditor *editor)
+EditorManager::makeFileWritable(IFile *file)
{
- if (!editor || !editor->file())
+ if (!file)
return Failed;
- QString directory = QFileInfo(editor->file()->fileName()).absolutePath();
+ QString directory = QFileInfo(file->fileName()).absolutePath();
IVersionControl *versionControl = m_d->m_core->vcsManager()->findVersionControlForDirectory(directory);
- IFile *file = editor->file();
const QString &fileName = file->fileName();
- switch (promptReadOnlyFile(fileName, versionControl, m_d->m_core->mainWindow(), true)) {
- case RO_OpenVCS:
+ switch (FileManager::promptReadOnlyFile(fileName, versionControl, m_d->m_core->mainWindow(), file->isSaveAsAllowed())) {
+ case FileManager::RO_OpenVCS:
if (!versionControl->vcsOpen(fileName)) {
QMessageBox::warning(m_d->m_core->mainWindow(), tr("Failed!"), tr("Could not open the file for editing with SCC."));
return Failed;
}
file->checkPermissions();
return OpenedWithVersionControl;
- case RO_MakeWriteable: {
+ case FileManager::RO_MakeWriteable: {
const bool permsOk = QFile::setPermissions(fileName, QFile::permissions(fileName) | QFile::WriteUser);
if (!permsOk) {
QMessageBox::warning(m_d->m_core->mainWindow(), tr("Failed!"), tr("Could not set permissions to writable."));
@@ -1484,23 +1423,23 @@ EditorManager::makeEditorWritable(IEditor *editor)
}
file->checkPermissions();
return MadeWritable;
- case RO_SaveAs :
- return saveFileAs(editor) ? SavedAs : Failed;
- case RO_Cancel:
+ case FileManager::RO_SaveAs :
+ return saveFileAs(file) ? SavedAs : Failed;
+ case FileManager::RO_Cancel:
break;
}
return Failed;
}
-bool EditorManager::saveFileAs(IEditor *editor)
+bool EditorManager::saveFileAs(IFile *fileParam)
{
- if (!editor)
- editor = currentEditor();
- if (!editor)
+ IFile *file = fileParam;
+ if (!file && currentEditor())
+ file = currentEditor()->file();
+ if (!file)
return false;
- IFile *file = editor->file();
- const QString &filter = formatFileFilters(m_d->m_core);
+ const QString &filter = m_d->m_core->mimeDatabase()->allFiltersString();
QString selectedFilter =
m_d->m_core->mimeDatabase()->findByFile(QFileInfo(file->fileName())).filterString();
const QString &absoluteFilePath =
@@ -1508,7 +1447,9 @@ bool EditorManager::saveFileAs(IEditor *editor)
if (absoluteFilePath.isEmpty())
return false;
+
if (absoluteFilePath != file->fileName()) {
+ // close existing editors for the new file name
const QList<IEditor *> existList = editorsForFileName(absoluteFilePath);
if (!existList.isEmpty()) {
closeEditors(existList, false);
@@ -1526,13 +1467,30 @@ bool EditorManager::saveFileAs(IEditor *editor)
// a good way out either (also the undo stack would be lost). Perhaps the best is to
// re-think part of the editors design.
- if (success && !editor->isTemporary())
- m_d->m_core->fileManager()->addToRecentFiles(file->fileName());
-
+ if (success) {
+ addFileToRecentFiles(file);
+ }
updateActions();
return success;
}
+/* Adds the file name to the recent files if there is at least one non-temporary editor for it */
+void EditorManager::addFileToRecentFiles(IFile *file)
+{
+ bool isTemporary = true;
+ QString editorId;
+ QList<IEditor *> editors = editorsForFile(file);
+ foreach (IEditor *editor, editors) {
+ if (!editor->isTemporary()) {
+ editorId = editor->id();
+ isTemporary = false;
+ break;
+ }
+ }
+ if (!isTemporary)
+ m_d->m_core->fileManager()->addToRecentFiles(file->fileName(), editorId);
+}
+
void EditorManager::gotoNextDocHistory()
{
OpenEditorsWindow *dialog = windowPopup();
@@ -1562,7 +1520,37 @@ void EditorManager::gotoPreviousDocHistory()
void EditorManager::makeCurrentEditorWritable()
{
if (IEditor* curEditor = currentEditor())
- makeEditorWritable(curEditor);
+ makeFileWritable(curEditor->file());
+}
+
+void EditorManager::updateWindowTitle()
+{
+ QString windowTitle = tr("Qt Creator");
+ if (!m_d->m_titleAddition.isEmpty()) {
+ windowTitle.prepend(m_d->m_titleAddition + " - ");
+ }
+ IEditor *curEditor = currentEditor();
+ if (curEditor) {
+ QString editorName = curEditor->displayName();
+ if (!editorName.isEmpty())
+ windowTitle.prepend(editorName + " - ");
+ QString filePath = QFileInfo(curEditor->file()->fileName()).absoluteFilePath();
+ if (!filePath.isEmpty())
+ m_d->m_core->mainWindow()->setWindowFilePath(filePath);
+ } else {
+ m_d->m_core->mainWindow()->setWindowFilePath(QString());
+ }
+ m_d->m_core->mainWindow()->setWindowTitle(windowTitle);
+}
+
+void EditorManager::handleEditorStateChange()
+{
+ updateActions();
+ IEditor *currEditor = currentEditor();
+ if (qobject_cast<IEditor *>(sender()) == currEditor) {
+ updateWindowTitle();
+ emit currentEditorStateChanged(currEditor);
+ }
}
void EditorManager::updateActions()
@@ -1635,6 +1623,27 @@ bool EditorManager::hasSplitter() const
return m_d->m_splitter->isSplitter();
}
+QList<IEditor*> EditorManager::visibleEditors() const
+{
+ QList<IEditor *> editors;
+ if (m_d->m_splitter->isSplitter()) {
+ SplitterOrView *firstView = m_d->m_splitter->findFirstView();
+ SplitterOrView *view = firstView;
+ if (view) {
+ do {
+ if (view->editor())
+ editors.append(view->editor());
+ view = m_d->m_splitter->findNextView(view);
+ } while (view && view != firstView);
+ }
+ } else {
+ if (m_d->m_splitter->editor()) {
+ editors.append(m_d->m_splitter->editor());
+ }
+ }
+ return editors;
+}
+
QList<IEditor*> EditorManager::openedEditors() const
{
return m_d->m_editorModel->editors();
@@ -1790,6 +1799,7 @@ bool EditorManager::restoreState(const QByteArray &state)
static const char * const documentStatesKey = "EditorManager/DocumentStates";
static const char * const externalEditorKey = "EditorManager/ExternalEditorCommand";
static const char * const reloadBehaviorKey = "EditorManager/ReloadBehavior";
+static const char * const utf8BomBehaviorKey = "EditorManager/Utf8BomBehavior";
void EditorManager::saveSettings()
{
@@ -1797,6 +1807,7 @@ void EditorManager::saveSettings()
settings->setValue(QLatin1String(documentStatesKey), m_d->m_editorStates);
settings->setValue(QLatin1String(externalEditorKey), m_d->m_externalEditor);
settings->setValue(QLatin1String(reloadBehaviorKey), m_d->m_reloadSetting);
+ settings->setValue(QLatin1String(utf8BomBehaviorKey), m_d->m_utf8BomSetting);
}
void EditorManager::readSettings()
@@ -1822,6 +1833,9 @@ void EditorManager::readSettings()
if (settings->contains(QLatin1String(reloadBehaviorKey)))
m_d->m_reloadSetting = (IFile::ReloadSetting)settings->value(QLatin1String(reloadBehaviorKey)).toInt();
+
+ if (settings->contains(QLatin1String(utf8BomBehaviorKey)))
+ m_d->m_utf8BomSetting = (IFile::Utf8BomSetting)settings->value(QLatin1String(utf8BomBehaviorKey)).toInt();
}
@@ -1989,6 +2003,25 @@ IFile::ReloadSetting EditorManager::reloadSetting() const
return m_d->m_reloadSetting;
}
+void EditorManager::setUtf8BomSetting(IFile::Utf8BomSetting behavior)
+{
+ m_d->m_utf8BomSetting = behavior;
+}
+
+IFile::Utf8BomSetting EditorManager::utf8BomSetting() const
+{
+ return m_d->m_utf8BomSetting;
+}
+
+QTextCodec *EditorManager::defaultTextEncoding() const
+{
+ QSettings *settings = Core::ICore::instance()->settings();
+ if (QTextCodec *candidate = QTextCodec::codecForName(
+ settings->value(QLatin1String(Constants::SETTINGS_DEFAULTTEXTENCODING)).toByteArray()))
+ return candidate;
+ return QTextCodec::codecForLocale();
+}
+
Core::IEditor *EditorManager::duplicateEditor(Core::IEditor *editor)
{
if (!editor->duplicateSupported())
@@ -1996,6 +2029,7 @@ Core::IEditor *EditorManager::duplicateEditor(Core::IEditor *editor)
IEditor *duplicate = editor->duplicate(0);
duplicate->restoreState(editor->saveState());
+ connect(duplicate, SIGNAL(changed()), this, SLOT(handleEditorStateChange()));
emit editorCreated(duplicate, duplicate->file()->fileName());
addEditor(duplicate, true);
return duplicate;
@@ -2041,7 +2075,8 @@ void EditorManager::removeAllSplits()
if (!m_d->m_splitter->isSplitter())
return;
IEditor *editor = m_d->m_currentEditor;
- m_d->m_currentEditor = 0; // trigger update below
+ // trigger update below
+ m_d->m_currentEditor = 0;
if (editor && m_d->m_editorModel->isDuplicate(editor))
m_d->m_editorModel->makeOriginal(editor);
m_d->m_splitter->unsplitAll();
@@ -2076,5 +2111,15 @@ qint64 EditorManager::maxTextFileSize()
{
return (qint64(3) << 24);
}
-//===================EditorClosingCoreListener======================
+
+void EditorManager::setWindowTitleAddition(const QString &addition)
+{
+ m_d->m_titleAddition = addition;
+ updateWindowTitle();
+}
+
+QString EditorManager::windowTitleAddition() const
+{
+ return m_d->m_titleAddition;
+}
diff --git a/src/plugins/coreplugin/editormanager/editormanager.h b/src/plugins/coreplugin/editormanager/editormanager.h
index 595f17901e..3c30d8770a 100644
--- a/src/plugins/coreplugin/editormanager/editormanager.h
+++ b/src/plugins/coreplugin/editormanager/editormanager.h
@@ -137,18 +137,18 @@ public:
QList<IEditor *> editorsForFile(IFile *file) const;
IEditor *currentEditor() const;
+ QList<IEditor *> visibleEditors() const;
+ QList<IEditor*> openedEditors() const;
+
IEditor *activateEditor(IEditor *editor, OpenEditorFlags flags = 0);
IEditor *activateEditor(const QModelIndex &index, Internal::EditorView *view = 0, OpenEditorFlags = 0);
IEditor *activateEditor(Core::Internal::EditorView *view, Core::IFile*file, OpenEditorFlags flags = 0);
- QList<IEditor*> openedEditors() const;
-
OpenEditorsModel *openedEditorsModel() const;
void closeEditor(const QModelIndex &index);
void closeOtherEditors(IEditor *editor);
QList<IEditor*> editorsForFiles(QList<IFile*> files) const;
- //QList<EditorGroup *> editorGroups() const;
void addCurrentPositionToNavigationHistory(IEditor *editor = 0, const QByteArray &saveState = QByteArray());
void cutForwardNavigationHistory();
@@ -156,7 +156,7 @@ public:
bool closeEditors(const QList<IEditor *> &editorsToClose, bool askAboutModifiedEditors = true);
- MakeWritableResult makeEditorWritable(IEditor *editor);
+ MakeWritableResult makeFileWritable(IFile *file);
QByteArray saveState() const;
bool restoreState(const QByteArray &state);
@@ -196,19 +196,19 @@ public:
void setReloadSetting(IFile::ReloadSetting behavior);
IFile::ReloadSetting reloadSetting() const;
- // Helper to display a message dialog when encountering a read-only
- // file, prompting the user about how to make it writeable.
- enum ReadOnlyAction { RO_Cancel, RO_OpenVCS, RO_MakeWriteable, RO_SaveAs };
+ void setUtf8BomSetting(IFile::Utf8BomSetting behavior);
+ IFile::Utf8BomSetting utf8BomSetting() const;
- static ReadOnlyAction promptReadOnlyFile(const QString &fileName,
- const IVersionControl *versionControl,
- QWidget *parent,
- bool displaySaveAsButton = false);
+ QTextCodec *defaultTextEncoding() const;
static qint64 maxTextFileSize();
+ void setWindowTitleAddition(const QString &addition);
+ QString windowTitleAddition() const;
+
signals:
void currentEditorChanged(Core::IEditor *editor);
+ void currentEditorStateChanged(Core::IEditor *editor);
void editorCreated(Core::IEditor *editor, const QString &fileName);
void editorOpened(Core::IEditor *editor);
void editorAboutToClose(Core::IEditor *editor);
@@ -218,8 +218,8 @@ public slots:
bool closeAllEditors(bool askAboutModifiedEditors = true);
void openInExternalEditor();
- bool saveFile(Core::IEditor *editor = 0);
- bool saveFileAs(Core::IEditor *editor = 0);
+ bool saveFile(Core::IFile *file = 0);
+ bool saveFileAs(Core::IFile *file = 0);
void revertToSaved();
void closeEditor();
void closeOtherEditors();
@@ -230,6 +230,8 @@ private slots:
void handleContextChange(Core::IContext *context);
void updateActions();
void makeCurrentEditorWritable();
+ void updateWindowTitle();
+ void handleEditorStateChange();
public slots:
void goBackInNavigationHistory();
@@ -267,7 +269,7 @@ private:
void emptyView(Core::Internal::EditorView *view);
Core::Internal::EditorView *currentEditorView() const;
IEditor *pickUnusedEditor() const;
-
+ void addFileToRecentFiles(IFile *file);
static EditorManager *m_instance;
EditorManagerPrivate *m_d;
@@ -279,5 +281,5 @@ private:
} // namespace Core
-Q_DECLARE_OPERATORS_FOR_FLAGS(Core::EditorManager::OpenEditorFlags);
+Q_DECLARE_OPERATORS_FOR_FLAGS(Core::EditorManager::OpenEditorFlags)
#endif // EDITORMANAGER_H
diff --git a/src/plugins/coreplugin/editormanager/editorview.cpp b/src/plugins/coreplugin/editormanager/editorview.cpp
index d471ce4bac..d3994ec84e 100644
--- a/src/plugins/coreplugin/editormanager/editorview.cpp
+++ b/src/plugins/coreplugin/editormanager/editorview.cpp
@@ -70,8 +70,6 @@
#include <qmacstyle_mac.h>
#endif
-Q_DECLARE_METATYPE(Core::IEditor *)
-
using namespace Core;
using namespace Core::Internal;
@@ -182,6 +180,12 @@ void EditorView::showEditorInfoBar(const QString &id,
m_infoWidgetLabel->setText(infoText);
m_infoWidgetButton->setText(buttonText);
+ if (object && !buttonText.isEmpty()) {
+ m_infoWidgetButton->show();
+ } else {
+ m_infoWidgetButton->hide();
+ }
+
m_infoWidgetButton->disconnect();
if (object && buttonPressMember)
connect(m_infoWidgetButton, SIGNAL(clicked()), object, buttonPressMember);
@@ -807,14 +811,26 @@ QByteArray SplitterOrView::saveState() const
IEditor* e = editor();
EditorManager *em = CoreImpl::instance()->editorManager();
- if (e && e == em->currentEditor()) {
+ // don't save state of temporary or ad-hoc editors
+ if (e && (e->isTemporary() || e->file()->fileName().isEmpty())) {
+ // look for another editor that is more suited
+ e = 0;
+ foreach (IEditor *otherEditor, editors()) {
+ if (!otherEditor->isTemporary() && !otherEditor->file()->fileName().isEmpty()) {
+ e = otherEditor;
+ break;
+ }
+ }
+ }
+
+ if (!e) {
+ stream << QByteArray("empty");
+ } else if (e == em->currentEditor()) {
stream << QByteArray("currenteditor")
<< e->file()->fileName() << e->id() << e->saveState();
- } else if (e) {
+ } else {
stream << QByteArray("editor")
<< e->file()->fileName() << e->id() << e->saveState();
- } else {
- stream << QByteArray("empty");
}
}
return bytes;
diff --git a/src/plugins/coreplugin/editormanager/ieditor.h b/src/plugins/coreplugin/editormanager/ieditor.h
index 59ca00808d..180282fd0f 100644
--- a/src/plugins/coreplugin/editormanager/ieditor.h
+++ b/src/plugins/coreplugin/editormanager/ieditor.h
@@ -36,6 +36,7 @@
#include <coreplugin/core_global.h>
#include <coreplugin/icontext.h>
+#include <QtCore/QMetaType>
namespace Core {
@@ -78,4 +79,6 @@ signals:
} // namespace Core
+Q_DECLARE_METATYPE(Core::IEditor*)
+
#endif // IEDITOR_H
diff --git a/src/plugins/coreplugin/editormanager/openeditorsmodel.cpp b/src/plugins/coreplugin/editormanager/openeditorsmodel.cpp
index 2a39223f4b..b037a9b35b 100644
--- a/src/plugins/coreplugin/editormanager/openeditorsmodel.cpp
+++ b/src/plugins/coreplugin/editormanager/openeditorsmodel.cpp
@@ -38,8 +38,6 @@
#include <QtCore/QDir>
#include <QtGui/QIcon>
-Q_DECLARE_METATYPE(Core::IEditor*)
-
namespace Core {
struct OpenEditorsModelPrivate {
diff --git a/src/plugins/coreplugin/editormanager/openeditorsview.cpp b/src/plugins/coreplugin/editormanager/openeditorsview.cpp
index 8bddfdcfdf..49d362887e 100644
--- a/src/plugins/coreplugin/editormanager/openeditorsview.cpp
+++ b/src/plugins/coreplugin/editormanager/openeditorsview.cpp
@@ -38,6 +38,7 @@
#include "icore.h"
#include <coreplugin/coreconstants.h>
+#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/filemanager.h>
#include <coreplugin/uniqueidmanager.h>
#include <coreplugin/actionmanager/actionmanager.h>
@@ -54,8 +55,6 @@
#include <qmacstyle_mac.h>
#endif
-Q_DECLARE_METATYPE(Core::IEditor*)
-
using namespace Core;
using namespace Core::Internal;
diff --git a/src/plugins/coreplugin/editortoolbar.cpp b/src/plugins/coreplugin/editortoolbar.cpp
index b38f1a43cc..116c5ad173 100644
--- a/src/plugins/coreplugin/editortoolbar.cpp
+++ b/src/plugins/coreplugin/editortoolbar.cpp
@@ -67,8 +67,6 @@
#include <QtGui/QLabel>
#include <QtGui/QToolBar>
-Q_DECLARE_METATYPE(Core::IEditor*)
-
enum {
debug = false
};
@@ -315,7 +313,7 @@ void EditorToolBar::listContextMenu(QPoint pos)
void EditorToolBar::makeEditorWritable()
{
if (currentEditor())
- ICore::instance()->editorManager()->makeEditorWritable(currentEditor());
+ ICore::instance()->editorManager()->makeFileWritable(currentEditor()->file());
}
void EditorToolBar::setCanGoBack(bool canGoBack)
diff --git a/src/plugins/coreplugin/fancyactionbar.cpp b/src/plugins/coreplugin/fancyactionbar.cpp
index e8d7b8a3ee..d1f0721e01 100644
--- a/src/plugins/coreplugin/fancyactionbar.cpp
+++ b/src/plugins/coreplugin/fancyactionbar.cpp
@@ -38,7 +38,6 @@
#include <coreplugin/icore.h>
#include <coreplugin/imode.h>
-#include <coreplugin/mainwindow.h>
#include <QtGui/QHBoxLayout>
#include <QtGui/QPainter>
diff --git a/src/plugins/coreplugin/filemanager.cpp b/src/plugins/coreplugin/filemanager.cpp
index c860cb173b..1478d91f8d 100644
--- a/src/plugins/coreplugin/filemanager.cpp
+++ b/src/plugins/coreplugin/filemanager.cpp
@@ -57,6 +57,7 @@
#include <QtGui/QFileDialog>
#include <QtGui/QMessageBox>
#include <QtGui/QMainWindow>
+#include <QtGui/QPushButton>
/*!
\class Core::FileManager
@@ -87,12 +88,13 @@
(see addToRecentFiles() and recentFiles()).
*/
-static const char settingsGroupC[] = "RecentFiles";
-static const char filesKeyC[] = "Files";
+static const char * const settingsGroupC = "RecentFiles";
+static const char * const filesKeyC = "Files";
+static const char * const editorsKeyC = "EditorIds";
-static const char directoryGroupC[] = "Directories";
-static const char projectDirectoryKeyC[] = "Projects";
-static const char useProjectDirectoryKeyC[] = "UseProjectsDirectory";
+static const char * const directoryGroupC = "Directories";
+static const char * const projectDirectoryKeyC = "Projects";
+static const char * const useProjectDirectoryKeyC = "UseProjectsDirectory";
namespace Core {
namespace Internal {
@@ -111,19 +113,22 @@ struct FileState
struct FileManagerPrivate {
- explicit FileManagerPrivate(QObject *q, QMainWindow *mw);
+ explicit FileManagerPrivate(FileManager *q, QMainWindow *mw);
+ static FileManager *m_instance;
QMap<QString, FileState> m_states;
QStringList m_changedFiles;
QList<IFile *> m_filesWithoutWatch;
+ QMap<IFile *, QStringList> m_filesWithWatch;
- QStringList m_recentFiles;
+ QList<FileManager::RecentFile> m_recentFiles;
static const int m_maxRecentFiles = 7;
QString m_currentFile;
QMainWindow *m_mainWindow;
QFileSystemWatcher *m_fileWatcher;
+ QFileSystemWatcher *m_linkWatcher;
bool m_blockActivated;
QString m_lastVisitedDirectory;
QString m_projectsDirectory;
@@ -135,7 +140,9 @@ struct FileManagerPrivate {
IFile *m_blockedIFile;
};
-FileManagerPrivate::FileManagerPrivate(QObject *q, QMainWindow *mw) :
+FileManager *FileManagerPrivate::m_instance = 0;
+
+FileManagerPrivate::FileManagerPrivate(FileManager *q, QMainWindow *mw) :
m_mainWindow(mw),
m_fileWatcher(new QFileSystemWatcher(q)),
m_blockActivated(false),
@@ -147,6 +154,17 @@ FileManagerPrivate::FileManagerPrivate(QObject *q, QMainWindow *mw) :
#endif
m_blockedIFile(0)
{
+ m_instance = q;
+ q->connect(m_fileWatcher, SIGNAL(fileChanged(QString)),
+ q, SLOT(changedFile(QString)));
+#ifdef Q_OS_UNIX
+ m_linkWatcher = new QFileSystemWatcher(q);
+ m_linkWatcher->setObjectName(QLatin1String("_qt_autotest_force_engine_poller"));
+ q->connect(m_linkWatcher, SIGNAL(fileChanged(QString)),
+ q, SLOT(changedFile(QString)));
+#else
+ m_linkWatcher = m_fileWatcher;
+#endif
}
} // namespace Internal
@@ -156,32 +174,12 @@ FileManager::FileManager(QMainWindow *mw)
d(new Internal::FileManagerPrivate(this, mw))
{
Core::ICore *core = Core::ICore::instance();
- connect(d->m_fileWatcher, SIGNAL(fileChanged(QString)),
- this, SLOT(changedFile(QString)));
connect(d->m_mainWindow, SIGNAL(windowActivated()),
this, SLOT(mainWindowActivated()));
connect(core, SIGNAL(contextChanged(Core::IContext*,Core::Context)),
this, SLOT(syncWithEditor(Core::IContext*)));
- const QSettings *s = core->settings();
- d->m_recentFiles = s->value(QLatin1String(settingsGroupC) + QLatin1Char('/') + QLatin1String(filesKeyC), QStringList()).toStringList();
- for (QStringList::iterator it = d->m_recentFiles.begin(); it != d->m_recentFiles.end(); ) {
- if (QFileInfo(*it).isFile()) {
- ++it;
- } else {
- it = d->m_recentFiles.erase(it);
- }
- }
- const QString directoryGroup = QLatin1String(directoryGroupC) + QLatin1Char('/');
- const QString settingsProjectDir = s->value(directoryGroup + QLatin1String(projectDirectoryKeyC),
- QString()).toString();
- if (!settingsProjectDir.isEmpty() && QFileInfo(settingsProjectDir).isDir()) {
- d->m_projectsDirectory = settingsProjectDir;
- } else {
- d->m_projectsDirectory = Utils::PathChooser::homePath();
- }
- d->m_useProjectsDirectory = s->value(directoryGroup + QLatin1String(useProjectDirectoryKeyC),
- d->m_useProjectsDirectory).toBool();
+ readSettings();
}
FileManager::~FileManager()
@@ -189,165 +187,178 @@ FileManager::~FileManager()
delete d;
}
+FileManager *FileManager::instance()
+{
+ return Internal::FileManagerPrivate::m_instance;
+}
+
/*!
\fn bool FileManager::addFiles(const QList<IFile *> &files, bool addWatcher)
Adds a list of IFile's to the collection. If \a addWatcher is true (the default),
the files are added to a file system watcher that notifies the file manager
about file changes.
-
- Returns true if the file specified by \a files have not been yet part of the file list.
*/
-bool FileManager::addFiles(const QList<IFile *> &files, bool addWatcher)
+void FileManager::addFiles(const QList<IFile *> &files, bool addWatcher)
{
if (!addWatcher) {
// We keep those in a separate list
- foreach(IFile *file, files)
- connect(file, SIGNAL(destroyed(QObject *)), this, SLOT(fileDestroyed(QObject *)));
-
- d->m_filesWithoutWatch.append(files);
- return true;
+ foreach (IFile *file, files) {
+ if (file && !d->m_filesWithoutWatch.contains(file)) {
+ connect(file, SIGNAL(destroyed(QObject *)), this, SLOT(fileDestroyed(QObject *)));
+ d->m_filesWithoutWatch.append(file);
+ }
+ }
+ return;
}
- bool filesAdded = false;
foreach (IFile *file, files) {
- if (!file)
- continue;
- const QString &fixedFileName = fixFileName(file->fileName());
- if (d->m_states.value(fixedFileName).lastUpdatedState.contains(file))
- continue;
- connect(file, SIGNAL(changed()), this, SLOT(checkForNewFileName()));
- connect(file, SIGNAL(destroyed(QObject *)), this, SLOT(fileDestroyed(QObject *)));
- filesAdded = true;
-
- addFileInfo(file);
+ if (file && !d->m_filesWithWatch.contains(file)) {
+ connect(file, SIGNAL(changed()), this, SLOT(checkForNewFileName()));
+ connect(file, SIGNAL(destroyed(QObject *)), this, SLOT(fileDestroyed(QObject *)));
+ addFileInfo(file);
+ }
}
- return filesAdded;
}
+/* Adds the IFile's file and possibly it's final link target to both m_states
+ (if it's file name is not empty), and the m_filesWithWatch list,
+ and adds a file watcher for each if not already done.
+ (The added file names are guaranteed to be absolute and cleaned.) */
void FileManager::addFileInfo(IFile *file)
{
- // We do want to insert the IFile into d->m_states even if the filename is empty
- // Such that m_states always contains all IFiles
-
- const QString fixedname = fixFileName(file->fileName());
- Internal::FileStateItem item;
- if (!fixedname.isEmpty()) {
- const QFileInfo fi(file->fileName());
- item.modified = fi.lastModified();
- item.permissions = fi.permissions();
- }
+ const QString fixedName = fixFileName(file->fileName(), KeepLinks);
+ const QString fixedResolvedName = fixFileName(file->fileName(), ResolveLinks);
+ addFileInfo(fixedResolvedName, file, false);
+ if (fixedName != fixedResolvedName)
+ addFileInfo(fixedName, file, true);
+}
- if (!d->m_states.contains(fixedname)) {
- d->m_states.insert(fixedname, Internal::FileState());
- if (!fixedname.isEmpty()) {
- d->m_fileWatcher->addPath(fixedname);
+/* only called from addFileInfo(IFile *) */
+void FileManager::addFileInfo(const QString &fileName, IFile *file, bool isLink)
+{
+ Internal::FileStateItem state;
+ if (!fileName.isEmpty()) {
+ const QFileInfo fi(fileName);
+ state.modified = fi.lastModified();
+ state.permissions = fi.permissions();
+ // Add watcher if we don't have that already
+ if (!d->m_states.contains(fileName)) {
+ d->m_states.insert(fileName, Internal::FileState());
+
+ if (isLink)
+ d->m_linkWatcher->addPath(fileName);
+ else
+ d->m_fileWatcher->addPath(fileName);
}
+ d->m_states[fileName].lastUpdatedState.insert(file, state);
}
-
- d->m_states[fixedname].lastUpdatedState.insert(file, item);
+ d->m_filesWithWatch[file].append(fileName); // inserts a new QStringList if not already there
}
+/* Updates the time stamp and permission information of the files
+ registered for this IFile (in m_filesWithWatch; can be the IFile's file + final link target) */
void FileManager::updateFileInfo(IFile *file)
{
- const QString fixedname = fixFileName(file->fileName());
- // If the filename is empty there's nothing to do
- if (fixedname.isEmpty())
- return;
- const QFileInfo fi(file->fileName());
-
- Internal::FileStateItem item;
- item.modified = fi.lastModified();
- item.permissions = fi.permissions();
-
- if (d->m_states.contains(fixedname) && d->m_states.value(fixedname).lastUpdatedState.contains(file))
- d->m_states[fixedname].lastUpdatedState.insert(file, item);
+ foreach (const QString &fileName, d->m_filesWithWatch.value(file)) {
+ // If the filename is empty there's nothing to do
+ if (fileName.isEmpty())
+ continue;
+ const QFileInfo fi(fileName);
+ Internal::FileStateItem item;
+ item.modified = fi.lastModified();
+ item.permissions = fi.permissions();
+ QTC_ASSERT(d->m_states.contains(fileName), continue);
+ QTC_ASSERT(d->m_states.value(fileName).lastUpdatedState.contains(file), continue);
+ d->m_states[fileName].lastUpdatedState.insert(file, item);
+ }
}
/// Dumps the state of the file manager's map
/// For debugging purposes
void FileManager::dump()
{
+ qDebug() << "======== dumping state map";
QMap<QString, Internal::FileState>::const_iterator it, end;
it = d->m_states.constBegin();
end = d->m_states.constEnd();
for (; it != end; ++it) {
- qDebug()<<" ";
qDebug() << it.key();
- qDebug() << it.value().expected.modified;
+ qDebug() << " expected:" << it.value().expected.modified;
QMap<IFile *, Internal::FileStateItem>::const_iterator jt, jend;
jt = it.value().lastUpdatedState.constBegin();
jend = it.value().lastUpdatedState.constEnd();
for (; jt != jend; ++jt) {
- qDebug() << jt.key() << jt.value().modified;
+ qDebug() << " " << jt.key()->fileName() << jt.value().modified;
}
}
-}
-
-void FileManager::renamedFile(const QString &from, QString &to)
-{
- QString fixedFrom = fixFileName(from);
- QString fixedTo = fixFileName(to);
- if (d->m_states.contains(fixedFrom)) {
- QTC_ASSERT(!d->m_states.contains(to), return);
- d->m_states.insert(fixedTo, d->m_states.value(fixedFrom));
- d->m_states.remove(fixedFrom);
- QFileInfo fi(to);
- d->m_states[fixedTo].expected.modified = fi.lastModified();
- d->m_states[fixedTo].expected.permissions = fi.permissions();
-
- d->m_fileWatcher->removePath(fixedFrom);
- d->m_fileWatcher->addPath(fixedTo);
-
- QMap<IFile *, Internal::FileStateItem>::iterator it, end;
- it = d->m_states[fixedTo].lastUpdatedState.begin();
- end = d->m_states[fixedTo].lastUpdatedState.end();
-
- for ( ; it != end; ++it) {
- d->m_blockedIFile = it.key();
- it.key()->rename(to);
- d->m_blockedIFile = it.key();
- it.value().modified = fi.lastModified();
- }
+ qDebug() << "------- dumping files with watch list";
+ foreach (IFile *key, d->m_filesWithWatch.keys()) {
+ qDebug() << key->fileName() << d->m_filesWithWatch.value(key);
}
+ qDebug() << "------- dumping watch list";
+ qDebug() << d->m_fileWatcher->files();
+ qDebug() << "------- dumping link watch list";
+ qDebug() << d->m_linkWatcher->files();
}
-///
-/// Does not use file->fileName, as such is save to use
-/// with renamed files and deleted files
-void FileManager::removeFileInfo(IFile *file)
+/*!
+ \fn void FileManager::renamedFile(const QString &from, QString &to)
+ \brief Tells the file manager that a file has been renamed on disk from within Qt Creator.
+
+ Needs to be called right after the actual renaming on disk (i.e. before the file system
+ watcher can report the event during the next event loop run). \a from needs to be an absolute file path.
+ This will notify all IFile objects pointing to that file of the rename
+ by calling IFile::rename, and update the cached time and permission
+ information to avoid annoying the user with "file has been removed"
+ popups.
+*/
+void FileManager::renamedFile(const QString &from, const QString &to)
{
- QString fileName;
- QMap<QString, Internal::FileState>::const_iterator it, end;
- end = d->m_states.constEnd();
- for (it = d->m_states.constBegin(); it != end; ++it) {
- if (it.value().lastUpdatedState.contains(file)) {
- fileName = it.key();
- break;
- }
+ const QString &fixedFrom = fixFileName(from, KeepLinks);
+
+ // gather the list of IFiles
+ QList<IFile *> filesToRename;
+ QMapIterator<IFile *, QStringList> it(d->m_filesWithWatch);
+ while (it.hasNext()) {
+ it.next();
+ if (it.value().contains(fixedFrom))
+ filesToRename.append(it.key());
}
- removeFileInfo(fileName, file);
+ // rename the IFiles
+ foreach (IFile *file, filesToRename) {
+ d->m_blockedIFile = file;
+ removeFileInfo(file);
+ file->rename(to);
+ addFileInfo(file);
+ d->m_blockedIFile = 0;
+ }
}
-void FileManager::removeFileInfo(const QString &fileName, IFile *file)
+/* Removes all occurrances of the IFile from m_filesWithWatch and m_states.
+ If that results in a file no longer being referenced by any IFile, this
+ also removes the file watcher.
+*/
+void FileManager::removeFileInfo(IFile *file)
{
- const QString &fixedName = fixFileName(fileName);
- if (d->m_states[fixedName].lastUpdatedState.contains(file)) {
- d->m_states[fixedName].lastUpdatedState.remove(file);
-
- if (d->m_states.value(fixedName).lastUpdatedState.isEmpty()) {
- d->m_states.remove(fixedName);
- if (!fixedName.isEmpty()) {
- d->m_fileWatcher->removePath(fixedName);
- }
+ if (!d->m_filesWithWatch.contains(file))
+ return;
+ foreach (const QString &fileName, d->m_filesWithWatch.value(file)) {
+ if (!d->m_states.contains(fileName))
+ continue;
+ d->m_states[fileName].lastUpdatedState.remove(file);
+ if (d->m_states.value(fileName).lastUpdatedState.isEmpty()) {
+ if (d->m_fileWatcher->files().contains(fileName))
+ d->m_fileWatcher->removePath(fileName);
+ if (d->m_linkWatcher->files().contains(fileName))
+ d->m_linkWatcher->removePath(fileName);
+ d->m_states.remove(fileName);
}
- } else {
- // We could not find the fileinfo, try harder to remove it
- removeFileInfo(file);
}
+ d->m_filesWithWatch.remove(file);
}
/*!
@@ -356,17 +367,14 @@ void FileManager::removeFileInfo(const QString &fileName, IFile *file)
Adds a IFile object to the collection. If \a addWatcher is true (the default),
the file is added to a file system watcher that notifies the file manager
about file changes.
-
- Returns true if the file specified by \a file has not been yet part of the file list.
*/
-bool FileManager::addFile(IFile *file, bool addWatcher)
+void FileManager::addFile(IFile *file, bool addWatcher)
{
- return addFiles(QList<IFile *>() << file, addWatcher);
+ addFiles(QList<IFile *>() << file, addWatcher);
}
void FileManager::fileDestroyed(QObject *obj)
{
- // removeFileInfo works even if the file does not really exist anymore
IFile *file = static_cast<IFile*>(obj);
// Check the special unwatched first:
if (d->m_filesWithoutWatch.contains(file)) {
@@ -383,25 +391,24 @@ void FileManager::fileDestroyed(QObject *obj)
Returns true if the file specified by \a file has been part of the file list.
*/
-bool FileManager::removeFile(IFile *file)
+void FileManager::removeFile(IFile *file)
{
- if (!file)
- return false;
+ QTC_ASSERT(file, return);
// Special casing unwatched files
if (d->m_filesWithoutWatch.contains(file)) {
disconnect(file, SIGNAL(destroyed(QObject *)), this, SLOT(fileDestroyed(QObject *)));
d->m_filesWithoutWatch.removeOne(file);
- return true;
+ return;
}
+ removeFileInfo(file);
disconnect(file, SIGNAL(changed()), this, SLOT(checkForNewFileName()));
disconnect(file, SIGNAL(destroyed(QObject *)), this, SLOT(fileDestroyed(QObject *)));
-
- removeFileInfo(file->fileName(), file);
- return true;
}
+/* Slot reacting on IFile::changed. We need to check if the signal was sent
+ because the file was saved under different name. */
void FileManager::checkForNewFileName()
{
IFile *file = qobject_cast<IFile *>(sender());
@@ -410,32 +417,33 @@ void FileManager::checkForNewFileName()
if (file == d->m_blockedIFile)
return;
QTC_ASSERT(file, return);
- const QString &fileName = fixFileName(file->fileName());
-
- // check if the IFile is in the map
- if (d->m_states.value(fileName).lastUpdatedState.contains(file)) {
- // the file might have been deleted and written again, so guard against that
- d->m_fileWatcher->removePath(fileName);
- d->m_fileWatcher->addPath(fileName);
- updateFileInfo(file);
- return;
- }
+ QTC_ASSERT(d->m_filesWithWatch.contains(file), return);
- // Probably the name has changed...
+ // Maybe the name has changed or file has been deleted and created again ...
// This also updates the state to the on disk state
removeFileInfo(file);
addFileInfo(file);
}
-// TODO Rename to nativeFileName
-QString FileManager::fixFileName(const QString &fileName)
+/*!
+ \fn QString FileManager::fixFileName(const QString &fileName, FixMode fixmode)
+ Returns a guaranteed cleaned path in native form. If the file exists,
+ it will either be a cleaned absolute file path (fixmode == KeepLinks), or
+ a cleaned canonical file path (fixmode == ResolveLinks).
+*/
+QString FileManager::fixFileName(const QString &fileName, FixMode fixmode)
{
QString s = fileName;
QFileInfo fi(s);
- if (!fi.exists())
- s = QDir::toNativeSeparators(s);
- else
- s = QDir::toNativeSeparators(fi.canonicalFilePath());
+ if (fi.exists()) {
+ if (fixmode == ResolveLinks)
+ s = fi.canonicalFilePath();
+ else
+ s = QDir::cleanPath(fi.absoluteFilePath());
+ } else {
+ s = QDir::cleanPath(s);
+ }
+ s = QDir::toNativeSeparators(s);
#ifdef Q_OS_WIN
s = s.toLower();
#endif
@@ -443,21 +451,6 @@ QString FileManager::fixFileName(const QString &fileName)
}
/*!
- \fn bool FileManager::isFileManaged(const QString &fileName) const
-
- Returns true if at least one IFile in the set points to \a fileName.
-*/
-bool FileManager::isFileManaged(const QString &fileName) const
-{
- if (fileName.isEmpty())
- return false;
-
- // TOOD check d->m_filesWithoutWatch
-
- return !d->m_states.contains(fixFileName(fileName));
-}
-
-/*!
\fn QList<IFile*> FileManager::modifiedFiles() const
Returns the list of IFile's that have been modified.
@@ -466,16 +459,11 @@ QList<IFile *> FileManager::modifiedFiles() const
{
QList<IFile *> modifiedFiles;
- QMap<QString, Internal::FileState>::const_iterator it, end;
- end = d->m_states.constEnd();
- for(it = d->m_states.constBegin(); it != end; ++it) {
- QMap<IFile *, Internal::FileStateItem>::const_iterator jt, jend;
- jt = (*it).lastUpdatedState.constBegin();
- jend = (*it).lastUpdatedState.constEnd();
- for( ; jt != jend; ++jt)
- if (jt.key()->isModified())
- modifiedFiles << jt.key();
+ foreach (IFile *file, d->m_filesWithWatch.keys()) {
+ if (file->isModified())
+ modifiedFiles << file;
}
+
foreach(IFile *file, d->m_filesWithoutWatch) {
if (file->isModified())
modifiedFiles << file;
@@ -513,7 +501,8 @@ void FileManager::unblockFileChange(IFile *file)
// If so then it's a expected change
updateFileInfo(file);
- updateExpectedState(fixFileName(file->fileName()));
+ foreach (const QString &fileName, d->m_filesWithWatch.value(file))
+ updateExpectedState(fileName);
}
/*!
@@ -543,18 +532,24 @@ void FileManager::unexpectFileChange(const QString &fileName)
// is the same as the saved one here
// If so then it's a expected change
- updateExpectedState(fileName);
+ if (fileName.isEmpty())
+ return;
+ const QString fixedName = fixFileName(fileName, KeepLinks);
+ updateExpectedState(fixedName);
+ const QString fixedResolvedName = fixFileName(fileName, ResolveLinks);
+ if (fixedName != fixedResolvedName)
+ updateExpectedState(fixedResolvedName);
}
+/* only called from unblock and unexpect file change methods */
void FileManager::updateExpectedState(const QString &fileName)
{
- const QString &fixedName = fixFileName(fileName);
- if (fixedName.isEmpty())
+ if (fileName.isEmpty())
return;
- QFileInfo fi(fixedName);
- if (d->m_states.contains(fixedName)) {
- d->m_states[fixedName].expected.modified = fi.lastModified();
- d->m_states[fixedName].expected.permissions = fi.permissions();
+ if (d->m_states.contains(fileName)) {
+ QFileInfo fi(fileName);
+ d->m_states[fileName].expected.modified = fi.lastModified();
+ d->m_states[fileName].expected.permissions = fi.permissions();
}
}
@@ -588,15 +583,6 @@ QList<IFile *> FileManager::saveModifiedFiles(const QList<IFile *> &files,
return saveModifiedFiles(files, cancelled, false, message, alwaysSaveMessage, alwaysSave);
}
-static QMessageBox::StandardButton skipFailedPrompt(QWidget *parent, const QString &fileName)
-{
- return QMessageBox::question(parent,
- FileManager::tr("Cannot save file"),
- FileManager::tr("Cannot save changes to '%1'. Do you want to continue and lose your changes?").arg(fileName),
- QMessageBox::YesToAll| QMessageBox::Yes|QMessageBox::No,
- QMessageBox::No);
-}
-
QList<IFile *> FileManager::saveModifiedFiles(const QList<IFile *> &files,
bool *cancelled,
bool silently,
@@ -648,46 +634,11 @@ QList<IFile *> FileManager::saveModifiedFiles(const QList<IFile *> &files,
filesToSave = dia.itemsToSave();
}
- bool yestoall = false;
- Core::VCSManager *vcsManager = Core::ICore::instance()->vcsManager();
foreach (IFile *file, filesToSave) {
- if (file->isReadOnly()) {
- const QString directory = QFileInfo(file->fileName()).absolutePath();
- if (IVersionControl *versionControl = vcsManager->findVersionControlForDirectory(directory))
- versionControl->vcsOpen(file->fileName());
- }
- if (!file->isReadOnly() && !file->fileName().isEmpty()) {
- blockFileChange(file);
- const bool ok = file->save();
- unblockFileChange(file);
- if (!ok)
- notSaved.append(file);
- } else if (QFile::exists(file->fileName()) && !file->isSaveAsAllowed()) {
- if (yestoall)
- continue;
- const QFileInfo fi(file->fileName());
- switch (skipFailedPrompt(d->m_mainWindow, fi.fileName())) {
- case QMessageBox::YesToAll:
- yestoall = true;
- break;
- case QMessageBox::No:
- if (cancelled)
- *cancelled = true;
- return filesToSave;
- default:
- break;
- }
- } else {
- QString fileName = getSaveAsFileName(file);
- bool ok = false;
- if (!fileName.isEmpty()) {
- blockFileChange(file);
- ok = file->save(fileName);
- file->checkPermissions();
- unblockFileChange(file);
- }
- if (!ok)
- notSaved.append(file);
+ if (!EditorManager::instance()->saveFile(file)) {
+ if (cancelled)
+ *cancelled = true;
+ notSaved.append(file);
}
}
}
@@ -801,6 +752,8 @@ QStringList FileManager::getOpenFileNames(const QString &filters,
if (path.isEmpty()) {
if (!d->m_currentFile.isEmpty())
path = QFileInfo(d->m_currentFile).absoluteFilePath();
+ if (path.isEmpty() && useProjectsDirectory())
+ path = projectsDirectory();
}
const QStringList files = QFileDialog::getOpenFileNames(d->m_mainWindow,
tr("Open File"),
@@ -811,14 +764,54 @@ QStringList FileManager::getOpenFileNames(const QString &filters,
return files;
}
+FileManager::ReadOnlyAction
+ FileManager::promptReadOnlyFile(const QString &fileName,
+ const IVersionControl *versionControl,
+ QWidget *parent,
+ bool displaySaveAsButton)
+{
+ // Version Control: If automatic open is desired, open right away.
+ bool promptVCS = false;
+ if (versionControl && versionControl->supportsOperation(IVersionControl::OpenOperation)) {
+ if (versionControl->settingsFlags() & IVersionControl::AutoOpen)
+ return RO_OpenVCS;
+ promptVCS = true;
+ }
+
+ // Create message box.
+ QMessageBox msgBox(QMessageBox::Question, tr("File is Read Only"),
+ tr("The file <i>%1</i> is read only.").arg(QDir::toNativeSeparators(fileName)),
+ QMessageBox::Cancel, parent);
+
+ QPushButton *vcsButton = 0;
+ if (promptVCS)
+ vcsButton = msgBox.addButton(tr("Open with VCS (%1)").arg(versionControl->displayName()), QMessageBox::AcceptRole);
+
+ QPushButton *makeWritableButton = msgBox.addButton(tr("Make writable"), QMessageBox::AcceptRole);
+
+ QPushButton *saveAsButton = 0;
+ if (displaySaveAsButton)
+ saveAsButton = msgBox.addButton(tr("Save as ..."), QMessageBox::ActionRole);
+
+ msgBox.setDefaultButton(vcsButton ? vcsButton : makeWritableButton);
+ msgBox.exec();
+
+ QAbstractButton *clickedButton = msgBox.clickedButton();
+ if (clickedButton == vcsButton)
+ return RO_OpenVCS;
+ if (clickedButton == makeWritableButton)
+ return RO_MakeWriteable;
+ if (displaySaveAsButton && clickedButton == saveAsButton)
+ return RO_SaveAs;
+ return RO_Cancel;
+}
void FileManager::changedFile(const QString &fileName)
{
const bool wasempty = d->m_changedFiles.isEmpty();
- const QString &fixedName = fixFileName(fileName);
- if (!d->m_changedFiles.contains(fixedName))
- d->m_changedFiles.append(fixedName);
+ if (!d->m_changedFiles.contains(fileName) && d->m_states.contains(fileName))
+ d->m_changedFiles.append(fileName);
if (wasempty && !d->m_changedFiles.isEmpty()) {
QTimer::singleShot(200, this, SLOT(checkForReload()));
@@ -835,6 +828,8 @@ void FileManager::mainWindowActivated()
void FileManager::checkForReload()
{
+ if (d->m_changedFiles.isEmpty())
+ return;
if (QApplication::activeWindow() != d->m_mainWindow)
return;
@@ -848,120 +843,154 @@ void FileManager::checkForReload()
QList<IEditor*> editorsToClose;
QMap<IFile*, QString> filesToSave;
- QStringList modifiedFileNames;
+
+ // collect file information
+ QMap<QString, Internal::FileStateItem> currentStates;
+ QMap<QString, IFile::ChangeType> changeTypes;
+ QSet<IFile *> changedIFiles;
foreach (const QString &fileName, d->m_changedFiles) {
- // Get the information from the filesystem
- IFile::ChangeTrigger behavior = IFile::TriggerExternal;
IFile::ChangeType type = IFile::TypeContents;
+ Internal::FileStateItem state;
QFileInfo fi(fileName);
if (!fi.exists()) {
type = IFile::TypeRemoved;
} else {
- modifiedFileNames << fileName;
- if (fi.lastModified() == d->m_states.value(fileName).expected.modified
- && fi.permissions() == d->m_states.value(fileName).expected.permissions) {
- behavior = IFile::TriggerInternal;
- }
+ state.modified = fi.lastModified();
+ state.permissions = fi.permissions();
}
+ currentStates.insert(fileName, state);
+ changeTypes.insert(fileName, type);
+ foreach (IFile *file, d->m_states.value(fileName).lastUpdatedState.keys())
+ changedIFiles.insert(file);
+ }
- const QMap<IFile *, Internal::FileStateItem> &lastUpdated =
- d->m_states.value(fileName).lastUpdatedState;
- QMap<IFile *, Internal::FileStateItem>::const_iterator it, end;
- it = lastUpdated.constBegin();
- end = lastUpdated.constEnd();
- for ( ; it != end; ++it) {
- IFile *file = it.key();
- d->m_blockedIFile = file;
- // Compare
- if (it.value().modified == fi.lastModified()
- && it.value().permissions == fi.permissions()) {
- // Already up to date
+ // handle the IFiles
+ foreach (IFile *file, changedIFiles) {
+ IFile::ChangeTrigger behavior = IFile::TriggerInternal;
+ IFile::ChangeType type = IFile::TypePermissions;
+ bool changed = false;
+ // find out the type & behavior from the two possible files
+ // behavior is internal if all changes are expected (and none removed)
+ // type is "max" of both types (remove > contents > permissions)
+ foreach (const QString & fileName, d->m_filesWithWatch.value(file)) {
+ // was the file reported?
+ if (!currentStates.contains(fileName))
continue;
+
+ Internal::FileStateItem currentState = currentStates.value(fileName);
+ Internal::FileStateItem expectedState = d->m_states.value(fileName).expected;
+ Internal::FileStateItem lastState = d->m_states.value(fileName).lastUpdatedState.value(file);
+ // did the file actually change?
+ if (lastState.modified == currentState.modified && lastState.permissions == currentState.permissions)
+ continue;
+ changed = true;
+
+ // was it only a permission change?
+ if (lastState.modified == currentState.modified)
+ continue;
+
+ // was the change unexpected?
+ if (currentState.modified != expectedState.modified || currentState.permissions != expectedState.permissions) {
+ behavior = IFile::TriggerExternal;
}
- // we've got some modification
- // check if it's contents or permissions:
- if (it.value().modified == fi.lastModified()) {
- // Only permission change
- file->reload(IFile::FlagReload, IFile::TypePermissions);
- // now we know it's a content change or file was removed
- } else if (defaultBehavior == IFile::ReloadUnmodified
- && type == IFile::TypeContents && !file->isModified()) {
- // content change, but unmodified (and settings say to reload in this case)
+
+ // find out the type
+ IFile::ChangeType fileChange = changeTypes.value(fileName);
+ if (fileChange == IFile::TypeRemoved) {
+ type = IFile::TypeRemoved;
+ behavior = IFile::TriggerExternal; // removed files always trigger externally
+ } else if (fileChange == IFile::TypeContents && type == IFile::TypePermissions) {
+ type = IFile::TypeContents;
+ }
+ }
+
+ if (!changed) // probably because the change was blocked with (un)blockFileChange
+ continue;
+
+ // handle it!
+ d->m_blockedIFile = file;
+
+ // we've got some modification
+ // check if it's contents or permissions:
+ if (type == IFile::TypePermissions) {
+ // Only permission change
+ file->reload(IFile::FlagReload, IFile::TypePermissions);
+ // now we know it's a content change or file was removed
+ } else if (defaultBehavior == IFile::ReloadUnmodified
+ && type == IFile::TypeContents && !file->isModified()) {
+ // content change, but unmodified (and settings say to reload in this case)
+ file->reload(IFile::FlagReload, type);
+ // file was removed or it's a content change and the default behavior for
+ // unmodified files didn't kick in
+ } else if (defaultBehavior == IFile::IgnoreAll) {
+ // content change or removed, but settings say ignore
+ file->reload(IFile::FlagIgnore, type);
+ // either the default behavior is to always ask,
+ // or the ReloadUnmodified default behavior didn't kick in,
+ // so do whatever the IFile wants us to do
+ } else {
+ // check if IFile wants us to ask
+ if (file->reloadBehavior(behavior, type) == IFile::BehaviorSilent) {
+ // content change or removed, IFile wants silent handling
file->reload(IFile::FlagReload, type);
- // file was removed or it's a content change and the default behavior for
- // unmodified files didn't kick in
- } else if (defaultBehavior == IFile::IgnoreAll) {
- // content change or removed, but settings say ignore
- file->reload(IFile::FlagIgnore, type);
- // either the default behavior is to always ask,
- // or the ReloadUnmodified default behavior didn't kick in,
- // so do whatever the IFile wants us to do
- } else {
- // check if IFile wants us to ask
- if (file->reloadBehavior(behavior, type) == IFile::BehaviorSilent) {
- // content change or removed, IFile wants silent handling
- file->reload(IFile::FlagReload, type);
- // IFile wants us to ask
- } else if (type == IFile::TypeContents) {
- // content change, IFile wants to ask user
- if (previousAnswer == Utils::ReloadNone) {
- // answer already given, ignore
- file->reload(IFile::FlagIgnore, IFile::TypeContents);
- } else if (previousAnswer == Utils::ReloadAll) {
- // answer already given, reload
+ // IFile wants us to ask
+ } else if (type == IFile::TypeContents) {
+ // content change, IFile wants to ask user
+ if (previousAnswer == Utils::ReloadNone) {
+ // answer already given, ignore
+ file->reload(IFile::FlagIgnore, IFile::TypeContents);
+ } else if (previousAnswer == Utils::ReloadAll) {
+ // answer already given, reload
+ file->reload(IFile::FlagReload, IFile::TypeContents);
+ } else {
+ // Ask about content change
+ previousAnswer = Utils::reloadPrompt(file->fileName(), file->isModified(), QApplication::activeWindow());
+ switch (previousAnswer) {
+ case Utils::ReloadAll:
+ case Utils::ReloadCurrent:
file->reload(IFile::FlagReload, IFile::TypeContents);
- } else {
- // Ask about content change
- previousAnswer = Utils::reloadPrompt(fileName, file->isModified(), QApplication::activeWindow());
- switch (previousAnswer) {
- case Utils::ReloadAll:
- case Utils::ReloadCurrent:
- file->reload(IFile::FlagReload, IFile::TypeContents);
- break;
- case Utils::ReloadSkipCurrent:
- case Utils::ReloadNone:
- file->reload(IFile::FlagIgnore, IFile::TypeContents);
- break;
- }
+ break;
+ case Utils::ReloadSkipCurrent:
+ case Utils::ReloadNone:
+ file->reload(IFile::FlagIgnore, IFile::TypeContents);
+ break;
}
- // IFile wants us to ask, and it's the TypeRemoved case
- } else {
- // Ask about removed file
- bool unhandled = true;
- while (unhandled) {
- switch (Utils::fileDeletedPrompt(fileName, QApplication::activeWindow())) {
- case Utils::FileDeletedSave:
- filesToSave.insert(file, fileName);
- unhandled = false;
- break;
- case Utils::FileDeletedSaveAs:
- {
- const QString &saveFileName = getSaveAsFileName(file);
- if (!saveFileName.isEmpty()) {
- filesToSave.insert(file, saveFileName);
- unhandled = false;
- }
- break;
- }
- case Utils::FileDeletedClose:
- editorsToClose << EditorManager::instance()->editorsForFile(file);
+ }
+ // IFile wants us to ask, and it's the TypeRemoved case
+ } else {
+ // Ask about removed file
+ bool unhandled = true;
+ while (unhandled) {
+ switch (Utils::fileDeletedPrompt(file->fileName(), QApplication::activeWindow())) {
+ case Utils::FileDeletedSave:
+ filesToSave.insert(file, file->fileName());
+ unhandled = false;
+ break;
+ case Utils::FileDeletedSaveAs:
+ {
+ const QString &saveFileName = getSaveAsFileName(file);
+ if (!saveFileName.isEmpty()) {
+ filesToSave.insert(file, saveFileName);
unhandled = false;
- break;
}
+ break;
+ }
+ case Utils::FileDeletedClose:
+ editorsToClose << EditorManager::instance()->editorsForFile(file);
+ unhandled = false;
+ break;
}
}
}
-
- updateFileInfo(file);
- d->m_blockedIFile = 0;
}
- }
- // cleanup
- if (!modifiedFileNames.isEmpty()) {
- d->m_fileWatcher->removePaths(modifiedFileNames);
- d->m_fileWatcher->addPaths(modifiedFileNames);
+ // update file info, also handling if e.g. link target has changed
+ removeFileInfo(file);
+ addFileInfo(file);
+ d->m_blockedIFile = 0;
}
+
+ // clean up
d->m_changedFiles.clear();
// handle deleted files
@@ -976,6 +1005,8 @@ void FileManager::checkForReload()
}
d->m_blockActivated = false;
+
+// dump();
}
void FileManager::syncWithEditor(Core::IContext *context)
@@ -990,19 +1021,28 @@ void FileManager::syncWithEditor(Core::IContext *context)
}
/*!
- \fn void FileManager::addToRecentFiles(const QString &fileName)
+ \fn void FileManager::addToRecentFiles(const QString &fileName, , const QString &editorId)
- Adds the \a fileName to the list of recent files.
+ Adds the \a fileName to the list of recent files. Associates the file to
+ be reopened with an editor of the given \a editorId, if possible.
+ \a editorId defaults to the empty id, which means to let the system figure out
+ the best editor itself.
*/
-void FileManager::addToRecentFiles(const QString &fileName)
+void FileManager::addToRecentFiles(const QString &fileName, const QString &editorId)
{
if (fileName.isEmpty())
return;
- QString prettyFileName(QDir::toNativeSeparators(fileName));
- d->m_recentFiles.removeAll(prettyFileName);
+ QString unifiedForm(fixFileName(fileName, KeepLinks));
+ QMutableListIterator<RecentFile > it(d->m_recentFiles);
+ while (it.hasNext()) {
+ RecentFile file = it.next();
+ QString recentUnifiedForm(fixFileName(file.first, KeepLinks));
+ if (unifiedForm == recentUnifiedForm)
+ it.remove();
+ }
if (d->m_recentFiles.count() > d->m_maxRecentFiles)
d->m_recentFiles.removeLast();
- d->m_recentFiles.prepend(prettyFileName);
+ d->m_recentFiles.prepend(RecentFile(fileName, editorId));
}
/*!
@@ -1010,16 +1050,24 @@ void FileManager::addToRecentFiles(const QString &fileName)
Returns the list of recent files.
*/
-QStringList FileManager::recentFiles() const
+QList<FileManager::RecentFile> FileManager::recentFiles() const
{
return d->m_recentFiles;
}
-void FileManager::saveRecentFiles()
+void FileManager::saveSettings()
{
+ QStringList recentFiles;
+ QStringList recentEditorIds;
+ foreach (const RecentFile &file, d->m_recentFiles) {
+ recentFiles.append(file.first);
+ recentEditorIds.append(file.second);
+ }
+
QSettings *s = Core::ICore::instance()->settings();
s->beginGroup(QLatin1String(settingsGroupC));
- s->setValue(QLatin1String(filesKeyC), d->m_recentFiles);
+ s->setValue(QLatin1String(filesKeyC), recentFiles);
+ s->setValue(QLatin1String(editorsKeyC), recentEditorIds);
s->endGroup();
s->beginGroup(QLatin1String(directoryGroupC));
s->setValue(QLatin1String(projectDirectoryKeyC), d->m_projectsDirectory);
@@ -1027,6 +1075,38 @@ void FileManager::saveRecentFiles()
s->endGroup();
}
+void FileManager::readSettings()
+{
+ QSettings *s = Core::ICore::instance()->settings();
+ d->m_recentFiles.clear();
+ s->beginGroup(QLatin1String(settingsGroupC));
+ QStringList recentFiles = s->value(QLatin1String(filesKeyC)).toStringList();
+ QStringList recentEditorIds = s->value(QLatin1String(editorsKeyC)).toStringList();
+ s->endGroup();
+ // clean non-existing files
+ QStringListIterator ids(recentEditorIds);
+ foreach (const QString &fileName, recentFiles) {
+ QString editorId;
+ if (ids.hasNext()) // guard against old or weird settings
+ editorId = ids.next();
+ if (QFileInfo(fileName).isFile())
+ d->m_recentFiles.append(RecentFile(QDir::fromNativeSeparators(fileName), // from native to guard against old settings
+ editorId));
+ }
+
+ s->beginGroup(QLatin1String(directoryGroupC));
+ const QString settingsProjectDir = s->value(QLatin1String(projectDirectoryKeyC),
+ QString()).toString();
+ if (!settingsProjectDir.isEmpty() && QFileInfo(settingsProjectDir).isDir()) {
+ d->m_projectsDirectory = settingsProjectDir;
+ } else {
+ d->m_projectsDirectory = Utils::PathChooser::homePath();
+ }
+ d->m_useProjectsDirectory = s->value(QLatin1String(useProjectDirectoryKeyC),
+ d->m_useProjectsDirectory).toBool();
+ s->endGroup();
+}
+
/*!
The current file is e.g. the file currently opened when an editor is active,
diff --git a/src/plugins/coreplugin/filemanager.h b/src/plugins/coreplugin/filemanager.h
index 86c53e6434..442b794292 100644
--- a/src/plugins/coreplugin/filemanager.h
+++ b/src/plugins/coreplugin/filemanager.h
@@ -38,6 +38,8 @@
#include <QtCore/QObject>
#include <QtCore/QStringList>
+#include <QtCore/QPair>
+#include <QtCore/QVariant>
QT_BEGIN_NAMESPACE
class QMainWindow;
@@ -48,6 +50,7 @@ namespace Core {
class ICore;
class IContext;
class IFile;
+class IVersionControl;
namespace Internal {
struct FileManagerPrivate;
@@ -57,17 +60,25 @@ class CORE_EXPORT FileManager : public QObject
{
Q_OBJECT
public:
+ enum FixMode {
+ ResolveLinks,
+ KeepLinks
+ };
+
+ typedef QPair<QString, QString> RecentFile;
+
explicit FileManager(QMainWindow *ew);
virtual ~FileManager();
+ static FileManager *instance();
+
// file pool to monitor
- bool addFiles(const QList<IFile *> &files, bool addWatcher = true);
- bool addFile(IFile *file, bool addWatcher = true);
- bool removeFile(IFile *file);
- bool isFileManaged(const QString &fileName) const;
+ void addFiles(const QList<IFile *> &files, bool addWatcher = true);
+ void addFile(IFile *file, bool addWatcher = true);
+ void removeFile(IFile *file);
QList<IFile *> modifiedFiles() const;
- void renamedFile(const QString &from, QString &to);
+ void renamedFile(const QString &from, const QString &to);
void blockFileChange(IFile *file);
void unblockFileChange(IFile *file);
@@ -76,17 +87,16 @@ public:
void unexpectFileChange(const QString &fileName);
// recent files
- void addToRecentFiles(const QString &fileName);
- QStringList recentFiles() const;
- void saveRecentFiles();
-
+ void addToRecentFiles(const QString &fileName, const QString &editorId = QString());
+ QList<RecentFile> recentFiles() const;
+ void saveSettings();
// current file
void setCurrentFile(const QString &filePath);
QString currentFile() const;
// helper methods
- static QString fixFileName(const QString &fileName);
+ static QString fixFileName(const QString &fileName, FixMode fixmode);
QStringList getOpenFileNames(const QString &filters,
const QString path = QString(),
@@ -106,6 +116,14 @@ public:
bool *alwaysSave = 0);
+ // Helper to display a message dialog when encountering a read-only
+ // file, prompting the user about how to make it writeable.
+ enum ReadOnlyAction { RO_Cancel, RO_OpenVCS, RO_MakeWriteable, RO_SaveAs };
+ static ReadOnlyAction promptReadOnlyFile(const QString &fileName,
+ const IVersionControl *versionControl,
+ QWidget *parent,
+ bool displaySaveAsButton = false);
+
QString fileDialogLastVisitedDirectory() const;
void setFileDialogLastVisitedDirectory(const QString &);
@@ -137,13 +155,12 @@ private slots:
void syncWithEditor(Core::IContext *context);
private:
+ void readSettings();
void dump();
void addFileInfo(IFile *file);
+ void addFileInfo(const QString &fileName, IFile *file, bool isLink);
void removeFileInfo(IFile *file);
- void removeFileInfo(const QString &fileName, IFile *file);
- void addWatch(const QString &filename);
- void removeWatch(const QString &filename);
void updateFileInfo(IFile *file);
void updateExpectedState(const QString &fileName);
@@ -174,4 +191,6 @@ private:
} // namespace Core
+Q_DECLARE_METATYPE(Core::FileManager::RecentFile)
+
#endif // FILEMANAGER_H
diff --git a/src/plugins/coreplugin/generalsettings.cpp b/src/plugins/coreplugin/generalsettings.cpp
index 991c6454a2..33ea238300 100644
--- a/src/plugins/coreplugin/generalsettings.cpp
+++ b/src/plugins/coreplugin/generalsettings.cpp
@@ -49,7 +49,6 @@
#include <QtCore/QDir>
#include <QtCore/QLibraryInfo>
#include <QtCore/QSettings>
-#include <QtCore/QTextCodec>
#include "ui_generalsettings.h"
@@ -58,7 +57,7 @@ using namespace Core::Internal;
GeneralSettings::GeneralSettings():
- m_dialog(0)
+ m_page(0), m_dialog(0)
{
}
@@ -130,36 +129,9 @@ QWidget *GeneralSettings::createPage(QWidget *parent)
m_page->setupUi(w);
QSettings* settings = Core::ICore::instance()->settings();
- fillLanguageBox();
+ Q_UNUSED(settings) // Windows
- QTextCodec *defaultTextCodec = QTextCodec::codecForLocale();
- if (QTextCodec *candidate = QTextCodec::codecForName(
- settings->value(QLatin1String("General/DefaultFileEncoding")).toByteArray()))
- defaultTextCodec = candidate;
-
- QList<int> mibs = QTextCodec::availableMibs();
- qSort(mibs);
- QList<int> sortedMibs;
- foreach (int mib, mibs)
- if (mib >= 0)
- sortedMibs += mib;
- foreach (int mib, mibs)
- if (mib < 0)
- sortedMibs += mib;
- int i = 0;
- foreach (int mib, sortedMibs) {
- QTextCodec *codec = QTextCodec::codecForMib(mib);
- m_codecs += codec;
- QString name = codec->name();
- foreach (const QByteArray &alias, codec->aliases()) {
- name += QLatin1String(" / ");
- name += QString::fromLatin1(alias);
- }
- m_page->encodingBox->addItem(name);
- if (defaultTextCodec == codec)
- m_page->encodingBox->setCurrentIndex(i);
- i++;
- }
+ fillLanguageBox();
m_page->colorButton->setColor(StyleHelper::requestedBaseColor());
m_page->externalEditorEdit->setText(EditorManager::instance()->externalEditor());
@@ -199,9 +171,15 @@ QWidget *GeneralSettings::createPage(QWidget *parent)
#endif
if (m_searchKeywords.isEmpty()) {
- QTextStream(&m_searchKeywords) << m_page->colorLabel->text() << ' '
- << m_page->terminalLabel->text() << ' ' << m_page->editorLabel->text()
- << ' '<< m_page->modifiedLabel->text();
+ QLatin1Char sep(' ');
+ QTextStream(&m_searchKeywords)
+ << m_page->interfaceBox->title() << sep
+ << m_page->colorLabel->text() << sep
+ << m_page->languageLabel->text() << sep
+ << m_page->systemBox->title() << sep
+ << m_page->terminalLabel->text() << sep
+ << m_page->editorLabel->text() << sep
+ << m_page->modifiedLabel->text();
m_searchKeywords.remove(QLatin1Char('&'));
}
return w;
@@ -214,6 +192,8 @@ bool GeneralSettings::matches(const QString &s) const
void GeneralSettings::apply()
{
+ if (!m_page) // wasn't shown, can't be changed
+ return;
int currentIndex = m_page->languageBox->currentIndex();
setLanguage(m_page->languageBox->itemData(currentIndex, Qt::UserRole).toString());
// Apply the new base color if accepted
@@ -227,16 +207,14 @@ void GeneralSettings::apply()
Utils::UnixUtils::setFileBrowser(Core::ICore::instance()->settings(), m_page->externalFileBrowserEdit->text());
#endif
#endif
-
- QSettings* settings = Core::ICore::instance()->settings();
- return settings->setValue(QLatin1String("General/DefaultFileEncoding"),
- m_codecs.at(m_page->encodingBox->currentIndex())->name());
-
}
void GeneralSettings::finish()
{
+ if (!m_page) // page was never shown
+ return;
delete m_page;
+ m_page = 0;
}
void GeneralSettings::resetInterfaceColor()
diff --git a/src/plugins/coreplugin/generalsettings.h b/src/plugins/coreplugin/generalsettings.h
index 4d21f59ef1..2b6a49c6ef 100644
--- a/src/plugins/coreplugin/generalsettings.h
+++ b/src/plugins/coreplugin/generalsettings.h
@@ -86,7 +86,6 @@ private:
Ui::GeneralSettings *m_page;
QString m_searchKeywords;
QPointer<QMessageBox> m_dialog;
- QList<QTextCodec *> m_codecs;
};
} // namespace Internal
diff --git a/src/plugins/coreplugin/generalsettings.ui b/src/plugins/coreplugin/generalsettings.ui
index a44dfdef5a..5a281652a1 100644
--- a/src/plugins/coreplugin/generalsettings.ui
+++ b/src/plugins/coreplugin/generalsettings.ui
@@ -6,13 +6,13 @@
<rect>
<x>0</x>
<y>0</y>
- <width>487</width>
- <height>343</height>
+ <width>527</width>
+ <height>323</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
- <widget class="QGroupBox" name="groupBox_2">
+ <widget class="QGroupBox" name="interfaceBox">
<property name="title">
<string>User Interface</string>
</property>
@@ -27,56 +27,6 @@
</property>
</widget>
</item>
- <item row="0" column="1">
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <widget class="Utils::QtColorButton" name="colorButton">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>64</width>
- <height>0</height>
- </size>
- </property>
- <property name="alphaAllowed" stdset="0">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QToolButton" name="resetButton">
- <property name="toolTip">
- <string>Reset to default</string>
- </property>
- <property name="text">
- <string>R</string>
- </property>
- <property name="icon">
- <iconset resource="core.qrc">
- <normaloff>:/core/images/reset.png</normaloff>:/core/images/reset.png</iconset>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>285</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
@@ -104,33 +54,43 @@
</item>
</layout>
</item>
- <item row="3" column="0">
- <widget class="QLabel" name="encodingLabel">
- <property name="text">
- <string>Default file encoding: </string>
- </property>
- </widget>
- </item>
- <item row="3" column="1">
- <layout class="QHBoxLayout" name="horizontalLayout_6">
+ <item row="0" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout">
<item>
- <widget class="QComboBox" name="encodingBox">
+ <widget class="Utils::QtColorButton" name="colorButton">
<property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <property name="sizeAdjustPolicy">
- <enum>QComboBox::AdjustToMinimumContentsLengthWithIcon</enum>
+ <property name="minimumSize">
+ <size>
+ <width>64</width>
+ <height>0</height>
+ </size>
</property>
- <property name="minimumContentsLength">
- <number>20</number>
+ <property name="alphaAllowed" stdset="0">
+ <bool>false</bool>
</property>
</widget>
</item>
<item>
- <spacer name="horizontalSpacer_6">
+ <widget class="QToolButton" name="resetButton">
+ <property name="toolTip">
+ <string>Reset to default</string>
+ </property>
+ <property name="text">
+ <string>R</string>
+ </property>
+ <property name="icon">
+ <iconset resource="core.qrc">
+ <normaloff>:/core/images/reset.png</normaloff>:/core/images/reset.png</iconset>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
@@ -155,7 +115,7 @@
</widget>
</item>
<item>
- <widget class="QGroupBox" name="groupBox">
+ <widget class="QGroupBox" name="systemBox">
<property name="title">
<string>System</string>
</property>
diff --git a/src/plugins/coreplugin/icontext.h b/src/plugins/coreplugin/icontext.h
index 48e97a2bb5..c129f0b5eb 100644
--- a/src/plugins/coreplugin/icontext.h
+++ b/src/plugins/coreplugin/icontext.h
@@ -70,7 +70,7 @@ public:
void prepend(int c) { d.prepend(c); }
void add(const Context &c) { d += c.d; }
void add(int c) { d.append(c); }
- bool operator==(const Context &c) { return d == c.d; }
+ bool operator==(const Context &c) const { return d == c.d; }
private:
QList<int> d;
diff --git a/src/plugins/coreplugin/icore.cpp b/src/plugins/coreplugin/icore.cpp
index 45ea20d975..b003df1af1 100644
--- a/src/plugins/coreplugin/icore.cpp
+++ b/src/plugins/coreplugin/icore.cpp
@@ -164,7 +164,7 @@
*/
/*!
- \fn VCSManager *ICore::vcsManager() const
+ \fn VcsManager *ICore::vcsManager() const
\brief Returns the application's vcs manager.
The vcs manager can be used to e.g. retrieve information about
diff --git a/src/plugins/coreplugin/icore.h b/src/plugins/coreplugin/icore.h
index 5f6868cd65..648c9d5e21 100644
--- a/src/plugins/coreplugin/icore.h
+++ b/src/plugins/coreplugin/icore.h
@@ -35,8 +35,6 @@
#define ICORE_H
#include "core_global.h"
-#include "dialogs/iwizard.h"
-#include "uniqueidmanager.h"
#include <QtCore/QObject>
#include <QtCore/QSettings>
@@ -44,14 +42,13 @@
QT_BEGIN_NAMESPACE
class QMainWindow;
class QPrinter;
-class QSettings;
class QStatusBar;
template <class T> class QList;
QT_END_NAMESPACE
namespace Core {
-
+class IWizard;
class ActionManager;
class Context;
class EditorManager;
@@ -66,7 +63,7 @@ class ScriptManager;
class SettingsDatabase;
class UniqueIDManager;
class VariableManager;
-class VCSManager;
+class VcsManager;
class CORE_EXPORT ICore : public QObject
{
@@ -100,7 +97,7 @@ public:
virtual ProgressManager *progressManager() const = 0;
virtual ScriptManager *scriptManager() const = 0;
virtual VariableManager *variableManager() const = 0;
- virtual VCSManager *vcsManager() const = 0;
+ virtual VcsManager *vcsManager() const = 0;
virtual ModeManager *modeManager() const = 0;
virtual MimeDatabase *mimeDatabase() const = 0;
virtual HelpManager *helpManager() const = 0;
@@ -108,6 +105,7 @@ public:
virtual QSettings *settings(QSettings::Scope scope = QSettings::UserScope) const = 0;
virtual SettingsDatabase *settingsDatabase() const = 0;
virtual QPrinter *printer() const = 0;
+ virtual QString userInterfaceLanguage() const = 0;
virtual QString resourcePath() const = 0;
virtual QString userResourcePath() const = 0;
@@ -123,7 +121,13 @@ public:
virtual void addContextObject(IContext *context) = 0;
virtual void removeContextObject(IContext *context) = 0;
- enum OpenFilesFlags { None = 0, SwitchMode = 1, CanContainLineNumbers = 2};
+ enum OpenFilesFlags {
+ None = 0,
+ SwitchMode = 1,
+ CanContainLineNumbers = 2,
+ /// Stop loading once the first file fails to load
+ StopOnLoadFail = 4
+ };
virtual void openFiles(const QStringList &fileNames, OpenFilesFlags flags = None) = 0;
signals:
diff --git a/src/plugins/coreplugin/ide_version.h.in b/src/plugins/coreplugin/ide_version.h.in
new file mode 100644
index 0000000000..2d28fac7db
--- /dev/null
+++ b/src/plugins/coreplugin/ide_version.h.in
@@ -0,0 +1,32 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#define IDE_VERSION_MAJOR $$replace(QTCREATOR_VERSION, "^(\\d+)\\.\\d+\\.\\d+(-.*)?$", \\1)
+#define IDE_VERSION_MINOR $$replace(QTCREATOR_VERSION, "^\\d+\\.(\\d+)\\.\\d+(-.*)?$", \\1)
+#define IDE_VERSION_RELEASE $$replace(QTCREATOR_VERSION, "^\\d+\\.\\d+\\.(\\d+)(-.*)?$", \\1)
diff --git a/src/plugins/coreplugin/ifile.h b/src/plugins/coreplugin/ifile.h
index e4c0b13754..4c1e97503e 100644
--- a/src/plugins/coreplugin/ifile.h
+++ b/src/plugins/coreplugin/ifile.h
@@ -54,6 +54,12 @@ public:
IgnoreAll = 2
};
+ enum Utf8BomSetting {
+ AlwaysAdd = 0,
+ OnlyKeep = 1,
+ AlwaysDelete = 2
+ };
+
enum ChangeTrigger {
TriggerInternal,
TriggerExternal
diff --git a/src/plugins/coreplugin/iversioncontrol.h b/src/plugins/coreplugin/iversioncontrol.h
index 2ad175b236..d38060a5d3 100644
--- a/src/plugins/coreplugin/iversioncontrol.h
+++ b/src/plugins/coreplugin/iversioncontrol.h
@@ -70,7 +70,7 @@ public:
* Returns whether files in this directory should be managed with this
* version control.
* If \a topLevel is non-null, it should return the topmost directory,
- * for which this IVersionControl should be used. The VCSManager assumes
+ * for which this IVersionControl should be used. The VcsManager assumes
* that all files in the returned directory are managed by the same IVersionControl.
*/
diff --git a/src/plugins/coreplugin/mainwindow.cpp b/src/plugins/coreplugin/mainwindow.cpp
index 8ba74a29ef..ba84a6ae99 100644
--- a/src/plugins/coreplugin/mainwindow.cpp
+++ b/src/plugins/coreplugin/mainwindow.cpp
@@ -86,6 +86,7 @@
#include <QtCore/QTimer>
#include <QtCore/QtPlugin>
#include <QtCore/QUrl>
+#include <QtCore/QDir>
#include <QtGui/QApplication>
#include <QtGui/QCloseEvent>
@@ -121,9 +122,7 @@ MainWindow::MainWindow() :
m_coreImpl(new CoreImpl(this)),
m_uniqueIDManager(new UniqueIDManager()),
m_additionalContexts(Constants::C_GLOBAL),
- // keep this in sync with main() in app/main.cpp
- m_settings(new QSettings(QSettings::IniFormat, QSettings::UserScope,
- QLatin1String("Nokia"), QLatin1String("QtCreator"), this)),
+ m_settings(ExtensionSystem::PluginManager::instance()->settings()),
m_globalSettings(new QSettings(QSettings::IniFormat, QSettings::SystemScope,
QLatin1String("Nokia"), QLatin1String("QtCreator"), this)),
m_settingsDatabase(new SettingsDatabase(QFileInfo(m_settings->fileName()).path(),
@@ -136,7 +135,7 @@ MainWindow::MainWindow() :
m_progressManager(new ProgressManagerPrivate()),
m_scriptManager(new ScriptManagerPrivate(this)),
m_variableManager(new VariableManager),
- m_vcsManager(new VCSManager),
+ m_vcsManager(new VcsManager),
m_statusBarManager(0),
m_modeManager(0),
m_mimeDatabase(new MimeDatabase),
@@ -406,7 +405,7 @@ static bool isDesktopFileManagerDrop(const QMimeData *d, QStringList *files = 0)
void MainWindow::dragEnterEvent(QDragEnterEvent *event)
{
- if (isDesktopFileManagerDrop(event->mimeData())) {
+ if (isDesktopFileManagerDrop(event->mimeData()) && m_filesToOpenDelayed.isEmpty()) {
event->accept();
} else {
event->ignore();
@@ -418,12 +417,23 @@ void MainWindow::dropEvent(QDropEvent *event)
QStringList files;
if (isDesktopFileManagerDrop(event->mimeData(), &files)) {
event->accept();
- openFiles(files, ICore::SwitchMode);
+ m_filesToOpenDelayed.append(files);
+ QTimer::singleShot(50, this, SLOT(openDelayedFiles()));
} else {
event->ignore();
}
}
+void MainWindow::openDelayedFiles()
+{
+ if (m_filesToOpenDelayed.isEmpty())
+ return;
+ activateWindow();
+ raise();
+ openFiles(m_filesToOpenDelayed, ICore::SwitchMode);
+ m_filesToOpenDelayed.clear();
+}
+
IContext *MainWindow::currentContextObject() const
{
return m_activeContext;
@@ -584,6 +594,7 @@ void MainWindow::registerDefaultActions()
ActionContainer *ac = am->createMenu(Constants::M_FILE_RECENTFILES);
mfile->addMenu(ac, Constants::G_FILE_OPEN);
ac->menu()->setTitle(tr("Recent &Files"));
+ ac->setOnAllDisabledBehavior(ActionContainer::Show);
// Save Action
icon = QIcon::fromTheme(QLatin1String("document-save"), QIcon(Constants::ICON_SAVEFILE));
@@ -833,16 +844,20 @@ void MainWindow::openFiles(const QStringList &fileNames, ICore::OpenFilesFlags f
const QFileInfo fi(fileName);
const QString absoluteFilePath = fi.absoluteFilePath();
if (IFileFactory *fileFactory = findFileFactory(nonEditorFileFactories, mimeDatabase(), fi)) {
- fileFactory->open(absoluteFilePath);
- if (flags && ICore::SwitchMode)
+ Core::IFile *file = fileFactory->open(absoluteFilePath);
+ if (!file && (flags & ICore::StopOnLoadFail))
+ return;
+ if (file && (flags & ICore::SwitchMode))
Core::ModeManager::instance()->activateMode(Core::Constants::MODE_EDIT);
} else {
QFlags<EditorManager::OpenEditorFlag> emFlags;
- if (flags && ICore::SwitchMode)
+ if (flags & ICore::SwitchMode)
emFlags = EditorManager::ModeSwitch;
- if (flags && ICore::CanContainLineNumbers)
+ if (flags & ICore::CanContainLineNumbers)
emFlags |= EditorManager::CanContainLineNumber;
- editorManager()->openEditor(absoluteFilePath, QString(), emFlags);
+ Core::IEditor *editor = editorManager()->openEditor(absoluteFilePath, QString(), emFlags);
+ if (!editor && (flags & ICore::StopOnLoadFail))
+ return;
}
}
}
@@ -1000,7 +1015,7 @@ MessageManager *MainWindow::messageManager() const
return m_messageManager;
}
-VCSManager *MainWindow::vcsManager() const
+VcsManager *MainWindow::vcsManager() const
{
return m_vcsManager;
}
@@ -1154,8 +1169,12 @@ void MainWindow::aboutToShutdown()
}
static const char *settingsGroup = "MainWindow";
-static const char *geometryKey = "Geometry";
static const char *colorKey = "Color";
+static const char *windowGeometryKey = "WindowGeometry";
+static const char *windowStateKey = "WindowState";
+
+// TODO compat for <= 2.1, remove later
+static const char *geometryKey = "Geometry";
static const char *maxKey = "Maximized";
static const char *fullScreenKey = "FullScreen";
@@ -1173,15 +1192,27 @@ void MainWindow::readSettings()
QColor(Utils::StyleHelper::DEFAULT_BASE_COLOR)).value<QColor>());
}
- const QVariant geom = m_settings->value(QLatin1String(geometryKey));
- if (geom.isValid()) {
- setGeometry(geom.toRect());
+ // TODO compat for <= 2.1, remove later
+ if (m_settings->contains(QLatin1String(geometryKey))) {
+ const QVariant geom = m_settings->value(QLatin1String(geometryKey));
+ if (geom.isValid()) {
+ setGeometry(geom.toRect());
+ } else {
+ resize(1024, 700);
+ }
+ if (m_settings->value(QLatin1String(maxKey), false).toBool())
+ setWindowState(Qt::WindowMaximized);
+ setFullScreen(m_settings->value(QLatin1String(fullScreenKey), false).toBool());
+
+ m_settings->remove(QLatin1String(geometryKey));
+ m_settings->remove(QLatin1String(maxKey));
+ m_settings->remove(QLatin1String(fullScreenKey));
} else {
- resize(1024, 700);
+ if (!restoreGeometry(m_settings->value(QLatin1String(windowGeometryKey)).toByteArray())) {
+ resize(1024, 700);
+ }
+ restoreState(m_settings->value(QLatin1String(windowStateKey)).toByteArray());
}
- if (m_settings->value(QLatin1String(maxKey), false).toBool())
- setWindowState(Qt::WindowMaximized);
- setFullScreen(m_settings->value(QLatin1String(fullScreenKey), false).toBool());
m_settings->endGroup();
@@ -1197,18 +1228,12 @@ void MainWindow::writeSettings()
if (!(m_overrideColor.isValid() && Utils::StyleHelper::baseColor() == m_overrideColor))
m_settings->setValue(QLatin1String(colorKey), Utils::StyleHelper::requestedBaseColor());
- if (windowState() & (Qt::WindowMaximized | Qt::WindowFullScreen)) {
- m_settings->setValue(QLatin1String(maxKey), (bool) (windowState() & Qt::WindowMaximized));
- m_settings->setValue(QLatin1String(fullScreenKey), (bool) (windowState() & Qt::WindowFullScreen));
- } else {
- m_settings->setValue(QLatin1String(maxKey), false);
- m_settings->setValue(QLatin1String(fullScreenKey), false);
- m_settings->setValue(QLatin1String(geometryKey), geometry());
- }
+ m_settings->setValue(QLatin1String(windowGeometryKey), saveGeometry());
+ m_settings->setValue(QLatin1String(windowStateKey), saveState());
m_settings->endGroup();
- m_fileManager->saveRecentFiles();
+ m_fileManager->saveSettings();
m_actionManager->saveSettings(m_settings);
m_editorManager->saveSettings();
m_navigationWidget->saveSettings(m_settings);
@@ -1268,11 +1293,11 @@ void MainWindow::aboutToShowRecentFiles()
aci->menu()->clear();
bool hasRecentFiles = false;
- foreach (const QString &fileName, m_fileManager->recentFiles()) {
+ foreach (const FileManager::RecentFile &file, m_fileManager->recentFiles()) {
hasRecentFiles = true;
QAction *action = aci->menu()->addAction(
- Utils::withTildeHomePath(fileName));
- action->setData(fileName);
+ QDir::toNativeSeparators(Utils::withTildeHomePath(file.first)));
+ action->setData(qVariantFromValue(file));
connect(action, SIGNAL(triggered()), this, SLOT(openRecentFile()));
}
aci->menu()->setEnabled(hasRecentFiles);
@@ -1281,9 +1306,8 @@ void MainWindow::aboutToShowRecentFiles()
void MainWindow::openRecentFile()
{
if (const QAction *action = qobject_cast<const QAction*>(sender())) {
- const QString fileName = action->data().toString();
- if (!fileName.isEmpty())
- editorManager()->openEditor(fileName, QString(), Core::EditorManager::ModeSwitch);
+ const FileManager::RecentFile file = action->data().value<FileManager::RecentFile>();
+ editorManager()->openEditor(file.first, file.second, Core::EditorManager::ModeSwitch);
}
}
diff --git a/src/plugins/coreplugin/mainwindow.h b/src/plugins/coreplugin/mainwindow.h
index 26c8d48cd5..638d90645a 100644
--- a/src/plugins/coreplugin/mainwindow.h
+++ b/src/plugins/coreplugin/mainwindow.h
@@ -34,16 +34,12 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
-#include "core_global.h"
+#include "eventfilteringmainwindow.h"
#include "icontext.h"
#include "icore.h"
-#include "dialogs/iwizard.h"
-
-#include "eventfilteringmainwindow.h"
#include <QtCore/QMap>
#include <QtGui/QColor>
-#include <QtCore/QSettings>
QT_BEGIN_NAMESPACE
class QSettings;
@@ -59,7 +55,6 @@ class StatusBarWidget;
class EditorManager;
class FileManager;
class HelpManager;
-class IContext;
class IWizard;
class MessageManager;
class MimeDatabase;
@@ -71,7 +66,7 @@ class ScriptManager;
class SettingsDatabase;
class UniqueIDManager;
class VariableManager;
-class VCSManager;
+class VcsManager;
namespace Internal {
@@ -85,7 +80,7 @@ class StatusBarManager;
class VersionDialog;
class SystemEditor;
-class CORE_EXPORT MainWindow : public EventFilteringMainWindow
+class MainWindow : public EventFilteringMainWindow
{
Q_OBJECT
@@ -116,7 +111,7 @@ public:
Core::MimeDatabase *mimeDatabase() const;
Core::HelpManager *helpManager() const;
- VCSManager *vcsManager() const;
+ VcsManager *vcsManager() const;
QSettings *settings(QSettings::Scope scope) const;
inline SettingsDatabase *settingsDatabase() const { return m_settingsDatabase; }
virtual QPrinter *printer() const;
@@ -170,6 +165,7 @@ private slots:
void updateFocusWidget(QWidget *old, QWidget *now);
void setSidebarVisible(bool visible);
void destroyVersionDialog();
+ void openDelayedFiles();
private:
void updateContextObject(IContext *context);
@@ -195,7 +191,7 @@ private:
ProgressManagerPrivate *m_progressManager;
ScriptManager *m_scriptManager;
QScopedPointer<VariableManager> m_variableManager;
- VCSManager *m_vcsManager;
+ VcsManager *m_vcsManager;
StatusBarManager *m_statusBarManager;
ModeManager *m_modeManager;
MimeDatabase *m_mimeDatabase;
@@ -231,6 +227,8 @@ private:
QToolButton *m_toggleSideBarButton;
QColor m_overrideColor;
+
+ QStringList m_filesToOpenDelayed;
};
} // namespace Internal
diff --git a/src/plugins/coreplugin/mimedatabase.cpp b/src/plugins/coreplugin/mimedatabase.cpp
index 07b07a2b62..d11b11200a 100644
--- a/src/plugins/coreplugin/mimedatabase.cpp
+++ b/src/plugins/coreplugin/mimedatabase.cpp
@@ -32,6 +32,7 @@
**************************************************************************/
#include "mimedatabase.h"
+#include "coreconstants.h"
#include <utils/qtcassert.h>
@@ -52,6 +53,8 @@
#include <QtXml/QXmlStreamReader>
+#include <algorithm>
+
enum { debugMimeDB = 0 };
// XML tags in mime files
@@ -114,7 +117,7 @@ namespace Internal {
// and read while checking).
class FileMatchContext {
- Q_DISABLE_COPY(FileMatchContext);
+ Q_DISABLE_COPY(FileMatchContext)
public:
// Max data to be read from a file
enum { MaxData = 2048 };
@@ -165,7 +168,7 @@ QByteArray FileMatchContext::data()
// The binary fallback matcher for "application/octet-stream".
class BinaryMatcher : public IMagicMatcher {
- Q_DISABLE_COPY(BinaryMatcher);
+ Q_DISABLE_COPY(BinaryMatcher)
public:
BinaryMatcher() {}
virtual bool matches(const QByteArray & /*data*/) const { return true; }
@@ -175,7 +178,7 @@ public:
// A heuristic text file matcher: If the data do not contain any character
// below tab (9), detect as text.
class HeuristicTextMagicMatcher : public IMagicMatcher {
- Q_DISABLE_COPY(HeuristicTextMagicMatcher);
+ Q_DISABLE_COPY(HeuristicTextMagicMatcher)
public:
HeuristicTextMagicMatcher() {}
virtual bool matches(const QByteArray &data) const;
@@ -647,7 +650,7 @@ namespace Internal {
// MimeDatabase helpers: Generic parser for a sequence of <mime-type>.
// Calls abstract handler function process for MimeType it finds.
class BaseMimeTypeParser {
- Q_DISABLE_COPY(BaseMimeTypeParser);
+ Q_DISABLE_COPY(BaseMimeTypeParser)
public:
BaseMimeTypeParser();
virtual ~BaseMimeTypeParser() {}
@@ -1307,6 +1310,29 @@ QStringList MimeDatabase::filterStrings() const
m_mutex.unlock();
return rc;
}
+QString MimeDatabase::allFiltersString(QString *allFilesFilter) const
+{
+ if (allFilesFilter)
+ allFilesFilter->clear();
+
+ // Compile list of filter strings, sort, and remove duplicates (different mime types might
+ // generate the same filter).
+ QStringList filters = filterStrings();
+ if (filters.empty())
+ return QString();
+ filters.sort();
+ filters.erase(std::unique(filters.begin(), filters.end()), filters.end());
+
+ static const QString allFiles =
+ QCoreApplication::translate("Core", Constants::ALL_FILES_FILTER);
+ if (allFilesFilter)
+ *allFilesFilter = allFiles;
+
+ // Prepend all files filter (instead of appending to work around a bug in Qt/Mac).
+ filters.prepend(allFiles);
+
+ return filters.join(QLatin1String(";;"));
+}
QString MimeDatabase::preferredSuffixByType(const QString &type) const
{
diff --git a/src/plugins/coreplugin/mimedatabase.h b/src/plugins/coreplugin/mimedatabase.h
index da765ef0cf..72b4a55381 100644
--- a/src/plugins/coreplugin/mimedatabase.h
+++ b/src/plugins/coreplugin/mimedatabase.h
@@ -275,6 +275,8 @@ public:
friend QDebug operator<<(QDebug d, const MimeDatabase &mt);
+ // returns a string with all the possible file filters, for use with file dialogs
+ QString allFiltersString(QString *allFilesFilter = 0) const;
private:
MimeType findByFileUnlocked(const QFileInfo &f) const;
diff --git a/src/plugins/coreplugin/modemanager.cpp b/src/plugins/coreplugin/modemanager.cpp
index dd15f1f734..fe57700442 100644
--- a/src/plugins/coreplugin/modemanager.cpp
+++ b/src/plugins/coreplugin/modemanager.cpp
@@ -155,6 +155,8 @@ IMode *ModeManager::mode(const QString &id) const
void ModeManager::activateModeType(const QString &type)
{
+ if (currentMode() && currentMode()->type() == type)
+ return;
int index = -1;
for (int i = 0; i < d->m_modes.count(); ++i) {
if (d->m_modes.at(i)->type() == type) {
@@ -202,6 +204,9 @@ void ModeManager::objectAdded(QObject *obj)
connect(cmd, SIGNAL(keySequenceChanged()), this, SLOT(updateModeToolTip()));
for (int i = 0; i < d->m_modeShortcuts.size(); ++i) {
Command *currentCmd = d->m_modeShortcuts.at(i);
+ // we need this hack with currentlyHasDefaultSequence
+ // because we call setDefaultShortcut multiple times on the same cmd
+ // and still expect the current shortcut to change with it
bool currentlyHasDefaultSequence = (currentCmd->keySequence()
== currentCmd->defaultKeySequence());
#ifdef Q_WS_MAC
@@ -281,6 +286,7 @@ void ModeManager::addAction(Command *command, int priority)
void ModeManager::addProjectSelector(QAction *action)
{
d->m_actionBar->addProjectSelector(action);
+ d->m_actions.insert(0, INT_MAX);
}
void ModeManager::currentTabAboutToChange(int index)
diff --git a/src/plugins/coreplugin/navigationwidget.cpp b/src/plugins/coreplugin/navigationwidget.cpp
index 866dc5ee25..1027b6dd75 100644
--- a/src/plugins/coreplugin/navigationwidget.cpp
+++ b/src/plugins/coreplugin/navigationwidget.cpp
@@ -222,10 +222,14 @@ QAbstractItemModel *NavigationWidget::factoryModel() const
void NavigationWidget::updateToggleText()
{
+ bool haveData = d->m_factoryModel->rowCount();
+ d->m_toggleSideBarAction->setVisible(haveData);
+ d->m_toggleSideBarAction->setEnabled(haveData);
+
if (isShown())
- d->m_toggleSideBarAction->setText(tr("Hide Sidebar"));
+ d->m_toggleSideBarAction->setToolTip(tr("Hide Sidebar"));
else
- d->m_toggleSideBarAction->setText(tr("Show Sidebar"));
+ d->m_toggleSideBarAction->setToolTip(tr("Show Sidebar"));
}
void NavigationWidget::placeHolderChanged(NavigationWidgetPlaceHolder *holder)
@@ -308,26 +312,31 @@ void NavigationWidget::saveSettings(QSettings *settings)
d->m_subWidgets.at(i)->saveSettings();
viewIds.append(d->m_subWidgets.at(i)->factory()->id());
}
- settings->setValue("Navigation/Views", viewIds);
- settings->setValue("Navigation/Visible", isShown());
- settings->setValue("Navigation/VerticalPosition", saveState());
- settings->setValue("Navigation/Width", d->m_width);
+ settings->setValue(QLatin1String("Navigation/Views"), viewIds);
+ settings->setValue(QLatin1String("Navigation/Visible"), isShown());
+ settings->setValue(QLatin1String("Navigation/VerticalPosition"), saveState());
+ settings->setValue(QLatin1String("Navigation/Width"), d->m_width);
}
void NavigationWidget::restoreSettings(QSettings *settings)
{
- int version = settings->value("Navigation/Version", 1).toInt();
- QStringList viewIds = settings->value("Navigation/Views").toStringList();
+ if (!d->m_factoryModel->rowCount()) {
+ // We have no widgets to show!
+ setShown(false);
+ return;
+ }
+
+ int version = settings->value(QLatin1String("Navigation/Version"), 1).toInt();
+ QStringList viewIds = settings->value(QLatin1String("Navigation/Views"),
+ QStringList("Projects")).toStringList();
bool restoreSplitterState = true;
if (version == 1) {
- if (viewIds.isEmpty())
- viewIds += "Projects";
- if (!viewIds.contains("Open Documents")) {
- viewIds += "Open Documents";
+ if (!viewIds.contains(QLatin1String("Open Documents"))) {
+ viewIds += QLatin1String("Open Documents");
restoreSplitterState = false;
}
- settings->setValue("Navigation/Version", 2);
+ settings->setValue(QLatin1String("Navigation/Version"), 2);
}
int position = 0;
@@ -346,14 +355,10 @@ void NavigationWidget::restoreSettings(QSettings *settings)
// Make sure we have at least the projects widget
insertSubItem(0, qMax(0, factoryIndex(QLatin1String("Projects"))));
- if (settings->contains("Navigation/Visible")) {
- setShown(settings->value("Navigation/Visible").toBool());
- } else {
- setShown(true);
- }
+ setShown(settings->value(QLatin1String("Navigation/Visible"), true).toBool());
- if (restoreSplitterState && settings->contains("Navigation/VerticalPosition")) {
- restoreState(settings->value("Navigation/VerticalPosition").toByteArray());
+ if (restoreSplitterState && settings->contains(QLatin1String("Navigation/VerticalPosition"))) {
+ restoreState(settings->value(QLatin1String("Navigation/VerticalPosition")).toByteArray());
} else {
QList<int> sizes;
sizes += 256;
@@ -362,17 +367,13 @@ void NavigationWidget::restoreSettings(QSettings *settings)
setSizes(sizes);
}
- if (settings->contains("Navigation/Width")) {
- d->m_width = settings->value("Navigation/Width").toInt();
- if (!d->m_width)
- d->m_width = 240;
- } else {
- d->m_width = 240; //pixel
- }
+ d->m_width = settings->value(QLatin1String("Navigation/Width"), 240).toInt();
+ if (d->m_width < 40)
+ d->m_width = 40;
+
// Apply
- if (NavigationWidgetPlaceHolder::m_current) {
+ if (NavigationWidgetPlaceHolder::m_current)
NavigationWidgetPlaceHolder::m_current->applyStoredSize(d->m_width);
- }
}
void NavigationWidget::closeSubWidgets()
@@ -388,10 +389,11 @@ void NavigationWidget::setShown(bool b)
{
if (d->m_shown == b)
return;
+ bool haveData = d->m_factoryModel->rowCount();
d->m_shown = b;
if (NavigationWidgetPlaceHolder::m_current) {
- NavigationWidgetPlaceHolder::m_current->setVisible(d->m_shown && !d->m_suppressed);
- d->m_toggleSideBarAction->setChecked(d->m_shown);
+ NavigationWidgetPlaceHolder::m_current->setVisible(d->m_shown && !d->m_suppressed && haveData);
+ d->m_toggleSideBarAction->setChecked(d->m_shown && !d->m_suppressed && haveData);
} else {
d->m_toggleSideBarAction->setChecked(false);
}
@@ -433,4 +435,3 @@ QHash<QString, Core::Command*> NavigationWidget::commandMap() const
}
} // namespace Core
-
diff --git a/src/plugins/coreplugin/outputpane.cpp b/src/plugins/coreplugin/outputpane.cpp
index 40c6af724c..d99b28de40 100644
--- a/src/plugins/coreplugin/outputpane.cpp
+++ b/src/plugins/coreplugin/outputpane.cpp
@@ -78,8 +78,11 @@ OutputPanePlaceHolder::OutputPanePlaceHolder(Core::IMode *mode, QSplitter* paren
OutputPanePlaceHolder::~OutputPanePlaceHolder()
{
if (d->m_current == this) {
- Internal::OutputPaneManager::instance()->setParent(0);
- Internal::OutputPaneManager::instance()->hide();
+ // FIXME: Prevent exit crash in debug mode.
+ if (Internal::OutputPaneManager *om = Internal::OutputPaneManager::instance()) {
+ om->setParent(0);
+ om->hide();
+ }
}
}
diff --git a/src/plugins/coreplugin/rssfetcher.cpp b/src/plugins/coreplugin/rssfetcher.cpp
index ffcb552a3a..5eb484746d 100644
--- a/src/plugins/coreplugin/rssfetcher.cpp
+++ b/src/plugins/coreplugin/rssfetcher.cpp
@@ -38,6 +38,7 @@
#include <QtCore/QSysInfo>
#include <QtCore/QLocale>
#include <QtCore/QEventLoop>
+#include <QtCore/QUrl>
#include <QtGui/QDesktopServices>
#include <QtGui/QLineEdit>
#include <QtNetwork/QNetworkReply>
@@ -52,7 +53,7 @@
#include <sys/utsname.h>
#endif
-using namespace Core::Internal;
+namespace Core {
static const QString getOsString()
{
@@ -123,7 +124,7 @@ RssFetcher::RssFetcher(int maxItems)
: QThread(0), m_maxItems(maxItems), m_items(0),
m_requestCount(0), m_networkAccessManager(0)
{
- qRegisterMetaType<RssItem>("RssItem");
+ qRegisterMetaType<Core::RssItem>("Core::RssItem");
moveToThread(this);
}
@@ -245,3 +246,5 @@ void RssFetcher::parseXml(QIODevice *device)
qPrintable(item.title));
}
}
+
+} // namespace Core
diff --git a/src/plugins/coreplugin/rssfetcher.h b/src/plugins/coreplugin/rssfetcher.h
index 1a1a055289..e4e3b888a7 100644
--- a/src/plugins/coreplugin/rssfetcher.h
+++ b/src/plugins/coreplugin/rssfetcher.h
@@ -37,16 +37,15 @@
#include "core_global.h"
#include <QtCore/QThread>
-#include <QtCore/QUrl>
QT_BEGIN_NAMESPACE
+class QUrl;
class QNetworkReply;
class QNetworkAccessManager;
class QIODevice;
QT_END_NAMESPACE
namespace Core {
-namespace Internal {
class CORE_EXPORT RssItem
{
@@ -68,7 +67,7 @@ public:
signals:
void newsItemReady(const QString& title, const QString& desciption, const QString& url);
- void rssItemReady(const RssItem& item);
+ void rssItemReady(const Core::RssItem& item);
void finished(bool error);
public slots:
@@ -88,7 +87,6 @@ private:
QNetworkAccessManager* m_networkAccessManager;
};
-} // namespace Core
} // namespace Internal
#endif // RSSFETCHER_H
diff --git a/src/plugins/coreplugin/scriptmanager/metatypedeclarations.h b/src/plugins/coreplugin/scriptmanager/metatypedeclarations.h
index 5d3bd9218d..fa893d7005 100644
--- a/src/plugins/coreplugin/scriptmanager/metatypedeclarations.h
+++ b/src/plugins/coreplugin/scriptmanager/metatypedeclarations.h
@@ -54,7 +54,6 @@ Q_DECLARE_METATYPE(Core::MessageManager*)
Q_DECLARE_METATYPE(Core::FileManager*)
Q_DECLARE_METATYPE(Core::IFile*)
Q_DECLARE_METATYPE(QList<Core::IFile*>)
-Q_DECLARE_METATYPE(Core::IEditor*)
Q_DECLARE_METATYPE(QList<Core::IEditor*>)
Q_DECLARE_METATYPE(Core::EditorGroup*)
Q_DECLARE_METATYPE(QList<Core::EditorGroup*>)
diff --git a/src/plugins/coreplugin/scriptmanager/qworkbench_wrapper.cpp b/src/plugins/coreplugin/scriptmanager/qworkbench_wrapper.cpp
deleted file mode 100644
index 1d22dcf2c6..0000000000
--- a/src/plugins/coreplugin/scriptmanager/qworkbench_wrapper.cpp
+++ /dev/null
@@ -1,365 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#include "qworkbench_wrapper.h"
-
-#include <wrap_helpers.h>
-
-#include <coreplugin/messagemanager.h>
-
-#include <utils/qtcassert.h>
-
-#include <QtCore/QDebug>
-#include <QtCore/QSettings>
-
-#include <QtGui/QMainWindow>
-
-#include <QtScript/QScriptEngine>
-
-namespace {
- enum { debugQWorkbenchWrappers = 0 };
-}
-
-namespace Core {
-namespace Internal {
-
-// -- CorePrototype
-CorePrototype::CorePrototype(QObject *parent) :
- QObject(parent)
-{
-}
-
-Core::MessageManager *CorePrototype::messageManager() const
-{
- return callee()->messageManager();
-}
-
-Core::FileManager *CorePrototype::fileManager() const
-{
- return callee()->fileManager();
-}
-
-Core::EditorManager *CorePrototype::editorManager() const
-{
- return callee()->editorManager();
-}
-
-QMainWindow *CorePrototype::mainWindow() const
-{
- return callee()->mainWindow();
-}
-
-QSettings *CorePrototype::settings() const
-{
- return callee()->settings();
-}
-
-void CorePrototype::updateAdditionalContexts(const Context &remove, const Context &add)
-{
- callee()->updateAdditionalContexts(remove, add);
-}
-
-QString CorePrototype::toString() const
-{
- return QLatin1String("Core");
-}
-
-CorePrototype::ICore *CorePrototype::callee() const
-{
- ICore *rc = qscriptvalue_cast<ICore *>(thisObject());
- QTC_ASSERT(rc, return 0);
- return rc;
-}
-
-// -- MessageManager
-
-MessageManagerPrototype::MessageManagerPrototype(QObject *parent) :
- QObject(parent)
-{
-}
-
-void MessageManagerPrototype::printToOutputPane(const QString &text, bool bringToForeground)
-{
- MessageManager *mm = qscriptvalue_cast<MessageManager *>(thisObject());
- QTC_ASSERT(mm, return);
- mm->printToOutputPane(text, bringToForeground);
-}
-
-void MessageManagerPrototype::printToOutputPanePopup(const QString &text)
-{
- MessageManager *mm = qscriptvalue_cast<MessageManager *>(thisObject());
- QTC_ASSERT(mm, return);
- mm->printToOutputPanePopup(text);
-}
-
-void MessageManagerPrototype::printToOutputPane(const QString &text)
-{
- MessageManager *mm = qscriptvalue_cast<MessageManager *>(thisObject());
- QTC_ASSERT(mm, return);
- mm->printToOutputPane(text);
-}
-
-QString MessageManagerPrototype::toString() const
-{
- return QLatin1String("MessageManager");
-}
-
-// -- FileManagerPrototype
-
-FileManagerPrototype::FileManagerPrototype(QObject *parent) :
- QObject(parent)
-{
-}
-
-FileManager *FileManagerPrototype::callee() const
-{
- FileManager *rc = qscriptvalue_cast<FileManager *>(thisObject());
- QTC_ASSERT(rc, return 0);
- return rc;
-}
-
-bool FileManagerPrototype::addFiles(const QList<Core::IFile *> &files)
-{
- return callee()->addFiles(files);
-}
-
-bool FileManagerPrototype::addFile(Core::IFile *file)
-{
- return callee()->addFile(file);
-}
-
-bool FileManagerPrototype::removeFile(Core::IFile *file)
-{
- return callee()->removeFile(file);
-}
-
-QList<Core::IFile*>
-FileManagerPrototype::saveModifiedFilesSilently(const QList<Core::IFile*> &files)
-{
- return callee()->saveModifiedFilesSilently(files);
-}
-
-QString FileManagerPrototype::getSaveAsFileName(Core::IFile *file)
-{
- return callee()->getSaveAsFileName(file);
-}
-
-bool FileManagerPrototype::isFileManaged(const QString &fileName) const
-{
- return callee()->isFileManaged(fileName);
-}
-
-void FileManagerPrototype::blockFileChange(Core::IFile *file)
-{
- callee()->blockFileChange(file);
-}
-
-void FileManagerPrototype::unblockFileChange(Core::IFile *file)
-{
- return callee()->unblockFileChange(file);
-}
-
-void FileManagerPrototype::addToRecentFiles(const QString &fileName)
-{
- return callee()->addToRecentFiles(fileName);
-}
-
-QStringList FileManagerPrototype::recentFiles() const
-{
- return callee()->recentFiles();
-}
-
-QString FileManagerPrototype::toString() const
-{
- return QLatin1String("FileManager");
-}
-
-// ------- FilePrototype
-
-FilePrototype::FilePrototype(QObject *parent) :
- QObject(parent)
-{
-}
-
-IFile *FilePrototype::callee() const
-{
- IFile *rc = qscriptvalue_cast<IFile *>(thisObject());
- QTC_ASSERT(rc, return 0);
- return rc;
-}
-
-QString FilePrototype::fileName () const { return callee()->fileName(); }
-QString FilePrototype::defaultPath () const { return callee()->defaultPath(); }
-QString FilePrototype::suggestedFileName () const { return callee()->suggestedFileName(); }
-
-bool FilePrototype::isModified () const { return callee()->isModified(); }
-bool FilePrototype::isReadOnly () const { return callee()->isReadOnly(); }
-bool FilePrototype::isSaveAsAllowed () const { return callee()->isSaveAsAllowed(); }
-
-QString FilePrototype::toString() const
-{
- QString rc = QLatin1String("File(");
- rc += fileName();
- rc += QLatin1Char(')');
- return rc;
-}
-
-// ------------- EditorManagerPrototype
-
-EditorManagerPrototype::EditorManagerPrototype(QObject *parent) :
- QObject(parent)
-{
-}
-
-Core::IEditor *EditorManagerPrototype::currentEditor() const
-{
- return callee()->currentEditor();
-}
-
-void EditorManagerPrototype::activateEditor(Core::IEditor *editor)
-{
- callee()->activateEditor(editor);
-}
-
-QList<Core::IEditor*> EditorManagerPrototype::openedEditors() const
-{
- return callee()->openedEditors();
-}
-
-QList<Core::IEditor*> EditorManagerPrototype::editorsForFiles(QList<Core::IFile*> files) const
-{
- return callee()->editorsForFiles(files);
-}
-
-bool EditorManagerPrototype::closeEditors(const QList<Core::IEditor*> editorsToClose, bool askAboutModifiedEditors)
-{
- return callee()->closeEditors(editorsToClose, askAboutModifiedEditors);
-}
-
-Core::IEditor *EditorManagerPrototype::openEditor(const QString &fileName, const QString &editorId)
-{
- return callee()->openEditor(fileName, editorId);
-}
-
-Core::IEditor *EditorManagerPrototype::newFile(const QString &editorId, QString titlePattern, const QString &contents)
-{
- return callee()->openEditorWithContents(editorId, &titlePattern, contents);
-}
-
-int EditorManagerPrototype::makeEditorWritable(Core::IEditor *editor)
-{
- return callee()->makeEditorWritable(editor);
-}
-
-QString EditorManagerPrototype::toString() const
-{
- return QLatin1String("EditorManager");
-}
-
-EditorManagerPrototype::EditorManager *EditorManagerPrototype::callee() const
-{
- EditorManager *rc = qscriptvalue_cast<EditorManager *>(thisObject());
- QTC_ASSERT(rc, return 0);
- return rc;
-}
-
-// ------------- EditorPrototype
-
-EditorPrototype::EditorPrototype(QObject *parent)
- : QObject(parent)
-{
-}
-
-QString EditorPrototype::displayName() const
-{
- return callee()->displayName();
-}
-
-void EditorPrototype::setDisplayName(const QString &title)
-{
- callee()->setDisplayName(title);
-}
-
-QString EditorPrototype::id() const
-{
- return callee()->id();
-}
-
-bool EditorPrototype::duplicateSupported() const
-{
- return callee()->duplicateSupported();
-}
-
-bool EditorPrototype::createNew(const QString &contents)
-{
- return callee()->createNew(contents);
-}
-
-bool EditorPrototype::open(const QString &fileName)
-{
- return callee()->open(fileName);
-}
-
-Core::IEditor *EditorPrototype::duplicate(QWidget *parent)
-{
- return callee()->duplicate(parent);
-}
-
-Core::IFile *EditorPrototype::file() const
-{
- return callee()->file();
-}
-
-QWidget* EditorPrototype::toolBar() const
-{
- return callee()->toolBar();
-}
-
-Core::IEditor *EditorPrototype::callee() const
-{
- IEditor *rc = qscriptvalue_cast<IEditor *>(thisObject());
- QTC_ASSERT(rc, return 0);
- return rc;
-}
-
-QString EditorPrototype::toString() const
-{
- QString rc = QLatin1String("Editor(");
- rc += displayName();
- rc += QLatin1Char(')');
- return rc;
-}
-
-
-} // namespace Internal
-} // namespace Core
diff --git a/src/plugins/coreplugin/scriptmanager/qworkbench_wrapper.h b/src/plugins/coreplugin/scriptmanager/qworkbench_wrapper.h
deleted file mode 100644
index 52018163df..0000000000
--- a/src/plugins/coreplugin/scriptmanager/qworkbench_wrapper.h
+++ /dev/null
@@ -1,232 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#ifndef QWORKBENCH_WRAPPER_H
-#define QWORKBENCH_WRAPPER_H
-
-#include "metatypedeclarations.h" // required for property declarations
-
-#include <QtCore/QObject>
-#include <QtCore/QString>
-#include <QtScript/QScriptable>
-#include <QtScript/QScriptValue>
-
-namespace Core {
-namespace Internal {
-
-// Script prototype for the core interface.
-
-class CorePrototype : public QObject, public QScriptable
-{
- Q_OBJECT
-
- Q_PROPERTY(Core::MessageManager *messageManager READ messageManager DESIGNABLE false SCRIPTABLE true STORED false)
- Q_PROPERTY(Core::FileManager *fileManager READ fileManager DESIGNABLE false SCRIPTABLE true STORED false)
- Q_PROPERTY(Core::EditorManager *editorManager READ editorManager DESIGNABLE false SCRIPTABLE true STORED false)
-
- Q_PROPERTY(QMainWindow *mainWindow READ mainWindow DESIGNABLE false SCRIPTABLE true STORED false)
- Q_PROPERTY(QSettings *settings READ settings DESIGNABLE false SCRIPTABLE true STORED false)
-
-public:
- typedef Core::ICore ICore;
-
- CorePrototype(QObject *parent);
-
- Core::MessageManager *messageManager() const;
- Core::FileManager *fileManager() const;
- Core::EditorManager *editorManager() const;
-
- QMainWindow *mainWindow() const;
- QSettings *settings() const;
-
-public slots:
- void updateAdditionalContexts(const Context &remove, const Context &add);
- QString toString() const;
-
-private:
- ICore *callee() const;
-};
-
-// Script prototype for the message manager.
-
-class MessageManagerPrototype : public QObject, public QScriptable
-{
- Q_OBJECT
-
-public:
- typedef Core::MessageManager MessageManager;
-
- MessageManagerPrototype(QObject *parent = 0);
-
-public slots:
- void printToOutputPane(const QString &text, bool bringToForeground);
- void printToOutputPanePopup(const QString &text); // pops up
- void printToOutputPane(const QString &text);
-
- QString toString() const;
-};
-
-// Script prototype for the file manager interface.
-
-class FileManagerPrototype : public QObject, public QScriptable
-{
- Q_OBJECT
-
- Q_PROPERTY(QStringList recentFiles READ recentFiles DESIGNABLE false SCRIPTABLE true STORED false)
-
-public:
- typedef Core::FileManager FileManager;
-
- FileManagerPrototype(QObject *parent = 0);
- QStringList recentFiles() const;
-
-public slots:
- bool addFiles(const QList<Core::IFile *> &files);
- bool addFile(Core::IFile *file);
- bool removeFile(Core::IFile *file);
-
- QList<Core::IFile*> saveModifiedFilesSilently(const QList<Core::IFile*> &files);
- QString getSaveAsFileName(Core::IFile *file);
-
- bool isFileManaged(const QString &fileName) const;
-
- void blockFileChange(Core::IFile *file);
- void unblockFileChange(Core::IFile *file);
-
- void addToRecentFiles(const QString &fileName);
- QString toString() const;
-
-private:
- FileManager *callee() const;
-};
-
-// Script prototype for the file interface.
-
-class FilePrototype : public QObject, public QScriptable
-{
- Q_OBJECT
-
- Q_PROPERTY(QString fileName READ fileName DESIGNABLE false SCRIPTABLE true STORED false)
- Q_PROPERTY(QString defaultPath READ defaultPath DESIGNABLE false SCRIPTABLE true STORED false)
- Q_PROPERTY(QString suggestedFileName READ suggestedFileName DESIGNABLE false SCRIPTABLE true STORED false)
- Q_PROPERTY(bool isModified READ isModified DESIGNABLE false SCRIPTABLE true STORED false)
- Q_PROPERTY(bool isReadOnly READ isReadOnly DESIGNABLE false SCRIPTABLE true STORED false)
- Q_PROPERTY(bool isSaveAsAllowed READ isSaveAsAllowed DESIGNABLE false SCRIPTABLE true STORED false)
-public:
- typedef Core::IFile IFile;
-
- FilePrototype(QObject *parent = 0);
-
- QString fileName() const;
- QString defaultPath() const;
- QString suggestedFileName() const;
-
- bool isModified() const;
- bool isReadOnly() const;
- bool isSaveAsAllowed() const;
-
-public slots:
- QString toString() const;
-
-private:
- IFile *callee() const;
-};
-
-// Script prototype for the editor manager interface.
-
-class EditorManagerPrototype : public QObject, public QScriptable
-{
- Q_OBJECT
- Q_PROPERTY(Core::IEditor* currentEditor READ currentEditor WRITE activateEditor DESIGNABLE false SCRIPTABLE true STORED false)
- Q_PROPERTY(QList<Core::IEditor*> openedEditors READ openedEditors DESIGNABLE false SCRIPTABLE true STORED false)
-public:
- typedef Core::EditorManager EditorManager;
-
- EditorManagerPrototype(QObject *parent = 0);
-
- Core::IEditor *currentEditor() const;
- void activateEditor(Core::IEditor *editor);
- QList<Core::IEditor*> openedEditors() const;
- QList<Core::IEditor*> editorHistory() const;
-
-public slots:
- QList<Core::IEditor*> editorsForFiles(QList<Core::IFile*> files) const;
- bool closeEditors(const QList<Core::IEditor*> editorsToClose, bool askAboutModifiedEditors);
- Core::IEditor *openEditor(const QString &fileName, const QString &editorId);
- Core::IEditor *newFile(const QString &editorId, QString titlePattern, const QString &contents);
- int makeEditorWritable(Core::IEditor *editor);
-
- QString toString() const;
-
-private:
- EditorManager *callee() const;
-};
-
-// Script prototype for the editor interface.
-
-class EditorPrototype : public QObject, public QScriptable
-{
- Q_OBJECT
- Q_PROPERTY(QString displayName READ displayName WRITE setDisplayName DESIGNABLE false SCRIPTABLE true STORED false)
- Q_PROPERTY(QString id READ id DESIGNABLE false SCRIPTABLE true STORED false)
- Q_PROPERTY(bool duplicateSupported READ duplicateSupported DESIGNABLE false SCRIPTABLE true STORED false)
- Q_PROPERTY(Core::IFile* file READ file DESIGNABLE false SCRIPTABLE true STORED false)
- Q_PROPERTY(QWidget* toolBar READ toolBar DESIGNABLE false SCRIPTABLE true STORED false)
-
-public:
- EditorPrototype(QObject *parent = 0);
-
- QString displayName() const;
- void setDisplayName(const QString &title);
-
- QString id() const;
- bool duplicateSupported() const;
-
- Core::IFile *file() const;
- QWidget* toolBar() const;
-
-public slots:
- bool createNew(const QString &contents);
- bool open(const QString &fileName);
- Core::IEditor *duplicate(QWidget *parent);
-
- QString toString() const;
-
-private:
- Core::IEditor *callee() const;
-};
-
-} // namespace Internal
-} // namespace Core
-
-#endif // QWORKBENCH_WRAPPER_H
diff --git a/src/plugins/coreplugin/scriptmanager/scriptmanager.cpp b/src/plugins/coreplugin/scriptmanager/scriptmanager.cpp
index 2f31798b8f..68bfa2bda8 100644
--- a/src/plugins/coreplugin/scriptmanager/scriptmanager.cpp
+++ b/src/plugins/coreplugin/scriptmanager/scriptmanager.cpp
@@ -32,7 +32,6 @@
**************************************************************************/
#include "scriptmanager_p.h"
-#include "qworkbench_wrapper.h"
#include "metatypedeclarations.h"
#include <utils/qtcassert.h>
@@ -244,26 +243,11 @@ ScriptManager::QScriptEnginePtr ScriptManagerPrivate::ensureEngineInitialized()
SharedTools::registerQObject<QMainWindow>(m_engine.data());
SharedTools::registerQObject<QStatusBar>(m_engine.data());
SharedTools::registerQObject<QSettings>(m_engine.data());
- // WB interfaces
- SharedTools::registerQObjectInterface<Core::MessageManager, MessageManagerPrototype>(m_engine.data());
-// SharedTools::registerQObjectInterface<Core::IFile, FilePrototype>(m_engine);
-// qScriptRegisterSequenceMetaType<QList<Core::IFile *> >(m_engine);
-// SharedTools::registerQObjectInterface<Core::FileManager, FileManagerPrototype>(m_engine);
-
-// SharedTools::registerQObjectInterface<Core::IEditor, EditorPrototype>(m_engine);
qScriptRegisterSequenceMetaType<QList<Core::IEditor *> >(m_engine.data());
-// SharedTools::registerQObjectInterface<Core::EditorGroup, EditorGroupPrototype>(m_engine);
qScriptRegisterSequenceMetaType<QList<Core::EditorGroup *> >(m_engine.data());
- SharedTools::registerQObjectInterface<Core::EditorManager, EditorManagerPrototype>(m_engine.data());
-
-// SharedTools::registerQObjectInterface<Core::ICore, CorePrototype>(m_engine);
-
- // Make "core" available
- m_engine->globalObject().setProperty(QLatin1String("core"), qScriptValueFromValue(m_engine.data(), Core::ICore::instance()));
-
// CLASSIC: registerInterfaceWithDefaultPrototype<Core::MessageManager, MessageManagerPrototype>(m_engine);
// Message box conveniences
diff --git a/src/plugins/coreplugin/ssh/sftpchannel.cpp b/src/plugins/coreplugin/ssh/sftpchannel.cpp
index 1a24875d8f..d6baf2fecb 100644
--- a/src/plugins/coreplugin/ssh/sftpchannel.cpp
+++ b/src/plugins/coreplugin/ssh/sftpchannel.cpp
@@ -218,6 +218,8 @@ SftpJobId SftpChannelPrivate::createJob(const AbstractSftpOperation::Ptr &job)
void SftpChannelPrivate::handleChannelSuccess()
{
+ if (channelState() == CloseRequested)
+ return;
#ifdef CREATOR_SSH_DEBUG
qDebug("sftp subsystem initialized");
#endif
@@ -227,6 +229,9 @@ void SftpChannelPrivate::handleChannelSuccess()
void SftpChannelPrivate::handleChannelFailure()
{
+ if (channelState() == CloseRequested)
+ return;
+
if (m_sftpState != SubsystemRequested) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
"Unexpected SSH_MSG_CHANNEL_FAILURE packet.");
@@ -237,6 +242,9 @@ void SftpChannelPrivate::handleChannelFailure()
void SftpChannelPrivate::handleChannelDataInternal(const QByteArray &data)
{
+ if (channelState() == CloseRequested)
+ return;
+
m_incomingData += data;
m_incomingPacket.consumeData(m_incomingData);
while (m_incomingPacket.isComplete()) {
@@ -768,6 +776,9 @@ SftpChannelPrivate::JobMap::Iterator SftpChannelPrivate::lookupJob(SftpJobId id)
void SftpChannelPrivate::closeHook()
{
+ m_jobs.clear();
+ m_incomingData.clear();
+ m_incomingPacket.clear();
emit closed();
}
diff --git a/src/plugins/coreplugin/ssh/sftpchannel.h b/src/plugins/coreplugin/ssh/sftpchannel.h
index 43e774645f..778465eca6 100644
--- a/src/plugins/coreplugin/ssh/sftpchannel.h
+++ b/src/plugins/coreplugin/ssh/sftpchannel.h
@@ -67,7 +67,8 @@ class SshSendFacility;
* Operations are identified by their job id, which is returned by
* the respective member function. If the function can right away detect that
* the operation cannot succeed, it returns SftpInvalidJob. If an error occurs
- * later, the finishedWithError() signal is emitted for the respective job.
+ * later, the finished() signal is emitted for the respective job with a
+ * non-empty error string.
* Note that directory names must not have a trailing slash.
*/
class CORE_EXPORT SftpChannel : public QObject
diff --git a/src/plugins/coreplugin/ssh/sshchannel_p.h b/src/plugins/coreplugin/ssh/sshchannel_p.h
index 5a1f7ffa81..1fbafeb5de 100644
--- a/src/plugins/coreplugin/ssh/sshchannel_p.h
+++ b/src/plugins/coreplugin/ssh/sshchannel_p.h
@@ -38,7 +38,7 @@
#include <QtCore/QObject>
#include <QtCore/QString>
-QT_FORWARD_DECLARE_CLASS(QTimer);
+QT_FORWARD_DECLARE_CLASS(QTimer)
namespace Core {
namespace Internal {
diff --git a/src/plugins/coreplugin/ssh/sshpacket_p.h b/src/plugins/coreplugin/ssh/sshpacket_p.h
index 009d7665fd..bfff169537 100644
--- a/src/plugins/coreplugin/ssh/sshpacket_p.h
+++ b/src/plugins/coreplugin/ssh/sshpacket_p.h
@@ -79,7 +79,7 @@ enum SshPacketType {
SSH_MSG_CHANNEL_CLOSE = 97,
SSH_MSG_CHANNEL_REQUEST = 98,
SSH_MSG_CHANNEL_SUCCESS = 99,
- SSH_MSG_CHANNEL_FAILURE = 100,
+ SSH_MSG_CHANNEL_FAILURE = 100
};
enum SshExtendedDataType { SSH_EXTENDED_DATA_STDERR = 1 };
diff --git a/src/plugins/coreplugin/ssh/sshremoteprocessrunner.cpp b/src/plugins/coreplugin/ssh/sshremoteprocessrunner.cpp
new file mode 100644
index 0000000000..f8ded6a2c1
--- /dev/null
+++ b/src/plugins/coreplugin/ssh/sshremoteprocessrunner.cpp
@@ -0,0 +1,210 @@
+#include "sshremoteprocessrunner.h"
+
+#define ASSERT_STATE(states) assertState(states, Q_FUNC_INFO)
+
+namespace Core {
+
+class SshRemoteProcessRunnerPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ SshRemoteProcessRunnerPrivate(const SshConnectionParameters &params,
+ QObject *parent);
+ SshRemoteProcessRunnerPrivate(const SshConnection::Ptr &connection,
+ QObject *parent);
+ void run(const QByteArray &command);
+ QByteArray command() const { return m_command; }
+
+ const SshConnection::Ptr m_connection;
+ SshRemoteProcess::Ptr m_process;
+
+signals:
+ void connectionError(Core::SshError);
+ void processStarted();
+ void processOutputAvailable(const QByteArray &output);
+ void processErrorOutputAvailable(const QByteArray &output);
+ void processClosed(int exitStatus);
+
+private slots:
+ void handleConnected();
+ void handleConnectionError(Core::SshError error);
+ void handleDisconnected();
+ void handleProcessStarted();
+ void handleProcessFinished(int exitStatus);
+
+private:
+ enum State { Inactive, Connecting, Connected, ProcessRunning };
+
+ void setState(State state);
+ void assertState(const QList<State> &allowedStates, const char *func);
+ void assertState(State allowedState, const char *func);
+
+ State m_state;
+ QByteArray m_command;
+ const SshConnectionParameters m_params;
+};
+
+
+SshRemoteProcessRunnerPrivate::SshRemoteProcessRunnerPrivate(const SshConnectionParameters &params,
+ QObject *parent)
+ : QObject(parent),
+ m_connection(SshConnection::create()),
+ m_state(Inactive),
+ m_params(params)
+{
+}
+
+SshRemoteProcessRunnerPrivate::SshRemoteProcessRunnerPrivate(const SshConnection::Ptr &connection,
+ QObject *parent)
+ : QObject(parent),
+ m_connection(connection),
+ m_state(Inactive),
+ m_params(connection->connectionParameters())
+{
+}
+
+void SshRemoteProcessRunnerPrivate::run(const QByteArray &command)
+{
+ ASSERT_STATE(Inactive);
+ setState(Connecting);
+
+ m_command = command;
+ connect(m_connection.data(), SIGNAL(error(Core::SshError)),
+ SLOT(handleConnectionError(Core::SshError)));
+ connect(m_connection.data(), SIGNAL(disconnected()),
+ SLOT(handleDisconnected()));
+ if (m_connection->state() == SshConnection::Connected) {
+ handleConnected();
+ } else {
+ connect(m_connection.data(), SIGNAL(connected()),
+ SLOT(handleConnected()));
+ m_connection->connectToHost(m_params);
+ }
+}
+
+void SshRemoteProcessRunnerPrivate::handleConnected()
+{
+ ASSERT_STATE(Connecting);
+ setState(Connected);
+
+ m_process = m_connection->createRemoteProcess(m_command);
+ connect(m_process.data(), SIGNAL(started()), SLOT(handleProcessStarted()));
+ connect(m_process.data(), SIGNAL(closed(int)),
+ SLOT(handleProcessFinished(int)));
+ connect(m_process.data(), SIGNAL(outputAvailable(QByteArray)),
+ SIGNAL(processOutputAvailable(QByteArray)));
+ connect(m_process.data(), SIGNAL(errorOutputAvailable(QByteArray)),
+ SIGNAL(processErrorOutputAvailable(QByteArray)));
+ m_process->start();
+}
+
+void SshRemoteProcessRunnerPrivate::handleConnectionError(Core::SshError error)
+{
+ handleDisconnected();
+ emit connectionError(error);
+}
+
+void SshRemoteProcessRunnerPrivate::handleDisconnected()
+{
+ ASSERT_STATE(QList<State>() << Connecting << Connected << ProcessRunning);
+ setState(Inactive);
+}
+
+void SshRemoteProcessRunnerPrivate::handleProcessStarted()
+{
+ ASSERT_STATE(Connected);
+ setState(ProcessRunning);
+
+ emit processStarted();
+}
+
+void SshRemoteProcessRunnerPrivate::handleProcessFinished(int exitStatus)
+{
+ switch (exitStatus) {
+ case SshRemoteProcess::FailedToStart:
+ ASSERT_STATE(Connected);
+ break;
+ case SshRemoteProcess::KilledBySignal:
+ case SshRemoteProcess::ExitedNormally:
+ ASSERT_STATE(ProcessRunning);
+ break;
+ default:
+ Q_ASSERT_X(false, Q_FUNC_INFO, "Impossible exit status.");
+ }
+ setState(Inactive);
+ emit processClosed(exitStatus);
+}
+
+void SshRemoteProcessRunnerPrivate::setState(State state)
+{
+ if (m_state != state) {
+ m_state = state;
+ if (m_state == Inactive) {
+ if (m_process)
+ disconnect(m_process.data(), 0, this, 0);
+ disconnect(m_connection.data(), 0, this, 0);
+ }
+ }
+}
+
+void SshRemoteProcessRunnerPrivate::assertState(const QList<State> &allowedStates,
+ const char *func)
+{
+ if (!allowedStates.contains(m_state))
+ qWarning("Unexpected state %d in function %s", m_state, func);
+}
+
+void SshRemoteProcessRunnerPrivate::assertState(State allowedState,
+ const char *func)
+{
+ assertState(QList<State>() << allowedState, func);
+}
+
+
+SshRemoteProcessRunner::Ptr SshRemoteProcessRunner::create(const SshConnectionParameters &params)
+{
+ return SshRemoteProcessRunner::Ptr(new SshRemoteProcessRunner(params));
+}
+
+SshRemoteProcessRunner::Ptr SshRemoteProcessRunner::create(const SshConnection::Ptr &connection)
+{
+ return SshRemoteProcessRunner::Ptr(new SshRemoteProcessRunner(connection));
+}
+
+SshRemoteProcessRunner::SshRemoteProcessRunner(const SshConnectionParameters &params)
+ : d(new SshRemoteProcessRunnerPrivate(params, this))
+{
+ init();
+}
+
+SshRemoteProcessRunner::SshRemoteProcessRunner(const SshConnection::Ptr &connection)
+ : d(new SshRemoteProcessRunnerPrivate(connection, this))
+{
+ init();
+}
+
+void SshRemoteProcessRunner::init()
+{
+ connect(d, SIGNAL(connectionError(Core::SshError)),
+ SIGNAL(connectionError(Core::SshError)));
+ connect(d, SIGNAL(processStarted()), SIGNAL(processStarted()));
+ connect(d, SIGNAL(processClosed(int)), SIGNAL(processClosed(int)));
+ connect(d, SIGNAL(processOutputAvailable(QByteArray)),
+ SIGNAL(processOutputAvailable(QByteArray)));
+ connect(d, SIGNAL(processErrorOutputAvailable(QByteArray)),
+ SIGNAL(processErrorOutputAvailable(QByteArray)));
+}
+
+void SshRemoteProcessRunner::run(const QByteArray &command)
+{
+ d->run(command);
+}
+
+QByteArray SshRemoteProcessRunner::command() const { return d->command(); }
+SshConnection::Ptr SshRemoteProcessRunner::connection() const { return d->m_connection; }
+SshRemoteProcess::Ptr SshRemoteProcessRunner::process() const { return d->m_process; }
+
+} // namespace Core
+
+
+#include "sshremoteprocessrunner.moc"
diff --git a/src/plugins/coreplugin/ssh/sshremoteprocessrunner.h b/src/plugins/coreplugin/ssh/sshremoteprocessrunner.h
new file mode 100644
index 0000000000..c55b08aa1c
--- /dev/null
+++ b/src/plugins/coreplugin/ssh/sshremoteprocessrunner.h
@@ -0,0 +1,44 @@
+#ifndef SSHREMOTEPROCESSRUNNER_H
+#define SSHREMOTEPROCESSRUNNER_H
+
+#include "sshconnection.h"
+#include "sshremoteprocess.h"
+
+namespace Core {
+class SshRemoteProcessRunnerPrivate;
+
+// Convenience class for running a remote process over an SSH connection.
+class CORE_EXPORT SshRemoteProcessRunner : public QObject
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(SshRemoteProcessRunner)
+public:
+ typedef QSharedPointer<SshRemoteProcessRunner> Ptr;
+
+ static Ptr create(const SshConnectionParameters &params);
+ static Ptr create(const SshConnection::Ptr &connection);
+
+ void run(const QByteArray &command);
+ QByteArray command() const;
+
+ SshConnection::Ptr connection() const;
+ SshRemoteProcess::Ptr process() const;
+
+signals:
+ void connectionError(Core::SshError);
+ void processStarted();
+ void processOutputAvailable(const QByteArray &output);
+ void processErrorOutputAvailable(const QByteArray &output);
+ void processClosed(int exitStatus); // values are of type SshRemoteProcess::ExitStatus
+
+private:
+ SshRemoteProcessRunner(const SshConnectionParameters &params);
+ SshRemoteProcessRunner(const SshConnection::Ptr &connection);
+ void init();
+
+ SshRemoteProcessRunnerPrivate *d;
+};
+
+} // namespace Core
+
+#endif // SSHREMOTEPROCESSRUNNER_H
diff --git a/src/plugins/coreplugin/variablemanager.cpp b/src/plugins/coreplugin/variablemanager.cpp
index f55653e31f..1a7d0d02df 100644
--- a/src/plugins/coreplugin/variablemanager.cpp
+++ b/src/plugins/coreplugin/variablemanager.cpp
@@ -36,6 +36,7 @@
#include "editormanager/ieditor.h"
#include "editormanager/editormanager.h"
+#include <utils/stringutils.h>
#include <utils/qtcassert.h>
#include <QtCore/QFileInfo>
@@ -45,6 +46,15 @@
namespace Core {
+class VMMapExpander : public Utils::AbstractQtcMacroExpander {
+public:
+ virtual bool resolveMacro(const QString &name, QString *ret)
+ {
+ *ret = Core::VariableManager::instance()->value(name);
+ return !ret->isEmpty();
+ }
+};
+
class VariableManagerPrivate : public QObject
{
Q_OBJECT
@@ -58,7 +68,8 @@ public slots:
void updateCurrentDocument(Core::IEditor *editor);
public:
- QMap<QString, QString> m_map;
+ QHash<QString, QString> m_map;
+ VMMapExpander m_macroExpander;
static VariableManager *m_instance;
};
@@ -148,20 +159,6 @@ QString VariableManager::value(const QString &variable, const QString &defaultVa
return d->m_map.value(variable, defaultValue);
}
-QString VariableManager::resolve(const QString &stringWithVariables) const
-{
- QString result = stringWithVariables;
- QMapIterator<QString, QString> i(d->m_map);
- while (i.hasNext()) {
- i.next();
- QString key = QLatin1String("${");
- key += i.key();
- key += QLatin1Char('}');
- result.replace(key, i.value());
- }
- return result;
-}
-
void VariableManager::insert(const QString &variable, const QString &value)
{
d->insert(variable, value);
@@ -182,6 +179,11 @@ bool VariableManager::remove(const QString &variable)
return d->remove(variable);
}
+Utils::AbstractMacroExpander *VariableManager::macroExpander()
+{
+ return &d->m_macroExpander;
+}
+
VariableManager* VariableManager::instance()
{
return VariableManagerPrivate::m_instance;
diff --git a/src/plugins/coreplugin/variablemanager.h b/src/plugins/coreplugin/variablemanager.h
index a5d86bef84..386bf94ab2 100644
--- a/src/plugins/coreplugin/variablemanager.h
+++ b/src/plugins/coreplugin/variablemanager.h
@@ -43,6 +43,10 @@ QT_BEGIN_NAMESPACE
class QFileInfo;
QT_END_NAMESPACE
+namespace Utils {
+class AbstractMacroExpander;
+}
+
namespace Core {
class VariableManagerPrivate;
@@ -62,7 +66,7 @@ public:
QString value(const QString &variable) const;
QString value(const QString &variable, const QString &defaultValue) const;
bool remove(const QString &variable);
- QString resolve(const QString &stringWithVariables) const;
+ Utils::AbstractMacroExpander *macroExpander();
private:
QScopedPointer<VariableManagerPrivate> d;
diff --git a/src/plugins/coreplugin/vcsmanager.cpp b/src/plugins/coreplugin/vcsmanager.cpp
index c6badc63d1..428d754816 100644
--- a/src/plugins/coreplugin/vcsmanager.cpp
+++ b/src/plugins/coreplugin/vcsmanager.cpp
@@ -63,22 +63,24 @@ static inline VersionControlList allVersionControls()
// ---- VCSManagerPrivate:
// Maintains a cache of top-level directory->version control.
-struct VCSManagerPrivate {
+class VcsManagerPrivate
+{
+public:
VersionControlCache m_cachedMatches;
};
-VCSManager::VCSManager(QObject *parent) :
+VcsManager::VcsManager(QObject *parent) :
QObject(parent),
- m_d(new VCSManagerPrivate)
+ m_d(new VcsManagerPrivate)
{
}
-VCSManager::~VCSManager()
+VcsManager::~VcsManager()
{
delete m_d;
}
-void VCSManager::extensionsInitialized()
+void VcsManager::extensionsInitialized()
{
// Change signal connections
FileManager *fileManager = ICore::instance()->fileManager();
@@ -90,7 +92,12 @@ void VCSManager::extensionsInitialized()
}
}
-IVersionControl* VCSManager::findVersionControlForDirectory(const QString &directory,
+static bool longerThanPath(QPair<QString, IVersionControl *> &pair1, QPair<QString, IVersionControl *> &pair2)
+{
+ return pair1.first.size() > pair2.first.size();
+}
+
+IVersionControl* VcsManager::findVersionControlForDirectory(const QString &directory,
QString *topLevelDirectory)
{
typedef VersionControlCache::const_iterator VersionControlCacheConstIterator;
@@ -147,31 +154,47 @@ IVersionControl* VCSManager::findVersionControlForDirectory(const QString &direc
// Nothing: ask the IVersionControls directly, insert the toplevel into the cache.
const VersionControlList versionControls = allVersionControls();
+ QList<QPair<QString, IVersionControl *> > allThatCanManage;
+
foreach (IVersionControl * versionControl, versionControls) {
QString topLevel;
if (versionControl->managesDirectory(directory, &topLevel)) {
- m_d->m_cachedMatches.insert(topLevel, versionControl);
- if (topLevelDirectory)
- *topLevelDirectory = topLevel;
if (debug)
- qDebug("<findVersionControlForDirectory: invocation of '%s' matches: %s",
- qPrintable(versionControl->displayName()), qPrintable(topLevel));
- return versionControl;
+ qDebug("<findVersionControlForDirectory: %s manages %s",
+ qPrintable(versionControl->displayName()),
+ qPrintable(topLevel));
+ allThatCanManage.push_back(qMakePair(topLevel, versionControl));
}
}
+
+ // To properly find a nested repository (say, git checkout inside SVN),
+ // we need to select the version control with the longest toplevel pathname.
+ qSort(allThatCanManage.begin(), allThatCanManage.end(), longerThanPath);
+
+ if (!allThatCanManage.isEmpty()) {
+ QString toplevel = allThatCanManage.first().first;
+ IVersionControl *versionControl = allThatCanManage.first().second;
+ m_d->m_cachedMatches.insert(toplevel, versionControl);
+ if (topLevelDirectory)
+ *topLevelDirectory = toplevel;
+ if (debug)
+ qDebug("<findVersionControlForDirectory: invocation of '%s' matches: %s",
+ qPrintable(versionControl->displayName()), qPrintable(toplevel));
+ return versionControl;
+ }
if (debug)
qDebug("<findVersionControlForDirectory: No match for %s", qPrintable(directory));
return 0;
}
-bool VCSManager::promptToDelete(const QString &fileName)
+bool VcsManager::promptToDelete(const QString &fileName)
{
if (IVersionControl *vc = findVersionControlForDirectory(QFileInfo(fileName).absolutePath()))
return promptToDelete(vc, fileName);
return true;
}
-IVersionControl *VCSManager::checkout(const QString &versionControlType,
+IVersionControl *VcsManager::checkout(const QString &versionControlType,
const QString &directory,
const QByteArray &url)
{
@@ -188,7 +211,7 @@ IVersionControl *VCSManager::checkout(const QString &versionControlType,
return 0;
}
-bool VCSManager::findVersionControl(const QString &versionControlType)
+bool VcsManager::findVersionControl(const QString &versionControlType)
{
foreach (IVersionControl * versionControl, allVersionControls()) {
if (versionControl->displayName() == versionControlType)
@@ -197,7 +220,7 @@ bool VCSManager::findVersionControl(const QString &versionControlType)
return false;
}
-QString VCSManager::getRepositoryURL(const QString &directory)
+QString VcsManager::repositoryUrl(const QString &directory)
{
IVersionControl *vc = findVersionControlForDirectory(directory);
@@ -206,15 +229,14 @@ QString VCSManager::getRepositoryURL(const QString &directory)
return QString();
}
-bool VCSManager::promptToDelete(IVersionControl *vc, const QString &fileName)
+bool VcsManager::promptToDelete(IVersionControl *vc, const QString &fileName)
{
QTC_ASSERT(vc, return true)
if (!vc->supportsOperation(IVersionControl::DeleteOperation))
return true;
- const QString title = QCoreApplication::translate("VCSManager", "Version Control");
- const QString msg = QCoreApplication::translate("VCSManager",
- "Would you like to remove this file from the version control system (%1)?\n"
- "Note: This might remove the local file.").arg(vc->displayName());
+ const QString title = tr("Version Control");
+ const QString msg = tr("Would you like to remove this file from the version control system (%1)?\n"
+ "Note: This might remove the local file.").arg(vc->displayName());
const QMessageBox::StandardButton button =
QMessageBox::question(0, title, msg, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
if (button != QMessageBox::Yes)
@@ -222,7 +244,7 @@ bool VCSManager::promptToDelete(IVersionControl *vc, const QString &fileName)
return vc->vcsDelete(fileName);
}
-CORE_EXPORT QDebug operator<<(QDebug in, const VCSManager &v)
+CORE_EXPORT QDebug operator<<(QDebug in, const VcsManager &v)
{
QDebug nospace = in.nospace();
const VersionControlCache::const_iterator cend = v.m_d->m_cachedMatches.constEnd();
diff --git a/src/plugins/coreplugin/vcsmanager.h b/src/plugins/coreplugin/vcsmanager.h
index ad81f04c40..7dbca605ff 100644
--- a/src/plugins/coreplugin/vcsmanager.h
+++ b/src/plugins/coreplugin/vcsmanager.h
@@ -45,12 +45,12 @@ QT_END_NAMESPACE
namespace Core {
-struct VCSManagerPrivate;
+class VcsManagerPrivate;
class IVersionControl;
-/* VCSManager:
+/* VcsManager:
* 1) Provides functionality for finding the IVersionControl * for a given
- * filename (findVersionControlForDirectory). Note that the VCSManager assumes
+ * filename (findVersionControlForDirectory). Note that the VcsManager assumes
* that if a IVersionControl * manages a directory, then it also manages
* all the files and all the subdirectories.
* It works by asking all IVersionControl * if they manage the file, and ask
@@ -60,13 +60,12 @@ class IVersionControl;
* branching repositories and routes them to its signals (repositoryChanged,
* filesChanged). */
-class CORE_EXPORT VCSManager : public QObject
+class CORE_EXPORT VcsManager : public QObject
{
Q_OBJECT
- Q_DISABLE_COPY(VCSManager)
public:
- explicit VCSManager(QObject *parent = 0);
- virtual ~VCSManager();
+ explicit VcsManager(QObject *parent = 0);
+ virtual ~VcsManager();
void extensionsInitialized();
@@ -75,8 +74,10 @@ public:
IVersionControl *checkout(const QString &versionControlType,
const QString &directory,
const QByteArray &url);
+ // Used only by Trac plugin.
bool findVersionControl(const QString &versionControl);
- QString getRepositoryURL(const QString &directory);
+ // Used only by Trac plugin.
+ QString repositoryUrl(const QString &directory);
// Shows a confirmation dialog, whether the file should also be deleted
// from revision control Calls sccDelete on the file. Returns false
@@ -84,16 +85,16 @@ public:
bool promptToDelete(const QString &fileName);
bool promptToDelete(IVersionControl *versionControl, const QString &fileName);
- friend CORE_EXPORT QDebug operator<<(QDebug in, const VCSManager &);
+ friend CORE_EXPORT QDebug operator<<(QDebug in, const VcsManager &);
signals:
void repositoryChanged(const QString &repository);
private:
- VCSManagerPrivate *m_d;
+ VcsManagerPrivate *m_d;
};
-CORE_EXPORT QDebug operator<<(QDebug in, const VCSManager &);
+CORE_EXPORT QDebug operator<<(QDebug in, const VcsManager &);
} // namespace Core
diff --git a/src/plugins/cpaster/CodePaster.pluginspec b/src/plugins/cpaster/CodePaster.pluginspec
deleted file mode 100644
index 006e5747af..0000000000
--- a/src/plugins/cpaster/CodePaster.pluginspec
+++ /dev/null
@@ -1,20 +0,0 @@
-<plugin name="CodePaster" version="2.0.95" compatVersion="2.0.95">
- <vendor>Nokia Corporation</vendor>
- <copyright>(C) 2010 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>Codepaster plugin for pushing/fetching diff from server</description>
- <url>http://qt.nokia.com</url>
- <dependencyList>
- <dependency name="TextEditor" version="2.0.95"/>
- <dependency name="ProjectExplorer" version="2.0.95"/>
- <dependency name="Core" version="2.0.95"/>
- </dependencyList>
-</plugin>
diff --git a/src/plugins/cpaster/CodePaster.pluginspec.in b/src/plugins/cpaster/CodePaster.pluginspec.in
new file mode 100644
index 0000000000..4fce738332
--- /dev/null
+++ b/src/plugins/cpaster/CodePaster.pluginspec.in
@@ -0,0 +1,19 @@
+<plugin name=\"CodePaster\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2010 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>Codepaster plugin for pushing/fetching diff from server</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name=\"TextEditor\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/cpaster/cpaster_dependencies.pri b/src/plugins/cpaster/cpaster_dependencies.pri
index 5c489ae1c4..ec55414dcf 100644
--- a/src/plugins/cpaster/cpaster_dependencies.pri
+++ b/src/plugins/cpaster/cpaster_dependencies.pri
@@ -1,3 +1,2 @@
-include(../../plugins/projectexplorer/projectexplorer.pri)
include(../../plugins/texteditor/texteditor.pri)
include(../../plugins/coreplugin/coreplugin.pri)
diff --git a/src/plugins/cpaster/cpasterplugin.cpp b/src/plugins/cpaster/cpasterplugin.cpp
index ed1bb07cf3..59d1277239 100644
--- a/src/plugins/cpaster/cpasterplugin.cpp
+++ b/src/plugins/cpaster/cpasterplugin.cpp
@@ -46,6 +46,7 @@
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/command.h>
+#include <coreplugin/uniqueidmanager.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/mimedatabase.h>
diff --git a/src/plugins/cpaster/fileshareprotocolsettingspage.cpp b/src/plugins/cpaster/fileshareprotocolsettingspage.cpp
index b8fcb5de4d..b1230266ff 100644
--- a/src/plugins/cpaster/fileshareprotocolsettingspage.cpp
+++ b/src/plugins/cpaster/fileshareprotocolsettingspage.cpp
@@ -100,7 +100,7 @@ FileShareProtocolSettings FileShareProtocolSettingsWidget::settings() const
// ----------FileShareProtocolSettingsPage
FileShareProtocolSettingsPage::FileShareProtocolSettingsPage(const QSharedPointer<FileShareProtocolSettings> &s,
QObject *parent) :
- Core::IOptionsPage(parent), m_settings(s)
+ Core::IOptionsPage(parent), m_settings(s), m_widget(0)
{
}
@@ -138,6 +138,8 @@ QWidget *FileShareProtocolSettingsPage::createPage(QWidget *parent)
void FileShareProtocolSettingsPage::apply()
{
+ if (!m_widget) // page was never shown
+ return;
const FileShareProtocolSettings newSettings = m_widget->settings();
if (newSettings != *m_settings) {
*m_settings = newSettings;
diff --git a/src/plugins/cpaster/settingspage.cpp b/src/plugins/cpaster/settingspage.cpp
index d4b3d75e66..436bc5a888 100644
--- a/src/plugins/cpaster/settingspage.cpp
+++ b/src/plugins/cpaster/settingspage.cpp
@@ -80,7 +80,7 @@ Settings SettingsWidget::settings()
}
SettingsPage::SettingsPage(const QSharedPointer<Settings> &settings) :
- m_settings(settings)
+ m_settings(settings), m_widget(0)
{
}
@@ -125,7 +125,8 @@ QWidget *SettingsPage::createPage(QWidget *parent)
void SettingsPage::apply()
{
- QTC_ASSERT(m_widget, return)
+ if (!m_widget) // page was never shown
+ return;
const Settings newSettings = m_widget->settings();
if (newSettings != *m_settings) {
*m_settings = newSettings;
diff --git a/src/plugins/cppeditor/CppEditor.pluginspec b/src/plugins/cppeditor/CppEditor.pluginspec
deleted file mode 100644
index f006943113..0000000000
--- a/src/plugins/cppeditor/CppEditor.pluginspec
+++ /dev/null
@@ -1,21 +0,0 @@
-<plugin name="CppEditor" version="2.0.95" compatVersion="2.0.95">
- <vendor>Nokia Corporation</vendor>
- <copyright>(C) 2010 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>
- <category>C++</category>
- <description>C/C++ editor component.</description>
- <url>http://qt.nokia.com</url>
- <dependencyList>
- <dependency name="Core" version="2.0.95"/>
- <dependency name="TextEditor" version="2.0.95"/>
- <dependency name="CppTools" version="2.0.95"/>
- </dependencyList>
-</plugin>
diff --git a/src/plugins/cppeditor/CppEditor.pluginspec.in b/src/plugins/cppeditor/CppEditor.pluginspec.in
new file mode 100644
index 0000000000..bdb82452e8
--- /dev/null
+++ b/src/plugins/cppeditor/CppEditor.pluginspec.in
@@ -0,0 +1,21 @@
+<plugin name=\"CppEditor\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2010 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>
+ <category>C++</category>
+ <description>C/C++ editor component.</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"TextEditor\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"CppTools\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/cppeditor/cppautocompleter.cpp b/src/plugins/cppeditor/cppautocompleter.cpp
new file mode 100644
index 0000000000..5b3b19db5a
--- /dev/null
+++ b/src/plugins/cppeditor/cppautocompleter.cpp
@@ -0,0 +1,138 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "cppautocompleter.h"
+
+#include <Token.h>
+
+#include <cplusplus/SimpleLexer.h>
+#include <cplusplus/MatchingText.h>
+#include <cplusplus/BackwardsScanner.h>
+
+#include <QtCore/QLatin1Char>
+#include <QtGui/QTextCursor>
+
+using namespace CppEditor;
+using namespace Internal;
+using namespace CPlusPlus;
+
+CppAutoCompleter::CppAutoCompleter()
+{}
+
+CppAutoCompleter::~CppAutoCompleter()
+{}
+
+bool CppAutoCompleter::contextAllowsAutoParentheses(const QTextCursor &cursor,
+ const QString &textToInsert) const
+{
+ QChar ch;
+
+ if (! textToInsert.isEmpty())
+ ch = textToInsert.at(0);
+
+ if (! (MatchingText::shouldInsertMatchingText(cursor)
+ || ch == QLatin1Char('\'')
+ || ch == QLatin1Char('"')))
+ return false;
+ else if (isInComment(cursor))
+ return false;
+
+ return true;
+}
+
+bool CppAutoCompleter::contextAllowsElectricCharacters(const QTextCursor &cursor) const
+{
+ const Token tk = SimpleLexer::tokenAt(cursor.block().text(), cursor.positionInBlock(),
+ BackwardsScanner::previousBlockState(cursor.block()));
+
+ // XXX Duplicated from CPPEditor::isInComment to avoid tokenizing twice
+ if (tk.isComment()) {
+ const unsigned pos = cursor.selectionEnd() - cursor.block().position();
+
+ if (pos == tk.end()) {
+ if (tk.is(T_CPP_COMMENT) || tk.is(T_CPP_DOXY_COMMENT))
+ return false;
+
+ const int state = cursor.block().userState() & 0xFF;
+ if (state > 0)
+ return false;
+ }
+
+ if (pos < tk.end())
+ return false;
+ }
+ else if (tk.is(T_STRING_LITERAL) || tk.is(T_WIDE_STRING_LITERAL)
+ || tk.is(T_CHAR_LITERAL) || tk.is(T_WIDE_CHAR_LITERAL)) {
+
+ const unsigned pos = cursor.selectionEnd() - cursor.block().position();
+ if (pos <= tk.end())
+ return false;
+ }
+
+ return true;
+}
+
+bool CppAutoCompleter::isInComment(const QTextCursor &cursor) const
+{
+ const Token tk = SimpleLexer::tokenAt(cursor.block().text(), cursor.positionInBlock(),
+ BackwardsScanner::previousBlockState(cursor.block()));
+
+ if (tk.isComment()) {
+ const unsigned pos = cursor.selectionEnd() - cursor.block().position();
+
+ if (pos == tk.end()) {
+ if (tk.is(T_CPP_COMMENT) || tk.is(T_CPP_DOXY_COMMENT))
+ return true;
+
+ const int state = cursor.block().userState() & 0xFF;
+ if (state > 0)
+ return true;
+ }
+
+ if (pos < tk.end())
+ return true;
+ }
+
+ return false;
+}
+
+QString CppAutoCompleter::insertMatchingBrace(const QTextCursor &cursor,
+ const QString &text,
+ QChar la,
+ int *skippedChars) const
+{
+ MatchingText m;
+ return m.insertMatchingBrace(cursor, text, la, skippedChars);
+}
+
+QString CppAutoCompleter::insertParagraphSeparator(const QTextCursor &cursor) const
+{
+ MatchingText m;
+ return m.insertParagraphSeparator(cursor);
+}
diff --git a/src/plugins/cppeditor/cppautocompleter.h b/src/plugins/cppeditor/cppautocompleter.h
new file mode 100644
index 0000000000..b9ba066e64
--- /dev/null
+++ b/src/plugins/cppeditor/cppautocompleter.h
@@ -0,0 +1,58 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 CPPAUTOCOMPLETER_H
+#define CPPAUTOCOMPLETER_H
+
+#include <texteditor/autocompleter.h>
+
+namespace CppEditor {
+namespace Internal {
+
+class CppAutoCompleter : public TextEditor::AutoCompleter
+{
+public:
+ CppAutoCompleter();
+ virtual ~CppAutoCompleter();
+
+ virtual bool contextAllowsAutoParentheses(const QTextCursor &cursor,
+ const QString &textToInsert = QString()) const;
+ virtual bool contextAllowsElectricCharacters(const QTextCursor &cursor) const;
+ virtual bool isInComment(const QTextCursor &cursor) const;
+ virtual QString insertMatchingBrace(const QTextCursor &cursor,
+ const QString &text,
+ QChar la,
+ int *skippedChars) const;
+ virtual QString insertParagraphSeparator(const QTextCursor &cursor) const;
+};
+
+} // Internal
+} // CppEditor
+
+#endif // CPPAUTOCOMPLETER_H
diff --git a/src/plugins/cppeditor/cppcompleteswitch.cpp b/src/plugins/cppeditor/cppcompleteswitch.cpp
new file mode 100644
index 0000000000..e23ee3b5a6
--- /dev/null
+++ b/src/plugins/cppeditor/cppcompleteswitch.cpp
@@ -0,0 +1,212 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "cppcompleteswitch.h"
+
+#include <cplusplus/Overview.h>
+#include <cplusplus/TypeOfExpression.h>
+#include <cpptools/cpprefactoringchanges.h>
+#include <utils/changeset.h>
+
+#include <AST.h>
+#include <ASTVisitor.h>
+#include <CoreTypes.h>
+#include <Symbols.h>
+
+#include <QtGui/QApplication>
+
+using namespace CPlusPlus;
+using namespace CppEditor;
+using namespace CppEditor::Internal;
+using namespace CppTools;
+using namespace Utils;
+
+namespace {
+
+class CaseStatementCollector : public ASTVisitor
+{
+public:
+ CaseStatementCollector(Document::Ptr document, const Snapshot &snapshot,
+ Scope *scope)
+ : ASTVisitor(document->translationUnit()),
+ document(document),
+ scope(scope)
+ {
+ typeOfExpression.init(document, snapshot);
+ }
+
+ QStringList operator ()(AST *ast)
+ {
+ values.clear();
+ foundCaseStatementLevel = false;
+ accept(ast);
+ return values;
+ }
+
+ bool preVisit(AST *ast) {
+ if (CaseStatementAST *cs = ast->asCaseStatement()) {
+ foundCaseStatementLevel = true;
+ if (ExpressionAST *expression = cs->expression->asIdExpression()) {
+ QList<LookupItem> candidates = typeOfExpression(expression,
+ document,
+ scope);
+ if (!candidates .isEmpty() && candidates.first().declaration()) {
+ Symbol *decl = candidates.first().declaration();
+ values << prettyPrint(LookupContext::fullyQualifiedName(decl));
+ }
+ }
+ return true;
+ } else if (foundCaseStatementLevel) {
+ return false;
+ }
+ return true;
+ }
+
+ Overview prettyPrint;
+ bool foundCaseStatementLevel;
+ QStringList values;
+ TypeOfExpression typeOfExpression;
+ Document::Ptr document;
+ Scope *scope;
+};
+
+class Operation: public CppQuickFixOperation
+{
+public:
+ Operation(const CppQuickFixState &state, int priority, CompoundStatementAST *compoundStatement, const QStringList &values)
+ : CppQuickFixOperation(state, priority)
+ , compoundStatement(compoundStatement)
+ , values(values)
+ {
+ setDescription(QApplication::translate("CppTools::QuickFix",
+ "Complete Switch Statement"));
+ }
+
+
+ virtual void performChanges(CppRefactoringFile *currentFile, CppRefactoringChanges *)
+ {
+ ChangeSet changes;
+ int start = currentFile->endOf(compoundStatement->lbrace_token);
+ changes.insert(start, QLatin1String("\ncase ")
+ + values.join(QLatin1String(":\nbreak;\ncase "))
+ + QLatin1String(":\nbreak;"));
+ currentFile->change(changes);
+ currentFile->indent(currentFile->range(compoundStatement));
+ }
+
+ CompoundStatementAST *compoundStatement;
+ QStringList values;
+};
+
+static Enum *findEnum(const QList<LookupItem> &results,
+ const LookupContext &ctxt)
+{
+ foreach (const LookupItem &result, results) {
+ const FullySpecifiedType fst = result.type();
+
+ Type *type = result.declaration() ? result.declaration()->type().type()
+ : fst.type();
+
+ if (!type)
+ continue;
+ if (Enum *e = type->asEnumType())
+ return e;
+ if (const NamedType *namedType = type->asNamedType()) {
+ const QList<LookupItem> candidates =
+ ctxt.lookup(namedType->name(), result.scope());
+ return findEnum(candidates, ctxt);
+ }
+ }
+
+ return 0;
+}
+
+static Enum *conditionEnum(const CppQuickFixState &state,
+ SwitchStatementAST *statement)
+{
+ Block *block = statement->symbol;
+ Scope *scope = state.document()->scopeAt(block->line(), block->column());
+ TypeOfExpression typeOfExpression;
+ typeOfExpression.init(state.document(), state.snapshot());
+ const QList<LookupItem> results = typeOfExpression(statement->condition,
+ state.document(),
+ scope);
+
+ return findEnum(results, typeOfExpression.context());
+}
+
+} // end of anonymous namespace
+
+QList<CppQuickFixOperation::Ptr> CompleteSwitchCaseStatement::match(const CppQuickFixState &state)
+{
+ const QList<AST *> &path = state.path();
+
+ if (path.isEmpty())
+ return noResult(); // nothing to do
+
+ // look for switch statement
+ for (int depth = path.size() - 1; depth >= 0; --depth) {
+ AST *ast = path.at(depth);
+ SwitchStatementAST *switchStatement = ast->asSwitchStatement();
+ if (switchStatement) {
+ if (!state.isCursorOn(switchStatement->switch_token) || !switchStatement->statement)
+ return noResult();
+ CompoundStatementAST *compoundStatement = switchStatement->statement->asCompoundStatement();
+ if (!compoundStatement) // we ignore pathologic case "switch (t) case A: ;"
+ return noResult();
+ // look if the condition's type is an enum
+ if (Enum *e = conditionEnum(state, switchStatement)) {
+ // check the possible enum values
+ QStringList values;
+ Overview prettyPrint;
+ for (unsigned i = 0; i < e->memberCount(); ++i) {
+ if (Declaration *decl = e->memberAt(i)->asDeclaration()) {
+ values << prettyPrint(LookupContext::fullyQualifiedName(decl));
+ }
+ }
+ // Get the used values
+ Block *block = switchStatement->symbol;
+ CaseStatementCollector caseValues(state.document(), state.snapshot(),
+ state.document()->scopeAt(block->line(), block->column()));
+ QStringList usedValues = caseValues(switchStatement);
+ // save the values that would be added
+ foreach (const QString &usedValue, usedValues)
+ values.removeAll(usedValue);
+ if (values.isEmpty())
+ return noResult();
+ else
+ return singleResult(new Operation(state, depth, compoundStatement, values));
+ }
+
+ return noResult();
+ }
+ }
+
+ return noResult();
+}
diff --git a/src/plugins/cppeditor/cppcompleteswitch.h b/src/plugins/cppeditor/cppcompleteswitch.h
new file mode 100644
index 0000000000..57772aa31c
--- /dev/null
+++ b/src/plugins/cppeditor/cppcompleteswitch.h
@@ -0,0 +1,52 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 CPPCOMPLETESWITCH_H
+#define CPPCOMPLETESWITCH_H
+
+#include "cppquickfix.h"
+
+#include <CPlusPlusForwardDeclarations.h>
+
+namespace CppEditor {
+namespace Internal {
+
+/*!
+ Adds missing case statements for "switch (enumVariable)"
+ */
+class CompleteSwitchCaseStatement: public CppQuickFixFactory
+{
+public:
+ virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state);
+};
+
+} // namespace Internal
+} // namespace CppEditor
+
+#endif // CPPCOMPLETESWITCH_H
diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp
index f6d90124c8..b52a566ac9 100644
--- a/src/plugins/cppeditor/cppeditor.cpp
+++ b/src/plugins/cppeditor/cppeditor.cpp
@@ -38,6 +38,9 @@
#include "cppchecksymbols.h"
#include "cppquickfix.h"
#include "cpplocalsymbols.h"
+#include "cppquickfixcollector.h"
+#include "cppqtstyleindenter.h"
+#include "cppautocompleter.h"
#include <AST.h>
#include <Control.h>
@@ -50,6 +53,7 @@
#include <ASTVisitor.h>
#include <SymbolVisitor.h>
#include <TranslationUnit.h>
+#include <cplusplus/ASTPath.h>
#include <cplusplus/ExpressionUnderCursor.h>
#include <cplusplus/TypeOfExpression.h>
#include <cplusplus/Overview.h>
@@ -68,6 +72,7 @@
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/command.h>
+#include <coreplugin/uniqueidmanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/mimedatabase.h>
@@ -75,7 +80,9 @@
#include <extensionsystem/pluginmanager.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <texteditor/basetextdocument.h>
+#include <texteditor/basetextdocumentlayout.h>
#include <texteditor/fontsettings.h>
+#include <texteditor/tabsettings.h>
#include <texteditor/texteditorconstants.h>
#include <QtCore/QDebug>
@@ -414,6 +421,9 @@ CPPEditor::CPPEditor(QWidget *parent)
setParenthesesMatchingEnabled(true);
setMarksVisible(true);
setCodeFoldingSupported(true);
+ setIndenter(new CppQtStyleIndenter);
+ setAutoCompleter(new CppAutoCompleter);
+
baseTextDocument()->setSyntaxHighlighter(new CppHighlighter);
m_modelManager = CppTools::CppModelManagerInterface::instance();
@@ -1102,21 +1112,30 @@ void CPPEditor::switchDeclarationDefinition()
if (! lastVisibleSymbol)
return;
- Function *functionScope = lastVisibleSymbol->asFunction();
- if (! functionScope)
- functionScope = lastVisibleSymbol->enclosingFunction();
+ Function *function = lastVisibleSymbol->asFunction();
+ if (! function)
+ function = lastVisibleSymbol->enclosingFunction();
- if (functionScope) {
+ if (function) {
LookupContext context(thisDocument, snapshot);
- Function *functionDefinition = functionScope->asFunction();
+ Function *functionDefinition = function->asFunction();
+ ClassOrNamespace *binding = context.lookupType(functionDefinition);
+
const QList<LookupItem> declarations = context.lookup(functionDefinition->name(), functionDefinition->enclosingScope());
+ QList<Symbol *> best;
foreach (const LookupItem &r, declarations) {
- Symbol *decl = r.declaration();
- // TODO: check decl.
- openCppEditorAt(linkToSymbol(decl));
- break;
+ if (Symbol *decl = r.declaration()) {
+ if (Function *funTy = decl->type()->asFunctionType()) {
+ if (funTy->isEqualTo(function) && decl != function && binding == r.binding())
+ best.prepend(decl);
+ else
+ best.append(decl);
+ }
+ }
}
+ if (! best.isEmpty())
+ openCppEditorAt(linkToSymbol(best.first()));
} else if (lastVisibleSymbol && lastVisibleSymbol->isDeclaration() && lastVisibleSymbol->type()->isFunctionType()) {
if (Symbol *def = snapshot.findMatchingDefinition(lastVisibleSymbol))
@@ -1168,6 +1187,195 @@ static inline LookupItem skipForwardDeclarations(const QList<LookupItem> &resolv
return result;
}
+namespace {
+
+QList<Declaration *> findMatchingDeclaration(const LookupContext &context,
+ Function *functionType)
+{
+ QList<Declaration *> result;
+
+ Scope *enclosingScope = functionType->enclosingScope();
+ while (! (enclosingScope->isNamespace() || enclosingScope->isClass()))
+ enclosingScope = enclosingScope->enclosingScope();
+ Q_ASSERT(enclosingScope != 0);
+
+ const Name *functionName = functionType->name();
+ if (! functionName)
+ return result; // anonymous function names are not valid c++
+
+ ClassOrNamespace *binding = 0;
+ const QualifiedNameId *qName = functionName->asQualifiedNameId();
+ if (qName) {
+ if (qName->base())
+ binding = context.lookupType(qName->base(), enclosingScope);
+ functionName = qName->name();
+ }
+
+ if (!binding) { // declaration for a global function
+ binding = context.lookupType(enclosingScope);
+
+ if (!binding)
+ return result;
+ }
+
+ const Identifier *funcId = functionName->identifier();
+ if (!funcId) // E.g. operator, which we might be able to handle in the future...
+ return result;
+
+ QList<Declaration *> good, better, best;
+
+ foreach (Symbol *s, binding->symbols()) {
+ Class *matchingClass = s->asClass();
+ if (!matchingClass)
+ continue;
+
+ for (Symbol *s = matchingClass->find(funcId); s; s = s->next()) {
+ if (! s->name())
+ continue;
+ else if (! funcId->isEqualTo(s->identifier()))
+ continue;
+ else if (! s->type()->isFunctionType())
+ continue;
+ else if (Declaration *decl = s->asDeclaration()) {
+ if (Function *declFunTy = decl->type()->asFunctionType()) {
+ if (functionType->isEqualTo(declFunTy))
+ best.prepend(decl);
+ else if (functionType->argumentCount() == declFunTy->argumentCount() && result.isEmpty())
+ better.prepend(decl);
+ else
+ good.append(decl);
+ }
+ }
+ }
+ }
+
+ result.append(best);
+ result.append(better);
+ result.append(good);
+
+ return result;
+}
+
+} // end of anonymous namespace
+
+CPPEditor::Link CPPEditor::attemptFuncDeclDef(const QTextCursor &cursor, const Document::Ptr &doc, Snapshot snapshot) const
+{
+ snapshot.insert(doc);
+
+ Link result;
+
+ QList<AST *> path = ASTPath(doc)(cursor);
+
+ if (path.size() < 5)
+ return result;
+
+ NameAST *name = path.last()->asName();
+ if (!name)
+ return result;
+
+ if (QualifiedNameAST *qName = path.at(path.size() - 2)->asQualifiedName()) {
+ // TODO: check which part of the qualified name we're on
+ if (qName->unqualified_name != name)
+ return result;
+ }
+
+ for (int i = path.size() - 1; i != -1; --i) {
+ AST *node = path.at(i);
+
+ if (node->asParameterDeclaration() != 0)
+ return result;
+ }
+
+ AST *declParent = 0;
+ DeclaratorAST *decl = 0;
+ for (int i = path.size() - 2; i > 0; --i) {
+ if ((decl = path.at(i)->asDeclarator()) != 0) {
+ declParent = path.at(i - 1);
+ break;
+ }
+ }
+ if (!decl || !declParent)
+ return result;
+ if (!decl->postfix_declarator_list || !decl->postfix_declarator_list->value)
+ return result;
+ FunctionDeclaratorAST *funcDecl = decl->postfix_declarator_list->value->asFunctionDeclarator();
+ if (!funcDecl)
+ return result;
+
+ Symbol *target = 0;
+ if (FunctionDefinitionAST *funDef = declParent->asFunctionDefinition()) {
+ QList<Declaration *> candidates = findMatchingDeclaration(LookupContext(doc, snapshot),
+ funDef->symbol);
+ if (!candidates.isEmpty()) // TODO: improve disambiguation
+ target = candidates.first();
+ } else if (declParent->asSimpleDeclaration()) {
+ target = snapshot.findMatchingDefinition(funcDecl->symbol);
+ }
+
+ if (target) {
+ result = linkToSymbol(target);
+
+ unsigned startLine, startColumn, endLine, endColumn;
+ doc->translationUnit()->getTokenStartPosition(name->firstToken(), &startLine, &startColumn);
+ doc->translationUnit()->getTokenEndPosition(name->lastToken() - 1, &endLine, &endColumn);
+
+ QTextDocument *textDocument = cursor.document();
+ result.begin = textDocument->findBlockByNumber(startLine - 1).position() + startColumn - 1;
+ result.end = textDocument->findBlockByNumber(endLine - 1).position() + endColumn - 1;
+ }
+
+ return result;
+}
+
+CPPEditor::Link CPPEditor::findMacroLink(const QByteArray &name) const
+{
+ if (! name.isEmpty()) {
+ if (Document::Ptr doc = m_lastSemanticInfo.doc) {
+ const Snapshot snapshot = m_modelManager->snapshot();
+ QSet<QString> processed;
+ return findMacroLink(name, doc, snapshot, &processed);
+ }
+ }
+
+ return Link();
+}
+
+CPPEditor::Link CPPEditor::findMacroLink(const QByteArray &name,
+ Document::Ptr doc,
+ const Snapshot &snapshot,
+ QSet<QString> *processed) const
+{
+ if (doc && ! name.startsWith('<') && ! processed->contains(doc->fileName())) {
+ processed->insert(doc->fileName());
+
+ foreach (const Macro &macro, doc->definedMacros()) {
+ if (macro.name() == name) {
+ Link link;
+ link.fileName = macro.fileName();
+ link.line = macro.line();
+ return link;
+ }
+ }
+
+ const QList<Document::Include> includes = doc->includes();
+ for (int index = includes.size() - 1; index != -1; --index) {
+ const Document::Include &i = includes.at(index);
+ Link link = findMacroLink(name, snapshot.document(i.fileName()), snapshot, processed);
+ if (! link.fileName.isEmpty())
+ return link;
+ }
+ }
+
+ return Link();
+}
+
+QString CPPEditor::identifierUnderCursor(QTextCursor *macroCursor) const
+{
+ macroCursor->movePosition(QTextCursor::StartOfWord);
+ macroCursor->movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
+ return macroCursor->selectedText();
+}
+
CPPEditor::Link CPPEditor::findLinkAt(const QTextCursor &cursor,
bool resolveTarget)
{
@@ -1177,6 +1385,14 @@ CPPEditor::Link CPPEditor::findLinkAt(const QTextCursor &cursor,
return link;
const Snapshot snapshot = m_modelManager->snapshot();
+
+ if (m_lastSemanticInfo.doc){
+ Link l = attemptFuncDeclDef(cursor, m_lastSemanticInfo.doc, snapshot);
+ if (l.isValid()) {
+ return l;
+ }
+ }
+
int lineNumber = 0, positionInBlock = 0;
convertPosition(cursor.position(), &lineNumber, &positionInBlock);
Document::Ptr doc = snapshot.document(file()->fileName());
@@ -1272,7 +1488,7 @@ CPPEditor::Link CPPEditor::findLinkAt(const QTextCursor &cursor,
}
}
- if (tk.isNot(T_IDENTIFIER))
+ if (tk.isNot(T_IDENTIFIER) && tk.kind() < T_FIRST_QT_KEYWORD && tk.kind() > T_LAST_KEYWORD)
return link;
tc.setPosition(endOfToken);
@@ -1285,11 +1501,27 @@ CPPEditor::Link CPPEditor::findLinkAt(const QTextCursor &cursor,
// Evaluate the type of the expression under the cursor
ExpressionUnderCursor expressionUnderCursor;
- const QString expression = expressionUnderCursor(tc);
+ QString expression = expressionUnderCursor(tc);
+
+ for (int pos = tc.position();; ++pos) {
+ const QChar ch = characterAt(pos);
+ if (ch.isSpace())
+ continue;
+ else {
+ if (ch == QLatin1Char('(') && ! expression.isEmpty()) {
+ tc.setPosition(pos);
+ if (TextEditor::TextBlockUserData::findNextClosingParenthesis(&tc, true)) {
+ expression.append(tc.selectedText());
+ }
+ }
+
+ break;
+ }
+ }
TypeOfExpression typeOfExpression;
typeOfExpression.init(doc, snapshot);
- const QList<LookupItem> resolvedSymbols = typeOfExpression(expression, scope, TypeOfExpression::Preprocess);
+ const QList<LookupItem> resolvedSymbols = typeOfExpression.reference(expression, scope, TypeOfExpression::Preprocess);
if (!resolvedSymbols.isEmpty()) {
LookupItem result = skipForwardDeclarations(resolvedSymbols);
@@ -1327,31 +1559,20 @@ CPPEditor::Link CPPEditor::findLinkAt(const QTextCursor &cursor,
link.begin = beginOfToken;
link.end = endOfToken;
return link;
-
- // This would jump to the type of a name
-#if 0
- } else if (NamedType *namedType = firstType->asNamedType()) {
- QList<Symbol *> candidates = context.resolve(namedType->name());
- if (!candidates.isEmpty()) {
- Symbol *s = candidates.takeFirst();
- openCppEditorAt(s->fileName(), s->line(), s->column());
- }
-#endif
- }
- } else {
- // Handle macro uses
- const Document::MacroUse *use = doc->findMacroUseAt(endOfToken - 1);
- if (use && use->macro().fileName() != QLatin1String("<configuration>")) {
- const Macro &macro = use->macro();
- link.fileName = macro.fileName();
- link.line = macro.line();
- link.begin = use->begin();
- link.end = use->end();
- return link;
}
}
- return link;
+ // Handle macro uses
+ QTextCursor macroCursor = cursor;
+ const QByteArray name = identifierUnderCursor(&macroCursor).toLatin1();
+ link = findMacroLink(name);
+ if (! link.fileName.isEmpty()) {
+ link.begin = macroCursor.selectionStart();
+ link.end = macroCursor.selectionEnd();
+ return link;
+ }
+
+ return Link();
}
void CPPEditor::jumpToDefinition()
@@ -1359,7 +1580,7 @@ void CPPEditor::jumpToDefinition()
openLink(findLinkAt(textCursor()));
}
-Symbol *CPPEditor::findDefinition(Symbol *symbol, const Snapshot &snapshot)
+Symbol *CPPEditor::findDefinition(Symbol *symbol, const Snapshot &snapshot) const
{
if (symbol->isFunction())
return 0; // symbol is a function definition.
@@ -1405,156 +1626,6 @@ QModelIndex CPPEditor::outlineModelIndex()
return m_outlineModelIndex;
}
-bool CPPEditor::isElectricCharacter(QChar ch) const
-{
- if (ch == QLatin1Char('{') ||
- ch == QLatin1Char('}') ||
- ch == QLatin1Char(':') ||
- ch == QLatin1Char('#')) {
- return true;
- }
- return false;
-}
-
-QString CPPEditor::insertMatchingBrace(const QTextCursor &tc, const QString &text,
- QChar la, int *skippedChars) const
-{
- MatchingText m;
- return m.insertMatchingBrace(tc, text, la, skippedChars);
-}
-
-QString CPPEditor::insertParagraphSeparator(const QTextCursor &tc) const
-{
- MatchingText m;
- return m.insertParagraphSeparator(tc);
-}
-
-
-bool CPPEditor::contextAllowsAutoParentheses(const QTextCursor &cursor,
- const QString &textToInsert) const
-{
- QChar ch;
-
- if (! textToInsert.isEmpty())
- ch = textToInsert.at(0);
-
- if (! (MatchingText::shouldInsertMatchingText(cursor) || ch == QLatin1Char('\'') || ch == QLatin1Char('"')))
- return false;
- else if (isInComment(cursor))
- return false;
-
- return true;
-}
-
-bool CPPEditor::contextAllowsElectricCharacters(const QTextCursor &cursor) const
-{
- const Token tk = SimpleLexer::tokenAt(cursor.block().text(), cursor.positionInBlock(), BackwardsScanner::previousBlockState(cursor.block()));
-
- // XXX Duplicated from CPPEditor::isInComment to avoid tokenizing twice
- if (tk.isComment()) {
- const unsigned pos = cursor.selectionEnd() - cursor.block().position();
-
- if (pos == tk.end()) {
- if (tk.is(T_CPP_COMMENT) || tk.is(T_CPP_DOXY_COMMENT))
- return false;
-
- const int state = cursor.block().userState() & 0xFF;
- if (state > 0)
- return false;
- }
-
- if (pos < tk.end())
- return false;
- }
- else if (tk.is(T_STRING_LITERAL) || tk.is(T_WIDE_STRING_LITERAL)
- || tk.is(T_CHAR_LITERAL) || tk.is(T_WIDE_CHAR_LITERAL)) {
-
- const unsigned pos = cursor.selectionEnd() - cursor.block().position();
- if (pos <= tk.end())
- return false;
- }
-
- return true;
-}
-
-bool CPPEditor::isInComment(const QTextCursor &cursor) const
-{
- const Token tk = SimpleLexer::tokenAt(cursor.block().text(), cursor.positionInBlock(), BackwardsScanner::previousBlockState(cursor.block()));
-
- if (tk.isComment()) {
- const unsigned pos = cursor.selectionEnd() - cursor.block().position();
-
- if (pos == tk.end()) {
- if (tk.is(T_CPP_COMMENT) || tk.is(T_CPP_DOXY_COMMENT))
- return true;
-
- const int state = cursor.block().userState() & 0xFF;
- if (state > 0)
- return true;
- }
-
- if (pos < tk.end())
- return true;
- }
-
- return false;
-}
-
-void CPPEditor::indentBlock(QTextDocument *doc, QTextBlock block, QChar typedChar)
-{
- Q_UNUSED(doc)
-
- const TabSettings &ts = tabSettings();
- CppTools::QtStyleCodeFormatter codeFormatter(ts);
-
- codeFormatter.updateStateUntil(block);
- int indent;
- int padding;
- codeFormatter.indentFor(block, &indent, &padding);
-
- // only reindent the current line when typing electric characters if the
- // indent is the same it would be if the line were empty
- if (isElectricCharacter(typedChar)) {
- int newlineIndent;
- int newlinePadding;
- codeFormatter.indentForNewLineAfter(block.previous(), &newlineIndent, &newlinePadding);
- if (ts.indentationColumn(block.text()) != newlineIndent + newlinePadding)
- return;
- }
-
- ts.indentLine(block, indent + padding, padding);
-}
-
-void CPPEditor::indent(QTextDocument *doc, const QTextCursor &cursor, QChar typedChar)
-{
- Q_UNUSED(doc)
- Q_UNUSED(typedChar)
-
- maybeClearSomeExtraSelections(cursor);
- if (cursor.hasSelection()) {
- QTextBlock block = doc->findBlock(cursor.selectionStart());
- const QTextBlock end = doc->findBlock(cursor.selectionEnd()).next();
-
- const TabSettings &ts = tabSettings();
- CppTools::QtStyleCodeFormatter codeFormatter(ts);
- codeFormatter.updateStateUntil(block);
-
- QTextCursor tc = textCursor();
- tc.beginEditBlock();
- do {
- int indent;
- int padding;
- codeFormatter.indentFor(block, &indent, &padding);
- ts.indentLine(block, indent + padding, padding);
- codeFormatter.updateLineStateChange(block);
- block = block.next();
- } while (block.isValid() && block != end);
- tc.endEditBlock();
- } else {
- indentBlock(doc, cursor.block(), typedChar);
- }
-}
-
bool CPPEditor::event(QEvent *e)
{
switch (e->type()) {
@@ -1739,22 +1810,7 @@ void CPPEditor::setFontSettings(const TextEditor::FontSettings &fs)
if (!highlighter)
return;
- static QVector<QString> categories;
- if (categories.isEmpty()) {
- categories << QLatin1String(TextEditor::Constants::C_NUMBER)
- << QLatin1String(TextEditor::Constants::C_STRING)
- << QLatin1String(TextEditor::Constants::C_TYPE)
- << QLatin1String(TextEditor::Constants::C_KEYWORD)
- << QLatin1String(TextEditor::Constants::C_OPERATOR)
- << QLatin1String(TextEditor::Constants::C_PREPROCESSOR)
- << QLatin1String(TextEditor::Constants::C_LABEL)
- << QLatin1String(TextEditor::Constants::C_COMMENT)
- << QLatin1String(TextEditor::Constants::C_DOXYGEN_COMMENT)
- << QLatin1String(TextEditor::Constants::C_DOXYGEN_TAG)
- << QLatin1String(TextEditor::Constants::C_VISUAL_WHITESPACE);
- }
-
- const QVector<QTextCharFormat> formats = fs.toTextCharFormats(categories);
+ const QVector<QTextCharFormat> formats = fs.toTextCharFormats(highlighterFormatCategories());
highlighter->setFormats(formats.constBegin(), formats.constEnd());
m_occurrencesFormat = fs.toTextCharFormat(QLatin1String(TextEditor::Constants::C_OCCURRENCES));
@@ -2179,4 +2235,23 @@ QModelIndex CPPEditor::indexForPosition(int line, int column, const QModelIndex
return lastIndex;
}
+QVector<QString> CPPEditor::highlighterFormatCategories()
+{
+ static QVector<QString> categories;
+ if (categories.isEmpty()) {
+ categories << QLatin1String(TextEditor::Constants::C_NUMBER)
+ << QLatin1String(TextEditor::Constants::C_STRING)
+ << QLatin1String(TextEditor::Constants::C_TYPE)
+ << QLatin1String(TextEditor::Constants::C_KEYWORD)
+ << QLatin1String(TextEditor::Constants::C_OPERATOR)
+ << QLatin1String(TextEditor::Constants::C_PREPROCESSOR)
+ << QLatin1String(TextEditor::Constants::C_LABEL)
+ << QLatin1String(TextEditor::Constants::C_COMMENT)
+ << QLatin1String(TextEditor::Constants::C_DOXYGEN_COMMENT)
+ << QLatin1String(TextEditor::Constants::C_DOXYGEN_TAG)
+ << QLatin1String(TextEditor::Constants::C_VISUAL_WHITESPACE);
+ }
+ return categories;
+}
+
#include "cppeditor.moc"
diff --git a/src/plugins/cppeditor/cppeditor.h b/src/plugins/cppeditor/cppeditor.h
index 1b5c872db7..7483430692 100644
--- a/src/plugins/cppeditor/cppeditor.h
+++ b/src/plugins/cppeditor/cppeditor.h
@@ -47,6 +47,7 @@
#include <QtCore/QWaitCondition>
#include <QtCore/QFutureWatcher>
#include <QtCore/QModelIndex>
+#include <QtCore/QVector>
QT_BEGIN_NAMESPACE
class QComboBox;
@@ -188,6 +189,8 @@ public:
static Link linkToSymbol(CPlusPlus::Symbol *symbol);
+ static QVector<QString> highlighterFormatCategories();
+
Q_SIGNALS:
void outlineModelIndexChanged(const QModelIndex &index);
@@ -211,20 +214,6 @@ protected:
TextEditor::BaseTextEditorEditable *createEditableInterface();
- // These override BaseTextEditor
- virtual bool isElectricCharacter(QChar ch) const;
-
- virtual QString insertMatchingBrace(const QTextCursor &tc, const QString &text,
- QChar la, int *skippedChars) const;
-
- virtual QString insertParagraphSeparator(const QTextCursor &tc) const;
-
- virtual bool contextAllowsAutoParentheses(const QTextCursor &cursor,
- const QString &textToInsert = QString()) const;
- virtual bool contextAllowsElectricCharacters(const QTextCursor &cursor) const;
-
- virtual bool isInComment(const QTextCursor &cursor) const;
-
const CPlusPlus::Macro *findCanonicalMacro(const QTextCursor &cursor,
CPlusPlus::Document::Ptr doc) const;
@@ -255,9 +244,7 @@ private:
void markSymbols(const QTextCursor &tc, const SemanticInfo &info);
bool sortedOutline() const;
- CPlusPlus::Symbol *findDefinition(CPlusPlus::Symbol *symbol, const CPlusPlus::Snapshot &snapshot);
- virtual void indentBlock(QTextDocument *doc, QTextBlock block, QChar typedChar);
- virtual void indent(QTextDocument *doc, const QTextCursor &cursor, QChar typedChar);
+ CPlusPlus::Symbol *findDefinition(CPlusPlus::Symbol *symbol, const CPlusPlus::Snapshot &snapshot) const;
TextEditor::ITextEditor *openCppEditorAt(const QString &fileName, int line,
int column = 0);
@@ -274,7 +261,14 @@ private:
void finishRename();
void abortRename();
+ Link attemptFuncDeclDef(const QTextCursor &cursor,
+ const CPlusPlus::Document::Ptr &doc,
+ CPlusPlus::Snapshot snapshot) const;
Link findLinkAt(const QTextCursor &, bool resolveTarget = true);
+ Link findMacroLink(const QByteArray &name) const;
+ Link findMacroLink(const QByteArray &name, CPlusPlus::Document::Ptr doc, const CPlusPlus::Snapshot &snapshot,
+ QSet<QString> *processed) const;
+ QString identifierUnderCursor(QTextCursor *macroCursor) const;
bool openCppEditorAt(const Link &);
QModelIndex indexForPosition(int line, int column, const QModelIndex &rootIndex = QModelIndex()) const;
diff --git a/src/plugins/cppeditor/cppeditor.pri b/src/plugins/cppeditor/cppeditor.pri
index c4d6fdf753..e3f320ef00 100644
--- a/src/plugins/cppeditor/cppeditor.pri
+++ b/src/plugins/cppeditor/cppeditor.pri
@@ -1,3 +1,3 @@
include(cppeditor_dependencies.pri)
-LIBS *= -l$$qtLibraryTarget(CppEditor)
+LIBS *= -l$$qtLibraryName(CppEditor)
diff --git a/src/plugins/cppeditor/cppeditor.pro b/src/plugins/cppeditor/cppeditor.pro
index 57767721ec..95abbbde12 100644
--- a/src/plugins/cppeditor/cppeditor.pro
+++ b/src/plugins/cppeditor/cppeditor.pro
@@ -21,7 +21,14 @@ HEADERS += cppplugin.h \
cppinsertdecldef.h \
cpplocalsymbols.h \
cpptypehierarchy.h \
- cppelementevaluator.h
+ cppelementevaluator.h \
+ cppquickfixcollector.h \
+ cppqtstyleindenter.h \
+ cppautocompleter.h \
+ cppcompleteswitch.h \
+ cppsnippetprovider.h \
+ cppinsertqtpropertymembers.h
+
SOURCES += cppplugin.cpp \
cppeditor.cpp \
cpphighlighter.cpp \
@@ -36,7 +43,13 @@ SOURCES += cppplugin.cpp \
cppinsertdecldef.cpp \
cpplocalsymbols.cpp \
cpptypehierarchy.cpp \
- cppelementevaluator.cpp
+ cppelementevaluator.cpp \
+ cppquickfixcollector.cpp \
+ cppqtstyleindenter.cpp \
+ cppautocompleter.cpp \
+ cppcompleteswitch.cpp \
+ cppsnippetprovider.cpp \
+ cppinsertqtpropertymembers.cpp
+
RESOURCES += cppeditor.qrc
-OTHER_FILES += CppEditor.pluginspec \
- CppEditor.mimetypes.xml
+OTHER_FILES += CppEditor.mimetypes.xml
diff --git a/src/plugins/cppeditor/cppeditorconstants.h b/src/plugins/cppeditor/cppeditorconstants.h
index 3098c586ce..4518ccebb2 100644
--- a/src/plugins/cppeditor/cppeditorconstants.h
+++ b/src/plugins/cppeditor/cppeditorconstants.h
@@ -72,6 +72,8 @@ const char * const CPP_HEADER_MIMETYPE = "text/x-c++hdr";
const char * const WIZARD_CATEGORY = "O.C++";
const char * const WIZARD_TR_CATEGORY = QT_TRANSLATE_NOOP("CppEditor", "C++");
+const char * const CPP_SNIPPETS_GROUP_ID = "C++";
+
} // namespace Constants
} // namespace CppEditor
diff --git a/src/plugins/cppeditor/cppinsertdecldef.cpp b/src/plugins/cppeditor/cppinsertdecldef.cpp
index 475390fe42..f75aa0057d 100644
--- a/src/plugins/cppeditor/cppinsertdecldef.cpp
+++ b/src/plugins/cppeditor/cppinsertdecldef.cpp
@@ -39,6 +39,7 @@
#include <cplusplus/LookupContext.h>
#include <cplusplus/Overview.h>
#include <cpptools/insertionpointlocator.h>
+#include <cpptools/cpprefactoringchanges.h>
#include <QtCore/QCoreApplication>
#include <QtCore/QDir>
diff --git a/src/plugins/cppeditor/cppinsertqtpropertymembers.cpp b/src/plugins/cppeditor/cppinsertqtpropertymembers.cpp
new file mode 100644
index 0000000000..3995af34d7
--- /dev/null
+++ b/src/plugins/cppeditor/cppinsertqtpropertymembers.cpp
@@ -0,0 +1,194 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "cppinsertqtpropertymembers.h"
+
+#include <AST.h>
+#include <Token.h>
+#include <cplusplus/Overview.h>
+#include <cpptools/insertionpointlocator.h>
+#include <cpptools/cpprefactoringchanges.h>
+#include <cppeditor/cppquickfix.h>
+
+using namespace CPlusPlus;
+using namespace CppTools;
+using namespace TextEditor;
+using namespace Utils;
+using namespace CppEditor;
+using namespace CppEditor::Internal;
+
+QList<CppQuickFixOperation::Ptr> InsertQtPropertyMembers::match(const CppQuickFixState &state)
+{
+ const QList<AST *> &path = state.path();
+
+ if (path.isEmpty())
+ return noResult();
+
+ AST * const ast = path.last();
+ QtPropertyDeclarationAST *qtPropertyDeclaration = ast->asQtPropertyDeclaration();
+ if (!qtPropertyDeclaration)
+ return noResult();
+
+ ClassSpecifierAST *klass = 0;
+ for (int i = path.size() - 2; i >= 0; --i) {
+ klass = path.at(i)->asClassSpecifier();
+ if (klass)
+ break;
+ }
+ if (!klass)
+ return noResult();
+
+ CppRefactoringChanges refactoring(state.snapshot());
+ const CppRefactoringFile &file = refactoring.file(state.document()->fileName());
+ const QString propertyName = file.textOf(qtPropertyDeclaration->property_name);
+ QString getterName;
+ QString setterName;
+ QString signalName;
+ int generateFlags = 0;
+ for (QtPropertyDeclarationItemListAST *it = qtPropertyDeclaration->property_declaration_item_list;
+ it; it = it->next) {
+ const QString tokenString = file.tokenAt(it->value->item_name_token).spell();
+ if (tokenString == QLatin1String("READ")) {
+ getterName = file.textOf(it->value->expression);
+ generateFlags |= GenerateGetter;
+ } else if (tokenString == QLatin1String("WRITE")) {
+ setterName = file.textOf(it->value->expression);
+ generateFlags |= GenerateSetter;
+ } else if (tokenString == QLatin1String("NOTIFY")) {
+ signalName = file.textOf(it->value->expression);
+ generateFlags |= GenerateSignal;
+ }
+ }
+ QString storageName = QString("m_%1").arg(propertyName);
+ generateFlags |= GenerateStorage;
+
+ Class *c = klass->symbol;
+
+ Overview overview;
+ for (unsigned i = 0; i < c->memberCount(); ++i) {
+ Symbol *member = c->memberAt(i);
+ FullySpecifiedType type = member->type();
+ if (member->asFunction() || (type.isValid() && type->asFunctionType())) {
+ const QString name = overview(member->name());
+ if (name == getterName) {
+ generateFlags &= ~GenerateGetter;
+ } else if (name == setterName) {
+ generateFlags &= ~GenerateSetter;
+ } else if (name == signalName) {
+ generateFlags &= ~GenerateSignal;
+ }
+ } else if (member->asDeclaration()) {
+ const QString name = overview(member->name());
+ if (name == storageName)
+ generateFlags &= ~GenerateStorage;
+ }
+ }
+
+ if (getterName.isEmpty() && setterName.isEmpty() && signalName.isEmpty())
+ return noResult();
+
+ return singleResult(new Operation(state, path.size() - 1, qtPropertyDeclaration, c,
+ generateFlags,
+ getterName, setterName, signalName, storageName));
+}
+
+InsertQtPropertyMembers::Operation::Operation(
+ const CppQuickFixState &state, int priority, QtPropertyDeclarationAST *declaration, Class *klass,
+ int generateFlags, const QString &getterName, const QString &setterName, const QString &signalName,
+ const QString &storageName)
+ : CppQuickFixOperation(state, priority)
+ , m_declaration(declaration)
+ , m_class(klass)
+ , m_generateFlags(generateFlags)
+ , m_getterName(getterName)
+ , m_setterName(setterName)
+ , m_signalName(signalName)
+ , m_storageName(storageName)
+{
+ QString desc = InsertQtPropertyMembers::tr("Generate missing Q_PROPERTY members...");
+ setDescription(desc);
+}
+
+void InsertQtPropertyMembers::Operation::performChanges(CppRefactoringFile *file, CppRefactoringChanges *refactoring)
+{
+ InsertionPointLocator locator(refactoring);
+ Utils::ChangeSet declarations;
+
+ const QString typeName = file->textOf(m_declaration->type_id);
+ const QString propertyName = file->textOf(m_declaration->property_name);
+
+ // getter declaration
+ if (m_generateFlags & GenerateGetter) {
+ // const QString getterDeclaration = QString("%1 %2() const;").arg(typeName, getterName);
+ const QString getterDeclaration = QString("%1 %2() const\n{\nreturn %3;\n}\n").arg(typeName, m_getterName, m_storageName);
+ InsertionLocation getterLoc = locator.methodDeclarationInClass(file->fileName(), m_class, InsertionPointLocator::Public);
+ Q_ASSERT(getterLoc.isValid());
+ insertAndIndent(file, &declarations, getterLoc, getterDeclaration);
+ }
+
+ // setter declaration
+ if (m_generateFlags & GenerateSetter) {
+ // const QString setterDeclaration = QString("void %1(%2 arg);").arg(setterName, typeName);
+ QString setterDeclaration = QString("void %1(%2 arg)\n{\n").arg(m_setterName, typeName);
+ if (!m_signalName.isEmpty()) {
+ setterDeclaration += QString("if (%1 != arg) {\n%1 = arg;\nemit %2(arg);\n}\n}\n").arg(m_storageName, m_signalName);
+ } else {
+ setterDeclaration += QString("%1 = arg;\n}\n").arg(m_storageName);
+ }
+ InsertionLocation setterLoc = locator.methodDeclarationInClass(file->fileName(), m_class, InsertionPointLocator::PublicSlot);
+ Q_ASSERT(setterLoc.isValid());
+ insertAndIndent(file, &declarations, setterLoc, setterDeclaration);
+ }
+
+ // signal declaration
+ if (m_generateFlags & GenerateSignal) {
+ const QString declaration = QString("void %1(%2 arg);\n").arg(m_signalName, typeName);
+ InsertionLocation loc = locator.methodDeclarationInClass(file->fileName(), m_class, InsertionPointLocator::Signals);
+ Q_ASSERT(loc.isValid());
+ insertAndIndent(file, &declarations, loc, declaration);
+ }
+
+ // storage
+ if (m_generateFlags & GenerateStorage) {
+ const QString storageDeclaration = QString("%1 m_%2;\n").arg(typeName, propertyName);
+ InsertionLocation storageLoc = locator.methodDeclarationInClass(file->fileName(), m_class, InsertionPointLocator::Private);
+ Q_ASSERT(storageLoc.isValid());
+ insertAndIndent(file, &declarations, storageLoc, storageDeclaration);
+ }
+
+ file->change(declarations);
+}
+
+void InsertQtPropertyMembers::Operation::insertAndIndent(RefactoringFile *file, ChangeSet *changeSet, const InsertionLocation &loc, const QString &text)
+{
+ int targetPosition1 = file->position(loc.line(), loc.column());
+ int targetPosition2 = qMax(0, file->position(loc.line(), 1) - 1);
+ changeSet->insert(targetPosition1, loc.prefix() + text + loc.suffix());
+ file->indent(Utils::ChangeSet::Range(targetPosition2, targetPosition1));
+}
diff --git a/src/plugins/cppeditor/cppinsertqtpropertymembers.h b/src/plugins/cppeditor/cppinsertqtpropertymembers.h
new file mode 100644
index 0000000000..94863444fc
--- /dev/null
+++ b/src/plugins/cppeditor/cppinsertqtpropertymembers.h
@@ -0,0 +1,101 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 CPPINSERTQTPROPERTYMEMBERS_H
+#define CPPINSERTQTPROPERTYMEMBERS_H
+
+#include <cppeditor/cppquickfix.h>
+
+#include <QtCore/QString>
+
+namespace CPlusPlus {
+class QtPropertyDeclarationAST;
+class Class;
+}
+
+namespace TextEditor {
+class RefactoringFile;
+}
+
+namespace Utils {
+class ChangeSet;
+}
+
+namespace CppTools {
+class InsertionLocation;
+}
+
+namespace CppEditor {
+namespace Internal {
+
+class InsertQtPropertyMembers : public CppQuickFixFactory
+{
+ Q_OBJECT
+
+public:
+ virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state);
+
+private:
+ enum GenerateFlag {
+ GenerateGetter = 1 << 0,
+ GenerateSetter = 1 << 1,
+ GenerateSignal = 1 << 2,
+ GenerateStorage = 1 << 3
+ };
+
+ class Operation: public CppQuickFixOperation
+ {
+ public:
+ Operation(const CppQuickFixState &state, int priority,
+ CPlusPlus::QtPropertyDeclarationAST *declaration, CPlusPlus::Class *klass,
+ int generateFlags,
+ const QString &getterName, const QString &setterName, const QString &signalName,
+ const QString &storageName);
+
+ virtual void performChanges(CppTools::CppRefactoringFile *file,
+ CppTools::CppRefactoringChanges *refactoring);
+
+ private:
+ void insertAndIndent(TextEditor::RefactoringFile *file, Utils::ChangeSet *changeSet,
+ const CppTools::InsertionLocation &loc, const QString &text);
+
+ CPlusPlus::QtPropertyDeclarationAST *m_declaration;
+ CPlusPlus::Class *m_class;
+ int m_generateFlags;
+ QString m_getterName;
+ QString m_setterName;
+ QString m_signalName;
+ QString m_storageName;
+ };
+};
+
+} // namespace Internal
+} // namespace CppEditor
+
+#endif // CPPINSERTQTPROPERTYMEMBERS_H
diff --git a/src/plugins/cppeditor/cppplugin.cpp b/src/plugins/cppeditor/cppplugin.cpp
index 72017c9295..5ebaf47801 100644
--- a/src/plugins/cppeditor/cppplugin.cpp
+++ b/src/plugins/cppeditor/cppplugin.cpp
@@ -40,7 +40,9 @@
#include "cpphoverhandler.h"
#include "cppquickfix.h"
#include "cppoutline.h"
+#include "cppquickfixcollector.h"
#include "cpptypehierarchy.h"
+#include "cppsnippetprovider.h"
#include <coreplugin/icore.h>
#include <coreplugin/coreconstants.h>
@@ -49,6 +51,7 @@
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/command.h>
+#include <coreplugin/uniqueidmanager.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <coreplugin/navigationwidget.h>
@@ -177,7 +180,7 @@ void CppPlugin::initializeEditor(CPPEditor *editor)
// auto completion
connect(editor, SIGNAL(requestAutoCompletion(TextEditor::ITextEditable*, bool)),
- TextEditor::Internal::CompletionSupport::instance(), SLOT(autoComplete(TextEditor::ITextEditable*, bool)));
+ TextEditor::CompletionSupport::instance(), SLOT(autoComplete(TextEditor::ITextEditable*, bool)));
// quick fix
connect(editor, SIGNAL(requestQuickFix(TextEditor::ITextEditable*)),
@@ -213,6 +216,7 @@ bool CppPlugin::initialize(const QStringList & /*arguments*/, QString *errorMess
addAutoReleasedObject(new CppHoverHandler);
addAutoReleasedObject(new CppOutlineWidgetFactory);
addAutoReleasedObject(new CppTypeHierarchyFactory);
+ addAutoReleasedObject(new CppSnippetProvider);
m_quickFixCollector = new CppQuickFixCollector;
addAutoReleasedObject(m_quickFixCollector);
@@ -404,7 +408,7 @@ void CppPlugin::quickFixNow()
if (editor->isOutdated())
m_quickFixTimer->start(QUICKFIX_INTERVAL);
else
- TextEditor::Internal::CompletionSupport::instance()->quickFix(m_currentTextEditable);
+ TextEditor::CompletionSupport::instance()->quickFix(m_currentTextEditable);
}
}
}
diff --git a/src/plugins/cppeditor/cppqtstyleindenter.cpp b/src/plugins/cppeditor/cppqtstyleindenter.cpp
new file mode 100644
index 0000000000..984c58271e
--- /dev/null
+++ b/src/plugins/cppeditor/cppqtstyleindenter.cpp
@@ -0,0 +1,140 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "cppqtstyleindenter.h"
+
+#include <cpptools/cppcodeformatter.h>
+#include <texteditor/basetexteditor.h>
+#include <texteditor/tabsettings.h>
+
+#include <QtCore/QChar>
+#include <QtGui/QTextDocument>
+#include <QtGui/QTextBlock>
+#include <QtGui/QTextCursor>
+
+using namespace CppEditor;
+using namespace Internal;
+
+CppQtStyleIndenter::CppQtStyleIndenter()
+{}
+
+CppQtStyleIndenter::~CppQtStyleIndenter()
+{}
+
+bool CppQtStyleIndenter::isElectricCharacter(const QChar &ch) const
+{
+ if (ch == QLatin1Char('{') ||
+ ch == QLatin1Char('}') ||
+ ch == QLatin1Char(':') ||
+ ch == QLatin1Char('#')) {
+ return true;
+ }
+ return false;
+}
+
+static bool colonIsElectric(const QString &text)
+{
+ // switch cases and access declarations should be reindented
+ if (text.contains(QLatin1String("case"))
+ || text.contains(QLatin1String("default"))
+ || text.contains(QLatin1String("public"))
+ || text.contains(QLatin1String("private"))
+ || text.contains(QLatin1String("protected"))
+ || text.contains(QLatin1String("signals"))) {
+ return true;
+ }
+
+ // lines that start with : might have a constructor initializer list
+ const QString trimmedtext = text.trimmed();
+ if (!trimmedtext.isEmpty() && trimmedtext.at(0) == QLatin1Char(':'))
+ return true;
+
+ return false;
+}
+
+void CppQtStyleIndenter::indentBlock(QTextDocument *doc,
+ const QTextBlock &block,
+ const QChar &typedChar,
+ TextEditor::BaseTextEditor *editor)
+{
+ Q_UNUSED(doc)
+
+ const TextEditor::TabSettings &ts = editor->tabSettings();
+ CppTools::QtStyleCodeFormatter codeFormatter(ts);
+
+ codeFormatter.updateStateUntil(block);
+ int indent;
+ int padding;
+ codeFormatter.indentFor(block, &indent, &padding);
+
+ if (isElectricCharacter(typedChar)) {
+ // : should not be electric for labels
+ if (typedChar == QLatin1Char(':') && !colonIsElectric(block.text()))
+ return;
+
+ // only reindent the current line when typing electric characters if the
+ // indent is the same it would be if the line were empty
+ int newlineIndent;
+ int newlinePadding;
+ codeFormatter.indentForNewLineAfter(block.previous(), &newlineIndent, &newlinePadding);
+ if (ts.indentationColumn(block.text()) != newlineIndent + newlinePadding)
+ return;
+ }
+
+ ts.indentLine(block, indent + padding, padding);
+}
+
+void CppQtStyleIndenter::indent(QTextDocument *doc,
+ const QTextCursor &cursor,
+ const QChar &typedChar,
+ TextEditor::BaseTextEditor *editor)
+{
+ if (cursor.hasSelection()) {
+ QTextBlock block = doc->findBlock(cursor.selectionStart());
+ const QTextBlock end = doc->findBlock(cursor.selectionEnd()).next();
+
+ const TextEditor::TabSettings &ts = editor->tabSettings();
+ CppTools::QtStyleCodeFormatter codeFormatter(ts);
+ codeFormatter.updateStateUntil(block);
+
+ QTextCursor tc = editor->textCursor();
+ tc.beginEditBlock();
+ do {
+ int indent;
+ int padding;
+ codeFormatter.indentFor(block, &indent, &padding);
+ ts.indentLine(block, indent + padding, padding);
+ codeFormatter.updateLineStateChange(block);
+ block = block.next();
+ } while (block.isValid() && block != end);
+ tc.endEditBlock();
+ } else {
+ indentBlock(doc, cursor.block(), typedChar, editor);
+ }
+}
diff --git a/src/plugins/cppeditor/cppqtstyleindenter.h b/src/plugins/cppeditor/cppqtstyleindenter.h
new file mode 100644
index 0000000000..f186479312
--- /dev/null
+++ b/src/plugins/cppeditor/cppqtstyleindenter.h
@@ -0,0 +1,59 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 CPPQTSTYLEINDENTER_H
+#define CPPQTSTYLEINDENTER_H
+
+#include <texteditor/indenter.h>
+
+namespace CppEditor {
+namespace Internal {
+
+class CppQtStyleIndenter : public TextEditor::Indenter
+{
+public:
+ CppQtStyleIndenter();
+ virtual ~CppQtStyleIndenter();
+
+ virtual bool isElectricCharacter(const QChar &ch) const;
+ virtual void indentBlock(QTextDocument *doc,
+ const QTextBlock &block,
+ const QChar &typedChar,
+ TextEditor::BaseTextEditor *editor);
+
+ virtual void indent(QTextDocument *doc,
+ const QTextCursor &cursor,
+ const QChar &typedChar,
+ TextEditor::BaseTextEditor *editor);
+};
+
+} // Internal
+} // CppEditor
+
+#endif // CPPQTSTYLEINDENTER_H
diff --git a/src/plugins/cppeditor/cppquickfix.cpp b/src/plugins/cppeditor/cppquickfix.cpp
index e3594a409b..a2df0a249e 100644
--- a/src/plugins/cppeditor/cppquickfix.cpp
+++ b/src/plugins/cppeditor/cppquickfix.cpp
@@ -33,6 +33,7 @@
#include "cppquickfix.h"
#include "cppeditor.h"
+#include "cppquickfixcollector.h"
#include <AST.h>
#include <TranslationUnit.h>
@@ -46,11 +47,7 @@
#include <cplusplus/DependencyTable.h>
#include <cplusplus/CppRewriter.h>
-#include <cppeditor/cppeditor.h>
#include <cpptools/cpprefactoringchanges.h>
-#include <cpptools/cpptoolsconstants.h>
-#include <cpptools/cppmodelmanagerinterface.h>
-#include <extensionsystem/pluginmanager.h>
#include <QtGui/QTextBlock>
@@ -95,6 +92,15 @@ const CppRefactoringFile CppQuickFixState::currentFile() const
return CppRefactoringFile(editor(), document());
}
+bool CppQuickFixState::isCursorOn(unsigned tokenIndex) const
+{
+ return currentFile().isCursorOn(tokenIndex);
+}
+
+bool CppQuickFixState::isCursorOn(const CPlusPlus::AST *ast) const
+{
+ return currentFile().isCursorOn(ast);
+}
CppQuickFixOperation::CppQuickFixOperation(const CppQuickFixState &state, int priority)
: QuickFixOperation(priority)
@@ -147,54 +153,3 @@ QList<CppQuickFixOperation::Ptr> CppQuickFixFactory::noResult()
{
return QList<CppQuickFixOperation::Ptr>();
}
-
-CppQuickFixCollector::CppQuickFixCollector()
-{
-}
-
-CppQuickFixCollector::~CppQuickFixCollector()
-{
-}
-
-bool CppQuickFixCollector::supportsEditor(TextEditor::ITextEditable *editor)
-{
- return CppTools::CppModelManagerInterface::instance()->isCppEditor(editor);
-}
-
-TextEditor::QuickFixState *CppQuickFixCollector::initializeCompletion(TextEditor::BaseTextEditor *editor)
-{
- if (CPPEditor *cppEditor = qobject_cast<CPPEditor *>(editor)) {
- const SemanticInfo info = cppEditor->semanticInfo();
-
- if (info.revision != cppEditor->editorRevision()) {
- // outdated
- qWarning() << "TODO: outdated semantic info, force a reparse.";
- return 0;
- }
-
- if (info.doc) {
- ASTPath astPath(info.doc);
-
- const QList<AST *> path = astPath(cppEditor->textCursor());
- if (! path.isEmpty()) {
- CppQuickFixState *state = new CppQuickFixState(editor);
- state->_path = path;
- state->_semanticInfo = info;
- state->_snapshot = CppTools::CppModelManagerInterface::instance()->snapshot();
- state->_context = LookupContext(info.doc, state->snapshot());
- return state;
- }
- }
- }
-
- return 0;
-}
-
-QList<TextEditor::QuickFixFactory *> CppQuickFixCollector::quickFixFactories() const
-{
- QList<TextEditor::QuickFixFactory *> results;
- ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
- foreach (CppQuickFixFactory *f, pm->getObjects<CppEditor::CppQuickFixFactory>())
- results.append(f);
- return results;
-}
diff --git a/src/plugins/cppeditor/cppquickfix.h b/src/plugins/cppeditor/cppquickfix.h
index 50bf9c1585..02caf56d83 100644
--- a/src/plugins/cppeditor/cppquickfix.h
+++ b/src/plugins/cppeditor/cppquickfix.h
@@ -39,16 +39,12 @@
#include <ASTfwd.h>
#include <cplusplus/CppDocument.h>
-#include <cpptools/cpprefactoringchanges.h>
-#include <texteditor/icompletioncollector.h>
#include <texteditor/quickfix.h>
-#include <utils/changeset.h>
-
-#include <QtCore/QSharedPointer>
-#include <QtGui/QTextCursor>
namespace CppTools {
class CppModelManagerInterface;
+ class CppRefactoringFile;
+ class CppRefactoringChanges;
} // end of namespace CppTools
namespace ExtensionSystem {
@@ -76,10 +72,8 @@ public:
const CppTools::CppRefactoringFile currentFile() const;
- bool isCursorOn(unsigned tokenIndex) const
- { return currentFile().isCursorOn(tokenIndex); }
- bool isCursorOn(const CPlusPlus::AST *ast) const
- { return currentFile().isCursorOn(ast); }
+ bool isCursorOn(unsigned tokenIndex) const;
+ bool isCursorOn(const CPlusPlus::AST *ast) const;
private:
QList<CPlusPlus::AST *> _path;
@@ -106,9 +100,6 @@ protected:
const CppQuickFixState &state() const;
-protected: // Utility functions forwarding to CppQuickFixState
- typedef Utils::ChangeSet::Range Range;
-
private:
CppQuickFixState _state;
};
@@ -140,26 +131,6 @@ protected:
static QList<CppQuickFixOperation::Ptr> noResult();
};
-namespace Internal {
-
-class CppQuickFixCollector: public TextEditor::QuickFixCollector
-{
- Q_OBJECT
-
-public:
- CppQuickFixCollector();
- virtual ~CppQuickFixCollector();
-
- virtual bool supportsEditor(TextEditor::ITextEditable *editor);
- virtual TextEditor::QuickFixState *initializeCompletion(TextEditor::BaseTextEditor *editor);
-
- virtual QList<TextEditor::QuickFixFactory *> quickFixFactories() const;
-
- /// Registers all quick-fixes in this plug-in as auto-released objects.
- static void registerQuickFixes(ExtensionSystem::IPlugin *plugIn);
-};
-
-} // end of namespace Internal
-} // end of namespace CppEditor
+} // namespace CppEditor
#endif // CPPQUICKFIX_H
diff --git a/src/plugins/cppeditor/cppquickfixcollector.cpp b/src/plugins/cppeditor/cppquickfixcollector.cpp
new file mode 100644
index 0000000000..5f360a429c
--- /dev/null
+++ b/src/plugins/cppeditor/cppquickfixcollector.cpp
@@ -0,0 +1,97 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "cppquickfixcollector.h"
+#include "cppeditor.h"
+
+#include <extensionsystem/pluginmanager.h>
+
+#include <cpptools/cpprefactoringchanges.h>
+#include <cpptools/cpptoolsconstants.h>
+#include <cpptools/cppmodelmanagerinterface.h>
+
+#include <AST.h>
+#include <cplusplus/ASTPath.h>
+
+namespace CppEditor {
+namespace Internal {
+
+CppQuickFixCollector::CppQuickFixCollector()
+{
+}
+
+CppQuickFixCollector::~CppQuickFixCollector()
+{
+}
+
+bool CppQuickFixCollector::supportsEditor(TextEditor::ITextEditable *editor)
+{
+ return CppTools::CppModelManagerInterface::instance()->isCppEditor(editor);
+}
+
+TextEditor::QuickFixState *CppQuickFixCollector::initializeCompletion(TextEditor::BaseTextEditor *editor)
+{
+ if (CPPEditor *cppEditor = qobject_cast<CPPEditor *>(editor)) {
+ const SemanticInfo info = cppEditor->semanticInfo();
+
+ if (info.revision != cppEditor->editorRevision()) {
+ // outdated
+ qWarning() << "TODO: outdated semantic info, force a reparse.";
+ return 0;
+ }
+
+ if (info.doc) {
+ CPlusPlus::ASTPath astPath(info.doc);
+
+ const QList<CPlusPlus::AST *> path = astPath(cppEditor->textCursor());
+ if (! path.isEmpty()) {
+ CppQuickFixState *state = new CppQuickFixState(editor);
+ state->_path = path;
+ state->_semanticInfo = info;
+ state->_snapshot = CppTools::CppModelManagerInterface::instance()->snapshot();
+ state->_context = CPlusPlus::LookupContext(info.doc, state->snapshot());
+ return state;
+ }
+ }
+ }
+
+ return 0;
+}
+
+QList<TextEditor::QuickFixFactory *> CppQuickFixCollector::quickFixFactories() const
+{
+ QList<TextEditor::QuickFixFactory *> results;
+ ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
+ foreach (CppQuickFixFactory *f, pm->getObjects<CppEditor::CppQuickFixFactory>())
+ results.append(f);
+ return results;
+}
+
+} // namespace Internal
+} // namespace CppEditor
diff --git a/src/plugins/cppeditor/cppquickfixcollector.h b/src/plugins/cppeditor/cppquickfixcollector.h
new file mode 100644
index 0000000000..afc2342fb7
--- /dev/null
+++ b/src/plugins/cppeditor/cppquickfixcollector.h
@@ -0,0 +1,65 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 QUICKFIXCOLLECTOR_H
+#define QUICKFIXCOLLECTOR_H
+
+#include <texteditor/quickfix.h>
+
+namespace ExtensionSystem {
+class IPlugin;
+}
+
+namespace TextEditor {
+class QuickFixState;
+}
+
+namespace CppEditor {
+namespace Internal {
+
+class CppQuickFixCollector: public TextEditor::QuickFixCollector
+{
+ Q_OBJECT
+public:
+ CppQuickFixCollector();
+ virtual ~CppQuickFixCollector();
+
+ virtual bool supportsEditor(TextEditor::ITextEditable *editor);
+ virtual TextEditor::QuickFixState *initializeCompletion(TextEditor::BaseTextEditor *editor);
+
+ virtual QList<TextEditor::QuickFixFactory *> quickFixFactories() const;
+
+ /// Registers all quick-fixes in this plug-in as auto-released objects.
+ static void registerQuickFixes(ExtensionSystem::IPlugin *plugIn);
+};
+
+} // namespace Internal
+} // namespace CppEditor
+
+#endif // QUICKFIXCOLLECTOR_H
diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp
index 279141e8ca..eaaeb788be 100644
--- a/src/plugins/cppeditor/cppquickfixes.cpp
+++ b/src/plugins/cppeditor/cppquickfixes.cpp
@@ -31,9 +31,12 @@
**
**************************************************************************/
+#include "cppcompleteswitch.h"
#include "cppeditor.h"
#include "cppquickfix.h"
#include "cppinsertdecldef.h"
+#include "cppinsertqtpropertymembers.h"
+#include "cppquickfixcollector.h"
#include <ASTVisitor.h>
#include <AST.h>
@@ -54,6 +57,8 @@
#include <cplusplus/TypeOfExpression.h>
#include <cplusplus/CppRewriter.h>
#include <cpptools/cpptoolsconstants.h>
+#include <cpptools/cpprefactoringchanges.h>
+#include <cpptools/insertionpointlocator.h>
#include <extensionsystem/iplugin.h>
#include <QtGui/QApplication>
@@ -525,7 +530,7 @@ private:
changes.insert(end, "\n}");
currentFile->change(changes);
- currentFile->indent(Range(start, end));
+ currentFile->indent(Utils::ChangeSet::Range(start, end));
}
private:
@@ -1281,174 +1286,6 @@ private:
};
};
-/*
- Adds missing case statements for "switch (enumVariable)"
-*/
-class CompleteSwitchCaseStatement: public CppQuickFixFactory
-{
-public:
- virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state)
- {
- const QList<AST *> &path = state.path();
-
- if (path.isEmpty())
- return noResult(); // nothing to do
-
- // look for switch statement
- for (int depth = path.size() - 1; depth >= 0; --depth) {
- AST *ast = path.at(depth);
- SwitchStatementAST *switchStatement = ast->asSwitchStatement();
- if (switchStatement) {
- if (!state.isCursorOn(switchStatement->switch_token) || !switchStatement->statement)
- return noResult();
- CompoundStatementAST *compoundStatement = switchStatement->statement->asCompoundStatement();
- if (!compoundStatement) // we ignore pathologic case "switch (t) case A: ;"
- return noResult();
- // look if the condition's type is an enum
- if (Enum *e = conditionEnum(state, switchStatement)) {
- // check the possible enum values
- QStringList values;
- Overview prettyPrint;
- for (unsigned i = 0; i < e->memberCount(); ++i) {
- if (Declaration *decl = e->memberAt(i)->asDeclaration()) {
- values << prettyPrint(LookupContext::fullyQualifiedName(decl));
- }
- }
- // Get the used values
- Block *block = switchStatement->symbol;
- CaseStatementCollector caseValues(state.document(), state.snapshot(),
- state.document()->scopeAt(block->line(), block->column()));
- QStringList usedValues = caseValues(switchStatement);
- // save the values that would be added
- foreach (const QString &usedValue, usedValues)
- values.removeAll(usedValue);
- if (values.isEmpty())
- return noResult();
- return singleResult(new Operation(state, depth, compoundStatement, values));
- }
- return noResult();
- }
- }
-
- return noResult();
- }
-
-protected:
- Enum *conditionEnum(const CppQuickFixState &state, SwitchStatementAST *statement)
- {
- Block *block = statement->symbol;
- Scope *scope = state.document()->scopeAt(block->line(), block->column());
- TypeOfExpression typeOfExpression;
- typeOfExpression.init(state.document(), state.snapshot());
- const QList<LookupItem> results = typeOfExpression(statement->condition,
- state.document(),
- scope);
-
- ///
- /// \note FIXME: the lookup has at least two problems: the result.declaration()
- /// will often be null, (i.e. when the condition is a function call)
- /// and the lookups will not look through typedefs.
- ///
-
- foreach (LookupItem result, results) {
- FullySpecifiedType fst = result.type();
- if (! result.declaration())
- continue;
- if (Enum *e = result.declaration()->type()->asEnumType())
- return e;
- if (NamedType *namedType = fst->asNamedType()) {
- QList<LookupItem> candidates =
- typeOfExpression.context().lookup(namedType->name(), scope);
- foreach (const LookupItem &r, candidates) {
- if (Symbol *candidate = r.declaration()) {
- if (Enum *e = candidate->asEnum()) {
- return e;
- }
- }
- }
- }
- }
- return 0;
- }
-
- class CaseStatementCollector : public ASTVisitor
- {
- public:
- CaseStatementCollector(Document::Ptr document, const Snapshot &snapshot,
- Scope *scope)
- : ASTVisitor(document->translationUnit()),
- document(document),
- scope(scope)
- {
- typeOfExpression.init(document, snapshot);
- }
-
- QStringList operator ()(AST *ast)
- {
- values.clear();
- foundCaseStatementLevel = false;
- accept(ast);
- return values;
- }
-
- bool preVisit(AST *ast) {
- if (CaseStatementAST *cs = ast->asCaseStatement()) {
- foundCaseStatementLevel = true;
- if (ExpressionAST *expression = cs->expression->asIdExpression()) {
- QList<LookupItem> candidates = typeOfExpression(expression,
- document,
- scope);
- if (!candidates .isEmpty() && candidates.first().declaration()) {
- Symbol *decl = candidates.first().declaration();
- values << prettyPrint(LookupContext::fullyQualifiedName(decl));
- }
- }
- return true;
- } else if (foundCaseStatementLevel) {
- return false;
- }
- return true;
- }
-
- Overview prettyPrint;
- bool foundCaseStatementLevel;
- QStringList values;
- TypeOfExpression typeOfExpression;
- Document::Ptr document;
- Scope *scope;
- };
-
-private:
- class Operation: public CppQuickFixOperation
- {
- public:
- Operation(const CppQuickFixState &state, int priority, CompoundStatementAST *compoundStatement, const QStringList &values)
- : CppQuickFixOperation(state, priority)
- , compoundStatement(compoundStatement)
- , values(values)
- {
- setDescription(QApplication::translate("CppTools::QuickFix",
- "Complete Switch Statement"));
- }
-
-
- virtual void performChanges(CppRefactoringFile *currentFile, CppRefactoringChanges *)
- {
- ChangeSet changes;
- int start = currentFile->endOf(compoundStatement->lbrace_token);
- changes.insert(start, QLatin1String("\ncase ")
- + values.join(QLatin1String(":\nbreak;\ncase "))
- + QLatin1String(":\nbreak;"));
- currentFile->change(changes);
- currentFile->indent(currentFile->range(compoundStatement));
- }
-
- CompoundStatementAST *compoundStatement;
- QStringList values;
- };
-};
-
-
class FixForwardDeclarationOp: public CppQuickFixFactory
{
public:
@@ -1753,11 +1590,11 @@ void CppQuickFixCollector::registerQuickFixes(ExtensionSystem::IPlugin *plugIn)
plugIn->addAutoReleasedObject(new TranslateStringLiteral);
plugIn->addAutoReleasedObject(new CStringToNSString);
plugIn->addAutoReleasedObject(new ConvertNumericLiteral);
-// Disabled for now: see the CompleteSwitchCaseStatement class for the reason.
-// plugIn->addAutoReleasedObject(new CompleteSwitchCaseStatement);
+ plugIn->addAutoReleasedObject(new Internal::CompleteSwitchCaseStatement);
plugIn->addAutoReleasedObject(new FixForwardDeclarationOp);
plugIn->addAutoReleasedObject(new AddLocalDeclarationOp);
plugIn->addAutoReleasedObject(new ToCamelCaseConverter);
+ plugIn->addAutoReleasedObject(new Internal::InsertQtPropertyMembers);
plugIn->addAutoReleasedObject(new Internal::DeclFromDef);
plugIn->addAutoReleasedObject(new Internal::DefFromDecl);
}
diff --git a/src/plugins/cppeditor/cppsnippetprovider.cpp b/src/plugins/cppeditor/cppsnippetprovider.cpp
new file mode 100644
index 0000000000..b7273f8c97
--- /dev/null
+++ b/src/plugins/cppeditor/cppsnippetprovider.cpp
@@ -0,0 +1,74 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "cppsnippetprovider.h"
+#include "cpphighlighter.h"
+#include "cppeditor.h"
+#include "cppqtstyleindenter.h"
+#include "cppautocompleter.h"
+#include "cppeditorconstants.h"
+
+#include <texteditor/texteditorsettings.h>
+#include <texteditor/fontsettings.h>
+#include <texteditor/texteditorconstants.h>
+#include <texteditor/snippets/snippeteditor.h>
+
+#include <QtCore/QLatin1String>
+
+using namespace CppEditor;
+using namespace Internal;
+
+CppSnippetProvider::CppSnippetProvider() :
+ TextEditor::ISnippetProvider()
+{}
+
+CppSnippetProvider::~CppSnippetProvider()
+{}
+
+QString CppSnippetProvider::groupId() const
+{
+ return QLatin1String(Constants::CPP_SNIPPETS_GROUP_ID);
+}
+
+QString CppSnippetProvider::displayName() const
+{
+ return tr("C++");
+}
+
+void CppSnippetProvider::decorateEditor(TextEditor::SnippetEditor *editor) const
+{
+ CppHighlighter *highlighter = new CppHighlighter;
+ const TextEditor::FontSettings &fs = TextEditor::TextEditorSettings::instance()->fontSettings();
+ const QVector<QTextCharFormat> &formats =
+ fs.toTextCharFormats(CPPEditor::highlighterFormatCategories());
+ highlighter->setFormats(formats.constBegin(), formats.constEnd());
+ editor->setSyntaxHighlighter(highlighter);
+ editor->setIndenter(new CppQtStyleIndenter);
+ editor->setAutoCompleter(new CppAutoCompleter);
+}
diff --git a/src/plugins/cppeditor/cppsnippetprovider.h b/src/plugins/cppeditor/cppsnippetprovider.h
new file mode 100644
index 0000000000..ba3f172be0
--- /dev/null
+++ b/src/plugins/cppeditor/cppsnippetprovider.h
@@ -0,0 +1,53 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 CPPSNIPPETEDITORDECORATOR_H
+#define CPPSNIPPETEDITORDECORATOR_H
+
+#include <texteditor/snippets/isnippetprovider.h>
+
+namespace CppEditor {
+namespace Internal {
+
+class CppSnippetProvider : public TextEditor::ISnippetProvider
+{
+public:
+ CppSnippetProvider();
+ virtual ~CppSnippetProvider();
+
+public:
+ virtual QString groupId() const;
+ virtual QString displayName() const;
+ virtual void decorateEditor(TextEditor::SnippetEditor *editor) const;
+};
+
+} // Internal
+} // CppEditor
+
+#endif // CPPSNIPPETEDITORDECORATOR_H
diff --git a/src/plugins/cppeditor/cpptypehierarchy.cpp b/src/plugins/cppeditor/cpptypehierarchy.cpp
index 6a5a7e44a2..6c21eb2b69 100644
--- a/src/plugins/cppeditor/cpptypehierarchy.cpp
+++ b/src/plugins/cppeditor/cpptypehierarchy.cpp
@@ -39,97 +39,19 @@
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/editormanager/editormanager.h>
-#include <coreplugin/coreconstants.h>
#include <utils/navigationtreeview.h>
+#include <utils/annotateditemdelegate.h>
#include <QtCore/QLatin1Char>
#include <QtCore/QLatin1String>
#include <QtCore/QModelIndex>
-#include <QtCore/QSettings>
#include <QtGui/QVBoxLayout>
#include <QtGui/QStandardItemModel>
-#include <QtGui/QFontMetrics>
-#include <QtGui/QApplication>
-#include <QtGui/QPainter>
#include <QtGui/QLabel>
using namespace CppEditor;
using namespace Internal;
-
-// CppTypeHierarchyItem
-CppTypeHierarchyItem::CppTypeHierarchyItem(const CppClass &cppClass) :
- QStandardItem(), m_cppClass(cppClass)
-{}
-
-CppTypeHierarchyItem::~CppTypeHierarchyItem()
-{}
-
-int CppTypeHierarchyItem::type() const
-{ return UserType; }
-
-const CppClass &CppTypeHierarchyItem::cppClass() const
-{ return m_cppClass; }
-
-// CppTypeHierarchyDelegate
-CppTypeHierarchyDelegate::CppTypeHierarchyDelegate(QObject *parent) : QStyledItemDelegate(parent)
-{}
-
-CppTypeHierarchyDelegate::~CppTypeHierarchyDelegate()
-{}
-
-void CppTypeHierarchyDelegate::paint(QPainter *painter,
- const QStyleOptionViewItem &option,
- const QModelIndex &index) const
-{
- if (const QStyleOptionViewItemV3 *v3 =
- qstyleoption_cast<const QStyleOptionViewItemV3 *>(&option)) {
- QApplication::style()->drawPrimitive(QStyle::PE_PanelItemViewItem, v3, painter, v3->widget);
-
- QStyleOptionViewItemV4 opt = option;
- initStyleOption(&opt, index);
-
- const QStandardItemModel *model = static_cast<const QStandardItemModel *>(index.model());
- CppTypeHierarchyItem *item =
- static_cast<CppTypeHierarchyItem *>(model->itemFromIndex(index));
-
- painter->save();
- const QIcon &icon = item->cppClass().icon();
- const QSize &iconSize = icon.actualSize(opt.decorationSize);
- QRect workingRect(opt.rect);
- QRect decorationRect(workingRect.topLeft(), iconSize);
- icon.paint(painter, decorationRect, opt.decorationAlignment);
- workingRect.setX(workingRect.x() + iconSize.width() + 4);
-
- QRect boundingRect;
- const QString &name = item->cppClass().name() + QLatin1Char(' ');
- painter->drawText(workingRect, Qt::AlignLeft, name, &boundingRect);
- if (item->cppClass().name() != item->cppClass().qualifiedName()) {
- QFont font(painter->font());
- if (font.pointSize() > 2)
- font.setPointSize(font.pointSize() - 2);
- else if (font.pointSize() > 1)
- font.setPointSize(font.pointSize() - 1);
- font.setItalic(true);
- painter->setFont(font);
-
- QFontMetrics metrics(font);
- workingRect.setX(boundingRect.x() + boundingRect.width());
- workingRect.setY(boundingRect.y() + boundingRect.height() - metrics.height());
- painter->drawText(workingRect, Qt::AlignLeft, item->cppClass().qualifiedName());
- }
- painter->restore();
- } else {
- QStyledItemDelegate::paint(painter, option, index);
- }
-}
-
-QSize CppTypeHierarchyDelegate::sizeHint(const QStyleOptionViewItem &option,
- const QModelIndex &index) const
-{
- QSize size = QStyledItemDelegate::sizeHint(option, index);
- size.rwidth() += 5; // Extend a bit because of the font processing.
- return size;
-}
+using namespace Utils;
// CppTypeHierarchyWidget
CppTypeHierarchyWidget::CppTypeHierarchyWidget(Core::IEditor *editor) :
@@ -148,7 +70,9 @@ CppTypeHierarchyWidget::CppTypeHierarchyWidget(Core::IEditor *editor) :
m_model = new QStandardItemModel;
m_treeView = new Utils::NavigationTreeView;
- m_delegate = new CppTypeHierarchyDelegate;
+ m_delegate = new AnnotatedItemDelegate;
+ m_delegate->setDelimiter(QLatin1String(" "));
+ m_delegate->setAnnotationRole(AnnotationRole);
m_treeView->setModel(m_model);
m_treeView->setEditTriggers(QAbstractItemView::NoEditTriggers);
m_treeView->setItemDelegate(m_delegate);
@@ -204,13 +128,16 @@ void CppTypeHierarchyWidget::perform()
void CppTypeHierarchyWidget::buildModel(const CppClass &cppClass, QStandardItem *parent)
{
- CppTypeHierarchyItem *item = new CppTypeHierarchyItem(cppClass);
+ QStandardItem *item = new QStandardItem;
parent->appendRow(item);
- // The delegate retrieves data from the item directly. This is to help size hint.
- const QString &display = cppClass.name() + cppClass.qualifiedName();
- m_model->setData(m_model->indexFromItem(item), display, Qt::DisplayRole);
+ m_model->setData(m_model->indexFromItem(item), cppClass.name(), Qt::DisplayRole);
+ if (cppClass.name() != cppClass.qualifiedName())
+ m_model->setData(m_model->indexFromItem(item), cppClass.qualifiedName(), AnnotationRole);
m_model->setData(m_model->indexFromItem(item), cppClass.icon(), Qt::DecorationRole);
+ QVariant link;
+ link.setValue(CPPEditor::Link(cppClass.link()));
+ m_model->setData(m_model->indexFromItem(item), link, LinkRole);
foreach (const CppClass &cppBase, cppClass.bases())
buildModel(cppBase, item);
@@ -220,10 +147,7 @@ void CppTypeHierarchyWidget::buildModel(const CppClass &cppClass, QStandardItem
void CppTypeHierarchyWidget::onItemClicked(const QModelIndex &index)
{
- if (QStandardItem *item = m_model->itemFromIndex(index)) {
- CppTypeHierarchyItem *cppItem = static_cast<CppTypeHierarchyItem *>(item);
- m_cppEditor->openLink(cppItem->cppClass().link());
- }
+ m_cppEditor->openLink(index.data(LinkRole).value<CPPEditor::Link>());
}
// CppTypeHierarchyStackedWidget
diff --git a/src/plugins/cppeditor/cpptypehierarchy.h b/src/plugins/cppeditor/cpptypehierarchy.h
index 79322aaf55..60b5b4a787 100644
--- a/src/plugins/cppeditor/cpptypehierarchy.h
+++ b/src/plugins/cppeditor/cpptypehierarchy.h
@@ -41,13 +41,11 @@
#include <QtCore/QString>
#include <QtGui/QWidget>
#include <QtGui/QStackedWidget>
-#include <QtGui/QStandardItem>
-#include <QtGui/QStyledItemDelegate>
QT_BEGIN_NAMESPACE
class QStandardItemModel;
+class QStandardItem;
class QModelIndex;
-class QPainter;
QT_END_NAMESPACE
namespace Core {
@@ -56,6 +54,7 @@ class IEditor;
namespace Utils {
class NavigationTreeView;
+class AnnotatedItemDelegate;
}
namespace CppEditor {
@@ -63,32 +62,6 @@ namespace Internal {
class CPPEditor;
-class CppTypeHierarchyItem : public QStandardItem
-{
-public:
- CppTypeHierarchyItem(const CppClass &cppClass);
- virtual ~CppTypeHierarchyItem();
-
- virtual int type() const;
-
- const CppClass &cppClass() const;
-
-private:
- CppClass m_cppClass;
-};
-
-class CppTypeHierarchyDelegate : public QStyledItemDelegate
-{
-public:
- CppTypeHierarchyDelegate(QObject *parent = 0);
- virtual ~CppTypeHierarchyDelegate();
-
- virtual void paint(QPainter *painter,
- const QStyleOptionViewItem &option,
- const QModelIndex &index) const;
- virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
-};
-
class CppTypeHierarchyWidget : public QWidget
{
Q_OBJECT
@@ -105,12 +78,17 @@ private slots:
void onItemClicked(const QModelIndex &index);
private:
+ enum ItemRole {
+ AnnotationRole = Qt::UserRole + 1,
+ LinkRole
+ };
+
void buildModel(const CppClass &cppClass, QStandardItem *item);
CPPEditor *m_cppEditor;
Utils::NavigationTreeView *m_treeView;
QStandardItemModel *m_model;
- CppTypeHierarchyDelegate *m_delegate;
+ Utils::AnnotatedItemDelegate *m_delegate;
};
// @todo: Pretty much the same design as the OutlineWidgetStack. Maybe we can generalize the
diff --git a/src/plugins/cpptools/CppTools.pluginspec b/src/plugins/cpptools/CppTools.pluginspec
deleted file mode 100644
index c7bd234c28..0000000000
--- a/src/plugins/cpptools/CppTools.pluginspec
+++ /dev/null
@@ -1,22 +0,0 @@
-<plugin name="CppTools" version="2.0.95" compatVersion="2.0.95">
- <vendor>Nokia Corporation</vendor>
- <copyright>(C) 2010 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>
- <category>C++</category>
- <description>Tools for analyzing C/C++ code.</description>
- <url>http://qt.nokia.com</url>
- <dependencyList>
- <dependency name="TextEditor" version="2.0.95"/>
- <dependency name="ProjectExplorer" version="2.0.95"/>
- <dependency name="Locator" version="2.0.95"/>
- <dependency name="Find" version="2.0.95"/>
- </dependencyList>
-</plugin>
diff --git a/src/plugins/cpptools/CppTools.pluginspec.in b/src/plugins/cpptools/CppTools.pluginspec.in
new file mode 100644
index 0000000000..704a64f450
--- /dev/null
+++ b/src/plugins/cpptools/CppTools.pluginspec.in
@@ -0,0 +1,22 @@
+<plugin name=\"CppTools\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2010 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>
+ <category>C++</category>
+ <description>Tools for analyzing C/C++ code.</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name=\"TextEditor\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"ProjectExplorer\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"Locator\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"Find\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/cpptools/completionsettingspage.cpp b/src/plugins/cpptools/completionsettingspage.cpp
index 8e74bfed09..5df367d82f 100644
--- a/src/plugins/cpptools/completionsettingspage.cpp
+++ b/src/plugins/cpptools/completionsettingspage.cpp
@@ -44,7 +44,7 @@
using namespace CppTools::Internal;
CompletionSettingsPage::CompletionSettingsPage()
- : m_page(new Ui_CompletionSettingsPage)
+ : m_page(0)
{
}
@@ -66,6 +66,7 @@ QString CompletionSettingsPage::displayName() const
QWidget *CompletionSettingsPage::createPage(QWidget *parent)
{
QWidget *w = new QWidget(parent);
+ m_page = new Ui_CompletionSettingsPage;
m_page->setupUi(w);
const TextEditor::CompletionSettings &settings =
@@ -117,6 +118,8 @@ QWidget *CompletionSettingsPage::createPage(QWidget *parent)
void CompletionSettingsPage::apply()
{
+ if (!m_page) // page was never shown
+ return;
TextEditor::CompletionSettings settings;
settings.m_caseSensitivity = caseSensitivity();
settings.m_completionTrigger = completionTrigger();
@@ -155,3 +158,11 @@ TextEditor::CompletionTrigger CompletionSettingsPage::completionTrigger() const
return TextEditor::AutomaticCompletion;
}
}
+
+void CompletionSettingsPage::finish()
+{
+ if (!m_page) // page was never shown
+ return;
+ delete m_page;
+ m_page = 0;
+}
diff --git a/src/plugins/cpptools/completionsettingspage.h b/src/plugins/cpptools/completionsettingspage.h
index 4cf2135f1d..f2927677cf 100644
--- a/src/plugins/cpptools/completionsettingspage.h
+++ b/src/plugins/cpptools/completionsettingspage.h
@@ -59,7 +59,7 @@ public:
QWidget *createPage(QWidget *parent);
void apply();
- void finish() { }
+ void finish();
virtual bool matches(const QString &) const;
private:
diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp
index 7e0d2502d2..9e3a5a534f 100644
--- a/src/plugins/cpptools/cppcodecompletion.cpp
+++ b/src/plugins/cpptools/cppcodecompletion.cpp
@@ -56,6 +56,8 @@
#include <cplusplus/BackwardsScanner.h>
#include <cplusplus/LookupContext.h>
+#include <cppeditor/cppeditorconstants.h>
+
#include <coreplugin/icore.h>
#include <coreplugin/mimedatabase.h>
#include <coreplugin/editormanager/editormanager.h>
@@ -63,6 +65,7 @@
#include <texteditor/itexteditor.h>
#include <texteditor/itexteditable.h>
#include <texteditor/basetexteditor.h>
+#include <texteditor/snippets/snippet.h>
#include <projectexplorer/projectexplorer.h>
#include <utils/faketooltip.h>
@@ -466,7 +469,8 @@ CppCodeCompletion::CppCodeCompletion(CppModelManager *manager)
m_automaticCompletion(false),
m_completionOperator(T_EOF_SYMBOL),
m_objcEnabled(true),
- m_snippetsParser(Core::ICore::instance()->resourcePath() + QLatin1String("/snippets/cpp.xml"))
+ m_snippetProvider(CppEditor::Constants::CPP_SNIPPETS_GROUP_ID,
+ QIcon(QLatin1String(":/texteditor/images/snippet.png")))
{
}
@@ -715,6 +719,31 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
{
int index = startCompletionHelper(editor);
if (index != -1) {
+ if (m_automaticCompletion) {
+ const int pos = editor->position();
+ const QChar ch = editor->characterAt(pos);
+ if (! (ch.isLetterOrNumber() || ch == QLatin1Char('_'))) {
+ for (int i = pos - 1;; --i) {
+ const QChar ch = editor->characterAt(i);
+ if (ch.isLetterOrNumber() || ch == QLatin1Char('_')) {
+ const QString wordUnderCursor = editor->textAt(i, pos - i);
+ if (wordUnderCursor.at(0).isLetter() || wordUnderCursor.at(0) == QLatin1Char('_')) {
+ foreach (const TextEditor::CompletionItem &i, m_completions) {
+ if (i.text == wordUnderCursor) {
+ cleanup();
+ return -1;
+ }
+ }
+ } else {
+ cleanup();
+ return -1;
+ }
+ } else
+ break;
+ }
+ }
+ }
+
if (m_completionOperator != T_EOF_SYMBOL)
qSort(m_completions.begin(), m_completions.end(), completionItemLessThan);
@@ -755,12 +784,12 @@ void CppCodeCompletion::completeObjCMsgSend(ClassOrNamespace *binding,
Symbol *arg = method->argumentAt(i);
text += selectorName->nameAt(i)->identifier()->chars();
text += QLatin1Char(':');
- text += QChar::ObjectReplacementCharacter;
+ text += TextEditor::Snippet::kVariableDelimiter;
text += QLatin1Char('(');
text += oo(arg->type());
text += QLatin1Char(')');
text += oo(arg->name());
- text += QChar::ObjectReplacementCharacter;
+ text += TextEditor::Snippet::kVariableDelimiter;
}
} else {
text = selectorName->identifier()->chars();
@@ -1922,6 +1951,11 @@ void CppCodeCompletion::complete(const TextEditor::CompletionItem &item, QChar t
}
#endif
} else if (! function->isAmbiguous()) {
+ // When the user typed the opening parenthesis, he'll likely also type the closing one,
+ // in which case it would be annoying if we put the cursor after the already automatically
+ // inserted closing parenthesis.
+ const bool skipClosingParenthesis = typedChar != QLatin1Char('(');
+
if (completionSettings().m_spaceAfterFunctionName)
extraChars += QLatin1Char(' ');
extraChars += QLatin1Char('(');
@@ -1941,7 +1975,7 @@ void CppCodeCompletion::complete(const TextEditor::CompletionItem &item, QChar t
}
// If the function takes no arguments, automatically place the closing parenthesis
- if (item.duplicateCount == 0 && ! function->hasArguments()) {
+ if (item.duplicateCount == 0 && ! function->hasArguments() && skipClosingParenthesis) {
extraChars += QLatin1Char(')');
if (endWithSemicolon) {
extraChars += semicolon;
@@ -2062,8 +2096,7 @@ bool CppCodeCompletion::objcKeywordsWanted() const
void CppCodeCompletion::addSnippets()
{
- static const QIcon icon(QLatin1String(":/texteditor/images/snippet.png"));
- m_completions.append(m_snippetsParser.execute(this, icon));
+ m_completions.append(m_snippetProvider.getSnippets(this));
}
#include "cppcodecompletion.moc"
diff --git a/src/plugins/cpptools/cppcodecompletion.h b/src/plugins/cpptools/cppcodecompletion.h
index 7ac11c2821..46bb3945d8 100644
--- a/src/plugins/cpptools/cppcodecompletion.h
+++ b/src/plugins/cpptools/cppcodecompletion.h
@@ -41,7 +41,7 @@
#include <cplusplus/TypeOfExpression.h>
#include <texteditor/icompletioncollector.h>
-#include <texteditor/snippetsparser.h>
+#include <texteditor/snippets/snippetcollector.h>
#include <QtCore/QObject>
#include <QtCore/QPointer>
@@ -157,7 +157,7 @@ private:
unsigned m_completionOperator;
bool m_objcEnabled;
- TextEditor::SnippetsParser m_snippetsParser;
+ TextEditor::SnippetCollector m_snippetProvider;
CPlusPlus::Icons m_icons;
CPlusPlus::Overview overview;
diff --git a/src/plugins/cpptools/cppcodeformatter.cpp b/src/plugins/cpptools/cppcodeformatter.cpp
index 281ce0c943..fdb179f3a4 100644
--- a/src/plugins/cpptools/cppcodeformatter.cpp
+++ b/src/plugins/cpptools/cppcodeformatter.cpp
@@ -386,6 +386,12 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
default: leave(); continue;
} break;
+ case label:
+ switch (kind) {
+ case T_COLON: leave(); break;
+ default: leave(); continue; // shouldn't happen
+ } break;
+
case multiline_comment_start:
case multiline_comment_cont:
if (kind != T_COMMENT && kind != T_DOXY_COMMENT) {
@@ -714,6 +720,10 @@ bool CodeFormatter::tryDeclaration()
enter(qt_like_macro);
return true;
}
+ if (m_tokens.size() > 1 && m_tokens.at(1).kind() == T_COLON) {
+ enter(label);
+ return true;
+ }
}
// fallthrough
case T_CHAR:
@@ -1042,12 +1052,13 @@ void QtStyleCodeFormatter::onEnter(int newState, int *indentDepth, int *savedInd
{
const State &parentState = state();
const Token &tk = currentToken();
- const int tokenPosition = column(tk.begin());
const bool firstToken = (tokenIndex() == 0);
const bool lastToken = (tokenIndex() == tokenCount() - 1);
- int nextTokenStart = 0;
- if (!lastToken)
- nextTokenStart = column(tokenAt(tokenIndex() + 1).begin());
+ const int tokenPosition = column(tk.begin());
+ const int nextTokenPosition = lastToken ? tokenPosition + tk.length()
+ : column(tokenAt(tokenIndex() + 1).begin());
+ const int spaceOrNextTokenPosition = lastToken ? tokenPosition + tk.length() + 1
+ : nextTokenPosition;
if (shouldClearPaddingOnEnter(newState))
*paddingDepth = 0;
@@ -1071,7 +1082,7 @@ void QtStyleCodeFormatter::onEnter(int newState, int *indentDepth, int *savedInd
case template_param:
if (!lastToken)
- *paddingDepth = tokenPosition-*indentDepth + tk.length();
+ *paddingDepth = nextTokenPosition-*indentDepth;
else {
if (*paddingDepth == 0)
*paddingDepth = 2*m_indentSize;
@@ -1108,24 +1119,24 @@ void QtStyleCodeFormatter::onEnter(int newState, int *indentDepth, int *savedInd
case arglist_open:
case condition_paren_open:
if (!lastToken)
- *paddingDepth = tokenPosition-*indentDepth + 1;
+ *paddingDepth = nextTokenPosition-*indentDepth;
else
*paddingDepth += m_indentSize;
break;
case ternary_op:
if (!lastToken)
- *paddingDepth = tokenPosition-*indentDepth + tk.length() + 1;
+ *paddingDepth = spaceOrNextTokenPosition-*indentDepth;
else
*paddingDepth += m_indentSize;
break;
case stream_op:
- *paddingDepth = tokenPosition-*indentDepth + tk.length() + 1;
+ *paddingDepth = spaceOrNextTokenPosition-*indentDepth;
break;
case stream_op_cont:
if (firstToken)
- *savedPaddingDepth = *paddingDepth = tokenPosition-*indentDepth + tk.length() + 1;
+ *savedPaddingDepth = *paddingDepth = spaceOrNextTokenPosition-*indentDepth;
break;
case member_init_open:
@@ -1163,7 +1174,7 @@ void QtStyleCodeFormatter::onEnter(int newState, int *indentDepth, int *savedInd
*indentDepth += m_indentSize;
if (followedByData) {
- *paddingDepth = column(tokenAt(tokenIndex() + 1).begin()) - *indentDepth;
+ *paddingDepth = nextTokenPosition-*indentDepth;
}
break;
}
@@ -1192,7 +1203,7 @@ void QtStyleCodeFormatter::onEnter(int newState, int *indentDepth, int *savedInd
if (!lastToken) {
if (parentState.type == initializer)
*savedPaddingDepth = tokenPosition-*indentDepth;
- *paddingDepth = nextTokenStart-*indentDepth;
+ *paddingDepth = nextTokenPosition-*indentDepth;
} else {
// avoid existing continuation indents
if (parentState.type == initializer)
@@ -1202,7 +1213,11 @@ void QtStyleCodeFormatter::onEnter(int newState, int *indentDepth, int *savedInd
break;
case block_open:
- if (parentState.type != case_cont)
+ // case_cont already adds some indent, revert it for a block
+ if (parentState.type == case_cont && !m_indentSubstatementBraces)
+ *indentDepth = *savedIndentDepth = parentState.savedIndentDepth;
+
+ if (m_indentSubstatementStatements)
*indentDepth += m_indentSize;
break;
@@ -1212,10 +1227,10 @@ void QtStyleCodeFormatter::onEnter(int newState, int *indentDepth, int *savedInd
*savedPaddingDepth = *paddingDepth;
// fixed extra indent when continuing 'if (', but not for 'else if ('
- if (tokenPosition <= *indentDepth + m_indentSize)
+ if (nextTokenPosition-*indentDepth <= m_indentSize)
*paddingDepth = 2*m_indentSize;
else
- *paddingDepth = tokenPosition-*indentDepth + 1;
+ *paddingDepth = nextTokenPosition-*indentDepth;
break;
case substatement:
@@ -1235,11 +1250,11 @@ void QtStyleCodeFormatter::onEnter(int newState, int *indentDepth, int *savedInd
} break;
case for_statement_paren_open:
- *paddingDepth = tokenPosition + 1 - *indentDepth;
+ *paddingDepth = nextTokenPosition - *indentDepth;
break;
case multiline_comment_start:
- *indentDepth = tokenPosition + 2;
+ *indentDepth = tokenPosition + 2; // nextTokenPosition won't work
break;
case multiline_comment_cont:
@@ -1306,6 +1321,8 @@ void QtStyleCodeFormatter::adjustIndent(const QList<CPlusPlus::Token> &tokens, i
case T_LBRACE: {
if (topState.type == case_cont) {
*indentDepth = topState.savedIndentDepth;
+ if (m_indentSubstatementBraces)
+ *indentDepth += m_indentSize;
*paddingDepth = 0;
// function definition - argument list is expression state
} else if (topState.type == expression && previousState.type == declaration_start) {
@@ -1336,8 +1353,8 @@ void QtStyleCodeFormatter::adjustIndent(const QList<CPlusPlus::Token> &tokens, i
}
case T_RBRACE: {
if (topState.type == block_open && previousState.type == case_cont) {
- *indentDepth = previousState.savedIndentDepth;
- *paddingDepth = previousState.savedPaddingDepth;
+ *indentDepth = topState.savedIndentDepth;
+ *paddingDepth = topState.savedPaddingDepth;
break;
}
for (int i = 0; state(i).type != topmost_intro; ++i) {
@@ -1369,10 +1386,16 @@ void QtStyleCodeFormatter::adjustIndent(const QList<CPlusPlus::Token> &tokens, i
// }
// break;
case T_DEFAULT:
- case T_CASE:
+ case T_CASE: {
+ int lastSubstatementIndent = 0;
for (int i = 0; state(i).type != topmost_intro; ++i) {
const int type = state(i).type;
- if (type == switch_statement || type == case_cont) {
+ if (type == substatement_open) {
+ lastSubstatementIndent = state(i).savedIndentDepth;
+ } else if (type == switch_statement) {
+ *indentDepth = lastSubstatementIndent;
+ break;
+ } else if (type == case_cont) {
*indentDepth = state(i).savedIndentDepth;
break;
} else if (type == topmost_intro) {
@@ -1380,6 +1403,7 @@ void QtStyleCodeFormatter::adjustIndent(const QList<CPlusPlus::Token> &tokens, i
}
}
break;
+ }
case T_PUBLIC:
case T_PRIVATE:
case T_PROTECTED:
@@ -1418,6 +1442,16 @@ void QtStyleCodeFormatter::adjustIndent(const QList<CPlusPlus::Token> &tokens, i
*indentDepth = 0;
}
break;
+ case T_IDENTIFIER:
+ if (topState.type == substatement
+ || topState.type == substatement_open
+ || topState.type == case_cont
+ || topState.type == block_open
+ || topState.type == defun_open) {
+ if (tokens.size() > 1 && tokens.at(1).kind() == T_COLON) // label?
+ *indentDepth = 0;
+ }
+ break;
}
}
diff --git a/src/plugins/cpptools/cppcodeformatter.h b/src/plugins/cpptools/cppcodeformatter.h
index 2034d8771d..a556ced7d5 100644
--- a/src/plugins/cpptools/cppcodeformatter.h
+++ b/src/plugins/cpptools/cppcodeformatter.h
@@ -54,7 +54,7 @@ namespace TextEditor {
class TabSettings;
}
-namespace CppTools {
+namespace CppTools {
namespace Internal {
class CppCodeFormatterData;
}
@@ -116,6 +116,7 @@ public: // must be public to make Q_GADGET introspection work
cpp_macro_cont, // Subsequent lines of a multi-line C preprocessor macro definition.
cpp_macro_conditional, // Special marker used for separating saved from current state when dealing with #ifdef
qt_like_macro, // after an identifier starting with Q_ or QT_ at the beginning of the line
+ label, // after an identifier followed by a colon
defun_open, // Brace that opens a top-level function definition.
using_start, // right after the "using" token
@@ -173,7 +174,7 @@ public: // must be public to make Q_GADGET introspection work
assign_open, // after an assignment token
expression, // after a '=' in a declaration_start once we're sure it's not '= {'
- initializer, // after a '=' in a declaration start
+ initializer // after a '=' in a declaration start
};
Q_ENUMS(StateType)
diff --git a/src/plugins/cpptools/cppfilesettingspage.cpp b/src/plugins/cpptools/cppfilesettingspage.cpp
index 401c6bcb47..35f74d672a 100644
--- a/src/plugins/cpptools/cppfilesettingspage.cpp
+++ b/src/plugins/cpptools/cppfilesettingspage.cpp
@@ -49,6 +49,7 @@
#include <QtCore/QCoreApplication>
#include <QtCore/QDate>
#include <QtCore/QLocale>
+#include <QtCore/QTextCodec>
#include <QtCore/QTextStream>
#include <QtGui/QFileDialog>
@@ -120,6 +121,14 @@ static bool keyWordReplacement(const QString &keyWord,
*value = QString::number(QDate::currentDate().year());
return true;
}
+ if (keyWord == QLatin1String("%MONTH%")) {
+ *value = QString::number(QDate::currentDate().month());
+ return true;
+ }
+ if (keyWord == QLatin1String("%DAY%")) {
+ *value = QString::number(QDate::currentDate().day());
+ return true;
+ }
if (keyWord == QLatin1String("%CLASS%")) {
*value = className;
return true;
@@ -204,7 +213,13 @@ QString CppFileSettings::licenseTemplate(const QString &fileName, const QString
qWarning("Unable to open the license template %s: %s", qPrintable(path), qPrintable(file.errorString()));
return QString();
}
- QString license = QString::fromUtf8(file.readAll());
+
+ QTextCodec *codec = Core::EditorManager::instance()->defaultTextEncoding();
+ QTextStream licenseStream(&file);
+ licenseStream.setCodec(codec);
+ licenseStream.setAutoDetectUnicode(true);
+ QString license = licenseStream.readAll();
+
parseLicenseTemplatePlaceholders(&license, fileName, className);
// Ensure exactly one additional new line separating stuff
const QChar newLine = QLatin1Char('\n');
diff --git a/src/plugins/cpptools/cpptools.pri b/src/plugins/cpptools/cpptools.pri
index 1dffbfc556..5732e896e7 100644
--- a/src/plugins/cpptools/cpptools.pri
+++ b/src/plugins/cpptools/cpptools.pri
@@ -1,3 +1,3 @@
include(cpptools_dependencies.pri)
-LIBS *= -l$$qtLibraryTarget(CppTools)
+LIBS *= -l$$qtLibraryName(CppTools)
diff --git a/src/plugins/cpptools/cpptools.pro b/src/plugins/cpptools/cpptools.pro
index 8062333db7..57507f3612 100644
--- a/src/plugins/cpptools/cpptools.pro
+++ b/src/plugins/cpptools/cpptools.pro
@@ -26,6 +26,7 @@ HEADERS += completionsettingspage.h \
cppfindreferences.h \
cppcodeformatter.h \
symbolsfindfilter.h \
+ uicodecompletionsupport.h \
insertionpointlocator.h \
cpprefactoringchanges.h
@@ -45,10 +46,9 @@ SOURCES += completionsettingspage.cpp \
cppfindreferences.cpp \
cppcodeformatter.cpp \
symbolsfindfilter.cpp \
+ uicodecompletionsupport.cpp \
insertionpointlocator.cpp \
cpprefactoringchanges.cpp
FORMS += completionsettingspage.ui \
cppfilesettingspage.ui
-
-OTHER_FILES += CppTools.pluginspec
diff --git a/src/plugins/cpptools/cpptoolsplugin.cpp b/src/plugins/cpptools/cpptoolsplugin.cpp
index 22419d23dd..947675e624 100644
--- a/src/plugins/cpptools/cpptoolsplugin.cpp
+++ b/src/plugins/cpptools/cpptoolsplugin.cpp
@@ -51,6 +51,7 @@
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/command.h>
+#include <coreplugin/uniqueidmanager.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <coreplugin/vcsmanager.h>
@@ -105,7 +106,7 @@ bool CppToolsPlugin::initialize(const QStringList &arguments, QString *error)
// Objects
m_modelManager = new CppModelManager(this);
- Core::VCSManager *vcsManager = core->vcsManager();
+ Core::VcsManager *vcsManager = core->vcsManager();
Core::FileManager *fileManager = core->fileManager();
connect(vcsManager, SIGNAL(repositoryChanged(QString)),
m_modelManager, SLOT(updateModifiedSourceFiles()));
diff --git a/src/plugins/cpptools/insertionpointlocator.h b/src/plugins/cpptools/insertionpointlocator.h
index bc250fcb8e..f475041fa2 100644
--- a/src/plugins/cpptools/insertionpointlocator.h
+++ b/src/plugins/cpptools/insertionpointlocator.h
@@ -98,7 +98,7 @@ public:
PublicSlot = Public | SlotBit,
ProtectedSlot = Protected | SlotBit,
- PrivateSlot = Private | SlotBit,
+ PrivateSlot = Private | SlotBit
};
public:
diff --git a/src/plugins/cpptools/uicodecompletionsupport.cpp b/src/plugins/cpptools/uicodecompletionsupport.cpp
new file mode 100644
index 0000000000..dc226b09a3
--- /dev/null
+++ b/src/plugins/cpptools/uicodecompletionsupport.cpp
@@ -0,0 +1,197 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "uicodecompletionsupport.h"
+#include <QtCore/QProcess>
+
+enum { debug = 0 };
+
+using namespace CppTools;
+
+UiCodeModelSupport::UiCodeModelSupport(CppTools::CppModelManagerInterface *modelmanager,
+ const QString &source,
+ const QString &uiHeaderFile)
+ : CppTools::AbstractEditorSupport(modelmanager),
+ m_sourceName(source),
+ m_fileName(uiHeaderFile),
+ m_updateIncludingFiles(false),
+ m_initialized(false)
+{
+ if (debug)
+ qDebug()<<"ctor UiCodeModelSupport for"<<m_sourceName<<uiHeaderFile;
+}
+
+UiCodeModelSupport::~UiCodeModelSupport()
+{
+ if (debug)
+ qDebug()<<"dtor ~UiCodeModelSupport for"<<m_sourceName;
+}
+
+void UiCodeModelSupport::init() const
+{
+ m_initialized = true;
+ QDateTime sourceTime = QFileInfo(m_sourceName).lastModified();
+ QFileInfo uiHeaderFileInfo(m_fileName);
+ QDateTime uiHeaderTime = uiHeaderFileInfo.exists() ? uiHeaderFileInfo.lastModified() : QDateTime();
+ if (uiHeaderTime.isValid() && (uiHeaderTime > sourceTime)) {
+ QFile file(m_fileName);
+ if (file.open(QFile::ReadOnly)) {
+ if (debug)
+ qDebug()<<"ui*h file is more recent then source file, using information from ui*h file"<<m_fileName;
+ QTextStream stream(&file);
+ m_contents = stream.readAll().toUtf8();
+ m_cacheTime = uiHeaderTime;
+ return;
+ }
+ }
+
+ if (debug)
+ qDebug()<<"ui*h file not found, or not recent enough, trying to create it on the fly";
+ QFile file(m_sourceName);
+ if (file.open(QFile::ReadOnly)) {
+ QTextStream stream(&file);
+ const QString contents = stream.readAll();
+ if (runUic(contents)) {
+ if (debug)
+ qDebug()<<"created on the fly";
+ return;
+ } else {
+ // uic run was unsuccesfull
+ if (debug)
+ qDebug()<<"uic run wasn't succesfull";
+ m_cacheTime = QDateTime ();
+ m_contents = QByteArray();
+ // and if the header file wasn't there, next time we need to update
+ // all of the files that include this header
+ if (!uiHeaderFileInfo.exists())
+ m_updateIncludingFiles = true;
+ return;
+ }
+ } else {
+ if (debug)
+ qDebug()<<"Could open "<<m_sourceName<<"needed for the cpp model";
+ m_contents = QByteArray();
+ }
+}
+
+QByteArray UiCodeModelSupport::contents() const
+{
+ if (!m_initialized)
+ init();
+
+ return m_contents;
+}
+
+QString UiCodeModelSupport::fileName() const
+{
+ return m_fileName;
+}
+
+void UiCodeModelSupport::setFileName(const QString &name)
+{
+ if (m_fileName == name && m_cacheTime.isValid())
+ return;
+
+ if (debug)
+ qDebug() << "UiCodeModelSupport::setFileName"<<name;
+
+ m_fileName = name;
+ m_contents.clear();
+ m_cacheTime = QDateTime();
+ init();
+}
+
+bool UiCodeModelSupport::runUic(const QString &ui) const
+{
+ QProcess process;
+ const QString uic = uicCommand();
+ process.setEnvironment(environment());
+
+ if (debug)
+ qDebug() << "UiCodeModelSupport::runUic " << uic << " on " << ui.size() << " bytes";
+ process.start(uic, QStringList(), QIODevice::ReadWrite);
+ if (!process.waitForStarted())
+ return false;
+ process.write(ui.toUtf8());
+ process.closeWriteChannel();
+ if (process.waitForFinished() && process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0) {
+ m_contents = process.readAllStandardOutput();
+ m_cacheTime = QDateTime::currentDateTime();
+ if (debug)
+ qDebug() << "ok" << m_contents.size() << "bytes.";
+ return true;
+ } else {
+ if (debug)
+ qDebug() << "failed" << process.readAllStandardError();
+ process.kill();
+ }
+ return false;
+}
+
+void UiCodeModelSupport::updateFromEditor(const QString &formEditorContents)
+{
+ if (runUic(formEditorContents)) {
+ updateDocument();
+ }
+}
+
+void UiCodeModelSupport::updateFromBuild()
+{
+ if (debug)
+ qDebug()<<"UiCodeModelSupport::updateFromBuild() for file"<<m_sourceName;
+ // This is mostly a fall back for the cases when uic couldn't be run
+ // it pays special attention to the case where a ui_*h was newly created
+ QDateTime sourceTime = QFileInfo(m_sourceName).lastModified();
+ if (m_cacheTime.isValid() && m_cacheTime >= sourceTime) {
+ if (debug)
+ qDebug()<<"Cache is still more recent then source";
+ return;
+ } else {
+ QFileInfo fi(m_fileName);
+ QDateTime uiHeaderTime = fi.exists() ? fi.lastModified() : QDateTime();
+ if (uiHeaderTime.isValid() && (uiHeaderTime > sourceTime)) {
+ if (m_cacheTime >= uiHeaderTime)
+ return;
+ if (debug)
+ qDebug()<<"found ui*h updating from it";
+
+ QFile file(m_fileName);
+ if (file.open(QFile::ReadOnly)) {
+ QTextStream stream(&file);
+ m_contents = stream.readAll().toUtf8();
+ m_cacheTime = uiHeaderTime;
+ updateDocument();
+ return;
+ }
+ }
+ if (debug)
+ qDebug()<<"ui*h not found or not more recent then source not changing anything";
+ }
+}
+
diff --git a/src/plugins/cpptools/uicodecompletionsupport.h b/src/plugins/cpptools/uicodecompletionsupport.h
new file mode 100644
index 0000000000..b03294960d
--- /dev/null
+++ b/src/plugins/cpptools/uicodecompletionsupport.h
@@ -0,0 +1,70 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 UICODECOMPLETIONSUPPORT_H
+#define UICODECOMPLETIONSUPPORT_H
+
+#include "cppmodelmanagerinterface.h"
+#include "cpptools_global.h"
+
+#include <QtCore/QDateTime>
+
+namespace CppTools {
+
+class CPPTOOLS_EXPORT UiCodeModelSupport : public CppTools::AbstractEditorSupport
+{
+public:
+ UiCodeModelSupport(CppTools::CppModelManagerInterface *modelmanager,
+ const QString &sourceFile,
+ const QString &uiHeaderFile);
+ ~UiCodeModelSupport();
+ void setFileName(const QString &name);
+ void setSourceName(const QString &name);
+ virtual QByteArray contents() const;
+ virtual QString fileName() const;
+ void updateFromEditor(const QString &formEditorContents);
+ void updateFromBuild();
+protected:
+ virtual QString uicCommand() const = 0;
+ virtual QStringList environment() const = 0;
+private:
+ void init() const;
+ bool runUic(const QString &ui) const;
+ QString m_sourceName;
+ QString m_fileName;
+ mutable bool m_updateIncludingFiles;
+ mutable bool m_initialized;
+ mutable QByteArray m_contents;
+ mutable QDateTime m_cacheTime;
+};
+
+} // CppTools
+
+#endif // UICODECOMPLETIONSUPPORT_H
diff --git a/src/plugins/cvs/CVS.pluginspec b/src/plugins/cvs/CVS.pluginspec
deleted file mode 100644
index 69855d63c2..0000000000
--- a/src/plugins/cvs/CVS.pluginspec
+++ /dev/null
@@ -1,22 +0,0 @@
-<plugin name="CVS" version="2.0.95" compatVersion="2.0.95">
- <vendor>Nokia Corporation</vendor>
- <copyright>(C) 2010 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>
- <category>Version Control</category>
- <description>CVS integration.</description>
- <url>http://qt.nokia.com</url>
- <dependencyList>
- <dependency name="TextEditor" version="2.0.95"/>
- <dependency name="ProjectExplorer" version="2.0.95"/>
- <dependency name="Core" version="2.0.95"/>
- <dependency name="VCSBase" version="2.0.95"/>
- </dependencyList>
-</plugin>
diff --git a/src/plugins/cvs/CVS.pluginspec.in b/src/plugins/cvs/CVS.pluginspec.in
new file mode 100644
index 0000000000..d2b35efbeb
--- /dev/null
+++ b/src/plugins/cvs/CVS.pluginspec.in
@@ -0,0 +1,22 @@
+<plugin name=\"CVS\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2010 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>
+ <category>Version Control</category>
+ <description>CVS integration.</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name=\"TextEditor\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"ProjectExplorer\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"VCSBase\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/cvs/cvs.pro b/src/plugins/cvs/cvs.pro
index c4f6478e93..0f042def66 100644
--- a/src/plugins/cvs/cvs.pro
+++ b/src/plugins/cvs/cvs.pro
@@ -34,5 +34,3 @@ SOURCES += annotationhighlighter.cpp \
FORMS += settingspage.ui
RESOURCES += cvs.qrc
-
-OTHER_FILES += CVS.pluginspec
diff --git a/src/plugins/cvs/cvsplugin.cpp b/src/plugins/cvs/cvsplugin.cpp
index cc4b293818..735f2fdcd5 100644
--- a/src/plugins/cvs/cvsplugin.cpp
+++ b/src/plugins/cvs/cvsplugin.cpp
@@ -55,6 +55,7 @@
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/command.h>
+#include <coreplugin/uniqueidmanager.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/vcsmanager.h>
#include <utils/stringutils.h>
diff --git a/src/plugins/cvs/settingspage.cpp b/src/plugins/cvs/settingspage.cpp
index fa637ef603..36c2f9475a 100644
--- a/src/plugins/cvs/settingspage.cpp
+++ b/src/plugins/cvs/settingspage.cpp
@@ -80,10 +80,17 @@ void SettingsPageWidget::setSettings(const CVSSettings &s)
QString SettingsPageWidget::searchKeywords() const
{
QString rc;
- QTextStream(&rc) << m_ui.promptToSubmitCheckBox->text()
- << ' ' << m_ui.describeByCommitIdCheckBox->text()
- << ' ' << m_ui.commandLabel->text()
- << ' ' << m_ui.rootLabel->text() << ' ' << m_ui.diffOptionsLabel->text();
+ QLatin1Char sep(' ');
+ QTextStream(&rc)
+ << sep << m_ui.configGroupBox->title()
+ << sep << m_ui.commandLabel->text()
+ << sep << m_ui.rootLabel->text()
+ << sep << m_ui.miscGroupBox->title()
+ << sep << m_ui.timeOutLabel->text()
+ << sep << m_ui.diffOptionsLabel->text()
+ << sep << m_ui.promptToSubmitCheckBox->text()
+ << sep << m_ui.describeByCommitIdCheckBox->text()
+ ;
rc.remove(QLatin1Char('&'));
return rc;
}
diff --git a/src/plugins/cvs/settingspage.ui b/src/plugins/cvs/settingspage.ui
index 4f1ebfd394..c065830b89 100644
--- a/src/plugins/cvs/settingspage.ui
+++ b/src/plugins/cvs/settingspage.ui
@@ -12,7 +12,7 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
- <widget class="QGroupBox" name="miscGroupBox">
+ <widget class="QGroupBox" name="configGroupBox">
<property name="title">
<string>Configuration</string>
</property>
@@ -25,7 +25,7 @@
</widget>
</item>
<item row="0" column="1">
- <widget class="Utils::PathChooser" name="commandPathChooser"/>
+ <widget class="Utils::PathChooser" name="commandPathChooser" native="true"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="rootLabel">
@@ -41,7 +41,7 @@
</widget>
</item>
<item>
- <widget class="QGroupBox" name="miscGroupBox_2">
+ <widget class="QGroupBox" name="miscGroupBox">
<property name="title">
<string>Miscellaneous</string>
</property>
diff --git a/src/plugins/debugger/Debugger.pluginspec b/src/plugins/debugger/Debugger.pluginspec
deleted file mode 100644
index 1beffa3693..0000000000
--- a/src/plugins/debugger/Debugger.pluginspec
+++ /dev/null
@@ -1,30 +0,0 @@
-<plugin name="Debugger" version="2.0.95" compatVersion="2.0.95">
- <vendor>Nokia Corporation</vendor>
- <copyright>(C) 2010 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>
- <category>Qt Creator</category>
- <description>Debugger integration.</description>
- <url>http://qt.nokia.com</url>
- <dependencyList>
- <dependency name="CppEditor" version="2.0.95"/><!-- Debugger plugin adds items to the editor's context menu -->
- <dependency name="ProjectExplorer" version="2.0.95"/>
- <dependency name="Core" version="2.0.95"/>
- <dependency name="Find" version="2.0.95"/>
- </dependencyList>
- <argumentList>
- <argument name="-disable-cdb">Disable Cdb debugger engine</argument>
- <argument name="-disable-gdb">Disable Gdb debugger engine</argument>
- <argument name="-disable-sdb">Disable Qt Script debugger engine</argument>
- <argument name="-disable-tcf">Disable Tcf debugger engine</argument>
- <argument name="-debug" parameter="pid-or-corefile">Attach to Process-Id or Core file</argument>
- <argument name="-wincrashevent" parameter="event-handle">Event handle used for attaching to crashed processes</argument>
- </argumentList>
-</plugin>
diff --git a/src/plugins/debugger/Debugger.pluginspec.in b/src/plugins/debugger/Debugger.pluginspec.in
new file mode 100644
index 0000000000..565da29a39
--- /dev/null
+++ b/src/plugins/debugger/Debugger.pluginspec.in
@@ -0,0 +1,30 @@
+<plugin name=\"Debugger\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2010 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>
+ <category>Qt Creator</category>
+ <description>Debugger integration.</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name=\"CppEditor\" version=\"$$QTCREATOR_VERSION\"/><!-- Debugger plugin adds items to the editor's context menu -->
+ <dependency name=\"ProjectExplorer\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"Find\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+ <argumentList>
+ <argument name=\"-disable-cdb\">Disable Cdb debugger engine</argument>
+ <argument name=\"-disable-gdb\">Disable Gdb debugger engine</argument>
+ <argument name=\"-disable-sdb\">Disable Qt Script debugger engine</argument>
+ <argument name=\"-disable-tcf\">Disable Tcf debugger engine</argument>
+ <argument name=\"-debug\" parameter=\"pid-or-corefile\">Attach to Process-Id or Core file</argument>
+ <argument name=\"-wincrashevent\" parameter=\"event-handle\">Event handle used for attaching to crashed processes</argument>
+ </argumentList>
+</plugin>
diff --git a/src/plugins/debugger/breakhandler.cpp b/src/plugins/debugger/breakhandler.cpp
index f5e579df9f..7c784be8f0 100644
--- a/src/plugins/debugger/breakhandler.cpp
+++ b/src/plugins/debugger/breakhandler.cpp
@@ -32,55 +32,73 @@
**************************************************************************/
#include "breakhandler.h"
+#include "breakpointmarker.h"
#include "debuggeractions.h"
+#include "debuggercore.h"
#include "debuggerengine.h"
-#include "debuggerplugin.h"
#include "debuggerstringutils.h"
-#include "threadshandler.h"
-#include "stackhandler.h"
#include "stackframe.h"
-#include <texteditor/basetextmark.h>
#include <utils/qtcassert.h>
#include <QtCore/QDir>
-#include <QtCore/QByteArray>
#include <QtCore/QFileInfo>
+#include <QtCore/QTimerEvent>
+//////////////////////////////////////////////////////////////////
+//
+// BreakHandler
+//
+//////////////////////////////////////////////////////////////////
+
namespace Debugger {
namespace Internal {
-static DebuggerPlugin *plugin() { return DebuggerPlugin::instance(); }
+BreakHandler::BreakHandler()
+ : m_syncTimerId(-1)
+{}
+BreakHandler::~BreakHandler()
+{}
-static Breakpoints m_bp;
+QIcon BreakHandler::breakpointIcon()
+{
+ static QIcon icon(_(":/debugger/images/breakpoint_16.png"));
+ return icon;
+}
-//////////////////////////////////////////////////////////////////
-//
-// BreakHandler
-//
-//////////////////////////////////////////////////////////////////
+QIcon BreakHandler::disabledBreakpointIcon()
+{
+ static QIcon icon(_(":/debugger/images/breakpoint_disabled_16.png"));
+ return icon;
+}
-BreakHandler::BreakHandler(Debugger::DebuggerEngine *engine)
- : m_breakpointIcon(_(":/debugger/images/breakpoint_16.png")),
- m_disabledBreakpointIcon(_(":/debugger/images/breakpoint_disabled_16.png")),
- m_pendingBreakPointIcon(_(":/debugger/images/breakpoint_pending_16.png")),
- //m_emptyIcon(_(":/debugger/images/watchpoint.png")),
- m_emptyIcon(_(":/debugger/images/breakpoint_pending_16.png")),
- //m_emptyIcon(_(":/debugger/images/debugger_empty_14.png")),
- m_watchpointIcon(_(":/debugger/images/watchpoint.png")),
- m_engine(engine),
- m_lastFound(0),
- m_lastFoundQueried(false)
+QIcon BreakHandler::pendingBreakpointIcon()
{
- QTC_ASSERT(m_engine, /**/);
+ static QIcon icon(_(":/debugger/images/breakpoint_pending_16.png"));
+ return icon;
}
-BreakHandler::~BreakHandler()
+QIcon BreakHandler::watchpointIcon()
{
- clear();
+ static QIcon icon(_(":/debugger/images/watchpoint.png"));
+ return icon;
+}
+
+QIcon BreakHandler::tracepointIcon()
+{
+ static QIcon icon(_(":/debugger/images/tracepoint.png"));
+ return icon;
+}
+
+QIcon BreakHandler::emptyIcon()
+{
+ static QIcon icon(_(":/debugger/images/breakpoint_pending_16.png"));
+ //static QIcon icon(_(":/debugger/images/watchpoint.png"));
+ //static QIcon icon(_(":/debugger/images/debugger_empty_14.png"));
+ return icon;
}
int BreakHandler::columnCount(const QModelIndex &parent) const
@@ -90,164 +108,245 @@ int BreakHandler::columnCount(const QModelIndex &parent) const
int BreakHandler::rowCount(const QModelIndex &parent) const
{
- return parent.isValid() ? 0 : size();
+ return parent.isValid() ? 0 : m_storage.size();
+}
+
+static inline bool fileNameMatch(const QString &f1, const QString &f2)
+{
+#ifdef Q_OS_WIN
+ return f1.compare(f2, Qt::CaseInsensitive) == 0;
+#else
+ return f1 == f2;
+#endif
}
-bool BreakHandler::hasPendingBreakpoints() const
+static bool isSimilarTo(const BreakpointParameters &data, const BreakpointResponse &needle)
{
- for (int i = size() - 1; i >= 0; i--)
- if (at(i)->pending)
- return true;
+ // Clear hit.
+ // Clear miss.
+ if (needle.type != UnknownType && data.type != UnknownType
+ && data.type != needle.type)
+ return false;
+
+ // Clear hit.
+ if (data.address && data.address == needle.address)
+ return true;
+
+ // At least at a position we were looking for.
+ // FIXME: breaks multiple breakpoints at the same location
+ if (!data.fileName.isEmpty()
+ && fileNameMatch(data.fileName, needle.fileName)
+ && data.lineNumber == needle.lineNumber)
+ return true;
+
+ // At least at a position we were looking for.
+ // FIXME: breaks multiple breakpoints at the same location
+ if (!data.fileName.isEmpty()
+ && fileNameMatch(data.fileName, needle.fileName)
+ && data.lineNumber == needle.lineNumber)
+ return true;
+
return false;
}
-BreakpointData *BreakHandler::at(int index) const
+BreakpointId BreakHandler::findSimilarBreakpoint(const BreakpointResponse &needle) const
{
- QTC_ASSERT(index < size(), return 0);
- return m_bp.at(index);
+ // Search a breakpoint we might refer to.
+ ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
+ for ( ; it != et; ++it) {
+ const BreakpointId id = it.key();
+ const BreakpointParameters &data = it->data;
+ const BreakpointResponse &response = it->response;
+ //qDebug() << "COMPARING " << data.toString() << " WITH " << needle.toString();
+ if (response.number && response.number == needle.number)
+ return id;
+
+ if (isSimilarTo(data, needle))
+ return id;
+ }
+ return BreakpointId();
}
-void BreakHandler::removeAt(int index)
+BreakpointId BreakHandler::findBreakpointByNumber(int bpNumber) const
{
- BreakpointData *data = at(index);
- QTC_ASSERT(data, return);
- m_bp.removeAt(index);
- delete data;
+ ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
+ for ( ; it != et; ++it)
+ if (it->response.number == bpNumber)
+ return it.key();
+ return BreakpointId();
}
-void BreakHandler::clear()
+BreakpointId BreakHandler::findBreakpointByFunction(const QString &functionName) const
{
- m_enabled.clear();
- m_disabled.clear();
- m_removed.clear();
+ ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
+ for ( ; it != et; ++it)
+ if (it->data.functionName == functionName)
+ return it.key();
+ return BreakpointId();
}
-BreakpointData *BreakHandler::findSimilarBreakpoint(const BreakpointData *needle) const
+BreakpointId BreakHandler::findBreakpointByAddress(quint64 address) const
{
- // Search a breakpoint we might refer to.
- for (int index = 0; index != size(); ++index) {
- BreakpointData *data = m_bp[index];
- if (data->isSimilarTo(needle))
- return data;
- }
- return 0;
+ ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
+ for ( ; it != et; ++it)
+ if (it->data.address == address)
+ return it.key();
+ return BreakpointId();
}
-BreakpointData *BreakHandler::findBreakpointByNumber(int bpNumber) const
+BreakpointId BreakHandler::findBreakpointByFileAndLine(const QString &fileName,
+ int lineNumber, bool useMarkerPosition)
{
- if (!size())
- return 0;
- QString numStr = QString::number(bpNumber);
- for (int index = 0; index != size(); ++index)
- if (at(index)->bpNumber == numStr)
- return at(index);
- return 0;
+ ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
+ for ( ; it != et; ++it)
+ if (it->isLocatedAt(fileName, lineNumber, useMarkerPosition))
+ return it.key();
+ return BreakpointId();
}
-int BreakHandler::findWatchPointIndexByAddress(quint64 address) const
+const BreakpointParameters &BreakHandler::breakpointData(BreakpointId id) const
{
- for (int index = size() - 1; index >= 0; --index) {
- BreakpointData *bd = at(index);
- if (bd->type == BreakpointData::WatchpointType && bd->address == address)
- return index;
+ static BreakpointParameters dummy;
+ ConstIterator it = m_storage.find(id);
+ QTC_ASSERT(it != m_storage.end(), return dummy);
+ return it->data;
+}
+
+BreakpointId BreakHandler::findWatchpointByAddress(quint64 address) const
+{
+ ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
+ for ( ; it != et; ++it)
+ if (it->data.isWatchpoint() && it->data.address == address)
+ return it.key();
+ return BreakpointId();
+}
+
+void BreakHandler::setWatchpointByAddress(quint64 address)
+{
+ const int id = findWatchpointByAddress(address);
+ if (id) {
+ qDebug() << "WATCHPOINT EXISTS";
+ // removeBreakpoint(index);
+ return;
}
- return -1;
+ BreakpointParameters data(Watchpoint);
+ data.address = address;
+ appendBreakpoint(data);
}
-bool BreakHandler::watchPointAt(quint64 address) const
+bool BreakHandler::hasWatchpointAt(quint64 address) const
{
- return findWatchPointIndexByAddress(address) != -1;
+ return findWatchpointByAddress(address);
}
void BreakHandler::saveBreakpoints()
{
//qDebug() << "SAVING BREAKPOINTS...";
- QTC_ASSERT(plugin(), return);
+ QTC_ASSERT(debuggerCore(), return);
QList<QVariant> list;
- for (int index = 0; index != size(); ++index) {
- const BreakpointData *data = at(index);
+ ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
+ for ( ; it != et; ++it) {
+ const BreakpointParameters &data = it->data;
QMap<QString, QVariant> map;
// Do not persist Watchpoints.
- //if (data->type == BreakpointData::WatchpointType)
- // continue;
- if (data->type != BreakpointData::BreakpointType)
- map.insert(_("type"), data->type);
- if (!data->fileName.isEmpty())
- map.insert(_("filename"), data->fileName);
- if (data->lineNumber)
- map.insert(_("linenumber"), QVariant(data->lineNumber));
- if (!data->funcName.isEmpty())
- map.insert(_("funcname"), data->funcName);
- if (data->address)
- map.insert(_("address"), data->address);
- if (!data->condition.isEmpty())
- map.insert(_("condition"), data->condition);
- if (data->ignoreCount)
- map.insert(_("ignorecount"), QVariant(data->ignoreCount));
- if (!data->threadSpec.isEmpty())
- map.insert(_("threadspec"), data->threadSpec);
- if (!data->enabled)
+ if (data.isWatchpoint())
+ continue;
+ if (data.type != BreakpointByFileAndLine)
+ map.insert(_("type"), data.type);
+ if (!data.fileName.isEmpty())
+ map.insert(_("filename"), data.fileName);
+ if (data.lineNumber)
+ map.insert(_("linenumber"), data.lineNumber);
+ if (!data.functionName.isEmpty())
+ map.insert(_("funcname"), data.functionName);
+ if (data.address)
+ map.insert(_("address"), data.address);
+ if (!data.condition.isEmpty())
+ map.insert(_("condition"), data.condition);
+ if (data.ignoreCount)
+ map.insert(_("ignorecount"), data.ignoreCount);
+ if (data.threadSpec)
+ map.insert(_("threadspec"), data.threadSpec);
+ if (!data.enabled)
map.insert(_("disabled"), _("1"));
- if (data->useFullPath)
+ if (data.useFullPath)
map.insert(_("usefullpath"), _("1"));
+ if (data.tracepoint)
+ map.insert(_("tracepoint"), _("1"));
list.append(map);
}
- plugin()->setSessionValue("Breakpoints", list);
+ debuggerCore()->setSessionValue("Breakpoints", list);
//qDebug() << "SAVED BREAKPOINTS" << this << list.size();
}
void BreakHandler::loadBreakpoints()
{
- QTC_ASSERT(plugin(), return);
+ QTC_ASSERT(debuggerCore(), return);
//qDebug() << "LOADING BREAKPOINTS...";
- QVariant value = plugin()->sessionValue("Breakpoints");
+ QVariant value = debuggerCore()->sessionValue("Breakpoints");
QList<QVariant> list = value.toList();
- clear();
+ //clear();
foreach (const QVariant &var, list) {
const QMap<QString, QVariant> map = var.toMap();
- BreakpointData *data = new BreakpointData;
+ BreakpointParameters data(BreakpointByFileAndLine);
QVariant v = map.value(_("filename"));
if (v.isValid())
- data->fileName = v.toString();
+ data.fileName = v.toString();
v = map.value(_("linenumber"));
if (v.isValid())
- data->lineNumber = v.toString().toInt();
+ data.lineNumber = v.toString().toInt();
v = map.value(_("condition"));
if (v.isValid())
- data->condition = v.toString().toLatin1();
+ data.condition = v.toString().toLatin1();
v = map.value(_("address"));
if (v.isValid())
- data->address = v.toString().toULongLong();
+ data.address = v.toString().toULongLong();
v = map.value(_("ignorecount"));
if (v.isValid())
- data->ignoreCount = v.toString().toInt();
+ data.ignoreCount = v.toString().toInt();
v = map.value(_("threadspec"));
if (v.isValid())
- data->threadSpec = v.toString().toLatin1();
+ data.threadSpec = v.toString().toInt();
v = map.value(_("funcname"));
if (v.isValid())
- data->funcName = v.toString();
+ data.functionName = v.toString();
v = map.value(_("disabled"));
if (v.isValid())
- data->enabled = !v.toInt();
+ data.enabled = !v.toInt();
v = map.value(_("usefullpath"));
if (v.isValid())
- data->useFullPath = bool(v.toInt());
- v = map.value(_("type"));
+ data.useFullPath = bool(v.toInt());
+ v = map.value(_("tracepoint"));
if (v.isValid())
- data->type = BreakpointData::Type(v.toInt());
- data->setMarkerFileName(data->fileName);
- data->setMarkerLineNumber(data->lineNumber);
- append(data);
+ data.tracepoint = bool(v.toInt());
+ v = map.value(_("type"));
+ if (v.isValid() && v.toInt() != UnknownType)
+ data.type = BreakpointType(v.toInt());
+ appendBreakpoint(data);
}
//qDebug() << "LOADED BREAKPOINTS" << this << list.size();
}
void BreakHandler::updateMarkers()
{
- for (int index = 0; index != size(); ++index)
- at(index)->updateMarker();
- emit layoutChanged();
+ ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
+ for ( ; it != et; ++it)
+ updateMarker(it.key());
+}
+
+void BreakHandler::updateMarker(BreakpointId id)
+{
+ Iterator it = m_storage.find(id);
+ QTC_ASSERT(it != m_storage.end(), return);
+
+ QString markerFileName = it->markerFileName();
+ int markerLineNumber = it->markerLineNumber();
+ if (it->marker && (markerFileName != it->marker->fileName()
+ || markerLineNumber != it->marker->lineNumber()))
+ it->destroyMarker();
+
+ if (!it->marker && !markerFileName.isEmpty() && markerLineNumber > 0)
+ it->marker = new BreakpointMarker(id, markerFileName, markerLineNumber);
}
QVariant BreakHandler::headerData(int section,
@@ -256,473 +355,854 @@ QVariant BreakHandler::headerData(int section,
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
static QString headers[] = {
tr("Number"), tr("Function"), tr("File"), tr("Line"),
- tr("Condition"), tr("Ignore"), tr("Threads"), tr("Address")
+ tr("Address"), tr("Condition"), tr("Ignore"), tr("Threads")
};
return headers[section];
}
return QVariant();
}
-QVariant BreakHandler::data(const QModelIndex &mi, int role) const
+BreakpointId BreakHandler::findBreakpointByIndex(const QModelIndex &index) const
{
- static const QString empty = QString(QLatin1Char('-'));
-
- switch (role) {
- case CurrentThreadIdRole:
- QTC_ASSERT(m_engine, return QVariant());
- return m_engine->threadsHandler()->currentThreadId();
-
- case EngineActionsEnabledRole:
- QTC_ASSERT(m_engine, return QVariant());
- return m_engine->debuggerActionsEnabled();
-
- case EngineCapabilitiesRole:
- QTC_ASSERT(m_engine, return QVariant());
- return m_engine->debuggerCapabilities();
-
- default:
- break;
- }
-
- QTC_ASSERT(mi.isValid(), return QVariant());
- if (mi.row() >= size())
- return QVariant();
-
- BreakpointData *data = at(mi.row());
-
- if (role == BreakpointRole)
- return qVariantFromValue(data);
+ int r = index.row();
+ ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
+ for (int i = 0; it != et; ++it, ++i)
+ if (i == r)
+ return it.key();
+ return BreakpointId();
+}
- if (role == BreakpointUseFullPathRole)
- return data->useFullPath;
+BreakpointIds BreakHandler::findBreakpointsByIndex(const QList<QModelIndex> &list) const
+{
+ QSet<BreakpointId> ids;
+ foreach (const QModelIndex &index, list)
+ ids.insert(findBreakpointByIndex(index));
+ return ids.toList();
+}
- if (role == BreakpointFileNameRole)
- return data->fileName;
+Qt::ItemFlags BreakHandler::flags(const QModelIndex &index) const
+{
+// switch (index.column()) {
+// //case 0:
+// // return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled;
+// default:
+ return QAbstractTableModel::flags(index);
+// }
+}
- if (role == BreakpointEnabledRole)
- return data->enabled;
+QString BreakHandler::displayFromThreadSpec(int spec)
+{
+ return spec == -1 ? BreakHandler::tr("(all)") : QString::number(spec);
+}
- if (role == BreakpointFunctionNameRole)
- return data->funcName;
+int BreakHandler::threadSpecFromDisplay(const QString &str)
+{
+ bool ok = false;
+ int result = str.toInt(&ok);
+ return ok ? result : -1;
+}
- if (role == BreakpointConditionRole)
- return data->condition;
+QVariant BreakHandler::data(const QModelIndex &mi, int role) const
+{
+ static const QString empty = QString(QLatin1Char('-'));
- if (role == BreakpointIgnoreCountRole)
- return data->ignoreCount ? QVariant(data->ignoreCount) : QVariant(QString());
+ if (!mi.isValid())
+ return QVariant();
- if (role == BreakpointThreadSpecRole)
- return data->threadSpec;
+ BreakpointId id = findBreakpointByIndex(mi);
+ //qDebug() << "DATA: " << id << role << mi.column();
+ ConstIterator it = m_storage.find(id);
+ QTC_ASSERT(it != m_storage.end(), return QVariant());
+ const BreakpointParameters &data = it->data;
+ const BreakpointResponse &response = it->response;
+
+ bool orig = false;
+ switch (it->state) {
+ case BreakpointInsertRequested:
+ case BreakpointInsertProceeding:
+ case BreakpointChangeRequested:
+ case BreakpointChangeProceeding:
+ case BreakpointInserted:
+ case BreakpointRemoveRequested:
+ case BreakpointRemoveProceeding:
+ break;
+ case BreakpointNew:
+ case BreakpointDead:
+ orig = true;
+ break;
+ };
switch (mi.column()) {
case 0:
if (role == Qt::DisplayRole) {
- const QString str = data->bpNumber;
- return str.isEmpty() ? empty : str;
- }
- if (role == Qt::DecorationRole) {
- if (data->type == BreakpointData::WatchpointType)
- return m_watchpointIcon;
- if (!data->enabled)
- return m_disabledBreakpointIcon;
- return data->pending ? m_pendingBreakPointIcon : m_breakpointIcon;
+ return QString::number(id);
+ //return QString("%1 - %2").arg(id).arg(response.number);
}
+ if (role == Qt::DecorationRole)
+ return it->icon();
break;
case 1:
if (role == Qt::DisplayRole) {
- const QString str = data->pending ? data->funcName : data->bpFuncName;
- return str.isEmpty() ? empty : str;
+ if (!response.functionName.isEmpty())
+ return response.functionName;
+ if (!data.functionName.isEmpty())
+ return data.functionName;
+ return empty;
}
break;
case 2:
if (role == Qt::DisplayRole) {
- QString str = data->pending ? data->fileName : data->bpFileName;
- str = QFileInfo(str).fileName();
+ QString str;
+ if (!response.fileName.isEmpty())
+ str = response.fileName;
+ if (str.isEmpty() && !data.fileName.isEmpty())
+ str = data.fileName;
+ if (str.isEmpty()) {
+ QString s = QFileInfo(str).fileName();
+ if (!s.isEmpty())
+ str = s;
+ }
// FIXME: better?
- //if (data->bpMultiple && str.isEmpty() && !data->markerFileName.isEmpty())
- // str = data->markerFileName;
- str = str.isEmpty() ? empty : str;
- if (data->useFullPath)
- str = QDir::toNativeSeparators(QLatin1String("/.../") + str);
- return str;
+ //if (data.multiple && str.isEmpty() && !response.fileName.isEmpty())
+ // str = response.fileName;
+ if (!str.isEmpty())
+ return QDir::toNativeSeparators(str);
+ return empty;
}
break;
case 3:
if (role == Qt::DisplayRole) {
- // FIXME: better?
- //if (data->bpMultiple && str.isEmpty() && !data->markerFileName.isEmpty())
- // str = data->markerLineNumber;
- const int nr = data->pending ? data->lineNumber : data->bpLineNumber;
- return nr ? QString::number(nr) : empty;
+ if (response.lineNumber > 0)
+ return response.lineNumber;
+ if (data.lineNumber > 0)
+ return data.lineNumber;
+ return empty;
}
if (role == Qt::UserRole + 1)
- return data->lineNumber;
+ return data.lineNumber;
break;
case 4:
+ if (role == Qt::DisplayRole) {
+ QString displayValue;
+ const quint64 address = orig ? data.address : response.address;
+ if (address)
+ displayValue += QString::fromAscii("0x%1").arg(address, 0, 16);
+ if (!response.extra.isEmpty()) {
+ if (!displayValue.isEmpty())
+ displayValue += QLatin1Char(' ');
+ displayValue += QString::fromAscii(response.extra);
+ }
+ return displayValue;
+ }
+ break;
+ case 5:
if (role == Qt::DisplayRole)
- return data->pending ? data->condition : data->bpCondition;
+ return orig ? data.condition : response.condition;
if (role == Qt::ToolTipRole)
return tr("Breakpoint will only be hit if this condition is met.");
if (role == Qt::UserRole + 1)
- return data->condition;
+ return data.condition;
break;
- case 5:
+ case 6:
if (role == Qt::DisplayRole) {
- const int ignoreCount = data->pending ? data->ignoreCount : data->bpIgnoreCount;
+ const int ignoreCount =
+ orig ? data.ignoreCount : response.ignoreCount;
return ignoreCount ? QVariant(ignoreCount) : QVariant(QString());
}
if (role == Qt::ToolTipRole)
return tr("Breakpoint will only be hit after being ignored so many times.");
if (role == Qt::UserRole + 1)
- return data->ignoreCount;
+ return data.ignoreCount;
break;
- case 6:
- if (role == Qt::DisplayRole) {
- if (data->pending)
- return !data->threadSpec.isEmpty() ? data->threadSpec : tr("(all)");
- else
- return !data->bpThreadSpec.isEmpty() ? data->bpThreadSpec : tr("(all)");
- }
+ case 7:
+ if (role == Qt::DisplayRole)
+ return displayFromThreadSpec(orig ? data.threadSpec : response.threadSpec);
if (role == Qt::ToolTipRole)
return tr("Breakpoint will only be hit in the specified thread(s).");
if (role == Qt::UserRole + 1)
- return data->threadSpec;
- break;
- case 7:
- if (role == Qt::DisplayRole) {
- QString displayValue;
- const quint64 effectiveAddress = data->type == BreakpointData::WatchpointType ?
- data->address : data->bpAddress;
- if (effectiveAddress)
- displayValue += QString::fromAscii("0x%1").arg(effectiveAddress, 0, 16);
- if (!data->bpState.isEmpty()) {
- if (!displayValue.isEmpty())
- displayValue += QLatin1Char(' ');
- displayValue += QString::fromAscii(data->bpState);
- }
- return displayValue;
- }
+ return displayFromThreadSpec(data.threadSpec);
break;
}
if (role == Qt::ToolTipRole)
- return theDebuggerBoolSetting(UseToolTipsInBreakpointsView)
- ? data->toToolTip() : QVariant();
+ return debuggerCore()->boolSetting(UseToolTipsInBreakpointsView)
+ ? QVariant(it->toToolTip()) : QVariant();
+
return QVariant();
}
-Qt::ItemFlags BreakHandler::flags(const QModelIndex &index) const
+#define GETTER(type, getter) \
+type BreakHandler::getter(BreakpointId id) const \
+{ \
+ ConstIterator it = m_storage.find(id); \
+ QTC_ASSERT(it != m_storage.end(), \
+ qDebug() << "ID" << id << "NOT KNOWN"; \
+ return type()); \
+ return it->data.getter; \
+}
+
+#define SETTER(type, getter, setter) \
+void BreakHandler::setter(BreakpointId id, const type &value) \
+{ \
+ Iterator it = m_storage.find(id); \
+ QTC_ASSERT(it != m_storage.end(), \
+ qDebug() << "ID" << id << "NOT KNOWN"; return); \
+ if (it->data.getter == value) \
+ return; \
+ it->data.getter = value; \
+ if (it->state != BreakpointNew) { \
+ it->state = BreakpointChangeRequested; \
+ scheduleSynchronization(); \
+ } \
+}
+
+#define PROPERTY(type, getter, setter) \
+ GETTER(type, getter) \
+ SETTER(type, getter, setter)
+
+
+PROPERTY(bool, useFullPath, setUseFullPath)
+PROPERTY(QString, fileName, setFileName)
+PROPERTY(QString, functionName, setFunctionName)
+PROPERTY(BreakpointType, type, setType)
+PROPERTY(int, threadSpec, setThreadSpec)
+PROPERTY(QByteArray, condition, setCondition)
+GETTER(int, lineNumber)
+PROPERTY(quint64, address, setAddress)
+PROPERTY(int, ignoreCount, setIgnoreCount)
+
+bool BreakHandler::isEnabled(BreakpointId id) const
{
-// switch (index.column()) {
-// //case 0:
-// // return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled;
-// default:
- return QAbstractTableModel::flags(index);
-// }
+ ConstIterator it = m_storage.find(id);
+ QTC_ASSERT(it != m_storage.end(), return false);
+ return it->data.enabled;
}
-bool BreakHandler::setData(const QModelIndex &index, const QVariant &value, int role)
-{
- switch (role) {
- case RequestActivateBreakpointRole: {
- const BreakpointData *data = at(value.toInt());
- QTC_ASSERT(data, return false);
- m_engine->gotoLocation(data->markerFileName(),
- data->markerLineNumber(), false);
- return true;
- }
-
- case RequestRemoveBreakpointByIndexRole: {
- BreakpointData *data = at(value.toInt());
- QTC_ASSERT(data, return false);
- removeBreakpoint(data);
- return true;
- }
-
- case RequestSynchronizeBreakpointsRole:
- QTC_ASSERT(m_engine, return false);
- m_engine->attemptBreakpointSynchronization();
- return true;
-
- case RequestBreakByFunctionRole:
- QTC_ASSERT(m_engine, return false);
- m_engine->breakByFunction(value.toString());
- return true;
-
- case RequestBreakByFunctionMainRole:
- QTC_ASSERT(m_engine, return false);
- m_engine->breakByFunctionMain();
- return true;
-
- case RequestBreakpointRole:
- QTC_ASSERT(m_engine, return false);
- BreakpointData *data = value.value<BreakpointData *>();
- if (data->funcName == "main") {
- m_engine->breakByFunctionMain();
- } else {
- appendBreakpoint(data);
- m_engine->attemptBreakpointSynchronization();
- }
- return true;
- }
+void BreakHandler::setEnabled(BreakpointId id, bool on)
+{
+ Iterator it = m_storage.find(id);
+ QTC_ASSERT(it != m_storage.end(), return);
+ //qDebug() << "SET ENABLED: " << id << it->data.isEnabled() << on;
+ if (it->data.enabled == on)
+ return;
+ it->data.enabled = on;
+ it->destroyMarker();
+ it->state = BreakpointChangeRequested;
+ updateMarker(id);
+ scheduleSynchronization();
+}
- BreakpointData *data = at(index.row());
+bool BreakHandler::isTracepoint(BreakpointId id) const
+{
+ ConstIterator it = m_storage.find(id);
+ QTC_ASSERT(it != m_storage.end(), return false);
+ return it->data.tracepoint;
+}
- switch (role) {
- case BreakpointEnabledRole:
- if (data->enabled != value.toBool())
- toggleBreakpointEnabled(data);
- return true;
+void BreakHandler::setTracepoint(BreakpointId id, bool on)
+{
+ Iterator it = m_storage.find(id);
+ QTC_ASSERT(it != m_storage.end(), return);
+ if (it->data.tracepoint == on)
+ return;
+ it->data.tracepoint = on;
+ it->destroyMarker();
+ it->state = BreakpointChangeRequested;
+ updateMarker(id);
+ scheduleSynchronization();
+}
- case BreakpointUseFullPathRole:
- if (data->useFullPath != value.toBool()) {
- data->useFullPath = value.toBool();
- emit layoutChanged();
- }
- return true;
+void BreakHandler::setMarkerFileAndLine(BreakpointId id,
+ const QString &fileName, int lineNumber)
+{
+ Iterator it = m_storage.find(id);
+ QTC_ASSERT(it != m_storage.end(), return);
+ if (it->response.fileName == fileName && it->response.lineNumber == lineNumber)
+ return;
+ it->response.fileName = fileName;
+ it->response.lineNumber = lineNumber;
+ it->destroyMarker();
+ updateMarker(id);
+ emit layoutChanged();
+}
- case BreakpointConditionRole: {
- QByteArray val = value.toString().toLatin1();
- if (val != data->condition) {
- data->condition = val;
- emit layoutChanged();
- }
- }
- return true;
+BreakpointState BreakHandler::state(BreakpointId id) const
+{
+ ConstIterator it = m_storage.find(id);
+ QTC_ASSERT(it != m_storage.end(), return BreakpointDead);
+ return it->state;
+}
- case BreakpointIgnoreCountRole: {
- const int ignoreCount = value.toInt();
- if (ignoreCount != data->ignoreCount) {
- data->ignoreCount = ignoreCount;
- emit layoutChanged();
- }
- }
- return true;
+DebuggerEngine *BreakHandler::engine(BreakpointId id) const
+{
+ ConstIterator it = m_storage.find(id);
+ QTC_ASSERT(it != m_storage.end(), return 0);
+ return it->engine;
+}
- case BreakpointThreadSpecRole: {
- QByteArray val = value.toString().toLatin1();
- if (val != data->threadSpec) {
- data->threadSpec = val;
- emit layoutChanged();
- }
- }
- return true;
+void BreakHandler::setEngine(BreakpointId id, DebuggerEngine *value)
+{
+ Iterator it = m_storage.find(id);
+ QTC_ASSERT(it != m_storage.end(), return);
+ QTC_ASSERT(it->state == BreakpointNew, /**/);
+ QTC_ASSERT(!it->engine, return);
+ it->engine = value;
+ it->state = BreakpointInsertRequested;
+ it->response = BreakpointResponse();
+ it->response.fileName = it->data.fileName;
+ updateMarker(id);
+ scheduleSynchronization();
+}
+
+static bool isAllowedTransition(BreakpointState from, BreakpointState to)
+{
+ switch (from) {
+ case BreakpointNew:
+ return to == BreakpointInsertRequested;
+ case BreakpointInsertRequested:
+ return to == BreakpointInsertProceeding;
+ case BreakpointInsertProceeding:
+ return to == BreakpointInserted
+ || to == BreakpointDead
+ || to == BreakpointChangeRequested;
+ case BreakpointChangeRequested:
+ return to == BreakpointChangeProceeding;
+ case BreakpointChangeProceeding:
+ return to == BreakpointInserted
+ || to == BreakpointDead;
+ case BreakpointInserted:
+ return to == BreakpointChangeRequested
+ || to == BreakpointRemoveRequested;
+ case BreakpointRemoveRequested:
+ return to == BreakpointRemoveProceeding;
+ case BreakpointRemoveProceeding:
+ return to == BreakpointDead;
+ case BreakpointDead:
+ return false;
}
+ qDebug() << "UNKNOWN BREAKPOINT STATE:" << from;
return false;
}
-void BreakHandler::reinsertBreakpoint(BreakpointData *data)
+void BreakHandler::setState(BreakpointId id, BreakpointState state)
{
- // FIXME: Use some more direct method?
- appendBreakpoint(data->clone());
- removeBreakpoint(data);
- m_engine->attemptBreakpointSynchronization();
- emit layoutChanged();
+ Iterator it = m_storage.find(id);
+ //qDebug() << "BREAKPOINT STATE TRANSITION" << id << it->state << state;
+ QTC_ASSERT(it != m_storage.end(), return);
+ QTC_ASSERT(isAllowedTransition(it->state, state),
+ qDebug() << "UNEXPECTED BREAKPOINT STATE TRANSITION"
+ << it->state << state);
+
+ if (it->state == state) {
+ qDebug() << "STATE UNCHANGED: " << id << state;
+ return;
+ }
+
+ it->state = state;
}
-void BreakHandler::append(BreakpointData *data)
+void BreakHandler::notifyBreakpointChangeAfterInsertNeeded(BreakpointId id)
{
- data->m_handler = this;
- m_bp.append(data);
+ QTC_ASSERT(state(id) == BreakpointInsertProceeding, qDebug() << state(id));
+ setState(id, BreakpointChangeRequested);
}
-Breakpoints BreakHandler::takeRemovedBreakpoints()
+void BreakHandler::notifyBreakpointInsertProceeding(BreakpointId id)
{
- Breakpoints result = m_removed;
- m_removed.clear();
- return result;
+ QTC_ASSERT(state(id) == BreakpointInsertRequested, qDebug() << state(id));
+ setState(id, BreakpointInsertProceeding);
}
-Breakpoints BreakHandler::takeEnabledBreakpoints()
+void BreakHandler::notifyBreakpointInsertOk(BreakpointId id)
{
- Breakpoints result = m_enabled;
- m_enabled.clear();
- return result;
+ QTC_ASSERT(state(id) == BreakpointInsertProceeding, qDebug() << state(id));
+ setState(id, BreakpointInserted);
+ ConstIterator it = m_storage.find(id);
+ QTC_ASSERT(it != m_storage.end(), return);
}
-Breakpoints BreakHandler::takeDisabledBreakpoints()
+void BreakHandler::notifyBreakpointInsertFailed(BreakpointId id)
{
- Breakpoints result = m_disabled;
- m_disabled.clear();
- return result;
+ QTC_ASSERT(state(id) == BreakpointInsertProceeding, qDebug() << state(id));
+ setState(id, BreakpointDead);
}
-void BreakHandler::removeBreakpointHelper(int index)
+void BreakHandler::notifyBreakpointRemoveProceeding(BreakpointId id)
{
- BreakpointData *data = at(index);
- QTC_ASSERT(data, return);
- m_bp.removeAt(index);
- data->removeMarker();
- m_removed.append(data);
+ QTC_ASSERT(state(id) == BreakpointRemoveRequested, qDebug() << state(id));
+ setState(id, BreakpointRemoveProceeding);
}
-void BreakHandler::removeBreakpoint(int index)
+void BreakHandler::notifyBreakpointRemoveOk(BreakpointId id)
{
- if (index < 0 || index >= size())
- return;
- removeBreakpointHelper(index);
- emit layoutChanged();
+ QTC_ASSERT(state(id) == BreakpointRemoveProceeding, qDebug() << state(id));
+ setState(id, BreakpointDead);
+ cleanupBreakpoint(id);
}
-void BreakHandler::removeBreakpoint(BreakpointData *data)
+void BreakHandler::notifyBreakpointRemoveFailed(BreakpointId id)
{
- removeBreakpointHelper(indexOf(data));
- emit layoutChanged();
+ QTC_ASSERT(state(id) == BreakpointRemoveProceeding, qDebug() << state(id));
+ setState(id, BreakpointDead);
+ cleanupBreakpoint(id);
}
-void BreakHandler::toggleBreakpointEnabled(BreakpointData *data)
+void BreakHandler::notifyBreakpointChangeProceeding(BreakpointId id)
{
- QTC_ASSERT(data, return);
- data->enabled = !data->enabled;
- if (data->enabled) {
- m_enabled.append(data);
- m_disabled.removeAll(data);
- } else {
- m_enabled.removeAll(data);
- m_disabled.append(data);
- }
- data->removeMarker(); // Force icon update.
- data->updateMarker();
- emit layoutChanged();
- m_engine->attemptBreakpointSynchronization();
+ QTC_ASSERT(state(id) == BreakpointChangeRequested, qDebug() << state(id));
+ setState(id, BreakpointChangeProceeding);
}
-void BreakHandler::toggleBreakpointEnabled(const QString &fileName, int lineNumber)
+void BreakHandler::notifyBreakpointChangeOk(BreakpointId id)
{
- BreakpointData *data = findBreakpoint(fileName, lineNumber);
- toggleBreakpointEnabled(data);
+ QTC_ASSERT(state(id) == BreakpointChangeProceeding, qDebug() << state(id));
+ setState(id, BreakpointInserted);
}
-void BreakHandler::appendBreakpoint(BreakpointData *data)
+void BreakHandler::notifyBreakpointChangeFailed(BreakpointId id)
{
- append(data);
- emit layoutChanged();
- saveBreakpoints(); // FIXME: remove?
- updateMarkers();
+ QTC_ASSERT(state(id) == BreakpointChangeProceeding, qDebug() << state(id));
+ setState(id, BreakpointDead);
}
-void BreakHandler::removeAllBreakpoints()
+void BreakHandler::notifyBreakpointReleased(BreakpointId id)
{
- for (int index = size(); --index >= 0;)
- removeBreakpointHelper(index);
- emit layoutChanged();
- updateMarkers();
+ //QTC_ASSERT(state(id) == BreakpointChangeProceeding, qDebug() << state(id));
+ Iterator it = m_storage.find(id);
+ QTC_ASSERT(it != m_storage.end(), return);
+ it->state = BreakpointNew;
+ it->engine = 0;
+ it->response = BreakpointResponse();
+ delete it->marker;
+ it->marker = 0;
+ updateMarker(id);
+ layoutChanged();
}
-BreakpointData *BreakHandler::findBreakpoint(quint64 address) const
+void BreakHandler::notifyBreakpointAdjusted(BreakpointId id,
+ const BreakpointParameters &data)
{
- foreach (BreakpointData *data, m_bp)
- if (data->address == address)
- return data;
- return 0;
+ QTC_ASSERT(state(id) == BreakpointInserted, qDebug() << state(id));
+ Iterator it = m_storage.find(id);
+ QTC_ASSERT(it != m_storage.end(), return);
+ it->data = data;
+ //if (it->needsChange())
+ // setState(id, BreakpointChangeRequested);
}
-BreakpointData *BreakHandler::findBreakpoint(const QString &fileName,
- int lineNumber, bool useMarkerPosition)
+void BreakHandler::notifyBreakpointNeedsReinsertion(BreakpointId id)
{
- foreach (BreakpointData *data, m_bp)
- if (data->isLocatedAt(fileName, lineNumber, useMarkerPosition))
- return data;
- return 0;
+ QTC_ASSERT(state(id) == BreakpointChangeProceeding, qDebug() << state(id));
+ Iterator it = m_storage.find(id);
+ QTC_ASSERT(it != m_storage.end(), return);
+ it->state = BreakpointInsertRequested;
}
-void BreakHandler::toggleBreakpoint(const QString &fileName, int lineNumber,
- quint64 address /* = 0 */)
+void BreakHandler::removeBreakpoint(BreakpointId id)
{
- BreakpointData *data = 0;
-
- if (address) {
- data = findBreakpoint(address);
+ Iterator it = m_storage.find(id);
+ QTC_ASSERT(it != m_storage.end(), return);
+ if (it->state == BreakpointInserted) {
+ setState(id, BreakpointRemoveRequested);
+ scheduleSynchronization();
+ } else if (it->state == BreakpointNew) {
+ it->state = BreakpointDead;
+ cleanupBreakpoint(id);
} else {
- data = findBreakpoint(fileName, lineNumber, true);
- if (!data)
- data = findBreakpoint(fileName, lineNumber, false);
+ qDebug() << "CANNOT REMOVE IN STATE " << it->state;
+ it->state = BreakpointRemoveRequested;
}
+}
- if (data) {
- removeBreakpoint(data);
- } else {
- data = new BreakpointData;
- if (address) {
- data->address = address;
- } else {
- data->fileName = fileName;
- data->lineNumber = lineNumber;
- }
- data->pending = true;
- data->setMarkerFileName(fileName);
- data->setMarkerLineNumber(lineNumber);
- appendBreakpoint(data);
- }
- m_engine->attemptBreakpointSynchronization();
+void BreakHandler::appendBreakpoint(const BreakpointParameters &data)
+{
+ QTC_ASSERT(data.type != UnknownType, return);
+
+ // Ok to be not thread-safe. The order does not matter and only the gui
+ // produces authoritative ids.
+ static quint64 currentId = 0;
+
+ BreakpointId id(++currentId);
+ BreakpointItem item;
+ item.data = data;
+ item.response.fileName = data.fileName;
+ item.response.lineNumber = data.lineNumber;
+ m_storage.insert(id, item);
+ updateMarker(id);
+ scheduleSynchronization();
}
void BreakHandler::saveSessionData()
{
- QTC_ASSERT(m_engine->isSessionEngine(), return);
saveBreakpoints();
}
void BreakHandler::loadSessionData()
{
- QTC_ASSERT(m_engine->isSessionEngine(), return);
- qDeleteAll(m_bp);
- m_bp.clear();
+ m_storage.clear();
loadBreakpoints();
- updateMarkers();
+}
+
+void BreakHandler::removeSessionData()
+{
+ Iterator it = m_storage.begin(), et = m_storage.end();
+ for ( ; it != et; ++it)
+ it->destroyMarker();
+ m_storage.clear();
+ layoutChanged();
}
void BreakHandler::breakByFunction(const QString &functionName)
{
// One breakpoint per function is enough for now. This does not handle
// combinations of multiple conditions and ignore counts, though.
- for (int index = size(); --index >= 0;) {
- const BreakpointData *data = at(index);
- QTC_ASSERT(data, break);
- if (data->funcName == functionName && data->condition.isEmpty()
- && data->ignoreCount == 0)
+ ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
+ for ( ; it != et; ++it) {
+ const BreakpointParameters &data = it->data;
+ if (data.functionName == functionName
+ && data.condition.isEmpty()
+ && data.ignoreCount == 0)
return;
}
- BreakpointData *data = new BreakpointData;
- data->funcName = functionName;
- append(data);
- //saveBreakpoints();
- updateMarkers();
+ BreakpointParameters data(BreakpointByFunction);
+ data.functionName = functionName;
+ appendBreakpoint(data);
+}
+
+QIcon BreakHandler::icon(BreakpointId id) const
+{
+ ConstIterator it = m_storage.find(id);
+ QTC_ASSERT(it != m_storage.end(),
+ qDebug() << "NO ICON FOR ID" << id;
+ return pendingBreakpointIcon());
+ return it->icon();
+}
+
+void BreakHandler::scheduleSynchronization()
+{
+ if (m_syncTimerId == -1)
+ m_syncTimerId = startTimer(10);
+}
+
+void BreakHandler::timerEvent(QTimerEvent *event)
+{
+ QTC_ASSERT(event->timerId() == m_syncTimerId, return);
+ killTimer(m_syncTimerId);
+ m_syncTimerId = -1;
+ saveBreakpoints(); // FIXME: remove?
+ debuggerCore()->synchronizeBreakpoints();
+}
+
+void BreakHandler::gotoLocation(BreakpointId id) const
+{
+ ConstIterator it = m_storage.find(id);
+ QTC_ASSERT(it != m_storage.end(), return);
+ DebuggerEngine *engine = debuggerCore()->currentEngine();
+ if (it->data.type == BreakpointByAddress) {
+ if (engine)
+ engine->gotoLocation(it->data.address);
+ } else {
+ if (engine)
+ engine->gotoLocation(
+ Location(it->markerFileName(), it->markerLineNumber()));
+ }
+}
+
+void BreakHandler::updateLineNumberFromMarker(BreakpointId id, int lineNumber)
+{
+ Iterator it = m_storage.find(id);
+ it->response.pending = false;
+ QTC_ASSERT(it != m_storage.end(), return);
+ if (it->response.lineNumber != lineNumber) {
+ // FIXME: Should we tell gdb about the change?
+ it->response.lineNumber = lineNumber;
+ }
+ // Ignore updates to the "real" line number while the debugger is
+ // running, as this can be triggered by moving the breakpoint to
+ // the next line that generated code.
+ if (it->response.number == 0) {
+ // FIXME: Do we need yet another data member?
+ it->data.lineNumber = lineNumber;
+ }
+ updateMarker(id);
+ emit layoutChanged();
}
-bool BreakHandler::isActive() const
+BreakpointIds BreakHandler::allBreakpointIds() const
{
- return m_engine->isActive();
+ BreakpointIds ids;
+ ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
+ for ( ; it != et; ++it)
+ ids.append(it.key());
+ return ids;
}
-void BreakHandler::initializeFromTemplate(BreakHandler *other)
+BreakpointIds BreakHandler::unclaimedBreakpointIds() const
{
- Q_UNUSED(other)
- m_inserted.clear();
- foreach(BreakpointData *data, m_bp) {
- if (m_engine->acceptsBreakpoint(data)) {
- data->m_handler = this;
- m_inserted.append(data);
- }
+ return engineBreakpointIds(0);
+}
+
+BreakpointIds BreakHandler::engineBreakpointIds(DebuggerEngine *engine) const
+{
+ BreakpointIds ids;
+ ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
+ for ( ; it != et; ++it)
+ if (it->engine == engine)
+ ids.append(it.key());
+ return ids;
+}
+
+void BreakHandler::cleanupBreakpoint(BreakpointId id)
+{
+ QTC_ASSERT(state(id) == BreakpointDead, qDebug() << state(id));
+ BreakpointItem item = m_storage.take(id);
+ item.destroyMarker();
+ layoutChanged();
+}
+
+const BreakpointResponse &BreakHandler::response(BreakpointId id) const
+{
+ static BreakpointResponse dummy;
+ ConstIterator it = m_storage.find(id);
+ QTC_ASSERT(it != m_storage.end(), return dummy);
+ return it->response;
+}
+
+bool BreakHandler::needsChange(BreakpointId id) const
+{
+ ConstIterator it = m_storage.find(id);
+ QTC_ASSERT(it != m_storage.end(), return false);
+ return it->needsChange();
+}
+
+void BreakHandler::setResponse(BreakpointId id, const BreakpointResponse &data)
+{
+ Iterator it = m_storage.find(id);
+ QTC_ASSERT(it != m_storage.end(), return);
+ it->response = data;
+ it->destroyMarker();
+ updateMarker(id);
+}
+
+void BreakHandler::setBreakpointData(BreakpointId id, const BreakpointParameters &data)
+{
+ Iterator it = m_storage.find(id);
+ QTC_ASSERT(it != m_storage.end(), return);
+ if (data == it->data)
+ return;
+ it->data = data;
+ if (it->needsChange() && it->state != BreakpointNew) {
+ setState(id, BreakpointChangeRequested);
+ scheduleSynchronization();
+ } else {
+ it->destroyMarker();
+ updateMarker(id);
+ layoutChanged();
}
}
-void BreakHandler::storeToTemplate(BreakHandler *other)
+//////////////////////////////////////////////////////////////////
+//
+// Storage
+//
+//////////////////////////////////////////////////////////////////
+
+BreakHandler::BreakpointItem::BreakpointItem()
+ : state(BreakpointNew), engine(0), marker(0)
+{}
+
+void BreakHandler::BreakpointItem::destroyMarker()
+{
+ BreakpointMarker *m = marker;
+ marker = 0;
+ delete m;
+}
+
+QString BreakHandler::BreakpointItem::markerFileName() const
{
- foreach (BreakpointData *data, m_bp) {
- data->m_handler = other;
- data->clear();
+ // Some heuristics to find a "good" file name.
+ if (!data.fileName.isEmpty()) {
+ QFileInfo fi(data.fileName);
+ if (fi.exists())
+ return fi.absoluteFilePath();
}
- other->saveSessionData();
+ if (!response.fileName.isEmpty()) {
+ QFileInfo fi(response.fileName);
+ if (fi.exists())
+ return fi.absoluteFilePath();
+ }
+ if (response.fileName.endsWith(data.fileName))
+ return response.fileName;
+ if (data.fileName.endsWith(response.fileName))
+ return data.fileName;
+ return response.fileName.size() > data.fileName.size()
+ ? response.fileName : data.fileName;
+}
+
+
+int BreakHandler::BreakpointItem::markerLineNumber() const
+{
+ return response.lineNumber ? response.lineNumber : data.lineNumber;
+}
+
+static void formatAddress(QTextStream &str, quint64 address)
+{
+ if (address) {
+ str << "0x";
+ str.setIntegerBase(16);
+ str << address;
+ str.setIntegerBase(10);
+ }
+}
+
+static QString stateToString(BreakpointState state)
+{
+ switch (state) {
+ case BreakpointNew: return "New";
+ case BreakpointInsertRequested: return "Insertion requested";
+ case BreakpointInsertProceeding: return "Insertion proceeding";
+ case BreakpointChangeRequested: return "Change requested";
+ case BreakpointChangeProceeding: return "Change proceeding";
+ case BreakpointInserted: return "Breakpoint inserted";
+ case BreakpointRemoveRequested: return "Removal requested";
+ case BreakpointRemoveProceeding: return "Removal proceeding";
+ case BreakpointDead: return "Dead";
+ default: return "<invalid state>";
+ }
+}
+
+bool BreakHandler::BreakpointItem::needsChange() const
+{
+ if (!data.conditionsMatch(response.condition))
+ return true;
+ if (data.ignoreCount != response.ignoreCount)
+ return true;
+ if (data.enabled != response.enabled)
+ return true;
+ if (data.threadSpec != response.threadSpec)
+ return true;
+ return false;
+}
+
+bool BreakHandler::BreakpointItem::isLocatedAt
+ (const QString &fileName, int lineNumber, bool useMarkerPosition) const
+{
+ int line = useMarkerPosition ? response.lineNumber : data.lineNumber;
+ return lineNumber == line
+ && (fileNameMatch(fileName, response.fileName)
+ || fileNameMatch(fileName, markerFileName()));
}
-int BreakHandler::size() const
+QIcon BreakHandler::BreakpointItem::icon() const
{
- return m_bp.size();
+ // FIXME: This seems to be called on each cursor blink as soon as the
+ // cursor is near a line with a breakpoint marker (+/- 2 lines or so).
+ if (data.isTracepoint())
+ return BreakHandler::tracepointIcon();
+ if (data.type == Watchpoint)
+ return BreakHandler::watchpointIcon();
+ if (!data.enabled)
+ return BreakHandler::disabledBreakpointIcon();
+ if (state == BreakpointInserted)
+ return BreakHandler::breakpointIcon();
+ return BreakHandler::pendingBreakpointIcon();
}
-int BreakHandler::indexOf(BreakpointData *data)
+QString BreakHandler::BreakpointItem::toToolTip() const
{
- return m_bp.indexOf(data);
+ QString t;
+
+ switch (data.type) {
+ case BreakpointByFileAndLine:
+ t = tr("Breakpoint by File and Line");
+ break;
+ case BreakpointByFunction:
+ t = tr("Breakpoint by Function");
+ break;
+ case BreakpointByAddress:
+ t = tr("Breakpoint by Address");
+ break;
+ case BreakpointAtThrow:
+ t = tr("Breakpoint at \"throw\"");
+ break;
+ case BreakpointAtCatch:
+ t = tr("Breakpoint at \"catch\"");
+ break;
+ case BreakpointAtMain:
+ t = tr("Breakpoint at Function \"main()\"");
+ break;
+ case Watchpoint:
+ t = tr("Watchpoint");
+ break;
+ case UnknownType:
+ t = tr("Unknown Breakpoint Type");
+ break;
+ }
+
+ QString rc;
+ QTextStream str(&rc);
+ str << "<html><body><table>"
+ //<< "<tr><td>" << tr("Id:") << "</td><td>" << m_id << "</td></tr>"
+ << "<tr><td>" << tr("State:")
+ << "</td><td>" << state << " (" << stateToString(state) << ")</td></tr>"
+ << "<tr><td>" << tr("Engine:")
+ << "</td><td>" << (engine ? engine->objectName() : "0") << "</td></tr>"
+ << "<tr><td>" << tr("Breakpoint Number:")
+ << "</td><td>" << response.number << "</td></tr>"
+ << "<tr><td>" << tr("Breakpoint Type:")
+ << "</td><td>" << t << "</td></tr>"
+ << "<tr><td>" << tr("Extra Information:")
+ << "</td><td>" << response.extra << "</td></tr>"
+ << "<tr><td>" << tr("Pending:")
+ << "</td><td>" << (response.pending ? "True" : "False") << "</td></tr>"
+ << "<tr><td>" << tr("Marker File:")
+ << "</td><td>" << markerFileName() << "</td></tr>"
+ << "<tr><td>" << tr("Marker Line:")
+ << "</td><td>" << markerLineNumber() << "</td></tr>"
+ << "</table><br><hr><table>"
+ << "<tr><th>" << tr("Property")
+ << "</th><th>" << tr("Requested")
+ << "</th><th>" << tr("Obtained") << "</th></tr>"
+ << "<tr><td>" << tr("Internal Number:")
+ << "</td><td>&mdash;</td><td>" << response.number << "</td></tr>"
+ << "<tr><td>" << tr("Function Name:")
+ << "</td><td>" << data.functionName
+ << "</td><td>" << response.functionName
+ << "</td></tr>"
+ << "<tr><td>" << tr("File Name:")
+ << "</td><td>" << QDir::toNativeSeparators(data.fileName)
+ << "</td><td>" << QDir::toNativeSeparators(response.fileName)
+ << "</td></tr>"
+ << "<tr><td>" << tr("Line Number:")
+ << "</td><td>" << data.lineNumber
+ << "</td><td>" << response.lineNumber << "</td></tr>"
+ << "<tr><td>" << tr("Breakpoint Address:")
+ << "</td><td>";
+ formatAddress(str, data.address);
+ str << "</td><td>";
+ formatAddress(str, response.address);
+ //str << "</td></tr>"
+ // << "<tr><td>" << tr("Corrected Line Number:")
+ // << "</td><td>-</td><td>";
+ //if (response.bpCorrectedLineNumber > 0)
+ // str << response.bpCorrectedLineNumber;
+ //else
+ // str << '-';
+ str << "</td></tr>"
+ << "<tr><td>" << tr("Condition:")
+ << "</td><td>" << data.condition
+ << "</td><td>" << response.condition << "</td></tr>"
+ << "<tr><td>" << tr("Ignore Count:") << "</td><td>";
+ if (data.ignoreCount)
+ str << data.ignoreCount;
+ str << "</td><td>";
+ if (response.ignoreCount)
+ str << response.ignoreCount;
+ str << "</td></tr>"
+ << "<tr><td>" << tr("Thread Specification:")
+ << "</td><td>" << data.threadSpec
+ << "</td><td>" << response.threadSpec << "</td></tr>"
+ << "</table></body></html>";
+ return rc;
}
} // namespace Internal
diff --git a/src/plugins/debugger/breakhandler.h b/src/plugins/debugger/breakhandler.h
index f13846f08f..59297e3a6c 100644
--- a/src/plugins/debugger/breakhandler.h
+++ b/src/plugins/debugger/breakhandler.h
@@ -41,103 +41,165 @@
#include <QtGui/QIcon>
+//////////////////////////////////////////////////////////////////
+//
+// BreakHandler
+//
+//////////////////////////////////////////////////////////////////
+
namespace Debugger {
class DebuggerEngine;
namespace Internal {
-//////////////////////////////////////////////////////////////////
-//
-// BreakHandler
-//
-//////////////////////////////////////////////////////////////////
+class BreakpointMarker;
class BreakHandler : public QAbstractTableModel
{
Q_OBJECT
public:
- explicit BreakHandler(DebuggerEngine *engine);
+ BreakHandler();
~BreakHandler();
- void removeAllBreakpoints();
void loadSessionData();
void saveSessionData();
+ void removeSessionData();
QAbstractItemModel *model() { return this; }
- BreakpointData *at(int index) const;
- int size() const;
- bool hasPendingBreakpoints() const;
- void removeAt(int index); // This also deletes the marker.
- void clear(); // This also deletes all the marker.
- int indexOf(BreakpointData *data);
+ // The only way to add a new breakpoint.
+ void appendBreakpoint(const BreakpointParameters &data);
+
+ BreakpointIds allBreakpointIds() const;
+ BreakpointIds engineBreakpointIds(DebuggerEngine *engine) const;
+ BreakpointIds unclaimedBreakpointIds() const;
+ int size() const { return m_storage.size(); }
+
// Find a breakpoint matching approximately the data in needle.
- BreakpointData *findSimilarBreakpoint(const BreakpointData *needle) const;
- BreakpointData *findBreakpointByNumber(int bpNumber) const;
- int findWatchPointIndexByAddress(quint64 address) const;
- bool watchPointAt(quint64 address) const;
+ BreakpointId findSimilarBreakpoint(const BreakpointResponse &needle) const;
+ BreakpointId findBreakpointByNumber(int bpNumber) const;
+ BreakpointId findWatchpointByAddress(quint64 address) const;
+ BreakpointId findBreakpointByFunction(const QString &functionName) const;
+ BreakpointId findBreakpointByIndex(const QModelIndex &index) const;
+ BreakpointIds findBreakpointsByIndex(const QList<QModelIndex> &list) const;
+ void setWatchpointByAddress(quint64 address);
+ bool hasWatchpointAt(quint64 address) const;
void updateMarkers();
- bool isActive() const;
-
- Breakpoints takeRemovedBreakpoints(); // Owned.
- Breakpoints takeEnabledBreakpoints(); // Not owned.
- Breakpoints takeDisabledBreakpoints(); // Not owned.
-
- QIcon breakpointIcon() const { return m_breakpointIcon; }
- QIcon disabledBreakpointIcon() const { return m_disabledBreakpointIcon; }
- QIcon pendingBreakPointIcon() const { return m_pendingBreakPointIcon; }
- QIcon emptyIcon() const { return m_emptyIcon; }
-
- void initializeFromTemplate(BreakHandler *other);
- void storeToTemplate(BreakHandler *other);
- void toggleBreakpoint(const QString &fileName, int lineNumber, quint64 address = 0);
- void toggleBreakpointEnabled(const QString &fileName, int lineNumber);
- BreakpointData *findBreakpoint(const QString &fileName, int lineNumber,
- bool useMarkerPosition = true);
- BreakpointData *findBreakpoint(quint64 address) const;
-
-public slots:
- void appendBreakpoint(BreakpointData *data);
- void reinsertBreakpoint(BreakpointData *data);
- void toggleBreakpointEnabled(BreakpointData *data);
+
+ static QIcon breakpointIcon();
+ static QIcon disabledBreakpointIcon();
+ static QIcon pendingBreakpointIcon();
+ static QIcon emptyIcon();
+ static QIcon watchpointIcon();
+ static QIcon tracepointIcon();
+
+ BreakpointId findBreakpointByFileAndLine(const QString &fileName,
+ int lineNumber, bool useMarkerPosition = true);
+ BreakpointId findBreakpointByAddress(quint64 address) const;
+
void breakByFunction(const QString &functionName);
- void removeBreakpoint(int index);
- void removeBreakpoint(BreakpointData *data);
+ void removeBreakpoint(BreakpointId id);
+ QIcon icon(BreakpointId id) const;
+ void gotoLocation(BreakpointId id) const;
+
+ // Getter retrieves property value.
+ // Setter sets property value and triggers update if changed.
+ bool useFullPath(BreakpointId id) const;
+ void setUseFullPath(BreakpointId, const bool &on);
+ QByteArray condition(BreakpointId id) const;
+ void setCondition(BreakpointId, const QByteArray &condition);
+ int ignoreCount(BreakpointId id) const;
+ void setIgnoreCount(BreakpointId, const int &count);
+ int threadSpec(BreakpointId id) const;
+ void setThreadSpec(BreakpointId, const int&spec);
+ QString fileName(BreakpointId id) const;
+ void setFileName(BreakpointId, const QString &fileName);
+ QString functionName(BreakpointId id) const;
+ void setFunctionName(BreakpointId, const QString &functionName);
+ BreakpointType type(BreakpointId id) const;
+ void setType(BreakpointId id, const BreakpointType &type);
+ quint64 address(BreakpointId id) const;
+ void setAddress(BreakpointId id, const quint64 &address);
+ int lineNumber(BreakpointId id) const;
+ void setBreakpointData(BreakpointId id, const BreakpointParameters &data);
+ const BreakpointParameters &breakpointData(BreakpointId id) const;
+ BreakpointState state(BreakpointId id) const;
+ bool isEnabled(BreakpointId id) const;
+ void setEnabled(BreakpointId id, bool on);
+ void updateLineNumberFromMarker(BreakpointId id, int lineNumber);
+ void setMarkerFileAndLine(BreakpointId id,
+ const QString &fileName, int lineNumber);
+ bool isTracepoint(BreakpointId id) const;
+ void setTracepoint(BreakpointId, bool on);
+ DebuggerEngine *engine(BreakpointId id) const;
+ void setEngine(BreakpointId id, DebuggerEngine *engine);
+ const BreakpointResponse &response(BreakpointId id) const;
+ void setResponse(BreakpointId id, const BreakpointResponse &data);
+ bool needsChange(BreakpointId id) const;
+
+ // State transitions.
+ void notifyBreakpointChangeAfterInsertNeeded(BreakpointId id);
+ void notifyBreakpointInsertProceeding(BreakpointId id);
+ void notifyBreakpointInsertOk(BreakpointId id);
+ void notifyBreakpointInsertFailed(BreakpointId id);
+ void notifyBreakpointChangeOk(BreakpointId id);
+ void notifyBreakpointChangeProceeding(BreakpointId id);
+ void notifyBreakpointChangeFailed(BreakpointId id);
+ void notifyBreakpointPending(BreakpointId id);
+ void notifyBreakpointRemoveProceeding(BreakpointId id);
+ void notifyBreakpointRemoveOk(BreakpointId id);
+ void notifyBreakpointRemoveFailed(BreakpointId id);
+ void notifyBreakpointReleased(BreakpointId id);
+ void notifyBreakpointNeedsReinsertion(BreakpointId id);
+ void notifyBreakpointAdjusted(BreakpointId id,
+ const BreakpointParameters &data);
+
+ static QString displayFromThreadSpec(int spec);
+ static int threadSpecFromDisplay(const QString &str);
private:
- friend class BreakpointMarker;
-
- // QAbstractItemModel
+ // QAbstractItemModel implementation.
int columnCount(const QModelIndex &parent) const;
int rowCount(const QModelIndex &parent) const;
QVariant data(const QModelIndex &index, int role) const;
- bool setData(const QModelIndex &index, const QVariant &value, int role);
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
- void markerUpdated(BreakpointMarker *, int lineNumber);
+ void setState(BreakpointId id, BreakpointState state);
void loadBreakpoints();
void saveBreakpoints();
- void removeBreakpointHelper(int index);
- void append(BreakpointData *data);
-
- const QIcon m_breakpointIcon;
- const QIcon m_disabledBreakpointIcon;
- const QIcon m_pendingBreakPointIcon;
- const QIcon m_emptyIcon;
- const QIcon m_watchpointIcon;
-
- Debugger::DebuggerEngine *m_engine; // Not owned.
- Breakpoints m_inserted; // Lately inserted breakpoints.
- Breakpoints m_removed; // Lately removed breakpoints.
- Breakpoints m_enabled; // Lately enabled breakpoints.
- Breakpoints m_disabled; // Lately disabled breakpoints.
-
- // Hack for BreakWindow::findSimilarBreakpoint
- mutable BreakpointData *m_lastFound;
- mutable bool m_lastFoundQueried;
+ void updateMarker(BreakpointId id);
+ void cleanupBreakpoint(BreakpointId id);
+
+ struct BreakpointItem
+ {
+ BreakpointItem();
+
+ void destroyMarker();
+ bool needsChange() const;
+ bool isLocatedAt(const QString &fileName, int lineNumber,
+ bool useMarkerPosition) const;
+ QString toToolTip() const;
+ QString markerFileName() const;
+ int markerLineNumber() const;
+ QIcon icon() const;
+
+ BreakpointParameters data;
+ BreakpointState state; // Current state of breakpoint.
+ DebuggerEngine *engine; // Engine currently handling the breakpoint.
+ BreakpointResponse response;
+ BreakpointMarker *marker;
+ };
+ typedef QHash<BreakpointId, BreakpointItem> BreakpointStorage;
+ typedef BreakpointStorage::ConstIterator ConstIterator;
+ typedef BreakpointStorage::Iterator Iterator;
+ BreakpointStorage m_storage;
+
+ void scheduleSynchronization();
+ void timerEvent(QTimerEvent *event);
+ int m_syncTimerId;
};
} // namespace Internal
diff --git a/src/plugins/debugger/breakpoint.cpp b/src/plugins/debugger/breakpoint.cpp
index 0df5b9f3e5..85a85563ee 100644
--- a/src/plugins/debugger/breakpoint.cpp
+++ b/src/plugins/debugger/breakpoint.cpp
@@ -31,371 +31,99 @@
**
**************************************************************************/
-#include "breakhandler.h"
-
-#include "debuggeractions.h"
-#include "debuggerengine.h"
-#include "debuggerstringutils.h"
-#include "threadshandler.h"
-#include "stackhandler.h"
-#include "stackframe.h"
-
-#include <texteditor/basetextmark.h>
-#include <utils/qtcassert.h>
+#include "breakpoint.h"
#include <QtCore/QByteArray>
#include <QtCore/QDebug>
-#include <QtCore/QTextStream>
-#include <QtCore/QFileInfo>
-#include <QtCore/QDir>
-
-//////////////////////////////////////////////////////////////////
-//
-// BreakpointMarker
-//
-//////////////////////////////////////////////////////////////////
-
-// Compare file names case insensitively on Windows.
-static inline bool fileNameMatch(const QString &f1, const QString &f2)
-{
-#ifdef Q_OS_WIN
- return f1.compare(f2, Qt::CaseInsensitive) == 0;
-#else
- return f1 == f2;
-#endif
-}
namespace Debugger {
namespace Internal {
-// The red blob on the left side in the cpp editor.
-class BreakpointMarker : public TextEditor::BaseTextMark
-{
- Q_OBJECT
-public:
- BreakpointMarker(BreakpointData *data, const QString &fileName, int lineNumber)
- : BaseTextMark(fileName, lineNumber)
- {
- m_data = data;
- m_pending = true;
- //qDebug() << "CREATE MARKER " << fileName << lineNumber;
- }
-
- ~BreakpointMarker()
- {
- //qDebug() << "REMOVE MARKER ";
- m_data = 0;
- }
-
- QIcon icon() const
- {
- const BreakHandler *handler = m_data->handler();
- if (!m_data->enabled)
- return handler->disabledBreakpointIcon();
- if (!handler->isActive())
- return handler->emptyIcon();
- return m_pending ? handler->pendingBreakPointIcon() : handler->breakpointIcon();
- }
-
- void setPending(bool pending)
- {
- if (pending == m_pending)
- return;
- m_pending = pending;
- updateMarker();
- }
-
- void updateBlock(const QTextBlock &)
- {
- //qDebug() << "BREAKPOINT MARKER UPDATE BLOCK";
- }
-
- void removedFromEditor()
- {
- if (!m_data)
- return;
-
- BreakHandler *handler = m_data->handler();
- handler->removeBreakpoint(m_data);
- //handler->saveBreakpoints();
- handler->updateMarkers();
- }
-
- void updateLineNumber(int lineNumber)
- {
- if (!m_data)
- return;
- //if (m_data->markerLineNumber == lineNumber)
- // return;
- if (m_data->markerLineNumber() != lineNumber) {
- m_data->setMarkerLineNumber(lineNumber);
- // FIXME: Should we tell gdb about the change?
- // Ignore it for now, as we would require re-compilation
- // and debugger re-start anyway.
- if (0 && m_data->bpLineNumber) {
- if (!m_data->bpNumber.trimmed().isEmpty()) {
- m_data->pending = true;
- }
- }
- }
- // Ignore updates to the "real" line number while the debugger is
- // running, as this can be triggered by moving the breakpoint to
- // the next line that generated code.
- // FIXME: Do we need yet another data member?
- if (m_data->bpNumber.trimmed().isEmpty()) {
- m_data->lineNumber = lineNumber;
- m_data->handler()->updateMarkers();
- }
- }
-
-private:
- BreakpointData *m_data;
- bool m_pending;
-};
-
-
//////////////////////////////////////////////////////////////////
//
-// BreakpointData
+// BreakpointParameters
//
//////////////////////////////////////////////////////////////////
-const char *BreakpointData::throwFunction = "throw";
-const char *BreakpointData::catchFunction = "catch";
-
-BreakpointData::BreakpointData() :
- m_handler(0), enabled(true),
- pending(true), type(BreakpointType),
- ignoreCount(0), lineNumber(0), address(0),
- useFullPath(false),
- bpIgnoreCount(0), bpLineNumber(0),
- bpCorrectedLineNumber(0), bpAddress(0),
- bpMultiple(false), bpEnabled(true),
- m_markerLineNumber(0), marker(0)
-{
-}
-
-BreakpointData *BreakpointData::clone() const
-{
- BreakpointData *data = new BreakpointData();
- data->m_handler = m_handler;
- data->enabled = enabled;
- data->type = type;
- data->fileName = fileName;
- data->condition = condition;
- data->ignoreCount = ignoreCount;
- data->lineNumber = lineNumber;
- data->address = address;
- data->threadSpec = threadSpec;
- data->funcName = funcName;
- data->useFullPath = useFullPath;
- if (isSetByFunction()) {
- // FIXME: Would removing it be better then leaving this
- // "history" around?
- data->m_markerFileName = m_markerFileName;
- data->m_markerLineNumber = m_markerLineNumber;
- } else {
- data->m_markerFileName = fileName;
- data->m_markerLineNumber = lineNumber;
- }
- return data;
-}
-
-BreakpointData::~BreakpointData()
-{
- removeMarker();
-}
-
-void BreakpointData::clear()
-{
- pending = true;
- bpNumber.clear();
- bpCondition.clear();
- bpIgnoreCount = 0;
- bpFileName.clear();
- bpFullName.clear();
- bpLineNumber = 0;
- bpCorrectedLineNumber = 0;
- bpThreadSpec.clear();
- bpFuncName.clear();
- bpAddress = 0;
- bpMultiple = false;
- bpEnabled = true;
- bpState.clear();
- m_markerFileName = fileName;
- m_markerLineNumber = lineNumber;
- updateMarker();
-}
-
-void BreakpointData::removeMarker()
-{
- BreakpointMarker *m = marker;
- marker = 0;
- delete m;
-}
-
-void BreakpointData::updateMarker()
-{
- if (marker && (m_markerFileName != marker->fileName()
- || m_markerLineNumber != marker->lineNumber()))
- removeMarker();
-
- if (!marker && !m_markerFileName.isEmpty() && m_markerLineNumber > 0)
- marker = new BreakpointMarker(this, m_markerFileName, m_markerLineNumber);
-
- if (marker)
- marker->setPending(pending);
-}
-
-void BreakpointData::setMarkerFileName(const QString &fileName)
-{
- m_markerFileName = fileName;
+BreakpointParameters::BreakpointParameters(BreakpointType t)
+ : type(t), enabled(true), useFullPath(false),
+ ignoreCount(0), lineNumber(0), address(0), threadSpec(-1),
+ tracepoint(false)
+{}
+
+bool BreakpointParameters::equals(const BreakpointParameters &rhs) const
+{
+ return type == rhs.type
+ && enabled == rhs.enabled
+ && useFullPath == rhs.useFullPath
+ && fileName == rhs.fileName
+ && conditionsMatch(rhs.condition)
+ && ignoreCount == rhs.ignoreCount
+ && lineNumber == rhs.lineNumber
+ && address == rhs.address
+ && threadSpec == rhs.threadSpec
+ && functionName == rhs.functionName
+ && tracepoint == rhs.tracepoint;
}
-void BreakpointData::setMarkerLineNumber(int lineNumber)
+bool BreakpointParameters::conditionsMatch(const QByteArray &other) const
{
- m_markerLineNumber = lineNumber;
-}
-
-static inline void formatAddress(QTextStream &str, quint64 address)
-{
- if (address) {
- str << "0x";
- str.setIntegerBase(16);
- str << address;
- str.setIntegerBase(10);
- }
-}
-
-QString BreakpointData::toToolTip() const
-{
- QString rc;
- QTextStream str(&rc);
- str << "<html><body><table>"
- << "<tr><td>" << BreakHandler::tr("Marker File:")
- << "</td><td>" << QDir::toNativeSeparators(m_markerFileName) << "</td></tr>"
- << "<tr><td>" << BreakHandler::tr("Marker Line:")
- << "</td><td>" << m_markerLineNumber << "</td></tr>"
- << "<tr><td>" << BreakHandler::tr("Breakpoint Number:")
- << "</td><td>" << bpNumber << "</td></tr>"
- << "<tr><td>" << BreakHandler::tr("Breakpoint Type:")
- << "</td><td>"
- << (type == BreakpointType ? BreakHandler::tr("Breakpoint")
- : type == WatchpointType ? BreakHandler::tr("Watchpoint")
- : BreakHandler::tr("Unknown breakpoint type"))
- << "</td></tr>"
- << "<tr><td>" << BreakHandler::tr("State:")
- << "</td><td>" << bpState << "</td></tr>"
- << "</table><br><hr><table>"
- << "<tr><th>" << BreakHandler::tr("Property")
- << "</th><th>" << BreakHandler::tr("Requested")
- << "</th><th>" << BreakHandler::tr("Obtained") << "</th></tr>"
- << "<tr><td>" << BreakHandler::tr("Internal Number:")
- << "</td><td>&mdash;</td><td>" << bpNumber << "</td></tr>"
- << "<tr><td>" << BreakHandler::tr("File Name:")
- << "</td><td>" << QDir::toNativeSeparators(fileName) << "</td><td>" << QDir::toNativeSeparators(bpFileName) << "</td></tr>"
- << "<tr><td>" << BreakHandler::tr("Function Name:")
- << "</td><td>" << funcName << "</td><td>" << bpFuncName << "</td></tr>"
- << "<tr><td>" << BreakHandler::tr("Line Number:") << "</td><td>";
- if (lineNumber)
- str << lineNumber;
- str << "</td><td>";
- if (bpLineNumber)
- str << bpLineNumber;
- str << "</td></tr>"
- << "<tr><td>" << BreakHandler::tr("Breakpoint Address:")
- << "</td><td>";
- formatAddress(str, address);
- str << "</td><td>";
- formatAddress(str, bpAddress);
- str << "</td></tr>"
- << "<tr><td>" << BreakHandler::tr("Corrected Line Number:")
- << "</td><td>-</td><td>";
- if (bpCorrectedLineNumber > 0) {
- str << bpCorrectedLineNumber;
- } else {
- str << '-';
- }
- str << "</td></tr>"
- << "<tr><td>" << BreakHandler::tr("Condition:")
- << "</td><td>" << condition << "</td><td>" << bpCondition << "</td></tr>"
- << "<tr><td>" << BreakHandler::tr("Ignore Count:") << "</td><td>";
- if (ignoreCount)
- str << ignoreCount;
- str << "</td><td>";
- if (bpIgnoreCount)
- str << bpIgnoreCount;
- str << "</td></tr>"
- << "<tr><td>" << BreakHandler::tr("Thread Specification:")
- << "</td><td>" << threadSpec << "</td><td>" << bpThreadSpec << "</td></tr>"
- << "</table></body></html>";
- return rc;
+ // Some versions of gdb "beautify" the passed condition.
+ QByteArray s1 = condition;
+ s1.replace(' ', "");
+ QByteArray s2 = other;
+ s2.replace(' ', "");
+ return s1 == s2;
}
-bool BreakpointData::isLocatedAt(const QString &fileName_, int lineNumber_,
- bool useMarkerPosition) const
-{
- int line = useMarkerPosition ? m_markerLineNumber : lineNumber;
- return lineNumber_ == line && fileNameMatch(fileName_, m_markerFileName);
+QString BreakpointParameters::toString() const
+{
+ QString result;
+ QTextStream ts(&result);
+ ts << " FileName: " << fileName;
+ ts << " Condition: " << condition;
+ ts << " IgnoreCount: " << ignoreCount;
+ ts << " LineNumber: " << lineNumber;
+ ts << " Address: " << address;
+ ts << " FunctionName: " << functionName;
+ ts << " UseFullPath: " << useFullPath;
+ ts << " Tracepoint: " << tracepoint;
+ return result;
}
-bool BreakpointData::isSimilarTo(const BreakpointData *needle) const
-{
- //qDebug() << "COMPARING " << toString() << " WITH " << needle->toString();
-
- // Clear hit.
- if (bpNumber == needle->bpNumber
- && !bpNumber.isEmpty()
- && bpNumber.toInt() != 0)
- return true;
-
- // Clear miss.
- if (type != needle->type)
- return false;
-
- // We have numbers, but they are different.
- if (!bpNumber.isEmpty() && !needle->bpNumber.isEmpty()
- && !bpNumber.startsWith(needle->bpNumber)
- && !needle->bpNumber.startsWith(bpNumber))
- return false;
- if (address && needle->address && address == needle->address)
- return true;
-
- // At least at a position we were looking for.
- // FIXME: breaks multiple breakpoints at the same location
- if (!fileName.isEmpty()
- && fileNameMatch(fileName, needle->fileName)
- && lineNumber == needle->lineNumber)
- return true;
-
- // At least at a position we were looking for.
- // FIXME: breaks multiple breakpoints at the same location
- if (!fileName.isEmpty()
- && fileNameMatch(fileName, needle->bpFileName)
- && lineNumber == needle->bpLineNumber)
- return true;
-
- return false;
-}
+//////////////////////////////////////////////////////////////////
+//
+// BreakpointParameters
+//
+//////////////////////////////////////////////////////////////////
-bool BreakpointData::conditionsMatch() const
-{
- // Some versions of gdb "beautify" the passed condition.
- QString s1 = condition;
- s1.remove(QChar(' '));
- QString s2 = bpCondition;
- s2.remove(QChar(' '));
- return s1 == s2;
+BreakpointResponse::BreakpointResponse()
+ : number(0), pending(true), multiple(false), correctedLineNumber(0)
+{}
+
+QString BreakpointResponse::toString() const
+{
+ QString result;
+ QTextStream ts(&result);
+ ts << " Number: " << number;
+ ts << " Pending: " << pending;
+ ts << " FullName: " << fullName;
+ ts << " Multiple: " << multiple;
+ ts << " Extra: " << extra;
+ ts << " CorrectedLineNumber: " << correctedLineNumber;
+ return result + BreakpointParameters::toString();
}
-void BreakpointData::reinsertBreakpoint()
+void BreakpointResponse::fromParameters(const BreakpointParameters &p)
{
- QTC_ASSERT(m_handler, return);
- m_handler->reinsertBreakpoint(this);
+ BreakpointParameters::operator=(p);
+ number = 0;
+ fullName.clear();
+ multiple = false;
+ extra.clear();
+ correctedLineNumber = 0;
}
} // namespace Internal
} // namespace Debugger
-
-#include "breakpoint.moc"
diff --git a/src/plugins/debugger/breakpoint.h b/src/plugins/debugger/breakpoint.h
index 66c3ecfa7d..0f4c2bc454 100644
--- a/src/plugins/debugger/breakpoint.h
+++ b/src/plugins/debugger/breakpoint.h
@@ -34,15 +34,14 @@
#ifndef DEBUGGER_BREAKPOINT_H
#define DEBUGGER_BREAKPOINT_H
-#include <QtCore/QMetaType>
#include <QtCore/QList>
+#include <QtCore/QMetaType>
#include <QtCore/QString>
namespace Debugger {
namespace Internal {
-class BreakpointMarker;
-class BreakHandler;
+typedef quint64 BreakpointId;
//////////////////////////////////////////////////////////////////
//
@@ -50,98 +49,82 @@ class BreakHandler;
//
//////////////////////////////////////////////////////////////////
-class BreakpointData
+enum BreakpointType
{
-public:
- BreakpointData();
- ~BreakpointData();
-
- void removeMarker();
- void updateMarker();
- QString toToolTip() const;
- BreakHandler *handler() { return m_handler; }
- void reinsertBreakpoint();
- void clear(); // Delete all generated data.
-
- bool isLocatedAt(const QString &fileName, int lineNumber,
- bool useMarkerPosition) const;
- bool isSimilarTo(const BreakpointData *needle) const;
- bool conditionsMatch() const;
-
- // This copies only the static data.
- BreakpointData *clone() const;
-
- // Generic name for function to break on 'throw'
- static const char *throwFunction;
- static const char *catchFunction;
-
-private:
- // Intentionally unimplemented.
- // Making it copyable is tricky because of the markers.
- BreakpointData(const BreakpointData &);
- void operator=(const BreakpointData &);
-
- // Our owner
- BreakHandler *m_handler; // Not owned.
- friend class BreakHandler;
+ UnknownType,
+ BreakpointByFileAndLine,
+ BreakpointByFunction,
+ BreakpointByAddress,
+ BreakpointAtThrow,
+ BreakpointAtCatch,
+ BreakpointAtMain,
+ Watchpoint
+};
-public:
- enum Type { BreakpointType, WatchpointType };
+enum BreakpointState
+{
+ BreakpointNew,
+ BreakpointInsertRequested, // Inferior was told about bp, not ack'ed.
+ BreakpointInsertProceeding,
+ BreakpointChangeRequested,
+ BreakpointChangeProceeding,
+ BreakpointInserted,
+ BreakpointRemoveRequested,
+ BreakpointRemoveProceeding,
+ BreakpointDead
+};
+class BreakpointParameters
+{
+public:
+ explicit BreakpointParameters(BreakpointType = UnknownType);
+ bool equals(const BreakpointParameters &rhs) const;
+ bool conditionsMatch(const QByteArray &other) const;
+ bool isWatchpoint() const { return type == Watchpoint; }
+ // Enough for now.
+ bool isBreakpoint() const { return type != Watchpoint && !tracepoint; }
+ bool isTracepoint() const { return tracepoint; }
+ QString toString() const;
+
+ bool operator==(const BreakpointParameters &p) const { return equals(p); }
+ bool operator!=(const BreakpointParameters &p) const { return !equals(p); }
+
+ BreakpointType type; // Type of breakpoint.
bool enabled; // Should we talk to the debugger engine?
- bool pending; // Does the debugger engine know about us already?
- Type type; // Type of breakpoint.
-
- // This "user requested information" will get stored in the session.
+ bool useFullPath; // Should we use the full path when setting the bp?
QString fileName; // Short name of source file.
QByteArray condition; // Condition associated with breakpoint.
int ignoreCount; // Ignore count associated with breakpoint.
int lineNumber; // Line in source file.
quint64 address; // Address for watchpoints.
- QByteArray threadSpec; // Thread specification.
- // Name of containing function, special values:
- // BreakpointData::throwFunction, BreakpointData::catchFunction
- QString funcName;
- bool useFullPath; // Should we use the full path when setting the bp?
+ int threadSpec; // Thread specification.
+ QString functionName;
+ bool tracepoint;
+};
- // This is what gdb produced in response.
- QByteArray bpNumber; // Breakpoint number assigned by the debugger engine.
- QByteArray bpCondition; // Condition acknowledged by the debugger engine.
- int bpIgnoreCount; // Ignore count acknowledged by the debugger engine.
- QString bpFileName; // File name acknowledged by the debugger engine.
- QString bpFullName; // Full file name acknowledged by the debugger engine.
- int bpLineNumber; // Line number acknowledged by the debugger engine.
- int bpCorrectedLineNumber; // Acknowledged by the debugger engine.
- QByteArray bpThreadSpec; // Thread spec acknowledged by the debugger engine.
- QString bpFuncName; // Function name acknowledged by the debugger engine.
- quint64 bpAddress; // Address acknowledged by the debugger engine.
- bool bpMultiple; // Happens in constructors/gdb.
- bool bpEnabled; // Enable/disable command sent.
- QByteArray bpState; // gdb: <PENDING>, <MULTIPLE>
-
- void setMarkerFileName(const QString &fileName);
- QString markerFileName() const { return m_markerFileName; }
-
- void setMarkerLineNumber(int lineNumber);
- int markerLineNumber() const { return m_markerLineNumber; }
-
- bool isSetByFunction() const { return !funcName.isEmpty(); }
- bool isSetByFileAndLine() const { return !fileName.isEmpty(); }
-
-private:
- // Taken from either user input or gdb responses.
- QString m_markerFileName; // Used to locate the marker.
- int m_markerLineNumber;
-
- // Our red blob in the editor.
- BreakpointMarker *marker;
+
+// This is what debuggers produced in response to the attempt to
+// insert a breakpoint. The data might differ from the requested bits.
+class BreakpointResponse : public BreakpointParameters
+{
+public:
+ BreakpointResponse();
+ QString toString() const;
+
+public:
+ void fromParameters(const BreakpointParameters &p);
+
+ int number; // Breakpoint number assigned by the debugger engine.
+ bool pending; // Breakpoint not fully resolved.
+ QString fullName; // Full file name acknowledged by the debugger engine.
+ bool multiple; // Happens in constructors/gdb.
+ QByteArray extra; // gdb: <PENDING>, <MULTIPLE>
+ int correctedLineNumber;
};
-typedef QList<BreakpointData *> Breakpoints;
+typedef QList<BreakpointId> BreakpointIds;
} // namespace Internal
} // namespace Debugger
-Q_DECLARE_METATYPE(Debugger::Internal::BreakpointData *);
-
#endif // DEBUGGER_BREAKPOINT_H
diff --git a/src/plugins/debugger/breakpoint.ui b/src/plugins/debugger/breakpoint.ui
index 5842e70aca..be26fbd8f5 100644
--- a/src/plugins/debugger/breakpoint.ui
+++ b/src/plugins/debugger/breakpoint.ui
@@ -47,69 +47,97 @@
<widget class="QLineEdit" name="lineEditLineNumber"/>
</item>
<item row="3" column="1">
- <widget class="QCheckBox" name="checkBoxUseFullPath">
+ <widget class="QCheckBox" name="checkBoxEnabled">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="3" column="0">
+ <widget class="QLabel" name="labelEnabled">
+ <property name="text">
+ <string>Enabled:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QCheckBox" name="checkBoxUseFullPath">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0">
<widget class="QLabel" name="labelUseFullPath">
<property name="text">
<string>Use full path:</string>
</property>
</widget>
</item>
- <item row="4" column="0">
+ <item row="5" column="0">
<widget class="QLabel" name="labelAddress">
<property name="text">
<string>Address:</string>
</property>
</widget>
</item>
- <item row="4" column="1">
+ <item row="5" column="1">
<widget class="QLineEdit" name="lineEditAddress"/>
</item>
- <item row="5" column="0">
+ <item row="6" column="0">
<widget class="QLabel" name="labelFunction">
<property name="text">
<string>Function:</string>
</property>
</widget>
</item>
- <item row="5" column="1">
+ <item row="6" column="1">
<widget class="QLineEdit" name="lineEditFunction"/>
</item>
- <item row="6" column="0">
+ <item row="7" column="0">
<widget class="QLabel" name="labelCondition">
<property name="text">
<string>Condition:</string>
</property>
</widget>
</item>
- <item row="6" column="1">
+ <item row="7" column="1">
<widget class="QLineEdit" name="lineEditCondition"/>
</item>
- <item row="7" column="0">
+ <item row="8" column="0">
<widget class="QLabel" name="labelIgnoreCount">
<property name="text">
<string>Ignore count:</string>
</property>
</widget>
</item>
- <item row="7" column="1">
+ <item row="8" column="1">
<widget class="QLineEdit" name="lineEditIgnoreCount"/>
</item>
- <item row="8" column="0">
+ <item row="9" column="0">
<widget class="QLabel" name="labelThreadSpec">
<property name="text">
<string>Thread specification:</string>
</property>
</widget>
</item>
- <item row="8" column="1">
+ <item row="9" column="1">
<widget class="QLineEdit" name="lineEditThreadSpec"/>
</item>
+ <item row="10" column="1">
+ <widget class="QCheckBox" name="checkBoxTracepoint">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="10" column="0">
+ <widget class="QLabel" name="labelTracepoint">
+ <property name="text">
+ <string>Tracepoint only:</string>
+ </property>
+ </widget>
+ </item>
</layout>
</item>
<item>
diff --git a/src/plugins/debugger/breakpointmarker.cpp b/src/plugins/debugger/breakpointmarker.cpp
new file mode 100644
index 0000000000..c77751b478
--- /dev/null
+++ b/src/plugins/debugger/breakpointmarker.cpp
@@ -0,0 +1,85 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "breakpointmarker.h"
+#include "breakhandler.h"
+#include "debuggercore.h"
+
+#include <texteditor/basetextmark.h>
+#include <utils/qtcassert.h>
+
+#include <QtCore/QByteArray>
+#include <QtCore/QDebug>
+
+
+//////////////////////////////////////////////////////////////////
+//
+// BreakpointMarker
+//
+//////////////////////////////////////////////////////////////////
+
+
+namespace Debugger {
+namespace Internal {
+
+BreakpointMarker::BreakpointMarker(BreakpointId id,
+ const QString &fileName, int lineNumber)
+ : BaseTextMark(fileName, lineNumber), m_id(id)
+{
+ //qDebug() << "CREATE MARKER " << fileName << lineNumber;
+}
+
+BreakpointMarker::~BreakpointMarker()
+{
+ //qDebug() << "REMOVE MARKER ";
+}
+
+QIcon BreakpointMarker::icon() const
+{
+ return breakHandler()->icon(m_id);
+}
+
+void BreakpointMarker::updateBlock(const QTextBlock &)
+{
+ //qDebug() << "BREAKPOINT MARKER UPDATE BLOCK";
+}
+
+void BreakpointMarker::removedFromEditor()
+{
+ breakHandler()->removeBreakpoint(m_id);
+}
+
+void BreakpointMarker::updateLineNumber(int lineNumber)
+{
+ breakHandler()->updateLineNumberFromMarker(m_id, lineNumber);
+}
+
+} // namespace Internal
+} // namespace Debugger
+
diff --git a/src/plugins/debugger/breakpointmarker.h b/src/plugins/debugger/breakpointmarker.h
new file mode 100644
index 0000000000..9445aec87c
--- /dev/null
+++ b/src/plugins/debugger/breakpointmarker.h
@@ -0,0 +1,62 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 DEBUGGER_BREAKPOINTMARKER_H
+#define DEBUGGER_BREAKPOINTMARKER_H
+
+#include <QtCore/QString>
+#include <QtGui/QIcon>
+
+#include "breakpoint.h"
+#include "breakhandler.h"
+#include <texteditor/basetextmark.h>
+
+namespace Debugger {
+namespace Internal {
+
+// The red blob on the left side in the cpp editor.
+class BreakpointMarker : public TextEditor::BaseTextMark
+{
+ Q_OBJECT
+public:
+ BreakpointMarker(BreakpointId id, const QString &fileName, int lineNumber);
+ ~BreakpointMarker();
+ QIcon icon() const;
+ void updateBlock(const QTextBlock &);
+ void removedFromEditor();
+ void updateLineNumber(int lineNumber);
+private:
+ BreakpointId m_id;
+ friend class BreakHandler;
+};
+
+} // namespace Internal
+} // namespace Debugger
+
+#endif
diff --git a/src/plugins/debugger/breakwindow.cpp b/src/plugins/debugger/breakwindow.cpp
index 096a3aa6c3..6450c5948c 100644
--- a/src/plugins/debugger/breakwindow.cpp
+++ b/src/plugins/debugger/breakwindow.cpp
@@ -32,9 +32,10 @@
**************************************************************************/
#include "breakwindow.h"
+#include "breakhandler.h"
#include "debuggeractions.h"
-#include "debuggerconstants.h"
+#include "debuggercore.h"
#include "ui_breakpoint.h"
#include "ui_breakcondition.h"
@@ -46,112 +47,273 @@
#include <QtGui/QAction>
#include <QtGui/QHeaderView>
+#include <QtGui/QIntValidator>
+#include <QtGui/QItemSelectionModel>
#include <QtGui/QKeyEvent>
#include <QtGui/QMenu>
#include <QtGui/QResizeEvent>
-#include <QtGui/QItemSelectionModel>
#include <QtGui/QToolButton>
#include <QtGui/QTreeView>
-#include <QtGui/QIntValidator>
namespace Debugger {
namespace Internal {
+
///////////////////////////////////////////////////////////////////////
//
-// BreakpointDialog
+// BreakpointDialog: Show a dialog for editing breakpoints. Shows controls
+// for the file-and-line, function and address parameters depending on the
+// breakpoint type. The controls not applicable to the current type
+// (say function name for file-and-line) are disabled and cleared out.
+// However,the values are saved and restored once the respective mode
+// is again choosen, which is done using m_savedParameters and
+// setters/getters taking the parts mask enumeration parameter.
//
///////////////////////////////////////////////////////////////////////
-class BreakpointDialog : public QDialog, public Ui::BreakpointDialog
+class BreakpointDialog : public QDialog
{
Q_OBJECT
public:
explicit BreakpointDialog(QWidget *parent);
- bool showDialog(BreakpointData *data);
+ bool showDialog(BreakpointParameters *data);
+
+ void setParameters(const BreakpointParameters &data);
+ BreakpointParameters parameters() const;
public slots:
void typeChanged(int index);
+
+private:
+ enum DialogPart {
+ FileAndLinePart = 0x1,
+ FunctionPart = 0x2,
+ AddressPart = 0x4,
+ AllParts = FileAndLinePart|FunctionPart|AddressPart
+ };
+
+ void setPartsEnabled(unsigned partsMask, bool on);
+ void clearParts(unsigned partsMask);
+ void getParts(unsigned partsMask, BreakpointParameters *data) const;
+ void setParts(unsigned partsMask, const BreakpointParameters &data);
+
+ void setType(BreakpointType type);
+ BreakpointType type() const;
+
+ Ui::BreakpointDialog m_ui;
+ BreakpointParameters m_savedParameters;
+ BreakpointType m_previousType;
};
-BreakpointDialog::BreakpointDialog(QWidget *parent) : QDialog(parent)
+BreakpointDialog::BreakpointDialog(QWidget *parent)
+ : QDialog(parent), m_previousType(UnknownType)
+{
+ // Match BreakpointType (omitting unknown type).
+ m_ui.setupUi(this);
+ QStringList types;
+ types << tr("File and Line Number") << tr("Function Name") << tr("Address")
+ << tr("throw") << tr("catch") << tr("Function \"main()\"")
+ << tr("Address (Watchpoint)");
+ QTC_ASSERT(types.size() == Watchpoint, return; )
+ m_ui.comboBoxType->addItems(types);
+ m_ui.pathChooserFileName->setExpectedKind(Utils::PathChooser::File);
+ connect(m_ui.comboBoxType, SIGNAL(activated(int)), SLOT(typeChanged(int)));
+ m_ui.lineEditIgnoreCount->setValidator(
+ new QIntValidator(0, 2147483647, m_ui.lineEditIgnoreCount));
+}
+
+void BreakpointDialog::setType(BreakpointType type)
+{
+ const int comboIndex = type - 1; // Skip UnknownType.
+ if (comboIndex != m_ui.comboBoxType->currentIndex()) {
+ m_ui.comboBoxType->setCurrentIndex(comboIndex);
+ typeChanged(comboIndex);
+ }
+}
+
+BreakpointType BreakpointDialog::type() const
+{
+ const int type = m_ui.comboBoxType->currentIndex() + 1; // Skip unknown type.
+ return static_cast<BreakpointType>(type);
+}
+
+void BreakpointDialog::setParameters(const BreakpointParameters &data)
+{
+ m_savedParameters = data;
+ setType(data.type);
+ setParts(AllParts, data);
+ m_ui.lineEditCondition->setText(QString::fromUtf8(data.condition));
+ m_ui.lineEditIgnoreCount->setText(QString::number(data.ignoreCount));
+ m_ui.lineEditThreadSpec->
+ setText(BreakHandler::displayFromThreadSpec(data.threadSpec));
+}
+
+BreakpointParameters BreakpointDialog::parameters() const
+{
+ BreakpointParameters data(type());
+ getParts(AllParts, &data);
+ data.condition = m_ui.lineEditCondition->text().toUtf8();
+ data.ignoreCount = m_ui.lineEditIgnoreCount->text().toInt();
+ data.threadSpec =
+ BreakHandler::threadSpecFromDisplay(m_ui.lineEditThreadSpec->text());
+ return data;
+}
+
+void BreakpointDialog::setPartsEnabled(unsigned partsMask, bool e)
{
- setupUi(this);
- comboBoxType->insertItem(0, tr("File and Line Number"));
- comboBoxType->insertItem(1, tr("Function Name"));
- comboBoxType->insertItem(2, tr("Function \"main()\""));
- comboBoxType->insertItem(3, tr("Address"));
- pathChooserFileName->setExpectedKind(Utils::PathChooser::File);
- connect(comboBoxType, SIGNAL(activated(int)), SLOT(typeChanged(int)));
- lineEditIgnoreCount->setValidator(new QIntValidator(0, 2147483647, lineEditIgnoreCount));
+ if (partsMask & FileAndLinePart) {
+ m_ui.labelFileName->setEnabled(e);
+ m_ui.pathChooserFileName->setEnabled(e);
+ m_ui.labelLineNumber->setEnabled(e);
+ m_ui.lineEditLineNumber->setEnabled(e);
+ m_ui.labelUseFullPath->setEnabled(e);
+ m_ui.checkBoxUseFullPath->setEnabled(e);
+ }
+
+ if (partsMask & FunctionPart) {
+ m_ui.labelFunction->setEnabled(e);
+ m_ui.lineEditFunction->setEnabled(e);
+ }
+
+ if (partsMask & AddressPart) {
+ m_ui.labelAddress->setEnabled(e);
+ m_ui.lineEditAddress->setEnabled(e);
+ }
}
-bool BreakpointDialog::showDialog(BreakpointData *data)
+void BreakpointDialog::clearParts(unsigned partsMask)
{
- pathChooserFileName->setPath(data->fileName);
- lineEditLineNumber->setText(QString::number(data->lineNumber));
- lineEditFunction->setText(data->funcName);
- lineEditCondition->setText(QString::fromUtf8(data->condition));
- lineEditIgnoreCount->setText(QString::number(data->ignoreCount));
- checkBoxUseFullPath->setChecked(data->useFullPath);
- lineEditThreadSpec->setText(QString::fromUtf8(data->threadSpec));
- if (data->address)
- lineEditAddress->setText(QString::fromAscii("0x%1").arg(data->address, 0, 16));
- int initialType = 0;
- if (!data->funcName.isEmpty())
- initialType = data->funcName == QLatin1String("main") ? 2 : 1;
- if (data->address)
- initialType = 3;
- typeChanged(initialType);
+ if (partsMask & FileAndLinePart) {
+ m_ui.pathChooserFileName->setPath(QString());
+ m_ui.lineEditLineNumber->clear();
+ m_ui.checkBoxUseFullPath->setChecked(false);
+ }
+
+ if (partsMask & FunctionPart)
+ m_ui.lineEditFunction->clear();
+
+ if (partsMask & AddressPart)
+ m_ui.lineEditAddress->clear();
+}
+
+void BreakpointDialog::getParts(unsigned partsMask, BreakpointParameters *data) const
+{
+ data->enabled = m_ui.checkBoxEnabled->isChecked();
+ data->tracepoint = m_ui.checkBoxTracepoint->isChecked();
+
+ if (partsMask & FileAndLinePart) {
+ data->lineNumber = m_ui.lineEditLineNumber->text().toInt();
+ data->useFullPath = m_ui.checkBoxUseFullPath->isChecked();
+ data->fileName = m_ui.pathChooserFileName->path();
+ }
+ if (partsMask & FunctionPart)
+ data->functionName = m_ui.lineEditFunction->text();
+
+ if (partsMask & AddressPart)
+ data->address = m_ui.lineEditAddress->text().toULongLong(0, 0);
+}
+
+void BreakpointDialog::setParts(unsigned mask, const BreakpointParameters &data)
+{
+ m_ui.checkBoxEnabled->setChecked(data.enabled);
+ m_ui.checkBoxUseFullPath->setChecked(data.useFullPath);
+
+ if (mask & FileAndLinePart) {
+ m_ui.pathChooserFileName->setPath(data.fileName);
+ m_ui.lineEditLineNumber->setText(QString::number(data.lineNumber));
+ m_ui.checkBoxTracepoint->setChecked(data.tracepoint);
+ }
+ if (mask & FunctionPart)
+ m_ui.lineEditFunction->setText(data.functionName);
+
+ if (mask & AddressPart) {
+ if (data.address) {
+ m_ui.lineEditAddress->setText(
+ QString::fromAscii("0x%1").arg(data.address, 0, 16));
+ } else {
+ m_ui.lineEditAddress->clear();
+ }
+ }
+}
+
+void BreakpointDialog::typeChanged(int)
+{
+ BreakpointType previousType = m_previousType;
+ const BreakpointType newType = type();
+ m_previousType = newType;
+ // Save current state.
+ switch(previousType) {
+ case UnknownType:
+ break;
+ case BreakpointByFileAndLine:
+ getParts(FileAndLinePart, &m_savedParameters);
+ break;
+ case BreakpointByFunction:
+ getParts(FunctionPart, &m_savedParameters);
+ break;
+ case BreakpointAtThrow:
+ case BreakpointAtCatch:
+ case BreakpointAtMain:
+ break;
+ case BreakpointByAddress:
+ case Watchpoint:
+ getParts(AddressPart, &m_savedParameters);
+ break;
+ }
+
+ // Enable and set up new state from saved values.
+ switch (newType) {
+ case UnknownType:
+ break;
+ case BreakpointByFileAndLine:
+ setParts(FileAndLinePart, m_savedParameters);
+ setPartsEnabled(FileAndLinePart, true);
+ clearParts(FunctionPart|AddressPart);
+ setPartsEnabled(FunctionPart|AddressPart, false);
+ break;
+ case BreakpointByFunction:
+ setParts(FunctionPart, m_savedParameters);
+ setPartsEnabled(FunctionPart, true);
+ clearParts(FileAndLinePart|AddressPart);
+ setPartsEnabled(FileAndLinePart|AddressPart, false);
+ break;
+ case BreakpointAtThrow:
+ case BreakpointAtCatch:
+ clearParts(AllParts);
+ setPartsEnabled(AllParts, false);
+ break;
+ case BreakpointAtMain:
+ m_ui.lineEditFunction->setText(QLatin1String("main")); // Just for display
+ clearParts(FileAndLinePart|AddressPart);
+ setPartsEnabled(AllParts, false);
+ break;
+ case BreakpointByAddress:
+ case Watchpoint:
+ setParts(AddressPart, m_savedParameters);
+ setPartsEnabled(AddressPart, true);
+ clearParts(FileAndLinePart|FunctionPart);
+ setPartsEnabled(FileAndLinePart|FunctionPart, false);
+ break;
+ }
+}
+
+bool BreakpointDialog::showDialog(BreakpointParameters *data)
+{
+ setParameters(*data);
if (exec() != QDialog::Accepted)
return false;
// Check if changed.
- const int newLineNumber = lineEditLineNumber->text().toInt();
- const bool newUseFullPath = checkBoxUseFullPath->isChecked();
- const quint64 newAddress = lineEditAddress->text().toULongLong(0, 0);
- const QString newFunc = lineEditFunction->text();
- const QString newFileName = pathChooserFileName->path();
- const QByteArray newCondition = lineEditCondition->text().toUtf8();
- const int newIgnoreCount = lineEditIgnoreCount->text().toInt();
- const QByteArray newThreadSpec = lineEditThreadSpec->text().toUtf8();
- if (newLineNumber == data->lineNumber && newUseFullPath == data->useFullPath
- && newAddress == data->address && newFunc == data->funcName
- && newFileName == data->fileName && newCondition == data->condition
- && newIgnoreCount == data->ignoreCount && newThreadSpec == data->threadSpec)
- return false; // Unchanged -> Cancel.
-
- data->address = newAddress;
- data->funcName = newFunc;
- data->useFullPath = newUseFullPath;
- data->fileName = newFileName;
- data->lineNumber = newLineNumber;
- data->condition = newCondition;
- data->ignoreCount = newIgnoreCount;
- data->threadSpec = newThreadSpec;
+ const BreakpointParameters newParameters = parameters();
+ if (data->equals(newParameters))
+ return false;
+
+ *data = newParameters;
return true;
}
-void BreakpointDialog::typeChanged(int index)
-{
- const bool isLineVisible = index == 0;
- const bool isFunctionVisible = index == 1;
- const bool isAddressVisible = index == 3;
- labelFileName->setEnabled(isLineVisible);
- pathChooserFileName->setEnabled(isLineVisible);
- labelLineNumber->setEnabled(isLineVisible);
- lineEditLineNumber->setEnabled(isLineVisible);
- labelUseFullPath->setEnabled(isLineVisible);
- checkBoxUseFullPath->setEnabled(isLineVisible);
- labelFunction->setEnabled(isFunctionVisible);
- lineEditFunction->setEnabled(isFunctionVisible);
- labelAddress->setEnabled(isAddressVisible);
- lineEditAddress->setEnabled(isAddressVisible);
- if (index == 2)
- lineEditFunction->setText(QLatin1String("main"));
-}
///////////////////////////////////////////////////////////////////////
//
@@ -164,7 +326,7 @@ BreakWindow::BreakWindow(QWidget *parent)
{
m_alwaysResizeColumnsToContents = false;
- QAction *act = theDebuggerAction(UseAlternatingRowColors);
+ QAction *act = debuggerCore()->action(UseAlternatingRowColors);
setFrameStyle(QFrame::NoFrame);
setAttribute(Qt::WA_MacShowFocusRect, false);
setWindowTitle(tr("Breakpoints"));
@@ -175,15 +337,12 @@ BreakWindow::BreakWindow(QWidget *parent)
setSelectionMode(QAbstractItemView::ExtendedSelection);
connect(this, SIGNAL(activated(QModelIndex)),
- this, SLOT(rowActivated(QModelIndex)));
+ SLOT(rowActivated(QModelIndex)));
connect(act, SIGNAL(toggled(bool)),
- this, SLOT(setAlternatingRowColorsHelper(bool)));
- connect(theDebuggerAction(UseAddressInBreakpointsView), SIGNAL(toggled(bool)),
- this, SLOT(showAddressColumn(bool)));
-}
-
-BreakWindow::~BreakWindow()
-{
+ SLOT(setAlternatingRowColorsHelper(bool)));
+ connect(debuggerCore()->action(UseAddressInBreakpointsView),
+ SIGNAL(toggled(bool)),
+ SLOT(showAddressColumn(bool)));
}
void BreakWindow::showAddressColumn(bool on)
@@ -191,15 +350,6 @@ void BreakWindow::showAddressColumn(bool on)
setColumnHidden(7, !on);
}
-static QModelIndexList normalizeIndexes(const QModelIndexList &list)
-{
- QModelIndexList res;
- foreach (const QModelIndex &index, list)
- if (index.column() == 0)
- res.append(index);
- return res;
-}
-
void BreakWindow::keyPressEvent(QKeyEvent *ev)
{
if (ev->key() == Qt::Key_Delete) {
@@ -207,8 +357,11 @@ void BreakWindow::keyPressEvent(QKeyEvent *ev)
QTC_ASSERT(sm, return);
QModelIndexList si = sm->selectedIndexes();
if (si.isEmpty())
- si.append(currentIndex().sibling(currentIndex().row(), 0));
- deleteBreakpoints(normalizeIndexes(si));
+ si.append(currentIndex());
+ const BreakpointIds ids = breakHandler()->findBreakpointsByIndex(si);
+ int row = qMin(model()->rowCount() - ids.size() - 1, currentIndex().row());
+ deleteBreakpoints(ids);
+ setCurrentIndex(si.at(0).sibling(row, 0));
}
QTreeView::keyPressEvent(ev);
}
@@ -221,43 +374,55 @@ void BreakWindow::resizeEvent(QResizeEvent *ev)
void BreakWindow::mouseDoubleClickEvent(QMouseEvent *ev)
{
QModelIndex indexUnderMouse = indexAt(ev->pos());
- if (indexUnderMouse.isValid() && indexUnderMouse.column() >= 4)
- editBreakpoints(QModelIndexList() << indexUnderMouse);
+ if (indexUnderMouse.isValid() && indexUnderMouse.column() >= 4) {
+ BreakpointId id = breakHandler()->findBreakpointByIndex(indexUnderMouse);
+ editBreakpoints(BreakpointIds() << id);
+ }
QTreeView::mouseDoubleClickEvent(ev);
}
+void BreakWindow::setModel(QAbstractItemModel *model)
+{
+ QTreeView::setModel(model);
+ resizeColumnToContents(0); // Number
+ resizeColumnToContents(3); // Line
+ resizeColumnToContents(6); // Ignore count
+}
+
void BreakWindow::contextMenuEvent(QContextMenuEvent *ev)
{
QMenu menu;
QItemSelectionModel *sm = selectionModel();
QTC_ASSERT(sm, return);
- QModelIndexList si = sm->selectedIndexes();
+ QModelIndexList selectedIndices = sm->selectedIndexes();
QModelIndex indexUnderMouse = indexAt(ev->pos());
- if (si.isEmpty() && indexUnderMouse.isValid())
- si.append(indexUnderMouse.sibling(indexUnderMouse.row(), 0));
- si = normalizeIndexes(si);
+ if (selectedIndices.isEmpty() && indexUnderMouse.isValid())
+ selectedIndices.append(indexUnderMouse);
+
+ BreakHandler *handler = breakHandler();
+ BreakpointIds selectedIds = handler->findBreakpointsByIndex(selectedIndices);
const int rowCount = model()->rowCount();
- const unsigned engineCapabilities =
- model()->data(QModelIndex(), EngineCapabilitiesRole).toUInt();
+ const unsigned engineCapabilities = BreakOnThrowAndCatchCapability;
+ // FIXME BP: model()->data(QModelIndex(), EngineCapabilitiesRole).toUInt();
QAction *deleteAction = new QAction(tr("Delete Breakpoint"), &menu);
- deleteAction->setEnabled(si.size() > 0);
+ deleteAction->setEnabled(!selectedIds.isEmpty());
QAction *deleteAllAction = new QAction(tr("Delete All Breakpoints"), &menu);
deleteAllAction->setEnabled(model()->rowCount() > 0);
// Delete by file: Find indices of breakpoints of the same file.
QAction *deleteByFileAction = 0;
- QList<int> breakPointsOfFile;
+ BreakpointIds breakpointsInFile;
if (indexUnderMouse.isValid()) {
const QModelIndex index = indexUnderMouse.sibling(indexUnderMouse.row(), 2);
- const QString file = model()->data(index).toString();
+ const QString file = index.data().toString();
if (!file.isEmpty()) {
for (int i = 0; i < rowCount; i++)
- if (model()->data(model()->index(i, 2)).toString() == file)
- breakPointsOfFile.push_back(i);
- if (breakPointsOfFile.size() > 1) {
+ if (index.data().toString() == file)
+ breakpointsInFile.append(handler->findBreakpointByIndex(index));
+ if (breakpointsInFile.size() > 1) {
deleteByFileAction =
new QAction(tr("Delete Breakpoints of \"%1\"").arg(file), &menu);
deleteByFileAction->setEnabled(true);
@@ -280,26 +445,23 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev)
QAction *editBreakpointAction =
new QAction(tr("Edit Breakpoint..."), &menu);
- editBreakpointAction->setEnabled(si.size() > 0);
+ editBreakpointAction->setEnabled(!selectedIds.isEmpty());
- int threadId = model()->data(QModelIndex(), CurrentThreadIdRole).toInt();
+ int threadId = 0;
+ // FIXME BP: m_engine->threadsHandler()->currentThreadId();
QString associateTitle = threadId == -1
? tr("Associate Breakpoint With All Threads")
: tr("Associate Breakpoint With Thread %1").arg(threadId);
QAction *associateBreakpointAction = new QAction(associateTitle, &menu);
- associateBreakpointAction->setEnabled(si.size() > 0);
+ associateBreakpointAction->setEnabled(!selectedIds.isEmpty());
QAction *synchronizeAction =
new QAction(tr("Synchronize Breakpoints"), &menu);
- synchronizeAction->setEnabled(
- model()->data(QModelIndex(), EngineActionsEnabledRole).toBool());
+ synchronizeAction->setEnabled(debuggerCore()->hasSnapshots());
- QModelIndex idx0 = (si.size() ? si.front() : QModelIndex());
- QModelIndex idx2 = idx0.sibling(idx0.row(), 2);
- bool enabled = si.isEmpty()
- || idx0.data(BreakpointEnabledRole).toBool();
+ bool enabled = selectedIds.isEmpty() || handler->isEnabled(selectedIds.at(0));
- const QString str5 = si.size() > 1
+ const QString str5 = selectedIds.size() > 1
? enabled
? tr("Disable Selected Breakpoints")
: tr("Enable Selected Breakpoints")
@@ -307,7 +469,7 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev)
? tr("Disable Breakpoint")
: tr("Enable Breakpoint");
QAction *toggleEnabledAction = new QAction(str5, &menu);
- toggleEnabledAction->setEnabled(si.size() > 0);
+ toggleEnabledAction->setEnabled(!selectedIds.isEmpty());
QAction *addBreakpointAction =
new QAction(tr("Add Breakpoint..."), this);
@@ -323,7 +485,7 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev)
menu.addAction(toggleEnabledAction);
menu.addSeparator();
menu.addAction(deleteAllAction);
- menu.addAction(deleteByFileAction);
+ //menu.addAction(deleteByFileAction);
menu.addSeparator();
menu.addAction(synchronizeAction);
if (engineCapabilities & BreakOnThrowAndCatchCapability) {
@@ -332,106 +494,79 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev)
menu.addAction(breakAtCatchAction);
}
menu.addSeparator();
- menu.addAction(theDebuggerAction(UseToolTipsInBreakpointsView));
- menu.addAction(theDebuggerAction(UseAddressInBreakpointsView));
+ menu.addAction(debuggerCore()->action(UseToolTipsInBreakpointsView));
+ menu.addAction(debuggerCore()->action(UseAddressInBreakpointsView));
menu.addAction(adjustColumnAction);
menu.addAction(alwaysAdjustAction);
menu.addSeparator();
- menu.addAction(theDebuggerAction(SettingsDialog));
+ menu.addAction(debuggerCore()->action(SettingsDialog));
QAction *act = menu.exec(ev->globalPos());
- if (act == deleteAction) {
- deleteBreakpoints(si);
- } else if (act == deleteAllAction) {
- QList<int> allRows;
- for (int i = 0; i < rowCount; i++)
- allRows.push_back(i);
- deleteBreakpoints(allRows);
- } else if (act == deleteByFileAction)
- deleteBreakpoints(breakPointsOfFile);
+ if (act == deleteAction)
+ deleteBreakpoints(selectedIds);
+ else if (act == deleteAllAction)
+ deleteBreakpoints(handler->allBreakpointIds());
+ else if (act == deleteByFileAction)
+ deleteBreakpoints(breakpointsInFile);
else if (act == adjustColumnAction)
resizeColumnsToContents();
else if (act == alwaysAdjustAction)
setAlwaysResizeColumnsToContents(!m_alwaysResizeColumnsToContents);
else if (act == editBreakpointAction)
- editBreakpoints(si);
+ editBreakpoints(selectedIds);
else if (act == associateBreakpointAction)
- associateBreakpoint(si, threadId);
+ associateBreakpoint(selectedIds, threadId);
else if (act == synchronizeAction)
- setModelData(RequestSynchronizeBreakpointsRole);
+ ; //synchronizeBreakpoints();
else if (act == toggleEnabledAction)
- setBreakpointsEnabled(si, !enabled);
+ setBreakpointsEnabled(selectedIds, !enabled);
else if (act == addBreakpointAction)
addBreakpoint();
else if (act == breakAtThrowAction)
- setModelData(RequestBreakByFunctionRole, QLatin1String(BreakpointData::throwFunction));
+ handler->appendBreakpoint(BreakpointParameters(BreakpointAtThrow));
else if (act == breakAtCatchAction)
- setModelData(RequestBreakByFunctionRole, QLatin1String(BreakpointData::catchFunction));
-}
-
-void BreakWindow::setBreakpointsEnabled(const QModelIndexList &list, bool enabled)
-{
- foreach (const QModelIndex &index, list)
- setModelData(BreakpointEnabledRole, enabled, index);
- setModelData(RequestSynchronizeBreakpointsRole);
-}
-
-void BreakWindow::setBreakpointsFullPath(const QModelIndexList &list, bool fullpath)
-{
- foreach (const QModelIndex &index, list)
- setModelData(BreakpointUseFullPathRole, fullpath, index);
- setModelData(RequestSynchronizeBreakpointsRole);
+ handler->appendBreakpoint(BreakpointParameters(BreakpointAtCatch));
}
-void BreakWindow::deleteBreakpoints(const QModelIndexList &indexes)
+void BreakWindow::setBreakpointsEnabled(const BreakpointIds &ids, bool enabled)
{
- QTC_ASSERT(!indexes.isEmpty(), return);
- QList<int> list;
- foreach (const QModelIndex &index, indexes)
- list.append(index.row());
- deleteBreakpoints(list);
+ BreakHandler *handler = breakHandler();
+ foreach (const BreakpointId id, ids)
+ handler->setEnabled(id, enabled);
}
-void BreakWindow::deleteBreakpoints(QList<int> list)
+void BreakWindow::deleteBreakpoints(const BreakpointIds &ids)
{
- if (list.empty())
- return;
- const int firstRow = list.front();
- qSort(list.begin(), list.end());
- for (int i = list.size(); --i >= 0; )
- setModelData(RequestRemoveBreakpointByIndexRole, list.at(i));
-
- const int row = qMin(firstRow, model()->rowCount() - 1);
- if (row >= 0)
- setCurrentIndex(model()->index(row, 0));
- setModelData(RequestSynchronizeBreakpointsRole);
+ BreakHandler *handler = breakHandler();
+ foreach (const BreakpointId id, ids)
+ handler->removeBreakpoint(id);
}
-bool BreakWindow::editBreakpoint(BreakpointData *data, QWidget *parent)
+void BreakWindow::editBreakpoint(BreakpointId id, QWidget *parent)
{
BreakpointDialog dialog(parent);
- return dialog.showDialog(data);
+ BreakpointParameters data = breakHandler()->breakpointData(id);
+ if (dialog.showDialog(&data))
+ breakHandler()->setBreakpointData(id, data);
}
void BreakWindow::addBreakpoint()
{
- BreakpointData *data = new BreakpointData();
- if (editBreakpoint(data, this))
- setModelData(RequestBreakpointRole, QVariant::fromValue(data));
- else
- delete data;
+ BreakpointParameters data(BreakpointByFileAndLine);
+ BreakpointDialog dialog(this);
+ if (dialog.showDialog(&data))
+ breakHandler()->appendBreakpoint(data);
}
-void BreakWindow::editBreakpoints(const QModelIndexList &list)
+void BreakWindow::editBreakpoints(const BreakpointIds &ids)
{
- QTC_ASSERT(!list.isEmpty(), return);
- if (list.size() == 1) {
- const QVariant dataV = model()->data(list.at(0), BreakpointRole);
- QTC_ASSERT(qVariantCanConvert<BreakpointData *>(dataV), return );
- BreakpointData *data = qvariant_cast<BreakpointData *>(dataV);
- if (editBreakpoint(data, this))
- data->reinsertBreakpoint();
+ QTC_ASSERT(!ids.isEmpty(), return);
+
+ const BreakpointId id = ids.at(0);
+
+ if (ids.size() == 1) {
+ editBreakpoint(id, this);
return;
}
@@ -440,14 +575,14 @@ void BreakWindow::editBreakpoints(const QModelIndexList &list)
Ui::BreakCondition ui;
ui.setupUi(&dlg);
dlg.setWindowTitle(tr("Edit Breakpoint Properties"));
- ui.lineEditIgnoreCount->setValidator(new QIntValidator(0, 2147483647, ui.lineEditIgnoreCount));
+ ui.lineEditIgnoreCount->setValidator(
+ new QIntValidator(0, 2147483647, ui.lineEditIgnoreCount));
- const QModelIndex idx = list.front();
- QAbstractItemModel *m = model();
-
- const QString oldCondition = m->data(idx, BreakpointConditionRole).toString();
- const QString oldIgnoreCount = m->data(idx, BreakpointIgnoreCountRole).toString();
- const QString oldThreadSpec = m->data(idx, BreakpointThreadSpecRole).toString();
+ BreakHandler *handler = breakHandler();
+ const QString oldCondition = QString::fromLatin1(handler->condition(id));
+ const QString oldIgnoreCount = QString::number(handler->ignoreCount(id));
+ const QString oldThreadSpec =
+ BreakHandler::displayFromThreadSpec(handler->threadSpec(id));
ui.lineEditCondition->setText(oldCondition);
ui.lineEditIgnoreCount->setText(oldIgnoreCount);
@@ -460,27 +595,23 @@ void BreakWindow::editBreakpoints(const QModelIndexList &list)
const QString newIgnoreCount = ui.lineEditIgnoreCount->text();
const QString newThreadSpec = ui.lineEditThreadSpec->text();
- // Unchanged -> cancel
if (newCondition == oldCondition && newIgnoreCount == oldIgnoreCount
&& newThreadSpec == oldThreadSpec)
return;
- foreach (const QModelIndex &idx, list) {
- m->setData(idx, newCondition, BreakpointConditionRole);
- m->setData(idx, newIgnoreCount, BreakpointIgnoreCountRole);
- m->setData(idx, newThreadSpec, BreakpointThreadSpecRole);
+ foreach (const BreakpointId id, ids) {
+ handler->setCondition(id, newCondition.toLatin1());
+ handler->setIgnoreCount(id, newIgnoreCount.toInt());
+ handler->setThreadSpec(id,
+ BreakHandler::threadSpecFromDisplay(newThreadSpec));
}
- setModelData(RequestSynchronizeBreakpointsRole);
}
-void BreakWindow::associateBreakpoint(const QModelIndexList &list, int threadId)
+void BreakWindow::associateBreakpoint(const BreakpointIds &ids, int threadId)
{
- QString str;
- if (threadId != -1)
- str = QString::number(threadId);
- foreach (const QModelIndex &index, list)
- setModelData(BreakpointThreadSpecRole, str, index);
- setModelData(RequestSynchronizeBreakpointsRole);
+ BreakHandler *handler = breakHandler();
+ foreach (const BreakpointId id, ids)
+ handler->setThreadSpec(id, threadId);
}
void BreakWindow::resizeColumnsToContents()
@@ -500,17 +631,9 @@ void BreakWindow::setAlwaysResizeColumnsToContents(bool on)
void BreakWindow::rowActivated(const QModelIndex &index)
{
- setModelData(RequestActivateBreakpointRole, index.row());
+ breakHandler()->gotoLocation(breakHandler()->findBreakpointByIndex(index));
}
-void BreakWindow::setModelData
- (int role, const QVariant &value, const QModelIndex &index)
-{
- QTC_ASSERT(model(), return);
- model()->setData(index, value, role);
-}
-
-
} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/breakwindow.h b/src/plugins/debugger/breakwindow.h
index 6d35efd28f..db3b77df68 100644
--- a/src/plugins/debugger/breakwindow.h
+++ b/src/plugins/debugger/breakwindow.h
@@ -34,7 +34,7 @@
#ifndef DEBUGGER_BREAKWINDOW_H
#define DEBUGGER_BREAKWINDOW_H
-#include "breakpoint.h"
+#include "breakhandler.h"
#include <QtGui/QTreeView>
@@ -47,9 +47,9 @@ class BreakWindow : public QTreeView
public:
explicit BreakWindow(QWidget *parent = 0);
- ~BreakWindow();
- static bool editBreakpoint(BreakpointData *data, QWidget *parent = 0);
+ static void editBreakpoint(BreakpointId id, QWidget *parent);
+ void setModel(QAbstractItemModel *model);
private slots:
void resizeColumnsToContents();
@@ -65,16 +65,11 @@ private:
void keyPressEvent(QKeyEvent *ev);
void mouseDoubleClickEvent(QMouseEvent *ev);
- void deleteBreakpoints(const QModelIndexList &list);
- void deleteBreakpoints(QList<int> rows);
+ void deleteBreakpoints(const BreakpointIds &ids);
void addBreakpoint();
- void editBreakpoints(const QModelIndexList &list);
- void associateBreakpoint(const QModelIndexList &list, int thread);
- void setBreakpointsEnabled(const QModelIndexList &list, bool enabled);
- void setBreakpointsFullPath(const QModelIndexList &list, bool fullpath);
-
- void setModelData(int role, const QVariant &value = QVariant(),
- const QModelIndex &index = QModelIndex());
+ void editBreakpoints(const BreakpointIds &ids);
+ void associateBreakpoint(const BreakpointIds &ids, int thread);
+ void setBreakpointsEnabled(const BreakpointIds &ids, bool enabled);
bool m_alwaysResizeColumnsToContents;
};
diff --git a/src/plugins/debugger/cdb/cdb.pri b/src/plugins/debugger/cdb/cdb.pri
index d0901fec59..59652c3856 100644
--- a/src/plugins/debugger/cdb/cdb.pri
+++ b/src/plugins/debugger/cdb/cdb.pri
@@ -16,7 +16,6 @@ HEADERS += \
$$PWD/cdboptions.h \
$$PWD/cdboptionspage.h \
$$PWD/cdbdumperhelper.h \
- $$PWD/cdbsymbolpathlisteditor.h \
$$PWD/cdbexceptionutils.h
SOURCES += \
@@ -31,7 +30,6 @@ SOURCES += \
$$PWD/cdboptions.cpp \
$$PWD/cdboptionspage.cpp \
$$PWD/cdbdumperhelper.cpp \
- $$PWD/cdbsymbolpathlisteditor.cpp \
$$PWD/cdbexceptionutils.cpp
FORMS += $$PWD/cdboptionspagewidget.ui
diff --git a/src/plugins/debugger/cdb/cdbassembler.cpp b/src/plugins/debugger/cdb/cdbassembler.cpp
index 0ee43a6a49..61d3a15029 100644
--- a/src/plugins/debugger/cdb/cdbassembler.cpp
+++ b/src/plugins/debugger/cdb/cdbassembler.cpp
@@ -83,6 +83,35 @@ Registers getRegisters(CIDebugControl *ctl,
return registers;
}
+bool setRegisterValueU64(CIDebugRegisters *ireg, unsigned index, quint64 value, QString *errorMessage)
+{
+ DEBUG_VALUE debugValueSet;
+ debugValueSet.Type = DEBUG_VALUE_INT64;
+ debugValueSet.I64 = value;
+ const HRESULT hr = ireg->SetValue(index, &debugValueSet);
+ if (FAILED(hr)) {
+ *errorMessage= CdbCore::msgComFailed("SetValue", hr);
+ false;
+ }
+ return true;
+}
+
+bool setRegisterValueU64(CIDebugControl *ctl,
+ CIDebugRegisters *ireg,
+ const QString &name, quint64 value,
+ QString *errorMessage)
+{
+ // Look up register by name
+ const Registers registers = getRegisters(ctl, ireg, errorMessage);
+ const int regCount = registers.size();
+ for (int r = 0; r < regCount; r++)
+ if (registers.at(r).name == name)
+ return setRegisterValueU64(ireg, r, value, errorMessage);
+ *errorMessage = QString::fromLatin1("Unable to set register '%1' to %2: No such register")
+ .arg(name).arg(value);
+ return false;
+}
+
/* Output parser for disassembler lines: Parse a disassembler line:
* \code
module!class::foo:
@@ -196,17 +225,17 @@ void DisassemblerOutputParser::parse(const QStringList &l)
}
}
-bool dissassemble(CdbCore::CoreEngine *engine,
- ULONG64 offset,
- unsigned long beforeLines,
- unsigned long afterLines,
- QTextStream &str,
- QString *errorMessage)
+bool disassemble(CdbCore::CoreEngine *engine,
+ ULONG64 offset,
+ unsigned long beforeLines,
+ unsigned long afterLines,
+ QTextStream &str,
+ QString *errorMessage)
{
if (debugCDB)
qDebug() << Q_FUNC_INFO << offset;
QString lines;
- if (!engine->dissassemble(offset, beforeLines, afterLines, &lines, errorMessage))
+ if (!engine->disassemble(offset, beforeLines, afterLines, &lines, errorMessage))
return false;
DisassemblerOutputParser parser(str);
parser.parse(lines.split(QLatin1Char('\n')));
diff --git a/src/plugins/debugger/cdb/cdbassembler.h b/src/plugins/debugger/cdb/cdbassembler.h
index fdea568e3b..2e8ee5db41 100644
--- a/src/plugins/debugger/cdb/cdbassembler.h
+++ b/src/plugins/debugger/cdb/cdbassembler.h
@@ -58,12 +58,18 @@ Registers getRegisters(CIDebugControl *ctl,
QString *errorMessage,
int base = 10 /* 16 for hex, etc */);
-bool dissassemble(CdbCore::CoreEngine *engine,
- ULONG64 offset,
- unsigned long beforeLines,
- unsigned long afterLines,
- QTextStream &str,
- QString *errorMessage);
+bool setRegisterValueU64(CIDebugRegisters *ireg, unsigned index, quint64 value,
+ QString *errorMessage);
+
+bool setRegisterValueU64(CIDebugControl *ctl, CIDebugRegisters *ireg, const QString &name,
+ quint64 value, QString *errorMessage);
+
+bool disassemble(CdbCore::CoreEngine *engine,
+ ULONG64 offset,
+ unsigned long beforeLines,
+ unsigned long afterLines,
+ QTextStream &str,
+ QString *errorMessage);
} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/cdb/cdbbreakpoint.cpp b/src/plugins/debugger/cdb/cdbbreakpoint.cpp
index f5d2b89111..fbf6518a13 100644
--- a/src/plugins/debugger/cdb/cdbbreakpoint.cpp
+++ b/src/plugins/debugger/cdb/cdbbreakpoint.cpp
@@ -32,33 +32,31 @@
**************************************************************************/
#include "cdbbreakpoint.h"
+#include "cdbengine_p.h"
+#include "corebreakpoint.h"
#include "cdbmodules.h"
+#include "breakhandler.h"
+#include "shared/dbgwinutils.h"
#include <QtCore/QDebug>
+#include <QtCore/QDir>
namespace Debugger {
namespace Internal {
-enum { debugBP = 0 };
-
// Convert breakpoint structs
-CdbCore::BreakPoint breakPointFromBreakPointData(const Debugger::Internal::BreakpointData &bpd)
+static CdbCore::BreakPoint breakPointFromBreakPointData(const BreakpointParameters &bpd, const QString &functionName)
{
CdbCore::BreakPoint rc;
- rc.type = bpd.type == Debugger::Internal::BreakpointData::BreakpointType ?
- CdbCore::BreakPoint::Code : CdbCore::BreakPoint::Data;
+ rc.type = bpd.type == Watchpoint ?
+ CdbCore::BreakPoint::Data :
+ CdbCore::BreakPoint::Code ;
rc.address = bpd.address;
- if (!bpd.threadSpec.isEmpty()) {
- bool ok;
- rc.threadId = bpd.threadSpec.toInt(&ok);
- if (!ok)
- qWarning("Cdb: Cannot convert breakpoint thread specification '%s'", bpd.threadSpec.constData());
- }
+ rc.threadId = bpd.threadSpec;
rc.fileName = QDir::toNativeSeparators(bpd.fileName);
rc.condition = bpd.condition;
- // Resolved function goes to bpd.bpFuncName.
- rc.funcName = bpd.bpFuncName.isEmpty() ? bpd.funcName : bpd.bpFuncName;
+ rc.funcName = functionName.isEmpty() ? bpd.functionName : functionName;
rc.ignoreCount = bpd.ignoreCount;
rc.lineNumber = bpd.lineNumber;
rc.oneShot = false;
@@ -71,56 +69,52 @@ static inline QString msgCannotSetBreakAtFunction(const QString &func, const QSt
return QString::fromLatin1("Cannot set a breakpoint at '%1': %2").arg(func, why);
}
-static bool addBreakpoint(CIDebugControl* debugControl,
- CIDebugSymbols *syms,
- BreakpointData *nbd,
- QString *warning)
+bool addCdbBreakpoint(CIDebugControl* debugControl,
+ CIDebugSymbols *syms,
+ const BreakpointParameters &bpIn,
+ BreakpointResponse *response,
+ QString *errorMessage)
{
- warning->clear();
+ const BreakpointParameters bp = fixWinMSVCBreakpoint(bpIn);
+ errorMessage->clear();
// Function breakpoints: Are the module names specified?
- if (!nbd->funcName.isEmpty()) {
- nbd->bpFuncName = nbd->funcName;
- switch (resolveSymbol(syms, &nbd->bpFuncName, warning)) {
+ QString resolvedFunction;
+ if (bp.type == BreakpointByFunction) {
+ resolvedFunction = bp.functionName;
+ switch (resolveSymbol(syms, &resolvedFunction, errorMessage)) {
case ResolveSymbolOk:
break;
case ResolveSymbolAmbiguous:
- *warning = msgCannotSetBreakAtFunction(nbd->funcName, *warning);
break;
case ResolveSymbolNotFound:
case ResolveSymbolError:
- *warning = msgCannotSetBreakAtFunction(nbd->funcName, *warning);
+ *errorMessage = msgCannotSetBreakAtFunction(bp.functionName, *errorMessage);
return false;
- };
+ }
+ if (debugBreakpoints)
+ qDebug() << bp.functionName << " resolved to " << resolvedFunction;
} // function breakpoint
// Now add...
quint64 address;
unsigned long id;
- const CdbCore::BreakPoint ncdbbp = breakPointFromBreakPointData(*nbd);
- if (!ncdbbp.add(debugControl, warning, &id, &address))
+ const CdbCore::BreakPoint ncdbbp = breakPointFromBreakPointData(bp, resolvedFunction);
+ if (!ncdbbp.add(debugControl, errorMessage, &id, &address))
return false;
- if (debugBP)
+ if (debugBreakpoints)
qDebug("Added %lu at 0x%lx %s", id, address, qPrintable(ncdbbp.toString()));
- nbd->pending = false;
- nbd->bpNumber = QByteArray::number(uint(id));
- nbd->bpAddress = address;
- // Take over rest as is
- nbd->bpCondition = nbd->condition;
- nbd->bpIgnoreCount = nbd->ignoreCount;
- nbd->bpThreadSpec = nbd->threadSpec;
- nbd->bpFileName = nbd->fileName;
- nbd->bpLineNumber = nbd->lineNumber;
+
+ response->fromParameters(bp);
+ response->number = id;
+ response->address = address;
+ response->functionName = resolvedFunction;
return true;
}
-// Synchronize (halted) engine breakpoints with those of the BreakHandler.
-bool synchronizeBreakPoints(CIDebugControl* debugControl,
- CIDebugSymbols *syms,
- BreakHandler *handler,
- QString *errorMessage,
- QStringList *warnings)
+// Delete all breakpoints
+bool deleteCdbBreakpoints(CIDebugControl* debugControl,
+ QString *errorMessage)
{
errorMessage->clear();
- warnings->clear();
// Do an initial check whether we are in a state that allows
// for modifying breakPoints
ULONG engineCount;
@@ -128,50 +122,28 @@ bool synchronizeBreakPoints(CIDebugControl* debugControl,
*errorMessage = QString::fromLatin1("Cannot modify breakpoints: %1").arg(*errorMessage);
return false;
}
- // Delete all breakpoints and re-insert all enabled breakpoints. This is the simplest
- // way to apply changes since CDB ids shift when removing breakpoints and there is no
- // easy way to re-match them.
+ if (debugBreakpoints)
+ qDebug("Deleting breakpoints 0..%lu", engineCount);
+
if (engineCount) {
for (int b = engineCount - 1; b >= 0 ; b--)
if (!CdbCore::BreakPoint::removeBreakPointById(debugControl, b, errorMessage))
return false;
}
- qDeleteAll(handler->takeRemovedBreakpoints());
- // Mark disabled ones
- foreach(BreakpointData *dbd, handler->takeDisabledBreakpoints())
- dbd->bpEnabled = false;
-
- // Insert all enabled ones as new
- QString warning;
- bool updateMarkers = false;
- const int size = handler->size();
- for (int i = 0; i < size; i++) {
- BreakpointData *breakpoint = handler->at(i);
- if (breakpoint->enabled)
- if (addBreakpoint(debugControl, syms, breakpoint, &warning)) {
- updateMarkers = true;
- } else {
- warnings->push_back(warning);
- }
- }
- // Mark enabled ones
- foreach(BreakpointData *ebd, handler->takeEnabledBreakpoints())
- ebd->bpEnabled = true;
-
- if (updateMarkers)
- handler->updateMarkers();
-
- if (debugBP > 1) {
- QList<CdbCore::BreakPoint> bps;
- CdbCore::BreakPoint::getBreakPoints(debugControl, &bps, errorMessage);
- QDebug nsp = qDebug().nospace();
- const int count = bps.size();
- nsp <<"### Breakpoints in engine: " << count << '\n';
- for (int i = 0; i < count; i++)
- nsp << " #" << i << ' ' << bps.at(i) << '\n';
- }
return true;
}
+void debugCdbBreakpoints(CIDebugControl* debugControl)
+{
+ QString errorMessage;
+ QList<CdbCore::BreakPoint> bps;
+ CdbCore::BreakPoint::getBreakPoints(debugControl, &bps, &errorMessage);
+ QDebug nsp = qDebug().nospace();
+ const int count = bps.size();
+ nsp <<"### Breakpoints in engine: " << count << '\n';
+ for (int i = 0; i < count; i++)
+ nsp << " #" << i << ' ' << bps.at(i) << '\n';
+}
+
} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/cdb/cdbbreakpoint.h b/src/plugins/debugger/cdb/cdbbreakpoint.h
index 7a6fe457bb..fc8aba3ac6 100644
--- a/src/plugins/debugger/cdb/cdbbreakpoint.h
+++ b/src/plugins/debugger/cdb/cdbbreakpoint.h
@@ -35,12 +35,8 @@
#define CDBBREAKPOINTS_H
#include "cdbcom.h"
-#include "corebreakpoint.h"
-#include "breakhandler.h"
#include <QtCore/QString>
-#include <QtCore/QList>
-#include <QtCore/QDir>
QT_BEGIN_NAMESPACE
class QDebug;
@@ -48,14 +44,19 @@ QT_END_NAMESPACE
namespace Debugger {
namespace Internal {
+class BreakpointParameters;
+class BreakpointResponse;
// Convert breakpoint structs
-CdbCore::BreakPoint breakPointFromBreakPointData(const Debugger::Internal::BreakpointData &bpd);
+bool addCdbBreakpoint(CIDebugControl* debugControl,
+ CIDebugSymbols *syms,
+ const BreakpointParameters &bp,
+ BreakpointResponse *response,
+ QString *errorMessage);
-// Synchronize (halted) engine with BreakHandler.
-bool synchronizeBreakPoints(CIDebugControl* ctl, CIDebugSymbols *syms,
- BreakHandler *bh,
- QString *errorMessage, QStringList *warnings);
+bool deleteCdbBreakpoints(CIDebugControl* debugControl, QString *errorMessage);
+
+void debugCdbBreakpoints(CIDebugControl* debugControl);
} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/cdb/cdbdebugeventcallback.cpp b/src/plugins/debugger/cdb/cdbdebugeventcallback.cpp
index d46c2824be..82ea855440 100644
--- a/src/plugins/debugger/cdb/cdbdebugeventcallback.cpp
+++ b/src/plugins/debugger/cdb/cdbdebugeventcallback.cpp
@@ -35,6 +35,7 @@
#include "cdbengine.h"
#include "cdbexceptionutils.h"
#include "cdbengine_p.h"
+#include "dbgwinutils.h"
#include <QtCore/QDebug>
#include <QtCore/QTextStream>
@@ -79,7 +80,7 @@ STDMETHODIMP CdbDebugEventCallback::Exception(
QTextStream str(&msg);
formatException(Exception, &m_pEngine->m_d->interfaces(), str);
}
- const bool fatal = isFatalException(Exception->ExceptionCode);
+ const bool fatal = isFatalWinException(Exception->ExceptionCode);
if (debugCDB)
qDebug() << Q_FUNC_INFO << "\nex=" << Exception->ExceptionCode << " fatal=" << fatal << msg;
m_pEngine->showMessage(msg, AppError);
@@ -230,7 +231,7 @@ STDMETHODIMP CdbExceptionLoggerEventCallback::Exception(
__in ULONG /* FirstChance */
)
{
- const bool recordException = !m_skipNonFatalExceptions || isFatalException(Exception->ExceptionCode);
+ const bool recordException = !m_skipNonFatalExceptions || isFatalWinException(Exception->ExceptionCode);
QString msg;
formatException(Exception, QTextStream(&msg));
if (recordException) {
diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp
index 0a7df20dac..d8afdc9387 100644
--- a/src/plugins/debugger/cdb/cdbengine.cpp
+++ b/src/plugins/debugger/cdb/cdbengine.cpp
@@ -44,9 +44,10 @@
#include "cdboptions.h"
#include "cdbexceptionutils.h"
#include "cdbsymbolpathlisteditor.h"
-#include "debuggeragents.h"
-#include "debuggeruiswitcher.h"
-#include "debuggermainwindow.h"
+#include "dbgwinutils.h"
+#include "debuggercore.h"
+#include "disassembleragent.h"
+#include "memoryagent.h"
#include "debuggeractions.h"
#include "breakhandler.h"
@@ -56,9 +57,11 @@
#include "registerhandler.h"
#include "moduleshandler.h"
#include "watchutils.h"
+#include "corebreakpoint.h"
#include <coreplugin/icore.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <utils/winutils.h>
#include <utils/consoleprocess.h>
#include <utils/fancymainwindow.h>
@@ -187,7 +190,7 @@ DebuggerEngine *CdbEngine::create(const DebuggerStartParameters &sp,
void CdbEnginePrivate::updateCodeLevel()
{
- const CdbCore::CoreEngine::CodeLevel cl = theDebuggerBoolSetting(OperateByInstruction) ?
+ const CdbCore::CoreEngine::CodeLevel cl = debuggerCore()->boolSetting(OperateByInstruction) ?
CdbCore::CoreEngine::CodeLevelAssembly : CdbCore::CoreEngine::CodeLevelSource;
setCodeLevel(cl);
}
@@ -353,42 +356,6 @@ void CdbEnginePrivate::checkVersion()
}
}
-void CdbEngine::startupChecks()
-{
- // Check symbol server unless the user has an external/internal setup
- if (!qgetenv("_NT_SYMBOL_PATH").isEmpty()
- || CdbOptions::indexOfSymbolServerPath(m_d->m_options->symbolPaths) != -1)
- return;
- // Prompt to use Symbol server unless the user checked "No nagging".
- Core::ICore *core = Core::ICore::instance();
- const QString nagSymbolServerKey = CdbOptions::settingsGroup() + QLatin1String("/NoPromptSymbolServer");
- bool noFurtherNagging = core->settings()->value(nagSymbolServerKey, false).toBool();
- if (noFurtherNagging)
- return;
-
- const QString symServUrl = QLatin1String("http://support.microsoft.com/kb/311503");
- const QString msg = tr("<html><head/><body><p>The debugger is not configured to use the public "
- "<a href=\"%1\">Microsoft Symbol Server</a>. This is recommended "
- "for retrieval of the symbols of the operating system libraries.</p>"
- "<p><i>Note:</i> A fast internet connection is required for this to work smoothly. Also, a delay "
- "might occur when connecting for the first time.</p>"
- "<p>Would you like to set it up?</p></br>"
- "</body></html>").arg(symServUrl);
- const QDialogButtonBox::StandardButton answer =
- Utils::CheckableMessageBox::question(core->mainWindow(), tr("Symbol Server"), msg,
- tr("Do not ask again"), &noFurtherNagging);
- core->settings()->setValue(nagSymbolServerKey, noFurtherNagging);
- if (answer == QDialogButtonBox::No)
- return;
- // Prompt for path and add it. Synchronize QSetting and debugger.
- const QString cacheDir = CdbSymbolPathListEditor::promptCacheDirectory(core->mainWindow());
- if (cacheDir.isEmpty())
- return;
- m_d->m_options->symbolPaths.push_back(CdbOptions::symbolServerPath(cacheDir));
- m_d->m_options->toSettings(core->settings());
- syncDebuggerPaths();
-}
-
void CdbEngine::setupEngine()
{
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
@@ -396,7 +363,12 @@ void CdbEngine::setupEngine()
if (debugCDBExecution)
qDebug("setupEngine");
CdbCore::BreakPoint::clearNormalizeFileNameCache();
- startupChecks();
+ // Nag to add symbol server
+ if (CdbSymbolPathListEditor::promptToAddSymbolServer(CdbOptions::settingsGroup(),
+ &(m_d->m_options->symbolPaths))) {
+ m_d->m_options->toSettings(Core::ICore::instance()->settings());
+ syncDebuggerPaths();
+ }
m_d->checkVersion();
if (m_d->m_hDebuggeeProcess) {
warning(QLatin1String("Internal error: Attempt to start debugger while another process is being debugged."));
@@ -467,7 +439,17 @@ void CdbEngine::runEngine()
needWatchTimer = true; // Fetch away module load, etc. even if crashed
break;
case StartInternal:
- case StartExternal:
+ case StartExternal: {
+ Utils::QtcProcess::SplitError perr;
+ QString pargs = Utils::QtcProcess::prepareArgs(sp.processArgs, &perr,
+ &sp.environment, &sp.workingDirectory);
+ if (perr != Utils::QtcProcess::SplitOk) {
+ // perr == BadQuoting is never returned on Windows
+ // FIXME? QTCREATORBUG-2809
+ errorMessage = QApplication::translate("DebuggerEngine", // Same message in GdbEngine
+ "Debugging complex command lines is currently not supported under Windows");
+ break;
+ }
if (sp.useTerminal) {
// Attaching to console processes triggers an initial breakpoint, which we do not want
m_d->m_ignoreInitialBreakPoint = true;
@@ -475,7 +457,7 @@ void CdbEngine::runEngine()
m_d->m_consoleStubProc.stop(); // We leave the console open, so recycle it now.
m_d->m_consoleStubProc.setWorkingDirectory(sp.workingDirectory);
m_d->m_consoleStubProc.setEnvironment(sp.environment);
- rc = m_d->m_consoleStubProc.start(sp.executable, sp.processArgs);
+ rc = m_d->m_consoleStubProc.start(sp.executable, pargs);
if (!rc)
errorMessage = tr("The console stub process was unable to start '%1'.").arg(sp.executable);
// continues in slotConsoleStubStarted()...
@@ -483,11 +465,11 @@ void CdbEngine::runEngine()
needWatchTimer = true;
rc = m_d->startDebuggerWithExecutable(sp.workingDirectory,
sp.executable,
- sp.processArgs,
- sp.environment,
+ pargs,
+ sp.environment.toStringList(),
&errorMessage);
}
- break;
+ break; }
case AttachCore:
errorMessage = tr("Attaching to core files is not supported.");
break;
@@ -534,11 +516,7 @@ void CdbEnginePrivate::processCreatedAttached(ULONG64 processHandle, ULONG64 ini
}
// Clear any saved breakpoints and set initial breakpoints
m_engine->executeDebuggerCommand(QLatin1String("bc"));
- if (m_engine->breakHandler()->hasPendingBreakpoints()) {
- if (debugCDBExecution)
- qDebug("processCreatedAttached: Syncing breakpoints");
- m_engine->attemptBreakpointSynchronization();
- }
+ m_engine->attemptBreakpointSynchronization();
// Attaching to crashed: This handshake (signalling an event) is required for
// the exception to be delivered to the debugger
// Also, see special handling in slotModulesLoaded().
@@ -1027,9 +1005,59 @@ void CdbEngine::executeRunToFunction(const QString &functionName)
warning(errorMessage);
}
-void CdbEngine::executeJumpToLine(const QString & /* fileName */, int /*lineNumber*/)
+void CdbEngine::setRegisterValue(int regnr, const QString &valueIn)
+{
+ bool success = false;
+ QString errorMessage;
+ do {
+ const quint64 value = valueIn.toULongLong(&success, 0);
+ if (!success) {
+ errorMessage = tr("Invalid register value '%1'").arg(valueIn);
+ break;
+ }
+ if (!setRegisterValueU64(m_d->interfaces().debugRegisters, regnr, value, &errorMessage))
+ break;
+ showMessage(QString::fromLatin1("Setting register %1 to 0x%2...").
+ arg(regnr).arg(value, 0, 16));
+ reloadRegisters();
+ success =true;
+ } while (false);
+ if (!success)
+ warning(tr("Cannot set register %1 to '%2': %3").
+ arg(regnr).arg(valueIn).arg(errorMessage));
+}
+
+void CdbEngine::executeJumpToLine(const QString &fileName, int lineNumber)
{
- warning(tr("Jump to line is not implemented"));
+ // 'Jump' to line by manipulating the program counter register 'rip'.
+ bool success = false;
+ QString errorMessage;
+ do {
+ const quint64 address = m_d->getSourceLineAddress(fileName, lineNumber, &errorMessage);
+ if (address == 0)
+ break;
+
+ if (!setRegisterValueU64(m_d->interfaces().debugControl,
+ m_d->interfaces().debugRegisters,
+#ifdef Q_OS_WIN64
+ QLatin1String("rip"),
+#else
+ QLatin1String("eip"),
+#endif
+ address, &errorMessage))
+ break;
+ showMessage(QString::fromLatin1("Jumping to %1:%2 (0x%3)...").
+ arg(QDir::toNativeSeparators(fileName)).arg(lineNumber).arg(address, 0, 16));
+
+ StackFrame frame;
+ frame.usable = true;
+ frame.file = fileName;
+ frame.line = lineNumber;
+ gotoLocation(frame);
+ success = true;
+ } while (false);
+ if (!success)
+ warning(tr("Cannot jump to %1:%2: %3").arg(fileName).arg(lineNumber).arg(errorMessage));
}
void CdbEngine::assignValueInDebugger(const WatchData *w, const QString &expr, const QVariant &valueV)
@@ -1078,9 +1106,10 @@ void CdbEngine::assignValueInDebugger(const WatchData *w, const QString &expr, c
v.toString();
}
// Update view
- if (WatchData *fwd = watchHandler()->findItem(w->iname)) {
- fwd->setValue(newValueObtained);
- watchHandler()->insertData(*fwd);
+ if (const WatchData *fwd = watchHandler()->findItem(w->iname)) {
+ WatchData modified = *fwd;
+ modified.setValue(newValueObtained);
+ watchHandler()->insertData(modified);
watchHandler()->updateWatchers();
}
success = true;
@@ -1134,14 +1163,14 @@ void CdbEngine::activateFrame(int frameIndex)
if (showAssembler) { // Assembly code: Clean out model and force instruction mode.
watchHandler()->beginCycle();
watchHandler()->endCycle();
- QAction *assemblerAction = theDebuggerAction(OperateByInstruction);
+ QAction *assemblerAction = debuggerCore()->action(OperateByInstruction);
if (!assemblerAction->isChecked())
assemblerAction->trigger();
success = true;
break;
}
- gotoLocation(frame, true);
+ gotoLocation(frame);
if (oldIndex != frameIndex || m_d->m_firstActivatedFrame) {
watchHandler()->beginCycle();
@@ -1178,26 +1207,83 @@ void CdbEngine::selectThread(int index)
}
}
+bool CdbEngine::stateAcceptsBreakpointChanges() const
+{
+ switch (state()) {
+ case InferiorRunOk:
+ case InferiorStopOk:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+bool CdbEngine::acceptsBreakpoint(BreakpointId id) const
+{
+ return DebuggerEngine::isCppBreakpoint(breakHandler()->breakpointData(id));
+}
+
void CdbEngine::attemptBreakpointSynchronization()
{
if (!m_d->m_hDebuggeeProcess) // Sometimes called from the breakpoint Window
return;
QString errorMessage;
- if (!m_d->attemptBreakpointSynchronization(&errorMessage))
+ if (!attemptBreakpointSynchronizationI(&errorMessage))
warning(msgFunctionFailed(Q_FUNC_INFO, errorMessage));
}
-bool CdbEnginePrivate::attemptBreakpointSynchronization(QString *errorMessage)
+// Figure out what kind of changes are required to synchronize
+enum BreakPointSyncType {
+ BreakpointsUnchanged, BreakpointsAdded, BreakpointsRemovedChanged
+};
+
+static inline BreakPointSyncType breakPointSyncType(const BreakHandler *handler, const BreakpointIds ids)
{
- if (!m_hDebuggeeProcess) {
+ bool added = false;
+ foreach (BreakpointId id, ids) {
+ switch (handler->state(id)) {
+ case BreakpointInsertRequested:
+ added = true;
+ break;
+ case BreakpointChangeRequested:
+ case BreakpointRemoveRequested:
+ return BreakpointsRemovedChanged;
+ default:
+ break;
+ }
+ }
+ return added ? BreakpointsAdded : BreakpointsUnchanged;
+}
+
+bool CdbEngine::attemptBreakpointSynchronizationI(QString *errorMessage)
+{
+
+ if (!m_d->m_hDebuggeeProcess) {
*errorMessage = QLatin1String("attemptBreakpointSynchronization() called while debugger is not running");
return false;
}
// Might be called nested while attempting to stop.
- if (m_breakEventMode == BreakEventSyncBreakPoints) {
+ if (m_d->m_breakEventMode == CdbEnginePrivate::BreakEventSyncBreakPoints) {
*errorMessage = QLatin1String("Nested invocation of attemptBreakpointSynchronization.");
return false;
}
+
+ // Check if there is anything to be done at all.
+ BreakHandler *handler = breakHandler();
+ // Take ownership of the breakpoint. Requests insertion. TODO: Cpp only?
+ foreach (BreakpointId id, handler->unclaimedBreakpointIds())
+ if (acceptsBreakpoint(id))
+ handler->setEngine(id, this);
+
+ // Find out if there is a need to synchronize again
+ const BreakpointIds ids = handler->engineBreakpointIds(this);
+ const BreakPointSyncType syncType = breakPointSyncType(handler, ids);
+ if (debugBreakpoints)
+ qDebug("attemptBreakpointSynchronizationI %d breakpoints, syncType=%d", ids.size(), syncType);
+ if (syncType == BreakpointsUnchanged)
+ return true;
+
// This is called from
// 1) CreateProcessEvent with the halted engine
// 2) from the break handler, potentially while the debuggee is running
@@ -1205,33 +1291,81 @@ bool CdbEnginePrivate::attemptBreakpointSynchronization(QString *errorMessage)
// no reliable indicator), we temporarily halt and have ourselves
// called again from the debug event handler.
+ CIDebugControl *control = m_d->interfaces().debugControl;
+ CIDebugSymbols *symbols = m_d->interfaces().debugSymbols;
+
ULONG dummy;
- const bool wasRunning = !CdbCore::BreakPoint::getBreakPointCount(interfaces().debugControl, &dummy);
+ const bool wasRunning = !CdbCore::BreakPoint::getBreakPointCount(control, &dummy);
if (debugCDB)
qDebug() << Q_FUNC_INFO << "\n Running=" << wasRunning;
if (wasRunning) {
- const HandleBreakEventMode oldMode = m_breakEventMode;
- m_breakEventMode = BreakEventSyncBreakPoints;
- if (!interruptInterferiorProcess(errorMessage)) {
- m_breakEventMode = oldMode;
+ const CdbEnginePrivate::HandleBreakEventMode oldMode = m_d->m_breakEventMode;
+ m_d->m_breakEventMode = CdbEnginePrivate::BreakEventSyncBreakPoints;
+ if (!m_d->interruptInterferiorProcess(errorMessage)) {
+ m_d->m_breakEventMode = oldMode;
return false;
}
return true;
}
- QStringList warnings;
- const bool ok = synchronizeBreakPoints(interfaces().debugControl,
- interfaces().debugSymbols,
- m_engine->breakHandler(),
- errorMessage, &warnings);
- if (const int warningsCount = warnings.size())
- for (int w = 0; w < warningsCount; w++)
- m_engine->warning(warnings.at(w));
- return ok;
+ // If there are changes/removals, delete all breakpoints and re-insert
+ // all enabled breakpoints. This is the simplest way to apply changes
+ // since CDB ids shift when removing breakpoints and there is no
+ // easy way to re-match them.
+ if (syncType == BreakpointsRemovedChanged && !deleteCdbBreakpoints(control, errorMessage))
+ return false;
+
+ foreach (BreakpointId id, ids) {
+ BreakpointResponse response;
+ const BreakpointParameters &data = handler->breakpointData(id);
+ errorMessage->clear();
+ switch (handler->state(id)) {
+ case BreakpointInsertRequested:
+ handler->notifyBreakpointInsertProceeding(id);
+ if (addCdbBreakpoint(control, symbols, data, &response, errorMessage)) {
+ handler->notifyBreakpointInsertOk(id);
+ handler->setResponse(id, response);
+ } else {
+ handler->notifyBreakpointInsertOk(id);
+ showMessage(*errorMessage, LogError);
+ }
+ break;
+ case BreakpointChangeRequested:
+ // Skip disabled breakpoints, else add.
+ handler->notifyBreakpointChangeProceeding(id);
+ if (data.enabled) {
+ if (addCdbBreakpoint(control, symbols, data, &response, errorMessage)) {
+ handler->notifyBreakpointChangeOk(id);
+ handler->setResponse(id, response);
+ } else {
+ handler->notifyBreakpointChangeFailed(id);
+ showMessage(*errorMessage, LogError);
+ }
+ } else {
+ handler->notifyBreakpointChangeOk(id);
+ }
+ break;
+ case BreakpointRemoveRequested:
+ handler->notifyBreakpointRemoveProceeding(id);
+ handler->notifyBreakpointRemoveOk(id);
+ break;
+ case BreakpointInserted:
+ // Existing breakpoints were deleted due to change/removal, re-set
+ if (syncType == BreakpointsRemovedChanged
+ && !addCdbBreakpoint(control, symbols, handler->breakpointData(id), &response, errorMessage))
+ showMessage(*errorMessage, LogError);
+ break;
+ default:
+ break;
+ }
+ }
+ if (debugBreakpoints)
+ debugCdbBreakpoints(control);
+ return true;
}
-void CdbEngine::fetchDisassembler(DisassemblerViewAgent *agent)
+void CdbEngine::fetchDisassembler(DisassemblerAgent *agent)
{
enum { ContextLines = 40 };
QString errorMessage;
@@ -1239,23 +1373,25 @@ void CdbEngine::fetchDisassembler(DisassemblerViewAgent *agent)
if (debugCDB)
qDebug() << "fetchDisassembler" << address << " Agent: " << agent->address();
+ DisassemblerLines lines;
if (address == 0) { // Clear window
- agent->setContents(QString());
+ agent->setContents(lines);
return;
}
QString disassembly;
QApplication::setOverrideCursor(Qt::WaitCursor);
- const bool ok = dissassemble(m_d, address, ContextLines, ContextLines, QTextStream(&disassembly), &errorMessage);
+ const bool ok = disassemble(m_d, address, ContextLines, ContextLines, QTextStream(&disassembly), &errorMessage);
QApplication::restoreOverrideCursor();
if (ok) {
- agent->setContents(disassembly);
+ foreach(const QString &line, disassembly.remove(QLatin1Char('\r')).split(QLatin1Char('\n')))
+ lines.appendLine(DisassemblerLine(line));
} else {
- agent->setContents(QString());
warning(errorMessage);
}
+ agent->setContents(lines);
}
-void CdbEngine::fetchMemory(MemoryViewAgent *agent, QObject *token, quint64 addr, quint64 length)
+void CdbEngine::fetchMemory(MemoryAgent *agent, QObject *token, quint64 addr, quint64 length)
{
if (!m_d->m_hDebuggeeProcess && !length)
return;
@@ -1290,7 +1426,7 @@ void CdbEngine::loadAllSymbols()
void CdbEngine::requestModuleSymbols(const QString &moduleName)
{
- QList<Symbol> rc;
+ Symbols rc;
QString errorMessage;
bool success = false;
do {
@@ -1304,7 +1440,7 @@ void CdbEngine::requestModuleSymbols(const QString &moduleName)
} while (false);
if (!success)
warning(errorMessage);
- showModuleSymbols(moduleName, rc);
+ debuggerCore()->showModuleSymbols(moduleName, rc);
}
void CdbEngine::reloadRegisters()
@@ -1334,13 +1470,13 @@ void CdbEngine::slotConsoleStubStarted()
m_d->startWatchTimer();
notifyInferiorPid(appPid);
} else {
- QMessageBox::critical(DebuggerUISwitcher::instance()->mainWindow(), tr("Debugger Error"), errorMessage);
+ QMessageBox::critical(debuggerCore()->mainWindow(), tr("Debugger Error"), errorMessage);
}
}
void CdbEngine::slotConsoleStubMessage(const QString &msg, bool)
{
- QMessageBox::critical(DebuggerUISwitcher::instance()->mainWindow(), tr("Debugger Error"), msg);
+ QMessageBox::critical(debuggerCore()->mainWindow(), tr("Debugger Error"), msg);
}
void CdbEngine::slotConsoleStubTerminated()
@@ -1453,7 +1589,7 @@ void CdbEnginePrivate::handleDebugEvent()
// Temp stop to sync breakpoints (without invoking states).
// Triggered when the users changes breakpoints while running.
QString errorMessage;
- attemptBreakpointSynchronization(&errorMessage);
+ m_engine->attemptBreakpointSynchronizationI(&errorMessage);
startWatchTimer();
if (!continueInferiorProcess(&errorMessage)) {
STATE_DEBUG(Q_FUNC_INFO, __LINE__, "BreakEventSyncBreakPoints / notifyInferiorSpontaneousStop");
@@ -1642,7 +1778,7 @@ void CdbEnginePrivate::updateStackTrace()
void CdbEnginePrivate::updateModules()
{
- QList<Module> modules;
+ Modules modules;
QString errorMessage;
if (!getModuleList(interfaces().debugSymbols, &modules, &errorMessage))
m_engine->warning(msgFunctionFailed(Q_FUNC_INFO, errorMessage));
@@ -1712,7 +1848,7 @@ void CdbEngine::syncDebuggerPaths()
unsigned CdbEngine::debuggerCapabilities() const
{
return DisassemblerCapability | RegisterCapability | ShowMemoryCapability
- |WatchpointCapability
+ |WatchpointCapability|JumpToLineCapability
|BreakOnThrowAndCatchCapability; // Sort-of: Can break on throw().
}
@@ -1745,14 +1881,14 @@ void addCdbOptionPages(QList<Core::IOptionsPage *> *opts)
bool checkCdbConfiguration(int toolChainI, QString *errorMsg, QString *settingsPage)
{
- const ProjectExplorer::ToolChain::ToolChainType toolChain = static_cast<ProjectExplorer::ToolChain::ToolChainType>(toolChainI);
+ const ProjectExplorer::ToolChainType toolChain = static_cast<ProjectExplorer::ToolChainType>(toolChainI);
switch (toolChain) {
- case ProjectExplorer::ToolChain::MinGW: // Do our best
- case ProjectExplorer::ToolChain::MSVC:
- case ProjectExplorer::ToolChain::WINCE:
- case ProjectExplorer::ToolChain::OTHER:
- case ProjectExplorer::ToolChain::UNKNOWN:
- case ProjectExplorer::ToolChain::INVALID:
+ case ProjectExplorer::ToolChain_MinGW: // Do our best
+ case ProjectExplorer::ToolChain_MSVC:
+ case ProjectExplorer::ToolChain_WINCE:
+ case ProjectExplorer::ToolChain_OTHER:
+ case ProjectExplorer::ToolChain_UNKNOWN:
+ case ProjectExplorer::ToolChain_INVALID:
break;
default:
//: %1 is something like "GCCE" or "Intel C++ Compiler (Linux)" (see ToolChain context)
diff --git a/src/plugins/debugger/cdb/cdbengine.h b/src/plugins/debugger/cdb/cdbengine.h
index c689624fae..9d15803e0a 100644
--- a/src/plugins/debugger/cdb/cdbengine.h
+++ b/src/plugins/debugger/cdb/cdbengine.h
@@ -41,7 +41,7 @@
namespace Debugger {
namespace Internal {
-class DisassemblerViewAgent;
+class DisassemblerAgent;
class CdbDebugEventCallback;
class CdbDebugOutput;
class CdbEnginePrivate;
@@ -87,10 +87,13 @@ public:
virtual void activateFrame(int index);
virtual void selectThread(int index);
+ virtual bool stateAcceptsBreakpointChanges() const;
+ virtual bool acceptsBreakpoint(BreakpointId id) const;
virtual void attemptBreakpointSynchronization();
- virtual void fetchDisassembler(DisassemblerViewAgent *agent);
- virtual void fetchMemory(MemoryViewAgent *, QObject *, quint64 addr, quint64 length);
+ virtual void setRegisterValue(int regnr, const QString &value);
+ virtual void fetchDisassembler(DisassemblerAgent *agent);
+ virtual void fetchMemory(MemoryAgent *, QObject *, quint64 addr, quint64 length);
virtual void reloadModules();
virtual void loadSymbols(const QString &moduleName);
@@ -112,12 +115,12 @@ private slots:
void warning(const QString &w);
private:
- void startupChecks();
inline bool startAttachDebugger(qint64 pid, DebuggerStartMode sm, QString *errorMessage);
void processTerminated(unsigned long exitCode);
void evaluateWatcher(WatchData *wd);
QString editorToolTip(const QString &exp, const QString &function);
bool step(unsigned long executionStatus);
+ bool attemptBreakpointSynchronizationI(QString *errorMessage);
CdbEnginePrivate *m_d;
diff --git a/src/plugins/debugger/cdb/cdbengine_p.h b/src/plugins/debugger/cdb/cdbengine_p.h
index 44e9ad8cd5..796911a508 100644
--- a/src/plugins/debugger/cdb/cdbengine_p.h
+++ b/src/plugins/debugger/cdb/cdbengine_p.h
@@ -99,7 +99,6 @@ public:
bool continueInferior(QString *errorMessage);
bool executeContinueCommand(const QString &command);
- bool attemptBreakpointSynchronization(QString *errorMessage);
void notifyException(long code, bool fatal, const QString &message);
@@ -148,6 +147,7 @@ enum { debugCDB = 0 };
enum { debugCDBExecution = 0 };
enum { debugCDBWatchHandling = 0 };
enum { debugToolTips = 0 };
+enum { debugBreakpoints = 0 };
} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/cdb/cdbexceptionutils.cpp b/src/plugins/debugger/cdb/cdbexceptionutils.cpp
index c8ffb7e646..a23177c269 100644
--- a/src/plugins/debugger/cdb/cdbexceptionutils.cpp
+++ b/src/plugins/debugger/cdb/cdbexceptionutils.cpp
@@ -34,6 +34,7 @@
#include "cdbexceptionutils.h"
#include "cdbengine_p.h"
#include "stacktracecontext.h"
+#include "dbgwinutils.h"
#include <QtCore/QString>
#include <QtCore/QTextStream>
@@ -155,106 +156,15 @@ QString ExceptionBlocker::format(const DEBUG_EXCEPTION_FILTER_PARAMETERS &p)
// ------------------ further exception utilities
// Simple exception formatting
+
void formatException(const EXCEPTION_RECORD64 *e, QTextStream &str)
{
- str.setIntegerBase(16);
- str << "\nException at 0x" << e->ExceptionAddress
- << ", code: 0x" << e->ExceptionCode << ": ";
- switch (e->ExceptionCode) {
- case winExceptionCppException:
- str << "C++ exception";
- break;
- case winExceptionStartupCompleteTrap:
- str << "Startup complete";
- break;
- case winExceptionDllNotFound:
- str << "DLL not found";
- break;
- case winExceptionDllEntryPointNoFound:
- str << "DLL entry point not found";
- break;
- case winExceptionDllInitFailed:
- str << "DLL failed to initialize";
- break;
- case winExceptionMissingSystemFile:
- str << "System file is missing";
- break;
- case winExceptionRpcServerUnavailable:
- str << "RPC server unavailable";
- break;
- case winExceptionRpcServerInvalid:
- str << "Invalid RPC server";
- break;
- case EXCEPTION_ACCESS_VIOLATION: {
- const bool writeOperation = e->ExceptionInformation[0];
- str << (writeOperation ? "write" : "read")
- << " access violation at: 0x" << e->ExceptionInformation[1];
- }
- break;
- case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
- str << "arrary bounds exceeded";
- break;
- case EXCEPTION_BREAKPOINT:
- str << "breakpoint";
- break;
- case EXCEPTION_DATATYPE_MISALIGNMENT:
- str << "datatype misalignment";
- break;
- case EXCEPTION_FLT_DENORMAL_OPERAND:
- str << "floating point exception";
- break;
- case EXCEPTION_FLT_DIVIDE_BY_ZERO:
- str << "division by zero";
- break;
- case EXCEPTION_FLT_INEXACT_RESULT:
- str << " floating-point operation cannot be represented exactly as a decimal fraction";
- break;
- case EXCEPTION_FLT_INVALID_OPERATION:
- str << "invalid floating-point operation";
- break;
- case EXCEPTION_FLT_OVERFLOW:
- str << "floating-point overflow";
- break;
- case EXCEPTION_FLT_STACK_CHECK:
- str << "floating-point operation stack over/underflow";
- break;
- case EXCEPTION_FLT_UNDERFLOW:
- str << "floating-point UNDERFLOW";
- break;
- case EXCEPTION_ILLEGAL_INSTRUCTION:
- str << "invalid instruction";
- break;
- case EXCEPTION_IN_PAGE_ERROR:
- str << "page in error";
- break;
- case EXCEPTION_INT_DIVIDE_BY_ZERO:
- str << "integer division by zero";
- break;
- case EXCEPTION_INT_OVERFLOW:
- str << "integer overflow";
- break;
- case EXCEPTION_INVALID_DISPOSITION:
- str << "invalid disposition to exception dispatcher";
- break;
- case EXCEPTION_NONCONTINUABLE_EXCEPTION:
- str << "attempt to continue execution after noncontinuable exception";
- break;
- case EXCEPTION_PRIV_INSTRUCTION:
- str << "privileged instruction";
- break;
- case EXCEPTION_SINGLE_STEP:
- str << "single step";
- break;
- case EXCEPTION_STACK_OVERFLOW:
- str << "stack_overflow";
- break;
- }
- str << ", flags=0x" << e->ExceptionFlags;
- if (e->ExceptionFlags == EXCEPTION_NONCONTINUABLE) {
- str << " (execution cannot be continued)";
- }
+ formatWindowsException(e->ExceptionCode, e->ExceptionAddress,
+ e->ExceptionFlags,
+ e->ExceptionInformation[0],
+ e->ExceptionInformation[1],
+ str);
str << "\n\n";
- str.setIntegerBase(10);
}
// Format exception with stacktrace in case of C++ exception
@@ -274,23 +184,5 @@ void formatException(const EXCEPTION_RECORD64 *e,
}
}
-bool isFatalException(LONG code)
-{
- switch (code) {
- case EXCEPTION_BREAKPOINT:
- case EXCEPTION_SINGLE_STEP:
- case winExceptionStartupCompleteTrap: // Mysterious exception at start of application
- case winExceptionRpcServerUnavailable:
- case winExceptionRpcServerInvalid:
- case winExceptionDllNotFound:
- case winExceptionDllEntryPointNoFound:
- case winExceptionCppException:
- return false;
- default:
- break;
- }
- return true;
-}
-
} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/cdb/cdbexceptionutils.h b/src/plugins/debugger/cdb/cdbexceptionutils.h
index f36f1ceb19..7460b5a304 100644
--- a/src/plugins/debugger/cdb/cdbexceptionutils.h
+++ b/src/plugins/debugger/cdb/cdbexceptionutils.h
@@ -50,18 +50,6 @@ namespace CdbCore {
namespace Debugger {
namespace Internal {
-// Special exception codes.
-enum { winExceptionCppException = 0xe06d7363,
- winExceptionStartupCompleteTrap = 0x406d1388,
- winExceptionRpcServerUnavailable = 0x6ba,
- winExceptionRpcServerInvalid = 0x6a6,
- winExceptionDllNotFound = 0xc0000135,
- winExceptionDllEntryPointNoFound = 0xc0000139,
- winExceptionDllInitFailed = 0xc0000142,
- winExceptionMissingSystemFile = 0xc0000143,
- winExceptionAppInitFailed = 0xc0000143
-};
-
class CdbDumperHelper;
// Utility class that blocks out exception handling (breaking)
@@ -106,9 +94,6 @@ void formatException(const EXCEPTION_RECORD64 *e,
const CdbCore::ComInterfaces *cif,
QTextStream &str);
-// Is this a crash/recoverable?
-bool isFatalException(LONG code);
-
} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/cdb/cdbmodules.cpp b/src/plugins/debugger/cdb/cdbmodules.cpp
index e502d8bdc4..9a7a168109 100644
--- a/src/plugins/debugger/cdb/cdbmodules.cpp
+++ b/src/plugins/debugger/cdb/cdbmodules.cpp
@@ -35,9 +35,11 @@
#include "moduleshandler.h"
#include "cdbengine_p.h"
#include "breakpoint.h"
+#include "shared/dbgwinutils.h"
#include <QtCore/QFileInfo>
#include <QtCore/QRegExp>
+#include <QtCore/QVector>
namespace Debugger {
namespace Internal {
@@ -115,7 +117,7 @@ bool getModuleByOffset(CIDebugSymbols *syms, quint64 offset,
return getModuleName(syms, index, &(module->moduleName), errorMessage);
}
-bool getModuleList(CIDebugSymbols *syms, QList<Module> *modules, QString *errorMessage)
+bool getModuleList(CIDebugSymbols *syms, Modules *modules, QString *errorMessage)
{
ULONG count;
modules->clear();
@@ -185,15 +187,9 @@ static ResolveSymbolResult resolveSymbol(CIDebugSymbols *syms, QString *symbol,
// Is it an incomplete symbol?
if (symbol->contains(QLatin1Char('!')))
return ResolveSymbolOk;
- // Throw and catch
- bool withinMSVCRunTime = false;
- if (*symbol == QLatin1String(BreakpointData::throwFunction)) {
- *symbol = QLatin1String("CxxThrowException");
- withinMSVCRunTime = true;
- } else if (*symbol == QLatin1String(BreakpointData::catchFunction)) {
- *symbol = QLatin1String("__CxxCallCatchBlock");
- withinMSVCRunTime = true;
- } else if (*symbol == QLatin1String("qMain")) // 'main' is a #define for gdb, but not for VS
+ const bool withinMSVCRunTime = *symbol == QLatin1String(winMSVCThrowFunction)
+ || *symbol == QLatin1String(winMSVCCatchFunction);
+ if (*symbol == QLatin1String("qMain")) // 'main' is a #define for gdb, but not for VS
*symbol = QLatin1String("main");
// resolve
if (!searchSymbols(syms, *symbol, matches, errorMessage))
@@ -269,7 +265,7 @@ ResolveSymbolResult resolveSymbol(CIDebugSymbols *syms, const QString &pattern,
// List symbols of a module
bool getModuleSymbols(CIDebugSymbols *syms, const QString &moduleName,
- QList<Symbol> *symbols, QString *errorMessage)
+ Symbols *symbols, QString *errorMessage)
{
// Search all symbols and retrieve addresses
symbols->clear();
diff --git a/src/plugins/debugger/cdb/cdbmodules.h b/src/plugins/debugger/cdb/cdbmodules.h
index 612da48c3f..067379aa1f 100644
--- a/src/plugins/debugger/cdb/cdbmodules.h
+++ b/src/plugins/debugger/cdb/cdbmodules.h
@@ -35,6 +35,7 @@
#define CDBMODULES_H
#include <QtCore/QStringList>
+#include <QtCore/QVector>
#include "cdbcom.h"
@@ -43,8 +44,10 @@ namespace Internal {
class Module;
class Symbol;
+typedef QVector<Module> Modules;
+typedef QVector<Symbol> Symbols;
-bool getModuleList(CIDebugSymbols *syms, QList<Module> *modules, QString *errorMessage);
+bool getModuleList(CIDebugSymbols *syms, Modules *modules, QString *errorMessage);
bool getModuleNameList(CIDebugSymbols *syms, QStringList *modules, QString *errorMessage);
bool getModuleByOffset(CIDebugSymbols *syms, quint64 offset, Module *module, QString *errorMessage);
@@ -66,7 +69,7 @@ ResolveSymbolResult resolveSymbol(CIDebugSymbols *syms, const QString &pattern,
// List symbols of a module
bool getModuleSymbols(CIDebugSymbols *syms, const QString &moduleName,
- QList<Symbol> *symbols, QString *errorMessage);
+ Symbols *symbols, QString *errorMessage);
} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/cdb/cdboptions.cpp b/src/plugins/debugger/cdb/cdboptions.cpp
index 0f8f7f4b30..85cada164e 100644
--- a/src/plugins/debugger/cdb/cdboptions.cpp
+++ b/src/plugins/debugger/cdb/cdboptions.cpp
@@ -33,6 +33,7 @@
#include "cdboptions.h"
#include "coreengine.h"
+#include "cdbsymbolpathlisteditor.h"
#include <QtCore/QSettings>
#include <QtCore/QDir>
@@ -121,36 +122,14 @@ unsigned CdbOptions::compare(const CdbOptions &rhs) const
return rc;
}
-static const char symbolServerPrefixC[] = "symsrv*symsrv.dll*";
-static const char symbolServerPostfixC[] = "*http://msdl.microsoft.com/download/symbols";
-
QString CdbOptions::symbolServerPath(const QString &cacheDir)
{
- QString s = QLatin1String(symbolServerPrefixC);
- s += QDir::toNativeSeparators(cacheDir);
- s += QLatin1String(symbolServerPostfixC);
- return s;
-}
-
-bool CdbOptions::isSymbolServerPath(const QString &path, QString *cacheDir /* = 0 */)
-{
- // Split apart symbol server post/prefixes
- if (!path.startsWith(QLatin1String(symbolServerPrefixC)) || !path.endsWith(QLatin1String(symbolServerPostfixC)))
- return false;
- if (cacheDir) {
- const unsigned prefixLength = qstrlen(symbolServerPrefixC);
- *cacheDir = path.mid(prefixLength, path.size() - prefixLength - qstrlen(symbolServerPostfixC));
- }
- return true;
+ return CdbSymbolPathListEditor::symbolServerPath(cacheDir);
}
-int CdbOptions::indexOfSymbolServerPath(const QStringList &paths, QString *cacheDir /* = 0 */)
+int CdbOptions::indexOfSymbolServerPath(const QStringList &symbolPaths, QString *cacheDir)
{
- const int count = paths.size();
- for (int i = 0; i < count; i++)
- if (CdbOptions::isSymbolServerPath(paths.at(i), cacheDir))
- return i;
- return -1;
+ return CdbSymbolPathListEditor::indexOfSymbolServerPath(symbolPaths, cacheDir);
}
} // namespace Internal
diff --git a/src/plugins/debugger/cdb/cdboptions.h b/src/plugins/debugger/cdb/cdboptions.h
index dc27dec690..8d2146eef2 100644
--- a/src/plugins/debugger/cdb/cdboptions.h
+++ b/src/plugins/debugger/cdb/cdboptions.h
@@ -64,7 +64,6 @@ public:
// Format a symbol server specification with a cache directory
static QString symbolServerPath(const QString &cacheDir);
// Check whether the path is a symbol server specification and return the cache directory
- static bool isSymbolServerPath(const QString &symbolPath, QString *cacheDir = 0);
static int indexOfSymbolServerPath(const QStringList &symbolPaths, QString *cacheDir = 0);
static QString settingsGroup();
diff --git a/src/plugins/debugger/cdb/cdbstackframecontext.cpp b/src/plugins/debugger/cdb/cdbstackframecontext.cpp
index e0b8f982d3..c28088f2a1 100644
--- a/src/plugins/debugger/cdb/cdbstackframecontext.cpp
+++ b/src/plugins/debugger/cdb/cdbstackframecontext.cpp
@@ -298,7 +298,7 @@ WatchHandleDumperInserter &WatchHandleDumperInserter::operator=(WatchData &wd)
// -----------CdbStackFrameContext
CdbStackFrameContext::CdbStackFrameContext(const QSharedPointer<CdbDumperHelper> &dumper,
CdbSymbolGroupContext *symbolContext) :
- m_useDumpers(dumper->isEnabled() && theDebuggerBoolSetting(UseDebuggingHelpers)),
+ m_useDumpers(dumper->isEnabled() && debuggerCore()->boolSetting(UseDebuggingHelpers)),
m_dumper(dumper),
m_symbolContext(symbolContext)
{
diff --git a/src/plugins/debugger/cdb/cdbstacktracecontext.cpp b/src/plugins/debugger/cdb/cdbstacktracecontext.cpp
index 7cba6f903f..10b16acdfd 100644
--- a/src/plugins/debugger/cdb/cdbstacktracecontext.cpp
+++ b/src/plugins/debugger/cdb/cdbstacktracecontext.cpp
@@ -37,13 +37,14 @@
#include "cdbdumperhelper.h"
#include "cdbengine_p.h"
#include "debuggeractions.h"
-#include "debuggerplugin.h"
+#include "debuggercore.h"
#include "watchutils.h"
#include "threadshandler.h"
#include <utils/savedaction.h>
#include <QtCore/QDebug>
+#include <QtCore/QFileInfo>
enum { debug = 0 };
@@ -77,8 +78,9 @@ CdbStackTraceContext::createSymbolGroup(const CdbCore::ComInterfaces & /* cif */
// Exclude uninitialized variables if desired
QStringList uninitializedVariables;
const CdbCore::StackFrame &frame = stackFrameAt(index);
- if (theDebuggerAction(UseCodeModel)->isChecked())
- getUninitializedVariables(DebuggerPlugin::instance()->cppCodeModelSnapshot(), frame.function, frame.fileName, frame.line, &uninitializedVariables);
+ if (debuggerCore()->action(UseCodeModel)->isChecked())
+ getUninitializedVariables(debuggerCore()->cppCodeModelSnapshot(),
+ frame.function, frame.fileName, frame.line, &uninitializedVariables);
if (debug)
qDebug() << frame << uninitializedVariables;
CdbSymbolGroupContext *sc = CdbSymbolGroupContext::create(prefix,
@@ -103,14 +105,14 @@ QList<StackFrame> CdbStackTraceContext::stackFrames() const
// Convert from Core data structures
QList<StackFrame> rc;
const int count = frameCount();
- const QString hexPrefix = QLatin1String("0x");
for(int i = 0; i < count; i++) {
const CdbCore::StackFrame &coreFrame = stackFrameAt(i);
StackFrame frame;
frame.level = i;
frame.file = coreFrame.fileName;
+ frame.usable = !frame.file.isEmpty() && QFileInfo(frame.file).isFile();
frame.line = coreFrame.line;
- frame.function =coreFrame.function;
+ frame.function = coreFrame.function;
frame.from = coreFrame.module;
frame.address = coreFrame.address;
rc.push_back(frame);
diff --git a/src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp b/src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp
index 2ad7321720..89be4bf7c6 100644
--- a/src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp
+++ b/src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp
@@ -38,6 +38,7 @@
#include "watchutils.h"
#include "debuggeractions.h"
#include "coreengine.h"
+#include "debuggercore.h"
#include <QtCore/QDebug>
#include <QtCore/QTextStream>
@@ -323,7 +324,7 @@ CdbSymbolGroupContext::CdbSymbolGroupContext(const QString &prefix,
CdbCore::SymbolGroupContext(prefix, symbolGroup,
dumper->comInterfaces()->debugDataSpaces,
uninitializedVariables),
- m_useDumpers(dumper->isEnabled() && theDebuggerBoolSetting(UseDebuggingHelpers)),
+ m_useDumpers(dumper->isEnabled() && debuggerCore()->boolSetting(UseDebuggingHelpers)),
m_dumper(dumper)
{
setShadowedNameFormat(WatchData::shadowedNameFormat());
diff --git a/src/plugins/debugger/cdb/cdbsymbolpathlisteditor.cpp b/src/plugins/debugger/cdb/cdbsymbolpathlisteditor.cpp
deleted file mode 100644
index 8c35590033..0000000000
--- a/src/plugins/debugger/cdb/cdbsymbolpathlisteditor.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#include "cdbsymbolpathlisteditor.h"
-#include "cdboptions.h"
-
-#include <utils/pathchooser.h>
-
-#include <QtCore/QDir>
-#include <QtCore/QDebug>
-#include <QtGui/QFileDialog>
-#include <QtGui/QAction>
-#include <QtGui/QDialogButtonBox>
-#include <QtGui/QVBoxLayout>
-#include <QtGui/QFormLayout>
-#include <QtGui/QMessageBox>
-
-namespace Debugger {
-namespace Internal {
-
-CacheDirectoryDialog::CacheDirectoryDialog(QWidget *parent) :
- QDialog(parent), m_chooser(new Utils::PathChooser),
- m_buttonBox(new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel))
-{
- setWindowTitle(tr("Select Local Cache Folder"));
- setModal(true);
- setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
-
- QFormLayout *formLayout = new QFormLayout;
- m_chooser->setExpectedKind(Utils::PathChooser::Directory);
- m_chooser->setMinimumWidth(400);
- formLayout->addRow(tr("Path:"), m_chooser);
-
- QVBoxLayout *mainLayout = new QVBoxLayout;
- mainLayout->addLayout(formLayout);
- mainLayout->addWidget(m_buttonBox);
-
- setLayout(mainLayout);
-
- connect(m_buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
- connect(m_buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
-}
-
-void CacheDirectoryDialog::setPath(const QString &p)
-{
- m_chooser->setPath(p);
-}
-
-QString CacheDirectoryDialog::path() const
-{
- return m_chooser->path();
-}
-
-void CacheDirectoryDialog::accept()
-{
- // Ensure path exists
- QString cache = path();
- if (cache.isEmpty())
- return;
- QFileInfo fi(cache);
- // Folder exists - all happy.
- if (fi.isDir()) {
- QDialog::accept();
- return;
- }
- // Does a file of the same name exist?
- if (fi.exists()) {
- QMessageBox::warning(this, tr("Already Exists"),
- tr("A file named '%1' already exists.").arg(cache));
- return;
- }
- // Create
- QDir root(QDir::root());
- if (!root.mkpath(cache)) {
- QMessageBox::warning(this, tr("Cannot Create"),
- tr("The folder '%1' could not be created.").arg(cache));
- return;
- }
- QDialog::accept();
-}
-
-CdbSymbolPathListEditor::CdbSymbolPathListEditor(QWidget *parent) :
- Utils::PathListEditor(parent)
-{
- //! Add Microsoft Symbol server connection
- QAction *action = insertAction(lastAddActionIndex() + 1, tr("Symbol Server..."), this, SLOT(addSymbolServer()));
- action->setToolTip(tr("Adds the Microsoft symbol server providing symbols for operating system libraries."
- "Requires specifying a local cache directory."));
-}
-
-QString CdbSymbolPathListEditor::promptCacheDirectory(QWidget *parent)
-{
- CacheDirectoryDialog dialog(parent);
- dialog.setPath(QDir::tempPath() + QDir::separator() + QLatin1String("symbolcache"));
- if (dialog.exec() != QDialog::Accepted)
- return QString();
- return dialog.path();
-}
-
-void CdbSymbolPathListEditor::addSymbolServer()
-{
- const QString cacheDir = promptCacheDirectory(this);
- if (!cacheDir.isEmpty())
- insertPathAtCursor(CdbOptions::symbolServerPath(cacheDir));
-}
-
-} // namespace Internal
-} // namespace Debugger
diff --git a/src/plugins/debugger/cdb/cdbsymbolpathlisteditor.h b/src/plugins/debugger/cdb/cdbsymbolpathlisteditor.h
deleted file mode 100644
index ed470cad06..0000000000
--- a/src/plugins/debugger/cdb/cdbsymbolpathlisteditor.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#ifndef SYMBOLPATHLISTEDITOR_H
-#define SYMBOLPATHLISTEDITOR_H
-
-#include <utils/pathlisteditor.h>
-
-#include <QtGui/QDialog>
-
-namespace Utils {
- class PathChooser;
-}
-
-QT_BEGIN_NAMESPACE
-class QDialogButtonBox;
-QT_END_NAMESPACE
-
-namespace Debugger {
-namespace Internal {
-
-// Internal helper dialog prompting for a cache directory
-// using a PathChooser.
-// Note that QFileDialog does not offer a way of suggesting
-// a non-existent folder, which is in turn automatically
-// created. This is done here (suggest $TEMP\symbolcache
-// regardless of its existence).
-
-class CacheDirectoryDialog : public QDialog {
- Q_OBJECT
-public:
- explicit CacheDirectoryDialog(QWidget *parent = 0);
-
- void setPath(const QString &p);
- QString path() const;
-
- virtual void accept();
-
-private:
- Utils::PathChooser *m_chooser;
- QDialogButtonBox *m_buttonBox;
-};
-
-class CdbSymbolPathListEditor : public Utils::PathListEditor
-{
- Q_OBJECT
-public:
- explicit CdbSymbolPathListEditor(QWidget *parent = 0);
-
- static QString promptCacheDirectory(QWidget *parent);
-
-private slots:
- void addSymbolServer();
-};
-
-} // namespace Internal
-} // namespace Debugger
-
-#endif // SYMBOLPATHLISTEDITOR_H
diff --git a/src/plugins/debugger/cdb/corebreakpoint.cpp b/src/plugins/debugger/cdb/corebreakpoint.cpp
index e36a7fad81..b4f005a131 100644
--- a/src/plugins/debugger/cdb/corebreakpoint.cpp
+++ b/src/plugins/debugger/cdb/corebreakpoint.cpp
@@ -33,8 +33,9 @@
#include "corebreakpoint.h"
#include "coreengine.h"
-#include "dbgwinutils.h"
-
+#ifndef TEST_COMPILE // Usage in manual tests
+# include "dbgwinutils.h"
+#endif
#include <utils/qtcassert.h>
#include <QtCore/QTextStream>
@@ -250,6 +251,9 @@ Q_GLOBAL_STATIC(NormalizedFileCache, normalizedFileNameCache)
QString BreakPoint::normalizeFileName(const QString &f)
{
+#ifdef TEST_COMPILE // Usage in manual tests
+ return f;
+#else
QTC_ASSERT(!f.isEmpty(), return f)
const NormalizedFileCache::const_iterator it = normalizedFileNameCache()->constFind(f);
if (it != normalizedFileNameCache()->constEnd())
@@ -260,6 +264,7 @@ QString BreakPoint::normalizeFileName(const QString &f)
normalizedName[0] = normalizedName.at(0).toUpper();
normalizedFileNameCache()->insert(f, normalizedName);
return normalizedName;
+#endif
}
void BreakPoint::clearNormalizeFileNameCache()
diff --git a/src/plugins/debugger/cdb/coreengine.cpp b/src/plugins/debugger/cdb/coreengine.cpp
index 97ed051d0f..e888953138 100644
--- a/src/plugins/debugger/cdb/coreengine.cpp
+++ b/src/plugins/debugger/cdb/coreengine.cpp
@@ -469,7 +469,7 @@ void CoreEngine::resetModuleLoadTimer()
bool CoreEngine::startDebuggerWithExecutable(const QString &workingDirectory,
const QString &filename,
- const QStringList &args,
+ const QString &args,
const QStringList &envList,
QString *errorMessage)
{
@@ -848,11 +848,11 @@ bool CoreEngine::writeToDebuggee(const QByteArray &buffer, quint64 address, QStr
return true;
}
-bool CoreEngine::dissassemble(ULONG64 offset,
- unsigned long beforeLines,
- unsigned long afterLines,
- QString *target,
- QString *errorMessage)
+bool CoreEngine::disassemble(ULONG64 offset,
+ unsigned long beforeLines,
+ unsigned long afterLines,
+ QString *target,
+ QString *errorMessage)
{
const ULONG flags = DEBUG_DISASM_MATCHING_SYMBOLS|DEBUG_DISASM_SOURCE_LINE_NUMBER|DEBUG_DISASM_SOURCE_FILE_NAME;
// Catch the output by temporarily setting another handler.
diff --git a/src/plugins/debugger/cdb/coreengine.h b/src/plugins/debugger/cdb/coreengine.h
index 3265dd3027..8cc197fb45 100644
--- a/src/plugins/debugger/cdb/coreengine.h
+++ b/src/plugins/debugger/cdb/coreengine.h
@@ -90,7 +90,7 @@ public:
// Start functions
bool startDebuggerWithExecutable(const QString &workingDirectory,
const QString &filename,
- const QStringList &args,
+ const QString &args,
const QStringList &env,
QString *errorMessage);
@@ -151,8 +151,8 @@ public:
bool createDebuggeeAscIIString(const QString &s, ULONG64 *address, QString *errorMessage);
bool writeToDebuggee(const QByteArray &buffer, quint64 address, QString *errorMessage);
// Write to debuggee memory in chunks
- bool dissassemble(ULONG64 offset, unsigned long beforeLines, unsigned long afterLines,
- QString *target, QString *errorMessage);
+ bool disassemble(ULONG64 offset, unsigned long beforeLines, unsigned long afterLines,
+ QString *target, QString *errorMessage);
quint64 getSourceLineAddress(const QString &file, int line, QString *errorMessage) const;
diff --git a/src/plugins/debugger/cdb2/bytearrayinputstream.cpp b/src/plugins/debugger/cdb2/bytearrayinputstream.cpp
new file mode 100644
index 0000000000..a1b1d40a6c
--- /dev/null
+++ b/src/plugins/debugger/cdb2/bytearrayinputstream.cpp
@@ -0,0 +1,122 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "bytearrayinputstream.h"
+
+namespace Debugger {
+namespace Cdb {
+
+ByteArrayInputStream::ByteArrayInputStream(QByteArray &ba) :
+ m_target(ba), m_integerBase(10), m_hexPrefix(false), m_width(0)
+{
+}
+
+void ByteArrayInputStream::appendSeparator(char c)
+{
+ if (!m_target.isEmpty() && !m_target.endsWith(c))
+ m_target.append(c);
+}
+
+void hexPrefixOn(ByteArrayInputStream &bs)
+{
+ bs.setHexPrefix(true);
+}
+
+void hexPrefixOff(ByteArrayInputStream &bs)
+{
+ bs.setHexPrefix(false);
+}
+
+void hex(ByteArrayInputStream &bs)
+{
+ bs.setIntegerBase(16);
+}
+
+void dec(ByteArrayInputStream &bs)
+{
+ bs.setIntegerBase(10);
+}
+
+void blankSeparator(ByteArrayInputStream &bs)
+{
+ bs.appendSeparator();
+}
+
+QByteArray trimFront(QByteArray in)
+{
+ if (in.isEmpty())
+ return in;
+ const int size = in.size();
+ int pos = 0;
+ for ( ; pos < size && isspace(in.at(pos)); pos++) ;
+ if (pos)
+ in.remove(0, pos);
+ return in;
+}
+
+QByteArray trimBack(QByteArray in)
+{
+ if (in.isEmpty())
+ return in;
+ const int size = in.size();
+ int pos = size - 1;
+ for ( ; pos >= 0 && isspace(in.at(pos)); pos--) ;
+ if (pos != size - 1)
+ in.truncate(pos + 1);
+ return in;
+}
+
+
+// Simplify: replace tabs, find all occurrences
+// of 2 blanks, check further up for blanks and remove that bit.
+QByteArray simplify(const QByteArray &inIn)
+{
+ if (inIn.isEmpty())
+ return inIn;
+ QByteArray in = trimFront(trimBack(inIn));
+ in.replace('\t', ' ');
+ in.replace('\n', ' ');
+ in.replace('\r', ' ');
+ const QByteArray twoBlanks = " ";
+ while (true) {
+ const int pos = in.indexOf(twoBlanks);
+ if (pos != -1) {
+ const int size = in.size();
+ int endPos = pos + twoBlanks.size();
+ for ( ; endPos < size && in.at(endPos) == ' '; endPos++) ;
+ in.remove(pos + 1, endPos - pos - 1);
+ } else {
+ break;
+ }
+ }
+ return in;
+}
+
+} // namespace Cdb
+} // namespace Debugger
diff --git a/src/plugins/debugger/cdb2/bytearrayinputstream.h b/src/plugins/debugger/cdb2/bytearrayinputstream.h
new file mode 100644
index 0000000000..d9b8258adc
--- /dev/null
+++ b/src/plugins/debugger/cdb2/bytearrayinputstream.h
@@ -0,0 +1,108 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 BYTEARRAYINPUTSTREAM_H
+#define BYTEARRAYINPUTSTREAM_H
+
+#include <QtCore/QByteArray>
+#include <QtCore/QString>
+
+namespace Debugger {
+namespace Cdb {
+
+class ByteArrayInputStream
+{
+ Q_DISABLE_COPY(ByteArrayInputStream)
+public:
+ typedef void (ModifierFunc)(ByteArrayInputStream &s);
+
+ explicit ByteArrayInputStream(QByteArray &ba);
+
+ ByteArrayInputStream &operator<<(char a) { m_target.append(a); return *this; }
+ ByteArrayInputStream &operator<<(const QByteArray &a) { m_target.append(a); return *this; }
+ ByteArrayInputStream &operator<<(const char *a) { m_target.append(a); return *this; }
+ ByteArrayInputStream &operator<<(const QString &a) { m_target.append(a.toLatin1()); return *this; }
+
+ ByteArrayInputStream &operator<<(int i) { appendInt(i); return *this; }
+ ByteArrayInputStream &operator<<(unsigned i) { appendInt(i); return *this; }
+ ByteArrayInputStream &operator<<(quint64 i) { appendInt(i); return *this; }
+ ByteArrayInputStream &operator<<(qint64 i) { appendInt(i); return *this; }
+
+ // Stream a modifier by invoking it
+ ByteArrayInputStream &operator<<(ModifierFunc mf) { mf(*this); return *this; }
+
+ void setHexPrefix(bool hp) { m_hexPrefix = hp; }
+ bool hexPrefix() const { return m_hexPrefix; }
+ void setIntegerBase(int b) { m_integerBase = b; }
+ int integerBase() const { return m_integerBase; }
+ // Append a separator if required (target does not end with it)
+ void appendSeparator(char c = ' ');
+
+private:
+ template <class IntType> void appendInt(IntType i);
+
+ QByteArray &m_target;
+ int m_integerBase;
+ bool m_hexPrefix;
+ int m_width;
+};
+
+template <class IntType>
+void ByteArrayInputStream::appendInt(IntType i)
+{
+ const bool hexPrefix = m_integerBase == 16 && m_hexPrefix;
+ if (hexPrefix)
+ m_target.append("0x");
+ const QByteArray n = QByteArray::number(i, m_integerBase);
+ if (m_width > 0) {
+ int pad = m_width - n.size();
+ if (hexPrefix)
+ pad -= 2;
+ if (pad > 0)
+ m_target.append(QByteArray(pad, '0'));
+ }
+ m_target.append(n);
+}
+
+// Streamable modifiers for ByteArrayInputStream
+void hexPrefixOn(ByteArrayInputStream &bs);
+void hexPrefixOff(ByteArrayInputStream &bs);
+void hex(ByteArrayInputStream &bs);
+void dec(ByteArrayInputStream &bs);
+void blankSeparator(ByteArrayInputStream &bs);
+
+// Bytearray parse helpers
+QByteArray trimFront(QByteArray in);
+QByteArray trimBack(QByteArray in);
+QByteArray simplify(const QByteArray &inIn);
+
+} // namespace Cdb
+} // namespace Debugger
+
+#endif // BYTEARRAYINPUTSTREAM_H
diff --git a/src/plugins/debugger/cdb2/cdb2.pri b/src/plugins/debugger/cdb2/cdb2.pri
new file mode 100644
index 0000000000..a9e3e1cc5b
--- /dev/null
+++ b/src/plugins/debugger/cdb2/cdb2.pri
@@ -0,0 +1,16 @@
+HEADERS += $$PWD/cdbengine2.h \
+ cdb2/bytearrayinputstream.h \
+ cdb2/cdbparsehelpers.h \
+ cdb2/cdboptions2.h \
+ cdb2/cdboptionspage2.h
+
+SOURCES += $$PWD/cdbengine2.cpp \
+ cdb2/bytearrayinputstream.cpp \
+ cdb2/cdbparsehelpers.cpp \
+ cdb2/cdboptions2.cpp \
+ cdb2/cdboptionspage2.cpp
+
+FORMS += cdb2/cdboptionspagewidget2.ui
+
+INCLUDEPATH*=$$PWD
+DEPENDPATH*=$$PWD
diff --git a/src/plugins/debugger/cdb2/cdbengine2.cpp b/src/plugins/debugger/cdb2/cdbengine2.cpp
new file mode 100644
index 0000000000..2050f05e9b
--- /dev/null
+++ b/src/plugins/debugger/cdb2/cdbengine2.cpp
@@ -0,0 +1,1916 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "cdbengine2.h"
+#include "cdboptions2.h"
+#include "cdboptionspage2.h"
+#include "bytearrayinputstream.h"
+#include "breakpoint.h"
+#include "breakhandler.h"
+#include "stackframe.h"
+#include "stackhandler.h"
+#include "watchhandler.h"
+#include "threadshandler.h"
+#include "debuggeractions.h"
+#include "debuggercore.h"
+#include "registerhandler.h"
+#include "disassembleragent.h"
+#include "memoryagent.h"
+#include "debuggertooltip.h"
+#include "cdbparsehelpers.h"
+#include "watchutils.h"
+#include "gdb/gdbmi.h"
+#include "shared/cdbsymbolpathlisteditor.h"
+
+#include <coreplugin/icore.h>
+#include <texteditor/itexteditor.h>
+
+#include <utils/synchronousprocess.h>
+#include <utils/winutils.h>
+#include <utils/qtcassert.h>
+#include <utils/savedaction.h>
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QFileInfo>
+#include <QtCore/QDir>
+#include <QtCore/QDebug>
+#include <QtCore/QTextStream>
+#include <QtCore/QDateTime>
+#include <QtGui/QToolTip>
+
+#ifdef Q_OS_WIN
+# include <utils/winutils.h>
+# include "dbgwinutils.h"
+#endif
+
+#include <cctype>
+
+Q_DECLARE_METATYPE(Debugger::Internal::DisassemblerAgent*)
+Q_DECLARE_METATYPE(Debugger::Internal::MemoryAgent*)
+
+enum { debug = 0 };
+enum { debugLocals = 0 };
+enum { debugBreakpoints = 0 };
+
+#if 0
+# define STATE_DEBUG(func, line, notifyFunc) qDebug("%s at %s:%d", notifyFunc, func, line);
+#else
+# define STATE_DEBUG(func, line, notifyFunc)
+#endif
+
+/* CdbEngine version 2: Run the CDB process on pipes and parse its output.
+ * The engine relies on a CDB extension Qt Creator provides as an extension
+ * library (32/64bit). It serves to:
+ * - Notify the engine about the state of the debugging session:
+ * + idle: (hooked with .idle_cmd) debuggee stopped
+ * + accessible: Debuggee stopped, cdb.exe accepts commands
+ * + inaccessible: Debuggee runs, no way to post commands
+ * + session active/inactive: Lost debuggee, terminating.
+ * - Hook up with output/event callbacks and produce formatted output
+ * - Provide some extension commands that produce output in a standardized (GDBMI)
+ * format that ends up in handleExtensionMessage().
+ * + pid Return debuggee pid for interrupting.
+ * + locals Print locals from SymbolGroup
+ * + expandLocals Expand locals in symbol group
+ * + registers, modules, threads
+ * Commands can be posted:
+ * postCommand: Does not expect a reply
+ * postBuiltinCommand: Run a builtin-command producing free-format, multiline output
+ * that is captured by enclosing it in special tokens using the 'echo' command and
+ * then invokes a callback with a CdbBuiltinCommand structure.
+ * postExtensionCommand: Run a command provided by the extension producing
+ * one-line output and invoke a callback with a CdbExtensionCommand structure. */
+
+namespace Debugger {
+namespace Cdb {
+
+static const char localsPrefixC[] = "local.";
+
+using namespace Debugger::Internal;
+
+struct MemoryViewCookie {
+ explicit MemoryViewCookie(MemoryAgent *a = 0, QObject *e = 0,
+ quint64 addr = 0, quint64 l = 0) :
+ agent(a), editorToken(e), address(addr), length(l) {}
+
+ MemoryAgent *agent;
+ QObject *editorToken;
+ quint64 address;
+ quint64 length;
+};
+
+struct SourceLocationCookie {
+ explicit SourceLocationCookie(const QString &f = QString(), int l = 0) :
+ fileName(f), lineNumber(l) {}
+
+ QString fileName;
+ int lineNumber;
+};
+
+} // namespace Cdb
+} // namespace Debugger
+
+Q_DECLARE_METATYPE(Debugger::Cdb::MemoryViewCookie)
+Q_DECLARE_METATYPE(Debugger::Cdb::SourceLocationCookie)
+
+namespace Debugger {
+namespace Cdb {
+
+// Base data structure for command queue entries with callback
+struct CdbCommandBase
+{
+ typedef CdbEngine::BuiltinCommandHandler CommandHandler;
+
+ CdbCommandBase();
+ CdbCommandBase(const QByteArray &cmd, int token, unsigned flags,
+ unsigned nc, const QVariant &cookie);
+
+ int token;
+ unsigned flags;
+ QByteArray command;
+ QVariant cookie;
+ // Continue with another commands as specified in CommandSequenceFlags
+ unsigned commandSequence;
+};
+
+CdbCommandBase::CdbCommandBase() :
+ token(0), flags(0), commandSequence(0)
+{
+}
+
+CdbCommandBase::CdbCommandBase(const QByteArray &cmd, int t, unsigned f,
+ unsigned nc, const QVariant &c) :
+ token(t), flags(f), command(cmd), cookie(c), commandSequence(nc)
+{
+}
+
+// Queue entry for builtin commands producing free-format
+// line-by-line output.
+struct CdbBuiltinCommand : public CdbCommandBase
+{
+ typedef CdbEngine::BuiltinCommandHandler CommandHandler;
+
+ CdbBuiltinCommand() {}
+ CdbBuiltinCommand(const QByteArray &cmd, int token, unsigned flags,
+ CommandHandler h,
+ unsigned nc, const QVariant &cookie) :
+ CdbCommandBase(cmd, token, flags, nc, cookie), handler(h) {}
+
+
+ QByteArray joinedReply() const;
+
+ CommandHandler handler;
+ QList<QByteArray> reply;
+};
+
+QByteArray CdbBuiltinCommand::joinedReply() const
+{
+ if (reply.isEmpty())
+ return QByteArray();
+ QByteArray answer;
+ answer.reserve(120 * reply.size());
+ foreach (const QByteArray &l, reply) {
+ answer += l;
+ answer += '\n';
+ }
+ return answer;
+}
+
+// Queue entry for Qt Creator extension commands producing one-line
+// output with success flag and error message.
+struct CdbExtensionCommand : public CdbCommandBase
+{
+ typedef CdbEngine::ExtensionCommandHandler CommandHandler;
+
+ CdbExtensionCommand() : success(false) {}
+ CdbExtensionCommand(const QByteArray &cmd, int token, unsigned flags,
+ CommandHandler h,
+ unsigned nc, const QVariant &cookie) :
+ CdbCommandBase(cmd, token, flags, nc, cookie), handler(h),success(false) {}
+
+ CommandHandler handler;
+ QByteArray reply;
+ QByteArray errorMessage;
+ bool success;
+};
+
+template <class CommandPtrType>
+int indexOfCommand(const QList<CommandPtrType> &l, int token)
+{
+ const int count = l.size();
+ for (int i = 0; i < count; i++)
+ if (l.at(i)->token == token)
+ return i;
+ return -1;
+}
+
+static inline bool validMode(DebuggerStartMode sm)
+{
+ switch (sm) {
+ case NoStartMode:
+ case AttachTcf:
+ case AttachCore:
+ case StartRemoteGdb:
+ return false;
+ default:
+ break;
+ }
+ return true;
+}
+
+// Accessed by RunControlFactory
+DebuggerEngine *createCdbEngine(const DebuggerStartParameters &sp, QString *errorMessage)
+{
+#ifdef Q_OS_WIN
+ CdbOptionsPage *op = CdbOptionsPage::instance();
+ QTC_ASSERT(op, return 0);
+ if (validMode(sp.startMode))
+ return new CdbEngine(sp, op->options());
+#else
+ Q_UNUSED(sp)
+#endif
+ *errorMessage = QString::fromLatin1("Unsuppported debug mode");
+ return 0;
+}
+
+bool isCdbEngineEnabled()
+{
+#ifdef Q_OS_WIN
+ return CdbOptionsPage::instance() && CdbOptionsPage::instance()->options()->enabled;
+#else
+ return false;
+#endif
+}
+
+void addCdb2OptionPages(QList<Core::IOptionsPage *> *opts)
+{
+ opts->push_back(new CdbOptionsPage);
+}
+
+#define QT_CREATOR_CDB_EXT "qtcreatorcdbext"
+
+static inline Utils::SavedAction *theAssemblerAction()
+{
+ return debuggerCore()->action(OperateByInstruction);
+}
+
+CdbEngine::CdbEngine(const DebuggerStartParameters &sp, const OptionsPtr &options) :
+ DebuggerEngine(sp),
+ m_creatorExtPrefix("<qtcreatorcdbext>|"),
+ m_tokenPrefix("<token>"),
+ m_options(options),
+ m_inferiorPid(0),
+ m_accessible(false),
+ m_specialStopMode(NoSpecialStop),
+ m_nextCommandToken(0),
+ m_nextBreakpointNumber(1),
+ m_currentBuiltinCommandIndex(-1),
+ m_extensionCommandPrefixBA("!"QT_CREATOR_CDB_EXT"."),
+ m_operateByInstructionPending(true),
+ m_operateByInstruction(true), // Default CDB setting
+ m_notifyEngineShutdownOnTermination(false),
+ m_hasDebuggee(false),
+ m_elapsedLogTime(0)
+{
+ Utils::SavedAction *assemblerAction = theAssemblerAction();
+ m_operateByInstructionPending = assemblerAction->isChecked();
+ connect(assemblerAction, SIGNAL(triggered(bool)), this, SLOT(operateByInstructionTriggered(bool)));
+
+ setObjectName(QLatin1String("CdbEngine"));
+ connect(&m_process, SIGNAL(finished(int)), this, SLOT(processFinished()));
+ connect(&m_process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(processError()));
+ connect(&m_process, SIGNAL(readyReadStandardOutput()), this, SLOT(readyReadStandardOut()));
+ connect(&m_process, SIGNAL(readyReadStandardError()), this, SLOT(readyReadStandardOut()));
+}
+
+CdbEngine::~CdbEngine()
+{
+}
+
+void CdbEngine::operateByInstructionTriggered(bool operateByInstruction)
+{
+ if (state() == InferiorStopOk) {
+ syncOperateByInstruction(operateByInstruction);
+ } else {
+ // To be set next time session becomes accessible
+ m_operateByInstructionPending = operateByInstruction;
+ }
+}
+
+void CdbEngine::syncOperateByInstruction(bool operateByInstruction)
+{
+ if (m_operateByInstruction == operateByInstruction)
+ return;
+ QTC_ASSERT(m_accessible, return; )
+ m_operateByInstruction = operateByInstruction;
+ postCommand(m_operateByInstruction ? QByteArray("l-t") : QByteArray("l+t"), 0);
+ postCommand(m_operateByInstruction ? QByteArray("l-s") : QByteArray("l+s"), 0);
+}
+
+void CdbEngine::setToolTipExpression(const QPoint &mousePos, TextEditor::ITextEditor *editor, int cursorPos)
+{
+ if (debug)
+ qDebug() << Q_FUNC_INFO;
+ // Need a stopped debuggee and a cpp file in a valid frame
+ if (state() != InferiorStopOk || !isCppEditor(editor) || stackHandler()->currentIndex() < 0)
+ return;
+ // Determine expression and function
+ int line;
+ int column;
+ QString function;
+ const QString exp = cppExpressionAt(editor, cursorPos, &line, &column, &function);
+ // Are we in the current stack frame
+ if (function.isEmpty() || exp.isEmpty() || function != stackHandler()->currentFrame().function)
+ return;
+ // No numerical or any other expressions [yet]
+ if (!(exp.at(0).isLetter() || exp.at(0) == QLatin1Char('_')))
+ return;
+ const QByteArray iname = QByteArray(localsPrefixC) + exp.toAscii();
+ if (const WatchData *data = watchHandler()->findItem(iname)) {
+ QToolTip::hideText();
+ QToolTip::showText(mousePos, data->toToolTip());
+ }
+}
+
+void CdbEngine::setupEngine()
+{
+ // Nag to add symbol server
+ if (Debugger::Internal::CdbSymbolPathListEditor::promptToAddSymbolServer(CdbOptions::settingsGroup(),
+ &(m_options->symbolPaths)))
+ m_options->toSettings(Core::ICore::instance()->settings());
+
+ QString errorMessage;
+ if (!doSetupEngine(&errorMessage)) { // Start engine which will run until initial breakpoint
+ showMessage(errorMessage, LogError);
+ notifyEngineSetupFailed();
+ }
+}
+
+// Determine full path to the CDB extension library.
+QString CdbEngine::extensionLibraryName(bool is64Bit)
+{
+ // Determine extension lib name and path to use
+ QString rc;
+ QTextStream(&rc) << QFileInfo(QCoreApplication::applicationDirPath()).path()
+ << "/lib/" << (is64Bit ? QT_CREATOR_CDB_EXT"64" : QT_CREATOR_CDB_EXT"32")
+ << '/' << QT_CREATOR_CDB_EXT << ".dll";
+ return rc;
+}
+
+// Determine environment for CDB.exe, start out with run config and
+// add CDB extension path merged with system value should there be one.
+static QStringList mergeEnvironment(QStringList runConfigEnvironment,
+ QString cdbExtensionPath)
+{
+ // Determine CDB extension path from Qt Creator
+ static const char cdbExtensionPathVariableC[] = "_NT_DEBUGGER_EXTENSION_PATH";
+ const QByteArray oldCdbExtensionPath = qgetenv(cdbExtensionPathVariableC);
+ if (!oldCdbExtensionPath.isEmpty()) {
+ cdbExtensionPath.append(QLatin1Char(';'));
+ cdbExtensionPath.append(QString::fromLocal8Bit(oldCdbExtensionPath));
+ }
+ // We do not assume someone sets _NT_DEBUGGER_EXTENSION_PATH in the run
+ // config, just to make sure, delete any existing entries
+ const QString cdbExtensionPathVariableAssign =
+ QLatin1String(cdbExtensionPathVariableC) + QLatin1Char('=');
+ for (QStringList::iterator it = runConfigEnvironment.begin(); it != runConfigEnvironment.end() ; ) {
+ if (it->startsWith(cdbExtensionPathVariableAssign)) {
+ it = runConfigEnvironment.erase(it);
+ break;
+ } else {
+ ++it;
+ }
+ }
+ runConfigEnvironment.append(cdbExtensionPathVariableAssign +
+ QDir::toNativeSeparators(cdbExtensionPath));
+ return runConfigEnvironment;
+}
+
+int CdbEngine::elapsedLogTime() const
+{
+ const int elapsed = m_logTime.elapsed();
+ const int delta = elapsed - m_elapsedLogTime;
+ m_elapsedLogTime = elapsed;
+ return delta;
+}
+
+bool CdbEngine::doSetupEngine(QString *errorMessage)
+{
+ m_logTime.start();
+ // Determine extension lib name and path to use
+ // The extension is passed as relative name with the path variable set
+ //(does not work with absolute path names)
+ const QFileInfo extensionFi(CdbEngine::extensionLibraryName(m_options->is64bit));
+ if (!extensionFi.isFile()) {
+ *errorMessage = QString::fromLatin1("Internal error: The extension %1 cannot be found.").
+ arg(QDir::toNativeSeparators(extensionFi.absoluteFilePath()));
+ return false;
+ }
+ const QString extensionFileName = extensionFi.fileName();
+ // Prepare arguments
+ const DebuggerStartParameters &sp = startParameters();
+ QStringList arguments;
+ const bool isRemote = sp.startMode == AttachToRemote;
+ if (isRemote) { // Must be first
+ arguments << QLatin1String("-remote") << sp.remoteChannel;
+ } else {
+ arguments << (QLatin1String("-a") + extensionFileName);
+ }
+ // Source line info/No terminal breakpoint / Pull extension
+ arguments << QLatin1String("-lines") << QLatin1String("-G")
+ // register idle (debuggee stop) notification
+ << QLatin1String("-c")
+ << QString::fromAscii(".idle_cmd " + m_extensionCommandPrefixBA + "idle");
+ if (sp.useTerminal) // Separate console
+ arguments << QLatin1String("-2");
+ if (!m_options->symbolPaths.isEmpty())
+ arguments << QLatin1String("-y") << m_options->symbolPaths.join(QString(QLatin1Char(';')));
+ if (!m_options->sourcePaths.isEmpty())
+ arguments << QLatin1String("-srcpath") << m_options->sourcePaths.join(QString(QLatin1Char(';')));
+ switch (sp.startMode) {
+ case StartInternal:
+ case StartExternal:
+ arguments << QDir::toNativeSeparators(sp.executable);
+ break;
+ case AttachToRemote:
+ break;
+ case AttachExternal:
+ case AttachCrashedExternal:
+ arguments << QLatin1String("-p") << QString::number(sp.attachPID);
+ if (sp.startMode == AttachCrashedExternal)
+ arguments << QLatin1String("-e") << sp.crashParameter << QLatin1String("-g");
+ break;
+ default:
+ *errorMessage = QString::fromLatin1("Internal error: Unsupported start mode %1.").arg(sp.startMode);
+ return false;
+ }
+ const QString executable = m_options->executable;
+ const QString msg = QString::fromLatin1("Launching %1 %2\nusing %3 of %4.").
+ arg(QDir::toNativeSeparators(executable),
+ arguments.join(QString(QLatin1Char(' '))),
+ QDir::toNativeSeparators(extensionFi.absoluteFilePath()),
+ extensionFi.lastModified().toString(Qt::SystemLocaleShortDate));
+ showMessage(msg, LogMisc);
+
+ m_outputBuffer.clear();
+ m_process.setEnvironment(mergeEnvironment(sp.environment.toStringList(), extensionFi.absolutePath()));
+#ifdef Q_OS_WIN
+ if (!sp.processArgs.isEmpty()) // Appends
+ m_process.setNativeArguments(sp.processArgs);
+#endif
+ m_process.start(executable, arguments);
+ if (!m_process.waitForStarted()) {
+ *errorMessage = QString::fromLatin1("Internal error: Cannot start process %1: %2").
+ arg(QDir::toNativeSeparators(executable), m_process.errorString());
+ return false;
+ }
+#ifdef Q_OS_WIN
+ const unsigned long pid = Utils::winQPidToPid(m_process.pid());
+#else
+ const unsigned long pid = 0;
+#endif
+ showMessage(QString::fromLatin1("%1 running as %2").
+ arg(QDir::toNativeSeparators(executable)).arg(pid), LogMisc);
+ m_hasDebuggee = true;
+ if (isRemote) { // We do not get an 'idle' in a remote session, but are accessible
+ m_accessible = true;
+ const QByteArray loadCommand = QByteArray(".load ")
+ + extensionFileName.toLocal8Bit();
+ postCommand(loadCommand, 0);
+ notifyEngineSetupOk();
+ }
+ return true;
+}
+
+void CdbEngine::setupInferior()
+{
+ if (debug)
+ qDebug("setupInferior");
+ attemptBreakpointSynchronization();
+ postExtensionCommand("pid", QByteArray(), 0, &CdbEngine::handlePid);
+}
+
+void CdbEngine::runEngine()
+{
+ if (debug)
+ qDebug("runEngine");
+ foreach (const QString &breakEvent, m_options->breakEvents)
+ postCommand(QByteArray("sxe ") + breakEvent.toAscii(), 0);
+ postCommand("g", 0);
+}
+
+bool CdbEngine::commandsPending() const
+{
+ return !m_builtinCommandQueue.isEmpty() || !m_extensionCommandQueue.isEmpty();
+}
+
+void CdbEngine::shutdownInferior()
+{
+ if (debug)
+ qDebug("CdbEngine::shutdownInferior in state '%s', process running %d", stateName(state()),
+ isCdbProcessRunning());
+
+ if (!isCdbProcessRunning()) { // Direct launch: Terminated with process.
+ if (debug)
+ qDebug("notifyInferiorShutdownOk");
+ notifyInferiorShutdownOk();
+ return;
+ }
+ if (!canInterruptInferior() || commandsPending()) {
+ notifyInferiorShutdownFailed();
+ return;
+ }
+
+ if (m_accessible) {
+ if (startParameters().startMode == AttachExternal || startParameters().startMode == AttachCrashedExternal)
+ detachDebugger();
+ if (debug)
+ qDebug("notifyInferiorShutdownOk");
+ notifyInferiorShutdownOk();
+ } else {
+ interruptInferior(); // Calls us again
+ }
+}
+
+/* shutdownEngine/processFinished:
+ * Note that in the case of launching a process by the debugger, the debugger
+ * automatically quits a short time after reporting the session becoming
+ * inaccessible without debuggee (notifyInferiorExited). In that case,
+ * processFinished() must not report any arbitrarily notifyEngineShutdownOk()
+ * as not to confuse the state engine.
+ */
+
+void CdbEngine::shutdownEngine()
+{
+ if (debug)
+ qDebug("CdbEngine::shutdownEngine in state '%s', process running %d,"
+ "accessible=%d,commands pending=%d",
+ stateName(state()), isCdbProcessRunning(), m_accessible,
+ commandsPending());
+
+ if (!isCdbProcessRunning()) { // Direct launch: Terminated with process.
+ if (debug)
+ qDebug("notifyEngineShutdownOk");
+ notifyEngineShutdownOk();
+ return;
+ }
+
+ // No longer trigger anything from messages
+ disconnect(&m_process, SIGNAL(readyReadStandardOutput()), this, 0);
+ disconnect(&m_process, SIGNAL(readyReadStandardError()), this, 0);
+ // Go for kill if there are commands pending.
+ if (m_accessible && !commandsPending()) {
+ // detach: Wait for debugger to finish.
+ if (startParameters().startMode == AttachExternal)
+ detachDebugger();
+ // Remote requires a bit more force to quit.
+ if (startParameters().startMode == AttachToRemote) {
+ postCommand(m_extensionCommandPrefixBA + "shutdownex", 0);
+ postCommand("qq", 0);
+ } else {
+ postCommand("q", 0);
+ }
+ m_notifyEngineShutdownOnTermination = true;
+ return;
+ } else {
+ // Remote process. No can do, currently
+ m_notifyEngineShutdownOnTermination = true;
+ Utils::SynchronousProcess::stopProcess(m_process);
+ return;
+ }
+ // Lost debuggee, debugger should quit anytime now
+ if (!m_hasDebuggee) {
+ m_notifyEngineShutdownOnTermination = true;
+ return;
+ }
+ interruptInferior();
+}
+
+void CdbEngine::processFinished()
+{
+ if (debug)
+ qDebug("CdbEngine::processFinished %dms '%s' notify=%d (exit state=%d, ex=%d)",
+ elapsedLogTime(), stateName(state()), m_notifyEngineShutdownOnTermination,
+ m_process.exitStatus(), m_process.exitCode());
+
+ const bool crashed = m_process.exitStatus() == QProcess::CrashExit;
+ if (crashed) {
+ showMessage(tr("CDB crashed"), LogError); // not in your life.
+ } else {
+ showMessage(tr("CDB exited (%1)").arg(m_process.exitCode()), LogMisc);
+ }
+
+ if (m_notifyEngineShutdownOnTermination) {
+ if (crashed) {
+ if (debug)
+ qDebug("notifyEngineIll");
+ notifyEngineIll();
+ } else {
+ if (debug)
+ qDebug("notifyEngineShutdownOk");
+ notifyEngineShutdownOk();
+ }
+ } else {
+ if (debug)
+ qDebug("notifyEngineSpontaneousShutdown");
+ notifyEngineSpontaneousShutdown();
+ }
+}
+
+void CdbEngine::detachDebugger()
+{
+ postCommand(".detach", 0);
+}
+
+void CdbEngine::updateWatchData(const Debugger::Internal::WatchData &dataIn,
+ const Debugger::Internal::WatchUpdateFlags & flags)
+{
+ if (debug)
+ qDebug("CdbEngine::updateWatchData() %dms %s incr=%d: %s",
+ elapsedLogTime(), stateName(state()),
+ flags.tryIncremental,
+ qPrintable(dataIn.toString()));
+
+ if (!dataIn.hasChildren) {
+ Debugger::Internal::WatchData data = dataIn;
+ data.setAllUnneeded();
+ watchHandler()->insertData(data);
+ return;
+ }
+ updateLocalVariable(dataIn.iname);
+}
+
+void CdbEngine::addLocalsOptions(ByteArrayInputStream &str) const
+{
+ if (debuggerCore()->boolSetting(UseDebuggingHelpers))
+ str << blankSeparator << "-c";
+ const QByteArray typeFormats = watchHandler()->typeFormatRequests();
+ if (!typeFormats.isEmpty())
+ str << blankSeparator << "-T " << typeFormats;
+ const QByteArray individualFormats = watchHandler()->individualFormatRequests();
+ if (!individualFormats.isEmpty())
+ str << blankSeparator << "-I " << individualFormats;
+}
+
+void CdbEngine::updateLocalVariable(const QByteArray &iname)
+{
+ const int stackFrame = stackHandler()->currentIndex();
+ if (stackFrame >= 0) {
+ QByteArray localsArguments;
+ ByteArrayInputStream str(localsArguments);
+ addLocalsOptions(str);
+ str << blankSeparator << stackFrame << ' ' << iname;
+ postExtensionCommand("locals", localsArguments, 0, &CdbEngine::handleLocals);
+ } else {
+ qWarning("Internal error; no stack frame in updateLocalVariable");
+ }
+}
+
+unsigned CdbEngine::debuggerCapabilities() const
+{
+ return DisassemblerCapability | RegisterCapability | ShowMemoryCapability
+ |WatchpointCapability|JumpToLineCapability
+ |BreakOnThrowAndCatchCapability; // Sort-of: Can break on throw().
+}
+
+void CdbEngine::executeStep()
+{
+ postCommand(QByteArray("t"), 0); // Step into-> t (trace)
+ notifyInferiorRunRequested();
+}
+
+void CdbEngine::executeStepOut()
+{
+ postCommand(QByteArray("gu"), 0); // Step out-> gu (go up)
+ notifyInferiorRunRequested();
+}
+
+void CdbEngine::executeNext()
+{
+ postCommand(QByteArray("p"), 0); // Step over -> p
+ notifyInferiorRunRequested();
+}
+
+void CdbEngine::executeStepI()
+{
+ executeStep();
+}
+
+void CdbEngine::executeNextI()
+{
+ executeNext();
+}
+
+void CdbEngine::continueInferior()
+{
+ notifyInferiorRunRequested();
+ doContinueInferior();
+}
+
+void CdbEngine::doContinueInferior()
+{
+ postCommand(QByteArray("g"), 0);
+}
+
+bool CdbEngine::canInterruptInferior() const
+{
+ return startParameters().startMode != AttachToRemote;
+}
+
+void CdbEngine::interruptInferior()
+{
+ if (canInterruptInferior()) {
+ doInterruptInferior(NoSpecialStop);
+ } else {
+ showMessage(tr("Interrupting is not possible in remote sessions."), LogError);
+ notifyInferiorStopOk();
+ notifyInferiorRunRequested();
+ notifyInferiorRunOk();
+ }
+}
+
+void CdbEngine::doInterruptInferior(SpecialStopMode sm)
+{
+#ifdef Q_OS_WIN
+ const SpecialStopMode oldSpecialMode = m_specialStopMode;
+ m_specialStopMode = sm;
+ QString errorMessage;
+ if (!Debugger::Internal::winDebugBreakProcess(m_inferiorPid, &errorMessage)) {
+ m_specialStopMode = oldSpecialMode;
+ showMessage(errorMessage, LogError);
+ }
+#else
+ Q_UNUSED(sm)
+#endif
+}
+
+void CdbEngine::executeRunToLine(const QString &fileName, int lineNumber)
+{
+ // Add one-shot breakpoint
+ Debugger::Internal::BreakpointParameters bp(Debugger::Internal::BreakpointByFileAndLine);
+ bp.fileName = fileName;
+ bp.lineNumber = lineNumber;
+ postCommand(cdbAddBreakpointCommand(bp, true), 0);
+ continueInferior();
+}
+
+void CdbEngine::executeRunToFunction(const QString &functionName)
+{
+ // Add one-shot breakpoint
+ Debugger::Internal::BreakpointParameters bp(Debugger::Internal::BreakpointByFunction);
+ bp.functionName = functionName;
+
+ postCommand(cdbAddBreakpointCommand(bp, true), 0);
+ continueInferior();
+}
+
+void CdbEngine::setRegisterValue(int regnr, const QString &value)
+{
+ const Debugger::Internal::Registers registers = registerHandler()->registers();
+ QTC_ASSERT(regnr < registers.size(), return)
+ // Value is decimal or 0x-hex-prefixed
+ QByteArray cmd;
+ ByteArrayInputStream str(cmd);
+ str << "r " << registers.at(regnr).name << '=' << value;
+ postCommand(cmd, 0);
+ reloadRegisters();
+}
+
+void CdbEngine::executeJumpToLine(const QString & fileName, int lineNumber)
+{
+ QByteArray cmd;
+ ByteArrayInputStream str(cmd);
+ // Resolve source line address and go to that location
+ str << "? `" << QDir::toNativeSeparators(fileName) << ':' << lineNumber << '`';
+ const QVariant cookie = qVariantFromValue(SourceLocationCookie(fileName, lineNumber));
+ postBuiltinCommand(cmd, 0, &CdbEngine::handleJumpToLineAddressResolution, 0, cookie);
+}
+
+void CdbEngine::handleJumpToLineAddressResolution(const CdbBuiltinCommandPtr &cmd)
+{
+ if (cmd->reply.isEmpty())
+ return;
+ // Evaluate expression: 5365511549 = 00000001`3fcf357d
+ // Set register 'rip' to hex address and goto lcoation
+ QByteArray answer = cmd->reply.front();
+ const int equalPos = answer.indexOf(" = ");
+ if (equalPos == -1)
+ return;
+ answer.remove(0, equalPos + 3);
+ QTC_ASSERT(qVariantCanConvert<SourceLocationCookie>(cmd->cookie), return ; )
+ const SourceLocationCookie cookie = qvariant_cast<SourceLocationCookie>(cmd->cookie);
+
+ QByteArray registerCmd;
+ ByteArrayInputStream str(registerCmd);
+ // PC-register depending on 64/32bit.
+ str << "r " << (m_options->is64bit ? "rip" : "eip") << "=0x" << answer;
+ postCommand(registerCmd, 0);
+ gotoLocation(Location(cookie.fileName, cookie.lineNumber));
+}
+
+void CdbEngine::assignValueInDebugger(const Debugger::Internal::WatchData *w, const QString &expr, const QVariant &value)
+{
+ if (debug)
+ qDebug() << "CdbEngine::assignValueInDebugger" << w->iname << expr << value;
+
+ if (state() != InferiorStopOk || stackHandler()->currentIndex() < 0) {
+ qWarning("Internal error: assignValueInDebugger: Invalid state or no stack frame.");
+ return;
+ }
+
+ QByteArray cmd;
+ ByteArrayInputStream str(cmd);
+ str << m_extensionCommandPrefixBA << "assign " << w->iname << '=' << value.toString();
+ postCommand(cmd, 0);
+ updateLocalVariable(w->iname);
+}
+
+void CdbEngine::handleThreads(const CdbExtensionCommandPtr &reply)
+{
+ if (debug)
+ qDebug("CdbEngine::handleThreads success=%d", reply->success);
+ if (reply->success) {
+ Debugger::Internal::GdbMi data;
+ data.fromString(reply->reply);
+ int currentThreadId;
+ Debugger::Internal::Threads threads = Debugger::Internal::ThreadsHandler::parseGdbmiThreads(data, &currentThreadId);
+ threadsHandler()->setThreads(threads);
+ threadsHandler()->setCurrentThreadId(currentThreadId);
+ // Continue sequence
+ postCommandSequence(reply->commandSequence);
+ } else {
+ showMessage(QString::fromLatin1(reply->errorMessage), LogError);
+ }
+}
+
+void CdbEngine::executeDebuggerCommand(const QString &command)
+{
+ postCommand(command.toLocal8Bit(), QuietCommand);
+}
+
+// Post command without callback
+void CdbEngine::postCommand(const QByteArray &cmd, unsigned flags)
+{
+ if (debug)
+ qDebug("CdbEngine::postCommand %dms '%s' %u %s\n",
+ elapsedLogTime(), cmd.constData(), flags, stateName(state()));
+ if (!(flags & QuietCommand))
+ showMessage(QString::fromLocal8Bit(cmd), LogInput);
+ m_process.write(cmd + '\n');
+}
+
+// Post a built-in-command producing free-format output with a callback.
+// In order to catch the output, it is enclosed in 'echo' commands
+// printing a specially formatted token to be identifiable in the output.
+void CdbEngine::postBuiltinCommand(const QByteArray &cmd, unsigned flags,
+ BuiltinCommandHandler handler,
+ unsigned nextCommandFlag,
+ const QVariant &cookie)
+{
+ if (!m_accessible) {
+ const QString msg = QString::fromLatin1("Attempt to issue builtin command '%1' to non-accessible session (%2)")
+ .arg(QString::fromLocal8Bit(cmd), QString::fromAscii(stateName(state())));
+ showMessage(msg, LogError);
+ return;
+ }
+ if (!flags & QuietCommand)
+ showMessage(QString::fromLocal8Bit(cmd), LogInput);
+
+ const int token = m_nextCommandToken++;
+ CdbBuiltinCommandPtr pendingCommand(new CdbBuiltinCommand(cmd, token, flags, handler, nextCommandFlag, cookie));
+
+ m_builtinCommandQueue.push_back(pendingCommand);
+ // Enclose command in echo-commands for token
+ QByteArray fullCmd;
+ ByteArrayInputStream str(fullCmd);
+ str << ".echo \"" << m_tokenPrefix << token << "<\"\n"
+ << cmd << "\n.echo \"" << m_tokenPrefix << token << ">\"\n";
+ if (debug)
+ qDebug("CdbEngine::postBuiltinCommand %dms '%s' flags=%u token=%d %s next=%u, cookie='%s', pending=%d, sequence=0x%x",
+ elapsedLogTime(), cmd.constData(), flags, token, stateName(state()), nextCommandFlag, qPrintable(cookie.toString()),
+ m_builtinCommandQueue.size(), nextCommandFlag);
+ if (debug > 1)
+ qDebug("CdbEngine::postBuiltinCommand: resulting command '%s'\n",
+ fullCmd.constData());
+ m_process.write(fullCmd);
+}
+
+// Post an extension command producing one-line output with a callback,
+// pass along token for identification in queue.
+void CdbEngine::postExtensionCommand(const QByteArray &cmd,
+ const QByteArray &arguments,
+ unsigned flags,
+ ExtensionCommandHandler handler,
+ unsigned nextCommandFlag,
+ const QVariant &cookie)
+{
+ if (!m_accessible) {
+ const QString msg = QString::fromLatin1("Attempt to issue extension command '%1' to non-accessible session (%2)")
+ .arg(QString::fromLocal8Bit(cmd), QString::fromAscii(stateName(state())));
+ showMessage(msg, LogError);
+ return;
+ }
+
+ const int token = m_nextCommandToken++;
+
+ // Format full command with token to be recognizeable in the output
+ QByteArray fullCmd;
+ ByteArrayInputStream str(fullCmd);
+ str << m_extensionCommandPrefixBA << cmd << " -t " << token;
+ if (!arguments.isEmpty())
+ str << ' ' << arguments;
+
+ if (!flags & QuietCommand)
+ showMessage(QString::fromLocal8Bit(fullCmd), LogInput);
+
+ CdbExtensionCommandPtr pendingCommand(new CdbExtensionCommand(fullCmd, token, flags, handler, nextCommandFlag, cookie));
+
+ m_extensionCommandQueue.push_back(pendingCommand);
+ // Enclose command in echo-commands for token
+ if (debug)
+ qDebug("CdbEngine::postExtensionCommand %dms '%s' flags=%u token=%d %s next=%u, cookie='%s', pending=%d, sequence=0x%x",
+ elapsedLogTime(), fullCmd.constData(), flags, token, stateName(state()), nextCommandFlag, qPrintable(cookie.toString()),
+ m_extensionCommandQueue.size(), nextCommandFlag);
+ m_process.write(fullCmd + '\n');
+}
+
+void CdbEngine::activateFrame(int index)
+{
+ // TODO: assembler,etc
+ if (index < 0)
+ return;
+ const Debugger::Internal::StackFrames &frames = stackHandler()->frames();
+ QTC_ASSERT(index < frames.size(), return; )
+
+ const StackFrame frame = frames.at(index);
+ if (debug || debugLocals)
+ qDebug("activateFrame idx=%d '%s' %d", index,
+ qPrintable(frame.file), frame.line);
+ stackHandler()->setCurrentIndex(index);
+ const bool showAssembler = !frames.at(index).isUsable();
+ if (showAssembler) { // Assembly code: Clean out model and force instruction mode.
+ watchHandler()->beginCycle();
+ watchHandler()->endCycle();
+ QAction *assemblerAction = theAssemblerAction();
+ if (assemblerAction->isChecked()) {
+ gotoLocation(frame);
+ } else {
+ assemblerAction->trigger(); // Seems to trigger update
+ }
+ return;
+ }
+ gotoLocation(frame);
+ // Watchers: Initial expand, get uninitialized and query
+ QByteArray arguments;
+ ByteArrayInputStream str(arguments);
+ // Pre-expand
+ const QSet<QByteArray> expanded = watchHandler()->expandedINames();
+ if (!expanded.isEmpty()) {
+ str << blankSeparator << "-e ";
+ int i = 0;
+ foreach(const QByteArray &e, expanded) {
+ if (i++)
+ str << ',';
+ str << e;
+ }
+ }
+ addLocalsOptions(str);
+ // Uninitialized variables if desired
+ if (debuggerCore()->boolSetting(UseCodeModel)) {
+ QStringList uninitializedVariables;
+ getUninitializedVariables(debuggerCore()->cppCodeModelSnapshot(),
+ frame.function, frame.file, frame.line, &uninitializedVariables);
+ if (!uninitializedVariables.isEmpty()) {
+ str << blankSeparator << "-u ";
+ int i = 0;
+ foreach(const QString &u, uninitializedVariables) {
+ if (i++)
+ str << ',';
+ str << localsPrefixC << u;
+ }
+ }
+ }
+ // Required arguments: frame
+ str << blankSeparator << index;
+ watchHandler()->beginCycle();
+ postExtensionCommand("locals", arguments, 0, &CdbEngine::handleLocals);
+}
+
+void CdbEngine::selectThread(int index)
+{
+ if (index < 0 || index == threadsHandler()->currentThread())
+ return;
+
+ resetLocation();
+ const int newThreadId = threadsHandler()->threads().at(index).id;
+ threadsHandler()->setCurrentThread(index);
+
+ const QByteArray cmd = "~" + QByteArray::number(newThreadId) + " s";
+ postBuiltinCommand(cmd, 0, &CdbEngine::dummyHandler, CommandListStack);
+}
+
+void CdbEngine::fetchDisassembler(Debugger::Internal::DisassemblerAgent *agent)
+{
+ QTC_ASSERT(m_accessible, return;)
+ QByteArray cmd;
+ ByteArrayInputStream str(cmd);
+ str << "u " << hex << hexPrefixOn << agent->address() << " L40";
+ const QVariant cookie = qVariantFromValue<Debugger::Internal::DisassemblerAgent*>(agent);
+ postBuiltinCommand(cmd, 0, &CdbEngine::handleDisassembler, 0, cookie);
+}
+
+// Parse: "00000000`77606060 cc int 3"
+void CdbEngine::handleDisassembler(const CdbBuiltinCommandPtr &command)
+{
+ QTC_ASSERT(qVariantCanConvert<Debugger::Internal::DisassemblerAgent*>(command->cookie), return;)
+ Debugger::Internal::DisassemblerAgent *agent = qvariant_cast<Debugger::Internal::DisassemblerAgent*>(command->cookie);
+ DisassemblerLines disassemblerLines;
+ foreach(const QByteArray &line, command->reply)
+ disassemblerLines.appendLine(DisassemblerLine(QString::fromLatin1(line)));
+ agent->setContents(disassemblerLines);
+}
+
+void CdbEngine::fetchMemory(Debugger::Internal::MemoryAgent *agent, QObject *editor, quint64 addr, quint64 length)
+{
+ if (!m_accessible) {
+ qWarning("Internal error: Attempt to read memory from inaccessible session: %s", Q_FUNC_INFO);
+ return;
+ }
+ if (debug)
+ qDebug("CdbEngine::fetchMemory %llu bytes from 0x%llx", length, addr);
+
+ QByteArray args;
+ ByteArrayInputStream str(args);
+ str << addr << ' ' << length;
+ const QVariant cookie = qVariantFromValue<MemoryViewCookie>(MemoryViewCookie(agent, editor, addr, length));
+ postExtensionCommand("memory", args, 0, &CdbEngine::handleMemory, 0, cookie);
+}
+
+void CdbEngine::handleMemory(const CdbExtensionCommandPtr &command)
+{
+ QTC_ASSERT(qVariantCanConvert<MemoryViewCookie>(command->cookie), return;)
+ const MemoryViewCookie memViewCookie = qvariant_cast<MemoryViewCookie>(command->cookie);
+ if (command->success) {
+ const QByteArray data = QByteArray::fromBase64(command->reply);
+ if (unsigned(data.size()) == memViewCookie.length)
+ memViewCookie.agent->addLazyData(memViewCookie.editorToken,
+ memViewCookie.address, data);
+ } else {
+ showMessage(QString::fromLocal8Bit(command->errorMessage), LogError);
+ }
+}
+
+void CdbEngine::reloadModules()
+{
+ postCommandSequence(CommandListModules);
+}
+
+void CdbEngine::loadSymbols(const QString & /* moduleName */)
+{
+}
+
+void CdbEngine::loadAllSymbols()
+{
+}
+
+void CdbEngine::requestModuleSymbols(const QString &moduleName)
+{
+ Q_UNUSED(moduleName)
+}
+
+void CdbEngine::reloadRegisters()
+{
+ postCommandSequence(CommandListRegisters);
+}
+
+void CdbEngine::reloadSourceFiles()
+{
+}
+
+void CdbEngine::reloadFullStack()
+{
+ if (debug)
+ qDebug("%s", Q_FUNC_INFO);
+ postCommandSequence(CommandListStack);
+}
+
+void CdbEngine::handlePid(const CdbExtensionCommandPtr &reply)
+{
+ if (reply->success) {
+ m_inferiorPid = reply->reply.toUInt();
+ showMessage(QString::fromLatin1("Inferior pid: %1."), LogMisc);
+ notifyInferiorSetupOk();
+ } else {
+ showMessage(QString::fromLatin1("Failed to determine inferior pid: %1").
+ arg(QLatin1String(reply->errorMessage)), LogError);
+ notifyInferiorSetupFailed();
+ }
+}
+
+// Parse CDB gdbmi register syntax
+static inline Debugger::Internal::Register parseRegister(const Debugger::Internal::GdbMi &gdbmiReg)
+{
+ Debugger::Internal::Register reg;
+ reg.name = gdbmiReg.findChild("name").data();
+ const Debugger::Internal::GdbMi description = gdbmiReg.findChild("description");
+ if (description.type() != Debugger::Internal::GdbMi::Invalid) {
+ reg.name += " (";
+ reg.name += description.data();
+ reg.name += ')';
+ }
+ reg.value = QString::fromAscii(gdbmiReg.findChild("value").data());
+ return reg;
+}
+
+void CdbEngine::handleModules(const CdbExtensionCommandPtr &reply)
+{
+ if (reply->success) {
+ Debugger::Internal::GdbMi value;
+ value.fromString(reply->reply);
+ if (value.type() == Debugger::Internal::GdbMi::List) {
+ Debugger::Internal::Modules modules;
+ modules.reserve(value.childCount());
+ foreach (const Debugger::Internal::GdbMi &gdbmiModule, value.children()) {
+ Debugger::Internal::Module module;
+ module.moduleName = QString::fromAscii(gdbmiModule.findChild("name").data());
+ module.modulePath = QString::fromAscii(gdbmiModule.findChild("image").data());
+ module.startAddress = QString::fromAscii(gdbmiModule.findChild("start").data());
+ module.endAddress = QString::fromAscii(gdbmiModule.findChild("end").data());
+ if (gdbmiModule.findChild("deferred").type() == Debugger::Internal::GdbMi::Invalid)
+ module.symbolsRead = Debugger::Internal::Module::ReadOk;
+ modules.push_back(module);
+ }
+ modulesHandler()->setModules(modules);
+ } else {
+ showMessage(QString::fromLatin1("Parse error in modules response."), LogError);
+ qWarning("Parse error in modules response:\n%s", reply->reply.constData());
+ }
+ } else {
+ showMessage(QString::fromLatin1("Failed to determine modules: %1").
+ arg(QLatin1String(reply->errorMessage)), LogError);
+ }
+ postCommandSequence(reply->commandSequence);
+
+}
+
+void CdbEngine::handleRegisters(const CdbExtensionCommandPtr &reply)
+{
+ if (reply->success) {
+ Debugger::Internal::GdbMi value;
+ value.fromString(reply->reply);
+ if (value.type() == Debugger::Internal::GdbMi::List) {
+ Debugger::Internal::Registers registers;
+ registers.reserve(value.childCount());
+ foreach (const Debugger::Internal::GdbMi &gdbmiReg, value.children())
+ registers.push_back(parseRegister(gdbmiReg));
+ registerHandler()->setRegisters(registers);
+ } else {
+ showMessage(QString::fromLatin1("Parse error in registers response."), LogError);
+ qWarning("Parse error in registers response:\n%s", reply->reply.constData());
+ }
+ } else {
+ showMessage(QString::fromLatin1("Failed to determine registers: %1").
+ arg(QLatin1String(reply->errorMessage)), LogError);
+ }
+ postCommandSequence(reply->commandSequence);
+}
+
+void CdbEngine::handleLocals(const CdbExtensionCommandPtr &reply)
+{
+ if (reply->success) {
+ QList<Debugger::Internal::WatchData> watchData;
+ GdbMi root;
+ root.fromString(reply->reply);
+ QTC_ASSERT(root.isList(), return ; )
+ if (debugLocals) {
+ qDebug() << root.toString(true, 4);
+ }
+ // Courtesy of GDB engine
+ foreach (const GdbMi &child, root.children()) {
+ WatchData dummy;
+ dummy.iname = child.findChild("iname").data();
+ dummy.name = QLatin1String(child.findChild("name").data());
+ parseWatchData(watchHandler()->expandedINames(), dummy, child, &watchData);
+ }
+ watchHandler()->insertBulkData(watchData);
+ watchHandler()->endCycle();
+ if (debugLocals) {
+ QDebug nsp = qDebug().nospace();
+ nsp << "Obtained " << watchData.size() << " items:\n";
+ foreach (const Debugger::Internal::WatchData &wd, watchData)
+ nsp << wd.toString() <<'\n';
+ }
+ } else {
+ showMessage(QString::fromLatin1(reply->errorMessage), LogError);
+ }
+}
+
+void CdbEngine::handleExpandLocals(const CdbExtensionCommandPtr &reply)
+{
+ if (!reply->success)
+ showMessage(QString::fromLatin1(reply->errorMessage), LogError);
+}
+
+enum CdbExecutionStatus {
+CDB_STATUS_NO_CHANGE=0, CDB_STATUS_GO = 1, CDB_STATUS_GO_HANDLED = 2,
+CDB_STATUS_GO_NOT_HANDLED = 3, CDB_STATUS_STEP_OVER = 4,
+CDB_STATUS_STEP_INTO = 5, CDB_STATUS_BREAK = 6, CDB_STATUS_NO_DEBUGGEE = 7,
+CDB_STATUS_STEP_BRANCH = 8, CDB_STATUS_IGNORE_EVENT = 9,
+CDB_STATUS_RESTART_REQUESTED = 10, CDB_STATUS_REVERSE_GO = 11,
+CDB_STATUS_REVERSE_STEP_BRANCH = 12, CDB_STATUS_REVERSE_STEP_OVER = 13,
+CDB_STATUS_REVERSE_STEP_INTO = 14 };
+
+static const char *cdbStatusName(unsigned long s)
+{
+ switch (s) {
+ case CDB_STATUS_NO_CHANGE:
+ return "No change";
+ case CDB_STATUS_GO:
+ return "go";
+ case CDB_STATUS_GO_HANDLED:
+ return "go_handled";
+ case CDB_STATUS_GO_NOT_HANDLED:
+ return "go_not_handled";
+ case CDB_STATUS_STEP_OVER:
+ return "step_over";
+ case CDB_STATUS_STEP_INTO:
+ return "step_into";
+ case CDB_STATUS_BREAK:
+ return "break";
+ case CDB_STATUS_NO_DEBUGGEE:
+ return "no_debuggee";
+ case CDB_STATUS_STEP_BRANCH:
+ return "step_branch";
+ case CDB_STATUS_IGNORE_EVENT:
+ return "ignore_event";
+ case CDB_STATUS_RESTART_REQUESTED:
+ return "restart_requested";
+ case CDB_STATUS_REVERSE_GO:
+ return "reverse_go";
+ case CDB_STATUS_REVERSE_STEP_BRANCH:
+ return "reverse_step_branch";
+ case CDB_STATUS_REVERSE_STEP_OVER:
+ return "reverse_step_over";
+ case CDB_STATUS_REVERSE_STEP_INTO:
+ return "reverse_step_into";
+ }
+ return "unknown";
+}
+
+void CdbEngine::handleSessionIdle(const QByteArray &message)
+{
+ if (!m_hasDebuggee)
+ return;
+
+ if (debug)
+ qDebug("CdbEngine::handleSessionIdle %dms '%s' in state '%s', special mode %d",
+ elapsedLogTime(), message.constData(),
+ stateName(state()), m_specialStopMode);
+
+ // Switch source level debugging
+ syncOperateByInstruction(m_operateByInstructionPending);
+
+ const SpecialStopMode specialStopMode = m_specialStopMode;
+ m_specialStopMode = NoSpecialStop;
+
+ switch(specialStopMode) {
+ case SpecialStopSynchronizeBreakpoints:
+ if (debug)
+ qDebug("attemptBreakpointSynchronization in special stop");
+ attemptBreakpointSynchronization();
+ doContinueInferior();
+ return;
+ case NoSpecialStop:
+ break;
+ }
+ switch(state()) { // Temporary stop at beginning
+ case EngineSetupRequested:
+ if (debug)
+ qDebug("notifyEngineSetupOk");
+ notifyEngineSetupOk();
+ return;
+ case InferiorSetupRequested:
+ return;
+ case InferiorStopRequested:
+ case InferiorRunOk:
+ break; // Proper stop of inferior handled below.
+
+ default:
+ qWarning("WARNING: CdbEngine::handleSessionAccessible called in state %s", stateName(state()));
+ return;
+ }
+ // Handle stop.
+ if (state() == InferiorStopRequested) {
+ if (debug)
+ qDebug("notifyInferiorStopOk");
+ notifyInferiorStopOk();
+ } else {
+ if (debug)
+ qDebug("notifyInferiorSpontaneousStop");
+ notifyInferiorSpontaneousStop();
+ }
+ // Start sequence to get all relevant data. Hack: Avoid module reload?
+ unsigned sequence = CommandListStack|CommandListThreads;
+ if (debuggerCore()->isDockVisible(QLatin1String(Constants::DOCKWIDGET_REGISTER)))
+ sequence |= CommandListRegisters;
+ if (debuggerCore()->isDockVisible(QLatin1String(Constants::DOCKWIDGET_MODULES)))
+ sequence |= CommandListModules;
+ postCommandSequence(sequence);
+ // Report stop reason (GDBMI)
+ Debugger::Internal::GdbMi stopReason;
+ stopReason.fromString(message);
+ if (debug)
+ qDebug("%s", stopReason.toString(true, 4).constData());
+ const QByteArray reason = stopReason.findChild("reason").data();
+ if (reason.isEmpty()) {
+ showStatusMessage(tr("Malformed stop response received."), LogError);
+ return;
+ }
+ const int threadId = stopReason.findChild("threadId").data().toInt();
+ if (reason == "breakpoint") {
+ const int number = stopReason.findChild("breakpointId").data().toInt();
+ const BreakpointId id = breakHandler()->findBreakpointByNumber(number);
+ if (id && breakHandler()->type(id) == Debugger::Internal::Watchpoint) {
+ showStatusMessage(msgWatchpointTriggered(id, number, breakHandler()->address(id), QString::number(threadId)));
+ } else {
+ showStatusMessage(msgBreakpointTriggered(id, number, QString::number(threadId)));
+ }
+ return;
+ }
+ if (reason == "exception") {
+ WinException exception;
+ exception.fromGdbMI(stopReason);
+#ifdef Q_OS_WIN
+ // It is possible to hit on a startup trap while stepping (if something
+ // pulls DLLs. Avoid showing a 'stopped' Message box.
+ if (exception.exceptionCode == winExceptionStartupCompleteTrap)
+ return;
+ if (Debugger::Internal::isDebuggerWinException(exception.exceptionCode)) {
+ showStatusMessage(msgInterrupted());
+ return;
+ }
+#endif
+ const QString description = exception.toString();
+ showStatusMessage(msgStoppedByException(description, QString::number(threadId)));
+ showStoppedByExceptionMessageBox(description);
+ return;
+ }
+ showStatusMessage(msgStopped(QLatin1String(reason)));
+}
+
+void CdbEngine::handleSessionAccessible(unsigned long cdbExState)
+{
+ const DebuggerState s = state();
+ if (!m_hasDebuggee || s == InferiorRunOk) // suppress reports
+ return;
+
+ if (debug)
+ qDebug("CdbEngine::handleSessionAccessible %dms in state '%s'/'%s', special mode %d",
+ elapsedLogTime(), cdbStatusName(cdbExState), stateName(state()), m_specialStopMode);
+
+ switch(s) {
+ case EngineShutdownRequested:
+ shutdownEngine();
+ break;
+ case InferiorShutdownRequested:
+ shutdownInferior();
+ break;
+ default:
+ break;
+ }
+}
+
+void CdbEngine::handleSessionInaccessible(unsigned long cdbExState)
+{
+ const DebuggerState s = state();
+
+ // suppress reports
+ if (!m_hasDebuggee || (s == InferiorRunOk && cdbExState != CDB_STATUS_NO_DEBUGGEE))
+ return;
+
+ if (debug)
+ qDebug("CdbEngine::handleSessionInaccessible %dms in state '%s', '%s', special mode %d",
+ elapsedLogTime(), cdbStatusName(cdbExState), stateName(state()), m_specialStopMode);
+
+ switch (state()) {
+ case EngineSetupRequested:
+ break;
+ case EngineRunRequested:
+ if (debug)
+ qDebug("notifyEngineRunAndInferiorRunOk");
+ notifyEngineRunAndInferiorRunOk();
+ break;
+ case InferiorRunOk:
+ case InferiorStopOk:
+ // Inaccessible without debuggee (exit breakpoint)
+ // We go for spontaneous engine shutdown instead.
+ if (cdbExState == CDB_STATUS_NO_DEBUGGEE) {
+ if (debug)
+ qDebug("Lost debuggeee");
+ m_hasDebuggee = false;
+ }
+ break;
+ case InferiorRunRequested:
+ if (debug)
+ qDebug("notifyInferiorRunOk");
+ notifyInferiorRunOk();
+ resetLocation();
+ break;
+ case EngineShutdownRequested:
+ break;
+ default:
+ break;
+ }
+}
+
+void CdbEngine::handleExtensionMessage(char t, int token, const QByteArray &what, const QByteArray &message)
+{
+ if (debug > 1) {
+ QDebug nospace = qDebug().nospace();
+ nospace << "handleExtensionMessage " << t << ' ' << token << ' ' << what
+ << ' ' << stateName(state());
+ if (t == 'N' || debug > 1) {
+ nospace << ' ' << message;
+ } else {
+ nospace << ' ' << message.size() << " bytes";
+ }
+ }
+
+ // Is there a reply expected, some command queued?
+ if (t == 'R' || t == 'N') {
+ if (token == -1) { // Default token, user typed in extension command
+ showMessage(QString::fromLatin1(message), LogMisc);
+ return;
+ }
+ const int index = indexOfCommand(m_extensionCommandQueue, token);
+ if (index != -1) {
+ // Did the command finish? Take off queue and complete, invoke CB
+ const CdbExtensionCommandPtr command = m_extensionCommandQueue.takeAt(index);
+ if (t == 'R') {
+ command->success = true;
+ command->reply = message;
+ } else {
+ command->success = false;
+ command->errorMessage = message;
+ }
+ if (debug)
+ qDebug("### Completed extension command '%s', token=%d, pending=%d",
+ command->command.constData(), command->token, m_extensionCommandQueue.size());
+ if (command->handler)
+ (this->*(command->handler))(command);
+ return;
+ }
+ }
+
+ if (what == "debuggee_output") {
+ showMessage(StringFromBase64EncodedUtf16(message), AppOutput);
+ return;
+ }
+
+ if (what == "event") {
+ showStatusMessage(QString::fromAscii(message), 5000);
+ return;
+ }
+
+ if (what == "session_accessible") {
+ if (!m_accessible) {
+ m_accessible = true;
+ handleSessionAccessible(message.toULong());
+ }
+ return;
+ }
+
+ if (what == "session_inaccessible") {
+ if (m_accessible) {
+ m_accessible = false;
+ handleSessionInaccessible(message.toULong());
+ }
+ return;
+ }
+
+ if (what == "session_idle") {
+ handleSessionIdle(message);
+ return;
+ }
+
+ if (what == "exception") {
+ WinException exception;
+ Debugger::Internal::GdbMi gdbmi;
+ gdbmi.fromString(message);
+ exception.fromGdbMI(gdbmi);
+ const QString message = exception.toString(true);
+ showStatusMessage(message);
+#ifdef Q_OS_WIN // Report C++ exception in application output as well.
+ if (exception.exceptionCode == Debugger::Internal::winExceptionCppException)
+ showMessage(message + QLatin1Char('\n'), AppOutput);
+#endif
+ return;
+ }
+
+ return;
+}
+
+// Check for a CDB prompt '0:000> ' ('process:thread> ')..no regexps for QByteArray...
+enum { CdbPromptLength = 7 };
+
+static inline bool isCdbPrompt(const QByteArray &c)
+{
+ return c.size() >= CdbPromptLength && c.at(6) == ' ' && c.at(5) == '>' && c.at(1) == ':'
+ && std::isdigit(c.at(0)) && std::isdigit(c.at(2)) && std::isdigit(c.at(3))
+ && std::isdigit(c.at(4));
+}
+
+// Check for '<token>32>' or '<token>32<'
+static inline bool checkCommandToken(const QByteArray &tokenPrefix, const QByteArray &c,
+ int *token, bool *isStart)
+{
+ *token = 0;
+ *isStart = false;
+ const int tokenPrefixSize = tokenPrefix.size();
+ const int size = c.size();
+ if (size < tokenPrefixSize + 2 || !std::isdigit(c.at(tokenPrefixSize)))
+ return false;
+ switch (c.at(size - 1)) {
+ case '>':
+ *isStart = false;
+ break;
+ case '<':
+ *isStart = true;
+ break;
+ default:
+ return false;
+ }
+ if (!c.startsWith(tokenPrefix))
+ return false;
+ bool ok;
+ *token = c.mid(tokenPrefixSize, size - tokenPrefixSize - 1).toInt(&ok);
+ return ok;
+}
+
+void CdbEngine::parseOutputLine(QByteArray line)
+{
+ // The hooked output callback in the extension suppresses prompts,
+ // it should happen only in initial and exit stages. Note however that
+ // if the output is not hooked, sequences of prompts are possible which
+ // can mix things up.
+ while (isCdbPrompt(line))
+ line.remove(0, CdbPromptLength);
+ // An extension notification
+ if (line.startsWith(m_creatorExtPrefix)) {
+ // "<qtcreatorcdbext>|type_char|token|serviceName|message"
+ const char type = line.at(m_creatorExtPrefix.size());
+ // integer token
+ const int tokenPos = m_creatorExtPrefix.size() + 2;
+ const int tokenEndPos = line.indexOf('|', tokenPos);
+ QTC_ASSERT(tokenEndPos != -1, return)
+ const int token = line.mid(tokenPos, tokenEndPos - tokenPos).toInt();
+ // const char 'serviceName'
+ const int whatPos = tokenEndPos + 1;
+ const int whatEndPos = line.indexOf('|', whatPos);
+ QTC_ASSERT(whatEndPos != -1, return)
+ const QByteArray what = line.mid(whatPos, whatEndPos - whatPos);
+ // Message
+ const QByteArray message = line.mid(whatEndPos + 1);
+ handleExtensionMessage(type, token, what, message);
+ return;
+ }
+ // Check for command start/end tokens within which the builtin command
+ // output is enclosed
+ int token = 0;
+ bool isStartToken = false;
+ const bool isCommandToken = checkCommandToken(m_tokenPrefix, line, &token, &isStartToken);
+ if (debug > 1)
+ qDebug("Reading CDB stdout '%s',\n isCommand=%d, token=%d, isStart=%d, current=%d",
+ line.constData(), isCommandToken, token, isStartToken, m_currentBuiltinCommandIndex);
+
+ // If there is a current command, wait for end of output indicated by token,
+ // command, trigger handler and finish, else append to its output.
+ if (m_currentBuiltinCommandIndex != -1) {
+ QTC_ASSERT(!isStartToken && m_currentBuiltinCommandIndex < m_builtinCommandQueue.size(), return; );
+ const CdbBuiltinCommandPtr &currentCommand = m_builtinCommandQueue.at(m_currentBuiltinCommandIndex);
+ if (isCommandToken) {
+ // Did the command finish? Invoke callback and remove from queue.
+ if (debug)
+ qDebug("### Completed builtin command '%s', token=%d, %d lines, pending=%d",
+ currentCommand->command.constData(), currentCommand->token,
+ currentCommand->reply.size(), m_builtinCommandQueue.size() - 1);
+ QTC_ASSERT(token == currentCommand->token, return; );
+ if (currentCommand->handler)
+ (this->*(currentCommand->handler))(currentCommand);
+ m_builtinCommandQueue.removeAt(m_currentBuiltinCommandIndex);
+ m_currentBuiltinCommandIndex = -1;
+ } else {
+ // Record output of current command
+ currentCommand->reply.push_back(line);
+ }
+ return;
+ } // m_currentCommandIndex
+ if (isCommandToken) {
+ // Beginning command token encountered, start to record output.
+ const int index = indexOfCommand(m_builtinCommandQueue, token);
+ QTC_ASSERT(isStartToken && index != -1, return; );
+ m_currentBuiltinCommandIndex = index;
+ const CdbBuiltinCommandPtr &currentCommand = m_builtinCommandQueue.at(m_currentBuiltinCommandIndex);
+ if (debug)
+ qDebug("### Gathering output for '%s' token %d", currentCommand->command.constData(), currentCommand->token);
+ return;
+ }
+
+ showMessage(QString::fromLocal8Bit(line), LogMisc);
+}
+
+void CdbEngine::readyReadStandardOut()
+{
+ m_outputBuffer += m_process.readAllStandardOutput();
+ // Split into lines and parse line by line.
+ while (true) {
+ const int endOfLinePos = m_outputBuffer.indexOf('\n');
+ if (endOfLinePos == -1) {
+ break;
+ } else {
+ // Check for '\r\n'
+ QByteArray line = m_outputBuffer.left(endOfLinePos);
+ if (!line.isEmpty() && line.at(line.size() - 1) == '\r')
+ line.truncate(line.size() - 1);
+ parseOutputLine(line);
+ m_outputBuffer.remove(0, endOfLinePos + 1);
+ }
+ }
+}
+
+void CdbEngine::readyReadStandardError()
+{
+ showMessage(QString::fromLocal8Bit(m_process.readAllStandardError()), LogError);
+}
+
+void CdbEngine::processError()
+{
+ showMessage(m_process.errorString(), LogError);
+}
+
+#if 0
+// Join breakpoint ids for a multi-breakpoint id commands like 'bc', 'be', 'bd'
+static QByteArray multiBreakpointCommand(const char *cmdC, const Debugger::Internal::Breakpoints &bps)
+{
+ QByteArray cmd(cmdC);
+ ByteArrayInputStream str(cmd);
+ foreach(const Debugger::Internal::BreakpointData *bp, bps)
+ str << ' ' << bp->bpNumber;
+ return cmd;
+}
+#endif
+
+// Figure out what kind of changes are required to synchronize
+enum BreakPointSyncType {
+ BreakpointsUnchanged, BreakpointsAdded, BreakpointsRemovedChanged
+};
+
+static inline BreakPointSyncType breakPointSyncType(const BreakHandler *handler,
+ const BreakpointIds ids)
+{
+ bool added = false;
+ foreach (BreakpointId id, ids) {
+ const BreakpointState state = handler->state(id);
+ if (debugBreakpoints > 1)
+ qDebug(" Checking on breakpoint %llu, state %d\n", id, state);
+ switch (state) {
+ case BreakpointInsertRequested:
+ added = true;
+ break;
+ case BreakpointChangeRequested:
+ case BreakpointRemoveRequested:
+ return BreakpointsRemovedChanged;
+ default:
+ break;
+ }
+ }
+ return added ? BreakpointsAdded : BreakpointsUnchanged;
+}
+
+bool CdbEngine::stateAcceptsBreakpointChanges() const
+{
+ switch (state()) {
+ case InferiorRunOk:
+ case InferiorStopOk:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+bool CdbEngine::acceptsBreakpoint(BreakpointId id) const
+{
+ return DebuggerEngine::isCppBreakpoint(breakHandler()->breakpointData(id));
+}
+
+void CdbEngine::attemptBreakpointSynchronization()
+{
+ // Check if there is anything to be done at all.
+ BreakHandler *handler = breakHandler();
+ // Take ownership of the breakpoint. Requests insertion. TODO: Cpp only?
+ foreach (BreakpointId id, handler->unclaimedBreakpointIds())
+ if (acceptsBreakpoint(id))
+ handler->setEngine(id, this);
+
+ // Find out if there is a need to synchronize again
+ const BreakpointIds ids = handler->engineBreakpointIds(this);
+ const BreakPointSyncType syncType = breakPointSyncType(handler, ids);
+ if (debugBreakpoints)
+ qDebug("attemptBreakpointSynchronizationI %dms accessible=%d, %s %d breakpoints, syncType=%d",
+ elapsedLogTime(), m_accessible, stateName(state()), ids.size(), syncType);
+ if (syncType == BreakpointsUnchanged)
+ return;
+
+ if (!m_accessible) {
+ // No nested calls.
+ if (m_specialStopMode != SpecialStopSynchronizeBreakpoints)
+ doInterruptInferior(SpecialStopSynchronizeBreakpoints);
+ return;
+ }
+
+ // If there are changes/removals, delete all breakpoints and re-insert
+ // all enabled breakpoints. This is the simplest
+ // way to apply changes since CDB ids shift when removing breakpoints and there is no
+ // easy way to re-match them.
+
+ if (syncType == BreakpointsRemovedChanged) { // Need to clear out all?
+ postCommand("bc *", 0);
+ m_nextBreakpointNumber = 0;
+ }
+
+ foreach (BreakpointId id, ids) {
+ BreakpointResponse response;
+ const BreakpointParameters &p = handler->breakpointData(id);
+ response.fromParameters(p);
+ switch (handler->state(id)) {
+ case BreakpointInsertRequested:
+ response.number = m_nextBreakpointNumber++;
+ postCommand(cdbAddBreakpointCommand(p, false, response.number), 0);
+ handler->notifyBreakpointInsertProceeding(id);
+ handler->notifyBreakpointInsertOk(id);
+ handler->setResponse(id, response);
+ break;
+ case BreakpointChangeRequested:
+ // Skip disabled breakpoints, else add.
+ handler->notifyBreakpointChangeProceeding(id);
+ if (p.enabled) {
+ response.number = m_nextBreakpointNumber++;
+ postCommand(cdbAddBreakpointCommand(p, false, response.number), 0);
+ handler->notifyBreakpointChangeOk(id);
+ handler->setResponse(id, response);
+ }
+ break;
+ case BreakpointRemoveRequested:
+ handler->notifyBreakpointRemoveProceeding(id);
+ handler->notifyBreakpointRemoveOk(id);
+ break;
+ case BreakpointInserted:
+ // Existing breakpoints were deleted due to change/removal, re-set
+ if (syncType == BreakpointsRemovedChanged) {
+ response.number = m_nextBreakpointNumber++;;
+ postCommand(cdbAddBreakpointCommand(p, false, response.number), 0);
+ handler->setResponse(id, response);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+QString CdbEngine::normalizeFileName(const QString &f)
+{
+ QMap<QString, QString>::const_iterator it = m_normalizedFileCache.constFind(f);
+ if (it != m_normalizedFileCache.constEnd())
+ return it.value();
+ const QString winF = QDir::toNativeSeparators(f);
+#ifdef Q_OS_WIN
+ QString normalized = winNormalizeFileName(winF);
+#else
+ QString normalized = winF;
+#endif
+ if (normalized.isEmpty()) { // At least upper case drive letter
+ normalized = winF;
+ if (normalized.size() > 2 && normalized.at(1) == QLatin1Char(':'))
+ normalized[0] = normalized.at(0).toUpper();
+ }
+ m_normalizedFileCache.insert(f, normalized);
+ return normalized;
+}
+
+// Parse frame from GDBMI. Duplicate of the gdb code, but that
+// has more processing.
+static StackFrames parseFrames(const QByteArray &data)
+{
+ GdbMi gdbmi;
+ gdbmi.fromString(data);
+ if (!gdbmi.isValid())
+ return StackFrames();
+
+ StackFrames rc;
+ const int count = gdbmi.childCount();
+ rc.reserve(count);
+ for (int i = 0; i < count; i++) {
+ const GdbMi &frameMi = gdbmi.childAt(i);
+ StackFrame frame;
+ frame.level = i;
+ const GdbMi fullName = frameMi.findChild("fullname");
+ if (fullName.isValid()) {
+ frame.file = QFile::decodeName(fullName.data());
+ frame.line = frameMi.findChild("line").data().toInt();
+ frame.usable = QFileInfo(frame.file).isFile();
+ }
+ frame.function = QLatin1String(frameMi.findChild("func").data());
+ frame.from = QLatin1String(frameMi.findChild("from").data());
+ frame.address = frameMi.findChild("addr").data().toULongLong(0, 16);
+ rc.push_back(frame);
+ }
+ return rc;
+}
+
+void CdbEngine::handleStackTrace(const CdbExtensionCommandPtr &command)
+{
+ // Parse frames, find current.
+ if (command->success) {
+ int current = -1;
+ StackFrames frames = parseFrames(command->reply);
+ const int count = frames.size();
+ for (int i = 0; i < count; i++) {
+ if (!frames.at(i).file.isEmpty()) {
+ frames[i].file = QDir::cleanPath(normalizeFileName(frames.at(i).file));
+ if (current == -1 && frames[i].usable)
+ current = i;
+ }
+ }
+ if (count && current == -1) // No usable frame, use assembly.
+ current = 0;
+ // Set
+ stackHandler()->setFrames(frames);
+ activateFrame(current);
+ postCommandSequence(command->commandSequence);
+ } else {
+ showMessage(command->errorMessage, LogError);
+ }
+}
+
+void CdbEngine::dummyHandler(const CdbBuiltinCommandPtr &command)
+{
+ postCommandSequence(command->commandSequence);
+}
+
+// Post a sequence of standard commands: Trigger next once one completes successfully
+void CdbEngine::postCommandSequence(unsigned mask)
+{
+ if (debug)
+ qDebug("postCommandSequence 0x%x\n", mask);
+
+ if (!mask)
+ return;
+ if (mask & CommandListThreads) {
+ postExtensionCommand("threads", QByteArray(), 0, &CdbEngine::handleThreads, mask & ~CommandListThreads);
+ return;
+ }
+ if (mask & CommandListStack) {
+ postExtensionCommand("stack", QByteArray(), 0, &CdbEngine::handleStackTrace, mask & ~CommandListStack);
+ return;
+ }
+ if (mask & CommandListRegisters) {
+ QTC_ASSERT(threadsHandler()->currentThread() >= 0, return; )
+ postExtensionCommand("registers", QByteArray(), 0, &CdbEngine::handleRegisters, mask & ~CommandListRegisters);
+ return;
+ }
+ if (mask & CommandListModules) {
+ postExtensionCommand("modules", QByteArray(), 0, &CdbEngine::handleModules, mask & ~CommandListModules);
+ return;
+ }
+}
+
+} // namespace Cdb
+} // namespace Debugger
diff --git a/src/plugins/debugger/cdb2/cdbengine2.h b/src/plugins/debugger/cdb2/cdbengine2.h
new file mode 100644
index 0000000000..3bd7e5035f
--- /dev/null
+++ b/src/plugins/debugger/cdb2/cdbengine2.h
@@ -0,0 +1,209 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 DEBUGGER_CDBENGINE_H
+#define DEBUGGER_CDBENGINE_H
+
+#include "debuggerengine.h"
+
+#include <QtCore/QSharedPointer>
+#include <QtCore/QProcess>
+#include <QtCore/QVariant>
+#include <QtCore/QMap>
+#include <QtCore/QTime>
+
+namespace Debugger {
+namespace Cdb {
+
+class DisassemblerAgent;
+struct CdbBuiltinCommand;
+struct CdbExtensionCommand;
+struct CdbOptions;
+class ByteArrayInputStream;
+
+class CdbEngine : public Debugger::DebuggerEngine
+{
+ Q_OBJECT
+
+public:
+ typedef QSharedPointer<CdbOptions> OptionsPtr;
+
+ enum CommandFlags { QuietCommand = 0x1 };
+ // Flag bits for a sequence of commands
+ enum CommandSequenceFlags {
+ CommandListStack = 0x1,
+ CommandListThreads = 0x2,
+ CommandListRegisters = 0x4,
+ CommandListModules = 0x8
+ };
+
+ typedef QSharedPointer<CdbBuiltinCommand> CdbBuiltinCommandPtr;
+ typedef QSharedPointer<CdbExtensionCommand> CdbExtensionCommandPtr;
+ typedef void (CdbEngine::*BuiltinCommandHandler)(const CdbBuiltinCommandPtr &);
+ typedef void (CdbEngine::*ExtensionCommandHandler)(const CdbExtensionCommandPtr &);
+
+ explicit CdbEngine(const DebuggerStartParameters &sp, const OptionsPtr &options);
+ virtual ~CdbEngine();
+ // Factory function that returns 0 if the debug engine library cannot be found.
+
+ virtual void setToolTipExpression(const QPoint &mousePos, TextEditor::ITextEditor *editor, int cursorPos);
+ virtual void setupEngine();
+ virtual void setupInferior();
+ virtual void runEngine();
+ virtual void shutdownInferior();
+ virtual void shutdownEngine();
+ virtual void detachDebugger();
+ virtual void updateWatchData(const Debugger::Internal::WatchData &data,
+ const Debugger::Internal::WatchUpdateFlags & flags = Debugger::Internal::WatchUpdateFlags());
+ virtual unsigned debuggerCapabilities() const;
+ virtual void setRegisterValue(int regnr, const QString &value);
+
+ virtual void executeStep();
+ virtual void executeStepOut();
+ virtual void executeNext();
+ virtual void executeStepI();
+ virtual void executeNextI();
+
+ virtual void continueInferior();
+ virtual void interruptInferior();
+
+ virtual void executeRunToLine(const QString &fileName, int lineNumber);
+ virtual void executeRunToFunction(const QString &functionName);
+ virtual void executeJumpToLine(const QString &fileName, int lineNumber);
+ virtual void assignValueInDebugger(const Debugger::Internal::WatchData *w, const QString &expr, const QVariant &value);
+ virtual void executeDebuggerCommand(const QString &command);
+
+ virtual void activateFrame(int index);
+ virtual void selectThread(int index);
+
+ virtual bool stateAcceptsBreakpointChanges() const;
+ virtual bool acceptsBreakpoint(BreakpointId id) const;
+ virtual void attemptBreakpointSynchronization();
+
+ virtual void fetchDisassembler(Debugger::Internal::DisassemblerAgent *agent);
+ virtual void fetchMemory(Debugger::Internal::MemoryAgent *, QObject *, quint64 addr, quint64 length);
+
+ virtual void reloadModules();
+ virtual void loadSymbols(const QString &moduleName);
+ virtual void loadAllSymbols();
+ virtual void requestModuleSymbols(const QString &moduleName);
+
+ virtual void reloadRegisters();
+ virtual void reloadSourceFiles();
+ virtual void reloadFullStack();
+
+ static QString extensionLibraryName(bool is64Bit);
+
+private slots:
+ void readyReadStandardOut();
+ void readyReadStandardError();
+ void processError();
+ void processFinished();
+ void postCommand(const QByteArray &cmd, unsigned flags);
+ void postBuiltinCommand(const QByteArray &cmd,
+ unsigned flags,
+ BuiltinCommandHandler handler,
+ unsigned nextCommandFlag = 0,
+ const QVariant &cookie = QVariant());
+
+ void postExtensionCommand(const QByteArray &cmd,
+ const QByteArray &arguments,
+ unsigned flags,
+ ExtensionCommandHandler handler,
+ unsigned nextCommandFlag = 0,
+ const QVariant &cookie = QVariant());
+
+ void postCommandSequence(unsigned mask);
+ void operateByInstructionTriggered(bool);
+
+private:
+ enum SpecialStopMode { NoSpecialStop, SpecialStopSynchronizeBreakpoints };
+
+ bool commandsPending() const;
+ void handleExtensionMessage(char t, int token, const QByteArray &what, const QByteArray &message);
+ bool doSetupEngine(QString *errorMessage);
+ void handleSessionAccessible(unsigned long cdbExState);
+ void handleSessionInaccessible(unsigned long cdbExState);
+ void handleSessionIdle(const QByteArray &message);
+ void doInterruptInferior(SpecialStopMode sm);
+ void doContinueInferior();
+ inline void parseOutputLine(QByteArray line);
+ inline bool isCdbProcessRunning() const { return m_process.state() != QProcess::NotRunning; }
+ bool canInterruptInferior() const;
+ void syncOperateByInstruction(bool operateByInstruction);
+
+ // Builtin commands
+ void dummyHandler(const CdbBuiltinCommandPtr &);
+ void handleStackTrace(const CdbExtensionCommandPtr &);
+ void handleRegisters(const CdbBuiltinCommandPtr &);
+ void handleDisassembler(const CdbBuiltinCommandPtr &);
+ void handleJumpToLineAddressResolution(const CdbBuiltinCommandPtr &);
+ // Extension commands
+ void handleThreads(const CdbExtensionCommandPtr &);
+ void handlePid(const CdbExtensionCommandPtr &reply);
+ void handleLocals(const CdbExtensionCommandPtr &reply);
+ void handleExpandLocals(const CdbExtensionCommandPtr &reply);
+ void handleRegisters(const CdbExtensionCommandPtr &reply);
+ void handleModules(const CdbExtensionCommandPtr &reply);
+ void handleMemory(const CdbExtensionCommandPtr &);
+
+ QString normalizeFileName(const QString &f);
+ void updateLocalVariable(const QByteArray &iname);
+ int elapsedLogTime() const;
+ void addLocalsOptions(ByteArrayInputStream &s) const;
+
+ const QByteArray m_creatorExtPrefix;
+ const QByteArray m_tokenPrefix;
+ const OptionsPtr m_options;
+
+ QProcess m_process;
+ QByteArray m_outputBuffer;
+ unsigned long m_inferiorPid;
+ // Debugger accessible (expecting commands)
+ bool m_accessible;
+ SpecialStopMode m_specialStopMode;
+ int m_nextCommandToken;
+ int m_nextBreakpointNumber;
+ QList<CdbBuiltinCommandPtr> m_builtinCommandQueue;
+ int m_currentBuiltinCommandIndex; // Current command whose output is recorded.
+ QList<CdbExtensionCommandPtr> m_extensionCommandQueue;
+ QMap<QString, QString> m_normalizedFileCache;
+ const QByteArray m_extensionCommandPrefixBA; // Library name used as prefix
+ bool m_operateByInstructionPending; // Creator operate by instruction action changed.
+ bool m_operateByInstruction;
+ bool m_notifyEngineShutdownOnTermination;
+ bool m_hasDebuggee;
+ QTime m_logTime;
+ mutable int m_elapsedLogTime;
+};
+
+} // namespace Cdb
+} // namespace Debugger
+
+#endif // DEBUGGER_CDBENGINE_H
diff --git a/src/plugins/debugger/cdb2/cdboptions2.cpp b/src/plugins/debugger/cdb2/cdboptions2.cpp
new file mode 100644
index 0000000000..57a364fdf6
--- /dev/null
+++ b/src/plugins/debugger/cdb2/cdboptions2.cpp
@@ -0,0 +1,227 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "cdboptions2.h"
+#include "cdbengine2.h"
+
+#ifdef Q_OS_WIN
+# include <utils/winutils.h>
+#endif
+
+#include <QtCore/QSettings>
+#include <QtCore/QDir>
+#include <QtCore/QFileInfo>
+#include <QtCore/QCoreApplication>
+
+static const char settingsGroupC[] = "CDB2";
+static const char enabledKeyC[] = "Enabled";
+static const char pathKeyC[] = "Path";
+static const char symbolPathsKeyC[] = "SymbolPaths";
+static const char sourcePathsKeyC[] = "SourcePaths";
+static const char breakEventKeyC[] = "BreakEvent";
+static const char is64bitKeyC[] = "64bit";
+
+namespace Debugger {
+namespace Cdb {
+
+CdbOptions::CdbOptions() :
+ enabled(false), is64bit(false)
+{
+}
+
+QString CdbOptions::settingsGroup()
+{
+ return QLatin1String(settingsGroupC);
+}
+
+void CdbOptions::clearExecutable()
+{
+ is64bit = enabled = false;
+ executable.clear();
+}
+
+void CdbOptions::clear()
+{
+ clearExecutable();
+ symbolPaths.clear();
+ sourcePaths.clear();
+}
+
+static inline QString msgAutoDetectFail(bool is64Bit, const QString &executable,
+ const QString &extLib)
+{
+ return QCoreApplication::translate("Debugger::Cdb::CdbOptions",
+ "Auto-detection of the new CDB debugging engine (%1bit) failed:\n"
+ "Debugger executable: %2\n"
+ "Extension library : %3 not present.\n").arg(is64Bit ? 64 : 32).
+ arg(QDir::toNativeSeparators(executable), QDir::toNativeSeparators(extLib));
+}
+
+static inline QString msgAutoDetect(bool is64Bit, const QString &executable,
+ const QString &extLib,
+ const QStringList &symbolPaths)
+{
+ return QCoreApplication::translate("Debugger::Cdb::CdbOptions",
+ "The new CDB debugging engine (%1bit) has been set up automatically:\n"
+ "Debugger executable: %2\n"
+ "Extension library : %3\n"
+ "Symbol paths : %4\n").arg(is64Bit ? 64 : 32).
+ arg(QDir::toNativeSeparators(executable), QDir::toNativeSeparators(extLib),
+ symbolPaths.join(QString(QLatin1Char(';'))));
+}
+
+QStringList CdbOptions::oldEngineSymbolPaths(const QSettings *s)
+{
+ return s->value(QLatin1String("CDB/SymbolPaths")).toStringList();
+}
+
+bool CdbOptions::autoDetect(const QSettings *s)
+{
+ QString autoExecutable;
+ bool auto64Bit;
+ // Check installation and existence of the extension library
+ CdbOptions::autoDetectExecutable(&autoExecutable, &auto64Bit);
+ if (autoExecutable.isEmpty())
+ return false;
+ const QString extLib = CdbEngine::extensionLibraryName(auto64Bit);
+ if (!QFileInfo(extLib).isFile()) {
+ const QString failMsg = msgAutoDetectFail(auto64Bit, autoExecutable, extLib);
+ qWarning("%s", qPrintable(failMsg));
+ clearExecutable();
+ return false;
+ }
+ enabled = true;
+ is64bit = auto64Bit;
+ executable = autoExecutable;
+ // Is there a symbol path from an old install? Use that
+ if (symbolPaths.empty())
+ symbolPaths = CdbOptions::oldEngineSymbolPaths(s);
+ const QString msg = msgAutoDetect(is64bit, QDir::toNativeSeparators(executable),
+ QDir::toNativeSeparators(extLib), symbolPaths);
+ qWarning("%s", qPrintable(msg));
+ return true;
+}
+
+void CdbOptions::fromSettings(QSettings *s)
+{
+ clear();
+ // Is this the first time we are called ->
+ // try to find automatically
+ const QString keyRoot = QLatin1String(settingsGroupC) + QLatin1Char('/');
+ const QString enabledKey = keyRoot + QLatin1String(enabledKeyC);
+ // First-time autodetection: Write back parameters
+ const bool firstTime = !s->contains(enabledKey);
+ if (firstTime && autoDetect(s)) {
+ toSettings(s);
+ return;
+ }
+ enabled = s->value(enabledKey, false).toBool();
+ is64bit = s->value(keyRoot + QLatin1String(is64bitKeyC), is64bit).toBool();
+ executable = s->value(keyRoot + QLatin1String(pathKeyC), executable).toString();
+ symbolPaths = s->value(keyRoot + QLatin1String(symbolPathsKeyC), QStringList()).toStringList();
+ sourcePaths = s->value(keyRoot + QLatin1String(sourcePathsKeyC), QStringList()).toStringList();
+ breakEvents = s->value(keyRoot + QLatin1String(breakEventKeyC), QStringList()).toStringList();
+}
+
+void CdbOptions::toSettings(QSettings *s) const
+{
+ s->beginGroup(QLatin1String(settingsGroupC));
+ s->setValue(QLatin1String(enabledKeyC), enabled);
+ s->setValue(QLatin1String(pathKeyC), executable);
+ s->setValue(QLatin1String(is64bitKeyC), is64bit);
+ s->setValue(QLatin1String(symbolPathsKeyC), symbolPaths);
+ s->setValue(QLatin1String(sourcePathsKeyC), sourcePaths);
+ s->setValue(QLatin1String(breakEventKeyC), breakEvents);
+ s->endGroup();
+}
+
+bool CdbOptions::equals(const CdbOptions &rhs) const
+{
+ return enabled == rhs.enabled && is64bit == rhs.is64bit
+ && executable == rhs.executable
+ && symbolPaths == rhs.symbolPaths
+ && sourcePaths == rhs.sourcePaths
+ && breakEvents == rhs.breakEvents;
+}
+
+bool CdbOptions::autoDetectExecutable(QString *outPath, bool *is64bitIn /* = 0 */,
+ QStringList *checkedDirectories /* = 0 */)
+{
+ // Look for $ProgramFiles/"Debugging Tools For Windows <bit-idy>/cdb.exe" and its
+ // " (x86)", " (x64)" variations.
+ static const char *postFixes[] = {" (x64)", " 64-bit", " (x86)", " (x32)" };
+ enum { first32bitIndex = 2 };
+
+ if (checkedDirectories)
+ checkedDirectories->clear();
+
+ outPath->clear();
+ const QByteArray programDirB = qgetenv("ProgramFiles");
+ if (programDirB.isEmpty())
+ return false;
+
+ const QString programDir = QString::fromLocal8Bit(programDirB) + QLatin1Char('/');
+ const QString installDir = QLatin1String("Debugging Tools For Windows");
+ const QString executable = QLatin1String("/cdb.exe");
+
+ QString path = programDir + installDir;
+ if (checkedDirectories)
+ checkedDirectories->push_back(path);
+ const QFileInfo fi(path + executable);
+ // Plain system installation
+ if (fi.isFile() && fi.isExecutable()) {
+ *outPath = fi.absoluteFilePath();
+ if (is64bitIn)
+#ifdef Q_OS_WIN
+ *is64bitIn = Utils::winIs64BitSystem();
+#else
+ *is64bitIn = false;
+#endif
+ return true;
+ }
+ // Try the post fixes
+ const int rootLength = path.size();
+ for (unsigned i = 0; i < sizeof(postFixes)/sizeof(const char*); i++) {
+ path.truncate(rootLength);
+ path += QLatin1String(postFixes[i]);
+ if (checkedDirectories)
+ checkedDirectories->push_back(path);
+ const QFileInfo fi2(path + executable);
+ if (fi2.isFile() && fi2.isExecutable()) {
+ if (is64bitIn)
+ *is64bitIn = i < first32bitIndex;
+ *outPath = fi2.absoluteFilePath();
+ return true;
+ }
+ }
+ return false;
+}
+
+} // namespace Internal
+} // namespace Debugger
diff --git a/src/plugins/debugger/cdb2/cdboptions2.h b/src/plugins/debugger/cdb2/cdboptions2.h
new file mode 100644
index 0000000000..ebec5a3951
--- /dev/null
+++ b/src/plugins/debugger/cdb2/cdboptions2.h
@@ -0,0 +1,78 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 CDBSETTINGS_H
+#define CDBSETTINGS_H
+
+#include <QtCore/QStringList>
+
+QT_BEGIN_NAMESPACE
+class QSettings;
+QT_END_NAMESPACE
+
+namespace Debugger {
+namespace Cdb {
+
+struct CdbOptions
+{
+public:
+ CdbOptions();
+ void clearExecutable();
+ void clear();
+
+ void fromSettings(QSettings *s); // Writes parameters on first-time autodetect
+ bool autoDetect(const QSettings *s);
+ void toSettings(QSettings *s) const;
+
+ bool equals(const CdbOptions &rhs) const;
+
+ static bool autoDetectExecutable(QString *outPath, bool *is64bit = 0,
+ QStringList *checkedDirectories = 0);
+
+ static QString settingsGroup();
+ static QStringList oldEngineSymbolPaths(const QSettings *s);
+
+ bool enabled;
+ bool is64bit;
+ QString executable;
+ QStringList symbolPaths;
+ QStringList sourcePaths;
+ // Events to break on (Command 'sxe' with abbreviation and optional parameter)
+ QStringList breakEvents;
+};
+
+inline bool operator==(const CdbOptions &s1, const CdbOptions &s2)
+{ return s1.equals(s2); }
+inline bool operator!=(const CdbOptions &s1, const CdbOptions &s2)
+{ return !s1.equals(s2); }
+
+} // namespace Internal
+} // namespace Debugger
+
+#endif // CDBSETTINGS_H
diff --git a/src/plugins/debugger/cdb2/cdboptionspage2.cpp b/src/plugins/debugger/cdb2/cdboptionspage2.cpp
new file mode 100644
index 0000000000..b60a6c56c0
--- /dev/null
+++ b/src/plugins/debugger/cdb2/cdboptionspage2.cpp
@@ -0,0 +1,446 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "cdboptionspage2.h"
+#include "cdboptions2.h"
+#include "debuggerconstants.h"
+#include "cdbengine2.h"
+
+#ifdef Q_OS_WIN
+# include <utils/winutils.h>
+#endif
+#include <utils/synchronousprocess.h>
+
+#include <coreplugin/icore.h>
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QUrl>
+#include <QtCore/QFileInfo>
+#include <QtCore/QDir>
+#include <QtCore/QDateTime>
+#include <QtCore/QTextStream>
+#include <QtCore/QTimer>
+#include <QtCore/QProcess>
+#include <QtGui/QMessageBox>
+#include <QtGui/QLineEdit>
+#include <QtGui/QDesktopServices>
+
+static const char *dgbToolsDownloadLink32C = "http://www.microsoft.com/whdc/devtools/debugging/installx86.Mspx";
+static const char *dgbToolsDownloadLink64C = "http://www.microsoft.com/whdc/devtools/debugging/install64bit.Mspx";
+
+namespace Debugger {
+namespace Cdb {
+
+struct EventsDescription {
+ const char *abbreviation;
+ bool hasParameter;
+ const char *description;
+};
+
+// Parameters of the "sxe" command
+const EventsDescription eventDescriptions[] =
+{
+ {"eh", false, QT_TRANSLATE_NOOP("Debugger::Cdb::CdbBreakEventWidget",
+ "C++ exception")},
+ {"ct", false, QT_TRANSLATE_NOOP("Debugger::Cdb::CdbBreakEventWidget",
+ "Thread creation")},
+ {"et", false, QT_TRANSLATE_NOOP("Debugger::Cdb::CdbBreakEventWidget",
+ "Thread exit")},
+ {"ld", true, QT_TRANSLATE_NOOP("Debugger::Cdb::CdbBreakEventWidget",
+ "Load Module:")},
+ {"ud", true, QT_TRANSLATE_NOOP("Debugger::Cdb::CdbBreakEventWidget",
+ "Unload Module:")},
+ {"out", true, QT_TRANSLATE_NOOP("Debugger::Cdb::CdbBreakEventWidget",
+ "Output:")}
+};
+
+static inline int indexOfEvent(const QString &abbrev)
+{
+ const size_t eventCount = sizeof(eventDescriptions) / sizeof(EventsDescription);
+ for (size_t e = 0; e < eventCount; e++)
+ if (abbrev == QLatin1String(eventDescriptions[e].abbreviation))
+ return int(e);
+ return -1;
+}
+
+CdbBreakEventWidget::CdbBreakEventWidget(QWidget *parent) : QWidget(parent)
+{
+ // 1 column with checkboxes only,
+ // further columns with checkbox + parameter
+ QHBoxLayout *mainLayout = new QHBoxLayout;
+ QVBoxLayout *leftLayout = new QVBoxLayout;
+ QFormLayout *parameterLayout = 0;
+ mainLayout->addLayout(leftLayout);
+ const size_t eventCount = sizeof(eventDescriptions) / sizeof(EventsDescription);
+ for (size_t e = 0; e < eventCount; e++) {
+ QCheckBox *cb = new QCheckBox(tr(eventDescriptions[e].description));
+ QLineEdit *le = 0;
+ if (eventDescriptions[e].hasParameter) {
+ if (!parameterLayout) {
+ parameterLayout = new QFormLayout;
+ mainLayout->addSpacerItem(new QSpacerItem(20, 0, QSizePolicy::MinimumExpanding, QSizePolicy::Ignored));
+ mainLayout->addLayout(parameterLayout);
+ }
+ le = new QLineEdit;
+ parameterLayout->addRow(cb, le);
+ if (parameterLayout->count() >= 4) // New column
+ parameterLayout = 0;
+ } else {
+ leftLayout->addWidget(cb);
+ }
+ m_checkBoxes.push_back(cb);
+ m_lineEdits.push_back(le);
+ }
+ setLayout(mainLayout);
+}
+
+void CdbBreakEventWidget::clear()
+{
+ foreach (QLineEdit *l, m_lineEdits) {
+ if (l)
+ l->clear();
+ }
+ foreach (QCheckBox *c, m_checkBoxes)
+ c->setChecked(false);
+}
+
+void CdbBreakEventWidget::setBreakEvents(const QStringList &l)
+{
+ clear();
+ // Split the list of ("eh", "out:MyOutput")
+ foreach (const QString &evt, l) {
+ const int colonPos = evt.indexOf(QLatin1Char(':'));
+ const QString abbrev = colonPos != -1 ? evt.mid(0, colonPos) : evt;
+ const int index = indexOfEvent(abbrev);
+ if (index != -1)
+ m_checkBoxes.at(index)->setChecked(true);
+ if (colonPos != -1 && m_lineEdits.at(index))
+ m_lineEdits.at(index)->setText(evt.mid(colonPos + 1));
+ }
+}
+
+QString CdbBreakEventWidget::filterText(int i) const
+{
+ return m_lineEdits.at(i) ? m_lineEdits.at(i)->text() : QString();
+}
+
+QStringList CdbBreakEventWidget::breakEvents() const
+{
+ // Compile a list of ("eh", "out:MyOutput")
+ QStringList rc;
+ const int eventCount = sizeof(eventDescriptions) / sizeof(EventsDescription);
+ for (int e = 0; e < eventCount; e++) {
+ if (m_checkBoxes.at(e)->isChecked()) {
+ const QString filter = filterText(e);
+ QString s = QLatin1String(eventDescriptions[e].abbreviation);
+ if (!filter.isEmpty()) {
+ s += QLatin1Char(':');
+ s += filter;
+ }
+ rc.push_back(s);
+ }
+ }
+ return rc;
+}
+
+static inline QString msgPathConfigNote()
+{
+#ifdef Q_OS_WIN
+ const bool is64bit = Utils::winIs64BitSystem();
+#else
+ const bool is64bit = false;
+#endif
+ const QString link = is64bit ? QLatin1String(dgbToolsDownloadLink64C) : QLatin1String(dgbToolsDownloadLink32C);
+ //: Label text for path configuration. %2 is "x-bit version".
+ return CdbOptionsPageWidget::tr(
+ "<html><body><p>Specify the path to the "
+ "<a href=\"%1\">Windows Console Debugger executable</a>"
+ " (%2) here.</p>"
+ "</body></html>").arg(link, (is64bit ? CdbOptionsPageWidget::tr("64-bit version")
+ : CdbOptionsPageWidget::tr("32-bit version")));
+}
+
+CdbOptionsPageWidget::CdbOptionsPageWidget(QWidget *parent) :
+ QWidget(parent), m_breakEventWidget(new CdbBreakEventWidget),
+ m_reportTimer(0)
+{
+ m_ui.setupUi(this);
+ m_ui.noteLabel->setText(msgPathConfigNote());
+ m_ui.noteLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
+ connect(m_ui.noteLabel, SIGNAL(linkActivated(QString)), this, SLOT(downLoadLinkActivated(QString)));
+
+ m_ui.pathChooser->setExpectedKind(Utils::PathChooser::ExistingCommand);
+ m_ui.pathChooser->addButton(tr("Autodetect"), this, SLOT(autoDetect()));
+ m_ui.cdbPathGroupBox->installEventFilter(this);
+ QVBoxLayout *eventLayout = new QVBoxLayout;
+ eventLayout->addWidget(m_breakEventWidget);
+ m_ui.eventGroupBox->setLayout(eventLayout);
+}
+
+void CdbOptionsPageWidget::setOptions(CdbOptions &o)
+{
+ m_ui.pathChooser->setPath(o.executable);
+ m_ui.is64BitCheckBox->setChecked(o.is64bit);
+ m_ui.cdbPathGroupBox->setChecked(o.enabled);
+ setSymbolPaths(o.symbolPaths);
+ m_ui.sourcePathListEditor->setPathList(o.sourcePaths);
+ m_breakEventWidget->setBreakEvents(o.breakEvents);
+}
+
+bool CdbOptionsPageWidget::is64Bit() const
+{
+ return m_ui.is64BitCheckBox->isChecked();
+}
+
+QString CdbOptionsPageWidget::path() const
+{
+ return m_ui.pathChooser->path();
+}
+
+CdbOptions CdbOptionsPageWidget::options() const
+{
+ CdbOptions rc;
+ rc.executable = path();
+ rc.enabled = m_ui.cdbPathGroupBox->isChecked();
+ rc.is64bit = is64Bit();
+ rc.symbolPaths = symbolPaths();
+ rc.sourcePaths = m_ui.sourcePathListEditor->pathList();
+ rc.breakEvents = m_breakEventWidget->breakEvents();
+ return rc;
+}
+
+QStringList CdbOptionsPageWidget::symbolPaths() const
+{
+ return m_ui.symbolPathListEditor->pathList();
+}
+
+void CdbOptionsPageWidget::setSymbolPaths(const QStringList &s)
+{
+ m_ui.symbolPathListEditor->setPathList(s);
+}
+
+void CdbOptionsPageWidget::hideReportLabel()
+{
+ m_ui.reportLabel->clear();
+ m_ui.reportLabel->setVisible(false);
+}
+
+void CdbOptionsPageWidget::autoDetect()
+{
+ QString executable;
+ QStringList checkedDirectories;
+ bool is64bit;
+ const bool ok = CdbOptions::autoDetectExecutable(&executable, &is64bit, &checkedDirectories);
+ m_ui.cdbPathGroupBox->setChecked(ok);
+ if (ok) {
+ m_ui.is64BitCheckBox->setChecked(is64bit);
+ m_ui.pathChooser->setPath(executable);
+ QString report;
+ // Now check for the extension library as well.
+ const bool allOk = checkInstallation(executable, is64Bit(), &report);
+ setReport(report, allOk);
+ // On this occasion, if no symbol paths are specified, check for an
+ // old CDB installation
+ if (symbolPaths().isEmpty())
+ setSymbolPaths(CdbOptions::oldEngineSymbolPaths(Core::ICore::instance()->settings()));
+ } else {
+ const QString msg = tr("\"Debugging Tools for Windows\" could not be found.");
+ const QString details = tr("Checked:\n%1").arg(checkedDirectories.join(QString(QLatin1Char('\n'))));
+ QMessageBox msbBox(QMessageBox::Information, tr("Autodetection"), msg, QMessageBox::Ok, this);
+ msbBox.setDetailedText(details);
+ msbBox.exec();
+ }
+}
+
+void CdbOptionsPageWidget::setReport(const QString &msg, bool success)
+{
+ // Hide label after some interval
+ if (!m_reportTimer) {
+ m_reportTimer = new QTimer(this);
+ m_reportTimer->setSingleShot(true);
+ connect(m_reportTimer, SIGNAL(timeout()), this, SLOT(hideReportLabel()));
+ } else {
+ if (m_reportTimer->isActive())
+ m_reportTimer->stop();
+ }
+ m_reportTimer->setInterval(success ? 10000 : 20000);
+ m_reportTimer->start();
+
+ m_ui.reportLabel->setText(msg);
+ m_ui.reportLabel->setStyleSheet(success ? QString() : QString::fromAscii("background-color : 'red'"));
+ m_ui.reportLabel->setVisible(true);
+}
+
+void CdbOptionsPageWidget::downLoadLinkActivated(const QString &link)
+{
+ QDesktopServices::openUrl(QUrl(link));
+}
+
+QString CdbOptionsPageWidget::searchKeywords() const
+{
+ QString rc;
+ QTextStream(&rc) << m_ui.pathLabel->text() << ' ' << m_ui.symbolPathLabel->text()
+ << ' ' << m_ui.sourcePathLabel->text();
+ rc.remove(QLatin1Char('&'));
+ return rc;
+}
+
+static QString cdbVersion(const QString &executable)
+{
+ QProcess cdb;
+ cdb.start(executable, QStringList(QLatin1String("-version")));
+ cdb.closeWriteChannel();
+ if (!cdb.waitForStarted())
+ return QString();
+ if (!cdb.waitForFinished()) {
+ Utils::SynchronousProcess::stopProcess(cdb);
+ return QString();
+ }
+ return QString::fromLocal8Bit(cdb.readAllStandardOutput());
+}
+
+bool CdbOptionsPageWidget::checkInstallation(const QString &executable,
+ bool is64Bit, QString *message)
+{
+ // 1) Check on executable
+ unsigned checkedItems = 0;
+ QString rc;
+ if (executable.isEmpty()) {
+ message->append(tr("No cdb executable specified.\n"));
+ } else {
+ const QString version = cdbVersion(executable);
+ if (version.isEmpty()) {
+ message->append(tr("Unable to determine version of %1.\n").
+ arg(executable));
+ } else {
+ message->append(tr("Version: %1").arg(version));
+ checkedItems++;
+ }
+ }
+
+ // 2) Check on extension library
+ const QFileInfo extensionFi(CdbEngine::extensionLibraryName(is64Bit));
+ if (extensionFi.isFile()) {
+ message->append(tr("Extension library: %1, built: %3.\n").
+ arg(QDir::toNativeSeparators(extensionFi.absoluteFilePath())).
+ arg(extensionFi.lastModified().toString(Qt::SystemLocaleShortDate)));
+ checkedItems++;
+ } else {
+ message->append("Extension library not found.\n");
+ }
+ return checkedItems == 2u;
+}
+
+bool CdbOptionsPageWidget::eventFilter(QObject *o, QEvent *e)
+{
+ if (o != m_ui.cdbPathGroupBox || e->type() != QEvent::ToolTip)
+ return QWidget::eventFilter(o, e);
+ QString message;
+ checkInstallation(path(), is64Bit(), &message);
+ m_ui.cdbPathGroupBox->setToolTip(message);
+ return false;
+}
+
+// ---------- CdbOptionsPage
+
+CdbOptionsPage *CdbOptionsPage::m_instance = 0;
+
+CdbOptionsPage::CdbOptionsPage() :
+ m_options(new CdbOptions)
+{
+ CdbOptionsPage::m_instance = this;
+ m_options->fromSettings(Core::ICore::instance()->settings());
+}
+
+CdbOptionsPage::~CdbOptionsPage()
+{
+ CdbOptionsPage::m_instance = 0;
+}
+
+QString CdbOptionsPage::settingsId()
+{
+ return QLatin1String("F.Cda"); // before old CDB
+}
+
+QString CdbOptionsPage::displayName() const
+{
+ return tr("CDB (new, experimental)");
+}
+
+QString CdbOptionsPage::category() const
+{
+ return QLatin1String(Debugger::Constants::DEBUGGER_SETTINGS_CATEGORY);
+}
+
+QString CdbOptionsPage::displayCategory() const
+{
+ return QCoreApplication::translate("Debugger", Debugger::Constants::DEBUGGER_SETTINGS_TR_CATEGORY);
+}
+
+QIcon CdbOptionsPage::categoryIcon() const
+{
+ return QIcon(QLatin1String(Debugger::Constants::DEBUGGER_COMMON_SETTINGS_CATEGORY_ICON));
+}
+
+QWidget *CdbOptionsPage::createPage(QWidget *parent)
+{
+ m_widget = new CdbOptionsPageWidget(parent);
+ m_widget->setOptions(*m_options);
+ if (m_searchKeywords.isEmpty())
+ m_searchKeywords = m_widget->searchKeywords();
+ return m_widget;
+}
+
+void CdbOptionsPage::apply()
+{
+ if (!m_widget)
+ return;
+ const CdbOptions newOptions = m_widget->options();
+ if (*m_options != newOptions) {
+ *m_options = newOptions;
+ m_options->toSettings(Core::ICore::instance()->settings());
+ }
+}
+
+void CdbOptionsPage::finish()
+{
+}
+
+bool CdbOptionsPage::matches(const QString &s) const
+{
+ return m_searchKeywords.contains(s, Qt::CaseInsensitive);
+}
+
+CdbOptionsPage *CdbOptionsPage::instance()
+{
+ return m_instance;
+}
+
+} // namespace Internal
+} // namespace Debugger
diff --git a/src/plugins/debugger/cdb2/cdboptionspage2.h b/src/plugins/debugger/cdb2/cdboptionspage2.h
new file mode 100644
index 0000000000..b441cdcc1f
--- /dev/null
+++ b/src/plugins/debugger/cdb2/cdboptionspage2.h
@@ -0,0 +1,138 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 CDBSETTINGSPAGE_H
+#define CDBSETTINGSPAGE_H
+
+#include "cdboptions2.h"
+
+#include <coreplugin/dialogs/ioptionspage.h>
+#include "ui_cdboptionspagewidget2.h"
+
+#include <QtGui/QWidget>
+#include <QtCore/QPointer>
+#include <QtCore/QSharedPointer>
+
+QT_BEGIN_NAMESPACE
+class QTimer;
+QT_END_NAMESPACE
+
+namespace Debugger {
+namespace Cdb {
+
+// Widget displaying a list of break events for the 'sxe' command
+// with a checkbox to enable 'break' and optionally a QLineEdit for
+// events with parameters (like 'out:Needle').
+class CdbBreakEventWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ explicit CdbBreakEventWidget(QWidget *parent = 0);
+
+ void setBreakEvents(const QStringList &l);
+ QStringList breakEvents() const;
+
+private:
+ QString filterText(int i) const;
+ void clear();
+
+ QList<QCheckBox*> m_checkBoxes;
+ QList<QLineEdit*> m_lineEdits;
+};
+
+class CdbOptionsPageWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ explicit CdbOptionsPageWidget(QWidget *parent);
+
+ void setOptions(CdbOptions &o);
+ CdbOptions options() const;
+
+ QString searchKeywords() const;
+
+ virtual bool eventFilter(QObject *, QEvent *);
+
+private slots:
+ void autoDetect();
+ void downLoadLinkActivated(const QString &);
+ void hideReportLabel();
+
+private:
+ QStringList symbolPaths() const;
+ void setSymbolPaths(const QStringList &s);
+ void setReport(const QString &, bool success);
+ inline bool is64Bit() const;
+ inline QString path() const;
+
+ static bool checkInstallation(const QString &executable, bool is64Bit,
+ QString *message);
+
+ Ui::CdbOptionsPageWidget2 m_ui;
+ CdbBreakEventWidget *m_breakEventWidget;
+ QTimer *m_reportTimer;
+};
+
+class CdbOptionsPage : public Core::IOptionsPage
+{
+ Q_DISABLE_COPY(CdbOptionsPage)
+ Q_OBJECT
+public:
+ explicit CdbOptionsPage();
+ virtual ~CdbOptionsPage();
+
+ static CdbOptionsPage *instance();
+
+ // IOptionsPage
+ virtual QString id() const { return settingsId(); }
+ virtual QString displayName() const;
+ virtual QString category() const;
+ virtual QString displayCategory() const;
+ QIcon categoryIcon() const;
+
+ virtual QWidget *createPage(QWidget *parent);
+ virtual void apply();
+ virtual void finish();
+ virtual bool matches(const QString &) const;
+
+ static QString settingsId();
+
+ QSharedPointer<CdbOptions> options() const { return m_options; }
+
+private:
+ static CdbOptionsPage *m_instance;
+ const QSharedPointer<CdbOptions> m_options;
+ QPointer<CdbOptionsPageWidget> m_widget;
+ QString m_searchKeywords;
+};
+
+} // namespace Internal
+} // namespace Debugger
+
+#endif // CDBSETTINGSPAGE_H
diff --git a/src/plugins/debugger/cdb2/cdboptionspagewidget2.ui b/src/plugins/debugger/cdb2/cdboptionspagewidget2.ui
new file mode 100644
index 0000000000..f15d09d1b8
--- /dev/null
+++ b/src/plugins/debugger/cdb2/cdboptionspagewidget2.ui
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Debugger::Cdb::CdbOptionsPageWidget2</class>
+ <widget class="QWidget" name="Debugger::Cdb::CdbOptionsPageWidget2">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>347</width>
+ <height>358</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QGroupBox" name="cdbPathGroupBox">
+ <property name="title">
+ <string extracomment="Placeholder">CDB</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <layout class="QFormLayout" name="formLayout">
+ <item row="1" column="0">
+ <widget class="QLabel" name="pathLabel">
+ <property name="text">
+ <string>Path:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="Utils::PathChooser" name="pathChooser" native="true"/>
+ </item>
+ <item row="0" column="0" colspan="2">
+ <widget class="QLabel" name="noteLabel">
+ <property name="text">
+ <string notr="true" extracomment="Placeholder">Note: bla, blah</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" colspan="2">
+ <widget class="QCheckBox" name="is64BitCheckBox">
+ <property name="text">
+ <string>64 bit</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="pathGroupBox">
+ <property name="title">
+ <string>Debugger Paths</string>
+ </property>
+ <layout class="QFormLayout" name="formLayout_2">
+ <property name="fieldGrowthPolicy">
+ <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
+ </property>
+ <item row="0" column="0">
+ <widget class="QLabel" name="symbolPathLabel">
+ <property name="text">
+ <string>Symbol paths:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="Debugger::Internal::CdbSymbolPathListEditor" name="symbolPathListEditor" native="true"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="sourcePathLabel">
+ <property name="text">
+ <string>Source paths:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="Utils::PathListEditor" name="sourcePathListEditor" native="true"/>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="eventGroupBox">
+ <property name="title">
+ <string>Break on:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="reportLabel">
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>Utils::PathChooser</class>
+ <extends>QWidget</extends>
+ <header location="global">utils/pathchooser.h</header>
+ <container>1</container>
+ </customwidget>
+ <customwidget>
+ <class>Utils::PathListEditor</class>
+ <extends>QWidget</extends>
+ <header location="global">utils/pathlisteditor.h</header>
+ <container>1</container>
+ </customwidget>
+ <customwidget>
+ <class>Debugger::Internal::CdbSymbolPathListEditor</class>
+ <extends>QWidget</extends>
+ <header location="global">cdbsymbolpathlisteditor.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/plugins/debugger/cdb2/cdbparsehelpers.cpp b/src/plugins/debugger/cdb2/cdbparsehelpers.cpp
new file mode 100644
index 0000000000..78e56a3551
--- /dev/null
+++ b/src/plugins/debugger/cdb2/cdbparsehelpers.cpp
@@ -0,0 +1,272 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "cdbparsehelpers.h"
+#include "breakpoint.h"
+#include "threadshandler.h"
+#include "registerhandler.h"
+#include "bytearrayinputstream.h"
+#include "gdb/gdbmi.h"
+#ifdef Q_OS_WIN
+# include "shared/dbgwinutils.h"
+#endif
+#include <QtCore/QByteArray>
+#include <QtCore/QVariant>
+#include <QtCore/QString>
+#include <QtCore/QDir>
+#include <QtCore/QDebug>
+
+#include <utils/qtcassert.h>
+
+#include <cctype>
+
+namespace Debugger {
+namespace Cdb {
+
+// Convert breakpoint in CDB syntax.
+QByteArray cdbAddBreakpointCommand(const Debugger::Internal::BreakpointParameters &bpIn, bool oneshot, int id)
+{
+#ifdef Q_OS_WIN
+ const Debugger::Internal::BreakpointParameters bp = Debugger::Internal::fixWinMSVCBreakpoint(bpIn);
+#else
+ const Debugger::Internal::BreakpointParameters bp = bpIn;
+#endif
+
+ QByteArray rc;
+ ByteArrayInputStream str(rc);
+
+ if (bp.threadSpec >= 0)
+ str << '~' << bp.threadSpec << ' ';
+
+ str << (bp.type == Debugger::Internal::Watchpoint ? "ba" : "bp");
+ if (id >= 0)
+ str << id;
+ str << ' ';
+ if (oneshot)
+ str << "/1 ";
+ switch (bp.type) {
+ case Debugger::Internal::UnknownType:
+ case Debugger::Internal::BreakpointAtCatch:
+ case Debugger::Internal::BreakpointAtThrow:
+ case Debugger::Internal::BreakpointAtMain:
+ QTC_ASSERT(false, return QByteArray(); )
+ break;
+ case Debugger::Internal::BreakpointByAddress:
+ str << hex << hexPrefixOn << bp.address << hexPrefixOff << dec;
+ break;
+ case Debugger::Internal::BreakpointByFunction:
+ str << bp.functionName;
+ break;
+ case Debugger::Internal::BreakpointByFileAndLine:
+ str << '`' << QDir::toNativeSeparators(bp.fileName) << ':' << bp.lineNumber << '`';
+ break;
+ case Debugger::Internal::Watchpoint:
+ str << "rw 1 " << hex << hexPrefixOn << bp.address << hexPrefixOff << dec;
+ break;
+ }
+ if (bp.ignoreCount)
+ str << ' ' << bp.ignoreCount;
+ // Condition currently unsupported.
+ return rc;
+}
+
+// Fix a CDB integer value: '00000000`0012a290' -> '12a290', '0n10' ->'10'
+QByteArray fixCdbIntegerValue(QByteArray t, bool stripLeadingZeros, int *basePtr /* = 0 */)
+{
+ if (t.isEmpty())
+ return t;
+ int base = 16;
+ // Prefixes
+ if (t.startsWith("0x")) {
+ t.remove(0, 2);
+ } else if (t.startsWith("0n")) {
+ base = 10;
+ t.remove(0, 2);
+ }
+ if (base == 16 && t.size() >= 9 && t.at(8) == '`')
+ t.remove(8, 1);
+ if (stripLeadingZeros) { // Strip all but last '0'
+ const int last = t.size() - 1;
+ int pos = 0;
+ for ( ; pos < last && t.at(pos) == '0'; pos++) ;
+ if (pos)
+ t.remove(0, pos);
+ }
+ if (basePtr)
+ *basePtr = base;
+ return t;
+}
+
+// Convert a CDB integer value: '00000000`0012a290' -> '12a290', '0n10' ->'10'
+QVariant cdbIntegerValue(const QByteArray &t)
+{
+ int base;
+ const QByteArray fixed = fixCdbIntegerValue(t, false, &base);
+ bool ok;
+ const QVariant converted = base == 16 ?
+ fixed.toULongLong(&ok, base) :
+ fixed.toLongLong(&ok, base);
+ QTC_ASSERT(ok, return QVariant(); )
+ return converted;
+}
+
+/* \code
+0:002> ~ [Debugger-Id] Id: <hex pid> <hex tid> Suspends count thread environment block add state name
+ 0 Id: 133c.1374 Suspend: 1 Teb: 000007ff`fffdd000 Unfrozen
+. 2 Id: 133c.1160 Suspend: 1 Teb: 000007ff`fffd9000 Unfrozen "QThread"
+ 3 Id: 133c.38c Suspend: 1 Teb: 000007ff`fffd7000 Unfrozen "QThread"
+\endcode */
+
+static inline bool parseThread(QByteArray line, Debugger::Internal::ThreadData *thread, bool *current)
+{
+ *current = false;
+ if (line.size() < 5)
+ return false;
+ *current = line.at(0) == '.';
+ if (current)
+ line[0] = ' ';
+ const QList<QByteArray> tokens = simplify(line).split(' ');
+ if (tokens.size() < 8 || tokens.at(1) != "Id:")
+ return false;
+ switch (tokens.size()) { // fallthru intended
+ case 9:
+ thread->name = QString::fromLocal8Bit(tokens.at(8));
+ case 8:
+ thread->state = QString::fromLocal8Bit(tokens.at(7));
+ case 3: {
+ const QByteArray &pidTid = tokens.at(2);
+ const int dotPos = pidTid.indexOf('.');
+ if (dotPos != -1)
+ thread->targetId = QLatin1String("0x") + QString::fromAscii(pidTid.mid(dotPos + 1));
+ }
+ case 1:
+ thread->id = tokens.at(0).toInt();
+ break;
+ } // switch size
+ return true;
+}
+
+QString debugByteArray(const QByteArray &a)
+{
+ QString rc;
+ const int size = a.size();
+ rc.reserve(size * 2);
+ QTextStream str(&rc);
+ for (int i = 0; i < size; i++) {
+ const unsigned char uc = (unsigned char)(a.at(i));
+ switch (uc) {
+ case 0:
+ str << "\\0";
+ break;
+ case '\n':
+ str << "\\n";
+ break;
+ case '\t':
+ str << "\\t";
+ break;
+ case '\r':
+ str << "\\r";
+ break;
+ default:
+ if (uc >=32 && uc < 128) {
+ str << a.at(i);
+ } else {
+ str << '<' << unsigned(uc) << '>';
+ }
+ break;
+ }
+ }
+ return rc;
+}
+
+QString StringFromBase64EncodedUtf16(const QByteArray &a)
+{
+ QByteArray utf16 = QByteArray::fromBase64(a);
+ utf16.append('\0');
+ utf16.append('\0');
+ return QString::fromUtf16(reinterpret_cast<const unsigned short *>(utf16.constData()));
+}
+
+WinException::WinException() :
+ exceptionCode(0), exceptionFlags(0), exceptionAddress(0),
+ info1(0),info2(0), firstChance(false), lineNumber(0)
+{
+}
+
+void WinException::fromGdbMI(const Debugger::Internal::GdbMi &gdbmi)
+{
+ exceptionCode = gdbmi.findChild("exceptionCode").data().toUInt();
+ exceptionFlags = gdbmi.findChild("exceptionFlags").data().toUInt();
+ exceptionAddress = gdbmi.findChild("exceptionAddress").data().toULongLong();
+ firstChance = gdbmi.findChild("firstChance").data() != "0";
+ const Debugger::Internal::GdbMi ginfo1 = gdbmi.findChild("exceptionInformation0");
+ if (ginfo1.isValid()) {
+ info1 = ginfo1.data().toULongLong();
+ const Debugger::Internal::GdbMi ginfo2 = gdbmi.findChild("exceptionInformation1");
+ if (ginfo2.isValid())
+ info2 = ginfo1.data().toULongLong();
+ }
+ const Debugger::Internal::GdbMi gLineNumber = gdbmi.findChild("exceptionLine");
+ if (gLineNumber.isValid()) {
+ lineNumber = gLineNumber.data().toInt();
+ file = gdbmi.findChild("exceptionFile").data();
+ }
+ function = gdbmi.findChild("exceptionFunction").data();
+}
+
+QString WinException::toString(bool includeLocation) const
+{
+ QString rc;
+ QTextStream str(&rc);
+#ifdef Q_OS_WIN
+ Debugger::Internal::formatWindowsException(exceptionCode, exceptionAddress,
+ exceptionFlags, info1, info2, str);
+#endif
+ if (includeLocation) {
+ if (lineNumber) {
+ str << " at " << QLatin1String(file) << ':' << lineNumber;
+ } else {
+ if (!function.isEmpty())
+ str << " in " << QLatin1String(function);
+ }
+ }
+ return rc;
+}
+
+QDebug operator<<(QDebug s, const WinException &e)
+{
+ QDebug nsp = s.nospace();
+ nsp << "code=" << e.exceptionCode << ",flags=" << e.exceptionFlags
+ << ",address=0x" << QString::number(e.exceptionAddress, 16)
+ << ",firstChance=" << e.firstChance;
+ return s;
+}
+
+} // namespace Cdb
+} // namespace Debugger
diff --git a/src/plugins/debugger/cdb2/cdbparsehelpers.h b/src/plugins/debugger/cdb2/cdbparsehelpers.h
new file mode 100644
index 0000000000..87ae6491f6
--- /dev/null
+++ b/src/plugins/debugger/cdb2/cdbparsehelpers.h
@@ -0,0 +1,88 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 CDBPARSEHELPERS_H
+#define CDBPARSEHELPERS_H
+
+#include <QtCore/QtGlobal>
+#include <QtCore/QList>
+#include <QtCore/QVector>
+#include <QtCore/QByteArray>
+
+QT_BEGIN_NAMESPACE
+class QVariant;
+class QDebug;
+QT_END_NAMESPACE
+
+namespace Debugger {
+namespace Internal {
+class BreakpointData;
+class BreakpointParameters;
+struct ThreadData;
+class Register;
+class GdbMi;
+} // namespace Internal
+
+namespace Cdb {
+
+// Convert breakpoint in CDB syntax.
+QByteArray cdbAddBreakpointCommand(const Debugger::Internal::BreakpointParameters &d, bool oneshot = false, int id = -1);
+
+// Convert a CDB integer value: '00000000`0012a290' -> '12a290', '0n10' ->'10'
+QByteArray fixCdbIntegerValue(QByteArray t, bool stripLeadingZeros = false, int *basePtr = 0);
+// Convert a CDB integer value into quint64 or int64
+QVariant cdbIntegerValue(const QByteArray &t);
+
+QString debugByteArray(const QByteArray &a);
+QString StringFromBase64EncodedUtf16(const QByteArray &a);
+
+// Model EXCEPTION_RECORD + firstchance
+struct WinException
+{
+ WinException();
+ void fromGdbMI(const Debugger::Internal::GdbMi &);
+ QString toString(bool includeLocation = false) const;
+
+ unsigned exceptionCode;
+ unsigned exceptionFlags;
+ quint64 exceptionAddress;
+ quint64 info1;
+ quint64 info2;
+ bool firstChance;
+ QByteArray file;
+ int lineNumber;
+ QByteArray function;
+};
+
+QDebug operator<<(QDebug s, const WinException &e);
+
+} // namespace Cdb
+} // namespace Debugger
+
+#endif // CDBPARSEHELPERS_H
diff --git a/src/plugins/debugger/commonoptionspage.ui b/src/plugins/debugger/commonoptionspage.ui
index 4a87dde0c7..86e2c4c221 100644
--- a/src/plugins/debugger/commonoptionspage.ui
+++ b/src/plugins/debugger/commonoptionspage.ui
@@ -12,7 +12,7 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
- <widget class="QGroupBox" name="groupBox">
+ <widget class="QGroupBox" name="behaviorBox">
<property name="title">
<string>GUI Behavior</string>
</property>
diff --git a/src/plugins/debugger/consolewindow.cpp b/src/plugins/debugger/consolewindow.cpp
index 705d600ed6..5a1376787b 100644
--- a/src/plugins/debugger/consolewindow.cpp
+++ b/src/plugins/debugger/consolewindow.cpp
@@ -32,32 +32,22 @@
**************************************************************************/
#include "consolewindow.h"
+#include "logwindow.h"
#include "debuggeractions.h"
-#include "debuggerconstants.h"
+#include "debuggercore.h"
#include <QtCore/QDebug>
-#include <QtCore/QFile>
-#include <QtCore/QTime>
-#include <QtGui/QAction>
#include <QtGui/QHBoxLayout>
#include <QtGui/QVBoxLayout>
#include <QtGui/QKeyEvent>
-#include <QtGui/QLabel>
-#include <QtGui/QLineEdit>
#include <QtGui/QMenu>
-#include <QtGui/QSpacerItem>
-#include <QtGui/QSplitter>
#include <QtGui/QSyntaxHighlighter>
-#include <QtGui/QTextBlock>
#include <QtGui/QPlainTextEdit>
-#include <QtGui/QFileDialog>
-#include <QtGui/QMessageBox>
#include <aggregation/aggregate.h>
#include <coreplugin/findplaceholder.h>
-#include <coreplugin/minisplitter.h>
#include <find/basetextfind.h>
#include <utils/savedaction.h>
@@ -165,7 +155,7 @@ public:
History() : m_index(0) {}
void append(const QString &item) {
m_items.removeAll(item);
- m_items.append(item); m_index = m_items.size() - 1;
+ m_items.append(item); m_index = m_items.size() - 1;
}
void down() { m_index = qMin(m_index + 1, m_items.size()); }
void up() { m_index = qMax(m_index - 1, 0); }
@@ -202,15 +192,15 @@ public:
void contextMenuEvent(QContextMenuEvent *ev)
{
- theDebuggerAction(ExecuteCommand)->setData(textCursor().block().text());
+ debuggerCore()->action(ExecuteCommand)->setData(textCursor().block().text());
QMenu *menu = createStandardContextMenu();
menu->addAction(m_clearContentsAction);
menu->addAction(m_saveContentsAction); // X11 clipboard is unreliable for long texts
- menu->addAction(theDebuggerAction(ExecuteCommand));
- menu->addAction(theDebuggerAction(LogTimeStamps));
- menu->addAction(theDebuggerAction(VerboseLog));
+ menu->addAction(debuggerCore()->action(ExecuteCommand));
+ menu->addAction(debuggerCore()->action(LogTimeStamps));
+ menu->addAction(debuggerCore()->action(VerboseLog));
menu->addSeparator();
- menu->addAction(theDebuggerAction(SettingsDialog));
+ menu->addAction(debuggerCore()->action(SettingsDialog));
menu->exec(ev->globalPos());
delete menu;
}
@@ -227,7 +217,7 @@ public:
if (c.unicode() >= 32 && c.unicode() < 128)
cleanCmd.append(c);
if (!cleanCmd.isEmpty()) {
- theDebuggerAction(ExecuteCommand)->trigger(cleanCmd);
+ debuggerCore()->action(ExecuteCommand)->trigger(cleanCmd);
m_history.append(cleanCmd);
}
}
@@ -272,25 +262,9 @@ private:
void Console::saveContents()
{
- while (true) {
- const QString fileName = QFileDialog::getSaveFileName(this, tr("Log File"));
- if (fileName.isEmpty())
- break;
- QFile file(fileName);
- if (file.open(QIODevice::WriteOnly|QIODevice::Text|QIODevice::Truncate)) {
- file.write(toPlainText().toUtf8());
- file.close();
- break;
- } else {
- QMessageBox::warning(this, tr("Write Failure"),
- tr("Unable to write log contents to '%1': %2").
- arg(fileName, file.errorString()));
- }
- }
+ LogWindow::writeLogContents(this, this);
}
-
-
/////////////////////////////////////////////////////////////////////
//
// ConsoleWindow
@@ -319,7 +293,7 @@ ConsoleWindow::ConsoleWindow(QWidget *parent)
//connect(m_console, SIGNAL(statusMessageRequested(QString,int)),
// this, SIGNAL(statusMessageRequested(QString,int)));
-};
+}
void ConsoleWindow::showOutput(int channel, const QString &output)
{
diff --git a/src/plugins/debugger/debugger.pri b/src/plugins/debugger/debugger.pri
index 52045952fd..d2df959e56 100644
--- a/src/plugins/debugger/debugger.pri
+++ b/src/plugins/debugger/debugger.pri
@@ -2,4 +2,4 @@ include(debugger_dependencies.pri)
INCLUDEPATH += $$PWD
DEPENDPATH += $$PWD
-LIBS *= -l$$qtLibraryTarget(Debugger)
+LIBS *= -l$$qtLibraryName(Debugger)
diff --git a/src/plugins/debugger/debugger.pro b/src/plugins/debugger/debugger.pro
index 62035c48e6..0497ed9089 100644
--- a/src/plugins/debugger/debugger.pro
+++ b/src/plugins/debugger/debugger.pro
@@ -18,21 +18,25 @@ QT += gui \
HEADERS += breakhandler.h \
breakpoint.h \
+ breakpointmarker.h \
breakwindow.h \
consolewindow.h \
debugger_global.h \
debuggeractions.h \
- debuggeragents.h \
+ debuggercore.h \
debuggerconstants.h \
debuggerdialogs.h \
debuggerengine.h \
debuggermainwindow.h \
debuggerplugin.h \
debuggerrunner.h \
+ debuggerstreamops.h \
debuggerstringutils.h \
debuggertooltip.h \
- debuggeruiswitcher.h \
+ disassembleragent.h \
+ disassemblerlines.h \
logwindow.h \
+ memoryagent.h \
moduleshandler.h \
moduleswindow.h \
name_demangler.h \
@@ -40,9 +44,9 @@ HEADERS += breakhandler.h \
procinterrupt.h \
registerhandler.h \
registerwindow.h \
- sessionengine.h \
snapshothandler.h \
snapshotwindow.h \
+ sourceagent.h \
sourcefileshandler.h \
sourcefileswindow.h \
stackframe.h \
@@ -52,23 +56,27 @@ HEADERS += breakhandler.h \
watchhandler.h \
watchutils.h \
watchwindow.h \
+ threaddata.h \
threadshandler.h \
watchdelegatewidgets.h
SOURCES += breakhandler.cpp \
breakpoint.cpp \
+ breakpointmarker.cpp \
breakwindow.cpp \
consolewindow.cpp \
debuggeractions.cpp \
- debuggeragents.cpp \
debuggerdialogs.cpp \
debuggerengine.cpp \
debuggermainwindow.cpp \
debuggerplugin.cpp \
debuggerrunner.cpp \
+ debuggerstreamops.cpp \
debuggertooltip.cpp \
- debuggeruiswitcher.cpp \
+ disassembleragent.cpp \
+ disassemblerlines.cpp \
logwindow.cpp \
+ memoryagent.cpp \
moduleshandler.cpp \
moduleswindow.cpp \
name_demangler.cpp \
@@ -76,9 +84,9 @@ SOURCES += breakhandler.cpp \
procinterrupt.cpp \
registerhandler.cpp \
registerwindow.cpp \
- sessionengine.cpp \
snapshothandler.cpp \
snapshotwindow.cpp \
+ sourceagent.cpp \
sourcefileshandler.cpp \
sourcefileswindow.cpp \
stackhandler.cpp \
@@ -100,7 +108,8 @@ FORMS += attachexternaldialog.ui \
dumperoptionpage.ui \
commonoptionspage.ui \
startexternaldialog.ui \
- startremotedialog.ui
+ startremotedialog.ui \
+ startremoteenginedialog.ui
RESOURCES += debugger.qrc
@@ -117,9 +126,11 @@ LIBS *= -lole32 \
-lshell32
}
include(cdb/cdb.pri)
+include(cdb2/cdb2.pri)
include(gdb/gdb.pri)
include(script/script.pri)
include(pdb/pdb.pri)
+include(lldb/lldbhost.pri)
contains(QT_CONFIG, declarative) {
QT += declarative
@@ -128,6 +139,3 @@ contains(QT_CONFIG, declarative) {
include(tcf/tcf.pri)
include(shared/shared.pri)
-
-
-OTHER_FILES += Debugger.pluginspec
diff --git a/src/plugins/debugger/debugger.qrc b/src/plugins/debugger/debugger.qrc
index 7688ef39a4..c5aa9cc39e 100644
--- a/src/plugins/debugger/debugger.qrc
+++ b/src/plugins/debugger/debugger.qrc
@@ -19,6 +19,7 @@
<file>images/debugger_stop.png</file>
<file>images/debugger_stop_small.png</file>
<file>images/watchpoint.png</file>
+ <file>images/tracepoint.png</file>
<file>images/breakpoint_16.png</file>
<file>images/breakpoint_24.png</file>
<file>images/breakpoint_disabled_16.png</file>
diff --git a/src/plugins/debugger/debuggeractions.cpp b/src/plugins/debugger/debuggeractions.cpp
index a747a2d4a9..9ff95c8abd 100644
--- a/src/plugins/debugger/debuggeractions.cpp
+++ b/src/plugins/debugger/debuggeractions.cpp
@@ -45,6 +45,7 @@
#include <QtCore/QDebug>
#include <QtCore/QVariant>
#include <QtCore/QSettings>
+#include <QtCore/QFileInfo>
#include <QtGui/QAction>
#include <QtGui/QAbstractButton>
@@ -55,8 +56,6 @@
using namespace Utils;
static const char debugModeSettingsGroupC[] = "DebugMode";
-static const char gdbBinariesSettingsGroupC[] = "GdbBinaries";
-static const char debugModeGdbBinaryKeyC[] = "GdbBinary";
namespace Debugger {
namespace Internal {
@@ -67,185 +66,59 @@ namespace Internal {
//
//////////////////////////////////////////////////////////////////////////
-DebuggerSettings::DebuggerSettings(QObject *parent)
- : QObject(parent)
-{}
-
-DebuggerSettings::~DebuggerSettings()
-{
- qDeleteAll(m_items);
-}
-
-void DebuggerSettings::insertItem(int code, SavedAction *item)
-{
- QTC_ASSERT(!m_items.contains(code),
- qDebug() << code << item->toString(); return);
- QTC_ASSERT(item->settingsKey().isEmpty() || item->defaultValue().isValid(),
- qDebug() << "NO DEFAULT VALUE FOR " << item->settingsKey());
- m_items[code] = item;
-}
-
-void DebuggerSettings::readSettings(QSettings *settings)
-{
- foreach (SavedAction *item, m_items)
- item->readSettings(settings);
- // Convert gdb binaries from flat settings list (see writeSettings)
- // into map ("binary1=gdb,1,2", "binary2=symbian_gdb,3,4").
- m_gdbBinaryToolChainMap.clear();
- const QChar separator = QLatin1Char(',');
- const QString keyRoot = QLatin1String(gdbBinariesSettingsGroupC) + QLatin1Char('/') +
- QLatin1String(debugModeGdbBinaryKeyC);
- for (int i = 1; ; i++) {
- const QString value = settings->value(keyRoot + QString::number(i)).toString();
- if (value.isEmpty())
- break;
- // Split apart comma-separated binary and its numerical toolchains.
- QStringList tokens = value.split(separator);
- if (tokens.size() < 2)
- break;
- const QString binary = tokens.front();
- tokens.pop_front();
- foreach(const QString &t, tokens) {
- // Paranoia: Check if the there is already a binary configured for the toolchain.
- const int toolChain = t.toInt();
- const QString predefinedGdb = m_gdbBinaryToolChainMap.key(toolChain);
- if (predefinedGdb.isEmpty()) {
- m_gdbBinaryToolChainMap.insert(binary, toolChain);
- } else {
- const QString toolChainName = ProjectExplorer::ToolChain::toolChainName(static_cast<ProjectExplorer::ToolChain::ToolChainType>(toolChain));
- const QString msg =
- QString::fromLatin1("An inconsistency has been encountered in the Ini-file '%1':\n"
- "Skipping gdb binary '%2' for toolchain '%3' as '%4' is already configured for it.").
- arg(settings->fileName(), binary, toolChainName, predefinedGdb);
- qWarning("%s", qPrintable(msg));
- }
- }
- }
- // Linux defaults
-#ifdef Q_OS_UNIX
- if (m_gdbBinaryToolChainMap.isEmpty()) {
- const QString gdb = QLatin1String("gdb");
- m_gdbBinaryToolChainMap.insert(gdb, ProjectExplorer::ToolChain::GCC);
- m_gdbBinaryToolChainMap.insert(gdb, ProjectExplorer::ToolChain::LINUX_ICC);
- m_gdbBinaryToolChainMap.insert(gdb, ProjectExplorer::ToolChain::OTHER);
- m_gdbBinaryToolChainMap.insert(gdb, ProjectExplorer::ToolChain::UNKNOWN);
- }
-#endif
-}
-
-void DebuggerSettings::writeSettings(QSettings *settings) const
-{
- foreach (SavedAction *item, m_items)
- item->writeSettings(settings);
- // Convert gdb binaries map into a flat settings list of
- // ("binary1=gdb,1,2", "binary2=symbian_gdb,3,4"). It needs to be ASCII for installers
- QString lastBinary;
- QStringList settingsList;
- const QChar separator = QLatin1Char(',');
- const GdbBinaryToolChainMap::const_iterator cend = m_gdbBinaryToolChainMap.constEnd();
- for (GdbBinaryToolChainMap::const_iterator it = m_gdbBinaryToolChainMap.constBegin(); it != cend; ++it) {
- if (it.key() != lastBinary) {
- lastBinary = it.key(); // Start new entry with first toolchain
- settingsList.push_back(lastBinary);
- }
- settingsList.back().append(separator); // Append toolchain to last binary
- settingsList.back().append(QString::number(it.value()));
- }
- // Terminate settings list by an empty element such that consecutive keys resulting
- // from ini-file merging are suppressed while reading.
- settingsList.push_back(QString());
- // Write out list
- settings->beginGroup(QLatin1String(gdbBinariesSettingsGroupC));
- settings->remove(QString()); // remove all keys in group.
- const int count = settingsList.size();
- const QString keyRoot = QLatin1String(debugModeGdbBinaryKeyC);
- for (int i = 0; i < count; i++)
- settings->setValue(keyRoot + QString::number(i + 1), settingsList.at(i));
- settings->endGroup();
-}
-
-SavedAction *DebuggerSettings::item(int code) const
+DebuggerSettings::DebuggerSettings(QSettings *settings)
{
- QTC_ASSERT(m_items.value(code, 0), qDebug() << "CODE: " << code; return 0);
- return m_items.value(code, 0);
-}
-
-QString DebuggerSettings::dump() const
-{
- QString out;
- QTextStream ts(&out);
- ts << "Debugger settings: ";
- foreach (SavedAction *item, m_items) {
- QString key = item->settingsKey();
- if (!key.isEmpty()) {
- const QString current = item->value().toString();
- const QString default_ = item->defaultValue().toString();
- ts << '\n' << key << ": " << current
- << " (default: " << default_ << ")";
- if (current != default_)
- ts << " ***";
- }
- }
- return out;
-}
-
-DebuggerSettings *DebuggerSettings::instance()
-{
- static DebuggerSettings *instance = 0;
- if (instance)
- return instance;
-
+ m_settings = settings;
const QString debugModeGroup = QLatin1String(debugModeSettingsGroupC);
- instance = new DebuggerSettings;
SavedAction *item = 0;
- item = new SavedAction(instance);
- instance->insertItem(SettingsDialog, item);
+ item = new SavedAction(this);
+ insertItem(SettingsDialog, item);
item->setText(tr("Debugger Properties..."));
//
// View
//
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setText(tr("Adjust Column Widths to Contents"));
- instance->insertItem(AdjustColumnWidths, item);
+ insertItem(AdjustColumnWidths, item);
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setText(tr("Always Adjust Column Widths to Contents"));
item->setCheckable(true);
- instance->insertItem(AlwaysAdjustColumnWidths, item);
+ insertItem(AlwaysAdjustColumnWidths, item);
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setText(tr("Use Alternating Row Colors"));
item->setSettingsKey(debugModeGroup, QLatin1String("UseAlternatingRowColours"));
item->setCheckable(true);
item->setDefaultValue(false);
- instance->insertItem(UseAlternatingRowColors, item);
+ insertItem(UseAlternatingRowColors, item);
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setText(tr("Show a Message Box When Receiving a Signal"));
item->setSettingsKey(debugModeGroup, QLatin1String("UseMessageBoxForSignals"));
item->setCheckable(true);
item->setDefaultValue(true);
item->setValue(true);
- instance->insertItem(UseMessageBoxForSignals, item);
+ insertItem(UseMessageBoxForSignals, item);
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setText(tr("Log Time Stamps"));
item->setSettingsKey(debugModeGroup, QLatin1String("LogTimeStamps"));
item->setCheckable(true);
item->setDefaultValue(false);
- instance->insertItem(LogTimeStamps, item);
+ insertItem(LogTimeStamps, item);
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setText(tr("Verbose Log"));
item->setSettingsKey(debugModeGroup, QLatin1String("VerboseLog"));
item->setCheckable(true);
item->setDefaultValue(false);
- instance->insertItem(VerboseLog, item);
+ insertItem(VerboseLog, item);
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setText(tr("Operate by Instruction"));
item->setCheckable(true);
item->setDefaultValue(false);
@@ -255,9 +128,9 @@ DebuggerSettings *DebuggerSettings::instance()
"instructions and the source location view also shows the "
"disassembled instructions."));
item->setIconVisibleInMenu(false);
- instance->insertItem(OperateByInstruction, item);
+ insertItem(OperateByInstruction, item);
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setText(tr("Dereference Pointers Automatically"));
item->setCheckable(true);
item->setDefaultValue(true);
@@ -266,69 +139,61 @@ DebuggerSettings *DebuggerSettings::instance()
"automatically dereference pointers. This saves a level in the "
"tree view, but also loses data for the now-missing intermediate "
"level."));
- instance->insertItem(AutoDerefPointers, item);
+ insertItem(AutoDerefPointers, item);
//
// Locals & Watchers
//
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setSettingsKey(debugModeGroup, QLatin1String("ShowStandardNamespace"));
item->setText(tr("Show \"std::\" Namespace in Types"));
item->setCheckable(true);
item->setDefaultValue(true);
item->setValue(true);
- instance->insertItem(ShowStdNamespace, item);
+ insertItem(ShowStdNamespace, item);
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setSettingsKey(debugModeGroup, QLatin1String("ShowQtNamespace"));
item->setText(tr("Show Qt's Namespace in Types"));
item->setCheckable(true);
item->setDefaultValue(true);
item->setValue(true);
- instance->insertItem(ShowQtNamespace, item);
+ insertItem(ShowQtNamespace, item);
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setSettingsKey(debugModeGroup, QLatin1String("SortStructMembers"));
item->setText(tr("Sort Members of Classes and Structs Alphabetically"));
item->setCheckable(true);
item->setDefaultValue(true);
item->setValue(true);
- instance->insertItem(SortStructMembers, item);
+ insertItem(SortStructMembers, item);
//
// DebuggingHelper
//
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setSettingsKey(debugModeGroup, QLatin1String("UseDebuggingHelper"));
item->setText(tr("Use Debugging Helpers"));
item->setCheckable(true);
item->setDefaultValue(true);
item->setValue(true);
- instance->insertItem(UseDebuggingHelpers, item);
+ insertItem(UseDebuggingHelpers, item);
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setSettingsKey(debugModeGroup, QLatin1String("UseCustomDebuggingHelperLocation"));
item->setCheckable(true);
item->setDefaultValue(false);
item->setValue(false);
- instance->insertItem(UseCustomDebuggingHelperLocation, item);
+ insertItem(UseCustomDebuggingHelperLocation, item);
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setSettingsKey(debugModeGroup, QLatin1String("CustomDebuggingHelperLocation"));
item->setCheckable(true);
item->setDefaultValue(QString());
item->setValue(QString());
- instance->insertItem(CustomDebuggingHelperLocation, item);
+ insertItem(CustomDebuggingHelperLocation, item);
- item = new SavedAction(instance);
- item->setSettingsKey(debugModeGroup, QLatin1String("DebugDebuggingHelpers"));
- item->setText(tr("Debug Debugging Helpers"));
- item->setCheckable(true);
- item->setDefaultValue(false);
- item->setValue(false);
- instance->insertItem(DebugDebuggingHelpers, item);
-
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setSettingsKey(debugModeGroup, QLatin1String("UseCodeModel"));
item->setText(tr("Use Code Model"));
item->setToolTip(tr("Selecting this causes the C++ Code Model being asked "
@@ -337,17 +202,17 @@ DebuggerSettings *DebuggerSettings::instance()
item->setCheckable(true);
item->setDefaultValue(true);
item->setValue(true);
- instance->insertItem(UseCodeModel, item);
+ insertItem(UseCodeModel, item);
//
// Breakpoints
//
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setText(tr("Synchronize Breakpoints"));
- instance->insertItem(SynchronizeBreakpoints, item);
+ insertItem(SynchronizeBreakpoints, item);
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setText(tr("Adjust Breakpoint Locations"));
item->setToolTip(tr("Not all source code lines generate "
"executable code. Putting a breakpoint on such a line acts as "
@@ -359,58 +224,58 @@ DebuggerSettings *DebuggerSettings::instance()
item->setDefaultValue(true);
item->setValue(true);
item->setSettingsKey(debugModeGroup, QLatin1String("AdjustBreakpointLocations"));
- instance->insertItem(AdjustBreakpointLocations, item);
+ insertItem(AdjustBreakpointLocations, item);
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setText(tr("Break on \"throw\""));
item->setCheckable(true);
item->setDefaultValue(false);
item->setValue(false);
item->setSettingsKey(debugModeGroup, QLatin1String("BreakOnThrow"));
- instance->insertItem(BreakOnThrow, item);
+ insertItem(BreakOnThrow, item);
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setText(tr("Break on \"catch\""));
item->setCheckable(true);
item->setDefaultValue(false);
item->setValue(false);
item->setSettingsKey(debugModeGroup, QLatin1String("BreakOnCatch"));
- instance->insertItem(BreakOnCatch, item);
+ insertItem(BreakOnCatch, item);
//
// Settings
//
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setSettingsKey(debugModeGroup, QLatin1String("Environment"));
item->setDefaultValue(QString());
- instance->insertItem(GdbEnvironment, item);
+ insertItem(GdbEnvironment, item);
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setSettingsKey(debugModeGroup, QLatin1String("ScriptFile"));
item->setDefaultValue(QString());
- instance->insertItem(GdbScriptFile, item);
+ insertItem(GdbScriptFile, item);
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setSettingsKey(debugModeGroup, QLatin1String("CloseBuffersOnExit"));
item->setCheckable(true);
item->setDefaultValue(false);
- instance->insertItem(CloseBuffersOnExit, item);
+ insertItem(CloseBuffersOnExit, item);
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setSettingsKey(debugModeGroup, QLatin1String("SwitchModeOnExit"));
item->setCheckable(true);
item->setDefaultValue(false);
- instance->insertItem(SwitchModeOnExit, item);
+ insertItem(SwitchModeOnExit, item);
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setSettingsKey(debugModeGroup, QLatin1String("AutoQuit"));
item->setText(tr("Automatically Quit Debugger"));
item->setCheckable(true);
item->setDefaultValue(false);
- instance->insertItem(AutoQuit, item);
+ insertItem(AutoQuit, item);
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setSettingsKey(debugModeGroup, QLatin1String("UseToolTips"));
item->setText(tr("Use tooltips in main editor when debugging"));
item->setToolTip(tr("Checking this will enable tooltips for variable "
@@ -419,52 +284,52 @@ DebuggerSettings *DebuggerSettings::instance()
"information, it is switched off by default."));
item->setCheckable(true);
item->setDefaultValue(false);
- instance->insertItem(UseToolTipsInMainEditor, item);
+ insertItem(UseToolTipsInMainEditor, item);
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setSettingsKey(debugModeGroup, QLatin1String("UseToolTipsInLocalsView"));
item->setText(tr("Use Tooltips in Locals View When Debugging"));
item->setToolTip(tr("Checking this will enable tooltips in the locals "
"view during debugging."));
item->setCheckable(true);
item->setDefaultValue(false);
- instance->insertItem(UseToolTipsInLocalsView, item);
+ insertItem(UseToolTipsInLocalsView, item);
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setSettingsKey(debugModeGroup, QLatin1String("UseToolTipsInBreakpointsView"));
item->setText(tr("Use Tooltips in Breakpoints View When Debugging"));
item->setToolTip(tr("Checking this will enable tooltips in the breakpoints "
"view during debugging."));
item->setCheckable(true);
item->setDefaultValue(false);
- instance->insertItem(UseToolTipsInBreakpointsView, item);
+ insertItem(UseToolTipsInBreakpointsView, item);
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setSettingsKey(debugModeGroup, QLatin1String("UseAddressInBreakpointsView"));
item->setText(tr("Show Address Data in Breakpoints View When Debugging"));
item->setToolTip(tr("Checking this will show a column with address "
"information in the breakpoint view during debugging."));
item->setCheckable(true);
item->setDefaultValue(false);
- instance->insertItem(UseAddressInBreakpointsView, item);
+ insertItem(UseAddressInBreakpointsView, item);
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setSettingsKey(debugModeGroup, QLatin1String("UseAddressInStackView"));
item->setText(tr("Show Address Data in Stack View When Debugging"));
item->setToolTip(tr("Checking this will show a column with address "
"information in the stack view during debugging."));
item->setCheckable(true);
item->setDefaultValue(false);
- instance->insertItem(UseAddressInStackView, item);
- item = new SavedAction(instance);
+ insertItem(UseAddressInStackView, item);
+ item = new SavedAction(this);
item->setSettingsKey(debugModeGroup, QLatin1String("ListSourceFiles"));
item->setText(tr("List Source Files"));
item->setCheckable(true);
item->setDefaultValue(false);
- instance->insertItem(ListSourceFiles, item);
+ insertItem(ListSourceFiles, item);
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setSettingsKey(debugModeGroup, QLatin1String("SkipKnownFrames"));
item->setText(tr("Skip Known Frames"));
item->setToolTip(tr("Selecting this results in well-known but usually "
@@ -472,89 +337,117 @@ DebuggerSettings *DebuggerSettings::instance()
"signal emission being skipped while single-stepping."));
item->setCheckable(true);
item->setDefaultValue(false);
- instance->insertItem(SkipKnownFrames, item);
+ insertItem(SkipKnownFrames, item);
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setSettingsKey(debugModeGroup, QLatin1String("EnableReverseDebugging"));
item->setText(tr("Enable Reverse Debugging"));
item->setCheckable(true);
item->setDefaultValue(false);
- instance->insertItem(EnableReverseDebugging, item);
+ insertItem(EnableReverseDebugging, item);
#ifdef Q_OS_WIN
- item = new RegisterPostMortemAction(instance);
+ item = new RegisterPostMortemAction(this);
item->setSettingsKey(debugModeGroup, QLatin1String("RegisterForPostMortem"));
item->setText(tr("Register For Post-Mortem Debugging"));
item->setCheckable(true);
item->setDefaultValue(false);
- instance->insertItem(RegisterForPostMortem, item);
+ insertItem(RegisterForPostMortem, item);
#endif
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setSettingsKey(debugModeGroup, QLatin1String("AllPluginBreakpoints"));
item->setDefaultValue(true);
- instance->insertItem(AllPluginBreakpoints, item);
+ insertItem(AllPluginBreakpoints, item);
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setSettingsKey(debugModeGroup, QLatin1String("SelectedPluginBreakpoints"));
item->setDefaultValue(false);
- instance->insertItem(SelectedPluginBreakpoints, item);
+ insertItem(SelectedPluginBreakpoints, item);
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setSettingsKey(debugModeGroup, QLatin1String("NoPluginBreakpoints"));
item->setDefaultValue(false);
- instance->insertItem(NoPluginBreakpoints, item);
+ insertItem(NoPluginBreakpoints, item);
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setSettingsKey(debugModeGroup, QLatin1String("SelectedPluginBreakpointsPattern"));
item->setDefaultValue(QLatin1String(".*"));
- instance->insertItem(SelectedPluginBreakpointsPattern, item);
+ insertItem(SelectedPluginBreakpointsPattern, item);
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setSettingsKey(debugModeGroup, QLatin1String("MaximalStackDepth"));
item->setDefaultValue(20);
- instance->insertItem(MaximalStackDepth, item);
+ insertItem(MaximalStackDepth, item);
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setText(tr("Reload Full Stack"));
- instance->insertItem(ExpandStack, item);
+ insertItem(ExpandStack, item);
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setText(tr("Create Full Backtrace"));
- instance->insertItem(CreateFullBacktrace, item);
+ insertItem(CreateFullBacktrace, item);
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setText(tr("Execute Line"));
- instance->insertItem(ExecuteCommand, item);
+ insertItem(ExecuteCommand, item);
- item = new SavedAction(instance);
+ item = new SavedAction(this);
item->setSettingsKey(debugModeGroup, QLatin1String("WatchdogTimeout"));
item->setDefaultValue(20);
- instance->insertItem(GdbWatchdogTimeout, item);
+ insertItem(GdbWatchdogTimeout, item);
+}
- return instance;
+
+DebuggerSettings::~DebuggerSettings()
+{
+ qDeleteAll(m_items);
}
+void DebuggerSettings::insertItem(int code, SavedAction *item)
+{
+ QTC_ASSERT(!m_items.contains(code),
+ qDebug() << code << item->toString(); return);
+ QTC_ASSERT(item->settingsKey().isEmpty() || item->defaultValue().isValid(),
+ qDebug() << "NO DEFAULT VALUE FOR " << item->settingsKey());
+ m_items[code] = item;
+}
-//////////////////////////////////////////////////////////////////////////
-//
-// DebuggerActions
-//
-//////////////////////////////////////////////////////////////////////////
+void DebuggerSettings::readSettings()
+{
+ foreach (SavedAction *item, m_items)
+ item->readSettings(m_settings);
+}
-SavedAction *theDebuggerAction(int code)
+void DebuggerSettings::writeSettings() const
{
- return DebuggerSettings::instance()->item(code);
+ foreach (SavedAction *item, m_items)
+ item->writeSettings(m_settings);
}
-bool theDebuggerBoolSetting(int code)
+SavedAction *DebuggerSettings::item(int code) const
{
- return DebuggerSettings::instance()->item(code)->value().toBool();
+ QTC_ASSERT(m_items.value(code, 0), qDebug() << "CODE: " << code; return 0);
+ return m_items.value(code, 0);
}
-QString theDebuggerStringSetting(int code)
+QString DebuggerSettings::dump() const
{
- return DebuggerSettings::instance()->item(code)->value().toString();
+ QString out;
+ QTextStream ts(&out);
+ ts << "Debugger settings: ";
+ foreach (SavedAction *item, m_items) {
+ QString key = item->settingsKey();
+ if (!key.isEmpty()) {
+ const QString current = item->value().toString();
+ const QString default_ = item->defaultValue().toString();
+ ts << '\n' << key << ": " << current
+ << " (default: " << default_ << ")";
+ if (current != default_)
+ ts << " ***";
+ }
+ }
+ return out;
}
} // namespace Internal
diff --git a/src/plugins/debugger/debuggeractions.h b/src/plugins/debugger/debuggeractions.h
index 85e94270db..ef9cf2212c 100644
--- a/src/plugins/debugger/debuggeractions.h
+++ b/src/plugins/debugger/debuggeractions.h
@@ -38,8 +38,6 @@
#include <QtCore/QMap>
QT_BEGIN_NAMESPACE
-class QAction;
-class QActionGroup;
class QSettings;
QT_END_NAMESPACE
@@ -52,35 +50,24 @@ namespace Internal {
class DebuggerSettings : public QObject
{
- Q_OBJECT
+ Q_OBJECT // For tr().
public:
- typedef QMultiMap<QString, int> GdbBinaryToolChainMap;
-
- explicit DebuggerSettings(QObject *parent = 0);
+ explicit DebuggerSettings(QSettings *setting);
~DebuggerSettings();
- GdbBinaryToolChainMap gdbBinaryToolChainMap() const
- { return m_gdbBinaryToolChainMap; }
- void setGdbBinaryToolChainMap(const GdbBinaryToolChainMap &map)
- { m_gdbBinaryToolChainMap = map; }
-
void insertItem(int code, Utils::SavedAction *item);
Utils::SavedAction *item(int code) const;
QString dump() const;
- static DebuggerSettings *instance();
-
-public slots:
- void readSettings(QSettings *settings);
- void writeSettings(QSettings *settings) const;
+ void readSettings();
+ void writeSettings() const;
private:
QHash<int, Utils::SavedAction *> m_items;
- GdbBinaryToolChainMap m_gdbBinaryToolChainMap;
+ QSettings *m_settings;
};
-
///////////////////////////////////////////////////////////
enum DebuggerActionCode
@@ -102,7 +89,6 @@ enum DebuggerActionCode
UseDebuggingHelpers,
UseCustomDebuggingHelperLocation,
CustomDebuggingHelperLocation,
- DebugDebuggingHelpers,
UseCodeModel,
@@ -150,13 +136,6 @@ enum DebuggerActionCode
BreakOnCatch
};
-// singleton access
-Utils::SavedAction *theDebuggerAction(int code);
-
-// convenience
-bool theDebuggerBoolSetting(int code);
-QString theDebuggerStringSetting(int code);
-
} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/debuggeragents.cpp b/src/plugins/debugger/debuggeragents.cpp
deleted file mode 100644
index 2b3be0695c..0000000000
--- a/src/plugins/debugger/debuggeragents.cpp
+++ /dev/null
@@ -1,430 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#include "debuggeragents.h"
-
-#include "debuggerengine.h"
-#include "debuggerplugin.h"
-#include "debuggerstringutils.h"
-#include "stackframe.h"
-
-#include <coreplugin/coreconstants.h>
-#include <coreplugin/editormanager/editormanager.h>
-#include <coreplugin/editormanager/ieditor.h>
-#include <coreplugin/mimedatabase.h>
-#include <coreplugin/icore.h>
-
-#include <texteditor/basetexteditor.h>
-#include <texteditor/plaintexteditor.h>
-#include <texteditor/basetextmark.h>
-#include <texteditor/itexteditor.h>
-#include <texteditor/texteditorconstants.h>
-#include <texteditor/basetextdocument.h>
-
-#include <utils/qtcassert.h>
-
-#include <QtCore/QDebug>
-#include <QtCore/QMetaObject>
-
-#include <QtGui/QMessageBox>
-#include <QtGui/QPlainTextEdit>
-#include <QtGui/QTextCursor>
-
-#include <limits.h>
-
-using namespace Core;
-
-namespace Debugger {
-namespace Internal {
-
-///////////////////////////////////////////////////////////////////////
-//
-// MemoryViewAgent
-//
-///////////////////////////////////////////////////////////////////////
-
-/*!
- \class MemoryViewAgent
-
- Objects form this class are created in response to user actions in
- the Gui for showing raw memory from the inferior. After creation
- it handles communication between the engine and the bineditor.
-*/
-
-namespace { const int DataRange = 1024 * 1024; }
-
-MemoryViewAgent::MemoryViewAgent(Debugger::DebuggerEngine *engine, quint64 addr)
- : QObject(engine), m_engine(engine)
-{
- QTC_ASSERT(engine, /**/);
- createBinEditor(addr);
-}
-
-MemoryViewAgent::MemoryViewAgent(Debugger::DebuggerEngine *engine, const QString &addr)
- : QObject(engine), m_engine(engine)
-{
- QTC_ASSERT(engine, /**/);
- bool ok = true;
- createBinEditor(addr.toULongLong(&ok, 0));
- //qDebug() << " ADDRESS: " << addr << addr.toUInt(&ok, 0);
-}
-
-MemoryViewAgent::~MemoryViewAgent()
-{
- EditorManager *editorManager = EditorManager::instance();
- QList<IEditor *> editors;
- foreach (QPointer<IEditor> editor, m_editors)
- if (editor)
- editors.append(editor.data());
- editorManager->closeEditors(editors);
-}
-
-void MemoryViewAgent::createBinEditor(quint64 addr)
-{
- EditorManager *editorManager = EditorManager::instance();
- QString titlePattern = tr("Memory $");
- IEditor *editor = editorManager->openEditorWithContents(
- Core::Constants::K_DEFAULT_BINARY_EDITOR_ID,
- &titlePattern);
- if (editor) {
- connect(editor->widget(),
- SIGNAL(lazyDataRequested(Core::IEditor *, quint64,bool)),
- SLOT(fetchLazyData(Core::IEditor *, quint64,bool)));
- connect(editor->widget(),
- SIGNAL(newWindowRequested(quint64)),
- SLOT(createBinEditor(quint64)));
- connect(editor->widget(),
- SIGNAL(newRangeRequested(Core::IEditor *, quint64)),
- SLOT(provideNewRange(Core::IEditor*,quint64)));
- connect(editor->widget(),
- SIGNAL(startOfFileRequested(Core::IEditor *)),
- SLOT(handleStartOfFileRequested(Core::IEditor*)));
- connect(editor->widget(),
- SIGNAL(endOfFileRequested(Core::IEditor *)),
- SLOT(handleEndOfFileRequested(Core::IEditor*)));
- m_editors << editor;
- editorManager->activateEditor(editor);
- QMetaObject::invokeMethod(editor->widget(), "setNewWindowRequestAllowed");
- QMetaObject::invokeMethod(editor->widget(), "setLazyData",
- Q_ARG(quint64, addr), Q_ARG(int, DataRange), Q_ARG(int, BinBlockSize));
- } else {
- DebuggerEngine::showMessageBox(QMessageBox::Warning,
- tr("No memory viewer available"),
- tr("The memory contents cannot be shown as no viewer plugin "
- "for binary data has been loaded."));
- deleteLater();
- }
-}
-
-void MemoryViewAgent::fetchLazyData(IEditor *editor, quint64 block, bool sync)
-{
- Q_UNUSED(sync); // FIXME: needed support for incremental searching
- m_engine->fetchMemory(this, editor, BinBlockSize * block, BinBlockSize);
-}
-
-void MemoryViewAgent::addLazyData(QObject *editorToken, quint64 addr,
- const QByteArray &ba)
-{
- IEditor *editor = qobject_cast<IEditor *>(editorToken);
- if (editor && editor->widget()) {
- Core::EditorManager::instance()->activateEditor(editor);
- QMetaObject::invokeMethod(editor->widget(), "addLazyData",
- Q_ARG(quint64, addr / BinBlockSize), Q_ARG(QByteArray, ba));
- }
-}
-
-void MemoryViewAgent::provideNewRange(IEditor *editor, quint64 address)
-{
- QMetaObject::invokeMethod(editor->widget(), "setLazyData",
- Q_ARG(quint64, address), Q_ARG(int, DataRange),
- Q_ARG(int, BinBlockSize));
-}
-
-// Since we are not dealing with files, we take these signals to mean
-// "move to start/end of range". This seems to make more sense than
-// jumping to the start or end of the address space, respectively.
-void MemoryViewAgent::handleStartOfFileRequested(IEditor *editor)
-{
- QMetaObject::invokeMethod(editor->widget(),
- "setCursorPosition", Q_ARG(int, 0));
-}
-
-void MemoryViewAgent::handleEndOfFileRequested(IEditor *editor)
-{
- QMetaObject::invokeMethod(editor->widget(),
- "setCursorPosition", Q_ARG(int, DataRange - 1));
-}
-
-
-
-///////////////////////////////////////////////////////////////////////
-//
-// DisassemblerViewAgent
-//
-///////////////////////////////////////////////////////////////////////
-
-// Used for the disassembler view
-class LocationMark2 : public TextEditor::ITextMark
-{
-public:
- LocationMark2() {}
-
- QIcon icon() const { return DebuggerPlugin::instance()->locationMarkIcon(); }
- void updateLineNumber(int /*lineNumber*/) {}
- void updateBlock(const QTextBlock & /*block*/) {}
- void removedFromEditor() {}
- void documentClosing() {}
-};
-
-struct DisassemblerViewAgentPrivate
-{
- DisassemblerViewAgentPrivate();
- void configureMimeType();
-
- QPointer<TextEditor::ITextEditor> editor;
- StackFrame frame;
- bool tryMixed;
- QPointer<DebuggerEngine> engine;
- LocationMark2 *locationMark;
- QHash<QString, QString> cache;
- QString mimeType;
-};
-
-DisassemblerViewAgentPrivate::DisassemblerViewAgentPrivate() :
- editor(0),
- tryMixed(true),
- locationMark(new LocationMark2),
- mimeType(_("text/x-qtcreator-generic-asm"))
-{
-}
-
-/*!
- \class DisassemblerViewAgent
-
- Objects from this class are created in response to user actions in
- the Gui for showing disassembled memory from the inferior. After creation
- it handles communication between the engine and the editor.
-*/
-
-DisassemblerViewAgent::DisassemblerViewAgent(DebuggerEngine *engine)
- : QObject(0), d(new DisassemblerViewAgentPrivate)
-{
- d->engine = engine;
-}
-
-DisassemblerViewAgent::~DisassemblerViewAgent()
-{
- EditorManager *editorManager = EditorManager::instance();
- if (d->editor)
- editorManager->closeEditors(QList<IEditor *>() << d->editor);
- d->editor = 0;
- delete d->locationMark;
- d->locationMark = 0;
- delete d;
- d = 0;
-}
-
-void DisassemblerViewAgent::cleanup()
-{
- d->cache.clear();
-}
-
-void DisassemblerViewAgent::resetLocation()
-{
- if (d->editor)
- d->editor->markableInterface()->removeMark(d->locationMark);
-}
-
-QString frameKey(const StackFrame &frame)
-{
- return _("%1:%2:%3").arg(frame.function).arg(frame.file).arg(frame.from);
-}
-
-const StackFrame &DisassemblerViewAgent::frame() const
-{
- return d->frame;
-}
-
-bool DisassemblerViewAgent::isMixed() const
-{
- return d->tryMixed
- && d->frame.line > 0
- && !d->frame.function.isEmpty()
- && d->frame.function != _("??");
-}
-
-void DisassemblerViewAgent::setFrame(const StackFrame &frame, bool tryMixed)
-{
- d->frame = frame;
- d->tryMixed = tryMixed;
- if (isMixed()) {
- QHash<QString, QString>::ConstIterator it = d->cache.find(frameKey(frame));
- if (it != d->cache.end()) {
- QString msg = _("Use cache disassembler for '%1' in '%2'")
- .arg(frame.function).arg(frame.file);
- d->engine->showMessage(msg);
- setContents(*it);
- return;
- }
- }
- d->engine->fetchDisassembler(this);
-}
-
-void DisassemblerViewAgentPrivate::configureMimeType()
-{
- QTC_ASSERT(editor, return);
-
- TextEditor::BaseTextDocument *doc = qobject_cast<TextEditor::BaseTextDocument *>(editor->file());
- QTC_ASSERT(doc, return);
- doc->setMimeType(mimeType);
-
- TextEditor::PlainTextEditor *pe = qobject_cast<TextEditor::PlainTextEditor *>(editor->widget());
- QTC_ASSERT(pe, return);
-
- if (const MimeType mtype = ICore::instance()->mimeDatabase()->findByType(mimeType)) {
- pe->configure(mtype);
- } else {
- qWarning("Assembler mimetype '%s' not found.", qPrintable(mimeType));
- }
-}
-
-QString DisassemblerViewAgent::mimeType() const
-{
- return d->mimeType;
-}
-
-void DisassemblerViewAgent::setMimeType(const QString &mt)
-{
- if (mt == d->mimeType)
- return;
- d->mimeType = mt;
- if (d->editor)
- d->configureMimeType();
-}
-
-// Return a pair of <linenumber [1..n], character position> of an address
-// in assembly code, assuming lines start with a sane hex address.
-static QPair<int, int> lineNumberOfAddress(const QString &disassembly, quint64 address)
-{
- if (disassembly.isEmpty())
- return QPair<int, int>(-1, -1);
-
- int pos = 0;
- const QChar newLine = QLatin1Char('\n');
-
- const int size = disassembly.size();
- for (int lineNumber = 1; pos < size; lineNumber++) {
- int endOfLinePos = disassembly.indexOf(newLine, pos + 1);
- if (endOfLinePos == -1)
- endOfLinePos = size;
- const QString line = disassembly.mid(pos, endOfLinePos - pos);
- if (DisassemblerViewAgent::addressFromDisassemblyLine(line) == address)
- return QPair<int, int>(lineNumber, pos);
- pos = endOfLinePos + 1;
- }
- return QPair<int, int>(-1, -1);;
-}
-
-void DisassemblerViewAgent::setContents(const QString &contents)
-{
- QTC_ASSERT(d, return);
- using namespace Core;
- using namespace TextEditor;
-
- d->cache.insert(frameKey(d->frame), contents);
- QPlainTextEdit *plainTextEdit = 0;
- EditorManager *editorManager = EditorManager::instance();
- if (!d->editor) {
- QString titlePattern = "Disassembler";
- d->editor = qobject_cast<ITextEditor *>(
- editorManager->openEditorWithContents(
- Core::Constants::K_DEFAULT_TEXT_EDITOR_ID,
- &titlePattern));
- QTC_ASSERT(d->editor, return);
- d->editor->setProperty("OpenedByDebugger", true);
- d->editor->setProperty("DisassemblerView", true);
- d->configureMimeType();
- }
-
- editorManager->activateEditor(d->editor);
-
- plainTextEdit = qobject_cast<QPlainTextEdit *>(d->editor->widget());
- if (plainTextEdit) {
- plainTextEdit->setPlainText(contents);
- plainTextEdit->setReadOnly(true);
- }
-
- d->editor->markableInterface()->removeMark(d->locationMark);
- d->editor->setDisplayName(_("Disassembler (%1)").arg(d->frame.function));
-
- const QPair<int, int> lineNumberPos = lineNumberOfAddress(contents, d->frame.address);
- if (lineNumberPos.first > 0) {
- d->editor->markableInterface()->addMark(d->locationMark, lineNumberPos.first);
- if (plainTextEdit) {
- QTextCursor tc = plainTextEdit->textCursor();
- tc.setPosition(lineNumberPos.second);
- plainTextEdit->setTextCursor(tc);
- }
- }
-}
-
-bool DisassemblerViewAgent::contentsCoversAddress(const QString &contents) const
-{
- QTC_ASSERT(d, return false);
-
- return lineNumberOfAddress(contents, d->frame.address).first > 0;
-}
-
-quint64 DisassemblerViewAgent::address() const
-{
- return d->frame.address;
-}
-
-// Return address of an assembly line "0x0dfd bla"
-quint64 DisassemblerViewAgent::addressFromDisassemblyLine(const QString &line)
-{
- // Mac gdb has an overflow reporting 64bit addresses causing the instruction
- // to follow the last digit "0x000000013fff4810mov 1,1". Truncate here.
- const int pos = qMin(line.indexOf(QLatin1Char(' ')), 19);
- if (pos < 0)
- return 0;
- QString addressS = line.left(pos);
- if (addressS.startsWith(QLatin1String("0x")))
- addressS.remove(0, 2);
- bool ok;
- const quint64 address = addressS.toULongLong(&ok, 16);
- return ok ? address : quint64(0);
-}
-
-} // namespace Internal
-} // namespace Debugger
diff --git a/src/plugins/debugger/debuggeragents.h b/src/plugins/debugger/debuggeragents.h
deleted file mode 100644
index ace907c63a..0000000000
--- a/src/plugins/debugger/debuggeragents.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#ifndef DEBUGGER_AGENTS_H
-#define DEBUGGER_AGENTS_H
-
-#include <QtCore/QObject>
-#include <QtCore/QPointer>
-
-namespace Core {
-class IEditor;
-}
-
-namespace Debugger {
-
-class DebuggerEngine;
-
-namespace Internal {
-
-class StackFrame;
-
-class MemoryViewAgent : public QObject
-{
- Q_OBJECT
-
-public:
- // Called from Gui
- explicit MemoryViewAgent(Debugger::DebuggerEngine *engine, quint64 startaddr);
- explicit MemoryViewAgent(Debugger::DebuggerEngine *engine, const QString &startaddr);
- ~MemoryViewAgent();
-
- enum { BinBlockSize = 1024 };
-
-public slots:
- // Called from Engine
- void addLazyData(QObject *editorToken, quint64 addr, const QByteArray &data);
-
-private:
- Q_SLOT void createBinEditor(quint64 startAddr);
- Q_SLOT void fetchLazyData(Core::IEditor *, quint64 block, bool sync);
- Q_SLOT void provideNewRange(Core::IEditor *editor, quint64 address);
- Q_SLOT void handleStartOfFileRequested(Core::IEditor *editor);
- Q_SLOT void handleEndOfFileRequested(Core::IEditor *editor);
-
- QList<QPointer<Core::IEditor> > m_editors;
- QPointer<Debugger::DebuggerEngine> m_engine;
-};
-
-struct DisassemblerViewAgentPrivate;
-
-class DisassemblerViewAgent : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(QString mimeType READ mimeType WRITE setMimeType)
-public:
- // Called from Gui
- explicit DisassemblerViewAgent(Debugger::DebuggerEngine *engine);
- ~DisassemblerViewAgent();
-
- void setFrame(const StackFrame &frame, bool tryMixed = true);
- const StackFrame &frame() const;
- void resetLocation();
- Q_SLOT void setContents(const QString &contents);
-
- // Mimetype: "text/a-asm" or some specialized architecture
- QString mimeType() const;
- Q_SLOT void setMimeType(const QString &mt);
-
- quint64 address() const;
- bool contentsCoversAddress(const QString &contents) const;
- void cleanup();
- bool isMixed() const;
-
- // Return address of an assembly line "0x0dfd bla"
- static quint64 addressFromDisassemblyLine(const QString &line);
-
-private:
- DisassemblerViewAgentPrivate *d;
-};
-
-
-} // namespace Internal
-} // namespace Debugger
-
-#endif // DEBUGGER_WATCHWINDOW_H
diff --git a/src/plugins/debugger/debuggerconstants.h b/src/plugins/debugger/debuggerconstants.h
index 1260f181b4..06f6abec25 100644
--- a/src/plugins/debugger/debuggerconstants.h
+++ b/src/plugins/debugger/debuggerconstants.h
@@ -51,7 +51,7 @@ const char * const STEPOUT = "Debugger.StepOut";
const char * const NEXT = "Debugger.NextLine";
const char * const REVERSE = "Debugger.ReverseDirection";
-const char * const M_DEBUG_VIEWS = "Debugger.Menu.View.Debug";
+const char * const M_DEBUG_VIEWS = "Debugger.Menu.View.Debug";
const char * const C_DEBUGMODE = "Debugger.DebugMode";
const char * const C_CPPDEBUGGER = "Gdb Debugger";
@@ -67,30 +67,38 @@ const char * const DEBUGGER_COMMON_SETTINGS_CATEGORY_ICON =
":/core/images/category_debug.png";
// dock widget names
-const char * const DOCKWIDGET_BREAK = "Debugger.Docks.Break";
-const char * const DOCKWIDGET_CONSOLE = "Debugger.Docks.Console";
-const char * const DOCKWIDGET_MODULES = "Debugger.Docks.Modules";
-const char * const DOCKWIDGET_REGISTER = "Debugger.Docks.Register";
-const char * const DOCKWIDGET_OUTPUT = "Debugger.Docks.Output";
-const char * const DOCKWIDGET_SNAPSHOTS = "Debugger.Docks.Snapshots";
-const char * const DOCKWIDGET_STACK = "Debugger.Docks.Stack";
+const char * const DOCKWIDGET_BREAK = "Debugger.Docks.Break";
+const char * const DOCKWIDGET_CONSOLE = "Debugger.Docks.Console";
+const char * const DOCKWIDGET_MODULES = "Debugger.Docks.Modules";
+const char * const DOCKWIDGET_REGISTER = "Debugger.Docks.Register";
+const char * const DOCKWIDGET_OUTPUT = "Debugger.Docks.Output";
+const char * const DOCKWIDGET_SNAPSHOTS = "Debugger.Docks.Snapshots";
+const char * const DOCKWIDGET_STACK = "Debugger.Docks.Stack";
const char * const DOCKWIDGET_SOURCE_FILES = "Debugger.Docks.SourceFiles";
-const char * const DOCKWIDGET_THREADS = "Debugger.Docks.Threads";
-const char * const DOCKWIDGET_WATCHERS = "Debugger.Docks.LocalsAndWatchers";
+const char * const DOCKWIDGET_THREADS = "Debugger.Docks.Threads";
+const char * const DOCKWIDGET_WATCHERS = "Debugger.Docks.LocalsAndWatchers";
const char * const DOCKWIDGET_QML_INSPECTOR = "Debugger.Docks.QmlInspector";
const char * const DOCKWIDGET_QML_SCRIPTCONSOLE = "Debugger.Docks.ScriptConsole";
+const char * const DOCKWIDGET_DEFAULT_AREA = "Debugger.Docks.DefaultArea";
namespace Internal {
enum { debug = 0 };
+} // namespace Internal
+
+const char * const OPENED_BY_DEBUGGER = "OpenedByDebugger";
+const char * const OPENED_WITH_DISASSEMBLY = "DisassemblerView";
+const char * const OPENED_WITH_MEMORY = "MemoryView";
+
+const char * const DEBUGMODE = "Debugger.DebugMode";
+const char * const DEBUG = "Debugger.Debug";
+const int P_ACTION_DEBUG = 90; //priority for the modemanager
#ifdef Q_OS_MAC
- const char * const LD_PRELOAD_ENV_VAR = "DYLD_INSERT_LIBRARIES";
+const char * const DEBUG_KEY = "Ctrl+Y";
#else
- const char * const LD_PRELOAD_ENV_VAR = "LD_PRELOAD";
+const char * const DEBUG_KEY = "F5";
#endif
-} // namespace Internal
-
} // namespace Constants
@@ -138,7 +146,8 @@ enum DebuggerStartMode
AttachTcf, // Attach to a running Target Communication Framework agent
AttachCore, // Attach to a core file
AttachToRemote, // Start and attach to a remote process
- StartRemoteGdb // Start gdb itself remotely
+ StartRemoteGdb, // Start gdb itself remotely
+ StartRemoteEngine // Start ipc guest engine on other machine
};
enum DebuggerCapabilities
@@ -156,7 +165,8 @@ enum DebuggerCapabilities
ReturnFromFunctionCapability = 0x400,
CreateFullBacktraceCapability = 0x800,
AddWatcherCapability = 0x1000,
- WatchpointCapability = 0x2000
+ WatchpointCapability = 0x2000,
+ ShowModuleSymbolsCapability = 0x4000
};
enum LogChannel
@@ -185,44 +195,6 @@ enum ModelRoles
EngineCapabilitiesRole,
EngineActionsEnabledRole,
RequestActivationRole,
-
- // Running
- RequestExecContinueRole,
- RequestExecInterruptRole,
- RequestExecResetRole,
- RequestExecStepRole,
- RequestExecStepOutRole,
- RequestExecNextRole,
- RequestExecRunToLineRole,
- RequestExecRunToFunctionRole,
- RequestExecReturnFromFunctionRole,
- RequestExecJumpToLineRole,
- RequestExecWatchRole,
- RequestExecSnapshotRole,
- RequestExecFrameDownRole,
- RequestExecFrameUpRole,
- RequestExecDetachRole,
- RequestExecExitRole,
- RequestOperatedByInstructionTriggeredRole,
- RequestExecuteCommandRole,
-
- // Breakpoints
- BreakpointRole,
- BreakpointEnabledRole,
- BreakpointUseFullPathRole,
- BreakpointFunctionNameRole,
- BreakpointFileNameRole,
- BreakpointConditionRole,
- BreakpointIgnoreCountRole,
- BreakpointThreadSpecRole,
- RequestActivateBreakpointRole,
- RequestRemoveBreakpointByIndexRole,
- RequestSynchronizeBreakpointsRole,
- RequestBreakByFunctionRole,
- RequestBreakByFunctionMainRole,
- RequestBreakpointRole,
- RequestToggleBreakpointRole,
- RequestToggleBreakpointEnabledRole,
RequestContextMenuRole,
// Locals and Watchers
@@ -239,48 +211,9 @@ enum ModelRoles
LocalsPointerValueRole, // Pointer value (address) as quint64
LocalsIsWatchpointAtAddressRole,
LocalsIsWatchpointAtPointerValueRole,
- RequestShowInEditorRole,
- RequestWatchPointRole,
- RequestToggleWatchRole,
- RequestToolTipByExpressionRole,
- RequestClearCppCodeModelSnapshotRole,
- RequestWatchExpressionRole,
- RequestRemoveWatchExpressionRole,
-
- // Stack
- StackFrameAddressRole,
- RequestActivateFrameRole,
- RequestReloadFullStackRole,
- RequestShowMemoryRole,
- RequestShowDisassemblerRole,
-
- // Threads
- CurrentThreadIdRole,
- RequestSelectThreadRole,
-
- // Modules
- RequestReloadModulesRole,
- RequestExamineModulesRole,
- RequestModuleSymbolsRole,
- RequestAllSymbolsRole,
- RequestOpenFileRole,
-
- // Registers
- RegisterNumberBaseRole, // Currently used number base
- RegisterAddressRole, // Start value for opening memory view
- RegisterChangedRole, // Used for painting changed values
- RegisterBigNumberRole, // Register is a big integer that cannot be handled as quint64.
- RequestSetRegisterRole,
- RequestReloadRegistersRole,
// Snapshots
- SnapshotCapabilityRole,
- RequestCreateSnapshotRole,
- RequestActivateSnapshotRole,
- RequestRemoveSnapshotRole,
-
- // Sources
- RequestReloadSourceFilesRole,
+ SnapshotCapabilityRole
};
enum DebuggerEngineType
@@ -292,7 +225,8 @@ enum DebuggerEngineType
PdbEngineType = 0x08,
TcfEngineType = 0x10,
QmlEngineType = 0x20,
- QmlCppEngineType = 0x40,
+ QmlCppEngineType = 0x40,
+ LldbEngineType = 0x80,
AllEngineTypes = GdbEngineType
| ScriptEngineType
| CdbEngineType
@@ -300,6 +234,7 @@ enum DebuggerEngineType
| TcfEngineType
| QmlEngineType
| QmlCppEngineType
+ | LldbEngineType
};
enum DebuggerLanguage
diff --git a/src/plugins/debugger/debuggercore.h b/src/plugins/debugger/debuggercore.h
new file mode 100644
index 0000000000..5f5470edfd
--- /dev/null
+++ b/src/plugins/debugger/debuggercore.h
@@ -0,0 +1,127 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 DEBUGGERCORE_H
+#define DEBUGGERCORE_H
+
+#include "debugger_global.h"
+#include "debuggerconstants.h"
+
+#include <QtCore/QObject>
+#include <QtCore/QMultiMap>
+#include <QtCore/QVector>
+
+QT_BEGIN_NAMESPACE
+class QIcon;
+class QMessageBox;
+class QWidget;
+QT_END_NAMESPACE
+
+namespace CPlusPlus {
+class Snapshot;
+}
+
+namespace Utils {
+class SavedAction;
+}
+
+namespace Debugger {
+
+class DebuggerEngine;
+class DebuggerStartParameters;
+
+namespace Internal {
+
+class BreakHandler;
+class SnapshotHandler;
+class Symbol;
+
+// This is the "internal" interface of the debugger plugin that's
+// used by debugger views and debugger engines. The interface is
+// implemented in DebuggerPluginPrivate.
+
+class DebuggerCore : public QObject
+{
+ Q_OBJECT
+
+public:
+ DebuggerCore() {}
+
+ virtual QVariant sessionValue(const QString &name) = 0;
+ virtual void setSessionValue(const QString &name, const QVariant &value) = 0;
+ virtual QVariant configValue(const QString &name) const = 0;
+ virtual void setConfigValue(const QString &name, const QVariant &value) = 0;
+ virtual void updateState(DebuggerEngine *engine) = 0;
+ virtual void updateWatchersWindow() = 0;
+ virtual void showQtDumperLibraryWarning(const QString &details) = 0;
+ virtual QIcon locationMarkIcon() const = 0;
+ virtual const CPlusPlus::Snapshot &cppCodeModelSnapshot() const = 0;
+ virtual bool hasSnapshots() const = 0;
+ virtual void openTextEditor(const QString &titlePattern, const QString &contents) = 0;
+ virtual BreakHandler *breakHandler() const = 0;
+ virtual SnapshotHandler *snapshotHandler() const = 0;
+ virtual DebuggerEngine *currentEngine() const = 0;
+ virtual bool isActiveDebugLanguage(int language) const = 0;
+
+ virtual void clearCppCodeModelSnapshot() = 0;
+
+ // void runTest(const QString &fileName);
+ virtual void showMessage(const QString &msg, int channel, int timeout = -1) = 0;
+
+ virtual bool isReverseDebugging() const = 0;
+ virtual void runControlStarted(DebuggerEngine *engine) = 0;
+ virtual void runControlFinished(DebuggerEngine *engine) = 0;
+ virtual void displayDebugger(DebuggerEngine *engine, bool updateEngine) = 0;
+ virtual DebuggerLanguages activeLanguages() const = 0;
+ virtual void synchronizeBreakpoints() = 0;
+
+ virtual bool initialize(const QStringList &arguments, QString *errorMessage) = 0;
+ virtual QWidget *mainWindow() const = 0;
+ virtual bool isDockVisible(const QString &objectName) const = 0;
+ virtual QString gdbBinaryForToolChain(int toolChain) const = 0;
+ virtual void showModuleSymbols(const QString &moduleName,
+ const QVector<Symbol> &symbols) = 0;
+ virtual void openMemoryEditor() = 0;
+ virtual void languagesChanged() = 0;
+
+ virtual Utils::SavedAction *action(int code) const = 0;
+ virtual bool boolSetting(int code) const = 0;
+ virtual QString stringSetting(int code) const = 0;
+};
+
+// This is the only way to access the global object.
+DebuggerCore *debuggerCore();
+inline BreakHandler *breakHandler() { return debuggerCore()->breakHandler(); }
+QMessageBox *showMessageBox(int icon, const QString &title,
+ const QString &text, int buttons = 0);
+
+} // namespace Internal
+} // namespace Debugger
+
+#endif // DEBUGGERPLUGIN_H
diff --git a/src/plugins/debugger/debuggerdialogs.cpp b/src/plugins/debugger/debuggerdialogs.cpp
index db7a04ade5..d0c86b9f91 100644
--- a/src/plugins/debugger/debuggerdialogs.cpp
+++ b/src/plugins/debugger/debuggerdialogs.cpp
@@ -33,12 +33,14 @@
#include "debuggerdialogs.h"
#include "debuggerconstants.h"
+#include "cdb2/cdbengine2.h"
#include "ui_attachcoredialog.h"
#include "ui_attachexternaldialog.h"
#include "ui_attachtcfdialog.h"
#include "ui_startexternaldialog.h"
#include "ui_startremotedialog.h"
+#include "ui_startremoteenginedialog.h"
#ifdef Q_OS_WIN
# include "shared/dbgwinutils.h"
@@ -47,9 +49,11 @@
#include <coreplugin/icore.h>
#include <utils/synchronousprocess.h>
#include <utils/historycompleter.h>
+#include <utils/qtcassert.h>
#include <QtCore/QDebug>
#include <QtCore/QProcess>
+#include <QtCore/QRegExp>
#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QCoreApplication>
@@ -60,6 +64,7 @@
#include <QtGui/QProxyModel>
#include <QtGui/QSortFilterProxyModel>
#include <QtGui/QMessageBox>
+#include <QtGui/QGroupBox>
using namespace Utils;
@@ -690,6 +695,27 @@ QString StartRemoteDialog::remoteArchitecture() const
return m_ui->architectureComboBox->currentText();
}
+QString StartRemoteDialog::gnuTarget() const
+{
+ return m_ui->gnuTargetComboBox->currentText();
+}
+
+void StartRemoteDialog::setGnuTargets(const QStringList &gnuTargets)
+{
+ m_ui->gnuTargetComboBox->clear();
+ if (!gnuTargets.isEmpty()) {
+ m_ui->gnuTargetComboBox->insertItems(0, gnuTargets);
+ m_ui->gnuTargetComboBox->setCurrentIndex(0);
+ }
+}
+
+void StartRemoteDialog::setGnuTarget(const QString &gnuTarget)
+{
+ const int index = m_ui->gnuTargetComboBox->findText(gnuTarget);
+ if (index != -1)
+ m_ui->gnuTargetComboBox->setCurrentIndex(index);
+}
+
void StartRemoteDialog::setServerStartScript(const QString &scriptName)
{
m_ui->serverStartScript->setPath(scriptName);
@@ -727,6 +753,97 @@ void StartRemoteDialog::updateState()
m_ui->serverStartScript->setEnabled(enabled);
}
+// --------- StartRemoteCdbDialog
+static inline QString cdbRemoteHelp()
+{
+ const char *cdbConnectionSyntax =
+ "Server:Port<br>"
+ "tcp:server=Server,port=Port[,password=Password][,ipversion=6]\n"
+ "tcp:clicon=Server,port=Port[,password=Password][,ipversion=6]\n"
+ "npipe:server=Server,pipe=PipeName[,password=Password]\n"
+ "com:port=COMPort,baud=BaudRate,channel=COMChannel[,password=Password]\n"
+ "spipe:proto=Protocol,{certuser=Cert|machuser=Cert},server=Server,pipe=PipeName[,password=Password]\n"
+ "ssl:proto=Protocol,{certuser=Cert|machuser=Cert},server=Server,port=Socket[,password=Password]\n"
+ "ssl:proto=Protocol,{certuser=Cert|machuser=Cert},clicon=Server,port=Socket[,password=Password]";
+
+ const QString ext32 = QDir::toNativeSeparators(Debugger::Cdb::CdbEngine::extensionLibraryName(false));
+ const QString ext64 = QDir::toNativeSeparators(Debugger::Cdb::CdbEngine::extensionLibraryName(true));
+ return StartRemoteCdbDialog::tr(
+ "<html><body><p>The remote CDB needs to load the matching Qt Creator CDB extension "
+ "(<code>%1</code> or <code>%2</code>, respectively).</p><p>Copy it onto the remote machine and set the "
+ "environment variable <code>%3</code> to point to its folder.</p><p>"
+ "Launch the remote CDB as <code>%4 &lt;executable&gt;</code> "
+ " to use TCP/IP as communication protocol.</p><p>Enter the connection parameters as:</p>"
+ "<pre>%5</pre></body></html>").
+ arg(ext32, ext64, QLatin1String("_NT_DEBUGGER_EXTENSION_PATH"),
+ QLatin1String("cdb.exe -server tcp:port=1234"),
+ QLatin1String(cdbConnectionSyntax));
+}
+
+StartRemoteCdbDialog::StartRemoteCdbDialog(QWidget *parent) :
+ QDialog(parent), m_okButton(0), m_lineEdit(new QLineEdit)
+{
+ setWindowTitle(tr("Start a CDB Remote Session"));
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+
+ QGroupBox *groupBox = new QGroupBox;
+ QFormLayout *formLayout = new QFormLayout;
+ QLabel *helpLabel = new QLabel(cdbRemoteHelp());
+ helpLabel->setWordWrap(true);
+ helpLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
+ formLayout->addRow(helpLabel);
+ QLabel *label = new QLabel(tr("&Connection:"));
+ label->setBuddy(m_lineEdit);
+ m_lineEdit->setMinimumWidth(400);
+ connect(m_lineEdit, SIGNAL(textChanged(QString)), this, SLOT(textChanged(QString)));
+ formLayout->addRow(label, m_lineEdit);
+ groupBox->setLayout(formLayout);
+
+ QVBoxLayout *vLayout = new QVBoxLayout;
+ vLayout->addWidget(groupBox);
+ QDialogButtonBox *box = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
+ vLayout->addWidget(box);
+ m_okButton = box->button(QDialogButtonBox::Ok);
+ connect(m_lineEdit, SIGNAL(returnPressed()), m_okButton, SLOT(animateClick()));
+ m_okButton->setEnabled(false);
+ connect(box, SIGNAL(accepted()), this, SLOT(accept()));
+ connect(box, SIGNAL(rejected()), this, SLOT(reject()));
+
+ setLayout(vLayout);
+}
+
+void StartRemoteCdbDialog::accept()
+{
+ if (!m_lineEdit->text().isEmpty())
+ QDialog::accept();
+}
+
+StartRemoteCdbDialog::~StartRemoteCdbDialog()
+{
+}
+
+void StartRemoteCdbDialog::textChanged(const QString &t)
+{
+ m_okButton->setEnabled(!t.isEmpty());
+}
+
+QString StartRemoteCdbDialog::connection() const
+{
+ const QString rc = m_lineEdit->text();
+ // Transform an IP:POrt ('localhost:1234') specification into full spec
+ QRegExp ipRegexp(QLatin1String("([\\w\\.\\-_]+):([0-9]{1,4})"));
+ QTC_ASSERT(ipRegexp.isValid(), return QString());
+ if (ipRegexp.exactMatch(rc))
+ return QString::fromAscii("tcp:server=%1,port=%2").arg(ipRegexp.cap(1), ipRegexp.cap(2));
+ return rc;
+}
+
+void StartRemoteCdbDialog::setConnection(const QString &c)
+{
+ m_lineEdit->setText(c);
+ m_okButton->setEnabled(!c.isEmpty());
+}
+
AddressDialog::AddressDialog(QWidget *parent) :
QDialog(parent),
m_lineEdit(new QLineEdit),
@@ -784,5 +901,54 @@ bool AddressDialog::isValid() const
return ok;
}
+///////////////////////////////////////////////////////////////////////
+//
+// StartRemoteEngineDialog
+//
+///////////////////////////////////////////////////////////////////////
+
+StartRemoteEngineDialog::StartRemoteEngineDialog(QWidget *parent) :
+ QDialog(parent) ,
+ m_ui(new Ui::StartRemoteEngineDialog)
+{
+ m_ui->setupUi(this);
+ m_ui->host->setCompleter(new HistoryCompleter(m_ui->host));
+ m_ui->username->setCompleter(new HistoryCompleter(m_ui->username));
+ m_ui->enginepath->setCompleter(new HistoryCompleter(m_ui->enginepath));
+ m_ui->inferiorpath->setCompleter(new HistoryCompleter(m_ui->inferiorpath));
+ connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
+ connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
+}
+
+StartRemoteEngineDialog::~StartRemoteEngineDialog()
+{
+}
+
+QString StartRemoteEngineDialog::host() const
+{
+ return m_ui->host->text();
+}
+
+QString StartRemoteEngineDialog::username() const
+{
+ return m_ui->username->text();
+}
+
+QString StartRemoteEngineDialog::password() const
+{
+ return m_ui->password->text();
+}
+
+QString StartRemoteEngineDialog::inferiorPath() const
+{
+ return m_ui->inferiorpath->text();
+}
+
+QString StartRemoteEngineDialog::enginePath() const
+{
+ return m_ui->enginepath->text();
+}
+
+
} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/debuggerdialogs.h b/src/plugins/debugger/debuggerdialogs.h
index 4267b30ede..41fb82b5f4 100644
--- a/src/plugins/debugger/debuggerdialogs.h
+++ b/src/plugins/debugger/debuggerdialogs.h
@@ -49,6 +49,7 @@ class AttachExternalDialog;
class AttachTcfDialog;
class StartExternalDialog;
class StartRemoteDialog;
+class StartRemoteEngineDialog;
} // namespace Ui
QT_END_NAMESPACE
@@ -182,6 +183,10 @@ public:
void setRemoteArchitecture(const QString &arch);
void setRemoteArchitectures(const QStringList &arches);
+ QString gnuTarget() const;
+ void setGnuTarget(const QString &gnuTarget);
+ void setGnuTargets(const QStringList &gnuTargets);
+
bool useServerStartScript() const;
void setUseServerStartScript(bool on);
QString serverStartScript() const;
@@ -200,6 +205,27 @@ private:
Ui::StartRemoteDialog *m_ui;
};
+class StartRemoteCdbDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit StartRemoteCdbDialog(QWidget *parent);
+ ~StartRemoteCdbDialog();
+
+ QString connection() const;
+ void setConnection(const QString &);
+
+ virtual void accept();
+
+private slots:
+ void textChanged(const QString &);
+
+private:
+ QPushButton *m_okButton;
+ QLineEdit *m_lineEdit;
+};
+
class AddressDialog : public QDialog {
Q_OBJECT
public:
@@ -221,6 +247,23 @@ private:
QDialogButtonBox *m_box;
};
+class StartRemoteEngineDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit StartRemoteEngineDialog(QWidget *parent);
+ ~StartRemoteEngineDialog();
+ QString username() const;
+ QString host() const;
+ QString password() const;
+ QString enginePath() const;
+ QString inferiorPath() const;
+
+private:
+ Ui::StartRemoteEngineDialog *m_ui;
+};
+
} // namespace Debugger
} // namespace Internal
diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp
index 82e1122eaf..7160c735f1 100644
--- a/src/plugins/debugger/debuggerengine.cpp
+++ b/src/plugins/debugger/debuggerengine.cpp
@@ -34,13 +34,14 @@
#include "debuggerengine.h"
#include "debuggeractions.h"
-#include "debuggeragents.h"
-#include "debuggerrunner.h"
+#include "debuggercore.h"
#include "debuggerplugin.h"
+#include "debuggerrunner.h"
#include "debuggerstringutils.h"
#include "debuggertooltip.h"
-#include "logwindow.h"
+#include "memoryagent.h"
+#include "disassembleragent.h"
#include "breakhandler.h"
#include "moduleshandler.h"
#include "registerhandler.h"
@@ -49,50 +50,30 @@
#include "stackhandler.h"
#include "threadshandler.h"
#include "watchhandler.h"
-#include "watchutils.h"
-#include "breakwindow.h"
#include <coreplugin/icore.h>
+#include <coreplugin/ifile.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <coreplugin/progressmanager/futureprogress.h>
-#include <projectexplorer/debugginghelper.h>
-#include <projectexplorer/project.h>
-#include <projectexplorer/projectexplorerconstants.h>
-#include <projectexplorer/target.h>
-#include <projectexplorer/buildconfiguration.h>
-#include <projectexplorer/applicationrunconfiguration.h> // For LocalApplication*
-
-#include <qt4projectmanager/qt4projectmanagerconstants.h>
+#include <projectexplorer/toolchain.h>
+#include <projectexplorer/toolchaintype.h>
#include <texteditor/itexteditor.h>
+#include <texteditor/basetextmark.h>
#include <utils/environment.h>
#include <utils/savedaction.h>
#include <utils/qtcassert.h>
#include <QtCore/QDebug>
-#include <QtCore/QDir>
-#include <QtCore/QFileInfo>
#include <QtCore/QTimer>
#include <QtCore/QFutureInterface>
-#include <QtGui/QAbstractItemView>
-#include <QtGui/QStandardItemModel>
-#include <QtGui/QAction>
-#include <QtGui/QMenu>
#include <QtGui/QMessageBox>
-#include <QtGui/QPlainTextEdit>
-#include <QtGui/QPushButton>
-#include <QtGui/QTextBlock>
-#include <QtGui/QTextCursor>
-#include <QtGui/QTextDocument>
-#include <QtGui/QTreeWidget>
-#include <QtGui/QMainWindow>
using namespace Core;
-using namespace Debugger;
using namespace Debugger::Internal;
using namespace ProjectExplorer;
using namespace TextEditor;
@@ -105,34 +86,33 @@ using namespace TextEditor;
#endif
# define XSDEBUG(s) qDebug() << s
+
///////////////////////////////////////////////////////////////////////
//
// DebuggerStartParameters
//
///////////////////////////////////////////////////////////////////////
+namespace Debugger {
+
DebuggerStartParameters::DebuggerStartParameters() :
isSnapshot(false),
attachPID(-1),
useTerminal(false),
- breakAtMain(false),
qmlServerAddress("127.0.0.1"),
qmlServerPort(0),
useServerStartScript(false),
connParams(SshConnectionParameters::NoProxy),
- toolChainType(ToolChain::UNKNOWN),
+ toolChainType(ToolChain_UNKNOWN),
startMode(NoStartMode),
executableUid(0)
{}
-void DebuggerStartParameters::clear()
+QString DebuggerStartParameters::toolChainName() const
{
- *this = DebuggerStartParameters();
+ return ToolChain::toolChainName(ProjectExplorer::ToolChainType(toolChainType));
}
-
-namespace Debugger {
-
QDebug operator<<(QDebug d, DebuggerState state)
{
//return d << DebuggerEngine::stateName(state) << '(' << int(state) << ')';
@@ -142,10 +122,9 @@ QDebug operator<<(QDebug d, DebuggerState state)
QDebug operator<<(QDebug str, const DebuggerStartParameters &sp)
{
QDebug nospace = str.nospace();
- const QString sep = QString(QLatin1Char(','));
nospace << "executable=" << sp.executable
<< " coreFile=" << sp.coreFile
- << " processArgs=" << sp.processArgs.join(sep)
+ << " processArgs=" << sp.processArgs
<< " environment=<" << sp.environment.size() << " variables>"
<< " workingDir=" << sp.workingDirectory
<< " attachPID=" << sp.attachPID
@@ -191,29 +170,26 @@ const char *DebuggerEngine::stateName(int s)
}
-//////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////
//
-// CommandHandler
+// LocationMark
//
-//////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////
-class CommandHandler : public QStandardItemModel
+// Used in "real" editors
+class LocationMark : public TextEditor::BaseTextMark
{
public:
- explicit CommandHandler(DebuggerEngine *engine) : m_engine(engine) {}
- bool setData(const QModelIndex &index, const QVariant &value, int role);
- QAbstractItemModel *model() { return this; }
+ LocationMark(const QString &fileName, int linenumber)
+ : BaseTextMark(fileName, linenumber)
+ {}
-private:
- QPointer<DebuggerEngine> m_engine;
+ QIcon icon() const { return debuggerCore()->locationMarkIcon(); }
+ void updateLineNumber(int /*lineNumber*/) {}
+ void updateBlock(const QTextBlock & /*block*/) {}
+ void removedFromEditor() {}
};
-bool CommandHandler::setData(const QModelIndex &, const QVariant &value, int role)
-{
- QTC_ASSERT(m_engine, qDebug() << value << role; return false);
- m_engine->handleCommand(role, value);
- return true;
-}
//////////////////////////////////////////////////////////////////////
@@ -230,30 +206,26 @@ public:
DebuggerEnginePrivate(DebuggerEngine *engine, const DebuggerStartParameters &sp)
: m_engine(engine),
m_runControl(0),
- m_isActive(false),
m_startParameters(sp),
m_state(DebuggerNotReady),
m_lastGoodState(DebuggerNotReady),
m_targetState(DebuggerNotReady),
- m_breakHandler(engine),
- m_commandHandler(engine),
- m_modulesHandler(engine),
- m_registerHandler(engine),
- m_sourceFilesHandler(engine),
- m_stackHandler(engine),
- m_threadsHandler(engine),
+ m_modulesHandler(),
+ m_registerHandler(),
+ m_sourceFilesHandler(),
+ m_stackHandler(),
+ m_threadsHandler(),
m_watchHandler(engine),
- m_disassemblerViewAgent(engine),
- m_runInWrapperEngine(false)
- {}
+ m_isSlaveEngine(false),
+ m_disassemblerAgent(engine),
+ m_memoryAgent(engine)
+ {
+ connect(&m_locationTimer, SIGNAL(timeout()), SLOT(resetLocation()));
+ }
~DebuggerEnginePrivate() {}
public slots:
- void breakpointSetRemoveMarginActionTriggered();
- void breakpointEnableDisableMarginActionTriggered();
- void handleContextMenuRequest(const QVariant &parameters);
-
void doSetupInferior();
void doRunEngine();
void doShutdownEngine();
@@ -261,25 +233,29 @@ public slots:
void doInterruptInferior();
void doFinishDebugger();
- void queueRunEngine() {
+ void queueRunEngine()
+ {
m_engine->setState(EngineRunRequested);
m_engine->showMessage(_("QUEUE: RUN ENGINE"));
QTimer::singleShot(0, this, SLOT(doRunEngine()));
}
- void queueShutdownEngine() {
+ void queueShutdownEngine()
+ {
m_engine->setState(EngineShutdownRequested);
m_engine->showMessage(_("QUEUE: SHUTDOWN ENGINE"));
QTimer::singleShot(0, this, SLOT(doShutdownEngine()));
}
- void queueShutdownInferior() {
+ void queueShutdownInferior()
+ {
m_engine->setState(InferiorShutdownRequested);
m_engine->showMessage(_("QUEUE: SHUTDOWN INFERIOR"));
QTimer::singleShot(0, this, SLOT(doShutdownInferior()));
}
- void queueFinishDebugger() {
+ void queueFinishDebugger()
+ {
QTC_ASSERT(state() == EngineShutdownOk
|| state() == EngineShutdownFailed, qDebug() << state());
m_engine->setState(DebuggerFinished);
@@ -287,20 +263,32 @@ public slots:
QTimer::singleShot(0, this, SLOT(doFinishDebugger()));
}
- void raiseApplication() {
+ void raiseApplication()
+ {
QTC_ASSERT(m_runControl, return);
m_runControl->bringApplicationToForeground(m_inferiorPid);
}
-private slots:
- void slotEditBreakpoint();
+ void scheduleResetLocation()
+ {
+ m_stackHandler.scheduleResetLocation();
+ m_locationTimer.setSingleShot(true);
+ m_locationTimer.start(80);
+ }
+
+ void resetLocation()
+ {
+ m_locationTimer.stop();
+ m_locationMark.reset();
+ m_stackHandler.resetLocation();
+ m_disassemblerAgent.resetLocation();
+ }
public:
DebuggerState state() const { return m_state; }
DebuggerEngine *m_engine; // Not owned.
DebuggerRunControl *m_runControl; // Not owned.
- bool m_isActive;
DebuggerStartParameters m_startParameters;
@@ -315,132 +303,21 @@ public:
qint64 m_inferiorPid;
- BreakHandler m_breakHandler;
- CommandHandler m_commandHandler;
ModulesHandler m_modulesHandler;
RegisterHandler m_registerHandler;
SourceFilesHandler m_sourceFilesHandler;
StackHandler m_stackHandler;
ThreadsHandler m_threadsHandler;
WatchHandler m_watchHandler;
- DisassemblerViewAgent m_disassemblerViewAgent;
QFutureInterface<void> m_progress;
- bool m_runInWrapperEngine;
+ bool m_isSlaveEngine;
+ DisassemblerAgent m_disassemblerAgent;
+ MemoryAgent m_memoryAgent;
+ QScopedPointer<TextEditor::BaseTextMark> m_locationMark;
+ QTimer m_locationTimer;
};
-void DebuggerEnginePrivate::breakpointSetRemoveMarginActionTriggered()
-{
- QAction *act = qobject_cast<QAction *>(sender());
- QTC_ASSERT(act, return);
- QList<QVariant> list = act->data().toList();
- QTC_ASSERT(list.size() >= 3, qDebug() << list; return);
- const QString fileName = list.at(0).toString();
- const int lineNumber = list.at(1).toInt();
- const quint64 address = list.at(2).toULongLong();
- m_breakHandler.toggleBreakpoint(fileName, lineNumber, address);
-}
-
-void DebuggerEnginePrivate::slotEditBreakpoint()
-{
- const QAction *act = qobject_cast<QAction *>(sender());
- QTC_ASSERT(act, return);
- const QVariant data = act->data();
- QTC_ASSERT(qVariantCanConvert<BreakpointData *>(data), return);
- BreakpointData *breakPointData = qvariant_cast<BreakpointData *>(data);
- if (BreakWindow::editBreakpoint(breakPointData, ICore::instance()->mainWindow()))
- breakPointData->reinsertBreakpoint();
-}
-
-void DebuggerEnginePrivate::breakpointEnableDisableMarginActionTriggered()
-{
- QAction *act = qobject_cast<QAction *>(sender());
- QTC_ASSERT(act, return);
- QList<QVariant> list = act->data().toList();
- QTC_ASSERT(list.size() == 3, qDebug() << list; return);
- const QString fileName = list.at(0).toString();
- const int lineNumber = list.at(1).toInt();
- m_breakHandler.toggleBreakpointEnabled(fileName, lineNumber);
-}
-
-void DebuggerEnginePrivate::handleContextMenuRequest(const QVariant &parameters)
-{
- const QList<QVariant> list = parameters.toList();
- QTC_ASSERT(list.size() == 3, qDebug() << list; return);
- TextEditor::ITextEditor *editor =
- (TextEditor::ITextEditor *)(list.at(0).value<quint64>());
- int lineNumber = list.at(1).toInt();
- QMenu *menu = (QMenu *)(list.at(2).value<quint64>());
-
- BreakpointData *data = 0;
- QString fileName;
- quint64 address = 0;
- if (editor->property("DisassemblerView").toBool()) {
- fileName = editor->file()->fileName();
- QString line = editor->contents()
- .section('\n', lineNumber - 1, lineNumber - 1);
- BreakpointData needle;
- address = needle.address = DisassemblerViewAgent::addressFromDisassemblyLine(line);
- needle.bpLineNumber = -1;
- data = m_breakHandler.findSimilarBreakpoint(&needle);
- } else {
- fileName = editor->file()->fileName();
- data = m_breakHandler.findBreakpoint(fileName, lineNumber);
- }
-
- QList<QVariant> args;
- args.append(fileName);
- args.append(lineNumber);
- args.append(address);
-
- if (data) {
- // existing breakpoint
- const QString number = QString::fromAscii(data->bpNumber);
- QAction *act;
- if (number.isEmpty())
- act = new QAction(tr("Remove Breakpoint"), menu);
- else
- act = new QAction(tr("Remove Breakpoint %1").arg(number), menu);
- act->setData(args);
- connect(act, SIGNAL(triggered()),
- this, SLOT(breakpointSetRemoveMarginActionTriggered()));
- menu->addAction(act);
-
- QAction *act2;
- if (data->enabled)
- if (number.isEmpty())
- act2 = new QAction(tr("Disable Breakpoint"), menu);
- else
- act2 = new QAction(tr("Disable Breakpoint %1").arg(number), menu);
- else
- if (number.isEmpty())
- act2 = new QAction(tr("Enable Breakpoint"), menu);
- else
- act2 = new QAction(tr("Enable Breakpoint %1").arg(number), menu);
- act2->setData(args);
- connect(act2, SIGNAL(triggered()),
- this, SLOT(breakpointEnableDisableMarginActionTriggered()));
- menu->addAction(act2);
- QAction *editAction;
- if (number.isEmpty())
- editAction = new QAction(tr("Edit Breakpoint..."), menu);
- else
- editAction = new QAction(tr("Edit Breakpoint %1...").arg(number), menu);
- connect(editAction, SIGNAL(triggered()), this, SLOT(slotEditBreakpoint()));
- editAction->setData(qVariantFromValue(data));
- menu->addAction(editAction);
- } else {
- // non-existing
- const QString text = address ?
- tr("Set Breakpoint at 0x%1").arg(address, 0, 16) :
- tr("Set Breakpoint at line %1").arg(lineNumber);
- QAction *act = new QAction(text, menu);
- act->setData(args);
- connect(act, SIGNAL(triggered()),
- this, SLOT(breakpointSetRemoveMarginActionTriggered()));
- menu->addAction(act);
- }
-}
//////////////////////////////////////////////////////////////////////
//
@@ -470,163 +347,6 @@ void DebuggerEngine::removeTooltip()
hideDebuggerToolTip();
}
-void DebuggerEngine::handleCommand(int role, const QVariant &value)
-{
- if (role != RequestToolTipByExpressionRole)
- removeTooltip();
-
- switch (role) {
- case RequestActivateFrameRole:
- activateFrame(value.toInt());
- break;
-
- case RequestReloadFullStackRole:
- reloadFullStack();
- break;
-
- case RequestReloadSourceFilesRole:
- reloadSourceFiles();
- break;
-
- case RequestReloadModulesRole:
- reloadModules();
- break;
-
- case RequestReloadRegistersRole:
- reloadRegisters();
- break;
-
- case RequestExecDetachRole:
- detachDebugger();
- break;
-
- case RequestExecContinueRole:
- continueInferior();
- break;
-
- case RequestExecInterruptRole:
- requestInterruptInferior();
- break;
-
- case RequestExecResetRole:
- notifyEngineIll(); // FIXME: check
- break;
-
- case RequestExecStepRole:
- executeStepX();
- break;
-
- case RequestExecStepOutRole:
- executeStepOutX();
- break;
-
- case RequestExecNextRole:
- executeStepNextX();
- break;
-
- case RequestExecRunToLineRole:
- executeRunToLine();
- break;
-
- case RequestExecRunToFunctionRole:
- executeRunToFunction();
- break;
-
- case RequestExecReturnFromFunctionRole:
- executeReturnX();
- break;
-
- case RequestExecJumpToLineRole:
- executeJumpToLine();
- break;
-
- case RequestExecWatchRole:
- addToWatchWindow();
- break;
-
- case RequestExecExitRole:
- d->queueShutdownInferior();
- break;
-
- case RequestCreateSnapshotRole:
- createSnapshot();
- break;
-
- case RequestActivationRole:
- setActive(value.toBool());
- break;
-
- case RequestExecFrameDownRole:
- frameDown();
- break;
-
- case RequestExecFrameUpRole:
- frameUp();
- break;
-
- case RequestOperatedByInstructionTriggeredRole:
- gotoLocation(stackHandler()->currentFrame(), true);
- break;
-
- case RequestExecuteCommandRole:
- executeDebuggerCommand(value.toString());
- break;
-
- case RequestToggleBreakpointRole: {
- QList<QVariant> list = value.toList();
- QTC_ASSERT(list.size() == 2, break);
- const QString fileName = list.at(0).toString();
- const int lineNumber = list.at(1).toInt();
- breakHandler()->toggleBreakpoint(fileName, lineNumber);
- break;
- }
-
- case RequestToolTipByExpressionRole: {
- QList<QVariant> list = value.toList();
- QTC_ASSERT(list.size() == 3, break);
- QPoint point = list.at(0).value<QPoint>();
- TextEditor::ITextEditor *editor = // Eeks.
- (TextEditor::ITextEditor *)(list.at(1).value<quint64>());
- int pos = list.at(2).toInt();
- setToolTipExpression(point, editor, pos);
- break;
- }
-
- case RequestContextMenuRole: {
- QList<QVariant> list = value.toList();
- QTC_ASSERT(list.size() == 3, break);
- d->handleContextMenuRequest(list);
- break;
- }
-
- case RequestShowMemoryRole: {
- qDebug() << "CREATING MEMORY VIEW";
- (void) MemoryViewAgent(this, "0x0");
- break;
- }
- }
-}
-
-void DebuggerEngine::showModuleSymbols
- (const QString &moduleName, const Symbols &symbols)
-{
- QTreeWidget *w = new QTreeWidget;
- w->setColumnCount(3);
- w->setRootIsDecorated(false);
- w->setAlternatingRowColors(true);
- w->setSortingEnabled(true);
- w->setHeaderLabels(QStringList() << tr("Symbol") << tr("Address") << tr("Code"));
- w->setWindowTitle(tr("Symbols in \"%1\"").arg(moduleName));
- foreach (const Symbol &s, symbols) {
- QTreeWidgetItem *it = new QTreeWidgetItem;
- it->setData(0, Qt::DisplayRole, s.name);
- it->setData(1, Qt::DisplayRole, s.address);
- it->setData(2, Qt::DisplayRole, s.state);
- w->addTopLevelItem(it);
- }
- plugin()->createNewDock(w);
-}
-
void DebuggerEngine::frameUp()
{
int currentIndex = stackHandler()->currentIndex();
@@ -644,11 +364,6 @@ ModulesHandler *DebuggerEngine::modulesHandler() const
return &d->m_modulesHandler;
}
-BreakHandler *DebuggerEngine::breakHandler() const
-{
- return &d->m_breakHandler;
-}
-
RegisterHandler *DebuggerEngine::registerHandler() const
{
return &d->m_registerHandler;
@@ -669,11 +384,6 @@ WatchHandler *DebuggerEngine::watchHandler() const
return &d->m_watchHandler;
}
-//SnapshotHandler *DebuggerEngine::snapshotHandler() const
-//{
-// return &d->m_snapshotHandler;
-//}
-
SourceFilesHandler *DebuggerEngine::sourceFilesHandler() const
{
return &d->m_sourceFilesHandler;
@@ -687,14 +397,6 @@ QAbstractItemModel *DebuggerEngine::modulesModel() const
return model;
}
-QAbstractItemModel *DebuggerEngine::breakModel() const
-{
- QAbstractItemModel *model = d->m_breakHandler.model();
- if (model->objectName().isEmpty()) // Make debugging easier.
- model->setObjectName(objectName() + QLatin1String("BreakModel"));
- return model;
-}
-
QAbstractItemModel *DebuggerEngine::registerModel() const
{
QAbstractItemModel *model = d->m_registerHandler.model();
@@ -751,15 +453,7 @@ QAbstractItemModel *DebuggerEngine::sourceFilesModel() const
return model;
}
-QAbstractItemModel *DebuggerEngine::commandModel() const
-{
- QAbstractItemModel *model = d->m_commandHandler.model();
- if (model->objectName().isEmpty()) // Make debugging easier.
- model->setObjectName(objectName() + QLatin1String("CommandModel"));
- return model;
-}
-
-void DebuggerEngine::fetchMemory(MemoryViewAgent *, QObject *,
+void DebuggerEngine::fetchMemory(MemoryAgent *, QObject *,
quint64 addr, quint64 length)
{
Q_UNUSED(addr);
@@ -776,7 +470,7 @@ void DebuggerEngine::showMessage(const QString &msg, int channel, int timeout) c
{
//if (msg.size() && msg.at(0).isUpper() && msg.at(1).isUpper())
// qDebug() << qPrintable(msg) << "IN STATE" << state();
- plugin()->showMessage(msg, channel, timeout);
+ debuggerCore()->showMessage(msg, channel, timeout);
if (d->m_runControl) {
d->m_runControl->showMessage(msg, channel);
} else {
@@ -786,7 +480,7 @@ void DebuggerEngine::showMessage(const QString &msg, int channel, int timeout) c
void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
{
- if (!isSessionEngine() && !d->m_runInWrapperEngine) {
+ if (!isSlaveEngine()) {
d->m_progress.setProgressRange(0, 1000);
Core::FutureProgress *fp = Core::ICore::instance()->progressManager()
->addTask(d->m_progress.future(),
@@ -797,199 +491,67 @@ void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
QTC_ASSERT(runControl, notifyEngineSetupFailed(); return);
QTC_ASSERT(!d->m_runControl, notifyEngineSetupFailed(); return);
- DebuggerEngine *sessionTemplate = plugin()->sessionTemplate();
- QTC_ASSERT(sessionTemplate, notifyEngineSetupFailed(); return);
- QTC_ASSERT(sessionTemplate != this, notifyEngineSetupFailed(); return);
-
- breakHandler()->initializeFromTemplate(sessionTemplate->breakHandler());
- watchHandler()->initializeFromTemplate(sessionTemplate->watchHandler());
-
d->m_runControl = runControl;
d->m_inferiorPid = d->m_startParameters.attachPID > 0
? d->m_startParameters.attachPID : 0;
- if (d->m_startParameters.environment.empty())
- d->m_startParameters.environment = Utils::Environment().toStringList();
-
- if (d->m_startParameters.breakAtMain)
- breakByFunctionMain();
+ if (!d->m_startParameters.environment.size())
+ d->m_startParameters.environment = Utils::Environment();
const unsigned engineCapabilities = debuggerCapabilities();
- theDebuggerAction(OperateByInstruction)
+ debuggerCore()->action(OperateByInstruction)
->setEnabled(engineCapabilities & DisassemblerCapability);
QTC_ASSERT(state() == DebuggerNotReady || state() == DebuggerFinished,
qDebug() << state());
+ d->m_lastGoodState = DebuggerNotReady;
+ d->m_targetState = DebuggerNotReady;
setState(EngineSetupRequested);
d->m_progress.setProgressValue(200);
setupEngine();
}
-void DebuggerEngine::breakByFunctionMain()
-{
-#ifdef Q_OS_WIN
- // FIXME: wrong on non-Qt based binaries
- emit breakByFunction("qMain");
-#else
- emit breakByFunction("main");
-#endif
-}
-
-void DebuggerEngine::breakByFunction(const QString &functionName)
-{
- d->m_breakHandler.breakByFunction(functionName);
- attemptBreakpointSynchronization();
-}
-
void DebuggerEngine::resetLocation()
{
- d->m_disassemblerViewAgent.resetLocation();
- d->m_stackHandler.setCurrentIndex(-1);
- plugin()->resetLocation();
+ // Do it after some delay to avoid flicker.
+ d->scheduleResetLocation();
}
-void DebuggerEngine::gotoLocation(const QString &fileName, int lineNumber, bool setMarker)
+void DebuggerEngine::gotoLocation(const Location &loc)
{
- StackFrame frame;
- frame.file = fileName;
- frame.line = lineNumber;
- gotoLocation(frame, setMarker);
-}
-
-void DebuggerEngine::gotoLocation(const StackFrame &frame, bool setMarker)
-{
- if (theDebuggerBoolSetting(OperateByInstruction) || !frame.isUsable()) {
- if (setMarker)
- plugin()->resetLocation();
- d->m_disassemblerViewAgent.setFrame(frame);
- } else {
- plugin()->gotoLocation(frame.file, frame.line, setMarker);
+ if (debuggerCore()->boolSetting(OperateByInstruction) || !loc.hasDebugInfo()) {
+ d->m_disassemblerAgent.setTryMixed(true);
+ d->m_disassemblerAgent.setLocation(loc);
+ return;
}
-}
-
-void DebuggerEngine::executeStepX()
-{
- resetLocation();
- if (theDebuggerBoolSetting(OperateByInstruction))
- executeStepI();
- else
- executeStep();
-}
-
-void DebuggerEngine::executeStepOutX()
-{
- resetLocation();
- executeStepOut();
-}
+ // CDB might hit on breakpoints while shutting down.
+ //if (m_shuttingDown)
+ // return;
-void DebuggerEngine::executeStepNextX()
-{
- resetLocation();
- if (theDebuggerBoolSetting(OperateByInstruction))
- executeNextI();
- else
- executeNext();
-}
+ d->resetLocation();
-void DebuggerEngine::executeReturnX()
-{
- resetLocation();
- executeReturn();
-}
-
-static TextEditor::ITextEditor *currentTextEditor()
-{
+ const QString file = loc.fileName();
+ const int line = loc.lineNumber();
EditorManager *editorManager = EditorManager::instance();
- if (!editorManager)
- return 0;
- Core::IEditor *editor = editorManager->currentEditor();
- return qobject_cast<ITextEditor*>(editor);
-}
-
-void DebuggerEngine::executeRunToLine()
-{
- ITextEditor *textEditor = currentTextEditor();
- QTC_ASSERT(textEditor, return);
- QString fileName = textEditor->file()->fileName();
- if (fileName.isEmpty())
- return;
- int lineNumber = textEditor->currentLine();
- resetLocation();
- executeRunToLine(fileName, lineNumber);
-}
-
-void DebuggerEngine::executeRunToFunction()
-{
- ITextEditor *textEditor = currentTextEditor();
- QTC_ASSERT(textEditor, return);
- QString fileName = textEditor->file()->fileName();
- QPlainTextEdit *ed = qobject_cast<QPlainTextEdit*>(textEditor->widget());
- if (!ed)
- return;
- QTextCursor cursor = ed->textCursor();
- QString functionName = cursor.selectedText();
- if (functionName.isEmpty()) {
- const QTextBlock block = cursor.block();
- const QString line = block.text();
- foreach (const QString &str, line.trimmed().split('(')) {
- QString a;
- for (int i = str.size(); --i >= 0; ) {
- if (!str.at(i).isLetterOrNumber())
- break;
- a = str.at(i) + a;
- }
- if (!a.isEmpty()) {
- functionName = a;
- break;
- }
- }
+ QList<IEditor *> editors = editorManager->editorsForFileName(file);
+ if (editors.isEmpty()) {
+ editors.append(editorManager->openEditor(file, QString(),
+ EditorManager::IgnoreNavigationHistory));
+ editors.back()->setProperty(Constants::OPENED_BY_DEBUGGER, true);
}
+ ITextEditor *texteditor = qobject_cast<ITextEditor *>(editors.back());
+ if (texteditor)
+ texteditor->gotoLine(line, 0);
- if (functionName.isEmpty())
- return;
- resetLocation();
- executeRunToFunction(functionName);
-}
+ if (loc.needsMarker())
+ d->m_locationMark.reset(new LocationMark(file, line));
-void DebuggerEngine::executeJumpToLine()
-{
- ITextEditor *textEditor = currentTextEditor();
- QTC_ASSERT(textEditor, return);
- QString fileName = textEditor->file()->fileName();
- int lineNumber = textEditor->currentLine();
- if (fileName.isEmpty())
- return;
- executeJumpToLine(fileName, lineNumber);
-}
-
-void DebuggerEngine::addToWatchWindow()
-{
- // Requires a selection, but that's the only case we want anyway.
- EditorManager *editorManager = EditorManager::instance();
- if (!editorManager)
- return;
- IEditor *editor = editorManager->currentEditor();
- if (!editor)
- return;
- ITextEditor *textEditor = qobject_cast<ITextEditor*>(editor);
- if (!textEditor)
- return;
- QTextCursor tc;
- QPlainTextEdit *ptEdit = qobject_cast<QPlainTextEdit*>(editor->widget());
- if (ptEdit)
- tc = ptEdit->textCursor();
- QString exp;
- if (tc.hasSelection()) {
- exp = tc.selectedText();
- } else {
- int line, column;
- exp = cppExpressionAt(textEditor, tc.position(), &line, &column);
- }
- if (exp.isEmpty())
- return;
- watchHandler()->watchExpression(exp);
+ // FIXME: Breaks with split views.
+ if (!d->m_memoryAgent.hasVisibleEditor() || loc.needsRaise())
+ editorManager->activateEditor(editors.back());
+ //qDebug() << "MEMORY: " << d->m_memoryAgent.hasVisibleEditor();
}
// Called from RunControl.
@@ -997,7 +559,6 @@ void DebuggerEngine::handleStartFailed()
{
showMessage("HANDLE RUNCONTROL START FAILED");
d->m_runControl = 0;
-
d->m_progress.setProgressValue(900);
d->m_progress.reportCanceled();
d->m_progress.reportFinished();
@@ -1012,12 +573,6 @@ void DebuggerEngine::handleFinished()
stackHandler()->removeAll();
threadsHandler()->removeAll();
watchHandler()->cleanup();
-
- DebuggerEngine *sessionTemplate = plugin()->sessionTemplate();
- QTC_ASSERT(sessionTemplate != this, /**/);
- breakHandler()->storeToTemplate(sessionTemplate->breakHandler());
- watchHandler()->storeToTemplate(sessionTemplate->watchHandler());
-
d->m_progress.setProgressValue(1000);
d->m_progress.reportFinished();
}
@@ -1044,14 +599,14 @@ DebuggerStartParameters &DebuggerEngine::startParameters()
bool DebuggerEngine::qtDumperLibraryEnabled() const
{
- return theDebuggerBoolSetting(UseDebuggingHelpers);
+ return debuggerCore()->boolSetting(UseDebuggingHelpers);
}
QStringList DebuggerEngine::qtDumperLibraryLocations() const
{
- if (theDebuggerAction(UseCustomDebuggingHelperLocation)->value().toBool()) {
+ if (debuggerCore()->action(UseCustomDebuggingHelperLocation)->value().toBool()) {
const QString customLocation =
- theDebuggerAction(CustomDebuggingHelperLocation)->value().toString();
+ debuggerCore()->action(CustomDebuggingHelperLocation)->value().toString();
const QString location =
tr("%1 (explicitly set in the Debugger Options)").arg(customLocation);
return QStringList(location);
@@ -1061,39 +616,13 @@ QStringList DebuggerEngine::qtDumperLibraryLocations() const
void DebuggerEngine::showQtDumperLibraryWarning(const QString &details)
{
- QMessageBox dialog(plugin()->mainWindow());
- QPushButton *qtPref = dialog.addButton(tr("Open Qt4 Options"),
- QMessageBox::ActionRole);
- QPushButton *helperOff = dialog.addButton(tr("Turn off Helper Usage"),
- QMessageBox::ActionRole);
- QPushButton *justContinue = dialog.addButton(tr("Continue Anyway"),
- QMessageBox::AcceptRole);
- dialog.setDefaultButton(justContinue);
- dialog.setWindowTitle(tr("Debugging Helper Missing"));
- dialog.setText(tr("The debugger could not load the debugging helper library."));
- dialog.setInformativeText(tr(
- "The debugging helper is used to nicely format the values of some Qt "
- "and Standard Library data types. "
- "It must be compiled for each used Qt version separately. "
- "On the Qt4 options page, select a Qt installation "
- "and click Rebuild."));
- if (!details.isEmpty())
- dialog.setDetailedText(details);
- dialog.exec();
- if (dialog.clickedButton() == qtPref) {
- Core::ICore::instance()->showOptionsDialog(
- _(Qt4ProjectManager::Constants::QT_SETTINGS_CATEGORY),
- _(Qt4ProjectManager::Constants::QTVERSION_SETTINGS_PAGE_ID));
- } else if (dialog.clickedButton() == helperOff) {
- theDebuggerAction(UseDebuggingHelpers)
- ->setValue(qVariantFromValue(false), false);
- }
+ debuggerCore()->showQtDumperLibraryWarning(details);
}
QString DebuggerEngine::qtDumperLibraryName() const
{
- if (theDebuggerAction(UseCustomDebuggingHelperLocation)->value().toBool())
- return theDebuggerAction(CustomDebuggingHelperLocation)->value().toString();
+ if (debuggerCore()->action(UseCustomDebuggingHelperLocation)->value().toBool())
+ return debuggerCore()->action(CustomDebuggingHelperLocation)->value().toString();
return startParameters().dumperLibrary;
}
@@ -1121,10 +650,9 @@ static bool isAllowedTransition(DebuggerState from, DebuggerState to)
case EngineSetupRequested:
return to == EngineSetupOk || to == EngineSetupFailed;
case EngineSetupFailed:
- // FIXME: In therory it's the engine's task to go into a
- // proper "Shutdown" state before calling notifyEngineSetupFailed
- //return to == DebuggerFinished;
- return to == EngineShutdownRequested;
+ // In is the engine's task to go into a proper "Shutdown"
+ // state before calling notifyEngineSetupFailed
+ return to == DebuggerFinished;
case EngineSetupOk:
return to == InferiorSetupRequested || to == EngineShutdownRequested;
@@ -1138,7 +666,7 @@ static bool isAllowedTransition(DebuggerState from, DebuggerState to)
|| to == InferiorUnrunnable || to == EngineRunFailed;
case EngineRunFailed:
- return to == InferiorShutdownRequested;
+ return to == EngineShutdownRequested;
case InferiorRunRequested:
return to == InferiorRunOk || to == InferiorRunFailed;
@@ -1175,7 +703,7 @@ static bool isAllowedTransition(DebuggerState from, DebuggerState to)
return to == EngineSetupRequested; // Happens on restart.
}
- qDebug() << "UNKNOWN STATE:" << from;
+ qDebug() << "UNKNOWN DEBUGGER STATE:" << from;
return false;
}
@@ -1344,7 +872,7 @@ void DebuggerEnginePrivate::doInterruptInferior()
void DebuggerEnginePrivate::doShutdownInferior()
{
QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state());
- m_engine->resetLocation();
+ resetLocation();
m_targetState = DebuggerFinished;
m_engine->showMessage(_("CALL: SHUTDOWN INFERIOR"));
m_engine->shutdownInferior();
@@ -1397,11 +925,7 @@ void DebuggerEngine::notifyEngineShutdownOk()
showMessage(_("NOTE: ENGINE SHUTDOWN OK"));
QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state());
setState(EngineShutdownOk);
- if (!d->m_runInWrapperEngine) {
- d->queueFinishDebugger();
- } else {
- setState(DebuggerFinished);
- }
+ d->queueFinishDebugger();
}
void DebuggerEngine::notifyEngineShutdownFailed()
@@ -1409,20 +933,18 @@ void DebuggerEngine::notifyEngineShutdownFailed()
showMessage(_("NOTE: ENGINE SHUTDOWN FAILED"));
QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state());
setState(EngineShutdownFailed);
- if (!d->m_runInWrapperEngine) {
- d->queueFinishDebugger();
- } else {
- setState(DebuggerFinished);
- }
+ d->queueFinishDebugger();
}
void DebuggerEnginePrivate::doFinishDebugger()
{
m_engine->showMessage(_("NOTE: FINISH DEBUGGER"));
QTC_ASSERT(state() == DebuggerFinished, qDebug() << state());
- m_engine->resetLocation();
- QTC_ASSERT(m_runControl, return);
- m_runControl->debuggingFinished();
+ resetLocation();
+ if (!m_engine->isSlaveEngine()) {
+ QTC_ASSERT(m_runControl, return);
+ m_runControl->debuggingFinished();
+ }
}
void DebuggerEngine::notifyEngineIll()
@@ -1462,7 +984,7 @@ void DebuggerEngine::notifyEngineSpontaneousShutdown()
void DebuggerEngine::notifyInferiorExited()
{
showMessage(_("NOTE: INFERIOR EXITED"));
- resetLocation();
+ d->resetLocation();
// This can be issued in almost any state. We assume, though,
// that at this point of time the inferior is not running anymore,
@@ -1490,19 +1012,40 @@ void DebuggerEngine::setState(DebuggerState state, bool forced)
if (!forced && !isAllowedTransition(oldState, state))
qDebug() << "UNEXPECTED STATE TRANSITION: " << msg;
+ if (state == DebuggerFinished) {
+ // Give up ownership on claimed breakpoints.
+ BreakHandler *handler = breakHandler();
+ foreach (BreakpointId id, handler->engineBreakpointIds(this))
+ handler->notifyBreakpointReleased(id);
+ }
+
const bool running = d->m_state == InferiorRunOk;
if (running)
threadsHandler()->notifyRunning();
showMessage(msg, LogDebug);
- plugin()->updateState(this);
+ updateViews();
emit stateChanged(d->m_state);
}
-void DebuggerEngine::setRunInWrapperEngine(bool value)
+void DebuggerEngine::updateViews()
+{
+ // The slave engines are not entitled to change the view. Their wishes
+ // should be coordinated by their master engine.
+ if (isSlaveEngine())
+ return;
+ debuggerCore()->updateState(this);
+}
+
+bool DebuggerEngine::isSlaveEngine() const
{
- d->m_runInWrapperEngine = value;
+ return d->m_isSlaveEngine;
+}
+
+void DebuggerEngine::setSlaveEngine(bool value)
+{
+ d->m_isSlaveEngine = value;
}
bool DebuggerEngine::debuggerActionsEnabled() const
@@ -1555,34 +1098,12 @@ qint64 DebuggerEngine::inferiorPid() const
return d->m_inferiorPid;
}
-DebuggerPlugin *DebuggerEngine::plugin()
-{
- return DebuggerPlugin::instance();
-}
-
-void DebuggerEngine::openFile(const QString &fileName, int lineNumber)
-{
- plugin()->gotoLocation(fileName, lineNumber, false);
-}
-
bool DebuggerEngine::isReverseDebugging() const
{
- return plugin()->isReverseDebugging();
-}
-
-bool DebuggerEngine::isActive() const
-{
- return d->m_isActive && !isSessionEngine();
-}
-
-void DebuggerEngine::setActive(bool on)
-{
- //qDebug() << "SETTING ACTIVE" << this << on;
- d->m_isActive = on;
- //breakHandler()->updateMarkers();
+ return debuggerCore()->isReverseDebugging();
}
-// called by DebuggerRunControl
+// Called by DebuggerRunControl.
void DebuggerEngine::quitDebugger()
{
showMessage("QUIT DEBUGGER REQUESTED");
@@ -1596,7 +1117,7 @@ void DebuggerEngine::quitDebugger()
d->doInterruptInferior();
break;
default:
- // FIXME: We should disable the actions connected to that
+ // FIXME: We should disable the actions connected to that.
notifyInferiorIll();
break;
}
@@ -1613,35 +1134,25 @@ void DebuggerEngine::progressPing()
d->m_progress.setProgressValue(progress);
}
-QMessageBox *DebuggerEngine::showMessageBox(int icon, const QString &title,
- const QString &text, int buttons)
-{
- return plugin()->showMessageBox(icon, title, text, buttons);
-}
-
DebuggerRunControl *DebuggerEngine::runControl() const
{
return d->m_runControl;
}
-void DebuggerEngine::setToolTipExpression(const QPoint &, TextEditor::ITextEditor *, int)
+void DebuggerEngine::setToolTipExpression
+ (const QPoint &, TextEditor::ITextEditor *, int)
{
}
-void DebuggerEngine::updateWatchData(const Internal::WatchData &, const Internal::WatchUpdateFlags &)
+void DebuggerEngine::updateWatchData(const WatchData &, const WatchUpdateFlags &)
{
}
-bool DebuggerEngine::isSessionEngine() const
-{
- return false;
-}
-
void DebuggerEngine::watchPoint(const QPoint &)
{
}
-void DebuggerEngine::fetchDisassembler(Internal::DisassemblerViewAgent *)
+void DebuggerEngine::fetchDisassembler(DisassemblerAgent *)
{
}
@@ -1708,20 +1219,98 @@ void DebuggerEngine::updateAll()
{
}
+#if 0
+ // FIXME: Remove explicit use of BreakpointData
+ if (!bp->engine && acceptsBreakpoint(id)) {
+ QTC_ASSERT(state == BreakpointNew, /**/);
+ // Take ownership of the breakpoint.
+ bp->engine = this;
+ }
+#endif
+
void DebuggerEngine::attemptBreakpointSynchronization()
{
+ if (!stateAcceptsBreakpointChanges()) {
+ showMessage(_("BREAKPOINT SYNCHRONIZATION NOT POSSIBLE IN CURRENT STATE"));
+ return;
+ }
+
+ BreakHandler *handler = breakHandler();
+
+ foreach (BreakpointId id, handler->unclaimedBreakpointIds()) {
+ // Take ownership of the breakpoint. Requests insertion.
+ if (acceptsBreakpoint(id))
+ handler->setEngine(id, this);
+ }
+
+ bool done = true;
+ foreach (BreakpointId id, handler->engineBreakpointIds(this)) {
+ switch (handler->state(id)) {
+ case BreakpointNew:
+ // Should not happen once claimed.
+ QTC_ASSERT(false, /**/);
+ continue;
+ case BreakpointInsertRequested:
+ done = false;
+ insertBreakpoint(id);
+ continue;
+ case BreakpointChangeRequested:
+ done = false;
+ changeBreakpoint(id);
+ continue;
+ case BreakpointRemoveRequested:
+ done = false;
+ removeBreakpoint(id);
+ continue;
+ case BreakpointChangeProceeding:
+ case BreakpointInsertProceeding:
+ case BreakpointRemoveProceeding:
+ done = false;
+ //qDebug() << "BREAKPOINT " << id << " STILL IN PROGRESS, STATE"
+ // << handler->state(id);
+ continue;
+ case BreakpointInserted:
+ //qDebug() << "BREAKPOINT " << id << " IS GOOD";
+ continue;
+ case BreakpointDead:
+ // Should not only be visible inside BreakpointHandler.
+ QTC_ASSERT(false, /**/);
+ continue;
+ }
+ QTC_ASSERT(false, qDebug() << "UNKNOWN STATE" << id << state());
+ }
+
+ if (done)
+ d->m_disassemblerAgent.updateBreakpointMarkers();
+}
+
+void DebuggerEngine::insertBreakpoint(BreakpointId id)
+{
+ BreakpointState state = breakHandler()->state(id);
+ QTC_ASSERT(state == BreakpointInsertRequested, qDebug() << state);
+ QTC_ASSERT(false, /**/);
+}
+
+void DebuggerEngine::removeBreakpoint(BreakpointId id)
+{
+ BreakpointState state = breakHandler()->state(id);
+ QTC_ASSERT(state == BreakpointRemoveRequested, qDebug() << state);
+ QTC_ASSERT(false, /**/);
}
-bool DebuggerEngine::acceptsBreakpoint(const BreakpointData *)
+void DebuggerEngine::changeBreakpoint(BreakpointId id)
{
- return true;
+ BreakpointState state = breakHandler()->state(id);
+ QTC_ASSERT(state == BreakpointChangeRequested, qDebug() << state);
+ QTC_ASSERT(false, /**/);
}
void DebuggerEngine::selectThread(int)
{
}
-void DebuggerEngine::assignValueInDebugger(const Internal::WatchData *, const QString &, const QVariant &)
+void DebuggerEngine::assignValueInDebugger(const WatchData *,
+ const QString &, const QVariant &)
{
}
@@ -1729,6 +1318,12 @@ void DebuggerEngine::detachDebugger()
{
}
+void DebuggerEngine::exitDebugger()
+{
+ QTC_ASSERT(d->m_state == InferiorStopOk, qDebug() << d->m_state);
+ d->queueShutdownInferior();
+}
+
void DebuggerEngine::executeStep()
{
}
@@ -1775,7 +1370,11 @@ void DebuggerEngine::executeJumpToLine(const QString &, int)
void DebuggerEngine::executeDebuggerCommand(const QString &)
{
+}
+BreakHandler *DebuggerEngine::breakHandler() const
+{
+ return debuggerCore()->breakHandler();
}
bool DebuggerEngine::isDying() const
@@ -1783,6 +1382,117 @@ bool DebuggerEngine::isDying() const
return targetState() == DebuggerFinished;
}
+QString DebuggerEngine::msgWatchpointTriggered(BreakpointId id,
+ const int number, quint64 address)
+{
+ return id
+ ? tr("Watchpoint %1 (%2) at 0x%3 triggered.")
+ .arg(id).arg(number).arg(address, 0, 16)
+ : tr("Internal watchpoint %1 at 0x%2 triggered.")
+ .arg(number).arg(address, 0, 16);
+}
+
+QString DebuggerEngine::msgWatchpointTriggered(BreakpointId id,
+ const int number, quint64 address, const QString &threadId)
+{
+ return id
+ ? tr("Watchpoint %1 (%2) at 0x%3 in thread %4 triggered.")
+ .arg(id).arg(number).arg(address, 0, 16).arg(threadId)
+ : tr("Internal watchpoint %1 at 0x%2 in thread %3 triggered.")
+ .arg(id).arg(number).arg(address, 0, 16).arg(threadId);
+}
+
+QString DebuggerEngine::msgBreakpointTriggered(BreakpointId id,
+ const int number, const QString &threadId)
+{
+ return id
+ ? tr("Stopped at breakpoint %1 (%2) in thread %3.")
+ .arg(id).arg(number).arg(threadId)
+ : tr("Stopped at internal breakpoint %1 in thread %2.")
+ .arg(number).arg(threadId);
+}
+
+QString DebuggerEngine::msgStopped(const QString &reason)
+{
+ return reason.isEmpty() ? tr("Stopped.") : tr("Stopped: \"%1\"").arg(reason);
+}
+
+QString DebuggerEngine::msgStoppedBySignal(const QString &meaning,
+ const QString &name)
+{
+ return tr("Stopped: %1 by signal %2.").arg(meaning, name);
+}
+
+QString DebuggerEngine::msgStoppedByException(const QString &description,
+ const QString &threadId)
+{
+ return tr("Stopped in thread %1 by: %2.").arg(threadId, description);
+}
+
+QString DebuggerEngine::msgInterrupted()
+{
+ return tr("Interrupted.");
+}
+
+void DebuggerEngine::showStoppedBySignalMessageBox(QString meaning, QString name)
+{
+ if (name.isEmpty())
+ name = tr(" <Unknown> ", "name");
+ if (meaning.isEmpty())
+ meaning = tr(" <Unknown> ", "meaning");
+ const QString msg = tr("<p>The inferior stopped because it received a "
+ "signal from the Operating System.<p>"
+ "<table><tr><td>Signal name : </td><td>%1</td></tr>"
+ "<tr><td>Signal meaning : </td><td>%2</td></tr></table>")
+ .arg(name, meaning);
+ showMessageBox(QMessageBox::Information, tr("Signal received"), msg);
+}
+
+void DebuggerEngine::showStoppedByExceptionMessageBox(const QString &description)
+{
+ const QString msg =
+ tr("<p>The inferior stopped because it triggered an exception.<p>%1").
+ arg(description);
+ showMessageBox(QMessageBox::Information, tr("Exception Triggered"), msg);
+}
+
+bool DebuggerEngine::isCppBreakpoint(const BreakpointParameters &p)
+{
+ // Qml is currently only file
+ if (p.type != BreakpointByFileAndLine)
+ return true;
+ return !p.fileName.endsWith(QLatin1String(".qml"), Qt::CaseInsensitive)
+ && !p.fileName.endsWith(QLatin1String(".js"), Qt::CaseInsensitive);
+}
+
+void DebuggerEngine::openMemoryView(quint64 address)
+{
+ d->m_memoryAgent.createBinEditor(address);
+}
+
+void DebuggerEngine::updateMemoryViews()
+{
+ d->m_memoryAgent.updateContents();
+}
+
+void DebuggerEngine::openDisassemblerView(const Location &location)
+{
+ DisassemblerAgent *agent = new DisassemblerAgent(this);
+ agent->setTryMixed(true);
+ agent->setLocation(location);
+}
+
+void DebuggerEngine::handleRemoteSetupDone(int gdbServerPort, int qmlPort)
+{
+ Q_UNUSED(gdbServerPort);
+ Q_UNUSED(qmlPort);
+}
+
+void DebuggerEngine::handleRemoteSetupFailed(const QString &message)
+{
+ Q_UNUSED(message);
+}
+
} // namespace Debugger
#include "debuggerengine.moc"
diff --git a/src/plugins/debugger/debuggerengine.h b/src/plugins/debugger/debuggerengine.h
index bf099c24d9..b7f788bd50 100644
--- a/src/plugins/debugger/debuggerengine.h
+++ b/src/plugins/debugger/debuggerengine.h
@@ -37,11 +37,14 @@
#include "debugger_global.h"
#include "debuggerconstants.h"
#include "moduleshandler.h" // For 'Symbols'
+#include "breakpoint.h" // For 'BreakpointId'
+#include "stackframe.h"
-#include <coreplugin/ssh/sshconnection.h>
+#include <coreplugin/ssh/sshconnection.h>
+
+#include <utils/environment.h>
#include <QtCore/QObject>
-#include <QtCore/QSharedPointer>
#include <QtCore/QStringList>
QT_BEGIN_NAMESPACE
@@ -60,40 +63,41 @@ class IOptionsPage;
namespace Debugger {
-class DebuggerRunControl;
-class DebuggerPlugin;
class DebuggerEnginePrivate;
-class QmlCppEngine;
+class DebuggerRunControl;
class DEBUGGER_EXPORT DebuggerStartParameters
{
public:
DebuggerStartParameters();
- void clear();
+ QString toolChainName() const;
QString executable;
QString displayName;
QString coreFile;
bool isSnapshot; // set if created internally
- QStringList processArgs;
- QStringList environment;
+ QString processArgs;
+ Utils::Environment environment;
QString workingDirectory;
qint64 attachPID;
bool useTerminal;
- bool breakAtMain;
- QString crashParameter; // for AttachCrashedExternal
- // for qml debugging
+ // Used by AttachCrashedExternal.
+ QString crashParameter;
+
+ // Used by Qml debugging.
QString qmlServerAddress;
quint16 qmlServerPort;
QString projectBuildDir;
QString projectDir;
- // for cpp+qml debugging
+
+ // Used by combined cpp+qml debugging.
DebuggerEngineType cppEngineType;
- // for remote debugging
+ // Used by remote debugging.
QString remoteChannel;
QString remoteArchitecture;
+ QString gnuTarget;
QString symbolFileName;
bool useServerStartScript;
QString serverStartScript;
@@ -121,9 +125,9 @@ DEBUGGER_EXPORT QDebug operator<<(QDebug str, DebuggerState state);
namespace Internal {
-class DisassemblerViewAgent;
-class MemoryViewAgent;
-class Symbol;
+class DebuggerPluginPrivate;
+class DisassemblerAgent;
+class MemoryAgent;
class WatchData;
class BreakHandler;
class ModulesHandler;
@@ -133,15 +137,54 @@ class StackFrame;
class SourceFilesHandler;
class ThreadsHandler;
class WatchHandler;
-class BreakpointData;
+class BreakpointParameters;
+class QmlCppEngine;
struct WatchUpdateFlags
{
WatchUpdateFlags() : tryIncremental(false) {}
bool tryIncremental;
};
+
+class Location
+{
+public:
+ Location() { init(); }
+ Location(quint64 address) { init(); m_address = address; }
+ Location(const QString &file) { init(); m_fileName = file; }
+ Location(const QString &file, int line, bool marker = true)
+ { init(); m_lineNumber = line; m_fileName = file; m_needsMarker = marker; }
+ Location(const StackFrame &frame, bool marker = true) //: m_frame(frame)
+ { init(); m_fileName = frame.file; m_lineNumber = frame.line;
+ m_needsMarker = marker; m_functionName = frame.function;
+ m_hasDebugInfo = frame.isUsable(); m_address = frame.address; }
+ QString fileName() const { return m_fileName; }
+ QString functionName() const { return m_functionName; }
+ int lineNumber() const { return m_lineNumber; }
+ void setNeedsRaise(bool on) { m_needsRaise = on; }
+ void setNeedsMarker(bool on) { m_needsMarker = on; }
+ void setFileName(const QString &fileName) { m_fileName = fileName; }
+ bool needsRaise() const { return m_needsRaise; }
+ bool needsMarker() const { return m_needsMarker; }
+ bool hasDebugInfo() const { return m_hasDebugInfo; }
+ quint64 address() const { return m_address; }
+
+private:
+ void init() { m_needsMarker = false; m_needsRaise = true; m_lineNumber = -1;
+ m_address = 0; m_hasDebugInfo = true; }
+ bool m_needsMarker;
+ bool m_needsRaise;
+ bool m_hasDebugInfo;
+ int m_lineNumber;
+ QString m_fileName;
+ QString m_functionName;
+ quint64 m_address;
+};
+
+
} // namespace Internal
+
// FIXME: DEBUGGER_EXPORT?
class DEBUGGER_EXPORT DebuggerEngine : public QObject
{
@@ -151,19 +194,21 @@ public:
explicit DebuggerEngine(const DebuggerStartParameters &sp);
virtual ~DebuggerEngine();
+ typedef Internal::BreakpointId BreakpointId;
virtual void setToolTipExpression(const QPoint & mousePos,
- TextEditor::ITextEditor * editor, int cursorPos);
- void initializeFromTemplate(DebuggerEngine *other);
+ TextEditor::ITextEditor *editor, int cursorPos);
virtual void updateWatchData(const Internal::WatchData &data,
- const Internal::WatchUpdateFlags & flags = Internal::WatchUpdateFlags());
+ const Internal::WatchUpdateFlags & flags = Internal::WatchUpdateFlags());
void startDebugger(DebuggerRunControl *runControl);
- virtual bool isSessionEngine() const;
virtual void watchPoint(const QPoint &);
- virtual void fetchMemory(Internal::MemoryViewAgent *, QObject *,
+ virtual void openMemoryView(quint64 addr);
+ virtual void fetchMemory(Internal::MemoryAgent *, QObject *,
quint64 addr, quint64 length);
- virtual void fetchDisassembler(Internal::DisassemblerViewAgent *);
+ virtual void updateMemoryViews();
+ virtual void openDisassemblerView(const Internal::Location &location);
+ virtual void fetchDisassembler(Internal::DisassemblerAgent *);
virtual void activateFrame(int index);
virtual void reloadModules();
@@ -186,19 +231,26 @@ public:
virtual void createSnapshot();
virtual void updateAll();
+
+ virtual bool stateAcceptsBreakpointChanges() const { return true; }
virtual void attemptBreakpointSynchronization();
- virtual bool acceptsBreakpoint(const Internal::BreakpointData *);
- virtual void selectThread(int index);
+ virtual bool acceptsBreakpoint(BreakpointId id) const = 0;
+ virtual void insertBreakpoint(BreakpointId id); // FIXME: make pure
+ virtual void removeBreakpoint(BreakpointId id); // FIXME: make pure
+ virtual void changeBreakpoint(BreakpointId id); // FIXME: make pure
- virtual void assignValueInDebugger(const Internal::WatchData *w, const QString &expr, const QVariant &value);
+ virtual void assignValueInDebugger(const Internal::WatchData *data,
+ const QString &expr, const QVariant &value);
virtual void removeTooltip();
+ virtual void selectThread(int index);
- // Convenience
- static QMessageBox *showMessageBox
- (int icon, const QString &title, const QString &text, int buttons = 0);
+ virtual void handleRemoteSetupDone(int gdbServerPort, int qmlPort);
+ virtual void handleRemoteSetupFailed(const QString &message);
protected:
+ friend class Internal::DebuggerPluginPrivate;
virtual void detachDebugger();
+ virtual void exitDebugger();
virtual void executeStep();
virtual void executeStepOut() ;
virtual void executeNext();
@@ -208,11 +260,9 @@ protected:
virtual void continueInferior();
virtual void interruptInferior();
-
virtual void requestInterruptInferior();
virtual void executeRunToLine(const QString &fileName, int lineNumber);
-
virtual void executeRunToFunction(const QString &functionName);
virtual void executeJumpToLine(const QString &fileName, int lineNumber);
virtual void executeDebuggerCommand(const QString &command);
@@ -221,28 +271,24 @@ protected:
virtual void frameDown();
public:
- static DebuggerPlugin *plugin();
const DebuggerStartParameters &startParameters() const;
DebuggerStartParameters &startParameters();
Internal::ModulesHandler *modulesHandler() const;
- Internal::BreakHandler *breakHandler() const;
Internal::RegisterHandler *registerHandler() const;
Internal::StackHandler *stackHandler() const;
Internal::ThreadsHandler *threadsHandler() const;
Internal::WatchHandler *watchHandler() const;
Internal::SourceFilesHandler *sourceFilesHandler() const;
+ Internal::BreakHandler *breakHandler() const;
- virtual QAbstractItemModel *commandModel() const;
virtual QAbstractItemModel *modulesModel() const;
- virtual QAbstractItemModel *breakModel() const;
virtual QAbstractItemModel *registerModel() const;
virtual QAbstractItemModel *stackModel() const;
virtual QAbstractItemModel *threadsModel() const;
virtual QAbstractItemModel *localsModel() const;
virtual QAbstractItemModel *watchersModel() const;
virtual QAbstractItemModel *returnModel() const;
- //QAbstractItemModel *snapshotModel() const;
virtual QAbstractItemModel *sourceFilesModel() const;
void progressPing();
@@ -250,15 +296,6 @@ public:
void handleStartFailed();
bool debuggerActionsEnabled() const;
static bool debuggerActionsEnabled(DebuggerState state);
- void showModuleSymbols(const QString &moduleName, const Internal::Symbols &symbols);
-
- void breakByFunction(const QString &functionName);
- void breakByFunctionMain();
-
- void executeStepX();
- void executeStepOutX();
- void executeStepNextX();
- void executeReturnX();
DebuggerState state() const;
DebuggerState lastGoodState() const;
@@ -276,22 +313,32 @@ public:
void notifyInferiorPid(qint64 pid);
qint64 inferiorPid() const;
bool isReverseDebugging() const;
- bool isActive() const; // True if this is the currently active engine;
- void setActive(bool on); // FIXME: private?
void handleCommand(int role, const QVariant &value);
// Convenience
- Q_SLOT void showMessage(const QString &msg, int channel = LogDebug, int timeout = -1) const;
+ Q_SLOT void showMessage(const QString &msg, int channel = LogDebug,
+ int timeout = -1) const;
Q_SLOT void showStatusMessage(const QString &msg, int timeout = -1) const;
void resetLocation();
- void openFile(const QString &fileName, int lineNumber = -1);
- virtual void gotoLocation(const QString &fileName, int lineNumber, bool setMarker);
- virtual void gotoLocation(const Internal::StackFrame &frame, bool setMarker);
+ virtual void gotoLocation(const Internal::Location &location);
virtual void quitDebugger(); // called by DebuggerRunControl
+ virtual void updateViews();
+ bool isSlaveEngine() const;
+
signals:
void stateChanged(const DebuggerState &state);
+ void updateViewsRequested();
+ /*
+ * For "external" clients of a debugger run control that needs to do
+ * further setup before the debugger is started (e.g. Maemo).
+ * Afterwards, handleSetupDone() or handleSetupFailed() must be called
+ * to continue or abort debugging, respectively.
+ * This signal is only emitted if the start parameters indicate that
+ * a server start script should be used, but none is given.
+ */
+ void requestRemoteSetup();
protected:
// The base notify*() function implementation should be sufficient
@@ -336,20 +383,30 @@ protected:
virtual void shutdownInferior() = 0;
virtual void shutdownEngine() = 0;
- void setState(DebuggerState state, bool forced = false);
- void setRunInWrapperEngine(bool value);
+ DebuggerRunControl *runControl() const; // FIXME: Protect.
protected:
- DebuggerRunControl *runControl() const;
+ static QString msgWatchpointTriggered(BreakpointId id,
+ int number, quint64 address);
+ static QString msgWatchpointTriggered(BreakpointId id,
+ int number, quint64 address, const QString &threadId);
+ static QString msgBreakpointTriggered(BreakpointId id,
+ int number, const QString &threadId);
+ static QString msgStopped(const QString &reason = QString());
+ static QString msgStoppedBySignal(const QString &meaning, const QString &name);
+ static QString msgStoppedByException(const QString &description,
+ const QString &threadId);
+ static QString msgInterrupted();
+ void showStoppedBySignalMessageBox(const QString meaning, QString name);
+ void showStoppedByExceptionMessageBox(const QString &description);
+
+ static bool isCppBreakpoint(const Internal::BreakpointParameters &p);
private:
- void executeRunToLine();
- void executeRunToFunction();
- void executeJumpToLine();
- void addToWatchWindow();
-
- // wrapper engine needs access to state of its subengines
- friend class QmlCppEngine;
+ // Wrapper engine needs access to state of its subengines.
+ friend class Internal::QmlCppEngine;
+ void setState(DebuggerState state, bool forced = false);
+ void setSlaveEngine(bool value);
friend class DebuggerEnginePrivate;
DebuggerEnginePrivate *d;
diff --git a/src/plugins/debugger/debuggermainwindow.cpp b/src/plugins/debugger/debuggermainwindow.cpp
index 1edaf7ad1f..5a1586daff 100644
--- a/src/plugins/debugger/debuggermainwindow.cpp
+++ b/src/plugins/debugger/debuggermainwindow.cpp
@@ -32,56 +32,704 @@
**************************************************************************/
#include "debuggermainwindow.h"
-#include "debuggeruiswitcher.h"
+#include "debuggercore.h"
-#include <QtGui/QMenu>
-#include <QtGui/QDockWidget>
+#include <utils/styledbar.h>
+#include <utils/qtcassert.h>
+#include <utils/fancymainwindow.h>
+
+#include <coreplugin/actionmanager/actioncontainer.h>
+#include <coreplugin/actionmanager/actionmanager.h>
+#include <coreplugin/actionmanager/command.h>
+#include <coreplugin/uniqueidmanager.h>
+#include <coreplugin/imode.h>
+#include <coreplugin/coreconstants.h>
+#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/findplaceholder.h>
+#include <coreplugin/icore.h>
+#include <coreplugin/minisplitter.h>
+#include <coreplugin/navigationwidget.h>
+#include <coreplugin/outputpane.h>
+#include <coreplugin/rightpane.h>
+
+#include <projectexplorer/project.h>
+#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/runconfiguration.h>
+#include <projectexplorer/session.h>
+#include <projectexplorer/target.h>
#include <QtCore/QDebug>
+#include <QtCore/QList>
+#include <QtCore/QMap>
+#include <QtCore/QPair>
+#include <QtCore/QSettings>
+
+#include <QtGui/QDockWidget>
+#include <QtGui/QMenu>
+#include <QtGui/QResizeEvent>
+#include <QtGui/QStackedWidget>
+#include <QtGui/QVBoxLayout>
+
+using namespace Core;
+using namespace ProjectExplorer;
+using namespace Debugger::Constants;
namespace Debugger {
namespace Internal {
-DebuggerMainWindow::DebuggerMainWindow(DebuggerUISwitcher *uiSwitcher, QWidget *parent) :
- FancyMainWindow(parent), m_uiSwitcher(uiSwitcher)
+class DockWidgetEventFilter : public QObject
+{
+public:
+ DockWidgetEventFilter(DebuggerMainWindowPrivate *mw) : m_mw(mw) {}
+private:
+ virtual bool eventFilter(QObject *obj, QEvent *event);
+ DebuggerMainWindowPrivate *m_mw;
+};
+
+class DebuggerMainWindowPrivate : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit DebuggerMainWindowPrivate(DebuggerMainWindow *mainWindow);
+
+ void activateQmlCppLayout();
+ void activateCppLayout();
+ void createViewsMenuItems();
+ bool isQmlCppActive() const;
+ bool isQmlActive() const;
+ void setSimpleDockWidgetArrangement();
+ // Debuggable languages are registered with this function.
+ void addLanguage(const DebuggerLanguage &language, const Core::Context &context);
+
+
+public slots:
+ void resetDebuggerLayout();
+ void updateUiForProject(ProjectExplorer::Project *project);
+ void updateUiForTarget(ProjectExplorer::Target *target);
+ void updateUiForRunConfiguration(ProjectExplorer::RunConfiguration *rc);
+ void updateUiForCurrentRunConfiguration();
+ void updateActiveLanguages();
+ void updateUiOnFileListChange();
+ void updateDockWidgetSettings();
+ void openMemoryEditor() { debuggerCore()->openMemoryEditor(); }
+
+public:
+ DebuggerMainWindow *q;
+ QList<QDockWidget *> m_dockWidgets;
+
+ QHash<QString, QVariant> m_dockWidgetActiveStateCpp;
+ QHash<QString, QVariant> m_dockWidgetActiveStateQmlCpp;
+ DockWidgetEventFilter m_resizeEventFilter;
+
+ QMap<DebuggerLanguage, QWidget *> m_toolBars;
+
+ DebuggerLanguages m_supportedLanguages;
+
+ QStackedWidget *m_toolbarStack;
+
+ QHash<DebuggerLanguage, Context> m_contextsForLanguage;
+
+ bool m_inDebugMode;
+ bool m_changingUI;
+
+ DebuggerLanguages m_previousDebugLanguages;
+ DebuggerLanguages m_activeDebugLanguages;
+
+ ActionContainer *m_viewsMenu;
+
+ QWeakPointer<Project> m_previousProject;
+ QWeakPointer<Target> m_previousTarget;
+ QWeakPointer<RunConfiguration> m_previousRunConfiguration;
+};
+
+DebuggerMainWindowPrivate::DebuggerMainWindowPrivate(DebuggerMainWindow *mw)
+ : q(mw)
+ , m_resizeEventFilter(this)
+ , m_supportedLanguages(AnyLanguage)
+ , m_toolbarStack(new QStackedWidget)
+ , m_inDebugMode(false)
+ , m_changingUI(false)
+ , m_previousDebugLanguages(AnyLanguage)
+ , m_activeDebugLanguages(AnyLanguage)
+ , m_viewsMenu(0)
+{
+ createViewsMenuItems();
+ addLanguage(CppLanguage, Context(C_CPPDEBUGGER));
+ addLanguage(QmlLanguage, Context(C_QMLDEBUGGER));
+}
+
+void DebuggerMainWindowPrivate::updateUiOnFileListChange()
+{
+ if (m_previousProject)
+ updateUiForTarget(m_previousProject.data()->activeTarget());
+}
+
+void DebuggerMainWindowPrivate::updateUiForProject(Project *project)
+{
+ if (!project)
+ return;
+ if (m_previousProject) {
+ disconnect(m_previousProject.data(),
+ SIGNAL(activeTargetChanged(ProjectExplorer::Target*)),
+ this, SLOT(updateUiForTarget(ProjectExplorer::Target*)));
+ }
+ m_previousProject = project;
+ connect(project, SIGNAL(fileListChanged()),
+ SLOT(updateUiOnFileListChange()));
+ connect(project, SIGNAL(activeTargetChanged(ProjectExplorer::Target*)),
+ SLOT(updateUiForTarget(ProjectExplorer::Target*)));
+ updateUiForTarget(project->activeTarget());
+}
+
+void DebuggerMainWindowPrivate::updateUiForTarget(Target *target)
+{
+ if (!target)
+ return;
+
+ if (m_previousTarget) {
+ disconnect(m_previousTarget.data(),
+ SIGNAL(activeRunConfigurationChanged(ProjectExplorer::RunConfiguration*)),
+ this, SLOT(updateUiForRunConfiguration(ProjectExplorer::RunConfiguration*)));
+ }
+ m_previousTarget = target;
+ connect(target,
+ SIGNAL(activeRunConfigurationChanged(ProjectExplorer::RunConfiguration*)),
+ SLOT(updateUiForRunConfiguration(ProjectExplorer::RunConfiguration*)));
+ updateUiForRunConfiguration(target->activeRunConfiguration());
+}
+
+// updates default debug language settings per run config.
+void DebuggerMainWindowPrivate::updateUiForRunConfiguration(RunConfiguration *rc)
+{
+ if (!rc)
+ return;
+ if (m_previousRunConfiguration)
+ disconnect(m_previousRunConfiguration.data(), SIGNAL(debuggersChanged()),
+ this, SLOT(updateUiForCurrentRunConfiguration()));
+ m_previousRunConfiguration = rc;
+ connect(m_previousRunConfiguration.data(),
+ SIGNAL(debuggersChanged()),
+ SLOT(updateUiForCurrentRunConfiguration()));
+ updateUiForCurrentRunConfiguration();
+}
+
+void DebuggerMainWindowPrivate::updateUiForCurrentRunConfiguration()
+{
+ updateActiveLanguages();
+}
+
+void DebuggerMainWindowPrivate::updateActiveLanguages()
{
- // TODO how to "append" style sheet?
- // QString sheet;
- // After setting it, all prev. style stuff seem to be ignored.
- /* sheet = QLatin1String(
- "Debugger--DebuggerMainWindow::separator {"
- " background: black;"
- " width: 1px;"
- " height: 1px;"
- "}"
- );
- setStyleSheet(sheet);
- */
+ DebuggerLanguages newLanguages = AnyLanguage;
+
+ if (m_previousRunConfiguration) {
+ if (m_previousRunConfiguration.data()->useCppDebugger())
+ newLanguages = CppLanguage;
+ if (m_previousRunConfiguration.data()->useQmlDebugger())
+ newLanguages |= QmlLanguage;
+ }
+
+ if (newLanguages != m_activeDebugLanguages) {
+ m_activeDebugLanguages = newLanguages;
+ debuggerCore()->languagesChanged();
+ }
+
+ if (m_changingUI || !m_inDebugMode)
+ return;
+
+ m_changingUI = true;
+
+ if (isQmlActive())
+ activateQmlCppLayout();
+ else
+ activateCppLayout();
+
+ m_previousDebugLanguages = m_activeDebugLanguages;
+
+ m_changingUI = false;
+}
+
+} // namespace Internal
+
+using namespace Internal;
+
+DebuggerMainWindow::DebuggerMainWindow()
+{
+ d = new DebuggerMainWindowPrivate(this);
}
DebuggerMainWindow::~DebuggerMainWindow()
{
+ delete d;
+}
+DebuggerLanguages DebuggerMainWindow::activeDebugLanguages() const
+{
+ return d->m_activeDebugLanguages;
}
-QMenu* DebuggerMainWindow::createPopupMenu()
+void DebuggerMainWindow::onModeChanged(IMode *mode)
{
- QMenu *menu = 0;
+ d->m_inDebugMode = (mode->id() == Constants::MODE_DEBUG);
+ setDockActionsVisible(d->m_inDebugMode);
- const QList<QDockWidget* > dockwidgets = m_uiSwitcher->i_mw_dockWidgets();
+ // Hide all the debugger windows if mode is different.
+ if (mode->id() == Constants::MODE_DEBUG) {
+ readSettings();
+ d->updateActiveLanguages();
+ } else {
+ // Hide dock widgets manually in case they are floating.
+ foreach (QDockWidget *dockWidget, d->m_dockWidgets) {
+ if (dockWidget->isFloating())
+ dockWidget->hide();
+ }
+ }
+}
- if (!dockwidgets.isEmpty()) {
- menu = FancyMainWindow::createPopupMenu();
+void DebuggerMainWindowPrivate::createViewsMenuItems()
+{
+ ICore *core = ICore::instance();
+ ActionManager *am = core->actionManager();
+ Context globalcontext(Core::Constants::C_GLOBAL);
+ m_viewsMenu = am->actionContainer(Id(Core::Constants::M_WINDOW_VIEWS));
+ QTC_ASSERT(m_viewsMenu, return)
+
+ QAction *openMemoryEditorAction = new QAction(this);
+ openMemoryEditorAction->setText(tr("Memory..."));
+ connect(openMemoryEditorAction, SIGNAL(triggered()),
+ SLOT(openMemoryEditor()));
+
+ // Add menu items
+ Command *cmd = 0;
+ cmd = am->registerAction(openMemoryEditorAction,
+ Core::Id("Debugger.Views.OpenMemoryEditor"),
+ Core::Context(Constants::C_DEBUGMODE));
+ m_viewsMenu->addAction(cmd);
+ cmd = am->registerAction(q->menuSeparator1(),
+ Core::Id("Debugger.Views.Separator1"), globalcontext);
+ m_viewsMenu->addAction(cmd);
+ cmd = am->registerAction(q->toggleLockedAction(),
+ Core::Id("Debugger.Views.ToggleLocked"), globalcontext);
+ m_viewsMenu->addAction(cmd);
+ cmd = am->registerAction(q->menuSeparator2(),
+ Core::Id("Debugger.Views.Separator2"), globalcontext);
+ m_viewsMenu->addAction(cmd);
+ cmd = am->registerAction(q->resetLayoutAction(),
+ Core::Id("Debugger.Views.ResetSimple"), globalcontext);
+ m_viewsMenu->addAction(cmd);
+}
+
+void DebuggerMainWindowPrivate::addLanguage(const DebuggerLanguage &languageId,
+ const Context &context)
+{
+ m_supportedLanguages = m_supportedLanguages | languageId;
+ m_toolBars.insert(languageId, 0);
+ m_contextsForLanguage.insert(languageId, context);
+}
+
+void DebuggerMainWindowPrivate::activateQmlCppLayout()
+{
+ ICore *core = ICore::instance();
+ Context qmlCppContext = m_contextsForLanguage.value(QmlLanguage);
+ qmlCppContext.add(m_contextsForLanguage.value(CppLanguage));
+
+ // always use cpp toolbar
+ m_toolbarStack->setCurrentWidget(m_toolBars.value(CppLanguage));
+
+ if (m_previousDebugLanguages & QmlLanguage) {
+ m_dockWidgetActiveStateQmlCpp = q->saveSettings();
+ core->updateAdditionalContexts(qmlCppContext, Context());
+ } else if (m_previousDebugLanguages & CppLanguage) {
+ m_dockWidgetActiveStateCpp = q->saveSettings();
+ core->updateAdditionalContexts(m_contextsForLanguage.value(CppLanguage),
+ Context());
+ }
+
+ q->restoreSettings(m_dockWidgetActiveStateQmlCpp);
+ core->updateAdditionalContexts(Context(), qmlCppContext);
+}
+
+void DebuggerMainWindowPrivate::activateCppLayout()
+{
+ ICore *core = ICore::instance();
+ Context qmlCppContext = m_contextsForLanguage.value(QmlLanguage);
+ qmlCppContext.add(m_contextsForLanguage.value(CppLanguage));
+ m_toolbarStack->setCurrentWidget(m_toolBars.value(CppLanguage));
+
+ if (m_previousDebugLanguages & QmlLanguage) {
+ m_dockWidgetActiveStateQmlCpp = q->saveSettings();
+ core->updateAdditionalContexts(qmlCppContext, Context());
+ } else if (m_previousDebugLanguages & CppLanguage) {
+ m_dockWidgetActiveStateCpp = q->saveSettings();
+ core->updateAdditionalContexts(m_contextsForLanguage.value(CppLanguage),
+ Context());
+ }
+
+ q->restoreSettings(m_dockWidgetActiveStateCpp);
+
+ const Context &cppContext = m_contextsForLanguage.value(CppLanguage);
+ core->updateAdditionalContexts(Context(), cppContext);
+}
+
+void DebuggerMainWindow::setToolbar(const DebuggerLanguage &language, QWidget *widget)
+{
+ Q_ASSERT(d->m_toolBars.contains(language));
+ d->m_toolBars[language] = widget;
+ d->m_toolbarStack->addWidget(widget);
+}
+
+QDockWidget *DebuggerMainWindow::dockWidget(const QString &objectName) const
+{
+ foreach (QDockWidget *dockWidget, d->m_dockWidgets) {
+ if (dockWidget->objectName() == objectName)
+ return dockWidget;
+ }
+ return 0;
+}
+
+bool DebuggerMainWindow::isDockVisible(const QString &objectName) const
+{
+ QDockWidget *dock = dockWidget(objectName);
+ return dock && dock->toggleViewAction()->isChecked();
+}
+
+/*!
+ Keep track of dock widgets so they can be shown/hidden for different languages
+*/
+QDockWidget *DebuggerMainWindow::createDockWidget(const DebuggerLanguage &language,
+ QWidget *widget)
+{
+// qDebug() << "CREATE DOCK" << widget->objectName() << "LANGUAGE ID" << language
+// << "VISIBLE BY DEFAULT" << ((d->m_activeDebugLanguages & language) ? "true" : "false");
+ QDockWidget *dockWidget = addDockForWidget(widget);
+ dockWidget->setObjectName(widget->objectName());
+ addDockWidget(Qt::BottomDockWidgetArea, dockWidget);
+ d->m_dockWidgets.append(dockWidget);
+
+ if (!(d->m_activeDebugLanguages & language))
+ dockWidget->hide();
+
+ Context globalContext(Core::Constants::C_GLOBAL);
+
+ ActionManager *am = ICore::instance()->actionManager();
+ QAction *toggleViewAction = dockWidget->toggleViewAction();
+ Command *cmd = am->registerAction(toggleViewAction,
+ QString("Debugger." + widget->objectName()), globalContext);
+ cmd->setAttribute(Command::CA_Hide);
+ d->m_viewsMenu->addAction(cmd);
+
+ dockWidget->installEventFilter(&d->m_resizeEventFilter);
+
+ connect(dockWidget->toggleViewAction(), SIGNAL(triggered(bool)),
+ d, SLOT(updateDockWidgetSettings()));
+ connect(dockWidget, SIGNAL(topLevelChanged(bool)),
+ d, SLOT(updateDockWidgetSettings()));
+ connect(dockWidget, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)),
+ d, SLOT(updateDockWidgetSettings()));
+
+ return dockWidget;
+}
+
+QWidget *DebuggerMainWindow::createContents(IMode *mode)
+{
+ ICore *core = ICore::instance();
+ ActionManager *am = core->actionManager();
+ ProjectExplorerPlugin *pe = ProjectExplorerPlugin::instance();
+ connect(pe->session(), SIGNAL(startupProjectChanged(ProjectExplorer::Project*)),
+ d, SLOT(updateUiForProject(ProjectExplorer::Project*)));
+
+ d->m_viewsMenu = am->actionContainer(Core::Id(Core::Constants::M_WINDOW_VIEWS));
+ QTC_ASSERT(d->m_viewsMenu, return 0)
+
+ //d->m_mainWindow = new Internal::DebuggerMainWindow(this);
+ setDocumentMode(true);
+ setDockNestingEnabled(true);
+ connect(this, SIGNAL(resetLayout()),
+ d, SLOT(resetDebuggerLayout()));
+ connect(toggleLockedAction(), SIGNAL(triggered()),
+ d, SLOT(updateDockWidgetSettings()));
+
+ QBoxLayout *editorHolderLayout = new QVBoxLayout;
+ editorHolderLayout->setMargin(0);
+ editorHolderLayout->setSpacing(0);
+
+ QWidget *editorAndFindWidget = new QWidget;
+ editorAndFindWidget->setLayout(editorHolderLayout);
+ editorHolderLayout->addWidget(new EditorManagerPlaceHolder(mode));
+ editorHolderLayout->addWidget(new FindToolBarPlaceHolder(editorAndFindWidget));
+
+ MiniSplitter *documentAndRightPane = new MiniSplitter;
+ documentAndRightPane->addWidget(editorAndFindWidget);
+ documentAndRightPane->addWidget(new RightPanePlaceHolder(mode));
+ documentAndRightPane->setStretchFactor(0, 1);
+ documentAndRightPane->setStretchFactor(1, 0);
+
+ Utils::StyledBar *debugToolBar = new Utils::StyledBar;
+ debugToolBar->setProperty("topBorder", true);
+ QHBoxLayout *debugToolBarLayout = new QHBoxLayout(debugToolBar);
+ debugToolBarLayout->setMargin(0);
+ debugToolBarLayout->setSpacing(0);
+ debugToolBarLayout->addWidget(d->m_toolbarStack);
+ debugToolBarLayout->addStretch();
+ debugToolBarLayout->addWidget(new Utils::StyledSeparator);
+
+ QDockWidget *dock = new QDockWidget(tr("Debugger Toolbar"));
+ dock->setObjectName(QLatin1String("Debugger Toolbar"));
+ dock->setWidget(debugToolBar);
+ dock->setFeatures(QDockWidget::NoDockWidgetFeatures);
+ dock->setAllowedAreas(Qt::BottomDockWidgetArea);
+ dock->setTitleBarWidget(new QWidget(dock));
+ addDockWidget(Qt::BottomDockWidgetArea, dock);
+ setToolBarDockWidget(dock);
+
+ QWidget *centralWidget = new QWidget;
+ setCentralWidget(centralWidget);
+
+ QVBoxLayout *centralLayout = new QVBoxLayout(centralWidget);
+ centralWidget->setLayout(centralLayout);
+ centralLayout->setMargin(0);
+ centralLayout->setSpacing(0);
+ centralLayout->addWidget(documentAndRightPane);
+ centralLayout->setStretch(0, 1);
+ centralLayout->setStretch(1, 0);
+
+ // Right-side window with editor, output etc.
+ MiniSplitter *mainWindowSplitter = new MiniSplitter;
+ mainWindowSplitter->addWidget(this);
+ QWidget *outputPane = new OutputPanePlaceHolder(mode, mainWindowSplitter);
+ outputPane->setObjectName(QLatin1String("DebuggerOutputPanePlaceHolder"));
+ mainWindowSplitter->addWidget(outputPane);
+ mainWindowSplitter->setStretchFactor(0, 10);
+ mainWindowSplitter->setStretchFactor(1, 0);
+ mainWindowSplitter->setOrientation(Qt::Vertical);
+
+ // Navigation and right-side window.
+ MiniSplitter *splitter = new MiniSplitter;
+ splitter->addWidget(new NavigationWidgetPlaceHolder(mode));
+ splitter->addWidget(mainWindowSplitter);
+ splitter->setStretchFactor(0, 0);
+ splitter->setStretchFactor(1, 1);
+ return splitter;
+}
+
+void DebuggerMainWindow::writeSettings() const
+{
+ ICore *core = ICore::instance();
+ QTC_ASSERT(core, return);
+ QSettings *settings = core->settings();
+ QTC_ASSERT(settings, return);
+
+ settings->beginGroup(QLatin1String("DebugMode.CppMode"));
+ QHashIterator<QString, QVariant> it(d->m_dockWidgetActiveStateCpp);
+ while (it.hasNext()) {
+ it.next();
+ settings->setValue(it.key(), it.value());
+ }
+ settings->endGroup();
+
+ settings->beginGroup(QLatin1String("DebugMode.CppQmlMode"));
+ it = QHashIterator<QString, QVariant>(d->m_dockWidgetActiveStateQmlCpp);
+ while (it.hasNext()) {
+ it.next();
+ settings->setValue(it.key(), it.value());
+ }
+ settings->endGroup();
+}
+
+void DebuggerMainWindow::readSettings()
+{
+ ICore *core = ICore::instance();
+ QTC_ASSERT(core, return);
+ QSettings *settings = core->settings();
+ QTC_ASSERT(settings, return);
+
+ d->m_dockWidgetActiveStateCpp.clear();
+ d->m_dockWidgetActiveStateQmlCpp.clear();
+
+ settings->beginGroup(QLatin1String("DebugMode.CppMode"));
+ foreach (const QString &key, settings->childKeys())
+ d->m_dockWidgetActiveStateCpp.insert(key, settings->value(key));
+ settings->endGroup();
+
+ settings->beginGroup(QLatin1String("DebugMode.CppQmlMode"));
+ foreach (const QString &key, settings->childKeys())
+ d->m_dockWidgetActiveStateQmlCpp.insert(key, settings->value(key));
+ settings->endGroup();
+
+ // Reset initial settings when there are none yet.
+ if (d->isQmlActive()) {
+ if (d->m_dockWidgetActiveStateQmlCpp.isEmpty()) {
+ d->m_activeDebugLanguages = DebuggerLanguage(QmlLanguage|CppLanguage);
+ d->setSimpleDockWidgetArrangement();
+ d->m_dockWidgetActiveStateCpp = saveSettings();
+ }
+ } else {
+ if (d->m_dockWidgetActiveStateCpp.isEmpty()) {
+ d->m_activeDebugLanguages = CppLanguage;
+ d->setSimpleDockWidgetArrangement();
+ d->m_dockWidgetActiveStateCpp = saveSettings();
+ }
+ }
+ writeSettings();
+}
+
+void DebuggerMainWindowPrivate::resetDebuggerLayout()
+{
+ setSimpleDockWidgetArrangement();
+
+ if (isQmlActive())
+ m_dockWidgetActiveStateQmlCpp = q->saveSettings();
+ else
+ m_dockWidgetActiveStateCpp = q->saveSettings();
+
+ updateActiveLanguages();
+}
+
+void DebuggerMainWindowPrivate::updateDockWidgetSettings()
+{
+ if (!m_inDebugMode || m_changingUI)
+ return;
- foreach (QDockWidget *dockWidget, dockwidgets) {
+ if (isQmlActive())
+ m_dockWidgetActiveStateQmlCpp = q->saveSettings();
+ else
+ m_dockWidgetActiveStateCpp = q->saveSettings();
+}
+
+bool DebuggerMainWindowPrivate::isQmlCppActive() const
+{
+ return (m_activeDebugLanguages & CppLanguage)
+ && (m_activeDebugLanguages & QmlLanguage);
+}
+
+bool DebuggerMainWindowPrivate::isQmlActive() const
+{
+ return (m_activeDebugLanguages & QmlLanguage);
+}
+
+QMenu *DebuggerMainWindow::createPopupMenu()
+{
+ QMenu *menu = 0;
+ if (!d->m_dockWidgets.isEmpty()) {
+ menu = FancyMainWindow::createPopupMenu();
+ foreach (QDockWidget *dockWidget, d->m_dockWidgets)
if (dockWidget->parentWidget() == this)
menu->addAction(dockWidget->toggleViewAction());
- }
menu->addSeparator();
}
-
return menu;
}
-} // namespace Internal
+void DebuggerMainWindowPrivate::setSimpleDockWidgetArrangement()
+{
+ using namespace Constants;
+ QTC_ASSERT(q, return);
+ q->setTrackingEnabled(false);
+
+ foreach (QDockWidget *dockWidget, m_dockWidgets) {
+ dockWidget->setFloating(false);
+ q->removeDockWidget(dockWidget);
+ }
+
+ foreach (QDockWidget *dockWidget, m_dockWidgets) {
+ int area = Qt::BottomDockWidgetArea;
+ QVariant p = dockWidget->property(DOCKWIDGET_DEFAULT_AREA);
+ if (p.isValid())
+ area = Qt::DockWidgetArea(p.toInt());
+ q->addDockWidget(Qt::DockWidgetArea(area), dockWidget);
+ dockWidget->hide();
+ }
+
+ QDockWidget *breakDock = q->dockWidget(DOCKWIDGET_BREAK);
+ QDockWidget *stackDock = q->dockWidget(DOCKWIDGET_STACK);
+ QDockWidget *watchDock = q->dockWidget(DOCKWIDGET_WATCHERS);
+ QDockWidget *snapshotsDock = q->dockWidget(DOCKWIDGET_SNAPSHOTS);
+ QDockWidget *threadsDock = q->dockWidget(DOCKWIDGET_THREADS);
+ QDockWidget *outputDock = q->dockWidget(DOCKWIDGET_OUTPUT);
+ QDockWidget *qmlInspectorDock = q->dockWidget(DOCKWIDGET_QML_INSPECTOR);
+ QDockWidget *scriptConsoleDock = q->dockWidget(DOCKWIDGET_QML_SCRIPTCONSOLE);
+ QDockWidget *modulesDock = q->dockWidget(DOCKWIDGET_MODULES);
+ QDockWidget *registerDock = q->dockWidget(DOCKWIDGET_REGISTER);
+ QDockWidget *sourceFilesDock = q->dockWidget(DOCKWIDGET_SOURCE_FILES);
+
+ QTC_ASSERT(breakDock, return);
+ QTC_ASSERT(stackDock, return);
+ QTC_ASSERT(watchDock, return);
+ QTC_ASSERT(snapshotsDock, return);
+ QTC_ASSERT(threadsDock, return);
+ QTC_ASSERT(outputDock, return);
+ //QTC_ASSERT(qmlInspectorDock, return); // This is really optional.
+ QTC_ASSERT(scriptConsoleDock, return);
+ QTC_ASSERT(modulesDock, return);
+ QTC_ASSERT(registerDock, return);
+ QTC_ASSERT(sourceFilesDock, return);
+
+ if (m_activeDebugLanguages.testFlag(Debugger::CppLanguage)
+ && m_activeDebugLanguages.testFlag(Debugger::QmlLanguage)) {
+
+ // cpp + qml
+ stackDock->show();
+ watchDock->show();
+ breakDock->show();
+ if (qmlInspectorDock)
+ qmlInspectorDock->show();
+
+ q->splitDockWidget(q->toolBarDockWidget(), stackDock, Qt::Vertical);
+ q->splitDockWidget(stackDock, breakDock, Qt::Horizontal);
+ q->tabifyDockWidget(stackDock, snapshotsDock);
+ q->tabifyDockWidget(stackDock, threadsDock);
+ if (qmlInspectorDock)
+ q->splitDockWidget(stackDock, qmlInspectorDock, Qt::Horizontal);
+
+ } else {
+
+ stackDock->show();
+ breakDock->show();
+ watchDock->show();
+ threadsDock->show();
+ snapshotsDock->show();
+
+ if ((m_activeDebugLanguages.testFlag(CppLanguage)
+ && !m_activeDebugLanguages.testFlag(QmlLanguage))
+ || m_activeDebugLanguages == AnyLanguage) {
+ threadsDock->show();
+ snapshotsDock->show();
+ } else {
+ scriptConsoleDock->show();
+ //if (qmlInspectorDock)
+ // qmlInspectorDock->show();
+ }
+ q->splitDockWidget(q->toolBarDockWidget(), stackDock, Qt::Vertical);
+ q->splitDockWidget(stackDock, breakDock, Qt::Horizontal);
+ q->tabifyDockWidget(breakDock, modulesDock);
+ q->tabifyDockWidget(breakDock, registerDock);
+ q->tabifyDockWidget(breakDock, threadsDock);
+ q->tabifyDockWidget(breakDock, sourceFilesDock);
+ q->tabifyDockWidget(breakDock, snapshotsDock);
+ q->tabifyDockWidget(breakDock, scriptConsoleDock);
+ //if (qmlInspectorDock)
+ // q->splitDockWidget(breakDock, qmlInspectorDock, Qt::Horizontal);
+ }
+
+ q->setTrackingEnabled(true);
+ q->update();
+}
+
+bool DockWidgetEventFilter::eventFilter(QObject *obj, QEvent *event)
+{
+ switch (event->type()) {
+ case QEvent::Resize:
+ case QEvent::ZOrderChange:
+ m_mw->updateDockWidgetSettings();
+ break;
+ default:
+ break;
+ }
+ return QObject::eventFilter(obj, event);
+}
+
} // namespace Debugger
+
+#include "debuggermainwindow.moc"
diff --git a/src/plugins/debugger/debuggermainwindow.h b/src/plugins/debugger/debuggermainwindow.h
index cf996a0a1c..d42f8bcd15 100644
--- a/src/plugins/debugger/debuggermainwindow.h
+++ b/src/plugins/debugger/debuggermainwindow.h
@@ -31,34 +31,58 @@
**
**************************************************************************/
-#ifndef DEBUGGERMAINWINDOW_H
-#define DEBUGGERMAINWINDOW_H
+#ifndef DEBUGGERUISWITCHER_H
+#define DEBUGGERUISWITCHER_H
-#include <utils/fancymainwindow.h>
+#include "debugger_global.h"
#include "debuggerconstants.h"
-QT_FORWARD_DECLARE_CLASS(QMenu);
+#include <utils/fancymainwindow.h>
+
+namespace Core {
+class Context;
+class IMode;
+}
namespace Debugger {
-class DebuggerUISwitcher;
namespace Internal {
+class DebuggerMainWindowPrivate;
+}
-class DebuggerMainWindow : public Utils::FancyMainWindow
+class DEBUGGER_EXPORT DebuggerMainWindow : public Utils::FancyMainWindow
{
- Q_OBJECT
public:
- explicit DebuggerMainWindow(DebuggerUISwitcher *uiSwitcher, QWidget *parent = 0);
- virtual ~DebuggerMainWindow();
+ DebuggerMainWindow();
+ ~DebuggerMainWindow();
+
+ // Debugger toolbars are registered with this function.
+ void setToolbar(const DebuggerLanguage &language, QWidget *widget);
+
+ // Active languages to be debugged.
+ DebuggerLanguages activeDebugLanguages() const;
+
+ // Called when all dependent plugins have loaded.
+ void initialize();
+
+ void onModeChanged(Core::IMode *mode);
+ QDockWidget *dockWidget(const QString &objectName) const;
+ bool isDockVisible(const QString &objectName) const;
+
+ // Dockwidgets are registered to the main window.
+ QDockWidget *createDockWidget(const DebuggerLanguage &language, QWidget *widget);
+
+ QWidget *createContents(Core::IMode *mode);
+ QMenu *createPopupMenu();
-protected:
- virtual QMenu *createPopupMenu();
+ void readSettings();
+ void writeSettings() const;
private:
- DebuggerUISwitcher *m_uiSwitcher;
+ friend class Internal::DebuggerMainWindowPrivate;
+ Internal::DebuggerMainWindowPrivate *d;
};
-} // namespace Internal
} // namespace Debugger
-#endif // DEBUGGERMAINWINDOW_H
+#endif // DEBUGGERUISWITCHER_H
diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp
index ff29fe9133..264e68a419 100644
--- a/src/plugins/debugger/debuggerplugin.cpp
+++ b/src/plugins/debugger/debuggerplugin.cpp
@@ -34,38 +34,35 @@
#include "debuggerplugin.h"
#include "debuggeractions.h"
-#include "debuggeragents.h"
#include "debuggerconstants.h"
+#include "debuggercore.h"
#include "debuggerdialogs.h"
#include "debuggerengine.h"
#include "debuggermainwindow.h"
-#include "debuggerplugin.h"
#include "debuggerrunner.h"
#include "debuggerstringutils.h"
#include "debuggertooltip.h"
-#include "debuggeruiswitcher.h"
+#include "breakpoint.h"
+#include "breakhandler.h"
#include "breakwindow.h"
#include "consolewindow.h"
+#include "disassembleragent.h"
#include "logwindow.h"
#include "moduleswindow.h"
#include "registerwindow.h"
#include "snapshotwindow.h"
+#include "stackhandler.h"
#include "stackwindow.h"
#include "sourcefileswindow.h"
#include "threadswindow.h"
+#include "watchhandler.h"
#include "watchwindow.h"
+#include "watchutils.h"
-#include "breakhandler.h"
-#include "sessionengine.h"
#include "snapshothandler.h"
#include "threadshandler.h"
-#include "watchutils.h"
-
-#ifdef Q_OS_WIN
-# include "shared/peutils.h"
-#endif
-
+#include "gdb/gdboptionspage.h"
#include "ui_commonoptionspage.h"
#include "ui_dumperoptionpage.h"
@@ -73,7 +70,8 @@
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/command.h>
-#include <coreplugin/basemode.h>
+#include <coreplugin/uniqueidmanager.h>
+#include <coreplugin/imode.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/dialogs/ioptionspage.h>
#include <coreplugin/editormanager/editormanager.h>
@@ -83,15 +81,8 @@
#include <coreplugin/imode.h>
#include <coreplugin/icorelistener.h>
#include <coreplugin/manhattanstyle.h>
-#include <coreplugin/messagemanager.h>
#include <coreplugin/minisplitter.h>
#include <coreplugin/modemanager.h>
-#include <coreplugin/navigationwidget.h>
-#include <coreplugin/outputpane.h>
-#include <coreplugin/rightpane.h>
-
-#include <cplusplus/ExpressionUnderCursor.h>
-#include <cplusplus/CppDocument.h>
#include <cppeditor/cppeditorconstants.h>
#include <cpptools/cppmodelmanagerinterface.h>
@@ -103,56 +94,31 @@
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/session.h>
#include <projectexplorer/target.h>
-#include <projectexplorer/toolchain.h>
+#include <projectexplorer/toolchaintype.h>
+
+#include <qt4projectmanager/qt4projectmanagerconstants.h>
#include <texteditor/basetexteditor.h>
-#include <texteditor/basetextmark.h>
#include <texteditor/fontsettings.h>
-#include <texteditor/itexteditor.h>
-#include <texteditor/texteditorconstants.h>
#include <texteditor/texteditorsettings.h>
-//#include <qt4projectmanager/qt4projectmanagerconstants.h>
-
#include <utils/qtcassert.h>
#include <utils/savedaction.h>
#include <utils/styledbar.h>
#include <qml/scriptconsole.h>
-#include <QtCore/QCoreApplication>
-#include <QtCore/QDebug>
-#include <QtCore/QDir>
-#include <QtCore/QFileInfo>
-#include <QtCore/QObject>
-#include <QtCore/QPoint>
-#include <QtCore/QSettings>
-#include <QtCore/QTextStream>
-#include <QtCore/QTime>
#include <QtCore/QTimer>
-#include <QtCore/QVariant>
#include <QtCore/QtPlugin>
-#include <QtCore/QScopedPointer>
-
-#include <QtGui/QAbstractItemView>
-#include <QtGui/QAction>
-#include <QtGui/QApplication>
#include <QtGui/QComboBox>
#include <QtGui/QDockWidget>
-#include <QtGui/QErrorMessage>
#include <QtGui/QFileDialog>
-#include <QtGui/QHeaderView>
-#include <QtGui/QLabel>
-#include <QtGui/QLineEdit>
#include <QtGui/QMenu>
#include <QtGui/QMessageBox>
-#include <QtGui/QPlainTextEdit>
#include <QtGui/QPushButton>
-#include <QtGui/QStatusBar>
#include <QtGui/QTextBlock>
#include <QtGui/QTextCursor>
#include <QtGui/QToolButton>
-#include <QtGui/QToolTip>
#include <QtGui/QTreeWidget>
#include <climits>
@@ -224,7 +190,7 @@
// | (core) | (attach) | | +
// | | | | +
// {notify- {notifyER&- {notifyER&- {notify- +
-// Inferior- Inferior- Inferior- RunEngine- +
+// Inferior- Inferior- Inferior- EngineRun- +
// Unrunnable} StopOk} RunOk} Failed} +
// + + + + +
// InferiorUnrunnable + InferiorRunOk + +
@@ -234,7 +200,7 @@
// `-+-+-+-+-+-+-+-+-+-+-+>-+
// +
// +
-// #Interupt@InferiorRunOk# +
+// #Interrupt@InferiorRunOk# +
// + +
// InferiorStopRequested +
// #SpontaneousStop + +
@@ -273,16 +239,19 @@
// * * +
// EngineShutdownRequested +
// + +
-// (calls *Engine->shutdownEngine()) <+-+-+-+-+-+-+-+-+-+-+-+-+-+'
-// | |
-// | |
-// {notify- {notify-
+// (calls *Engine->shutdownEngine()) <+-+-+-+-+-+-+-+-+-+-+-+-+-+'
+// | |
+// | |
+// {notify- {notify-
// Engine- Engine-
-// ShutdownOk} ShutdownFailed}
-// + +
-// EngineShutdownOk EngineShutdownFailed
+// ShutdownOk} ShutdownFailed}
+// + +
+// EngineShutdownOk EngineShutdownFailed
// * *
// DebuggerFinished
+//
+
+
/* Here is a matching graph as a GraphViz graph. View it using
* \code
grep "^sg1:" debuggerplugin.cpp | cut -c5- | dot -osg1.ps -Tps && gv sg1.ps
@@ -343,7 +312,7 @@ sg1: }
//
//
// GdbEngine::setupInferior()
-// +
+// +
// (calls *Adapter->prepareInferior())
// | |
// | `---> handlePrepareInferiorFailed()
@@ -352,7 +321,7 @@ sg1: }
// |
// handleInferiorPrepared()
// +
-// {notifyInferiorSetupOk}
+// {notifyInferiorSetupOk}
@@ -360,7 +329,6 @@ sg1: }
using namespace Core;
using namespace Debugger::Constants;
-using namespace Debugger::Internal;
using namespace ProjectExplorer;
using namespace TextEditor;
@@ -378,6 +346,8 @@ const char * const ATTACHEXTERNAL = "Debugger.AttachExternal";
const char * const ATTACHCORE = "Debugger.AttachCore";
const char * const ATTACHTCF = "Debugger.AttachTcf";
const char * const ATTACHREMOTE = "Debugger.AttachRemote";
+const char * const ATTACHREMOTECDB = "Debugger.AttachRemoteCDB";
+const char * const STARTREMOTELLDB = "Debugger.StartRemoteLLDB";
const char * const DETACH = "Debugger.Detach";
const char * const RUN_TO_LINE1 = "Debugger.RunToLine1";
@@ -429,45 +399,58 @@ const char * const SNAPSHOT_KEY = "Ctrl+D,Ctrl+S";
#endif
} // namespace Constants
-} // namespace Debugger
-
-
-static SessionManager *sessionManager()
-{
- return ProjectExplorerPlugin::instance()->session();
-}
-static QSettings *settings()
-{
- return ICore::instance()->settings();
-}
+namespace Cdb {
+void addCdb2OptionPages(QList<Core::IOptionsPage*> *);
+} // namespace Cdb
-static QToolButton *toolButton(QAction *action)
-{
- QToolButton *button = new QToolButton;
- button->setDefaultAction(action);
- return button;
-}
-namespace Debugger {
namespace Internal {
-static const char *Role = "ROLE";
-
// FIXME: Outdated?
// The createCdbEngine function takes a list of options pages it can add to.
// This allows for having a "enabled" toggle on the page independently
// of the engine. That's good for not enabling the related ActiveX control
// unnecessarily.
-void addGdbOptionPages(QList<Core::IOptionsPage*> *opts);
-void addScriptOptionPages(QList<Core::IOptionsPage*> *opts);
-void addTcfOptionPages(QList<Core::IOptionsPage*> *opts);
+void addGdbOptionPages(QList<IOptionsPage*> *opts);
+void addScriptOptionPages(QList<IOptionsPage*> *opts);
+void addTcfOptionPages(QList<IOptionsPage*> *opts);
#ifdef CDB_ENABLED
-void addCdbOptionPages(QList<Core::IOptionsPage*> *opts);
+void addCdbOptionPages(QList<IOptionsPage*> *opts);
+#endif
+
+#ifdef WITH_LLDB
+void addLldbOptionPages(QList<IOptionsPage*> *opts);
#endif
+static SessionManager *sessionManager()
+{
+ return ProjectExplorerPlugin::instance()->session();
+}
+
+static QToolButton *toolButton(QAction *action)
+{
+ QToolButton *button = new QToolButton;
+ button->setDefaultAction(action);
+ return button;
+}
+
+// Retrieve file name and line and optionally address
+// from the data set on the text editor context menu action.
+static bool positionFromActionData(const QObject *sender,
+ QString *fileName, int *lineNumber, quint64 *address)
+{
+ const QAction *action = qobject_cast<const QAction *>(sender);
+ QTC_ASSERT(action, return false);
+ const QVariantList data = action->data().toList();
+ QTC_ASSERT(data.size() == 3, return false);
+ *fileName = data.front().toString();
+ *lineNumber = data.at(1).toInt();
+ *address = data.at(2).toULongLong();
+ return true;
+}
struct AttachRemoteParameters
{
@@ -476,7 +459,7 @@ struct AttachRemoteParameters
quint64 attachPid;
QString attachTarget; // core file name or server:port
- // Event handle for attaching to crashed Windows processes.
+ // Event handle for attaching to crashed Windows processes.
quint64 winCrashEvent;
};
@@ -486,49 +469,68 @@ void AttachRemoteParameters::clear()
attachTarget.clear();
}
+
///////////////////////////////////////////////////////////////////////
//
-// DebugMode
+// DummyEngine
//
///////////////////////////////////////////////////////////////////////
-class DebugMode : public Core::BaseMode
+class DummyEngine : public DebuggerEngine
{
-public:
- DebugMode(QObject *parent = 0) : BaseMode(parent)
- {
- setDisplayName(QCoreApplication::translate("Debugger::Internal::DebugMode", "Debug"));
- setType(Core::Constants::MODE_EDIT_TYPE);
- setId(MODE_DEBUG);
- setIcon(QIcon(__(":/fancyactionbar/images/mode_Debug.png")));
- setPriority(P_MODE_DEBUG);
- }
+ Q_OBJECT
- ~DebugMode()
- {
- // Make sure the editor manager does not get deleted.
- EditorManager::instance()->setParent(0);
- }
+public:
+ DummyEngine() : DebuggerEngine(DebuggerStartParameters()) {}
+ ~DummyEngine() {}
+
+ void setupEngine() {}
+ void setupInferior() {}
+ void runEngine() {}
+ void shutdownEngine() {}
+ void shutdownInferior() {}
+ void executeDebuggerCommand(const QString &) {}
+ unsigned debuggerCapabilities() const { return 0; }
+ bool acceptsBreakpoint(BreakpointId) const { return false; }
};
+static DebuggerEngine *dummyEngine()
+{
+ static DummyEngine dummy;
+ return &dummy;
+}
+
+
///////////////////////////////////////////////////////////////////////
//
-// LocationMark
+// DebugMode
//
///////////////////////////////////////////////////////////////////////
-// Used in "real" editors
-class LocationMark : public TextEditor::BaseTextMark
+class DebugMode : public IMode
{
public:
- LocationMark(const QString &fileName, int linenumber)
- : BaseTextMark(fileName, linenumber)
- {}
-
- QIcon icon() const { return DebuggerPlugin::instance()->locationMarkIcon(); }
- void updateLineNumber(int /*lineNumber*/) {}
- void updateBlock(const QTextBlock & /*block*/) {}
- void removedFromEditor() {}
+ DebugMode() : m_widget(0) { setObjectName(QLatin1String("DebugMode")); }
+
+ ~DebugMode()
+ {
+ // Make sure the editor manager does not get deleted.
+ //EditorManager::instance()->setParent(0);
+ delete m_widget;
+ }
+
+ // IMode
+ QString displayName() const { return DebuggerPlugin::tr("Debug"); }
+ QIcon icon() const { return QIcon(__(":/fancyactionbar/images/mode_Debug.png")); }
+ int priority() const { return P_MODE_DEBUG; }
+ QWidget *widget();
+ QString id() const { return MODE_DEBUG; }
+ QString type() const { return CC::MODE_EDIT_TYPE; }
+ Context context() const
+ { return Context(CC::C_EDITORMANAGER, C_DEBUGMODE, CC::C_NAVIGATION_PANE); }
+ QString contextHelpId() const { return QString(); }
+private:
+ QWidget *m_widget;
};
@@ -556,7 +558,7 @@ public:
{ return QIcon(QLatin1String(DEBUGGER_COMMON_SETTINGS_CATEGORY_ICON)); }
QWidget *createPage(QWidget *parent);
- void apply() { m_group.apply(settings()); }
+ void apply() { m_group.apply(ICore::instance()->settings()); }
void finish() { m_group.finish(); }
virtual bool matches(const QString &s) const;
@@ -572,32 +574,32 @@ QWidget *CommonOptionsPage::createPage(QWidget *parent)
m_ui.setupUi(w);
m_group.clear();
- m_group.insert(theDebuggerAction(ListSourceFiles),
+ m_group.insert(debuggerCore()->action(ListSourceFiles),
m_ui.checkBoxListSourceFiles);
- m_group.insert(theDebuggerAction(UseAlternatingRowColors),
+ m_group.insert(debuggerCore()->action(UseAlternatingRowColors),
m_ui.checkBoxUseAlternatingRowColors);
- m_group.insert(theDebuggerAction(UseToolTipsInMainEditor),
+ m_group.insert(debuggerCore()->action(UseToolTipsInMainEditor),
m_ui.checkBoxUseToolTipsInMainEditor);
- m_group.insert(theDebuggerAction(CloseBuffersOnExit),
+ m_group.insert(debuggerCore()->action(CloseBuffersOnExit),
m_ui.checkBoxCloseBuffersOnExit);
- m_group.insert(theDebuggerAction(SwitchModeOnExit),
+ m_group.insert(debuggerCore()->action(SwitchModeOnExit),
m_ui.checkBoxSwitchModeOnExit);
- m_group.insert(theDebuggerAction(AutoDerefPointers), 0);
- m_group.insert(theDebuggerAction(UseToolTipsInLocalsView), 0);
- m_group.insert(theDebuggerAction(UseToolTipsInBreakpointsView), 0);
- m_group.insert(theDebuggerAction(UseAddressInBreakpointsView), 0);
- m_group.insert(theDebuggerAction(UseAddressInStackView), 0);
- m_group.insert(theDebuggerAction(MaximalStackDepth),
+ m_group.insert(debuggerCore()->action(AutoDerefPointers), 0);
+ m_group.insert(debuggerCore()->action(UseToolTipsInLocalsView), 0);
+ m_group.insert(debuggerCore()->action(UseToolTipsInBreakpointsView), 0);
+ m_group.insert(debuggerCore()->action(UseAddressInBreakpointsView), 0);
+ m_group.insert(debuggerCore()->action(UseAddressInStackView), 0);
+ m_group.insert(debuggerCore()->action(MaximalStackDepth),
m_ui.spinBoxMaximalStackDepth);
- m_group.insert(theDebuggerAction(ShowStdNamespace), 0);
- m_group.insert(theDebuggerAction(ShowQtNamespace), 0);
- m_group.insert(theDebuggerAction(SortStructMembers), 0);
- m_group.insert(theDebuggerAction(LogTimeStamps), 0);
- m_group.insert(theDebuggerAction(VerboseLog), 0);
- m_group.insert(theDebuggerAction(BreakOnThrow), 0);
- m_group.insert(theDebuggerAction(BreakOnCatch), 0);
+ m_group.insert(debuggerCore()->action(ShowStdNamespace), 0);
+ m_group.insert(debuggerCore()->action(ShowQtNamespace), 0);
+ m_group.insert(debuggerCore()->action(SortStructMembers), 0);
+ m_group.insert(debuggerCore()->action(LogTimeStamps), 0);
+ m_group.insert(debuggerCore()->action(VerboseLog), 0);
+ m_group.insert(debuggerCore()->action(BreakOnThrow), 0);
+ m_group.insert(debuggerCore()->action(BreakOnCatch), 0);
#ifdef Q_OS_WIN
- Utils::SavedAction *registerAction = theDebuggerAction(RegisterForPostMortem);
+ Utils::SavedAction *registerAction = debuggerCore()->action(RegisterForPostMortem);
m_group.insert(registerAction,
m_ui.checkBoxRegisterForPostMortem);
connect(registerAction, SIGNAL(toggled(bool)),
@@ -605,14 +607,18 @@ QWidget *CommonOptionsPage::createPage(QWidget *parent)
#endif
if (m_searchKeywords.isEmpty()) {
- QTextStream(&m_searchKeywords) << ' '
- << m_ui.checkBoxListSourceFiles->text()
- << ' ' << m_ui.checkBoxUseAlternatingRowColors->text()
- << ' ' << m_ui.checkBoxUseToolTipsInMainEditor->text()
+ QLatin1Char sep(' ');
+ QTextStream(&m_searchKeywords)
+ << sep << m_ui.checkBoxUseAlternatingRowColors->text()
+ << sep << m_ui.checkBoxUseToolTipsInMainEditor->text()
+ << sep << m_ui.checkBoxListSourceFiles->text()
#ifdef Q_OS_WIN
- << ' ' << m_ui.checkBoxRegisterForPostMortem->text()
+ << sep << m_ui.checkBoxRegisterForPostMortem->text()
#endif
- << ' ' << m_ui.labelMaximalStackDepth->text();
+ << sep << m_ui.checkBoxCloseBuffersOnExit->text()
+ << sep << m_ui.checkBoxSwitchModeOnExit->text()
+ << sep << m_ui.labelMaximalStackDepth->text()
+ ;
m_searchKeywords.remove(QLatin1Char('&'));
}
#ifndef Q_OS_WIN
@@ -632,16 +638,15 @@ bool CommonOptionsPage::matches(const QString &s) const
//
///////////////////////////////////////////////////////////////////////
-static inline bool oxygenStyle()
+static bool oxygenStyle()
{
- if (const ManhattanStyle *ms = qobject_cast<const ManhattanStyle *>(qApp->style()))
- return !qstrcmp("OxygenStyle", ms->baseStyle()->metaObject()->className());
- return false;
+ const ManhattanStyle *ms = qobject_cast<const ManhattanStyle *>(qApp->style());
+ return ms && !qstrcmp("OxygenStyle", ms->baseStyle()->metaObject()->className());
}
class DebuggingHelperOptionPage : public Core::IOptionsPage
-{ // Needs tr - context
- Q_OBJECT
+{
+ Q_OBJECT // Needs tr-context.
public:
DebuggingHelperOptionPage() {}
@@ -655,7 +660,7 @@ public:
{ return QIcon(QLatin1String(DEBUGGER_COMMON_SETTINGS_CATEGORY_ICON)); }
QWidget *createPage(QWidget *parent);
- void apply() { m_group.apply(settings()); }
+ void apply() { m_group.apply(ICore::instance()->settings()); }
void finish() { m_group.finish(); }
virtual bool matches(const QString &s) const;
@@ -673,33 +678,26 @@ QWidget *DebuggingHelperOptionPage::createPage(QWidget *parent)
m_ui.dumperLocationChooser->setExpectedKind(Utils::PathChooser::Command);
m_ui.dumperLocationChooser->setPromptDialogTitle(tr("Choose DebuggingHelper Location"));
m_ui.dumperLocationChooser->setInitialBrowsePathBackup(
- Core::ICore::instance()->resourcePath() + "../../lib");
+ ICore::instance()->resourcePath() + "../../lib");
m_group.clear();
- m_group.insert(theDebuggerAction(UseDebuggingHelpers),
+ m_group.insert(debuggerCore()->action(UseDebuggingHelpers),
m_ui.debuggingHelperGroupBox);
- m_group.insert(theDebuggerAction(UseCustomDebuggingHelperLocation),
+ m_group.insert(debuggerCore()->action(UseCustomDebuggingHelperLocation),
m_ui.customLocationGroupBox);
// Suppress Oxygen style's giving flat group boxes bold titles.
if (oxygenStyle())
m_ui.customLocationGroupBox->setStyleSheet(_("QGroupBox::title { font: ; }"));
- m_group.insert(theDebuggerAction(CustomDebuggingHelperLocation),
+ m_group.insert(debuggerCore()->action(CustomDebuggingHelperLocation),
m_ui.dumperLocationChooser);
- m_group.insert(theDebuggerAction(UseCodeModel),
+ m_group.insert(debuggerCore()->action(UseCodeModel),
m_ui.checkBoxUseCodeModel);
-#ifdef QT_DEBUG
- m_group.insert(theDebuggerAction(DebugDebuggingHelpers),
- m_ui.checkBoxDebugDebuggingHelpers);
-#else
- m_ui.checkBoxDebugDebuggingHelpers->hide();
-#endif
-
#ifndef QT_DEBUG
#if 0
- cmd = am->registerAction(m_manager->m_dumpLogAction,
+ cmd = am->registerAction(m_dumpLogAction,
DUMP_LOG, globalcontext);
//cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+D,Ctrl+L")));
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+F11")));
@@ -712,8 +710,7 @@ QWidget *DebuggingHelperOptionPage::createPage(QWidget *parent)
<< ' ' << m_ui.debuggingHelperGroupBox->title()
<< ' ' << m_ui.customLocationGroupBox->title()
<< ' ' << m_ui.dumperLocationLabel->text()
- << ' ' << m_ui.checkBoxUseCodeModel->text()
- << ' ' << m_ui.checkBoxDebugDebuggingHelpers->text();
+ << ' ' << m_ui.checkBoxUseCodeModel->text();
m_searchKeywords.remove(QLatin1Char('&'));
}
return w;
@@ -780,25 +777,29 @@ static bool parseArgument(QStringList::const_iterator &it,
}
// Engine disabling.
if (option == _("-disable-cdb")) {
- *enabledEngines &= ~Debugger::CdbEngineType;
+ *enabledEngines &= ~CdbEngineType;
return true;
}
if (option == _("-disable-gdb")) {
- *enabledEngines &= ~Debugger::GdbEngineType;
+ *enabledEngines &= ~GdbEngineType;
return true;
}
if (option == _("-disable-qmldb")) {
- *enabledEngines &= ~Debugger::QmlEngineType;
+ *enabledEngines &= ~QmlEngineType;
return true;
}
if (option == _("-disable-sdb")) {
- *enabledEngines &= ~Debugger::ScriptEngineType;
+ *enabledEngines &= ~ScriptEngineType;
return true;
}
if (option == _("-disable-tcf")) {
*enabledEngines &= ~TcfEngineType;
return true;
}
+ if (option == _("-disable-lldb")) {
+ *enabledEngines &= ~LldbEngineType;
+ return true;
+ }
*errorMessage = DebuggerPlugin::tr("Invalid debugger option: %1").arg(option);
return false;
@@ -813,7 +814,7 @@ static bool parseArguments(const QStringList &args,
for (QStringList::const_iterator it = args.constBegin(); it != cend; ++it)
if (!parseArgument(it, cend, attachRemoteParameters, enabledEngines, errorMessage))
return false;
- if (Debugger::Constants::Internal::debug)
+ if (Constants::Internal::debug)
qDebug().nospace() << args << "engines=0x"
<< QString::number(*enabledEngines, 16)
<< " pid" << attachRemoteParameters->attachPid
@@ -828,50 +829,38 @@ static bool parseArguments(const QStringList &args,
//
///////////////////////////////////////////////////////////////////////
-static bool isDebuggable(Core::IEditor *editor)
+static bool isDebuggable(IEditor *editor)
{
// Only blacklist Qml. Whitelisting would fail on C++ code in files
// with strange names, more harm would be done this way.
- //Core::IFile *file = editor->file();
- //return !(file && file->mimeType() == "application/x-qml");
-
+ // IFile *file = editor->file();
+ // return !(file && file->mimeType() == "application/x-qml");
// Nowadays, even Qml is debuggable.
- Q_UNUSED(editor);
- return true;
+ return editor;
}
-static TextEditor::ITextEditor *currentTextEditor()
-{
- EditorManager *editorManager = EditorManager::instance();
- if (!editorManager)
- return 0;
- Core::IEditor *editor = editorManager->currentEditor();
- return qobject_cast<ITextEditor*>(editor);
-}
///////////////////////////////////////////////////////////////////////
//
-// DebuggerPluginPrivate
+// Debugger Actions
//
///////////////////////////////////////////////////////////////////////
struct DebuggerActions
{
QAction *continueAction;
- QAction *stopAction; // on the application output button if "Stop" is possible
+ QAction *exitAction; // on the application output button if "Stop" is possible
QAction *interruptAction; // on the fat debug button if "Pause" is possible
QAction *undisturbableAction; // on the fat debug button if nothing can be done
QAction *resetAction; // FIXME: Should not be needed in a stable release
QAction *stepAction;
QAction *stepOutAction;
- QAction *runToLineAction1; // in the Debug menu
- QAction *runToLineAction2; // in the text editor context menu
+ QAction *runToLineAction; // Debug menu
QAction *runToFunctionAction;
- QAction *jumpToLineAction1; // in the Debug menu
- QAction *jumpToLineAction2; // in the text editor context menu
+ QAction *jumpToLineAction; // in the Debug menu
QAction *returnFromFunctionAction;
QAction *nextAction;
- QAction *snapshotAction;
+ //QAction *snapshotAction;
QAction *watchAction1; // in the Debug menu
QAction *watchAction2; // in the text editor context menu
QAction *breakAction;
@@ -881,9 +870,8 @@ struct DebuggerActions
QAction *frameDownAction;
};
-} // namespace Internal
+static DebuggerPluginPrivate *theDebuggerCore = 0;
-using namespace Debugger::Internal;
///////////////////////////////////////////////////////////////////////
//
@@ -891,31 +879,101 @@ using namespace Debugger::Internal;
//
///////////////////////////////////////////////////////////////////////
-class DebuggerPluginPrivate : public QObject
+class DebuggerPluginPrivate : public DebuggerCore
{
Q_OBJECT
public:
explicit DebuggerPluginPrivate(DebuggerPlugin *plugin);
+ ~DebuggerPluginPrivate();
bool initialize(const QStringList &arguments, QString *errorMessage);
- void notifyCurrentEngine(int role, const QVariant &value = QVariant());
- void connectEngine(DebuggerEngine *engine, bool notify = true);
- void disconnectEngine() { connectEngine(m_sessionEngine); }
+ void extensionsInitialized();
+ void aboutToShutdown();
+
+ void connectEngine(DebuggerEngine *engine);
+ void disconnectEngine() { connectEngine(0); }
+ DebuggerEngine *currentEngine() const { return m_currentEngine; }
public slots:
+ void selectThread(int index)
+ {
+ currentEngine()->selectThread(index);
+ }
+
+ void breakpointSetMarginActionTriggered()
+ {
+ QString fileName;
+ int lineNumber;
+ quint64 address;
+ if (positionFromActionData(sender(), &fileName, &lineNumber, &address)) {
+ if (address)
+ toggleBreakpointByAddress(address);
+ else
+ toggleBreakpointByFileAndLine(fileName, lineNumber);
+ }
+ }
+
+ void breakpointRemoveMarginActionTriggered()
+ {
+ const QAction *act = qobject_cast<QAction *>(sender());
+ QTC_ASSERT(act, return);
+ m_breakHandler->removeBreakpoint(act->data().toInt());
+ }
+
+ void breakpointEnableMarginActionTriggered()
+ {
+ const QAction *act = qobject_cast<QAction *>(sender());
+ QTC_ASSERT(act, return);
+ breakHandler()->setEnabled(act->data().toInt(), true);
+ }
+
+ void breakpointDisableMarginActionTriggered()
+ {
+ const QAction *act = qobject_cast<QAction *>(sender());
+ QTC_ASSERT(act, return);
+ breakHandler()->setEnabled(act->data().toInt(), false);
+ }
+
void updateWatchersHeader(int section, int, int newSize)
- { m_watchersWindow->header()->resizeSection(section, newSize); }
+ {
+ m_watchersWindow->header()->resizeSection(section, newSize);
+ }
void sourceFilesDockToggled(bool on)
- { if (on) notifyCurrentEngine(RequestReloadSourceFilesRole); }
+ {
+ if (on && m_currentEngine->state() == InferiorStopOk)
+ m_currentEngine->reloadSourceFiles();
+ }
+
void modulesDockToggled(bool on)
- { if (on) notifyCurrentEngine(RequestReloadModulesRole); }
+ {
+ if (on && m_currentEngine->state() == InferiorStopOk)
+ m_currentEngine->reloadModules();
+ }
+
void registerDockToggled(bool on)
- { if (on) notifyCurrentEngine(RequestReloadRegistersRole); }
+ {
+ if (on && m_currentEngine->state() == InferiorStopOk)
+ m_currentEngine->reloadRegisters();
+ }
- void onAction();
- void setSimpleDockWidgetArrangement(const Debugger::DebuggerLanguages &activeLanguages);
+ void synchronizeBreakpoints()
+ {
+ showMessage("ATTEMPT SYNC", LogDebug);
+ for (int i = 0, n = m_snapshotHandler->size(); i != n; ++i) {
+ if (DebuggerEngine *engine = m_snapshotHandler->at(i))
+ engine->attemptBreakpointSynchronization();
+ }
+ }
+
+ void synchronizeWatchers()
+ {
+ for (int i = 0, n = m_snapshotHandler->size(); i != n; ++i) {
+ if (DebuggerEngine *engine = m_snapshotHandler->at(i))
+ engine->watchHandler()->updateWatchers();
+ }
+ }
void editorOpened(Core::IEditor *editor);
void editorAboutToClose(Core::IEditor *editor);
@@ -928,12 +986,16 @@ public slots:
void activatePreviousMode();
void activateDebugMode();
void toggleBreakpoint();
- void toggleBreakpoint(const QString &fileName, int lineNumber);
+ void toggleBreakpointByFileAndLine(const QString &fileName, int lineNumber);
+ void toggleBreakpointByAddress(quint64 address);
void onModeChanged(Core::IMode *mode);
void showSettingsDialog();
+ void debugProject();
void startExternalApplication();
+ void startRemoteCdbSession();
void startRemoteApplication();
+ void startRemoteEngine();
void attachExternalApplication();
void attachExternalApplication
(qint64 pid, const QString &binary, const QString &crashParameter);
@@ -944,16 +1006,33 @@ public slots:
void attachRemoteTcf();
void enableReverseDebuggingTriggered(const QVariant &value);
- void languagesChanged(const Debugger::DebuggerLanguages &languages);
+ void languagesChanged();
void showStatusMessage(const QString &msg, int timeout = -1);
void openMemoryEditor();
- DebuggerMainWindow *mainWindow()
- { return qobject_cast<DebuggerMainWindow*>
- (DebuggerUISwitcher::instance()->mainWindow()); }
+ const CPlusPlus::Snapshot &cppCodeModelSnapshot() const;
+
+ void showQtDumperLibraryWarning(const QString &details);
+ DebuggerMainWindow *mainWindow() const { return m_mainWindow; }
+ bool isDockVisible(const QString &objectName) const
+ { return mainWindow()->isDockVisible(objectName); }
+
+ bool hasSnapshots() const { return m_snapshotHandler->size(); }
+ void createNewDock(QWidget *widget);
+
+ void runControlStarted(DebuggerEngine *engine);
+ void runControlFinished(DebuggerEngine *engine);
+ DebuggerLanguages activeLanguages() const;
+ QString gdbBinaryForToolChain(int toolChain) const;
+ void remoteCommand(const QStringList &options, const QStringList &);
+
+ bool isReverseDebugging() const;
- inline void setConfigValue(const QString &name, const QVariant &value);
- inline QVariant configValue(const QString &name) const;
+ BreakHandler *breakHandler() const { return m_breakHandler; }
+ SnapshotHandler *snapshotHandler() const { return m_snapshotHandler; }
+
+ void setConfigValue(const QString &name, const QVariant &value);
+ QVariant configValue(const QString &name) const;
DebuggerRunControl *createDebugger(const DebuggerStartParameters &sp,
RunConfiguration *rc = 0);
@@ -968,10 +1047,9 @@ public slots:
DebuggerState state() const { return m_state; }
void updateState(DebuggerEngine *engine);
+ void updateWatchersWindow();
void onCurrentProjectChanged(ProjectExplorer::Project *project);
- void gotoLocation(const QString &file, int line, bool setMarker);
-
void clearStatusMessage();
void sessionLoaded();
@@ -982,33 +1060,241 @@ public slots:
void scriptExpressionEntered(const QString &expression);
void coreShutdown();
+public slots:
+ void updateDebugActions();
+
+ void handleExecDetach()
+ {
+ currentEngine()->resetLocation();
+ currentEngine()->detachDebugger();
+ }
+
+ void handleExecContinue()
+ {
+ currentEngine()->resetLocation();
+ currentEngine()->continueInferior();
+ }
+
+ void handleExecInterrupt()
+ {
+ currentEngine()->resetLocation();
+ currentEngine()->requestInterruptInferior();
+ }
+
+ void handleExecReset()
+ {
+ currentEngine()->resetLocation();
+ currentEngine()->notifyEngineIll(); // FIXME: Check.
+ }
+
+ void handleExecStep()
+ {
+ currentEngine()->resetLocation();
+ if (boolSetting(OperateByInstruction))
+ currentEngine()->executeStepI();
+ else
+ currentEngine()->executeStep();
+ }
+
+ void handleExecNext()
+ {
+ currentEngine()->resetLocation();
+ if (boolSetting(OperateByInstruction))
+ currentEngine()->executeNextI();
+ else
+ currentEngine()->executeNext();
+ }
+
+ void handleExecStepOut()
+ {
+ currentEngine()->resetLocation();
+ currentEngine()->executeStepOut();
+ }
+
+ void handleExecReturn()
+ {
+ currentEngine()->resetLocation();
+ currentEngine()->executeReturn();
+ }
+
+ void handleExecJumpToLine()
+ {
+ //removeTooltip();
+ currentEngine()->resetLocation();
+ QString fileName;
+ int lineNumber;
+ if (currentTextEditorPosition(&fileName, &lineNumber))
+ currentEngine()->executeJumpToLine(fileName, lineNumber);
+ }
+
+ void handleExecRunToLine()
+ {
+ //removeTooltip();
+ currentEngine()->resetLocation();
+ QString fileName;
+ int lineNumber;
+ if (currentTextEditorPosition(&fileName, &lineNumber))
+ currentEngine()->executeRunToLine(fileName, lineNumber);
+ }
+
+ void handleExecRunToFunction()
+ {
+ currentEngine()->resetLocation();
+ ITextEditor *textEditor = currentTextEditor();
+ QTC_ASSERT(textEditor, return);
+ QPlainTextEdit *ed = qobject_cast<QPlainTextEdit*>(textEditor->widget());
+ if (!ed)
+ return;
+ QTextCursor cursor = ed->textCursor();
+ QString functionName = cursor.selectedText();
+ if (functionName.isEmpty()) {
+ const QTextBlock block = cursor.block();
+ const QString line = block.text();
+ foreach (const QString &str, line.trimmed().split('(')) {
+ QString a;
+ for (int i = str.size(); --i >= 0; ) {
+ if (!str.at(i).isLetterOrNumber())
+ break;
+ a = str.at(i) + a;
+ }
+ if (!a.isEmpty()) {
+ functionName = a;
+ break;
+ }
+ }
+ }
+
+ if (!functionName.isEmpty())
+ currentEngine()->executeRunToFunction(functionName);
+ }
+
+ void slotEditBreakpoint()
+ {
+ const QAction *act = qobject_cast<QAction *>(sender());
+ QTC_ASSERT(act, return);
+ const BreakpointId id = act->data().toInt();
+ QTC_ASSERT(id > 0, return);
+ BreakWindow::editBreakpoint(id, mainWindow());
+ }
+
+ void slotRunToLine()
+ {
+ // Run to line, file name and line number set as list.
+ QString fileName;
+ int lineNumber;
+ quint64 address;
+ if (positionFromActionData(sender(), &fileName, &lineNumber, &address))
+ currentEngine()->executeRunToLine(fileName, lineNumber);
+ }
+
+ void slotJumpToLine()
+ {
+ QString fileName;
+ int lineNumber;
+ quint64 address;
+ if (positionFromActionData(sender(), &fileName, &lineNumber, &address))
+ currentEngine()->executeJumpToLine(fileName, lineNumber);
+ }
+
+ void handleAddToWatchWindow()
+ {
+ // Requires a selection, but that's the only case we want anyway.
+ EditorManager *editorManager = EditorManager::instance();
+ if (!editorManager)
+ return;
+ IEditor *editor = editorManager->currentEditor();
+ if (!editor)
+ return;
+ ITextEditor *textEditor = qobject_cast<ITextEditor*>(editor);
+ if (!textEditor)
+ return;
+ QTextCursor tc;
+ QPlainTextEdit *ptEdit = qobject_cast<QPlainTextEdit*>(editor->widget());
+ if (ptEdit)
+ tc = ptEdit->textCursor();
+ QString exp;
+ if (tc.hasSelection()) {
+ exp = tc.selectedText();
+ } else {
+ int line, column;
+ exp = cppExpressionAt(textEditor, tc.position(), &line, &column);
+ }
+ if (exp.isEmpty())
+ return;
+ currentEngine()->watchHandler()->watchExpression(exp);
+ }
+
+ void handleExecExit()
+ {
+ currentEngine()->exitDebugger();
+ }
+
+ void handleFrameDown()
+ {
+ currentEngine()->frameDown();
+ }
+
+ void handleFrameUp()
+ {
+ currentEngine()->frameUp();
+ }
+
+ void handleOperateByInstructionTriggered(bool operateByInstructionTriggered)
+ {
+ // Go to source only if we have the file.
+ if (currentEngine()->stackHandler()->currentIndex() >= 0) {
+ const StackFrame frame = currentEngine()->stackHandler()->currentFrame();
+ if (operateByInstructionTriggered || frame.isUsable()) {
+ currentEngine()->gotoLocation(Location(frame, true));
+ }
+ }
+ }
+
+ bool isActiveDebugLanguage(int lang) const
+ {
+ return m_mainWindow->activeDebugLanguages() & lang;
+ }
+
+ QVariant sessionValue(const QString &name);
+ void setSessionValue(const QString &name, const QVariant &value);
+ QIcon locationMarkIcon() const { return m_locationMarkIcon; }
+
+ void openTextEditor(const QString &titlePattern0, const QString &contents);
+ void clearCppCodeModelSnapshot();
+ void showMessage(const QString &msg, int channel, int timeout = -1);
+
+ Utils::SavedAction *action(int code) const;
+ bool boolSetting(int code) const;
+ QString stringSetting(int code) const;
+
+ void showModuleSymbols(const QString &moduleName, const Symbols &symbols);
+
public:
DebuggerState m_state;
- DebuggerUISwitcher *m_uiSwitcher;
- DebuggerPlugin *m_manager;
- DebugMode *m_debugMode;
+ DebuggerMainWindow *m_mainWindow;
DebuggerRunControlFactory *m_debuggerRunControlFactory;
QString m_previousMode;
- QScopedPointer<TextEditor::BaseTextMark> m_locationMark;
- Core::Context m_continuableContext;
- Core::Context m_interruptibleContext;
- Core::Context m_undisturbableContext;
- Core::Context m_finishedContext;
- Core::Context m_anyContext;
+ Context m_continuableContext;
+ Context m_interruptibleContext;
+ Context m_undisturbableContext;
+ Context m_finishedContext;
+ Context m_anyContext;
AttachRemoteParameters m_attachRemoteParameters;
+ QAction *m_debugAction;
QAction *m_startExternalAction;
QAction *m_startRemoteAction;
+ QAction *m_startRemoteCdbAction;
+ QAction *m_startRemoteLldbAction;
QAction *m_attachExternalAction;
QAction *m_attachCoreAction;
QAction *m_attachTcfAction;
QAction *m_detachAction;
- QComboBox *m_langBox;
QToolButton *m_reverseToolButton;
QIcon m_startIcon;
- QIcon m_stopIcon;
+ QIcon m_exitIcon;
QIcon m_continueIcon;
QIcon m_interruptIcon;
QIcon m_locationMarkIcon;
@@ -1016,26 +1302,14 @@ public:
QLabel *m_statusLabel;
QComboBox *m_threadBox;
- QDockWidget *m_breakDock;
- //QDockWidget *m_consoleDock;
- QDockWidget *m_modulesDock;
- QDockWidget *m_outputDock;
- QDockWidget *m_registerDock;
- QDockWidget *m_snapshotDock;
- QDockWidget *m_sourceFilesDock;
- QDockWidget *m_stackDock;
- QDockWidget *m_threadsDock;
- QDockWidget *m_watchDock;
- QDockWidget* m_scriptConsoleDock;
-
DebuggerActions m_actions;
BreakWindow *m_breakWindow;
+ BreakHandler *m_breakHandler;
//ConsoleWindow *m_consoleWindow;
QTreeView *m_returnWindow;
QTreeView *m_localsWindow;
QTreeView *m_watchersWindow;
- QTreeView *m_commandWindow;
QAbstractItemView *m_registerWindow;
QAbstractItemView *m_modulesWindow;
QAbstractItemView *m_snapshotWindow;
@@ -1045,39 +1319,36 @@ public:
LogWindow *m_logWindow;
ScriptConsole *m_scriptConsoleWindow;
- SessionEngine *m_sessionEngine;
-
bool m_busy;
QTimer m_statusTimer;
QString m_lastPermanentStatusMessage;
- CPlusPlus::Snapshot m_codeModelSnapshot;
+ mutable CPlusPlus::Snapshot m_codeModelSnapshot;
DebuggerPlugin *m_plugin;
SnapshotHandler *m_snapshotHandler;
bool m_shuttingDown;
+ DebuggerEngine *m_currentEngine;
+ DebuggerSettings *m_debuggerSettings;
+ QSettings *m_coreSettings;
+ bool m_gdbBinariesChanged;
+ uint m_cmdLineEnabledEngines;
};
-DebuggerPluginPrivate::DebuggerPluginPrivate(DebuggerPlugin *plugin) :
- m_shuttingDown(false)
+DebuggerPluginPrivate::DebuggerPluginPrivate(DebuggerPlugin *plugin)
{
+ QTC_ASSERT(!theDebuggerCore, /**/);
+ theDebuggerCore = this;
+
m_plugin = plugin;
+ m_startRemoteCdbAction = 0;
+ m_shuttingDown = false;
m_statusLabel = 0;
m_threadBox = 0;
- m_breakDock = 0;
- //m_consoleDock = 0;
- m_modulesDock = 0;
- m_outputDock = 0;
- m_registerDock = 0;
- m_snapshotDock = 0;
- m_sourceFilesDock = 0;
- m_stackDock = 0;
- m_threadsDock = 0;
- m_watchDock = 0;
-
m_breakWindow = 0;
+ m_breakHandler = 0;
m_returnWindow = 0;
m_localsWindow = 0;
m_watchersWindow = 0;
@@ -1090,640 +1361,80 @@ DebuggerPluginPrivate::DebuggerPluginPrivate(DebuggerPlugin *plugin) :
m_logWindow = 0;
m_scriptConsoleWindow = 0;
- m_sessionEngine = 0;
- m_debugMode = 0;
-
- m_continuableContext = Core::Context(0);
- m_interruptibleContext = Core::Context(0);
- m_undisturbableContext = Core::Context(0);
- m_finishedContext = Core::Context(0);
- m_anyContext = Core::Context(0);
+ m_continuableContext = Context(0);
+ m_interruptibleContext = Context(0);
+ m_undisturbableContext = Context(0);
+ m_finishedContext = Context(0);
+ m_anyContext = Context(0);
- m_debugMode = 0;
- m_uiSwitcher = 0;
+ m_mainWindow = 0;
m_state = DebuggerNotReady;
m_snapshotHandler = 0;
-}
-
-bool DebuggerPluginPrivate::initialize(const QStringList &arguments, QString *errorMessage)
-{
- m_continuableContext = Core::Context("Gdb.Continuable");
- m_interruptibleContext = Core::Context("Gdb.Interruptible");
- m_undisturbableContext = Core::Context("Gdb.Undisturbable");
- m_finishedContext = Core::Context("Gdb.Finished");
- m_anyContext.add(m_continuableContext);
- m_anyContext.add(m_interruptibleContext);
- m_anyContext.add(m_undisturbableContext);
- m_anyContext.add(m_finishedContext);
-
- // FIXME: Move part of this to extensionsInitialized()?
- ICore *core = ICore::instance();
- QTC_ASSERT(core, return false);
- connect(core, SIGNAL(coreAboutToClose()), this, SLOT(coreShutdown()));
-
- Core::ActionManager *am = core->actionManager();
- QTC_ASSERT(am, return false);
-
- const Core::Context globalcontext(CC::C_GLOBAL);
- const Core::Context cppDebuggercontext(C_CPPDEBUGGER);
- const Core::Context qmlDebuggerContext(C_QMLDEBUGGER);
- const Core::Context cppeditorcontext(CppEditor::Constants::C_CPPEDITOR);
-
- m_startIcon = QIcon(_(":/debugger/images/debugger_start_small.png"));
- m_startIcon.addFile(__(":/debugger/images/debugger_start.png"));
- m_stopIcon = QIcon(_(":/debugger/images/debugger_stop_small.png"));
- m_stopIcon.addFile(__(":/debugger/images/debugger_stop.png"));
- m_continueIcon = QIcon(__(":/debugger/images/debugger_continue_small.png"));
- m_continueIcon.addFile(__(":/debugger/images/debugger_continue.png"));
- m_interruptIcon = QIcon(_(":/debugger/images/debugger_interrupt_small.png"));
- m_interruptIcon.addFile(__(":/debugger/images/debugger_interrupt.png"));
- m_locationMarkIcon = QIcon(_(":/debugger/images/location_16.png"));
-
- m_busy = false;
-
- m_statusLabel = new QLabel;
- m_statusLabel->setMinimumSize(QSize(30, 10));
-
- m_breakWindow = new BreakWindow;
- m_breakWindow->setObjectName(QLatin1String("CppDebugBreakpoints"));
- //m_consoleWindow = new ConsoleWindow;
- //m_consoleWindow->setObjectName(QLatin1String("CppDebugConsole"));
- m_modulesWindow = new ModulesWindow;
- m_modulesWindow->setObjectName(QLatin1String("CppDebugModules"));
- m_logWindow = new LogWindow;
- m_logWindow->setObjectName(QLatin1String("CppDebugOutput"));
-
- m_registerWindow = new RegisterWindow;
- m_registerWindow->setObjectName(QLatin1String("CppDebugRegisters"));
- m_snapshotWindow = new SnapshotWindow;
- m_snapshotWindow->setObjectName(QLatin1String("CppDebugSnapshots"));
- m_stackWindow = new StackWindow;
- m_stackWindow->setObjectName(QLatin1String("CppDebugStack"));
- m_sourceFilesWindow = new SourceFilesWindow;
- m_sourceFilesWindow->setObjectName(QLatin1String("CppDebugSources"));
- m_threadsWindow = new ThreadsWindow;
- m_threadsWindow->setObjectName(QLatin1String("CppDebugThreads"));
- m_returnWindow = new WatchWindow(WatchWindow::ReturnType);
- m_returnWindow->setObjectName(QLatin1String("CppDebugReturn"));
- m_localsWindow = new WatchWindow(WatchWindow::LocalsType);
- m_localsWindow->setObjectName(QLatin1String("CppDebugLocals"));
- m_watchersWindow = new WatchWindow(WatchWindow::WatchersType);
- m_watchersWindow->setObjectName(QLatin1String("CppDebugWatchers"));
- m_commandWindow = new QTreeView;
- m_scriptConsoleWindow = new ScriptConsole;
- m_scriptConsoleWindow->setWindowTitle(tr("QML Script Console"));
- m_scriptConsoleWindow->setObjectName(QLatin1String("QMLScriptConsole"));
- connect(m_scriptConsoleWindow, SIGNAL(expressionEntered(QString)),
- SLOT(scriptExpressionEntered(QString)));
-
- // Session related data
- m_sessionEngine = new SessionEngine;
-
- // Snapshot
- m_snapshotHandler = new SnapshotHandler;
- m_snapshotWindow->setModel(m_snapshotHandler->model());
-
- // Debug mode setup
- m_debugMode = new DebugMode(this);
-
- // Watchers
- connect(m_localsWindow->header(), SIGNAL(sectionResized(int,int,int)),
- this, SLOT(updateWatchersHeader(int,int,int)), Qt::QueuedConnection);
-
- m_actions.continueAction = new QAction(tr("Continue"), this);
- m_actions.continueAction->setProperty(Role, RequestExecContinueRole);
- m_actions.continueAction->setIcon(m_continueIcon);
-
- m_actions.stopAction = new QAction(tr("Stop Debugger"), this);
- m_actions.stopAction->setProperty(Role, RequestExecExitRole);
- m_actions.stopAction->setIcon(m_stopIcon);
-
- m_actions.interruptAction = new QAction(tr("Interrupt"), this);
- m_actions.interruptAction->setIcon(m_interruptIcon);
- m_actions.interruptAction->setProperty(Role, RequestExecInterruptRole);
-
- m_actions.undisturbableAction = new QAction(tr("Debugger is Busy"), this);
- // A "disabled pause" seems to be a good choice.
- m_actions.undisturbableAction->setIcon(m_interruptIcon);
- m_actions.undisturbableAction->setEnabled(false);
-
- m_actions.resetAction = new QAction(tr("Abort Debugging"), this);
- m_actions.resetAction->setProperty(Role, RequestExecResetRole);
- m_actions.resetAction->setToolTip(tr("Aborts debugging and "
- "resets the debugger to the initial state."));
-
- m_actions.nextAction = new QAction(tr("Step Over"), this);
- m_actions.nextAction->setProperty(Role, RequestExecNextRole);
- m_actions.nextAction->setIcon(
- QIcon(__(":/debugger/images/debugger_stepover_small.png")));
-
- m_actions.stepAction = new QAction(tr("Step Into"), this);
- m_actions.stepAction->setProperty(Role, RequestExecStepRole);
- m_actions.stepAction->setIcon(
- QIcon(__(":/debugger/images/debugger_stepinto_small.png")));
-
- m_actions.stepOutAction = new QAction(tr("Step Out"), this);
- m_actions.stepOutAction->setProperty(Role, RequestExecStepOutRole);
- m_actions.stepOutAction->setIcon(
- QIcon(__(":/debugger/images/debugger_stepout_small.png")));
-
- m_actions.runToLineAction1 = new QAction(tr("Run to Line"), this);
- m_actions.runToLineAction1->setProperty(Role, RequestExecRunToLineRole);
- m_actions.runToLineAction2 = new QAction(tr("Run to Line"), this);
- m_actions.runToLineAction2->setProperty(Role, RequestExecRunToLineRole);
-
- m_actions.runToFunctionAction =
- new QAction(tr("Run to Outermost Function"), this);
- m_actions.runToFunctionAction->setProperty(Role, RequestExecRunToFunctionRole);
-
- m_actions.returnFromFunctionAction =
- new QAction(tr("Immediately Return From Inner Function"), this);
- m_actions.returnFromFunctionAction->setProperty(Role, RequestExecReturnFromFunctionRole);
-
- m_actions.jumpToLineAction1 = new QAction(tr("Jump to Line"), this);
- m_actions.jumpToLineAction1->setProperty(Role, RequestExecJumpToLineRole);
- m_actions.jumpToLineAction2 = new QAction(tr("Jump to Line"), this);
- m_actions.jumpToLineAction2->setProperty(Role, RequestExecJumpToLineRole);
-
- m_actions.breakAction = new QAction(tr("Toggle Breakpoint"), this);
-
- m_actions.watchAction1 = new QAction(tr("Add to Watch Window"), this);
- m_actions.watchAction1->setProperty(Role, RequestExecWatchRole);
- m_actions.watchAction2 = new QAction(tr("Add to Watch Window"), this);
- m_actions.watchAction2->setProperty(Role, RequestExecWatchRole);
-
- m_actions.snapshotAction = new QAction(tr("Create Snapshot"), this);
- m_actions.snapshotAction->setProperty(Role, RequestCreateSnapshotRole);
- m_actions.snapshotAction->setIcon(
- QIcon(__(":/debugger/images/debugger_snapshot_small.png")));
-
- m_actions.reverseDirectionAction =
- new QAction(tr("Reverse Direction"), this);
- m_actions.reverseDirectionAction->setCheckable(true);
- m_actions.reverseDirectionAction->setChecked(false);
- m_actions.reverseDirectionAction->setIcon(
- QIcon(__(":/debugger/images/debugger_reversemode_16.png")));
- m_actions.reverseDirectionAction->setIconVisibleInMenu(false);
-
- m_actions.frameDownAction =
- new QAction(tr("Move to Called Frame"), this);
- m_actions.frameDownAction->setProperty(Role, RequestExecFrameDownRole);
- m_actions.frameUpAction =
- new QAction(tr("Move to Calling Frame"), this);
- m_actions.frameUpAction->setProperty(Role, RequestExecFrameUpRole);
-
- m_actions.reverseDirectionAction->setCheckable(false);
- theDebuggerAction(OperateByInstruction)->
- setProperty(Role, RequestOperatedByInstructionTriggeredRole);
-
- connect(m_actions.continueAction, SIGNAL(triggered()), SLOT(onAction()));
- connect(m_actions.nextAction, SIGNAL(triggered()), SLOT(onAction()));
- connect(m_actions.stepAction, SIGNAL(triggered()), SLOT(onAction()));
- connect(m_actions.stepOutAction, SIGNAL(triggered()), SLOT(onAction()));
- connect(m_actions.runToLineAction1, SIGNAL(triggered()), SLOT(onAction()));
- connect(m_actions.runToLineAction2, SIGNAL(triggered()), SLOT(onAction()));
- connect(m_actions.runToFunctionAction, SIGNAL(triggered()), SLOT(onAction()));
- connect(m_actions.jumpToLineAction1, SIGNAL(triggered()), SLOT(onAction()));
- connect(m_actions.jumpToLineAction2, SIGNAL(triggered()), SLOT(onAction()));
- connect(m_actions.returnFromFunctionAction, SIGNAL(triggered()), SLOT(onAction()));
- connect(m_actions.watchAction1, SIGNAL(triggered()), SLOT(onAction()));
- connect(m_actions.watchAction2, SIGNAL(triggered()), SLOT(onAction()));
- connect(m_actions.snapshotAction, SIGNAL(triggered()), SLOT(onAction()));
- connect(m_actions.frameDownAction, SIGNAL(triggered()), SLOT(onAction()));
- connect(m_actions.frameUpAction, SIGNAL(triggered()), SLOT(onAction()));
- connect(m_actions.stopAction, SIGNAL(triggered()), SLOT(onAction()));
- connect(m_actions.interruptAction, SIGNAL(triggered()), SLOT(onAction()));
- connect(m_actions.resetAction, SIGNAL(triggered()), SLOT(onAction()));
- connect(&m_statusTimer, SIGNAL(timeout()), SLOT(clearStatusMessage()));
-
- connect(theDebuggerAction(ExecuteCommand), SIGNAL(triggered()),
- SLOT(executeDebuggerCommand()));
-
- connect(theDebuggerAction(OperateByInstruction), SIGNAL(triggered()),
- SLOT(onAction()));
-
- m_plugin->readSettings();
-
- // Cpp/Qml ui setup
- m_uiSwitcher = new DebuggerUISwitcher(m_debugMode, this);
- ExtensionSystem::PluginManager::instance()->addObject(m_uiSwitcher);
- m_uiSwitcher->addLanguage(CppLanguage, cppDebuggercontext);
- m_uiSwitcher->addLanguage(QmlLanguage, qmlDebuggerContext);
-
- // Dock widgets
- m_breakDock = m_uiSwitcher->createDockWidget(CppLanguage, m_breakWindow);
- m_breakDock->setObjectName(QString(DOCKWIDGET_BREAK));
+ m_currentEngine = 0;
+ m_debuggerSettings = 0;
- //m_consoleDock = m_uiSwitcher->createDockWidget(CppLanguage, m_consoleWindow,
- // Qt::TopDockWidgetArea);
- //m_consoleDock->setObjectName(QString(DOCKWIDGET_OUTPUT));
+ m_gdbBinariesChanged = true;
+ m_cmdLineEnabledEngines = AllEngineTypes;
- m_modulesDock = m_uiSwitcher->createDockWidget(CppLanguage, m_modulesWindow,
- Qt::TopDockWidgetArea);
- m_modulesDock->setObjectName(QString(DOCKWIDGET_MODULES));
- connect(m_modulesDock->toggleViewAction(), SIGNAL(toggled(bool)),
- SLOT(modulesDockToggled(bool)), Qt::QueuedConnection);
-
- m_registerDock = m_uiSwitcher->createDockWidget(CppLanguage, m_registerWindow,
- Qt::TopDockWidgetArea);
- m_registerDock->setObjectName(QString(DOCKWIDGET_REGISTER));
- connect(m_registerDock->toggleViewAction(), SIGNAL(toggled(bool)),
- SLOT(registerDockToggled(bool)), Qt::QueuedConnection);
-
- m_outputDock = m_uiSwitcher->createDockWidget(AnyLanguage, m_logWindow,
- Qt::TopDockWidgetArea);
- m_outputDock->setObjectName(QString(DOCKWIDGET_OUTPUT));
-
- m_snapshotDock = m_uiSwitcher->createDockWidget(CppLanguage, m_snapshotWindow);
- m_snapshotDock->setObjectName(QString(DOCKWIDGET_SNAPSHOTS));
-
- m_stackDock = m_uiSwitcher->createDockWidget(CppLanguage, m_stackWindow);
- m_stackDock->setObjectName(QString(DOCKWIDGET_STACK));
-
- m_sourceFilesDock = m_uiSwitcher->createDockWidget(CppLanguage,
- m_sourceFilesWindow, Qt::TopDockWidgetArea);
- m_sourceFilesDock->setObjectName(QString(DOCKWIDGET_SOURCE_FILES));
- connect(m_sourceFilesDock->toggleViewAction(), SIGNAL(toggled(bool)),
- SLOT(sourceFilesDockToggled(bool)), Qt::QueuedConnection);
+ m_reverseToolButton = 0;
+ m_debugAction = 0;
+ m_startExternalAction = 0;
+ m_startRemoteAction = 0;
+ m_startRemoteCdbAction = 0;
+ m_startRemoteLldbAction = 0;
+ m_attachExternalAction = 0;
+ m_attachCoreAction = 0;
+ m_attachTcfAction = 0;
+ m_detachAction = 0;
+}
- m_threadsDock = m_uiSwitcher->createDockWidget(CppLanguage, m_threadsWindow);
- m_threadsDock->setObjectName(QString(DOCKWIDGET_THREADS));
+DebuggerPluginPrivate::~DebuggerPluginPrivate()
+{
+ delete m_debuggerSettings;
+ m_debuggerSettings = 0;
- QSplitter *localsAndWatchers = new Core::MiniSplitter(Qt::Vertical);
- localsAndWatchers->setObjectName(QLatin1String("CppDebugLocalsAndWatchers"));
- localsAndWatchers->setWindowTitle(m_localsWindow->windowTitle());
- localsAndWatchers->addWidget(m_localsWindow);
- localsAndWatchers->addWidget(m_returnWindow);
- localsAndWatchers->addWidget(m_watchersWindow);
- localsAndWatchers->setStretchFactor(0, 3);
- localsAndWatchers->setStretchFactor(1, 1);
- localsAndWatchers->setStretchFactor(2, 1);
+ delete m_mainWindow;
+ m_mainWindow = 0;
- m_watchDock = m_uiSwitcher->createDockWidget(CppLanguage, localsAndWatchers);
- m_watchDock->setObjectName(QString(DOCKWIDGET_WATCHERS));
+ delete m_snapshotHandler;
+ m_snapshotHandler = 0;
+}
- m_scriptConsoleDock =
- m_uiSwitcher->createDockWidget(QmlLanguage, m_scriptConsoleWindow);
- m_scriptConsoleDock->setObjectName(QString(DOCKWIDGET_QML_SCRIPTCONSOLE));
+DebuggerCore *debuggerCore()
+{
+ return theDebuggerCore;
+}
- // Do not fail the whole plugin if something goes wrong here.
- uint cmdLineEnabledEngines = AllEngineTypes;
+bool DebuggerPluginPrivate::initialize(const QStringList &arguments,
+ QString *errorMessage)
+{
+ // Do not fail to load the whole plugin if something goes wrong here.
if (!parseArguments(arguments, &m_attachRemoteParameters,
- &cmdLineEnabledEngines, errorMessage)) {
+ &m_cmdLineEnabledEngines, errorMessage)) {
*errorMessage = tr("Error evaluating command line arguments: %1")
.arg(*errorMessage);
qWarning("%s\n", qPrintable(*errorMessage));
errorMessage->clear();
}
- // Register factory of DebuggerRunControl.
- m_debuggerRunControlFactory = new DebuggerRunControlFactory
- (m_plugin, DebuggerEngineType(cmdLineEnabledEngines));
- m_plugin->addAutoReleasedObject(m_debuggerRunControlFactory);
-
- m_debugMode->setContext(
- Core::Context(CC::C_EDITORMANAGER, C_DEBUGMODE, CC::C_NAVIGATION_PANE));
-
- m_reverseToolButton = 0;
-
- // Handling of external applications.
- m_startExternalAction = new QAction(this);
- m_startExternalAction->setText(tr("Start and Debug External Application..."));
- connect(m_startExternalAction, SIGNAL(triggered()),
- SLOT(startExternalApplication()));
-
- m_attachExternalAction = new QAction(this);
- m_attachExternalAction->setText(tr("Attach to Running External Application..."));
- connect(m_attachExternalAction, SIGNAL(triggered()),
- SLOT(attachExternalApplication()));
-
- m_attachCoreAction = new QAction(this);
- m_attachCoreAction->setText(tr("Attach to Core..."));
- connect(m_attachCoreAction, SIGNAL(triggered()), this, SLOT(attachCore()));
-
- m_attachTcfAction = new QAction(this);
- m_attachTcfAction->setText(tr("Attach to Running Tcf Agent..."));
- m_attachTcfAction->setToolTip(tr("This attaches to a running "
- "'Target Communication Framework' agent."));
- connect(m_attachTcfAction, SIGNAL(triggered()), SLOT(attachRemoteTcf()));
-
- m_startRemoteAction = new QAction(this);
- m_startRemoteAction->setText(tr("Start and Attach to Remote Application..."));
- connect(m_startRemoteAction, SIGNAL(triggered()),
- SLOT(startRemoteApplication()));
-
- m_detachAction = new QAction(this);
- m_detachAction->setText(tr("Detach Debugger"));
- m_detachAction->setProperty(Role, RequestExecDetachRole);
- connect(m_detachAction, SIGNAL(triggered()), SLOT(onAction()));
-
-
- Core::Command *cmd = 0;
-
- Core::ActionContainer *mstart =
- am->actionContainer(PE::M_DEBUG_STARTDEBUGGING);
-
- cmd = am->registerAction(m_actions.continueAction,
- PE::DEBUG, m_continuableContext);
- mstart->addAction(cmd, CC::G_DEFAULT_ONE);
-
- cmd = am->registerAction(m_startExternalAction,
- Constants::STARTEXTERNAL, globalcontext);
- cmd->setAttribute(Command::CA_Hide);
- mstart->addAction(cmd, CC::G_DEFAULT_ONE);
-
- cmd = am->registerAction(m_attachExternalAction,
- Constants::ATTACHEXTERNAL, globalcontext);
- cmd->setAttribute(Command::CA_Hide);
- mstart->addAction(cmd, CC::G_DEFAULT_ONE);
-
- cmd = am->registerAction(m_attachCoreAction,
- Constants::ATTACHCORE, globalcontext);
-
- cmd->setAttribute(Command::CA_Hide);
- mstart->addAction(cmd, CC::G_DEFAULT_ONE);
-
- cmd = am->registerAction(m_attachTcfAction,
- Constants::ATTACHTCF, globalcontext);
- mstart->addAction(cmd, Core::Constants::G_DEFAULT_ONE);
-
- cmd = am->registerAction(m_startRemoteAction,
- Constants::ATTACHREMOTE, globalcontext);
- cmd->setAttribute(Command::CA_Hide);
- mstart->addAction(cmd, CC::G_DEFAULT_ONE);
-
- cmd = am->registerAction(m_detachAction,
- Constants::DETACH, globalcontext);
- cmd->setAttribute(Command::CA_Hide);
- m_uiSwitcher->addMenuAction(cmd, AnyLanguage, CC::G_DEFAULT_ONE);
-
- cmd = am->registerAction(m_actions.stopAction,
- Constants::STOP, globalcontext);
- //cmd->setDefaultKeySequence(QKeySequence(Constants::STOP_KEY));
- cmd->setDefaultText(tr("Stop Debugger"));
- m_uiSwitcher->addMenuAction(cmd, AnyLanguage, CC::G_DEFAULT_ONE);
-
- cmd = am->registerAction(m_actions.interruptAction,
- PE::DEBUG, m_interruptibleContext);
- cmd->setDefaultText(tr("Interrupt Debugger"));
-
- cmd = am->registerAction(m_actions.undisturbableAction,
- PE::DEBUG, m_undisturbableContext);
- cmd->setDefaultText(tr("Debugger is Busy"));
-
- cmd = am->registerAction(m_actions.resetAction,
- Constants::RESET, globalcontext);
- //cmd->setDefaultKeySequence(QKeySequence(Constants::RESET_KEY));
- cmd->setDefaultText(tr("Reset Debugger"));
- m_uiSwitcher->addMenuAction(cmd, AnyLanguage, CC::G_DEFAULT_ONE);
-
- QAction *sep = new QAction(this);
- sep->setSeparator(true);
- cmd = am->registerAction(sep, _("Debugger.Sep.Step"), globalcontext);
- m_uiSwitcher->addMenuAction(cmd, CppLanguage);
-
- cmd = am->registerAction(m_actions.nextAction,
- Constants::NEXT, cppDebuggercontext);
- cmd->setDefaultKeySequence(QKeySequence(Constants::NEXT_KEY));
- cmd->setAttribute(Command::CA_Hide);
- m_uiSwitcher->addMenuAction(cmd, CppLanguage);
-
- cmd = am->registerAction(m_actions.stepAction,
- Constants::STEP, cppDebuggercontext);
- cmd->setDefaultKeySequence(QKeySequence(Constants::STEP_KEY));
- cmd->setAttribute(Command::CA_Hide);
- m_uiSwitcher->addMenuAction(cmd, CppLanguage);
-
-
- cmd = am->registerAction(m_actions.stepOutAction,
- Constants::STEPOUT, cppDebuggercontext);
- cmd->setDefaultKeySequence(QKeySequence(Constants::STEPOUT_KEY));
- cmd->setAttribute(Command::CA_Hide);
- m_uiSwitcher->addMenuAction(cmd, CppLanguage);
-
-
- cmd = am->registerAction(m_actions.runToLineAction1,
- Constants::RUN_TO_LINE1, cppDebuggercontext);
- cmd->setDefaultKeySequence(QKeySequence(Constants::RUN_TO_LINE_KEY));
- cmd->setAttribute(Command::CA_Hide);
- m_uiSwitcher->addMenuAction(cmd, CppLanguage);
-
-
- cmd = am->registerAction(m_actions.runToFunctionAction,
- Constants::RUN_TO_FUNCTION, cppDebuggercontext);
- cmd->setDefaultKeySequence(QKeySequence(Constants::RUN_TO_FUNCTION_KEY));
- cmd->setAttribute(Command::CA_Hide);
- m_uiSwitcher->addMenuAction(cmd, CppLanguage);
-
-
- cmd = am->registerAction(m_actions.jumpToLineAction1,
- Constants::JUMP_TO_LINE1, cppDebuggercontext);
- cmd->setAttribute(Command::CA_Hide);
- m_uiSwitcher->addMenuAction(cmd, CppLanguage);
-
-
- cmd = am->registerAction(m_actions.returnFromFunctionAction,
- Constants::RETURN_FROM_FUNCTION, cppDebuggercontext);
- cmd->setAttribute(Command::CA_Hide);
- m_uiSwitcher->addMenuAction(cmd, CppLanguage);
-
-
- cmd = am->registerAction(m_actions.reverseDirectionAction,
- Constants::REVERSE, cppDebuggercontext);
- cmd->setDefaultKeySequence(QKeySequence(Constants::REVERSE_KEY));
- cmd->setAttribute(Command::CA_Hide);
- m_uiSwitcher->addMenuAction(cmd, CppLanguage);
-
-
- sep = new QAction(this);
- sep->setSeparator(true);
- cmd = am->registerAction(sep, _("Debugger.Sep.Break"), globalcontext);
- m_uiSwitcher->addMenuAction(cmd, CppLanguage);
-
-
- cmd = am->registerAction(m_actions.snapshotAction,
- Constants::SNAPSHOT, cppDebuggercontext);
- cmd->setDefaultKeySequence(QKeySequence(Constants::SNAPSHOT_KEY));
- cmd->setAttribute(Command::CA_Hide);
- m_uiSwitcher->addMenuAction(cmd, CppLanguage);
-
- cmd = am->registerAction(m_actions.frameDownAction,
- Constants::FRAME_DOWN, cppDebuggercontext);
- cmd = am->registerAction(m_actions.frameUpAction,
- Constants::FRAME_UP, cppDebuggercontext);
-
-
- cmd = am->registerAction(theDebuggerAction(OperateByInstruction),
- Constants::OPERATE_BY_INSTRUCTION, cppDebuggercontext);
- cmd->setAttribute(Command::CA_Hide);
- m_uiSwitcher->addMenuAction(cmd, CppLanguage);
-
-
- cmd = am->registerAction(m_actions.breakAction,
- Constants::TOGGLE_BREAK, globalcontext);
- cmd->setDefaultKeySequence(QKeySequence(Constants::TOGGLE_BREAK_KEY));
- m_uiSwitcher->addMenuAction(cmd, CppLanguage);
- connect(m_actions.breakAction, SIGNAL(triggered()),
- this, SLOT(toggleBreakpoint()));
-
- //mcppcontext->addAction(cmd);
-
- sep = new QAction(this);
- sep->setSeparator(true);
- cmd = am->registerAction(sep, _("Debugger.Sep.Watch"), globalcontext);
- m_uiSwitcher->addMenuAction(cmd, CppLanguage);
-
-
- cmd = am->registerAction(m_actions.watchAction1,
- Constants::ADD_TO_WATCH1, cppeditorcontext);
- cmd->action()->setEnabled(true);
- //cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+D,Ctrl+W")));
- m_uiSwitcher->addMenuAction(cmd, CppLanguage);
-
-
- // Editor context menu
- ActionContainer *editorContextMenu =
- am->actionContainer(CppEditor::Constants::M_CONTEXT);
- cmd = am->registerAction(sep, _("Debugger.Sep.Views"),
- cppDebuggercontext);
- editorContextMenu->addAction(cmd);
- cmd->setAttribute(Command::CA_Hide);
-
- cmd = am->registerAction(m_actions.watchAction2,
- Constants::ADD_TO_WATCH2, cppDebuggercontext);
- cmd->action()->setEnabled(true);
- editorContextMenu->addAction(cmd);
- cmd->setAttribute(Command::CA_Hide);
-
- cmd = am->registerAction(m_actions.runToLineAction2,
- Constants::RUN_TO_LINE2, cppDebuggercontext);
- cmd->action()->setEnabled(true);
- editorContextMenu->addAction(cmd);
- cmd->setAttribute(Command::CA_Hide);
-
- cmd = am->registerAction(m_actions.jumpToLineAction2,
- Constants::JUMP_TO_LINE2, cppDebuggercontext);
- cmd->action()->setEnabled(true);
- editorContextMenu->addAction(cmd);
- cmd->setAttribute(Command::CA_Hide);
-
- m_plugin->addAutoReleasedObject(new CommonOptionsPage);
- QList<Core::IOptionsPage *> engineOptionPages;
- if (cmdLineEnabledEngines & GdbEngineType)
- addGdbOptionPages(&engineOptionPages);
-#ifdef CDB_ENABLED
- if (cmdLineEnabledEngines & CdbEngineType)
- addCdbOptionPages(&engineOptionPages);
-#endif
- //if (cmdLineEnabledEngines & ScriptEngineType)
- // addScriptOptionPages(&engineOptionPages);
- //if (cmdLineEnabledEngines & TcfEngineType)
- // addTcfOptionPages(&engineOptionPages);
- foreach (Core::IOptionsPage *op, engineOptionPages)
- m_plugin->addAutoReleasedObject(op);
- m_plugin->addAutoReleasedObject(new DebuggingHelperOptionPage);
-
- //setSimpleDockWidgetArrangement(Lang_Cpp);
-
- connect(ModeManager::instance(), SIGNAL(currentModeChanged(Core::IMode*)),
- this, SLOT(onModeChanged(Core::IMode*)));
- m_debugMode->widget()->setFocusProxy(EditorManager::instance());
- m_plugin->addObject(m_debugMode);
-
-
- //
- // Connections
- //
-
- // TextEditor
- connect(TextEditorSettings::instance(),
- SIGNAL(fontSettingsChanged(TextEditor::FontSettings)),
- SLOT(fontSettingsChanged(TextEditor::FontSettings)));
-
- // ProjectExplorer
- connect(sessionManager(), SIGNAL(sessionLoaded()),
- SLOT(sessionLoaded()));
- connect(sessionManager(), SIGNAL(aboutToSaveSession()),
- SLOT(aboutToSaveSession()));
- connect(sessionManager(), SIGNAL(aboutToUnloadSession()),
- SLOT(aboutToUnloadSession()));
-
- // EditorManager
- QObject *editorManager = core->editorManager();
- connect(editorManager, SIGNAL(editorAboutToClose(Core::IEditor*)),
- SLOT(editorAboutToClose(Core::IEditor*)));
- connect(editorManager, SIGNAL(editorOpened(Core::IEditor*)),
- SLOT(editorOpened(Core::IEditor*)));
-
- // Application interaction
- connect(theDebuggerAction(SettingsDialog), SIGNAL(triggered()),
- SLOT(showSettingsDialog()));
-
- // Toolbar
- QWidget *toolbarContainer = new QWidget;
-
- QHBoxLayout *hbox = new QHBoxLayout(toolbarContainer);
- hbox->setMargin(0);
- hbox->setSpacing(0);
- hbox->addWidget(toolButton(am->command(PE::DEBUG)->action()));
- hbox->addWidget(toolButton(am->command(STOP)->action()));
- hbox->addWidget(toolButton(am->command(NEXT)->action()));
- hbox->addWidget(toolButton(am->command(STEP)->action()));
- hbox->addWidget(toolButton(am->command(STEPOUT)->action()));
- hbox->addWidget(toolButton(am->command(OPERATE_BY_INSTRUCTION)->action()));
-
- //hbox->addWidget(new Utils::StyledSeparator);
- m_reverseToolButton = toolButton(am->command(REVERSE)->action());
- hbox->addWidget(m_reverseToolButton);
- //m_reverseToolButton->hide();
-
- hbox->addWidget(new Utils::StyledSeparator);
- hbox->addWidget(new QLabel(tr("Threads:")));
-
- m_threadBox = new QComboBox;
- connect(m_threadBox, SIGNAL(activated(int)),
- m_threadsWindow, SLOT(selectThread(int)));
-
- hbox->addWidget(m_threadBox);
- hbox->addSpacerItem(new QSpacerItem(4, 0));
- hbox->addWidget(m_statusLabel, 10);
-
- m_uiSwitcher->setToolbar(CppLanguage, toolbarContainer);
- connect(m_uiSwitcher,
- SIGNAL(dockResetRequested(Debugger::DebuggerLanguages)),
- SLOT(setSimpleDockWidgetArrangement(Debugger::DebuggerLanguages)));
-
- connect(theDebuggerAction(EnableReverseDebugging),
- SIGNAL(valueChanged(QVariant)),
- SLOT(enableReverseDebuggingTriggered(QVariant)));
-
- // UI Switcher
- connect(m_uiSwitcher,
- SIGNAL(activeLanguagesChanged(Debugger::DebuggerLanguages)),
- SLOT(languagesChanged(Debugger::DebuggerLanguages)));
-
- setInitialState();
- connectEngine(m_sessionEngine, false);
-
- connect(sessionManager(),
- SIGNAL(startupProjectChanged(ProjectExplorer::Project*)),
- SLOT(onCurrentProjectChanged(ProjectExplorer::Project*)));
+ // Cpp/Qml ui setup
+ m_mainWindow = new DebuggerMainWindow;
return true;
}
void DebuggerPluginPrivate::setConfigValue(const QString &name, const QVariant &value)
{
- settings()->setValue(_("DebugMode/") + name, value);
+ m_coreSettings->setValue(_("DebugMode/") + name, value);
}
QVariant DebuggerPluginPrivate::configValue(const QString &name) const
{
- const QVariant value = settings()->value(_("DebugMode/") + name);
+ const QVariant value = m_coreSettings->value(_("DebugMode/") + name);
if (value.isValid())
return value;
// Legacy (pre-2.1): Check old un-namespaced-settings.
- return settings()->value(name);
+ return m_coreSettings->value(name);
}
void DebuggerPluginPrivate::onCurrentProjectChanged(Project *project)
@@ -1737,11 +1448,11 @@ void DebuggerPluginPrivate::onCurrentProjectChanged(Project *project)
}
for (int i = 0, n = m_snapshotHandler->size(); i != n; ++i) {
// Run controls might be deleted during exit.
- if (DebuggerRunControl *runControl = m_snapshotHandler->at(i)) {
+ if (DebuggerEngine *engine = m_snapshotHandler->at(i)) {
+ DebuggerRunControl *runControl = engine->runControl();
RunConfiguration *rc = runControl->runConfiguration();
if (rc == activeRc) {
m_snapshotHandler->setCurrentIndex(i);
- DebuggerEngine *engine = runControl->engine();
updateState(engine);
return;
}
@@ -1752,19 +1463,11 @@ void DebuggerPluginPrivate::onCurrentProjectChanged(Project *project)
core->updateAdditionalContexts(m_anyContext, Context());
}
-void DebuggerPluginPrivate::onAction()
-{
- QAction *act = qobject_cast<QAction *>(sender());
- QTC_ASSERT(act, return);
- const int role = act->property(Role).toInt();
- notifyCurrentEngine(role);
-}
-
-void DebuggerPluginPrivate::languagesChanged(const DebuggerLanguages &languages)
+void DebuggerPluginPrivate::languagesChanged()
{
- const bool debuggerIsCPP = (languages & CppLanguage);
+ const bool debuggerIsCPP =
+ m_mainWindow->activeDebugLanguages() & CppLanguage;
//qDebug() << "DEBUGGER IS CPP: " << debuggerIsCPP;
-
m_startExternalAction->setVisible(debuggerIsCPP);
m_attachExternalAction->setVisible(debuggerIsCPP);
m_attachCoreAction->setVisible(debuggerIsCPP);
@@ -1772,6 +1475,13 @@ void DebuggerPluginPrivate::languagesChanged(const DebuggerLanguages &languages)
m_detachAction->setVisible(debuggerIsCPP);
}
+void DebuggerPluginPrivate::debugProject()
+{
+ ProjectExplorerPlugin *pe = ProjectExplorerPlugin::instance();
+ if (Project *pro = pe->startupProject())
+ pe->runProject(pro, Constants::DEBUGMODE);
+}
+
void DebuggerPluginPrivate::startExternalApplication()
{
DebuggerStartParameters sp;
@@ -1794,25 +1504,25 @@ void DebuggerPluginPrivate::startExternalApplication()
sp.executable = dlg.executableFile();
sp.startMode = StartExternal;
sp.workingDirectory = dlg.workingDirectory();
- sp.breakAtMain = dlg.breakAtMain();
if (!dlg.executableArguments().isEmpty())
- sp.processArgs = dlg.executableArguments().split(QLatin1Char(' '));
+ sp.processArgs = dlg.executableArguments();
// Fixme: 1 of 3 testing hacks.
- if (!sp.processArgs.isEmpty()
- && (sp.processArgs.front() == _("@tcf@") || sp.processArgs.front() == _("@sym@")))
- sp.toolChainType = ToolChain::RVCT_ARMV5;
+ if (sp.processArgs.startsWith(__("@tcf@ ")) || sp.processArgs.startsWith(__("@sym@ ")))
+ sp.toolChainType = ToolChain_RVCT2_ARMV5;
+ if (dlg.breakAtMain()) {
+#ifdef Q_OS_WIN
+ // FIXME: wrong on non-Qt based binaries
+ breakHandler()->breakByFunction("qMain");
+#else
+ breakHandler()->breakByFunction("main");
+#endif
+ }
if (RunControl *rc = m_debuggerRunControlFactory->create(sp))
startDebugger(rc);
}
-void DebuggerPluginPrivate::notifyCurrentEngine(int role, const QVariant &value)
-{
- QTC_ASSERT(m_commandWindow && m_commandWindow->model(), return);
- m_commandWindow->model()->setData(QModelIndex(), value, role);
-}
-
void DebuggerPluginPrivate::attachExternalApplication()
{
AttachExternalDialog dlg(mainWindow());
@@ -1874,6 +1584,25 @@ void DebuggerPluginPrivate::attachRemote(const QString &spec)
startDebugger(rc);
}
+void DebuggerPluginPrivate::startRemoteCdbSession()
+{
+ const QString connectionKey = _("CdbRemoteConnection");
+ DebuggerStartParameters sp;
+ sp.toolChainType = ToolChain_MSVC;
+ sp.startMode = AttachToRemote;
+ StartRemoteCdbDialog dlg(mainWindow());
+ QString previousConnection = configValue(connectionKey).toString();
+ if (previousConnection.isEmpty())
+ previousConnection = QLatin1String("localhost:1234");
+ dlg.setConnection(previousConnection);
+ if (dlg.exec() != QDialog::Accepted)
+ return;
+ sp.remoteChannel = dlg.connection();
+ setConfigValue(connectionKey, sp.remoteChannel);
+ if (RunControl *rc = createDebugger(sp))
+ startDebugger(rc);
+}
+
void DebuggerPluginPrivate::startRemoteApplication()
{
DebuggerStartParameters sp;
@@ -1881,16 +1610,28 @@ void DebuggerPluginPrivate::startRemoteApplication()
QStringList arches;
arches.append(_("i386:x86-64:intel"));
arches.append(_("i386"));
+ arches.append(_("arm"));
QString lastUsed = configValue(_("LastRemoteArchitecture")).toString();
if (!arches.contains(lastUsed))
arches.prepend(lastUsed);
dlg.setRemoteArchitectures(arches);
+ QStringList gnuTargets;
+ gnuTargets.append(_("auto"));
+ gnuTargets.append(_("i686-linux-gnu"));
+ gnuTargets.append(_("x86_64-linux-gnu"));
+ gnuTargets.append(_("arm-none-linux-gnueabi"));
+ const QString lastUsedGnuTarget
+ = configValue(_("LastGnuTarget")).toString();
+ if (!gnuTargets.contains(lastUsedGnuTarget))
+ gnuTargets.prepend(lastUsedGnuTarget);
+ dlg.setGnuTargets(gnuTargets);
dlg.setRemoteChannel(
configValue(_("LastRemoteChannel")).toString());
dlg.setLocalExecutable(
configValue(_("LastLocalExecutable")).toString());
dlg.setDebugger(configValue(_("LastDebugger")).toString());
dlg.setRemoteArchitecture(lastUsed);
+ dlg.setGnuTarget(lastUsedGnuTarget);
dlg.setServerStartScript(
configValue(_("LastServerStartScript")).toString());
dlg.setUseServerStartScript(
@@ -1902,16 +1643,18 @@ void DebuggerPluginPrivate::startRemoteApplication()
setConfigValue(_("LastLocalExecutable"), dlg.localExecutable());
setConfigValue(_("LastDebugger"), dlg.debugger());
setConfigValue(_("LastRemoteArchitecture"), dlg.remoteArchitecture());
+ setConfigValue(_("LastGnuTarget"), dlg.gnuTarget());
setConfigValue(_("LastServerStartScript"), dlg.serverStartScript());
setConfigValue(_("LastUseServerStartScript"), dlg.useServerStartScript());
setConfigValue(_("LastSysroot"), dlg.sysRoot());
sp.remoteChannel = dlg.remoteChannel();
sp.remoteArchitecture = dlg.remoteArchitecture();
+ sp.gnuTarget = dlg.gnuTarget();
sp.executable = dlg.localExecutable();
sp.displayName = dlg.localExecutable();
sp.debuggerCommand = dlg.debugger(); // Override toolchain-detection.
if (!sp.debuggerCommand.isEmpty())
- sp.toolChainType = ToolChain::INVALID;
+ sp.toolChainType = ToolChain_INVALID;
sp.startMode = AttachToRemote;
sp.useServerStartScript = dlg.useServerStartScript();
sp.serverStartScript = dlg.serverStartScript();
@@ -1920,6 +1663,29 @@ void DebuggerPluginPrivate::startRemoteApplication()
startDebugger(rc);
}
+void DebuggerPluginPrivate::startRemoteEngine()
+{
+ DebuggerStartParameters sp;
+ StartRemoteEngineDialog dlg(mainWindow());
+ if (dlg.exec() != QDialog::Accepted)
+ return;
+
+ sp.connParams.host = dlg.host();
+ sp.connParams.uname = dlg.username();
+ sp.connParams.pwd = dlg.password();
+
+ sp.connParams.timeout = 5;
+ sp.connParams.authType = SshConnectionParameters::AuthByPwd;
+ sp.connParams.port = 22;
+ sp.connParams.proxyType = SshConnectionParameters::NoProxy;
+
+ sp.executable = dlg.inferiorPath();
+ sp.serverStartScript = dlg.enginePath();
+ sp.startMode = StartRemoteEngine;
+ if (RunControl *rc = createDebugger(sp))
+ startDebugger(rc);
+}
+
void DebuggerPluginPrivate::enableReverseDebuggingTriggered(const QVariant &value)
{
QTC_ASSERT(m_reverseToolButton, return);
@@ -1971,17 +1737,16 @@ bool DebuggerPluginPrivate::attachCmdLine()
return true;
}
const QString target = m_attachRemoteParameters.attachTarget;
- if (!target.isEmpty()) {
- if (target.indexOf(':') > 0) {
- showStatusMessage(tr("Attaching to remote server %1.").arg(target));
- attachRemote(target);
- } else {
- showStatusMessage(tr("Attaching to core %1.").arg(target));
- attachCore(target, QString());
- }
- return true;
+ if (target.isEmpty())
+ return false;
+ if (target.indexOf(':') > 0) {
+ showStatusMessage(tr("Attaching to remote server %1.").arg(target));
+ attachRemote(target);
+ } else {
+ showStatusMessage(tr("Attaching to core %1.").arg(target));
+ attachCore(target, QString());
}
- return false;
+ return true;
}
void DebuggerPluginPrivate::editorOpened(Core::IEditor *editor)
@@ -1991,13 +1756,15 @@ void DebuggerPluginPrivate::editorOpened(Core::IEditor *editor)
ITextEditor *textEditor = qobject_cast<ITextEditor *>(editor);
if (!textEditor)
return;
- connect(textEditor, SIGNAL(markRequested(TextEditor::ITextEditor*,int)),
- this, SLOT(requestMark(TextEditor::ITextEditor*,int)));
- connect(editor, SIGNAL(tooltipRequested(TextEditor::ITextEditor*,QPoint,int)),
- this, SLOT(showToolTip(TextEditor::ITextEditor*,QPoint,int)));
+ connect(textEditor,
+ SIGNAL(markRequested(TextEditor::ITextEditor*,int)),
+ SLOT(requestMark(TextEditor::ITextEditor*,int)));
+ connect(editor,
+ SIGNAL(tooltipRequested(TextEditor::ITextEditor*,QPoint,int)),
+ SLOT(showToolTip(TextEditor::ITextEditor*,QPoint,int)));
connect(textEditor,
SIGNAL(markContextMenuRequested(TextEditor::ITextEditor*,int,QMenu*)),
- this, SLOT(requestContextMenu(TextEditor::ITextEditor*,int,QMenu*)));
+ SLOT(requestContextMenu(TextEditor::ITextEditor*,int,QMenu*)));
}
void DebuggerPluginPrivate::editorAboutToClose(Core::IEditor *editor)
@@ -2007,11 +1774,14 @@ void DebuggerPluginPrivate::editorAboutToClose(Core::IEditor *editor)
ITextEditor *textEditor = qobject_cast<ITextEditor *>(editor);
if (!textEditor)
return;
- disconnect(textEditor, SIGNAL(markRequested(TextEditor::ITextEditor*,int)),
+ disconnect(textEditor,
+ SIGNAL(markRequested(TextEditor::ITextEditor*,int)),
this, SLOT(requestMark(TextEditor::ITextEditor*,int)));
- disconnect(editor, SIGNAL(tooltipRequested(TextEditor::ITextEditor*,QPoint,int)),
+ disconnect(editor,
+ SIGNAL(tooltipRequested(TextEditor::ITextEditor*,QPoint,int)),
this, SLOT(showToolTip(TextEditor::ITextEditor*,QPoint,int)));
- disconnect(textEditor, SIGNAL(markContextMenuRequested(TextEditor::ITextEditor*,int,QMenu*)),
+ disconnect(textEditor,
+ SIGNAL(markContextMenuRequested(TextEditor::ITextEditor*,int,QMenu*)),
this, SLOT(requestContextMenu(TextEditor::ITextEditor*,int,QMenu*)));
}
@@ -2021,50 +1791,163 @@ void DebuggerPluginPrivate::requestContextMenu(TextEditor::ITextEditor *editor,
if (!isDebuggable(editor))
return;
- QList<QVariant> list;
- list.append(quint64(editor));
- list.append(lineNumber);
- list.append(quint64(menu));
- notifyCurrentEngine(RequestContextMenuRole, list);
+ BreakpointId id = BreakpointId();
+ QString fileName;
+ quint64 address = 0;
+
+ if (editor->property("DisassemblerView").toBool()) {
+ fileName = editor->file()->fileName();
+ QString line = editor->contents()
+ .section('\n', lineNumber - 1, lineNumber - 1);
+ BreakpointResponse needle;
+ needle.type = BreakpointByAddress;
+ needle.address = DisassemblerAgent::addressFromDisassemblyLine(line);
+ address = needle.address;
+ needle.lineNumber = -1;
+ id = breakHandler()->findSimilarBreakpoint(needle);
+ } else {
+ fileName = editor->file()->fileName();
+ id = breakHandler()->findBreakpointByFileAndLine(fileName, lineNumber);
+ }
+
+ QList<QVariant> args;
+ args.append(fileName);
+ args.append(lineNumber);
+ args.append(address);
+
+ if (id) {
+ // Remove existing breakpoint.
+ QAction *act = new QAction(menu);
+ act->setData(int(id));
+ act->setText(tr("Remove Breakpoint %1").arg(id));
+ connect(act, SIGNAL(triggered()),
+ SLOT(breakpointRemoveMarginActionTriggered()));
+ menu->addAction(act);
+
+ // Enable/disable existing breakpoint.
+ act = new QAction(menu);
+ act->setData(int(id));
+ if (breakHandler()->isEnabled(id)) {
+ act->setText(tr("Disable Breakpoint %1").arg(id));
+ connect(act, SIGNAL(triggered()),
+ SLOT(breakpointDisableMarginActionTriggered()));
+ } else {
+ act->setText(tr("Enable Breakpoint %1").arg(id));
+ connect(act, SIGNAL(triggered()),
+ SLOT(breakpointEnableMarginActionTriggered()));
+ }
+ menu->addAction(act);
+
+ // Edit existing breakpoint.
+ act = new QAction(menu);
+ act->setText(tr("Edit Breakpoint %1...").arg(id));
+ connect(act, SIGNAL(triggered()), SLOT(slotEditBreakpoint()));
+ act->setData(int(id));
+ menu->addAction(act);
+ } else {
+ // Handle non-existing breakpoint.
+ const QString text = address ?
+ tr("Set Breakpoint at 0x%1").arg(address, 0, 16) :
+ tr("Set Breakpoint at line %1").arg(lineNumber);
+ QAction *act = new QAction(text, menu);
+ act->setData(args);
+ connect(act, SIGNAL(triggered()),
+ SLOT(breakpointSetMarginActionTriggered()));
+ menu->addAction(act);
+ }
+ // Run to, jump to line below in stopped state.
+ if (state() == InferiorStopOk) {
+ menu->addSeparator();
+ const QString runText =
+ DebuggerEngine::tr("Run to Line %1").arg(lineNumber);
+ QAction *runToLineAction = new QAction(runText, menu);
+ runToLineAction->setData(args);
+ connect(runToLineAction, SIGNAL(triggered()), SLOT(slotRunToLine()));
+ menu->addAction(runToLineAction);
+ if (currentEngine()->debuggerCapabilities() & JumpToLineCapability) {
+ const QString jumpText =
+ DebuggerEngine::tr("Jump to Line %1").arg(lineNumber);
+ QAction *jumpToLineAction = new QAction(jumpText, menu);
+ menu->addAction(runToLineAction);
+ jumpToLineAction->setData(args);
+ connect(jumpToLineAction, SIGNAL(triggered()), SLOT(slotJumpToLine()));
+ menu->addAction(jumpToLineAction);
+ }
+ }
}
void DebuggerPluginPrivate::toggleBreakpoint()
{
ITextEditor *textEditor = currentTextEditor();
QTC_ASSERT(textEditor, return);
- int lineNumber = textEditor->currentLine();
- if (lineNumber >= 0)
- toggleBreakpoint(textEditor->file()->fileName(), lineNumber);
+ const int lineNumber = textEditor->currentLine();
+ if (textEditor->property("DisassemblerView").toBool()) {
+ QString line = textEditor->contents()
+ .section('\n', lineNumber - 1, lineNumber - 1);
+ quint64 address = DisassemblerAgent::addressFromDisassemblyLine(line);
+ toggleBreakpointByAddress(address);
+ } else if (lineNumber >= 0) {
+ toggleBreakpointByFileAndLine(textEditor->file()->fileName(), lineNumber);
+ }
+}
+
+void DebuggerPluginPrivate::toggleBreakpointByFileAndLine(const QString &fileName,
+ int lineNumber)
+{
+ BreakHandler *handler = m_breakHandler;
+ BreakpointId id =
+ handler->findBreakpointByFileAndLine(fileName, lineNumber, true);
+ if (!id)
+ id = handler->findBreakpointByFileAndLine(fileName, lineNumber, false);
+
+ if (id) {
+ handler->removeBreakpoint(id);
+ } else {
+ BreakpointParameters data(BreakpointByFileAndLine);
+ data.fileName = fileName;
+ data.lineNumber = lineNumber;
+ handler->appendBreakpoint(data);
+ }
+ synchronizeBreakpoints();
}
-void DebuggerPluginPrivate::toggleBreakpoint(const QString &fileName, int lineNumber)
+void DebuggerPluginPrivate::toggleBreakpointByAddress(quint64 address)
{
- QList<QVariant> list;
- list.append(fileName);
- list.append(lineNumber);
- notifyCurrentEngine(RequestToggleBreakpointRole, list);
+ BreakHandler *handler = m_breakHandler;
+ BreakpointId id = handler->findBreakpointByAddress(address);
+
+ if (id) {
+ handler->removeBreakpoint(id);
+ } else {
+ BreakpointParameters data(BreakpointByAddress);
+ data.address = address;
+ handler->appendBreakpoint(data);
+ }
+ synchronizeBreakpoints();
}
void DebuggerPluginPrivate::requestMark(ITextEditor *editor, int lineNumber)
{
- if (isDebuggable(editor) && editor && editor->file())
- toggleBreakpoint(editor->file()->fileName(), lineNumber);
+ if (editor->property("DisassemblerView").toBool()) {
+ QString line = editor->contents()
+ .section('\n', lineNumber - 1, lineNumber - 1);
+ quint64 address = DisassemblerAgent::addressFromDisassemblyLine(line);
+ toggleBreakpointByAddress(address);
+ } else if (editor->file()) {
+ toggleBreakpointByFileAndLine(editor->file()->fileName(), lineNumber);
+ }
}
-void DebuggerPluginPrivate::showToolTip(ITextEditor *editor, const QPoint &point, int pos)
+void DebuggerPluginPrivate::showToolTip(ITextEditor *editor,
+ const QPoint &point, int pos)
{
if (!isDebuggable(editor))
return;
- if (!theDebuggerBoolSetting(UseToolTipsInMainEditor))
+ if (!boolSetting(UseToolTipsInMainEditor))
return;
if (state() != InferiorStopOk)
return;
-
- QList<QVariant> list;
- list.append(point);
- list.append(quint64(editor));
- list.append(pos);
- notifyCurrentEngine(RequestToolTipByExpressionRole, list);
+ currentEngine()->setToolTipExpression(point, editor, pos);
}
DebuggerRunControl *DebuggerPluginPrivate::createDebugger
@@ -2073,6 +1956,7 @@ DebuggerRunControl *DebuggerPluginPrivate::createDebugger
return m_debuggerRunControlFactory->create(sp, rc);
}
+// If updateEngine is set, the engine will update its threads/modules and so forth.
void DebuggerPluginPrivate::displayDebugger(DebuggerEngine *engine, bool updateEngine)
{
QTC_ASSERT(engine, return);
@@ -2080,31 +1964,28 @@ void DebuggerPluginPrivate::displayDebugger(DebuggerEngine *engine, bool updateE
connectEngine(engine);
if (updateEngine)
engine->updateAll();
- updateState(engine);
+ engine->updateViews();
}
void DebuggerPluginPrivate::startDebugger(RunControl *rc)
{
QTC_ASSERT(rc, return);
- ProjectExplorerPlugin::instance()->startRunControl(rc, PE::DEBUGMODE);
+ ProjectExplorerPlugin::instance()->startRunControl(rc, Constants::DEBUGMODE);
}
-void DebuggerPluginPrivate::connectEngine(DebuggerEngine *engine, bool notify)
+
+void DebuggerPluginPrivate::connectEngine(DebuggerEngine *engine)
{
- const QAbstractItemModel *oldCommandModel = m_commandWindow->model();
- if (oldCommandModel == engine->commandModel()) {
- // qDebug("RECONNECTING ENGINE %s", qPrintable(engine->objectName()));
- return;
- }
+ if (!engine)
+ engine = dummyEngine();
- if (notify)
- notifyCurrentEngine(RequestActivationRole, false);
+ if (m_currentEngine == engine)
+ return;
- // qDebug("CONNECTING ENGINE %s (OLD ENGINE: %s)", qPrintable(engine->objectName()),
- // (oldCommandModel ? qPrintable(oldCommandModel->objectName()) : ""));
+ if (m_currentEngine)
+ m_currentEngine->resetLocation();
+ m_currentEngine = engine;
- m_breakWindow->setModel(engine->breakModel());
- m_commandWindow->setModel(engine->commandModel());
m_localsWindow->setModel(engine->localsModel());
m_modulesWindow->setModel(engine->modulesModel());
m_registerWindow->setModel(engine->registerModel());
@@ -2115,8 +1996,6 @@ void DebuggerPluginPrivate::connectEngine(DebuggerEngine *engine, bool notify)
m_threadBox->setModel(engine->threadsModel());
m_threadBox->setModelColumn(ThreadData::NameColumn);
m_watchersWindow->setModel(engine->watchersModel());
- if (notify)
- notifyCurrentEngine(RequestActivationRole, true);
}
static void changeFontSize(QWidget *widget, qreal size)
@@ -2145,24 +2024,30 @@ void DebuggerPluginPrivate::fontSettingsChanged
void DebuggerPluginPrivate::cleanupViews()
{
- m_plugin->resetLocation();
m_actions.reverseDirectionAction->setChecked(false);
m_actions.reverseDirectionAction->setEnabled(false);
hideDebuggerToolTip();
- // FIXME ABC: Delete run control / engine?
- //if (d->m_engine)
- // d->m_engine->cleanup();
-
- if (theDebuggerBoolSetting(CloseBuffersOnExit)) {
- if (EditorManager *editorManager = EditorManager::instance()) {
- QList<IEditor *> toClose;
- foreach (IEditor *editor, editorManager->openedEditors())
- if (editor->property("OpenedByDebugger").toBool())
- toClose.append(editor);
- editorManager->closeEditors(toClose);
+ if (!boolSetting(CloseBuffersOnExit))
+ return;
+
+ EditorManager *editorManager = EditorManager::instance();
+ QTC_ASSERT(editorManager, return);
+ QList<IEditor *> toClose;
+ foreach (IEditor *editor, editorManager->openedEditors()) {
+ if (editor->property(Constants::OPENED_BY_DEBUGGER).toBool()) {
+ // Close disassembly views. Close other opened files
+ // if they are not modified and not current editor.
+ if (editor->property(Constants::OPENED_WITH_DISASSEMBLY).toBool()
+ || (!editor->file()->isModified()
+ && editor != editorManager->currentEditor())) {
+ toClose.append(editor);
+ } else {
+ editor->setProperty(Constants::OPENED_BY_DEBUGGER, false);
+ }
}
}
+ editorManager->closeEditors(toClose);
}
void DebuggerPluginPrivate::setBusyCursor(bool busy)
@@ -2187,59 +2072,6 @@ void DebuggerPluginPrivate::setBusyCursor(bool busy)
m_scriptConsoleWindow->setCursor(cursor);
}
-void DebuggerPluginPrivate::setSimpleDockWidgetArrangement
- (const DebuggerLanguages &activeLanguages)
-{
- Debugger::DebuggerUISwitcher *uiSwitcher = DebuggerUISwitcher::instance();
- DebuggerMainWindow *mw = mainWindow();
- mw->setTrackingEnabled(false);
-
- QList<QDockWidget *> dockWidgets = mw->dockWidgets();
- foreach (QDockWidget *dockWidget, dockWidgets) {
- dockWidget->setFloating(false);
- mw->removeDockWidget(dockWidget);
- }
-
- foreach (QDockWidget *dockWidget, dockWidgets) {
- if (dockWidget == m_outputDock /*|| dockWidget == m_consoleDock*/) {
- mw->addDockWidget(Qt::TopDockWidgetArea, dockWidget);
- } else {
- mw->addDockWidget(Qt::BottomDockWidgetArea, dockWidget);
- }
- dockWidget->hide();
- }
-
- if ((activeLanguages.testFlag(CppLanguage)
- && !activeLanguages.testFlag(QmlLanguage))
- || activeLanguages == AnyLanguage) {
- m_stackDock->show();
- m_breakDock->show();
- m_watchDock->show();
- m_threadsDock->show();
- m_snapshotDock->show();
- } else {
- m_stackDock->show();
- m_breakDock->show();
- m_watchDock->show();
- m_scriptConsoleDock->show();
- if (uiSwitcher->qmlInspectorWindow())
- uiSwitcher->qmlInspectorWindow()->show();
- }
- mw->splitDockWidget(mw->toolBarDockWidget(), m_stackDock, Qt::Vertical);
- mw->splitDockWidget(m_stackDock, m_watchDock, Qt::Horizontal);
- mw->tabifyDockWidget(m_watchDock, m_breakDock);
- mw->tabifyDockWidget(m_watchDock, m_modulesDock);
- mw->tabifyDockWidget(m_watchDock, m_registerDock);
- mw->tabifyDockWidget(m_watchDock, m_threadsDock);
- mw->tabifyDockWidget(m_watchDock, m_sourceFilesDock);
- mw->tabifyDockWidget(m_watchDock, m_snapshotDock);
- mw->tabifyDockWidget(m_watchDock, m_scriptConsoleDock);
- if (uiSwitcher->qmlInspectorWindow())
- mw->tabifyDockWidget(m_watchDock, uiSwitcher->qmlInspectorWindow());
-
- mw->setTrackingEnabled(true);
-}
-
void DebuggerPluginPrivate::setInitialState()
{
m_watchersWindow->setVisible(false);
@@ -2262,40 +2094,51 @@ void DebuggerPluginPrivate::setInitialState()
m_actions.watchAction1->setEnabled(true);
m_actions.watchAction2->setEnabled(true);
m_actions.breakAction->setEnabled(true);
- m_actions.snapshotAction->setEnabled(false);
- theDebuggerAction(OperateByInstruction)->setEnabled(false);
+ //m_actions.snapshotAction->setEnabled(false);
+ action(OperateByInstruction)->setEnabled(false);
- m_actions.stopAction->setEnabled(false);
+ m_actions.exitAction->setEnabled(false);
m_actions.resetAction->setEnabled(false);
m_actions.stepAction->setEnabled(false);
m_actions.stepOutAction->setEnabled(false);
- m_actions.runToLineAction1->setEnabled(false);
- m_actions.runToLineAction2->setEnabled(false);
+ m_actions.runToLineAction->setEnabled(false);
m_actions.runToFunctionAction->setEnabled(false);
m_actions.returnFromFunctionAction->setEnabled(false);
- m_actions.jumpToLineAction1->setEnabled(false);
- m_actions.jumpToLineAction2->setEnabled(false);
+ m_actions.jumpToLineAction->setEnabled(false);
m_actions.nextAction->setEnabled(false);
- theDebuggerAction(AutoDerefPointers)->setEnabled(true);
- theDebuggerAction(ExpandStack)->setEnabled(false);
- theDebuggerAction(ExecuteCommand)->setEnabled(m_state == InferiorStopOk);
+ action(AutoDerefPointers)->setEnabled(true);
+ action(ExpandStack)->setEnabled(false);
+ action(ExecuteCommand)->setEnabled(m_state == InferiorStopOk);
m_scriptConsoleWindow->setEnabled(false);
//emit m_plugin->stateChanged(m_state);
}
-void DebuggerPluginPrivate::updateState(DebuggerEngine *engine)
+void DebuggerPluginPrivate::updateWatchersWindow()
{
- QTC_ASSERT(engine != 0 && m_watchersWindow->model() != 0 && m_returnWindow->model() != 0, return);
- m_threadBox->setCurrentIndex(engine->threadsHandler()->currentThread());
-
m_watchersWindow->setVisible(
m_watchersWindow->model()->rowCount(QModelIndex()) > 0);
m_returnWindow->setVisible(
m_returnWindow->model()->rowCount(QModelIndex()) > 0);
+}
+
+void DebuggerPluginPrivate::updateState(DebuggerEngine *engine)
+{
+ QTC_ASSERT(engine, return);
+ QTC_ASSERT(m_watchersWindow->model(), return);
+ QTC_ASSERT(m_returnWindow->model(), return);
+ QTC_ASSERT(!engine->isSlaveEngine(), return);
+
+ m_threadBox->setCurrentIndex(engine->threadsHandler()->currentThread());
+
+ updateWatchersWindow();
+
+ //m_plugin->showMessage(QString("PLUGIN SET STATE: ")
+ // + DebuggerEngine::stateName(engine->state()), LogStatus);
+ //qDebug() << "PLUGIN SET STATE: " << engine->state();
if (m_state == engine->state())
return;
@@ -2303,8 +2146,6 @@ void DebuggerPluginPrivate::updateState(DebuggerEngine *engine)
m_state = engine->state();
bool actionsEnabled = DebuggerEngine::debuggerActionsEnabled(m_state);
- //qDebug() << "PLUGIN SET STATE: " << m_state;
-
ICore *core = ICore::instance();
ActionManager *am = core->actionManager();
if (m_state == DebuggerNotReady) {
@@ -2312,33 +2153,33 @@ void DebuggerPluginPrivate::updateState(DebuggerEngine *engine)
// F5 starts debugging. It is "startable".
m_actions.interruptAction->setEnabled(false);
m_actions.continueAction->setEnabled(false);
- m_actions.stopAction->setEnabled(false);
+ m_actions.exitAction->setEnabled(false);
am->command(Constants::STOP)->setKeySequence(QKeySequence());
- am->command(PE::DEBUG)->setKeySequence(QKeySequence(ProjectExplorer::Constants::DEBUG_KEY));
+ am->command(Constants::DEBUG)->setKeySequence(QKeySequence(DEBUG_KEY));
core->updateAdditionalContexts(m_anyContext, Context());
} else if (m_state == InferiorStopOk) {
// F5 continues, Shift-F5 kills. It is "continuable".
m_actions.interruptAction->setEnabled(false);
m_actions.continueAction->setEnabled(true);
- m_actions.stopAction->setEnabled(true);
+ m_actions.exitAction->setEnabled(true);
am->command(Constants::STOP)->setKeySequence(QKeySequence(STOP_KEY));
- am->command(PE::DEBUG)->setKeySequence(QKeySequence(ProjectExplorer::Constants::DEBUG_KEY));
+ am->command(Constants::DEBUG)->setKeySequence(QKeySequence(DEBUG_KEY));
core->updateAdditionalContexts(m_anyContext, m_continuableContext);
} else if (m_state == InferiorRunOk) {
// Shift-F5 interrupts. It is also "interruptible".
m_actions.interruptAction->setEnabled(true);
m_actions.continueAction->setEnabled(false);
- m_actions.stopAction->setEnabled(false);
+ m_actions.exitAction->setEnabled(false);
am->command(Constants::STOP)->setKeySequence(QKeySequence());
- am->command(PE::DEBUG)->setKeySequence(QKeySequence(STOP_KEY));
+ am->command(Constants::DEBUG)->setKeySequence(QKeySequence(STOP_KEY));
core->updateAdditionalContexts(m_anyContext, m_interruptibleContext);
} else if (m_state == DebuggerFinished) {
// We don't want to do anything anymore.
m_actions.interruptAction->setEnabled(false);
m_actions.continueAction->setEnabled(false);
- m_actions.stopAction->setEnabled(false);
+ m_actions.exitAction->setEnabled(false);
am->command(Constants::STOP)->setKeySequence(QKeySequence());
- am->command(PE::DEBUG)->setKeySequence(QKeySequence(ProjectExplorer::Constants::DEBUG_KEY));
+ am->command(Constants::DEBUG)->setKeySequence(QKeySequence(DEBUG_KEY));
//core->updateAdditionalContexts(m_anyContext, m_finishedContext);
m_codeModelSnapshot = CPlusPlus::Snapshot();
core->updateAdditionalContexts(m_anyContext, Context());
@@ -2348,17 +2189,17 @@ void DebuggerPluginPrivate::updateState(DebuggerEngine *engine)
// We don't want to do anything anymore.
m_actions.interruptAction->setEnabled(false);
m_actions.continueAction->setEnabled(false);
- m_actions.stopAction->setEnabled(true);
+ m_actions.exitAction->setEnabled(true);
am->command(Constants::STOP)->setKeySequence(QKeySequence(STOP_KEY));
- am->command(PE::DEBUG)->setKeySequence(QKeySequence(STOP_KEY));
+ am->command(Constants::DEBUG)->setKeySequence(QKeySequence(STOP_KEY));
core->updateAdditionalContexts(m_anyContext, m_finishedContext);
} else {
// Everything else is "undisturbable".
m_actions.interruptAction->setEnabled(false);
m_actions.continueAction->setEnabled(false);
- m_actions.stopAction->setEnabled(false);
+ m_actions.exitAction->setEnabled(false);
am->command(Constants::STOP)->setKeySequence(QKeySequence());
- am->command(PE::DEBUG)->setKeySequence(QKeySequence());
+ am->command(Constants::DEBUG)->setKeySequence(QKeySequence());
core->updateAdditionalContexts(m_anyContext, m_undisturbableContext);
}
@@ -2371,9 +2212,9 @@ void DebuggerPluginPrivate::updateState(DebuggerEngine *engine)
#endif
m_startRemoteAction->setEnabled(true);
+ const bool isCore = engine->startParameters().startMode == AttachCore;
const bool stopped = m_state == InferiorStopOk;
- const bool detachable = stopped
- && engine->startParameters().startMode != AttachCore;
+ const bool detachable = stopped && !isCore;
m_detachAction->setEnabled(detachable);
if (stopped)
@@ -2381,38 +2222,36 @@ void DebuggerPluginPrivate::updateState(DebuggerEngine *engine)
const uint caps = engine->debuggerCapabilities();
const bool canReverse = (caps & ReverseSteppingCapability)
- && theDebuggerBoolSetting(EnableReverseDebugging);
+ && boolSetting(EnableReverseDebugging);
m_actions.reverseDirectionAction->setEnabled(canReverse);
m_actions.watchAction1->setEnabled(true);
m_actions.watchAction2->setEnabled(true);
m_actions.breakAction->setEnabled(true);
- m_actions.snapshotAction->setEnabled(stopped && (caps & SnapshotCapability));
+ //m_actions.snapshotAction->setEnabled(stopped && (caps & SnapshotCapability));
- theDebuggerAction(OperateByInstruction)->setEnabled(stopped);
+ action(OperateByInstruction)->setEnabled(stopped || isCore);
m_actions.resetAction->setEnabled(m_state != DebuggerNotReady
&& m_state != DebuggerFinished);
m_actions.stepAction->setEnabled(stopped);
m_actions.stepOutAction->setEnabled(stopped);
- m_actions.runToLineAction1->setEnabled(stopped);
- m_actions.runToLineAction2->setEnabled(stopped);
+ m_actions.runToLineAction->setEnabled(stopped);
m_actions.runToFunctionAction->setEnabled(stopped);
m_actions.returnFromFunctionAction->
setEnabled(stopped && (caps & ReturnFromFunctionCapability));
const bool canJump = stopped && (caps & JumpToLineCapability);
- m_actions.jumpToLineAction1->setEnabled(canJump);
- m_actions.jumpToLineAction2->setEnabled(canJump);
+ m_actions.jumpToLineAction->setEnabled(canJump);
m_actions.nextAction->setEnabled(stopped);
const bool canDeref = actionsEnabled && (caps & AutoDerefPointersCapability);
- theDebuggerAction(AutoDerefPointers)->setEnabled(canDeref);
- theDebuggerAction(AutoDerefPointers)->setEnabled(true);
- theDebuggerAction(ExpandStack)->setEnabled(actionsEnabled);
- theDebuggerAction(ExecuteCommand)->setEnabled(m_state == InferiorStopOk);
+ action(AutoDerefPointers)->setEnabled(canDeref);
+ action(AutoDerefPointers)->setEnabled(true);
+ action(ExpandStack)->setEnabled(actionsEnabled);
+ action(ExecuteCommand)->setEnabled(m_state == InferiorStopOk);
const bool notbusy = m_state == InferiorStopOk
|| m_state == DebuggerNotReady
@@ -2423,22 +2262,11 @@ void DebuggerPluginPrivate::updateState(DebuggerEngine *engine)
m_scriptConsoleWindow->setEnabled(stopped);
}
-void DebuggerPluginPrivate::gotoLocation(const QString &file, int line, bool setMarker)
+void DebuggerPluginPrivate::updateDebugActions()
{
- // CDB might hit on breakpoints while shutting down.
- if (m_shuttingDown)
- return;
-
- bool newEditor = false;
- ITextEditor *editor =
- BaseTextEditor::openEditorAt(file, line, 0, QString(),
- EditorManager::IgnoreNavigationHistory, &newEditor);
- if (!editor)
- return;
- if (newEditor)
- editor->setProperty("OpenedByDebugger", true);
- if (setMarker)
- m_locationMark.reset(new LocationMark(file, line));
+ ProjectExplorerPlugin *pe = ProjectExplorerPlugin::instance();
+ Project *project = pe->startupProject();
+ m_debugAction->setEnabled(pe->canRun(project, Constants::DEBUGMODE));
}
void DebuggerPluginPrivate::onModeChanged(IMode *mode)
@@ -2447,9 +2275,9 @@ void DebuggerPluginPrivate::onModeChanged(IMode *mode)
// different then the debugger mode. E.g. Welcome and Help mode and
// also on shutdown.
- m_uiSwitcher->onModeChanged(mode);
+ m_mainWindow->onModeChanged(mode);
- if (mode != m_debugMode)
+ if (mode->id() != Constants::MODE_DEBUG)
return;
EditorManager *editorManager = EditorManager::instance();
@@ -2459,7 +2287,7 @@ void DebuggerPluginPrivate::onModeChanged(IMode *mode)
void DebuggerPluginPrivate::showSettingsDialog()
{
- Core::ICore::instance()->showOptionsDialog(
+ ICore::instance()->showOptionsDialog(
_(DEBUGGER_SETTINGS_CATEGORY),
_(DEBUGGER_COMMON_SETTINGS_ID));
}
@@ -2487,7 +2315,7 @@ void DebuggerPluginPrivate::clearStatusMessage()
/*! Activates the previous mode when the current mode is the debug mode. */
void DebuggerPluginPrivate::activatePreviousMode()
{
- Core::ModeManager *modeManager = ICore::instance()->modeManager();
+ ModeManager *modeManager = ICore::instance()->modeManager();
if (modeManager->currentMode() == modeManager->mode(MODE_DEBUG)
&& !m_previousMode.isEmpty()) {
@@ -2507,34 +2335,37 @@ void DebuggerPluginPrivate::activateDebugMode()
void DebuggerPluginPrivate::sessionLoaded()
{
- m_sessionEngine->loadSessionData();
+ m_breakHandler->loadSessionData();
+ dummyEngine()->watchHandler()->loadSessionData();
}
void DebuggerPluginPrivate::aboutToUnloadSession()
{
+ m_breakHandler->removeSessionData();
// Stop debugging the active project when switching sessions.
- // Note that at startup, session switches may occur, which interfer
+ // Note that at startup, session switches may occur, which interfere
// with command-line debugging startup.
// FIXME ABC: Still wanted? Iterate?
//if (d->m_engine && state() != DebuggerNotReady
- // && runControl()->sp().startMode == StartInternal)
+ // && engine()->sp().startMode == StartInternal)
// d->m_engine->shutdown();
}
void DebuggerPluginPrivate::aboutToSaveSession()
{
- m_sessionEngine->saveSessionData();
+ dummyEngine()->watchHandler()->loadSessionData();
+ m_breakHandler->saveSessionData();
}
void DebuggerPluginPrivate::executeDebuggerCommand()
{
if (QAction *action = qobject_cast<QAction *>(sender()))
- notifyCurrentEngine(RequestExecuteCommandRole, action->data().toString());
+ currentEngine()->executeDebuggerCommand(action->data().toString());
}
void DebuggerPluginPrivate::showStatusMessage(const QString &msg0, int timeout)
{
- m_plugin->showMessage(msg0, LogStatus);
+ showMessage(msg0, LogStatus);
QString msg = msg0;
msg.replace(QLatin1Char('\n'), QString());
m_statusLabel->setText(msg);
@@ -2549,17 +2380,14 @@ void DebuggerPluginPrivate::showStatusMessage(const QString &msg0, int timeout)
void DebuggerPluginPrivate::scriptExpressionEntered(const QString &expression)
{
- notifyCurrentEngine(RequestExecuteCommandRole, expression);
+ currentEngine()->executeDebuggerCommand(expression);
}
void DebuggerPluginPrivate::openMemoryEditor()
-{
+{
AddressDialog dialog;
- if (dialog.exec() != QDialog::Accepted)
- return;
- QTC_ASSERT(m_watchersWindow, return);
- m_watchersWindow->model()->setData(
- QModelIndex(), dialog.address(), RequestShowMemoryRole);
+ if (dialog.exec() == QDialog::Accepted)
+ currentEngine()->openMemoryView(dialog.address());
}
void DebuggerPluginPrivate::coreShutdown()
@@ -2567,331 +2395,882 @@ void DebuggerPluginPrivate::coreShutdown()
m_shuttingDown = true;
}
-///////////////////////////////////////////////////////////////////////
-//
-// DebuggerPlugin
-//
-///////////////////////////////////////////////////////////////////////
-
-DebuggerPlugin *theInstance = 0;
-
-DebuggerPlugin *DebuggerPlugin::instance()
-{
- return theInstance;
-}
-
-DebuggerPlugin::DebuggerPlugin()
-{
- d = new DebuggerPluginPrivate(this);
- theInstance = this;
-}
-
-DebuggerPlugin::~DebuggerPlugin()
-{
- delete d->m_sessionEngine;
- d->m_sessionEngine = 0;
-
- theInstance = 0;
- delete DebuggerSettings::instance();
-
- removeObject(d->m_debugMode);
-
- delete d->m_debugMode;
- d->m_debugMode = 0;
-
- removeObject(d->m_uiSwitcher);
- delete d->m_uiSwitcher;
- d->m_uiSwitcher = 0;
-
- delete d->m_commandWindow;
- d->m_commandWindow = 0;
-
- delete d->m_snapshotHandler;
- d->m_snapshotHandler = 0;
-
- delete d;
-}
-
-bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMessage)
+const CPlusPlus::Snapshot &DebuggerPluginPrivate::cppCodeModelSnapshot() const
{
- return d->initialize(arguments, errorMessage);
+ using namespace CppTools;
+ if (m_codeModelSnapshot.isEmpty() && action(UseCodeModel)->isChecked())
+ m_codeModelSnapshot = CppModelManagerInterface::instance()->snapshot();
+ return m_codeModelSnapshot;
}
-void DebuggerPlugin::setSessionValue(const QString &name, const QVariant &value)
+void DebuggerPluginPrivate::setSessionValue(const QString &name, const QVariant &value)
{
QTC_ASSERT(sessionManager(), return);
sessionManager()->setValue(name, value);
//qDebug() << "SET SESSION VALUE: " << name;
}
-QVariant DebuggerPlugin::sessionValue(const QString &name)
+QVariant DebuggerPluginPrivate::sessionValue(const QString &name)
{
QTC_ASSERT(sessionManager(), return QVariant());
//qDebug() << "GET SESSION VALUE: " << name;
return sessionManager()->value(name);
}
-void DebuggerPlugin::setConfigValue(const QString &name, const QVariant &value)
-{
- QTC_ASSERT(d->m_debugMode, return);
- settings()->setValue(name, value);
-}
-
-QVariant DebuggerPlugin::configValue(const QString &name) const
-{
- QTC_ASSERT(d->m_debugMode, return QVariant());
- return settings()->value(name);
-}
-
-void DebuggerPlugin::resetLocation()
-{
- d->m_locationMark.reset();
-}
-
-void DebuggerPlugin::gotoLocation(const QString &file, int line, bool setMarker)
-{
- d->gotoLocation(file, line, setMarker);
-}
-
-void DebuggerPlugin::openTextEditor(const QString &titlePattern0,
+void DebuggerPluginPrivate::openTextEditor(const QString &titlePattern0,
const QString &contents)
{
- if (d->m_shuttingDown)
+ if (m_shuttingDown)
return;
QString titlePattern = titlePattern0;
EditorManager *editorManager = EditorManager::instance();
QTC_ASSERT(editorManager, return);
IEditor *editor = editorManager->openEditorWithContents(
- Core::Constants::K_DEFAULT_TEXT_EDITOR_ID, &titlePattern, contents);
+ CC::K_DEFAULT_TEXT_EDITOR_ID, &titlePattern, contents);
QTC_ASSERT(editor, return);
editorManager->activateEditor(editor, EditorManager::IgnoreNavigationHistory);
}
-void DebuggerPlugin::writeSettings() const
-{
- QSettings *s = settings();
- DebuggerSettings::instance()->writeSettings(s);
-}
-
-void DebuggerPlugin::readSettings()
-{
- //qDebug() << "PLUGIN READ SETTINGS";
- QSettings *s = settings();
- DebuggerSettings::instance()->readSettings(s);
-}
-
-const CPlusPlus::Snapshot &DebuggerPlugin::cppCodeModelSnapshot() const
-{
- if (d->m_codeModelSnapshot.isEmpty() && theDebuggerAction(UseCodeModel)->isChecked())
- d->m_codeModelSnapshot = CppTools::CppModelManagerInterface::instance()->snapshot();
- return d->m_codeModelSnapshot;
-}
-void DebuggerPlugin::clearCppCodeModelSnapshot()
-{
- d->m_codeModelSnapshot = CPlusPlus::Snapshot();
-}
-
-ExtensionSystem::IPlugin::ShutdownFlag DebuggerPlugin::aboutToShutdown()
+void DebuggerPluginPrivate::clearCppCodeModelSnapshot()
{
- disconnect(sessionManager(),
- SIGNAL(startupProjectChanged(ProjectExplorer::Project*)), d, 0);
- writeSettings();
- if (d->m_uiSwitcher)
- d->m_uiSwitcher->aboutToShutdown();
- return SynchronousShutdown;
+ m_codeModelSnapshot = CPlusPlus::Snapshot();
}
-void DebuggerPlugin::showMessage(const QString &msg, int channel, int timeout)
+void DebuggerPluginPrivate::showMessage(const QString &msg, int channel, int timeout)
{
//qDebug() << "PLUGIN OUTPUT: " << channel << msg;
- LogWindow *ow = d->m_logWindow;
- //ConsoleWindow *cw = d->m_consoleWindow;
- QTC_ASSERT(ow, return);
+ //ConsoleWindow *cw = m_consoleWindow;
+ QTC_ASSERT(m_logWindow, return);
switch (channel) {
case StatusBar:
- // This will append to ow's output pane, too.
- d->showStatusMessage(msg, timeout);
+ // This will append to m_logWindow's output pane, too.
+ showStatusMessage(msg, timeout);
break;
case LogMiscInput:
- ow->showInput(LogMisc, msg);
- ow->showOutput(LogMisc, msg);
+ m_logWindow->showInput(LogMisc, msg);
+ m_logWindow->showOutput(LogMisc, msg);
break;
case LogInput:
- ow->showInput(LogInput, msg);
- ow->showOutput(LogInput, msg);
+ m_logWindow->showInput(LogInput, msg);
+ m_logWindow->showOutput(LogInput, msg);
break;
case ScriptConsoleOutput:
- d->m_scriptConsoleWindow->appendResult(msg);
+ m_scriptConsoleWindow->appendResult(msg);
+ break;
+ case LogError: {
+ m_logWindow->showOutput(channel, msg);
+ QAction *action = m_mainWindow->dockWidget(_(DOCKWIDGET_OUTPUT))
+ ->toggleViewAction();
+ if (!action->isChecked())
+ action->trigger();
break;
+ }
default:
- ow->showOutput(channel, msg);
- //cw->showOutput(channel, msg);
+ m_logWindow->showOutput(channel, msg);
break;
}
}
+void DebuggerPluginPrivate::showQtDumperLibraryWarning(const QString &details)
+{
+ QMessageBox dialog(mainWindow());
+ QPushButton *qtPref = dialog.addButton(tr("Open Qt4 Options"),
+ QMessageBox::ActionRole);
+ QPushButton *helperOff = dialog.addButton(tr("Turn off Helper Usage"),
+ QMessageBox::ActionRole);
+ QPushButton *justContinue = dialog.addButton(tr("Continue Anyway"),
+ QMessageBox::AcceptRole);
+ dialog.setDefaultButton(justContinue);
+ dialog.setWindowTitle(tr("Debugging Helper Missing"));
+ dialog.setText(tr("The debugger could not load the debugging helper library."));
+ dialog.setInformativeText(tr(
+ "The debugging helper is used to nicely format the values of some Qt "
+ "and Standard Library data types. "
+ "It must be compiled for each used Qt version separately. "
+ "On the Qt4 options page, select a Qt installation "
+ "and click Rebuild."));
+ if (!details.isEmpty())
+ dialog.setDetailedText(details);
+ dialog.exec();
+ if (dialog.clickedButton() == qtPref) {
+ ICore::instance()->showOptionsDialog(
+ _(Qt4ProjectManager::Constants::QT_SETTINGS_CATEGORY),
+ _(Qt4ProjectManager::Constants::QTVERSION_SETTINGS_PAGE_ID));
+ } else if (dialog.clickedButton() == helperOff) {
+ action(UseDebuggingHelpers)->setValue(qVariantFromValue(false), false);
+ }
+}
-//////////////////////////////////////////////////////////////////////
-//
-// Register specific stuff
-//
-//////////////////////////////////////////////////////////////////////
+void DebuggerPluginPrivate::createNewDock(QWidget *widget)
+{
+ QDockWidget *dockWidget =
+ m_mainWindow->createDockWidget(CppLanguage, widget);
+ dockWidget->setWindowTitle(widget->windowTitle());
+ dockWidget->setFeatures(QDockWidget::DockWidgetClosable);
+ dockWidget->show();
+}
-bool DebuggerPlugin::isReverseDebugging() const
+void DebuggerPluginPrivate::runControlStarted(DebuggerEngine *engine)
{
- return d->m_actions.reverseDirectionAction->isChecked();
+ activateDebugMode();
+ const QString message = tr("Starting debugger '%1' for tool chain '%2'...")
+ .arg(engine->objectName())
+ .arg(engine->startParameters().toolChainName());
+ showMessage(message, StatusBar);
+ showMessage(m_debuggerSettings->dump(), LogDebug);
+ m_snapshotHandler->appendSnapshot(engine);
+ connectEngine(engine);
}
-QMessageBox *DebuggerPlugin::showMessageBox(int icon, const QString &title,
+void DebuggerPluginPrivate::runControlFinished(DebuggerEngine *engine)
+{
+ m_snapshotHandler->removeSnapshot(engine);
+ if (m_snapshotHandler->size() == 0) {
+ // Last engine quits.
+ disconnectEngine();
+ if (boolSetting(SwitchModeOnExit))
+ activatePreviousMode();
+ } else {
+ // Connect to some existing engine.
+ m_snapshotHandler->activateSnapshot(0);
+ }
+}
+
+void DebuggerPluginPrivate::remoteCommand(const QStringList &options,
+ const QStringList &)
+{
+ if (options.isEmpty())
+ return;
+
+ unsigned enabledEngines = 0;
+ QString errorMessage;
+
+ if (!parseArguments(options,
+ &m_attachRemoteParameters, &enabledEngines, &errorMessage)) {
+ qWarning("%s", qPrintable(errorMessage));
+ return;
+ }
+
+ if (!attachCmdLine())
+ qWarning("%s", qPrintable(
+ _("Incomplete remote attach command received: %1").
+ arg(options.join(QString(QLatin1Char(' '))))));
+}
+
+QString DebuggerPluginPrivate::gdbBinaryForToolChain(int toolChain) const
+{
+ return GdbOptionsPage::gdbBinaryToolChainMap.key(toolChain);
+}
+
+DebuggerLanguages DebuggerPluginPrivate::activeLanguages() const
+{
+ QTC_ASSERT(m_mainWindow, return AnyLanguage);
+ return m_mainWindow->activeDebugLanguages();
+}
+
+bool DebuggerPluginPrivate::isReverseDebugging() const
+{
+ return m_actions.reverseDirectionAction->isChecked();
+}
+
+QMessageBox *showMessageBox(int icon, const QString &title,
const QString &text, int buttons)
{
QMessageBox *mb = new QMessageBox(QMessageBox::Icon(icon),
- title, text, QMessageBox::StandardButtons(buttons), mainWindow());
+ title, text, QMessageBox::StandardButtons(buttons),
+ debuggerCore()->mainWindow());
mb->setAttribute(Qt::WA_DeleteOnClose);
mb->show();
return mb;
}
-void DebuggerPlugin::ensureLogVisible()
+void DebuggerPluginPrivate::extensionsInitialized()
{
- QAction *action = d->m_outputDock->toggleViewAction();
- if (!action->isChecked())
- action->trigger();
-}
+ ICore *core = ICore::instance();
+ QTC_ASSERT(core, return);
+ m_coreSettings = core->settings();
+ m_debuggerSettings = new DebuggerSettings(m_coreSettings);
+
+ m_continuableContext = Context("Gdb.Continuable");
+ m_interruptibleContext = Context("Gdb.Interruptible");
+ m_undisturbableContext = Context("Gdb.Undisturbable");
+ m_finishedContext = Context("Gdb.Finished");
+ m_anyContext.add(m_continuableContext);
+ m_anyContext.add(m_interruptibleContext);
+ m_anyContext.add(m_undisturbableContext);
+ m_anyContext.add(m_finishedContext);
-QIcon DebuggerPlugin::locationMarkIcon() const
-{
- return d->m_locationMarkIcon;
-}
+ connect(core, SIGNAL(coreAboutToClose()), this, SLOT(coreShutdown()));
-void DebuggerPlugin::extensionsInitialized()
-{
- d->m_uiSwitcher->initialize();
- d->m_watchersWindow->setVisible(false);
- d->m_returnWindow->setVisible(false);
- connect(d->m_uiSwitcher, SIGNAL(memoryEditorRequested()),
- d, SLOT(openMemoryEditor()));
+ Core::ActionManager *am = core->actionManager();
+ QTC_ASSERT(am, return);
+
+ const Context globalcontext(CC::C_GLOBAL);
+ const Context cppDebuggercontext(C_CPPDEBUGGER);
+ const Context qmlDebuggerContext(C_QMLDEBUGGER);
+ const Context cppeditorcontext(CppEditor::Constants::C_CPPEDITOR);
+
+ m_startIcon = QIcon(_(":/debugger/images/debugger_start_small.png"));
+ m_startIcon.addFile(__(":/debugger/images/debugger_start.png"));
+ m_exitIcon = QIcon(_(":/debugger/images/debugger_stop_small.png"));
+ m_exitIcon.addFile(__(":/debugger/images/debugger_stop.png"));
+ m_continueIcon = QIcon(__(":/debugger/images/debugger_continue_small.png"));
+ m_continueIcon.addFile(__(":/debugger/images/debugger_continue.png"));
+ m_interruptIcon = QIcon(_(":/debugger/images/debugger_interrupt_small.png"));
+ m_interruptIcon.addFile(__(":/debugger/images/debugger_interrupt.png"));
+ m_locationMarkIcon = QIcon(_(":/debugger/images/location_16.png"));
+
+ m_busy = false;
+
+ m_statusLabel = new QLabel;
+ m_statusLabel->setMinimumSize(QSize(30, 10));
+
+ m_breakHandler = new BreakHandler;
+ m_breakWindow = new BreakWindow;
+ m_breakWindow->setObjectName(DOCKWIDGET_BREAK);
+ m_breakWindow->setModel(m_breakHandler->model());
+
+ //m_consoleWindow = new ConsoleWindow;
+ //m_consoleWindow->setObjectName(QLatin1String("CppDebugConsole"));
+ m_modulesWindow = new ModulesWindow;
+ m_modulesWindow->setObjectName(DOCKWIDGET_MODULES);
+ m_logWindow = new LogWindow;
+ m_logWindow->setObjectName(DOCKWIDGET_OUTPUT);
+ m_registerWindow = new RegisterWindow;
+ m_registerWindow->setObjectName(DOCKWIDGET_REGISTER);
+ m_stackWindow = new StackWindow;
+ m_stackWindow->setObjectName(DOCKWIDGET_STACK);
+ m_sourceFilesWindow = new SourceFilesWindow;
+ m_sourceFilesWindow->setObjectName(DOCKWIDGET_SOURCE_FILES);
+ m_threadsWindow = new ThreadsWindow;
+ m_threadsWindow->setObjectName(DOCKWIDGET_THREADS);
+ m_returnWindow = new WatchWindow(WatchWindow::ReturnType);
+ m_returnWindow->setObjectName(QLatin1String("CppDebugReturn"));
+ m_localsWindow = new WatchWindow(WatchWindow::LocalsType);
+ m_localsWindow->setObjectName(QLatin1String("CppDebugLocals"));
+ m_watchersWindow = new WatchWindow(WatchWindow::WatchersType);
+ m_watchersWindow->setObjectName(QLatin1String("CppDebugWatchers"));
+ m_scriptConsoleWindow = new ScriptConsole;
+ m_scriptConsoleWindow->setWindowTitle(tr("QML Script Console"));
+ m_scriptConsoleWindow->setObjectName(DOCKWIDGET_QML_SCRIPTCONSOLE);
+ connect(m_scriptConsoleWindow, SIGNAL(expressionEntered(QString)),
+ SLOT(scriptExpressionEntered(QString)));
+
+ // Snapshot
+ m_snapshotHandler = new SnapshotHandler;
+ m_snapshotWindow = new SnapshotWindow(m_snapshotHandler);
+ m_snapshotWindow->setObjectName(DOCKWIDGET_SNAPSHOTS);
+ m_snapshotWindow->setModel(m_snapshotHandler->model());
+
+ // Watchers
+ connect(m_localsWindow->header(), SIGNAL(sectionResized(int,int,int)),
+ SLOT(updateWatchersHeader(int,int,int)), Qt::QueuedConnection);
+
+ QAction *act = 0;
+
+ act = m_actions.continueAction = new QAction(tr("Continue"), this);
+ act->setIcon(m_continueIcon);
+ connect(act, SIGNAL(triggered()), SLOT(handleExecContinue()));
+
+ act = m_actions.exitAction = new QAction(tr("Exit Debugger"), this);
+ act->setIcon(m_exitIcon);
+ connect(act, SIGNAL(triggered()), SLOT(handleExecExit()));
+
+ act = m_actions.interruptAction = new QAction(tr("Interrupt"), this);
+ act->setIcon(m_interruptIcon);
+ connect(act, SIGNAL(triggered()), SLOT(handleExecInterrupt()));
+
+ // A "disabled pause" seems to be a good choice.
+ act = m_actions.undisturbableAction = new QAction(tr("Debugger is Busy"), this);
+ act->setIcon(m_interruptIcon);
+ act->setEnabled(false);
+
+ act = m_actions.resetAction = new QAction(tr("Abort Debugging"), this);
+ act->setToolTip(tr("Aborts debugging and "
+ "resets the debugger to the initial state."));
+ connect(act, SIGNAL(triggered()), SLOT(handleExecReset()));
+
+ act = m_actions.nextAction = new QAction(tr("Step Over"), this);
+ act->setIcon(QIcon(__(":/debugger/images/debugger_stepover_small.png")));
+ connect(act, SIGNAL(triggered()), SLOT(handleExecNext()));
+
+ act = m_actions.stepAction = new QAction(tr("Step Into"), this);
+ act->setIcon(QIcon(__(":/debugger/images/debugger_stepinto_small.png")));
+ connect(act, SIGNAL(triggered()), SLOT(handleExecStep()));
+
+ act = m_actions.stepOutAction = new QAction(tr("Step Out"), this);
+ act->setIcon(QIcon(__(":/debugger/images/debugger_stepout_small.png")));
+ connect(act, SIGNAL(triggered()), SLOT(handleExecStepOut()));
+
+ act = m_actions.runToLineAction = new QAction(tr("Run to Line"), this);
+ connect(act, SIGNAL(triggered()), SLOT(handleExecRunToLine()));
+
+ act = m_actions.runToFunctionAction =
+ new QAction(tr("Run to Outermost Function"), this);
+ connect(act, SIGNAL(triggered()), SLOT(handleExecRunToFunction()));
+
+ act = m_actions.returnFromFunctionAction =
+ new QAction(tr("Immediately Return From Inner Function"), this);
+ connect(act, SIGNAL(triggered()), SLOT(handleExecReturn()));
+
+ act = m_actions.jumpToLineAction = new QAction(tr("Jump to Line"), this);
+ connect(act, SIGNAL(triggered()), SLOT(handleExecJumpToLine()));
+
+ act = m_actions.breakAction = new QAction(tr("Toggle Breakpoint"), this);
+
+ act = m_actions.watchAction1 = new QAction(tr("Add to Watch Window"), this);
+ connect(act, SIGNAL(triggered()), SLOT(handleAddToWatchWindow()));
+
+ act = m_actions.watchAction2 = new QAction(tr("Add to Watch Window"), this);
+ connect(act, SIGNAL(triggered()), SLOT(handleAddToWatchWindow()));
+
+ //m_actions.snapshotAction = new QAction(tr("Create Snapshot"), this);
+ //m_actions.snapshotAction->setProperty(Role, RequestCreateSnapshotRole);
+ //m_actions.snapshotAction->setIcon(
+ // QIcon(__(":/debugger/images/debugger_snapshot_small.png")));
+
+ act = m_actions.reverseDirectionAction =
+ new QAction(tr("Reverse Direction"), this);
+ act->setCheckable(true);
+ act->setChecked(false);
+ act->setCheckable(false);
+ act->setIcon(QIcon(__(":/debugger/images/debugger_reversemode_16.png")));
+ act->setIconVisibleInMenu(false);
+
+ act = m_actions.frameDownAction = new QAction(tr("Move to Called Frame"), this);
+ connect(act, SIGNAL(triggered()), SLOT(handleFrameDown()));
+
+ act = m_actions.frameUpAction = new QAction(tr("Move to Calling Frame"), this);
+ connect(act, SIGNAL(triggered()), SLOT(handleFrameUp()));
+
+ connect(action(OperateByInstruction), SIGNAL(triggered(bool)),
+ SLOT(handleOperateByInstructionTriggered(bool)));
+
+ connect(&m_statusTimer, SIGNAL(timeout()), SLOT(clearStatusMessage()));
+
+ connect(action(ExecuteCommand), SIGNAL(triggered()),
+ SLOT(executeDebuggerCommand()));
+
+ ActionContainer *debugMenu =
+ am->actionContainer(ProjectExplorer::Constants::M_DEBUG);
+
+ // Dock widgets
+ QDockWidget *dock = 0;
+ dock = m_mainWindow->createDockWidget(CppLanguage, m_modulesWindow);
+ connect(dock->toggleViewAction(), SIGNAL(toggled(bool)),
+ SLOT(modulesDockToggled(bool)), Qt::QueuedConnection);
+
+ dock = m_mainWindow->createDockWidget(CppLanguage, m_registerWindow);
+ connect(dock->toggleViewAction(), SIGNAL(toggled(bool)),
+ SLOT(registerDockToggled(bool)), Qt::QueuedConnection);
+
+ dock = m_mainWindow->createDockWidget(CppLanguage, m_sourceFilesWindow);
+ connect(dock->toggleViewAction(), SIGNAL(toggled(bool)),
+ SLOT(sourceFilesDockToggled(bool)), Qt::QueuedConnection);
+
+ dock = m_mainWindow->createDockWidget(AnyLanguage, m_logWindow);
+ dock->setProperty(DOCKWIDGET_DEFAULT_AREA, Qt::TopDockWidgetArea);
+
+ m_mainWindow->createDockWidget(CppLanguage, m_breakWindow);
+ //m_mainWindow->createDockWidget(CppLanguage, m_consoleWindow);
+ m_mainWindow->createDockWidget(CppLanguage, m_snapshotWindow);
+ m_mainWindow->createDockWidget(CppLanguage, m_stackWindow);
+ m_mainWindow->createDockWidget(CppLanguage, m_threadsWindow);
+ m_mainWindow->createDockWidget(QmlLanguage, m_scriptConsoleWindow);
+
+ QSplitter *localsAndWatchers = new Core::MiniSplitter(Qt::Vertical);
+ localsAndWatchers->setObjectName(DOCKWIDGET_WATCHERS);
+ localsAndWatchers->setWindowTitle(m_localsWindow->windowTitle());
+ localsAndWatchers->addWidget(m_localsWindow);
+ localsAndWatchers->addWidget(m_returnWindow);
+ localsAndWatchers->addWidget(m_watchersWindow);
+ localsAndWatchers->setStretchFactor(0, 3);
+ localsAndWatchers->setStretchFactor(1, 1);
+ localsAndWatchers->setStretchFactor(2, 1);
+
+ dock = m_mainWindow->createDockWidget(CppLanguage, localsAndWatchers);
+ dock->setProperty(DOCKWIDGET_DEFAULT_AREA, Qt::RightDockWidgetArea);
+
+ m_debuggerSettings->readSettings();
+ GdbOptionsPage::readGdbBinarySettings();
+
+ // Register factory of DebuggerRunControl.
+ m_debuggerRunControlFactory = new DebuggerRunControlFactory
+ (m_plugin, DebuggerEngineType(m_cmdLineEnabledEngines));
+ m_plugin->addAutoReleasedObject(m_debuggerRunControlFactory);
+
+ // The main "Start Debugging" action.
+ act = m_debugAction = new QAction(this);
+ QIcon debuggerIcon(":/projectexplorer/images/debugger_start_small.png");
+ debuggerIcon.addFile(":/projectexplorer/images/debugger_start.png");
+ act->setIcon(debuggerIcon);
+ act->setText(tr("Start Debugging"));
+ connect(act, SIGNAL(triggered()), this, SLOT(debugProject()));
+
+ // Handling of external applications.
+ act = m_startExternalAction = new QAction(this);
+ act->setText(tr("Start and Debug External Application..."));
+ connect(act, SIGNAL(triggered()), SLOT(startExternalApplication()));
+
+ act = m_startRemoteLldbAction = new QAction(this);
+ act->setText(tr("Start and Debug External Application with External Engine..."));
+ connect(act, SIGNAL(triggered()), SLOT(startRemoteEngine()));
+
+ act = m_attachExternalAction = new QAction(this);
+ act->setText(tr("Attach to Running External Application..."));
+ connect(act, SIGNAL(triggered()), SLOT(attachExternalApplication()));
+
+ act = m_attachCoreAction = new QAction(this);
+ act->setText(tr("Attach to Core..."));
+ connect(act, SIGNAL(triggered()), SLOT(attachCore()));
+
+ act = m_attachTcfAction = new QAction(this);
+ act->setText(tr("Attach to Running Tcf Agent..."));
+ act->setToolTip(tr("This attaches to a running "
+ "'Target Communication Framework' agent."));
+ connect(act, SIGNAL(triggered()), SLOT(attachRemoteTcf()));
+
+ act = m_startRemoteAction = new QAction(this);
+ act->setText(tr("Start and Attach to Remote Application..."));
+ connect(act, SIGNAL(triggered()), SLOT(startRemoteApplication()));
+
+#ifdef Q_OS_WIN
+ m_startRemoteCdbAction = new QAction(tr("Attach to Remote CDB Session..."), this);
+ connect(m_startRemoteCdbAction, SIGNAL(triggered()), SLOT(startRemoteCdbSession()));
+#endif
+
+ act = m_detachAction = new QAction(this);
+ act->setText(tr("Detach Debugger"));
+ connect(act, SIGNAL(triggered()), SLOT(handleExecDetach()));
+
+ Command *cmd = 0;
+ ActionContainer *mstart = am->actionContainer(PE::M_DEBUG_STARTDEBUGGING);
+
+ cmd = am->registerAction(m_debugAction, Constants::DEBUG, globalcontext);
+ cmd->setAttribute(Core::Command::CA_UpdateText);
+ cmd->setAttribute(Core::Command::CA_UpdateIcon);
+ cmd->setDefaultText(tr("Start Debugging"));
+ cmd->setDefaultKeySequence(QKeySequence(Constants::DEBUG_KEY));
+ mstart->addAction(cmd, Core::Constants::G_DEFAULT_ONE);
+ Core::ICore::instance()->modeManager()->addAction(cmd, Constants::P_ACTION_DEBUG);
+
+ cmd = am->registerAction(m_actions.continueAction,
+ Constants::DEBUG, m_continuableContext);
+ mstart->addAction(cmd, CC::G_DEFAULT_ONE);
+
+ cmd = am->registerAction(m_startExternalAction,
+ Constants::STARTEXTERNAL, globalcontext);
+ cmd->setAttribute(Command::CA_Hide);
+ mstart->addAction(cmd, CC::G_DEFAULT_ONE);
+
+ cmd = am->registerAction(m_startRemoteLldbAction,
+ Constants::STARTREMOTELLDB, globalcontext);
+ cmd->setAttribute(Command::CA_Hide);
+ mstart->addAction(cmd, CC::G_DEFAULT_ONE);
+
+ cmd = am->registerAction(m_attachExternalAction,
+ Constants::ATTACHEXTERNAL, globalcontext);
+ cmd->setAttribute(Command::CA_Hide);
+ mstart->addAction(cmd, CC::G_DEFAULT_ONE);
+
+ cmd = am->registerAction(m_attachCoreAction,
+ Constants::ATTACHCORE, globalcontext);
+
+ cmd->setAttribute(Command::CA_Hide);
+ mstart->addAction(cmd, CC::G_DEFAULT_ONE);
+
+ cmd = am->registerAction(m_attachTcfAction,
+ Constants::ATTACHTCF, globalcontext);
+ mstart->addAction(cmd, CC::G_DEFAULT_ONE);
+
+ cmd = am->registerAction(m_startRemoteAction,
+ Constants::ATTACHREMOTE, globalcontext);
+ cmd->setAttribute(Command::CA_Hide);
+ mstart->addAction(cmd, CC::G_DEFAULT_ONE);
+
+ if (m_startRemoteCdbAction) {
+ cmd = am->registerAction(m_startRemoteCdbAction,
+ Constants::ATTACHREMOTECDB, globalcontext);
+ cmd->setAttribute(Command::CA_Hide);
+ mstart->addAction(cmd, CC::G_DEFAULT_ONE);
+ }
+
+ cmd = am->registerAction(m_detachAction,
+ Constants::DETACH, globalcontext);
+ cmd->setAttribute(Command::CA_Hide);
+ debugMenu->addAction(cmd, CC::G_DEFAULT_ONE);
+
+ cmd = am->registerAction(m_actions.exitAction,
+ Constants::STOP, globalcontext);
+ //cmd->setDefaultKeySequence(QKeySequence(Constants::STOP_KEY));
+ cmd->setDefaultText(tr("Stop Debugger"));
+ debugMenu->addAction(cmd, CC::G_DEFAULT_ONE);
+
+ cmd = am->registerAction(m_actions.interruptAction,
+ Constants::DEBUG, m_interruptibleContext);
+ cmd->setDefaultText(tr("Interrupt Debugger"));
+
+ cmd = am->registerAction(m_actions.undisturbableAction,
+ Constants::DEBUG, m_undisturbableContext);
+ cmd->setDefaultText(tr("Debugger is Busy"));
+
+ cmd = am->registerAction(m_actions.resetAction,
+ Constants::RESET, globalcontext);
+ //cmd->setDefaultKeySequence(QKeySequence(Constants::RESET_KEY));
+ cmd->setDefaultText(tr("Reset Debugger"));
+ debugMenu->addAction(cmd, CC::G_DEFAULT_ONE);
+
+ QAction *sep = new QAction(this);
+ sep->setSeparator(true);
+ cmd = am->registerAction(sep, _("Debugger.Sep.Step"), globalcontext);
+ debugMenu->addAction(cmd);
+
+ cmd = am->registerAction(m_actions.nextAction,
+ Constants::NEXT, cppDebuggercontext);
+ cmd->setDefaultKeySequence(QKeySequence(Constants::NEXT_KEY));
+ cmd->setAttribute(Command::CA_Hide);
+ debugMenu->addAction(cmd);
+
+ cmd = am->registerAction(m_actions.stepAction,
+ Constants::STEP, cppDebuggercontext);
+ cmd->setDefaultKeySequence(QKeySequence(Constants::STEP_KEY));
+ cmd->setAttribute(Command::CA_Hide);
+ debugMenu->addAction(cmd);
+
+ cmd = am->registerAction(m_actions.stepOutAction,
+ Constants::STEPOUT, cppDebuggercontext);
+ cmd->setDefaultKeySequence(QKeySequence(Constants::STEPOUT_KEY));
+ cmd->setAttribute(Command::CA_Hide);
+ debugMenu->addAction(cmd);
+
+ cmd = am->registerAction(m_actions.runToLineAction,
+ Constants::RUN_TO_LINE1, cppDebuggercontext);
+ cmd->setDefaultKeySequence(QKeySequence(Constants::RUN_TO_LINE_KEY));
+ cmd->setAttribute(Command::CA_Hide);
+ debugMenu->addAction(cmd);
+
+ cmd = am->registerAction(m_actions.runToFunctionAction,
+ Constants::RUN_TO_FUNCTION, cppDebuggercontext);
+ cmd->setDefaultKeySequence(QKeySequence(Constants::RUN_TO_FUNCTION_KEY));
+ cmd->setAttribute(Command::CA_Hide);
+ debugMenu->addAction(cmd);
+
+ cmd = am->registerAction(m_actions.jumpToLineAction,
+ Constants::JUMP_TO_LINE1, cppDebuggercontext);
+ cmd->setAttribute(Command::CA_Hide);
+ debugMenu->addAction(cmd);
+
+ cmd = am->registerAction(m_actions.returnFromFunctionAction,
+ Constants::RETURN_FROM_FUNCTION, cppDebuggercontext);
+ cmd->setAttribute(Command::CA_Hide);
+ debugMenu->addAction(cmd);
+
+ cmd = am->registerAction(m_actions.reverseDirectionAction,
+ Constants::REVERSE, cppDebuggercontext);
+ cmd->setDefaultKeySequence(QKeySequence(Constants::REVERSE_KEY));
+ cmd->setAttribute(Command::CA_Hide);
+ debugMenu->addAction(cmd);
+
+ sep = new QAction(this);
+ sep->setSeparator(true);
+ cmd = am->registerAction(sep, _("Debugger.Sep.Break"), globalcontext);
+ debugMenu->addAction(cmd);
+
+ //cmd = am->registerAction(m_actions.snapshotAction,
+ // Constants::SNAPSHOT, cppDebuggercontext);
+ //cmd->setDefaultKeySequence(QKeySequence(Constants::SNAPSHOT_KEY));
+ //cmd->setAttribute(Command::CA_Hide);
+ //debugMenu->addAction(cmd);
+
+ cmd = am->registerAction(m_actions.frameDownAction,
+ Constants::FRAME_DOWN, cppDebuggercontext);
+ cmd = am->registerAction(m_actions.frameUpAction,
+ Constants::FRAME_UP, cppDebuggercontext);
+
+ cmd = am->registerAction(action(OperateByInstruction),
+ Constants::OPERATE_BY_INSTRUCTION, cppDebuggercontext);
+ cmd->setAttribute(Command::CA_Hide);
+ debugMenu->addAction(cmd);
+
+ cmd = am->registerAction(m_actions.breakAction,
+ Constants::TOGGLE_BREAK, globalcontext);
+ cmd->setDefaultKeySequence(QKeySequence(Constants::TOGGLE_BREAK_KEY));
+ debugMenu->addAction(cmd);
+ connect(m_actions.breakAction, SIGNAL(triggered()),
+ SLOT(toggleBreakpoint()));
+
+ sep = new QAction(this);
+ sep->setSeparator(true);
+ cmd = am->registerAction(sep, _("Debugger.Sep.Watch"), globalcontext);
+ debugMenu->addAction(cmd);
+
+ cmd = am->registerAction(m_actions.watchAction1,
+ Constants::ADD_TO_WATCH1, cppeditorcontext);
+ cmd->action()->setEnabled(true);
+ //cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+D,Ctrl+W")));
+ debugMenu->addAction(cmd);
+
+
+ // Editor context menu
+ ActionContainer *editorContextMenu =
+ am->actionContainer(CppEditor::Constants::M_CONTEXT);
+ cmd = am->registerAction(sep, _("Debugger.Sep.Views"),
+ cppDebuggercontext);
+ editorContextMenu->addAction(cmd);
+ cmd->setAttribute(Command::CA_Hide);
+
+ cmd = am->registerAction(m_actions.watchAction2,
+ Constants::ADD_TO_WATCH2, cppDebuggercontext);
+ cmd->action()->setEnabled(true);
+ editorContextMenu->addAction(cmd);
+ cmd->setAttribute(Command::CA_Hide);
+
+ m_plugin->addAutoReleasedObject(new CommonOptionsPage);
+ QList<Core::IOptionsPage *> engineOptionPages;
+ if (m_cmdLineEnabledEngines & GdbEngineType)
+ addGdbOptionPages(&engineOptionPages);
+#ifdef CDB_ENABLED
+ if (m_cmdLineEnabledEngines & CdbEngineType)
+ addCdbOptionPages(&engineOptionPages);
+#endif
+#ifdef Q_OS_WIN
+ Debugger::Cdb::addCdb2OptionPages(&engineOptionPages);
+#endif
+#ifdef WITH_LLDB
+ if (m_cmdLineEnabledEngines & LldbEngineType)
+ addLldbOptionPages(&engineOptionPages);
+#endif
+
+ //if (m_cmdLineEnabledEngines & ScriptEngineType)
+ // addScriptOptionPages(&engineOptionPages);
+ //if (m_cmdLineEnabledEngines & TcfEngineType)
+ // addTcfOptionPages(&engineOptionPages);
+ foreach (Core::IOptionsPage *op, engineOptionPages)
+ m_plugin->addAutoReleasedObject(op);
+ m_plugin->addAutoReleasedObject(new DebuggingHelperOptionPage);
+
+ connect(ModeManager::instance(), SIGNAL(currentModeChanged(Core::IMode*)),
+ SLOT(onModeChanged(Core::IMode*)));
+
+
+ // Debug mode setup
+ m_plugin->addAutoReleasedObject(new DebugMode);
+
+ //
+ // Connections
+ //
+
+ // TextEditor
+ connect(TextEditorSettings::instance(),
+ SIGNAL(fontSettingsChanged(TextEditor::FontSettings)),
+ SLOT(fontSettingsChanged(TextEditor::FontSettings)));
+
+ // ProjectExplorer
+ connect(sessionManager(), SIGNAL(sessionLoaded()),
+ SLOT(sessionLoaded()));
+ connect(sessionManager(), SIGNAL(aboutToSaveSession()),
+ SLOT(aboutToSaveSession()));
+ connect(sessionManager(), SIGNAL(aboutToUnloadSession()),
+ SLOT(aboutToUnloadSession()));
+ connect(ProjectExplorerPlugin::instance(), SIGNAL(updateRunActions()),
+ SLOT(updateDebugActions()));
+
+ // EditorManager
+ QObject *editorManager = core->editorManager();
+ connect(editorManager, SIGNAL(editorAboutToClose(Core::IEditor*)),
+ SLOT(editorAboutToClose(Core::IEditor*)));
+ connect(editorManager, SIGNAL(editorOpened(Core::IEditor*)),
+ SLOT(editorOpened(Core::IEditor*)));
+
+ // Application interaction
+ connect(action(SettingsDialog), SIGNAL(triggered()),
+ SLOT(showSettingsDialog()));
+
+ // Toolbar
+ QWidget *toolbarContainer = new QWidget;
+
+ QHBoxLayout *hbox = new QHBoxLayout(toolbarContainer);
+ hbox->setMargin(0);
+ hbox->setSpacing(0);
+ hbox->addWidget(toolButton(am->command(Constants::DEBUG)->action()));
+ hbox->addWidget(toolButton(am->command(STOP)->action()));
+ hbox->addWidget(toolButton(am->command(NEXT)->action()));
+ hbox->addWidget(toolButton(am->command(STEP)->action()));
+ hbox->addWidget(toolButton(am->command(STEPOUT)->action()));
+ hbox->addWidget(toolButton(am->command(OPERATE_BY_INSTRUCTION)->action()));
+
+ //hbox->addWidget(new Utils::StyledSeparator);
+ m_reverseToolButton = toolButton(am->command(REVERSE)->action());
+ hbox->addWidget(m_reverseToolButton);
+ //m_reverseToolButton->hide();
+
+ hbox->addWidget(new Utils::StyledSeparator);
+ hbox->addWidget(new QLabel(tr("Threads:")));
+
+ m_threadBox = new QComboBox;
+ connect(m_threadBox, SIGNAL(activated(int)), SLOT(selectThread(int)));
+
+ hbox->addWidget(m_threadBox);
+ hbox->addSpacerItem(new QSpacerItem(4, 0));
+ hbox->addWidget(m_statusLabel, 10);
+
+ m_mainWindow->setToolbar(CppLanguage, toolbarContainer);
+
+ connect(action(EnableReverseDebugging),
+ SIGNAL(valueChanged(QVariant)),
+ SLOT(enableReverseDebuggingTriggered(QVariant)));
+
+ setInitialState();
+ connectEngine(0);
+
+ connect(sessionManager(),
+ SIGNAL(startupProjectChanged(ProjectExplorer::Project*)),
+ SLOT(onCurrentProjectChanged(ProjectExplorer::Project*)));
+
+ QTC_ASSERT(m_coreSettings, /**/);
+ m_watchersWindow->setVisible(false);
+ m_returnWindow->setVisible(false);
// time gdb -i mi -ex 'debuggerplugin.cpp:800' -ex r -ex q bin/qtcreator.bin
const QByteArray env = qgetenv("QTC_DEBUGGER_TEST");
//qDebug() << "EXTENSIONS INITIALIZED:" << env;
// if (!env.isEmpty())
// m_plugin->runTest(QString::fromLocal8Bit(env));
- if (d->m_attachRemoteParameters.attachPid
- || !d->m_attachRemoteParameters.attachTarget.isEmpty())
- QTimer::singleShot(0, d, SLOT(attachCmdLine()));
+ if (m_attachRemoteParameters.attachPid
+ || !m_attachRemoteParameters.attachTarget.isEmpty())
+ QTimer::singleShot(0, this, SLOT(attachCmdLine()));
}
-QWidget *DebuggerPlugin::mainWindow() const
+Utils::SavedAction *DebuggerPluginPrivate::action(int code) const
{
- return d->m_uiSwitcher->mainWindow();
+ return m_debuggerSettings->item(code);
}
-DebuggerRunControl *DebuggerPlugin::createDebugger
- (const DebuggerStartParameters &sp, RunConfiguration *rc)
+bool DebuggerPluginPrivate::boolSetting(int code) const
{
- return instance()->d->createDebugger(sp, rc);
+ return m_debuggerSettings->item(code)->value().toBool();
}
-void DebuggerPlugin::startDebugger(RunControl *runControl)
+QString DebuggerPluginPrivate::stringSetting(int code) const
{
- instance()->d->startDebugger(runControl);
+ return m_debuggerSettings->item(code)->value().toString();
}
-void DebuggerPlugin::displayDebugger(RunControl *runControl)
+void DebuggerPluginPrivate::showModuleSymbols(const QString &moduleName,
+ const Symbols &symbols)
{
- DebuggerRunControl *rc = qobject_cast<DebuggerRunControl *>(runControl);
- QTC_ASSERT(rc, return);
- instance()->d->displayDebugger(rc->engine());
+ QTreeWidget *w = new QTreeWidget;
+ w->setColumnCount(5);
+ w->setRootIsDecorated(false);
+ w->setAlternatingRowColors(true);
+ w->setSortingEnabled(true);
+ w->setObjectName("Symbols." + moduleName);
+ QStringList header;
+ header.append(tr("Symbol"));
+ header.append(tr("Address"));
+ header.append(tr("Code"));
+ header.append(tr("Section"));
+ header.append(tr("Name"));
+ w->setHeaderLabels(header);
+ w->setWindowTitle(tr("Symbols in \"%1\"").arg(moduleName));
+ foreach (const Symbol &s, symbols) {
+ QTreeWidgetItem *it = new QTreeWidgetItem;
+ it->setData(0, Qt::DisplayRole, s.name);
+ it->setData(1, Qt::DisplayRole, s.address);
+ it->setData(2, Qt::DisplayRole, s.state);
+ it->setData(3, Qt::DisplayRole, s.section);
+ it->setData(4, Qt::DisplayRole, s.demangled);
+ w->addTopLevelItem(it);
+ }
+ createNewDock(w);
}
-// if updateEngine is set, the engine will update its threads/modules and so forth.
-void DebuggerPlugin::displayDebugger(DebuggerEngine *engine, bool updateEngine)
+void DebuggerPluginPrivate::aboutToShutdown()
{
- instance()->d->displayDebugger(engine, updateEngine);
+ disconnect(sessionManager(),
+ SIGNAL(startupProjectChanged(ProjectExplorer::Project*)),
+ this, 0);
+ m_debuggerSettings->writeSettings();
+ m_mainWindow->writeSettings();
+ if (GdbOptionsPage::gdbBinariesChanged)
+ GdbOptionsPage::writeGdbBinarySettings();
}
-void DebuggerPlugin::updateState(DebuggerEngine *engine)
+} // namespace Internal
+
+
+///////////////////////////////////////////////////////////////////////
+//
+// DebuggerPlugin
+//
+///////////////////////////////////////////////////////////////////////
+
+using namespace Debugger::Internal;
+
+DebuggerPlugin::DebuggerPlugin()
{
- d->updateState(engine);
+ theDebuggerCore = new DebuggerPluginPrivate(this);
}
-void DebuggerPlugin::activateDebugMode()
+DebuggerPlugin::~DebuggerPlugin()
{
- d->activateDebugMode();
+ delete theDebuggerCore;
+ theDebuggerCore = 0;
}
-void DebuggerPlugin::createNewDock(QWidget *widget)
+bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMessage)
{
- QDockWidget *dockWidget =
- DebuggerUISwitcher::instance()->createDockWidget(CppLanguage, widget);
- dockWidget->setWindowTitle(widget->windowTitle());
- dockWidget->setObjectName(widget->windowTitle());
- dockWidget->setFeatures(QDockWidget::DockWidgetClosable);
- //dockWidget->setWidget(widget);
- //mainWindow()->addDockWidget(Qt::TopDockWidgetArea, dockWidget);
- dockWidget->show();
+ return theDebuggerCore->initialize(arguments, errorMessage);
}
-void DebuggerPlugin::runControlStarted(DebuggerRunControl *runControl)
+ExtensionSystem::IPlugin::ShutdownFlag DebuggerPlugin::aboutToShutdown()
{
- d->connectEngine(runControl->engine());
- d->m_snapshotHandler->appendSnapshot(runControl);
+ theDebuggerCore->aboutToShutdown();
+ return SynchronousShutdown;
}
-void DebuggerPlugin::runControlFinished(DebuggerRunControl *runControl)
+void DebuggerPlugin::remoteCommand(const QStringList &options,
+ const QStringList &list)
{
- Q_UNUSED(runControl);
- d->m_snapshotHandler->removeSnapshot(runControl);
- d->disconnectEngine();
- if (theDebuggerBoolSetting(SwitchModeOnExit))
- if (d->m_snapshotHandler->size() == 0)
- d->activatePreviousMode();
+ theDebuggerCore->remoteCommand(options, list);
}
-DebuggerLanguages DebuggerPlugin::activeLanguages() const
+
+DebuggerRunControl *DebuggerPlugin::createDebugger
+ (const DebuggerStartParameters &sp, RunConfiguration *rc)
{
- return DebuggerUISwitcher::instance()->activeDebugLanguages();
+ return theDebuggerCore->createDebugger(sp, rc);
}
-DebuggerEngine *DebuggerPlugin::sessionTemplate()
+void DebuggerPlugin::startDebugger(RunControl *runControl)
{
- return d->m_sessionEngine;
+ theDebuggerCore->startDebugger(runControl);
}
-bool DebuggerPlugin::isRegisterViewVisible() const
+void DebuggerPlugin::extensionsInitialized()
{
- return d->m_registerDock->toggleViewAction()->isChecked();
+ theDebuggerCore->extensionsInitialized();
}
-bool DebuggerPlugin::hasSnapsnots() const
+bool DebuggerPlugin::isActiveDebugLanguage(int language)
{
- return d->m_snapshotHandler->size();
+ return theDebuggerCore->isActiveDebugLanguage(language);
}
-void DebuggerPlugin::remoteCommand(const QStringList &options, const QStringList &)
+DebuggerMainWindow *DebuggerPlugin::mainWindow()
{
- if (options.isEmpty())
- return;
-
- unsigned enabledEngines = 0;
- QString errorMessage;
- bool success = false;
- do {
- if (!parseArguments(options, &d->m_attachRemoteParameters, &enabledEngines, &errorMessage))
- break;
-
- if (!d->attachCmdLine()) {
- errorMessage = QString::fromLatin1("Incomplete remote attach command received: %1").
- arg(options.join(QString(QLatin1Char(' '))));
- break;
- }
- success = true;
- } while (false);
+ return theDebuggerCore->m_mainWindow;
+}
- if (!success)
- qWarning("%s", qPrintable(errorMessage));
+QWidget *DebugMode::widget()
+{
+ if (!m_widget) {
+ //qDebug() << "CREATING DEBUG MODE WIDGET";
+ m_widget = theDebuggerCore->m_mainWindow->createContents(this);
+ m_widget->setFocusProxy(EditorManager::instance());
+ }
+ return m_widget;
}
//////////////////////////////////////////////////////////////////////
diff --git a/src/plugins/debugger/debuggerplugin.h b/src/plugins/debugger/debuggerplugin.h
index d354c115f7..bb811bf9f2 100644
--- a/src/plugins/debugger/debuggerplugin.h
+++ b/src/plugins/debugger/debuggerplugin.h
@@ -35,18 +35,10 @@
#define DEBUGGERPLUGIN_H
#include "debugger_global.h"
-#include "debuggerconstants.h"
#include <extensionsystem/iplugin.h>
-QT_BEGIN_NAMESPACE
-class QIcon;
-class QMessageBox;
-QT_END_NAMESPACE
-
-namespace CPlusPlus {
-class Snapshot;
-}
+#include <QtCore/QObject>
namespace ProjectExplorer {
class RunConfiguration;
@@ -54,14 +46,15 @@ class RunControl;
}
namespace Debugger {
-class DebuggerEngine;
-class DebuggerPluginPrivate;
+
+class DebuggerMainWindow;
class DebuggerRunControl;
class DebuggerStartParameters;
-namespace Internal {
-class DebuggerListener;
-}
+// This is the "external" interface of the debugger plugin that's visible
+// from Qt Creator core. The internal interface to global debugger
+// functionality that is used by debugger views and debugger engines
+// is DebuggerCore, implemented in DebuggerPluginPrivate.
class DEBUGGER_EXPORT DebuggerPlugin : public ExtensionSystem::IPlugin
{
@@ -71,67 +64,21 @@ public:
DebuggerPlugin();
~DebuggerPlugin();
- static DebuggerPlugin *instance();
-
+ // Used by Maemo debugging support.
static DebuggerRunControl *createDebugger(const DebuggerStartParameters &sp,
ProjectExplorer::RunConfiguration *rc = 0);
static void startDebugger(ProjectExplorer::RunControl *runControl);
- static void displayDebugger(ProjectExplorer::RunControl *runControl);
- static void displayDebugger(DebuggerEngine *engine, bool updateEngine = true);
-
- QVariant sessionValue(const QString &name);
- void setSessionValue(const QString &name, const QVariant &value);
- QVariant configValue(const QString &name) const;
- void setConfigValue(const QString &name, const QVariant &value);
- void updateState(DebuggerEngine *engine);
- virtual void remoteCommand(const QStringList &options, const QStringList &arguments);
-
- QIcon locationMarkIcon() const;
- void activateDebugMode();
-
- const CPlusPlus::Snapshot &cppCodeModelSnapshot() const;
- bool isRegisterViewVisible() const;
- bool hasSnapsnots() const;
-
- void openTextEditor(const QString &titlePattern, const QString &contents);
-public slots:
- void clearCppCodeModelSnapshot();
- void ensureLogVisible();
-
- // void runTest(const QString &fileName);
- void showMessage(const QString &msg, int channel, int timeout = -1);
+ // Used by QmlJSInspector.
+ static bool isActiveDebugLanguage(int language);
+ static DebuggerMainWindow *mainWindow();
private:
- friend class DebuggerEngine;
- friend class DebuggerPluginPrivate;
- friend class DebuggerRunControl;
-
- void resetLocation();
- void gotoLocation(const QString &fileName, int lineNumber, bool setMarker);
- void readSettings();
- void writeSettings() const;
-
- bool isReverseDebugging() const;
- void createNewDock(QWidget *widget);
- void runControlStarted(DebuggerRunControl *runControl);
- void runControlFinished(DebuggerRunControl *runControl);
- DebuggerLanguages activeLanguages() const;
-
- // This contains per-session data like breakpoints and watched
- // expression. It serves as a template for new engine instantiations.
- DebuggerEngine *sessionTemplate();
-
- QMessageBox *showMessageBox(int icon, const QString &title,
- const QString &text, int buttons = 0);
-
+ // IPlugin implementation.
bool initialize(const QStringList &arguments, QString *errorMessage);
+ void remoteCommand(const QStringList &options, const QStringList &arguments);
ShutdownFlag aboutToShutdown();
void extensionsInitialized();
-
- QWidget *mainWindow() const;
-
- DebuggerPluginPrivate *d;
};
} // namespace Debugger
diff --git a/src/plugins/debugger/debuggerrunner.cpp b/src/plugins/debugger/debuggerrunner.cpp
index b3c2292e65..eb274835ef 100644
--- a/src/plugins/debugger/debuggerrunner.cpp
+++ b/src/plugins/debugger/debuggerrunner.cpp
@@ -34,16 +34,13 @@
#include "debuggerrunner.h"
#include "debuggeractions.h"
-#include "debuggerconstants.h"
+#include "debuggercore.h"
#include "debuggerengine.h"
+#include "debuggermainwindow.h"
#include "debuggerplugin.h"
#include "debuggerstringutils.h"
-#include "debuggeruiswitcher.h"
-#include "gdb/gdbengine.h"
-#include "gdb/remotegdbserveradapter.h"
-#include "gdb/remoteplaingdbadapter.h"
-#include "qml/qmlengine.h"
-#include "qml/qmlcppengine.h"
+#include "gdb/gdboptionspage.h"
+#include "lldb/lldbenginehost.h"
#ifdef Q_OS_WIN
# include "peutils.h"
@@ -51,33 +48,31 @@
#include <projectexplorer/debugginghelper.h>
#include <projectexplorer/project.h>
-#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/toolchain.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/target.h>
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/applicationrunconfiguration.h> // For LocalApplication*
-#include <utils/environment.h>
#include <utils/synchronousprocess.h>
#include <utils/qtcassert.h>
#include <utils/fancymainwindow.h>
+#include <utils/qtcprocess.h>
#include <coreplugin/icore.h>
-#include <QtCore/QDebug>
#include <QtCore/QDir>
-#include <QtCore/QFileInfo>
-#include <QtCore/QTimer>
-#include <QtCore/QStringList>
-
-#include <QtGui/QAbstractItemView>
-#include <QtGui/QTextDocument>
-#include <QtGui/QTreeWidget>
#include <QtGui/QMessageBox>
using namespace ProjectExplorer;
using namespace Debugger::Internal;
namespace Debugger {
+
+namespace Cdb {
+DebuggerEngine *createCdbEngine(const DebuggerStartParameters &, QString *error);
+bool isCdbEngineEnabled(); // Check the configuration page
+}
+
namespace Internal {
DebuggerEngine *createGdbEngine(const DebuggerStartParameters &);
@@ -86,8 +81,9 @@ DebuggerEngine *createPdbEngine(const DebuggerStartParameters &);
DebuggerEngine *createTcfEngine(const DebuggerStartParameters &);
DebuggerEngine *createQmlEngine(const DebuggerStartParameters &);
DebuggerEngine *createQmlCppEngine(const DebuggerStartParameters &);
+DebuggerEngine *createLldbEngine(const DebuggerStartParameters &);
-bool checkGdbConfiguration(int toolChain, QString *errorMsg, QString *settingsPage);
+extern QString msgNoBinaryForToolChain(int tc);
// FIXME: Outdated?
// The createCdbEngine function takes a list of options pages it can add to.
@@ -96,27 +92,24 @@ bool checkGdbConfiguration(int toolChain, QString *errorMsg, QString *settingsPa
// unnecessarily.
#ifdef CDB_ENABLED
-DebuggerEngine *createCdbEngine(const DebuggerStartParameters &, QString *errorMessage);
+
+DebuggerEngine *createCdbEngine(const DebuggerStartParameters &, QString *error);
bool checkCdbConfiguration(int toolChain, QString *errorMsg, QString *settingsPage);
bool isCdbEngineEnabled(); // Check the configuration page
-#else
-DebuggerEngine *createCdbEngine(const DebuggerStartParameters &, QString *) { return 0; }
-bool checkCdbConfiguration(int, QString *, QString *) { return false; }
-#endif
-} // namespace Internal
+#else
-static QString toolChainName(int toolChainType)
+DebuggerEngine *createCdbEngine(const DebuggerStartParameters &, QString *)
{
- return ToolChain::toolChainName(ToolChain::ToolChainType(toolChainType));
+ return 0;
}
+bool checkCdbConfiguration(int, QString *, QString *)
+{
+ return false;
+}
-////////////////////////////////////////////////////////////////////////
-//
-// DebuggerRunControlFactory
-//
-////////////////////////////////////////////////////////////////////////
+#endif
static QString msgEngineNotAvailable(const char *engine)
{
@@ -124,142 +117,26 @@ static QString msgEngineNotAvailable(const char *engine)
"which is disabled.").arg(QLatin1String(engine));
}
-static DebuggerPlugin *plugin() { return DebuggerPlugin::instance(); }
-
-// A factory to create DebuggerRunControls
-DebuggerRunControlFactory::DebuggerRunControlFactory(QObject *parent,
- unsigned enabledEngines)
- : IRunControlFactory(parent), m_enabledEngines(enabledEngines)
-{}
-
-bool DebuggerRunControlFactory::canRun(RunConfiguration *runConfiguration, const QString &mode) const
-{
-// return mode == ProjectExplorer::Constants::DEBUGMODE;
- return mode == ProjectExplorer::Constants::DEBUGMODE
- && qobject_cast<LocalApplicationRunConfiguration *>(runConfiguration);
-}
-
-QString DebuggerRunControlFactory::displayName() const
-{
- return tr("Debug");
-}
-
-// Find Qt installation by running qmake
-static inline QString findQtInstallPath(const QString &qmakePath)
-{
- QProcess proc;
- QStringList args;
- args.append(QLatin1String("-query"));
- args.append(QLatin1String("QT_INSTALL_HEADERS"));
- proc.start(qmakePath, args);
- if (!proc.waitForStarted()) {
- qWarning("%s: Cannot start '%s': %s", Q_FUNC_INFO, qPrintable(qmakePath),
- qPrintable(proc.errorString()));
- return QString();
- }
- proc.closeWriteChannel();
- if (!proc.waitForFinished()) {
- Utils::SynchronousProcess::stopProcess(proc);
- qWarning("%s: Timeout running '%s'.", Q_FUNC_INFO, qPrintable(qmakePath));
- return QString();
- }
- if (proc.exitStatus() != QProcess::NormalExit) {
- qWarning("%s: '%s' crashed.", Q_FUNC_INFO, qPrintable(qmakePath));
- return QString();
- }
- const QByteArray ba = proc.readAllStandardOutput().trimmed();
- QDir dir(QString::fromLocal8Bit(ba));
- if (dir.exists() && dir.cdUp())
- return dir.absolutePath();
- return QString();
-}
-
-static DebuggerStartParameters localStartParameters(RunConfiguration *runConfiguration)
-{
- DebuggerStartParameters sp;
- QTC_ASSERT(runConfiguration, return sp);
- LocalApplicationRunConfiguration *rc =
- qobject_cast<LocalApplicationRunConfiguration *>(runConfiguration);
- QTC_ASSERT(rc, return sp);
-
- sp.startMode = StartInternal;
- sp.environment = rc->environment().toStringList();
- sp.workingDirectory = rc->workingDirectory();
- sp.executable = rc->executable();
- sp.processArgs = rc->commandLineArguments();
- sp.toolChainType = rc->toolChainType();
- sp.useTerminal = rc->runMode() == LocalApplicationRunConfiguration::Console;
- sp.dumperLibrary = rc->dumperLibrary();
- sp.dumperLibraryLocations = rc->dumperLibraryLocations();
-
- DebuggerLanguages activeLangs = DebuggerUISwitcher::instance()->activeDebugLanguages();
- if (activeLangs & QmlLanguage) {
- sp.qmlServerAddress = QLatin1String("127.0.0.1");
- sp.qmlServerPort = runConfiguration->qmlDebugServerPort();
-
- sp.projectDir = runConfiguration->target()->project()->projectDirectory();
- if (runConfiguration->target()->activeBuildConfiguration())
- sp.projectBuildDir = runConfiguration->target()->activeBuildConfiguration()->buildDirectory();
-
- sp.processArgs.append(QLatin1String("-qmljsdebugger=port:") + QString::number(sp.qmlServerPort));
- }
-
- // FIXME: If it's not yet build this will be empty and not filled
- // when rebuild as the runConfiguration is not stored and therefore
- // cannot be used to retrieve the dumper location.
- //qDebug() << "DUMPER: " << sp.dumperLibrary << sp.dumperLibraryLocations;
- sp.displayName = rc->displayName();
-
- // Find qtInstallPath.
- QString qmakePath = DebuggingHelperLibrary::findSystemQt(rc->environment());
- if (!qmakePath.isEmpty())
- sp.qtInstallPath = findQtInstallPath(qmakePath);
- return sp;
-}
-
-RunControl *DebuggerRunControlFactory::create
- (RunConfiguration *runConfiguration, const QString &mode)
-{
- QTC_ASSERT(mode == ProjectExplorer::Constants::DEBUGMODE, return 0);
- DebuggerStartParameters sp = localStartParameters(runConfiguration);
- return create(sp, runConfiguration);
-}
-
-DebuggerRunControl *DebuggerRunControlFactory::create(
- const DebuggerStartParameters &sp,
- RunConfiguration *runConfiguration)
-{
- DebuggerRunControl *runControl =
- new DebuggerRunControl(runConfiguration, m_enabledEngines, sp);
- if (!runControl->engine()) {
- qDebug() << "FAILED TO CREATE ENGINE";
- delete runControl;
- return 0;
- }
- return runControl;
-}
-
-QWidget *DebuggerRunControlFactory::createConfigurationWidget
- (RunConfiguration *runConfiguration)
-{
- // NBS TODO: Add GDB-specific configuration widget
- Q_UNUSED(runConfiguration)
- return 0;
-}
-
-
////////////////////////////////////////////////////////////////////////
//
-// DebuggerRunControl
+// DebuggerRunControlPrivate
//
////////////////////////////////////////////////////////////////////////
-struct DebuggerRunnerPrivate {
- explicit DebuggerRunnerPrivate(RunConfiguration *runConfiguration,
- unsigned enabledEngines);
-
+class DebuggerRunControlPrivate
+{
+public:
+ DebuggerRunControlPrivate(DebuggerRunControl *parent,
+ RunConfiguration *runConfiguration, unsigned enabledEngines);
unsigned enabledEngines() const;
+ DebuggerEngineType engineForExecutable(unsigned enabledEngineTypes,
+ const QString &executable);
+ DebuggerEngineType engineForMode(unsigned enabledEngineTypes,
+ DebuggerStartMode mode);
+
+public:
+ DebuggerRunControl *q;
DebuggerEngine *m_engine;
const QWeakPointer<RunConfiguration> m_myRunConfiguration;
bool m_running;
@@ -268,100 +145,41 @@ struct DebuggerRunnerPrivate {
QString m_settingsIdHint;
};
-unsigned DebuggerRunnerPrivate::enabledEngines() const
+unsigned DebuggerRunControlPrivate::enabledEngines() const
{
unsigned rc = m_cmdLineEnabledEngines;
#ifdef CDB_ENABLED
- if (!Internal::isCdbEngineEnabled())
+ if (!isCdbEngineEnabled() && !Cdb::isCdbEngineEnabled())
rc &= ~CdbEngineType;
#endif
return rc;
}
-DebuggerRunnerPrivate::DebuggerRunnerPrivate(RunConfiguration *runConfiguration,
- unsigned enabledEngines) :
- m_engine(0)
+DebuggerRunControlPrivate::DebuggerRunControlPrivate(DebuggerRunControl *parent,
+ RunConfiguration *runConfiguration, unsigned enabledEngines)
+ : q(parent)
+ , m_engine(0)
, m_myRunConfiguration(runConfiguration)
, m_running(false)
, m_cmdLineEnabledEngines(enabledEngines)
{
}
-DebuggerRunControl::DebuggerRunControl(RunConfiguration *runConfiguration,
- unsigned enabledEngines, const DebuggerStartParameters &sp)
- : RunControl(runConfiguration, ProjectExplorer::Constants::DEBUGMODE),
- d(new DebuggerRunnerPrivate(runConfiguration, enabledEngines))
-{
- connect(this, SIGNAL(finished()), this, SLOT(handleFinished()));
- DebuggerStartParameters startParams = sp;
- createEngine(startParams);
-}
-
-DebuggerRunControl::~DebuggerRunControl()
-{
- disconnect();
- if (DebuggerEngine *engine = d->m_engine) {
- d->m_engine = 0;
- engine->disconnect();
- delete engine;
- }
-}
-
-const DebuggerStartParameters &DebuggerRunControl::startParameters() const
-{
- QTC_ASSERT(d->m_engine, return *(new DebuggerStartParameters()));
- return d->m_engine->startParameters();
-}
-
-static DebuggerEngineType engineForToolChain(int toolChainType)
-{
- switch (toolChainType) {
- case ProjectExplorer::ToolChain::LINUX_ICC:
- case ProjectExplorer::ToolChain::MinGW:
- case ProjectExplorer::ToolChain::GCC:
- case ProjectExplorer::ToolChain::WINSCW: // S60
- case ProjectExplorer::ToolChain::GCCE:
- case ProjectExplorer::ToolChain::RVCT_ARMV5:
- case ProjectExplorer::ToolChain::RVCT_ARMV6:
- case ProjectExplorer::ToolChain::RVCT_ARMV5_GNUPOC:
- case ProjectExplorer::ToolChain::GCCE_GNUPOC:
- case ProjectExplorer::ToolChain::GCC_MAEMO:
- return GdbEngineType;
-
- case ProjectExplorer::ToolChain::MSVC:
- case ProjectExplorer::ToolChain::WINCE:
- return CdbEngineType;
-
- case ProjectExplorer::ToolChain::OTHER:
- case ProjectExplorer::ToolChain::UNKNOWN:
- case ProjectExplorer::ToolChain::INVALID:
- default:
- break;
- }
- return NoEngineType;
-}
-
-
// Figure out the debugger type of an executable. Analyze executable
// unless the toolchain provides a hint.
-DebuggerEngineType DebuggerRunControl::engineForExecutable(unsigned enabledEngineTypes, const QString &executable)
+DebuggerEngineType DebuggerRunControlPrivate::engineForExecutable
+ (unsigned enabledEngineTypes, const QString &executable)
{
- /*if (executable.endsWith(_("qmlviewer"))) {
- if (enabledEngineTypes & QmlEngineType)
- return QmlEngineType;
- d->m_errorMessage = msgEngineNotAvailable("Qml Engine");
- }*/
-
if (executable.endsWith(_(".js"))) {
if (enabledEngineTypes & ScriptEngineType)
return ScriptEngineType;
- d->m_errorMessage = msgEngineNotAvailable("Script Engine");
+ m_errorMessage = msgEngineNotAvailable("Script Engine");
}
if (executable.endsWith(_(".py"))) {
if (enabledEngineTypes & PdbEngineType)
return PdbEngineType;
- d->m_errorMessage = msgEngineNotAvailable("Pdb Engine");
+ m_errorMessage = msgEngineNotAvailable("Pdb Engine");
}
#ifdef Q_OS_WIN
@@ -371,33 +189,35 @@ DebuggerEngineType DebuggerRunControl::engineForExecutable(unsigned enabledEngin
// If a file has PDB files, it has been compiled by VS.
QStringList pdbFiles;
- if (!getPDBFiles(executable, &pdbFiles, &d->m_errorMessage)) {
+ if (!getPDBFiles(executable, &pdbFiles, &m_errorMessage)) {
qWarning("Cannot determine type of executable %s: %s",
- qPrintable(executable), qPrintable(d->m_errorMessage));
+ qPrintable(executable), qPrintable(m_errorMessage));
return NoEngineType;
}
if (pdbFiles.empty())
return GdbEngineType;
// We need the CDB debugger in order to be able to debug VS
- // executables
- if (checkDebugConfiguration(ToolChain::MSVC, &d->m_errorMessage, 0, &d->m_settingsIdHint)) {
+ // executables.
+ if (DebuggerRunControl::checkDebugConfiguration(ProjectExplorer::ToolChain_MSVC,
+ &m_errorMessage, 0, &m_settingsIdHint)) {
if (enabledEngineTypes & CdbEngineType)
return CdbEngineType;
- d->m_errorMessage = msgEngineNotAvailable("Cdb Engine");
+ m_errorMessage = msgEngineNotAvailable("Cdb Engine");
return NoEngineType;
}
#else
if (enabledEngineTypes & GdbEngineType)
return GdbEngineType;
- d->m_errorMessage = msgEngineNotAvailable("Gdb Engine");
+ m_errorMessage = msgEngineNotAvailable("Gdb Engine");
#endif
return NoEngineType;
}
// Debugger type for mode.
-DebuggerEngineType DebuggerRunControl::engineForMode(unsigned enabledEngineTypes, DebuggerStartMode startMode)
+DebuggerEngineType DebuggerRunControlPrivate::engineForMode
+ (unsigned enabledEngineTypes, DebuggerStartMode startMode)
{
if (startMode == AttachTcf)
return TcfEngineType;
@@ -407,25 +227,72 @@ DebuggerEngineType DebuggerRunControl::engineForMode(unsigned enabledEngineTypes
if (startMode != AttachToRemote && (enabledEngineTypes & CdbEngineType))
return CdbEngineType;
if (startMode == AttachCrashedExternal) {
- d->m_errorMessage = tr("There is no debugging engine available for post-mortem debugging.");
+ m_errorMessage = DebuggerRunControl::tr("There is no debugging engine available for post-mortem debugging.");
return NoEngineType;
}
return GdbEngineType;
#else
Q_UNUSED(startMode)
Q_UNUSED(enabledEngineTypes)
- // d->m_errorMessage = msgEngineNotAvailable("Gdb Engine");
+ // >m_errorMessage = msgEngineNotAvailable("Gdb Engine");
return GdbEngineType;
#endif
}
-void DebuggerRunControl::createEngine(const DebuggerStartParameters &startParams)
+} // namespace Internal
+
+
+////////////////////////////////////////////////////////////////////////
+//
+// DebuggerRunControl
+//
+////////////////////////////////////////////////////////////////////////
+
+static DebuggerEngineType engineForToolChain(int toolChainType)
+{
+ switch (toolChainType) {
+ case ProjectExplorer::ToolChain_LINUX_ICC:
+ case ProjectExplorer::ToolChain_MinGW:
+ case ProjectExplorer::ToolChain_GCC:
+ case ProjectExplorer::ToolChain_WINSCW: // S60
+ case ProjectExplorer::ToolChain_GCCE:
+ case ProjectExplorer::ToolChain_RVCT2_ARMV5:
+ case ProjectExplorer::ToolChain_RVCT2_ARMV6:
+ case ProjectExplorer::ToolChain_RVCT_ARMV5_GNUPOC:
+ case ProjectExplorer::ToolChain_GCCE_GNUPOC:
+ case ProjectExplorer::ToolChain_GCC_MAEMO:
+#ifdef WITH_LLDB
+ // lldb override
+ if (Core::ICore::instance()->settings()->value("LLDB/enabled").toBool())
+ return LldbEngineType;
+#endif
+ return GdbEngineType;
+
+
+ case ProjectExplorer::ToolChain_MSVC:
+ case ProjectExplorer::ToolChain_WINCE:
+ return CdbEngineType;
+
+ case ProjectExplorer::ToolChain_OTHER:
+ case ProjectExplorer::ToolChain_UNKNOWN:
+ case ProjectExplorer::ToolChain_INVALID:
+ default:
+ break;
+ }
+ return NoEngineType;
+}
+
+DebuggerRunControl::DebuggerRunControl(RunConfiguration *runConfiguration,
+ unsigned enabledEngines, const DebuggerStartParameters &startParams)
+ : RunControl(runConfiguration, Constants::DEBUGMODE),
+ d(new DebuggerRunControlPrivate(this, runConfiguration, enabledEngines))
{
- DebuggerStartParameters sp = startParams;
+ connect(this, SIGNAL(finished()), SLOT(handleFinished()));
// Figure out engine according to toolchain, executable, attach or default.
DebuggerEngineType engineType = NoEngineType;
- DebuggerLanguages activeLangs = DebuggerPlugin::instance()->activeLanguages();
+ DebuggerLanguages activeLangs = debuggerCore()->activeLanguages();
+ DebuggerStartParameters sp = startParams;
const unsigned enabledEngineTypes = d->enabledEngines();
if (sp.executable.endsWith(_(".js")))
engineType = ScriptEngineType;
@@ -439,17 +306,22 @@ void DebuggerRunControl::createEngine(const DebuggerStartParameters &startParams
}
}
- // Fixme: 1 of 3 testing hacks.
- if (sp.processArgs.size() >= 5 && sp.processArgs.at(0) == _("@tcf@"))
+ // FIXME: Unclean ipc override. Someone please have a better idea.
+ if (sp.startMode == StartRemoteEngine)
+ // For now thats the only supported IPC engine.
+ engineType = LldbEngineType;
+
+ // FIXME: 1 of 3 testing hacks.
+ if (sp.processArgs.startsWith(__("@tcf@ ")))
engineType = GdbEngineType;
if (engineType == NoEngineType
&& sp.startMode != AttachToRemote
&& !sp.executable.isEmpty())
- engineType = engineForExecutable(enabledEngineTypes, sp.executable);
+ engineType = d->engineForExecutable(enabledEngineTypes, sp.executable);
if (engineType == NoEngineType)
- engineType = engineForMode(enabledEngineTypes, sp.startMode);
+ engineType = d->engineForMode(enabledEngineTypes, sp.startMode);
if ((engineType != QmlEngineType && engineType != NoEngineType)
&& (activeLangs & QmlLanguage)) {
@@ -466,63 +338,64 @@ void DebuggerRunControl::createEngine(const DebuggerStartParameters &startParams
switch (engineType) {
case GdbEngineType:
d->m_engine = createGdbEngine(sp);
- initGdbEngine(qobject_cast<Internal::GdbEngine *>(d->m_engine));
break;
case ScriptEngineType:
- d->m_engine = Internal::createScriptEngine(sp);
+ d->m_engine = createScriptEngine(sp);
break;
case CdbEngineType:
- d->m_engine = Internal::createCdbEngine(sp, &d->m_errorMessage);
+ // Try new engine, fall back to old.
+ if (Cdb::isCdbEngineEnabled())
+ d->m_engine = Cdb::createCdbEngine(sp, &d->m_errorMessage);
+ else
+ d->m_engine = Internal::createCdbEngine(sp, &d->m_errorMessage);
break;
case PdbEngineType:
- d->m_engine = Internal::createPdbEngine(sp);
+ d->m_engine = createPdbEngine(sp);
break;
case TcfEngineType:
- d->m_engine = Internal::createTcfEngine(sp);
+ d->m_engine = createTcfEngine(sp);
break;
case QmlEngineType:
- d->m_engine = Internal::createQmlEngine(sp);
- connect(qobject_cast<QmlEngine *>(d->m_engine),
- SIGNAL(remoteStartupRequested()), this,
- SIGNAL(engineRequestSetup()));
+ d->m_engine = createQmlEngine(sp);
break;
case QmlCppEngineType:
- d->m_engine = Internal::createQmlCppEngine(sp);
- if (Internal::GdbEngine *embeddedGdbEngine = gdbEngine())
- initGdbEngine(embeddedGdbEngine);
+ d->m_engine = createQmlCppEngine(sp);
break;
- case NoEngineType:
- case AllEngineTypes:
+ case LldbEngineType:
+ d->m_engine = createLldbEngine(sp);
+ case NoEngineType:
+ case AllEngineTypes:
break;
}
if (!d->m_engine) {
// Could not find anything suitable.
debuggingFinished();
- // Create Message box with possibility to go to settings
+ // Create Message box with possibility to go to settings.
const QString msg = tr("Cannot debug '%1' (tool chain: '%2'): %3")
- .arg(sp.executable, toolChainName(sp.toolChainType), d->m_errorMessage);
+ .arg(sp.executable, sp.toolChainName(), d->m_errorMessage);
Core::ICore::instance()->showWarningWithOptions(tr("Warning"),
- msg, QString(), QLatin1String(Constants::DEBUGGER_SETTINGS_CATEGORY),
- d->m_settingsIdHint);
+ msg, QString(), QLatin1String(Constants::DEBUGGER_SETTINGS_CATEGORY),
+ d->m_settingsIdHint);
}
}
-void DebuggerRunControl::initGdbEngine(Internal::GdbEngine *engine)
+DebuggerRunControl::~DebuggerRunControl()
{
- QTC_ASSERT(engine, return)
-
- // Forward adapter signals.
- Internal::AbstractGdbAdapter *adapter = engine->gdbAdapter();
- if (RemotePlainGdbAdapter *rpga = qobject_cast<RemotePlainGdbAdapter *>(adapter)) {
- connect(rpga, SIGNAL(requestSetup()), this,
- SIGNAL(engineRequestSetup()));
- } else if (RemoteGdbServerAdapter *rgsa = qobject_cast<RemoteGdbServerAdapter *>(adapter)) {
- connect(rgsa, SIGNAL(requestSetup()),
- this, SIGNAL(engineRequestSetup()));
+ disconnect();
+ if (DebuggerEngine *engine = d->m_engine) {
+ d->m_engine = 0;
+ engine->disconnect();
+ delete engine;
}
}
+const DebuggerStartParameters &DebuggerRunControl::startParameters() const
+{
+ QTC_ASSERT(d->m_engine, return *(new DebuggerStartParameters()));
+ return d->m_engine->startParameters();
+}
+
QString DebuggerRunControl::displayName() const
{
QTC_ASSERT(d->m_engine, return QString());
@@ -531,7 +404,8 @@ QString DebuggerRunControl::displayName() const
void DebuggerRunControl::setCustomEnvironment(Utils::Environment env)
{
- d->m_engine->startParameters().environment = env.toStringList();
+ QTC_ASSERT(d->m_engine, return);
+ d->m_engine->startParameters().environment = env;
}
bool DebuggerRunControl::checkDebugConfiguration(int toolChain,
@@ -547,23 +421,28 @@ bool DebuggerRunControl::checkDebugConfiguration(int toolChain,
bool success = true;
- if (!(DebuggerPlugin::instance()->activeLanguages() & CppLanguage))
+ if (!(debuggerCore()->activeLanguages() & CppLanguage))
return success;
switch(toolChain) {
- case ProjectExplorer::ToolChain::GCC:
- case ProjectExplorer::ToolChain::LINUX_ICC:
- case ProjectExplorer::ToolChain::MinGW:
- case ProjectExplorer::ToolChain::WINCE: // S60
- case ProjectExplorer::ToolChain::WINSCW:
- case ProjectExplorer::ToolChain::GCCE:
- case ProjectExplorer::ToolChain::RVCT_ARMV5:
- case ProjectExplorer::ToolChain::RVCT_ARMV6:
- success = checkGdbConfiguration(toolChain, errorMessage, settingsPage);
- if (!success)
+ case ProjectExplorer::ToolChain_GCC:
+ case ProjectExplorer::ToolChain_LINUX_ICC:
+ case ProjectExplorer::ToolChain_MinGW:
+ case ProjectExplorer::ToolChain_WINCE: // S60
+ case ProjectExplorer::ToolChain_WINSCW:
+ case ProjectExplorer::ToolChain_GCCE:
+ case ProjectExplorer::ToolChain_RVCT2_ARMV5:
+ case ProjectExplorer::ToolChain_RVCT2_ARMV6:
+ if (debuggerCore()->gdbBinaryForToolChain(toolChain).isEmpty()) {
+ *errorMessage = msgNoBinaryForToolChain(toolChain);
+ *settingsPage = GdbOptionsPage::settingsId();
*errorMessage += msgEngineNotAvailable("Gdb");
+ success = false;
+ } else {
+ success = true;
+ }
break;
- case ProjectExplorer::ToolChain::MSVC:
+ case ProjectExplorer::ToolChain_MSVC:
success = checkCdbConfiguration(toolChain, errorMessage, settingsPage);
if (!success) {
*errorMessage += msgEngineNotAvailable("Cdb");
@@ -581,36 +460,14 @@ bool DebuggerRunControl::checkDebugConfiguration(int toolChain,
void DebuggerRunControl::start()
{
QTC_ASSERT(d->m_engine, return);
- const DebuggerStartParameters &sp = d->m_engine->startParameters();
-
- QString errorMessage;
- QString settingsCategory;
- QString settingsPage;
-
- if (!checkDebugConfiguration(sp.toolChainType,
- &errorMessage, &settingsCategory, &settingsPage)) {
- emit appendMessage(this, errorMessage, true);
- emit finished();
- Core::ICore::instance()->showWarningWithOptions(tr("Debugger"),
- errorMessage, QString(), settingsCategory, settingsPage);
- return;
- }
-
- plugin()->activateDebugMode();
- DebuggerUISwitcher::instance()->aboutToStartDebugger();
-
- const QString message = tr("Starting debugger '%1' for tool chain '%2'...").
- arg(d->m_engine->objectName(), toolChainName(sp.toolChainType));
- plugin()->showMessage(message, StatusBar);
- plugin()->showMessage(DebuggerSettings::instance()->dump(), LogDebug);
- plugin()->runControlStarted(this);
+ debuggerCore()->runControlStarted(d->m_engine);
// We might get a synchronous startFailed() notification on Windows,
// when launching the process fails. Emit a proper finished() sequence.
emit started();
d->m_running = true;
- engine()->startDebugger(this);
+ d->m_engine->startDebugger(this);
if (d->m_running) {
emit addToOutputWindowInline(this, tr("Debugging starts"), false);
@@ -623,15 +480,15 @@ void DebuggerRunControl::startFailed()
emit addToOutputWindowInline(this, tr("Debugging has failed"), false);
d->m_running = false;
emit finished();
- engine()->handleStartFailed();
+ d->m_engine->handleStartFailed();
}
void DebuggerRunControl::handleFinished()
{
emit addToOutputWindowInline(this, tr("Debugging has finished"), false);
- if (engine())
- engine()->handleFinished();
- plugin()->runControlFinished(this);
+ if (d->m_engine)
+ d->m_engine->handleFinished();
+ debuggerCore()->runControlFinished(d->m_engine);
}
void DebuggerRunControl::showMessage(const QString &msg, int channel)
@@ -659,7 +516,7 @@ bool DebuggerRunControl::aboutToStop() const
" Would you still like to terminate it?");
const QMessageBox::StandardButton answer =
- QMessageBox::question(DebuggerUISwitcher::instance()->mainWindow(),
+ QMessageBox::question(debuggerCore()->mainWindow(),
tr("Close Debugging Session"), question,
QMessageBox::Yes|QMessageBox::No);
return answer == QMessageBox::Yes;
@@ -683,82 +540,153 @@ bool DebuggerRunControl::isRunning() const
return d->m_running;
}
-DebuggerState DebuggerRunControl::state() const
-{
- QTC_ASSERT(d->m_engine, return DebuggerNotReady);
- return d->m_engine->state();
-}
-
DebuggerEngine *DebuggerRunControl::engine()
{
QTC_ASSERT(d->m_engine, /**/);
return d->m_engine;
}
-Internal::GdbEngine *DebuggerRunControl::gdbEngine() const
+RunConfiguration *DebuggerRunControl::runConfiguration() const
{
- QTC_ASSERT(d->m_engine, return 0);
- if (GdbEngine *gdbEngine = qobject_cast<GdbEngine *>(d->m_engine))
- return gdbEngine;
- if (QmlCppEngine * const qmlEngine = qobject_cast<QmlCppEngine *>(d->m_engine))
- if (Internal::GdbEngine *embeddedGdbEngine = qobject_cast<GdbEngine *>(qmlEngine->cppEngine()))
- return embeddedGdbEngine;
- return 0;
+ return d->m_myRunConfiguration.data();
+}
+
+
+////////////////////////////////////////////////////////////////////////
+//
+// DebuggerRunControlFactory
+//
+////////////////////////////////////////////////////////////////////////
+
+// A factory to create DebuggerRunControls
+DebuggerRunControlFactory::DebuggerRunControlFactory(QObject *parent,
+ unsigned enabledEngines)
+ : IRunControlFactory(parent), m_enabledEngines(enabledEngines)
+{}
+
+bool DebuggerRunControlFactory::canRun(RunConfiguration *runConfiguration, const QString &mode) const
+{
+// return mode == ProjectExplorer::Constants::DEBUGMODE;
+ return mode == Constants::DEBUGMODE
+ && qobject_cast<LocalApplicationRunConfiguration *>(runConfiguration);
}
-Internal::AbstractGdbAdapter *DebuggerRunControl::gdbAdapter() const
+QString DebuggerRunControlFactory::displayName() const
{
- GdbEngine *engine = gdbEngine();
- QTC_ASSERT(engine, return 0)
- return engine->gdbAdapter();
+ return tr("Debug");
}
-void DebuggerRunControl::handleRemoteSetupDone()
+// Find Qt installation by running qmake
+static inline QString findQtInstallPath(const QString &qmakePath)
{
- if (QmlEngine *qmlEngine = qobject_cast<QmlEngine *>(d->m_engine)) {
- qmlEngine->handleRemoteSetupDone();
- } else if (Internal::AbstractGdbAdapter *adapter = gdbAdapter()) {
- if (RemotePlainGdbAdapter *rpga = qobject_cast<RemotePlainGdbAdapter *>(adapter)) {
- rpga->handleSetupDone();
- } else if (RemoteGdbServerAdapter *rgsa = qobject_cast<RemoteGdbServerAdapter *>(adapter)) {
- rgsa->handleSetupDone();
- } else {
- QTC_ASSERT(false, /* */ );
- }
- } else {
- QTC_ASSERT(false, /* */ );
+ QProcess proc;
+ QStringList args;
+ args.append(QLatin1String("-query"));
+ args.append(QLatin1String("QT_INSTALL_HEADERS"));
+ proc.start(qmakePath, args);
+ if (!proc.waitForStarted()) {
+ qWarning("%s: Cannot start '%s': %s", Q_FUNC_INFO, qPrintable(qmakePath),
+ qPrintable(proc.errorString()));
+ return QString();
}
+ proc.closeWriteChannel();
+ if (!proc.waitForFinished()) {
+ Utils::SynchronousProcess::stopProcess(proc);
+ qWarning("%s: Timeout running '%s'.", Q_FUNC_INFO, qPrintable(qmakePath));
+ return QString();
+ }
+ if (proc.exitStatus() != QProcess::NormalExit) {
+ qWarning("%s: '%s' crashed.", Q_FUNC_INFO, qPrintable(qmakePath));
+ return QString();
+ }
+ const QByteArray ba = proc.readAllStandardOutput().trimmed();
+ QDir dir(QString::fromLocal8Bit(ba));
+ if (dir.exists() && dir.cdUp())
+ return dir.absolutePath();
+ return QString();
}
-void DebuggerRunControl::handleRemoteSetupFailed(const QString &message)
+static DebuggerStartParameters localStartParameters(RunConfiguration *runConfiguration)
{
- if (QmlEngine *qmlEngine = qobject_cast<QmlEngine *>(d->m_engine)) {
- qmlEngine->handleRemoteSetupFailed(message);
- } else if (Internal::AbstractGdbAdapter *adapter = gdbAdapter()) {
- if (RemotePlainGdbAdapter *rpga = qobject_cast<RemotePlainGdbAdapter *>(adapter)) {
- rpga->handleSetupFailed(message);
- } else if (RemoteGdbServerAdapter *rgsa = qobject_cast<RemoteGdbServerAdapter *>(adapter)) {
- rgsa->handleSetupFailed(message);
- } else {
- QTC_ASSERT(false, /* */ );
- }
- } else {
- QTC_ASSERT(false, /* */ );
+ DebuggerStartParameters sp;
+ QTC_ASSERT(runConfiguration, return sp);
+ LocalApplicationRunConfiguration *rc =
+ qobject_cast<LocalApplicationRunConfiguration *>(runConfiguration);
+ QTC_ASSERT(rc, return sp);
+
+ sp.startMode = StartInternal;
+ sp.environment = rc->environment();
+ sp.workingDirectory = rc->workingDirectory();
+ sp.executable = rc->executable();
+ sp.processArgs = rc->commandLineArguments();
+ sp.toolChainType = rc->toolChainType();
+ sp.useTerminal = rc->runMode() == LocalApplicationRunConfiguration::Console;
+ sp.dumperLibrary = rc->dumperLibrary();
+ sp.dumperLibraryLocations = rc->dumperLibraryLocations();
+
+ if (debuggerCore()->isActiveDebugLanguage(QmlLanguage)) {
+ sp.qmlServerAddress = QLatin1String("127.0.0.1");
+ sp.qmlServerPort = runConfiguration->qmlDebugServerPort();
+
+ sp.projectDir = runConfiguration->target()->project()->projectDirectory();
+ if (runConfiguration->target()->activeBuildConfiguration())
+ sp.projectBuildDir = runConfiguration->target()
+ ->activeBuildConfiguration()->buildDirectory();
+
+ Utils::QtcProcess::addArg(&sp.processArgs, QLatin1String("-qmljsdebugger=port:")
+ + QString::number(sp.qmlServerPort));
}
+
+ // FIXME: If it's not yet build this will be empty and not filled
+ // when rebuild as the runConfiguration is not stored and therefore
+ // cannot be used to retrieve the dumper location.
+ //qDebug() << "DUMPER: " << sp.dumperLibrary << sp.dumperLibraryLocations;
+ sp.displayName = rc->displayName();
+
+ // Find qtInstallPath.
+ QString qmakePath = DebuggingHelperLibrary::findSystemQt(rc->environment());
+ if (!qmakePath.isEmpty())
+ sp.qtInstallPath = findQtInstallPath(qmakePath);
+ return sp;
}
-void DebuggerRunControl::emitAddToOutputWindow(const QString &line, bool onStdErr)
+RunControl *DebuggerRunControlFactory::create
+ (RunConfiguration *runConfiguration, const QString &mode)
{
- emit addToOutputWindow(this, line, onStdErr);
+ QTC_ASSERT(mode == Constants::DEBUGMODE, return 0);
+ DebuggerStartParameters sp = localStartParameters(runConfiguration);
+ return create(sp, runConfiguration);
}
-void DebuggerRunControl::emitAppendMessage(const QString &m, bool isError)
+QWidget *DebuggerRunControlFactory::createConfigurationWidget
+ (RunConfiguration *runConfiguration)
{
- emit appendMessage(this, m, isError);
+ // NBS TODO: Add GDB-specific configuration widget
+ Q_UNUSED(runConfiguration)
+ return 0;
}
-RunConfiguration *DebuggerRunControl::runConfiguration() const
+DebuggerRunControl *DebuggerRunControlFactory::create
+ (const DebuggerStartParameters &sp, RunConfiguration *runConfiguration)
{
- return d->m_myRunConfiguration.data();
+ QString errorMessage;
+ QString settingsCategory;
+ QString settingsPage;
+
+ if (!DebuggerRunControl::checkDebugConfiguration(sp.toolChainType,
+ &errorMessage, &settingsCategory, &settingsPage)) {
+ //emit appendMessage(this, errorMessage, true);
+ Core::ICore::instance()->showWarningWithOptions(tr("Debugger"),
+ errorMessage, QString(), settingsCategory, settingsPage);
+ return 0;
+ }
+
+ DebuggerRunControl *runControl =
+ new DebuggerRunControl(runConfiguration, m_enabledEngines, sp);
+ if (runControl->d->m_engine)
+ return runControl;
+ delete runControl;
+ return 0;
}
+
} // namespace Debugger
diff --git a/src/plugins/debugger/debuggerrunner.h b/src/plugins/debugger/debuggerrunner.h
index ddd8c6bc1a..0c87d4d76b 100644
--- a/src/plugins/debugger/debuggerrunner.h
+++ b/src/plugins/debugger/debuggerrunner.h
@@ -48,22 +48,15 @@ class Environment;
namespace Debugger {
class DebuggerEngine;
class DebuggerRunControl;
-class QmlEngine;
class DebuggerStartParameters;
-struct DebuggerRunnerPrivate;
namespace Internal {
-class GdbEngine;
-class AbstractGdbAdapter;
-}
-//DEBUGGER_EXPORT QDebug operator<<(QDebug str, const DebuggerStartParameters &);
+class DebuggerRunControlPrivate;
-class DEBUGGER_EXPORT DebuggerRunControlFactory
+class DebuggerRunControlFactory
: public ProjectExplorer::IRunControlFactory
{
- Q_OBJECT
-
public:
DebuggerRunControlFactory(QObject *parent, unsigned enabledEngines);
@@ -78,6 +71,7 @@ public:
// FIXME: Used by qmljsinspector.cpp:469
RunControl *create(RunConfiguration *runConfiguration, const QString &mode);
bool canRun(RunConfiguration *runConfiguration, const QString &mode) const;
+
private:
QString displayName() const;
QWidget *createConfigurationWidget(RunConfiguration *runConfiguration);
@@ -85,6 +79,8 @@ private:
unsigned m_enabledEngines;
};
+} // namespace Internal
+
// This is a job description containing all data "local" to the jobs, including
// the models of the individual debugger views.
@@ -95,45 +91,32 @@ class DEBUGGER_EXPORT DebuggerRunControl
public:
typedef ProjectExplorer::RunConfiguration RunConfiguration;
- explicit DebuggerRunControl(RunConfiguration *runConfiguration,
+ DebuggerRunControl(RunConfiguration *runConfiguration,
unsigned enabledEngines, const DebuggerStartParameters &sp);
~DebuggerRunControl();
// ProjectExplorer::RunControl
- virtual void start();
- virtual bool aboutToStop() const;
- virtual StopResult stop();
- virtual bool isRunning() const;
+ void start();
+ bool aboutToStop() const;
+ StopResult stop(); // Called from SnapshotWindow.
+ bool isRunning() const;
QString displayName() const;
- void createEngine(const DebuggerStartParameters &startParameters);
-
void setCustomEnvironment(Utils::Environment env);
-
void startFailed();
void debuggingFinished();
RunConfiguration *runConfiguration() const;
-
- DebuggerState state() const;
- DebuggerEngine *engine();
+ DebuggerEngine *engine(); // FIXME: Remove. Only used by Maemo support.
void showMessage(const QString &msg, int channel);
- void handleRemoteSetupDone();
- void handleRemoteSetupFailed(const QString &message);
-
static bool checkDebugConfiguration(int toolChain,
QString *errorMessage,
QString *settingsCategory = 0,
QString *settingsPage = 0);
-
signals:
void engineRequestSetup();
-public slots:
- void emitAddToOutputWindow(const QString &line, bool onStdErr);
- void emitAppendMessage(const QString &, bool isError);
-
private slots:
void handleFinished();
@@ -141,13 +124,8 @@ protected:
const DebuggerStartParameters &startParameters() const;
private:
- DebuggerEngineType engineForExecutable(unsigned enabledEngineTypes, const QString &executable);
- DebuggerEngineType engineForMode(unsigned enabledEngineTypes, DebuggerStartMode mode);
- void initGdbEngine(Internal::GdbEngine *engine);
- Internal::GdbEngine *gdbEngine() const;
- Internal::AbstractGdbAdapter *gdbAdapter() const;
-
- QScopedPointer<DebuggerRunnerPrivate> d;
+ friend class Internal::DebuggerRunControlFactory;
+ QScopedPointer<Internal::DebuggerRunControlPrivate> d;
};
} // namespace Debugger
diff --git a/src/plugins/debugger/debuggerstreamops.cpp b/src/plugins/debugger/debuggerstreamops.cpp
new file mode 100644
index 0000000000..7dff5b22bf
--- /dev/null
+++ b/src/plugins/debugger/debuggerstreamops.cpp
@@ -0,0 +1,293 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "debuggerstreamops.h"
+
+namespace Debugger {
+namespace Internal {
+
+QDataStream &operator<<(QDataStream &stream, const ThreadData &d)
+{
+ stream << (qint64)d.id;
+ stream << d.address;
+ stream << d.function;
+ stream << d.fileName;
+ stream << d.state;
+ stream << d.lineNumber;
+ stream << d.name;
+ return stream;
+}
+
+QDataStream &operator>>(QDataStream &stream, ThreadData &d)
+{
+ qint64 id;
+ stream >> id;
+ d.id = id;
+ stream >> d.address;
+ stream >> d.function;
+ stream >> d.fileName;
+ stream >> d.state;
+ stream >> d.lineNumber;
+ stream >> d.name;
+ return stream;
+}
+
+QDataStream &operator<<(QDataStream &stream, const Threads &threads)
+{
+ stream << (quint64)threads.count();
+ for (int i = 0; i < threads.count(); i++)
+ {
+ const ThreadData &d = threads.at(i);
+ stream << d;
+ }
+ return stream;
+}
+
+QDataStream &operator>>(QDataStream &stream, Threads &threads)
+{
+ quint64 count;
+ stream >> count;
+ threads.clear();
+ for (quint64 i = 0; i < count; i++)
+ {
+ ThreadData d;
+ stream >> d;
+ threads.append(d);
+ }
+ return stream;
+}
+
+QDataStream &operator<<(QDataStream &stream, const StackFrame &s)
+{
+ stream << (quint64)s.level;
+ stream << s.function;
+ stream << s.file;
+ stream << s.from;
+ stream << s.to;
+ stream << s.line;
+ stream << s.address;
+ stream << s.usable;
+ return stream;
+}
+
+QDataStream &operator>>(QDataStream &stream, StackFrame &s)
+{
+ quint64 level;
+ stream >> level;
+ s.level = level;
+ stream >> s.function;
+ stream >> s.file;
+ stream >> s.from;
+ stream >> s.to;
+ stream >> s.line;
+ stream >> s.address;
+ stream >> s.usable;
+ return stream;
+}
+
+QDataStream &operator<<(QDataStream &stream, const StackFrames &frames)
+{
+ stream << (quint64)frames.count();
+ for (int i = 0; i < frames.count(); i++)
+ {
+ const StackFrame &s = frames.at(i);
+ stream << s;
+ }
+ return stream;
+}
+
+QDataStream &operator>>(QDataStream &stream, StackFrames &frames)
+{
+ quint64 count;
+ stream >> count;
+ frames.clear();
+ for (quint64 i = 0; i < count; i++)
+ {
+ StackFrame s;
+ stream >> s;
+ frames.append(s);
+ }
+ return stream;
+}
+
+QDataStream &operator<<(QDataStream &stream, const BreakpointResponse &s)
+{
+ stream << s.number;
+ stream << s.condition;
+ stream << s.ignoreCount;
+ stream << s.fileName;
+ stream << s.fullName;
+ stream << s.lineNumber;
+ //stream << s.bpCorrectedLineNumber;
+ stream << s.threadSpec;
+ stream << s.functionName;
+ stream << s.address;
+ return stream;
+}
+
+QDataStream &operator>>(QDataStream &stream, BreakpointResponse &s)
+{
+ stream >> s.number;
+ stream >> s.condition;
+ stream >> s.ignoreCount;
+ stream >> s.fileName;
+ stream >> s.fullName;
+ stream >> s.lineNumber;
+ //stream >> s.bpCorrectedLineNumber;
+ stream >> s.threadSpec;
+ stream >> s.functionName;
+ stream >> s.address;
+ return stream;
+}
+
+QDataStream &operator<<(QDataStream &stream, const BreakpointParameters &s)
+{
+ stream << s.fileName;
+ stream << s.condition;
+ stream << quint64(s.ignoreCount);
+ stream << quint64(s.lineNumber);
+ stream << quint64(s.address);
+ stream << s.functionName;
+ stream << s.useFullPath;
+ stream << s.tracepoint;
+ return stream;
+}
+
+QDataStream &operator>>(QDataStream &stream, BreakpointParameters &s)
+{
+ quint64 t;
+ QString str;
+ QByteArray ba;
+ bool b;
+ stream >> str; s.fileName = str;
+ stream >> ba; s.condition = ba;
+ stream >> t; s.ignoreCount = t;
+ stream >> t; s.lineNumber = t;
+ stream >> t; s.address = t;
+ stream >> str; s.functionName = str;
+ stream >> b; s.useFullPath = b;
+ stream >> b; s.tracepoint = b;
+ return stream;
+}
+
+QDataStream &operator<<(QDataStream &stream, const WatchData &wd)
+{
+ stream << wd.id;
+ stream << wd.iname;
+ stream << wd.exp;
+ stream << wd.name;
+ stream << wd.value;
+ stream << wd.editvalue;
+ stream << wd.editformat;
+ stream << wd.valuetooltip;
+ stream << wd.typeFormats;
+ stream << wd.type;
+ stream << wd.displayedType;
+ stream << wd.variable;
+ stream << wd.address;
+ stream << wd.hasChildren;
+ stream << wd.generation;
+ stream << wd.valueEnabled;
+ stream << wd.valueEditable;
+ stream << wd.error;
+ stream << wd.state;
+ stream << wd.changed;
+ return stream;
+}
+
+QDataStream &operator>>(QDataStream &stream, WatchData &wd)
+{
+ stream >> wd.id;
+ stream >> wd.iname;
+ stream >> wd.exp;
+ stream >> wd.name;
+ stream >> wd.value;
+ stream >> wd.editvalue;
+ stream >> wd.editformat;
+ stream >> wd.valuetooltip;
+ stream >> wd.typeFormats;
+ stream >> wd.type;
+ stream >> wd.displayedType;
+ stream >> wd.variable;
+ stream >> wd.address;
+ stream >> wd.hasChildren;
+ stream >> wd.generation;
+ stream >> wd.valueEnabled;
+ stream >> wd.valueEditable;
+ stream >> wd.error;
+ stream >> wd.state;
+ stream >> wd.changed;
+ return stream;
+}
+
+QDataStream &operator<<(QDataStream& stream, const DisassemblerLine &o)
+{
+ stream << o.address;
+ stream << o.data;
+ return stream;
+}
+
+QDataStream &operator>>(QDataStream& stream, DisassemblerLine &o)
+{
+ stream >> o.address;
+ stream >> o.data;
+ return stream;
+}
+
+QDataStream &operator<<(QDataStream& stream, const DisassemblerLines &o)
+{
+ stream << quint64(o.size());
+ for (int i = 0; i < o.size(); i++)
+ {
+ stream << o.at(i);
+ }
+ return stream;
+}
+
+QDataStream &operator>>(QDataStream& stream, DisassemblerLines &o)
+{
+ DisassemblerLines r;
+ quint64 count;
+ stream >> count;
+ for (quint64 i = 0; i < count; i++)
+ {
+ DisassemblerLine line;
+ stream >> line;
+ r.appendLine(line);
+ }
+ o = r;
+ return stream;
+}
+
+
+
+} // namespace Internal
+} // namespace Debugger
+
+
diff --git a/src/plugins/debugger/debuggerstreamops.h b/src/plugins/debugger/debuggerstreamops.h
new file mode 100644
index 0000000000..b7bc2a7d0d
--- /dev/null
+++ b/src/plugins/debugger/debuggerstreamops.h
@@ -0,0 +1,67 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 DEBUGGERPLUGIN_STREAMOPS_H
+#define DEBUGGERPLUGIN_STREAMOPS_H
+
+#include "breakpoint.h"
+#include "stackframe.h"
+#include "threaddata.h"
+#include "watchdata.h"
+#include "disassemblerlines.h"
+
+#include <QtCore/QDataStream>
+#include <QtCore/QVector>
+
+namespace Debugger {
+namespace Internal {
+
+QDataStream &operator<<(QDataStream& stream, const ThreadData &thread);
+QDataStream &operator>>(QDataStream& stream, ThreadData &threads);
+QDataStream &operator<<(QDataStream& stream, const Threads &threads);
+QDataStream &operator>>(QDataStream& stream, Threads &threads);
+QDataStream &operator<<(QDataStream& stream, const StackFrame& frame);
+QDataStream &operator>>(QDataStream& stream, StackFrame &frame);
+QDataStream &operator<<(QDataStream& stream, const StackFrames& frames);
+QDataStream &operator>>(QDataStream& stream, StackFrames &frames);
+QDataStream &operator<<(QDataStream& stream, const BreakpointParameters &data);
+QDataStream &operator>>(QDataStream& stream, BreakpointParameters &data);
+QDataStream &operator<<(QDataStream& stream, const BreakpointResponse &data);
+QDataStream &operator>>(QDataStream& stream, BreakpointResponse &data);
+QDataStream &operator<<(QDataStream& stream, const WatchData &data);
+QDataStream &operator>>(QDataStream& stream, WatchData &data);
+QDataStream &operator<<(QDataStream& stream, const DisassemblerLine &o);
+QDataStream &operator>>(QDataStream& stream, DisassemblerLine &o);
+QDataStream &operator<<(QDataStream& stream, const DisassemblerLines &o);
+QDataStream &operator>>(QDataStream& stream, DisassemblerLines &o);
+
+} // namespace Internal
+} // namespace Debugger
+
+#endif
diff --git a/src/plugins/debugger/debuggertooltip.cpp b/src/plugins/debugger/debuggertooltip.cpp
index 04be1ce9f2..cacea72303 100644
--- a/src/plugins/debugger/debuggertooltip.cpp
+++ b/src/plugins/debugger/debuggertooltip.cpp
@@ -33,18 +33,15 @@
#include "debuggertooltip.h"
-#include <QtCore/QPointer>
#include <QtCore/QtDebug>
+#include <QtCore/QPointer>
#include <QtGui/QApplication>
-#include <QtGui/QHBoxLayout>
+#include <QtGui/QDesktopWidget>
#include <QtGui/QHeaderView>
#include <QtGui/QKeyEvent>
-#include <QtGui/QLabel>
+#include <QtGui/QScrollBar>
#include <QtGui/QTreeView>
-#include <QtGui/QVBoxLayout>
-#include <QtGui/QWidget>
-
namespace Debugger {
namespace Internal {
@@ -60,8 +57,7 @@ public:
QSize sizeHint() const { return m_size; }
void done();
- void run(const QPoint &point, QAbstractItemModel *model,
- const QModelIndex &index, const QString &msg);
+ void run(const QPoint &point, const QModelIndex &index);
int computeHeight(const QModelIndex &index) const;
Q_SLOT void computeSize();
@@ -103,9 +99,8 @@ bool ToolTipWidget::eventFilter(QObject *ob, QEvent *ev)
return true;
break;
case QEvent::KeyPress:
- if (static_cast<QKeyEvent *>(ev)->key() == Qt::Key_Escape) {
+ if (static_cast<QKeyEvent *>(ev)->key() == Qt::Key_Escape)
return true;
- }
break;
case QEvent::KeyRelease:
if (static_cast<QKeyEvent *>(ev)->key() == Qt::Key_Escape) {
@@ -131,7 +126,7 @@ int ToolTipWidget::computeHeight(const QModelIndex &index) const
return s;
}
-Q_SLOT void ToolTipWidget::computeSize()
+void ToolTipWidget::computeSize()
{
int columns = 0;
for (int i = 0; i < 3; ++i) {
@@ -139,6 +134,33 @@ Q_SLOT void ToolTipWidget::computeSize()
columns += sizeHintForColumn(i);
}
int rows = computeHeight(QModelIndex());
+
+ // Fit tooltip to screen, showing/hiding scrollbars as needed.
+ // Add a bit of space to account for tooltip border, and not
+ // touch the border of the screen.
+ QPoint pos(x(), y());
+ QRect desktopRect = QApplication::desktop()->availableGeometry(pos);
+ const int maxWidth = desktopRect.right() - pos.x() - 5 - 5;
+ const int maxHeight = desktopRect.bottom() - pos.y() - 5 - 5;
+
+ if (columns > maxWidth)
+ rows += horizontalScrollBar()->height();
+
+ if (rows > maxHeight) {
+ setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
+ rows = maxHeight;
+ columns += verticalScrollBar()->width();
+ } else {
+ setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ }
+
+ if (columns > maxWidth) {
+ setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
+ columns = maxWidth;
+ } else {
+ setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ }
+
m_size = QSize(columns + 5, rows + 5);
setMinimumSize(m_size);
setMaximumSize(m_size);
@@ -150,20 +172,13 @@ void ToolTipWidget::done()
deleteLater();
}
-void ToolTipWidget::run(const QPoint &point, QAbstractItemModel *model,
- const QModelIndex &index, const QString & /* msg */)
+void ToolTipWidget::run(const QPoint &point, const QModelIndex &index)
{
+ QAbstractItemModel *model = const_cast<QAbstractItemModel *>(index.model());
move(point);
setModel(model);
computeSize();
setRootIsDecorated(model->hasChildren(index));
- // FIXME: use something more sensible
- QPalette pal = palette();
- QColor bg = pal.color(QPalette::Base);
- bg.setAlpha(20);
- pal.setColor(QPalette::Base, bg);
- setPalette(pal);
- //viewport()->setPalette(pal);
}
void ToolTipWidget::leaveEvent(QEvent *ev)
@@ -173,13 +188,12 @@ void ToolTipWidget::leaveEvent(QEvent *ev)
hide();
}
-void showDebuggerToolTip(const QPoint &point, QAbstractItemModel *model,
- const QModelIndex &index, const QString &msg)
+void showDebuggerToolTip(const QPoint &point, const QModelIndex &index)
{
- if (model) {
+ if (index.model()) {
if (!theToolTipWidget)
theToolTipWidget = new ToolTipWidget(0);
- theToolTipWidget->run(point, model, index, msg);
+ theToolTipWidget->run(point, index);
theToolTipWidget->show();
} else if (theToolTipWidget) {
theToolTipWidget->done();
diff --git a/src/plugins/debugger/debuggertooltip.h b/src/plugins/debugger/debuggertooltip.h
index 828b755d25..941a744f57 100644
--- a/src/plugins/debugger/debuggertooltip.h
+++ b/src/plugins/debugger/debuggertooltip.h
@@ -37,18 +37,14 @@
#include <QtCore/QtGlobal>
QT_BEGIN_NAMESPACE
-class QAbstractItemModel;
class QModelIndex;
class QPoint;
-class QString;
QT_END_NAMESPACE
namespace Debugger {
namespace Internal {
-void showDebuggerToolTip(const QPoint &point, QAbstractItemModel *model,
- const QModelIndex &rootIndex, const QString &msg);
-
+void showDebuggerToolTip(const QPoint &point, const QModelIndex &rootIndex);
void hideDebuggerToolTip(int delay = 0);
} // namespace Internal
diff --git a/src/plugins/debugger/debuggeruiswitcher.cpp b/src/plugins/debugger/debuggeruiswitcher.cpp
deleted file mode 100644
index 3c74d3676d..0000000000
--- a/src/plugins/debugger/debuggeruiswitcher.cpp
+++ /dev/null
@@ -1,730 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#include "debuggeruiswitcher.h"
-#include "debuggermainwindow.h"
-#include "debuggeractions.h"
-#include "debuggerconstants.h"
-#include "debuggerrunner.h"
-#include "debuggerplugin.h"
-#include "savedaction.h"
-
-#include <utils/savedaction.h>
-#include <utils/styledbar.h>
-#include <utils/qtcassert.h>
-
-#include <coreplugin/actionmanager/actioncontainer.h>
-#include <coreplugin/actionmanager/actionmanager.h>
-#include <coreplugin/actionmanager/command.h>
-#include <coreplugin/basemode.h>
-#include <coreplugin/coreconstants.h>
-#include <coreplugin/editormanager/editormanager.h>
-#include <coreplugin/findplaceholder.h>
-#include <coreplugin/icore.h>
-#include <coreplugin/minisplitter.h>
-#include <coreplugin/modemanager.h>
-#include <coreplugin/navigationwidget.h>
-#include <coreplugin/outputpane.h>
-#include <coreplugin/rightpane.h>
-
-#include <projectexplorer/projectexplorerconstants.h>
-#include <projectexplorer/projectexplorer.h>
-#include <projectexplorer/session.h>
-#include <projectexplorer/project.h>
-#include <projectexplorer/target.h>
-#include <projectexplorer/runconfiguration.h>
-
-#include <QtGui/QActionGroup>
-#include <QtGui/QStackedWidget>
-#include <QtGui/QVBoxLayout>
-#include <QtGui/QMenu>
-#include <QtGui/QDockWidget>
-#include <QtGui/QResizeEvent>
-#include <QtCore/QDebug>
-#include <QtCore/QList>
-#include <QtCore/QMap>
-#include <QtCore/QPair>
-#include <QtCore/QSettings>
-
-using namespace Core;
-
-namespace Debugger {
-namespace Internal {
-
-class DockWidgetEventFilter : public QObject
-{
- Q_OBJECT
-
-public:
- explicit DockWidgetEventFilter(QObject *parent = 0) : QObject(parent) {}
-
-signals:
- void widgetResized();
-
-protected:
- virtual bool eventFilter(QObject *obj, QEvent *event);
-};
-
-bool DockWidgetEventFilter::eventFilter(QObject *obj, QEvent *event)
-{
- switch (event->type()) {
- case QEvent::Resize:
- case QEvent::ZOrderChange:
- emit widgetResized();
- break;
- default:
- break;
- }
- return QObject::eventFilter(obj, event);
-}
-
-}
-// first: language id, second: menu item
-typedef QPair<DebuggerLanguage, QAction *> ViewsMenuItems;
-
-struct DebuggerUISwitcherPrivate
-{
- explicit DebuggerUISwitcherPrivate(DebuggerUISwitcher *q);
-
- QList<ViewsMenuItems> m_viewsMenuItems;
- QList<QDockWidget *> m_dockWidgets;
-
- QHash<QString, QVariant> m_dockWidgetActiveStateCpp;
- QHash<QString, QVariant> m_dockWidgetActiveStateQmlCpp;
- Internal::DockWidgetEventFilter *m_resizeEventFilter;
-
- QMap<DebuggerLanguage, QWidget *> m_toolBars;
-
- DebuggerLanguages m_supportedLanguages;
- int m_languageCount;
-
- QStackedWidget *m_toolbarStack;
- Internal::DebuggerMainWindow *m_mainWindow;
-
- QHash<DebuggerLanguage, Context> m_contextsForLanguage;
-
- bool m_inDebugMode;
- bool m_changingUI;
-
- DebuggerLanguages m_previousDebugLanguages;
- DebuggerLanguages m_activeDebugLanguages;
- QAction *m_openMemoryEditorAction;
-
- ActionContainer *m_viewsMenu;
- ActionContainer *m_debugMenu;
-
- QMultiHash<DebuggerLanguage, Command *> m_menuCommands;
-
- QWeakPointer<ProjectExplorer::Project> m_previousProject;
- QWeakPointer<ProjectExplorer::Target> m_previousTarget;
- QWeakPointer<ProjectExplorer::RunConfiguration> m_previousRunConfiguration;
-
- bool m_initialized;
-
- static DebuggerUISwitcher *m_instance;
-};
-
-DebuggerUISwitcherPrivate::DebuggerUISwitcherPrivate(DebuggerUISwitcher *q)
- : m_resizeEventFilter(new Internal::DockWidgetEventFilter(q))
- , m_supportedLanguages(AnyLanguage)
- , m_languageCount(0)
- , m_toolbarStack(new QStackedWidget)
- , m_inDebugMode(false)
- , m_changingUI(false)
- , m_previousDebugLanguages(AnyLanguage)
- , m_activeDebugLanguages(AnyLanguage)
- , m_openMemoryEditorAction(0)
- , m_viewsMenu(0)
- , m_debugMenu(0)
- , m_initialized(false)
-{
-}
-
-DebuggerUISwitcher *DebuggerUISwitcherPrivate::m_instance = 0;
-
-DebuggerUISwitcher::DebuggerUISwitcher(BaseMode *mode, QObject* parent)
- : QObject(parent), d(new DebuggerUISwitcherPrivate(this))
-{
- mode->setWidget(createContents(mode));
-
- ICore *core = ICore::instance();
- ActionManager *am = core->actionManager();
-
- ProjectExplorer::ProjectExplorerPlugin *pe =
- ProjectExplorer::ProjectExplorerPlugin::instance();
- connect(pe->session(), SIGNAL(startupProjectChanged(ProjectExplorer::Project*)),
- SLOT(updateUiForProject(ProjectExplorer::Project*)));
- connect(d->m_resizeEventFilter, SIGNAL(widgetResized()),
- SLOT(updateDockWidgetSettings()));
-
- d->m_debugMenu = am->actionContainer(ProjectExplorer::Constants::M_DEBUG);
- d->m_viewsMenu = am->actionContainer(Core::Id(Core::Constants::M_WINDOW_VIEWS));
- QTC_ASSERT(d->m_viewsMenu, return)
-
- DebuggerUISwitcherPrivate::m_instance = this;
-}
-
-DebuggerUISwitcher::~DebuggerUISwitcher()
-{
- DebuggerUISwitcherPrivate::m_instance = 0;
- delete d;
-}
-
-void DebuggerUISwitcher::updateUiOnFileListChange()
-{
- if (d->m_previousProject)
- updateUiForTarget(d->m_previousProject.data()->activeTarget());
-}
-
-void DebuggerUISwitcher::updateUiForProject(ProjectExplorer::Project *project)
-{
- if (!project)
- return;
- if (d->m_previousProject) {
- disconnect(d->m_previousProject.data(),
- SIGNAL(activeTargetChanged(ProjectExplorer::Target*)),
- this, SLOT(updateUiForTarget(ProjectExplorer::Target*)));
- }
- d->m_previousProject = project;
- connect(project, SIGNAL(fileListChanged()),
- SLOT(updateUiOnFileListChange()));
- connect(project, SIGNAL(activeTargetChanged(ProjectExplorer::Target*)),
- SLOT(updateUiForTarget(ProjectExplorer::Target*)));
- updateUiForTarget(project->activeTarget());
-}
-
-void DebuggerUISwitcher::updateUiForTarget(ProjectExplorer::Target *target)
-{
- if (!target)
- return;
-
- if (d->m_previousTarget) {
- disconnect(d->m_previousTarget.data(),
- SIGNAL(activeRunConfigurationChanged(ProjectExplorer::RunConfiguration*)),
- this, SLOT(updateUiForRunConfiguration(ProjectExplorer::RunConfiguration*)));
- }
- d->m_previousTarget = target;
- connect(target,
- SIGNAL(activeRunConfigurationChanged(ProjectExplorer::RunConfiguration*)),
- SLOT(updateUiForRunConfiguration(ProjectExplorer::RunConfiguration*)));
- updateUiForRunConfiguration(target->activeRunConfiguration());
-}
-
-// updates default debug language settings per run config.
-void DebuggerUISwitcher::updateUiForRunConfiguration(ProjectExplorer::RunConfiguration *rc)
-{
- if (rc) {
- if (d->m_previousRunConfiguration) {
- disconnect(d->m_previousRunConfiguration.data(),
- SIGNAL(debuggersChanged()),
- this, SLOT(updateUiForCurrentRunConfiguration()));
- }
- d->m_previousRunConfiguration = rc;
- connect(d->m_previousRunConfiguration.data(),
- SIGNAL(debuggersChanged()),
- this, SLOT(updateUiForCurrentRunConfiguration()));
-
- updateUiForCurrentRunConfiguration();
- }
-}
-
-void DebuggerUISwitcher::updateUiForCurrentRunConfiguration()
-{
- updateActiveLanguages();
-}
-
-void DebuggerUISwitcher::updateActiveLanguages()
-{
- DebuggerLanguages newLanguages = AnyLanguage;
-
- if (d->m_previousRunConfiguration) {
- if (d->m_previousRunConfiguration.data()->useCppDebugger())
- newLanguages = CppLanguage;
- if (d->m_previousRunConfiguration.data()->useQmlDebugger())
- newLanguages |= QmlLanguage;
- }
-
- if (newLanguages != d->m_activeDebugLanguages) {
- d->m_activeDebugLanguages = newLanguages;
- emit activeLanguagesChanged(d->m_activeDebugLanguages);
- }
-
- updateUi();
-}
-
-DebuggerLanguages DebuggerUISwitcher::supportedLanguages() const
-{
- return d->m_supportedLanguages;
-}
-
-void DebuggerUISwitcher::addMenuAction(Command *command,
- const DebuggerLanguage &language, const QString &group)
-{
- d->m_debugMenu->addAction(command, group);
- d->m_menuCommands.insert(language, command);
-}
-
-DebuggerLanguages DebuggerUISwitcher::activeDebugLanguages() const
-{
- return d->m_activeDebugLanguages;
-}
-
-void DebuggerUISwitcher::onModeChanged(IMode *mode)
-{
- d->m_inDebugMode = (mode->id() == Constants::MODE_DEBUG);
- d->m_mainWindow->setDockActionsVisible(d->m_inDebugMode);
- hideInactiveWidgets();
-
- if (mode->id() != Constants::MODE_DEBUG)
- //|| DebuggerPlugin::instance()->hasSnapsnots())
- return;
-
- updateActiveLanguages();
-}
-
-void DebuggerUISwitcher::hideInactiveWidgets()
-{
- // Hide all the debugger windows if mode is different.
- if (d->m_inDebugMode)
- return;
- // Hide dock widgets manually in case they are floating.
- foreach (QDockWidget *dockWidget, d->m_dockWidgets) {
- if (dockWidget->isFloating())
- dockWidget->hide();
- }
-}
-
-void DebuggerUISwitcher::createViewsMenuItems()
-{
- ICore *core = ICore::instance();
- ActionManager *am = core->actionManager();
- Context globalcontext(Core::Constants::C_GLOBAL);
-
- d->m_openMemoryEditorAction = new QAction(this);
- d->m_openMemoryEditorAction->setText(tr("Memory..."));
- connect(d->m_openMemoryEditorAction, SIGNAL(triggered()),
- SIGNAL(memoryEditorRequested()));
-
- // Add menu items
- Command *cmd = 0;
- cmd = am->registerAction(d->m_openMemoryEditorAction,
- Core::Id("Debugger.Views.OpenMemoryEditor"),
- Core::Context(Constants::C_DEBUGMODE));
- d->m_viewsMenu->addAction(cmd);
- cmd = am->registerAction(d->m_mainWindow->menuSeparator1(),
- Core::Id("Debugger.Views.Separator1"), globalcontext);
- d->m_viewsMenu->addAction(cmd);
- cmd = am->registerAction(d->m_mainWindow->toggleLockedAction(),
- Core::Id("Debugger.Views.ToggleLocked"), globalcontext);
- d->m_viewsMenu->addAction(cmd);
- cmd = am->registerAction(d->m_mainWindow->menuSeparator2(),
- Core::Id("Debugger.Views.Separator2"), globalcontext);
- d->m_viewsMenu->addAction(cmd);
- cmd = am->registerAction(d->m_mainWindow->resetLayoutAction(),
- Core::Id("Debugger.Views.ResetSimple"), globalcontext);
- d->m_viewsMenu->addAction(cmd);
-}
-
-DebuggerUISwitcher *DebuggerUISwitcher::instance()
-{
- return DebuggerUISwitcherPrivate::m_instance;
-}
-
-void DebuggerUISwitcher::addLanguage(const DebuggerLanguage &languageId, const Context &context)
-{
- bool activate = (d->m_supportedLanguages == AnyLanguage);
- d->m_supportedLanguages = d->m_supportedLanguages | languageId;
- d->m_languageCount++;
-
- d->m_toolBars.insert(languageId, 0);
- d->m_contextsForLanguage.insert(languageId, context);
-
- updateUiForRunConfiguration(0);
-
- if (activate)
- updateUi();
-}
-
-void DebuggerUISwitcher::updateUi()
-{
- if (d->m_changingUI || !d->m_initialized || !d->m_inDebugMode)
- return;
-
- d->m_changingUI = true;
-
- if (isQmlActive()) {
- activateQmlCppLayout();
- } else {
- activateCppLayout();
- }
-
- d->m_previousDebugLanguages = d->m_activeDebugLanguages;
-
- d->m_changingUI = false;
-}
-
-void DebuggerUISwitcher::activateQmlCppLayout()
-{
- ICore *core = ICore::instance();
- Context qmlCppContext = d->m_contextsForLanguage.value(QmlLanguage);
- qmlCppContext.add(d->m_contextsForLanguage.value(CppLanguage));
-
- // always use cpp toolbar
- d->m_toolbarStack->setCurrentWidget(d->m_toolBars.value(CppLanguage));
-
- if (d->m_previousDebugLanguages & QmlLanguage) {
- d->m_dockWidgetActiveStateQmlCpp = d->m_mainWindow->saveSettings();
- core->updateAdditionalContexts(qmlCppContext, Context());
- } else if (d->m_previousDebugLanguages & CppLanguage) {
- d->m_dockWidgetActiveStateCpp = d->m_mainWindow->saveSettings();
- core->updateAdditionalContexts(d->m_contextsForLanguage.value(CppLanguage), Context());
- }
-
- d->m_mainWindow->restoreSettings(d->m_dockWidgetActiveStateQmlCpp);
- core->updateAdditionalContexts(Context(), qmlCppContext);
-}
-
-void DebuggerUISwitcher::activateCppLayout()
-{
- ICore *core = ICore::instance();
- Context qmlCppContext = d->m_contextsForLanguage.value(QmlLanguage);
- qmlCppContext.add(d->m_contextsForLanguage.value(CppLanguage));
- d->m_toolbarStack->setCurrentWidget(d->m_toolBars.value(CppLanguage));
-
- if (d->m_previousDebugLanguages & QmlLanguage) {
- d->m_dockWidgetActiveStateQmlCpp = d->m_mainWindow->saveSettings();
- core->updateAdditionalContexts(qmlCppContext, Context());
- } else if (d->m_previousDebugLanguages & CppLanguage) {
- d->m_dockWidgetActiveStateCpp = d->m_mainWindow->saveSettings();
- core->updateAdditionalContexts(d->m_contextsForLanguage.value(CppLanguage), Context());
- }
-
- d->m_mainWindow->restoreSettings(d->m_dockWidgetActiveStateCpp);
-
- const Context &cppContext = d->m_contextsForLanguage.value(CppLanguage);
- core->updateAdditionalContexts(Context(), cppContext);
-}
-
-void DebuggerUISwitcher::setToolbar(const DebuggerLanguage &language, QWidget *widget)
-{
- Q_ASSERT(d->m_toolBars.contains(language));
- d->m_toolBars[language] = widget;
- d->m_toolbarStack->addWidget(widget);
-}
-
-Utils::FancyMainWindow *DebuggerUISwitcher::mainWindow() const
-{
- return d->m_mainWindow;
-}
-
-QWidget *DebuggerUISwitcher::createMainWindow(BaseMode *mode)
-{
- d->m_mainWindow = new Internal::DebuggerMainWindow(this);
- d->m_mainWindow->setDocumentMode(true);
- d->m_mainWindow->setDockNestingEnabled(true);
- connect(d->m_mainWindow, SIGNAL(resetLayout()),
- SLOT(resetDebuggerLayout()));
- connect(d->m_mainWindow->toggleLockedAction(), SIGNAL(triggered()),
- SLOT(updateDockWidgetSettings()));
-
- QBoxLayout *editorHolderLayout = new QVBoxLayout;
- editorHolderLayout->setMargin(0);
- editorHolderLayout->setSpacing(0);
-
- QWidget *editorAndFindWidget = new QWidget;
- editorAndFindWidget->setLayout(editorHolderLayout);
- editorHolderLayout->addWidget(new EditorManagerPlaceHolder(mode));
- editorHolderLayout->addWidget(new FindToolBarPlaceHolder(editorAndFindWidget));
-
- MiniSplitter *documentAndRightPane = new MiniSplitter;
- documentAndRightPane->addWidget(editorAndFindWidget);
- documentAndRightPane->addWidget(new RightPanePlaceHolder(mode));
- documentAndRightPane->setStretchFactor(0, 1);
- documentAndRightPane->setStretchFactor(1, 0);
-
- Utils::StyledBar *debugToolBar = new Utils::StyledBar;
- debugToolBar->setProperty("topBorder", true);
- QHBoxLayout *debugToolBarLayout = new QHBoxLayout(debugToolBar);
- debugToolBarLayout->setMargin(0);
- debugToolBarLayout->setSpacing(0);
- debugToolBarLayout->addWidget(d->m_toolbarStack);
- debugToolBarLayout->addStretch();
- debugToolBarLayout->addWidget(new Utils::StyledSeparator);
-
- QDockWidget *dock = new QDockWidget(tr("Debugger Toolbar"));
- dock->setObjectName(QLatin1String("Debugger Toolbar"));
- dock->setWidget(debugToolBar);
- dock->setFeatures(QDockWidget::NoDockWidgetFeatures);
- dock->setAllowedAreas(Qt::BottomDockWidgetArea);
- dock->setTitleBarWidget(new QWidget(dock));
- d->m_mainWindow->addDockWidget(Qt::BottomDockWidgetArea, dock);
- d->m_mainWindow->setToolBarDockWidget(dock);
-
- QWidget *centralWidget = new QWidget;
- d->m_mainWindow->setCentralWidget(centralWidget);
-
- QVBoxLayout *centralLayout = new QVBoxLayout(centralWidget);
- centralWidget->setLayout(centralLayout);
- centralLayout->setMargin(0);
- centralLayout->setSpacing(0);
- centralLayout->addWidget(documentAndRightPane);
- centralLayout->setStretch(0, 1);
- centralLayout->setStretch(1, 0);
-
- return d->m_mainWindow;
-}
-
-QDockWidget *DebuggerUISwitcher::breakWindow() const
-{
- return dockWidget(Constants::DOCKWIDGET_BREAK);
-}
-
-QDockWidget *DebuggerUISwitcher::stackWindow() const
-{
- return dockWidget(Constants::DOCKWIDGET_STACK);
-}
-
-QDockWidget *DebuggerUISwitcher::watchWindow() const
-{
- return dockWidget(Constants::DOCKWIDGET_WATCHERS);
-}
-
-QDockWidget *DebuggerUISwitcher::outputWindow() const
-{
- return dockWidget(Constants::DOCKWIDGET_OUTPUT);
-}
-
-QDockWidget *DebuggerUISwitcher::snapshotsWindow() const
-{
- return dockWidget(Constants::DOCKWIDGET_SNAPSHOTS);
-}
-
-QDockWidget *DebuggerUISwitcher::threadsWindow() const
-{
- return dockWidget(Constants::DOCKWIDGET_THREADS);
-}
-
-QDockWidget *DebuggerUISwitcher::qmlInspectorWindow() const
-{
- return dockWidget(Constants::DOCKWIDGET_QML_INSPECTOR);
-}
-
-QDockWidget *DebuggerUISwitcher::dockWidget(const QString &objectName) const
-{
- foreach(QDockWidget *dockWidget, d->m_dockWidgets) {
- if (dockWidget->objectName() == objectName)
- return dockWidget;
- }
- return 0;
-}
-
-/*!
- Keep track of dock widgets so they can be shown/hidden for different languages
-*/
-QDockWidget *DebuggerUISwitcher::createDockWidget(const DebuggerLanguage &language,
- QWidget *widget, Qt::DockWidgetArea area)
-{
-// qDebug() << "CREATE DOCK" << widget->objectName() << "LANGUAGE ID" << language
-// << "VISIBLE BY DEFAULT" << ((d->m_activeDebugLanguages & language) ? "true" : "false");
- QDockWidget *dockWidget = d->m_mainWindow->addDockForWidget(widget);
- d->m_mainWindow->addDockWidget(area, dockWidget);
- d->m_dockWidgets.append(dockWidget);
-
- if (!(d->m_activeDebugLanguages & language))
- dockWidget->hide();
-
- Context globalContext(Core::Constants::C_GLOBAL);
-
- ActionManager *am = ICore::instance()->actionManager();
- QAction *toggleViewAction = dockWidget->toggleViewAction();
- Command *cmd = am->registerAction(toggleViewAction,
- QString("Debugger." + dockWidget->objectName()), globalContext);
- cmd->setAttribute(Command::CA_Hide);
- d->m_viewsMenu->addAction(cmd);
-
- d->m_viewsMenuItems.append(qMakePair(language, toggleViewAction));
-
- dockWidget->installEventFilter(d->m_resizeEventFilter);
-
- connect(dockWidget->toggleViewAction(), SIGNAL(triggered(bool)),
- SLOT(updateDockWidgetSettings()));
- connect(dockWidget, SIGNAL(topLevelChanged(bool)),
- SLOT(updateDockWidgetSettings()));
- connect(dockWidget, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)),
- SLOT(updateDockWidgetSettings()));
-
- return dockWidget;
-}
-
-QWidget *DebuggerUISwitcher::createContents(BaseMode *mode)
-{
- // right-side window with editor, output etc.
- MiniSplitter *mainWindowSplitter = new MiniSplitter;
- mainWindowSplitter->addWidget(createMainWindow(mode));
- mainWindowSplitter->addWidget(new OutputPanePlaceHolder(mode, mainWindowSplitter));
- mainWindowSplitter->setStretchFactor(0, 10);
- mainWindowSplitter->setStretchFactor(1, 0);
- mainWindowSplitter->setOrientation(Qt::Vertical);
-
- // navigation + right-side window
- MiniSplitter *splitter = new MiniSplitter;
- splitter->addWidget(new NavigationWidgetPlaceHolder(mode));
- splitter->addWidget(mainWindowSplitter);
- splitter->setStretchFactor(0, 0);
- splitter->setStretchFactor(1, 1);
- return splitter;
-}
-
-void DebuggerUISwitcher::aboutToStartDebugger()
-{
- if (!DebuggerPlugin::instance()->hasSnapsnots())
- updateActiveLanguages();
-}
-
-void DebuggerUISwitcher::aboutToShutdown()
-{
- writeSettings();
-}
-
-void DebuggerUISwitcher::writeSettings() const
-{
- QSettings *settings = ICore::instance()->settings();
- {
- settings->beginGroup(QLatin1String("DebugMode.CppMode"));
- QHashIterator<QString, QVariant> it(d->m_dockWidgetActiveStateCpp);
- while (it.hasNext()) {
- it.next();
- settings->setValue(it.key(), it.value());
- }
- settings->endGroup();
- }
- {
- settings->beginGroup(QLatin1String("DebugMode.CppQmlMode"));
- QHashIterator<QString, QVariant> it(d->m_dockWidgetActiveStateQmlCpp);
- while (it.hasNext()) {
- it.next();
- settings->setValue(it.key(), it.value());
- }
- settings->endGroup();
- }
-}
-
-void DebuggerUISwitcher::readSettings()
-{
- QSettings *settings = ICore::instance()->settings();
- d->m_dockWidgetActiveStateCpp.clear();
- d->m_dockWidgetActiveStateQmlCpp.clear();
-
- settings->beginGroup(QLatin1String("DebugMode.CppMode"));
- foreach (const QString &key, settings->childKeys()) {
- d->m_dockWidgetActiveStateCpp.insert(key, settings->value(key));
- }
- settings->endGroup();
-
- settings->beginGroup(QLatin1String("DebugMode.CppQmlMode"));
- foreach (const QString &key, settings->childKeys()) {
- d->m_dockWidgetActiveStateQmlCpp.insert(key, settings->value(key));
- }
- settings->endGroup();
-
- // reset initial settings when there are none yet
- DebuggerLanguages langs = d->m_activeDebugLanguages;
- if (d->m_dockWidgetActiveStateCpp.isEmpty()) {
- d->m_activeDebugLanguages = CppLanguage;
- resetDebuggerLayout();
- }
- if (d->m_dockWidgetActiveStateQmlCpp.isEmpty()) {
- d->m_activeDebugLanguages = QmlLanguage;
- resetDebuggerLayout();
- }
- d->m_activeDebugLanguages = langs;
-}
-
-void DebuggerUISwitcher::initialize()
-{
- createViewsMenuItems();
-
- emit dockResetRequested(AnyLanguage);
- readSettings();
-
- updateUi();
-
- hideInactiveWidgets();
- d->m_mainWindow->setDockActionsVisible(false);
- d->m_initialized = true;
-}
-
-void DebuggerUISwitcher::resetDebuggerLayout()
-{
- emit dockResetRequested(d->m_activeDebugLanguages);
-
- if (isQmlActive()) {
- d->m_dockWidgetActiveStateQmlCpp = d->m_mainWindow->saveSettings();
- } else {
- d->m_dockWidgetActiveStateCpp = d->m_mainWindow->saveSettings();
- }
-
- updateActiveLanguages();
-}
-
-void DebuggerUISwitcher::updateDockWidgetSettings()
-{
- if (!d->m_inDebugMode || d->m_changingUI)
- return;
-
- if (isQmlActive()) {
- d->m_dockWidgetActiveStateQmlCpp = d->m_mainWindow->saveSettings();
- } else {
- d->m_dockWidgetActiveStateCpp = d->m_mainWindow->saveSettings();
- }
-}
-
-bool DebuggerUISwitcher::isQmlCppActive() const
-{
- return (d->m_activeDebugLanguages & CppLanguage)
- && (d->m_activeDebugLanguages & QmlLanguage);
-}
-
-bool DebuggerUISwitcher::isQmlActive() const
-{
- return (d->m_activeDebugLanguages & QmlLanguage);
-}
-
-QList<QDockWidget* > DebuggerUISwitcher::i_mw_dockWidgets() const
-{
- return d->m_dockWidgets;
-}
-
-} // namespace Debugger
-
-#include "debuggeruiswitcher.moc"
diff --git a/src/plugins/debugger/debuggeruiswitcher.h b/src/plugins/debugger/debuggeruiswitcher.h
deleted file mode 100644
index e43a698b92..0000000000
--- a/src/plugins/debugger/debuggeruiswitcher.h
+++ /dev/null
@@ -1,165 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#ifndef DEBUGGERUISWITCHER_H
-#define DEBUGGERUISWITCHER_H
-
-#include "debugger_global.h"
-#include "debuggerconstants.h"
-
-#include <QtCore/QObject>
-
-QT_BEGIN_NAMESPACE
-class QDockWidget;
-QT_END_NAMESPACE
-
-namespace Core {
- class ActionContainer;
- class Command;
- class Context;
- class BaseMode;
- class IMode;
-}
-
-namespace Utils {
-class FancyMainWindow;
- class SavedAction;
-}
-
-namespace ProjectExplorer {
- class Project;
- class Target;
- class RunConfiguration;
-}
-
-namespace Debugger {
-struct DebuggerUISwitcherPrivate;
-
-namespace Internal {
-class DebuggerMainWindow;
-};
-
-class DEBUGGER_EXPORT DebuggerUISwitcher : public QObject
-{
- Q_OBJECT
-
-public:
- explicit DebuggerUISwitcher(Core::BaseMode *mode, QObject *parent = 0);
- virtual ~DebuggerUISwitcher();
-
- static DebuggerUISwitcher *instance();
-
- // debuggable languages are registered with this function.
- void addLanguage(const DebuggerLanguage &language, const Core::Context &context);
-
- // debugger toolbars are registered with this function
- void setToolbar(const DebuggerLanguage &language, QWidget *widget);
-
- // menu actions are registered with this function
- void addMenuAction(Core::Command *command, const DebuggerLanguage &language,
- const QString &group = QString());
-
- // all supported languages
- DebuggerLanguages supportedLanguages() const;
-
- // active languages to be debugged.
- DebuggerLanguages activeDebugLanguages() const;
-
- // called when all dependent plugins have loaded
- void initialize();
-
- void aboutToStartDebugger();
- void aboutToShutdown();
- void onModeChanged(Core::IMode *mode);
-
- // most common debugger windows
- QDockWidget *breakWindow() const;
- QDockWidget *stackWindow() const;
- QDockWidget *watchWindow() const;
- QDockWidget *snapshotsWindow() const;
- QDockWidget *threadsWindow() const;
- QDockWidget *outputWindow() const;
- QDockWidget *qmlInspectorWindow() const;
-
- QDockWidget *dockWidget(const QString &objectName) const;
-
- // dockwidgets are registered to the main window
- QDockWidget *createDockWidget(const DebuggerLanguage &language, QWidget *widget,
- Qt::DockWidgetArea area = Qt::TopDockWidgetArea);
-
- Utils::FancyMainWindow *mainWindow() const;
-
-signals:
- // emit when user changes active languages from the menu.
- // Both UI and debugger startup are affected.
- void activeLanguagesChanged(Debugger::DebuggerLanguages activeLanguages);
- void dockResetRequested(const Debugger::DebuggerLanguages &activeLanguages);
- void memoryEditorRequested();
-
-private slots:
- void updateUi();
- void resetDebuggerLayout();
-
- void updateUiForProject(ProjectExplorer::Project *project);
- void updateUiForTarget(ProjectExplorer::Target *target);
- void updateUiForRunConfiguration(ProjectExplorer::RunConfiguration *rc);
- void updateUiForCurrentRunConfiguration();
- void updateUiOnFileListChange();
-
- void updateActiveLanguages();
- void updateDockWidgetSettings();
-
-private:
- // Used by MainWindow
- friend class Internal::DebuggerMainWindow;
- QList<QDockWidget *> i_mw_dockWidgets() const;
-
- void activateQmlCppLayout();
- void activateCppLayout();
-
- void hideInactiveWidgets();
- void createViewsMenuItems();
- void readSettings();
- void writeSettings() const;
- bool isQmlCppActive() const;
- bool isQmlActive() const;
-
- QWidget *createContents(Core::BaseMode *mode);
- QWidget *createMainWindow(Core::BaseMode *mode);
-
- DebuggerUISwitcherPrivate *d;
-};
-
-} // namespace Debugger
-
-#endif // DEBUGGERUISWITCHER_H
diff --git a/src/plugins/debugger/disassembleragent.cpp b/src/plugins/debugger/disassembleragent.cpp
new file mode 100644
index 0000000000..5337451aeb
--- /dev/null
+++ b/src/plugins/debugger/disassembleragent.cpp
@@ -0,0 +1,354 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "disassembleragent.h"
+
+#include "breakhandler.h"
+#include "debuggerengine.h"
+#include "debuggercore.h"
+#include "debuggerstringutils.h"
+#include "stackframe.h"
+
+#include <coreplugin/coreconstants.h>
+#include <coreplugin/editormanager/ieditor.h>
+#include <coreplugin/icore.h>
+#include <coreplugin/mimedatabase.h>
+
+#include <texteditor/basetextdocument.h>
+#include <texteditor/basetexteditor.h>
+#include <texteditor/basetextmark.h>
+#include <texteditor/plaintexteditor.h>
+#include <texteditor/texteditorconstants.h>
+
+#include <utils/qtcassert.h>
+
+#include <QtGui/QTextBlock>
+#include <QtGui/QIcon>
+
+
+using namespace Core;
+
+namespace Debugger {
+namespace Internal {
+
+///////////////////////////////////////////////////////////////////////
+//
+// DisassemblerAgent
+//
+///////////////////////////////////////////////////////////////////////
+
+class LocationMark2 : public TextEditor::ITextMark
+{
+public:
+ LocationMark2() {}
+
+ QIcon icon() const { return debuggerCore()->locationMarkIcon(); }
+ void updateLineNumber(int /*lineNumber*/) {}
+ void updateBlock(const QTextBlock & /*block*/) {}
+ void removedFromEditor() {}
+ void documentClosing() {}
+};
+
+class BreakpointMarker2 : public TextEditor::ITextMark
+{
+public:
+ BreakpointMarker2(const QIcon &icon) : m_icon(icon) {}
+
+ QIcon icon() const { return m_icon; }
+ void updateLineNumber(int) {}
+ void updateBlock(const QTextBlock &) {}
+ void removedFromEditor() {}
+ void documentClosing() {}
+
+private:
+ QIcon m_icon;
+};
+
+
+class DisassemblerAgentPrivate
+{
+public:
+ DisassemblerAgentPrivate();
+ ~DisassemblerAgentPrivate();
+ void configureMimeType();
+
+public:
+ QPointer<TextEditor::ITextEditor> editor;
+ Location location;
+ bool tryMixed;
+ QPointer<DebuggerEngine> engine;
+ TextEditor::ITextMark *locationMark;
+ QList<TextEditor::ITextMark *> breakpointMarks;
+
+ QHash<QString, DisassemblerLines> cache;
+ QString mimeType;
+};
+
+DisassemblerAgentPrivate::DisassemblerAgentPrivate()
+ : editor(0),
+ tryMixed(true),
+ locationMark(new LocationMark2),
+ mimeType(_("text/x-qtcreator-generic-asm"))
+{
+}
+
+DisassemblerAgentPrivate::~DisassemblerAgentPrivate()
+{
+ if (editor) {
+ EditorManager *editorManager = EditorManager::instance();
+ editorManager->closeEditors(QList<IEditor *>() << editor);
+ }
+ editor = 0;
+ delete locationMark;
+}
+
+/*!
+ \class DisassemblerAgent
+
+ Objects from this class are created in response to user actions in
+ the Gui for showing disassembled memory from the inferior. After creation
+ it handles communication between the engine and the editor.
+*/
+
+DisassemblerAgent::DisassemblerAgent(DebuggerEngine *engine)
+ : QObject(0), d(new DisassemblerAgentPrivate)
+{
+ d->engine = engine;
+}
+
+DisassemblerAgent::~DisassemblerAgent()
+{
+ delete d;
+ d = 0;
+}
+
+void DisassemblerAgent::cleanup()
+{
+ d->cache.clear();
+}
+
+void DisassemblerAgent::resetLocation()
+{
+ if (!d->editor)
+ return;
+ d->editor->markableInterface()->removeMark(d->locationMark);
+}
+
+static QString frameKey(const Location &loc)
+{
+ return _("%1:%2:%3").arg(loc.functionName())
+ .arg(loc.fileName()).arg(loc.address());
+}
+
+const Location &DisassemblerAgent::location() const
+{
+ return d->location;
+}
+
+bool DisassemblerAgent::isMixed() const
+{
+ return d->tryMixed
+ && d->location.lineNumber() > 0
+ && !d->location.functionName().isEmpty()
+ && d->location.functionName() != _("??");
+}
+
+void DisassemblerAgent::setLocation(const Location &loc)
+{
+ d->location = loc;
+ if (isMixed()) {
+ QHash<QString, DisassemblerLines>::ConstIterator it =
+ d->cache.find(frameKey(loc));
+ if (it != d->cache.end()) {
+ QString msg = _("Use cache disassembler for '%1' in '%2'")
+ .arg(loc.functionName()).arg(loc.fileName());
+ d->engine->showMessage(msg);
+ setContents(*it);
+ updateBreakpointMarkers();
+ updateLocationMarker();
+ return;
+ }
+ }
+ d->engine->fetchDisassembler(this);
+}
+
+void DisassemblerAgentPrivate::configureMimeType()
+{
+ QTC_ASSERT(editor, return);
+
+ TextEditor::BaseTextDocument *doc =
+ qobject_cast<TextEditor::BaseTextDocument *>(editor->file());
+ QTC_ASSERT(doc, return);
+ doc->setMimeType(mimeType);
+
+ TextEditor::PlainTextEditor *pe =
+ qobject_cast<TextEditor::PlainTextEditor *>(editor->widget());
+ QTC_ASSERT(pe, return);
+
+ MimeType mtype = ICore::instance()->mimeDatabase()->findByType(mimeType);
+ if (mtype)
+ pe->configure(mtype);
+ else
+ qWarning("Assembler mimetype '%s' not found.", qPrintable(mimeType));
+}
+
+QString DisassemblerAgent::mimeType() const
+{
+ return d->mimeType;
+}
+
+void DisassemblerAgent::setMimeType(const QString &mt)
+{
+ if (mt == d->mimeType)
+ return;
+ d->mimeType = mt;
+ if (d->editor)
+ d->configureMimeType();
+}
+
+void DisassemblerAgent::setContents(const DisassemblerLines &contents)
+{
+ QTC_ASSERT(d, return);
+ using namespace Core;
+ using namespace TextEditor;
+
+ EditorManager *editorManager = EditorManager::instance();
+ if (!d->editor) {
+ QString titlePattern = "Disassembler";
+ d->editor = qobject_cast<ITextEditor *>(
+ editorManager->openEditorWithContents(
+ Core::Constants::K_DEFAULT_TEXT_EDITOR_ID,
+ &titlePattern));
+ QTC_ASSERT(d->editor, return);
+ d->editor->setProperty(Debugger::Constants::OPENED_BY_DEBUGGER, true);
+ d->editor->setProperty(Debugger::Constants::OPENED_WITH_DISASSEMBLY, true);
+ d->configureMimeType();
+
+ BaseTextEditor *baseTextEdit =
+ qobject_cast<BaseTextEditor *>(d->editor->widget());
+ if (baseTextEdit)
+ baseTextEdit->setRequestMarkEnabled(true);
+ }
+
+ editorManager->activateEditor(d->editor);
+
+ QPlainTextEdit *plainTextEdit =
+ qobject_cast<QPlainTextEdit *>(d->editor->widget());
+ QTC_ASSERT(plainTextEdit, return);
+
+ QString str;
+ for (int i = 0, n = contents.size(); i != n; ++i) {
+ const DisassemblerLine &dl = contents.at(i);
+ if (dl.address) {
+ str += QString("0x");
+ str += QString::number(dl.address, 16);
+ str += " ";
+ }
+ str += dl.data;
+ str += "\n";
+ }
+ plainTextEdit->setPlainText(str);
+ plainTextEdit->setReadOnly(true);
+
+ d->cache.insert(frameKey(d->location), contents);
+ d->editor->setDisplayName(_("Disassembler (%1)")
+ .arg(d->location.functionName()));
+
+ updateBreakpointMarkers();
+ updateLocationMarker();
+}
+
+void DisassemblerAgent::updateLocationMarker()
+{
+ QTC_ASSERT(d->editor, return);
+
+ const DisassemblerLines &contents = d->cache.value(frameKey(d->location));
+ int lineNumber = contents.lineForAddress(d->location.address());
+
+ if (d->location.needsMarker()) {
+ d->editor->markableInterface()->removeMark(d->locationMark);
+ if (lineNumber)
+ d->editor->markableInterface()->addMark(d->locationMark, lineNumber);
+ }
+
+ QPlainTextEdit *plainTextEdit =
+ qobject_cast<QPlainTextEdit *>(d->editor->widget());
+ QTC_ASSERT(plainTextEdit, return);
+ QTextCursor tc = plainTextEdit->textCursor();
+ QTextBlock block = tc.document()->findBlockByNumber(lineNumber - 1);
+ tc.setPosition(block.position());
+ plainTextEdit->setTextCursor(tc);
+}
+
+void DisassemblerAgent::updateBreakpointMarkers()
+{
+ if (!d->editor)
+ return;
+
+ BreakHandler *handler = breakHandler();
+ BreakpointIds ids = handler->engineBreakpointIds(d->engine);
+ if (ids.isEmpty())
+ return;
+
+ const DisassemblerLines &contents = d->cache.value(frameKey(d->location));
+
+ foreach (TextEditor::ITextMark *marker, d->breakpointMarks)
+ d->editor->markableInterface()->removeMark(marker);
+ d->breakpointMarks.clear();
+ foreach (BreakpointId id, ids) {
+ const quint64 address = handler->address(id);
+ if (!address)
+ continue;
+ const int lineNumber = contents.lineForAddress(address);
+ if (!lineNumber)
+ continue;
+ BreakpointMarker2 *marker = new BreakpointMarker2(handler->icon(id));
+ d->breakpointMarks.append(marker);
+ d->editor->markableInterface()->addMark(marker, lineNumber);
+ }
+}
+
+quint64 DisassemblerAgent::address() const
+{
+ return d->location.address();
+}
+
+// Return address of an assembly line "0x0dfd bla"
+quint64 DisassemblerAgent::addressFromDisassemblyLine(const QString &line)
+{
+ return DisassemblerLine(line).address;
+}
+
+void DisassemblerAgent::setTryMixed(bool on)
+{
+ d->tryMixed = on;
+}
+
+} // namespace Internal
+} // namespace Debugger
diff --git a/src/plugins/debugger/disassembleragent.h b/src/plugins/debugger/disassembleragent.h
new file mode 100644
index 0000000000..930400b3d2
--- /dev/null
+++ b/src/plugins/debugger/disassembleragent.h
@@ -0,0 +1,88 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 DEBUGGER_DISASSEMBLERAGENT_H
+#define DEBUGGER_DISASSEMBLERAGENT_H
+
+#include "disassemblerlines.h"
+
+#include <QtCore/QObject>
+#include <QtCore/QPointer>
+
+namespace Core {
+class IEditor;
+}
+
+namespace Debugger {
+
+class DebuggerEngine;
+
+namespace Internal {
+
+class Location;
+class DisassemblerAgentPrivate;
+
+class DisassemblerAgent : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString mimeType READ mimeType WRITE setMimeType)
+public:
+ // Called from Gui
+ explicit DisassemblerAgent(DebuggerEngine *engine);
+ ~DisassemblerAgent();
+
+ void setTryMixed(bool on);
+ void setLocation(const Location &location);
+ const Location &location() const;
+ void resetLocation();
+ void setContents(const DisassemblerLines &contents);
+ void updateLocationMarker();
+ void updateBreakpointMarkers();
+
+ // Mimetype: "text/a-asm" or some specialized architecture
+ QString mimeType() const;
+ Q_SLOT void setMimeType(const QString &mt);
+
+ quint64 address() const;
+ bool contentsCoversAddress(const QString &contents) const;
+ void cleanup();
+ bool isMixed() const;
+
+ // Return address of an assembly line "0x0dfd bla"
+ static quint64 addressFromDisassemblyLine(const QString &data);
+
+private:
+ DisassemblerAgentPrivate *d;
+};
+
+
+} // namespace Internal
+} // namespace Debugger
+
+#endif // DEBUGGER_DISASSEMBLERAGENT_H
diff --git a/src/plugins/debugger/disassemblerlines.cpp b/src/plugins/debugger/disassemblerlines.cpp
new file mode 100644
index 0000000000..75f315a9ac
--- /dev/null
+++ b/src/plugins/debugger/disassemblerlines.cpp
@@ -0,0 +1,86 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "disassemblerlines.h"
+
+namespace Debugger {
+namespace Internal {
+
+DisassemblerLine::DisassemblerLine(const QString &unparsed)
+{
+ // Mac gdb has an overflow reporting 64bit addresses causing the instruction
+ // to follow the last digit "0x000000013fff4810mov 1,1". Truncate here.
+ const int pos = qMin(unparsed.indexOf(QLatin1Char(' ')), 19);
+ if (pos < 0) {
+ address = 0;
+ data = unparsed;
+ return;
+ }
+ QString addr = unparsed.left(pos);
+ // MSVC 64bit: Remove 64bit separator 00000000`00a45000'.
+ if (addr.size() >= 9 && addr.at(8) == QLatin1Char('`'))
+ addr.remove(8, 1);
+
+ if (addr.endsWith(':')) // clang
+ addr.chop(1);
+ if (addr.startsWith(QLatin1String("0x")))
+ addr.remove(0, 2);
+ bool ok;
+ address = addr.toULongLong(&ok, 16);
+ if (address)
+ data = unparsed.mid(pos + 1);
+ else
+ data = unparsed;
+}
+
+int DisassemblerLines::lineForAddress(quint64 address) const
+{
+ return m_rowCache.value(address);
+}
+
+bool DisassemblerLines::coversAddress(quint64 address) const
+{
+ return m_rowCache.value(address) != 0;
+}
+
+void DisassemblerLines::appendComment(const QString &comment)
+{
+ DisassemblerLine dl;
+ dl.data = comment;
+ m_data.append(dl);
+}
+
+void DisassemblerLines::appendLine(const DisassemblerLine &dl)
+{
+ m_data.append(dl);
+ m_rowCache[dl.address] = m_data.size();
+}
+
+} // namespace Internal
+} // namespace Debugger
diff --git a/src/plugins/debugger/disassemblerlines.h b/src/plugins/debugger/disassemblerlines.h
new file mode 100644
index 0000000000..a32d83b574
--- /dev/null
+++ b/src/plugins/debugger/disassemblerlines.h
@@ -0,0 +1,71 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 DEBUGGER_DISASSEMBLERLINES_H
+#define DEBUGGER_DISASSEMBLERLINES_H
+
+#include <QtCore/QString>
+#include <QtCore/QHash>
+#include <QtCore/QVector>
+
+namespace Debugger {
+namespace Internal {
+
+class DisassemblerLine
+{
+public:
+ DisassemblerLine() : address(0) {}
+ DisassemblerLine(const QString &unparsed);
+
+public:
+ quint64 address;
+ QString data;
+};
+
+class DisassemblerLines
+{
+public:
+ DisassemblerLines() {}
+
+ bool coversAddress(quint64 address) const;
+ void appendLine(const DisassemblerLine &dl);
+ void appendComment(const QString &comment);
+ int size() const { return m_data.size(); }
+ const DisassemblerLine &at(int i) const { return m_data.at(i); }
+ int lineForAddress(quint64 address) const;
+
+private:
+ QVector<DisassemblerLine> m_data;
+ QHash<quint64, int> m_rowCache;
+};
+
+} // namespace Internal
+} // namespace Debugger
+
+#endif // DEBUGGER_DISASSEMBLERLINES_H
diff --git a/src/plugins/debugger/dumperoptionpage.ui b/src/plugins/debugger/dumperoptionpage.ui
index 59ff2d9603..d3899b6f55 100644
--- a/src/plugins/debugger/dumperoptionpage.ui
+++ b/src/plugins/debugger/dumperoptionpage.ui
@@ -70,16 +70,6 @@
</property>
</widget>
</item>
- <item>
- <widget class="QCheckBox" name="checkBoxDebugDebuggingHelpers">
- <property name="toolTip">
- <string notr="true">This is an internal tool to make debugging the debugging helper code easier. Using this action is in general not needed unless you want do debug Qt Creator itself.</string>
- </property>
- <property name="text">
- <string>Debug debugging helper</string>
- </property>
- </widget>
- </item>
</layout>
</widget>
</item>
diff --git a/src/plugins/debugger/gdb/abstractgdbadapter.cpp b/src/plugins/debugger/gdb/abstractgdbadapter.cpp
index 0204126fa6..92cd683fcc 100644
--- a/src/plugins/debugger/gdb/abstractgdbadapter.cpp
+++ b/src/plugins/debugger/gdb/abstractgdbadapter.cpp
@@ -32,10 +32,13 @@
**************************************************************************/
#include "abstractgdbadapter.h"
-
+#include "gdbengine.h"
#include "abstractgdbprocess.h"
#include <utils/qtcassert.h>
+#ifdef Q_OS_WIN
+#include <utils/qtcprocess.h>
+#endif
#include <QtCore/QProcess>
@@ -78,6 +81,24 @@ bool AbstractGdbAdapter::isTrkAdapter() const
return false;
}
+#ifdef Q_OS_WIN
+bool AbstractGdbAdapter::prepareWinCommand()
+{
+ Utils::QtcProcess::SplitError perr;
+ startParameters().processArgs = Utils::QtcProcess::prepareArgs(
+ startParameters().processArgs, &perr,
+ &startParameters().environment, &startParameters().workingDirectory);
+ if (perr != Utils::QtcProcess::SplitOk) {
+ // perr == BadQuoting is never returned on Windows
+ // FIXME? QTCREATORBUG-2809
+ m_engine->handleAdapterStartFailed(QCoreApplication::translate("DebuggerEngine", // Same message in CdbEngine
+ "Debugging complex command lines is currently not supported under Windows"), QString());
+ return false;
+ }
+ return true;
+}
+#endif
+
QString AbstractGdbAdapter::msgGdbStopFailed(const QString &why)
{
return tr("The Gdb process could not be stopped:\n%1").arg(why);
@@ -108,5 +129,36 @@ QString AbstractGdbAdapter::msgConnectRemoteServerFailed(const QString &why)
return tr("Connecting to remote server failed:\n%1").arg(why);
}
+DebuggerState AbstractGdbAdapter::state() const
+{
+ return m_engine->state();
+}
+
+const DebuggerStartParameters &AbstractGdbAdapter::startParameters() const
+{
+ return m_engine->startParameters();
+}
+
+DebuggerStartParameters &AbstractGdbAdapter::startParameters()
+{
+ return m_engine->startParameters();
+}
+
+void AbstractGdbAdapter::showMessage(const QString &msg, int channel, int timeout)
+{
+ m_engine->showMessage(msg, channel, timeout);
+}
+
+void AbstractGdbAdapter::handleRemoteSetupDone(int gdbServerPort, int qmlPort)
+{
+ Q_UNUSED(gdbServerPort);
+ Q_UNUSED(qmlPort);
+}
+
+void AbstractGdbAdapter::handleRemoteSetupFailed(const QString &reason)
+{
+ Q_UNUSED(reason);
+}
+
} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/gdb/abstractgdbadapter.h b/src/plugins/debugger/gdb/abstractgdbadapter.h
index 9b85a4d0cd..526688a5af 100644
--- a/src/plugins/debugger/gdb/abstractgdbadapter.h
+++ b/src/plugins/debugger/gdb/abstractgdbadapter.h
@@ -34,14 +34,20 @@
#ifndef DEBUGGER_ABSTRACT_GDB_ADAPTER
#define DEBUGGER_ABSTRACT_GDB_ADAPTER
-#include <QtCore/QObject>
-
+#include "debuggerconstants.h"
+// Need to include gdbengine.h as otherwise MSVC crashes
+// on invoking the first adapter callback in a *derived* adapter class.
#include "gdbengine.h"
+#include <QtCore/QObject>
+
namespace Debugger {
+class DebuggerStartParameters;
+
namespace Internal {
class AbstractGdbProcess;
+class GdbResponse;
// AbstractGdbAdapter is inherited by PlainGdbAdapter used for local
// debugging and TrkGdbAdapter used for on-device debugging.
@@ -88,13 +94,17 @@ public:
virtual void trkReloadRegisters() {}
virtual void trkReloadThreads() {}
+ virtual void handleRemoteSetupDone(int gdbServerPort, int qmlPort);
+ virtual void handleRemoteSetupFailed(const QString &reason);
+
protected:
- DebuggerState state() const
- { return m_engine->state(); }
- const DebuggerStartParameters &startParameters() const
- { return m_engine->startParameters(); }
- void showMessage(const QString &msg, int channel = LogDebug, int timeout = 1)
- { m_engine->showMessage(msg, channel, timeout); }
+ DebuggerState state() const;
+ const DebuggerStartParameters &startParameters() const;
+ DebuggerStartParameters &startParameters();
+ void showMessage(const QString &msg, int channel = LogDebug, int timeout = 1);
+#ifdef Q_OS_WIN
+ bool prepareWinCommand();
+#endif
GdbEngine * const m_engine;
};
diff --git a/src/plugins/debugger/gdb/abstractplaingdbadapter.cpp b/src/plugins/debugger/gdb/abstractplaingdbadapter.cpp
index 76966de2ca..5f047ec54a 100644
--- a/src/plugins/debugger/gdb/abstractplaingdbadapter.cpp
+++ b/src/plugins/debugger/gdb/abstractplaingdbadapter.cpp
@@ -32,8 +32,10 @@
**************************************************************************/
#include "abstractplaingdbadapter.h"
-
+#include "gdbmi.h"
+#include "gdbengine.h"
#include "debuggeractions.h"
+#include "debuggercore.h"
#include "debuggerstringutils.h"
#include <utils/qtcassert.h>
@@ -55,7 +57,7 @@ void AbstractPlainGdbAdapter::setupInferior()
{
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
if (!startParameters().processArgs.isEmpty()) {
- QString args = startParameters().processArgs.join(_(" "));
+ QString args = startParameters().processArgs;
m_engine->postCommand("-exec-arguments " + toLocalEncoding(args));
}
m_engine->postCommand("-file-exec-and-symbols \"" + execFilePath() + '"',
@@ -99,7 +101,7 @@ void AbstractPlainGdbAdapter::handleExecRun(const GdbResponse &response)
showMessage(_("INFERIOR STARTED"));
showMessage(msgInferiorSetupOk(), StatusBar);
// FIXME: That's the wrong place for it.
- if (theDebuggerBoolSetting(EnableReverseDebugging))
+ if (debuggerCore()->boolSetting(EnableReverseDebugging))
m_engine->postCommand("target record");
} else {
QString msg = fromLocalEncoding(response.data.findChild("msg").data());
diff --git a/src/plugins/debugger/gdb/attachgdbadapter.cpp b/src/plugins/debugger/gdb/attachgdbadapter.cpp
index c491f98b5d..f594b38956 100644
--- a/src/plugins/debugger/gdb/attachgdbadapter.cpp
+++ b/src/plugins/debugger/gdb/attachgdbadapter.cpp
@@ -32,6 +32,7 @@
**************************************************************************/
#include "attachgdbadapter.h"
+#include "gdbmi.h"
#include "gdbengine.h"
#include "procinterrupt.h"
@@ -81,10 +82,11 @@ void AttachGdbAdapter::setupInferior()
void AttachGdbAdapter::runEngine()
{
QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
- m_engine->notifyEngineRunAndInferiorStopOk();
- m_engine->continueInferiorInternal();
m_engine->showStatusMessage(tr("Attached to process %1.")
.arg(m_engine->inferiorPid()));
+ m_engine->notifyEngineRunAndInferiorStopOk();
+ GdbMi data;
+ m_engine->handleStop0(data);
}
void AttachGdbAdapter::handleAttach(const GdbResponse &response)
diff --git a/src/plugins/debugger/gdb/attachgdbadapter.h b/src/plugins/debugger/gdb/attachgdbadapter.h
index 5e77137381..0968a17857 100644
--- a/src/plugins/debugger/gdb/attachgdbadapter.h
+++ b/src/plugins/debugger/gdb/attachgdbadapter.h
@@ -35,8 +35,7 @@
#define DEBUGGER_ATTACHGDBADAPTER_H
#include "abstractgdbadapter.h"
-
-#include "abstractgdbprocess.h"
+#include "localgdbprocess.h"
namespace Debugger {
namespace Internal {
diff --git a/src/plugins/debugger/gdb/classicgdbengine.cpp b/src/plugins/debugger/gdb/classicgdbengine.cpp
index 4bacf8cf22..644c3b3fdf 100644
--- a/src/plugins/debugger/gdb/classicgdbengine.cpp
+++ b/src/plugins/debugger/gdb/classicgdbengine.cpp
@@ -32,11 +32,12 @@
**************************************************************************/
#include "gdbengine.h"
+#include "gdbmi.h"
#include "abstractgdbadapter.h"
#include "debuggeractions.h"
+#include "debuggercore.h"
#include "debuggerstringutils.h"
-#include "debuggerplugin.h"
#include "stackhandler.h"
#include "watchhandler.h"
@@ -276,7 +277,7 @@ void GdbEngine::updateSubItemClassic(const WatchData &data0)
qDebug() << "IT'S A POINTER";
# endif
- if (theDebuggerBoolSetting(AutoDerefPointers)) {
+ if (debuggerCore()->boolSetting(AutoDerefPointers)) {
// Try automatic dereferentiation
data.exp = "(*(" + data.exp + "))";
data.type = data.type + "."; // FIXME: fragile HACK to avoid recursion
@@ -589,27 +590,12 @@ void GdbEngine::updateAllClassic()
updateLocals();
}
-void GdbEngine::setDebugDebuggingHelpersClassic(const QVariant &on)
-{
- PRECONDITION;
- if (on.toBool()) {
- showMessage(_("SWITCHING ON DUMPER DEBUGGING"));
- postCommand("set unwindonsignal off");
- breakByFunction(_("qDumpObjectData440"));
- //updateLocals();
- } else {
- showMessage(_("SWITCHING OFF DUMPER DEBUGGING"));
- postCommand("set unwindonsignal on");
- }
-}
-
void GdbEngine::setDebuggingHelperStateClassic(DebuggingHelperState s)
{
PRECONDITION;
m_debuggingHelperState = s;
}
-
void GdbEngine::handleStackListArgumentsClassic(const GdbResponse &response)
{
PRECONDITION;
@@ -661,13 +647,13 @@ void GdbEngine::handleStackListLocalsClassic(const GdbResponse &response)
// handleStop1, which passes on the frame as cookie. The whole stack
// is not known at this point.
QStringList uninitializedVariables;
- if (theDebuggerAction(UseCodeModel)->isChecked()) {
+ if (debuggerCore()->action(UseCodeModel)->isChecked()) {
const StackFrame frame =
qVariantCanConvert<Debugger::Internal::StackFrame>(response.cookie)
? qVariantValue<Debugger::Internal::StackFrame>(response.cookie)
: stackHandler()->currentFrame();
if (frame.isUsable())
- getUninitializedVariables(plugin()->cppCodeModelSnapshot(),
+ getUninitializedVariables(debuggerCore()->cppCodeModelSnapshot(),
frame.function, frame.file, frame.line,
&uninitializedVariables);
}
diff --git a/src/plugins/debugger/gdb/coregdbadapter.cpp b/src/plugins/debugger/gdb/coregdbadapter.cpp
index 1f014b2c82..69afdb148b 100644
--- a/src/plugins/debugger/gdb/coregdbadapter.cpp
+++ b/src/plugins/debugger/gdb/coregdbadapter.cpp
@@ -33,9 +33,11 @@
#include "coregdbadapter.h"
+#include "debuggercore.h"
#include "debuggeractions.h"
-#include "gdbengine.h"
#include "debuggerstringutils.h"
+#include "gdbmi.h"
+#include "gdbengine.h"
#include <utils/qtcassert.h>
@@ -77,7 +79,7 @@ void CoreGdbAdapter::startAdapter()
return;
//if (m_executable.isEmpty()) {
- // DebuggerEngine::showMessageBox(QMessageBox::Warning,
+ // showMessageBox(QMessageBox::Warning,
// tr("Error Loading Symbols"),
// tr("No executable to load symbols from specified."));
//}
@@ -104,7 +106,7 @@ void CoreGdbAdapter::startAdapter()
msg += _(" ");
msg += tr("Try to specify the binary using the "
"<i>Debug->Start Debugging->Attach to Core</i> dialog.");
- DebuggerEngine::showMessageBox(QMessageBox::Warning,
+ showMessageBox(QMessageBox::Warning,
tr("Loading core file failed"), msg);
m_engine->notifyEngineSetupFailed();
}
diff --git a/src/plugins/debugger/gdb/coregdbadapter.h b/src/plugins/debugger/gdb/coregdbadapter.h
index f7dceeb110..1a0fafd2bb 100644
--- a/src/plugins/debugger/gdb/coregdbadapter.h
+++ b/src/plugins/debugger/gdb/coregdbadapter.h
@@ -35,9 +35,7 @@
#define DEBUGGER_COREGDBADAPTER_H
#include "abstractgdbadapter.h"
-
-#include "abstractgdbprocess.h"
-
+#include "localgdbprocess.h"
namespace Debugger {
namespace Internal {
diff --git a/src/plugins/debugger/gdb/gdbchooserwidget.cpp b/src/plugins/debugger/gdb/gdbchooserwidget.cpp
index 5afe50c471..cee59bd118 100644
--- a/src/plugins/debugger/gdb/gdbchooserwidget.cpp
+++ b/src/plugins/debugger/gdb/gdbchooserwidget.cpp
@@ -52,7 +52,6 @@
#include <QtGui/QIcon>
#include <QtGui/QGroupBox>
#include <QtGui/QCheckBox>
-
#include <QtCore/QDebug>
#include <QtCore/QSet>
#include <QtCore/QDir>
@@ -71,29 +70,29 @@ static QList<int> allGdbToolChains()
QList<int> rc;
rc
#ifdef Q_OS_UNIX
- << ProjectExplorer::ToolChain::GCC
- << ProjectExplorer::ToolChain::LINUX_ICC
+ << ProjectExplorer::ToolChain_GCC
+ << ProjectExplorer::ToolChain_LINUX_ICC
#endif
#ifdef Q_OS_WIN
- << ProjectExplorer::ToolChain::MinGW
- << ProjectExplorer::ToolChain::WINSCW
- << ProjectExplorer::ToolChain::GCCE
- << ProjectExplorer::ToolChain::RVCT_ARMV5
- << ProjectExplorer::ToolChain::RVCT_ARMV6
+ << ProjectExplorer::ToolChain_MinGW
+ << ProjectExplorer::ToolChain_WINSCW
+ << ProjectExplorer::ToolChain_GCCE
+ << ProjectExplorer::ToolChain_RVCT2_ARMV5
+ << ProjectExplorer::ToolChain_RVCT2_ARMV6
#endif
- << ProjectExplorer::ToolChain::GCC_MAEMO
+ << ProjectExplorer::ToolChain_GCC_MAEMO
#ifdef Q_OS_UNIX
- << ProjectExplorer::ToolChain::GCCE_GNUPOC
- << ProjectExplorer::ToolChain::RVCT_ARMV5_GNUPOC
+ << ProjectExplorer::ToolChain_GCCE_GNUPOC
+ << ProjectExplorer::ToolChain_RVCT_ARMV5_GNUPOC
#endif
- << ProjectExplorer::ToolChain::OTHER
- << ProjectExplorer::ToolChain::UNKNOWN;
+ << ProjectExplorer::ToolChain_OTHER
+ << ProjectExplorer::ToolChain_UNKNOWN;
return rc;
}
static inline QString toolChainName(int tc)
{
- return ProjectExplorer::ToolChain::toolChainName(static_cast<ProjectExplorer::ToolChain::ToolChainType>(tc));
+ return ProjectExplorer::ToolChain::toolChainName(static_cast<ProjectExplorer::ToolChainType>(tc));
}
namespace Debugger {
@@ -278,9 +277,10 @@ void GdbBinaryModel::append(const QString &binary, const QList<int> &toolChains)
GdbChooserWidget::GdbChooserWidget(QWidget *parent) :
QWidget(parent),
m_treeView(new QTreeView),
- m_model(new GdbBinaryModel),
+ m_model(new GdbBinaryModel(m_treeView)),
m_addButton(new QToolButton),
- m_deleteButton(new QToolButton)
+ m_deleteButton(new QToolButton),
+ m_dirty(false)
{
QHBoxLayout *mainHLayout = new QHBoxLayout;
@@ -343,6 +343,7 @@ void GdbChooserWidget::slotAdd()
}
// Add binary + toolchain to model
m_model->append(path, binaryDialog.toolChains());
+ m_dirty = true;
}
void GdbChooserWidget::slotRemove()
@@ -354,6 +355,7 @@ void GdbChooserWidget::slotRemove()
void GdbChooserWidget::removeItem(QStandardItem *item)
{
m_model->removeRow(item->row());
+ m_dirty = true;
}
void GdbChooserWidget::slotCurrentChanged(const QModelIndex &current, const QModelIndex &)
@@ -374,7 +376,8 @@ void GdbChooserWidget::slotDoubleClicked(const QModelIndex &current)
BinaryToolChainDialog dialog(this);
dialog.setPath(oldBinary);
- dialog.setToolChainChoices(toolChainChoices.toList());
+ const BinaryToolChainMap map = gdbBinaries();
+ dialog.setToolChainChoices(toolChainChoices.toList(), &map);
dialog.setToolChains(oldToolChains);
if (dialog.exec() != QDialog::Accepted)
return;
@@ -386,6 +389,7 @@ void GdbChooserWidget::slotDoubleClicked(const QModelIndex &current)
GdbBinaryModel::setBinaryItem(m_model->item(row, binaryColumn), newBinary);
GdbBinaryModel::setToolChainItem(m_model->item(row, toolChainColumn), newToolChains);
+ m_dirty = true;
}
GdbChooserWidget::BinaryToolChainMap GdbChooserWidget::gdbBinaries() const
@@ -398,6 +402,17 @@ void GdbChooserWidget::setGdbBinaries(const BinaryToolChainMap &m)
m_model->setGdbBinaries(m);
for (int c = 0; c < ColumnCount; c++)
m_treeView->resizeColumnToContents(c);
+ m_dirty = false;
+}
+
+bool GdbChooserWidget::isDirty() const
+{
+ return m_dirty;
+}
+
+void GdbChooserWidget::clearDirty()
+{
+ m_dirty = false;
}
// -------------- ToolChainSelectorWidget
@@ -428,28 +443,28 @@ ToolChainSelectorWidget::ToolChainSelectorWidget(QWidget *parent) :
// Group checkboxes into categories
foreach(int tc, allGdbToolChains()) {
switch (tc) {
- case ProjectExplorer::ToolChain::GCC:
- case ProjectExplorer::ToolChain::LINUX_ICC:
- case ProjectExplorer::ToolChain::MinGW:
- case ProjectExplorer::ToolChain::OTHER:
- case ProjectExplorer::ToolChain::UNKNOWN:
+ case ProjectExplorer::ToolChain_GCC:
+ case ProjectExplorer::ToolChain_LINUX_ICC:
+ case ProjectExplorer::ToolChain_MinGW:
+ case ProjectExplorer::ToolChain_OTHER:
+ case ProjectExplorer::ToolChain_UNKNOWN:
desktopLayout->addWidget(createToolChainCheckBox(tc));
break;
- case ProjectExplorer::ToolChain::MSVC:
- case ProjectExplorer::ToolChain::WINCE:
+ case ProjectExplorer::ToolChain_MSVC:
+ case ProjectExplorer::ToolChain_WINCE:
break;
- case ProjectExplorer::ToolChain::WINSCW:
- case ProjectExplorer::ToolChain::GCCE:
- case ProjectExplorer::ToolChain::RVCT_ARMV5:
- case ProjectExplorer::ToolChain::RVCT_ARMV6:
- case ProjectExplorer::ToolChain::GCCE_GNUPOC:
- case ProjectExplorer::ToolChain::RVCT_ARMV5_GNUPOC:
+ case ProjectExplorer::ToolChain_WINSCW:
+ case ProjectExplorer::ToolChain_GCCE:
+ case ProjectExplorer::ToolChain_RVCT2_ARMV5:
+ case ProjectExplorer::ToolChain_RVCT2_ARMV6:
+ case ProjectExplorer::ToolChain_GCCE_GNUPOC:
+ case ProjectExplorer::ToolChain_RVCT_ARMV5_GNUPOC:
symbianLayout->addWidget(createToolChainCheckBox(tc));
break;
- case ProjectExplorer::ToolChain::GCC_MAEMO:
+ case ProjectExplorer::ToolChain_GCC_MAEMO:
maemoLayout->addWidget(createToolChainCheckBox(tc));
break;
- case ProjectExplorer::ToolChain::INVALID:
+ case ProjectExplorer::ToolChain_INVALID:
break;
}
}
@@ -466,11 +481,29 @@ QCheckBox *ToolChainSelectorWidget::createToolChainCheckBox(int tc)
return cb;
}
-void ToolChainSelectorWidget::setEnabledToolChains(const QList<int> &enabled)
+static inline QString msgDisabledToolChainToolTip(const QString &binary, int toolChain)
{
- foreach(QCheckBox *cb, m_checkBoxes)
- if (!enabled.contains(toolChainOfCheckBox(cb)))
+ return ToolChainSelectorWidget::tr(
+ "<html><head/><body><p>Another gdb binary (<i>%1</i>) is currently configured "
+ "to handle the toolchain <i>%2</i>.</p></body></html>").
+ arg(QFileInfo(binary).fileName(), toolChainName(toolChain));
+}
+
+void ToolChainSelectorWidget::setEnabledToolChains(const QList<int> &enabled,
+ const BinaryToolChainMap *binaryToolChainMap)
+{
+ foreach(QCheckBox *cb, m_checkBoxes) {
+ const int toolChain = toolChainOfCheckBox(cb);
+ if (enabled.contains(toolChain)) {
+ cb->setToolTip(QString());
+ } else {
+ // Toolchain is handled by a different binary, hint to user.
cb->setEnabled(false);
+ const QString binary = binaryToolChainMap ? binaryToolChainMap->key(toolChain) : QString();
+ if (!binary.isEmpty())
+ cb->setToolTip(msgDisabledToolChainToolTip(binary, toolChain));
+ }
+ }
}
void ToolChainSelectorWidget::setCheckedToolChains(const QList<int> &checked)
@@ -544,9 +577,10 @@ BinaryToolChainDialog::BinaryToolChainDialog(QWidget *parent) :
m_pathChooser->setFocus();
}
-void BinaryToolChainDialog::setToolChainChoices(const QList<int> &tcs)
+void BinaryToolChainDialog::setToolChainChoices(const QList<int> &tcs,
+ const BinaryToolChainMap *binaryToolChainMap)
{
- m_toolChainSelector->setEnabledToolChains(tcs);
+ m_toolChainSelector->setEnabledToolChains(tcs, binaryToolChainMap);
}
void BinaryToolChainDialog::setToolChains(const QList<int> &tcs)
diff --git a/src/plugins/debugger/gdb/gdbchooserwidget.h b/src/plugins/debugger/gdb/gdbchooserwidget.h
index 78f734f148..e355fa4711 100644
--- a/src/plugins/debugger/gdb/gdbchooserwidget.h
+++ b/src/plugins/debugger/gdb/gdbchooserwidget.h
@@ -72,6 +72,11 @@ public:
BinaryToolChainMap gdbBinaries() const;
void setGdbBinaries(const BinaryToolChainMap &m);
+ bool isDirty() const;
+
+public slots:
+ void clearDirty();
+
private slots:
void slotAdd();
void slotRemove();
@@ -87,6 +92,7 @@ private:
GdbBinaryModel *m_model;
QToolButton *m_addButton;
QToolButton *m_deleteButton;
+ bool m_dirty;
};
// Present toolchains with checkboxes grouped in QGroupBox panes
@@ -95,9 +101,13 @@ private:
class ToolChainSelectorWidget : public QWidget {
Q_OBJECT
public:
+ typedef GdbChooserWidget::BinaryToolChainMap BinaryToolChainMap;
+
explicit ToolChainSelectorWidget(QWidget *parent = 0);
- void setEnabledToolChains(const QList<int> &);
+ void setEnabledToolChains(const QList<int> &enabled,
+ // Optionally used for generating a tooltip for the disabled check boxes
+ const BinaryToolChainMap *binaryToolChainMap = 0);
void setCheckedToolChains(const QList<int> &);
QList<int> checkedToolChains() const;
@@ -123,9 +133,13 @@ private:
class BinaryToolChainDialog : public QDialog {
Q_OBJECT
public:
+ typedef GdbChooserWidget::BinaryToolChainMap BinaryToolChainMap;
+
explicit BinaryToolChainDialog(QWidget *parent);
- void setToolChainChoices(const QList<int> &);
+ void setToolChainChoices(const QList<int> &,
+ // Optionally used for generating a tooltip for the disabled check boxes
+ const BinaryToolChainMap *binaryToolChainMap = 0);
void setToolChains(const QList<int> &);
QList<int> toolChains() const;
diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
index 9e2950069d..08b4416008 100644
--- a/src/plugins/debugger/gdb/gdbengine.cpp
+++ b/src/plugins/debugger/gdb/gdbengine.cpp
@@ -35,12 +35,6 @@
#include "gdbengine.h"
-#include "gdboptionspage.h"
-#include "debuggeruiswitcher.h"
-#include "debuggermainwindow.h"
-#include "debuggerplugin.h"
-#include "debuggerrunner.h"
-
#include "attachgdbadapter.h"
#include "coregdbadapter.h"
#include "localplaingdbadapter.h"
@@ -50,13 +44,18 @@
#include "trkgdbadapter.h"
#include "tcftrkgdbadapter.h"
-#include "watchutils.h"
#include "debuggeractions.h"
-#include "debuggeragents.h"
#include "debuggerconstants.h"
-#include "debuggertooltip.h"
+#include "debuggercore.h"
+#include "debuggerplugin.h"
+#include "debuggerrunner.h"
#include "debuggerstringutils.h"
+#include "debuggertooltip.h"
+#include "disassembleragent.h"
#include "gdbmi.h"
+#include "gdboptionspage.h"
+#include "memoryagent.h"
+#include "watchutils.h"
#include "breakhandler.h"
#include "moduleshandler.h"
@@ -67,16 +66,12 @@
#include "threadshandler.h"
#include "watchhandler.h"
-#include "sourcefileswindow.h"
-
-#include "debuggerdialogs.h"
#include "logwindow.h"
-#include <utils/qtcassert.h>
-#include <utils/fancymainwindow.h>
-#include <texteditor/itexteditor.h>
-#include <projectexplorer/toolchain.h>
#include <coreplugin/icore.h>
+#include <projectexplorer/toolchain.h>
+#include <texteditor/itexteditor.h>
+#include <utils/qtcassert.h>
#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
@@ -185,20 +180,34 @@ GdbEngine::GdbEngine(const DebuggerStartParameters &startParameters)
setObjectName(QLatin1String("GdbEngine"));
qRegisterMetaType<WatchData>("WatchData");
- m_commandTimer = new QTimer(this);
- m_commandTimer->setSingleShot(true);
- connect(m_commandTimer, SIGNAL(timeout()), SLOT(commandTimeout()));
-
- // Needs no resetting in initializeVariables()
m_busy = false;
- initializeVariables();
+ m_gdbAdapter = 0;
+ m_debuggingHelperState = DebuggingHelperUninitialized;
+ m_gdbVersion = 100;
+ m_gdbBuildVersion = -1;
+ m_isMacGdb = false;
+ m_hasPython = false;
+ m_registerNamesListed = false;
+ m_hasInferiorThreadList = false;
+ m_sourcesListUpdating = false;
+ m_oldestAcceptableToken = -1;
+ m_outputCodec = QTextCodec::codecForLocale();
+ m_pendingWatchRequests = 0;
+ m_pendingBreakpointRequests = 0;
+ m_commandsDoneCallback = 0;
+ m_stackNeeded = false;
+ invalidateSourcesList();
+
m_gdbAdapter = createAdapter();
- connect(theDebuggerAction(AutoDerefPointers), SIGNAL(valueChanged(QVariant)),
+ m_commandTimer.setSingleShot(true);
+ connect(&m_commandTimer, SIGNAL(timeout()), SLOT(commandTimeout()));
+
+ connect(debuggerCore()->action(AutoDerefPointers), SIGNAL(valueChanged(QVariant)),
SLOT(reloadLocals()));
- connect(theDebuggerAction(SortStructMembers), SIGNAL(valueChanged(QVariant)),
+ connect(debuggerCore()->action(SortStructMembers), SIGNAL(valueChanged(QVariant)),
SLOT(reloadLocals()));
- connect(theDebuggerAction(CreateFullBacktrace), SIGNAL(triggered()),
+ connect(debuggerCore()->action(CreateFullBacktrace), SIGNAL(triggered()),
SLOT(createFullBacktrace()));
}
@@ -207,11 +216,6 @@ DebuggerStartMode GdbEngine::startMode() const
return startParameters().startMode;
}
-QMainWindow *GdbEngine::mainWindow() const
-{
- return DebuggerUISwitcher::instance()->mainWindow();
-}
-
AbstractGdbProcess *GdbEngine::gdbProc() const
{
return m_gdbAdapter->gdbProc();
@@ -226,49 +230,6 @@ GdbEngine::~GdbEngine()
m_gdbAdapter = 0;
}
-void GdbEngine::initializeVariables()
-{
- m_debuggingHelperState = DebuggingHelperUninitialized;
- m_gdbVersion = 100;
- m_gdbBuildVersion = -1;
- m_isMacGdb = false;
- m_hasPython = false;
- m_registerNamesListed = false;
- m_hasInferiorThreadList = false;
-
- m_fullToShortName.clear();
- m_shortToFullName.clear();
-
- invalidateSourcesList();
- m_sourcesListUpdating = false;
- m_oldestAcceptableToken = -1;
- m_outputCodec = QTextCodec::codecForLocale();
- m_pendingWatchRequests = 0;
- m_pendingBreakpointRequests = 0;
- m_commandsDoneCallback = 0;
- m_commandsToRunOnTemporaryBreak.clear();
- m_cookieForToken.clear();
-
- m_pendingConsoleStreamOutput.clear();
- m_pendingLogStreamOutput.clear();
-
- m_inbuffer.clear();
- m_resultVarName.clear();
-
- m_commandTimer->stop();
-
- // ConverterState has no reset() function.
- m_outputCodecState.~ConverterState();
- new (&m_outputCodecState) QTextCodec::ConverterState();
-
- m_currentFunctionArgs.clear();
- m_currentFrame.clear();
- m_dumperHelper.clear();
-#ifdef Q_OS_LINUX
- m_entryPoint.clear();
-#endif
-}
-
QString GdbEngine::errorMessage(QProcess::ProcessError error)
{
switch (error) {
@@ -464,9 +425,8 @@ void GdbEngine::handleResponse(const QByteArray &buff)
// line="1584",shlib="/../libFoo_debug.dylib",times="0"}
const GdbMi bkpt = result.findChild("bkpt");
const int number = bkpt.findChild("number").data().toInt();
- BreakpointData *data = breakHandler()->findBreakpointByNumber(number);
- setBreakpointDataFromOutput(data, bkpt);
- breakHandler()->updateMarkers();
+ BreakpointId id = breakHandler()->findBreakpointByNumber(number);
+ updateBreakpointDataFromOutput(id, bkpt);
} else {
qDebug() << "IGNORED ASYNC OUTPUT"
<< asyncClass << result.toString();
@@ -521,7 +481,7 @@ void GdbEngine::handleResponse(const QByteArray &buff)
// On Windows, the contents seem to depend on the debugger
// version and/or OS version used.
if (data.startsWith("warning:"))
- showMessage(_(data.mid(9)), AppStuff); // cut "warning: "
+ showMessage(_(data.mid(9)), AppStuff); // Cut "warning: "
break;
}
@@ -538,14 +498,6 @@ void GdbEngine::handleResponse(const QByteArray &buff)
if (resultClass == "done") {
response.resultClass = GdbResultDone;
} else if (resultClass == "running") {
- // FIXME: Handle this in the individual result handlers.
- //if (state() == InferiorStopOk) { // Result of manual command.
- // resetLocation();
- // setTokenBarrier();
- // setState(InferiorRunRequested);
- //}
- //setState(InferiorRunOk);
- //showStatusMessage(tr("Running..."));
response.resultClass = GdbResultRunning;
} else if (resultClass == "connected") {
response.resultClass = GdbResultConnected;
@@ -565,7 +517,7 @@ void GdbEngine::handleResponse(const QByteArray &buff)
response.data.m_type = GdbMi::Tuple;
response.data.m_name = "data";
} else {
- // Archer has this
+ // Archer has this.
response.data.m_type = GdbMi::Tuple;
response.data.m_name = "data";
}
@@ -603,15 +555,14 @@ void GdbEngine::readGdbStandardError()
void GdbEngine::readGdbStandardOutput()
{
- if (m_commandTimer->isActive())
- m_commandTimer->start(); // Retrigger
+ m_commandTimer.start(); // Restart timer.
int newstart = 0;
int scan = m_inbuffer.size();
m_inbuffer.append(gdbProc()->readAllStandardOutput());
- // This can trigger when a dialog starts a nested event loop
+ // This can trigger when a dialog starts a nested event loop.
if (m_busy)
return;
@@ -756,16 +707,6 @@ void GdbEngine::postCommandHelper(const GdbCommand &cmd)
showMessage(_("CHILD ALREADY BEING INTERRUPTED. STILL HOPING."));
// Calling shutdown() here breaks all situations where two
// NeedsStop commands are issued in quick succession.
- //} else if (state() == InferiorStopRequested_Kill) {
- // showMessage(_("CHILD ALREADY BEING INTERRUPTED (KILL PENDING)"));
- // // FIXME
- // shutdown();
- //} else if (state() == InferiorRunRequested) {
- // if (cmd.flags & LosesChild)
- // setState(InferiorRunRequested_Kill);
- // showMessage(_("RUNNING REQUESTED; POSTPONING INTERRUPT"));
- //} else if (state() == InferiorRunRequested_Kill) {
- // showMessage(_("RUNNING REQUESTED; POSTPONING INTERRUPT (KILL PENDING)"));
} else if (state() == InferiorRunOk) {
showStatusMessage(tr("Stopping temporarily"), 1000);
interruptInferiorTemporarily();
@@ -812,22 +753,22 @@ void GdbEngine::flushCommand(const GdbCommand &cmd0)
m_gdbAdapter->write(cmd.command + "\r\n");
// Start Watchdog.
- if (m_commandTimer->interval() <= 20000)
- m_commandTimer->setInterval(commandTimeoutTime());
+ if (m_commandTimer.interval() <= 20000)
+ m_commandTimer.setInterval(commandTimeoutTime());
// The process can die for external reason between the "-gdb-exit" was
// sent and a response could be retrieved. We don't want the watchdog
// to bark in that case since the only possible outcome is a dead
// process anyway.
if (!cmd.command.endsWith("-gdb-exit"))
- m_commandTimer->start();
+ m_commandTimer.start();
//if (cmd.flags & LosesChild)
- // setState(InferiorShutdownRequested);
+ // notifyInferiorIll();
}
int GdbEngine::commandTimeoutTime() const
{
- int time = theDebuggerAction(GdbWatchdogTimeout)->value().toInt();
+ int time = debuggerCore()->action(GdbWatchdogTimeout)->value().toInt();
return 1000 * qMax(20, time);
}
@@ -847,8 +788,8 @@ void GdbEngine::commandTimeout()
}
if (killIt) {
showMessage(_("TIMED OUT WAITING FOR GDB REPLY. COMMANDS STILL IN PROGRESS:"));
- int timeOut = m_commandTimer->interval();
- //m_commandTimer->stop();
+ int timeOut = m_commandTimer.interval();
+ //m_commandTimer.stop();
const QString msg = tr("The gdb process has not responded "
"to a command within %1 seconds. This could mean it is stuck "
"in an endless loop or taking longer than expected to perform "
@@ -918,13 +859,29 @@ void GdbEngine::handleResultRecord(GdbResponse *response)
// and library load messages.
showMessage(_("APPLYING WORKAROUND #4"));
notifyInferiorStopOk();
- //setState(InferiorShutdownRequested);
- //setState(InferiorShutdownOk);
+ //notifyInferiorIll();
//showStatusMessage(tr("Executable failed: %1")
// .arg(QString::fromLocal8Bit(msg)));
//shutdown();
//showMessageBox(QMessageBox::Critical,
// tr("Executable failed"), QString::fromLocal8Bit(msg));
+ } else if (msg.contains("Cannot insert breakpoint")) {
+ // For breakpoints set by address to non-existent addresses we
+ // might get something like "6^error,msg="Warning:\nCannot insert
+ // breakpoint 3.\nError accessing memory address 0x34592327:
+ // Input/output error.\nCannot insert breakpoint 4.\nError
+ // accessing memory address 0x34592335: Input/output error.\n".
+ // This should not stop us from proceeding.
+ // Most notably, that happens after a "6^running" and "*running"
+ // We are probably sitting at _start and can't proceed as
+ // long as the breakpoints are enabled.
+ // FIXME: Should we silently disable the offending breakpoints?
+ showMessage(_("APPLYING WORKAROUND #5"));
+ showMessageBox(QMessageBox::Critical,
+ tr("Setting breakpoints failed"), QString::fromLocal8Bit(msg));
+ QTC_ASSERT(state() == InferiorRunOk, /**/);
+ notifyInferiorSpontaneousStop();
+ notifyEngineIll();
} else {
showMessageBox(QMessageBox::Critical,
tr("Executable failed"), QString::fromLocal8Bit(msg));
@@ -936,7 +893,7 @@ void GdbEngine::handleResultRecord(GdbResponse *response)
}
GdbCommand cmd = m_cookieForToken.take(token);
- if (theDebuggerBoolSetting(LogTimeStamps)) {
+ if (debuggerCore()->boolSetting(LogTimeStamps)) {
showMessage(_("Response time: %1: %2 s")
.arg(_(cmd.command))
.arg(cmd.postTime.msecsTo(QTime::currentTime()) / 1000.),
@@ -1031,7 +988,7 @@ void GdbEngine::handleResultRecord(GdbResponse *response)
}
if (m_cookieForToken.isEmpty())
- m_commandTimer->stop();
+ m_commandTimer.stop();
}
void GdbEngine::executeDebuggerCommand(const QString &command)
@@ -1106,31 +1063,13 @@ void GdbEngine::handleExecuteRunToLine(const GdbResponse &response)
//>~"testArray () at ../simple/app.cpp:241\n"
//>~"241\t s[1] = \"b\";\n"
//>122^done
- gotoLocation(m_targetFrame, true);
+ gotoLocation(m_targetFrame);
showStatusMessage(tr("Target line hit. Stopped"));
notifyInferiorSpontaneousStop();
handleStop1(response);
}
}
-/*
-void GdbEngine::handleExecuteRunToFunction(const GdbResponse &response)
-{
- // FIXME: remove this special case as soon as there's a real
- // reason given when the temporary breakpoint is hit.
- // reight now we get:
- // 14*stopped,thread-id="1",frame={addr="0x0000000000403ce4",
- // func="foo",args=[{name="str",value="@0x7fff0f450460"}],
- // file="main.cpp",fullname="/tmp/g/main.cpp",line="37"}
- QTC_ASSERT(state() == InferiorStopRequested, qDebug() << state())
- setState(InferiorStopOk);
- showStatusMessage(tr("Function reached. Stopped"));
- GdbMi frame = response.data.findChild("frame");
- StackFrame f = parseStackFrame(frame, 0);
- gotoLocation(f, true);
-}
-*/
-
static bool isExitedReason(const QByteArray &reason)
{
return reason == "exited-normally" // inferior exited normally
@@ -1143,7 +1082,7 @@ static bool isExitedReason(const QByteArray &reason)
void GdbEngine::handleAqcuiredInferior()
{
// Reverse debugging. FIXME: Should only be used when available.
- //if (theDebuggerBoolSetting(EnableReverseDebugging))
+ //if (debuggerCore()->boolSetting(EnableReverseDebugging))
// postCommand("target response");
tryLoadDebuggingHelpers();
@@ -1151,16 +1090,16 @@ void GdbEngine::handleAqcuiredInferior()
# ifndef Q_OS_MAC
// intentionally after tryLoadDebuggingHelpers(),
// otherwise we'd interrupt solib loading.
- if (theDebuggerBoolSetting(AllPluginBreakpoints)) {
+ if (debuggerCore()->boolSetting(AllPluginBreakpoints)) {
postCommand("set auto-solib-add on");
postCommand("set stop-on-solib-events 0");
postCommand("sharedlibrary .*");
- } else if (theDebuggerBoolSetting(SelectedPluginBreakpoints)) {
+ } else if (debuggerCore()->boolSetting(SelectedPluginBreakpoints)) {
postCommand("set auto-solib-add on");
postCommand("set stop-on-solib-events 1");
postCommand("sharedlibrary "
+ theDebuggerStringSetting(SelectedPluginBreakpointsPattern));
- } else if (theDebuggerBoolSetting(NoPluginBreakpoints)) {
+ } else if (debuggerCore()->boolSetting(NoPluginBreakpoints)) {
// should be like that already
postCommand("set auto-solib-add off");
postCommand("set stop-on-solib-events 0");
@@ -1214,6 +1153,33 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
return;
}
+ const int bkptno = data.findChild("bkptno").data().toInt();
+ const GdbMi frame = data.findChild("frame");
+
+ const int lineNumber = frame.findChild("line").data().toInt();
+ QString fullName = QString::fromUtf8(frame.findChild("fullname").data());
+ if (fullName.isEmpty())
+ fullName = QString::fromUtf8(frame.findChild("file").data());
+
+ if (bkptno && frame.isValid()) {
+ // Use opportunity to update the breakpoint marker position.
+ BreakHandler *handler = breakHandler();
+ BreakpointId id = handler->findBreakpointByNumber(bkptno);
+ const BreakpointResponse &response = handler->response(id);
+ QString fileName = response.fileName;
+ if (fileName.isEmpty())
+ fileName = handler->fileName(id);
+ if (fileName.isEmpty())
+ fileName = fullName;
+ if (!fileName.isEmpty())
+ handler->setMarkerFileAndLine(id, fileName, lineNumber);
+ }
+
+ // Quickly set the location marker.
+ if (lineNumber && !debuggerCore()->boolSetting(OperateByInstruction)
+ && QFileInfo(fullName).exists())
+ gotoLocation(Location(fullName, lineNumber));
+
if (!m_commandsToRunOnTemporaryBreak.isEmpty()) {
QTC_ASSERT(state() == InferiorStopRequested, qDebug() << state())
notifyInferiorStopOk();
@@ -1245,6 +1211,36 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
notifyInferiorStopOk();
}
+ // FIXME: Replace the #ifdef by the "target" architecture.
+#ifdef Q_OS_LINUX
+ if (!m_entryPoint.isEmpty()) {
+ // This is needed as long as we support stock gdb 6.8.
+ if (frame.findChild("addr").data() == m_entryPoint) {
+ // There are two expected reasons for getting here:
+ // 1) For some reason, attaching to a stopped process causes *two*
+ // SIGSTOPs
+ // when trying to continue (kernel i386 2.6.24-23-ubuntu, gdb 6.8).
+ // Interestingly enough, on MacOSX no signal is delivered at all.
+ // 2) The explicit tbreak at the entry point we set to query the PID.
+ // Gdb <= 6.8 reports a frame but no reason, 6.8.50+ reports
+ // everything.
+ // The case of the user really setting a breakpoint at _start is simply
+ // unsupported.
+ if (!inferiorPid()) // For programs without -pthread under gdb <= 6.8.
+ postCommand("info proc", CB(handleInfoProc));
+ continueInferiorInternal();
+ return;
+ }
+ // We are past the initial stop(s). No need to waste time on further checks.
+ m_entryPoint.clear();
+ }
+#endif
+
+ handleStop0(data);
+}
+
+void GdbEngine::handleStop0(const GdbMi &data)
+{
#if 0 // See http://vladimir_prus.blogspot.com/2007/12/debugger-stories-pending-breakpoints.html
// Due to LD_PRELOADing the dumpers, these events can occur even before
// reaching the entry point. So handle it before the entry point hacks below.
@@ -1259,7 +1255,7 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
postCommand("set stop-on-solib-events 0");
#if 0
// The related code (handleAqcuiredInferior()) is disabled as well.
- if (theDebuggerBoolSetting(SelectedPluginBreakpoints)) {
+ if (debuggerCore()->boolSetting(SelectedPluginBreakpoints)) {
QString dataStr = _(data.toString());
showMessage(_("SHARED LIBRARY EVENT: ") + dataStr);
QString pat = theDebuggerStringSetting(SelectedPluginBreakpointsPattern);
@@ -1274,28 +1270,8 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
}
#endif
- // FIXME: Replace the #ifdef by the "target" architecture
-#ifdef Q_OS_LINUX
- if (!m_entryPoint.isEmpty()) {
- GdbMi frameData = data.findChild("frame");
- if (frameData.findChild("addr").data() == m_entryPoint) {
- // There are two expected reasons for getting here:
- // 1) For some reason, attaching to a stopped process causes *two* SIGSTOPs
- // when trying to continue (kernel i386 2.6.24-23-ubuntu, gdb 6.8).
- // Interestingly enough, on MacOSX no signal is delivered at all.
- // 2) The explicit tbreak at the entry point we set to query the PID.
- // Gdb <= 6.8 reports a frame but no reason, 6.8.50+ reports everything.
- // The case of the user really setting a breakpoint at _start is simply
- // unsupported.
- if (!inferiorPid()) // For programs without -pthread under gdb <= 6.8.
- postCommand("info proc", CB(handleInfoProc));
- continueInferiorInternal();
- return;
- }
- // We are past the initial stop(s). No need to waste time on further checks.
- m_entryPoint.clear();
- }
-#endif
+ const GdbMi frame = data.findChild("frame");
+ const QByteArray reason = data.findChild("reason").data();
// This was seen on XP after removing a breakpoint while running
// >945*stopped,reason="signal-received",signal-name="SIGTRAP",
@@ -1316,22 +1292,21 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
// Jump over well-known frames.
static int stepCounter = 0;
- if (theDebuggerBoolSetting(SkipKnownFrames)) {
+ if (debuggerCore()->boolSetting(SkipKnownFrames)) {
if (reason == "end-stepping-range" || reason == "function-finished") {
- GdbMi frame = data.findChild("frame");
//showMessage(frame.toString());
QString funcName = _(frame.findChild("func").data());
QString fileName = QString::fromLocal8Bit(frame.findChild("file").data());
if (isLeavableFunction(funcName, fileName)) {
//showMessage(_("LEAVING ") + funcName);
++stepCounter;
- executeStepOutX();
+ executeStepOut();
return;
}
if (isSkippableFunction(funcName, fileName)) {
//showMessage(_("SKIPPING ") + funcName);
++stepCounter;
- executeStepX();
+ executeStep();
return;
}
//if (stepCounter)
@@ -1423,85 +1398,72 @@ void GdbEngine::handleStop1(const GdbMi &data)
// {name="p",value="0x0"}],file="x.h",fullname="/home/.../x.h",line="95"},
// thread-id="1",stopped-threads="all",core="2"
GdbMi wpt = data.findChild("wpt");
- QByteArray bpNumber = wpt.findChild("number").data();
- QByteArray bpAddress = wpt.findChild("exp").data();
- //QByteArray threadId = data.findChild("thread-id").data();
- showStatusMessage(tr("Watchpoint %1 at %2 triggered:")
- .arg(_(bpNumber), _(bpAddress)));
+ const int bpNumber = wpt.findChild("number").data().toInt();
+ const BreakpointId id = breakHandler()->findBreakpointByNumber(bpNumber);
+ const quint64 bpAddress = wpt.findChild("exp").data().mid(1).toULongLong(0, 0);
+ showStatusMessage(msgWatchpointTriggered(id, bpNumber, bpAddress));
} else if (reason == "breakpoint-hit") {
- QByteArray bpNumber = data.findChild("bkptno").data();
- QByteArray threadId = data.findChild("thread-id").data();
- showStatusMessage(tr("Stopped at breakpoint %1 in thread %2")
- .arg(_(bpNumber), _(threadId)));
+ GdbMi gNumber = data.findChild("bkptno"); // 'number' or 'bkptno'?
+ if (!gNumber.isValid())
+ gNumber = data.findChild("number");
+ const int bpNumber = gNumber.data().toInt();
+ const QByteArray threadId = data.findChild("thread-id").data();
+ const BreakpointId id = breakHandler()->findBreakpointByNumber(bpNumber);
+ showStatusMessage(msgBreakpointTriggered(id, bpNumber, _(threadId)));
} else {
- QString reasontr = tr("Stopped: \"%1\"").arg(_(reason));
+ QString reasontr = msgStopped(_(reason));
if (reason == "signal-received"
- && theDebuggerBoolSetting(UseMessageBoxForSignals)) {
+ && debuggerCore()->boolSetting(UseMessageBoxForSignals)) {
QByteArray name = data.findChild("signal-name").data();
QByteArray meaning = data.findChild("signal-meaning").data();
// Ignore these as they are showing up regularly when
// stopping debugging.
- if (name != STOP_SIGNAL
- && (startParameters().startMode != AttachToRemote
- || name != CROSS_STOP_SIGNAL)) {
- QString msg = tr("<p>The inferior stopped because it received a "
- "signal from the Operating System.<p>"
- "<table><tr><td>Signal name : </td><td>%1</td></tr>"
- "<tr><td>Signal meaning : </td><td>%2</td></tr></table>")
- .arg(name.isEmpty() ? tr(" <Unknown> ", "name") : _(name))
- .arg(meaning.isEmpty() ? tr(" <Unknown> ", "meaning") : _(meaning));
- showMessageBox(QMessageBox::Information,
- tr("Signal received"), msg);
+ if (name == STOP_SIGNAL) {
+ showMessage(_(STOP_SIGNAL " CONSIDERED HARMLESS. CONTINUING."));
+ } else if (startParameters().startMode == AttachToRemote
+ && name == CROSS_STOP_SIGNAL) {
+ showMessage(_(CROSS_STOP_SIGNAL " CONSIDERED HARMLESS. CONTINUING."));
+ } else {
+ showMessage(_("HANDLING SIGNAL" + name));
+ showStoppedBySignalMessageBox(_(meaning), _(name));
if (!name.isEmpty() && !meaning.isEmpty())
- reasontr = tr("Stopped: %1 by signal %2")
- .arg(_(meaning)).arg(_(name));
+ reasontr = msgStoppedBySignal(_(meaning), _(name));
}
}
if (reason.isEmpty())
- showStatusMessage(tr("Stopped."));
+ showStatusMessage(msgStopped());
else
showStatusMessage(reasontr);
}
- const GdbMi gdbmiFrame = data.findChild("frame");
-
- m_currentFrame = _(gdbmiFrame.findChild("addr").data() + '%' +
- gdbmiFrame.findChild("func").data() + '%');
-
- // Quick shot: Jump to stack frame #0.
- StackFrame frame;
- if (gdbmiFrame.isValid()) {
- frame = parseStackFrame(gdbmiFrame, 0);
- gotoLocation(frame, true);
- }
+ // Let the event loop run before deciding whether to update the stack.
+ m_stackNeeded = true; // setTokenBarrier() might reset this.
+ m_currentThreadId = data.findChild("thread-id").data().toInt();
+ QTimer::singleShot(0, this, SLOT(handleStop2()));
+}
- //
- // Stack
- //
- stackHandler()->setCurrentIndex(0);
- updateLocals(qVariantFromValue(frame)); // Quick shot
+void GdbEngine::handleStop2()
+{
+ // We are already continuing.
+ if (!m_stackNeeded)
+ return;
- reloadStack(false);
+ reloadStack(false); // Will trigger register reload.
if (supportsThreads()) {
- int currentId = data.findChild("thread-id").data().toInt();
if (m_gdbAdapter->isTrkAdapter()) {
m_gdbAdapter->trkReloadThreads();
} else if (m_isMacGdb) {
postCommand("-thread-list-ids", Discardable,
- CB(handleThreadListIds), currentId);
+ CB(handleThreadListIds), m_currentThreadId);
} else {
// This is only available in gdb 7.1+.
postCommand("-thread-info", Discardable,
- CB(handleThreadInfo), currentId);
+ CB(handleThreadInfo), m_currentThreadId);
}
}
- //
- // Registers
- //
- reloadRegisters();
}
void GdbEngine::handleInfoProc(const GdbResponse &response)
@@ -1563,8 +1525,13 @@ void GdbEngine::pythonDumpersFailed()
if (m_gdbAdapter->dumperHandling()
== AbstractGdbAdapter::DumperLoadedByGdbPreload
&& checkDebuggingHelpersClassic()) {
+#ifdef Q_OS_MAC
+ const char * const LD_PRELOAD_ENV_VAR = "DYLD_INSERT_LIBRARIES";
+#else
+ const char * const LD_PRELOAD_ENV_VAR = "LD_PRELOAD";
+#endif
QByteArray cmd = "set environment ";
- cmd += Debugger::Constants::Internal::LD_PRELOAD_ENV_VAR;
+ cmd += LD_PRELOAD_ENV_VAR;
cmd += ' ';
cmd += startParameters().startMode == StartRemoteGdb
? startParameters().remoteDumperLib
@@ -1622,7 +1589,7 @@ QString GdbEngine::cleanupFullName(const QString &fileName)
#ifdef Q_OS_WIN
QTC_ASSERT(!fileName.isEmpty(), return QString())
// Gdb on windows often delivers "fullnames" which
- // a) have no drive letter and b) are not normalized.
+ // (a) have no drive letter and (b) are not normalized.
QFileInfo fi(fileName);
if (fi.isReadable())
cleanFilePath = QDir::cleanPath(fi.absoluteFilePath());
@@ -1690,7 +1657,8 @@ void GdbEngine::notifyAdapterShutdownOk()
case QProcess::Running:
postCommand("-gdb-exit", GdbEngine::ExitRequest, CB(handleGdbExit));
break;
- case QProcess::NotRunning: // Cannot find executable
+ case QProcess::NotRunning:
+ // Cannot find executable.
notifyEngineShutdownOk();
break;
case QProcess::Starting:
@@ -1735,31 +1703,25 @@ int GdbEngine::currentFrame() const
return stackHandler()->currentIndex();
}
-static inline QString msgNoBinaryForToolChain(int tc)
+QString msgNoBinaryForToolChain(int tc)
{
- const ProjectExplorer::ToolChain::ToolChainType toolChain = static_cast<ProjectExplorer::ToolChain::ToolChainType>(tc);
- const QString toolChainName = ProjectExplorer::ToolChain::toolChainName(toolChain);
- return GdbEngine::tr("There is no gdb binary available for '%1'").arg(toolChainName);
-}
-
-static QString gdbBinaryForToolChain(int toolChain)
-{
- return DebuggerSettings::instance()->gdbBinaryToolChainMap().key(toolChain);
+ using namespace ProjectExplorer;
+ return GdbEngine::tr("There is no gdb binary available for '%1'")
+ .arg(ToolChain::toolChainName(ToolChainType(tc)));
}
AbstractGdbAdapter *GdbEngine::createAdapter()
{
const DebuggerStartParameters &sp = startParameters();
- //qDebug() << "CREATE ADAPTER: " << sp.toolChainType;
switch (sp.toolChainType) {
- case ProjectExplorer::ToolChain::WINSCW: // S60
- case ProjectExplorer::ToolChain::GCCE:
- case ProjectExplorer::ToolChain::RVCT_ARMV5:
- case ProjectExplorer::ToolChain::RVCT_ARMV6:
- case ProjectExplorer::ToolChain::RVCT_ARMV5_GNUPOC:
- case ProjectExplorer::ToolChain::GCCE_GNUPOC:
- // fixme: 1 of 3 testing hacks
- if (sp.processArgs.size() >= 5 && sp.processArgs.at(0) == _("@tcf@"))
+ case ProjectExplorer::ToolChain_WINSCW: // S60
+ case ProjectExplorer::ToolChain_GCCE:
+ case ProjectExplorer::ToolChain_RVCT2_ARMV5:
+ case ProjectExplorer::ToolChain_RVCT2_ARMV6:
+ case ProjectExplorer::ToolChain_RVCT_ARMV5_GNUPOC:
+ case ProjectExplorer::ToolChain_GCCE_GNUPOC:
+ // FIXME: 1 of 3 testing hacks.
+ if (sp.processArgs.startsWith(__("@tcf@ ")))
return new TcfTrkGdbAdapter(this);
return new TrkGdbAdapter(this);
default:
@@ -1784,17 +1746,13 @@ AbstractGdbAdapter *GdbEngine::createAdapter()
void GdbEngine::setupEngine()
{
- //qDebug() << "GDB START DEBUGGER";
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
QTC_ASSERT(m_debuggingHelperState == DebuggingHelperUninitialized, /**/);
- //qDebug() << "CREATED ADAPTER: " << m_gdbAdapter;
-
if (m_gdbAdapter->dumperHandling() != AbstractGdbAdapter::DumperNotAvailable) {
- connect(theDebuggerAction(UseDebuggingHelpers), SIGNAL(valueChanged(QVariant)),
- this, SLOT(setUseDebuggingHelpers(QVariant)));
- connect(theDebuggerAction(DebugDebuggingHelpers), SIGNAL(valueChanged(QVariant)),
- this, SLOT(setDebugDebuggingHelpersClassic(QVariant)));
+ connect(debuggerCore()->action(UseDebuggingHelpers),
+ SIGNAL(valueChanged(QVariant)),
+ SLOT(setUseDebuggingHelpers(QVariant)));
}
QTC_ASSERT(state() == EngineSetupRequested, /**/);
@@ -1804,14 +1762,19 @@ void GdbEngine::setupEngine()
unsigned GdbEngine::debuggerCapabilities() const
{
unsigned caps = ReverseSteppingCapability
- | AutoDerefPointersCapability | DisassemblerCapability
- | RegisterCapability | ShowMemoryCapability
- | JumpToLineCapability | ReloadModuleCapability
- | ReloadModuleSymbolsCapability | BreakOnThrowAndCatchCapability
+ | AutoDerefPointersCapability
+ | DisassemblerCapability
+ | RegisterCapability
+ | ShowMemoryCapability
+ | JumpToLineCapability
+ | ReloadModuleCapability
+ | ReloadModuleSymbolsCapability
+ | BreakOnThrowAndCatchCapability
| ReturnFromFunctionCapability
| CreateFullBacktraceCapability
| WatchpointCapability
- | AddWatcherCapability;
+ | AddWatcherCapability
+ | ShowModuleSymbolsCapability;
if (startParameters().startMode == AttachCore)
return caps;
@@ -1830,6 +1793,7 @@ void GdbEngine::continueInferiorInternal()
void GdbEngine::autoContinueInferior()
{
+ resetLocation();
continueInferiorInternal();
showStatusMessage(tr("Continuing after temporary stop..."), 1000);
}
@@ -1837,7 +1801,6 @@ void GdbEngine::autoContinueInferior()
void GdbEngine::continueInferior()
{
QTC_ASSERT(state() == InferiorStopOk, qDebug() << state());
- resetLocation();
setTokenBarrier();
continueInferiorInternal();
}
@@ -1988,7 +1951,6 @@ void GdbEngine::executeRunToFunction(const QString &functionName)
postCommand("-break-insert -t " + functionName.toLatin1());
showStatusMessage(tr("Run to function %1 requested...").arg(functionName), 5000);
continueInferiorInternal();
- //postCommand("-exec-continue", handleExecuteRunToFunction);
}
void GdbEngine::executeJumpToLine(const QString &fileName, int lineNumber)
@@ -2009,11 +1971,11 @@ void GdbEngine::executeJumpToLine(const QString &fileName, int lineNumber)
// ~"run1 (argc=1, argv=0x7fffbf1f5538) at test1.cpp:242"
// ~"242\t x *= 2;"
// 23^done"
- gotoLocation(frame, true);
+ gotoLocation(frame);
//setBreakpoint();
//postCommand("jump " + loc);
#else
- gotoLocation(frame, true);
+ gotoLocation(frame);
setBreakpoint(fileName, lineNumber);
notifyInferiorRunRequested();
postCommand("jump " + loc, RunRequest);
@@ -2061,9 +2023,10 @@ void GdbEngine::setTokenBarrier()
}
PENDING_DEBUG("\n--- token barrier ---\n");
showMessage(_("--- token barrier ---"), LogMiscInput);
- if (theDebuggerBoolSetting(LogTimeStamps))
+ if (debuggerCore()->boolSetting(LogTimeStamps))
showMessage(LogWindow::logTimeStamp(), LogMiscInput);
m_oldestAcceptableToken = currentToken();
+ m_stackNeeded = false;
}
@@ -2073,85 +2036,82 @@ void GdbEngine::setTokenBarrier()
//
//////////////////////////////////////////////////////////////////////
-void GdbEngine::setBreakpointDataFromOutput(BreakpointData *data, const GdbMi &bkpt)
+void GdbEngine::updateBreakpointDataFromOutput(BreakpointId id, const GdbMi &bkpt)
{
- if (!bkpt.isValid())
- return;
- if (!data)
- return;
- data->pending = false;
- data->bpMultiple = false;
- data->bpEnabled = true;
- data->bpCondition.clear();
+ QTC_ASSERT(bkpt.isValid(), return);
+ BreakpointResponse response = breakHandler()->response(id);
+
+ response.multiple = false;
+ response.enabled = true;
+ response.pending = false;
+ response.condition.clear();
QByteArray file, fullName;
foreach (const GdbMi &child, bkpt.children()) {
if (child.hasName("number")) {
- data->bpNumber = child.data();
+ response.number = child.data().toInt();
} else if (child.hasName("func")) {
- data->bpFuncName = _(child.data());
+ response.functionName = _(child.data());
} else if (child.hasName("addr")) {
// <MULTIPLE> happens in constructors. In this case there are
// _two_ fields named "addr" in the response. On Linux that is...
if (child.data().startsWith("0x")) {
- data->bpAddress = child.data().mid(2).toULongLong(0, 16);
+ response.address = child.data().mid(2).toULongLong(0, 16);
} else {
- data->bpState = child.data();
+ response.extra = child.data();
if (child.data() == "<MULTIPLE>")
- data->bpMultiple = true;
+ response.multiple = true;
}
} else if (child.hasName("file")) {
file = child.data();
} else if (child.hasName("fullname")) {
fullName = child.data();
} else if (child.hasName("line")) {
- bool ok;
- const int lineNumber = child.data().toInt(&ok);
- data->bpLineNumber = lineNumber;
- if (ok && data->bpCorrectedLineNumber <= 0)
- data->setMarkerLineNumber(lineNumber);
+ response.lineNumber = child.data().toInt();
} else if (child.hasName("cond")) {
- data->bpCondition = child.data();
// gdb 6.3 likes to "rewrite" conditions. Just accept that fact.
- if (data->bpCondition != data->condition && data->conditionsMatch())
- data->condition = data->bpCondition;
+ response.condition = child.data();
} else if (child.hasName("enabled")) {
- data->bpEnabled = (child.data() == "y");
+ response.enabled = (child.data() == "y");
} else if (child.hasName("pending")) {
- data->pending = true;
// Any content here would be interesting only if we did accept
// spontaneously appearing breakpoints (user using gdb commands).
+ response.pending = true;
} else if (child.hasName("at")) {
- // Happens with (e.g.?) gdb 6.4 symbianelf
+ // Happens with gdb 6.4 symbianelf.
QByteArray ba = child.data();
if (ba.startsWith('<') && ba.endsWith('>'))
ba = ba.mid(1, ba.size() - 2);
- data->bpFuncName = _(ba);
+ response.functionName = _(ba);
} else if (child.hasName("thread")) {
- data->bpThreadSpec = child.data();
+ response.threadSpec = child.data().toInt();
} else if (child.hasName("type")) {
- if (child.data().contains("reakpoint")) // "breakpoint", "hw breakpoint"
- data->type = BreakpointData::BreakpointType;
- else // FIXME: Incomplete list of cases.
- data->type = BreakpointData::WatchpointType;
+ // "breakpoint", "hw breakpoint", "tracepoint"
+ if (child.data().contains("tracepoint"))
+ response.tracepoint = true;
+ else if (!child.data().contains("reakpoint"))
+ response.type = Watchpoint;
}
// This field is not present. Contents needs to be parsed from
// the plain "ignore" response.
//else if (child.hasName("ignore"))
- // data->bpIgnoreCount = child.data();
+ // response.ignoreCount = child.data();
}
QString name;
if (!fullName.isEmpty()) {
name = cleanupFullName(QFile::decodeName(fullName));
- if (data->markerFileName().isEmpty())
- data->setMarkerFileName(name);
+ response.fileName = name;
+ //if (data->markerFileName().isEmpty())
+ // data->setMarkerFileName(name);
} else {
name = QFile::decodeName(file);
// Use fullName() once we have a mapping which is more complete than
// gdb's own. No point in assigning markerFileName for now.
}
if (!name.isEmpty())
- data->bpFileName = name;
+ response.fileName = name;
+
+ breakHandler()->setResponse(id, response);
}
QString GdbEngine::breakLocation(const QString &file) const
@@ -2163,99 +2123,112 @@ QString GdbEngine::breakLocation(const QString &file) const
return where;
}
-static inline QByteArray bpAddressSpec(quint64 address)
+static QByteArray addressSpec(quint64 address)
{
return "*0x" + QByteArray::number(address, 16);
}
-QByteArray GdbEngine::breakpointLocation(const BreakpointData *data)
+QByteArray GdbEngine::breakpointLocation(BreakpointId id)
{
- if (!data->funcName.isEmpty()) {
- if (data->funcName == QLatin1String(BreakpointData::throwFunction))
- return QByteArray("__cxa_throw");
- if (data->funcName == QLatin1String(BreakpointData::catchFunction))
- return QByteArray("__cxa_begin_catch");
- return data->funcName.toLatin1();
- }
- if (data->address)
- return bpAddressSpec(data->address);
- // In this case, data->funcName is something like '*0xdeadbeef'
- if (data->lineNumber == 0)
- return data->funcName.toLatin1();
- QString loc = data->useFullPath ? data->fileName : breakLocation(data->fileName);
+ BreakHandler *handler = breakHandler();
+ const BreakpointParameters &data = handler->breakpointData(id);
+ QTC_ASSERT(data.type != UnknownType, return QByteArray());
+ // FIXME: Non-GCC-runtime
+ if (data.type == BreakpointAtThrow)
+ return "__cxa_throw";
+ if (data.type == BreakpointAtCatch)
+ return "__cxa_begin_catch";
+ if (data.type == BreakpointAtMain)
+#ifdef Q_OS_WIN
+ // FIXME: Should be target specific.
+ return "qMain";
+#else
+ return "main";
+#endif
+ if (data.type == BreakpointByFunction)
+ return data.functionName.toUtf8();
+ if (data.type == BreakpointByAddress)
+ return addressSpec(data.address);
+
+ const QString fileName = data.useFullPath
+ ? data.fileName : breakLocation(data.fileName);
// The argument is simply a C-quoted version of the argument to the
// non-MI "break" command, including the "original" quoting it wants.
- return "\"\\\"" + GdbMi::escapeCString(loc).toLocal8Bit() + "\\\":"
- + QByteArray::number(data->lineNumber) + '"';
-}
-
-void GdbEngine::sendInsertBreakpoint(int index)
-{
- const BreakpointData *data = breakHandler()->at(index);
- // Set up fallback in case of pending breakpoints which aren't handled
- // by the MI interface.
- if (data->type == BreakpointData::WatchpointType) {
- postCommand("watch " + bpAddressSpec(data->address),
- NeedsStop | RebuildBreakpointModel,
- CB(handleWatchInsert), index);
- return;
- }
-
- QByteArray cmd;
- if (m_isMacGdb) {
- cmd = "-break-insert -l -1 -f ";
- } else if (m_gdbAdapter->isTrkAdapter()) {
- cmd = "-break-insert -h -f ";
- } else if (m_gdbVersion >= 70000) {
- cmd = "-break-insert ";
- if (!data->threadSpec.isEmpty())
- cmd += "-p " + data->threadSpec;
- cmd += " -f ";
- } else if (m_gdbVersion >= 60800) {
- // Probably some earlier version would work as well.
- cmd = "-break-insert -f ";
- } else {
- cmd = "-break-insert ";
- }
- //if (!data->condition.isEmpty())
- // cmd += "-c " + data->condition + ' ';
- cmd += breakpointLocation(data);
- postCommand(cmd, NeedsStop | RebuildBreakpointModel,
- CB(handleBreakInsert1), index);
+ return "\"\\\"" + GdbMi::escapeCString(fileName).toLocal8Bit() + "\\\":"
+ + QByteArray::number(data.lineNumber) + '"';
}
void GdbEngine::handleWatchInsert(const GdbResponse &response)
{
- int index = response.cookie.toInt();
+ const int id = response.cookie.toInt();
if (response.resultClass == GdbResultDone) {
// "Hardware watchpoint 2: *0xbfffed40\n"
QByteArray ba = response.data.findChild("consolestreamoutput").data();
- if (ba.startsWith("Hardware watchpoint ")) {
- const int pos = ba.indexOf(':', 20);
- BreakpointData *data = breakHandler()->at(index);
- data->bpNumber = ba.mid(20, pos - 20);
- breakHandler()->updateMarkers();
+ if (ba.startsWith("Hardware watchpoint ")
+ || ba.startsWith("Watchpoint ")) {
+ const int end = ba.indexOf(':');
+ const int begin = ba.lastIndexOf(' ', end) + 1;
+ const QByteArray address = ba.mid(end + 3).trimmed();
+ BreakHandler *handler = breakHandler();
+ BreakpointResponse response = handler->response(id);
+ response.number = ba.mid(begin, end - begin).toInt();
+ response.address = address.toULongLong(0, 0);
+ handler->setResponse(id, response);
+ QTC_ASSERT(!handler->needsChange(id), /**/);
+ handler->notifyBreakpointInsertOk(id);
} else {
- showMessage(_("CANNOT PARSE WATCHPOINT FROM" + ba));
+ showMessage(_("CANNOT PARSE WATCHPOINT FROM " + ba));
}
}
}
+void GdbEngine::attemptAdjustBreakpointLocation(BreakpointId id)
+{
+ if (!debuggerCore()->boolSetting(AdjustBreakpointLocations))
+ return;
+ BreakpointResponse response = breakHandler()->response(id);
+ if (response.address == 0 || response.correctedLineNumber != 0)
+ return;
+ // Prevent endless loop.
+ response.correctedLineNumber = -1;
+ breakHandler()->setResponse(id, response);
+ postCommand("info line *0x" + QByteArray::number(response.address, 16),
+ NeedsStop | RebuildBreakpointModel,
+ CB(handleInfoLine), id);
+}
+
void GdbEngine::handleBreakInsert1(const GdbResponse &response)
{
- int index = response.cookie.toInt();
- BreakpointData *data = breakHandler()->at(index);
+ BreakHandler *handler = breakHandler();
+ BreakpointId id(response.cookie.toInt());
if (response.resultClass == GdbResultDone) {
// Interesting only on Mac?
GdbMi bkpt = response.data.findChild("bkpt");
- setBreakpointDataFromOutput(data, bkpt);
+ updateBreakpointDataFromOutput(id, bkpt);
+ if (handler->needsChange(id)) {
+ handler->notifyBreakpointChangeAfterInsertNeeded(id);
+ changeBreakpoint(id);
+ } else {
+ handler->notifyBreakpointInsertOk(id);
+ attemptAdjustBreakpointLocation(id);
+ }
+ } else if (response.data.findChild("msg").data().contains("Unknown option")) {
+ // Older version of gdb don't know the -a option to set tracepoints
+ // ^error,msg="mi_cmd_break_insert: Unknown option ``a''"
+ const QString fileName = handler->fileName(id);
+ const int lineNumber = handler->lineNumber(id);
+ QByteArray cmd = "trace "
+ "\"" + GdbMi::escapeCString(fileName).toLocal8Bit() + "\":"
+ + QByteArray::number(lineNumber);
+ postCommand(cmd, NeedsStop | RebuildBreakpointModel,
+ CB(handleTraceInsert2), id);
} else {
// Some versions of gdb like "GNU gdb (GDB) SUSE (6.8.91.20090930-2.4)"
// know how to do pending breakpoints using CLI but not MI. So try
// again with MI.
- QByteArray cmd = "break " + breakpointLocation(data);
+ QByteArray cmd = "break " + breakpointLocation(id);
postCommand(cmd, NeedsStop | RebuildBreakpointModel,
- CB(handleBreakInsert2), index);
+ CB(handleBreakInsert2), id);
}
}
@@ -2273,6 +2246,12 @@ void GdbEngine::handleBreakInsert2(const GdbResponse &response)
}
}
+void GdbEngine::handleTraceInsert2(const GdbResponse &response)
+{
+ if (response.resultClass == GdbResultDone)
+ reloadBreakListInternal();
+}
+
void GdbEngine::reloadBreakListInternal()
{
postCommand("-break-list",
@@ -2314,20 +2293,16 @@ void GdbEngine::handleBreakList(const GdbMi &table)
if (num <= 0)
bkpts.removeAt(i);
}
- //qDebug() << "LEFT" << bkpts.size() << "BREAKPOINTS";
}
foreach (const GdbMi &bkpt, bkpts) {
- BreakpointData temp;
- setBreakpointDataFromOutput(&temp, bkpt);
- BreakpointData *data = breakHandler()->findSimilarBreakpoint(&temp);
- //qDebug() << "\n\nGOT: " << bkpt.toString() << '\n' << temp.toString();
- if (data) {
- //qDebug() << " FROM: " << data->toString();
- setBreakpointDataFromOutput(data, bkpt);
- //qDebug() << " TO: " << data->toString();
+ BreakpointResponse needle;
+ needle.number = bkpt.findChild("number").data().toInt();
+ BreakpointId id = breakHandler()->findSimilarBreakpoint(needle);
+ if (id != BreakpointId(-1)) {
+ updateBreakpointDataFromOutput(id, bkpt);
} else {
- //qDebug() << " NOTHING SUITABLE FOUND";
+ qDebug() << " NOTHING SUITABLE FOUND";
showMessage(_("CANNOT FIND BP: " + bkpt.toString()));
}
}
@@ -2337,14 +2312,44 @@ void GdbEngine::handleBreakList(const GdbMi &table)
void GdbEngine::handleBreakDisable(const GdbResponse &response)
{
- if (response.resultClass == GdbResultDone) {
- breakHandler()->updateMarkers();
- }
+ QTC_ASSERT(response.resultClass == GdbResultDone, /**/)
+ const BreakpointId id = response.cookie.toInt();
+ BreakHandler *handler = breakHandler();
+ // This should only be the requested state.
+ QTC_ASSERT(!handler->isEnabled(id), /* Prevent later recursion */);
+ BreakpointResponse br = handler->response(id);
+ br.enabled = false;
+ handler->setResponse(id, br);
+ changeBreakpoint(id); // Maybe there's more to do.
+}
+
+void GdbEngine::handleBreakEnable(const GdbResponse &response)
+{
+ QTC_ASSERT(response.resultClass == GdbResultDone, /**/)
+ const BreakpointId id = response.cookie.toInt();
+ BreakHandler *handler = breakHandler();
+ // This should only be the requested state.
+ QTC_ASSERT(handler->isEnabled(id), /* Prevent later recursion */);
+ BreakpointResponse br = handler->response(id);
+ br.enabled = true;
+ handler->setResponse(id, br);
+ changeBreakpoint(id); // Maybe there's more to do.
+}
+
+void GdbEngine::handleBreakThreadSpec(const GdbResponse &response)
+{
+ QTC_ASSERT(response.resultClass == GdbResultDone, /**/)
+ const BreakpointId id = response.cookie.toInt();
+ BreakHandler *handler = breakHandler();
+ BreakpointResponse br = handler->response(id);
+ br.threadSpec = handler->threadSpec(id);
+ handler->setResponse(id, br);
+ handler->notifyBreakpointNeedsReinsertion(id);
+ insertBreakpoint(id);
}
void GdbEngine::handleBreakIgnore(const GdbResponse &response)
{
- int bpNumber = response.cookie.toInt();
// gdb 6.8:
// ignore 2 0:
// ~"Will stop next time breakpoint 2 is reached.\n"
@@ -2355,45 +2360,41 @@ void GdbEngine::handleBreakIgnore(const GdbResponse &response)
// 29^done
//
// gdb 6.3 does not produce any console output
- BreakpointData *data = breakHandler()->findBreakpointByNumber(bpNumber);
- if (response.resultClass == GdbResultDone && data) {
- QString msg = _(response.data.findChild("consolestreamoutput").data());
- //if (msg.contains(__("Will stop next time breakpoint"))) {
- // data->bpIgnoreCount = _("0");
- //} else if (msg.contains(__("Will ignore next"))) {
- // data->bpIgnoreCount = data->ignoreCount;
- //}
- // FIXME: this assumes it is doing the right thing...
- data->bpIgnoreCount = data->ignoreCount;
- breakHandler()->updateMarkers();
- }
+ QTC_ASSERT(response.resultClass == GdbResultDone, /**/)
+ QString msg = _(response.data.findChild("consolestreamoutput").data());
+ BreakpointId id = response.cookie.toInt();
+ BreakHandler *handler = breakHandler();
+ BreakpointResponse br = handler->response(id);
+ //if (msg.contains(__("Will stop next time breakpoint")))
+ // response.ignoreCount = _("0");
+ //else if (msg.contains(__("Will ignore next")))
+ // response.ignoreCount = data->ignoreCount;
+ // FIXME: this assumes it is doing the right thing...
+ br.ignoreCount = handler->ignoreCount(id);
+ handler->setResponse(id, br);
+ changeBreakpoint(id); // Maybe there's more to do.
}
void GdbEngine::handleBreakCondition(const GdbResponse &response)
{
- int bpNumber = response.cookie.toInt();
- BreakpointData *data = breakHandler()->findBreakpointByNumber(bpNumber);
- if (response.resultClass == GdbResultDone) {
- // We just assume it was successful. Otherwise we had to parse
- // the output stream data.
- //qDebug() << "HANDLE BREAK CONDITION" << bpNumber << data->condition;
- data->bpCondition = data->condition;
- } else {
- QByteArray msg = response.data.findChild("msg").data();
- // happens on Mac
- if (1 || msg.startsWith("Error parsing breakpoint condition. "
- " Will try again when we hit the breakpoint.")) {
- //qDebug() << "ERROR BREAK CONDITION" << bpNumber << data->condition;
- data->bpCondition = data->condition;
- }
- }
- breakHandler()->updateMarkers();
+ // Can happen at invalid condition strings.
+ //QTC_ASSERT(response.resultClass == GdbResultDone, /**/)
+ const BreakpointId id = response.cookie.toInt();
+ BreakHandler *handler = breakHandler();
+ // We just assume it was successful. Otherwise we had to parse
+ // the output stream data.
+ // The following happens on Mac:
+ // QByteArray msg = response.data.findChild("msg").data();
+ // if (1 || msg.startsWith("Error parsing breakpoint condition. "
+ // " Will try again when we hit the breakpoint.")) {
+ BreakpointResponse br = handler->response(id);
+ br.condition = handler->condition(id);
+ handler->setResponse(id, br);
+ changeBreakpoint(id); // Maybe there's more to do.
}
-void GdbEngine::extractDataFromInfoBreak(const QString &output, BreakpointData *data)
+void GdbEngine::extractDataFromInfoBreak(const QString &output, BreakpointId id)
{
- data->bpFileName = _("<MULTIPLE>");
-
//qDebug() << output;
if (output.isEmpty())
return;
@@ -2414,10 +2415,15 @@ void GdbEngine::extractDataFromInfoBreak(const QString &output, BreakpointData *
QRegExp re(_("MULTIPLE.*(0x[0-9a-f]+) in (.*)\\s+at (.*):([\\d]+)([^\\d]|$)"));
re.setMinimal(true);
+ BreakpointResponse response;
+ response.fileName = _("<MULTIPLE>");
+
+ QString requestedFileName = breakHandler()->fileName(id);
+
if (re.indexIn(output) != -1) {
- data->bpAddress = re.cap(1).toULongLong(0, 16);
- data->bpFuncName = re.cap(2).trimmed();
- data->bpLineNumber = re.cap(4).toInt();
+ response.address = re.cap(1).toULongLong(0, 16);
+ response.functionName = re.cap(2).trimmed();
+ response.lineNumber = re.cap(4).toInt();
QString full = fullName(re.cap(3));
if (full.isEmpty()) {
// FIXME: This happens without UsePreciseBreakpoints regularly.
@@ -2434,18 +2440,14 @@ void GdbEngine::extractDataFromInfoBreak(const QString &output, BreakpointData *
// for "/full/path/to/foo.cpp". In this case, using the requested
// instead of the acknowledged name makes sense as it will allow setting
// the marker in more cases.
- if (data->fileName.endsWith(full))
- full = data->fileName;
- data->setMarkerLineNumber(data->bpLineNumber);
- if (data->markerFileName().isEmpty()) {
- qDebug() << "111";
- data->setMarkerFileName(full);
- }
- data->bpFileName = full;
+ if (requestedFileName.endsWith(full))
+ full = requestedFileName;
+ response.fileName = full;
} else {
qDebug() << "COULD NOT MATCH " << re.pattern() << " AND " << output;
- data->bpNumber = "<unavailable>";
+ response.number = -1; // <unavailable>
}
+ breakHandler()->setResponse(id, response);
}
void GdbEngine::handleBreakInfo(const GdbResponse &response)
@@ -2453,13 +2455,10 @@ void GdbEngine::handleBreakInfo(const GdbResponse &response)
if (response.resultClass == GdbResultDone) {
// Old-style output for multiple breakpoints, presumably in a
// constructor.
- const int bpNumber = response.cookie.toInt();
- BreakpointData *data = breakHandler()->findBreakpointByNumber(bpNumber);
- if (data) {
- QString str = QString::fromLocal8Bit(
- response.data.findChild("consolestreamoutput").data());
- extractDataFromInfoBreak(str, data);
- }
+ const BreakpointId id(response.cookie.toInt());
+ const QString str = QString::fromLocal8Bit(
+ response.data.findChild("consolestreamoutput").data());
+ extractDataFromInfoBreak(str, id);
}
}
@@ -2469,143 +2468,141 @@ void GdbEngine::handleInfoLine(const GdbResponse &response)
// Old-style output: "Line 1102 of \"simple/app.cpp\" starts
// at address 0x80526aa <_Z10...+131> and ends at 0x80526b5
// <_Z10testQStackv+142>.\n"
- const int bpNumber = response.cookie.toInt();
- BreakpointData *data = breakHandler()->findBreakpointByNumber(bpNumber);
- if (!data)
- return;
QByteArray ba = response.data.findChild("consolestreamoutput").data();
+ const BreakpointId id = response.cookie.toInt();
const int pos = ba.indexOf(' ', 5);
if (ba.startsWith("Line ") && pos != -1) {
const int line = ba.mid(5, pos - 5).toInt();
- data->bpCorrectedLineNumber = line;
- data->setMarkerLineNumber(line);
+ BreakpointResponse br = breakHandler()->response(id);
+ br.lineNumber = line;
+ breakHandler()->setResponse(id, br);
}
}
}
-void GdbEngine::attemptBreakpointSynchronization()
-{
- QTC_ASSERT(!m_sourcesListUpdating,
- qDebug() << "SOURCES LIST CURRENTLY UPDATING"; return);
- showMessage(_("ATTEMPT BREAKPOINT SYNC"));
-
- // We don't have breakpoints in core files.
- if (startParameters().startMode == AttachCore)
- return;
+bool GdbEngine::stateAcceptsBreakpointChanges() const
+{
switch (state()) {
case InferiorSetupRequested:
case InferiorRunRequested:
case InferiorRunOk:
case InferiorStopRequested:
case InferiorStopOk:
- break;
+ return true;
default:
- //qDebug() << "attempted breakpoint sync in state" << state();
- showMessage(_("... NOT POSSIBLE IN CURRENT STATE"));
- return;
+ return false;
}
+}
- if (m_breakListOutdated) {
- reloadBreakListInternal();
- return;
- }
+bool GdbEngine::acceptsBreakpoint(BreakpointId id) const
+{
+ return DebuggerEngine::isCppBreakpoint(breakHandler()->breakpointData(id));
+}
+void GdbEngine::insertBreakpoint(BreakpointId id)
+{
+ // Set up fallback in case of pending breakpoints which aren't handled
+ // by the MI interface.
BreakHandler *handler = breakHandler();
-
- foreach (BreakpointData *data, handler->takeDisabledBreakpoints()) {
- QByteArray bpNumber = data->bpNumber;
- if (!bpNumber.trimmed().isEmpty()) {
- postCommand("-break-disable " + bpNumber,
- NeedsStop | RebuildBreakpointModel);
- data->bpEnabled = false;
- }
+ QTC_ASSERT(handler->state(id) == BreakpointInsertRequested, /**/);
+ handler->notifyBreakpointInsertProceeding(id);
+ if (handler->type(id) == Watchpoint) {
+ postCommand("watch " + addressSpec(handler->address(id)),
+ NeedsStop | RebuildBreakpointModel,
+ CB(handleWatchInsert), id);
+ return;
}
- foreach (BreakpointData *data, handler->takeEnabledBreakpoints()) {
- QByteArray bpNumber = data->bpNumber;
- if (!bpNumber.trimmed().isEmpty()) {
- postCommand("-break-enable " + bpNumber,
- NeedsStop | RebuildBreakpointModel);
- data->bpEnabled = true;
- }
+ QByteArray cmd;
+ if (handler->isTracepoint(id)) {
+ cmd = "-break-insert -a -f ";
+ } else if (m_isMacGdb) {
+ cmd = "-break-insert -l -1 -f ";
+ } else if (m_gdbAdapter->isTrkAdapter()) {
+ cmd = "-break-insert -h -f ";
+ } else if (m_gdbVersion >= 70000) {
+ int spec = handler->threadSpec(id);
+ cmd = "-break-insert ";
+ if (spec >= 0)
+ cmd += "-p " + QByteArray::number(spec);
+ cmd += " -f ";
+ } else if (m_gdbVersion >= 60800) {
+ // Probably some earlier version would work as well.
+ cmd = "-break-insert -f ";
+ } else {
+ cmd = "-break-insert ";
}
+ //if (!data->condition.isEmpty())
+ // cmd += "-c " + data->condition + ' ';
+ cmd += breakpointLocation(id);
+ postCommand(cmd, NeedsStop | RebuildBreakpointModel,
+ CB(handleBreakInsert1), id);
+}
- foreach (BreakpointData *data, handler->takeRemovedBreakpoints()) {
- QByteArray bpNumber = data->bpNumber;
- if (!bpNumber.trimmed().isEmpty()) {
- showMessage(_("DELETING BP " + bpNumber + " IN "
- + data->markerFileName().toLocal8Bit()));
- postCommand("-break-delete " + bpNumber,
- NeedsStop | RebuildBreakpointModel);
- } else {
- showMessage(_("QUIETLY REMOVING UNNUMBERED BREAKPOINT"));
- }
- delete data;
- }
-
- for (int index = 0; index != handler->size(); ++index) {
- BreakpointData *data = handler->at(index);
- if (data->bpNumber.isEmpty()) { // Unset breakpoint?
- data->bpNumber = " "; // Sent, but no feedback yet.
- sendInsertBreakpoint(index);
- } else if (data->bpNumber.toInt()) {
- if (data->bpMultiple && data->bpFileName.isEmpty()) {
- postCommand("info break " + data->bpNumber,
- NeedsStop | RebuildBreakpointModel,
- CB(handleBreakInfo), data->bpNumber.toInt());
- continue;
- }
- if (data->condition != data->bpCondition && !data->conditionsMatch()) {
- // Update conditions if needed.
- postCommand("condition " + data->bpNumber + ' ' + data->condition,
- NeedsStop | RebuildBreakpointModel,
- CB(handleBreakCondition), data->bpNumber.toInt());
- }
- else // Because gdb won't do both changes at a time anyway.
- if (data->ignoreCount != data->bpIgnoreCount) {
- // Update ignorecount if needed.
- QByteArray ic = QByteArray::number(data->ignoreCount);
- postCommand("ignore " + data->bpNumber + ' ' + ic,
- NeedsStop | RebuildBreakpointModel,
- CB(handleBreakIgnore), data->bpNumber.toInt());
- continue;
- }
- if (!data->enabled && data->bpEnabled) {
- postCommand("-break-disable " + data->bpNumber,
- NeedsStop | RebuildBreakpointModel,
- CB(handleBreakDisable), data->bpNumber.toInt());
- data->bpEnabled = false;
- continue;
- }
- if (data->threadSpec != data->bpThreadSpec && !data->bpNumber.isEmpty()) {
- // The only way to change this seems to be to re-set the bp completely.
- //qDebug() << "FIXME: THREAD: " << data->threadSpec << data->bpThreadSpec;
- data->bpThreadSpec.clear();
- postCommand("-break-delete " + data->bpNumber,
- NeedsStop | RebuildBreakpointModel);
- sendInsertBreakpoint(index);
- continue;
- }
- if (data->bpAddress && data->bpCorrectedLineNumber == 0) {
- // Prevent endless loop.
- data->bpCorrectedLineNumber = -1;
- if (theDebuggerBoolSetting(AdjustBreakpointLocations)) {
- postCommand(
- "info line *0x" + QByteArray::number(data->bpAddress, 16),
- NeedsStop | RebuildBreakpointModel,
- CB(handleInfoLine), data->bpNumber.toInt());
- }
- }
- }
+void GdbEngine::changeBreakpoint(BreakpointId id)
+{
+ BreakHandler *handler = breakHandler();
+ const BreakpointParameters &data = handler->breakpointData(id);
+ QTC_ASSERT(data.type != UnknownType, return);
+ const BreakpointResponse &response = handler->response(id);
+ QTC_ASSERT(response.number > 0, return);
+ const QByteArray bpnr = QByteArray::number(response.number);
+ QTC_ASSERT(response.number > 0, return);
+ const BreakpointState state = handler->state(id);
+ if (state == BreakpointChangeRequested)
+ handler->notifyBreakpointChangeProceeding(id);
+ const BreakpointState state2 = handler->state(id);
+ QTC_ASSERT(state2 == BreakpointChangeProceeding, qDebug() << state2);
+
+ if (data.threadSpec != response.threadSpec) {
+ // The only way to change this seems to be to re-set the bp completely.
+ postCommand("-break-delete " + bpnr,
+ NeedsStop | RebuildBreakpointModel,
+ CB(handleBreakThreadSpec), id);
+ return;
}
-
- handler->updateMarkers();
+ if (!data.conditionsMatch(response.condition)) {
+ postCommand("condition " + bpnr + ' ' + data.condition,
+ NeedsStop | RebuildBreakpointModel,
+ CB(handleBreakCondition), id);
+ return;
+ }
+ if (data.ignoreCount != response.ignoreCount) {
+ postCommand("ignore " + bpnr + ' ' + QByteArray::number(data.ignoreCount),
+ NeedsStop | RebuildBreakpointModel,
+ CB(handleBreakIgnore), id);
+ return;
+ }
+ if (!data.enabled && response.enabled) {
+ postCommand("-break-disable " + bpnr,
+ NeedsStop | RebuildBreakpointModel,
+ CB(handleBreakDisable), id);
+ return;
+ }
+ if (data.enabled && !response.enabled) {
+ postCommand("-break-enable " + bpnr,
+ NeedsStop | RebuildBreakpointModel,
+ CB(handleBreakEnable), id);
+ return;
+ }
+ handler->notifyBreakpointChangeOk(id);
+ attemptAdjustBreakpointLocation(id);
}
-bool GdbEngine::acceptsBreakpoint(const Internal::BreakpointData *br)
+void GdbEngine::removeBreakpoint(BreakpointId id)
{
- return !( br->fileName.endsWith(QLatin1String("js")) || br->fileName.endsWith(QLatin1String("qml")) );
+ BreakHandler *handler = breakHandler();
+ QTC_ASSERT(handler->state(id) == BreakpointRemoveRequested, /**/);
+ handler->notifyBreakpointRemoveProceeding(id);
+ BreakpointResponse br = handler->response(id);
+ showMessage(_("DELETING BP %1 IN %2").arg(br.number)
+ .arg(handler->fileName(id)));
+ postCommand("-break-delete " + QByteArray::number(br.number),
+ NeedsStop | RebuildBreakpointModel);
+ // Pretend it succeeds without waiting for response. Feels better.
+ // FIXME: Really?
+ handler->notifyBreakpointRemoveOk(id);
}
@@ -2630,36 +2627,76 @@ void GdbEngine::loadAllSymbols()
void GdbEngine::requestModuleSymbols(const QString &moduleName)
{
- QList<Symbol> rc;
- bool success = false;
- QString errorMessage;
- do {
- const QString nmBinary = _("nm");
- QProcess proc;
- proc.start(nmBinary, QStringList() << _("-D") << moduleName);
- if (!proc.waitForFinished()) {
- errorMessage = tr("Unable to run '%1': %2").arg(nmBinary, proc.errorString());
- break;
- }
- const QString contents = QString::fromLocal8Bit(proc.readAllStandardOutput());
- const QRegExp re(_("([0-9a-f]+)?\\s+([^\\s]+)\\s+([^\\s]+)"));
- Q_ASSERT(re.isValid());
- foreach (const QString &line, contents.split(_c('\n'))) {
- if (re.indexIn(line) != -1) {
- Symbol symbol;
- symbol.address = re.cap(1);
- symbol.state = re.cap(2);
- symbol.name = re.cap(3);
- rc.push_back(symbol);
+ QTemporaryFile tf(QDir::tempPath() + _("/gdbsymbols"));
+ if (!tf.open())
+ return;
+ QString fileName = tf.fileName();
+ tf.close();
+ postCommand("maint print msymbols " + fileName.toLocal8Bit()
+ + " " + moduleName.toLocal8Bit(),
+ NeedsStop, CB(handleShowModuleSymbols),
+ QVariant(moduleName + QLatin1Char('@') + fileName));
+}
+
+void GdbEngine::handleShowModuleSymbols(const GdbResponse &response)
+{
+ const QString cookie = response.cookie.toString();
+ const QString moduleName = cookie.section(QLatin1Char('@'), 0, 0);
+ const QString fileName = cookie.section(QLatin1Char('@'), 1, 1);
+ if (response.resultClass == GdbResultDone) {
+ Symbols rc;
+ QFile file(fileName);
+ file.open(QIODevice::ReadOnly);
+ // Object file /opt/dev/qt/lib/libQtNetworkMyns.so.4:
+ // [ 0] A 0x16bd64 _DYNAMIC moc_qudpsocket.cpp
+ // [12] S 0xe94680 _ZN4myns5QFileC1Ev section .plt myns::QFile::QFile()
+ foreach (const QByteArray &line, file.readAll().split('\n')) {
+ if (line.isEmpty())
+ continue;
+ if (line.at(0) != '[')
+ continue;
+ int posCode = line.indexOf(']') + 2;
+ int posAddress = line.indexOf("0x", posCode);
+ if (posAddress == -1)
+ continue;
+ int posName = line.indexOf(" ", posAddress);
+ int lenAddress = posName - posAddress - 1;
+ int posSection = line.indexOf(" section ");
+ int lenName = 0;
+ int lenSection = 0;
+ int posDemangled = 0;
+ if (posSection == -1) {
+ lenName = line.size() - posName;
+ posDemangled = posName;
} else {
- qWarning("moduleSymbols: unhandled: %s", qPrintable(line));
+ lenName = posSection - posName;
+ posSection += 10;
+ posDemangled = line.indexOf(' ', posSection + 1);
+ if (posDemangled == -1) {
+ lenSection = line.size() - posSection;
+ } else {
+ lenSection = posDemangled - posSection;
+ posDemangled += 1;
+ }
}
+ int lenDemangled = 0;
+ if (posDemangled != -1)
+ lenDemangled = line.size() - posDemangled;
+ Symbol symbol;
+ symbol.state = _(line.mid(posCode, 1));
+ symbol.address = _(line.mid(posAddress, lenAddress));
+ symbol.name = _(line.mid(posName, lenName));
+ symbol.section = _(line.mid(posSection, lenSection));
+ symbol.demangled = _(line.mid(posDemangled, lenDemangled));
+ rc.push_back(symbol);
}
- success = true;
- } while (false);
- if (!success)
- qWarning("moduleSymbols: %s\n", qPrintable(errorMessage));
- showModuleSymbols(moduleName, rc);
+ file.close();
+ file.remove();
+ debuggerCore()->showModuleSymbols(moduleName, rc);
+ } else {
+ showMessageBox(QMessageBox::Critical, tr("Cannot Read Symbols"),
+ tr("Cannot read symbols for module \"%1\".").arg(fileName));
+ }
}
void GdbEngine::reloadModules()
@@ -2680,7 +2717,7 @@ void GdbEngine::reloadModulesInternal()
void GdbEngine::handleModulesList(const GdbResponse &response)
{
- QList<Module> modules;
+ Modules modules;
if (response.resultClass == GdbResultDone) {
// That's console-based output, likely Linux or Windows,
// but we can avoid the #ifdef here.
@@ -2793,18 +2830,17 @@ void GdbEngine::selectThread(int index)
Threads threads = threadsHandler()->threads();
QTC_ASSERT(index < threads.size(), return);
const int id = threads.at(index).id;
- showStatusMessage(tr("Retrieving data for stack view thread 0x%1...").arg(id, 0, 16), 10000);
- postCommand("-thread-select " + QByteArray::number(id),
+ showStatusMessage(tr("Retrieving data for stack view thread 0x%1...")
+ .arg(id, 0, 16), 10000);
+ postCommand("-thread-select " + QByteArray::number(id), Discardable,
CB(handleStackSelectThread));
}
void GdbEngine::handleStackSelectThread(const GdbResponse &)
{
QTC_ASSERT(state() == InferiorUnrunnable || state() == InferiorStopOk, /**/);
- //qDebug("FIXME: StackHandler::handleOutput: SelectThread");
showStatusMessage(tr("Retrieving data for stack view..."), 3000);
- reloadRegisters();
- reloadStack(true);
+ reloadStack(true); // Will reload registers.
updateLocals();
}
@@ -2819,7 +2855,7 @@ void GdbEngine::reloadStack(bool forceGotoLocation)
{
PENDING_DEBUG("RELOAD STACK");
QByteArray cmd = "-stack-list-frames";
- int stackDepth = theDebuggerAction(MaximalStackDepth)->value().toInt();
+ int stackDepth = debuggerCore()->action(MaximalStackDepth)->value().toInt();
if (stackDepth && !m_gdbAdapter->isTrkAdapter())
cmd += " 0 " + QByteArray::number(stackDepth);
// FIXME: gdb 6.4 symbianelf likes to be asked twice. The first time it
@@ -2849,6 +2885,7 @@ StackFrame GdbEngine::parseStackFrame(const GdbMi &frameMi, int level)
frame.from = _(frameMi.findChild("from").data());
frame.line = frameMi.findChild("line").data().toInt();
frame.address = frameMi.findChild("addr").data().toULongLong(0, 16);
+ frame.usable = QFileInfo(frame.file).isReadable();
return frame;
}
@@ -2860,6 +2897,7 @@ void GdbEngine::handleStackListFrames(const GdbResponse &response)
// ^error,data={msg="Previous frame identical to this frame (corrupt stack?)"
// logstreamoutput="Previous frame identical to this frame (corrupt stack?)\n"
//qDebug() << "LISTING STACK FAILED: " << response.toString();
+ reloadRegisters();
return;
}
@@ -2904,8 +2942,8 @@ void GdbEngine::handleStackListFrames(const GdbResponse &response)
}
bool canExpand = !cookie.isFull
- && (n >= theDebuggerAction(MaximalStackDepth)->value().toInt());
- theDebuggerAction(ExpandStack)->setEnabled(canExpand);
+ && (n >= debuggerCore()->action(MaximalStackDepth)->value().toInt());
+ debuggerCore()->action(ExpandStack)->setEnabled(canExpand);
stackHandler()->setFrames(stackFrames, canExpand);
// We can't jump to any file if we don't have any frames.
@@ -2917,32 +2955,23 @@ void GdbEngine::handleStackListFrames(const GdbResponse &response)
// a few exceptions:
// Always jump to frame #0 when stepping by instruction.
- if (theDebuggerBoolSetting(OperateByInstruction))
+ if (debuggerCore()->boolSetting(OperateByInstruction))
targetFrame = 0;
// If there is no frame with source, jump to frame #0.
if (targetFrame == -1)
targetFrame = 0;
- // Mac gdb does not add the location to the "stopped" message,
- // so the early gotoLocation() was not triggered. Force it here.
- // For targetFrame == 0 we already issued a 'gotoLocation'
- // when reading the *stopped message.
- bool jump = (m_isMacGdb || targetFrame != 0);
-
stackHandler()->setCurrentIndex(targetFrame);
- if (jump || cookie.gotoLocation)
- activateFrame(targetFrame);
+ activateFrame(targetFrame);
}
void GdbEngine::activateFrame(int frameIndex)
{
- resetLocation();
if (state() != InferiorStopOk && state() != InferiorUnrunnable)
return;
StackHandler *handler = stackHandler();
- int oldIndex = handler->currentIndex();
if (frameIndex == handler->stackSize()) {
reloadFullStack();
@@ -2951,60 +2980,41 @@ void GdbEngine::activateFrame(int frameIndex)
QTC_ASSERT(frameIndex < handler->stackSize(), return);
- if (oldIndex != frameIndex) {
- // Assuming the command always succeeds this saves a roundtrip.
- // Otherwise the lines below would need to get triggered
- // after a response to this -stack-select-frame here.
- handler->setCurrentIndex(frameIndex);
- postCommand("-stack-select-frame " + QByteArray::number(frameIndex),
- CB(handleStackSelectFrame));
- }
- gotoLocation(handler->currentFrame(), true);
+ // Assuming the command always succeeds this saves a roundtrip.
+ // Otherwise the lines below would need to get triggered
+ // after a response to this -stack-select-frame here.
+ handler->setCurrentIndex(frameIndex);
+ postCommand("-stack-select-frame " + QByteArray::number(frameIndex),
+ Discardable, CB(handleStackSelectFrame));
+ gotoLocation(stackHandler()->currentFrame());
+ updateLocals();
+ reloadRegisters();
}
void GdbEngine::handleStackSelectFrame(const GdbResponse &response)
{
Q_UNUSED(response);
- updateLocals();
- reloadRegisters();
}
void GdbEngine::handleThreadInfo(const GdbResponse &response)
{
- int id = response.cookie.toInt();
+ const int id = response.cookie.toInt();
if (response.resultClass == GdbResultDone) {
- // ^done,threads=[{id="1",target-id="Thread 0xb7fdc710 (LWP 4264)",
- // frame={level="0",addr="0x080530bf",func="testQString",args=[],
- // file="/.../app.cpp",fullname="/../app.cpp",line="1175"},
- // state="stopped",core="0"}],current-thread-id="1"
- const QList<GdbMi> items = response.data.findChild("threads").children();
- Threads threads;
- for (int index = 0, n = items.size(); index != n; ++index) {
- bool ok = false;
- const GdbMi item = items.at(index);
- const GdbMi frame = item.findChild("frame");
- ThreadData thread;
- thread.id = item.findChild("id").data().toInt();
- thread.targetId = QString::fromAscii(item.findChild("target-id").data());
- thread.core = QString::fromLatin1(item.findChild("core").data());
- thread.state = QString::fromLatin1(item.findChild("state").data());
- thread.address = frame.findChild("addr").data().toULongLong(&ok, 0);
- thread.function = QString::fromLatin1(frame.findChild("func").data());
- thread.fileName = QString::fromLatin1(frame.findChild("fullname").data());
- thread.lineNumber = frame.findChild("line").data().toInt();
- threads.append(thread);
- }
+ int currentThreadId;
+ const Threads threads =
+ ThreadsHandler::parseGdbmiThreads(response.data, &currentThreadId);
threadsHandler()->setThreads(threads);
- const int currentThreadId =
- response.data.findChild("current-thread-id").data().toInt();
threadsHandler()->setCurrentThreadId(currentThreadId);
- plugin()->updateState(this); // Adjust Threads combobox.
- if (m_hasInferiorThreadList)
- postCommand("threadnames " + theDebuggerAction(MaximalStackDepth)->value().toByteArray(), CB(handleThreadNames), id);
+ updateViews(); // Adjust Threads combobox.
+ if (m_hasInferiorThreadList) {
+ postCommand("threadnames " +
+ debuggerCore()->action(MaximalStackDepth)->value().toByteArray(),
+ Discardable, CB(handleThreadNames), id);
+ }
} else {
// Fall back for older versions: Try to get at least a list
// of running threads.
- postCommand("-thread-list-ids", CB(handleThreadListIds), id);
+ postCommand("-thread-list-ids", Discardable, CB(handleThreadListIds), id);
}
}
@@ -3037,16 +3047,16 @@ void GdbEngine::handleThreadNames(const GdbResponse &response)
int id = name.findChild("id").data().toInt();
for (int index = 0, n = threads.size(); index != n; ++index) {
ThreadData & thread = threads[index];
- if (thread.id == id) {
- thread.name = decodeData(name.findChild("value").data(), name.findChild("valueencoded").data().toInt());
+ if (thread.id == (quint64)id) {
+ thread.name = decodeData(name.findChild("value").data(),
+ name.findChild("valueencoded").data().toInt());
break;
}
}
}
threadsHandler()->setThreads(threads);
- plugin()->updateState(this);
+ updateViews();
}
-
}
@@ -3104,7 +3114,7 @@ void GdbEngine::handleMakeSnapshot(const GdbResponse &response)
void GdbEngine::reloadRegisters()
{
- if (!plugin()->isRegisterViewVisible())
+ if (!debuggerCore()->isDockVisible(_(Constants::DOCKWIDGET_REGISTER)))
return;
if (state() != InferiorStopOk && state() != InferiorUnrunnable)
@@ -3221,22 +3231,20 @@ bool GdbEngine::supportsThreads() const
bool GdbEngine::showToolTip()
{
- QByteArray iname = tooltipIName(m_toolTipExpression);
+ const QByteArray iname = tooltipIName(m_toolTipExpression);
- if (!theDebuggerBoolSetting(UseToolTipsInMainEditor)) {
+ if (!debuggerCore()->boolSetting(UseToolTipsInMainEditor)) {
watchHandler()->removeData(iname);
return true;
}
- WatchModel *model = watchHandler()->model(TooltipsWatch);
- WatchItem *item = model->findItem(iname, model->rootItem());
- if (!item) {
+ const QModelIndex index = watchHandler()->itemIndex(iname);
+ if (!index.isValid()) {
watchHandler()->removeData(iname);
hideDebuggerToolTip();
return false;
}
- QModelIndex index = model->watchIndex(item);
- showDebuggerToolTip(m_toolTipPos, model, index, m_toolTipExpression);
+ showDebuggerToolTip(m_toolTipPos, index);
return true;
}
@@ -3244,12 +3252,8 @@ void GdbEngine::setToolTipExpression(const QPoint &mousePos,
TextEditor::ITextEditor *editor, int cursorPos)
{
if (state() != InferiorStopOk || !isCppEditor(editor)) {
- //qDebug() << "SUPPRESSING DEBUGGER TOOLTIP, INFERIOR NOT STOPPED/Non Cpp editor";
- return;
- }
-
- if (theDebuggerBoolSetting(DebugDebuggingHelpers)) {
- // minimize interference
+ //qDebug() << "SUPPRESSING DEBUGGER TOOLTIP, INFERIOR NOT STOPPED "
+ // " OR NOT A CPPEDITOR";
return;
}
@@ -3366,23 +3370,19 @@ void GdbEngine::reloadLocals()
bool GdbEngine::hasDebuggingHelperForType(const QByteArray &type) const
{
- if (!theDebuggerBoolSetting(UseDebuggingHelpers))
+ if (!debuggerCore()->boolSetting(UseDebuggingHelpers))
return false;
if (m_gdbAdapter->dumperHandling() == AbstractGdbAdapter::DumperNotAvailable) {
- // "call" is not possible in gdb when looking at core files
+ // Inferior calls are not possible in gdb when looking at core files.
return type == "QString" || type.endsWith("::QString")
|| type == "QStringList" || type.endsWith("::QStringList");
}
- if (theDebuggerBoolSetting(DebugDebuggingHelpers)
- && stackHandler()->isDebuggingDebuggingHelpers())
- return false;
-
if (m_debuggingHelperState != DebuggingHelperAvailable)
return false;
- // simple types
+ // Simple types.
return m_dumperHelper.type(type) != QtDumperHelper::UnknownType;
}
@@ -3473,7 +3473,7 @@ void GdbEngine::rebuildWatchModel()
if (!isSynchronous())
m_processedNames.clear();
PENDING_DEBUG("REBUILDING MODEL" << count);
- if (theDebuggerBoolSetting(LogTimeStamps))
+ if (debuggerCore()->boolSetting(LogTimeStamps))
showMessage(LogWindow::logTimeStamp(), LogMiscInput);
showMessage(_("<Rebuild Watchmodel %1>").arg(count), LogMiscInput);
showStatusMessage(tr("Finished retrieving data"), 400);
@@ -3568,6 +3568,7 @@ void GdbEngine::updateLocals(const QVariant &cookie)
updateLocalsPython(false, QByteArray());
else
updateLocalsClassic(cookie);
+ updateMemoryViews();
}
@@ -3617,7 +3618,6 @@ WatchData GdbEngine::localVariable(const GdbMi &item,
data.iname = "local." + name;
data.name = nam;
data.exp = name;
- data.framekey = m_currentFrame + data.name;
setWatchDataType(data, item.findChild("type"));
if (uninitializedVariables.contains(data.name)) {
data.setError(WatchData::msgNotInScope());
@@ -3661,7 +3661,8 @@ void GdbEngine::insertData(const WatchData &data0)
watchHandler()->insertData(data);
}
-void GdbEngine::assignValueInDebugger(const Internal::WatchData *, const QString &expression, const QVariant &value)
+void GdbEngine::assignValueInDebugger(const WatchData *,
+ const QString &expression, const QVariant &value)
{
postCommand("-var-delete assign");
postCommand("-var-create assign * " + expression.toLatin1());
@@ -3698,15 +3699,15 @@ void GdbEngine::handleWatchPoint(const GdbResponse &response)
struct MemoryAgentCookie
{
MemoryAgentCookie() : agent(0), token(0), address(0) {}
- MemoryAgentCookie(MemoryViewAgent *agent_, QObject *token_, quint64 address_)
+ MemoryAgentCookie(MemoryAgent *agent_, QObject *token_, quint64 address_)
: agent(agent_), token(token_), address(address_)
{}
- QPointer<MemoryViewAgent> agent;
+ QPointer<MemoryAgent> agent;
QPointer<QObject> token;
quint64 address;
};
-void GdbEngine::fetchMemory(MemoryViewAgent *agent, QObject *token, quint64 addr,
+void GdbEngine::fetchMemory(MemoryAgent *agent, QObject *token, quint64 addr,
quint64 length)
{
//qDebug() << "GDB MEMORY FETCH" << agent << addr << length;
@@ -3745,17 +3746,17 @@ class DisassemblerAgentCookie
{
public:
DisassemblerAgentCookie() : agent(0), attempts(0) {}
- DisassemblerAgentCookie(DisassemblerViewAgent *agent_)
+ DisassemblerAgentCookie(DisassemblerAgent *agent_)
: agent(agent_), attempts(0)
{}
public:
- QPointer<DisassemblerViewAgent> agent;
+ QPointer<DisassemblerAgent> agent;
int attempts;
};
// FIXME: add agent->frame() accessor and use that
-void GdbEngine::fetchDisassembler(DisassemblerViewAgent *agent)
+void GdbEngine::fetchDisassembler(DisassemblerAgent *agent)
{
fetchDisassemblerByCli(agent, agent->isMixed());
/*
@@ -3827,23 +3828,20 @@ void GdbEngine::fetchDisassemblerByAddressCli(const DisassemblerAgentCookie &ac0
QVariant::fromValue(ac));
}
-static QByteArray parseLine(const GdbMi &line)
+static DisassemblerLine parseLine(const GdbMi &line)
{
- QByteArray ba;
- ba.reserve(200);
+ DisassemblerLine dl;
QByteArray address = line.findChild("address").data();
//QByteArray funcName = line.findChild("func-name").data();
//QByteArray offset = line.findChild("offset").data();
- QByteArray inst = line.findChild("inst").data();
- ba += address + QByteArray(15 - address.size(), ' ');
+ dl.address = address.toULongLong();
//ba += funcName + "+" + offset + " ";
//ba += QByteArray(30 - funcName.size() - offset.size(), ' ');
- ba += inst;
- ba += '\n';
- return ba;
+ dl.data = _(line.findChild("inst").data());
+ return dl;
}
-QString GdbEngine::parseDisassembler(const GdbMi &lines)
+DisassemblerLines GdbEngine::parseDisassembler(const GdbMi &lines)
{
// ^done,data={asm_insns=[src_and_asm_line={line="1243",file=".../app.cpp",
// line_asm_insn=[{address="0x08054857",func-name="main",offset="27",
@@ -3856,35 +3854,35 @@ QString GdbEngine::parseDisassembler(const GdbMi &lines)
// {address="0x0805acf8",func-name="...",offset="25",inst="and $0xe8,%al"},
// {address="0x0805acfa",func-name="...",offset="27",inst="pop %esp"},
- QList<QByteArray> fileContents;
+ QStringList fileContents;
bool fileLoaded = false;
- QByteArray ba;
- ba.reserve(200 * lines.children().size());
+ DisassemblerLines result;
// FIXME: Performance?
foreach (const GdbMi &child, lines.children()) {
if (child.hasName("src_and_asm_line")) {
- // mixed mode
+ // Mixed mode.
if (!fileLoaded) {
QString fileName = QFile::decodeName(child.findChild("file").data());
fileName = cleanupFullName(fileName);
QFile file(fileName);
file.open(QIODevice::ReadOnly);
- fileContents = file.readAll().split('\n');
+ QTextStream ts(&file);
+ fileContents = ts.readAll().split(QLatin1Char('\n'));
fileLoaded = true;
}
int line = child.findChild("line").data().toInt();
if (line >= 1 && line <= fileContents.size())
- ba += " " + fileContents.at(line - 1) + '\n';
+ result.appendComment(fileContents.at(line - 1));
GdbMi insn = child.findChild("line_asm_insn");
- foreach (const GdbMi &line, insn.children())
- ba += parseLine(line);
+ foreach (const GdbMi &item, insn.children())
+ result.appendLine(parseLine(item));
} else {
- // the non-mixed version
- ba += parseLine(child);
+ // The non-mixed version.
+ result.appendLine(parseLine(child));
}
}
- return _(ba);
+ return result;
}
void GdbEngine::handleFetchDisassemblerByLine(const GdbResponse &response)
@@ -3900,10 +3898,10 @@ void GdbEngine::handleFetchDisassemblerByLine(const GdbResponse &response)
&& lines.childAt(0).findChild("line").data() == "0")
fetchDisassemblerByAddress(ac, true);
else {
- QString contents = parseDisassembler(lines);
- if (ac.agent->contentsCoversAddress(contents)) {
+ DisassemblerLines dlines = parseDisassembler(lines);
+ if (dlines.coversAddress(ac.agent->address())) {
// All is well.
- ac.agent->setContents(contents);
+ ac.agent->setContents(dlines);
} else {
// Can happen e.g. for initializer list on symbian/rvct where
// we get a file name and line number but where the 'fully
@@ -3935,9 +3933,9 @@ void GdbEngine::handleFetchDisassemblerByAddress1(const GdbResponse &response)
if (lines.children().isEmpty())
fetchDisassemblerByAddress(ac, false);
else {
- QString contents = parseDisassembler(lines);
- if (ac.agent->contentsCoversAddress(contents)) {
- ac.agent->setContents(parseDisassembler(lines));
+ DisassemblerLines dlines = parseDisassembler(lines);
+ if (dlines.coversAddress(ac.agent->address())) {
+ ac.agent->setContents(dlines);
} else {
showMessage(_("FALL BACK TO NON-MIXED"));
fetchDisassemblerByAddress(ac, false);
@@ -3984,35 +3982,42 @@ void GdbEngine::handleFetchDisassemblerByCli(const GdbResponse &response)
// First line is something like
// "Dump of assembler code from 0xb7ff598f to 0xb7ff5a07:"
GdbMi output = response.data.findChild("consolestreamoutput");
- QStringList res;
- foreach (QByteArray line, output.data().split('\n')) {
- line = line.trimmed();
+ DisassemblerLines dlines;
+ QByteArray lastFunction;
+ foreach (const QByteArray &line0, output.data().split('\n')) {
+ QByteArray line = line0.trimmed();
if (line.startsWith("=> "))
line = line.mid(3);
+ if (line.isEmpty())
+ continue;
if (line.startsWith("Current language:"))
continue;
+ if (line.startsWith("Dump of assembler"))
+ continue;
if (line.startsWith("The current source"))
continue;
+ if (line.startsWith("End of assembler"))
+ continue;
if (line.startsWith("0x")) {
- int pos1 = line.indexOf('<');
+ int pos1 = line.indexOf('<') + 1;
int pos2 = line.indexOf('+', pos1);
- int pos3 = line.indexOf('>', pos2);
- if (pos3 >= 0) {
- QByteArray ba = " <+" + line.mid(pos2 + 1, pos3 - pos2 - 1);
- ba = line.left(pos1 - 1) + ba.rightJustified(4)
- + ">: " + line.mid(pos3 + 2);
- res.append(_(ba));
- } else {
- res.append(_(line));
+ int pos3 = line.indexOf('>', pos1);
+ if (pos1 < pos2 && pos2 < pos3) {
+ QByteArray function = line.mid(pos1, pos2 - pos1);
+ if (function != lastFunction) {
+ dlines.appendComment(QString());
+ dlines.appendComment(_("Function: ") + _(function));
+ lastFunction = function;
+ }
+ line.replace(pos1, pos2 - pos1, "");
}
+ dlines.appendLine(DisassemblerLine(_(line)));
continue;
}
- res.append(someSpace + _(line));
+ dlines.appendComment(someSpace + _(line));
}
- // Drop "End of assembler dump." line.
- res.takeLast();
- if (res.size() > 1)
- ac.agent->setContents(res.join(_("\n")));
+ if (dlines.size())
+ ac.agent->setContents(dlines);
else
fetchDisassemblerByAddressCli(ac);
}
@@ -4040,7 +4045,7 @@ bool GdbEngine::startGdb(const QStringList &args, const QString &gdb, const QStr
m_gdb = QString::fromLocal8Bit(qgetenv("QTC_DEBUGGER_PATH"));
if (m_gdb.isEmpty() && startParameters().startMode != StartRemoteGdb)
- m_gdb = gdbBinaryForToolChain(startParameters().toolChainType);
+ m_gdb = debuggerCore()->gdbBinaryForToolChain(startParameters().toolChainType);
if (m_gdb.isEmpty())
m_gdb = gdb;
if (m_gdb.isEmpty()) {
@@ -4054,36 +4059,46 @@ bool GdbEngine::startGdb(const QStringList &args, const QString &gdb, const QStr
gdbArgs << _("-i");
gdbArgs << _("mi");
gdbArgs += args;
+
#ifdef Q_OS_WIN
// Set python path. By convention, python is located below gdb executable.
// Extend the environment set on the process in startAdapter().
const QFileInfo fi(m_gdb);
- bool foundPython = false;
- if (fi.isAbsolute()) {
- const QString winPythonVersion = QLatin1String(winPythonVersionC);
- const QDir dir = fi.absoluteDir();
- if (dir.exists(winPythonVersion)) {
- QProcessEnvironment environment = gdbProc()->processEnvironment();
- const QString pythonPathVariable = QLatin1String("PYTHONPATH");
- // Check for existing values.
- if (environment.contains(pythonPathVariable)) {
- const QString oldPythonPath = environment.value(pythonPathVariable);
- showMessage(_("Using existing python path: %1")
- .arg(oldPythonPath), LogMisc);
- } else {
- const QString pythonPath =
- QDir::toNativeSeparators(dir.absoluteFilePath(winPythonVersion));
- environment.insert(pythonPathVariable, pythonPath);
- showMessage(_("Python path: %1").arg(pythonPath), LogMisc);
- gdbProc()->setProcessEnvironment(environment);
- }
- foundPython = true;
- }
+ if (!fi.isAbsolute()) {
+ showMessage(_("GDB %1 DOES NOT HAVE ABSOLUTE LOCATION.").arg(m_gdb));
+ const QString msg = tr("The gdb location must be given as an "
+ "absolute path in the debugger settings.");
+ handleAdapterStartFailed(msg, settingsIdHint);
+ return false;
}
- if (!foundPython) {
- showMessage(_("UNSUPPORTED GDB %1 DOES NOT HAVE PYTHON.").arg(m_gdb));
- showStatusMessage(_("Gdb at %1 does not have python").arg(m_gdb));
+
+ const QString winPythonVersion = QLatin1String(winPythonVersionC);
+ const QDir dir = fi.absoluteDir();
+
+ QProcessEnvironment environment = gdbProc()->processEnvironment();
+ const QString pythonPathVariable = QLatin1String("PYTHONPATH");
+ QString pythonPath;
+
+ if (dir.exists(winPythonVersion)) {
+ pythonPath = QDir::toNativeSeparators(dir.absoluteFilePath(winPythonVersion));
+ } else if (dir.exists(QLatin1String("lib"))) { // Needed for our gdb 7.2 packages
+ pythonPath = QDir::toNativeSeparators(dir.absoluteFilePath(QLatin1String("lib")));
+ } else {
+ if (environment.contains(pythonPathVariable)) {
+ pythonPath = environment.value(pythonPathVariable);
+ } else {
+ showMessage(_("GDB %1 CANNOT FIND PYTHON INSTALLATION.").arg(m_gdb));
+ showStatusMessage(_("Gdb at %1 cannot find python").arg(m_gdb));
+ const QString msg = tr("The gdb installed at %1 cannot "
+ "find a valid python installation in its %2 subdirectory.\n"
+ "You may set the PYTHONPATH to your installation.")
+ .arg(m_gdb).arg(winPythonVersion);
+ handleAdapterStartFailed(msg, settingsIdHint);
+ return false;
+ }
}
+ environment.insert(pythonPathVariable, pythonPath);
+ showMessage(_("Python path: %1").arg(pythonPath), LogMisc);
#endif
connect(gdbProc(), SIGNAL(error(QProcess::ProcessError)),
@@ -4181,7 +4196,7 @@ bool GdbEngine::startGdb(const QStringList &args, const QString &gdb, const QStr
loadPythonDumpers();
}
- QString scriptFileName = theDebuggerStringSetting(GdbScriptFile);
+ QString scriptFileName = debuggerCore()->stringSetting(GdbScriptFile);
if (!scriptFileName.isEmpty()) {
if (QFileInfo(scriptFileName).isReadable()) {
postCommand("source " + scriptFileName.toLocal8Bit());
@@ -4215,7 +4230,7 @@ void GdbEngine::handleGdbError(QProcess::ProcessError error)
{
const QString msg = errorMessage(error);
showMessage(_("HANDLE GDB ERROR: ") + msg);
- // Show a message box for asynchroneously reported issues.
+ // Show a message box for asynchronously reported issues.
switch (error) {
case QProcess::FailedToStart:
// This should be handled by the code trying to start the process.
@@ -4228,7 +4243,7 @@ void GdbEngine::handleGdbError(QProcess::ProcessError error)
case QProcess::Timedout:
default:
//gdbProc()->kill();
- //setState(EngineShutdownRequested, true);
+ //notifyEngineIll();
showMessageBox(QMessageBox::Critical, tr("Gdb I/O Error"), msg);
break;
}
@@ -4236,34 +4251,30 @@ void GdbEngine::handleGdbError(QProcess::ProcessError error)
void GdbEngine::handleGdbFinished(int code, QProcess::ExitStatus type)
{
- //qDebug() << "GDB PROCESS FINISHED";
+ if (m_commandTimer.isActive())
+ m_commandTimer.stop();
+
showMessage(_("GDB PROCESS FINISHED, status %1, code %2").arg(type).arg(code));
-/*
- if (!m_gdbAdapter) {
- showMessage(_("NO ADAPTER PRESENT"));
- } else if (state() == EngineShutdownRequested) {
- showMessage(_("GOING TO SHUT DOWN ADAPTER"));
- //m_gdbAdapter->shutdownEngine(); FIXME AAA
- } else if (state() != EngineSetupFailed) {
- showStatusMessage(msg);
- //m_gdbAdapter->shutdownEngine();
- }
- initializeVariables();
-*/
- if (state() == EngineShutdownRequested) {
+
+ switch (state()) {
+ case EngineShutdownRequested:
notifyEngineShutdownOk();
- } else if (state() == InferiorRunOk) {
+ break;
+ case InferiorRunOk:
// This could either be a real gdb crash or a quickly exited inferior
// in the terminal adapter. In this case the stub proc will die soon,
// too, so there's no need to act here.
showMessage(_("The gdb process exited somewhat unexpectedly."));
notifyEngineSpontaneousShutdown();
- } else {
- QString msg = tr("The gdb process exited unexpectedly (%1).")
- .arg((type == QProcess::CrashExit)
- ? tr("crashed") : tr("code %1").arg(code));
+ break;
+ default: {
+ notifyEngineIll(); // Initiate shutdown sequence
+ const QString msg = type == QProcess::CrashExit ?
+ tr("The gdb process crashed.") :
+ tr("The gdb process exited unexpectedly (code %1)").arg(code);
showMessageBox(QMessageBox::Critical, tr("Unexpected Gdb Exit"), msg);
- notifyEngineSpontaneousShutdown();
+ break;
+ }
}
}
@@ -4399,14 +4410,14 @@ void GdbEngine::createFullBacktrace()
void GdbEngine::handleCreateFullBacktrace(const GdbResponse &response)
{
if (response.resultClass == GdbResultDone) {
- plugin()->openTextEditor(_("Backtrace $"),
+ debuggerCore()->openTextEditor(_("Backtrace $"),
_(response.data.findChild("consolestreamoutput").data()));
}
}
void GdbEngine::resetCommandQueue()
{
- m_commandTimer->stop();
+ m_commandTimer.stop();
if (!m_cookieForToken.isEmpty()) {
QString msg;
QTextStream ts(&msg);
@@ -4425,20 +4436,20 @@ void GdbEngine::removeTooltip()
DebuggerEngine::removeTooltip();
}
-//
-// Factory
-//
+void GdbEngine::handleRemoteSetupDone(int gdbServerPort, int qmlPort)
+{
+ m_gdbAdapter->handleRemoteSetupDone(gdbServerPort, qmlPort);
+}
-bool checkGdbConfiguration(int toolChain, QString *errorMessage, QString *settingsPage)
+void GdbEngine::handleRemoteSetupFailed(const QString &message)
{
- if (gdbBinaryForToolChain(toolChain).isEmpty()) {
- *errorMessage = msgNoBinaryForToolChain(toolChain);
- *settingsPage = GdbOptionsPage::settingsId();
- return false;
- }
- return true;
+ m_gdbAdapter->handleRemoteSetupFailed(message);
}
+//
+// Factory
+//
+
DebuggerEngine *createGdbEngine(const DebuggerStartParameters &startParameters)
{
return new GdbEngine(startParameters);
@@ -4452,6 +4463,6 @@ void addGdbOptionPages(QList<Core::IOptionsPage *> *opts)
} // namespace Internal
} // namespace Debugger
-Q_DECLARE_METATYPE(Debugger::Internal::MemoryAgentCookie);
-Q_DECLARE_METATYPE(Debugger::Internal::DisassemblerAgentCookie);
-Q_DECLARE_METATYPE(Debugger::Internal::GdbMi);
+Q_DECLARE_METATYPE(Debugger::Internal::MemoryAgentCookie)
+Q_DECLARE_METATYPE(Debugger::Internal::DisassemblerAgentCookie)
+Q_DECLARE_METATYPE(Debugger::Internal::GdbMi)
diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h
index b4481d0a35..070a19a474 100644
--- a/src/plugins/debugger/gdb/gdbengine.h
+++ b/src/plugins/debugger/gdb/gdbengine.h
@@ -36,12 +36,11 @@
#include "debuggerengine.h"
-#include "gdbmi.h"
-#include "localgdbprocess.h"
#include "stackframe.h"
#include "watchutils.h"
#include <QtCore/QByteArray>
+#include <QtCore/QProcess>
#include <QtCore/QHash>
#include <QtCore/QMap>
#include <QtCore/QMultiMap>
@@ -50,14 +49,9 @@
#include <QtCore/QSet>
#include <QtCore/QTextCodec>
#include <QtCore/QTime>
+#include <QtCore/QTimer>
#include <QtCore/QVariant>
-#include <QtCore/QSharedPointer>
-QT_BEGIN_NAMESPACE
-class QMainWindow;
-class QMessageBox;
-class QTimer;
-QT_END_NAMESPACE
namespace Debugger {
namespace Internal {
@@ -67,9 +61,9 @@ class AbstractGdbProcess;
class GdbResponse;
class GdbMi;
-class BreakpointData;
class WatchData;
class DisassemblerAgentCookie;
+class DisassemblerLines;
class AttachGdbAdapter;
class CoreGdbAdapter;
@@ -82,7 +76,7 @@ enum DebuggingHelperState
DebuggingHelperUninitialized,
DebuggingHelperLoadTried,
DebuggingHelperAvailable,
- DebuggingHelperUnavailable,
+ DebuggingHelperUnavailable
};
@@ -124,7 +118,6 @@ private: ////////// General Interface //////////
private: ////////// General State //////////
- void initializeVariables();
DebuggerStartMode startMode() const;
Q_SLOT void reloadLocals();
@@ -138,6 +131,8 @@ private: ////////// Gdb Process Management //////////
const QString &settingsIdHint = QString());
void handleInferiorShutdown(const GdbResponse &response);
void handleGdbExit(const GdbResponse &response);
+ void handleRemoteSetupDone(int gdbServerPort, int qmlPort);
+ void handleRemoteSetupFailed(const QString &message);
void handleAdapterStarted();
void defaultInferiorShutdown(const char *cmd);
@@ -191,7 +186,7 @@ private: ////////// Gdb Command Management //////////
enum GdbCommandFlag {
NoFlags = 0,
// The command needs a stopped inferior.
- NeedsStop = 1,
+ NeedsStop = 1,
// No need to wait for the reply before continuing inferior.
Discardable = 2,
// Trigger watch model rebuild when no such commands are pending anymore.
@@ -210,7 +205,7 @@ private: ////////// Gdb Command Management //////////
// This command needs to be send immediately.
Immediate = 256,
// This is a command that needs to be wrapped into -interpreter-exec console
- ConsoleCommand = 512,
+ ConsoleCommand = 512
};
Q_DECLARE_FLAGS(GdbCommandFlags, GdbCommandFlag)
private:
@@ -265,7 +260,7 @@ private: ////////// Gdb Command Management //////////
QHash<int, GdbCommand> m_cookieForToken;
int commandTimeoutTime() const;
- QTimer *m_commandTimer;
+ QTimer m_commandTimer;
QByteArray m_pendingConsoleStreamOutput;
QByteArray m_pendingLogStreamOutput;
@@ -290,8 +285,10 @@ private: ////////// Gdb Output, State & Capability Handling //////////
void handleResponse(const QByteArray &buff);
void handleStopResponse(const GdbMi &data);
void handleResultRecord(GdbResponse *response);
+ void handleStop0(const GdbMi &data);
void handleStop1(const GdbResponse &response);
void handleStop1(const GdbMi &data);
+ Q_SLOT void handleStop2();
StackFrame parseStackFrame(const GdbMi &mi, int level);
void resetCommandQueue();
@@ -312,25 +309,28 @@ private: ////////// Gdb Output, State & Capability Handling //////////
private: ////////// Inferior Management //////////
// This should be always the last call in a function.
- Q_SLOT virtual void attemptBreakpointSynchronization();
- bool acceptsBreakpoint(const Internal::BreakpointData *br);
-
- virtual void executeStep();
- virtual void executeStepOut();
- virtual void executeNext();
- virtual void executeStepI();
- virtual void executeNextI();
+ bool stateAcceptsBreakpointChanges() const;
+ bool acceptsBreakpoint(BreakpointId id) const;
+ void insertBreakpoint(BreakpointId id);
+ void removeBreakpoint(BreakpointId id);
+ void changeBreakpoint(BreakpointId id);
+
+ void executeStep();
+ void executeStepOut();
+ void executeNext();
+ void executeStepI();
+ void executeNextI();
void continueInferiorInternal();
void autoContinueInferior();
- virtual void continueInferior();
- virtual void interruptInferior();
+ void continueInferior();
+ void interruptInferior();
void interruptInferiorTemporarily();
- virtual void executeRunToLine(const QString &fileName, int lineNumber);
- virtual void executeRunToFunction(const QString &functionName);
- virtual void executeJumpToLine(const QString &fileName, int lineNumber);
- virtual void executeReturn();
+ void executeRunToLine(const QString &fileName, int lineNumber);
+ void executeRunToFunction(const QString &functionName);
+ void executeJumpToLine(const QString &fileName, int lineNumber);
+ void executeReturn();
void handleExecuteContinue(const GdbResponse &response);
void handleExecuteStep(const GdbResponse &response);
@@ -338,7 +338,6 @@ private: ////////// Inferior Management //////////
void handleExecuteReturn(const GdbResponse &response);
void handleExecuteJumpToLine(const GdbResponse &response);
void handleExecuteRunToLine(const GdbResponse &response);
- //void handleExecuteRunToFunction(const GdbResponse &response);
void maybeHandleInferiorPidChanged(const QString &pid);
void handleInfoProc(const GdbResponse &response);
@@ -347,8 +346,8 @@ private: ////////// Inferior Management //////////
private: ////////// View & Data Stuff //////////
- virtual void selectThread(int index);
- virtual void activateFrame(int index);
+ void selectThread(int index);
+ void activateFrame(int index);
//
// Breakpoint specific stuff
@@ -357,29 +356,33 @@ private: ////////// View & Data Stuff //////////
void handleBreakList(const GdbMi &table);
void handleBreakIgnore(const GdbResponse &response);
void handleBreakDisable(const GdbResponse &response);
+ void handleBreakEnable(const GdbResponse &response);
void handleBreakInsert1(const GdbResponse &response);
void handleBreakInsert2(const GdbResponse &response);
+ void handleTraceInsert2(const GdbResponse &response);
void handleBreakCondition(const GdbResponse &response);
void handleBreakInfo(const GdbResponse &response);
+ void handleBreakThreadSpec(const GdbResponse &response);
void handleWatchInsert(const GdbResponse &response);
void handleInfoLine(const GdbResponse &response);
- void extractDataFromInfoBreak(const QString &output, BreakpointData *data);
- void setBreakpointDataFromOutput(BreakpointData *data, const GdbMi &bkpt);
- QByteArray breakpointLocation(const BreakpointData *data);
- void sendInsertBreakpoint(int index);
+ void extractDataFromInfoBreak(const QString &output, BreakpointId);
+ void updateBreakpointDataFromOutput(BreakpointId id, const GdbMi &bkpt);
+ QByteArray breakpointLocation(BreakpointId id);
QString breakLocation(const QString &file) const;
void reloadBreakListInternal();
+ void attemptAdjustBreakpointLocation(BreakpointId id);
//
// Modules specific stuff
//
- virtual void loadSymbols(const QString &moduleName);
- virtual void loadAllSymbols();
- virtual void requestModuleSymbols(const QString &moduleName);
- virtual void reloadModules();
- virtual void examineModules();
+ void loadSymbols(const QString &moduleName);
+ void loadAllSymbols();
+ void requestModuleSymbols(const QString &moduleName);
+ void reloadModules();
+ void examineModules();
void reloadModulesInternal();
void handleModulesList(const GdbResponse &response);
+ void handleShowModuleSymbols(const GdbResponse &response);
bool m_modulesListOutdated;
@@ -392,15 +395,15 @@ private: ////////// View & Data Stuff //////////
//
// Register specific stuff
//
- Q_SLOT virtual void reloadRegisters();
- virtual void setRegisterValue(int nr, const QString &value);
+ Q_SLOT void reloadRegisters();
+ void setRegisterValue(int nr, const QString &value);
void handleRegisterListNames(const GdbResponse &response);
void handleRegisterListValues(const GdbResponse &response);
//
// Disassembler specific stuff
//
- virtual void fetchDisassembler(DisassemblerViewAgent *agent);
+ void fetchDisassembler(DisassemblerAgent *agent);
void fetchDisassemblerByAddress(const DisassemblerAgentCookie &ac,
bool useMixedMode);
void fetchDisassemblerByCli(const DisassemblerAgentCookie &ac,
@@ -410,12 +413,12 @@ private: ////////// View & Data Stuff //////////
void handleFetchDisassemblerByLine(const GdbResponse &response);
void handleFetchDisassemblerByAddress1(const GdbResponse &response);
void handleFetchDisassemblerByAddress0(const GdbResponse &response);
- QString parseDisassembler(const GdbMi &lines);
+ DisassemblerLines parseDisassembler(const GdbMi &lines);
//
// Source file specific stuff
//
- virtual void reloadSourceFiles();
+ void reloadSourceFiles();
void reloadSourceFilesInternal();
void handleQuerySources(const GdbResponse &response);
@@ -448,7 +451,6 @@ private: ////////// View & Data Stuff //////////
int currentFrame() const;
QList<GdbMi> m_currentFunctionArgs;
- QString m_currentFrame;
//
// Watch specific stuff
@@ -456,9 +458,10 @@ private: ////////// View & Data Stuff //////////
virtual void setToolTipExpression(const QPoint &mousePos,
TextEditor::ITextEditor *editor, int cursorPos);
- virtual void assignValueInDebugger(const Internal::WatchData *w, const QString &expr, const QVariant &value);
+ virtual void assignValueInDebugger(const WatchData *data,
+ const QString &expr, const QVariant &value);
- virtual void fetchMemory(MemoryViewAgent *agent, QObject *token,
+ virtual void fetchMemory(MemoryAgent *agent, QObject *token,
quint64 addr, quint64 length);
void handleFetchMemory(const GdbResponse &response);
@@ -521,18 +524,16 @@ private: ////////// View & Data Stuff //////////
void setDebuggingHelperStateClassic(DebuggingHelperState);
void tryLoadDebuggingHelpersClassic();
void tryQueryDebuggingHelpersClassic();
- Q_SLOT void setDebugDebuggingHelpersClassic(const QVariant &on);
Q_SLOT void setUseDebuggingHelpers(const QVariant &on);
DebuggingHelperState m_debuggingHelperState;
QtDumperHelper m_dumperHelper;
QString m_gdb;
- //
+ //
// Convenience Functions
//
QString errorMessage(QProcess::ProcessError error);
- QMainWindow *mainWindow() const;
AbstractGdbProcess *gdbProc() const;
void showExecutionError(const QString &message);
@@ -541,6 +542,10 @@ private: ////////// View & Data Stuff //////////
QString m_toolTipExpression;
QPoint m_toolTipPos;
+ // For short-circuiting stack and thread list evaluation.
+ bool m_stackNeeded;
+ int m_currentThreadId;
+
// HACK:
StackFrame m_targetFrame;
};
diff --git a/src/plugins/debugger/gdb/gdbmi.cpp b/src/plugins/debugger/gdb/gdbmi.cpp
index 82d87e5d08..e4d8f67318 100644
--- a/src/plugins/debugger/gdb/gdbmi.cpp
+++ b/src/plugins/debugger/gdb/gdbmi.cpp
@@ -390,7 +390,7 @@ QByteArray GdbResponse::stringFromResultClass(GdbResultClass resultClass)
case GdbResultExit: return "exit";
default: return "unknown";
}
-};
+}
QByteArray GdbResponse::toString() const
{
diff --git a/src/plugins/debugger/gdb/gdbmi.h b/src/plugins/debugger/gdb/gdbmi.h
index a985c4cb1a..9dda287e23 100644
--- a/src/plugins/debugger/gdb/gdbmi.h
+++ b/src/plugins/debugger/gdb/gdbmi.h
@@ -104,7 +104,7 @@ public:
Invalid,
Const,
Tuple,
- List,
+ List
};
Type m_type;
@@ -156,7 +156,7 @@ enum GdbResultClass
GdbResultRunning,
GdbResultConnected,
GdbResultError,
- GdbResultExit,
+ GdbResultExit
};
class GdbResponse
@@ -178,6 +178,6 @@ void extractGdbVersion(const QString &msg,
} // namespace Internal
} // namespace Debugger
-//Q_DECLARE_METATYPE(GdbDebugger::Internal::GdbMi);
+//Q_DECLARE_METATYPE(GdbDebugger::Internal::GdbMi)
#endif // DEBUGGER_GDBMI_H
diff --git a/src/plugins/debugger/gdb/gdboptionspage.cpp b/src/plugins/debugger/gdb/gdboptionspage.cpp
index 128cf86cd0..a55e43942c 100644
--- a/src/plugins/debugger/gdb/gdboptionspage.cpp
+++ b/src/plugins/debugger/gdb/gdboptionspage.cpp
@@ -33,16 +33,117 @@
#include "gdboptionspage.h"
#include "debuggeractions.h"
-#include "debuggerconstants.h"
+#include "debuggercore.h"
#include <coreplugin/icore.h>
+#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/toolchain.h>
+#include <projectexplorer/toolchaintype.h>
+
#include <QtCore/QCoreApplication>
#include <QtCore/QTextStream>
+#include <QtCore/QFileInfo>
namespace Debugger {
namespace Internal {
+const char gdbBinariesSettingsGroupC[] = "GdbBinaries";
+const char debugModeGdbBinaryKeyC[] = "GdbBinary";
+
+GdbOptionsPage::GdbBinaryToolChainMap GdbOptionsPage::gdbBinaryToolChainMap;
+bool GdbOptionsPage::gdbBinariesChanged = true;
+
+void GdbOptionsPage::readGdbBinarySettings() /* static */
+{
+ using namespace ProjectExplorer;
+ QSettings *settings = Core::ICore::instance()->settings();
+ // Convert gdb binaries from flat settings list (see writeSettings)
+ // into map ("binary1=gdb,1,2", "binary2=symbian_gdb,3,4").
+ gdbBinaryToolChainMap.clear();
+ const QChar separator = QLatin1Char(',');
+ const QString keyRoot = QLatin1String(gdbBinariesSettingsGroupC) + QLatin1Char('/') +
+ QLatin1String(debugModeGdbBinaryKeyC);
+ for (int i = 1; ; i++) {
+ const QString value = settings->value(keyRoot + QString::number(i)).toString();
+ if (value.isEmpty())
+ break;
+ // Split apart comma-separated binary and its numerical toolchains.
+ QStringList tokens = value.split(separator);
+ if (tokens.size() < 2)
+ break;
+ const QString binary = tokens.front();
+ // Skip non-existent absolute binaries allowing for upgrades by the installer.
+ // Force a rewrite of the settings file.
+ const QFileInfo binaryInfo(binary);
+ if (binaryInfo.isAbsolute() && !binaryInfo.isExecutable()) {
+ gdbBinariesChanged = true;
+ const QString msg = QString::fromLatin1("Warning: The gdb binary '%1' does not exist, skipping.\n").arg(binary);
+ qWarning("%s", qPrintable(msg));
+ continue;
+ }
+ // Create entries for all toolchains.
+ tokens.pop_front();
+ foreach (const QString &t, tokens) {
+ // Paranoia: Check if the there is already a binary configured for the toolchain.
+ const int toolChain = t.toInt();
+ const QString predefinedGdb = gdbBinaryToolChainMap.key(toolChain);
+ if (predefinedGdb.isEmpty()) {
+ gdbBinaryToolChainMap.insert(binary, toolChain);
+ } else {
+ const QString toolChainName =
+ ProjectExplorer::ToolChain::toolChainName(ToolChainType(toolChain));
+ const QString msg =
+ QString::fromLatin1("An inconsistency has been encountered in the Ini-file '%1':\n"
+ "Skipping gdb binary '%2' for toolchain '%3' as '%4' is already configured for it.").
+ arg(settings->fileName(), binary, toolChainName, predefinedGdb);
+ qWarning("%s", qPrintable(msg));
+ }
+ }
+ }
+ // Linux defaults
+#ifdef Q_OS_UNIX
+ if (gdbBinaryToolChainMap.isEmpty()) {
+ const QString gdb = QLatin1String("gdb");
+ gdbBinaryToolChainMap.insert(gdb, ToolChain_GCC);
+ gdbBinaryToolChainMap.insert(gdb, ToolChain_LINUX_ICC);
+ gdbBinaryToolChainMap.insert(gdb, ToolChain_OTHER);
+ gdbBinaryToolChainMap.insert(gdb, ToolChain_UNKNOWN);
+ }
+#endif
+}
+
+void GdbOptionsPage::writeGdbBinarySettings() /* static */
+{
+ QSettings *settings = Core::ICore::instance()->settings();
+ // Convert gdb binaries map into a flat settings list of
+ // ("binary1=gdb,1,2", "binary2=symbian_gdb,3,4"). It needs to be ASCII for installers
+ QString lastBinary;
+ QStringList settingsList;
+ const QChar separator = QLatin1Char(',');
+ const GdbBinaryToolChainMap::const_iterator cend = gdbBinaryToolChainMap.constEnd();
+ for (GdbBinaryToolChainMap::const_iterator it = gdbBinaryToolChainMap.constBegin(); it != cend; ++it) {
+ if (it.key() != lastBinary) {
+ lastBinary = it.key(); // Start new entry with first toolchain
+ settingsList.push_back(lastBinary);
+ }
+ settingsList.back().append(separator); // Append toolchain to last binary
+ settingsList.back().append(QString::number(it.value()));
+ }
+ // Terminate settings list by an empty element such that consecutive keys resulting
+ // from ini-file merging are suppressed while reading.
+ settingsList.push_back(QString());
+ // Write out list
+ settings->beginGroup(QLatin1String(gdbBinariesSettingsGroupC));
+ settings->remove(QString()); // remove all keys in group.
+ const int count = settingsList.size();
+ const QString keyRoot = QLatin1String(debugModeGdbBinaryKeyC);
+ for (int i = 0; i < count; i++)
+ settings->setValue(keyRoot + QString::number(i + 1), settingsList.at(i));
+ settings->endGroup();
+}
+
GdbOptionsPage::GdbOptionsPage()
+ : m_ui(0)
{
}
@@ -74,73 +175,92 @@ QIcon GdbOptionsPage::categoryIcon() const
QWidget *GdbOptionsPage::createPage(QWidget *parent)
{
QWidget *w = new QWidget(parent);
- m_ui.setupUi(w);
- m_ui.gdbChooserWidget
- ->setGdbBinaries(DebuggerSettings::instance()->gdbBinaryToolChainMap());
- m_ui.scriptFileChooser->setExpectedKind(Utils::PathChooser::File);
- m_ui.scriptFileChooser->setPromptDialogTitle(tr("Choose Location of Startup Script File"));
+ m_ui = new Ui::GdbOptionsPage;
+ m_ui->setupUi(w);
+ m_ui->gdbChooserWidget->setGdbBinaries(gdbBinaryToolChainMap);
+ m_ui->scriptFileChooser->setExpectedKind(Utils::PathChooser::File);
+ m_ui->scriptFileChooser->setPromptDialogTitle(tr("Choose Location of Startup Script File"));
m_group.clear();
- m_group.insert(theDebuggerAction(GdbScriptFile),
- m_ui.scriptFileChooser);
- m_group.insert(theDebuggerAction(GdbEnvironment),
- m_ui.environmentEdit);
- m_group.insert(theDebuggerAction(AdjustBreakpointLocations),
- m_ui.checkBoxAdjustBreakpointLocations);
- m_group.insert(theDebuggerAction(GdbWatchdogTimeout),
- m_ui.spinBoxGdbWatchdogTimeout);
-
- m_group.insert(theDebuggerAction(UseMessageBoxForSignals),
- m_ui.checkBoxUseMessageBoxForSignals);
- m_group.insert(theDebuggerAction(SkipKnownFrames),
- m_ui.checkBoxSkipKnownFrames);
- m_group.insert(theDebuggerAction(EnableReverseDebugging),
- m_ui.checkBoxEnableReverseDebugging);
- m_group.insert(theDebuggerAction(GdbWatchdogTimeout), 0);
+ m_group.insert(debuggerCore()->action(GdbScriptFile),
+ m_ui->scriptFileChooser);
+ m_group.insert(debuggerCore()->action(GdbEnvironment),
+ m_ui->environmentEdit);
+ m_group.insert(debuggerCore()->action(AdjustBreakpointLocations),
+ m_ui->checkBoxAdjustBreakpointLocations);
+ m_group.insert(debuggerCore()->action(GdbWatchdogTimeout),
+ m_ui->spinBoxGdbWatchdogTimeout);
+
+ m_group.insert(debuggerCore()->action(UseMessageBoxForSignals),
+ m_ui->checkBoxUseMessageBoxForSignals);
+ m_group.insert(debuggerCore()->action(SkipKnownFrames),
+ m_ui->checkBoxSkipKnownFrames);
+ m_group.insert(debuggerCore()->action(EnableReverseDebugging),
+ m_ui->checkBoxEnableReverseDebugging);
+ m_group.insert(debuggerCore()->action(GdbWatchdogTimeout), 0);
#if 1
- m_ui.groupBoxPluginDebugging->hide();
+ m_ui->groupBoxPluginDebugging->hide();
#else // The related code (handleAqcuiredInferior()) is disabled as well.
- m_group.insert(theDebuggerAction(AllPluginBreakpoints),
- m_ui.radioButtonAllPluginBreakpoints);
- m_group.insert(theDebuggerAction(SelectedPluginBreakpoints),
- m_ui.radioButtonSelectedPluginBreakpoints);
- m_group.insert(theDebuggerAction(NoPluginBreakpoints),
- m_ui.radioButtonNoPluginBreakpoints);
- m_group.insert(theDebuggerAction(SelectedPluginBreakpointsPattern),
- m_ui.lineEditSelectedPluginBreakpointsPattern);
+ m_group.insert(debuggerCore()->action(AllPluginBreakpoints),
+ m_ui->radioButtonAllPluginBreakpoints);
+ m_group.insert(debuggerCore()->action(SelectedPluginBreakpoints),
+ m_ui->radioButtonSelectedPluginBreakpoints);
+ m_group.insert(debuggerCore()->action(NoPluginBreakpoints),
+ m_ui->radioButtonNoPluginBreakpoints);
+ m_group.insert(debuggerCore()->action(SelectedPluginBreakpointsPattern),
+ m_ui->lineEditSelectedPluginBreakpointsPattern);
#endif
- m_ui.lineEditSelectedPluginBreakpointsPattern->
- setEnabled(theDebuggerAction(SelectedPluginBreakpoints)->value().toBool());
- connect(m_ui.radioButtonSelectedPluginBreakpoints, SIGNAL(toggled(bool)),
- m_ui.lineEditSelectedPluginBreakpointsPattern, SLOT(setEnabled(bool)));
+ m_ui->lineEditSelectedPluginBreakpointsPattern->
+ setEnabled(debuggerCore()->action(SelectedPluginBreakpoints)->value().toBool());
+ connect(m_ui->radioButtonSelectedPluginBreakpoints, SIGNAL(toggled(bool)),
+ m_ui->lineEditSelectedPluginBreakpointsPattern, SLOT(setEnabled(bool)));
// FIXME
- m_ui.environmentEdit->hide();
- m_ui.labelEnvironment->hide();
+ m_ui->environmentEdit->hide();
+ m_ui->labelEnvironment->hide();
if (m_searchKeywords.isEmpty()) {
- // TODO: Add breakpoints, environment?
- QTextStream(&m_searchKeywords) << ' ' << QLatin1String("gdb")
- << ' ' << m_ui.checkBoxSkipKnownFrames->text()
- << ' ' << m_ui.checkBoxEnableReverseDebugging->text()
- << ' ' << m_ui.checkBoxUseMessageBoxForSignals->text()
- << ' ' << m_ui.labelEnvironment->text()
- << ' ' << m_ui.labelGdbStartupScript->text();
+ QLatin1Char sep(' ');
+ QTextStream(&m_searchKeywords)
+ << sep << m_ui->groupBoxLocations->title()
+ << sep << m_ui->labelEnvironment->text()
+ << sep << m_ui->labelGdbStartupScript->text()
+ << sep << m_ui->labelGdbWatchdogTimeout->text()
+ << sep << m_ui->checkBoxEnableReverseDebugging->text()
+ << sep << m_ui->checkBoxSkipKnownFrames->text()
+ << sep << m_ui->checkBoxUseMessageBoxForSignals->text()
+ << sep << m_ui->checkBoxAdjustBreakpointLocations->text()
+ << sep << m_ui->groupBoxPluginDebugging->title()
+ << sep << m_ui->radioButtonAllPluginBreakpoints->text()
+ << sep << m_ui->radioButtonSelectedPluginBreakpoints->text()
+ << sep << m_ui->labelSelectedPluginBreakpoints->text()
+ << sep << m_ui->radioButtonNoPluginBreakpoints->text()
+ ;
m_searchKeywords.remove(QLatin1Char('&'));
}
return w;
}
+
void GdbOptionsPage::apply()
{
+ if (!m_ui) // page never shown
+ return;
m_group.apply(Core::ICore::instance()->settings());
- DebuggerSettings::instance()
- ->setGdbBinaryToolChainMap(m_ui.gdbChooserWidget->gdbBinaries());
+ if (m_ui->gdbChooserWidget->isDirty()) {
+ gdbBinariesChanged = true;
+ gdbBinaryToolChainMap = m_ui->gdbChooserWidget->gdbBinaries();
+ m_ui->gdbChooserWidget->clearDirty();
+ }
}
void GdbOptionsPage::finish()
{
+ if (!m_ui) // page never shown
+ return;
+ delete m_ui;
+ m_ui = 0;
m_group.finish();
}
diff --git a/src/plugins/debugger/gdb/gdboptionspage.h b/src/plugins/debugger/gdb/gdboptionspage.h
index 799b025769..7c4a7ccabe 100644
--- a/src/plugins/debugger/gdb/gdboptionspage.h
+++ b/src/plugins/debugger/gdb/gdboptionspage.h
@@ -39,7 +39,6 @@
#include <coreplugin/dialogs/ioptionspage.h>
#include <utils/savedaction.h>
-
namespace Debugger {
namespace Internal {
@@ -62,8 +61,14 @@ public:
static QString settingsId();
+ typedef QMultiMap<QString, int> GdbBinaryToolChainMap;
+ static GdbBinaryToolChainMap gdbBinaryToolChainMap;
+ static bool gdbBinariesChanged;
+ static void readGdbBinarySettings();
+ static void writeGdbBinarySettings();
+
private:
- Ui::GdbOptionsPage m_ui;
+ Ui::GdbOptionsPage *m_ui;
Utils::SavedActionSet m_group;
QString m_searchKeywords;
};
diff --git a/src/plugins/debugger/gdb/localplaingdbadapter.cpp b/src/plugins/debugger/gdb/localplaingdbadapter.cpp
index 77ce4b935d..e91853be54 100644
--- a/src/plugins/debugger/gdb/localplaingdbadapter.cpp
+++ b/src/plugins/debugger/gdb/localplaingdbadapter.cpp
@@ -35,6 +35,7 @@
#include "gdbengine.h"
#include "procinterrupt.h"
+#include "debuggercore.h"
#include "debuggerstringutils.h"
#include <utils/qtcassert.h>
@@ -75,6 +76,11 @@ void LocalPlainGdbAdapter::startAdapter()
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
showMessage(_("TRYING TO START ADAPTER"));
+#ifdef Q_OS_WIN
+ if (!prepareWinCommand())
+ return;
+#endif
+
QStringList gdbArgs;
if (!m_outputCollector.listen()) {
@@ -86,8 +92,8 @@ void LocalPlainGdbAdapter::startAdapter()
if (!startParameters().workingDirectory.isEmpty())
m_gdbProc.setWorkingDirectory(startParameters().workingDirectory);
- if (!startParameters().environment.isEmpty())
- m_gdbProc.setEnvironment(startParameters().environment);
+ if (startParameters().environment.size())
+ m_gdbProc.setEnvironment(startParameters().environment.toStringList());
if (!m_engine->startGdb(gdbArgs)) {
m_outputCollector.shutdown();
@@ -144,7 +150,7 @@ void LocalPlainGdbAdapter::checkForReleaseBuild()
// "30 .debug_info 00087d36 00000000 00000000 0006bbd5 2**0\n"
// " CONTENTS, READONLY, DEBUGGING"
if (ba.contains("Sections:") && !ba.contains(".debug_info")) {
- m_engine->showMessageBox(QMessageBox::Information, "Warning",
+ showMessageBox(QMessageBox::Information, "Warning",
tr("This does not seem to be a \"Debug\" build.\n"
"Setting breakpoints by file name and line number may fail."));
}
diff --git a/src/plugins/debugger/gdb/localplaingdbadapter.h b/src/plugins/debugger/gdb/localplaingdbadapter.h
index 300b9977fd..388c3af0f5 100644
--- a/src/plugins/debugger/gdb/localplaingdbadapter.h
+++ b/src/plugins/debugger/gdb/localplaingdbadapter.h
@@ -35,9 +35,7 @@
#define DEBUGGER_PLAINGDBADAPTER_H
#include "abstractplaingdbadapter.h"
-
-#include "abstractgdbprocess.h"
-
+#include "localgdbprocess.h"
#include <outputcollector.h>
namespace Debugger {
diff --git a/src/plugins/debugger/gdb/pythongdbengine.cpp b/src/plugins/debugger/gdb/pythongdbengine.cpp
index a2fa29a75a..e204f384a9 100644
--- a/src/plugins/debugger/gdb/pythongdbengine.cpp
+++ b/src/plugins/debugger/gdb/pythongdbengine.cpp
@@ -32,9 +32,10 @@
**************************************************************************/
#include "gdbengine.h"
-
+#include "gdbmi.h"
#include "abstractgdbadapter.h"
#include "debuggeractions.h"
+#include "debuggercore.h"
#include "debuggerstringutils.h"
#include "breakhandler.h"
@@ -79,9 +80,9 @@ void GdbEngine::updateLocalsPython(bool tryPartial, const QByteArray &varList)
}
QByteArray options;
- if (theDebuggerBoolSetting(UseDebuggingHelpers))
+ if (debuggerCore()->boolSetting(UseDebuggingHelpers))
options += "fancy,";
- if (theDebuggerBoolSetting(AutoDerefPointers))
+ if (debuggerCore()->boolSetting(AutoDerefPointers))
options += "autoderef,";
if (!qgetenv("QTC_DEBUGGER_PYTHON_VERBOSE").isEmpty())
options += "pe,";
diff --git a/src/plugins/debugger/gdb/remotegdbprocess.cpp b/src/plugins/debugger/gdb/remotegdbprocess.cpp
index a6c72b743f..e301867d1f 100644
--- a/src/plugins/debugger/gdb/remotegdbprocess.cpp
+++ b/src/plugins/debugger/gdb/remotegdbprocess.cpp
@@ -36,6 +36,9 @@
#include "remoteplaingdbadapter.h"
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
+
+#include <QtCore/QFileInfo>
#include <ctype.h>
@@ -46,7 +49,8 @@ namespace Internal {
RemoteGdbProcess::RemoteGdbProcess(const Core::SshConnectionParameters &connParams,
RemotePlainGdbAdapter *adapter, QObject *parent)
- : AbstractGdbProcess(parent), m_connParams(connParams), m_adapter(adapter)
+ : AbstractGdbProcess(parent), m_connParams(connParams),
+ m_state(Inactive), m_adapter(adapter)
{
}
@@ -68,15 +72,25 @@ void RemoteGdbProcess::start(const QString &cmd, const QStringList &args)
{
Q_UNUSED(cmd);
Q_UNUSED(args);
- QTC_ASSERT(m_gdbStarted, return);
+ QTC_ASSERT(m_state == RunningGdb, return);
}
-void RemoteGdbProcess::realStart(const QString &cmd, const QStringList &args)
+void RemoteGdbProcess::realStart(const QString &cmd, const QStringList &args,
+ const QString &executableFilePath)
{
+ QTC_ASSERT(m_state == Inactive, return);
+ setState(Connecting);
+
m_command = cmd;
m_cmdArgs = args;
- m_gdbStarted = false;
+ m_appOutputFileName = "app_output_"
+ + QFileInfo(executableFilePath).fileName().toUtf8();
m_error.clear();
+ m_lastSeqNr.clear();
+ m_currentGdbOutput.clear();
+ m_gdbOutput.clear();
+ m_errorOutput.clear();
+ m_inputToSend.clear();
m_conn = SshConnection::create();
connect(m_conn.data(), SIGNAL(connected()), this, SLOT(handleConnected()));
connect(m_conn.data(), SIGNAL(error(Core::SshError)), this,
@@ -86,8 +100,14 @@ void RemoteGdbProcess::realStart(const QString &cmd, const QStringList &args)
void RemoteGdbProcess::handleConnected()
{
+ if (m_state == Inactive)
+ return;
+
+ QTC_ASSERT(m_state == Connecting, return);
+ setState(CreatingFifo);
+
m_fifoCreator = m_conn->createRemoteProcess( "rm -f "
- + AppOutputFile + " && mkfifo " + AppOutputFile);
+ + m_appOutputFileName + " && mkfifo " + m_appOutputFileName);
connect(m_fifoCreator.data(), SIGNAL(closed(int)), this,
SLOT(handleFifoCreationFinished(int)));
m_fifoCreator->start();
@@ -95,15 +115,22 @@ void RemoteGdbProcess::handleConnected()
void RemoteGdbProcess::handleConnectionError()
{
- emitErrorExit(tr("Connection could not be established."));
+ if (m_state != Inactive)
+ emitErrorExit(tr("Connection failure: %1.").arg(m_conn->errorString()));
}
void RemoteGdbProcess::handleFifoCreationFinished(int exitStatus)
{
+ if (m_state == Inactive)
+ return;
+ QTC_ASSERT(m_state == CreatingFifo, return);
+
if (exitStatus != SshRemoteProcess::ExitedNormally) {
emitErrorExit(tr("Could not create FIFO."));
} else {
- m_appOutputReader = m_conn->createRemoteProcess("cat " + AppOutputFile);
+ setState(StartingFifoReader);
+ m_appOutputReader = m_conn->createRemoteProcess("cat "
+ + m_appOutputFileName + " && rm -f " + m_appOutputFileName);
connect(m_appOutputReader.data(), SIGNAL(started()), this,
SLOT(handleAppOutputReaderStarted()));
connect(m_appOutputReader.data(), SIGNAL(closed(int)), this,
@@ -114,13 +141,18 @@ void RemoteGdbProcess::handleFifoCreationFinished(int exitStatus)
void RemoteGdbProcess::handleAppOutputReaderStarted()
{
+ if (m_state == Inactive)
+ return;
+ QTC_ASSERT(m_state == StartingFifoReader, return);
+ setState(StartingGdb);
+
connect(m_appOutputReader.data(), SIGNAL(outputAvailable(QByteArray)),
this, SLOT(handleAppOutput(QByteArray)));
QByteArray cmdLine = "DISPLAY=:0.0 " + m_command.toUtf8() + ' '
- + m_cmdArgs.join(QLatin1String(" ")).toUtf8()
- + " -tty=" + AppOutputFile;
+ + Utils::QtcProcess::joinArgsUnix(m_cmdArgs).toUtf8()
+ + " -tty=" + m_appOutputFileName;
if (!m_wd.isEmpty())
- cmdLine.prepend("cd " + m_wd.toUtf8() + " && ");
+ cmdLine.prepend("cd " + Utils::QtcProcess::quoteArgUnix(m_wd).toUtf8() + " && ");
m_gdbProc = m_conn->createRemoteProcess(cmdLine);
connect(m_gdbProc.data(), SIGNAL(started()), this,
SLOT(handleGdbStarted()));
@@ -141,38 +173,48 @@ void RemoteGdbProcess::handleAppOutputReaderFinished(int exitStatus)
void RemoteGdbProcess::handleGdbStarted()
{
- m_gdbStarted = true;
+ if (m_state == Inactive)
+ return;
+ QTC_ASSERT(m_state == StartingGdb, return);
+ setState(RunningGdb);
emit started();
}
void RemoteGdbProcess::handleGdbFinished(int exitStatus)
{
+ if (m_state == Inactive)
+ return;
+ QTC_ASSERT(m_state == RunningGdb, return);
+
switch (exitStatus) {
case SshRemoteProcess::FailedToStart:
m_error = tr("Remote gdb failed to start.");
+ setState(Inactive);
emit startFailed();
break;
case SshRemoteProcess::KilledBySignal:
emitErrorExit(tr("Remote gdb crashed."));
break;
case SshRemoteProcess::ExitedNormally:
- emit finished(m_gdbProc->exitCode(), QProcess::NormalExit);
+ const int exitCode = m_gdbProc->exitCode();
+ setState(Inactive);
+ emit finished(exitCode, QProcess::NormalExit);
break;
}
- disconnect(m_conn.data(), 0, this, 0);
- m_gdbProc = SshRemoteProcess::Ptr();
- m_appOutputReader = SshRemoteProcess::Ptr();
- m_conn->disconnectFromHost();
}
bool RemoteGdbProcess::waitForStarted()
{
- return m_error.isEmpty();
+ if (m_state == Inactive)
+ return false;
+ QTC_ASSERT(m_state == RunningGdb, return false);
+ return true;
}
qint64 RemoteGdbProcess::write(const QByteArray &data)
{
- if (!m_gdbStarted || !m_inputToSend.isEmpty() || !m_lastSeqNr.isEmpty())
+ if (m_state != RunningGdb || !m_inputToSend.isEmpty()
+ || !m_lastSeqNr.isEmpty())
m_inputToSend.enqueue(data);
else
sendInput(data);
@@ -181,13 +223,19 @@ qint64 RemoteGdbProcess::write(const QByteArray &data)
void RemoteGdbProcess::kill()
{
- SshRemoteProcess::Ptr killProc
- = m_conn->createRemoteProcess("pkill -SIGKILL -x gdb");
- killProc->start();
+ if (m_state == RunningGdb) {
+ SshRemoteProcess::Ptr killProc
+ = m_conn->createRemoteProcess("pkill -SIGKILL -x gdb");
+ killProc->start();
+ } else {
+ setState(Inactive);
+ }
}
void RemoteGdbProcess::interruptInferior()
{
+ QTC_ASSERT(m_state == RunningGdb, return);
+
SshRemoteProcess::Ptr intProc
= m_conn->createRemoteProcess("pkill -x -SIGINT gdb");
intProc->start();
@@ -195,7 +243,11 @@ void RemoteGdbProcess::interruptInferior()
QProcess::ProcessState RemoteGdbProcess::state() const
{
- return m_gdbStarted ? QProcess::Running : QProcess::Starting;
+ switch (m_state) {
+ case RunningGdb: return QProcess::Running;
+ case Inactive: return QProcess::NotRunning;
+ default: return QProcess::Starting;
+ }
}
QString RemoteGdbProcess::errorString() const
@@ -205,6 +257,10 @@ QString RemoteGdbProcess::errorString() const
void RemoteGdbProcess::handleGdbOutput(const QByteArray &output)
{
+ if (m_state == Inactive)
+ return;
+ QTC_ASSERT(m_state == RunningGdb, return);
+
// TODO: Carriage return removal still necessary?
m_currentGdbOutput += removeCarriageReturn(output);
#if 0
@@ -267,6 +323,8 @@ int RemoteGdbProcess::findAnchor(const QByteArray &data) const
void RemoteGdbProcess::sendInput(const QByteArray &data)
{
+ QTC_ASSERT(m_state == RunningGdb, return);
+
int pos;
for (pos = 0; pos < data.size(); ++pos)
if (!isdigit(data.at(pos)))
@@ -277,13 +335,16 @@ void RemoteGdbProcess::sendInput(const QByteArray &data)
void RemoteGdbProcess::handleAppOutput(const QByteArray &output)
{
- m_adapter->handleApplicationOutput(output);
+ if (m_state == RunningGdb)
+ m_adapter->handleApplicationOutput(output);
}
void RemoteGdbProcess::handleErrOutput(const QByteArray &output)
{
- m_errorOutput += output;
- emit readyReadStandardError();
+ if (m_state == RunningGdb) {
+ m_errorOutput += output;
+ emit readyReadStandardError();
+ }
}
QByteArray RemoteGdbProcess::removeCarriageReturn(const QByteArray &data)
@@ -301,12 +362,35 @@ void RemoteGdbProcess::emitErrorExit(const QString &error)
{
if (m_error.isEmpty()) {
m_error = error;
+ setState(Inactive);
emit finished(-1, QProcess::CrashExit);
}
}
+void RemoteGdbProcess::setState(State newState)
+{
+ if (m_state == newState)
+ return;
+ m_state = newState;
+ if (m_state == Inactive) {
+ if (m_gdbProc) {
+ disconnect(m_gdbProc.data(), 0, this, 0);
+ m_gdbProc = SshRemoteProcess::Ptr();
+ }
+ if (m_appOutputReader) {
+ disconnect(m_appOutputReader.data(), 0, this, 0);
+ m_appOutputReader = SshRemoteProcess::Ptr();
+ }
+ if (m_fifoCreator) {
+ disconnect(m_fifoCreator.data(), 0, this, 0);
+ m_fifoCreator = SshRemoteProcess::Ptr();
+ }
+ disconnect(m_conn.data(), 0, this, 0);
+ m_conn->disconnectFromHost();
+ }
+}
+
const QByteArray RemoteGdbProcess::CtrlC = QByteArray(1, 0x3);
-const QByteArray RemoteGdbProcess::AppOutputFile("app_output");
} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/gdb/remotegdbprocess.h b/src/plugins/debugger/gdb/remotegdbprocess.h
index 3dc97800ca..a0317374d8 100644
--- a/src/plugins/debugger/gdb/remotegdbprocess.h
+++ b/src/plugins/debugger/gdb/remotegdbprocess.h
@@ -71,7 +71,8 @@ public:
virtual void setWorkingDirectory(const QString &dir);
void interruptInferior();
- void realStart(const QString &cmd, const QStringList &args);
+ void realStart(const QString &cmd, const QStringList &args,
+ const QString &executableFilePath);
static const QByteArray CtrlC;
@@ -92,14 +93,18 @@ private slots:
void handleErrOutput(const QByteArray &output);
private:
+ enum State {
+ Inactive, Connecting, CreatingFifo, StartingFifoReader,
+ StartingGdb, RunningGdb
+ };
+
static QByteArray readerCmdLine(const QByteArray &file);
int findAnchor(const QByteArray &data) const;
void sendInput(const QByteArray &data);
QByteArray removeCarriageReturn(const QByteArray &data);
void emitErrorExit(const QString &error);
-
- static const QByteArray AppOutputFile;
+ void setState(State newState);
Core::SshConnectionParameters m_connParams;
Core::SshConnection::Ptr m_conn;
@@ -115,7 +120,8 @@ private:
QByteArray m_currentGdbOutput;
QByteArray m_lastSeqNr;
QString m_error;
- bool m_gdbStarted;
+ QByteArray m_appOutputFileName;
+ State m_state;
RemotePlainGdbAdapter *m_adapter;
};
diff --git a/src/plugins/debugger/gdb/remotegdbserveradapter.cpp b/src/plugins/debugger/gdb/remotegdbserveradapter.cpp
index 1957734e75..0afddf1854 100644
--- a/src/plugins/debugger/gdb/remotegdbserveradapter.cpp
+++ b/src/plugins/debugger/gdb/remotegdbserveradapter.cpp
@@ -33,12 +33,14 @@
#include "remotegdbserveradapter.h"
+#include "debuggercore.h"
#include "debuggerstringutils.h"
#include "gdbengine.h"
+#include "gdbmi.h"
#include <utils/qtcassert.h>
#include <utils/fancymainwindow.h>
-#include <projectexplorer/toolchain.h>
+#include <projectexplorer/toolchaintype.h>
#include <QtCore/QFileInfo>
#include <QtGui/QMessageBox>
@@ -61,26 +63,26 @@ RemoteGdbServerAdapter::RemoteGdbServerAdapter(GdbEngine *engine, int toolChainT
m_toolChainType(toolChainType)
{
connect(&m_uploadProc, SIGNAL(error(QProcess::ProcessError)),
- this, SLOT(uploadProcError(QProcess::ProcessError)));
+ SLOT(uploadProcError(QProcess::ProcessError)));
connect(&m_uploadProc, SIGNAL(readyReadStandardOutput()),
- this, SLOT(readUploadStandardOutput()));
+ SLOT(readUploadStandardOutput()));
connect(&m_uploadProc, SIGNAL(readyReadStandardError()),
- this, SLOT(readUploadStandardError()));
- connect(&m_uploadProc, SIGNAL(finished(int)), this,
+ SLOT(readUploadStandardError()));
+ connect(&m_uploadProc, SIGNAL(finished(int)),
SLOT(uploadProcFinished()));
}
AbstractGdbAdapter::DumperHandling RemoteGdbServerAdapter::dumperHandling() const
{
switch (m_toolChainType) {
- case ProjectExplorer::ToolChain::MinGW:
- case ProjectExplorer::ToolChain::MSVC:
- case ProjectExplorer::ToolChain::WINCE:
- case ProjectExplorer::ToolChain::WINSCW:
- case ProjectExplorer::ToolChain::GCCE:
- case ProjectExplorer::ToolChain::RVCT_ARMV5:
- case ProjectExplorer::ToolChain::RVCT_ARMV6:
- case ProjectExplorer::ToolChain::GCC_MAEMO:
+ case ProjectExplorer::ToolChain_MinGW:
+ case ProjectExplorer::ToolChain_MSVC:
+ case ProjectExplorer::ToolChain_WINCE:
+ case ProjectExplorer::ToolChain_WINSCW:
+ case ProjectExplorer::ToolChain_GCCE:
+ case ProjectExplorer::ToolChain_RVCT2_ARMV5:
+ case ProjectExplorer::ToolChain_RVCT2_ARMV6:
+ case ProjectExplorer::ToolChain_GCC_MAEMO:
return DumperLoadedByGdb;
default:
break;
@@ -98,7 +100,7 @@ void RemoteGdbServerAdapter::startAdapter()
}
if (startParameters().serverStartScript.isEmpty()) {
showMessage(_("No server start script given. "), StatusBar);
- emit requestSetup();
+ m_engine->requestRemoteSetup();
} else {
m_uploadProc.start(_("/bin/sh ") + startParameters().serverStartScript);
m_uploadProc.waitForStarted();
@@ -136,7 +138,7 @@ void RemoteGdbServerAdapter::uploadProcError(QProcess::ProcessError error)
}
showMessage(msg, StatusBar);
- DebuggerEngine::showMessageBox(QMessageBox::Critical, tr("Error"), msg);
+ showMessageBox(QMessageBox::Critical, tr("Error"), msg);
}
void RemoteGdbServerAdapter::readUploadStandardOutput()
@@ -161,7 +163,7 @@ void RemoteGdbServerAdapter::uploadProcFinished()
&& m_uploadProc.exitCode() == 0)
handleSetupDone();
else
- handleSetupFailed(m_uploadProc.errorString());
+ handleRemoteSetupFailed(m_uploadProc.errorString());
}
void RemoteGdbServerAdapter::setupInferior()
@@ -175,12 +177,15 @@ void RemoteGdbServerAdapter::setupInferior()
}
const QByteArray sysRoot = startParameters().sysRoot.toLocal8Bit();
const QByteArray remoteArch = startParameters().remoteArchitecture.toLatin1();
+ const QByteArray gnuTarget = startParameters().gnuTarget.toLatin1();
const QByteArray solibPath =
QFileInfo(startParameters().dumperLibrary).path().toLocal8Bit();
- const QString args = startParameters().processArgs.join(_(" "));
+ const QString args = startParameters().processArgs;
if (!remoteArch.isEmpty())
m_engine->postCommand("set architecture " + remoteArch);
+ if (!gnuTarget.isEmpty())
+ m_engine->postCommand("set gnutarget " + gnuTarget);
if (!sysRoot.isEmpty())
m_engine->postCommand("set sysroot " + sysRoot);
if (!solibPath.isEmpty())
@@ -190,7 +195,7 @@ void RemoteGdbServerAdapter::setupInferior()
// This has to be issued before 'target remote'. On pre-7.0 the
// command is not present and will result in ' No symbol table is
- // loaded. Use the "file" command.' as gdb tries to set the
+ // loaded. Use the "file" command.' as gdb tries to set the
// value of a variable with name 'target-async'.
//
// Testing with -list-target-features which was introduced at
@@ -272,9 +277,21 @@ void RemoteGdbServerAdapter::runEngine()
void RemoteGdbServerAdapter::interruptInferior()
{
- // FIXME: On some gdb versions like git 170ffa5d7dd this produces
- // >810^error,msg="mi_cmd_exec_interrupt: Inferior not executing."
- m_engine->postCommand("-exec-interrupt", GdbEngine::Immediate);
+ QTC_ASSERT(state() == InferiorStopRequested, qDebug() << state());
+ m_engine->postCommand("-exec-interrupt", GdbEngine::Immediate,
+ CB(handleInterruptInferior));
+}
+
+void RemoteGdbServerAdapter::handleInterruptInferior(const GdbResponse &response)
+{
+ if (response.resultClass == GdbResultDone) {
+ // The gdb server will trigger extra output that we will pick up
+ // to do a proper state transition.
+ } else {
+ // FIXME: On some gdb versions like git 170ffa5d7dd this produces
+ // >810^error,msg="mi_cmd_exec_interrupt: Inferior not executing."
+ m_engine->notifyInferiorStopOk();
+ }
}
void RemoteGdbServerAdapter::shutdownInferior()
@@ -287,15 +304,30 @@ void RemoteGdbServerAdapter::shutdownAdapter()
m_engine->notifyAdapterShutdownOk();
}
-void RemoteGdbServerAdapter::handleSetupDone()
+void RemoteGdbServerAdapter::handleRemoteSetupDone(int gdbServerPort, int qmlPort)
{
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
+ if (qmlPort != -1)
+ startParameters().qmlServerPort = qmlPort;
+ if (gdbServerPort != -1) {
+ QString &rc = startParameters().remoteChannel;
+ const int sepIndex = rc.lastIndexOf(QLatin1Char(':'));
+ if (sepIndex != -1) {
+ rc.replace(sepIndex + 1, rc.count() - sepIndex - 1,
+ QString::number(gdbServerPort));
+ }
+ }
+ handleSetupDone();
+}
+
+void RemoteGdbServerAdapter::handleSetupDone()
+{
if (m_engine->startGdb(QStringList(), startParameters().debuggerCommand))
m_engine->handleAdapterStarted();
}
-void RemoteGdbServerAdapter::handleSetupFailed(const QString &reason)
+void RemoteGdbServerAdapter::handleRemoteSetupFailed(const QString &reason)
{
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
diff --git a/src/plugins/debugger/gdb/remotegdbserveradapter.h b/src/plugins/debugger/gdb/remotegdbserveradapter.h
index 45871e8ac7..378a3831a5 100644
--- a/src/plugins/debugger/gdb/remotegdbserveradapter.h
+++ b/src/plugins/debugger/gdb/remotegdbserveradapter.h
@@ -35,8 +35,7 @@
#define DEBUGGER_REMOTEGDBADAPTER_H
#include "abstractgdbadapter.h"
-
-#include "abstractgdbprocess.h"
+#include "localgdbprocess.h"
namespace Debugger {
namespace Internal {
@@ -53,8 +52,6 @@ class RemoteGdbServerAdapter : public AbstractGdbAdapter
public:
RemoteGdbServerAdapter(GdbEngine *engine, int toolChainType, QObject *parent = 0);
- void handleSetupDone();
- void handleSetupFailed(const QString &reason);
private:
DumperHandling dumperHandling() const;
@@ -68,6 +65,8 @@ private:
AbstractGdbProcess *gdbProc() { return &m_gdbProc; }
+ void handleSetupDone();
+
signals:
/*
* For "external" clients of a debugger run control that need to do
@@ -85,10 +84,14 @@ private:
Q_SLOT void uploadProcError(QProcess::ProcessError error);
Q_SLOT void uploadProcFinished();
+ virtual void handleRemoteSetupDone(int gdbServerPort, int qmlPort);
+ virtual void handleRemoteSetupFailed(const QString &reason);
+
void handleSetTargetAsync(const GdbResponse &response);
void handleFileExecAndSymbols(const GdbResponse &response);
void callTargetRemote();
void handleTargetRemote(const GdbResponse &response);
+ void handleInterruptInferior(const GdbResponse &response);
const int m_toolChainType;
diff --git a/src/plugins/debugger/gdb/remoteplaingdbadapter.cpp b/src/plugins/debugger/gdb/remoteplaingdbadapter.cpp
index e35551729c..46823086c8 100644
--- a/src/plugins/debugger/gdb/remoteplaingdbadapter.cpp
+++ b/src/plugins/debugger/gdb/remoteplaingdbadapter.cpp
@@ -32,12 +32,12 @@
**************************************************************************/
#include "remoteplaingdbadapter.h"
+#include "gdbengine.h"
#include <debugger/debuggeractions.h>
#include <debugger/debuggerstringutils.h>
#include <utils/qtcassert.h>
-
namespace Debugger {
namespace Internal {
@@ -54,8 +54,7 @@ void RemotePlainGdbAdapter::startAdapter()
{
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
showMessage(QLatin1String("TRYING TO START ADAPTER"));
-
- emit requestSetup();
+ m_engine->requestRemoteSetup();
}
void RemotePlainGdbAdapter::setupInferior()
@@ -105,16 +104,20 @@ void RemotePlainGdbAdapter::shutdownAdapter()
m_engine->notifyAdapterShutdownOk();
}
-void RemotePlainGdbAdapter::handleSetupDone()
+void RemotePlainGdbAdapter::handleRemoteSetupDone(int gdbServerPort, int qmlPort)
{
+ Q_UNUSED(gdbServerPort);
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
+ if (qmlPort != -1)
+ startParameters().qmlServerPort = qmlPort;
if (!startParameters().workingDirectory.isEmpty())
m_gdbProc.setWorkingDirectory(startParameters().workingDirectory);
- if (!startParameters().environment.isEmpty())
- m_gdbProc.setEnvironment(startParameters().environment);
+ if (startParameters().environment.size())
+ m_gdbProc.setEnvironment(startParameters().environment.toStringList());
m_gdbProc.realStart(m_engine->startParameters().debuggerCommand,
- QStringList() << QLatin1String("-i") << QLatin1String("mi"));
+ QStringList() << QLatin1String("-i") << QLatin1String("mi"),
+ m_engine->startParameters().executable);
}
void RemotePlainGdbAdapter::handleGdbStarted()
@@ -129,7 +132,7 @@ void RemotePlainGdbAdapter::handleGdbStartFailed()
m_engine->handleAdapterStartFailed(m_gdbProc.errorString());
}
-void RemotePlainGdbAdapter::handleSetupFailed(const QString &reason)
+void RemotePlainGdbAdapter::handleRemoteSetupFailed(const QString &reason)
{
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
diff --git a/src/plugins/debugger/gdb/remoteplaingdbadapter.h b/src/plugins/debugger/gdb/remoteplaingdbadapter.h
index f623242c46..137fe400ed 100644
--- a/src/plugins/debugger/gdb/remoteplaingdbadapter.h
+++ b/src/plugins/debugger/gdb/remoteplaingdbadapter.h
@@ -47,11 +47,6 @@ class RemotePlainGdbAdapter : public AbstractPlainGdbAdapter
public:
friend class RemoteGdbProcess;
explicit RemotePlainGdbAdapter(GdbEngine *engine, QObject *parent = 0);
- void handleSetupDone();
- void handleSetupFailed(const QString &reason);
-
-signals:
- void requestSetup();
private slots:
void handleGdbStarted();
@@ -63,6 +58,8 @@ private:
void interruptInferior();
void shutdownInferior();
void shutdownAdapter();
+ void handleRemoteSetupDone(int gdbServerPort, int qmlPort);
+ void handleRemoteSetupFailed(const QString &reason);
AbstractGdbProcess *gdbProc() { return &m_gdbProc; }
DumperHandling dumperHandling() const { return DumperLoadedByGdbPreload; }
diff --git a/src/plugins/debugger/gdb/symbian.cpp b/src/plugins/debugger/gdb/symbian.cpp
index e49b0f4679..18a4a0fb5c 100644
--- a/src/plugins/debugger/gdb/symbian.cpp
+++ b/src/plugins/debugger/gdb/symbian.cpp
@@ -40,6 +40,7 @@
#include <QtCore/QDebug>
#include <QtCore/QTextStream>
+#include <QtCore/QFileInfo>
namespace Debugger {
namespace Internal {
@@ -207,14 +208,12 @@ Snapshot::Snapshot()
void Snapshot::reset()
{
+ MEMORY_DEBUG("RESET SNAPSHOT MEMORY INITIALLY: " << memory.size() << " BLOCK LEFT");
for (Memory::Iterator it = memory.begin(); it != memory.end(); ) {
- if (isReadOnly(it.key())) {
- MEMORY_DEBUG("KEEPING READ-ONLY RANGE" << it.key());
- ++it;
- } else {
- it = memory.erase(it);
- }
+ MEMORY_DEBUG("EXAMINING " << it.key());
+ it = memory.erase(it);
}
+ MEMORY_DEBUG("RESET SNAPSHOT MEMORY FINALLY: " << memory.size() << " BLOCK LEFT");
const int threadCount = threadInfo.size();
for (int i =0; i < threadCount; i++) {
@@ -470,7 +469,7 @@ QByteArray Snapshot::memoryReadLogMessage(uint addr, uint threadId, bool verbose
logMsg += " length ";
logMsg += QByteArray::number(ba.size());
logMsg += " :";
- logMsg += trk::stringFromArray(ba, 16).toAscii();
+ logMsg += trk::stringFromArray(ba, ba.size()).toAscii();
}
return logMsg;
}
@@ -550,6 +549,83 @@ QVector<QByteArray> gdbStartupSequence()
return s;
}
+// Local symbol file handling
+
+enum { symDebug = 0 };
+
+// Build complete file name of a local sym file from DLL
+// 'QtCore.dll' to 'c:\\foo\QtCore.dll.sym'.
+
+static inline QString symFileName(const QString &folder,
+ const QString &libName)
+{
+ QString fileName = folder;
+ fileName.append(QLatin1Char('/'));
+ fileName.append(libName);
+ fileName.append(QLatin1String(".sym"));
+ return fileName;
+}
+
+// Look up in local symbol file matching remote library loaded in
+// cache pointed to by environmentname or in standard location
+// (next to application.sym file).
+QString localSymFileForLibrary(const QByteArray &libName,
+ // urel/udeb: exe directory
+ const QString &standardSymDirectory)
+{
+ // Check
+ const QByteArray envSymFileCacheDirectory = qgetenv("QTC_SYMBIAN_SYMBOLFILE_CACHE");
+ if (envSymFileCacheDirectory.isEmpty() && standardSymDirectory.isEmpty())
+ return QString();
+ // Base name
+ int lastSlashPos = libName.lastIndexOf('/');
+ if (lastSlashPos == -1)
+ lastSlashPos = libName.lastIndexOf('\\');
+ const QString libBaseName = QString::fromLatin1(lastSlashPos != - 1 ? libName.mid(lastSlashPos + 1) : libName);
+ // Check environment variable
+ if (!envSymFileCacheDirectory.isEmpty()) {
+ const QFileInfo envFi(symFileName(QString::fromLatin1(envSymFileCacheDirectory), libBaseName));
+ if (symDebug)
+ qDebug("SYM-ENV: %s exists %d\n", qPrintable(envFi.absoluteFilePath()), envFi.isFile());
+ if (envFi.isFile())
+ return envFi.absoluteFilePath();
+ }
+ // Check standard location
+ if (!standardSymDirectory.isEmpty()) {
+ const QFileInfo standardFi(symFileName(standardSymDirectory, libBaseName));
+ if (symDebug)
+ qDebug("SYM-STANDARD: %s exists %d\n", qPrintable(standardFi.absoluteFilePath()), standardFi.isFile());
+ if (standardFi.isFile())
+ return standardFi.absoluteFilePath();
+ }
+ return QString();
+}
+
+// Return a load command for a local symbol file for a library with address.
+QByteArray symFileLoadCommand(const QString &symFileNameIn,
+ quint64 code, quint64 data)
+{
+ QByteArray symFileName = symFileNameIn.toLatin1();
+ symFileName.replace('\\', '/'); // gdb wants forward slashes
+ QByteArray command = "add-symbol-file \"";
+ command += symFileName;
+ command += "\" 0x";
+ command += QByteArray::number(code, 16);
+ if (data) {
+ command += " -s .data 0x";
+ command += QByteArray::number(data, 16);
+ }
+ return command;
+}
+
+QString msgLoadLocalSymFile(const QString &symFileName,
+ const QByteArray &libName, quint64 code)
+{
+ return QString::fromAscii("Loading symbol file '%1' for '%2' at 0x%3").
+ arg(symFileName, QString::fromLatin1(libName)).
+ arg(code, 0, 16);
+}
+
} // namespace Symbian
// Generic gdb server helpers: Read address/length off a memory
diff --git a/src/plugins/debugger/gdb/symbian.h b/src/plugins/debugger/gdb/symbian.h
index 988c6aa613..122b845a27 100644
--- a/src/plugins/debugger/gdb/symbian.h
+++ b/src/plugins/debugger/gdb/symbian.h
@@ -88,7 +88,7 @@ namespace Symbian {
enum CodeMode
{
ArmMode = 0,
- ThumbMode,
+ ThumbMode
};
enum TargetConstants
@@ -201,6 +201,16 @@ extern const char *gdbArchitectureXml;
QVector<QByteArray> gdbStartupSequence();
+// Look up in symbol file matching library name in local cache
+QString localSymFileForLibrary(const QByteArray &libName,
+ const QString &standardSymDirectory = QString());
+// Return a load command for a local symbol file for a library
+QByteArray symFileLoadCommand(const QString &symFileName, quint64 code,
+ quint64 data = 0);
+// Utility message
+QString msgLoadLocalSymFile(const QString &symFileName,
+ const QByteArray &libName, quint64 code);
+
} // namespace Symbian
// Generic gdb server helpers: read 'm','X' commands.
@@ -213,6 +223,6 @@ QPair<quint64, unsigned> parseGdbSetBreakpointRequest(const QByteArray &cmd);
} // namespace Internal
} // namespace Debugger
-Q_DECLARE_METATYPE(Debugger::Internal::MemoryRange);
+Q_DECLARE_METATYPE(Debugger::Internal::MemoryRange)
#endif // SYMBIANUTILS_H
diff --git a/src/plugins/debugger/gdb/tcftrkgdbadapter.cpp b/src/plugins/debugger/gdb/tcftrkgdbadapter.cpp
index 5cf2b2cd05..993f1ae4cf 100644
--- a/src/plugins/debugger/gdb/tcftrkgdbadapter.cpp
+++ b/src/plugins/debugger/gdb/tcftrkgdbadapter.cpp
@@ -32,12 +32,13 @@
**************************************************************************/
#include "tcftrkgdbadapter.h"
-
#include "tcftrkdevice.h"
#include "trkutils.h"
+#include "gdbmi.h"
#include "registerhandler.h"
#include "threadshandler.h"
+#include "debuggercore.h"
#include "debuggeractions.h"
#include "debuggerstringutils.h"
#include "watchutils.h"
@@ -47,6 +48,7 @@
#include <utils/qtcassert.h>
#include <utils/savedaction.h>
+#include <utils/qtcprocess.h>
#include <QtCore/QTimer>
#include <QtCore/QDir>
@@ -139,9 +141,9 @@ TcfTrkGdbAdapter::TcfTrkGdbAdapter(GdbEngine *engine) :
#endif
m_gdbServerName = _("127.0.0.1:%1").arg(2222 + portOffset);
- setVerbose(theDebuggerBoolSetting(VerboseLog) ? 1 : 0);
+ setVerbose(debuggerCore()->boolSetting(VerboseLog) ? 1 : 0);
- connect(theDebuggerAction(VerboseLog), SIGNAL(valueChanged(QVariant)),
+ connect(debuggerCore()->action(VerboseLog), SIGNAL(valueChanged(QVariant)),
this, SLOT(setVerbose(QVariant)));
connect(m_trkDevice, SIGNAL(error(QString)),
this, SLOT(tcftrkDeviceError(QString)));
@@ -213,6 +215,16 @@ void TcfTrkGdbAdapter::handleTcfTrkRunControlModuleLoadContextSuspendedEvent(con
library.dataseg = minfo.dataAddress;
library.pid = RunControlContext::processIdFromTcdfId(se.id());
m_session.libraries.push_back(library);
+ // Load local symbol file into gdb provided there is one
+ if (library.codeseg) {
+ const QString localSymFileName = Symbian::localSymFileForLibrary(library.name,
+ m_symbolFileFolder);
+ if (!localSymFileName.isEmpty()) {
+ showMessage(Symbian::msgLoadLocalSymFile(localSymFileName, library.name, library.codeseg), LogMisc);
+ m_engine->postCommand(Symbian::symFileLoadCommand(localSymFileName, library.codeseg, library.dataseg));
+ } // has local sym
+ } // code seg
+
} else {
const int index = m_session.modules.indexOf(moduleName);
if (index != -1) {
@@ -320,8 +332,9 @@ void TcfTrkGdbAdapter::tcftrkEvent(const TcfTrkEvent &e)
static_cast<const TcfTrkRunControlContextSuspendedEvent &>(e);
const unsigned threadId = RunControlContext::threadIdFromTcdfId(se.id());
const QString reason = QString::fromUtf8(se.reasonID());
- showMessage(_("Reset snapshot (Thread 0x%1 stopped: '%2')").
- arg(threadId, 0, 16).arg(reason));
+ const QString message = QString::fromUtf8(se.message()).replace(QLatin1String("\n"), QLatin1String(", "));
+ showMessage(_("Thread %1 stopped: '%2': %3").
+ arg(threadId).arg(reason, message), LogMisc);
// Stopped in a new thread: Add.
m_snapshot.reset();
m_session.tid = threadId;
@@ -630,11 +643,7 @@ void TcfTrkGdbAdapter::handleGdbServerCommand(const QByteArray &cmd)
else if (cmd == "k" || cmd.startsWith("vKill")) {
// Kill inferior process
logMessage(msgGdbPacket(QLatin1String("kill")));
- // Requires id of main thread to terminate.
- // Note that calling 'Settings|set|removeExecutable' crashes TCF TRK,
- // so, it is apparently not required.
- m_trkDevice->sendRunControlTerminateCommand(TcfTrkCallback(),
- mainThreadContextId());
+ sendRunControlTerminateCommand();
}
else if (cmd.startsWith('m')) {
@@ -943,6 +952,28 @@ void TcfTrkGdbAdapter::handleGdbServerCommand(const QByteArray &cmd)
}
}
+void TcfTrkGdbAdapter::sendRunControlTerminateCommand()
+{
+ // Requires id of main thread to terminate.
+ // Note that calling 'Settings|set|removeExecutable' crashes TCF TRK,
+ // so, it is apparently not required.
+ m_trkDevice->sendRunControlTerminateCommand(TcfTrkCallback(this, &TcfTrkGdbAdapter::handleRunControlTerminate),
+ mainThreadContextId());
+}
+
+void TcfTrkGdbAdapter::handleRunControlTerminate(const tcftrk::TcfTrkCommandResult &)
+{
+ QString msg = QString::fromLatin1("CODA disconnected");
+ const bool emergencyShutdown = m_gdbProc.state() != QProcess::Running;
+ if (emergencyShutdown)
+ msg += QString::fromLatin1(" (emergency shutdown");
+ logMessage(msg);
+ if (emergencyShutdown) {
+ cleanup();
+ m_engine->notifyAdapterShutdownOk();
+ }
+}
+
void TcfTrkGdbAdapter::gdbSetCurrentThread(const QByteArray &cmd, const char *why)
{
// Thread ID from Hg/Hc commands: '-1': All, '0': arbitrary, else hex thread id.
@@ -973,8 +1004,10 @@ void TcfTrkGdbAdapter::startAdapter()
// Retrieve parameters
const DebuggerStartParameters &parameters = startParameters();
m_remoteExecutable = parameters.executable;
- m_remoteArguments = parameters.processArgs;
+ m_remoteArguments = Utils::QtcProcess::splitArgs(parameters.processArgs);
m_symbolFile = parameters.symbolFileName;
+ if (!m_symbolFile.isEmpty())
+ m_symbolFileFolder = QFileInfo(m_symbolFile).absolutePath();
QPair<QString, unsigned short> tcfTrkAddress;
@@ -985,15 +1018,15 @@ void TcfTrkGdbAdapter::startAdapter()
if (debug)
qDebug() << parameters.processArgs;
// Fixme: 1 of 3 testing hacks.
- if (parameters.processArgs.size() < 5 || parameters.processArgs.at(0) != _("@tcf@")) {
+ if (m_remoteArguments.size() < 5 || m_remoteArguments.at(0) != __("@tcf@")) {
m_engine->handleAdapterStartFailed(_("Parameter error"), QString());
return;
}
- m_remoteExecutable = parameters.processArgs.at(1);
- m_uid = parameters.processArgs.at(2).toUInt(0, 16);
- m_symbolFile = parameters.processArgs.at(3);
- tcfTrkAddress = splitIpAddressSpec(parameters.processArgs.at(4), 1534);
+ m_remoteExecutable = m_remoteArguments.at(1);
+ m_uid = m_remoteArguments.at(2).toUInt(0, 16);
+ m_symbolFile = m_remoteArguments.at(3);
+ tcfTrkAddress = splitIpAddressSpec(m_remoteArguments.at(4), 1534);
m_remoteArguments.clear();
// Unixish gdbs accept only forward slashes
@@ -1045,6 +1078,7 @@ void TcfTrkGdbAdapter::setupInferior()
void TcfTrkGdbAdapter::addThread(unsigned id)
{
+ showMessage(QString::fromLatin1("Thread %1 reported").arg(id), LogMisc);
// Make thread known, register as main if it is the first one.
if (m_snapshot.indexOfThread(id) == -1) {
m_snapshot.addThread(id);
@@ -1156,8 +1190,16 @@ void TcfTrkGdbAdapter::shutdownInferior()
void TcfTrkGdbAdapter::shutdownAdapter()
{
- cleanup();
- m_engine->notifyAdapterShutdownOk();
+ if (m_gdbProc.state() == QProcess::Running) {
+ cleanup();
+ m_engine->notifyAdapterShutdownOk();
+ } else {
+ // Something is wrong, gdb crashed. Kill debuggee (see handleDeleteProcess2)
+ if (m_trkDevice->device()->isOpen()) {
+ logMessage("Emergency shutdown of CODA", LogError);
+ sendRunControlTerminateCommand();
+ }
+ }
}
void TcfTrkGdbAdapter::trkReloadRegisters()
diff --git a/src/plugins/debugger/gdb/tcftrkgdbadapter.h b/src/plugins/debugger/gdb/tcftrkgdbadapter.h
index 1e3fc0aed6..1af1110b8e 100644
--- a/src/plugins/debugger/gdb/tcftrkgdbadapter.h
+++ b/src/plugins/debugger/gdb/tcftrkgdbadapter.h
@@ -35,7 +35,7 @@
#define DEBUGGER_TCFTRKGDBADAPTER_H
#include "abstractgdbadapter.h"
-
+#include "localgdbprocess.h"
#include "callback.h"
#include "trkutils.h"
#include "symbian.h"
@@ -112,6 +112,8 @@ private:
void interruptInferior();
void shutdownInferior();
void shutdownAdapter();
+ void sendRunControlTerminateCommand();
+ void handleRunControlTerminate(const tcftrk::TcfTrkCommandResult &);
void sendRegistersGetMCommand();
void handleWriteRegister(const tcftrk::TcfTrkCommandResult &result);
void reportRegisters();
@@ -182,6 +184,7 @@ private:
unsigned m_uid;
QStringList m_remoteArguments;
QString m_symbolFile;
+ QString m_symbolFileFolder;
int m_verbose;
bool m_bufferedMemoryRead;
bool m_firstResumableExeLoadedEvent;
diff --git a/src/plugins/debugger/gdb/termgdbadapter.cpp b/src/plugins/debugger/gdb/termgdbadapter.cpp
index a3dde41c1d..e500269f2a 100644
--- a/src/plugins/debugger/gdb/termgdbadapter.cpp
+++ b/src/plugins/debugger/gdb/termgdbadapter.cpp
@@ -32,10 +32,11 @@
**************************************************************************/
#include "termgdbadapter.h"
-
+#include "gdbmi.h"
#include "gdbengine.h"
#include "procinterrupt.h"
#include "debuggerstringutils.h"
+#include "debuggercore.h"
#include <utils/qtcassert.h>
#include <coreplugin/icore.h>
@@ -99,10 +100,14 @@ void TermGdbAdapter::startAdapter()
// m_stubProc.stop();
// m_stubProc.blockSignals(false);
+#ifdef Q_OS_WIN
+ if (!prepareWinCommand())
+ return;
+#endif
+
m_stubProc.setWorkingDirectory(startParameters().workingDirectory);
// Set environment + dumper preload.
- QStringList environment = startParameters().environment;
- m_stubProc.setEnvironment(environment);
+ m_stubProc.setEnvironment(startParameters().environment);
// FIXME: Starting the stub implies starting the inferior. This is
// fairly unclean as far as the state machine and error reporting go.
if (!m_stubProc.start(startParameters().executable,
@@ -203,7 +208,7 @@ void TermGdbAdapter::interruptInferior()
void TermGdbAdapter::stubMessage(const QString &msg, bool)
{
- DebuggerEngine::showMessageBox(QMessageBox::Critical, tr("Debugger Error"), msg);
+ showMessageBox(QMessageBox::Critical, tr("Debugger Error"), msg);
}
void TermGdbAdapter::stubExited()
diff --git a/src/plugins/debugger/gdb/termgdbadapter.h b/src/plugins/debugger/gdb/termgdbadapter.h
index 64a60c0f1b..0ebba53535 100644
--- a/src/plugins/debugger/gdb/termgdbadapter.h
+++ b/src/plugins/debugger/gdb/termgdbadapter.h
@@ -35,10 +35,9 @@
#define DEBUGGER_TERMGDBADAPTER_H
#include "abstractgdbadapter.h"
+#include "localgdbprocess.h"
-#include "abstractgdbprocess.h"
-
-#include <consoleprocess.h>
+#include <utils/consoleprocess.h>
namespace Debugger {
namespace Internal {
diff --git a/src/plugins/debugger/gdb/trkgdbadapter.cpp b/src/plugins/debugger/gdb/trkgdbadapter.cpp
index cd29b8185c..61af444278 100644
--- a/src/plugins/debugger/gdb/trkgdbadapter.cpp
+++ b/src/plugins/debugger/gdb/trkgdbadapter.cpp
@@ -33,6 +33,7 @@
#include "trkgdbadapter.h"
+#include "gdbmi.h"
#include "launcher.h"
#include "symbiandevicemanager.h"
#include "s60debuggerbluetoothstarter.h"
@@ -41,6 +42,7 @@
#include "registerhandler.h"
#include "threadshandler.h"
#include "debuggeractions.h"
+#include "debuggercore.h"
#include "debuggerstringutils.h"
#include "watchutils.h"
#ifndef STANDALONE_RUNNER
@@ -48,6 +50,7 @@
#endif
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <utils/savedaction.h>
#include <QtCore/QTimer>
@@ -110,9 +113,9 @@ TrkGdbAdapter::TrkGdbAdapter(GdbEngine *engine) :
#endif
m_gdbServerName = _("127.0.0.1:%1").arg(2222 + portOffset);
- setVerbose(theDebuggerBoolSetting(VerboseLog));
+ setVerbose(debuggerCore()->boolSetting(VerboseLog));
- connect(theDebuggerAction(VerboseLog), SIGNAL(valueChanged(QVariant)),
+ connect(debuggerCore()->action(VerboseLog), SIGNAL(valueChanged(QVariant)),
this, SLOT(setVerbose(QVariant)));
}
@@ -266,6 +269,7 @@ void TrkGdbAdapter::logMessage(const QString &msg, int logChannel)
{
if (m_verbose || logChannel != LogDebug)
showMessage("TRK LOG: " + msg, logChannel);
+ MEMORY_DEBUG("GDB: " << msg);
}
//
@@ -558,10 +562,7 @@ void TrkGdbAdapter::handleGdbServerCommand(const QByteArray &cmd)
}
else if (cmd == "k" || cmd.startsWith("vKill")) {
- // Kill inferior process
- logMessage(msgGdbPacket(QLatin1String("kill")));
- sendTrkMessage(0x41, TrkCB(handleDeleteProcess),
- trkDeleteProcessMessage(), "Delete process");
+ trkKill();
}
else if (cmd.startsWith('m')) {
@@ -864,6 +865,14 @@ void TrkGdbAdapter::gdbSetCurrentThread(const QByteArray &cmd, const char *why)
sendGdbServerMessage("OK", message);
}
+void TrkGdbAdapter::trkKill()
+{
+ // Kill inferior process
+ logMessage(msgGdbPacket(QLatin1String("kill")));
+ sendTrkMessage(0x41, TrkCB(handleDeleteProcess),
+ trkDeleteProcessMessage(), "Delete process");
+}
+
void TrkGdbAdapter::trkContinueAll(const char *why)
{
if (why)
@@ -949,7 +958,9 @@ void TrkGdbAdapter::handleTrkResult(const TrkResult &result)
case TrkNotifyStopped: { // 0x90 Notified Stopped
// 90 01 78 6a 40 40 00 00 07 23 00 00 07 24 00 00
showMessage(_("RESET SNAPSHOT (NOTIFY STOPPED)"));
+ MEMORY_DEBUG("WE STOPPED");
m_snapshot.reset();
+ MEMORY_DEBUG(" AFTER CLEANING: " << m_snapshot.memory.size() << " BLOCKS LEFT");
QString reason;
uint addr;
uint pid;
@@ -1039,6 +1050,15 @@ void TrkGdbAdapter::handleTrkResult(const TrkResult &result)
if (tid && tid != unsigned(-1) && m_snapshot.indexOfThread(tid) == -1)
m_snapshot.addThread(tid);
logMessage(logMsg);
+ // Load local symbol file into gdb provided there is one
+ if (lib.codeseg) {
+ const QString localSymFileName = Symbian::localSymFileForLibrary(lib.name, m_symbolFileFolder);
+ if (!localSymFileName.isEmpty()) {
+ showMessage(Symbian::msgLoadLocalSymFile(localSymFileName, lib.name, lib.codeseg), LogMisc);
+ m_engine->postCommand(Symbian::symFileLoadCommand(localSymFileName, lib.codeseg, lib.dataseg));
+ } // has local sym
+ } // code seg
+
// This lets gdb trigger a register update etc.
// With CS gdb 6.4 we get a non-standard $qfDllInfo#7f+ request
// afterwards, so don't use it for now.
@@ -1137,9 +1157,19 @@ void TrkGdbAdapter::handleDeleteProcess(const TrkResult &result)
void TrkGdbAdapter::handleDeleteProcess2(const TrkResult &result)
{
Q_UNUSED(result);
- logMessage("App TRK disconnected");
- sendGdbServerAck();
- sendGdbServerMessage("", "process killed");
+ QString msg = QString::fromLatin1("App TRK disconnected");
+
+ const bool emergencyShutdown = m_gdbProc.state() != QProcess::Running;
+ if (emergencyShutdown)
+ msg += QString::fromLatin1(" (emergency shutdown");
+ logMessage(msg);
+ if (emergencyShutdown) {
+ cleanup();
+ m_engine->notifyAdapterShutdownOk();
+ } else {
+ sendGdbServerAck();
+ sendGdbServerMessage("", "process killed");
+ }
}
void TrkGdbAdapter::handleReadRegisters(const TrkResult &result)
@@ -1215,6 +1245,7 @@ void TrkGdbAdapter::handleReadMemoryBuffered(const TrkResult &result)
if (extractShort(result.data.data() + 1) + 3 != result.data.size())
logMessage("\n BAD MEMORY RESULT: " + result.data.toHex() + "\n", LogError);
const MemoryRange range = result.cookie.value<MemoryRange>();
+ MEMORY_DEBUG("HANDLE READ MEMORY ***BUFFERED*** FOR " << range);
if (const int errorCode = result.errorCode()) {
logMessage(_("TEMPORARY: ") + msgMemoryReadError(errorCode, range.from));
logMessage(_("RETRYING UNBUFFERED"));
@@ -1224,6 +1255,7 @@ void TrkGdbAdapter::handleReadMemoryBuffered(const TrkResult &result)
return;
}
const QByteArray ba = result.data.mid(3);
+ MEMORY_DEBUG("INSERT KNOWN MEMORY RANGE: " << range << m_snapshot.memory.size() << " BLOCKS");
m_snapshot.insertMemory(range, ba);
tryAnswerGdbMemoryRequest(true);
}
@@ -1233,6 +1265,7 @@ void TrkGdbAdapter::handleReadMemoryUnbuffered(const TrkResult &result)
if (extractShort(result.data.data() + 1) + 3 != result.data.size())
logMessage("\n BAD MEMORY RESULT: " + result.data.toHex() + "\n", LogError);
const MemoryRange range = result.cookie.value<MemoryRange>();
+ MEMORY_DEBUG("HANDLE READ MEMORY UNBUFFERED FOR " << range);
if (const int errorCode = result.errorCode()) {
logMessage(_("TEMPORARY: ") + msgMemoryReadError(errorCode, range.from));
logMessage(_("RETRYING UNBUFFERED"));
@@ -1250,6 +1283,7 @@ void TrkGdbAdapter::handleReadMemoryUnbuffered(const TrkResult &result)
}
const QByteArray ba = result.data.mid(3);
m_snapshot.insertMemory(range, ba);
+ MEMORY_DEBUG("INSERT KNOWN MEMORY RANGE: " << range << m_snapshot.memory.size() << " BLOCKS");
tryAnswerGdbMemoryRequest(false);
}
@@ -1313,10 +1347,10 @@ void TrkGdbAdapter::tryAnswerGdbMemoryRequest(bool buffered)
int len = needed.to - needed.from;
logMessage(_("Requesting unbuffered memory %1 bytes from 0x%2")
.arg(len).arg(needed.from, 0, 16));
+ MEMORY_DEBUG(" FETCH UNBUFFERED MEMORY : " << needed);
sendTrkMessage(0x10, TrkCB(handleReadMemoryUnbuffered),
trkReadMemoryMessage(needed),
QVariant::fromValue(needed));
- MEMORY_DEBUG(" FETCH UNBUFFERED MEMORY : " << needed);
}
}
@@ -1544,12 +1578,15 @@ void TrkGdbAdapter::startAdapter()
m_remoteExecutable = parameters.executable;
m_remoteArguments = parameters.processArgs;
m_symbolFile = parameters.symbolFileName;
+ if (!m_symbolFile.isEmpty())
+ m_symbolFileFolder = QFileInfo(m_symbolFile).absolutePath();
QString remoteChannel = parameters.remoteChannel;
// FIXME: testing hack, remove!
- if (parameters.processArgs.size() >= 4 && parameters.processArgs.at(0) == _("@sym@")) {
- remoteChannel = parameters.processArgs.at(1);
- m_remoteExecutable = parameters.processArgs.at(2);
- m_symbolFile = parameters.processArgs.at(3);
+ if (m_remoteArguments.startsWith(__("@sym@ "))) {
+ QStringList pa = Utils::QtcProcess::splitArgs(m_remoteArguments);
+ remoteChannel = pa.at(1);
+ m_remoteExecutable = pa.at(2);
+ m_symbolFile = pa.at(3);
m_remoteArguments.clear();
}
// Unixish gdbs accept only forward slashes
@@ -1642,6 +1679,8 @@ void TrkGdbAdapter::handleCreateProcess(const TrkResult &result)
logMessage(warnMessage, LogError);
}
+ m_engine->postCommand("set gnutarget arm-none-symbianelf");
+
const QByteArray symbolFile = m_symbolFile.toLocal8Bit();
if (symbolFile.isEmpty()) {
logMessage(_("WARNING: No symbol file available."), LogError);
@@ -1925,8 +1964,16 @@ void TrkGdbAdapter::shutdownInferior()
void TrkGdbAdapter::shutdownAdapter()
{
- cleanup();
- m_engine->notifyAdapterShutdownOk();
+ if (m_gdbProc.state() == QProcess::Running) {
+ cleanup();
+ m_engine->notifyAdapterShutdownOk();
+ } else {
+ // Something is wrong, gdb crashed. Kill debuggee (see handleDeleteProcess2)
+ if (m_trkDevice->isOpen()) {
+ logMessage("Emergency shutdown of TRK", LogError);
+ trkKill();
+ }
+ }
}
void TrkGdbAdapter::trkReloadRegisters()
diff --git a/src/plugins/debugger/gdb/trkgdbadapter.h b/src/plugins/debugger/gdb/trkgdbadapter.h
index f866129a09..3fb12b2a79 100644
--- a/src/plugins/debugger/gdb/trkgdbadapter.h
+++ b/src/plugins/debugger/gdb/trkgdbadapter.h
@@ -35,7 +35,7 @@
#define DEBUGGER_TRKGDBADAPTER_H
#include "abstractgdbadapter.h"
-
+#include "localgdbprocess.h"
#include "trkutils.h"
#include "callback.h"
#include "symbian.h"
@@ -139,6 +139,7 @@ private:
Q_SLOT void handleTrkResult(const trk::TrkResult &data);
Q_SLOT void handleTrkError(const QString &msg);
void trkContinueAll(const char *why);
+ void trkKill();
void handleTrkContinueNext(const TrkResult &result);
void trkContinueNext(int threadIndex);
@@ -228,8 +229,9 @@ private:
trk::Session m_session; // global-ish data (process id, target information)
Symbian::Snapshot m_snapshot; // local-ish data (memory and registers)
QString m_remoteExecutable;
- QStringList m_remoteArguments;
+ QString m_remoteArguments;
QString m_symbolFile;
+ QString m_symbolFileFolder;
int m_verbose;
bool m_bufferedMemoryRead;
LocalGdbProcess m_gdbProc;
diff --git a/src/plugins/debugger/images/tracepoint.png b/src/plugins/debugger/images/tracepoint.png
new file mode 100644
index 0000000000..f08d216bf3
--- /dev/null
+++ b/src/plugins/debugger/images/tracepoint.png
Binary files differ
diff --git a/src/plugins/debugger/lldb/guest/README b/src/plugins/debugger/lldb/guest/README
new file mode 100644
index 0000000000..be9d4fbee7
--- /dev/null
+++ b/src/plugins/debugger/lldb/guest/README
@@ -0,0 +1,31 @@
+LLDB Guest Engine
+
+You can use the LLDB debugger from the LLVM project with the Qt Creator debugger
+plugin on Mac OS.
+
+For the Qt Creator build to pick up the LLDB Guest Engine,
+you must download the LLDB debugger and configure it
+to be included in the Qt Creator build.
+
+To debug an application, Qt Creator must access the memory of the application.
+On Mac OS X, this requires code signing.
+
+To enable LLDB debugger support in Qt Creator:
+
+1. To download the LLDB debugger, enter the following command:
+ svn co http://llvm.org/svn/llvm-project/lldb/trunk lldb
+
+2. To sign the code, follow the instructions in lldb/docs/code-signing.txt.
+
+3. To open LLDB in Xcode for building, enter the following command:
+ open lldb.xcodeproj
+ then select the Release target and press the build button.
+
+4. In Xcode, press the build button.
+
+5. type the following to have the qt creator build system find your lldb build:
+ export WITH_LLDB=/path/to/lldb
+
+6. To rebuild Qt Creator, change back to the top level directory of
+ the Qt Creator source, and enter the following command:
+ qmake -r && make
diff --git a/src/plugins/debugger/lldb/guest/lldbengineguest.cpp b/src/plugins/debugger/lldb/guest/lldbengineguest.cpp
new file mode 100644
index 0000000000..5fe0a275ac
--- /dev/null
+++ b/src/plugins/debugger/lldb/guest/lldbengineguest.cpp
@@ -0,0 +1,768 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#define QT_NO_CAST_FROM_ASCII
+
+#include "lldbengineguest.h"
+
+#include "debuggeractions.h"
+#include "debuggerconstants.h"
+#include "debuggerdialogs.h"
+#include "debuggerplugin.h"
+#include "debuggerstringutils.h"
+
+#include "breakhandler.h"
+#include "breakpoint.h"
+#include "moduleshandler.h"
+#include "registerhandler.h"
+#include "stackhandler.h"
+#include "watchhandler.h"
+#include "watchutils.h"
+#include "threadshandler.h"
+
+#include <utils/qtcassert.h>
+#include <QtCore/QDebug>
+#include <QtCore/QProcess>
+#include <QtCore/QFileInfo>
+#include <QtCore/QThread>
+#include <QtCore/QMutexLocker>
+
+#include <lldb/API/LLDB.h>
+
+#define DEBUG_FUNC_ENTER \
+ showMessage(QString(QLatin1String("LLDB guest engine: %1 ")) \
+ .arg(QLatin1String(Q_FUNC_INFO))); \
+ qDebug("%s", Q_FUNC_INFO)
+
+#define SYNC_INFERIOR_OR(x) if (m_running) { x; }
+
+
+namespace Debugger {
+namespace Internal {
+
+void LldbEventListener::listen(lldb::SBListener *listener)
+{
+ while (true) {
+ lldb::SBEvent event;
+ if (listener->WaitForEvent(1000, event))
+ emit lldbEvent(&event);
+ }
+}
+
+LldbEngineGuest::LldbEngineGuest()
+ : IPCEngineGuest()
+ , m_running (false)
+ , m_worker (new LldbEventListener)
+ , m_lldb (new lldb::SBDebugger)
+ , m_target (new lldb::SBTarget)
+ , m_process (new lldb::SBProcess)
+ , m_listener(new lldb::SBListener("bla"))
+ , m_relistFrames (false)
+#if defined(HAVE_LLDB_PRIVATE)
+ , py (new PythonLLDBToGdbMiHack)
+#endif
+{
+ qRegisterMetaType<lldb::SBListener *>("lldb::SBListener *");
+ qRegisterMetaType<lldb::SBEvent *>("lldb::SBEvent *");
+
+ m_worker->moveToThread(&m_wThread);
+ connect(m_worker, SIGNAL(lldbEvent(lldb::SBEvent *)), this,
+ SLOT(lldbEvent(lldb::SBEvent *)), Qt::BlockingQueuedConnection);
+ m_wThread.start();
+ setObjectName(QLatin1String("LLDBEngineGuest"));
+}
+
+LldbEngineGuest::~LldbEngineGuest()
+{
+ delete m_lldb;
+ delete m_target;
+ delete m_process;
+ delete m_listener;
+}
+
+
+void LldbEngineGuest::nuke()
+{
+ ::exit(4);
+}
+
+void LldbEngineGuest::setupEngine()
+{
+ DEBUG_FUNC_ENTER;
+
+ lldb::SBDebugger::Initialize();
+
+ *m_lldb = lldb::SBDebugger::Create();
+ m_lldb->Initialize();
+ if (m_lldb->IsValid())
+ notifyEngineSetupOk();
+ else
+ notifyEngineSetupFailed();
+
+}
+
+void LldbEngineGuest::setupInferior(const QString &executable,
+ const QStringList &args, const QStringList &env)
+{
+ DEBUG_FUNC_ENTER;
+
+ foreach (const QString &s, args) {
+ m_arguments.append(s.toLocal8Bit());
+ }
+ foreach (const QString &s, env) {
+ m_environment.append(s.toLocal8Bit());
+ }
+
+ qDebug("creating target for %s", executable.toLocal8Bit().data());
+ showStatusMessage(QLatin1String("starting ") + executable);
+ *m_target = m_lldb->CreateTarget(executable.toLocal8Bit().data());
+ if (!m_target->IsValid()) {
+ notifyInferiorSetupFailed();
+ return;
+ }
+ DEBUG_FUNC_ENTER;
+
+ const char **argp = new const char *[m_arguments.count() + 1];
+ argp[m_arguments.count()] = 0;
+ for (int i = 0; i < m_arguments.count(); i++) {
+ argp[i] = m_arguments[i].data();
+ }
+
+ const char **envp = new const char *[m_environment.count() + 1];
+ envp[m_environment.count()] = 0;
+ for (int i = 0; i < m_environment.count(); i++) {
+ envp[i] = m_environment[i].data();
+ }
+ lldb::SBError err;
+ *m_process = m_target->Launch(argp, envp, NULL, NULL, true, err);
+
+ if (!err.Success()) {
+ showMessage(QString::fromLocal8Bit(err.GetCString()));
+ qDebug() << err.GetCString();
+ notifyInferiorSetupFailed();
+ }
+
+ /*
+ * note, the actual string ptrs are still valid. They are in m_environment.
+ * They probably leak. Considered the marvelous API, there is not much we can do
+ */
+ delete [] envp;
+
+ if (!m_process->IsValid())
+ notifyEngineRunFailed();
+ QTC_ASSERT(m_listener->IsValid(), qDebug() << false);
+ m_listener->StartListeningForEvents(m_process->GetBroadcaster(), UINT32_MAX);
+ QMetaObject::invokeMethod(m_worker, "listen", Qt::QueuedConnection,
+ Q_ARG(lldb::SBListener *, m_listener));
+ notifyInferiorSetupOk();
+}
+
+void LldbEngineGuest::runEngine()
+{
+ DEBUG_FUNC_ENTER;
+ m_process->Continue();
+}
+
+void LldbEngineGuest::shutdownInferior()
+{
+ DEBUG_FUNC_ENTER;
+ m_process->Kill();
+}
+
+void LldbEngineGuest::shutdownEngine()
+{
+ DEBUG_FUNC_ENTER;
+ m_currentFrame = lldb::SBFrame();
+ m_currentThread = lldb::SBThread();
+ m_breakpoints.clear();
+ m_localesCache.clear();
+
+ /*
+ * this leaks. However, Terminate is broken and lldb leaks anyway
+ * We should kill the engine guest process
+ */
+
+ *m_lldb = lldb::SBDebugger();
+ // leakd.Terminate();
+ notifyEngineShutdownOk();
+}
+
+void LldbEngineGuest::detachDebugger()
+{
+ DEBUG_FUNC_ENTER;
+}
+
+void LldbEngineGuest::executeStep()
+{
+ DEBUG_FUNC_ENTER;
+
+ if (!m_currentThread.IsValid())
+ return;
+ m_currentThread.StepInto();
+}
+
+void LldbEngineGuest::executeStepOut()
+{
+ DEBUG_FUNC_ENTER;
+
+ if (!m_currentThread.IsValid())
+ return;
+ m_currentThread.StepOut();
+}
+
+void LldbEngineGuest::executeNext()
+{
+ DEBUG_FUNC_ENTER;
+
+ if (!m_currentThread.IsValid())
+ return;
+ m_currentThread.StepOver();
+}
+
+void LldbEngineGuest::executeStepI()
+{
+ DEBUG_FUNC_ENTER;
+
+ if (!m_currentThread.IsValid())
+ return;
+ m_currentThread.StepInstruction(false);
+}
+
+void LldbEngineGuest::executeNextI()
+{
+ DEBUG_FUNC_ENTER;
+
+ if (!m_currentThread.IsValid())
+ return;
+ m_currentThread.StepInstruction(true);
+}
+
+void LldbEngineGuest::continueInferior()
+{
+ DEBUG_FUNC_ENTER;
+
+ notifyInferiorRunRequested();
+ m_process->Continue();
+ showStatusMessage(QLatin1String("resuming inferior"));
+}
+void LldbEngineGuest::interruptInferior()
+{
+ DEBUG_FUNC_ENTER;
+
+ m_process->Stop();
+ notifyInferiorStopOk();
+ m_relistFrames = true;
+ updateThreads();
+}
+
+void LldbEngineGuest::executeRunToLine(const QString &fileName, int lineNumber)
+{
+ DEBUG_FUNC_ENTER;
+
+ // TODO
+ Q_UNUSED(fileName);
+ Q_UNUSED(lineNumber);
+}
+
+void LldbEngineGuest::executeRunToFunction(const QString &functionName)
+{
+ DEBUG_FUNC_ENTER;
+
+ // TODO
+ Q_UNUSED(functionName);
+}
+void LldbEngineGuest::executeJumpToLine(const QString &fileName, int lineNumber)
+{
+ DEBUG_FUNC_ENTER;
+
+ // TODO
+ Q_UNUSED(fileName);
+ Q_UNUSED(lineNumber);
+}
+
+void LldbEngineGuest::activateFrame(qint64 token)
+{
+ DEBUG_FUNC_ENTER;
+ SYNC_INFERIOR_OR(showMessage(QLatin1String(
+ "activateFrame called while inferior running")); return);
+
+ currentFrameChanged(token);
+ m_localesCache.clear();
+
+ lldb::SBFrame fr = m_currentThread.GetFrameAtIndex(token);
+ m_currentFrame = fr;
+ lldb::SBSymbolContext context = fr.GetSymbolContext(lldb::eSymbolContextEverything);
+ lldb::SBValueList values = fr.GetVariables(true, true, false, true);
+ QList<WatchData> wd;
+ QByteArray iname = "local";
+ for (uint i = 0; i < values.GetSize(); i++) {
+ lldb::SBValue v = values.GetValueAtIndex(i);
+ if (!v.IsInScope(fr))
+ continue;
+ getWatchDataR(v, 1, iname, wd);
+ }
+ updateWatchData(true, wd);
+}
+
+void LldbEngineGuest::requestUpdateWatchData(const Internal::WatchData &data,
+ const Internal::WatchUpdateFlags &)
+{
+ DEBUG_FUNC_ENTER;
+ SYNC_INFERIOR_OR(return);
+
+ lldb::SBValue v = m_localesCache.value(QString::fromUtf8(data.iname));
+ QList<WatchData> wd;
+ for (uint j = 0; j < v.GetNumChildren(); j++) {
+ lldb::SBValue vv = v.GetChildAtIndex(j);
+ getWatchDataR(vv, 1, data.iname, wd);
+ }
+ updateWatchData(false, wd);
+}
+
+void LldbEngineGuest::getWatchDataR(lldb::SBValue v, int level,
+ const QByteArray &p_iname, QList<WatchData> &wd)
+{
+ QByteArray iname = p_iname + "." + QByteArray(v.GetName());
+ m_localesCache.insert(QString::fromLocal8Bit(iname), v);
+
+#if defined(HAVE_LLDB_PRIVATE)
+ wd += py->expand(p_iname, v, m_currentFrame, *m_process);
+#else
+ WatchData d;
+ d.name = QString::fromLocal8Bit(v.GetName());
+ d.iname = iname;
+ d.type = QByteArray(v.GetTypeName()).trimmed();
+ d.value = (QString::fromLocal8Bit(v.GetValue(m_currentFrame)));
+ d.hasChildren = v.GetNumChildren();
+ d.state = WatchData::State(0);
+ wd.append(d);
+#endif
+
+ if (--level > 0) {
+ for (uint j = 0; j < v.GetNumChildren(); j++) {
+ lldb::SBValue vv = v.GetChildAtIndex(j);
+ getWatchDataR(vv, level, iname, wd);
+ }
+ }
+}
+
+void LldbEngineGuest::disassemble(quint64 pc)
+{
+ DEBUG_FUNC_ENTER;
+ SYNC_INFERIOR_OR(return);
+
+ if (!m_currentThread.IsValid())
+ return;
+ for (uint j = 0; j < m_currentThread.GetNumFrames(); j++) {
+ lldb::SBFrame fr = m_currentThread.GetFrameAtIndex(j);
+ if (pc == fr.GetPCAddress().GetLoadAddress(*m_target)) {
+ QString linesStr = QString::fromLocal8Bit(fr.Disassemble());
+ DisassemblerLines lines;
+ foreach (const QString &lineStr, linesStr.split(QLatin1Char('\n'))) {
+ lines.appendLine(DisassemblerLine(lineStr));
+ }
+ disassembled(pc, lines);
+ }
+ }
+}
+void LldbEngineGuest::fetchFrameSource(qint64 frame)
+{
+ QFile f(m_frame_to_file.value(frame));
+ f.open(QFile::ReadOnly);
+ frameSourceFetched(frame, QFileInfo(m_frame_to_file.value(frame)).fileName()
+ , QString::fromLocal8Bit(f.readAll()));
+}
+
+void LldbEngineGuest::addBreakpoint(BreakpointId id,
+ const Internal::BreakpointParameters &bp_)
+{
+ DEBUG_FUNC_ENTER;
+ SYNC_INFERIOR_OR(notifyAddBreakpointFailed(id); return);
+
+ Internal::BreakpointParameters bp(bp_);
+
+ lldb::SBBreakpoint llbp = m_target->BreakpointCreateByLocation(
+ bp.fileName.toLocal8Bit().constData(), bp.lineNumber);
+ if (llbp.IsValid()) {
+ m_breakpoints.insert(id, llbp);
+
+ llbp.SetIgnoreCount(bp.ignoreCount);
+ bp.ignoreCount = llbp.GetIgnoreCount();
+ bp.enabled = llbp.IsEnabled();
+
+ lldb::SBBreakpointLocation location = llbp.GetLocationAtIndex(0);
+ if (location.IsValid()) {
+ bp.address = location.GetLoadAddress();
+
+ // FIXME get those from lldb
+ bp.lineNumber = bp.lineNumber;
+ bp.fileName = bp.fileName;
+ notifyAddBreakpointOk(id);
+ showMessage(QLatin1String("[BB] ok."));
+ notifyBreakpointAdjusted(id, bp);
+ } else {
+ m_breakpoints.take(id);
+ showMessage(QLatin1String("[BB] failed. cant resolve yet"));
+// notifyAddBreakpointFailed(id);
+// notifyAddBreakpointOk(id);
+ }
+ } else {
+ showMessage(QLatin1String("[BB] failed. dunno."));
+ notifyAddBreakpointFailed(id);
+ }
+}
+
+void LldbEngineGuest::removeBreakpoint(BreakpointId id)
+{
+ DEBUG_FUNC_ENTER;
+ SYNC_INFERIOR_OR(notifyRemoveBreakpointFailed(id); return);
+
+ lldb::SBBreakpoint llbp = m_breakpoints.take(id);
+ llbp.SetEnabled(false);
+ notifyRemoveBreakpointOk(id);
+}
+
+void LldbEngineGuest::changeBreakpoint(BreakpointId id,
+ const Internal::BreakpointParameters &bp)
+{
+ DEBUG_FUNC_ENTER;
+
+ // TODO
+ Q_UNUSED(id);
+ Q_UNUSED(bp);
+}
+
+void LldbEngineGuest::selectThread(qint64 token)
+{
+ DEBUG_FUNC_ENTER;
+ SYNC_INFERIOR_OR(return);
+
+ m_frame_to_file.clear();
+ for (uint i = 0; i < m_process->GetNumThreads(); i++) {
+ lldb::SBThread t = m_process->GetThreadAtIndex(i);
+ if (t.GetThreadID() == token) {
+ m_currentThread = t;
+ StackFrames frames;
+ int firstResolvableFrame = -1;
+ for (uint j = 0; j < t.GetNumFrames(); j++) {
+ lldb::SBFrame fr = t.GetFrameAtIndex(j);
+ if (!fr.IsValid()) {
+ qDebug("warning: frame %i is garbage", j);
+ continue;
+ }
+ lldb::SBSymbolContext context =
+ fr.GetSymbolContext(lldb::eSymbolContextEverything);
+ lldb::SBSymbol sym = fr.GetSymbol();
+ lldb::SBFunction func = fr.GetFunction();
+ lldb::SBCompileUnit tu = fr.GetCompileUnit();
+ lldb::SBModule module = fr.GetModule();
+ lldb::SBBlock block = fr.GetBlock();
+ lldb::SBBlock fblock = fr.GetFrameBlock();
+ lldb::SBLineEntry le = fr.GetLineEntry();
+ lldb::SBValueList values = fr.GetVariables(true, true, true, false);
+#if 0
+ qDebug()<<"\tframe "<<fr.GetFrameID();
+ qDebug() << "\t\tPC: " << ("0x" + QByteArray::number(
+ fr.GetPCAddress().GetLoadAddress(*m_target), 16)).data();
+ qDebug() << "\t\tFP: " << ("0x" + QByteArray::number(fr.GetFP(), 16)).data();
+ qDebug() << "\t\tSP: " << ("0x" + QByteArray::number(fr.GetSP(), 16)).data();
+ qDebug() << "\t\tsymbol: " << sym.IsValid() << sym.GetName() << sym.GetMangledName();
+ qDebug() << "\t\tfunction:" << func.IsValid();
+ qDebug() << "\t\ttu: " << tu.IsValid();
+ if (tu.IsValid()) {
+
+ }
+ qDebug() << "\t\tmodule: " << module.IsValid() << module.GetFileSpec().IsValid()
+ << module.GetFileSpec().GetFilename();
+ qDebug() << "\t\tblock: " << block.IsValid() << block.GetInlinedName();
+ qDebug() << "\t\tfblock: " << block.IsValid() << block.GetInlinedName();
+ qDebug() << "\t\tle: " << le.IsValid() << le.GetLine()<<le.GetColumn();
+ qDebug() << "\t\tvalues: "<<values.IsValid() << values.GetSize();
+ qDebug() << "\t\tcontext: " << context.IsValid();
+ qDebug() << "\t\t\tmodule: " << context.GetModule().IsValid();
+ qDebug() << "\t\t\tfunction: " << context.GetFunction().IsValid();
+ qDebug() << "\t\t\tblock: " << context.GetBlock().IsValid();
+ qDebug() << "\t\t\tle: " << context.GetLineEntry().IsValid();
+ qDebug() << "\t\t\tsymbol: " << context.GetSymbol().IsValid();
+// qDebug() << "\t\tdisassemly -->\n" << fr.Disassemble() << "<--";
+#endif
+
+ QString sourceFile;
+ QString sourceFilePath;
+ int lineNumber = 0;
+ if (le.IsValid()) {
+ lineNumber = le.GetLine();
+ if (le.GetFileSpec().IsValid()) {
+ sourceFile = QString::fromLocal8Bit(le.GetFileSpec().GetFilename());
+ sourceFilePath = QString::fromLocal8Bit(le.GetFileSpec().GetDirectory())
+ + QLatin1String("/") + sourceFile;
+ if (firstResolvableFrame < 0)
+ firstResolvableFrame = j;
+ }
+ }
+ sourceFilePath = QFileInfo(sourceFilePath).canonicalFilePath();
+
+ QString functionName;
+ if (func.IsValid())
+ functionName = QString::fromLocal8Bit(func.GetName());
+ else
+ functionName = QString::fromLocal8Bit(sym.GetName());
+
+ StackFrame frame;
+ frame.level = fr.GetFrameID();
+ if (func.IsValid())
+ frame.function = QString::fromLocal8Bit(func.GetName());
+ else
+ frame.function = QString::fromLocal8Bit(sym.GetName());
+ frame.from = QString::fromLocal8Bit(module.GetFileSpec().GetFilename());
+ frame.address = fr.GetPCAddress().GetLoadAddress(*m_target);
+ frame.line = lineNumber;
+ frame.file = sourceFilePath;
+ frame.usable = QFileInfo(frame.file).isReadable();
+ frames.append(frame);
+ m_frame_to_file.insert(j, frame.file);
+ }
+ currentThreadChanged(token);
+ listFrames(frames);
+ activateFrame(firstResolvableFrame > -1 ? firstResolvableFrame : 0);
+ return;
+ }
+ }
+}
+
+void LldbEngineGuest::updateThreads()
+{
+ DEBUG_FUNC_ENTER;
+ SYNC_INFERIOR_OR(return);
+
+ /* There is no way to find the StopReason of a _process_
+ * We try to emulate gdb here, by assuming there must be exactly one 'guilty' thread.
+ * However, if there are no threads at all, it must be that the process
+ * no longer exists. Let's tear down the whole session.
+ */
+ if (m_process->GetNumThreads() < 1) {
+ notifyEngineSpontaneousShutdown();
+ m_process->Kill();
+ m_process->Destroy();
+ }
+
+ Threads threads;
+ for (uint i = 0; i < m_process->GetNumThreads(); i++) {
+ lldb::SBThread t = m_process->GetThreadAtIndex(i);
+ if (!t.IsValid()) {
+ qDebug("warning: thread %i is garbage", i);
+ continue;
+ }
+ ThreadData thread;
+ thread.id = t.GetThreadID();
+ thread.targetId = QString::number(t.GetThreadID());
+ thread.core = QString();
+ thread.state = QString::number(t.GetStopReason());
+
+ switch (t.GetStopReason()) {
+ case lldb::eStopReasonInvalid:
+ case lldb::eStopReasonNone:
+ case lldb::eStopReasonTrace:
+ thread.state = QLatin1String("running");
+ break;
+ case lldb::eStopReasonBreakpoint:
+ case lldb::eStopReasonWatchpoint:
+ showStatusMessage(QLatin1String("hit breakpoint"));
+ thread.state = QLatin1String("hit breakpoint");
+ if (m_currentThread.GetThreadID() != t.GetThreadID()) {
+ m_currentThread = t;
+ currentThreadChanged(t.GetThreadID());
+ m_relistFrames = true;
+ }
+ break;
+ case lldb::eStopReasonSignal:
+ showStatusMessage(QLatin1String("stopped"));
+ thread.state = QLatin1String("stopped");
+ if (m_currentThread.GetThreadID() != t.GetThreadID()) {
+ m_currentThread = t;
+ currentThreadChanged(t.GetThreadID());
+ m_relistFrames = true;
+ }
+ break;
+ case lldb::eStopReasonException:
+ showStatusMessage(QLatin1String("application crashed."));
+ thread.state = QLatin1String("crashed");
+ if (m_currentThread.GetThreadID() != t.GetThreadID()) {
+ m_currentThread = t;
+ currentThreadChanged(t.GetThreadID());
+ m_relistFrames = true;
+ }
+ break;
+ case lldb::eStopReasonPlanComplete:
+ thread.state = QLatin1String("crazy things happened");
+ break;
+ };
+
+ thread.lineNumber = 0;
+ thread.name = QString::fromLocal8Bit(t.GetName());
+
+ lldb::SBFrame fr = t.GetFrameAtIndex(0);
+ if (!fr.IsValid()) {
+ qDebug("warning: frame 0 is garbage");
+ continue;
+ }
+ lldb::SBSymbolContext context = fr.GetSymbolContext(lldb::eSymbolContextEverything);
+ lldb::SBSymbol sym = fr.GetSymbol();
+ lldb::SBFunction func = fr.GetFunction();
+ lldb::SBLineEntry le = fr.GetLineEntry();
+ QString sourceFile;
+ QString sourceFilePath;
+ int lineNumber = 0;
+ if (le.IsValid()) {
+ lineNumber = le.GetLine();
+ if (le.GetFileSpec().IsValid()) {
+ sourceFile = QString::fromLocal8Bit(le.GetFileSpec().GetFilename());
+ sourceFilePath = QString::fromLocal8Bit(le.GetFileSpec().GetDirectory())
+ + QLatin1String("/") + sourceFile;
+ }
+ }
+ QString functionName;
+ if (func.IsValid())
+ functionName = QString::fromLocal8Bit(func.GetName());
+ else
+ functionName = QString::fromLocal8Bit(sym.GetName());
+
+ lldb::SBValueList values = fr.GetVariables(true, true, false, false);
+ thread.fileName = sourceFile;
+ thread.function = functionName;
+ thread.address = fr.GetPCAddress().GetLoadAddress(*m_target);
+ thread.lineNumber = lineNumber;
+ threads.append(thread);
+ }
+ listThreads(threads);
+ if (m_relistFrames) {
+ selectThread(m_currentThread.GetThreadID());
+ m_relistFrames = false;
+ }
+}
+
+void LldbEngineGuest::lldbEvent(lldb::SBEvent *ev)
+{
+ qDebug() << "lldbevent" << ev->GetType() <<
+ m_process->GetState() << (int)state();
+
+ uint32_t etype = ev->GetType();
+ switch (etype) {
+ // ProcessEvent
+ case 1:
+ switch (m_process->GetState()) {
+ case lldb::eStateRunning: // 5
+ if (!m_running) {
+ m_running = true;
+ }
+ notifyInferiorPid(m_process->GetProcessID());
+ switch (state()) {
+ case EngineRunRequested:
+ notifyEngineRunAndInferiorRunOk();
+ break;
+ case InferiorRunRequested:
+ notifyInferiorRunOk();
+ break;
+ case InferiorStopOk:
+ notifyInferiorRunRequested();
+ notifyInferiorRunOk();
+ break;
+ default:
+ break;
+ }
+ break;
+ case lldb::eStateExited: // 9
+ if (m_running) {
+ m_running = false;
+ }
+ switch (state()) {
+ case InferiorShutdownRequested:
+ notifyInferiorShutdownOk();
+ break;
+ case InferiorRunOk:
+ m_relistFrames = true;
+ updateThreads();
+ notifyEngineSpontaneousShutdown();
+ m_process->Kill();
+ m_process->Destroy();
+ break;
+ default:
+ updateThreads();
+ break;
+ }
+ break;
+ case lldb::eStateStopped: // 4
+ if (m_running) {
+ m_running = false;
+ }
+ switch (state()) {
+ case InferiorShutdownRequested:
+ notifyInferiorShutdownOk();
+ break;
+ case InferiorRunOk:
+ m_relistFrames = true;
+ updateThreads();
+ notifyInferiorSpontaneousStop();
+ // fall
+ default:
+ m_relistFrames = true;
+ updateThreads();
+ break;
+ }
+ break;
+ case lldb::eStateCrashed: // 7
+ if (m_running) {
+ m_running = false;
+ }
+ switch (state()) {
+ case InferiorShutdownRequested:
+ notifyInferiorShutdownOk();
+ break;
+ case InferiorRunOk:
+ m_relistFrames = true;
+ updateThreads();
+ notifyInferiorSpontaneousStop();
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ qDebug("unexpected ProcessEvent");
+ break;
+ }
+ break;;
+ default:
+ break;;
+ };
+}
+
+
+} // namespace Internal
+} // namespace Debugger
diff --git a/src/plugins/debugger/lldb/guest/lldbengineguest.h b/src/plugins/debugger/lldb/guest/lldbengineguest.h
new file mode 100644
index 0000000000..93f0c0a256
--- /dev/null
+++ b/src/plugins/debugger/lldb/guest/lldbengineguest.h
@@ -0,0 +1,136 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 DEBUGGER_LLDBENGINE_GUEST_H
+#define DEBUGGER_LLDBENGINE_GUEST_H
+
+#include "ipcengineguest.h"
+
+#include <QtCore/QQueue>
+#include <QtCore/QVariant>
+#include <QtCore/QThread>
+#include <QtCore/QStringList>
+
+#include <lldb/API/LLDB.h>
+
+#if defined(HAVE_LLDB_PRIVATE)
+#include "pygdbmiemu.h"
+#endif
+
+Q_DECLARE_METATYPE (lldb::SBListener *)
+Q_DECLARE_METATYPE (lldb::SBEvent *)
+
+namespace Debugger {
+namespace Internal {
+
+class LldbEventListener : public QObject
+{
+Q_OBJECT
+public slots:
+ void listen(lldb::SBListener *listener);
+signals:
+ // lldb API uses non thread safe implicit sharing with no explicit copy feature
+ // additionally the scope is undefined, hence this signal needs to be connected BlockingQueued
+ // whutever, works for now.
+ void lldbEvent(lldb::SBEvent *ev);
+};
+
+
+class LldbEngineGuest : public IPCEngineGuest
+{
+ Q_OBJECT
+
+public:
+ explicit LldbEngineGuest();
+ ~LldbEngineGuest();
+
+ void nuke();
+ void setupEngine();
+ void setupInferior(const QString &executable, const QStringList &arguments,
+ const QStringList &environment);
+ void runEngine();
+ void shutdownInferior();
+ void shutdownEngine();
+ void detachDebugger();
+ void executeStep();
+ void executeStepOut() ;
+ void executeNext();
+ void executeStepI();
+ void executeNextI();
+ void continueInferior();
+ void interruptInferior();
+ void executeRunToLine(const QString &fileName, int lineNumber);
+ void executeRunToFunction(const QString &functionName);
+ void executeJumpToLine(const QString &fileName, int lineNumber);
+ void activateFrame(qint64);
+ void selectThread(qint64);
+ void disassemble(quint64 pc);
+ void addBreakpoint(BreakpointId id, const BreakpointParameters &bp);
+ void removeBreakpoint(BreakpointId id);
+ void changeBreakpoint(BreakpointId id, const BreakpointParameters &bp);
+ void requestUpdateWatchData(const WatchData &data,
+ const WatchUpdateFlags &flags);
+ void fetchFrameSource(qint64 frame);
+
+private:
+ bool m_running;
+
+ QList<QByteArray> m_arguments;
+ QList<QByteArray> m_environment;
+ QThread m_wThread;
+ LldbEventListener *m_worker;
+ lldb::SBDebugger *m_lldb;
+ lldb::SBTarget *m_target;
+ lldb::SBProcess *m_process;
+ lldb::SBListener *m_listener;
+
+ lldb::SBFrame m_currentFrame;
+ lldb::SBThread m_currentThread;
+ bool m_relistFrames;
+ QHash<QString, lldb::SBValue> m_localesCache;
+ QHash<BreakpointId, lldb::SBBreakpoint> m_breakpoints;
+ QHash<qint64, QString> m_frame_to_file;
+
+ void updateThreads();
+ void getWatchDataR(lldb::SBValue v, int level,
+ const QByteArray &p_iname, QList<WatchData> &wd);
+
+#if defined(HAVE_LLDB_PRIVATE)
+ PythonLLDBToGdbMiHack * py;
+#endif
+
+private slots:
+ void lldbEvent(lldb::SBEvent *ev);
+};
+
+} // namespace Internal
+} // namespace Debugger
+
+#endif // DEBUGGER_LLDBENGINE_H
+#define SYNC_INFERIOR
diff --git a/src/plugins/debugger/lldb/guest/main.cpp b/src/plugins/debugger/lldb/guest/main.cpp
new file mode 100644
index 0000000000..084ed016fa
--- /dev/null
+++ b/src/plugins/debugger/lldb/guest/main.cpp
@@ -0,0 +1,121 @@
+#include <QtCore/QCoreApplication>
+#include <QtNetwork/QLocalSocket>
+#include "lldbengineguest.h"
+#include <cstdio>
+#include <QSocketNotifier>
+#include <QQueue>
+
+
+// #define DO_STDIO_DEBUG 1
+#ifdef DO_STDIO_DEBUG
+#define D_STDIO0(x) qDebug(x)
+#define D_STDIO1(x,a1) qDebug(x,a1)
+#define D_STDIO2(x,a1,a2) qDebug(x,a1,a2)
+#define D_STDIO3(x,a1,a2,a3) qDebug(x,a1,a2,a3)
+#else
+#define D_STDIO0(x)
+#define D_STDIO1(x,a1)
+#define D_STDIO2(x,a1,a2)
+#define D_STDIO3(x,a1,a2,a3)
+#endif
+
+class Stdio : public QIODevice
+{
+ Q_OBJECT
+public:
+ QSocketNotifier notify;
+ Stdio()
+ : QIODevice()
+ , notify(fileno(stdin), QSocketNotifier::Read)
+ , buckethead(0)
+ {
+ setvbuf(stdin , NULL , _IONBF , 0);
+ setvbuf(stdout , NULL , _IONBF , 0);
+ setOpenMode(QIODevice::ReadWrite | QIODevice::Unbuffered);
+ connect(&notify, SIGNAL(activated(int)), this, SLOT(activated()));
+ }
+ virtual qint64 bytesAvailable () const
+ {
+ qint64 r = QIODevice::bytesAvailable();
+ foreach (const QByteArray &bucket, buckets)
+ r += bucket.size();
+ r-= buckethead;
+ return r;
+ }
+
+ virtual qint64 readData (char * data, qint64 maxSize)
+ {
+ D_STDIO1("readData %lli",maxSize);
+ qint64 size = maxSize;
+ while (size > 0) {
+ if (!buckets.size()) {
+ D_STDIO1("done prematurely with %lli", maxSize - size);
+ return maxSize - size;
+ }
+ QByteArray &bucket = buckets.head();
+ if ((size + buckethead) >= bucket.size()) {
+ int d = bucket.size() - buckethead;
+ D_STDIO3("read (over bucket) d: %i buckethead: %i bucket.size(): %i",
+ d, buckethead, bucket.size());
+ memcpy(data, bucket.data() + buckethead, d);
+ data += d;
+ size -= d;
+ buckets.dequeue();
+ buckethead = 0;
+ } else {
+ D_STDIO1("read (in bucket) size: %lli", size);
+ memcpy(data, bucket.data() + buckethead, size);
+ data += size;
+ buckethead += size;
+ size = 0;
+ }
+ }
+ D_STDIO1("done with %lli",(maxSize - size));
+ return maxSize - size;
+ }
+
+ virtual qint64 writeData (const char * data, qint64 maxSize)
+ {
+ return ::write(fileno(stdout), data, maxSize);
+ }
+
+ QQueue<QByteArray> buckets;
+ int buckethead;
+
+private slots:
+ void activated()
+ {
+ QByteArray a;
+ a.resize(1000);
+ int ret = ::read(fileno(stdin), a.data(), 1000);
+ if (ret == 0)
+ ::exit(0);
+ assert(ret <= 1000);
+ D_STDIO1("activated %i", ret);
+ a.resize(ret);
+ buckets.enqueue(a);
+ emit readyRead();
+ }
+};
+
+int main(int argc, char **argv)
+{
+ QCoreApplication app(argc, argv);
+ qDebug() << "guest engine operational";
+
+ Debugger::Internal::LldbEngineGuest lldb;
+
+
+ Stdio stdio;
+ lldb.setHostDevice(&stdio);
+
+ return app.exec();
+}
+
+extern "C" {
+extern const unsigned char lldbVersionString[] __attribute__ ((used)) = "@(#)PROGRAM:lldb PROJECT:lldb-26" "\n";
+extern const double lldbVersionNumber __attribute__ ((used)) = (double)26.;
+extern const double LLDBVersionNumber __attribute__ ((used)) = (double)26.;
+}
+
+#include "main.moc"
diff --git a/src/plugins/debugger/lldb/guest/qtcreator-lldb.plist b/src/plugins/debugger/lldb/guest/qtcreator-lldb.plist
new file mode 100644
index 0000000000..847183c8a9
--- /dev/null
+++ b/src/plugins/debugger/lldb/guest/qtcreator-lldb.plist
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.nokia.qtcreator-lldb</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>Qt Creator LLDB Guest</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>SecTaskAccess</key>
+ <array>
+ <string>allowed</string>
+ <string>safe</string>
+ </array>
+</dict>
+</plist>
diff --git a/src/plugins/debugger/lldb/guest/qtcreator-lldb.pri b/src/plugins/debugger/lldb/guest/qtcreator-lldb.pri
new file mode 100644
index 0000000000..f44c3e9c84
--- /dev/null
+++ b/src/plugins/debugger/lldb/guest/qtcreator-lldb.pri
@@ -0,0 +1,2 @@
+WITH_LLDB = $$(WITH_LLDB)
+macx: !isEmpty(WITH_LLDB) : SUBDIRS += $$PWD/qtcreator-lldb.pro
diff --git a/src/plugins/debugger/lldb/guest/qtcreator-lldb.pro b/src/plugins/debugger/lldb/guest/qtcreator-lldb.pro
new file mode 100644
index 0000000000..55688aad53
--- /dev/null
+++ b/src/plugins/debugger/lldb/guest/qtcreator-lldb.pro
@@ -0,0 +1,61 @@
+WITH_LLDB = $$(WITH_LLDB)
+
+!macx: error (This can only be built on mac)
+!exists($${WITH_LLDB}/include/lldb/lldb-enumerations.h): error(please see the README for build instructions)
+
+include(../../../../../qtcreator.pri)
+TEMPLATE = app
+CONFIG -= app_bundle
+CONFIG += debug
+TARGET = qtcreator-lldb
+DEPENDPATH += . .. ../.. ../../.. ../../../../libs
+INCLUDEPATH += . .. ../.. ../../.. ../../../../libs
+DESTDIR = $$IDE_LIBEXEC_PATH
+
+QT = core network
+
+MOC_DIR=.tmp
+OBJECTS_DIR=.tmp
+
+HEADERS += ../ipcengineguest.h \
+ ../debuggerstreamops.h \
+ ../breakpoint.h \
+ ../watchdata.h \
+ ../stackframe.h \
+ ../disassemblerlines.h \
+ lldbengineguest.h
+
+SOURCES += ../ipcengineguest.cpp \
+ ../debuggerstreamops.cpp \
+ ../breakpoint.cpp \
+ ../watchdata.cpp \
+ ../stackframe.cpp \
+ ../disassemblerlines.cpp \
+ lldbengineguest.cpp \
+ main.cpp
+
+
+LIBS += -sectcreate __TEXT __info_plist $$PWD/qtcreator-lldb.plist
+
+POSTL = rm -rf \'$${IDE_LIBEXEC_PATH}/LLDB.framework\' $$escape_expand(\\n\\t) \
+ $$QMAKE_COPY_DIR $${WITH_LLDB}/build/Release/* \'$$IDE_LIBEXEC_PATH\' $$escape_expand(\\n\\t) \
+ install_name_tool -change '@rpath/LLDB.framework/Versions/A/LLDB' '@executable_path/LLDB.framework/Versions/A/LLDB' $(TARGET) $$escape_expand(\\n\\t) \
+ codesign -s lldb_codesign $(TARGET)
+
+!isEmpty(QMAKE_POST_LINK):QMAKE_POST_LINK = $$escape_expand(\\n\\t)$$QMAKE_POST_LINK
+QMAKE_POST_LINK = $$POSTL $$QMAKE_POST_LINK
+silent:QMAKE_POST_LINK = @echo signing $@ && $$QMAKE_POST_LINK
+
+LIBS += -framework Security -framework Python
+
+DEFINES += __STDC_LIMIT_MACROS __STDC_CONSTANT_MACROS
+
+INCLUDEPATH += $${WITH_LLDB}/include $${WITH_LLDB}/llvm/include/
+LIBS += -F$${WITH_LLDB}/build/Release -framework LLDB
+
+# include (lldb.pri)
+# DEFINES += HAVE_LLDB_PRIVATE
+# HEADERS += pygdbmiemu.h
+# SOURCES += pygdbmiemu.cpp
+
+
diff --git a/src/plugins/debugger/lldb/ipcengineguest.cpp b/src/plugins/debugger/lldb/ipcengineguest.cpp
new file mode 100644
index 0000000000..c7839fad61
--- /dev/null
+++ b/src/plugins/debugger/lldb/ipcengineguest.cpp
@@ -0,0 +1,637 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "ipcengineguest.h"
+#include "ipcenginehost.h"
+#include "breakpoint.h"
+#include "stackframe.h"
+#include "threaddata.h"
+#include "debuggerstreamops.h"
+
+#include <QSysInfo>
+#include <QDebug>
+#include <QFileInfo>
+#include <QTimer>
+#include <utils/qtcassert.h>
+#include <QLocalSocket>
+
+#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+#define SET_NATIVE_BYTE_ORDER(x) x.setByteOrder(QDataStream::LittleEndian)
+#else
+#define SET_NATIVE_BYTE_ORDER(x) x.setByteOrder(QDataStream::BigEndian)
+#endif
+
+namespace Debugger {
+namespace Internal {
+
+IPCEngineGuest::IPCEngineGuest()
+ : QObject()
+ , m_local_host(0)
+ , m_nextMessagePayloadSize(0)
+ , m_cookie(1)
+ , m_device(0)
+{
+}
+
+IPCEngineGuest::~IPCEngineGuest()
+{
+}
+
+void IPCEngineGuest::setLocalHost(IPCEngineHost *host)
+{
+ m_local_host = host;
+}
+
+void IPCEngineGuest::setHostDevice(QIODevice *device)
+{
+ if (m_device) {
+ disconnect(m_device, SIGNAL(readyRead()), this, SLOT(readyRead()));
+ delete m_device;
+ }
+ m_device = device;
+ if (m_device)
+ connect(m_device, SIGNAL(readyRead()), SLOT(readyRead()));
+}
+
+void IPCEngineGuest::rpcCall(Function f, QByteArray payload)
+{
+#if 0
+ if (m_local_host) {
+ QMetaObject::invokeMethod(m_local_host,
+ "rpcCallback",
+ Qt::QueuedConnection,
+ Q_ARG(quint64, f),
+ Q_ARG(QByteArray, payload));
+ } else
+#endif
+ if (m_device) {
+ {
+ QDataStream s(m_device);
+ SET_NATIVE_BYTE_ORDER(s);
+ s << m_cookie++;
+ s << quint64(f);
+ s << quint64(payload.size());
+ }
+ m_device->write(payload);
+ m_device->putChar('T');
+ QLocalSocket *sock = qobject_cast<QLocalSocket *>(m_device);
+ if (sock)
+ sock->flush();
+ }
+}
+
+void IPCEngineGuest::readyRead()
+{
+ if (!m_nextMessagePayloadSize) {
+ if (quint64(m_device->bytesAvailable()) < 3 * sizeof(quint64))
+ return;
+ QDataStream s(m_device);
+ SET_NATIVE_BYTE_ORDER(s);
+ s >> m_nextMessageCookie;
+ s >> m_nextMessageFunction;
+ s >> m_nextMessagePayloadSize;
+ m_nextMessagePayloadSize += 1; // terminator and "got header" marker
+ }
+
+ quint64 ba = m_device->bytesAvailable();
+ if (ba < m_nextMessagePayloadSize)
+ return;
+
+ qint64 rrr = m_nextMessagePayloadSize;
+ QByteArray payload = m_device->read(rrr);
+ if (quint64(payload.size()) != m_nextMessagePayloadSize || !payload.endsWith('T')) {
+ qDebug("IPC Error: corrupted frame");
+ showMessage(QLatin1String("[guest] IPC Error: corrupted frame"), LogError);
+ nuke();
+ return;
+ }
+ payload.chop(1);
+ rpcCallback(m_nextMessageFunction, payload);
+ m_nextMessagePayloadSize = 0;
+
+ if (quint64(m_device->bytesAvailable ()) >= 3 * sizeof(quint64))
+ QTimer::singleShot(0, this, SLOT(readyRead()));
+}
+
+void IPCEngineGuest::rpcCallback(quint64 f, QByteArray payload)
+{
+ switch (f) {
+ default:
+ qDebug("IPC Error: unhandled id in host to guest call");
+ showMessage(QLatin1String("IPC Error: unhandled id in host to guest call"), LogError);
+ nuke();
+ break;
+ case IPCEngineHost::SetupIPC:
+ {
+ QDataStream s(payload);
+ SET_NATIVE_BYTE_ORDER(s);
+ int version;
+ s >> version;
+ Q_ASSERT(version == 1);
+ }
+ break;
+ case IPCEngineHost::StateChanged:
+ {
+ QDataStream s(payload);
+ SET_NATIVE_BYTE_ORDER(s);
+ quint64 st;
+ s >> st;
+ m_state = (DebuggerState)st;
+ }
+ break;
+ case IPCEngineHost::SetupEngine:
+ setupEngine();
+ break;
+ case IPCEngineHost::SetupInferior:
+ {
+ QDataStream s(payload);
+ SET_NATIVE_BYTE_ORDER(s);
+ QString executable;
+ QStringList arguments;
+ QStringList environment;
+ s >> executable;
+ s >> arguments;
+ s >> environment;
+ setupInferior(executable, arguments, environment);
+ }
+ break;
+ case IPCEngineHost::RunEngine:
+ runEngine();
+ break;
+ case IPCEngineHost::ShutdownInferior:
+ shutdownInferior();
+ break;
+ case IPCEngineHost::ShutdownEngine:
+ shutdownEngine();
+ break;
+ case IPCEngineHost::DetachDebugger:
+ detachDebugger();
+ break;
+ case IPCEngineHost::ExecuteStep:
+ executeStep();
+ break;
+ case IPCEngineHost::ExecuteStepOut:
+ executeStepOut();
+ break;
+ case IPCEngineHost::ExecuteNext:
+ executeNext();
+ break;
+ case IPCEngineHost::ExecuteStepI:
+ executeStepI();
+ break;
+ case IPCEngineHost::ExecuteNextI:
+ executeNextI();
+ break;
+ case IPCEngineHost::ContinueInferior:
+ continueInferior();
+ break;
+ case IPCEngineHost::InterruptInferior:
+ interruptInferior();
+ break;
+ case IPCEngineHost::ExecuteRunToLine:
+ {
+ QDataStream s(payload);
+ SET_NATIVE_BYTE_ORDER(s);
+ QString fileName;
+ quint64 lineNumber;
+ s >> fileName;
+ s >> lineNumber;
+ executeRunToLine(fileName, lineNumber);
+ }
+ break;
+ case IPCEngineHost::ExecuteRunToFunction:
+ {
+ QDataStream s(payload);
+ SET_NATIVE_BYTE_ORDER(s);
+ QString functionName;
+ s >> functionName;
+ executeRunToFunction(functionName);
+ }
+ break;
+ case IPCEngineHost::ExecuteJumpToLine:
+ {
+ QDataStream s(payload);
+ SET_NATIVE_BYTE_ORDER(s);
+ QString fileName;
+ quint64 lineNumber;
+ s >> fileName;
+ s >> lineNumber;
+ executeJumpToLine(fileName, lineNumber);
+ }
+ break;
+ case IPCEngineHost::ActivateFrame:
+ {
+ QDataStream s(payload);
+ SET_NATIVE_BYTE_ORDER(s);
+ quint64 id;
+ s >> id;
+ activateFrame(id);
+ }
+ break;
+ case IPCEngineHost::SelectThread:
+ {
+ QDataStream s(payload);
+ SET_NATIVE_BYTE_ORDER(s);
+ quint64 id;
+ s >> id;
+ selectThread(id);
+ }
+ break;
+ case IPCEngineHost::Disassemble:
+ {
+ QDataStream s(payload);
+ SET_NATIVE_BYTE_ORDER(s);
+ quint64 pc;
+ s >> pc;
+ disassemble(pc);
+ }
+ break;
+ case IPCEngineHost::AddBreakpoint:
+ {
+ QDataStream s(payload);
+ SET_NATIVE_BYTE_ORDER(s);
+ BreakpointId id;
+ BreakpointParameters d;
+ s >> id;
+ s >> d;
+ addBreakpoint(id, d);
+ }
+ break;
+ case IPCEngineHost::RemoveBreakpoint:
+ {
+ QDataStream s(payload);
+ SET_NATIVE_BYTE_ORDER(s);
+ BreakpointId id;
+ s >> id;
+ removeBreakpoint(id);
+ }
+ break;
+ case IPCEngineHost::ChangeBreakpoint:
+ {
+ QDataStream s(payload);
+ SET_NATIVE_BYTE_ORDER(s);
+ BreakpointId id;
+ BreakpointParameters d;
+ s >> id;
+ s >> d;
+ changeBreakpoint(id, d);
+ }
+ break;
+ case IPCEngineHost::RequestUpdateWatchData:
+ {
+ QDataStream s(payload);
+ SET_NATIVE_BYTE_ORDER(s);
+ WatchData data;
+ s >> data;
+ requestUpdateWatchData(data);
+ }
+ break;
+ case IPCEngineHost::FetchFrameSource:
+ {
+ QDataStream s(payload);
+ SET_NATIVE_BYTE_ORDER(s);
+ qint64 id;
+ s >> id;
+ fetchFrameSource(id);
+ }
+ break;
+ };
+}
+
+DebuggerState IPCEngineGuest::state() const
+{
+ return m_state;
+}
+
+void IPCEngineGuest::notifyEngineSetupOk()
+{
+ rpcCall(NotifyEngineSetupOk);
+}
+
+void IPCEngineGuest::notifyEngineSetupFailed()
+{
+ rpcCall(NotifyEngineSetupFailed);
+}
+
+void IPCEngineGuest::notifyEngineRunFailed()
+{
+ rpcCall(NotifyEngineRunFailed);
+}
+
+void IPCEngineGuest::notifyInferiorSetupOk()
+{
+ rpcCall(NotifyInferiorSetupOk);
+}
+
+void IPCEngineGuest::notifyInferiorSetupFailed()
+{
+ rpcCall(NotifyInferiorSetupFailed);
+}
+
+void IPCEngineGuest::notifyEngineRunAndInferiorRunOk()
+{
+ rpcCall(NotifyEngineRunAndInferiorRunOk);
+}
+
+void IPCEngineGuest::notifyEngineRunAndInferiorStopOk()
+{
+ rpcCall(NotifyEngineRunAndInferiorStopOk);
+}
+
+void IPCEngineGuest::notifyInferiorRunRequested()
+{
+ rpcCall(NotifyInferiorRunRequested);
+}
+
+void IPCEngineGuest::notifyInferiorRunOk()
+{
+ rpcCall(NotifyInferiorRunOk);
+}
+
+void IPCEngineGuest::notifyInferiorRunFailed()
+{
+ rpcCall(NotifyInferiorRunFailed);
+}
+
+void IPCEngineGuest::notifyInferiorStopOk()
+{
+ rpcCall(NotifyInferiorStopOk);
+}
+
+void IPCEngineGuest::notifyInferiorSpontaneousStop()
+{
+ rpcCall(NotifyInferiorSpontaneousStop);
+}
+
+void IPCEngineGuest::notifyInferiorStopFailed()
+{
+ rpcCall(NotifyInferiorStopFailed);
+}
+
+void IPCEngineGuest::notifyInferiorExited()
+{
+ rpcCall(NotifyInferiorExited);
+}
+
+void IPCEngineGuest::notifyInferiorShutdownOk()
+{
+ rpcCall(NotifyInferiorShutdownOk);
+}
+
+void IPCEngineGuest::notifyInferiorShutdownFailed()
+{
+ rpcCall(NotifyInferiorShutdownFailed);
+}
+
+void IPCEngineGuest::notifyEngineSpontaneousShutdown()
+{
+ rpcCall(NotifyEngineSpontaneousShutdown);
+}
+
+void IPCEngineGuest::notifyEngineShutdownOk()
+{
+ rpcCall(NotifyEngineShutdownOk);
+}
+
+void IPCEngineGuest::notifyEngineShutdownFailed()
+{
+ rpcCall(NotifyEngineShutdownFailed);
+}
+
+void IPCEngineGuest::notifyInferiorIll()
+{
+ rpcCall(NotifyInferiorIll);
+}
+
+void IPCEngineGuest::notifyEngineIll()
+{
+ rpcCall(NotifyEngineIll);
+}
+
+void IPCEngineGuest::notifyInferiorPid(qint64 pid)
+{
+ QByteArray p;
+ {
+ QDataStream s(&p, QIODevice::WriteOnly);
+ SET_NATIVE_BYTE_ORDER(s);
+ s << pid;
+ }
+ rpcCall(NotifyInferiorPid, p);
+}
+
+void IPCEngineGuest::showStatusMessage(const QString &msg, quint64 timeout)
+{
+ QByteArray p;
+ {
+ QDataStream s(&p, QIODevice::WriteOnly);
+ SET_NATIVE_BYTE_ORDER(s);
+ s << msg;
+ s << (qint64)timeout;
+ }
+ rpcCall(ShowStatusMessage, p);
+}
+
+void IPCEngineGuest::showMessage(const QString &msg, quint16 channel, quint64 timeout)
+{
+ QByteArray p;
+ {
+ QDataStream s(&p, QIODevice::WriteOnly);
+ SET_NATIVE_BYTE_ORDER(s);
+ s << msg;
+ s << (qint64)channel;
+ s << (qint64)timeout;
+ }
+ rpcCall(ShowMessage, p);
+}
+
+void IPCEngineGuest::currentFrameChanged(qint64 osid)
+{
+ QByteArray p;
+ {
+ QDataStream s(&p, QIODevice::WriteOnly);
+ SET_NATIVE_BYTE_ORDER(s);
+ s << osid;
+ }
+ rpcCall(CurrentFrameChanged, p);
+}
+
+void IPCEngineGuest::currentThreadChanged(qint64 osid)
+{
+ QByteArray p;
+ {
+ QDataStream s(&p, QIODevice::WriteOnly);
+ SET_NATIVE_BYTE_ORDER(s);
+ s << osid;
+ }
+ rpcCall(CurrentThreadChanged, p);
+}
+
+void IPCEngineGuest::listFrames(const StackFrames &frames)
+{
+ QByteArray p;
+ {
+ QDataStream s(&p, QIODevice::WriteOnly);
+ SET_NATIVE_BYTE_ORDER(s);
+ s << frames;
+ }
+ rpcCall(ListFrames, p);
+}
+
+void IPCEngineGuest::listThreads(const Threads &threads)
+{
+ QByteArray p;
+ {
+ QDataStream s(&p, QIODevice::WriteOnly);
+ SET_NATIVE_BYTE_ORDER(s);
+ s << threads;
+ }
+ rpcCall(ListThreads, p);
+}
+
+void IPCEngineGuest::disassembled(quint64 pc, const DisassemblerLines &da)
+{
+ QByteArray p;
+ {
+ QDataStream s(&p, QIODevice::WriteOnly);
+ SET_NATIVE_BYTE_ORDER(s);
+ s << pc;
+ s << da;
+ }
+ rpcCall(Disassembled, p);
+}
+
+void IPCEngineGuest::notifyAddBreakpointOk(BreakpointId id)
+{
+ QByteArray p;
+ {
+ QDataStream s(&p, QIODevice::WriteOnly);
+ SET_NATIVE_BYTE_ORDER(s);
+ s << id;
+ }
+ rpcCall(NotifyAddBreakpointOk, p);
+}
+
+void IPCEngineGuest::notifyAddBreakpointFailed(BreakpointId id)
+{
+ QByteArray p;
+ {
+ QDataStream s(&p, QIODevice::WriteOnly);
+ SET_NATIVE_BYTE_ORDER(s);
+ s << id;
+ }
+ rpcCall(NotifyAddBreakpointFailed, p);
+}
+
+void IPCEngineGuest::notifyRemoveBreakpointOk(BreakpointId id)
+{
+ QByteArray p;
+ {
+ QDataStream s(&p, QIODevice::WriteOnly);
+ SET_NATIVE_BYTE_ORDER(s);
+ s << id;
+ }
+ rpcCall(NotifyRemoveBreakpointOk, p);
+}
+
+void IPCEngineGuest::notifyRemoveBreakpointFailed(BreakpointId id)
+{
+ QByteArray p;
+ {
+ QDataStream s(&p, QIODevice::WriteOnly);
+ SET_NATIVE_BYTE_ORDER(s);
+ s << id;
+ }
+ rpcCall(NotifyRemoveBreakpointFailed, p);
+}
+
+void IPCEngineGuest::notifyChangeBreakpointOk(BreakpointId id)
+{
+ QByteArray p;
+ {
+ QDataStream s(&p, QIODevice::WriteOnly);
+ SET_NATIVE_BYTE_ORDER(s);
+ s << id;
+ }
+ rpcCall(NotifyChangeBreakpointOk, p);
+}
+
+void IPCEngineGuest::notifyChangeBreakpointFailed(BreakpointId id)
+{
+ QByteArray p;
+ {
+ QDataStream s(&p, QIODevice::WriteOnly);
+ SET_NATIVE_BYTE_ORDER(s);
+ s << id;
+ }
+ rpcCall(NotifyChangeBreakpointFailed, p);
+}
+
+void IPCEngineGuest::notifyBreakpointAdjusted(BreakpointId id,
+ const BreakpointParameters &bp)
+{
+ QByteArray p;
+ {
+ QDataStream s(&p, QIODevice::WriteOnly);
+ SET_NATIVE_BYTE_ORDER(s);
+ s << id << bp;
+ }
+ rpcCall(NotifyBreakpointAdjusted, p);
+}
+
+void IPCEngineGuest::updateWatchData(bool fullCycle, const QList<WatchData> &wd)
+{
+ QByteArray p;
+ {
+ QDataStream s(&p, QIODevice::WriteOnly);
+ SET_NATIVE_BYTE_ORDER(s);
+ s << fullCycle;
+ s << quint64(wd.count());
+ for (int i = 0; i < wd.count(); ++i)
+ s << wd.at(i);
+ }
+ rpcCall(UpdateWatchData, p);
+}
+
+void IPCEngineGuest::frameSourceFetched(qint64 id, const QString &name, const QString &source)
+{
+ QByteArray p;
+ {
+ QDataStream s(&p, QIODevice::WriteOnly);
+ SET_NATIVE_BYTE_ORDER(s);
+ s << id;
+ s << name;
+ s << source;
+ }
+ rpcCall(FrameSourceFetched, p);
+}
+
+} // namespace Internal
+} // namespace Debugger
+
+
diff --git a/src/plugins/debugger/lldb/ipcengineguest.h b/src/plugins/debugger/lldb/ipcengineguest.h
new file mode 100644
index 0000000000..ce5189ef73
--- /dev/null
+++ b/src/plugins/debugger/lldb/ipcengineguest.h
@@ -0,0 +1,191 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 DEBUGGER_IPCENGINE_H
+#define DEBUGGER_IPCENGINE_H
+
+#include "breakhandler.h"
+#include "debuggerengine.h"
+#include "disassemblerlines.h"
+#include "stackhandler.h"
+#include "threadshandler.h"
+
+#include <QtCore/QQueue>
+#include <QtCore/QThread>
+#include <QtCore/QVariant>
+
+namespace Debugger {
+namespace Internal {
+
+class IPCEngineHost;
+class IPCEngineGuest : public QObject
+{
+ Q_OBJECT
+
+public:
+ IPCEngineGuest();
+ virtual ~IPCEngineGuest();
+
+ void setLocalHost(IPCEngineHost *);
+ void setHostDevice(QIODevice *);
+
+ virtual void nuke() = 0;
+ virtual void setupEngine() = 0;
+ virtual void setupInferior(const QString &executeable,
+ const QStringList &arguments, const QStringList &environment) = 0;
+ virtual void runEngine() = 0;
+ virtual void shutdownInferior() = 0;
+ virtual void shutdownEngine() = 0;
+ virtual void detachDebugger() = 0;
+ virtual void executeStep() = 0;
+ virtual void executeStepOut() = 0;
+ virtual void executeNext() = 0;
+ virtual void executeStepI() = 0;
+ virtual void executeNextI() = 0;
+ virtual void continueInferior() = 0;
+ virtual void interruptInferior() = 0;
+ virtual void executeRunToLine(const QString &fileName, int lineNumber) = 0;
+ virtual void executeRunToFunction(const QString &functionName) = 0;
+ virtual void executeJumpToLine(const QString &fileName, int lineNumber) = 0;
+ virtual void activateFrame(qint64 token) = 0;
+ virtual void selectThread(qint64 token) = 0;
+ virtual void disassemble(quint64 pc) = 0;
+ virtual void addBreakpoint(BreakpointId id, const BreakpointParameters &bp) = 0;
+ virtual void removeBreakpoint(BreakpointId id) = 0;
+ virtual void changeBreakpoint(BreakpointId id, const BreakpointParameters &bp) = 0;
+ virtual void requestUpdateWatchData(const WatchData &data,
+ const WatchUpdateFlags & flags = WatchUpdateFlags()) = 0;
+ virtual void fetchFrameSource(qint64 frame) = 0;
+
+ enum Function
+ {
+ NotifyEngineSetupOk = 1,
+ NotifyEngineSetupFailed = 2,
+ NotifyEngineRunFailed = 3,
+ NotifyInferiorSetupOk = 4,
+ NotifyInferiorSetupFailed = 5,
+ NotifyEngineRunAndInferiorRunOk = 6,
+ NotifyEngineRunAndInferiorStopOk = 7,
+ NotifyInferiorRunRequested = 8,
+ NotifyInferiorRunOk = 9,
+ NotifyInferiorRunFailed = 10,
+ NotifyInferiorStopOk = 11,
+ NotifyInferiorSpontaneousStop = 12,
+ NotifyInferiorStopFailed = 13,
+ NotifyInferiorExited = 14,
+ NotifyInferiorShutdownOk = 15,
+ NotifyInferiorShutdownFailed = 16,
+ NotifyEngineSpontaneousShutdown = 17,
+ NotifyEngineShutdownOk = 18,
+ NotifyEngineShutdownFailed = 19,
+ NotifyInferiorIll = 20,
+ NotifyEngineIll = 21,
+ NotifyInferiorPid = 22,
+ ShowStatusMessage = 23,
+ ShowMessage = 24,
+ CurrentFrameChanged = 25,
+ CurrentThreadChanged = 26,
+ ListFrames = 27,
+ ListThreads = 28,
+ Disassembled = 29,
+ NotifyAddBreakpointOk = 30,
+ NotifyAddBreakpointFailed = 31,
+ NotifyRemoveBreakpointOk = 32,
+ NotifyRemoveBreakpointFailed = 33,
+ NotifyChangeBreakpointOk = 34,
+ NotifyChangeBreakpointFailed = 35,
+ NotifyBreakpointAdjusted = 36,
+ UpdateWatchData = 47,
+ FrameSourceFetched = 48
+ };
+ Q_ENUMS(Function)
+
+ DebuggerState state() const;
+ void notifyEngineSetupOk();
+ void notifyEngineSetupFailed();
+ void notifyEngineRunFailed();
+ void notifyInferiorSetupOk();
+ void notifyInferiorSetupFailed();
+ void notifyEngineRunAndInferiorRunOk();
+ void notifyEngineRunAndInferiorStopOk();
+ void notifyInferiorRunRequested();
+ void notifyInferiorRunOk();
+ void notifyInferiorRunFailed();
+ void notifyInferiorStopOk();
+ void notifyInferiorSpontaneousStop();
+ void notifyInferiorStopFailed();
+ void notifyInferiorExited();
+ void notifyInferiorShutdownOk();
+ void notifyInferiorShutdownFailed();
+ void notifyEngineSpontaneousShutdown();
+ void notifyEngineShutdownOk();
+ void notifyEngineShutdownFailed();
+ void notifyInferiorIll();
+ void notifyEngineIll();
+ void notifyInferiorPid(qint64 pid);
+ void showMessage(const QString &msg, quint16 channel = LogDebug, quint64 timeout = -1);
+ void showStatusMessage(const QString &msg, quint64 timeout = -1);
+
+ void currentFrameChanged(qint64 token);
+ void currentThreadChanged(qint64 token);
+ void listFrames(const StackFrames &);
+ void listThreads(const Threads &);
+ void disassembled(quint64 pc, const DisassemblerLines &da);
+
+ void notifyAddBreakpointOk(BreakpointId id);
+ void notifyAddBreakpointFailed(BreakpointId id);
+ void notifyRemoveBreakpointOk(BreakpointId id);
+ void notifyRemoveBreakpointFailed(BreakpointId id);
+ void notifyChangeBreakpointOk(BreakpointId id);
+ void notifyChangeBreakpointFailed(BreakpointId id);
+ void notifyBreakpointAdjusted(BreakpointId id, const BreakpointParameters &bp);
+
+ void updateWatchData(bool fullCycle, const QList<WatchData> &);
+
+ void frameSourceFetched(qint64 frame, const QString &name, const QString &sourceCode);
+
+ void rpcCall(Function f, QByteArray payload = QByteArray());
+public slots:
+ void rpcCallback(quint64 f, QByteArray payload = QByteArray());
+private slots:
+ void readyRead();
+private:
+ IPCEngineHost *m_local_host;
+ quint64 m_nextMessageCookie;
+ quint64 m_nextMessageFunction;
+ quint64 m_nextMessagePayloadSize;
+ quint64 m_cookie;
+ QIODevice *m_device;
+ DebuggerState m_state;
+};
+
+} // namespace Internal
+} // namespace Debugger
+
+#endif // DEBUGGER_LLDBENGINE_H
diff --git a/src/plugins/debugger/lldb/ipcenginehost.cpp b/src/plugins/debugger/lldb/ipcenginehost.cpp
new file mode 100644
index 0000000000..c5fb023cf5
--- /dev/null
+++ b/src/plugins/debugger/lldb/ipcenginehost.cpp
@@ -0,0 +1,655 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "ipcenginehost.h"
+
+#include "ipcengineguest.h"
+#include "breakhandler.h"
+#include "breakpoint.h"
+#include "disassemblerlines.h"
+#include "moduleshandler.h"
+#include "registerhandler.h"
+#include "stackhandler.h"
+#include "watchhandler.h"
+#include "watchutils.h"
+#include "threadshandler.h"
+#include "disassembleragent.h"
+#include "memoryagent.h"
+#include "debuggerstreamops.h"
+#include "debuggercore.h"
+
+#include <utils/qtcassert.h>
+
+#include <QSysInfo>
+#include <QDebug>
+#include <QFileInfo>
+#include <QTimer>
+#include <QLocalSocket>
+
+#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+#define SET_NATIVE_BYTE_ORDER(x) x.setByteOrder(QDataStream::LittleEndian)
+#else
+#define SET_NATIVE_BYTE_ORDER(x) x.setByteOrder(QDataStream::BigEndian)
+#endif
+
+namespace Debugger {
+namespace Internal {
+
+IPCEngineHost::IPCEngineHost (const DebuggerStartParameters &startParameters)
+ : DebuggerEngine(startParameters)
+ , m_localGuest(0)
+ , m_nextMessagePayloadSize(0)
+ , m_cookie(1)
+ , m_device(0)
+{
+ connect(this, SIGNAL(stateChanged(DebuggerState)), SLOT(m_stateChanged(DebuggerState)));
+}
+
+IPCEngineHost::~IPCEngineHost()
+{
+ delete m_device;
+}
+
+void IPCEngineHost::setLocalGuest(IPCEngineGuest *guest)
+{
+ m_localGuest = guest;
+}
+
+void IPCEngineHost::setGuestDevice(QIODevice *device)
+{
+ if (m_device) {
+ disconnect(m_device, SIGNAL(readyRead()), this, SLOT(readyRead()));
+ delete m_device;
+ }
+ m_device = device;
+ if (m_device)
+ connect(m_device, SIGNAL(readyRead()), this, SLOT(readyRead()));
+}
+
+void IPCEngineHost::setupEngine()
+{
+ QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
+ rpcCall(SetupEngine);
+}
+
+void IPCEngineHost::setupInferior()
+{
+ QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
+ QByteArray p;
+ {
+ QDataStream s(&p, QIODevice::WriteOnly);
+ SET_NATIVE_BYTE_ORDER(s);
+ s << QFileInfo(startParameters().executable).absoluteFilePath();
+ s << startParameters().processArgs;
+ s << startParameters().environment.toStringList();
+ }
+ rpcCall(SetupInferior, p);
+}
+
+void IPCEngineHost::runEngine()
+{
+ QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
+ rpcCall(RunEngine);
+}
+
+void IPCEngineHost::shutdownInferior()
+{
+ QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state());
+ rpcCall(ShutdownInferior);
+}
+
+void IPCEngineHost::shutdownEngine()
+{
+ rpcCall(ShutdownEngine);
+}
+
+void IPCEngineHost::detachDebugger()
+{
+ rpcCall(DetachDebugger);
+}
+
+void IPCEngineHost::executeStep()
+{
+ rpcCall(ExecuteStep);
+}
+
+void IPCEngineHost::executeStepOut()
+{
+ rpcCall(ExecuteStepOut);
+}
+
+void IPCEngineHost::executeNext()
+{
+ rpcCall(ExecuteNext);
+}
+
+void IPCEngineHost::executeStepI()
+{
+ rpcCall(ExecuteStepI);
+}
+
+void IPCEngineHost::executeNextI()
+{
+ rpcCall(ExecuteNextI);
+}
+
+void IPCEngineHost::continueInferior()
+{
+ QTC_ASSERT(state() == InferiorStopOk, qDebug() << state());
+ resetLocation();
+ rpcCall(ContinueInferior);
+}
+
+void IPCEngineHost::interruptInferior()
+{
+ QTC_ASSERT(state() == InferiorStopRequested, qDebug() << state());
+ rpcCall(InterruptInferior);
+}
+
+void IPCEngineHost::executeRunToLine(const QString &fileName, int lineNumber)
+{
+ QByteArray p;
+ {
+ QDataStream s(&p, QIODevice::WriteOnly);
+ SET_NATIVE_BYTE_ORDER(s);
+ s << fileName;
+ s << quint64(lineNumber);
+ }
+ rpcCall(ExecuteRunToLine, p);
+}
+
+void IPCEngineHost::executeRunToFunction(const QString &functionName)
+{
+ QByteArray p;
+ {
+ QDataStream s(&p, QIODevice::WriteOnly);
+ SET_NATIVE_BYTE_ORDER(s);
+ s << functionName;
+ }
+ rpcCall(ExecuteRunToFunction, p);
+}
+
+void IPCEngineHost::executeJumpToLine(const QString &fileName, int lineNumber)
+{
+ QByteArray p;
+ {
+ QDataStream s(&p, QIODevice::WriteOnly);
+ SET_NATIVE_BYTE_ORDER(s);
+ s << fileName;
+ s << quint64(lineNumber);
+ }
+ rpcCall(ExecuteJumpToLine, p);
+}
+
+
+void IPCEngineHost::activateFrame(int index)
+{
+ resetLocation();
+ QByteArray p;
+ {
+ QDataStream s(&p, QIODevice::WriteOnly);
+ SET_NATIVE_BYTE_ORDER(s);
+ s << quint64(index);
+ }
+ rpcCall(ActivateFrame, p);
+}
+
+void IPCEngineHost::selectThread(int index)
+{
+ resetLocation();
+ Threads threads = threadsHandler()->threads();
+ QTC_ASSERT(index < threads.size(), return);
+ QByteArray p;
+ {
+ QDataStream s(&p, QIODevice::WriteOnly);
+ SET_NATIVE_BYTE_ORDER(s);
+ s << quint64(threads.at(index).id);
+ }
+ rpcCall(SelectThread, p);
+}
+
+void IPCEngineHost::fetchDisassembler(DisassemblerAgent *v)
+{
+ quint64 address = v->location().address();
+ m_frameToDisassemblerAgent.insert(address, v);
+ QByteArray p;
+ {
+ QDataStream s(&p, QIODevice::WriteOnly);
+ SET_NATIVE_BYTE_ORDER(s);
+ s << address;
+ }
+ rpcCall(Disassemble, p);
+}
+
+void IPCEngineHost::insertBreakpoint(BreakpointId id)
+{
+ breakHandler()->notifyBreakpointInsertProceeding(id);
+ QByteArray p;
+ {
+ QDataStream s(&p, QIODevice::WriteOnly);
+ SET_NATIVE_BYTE_ORDER(s);
+ s << id;
+ s << breakHandler()->breakpointData(id);
+ }
+ rpcCall(AddBreakpoint, p);
+}
+
+void IPCEngineHost::removeBreakpoint(BreakpointId id)
+{
+ breakHandler()->notifyBreakpointRemoveProceeding(id);
+ QByteArray p;
+ {
+ QDataStream s(&p, QIODevice::WriteOnly);
+ SET_NATIVE_BYTE_ORDER(s);
+ s << id;
+ }
+ rpcCall(RemoveBreakpoint, p);
+}
+
+void IPCEngineHost::changeBreakpoint(BreakpointId id)
+{
+ breakHandler()->notifyBreakpointChangeProceeding(id);
+ QByteArray p;
+ {
+ QDataStream s(&p, QIODevice::WriteOnly);
+ SET_NATIVE_BYTE_ORDER(s);
+ s << id;
+ s << breakHandler()->breakpointData(id);
+ }
+ rpcCall(RemoveBreakpoint, p);
+}
+
+void IPCEngineHost::updateWatchData(const WatchData &data,
+ const WatchUpdateFlags &flags)
+{
+ Q_UNUSED(flags);
+ QByteArray p;
+ {
+ QDataStream s(&p, QIODevice::WriteOnly);
+ SET_NATIVE_BYTE_ORDER(s);
+ s << data;
+ }
+ rpcCall(RequestUpdateWatchData, p);
+}
+
+void IPCEngineHost::fetchFrameSource(qint64 id)
+{
+ QByteArray p;
+ {
+ QDataStream s(&p, QIODevice::WriteOnly);
+ SET_NATIVE_BYTE_ORDER(s);
+ s << id;
+ }
+ rpcCall(FetchFrameSource, p);
+}
+
+void IPCEngineHost::rpcCallback(quint64 f, QByteArray payload)
+{
+ switch (f) {
+ default:
+ showMessage(QLatin1String("IPC Error: unhandled id in guest to host call"));
+ showMessage(tr("Fatal engine shutdown. Incompatible binary or ipc error."), LogError);
+ showStatusMessage(tr("Fatal engine shutdown. Incompatible binary or ipc error."));
+ nuke();
+ break;
+ case IPCEngineGuest::NotifyEngineSetupOk:
+ notifyEngineSetupOk();
+ break;
+ case IPCEngineGuest::NotifyEngineSetupFailed:
+ notifyEngineSetupFailed();
+ break;
+ case IPCEngineGuest::NotifyEngineRunFailed:
+ notifyEngineRunFailed();
+ break;
+ case IPCEngineGuest::NotifyInferiorSetupOk:
+ attemptBreakpointSynchronization();
+ notifyInferiorSetupOk();
+ break;
+ case IPCEngineGuest::NotifyInferiorSetupFailed:
+ notifyInferiorSetupFailed();
+ break;
+ case IPCEngineGuest::NotifyEngineRunAndInferiorRunOk:
+ notifyEngineRunAndInferiorRunOk();
+ break;
+ case IPCEngineGuest::NotifyEngineRunAndInferiorStopOk:
+ notifyEngineRunAndInferiorStopOk();
+ break;
+ case IPCEngineGuest::NotifyInferiorRunRequested:
+ notifyInferiorRunRequested();
+ break;
+ case IPCEngineGuest::NotifyInferiorRunOk:
+ notifyInferiorRunOk();
+ break;
+ case IPCEngineGuest::NotifyInferiorRunFailed:
+ notifyInferiorRunFailed();
+ break;
+ case IPCEngineGuest::NotifyInferiorStopOk:
+ notifyInferiorStopOk();
+ break;
+ case IPCEngineGuest::NotifyInferiorSpontaneousStop:
+ notifyInferiorSpontaneousStop();
+ break;
+ case IPCEngineGuest::NotifyInferiorStopFailed:
+ notifyInferiorStopFailed();
+ break;
+ case IPCEngineGuest::NotifyInferiorExited:
+ notifyInferiorExited();
+ break;
+ case IPCEngineGuest::NotifyInferiorShutdownOk:
+ notifyInferiorShutdownOk();
+ break;
+ case IPCEngineGuest::NotifyInferiorShutdownFailed:
+ notifyInferiorShutdownFailed();
+ break;
+ case IPCEngineGuest::NotifyEngineSpontaneousShutdown:
+ notifyEngineSpontaneousShutdown();
+ break;
+ case IPCEngineGuest::NotifyEngineShutdownOk:
+ notifyEngineShutdownOk();
+ break;
+ case IPCEngineGuest::NotifyEngineShutdownFailed:
+ notifyEngineShutdownFailed();
+ break;
+ case IPCEngineGuest::NotifyInferiorIll:
+ notifyInferiorIll();
+ break;
+ case IPCEngineGuest::NotifyEngineIll:
+ notifyEngineIll();
+ break;
+ case IPCEngineGuest::NotifyInferiorPid:
+ {
+ QDataStream s(payload);
+ SET_NATIVE_BYTE_ORDER(s);
+ quint64 pid;
+ s >> pid;
+ notifyInferiorPid(pid);
+ }
+ break;
+ case IPCEngineGuest::ShowStatusMessage:
+ {
+ QDataStream s(payload);
+ SET_NATIVE_BYTE_ORDER(s);
+ QString msg;
+ qint64 timeout;
+ s >> msg;
+ s >> timeout;
+ showStatusMessage(msg, timeout);
+ }
+ break;
+ case IPCEngineGuest::ShowMessage:
+ {
+ QDataStream s(payload);
+ SET_NATIVE_BYTE_ORDER(s);
+ QString msg;
+ qint16 channel;
+ qint64 timeout;
+ s >> msg;
+ s >> channel;
+ s >> timeout;
+ showMessage(msg, channel, timeout);
+ }
+ break;
+ case IPCEngineGuest::CurrentFrameChanged:
+ {
+ QDataStream s(payload);
+ SET_NATIVE_BYTE_ORDER(s);
+ quint64 token;
+ s >> token;
+
+ resetLocation();
+ StackHandler *sh = stackHandler();
+ sh->setCurrentIndex(token);
+ if (!sh->currentFrame().isUsable() || QFileInfo(sh->currentFrame().file).exists())
+ gotoLocation(Location(sh->currentFrame(), true));
+ else if (!m_sourceAgents.contains(sh->currentFrame().file))
+ fetchFrameSource(token);
+ foreach(SourceAgent *agent, m_sourceAgents.values())
+ agent->updateLocationMarker();
+ }
+ break;
+ case IPCEngineGuest::CurrentThreadChanged:
+ {
+ QDataStream s(payload);
+ SET_NATIVE_BYTE_ORDER(s);
+ quint64 token;
+ s >> token;
+ threadsHandler()->setCurrentThreadId(token);
+ }
+ break;
+ case IPCEngineGuest::ListFrames:
+ {
+ QDataStream s(payload);
+ SET_NATIVE_BYTE_ORDER(s);
+ StackFrames frames;
+ s >> frames;
+ stackHandler()->setFrames(frames);
+ }
+ break;
+ case IPCEngineGuest::ListThreads:
+ {
+ QDataStream s(payload);
+ SET_NATIVE_BYTE_ORDER(s);
+ Threads threads;
+ s >> threads;
+ threadsHandler()->setThreads(threads);
+ }
+ break;
+ case IPCEngineGuest::Disassembled:
+ {
+ QDataStream s(payload);
+ SET_NATIVE_BYTE_ORDER(s);
+ quint64 pc;
+ DisassemblerLines lines;
+ s >> pc;
+ s >> lines;
+ DisassemblerAgent *view = m_frameToDisassemblerAgent.take(pc);
+ if (view)
+ view->setContents(lines);
+ }
+ break;
+ case IPCEngineGuest::UpdateWatchData:
+ {
+ QDataStream s(payload);
+ SET_NATIVE_BYTE_ORDER(s);
+ bool fullCycle;
+ qint64 count;
+ QList<WatchData> wd;
+ s >> fullCycle;
+ s >> count;
+ for (qint64 i = 0; i < count; ++i) {
+ WatchData d;
+ s >> d;
+ wd.append(d);
+ }
+ WatchHandler *wh = watchHandler();
+ if (!wh)
+ break;
+ wh->beginCycle(fullCycle);
+ wh->insertBulkData(wd);
+ wh->endCycle(fullCycle);
+ }
+ break;
+ case IPCEngineGuest::NotifyAddBreakpointOk:
+ {
+ attemptBreakpointSynchronization();
+ QDataStream s(payload);
+ SET_NATIVE_BYTE_ORDER(s);
+ BreakpointId id;
+ s >> id;
+ breakHandler()->notifyBreakpointInsertOk(id);
+ }
+ break;
+ case IPCEngineGuest::NotifyAddBreakpointFailed:
+ {
+ QDataStream s(payload);
+ SET_NATIVE_BYTE_ORDER(s);
+ BreakpointId id;
+ s >> id;
+ breakHandler()->notifyBreakpointInsertFailed(id);
+ }
+ break;
+ case IPCEngineGuest::NotifyRemoveBreakpointOk:
+ {
+ QDataStream s(payload);
+ SET_NATIVE_BYTE_ORDER(s);
+ BreakpointId id;
+ s >> id;
+ breakHandler()->notifyBreakpointRemoveOk(id);
+ }
+ break;
+ case IPCEngineGuest::NotifyRemoveBreakpointFailed:
+ {
+ QDataStream s(payload);
+ SET_NATIVE_BYTE_ORDER(s);
+ BreakpointId id;
+ s >> id;
+ breakHandler()->notifyBreakpointRemoveFailed(id);
+ }
+ break;
+ case IPCEngineGuest::NotifyChangeBreakpointOk:
+ {
+ QDataStream s(payload);
+ SET_NATIVE_BYTE_ORDER(s);
+ BreakpointId id;
+ s >> id;
+ breakHandler()->notifyBreakpointChangeOk(id);
+ }
+ break;
+ case IPCEngineGuest::NotifyChangeBreakpointFailed:
+ {
+ QDataStream s(payload);
+ SET_NATIVE_BYTE_ORDER(s);
+ BreakpointId id;
+ s >> id;
+ breakHandler()->notifyBreakpointChangeFailed(id);
+ }
+ break;
+ case IPCEngineGuest::NotifyBreakpointAdjusted:
+ {
+ QDataStream s(payload);
+ SET_NATIVE_BYTE_ORDER(s);
+ BreakpointId id;
+ BreakpointParameters d;
+ s >> id >> d;
+ breakHandler()->notifyBreakpointAdjusted(id, d);
+ }
+ break;
+ case IPCEngineGuest::FrameSourceFetched:
+ {
+ QDataStream s(payload);
+ SET_NATIVE_BYTE_ORDER(s);
+ qint64 token;
+ QString path;
+ QString source;
+ s >> token >> path >> source;
+ SourceAgent *agent = new SourceAgent(this);
+ agent->setSourceProducerName(startParameters().connParams.host);
+ agent->setContent(path, source);
+ m_sourceAgents.insert(path, agent);
+ agent->updateLocationMarker();
+ }
+ break;
+ }
+}
+
+void IPCEngineHost::m_stateChanged(const DebuggerState &state)
+{
+ QByteArray p;
+ {
+ QDataStream s(&p, QIODevice::WriteOnly);
+ SET_NATIVE_BYTE_ORDER(s);
+ s << (qint64)state;
+ }
+ rpcCall(StateChanged, p);
+
+}
+
+void IPCEngineHost::rpcCall(Function f, QByteArray payload)
+{
+ if (m_localGuest) {
+ QMetaObject::invokeMethod(m_localGuest,
+ "rpcCallback",
+ Qt::QueuedConnection,
+ Q_ARG(quint64, f),
+ Q_ARG(QByteArray, payload));
+ } else if (m_device) {
+ QByteArray header;
+ {
+ QDataStream s(&header, QIODevice::WriteOnly);
+ SET_NATIVE_BYTE_ORDER(s);
+ s << m_cookie++;
+ s << (quint64) f;
+ s << (quint64) payload.size();
+ }
+ m_device->write(header);
+ m_device->write(payload);
+ m_device->putChar('T');
+ QLocalSocket *sock = qobject_cast<QLocalSocket *>(m_device);
+ if (sock)
+ sock->flush();
+ }
+}
+
+void IPCEngineHost::readyRead()
+{
+ QDataStream s(m_device);
+ SET_NATIVE_BYTE_ORDER(s);
+ if (!m_nextMessagePayloadSize) {
+ if (quint64(m_device->bytesAvailable ()) < 3 * sizeof(quint64))
+ return;
+ s >> m_nextMessageCookie;
+ s >> m_nextMessageFunction;
+ s >> m_nextMessagePayloadSize;
+ m_nextMessagePayloadSize += 1; // Terminator and "got header" marker.
+ }
+
+ quint64 ba = m_device->bytesAvailable();
+ if (ba < m_nextMessagePayloadSize)
+ return;
+
+ QByteArray payload = m_device->read(m_nextMessagePayloadSize - 1);
+
+ char terminator;
+ m_device->getChar(&terminator);
+ if (terminator != 'T') {
+ showStatusMessage(tr("Fatal engine shutdown. Incompatible binary or ipc error."));
+ showMessage(QLatin1String("IPC Error: terminator missing"));
+ nuke();
+ return;
+ }
+ rpcCallback(m_nextMessageFunction, payload);
+ m_nextMessagePayloadSize = 0;
+ if (quint64(m_device->bytesAvailable()) >= 3 * sizeof(quint64))
+ QTimer::singleShot(0, this, SLOT(readyRead()));
+}
+
+} // namespace Internal
+} // namespace Debugger
+
+
diff --git a/src/plugins/debugger/lldb/ipcenginehost.h b/src/plugins/debugger/lldb/ipcenginehost.h
new file mode 100644
index 0000000000..aa6eb534a4
--- /dev/null
+++ b/src/plugins/debugger/lldb/ipcenginehost.h
@@ -0,0 +1,139 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 DEBUGGER_IPCENGINE_HOST_H
+#define DEBUGGER_IPCENGINE_HOST_H
+
+#include "debuggerengine.h"
+#include "threadshandler.h"
+#include "stackhandler.h"
+#include "breakhandler.h"
+#include "sourceagent.h"
+
+#include <QtCore/QQueue>
+#include <QtCore/QVariant>
+#include <QtCore/QThread>
+
+namespace Debugger {
+namespace Internal {
+
+class IPCEngineGuest;
+class IPCEngineHost : public DebuggerEngine
+{
+ Q_OBJECT
+
+public:
+ explicit IPCEngineHost(const DebuggerStartParameters &startParameters);
+ ~IPCEngineHost();
+
+ // use either one
+ void setLocalGuest(IPCEngineGuest *);
+ void setGuestDevice(QIODevice *);
+
+ enum Function
+ {
+ SetupIPC = 1,
+ StateChanged = 2,
+ SetupEngine = 3,
+ SetupInferior = 4,
+ RunEngine = 5,
+ ShutdownInferior = 6,
+ ShutdownEngine = 7,
+ DetachDebugger = 8,
+ ExecuteStep = 9,
+ ExecuteStepOut = 10,
+ ExecuteNext = 11,
+ ExecuteStepI = 12,
+ ExecuteNextI = 13,
+ ContinueInferior = 14,
+ InterruptInferior = 15,
+ ExecuteRunToLine = 16,
+ ExecuteRunToFunction = 17,
+ ExecuteJumpToLine = 18,
+ ActivateFrame = 19,
+ SelectThread = 20,
+ Disassemble = 21,
+ AddBreakpoint = 22,
+ RemoveBreakpoint = 23,
+ ChangeBreakpoint = 24,
+ RequestUpdateWatchData = 25,
+ FetchFrameSource = 26
+ };
+ Q_ENUMS(Function)
+
+ void setupEngine();
+ void setupInferior();
+ void runEngine();
+ void shutdownInferior();
+ void shutdownEngine();
+ void detachDebugger();
+ void executeStep();
+ void executeStepOut() ;
+ void executeNext();
+ void executeStepI();
+ void executeNextI();
+ void continueInferior();
+ void interruptInferior();
+ void executeRunToLine(const QString &fileName, int lineNumber);
+ void executeRunToFunction(const QString &functionName);
+ void executeJumpToLine(const QString &fileName, int lineNumber);
+ void activateFrame(int index);
+ void selectThread(int index);
+ void fetchDisassembler(DisassemblerAgent *);
+ bool acceptsBreakpoint(BreakpointId) const { return true; } // FIXME
+ void insertBreakpoint(BreakpointId id);
+ void removeBreakpoint(BreakpointId id);
+ void changeBreakpoint(BreakpointId id);
+ void updateWatchData(const WatchData &data,
+ const WatchUpdateFlags &flags = WatchUpdateFlags());
+ void fetchFrameSource(qint64 id);
+
+ void rpcCall(Function f, QByteArray payload = QByteArray());
+protected:
+ virtual void nuke() = 0;
+public slots:
+ void rpcCallback(quint64 f, QByteArray payload = QByteArray());
+private slots:
+ void m_stateChanged(const DebuggerState &state);
+ void readyRead();
+private:
+ IPCEngineGuest *m_localGuest;
+ quint64 m_nextMessageCookie;
+ quint64 m_nextMessageFunction;
+ quint64 m_nextMessagePayloadSize;
+ quint64 m_cookie;
+ QIODevice *m_device;
+ QHash<quint64, DisassemblerAgent *> m_frameToDisassemblerAgent;
+ QHash<QString, SourceAgent *> m_sourceAgents;
+};
+
+} // namespace Internal
+} // namespace Debugger
+
+#endif // DEBUGGER_LLDBENGINE_H
diff --git a/src/plugins/debugger/lldb/lldbenginehost.cpp b/src/plugins/debugger/lldb/lldbenginehost.cpp
new file mode 100644
index 0000000000..be77862627
--- /dev/null
+++ b/src/plugins/debugger/lldb/lldbenginehost.cpp
@@ -0,0 +1,232 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#define QT_NO_CAST_FROM_ASCII
+
+#include "lldbenginehost.h"
+
+#include "debuggeractions.h"
+#include "debuggerconstants.h"
+#include "debuggerdialogs.h"
+#include "debuggerplugin.h"
+#include "debuggerstringutils.h"
+
+#include "breakhandler.h"
+#include "breakpoint.h"
+#include "moduleshandler.h"
+#include "registerhandler.h"
+#include "stackhandler.h"
+#include "watchhandler.h"
+#include "watchutils.h"
+#include "threadshandler.h"
+#include "disassembleragent.h"
+#include "memoryagent.h"
+
+#include <coreplugin/icore.h>
+#include <utils/qtcassert.h>
+
+#include <QtCore/QDebug>
+#include <QtCore/QProcess>
+#include <QtCore/QFileInfo>
+#include <QtCore/QThread>
+#include <QtCore/QCoreApplication>
+
+namespace Debugger {
+namespace Internal {
+
+SshIODevice::SshIODevice(Core::SshRemoteProcessRunner::Ptr r)
+ : runner(r)
+ , buckethead(0)
+{
+ setOpenMode(QIODevice::ReadWrite | QIODevice::Unbuffered);
+ connect (runner.data(), SIGNAL(processStarted()),
+ this, SLOT(processStarted()));
+ connect(runner.data(), SIGNAL(processOutputAvailable(const QByteArray &)),
+ this, SLOT(outputAvailable(const QByteArray &)));
+ connect(runner.data(), SIGNAL(processErrorOutputAvailable(const QByteArray &)),
+ this, SLOT(errorOutputAvailable(const QByteArray &)));
+}
+qint64 SshIODevice::bytesAvailable () const
+{
+ qint64 r = QIODevice::bytesAvailable();
+ foreach (const QByteArray &bucket, buckets)
+ r += bucket.size();
+ r-= buckethead;
+ return r;
+}
+qint64 SshIODevice::writeData (const char * data, qint64 maxSize)
+{
+ if (proc == 0) {
+ startupbuffer += QByteArray::fromRawData(data, maxSize);
+ return maxSize;
+ }
+ proc->sendInput(QByteArray::fromRawData(data, maxSize));
+ return maxSize;
+}
+qint64 SshIODevice::readData (char * data, qint64 maxSize)
+{
+ if (proc == 0)
+ return 0;
+ qint64 size = maxSize;
+ while (size > 0) {
+ if (!buckets.size()) {
+ return maxSize - size;
+ }
+ QByteArray &bucket = buckets.head();
+ if ((size + buckethead) >= bucket.size()) {
+ int d = bucket.size() - buckethead;
+ memcpy(data, bucket.data() + buckethead, d);
+ data += d;
+ size -= d;
+ buckets.dequeue();
+ buckethead = 0;
+ } else {
+ memcpy(data, bucket.data() + buckethead, size);
+ data += size;
+ buckethead += size;
+ size = 0;
+ }
+ }
+ return maxSize - size;
+}
+
+void SshIODevice::processStarted()
+{
+ proc = runner->process();
+ proc->sendInput(startupbuffer);
+}
+
+void SshIODevice::outputAvailable(const QByteArray &output)
+{
+ buckets.enqueue(output);
+ emit readyRead();
+}
+
+void SshIODevice::errorOutputAvailable(const QByteArray &output)
+{
+ fprintf(stderr, "%s", output.data());
+}
+
+
+LldbEngineHost::LldbEngineHost(const DebuggerStartParameters &startParameters)
+ :IPCEngineHost(startParameters)
+{
+ showMessage(QLatin1String("setting up coms"));
+
+ if (startParameters.startMode == StartRemoteEngine)
+ {
+ m_guestProcess = 0;
+ Core::SshRemoteProcessRunner::Ptr runner =
+ Core::SshRemoteProcessRunner::create(startParameters.connParams);
+ connect (runner.data(), SIGNAL(connectionError(Core::SshError)),
+ this, SLOT(sshConnectionError(Core::SshError)));
+ runner->run(startParameters.serverStartScript.toUtf8());
+ setGuestDevice(new SshIODevice(runner));
+ } else {
+ m_guestProcess = new QProcess(this);
+
+ connect(m_guestProcess, SIGNAL(finished(int, QProcess::ExitStatus)),
+ this, SLOT(finished(int, QProcess::ExitStatus)));
+
+ connect(m_guestProcess, SIGNAL(readyReadStandardError()), this,
+ SLOT(stderrReady()));
+
+
+ QString a = Core::ICore::instance()->resourcePath() + QLatin1String("/qtcreator-lldb");
+ if(getenv("QTC_LLDB_GUEST") != 0)
+ a = QString::fromLocal8Bit(getenv("QTC_LLDB_GUEST"));
+
+ showStatusMessage(QString(QLatin1String("starting %1")).arg(a));
+
+ m_guestProcess->start(a, QStringList(), QIODevice::ReadWrite | QIODevice::Unbuffered);
+ m_guestProcess->setReadChannel(QProcess::StandardOutput);
+
+ if (!m_guestProcess->waitForStarted()) {
+ showStatusMessage(tr("qtcreator-lldb failed to start %1").arg(m_guestProcess->error()));
+ notifyEngineSpontaneousShutdown();
+ return;
+ }
+
+ setGuestDevice(m_guestProcess);
+ }
+}
+
+LldbEngineHost::~LldbEngineHost()
+{
+ showMessage(QLatin1String("tear down qtcreator-lldb"));
+
+ if (m_guestProcess) {
+ disconnect(m_guestProcess, SIGNAL(finished(int, QProcess::ExitStatus)),
+ this, SLOT(finished (int, QProcess::ExitStatus)));
+
+
+ m_guestProcess->terminate();
+ m_guestProcess->kill();
+ }
+ if (m_ssh.data() && m_ssh->process().data()) {
+ // TODO: openssh doesn't do that
+
+ m_ssh->process()->kill();
+ }
+}
+
+void LldbEngineHost::nuke()
+{
+ stderrReady();
+ showMessage(QLatin1String("Nuke engaged. Bug in Engine/IPC or incompatible IPC versions. "), LogError);
+ showStatusMessage(tr("Fatal engine shutdown. Consult debugger log for details."));
+ m_guestProcess->terminate();
+ m_guestProcess->kill();
+ notifyEngineSpontaneousShutdown();
+}
+void LldbEngineHost::sshConnectionError(Core::SshError e)
+{
+ showStatusMessage(tr("ssh connection error: %1").arg(e));
+}
+
+void LldbEngineHost::finished(int, QProcess::ExitStatus status)
+{
+ showMessage(QString(QLatin1String("guest went bye bye. exit status: %1 and code: %2"))
+ .arg(status).arg(m_guestProcess->exitCode()), LogError);
+ nuke();
+}
+
+void LldbEngineHost::stderrReady()
+{
+ fprintf(stderr,"%s", m_guestProcess->readAllStandardError().data());
+}
+
+DebuggerEngine *createLldbEngine(const DebuggerStartParameters &startParameters)
+{
+ return new LldbEngineHost(startParameters);
+}
+
+} // namespace Internal
+} // namespace Debugger
+
diff --git a/src/plugins/debugger/lldb/lldbenginehost.h b/src/plugins/debugger/lldb/lldbenginehost.h
new file mode 100644
index 0000000000..2e17370d29
--- /dev/null
+++ b/src/plugins/debugger/lldb/lldbenginehost.h
@@ -0,0 +1,87 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 DEBUGGER_LLDBENGINE_HOST_H
+#define DEBUGGER_LLDBENGINE_HOST_H
+
+#include "ipcenginehost.h"
+#include <coreplugin/ssh/ssherrors.h>
+#include <coreplugin/ssh/sshconnection.h>
+#include <coreplugin/ssh/sshremoteprocess.h>
+#include <coreplugin/ssh/sshremoteprocessrunner.h>
+
+#include <QtCore/QProcess>
+#include <QtCore/QQueue>
+
+namespace Debugger {
+namespace Internal {
+
+class SshIODevice : public QIODevice
+{
+Q_OBJECT
+public:
+ SshIODevice(Core::SshRemoteProcessRunner::Ptr r);
+ virtual qint64 bytesAvailable () const;
+ virtual qint64 writeData (const char * data, qint64 maxSize);
+ virtual qint64 readData (char * data, qint64 maxSize);
+private slots:
+ void processStarted();
+ void outputAvailable(const QByteArray &output);
+ void errorOutputAvailable(const QByteArray &output);
+private:
+ Core::SshRemoteProcessRunner::Ptr runner;
+ Core::SshRemoteProcess::Ptr proc;
+ int buckethead;
+ QQueue<QByteArray> buckets;
+ QByteArray startupbuffer;
+};
+
+class LldbEngineHost : public IPCEngineHost
+{
+ Q_OBJECT
+
+public:
+ explicit LldbEngineHost(const DebuggerStartParameters &startParameters);
+ ~LldbEngineHost();
+
+private:
+ QProcess *m_guestProcess;
+ Core::SshRemoteProcessRunner::Ptr m_ssh;
+protected:
+ void nuke();
+private slots:
+ void sshConnectionError(Core::SshError);
+ void finished(int, QProcess::ExitStatus);
+ void stderrReady();
+};
+
+} // namespace Internal
+} // namespace Debugger
+
+#endif // DEBUGGER_LLDBENGINE_HOST_H
diff --git a/src/plugins/debugger/lldb/lldbhost.pri b/src/plugins/debugger/lldb/lldbhost.pri
new file mode 100644
index 0000000000..0e9297d7e3
--- /dev/null
+++ b/src/plugins/debugger/lldb/lldbhost.pri
@@ -0,0 +1,20 @@
+WITH_LLDB = $$(WITH_LLDB)
+
+HEADERS += $$PWD/ipcenginehost.h \
+ $$PWD/lldbenginehost.h
+
+SOURCES += $$PWD/ipcenginehost.cpp \
+ $$PWD/lldbenginehost.cpp
+
+INCLUDEPATH+=
+
+FORMS +=
+
+RESOURCES +=
+
+!isEmpty(WITH_LLDB) {
+ DEFINES += WITH_LLDB
+ HEADERS += $$PWD/lldboptionspage.h
+ SOURCES += $$PWD/lldboptionspage.cpp
+ FORMS += $$PWD/lldboptionspagewidget.ui
+}
diff --git a/src/plugins/debugger/lldb/lldboptionspage.cpp b/src/plugins/debugger/lldb/lldboptionspage.cpp
new file mode 100644
index 0000000000..7e62a64a66
--- /dev/null
+++ b/src/plugins/debugger/lldb/lldboptionspage.cpp
@@ -0,0 +1,132 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "lldboptionspage.h"
+#include "debuggerconstants.h"
+
+#include <coreplugin/icore.h>
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QUrl>
+#include <QtCore/QTextStream>
+#include <QtGui/QMessageBox>
+#include <QtGui/QDesktopServices>
+
+namespace Debugger {
+namespace Internal {
+
+LldbOptionsPageWidget::LldbOptionsPageWidget(QWidget *parent, QSettings *s_)
+ : QWidget(parent)
+ , s(s_)
+{
+ m_ui.setupUi(this);
+ load();
+}
+
+void LldbOptionsPageWidget::save()
+{
+ s->beginGroup(QLatin1String("LLDB"));
+ s->setValue(QLatin1String("enabled"), m_ui.enableLldb->isChecked ());
+ s->setValue(QLatin1String("gdbEmu"), m_ui.gdbEmu->isChecked ());
+ s->endGroup();
+}
+
+void LldbOptionsPageWidget::load()
+{
+ s->beginGroup(QLatin1String("LLDB"));
+ m_ui.enableLldb->setChecked(s->value(QLatin1String("enabled"), false).toBool());
+ m_ui.gdbEmu->setChecked(s->value(QLatin1String("gdbEmu"), true).toBool());
+ s->endGroup();
+}
+
+// ---------- LldbOptionsPage
+LldbOptionsPage::LldbOptionsPage()
+{
+// m_options->fromSettings(Core::ICore::instance()->settings());
+}
+
+LldbOptionsPage::~LldbOptionsPage()
+{
+}
+
+QString LldbOptionsPage::settingsId()
+{
+ return QLatin1String("F.Lldb");
+}
+
+QString LldbOptionsPage::displayName() const
+{
+ return tr("LLDB");
+}
+
+QString LldbOptionsPage::category() const
+{
+ return QLatin1String(Debugger::Constants::DEBUGGER_SETTINGS_CATEGORY);
+}
+
+QString LldbOptionsPage::displayCategory() const
+{
+ return QCoreApplication::translate("Debugger", Debugger::Constants::DEBUGGER_SETTINGS_TR_CATEGORY);
+}
+
+QIcon LldbOptionsPage::categoryIcon() const
+{
+ return QIcon(QLatin1String(Debugger::Constants::DEBUGGER_COMMON_SETTINGS_CATEGORY_ICON));
+}
+
+QWidget *LldbOptionsPage::createPage(QWidget *parent)
+{
+ m_widget = new LldbOptionsPageWidget(parent, Core::ICore::instance()->settings());
+ return m_widget;
+}
+
+void LldbOptionsPage::apply()
+{
+ if (!m_widget)
+ return;
+ m_widget->save();
+}
+
+void LldbOptionsPage::finish()
+{
+}
+
+bool LldbOptionsPage::matches(const QString &s) const
+{
+ return QString(s.toLower()).contains("lldb");
+}
+
+void addLldbOptionPages(QList<Core::IOptionsPage *> *opts)
+{
+ opts->push_back(new LldbOptionsPage);
+}
+
+
+} // namespace Internal
+} // namespace Debugger
diff --git a/src/plugins/debugger/lldb/lldboptionspage.h b/src/plugins/debugger/lldb/lldboptionspage.h
new file mode 100644
index 0000000000..3482a3a4e0
--- /dev/null
+++ b/src/plugins/debugger/lldb/lldboptionspage.h
@@ -0,0 +1,88 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 LLDBSETTINGSPAGE_H
+#define LLDBSETTINGSPAGE_H
+
+#include <coreplugin/dialogs/ioptionspage.h>
+#include "ui_lldboptionspagewidget.h"
+
+#include <QtGui/QWidget>
+#include <QtCore/QPointer>
+#include <QtCore/QSharedPointer>
+#include <QtCore/QSettings>
+
+namespace Debugger {
+namespace Internal {
+
+class LldbOptionsPageWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ explicit LldbOptionsPageWidget(QWidget *parent, QSettings *s);
+
+public slots:
+ void save();
+ void load();
+
+private:
+ Ui::LldbOptionsPageWidget m_ui;
+ QSettings *s;
+};
+
+class LldbOptionsPage : public Core::IOptionsPage
+{
+ Q_DISABLE_COPY(LldbOptionsPage)
+ Q_OBJECT
+public:
+ explicit LldbOptionsPage();
+ virtual ~LldbOptionsPage();
+
+ // IOptionsPage
+ virtual QString id() const { return settingsId(); }
+ virtual QString displayName() const;
+ virtual QString category() const;
+ virtual QString displayCategory() const;
+ QIcon categoryIcon() const;
+
+ virtual QWidget *createPage(QWidget *parent);
+ virtual void apply();
+ virtual void finish();
+ virtual bool matches(const QString &) const;
+
+ static QString settingsId();
+
+private:
+ QPointer<LldbOptionsPageWidget> m_widget;
+};
+
+} // namespace Internal
+} // namespace Debugger
+
+#endif // LLDBSETTINGSPAGE_H
diff --git a/src/plugins/debugger/lldb/lldboptionspagewidget.ui b/src/plugins/debugger/lldb/lldboptionspagewidget.ui
new file mode 100644
index 0000000000..0661cfa540
--- /dev/null
+++ b/src/plugins/debugger/lldb/lldboptionspagewidget.ui
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>LldbOptionsPageWidget</class>
+ <widget class="QWidget" name="LldbOptionsPageWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>522</width>
+ <height>512</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout"/>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="enableLldb">
+ <property name="title">
+ <string>Enable LLDB</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QCheckBox" name="gdbEmu">
+ <property name="text">
+ <string>Use Gdb python dumpers</string>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>203</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/plugins/debugger/logwindow.cpp b/src/plugins/debugger/logwindow.cpp
index b709b3d91a..4ab95e945d 100644
--- a/src/plugins/debugger/logwindow.cpp
+++ b/src/plugins/debugger/logwindow.cpp
@@ -34,23 +34,18 @@
#include "logwindow.h"
#include "debuggeractions.h"
-#include "debuggerconstants.h"
+#include "debuggercore.h"
#include <QtCore/QDebug>
#include <QtCore/QFile>
#include <QtCore/QTime>
-#include <QtGui/QAction>
#include <QtGui/QHBoxLayout>
#include <QtGui/QVBoxLayout>
#include <QtGui/QKeyEvent>
-#include <QtGui/QLabel>
-#include <QtGui/QLineEdit>
#include <QtGui/QMenu>
#include <QtGui/QSpacerItem>
-#include <QtGui/QSplitter>
#include <QtGui/QSyntaxHighlighter>
-#include <QtGui/QTextBlock>
#include <QtGui/QPlainTextEdit>
#include <QtGui/QFileDialog>
#include <QtGui/QMessageBox>
@@ -207,12 +202,12 @@ public:
menu->addAction(m_clearContentsAction);
menu->addAction(m_saveContentsAction); // X11 clipboard is unreliable for long texts
addContextActions(menu);
- theDebuggerAction(ExecuteCommand)->setData(textCursor().block().text());
- menu->addAction(theDebuggerAction(ExecuteCommand));
- menu->addAction(theDebuggerAction(LogTimeStamps));
- menu->addAction(theDebuggerAction(VerboseLog));
+ debuggerCore()->action(ExecuteCommand)->setData(textCursor().block().text());
+ menu->addAction(debuggerCore()->action(ExecuteCommand));
+ menu->addAction(debuggerCore()->action(LogTimeStamps));
+ menu->addAction(debuggerCore()->action(VerboseLog));
menu->addSeparator();
- menu->addAction(theDebuggerAction(SettingsDialog));
+ menu->addAction(debuggerCore()->action(SettingsDialog));
menu->exec(ev->globalPos());
delete menu;
}
@@ -229,24 +224,9 @@ private:
void DebuggerPane::saveContents()
{
- while (true) {
- const QString fileName = QFileDialog::getSaveFileName(this, tr("Log File"));
- if (fileName.isEmpty())
- break;
- QFile file(fileName);
- if (file.open(QIODevice::WriteOnly|QIODevice::Text|QIODevice::Truncate)) {
- file.write(toPlainText().toUtf8());
- file.close();
- break;
- } else {
- QMessageBox::warning(this, tr("Write Failure"),
- tr("Unable to write log contents to '%1': %2").
- arg(fileName, file.errorString()));
- }
- }
+ LogWindow::writeLogContents(this, this);
}
-
/////////////////////////////////////////////////////////////////////
//
// InputPane
@@ -272,7 +252,7 @@ private:
void keyPressEvent(QKeyEvent *ev)
{
if (ev->modifiers() == Qt::ControlModifier && ev->key() == Qt::Key_Return)
- theDebuggerAction(ExecuteCommand)->trigger(textCursor().block().text());
+ debuggerCore()->action(ExecuteCommand)->trigger(textCursor().block().text());
else if (ev->modifiers() == Qt::ControlModifier && ev->key() == Qt::Key_R)
emit clearContentsRequested();
else
@@ -300,7 +280,7 @@ private:
void addContextActions(QMenu *menu)
{
- menu->addAction(theDebuggerAction(ExecuteCommand));
+ menu->addAction(debuggerCore()->action(ExecuteCommand));
}
void focusInEvent(QFocusEvent *ev)
@@ -406,7 +386,7 @@ LogWindow::LogWindow(QWidget *parent)
this, SIGNAL(statusMessageRequested(QString,int)));
connect(m_inputText, SIGNAL(commandSelected(int)),
m_combinedText, SLOT(gotoResult(int)));
-};
+}
void LogWindow::showOutput(int channel, const QString &output)
{
@@ -417,7 +397,7 @@ void LogWindow::showOutput(int channel, const QString &output)
cursor.movePosition(QTextCursor::End);
bool atEnd = oldCursor.position() == cursor.position();
- if (theDebuggerBoolSetting(LogTimeStamps))
+ if (debuggerCore()->boolSetting(LogTimeStamps))
m_combinedText->appendPlainText(charForChannel(LogTime) + logTimeStamp());
foreach (QString line, output.split('\n')) {
// FIXME: QTextEdit asserts on really long lines...
@@ -439,7 +419,7 @@ void LogWindow::showOutput(int channel, const QString &output)
void LogWindow::showInput(int channel, const QString &input)
{
Q_UNUSED(channel)
- if (theDebuggerBoolSetting(LogTimeStamps))
+ if (debuggerCore()->boolSetting(LogTimeStamps))
m_inputText->appendPlainText(logTimeStamp());
m_inputText->appendPlainText(input);
QTextCursor cursor = m_inputText->textCursor();
@@ -494,6 +474,27 @@ QString LogWindow::logTimeStamp()
return lastTimeStamp;
}
+bool LogWindow::writeLogContents(const QPlainTextEdit *editor, QWidget *parent)
+{
+ bool success = false;
+ while (!success) {
+ const QString fileName = QFileDialog::getSaveFileName(parent, tr("Log File"));
+ if (fileName.isEmpty())
+ break;
+ QFile file(fileName);
+ if (file.open(QIODevice::WriteOnly|QIODevice::Text|QIODevice::Truncate)) {
+ file.write(editor->toPlainText().toUtf8());
+ file.close();
+ success = true;
+ } else {
+ QMessageBox::warning(parent, tr("Write Failure"),
+ tr("Unable to write log contents to '%1': %2").
+ arg(fileName, file.errorString()));
+ }
+ }
+ return success;
+}
+
} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/logwindow.h b/src/plugins/debugger/logwindow.h
index 496c860d8d..c11380e0f9 100644
--- a/src/plugins/debugger/logwindow.h
+++ b/src/plugins/debugger/logwindow.h
@@ -59,6 +59,8 @@ public:
static QString logTimeStamp();
+ static bool writeLogContents(const QPlainTextEdit *editor, QWidget *parent = 0);
+
public slots:
void clearContents();
void showOutput(int channel, const QString &output);
diff --git a/src/plugins/debugger/memoryagent.cpp b/src/plugins/debugger/memoryagent.cpp
new file mode 100644
index 0000000000..2b11f5615a
--- /dev/null
+++ b/src/plugins/debugger/memoryagent.cpp
@@ -0,0 +1,174 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "memoryagent.h"
+
+#include "debuggerengine.h"
+#include "debuggercore.h"
+
+#include <coreplugin/coreconstants.h>
+#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/editormanager/ieditor.h>
+#include <coreplugin/icore.h>
+
+#include <utils/qtcassert.h>
+
+#include <QtGui/QMessageBox>
+
+using namespace Core;
+
+namespace Debugger {
+namespace Internal {
+
+///////////////////////////////////////////////////////////////////////
+//
+// MemoryAgent
+//
+///////////////////////////////////////////////////////////////////////
+
+/*!
+ \class MemoryAgent
+
+ Objects form this class are created in response to user actions in
+ the Gui for showing raw memory from the inferior. After creation
+ it handles communication between the engine and the bineditor.
+*/
+
+namespace { const int DataRange = 1024 * 1024; }
+
+MemoryAgent::MemoryAgent(Debugger::DebuggerEngine *engine)
+ : QObject(engine), m_engine(engine)
+{
+ QTC_ASSERT(engine, /**/);
+}
+
+MemoryAgent::~MemoryAgent()
+{
+ QList<IEditor *> editors;
+ foreach (QPointer<IEditor> editor, m_editors)
+ if (editor)
+ editors.append(editor.data());
+ EditorManager::instance()->closeEditors(editors);
+}
+
+void MemoryAgent::createBinEditor(quint64 addr)
+{
+ EditorManager *editorManager = EditorManager::instance();
+ QString titlePattern = tr("Memory $");
+ IEditor *editor = editorManager->openEditorWithContents(
+ Core::Constants::K_DEFAULT_BINARY_EDITOR_ID,
+ &titlePattern);
+ editorManager->activateEditor(editor);
+ if (editor) {
+ editor->setProperty(Debugger::Constants::OPENED_BY_DEBUGGER, true);
+ editor->setProperty(Debugger::Constants::OPENED_WITH_MEMORY, true);
+ connect(editor->widget(),
+ SIGNAL(lazyDataRequested(Core::IEditor *, quint64,bool)),
+ SLOT(fetchLazyData(Core::IEditor *, quint64,bool)));
+ connect(editor->widget(),
+ SIGNAL(newWindowRequested(quint64)),
+ SLOT(createBinEditor(quint64)));
+ connect(editor->widget(),
+ SIGNAL(newRangeRequested(Core::IEditor *, quint64)),
+ SLOT(provideNewRange(Core::IEditor*,quint64)));
+ connect(editor->widget(),
+ SIGNAL(startOfFileRequested(Core::IEditor *)),
+ SLOT(handleStartOfFileRequested(Core::IEditor*)));
+ connect(editor->widget(),
+ SIGNAL(endOfFileRequested(Core::IEditor *)),
+ SLOT(handleEndOfFileRequested(Core::IEditor*)));
+ m_editors << editor;
+ QMetaObject::invokeMethod(editor->widget(), "setNewWindowRequestAllowed");
+ QMetaObject::invokeMethod(editor->widget(), "setLazyData",
+ Q_ARG(quint64, addr), Q_ARG(int, DataRange), Q_ARG(int, BinBlockSize));
+ } else {
+ showMessageBox(QMessageBox::Warning,
+ tr("No memory viewer available"),
+ tr("The memory contents cannot be shown as no viewer plugin "
+ "for binary data has been loaded."));
+ deleteLater();
+ }
+}
+
+void MemoryAgent::fetchLazyData(IEditor *editor, quint64 block, bool sync)
+{
+ Q_UNUSED(sync); // FIXME: needed support for incremental searching
+ m_engine->fetchMemory(this, editor, BinBlockSize * block, BinBlockSize);
+}
+
+void MemoryAgent::addLazyData(QObject *editorToken, quint64 addr,
+ const QByteArray &ba)
+{
+ IEditor *editor = qobject_cast<IEditor *>(editorToken);
+ if (editor && editor->widget()) {
+ QMetaObject::invokeMethod(editor->widget(), "addLazyData",
+ Q_ARG(quint64, addr / BinBlockSize), Q_ARG(QByteArray, ba));
+ }
+}
+
+void MemoryAgent::provideNewRange(IEditor *editor, quint64 address)
+{
+ QMetaObject::invokeMethod(editor->widget(), "setLazyData",
+ Q_ARG(quint64, address), Q_ARG(int, DataRange),
+ Q_ARG(int, BinBlockSize));
+}
+
+// Since we are not dealing with files, we take these signals to mean
+// "move to start/end of range". This seems to make more sense than
+// jumping to the start or end of the address space, respectively.
+void MemoryAgent::handleStartOfFileRequested(IEditor *editor)
+{
+ QMetaObject::invokeMethod(editor->widget(),
+ "setCursorPosition", Q_ARG(int, 0));
+}
+
+void MemoryAgent::handleEndOfFileRequested(IEditor *editor)
+{
+ QMetaObject::invokeMethod(editor->widget(),
+ "setCursorPosition", Q_ARG(int, DataRange - 1));
+}
+
+void MemoryAgent::updateContents()
+{
+ foreach (QPointer<IEditor> editor, m_editors)
+ if (editor)
+ QMetaObject::invokeMethod(editor->widget(), "updateContents");
+}
+
+bool MemoryAgent::hasVisibleEditor() const
+{
+ QList<IEditor *> visible = EditorManager::instance()->visibleEditors();
+ foreach (QPointer<IEditor> editor, m_editors)
+ if (visible.contains(editor.data()))
+ return true;
+ return false;
+}
+
+} // namespace Internal
+} // namespace Debugger
diff --git a/src/plugins/debugger/memoryagent.h b/src/plugins/debugger/memoryagent.h
new file mode 100644
index 0000000000..050f9916e9
--- /dev/null
+++ b/src/plugins/debugger/memoryagent.h
@@ -0,0 +1,82 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** No Commercial Usage
+**
+** This file 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.
+**
+**************************************************************************/
+
+#ifndef DEBUGGER_MEMORYAGENT_H
+#define DEBUGGER_MEMORYAGENT_H
+
+#include <QtCore/QObject>
+#include <QtCore/QPointer>
+
+namespace Core {
+class IEditor;
+}
+
+namespace Debugger {
+
+class DebuggerEngine;
+
+namespace Internal {
+
+class MemoryAgent : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit MemoryAgent(DebuggerEngine *engine);
+ ~MemoryAgent();
+
+ enum { BinBlockSize = 1024 };
+ bool hasVisibleEditor() const;
+
+public slots:
+ // Called by engine to create a new view.
+ void createBinEditor(quint64 startAddr);
+ // Called by engine to trigger update of contents.
+ void updateContents();
+ // Called by enine to pass updated contents.
+ void addLazyData(QObject *editorToken, quint64 addr, const QByteArray &data);
+
+private:
+ Q_SLOT void fetchLazyData(Core::IEditor *, quint64 block, bool sync);
+ Q_SLOT void provideNewRange(Core::IEditor *editor, quint64 address);
+ Q_SLOT void handleStartOfFileRequested(Core::IEditor *editor);
+ Q_SLOT void handleEndOfFileRequested(Core::IEditor *editor);
+
+ QList<QPointer<Core::IEditor> > m_editors;
+ QPointer<DebuggerEngine> m_engine;
+};
+
+} // namespace Internal
+} // namespace Debugger
+
+#endif // DEBUGGER_MEMORYAGENT_H
diff --git a/src/plugins/debugger/moduleshandler.cpp b/src/plugins/debugger/moduleshandler.cpp
index e4a7c654aa..bb56cef23b 100644
--- a/src/plugins/debugger/moduleshandler.cpp
+++ b/src/plugins/debugger/moduleshandler.cpp
@@ -32,17 +32,10 @@
**************************************************************************/
#include "moduleshandler.h"
-#include "debuggerengine.h"
#include <utils/qtcassert.h>
#include <QtCore/QDebug>
-#include <QtCore/QDir>
-#include <QtCore/QTextStream>
-
-#include <QtGui/QAction>
-#include <QtGui/QMainWindow>
-#include <QtGui/QStandardItemModel>
#include <QtGui/QSortFilterProxyModel>
@@ -55,41 +48,8 @@
namespace Debugger {
namespace Internal {
-class ModulesModel : public QAbstractItemModel
-{ // Needs tr - context.
- Q_OBJECT
-public:
- explicit ModulesModel(ModulesHandler *parent, DebuggerEngine *engine);
-
- // QAbstractItemModel
- int columnCount(const QModelIndex &parent) const
- { return parent.isValid() ? 0 : 5; }
- int rowCount(const QModelIndex &parent) const
- { return parent.isValid() ? 0 : m_modules.size(); }
- QModelIndex parent(const QModelIndex &) const { return QModelIndex(); }
- QModelIndex index(int row, int column, const QModelIndex &) const
- { return createIndex(row, column); }
- QVariant headerData(int section, Qt::Orientation orientation, int role) const;
- QVariant data(const QModelIndex &index, int role) const;
- bool setData(const QModelIndex &index, const QVariant &value, int role);
-
- void clearModel();
- void addModule(const Module &module);
- void removeModule(const QString &moduleName);
- void setModules(const Modules &modules);
- void updateModule(const QString &moduleName, const Module &module);
-
- const Modules &modules() const { return m_modules; }
-
-private:
- int indexOfModule(const QString &name) const;
-
- DebuggerEngine *m_engine;
- Modules m_modules;
-};
-
-ModulesModel::ModulesModel(ModulesHandler *parent, DebuggerEngine *engine)
- : QAbstractItemModel(parent), m_engine(engine)
+ModulesModel::ModulesModel(ModulesHandler *parent)
+ : QAbstractItemModel(parent)
{}
QVariant ModulesModel::headerData(int section,
@@ -111,12 +71,6 @@ QVariant ModulesModel::headerData(int section,
QVariant ModulesModel::data(const QModelIndex &index, int role) const
{
- if (role == EngineCapabilitiesRole)
- return m_engine->debuggerCapabilities();
-
- if (role == EngineActionsEnabledRole)
- return m_engine->debuggerActionsEnabled();
-
int row = index.row();
if (row < 0 || row >= m_modules.size())
return QVariant();
@@ -163,34 +117,6 @@ QVariant ModulesModel::data(const QModelIndex &index, int role) const
return QVariant();
}
-bool ModulesModel::setData(const QModelIndex &index, const QVariant &value, int role)
-{
- Q_UNUSED(index);
-
- switch (role) {
- case RequestReloadModulesRole:
- m_engine->reloadModules();
- return true;
-
- case RequestExamineModulesRole:
- m_engine->examineModules();
- return true;
-
- case RequestModuleSymbolsRole:
- m_engine->loadSymbols(value.toString());
- return true;
-
- case RequestAllSymbolsRole:
- m_engine->loadAllSymbols();
- return true;
-
- case RequestOpenFileRole:
- m_engine->openFile(value.toString());
- return true;
- }
- return false;
-}
-
void ModulesModel::addModule(const Module &m)
{
beginInsertRows(QModelIndex(), m_modules.size(), m_modules.size());
@@ -226,7 +152,7 @@ void ModulesModel::removeModule(const QString &moduleName)
const int index = indexOfModule(moduleName);
QTC_ASSERT(index != -1, return);
beginRemoveRows(QModelIndex(), index, index);
- m_modules.removeAt(index);
+ m_modules.remove(index);
endRemoveRows();
}
@@ -244,9 +170,9 @@ void ModulesModel::updateModule(const QString &moduleName, const Module &module)
//
//////////////////////////////////////////////////////////////////
-ModulesHandler::ModulesHandler(DebuggerEngine *engine)
+ModulesHandler::ModulesHandler()
{
- m_model = new ModulesModel(this, engine);
+ m_model = new ModulesModel(this);
m_proxyModel = new QSortFilterProxyModel(this);
m_proxyModel->setSourceModel(m_model);
}
@@ -289,4 +215,3 @@ Modules ModulesHandler::modules() const
} // namespace Internal
} // namespace Debugger
-#include "moduleshandler.moc"
diff --git a/src/plugins/debugger/moduleshandler.h b/src/plugins/debugger/moduleshandler.h
index 909877e511..3a9ee655ba 100644
--- a/src/plugins/debugger/moduleshandler.h
+++ b/src/plugins/debugger/moduleshandler.h
@@ -34,22 +34,17 @@
#ifndef DEBUGGER_MODULESHANDLER_H
#define DEBUGGER_MODULESHANDLER_H
-#include <QtCore/QList>
+#include <QtCore/QVector>
#include <QtCore/QObject>
-
-QT_BEGIN_NAMESPACE
-class QAbstractItemModel;
-class QSortFilterProxyModel;
-QT_END_NAMESPACE
+#include <QtGui/QSortFilterProxyModel>
namespace Debugger {
-
-class DebuggerEngine;
-
namespace Internal {
class ModulesModel;
+class ModulesHandler;
+
//////////////////////////////////////////////////////////////////
//
@@ -63,9 +58,11 @@ public:
QString address;
QString state;
QString name;
+ QString section;
+ QString demangled;
};
-typedef QList<Symbol> Symbols;
+typedef QVector<Symbol> Symbols;
//////////////////////////////////////////////////////////////////
//
@@ -82,12 +79,12 @@ public:
enum SymbolReadState {
UnknownReadState, // Not tried.
ReadFailed, // Tried to read, but failed.
- ReadOk, // Dwarf index available.
+ ReadOk // Dwarf index available.
};
enum SymbolType {
UnknownType, // Unknown.
PlainSymbols, // Ordinary symbols available.
- FastSymbols, // Dwarf index available.
+ FastSymbols // Dwarf index available.
};
QString moduleName;
QString modulePath;
@@ -97,7 +94,46 @@ public:
QString endAddress;
};
-typedef QList<Module> Modules;
+typedef QVector<Module> Modules;
+
+
+//////////////////////////////////////////////////////////////////
+//
+// ModulesModel
+//
+//////////////////////////////////////////////////////////////////
+
+class ModulesModel : public QAbstractItemModel
+{
+ // Needs tr - context.
+ Q_OBJECT
+public:
+ ModulesModel(ModulesHandler *parent);
+
+ // QAbstractItemModel
+ int columnCount(const QModelIndex &parent) const
+ { return parent.isValid() ? 0 : 5; }
+ int rowCount(const QModelIndex &parent) const
+ { return parent.isValid() ? 0 : m_modules.size(); }
+ QModelIndex parent(const QModelIndex &) const { return QModelIndex(); }
+ QModelIndex index(int row, int column, const QModelIndex &) const
+ { return createIndex(row, column); }
+ QVariant headerData(int section, Qt::Orientation orientation, int role) const;
+ QVariant data(const QModelIndex &index, int role) const;
+
+ void clearModel();
+ void addModule(const Module &module);
+ void removeModule(const QString &moduleName);
+ void setModules(const Modules &modules);
+ void updateModule(const QString &moduleName, const Module &module);
+
+ const Modules &modules() const { return m_modules; }
+
+private:
+ int indexOfModule(const QString &name) const;
+
+ Modules m_modules;
+};
//////////////////////////////////////////////////////////////////
@@ -108,8 +144,10 @@ typedef QList<Module> Modules;
class ModulesHandler : public QObject
{
+ Q_OBJECT
+
public:
- explicit ModulesHandler(DebuggerEngine *engine);
+ ModulesHandler();
QAbstractItemModel *model() const;
diff --git a/src/plugins/debugger/moduleswindow.cpp b/src/plugins/debugger/moduleswindow.cpp
index 1d4e14f346..77796db0d7 100644
--- a/src/plugins/debugger/moduleswindow.cpp
+++ b/src/plugins/debugger/moduleswindow.cpp
@@ -33,15 +33,16 @@
#include "moduleswindow.h"
-#include "debuggerconstants.h"
#include "debuggeractions.h"
+#include "debuggerconstants.h"
+#include "debuggercore.h"
+#include "debuggerengine.h"
#include <utils/qtcassert.h>
#include <utils/savedaction.h>
#include <QtCore/QDebug>
-#include <QtGui/QAction>
#include <QtGui/QHeaderView>
#include <QtGui/QMenu>
#include <QtGui/QResizeEvent>
@@ -59,7 +60,7 @@ namespace Internal {
ModulesWindow::ModulesWindow(QWidget *parent)
: QTreeView(parent), m_alwaysResizeColumnsToContents(false)
{
- QAction *act = theDebuggerAction(UseAlternatingRowColors);
+ QAction *act = debuggerCore()->action(UseAlternatingRowColors);
setWindowTitle(tr("Modules"));
setAttribute(Qt::WA_MacShowFocusRect, false);
setSortingEnabled(true);
@@ -68,32 +69,16 @@ ModulesWindow::ModulesWindow(QWidget *parent)
setIconSize(QSize(10, 10));
connect(this, SIGNAL(activated(QModelIndex)),
- this, SLOT(moduleActivated(QModelIndex)));
+ SLOT(moduleActivated(QModelIndex)));
connect(act, SIGNAL(toggled(bool)),
- this, SLOT(setAlternatingRowColorsHelper(bool)));
+ SLOT(setAlternatingRowColorsHelper(bool)));
}
void ModulesWindow::moduleActivated(const QModelIndex &index)
{
- qDebug() << "ACTIVATED: " << index.row() << index.column()
- << index.data().toString();
- setModelData(RequestOpenFileRole, index.data().toString());
-}
-
-void ModulesWindow::resizeEvent(QResizeEvent *event)
-{
- //QHeaderView *hv = header();
- //int totalSize = event->size().width() - 110;
- //hv->resizeSection(0, totalSize / 4);
- //hv->resizeSection(1, totalSize / 4);
- //hv->resizeSection(2, totalSize / 4);
- //hv->resizeSection(3, totalSize / 4);
- //hv->resizeSection(0, 60);
- //hv->resizeSection(1, (totalSize * 50) / 100);
- //hv->resizeSection(2, (totalSize * 50) / 100);
- //hv->resizeSection(3, 50);
- //setColumnHidden(3, true);
- QTreeView::resizeEvent(event);
+ DebuggerEngine *engine = debuggerCore()->currentEngine();
+ QTC_ASSERT(engine, return);
+ engine->gotoLocation(index.data().toString());
}
void ModulesWindow::contextMenuEvent(QContextMenuEvent *ev)
@@ -105,10 +90,10 @@ void ModulesWindow::contextMenuEvent(QContextMenuEvent *ev)
if (index.isValid())
name = index.data().toString();
- const bool enabled =
- model() && model()->data(index, EngineActionsEnabledRole).toBool();
- const unsigned capabilities =
- model()->data(index, EngineCapabilitiesRole).toInt();
+ DebuggerEngine *engine = debuggerCore()->currentEngine();
+ QTC_ASSERT(engine, return);
+ const bool enabled = engine->debuggerActionsEnabled();
+ const unsigned capabilities = engine->debuggerCapabilities();
QMenu menu;
@@ -117,9 +102,9 @@ void ModulesWindow::contextMenuEvent(QContextMenuEvent *ev)
actUpdateModuleList
->setEnabled(enabled && (capabilities & ReloadModuleCapability));
- QAction *actShowSourceFiles
+ QAction *actShowModuleSources
= new QAction(tr("Show Source Files for Module \"%1\"").arg(name), &menu);
- actShowSourceFiles
+ actShowModuleSources
->setEnabled(enabled && (capabilities & ReloadModuleCapability));
QAction *actLoadSymbolsForAllModules
@@ -134,14 +119,14 @@ void ModulesWindow::contextMenuEvent(QContextMenuEvent *ev)
QAction *actLoadSymbolsForModule = 0;
QAction *actEditFile = 0;
- QAction *actShowSymbols = 0;
+ QAction *actShowModuleSymbols = 0;
if (name.isEmpty()) {
actLoadSymbolsForModule = new QAction(tr("Load Symbols for Module"), &menu);
actLoadSymbolsForModule->setEnabled(false);
actEditFile = new QAction(tr("Edit File"), &menu);
actEditFile->setEnabled(false);
- actShowSymbols = new QAction(tr("Show Symbols"), &menu);
- actShowSymbols->setEnabled(false);
+ actShowModuleSymbols = new QAction(tr("Show Symbols"), &menu);
+ actShowModuleSymbols->setEnabled(false);
} else {
actLoadSymbolsForModule
= new QAction(tr("Load Symbols for Module \"%1\"").arg(name), &menu);
@@ -149,17 +134,19 @@ void ModulesWindow::contextMenuEvent(QContextMenuEvent *ev)
->setEnabled(capabilities & ReloadModuleSymbolsCapability);
actEditFile
= new QAction(tr("Edit File \"%1\"").arg(name), &menu);
- actShowSymbols
+ actShowModuleSymbols
= new QAction(tr("Show Symbols in File \"%1\"").arg(name), &menu);
+ actShowModuleSymbols
+ ->setEnabled(capabilities & ShowModuleSymbolsCapability);
}
menu.addAction(actUpdateModuleList);
- //menu.addAction(actShowSourceFiles); // FIXME
+ //menu.addAction(actShowModuleSources); // FIXME
menu.addAction(actLoadSymbolsForAllModules);
menu.addAction(actExamineAllModules);
menu.addAction(actLoadSymbolsForModule);
menu.addAction(actEditFile);
- //menu.addAction(actShowSymbols); // FIXME
+ menu.addAction(actShowModuleSymbols);
menu.addSeparator();
QAction *actAdjustColumnWidths =
menu.addAction(tr("Adjust Column Widths to Contents"));
@@ -168,29 +155,28 @@ void ModulesWindow::contextMenuEvent(QContextMenuEvent *ev)
actAlwaysAdjustColumnWidth->setCheckable(true);
actAlwaysAdjustColumnWidth->setChecked(m_alwaysResizeColumnsToContents);
menu.addSeparator();
- menu.addAction(theDebuggerAction(SettingsDialog));
+ menu.addAction(debuggerCore()->action(SettingsDialog));
QAction *act = menu.exec(ev->globalPos());
- if (act == actUpdateModuleList) {
- setModelData(RequestReloadModulesRole);
- } else if (act == actAdjustColumnWidths) {
- resizeColumnsToContents();
- } else if (act == actAlwaysAdjustColumnWidth) {
- setAlwaysResizeColumnsToContents(!m_alwaysResizeColumnsToContents);
- //} else if (act == actShowSourceFiles) {
- // emit displaySourceRequested(name);
- } else if (act == actLoadSymbolsForAllModules) {
- setModelData(RequestAllSymbolsRole);
- } else if (act == actExamineAllModules) {
- setModelData(RequestExamineModulesRole);
- } else if (act == actLoadSymbolsForModule) {
- setModelData(RequestModuleSymbolsRole, name);
- } else if (act == actEditFile) {
- setModelData(RequestOpenFileRole, name);
- } else if (act == actShowSymbols) {
- setModelData(RequestModuleSymbolsRole, name);
- }
+ if (act == actUpdateModuleList)
+ engine->reloadModules();
+ else if (act == actAdjustColumnWidths)
+ resizeColumnsToContents();
+ else if (act == actAlwaysAdjustColumnWidth)
+ setAlwaysResizeColumnsToContents(!m_alwaysResizeColumnsToContents);
+ else if (act == actShowModuleSources)
+ engine->loadSymbols(name);
+ else if (act == actLoadSymbolsForAllModules)
+ engine->loadAllSymbols();
+ else if (act == actExamineAllModules)
+ engine->examineModules();
+ else if (act == actLoadSymbolsForModule)
+ engine->loadSymbols(name);
+ else if (act == actEditFile)
+ engine->gotoLocation(name);
+ else if (act == actShowModuleSymbols)
+ engine->requestModuleSymbols(name);
}
void ModulesWindow::resizeColumnsToContents()
@@ -220,12 +206,5 @@ void ModulesWindow::setModel(QAbstractItemModel *model)
setAlwaysResizeColumnsToContents(true);
}
-void ModulesWindow::setModelData
- (int role, const QVariant &value, const QModelIndex &index)
-{
- QTC_ASSERT(model(), return);
- model()->setData(index, value, role);
-}
-
} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/moduleswindow.h b/src/plugins/debugger/moduleswindow.h
index 57546d8e25..75e1ed4ea3 100644
--- a/src/plugins/debugger/moduleswindow.h
+++ b/src/plugins/debugger/moduleswindow.h
@@ -53,11 +53,8 @@ private slots:
void setAlternatingRowColorsHelper(bool on) { setAlternatingRowColors(on); }
private:
- void resizeEvent(QResizeEvent *ev);
void contextMenuEvent(QContextMenuEvent *ev);
void setModel(QAbstractItemModel *model);
- void setModelData(int role, const QVariant &value = QVariant(),
- const QModelIndex &index = QModelIndex());
bool m_alwaysResizeColumnsToContents;
};
diff --git a/src/plugins/debugger/pdb/pdbengine.cpp b/src/plugins/debugger/pdb/pdbengine.cpp
index b4b6fbf079..15d2047053 100644
--- a/src/plugins/debugger/pdb/pdbengine.cpp
+++ b/src/plugins/debugger/pdb/pdbengine.cpp
@@ -36,7 +36,7 @@
#include "pdbengine.h"
#include "debuggeractions.h"
-#include "debuggerconstants.h"
+#include "debuggercore.h"
#include "debuggerdialogs.h"
#include "debuggerplugin.h"
#include "debuggerstringutils.h"
@@ -54,7 +54,6 @@
#include <texteditor/itexteditor.h>
#include <coreplugin/ifile.h>
-//#include <coreplugin/scriptmanager/scriptmanager.h>
#include <coreplugin/icore.h>
#include <QtCore/QDateTime>
@@ -171,7 +170,7 @@ void PdbEngine::setupEngine()
connect(this, SIGNAL(outputReady(QByteArray)),
SLOT(handleOutput2(QByteArray)), Qt::QueuedConnection);
- // We will stop immediatly, so setup a proper callback.
+ // We will stop immediately, so setup a proper callback.
PdbCommand cmd;
cmd.callback = &PdbEngine::handleFirstCommand;
m_commands.enqueue(cmd);
@@ -323,7 +322,7 @@ void PdbEngine::activateFrame(int frameIndex)
//postCommand("-stack-select-frame " + QByteArray::number(frameIndex),
// CB(handleStackSelectFrame));
}
- gotoLocation(handler->currentFrame(), true);
+ gotoLocation(handler->currentFrame());
}
void PdbEngine::selectThread(int index)
@@ -331,58 +330,34 @@ void PdbEngine::selectThread(int index)
Q_UNUSED(index)
}
-static QByteArray breakpointLocation(const BreakpointData *data)
+bool PdbEngine::acceptsBreakpoint(BreakpointId id) const
{
- if (!data->funcName.isEmpty())
- return data->funcName.toLatin1();
- // In this case, data->funcName is something like '*0xdeadbeef'
- if (data->lineNumber == 0)
- return data->funcName.toLatin1();
- //QString loc = data->useFullPath ? data->fileName : breakLocation(data->fileName);
- // The argument is simply a C-quoted version of the argument to the
- // non-MI "break" command, including the "original" quoting it wants.
- //return "\"\\\"" + GdbMi::escapeCString(data->fileName).toLocal8Bit() + "\\\":"
- // + data->lineNumber + '"';
- return data->fileName.toLocal8Bit() + ':' + QByteArray::number(data->lineNumber);
+ const QString fileName = breakHandler()->fileName(id);
+ return fileName.endsWith(QLatin1String(".py"));
}
-void PdbEngine::attemptBreakpointSynchronization()
+void PdbEngine::insertBreakpoint(BreakpointId id)
{
BreakHandler *handler = breakHandler();
- //qDebug() << "ATTEMPT BP SYNC";
- bool updateNeeded = false;
- for (int index = 0; index != handler->size(); ++index) {
- BreakpointData *data = handler->at(index);
- if (data->pending) {
- data->pending = false; // FIXME
- updateNeeded = true;
- QByteArray loc = breakpointLocation(data);
- postCommand("break " + loc, CB(handleBreakInsert), QVariant(index));
- }
-/*
- if (data->bpNumber.isEmpty()) {
- data->bpNumber = QByteArray::number(index + 1);
- updateNeeded = true;
- }
- if (!data->fileName.isEmpty() && data->markerFileName().isEmpty()) {
- data->setMarkerFileName(data->fileName);
- data->setMarkerLineNumber(data->lineNumber.toInt());
- updateNeeded = true;
- }
-*/
- }
- //if (updateNeeded)
- // handler->updateMarkers();
+ QTC_ASSERT(handler->state(id) == BreakpointInsertRequested, /**/);
+ handler->notifyBreakpointInsertProceeding(id);
+
+ QByteArray loc;
+ if (handler->type(id) == BreakpointByFunction)
+ loc = handler->functionName(id).toLatin1();
+ else
+ loc = handler->fileName(id).toLocal8Bit() + ':'
+ + QByteArray::number(handler->lineNumber(id));
+
+ postCommand("break " + loc, CB(handleBreakInsert), QVariant(id));
}
void PdbEngine::handleBreakInsert(const PdbResponse &response)
{
//qDebug() << "BP RESPONSE: " << response.data;
// "Breakpoint 1 at /pdb/math.py:10"
- int index = response.cookie.toInt();
+ BreakpointId id(response.cookie.toInt());
BreakHandler *handler = breakHandler();
- BreakpointData *data = handler->at(index);
- QTC_ASSERT(data, return);
QTC_ASSERT(response.data.startsWith("Breakpoint "), return);
int pos1 = response.data.indexOf(" at ");
QTC_ASSERT(pos1 != -1, return);
@@ -390,10 +365,24 @@ void PdbEngine::handleBreakInsert(const PdbResponse &response)
int pos2 = response.data.lastIndexOf(":");
QByteArray file = response.data.mid(pos1 + 4, pos2 - pos1 - 4);
QByteArray line = response.data.mid(pos2 + 1);
- data->bpNumber = bpnr;
- data->bpFileName = _(file);
- data->bpLineNumber = line.toInt();
- handler->updateMarkers();
+ BreakpointResponse br;
+ br.number = bpnr.toInt();
+ br.fileName = _(file);
+ br.lineNumber = line.toInt();
+ handler->setResponse(id, br);
+}
+
+void PdbEngine::removeBreakpoint(BreakpointId id)
+{
+ BreakHandler *handler = breakHandler();
+ QTC_ASSERT(handler->state(id) == BreakpointRemoveRequested, /**/);
+ handler->notifyBreakpointRemoveProceeding(id);
+ BreakpointResponse br = handler->response(id);
+ showMessage(_("DELETING BP %1 IN %2").arg(br.number)
+ .arg(handler->fileName(id)));
+ postCommand("clear " + QByteArray::number(br.number));
+ // Pretend it succeeds without waiting for response.
+ handler->notifyBreakpointRemoveOk(id);
}
void PdbEngine::loadSymbols(const QString &moduleName)
@@ -451,7 +440,7 @@ void PdbEngine::handleListSymbols(const PdbResponse &response)
symbol.name = _(item.findChild("name").data());
symbols.append(symbol);
}
- showModuleSymbols(moduleName, symbols);
+ debuggerCore()->showModuleSymbols(moduleName, symbols);
}
//////////////////////////////////////////////////////////////////////
@@ -698,7 +687,7 @@ void PdbEngine::handleResponse(const QByteArray &response0)
frame.file = _(fileName);
frame.line = lineNumber;
if (frame.line > 0 && QFileInfo(frame.file).exists()) {
- gotoLocation(frame, true);
+ gotoLocation(frame);
notifyInferiorSpontaneousStop();
return;
}
@@ -745,9 +734,9 @@ void PdbEngine::updateLocals()
}
QByteArray options;
- if (theDebuggerBoolSetting(UseDebuggingHelpers))
+ if (debuggerCore()->boolSetting(UseDebuggingHelpers))
options += "fancy,";
- if (theDebuggerBoolSetting(AutoDerefPointers))
+ if (debuggerCore()->boolSetting(AutoDerefPointers))
options += "autoderef,";
if (options.isEmpty())
options += "defaults,";
@@ -812,7 +801,7 @@ void PdbEngine::handleBacktrace(const PdbResponse &response)
if (currentIndex != -1) {
currentIndex = frameCount - currentIndex - 1;
stackHandler()->setCurrentIndex(currentIndex);
- gotoLocation(stackFrames.at(currentIndex), true);
+ gotoLocation(stackFrames.at(currentIndex));
}
updateLocals();
diff --git a/src/plugins/debugger/pdb/pdbengine.h b/src/plugins/debugger/pdb/pdbengine.h
index bc43566e08..cb1d1aa805 100644
--- a/src/plugins/debugger/pdb/pdbengine.h
+++ b/src/plugins/debugger/pdb/pdbengine.h
@@ -92,9 +92,12 @@ private:
void activateFrame(int index);
void selectThread(int index);
- void attemptBreakpointSynchronization();
+ bool acceptsBreakpoint(BreakpointId id) const;
+ void insertBreakpoint(BreakpointId id);
+ void removeBreakpoint(BreakpointId id);
- void assignValueInDebugger(const Internal::WatchData *w, const QString &expr, const QVariant &value);
+ void assignValueInDebugger(const WatchData *data,
+ const QString &expr, const QVariant &value);
void executeDebuggerCommand(const QString &command);
void loadSymbols(const QString &moduleName);
diff --git a/src/plugins/debugger/qml/qmladapter.cpp b/src/plugins/debugger/qml/qmladapter.cpp
index 5547771359..98ea73fad0 100644
--- a/src/plugins/debugger/qml/qmladapter.cpp
+++ b/src/plugins/debugger/qml/qmladapter.cpp
@@ -152,7 +152,7 @@ void QmlAdapter::sendMessage(const QByteArray &msg)
void QmlAdapter::connectionErrorOccurred(QAbstractSocket::SocketError socketError)
{
- showConnectionErrorMessage(tr("Error: (%1) %2", "%1=error code, %2=error message")
+ showConnectionStatusMessage(tr("Error: (%1) %2", "%1=error code, %2=error message")
.arg(d->m_conn->error()).arg(d->m_conn->errorString()));
// this is only an error if we are already connected and something goes wrong.
@@ -195,7 +195,6 @@ void QmlAdapter::connectionStateChanged()
if (!d->m_mainClient) {
d->m_mainClient = new QDeclarativeEngineDebug(d->m_conn, this);
- logServiceStatusChange(QLatin1String("QmlObserver"), static_cast<QDeclarativeDebugClient::Status>(d->m_mainClient->status()));
}
createDebuggerClient();
@@ -223,8 +222,6 @@ void QmlAdapter::createDebuggerClient()
connect(d->m_qmlClient, SIGNAL(messageWasReceived(QByteArray)),
d->m_engine.data(), SLOT(messageReceived(QByteArray)));
- logServiceStatusChange(d->m_qmlClient->name(), d->m_qmlClient->status());
-
//engine->startSuccessful(); // FIXME: AAA: port to new debugger states
}
@@ -276,7 +273,7 @@ void QmlAdapter::logServiceStatusChange(const QString &service, QDeclarativeDebu
{
switch (newStatus) {
case QDeclarativeDebugClient::Unavailable: {
- showConnectionErrorMessage(tr("Error: Cannot connect to debug service '%1'. Debugging functionality will be limited.").arg(service));
+ showConnectionErrorMessage(tr("Debug service '%1' became unavailable.").arg(service));
emit serviceConnectionError(service);
break;
}
@@ -292,6 +289,12 @@ void QmlAdapter::logServiceStatusChange(const QString &service, QDeclarativeDebu
}
}
+void QmlAdapter::logServiceActivity(const QString &service, const QString &logMessage)
+{
+ if (!d->m_engine.isNull())
+ d->m_engine.data()->showMessage(QString("%1 %2").arg(service, logMessage), LogDebug);
+}
+
void QmlAdapter::flushSendBuffer()
{
QTC_ASSERT(d->m_qmlClient->status() == QDeclarativeDebugClient::Enabled, return);
diff --git a/src/plugins/debugger/qml/qmladapter.h b/src/plugins/debugger/qml/qmladapter.h
index 5aaef1734d..dd31629ae8 100644
--- a/src/plugins/debugger/qml/qmladapter.h
+++ b/src/plugins/debugger/qml/qmladapter.h
@@ -77,7 +77,9 @@ public:
void setMaxConnectionAttempts(int maxAttempts);
void setConnectionAttemptInterval(int interval);
- void logServiceStatusChange(const QString &service, QDeclarativeDebugClient::Status newStatus);
+public slots:
+ void logServiceStatusChange(const QString &service, QDeclarativeDebugClient::Status newStatus);
+ void logServiceActivity(const QString &service, const QString &logMessage);
signals:
void connected();
diff --git a/src/plugins/debugger/qml/qmlcppengine.cpp b/src/plugins/debugger/qml/qmlcppengine.cpp
index a61dbc7278..0b8f53b2ea 100644
--- a/src/plugins/debugger/qml/qmlcppengine.cpp
+++ b/src/plugins/debugger/qml/qmlcppengine.cpp
@@ -1,7 +1,7 @@
#include "qmlcppengine.h"
#include "qmlengine.h"
-#include "debuggeruiswitcher.h"
-#include "debuggerplugin.h"
+#include "debuggermainwindow.h"
+#include "debuggercore.h"
#include <qmljseditor/qmljseditorconstants.h>
#include <coreplugin/editormanager/editormanager.h>
@@ -10,10 +10,10 @@
#include <QtCore/QTimer>
namespace Debugger {
+namespace Internal {
const int ConnectionWaitTimeMs = 5000;
-namespace Internal {
DebuggerEngine *createCdbEngine(const DebuggerStartParameters &, QString *);
DebuggerEngine *createGdbEngine(const DebuggerStartParameters &);
DebuggerEngine *createQmlEngine(const DebuggerStartParameters &);
@@ -21,85 +21,81 @@ DebuggerEngine *createQmlEngine(const DebuggerStartParameters &);
DebuggerEngine *createQmlCppEngine(const DebuggerStartParameters &sp)
{
QmlCppEngine *newEngine = new QmlCppEngine(sp);
- if (newEngine->cppEngine()) {
+ if (newEngine->cppEngine())
return newEngine;
- } else {
- delete newEngine;
- return 0;
- }
+ delete newEngine;
+ return 0;
}
-} // namespace Internal
-struct QmlCppEnginePrivate {
+class QmlCppEnginePrivate
+{
+public:
QmlCppEnginePrivate();
+ ~QmlCppEnginePrivate() {}
- QmlEngine *m_qmlEngine;
+ friend class QmlCppEngine;
+private:
+ DebuggerEngine *m_qmlEngine;
DebuggerEngine *m_cppEngine;
DebuggerEngine *m_activeEngine;
- bool m_shutdownOk;
- bool m_shutdownDeferred;
- bool m_shutdownDone;
- bool m_isInitialStartup;
+ DebuggerState m_errorState;
};
-QmlCppEnginePrivate::QmlCppEnginePrivate() :
- m_qmlEngine(0),
+QmlCppEnginePrivate::QmlCppEnginePrivate()
+ : m_qmlEngine(0),
m_cppEngine(0),
m_activeEngine(0),
- m_shutdownOk(true)
- , m_shutdownDeferred(false)
- , m_shutdownDone(false)
- , m_isInitialStartup(true)
-{
-}
+ m_errorState(InferiorRunOk)
+{}
+
QmlCppEngine::QmlCppEngine(const DebuggerStartParameters &sp)
: DebuggerEngine(sp), d(new QmlCppEnginePrivate)
{
- d->m_qmlEngine = qobject_cast<QmlEngine*>(Internal::createQmlEngine(sp));
- d->m_qmlEngine->setAttachToRunningExternalApp(true);
+ d->m_qmlEngine = createQmlEngine(sp);
if (startParameters().cppEngineType == GdbEngineType) {
- d->m_cppEngine = Internal::createGdbEngine(sp);
+ d->m_cppEngine = createGdbEngine(sp);
} else {
QString errorMessage;
- d->m_cppEngine = Internal::createCdbEngine(sp, &errorMessage);
+ d->m_cppEngine = createCdbEngine(sp, &errorMessage);
if (!d->m_cppEngine) {
qWarning("%s", qPrintable(errorMessage));
return;
}
}
- d->m_cppEngine->setRunInWrapperEngine(true);
- d->m_qmlEngine->setRunInWrapperEngine(true);
+ d->m_cppEngine->setSlaveEngine(true);
+ d->m_qmlEngine->setSlaveEngine(true);
d->m_activeEngine = d->m_cppEngine;
- connect(d->m_cppEngine, SIGNAL(stateChanged(DebuggerState)), SLOT(masterEngineStateChanged(DebuggerState)));
- connect(d->m_qmlEngine, SIGNAL(stateChanged(DebuggerState)), SLOT(slaveEngineStateChanged(DebuggerState)));
+ connect(d->m_cppEngine, SIGNAL(stateChanged(DebuggerState)),
+ SLOT(masterEngineStateChanged(DebuggerState)));
+ connect(d->m_qmlEngine, SIGNAL(stateChanged(DebuggerState)),
+ SLOT(slaveEngineStateChanged(DebuggerState)));
- Core::EditorManager *em = Core::EditorManager::instance();
- connect(em, SIGNAL(currentEditorChanged(Core::IEditor*)), SLOT(editorChanged(Core::IEditor*)));
+ connect(Core::EditorManager::instance(),
+ SIGNAL(currentEditorChanged(Core::IEditor*)),
+ SLOT(editorChanged(Core::IEditor*)));
}
QmlCppEngine::~QmlCppEngine()
{
delete d->m_qmlEngine;
delete d->m_cppEngine;
- d->m_qmlEngine = 0;
- d->m_cppEngine = 0;
}
void QmlCppEngine::editorChanged(Core::IEditor *editor)
{
- // change the engine based on editor, but only if we're not currently in stopped state.
+ // Change the engine based on editor, but only if we're not
+ // currently in stopped state.
if (state() != InferiorRunOk || !editor)
return;
- if (editor->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID) {
+ if (editor->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID)
setActiveEngine(QmlLanguage);
- } else {
+ else
setActiveEngine(CppLanguage);
- }
}
void QmlCppEngine::setActiveEngine(DebuggerLanguage language)
@@ -120,17 +116,27 @@ void QmlCppEngine::setActiveEngine(DebuggerLanguage language)
}
if (previousEngine != d->m_activeEngine) {
showStatusMessage(tr("%1 debugger activated").arg(engineName));
- plugin()->displayDebugger(d->m_activeEngine, updateEngine);
+ debuggerCore()->displayDebugger(d->m_activeEngine, updateEngine);
}
}
+DebuggerLanguage QmlCppEngine::activeEngine() const
+{
+ if (d->m_activeEngine == d->m_cppEngine)
+ return CppLanguage;
+ if (d->m_activeEngine == d->m_qmlEngine)
+ return QmlLanguage;
+ return AnyLanguage;
+}
+
void QmlCppEngine::setToolTipExpression(const QPoint & mousePos,
TextEditor::ITextEditor *editor, int cursorPos)
{
d->m_activeEngine->setToolTipExpression(mousePos, editor, cursorPos);
}
-void QmlCppEngine::updateWatchData(const Internal::WatchData &data, const Internal::WatchUpdateFlags &flags)
+void QmlCppEngine::updateWatchData(const WatchData &data,
+ const WatchUpdateFlags &flags)
{
d->m_activeEngine->updateWatchData(data, flags);
}
@@ -140,15 +146,15 @@ void QmlCppEngine::watchPoint(const QPoint &point)
d->m_cppEngine->watchPoint(point);
}
-void QmlCppEngine::fetchMemory(Internal::MemoryViewAgent *mva, QObject *obj,
+void QmlCppEngine::fetchMemory(MemoryAgent *ma, QObject *obj,
quint64 addr, quint64 length)
{
- d->m_cppEngine->fetchMemory(mva, obj, addr, length);
+ d->m_cppEngine->fetchMemory(ma, obj, addr, length);
}
-void QmlCppEngine::fetchDisassembler(Internal::DisassemblerViewAgent *dva)
+void QmlCppEngine::fetchDisassembler(DisassemblerAgent *da)
{
- d->m_cppEngine->fetchDisassembler(dva);
+ d->m_cppEngine->fetchDisassembler(da);
}
void QmlCppEngine::activateFrame(int index)
@@ -230,12 +236,13 @@ void QmlCppEngine::updateAll()
void QmlCppEngine::attemptBreakpointSynchronization()
{
d->m_cppEngine->attemptBreakpointSynchronization();
- static_cast<DebuggerEngine*>(d->m_qmlEngine)->attemptBreakpointSynchronization();
+ d->m_qmlEngine->attemptBreakpointSynchronization();
}
-bool QmlCppEngine::acceptsBreakpoint(const Internal::BreakpointData *br)
+bool QmlCppEngine::acceptsBreakpoint(BreakpointId id) const
{
- return d->m_cppEngine->acceptsBreakpoint(br) || d->m_qmlEngine->acceptsBreakpoint(br);
+ return d->m_cppEngine->acceptsBreakpoint(id)
+ || d->m_qmlEngine->acceptsBreakpoint(id);
}
void QmlCppEngine::selectThread(int index)
@@ -243,14 +250,10 @@ void QmlCppEngine::selectThread(int index)
d->m_cppEngine->selectThread(index);
}
-void QmlCppEngine::assignValueInDebugger(const Internal::WatchData *w, const QString &expr, const QVariant &value)
-{
- d->m_activeEngine->assignValueInDebugger(w, expr, value);
-}
-
-QAbstractItemModel *QmlCppEngine::commandModel() const
+void QmlCppEngine::assignValueInDebugger(const WatchData *data,
+ const QString &expr, const QVariant &value)
{
- return d->m_activeEngine->commandModel();
+ d->m_activeEngine->assignValueInDebugger(data, expr, value);
}
QAbstractItemModel *QmlCppEngine::modulesModel() const
@@ -258,11 +261,6 @@ QAbstractItemModel *QmlCppEngine::modulesModel() const
return d->m_cppEngine->modulesModel();
}
-QAbstractItemModel *QmlCppEngine::breakModel() const
-{
- return d->m_activeEngine->breakModel();
-}
-
QAbstractItemModel *QmlCppEngine::registerModel() const
{
return d->m_cppEngine->registerModel();
@@ -336,17 +334,31 @@ void QmlCppEngine::executeReturn()
void QmlCppEngine::continueInferior()
{
- d->m_activeEngine->continueInferior();
+ if (d->m_activeEngine->state() == InferiorStopOk) {
+ d->m_activeEngine->continueInferior();
+ } else {
+ notifyInferiorRunRequested();
+ }
}
void QmlCppEngine::interruptInferior()
{
- d->m_activeEngine->interruptInferior();
+ if (d->m_activeEngine->state() == InferiorRunOk) {
+ d->m_activeEngine->requestInterruptInferior();
+ } else {
+ if (d->m_activeEngine->state() == InferiorStopOk && (!checkErrorState(InferiorStopFailed))) {
+ notifyInferiorStopOk();
+ }
+ }
}
void QmlCppEngine::requestInterruptInferior()
{
- d->m_activeEngine->requestInterruptInferior();
+ DebuggerEngine::requestInterruptInferior();
+
+ if (d->m_activeEngine->state() == InferiorRunOk) {
+ d->m_activeEngine->requestInterruptInferior();
+ }
}
void QmlCppEngine::executeRunToLine(const QString &fileName, int lineNumber)
@@ -379,6 +391,50 @@ void QmlCppEngine::frameDown()
d->m_activeEngine->frameDown();
}
+/////////////////////////////////////////////////////////
+
+bool QmlCppEngine::checkErrorState(const DebuggerState stateToCheck)
+{
+ if (d->m_errorState != stateToCheck)
+ return false;
+
+ // reset state ( so that more than one error can accumulate over time )
+ d->m_errorState = InferiorRunOk;
+ switch (stateToCheck) {
+ case InferiorRunOk:
+ // nothing to do
+ break;
+ case EngineRunFailed:
+ notifyEngineRunFailed();
+ break;
+ case EngineSetupFailed:
+ notifyEngineSetupFailed();
+ break;
+ case EngineShutdownFailed:
+ notifyEngineShutdownFailed();
+ break;
+ case InferiorSetupFailed:
+ notifyInferiorSetupFailed();
+ break;
+ case InferiorRunFailed:
+ notifyInferiorRunFailed();
+ break;
+ case InferiorUnrunnable:
+ notifyInferiorUnrunnable();
+ break;
+ case InferiorStopFailed:
+ notifyInferiorStopFailed();
+ break;
+ case InferiorShutdownFailed:
+ notifyInferiorShutdownFailed();
+ break;
+ default:
+ // unexpected
+ break;
+ }
+ return true;
+}
+
void QmlCppEngine::notifyInferiorRunOk()
{
DebuggerEngine::notifyInferiorRunOk();
@@ -394,206 +450,183 @@ void QmlCppEngine::setupEngine()
void QmlCppEngine::setupInferior()
{
- // called through notifyEngineSetupOk
+ if (!checkErrorState(InferiorSetupFailed)) {
+ notifyInferiorSetupOk();
+ }
}
void QmlCppEngine::runEngine()
{
- // should never happen
- showMessage(QString(Q_FUNC_INFO), LogError);
+ if (!checkErrorState(EngineRunFailed)) {
+ if (d->m_errorState == InferiorRunOk) {
+ switch (d->m_activeEngine->state()) {
+ case InferiorRunOk:
+ notifyEngineRunAndInferiorRunOk();
+ break;
+ case InferiorStopOk:
+ notifyEngineRunAndInferiorStopOk();
+ break;
+ default: // not supported?
+ notifyEngineRunFailed();
+ break;
+ }
+ } else {
+ notifyEngineRunFailed();
+ }
+ }
}
void QmlCppEngine::shutdownInferior()
{
- // user wants to stop inferior: always use cpp engine for this.
- if (d->m_activeEngine == d->m_qmlEngine) {
- d->m_activeEngine = d->m_cppEngine;
-
- // we end up in this state after trying to shut down while debugging qml.
- // b/c qml does not shutdown by itself, restore previous state and continue.
- if (d->m_qmlEngine->state() == InferiorShutdownRequested) {
- d->m_qmlEngine->setState(InferiorStopOk, true);
- }
-
- if (d->m_qmlEngine->state() == InferiorStopOk) {
- d->m_qmlEngine->continueInferior();
+ if (!checkErrorState(InferiorShutdownFailed)) {
+ if (d->m_cppEngine->state() == InferiorStopOk) {
+ d->m_cppEngine->quitDebugger();
+ } else {
+ notifyInferiorShutdownOk();
}
}
- if (d->m_cppEngine->state() == InferiorRunOk) {
- // first interrupt c++ engine; when done, we can shutdown.
- d->m_shutdownDeferred = true;
- d->m_cppEngine->requestInterruptInferior();
- }
- if (!d->m_shutdownDeferred)
- d->m_cppEngine->shutdownInferior();
}
-void QmlCppEngine::shutdownEngine()
-{
- d->m_cppEngine->shutdownEngine();
- d->m_qmlEngine->shutdownEngineAsSlave();
- notifyEngineShutdownOk();
-}
-
-void QmlCppEngine::finishDebugger()
+void QmlCppEngine::initEngineShutdown()
{
- if (!d->m_shutdownDone) {
- d->m_shutdownDone = true;
- if (d->m_shutdownOk) {
- notifyEngineShutdownOk();
+ if (d->m_qmlEngine->state() != DebuggerFinished) {
+ d->m_qmlEngine->quitDebugger();
+ } else
+ if (d->m_cppEngine->state() != DebuggerFinished) {
+ d->m_cppEngine->quitDebugger();
+ } else
+ if (state() == EngineSetupRequested) {
+ if (!runControl() || d->m_errorState == EngineSetupFailed) {
+ notifyEngineSetupFailed();
} else {
- notifyEngineShutdownFailed();
+ notifyEngineSetupOk();
}
+ } else
+ if (state() == InferiorStopRequested) {
+ checkErrorState(InferiorStopFailed);
+ } else
+ if (state() == InferiorShutdownRequested && !checkErrorState(InferiorShutdownFailed)) {
+ notifyInferiorShutdownOk();
+ } else
+ if (state() != DebuggerFinished) {
+ quitDebugger();
}
}
-void QmlCppEngine::setupSlaveEngineOnTimer()
+void QmlCppEngine::shutdownEngine()
{
- QTimer::singleShot(0, this, SLOT(setupSlaveEngine()));
+ if (!checkErrorState(EngineShutdownFailed)) {
+ showStatusMessage(tr("Debugging finished"));
+ notifyEngineShutdownOk();
+ }
}
void QmlCppEngine::setupSlaveEngine()
{
- if (state() == InferiorRunRequested)
+ if (d->m_qmlEngine->state() == DebuggerNotReady)
d->m_qmlEngine->startDebugger(runControl());
}
void QmlCppEngine::masterEngineStateChanged(const DebuggerState &newState)
{
- //qDebug() << "gdb state set to" << newState;
-
- switch(newState) {
- case EngineSetupRequested:
- // go through this state
- break;
-
- case EngineSetupFailed:
- notifyEngineSetupFailed();
- break;
-
- case EngineSetupOk:
- notifyEngineSetupOk();
- break;
-
- case InferiorSetupRequested:
- // go through this state
- break;
-
- case InferiorSetupFailed:
- notifyInferiorSetupFailed();
- break;
-
- case EngineRunRequested:
- setState(newState);
- break;
-
- case EngineRunFailed:
- notifyEngineRunFailed();
- break;
+ if (newState == InferiorStopOk) {
+ setActiveEngine(CppLanguage);
+ }
+ engineStateChanged(newState);
+}
- case InferiorUnrunnable:
- setState(newState);
- break;
+void QmlCppEngine::slaveEngineStateChanged(const DebuggerState &newState)
+{
+ if (newState == InferiorStopOk) {
+ setActiveEngine(QmlLanguage);
+ }
+ engineStateChanged(newState);
+}
- case InferiorRunRequested:
- setState(newState);
- break;
+void QmlCppEngine::engineStateChanged(const DebuggerState &newState)
+{
+ switch (newState) {
case InferiorRunOk:
+ // startup?
if (d->m_qmlEngine->state() == DebuggerNotReady) {
- if (d->m_isInitialStartup) {
- d->m_isInitialStartup = false;
- setupSlaveEngineOnTimer();
- } else {
- setupSlaveEngine();
- }
- } else {
+ setupSlaveEngine();
+ } else
+ if (d->m_cppEngine->state() == DebuggerNotReady) {
+ setupEngine();
+ } else
+ if (state() == EngineSetupRequested) {
+ notifyEngineSetupOk();
+ } else
+ // breakpoint?
+ if (state() == InferiorStopOk) {
+ continueInferior();
+ } else
+ if (state() == InferiorStopRequested) {
+ checkErrorState(InferiorStopFailed);
+ } else
+ if (state() == InferiorRunRequested && (!checkErrorState(InferiorRunFailed)) && (!checkErrorState(InferiorUnrunnable))) {
notifyInferiorRunOk();
}
break;
- case InferiorRunFailed:
- notifyInferiorRunFailed();
+ case InferiorRunRequested:
+ // follow the inferior
+ if (state() == InferiorStopOk && checkErrorState(InferiorRunOk)) {
+ continueInferior();
+ }
break;
case InferiorStopRequested:
- if (state() == InferiorRunRequested) {
- // if stopping on startup, move on to normal state
- // and go forward. Also, stop connection and continue later if needed.
- d->m_qmlEngine->pauseConnection();
- setState(EngineRunRequested, true);
- notifyEngineRunAndInferiorRunOk();
- setState(newState);
- } else {
- setState(newState);
+ // follow the inferior
+ if (state() == InferiorRunOk && checkErrorState(InferiorRunOk)) {
+ requestInterruptInferior();
}
break;
case InferiorStopOk:
- // debugger can stop while qml connection is not made yet, so we can
- // end up in an illegal state transition here.
- if (state() == InferiorStopRequested
- || state() == InferiorRunFailed)
- {
- setState(newState);
- } else if (state() == InferiorRunOk) {
- // if we break on CPP side while running & engine is QML, switch.
- if (d->m_activeEngine == d->m_qmlEngine) {
- setActiveEngine(CppLanguage);
+ // check breakpoints
+ if (state() == InferiorRunRequested) {
+ checkErrorState(InferiorRunFailed);
+ } else
+ if (checkErrorState(InferiorRunOk)) {
+ if (state() == InferiorRunOk) {
+ requestInterruptInferior();
+ } else
+ if (state() == InferiorStopRequested) {
+ interruptInferior();
}
- setState(newState);
- } else if (state() == InferiorRunRequested) {
- setState(newState, true);
- }
- if (d->m_shutdownDeferred) {
- d->m_activeEngine = d->m_cppEngine;
- d->m_shutdownDeferred = false;
- shutdownInferior();
}
break;
+ case EngineRunFailed:
+ case EngineSetupFailed:
+ case EngineShutdownFailed:
+ case InferiorSetupFailed:
+ case InferiorRunFailed:
+ case InferiorUnrunnable:
case InferiorStopFailed:
- setState(newState);
- if (d->m_shutdownDeferred) {
- d->m_activeEngine = d->m_cppEngine;
- d->m_shutdownDeferred = false;
- shutdownInferior();
+ case InferiorShutdownFailed:
+ if (d->m_errorState == InferiorRunOk) {
+ d->m_errorState = newState;
}
break;
- // here, we shut down the qml engine first.
- // but due to everything being asyncronous, we cannot guarantee
- // that it is shut down completely before gdb engine is shut down.
case InferiorShutdownRequested:
- if (d->m_activeEngine == d->m_qmlEngine) {
- d->m_activeEngine = d->m_cppEngine;
+ if (activeEngine() == QmlLanguage) {
+ setActiveEngine(CppLanguage);
}
-
- d->m_qmlEngine->shutdownInferiorAsSlave();
- setState(newState);
- break;
-
- case InferiorShutdownOk:
- setState(newState);
- d->m_qmlEngine->shutdownEngineAsSlave();
- break;
-
- case InferiorShutdownFailed:
- setState(newState);
- d->m_qmlEngine->shutdownEngineAsSlave();
break;
case EngineShutdownRequested:
- setState(newState);
+ // we have to abort the setup before the sub-engines die
+ // because we depend on an active runcontrol that will be shut down by the dying engine
+ if (state() == EngineSetupRequested)
+ notifyEngineSetupFailed();
break;
- case EngineShutdownOk:
- finishDebugger();
- break;
-
- case EngineShutdownFailed:
- d->m_shutdownOk = false;
- finishDebugger();
+ case DebuggerFinished:
+ initEngineShutdown();
break;
default:
@@ -601,85 +634,16 @@ void QmlCppEngine::masterEngineStateChanged(const DebuggerState &newState)
}
}
-void QmlCppEngine::slaveEngineStateChanged(const DebuggerState &newState)
+void QmlCppEngine::handleRemoteSetupDone(int gdbServerPort, int qmlPort)
{
- //qDebug() << " qml engine changed to" << newState;
-
- if (d->m_activeEngine == d->m_qmlEngine) {
- handleSlaveEngineStateChangeAsActive(newState);
- } else {
- handleSlaveEngineStateChange(newState);
- }
+ d->m_qmlEngine->handleRemoteSetupDone(gdbServerPort, qmlPort);
+ d->m_cppEngine->handleRemoteSetupDone(gdbServerPort, qmlPort);
}
-void QmlCppEngine::handleSlaveEngineStateChange(const DebuggerState &newState)
+void QmlCppEngine::handleRemoteSetupFailed(const QString &message)
{
- switch(newState) {
- case InferiorRunOk:
- if (state() == InferiorRunRequested) {
- // force state back so that the notification will succeed on init
- setState(EngineRunRequested, true);
- notifyEngineRunAndInferiorRunOk();
- } else {
- // we have to manually override state with current one, because
- // otherwise we'll have debugger controls in inconsistent state.
- setState(state(), true);
- }
-
- break;
-
- case InferiorStopOk:
- if (state() == InferiorRunOk) {
- // breakpoint was hit while running the app; change the active engine.
- setActiveEngine(QmlLanguage);
- setState(InferiorStopOk);
- }
- break;
-
- case InferiorRunFailed:
- notifyInferiorRunFailed();
- break;
-
- case EngineShutdownFailed:
- d->m_shutdownOk = false;
- break;
-
- default:
- // reset wrapper engine state to current state.
- setState(state(), true);
- break;
- }
-}
-
-void QmlCppEngine::handleSlaveEngineStateChangeAsActive(const DebuggerState &newState)
-{
- switch(newState) {
- case InferiorRunRequested:
- setState(newState);
- break;
-
- case InferiorRunOk:
- setState(newState);
- break;
-
- case InferiorStopOk:
- setState(newState);
- break;
-
- case InferiorRunFailed:
- notifyInferiorRunFailed();
- break;
-
- case InferiorShutdownRequested:
- if (d->m_cppEngine->state() == InferiorRunOk) {
- // occurs when user presses stop button from debugger UI.
- shutdownInferior();
- }
- break;
-
- default:
- break;
- }
+ d->m_qmlEngine->handleRemoteSetupFailed(message);
+ d->m_cppEngine->handleRemoteSetupFailed(message);
}
DebuggerEngine *QmlCppEngine::cppEngine() const
@@ -687,4 +651,5 @@ DebuggerEngine *QmlCppEngine::cppEngine() const
return d->m_cppEngine;
}
+} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/qml/qmlcppengine.h b/src/plugins/debugger/qml/qmlcppengine.h
index d3bb72056d..0e554aa295 100644
--- a/src/plugins/debugger/qml/qmlcppengine.h
+++ b/src/plugins/debugger/qml/qmlcppengine.h
@@ -10,8 +10,9 @@ class IEditor;
}
namespace Debugger {
+namespace Internal {
-struct QmlCppEnginePrivate;
+class QmlCppEnginePrivate;
class DEBUGGER_EXPORT QmlCppEngine : public DebuggerEngine
{
@@ -20,16 +21,18 @@ public:
explicit QmlCppEngine(const DebuggerStartParameters &sp);
virtual ~QmlCppEngine();
+ DebuggerLanguage activeEngine() const;
void setActiveEngine(DebuggerLanguage language);
- virtual void setToolTipExpression(const QPoint & /* mousePos */,
- TextEditor::ITextEditor * /* editor */, int /* cursorPos */);
- virtual void updateWatchData(const Internal::WatchData & /* data */, const Internal::WatchUpdateFlags &flags);
+ virtual void setToolTipExpression(const QPoint &mousePos,
+ TextEditor::ITextEditor * editor, int cursorPos);
+ virtual void updateWatchData(const WatchData &data,
+ const WatchUpdateFlags &flags);
virtual void watchPoint(const QPoint &);
- virtual void fetchMemory(Internal::MemoryViewAgent *, QObject *,
+ virtual void fetchMemory(MemoryAgent *, QObject *,
quint64 addr, quint64 length);
- virtual void fetchDisassembler(Internal::DisassemblerViewAgent *);
+ virtual void fetchDisassembler(DisassemblerAgent *);
virtual void activateFrame(int index);
virtual void reloadModules();
@@ -52,14 +55,13 @@ public:
virtual void updateAll();
virtual void attemptBreakpointSynchronization();
- virtual bool acceptsBreakpoint(const Internal::BreakpointData *br);
+ virtual bool acceptsBreakpoint(BreakpointId id) const;
virtual void selectThread(int index);
- virtual void assignValueInDebugger(const Internal::WatchData *w, const QString &expr, const QVariant &value);
+ virtual void assignValueInDebugger(const WatchData *data,
+ const QString &expr, const QVariant &value);
- QAbstractItemModel *commandModel() const;
QAbstractItemModel *modulesModel() const;
- QAbstractItemModel *breakModel() const;
QAbstractItemModel *registerModel() const;
QAbstractItemModel *stackModel() const;
QAbstractItemModel *threadsModel() const;
@@ -69,6 +71,8 @@ public:
QAbstractItemModel *sourceFilesModel() const;
DebuggerEngine *cppEngine() const;
+ virtual void handleRemoteSetupDone(int gdbServerPort, int qmlPort);
+ virtual void handleRemoteSetupFailed(const QString &message);
protected:
virtual void detachDebugger();
@@ -106,15 +110,15 @@ private slots:
void editorChanged(Core::IEditor *editor);
private:
- void setupSlaveEngineOnTimer();
- void finishDebugger();
- void handleSlaveEngineStateChange(const DebuggerState &newState);
- void handleSlaveEngineStateChangeAsActive(const DebuggerState &newState);
+ void initEngineShutdown();
+ bool checkErrorState(const DebuggerState stateToCheck);
+ void engineStateChanged(const DebuggerState &newState);
private:
QScopedPointer<QmlCppEnginePrivate> d;
};
+} // namespace Internal
} // namespace Debugger
#endif // QMLGDBENGINE_H
diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp
index 2609749e81..178b0e0a2c 100644
--- a/src/plugins/debugger/qml/qmlengine.cpp
+++ b/src/plugins/debugger/qml/qmlengine.cpp
@@ -35,13 +35,13 @@
#include "qmladapter.h"
#include "debuggeractions.h"
-#include "debuggertooltip.h"
#include "debuggerconstants.h"
-#include "debuggerplugin.h"
+#include "debuggercore.h"
#include "debuggerdialogs.h"
-#include "debuggerstringutils.h"
-#include "debuggeruiswitcher.h"
+#include "debuggermainwindow.h"
#include "debuggerrunner.h"
+#include "debuggerstringutils.h"
+#include "debuggertooltip.h"
#include "breakhandler.h"
#include "moduleshandler.h"
@@ -88,41 +88,82 @@ enum {
namespace Debugger {
namespace Internal {
-QDataStream& operator>>(QDataStream& s, WatchData &data)
+struct JSAgentBreakpointData
+{
+ QByteArray functionName;
+ QByteArray fileName;
+ qint32 lineNumber;
+};
+
+uint qHash(const JSAgentBreakpointData &b)
+{
+ return b.lineNumber ^ qHash(b.fileName);
+}
+
+QDataStream &operator<<(QDataStream &s, const JSAgentBreakpointData &data)
+{
+ return s << data.functionName << data.fileName << data.lineNumber;
+}
+
+QDataStream &operator>>(QDataStream &s, JSAgentBreakpointData &data)
+{
+ return s >> data.functionName >> data.fileName >> data.lineNumber;
+}
+
+bool operator==(const JSAgentBreakpointData &b1, const JSAgentBreakpointData &b2)
+{
+ return b1.lineNumber == b2.lineNumber && b1.fileName == b2.fileName;
+}
+
+typedef QSet<JSAgentBreakpointData> JSAgentBreakpoints;
+
+
+static QDataStream &operator>>(QDataStream &s, WatchData &data)
{
data = WatchData();
- QString value;
- QString type;
- bool hasChildren;
- s >> data.exp >> data.name >> value >> type >> hasChildren >> data.objectId;
- data.setType(type.toUtf8(), false);
- data.setValue(value);
+ QByteArray name;
+ QByteArray value;
+ QByteArray type;
+ bool hasChildren = false;
+ s >> data.exp >> name >> value >> type >> hasChildren >> data.id;
+ data.name = QString::fromUtf8(name);
+ data.setType(type, false);
+ data.setValue(QString::fromUtf8(value));
data.setHasChildren(hasChildren);
data.setAllUnneeded();
return s;
}
-} // namespace Internal
+static QDataStream &operator>>(QDataStream &s, StackFrame &frame)
+{
+ frame = StackFrame();
+ QByteArray function;
+ QByteArray file;
+ s >> function >> file >> frame.line;
+ frame.function = QString::fromUtf8(function);
+ frame.file = QString::fromUtf8(file);
+ frame.usable = QFileInfo(frame.file).isReadable();
+ return s;
+}
+
-struct QmlEnginePrivate {
+class QmlEnginePrivate
+{
+public:
explicit QmlEnginePrivate(QmlEngine *q);
+ ~QmlEnginePrivate() { delete m_adapter; }
+private:
+ friend class QmlEngine;
int m_ping;
QmlAdapter *m_adapter;
ProjectExplorer::ApplicationLauncher m_applicationLauncher;
- bool m_addedAdapterToObjectPool;
- bool m_attachToRunningExternalApp;
- bool m_hasShutdown;
};
-QmlEnginePrivate::QmlEnginePrivate(QmlEngine *q) :
- m_ping(0)
-, m_adapter(new QmlAdapter(q))
-, m_addedAdapterToObjectPool(false)
-, m_attachToRunningExternalApp(false)
-, m_hasShutdown(false)
-{
-}
+QmlEnginePrivate::QmlEnginePrivate(QmlEngine *q)
+ : m_ping(0), m_adapter(new QmlAdapter(q))
+{}
+
///////////////////////////////////////////////////////////////////////
//
@@ -137,36 +178,14 @@ QmlEngine::QmlEngine(const DebuggerStartParameters &startParameters)
}
QmlEngine::~QmlEngine()
-{
-}
-
-void QmlEngine::setAttachToRunningExternalApp(bool value)
-{
- d->m_attachToRunningExternalApp = value;
-}
-
-void QmlEngine::pauseConnection()
-{
- d->m_adapter->pauseConnection();
-}
-
-void QmlEngine::gotoLocation(const QString &fileName, int lineNumber, bool setMarker)
-{
- QString processedFilename = fileName;
+{}
- if (isShadowBuildProject())
- processedFilename = fromShadowBuildFilename(fileName);
-
- DebuggerEngine::gotoLocation(processedFilename, lineNumber, setMarker);
-}
-
-void QmlEngine::gotoLocation(const Internal::StackFrame &frame, bool setMarker)
+void QmlEngine::gotoLocation(const Location &loc0)
{
- Internal::StackFrame adjustedFrame = frame;
+ Location loc = loc0;
if (isShadowBuildProject())
- adjustedFrame.file = fromShadowBuildFilename(frame.file);
-
- DebuggerEngine::gotoLocation(adjustedFrame, setMarker);
+ loc.setFileName(fromShadowBuildFilename(loc0.fileName()));
+ DebuggerEngine::gotoLocation(loc);
}
void QmlEngine::setupInferior()
@@ -174,14 +193,14 @@ void QmlEngine::setupInferior()
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
if (startParameters().startMode == AttachToRemote) {
- emit remoteStartupRequested();
+ requestRemoteSetup();
} else {
connect(&d->m_applicationLauncher, SIGNAL(processExited(int)),
- this, SLOT(disconnected()));
+ SLOT(disconnected()));
connect(&d->m_applicationLauncher, SIGNAL(appendMessage(QString,bool)),
- runControl(), SLOT(emitAppendMessage(QString,bool)));
- connect(&d->m_applicationLauncher, SIGNAL(appendOutput(QString, bool)),
- runControl(), SLOT(emitAddToOutputWindow(QString, bool)));
+ SLOT(appendMessage(QString,bool)));
+ connect(&d->m_applicationLauncher, SIGNAL(appendOutput(QString,bool)),
+ SLOT(appendOutput(QString,bool)));
connect(&d->m_applicationLauncher, SIGNAL(bringToForegroundRequested(qint64)),
runControl(), SLOT(bringApplicationToForeground(qint64)));
@@ -192,58 +211,103 @@ void QmlEngine::setupInferior()
}
}
+void QmlEngine::appendMessage(const QString &msg, bool)
+{
+ showMessage(msg, AppStuff);
+}
+
+void QmlEngine::appendOutput(const QString &msg, bool)
+{
+ showMessage(msg, AppOutput);
+}
+
void QmlEngine::connectionEstablished()
{
attemptBreakpointSynchronization();
- ExtensionSystem::PluginManager *pluginManager = ExtensionSystem::PluginManager::instance();
+ ExtensionSystem::PluginManager *pluginManager =
+ ExtensionSystem::PluginManager::instance();
pluginManager->addObject(d->m_adapter);
pluginManager->addObject(this);
- d->m_addedAdapterToObjectPool = true;
- plugin()->showMessage(tr("QML Debugger connected."), StatusBar);
+ showMessage(tr("QML Debugger connected."), StatusBar);
notifyEngineRunAndInferiorRunOk();
+
}
void QmlEngine::connectionStartupFailed()
{
- QMessageBox::critical(0,
- tr("Failed to connect to debugger"),
- tr("Could not connect to QML debugger server at %1:%2.")
- .arg(startParameters().qmlServerAddress)
- .arg(startParameters().qmlServerPort));
+ QMessageBox::critical(0, tr("Failed to connect to debugger"),
+ tr("Could not connect to QML debugger server at %1:%2.")
+ .arg(startParameters().qmlServerAddress)
+ .arg(startParameters().qmlServerPort));
notifyEngineRunFailed();
}
void QmlEngine::connectionError(QAbstractSocket::SocketError socketError)
{
if (socketError ==QAbstractSocket::RemoteHostClosedError)
- plugin()->showMessage(tr("QML Debugger: Remote host closed connection."), StatusBar);
+ showMessage(tr("QML Debugger: Remote host closed connection."), StatusBar);
}
void QmlEngine::serviceConnectionError(const QString &serviceName)
{
- plugin()->showMessage(tr("QML Debugger: Could not connect to service '%1'.").arg(serviceName), StatusBar);
+ showMessage(tr("QML Debugger: Could not connect to service '%1'.")
+ .arg(serviceName), StatusBar);
}
+void QmlEngine::pauseConnection()
+{
+ d->m_adapter->pauseConnection();
+}
+
+void QmlEngine::closeConnection()
+{
+ ExtensionSystem::PluginManager *pluginManager = ExtensionSystem::PluginManager::instance();
+ if (pluginManager->allObjects().contains(this)) {
+ disconnect(d->m_adapter, SIGNAL(connectionStartupFailed()), this, SLOT(connectionStartupFailed()));
+ d->m_adapter->closeConnection();
+
+ pluginManager->removeObject(d->m_adapter);
+ pluginManager->removeObject(this);
+ }
+}
+
+
void QmlEngine::runEngine()
{
QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
- if (!d->m_attachToRunningExternalApp) {
+ if (!isSlaveEngine()) {
+ startApplicationLauncher();
+ }
+
+ d->m_adapter->beginConnection();
+}
+
+void QmlEngine::startApplicationLauncher()
+{
+ if (!d->m_applicationLauncher.isRunning()) {
d->m_applicationLauncher.start(ProjectExplorer::ApplicationLauncher::Gui,
startParameters().executable,
startParameters().processArgs);
}
+}
- d->m_adapter->beginConnection();
- plugin()->showMessage(tr("QML Debugger connecting..."), StatusBar);
+void QmlEngine::stopApplicationLauncher()
+{
+ if (d->m_applicationLauncher.isRunning()) {
+ disconnect(&d->m_applicationLauncher, SIGNAL(processExited(int)), this, SLOT(disconnected()));
+ d->m_applicationLauncher.stop();
+ }
}
-void QmlEngine::handleRemoteSetupDone()
+void QmlEngine::handleRemoteSetupDone(int port)
{
+ if (port != -1)
+ startParameters().qmlServerPort = port;
notifyInferiorSetupOk();
}
@@ -254,78 +318,25 @@ void QmlEngine::handleRemoteSetupFailed(const QString &message)
notifyInferiorSetupFailed();
}
-void QmlEngine::shutdownInferiorAsSlave()
-{
- resetLocation();
-
- // This can be issued in almost any state. We assume, though,
- // that at this point of time the inferior is not running anymore,
- // even if stop notification were not issued or got lost.
- if (state() == InferiorRunOk) {
- setState(InferiorStopRequested);
- setState(InferiorStopOk);
- setState(InferiorShutdownRequested);
- setState(InferiorShutdownOk);
- } else {
- // force
- setState(InferiorShutdownRequested, true);
- setState(InferiorShutdownOk);
- }
-}
-
-void QmlEngine::shutdownEngineAsSlave()
-{
- if (d->m_hasShutdown)
- return;
-
- disconnect(d->m_adapter, SIGNAL(connectionStartupFailed()), this, SLOT(connectionStartupFailed()));
- d->m_adapter->closeConnection();
-
- if (d->m_addedAdapterToObjectPool) {
- ExtensionSystem::PluginManager *pluginManager = ExtensionSystem::PluginManager::instance();
- pluginManager->removeObject(d->m_adapter);
- pluginManager->removeObject(this);
- }
-
- if (d->m_attachToRunningExternalApp) {
- setState(EngineShutdownRequested, true);
- setState(EngineShutdownOk, true);
- setState(DebuggerFinished, true);
- } else {
- if (d->m_applicationLauncher.isRunning()) {
- // should only happen if engine is ill
- disconnect(&d->m_applicationLauncher, SIGNAL(processExited(int)), this, SLOT(disconnected()));
- d->m_applicationLauncher.stop();
- }
- }
- d->m_hasShutdown = true;
-}
-
void QmlEngine::shutdownInferior()
{
- // don't do normal shutdown if running as slave engine
- if (d->m_attachToRunningExternalApp)
- return;
-
- QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state());
- if (!d->m_applicationLauncher.isRunning()) {
- showMessage(tr("Trying to stop while process is no longer running."), LogError);
- } else {
- disconnect(&d->m_applicationLauncher, SIGNAL(processExited(int)), this, SLOT(disconnected()));
- if (!d->m_attachToRunningExternalApp)
- d->m_applicationLauncher.stop();
+ if (isSlaveEngine()) {
+ resetLocation();
}
+ stopApplicationLauncher();
notifyInferiorShutdownOk();
}
void QmlEngine::shutdownEngine()
{
- QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state());
+ closeConnection();
- shutdownEngineAsSlave();
+ // double check (ill engine?):
+ stopApplicationLauncher();
notifyEngineShutdownOk();
- plugin()->showMessage(QString(), StatusBar);
+ if (!isSlaveEngine())
+ showMessage(QString(), StatusBar);
}
void QmlEngine::setupEngine()
@@ -333,10 +344,13 @@ void QmlEngine::setupEngine()
d->m_adapter->setMaxConnectionAttempts(MaxConnectionAttempts);
d->m_adapter->setConnectionAttemptInterval(ConnectionAttemptDefaultInterval);
connect(d->m_adapter, SIGNAL(connectionError(QAbstractSocket::SocketError)),
- SLOT(connectionError(QAbstractSocket::SocketError)));
- connect(d->m_adapter, SIGNAL(serviceConnectionError(QString)), SLOT(serviceConnectionError(QString)));
- connect(d->m_adapter, SIGNAL(connected()), SLOT(connectionEstablished()));
- connect(d->m_adapter, SIGNAL(connectionStartupFailed()), SLOT(connectionStartupFailed()));
+ SLOT(connectionError(QAbstractSocket::SocketError)));
+ connect(d->m_adapter, SIGNAL(serviceConnectionError(QString)),
+ SLOT(serviceConnectionError(QString)));
+ connect(d->m_adapter, SIGNAL(connected()),
+ SLOT(connectionEstablished()));
+ connect(d->m_adapter, SIGNAL(connectionStartupFailed()),
+ SLOT(connectionStartupFailed()));
notifyEngineSetupOk();
}
@@ -346,7 +360,9 @@ void QmlEngine::continueInferior()
QTC_ASSERT(state() == InferiorStopOk, qDebug() << state());
QByteArray reply;
QDataStream rs(&reply, QIODevice::WriteOnly);
- rs << QByteArray("CONTINUE");
+ QByteArray cmd = "CONTINUE";
+ rs << cmd;
+ logMessage(LogSend, cmd);
sendMessage(reply);
resetLocation();
notifyInferiorRunRequested();
@@ -357,7 +373,9 @@ void QmlEngine::interruptInferior()
{
QByteArray reply;
QDataStream rs(&reply, QIODevice::WriteOnly);
- rs << QByteArray("INTERRUPT");
+ QByteArray cmd = "INTERRUPT";
+ rs << cmd;
+ logMessage(LogSend, cmd);
sendMessage(reply);
notifyInferiorStopOk();
}
@@ -366,7 +384,9 @@ void QmlEngine::executeStep()
{
QByteArray reply;
QDataStream rs(&reply, QIODevice::WriteOnly);
- rs << QByteArray("STEPINTO");
+ QByteArray cmd = "STEPINTO";
+ rs << cmd;
+ logMessage(LogSend, cmd);
sendMessage(reply);
notifyInferiorRunRequested();
notifyInferiorRunOk();
@@ -376,7 +396,9 @@ void QmlEngine::executeStepI()
{
QByteArray reply;
QDataStream rs(&reply, QIODevice::WriteOnly);
- rs << QByteArray("STEPINTO");
+ QByteArray cmd = "STEPINTO";
+ rs << cmd;
+ logMessage(LogSend, cmd);
sendMessage(reply);
notifyInferiorRunRequested();
notifyInferiorRunOk();
@@ -386,7 +408,9 @@ void QmlEngine::executeStepOut()
{
QByteArray reply;
QDataStream rs(&reply, QIODevice::WriteOnly);
- rs << QByteArray("STEPOUT");
+ QByteArray cmd = "STEPOUT";
+ rs << cmd;
+ logMessage(LogSend, cmd);
sendMessage(reply);
notifyInferiorRunRequested();
notifyInferiorRunOk();
@@ -396,7 +420,9 @@ void QmlEngine::executeNext()
{
QByteArray reply;
QDataStream rs(&reply, QIODevice::WriteOnly);
- rs << QByteArray("STEPOVER");
+ QByteArray cmd = "STEPOVER";
+ rs << cmd;
+ logMessage(LogSend, cmd);
sendMessage(reply);
notifyInferiorRunRequested();
notifyInferiorRunOk();
@@ -429,15 +455,14 @@ void QmlEngine::executeJumpToLine(const QString &fileName, int lineNumber)
void QmlEngine::activateFrame(int index)
{
- Q_UNUSED(index)
-
QByteArray reply;
QDataStream rs(&reply, QIODevice::WriteOnly);
- rs << QByteArray("ACTIVATE_FRAME");
- rs << index;
+ QByteArray cmd = "ACTIVATE_FRAME";
+ rs << cmd
+ << index;
+ logMessage(LogSend, QString("%1 %2").arg(QString(cmd), QString::number(index)));
sendMessage(reply);
-
- gotoLocation(stackHandler()->frames().value(index), true);
+ gotoLocation(stackHandler()->frames().value(index));
}
void QmlEngine::selectThread(int index)
@@ -447,37 +472,62 @@ void QmlEngine::selectThread(int index)
void QmlEngine::attemptBreakpointSynchronization()
{
- Internal::BreakHandler *handler = breakHandler();
- //bool updateNeeded = false;
- QSet< QPair<QString, qint32> > breakList;
- for (int index = 0; index != handler->size(); ++index) {
- Internal::BreakpointData *data = handler->at(index);
- QString processedFilename = data->fileName;
+ BreakHandler *handler = breakHandler();
+
+ foreach (BreakpointId id, handler->unclaimedBreakpointIds()) {
+ // Take ownership of the breakpoint. Requests insertion.
+ if (acceptsBreakpoint(id))
+ handler->setEngine(id, this);
+ }
+
+ JSAgentBreakpoints breakpoints;
+ foreach (BreakpointId id, handler->engineBreakpointIds(this)) {
+ if (handler->state(id) == BreakpointRemoveRequested) {
+ handler->notifyBreakpointRemoveProceeding(id);
+ handler->notifyBreakpointRemoveOk(id);
+ } else {
+ if (handler->state(id) == BreakpointInsertRequested) {
+ handler->notifyBreakpointInsertProceeding(id);
+ }
+ QString processedFilename = handler->fileName(id);
#ifdef Q_OS_MACX
- // Qt Quick Applications by default copy the qml directory to buildDir()/X.app/Contents/Resources
- const QString applicationBundleDir
- = QFileInfo(startParameters().executable).absolutePath() + "/../..";
- processedFilename = mangleFilenamePaths(data->fileName, startParameters().projectDir, applicationBundleDir + "/Contents/Resources");
+ // Qt Quick Applications by default copy the qml directory to buildDir()/X.app/Contents/Resources
+ const QString applicationBundleDir
+ = QFileInfo(startParameters().executable).absolutePath() + "/../..";
+ processedFilename = mangleFilenamePaths(handler->fileName(id), startParameters().projectDir, applicationBundleDir + "/Contents/Resources");
#endif
- if (isShadowBuildProject())
- processedFilename = toShadowBuildFilename(processedFilename);
-
- breakList << qMakePair(processedFilename, data->lineNumber);
+ if (isShadowBuildProject())
+ processedFilename = toShadowBuildFilename(processedFilename);
+ JSAgentBreakpointData bp;
+ bp.fileName = processedFilename.toUtf8();
+ bp.lineNumber = handler->lineNumber(id);
+ bp.functionName = handler->functionName(id).toUtf8();
+ breakpoints.insert(bp);
+ if (handler->state(id) == BreakpointInsertProceeding) {
+ handler->notifyBreakpointInsertOk(id);
+ }
+ }
}
- {
QByteArray reply;
QDataStream rs(&reply, QIODevice::WriteOnly);
- rs << QByteArray("BREAKPOINTS");
- rs << breakList;
- //qDebug() << Q_FUNC_INFO << breakList;
- sendMessage(reply);
+ QByteArray cmd = "BREAKPOINTS";
+ rs << cmd
+ << breakpoints;
+
+ QStringList breakPointsStr;
+ foreach (const JSAgentBreakpointData &bp, breakpoints) {
+ breakPointsStr << QString("('%1' '%2' %3)").arg(QString(bp.functionName),
+ QString(bp.fileName), QString::number(bp.lineNumber));
}
+ logMessage(LogSend, QString("%1 [%2]").arg(QString(cmd), breakPointsStr.join(", ")));
+
+ sendMessage(reply);
}
-bool QmlEngine::acceptsBreakpoint(const Internal::BreakpointData *br)
+bool QmlEngine::acceptsBreakpoint(BreakpointId id) const
{
- return (br->fileName.endsWith(QLatin1String("qml")) || br->fileName.endsWith(QLatin1String("js")));
+ return !DebuggerEngine::isCppBreakpoint(breakHandler()->breakpointData(id));
}
void QmlEngine::loadSymbols(const QString &moduleName)
@@ -504,9 +554,11 @@ void QmlEngine::requestModuleSymbols(const QString &moduleName)
//
//////////////////////////////////////////////////////////////////////
-void QmlEngine::setToolTipExpression(const QPoint &mousePos, TextEditor::ITextEditor *editor, int cursorPos)
+void QmlEngine::setToolTipExpression(const QPoint &mousePos,
+ TextEditor::ITextEditor *editor, int cursorPos)
{
- // this is processed by QML inspector, which has deps to qml js editor. Makes life easier.
+ // This is processed by QML inspector, which has dependencies to
+ // the qml js editor. Makes life easier.
emit tooltipRequested(mousePos, editor, cursorPos);
}
@@ -516,8 +568,8 @@ void QmlEngine::setToolTipExpression(const QPoint &mousePos, TextEditor::ITextEd
//
//////////////////////////////////////////////////////////////////////
-void QmlEngine::assignValueInDebugger(const Internal::WatchData *,
- const QString &expression, const QVariant &valueV)
+void QmlEngine::assignValueInDebugger(const WatchData *,
+ const QString &expression, const QVariant &valueV)
{
QRegExp inObject("@([0-9a-fA-F]+)->(.+)");
if (inObject.exactMatch(expression)) {
@@ -527,14 +579,19 @@ void QmlEngine::assignValueInDebugger(const Internal::WatchData *,
if (ok && objectId > 0 && !property.isEmpty()) {
QByteArray reply;
QDataStream rs(&reply, QIODevice::WriteOnly);
- rs << QByteArray("SET_PROPERTY");
+ QByteArray cmd = "SET_PROPERTY";
+ rs << cmd;
rs << expression.toUtf8() << objectId << property << valueV.toString();
+ logMessage(LogSend, QString("%1 %2 %3 %4 %5").arg(
+ QString(cmd), QString::number(objectId), QString(property),
+ valueV.toString()));
sendMessage(reply);
}
}
}
-void QmlEngine::updateWatchData(const Internal::WatchData &data, const Internal::WatchUpdateFlags &)
+void QmlEngine::updateWatchData(const WatchData &data,
+ const WatchUpdateFlags &)
{
// qDebug() << "UPDATE WATCH DATA" << data.toString();
//watchHandler()->rebuildModel();
@@ -543,20 +600,26 @@ void QmlEngine::updateWatchData(const Internal::WatchData &data, const Internal:
if (!data.name.isEmpty() && data.isValueNeeded()) {
QByteArray reply;
QDataStream rs(&reply, QIODevice::WriteOnly);
- rs << QByteArray("EXEC");
+ QByteArray cmd = "EXEC";
+ rs << cmd;
rs << data.iname << data.name;
+ logMessage(LogSend, QString("%1 %2 %3").arg(QString(cmd), QString(data.iname),
+ QString(data.name)));
sendMessage(reply);
}
if (!data.name.isEmpty() && data.isChildrenNeeded()
&& watchHandler()->isExpandedIName(data.iname))
- expandObject(data.iname, data.objectId);
+ expandObject(data.iname, data.id);
{
QByteArray reply;
QDataStream rs(&reply, QIODevice::WriteOnly);
- rs << QByteArray("WATCH_EXPRESSIONS");
+ QByteArray cmd = "WATCH_EXPRESSIONS";
+ rs << cmd;
rs << watchHandler()->watchedExpressions();
+ logMessage(LogSend, QString("%1 %2").arg(
+ QString(cmd), watchHandler()->watchedExpressions().join(", ")));
sendMessage(reply);
}
@@ -564,12 +627,15 @@ void QmlEngine::updateWatchData(const Internal::WatchData &data, const Internal:
watchHandler()->insertData(data);
}
-void QmlEngine::expandObject(const QByteArray& iname, quint64 objectId)
+void QmlEngine::expandObject(const QByteArray &iname, quint64 objectId)
{
QByteArray reply;
QDataStream rs(&reply, QIODevice::WriteOnly);
- rs << QByteArray("EXPAND");
+ QByteArray cmd = "EXPAND";
+ rs << cmd;
rs << iname << objectId;
+ logMessage(LogSend, QString("%1 %2 %3").arg(QString(cmd), QString(iname),
+ QString::number(objectId)));
sendMessage(reply);
}
@@ -578,17 +644,17 @@ void QmlEngine::sendPing()
d->m_ping++;
QByteArray reply;
QDataStream rs(&reply, QIODevice::WriteOnly);
- rs << QByteArray("PING");
+ QByteArray cmd = "PING";
+ rs << cmd;
rs << d->m_ping;
+ logMessage(LogSend, QString("%1 %2").arg(QString(cmd), QString::number(d->m_ping)));
sendMessage(reply);
}
-namespace Internal {
DebuggerEngine *createQmlEngine(const DebuggerStartParameters &sp)
{
return new QmlEngine(sp);
}
-} // namespace Internal
unsigned QmlEngine::debuggerCapabilities() const
{
@@ -612,50 +678,47 @@ void QmlEngine::messageReceived(const QByteArray &message)
QByteArray command;
stream >> command;
- showMessage(QLatin1String("RECEIVED RESPONSE: ") + Internal::quoteUnprintableLatin1(message));
if (command == "STOPPED") {
- if (state() == InferiorRunOk) {
+ if (state() == InferiorRunOk)
notifyInferiorSpontaneousStop();
- }
- QList<QPair<QString, QPair<QString, qint32> > > backtrace;
- QList<Internal::WatchData> watches;
- QList<Internal::WatchData> locals;
- stream >> backtrace >> watches >> locals;
-
- Internal::StackFrames stackFrames;
- typedef QPair<QString, QPair<QString, qint32> > Iterator;
- foreach (const Iterator &it, backtrace) {
- Internal::StackFrame frame;
- frame.file = it.second.first;
- frame.line = it.second.second;
- frame.function = it.first;
- stackFrames.append(frame);
- }
+ QString logString = QString(command);
+
+ StackFrames stackFrames;
+ QList<WatchData> watches;
+ QList<WatchData> locals;
+ stream >> stackFrames >> watches >> locals;
- gotoLocation(stackFrames.value(0), true);
+ logString += " (" % QString::number(stackFrames.size()) % " stack frames)";
+ logString += " (" % QString::number(watches.size()) % " watches)";
+ logString += " (" % QString::number(locals.size()) % " locals)";
+
+ for (int i = 0; i != stackFrames.size(); ++i)
+ stackFrames[i].level = i + 1;
+
+ gotoLocation(stackFrames.value(0));
stackHandler()->setFrames(stackFrames);
watchHandler()->beginCycle();
bool needPing = false;
- foreach (Internal::WatchData data, watches) {
+ foreach (WatchData data, watches) {
data.iname = watchHandler()->watcherName(data.exp);
watchHandler()->insertData(data);
if (watchHandler()->expandedINames().contains(data.iname)) {
needPing = true;
- expandObject(data.iname, data.objectId);
+ expandObject(data.iname, data.id);
}
}
- foreach (Internal::WatchData data, locals) {
+ foreach (WatchData data, locals) {
data.iname = "local." + data.exp;
watchHandler()->insertData(data);
if (watchHandler()->expandedINames().contains(data.iname)) {
needPing = true;
- expandObject(data.iname, data.objectId);
+ expandObject(data.iname, data.id);
}
}
@@ -666,10 +729,16 @@ void QmlEngine::messageReceived(const QByteArray &message)
bool becauseOfException;
stream >> becauseOfException;
+
+ logString += becauseOfException ? " exception" : " no_exception";
+
if (becauseOfException) {
QString error;
stream >> error;
+ logString += " " % error;
+ logMessage(LogReceive, logString);
+
QString msg =
tr("<p>An Uncaught Exception occured in <i>%1</i>:</p><p>%2</p>")
.arg(stackFrames.value(0).file, Qt::escape(error));
@@ -679,71 +748,84 @@ void QmlEngine::messageReceived(const QByteArray &message)
// Make breakpoint non-pending
//
QString file;
+ QString function;
int line = -1;
if (!stackFrames.isEmpty()) {
file = stackFrames.at(0).file;
line = stackFrames.at(0).line;
+ function = stackFrames.at(0).function;
if (isShadowBuildProject()) {
file = fromShadowBuildFilename(file);
}
}
- Internal::BreakHandler *handler = breakHandler();
- for (int index = 0; index != handler->size(); ++index) {
- Internal::BreakpointData *data = handler->at(index);
- QString processedFilename = data->fileName;
-
- if (processedFilename == file
- && data->lineNumber == line) {
- data->pending = false;
- data->bpFileName = file;
- data->bpLineNumber = line;
- data->updateMarker();
+ BreakHandler *handler = breakHandler();
+ foreach (BreakpointId id, handler->engineBreakpointIds(this)) {
+ QString processedFilename = handler->fileName(id);
+ if (processedFilename == file && handler->lineNumber(id) == line) {
+ QTC_ASSERT(handler->state(id) == BreakpointInserted,/**/);
+ BreakpointResponse br = handler->response(id);
+ br.fileName = file;
+ br.lineNumber = line;
+ br.functionName = function;
+ handler->setResponse(id, br);
}
}
+
+ logMessage(LogReceive, logString);
}
} else if (command == "RESULT") {
- Internal::WatchData data;
+ WatchData data;
QByteArray iname;
stream >> iname >> data;
+
+ logMessage(LogReceive, QString("%1 %2 %3").arg(QString(command),
+ QString(iname), QString(data.value)));
data.iname = iname;
if (iname.startsWith("watch.")) {
watchHandler()->insertData(data);
} else if(iname == "console") {
- plugin()->showMessage(data.value, ScriptConsoleOutput);
+ showMessage(data.value, ScriptConsoleOutput);
} else {
qWarning() << "QmlEngine: Unexcpected result: " << iname << data.value;
}
} else if (command == "EXPANDED") {
- QList<Internal::WatchData> result;
+ QList<WatchData> result;
QByteArray iname;
stream >> iname >> result;
+
+ logMessage(LogReceive, QString("%1 %2 (%3 x watchdata)").arg(
+ QString(command), QString(iname), QString::number(result.size())));
bool needPing = false;
- foreach (Internal::WatchData data, result) {
+ foreach (WatchData data, result) {
data.iname = iname + '.' + data.exp;
watchHandler()->insertData(data);
if (watchHandler()->expandedINames().contains(data.iname)) {
needPing = true;
- expandObject(data.iname, data.objectId);
+ expandObject(data.iname, data.id);
}
}
if (needPing)
sendPing();
} else if (command == "LOCALS") {
- QList<Internal::WatchData> locals;
+ QList<WatchData> locals;
int frameId;
stream >> frameId >> locals;
+
+ logMessage(LogReceive, QString("%1 %2 (%3 x locals)").arg(
+ QString(command), QString::number(frameId),
+ QString::number(locals.size())));
watchHandler()->beginCycle();
bool needPing = false;
- foreach (Internal::WatchData data, locals) {
+ foreach (WatchData data, locals) {
data.iname = "local." + data.exp;
watchHandler()->insertData(data);
if (watchHandler()->expandedINames().contains(data.iname)) {
needPing = true;
- expandObject(data.iname, data.objectId);
+ expandObject(data.iname, data.id);
}
}
if (needPing)
@@ -754,17 +836,20 @@ void QmlEngine::messageReceived(const QByteArray &message)
} else if (command == "PONG") {
int ping;
stream >> ping;
+
+ logMessage(LogReceive, QString("%1 %2").arg(QString(command), QString::number(ping)));
+
if (ping == d->m_ping)
watchHandler()->endCycle();
} else {
qDebug() << Q_FUNC_INFO << "Unknown command: " << command;
+ logMessage(LogReceive, QString("%1 UNKNOWN COMMAND!!").arg(QString(command)));
}
-
}
void QmlEngine::disconnected()
{
- plugin()->showMessage(tr("QML Debugger disconnected."), StatusBar);
+ showMessage(tr("QML Debugger disconnected."), StatusBar);
notifyInferiorExited();
}
@@ -772,33 +857,23 @@ void QmlEngine::executeDebuggerCommand(const QString& command)
{
QByteArray reply;
QDataStream rs(&reply, QIODevice::WriteOnly);
- rs << QByteArray("EXEC");
- rs << QByteArray("console") << command;
+ QByteArray cmd = "EXEC";
+ QByteArray console = "console";
+ rs << cmd << console << command;
+ logMessage(LogSend, QString("%1 %2 %3").arg(QString(cmd), QString(console),
+ QString(command)));
sendMessage(reply);
}
bool QmlEngine::isShadowBuildProject() const
{
- if (!startParameters().projectBuildDir.isEmpty()
- && (startParameters().projectDir != startParameters().projectBuildDir))
- {
- return true;
- }
- return false;
+ return !startParameters().projectBuildDir.isEmpty()
+ && startParameters().projectDir != startParameters().projectBuildDir;
}
QString QmlEngine::qmlImportPath() const
{
- QString result;
- const QString qmlImportPathPrefix("QML_IMPORT_PATH=");
- QStringList env = startParameters().environment;
- foreach(const QString &envStr, env) {
- if (envStr.startsWith(qmlImportPathPrefix)) {
- result = envStr.mid(qmlImportPathPrefix.length());
- break;
- }
- }
- return result;
+ return startParameters().environment.value("QML_IMPORT_PATH");
}
QString QmlEngine::toShadowBuildFilename(const QString &filename) const
@@ -814,7 +889,8 @@ QString QmlEngine::toShadowBuildFilename(const QString &filename) const
return newFilename;
}
-QString QmlEngine::mangleFilenamePaths(const QString &filename, const QString &oldBasePath, const QString &newBasePath) const
+QString QmlEngine::mangleFilenamePaths(const QString &filename,
+ const QString &oldBasePath, const QString &newBasePath) const
{
QDir oldBaseDir(oldBasePath);
QDir newBaseDir(newBasePath);
@@ -852,5 +928,18 @@ QString QmlEngine::fromShadowBuildFilename(const QString &filename) const
return newFilename;
}
+void QmlEngine::logMessage(LogDirection direction, const QString &message)
+{
+ QString msg = "JSDebugger";
+ if (direction == LogSend) {
+ msg += " sending ";
+ } else {
+ msg += " receiving ";
+ }
+ msg += message;
+ showMessage(msg, LogDebug);
+}
+
+} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/qml/qmlengine.h b/src/plugins/debugger/qml/qmlengine.h
index 3f12f44e1d..4a37148509 100644
--- a/src/plugins/debugger/qml/qmlengine.h
+++ b/src/plugins/debugger/qml/qmlengine.h
@@ -40,27 +40,23 @@
#include <QtNetwork/QAbstractSocket>
namespace Debugger {
-class QmlAdapter;
+namespace Internal {
-struct QmlEnginePrivate;
+class QmlEnginePrivate;
-class DEBUGGER_EXPORT QmlEngine : public DebuggerEngine
+class QmlEngine : public DebuggerEngine
{
Q_OBJECT
public:
explicit QmlEngine(const DebuggerStartParameters &startParameters);
- virtual ~QmlEngine();
+ ~QmlEngine();
- void handleRemoteSetupDone();
+ void handleRemoteSetupDone(int port);
void handleRemoteSetupFailed(const QString &message);
- void setAttachToRunningExternalApp(bool value);
- void shutdownInferiorAsSlave();
- void shutdownEngineAsSlave();
+ void gotoLocation(const Location &location);
void pauseConnection();
- void gotoLocation(const QString &fileName, int lineNumber, bool setMarker);
- void gotoLocation(const Internal::StackFrame &frame, bool setMarker);
public slots:
void messageReceived(const QByteArray &message);
@@ -70,7 +66,7 @@ signals:
void remoteStartupRequested();
private:
- // DebuggerEngine implementation
+ // DebuggerEngine implementation.
bool isSynchronous() const { return false; }
void executeStep();
void executeStepOut();
@@ -84,7 +80,8 @@ private:
void shutdownInferior();
void shutdownEngine();
- void setToolTipExpression(const QPoint &mousePos, TextEditor::ITextEditor *editor, int cursorPos);
+ void setToolTipExpression(const QPoint &mousePos,
+ TextEditor::ITextEditor *editor, int cursorPos);
void continueInferior();
void interruptInferior();
@@ -97,9 +94,10 @@ private:
void selectThread(int index);
void attemptBreakpointSynchronization();
- bool acceptsBreakpoint(const Internal::BreakpointData *br);
+ bool acceptsBreakpoint(BreakpointId id) const;
- void assignValueInDebugger(const Internal::WatchData *w, const QString &expr, const QVariant &value);
+ void assignValueInDebugger(const WatchData *data,
+ const QString &expr, const QVariant &value);
void loadSymbols(const QString &moduleName);
void loadAllSymbols();
void requestModuleSymbols(const QString &moduleName);
@@ -109,37 +107,53 @@ private:
void reloadFullStack() {}
bool supportsThreads() const { return false; }
- void updateWatchData(const Internal::WatchData &data, const Internal::WatchUpdateFlags &flags);
- void executeDebuggerCommand(const QString& command);
+ void updateWatchData(const WatchData &data,
+ const WatchUpdateFlags &flags);
+ void executeDebuggerCommand(const QString &command);
unsigned int debuggerCapabilities() const;
signals:
void sendMessage(const QByteArray &msg);
- void tooltipRequested(const QPoint &mousePos, TextEditor::ITextEditor *editor, int cursorPos);
+ void tooltipRequested(const QPoint &mousePos,
+ TextEditor::ITextEditor *editor, int cursorPos);
private slots:
void connectionEstablished();
void connectionStartupFailed();
void connectionError(QAbstractSocket::SocketError error);
void serviceConnectionError(const QString &service);
+ void appendMessage(const QString &msg, bool);
+ void appendOutput(const QString &msg, bool);
private:
void expandObject(const QByteArray &iname, quint64 objectId);
void sendPing();
+ void closeConnection();
+ void startApplicationLauncher();
+ void stopApplicationLauncher();
+
bool isShadowBuildProject() const;
QString fromShadowBuildFilename(const QString &filename) const;
- QString mangleFilenamePaths(const QString &filename, const QString &oldBasePath, const QString &newBasePath) const;
+ QString mangleFilenamePaths(const QString &filename,
+ const QString &oldBasePath, const QString &newBasePath) const;
QString toShadowBuildFilename(const QString &filename) const;
QString qmlImportPath() const;
+ enum LogDirection {
+ LogSend,
+ LogReceive
+ };
+ void logMessage(LogDirection direction, const QString &str);
+
private:
friend class QmlCppEngine;
QScopedPointer<QmlEnginePrivate> d;
};
+} // namespace Internal
} // namespace Debugger
#endif // DEBUGGER_QMLENGINE_H
diff --git a/src/plugins/debugger/qml/scriptconsole.cpp b/src/plugins/debugger/qml/scriptconsole.cpp
index 5a8ab9dfe2..7cf254ebcd 100644
--- a/src/plugins/debugger/qml/scriptconsole.cpp
+++ b/src/plugins/debugger/qml/scriptconsole.cpp
@@ -42,7 +42,6 @@
#include <texteditor/fontsettings.h>
#include <texteditor/texteditorconstants.h>
#include <texteditor/texteditorsettings.h>
-#include <debuggeruiswitcher.h>
namespace Debugger {
namespace Internal {
diff --git a/src/plugins/debugger/registerhandler.cpp b/src/plugins/debugger/registerhandler.cpp
index bc3fbf9826..bced417407 100644
--- a/src/plugins/debugger/registerhandler.cpp
+++ b/src/plugins/debugger/registerhandler.cpp
@@ -32,24 +32,8 @@
**************************************************************************/
#include "registerhandler.h"
-
-#include "debuggeractions.h"
-#include "debuggeragents.h"
-#include "debuggerconstants.h"
-#include "debuggerengine.h"
#include "watchdelegatewidgets.h"
-#include <utils/qtcassert.h>
-
-#include <QtCore/QAbstractTableModel>
-#include <QtCore/QDebug>
-
-#include <QtGui/QColor>
-
-using namespace Debugger;
-using namespace Debugger::Internal;
-using namespace Debugger::Constants;
-
//////////////////////////////////////////////////////////////////
//
@@ -57,8 +41,11 @@ using namespace Debugger::Constants;
//
//////////////////////////////////////////////////////////////////
-RegisterHandler::RegisterHandler(DebuggerEngine *engine)
- : m_engine(engine), m_base(15)
+namespace Debugger {
+namespace Internal {
+
+RegisterHandler::RegisterHandler()
+ : m_base(-1)
{
setNumberBase(16);
}
@@ -74,53 +61,36 @@ int RegisterHandler::columnCount(const QModelIndex &parent) const
}
// Editor value: Preferably number, else string.
-QVariant RegisterHandler::editValue(const Register &reg)
+QVariant Register::editValue() const
{
bool ok = true;
// Try to convert to number?
- const qulonglong value = reg.value.toULongLong(&ok, 0); // Autodetect format
+ const qulonglong v = value.toULongLong(&ok, 0); // Autodetect format
if (ok)
- return QVariant(value);
- return QVariant(reg.value);
+ return QVariant(v);
+ return QVariant(value);
}
// Editor value: Preferably padded number, else padded string.
-inline QString RegisterHandler::displayValue(const Register &reg) const
+QString Register::displayValue(int base, int strlen) const
{
- const QVariant editV = RegisterHandler::editValue(reg);
+ const QVariant editV = editValue();
if (editV.type() == QVariant::ULongLong)
- return QString::fromAscii("%1").arg(editV.toULongLong(), m_strlen, m_base);
+ return QString::fromAscii("%1").arg(editV.toULongLong(), strlen, base);
const QString stringValue = editV.toString();
- if (stringValue.size() < m_strlen)
- return QString(m_strlen - stringValue.size(), QLatin1Char(' ')) + reg.value;
+ if (stringValue.size() < strlen)
+ return QString(strlen - stringValue.size(), QLatin1Char(' ')) + value;
return stringValue;
}
QVariant RegisterHandler::data(const QModelIndex &index, int role) const
{
- switch (role) {
- case EngineStateRole:
- return m_engine->state();
-
- case EngineCapabilitiesRole:
- return m_engine->debuggerCapabilities();
-
- case EngineActionsEnabledRole:
- return m_engine->debuggerActionsEnabled();
- }
-
if (!index.isValid() || index.row() >= m_registers.size())
return QVariant();
const Register &reg = m_registers.at(index.row());
switch (role) {
- case RegisterAddressRole: {
- // Return some address associated with the register. Autodetect format
- const QVariant editV = RegisterHandler::editValue(reg);
- return editV.type() == QVariant::ULongLong ? editV : QVariant();
- }
-
case Qt::DisplayRole:
switch (index.column()) {
case 0: {
@@ -128,18 +98,12 @@ QVariant RegisterHandler::data(const QModelIndex &index, int role) const
return QVariant(padding + reg.name + padding);
}
case 1: // Display: Pad value for alignment
- return displayValue(reg);
+ return reg.displayValue(m_base, m_strlen);
} // switch column
case Qt::EditRole: // Edit: Unpadded for editing
- return RegisterHandler::editValue(reg);
+ return reg.editValue();
case Qt::TextAlignmentRole:
return index.column() == 1 ? QVariant(Qt::AlignRight) : QVariant();
- case RegisterChangedRole:
- return QVariant(reg.changed);
- case RegisterBigNumberRole: // Editor: Can it be handled as quint64?
- return editValue(reg).type() != QVariant::ULongLong;
- case RegisterNumberBaseRole: // Big integers are assumed to be hexadecimal
- return editValue(reg).type() == QVariant::ULongLong ? m_base : 16;
default:
break;
}
@@ -165,31 +129,12 @@ Qt::ItemFlags RegisterHandler::flags(const QModelIndex &idx) const
const Qt::ItemFlags notEditable = Qt::ItemIsSelectable|Qt::ItemIsEnabled;
// Can edit registers if they are hex numbers and not arrays.
- if (idx.column() == 1 && IntegerWatchLineEdit::isUnsignedHexNumber(m_registers.at(idx.row()).value))
+ if (idx.column() == 1
+ && IntegerWatchLineEdit::isUnsignedHexNumber(m_registers.at(idx.row()).value))
return notEditable | Qt::ItemIsEditable;
return notEditable;
}
-bool RegisterHandler::setData(const QModelIndex &index, const QVariant &value, int role)
-{
- switch (role) {
- case RequestSetRegisterRole:
- m_engine->setRegisterValue(index.row(), value.toString());
- return true;
-
- case RequestReloadRegistersRole:
- m_engine->reloadRegisters();
- return true;
-
- case RequestShowMemoryRole:
- (void) new MemoryViewAgent(m_engine, value.toString());
- return true;
-
- default:
- return QAbstractTableModel::setData(index, value, role);
- }
-}
-
void RegisterHandler::removeAll()
{
m_registers.clear();
@@ -236,3 +181,6 @@ void RegisterHandler::setNumberBase(int base)
emit reset();
}
}
+
+} // namespace Internal
+} // namespace Debugger
diff --git a/src/plugins/debugger/registerhandler.h b/src/plugins/debugger/registerhandler.h
index a3aef16adb..5bce257368 100644
--- a/src/plugins/debugger/registerhandler.h
+++ b/src/plugins/debugger/registerhandler.h
@@ -38,14 +38,16 @@
#include <QtCore/QVector>
namespace Debugger {
-class DebuggerEngine;
-
namespace Internal {
+
class Register
{
public:
Register() : changed(true) {}
- Register(QByteArray const &name_) : name(name_), changed(true) {}
+ Register(const QByteArray &name_) : name(name_), changed(true) {}
+
+ QVariant editValue() const;
+ QString displayValue(int base, int strlen) const;
public:
QByteArray name;
@@ -64,7 +66,7 @@ class RegisterHandler : public QAbstractTableModel
Q_OBJECT
public:
- explicit RegisterHandler(DebuggerEngine *engine);
+ RegisterHandler();
QAbstractItemModel *model() { return this; }
@@ -72,22 +74,20 @@ public:
void setRegisters(const Registers &registers);
void setAndMarkRegisters(const Registers &registers);
Registers registers() const;
+ Register registerAt(int i) const { return m_registers.at(i); }
void removeAll();
Q_SLOT void setNumberBase(int base);
+ int numberBase() const { return m_base; }
private:
void calculateWidth();
- inline QString displayValue(const Register &reg) const;
- static QVariant editValue(const Register &reg);
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
- bool setData(const QModelIndex &index, const QVariant &, int role);
QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const;
Qt::ItemFlags flags(const QModelIndex &idx) const;
- DebuggerEngine *m_engine; // Not owned.
Registers m_registers;
int m_base;
int m_strlen; // approximate width of a value in chars.
diff --git a/src/plugins/debugger/registerwindow.cpp b/src/plugins/debugger/registerwindow.cpp
index 411dcb1745..50e135ce72 100644
--- a/src/plugins/debugger/registerwindow.cpp
+++ b/src/plugins/debugger/registerwindow.cpp
@@ -35,29 +35,38 @@
#include "debuggeractions.h"
#include "debuggerconstants.h"
-
+#include "debuggercore.h"
+#include "debuggerengine.h"
+#include "registerhandler.h"
#include "watchdelegatewidgets.h"
#include <utils/qtcassert.h>
#include <utils/savedaction.h>
#include <QtCore/QDebug>
-#include <QtCore/QDir>
-#include <QtCore/QFileInfo>
-#include <QtCore/QFileInfoList>
-#include <QtGui/QAction>
#include <QtGui/QHeaderView>
#include <QtGui/QItemDelegate>
-#include <QtGui/QLineEdit>
#include <QtGui/QMenu>
#include <QtGui/QPainter>
#include <QtGui/QResizeEvent>
-#include <QtGui/QToolButton>
+
namespace Debugger {
namespace Internal {
+static DebuggerEngine *currentEngine()
+{
+ return debuggerCore()->currentEngine();
+}
+
+static RegisterHandler *currentHandler()
+{
+ DebuggerEngine *engine = currentEngine();
+ QTC_ASSERT(engine, return 0);
+ return engine->registerHandler();
+}
+
///////////////////////////////////////////////////////////////////////
//
// RegisterDelegate
@@ -67,18 +76,21 @@ namespace Internal {
class RegisterDelegate : public QItemDelegate
{
public:
- RegisterDelegate(RegisterWindow *owner, QObject *parent)
- : QItemDelegate(parent), m_owner(owner)
+ RegisterDelegate(QObject *parent)
+ : QItemDelegate(parent)
{}
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &,
const QModelIndex &index) const
{
+ Register reg = currentHandler()->registerAt(index.row());
IntegerWatchLineEdit *lineEdit = new IntegerWatchLineEdit(parent);
- lineEdit->setBase(index.data(RegisterNumberBaseRole).toInt());
- lineEdit->setBigInt(index.data(RegisterBigNumberRole).toBool());
+ const int base = currentHandler()->numberBase();
+ const bool big = reg.value.size() > 16;
+ // Big integers are assumed to be hexadecimal.
+ lineEdit->setBigInt(big);
+ lineEdit->setBase(big ? 16 : base);
lineEdit->setSigned(false);
-
lineEdit->setAlignment(Qt::AlignRight);
return lineEdit;
}
@@ -90,13 +102,14 @@ public:
lineEdit->setModelData(index.data(Qt::EditRole));
}
- void setModelData(QWidget *editor, QAbstractItemModel *, const QModelIndex &index) const
+ void setModelData(QWidget *editor, QAbstractItemModel *,
+ const QModelIndex &index) const
{
if (index.column() != 1)
return;
IntegerWatchLineEdit *lineEdit = qobject_cast<IntegerWatchLineEdit*>(editor);
QTC_ASSERT(lineEdit, return);
- m_owner->model()->setData(index, lineEdit->modelData(), RequestSetRegisterRole);
+ currentEngine()->setRegisterValue(index.row(), lineEdit->text());
}
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
@@ -109,7 +122,7 @@ public:
const QModelIndex &index) const
{
if (index.column() == 1) {
- bool paintRed = index.data(RegisterChangedRole).toBool();
+ bool paintRed = currentHandler()->registerAt(index.row()).changed;
QPen oldPen = painter->pen();
if (paintRed)
painter->setPen(QColor(200, 0, 0));
@@ -135,9 +148,6 @@ public:
QItemDelegate::paint(painter, option, index);
}
}
-
-private:
- RegisterWindow *m_owner;
};
@@ -150,16 +160,16 @@ private:
RegisterWindow::RegisterWindow(QWidget *parent)
: QTreeView(parent), m_alwaysResizeColumnsToContents(true)
{
- QAction *act = theDebuggerAction(UseAlternatingRowColors);
+ QAction *act = debuggerCore()->action(UseAlternatingRowColors);
setFrameStyle(QFrame::NoFrame);
setWindowTitle(tr("Registers"));
setAttribute(Qt::WA_MacShowFocusRect, false);
setAlternatingRowColors(act->isChecked());
setRootIsDecorated(false);
- setItemDelegate(new RegisterDelegate(this, this));
+ setItemDelegate(new RegisterDelegate(this));
connect(act, SIGNAL(toggled(bool)),
- this, SLOT(setAlternatingRowColorsHelper(bool)));
+ SLOT(setAlternatingRowColorsHelper(bool)));
}
void RegisterWindow::resizeEvent(QResizeEvent *ev)
@@ -171,9 +181,12 @@ void RegisterWindow::contextMenuEvent(QContextMenuEvent *ev)
{
QMenu menu;
- const unsigned engineCapabilities = modelData(EngineCapabilitiesRole).toUInt();
- const bool actionsEnabled = modelData(EngineActionsEnabledRole).toInt();
- const int state = modelData(EngineStateRole).toInt();
+ DebuggerEngine *engine = currentEngine();
+ QTC_ASSERT(engine, return);
+ RegisterHandler *handler = currentHandler();
+ const unsigned engineCapabilities = engine->debuggerCapabilities();
+ const bool actionsEnabled = engine->debuggerActionsEnabled();
+ const int state = engine->state();
QAction *actReload = menu.addAction(tr("Reload Register Listing"));
actReload->setEnabled((engineCapabilities & RegisterCapability)
@@ -182,7 +195,7 @@ void RegisterWindow::contextMenuEvent(QContextMenuEvent *ev)
menu.addSeparator();
QModelIndex idx = indexAt(ev->pos());
- QString address = modelData(RegisterAddressRole, idx).toString();
+ QString address = handler->registers().at(idx.row()).value;
QAction *actShowMemory = menu.addAction(QString());
if (address.isEmpty()) {
actShowMemory->setText(tr("Open Memory Editor"));
@@ -194,7 +207,7 @@ void RegisterWindow::contextMenuEvent(QContextMenuEvent *ev)
}
menu.addSeparator();
- int base = modelData(RegisterNumberBaseRole).toInt();
+ const int base = handler->numberBase();
QAction *act16 = menu.addAction(tr("Hexadecimal"));
act16->setCheckable(true);
act16->setChecked(base == 16);
@@ -216,7 +229,7 @@ void RegisterWindow::contextMenuEvent(QContextMenuEvent *ev)
actAlwaysAdjust->setChecked(m_alwaysResizeColumnsToContents);
menu.addSeparator();
- menu.addAction(theDebuggerAction(SettingsDialog));
+ menu.addAction(debuggerCore()->action(SettingsDialog));
QAction *act = menu.exec(ev->globalPos());
@@ -225,13 +238,17 @@ void RegisterWindow::contextMenuEvent(QContextMenuEvent *ev)
else if (act == actAlwaysAdjust)
setAlwaysResizeColumnsToContents(!m_alwaysResizeColumnsToContents);
else if (act == actReload)
- setModelData(RequestReloadRegistersRole);
+ engine->reloadRegisters();
else if (act == actShowMemory)
- setModelData(RequestShowMemoryRole, address);
- else if (act) {
- base = (act == act10 ? 10 : act == act8 ? 8 : act == act2 ? 2 : 16);
- QMetaObject::invokeMethod(model(), "setNumberBase", Q_ARG(int, base));
- }
+ engine->openMemoryView(address.toULongLong(0, 0));
+ else if (act == act16)
+ handler->setNumberBase(16);
+ else if (act == act10)
+ handler->setNumberBase(10);
+ else if (act == act8)
+ handler->setNumberBase(8);
+ else if (act == act2)
+ handler->setNumberBase(2);
}
void RegisterWindow::resizeColumnsToContents()
@@ -258,20 +275,7 @@ void RegisterWindow::setModel(QAbstractItemModel *model)
void RegisterWindow::reloadRegisters()
{
// FIXME: Only trigger when becoming visible?
- setModelData(RequestReloadRegistersRole);
-}
-
-void RegisterWindow::setModelData
- (int role, const QVariant &value, const QModelIndex &index)
-{
- QTC_ASSERT(model(), return);
- model()->setData(index, value, role);
-}
-
-QVariant RegisterWindow::modelData(int role, const QModelIndex &index)
-{
- QTC_ASSERT(model(), return QVariant());
- return model()->data(index, role);
+ currentEngine()->reloadRegisters();
}
} // namespace Internal
diff --git a/src/plugins/debugger/registerwindow.h b/src/plugins/debugger/registerwindow.h
index e4c5da8733..0fbc148bd9 100644
--- a/src/plugins/debugger/registerwindow.h
+++ b/src/plugins/debugger/registerwindow.h
@@ -57,10 +57,6 @@ private:
void resizeEvent(QResizeEvent *ev);
void contextMenuEvent(QContextMenuEvent *ev);
- void setModelData(int role, const QVariant &value = QVariant(),
- const QModelIndex &index = QModelIndex());
- QVariant modelData(int role, const QModelIndex &index = QModelIndex());
-
bool m_alwaysResizeColumnsToContents;
};
@@ -68,4 +64,3 @@ private:
} // namespace Debugger
#endif // DEBUGGER_REGISTERWINDOW_H
-
diff --git a/src/plugins/debugger/script/scriptengine.cpp b/src/plugins/debugger/script/scriptengine.cpp
index 79813744b9..f173780e89 100644
--- a/src/plugins/debugger/script/scriptengine.cpp
+++ b/src/plugins/debugger/script/scriptengine.cpp
@@ -37,6 +37,7 @@
#include "breakhandler.h"
#include "debuggerconstants.h"
+#include "debuggercore.h"
#include "debuggerdialogs.h"
#include "debuggerstringutils.h"
#include "moduleshandler.h"
@@ -450,8 +451,16 @@ void ScriptEngine::selectThread(int index)
Q_UNUSED(index)
}
+bool ScriptEngine::acceptsBreakpoint(BreakpointId id) const
+{
+ const QString fileName = breakHandler()->fileName(id);
+ return fileName.endsWith(QLatin1String(".js"));
+}
+
void ScriptEngine::attemptBreakpointSynchronization()
{
+ QTC_ASSERT(false, /* FIXME */);
+/*
BreakHandler *handler = breakHandler();
bool updateNeeded = false;
for (int index = 0; index != handler->size(); ++index) {
@@ -472,6 +481,7 @@ void ScriptEngine::attemptBreakpointSynchronization()
}
if (updateNeeded)
handler->updateMarkers();
+*/
}
void ScriptEngine::loadSymbols(const QString &moduleName)
@@ -593,31 +603,6 @@ void ScriptEngine::assignValueInDebugger(const Internal::WatchData *,
updateLocals();
}
-static BreakpointData *findBreakPointByFunction(BreakHandler *handler,
- const QString &functionName)
-{
- const int count = handler->size();
- for (int b = 0; b < count; b++) {
- BreakpointData *data = handler->at(b);
- if (data->funcName == functionName)
- return data;
- }
- return 0;
-}
-
-static BreakpointData *findBreakPointByFileName(BreakHandler *handler,
- int lineNumber,
- const QString &fileName)
-{
- const int count = handler->size();
- for (int b = 0; b < count; b++) {
- BreakpointData *data = handler->at(b);
- if (lineNumber == data->lineNumber && fileName == data->fileName)
- return data;
- }
- return 0;
-}
-
bool ScriptEngine::checkForBreakCondition(bool byFunction)
{
// FIXME: Should that ever happen after setAgent(0) in shutdownInferior()?
@@ -633,42 +618,35 @@ bool ScriptEngine::checkForBreakCondition(bool byFunction)
const QString fileName = info.fileName();
const int lineNumber = byFunction
? info.functionStartLineNumber() : info.lineNumber();
- SDEBUG(Q_FUNC_INFO << byFunction << functionName
- << lineNumber << fileName);
+ SDEBUG(Q_FUNC_INFO << byFunction << functionName << lineNumber << fileName);
if (m_stopOnNextLine) {
// Interrupt inferior
m_stopOnNextLine = false;
} else {
if (byFunction && functionName.isEmpty())
return false;
- BreakpointData *data = byFunction ?
- findBreakPointByFunction(breakHandler(), functionName) :
- findBreakPointByFileName(breakHandler(), lineNumber, fileName);
- if (!data)
- return false;
+ BreakHandler *handler = breakHandler();
+ BreakpointId id = byFunction ?
+ handler->findBreakpointByFunction(functionName) :
+ handler->findBreakpointByFileAndLine(fileName, lineNumber, false);
// Skip disabled breakpoint.
- if (!data->enabled)
+ if (!handler->isEnabled(id))
return false;
+ BreakpointResponse br;
// We just run into a breakpoint.
//SDEBUG("RESOLVING BREAKPOINT AT " << fileName << lineNumber);
- data->bpLineNumber = lineNumber;
- data->bpFileName = fileName;
- data->bpFuncName = functionName;
- data->setMarkerLineNumber(lineNumber);
- data->setMarkerFileName(fileName);
- data->pending = false;
- data->updateMarker();
+ br.lineNumber = lineNumber;
+ br.fileName = fileName;
+ br.functionName = functionName;
+ handler->notifyBreakpointInsertOk(id);
+ handler->setResponse(id, br);
}
notifyInferiorSpontaneousStop();
SDEBUG("Stopped at " << lineNumber << fileName);
showStatusMessage(tr("Stopped at %1:%2.").arg(fileName).arg(lineNumber), 5000);
-
- StackFrame frame;
- frame.file = fileName;
- frame.line = lineNumber;
- gotoLocation(frame, true);
+ gotoLocation(Location(fileName, lineNumber));
updateLocals();
return true;
}
@@ -706,9 +684,11 @@ void ScriptEngine::updateLocals()
m_scriptEngine->setAgent(0);
WatchData data;
+ data.id = m_watchIdCounter++;
+ m_watchIdToScriptValue.insert(data.id, context->activationObject());
data.iname = "local";
data.name = _(data.iname);
- data.scriptValue = context->activationObject();
+
watchHandler()->beginCycle();
updateSubItem(data);
watchHandler()->endCycle();
@@ -748,8 +728,8 @@ void ScriptEngine::updateSubItem(const WatchData &data0)
//SDEBUG("\nUPDATE SUBITEM: " << data.toString() << data.scriptValue.toString());
QTC_ASSERT(data.isValid(), return);
+ const QScriptValue &ob = m_watchIdToScriptValue.value(data.id);
if (data.isTypeNeeded() || data.isValueNeeded()) {
- const QScriptValue &ob = data.scriptValue;
if (ob.isArray()) {
data.setType("Array", false);
data.setValue(QString(QLatin1Char(' ')));
@@ -806,14 +786,15 @@ void ScriptEngine::updateSubItem(const WatchData &data0)
}
if (data.isChildrenNeeded()) {
- QScriptValueIterator it(data.scriptValue);
+ QScriptValueIterator it(ob);
while (it.hasNext()) {
it.next();
WatchData data1;
data1.iname = data.iname + '.' + it.name().toLatin1();
data1.exp = it.name().toLatin1();
data1.name = it.name();
- data1.scriptValue = it.value();
+ data.id = m_watchIdCounter++;
+ m_watchIdToScriptValue.insert(data.id, it.value());
if (watchHandler()->isExpandedIName(data1.iname)) {
data1.setChildrenNeeded();
} else {
@@ -826,7 +807,7 @@ void ScriptEngine::updateSubItem(const WatchData &data0)
}
if (data.isHasChildrenNeeded()) {
- QScriptValueIterator it(data.scriptValue);
+ QScriptValueIterator it(ob);
data.setHasChildren(it.hasNext());
}
diff --git a/src/plugins/debugger/script/scriptengine.h b/src/plugins/debugger/script/scriptengine.h
index 35c4d9d00d..0345e21f86 100644
--- a/src/plugins/debugger/script/scriptengine.h
+++ b/src/plugins/debugger/script/scriptengine.h
@@ -38,6 +38,7 @@
#include <QtCore/QSharedPointer>
#include <QtCore/QScopedPointer>
+#include <QtCore/QHash>
QT_BEGIN_NAMESPACE
class QScriptEngine;
@@ -90,9 +91,11 @@ private:
void activateFrame(int index);
void selectThread(int index);
+ bool acceptsBreakpoint(BreakpointId id) const;
void attemptBreakpointSynchronization();
- void assignValueInDebugger(const Internal::WatchData *w, const QString &expr, const QVariant &value);
+ void assignValueInDebugger(const WatchData *w,
+ const QString &expr, const QVariant &value);
void executeDebuggerCommand(const QString &command);
void loadSymbols(const QString &moduleName);
@@ -118,6 +121,8 @@ private:
QString m_scriptContents;
QString m_scriptFileName;
QScopedPointer<ScriptAgent> m_scriptAgent;
+ QHash<quint64,QScriptValue> m_watchIdToScriptValue;
+ quint64 m_watchIdCounter;
bool m_stopped;
bool m_stopOnNextLine;
diff --git a/src/plugins/debugger/sessionengine.cpp b/src/plugins/debugger/sessionengine.cpp
deleted file mode 100644
index f428b85a28..0000000000
--- a/src/plugins/debugger/sessionengine.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#include "sessionengine.h"
-#include "breakhandler.h"
-#include "watchhandler.h"
-#include "debuggerconstants.h"
-
-#include <utils/qtcassert.h>
-
-#include <QtCore/QDebug>
-
-namespace Debugger {
-namespace Internal {
-
-// This class contains data serving as a template for debugger engines
-// started during a session.
-
-SessionEngine::SessionEngine()
- : DebuggerEngine(DebuggerStartParameters())
-{
- setObjectName(QLatin1String("SessionEngine"));
-}
-
-void SessionEngine::executeDebuggerCommand(const QString &command)
-{
- QTC_ASSERT(false, qDebug() << command)
-}
-
-void SessionEngine::loadSessionData()
-{
- breakHandler()->loadSessionData();
- watchHandler()->loadSessionData();
-}
-
-void SessionEngine::saveSessionData()
-{
- watchHandler()->saveSessionData();
- breakHandler()->saveSessionData();
-}
-
-unsigned SessionEngine::debuggerCapabilities() const
-{
- return DebuggerEngine::debuggerCapabilities()
- | AddWatcherCapability
- | BreakOnThrowAndCatchCapability
- | WatchpointCapability;
-}
-
-} // namespace Internal
-} // namespace Debugger
-
diff --git a/src/plugins/debugger/sessionengine.h b/src/plugins/debugger/sessionengine.h
deleted file mode 100644
index 89c9f47b53..0000000000
--- a/src/plugins/debugger/sessionengine.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#ifndef DEBUGGER_SESSIONENGINE_H
-#define DEBUGGER_SESSIONENGINE_H
-
-#include "debuggerengine.h"
-
-namespace Debugger {
-namespace Internal {
-
-// This class contains data serving as a template for debugger engines
-// started during a session.
-
-class SessionEngine : public DebuggerEngine
-{
- Q_OBJECT
-
-public:
- SessionEngine();
-
- virtual void setupEngine() {}
- virtual void setupInferior() {}
- virtual void runEngine() {}
- virtual void shutdownEngine() {}
- virtual void shutdownInferior() {}
- virtual void executeDebuggerCommand(const QString &command);
- virtual unsigned debuggerCapabilities() const;
-
- virtual bool isSessionEngine() const { return true; }
-
- void loadSessionData();
- void saveSessionData();
-};
-
-
-} // namespace Internal
-} // namespace Debugger
-
-#endif // DEBUGGER_SESSIONENGINE_H
diff --git a/src/plugins/debugger/shared/cdbsymbolpathlisteditor.cpp b/src/plugins/debugger/shared/cdbsymbolpathlisteditor.cpp
new file mode 100644
index 0000000000..ff98d4ac23
--- /dev/null
+++ b/src/plugins/debugger/shared/cdbsymbolpathlisteditor.cpp
@@ -0,0 +1,207 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "cdbsymbolpathlisteditor.h"
+
+#include <coreplugin/icore.h>
+
+#include <utils/pathchooser.h>
+#include <utils/checkablemessagebox.h>
+
+#include <QtCore/QDir>
+#include <QtCore/QDebug>
+#include <QtGui/QFileDialog>
+#include <QtGui/QAction>
+#include <QtGui/QDialogButtonBox>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QFormLayout>
+#include <QtGui/QMessageBox>
+#include <QtGui/QMainWindow>
+
+namespace Debugger {
+namespace Internal {
+
+CacheDirectoryDialog::CacheDirectoryDialog(QWidget *parent) :
+ QDialog(parent), m_chooser(new Utils::PathChooser),
+ m_buttonBox(new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel))
+{
+ setWindowTitle(tr("Select Local Cache Folder"));
+ setModal(true);
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+
+ QFormLayout *formLayout = new QFormLayout;
+ m_chooser->setExpectedKind(Utils::PathChooser::Directory);
+ m_chooser->setMinimumWidth(400);
+ formLayout->addRow(tr("Path:"), m_chooser);
+
+ QVBoxLayout *mainLayout = new QVBoxLayout;
+ mainLayout->addLayout(formLayout);
+ mainLayout->addWidget(m_buttonBox);
+
+ setLayout(mainLayout);
+
+ connect(m_buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
+ connect(m_buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
+}
+
+void CacheDirectoryDialog::setPath(const QString &p)
+{
+ m_chooser->setPath(p);
+}
+
+QString CacheDirectoryDialog::path() const
+{
+ return m_chooser->path();
+}
+
+void CacheDirectoryDialog::accept()
+{
+ // Ensure path exists
+ QString cache = path();
+ if (cache.isEmpty())
+ return;
+ QFileInfo fi(cache);
+ // Folder exists - all happy.
+ if (fi.isDir()) {
+ QDialog::accept();
+ return;
+ }
+ // Does a file of the same name exist?
+ if (fi.exists()) {
+ QMessageBox::warning(this, tr("Already Exists"),
+ tr("A file named '%1' already exists.").arg(cache));
+ return;
+ }
+ // Create
+ QDir root(QDir::root());
+ if (!root.mkpath(cache)) {
+ QMessageBox::warning(this, tr("Cannot Create"),
+ tr("The folder '%1' could not be created.").arg(cache));
+ return;
+ }
+ QDialog::accept();
+}
+
+// ---------------- CdbSymbolPathListEditor
+
+const char *CdbSymbolPathListEditor::symbolServerPrefixC = "symsrv*symsrv.dll*";
+const char *CdbSymbolPathListEditor::symbolServerPostfixC = "*http://msdl.microsoft.com/download/symbols";
+
+CdbSymbolPathListEditor::CdbSymbolPathListEditor(QWidget *parent) :
+ Utils::PathListEditor(parent)
+{
+ //! Add Microsoft Symbol server connection
+ QAction *action = insertAction(lastAddActionIndex() + 1, tr("Symbol Server..."), this, SLOT(addSymbolServer()));
+ action->setToolTip(tr("Adds the Microsoft symbol server providing symbols for operating system libraries."
+ "Requires specifying a local cache directory."));
+}
+
+QString CdbSymbolPathListEditor::promptCacheDirectory(QWidget *parent)
+{
+ CacheDirectoryDialog dialog(parent);
+ dialog.setPath(QDir::tempPath() + QDir::separator() + QLatin1String("symbolcache"));
+ if (dialog.exec() != QDialog::Accepted)
+ return QString();
+ return dialog.path();
+}
+
+void CdbSymbolPathListEditor::addSymbolServer()
+{
+ const QString cacheDir = promptCacheDirectory(this);
+ if (!cacheDir.isEmpty())
+ insertPathAtCursor(CdbSymbolPathListEditor::symbolServerPath(cacheDir));
+}
+
+QString CdbSymbolPathListEditor::symbolServerPath(const QString &cacheDir)
+{
+ QString s = QLatin1String(symbolServerPrefixC);
+ s += QDir::toNativeSeparators(cacheDir);
+ s += QLatin1String(symbolServerPostfixC);
+ return s;
+}
+
+bool CdbSymbolPathListEditor::isSymbolServerPath(const QString &path, QString *cacheDir /* = 0 */)
+{
+ // Split apart symbol server post/prefixes
+ if (!path.startsWith(QLatin1String(symbolServerPrefixC)) || !path.endsWith(QLatin1String(symbolServerPostfixC)))
+ return false;
+ if (cacheDir) {
+ const unsigned prefixLength = qstrlen(symbolServerPrefixC);
+ *cacheDir = path.mid(prefixLength, path.size() - prefixLength - qstrlen(symbolServerPostfixC));
+ }
+ return true;
+}
+
+int CdbSymbolPathListEditor::indexOfSymbolServerPath(const QStringList &paths, QString *cacheDir /* = 0 */)
+{
+ const int count = paths.size();
+ for (int i = 0; i < count; i++)
+ if (CdbSymbolPathListEditor::isSymbolServerPath(paths.at(i), cacheDir))
+ return i;
+ return -1;
+}
+
+bool CdbSymbolPathListEditor::promptToAddSymbolServer(const QString &settingsGroup, QStringList *symbolPaths)
+{
+ // Check symbol server unless the user has an external/internal setup
+ if (!qgetenv("_NT_SYMBOL_PATH").isEmpty()
+ || CdbSymbolPathListEditor::indexOfSymbolServerPath(*symbolPaths) != -1)
+ return false;
+ // Prompt to use Symbol server unless the user checked "No nagging".
+ Core::ICore *core = Core::ICore::instance();
+ const QString nagSymbolServerKey = settingsGroup + QLatin1String("/NoPromptSymbolServer");
+ bool noFurtherNagging = core->settings()->value(nagSymbolServerKey, false).toBool();
+ if (noFurtherNagging)
+ return false;
+
+ const QString symServUrl = QLatin1String("http://support.microsoft.com/kb/311503");
+ const QString msg = tr("<html><head/><body><p>The debugger is not configured to use the public "
+ "<a href=\"%1\">Microsoft Symbol Server</a>. This is recommended "
+ "for retrieval of the symbols of the operating system libraries.</p>"
+ "<p><i>Note:</i> A fast internet connection is required for this to work smoothly. Also, a delay "
+ "might occur when connecting for the first time.</p>"
+ "<p>Would you like to set it up?</p></br>"
+ "</body></html>").arg(symServUrl);
+ const QDialogButtonBox::StandardButton answer =
+ Utils::CheckableMessageBox::question(core->mainWindow(), tr("Symbol Server"), msg,
+ tr("Do not ask again"), &noFurtherNagging);
+ core->settings()->setValue(nagSymbolServerKey, noFurtherNagging);
+ if (answer == QDialogButtonBox::No)
+ return false;
+ // Prompt for path and add it. Synchronize QSetting and debugger.
+ const QString cacheDir = CdbSymbolPathListEditor::promptCacheDirectory(core->mainWindow());
+ if (cacheDir.isEmpty())
+ return false;
+
+ symbolPaths->push_back(CdbSymbolPathListEditor::symbolServerPath(cacheDir));
+ return true;
+}
+
+} // namespace Internal
+} // namespace Debugger
diff --git a/src/plugins/debugger/shared/cdbsymbolpathlisteditor.h b/src/plugins/debugger/shared/cdbsymbolpathlisteditor.h
new file mode 100644
index 0000000000..52f6b3d3b3
--- /dev/null
+++ b/src/plugins/debugger/shared/cdbsymbolpathlisteditor.h
@@ -0,0 +1,99 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 SYMBOLPATHLISTEDITOR_H
+#define SYMBOLPATHLISTEDITOR_H
+
+#include <utils/pathlisteditor.h>
+
+#include <QtGui/QDialog>
+
+namespace Utils {
+ class PathChooser;
+}
+
+QT_BEGIN_NAMESPACE
+class QDialogButtonBox;
+QT_END_NAMESPACE
+
+namespace Debugger {
+namespace Internal {
+
+// Internal helper dialog prompting for a cache directory
+// using a PathChooser.
+// Note that QFileDialog does not offer a way of suggesting
+// a non-existent folder, which is in turn automatically
+// created. This is done here (suggest $TEMP\symbolcache
+// regardless of its existence).
+
+class CacheDirectoryDialog : public QDialog {
+ Q_OBJECT
+public:
+ explicit CacheDirectoryDialog(QWidget *parent = 0);
+
+ void setPath(const QString &p);
+ QString path() const;
+
+ virtual void accept();
+
+private:
+ Utils::PathChooser *m_chooser;
+ QDialogButtonBox *m_buttonBox;
+};
+
+class CdbSymbolPathListEditor : public Utils::PathListEditor
+{
+ Q_OBJECT
+public:
+ explicit CdbSymbolPathListEditor(QWidget *parent = 0);
+
+ static QString promptCacheDirectory(QWidget *parent);
+
+ // Pre- and Postfix used to build a symbol server path specification
+ static const char *symbolServerPrefixC;
+ static const char *symbolServerPostfixC;
+
+ // Format a symbol server specification with a local cache directory
+ static QString symbolServerPath(const QString &cacheDir);
+ // Check for a symbol server path and extract local cache directory
+ static bool isSymbolServerPath(const QString &path, QString *cacheDir = 0);
+ // Check for symbol server in list of paths.
+ static int indexOfSymbolServerPath(const QStringList &paths, QString *cacheDir = 0);
+
+ // Nag user to add a symbol server to the path list on debugger startup.
+ static bool promptToAddSymbolServer(const QString &settingsGroup, QStringList *symbolPaths);
+
+private slots:
+ void addSymbolServer();
+};
+
+} // namespace Internal
+} // namespace Debugger
+
+#endif // SYMBOLPATHLISTEDITOR_H
diff --git a/src/plugins/debugger/shared/dbgwinutils.cpp b/src/plugins/debugger/shared/dbgwinutils.cpp
index 09d3e9d726..8c8ca930d0 100644
--- a/src/plugins/debugger/shared/dbgwinutils.cpp
+++ b/src/plugins/debugger/shared/dbgwinutils.cpp
@@ -32,10 +32,13 @@
**************************************************************************/
#include "winutils.h"
+#include "dbgwinutils.h"
#include "debuggerdialogs.h"
+#include "breakpoint.h"
#include <QtCore/QDebug>
#include <QtCore/QString>
+#include <QtCore/QTextStream>
// Enable Win API of XP SP1 and later
#ifdef Q_OS_WIN
@@ -256,5 +259,156 @@ bool isWinProcessBeingDebugged(unsigned long pid)
return debugged != FALSE;
}
+// Simple exception formatting
+void formatWindowsException(unsigned long code, quint64 address,
+ unsigned long flags, quint64 info1, quint64 info2,
+ QTextStream &str)
+{
+ str.setIntegerBase(16);
+ str << "\nException at 0x" << address
+ << ", code: 0x" << code << ": ";
+ switch (code) {
+ case winExceptionCppException:
+ str << "C++ exception";
+ break;
+ case winExceptionStartupCompleteTrap:
+ str << "Startup complete";
+ break;
+ case winExceptionDllNotFound:
+ str << "DLL not found";
+ break;
+ case winExceptionDllEntryPointNoFound:
+ str << "DLL entry point not found";
+ break;
+ case winExceptionDllInitFailed:
+ str << "DLL failed to initialize";
+ break;
+ case winExceptionMissingSystemFile:
+ str << "System file is missing";
+ break;
+ case winExceptionRpcServerUnavailable:
+ str << "RPC server unavailable";
+ break;
+ case winExceptionRpcServerInvalid:
+ str << "Invalid RPC server";
+ break;
+ case EXCEPTION_ACCESS_VIOLATION: {
+ const bool writeOperation = info1;
+ str << (writeOperation ? "write" : "read")
+ << " access violation at: 0x" << info2;
+ }
+ break;
+ case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
+ str << "arrary bounds exceeded";
+ break;
+ case EXCEPTION_BREAKPOINT:
+ str << "breakpoint";
+ break;
+ case EXCEPTION_DATATYPE_MISALIGNMENT:
+ str << "datatype misalignment";
+ break;
+ case EXCEPTION_FLT_DENORMAL_OPERAND:
+ str << "floating point exception";
+ break;
+ case EXCEPTION_FLT_DIVIDE_BY_ZERO:
+ str << "division by zero";
+ break;
+ case EXCEPTION_FLT_INEXACT_RESULT:
+ str << " floating-point operation cannot be represented exactly as a decimal fraction";
+ break;
+ case EXCEPTION_FLT_INVALID_OPERATION:
+ str << "invalid floating-point operation";
+ break;
+ case EXCEPTION_FLT_OVERFLOW:
+ str << "floating-point overflow";
+ break;
+ case EXCEPTION_FLT_STACK_CHECK:
+ str << "floating-point operation stack over/underflow";
+ break;
+ case EXCEPTION_FLT_UNDERFLOW:
+ str << "floating-point UNDERFLOW";
+ break;
+ case EXCEPTION_ILLEGAL_INSTRUCTION:
+ str << "invalid instruction";
+ break;
+ case EXCEPTION_IN_PAGE_ERROR:
+ str << "page in error";
+ break;
+ case EXCEPTION_INT_DIVIDE_BY_ZERO:
+ str << "integer division by zero";
+ break;
+ case EXCEPTION_INT_OVERFLOW:
+ str << "integer overflow";
+ break;
+ case EXCEPTION_INVALID_DISPOSITION:
+ str << "invalid disposition to exception dispatcher";
+ break;
+ case EXCEPTION_NONCONTINUABLE_EXCEPTION:
+ str << "attempt to continue execution after noncontinuable exception";
+ break;
+ case EXCEPTION_PRIV_INSTRUCTION:
+ str << "privileged instruction";
+ break;
+ case EXCEPTION_SINGLE_STEP:
+ str << "single step";
+ break;
+ case EXCEPTION_STACK_OVERFLOW:
+ str << "stack_overflow";
+ break;
+ }
+ str << ", flags=0x" << flags;
+ if (flags == EXCEPTION_NONCONTINUABLE) {
+ str << " (execution cannot be continued)";
+ }
+ str.setIntegerBase(10);
+}
+
+bool isDebuggerWinException(long code)
+{
+ return code ==EXCEPTION_BREAKPOINT || code == EXCEPTION_SINGLE_STEP;
+}
+
+bool isFatalWinException(long code)
+{
+ switch (code) {
+ case EXCEPTION_BREAKPOINT:
+ case EXCEPTION_SINGLE_STEP:
+ case winExceptionStartupCompleteTrap: // Mysterious exception at start of application
+ case winExceptionRpcServerUnavailable:
+ case winExceptionRpcServerInvalid:
+ case winExceptionDllNotFound:
+ case winExceptionDllEntryPointNoFound:
+ case winExceptionCppException:
+ return false;
+ default:
+ break;
+ }
+ return true;
+}
+
+// Special function names in MSVC runtime
+const char *winMSVCThrowFunction = "CxxThrowException";
+const char *winMSVCCatchFunction = "__CxxCallCatchBlock";
+
+BreakpointParameters fixWinMSVCBreakpoint(const BreakpointParameters &p)
+{
+ if (p.type == BreakpointAtThrow) {
+ BreakpointParameters rc(BreakpointByFunction);
+ rc.functionName = QLatin1String(winMSVCThrowFunction);
+ return rc;
+ }
+ if (p.type == BreakpointAtCatch) {
+ BreakpointParameters rc(BreakpointByFunction);
+ rc.functionName = QLatin1String(winMSVCCatchFunction);
+ return rc;
+ }
+ if (p.type == BreakpointAtMain) {
+ BreakpointParameters rc(BreakpointByFunction);
+ rc.functionName = QLatin1String("main");
+ return rc;
+ }
+ return p;
+}
+
} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/shared/dbgwinutils.h b/src/plugins/debugger/shared/dbgwinutils.h
index afdfc05d34..147fc91839 100644
--- a/src/plugins/debugger/shared/dbgwinutils.h
+++ b/src/plugins/debugger/shared/dbgwinutils.h
@@ -37,10 +37,13 @@
#include <QtCore/QList>
QT_FORWARD_DECLARE_CLASS(QString)
+QT_FORWARD_DECLARE_CLASS(QTextStream)
namespace Debugger {
namespace Internal {
+class BreakpointParameters;
+
struct ProcData; // debuggerdialogs, used by the process listing dialogs
QList<ProcData> winProcessList();
@@ -63,6 +66,35 @@ QString winNormalizeFileName(const QString &f);
bool isWinProcessBeingDebugged(unsigned long pid);
+// Special exception codes.
+enum { winExceptionCppException = 0xe06d7363,
+ winExceptionStartupCompleteTrap = 0x406d1388,
+ winExceptionRpcServerUnavailable = 0x6ba,
+ winExceptionRpcServerInvalid = 0x6a6,
+ winExceptionDllNotFound = 0xc0000135,
+ winExceptionDllEntryPointNoFound = 0xc0000139,
+ winExceptionDllInitFailed = 0xc0000142,
+ winExceptionMissingSystemFile = 0xc0000143,
+ winExceptionAppInitFailed = 0xc0000143
+};
+
+// Format windows Exception
+void formatWindowsException(unsigned long code, quint64 address,
+ unsigned long flags, quint64 info1, quint64 info2,
+ QTextStream &str);
+// Check for access violation, etc.
+bool isFatalWinException(long code);
+
+// Check for EXCEPTION_BREAKPOINT, EXCEPTION_SINGLE_STEP
+bool isDebuggerWinException(long code);
+
+// fix up breakpoints (catch/throw, etc).
+BreakpointParameters fixWinMSVCBreakpoint(const BreakpointParameters &p);
+
+// Special function names in MSVC runtime
+extern const char *winMSVCThrowFunction;
+extern const char *winMSVCCatchFunction;
+
} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/shared/shared.pri b/src/plugins/debugger/shared/shared.pri
index 760b012a44..9f4666d54b 100644
--- a/src/plugins/debugger/shared/shared.pri
+++ b/src/plugins/debugger/shared/shared.pri
@@ -1,12 +1,12 @@
+SOURCES += $$PWD/backtrace.cpp \
+ $$PWD/cdbsymbolpathlisteditor.cpp
-
-SOURCES += $$PWD/backtrace.cpp
-HEADERS += $$PWD/backtrace.h
-
-win32 {
+HEADERS += $$PWD/backtrace.h \
+ $$PWD/cdbsymbolpathlisteditor.h
INCLUDEPATH+=$$PWD
+win32 {
SOURCES += $$PWD/peutils.cpp \
$$PWD/dbgwinutils.cpp \
$$PWD/sharedlibraryinjector.cpp
@@ -17,8 +17,7 @@ HEADERS += $$PWD/peutils.h \
contains(QMAKE_CXX, cl) {
# For the Privilege manipulation functions in sharedlibraryinjector.cpp.
-# Not required for MinGW.
- LIBS += advapi32.lib
+ LIBS += -ladvapi32
}
}
diff --git a/src/plugins/debugger/snapshothandler.cpp b/src/plugins/debugger/snapshothandler.cpp
index 30a84bedae..df335391e8 100644
--- a/src/plugins/debugger/snapshothandler.cpp
+++ b/src/plugins/debugger/snapshothandler.cpp
@@ -33,20 +33,16 @@
#include "snapshothandler.h"
-#include "sessionengine.h"
-#include "debuggeractions.h"
#include "debuggerconstants.h"
+#include "debuggercore.h"
#include "debuggerengine.h"
#include "debuggerrunner.h"
-#include "debuggerplugin.h"
#include <utils/qtcassert.h>
-#include <utils/savedaction.h>
-#include <QtCore/QAbstractTableModel>
#include <QtCore/QDebug>
-#include <QtCore/QFileInfo>
-#include <QtCore/QDir>
+#include <QtCore/QFile>
+#include <QtGui/QIcon>
namespace Debugger {
namespace Internal {
@@ -131,21 +127,14 @@ SnapshotHandler::SnapshotHandler()
SnapshotHandler::~SnapshotHandler()
{
for (int i = m_snapshots.size(); --i >= 0; ) {
- if (DebuggerEngine *engine = engineAt(i)) {
- const DebuggerStartParameters & sp = engine->startParameters();
+ if (DebuggerEngine *engine = at(i)) {
+ const DebuggerStartParameters &sp = engine->startParameters();
if (sp.isSnapshot && !sp.coreFile.isEmpty())
QFile::remove(sp.coreFile);
}
}
}
-DebuggerEngine *SnapshotHandler::engineAt(int i) const
-{
- DebuggerEngine *engine = m_snapshots.at(i)->engine();
- QTC_ASSERT(engine, qDebug() << "ENGINE AT " << i << "DELETED");
- return engine;
-}
-
int SnapshotHandler::rowCount(const QModelIndex &parent) const
{
// Since the stack is not a tree, row count is 0 for any valid parent
@@ -162,7 +151,7 @@ QVariant SnapshotHandler::data(const QModelIndex &index, int role) const
if (!index.isValid() || index.row() >= m_snapshots.size())
return QVariant();
- const DebuggerEngine *engine = engineAt(index.row());
+ const DebuggerEngine *engine = at(index.row());
if (role == SnapshotCapabilityRole)
return engine && (engine->debuggerCapabilities() & SnapshotCapability);
@@ -185,7 +174,8 @@ QVariant SnapshotHandler::data(const QModelIndex &index, int role) const
case Qt::ToolTipRole:
return QVariant();
- case Qt::DecorationRole: // Return icon that indicates whether this is the active stack frame
+ case Qt::DecorationRole:
+ // Return icon that indicates whether this is the active stack frame.
if (index.column() == 0)
return (index.row() == m_currentIndex) ? m_positionIcon : m_emptyIcon;
break;
@@ -216,38 +206,43 @@ Qt::ItemFlags SnapshotHandler::flags(const QModelIndex &index) const
return true ? QAbstractTableModel::flags(index) : Qt::ItemFlags(0);
}
-bool SnapshotHandler::setData
- (const QModelIndex &index, const QVariant &value, int role)
+void SnapshotHandler::activateSnapshot(int index)
{
- Q_UNUSED(value);
- if (index.isValid() && role == RequestCreateSnapshotRole) {
- DebuggerEngine *engine = engineAt(index.row());
- QTC_ASSERT(engine, return false);
- engine->createSnapshot();
- return true;
- }
- if (index.isValid() && role == RequestActivateSnapshotRole) {
- m_currentIndex = index.row();
- //qDebug() << "ACTIVATING INDEX: " << m_currentIndex << " OF " << size();
- DebuggerPlugin::displayDebugger(m_snapshots.at(m_currentIndex));
- reset();
- return true;
- }
- if (index.isValid() && role == RequestRemoveSnapshotRole) {
- DebuggerEngine *engine = engineAt(index.row());
- //qDebug() << "REMOVING " << engine;
- QTC_ASSERT(engine, return false);
- engine->quitDebugger();
- return true;
- }
- return false;
+ m_currentIndex = index;
+ //qDebug() << "ACTIVATING INDEX: " << m_currentIndex << " OF " << size();
+ debuggerCore()->displayDebugger(at(index), true);
+ reset();
}
+void SnapshotHandler::createSnapshot(int index)
+{
+ DebuggerEngine *engine = at(index);
+ QTC_ASSERT(engine, return);
+ engine->createSnapshot();
+}
+
+void SnapshotHandler::removeSnapshot(int index)
+{
+ DebuggerEngine *engine = at(index);
+ //qDebug() << "REMOVING " << engine;
+ QTC_ASSERT(engine, return);
#if 0
// See http://sourceware.org/bugzilla/show_bug.cgi?id=11241.
setState(EngineSetupRequested);
postCommand("set stack-cache off");
#endif
+ //QString fileName = engine->startParameters().coreFile;
+ //if (!fileName.isEmpty())
+ // QFile::remove(fileName);
+ m_snapshots.removeAt(index);
+ if (index == m_currentIndex)
+ m_currentIndex = -1;
+ else if (index < m_currentIndex)
+ --m_currentIndex;
+ //engine->quitDebugger();
+ reset();
+}
+
void SnapshotHandler::removeAll()
{
@@ -256,58 +251,31 @@ void SnapshotHandler::removeAll()
reset();
}
-void SnapshotHandler::appendSnapshot(DebuggerRunControl *rc)
+void SnapshotHandler::appendSnapshot(DebuggerEngine *engine)
{
- m_snapshots.append(rc);
+ m_snapshots.append(engine);
m_currentIndex = size() - 1;
reset();
}
-void SnapshotHandler::removeSnapshot(DebuggerRunControl *rc)
+void SnapshotHandler::removeSnapshot(DebuggerEngine *engine)
{
// Could be that the run controls died before it was appended.
- int index = m_snapshots.indexOf(rc);
+ int index = m_snapshots.indexOf(engine);
if (index != -1)
removeSnapshot(index);
}
-void SnapshotHandler::removeSnapshot(int index)
-{
- const DebuggerEngine *engine = engineAt(index);
- QTC_ASSERT(engine, return);
- QString fileName = engine->startParameters().coreFile;
- //if (!fileName.isEmpty())
- // QFile::remove(fileName);
- m_snapshots.removeAt(index);
- if (index == m_currentIndex)
- m_currentIndex = -1;
- else if (index < m_currentIndex)
- --m_currentIndex;
- reset();
-}
-
void SnapshotHandler::setCurrentIndex(int index)
{
m_currentIndex = index;
reset();
}
-DebuggerRunControl *SnapshotHandler::at(int i) const
+DebuggerEngine *SnapshotHandler::at(int i) const
{
return m_snapshots.at(i).data();
}
-QList<DebuggerRunControl*> SnapshotHandler::runControls() const
-{
- // Return unique list of run controls
- QList<DebuggerRunControl*> rc;
- rc.reserve(m_snapshots.size());
- foreach(const QPointer<DebuggerRunControl> &runControlPtr, m_snapshots)
- if (DebuggerRunControl *runControl = runControlPtr)
- if (!rc.contains(runControl))
- rc.push_back(runControl);
- return rc;
-}
-
} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/snapshothandler.h b/src/plugins/debugger/snapshothandler.h
index e6b3506d03..fc7088c18a 100644
--- a/src/plugins/debugger/snapshothandler.h
+++ b/src/plugins/debugger/snapshothandler.h
@@ -34,12 +34,11 @@
#ifndef DEBUGGER_SNAPSHOTHANDLER_H
#define DEBUGGER_SNAPSHOTHANDLER_H
-#include <QtCore/QAbstractItemModel>
+#include <QtCore/QAbstractTableModel>
#include <QtCore/QPointer>
namespace Debugger {
-class DebuggerRunControl;
class DebuggerEngine;
namespace Internal {
@@ -63,27 +62,27 @@ public:
void removeAll();
QAbstractItemModel *model() { return this; }
int currentIndex() const { return m_currentIndex; }
- void appendSnapshot(DebuggerRunControl *rc);
- void removeSnapshot(DebuggerRunControl *rc);
+ void appendSnapshot(DebuggerEngine *engine);
+ void removeSnapshot(DebuggerEngine *engine);
void setCurrentIndex(int index);
int size() const { return m_snapshots.size(); }
- DebuggerRunControl *at(int i) const;
- QList<DebuggerRunControl*> runControls() const;
+ DebuggerEngine *at(int index) const;
+
+ void createSnapshot(int index);
+ void activateSnapshot(int index);
+ void removeSnapshot(int index);
private:
// QAbstractTableModel
int rowCount(const QModelIndex &parent) const;
int columnCount(const QModelIndex &parent) const;
QVariant data(const QModelIndex &index, int role) const;
- bool setData(const QModelIndex &index, const QVariant &value, int role);
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
Q_SLOT void resetModel() { reset(); }
- DebuggerEngine *engineAt(int i) const;
- void removeSnapshot(int index);
int m_currentIndex;
- QList< QPointer<DebuggerRunControl> > m_snapshots;
+ QList< QPointer<DebuggerEngine> > m_snapshots;
const QVariant m_positionIcon;
const QVariant m_emptyIcon;
};
diff --git a/src/plugins/debugger/snapshotwindow.cpp b/src/plugins/debugger/snapshotwindow.cpp
index c4da64628f..f08c3b4942 100644
--- a/src/plugins/debugger/snapshotwindow.cpp
+++ b/src/plugins/debugger/snapshotwindow.cpp
@@ -32,29 +32,20 @@
**************************************************************************/
#include "snapshotwindow.h"
+#include "snapshothandler.h"
#include "debuggeractions.h"
-#include "debuggerconstants.h"
+#include "debuggercore.h"
+#include "debuggerengine.h"
#include <utils/qtcassert.h>
#include <utils/savedaction.h>
#include <QtCore/QDebug>
-#include <QtGui/QAction>
#include <QtGui/QHeaderView>
-#include <QtGui/QKeyEvent>
#include <QtGui/QMenu>
-#include <QtGui/QTreeView>
-
-static QModelIndexList normalizeIndexes(const QModelIndexList &list)
-{
- QModelIndexList res;
- foreach (const QModelIndex &idx, list)
- if (idx.column() == 0)
- res.append(idx);
- return res;
-}
+#include <QtGui/QKeyEvent>
namespace Debugger {
@@ -66,10 +57,12 @@ namespace Internal {
//
///////////////////////////////////////////////////////////////////////
-SnapshotWindow::SnapshotWindow(QWidget *parent)
- : QTreeView(parent), m_alwaysResizeColumnsToContents(false)
+SnapshotWindow::SnapshotWindow(SnapshotHandler *handler)
+ : m_alwaysResizeColumnsToContents(false)
{
- QAction *act = theDebuggerAction(UseAlternatingRowColors);
+ m_snapshotHandler = handler;
+
+ QAction *act = debuggerCore()->action(UseAlternatingRowColors);
setWindowTitle(tr("Snapshots"));
setAttribute(Qt::WA_MacShowFocusRect, false);
setFrameStyle(QFrame::NoFrame);
@@ -80,25 +73,14 @@ SnapshotWindow::SnapshotWindow(QWidget *parent)
header()->setDefaultAlignment(Qt::AlignLeft);
connect(this, SIGNAL(activated(QModelIndex)),
- this, SLOT(rowActivated(QModelIndex)));
+ SLOT(rowActivated(QModelIndex)));
connect(act, SIGNAL(toggled(bool)),
- this, SLOT(setAlternatingRowColorsHelper(bool)));
-}
-
-SnapshotWindow::~SnapshotWindow()
-{
+ SLOT(setAlternatingRowColorsHelper(bool)));
}
void SnapshotWindow::rowActivated(const QModelIndex &index)
{
- model()->setData(index, index.row(), RequestActivateSnapshotRole);
-}
-
-void SnapshotWindow::removeSnapshots(const QModelIndexList &indexes)
-{
- QTC_ASSERT(!indexes.isEmpty(), return);
- foreach (const QModelIndex &idx, indexes)
- model()->setData(idx, QVariant(), RequestRemoveSnapshotRole);
+ m_snapshotHandler->activateSnapshot(index.row());
}
void SnapshotWindow::keyPressEvent(QKeyEvent *ev)
@@ -109,7 +91,10 @@ void SnapshotWindow::keyPressEvent(QKeyEvent *ev)
QModelIndexList si = sm->selectedIndexes();
if (si.isEmpty())
si.append(currentIndex().sibling(currentIndex().row(), 0));
- removeSnapshots(normalizeIndexes(si));
+
+ foreach (const QModelIndex &idx, si)
+ if (idx.column() == 0)
+ removeSnapshot(idx.row());
}
QTreeView::keyPressEvent(ev);
}
@@ -139,20 +124,25 @@ void SnapshotWindow::contextMenuEvent(QContextMenuEvent *ev)
menu.addSeparator();
- menu.addAction(theDebuggerAction(SettingsDialog));
+ menu.addAction(debuggerCore()->action(SettingsDialog));
QAction *act = menu.exec(ev->globalPos());
if (act == actCreate)
- model()->setData(idx, idx.row(), RequestCreateSnapshotRole);
+ m_snapshotHandler->createSnapshot(idx.row());
else if (act == actRemove)
- model()->setData(idx, idx.row(), RequestRemoveSnapshotRole);
+ removeSnapshot(idx.row());
else if (act == actAdjust)
resizeColumnsToContents();
else if (act == actAlwaysAdjust)
setAlwaysResizeColumnsToContents(!m_alwaysResizeColumnsToContents);
}
+void SnapshotWindow::removeSnapshot(int i)
+{
+ m_snapshotHandler->at(i)->quitDebugger();
+}
+
void SnapshotWindow::resizeColumnsToContents()
{
for (int i = model()->columnCount(); --i >= 0; )
diff --git a/src/plugins/debugger/snapshotwindow.h b/src/plugins/debugger/snapshotwindow.h
index 98b74c7a1b..f819831e05 100644
--- a/src/plugins/debugger/snapshotwindow.h
+++ b/src/plugins/debugger/snapshotwindow.h
@@ -36,21 +36,17 @@
#include <QtGui/QTreeView>
-QT_BEGIN_NAMESPACE
-class QComboBox;
-class QModelIndex;
-QT_END_NAMESPACE
-
namespace Debugger {
namespace Internal {
+class SnapshotHandler;
+
class SnapshotWindow : public QTreeView
{
Q_OBJECT
public:
- SnapshotWindow(QWidget *parent = 0);
- ~SnapshotWindow();
+ explicit SnapshotWindow(SnapshotHandler *handler);
public slots:
void resizeColumnsToContents();
@@ -61,11 +57,12 @@ private slots:
void setAlternatingRowColorsHelper(bool on) { setAlternatingRowColors(on); }
private:
+ void removeSnapshot(int i);
void keyPressEvent(QKeyEvent *ev);
void contextMenuEvent(QContextMenuEvent *ev);
- void removeSnapshots(const QModelIndexList &list);
bool m_alwaysResizeColumnsToContents;
+ SnapshotHandler *m_snapshotHandler;
};
} // namespace Internal
diff --git a/src/plugins/debugger/sourceagent.cpp b/src/plugins/debugger/sourceagent.cpp
new file mode 100644
index 0000000000..b9b76cc200
--- /dev/null
+++ b/src/plugins/debugger/sourceagent.cpp
@@ -0,0 +1,187 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "sourceagent.h"
+
+#include "breakhandler.h"
+#include "debuggerengine.h"
+#include "debuggercore.h"
+#include "debuggerstringutils.h"
+#include "stackframe.h"
+#include "stackhandler.h"
+
+#include <coreplugin/coreconstants.h>
+#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/editormanager/ieditor.h>
+#include <coreplugin/mimedatabase.h>
+#include <coreplugin/icore.h>
+
+#include <texteditor/basetextdocument.h>
+#include <texteditor/basetexteditor.h>
+#include <texteditor/basetextmark.h>
+#include <texteditor/plaintexteditor.h>
+#include <texteditor/texteditorconstants.h>
+
+#include <cppeditor/cppeditorconstants.h>
+
+#include <utils/qtcassert.h>
+
+#include <QtCore/QDebug>
+#include <QtCore/QMetaObject>
+#include <QtCore/QTimer>
+
+#include <QtGui/QMessageBox>
+#include <QtGui/QPlainTextEdit>
+#include <QtGui/QTextBlock>
+#include <QtGui/QTextCursor>
+#include <QtGui/QIcon>
+
+#include <limits.h>
+
+using namespace Core;
+
+namespace Debugger {
+namespace Internal {
+
+class LocationMarkFoo : public TextEditor::ITextMark
+{
+public:
+ LocationMarkFoo() {}
+
+ QIcon icon() const { return debuggerCore()->locationMarkIcon(); }
+ void updateLineNumber(int /*lineNumber*/) {}
+ void updateBlock(const QTextBlock & /*block*/) {}
+ void removedFromEditor() {}
+ void documentClosing() {}
+};
+
+class SourceAgentPrivate
+{
+public:
+ SourceAgentPrivate();
+ ~SourceAgentPrivate();
+
+public:
+ QPointer<TextEditor::ITextEditor> editor;
+ QPointer<DebuggerEngine> engine;
+ TextEditor::ITextMark *locationMark;
+ QString path;
+ QString producer;
+};
+
+SourceAgentPrivate::SourceAgentPrivate()
+ : editor(0)
+ , locationMark(new LocationMarkFoo)
+ , producer("remote")
+{
+}
+
+SourceAgentPrivate::~SourceAgentPrivate()
+{
+ if (editor) {
+ EditorManager *editorManager = EditorManager::instance();
+ editorManager->closeEditors(QList<IEditor *>() << editor);
+ }
+ editor = 0;
+ delete locationMark;
+}
+
+SourceAgent::SourceAgent(DebuggerEngine *engine)
+ : QObject(0), d(new SourceAgentPrivate)
+{
+ d->engine = engine;
+}
+
+SourceAgent::~SourceAgent()
+{
+ delete d;
+ d = 0;
+}
+
+void SourceAgent::setSourceProducerName(const QString &name)
+{
+ d->producer = name;
+}
+
+void SourceAgent::setContent(const QString &filePath, const QString &content)
+{
+ QTC_ASSERT(d, return);
+ using namespace Core;
+ using namespace TextEditor;
+
+ d->path = filePath;
+
+ EditorManager *editorManager = EditorManager::instance();
+ if (!d->editor) {
+ QString titlePattern = d->producer + QLatin1String(": ")
+ + QFileInfo(filePath).fileName();
+ d->editor = qobject_cast<ITextEditor *>(
+ editorManager->openEditorWithContents(
+ CppEditor::Constants::CPPEDITOR_ID,
+ &titlePattern, content));
+ QTC_ASSERT(d->editor, return);
+ d->editor->setProperty(Debugger::Constants::OPENED_BY_DEBUGGER, true);
+
+ BaseTextEditor *baseTextEdit =
+ qobject_cast<BaseTextEditor *>(d->editor->widget());
+ if (baseTextEdit)
+ baseTextEdit->setRequestMarkEnabled(true);
+ }
+
+ editorManager->activateEditor(d->editor);
+
+ QPlainTextEdit *plainTextEdit =
+ qobject_cast<QPlainTextEdit *>(d->editor->widget());
+ QTC_ASSERT(plainTextEdit, return);
+ plainTextEdit->setReadOnly(true);
+
+ updateLocationMarker();
+}
+
+void SourceAgent::updateLocationMarker()
+{
+ QTC_ASSERT(d->editor, return);
+
+ d->editor->markableInterface()->removeMark(d->locationMark);
+ if (d->engine->stackHandler()->currentFrame().file == d->path) {
+ int lineNumber = d->engine->stackHandler()->currentFrame().line;
+ d->editor->markableInterface()->addMark(d->locationMark, lineNumber);
+ QPlainTextEdit *plainTextEdit = qobject_cast<QPlainTextEdit *>(d->editor->widget());
+ QTC_ASSERT(plainTextEdit, return);
+ QTextCursor tc = plainTextEdit->textCursor();
+ QTextBlock block = tc.document()->findBlockByNumber(lineNumber - 1);
+ tc.setPosition(block.position());
+ plainTextEdit->setTextCursor(tc);
+ EditorManager *editorManager = EditorManager::instance();
+ editorManager->activateEditor(d->editor);
+ }
+}
+
+} // namespace Internal
+} // namespace Debugger
diff --git a/src/plugins/debugger/sourceagent.h b/src/plugins/debugger/sourceagent.h
new file mode 100644
index 0000000000..649e01ab7d
--- /dev/null
+++ b/src/plugins/debugger/sourceagent.h
@@ -0,0 +1,62 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 DEBUGGER_SOURCE_AGENT_H
+#define DEBUGGER_SOURCE_AGENT_H
+
+#include <QtCore/QObject>
+#include <QtCore/QHash>
+#include <QtCore/QPointer>
+#include <QtCore/QVector>
+
+namespace Debugger {
+
+class DebuggerEngine;
+
+namespace Internal {
+
+class SourceAgentPrivate;
+class SourceAgent : public QObject
+{
+public:
+ explicit SourceAgent(Debugger::DebuggerEngine *engine);
+ ~SourceAgent();
+ void setSourceProducerName(const QString &name);
+ void resetLocation();
+ void setContent(const QString &name, const QString &content);
+ void updateLocationMarker();
+private:
+ SourceAgentPrivate *d;
+};
+
+
+} // namespace Internal
+} // namespace Debugger
+
+#endif
diff --git a/src/plugins/debugger/sourcefileshandler.cpp b/src/plugins/debugger/sourcefileshandler.cpp
index 0aaba7c108..1720e9ea72 100644
--- a/src/plugins/debugger/sourcefileshandler.cpp
+++ b/src/plugins/debugger/sourcefileshandler.cpp
@@ -33,9 +33,6 @@
#include "sourcefileshandler.h"
-#include "debuggerconstants.h"
-#include "debuggerengine.h"
-
#include <QtCore/QDebug>
#include <QtCore/QFileInfo>
@@ -44,8 +41,7 @@
namespace Debugger {
namespace Internal {
-SourceFilesHandler::SourceFilesHandler(DebuggerEngine *engine)
- : m_engine(engine)
+SourceFilesHandler::SourceFilesHandler()
{
QSortFilterProxyModel *proxy = new QSortFilterProxyModel(this);
proxy->setSourceModel(this);
@@ -84,11 +80,6 @@ Qt::ItemFlags SourceFilesHandler::flags(const QModelIndex &index) const
QVariant SourceFilesHandler::data(const QModelIndex &index, int role) const
{
- switch (role) {
- case EngineActionsEnabledRole:
- return m_engine->debuggerActionsEnabled();
- }
-
int row = index.row();
if (row < 0 || row >= m_shortNames.size())
return QVariant();
@@ -111,22 +102,6 @@ QVariant SourceFilesHandler::data(const QModelIndex &index, int role) const
return QVariant();
}
-bool SourceFilesHandler::setData
- (const QModelIndex &index, const QVariant &value, int role)
-{
- Q_UNUSED(index);
- switch (role) {
- case RequestReloadSourceFilesRole:
- m_engine->reloadSourceFiles();
- return true;
-
- case RequestOpenFileRole:
- m_engine->openFile(value.toString());
- return true;
- }
- return false;
-}
-
void SourceFilesHandler::setSourceFiles(const QMap<QString, QString> &sourceFiles)
{
m_shortNames.clear();
diff --git a/src/plugins/debugger/sourcefileshandler.h b/src/plugins/debugger/sourcefileshandler.h
index f6f2972e50..de034e49e7 100644
--- a/src/plugins/debugger/sourcefileshandler.h
+++ b/src/plugins/debugger/sourcefileshandler.h
@@ -35,13 +35,9 @@
#define DEBUGGER_SOURCEFILESHANDLER_H
#include <QtCore/QAbstractItemModel>
-#include <QtCore/QMap>
#include <QtCore/QStringList>
-
namespace Debugger {
-class DebuggerEngine;
-
namespace Internal {
class SourceFilesHandler : public QAbstractItemModel
@@ -49,7 +45,7 @@ class SourceFilesHandler : public QAbstractItemModel
Q_OBJECT
public:
- explicit SourceFilesHandler(DebuggerEngine *engine);
+ SourceFilesHandler();
int columnCount(const QModelIndex &parent) const
{ return parent.isValid() ? 0 : 2; }
@@ -60,7 +56,6 @@ public:
{ return createIndex(row, column); }
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
QVariant data(const QModelIndex &index, int role) const;
- bool setData(const QModelIndex &index, const QVariant &value, int role);
Qt::ItemFlags flags(const QModelIndex &index) const;
void clearModel();
@@ -72,7 +67,6 @@ public:
QAbstractItemModel *model() { return m_proxyModel; }
private:
- DebuggerEngine *m_engine;
QStringList m_shortNames;
QStringList m_fullNames;
QAbstractItemModel *m_proxyModel;
diff --git a/src/plugins/debugger/sourcefileswindow.cpp b/src/plugins/debugger/sourcefileswindow.cpp
index 1dcce948c2..8b537327c8 100644
--- a/src/plugins/debugger/sourcefileswindow.cpp
+++ b/src/plugins/debugger/sourcefileswindow.cpp
@@ -35,6 +35,8 @@
#include "debuggeractions.h"
#include "debuggerconstants.h"
+#include "debuggercore.h"
+#include "debuggerengine.h"
#include <utils/qtcassert.h>
#include <utils/savedaction.h>
@@ -42,11 +44,9 @@
#include <QtCore/QDebug>
#include <QtCore/QFileInfo>
-#include <QtGui/QAction>
#include <QtGui/QHeaderView>
#include <QtGui/QMenu>
#include <QtGui/QResizeEvent>
-#include <QtGui/QTreeView>
//////////////////////////////////////////////////////////////////
@@ -58,10 +58,15 @@
namespace Debugger {
namespace Internal {
+static DebuggerEngine *currentEngine()
+{
+ return debuggerCore()->currentEngine();
+}
+
SourceFilesWindow::SourceFilesWindow(QWidget *parent)
: QTreeView(parent)
{
- QAction *act = theDebuggerAction(UseAlternatingRowColors);
+ QAction *act = debuggerCore()->action(UseAlternatingRowColors);
setAttribute(Qt::WA_MacShowFocusRect, false);
setFrameStyle(QFrame::NoFrame);
@@ -73,22 +78,26 @@ SourceFilesWindow::SourceFilesWindow(QWidget *parent)
//header()->setDefaultAlignment(Qt::AlignLeft);
connect(this, SIGNAL(activated(QModelIndex)),
- this, SLOT(sourceFileActivated(QModelIndex)));
+ SLOT(sourceFileActivated(QModelIndex)));
connect(act, SIGNAL(toggled(bool)),
- this, SLOT(setAlternatingRowColorsHelper(bool)));
+ SLOT(setAlternatingRowColorsHelper(bool)));
}
void SourceFilesWindow::sourceFileActivated(const QModelIndex &index)
{
- setModelData(RequestOpenFileRole, index.data());
+ DebuggerEngine *engine = currentEngine();
+ QTC_ASSERT(engine, return);
+ engine->gotoLocation(index.data().toString());
}
void SourceFilesWindow::contextMenuEvent(QContextMenuEvent *ev)
{
+ DebuggerEngine *engine = currentEngine();
+ QTC_ASSERT(engine, return);
QModelIndex index = indexAt(ev->pos());
index = index.sibling(index.row(), 0);
QString name = index.data().toString();
- bool engineActionsEnabled = index.data(EngineActionsEnabledRole).toBool();
+ bool engineActionsEnabled = engine->debuggerActionsEnabled();
QMenu menu;
QAction *act1 = new QAction(tr("Reload Data"), &menu);
@@ -107,21 +116,14 @@ void SourceFilesWindow::contextMenuEvent(QContextMenuEvent *ev)
menu.addAction(act1);
menu.addAction(act2);
menu.addSeparator();
- menu.addAction(theDebuggerAction(SettingsDialog));
+ menu.addAction(debuggerCore()->action(SettingsDialog));
QAction *act = menu.exec(ev->globalPos());
if (act == act1)
- setModelData(RequestReloadSourceFilesRole);
+ engine->reloadSourceFiles();
else if (act == act2)
- setModelData(RequestOpenFileRole, name);
-}
-
-void SourceFilesWindow::setModelData
- (int role, const QVariant &value, const QModelIndex &index)
-{
- QTC_ASSERT(model(), return);
- model()->setData(index, value, role);
+ engine->gotoLocation(name);
}
} // namespace Internal
diff --git a/src/plugins/debugger/sourcefileswindow.h b/src/plugins/debugger/sourcefileswindow.h
index 280559a569..0797f1e13f 100644
--- a/src/plugins/debugger/sourcefileswindow.h
+++ b/src/plugins/debugger/sourcefileswindow.h
@@ -34,10 +34,8 @@
#ifndef DEBUGGER_SOURCEFILEWINDOW_H
#define DEBUGGER_SOURCEFILEWINDOW_H
-#include <QtCore/QMap>
#include <QtGui/QTreeView>
-
namespace Debugger {
namespace Internal {
@@ -54,8 +52,6 @@ private slots:
private:
void contextMenuEvent(QContextMenuEvent *ev);
- void setModelData(int role, const QVariant &value = QVariant(),
- const QModelIndex &index = QModelIndex());
};
} // namespace Internal
diff --git a/src/plugins/debugger/stackframe.cpp b/src/plugins/debugger/stackframe.cpp
index 566f253305..daec23b75c 100644
--- a/src/plugins/debugger/stackframe.cpp
+++ b/src/plugins/debugger/stackframe.cpp
@@ -32,15 +32,12 @@
**************************************************************************/
#include "stackframe.h"
-#include "stackhandler.h"
#include <QtCore/QFileInfo>
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QTextStream>
-
-#include <QtGui/QToolTip>
-#include <QtGui/QFontMetrics>
+#include <QtCore/QCoreApplication>
namespace Debugger {
namespace Internal {
@@ -52,12 +49,12 @@ namespace Internal {
////////////////////////////////////////////////////////////////////////
StackFrame::StackFrame()
- : level(0), line(0), address(0)
+ : level(-1), line(-1), address(0), usable(false)
{}
void StackFrame::clear()
{
- line = level = 0;
+ line = level = -1;
function.clear();
file.clear();
from.clear();
@@ -67,23 +64,23 @@ void StackFrame::clear()
bool StackFrame::isUsable() const
{
- return !file.isEmpty() && QFileInfo(file).isReadable();
+ return usable;
}
QString StackFrame::toString() const
{
QString res;
QTextStream str(&res);
- str << StackHandler::tr("Address:") << ' ';
+ str << tr("Address:") << ' ';
str.setIntegerBase(16);
str << address;
str.setIntegerBase(10);
str << ' '
- << StackHandler::tr("Function:") << ' ' << function << ' '
- << StackHandler::tr("File:") << ' ' << file << ' '
- << StackHandler::tr("Line:") << ' ' << line << ' '
- << StackHandler::tr("From:") << ' ' << from << ' '
- << StackHandler::tr("To:") << ' ' << to;
+ << tr("Function:") << ' ' << function << ' '
+ << tr("File:") << ' ' << file << ' '
+ << tr("Line:") << ' ' << line << ' '
+ << tr("From:") << ' ' << from << ' '
+ << tr("To:") << ' ' << to;
return res;
}
@@ -93,17 +90,16 @@ QString StackFrame::toToolTip() const
QString res;
QTextStream str(&res);
str << "<html><body><table>"
- << "<tr><td>" << StackHandler::tr("Address:") << "</td><td>0x";
+ << "<tr><td>" << tr("Address:") << "</td><td>0x";
str.setIntegerBase(16);
str << address;
str.setIntegerBase(10);
str << "</td></tr>"
- << "<tr><td>" << StackHandler::tr("Function:") << "</td><td>" << function << "</td></tr>"
- << "<tr><td>" << StackHandler::tr("File:") << "</td><td width="
- << QFontMetrics(QToolTip::font()).width(filePath) << ">" << filePath << "</td></tr>"
- << "<tr><td>" << StackHandler::tr("Line:") << "</td><td>" << line << "</td></tr>"
- << "<tr><td>" << StackHandler::tr("From:") << "</td><td>" << from << "</td></tr>"
- << "<tr><td>" << StackHandler::tr("To:") << "</td><td>" << to << "</td></tr>"
+ << "<tr><td>" << tr("Function:") << "</td><td>" << function << "</td></tr>"
+ << "<tr><td>" << tr("File:") << "</td><td>" << filePath << "</td></tr>"
+ << "<tr><td>" << tr("Line:") << "</td><td>" << line << "</td></tr>"
+ << "<tr><td>" << tr("From:") << "</td><td>" << from << "</td></tr>"
+ << "<tr><td>" << tr("To:") << "</td><td>" << to << "</td></tr>"
<< "</table></body></html>";
return res;
}
diff --git a/src/plugins/debugger/stackframe.h b/src/plugins/debugger/stackframe.h
index a77c2b79ea..b5ae14ae5a 100644
--- a/src/plugins/debugger/stackframe.h
+++ b/src/plugins/debugger/stackframe.h
@@ -37,6 +37,7 @@
#include <QtCore/QList>
#include <QtCore/QMetaType>
#include <QtCore/QString>
+#include <QtCore/QCoreApplication>
QT_BEGIN_NAMESPACE
class QDebug;
@@ -55,13 +56,16 @@ public:
QString toString() const;
public:
- int level;
+ qint32 level;
QString function;
QString file; // We try to put an absolute file name in there.
QString from; // Sometimes something like "/usr/lib/libstdc++.so.6"
QString to; // Used in ScriptEngine only.
- int line;
+ qint32 line;
quint64 address;
+ bool usable;
+
+ Q_DECLARE_TR_FUNCTIONS(StackHandler)
};
QDebug operator<<(QDebug d, const StackFrame &frame);
@@ -71,6 +75,6 @@ typedef QList<StackFrame> StackFrames;
} // namespace Internal
} // namespace Debugger
-Q_DECLARE_METATYPE(Debugger::Internal::StackFrame);
+Q_DECLARE_METATYPE(Debugger::Internal::StackFrame)
#endif // DEBUGGER_STACKFRAME_H
diff --git a/src/plugins/debugger/stackhandler.cpp b/src/plugins/debugger/stackhandler.cpp
index 5c031f3889..5ae6eec56d 100644
--- a/src/plugins/debugger/stackhandler.cpp
+++ b/src/plugins/debugger/stackhandler.cpp
@@ -34,17 +34,15 @@
#include "stackhandler.h"
#include "debuggeractions.h"
-#include "debuggeragents.h"
+#include "debuggercore.h"
#include "debuggerengine.h"
#include <utils/qtcassert.h>
#include <utils/savedaction.h>
-#include <QtCore/QAbstractTableModel>
#include <QtCore/QDebug>
#include <QtCore/QFileInfo>
-
namespace Debugger {
namespace Internal {
@@ -54,21 +52,20 @@ namespace Internal {
//
////////////////////////////////////////////////////////////////////////
-StackHandler::StackHandler(DebuggerEngine *engine)
+StackHandler::StackHandler()
: m_positionIcon(QIcon(QLatin1String(":/debugger/images/location_16.png"))),
m_emptyIcon(QIcon(QLatin1String(":/debugger/images/debugger_empty_14.png")))
{
- m_engine = engine;
- m_disassemblerViewAgent = new DisassemblerViewAgent(engine);
+ m_resetLocationScheduled = false;
+ m_contentsValid = false;
m_currentIndex = 0;
m_canExpand = false;
- connect(theDebuggerAction(OperateByInstruction), SIGNAL(triggered()),
+ connect(debuggerCore()->action(OperateByInstruction), SIGNAL(triggered()),
this, SLOT(resetModel()));
}
StackHandler::~StackHandler()
{
- delete m_disassemblerViewAgent;
}
int StackHandler::rowCount(const QModelIndex &parent) const
@@ -84,17 +81,6 @@ int StackHandler::columnCount(const QModelIndex &parent) const
QVariant StackHandler::data(const QModelIndex &index, int role) const
{
- switch (role) {
- case EngineStateRole:
- return m_engine->state();
-
- case EngineCapabilitiesRole:
- return m_engine->debuggerCapabilities();
-
- case EngineActionsEnabledRole:
- return m_engine->debuggerActionsEnabled();
- }
-
if (!index.isValid() || index.row() >= m_stackFrames.size() + m_canExpand)
return QVariant();
@@ -119,7 +105,7 @@ QVariant StackHandler::data(const QModelIndex &index, int role) const
case 2: // File name
return frame.file.isEmpty() ? frame.from : QFileInfo(frame.file).fileName();
case 3: // Line number
- return frame.line;
+ return frame.line >= 0 ? QVariant(frame.line) : QVariant();
case 4: // Address
if (frame.address)
return QString::fromAscii("0x%1").arg(frame.address, 0, 16);
@@ -130,12 +116,10 @@ QVariant StackHandler::data(const QModelIndex &index, int role) const
if (role == Qt::DecorationRole && index.column() == 0) {
// Return icon that indicates whether this is the active stack frame
- return (index.row() == m_currentIndex) ? m_positionIcon : m_emptyIcon;
+ return (m_contentsValid && index.row() == m_currentIndex)
+ ? m_positionIcon : m_emptyIcon;
}
- if (role == StackFrameAddressRole)
- return frame.address;
-
if (role == Qt::ToolTipRole)
return frame.toToolTip();
@@ -143,29 +127,6 @@ QVariant StackHandler::data(const QModelIndex &index, int role) const
}
-bool StackHandler::setData(const QModelIndex &index, const QVariant &value, int role)
-{
- switch (role) {
- case RequestReloadFullStackRole:
- case RequestActivateFrameRole:
- m_engine->handleCommand(role, value);
- return true;
-
- case RequestShowMemoryRole:
- (void) new MemoryViewAgent(m_engine, value.toString());
- return true;
-
- case RequestShowDisassemblerRole: {
- const StackFrame &frame = m_stackFrames.at(value.toInt());
- m_disassemblerViewAgent->setFrame(frame);
- return true;
- }
-
- default:
- return QAbstractTableModel::setData(index, value, role);
- }
-}
-
QVariant StackHandler::headerData(int section, Qt::Orientation orient, int role) const
{
if (orient == Qt::Horizontal && role == Qt::DisplayRole) {
@@ -188,8 +149,9 @@ Qt::ItemFlags StackHandler::flags(const QModelIndex &index) const
return QAbstractTableModel::flags(index);
const StackFrame &frame = m_stackFrames.at(index.row());
const bool isValid = (frame.isUsable() && !frame.function.isEmpty())
- || theDebuggerBoolSetting(OperateByInstruction);
- return isValid ? QAbstractTableModel::flags(index) : Qt::ItemFlags(0);
+ || debuggerCore()->boolSetting(OperateByInstruction);
+ return isValid && m_contentsValid
+ ? QAbstractTableModel::flags(index) : Qt::ItemFlags(0);
}
StackFrame StackHandler::currentFrame() const
@@ -224,6 +186,8 @@ void StackHandler::removeAll()
void StackHandler::setFrames(const StackFrames &frames, bool canExpand)
{
+ m_resetLocationScheduled = false;
+ m_contentsValid = true;
m_canExpand = canExpand;
m_stackFrames = frames;
if (m_currentIndex >= m_stackFrames.size())
@@ -236,12 +200,18 @@ const StackFrames &StackHandler::frames() const
return m_stackFrames;
}
-bool StackHandler::isDebuggingDebuggingHelpers() const
+void StackHandler::scheduleResetLocation()
{
- for (int i = m_stackFrames.size(); --i >= 0; )
- if (m_stackFrames.at(i).function.startsWith(QLatin1String("qDumpObjectData")))
- return true;
- return false;
+ m_resetLocationScheduled = true;
+ m_contentsValid = false;
+}
+
+void StackHandler::resetLocation()
+{
+ if (m_resetLocationScheduled) {
+ m_resetLocationScheduled = false;
+ reset();
+ }
}
} // namespace Internal
diff --git a/src/plugins/debugger/stackhandler.h b/src/plugins/debugger/stackhandler.h
index 89481040d4..65bf0e821a 100644
--- a/src/plugins/debugger/stackhandler.h
+++ b/src/plugins/debugger/stackhandler.h
@@ -37,20 +37,13 @@
#include "stackframe.h"
#include <QtCore/QAbstractItemModel>
-#include <QtCore/QObject>
-
-#include <QtGui/QIcon>
namespace Debugger {
-class DebuggerEngine;
-
namespace Internal {
-class DisassemblerViewAgent;
-
////////////////////////////////////////////////////////////////////////
//
-// StackModel
+// StackCookie
//
////////////////////////////////////////////////////////////////////////
@@ -75,7 +68,7 @@ class StackHandler : public QAbstractTableModel
Q_OBJECT
public:
- explicit StackHandler(DebuggerEngine *engine);
+ StackHandler();
~StackHandler();
void setFrames(const StackFrames &frames, bool canExpand = false);
@@ -83,31 +76,33 @@ public:
void setCurrentIndex(int index);
int currentIndex() const { return m_currentIndex; }
StackFrame currentFrame() const;
+ const StackFrame &frameAt(int index) const { return m_stackFrames.at(index); }
int stackSize() const { return m_stackFrames.size(); }
quint64 topAddress() const { return m_stackFrames.at(0).address; }
// Called from StackHandler after a new stack list has been received
void removeAll();
QAbstractItemModel *model() { return this; }
- bool isDebuggingDebuggingHelpers() const;
+ bool isContentsValid() const { return m_contentsValid; }
+ void scheduleResetLocation();
+ void resetLocation();
private:
// QAbstractTableModel
int rowCount(const QModelIndex &parent) const;
int columnCount(const QModelIndex &parent) const;
QVariant data(const QModelIndex &index, int role) const;
- bool setData(const QModelIndex &index, const QVariant &, int role);
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
Q_SLOT void resetModel() { reset(); }
- DebuggerEngine *m_engine;
- DisassemblerViewAgent *m_disassemblerViewAgent;
StackFrames m_stackFrames;
int m_currentIndex;
const QVariant m_positionIcon;
const QVariant m_emptyIcon;
bool m_canExpand;
+ bool m_resetLocationScheduled;
+ bool m_contentsValid;
};
} // namespace Internal
diff --git a/src/plugins/debugger/stackwindow.cpp b/src/plugins/debugger/stackwindow.cpp
index 23550238bf..ad97a8c58e 100644
--- a/src/plugins/debugger/stackwindow.cpp
+++ b/src/plugins/debugger/stackwindow.cpp
@@ -32,37 +32,39 @@
**************************************************************************/
#include "stackwindow.h"
-#include "stackframe.h"
+#include "stackhandler.h"
#include "debuggeractions.h"
#include "debuggerconstants.h"
+#include "debuggercore.h"
+#include "debuggerengine.h"
#include <utils/qtcassert.h>
#include <utils/savedaction.h>
#include <QtCore/QDebug>
-#include <QtGui/QAction>
#include <QtGui/QApplication>
#include <QtGui/QClipboard>
-#include <QtGui/QComboBox>
#include <QtGui/QHeaderView>
#include <QtGui/QMenu>
#include <QtGui/QResizeEvent>
-#include <QtGui/QTreeView>
-#include <QtGui/QVBoxLayout>
-
namespace Debugger {
namespace Internal {
+static DebuggerEngine *currentEngine()
+{
+ return debuggerCore()->currentEngine();
+}
+
StackWindow::StackWindow(QWidget *parent)
: QTreeView(parent), m_alwaysResizeColumnsToContents(false)
{
setAttribute(Qt::WA_MacShowFocusRect, false);
setFrameStyle(QFrame::NoFrame);
- QAction *act = theDebuggerAction(UseAlternatingRowColors);
+ QAction *act = debuggerCore()->action(UseAlternatingRowColors);
setWindowTitle(tr("Stack"));
setAlternatingRowColors(act->isChecked());
@@ -70,23 +72,18 @@ StackWindow::StackWindow(QWidget *parent)
setIconSize(QSize(10, 10));
header()->setDefaultAlignment(Qt::AlignLeft);
- header()->resizeSection(0, 60);
- header()->resizeSection(3, 60);
connect(this, SIGNAL(activated(QModelIndex)),
- this, SLOT(rowActivated(QModelIndex)));
+ SLOT(rowActivated(QModelIndex)));
connect(act, SIGNAL(toggled(bool)),
- this, SLOT(setAlternatingRowColorsHelper(bool)));
- connect(theDebuggerAction(UseAddressInStackView), SIGNAL(toggled(bool)),
- this, SLOT(showAddressColumn(bool)));
- connect(theDebuggerAction(ExpandStack), SIGNAL(triggered()),
- this, SLOT(reloadFullStack()));
- connect(theDebuggerAction(MaximalStackDepth), SIGNAL(triggered()),
- this, SLOT(reloadFullStack()));
-}
-
-StackWindow::~StackWindow()
-{
+ SLOT(setAlternatingRowColorsHelper(bool)));
+ connect(debuggerCore()->action(UseAddressInStackView), SIGNAL(toggled(bool)),
+ SLOT(showAddressColumn(bool)));
+ connect(debuggerCore()->action(ExpandStack), SIGNAL(triggered()),
+ SLOT(reloadFullStack()));
+ connect(debuggerCore()->action(MaximalStackDepth), SIGNAL(triggered()),
+ SLOT(reloadFullStack()));
+ showAddressColumn(false);
}
void StackWindow::showAddressColumn(bool on)
@@ -96,23 +93,37 @@ void StackWindow::showAddressColumn(bool on)
void StackWindow::rowActivated(const QModelIndex &index)
{
- setModelData(RequestActivateFrameRole, index.row());
+ currentEngine()->activateFrame(index.row());
+}
+
+void StackWindow::setModel(QAbstractItemModel *model)
+{
+ QTreeView::setModel(model);
+ //resizeColumnsToContents();
+ resizeColumnToContents(0);
+ resizeColumnToContents(3);
}
void StackWindow::contextMenuEvent(QContextMenuEvent *ev)
{
+ DebuggerEngine *engine = currentEngine();
+ StackHandler *handler = engine->stackHandler();
const QModelIndex index = indexAt(ev->pos());
- const quint64 address = modelData(StackFrameAddressRole, index).toULongLong();
- const unsigned engineCapabilities = modelData(EngineCapabilitiesRole).toUInt();
+ const int row = index.row();
+ const unsigned engineCapabilities = engine->debuggerCapabilities();
+ StackFrame frame;
+ if (row >= 0 && row < handler->stackSize())
+ frame = handler->frameAt(row);
+ const quint64 address = frame.address;
QMenu menu;
- menu.addAction(theDebuggerAction(ExpandStack));
+ menu.addAction(debuggerCore()->action(ExpandStack));
QAction *actCopyContents = menu.addAction(tr("Copy Contents to Clipboard"));
actCopyContents->setEnabled(model() != 0);
if (engineCapabilities & CreateFullBacktraceCapability)
- menu.addAction(theDebuggerAction(CreateFullBacktrace));
+ menu.addAction(debuggerCore()->action(CreateFullBacktrace));
QAction *actShowMemory = menu.addAction(QString());
if (address == 0) {
@@ -134,9 +145,9 @@ void StackWindow::contextMenuEvent(QContextMenuEvent *ev)
menu.addSeparator();
#if 0 // @TODO: not implemented
- menu.addAction(theDebuggerAction(UseToolTipsInStackView));
+ menu.addAction(debuggerCore()->action(UseToolTipsInStackView));
#endif
- menu.addAction(theDebuggerAction(UseAddressInStackView));
+ menu.addAction(debuggerCore()->action(UseAddressInStackView));
QAction *actAdjust = menu.addAction(tr("Adjust Column Widths to Contents"));
@@ -147,7 +158,7 @@ void StackWindow::contextMenuEvent(QContextMenuEvent *ev)
menu.addSeparator();
- menu.addAction(theDebuggerAction(SettingsDialog));
+ menu.addAction(debuggerCore()->action(SettingsDialog));
QAction *act = menu.exec(ev->globalPos());
@@ -158,9 +169,9 @@ void StackWindow::contextMenuEvent(QContextMenuEvent *ev)
else if (act == actAlwaysAdjust)
setAlwaysResizeColumnsToContents(!m_alwaysResizeColumnsToContents);
else if (act == actShowMemory)
- setModelData(RequestShowMemoryRole, address);
+ engine->openMemoryView(address);
else if (act == actShowDisassembler)
- setModelData(RequestShowDisassemblerRole, index.row());
+ engine->openDisassemblerView(frame);
}
void StackWindow::copyContentsToClipboard()
@@ -185,7 +196,7 @@ void StackWindow::copyContentsToClipboard()
void StackWindow::reloadFullStack()
{
- setModelData(RequestReloadFullStackRole);
+ currentEngine()->reloadFullStack();
}
void StackWindow::resizeColumnsToContents()
@@ -203,19 +214,5 @@ void StackWindow::setAlwaysResizeColumnsToContents(bool on)
header()->setResizeMode(i, mode);
}
-void StackWindow::setModelData
- (int role, const QVariant &value, const QModelIndex &index)
-{
- QTC_ASSERT(model(), return);
- model()->setData(index, value, role);
-}
-
-QVariant StackWindow::modelData(int role, const QModelIndex &index)
-{
- QTC_ASSERT(model(), return QVariant());
- return model()->data(index, role);
-}
-
-
} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/stackwindow.h b/src/plugins/debugger/stackwindow.h
index b8d7460c37..d5dd8187f8 100644
--- a/src/plugins/debugger/stackwindow.h
+++ b/src/plugins/debugger/stackwindow.h
@@ -45,7 +45,6 @@ class StackWindow : public QTreeView
public:
explicit StackWindow(QWidget *parent = 0);
- ~StackWindow();
public slots:
void resizeColumnsToContents();
@@ -58,13 +57,10 @@ private slots:
void reloadFullStack();
private:
+ void setModel(QAbstractItemModel *model);
void contextMenuEvent(QContextMenuEvent *ev);
void copyContentsToClipboard();
- void setModelData(int role, const QVariant &value = QVariant(),
- const QModelIndex &index = QModelIndex());
- QVariant modelData(int role, const QModelIndex &index = QModelIndex());
-
bool m_alwaysResizeColumnsToContents;
};
diff --git a/src/plugins/debugger/startremotedialog.ui b/src/plugins/debugger/startremotedialog.ui
index fe83dd259f..f02da26c86 100644
--- a/src/plugins/debugger/startremotedialog.ui
+++ b/src/plugins/debugger/startremotedialog.ui
@@ -6,25 +6,16 @@
<rect>
<x>0</x>
<y>0</y>
- <width>439</width>
- <height>224</height>
+ <width>446</width>
+ <height>269</height>
</rect>
</property>
<property name="windowTitle">
<string>Start Debugger</string>
</property>
- <layout class="QVBoxLayout">
- <property name="spacing">
- <number>6</number>
- </property>
- <property name="margin">
- <number>9</number>
- </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QFormLayout" name="formLayout">
- <property name="fieldGrowthPolicy">
- <enum>QFormLayout::ExpandingFieldsGrow</enum>
- </property>
<item row="0" column="0">
<widget class="QLabel" name="debuggerLabel">
<property name="text">
@@ -74,33 +65,47 @@
</widget>
</item>
<item row="4" column="0">
+ <widget class="QLabel" name="gnuTargetLabel">
+ <property name="text">
+ <string>GNU target</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QComboBox" name="gnuTargetComboBox">
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0">
<widget class="QLabel" name="sysrootLabel">
<property name="text">
<string>Sysroot:</string>
</property>
</widget>
</item>
- <item row="4" column="1">
+ <item row="5" column="1">
<widget class="Utils::PathChooser" name="sysrootPathChooser" native="true"/>
</item>
- <item row="5" column="0">
+ <item row="6" column="0">
<widget class="QLabel" name="useServerStartScriptLabel">
<property name="text">
<string>Use server start script:</string>
</property>
</widget>
</item>
- <item row="5" column="1">
+ <item row="6" column="1">
<widget class="QCheckBox" name="useServerStartScriptCheckBox"/>
</item>
- <item row="6" column="0">
+ <item row="7" column="0">
<widget class="QLabel" name="serverStartScriptLabel">
<property name="text">
<string>Server start script:</string>
</property>
</widget>
</item>
- <item row="6" column="1">
+ <item row="7" column="1">
<widget class="Utils::PathChooser" name="serverStartScript" native="true"/>
</item>
</layout>
diff --git a/src/plugins/debugger/startremoteenginedialog.ui b/src/plugins/debugger/startremoteenginedialog.ui
new file mode 100644
index 0000000000..ff7fc66936
--- /dev/null
+++ b/src/plugins/debugger/startremoteenginedialog.ui
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>StartRemoteEngineDialog</class>
+ <widget class="QDialog" name="StartRemoteEngineDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>884</width>
+ <height>601</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Start Remote Engine</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="channelLabel">
+ <property name="text">
+ <string>Host:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="0" colspan="4">
+ <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>
+ <item row="3" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Engine path:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Inferior path:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="2">
+ <widget class="QLineEdit" name="inferiorpath"/>
+ </item>
+ <item row="3" column="2">
+ <widget class="QLineEdit" name="enginepath"/>
+ </item>
+ <item row="0" column="2">
+ <widget class="QLineEdit" name="host">
+ <property name="text">
+ <string notr="true"/>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2">
+ <widget class="QLineEdit" name="password">
+ <property name="echoMode">
+ <enum>QLineEdit::Password</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QLineEdit" name="username"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Username:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Password:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="1" colspan="2">
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <tabstops>
+ <tabstop>host</tabstop>
+ <tabstop>username</tabstop>
+ <tabstop>password</tabstop>
+ <tabstop>enginepath</tabstop>
+ <tabstop>inferiorpath</tabstop>
+ <tabstop>buttonBox</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/plugins/debugger/tcf/json.h b/src/plugins/debugger/tcf/json.h
index 0d6b215cde..3daf594b0c 100644
--- a/src/plugins/debugger/tcf/json.h
+++ b/src/plugins/debugger/tcf/json.h
@@ -55,7 +55,7 @@ public:
String,
Number,
Object,
- Array,
+ Array
};
Type m_type;
@@ -99,6 +99,6 @@ private:
} // namespace Internal
} // namespace Debugger
-//Q_DECLARE_METATYPE(GdbDebugger::Internal::JsonValue);
+//Q_DECLARE_METATYPE(GdbDebugger::Internal::JsonValue)
#endif // DEBUGGER_JSON_H
diff --git a/src/plugins/debugger/tcf/tcfengine.h b/src/plugins/debugger/tcf/tcfengine.h
index 47e3771bb0..3545e8d607 100644
--- a/src/plugins/debugger/tcf/tcfengine.h
+++ b/src/plugins/debugger/tcf/tcfengine.h
@@ -96,8 +96,10 @@ private:
void selectThread(int index);
void attemptBreakpointSynchronization();
+ bool acceptsBreakpoint(BreakpointId) const { return false; }
- void assignValueInDebugger(const Internal::WatchData *w, const QString &expr, const QVariant &value);
+ void assignValueInDebugger(const WatchData *data,
+ const QString &expr, const QVariant &value);
void executeDebuggerCommand(const QString &command);
void loadSymbols(const QString &moduleName);
diff --git a/src/plugins/debugger/threaddata.h b/src/plugins/debugger/threaddata.h
new file mode 100644
index 0000000000..9c81fe1c49
--- /dev/null
+++ b/src/plugins/debugger/threaddata.h
@@ -0,0 +1,94 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 THREADDATA_H
+#define THREADDATA_H
+
+#include <QtCore/QList>
+
+namespace Debugger {
+
+namespace Internal {
+
+////////////////////////////////////////////////////////////////////////
+//
+// ThreadData
+//
+////////////////////////////////////////////////////////////////////////
+
+/*! A structure containing information about a single thread */
+struct ThreadData
+{
+ ThreadData(quint64 threadid = 0)
+ : id(threadid), frameLevel(-1), address (0), lineNumber(-1)
+ {}
+
+ enum {
+ IdColumn,
+ AddressColumn,
+ FunctionColumn,
+ FileColumn,
+ LineColumn,
+ StateColumn,
+ NameColumn,
+ CoreColumn,
+ ColumnCount = CoreColumn
+ };
+
+ void notifyRunning() // Clear state information.
+ {
+ address = 0;
+ function.clear();
+ fileName.clear();
+ frameLevel = -1;
+ state.clear();
+ lineNumber = -1;
+ }
+
+ // Permanent data.
+ quint64 id;
+ QString targetId;
+ QString core;
+
+ // State information when stopped.
+ qint32 frameLevel;
+ quint64 address;
+ QString function;
+ QString fileName;
+ QString state;
+ qint32 lineNumber;
+ QString name;
+};
+
+typedef QVector<ThreadData> Threads;
+
+} // namespace Internal
+} // namespace Debugger
+
+#endif // THREADDATA_H
diff --git a/src/plugins/debugger/threadshandler.cpp b/src/plugins/debugger/threadshandler.cpp
index f8c2db1f3c..c77546852f 100644
--- a/src/plugins/debugger/threadshandler.cpp
+++ b/src/plugins/debugger/threadshandler.cpp
@@ -32,9 +32,9 @@
**************************************************************************/
#include "threadshandler.h"
+#include "gdb/gdbmi.h"
#include "debuggerconstants.h"
-#include "debuggerengine.h"
#include <QtCore/QDebug>
#include <QtCore/QTextStream>
@@ -48,48 +48,30 @@ namespace Internal {
//
///////////////////////////////////////////////////////////////////////
-ThreadData::ThreadData(int threadId)
+static QString threadToolTip(const ThreadData &thread)
{
- notifyRunning();
- id = threadId;
-}
-
-void ThreadData::notifyRunning()
-{
- address = 0;
- function.clear();
- fileName.clear();
- frameLevel = -1;
- state.clear();
- lineNumber = -1;
-}
-
-static inline QString threadToolTip(const ThreadData &thread)
-{
- const char tableRowStartC[] = "<tr><td>";
- const char tableRowSeparatorC[] = "</td><td>";
- const char tableRowEndC[] = "</td>";
+ const char start[] = "<tr><td>";
+ const char sep[] = "</td><td>";
+ const char end[] = "</td>";
QString rc;
QTextStream str(&rc);
str << "<html><head/><body><table>"
- << tableRowStartC << ThreadsHandler::tr("Thread&nbsp;id:")
- << tableRowSeparatorC << thread.id << tableRowEndC;
+ << start << ThreadsHandler::tr("Thread&nbsp;id:")
+ << sep << thread.id << end;
if (!thread.targetId.isEmpty())
- str << tableRowStartC << ThreadsHandler::tr("Target&nbsp;id:")
- << tableRowSeparatorC << thread.targetId << tableRowEndC;
+ str << start << ThreadsHandler::tr("Target&nbsp;id:")
+ << sep << thread.targetId << end;
if (!thread.name.isEmpty())
- str << tableRowStartC << ThreadsHandler::tr("Name:")
- << tableRowSeparatorC << thread.name << tableRowEndC;
+ str << start << ThreadsHandler::tr("Name:")
+ << sep << thread.name << end;
if (!thread.state.isEmpty())
- str << tableRowStartC << ThreadsHandler::tr("State:")
- << tableRowSeparatorC << thread.state << tableRowEndC;
+ str << start << ThreadsHandler::tr("State:")
+ << sep << thread.state << end;
if (!thread.core.isEmpty())
- str << tableRowStartC << ThreadsHandler::tr("Core:")
- << tableRowSeparatorC << thread.core << tableRowEndC;
-
+ str << start << ThreadsHandler::tr("Core:")
+ << sep << thread.core << end;
if (thread.address) {
- str << tableRowStartC << ThreadsHandler::tr("Stopped&nbsp;at:")
- << tableRowSeparatorC;
+ str << start << ThreadsHandler::tr("Stopped&nbsp;at:") << sep;
if (!thread.function.isEmpty())
str << thread.function << "<br>";
if (!thread.fileName.isEmpty())
@@ -108,9 +90,8 @@ static inline QString threadToolTip(const ThreadData &thread)
//
///////////////////////////////////////////////////////////////////////
-ThreadsHandler::ThreadsHandler(DebuggerEngine *engine)
- : m_engine(engine),
- m_currentIndex(0),
+ThreadsHandler::ThreadsHandler()
+ : m_currentIndex(0),
m_positionIcon(QLatin1String(":/debugger/images/location_16.png")),
m_emptyIcon(QLatin1String(":/debugger/images/debugger_empty_14.png"))
{
@@ -118,7 +99,7 @@ ThreadsHandler::ThreadsHandler(DebuggerEngine *engine)
int ThreadsHandler::rowCount(const QModelIndex &parent) const
{
- // Since the stack is not a tree, row count is 0 for any valid parent
+ // Since the stack is not a tree, row count is 0 for any valid parent.
return parent.isValid() ? 0 : m_threads.size();
}
@@ -157,14 +138,14 @@ QVariant ThreadsHandler::data(const QModelIndex &index, int role) const
case ThreadData::StateColumn:
return thread.state;
case ThreadData::NameColumn:
- if (thread.name.isEmpty())
- return thread.id;
- return thread.name;
+ if (!thread.name.isEmpty())
+ return thread.name;
+ return thread.id;
}
case Qt::ToolTipRole:
return threadToolTip(thread);
case Qt::DecorationRole:
- // Return icon that indicates whether this is the active stack frame
+ // Return icon that indicates whether this is the active stack frame.
if (index.column() == 0)
return (index.row() == m_currentIndex) ? m_positionIcon : m_emptyIcon;
break;
@@ -200,16 +181,6 @@ QVariant ThreadsHandler::headerData
return QVariant();
}
-bool ThreadsHandler::setData
- (const QModelIndex &index, const QVariant &value, int role)
-{
- if (role == RequestSelectThreadRole) {
- m_engine->selectThread(value.toInt());
- return true;
- }
- return QAbstractTableModel::setData(index, value, role);
-}
-
int ThreadsHandler::currentThreadId() const
{
if (m_currentIndex < 0 || m_currentIndex >= m_threads.size())
@@ -222,7 +193,7 @@ void ThreadsHandler::setCurrentThread(int index)
if (index == m_currentIndex)
return;
- // Emit changed for previous frame
+ // Emit changed for previous frame.
QModelIndex i = ThreadsHandler::index(m_currentIndex, 0);
emit dataChanged(i, i);
@@ -243,10 +214,10 @@ void ThreadsHandler::setCurrentThreadId(int id)
}
}
-int ThreadsHandler::indexOf(int threadId) const
+int ThreadsHandler::indexOf(quint64 threadId) const
{
const int count = m_threads.size();
- for(int i = 0; i < count; i++)
+ for (int i = 0; i < count; ++i)
if (m_threads.at(i).id == threadId)
return i;
return -1;
@@ -286,5 +257,37 @@ void ThreadsHandler::notifyRunning()
index(m_threads.size() - 1, ThreadData::ColumnCount - 1));
}
+Threads ThreadsHandler::parseGdbmiThreads(const GdbMi &data, int *currentThread)
+{
+ // ^done,threads=[{id="1",target-id="Thread 0xb7fdc710 (LWP 4264)",
+ // frame={level="0",addr="0x080530bf",func="testQString",args=[],
+ // file="/.../app.cpp",fullname="/../app.cpp",line="1175"},
+ // state="stopped",core="0"}],current-thread-id="1"
+ const QList<GdbMi> items = data.findChild("threads").children();
+ const int n = items.size();
+ Threads threads;
+ threads.reserve(n);
+ for (int index = 0; index != n; ++index) {
+ bool ok = false;
+ const GdbMi item = items.at(index);
+ const GdbMi frame = item.findChild("frame");
+ ThreadData thread;
+ thread.id = item.findChild("id").data().toInt();
+ thread.targetId = QString::fromAscii(item.findChild("target-id").data());
+ thread.core = QString::fromLatin1(item.findChild("core").data());
+ thread.state = QString::fromLatin1(item.findChild("state").data());
+ thread.address = frame.findChild("addr").data().toULongLong(&ok, 0);
+ thread.function = QString::fromLatin1(frame.findChild("func").data());
+ thread.fileName = QString::fromLatin1(frame.findChild("fullname").data());
+ thread.lineNumber = frame.findChild("line").data().toInt();
+ // Non-GDB (Cdb2) output name here.
+ thread.name = QString::fromLatin1(frame.findChild("name").data());
+ threads.append(thread);
+ }
+ if (currentThread)
+ *currentThread = data.findChild("current-thread-id").data().toInt();
+ return threads;
+}
+
} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/threadshandler.h b/src/plugins/debugger/threadshandler.h
index ee4acdc5f8..1a36b412b3 100644
--- a/src/plugins/debugger/threadshandler.h
+++ b/src/plugins/debugger/threadshandler.h
@@ -39,55 +39,11 @@
#include <QtGui/QIcon>
+#include "threaddata.h"
namespace Debugger {
-class DebuggerEngine;
-
namespace Internal {
-
-////////////////////////////////////////////////////////////////////////
-//
-// ThreadData
-//
-////////////////////////////////////////////////////////////////////////
-
-/*! A structure containing information about a single thread */
-struct ThreadData
-{
- ThreadData(int threadId = 0);
-
- enum {
- IdColumn,
- AddressColumn,
- FunctionColumn,
- FileColumn,
- LineColumn,
- StateColumn,
- NameColumn,
- CoreColumn,
- ColumnCount = CoreColumn
- };
-
- // Permanent data.
- int id;
- QString targetId;
- QString core;
-
- // State information when stopped
- void notifyRunning(); // Clear state information
-
- int frameLevel;
- quint64 address;
- QString function;
- QString fileName;
- QString state;
- int lineNumber;
- QString name;
-};
-
-typedef QVector<ThreadData> Threads;
-
-
+class GdbMi;
////////////////////////////////////////////////////////////////////////
//
// ThreadsHandler
@@ -100,15 +56,14 @@ class ThreadsHandler : public QAbstractTableModel
Q_OBJECT
public:
- explicit ThreadsHandler(DebuggerEngine *engine);
+ ThreadsHandler();
int currentThread() const { return m_currentIndex; }
void setCurrentThread(int index);
int currentThreadId() const;
void setCurrentThreadId(int id);
- int indexOf(int threadId) const;
+ int indexOf(quint64 threadId) const;
- void selectThread(int index);
void setThreads(const Threads &threads);
void removeAll();
Threads threads() const;
@@ -117,16 +72,15 @@ public:
// Clear out all frame information
void notifyRunning();
+ static Threads parseGdbmiThreads(const GdbMi &data, int *currentThread = 0);
+
private:
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
- bool setData(const QModelIndex &index, const QVariant &value, int role);
QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const;
-private:
- DebuggerEngine *m_engine;
Threads m_threads;
int m_currentIndex;
const QIcon m_positionIcon;
diff --git a/src/plugins/debugger/threadswindow.cpp b/src/plugins/debugger/threadswindow.cpp
index f331cd4dac..edee696797 100644
--- a/src/plugins/debugger/threadswindow.cpp
+++ b/src/plugins/debugger/threadswindow.cpp
@@ -33,24 +33,26 @@
#include "threadswindow.h"
+#include "threadshandler.h"
#include "debuggeractions.h"
#include "debuggerconstants.h"
+#include "debuggercore.h"
+#include "debuggerengine.h"
#include <utils/savedaction.h>
-#include <QtGui/QAction>
+#include <QtCore/QDebug>
#include <QtGui/QContextMenuEvent>
#include <QtGui/QHeaderView>
#include <QtGui/QMenu>
-
namespace Debugger {
namespace Internal {
ThreadsWindow::ThreadsWindow(QWidget *parent)
: QTreeView(parent), m_alwaysResizeColumnsToContents(false)
{
- QAction *act = theDebuggerAction(UseAlternatingRowColors);
+ QAction *act = debuggerCore()->action(UseAlternatingRowColors);
setAttribute(Qt::WA_MacShowFocusRect, false);
setFrameStyle(QFrame::NoFrame);
@@ -69,7 +71,15 @@ ThreadsWindow::ThreadsWindow(QWidget *parent)
void ThreadsWindow::rowActivated(const QModelIndex &index)
{
- selectThread(index.row());
+ debuggerCore()->currentEngine()->selectThread(index.row());
+}
+
+void ThreadsWindow::setModel(QAbstractItemModel *model)
+{
+ QTreeView::setModel(model);
+ resizeColumnToContents(0); // Id
+ resizeColumnToContents(4); // Line
+ resizeColumnToContents(6); // Name
}
void ThreadsWindow::contextMenuEvent(QContextMenuEvent *ev)
@@ -83,7 +93,7 @@ void ThreadsWindow::contextMenuEvent(QContextMenuEvent *ev)
alwaysAdjustColumnAction->setChecked(m_alwaysResizeColumnsToContents);
menu.addSeparator();
- menu.addAction(theDebuggerAction(SettingsDialog));
+ menu.addAction(debuggerCore()->action(SettingsDialog));
QAction *act = menu.exec(ev->globalPos());
if (!act)
@@ -111,10 +121,5 @@ void ThreadsWindow::setAlwaysResizeColumnsToContents(bool on)
header()->setResizeMode(0, mode);
}
-void ThreadsWindow::selectThread(int index)
-{
- model()->setData(QModelIndex(), index, RequestSelectThreadRole);
-}
-
} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/threadswindow.h b/src/plugins/debugger/threadswindow.h
index 4b9c7a0967..06b0ea9431 100644
--- a/src/plugins/debugger/threadswindow.h
+++ b/src/plugins/debugger/threadswindow.h
@@ -49,13 +49,13 @@ public:
public slots:
void resizeColumnsToContents();
void setAlwaysResizeColumnsToContents(bool on);
- void selectThread(int index);
private slots:
void rowActivated(const QModelIndex &index);
void setAlternatingRowColorsHelper(bool on) { setAlternatingRowColors(on); }
private:
+ void setModel(QAbstractItemModel *model);
void contextMenuEvent(QContextMenuEvent *ev);
bool m_alwaysResizeColumnsToContents;
diff --git a/src/plugins/debugger/watchdata.cpp b/src/plugins/debugger/watchdata.cpp
index b21d1609f6..ecd03e2a2d 100644
--- a/src/plugins/debugger/watchdata.cpp
+++ b/src/plugins/debugger/watchdata.cpp
@@ -1,13 +1,8 @@
-
#include "watchdata.h"
-#include "watchutils.h"
#include <QtCore/QTextStream>
#include <QtCore/QDebug>
-#include <QtGui/QApplication>
-#include <QtGui/QTextDocument> // Qt::escape
-
////////////////////////////////////////////////////////////////////
//
// WatchData
@@ -17,19 +12,107 @@
namespace Debugger {
namespace Internal {
+enum GuessChildrenResult { HasChildren, HasNoChildren, HasPossiblyChildren };
+static QString qt_escape(const QString& plain)
+{
+ QString rich;
+ rich.reserve(int(plain.length() * 1.1));
+ for (int i = 0; i < plain.length(); ++i) {
+ if (plain.at(i) == QLatin1Char('<'))
+ rich += QLatin1String("&lt;");
+ else if (plain.at(i) == QLatin1Char('>'))
+ rich += QLatin1String("&gt;");
+ else if (plain.at(i) == QLatin1Char('&'))
+ rich += QLatin1String("&amp;");
+ else if (plain.at(i) == QLatin1Char('"'))
+ rich += QLatin1String("&quot;");
+ else
+ rich += plain.at(i);
+ }
+ return rich;
+}
+
+bool isPointerType(const QByteArray &type)
+{
+ return type.endsWith('*') || type.endsWith("* const");
+}
+
+bool isCharPointerType(const QByteArray &type)
+{
+ return type == "char *" || type == "const char *" || type == "char const *";
+}
+
+bool isIntType(const QByteArray &type)
+{
+ if (type.isEmpty())
+ return false;
+ switch (type.at(0)) {
+ case 'b':
+ return type == "bool";
+ case 'c':
+ return type == "char";
+ case 'i':
+ return type == "int" || type == "int64";
+ case 'l':
+ return type == "long"
+ || type == "long long";
+ case 'p':
+ return type == "ptrdiff_t";
+ case 'q':
+ return type == "qint16" || type == "quint16"
+ || type == "qint32" || type == "quint32"
+ || type == "qint64" || type == "quint64";
+ case 's':
+ return type == "short"
+ || type == "signed"
+ || type == "size_t"
+ || type == "std::size_t"
+ || type == "std::ptrdiff_t"
+ || type.startsWith("signed ");
+ case 'u':
+ return type == "unsigned"
+ || type.startsWith("unsigned ");
+ default:
+ return false;
+ }
+}
+
+bool isFloatType(const QByteArray &type)
+{
+ return type == "float" || type == "double" || type == "qreal";
+}
+
+bool isIntOrFloatType(const QByteArray &type)
+{
+ return isIntType(type) || isFloatType(type);
+}
+
+GuessChildrenResult guessChildren(const QByteArray &type)
+{
+ if (isIntOrFloatType(type))
+ return HasNoChildren;
+ if (isCharPointerType(type))
+ return HasNoChildren;
+ if (isPointerType(type))
+ return HasChildren;
+ if (type.endsWith("QString"))
+ return HasNoChildren;
+ return HasPossiblyChildren;
+}
+
WatchData::WatchData() :
+ id(0),
+ state(InitialState),
editformat(0),
address(0),
- hasChildren(false),
generation(-1),
+ hasChildren(false),
valueEnabled(true),
valueEditable(true),
error(false),
- source(0),
- objectId(0),
- state(InitialState),
changed(false),
- sortId(0)
+ sortId(0),
+ source(0)
{
}
@@ -45,7 +128,6 @@ bool WatchData::isEqual(const WatchData &other) const
&& displayedType == other.displayedType
&& variable == other.variable
&& address == other.address
- && framekey == other.framekey
&& hasChildren == other.hasChildren
&& valueEnabled == other.valueEnabled
&& valueEditable == other.valueEditable
@@ -213,8 +295,6 @@ QString WatchData::toString() const
if (isChildrenNeeded())
str << "children=<needed>,";
- if (source)
- str << "source=" << source;
str.flush();
if (res.endsWith(QLatin1Char(',')))
res.truncate(res.size() - 1);
@@ -226,7 +306,7 @@ static void formatToolTipRow(QTextStream &str,
const QString &category, const QString &value)
{
str << "<tr><td>" << category << "</td><td> : </td><td>"
- << Qt::escape(value) << "</td></tr>";
+ << qt_escape(value) << "</td></tr>";
}
static QString typeToolTip(const WatchData &wd)
@@ -247,19 +327,19 @@ QString WatchData::toToolTip() const
QString res;
QTextStream str(&res);
str << "<html><body><table>";
- formatToolTipRow(str, QCoreApplication::translate("Debugger::Internal::WatchHandler", "Name"), name);
- formatToolTipRow(str, QCoreApplication::translate("Debugger::Internal::WatchHandler", "Expression"), exp);
- formatToolTipRow(str, QCoreApplication::translate("Debugger::Internal::WatchHandler", "Type"), typeToolTip(*this));
+ formatToolTipRow(str, tr("Name"), name);
+ formatToolTipRow(str, tr("Expression"), exp);
+ formatToolTipRow(str, tr("Type"), typeToolTip(*this));
QString val = value;
if (value.size() > 1000) {
val.truncate(1000);
- val += QCoreApplication::translate("Debugger::Internal::WatchHandler", " ... <cut off>");
+ val += tr(" ... <cut off>");
}
- formatToolTipRow(str, QCoreApplication::translate("Debugger::Internal::WatchHandler", "Value"), val);
- formatToolTipRow(str, QCoreApplication::translate("Debugger::Internal::WatchHandler", "Object Address"),
+ formatToolTipRow(str, tr("Value"), val);
+ formatToolTipRow(str, tr("Object Address"),
QString::fromAscii(hexAddress()));
- formatToolTipRow(str, QCoreApplication::translate("Debugger::Internal::WatchHandler", "Internal ID"), iname);
- formatToolTipRow(str, QCoreApplication::translate("Debugger::Internal::WatchHandler", "Generation"),
+ formatToolTipRow(str, tr("Internal ID"), iname);
+ formatToolTipRow(str, tr("Generation"),
QString::number(generation));
str << "</table></body></html>";
return res;
diff --git a/src/plugins/debugger/watchdata.h b/src/plugins/debugger/watchdata.h
index 760ae189fa..26643225eb 100644
--- a/src/plugins/debugger/watchdata.h
+++ b/src/plugins/debugger/watchdata.h
@@ -36,8 +36,7 @@
#include <QtCore/QMetaType>
#include <QtCore/QtGlobal>
-#include <QtCore/QObject>
-#include <QtScript/QScriptValue>
+#include <QtCore/QCoreApplication>
namespace Debugger {
namespace Internal {
@@ -49,11 +48,11 @@ public:
enum State
{
- Complete = 0,
+ Complete = 0,
HasChildrenNeeded = 1,
- ValueNeeded = 2,
- TypeNeeded = 4,
- ChildrenNeeded = 8,
+ ValueNeeded = 2,
+ TypeNeeded = 4,
+ ChildrenNeeded = 8,
NeededMask = ValueNeeded
| TypeNeeded
@@ -66,87 +65,90 @@ public:
| HasChildrenNeeded
};
- void setValue(const QString &);
- void setType(const QByteArray &, bool guessChildrenFromType = true);
- void setValueToolTip(const QString &);
- void setError(const QString &);
- void setAddress(const quint64 &);
- void setHexAddress(const QByteArray &a);
-
bool isSomethingNeeded() const { return state & NeededMask; }
- void setAllNeeded() { state = NeededMask; }
- void setAllUnneeded() { state = State(0); }
+ void setAllNeeded() { state = NeededMask; }
+ void setAllUnneeded() { state = State(0); }
bool isTypeNeeded() const { return state & TypeNeeded; }
- bool isTypeKnown() const { return !(state & TypeNeeded); }
- void setTypeNeeded() { state = State(state | TypeNeeded); }
- void setTypeUnneeded() { state = State(state & ~TypeNeeded); }
+ bool isTypeKnown() const { return !(state & TypeNeeded); }
+ void setTypeNeeded() { state = State(state | TypeNeeded); }
+ void setTypeUnneeded() { state = State(state & ~TypeNeeded); }
bool isValueNeeded() const { return state & ValueNeeded; }
- bool isValueKnown() const { return !(state & ValueNeeded); }
- void setValueNeeded() { state = State(state | ValueNeeded); }
- void setValueUnneeded() { state = State(state & ~ValueNeeded); }
+ bool isValueKnown() const { return !(state & ValueNeeded); }
+ void setValueNeeded() { state = State(state | ValueNeeded); }
+ void setValueUnneeded() { state = State(state & ~ValueNeeded); }
bool isChildrenNeeded() const { return state & ChildrenNeeded; }
- bool isChildrenKnown() const { return !(state & ChildrenNeeded); }
- void setChildrenNeeded() { state = State(state | ChildrenNeeded); }
+ bool isChildrenKnown() const { return !(state & ChildrenNeeded); }
+ void setChildrenNeeded() { state = State(state | ChildrenNeeded); }
void setChildrenUnneeded() { state = State(state & ~ChildrenNeeded); }
bool isHasChildrenNeeded() const { return state & HasChildrenNeeded; }
- bool isHasChildrenKnown() const { return !(state & HasChildrenNeeded); }
- void setHasChildrenNeeded() { state = State(state | HasChildrenNeeded); }
+ bool isHasChildrenKnown() const { return !(state & HasChildrenNeeded); }
+ void setHasChildrenNeeded() { state = State(state | HasChildrenNeeded); }
void setHasChildrenUnneeded() { state = State(state & ~HasChildrenNeeded); }
- void setHasChildren(bool c) { hasChildren = c; setHasChildrenUnneeded();
- if (!c) setChildrenUnneeded(); }
+ void setHasChildren(bool c) { hasChildren = c; setHasChildrenUnneeded();
+ if (!c) setChildrenUnneeded(); }
- QString toString() const;
- QString toToolTip() const;
- bool isLocal() const { return iname.startsWith("local."); }
+ bool isLocal() const { return iname.startsWith("local."); }
bool isWatcher() const { return iname.startsWith("watch."); }
- bool isValid() const { return !iname.isEmpty(); }
+ bool isValid() const { return !iname.isEmpty(); }
bool isEqual(const WatchData &other) const;
- quint64 coreAddress() const;
- QByteArray hexAddress() const;
+
+ void setError(const QString &);
+ void setValue(const QString &);
+ void setValueToolTip(const QString &);
+ void setType(const QByteArray &, bool guessChildrenFromType = true);
+ void setAddress(const quint64 &);
+ void setHexAddress(const QByteArray &a);
+
+ QString toString() const;
+ QString toToolTip() const;
static QString msgNotInScope();
static QString shadowedName(const QString &name, int seen);
static const QString &shadowedNameFormat();
+ quint64 coreAddress() const;
+ QByteArray hexAddress() const;
+
public:
- QByteArray iname; // Internal name sth like 'local.baz.public.a'
- QByteArray exp; // The expression
- QString name; // Displayed name
- QString value; // Displayed value
- QByteArray editvalue; // Displayed value
- int editformat; // Format of displayed value
- QString valuetooltip; // Tooltip in value column
- QString typeFormats; // Selection of formats of displayed value
+ quint64 id; // Token for the engine for internal mapping
+ qint32 state; // 'needed' flags;
+ QByteArray iname; // Internal name sth like 'local.baz.public.a'
+ QByteArray exp; // The expression
+ QString name; // Displayed name
+ QString value; // Displayed value
+ QByteArray editvalue; // Displayed value
+ qint32 editformat; // Format of displayed value
+ QString valuetooltip; // Tooltip in value column
+ QString typeFormats; // Selection of formats of displayed value
QByteArray type; // Type for further processing
- QString displayedType;// Displayed type (optional)
- QByteArray variable; // Name of internal Gdb variable if created
- quint64 address; // Displayed address
- QString framekey; // Key for type cache
- QScriptValue scriptValue; // If needed...
+ QString displayedType;// Displayed type (optional)
+ quint64 address; // Displayed address
+ qint32 generation; // When updated?
bool hasChildren;
- int generation; // When updated?
- bool valueEnabled; // Value will be greyed out or not
- bool valueEditable; // Value will be editable
+ bool valueEnabled; // Value will be enabled or not
+ bool valueEditable; // Value will be editable
bool error;
+ bool changed;
+ qint32 sortId;
QByteArray dumperFlags;
+ Q_DECLARE_TR_FUNCTIONS(Debugger::Internal::WatchHandler)
+
public:
- int source; // Originated from dumper or symbol evaluation? (CDB only)
- quint64 objectId; // Object id used for the QMLEngine
- int state;
- bool changed;
- int sortId;
+ // FIXME: this is engine specific data that should be mapped internally
+ QByteArray variable; // Name of internal Gdb variable if created
+ qint32 source; // Originated from dumper or symbol evaluation? (CDB only)
};
} // namespace Internal
} // namespace Debugger
-Q_DECLARE_METATYPE(Debugger::Internal::WatchData);
+Q_DECLARE_METATYPE(Debugger::Internal::WatchData)
#endif // DEBUGGER_WATCHDATA_H
diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp
index 654f5da8fb..d01bd232e3 100644
--- a/src/plugins/debugger/watchhandler.cpp
+++ b/src/plugins/debugger/watchhandler.cpp
@@ -34,11 +34,9 @@
#include "watchhandler.h"
#include "breakhandler.h"
-#include "breakpoint.h"
#include "debuggeractions.h"
-#include "debuggeragents.h"
+#include "debuggercore.h"
#include "debuggerengine.h"
-#include "debuggerplugin.h"
#include "watchutils.h"
#if USE_MODEL_TEST
@@ -48,24 +46,22 @@
#include <utils/qtcassert.h>
#include <utils/savedaction.h>
+#include <cplusplus/CppRewriter.h>
+
#include <QtCore/QDebug>
#include <QtCore/QEvent>
#include <QtCore/QFile>
#include <QtCore/QProcess>
#include <QtCore/QTextStream>
-#include <QtCore/QTimer>
#include <QtCore/QtAlgorithms>
-#include <QtGui/QAction>
-#include <QtGui/QApplication>
#include <QtGui/QLabel>
-#include <QtGui/QToolTip>
#include <QtGui/QTextEdit>
#include <ctype.h>
#include <utils/qtcassert.h>
-// creates debug output for accesses to the model
+// Creates debug output for accesses to the model.
//#define DEBUG_MODEL 1
#if DEBUG_MODEL
@@ -84,7 +80,8 @@ static const QString strNotInScope =
static int watcherCounter = 0;
static int generationCounter = 0;
-static DebuggerPlugin *plugin() { return DebuggerPlugin::instance(); }
+QHash<QByteArray, int> WatchHandler::m_watcherNames;
+QHash<QByteArray, int> WatchHandler::m_typeFormats;
////////////////////////////////////////////////////////////////////
//
@@ -251,38 +248,6 @@ static QByteArray parentName(const QByteArray &iname)
return iname.left(pos);
}
-
-static QString chopConst(QString type)
-{
- while (1) {
- if (type.startsWith(QLatin1String("const")))
- type = type.mid(5);
- else if (type.startsWith(QLatin1Char(' ')))
- type = type.mid(1);
- else if (type.endsWith(QLatin1String("const")))
- type.chop(5);
- else if (type.endsWith(QLatin1Char(' ')))
- type.chop(1);
- else
- break;
- }
- return type;
-}
-
-static inline QRegExp stdStringRegExp(const QString &charType)
-{
- QString rc = QLatin1String("basic_string<");
- rc += charType;
- rc += QLatin1String(",[ ]?std::char_traits<");
- rc += charType;
- rc += QLatin1String(">,[ ]?std::allocator<");
- rc += charType;
- rc += QLatin1String("> >");
- const QRegExp re(rc);
- Q_ASSERT(re.isValid());
- return re;
-}
-
static QString niceTypeHelper(const QByteArray &typeIn)
{
typedef QMap<QByteArray, QString> Cache;
@@ -290,100 +255,9 @@ static QString niceTypeHelper(const QByteArray &typeIn)
const Cache::const_iterator it = cache.constFind(typeIn);
if (it != cache.constEnd())
return it.value();
-
- QString type = QString::fromUtf8(typeIn);
- type.replace(QLatin1Char('*'), QLatin1Char('@'));
-
- for (int i = 0; i < 10; ++i) {
- int start = type.indexOf("std::allocator<");
- if (start == -1)
- break;
- // search for matching '>'
- int pos;
- int level = 0;
- for (pos = start + 12; pos < type.size(); ++pos) {
- int c = type.at(pos).unicode();
- if (c == '<') {
- ++level;
- } else if (c == '>') {
- --level;
- if (level == 0)
- break;
- }
- }
- QString alloc = type.mid(start, pos + 1 - start).trimmed();
- QString inner = alloc.mid(15, alloc.size() - 16).trimmed();
-
- if (inner == QLatin1String("char")) { // std::string
- const QRegExp stringRegexp = stdStringRegExp(inner);
- type.replace(stringRegexp, QLatin1String("string"));
- } else if (inner == QLatin1String("wchar_t")) { // std::wstring
- const QRegExp wchartStringRegexp = stdStringRegExp(inner);
- type.replace(wchartStringRegexp, QLatin1String("wstring"));
- } else if (inner == QLatin1String("unsigned short")) { // std::wstring/MSVC
- const QRegExp usStringRegexp = stdStringRegExp(inner);
- type.replace(usStringRegexp, QLatin1String("wstring"));
- }
- // std::vector, std::deque, std::list
- const QRegExp re1(QString::fromLatin1("(vector|list|deque)<%1, ?%2\\s*>").arg(inner, alloc));
- Q_ASSERT(re1.isValid());
- if (re1.indexIn(type) != -1)
- type.replace(re1.cap(0), QString::fromLatin1("%1<%2>").arg(re1.cap(1), inner));
-
- // std::stack
- QRegExp re6(QString::fromLatin1("stack<%1, ?std::deque<%2> >").arg(inner, inner));
- if (!re6.isMinimal())
- re6.setMinimal(true);
- Q_ASSERT(re6.isValid());
- if (re6.indexIn(type) != -1)
- type.replace(re6.cap(0), QString::fromLatin1("stack<%1>").arg(inner));
-
- // std::set
- QRegExp re4(QString::fromLatin1("set<%1, ?std::less<%2>, ?%3\\s*>").arg(inner, inner, alloc));
- if (!re4.isMinimal())
- re4.setMinimal(true);
- Q_ASSERT(re4.isValid());
- if (re4.indexIn(type) != -1)
- type.replace(re4.cap(0), QString::fromLatin1("set<%1>").arg(inner));
-
- // std::map
- if (inner.startsWith("std::pair<")) {
- // search for outermost ','
- int pos;
- int level = 0;
- for (pos = 10; pos < inner.size(); ++pos) {
- int c = inner.at(pos).unicode();
- if (c == '<')
- ++level;
- else if (c == '>')
- --level;
- else if (c == ',' && level == 0)
- break;
- }
- QString ckey = inner.mid(10, pos - 10);
- QString key = chopConst(ckey);
- QString value = inner.mid(pos + 2, inner.size() - 3 - pos).trimmed();
- QRegExp re5(QString("map<%1, ?%2, ?std::less<%3 ?>, ?%4\\s*>")
- .arg(key, value, key, alloc));
- if (!re5.isMinimal())
- re5.setMinimal(true);
- Q_ASSERT(re5.isValid());
- if (re5.indexIn(type) != -1) {
- type.replace(re5.cap(0), QString("map<%1, %2>").arg(key, value));
- } else {
- QRegExp re7(QString("map<const %1, ?%2, ?std::less<const %3>, ?%4\\s*>")
- .arg(key, value, key, alloc));
- if (!re7.isMinimal())
- re7.setMinimal(true);
- if (re7.indexIn(type) != -1)
- type.replace(re7.cap(0), QString("map<const %1, %2>").arg(key, value));
- }
- }
- }
- type.replace(QLatin1Char('@'), QLatin1Char('*'));
- type.replace(QLatin1String(" >"), QLatin1String(">"));
- cache.insert(typeIn, type); // For simplicity, also cache unmodified types
- return type;
+ const QString simplified = CPlusPlus::simplifySTLType(typeIn);
+ cache.insert(typeIn, simplified); // For simplicity, also cache unmodified types
+ return simplified;
}
QString WatchModel::displayType(const WatchData &data) const
@@ -391,9 +265,9 @@ QString WatchModel::displayType(const WatchData &data) const
if (!data.displayedType.isEmpty())
return data.displayedType;
QString type = niceTypeHelper(data.type);
- if (!theDebuggerBoolSetting(ShowStdNamespace))
+ if (!debuggerCore()->boolSetting(ShowStdNamespace))
type.remove(QLatin1String("std::"));
- if (!theDebuggerBoolSetting(ShowQtNamespace)) {
+ if (!debuggerCore()->boolSetting(ShowQtNamespace)) {
const QString qtNamespace = QString::fromLatin1(engine()->qtNamespace());
if (!qtNamespace.isEmpty())
type.remove(qtNamespace);
@@ -489,8 +363,15 @@ static inline QString formattedValue(const WatchData &data, int format)
else if (result == QLatin1String("<not accessible>"))
result = WatchHandler::tr("<not accessible>");
else if (result.endsWith(" items>")) {
- const int size = result.mid(1, result.indexOf(' ') - 1).toInt();
- result = WatchHandler::tr("<%n items>", 0, size);
+ // '<10 items>' or '<>10 items>' (more than)
+ bool ok;
+ const bool moreThan = result.at(1) == QLatin1Char('>');
+ const int numberPos = moreThan ? 2 : 1;
+ const int size = result.mid(numberPos, result.indexOf(' ') - numberPos).toInt(&ok);
+ QTC_ASSERT(ok, qWarning("WatchHandler: Invalid item count '%s'", qPrintable(result)) ; )
+ result = moreThan ?
+ WatchHandler::tr("<more than %n items>", 0, size) :
+ WatchHandler::tr("<%n items>", 0, size);
}
}
return result;
@@ -702,17 +583,6 @@ static inline QString expression(const WatchItem *item)
QVariant WatchModel::data(const QModelIndex &idx, int role) const
{
- switch (role) {
- case EngineCapabilitiesRole:
- return engine()->debuggerCapabilities();
-
- case EngineActionsEnabledRole:
- return engine()->debuggerActionsEnabled();
-
- case EngineStateRole:
- return QVariant(int(engine()->state()));
- }
-
const WatchItem *item = watchItem(idx);
const WatchItem &data = *item;
@@ -750,7 +620,7 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const
default: break;
} // switch editrole column
case Qt::ToolTipRole:
- return theDebuggerBoolSetting(UseToolTipsInLocalsView)
+ return debuggerCore()->boolSetting(UseToolTipsInLocalsView)
? data.toToolTip() : QVariant();
case Qt::ForegroundRole: {
@@ -808,7 +678,7 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const
case LocalsIsWatchpointAtAddressRole:
return engine()->breakHandler()
- ->watchPointAt(data.coreAddress());
+ ->hasWatchpointAt(data.coreAddress());
case LocalsAddressRole:
return data.coreAddress();
@@ -816,7 +686,7 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const
case LocalsIsWatchpointAtPointerValueRole:
if (isPointerType(data.type))
return engine()->breakHandler()
- ->watchPointAt(pointerValue(data.value));
+ ->hasWatchpointAt(pointerValue(data.value));
return false;
default:
@@ -827,44 +697,6 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const
bool WatchModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
- switch (role) {
- case RequestShowInEditorRole: {
- m_handler->showInEditor();
- return true;
- }
-
- case RequestToggleWatchRole: {
- BreakHandler *handler = engine()->breakHandler();
- const quint64 address = value.toULongLong();
- const int index = handler->findWatchPointIndexByAddress(address);
- if (index == -1) {
- BreakpointData *data = new BreakpointData;
- data->type = BreakpointData::WatchpointType;
- data->address = address;
- handler->appendBreakpoint(data);
- } else {
- handler->removeBreakpoint(index);
- }
- engine()->attemptBreakpointSynchronization();
- return true;
- }
-
- case RequestShowMemoryRole: {
- (void) new MemoryViewAgent(engine(), value.toULongLong());
- return true;
- }
-
- case RequestClearCppCodeModelSnapshotRole: {
- plugin()->clearCppCodeModelSnapshot();
- return true;
- }
-
- case RequestWatchPointRole: {
- engine()->watchPoint(value.toPoint());
- return true;
- }
- }
-
WatchItem &data = *watchItem(index);
switch (role) {
@@ -904,14 +736,6 @@ bool WatchModel::setData(const QModelIndex &index, const QVariant &value, int ro
engine()->updateWatchData(data);
break;
}
-
- case RequestRemoveWatchExpressionRole:
- m_handler->removeWatchExpression(value.toString());
- break;
-
- case RequestWatchExpressionRole:
- m_handler->watchExpression(value.toString());
- break;
}
emit dataChanged(index, index);
@@ -1020,7 +844,7 @@ bool watchItemSorter(const WatchItem *item1, const WatchItem *item2)
static int findInsertPosition(const QList<WatchItem *> &list, const WatchItem *item)
{
- sortWatchDataAlphabetically = theDebuggerBoolSetting(SortStructMembers);
+ sortWatchDataAlphabetically = debuggerCore()->boolSetting(SortStructMembers);
const QList<WatchItem *>::const_iterator it =
qLowerBound(list.begin(), list.end(), item, watchItemSorter);
return it - list.begin();
@@ -1107,7 +931,7 @@ void WatchModel::insertBulkData(const QList<WatchData> &list)
}
QModelIndex index = watchIndex(parent);
- sortWatchDataAlphabetically = theDebuggerBoolSetting(SortStructMembers);
+ sortWatchDataAlphabetically = debuggerCore()->boolSetting(SortStructMembers);
QMap<WatchDataSortKey, WatchData> newList;
typedef QMap<WatchDataSortKey, WatchData>::iterator Iterator;
foreach (const WatchItem &data, list)
@@ -1239,11 +1063,11 @@ WatchHandler::WatchHandler(DebuggerEngine *engine)
m_watchers = new WatchModel(this, WatchersWatch);
m_tooltips = new WatchModel(this, TooltipsWatch);
- connect(theDebuggerAction(ShowStdNamespace),
+ connect(debuggerCore()->action(ShowStdNamespace),
SIGNAL(triggered()), this, SLOT(emitAllChanged()));
- connect(theDebuggerAction(ShowQtNamespace),
+ connect(debuggerCore()->action(ShowQtNamespace),
SIGNAL(triggered()), this, SLOT(emitAllChanged()));
- connect(theDebuggerAction(SortStructMembers),
+ connect(debuggerCore()->action(SortStructMembers),
SIGNAL(triggered()), this, SLOT(emitAllChanged()));
}
@@ -1308,7 +1132,8 @@ void WatchHandler::insertData(const WatchData &data)
if (!m_engine->isSynchronous()) {
m_engine->updateWatchData(data);
} else {
- qDebug() << "ENDLESS LOOP: SOMETHING NEEDED: " << data.toString();
+ m_engine->showMessage(QLatin1String("ENDLESS LOOP: SOMETHING NEEDED: ")
+ + data.toString());
WatchData data1 = data;
data1.setAllUnneeded();
data1.setValue(QLatin1String("<unavailable synchronous data>"));
@@ -1378,9 +1203,9 @@ QByteArray WatchHandler::watcherName(const QByteArray &exp)
void WatchHandler::watchExpression(const QString &exp)
{
- QTC_ASSERT(m_engine && (m_engine->debuggerCapabilities() & AddWatcherCapability), return ; );
- // Do not insert multiple placeholders.
- if (exp.isEmpty() && m_watcherNames.contains(QByteArray()))
+ QTC_ASSERT(m_engine, return);
+ // Do not insert the same entry more then once.
+ if (m_watcherNames.value(exp.toLatin1()))
return;
// FIXME: 'exp' can contain illegal characters
@@ -1391,10 +1216,16 @@ void WatchHandler::watchExpression(const QString &exp)
if (exp.isEmpty())
data.setAllUnneeded();
data.iname = watcherName(data.exp);
- if (m_engine->isSynchronous() && !m_engine->isSessionEngine())
+ if (m_engine->state() == DebuggerNotReady) {
+ data.setAllUnneeded();
+ data.setValue(" ");
+ data.setHasChildren(false);
+ insertData(data);
+ } else if (m_engine->isSynchronous()) {
m_engine->updateWatchData(data);
- else
+ } else {
insertData(data);
+ }
updateWatchersWindow();
saveWatchers();
emitAllChanged();
@@ -1427,8 +1258,9 @@ void WatchHandler::showEditValue(const WatchData &data)
delete w;
l = new QLabel;
const QString title = data.address ?
- tr("%1 Object at %2").arg(QLatin1String(data.type), QLatin1String(data.hexAddress())) :
- tr("%1 Object at Unknown Address").arg(QLatin1String(data.type));
+ tr("%1 Object at %2").arg(QLatin1String(data.type),
+ QLatin1String(data.hexAddress())) :
+ tr("%1 Object at Unknown Address").arg(QLatin1String(data.type));
l->setWindowTitle(title);
m_editHandlers[key] = l;
}
@@ -1455,7 +1287,7 @@ void WatchHandler::showEditValue(const WatchData &data)
QImage im(bits, width, height, QImage::Format(format));
#if 1
- // enforcing copy of image data
+ // Qt bug. Enforce copy of image data.
QImage im2(im);
im.detach();
#endif
@@ -1464,7 +1296,7 @@ void WatchHandler::showEditValue(const WatchData &data)
l->resize(width, height);
l->show();
} else if (data.editformat == 2) {
- // QString
+ // Display QString in a separate widget.
QTextEdit *t = qobject_cast<QTextEdit *>(w);
if (!t) {
delete w;
@@ -1503,43 +1335,20 @@ void WatchHandler::removeWatchExpression(const QString &exp0)
if (item->exp == exp) {
m_watchers->destroyItem(item);
saveWatchers();
+ updateWatchersWindow();
+ emitAllChanged();
break;
}
}
- emitAllChanged();
- updateWatchersWindow();
}
void WatchHandler::updateWatchersWindow()
{
// Force show/hide of watchers and return view.
- plugin()->updateState(m_engine);
-}
-
-void WatchHandler::updateWatchers()
-{
- //qDebug() << "UPDATE WATCHERS";
- // copy over all watchers and mark all watchers as incomplete
- foreach (const QByteArray &exp, m_watcherNames.keys()) {
- WatchData data;
- data.iname = watcherName(exp);
- data.setAllNeeded();
- data.name = exp;
- data.exp = exp;
- insertData(data);
- }
+ debuggerCore()->updateWatchersWindow();
}
-void WatchHandler::loadWatchers()
-{
- QVariant value = plugin()->sessionValue("Watchers");
- foreach (const QString &exp, value.toStringList())
- m_watcherNames[exp.toLatin1()] = watcherCounter++;
-
- //qDebug() << "LOAD WATCHERS: " << m_watchers;
-}
-
-QStringList WatchHandler::watchedExpressions() const
+QStringList WatchHandler::watchedExpressions()
{
// Filter out invalid watchers.
QStringList watcherNames;
@@ -1555,13 +1364,12 @@ QStringList WatchHandler::watchedExpressions() const
void WatchHandler::saveWatchers()
{
- //qDebug() << "SAVE WATCHERS: " << m_watchers;
- plugin()->setSessionValue("Watchers", QVariant(watchedExpressions()));
+ debuggerCore()->setSessionValue("Watchers", QVariant(watchedExpressions()));
}
void WatchHandler::loadTypeFormats()
{
- QVariant value = plugin()->sessionValue("DefaultFormats");
+ QVariant value = debuggerCore()->sessionValue("DefaultFormats");
QMap<QString, QVariant> typeFormats = value.toMap();
QMapIterator<QString, QVariant> it(typeFormats);
while (it.hasNext()) {
@@ -1584,48 +1392,43 @@ void WatchHandler::saveTypeFormats()
typeFormats.insert(key, format);
}
}
- plugin()->setSessionValue("DefaultFormats", QVariant(typeFormats));
+ debuggerCore()->setSessionValue("DefaultFormats", QVariant(typeFormats));
}
void WatchHandler::saveSessionData()
{
- QTC_ASSERT(m_engine->isSessionEngine(), return);
saveWatchers();
saveTypeFormats();
}
void WatchHandler::loadSessionData()
{
- QTC_ASSERT(m_engine->isSessionEngine(), return);
- loadWatchers();
loadTypeFormats();
+ m_watcherNames.clear();
+ QVariant value = debuggerCore()->sessionValue("Watchers");
+ foreach (WatchItem *item, m_watchers->rootItem()->children)
+ m_watchers->destroyItem(item);
+ foreach (const QString &exp, value.toStringList())
+ watchExpression(exp);
+ updateWatchersWindow();
+ emitAllChanged();
+}
+void WatchHandler::updateWatchers()
+{
+ foreach (WatchItem *item, m_watchers->rootItem()->children)
+ m_watchers->destroyItem(item);
+ // Copy over all watchers and mark all watchers as incomplete.
foreach (const QByteArray &exp, m_watcherNames.keys()) {
WatchData data;
data.iname = watcherName(exp);
- data.setAllUnneeded();
+ data.setAllNeeded();
data.name = exp;
data.exp = exp;
insertData(data);
}
- updateWatchersWindow();
-}
-
-void WatchHandler::initializeFromTemplate(WatchHandler *other)
-{
- m_watcherNames = other->m_watcherNames;
- m_typeFormats = other->m_typeFormats;
- m_individualFormats = other->m_individualFormats;
-}
-
-void WatchHandler::storeToTemplate(WatchHandler *other)
-{
- other->m_watcherNames = m_watcherNames;
- other->m_typeFormats = m_typeFormats;
- other->m_individualFormats = m_individualFormats;
}
-
WatchModel *WatchHandler::model(WatchType type) const
{
switch (type) {
@@ -1652,13 +1455,29 @@ WatchModel *WatchHandler::modelForIName(const QByteArray &iname) const
return 0;
}
-WatchData *WatchHandler::findItem(const QByteArray &iname) const
+const WatchData *WatchHandler::watchData(WatchType type, const QModelIndex &index) const
+{
+ if (index.isValid())
+ if (const WatchModel *m = model(type))
+ return m->watchItem(index);
+ return 0;
+}
+
+const WatchData *WatchHandler::findItem(const QByteArray &iname) const
{
const WatchModel *model = modelForIName(iname);
QTC_ASSERT(model, return 0);
return model->findItem(iname, model->m_root);
}
+QModelIndex WatchHandler::itemIndex(const QByteArray &iname) const
+{
+ if (const WatchModel *model = modelForIName(iname))
+ if (WatchItem *item = model->findItem(iname, model->m_root))
+ return model->watchIndex(item);
+ return QModelIndex();
+}
+
void WatchHandler::setFormat(const QByteArray &type, int format)
{
if (format == -1)
@@ -1739,12 +1558,12 @@ void WatchHandler::addTypeFormats(const QByteArray &type, const QStringList &for
m_reportedTypeFormats.insert(type, formats);
}
-void WatchHandler::showInEditor()
+QString WatchHandler::editorContents()
{
QString contents;
showInEditorHelper(&contents, m_locals->m_root, 0);
showInEditorHelper(&contents, m_watchers->m_root, 0);
- plugin()->openTextEditor(tr("Locals & Watchers"), contents);
+ return contents;
}
void WatchHandler::showInEditorHelper(QString *contents, WatchItem *item, int depth)
@@ -1765,5 +1584,6 @@ void WatchHandler::removeTooltip()
m_tooltips->reinitialize();
m_tooltips->emitAllChanged();
}
+
} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/watchhandler.h b/src/plugins/debugger/watchhandler.h
index 5b822513c4..dc00c310b2 100644
--- a/src/plugins/debugger/watchhandler.h
+++ b/src/plugins/debugger/watchhandler.h
@@ -37,7 +37,6 @@
#include "watchdata.h"
#include <QtCore/QPointer>
-#include <QtCore/QObject>
#include <QtCore/QHash>
#include <QtCore/QSet>
#include <QtCore/QStringList>
@@ -64,7 +63,7 @@ enum IntegerFormat
DecimalFormat = 0, // Keep that at 0 as default.
HexadecimalFormat,
BinaryFormat,
- OctalFormat,
+ OctalFormat
};
class WatchModel : public QAbstractItemModel
@@ -92,7 +91,6 @@ private:
void fetchMore(const QModelIndex &parent);
friend class WatchHandler;
- friend class GdbEngine;
WatchItem *watchItem(const QModelIndex &) const;
QModelIndex watchIndex(const WatchItem *needle) const;
@@ -156,21 +154,21 @@ public:
void insertData(const WatchData &data);
void insertBulkData(const QList<WatchData> &data);
void removeData(const QByteArray &iname);
- WatchData *findItem(const QByteArray &iname) const;
+
+ const WatchData *watchData(WatchType type, const QModelIndex &) const;
+ const WatchData *findItem(const QByteArray &iname) const;
+ QModelIndex itemIndex(const QByteArray &iname) const;
void loadSessionData();
void saveSessionData();
void removeTooltip();
- void initializeFromTemplate(WatchHandler *other);
- void storeToTemplate(WatchHandler *other);
-
bool isExpandedIName(const QByteArray &iname) const
{ return m_expandedINames.contains(iname); }
QSet<QByteArray> expandedINames() const
{ return m_expandedINames; }
- QStringList watchedExpressions() const;
- QHash<QByteArray, int> watcherNames() const
+ static QStringList watchedExpressions();
+ static QHash<QByteArray, int> watcherNames()
{ return m_watcherNames; }
QByteArray expansionRequests() const;
@@ -182,18 +180,18 @@ public:
void addTypeFormats(const QByteArray &type, const QStringList &formats);
QByteArray watcherName(const QByteArray &exp);
+ void synchronizeWatchers();
+ QString editorContents();
private:
friend class WatchModel;
- void loadWatchers();
void saveWatchers();
+ static void loadTypeFormats();
+ static void saveTypeFormats();
- void loadTypeFormats();
- void saveTypeFormats();
void setFormat(const QByteArray &type, int format);
void updateWatchersWindow();
- void showInEditor();
void showInEditorHelper(QString *contents, WatchItem *item, int level);
bool m_inChange;
@@ -202,8 +200,8 @@ private:
typedef QMap<QString, QPointer<QObject> > EditHandlers;
EditHandlers m_editHandlers;
- QHash<QByteArray, int> m_watcherNames;
- QHash<QByteArray, int> m_typeFormats;
+ static QHash<QByteArray, int> m_watcherNames;
+ static QHash<QByteArray, int> m_typeFormats;
QHash<QByteArray, int> m_individualFormats; // Indexed by iname.
QHash<QString, QStringList> m_reportedTypeFormats;
diff --git a/src/plugins/debugger/watchutils.cpp b/src/plugins/debugger/watchutils.cpp
index b801bd7e6b..253116adfd 100644
--- a/src/plugins/debugger/watchutils.cpp
+++ b/src/plugins/debugger/watchutils.cpp
@@ -44,6 +44,7 @@
#include <texteditor/basetextmark.h>
#include <texteditor/itexteditor.h>
#include <texteditor/texteditorconstants.h>
+#include <coreplugin/editormanager/editormanager.h>
#include <cpptools/cppmodelmanagerinterface.h>
#include <cpptools/cpptoolsconstants.h>
@@ -277,16 +278,6 @@ bool isKeyWord(const QString &exp)
|| exp == QLatin1String("while");
}
-bool isPointerType(const QByteArray &type)
-{
- return type.endsWith('*') || type.endsWith("* const");
-}
-
-bool isCharPointerType(const QByteArray &type)
-{
- return type == "char *" || type == "const char *" || type == "char const *";
-}
-
bool startsWithDigit(const QString &str)
{
return !str.isEmpty() && str.at(0).isDigit();
@@ -544,69 +535,11 @@ QString extractTypeFromPTypeOutput(const QString &str)
return res.simplified();
}
-bool isIntType(const QByteArray &type)
-{
- if (type.isEmpty())
- return false;
- switch (type.at(0)) {
- case 'b':
- return type == "bool";
- case 'c':
- return type == "char";
- case 'i':
- return type == "int" || type == "int64";
- case 'l':
- return type == "long"
- || type == "long long";
- case 'p':
- return type == "ptrdiff_t";
- case 'q':
- return type == "qint16" || type == "quint16"
- || type == "qint32" || type == "quint32"
- || type == "qint64" || type == "quint64";
- case 's':
- return type == "short"
- || type == "signed"
- || type == "size_t"
- || type == "std::size_t"
- || type == "std::ptrdiff_t"
- || type.startsWith("signed ");
- case 'u':
- return type == "unsigned"
- || type.startsWith("unsigned ");
- default:
- return false;
- }
-}
-
bool isSymbianIntType(const QByteArray &type)
{
return type == "TInt" || type == "TBool";
}
-bool isFloatType(const QByteArray &type)
-{
- return type == "float" || type == "double" || type == "qreal";
-}
-
-bool isIntOrFloatType(const QByteArray &type)
-{
- return isIntType(type) || isFloatType(type);
-}
-
-GuessChildrenResult guessChildren(const QByteArray &type)
-{
- if (isIntOrFloatType(type))
- return HasNoChildren;
- if (isCharPointerType(type))
- return HasNoChildren;
- if (isPointerType(type))
- return HasChildren;
- if (type.endsWith("QString"))
- return HasNoChildren;
- return HasPossiblyChildren;
-}
-
QByteArray sizeofTypeExpression(const QByteArray &type, QtDumperHelper::Debugger debugger)
{
if (type.endsWith('*'))
@@ -736,6 +669,14 @@ QString decodeData(const QByteArray &ba, int encoding)
return QCoreApplication::translate("Debugger", "<Encoding error>");
}
+TextEditor::ITextEditor *currentTextEditor()
+{
+ if (const Core::EditorManager *editorManager = Core::EditorManager::instance())
+ if (Core::IEditor *editor = editorManager->currentEditor())
+ return qobject_cast<TextEditor::ITextEditor*>(editor);
+ return 0;
+}
+
// Editor tooltip support
bool isCppEditor(Core::IEditor *editor)
{
@@ -750,6 +691,24 @@ bool isCppEditor(Core::IEditor *editor)
|| mimeType == OBJECTIVE_CPP_SOURCE_MIMETYPE;
}
+bool currentTextEditorPosition(QString *fileNameIn /* = 0 */,
+ int *lineNumberIn /* = 0 */)
+{
+ QString fileName;
+ int lineNumber = 0;
+ if (TextEditor::ITextEditor *textEditor = currentTextEditor()) {
+ if (const Core::IFile *file = textEditor->file()) {
+ fileName = file->fileName();
+ lineNumber = textEditor->currentLine();
+ }
+ }
+ if (fileNameIn)
+ *fileNameIn = fileName;
+ if (lineNumberIn)
+ *lineNumberIn = lineNumber;
+ return !fileName.isEmpty();
+}
+
// Return the Cpp expression, and, if desired, the function
QString cppExpressionAt(TextEditor::ITextEditor *editor, int pos,
int *line, int *column, QString *function /* = 0 */)
@@ -1454,9 +1413,16 @@ static bool gdbMiGetBoolValue(bool *target,
struct GdbMiRecursionContext
{
- GdbMiRecursionContext(int recursionLevelIn = 0) :
- recursionLevel(recursionLevelIn), childNumChild(-1), childIndex(0) {}
+ enum Type
+ {
+ Debugger, // Debugger symbol dump, recursive/symmetrical
+ GdbMacrosCpp // old gdbmacros.cpp format, unsymmetrical
+ };
+
+ GdbMiRecursionContext(Type t, int recursionLevelIn = 0) :
+ type(t), recursionLevel(recursionLevelIn), childNumChild(-1), childIndex(0) {}
+ const Type type;
int recursionLevel;
int childNumChild;
int childIndex;
@@ -1474,31 +1440,41 @@ static void gbdMiToWatchData(const GdbMi &root,
QString v;
QByteArray b;
// Check for name/iname and use as expression default
- if (ctx.recursionLevel == 0) {
- // parents have only iname, from which name is derived
- QString iname;
- if (!gdbMiGetStringValue(&iname, root, "iname"))
- qWarning("Internal error: iname missing");
- w.iname = iname.toLatin1();
- w.name = iname;
- const int lastDotPos = w.name.lastIndexOf(QLatin1Char('.'));
- if (lastDotPos != -1)
- w.name.remove(0, lastDotPos + 1);
- w.exp = w.name.toLatin1();
+ w.sortId = ctx.childIndex;
+ // Fully symmetrical
+ if (ctx.type == GdbMiRecursionContext::Debugger) {
+ gdbMiGetByteArrayValue(&w.iname, root, "iname");
+ gdbMiGetStringValue(&w.name, root, "name");
+ gdbMiGetByteArrayValue(&w.exp, root, "exp");
} else {
- // Children can have a 'name' attribute. If missing, assume array index
- // For display purposes, it can be overridden by "key"
- if (!gdbMiGetStringValue(&w.name, root, "name")) {
- w.name = QString::number(ctx.childIndex);
- }
- // Set iname
- w.iname = ctx.parentIName;
- w.iname += '.';
- w.iname += w.name.toLatin1();
- // Key?
- QString key;
- if (gdbMiGetStringValue(&key, root, "key", "keyencoded")) {
- w.name = key.size() > 13 ? key.mid(0, 13) + QLatin1String("...") : key;
+ // gdbmacros.cpp: iname/name present according to recursion level
+ // Check for name/iname and use as expression default
+ if (ctx.recursionLevel == 0) {
+ // parents have only iname, from which name is derived
+ QString iname;
+ if (!gdbMiGetStringValue(&iname, root, "iname"))
+ qWarning("Internal error: iname missing");
+ w.iname = iname.toLatin1();
+ w.name = iname;
+ const int lastDotPos = w.name.lastIndexOf(QLatin1Char('.'));
+ if (lastDotPos != -1)
+ w.name.remove(0, lastDotPos + 1);
+ w.exp = w.name.toLatin1();
+ } else {
+ // Children can have a 'name' attribute. If missing, assume array index
+ // For display purposes, it can be overridden by "key"
+ if (!gdbMiGetStringValue(&w.name, root, "name")) {
+ w.name = QString::number(ctx.childIndex);
+ }
+ // Set iname
+ w.iname = ctx.parentIName;
+ w.iname += '.';
+ w.iname += w.name.toLatin1();
+ // Key?
+ QString key;
+ if (gdbMiGetStringValue(&key, root, "key", "keyencoded")) {
+ w.name = key.size() > 13 ? key.mid(0, 13) + QLatin1String("...") : key;
+ }
}
}
if (w.name.isEmpty()) {
@@ -1552,7 +1528,7 @@ static void gbdMiToWatchData(const GdbMi &root,
if (children.empty())
return;
wl->back().setChildrenUnneeded();
- GdbMiRecursionContext nextLevelContext(ctx.recursionLevel + 1);
+ GdbMiRecursionContext nextLevelContext(ctx.type, ctx.recursionLevel + 1);
nextLevelContext.parentIName = w.iname;
gdbMiGetStringValue(&nextLevelContext.childType, root, "childtype");
if (!gdbMiGetIntValue(&nextLevelContext.childNumChild, root, "childnumchild"))
@@ -1567,10 +1543,19 @@ bool QtDumperHelper::parseValue(const char *data, QList<WatchData> *l)
{
l->clear();
GdbMi root;
- root.fromStringMultiple(QByteArray(data));
- if (!root.isValid())
- return false;
- gbdMiToWatchData(root, GdbMiRecursionContext(), l);
+ // Array (CDB2)
+ if (*data == '[') {
+ root.fromString(data);
+ if (!root.isValid())
+ return false;
+ foreach(const GdbMi &child, root.children())
+ gbdMiToWatchData(child, GdbMiRecursionContext(GdbMiRecursionContext::Debugger), l);
+ } else {
+ root.fromStringMultiple(QByteArray(data));
+ if (!root.isValid())
+ return false;
+ gbdMiToWatchData(root, GdbMiRecursionContext(GdbMiRecursionContext::GdbMacrosCpp), l);
+ }
return true;
}
diff --git a/src/plugins/debugger/watchutils.h b/src/plugins/debugger/watchutils.h
index 1b042e6952..7616802cab 100644
--- a/src/plugins/debugger/watchutils.h
+++ b/src/plugins/debugger/watchutils.h
@@ -95,6 +95,10 @@ QString quoteUnprintableLatin1(const QByteArray &ba);
bool isCppEditor(Core::IEditor *editor);
QString cppExpressionAt(TextEditor::ITextEditor *editor, int pos,
int *line, int *column, QString *function = 0);
+// Editor helpers
+TextEditor::ITextEditor *currentTextEditor();
+bool currentTextEditorPosition(QString *fileNameIn = 0,
+ int *lineNumberIn = 0);
// Decode string data as returned by the dumper helpers.
QString decodeData(const QByteArray &baIn, int encoding);
diff --git a/src/plugins/debugger/watchwindow.cpp b/src/plugins/debugger/watchwindow.cpp
index 52ad6eb15f..0718a1fa99 100644
--- a/src/plugins/debugger/watchwindow.cpp
+++ b/src/plugins/debugger/watchwindow.cpp
@@ -33,20 +33,22 @@
#include "watchwindow.h"
+#include "breakhandler.h"
#include "debuggeractions.h"
#include "debuggerconstants.h"
-#include "debuggerengine.h"
+#include "debuggercore.h"
#include "debuggerdialogs.h"
-#include "watchhandler.h"
+#include "debuggerengine.h"
#include "watchdelegatewidgets.h"
+#include "watchhandler.h"
#include <utils/qtcassert.h>
#include <utils/savedaction.h>
#include <QtCore/QDebug>
-#include <QtCore/QVariant>
-#include <QtCore/QMetaProperty>
#include <QtCore/QMetaObject>
+#include <QtCore/QMetaProperty>
+#include <QtCore/QVariant>
#include <QtGui/QContextMenuEvent>
#include <QtGui/QHeaderView>
@@ -54,8 +56,6 @@
#include <QtGui/QMenu>
#include <QtGui/QResizeEvent>
-using namespace Debugger;
-using namespace Debugger::Internal;
/////////////////////////////////////////////////////////////////////
//
@@ -63,17 +63,28 @@ using namespace Debugger::Internal;
//
/////////////////////////////////////////////////////////////////////
+namespace Debugger {
+namespace Internal {
+
+static DebuggerEngine *currentEngine()
+{
+ return debuggerCore()->currentEngine();
+}
+
class WatchDelegate : public QItemDelegate
{
public:
- explicit WatchDelegate(QObject *parent) : QItemDelegate(parent) {}
+ explicit WatchDelegate(WatchWindow *parent)
+ : QItemDelegate(parent), m_watchWindow(parent)
+ {}
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &,
const QModelIndex &index) const
{
// Value column: Custom editor. Apply integer-specific settings.
if (index.column() == 1) {
- const QVariant::Type type = static_cast<QVariant::Type>(index.data(LocalsEditTypeRole).toInt());
+ const QVariant::Type type =
+ static_cast<QVariant::Type>(index.data(LocalsEditTypeRole).toInt());
switch (type) {
case QVariant::Bool:
return new BooleanComboBox(parent);
@@ -101,12 +112,12 @@ public:
}
const QMetaProperty userProperty = editor->metaObject()->userProperty();
QTC_ASSERT(userProperty.isValid(), return);
- const QVariant value = editor->property(userProperty.name());
+ const QString value = editor->property(userProperty.name()).toString();
const QString exp = index.data(LocalsExpressionRole).toString();
- if (exp != value.toString()) {
- model->setData(index, exp, RequestRemoveWatchExpressionRole);
- model->setData(index, value, RequestWatchExpressionRole);
- }
+ if (exp == value)
+ return;
+ m_watchWindow->removeWatchExpression(exp);
+ m_watchWindow->watchExpression(value);
}
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
@@ -114,6 +125,9 @@ public:
{
editor->setGeometry(option.rect);
}
+
+private:
+ WatchWindow *m_watchWindow;
};
/////////////////////////////////////////////////////////////////////
@@ -129,7 +143,7 @@ WatchWindow::WatchWindow(Type type, QWidget *parent)
{
m_grabbing = false;
- QAction *act = theDebuggerAction(UseAlternatingRowColors);
+ QAction *act = debuggerCore()->action(UseAlternatingRowColors);
setFrameStyle(QFrame::NoFrame);
setAttribute(Qt::WA_MacShowFocusRect, false);
setWindowTitle(tr("Locals and Watchers"));
@@ -217,8 +231,35 @@ void WatchWindow::mouseDoubleClickEvent(QMouseEvent *ev)
QTreeView::mouseDoubleClickEvent(ev);
}
+// Text for add watch action with truncated expression
+static inline QString addWatchActionText(QString exp)
+{
+ if (exp.isEmpty())
+ return WatchWindow::tr("Watch Expression");
+ if (exp.size() > 30) {
+ exp.truncate(30);
+ exp.append(QLatin1String("..."));
+ }
+ return WatchWindow::tr("Watch Expression \"%1\"").arg(exp);
+}
+
+// Text for add watch action with truncated expression
+static inline QString removeWatchActionText(QString exp)
+{
+ if (exp.isEmpty())
+ return WatchWindow::tr("Remove Watch Expression");
+ if (exp.size() > 30) {
+ exp.truncate(30);
+ exp.append(QLatin1String("..."));
+ }
+ return WatchWindow::tr("Remove Watch Expression \"%1\"").arg(exp);
+}
+
void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
{
+ DebuggerEngine *engine = currentEngine();
+ WatchHandler *handler = engine->watchHandler();
+
const QModelIndex idx = indexAt(ev->pos());
const QModelIndex mi0 = idx.sibling(idx.row(), 0);
const QModelIndex mi1 = idx.sibling(idx.row(), 1);
@@ -237,70 +278,62 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
const int effectiveIndividualFormat =
individualFormat == -1 ? typeFormat : individualFormat;
- QMenu typeFormatMenu;
+ QMenu formatMenu;
QList<QAction *> typeFormatActions;
- QAction *clearTypeFormatAction = 0;
- if (idx.isValid()) {
- typeFormatMenu.setTitle(
- tr("Change Format for Type \"%1\"").arg(type));
- if (alternativeFormats.isEmpty()) {
- typeFormatMenu.setEnabled(false);
- } else {
- clearTypeFormatAction = typeFormatMenu.addAction(tr("Automatic"));
- clearTypeFormatAction->setEnabled(typeFormat != -1);
- clearTypeFormatAction->setCheckable(true);
- clearTypeFormatAction->setChecked(typeFormat == -1);
- typeFormatMenu.addSeparator();
- for (int i = 0; i != alternativeFormats.size(); ++i) {
- const QString format = alternativeFormats.at(i);
- QAction *act = new QAction(format, &typeFormatMenu);
- act->setCheckable(true);
- if (i == typeFormat)
- act->setChecked(true);
- typeFormatMenu.addAction(act);
- typeFormatActions.append(act);
- }
- }
- } else {
- typeFormatMenu.setTitle(tr("Change Format for Type"));
- typeFormatMenu.setEnabled(false);
- }
-
- QMenu individualFormatMenu;
QList<QAction *> individualFormatActions;
+ QAction *clearTypeFormatAction = 0;
QAction *clearIndividualFormatAction = 0;
- if (idx.isValid()) {
- individualFormatMenu.setTitle(
- tr("Change Format for Object Named \"%1\"").arg(mi0.data().toString()));
- if (alternativeFormats.isEmpty()) {
- individualFormatMenu.setEnabled(false);
- } else {
- clearIndividualFormatAction
- = individualFormatMenu.addAction(tr("Automatic"));
- clearIndividualFormatAction->setEnabled(individualFormat != -1);
- clearIndividualFormatAction->setCheckable(true);
- clearIndividualFormatAction->setChecked(individualFormat == -1);
- individualFormatMenu.addSeparator();
- for (int i = 0; i != alternativeFormats.size(); ++i) {
- const QString format = alternativeFormats.at(i);
- QAction *act = new QAction(format, &individualFormatMenu);
- act->setCheckable(true);
- if (i == effectiveIndividualFormat)
- act->setChecked(true);
- individualFormatMenu.addAction(act);
- individualFormatActions.append(act);
- }
+ formatMenu.setTitle(tr("Change Display Format..."));
+ if (idx.isValid() && !alternativeFormats.isEmpty()) {
+ QAction *dummy = formatMenu.addAction(
+ tr("Change Display for Type \"%1\"").arg(type));
+ dummy->setEnabled(false);
+ formatMenu.addSeparator();
+ clearTypeFormatAction = formatMenu.addAction(tr("Automatic"));
+ //clearTypeFormatAction->setEnabled(typeFormat != -1);
+ //clearTypeFormatAction->setEnabled(individualFormat != -1);
+ clearTypeFormatAction->setCheckable(true);
+ clearTypeFormatAction->setChecked(typeFormat == -1);
+ formatMenu.addSeparator();
+ for (int i = 0; i != alternativeFormats.size(); ++i) {
+ const QString format = alternativeFormats.at(i);
+ QAction *act = new QAction(format, &formatMenu);
+ act->setCheckable(true);
+ //act->setEnabled(individualFormat != -1);
+ if (i == typeFormat)
+ act->setChecked(true);
+ formatMenu.addAction(act);
+ typeFormatActions.append(act);
+ }
+ formatMenu.addSeparator();
+ dummy = formatMenu.addAction(
+ tr("Change Display for Object Named \"%1\"").arg(mi0.data().toString()));
+ dummy->setEnabled(false);
+ formatMenu.addSeparator();
+ clearIndividualFormatAction
+ = formatMenu.addAction(tr("Use Display Format Based on Type"));
+ //clearIndividualFormatAction->setEnabled(individualFormat != -1);
+ clearIndividualFormatAction->setCheckable(true);
+ clearIndividualFormatAction->setChecked(effectiveIndividualFormat == -1);
+ formatMenu.addSeparator();
+ for (int i = 0; i != alternativeFormats.size(); ++i) {
+ const QString format = alternativeFormats.at(i);
+ QAction *act = new QAction(format, &formatMenu);
+ act->setCheckable(true);
+ if (i == effectiveIndividualFormat)
+ act->setChecked(true);
+ formatMenu.addAction(act);
+ individualFormatActions.append(act);
}
} else {
- individualFormatMenu.setTitle(tr("Change Format for Object"));
- individualFormatMenu.setEnabled(false);
+ formatMenu.setEnabled(false);
}
- const bool actionsEnabled = modelData(EngineActionsEnabledRole).toBool();
- const unsigned engineCapabilities = modelData(EngineCapabilitiesRole).toUInt();
+ const bool actionsEnabled = engine->debuggerActionsEnabled();
+ const unsigned engineCapabilities = engine->debuggerCapabilities();
const bool canHandleWatches =
actionsEnabled && (engineCapabilities & AddWatcherCapability);
- const DebuggerState state = static_cast<DebuggerState>(modelData(EngineStateRole).toInt());
+ const DebuggerState state = engine->state();
QMenu menu;
QAction *actInsertNewWatchItem = menu.addAction(tr("Insert New Watch Item"));
@@ -308,87 +341,97 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
QAction *actSelectWidgetToWatch = menu.addAction(tr("Select Widget to Watch"));
actSelectWidgetToWatch->setEnabled(canHandleWatches);
- QAction *actOpenMemoryEditAtVariableAddress = 0;
- QAction *actOpenMemoryEditAtPointerValue = 0;
- QAction *actOpenMemoryEditor =
- new QAction(tr("Open Memory Editor..."), &menu);
- const bool canShowMemory = engineCapabilities & ShowMemoryCapability;
- actOpenMemoryEditor->setEnabled(actionsEnabled && canShowMemory);
-
// Offer to open address pointed to or variable address.
const bool createPointerActions = pointerValue && pointerValue != address;
- if (canShowMemory && address)
- actOpenMemoryEditAtVariableAddress =
- new QAction(tr("Open Memory Editor at Object's Address (0x%1)")
- .arg(address, 0, 16), &menu);
- if (createPointerActions)
- actOpenMemoryEditAtPointerValue =
- new QAction(tr("Open Memory Editor at Referenced Address (0x%1)")
- .arg(pointerValue, 0, 16), &menu);
menu.addSeparator();
- QAction *actSetWatchPointAtVariableAddress = 0;
- QAction *actSetWatchPointAtPointerValue = 0;
+ QAction *actSetWatchpointAtVariableAddress = 0;
+ QAction *actSetWatchpointAtPointerValue = 0;
const bool canSetWatchpoint = engineCapabilities & WatchpointCapability;
if (canSetWatchpoint && address) {
- actSetWatchPointAtVariableAddress =
- new QAction(tr("Break on Changes at Object's Address (0x%1)")
+ actSetWatchpointAtVariableAddress =
+ new QAction(tr("Add Watchpoint at Object's Address (0x%1)")
.arg(address, 0, 16), &menu);
- actSetWatchPointAtVariableAddress->setCheckable(true);
- actSetWatchPointAtVariableAddress->
+ actSetWatchpointAtVariableAddress->
setChecked(mi0.data(LocalsIsWatchpointAtAddressRole).toBool());
if (createPointerActions) {
- actSetWatchPointAtPointerValue =
- new QAction(tr("Break on Changes at Referenced Address (0x%1)")
+ actSetWatchpointAtPointerValue =
+ new QAction(tr("Add Watchpoint at Referenced Address (0x%1)")
.arg(pointerValue, 0, 16), &menu);
- actSetWatchPointAtPointerValue->setCheckable(true);
- actSetWatchPointAtPointerValue->
+ actSetWatchpointAtPointerValue->setCheckable(true);
+ actSetWatchpointAtPointerValue->
setChecked(mi0.data(LocalsIsWatchpointAtPointerValueRole).toBool());
}
} else {
- actSetWatchPointAtVariableAddress =
- new QAction(tr("Break on Changing Contents"), &menu);
- actSetWatchPointAtVariableAddress->setEnabled(false);
+ actSetWatchpointAtVariableAddress =
+ new QAction(tr("Add Watchpoint"), &menu);
+ actSetWatchpointAtVariableAddress->setEnabled(false);
}
+ actSetWatchpointAtVariableAddress->setToolTip(
+ tr("Setting a watchpoint on an address will cause the program "
+ "to stop when the data at the address it modified."));
- QString actionName = exp.isEmpty() ? tr("Watch Expression")
- : tr("Watch Expression \"%1\"").arg(exp);
- QAction *actWatchExpression = new QAction(actionName, &menu);
+ QAction *actWatchExpression = new QAction(addWatchActionText(exp), &menu);
actWatchExpression->setEnabled(canHandleWatches && !exp.isEmpty());
// Can remove watch if engine can handle it or session engine.
- actionName = exp.isEmpty() ? tr("Remove Watch Expression")
- : tr("Remove Watch Expression \"%1\"").arg(exp);
- QAction *actRemoveWatchExpression = new QAction(actionName, &menu);
- actRemoveWatchExpression->setEnabled((canHandleWatches || state == DebuggerNotReady)
- && !exp.isEmpty());
+ QAction *actRemoveWatchExpression = new QAction(removeWatchActionText(exp), &menu);
+ actRemoveWatchExpression->setEnabled(
+ (canHandleWatches || state == DebuggerNotReady) && !exp.isEmpty());
if (m_type == LocalsType)
menu.addAction(actWatchExpression);
else
menu.addAction(actRemoveWatchExpression);
+ QMenu memoryMenu;
+ memoryMenu.setTitle(tr("Open Memory Editor..."));
+ QAction *actOpenMemoryEditAtVariableAddress = new QAction(&memoryMenu);
+ QAction *actOpenMemoryEditAtPointerValue = new QAction(&memoryMenu);
+ QAction *actOpenMemoryEditor = new QAction(&memoryMenu);
+ if (engineCapabilities & ShowMemoryCapability) {
+ actOpenMemoryEditor->setText(tr("Open Memory Editor..."));
+ if (address) {
+ actOpenMemoryEditAtVariableAddress->setText(
+ tr("Open Memory Editor at Object's Address (0x%1)")
+ .arg(address, 0, 16));
+ } else {
+ actOpenMemoryEditAtVariableAddress->setText(
+ tr("Open Memory Editor at Object's Address"));
+ actOpenMemoryEditAtVariableAddress->setEnabled(false);
+ }
+ if (createPointerActions) {
+ actOpenMemoryEditAtPointerValue->setText(
+ tr("Open Memory Editor at Referenced Address (0x%1)")
+ .arg(pointerValue, 0, 16));
+ } else {
+ actOpenMemoryEditAtPointerValue->setText(
+ tr("Open Memory Editor at Referenced Address"));
+ actOpenMemoryEditAtPointerValue->setEnabled(false);
+ }
+ memoryMenu.addAction(actOpenMemoryEditAtVariableAddress);
+ memoryMenu.addAction(actOpenMemoryEditAtPointerValue);
+ memoryMenu.addAction(actOpenMemoryEditor);
+ } else {
+ memoryMenu.setEnabled(false);
+ }
+
menu.addAction(actInsertNewWatchItem);
menu.addAction(actSelectWidgetToWatch);
- menu.addMenu(&typeFormatMenu);
- menu.addMenu(&individualFormatMenu);
- if (actOpenMemoryEditAtVariableAddress)
- menu.addAction(actOpenMemoryEditAtVariableAddress);
- if (actOpenMemoryEditAtPointerValue)
- menu.addAction(actOpenMemoryEditAtPointerValue);
- menu.addAction(actOpenMemoryEditor);
- menu.addAction(actSetWatchPointAtVariableAddress);
- if (actSetWatchPointAtPointerValue)
- menu.addAction(actSetWatchPointAtPointerValue);
+ menu.addMenu(&formatMenu);
+ menu.addMenu(&memoryMenu);
+ menu.addAction(actSetWatchpointAtVariableAddress);
+ if (actSetWatchpointAtPointerValue)
+ menu.addAction(actSetWatchpointAtPointerValue);
menu.addSeparator();
- menu.addAction(theDebuggerAction(UseDebuggingHelpers));
- menu.addAction(theDebuggerAction(UseToolTipsInLocalsView));
- menu.addAction(theDebuggerAction(AutoDerefPointers));
- menu.addAction(theDebuggerAction(ShowStdNamespace));
- menu.addAction(theDebuggerAction(ShowQtNamespace));
- menu.addAction(theDebuggerAction(SortStructMembers));
+ menu.addAction(debuggerCore()->action(UseDebuggingHelpers));
+ menu.addAction(debuggerCore()->action(UseToolTipsInLocalsView));
+ menu.addAction(debuggerCore()->action(AutoDerefPointers));
+ menu.addAction(debuggerCore()->action(ShowStdNamespace));
+ menu.addAction(debuggerCore()->action(ShowQtNamespace));
+ menu.addAction(debuggerCore()->action(SortStructMembers));
QAction *actAdjustColumnWidths =
menu.addAction(tr("Adjust Column Widths to Contents"));
@@ -401,13 +444,13 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
QAction *actClearCodeModelSnapshot
= new QAction(tr("Refresh Code Model Snapshot"), &menu);
actClearCodeModelSnapshot->setEnabled(actionsEnabled
- && theDebuggerAction(UseCodeModel)->isChecked());
+ && debuggerCore()->action(UseCodeModel)->isChecked());
menu.addAction(actClearCodeModelSnapshot);
QAction *actShowInEditor
= new QAction(tr("Show View Contents in Editor"), &menu);
actShowInEditor->setEnabled(actionsEnabled);
menu.addAction(actShowInEditor);
- menu.addAction(theDebuggerAction(SettingsDialog));
+ menu.addAction(debuggerCore()->action(SettingsDialog));
QAction *act = menu.exec(ev->globalPos());
if (act == 0)
@@ -420,17 +463,17 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
} else if (act == actInsertNewWatchItem) {
watchExpression(QString());
} else if (act == actOpenMemoryEditAtVariableAddress) {
- setModelData(RequestShowMemoryRole, address);
+ currentEngine()->openMemoryView(address);
} else if (act == actOpenMemoryEditAtPointerValue) {
- setModelData(RequestShowMemoryRole, pointerValue);
+ currentEngine()->openMemoryView(pointerValue);
} else if (act == actOpenMemoryEditor) {
AddressDialog dialog;
if (dialog.exec() == QDialog::Accepted)
- setModelData(RequestShowMemoryRole, dialog.address());
- } else if (act == actSetWatchPointAtVariableAddress) {
- setModelData(RequestToggleWatchRole, address);
- } else if (act == actSetWatchPointAtPointerValue) {
- setModelData(RequestToggleWatchRole, pointerValue);
+ currentEngine()->openMemoryView(dialog.address());
+ } else if (act == actSetWatchpointAtVariableAddress) {
+ setWatchpoint(address);
+ } else if (act == actSetWatchpointAtPointerValue) {
+ setWatchpoint(pointerValue);
} else if (act == actSelectWidgetToWatch) {
grabMouse(Qt::CrossCursor);
m_grabbing = true;
@@ -439,13 +482,14 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
} else if (act == actRemoveWatchExpression) {
removeWatchExpression(exp);
} else if (act == actClearCodeModelSnapshot) {
- setModelData(RequestClearCppCodeModelSnapshotRole);
+ debuggerCore()->clearCppCodeModelSnapshot();
} else if (act == clearTypeFormatAction) {
setModelData(LocalsTypeFormatRole, -1, mi1);
} else if (act == clearIndividualFormatAction) {
setModelData(LocalsIndividualFormatRole, -1, mi1);
} else if (act == actShowInEditor) {
- setModelData(RequestShowInEditorRole);
+ QString contents = handler->editorContents();
+ debuggerCore()->openTextEditor(tr("Locals & Watchers"), contents);
} else {
for (int i = 0; i != typeFormatActions.size(); ++i) {
if (act == typeFormatActions.at(i))
@@ -481,7 +525,7 @@ bool WatchWindow::event(QEvent *ev)
QMouseEvent *mev = static_cast<QMouseEvent *>(ev);
m_grabbing = false;
releaseMouse();
- setModelData(RequestWatchPointRole, mapToGlobal(mev->pos()));
+ currentEngine()->watchPoint(mapToGlobal(mev->pos()));
}
return QTreeView::event(ev);
}
@@ -501,10 +545,8 @@ void WatchWindow::setModel(QAbstractItemModel *model)
if (m_type != LocalsType)
header()->hide();
- connect(model, SIGNAL(layoutChanged()),
- this, SLOT(resetHelper()));
- connect(model, SIGNAL(enableUpdates(bool)),
- this, SLOT(setUpdatesEnabled(bool)));
+ connect(model, SIGNAL(layoutChanged()), SLOT(resetHelper()));
+ connect(model, SIGNAL(enableUpdates(bool)), SLOT(setUpdatesEnabled(bool)));
}
void WatchWindow::setUpdatesEnabled(bool enable)
@@ -515,32 +557,38 @@ void WatchWindow::setUpdatesEnabled(bool enable)
void WatchWindow::resetHelper()
{
+ bool old = updatesEnabled();
+ setUpdatesEnabled(false);
resetHelper(model()->index(0, 0));
+ setUpdatesEnabled(old);
}
void WatchWindow::resetHelper(const QModelIndex &idx)
{
if (idx.data(LocalsExpandedRole).toBool()) {
//qDebug() << "EXPANDING " << model()->data(idx, INameRole);
- expand(idx);
- for (int i = 0, n = model()->rowCount(idx); i != n; ++i) {
- QModelIndex idx1 = model()->index(i, 0, idx);
- resetHelper(idx1);
+ if (!isExpanded(idx)) {
+ expand(idx);
+ for (int i = 0, n = model()->rowCount(idx); i != n; ++i) {
+ QModelIndex idx1 = model()->index(i, 0, idx);
+ resetHelper(idx1);
+ }
}
} else {
//qDebug() << "COLLAPSING " << model()->data(idx, INameRole);
- collapse(idx);
+ if (isExpanded(idx))
+ collapse(idx);
}
}
void WatchWindow::watchExpression(const QString &exp)
{
- setModelData(RequestWatchExpressionRole, exp);
+ currentEngine()->watchHandler()->watchExpression(exp);
}
void WatchWindow::removeWatchExpression(const QString &exp)
{
- setModelData(RequestRemoveWatchExpressionRole, exp);
+ currentEngine()->watchHandler()->removeWatchExpression(exp);
}
void WatchWindow::setModelData
@@ -550,9 +598,11 @@ void WatchWindow::setModelData
model()->setData(index, value, role);
}
-QVariant WatchWindow::modelData(int role, const QModelIndex &index)
+void WatchWindow::setWatchpoint(quint64 address)
{
- QTC_ASSERT(model(), return QVariant());
- return model()->data(index, role);
+ breakHandler()->setWatchpointByAddress(address);
}
+} // namespace Internal
+} // namespace Debugger
+
diff --git a/src/plugins/debugger/watchwindow.h b/src/plugins/debugger/watchwindow.h
index 4a810f8789..576e6d78be 100644
--- a/src/plugins/debugger/watchwindow.h
+++ b/src/plugins/debugger/watchwindow.h
@@ -36,7 +36,6 @@
#include <QtGui/QTreeView>
-
namespace Debugger {
namespace Internal {
@@ -61,6 +60,8 @@ public slots:
void setAlwaysResizeColumnsToContents(bool on = true);
void setModel(QAbstractItemModel *model);
void setAlternatingRowColorsHelper(bool on) { setAlternatingRowColors(on); }
+ void watchExpression(const QString &exp);
+ void removeWatchExpression(const QString &exp);
private:
Q_SLOT void resetHelper();
@@ -78,12 +79,10 @@ private:
void editItem(const QModelIndex &idx);
void resetHelper(const QModelIndex &idx);
- void watchExpression(const QString &exp);
- void removeWatchExpression(const QString &exp);
+ void setWatchpoint(quint64 address);
void setModelData(int role, const QVariant &value = QVariant(),
const QModelIndex &index = QModelIndex());
- QVariant modelData(int role, const QModelIndex &index = QModelIndex());
bool m_alwaysResizeColumnsToContents;
Type m_type;
diff --git a/src/plugins/designer/Designer.pluginspec b/src/plugins/designer/Designer.pluginspec
deleted file mode 100644
index 89535ac8dd..0000000000
--- a/src/plugins/designer/Designer.pluginspec
+++ /dev/null
@@ -1,21 +0,0 @@
-<plugin name="Designer" version="2.0.95" compatVersion="2.0.95">
- <vendor>Nokia Corporation</vendor>
- <copyright>(C) 2010 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>
- <category>Qt Creator</category>
- <description>Qt Designer integration.</description>
- <url>http://qt.nokia.com</url>
- <dependencyList>
- <dependency name="Core" version="2.0.95"/>
-<!-- For compiling with CPP support enabled -->
- <dependency name="CppEditor" version="2.0.95"/>
- </dependencyList>
-</plugin>
diff --git a/src/plugins/designer/Designer.pluginspec.in b/src/plugins/designer/Designer.pluginspec.in
new file mode 100644
index 0000000000..e917a2e81a
--- /dev/null
+++ b/src/plugins/designer/Designer.pluginspec.in
@@ -0,0 +1,22 @@
+<plugin name=\"Designer\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2010 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>
+ <category>Qt Creator</category>
+ <description>Qt Designer integration.</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
+<!-- For compiling with CPP support enabled -->
+ <dependency name=\"CppTools\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"TextEditor\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/designer/designer.pri b/src/plugins/designer/designer.pri
index d8af4897b3..829605d75e 100644
--- a/src/plugins/designer/designer.pri
+++ b/src/plugins/designer/designer.pri
@@ -1,3 +1,3 @@
include(designer_dependencies.pri)
-LIBS *= -l$$qtLibraryTarget(Designer)
+LIBS *= -l$$qtLibraryName(Designer)
diff --git a/src/plugins/designer/designer.pro b/src/plugins/designer/designer.pro
index 83b0ce035d..0437569573 100644
--- a/src/plugins/designer/designer.pro
+++ b/src/plugins/designer/designer.pro
@@ -62,4 +62,4 @@ SOURCES += formeditorplugin.cpp \
RESOURCES += designer.qrc
-OTHER_FILES += Designer.pluginspec Designer.mimetypes.xml README.txt
+OTHER_FILES += Designer.mimetypes.xml README.txt
diff --git a/src/plugins/designer/designer_dependencies.pri b/src/plugins/designer/designer_dependencies.pri
index 4c98d46428..f19342ea3c 100644
--- a/src/plugins/designer/designer_dependencies.pri
+++ b/src/plugins/designer/designer_dependencies.pri
@@ -1,3 +1,5 @@
-include(../../plugins/cppeditor/cppeditor.pri)
+include(../../libs/cplusplus/cplusplus.pri)
+include(../../plugins/cpptools/cpptools.pri)
+include(../../plugins/texteditor/texteditor.pri)
include(../../libs/utils/utils.pri)
include(../../plugins/coreplugin/coreplugin.pri)
diff --git a/src/plugins/designer/formeditorplugin.cpp b/src/plugins/designer/formeditorplugin.cpp
index ece8943137..0881ac10e4 100644
--- a/src/plugins/designer/formeditorplugin.cpp
+++ b/src/plugins/designer/formeditorplugin.cpp
@@ -38,10 +38,10 @@
#ifdef CPP_ENABLED
# include "formclasswizard.h"
-# include <cppeditor/cppeditorconstants.h>
# include "cppsettingspage.h"
#endif
+#include "settingspage.h"
#include "designerconstants.h"
#include <coreplugin/icore.h>
@@ -89,9 +89,10 @@ bool FormEditorPlugin::initialize(const QStringList &arguments, QString *error)
initializeTemplates();
addAutoReleasedObject(new FormEditorFactory);
+ addAutoReleasedObject(new SettingsPageProvider);
// Ensure that loading designer translations is done before FormEditorW is instantiated
- const QString locale = qApp->property("qtc_locale").toString();
+ const QString locale = Core::ICore::instance()->userInterfaceLanguage();
if (!locale.isEmpty()) {
QTranslator *qtr = new QTranslator(this);
const QString &creatorTrPath =
@@ -102,18 +103,9 @@ bool FormEditorPlugin::initialize(const QStringList &arguments, QString *error)
qApp->installTranslator(qtr);
}
error->clear();
- // Delayed loading: Make sure settings pages are there if options
- // dialog is requested.
- connect(Core::ICore::instance(), SIGNAL(optionsDialogRequested()),
- this, SLOT(ensurePluginInitialized()));
return true;
}
-void FormEditorPlugin::ensurePluginInitialized()
-{
- FormEditorW::instance()->ensureInitStage(FormEditorW::RegisterPlugins);
-}
-
void FormEditorPlugin::extensionsInitialized()
{
// 4) test and make sure everything works (undo, saving, editors, opening/closing multiple files, dirtiness etc)
diff --git a/src/plugins/designer/formeditorplugin.h b/src/plugins/designer/formeditorplugin.h
index 0c89c7cc16..dc5c2ad53e 100644
--- a/src/plugins/designer/formeditorplugin.h
+++ b/src/plugins/designer/formeditorplugin.h
@@ -61,9 +61,6 @@ public:
bool initialize(const QStringList &arguments, QString *error_message = 0);
void extensionsInitialized();
-public slots:
- void ensurePluginInitialized();
-
private:
void initializeTemplates();
diff --git a/src/plugins/designer/formeditorstack.h b/src/plugins/designer/formeditorstack.h
index 2cc132cbf1..7a1cfd7c5e 100644
--- a/src/plugins/designer/formeditorstack.h
+++ b/src/plugins/designer/formeditorstack.h
@@ -61,7 +61,7 @@ namespace Internal {
class FormEditorStack : public QStackedWidget
{
Q_OBJECT
- Q_DISABLE_COPY(FormEditorStack);
+ Q_DISABLE_COPY(FormEditorStack)
public:
explicit FormEditorStack(QWidget *parent = 0);
diff --git a/src/plugins/designer/formeditorw.cpp b/src/plugins/designer/formeditorw.cpp
index fcddca60e2..2f569c332b 100644
--- a/src/plugins/designer/formeditorw.cpp
+++ b/src/plugins/designer/formeditorw.cpp
@@ -53,6 +53,7 @@
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/command.h>
+#include <coreplugin/uniqueidmanager.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/minisplitter.h>
#include <coreplugin/mimedatabase.h>
@@ -189,7 +190,6 @@ FormEditorW::FormEditorW() :
foreach (QDesignerOptionsPageInterface *designerPage, m_formeditor->optionsPages()) {
SettingsPage *settingsPage = new SettingsPage(designerPage);
- ExtensionSystem::PluginManager::instance()->addObject(settingsPage);
m_settingsPages.append(settingsPage);
}
@@ -216,10 +216,8 @@ FormEditorW::~FormEditorW()
}
delete m_formeditor;
- foreach (SettingsPage *settingsPage, m_settingsPages) {
- ExtensionSystem::PluginManager::instance()->removeObject(settingsPage);
- delete settingsPage;
- }
+ qDeleteAll(m_settingsPages);
+ m_settingsPages.clear();
delete m_integration;
m_self = 0;
@@ -340,7 +338,9 @@ void FormEditorW::fullInit()
// 'Run' in 'Design' mode emits output.
Core::MiniSplitter *splitter = new Core::MiniSplitter(Qt::Vertical);
splitter->addWidget(m_editorWidget);
- splitter->addWidget(new Core::OutputPanePlaceHolder(m_designMode, splitter));
+ QWidget *outputPane = new Core::OutputPanePlaceHolder(m_designMode, splitter);
+ outputPane->setObjectName(QLatin1String("DesignerOutputPanePlaceHolder"));
+ splitter->addWidget(outputPane);
layout->addWidget(splitter);
m_modeWidget->setLayout(layout);
@@ -390,6 +390,11 @@ void FormEditorW::initDesignerSubWindows()
m_designerSubWindows[ActionEditorSubWindow] = ae;
}
+QList<Core::IOptionsPage *> FormEditorW::optionsPages() const
+{
+ return m_settingsPages;
+}
+
void FormEditorW::ensureInitStage(InitializationStage s)
{
if (Designer::Constants::Internal::debug)
diff --git a/src/plugins/designer/formeditorw.h b/src/plugins/designer/formeditorw.h
index 3f92188868..ef788a4de1 100644
--- a/src/plugins/designer/formeditorw.h
+++ b/src/plugins/designer/formeditorw.h
@@ -36,7 +36,8 @@
#include "designerconstants.h"
-#include "coreplugin/icontext.h"
+#include <coreplugin/icontext.h>
+#include <coreplugin/dialogs/ioptionspage.h>
#include <QtCore/QMap>
#include <QtCore/QObject>
@@ -89,12 +90,10 @@ class DesignerContext;
* The plugin uses this stage at first by calling ensureInitStage().
* Requesting an editor via instance() will fully initialize the class.
* This is based on the assumption that the Designer settings work with
- * no plugins loaded. If that does not work, full initialization can be
- * triggered by connection to the ICore::optionsDialogRequested() signal.
+ * no plugins loaded.
*
* The form editor shows a read-only XML editor in edit mode and Qt Designer
- * in Design mode. It connects to void EditorManager::currentEditorChanged()
- * and switches modes if a designer XML editor is activated. */
+ * in Design mode. */
class FormEditorW : public QObject
{
Q_OBJECT
@@ -121,6 +120,7 @@ public:
inline QWidget * const*designerSubWindows() const { return m_designerSubWindows; }
EditorData activeEditor() const;
+ QList<Core::IOptionsPage *> optionsPages() const;
private slots:
void activateEditMode(int id);
@@ -182,7 +182,7 @@ private:
QAction *m_lockAction;
QAction *m_resetLayoutAction;
- QList<SettingsPage *> m_settingsPages;
+ QList<Core::IOptionsPage *> m_settingsPages;
QActionGroup *m_actionGroupEditMode;
QAction *m_actionPrint;
QAction *m_actionPreview;
diff --git a/src/plugins/designer/formwindoweditor.cpp b/src/plugins/designer/formwindoweditor.cpp
index 804674a2a8..24c74e64e6 100644
--- a/src/plugins/designer/formwindoweditor.cpp
+++ b/src/plugins/designer/formwindoweditor.cpp
@@ -216,6 +216,7 @@ QString FormWindowEditor::displayName() const
void FormWindowEditor::setDisplayName(const QString &title)
{
d->m_textEditable.setDisplayName(title);
+ emit changed();
}
bool FormWindowEditor::duplicateSupported() const
diff --git a/src/plugins/designer/qtcreatorintegration.cpp b/src/plugins/designer/qtcreatorintegration.cpp
index acb77077ef..345ba97d01 100644
--- a/src/plugins/designer/qtcreatorintegration.cpp
+++ b/src/plugins/designer/qtcreatorintegration.cpp
@@ -358,6 +358,51 @@ static Document::Ptr addDefinition(const CPlusPlus::Snapshot &docTable,
return Document::Ptr();
}
+static QString addConstRefIfNeeded(const QString &argument)
+{
+ if (argument.startsWith(QLatin1String("const "))
+ || argument.endsWith(QLatin1Char('&'))
+ || argument.endsWith(QLatin1Char('*')))
+ return argument;
+
+ // for those types we don't want to add "const &"
+ static const QStringList nonConstRefs = QStringList()
+ << QLatin1String("bool")
+ << QLatin1String("int")
+ << QLatin1String("uint")
+ << QLatin1String("float")
+ << QLatin1String("double")
+ << QLatin1String("long")
+ << QLatin1String("short")
+ << QLatin1String("char")
+ << QLatin1String("signed")
+ << QLatin1String("unsigned")
+ << QLatin1String("qint64")
+ << QLatin1String("quint64");
+
+ for (int i = 0; i < nonConstRefs.count(); i++) {
+ const QString nonConstRef = nonConstRefs.at(i);
+ if (argument == nonConstRef || argument.startsWith(nonConstRef + QLatin1Char(' ')))
+ return argument;
+ }
+ return QLatin1String("const ") + argument + QLatin1Char('&');
+}
+
+static QString formatArgument(const QString &argument)
+{
+ QString formattedArgument = argument;
+ int i = argument.count();
+ while (i > 0) { // from the end of the "argument" string
+ i--;
+ const QChar c = argument.at(i); // take the char
+ if (c != QLatin1Char('*') && c != QLatin1Char('&')) { // if it's not the * or &
+ formattedArgument.insert(i + 1, QLatin1Char(' ')); // insert space after that char or just append space (to separate it from the parameter name)
+ break;
+ }
+ }
+ return formattedArgument;
+}
+
// Insert the parameter names into a signature, "void foo(bool)" ->
// "void foo(bool checked)"
static QString addParameterNames(const QString &functionSignature, const QStringList &parameterNames)
@@ -374,10 +419,19 @@ static QString addParameterNames(const QString &functionSignature, const QString
for (int i = 0; i < aCount; ++i) {
if (i > 0)
functionName += QLatin1String(", ");
- functionName += arguments.at(i);
+ const QString argument = addConstRefIfNeeded(arguments.at(i));
+ functionName += formatArgument(argument);
if (i < pCount) {
- functionName += QLatin1Char(' ');
- functionName += parameterNames.at(i);
+ // prepare parameterName
+ QString parameterName = parameterNames.at(i);
+ if (parameterName.isEmpty()) {
+ const QString generatedName = QLatin1String("arg") + QString::number(i + 1);
+ if (!parameterNames.contains(generatedName))
+ parameterName = generatedName;
+ }
+ // add parameterName if not empty
+ if (!parameterName.isEmpty())
+ functionName += parameterName;
}
}
functionName += QLatin1Char(')');
diff --git a/src/plugins/designer/settingspage.cpp b/src/plugins/designer/settingspage.cpp
index e680fffbbe..fe30d67316 100644
--- a/src/plugins/designer/settingspage.cpp
+++ b/src/plugins/designer/settingspage.cpp
@@ -33,6 +33,7 @@
#include "settingspage.h"
#include "designerconstants.h"
+#include "formeditorw.h"
#include <extensionsystem/pluginmanager.h>
#include "qt_private/abstractoptionspage_p.h"
@@ -41,7 +42,7 @@
using namespace Designer::Internal;
SettingsPage::SettingsPage(QDesignerOptionsPageInterface *designerPage) :
- m_designerPage(designerPage)
+ m_designerPage(designerPage), m_initialized(false)
{
}
@@ -76,15 +77,52 @@ QIcon SettingsPage::categoryIcon() const
QWidget *SettingsPage::createPage(QWidget *parent)
{
+ m_initialized = true;
return m_designerPage->createPage(parent);
}
void SettingsPage::apply()
{
- m_designerPage->apply();
+ if (m_initialized)
+ m_designerPage->apply();
}
void SettingsPage::finish()
{
- m_designerPage->finish();
+ if (m_initialized)
+ m_designerPage->finish();
+}
+
+SettingsPageProvider::SettingsPageProvider(QObject *parent)
+ : IOptionsPageProvider(parent), m_initialized(false)
+{
+}
+
+SettingsPageProvider::~SettingsPageProvider()
+{
+}
+
+QString SettingsPageProvider::category() const
+{
+ return QLatin1String(Designer::Constants::SETTINGS_CATEGORY);
+}
+
+QString SettingsPageProvider::displayCategory() const
+{
+ return QCoreApplication::translate("Designer", Designer::Constants::SETTINGS_TR_CATEGORY);
+}
+
+QIcon SettingsPageProvider::categoryIcon() const
+{
+ return QIcon(QLatin1String(Designer::Constants::SETTINGS_CATEGORY_ICON));
+}
+
+QList<Core::IOptionsPage *> SettingsPageProvider::pages() const
+{
+ if (!m_initialized) {
+ // get options pages from designer
+ m_initialized = true;
+ FormEditorW::ensureInitStage(FormEditorW::RegisterPlugins);
+ }
+ return FormEditorW::instance()->optionsPages();
}
diff --git a/src/plugins/designer/settingspage.h b/src/plugins/designer/settingspage.h
index 32a7a792ae..ee5d11eebe 100644
--- a/src/plugins/designer/settingspage.h
+++ b/src/plugins/designer/settingspage.h
@@ -65,6 +65,25 @@ public:
private:
QDesignerOptionsPageInterface *m_designerPage;
+ bool m_initialized;
+};
+
+class SettingsPageProvider : public Core::IOptionsPageProvider
+{
+ Q_OBJECT
+
+public:
+ SettingsPageProvider(QObject *parent = 0);
+ ~SettingsPageProvider();
+
+ QString category() const;
+ QString displayCategory() const;
+ QIcon categoryIcon() const;
+
+ QList<Core::IOptionsPage *> pages() const;
+
+private:
+ mutable bool m_initialized;
};
} // namespace Internal
diff --git a/src/plugins/fakevim/FakeVim.pluginspec b/src/plugins/fakevim/FakeVim.pluginspec
deleted file mode 100644
index 2525922dd7..0000000000
--- a/src/plugins/fakevim/FakeVim.pluginspec
+++ /dev/null
@@ -1,21 +0,0 @@
-<plugin name="FakeVim" version="2.0.95" compatVersion="2.0.95">
- <vendor>Nokia Corporation</vendor>
- <copyright>(C) 2010 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>VI-style keyboard navigation.</description>
- <url>http://qt.nokia.com</url>
- <dependencyList>
- <dependency name="CppEditor" version="2.0.95"/><!-- Plugin adds items to the editor's context menu -->
- <dependency name="TextEditor" version="2.0.95"/>
- <dependency name="ProjectExplorer" version="2.0.95"/>
- <dependency name="Core" version="2.0.95"/>
- </dependencyList>
-</plugin>
diff --git a/src/plugins/fakevim/FakeVim.pluginspec.in b/src/plugins/fakevim/FakeVim.pluginspec.in
new file mode 100644
index 0000000000..3a3570a484
--- /dev/null
+++ b/src/plugins/fakevim/FakeVim.pluginspec.in
@@ -0,0 +1,21 @@
+<plugin name=\"FakeVim\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2010 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>VI-style keyboard navigation.</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name=\"CppEditor\" version=\"$$QTCREATOR_VERSION\"/><!-- Plugin adds items to the editor's context menu -->
+ <dependency name=\"TextEditor\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"ProjectExplorer\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/fakevim/fakevim.pro b/src/plugins/fakevim/fakevim.pro
index adffef024e..1c282309f1 100644
--- a/src/plugins/fakevim/fakevim.pro
+++ b/src/plugins/fakevim/fakevim.pro
@@ -21,4 +21,3 @@ HEADERS += fakevimactions.h \
fakevimsyntax.h \
fakevimplugin.h
FORMS += fakevimoptions.ui
-OTHER_FILES += FakeVim.pluginspec
diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp
index caa8cb7ea5..8aa5f7520c 100644
--- a/src/plugins/fakevim/fakevimhandler.cpp
+++ b/src/plugins/fakevim/fakevimhandler.cpp
@@ -143,7 +143,7 @@ enum Mode
InsertMode,
ReplaceMode,
CommandMode,
- ExMode,
+ ExMode
};
/*! A \e SubMode is used for things that require one more data item
@@ -166,7 +166,7 @@ enum SubMode
CapitalZSubMode, // Used for Z
ReplaceSubMode, // Used for r
OpenSquareSubMode, // Used for [
- CloseSquareSubMode, // Used for ]
+ CloseSquareSubMode // Used for ]
};
/*! A \e SubSubMode is used for things that require one more data item
@@ -183,7 +183,7 @@ enum SubSubMode
DownCaseSubSubMode, // Used for gu.
UpCaseSubSubMode, // Used for gU.
TextObjectSubSubMode, // Used for thing like iw, aW, as etc.
- SearchSubSubMode,
+ SearchSubSubMode
};
enum VisualMode
@@ -191,14 +191,14 @@ enum VisualMode
NoVisualMode,
VisualCharMode,
VisualLineMode,
- VisualBlockMode,
+ VisualBlockMode
};
enum MoveType
{
MoveExclusive,
MoveInclusive,
- MoveLineWise,
+ MoveLineWise
};
/*!
@@ -407,15 +407,18 @@ public:
bool is(int c) const
{
- return m_xkey == c && (m_modifiers == 0
- || m_modifiers == Qt::ShiftModifier
- || m_modifiers == Qt::GroupSwitchModifier);
+ return m_xkey == c && m_modifiers != Qt::ControlModifier;
}
bool isControl(int c) const
{
- return m_modifiers == Qt::ControlModifier &&
- (m_xkey == c || m_xkey + 32 == c || m_xkey + 64 == c || m_xkey + 96 == c);
+ return m_modifiers ==
+#ifdef Q_WS_MAC
+ Qt::MetaModifier
+#else
+ Qt::ControlModifier
+#endif
+ && (m_xkey == c || m_xkey + 32 == c || m_xkey + 64 == c || m_xkey + 96 == c);
}
bool isShift(int c) const
@@ -823,6 +826,7 @@ public:
bool m_lastSearchForward;
bool m_findPending;
+ int m_findStartPosition;
QString m_lastInsertion;
QString m_lastDeletion;
@@ -993,6 +997,7 @@ void FakeVimHandler::Private::init()
m_subsubmode = NoSubSubMode;
m_passing = false;
m_findPending = false;
+ m_findStartPosition = -1;
m_fakeEnd = false;
m_positionPastEnd = false;
m_anchorPastEnd = false;
@@ -1033,7 +1038,12 @@ bool FakeVimHandler::Private::wantsOverride(QKeyEvent *ev)
}
// We are interested in overriding most Ctrl key combinations
- if (mods == Qt::ControlModifier
+ if (mods ==
+#ifdef Q_WS_MAC
+ Qt::MetaModifier
+#else
+ Qt::ControlModifier
+#endif
&& !config(ConfigPassControlKey).toBool()
&& ((key >= Key_A && key <= Key_Z && key != Key_K)
|| key == Key_BracketLeft || key == Key_BracketRight)) {
@@ -1227,7 +1237,13 @@ void FakeVimHandler::Private::importSelection()
// Import new selection.
Qt::KeyboardModifiers mods = QApplication::keyboardModifiers();
if (cursor().hasSelection()) {
- if (mods & Qt::ControlModifier)
+ if (mods &
+#ifdef Q_WS_MAC
+ Qt::MetaModifier
+#else
+ Qt::ControlModifier
+#endif
+ )
m_visualMode = VisualBlockMode;
else if (mods & Qt::AltModifier)
m_visualMode = VisualBlockMode;
@@ -1335,8 +1351,9 @@ void FakeVimHandler::Private::stopIncrementalFind()
if (m_findPending) {
m_findPending = false;
QTextCursor tc = cursor();
- tc.setPosition(tc.selectionStart());
- setCursor(tc);
+ setAnchorAndPosition(m_findStartPosition, tc.selectionStart());
+ finishMovement();
+ setAnchor();
}
}
@@ -1933,8 +1950,10 @@ EventResult FakeVimHandler::Private::handleCommandMode(const Input &input)
if (hasConfig(ConfigUseCoreSearch)) {
// re-use the core dialog.
m_findPending = true;
+ m_findStartPosition = position();
+ m_movetype = MoveExclusive;
+ setAnchor(); // clear selection: otherwise, search is restricted to selection
emit q->findRequested(!m_lastSearchForward);
- //m_tc.setPosition(m_tc.selectionStart());
} else {
// FIXME: make core find dialog sufficiently flexible to
// produce the "default vi" behaviour too. For now, roll our own.
@@ -2315,12 +2334,23 @@ EventResult FakeVimHandler::Private::handleCommandMode(const Input &input)
handleStartOfLine();
finishMovement();
} else if (input.is('n') || input.is('N')) {
- SearchData sd;
- sd.needle = g.searchHistory.current();
- sd.forward = input.is('n') ? m_lastSearchForward : !m_lastSearchForward;
- sd.highlightCursor = false;
- sd.highlightMatches = true;
- search(sd);
+ if (hasConfig(ConfigUseCoreSearch)) {
+ bool forward = (input.is('n')) ? m_lastSearchForward : !m_lastSearchForward;
+ int pos = position();
+ emit q->findNextRequested(!forward);
+ if (forward && pos == cursor().selectionStart()) {
+ // if cursor is already positioned at the start of a find result, this is returned
+ emit q->findNextRequested(false);
+ }
+ setPosition(cursor().selectionStart());
+ } else {
+ SearchData sd;
+ sd.needle = g.searchHistory.current();
+ sd.forward = input.is('n') ? m_lastSearchForward : !m_lastSearchForward;
+ sd.highlightCursor = false;
+ sd.highlightMatches = true;
+ search(sd);
+ }
} else if (isVisualMode() && (input.is('o') || input.is('O'))) {
int pos = position();
setAnchorAndPosition(pos, anchor());
@@ -2672,6 +2702,12 @@ EventResult FakeVimHandler::Private::handleInsertMode(const Input &input)
insertInInsertMode(input.raw());
} else if (input.isControl('v')) {
m_ctrlVActive = true;
+ } else if (input.isControl('w')) {
+ int endPos = position();
+ moveToWordBoundary(false, false, false);
+ int beginPos = position();
+ Range range(beginPos, endPos, RangeCharMode);
+ removeText(range);
} else if (input.isKey(Key_Insert)) {
if (m_mode == ReplaceMode)
m_mode = InsertMode;
@@ -2681,6 +2717,10 @@ EventResult FakeVimHandler::Private::handleInsertMode(const Input &input)
moveLeft(count());
setTargetColumn();
m_lastInsertion.clear();
+ } else if (input.isControl(Key_Left)) {
+ moveToWordBoundary(false, false);
+ setTargetColumn();
+ m_lastInsertion.clear();
} else if (input.isKey(Key_Down)) {
//removeAutomaticIndentation();
m_submode = NoSubMode;
@@ -2695,6 +2735,11 @@ EventResult FakeVimHandler::Private::handleInsertMode(const Input &input)
moveRight(count());
setTargetColumn();
m_lastInsertion.clear();
+ } else if (input.isControl(Key_Right)) {
+ moveToWordBoundary(false, true);
+ moveRight(); // we need one more move since we are in insert mode
+ setTargetColumn();
+ m_lastInsertion.clear();
} else if (input.isKey(Key_Home)) {
moveToStartOfLine();
setTargetColumn();
@@ -3649,7 +3694,7 @@ void FakeVimHandler::Private::search(const SearchData &sd)
}
// Set Cursor. In contrast to the main editor we have the cursor
- // position befor the anchor position.
+ // position before the anchor position.
setAnchorAndPosition(tc.position(), tc.anchor());
// Making this unconditional feels better, but is not "vim like".
diff --git a/src/plugins/fakevim/fakevimhandler.h b/src/plugins/fakevim/fakevimhandler.h
index e03337dcf4..8e20205259 100644
--- a/src/plugins/fakevim/fakevimhandler.h
+++ b/src/plugins/fakevim/fakevimhandler.h
@@ -48,7 +48,7 @@ enum RangeMode
RangeLineMode, // V
RangeLineModeExclusive,
RangeBlockMode, // Ctrl-v
- RangeBlockAndTailMode, // Ctrl-v for D and X
+ RangeBlockAndTailMode // Ctrl-v for D and X
};
struct Range
@@ -141,7 +141,7 @@ private:
} // namespace Internal
} // namespace FakeVim
-Q_DECLARE_METATYPE(FakeVim::Internal::ExCommand);
+Q_DECLARE_METATYPE(FakeVim::Internal::ExCommand)
#endif // FAKEVIM_HANDLER_H
diff --git a/src/plugins/fakevim/fakevimoptions.ui b/src/plugins/fakevim/fakevimoptions.ui
index 2445c6eb52..3142a28de4 100644
--- a/src/plugins/fakevim/fakevimoptions.ui
+++ b/src/plugins/fakevim/fakevimoptions.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>472</width>
- <height>421</height>
+ <width>513</width>
+ <height>445</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
@@ -26,7 +26,7 @@
</widget>
</item>
<item>
- <widget class="QGroupBox" name="groupBox">
+ <widget class="QGroupBox" name="behaviorBox">
<property name="title">
<string>Vim Behavior</string>
</property>
diff --git a/src/plugins/fakevim/fakevimplugin.cpp b/src/plugins/fakevim/fakevimplugin.cpp
index 634d2f022a..a819f97c51 100644
--- a/src/plugins/fakevim/fakevimplugin.cpp
+++ b/src/plugins/fakevim/fakevimplugin.cpp
@@ -54,7 +54,6 @@
#include <coreplugin/statusbarmanager.h>
#include <projectexplorer/projectexplorerconstants.h>
-#include <projectexplorer/session.h>
#include <texteditor/basetextdocumentlayout.h>
#include <texteditor/basetexteditor.h>
@@ -63,6 +62,7 @@
#include <texteditor/texteditorconstants.h>
#include <texteditor/tabsettings.h>
#include <texteditor/texteditorsettings.h>
+#include <texteditor/indenter.h>
#include <find/findplugin.h>
#include <find/textfindconstants.h>
@@ -94,8 +94,6 @@
using namespace FakeVim::Internal;
using namespace TextEditor;
using namespace Core;
-using namespace ProjectExplorer;
-
namespace FakeVim {
namespace Constants {
@@ -205,19 +203,24 @@ QWidget *FakeVimOptionPage::createPage(QWidget *parent)
connect(m_ui.pushButtonSetPlainStyle, SIGNAL(clicked()),
this, SLOT(setPlainStyle()));
if (m_searchKeywords.isEmpty()) {
+ QLatin1Char sep(' ');
QTextStream(&m_searchKeywords)
- << ' ' << m_ui.checkBoxAutoIndent->text()
- << ' ' << m_ui.checkBoxExpandTab->text()
- << ' ' << m_ui.checkBoxShowMarks->text()
- << ' ' << m_ui.checkBoxSmartIndent->text()
- << ' ' << m_ui.checkBoxPassControlKey->text()
- << ' ' << m_ui.checkBoxHlSearch->text()
- << ' ' << m_ui.checkBoxIncSearch->text()
- << ' ' << m_ui.checkBoxSmartTab->text()
- << ' ' << m_ui.checkBoxStartOfLine->text()
- << ' ' << m_ui.labelShiftWidth->text()
- << ' ' << m_ui.labelTabulator->text()
- << ' ' << m_ui.labelBackspace->text();
+ << sep << m_ui.checkBoxUseFakeVim->text()
+ << sep << m_ui.checkBoxReadVimRc->text()
+ << sep << m_ui.checkBoxAutoIndent->text()
+ << sep << m_ui.checkBoxSmartIndent->text()
+ << sep << m_ui.checkBoxExpandTab->text()
+ << sep << m_ui.checkBoxSmartTab->text()
+ << sep << m_ui.checkBoxHlSearch->text()
+ << sep << m_ui.checkBoxIncSearch->text()
+ << sep << m_ui.checkBoxStartOfLine->text()
+ << sep << m_ui.checkBoxUseCoreSearch->text()
+ << sep << m_ui.checkBoxShowMarks->text()
+ << sep << m_ui.checkBoxPassControlKey->text()
+ << sep << m_ui.labelShiftWidth->text()
+ << sep << m_ui.labelTabulator->text()
+ << sep << m_ui.labelBackspace->text()
+ << sep << m_ui.labelIsKeyword->text();
m_searchKeywords.remove(QLatin1Char('&'));
}
return w;
@@ -284,7 +287,7 @@ struct CommandItem
QTreeWidgetItem *m_item;
};
-Q_DECLARE_METATYPE(CommandItem *);
+Q_DECLARE_METATYPE(CommandItem *)
namespace FakeVim {
namespace Internal {
@@ -549,6 +552,9 @@ private:
void readSettings(QSettings *settings);
void writeSettings(QSettings *settings);
+ typedef int (*DistFunction)(const QRect &cursor, const QRect &other);
+ void moveSomewhere(DistFunction f);
+
CommandMap &exCommandMap() { return m_exCommandMap; }
CommandMap &defaultExCommandMap() { return m_exCommandMap; }
CommandMap m_exCommandMap;
@@ -726,7 +732,7 @@ void FakeVimPluginPrivate::triggerAction(const QString &code)
Core::ActionManager *am = actionManager();
QTC_ASSERT(am, return);
Core::Command *cmd = am->command(code);
- QTC_ASSERT(cmd, qDebug() << "UNKNOW CODE: " << code; return);
+ QTC_ASSERT(cmd, qDebug() << "UNKNOWN CODE: " << code; return);
QAction *action = cmd->action();
QTC_ASSERT(action, return);
action->trigger();
@@ -741,42 +747,140 @@ void FakeVimPluginPrivate::setActionChecked(const QString &code, bool check)
QAction *action = cmd->action();
QTC_ASSERT(action, return);
QTC_ASSERT(action->isCheckable(), return);
- action->setChecked(check);
+ action->setChecked(!check); // trigger negates the action's state
action->trigger();
}
+static int moveRightWeight(const QRect &cursor, const QRect &other)
+{
+ int dx = other.left() - cursor.right();
+ if (dx < 0)
+ return -1;
+ int w = 10000 * dx;
+ int dy1 = cursor.top() - other.bottom();
+ int dy2 = cursor.bottom() - other.top();
+ w += dy1 * (dy1 > 0);
+ w += dy2 * (dy2 > 0);
+ qDebug() << " DX: " << dx << dy1 << dy2 << w;
+ return w;
+}
+
+static int moveLeftWeight(const QRect &cursor, const QRect &other)
+{
+ int dx = other.right() - cursor.left();
+ if (dx < 0)
+ return -1;
+ int w = 10000 * dx;
+ int dy1 = cursor.top() - other.bottom();
+ int dy2 = cursor.bottom() - other.top();
+ w += dy1 * (dy1 > 0);
+ w += dy2 * (dy2 > 0);
+ return w;
+}
+
+static int moveUpWeight(const QRect &cursor, const QRect &other)
+{
+ int dy = other.bottom() - cursor.top();
+ if (dy < 0)
+ return -1;
+ int w = 10000 * dy;
+ int dx1 = cursor.left() - other.right();
+ int dx2 = cursor.right() - other.left();
+ w += dx1 * (dx1 > 0);
+ w += dx2 * (dx2 > 0);
+ return w;
+}
+
+static int moveDownWeight(const QRect &cursor, const QRect &other)
+{
+ int dy = other.top() - cursor.bottom();
+ if (dy < 0)
+ return -1;
+ int w = 10000 * dy;
+ int dx1 = cursor.left() - other.right();
+ int dx2 = cursor.right() - other.left();
+ w += dx1 * (dx1 > 0);
+ w += dx2 * (dx2 > 0);
+ return w;
+}
+
void FakeVimPluginPrivate::windowCommand(int key)
{
# define control(n) (256 + n)
- QString code;
switch (key) {
case 'c': case 'C': case control('c'):
- code = Core::Constants::CLOSE;
+ triggerAction(Core::Constants::CLOSE);
break;
case 'n': case 'N': case control('n'):
- code = Core::Constants::GOTONEXT;
+ triggerAction(Core::Constants::GOTONEXT);
break;
case 'o': case 'O': case control('o'):
- code = Core::Constants::REMOVE_ALL_SPLITS;
- code = Core::Constants::REMOVE_CURRENT_SPLIT;
+ //triggerAction(Core::Constants::REMOVE_ALL_SPLITS);
+ triggerAction(Core::Constants::REMOVE_CURRENT_SPLIT);
break;
case 'p': case 'P': case control('p'):
- code = Core::Constants::GOTOPREV;
+ triggerAction(Core::Constants::GOTOPREV);
break;
case 's': case 'S': case control('s'):
- code = Core::Constants::SPLIT;
+ triggerAction(Core::Constants::SPLIT);
break;
case 'w': case 'W': case control('w'):
- code = Core::Constants::GOTO_OTHER_SPLIT;
+ triggerAction(Core::Constants::GOTO_OTHER_SPLIT);
+ break;
+ case Qt::Key_Right:
+ moveSomewhere(&moveRightWeight);
+ break;
+ case Qt::Key_Left:
+ moveSomewhere(&moveLeftWeight);
+ break;
+ case Qt::Key_Up:
+ moveSomewhere(&moveUpWeight);
+ break;
+ case Qt::Key_Down:
+ moveSomewhere(&moveDownWeight);
+ break;
+ default:
+ qDebug() << "UNKNOWN WINDOWS COMMAND: " << key;
break;
}
# undef control
- //qDebug() << "RUNNING WINDOW COMMAND: " << key << code;
- if (code.isEmpty()) {
- //qDebug() << "UNKNOWN WINDOWS COMMAND: " << key;
- return;
+}
+
+void FakeVimPluginPrivate::moveSomewhere(DistFunction f)
+{
+ IEditor *editor = editorManager()->currentEditor();
+ QWidget *w = editor->widget();
+ QPlainTextEdit *pe =
+ qobject_cast<QPlainTextEdit *>(editor->widget());
+ QTC_ASSERT(pe, return);
+ QRect rc = pe->cursorRect();
+ QRect cursorRect(w->mapToGlobal(rc.topLeft()),
+ w->mapToGlobal(rc.bottomRight()));
+ //qDebug() << "\nCURSOR: " << cursorRect;
+
+ IEditor *bestEditor = 0;
+ int bestValue = 1 << 30;
+
+ QList<IEditor*> editors = editorManager()->visibleEditors();
+ foreach (IEditor *editor, editors) {
+ QWidget *w = editor->widget();
+ QRect editorRect(w->mapToGlobal(w->geometry().topLeft()),
+ w->mapToGlobal(w->geometry().bottomRight()));
+ //qDebug() << " EDITOR: " << editorRect << editor;
+
+ int value = f(cursorRect, editorRect);
+ if (value != -1 && value < bestValue) {
+ bestValue = value;
+ bestEditor = editor;
+ //qDebug() << " BEST SO FAR: " << bestValue << bestEditor;
+ }
}
- triggerAction(code);
+ //qDebug() << " BEST: " << bestValue << bestEditor;
+
+ // FIME: This is know to fail as the EditorManager will fall back to
+ // the current editor's view. Needs additional public API there.
+ if (bestEditor)
+ editorManager()->activateEditor(bestEditor);
}
void FakeVimPluginPrivate::find(bool reverse)
@@ -913,7 +1017,7 @@ void FakeVimPluginPrivate::triggerCompletions()
if (!handler)
return;
if (BaseTextEditor *bt = qobject_cast<BaseTextEditor *>(handler->widget()))
- TextEditor::Internal::CompletionSupport::instance()->
+ TextEditor::CompletionSupport::instance()->
autoComplete(bt->editableInterface(), false);
// bt->triggerCompletions();
}
@@ -942,7 +1046,7 @@ void FakeVimPluginPrivate::checkForElectricCharacter(bool *result, QChar c)
if (!handler)
return;
if (BaseTextEditor *bt = qobject_cast<BaseTextEditor *>(handler->widget()))
- *result = bt->isElectricCharacter(c);
+ *result = bt->indenter()->isElectricCharacter(c);
}
void FakeVimPluginPrivate::handleExCommand(bool *handled, const ExCommand &cmd)
@@ -1010,12 +1114,12 @@ void FakeVimPluginPrivate::handleExCommand(bool *handled, const ExCommand &cmd)
// :se[t]
showSettingsDialog();
} else if (cmd.args == "ic" || cmd.args == "ignorecase") {
- // :set noic
+ // :set nc
setActionChecked(Find::Constants::CASE_SENSITIVE, false);
- *handled = false; // Let the handler see it as well.
} else if (cmd.args == "noic" || cmd.args == "noignorecase") {
// :set noic
setActionChecked(Find::Constants::CASE_SENSITIVE, true);
+ } else {
*handled = false; // Let the handler see it as well.
}
} else if (cmd.matches("n", "next")) {
@@ -1139,7 +1243,7 @@ void FakeVimPluginPrivate::indentRegion(int beginLine, int endLine,
while (!cursor.atBlockEnd())
cursor.deleteChar();
} else {
- bt->indentBlock(doc, block, typedChar);
+ bt->indenter()->indentBlock(doc, block, typedChar, bt);
}
block = block.next();
}
@@ -1177,8 +1281,8 @@ void FakeVimPluginPrivate::changeSelection
int FakeVimPluginPrivate::currentFile() const
{
Core::OpenEditorsModel *model = editorManager()->openedEditorsModel();
- IEditor *cur = Core::EditorManager::instance()->currentEditor();
- return model->indexOf(cur).row();
+ IEditor *editor = editorManager()->currentEditor();
+ return model->indexOf(editor).row();
}
void FakeVimPluginPrivate::switchToFile(int n)
diff --git a/src/plugins/find/Find.pluginspec b/src/plugins/find/Find.pluginspec
deleted file mode 100644
index a79dceeb5f..0000000000
--- a/src/plugins/find/Find.pluginspec
+++ /dev/null
@@ -1,19 +0,0 @@
-<plugin name="Find" version="2.0.95" compatVersion="2.0.95">
- <vendor>Nokia Corporation</vendor>
- <copyright>(C) 2010 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>
- <category>Qt Creator</category>
- <description>Provides the find widget and the hooks for find implementations.</description>
- <url>http://qt.nokia.com</url>
- <dependencyList>
- <dependency name="Core" version="2.0.95"/>
- </dependencyList>
-</plugin>
diff --git a/src/plugins/find/Find.pluginspec.in b/src/plugins/find/Find.pluginspec.in
new file mode 100644
index 0000000000..7fb4144b43
--- /dev/null
+++ b/src/plugins/find/Find.pluginspec.in
@@ -0,0 +1,19 @@
+<plugin name=\"Find\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2010 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>
+ <category>Qt Creator</category>
+ <description>Provides the find widget and the hooks for find implementations.</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/find/find.pri b/src/plugins/find/find.pri
index b28aec122f..5ab55ec434 100644
--- a/src/plugins/find/find.pri
+++ b/src/plugins/find/find.pri
@@ -1,3 +1,3 @@
include(find_dependencies.pri)
-LIBS *= -l$$qtLibraryTarget(Find)
+LIBS *= -l$$qtLibraryName(Find)
diff --git a/src/plugins/find/find.pro b/src/plugins/find/find.pro
index d0f67a405c..c0c93d3625 100644
--- a/src/plugins/find/find.pro
+++ b/src/plugins/find/find.pro
@@ -32,5 +32,3 @@ SOURCES += findtoolwindow.cpp \
FORMS += findwidget.ui \
finddialog.ui
RESOURCES += find.qrc
-
-OTHER_FILES += Find.pluginspec
diff --git a/src/plugins/genericprojectmanager/GenericProjectManager.pluginspec b/src/plugins/genericprojectmanager/GenericProjectManager.pluginspec
deleted file mode 100644
index 9303e5848c..0000000000
--- a/src/plugins/genericprojectmanager/GenericProjectManager.pluginspec
+++ /dev/null
@@ -1,22 +0,0 @@
-<plugin name="GenericProjectManager" version="2.0.95" compatVersion="2.0.95">
- <vendor>Nokia Corporation</vendor>
- <copyright>(C) 2010 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>
- <category>Build Systems</category>
- <description>Generic support</description>
- <url>http://qt.nokia.com</url>
- <dependencyList>
- <dependency name="TextEditor" version="2.0.95"/>
- <dependency name="ProjectExplorer" version="2.0.95"/>
- <dependency name="CppTools" version="2.0.95"/>
- <dependency name="CppEditor" version="2.0.95"/>
- </dependencyList>
-</plugin>
diff --git a/src/plugins/genericprojectmanager/GenericProjectManager.pluginspec.in b/src/plugins/genericprojectmanager/GenericProjectManager.pluginspec.in
new file mode 100644
index 0000000000..3b77ffeba7
--- /dev/null
+++ b/src/plugins/genericprojectmanager/GenericProjectManager.pluginspec.in
@@ -0,0 +1,21 @@
+<plugin name=\"GenericProjectManager\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2010 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>
+ <category>Build Systems</category>
+ <description>Generic support</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name=\"TextEditor\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"ProjectExplorer\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"CppTools\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/genericprojectmanager/genericbuildconfiguration.cpp b/src/plugins/genericprojectmanager/genericbuildconfiguration.cpp
index 1321847187..000d28787a 100644
--- a/src/plugins/genericprojectmanager/genericbuildconfiguration.cpp
+++ b/src/plugins/genericprojectmanager/genericbuildconfiguration.cpp
@@ -38,6 +38,7 @@
#include "generictarget.h"
#include <projectexplorer/buildsteplist.h>
+#include <projectexplorer/toolchain.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <utils/qtcassert.h>
@@ -88,11 +89,6 @@ bool GenericBuildConfiguration::fromMap(const QVariantMap &map)
return BuildConfiguration::fromMap(map);
}
-Utils::Environment GenericBuildConfiguration::environment() const
-{
- return Utils::Environment::systemEnvironment();
-}
-
QString GenericBuildConfiguration::buildDirectory() const
{
// Convert to absolute path when necessary
diff --git a/src/plugins/genericprojectmanager/genericbuildconfiguration.h b/src/plugins/genericprojectmanager/genericbuildconfiguration.h
index 43e1d38cd2..d650dd3934 100644
--- a/src/plugins/genericprojectmanager/genericbuildconfiguration.h
+++ b/src/plugins/genericprojectmanager/genericbuildconfiguration.h
@@ -53,7 +53,6 @@ public:
GenericTarget *genericTarget() const;
- virtual Utils::Environment environment() const;
virtual QString buildDirectory() const;
QString rawBuildDirectory() const;
diff --git a/src/plugins/genericprojectmanager/genericmakestep.cpp b/src/plugins/genericprojectmanager/genericmakestep.cpp
index 763003cf39..9cf8adbbeb 100644
--- a/src/plugins/genericprojectmanager/genericmakestep.cpp
+++ b/src/plugins/genericprojectmanager/genericmakestep.cpp
@@ -44,7 +44,9 @@
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/gnumakeparser.h>
#include <coreplugin/variablemanager.h>
+#include <utils/stringutils.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <QtGui/QFormLayout>
#include <QtGui/QGroupBox>
@@ -106,19 +108,17 @@ bool GenericMakeStep::init()
GenericBuildConfiguration *bc = genericBuildConfiguration();
setEnabled(true);
- Core::VariableManager *vm = Core::VariableManager::instance();
- const QString rawBuildDir = bc->buildDirectory();
- const QString buildDir = vm->resolve(rawBuildDir);
- setWorkingDirectory(buildDir);
-
- setCommand(makeCommand());
- setArguments(replacedArguments());
-
- setEnvironment(bc->environment());
-
- setOutputParser(new ProjectExplorer::GnuMakeParser(buildDir));
+ ProjectExplorer::ProcessParameters *pp = processParameters();
+ pp->setMacroExpander(bc->macroExpander());
+ pp->setWorkingDirectory(bc->buildDirectory());
+ pp->setEnvironment(bc->environment());
+ pp->setCommand(makeCommand());
+ pp->setArguments(allArguments());
+
+ setOutputParser(new ProjectExplorer::GnuMakeParser());
if (bc->genericTarget()->genericProject()->toolChain())
appendOutputParser(bc->genericTarget()->genericProject()->toolChain()->outputParser());
+ outputParser()->setWorkingDirectory(pp->effectiveWorkingDirectory());
return AbstractProcessStep::init();
}
@@ -136,25 +136,17 @@ QVariantMap GenericMakeStep::toMap() const
bool GenericMakeStep::fromMap(const QVariantMap &map)
{
m_buildTargets = map.value(QLatin1String(BUILD_TARGETS_KEY)).toStringList();
- m_makeArguments = map.value(QLatin1String(MAKE_ARGUMENTS_KEY)).toStringList();
+ m_makeArguments = map.value(QLatin1String(MAKE_ARGUMENTS_KEY)).toString();
m_makeCommand = map.value(QLatin1String(MAKE_COMMAND_KEY)).toString();
return BuildStep::fromMap(map);
}
-QStringList GenericMakeStep::replacedArguments() const
+QString GenericMakeStep::allArguments() const
{
- Core::VariableManager *vm = Core::VariableManager::instance();
- const QStringList targets = m_buildTargets;
- QStringList arguments = m_makeArguments;
- QStringList replacedArguments;
- foreach (const QString &arg, arguments) {
- replacedArguments.append(vm->resolve(arg));
- }
- foreach (const QString &arg, targets) {
- replacedArguments.append(vm->resolve(arg));
- }
- return replacedArguments;
+ QString args = m_makeArguments;
+ Utils::QtcProcess::addArgs(&args, m_buildTargets);
+ return args;
}
QString GenericMakeStep::makeCommand() const
@@ -247,11 +239,8 @@ void GenericMakeStepConfigWidget::init()
{
updateMakeOverrrideLabel();
- QString makeCommand = m_makeStep->m_makeCommand;
- m_ui->makeLineEdit->setText(makeCommand);
-
- const QStringList &makeArguments = m_makeStep->m_makeArguments;
- m_ui->makeArgumentsLineEdit->setText(Utils::Environment::joinArgumentList(makeArguments));
+ m_ui->makeLineEdit->setText(m_makeStep->m_makeCommand);
+ m_ui->makeArgumentsLineEdit->setText(m_makeStep->m_makeArguments);
// Disconnect to make the changes to the items
disconnect(m_ui->targetsList, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(itemChanged(QListWidgetItem*)));
@@ -269,9 +258,15 @@ void GenericMakeStepConfigWidget::init()
void GenericMakeStepConfigWidget::updateDetails()
{
- m_summaryText = tr("<b>Make:</b> %1 %2")
- .arg(m_makeStep->makeCommand(),
- Utils::Environment::joinArgumentList(m_makeStep->replacedArguments()));
+ GenericBuildConfiguration *bc = m_makeStep->genericBuildConfiguration();
+
+ ProjectExplorer::ProcessParameters param;
+ param.setMacroExpander(bc->macroExpander());
+ param.setWorkingDirectory(bc->buildDirectory());
+ param.setEnvironment(bc->environment());
+ param.setCommand(m_makeStep->makeCommand());
+ param.setArguments(m_makeStep->allArguments());
+ m_summaryText = param.summary(displayName());
emit updateSummary();
}
@@ -294,8 +289,7 @@ void GenericMakeStepConfigWidget::makeLineEditTextEdited()
void GenericMakeStepConfigWidget::makeArgumentsLineEditTextEdited()
{
- m_makeStep->m_makeArguments =
- Utils::Environment::parseCombinedArgString(m_ui->makeArgumentsLineEdit->text());
+ m_makeStep->m_makeArguments = m_ui->makeArgumentsLineEdit->text();
updateDetails();
}
diff --git a/src/plugins/genericprojectmanager/genericmakestep.h b/src/plugins/genericprojectmanager/genericmakestep.h
index 665e6d9495..2c2c1f81eb 100644
--- a/src/plugins/genericprojectmanager/genericmakestep.h
+++ b/src/plugins/genericprojectmanager/genericmakestep.h
@@ -71,7 +71,7 @@ public:
virtual bool immutable() const;
bool buildsTarget(const QString &target) const;
void setBuildTarget(const QString &target, bool on);
- QStringList replacedArguments() const;
+ QString allArguments() const;
QString makeCommand() const;
QVariantMap toMap() const;
@@ -85,7 +85,7 @@ private:
void ctor();
QStringList m_buildTargets;
- QStringList m_makeArguments;
+ QString m_makeArguments;
QString m_makeCommand;
};
diff --git a/src/plugins/genericprojectmanager/genericproject.cpp b/src/plugins/genericprojectmanager/genericproject.cpp
index 130e84c746..84913d2096 100644
--- a/src/plugins/genericprojectmanager/genericproject.cpp
+++ b/src/plugins/genericprojectmanager/genericproject.cpp
@@ -68,7 +68,6 @@ const char * const TOOLCHAIN_KEY("GenericProjectManager.GenericProject.Toolchain
GenericProject::GenericProject(Manager *manager, const QString &fileName)
: m_manager(manager),
m_fileName(fileName),
- m_targetFactory(new GenericTargetFactory(this)),
m_toolChain(0)
{
QFileInfo fileInfo(m_fileName);
@@ -94,11 +93,6 @@ GenericProject::~GenericProject()
delete m_toolChain;
}
-GenericTargetFactory *GenericProject::targetFactory() const
-{
- return m_targetFactory;
-}
-
GenericTarget *GenericProject::activeTarget() const
{
return static_cast<GenericTarget *>(Project::activeTarget());
@@ -334,7 +328,7 @@ void GenericProject::setIncludePaths(const QStringList &includePaths)
QByteArray GenericProject::defines() const
{ return m_defines; }
-void GenericProject::setToolChainType(ProjectExplorer::ToolChain::ToolChainType type)
+void GenericProject::setToolChainType(ProjectExplorer::ToolChainType type)
{
using namespace ProjectExplorer;
@@ -343,23 +337,23 @@ void GenericProject::setToolChainType(ProjectExplorer::ToolChain::ToolChainType
delete m_toolChain;
m_toolChain = 0;
- if (type == ToolChain::MinGW) {
+ if (type == ToolChain_MinGW) {
const QLatin1String qmake_cxx("g++"); // ### FIXME
const QString mingwDirectory; // ### FIXME
m_toolChain = ToolChain::createMinGWToolChain(qmake_cxx, mingwDirectory);
- } else if (type == ToolChain::MSVC) {
+ } else if (type == ToolChain_MSVC) {
const QString msvcVersion; // ### FIXME
m_toolChain = ToolChain::createMSVCToolChain(msvcVersion, false);
- } else if (type == ToolChain::WINCE) {
+ } else if (type == ToolChain_WINCE) {
const QString msvcVersion, wincePlatform; // ### FIXME
m_toolChain = ToolChain::createWinCEToolChain(msvcVersion, wincePlatform);
- } else if (type == ToolChain::GCC) {
+ } else if (type == ToolChain_GCC) {
const QLatin1String qmake_cxx("g++"); // ### FIXME
m_toolChain = ToolChain::createGccToolChain(qmake_cxx);
- } else if (type == ToolChain::LINUX_ICC) {
+ } else if (type == ToolChain_LINUX_ICC) {
m_toolChain = ToolChain::createLinuxIccToolChain();
}
}
@@ -369,7 +363,7 @@ ProjectExplorer::ToolChain *GenericProject::toolChain() const
return m_toolChain;
}
-ProjectExplorer::ToolChain::ToolChainType GenericProject::toolChainType() const
+ProjectExplorer::ToolChainType GenericProject::toolChainType() const
{ return m_toolChainType; }
QString GenericProject::displayName() const
@@ -397,11 +391,6 @@ QList<ProjectExplorer::Project *> GenericProject::dependsOn()
return QList<Project *>();
}
-ProjectExplorer::BuildConfigWidget *GenericProject::createConfigWidget()
-{
- return new GenericBuildSettingsWidget(this);
-}
-
QList<ProjectExplorer::BuildConfigWidget*> GenericProject::subConfigWidgets()
{
QList<ProjectExplorer::BuildConfigWidget*> list;
@@ -453,11 +442,14 @@ bool GenericProject::fromMap(const QVariantMap &map)
}
// Add default setup:
- if (targets().isEmpty())
- addTarget(targetFactory()->create(this, QLatin1String(GENERIC_DESKTOP_TARGET_ID)));
+ if (targets().isEmpty()) {
+ GenericTargetFactory *factory =
+ ExtensionSystem::PluginManager::instance()->getObject<GenericTargetFactory>();
+ addTarget(factory->create(this, QLatin1String(GENERIC_DESKTOP_TARGET_ID)));
+ }
- ToolChain::ToolChainType type =
- static_cast<ProjectExplorer::ToolChain::ToolChainType>
+ ToolChainType type =
+ static_cast<ProjectExplorer::ToolChainType>
(map.value(QLatin1String(TOOLCHAIN_KEY), 0).toInt());
setToolChainType(type);
@@ -472,8 +464,8 @@ bool GenericProject::fromMap(const QVariantMap &map)
// GenericBuildSettingsWidget
////////////////////////////////////////////////////////////////////////////////////
-GenericBuildSettingsWidget::GenericBuildSettingsWidget(GenericProject *project)
- : m_project(project), m_buildConfiguration(0)
+GenericBuildSettingsWidget::GenericBuildSettingsWidget(GenericTarget *target)
+ : m_target(target), m_buildConfiguration(0)
{
QFormLayout *fl = new QFormLayout(this);
fl->setContentsMargins(0, -1, 0, -1);
@@ -482,7 +474,7 @@ GenericBuildSettingsWidget::GenericBuildSettingsWidget(GenericProject *project)
// build directory
m_pathChooser = new Utils::PathChooser(this);
m_pathChooser->setEnabled(true);
- m_pathChooser->setBaseDirectory(project->projectDirectory());
+ m_pathChooser->setBaseDirectory(m_target->genericProject()->projectDirectory());
fl->addRow(tr("Build directory:"), m_pathChooser);
connect(m_pathChooser, SIGNAL(changed(QString)), this, SLOT(buildDirectoryChanged()));
@@ -492,9 +484,9 @@ GenericBuildSettingsWidget::GenericBuildSettingsWidget(GenericProject *project)
using namespace ProjectExplorer;
int index = 0;
int selectedIndex = -1;
- foreach (ToolChain::ToolChainType tc, ToolChain::supportedToolChains()) {
- toolChainChooser->addItem(ToolChain::toolChainName(tc), QVariant::fromValue<ToolChain::ToolChainType>(tc));
- if (m_project->toolChainType() == tc)
+ foreach (ToolChainType tc, ToolChain::supportedToolChains()) {
+ toolChainChooser->addItem(ToolChain::toolChainName(tc), QVariant::fromValue<ToolChainType>(tc));
+ if (m_target->genericProject()->toolChainType() == tc)
selectedIndex = index;
++index;
}
@@ -526,8 +518,8 @@ void GenericBuildSettingsWidget::toolChainSelected(int index)
using namespace ProjectExplorer;
QComboBox *toolChainChooser = qobject_cast<QComboBox*>(sender());
- ToolChain::ToolChainType type = toolChainChooser->itemData(index).value<ToolChain::ToolChainType>();
- m_project->setToolChainType(type);
+ ToolChainType type = toolChainChooser->itemData(index).value<ToolChainType>();
+ m_target->genericProject()->setToolChainType(type);
}
////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/plugins/genericprojectmanager/genericproject.h b/src/plugins/genericprojectmanager/genericproject.h
index cd66cfadab..3bb3f5a5bd 100644
--- a/src/plugins/genericprojectmanager/genericproject.h
+++ b/src/plugins/genericprojectmanager/genericproject.h
@@ -42,7 +42,7 @@
#include <projectexplorer/projectnodes.h>
#include <projectexplorer/target.h>
#include <projectexplorer/buildstep.h>
-#include <projectexplorer/toolchain.h>
+#include <projectexplorer/toolchaintype.h>
#include <projectexplorer/buildconfiguration.h>
#include <coreplugin/ifile.h>
@@ -52,12 +52,15 @@ namespace Utils {
class PathChooser;
}
+namespace ProjectExplorer {
+class ToolChain;
+}
+
namespace GenericProjectManager {
namespace Internal {
class GenericBuildConfiguration;
class GenericProject;
class GenericTarget;
-class GenericTargetFactory;
class GenericMakeStep;
class GenericProjectFile;
@@ -76,13 +79,11 @@ public:
QString displayName() const;
QString id() const;
Core::IFile *file() const;
- GenericTargetFactory *targetFactory() const;
ProjectExplorer::IProjectManager *projectManager() const;
GenericTarget *activeTarget() const;
QList<ProjectExplorer::Project *> dependsOn();
- ProjectExplorer::BuildConfigWidget *createConfigWidget();
QList<ProjectExplorer::BuildConfigWidget*> subConfigWidgets();
GenericProjectNode *rootProjectNode() const;
@@ -110,8 +111,8 @@ public:
QStringList projectIncludePaths() const;
QStringList files() const;
QStringList generated() const;
- ProjectExplorer::ToolChain::ToolChainType toolChainType() const;
- void setToolChainType(ProjectExplorer::ToolChain::ToolChainType type);
+ ProjectExplorer::ToolChainType toolChainType() const;
+ void setToolChainType(ProjectExplorer::ToolChainType type);
QVariantMap toMap() const;
@@ -131,7 +132,6 @@ private:
QString m_configFileName;
GenericProjectFile *m_file;
QString m_projectName;
- GenericTargetFactory *m_targetFactory;
QStringList m_rawFileList;
QStringList m_files;
@@ -143,7 +143,7 @@ private:
GenericProjectNode *m_rootNode;
ProjectExplorer::ToolChain *m_toolChain;
- ProjectExplorer::ToolChain::ToolChainType m_toolChainType;
+ ProjectExplorer::ToolChainType m_toolChainType;
QFuture<void> m_codeModelFuture;
};
@@ -180,7 +180,7 @@ class GenericBuildSettingsWidget : public ProjectExplorer::BuildConfigWidget
Q_OBJECT
public:
- GenericBuildSettingsWidget(GenericProject *project);
+ GenericBuildSettingsWidget(GenericTarget *target);
virtual ~GenericBuildSettingsWidget();
virtual QString displayName() const;
@@ -192,7 +192,7 @@ private Q_SLOTS:
void toolChainSelected(int index);
private:
- GenericProject *m_project;
+ GenericTarget *m_target;
Utils::PathChooser *m_pathChooser;
GenericBuildConfiguration *m_buildConfiguration;
};
diff --git a/src/plugins/genericprojectmanager/genericprojectmanager.h b/src/plugins/genericprojectmanager/genericprojectmanager.h
index 8ceef2c2aa..0bcfa5175e 100644
--- a/src/plugins/genericprojectmanager/genericprojectmanager.h
+++ b/src/plugins/genericprojectmanager/genericprojectmanager.h
@@ -35,6 +35,7 @@
#define GENERICPROJECTMANAGER_H
#include <projectexplorer/iprojectmanager.h>
+#include <coreplugin/icontext.h>
namespace GenericProjectManager {
namespace Internal {
diff --git a/src/plugins/genericprojectmanager/genericprojectmanager.pro b/src/plugins/genericprojectmanager/genericprojectmanager.pro
index 0c3e3ee304..48a51d874e 100644
--- a/src/plugins/genericprojectmanager/genericprojectmanager.pro
+++ b/src/plugins/genericprojectmanager/genericprojectmanager.pro
@@ -25,4 +25,3 @@ SOURCES = genericproject.cpp \
genericbuildconfiguration.cpp
RESOURCES += genericproject.qrc
FORMS += genericmakestep.ui
-OTHER_FILES += GenericProjectManager.pluginspec
diff --git a/src/plugins/genericprojectmanager/genericprojectmanager_dependencies.pri b/src/plugins/genericprojectmanager/genericprojectmanager_dependencies.pri
index 80118ad122..78430f853b 100644
--- a/src/plugins/genericprojectmanager/genericprojectmanager_dependencies.pri
+++ b/src/plugins/genericprojectmanager/genericprojectmanager_dependencies.pri
@@ -1,4 +1,3 @@
include(../../plugins/projectexplorer/projectexplorer.pri)
include(../../plugins/cpptools/cpptools.pri)
-include(../../plugins/cppeditor/cppeditor.pri)
include(../../plugins/texteditor/texteditor.pri)
diff --git a/src/plugins/genericprojectmanager/genericprojectplugin.cpp b/src/plugins/genericprojectmanager/genericprojectplugin.cpp
index ba40370ccd..1636f12d8e 100644
--- a/src/plugins/genericprojectmanager/genericprojectplugin.cpp
+++ b/src/plugins/genericprojectmanager/genericprojectplugin.cpp
@@ -37,6 +37,7 @@
#include "genericprojectconstants.h"
#include "genericprojectfileseditor.h"
#include "genericmakestep.h"
+#include "generictarget.h"
#include <coreplugin/icore.h>
#include <coreplugin/mimedatabase.h>
@@ -82,6 +83,7 @@ bool GenericProjectPlugin::initialize(const QStringList &, QString *errorMessage
addAutoReleasedObject(manager);
addAutoReleasedObject(new GenericMakeStepFactory);
addAutoReleasedObject(new GenericProjectWizard);
+ addAutoReleasedObject(new GenericTargetFactory);
return true;
}
diff --git a/src/plugins/genericprojectmanager/generictarget.cpp b/src/plugins/genericprojectmanager/generictarget.cpp
index ab29550755..42b4cb12f2 100644
--- a/src/plugins/genericprojectmanager/generictarget.cpp
+++ b/src/plugins/genericprojectmanager/generictarget.cpp
@@ -70,6 +70,11 @@ GenericTarget::~GenericTarget()
{
}
+ProjectExplorer::BuildConfigWidget *GenericTarget::createConfigWidget()
+{
+ return new GenericBuildSettingsWidget(this);
+}
+
GenericProject *GenericTarget::genericProject() const
{
return static_cast<GenericProject *>(project());
@@ -111,6 +116,11 @@ GenericTargetFactory::~GenericTargetFactory()
{
}
+bool GenericTargetFactory::supportsTargetId(const QString &id) const
+{
+ return id == QLatin1String(GENERIC_DESKTOP_TARGET_ID);
+}
+
QStringList GenericTargetFactory::availableCreationIds(ProjectExplorer::Project *parent) const
{
if (!qobject_cast<GenericProject *>(parent))
diff --git a/src/plugins/genericprojectmanager/generictarget.h b/src/plugins/genericprojectmanager/generictarget.h
index 2f0f57c76a..53449e1bb8 100644
--- a/src/plugins/genericprojectmanager/generictarget.h
+++ b/src/plugins/genericprojectmanager/generictarget.h
@@ -65,6 +65,8 @@ public:
explicit GenericTarget(GenericProject *parent);
~GenericTarget();
+ ProjectExplorer::BuildConfigWidget *createConfigWidget();
+
GenericProject *genericProject() const;
GenericBuildConfigurationFactory *buildConfigurationFactory() const;
@@ -87,6 +89,8 @@ public:
explicit GenericTargetFactory(QObject *parent = 0);
~GenericTargetFactory();
+ bool supportsTargetId(const QString &id) const;
+
QStringList availableCreationIds(ProjectExplorer::Project *parent) const;
QString displayNameForId(const QString &id) const;
diff --git a/src/plugins/git/ScmGit.pluginspec b/src/plugins/git/ScmGit.pluginspec
deleted file mode 100644
index e6030ad26d..0000000000
--- a/src/plugins/git/ScmGit.pluginspec
+++ /dev/null
@@ -1,22 +0,0 @@
-<plugin name="ScmGit" version="2.0.95" compatVersion="2.0.95">
- <vendor>Nokia Corporation</vendor>
- <copyright>(C) 2010 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>
- <category>Version Control</category>
- <description>Git integration.</description>
- <url>http://qt.nokia.com</url>
- <dependencyList>
- <dependency name="TextEditor" version="2.0.95"/>
- <dependency name="ProjectExplorer" version="2.0.95"/>
- <dependency name="Core" version="2.0.95"/>
- <dependency name="VCSBase" version="2.0.95"/>
- </dependencyList>
-</plugin>
diff --git a/src/plugins/git/ScmGit.pluginspec.in b/src/plugins/git/ScmGit.pluginspec.in
new file mode 100644
index 0000000000..d81d4d4731
--- /dev/null
+++ b/src/plugins/git/ScmGit.pluginspec.in
@@ -0,0 +1,22 @@
+<plugin name=\"ScmGit\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2010 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>
+ <category>Version Control</category>
+ <description>Git integration.</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name=\"TextEditor\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"ProjectExplorer\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"VCSBase\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/git/changeselectiondialog.cpp b/src/plugins/git/changeselectiondialog.cpp
index 71962ca66b..342d6aa77e 100644
--- a/src/plugins/git/changeselectiondialog.cpp
+++ b/src/plugins/git/changeselectiondialog.cpp
@@ -43,6 +43,7 @@ ChangeSelectionDialog::ChangeSelectionDialog(QWidget *parent)
: QDialog(parent)
{
m_ui.setupUi(this);
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
connect(m_ui.repositoryButton, SIGNAL(clicked()), this, SLOT(selectWorkingDirectory()));
setWindowTitle(tr("Select a Git Commit"));
}
@@ -60,6 +61,9 @@ QString ChangeSelectionDialog::repository() const
void ChangeSelectionDialog::setRepository(const QString &s)
{
m_ui.repositoryEdit->setText(QDir::toNativeSeparators(s));
+ m_ui.changeNumberEdit->setFocus(Qt::ActiveWindowFocusReason);
+ m_ui.changeNumberEdit->setText(QLatin1String("HEAD"));
+ m_ui.changeNumberEdit->selectAll();
}
void ChangeSelectionDialog::selectWorkingDirectory()
diff --git a/src/plugins/git/changeselectiondialog.ui b/src/plugins/git/changeselectiondialog.ui
index b2f368e686..704596b3a8 100644
--- a/src/plugins/git/changeselectiondialog.ui
+++ b/src/plugins/git/changeselectiondialog.ui
@@ -6,13 +6,13 @@
<rect>
<x>0</x>
<y>0</y>
- <width>327</width>
- <height>91</height>
+ <width>359</width>
+ <height>115</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="sizeConstraint">
- <enum>QLayout::SetMinAndMaxSize</enum>
+ <enum>QLayout::SetDefaultConstraint</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label">
diff --git a/src/plugins/git/clonewizardpage.cpp b/src/plugins/git/clonewizardpage.cpp
index f04292d4dd..8a3af9407a 100644
--- a/src/plugins/git/clonewizardpage.cpp
+++ b/src/plugins/git/clonewizardpage.cpp
@@ -132,7 +132,7 @@ QString CloneWizardPage::directoryFromRepository(const QString &urlIn) const
}
// fix invalid characters
const QChar dash = QLatin1Char('-');
- url.replace(QRegExp(QLatin1String("[^0-9a-zA-Z_-]")), dash);
+ url.replace(QRegExp(QLatin1String("[^0-9a-zA-Z_.-]")), dash);
// trim leading dashes (they are annoying and get created when using local pathes)
url.replace(QRegExp(QLatin1String("^-+")), QString());
return url;
diff --git a/src/plugins/git/git.pro b/src/plugins/git/git.pro
index 7ffe7d8999..435519768a 100644
--- a/src/plugins/git/git.pro
+++ b/src/plugins/git/git.pro
@@ -48,7 +48,6 @@ FORMS += changeselectiondialog.ui \
gitsubmitpanel.ui \
branchdialog.ui \
stashdialog.ui
-OTHER_FILES += ScmGit.pluginspec
include(gitorious/gitorious.pri)
RESOURCES += \
diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp
index 5a8a159edf..be02c7fadb 100644
--- a/src/plugins/git/gitclient.cpp
+++ b/src/plugins/git/gitclient.cpp
@@ -53,6 +53,7 @@
#include <texteditor/itexteditor.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <utils/synchronousprocess.h>
#include <utils/environment.h>
#include <vcsbase/vcsbaseeditor.h>
@@ -66,13 +67,289 @@
#include <QtCore/QDir>
#include <QtCore/QSignalMapper>
+#include <QtGui/QComboBox>
#include <QtGui/QMainWindow> // for msg box parent
#include <QtGui/QMessageBox>
-#include <QtGui/QPushButton>
+#include <QtGui/QToolButton>
static const char *const kGitDirectoryC = ".git";
static const char *const kBranchIndicatorC = "# On branch";
+namespace Git {
+namespace Internal {
+
+BaseGitArgumentsWidget::BaseGitArgumentsWidget(GitSettings *settings,
+ Git::Internal::GitClient *client,
+ const QString &directory,
+ const QStringList &args) :
+ QWidget(0),
+ m_client(client),
+ m_workingDirectory(directory),
+ m_diffArgs(args),
+ m_settings(settings)
+{
+ Q_ASSERT(settings);
+ Q_ASSERT(client);
+}
+
+} // namespace Internal
+} // namespace Git
+
+namespace {
+
+class BaseGitDiffArgumentsWidget : public Git::Internal::BaseGitArgumentsWidget
+{
+public:
+ BaseGitDiffArgumentsWidget(Git::Internal::GitSettings *settings,
+ Git::Internal::GitClient *client,
+ const QString &directory,
+ const QStringList &args) :
+ BaseGitArgumentsWidget(settings, client, directory, args),
+ m_patience(0),
+ m_ignoreSpaces(0)
+ {
+ QHBoxLayout * layout = new QHBoxLayout(this);
+ layout->setContentsMargins(3, 0, 3, 0);
+
+ m_patience = new QToolButton;
+ m_patience->setToolTip(tr("Use the patience algorithmn for calculating the diff"));
+ m_patience->setText(tr("Patience"));
+ layout->addWidget(m_patience);
+ m_patience->setCheckable(true);
+ m_patience->setChecked(m_settings->diffPatience);
+ connect(m_patience, SIGNAL(toggled(bool)), this, SLOT(testForArgumentsChanged()));
+
+ m_ignoreSpaces = new QToolButton;
+ m_ignoreSpaces->setToolTip(tr("Ignore whitespaces only changes"));
+ m_ignoreSpaces->setText(tr("Ignore Whitespace"));
+ layout->addWidget(m_ignoreSpaces);
+ m_ignoreSpaces->setCheckable(true);
+ m_ignoreSpaces->setChecked(m_settings->ignoreSpaceChangesInDiff);
+ connect(m_ignoreSpaces, SIGNAL(toggled(bool)), this, SLOT(testForArgumentsChanged()));
+
+ m_prettyFormat = new QComboBox;
+ m_prettyFormat->setToolTip(tr("Select the pretty printing format"));
+ m_prettyFormat->addItem(tr("oneline"), QLatin1String("oneline"));
+ m_prettyFormat->addItem(tr("short"), QLatin1String("short"));
+ m_prettyFormat->addItem(tr("medium"), QLatin1String("medium"));
+ m_prettyFormat->addItem(tr("full"), QLatin1String("full"));
+ m_prettyFormat->addItem(tr("fuller"), QLatin1String("fuller"));
+ m_prettyFormat->addItem(tr("email"), QLatin1String("email"));
+ m_prettyFormat->addItem(tr("raw"), QLatin1String("raw"));
+ layout->addWidget(m_prettyFormat);
+ m_prettyFormat->setCurrentIndex(m_settings->showPrettyFormat);
+ m_prettyFormat->setVisible(false);
+ connect(m_prettyFormat, SIGNAL(currentIndexChanged(int)), this, SLOT(testForArgumentsChanged()));
+ }
+
+ QStringList arguments() const
+ {
+ QStringList args;
+ foreach (const QString &arg, m_diffArgs) {
+ if (arg == QLatin1String("--patience")
+ || arg == QLatin1String("--ignore-space-change")
+ || arg.startsWith(QLatin1String("--pretty="))
+ || arg.startsWith(QLatin1String("--format=")))
+ continue;
+ args.append(arg);
+ }
+
+ if (m_patience->isChecked() && m_patience->isVisible())
+ args.prepend(QLatin1String("--patience"));
+ if (m_ignoreSpaces->isChecked() && m_ignoreSpaces->isVisible())
+ args.prepend(QLatin1String("--ignore-space-change"));
+ if (m_prettyFormat->isVisible()) {
+ args.prepend(QString::fromLatin1("--pretty=")
+ + m_prettyFormat->itemData(m_prettyFormat->currentIndex()).toString());
+ }
+
+ return args;
+ }
+
+ void testForArgumentsChanged() {
+ m_settings->diffPatience = m_patience->isChecked();
+ m_settings->ignoreSpaceChangesInDiff = m_ignoreSpaces->isChecked();
+ m_settings->showPrettyFormat = m_prettyFormat->currentIndex();
+
+ QStringList newArguments = arguments();
+
+ if (newArguments == m_diffArgs)
+ return;
+
+ m_diffArgs = newArguments;
+ redoCommand();
+ }
+
+protected:
+ QToolButton *m_patience;
+ QToolButton *m_ignoreSpaces;
+ QComboBox *m_prettyFormat;
+};
+
+class GitCommitDiffArgumentsWidget : public BaseGitDiffArgumentsWidget
+{
+public:
+ GitCommitDiffArgumentsWidget(Git::Internal::GitSettings *settings,
+ Git::Internal::GitClient *client, const QString &directory,
+ const QStringList &args, const QStringList &unstaged,
+ const QStringList &staged) :
+ BaseGitDiffArgumentsWidget(settings, client, directory, args),
+ m_unstagedFileNames(unstaged),
+ m_stagedFileNames(staged)
+ { }
+
+ void redoCommand()
+ {
+ m_client->diff(m_workingDirectory, m_diffArgs, m_unstagedFileNames, m_stagedFileNames);
+ }
+
+private:
+ const QStringList m_unstagedFileNames;
+ const QStringList m_stagedFileNames;
+};
+
+class GitFileDiffArgumentsWidget : public BaseGitDiffArgumentsWidget
+{
+public:
+ GitFileDiffArgumentsWidget(Git::Internal::GitSettings *settings,
+ Git::Internal::GitClient *client, const QString &directory,
+ const QStringList &args, const QString &file) :
+ BaseGitDiffArgumentsWidget(settings, client, directory, args),
+ m_fileName(file)
+ { }
+
+ void redoCommand()
+ {
+ m_client->diff(m_workingDirectory, m_diffArgs, m_fileName);
+ }
+
+private:
+ const QString m_fileName;
+};
+
+class GitBranchDiffArgumentsWidget : public BaseGitDiffArgumentsWidget
+{
+public:
+ GitBranchDiffArgumentsWidget(Git::Internal::GitSettings *settings,
+ Git::Internal::GitClient *client, const QString &directory,
+ const QStringList &args, const QString &branch) :
+ BaseGitDiffArgumentsWidget(settings, client, directory, args),
+ m_branchName(branch)
+ { }
+
+ void redoCommand()
+ {
+ m_client->diffBranch(m_workingDirectory, m_diffArgs, m_branchName);
+ }
+
+private:
+ const QString m_branchName;
+};
+
+class GitShowArgumentsWidget : public BaseGitDiffArgumentsWidget
+{
+public:
+ GitShowArgumentsWidget(Git::Internal::GitSettings *settings,
+ Git::Internal::GitClient *client, const QString &directory,
+ const QStringList &args, const QString &id) :
+ BaseGitDiffArgumentsWidget(settings, client, directory, args),
+ m_id(id)
+ {
+ m_patience->setVisible(false);
+ m_ignoreSpaces->setVisible(false);
+ m_prettyFormat->setVisible(true);
+ }
+
+ void redoCommand()
+ {
+ m_client->show(m_workingDirectory, m_id, m_diffArgs);
+ }
+
+private:
+ const QString m_id;
+};
+
+
+class GitBlameArgumentsWidget : public Git::Internal::BaseGitArgumentsWidget
+{
+public:
+ GitBlameArgumentsWidget(Git::Internal::GitSettings *settings,
+ Git::Internal::GitClient *client, const QString &directory,
+ const QStringList &args, const QString &revision,
+ const QString &fileName) :
+ Git::Internal::BaseGitArgumentsWidget(settings, client, directory, args),
+ m_omitDate(0),
+ m_ignoreSpaces(0),
+ m_editor(0),
+ m_revision(revision),
+ m_fileName(fileName)
+ {
+ QHBoxLayout * layout = new QHBoxLayout(this);
+ layout->setContentsMargins(3, 0, 3, 0);
+
+ m_omitDate = new QToolButton;
+ m_omitDate->setToolTip(tr("Do not show the date a change was made in the output"));
+ m_omitDate->setText(tr("Omit Date"));
+ layout->addWidget(m_omitDate);
+ m_omitDate->setCheckable(true);
+ m_omitDate->setChecked(m_settings->omitAnnotationDate);
+ m_omitDate->setMinimumHeight(16);
+ m_omitDate->setMaximumHeight(16);
+ connect(m_omitDate, SIGNAL(toggled(bool)), this, SLOT(testForArgumentsChanged()));
+
+ m_ignoreSpaces = new QToolButton;
+ m_ignoreSpaces->setToolTip(tr("Ignore whitespace only changes"));
+ m_ignoreSpaces->setText(tr("Ignore Whitespace"));
+ layout->addWidget(m_ignoreSpaces);
+ m_ignoreSpaces->setCheckable(true);
+ m_ignoreSpaces->setChecked(m_settings->ignoreSpaceChangesInBlame);
+ m_ignoreSpaces->setMinimumHeight(16);
+ m_ignoreSpaces->setMaximumHeight(16);
+ connect(m_ignoreSpaces, SIGNAL(toggled(bool)), this, SLOT(testForArgumentsChanged()));
+ }
+
+ void setEditor(VCSBase::VCSBaseEditor *editor)
+ {
+ Q_ASSERT(editor);
+ m_editor = editor;
+ }
+
+ QStringList arguments() const
+ {
+ QStringList args = m_diffArgs;
+
+ args.removeAll(QLatin1String("-w"));
+
+ if (m_ignoreSpaces->isChecked())
+ args.prepend(QLatin1String("-w"));
+
+ return args;
+ }
+
+ void testForArgumentsChanged() {
+ m_settings->omitAnnotationDate = m_omitDate->isChecked();
+ m_settings->ignoreSpaceChangesInBlame = m_ignoreSpaces->isChecked();
+
+ m_diffArgs = arguments();
+ redoCommand(); // always redo for omit date
+ }
+
+ void redoCommand()
+ {
+ m_client->blame(m_workingDirectory, m_diffArgs, m_fileName,
+ m_revision, m_editor->lineNumberOfCurrentEditor());
+ }
+
+private:
+ QToolButton *m_omitDate;
+ QToolButton *m_ignoreSpaces;
+ VCSBase::VCSBaseEditor *m_editor;
+ QString m_revision;
+ QString m_fileName;
+};
+
+} // namespace
+
inline Core::IEditor* locateEditor(const Core::ICore *core, const char *property, const QString &entry)
{
foreach (Core::IEditor *ed, core->editorManager()->openedEditors())
@@ -150,41 +427,57 @@ QString GitClient::findRepositoryForDirectory(const QString &dir)
return VCSBase::VCSBasePlugin::findRepositoryForDirectory(dir, checkFile);
}
+VCSBase::VCSBaseEditor *GitClient::findExistingVCSEditor(const char *registerDynamicProperty,
+ const QString &dynamicPropertyValue) const
+{
+ VCSBase::VCSBaseEditor *rc = 0;
+ Core::IEditor *outputEditor = locateEditor(m_core, registerDynamicProperty, dynamicPropertyValue);
+ if (!outputEditor)
+ return 0;
+
+ // Exists already
+ Core::EditorManager::instance()->activateEditor(outputEditor, Core::EditorManager::ModeSwitch);
+ outputEditor->createNew(m_msgWait);
+ rc = VCSBase::VCSBaseEditor::getVcsBaseEditor(outputEditor);
+
+ return rc;
+}
+
+
/* Create an editor associated to VCS output of a source file/directory
* (using the file's codec). Makes use of a dynamic property to find an
* existing instance and to reuse it (in case, say, 'git diff foo' is
* already open). */
-VCSBase::VCSBaseEditor
- *GitClient::createVCSEditor(const QString &id,
- QString title,
- // Source file or directory
- const QString &source,
- bool setSourceCodec,
- // Dynamic property and value to identify that editor
- const char *registerDynamicProperty,
- const QString &dynamicPropertyValue) const
+VCSBase::VCSBaseEditor *GitClient::createVCSEditor(const QString &id,
+ QString title,
+ // Source file or directory
+ const QString &source,
+ bool setSourceCodec,
+ // Dynamic property and value to identify that editor
+ const char *registerDynamicProperty,
+ const QString &dynamicPropertyValue,
+ QWidget *configWidget) const
{
VCSBase::VCSBaseEditor *rc = 0;
- Core::IEditor* outputEditor = locateEditor(m_core, registerDynamicProperty, dynamicPropertyValue);
- if (outputEditor) {
- // Exists already
- outputEditor->createNew(m_msgWait);
- rc = VCSBase::VCSBaseEditor::getVcsBaseEditor(outputEditor);
- QTC_ASSERT(rc, return 0);
- } else {
- // Create new, set wait message, set up with source and codec
- outputEditor = m_core->editorManager()->openEditorWithContents(id, &title, m_msgWait);
- outputEditor->file()->setProperty(registerDynamicProperty, dynamicPropertyValue);
- rc = VCSBase::VCSBaseEditor::getVcsBaseEditor(outputEditor);
- connect(rc, SIGNAL(annotateRevisionRequested(QString,QString,int)),
- this, SLOT(slotBlameRevisionRequested(QString,QString,int)));
- QTC_ASSERT(rc, return 0);
- rc->setSource(source);
- if (setSourceCodec)
- rc->setCodec(VCSBase::VCSBaseEditor::getCodec(source));
- }
+ Q_ASSERT(!findExistingVCSEditor(registerDynamicProperty, dynamicPropertyValue));
+
+ // Create new, set wait message, set up with source and codec
+ Core::IEditor *outputEditor = m_core->editorManager()->openEditorWithContents(id, &title, m_msgWait);
+ outputEditor->file()->setProperty(registerDynamicProperty, dynamicPropertyValue);
+ rc = VCSBase::VCSBaseEditor::getVcsBaseEditor(outputEditor);
+ connect(rc, SIGNAL(annotateRevisionRequested(QString,QString,int)),
+ this, SLOT(slotBlameRevisionRequested(QString,QString,int)));
+ QTC_ASSERT(rc, return 0);
+ rc->setSource(source);
+ if (setSourceCodec)
+ rc->setCodec(VCSBase::VCSBaseEditor::getCodec(source));
+
m_core->editorManager()->activateEditor(outputEditor, Core::EditorManager::ModeSwitch);
rc->setForceReadOnly(true);
+
+ if (configWidget)
+ rc->setConfigurationWidget(configWidget);
+
return rc;
}
@@ -201,7 +494,17 @@ void GitClient::diff(const QString &workingDirectory,
const QString editorId = QLatin1String(Git::Constants::GIT_DIFF_EDITOR_ID);
const QString title = tr("Git Diff");
- VCSBase::VCSBaseEditor *editor = createVCSEditor(editorId, title, workingDirectory, true, "originalFileName", workingDirectory);
+ QStringList userDiffArgs = diffArgs;
+ VCSBase::VCSBaseEditor *editor = findExistingVCSEditor("originalFileName", workingDirectory);
+ if (!editor) {
+ GitCommitDiffArgumentsWidget *argWidget =
+ new GitCommitDiffArgumentsWidget(&m_settings, this, workingDirectory, diffArgs,
+ unstagedFileNames, stagedFileNames);
+ userDiffArgs = argWidget->arguments();
+
+ editor = createVCSEditor(editorId, title,
+ workingDirectory, true, "originalFileName", workingDirectory, argWidget);
+ }
editor->setDiffBaseDirectory(workingDirectory);
// Create a batch of 2 commands to be run after each other in case
@@ -209,27 +512,27 @@ void GitClient::diff(const QString &workingDirectory,
// when using the submit dialog.
GitCommand *command = createCommand(workingDirectory, editor);
// Directory diff?
- QStringList commonDiffArgs;
- commonDiffArgs << QLatin1String("diff") << QLatin1String(noColorOption);
- if (m_settings.diffPatience)
- commonDiffArgs << QLatin1String("--patience");
- if (m_settings.ignoreSpaceChanges)
- commonDiffArgs << QLatin1String("--ignore-space-change");
+
+ QStringList cmdArgs;
+ cmdArgs << QLatin1String("diff") << QLatin1String(noColorOption);
+
if (unstagedFileNames.empty() && stagedFileNames.empty()) {
- QStringList arguments(commonDiffArgs);
- arguments << diffArgs;
+ QStringList arguments(cmdArgs);
+ arguments << userDiffArgs;
outputWindow()->appendCommand(workingDirectory, binary, arguments);
command->addJob(arguments, m_settings.timeoutSeconds);
} else {
// Files diff.
if (!unstagedFileNames.empty()) {
- QStringList arguments(commonDiffArgs);
+ QStringList arguments(cmdArgs);
+ arguments << userDiffArgs;
arguments << QLatin1String("--") << unstagedFileNames;
outputWindow()->appendCommand(workingDirectory, binary, arguments);
command->addJob(arguments, m_settings.timeoutSeconds);
}
if (!stagedFileNames.empty()) {
- QStringList arguments(commonDiffArgs);
+ QStringList arguments(cmdArgs);
+ arguments << userDiffArgs;
arguments << QLatin1String("--cached") << diffArgs << QLatin1String("--") << stagedFileNames;
outputWindow()->appendCommand(workingDirectory, binary, arguments);
command->addJob(arguments, m_settings.timeoutSeconds);
@@ -242,18 +545,28 @@ void GitClient::diff(const QString &workingDirectory,
const QStringList &diffArgs,
const QString &fileName)
{
- if (Git::Constants::debug)
- qDebug() << "diff" << workingDirectory << fileName;
- QStringList arguments;
- arguments << QLatin1String("diff") << QLatin1String(noColorOption)
- << diffArgs;
- if (!fileName.isEmpty())
- arguments << QLatin1String("--") << fileName;
const QString editorId = QLatin1String(Git::Constants::GIT_DIFF_EDITOR_ID);
const QString title = tr("Git Diff %1").arg(fileName);
const QString sourceFile = VCSBase::VCSBaseEditor::getSource(workingDirectory, fileName);
- VCSBase::VCSBaseEditor *editor = createVCSEditor(editorId, title, sourceFile, true, "originalFileName", sourceFile);
- executeGit(workingDirectory, arguments, editor);
+
+ QStringList userDiffArgs = diffArgs;
+ VCSBase::VCSBaseEditor *editor = findExistingVCSEditor("originalFileName", sourceFile);
+ if (!editor) {
+ GitFileDiffArgumentsWidget *argWidget =
+ new GitFileDiffArgumentsWidget(&m_settings, this, workingDirectory,
+ diffArgs, fileName);
+ userDiffArgs = argWidget->arguments();
+
+ editor = createVCSEditor(editorId, title, sourceFile, true, "originalFileName", sourceFile, argWidget);
+ }
+
+ QStringList cmdArgs;
+ cmdArgs << QLatin1String("diff") << QLatin1String(noColorOption)
+ << userDiffArgs;
+
+ if (!fileName.isEmpty())
+ cmdArgs << QLatin1String("--") << fileName;
+ executeGit(workingDirectory, cmdArgs, editor);
}
void GitClient::diffBranch(const QString &workingDirectory,
@@ -262,16 +575,27 @@ void GitClient::diffBranch(const QString &workingDirectory,
{
if (Git::Constants::debug)
qDebug() << "diffBranch" << workingDirectory << branchName;
- QStringList arguments;
- arguments << QLatin1String("diff") << QLatin1String(noColorOption)
- << diffArgs << branchName;
const QString editorId = QLatin1String(Git::Constants::GIT_DIFF_EDITOR_ID);
const QString title = tr("Git Diff Branch %1").arg(branchName);
const QString sourceFile = VCSBase::VCSBaseEditor::getSource(workingDirectory, QStringList());
- VCSBase::VCSBaseEditor *editor = createVCSEditor(editorId, title, sourceFile, true,
- "BranchName", branchName);
- executeGit(workingDirectory, arguments, editor);
+
+ QStringList userDiffArgs = diffArgs;
+ VCSBase::VCSBaseEditor *editor = findExistingVCSEditor("BranchName", branchName);
+ if (!editor) {
+ GitBranchDiffArgumentsWidget *argWidget =
+ new GitBranchDiffArgumentsWidget(&m_settings, this, workingDirectory,
+ diffArgs, branchName);
+ userDiffArgs = argWidget->arguments();
+
+ editor = createVCSEditor(editorId, title, sourceFile, true, "BranchName", branchName, argWidget);
+ }
+
+ QStringList cmdArgs;
+ cmdArgs << QLatin1String("diff") << QLatin1String(noColorOption)
+ << diffArgs << branchName;
+
+ executeGit(workingDirectory, cmdArgs, editor);
}
void GitClient::status(const QString &workingDirectory)
@@ -311,7 +635,9 @@ void GitClient::graphLog(const QString &workingDirectory, const QString & branch
}
const QString editorId = QLatin1String(Git::Constants::GIT_LOG_EDITOR_ID);
const QString sourceFile = VCSBase::VCSBaseEditor::getSource(workingDirectory, QStringList());
- VCSBase::VCSBaseEditor *editor = createVCSEditor(editorId, title, sourceFile, false, "logFileName", sourceFile);
+ VCSBase::VCSBaseEditor *editor = findExistingVCSEditor("logFileName", sourceFile);
+ if (!editor)
+ editor = createVCSEditor(editorId, title, sourceFile, false, "logFileName", sourceFile, 0);
executeGit(workingDirectory, arguments, editor);
}
@@ -334,7 +660,9 @@ void GitClient::log(const QString &workingDirectory, const QStringList &fileName
const QString title = tr("Git Log %1").arg(msgArg);
const QString editorId = QLatin1String(Git::Constants::GIT_LOG_EDITOR_ID);
const QString sourceFile = VCSBase::VCSBaseEditor::getSource(workingDirectory, fileNames);
- VCSBase::VCSBaseEditor *editor = createVCSEditor(editorId, title, sourceFile, false, "logFileName", sourceFile);
+ VCSBase::VCSBaseEditor *editor = findExistingVCSEditor("logFileName", sourceFile);
+ if (!editor)
+ editor = createVCSEditor(editorId, title, sourceFile, false, "logFileName", sourceFile, 0);
editor->setFileLogAnnotateEnabled(enableAnnotationContextMenu);
executeGit(workingDirectory, arguments, editor);
}
@@ -354,7 +682,7 @@ static inline QString msgCannotShow(const QString &sha)
return GitClient::tr("Cannot describe '%1'.").arg(sha);
}
-void GitClient::show(const QString &source, const QString &id)
+void GitClient::show(const QString &source, const QString &id, const QStringList &args)
{
if (Git::Constants::debug)
qDebug() << "show" << source << id;
@@ -363,12 +691,22 @@ void GitClient::show(const QString &source, const QString &id)
return;
}
- QStringList arguments;
- arguments << QLatin1String("show") << QLatin1String(noColorOption) << id;
-
+ QStringList userArgs = args;
const QString title = tr("Git Show %1").arg(id);
const QString editorId = QLatin1String(Git::Constants::GIT_DIFF_EDITOR_ID);
- VCSBase::VCSBaseEditor *editor = createVCSEditor(editorId, title, source, true, "show", id);
+ VCSBase::VCSBaseEditor *editor = findExistingVCSEditor("show", id);
+ if (!editor) {
+ GitShowArgumentsWidget *argWidget =
+ new GitShowArgumentsWidget(&m_settings, this, source,
+ QStringList(), id);
+ userArgs = argWidget->arguments();
+ editor = createVCSEditor(editorId, title, source, true, "show", id, argWidget);
+ }
+
+ QStringList arguments;
+ arguments << QLatin1String("show") << QLatin1String(noColorOption);
+ arguments.append(userArgs);
+ arguments << id;
const QFileInfo sourceFi(source);
const QString workDir = sourceFi.isDir() ? sourceFi.absoluteFilePath() : sourceFi.absolutePath();
@@ -383,29 +721,41 @@ void GitClient::slotBlameRevisionRequested(const QString &source, QString change
if (blankPos != -1)
change.truncate(blankPos);
const QFileInfo fi(source);
- blame(fi.absolutePath(), fi.fileName(), change, lineNumber);
+ blame(fi.absolutePath(), QStringList(), fi.fileName(), change, lineNumber);
}
void GitClient::blame(const QString &workingDirectory,
+ const QStringList &args,
const QString &fileName,
const QString &revision /* = QString() */,
int lineNumber /* = -1 */)
{
if (Git::Constants::debug)
- qDebug() << "blame" << workingDirectory << fileName << lineNumber;
- QStringList arguments(QLatin1String("blame"));
- arguments << QLatin1String("--root");
- if (m_plugin->settings().ignoreSpaceChanges)
- arguments << QLatin1String("-w");
- arguments << QLatin1String("--") << fileName;
- if (!revision.isEmpty())
- arguments << revision;
+ qDebug() << "blame" << workingDirectory << fileName << lineNumber << args;
+
const QString editorId = QLatin1String(Git::Constants::GIT_BLAME_EDITOR_ID);
const QString id = VCSBase::VCSBaseEditor::getTitleId(workingDirectory, QStringList(fileName), revision);
const QString title = tr("Git Blame %1").arg(id);
const QString sourceFile = VCSBase::VCSBaseEditor::getSource(workingDirectory, fileName);
- VCSBase::VCSBaseEditor *editor = createVCSEditor(editorId, title, sourceFile, true, "blameFileName", id);
+ QStringList userBlameArgs = args;
+ VCSBase::VCSBaseEditor *editor = findExistingVCSEditor("blameFileName", id);
+ if (!editor) {
+ GitBlameArgumentsWidget *argWidget =
+ new GitBlameArgumentsWidget(&m_settings, this, workingDirectory, userBlameArgs,
+ revision, fileName);
+ editor = createVCSEditor(editorId, title, sourceFile, true, "blameFileName", id, argWidget);
+ argWidget->setEditor(editor);
+
+ userBlameArgs = argWidget->arguments();
+ }
+
+ QStringList arguments(QLatin1String("blame"));
+ arguments << QLatin1String("--root");
+ arguments.append(userBlameArgs);
+ arguments << QLatin1String("--") << fileName;
+ if (!revision.isEmpty())
+ arguments << revision;
executeGit(workingDirectory, arguments, editor, false, GitCommand::NoReport, lineNumber);
}
@@ -1356,7 +1706,7 @@ bool GitClient::tryLauchingGitK(const QProcessEnvironment &env,
#endif
VCSBase::VCSBaseOutputWindow *outwin = VCSBase::VCSBaseOutputWindow::instance();
if (!m_settings.gitkOptions.isEmpty())
- arguments.append(m_settings.gitkOptions.split(QLatin1Char(' ')));
+ arguments.append(Utils::QtcProcess::splitArgs(m_settings.gitkOptions));
outwin->appendCommand(workingDirectory, binary, arguments);
// This should always use QProcess::startDetached (as not to kill
// the child), but that does not have an environment parameter.
@@ -1779,7 +2129,9 @@ void GitClient::subversionLog(const QString &workingDirectory)
const QString title = tr("Git SVN Log");
const QString editorId = QLatin1String(Git::Constants::C_GIT_COMMAND_LOG_EDITOR);
const QString sourceFile = VCSBase::VCSBaseEditor::getSource(workingDirectory, QStringList());
- VCSBase::VCSBaseEditor *editor = createVCSEditor(editorId, title, sourceFile, false, "svnLog", sourceFile);
+ VCSBase::VCSBaseEditor *editor = findExistingVCSEditor("svnLog", sourceFile);
+ if (!editor)
+ editor = createVCSEditor(editorId, title, sourceFile, false, "svnLog", sourceFile, 0);
executeGit(workingDirectory, arguments, editor);
}
diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h
index 11d0036a3a..c81917bf0d 100644
--- a/src/plugins/git/gitclient.h
+++ b/src/plugins/git/gitclient.h
@@ -41,8 +41,10 @@
#include <QtCore/QString>
#include <QtCore/QStringList>
+#include <QtGui/QWidget>
QT_BEGIN_NAMESPACE
+class QCheckBox;
class QErrorMessage;
class QSignalMapper;
class QDebug;
@@ -69,7 +71,7 @@ class GitOutputWindow;
class GitCommand;
struct CommitData;
struct GitSubmitEditorPanelData;
-struct Stash;
+class Stash;
class GitClient : public QObject
{
@@ -95,7 +97,7 @@ public:
void graphLog(const QString &workingDirectory, const QString &branch);
void log(const QString &workingDirectory, const QStringList &fileNames,
bool enableAnnotationContextMenu = false);
- void blame(const QString &workingDirectory, const QString &fileName,
+ void blame(const QString &workingDirectory, const QStringList &args, const QString &fileName,
const QString &revision = QString(), int lineNumber = -1);
void checkout(const QString &workingDirectory, const QString &file);
void checkoutBranch(const QString &workingDirectory, const QString &branch);
@@ -227,18 +229,21 @@ public:
static const char *noColorOption;
public slots:
- void show(const QString &source, const QString &id);
+ void show(const QString &source, const QString &id, const QStringList &args = QStringList());
private slots:
void slotBlameRevisionRequested(const QString &source, QString change, int lineNumber);
private:
+ VCSBase::VCSBaseEditor *findExistingVCSEditor(const char *registerDynamicProperty,
+ const QString &dynamicPropertyValue) const;
VCSBase::VCSBaseEditor *createVCSEditor(const QString &kind,
- QString title,
- const QString &source,
- bool setSourceCodec,
- const char *registerDynamicProperty,
- const QString &dynamicPropertyValue) const;
+ QString title,
+ const QString &source,
+ bool setSourceCodec,
+ const char *registerDynamicProperty,
+ const QString &dynamicPropertyValue,
+ QWidget *configWidget) const;
GitCommand *createCommand(const QString &workingDirectory,
VCSBase::VCSBaseEditor* editor = 0,
@@ -292,6 +297,28 @@ private:
bool m_hasCachedGitVersion;
};
+class BaseGitArgumentsWidget : public QWidget {
+ Q_OBJECT
+
+public:
+ BaseGitArgumentsWidget(GitSettings *settings,
+ GitClient *client, const QString &directory,
+ const QStringList &args);
+
+ virtual QStringList arguments() const = 0;
+ virtual void redoCommand() = 0;
+
+protected slots:
+ virtual void testForArgumentsChanged() = 0;
+
+protected:
+ GitClient *m_client;
+
+ const QString m_workingDirectory;
+ QStringList m_diffArgs;
+ GitSettings *m_settings;
+};
+
} // namespace Internal
} // namespace Git
diff --git a/src/plugins/git/giteditor.cpp b/src/plugins/git/giteditor.cpp
index 71066a7271..ee736b3c3d 100644
--- a/src/plugins/git/giteditor.cpp
+++ b/src/plugins/git/giteditor.cpp
@@ -118,7 +118,7 @@ QString GitEditor::changeUnderCursor(const QTextCursor &c) const
VCSBase::DiffHighlighter *GitEditor::createDiffHighlighter() const
{
- const QRegExp filePattern(QLatin1String("^[-+][-+][-+] [ab].*"));
+ const QRegExp filePattern(QLatin1String("^(diff --git a/|index |[+-][+-][+-] [ab]).*$"));
return new VCSBase::DiffHighlighter(filePattern);
}
diff --git a/src/plugins/git/giteditor.h b/src/plugins/git/giteditor.h
index 91091294a0..5d85e05fa8 100644
--- a/src/plugins/git/giteditor.h
+++ b/src/plugins/git/giteditor.h
@@ -51,7 +51,7 @@ class GitEditor : public VCSBase::VCSBaseEditor
public:
explicit GitEditor(const VCSBase::VCSBaseEditorParameters *type,
- QWidget *parent);
+ QWidget *parent);
public slots:
void setPlainTextDataFiltered(const QByteArray &a);
diff --git a/src/plugins/git/gitorious/gitorious.h b/src/plugins/git/gitorious/gitorious.h
index 54c96e8920..d674470d45 100644
--- a/src/plugins/git/gitorious/gitorious.h
+++ b/src/plugins/git/gitorious/gitorious.h
@@ -57,7 +57,7 @@ struct GitoriousRepository
CloneRepository,
BaselineRepository, // Nokia extension
SharedRepository, // Nokia extension
- PersonalRepository, // Nokia extension
+ PersonalRepository // Nokia extension
};
GitoriousRepository();
diff --git a/src/plugins/git/gitplugin.cpp b/src/plugins/git/gitplugin.cpp
index 82e8a2b6cc..116fbc9b29 100644
--- a/src/plugins/git/gitplugin.cpp
+++ b/src/plugins/git/gitplugin.cpp
@@ -52,6 +52,7 @@
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/command.h>
+#include <coreplugin/uniqueidmanager.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/filemanager.h>
@@ -599,7 +600,7 @@ void GitPlugin::blameFile()
const VCSBase::VCSBasePluginState state = currentState();
QTC_ASSERT(state.hasFile(), return)
const int lineNumber = VCSBase::VCSBaseEditor::lineNumberOfCurrentEditor(state.currentFile());
- m_gitClient->blame(state.currentFileTopLevel(), state.relativeCurrentFile(), QString(), lineNumber);
+ m_gitClient->blame(state.currentFileTopLevel(), QStringList(), state.relativeCurrentFile(), QString(), lineNumber);
}
void GitPlugin::logProject()
@@ -759,8 +760,8 @@ bool GitPlugin::submitEditorAboutToClose(VCSBase::VCSBaseSubmitEditor *submitEdi
const VCSBase::VCSBaseSubmitEditor::PromptSubmitResult answer =
editor->promptSubmit(tr("Closing Git Editor"),
tr("Do you want to commit the change?"),
- tr("The commit message check failed. Do you want to commit the change?"),
- &settings.promptToSubmit, !m_submitActionTriggered);
+ tr("Git will not accept this commit. Do you want to continue to edit it?"),
+ &settings.promptToSubmit, !m_submitActionTriggered, false);
m_submitActionTriggered = false;
switch (answer) {
case VCSBase::VCSBaseSubmitEditor::SubmitCanceled:
diff --git a/src/plugins/git/gitsettings.cpp b/src/plugins/git/gitsettings.cpp
index 7596bf2a66..5c4016b42d 100644
--- a/src/plugins/git/gitsettings.cpp
+++ b/src/plugins/git/gitsettings.cpp
@@ -48,10 +48,12 @@ static const char timeoutKeyC[] = "TimeOut";
static const char pullRebaseKeyC[] = "PullRebase";
static const char promptToSubmitKeyC[] = "PromptForSubmit";
static const char omitAnnotationDateKeyC[] = "OmitAnnotationDate";
-static const char ignoreSpaceChangesC[] = "SpaceIgnorantBlame";
+static const char ignoreSpaceChangesBlameKeyC[] = "SpaceIgnorantBlame";
+static const char ignoreSpaceChangesDiffKeyC[] = "SpaceIgnorantDiff";
static const char diffPatienceKeyC[] = "DiffPatience";
static const char winSetHomeEnvironmentKeyC[] = "WinSetHomeEnvironment";
static const char gitkOptionsKeyC[] = "GitKOptions";
+static const char showPrettyFormatC[] = "DiffPrettyFormat";
enum {
defaultPullRebase = 0,
@@ -73,9 +75,11 @@ GitSettings::GitSettings() :
pullRebase(bool(defaultPullRebase)),
promptToSubmit(true),
omitAnnotationDate(false),
- ignoreSpaceChanges(true),
+ ignoreSpaceChangesInDiff(false),
+ ignoreSpaceChangesInBlame(true),
diffPatience(true),
- winSetHomeEnvironment(false)
+ winSetHomeEnvironment(false),
+ showPrettyFormat(5)
{
}
@@ -89,10 +93,12 @@ void GitSettings::fromSettings(QSettings *settings)
pullRebase = settings->value(QLatin1String(pullRebaseKeyC), bool(defaultPullRebase)).toBool();
promptToSubmit = settings->value(QLatin1String(promptToSubmitKeyC), true).toBool();
omitAnnotationDate = settings->value(QLatin1String(omitAnnotationDateKeyC), false).toBool();
- ignoreSpaceChanges = settings->value(QLatin1String(ignoreSpaceChangesC), true).toBool();
+ ignoreSpaceChangesInDiff = settings->value(QLatin1String(ignoreSpaceChangesDiffKeyC), true).toBool();
+ ignoreSpaceChangesInBlame = settings->value(QLatin1String(ignoreSpaceChangesBlameKeyC), true).toBool();
diffPatience = settings->value(QLatin1String(diffPatienceKeyC), true).toBool();
winSetHomeEnvironment = settings->value(QLatin1String(winSetHomeEnvironmentKeyC), false).toBool();
gitkOptions = settings->value(QLatin1String(gitkOptionsKeyC)).toString();
+ showPrettyFormat = settings->value(QLatin1String(showPrettyFormatC), 5).toInt();
settings->endGroup();
}
@@ -106,10 +112,12 @@ void GitSettings::toSettings(QSettings *settings) const
settings->setValue(QLatin1String(pullRebaseKeyC), pullRebase);
settings->setValue(QLatin1String(promptToSubmitKeyC), promptToSubmit);
settings->setValue(QLatin1String(omitAnnotationDateKeyC), omitAnnotationDate);
- settings->setValue(QLatin1String(ignoreSpaceChangesC), ignoreSpaceChanges);
+ settings->setValue(QLatin1String(ignoreSpaceChangesDiffKeyC), ignoreSpaceChangesInDiff);
+ settings->setValue(QLatin1String(ignoreSpaceChangesBlameKeyC), ignoreSpaceChangesInBlame);
settings->setValue(QLatin1String(diffPatienceKeyC), diffPatience);
settings->setValue(QLatin1String(winSetHomeEnvironmentKeyC), winSetHomeEnvironment);
settings->setValue(QLatin1String(gitkOptionsKeyC), gitkOptions);
+ settings->setValue(QLatin1String(showPrettyFormatC), showPrettyFormat);
settings->endGroup();
}
@@ -118,9 +126,11 @@ bool GitSettings::equals(const GitSettings &s) const
return adoptPath == s.adoptPath && path == s.path && logCount == s.logCount
&& timeoutSeconds == s.timeoutSeconds && promptToSubmit == s.promptToSubmit
&& pullRebase == s.pullRebase
- && omitAnnotationDate == s.omitAnnotationDate && ignoreSpaceChanges == s.ignoreSpaceChanges
+ && omitAnnotationDate == s.omitAnnotationDate
+ && ignoreSpaceChangesInBlame == s.ignoreSpaceChangesInBlame
+ && ignoreSpaceChangesInDiff == s.ignoreSpaceChangesInDiff
&& diffPatience == s.diffPatience && winSetHomeEnvironment == s.winSetHomeEnvironment
- && gitkOptions == s.gitkOptions;
+ && gitkOptions == s.gitkOptions && showPrettyFormat == s.showPrettyFormat;
}
QString GitSettings::gitBinaryPath(bool *ok, QString *errorMessage) const
diff --git a/src/plugins/git/gitsettings.h b/src/plugins/git/gitsettings.h
index b5668ac81f..47a6eb4bec 100644
--- a/src/plugins/git/gitsettings.h
+++ b/src/plugins/git/gitsettings.h
@@ -63,9 +63,11 @@ struct GitSettings
bool pullRebase;
bool promptToSubmit;
bool omitAnnotationDate;
- bool ignoreSpaceChanges;
+ bool ignoreSpaceChangesInDiff;
+ bool ignoreSpaceChangesInBlame;
bool diffPatience;
bool winSetHomeEnvironment;
+ int showPrettyFormat;
QString gitkOptions;
};
diff --git a/src/plugins/git/gitsubmiteditor.cpp b/src/plugins/git/gitsubmiteditor.cpp
index c8d4f7339e..27a095c552 100644
--- a/src/plugins/git/gitsubmiteditor.cpp
+++ b/src/plugins/git/gitsubmiteditor.cpp
@@ -124,25 +124,6 @@ void GitSubmitEditor::slotDiffSelected(const QStringList &files)
emit diff(unstagedFiles, stagedFiles);
}
-QString GitSubmitEditor::fileContents() const
-{
- // We need to manually purge out comment lines starting with
- // hash '#' since git does not do that when using -F.
- const QChar newLine = QLatin1Char('\n');
- const QChar hash = QLatin1Char('#');
- QString message = VCSBase::VCSBaseSubmitEditor::fileContents();
- for (int pos = 0; pos < message.size(); ) {
- const int newLinePos = message.indexOf(newLine, pos);
- const int startOfNextLine = newLinePos == -1 ? message.size() : newLinePos + 1;
- if (message.at(pos) == hash) {
- message.remove(pos, startOfNextLine - pos);
- } else {
- pos = startOfNextLine;
- }
- }
- return message;
-}
-
GitSubmitEditorPanelData GitSubmitEditor::panelData() const
{
return const_cast<GitSubmitEditor*>(this)->submitEditorWidget()->panelData();
diff --git a/src/plugins/git/gitsubmiteditor.h b/src/plugins/git/gitsubmiteditor.h
index 26396bbc45..ace3d0f558 100644
--- a/src/plugins/git/gitsubmiteditor.h
+++ b/src/plugins/git/gitsubmiteditor.h
@@ -58,8 +58,6 @@ public:
void setCommitData(const CommitData &);
GitSubmitEditorPanelData panelData() const;
- virtual QString fileContents() const;
-
signals:
void diff(const QStringList &unstagedFiles, const QStringList &stagedFiles);
diff --git a/src/plugins/git/gitsubmiteditorwidget.cpp b/src/plugins/git/gitsubmiteditorwidget.cpp
index ceb72d1f00..57f8b145a2 100644
--- a/src/plugins/git/gitsubmiteditorwidget.cpp
+++ b/src/plugins/git/gitsubmiteditorwidget.cpp
@@ -155,12 +155,35 @@ void GitSubmitEditorWidget::setPanelData(const GitSubmitEditorPanelData &data)
bool GitSubmitEditorWidget::canSubmit() const
{
+ QString message = cleanupDescription(descriptionText()).trimmed();
+
if (m_gitSubmitPanelUi.invalidAuthorLabel->isVisible()
- || m_gitSubmitPanelUi.invalidEmailLabel->isVisible())
+ || m_gitSubmitPanelUi.invalidEmailLabel->isVisible()
+ || message.isEmpty())
return false;
return SubmitEditorWidget::canSubmit();
}
+QString GitSubmitEditorWidget::cleanupDescription(const QString &input) const
+{
+ // We need to manually purge out comment lines starting with
+ // hash '#' since git does not do that when using -F.
+ const QChar newLine = QLatin1Char('\n');
+ const QChar hash = QLatin1Char('#');
+ QString message = input;
+ for (int pos = 0; pos < message.size(); ) {
+ const int newLinePos = message.indexOf(newLine, pos);
+ const int startOfNextLine = newLinePos == -1 ? message.size() : newLinePos + 1;
+ if (message.at(pos) == hash) {
+ message.remove(pos, startOfNextLine - pos);
+ } else {
+ pos = startOfNextLine;
+ }
+ }
+ return message;
+
+}
+
void GitSubmitEditorWidget::authorInformationChanged()
{
bool bothEmpty = m_gitSubmitPanelUi.authorLineEdit->text().isEmpty() &&
diff --git a/src/plugins/git/gitsubmiteditorwidget.h b/src/plugins/git/gitsubmiteditorwidget.h
index 75273ca2b5..ebb910dc3b 100644
--- a/src/plugins/git/gitsubmiteditorwidget.h
+++ b/src/plugins/git/gitsubmiteditorwidget.h
@@ -71,6 +71,7 @@ public:
protected:
bool canSubmit() const;
+ QString cleanupDescription(const QString &) const;
private slots:
void authorInformationChanged();
diff --git a/src/plugins/git/gitutils.cpp b/src/plugins/git/gitutils.cpp
index 7d174ed4a2..fef48d9e25 100644
--- a/src/plugins/git/gitutils.cpp
+++ b/src/plugins/git/gitutils.cpp
@@ -71,20 +71,14 @@ bool Stash::parseStashLine(const QString &l)
const int messagePos = l.indexOf(colon, branchPos + 1);
if (messagePos < 0)
return false;
- // Name
- const QString newName = l.left(branchPos);
// Branch spec
- const QString branchSpec = l.mid(branchPos + 1, messagePos - branchPos - 1);
- const bool emptyMessage = branchSpec.contains(QLatin1String("WIP")); // "Work in Progress or sth"
- const int onIndex = branchSpec.indexOf(QLatin1String("on "), 0, Qt::CaseInsensitive);
- if (onIndex == -1)
+ const int onIndex = l.indexOf(QLatin1String("on "), branchPos + 2, Qt::CaseInsensitive);
+ if (onIndex == -1 || onIndex >= messagePos)
return false;
- const QString newBranch = branchSpec.mid(onIndex + 3);
// Happy!
- name = newName;
- branch = newBranch;
- if (!emptyMessage)
- message = l.mid(messagePos + 2); // skip blank
+ name = l.left(branchPos);
+ branch = l.mid(onIndex + 3, messagePos - onIndex - 3);
+ message = l.mid(messagePos + 2); // skip blank
return true;
}
diff --git a/src/plugins/git/gitutils.h b/src/plugins/git/gitutils.h
index 2bf417220e..a3a8b7ae73 100644
--- a/src/plugins/git/gitutils.h
+++ b/src/plugins/git/gitutils.h
@@ -44,7 +44,8 @@ QT_END_NAMESPACE
namespace Git {
namespace Internal {
-struct Stash {
+class Stash {
+public:
void clear();
bool parseStashLine(const QString &l);
diff --git a/src/plugins/git/gitversioncontrol.cpp b/src/plugins/git/gitversioncontrol.cpp
index e356cfcce0..f0a06e31f0 100644
--- a/src/plugins/git/gitversioncontrol.cpp
+++ b/src/plugins/git/gitversioncontrol.cpp
@@ -236,7 +236,7 @@ bool GitVersionControl::managesDirectory(const QString &directory, QString *topL
bool GitVersionControl::vcsAnnotate(const QString &file, int line)
{
const QFileInfo fi(file);
- gitClient()->blame(fi.absolutePath(), fi.fileName(), QString(), line);
+ gitClient()->blame(fi.absolutePath(), QStringList(), fi.fileName(), QString(), line);
return true;
}
diff --git a/src/plugins/git/settingspage.cpp b/src/plugins/git/settingspage.cpp
index 84612d02aa..29c4c549d9 100644
--- a/src/plugins/git/settingspage.cpp
+++ b/src/plugins/git/settingspage.cpp
@@ -77,9 +77,6 @@ GitSettings SettingsPageWidget::settings() const
rc.timeoutSeconds = m_ui.timeoutSpinBox->value();
rc.pullRebase = m_ui.pullRebaseCheckBox->isChecked();
rc.promptToSubmit = m_ui.promptToSubmitCheckBox->isChecked();
- rc.omitAnnotationDate = m_ui.omitAnnotationDataCheckBox->isChecked();
- rc.ignoreSpaceChanges = m_ui.spaceIgnorantBlameCheckBox->isChecked();
- rc.diffPatience = m_ui.diffPatienceCheckBox->isChecked();
rc.winSetHomeEnvironment = m_ui.winHomeCheckBox->isChecked();
rc.gitkOptions = m_ui.gitkOptionsLineEdit->text().trimmed();
return rc;
@@ -93,9 +90,6 @@ void SettingsPageWidget::setSettings(const GitSettings &s)
m_ui.timeoutSpinBox->setValue(s.timeoutSeconds);
m_ui.pullRebaseCheckBox->setChecked(s.pullRebase);
m_ui.promptToSubmitCheckBox->setChecked(s.promptToSubmit);
- m_ui.omitAnnotationDataCheckBox->setChecked(s.omitAnnotationDate);
- m_ui.spaceIgnorantBlameCheckBox->setChecked(s.ignoreSpaceChanges);
- m_ui.diffPatienceCheckBox->setChecked(s.diffPatience);
m_ui.winHomeCheckBox->setChecked(s.winSetHomeEnvironment);
m_ui.gitkOptionsLineEdit->setText(s.gitkOptions);
}
@@ -108,13 +102,19 @@ void SettingsPageWidget::setSystemPath()
QString SettingsPageWidget::searchKeywords() const
{
QString rc;
- QTextStream(&rc) << ' ' << m_ui.pathlabel->text() << ' ' << m_ui.logCountLabel->text()
- << ' ' << m_ui.timeoutLabel->text()
- << ' ' << m_ui.promptToSubmitCheckBox->text()
- << ' ' << m_ui.promptToSubmitCheckBox->text()
- << ' ' << m_ui.omitAnnotationDataCheckBox->text()
- << ' ' << m_ui.environmentGroupBox->title()
- << ' ' << m_ui.spaceIgnorantBlameCheckBox->text();
+ QLatin1Char sep(' ');
+ QTextStream(&rc)
+ << sep << m_ui.environmentGroupBox->title()
+ << sep << m_ui.pathlabel->text()
+ << sep << m_ui.winHomeCheckBox->text()
+ << sep << m_ui.groupBox->title()
+ << sep << m_ui.logCountLabel->text()
+ << sep << m_ui.timeoutLabel->text()
+ << sep << m_ui.promptToSubmitCheckBox->text()
+ << sep << m_ui.promptToSubmitCheckBox->text()
+ << sep << m_ui.gitkGroupBox->title()
+ << sep << m_ui.gitkOptionsLabel->text()
+ ;
rc.remove(QLatin1Char('&'));
return rc;
}
diff --git a/src/plugins/git/settingspage.ui b/src/plugins/git/settingspage.ui
index 386de3f01b..6a7eefe881 100644
--- a/src/plugins/git/settingspage.ui
+++ b/src/plugins/git/settingspage.ui
@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
- <width>361</width>
+ <width>390</width>
<height>444</height>
</rect>
</property>
@@ -128,27 +128,6 @@
</property>
</widget>
</item>
- <item row="5" column="0" colspan="2">
- <widget class="QCheckBox" name="omitAnnotationDataCheckBox">
- <property name="text">
- <string>Omit date from blame output</string>
- </property>
- </widget>
- </item>
- <item row="6" column="0" colspan="2">
- <widget class="QCheckBox" name="spaceIgnorantBlameCheckBox">
- <property name="text">
- <string>Ignore whitespace changes in blame and diff</string>
- </property>
- </widget>
- </item>
- <item row="4" column="0">
- <widget class="QCheckBox" name="diffPatienceCheckBox">
- <property name="text">
- <string>Use &quot;patience diff&quot; algorithm</string>
- </property>
- </widget>
- </item>
<item row="3" column="0" colspan="2">
<widget class="QCheckBox" name="pullRebaseCheckBox">
<property name="text">
diff --git a/src/plugins/glsleditor/GLSLEditor.mimetypes.xml b/src/plugins/glsleditor/GLSLEditor.mimetypes.xml
new file mode 100644
index 0000000000..9d2eb6c7db
--- /dev/null
+++ b/src/plugins/glsleditor/GLSLEditor.mimetypes.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
+
+ <mime-type type="application/x-glsl">
+ <alias type="text/x-glsl"/>
+ <sub-class-of type="text/plain"/>
+ <comment>GLSL Shader file</comment>
+ <glob pattern="*.glsl"/>
+ <glob pattern="*.shader"/>
+ </mime-type>
+
+ <mime-type type="text/x-glsl-frag">
+ <sub-class-of type="text/x-glsl"/>
+ <comment>GLSL Fragment Shader file</comment>
+ <glob pattern="*.frag"/>
+ </mime-type>
+
+ <mime-type type="text/x-glsl-es-frag">
+ <sub-class-of type="text/x-glsl"/>
+ <comment>GLSL/ES Fragment Shader file</comment>
+ <glob pattern="*.fsh"/>
+ </mime-type>
+
+ <mime-type type="text/x-glsl-vert">
+ <sub-class-of type="text/x-glsl"/>
+ <comment>GLSL Vertex Shader file</comment>
+ <glob pattern="*.vert"/>
+ </mime-type>
+
+ <mime-type type="text/x-glsl-es-vert">
+ <sub-class-of type="text/x-glsl"/>
+ <comment>GLSL/ES Vertex Shader file</comment>
+ <glob pattern="*.vsh"/>
+ </mime-type>
+
+</mime-info>
diff --git a/src/plugins/glsleditor/GLSLEditor.pluginspec.in b/src/plugins/glsleditor/GLSLEditor.pluginspec.in
new file mode 100644
index 0000000000..2d9be00ce4
--- /dev/null
+++ b/src/plugins/glsleditor/GLSLEditor.pluginspec.in
@@ -0,0 +1,21 @@
+<plugin name=\"GLSLEditor\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2010 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>
+ <category>GLSL</category>
+ <description>Editor for GLSL.</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"TextEditor\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"ProjectExplorer\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/glsleditor/glslautocompleter.cpp b/src/plugins/glsleditor/glslautocompleter.cpp
new file mode 100644
index 0000000000..dc29d26c90
--- /dev/null
+++ b/src/plugins/glsleditor/glslautocompleter.cpp
@@ -0,0 +1,137 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "glslautocompleter.h"
+
+#include <Token.h>
+#include <cplusplus/SimpleLexer.h>
+#include <cplusplus/MatchingText.h>
+#include <cplusplus/BackwardsScanner.h>
+
+#include <QtCore/QLatin1Char>
+#include <QtGui/QTextCursor>
+
+using namespace GLSLEditor;
+using namespace Internal;
+using namespace CPlusPlus;
+
+GLSLCompleter::GLSLCompleter()
+{}
+
+GLSLCompleter::~GLSLCompleter()
+{}
+
+bool GLSLCompleter::contextAllowsAutoParentheses(const QTextCursor &cursor,
+ const QString &textToInsert) const
+{
+ QChar ch;
+
+ if (! textToInsert.isEmpty())
+ ch = textToInsert.at(0);
+
+ if (! (MatchingText::shouldInsertMatchingText(cursor)
+ || ch == QLatin1Char('\'')
+ || ch == QLatin1Char('"')))
+ return false;
+ else if (isInComment(cursor))
+ return false;
+
+ return true;
+}
+
+bool GLSLCompleter::contextAllowsElectricCharacters(const QTextCursor &cursor) const
+{
+ const Token tk = SimpleLexer::tokenAt(cursor.block().text(), cursor.positionInBlock(),
+ BackwardsScanner::previousBlockState(cursor.block()));
+
+ // XXX Duplicated from CPPEditor::isInComment to avoid tokenizing twice
+ if (tk.isComment()) {
+ const unsigned pos = cursor.selectionEnd() - cursor.block().position();
+
+ if (pos == tk.end()) {
+ if (tk.is(T_CPP_COMMENT) || tk.is(T_CPP_DOXY_COMMENT))
+ return false;
+
+ const int state = cursor.block().userState() & 0xFF;
+ if (state > 0)
+ return false;
+ }
+
+ if (pos < tk.end())
+ return false;
+ }
+ else if (tk.is(T_STRING_LITERAL) || tk.is(T_WIDE_STRING_LITERAL)
+ || tk.is(T_CHAR_LITERAL) || tk.is(T_WIDE_CHAR_LITERAL)) {
+
+ const unsigned pos = cursor.selectionEnd() - cursor.block().position();
+ if (pos <= tk.end())
+ return false;
+ }
+
+ return true;
+}
+
+bool GLSLCompleter::isInComment(const QTextCursor &cursor) const
+{
+ const Token tk = SimpleLexer::tokenAt(cursor.block().text(), cursor.positionInBlock(),
+ BackwardsScanner::previousBlockState(cursor.block()));
+
+ if (tk.isComment()) {
+ const unsigned pos = cursor.selectionEnd() - cursor.block().position();
+
+ if (pos == tk.end()) {
+ if (tk.is(T_CPP_COMMENT) || tk.is(T_CPP_DOXY_COMMENT))
+ return true;
+
+ const int state = cursor.block().userState() & 0xFF;
+ if (state > 0)
+ return true;
+ }
+
+ if (pos < tk.end())
+ return true;
+ }
+
+ return false;
+}
+
+QString GLSLCompleter::insertMatchingBrace(const QTextCursor &cursor,
+ const QString &text,
+ QChar la,
+ int *skippedChars) const
+{
+ MatchingText m;
+ return m.insertMatchingBrace(cursor, text, la, skippedChars);
+}
+
+QString GLSLCompleter::insertParagraphSeparator(const QTextCursor &cursor) const
+{
+ MatchingText m;
+ return m.insertParagraphSeparator(cursor);
+}
diff --git a/src/plugins/glsleditor/glslautocompleter.h b/src/plugins/glsleditor/glslautocompleter.h
new file mode 100644
index 0000000000..7ee2ce6957
--- /dev/null
+++ b/src/plugins/glsleditor/glslautocompleter.h
@@ -0,0 +1,62 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** No Commercial Usage
+**
+** This file 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.
+**
+**************************************************************************/
+
+#ifndef GLSLAUTOCOMPLETER_H
+#define GLSLAUTOCOMPLETER_H
+
+#include <texteditor/autocompleter.h>
+
+namespace GLSLEditor {
+namespace Internal {
+
+class GLSLCompleter : public TextEditor::AutoCompleter
+{
+public:
+ GLSLCompleter();
+ virtual ~GLSLCompleter();
+
+ virtual bool contextAllowsAutoParentheses(const QTextCursor &cursor,
+ const QString &textToInsert = QString()) const;
+ virtual bool contextAllowsElectricCharacters(const QTextCursor &cursor) const;
+ virtual bool isInComment(const QTextCursor &cursor) const;
+ virtual QString insertMatchingBrace(const QTextCursor &cursor,
+ const QString &text,
+ QChar la,
+ int *skippedChars) const;
+ virtual QString insertParagraphSeparator(const QTextCursor &cursor) const;
+};
+
+} // Internal
+} // GLSLEditor
+
+#endif // GLSLAUTOCOMPLETER_H
diff --git a/src/plugins/glsleditor/glslcodecompletion.cpp b/src/plugins/glsleditor/glslcodecompletion.cpp
new file mode 100644
index 0000000000..2cbaf211c6
--- /dev/null
+++ b/src/plugins/glsleditor/glslcodecompletion.cpp
@@ -0,0 +1,726 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "glslcodecompletion.h"
+#include "glsleditor.h"
+#include "glsleditorplugin.h"
+#include <glsl/glslengine.h>
+#include <glsl/glslengine.h>
+#include <glsl/glsllexer.h>
+#include <glsl/glslparser.h>
+#include <glsl/glslsemantic.h>
+#include <glsl/glslsymbols.h>
+#include <glsl/glslastdump.h>
+#include <cplusplus/ExpressionUnderCursor.h>
+#include <texteditor/completionsettings.h>
+#include <utils/faketooltip.h>
+#include <QtGui/QIcon>
+#include <QtGui/QPainter>
+#include <QtGui/QLabel>
+#include <QtGui/QToolButton>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QApplication>
+#include <QtGui/QDesktopWidget>
+#include <QtCore/QDebug>
+
+using namespace GLSLEditor;
+using namespace GLSLEditor::Internal;
+
+enum CompletionOrder {
+ SpecialMemberOrder = -5
+};
+
+static bool isIdentifierChar(QChar ch)
+{
+ return ch.isLetterOrNumber() || ch == QLatin1Char('_');
+}
+
+static bool isDelimiter(QChar ch)
+{
+ switch (ch.unicode()) {
+ case '{':
+ case '}':
+ case '[':
+ case ']':
+ case ')':
+ case '?':
+ case '!':
+ case ':':
+ case ';':
+ case ',':
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+static bool checkStartOfIdentifier(const QString &word)
+{
+ if (! word.isEmpty()) {
+ const QChar ch = word.at(0);
+ if (ch.isLetter() || ch == QLatin1Char('_'))
+ return true;
+ }
+
+ return false;
+}
+
+namespace GLSLEditor {
+namespace Internal {
+class FunctionArgumentWidget : public QLabel
+{
+ Q_OBJECT
+
+public:
+ FunctionArgumentWidget();
+ void showFunctionHint(QVector<GLSL::Function *> functionSymbols,
+ int startPosition);
+
+protected:
+ bool eventFilter(QObject *obj, QEvent *e);
+
+private slots:
+ void nextPage();
+ void previousPage();
+
+private:
+ void updateArgumentHighlight();
+ void updateHintText();
+ void placeInsideScreen();
+
+ GLSL::Function *currentFunction() const
+ { return m_items.at(m_current); }
+
+ int m_startpos;
+ int m_currentarg;
+ int m_current;
+ bool m_escapePressed;
+
+ TextEditor::ITextEditor *m_editor;
+
+ QWidget *m_pager;
+ QLabel *m_numberLabel;
+ Utils::FakeToolTip *m_popupFrame;
+ QVector<GLSL::Function *> m_items;
+};
+
+
+FunctionArgumentWidget::FunctionArgumentWidget():
+ m_startpos(-1),
+ m_current(0),
+ m_escapePressed(false)
+{
+ QObject *editorObject = Core::EditorManager::instance()->currentEditor();
+ m_editor = qobject_cast<TextEditor::ITextEditor *>(editorObject);
+
+ m_popupFrame = new Utils::FakeToolTip(m_editor->widget());
+
+ QToolButton *downArrow = new QToolButton;
+ downArrow->setArrowType(Qt::DownArrow);
+ downArrow->setFixedSize(16, 16);
+ downArrow->setAutoRaise(true);
+
+ QToolButton *upArrow = new QToolButton;
+ upArrow->setArrowType(Qt::UpArrow);
+ upArrow->setFixedSize(16, 16);
+ upArrow->setAutoRaise(true);
+
+ setParent(m_popupFrame);
+ setFocusPolicy(Qt::NoFocus);
+
+ m_pager = new QWidget;
+ QHBoxLayout *hbox = new QHBoxLayout(m_pager);
+ hbox->setMargin(0);
+ hbox->setSpacing(0);
+ hbox->addWidget(upArrow);
+ m_numberLabel = new QLabel;
+ hbox->addWidget(m_numberLabel);
+ hbox->addWidget(downArrow);
+
+ QHBoxLayout *layout = new QHBoxLayout;
+ layout->setMargin(0);
+ layout->setSpacing(0);
+ layout->addWidget(m_pager);
+ layout->addWidget(this);
+ m_popupFrame->setLayout(layout);
+
+ connect(upArrow, SIGNAL(clicked()), SLOT(previousPage()));
+ connect(downArrow, SIGNAL(clicked()), SLOT(nextPage()));
+
+ setTextFormat(Qt::RichText);
+
+ qApp->installEventFilter(this);
+}
+
+void FunctionArgumentWidget::showFunctionHint(QVector<GLSL::Function *> functionSymbols,
+ int startPosition)
+{
+ Q_ASSERT(!functionSymbols.isEmpty());
+
+ if (m_startpos == startPosition)
+ return;
+
+ m_pager->setVisible(functionSymbols.size() > 1);
+
+ m_items = functionSymbols;
+ m_startpos = startPosition;
+ m_current = 0;
+ m_escapePressed = false;
+
+ // update the text
+ m_currentarg = -1;
+ updateArgumentHighlight();
+
+ m_popupFrame->show();
+}
+
+void FunctionArgumentWidget::nextPage()
+{
+ m_current = (m_current + 1) % m_items.size();
+ updateHintText();
+}
+
+void FunctionArgumentWidget::previousPage()
+{
+ if (m_current == 0)
+ m_current = m_items.size() - 1;
+ else
+ --m_current;
+
+ updateHintText();
+}
+
+void FunctionArgumentWidget::updateArgumentHighlight()
+{
+ int curpos = m_editor->position();
+ if (curpos < m_startpos) {
+ m_popupFrame->close();
+ return;
+ }
+
+ const QByteArray str = m_editor->textAt(m_startpos, curpos - m_startpos).toLatin1();
+
+ int argnr = 0;
+ int parcount = 0;
+ GLSL::Lexer lexer(0, str.constData(), str.length());
+ GLSL::Token tk;
+ QList<GLSL::Token> tokens;
+ do {
+ lexer.yylex(&tk);
+ tokens.append(tk);
+ } while (tk.isNot(GLSL::Parser::EOF_SYMBOL));
+ for (int i = 0; i < tokens.count(); ++i) {
+ const GLSL::Token &tk = tokens.at(i);
+ if (tk.is(GLSL::Parser::T_LEFT_PAREN))
+ ++parcount;
+ else if (tk.is(GLSL::Parser::T_RIGHT_PAREN))
+ --parcount;
+ else if (! parcount && tk.is(GLSL::Parser::T_COMMA))
+ ++argnr;
+ }
+
+ if (m_currentarg != argnr) {
+ m_currentarg = argnr;
+ updateHintText();
+ }
+
+ if (parcount < 0)
+ m_popupFrame->close();
+}
+
+bool FunctionArgumentWidget::eventFilter(QObject *obj, QEvent *e)
+{
+ switch (e->type()) {
+ case QEvent::ShortcutOverride:
+ if (static_cast<QKeyEvent*>(e)->key() == Qt::Key_Escape) {
+ m_escapePressed = true;
+ }
+ break;
+ case QEvent::KeyPress:
+ if (static_cast<QKeyEvent*>(e)->key() == Qt::Key_Escape) {
+ m_escapePressed = true;
+ }
+ if (m_items.size() > 1) {
+ QKeyEvent *ke = static_cast<QKeyEvent*>(e);
+ if (ke->key() == Qt::Key_Up) {
+ previousPage();
+ return true;
+ } else if (ke->key() == Qt::Key_Down) {
+ nextPage();
+ return true;
+ }
+ return false;
+ }
+ break;
+ case QEvent::KeyRelease:
+ if (static_cast<QKeyEvent*>(e)->key() == Qt::Key_Escape && m_escapePressed) {
+ m_popupFrame->close();
+ return false;
+ }
+ updateArgumentHighlight();
+ break;
+ case QEvent::WindowDeactivate:
+ case QEvent::FocusOut:
+ if (obj != m_editor->widget())
+ break;
+ m_popupFrame->close();
+ break;
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseButtonDblClick:
+ case QEvent::Wheel: {
+ QWidget *widget = qobject_cast<QWidget *>(obj);
+ if (! (widget == this || m_popupFrame->isAncestorOf(widget))) {
+ m_popupFrame->close();
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ return false;
+}
+
+void FunctionArgumentWidget::updateHintText()
+{
+ setText(currentFunction()->prettyPrint(m_currentarg));
+
+ m_numberLabel->setText(tr("%1 of %2").arg(m_current + 1).arg(m_items.size()));
+
+ placeInsideScreen();
+}
+
+void FunctionArgumentWidget::placeInsideScreen()
+{
+ const QDesktopWidget *desktop = QApplication::desktop();
+#ifdef Q_WS_MAC
+ const QRect screen = desktop->availableGeometry(desktop->screenNumber(m_editor->widget()));
+#else
+ const QRect screen = desktop->screenGeometry(desktop->screenNumber(m_editor->widget()));
+#endif
+
+ m_pager->setFixedWidth(m_pager->minimumSizeHint().width());
+
+ setWordWrap(false);
+ const int maxDesiredWidth = screen.width() - 10;
+ const QSize minHint = m_popupFrame->minimumSizeHint();
+ if (minHint.width() > maxDesiredWidth) {
+ setWordWrap(true);
+ m_popupFrame->setFixedWidth(maxDesiredWidth);
+ const int extra =
+ m_popupFrame->contentsMargins().bottom() + m_popupFrame->contentsMargins().top();
+ m_popupFrame->setFixedHeight(heightForWidth(maxDesiredWidth - m_pager->width()) + extra);
+ } else {
+ m_popupFrame->setFixedSize(minHint);
+ }
+
+ const QSize sz = m_popupFrame->size();
+ QPoint pos = m_editor->cursorRect(m_startpos).topLeft();
+ pos.setY(pos.y() - sz.height() - 1);
+
+ if (pos.x() + sz.width() > screen.right())
+ pos.setX(screen.right() - sz.width());
+
+ m_popupFrame->move(pos);
+}
+
+} // Internal
+} // GLSLEditor
+
+
+
+CodeCompletion::CodeCompletion(QObject *parent)
+ : ICompletionCollector(parent),
+ m_editor(0),
+ m_startPosition(-1),
+ m_restartCompletion(false),
+ m_keywordVariant(-1),
+ m_keywordIcon(":/glsleditor/images/keyword.png"),
+ m_varIcon(":/glsleditor/images/var.png"),
+ m_functionIcon(":/glsleditor/images/func.png"),
+ m_typeIcon(":/glsleditor/images/type.png"),
+ m_constIcon(":/glsleditor/images/const.png"),
+ m_attributeIcon(":/glsleditor/images/attribute.png"),
+ m_uniformIcon(":/glsleditor/images/uniform.png"),
+ m_varyingIcon(":/glsleditor/images/varying.png"),
+ m_otherIcon(":/glsleditor/images/other.png")
+{
+}
+
+CodeCompletion::~CodeCompletion()
+{
+}
+
+TextEditor::ITextEditable *CodeCompletion::editor() const
+{
+ return m_editor;
+}
+
+int CodeCompletion::startPosition() const
+{
+ return m_startPosition;
+}
+
+bool CodeCompletion::supportsEditor(TextEditor::ITextEditable *editor)
+{
+ if (qobject_cast<GLSLTextEditor *>(editor->widget()) != 0)
+ return true;
+
+ return false;
+}
+
+bool CodeCompletion::triggersCompletion(TextEditor::ITextEditable *editor)
+{
+ const int cursorPosition = editor->position();
+ const QChar ch = editor->characterAt(cursorPosition - 1);
+
+ if (completionSettings().m_completionTrigger == TextEditor::AutomaticCompletion) {
+ const QChar characterUnderCursor = editor->characterAt(cursorPosition);
+
+ if (isIdentifierChar(ch) && (characterUnderCursor.isSpace() ||
+ characterUnderCursor.isNull() ||
+ isDelimiter(characterUnderCursor))) {
+ int pos = editor->position() - 1;
+ for (; pos != -1; --pos) {
+ if (! isIdentifierChar(editor->characterAt(pos)))
+ break;
+ }
+ ++pos;
+
+ const QString word = editor->textAt(pos, cursorPosition - pos);
+ if (word.length() > 2 && checkStartOfIdentifier(word)) {
+ for (int i = 0; i < word.length(); ++i) {
+ if (! isIdentifierChar(word.at(i)))
+ return false;
+ }
+ return true;
+ }
+ }
+ }
+
+ if (ch == QLatin1Char('(') || ch == QLatin1Char('.') || ch == QLatin1Char(','))
+ return true;
+
+ return false;
+}
+
+int CodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
+{
+ m_editor = editor;
+
+ int pos = editor->position() - 1;
+ QChar ch = editor->characterAt(pos);
+ while (ch.isLetterOrNumber() || ch == QLatin1Char('_'))
+ ch = editor->characterAt(--pos);
+
+ CPlusPlus::ExpressionUnderCursor expressionUnderCursor;
+ GLSLTextEditor *edit = qobject_cast<GLSLTextEditor *>(editor->widget());
+
+ QList<GLSL::Symbol *> members;
+ QStringList specialMembers;
+
+ bool functionCall = (ch == QLatin1Char('(') && pos == editor->position() - 1);
+
+ if (ch == QLatin1Char(',')) {
+ QTextCursor tc(edit->document());
+ tc.setPosition(pos);
+ const int start = expressionUnderCursor.startOfFunctionCall(tc);
+ if (start == -1)
+ return -1;
+
+ if (edit->characterAt(start) == QLatin1Char('(')) {
+ pos = start;
+ ch = QLatin1Char('(');
+ functionCall = true;
+ }
+ }
+
+ if (ch == QLatin1Char('.') || functionCall) {
+ const bool memberCompletion = ! functionCall;
+ QTextCursor tc(edit->document());
+ tc.setPosition(pos);
+
+ // get the expression under cursor
+ const QByteArray code = expressionUnderCursor(tc).toLatin1();
+ //qDebug() << endl << "expression:" << code;
+
+ // parse the expression
+ GLSL::Engine engine;
+ GLSL::Parser parser(&engine, code, code.size(), edit->languageVariant());
+ GLSL::ExpressionAST *expr = parser.parseExpression();
+
+#if 0
+ // dump it!
+ QTextStream qout(stdout, QIODevice::WriteOnly);
+ GLSL::ASTDump dump(qout);
+ dump(expr);
+#endif
+
+ if (Document::Ptr doc = edit->glslDocument()) {
+ GLSL::Scope *currentScope = doc->scopeAt(pos);
+
+ GLSL::Semantic sem;
+ GLSL::Semantic::ExprResult exprTy = sem.expression(expr, currentScope, doc->engine());
+ if (exprTy.type) {
+ if (memberCompletion) {
+ if (const GLSL::VectorType *vecTy = exprTy.type->asVectorType()) {
+ members = vecTy->members();
+
+ // Sort the most relevant swizzle orderings to the top.
+ specialMembers += QLatin1String("xy");
+ specialMembers += QLatin1String("xyz");
+ specialMembers += QLatin1String("xyzw");
+ specialMembers += QLatin1String("rgb");
+ specialMembers += QLatin1String("rgba");
+ specialMembers += QLatin1String("st");
+ specialMembers += QLatin1String("stp");
+ specialMembers += QLatin1String("stpq");
+
+ } else if (const GLSL::Struct *structTy = exprTy.type->asStructType()) {
+ members = structTy->members();
+
+ } else {
+ // some other type
+ }
+ } else { // function completion
+ QVector<GLSL::Function *> signatures;
+ if (const GLSL::Function *funTy = exprTy.type->asFunctionType())
+ signatures.append(const_cast<GLSL::Function *>(funTy)); // ### get rid of the const_cast
+ else if (const GLSL::OverloadSet *overload = exprTy.type->asOverloadSetType())
+ signatures = overload->functions();
+
+ if (! signatures.isEmpty()) {
+ // Recreate if necessary
+ if (!m_functionArgumentWidget)
+ m_functionArgumentWidget = new FunctionArgumentWidget;
+
+ m_functionArgumentWidget->showFunctionHint(signatures, pos + 1);
+ return false;
+ }
+ }
+ } else {
+ // undefined
+
+ }
+
+ } else {
+ // sorry, there's no document
+ }
+
+ } else {
+ // it's a global completion
+ if (Document::Ptr doc = edit->glslDocument()) {
+ GLSL::Scope *currentScope = doc->scopeAt(pos);
+ bool isGlobal = !currentScope || !currentScope->scope();
+
+ // add the members from the scope chain
+ for (; currentScope; currentScope = currentScope->scope())
+ members += currentScope->members();
+
+ // if this is the global scope, then add some standard Qt attribute
+ // and uniform names for autocompleting variable declarations
+ // this isn't a complete list, just the most common
+ if (isGlobal) {
+ static const char * const attributeNames[] = {
+ "qt_Vertex",
+ "qt_Normal",
+ "qt_MultiTexCoord0",
+ "qt_MultiTexCoord1",
+ "qt_MultiTexCoord2",
+ 0
+ };
+ static const char * const uniformNames[] = {
+ "qt_ModelViewProjectionMatrix",
+ "qt_ModelViewMatrix",
+ "qt_ProjectionMatrix",
+ "qt_NormalMatrix",
+ "qt_Texture0",
+ "qt_Texture1",
+ "qt_Texture2",
+ "qt_Color",
+ "qt_Opacity",
+ 0
+ };
+ for (int index = 0; attributeNames[index]; ++index) {
+ TextEditor::CompletionItem item(this);
+ item.text = QString::fromLatin1(attributeNames[index]);
+ item.icon = m_attributeIcon;
+ m_completions.append(item);
+ }
+ for (int index = 0; uniformNames[index]; ++index) {
+ TextEditor::CompletionItem item(this);
+ item.text = QString::fromLatin1(uniformNames[index]);
+ item.icon = m_uniformIcon;
+ m_completions.append(item);
+ }
+ }
+ }
+
+ if (m_keywordVariant != edit->languageVariant()) {
+ QStringList keywords = GLSL::Lexer::keywords(edit->languageVariant());
+ m_keywordCompletions.clear();
+ for (int index = 0; index < keywords.size(); ++index) {
+ TextEditor::CompletionItem item(this);
+ item.text = keywords.at(index);
+ item.icon = m_keywordIcon;
+ m_keywordCompletions.append(item);
+ }
+ m_keywordVariant = edit->languageVariant();
+ }
+
+ m_completions += m_keywordCompletions;
+ }
+
+ foreach (GLSL::Symbol *s, members) {
+ TextEditor::CompletionItem item(this);
+ GLSL::Variable *var = s->asVariable();
+ if (var) {
+ int storageType = var->qualifiers() & GLSL::QualifiedTypeAST::StorageMask;
+ if (storageType == GLSL::QualifiedTypeAST::Attribute)
+ item.icon = m_attributeIcon;
+ else if (storageType == GLSL::QualifiedTypeAST::Uniform)
+ item.icon = m_uniformIcon;
+ else if (storageType == GLSL::QualifiedTypeAST::Varying)
+ item.icon = m_varyingIcon;
+ else if (storageType == GLSL::QualifiedTypeAST::Const)
+ item.icon = m_constIcon;
+ else
+ item.icon = m_varIcon;
+ } else if (s->asArgument()) {
+ item.icon = m_varIcon;
+ } else if (s->asFunction() || s->asOverloadSet()) {
+ item.icon = m_functionIcon;
+ } else if (s->asStruct()) {
+ item.icon = m_typeIcon;
+ } else {
+ item.icon = m_otherIcon;
+ }
+ item.text = s->name();
+ if (specialMembers.contains(item.text))
+ item.order = SpecialMemberOrder;
+ m_completions.append(item);
+ }
+
+ m_startPosition = pos + 1;
+ return m_startPosition;
+}
+
+void CodeCompletion::completions(QList<TextEditor::CompletionItem> *completions)
+{
+ const int length = m_editor->position() - m_startPosition;
+
+ if (length == 0)
+ *completions = m_completions;
+ else if (length > 0) {
+ const QString key = m_editor->textAt(m_startPosition, length);
+
+ filter(m_completions, completions, key);
+
+ if (completions->size() == 1) {
+ if (key == completions->first().text)
+ completions->clear();
+ }
+ }
+}
+
+bool CodeCompletion::typedCharCompletes(const TextEditor::CompletionItem &item, QChar typedChar)
+{
+ Q_UNUSED(item);
+ Q_UNUSED(typedChar);
+ return false;
+}
+
+void CodeCompletion::complete(const TextEditor::CompletionItem &item, QChar typedChar)
+{
+ Q_UNUSED(typedChar);
+
+ QString toInsert = item.text;
+
+ const int length = m_editor->position() - m_startPosition;
+ m_editor->setCurPos(m_startPosition);
+ m_editor->replace(length, toInsert);
+
+ if (toInsert.endsWith(QLatin1Char('.')) || toInsert.endsWith(QLatin1Char('(')))
+ m_restartCompletion = true;
+}
+
+bool CodeCompletion::partiallyComplete(const QList<TextEditor::CompletionItem> &completionItems)
+{
+ return ICompletionCollector::partiallyComplete(completionItems);
+}
+
+bool CodeCompletion::glslCompletionItemLessThan(const TextEditor::CompletionItem &l, const TextEditor::CompletionItem &r)
+{
+ if (l.order != r.order)
+ return l.order < r.order;
+ return completionItemLessThan(l, r);
+}
+
+QList<TextEditor::CompletionItem> CodeCompletion::getCompletions()
+{
+ QList<TextEditor::CompletionItem> completionItems;
+
+ completions(&completionItems);
+
+ qStableSort(completionItems.begin(), completionItems.end(), glslCompletionItemLessThan);
+
+ // Remove duplicates
+ QString lastKey;
+ QVariant lastData;
+ QList<TextEditor::CompletionItem> uniquelist;
+
+ foreach (const TextEditor::CompletionItem &item, completionItems) {
+ if (item.text != lastKey || item.data.type() != lastData.type()) {
+ uniquelist.append(item);
+ lastKey = item.text;
+ lastData = item.data;
+ }
+ }
+
+ return uniquelist;
+}
+
+bool CodeCompletion::shouldRestartCompletion()
+{
+ return m_restartCompletion;
+}
+
+void CodeCompletion::cleanup()
+{
+ m_editor = 0;
+ m_completions.clear();
+ m_restartCompletion = false;
+ m_startPosition = -1;
+}
+
+#include "glslcodecompletion.moc"
diff --git a/src/plugins/glsleditor/glslcodecompletion.h b/src/plugins/glsleditor/glslcodecompletion.h
new file mode 100644
index 0000000000..0b7d1fad84
--- /dev/null
+++ b/src/plugins/glsleditor/glslcodecompletion.h
@@ -0,0 +1,126 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 GLSLCODECOMPLETION_H
+#define GLSLCODECOMPLETION_H
+
+#include <texteditor/icompletioncollector.h>
+#include <QtCore/QPointer>
+
+namespace GLSLEditor {
+namespace Internal {
+
+class FunctionArgumentWidget;
+
+class CodeCompletion: public TextEditor::ICompletionCollector
+{
+ Q_OBJECT
+
+public:
+ CodeCompletion(QObject *parent = 0);
+ virtual ~CodeCompletion();
+
+ /* Returns the current active ITextEditable */
+ virtual TextEditor::ITextEditable *editor() const;
+ virtual int startPosition() const;
+
+ /*
+ * Returns true if this completion collector can be used with the given editor.
+ */
+ virtual bool supportsEditor(TextEditor::ITextEditable *editor);
+
+ /* This method should return whether the cursor is at a position which could
+ * trigger an autocomplete. It will be called each time a character is typed in
+ * the text editor.
+ */
+ virtual bool triggersCompletion(TextEditor::ITextEditable *editor);
+
+ // returns starting position
+ virtual int startCompletion(TextEditor::ITextEditable *editor);
+
+ /* This method should add all the completions it wants to show into the list,
+ * based on the given cursor position.
+ */
+ virtual void completions(QList<TextEditor::CompletionItem> *completions);
+
+ /**
+ * This method should return true when the given typed character should cause
+ * the selected completion item to be completed.
+ */
+ virtual bool typedCharCompletes(const TextEditor::CompletionItem &item, QChar typedChar);
+
+ /**
+ * This method should complete the given completion item.
+ *
+ * \param typedChar Non-null when completion was triggered by typing a
+ * character. Possible values depend on typedCharCompletes()
+ */
+ virtual void complete(const TextEditor::CompletionItem &item, QChar typedChar);
+
+ /* This method gives the completion collector a chance to partially complete
+ * based on a set of items. The general use case is to complete the common
+ * prefix shared by all possible completion items.
+ *
+ * Returns whether the completion popup should be closed.
+ */
+ virtual bool partiallyComplete(const QList<TextEditor::CompletionItem> &completionItems);
+
+ virtual QList<TextEditor::CompletionItem> getCompletions();
+ virtual bool shouldRestartCompletion();
+
+ /* Called when it's safe to clean up the completion items.
+ */
+ virtual void cleanup();
+
+private:
+ QList<TextEditor::CompletionItem> m_completions;
+ QList<TextEditor::CompletionItem> m_keywordCompletions;
+ TextEditor::ITextEditable *m_editor;
+ int m_startPosition;
+ bool m_restartCompletion;
+ QPointer<FunctionArgumentWidget> m_functionArgumentWidget;
+
+ static bool glslCompletionItemLessThan(const TextEditor::CompletionItem &l, const TextEditor::CompletionItem &r);
+
+ int m_keywordVariant;
+
+ QIcon m_keywordIcon;
+ QIcon m_varIcon;
+ QIcon m_functionIcon;
+ QIcon m_typeIcon;
+ QIcon m_constIcon;
+ QIcon m_attributeIcon;
+ QIcon m_uniformIcon;
+ QIcon m_varyingIcon;
+ QIcon m_otherIcon;
+};
+
+} // namespace Internal
+} // namespace GLSLEditor
+
+#endif // GLSLCODECOMPLETION_H
diff --git a/src/plugins/glsleditor/glsleditor.cpp b/src/plugins/glsleditor/glsleditor.cpp
new file mode 100644
index 0000000000..5ff01d764d
--- /dev/null
+++ b/src/plugins/glsleditor/glsleditor.cpp
@@ -0,0 +1,419 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "glsleditor.h"
+#include "glsleditoreditable.h"
+#include "glsleditorconstants.h"
+#include "glsleditorplugin.h"
+#include "glslhighlighter.h"
+#include "glslautocompleter.h"
+#include "glslindenter.h"
+
+#include <glsl/glsllexer.h>
+#include <glsl/glslparser.h>
+#include <glsl/glslengine.h>
+#include <glsl/glslsemantic.h>
+#include <glsl/glslsymbols.h>
+
+#include <coreplugin/actionmanager/actionmanager.h>
+#include <coreplugin/actionmanager/actioncontainer.h>
+#include <coreplugin/uniqueidmanager.h>
+#include <coreplugin/actionmanager/command.h>
+#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/icore.h>
+#include <coreplugin/mimedatabase.h>
+#include <extensionsystem/pluginmanager.h>
+#include <texteditor/basetextdocument.h>
+#include <texteditor/fontsettings.h>
+#include <texteditor/tabsettings.h>
+#include <texteditor/texteditorconstants.h>
+#include <texteditor/texteditorsettings.h>
+#include <texteditor/syntaxhighlighter.h>
+#include <texteditor/refactoroverlay.h>
+#include <texteditor/tooltip/tooltip.h>
+#include <qmldesigner/qmldesignerconstants.h>
+#include <utils/changeset.h>
+#include <utils/uncommentselection.h>
+
+#include <QtCore/QFileInfo>
+#include <QtCore/QSignalMapper>
+#include <QtCore/QTimer>
+#include <QtCore/QDebug>
+
+#include <QtGui/QMenu>
+#include <QtGui/QComboBox>
+#include <QtGui/QHeaderView>
+#include <QtGui/QInputDialog>
+#include <QtGui/QMainWindow>
+#include <QtGui/QToolBar>
+#include <QtGui/QTreeView>
+
+using namespace GLSL;
+using namespace GLSLEditor;
+using namespace GLSLEditor::Internal;
+
+enum {
+ UPDATE_DOCUMENT_DEFAULT_INTERVAL = 150
+};
+
+namespace {
+
+class CreateRanges: protected GLSL::Visitor
+{
+ QTextDocument *textDocument;
+ Document::Ptr glslDocument;
+
+public:
+ CreateRanges(QTextDocument *textDocument, Document::Ptr glslDocument)
+ : textDocument(textDocument), glslDocument(glslDocument) {}
+
+ void operator()(GLSL::AST *ast) { accept(ast); }
+
+protected:
+ using GLSL::Visitor::visit;
+
+ virtual void endVisit(GLSL::CompoundStatementAST *ast)
+ {
+ if (ast->symbol) {
+ QTextCursor tc(textDocument);
+ tc.setPosition(ast->start);
+ tc.setPosition(ast->end, QTextCursor::KeepAnchor);
+ glslDocument->addRange(tc, ast->symbol);
+ }
+ }
+};
+
+} // end of anonymous namespace
+
+Document::Document()
+ : _engine(0)
+ , _ast(0)
+ , _globalScope(0)
+{
+
+}
+
+Document::~Document()
+{
+ delete _globalScope;
+ delete _engine;
+}
+
+GLSL::Scope *Document::scopeAt(int position) const
+{
+ foreach (const Range &c, _cursors) {
+ if (position >= c.cursor.selectionStart() && position <= c.cursor.selectionEnd())
+ return c.scope;
+ }
+ return _globalScope;
+}
+
+void Document::addRange(const QTextCursor &cursor, GLSL::Scope *scope)
+{
+ Range c;
+ c.cursor = cursor;
+ c.scope = scope;
+ _cursors.append(c);
+}
+
+GLSLTextEditor::GLSLTextEditor(QWidget *parent) :
+ TextEditor::BaseTextEditor(parent),
+ m_outlineCombo(0)
+{
+ setParenthesesMatchingEnabled(true);
+ setMarksVisible(true);
+ setCodeFoldingSupported(true);
+ setIndenter(new GLSLIndenter());
+ setAutoCompleter(new GLSLCompleter());
+
+ m_updateDocumentTimer = new QTimer(this);
+ m_updateDocumentTimer->setInterval(UPDATE_DOCUMENT_DEFAULT_INTERVAL);
+ m_updateDocumentTimer->setSingleShot(true);
+ connect(m_updateDocumentTimer, SIGNAL(timeout()), this, SLOT(updateDocumentNow()));
+
+ connect(this, SIGNAL(textChanged()), this, SLOT(updateDocument()));
+
+ baseTextDocument()->setSyntaxHighlighter(new Highlighter(this, document()));
+
+// if (m_modelManager) {
+// m_semanticHighlighter->setModelManager(m_modelManager);
+// connect(m_modelManager, SIGNAL(documentUpdated(GLSL::Document::Ptr)),
+// this, SLOT(onDocumentUpdated(GLSL::Document::Ptr)));
+// connect(m_modelManager, SIGNAL(libraryInfoUpdated(QString,GLSL::LibraryInfo)),
+// this, SLOT(forceSemanticRehighlight()));
+// connect(this->document(), SIGNAL(modificationChanged(bool)), this, SLOT(modificationChanged(bool)));
+// }
+}
+
+GLSLTextEditor::~GLSLTextEditor()
+{
+}
+
+int GLSLTextEditor::editorRevision() const
+{
+ //return document()->revision();
+ return 0;
+}
+
+bool GLSLTextEditor::isOutdated() const
+{
+// if (m_semanticInfo.revision() != editorRevision())
+// return true;
+
+ return false;
+}
+
+Core::IEditor *GLSLEditorEditable::duplicate(QWidget *parent)
+{
+ GLSLTextEditor *newEditor = new GLSLTextEditor(parent);
+ newEditor->duplicateFrom(editor());
+ GLSLEditorPlugin::instance()->initializeEditor(newEditor);
+ return newEditor->editableInterface();
+}
+
+QString GLSLEditorEditable::id() const
+{
+ return QLatin1String(GLSLEditor::Constants::C_GLSLEDITOR_ID);
+}
+
+bool GLSLEditorEditable::open(const QString &fileName)
+{
+ editor()->setMimeType(Core::ICore::instance()->mimeDatabase()->findByFile(QFileInfo(fileName)).type());
+ bool b = TextEditor::BaseTextEditorEditable::open(fileName);
+ return b;
+}
+
+Core::Context GLSLEditorEditable::context() const
+{
+ return m_context;
+}
+
+void GLSLTextEditor::setFontSettings(const TextEditor::FontSettings &fs)
+{
+ TextEditor::BaseTextEditor::setFontSettings(fs);
+ Highlighter *highlighter = qobject_cast<Highlighter*>(baseTextDocument()->syntaxHighlighter());
+ if (!highlighter)
+ return;
+
+ /*
+ NumberFormat,
+ StringFormat,
+ TypeFormat,
+ KeywordFormat,
+ LabelFormat,
+ CommentFormat,
+ VisualWhitespace,
+ */
+ static QVector<QString> categories;
+ if (categories.isEmpty()) {
+ categories << QLatin1String(TextEditor::Constants::C_NUMBER)
+ << QLatin1String(TextEditor::Constants::C_STRING)
+ << QLatin1String(TextEditor::Constants::C_TYPE)
+ << QLatin1String(TextEditor::Constants::C_KEYWORD)
+ << QLatin1String(TextEditor::Constants::C_OPERATOR)
+ << QLatin1String(TextEditor::Constants::C_PREPROCESSOR)
+ << QLatin1String(TextEditor::Constants::C_LABEL)
+ << QLatin1String(TextEditor::Constants::C_COMMENT)
+ << QLatin1String(TextEditor::Constants::C_DOXYGEN_COMMENT)
+ << QLatin1String(TextEditor::Constants::C_DOXYGEN_TAG)
+ << QLatin1String(TextEditor::Constants::C_VISUAL_WHITESPACE)
+ << QLatin1String(TextEditor::Constants::C_REMOVED_LINE);
+ }
+
+ highlighter->setFormats(fs.toTextCharFormats(categories));
+ highlighter->rehighlight();
+}
+
+QString GLSLTextEditor::wordUnderCursor() const
+{
+ QTextCursor tc = textCursor();
+ const QChar ch = characterAt(tc.position() - 1);
+ // make sure that we're not at the start of the next word.
+ if (ch.isLetterOrNumber() || ch == QLatin1Char('_'))
+ tc.movePosition(QTextCursor::Left);
+ tc.movePosition(QTextCursor::StartOfWord);
+ tc.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
+ const QString word = tc.selectedText();
+ return word;
+}
+
+TextEditor::BaseTextEditorEditable *GLSLTextEditor::createEditableInterface()
+{
+ GLSLEditorEditable *editable = new GLSLEditorEditable(this);
+ createToolBar(editable);
+ return editable;
+}
+
+void GLSLTextEditor::createToolBar(GLSLEditorEditable *editable)
+{
+ m_outlineCombo = new QComboBox;
+ m_outlineCombo->setMinimumContentsLength(22);
+
+ // ### m_outlineCombo->setModel(m_outlineModel);
+
+ QTreeView *treeView = new QTreeView;
+ treeView->header()->hide();
+ treeView->setItemsExpandable(false);
+ treeView->setRootIsDecorated(false);
+ m_outlineCombo->setView(treeView);
+ treeView->expandAll();
+
+ //m_outlineCombo->setSizeAdjustPolicy(QComboBox::AdjustToContents);
+
+ // Make the combo box prefer to expand
+ QSizePolicy policy = m_outlineCombo->sizePolicy();
+ policy.setHorizontalPolicy(QSizePolicy::Expanding);
+ m_outlineCombo->setSizePolicy(policy);
+
+ QToolBar *toolBar = static_cast<QToolBar*>(editable->toolBar());
+
+ QList<QAction*> actions = toolBar->actions();
+ toolBar->insertWidget(actions.first(), m_outlineCombo);
+}
+
+bool GLSLTextEditor::event(QEvent *e)
+{
+ return BaseTextEditor::event(e);
+}
+
+void GLSLTextEditor::unCommentSelection()
+{
+ Utils::unCommentSelection(this);
+}
+
+void GLSLTextEditor::updateDocument()
+{
+ m_updateDocumentTimer->start();
+}
+
+void GLSLTextEditor::updateDocumentNow()
+{
+ m_updateDocumentTimer->stop();
+
+ int variant = languageVariant();
+ const QString contents = toPlainText(); // get the code from the editor
+ const QByteArray preprocessedCode = contents.toLatin1(); // ### use the QtCreator C++ preprocessor.
+
+ Document::Ptr doc(new Document());
+ GLSL::Engine *engine = new GLSL::Engine();
+ doc->_engine = new GLSL::Engine();
+ Parser parser(doc->_engine, preprocessedCode.constData(), preprocessedCode.size(), variant);
+ TranslationUnitAST *ast = parser.parse();
+ if (ast != 0 || extraSelections(CodeWarningsSelection).isEmpty()) {
+ GLSLEditorPlugin *plugin = GLSLEditorPlugin::instance();
+
+ Semantic sem;
+ Scope *globalScope = engine->newNamespace();
+ doc->_globalScope = globalScope;
+ sem.translationUnit(plugin->shaderInit(variant)->ast, globalScope, plugin->shaderInit(variant)->engine);
+ if (variant & Lexer::Variant_VertexShader)
+ sem.translationUnit(plugin->vertexShaderInit(variant)->ast, globalScope, plugin->vertexShaderInit(variant)->engine);
+ if (variant & Lexer::Variant_FragmentShader)
+ sem.translationUnit(plugin->fragmentShaderInit(variant)->ast, globalScope, plugin->fragmentShaderInit(variant)->engine);
+ sem.translationUnit(ast, globalScope, engine);
+
+ CreateRanges createRanges(document(), doc);
+ createRanges(ast);
+
+ QTextCharFormat errorFormat;
+ errorFormat.setUnderlineStyle(QTextCharFormat::WaveUnderline);
+ errorFormat.setUnderlineColor(Qt::red);
+
+ QTextCharFormat warningFormat;
+ warningFormat.setUnderlineStyle(QTextCharFormat::WaveUnderline);
+ warningFormat.setUnderlineColor(Qt::darkYellow);
+
+ QList<QTextEdit::ExtraSelection> sels;
+ QSet<int> errors;
+
+ foreach (const DiagnosticMessage &m, engine->diagnosticMessages()) {
+ if (! m.line())
+ continue;
+ else if (errors.contains(m.line()))
+ continue;
+
+ errors.insert(m.line());
+
+ QTextCursor cursor(document()->findBlockByNumber(m.line() - 1));
+ cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
+
+ QTextEdit::ExtraSelection sel;
+ sel.cursor = cursor;
+ sel.format = m.isError() ? errorFormat : warningFormat;
+ sel.format.setToolTip(m.message());
+ sels.append(sel);
+ }
+
+ setExtraSelections(CodeWarningsSelection, sels);
+ m_glslDocument = doc;
+ }
+}
+
+int GLSLTextEditor::languageVariant() const
+{
+ int variant = 0;
+ QString type = mimeType();
+ bool isVertex = false;
+ bool isFragment = false;
+ bool isDesktop = false;
+ if (type.isEmpty()) {
+ // ### Before file has been opened, so don't know the mime type.
+ isVertex = true;
+ isFragment = true;
+ } else if (type == QLatin1String("text/x-glsl") ||
+ type == QLatin1String("application/x-glsl")) {
+ isVertex = true;
+ isFragment = true;
+ isDesktop = true;
+ } else if (type == QLatin1String("text/x-glsl-vert")) {
+ isVertex = true;
+ isDesktop = true;
+ } else if (type == QLatin1String("text/x-glsl-frag")) {
+ isFragment = true;
+ isDesktop = true;
+ } else if (type == QLatin1String("text/x-glsl-es-vert")) {
+ isVertex = true;
+ } else if (type == QLatin1String("text/x-glsl-es-frag")) {
+ isFragment = true;
+ }
+ if (isDesktop)
+ variant |= Lexer::Variant_GLSL_120;
+ else
+ variant |= Lexer::Variant_GLSL_ES_100;
+ if (isVertex)
+ variant |= Lexer::Variant_VertexShader;
+ if (isFragment)
+ variant |= Lexer::Variant_FragmentShader;
+ return variant;
+}
+
+Document::Ptr GLSLTextEditor::glslDocument() const
+{
+ return m_glslDocument;
+}
diff --git a/src/plugins/glsleditor/glsleditor.h b/src/plugins/glsleditor/glsleditor.h
new file mode 100644
index 0000000000..753802af88
--- /dev/null
+++ b/src/plugins/glsleditor/glsleditor.h
@@ -0,0 +1,129 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 GLSLEDITOR_H
+#define GLSLEDITOR_H
+
+#include "glsleditor_global.h"
+#include "glsleditoreditable.h"
+
+#include <glsl/glsl.h>
+
+#include <texteditor/basetexteditor.h>
+#include <texteditor/quickfix.h>
+
+#include <QtCore/QSharedPointer>
+#include <QtCore/QSet>
+
+QT_BEGIN_NAMESPACE
+class QComboBox;
+class QTimer;
+QT_END_NAMESPACE
+
+namespace Core {
+class ICore;
+}
+
+namespace GLSLEditor {
+class GLSLTextEditor;
+
+class GLSLEDITOR_EXPORT Document
+{
+public:
+ typedef QSharedPointer<Document> Ptr;
+
+ Document();
+ ~Document();
+
+ GLSL::Engine *engine() const { return _engine; }
+ GLSL::TranslationUnitAST *ast() const { return _ast; }
+ GLSL::Scope *globalScope() const { return _globalScope; }
+
+ GLSL::Scope *scopeAt(int position) const;
+ void addRange(const QTextCursor &cursor, GLSL::Scope *scope);
+
+private:
+ struct Range {
+ QTextCursor cursor;
+ GLSL::Scope *scope;
+ };
+
+ GLSL::Engine *_engine;
+ GLSL::TranslationUnitAST *_ast;
+ GLSL::Scope *_globalScope;
+ QList<Range> _cursors;
+
+ friend class GLSLTextEditor;
+};
+
+class GLSLEDITOR_EXPORT GLSLTextEditor : public TextEditor::BaseTextEditor
+{
+ Q_OBJECT
+
+public:
+ GLSLTextEditor(QWidget *parent = 0);
+ ~GLSLTextEditor();
+
+ virtual void unCommentSelection();
+
+ int editorRevision() const;
+ bool isOutdated() const;
+
+ QSet<QString> identifiers() const;
+
+ int languageVariant() const;
+
+ Document::Ptr glslDocument() const;
+
+public slots:
+ virtual void setFontSettings(const TextEditor::FontSettings &);
+
+private slots:
+ void updateDocument();
+ void updateDocumentNow();
+
+protected:
+ bool event(QEvent *e);
+ TextEditor::BaseTextEditorEditable *createEditableInterface();
+ void createToolBar(Internal::GLSLEditorEditable *editable);
+
+private:
+ void setSelectedElements();
+ QString wordUnderCursor() const;
+
+ const Core::Context m_context;
+
+ QTimer *m_updateDocumentTimer;
+ QComboBox *m_outlineCombo;
+ Document::Ptr m_glslDocument;
+};
+
+} // namespace GLSLEditor
+
+#endif // GLSLEDITOR_H
diff --git a/src/plugins/glsleditor/glsleditor.pri b/src/plugins/glsleditor/glsleditor.pri
new file mode 100644
index 0000000000..aac9022e3e
--- /dev/null
+++ b/src/plugins/glsleditor/glsleditor.pri
@@ -0,0 +1,3 @@
+include(qmljseditor_dependencies.pri)
+
+LIBS *= -l$$qtLibraryName(QmlJSEditor)
diff --git a/src/plugins/glsleditor/glsleditor.pro b/src/plugins/glsleditor/glsleditor.pro
new file mode 100644
index 0000000000..be0cdf3b43
--- /dev/null
+++ b/src/plugins/glsleditor/glsleditor.pro
@@ -0,0 +1,39 @@
+TEMPLATE = lib
+TARGET = GLSLEditor
+include(../../qtcreatorplugin.pri)
+include(glsleditor_dependencies.pri)
+
+DEFINES += \
+ GLSLEDITOR_LIBRARY \
+ QT_CREATOR
+
+HEADERS += \
+glsleditor.h \
+glsleditor_global.h \
+glsleditoractionhandler.h \
+glsleditorconstants.h \
+glsleditoreditable.h \
+glsleditorfactory.h \
+glsleditorplugin.h \
+glslfilewizard.h \
+glslhighlighter.h \
+glslcodecompletion.h \
+glslautocompleter.h \
+glslindenter.h \
+glslhoverhandler.h
+
+SOURCES += \
+glsleditor.cpp \
+glsleditoractionhandler.cpp \
+glsleditoreditable.cpp \
+glsleditorfactory.cpp \
+glsleditorplugin.cpp \
+glslfilewizard.cpp \
+glslhighlighter.cpp \
+glslcodecompletion.cpp \
+glslautocompleter.cpp \
+glslindenter.cpp \
+glslhoverhandler.cpp
+
+OTHER_FILES += GLSLEditor.mimetypes.xml
+RESOURCES += glsleditor.qrc
diff --git a/src/plugins/glsleditor/glsleditor.qrc b/src/plugins/glsleditor/glsleditor.qrc
new file mode 100644
index 0000000000..3455048e00
--- /dev/null
+++ b/src/plugins/glsleditor/glsleditor.qrc
@@ -0,0 +1,15 @@
+<RCC>
+ <qresource prefix="/glsleditor">
+ <file>GLSLEditor.mimetypes.xml</file>
+ <file>images/glslfile.png</file>
+ <file>images/keyword.png</file>
+ <file>images/var.png</file>
+ <file>images/func.png</file>
+ <file>images/type.png</file>
+ <file>images/const.png</file>
+ <file>images/attribute.png</file>
+ <file>images/uniform.png</file>
+ <file>images/varying.png</file>
+ <file>images/other.png</file>
+ </qresource>
+</RCC>
diff --git a/src/plugins/glsleditor/glsleditor_dependencies.pri b/src/plugins/glsleditor/glsleditor_dependencies.pri
new file mode 100644
index 0000000000..163216eac4
--- /dev/null
+++ b/src/plugins/glsleditor/glsleditor_dependencies.pri
@@ -0,0 +1,7 @@
+include(../../plugins/coreplugin/coreplugin.pri)
+include(../../plugins/texteditor/texteditor.pri)
+include(../../plugins/projectexplorer/projectexplorer.pri)
+include(../../plugins/cpptools/cpptools.pri)
+include(../../libs/glsl/glsl.pri)
+include(../../libs/utils/utils.pri)
+include(../../libs/cplusplus/cplusplus.pri)
diff --git a/src/plugins/glsleditor/glsleditor_global.h b/src/plugins/glsleditor/glsleditor_global.h
new file mode 100644
index 0000000000..bd3f06177c
--- /dev/null
+++ b/src/plugins/glsleditor/glsleditor_global.h
@@ -0,0 +1,41 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 GLSLEDITOR_GLOBAL_H
+#define GLSLEDITOR_GLOBAL_H
+
+#include <QtGlobal>
+
+#if defined(GLSLEDITOR_LIBRARY)
+# define GLSLEDITOR_EXPORT Q_DECL_EXPORT
+#else
+# define GLSLEDITOR_EXPORT Q_DECL_IMPORT
+#endif
+
+#endif // GLSLEDITOR_GLOBAL_H
diff --git a/src/plugins/glsleditor/glsleditoractionhandler.cpp b/src/plugins/glsleditor/glsleditoractionhandler.cpp
new file mode 100644
index 0000000000..61d524eb1b
--- /dev/null
+++ b/src/plugins/glsleditor/glsleditoractionhandler.cpp
@@ -0,0 +1,57 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "glsleditoractionhandler.h"
+#include "glsleditorconstants.h"
+#include "glsleditor.h"
+
+#include <coreplugin/icore.h>
+#include <coreplugin/actionmanager/actionmanager.h>
+
+#include <QtCore/QDebug>
+#include <QtGui/QAction>
+#include <QtGui/QMainWindow>
+#include <QtGui/QMessageBox>
+
+namespace GLSLEditor {
+namespace Internal {
+
+GLSLEditorActionHandler::GLSLEditorActionHandler()
+ : TextEditor::TextEditorActionHandler(GLSLEditor::Constants::C_GLSLEDITOR_ID, Format)
+{
+}
+
+void GLSLEditorActionHandler::createActions()
+{
+ TextEditor::TextEditorActionHandler::createActions();
+}
+
+
+} // namespace Internal
+} // namespace GLSLEditor
diff --git a/src/plugins/glsleditor/glsleditoractionhandler.h b/src/plugins/glsleditor/glsleditoractionhandler.h
new file mode 100644
index 0000000000..070564fda9
--- /dev/null
+++ b/src/plugins/glsleditor/glsleditoractionhandler.h
@@ -0,0 +1,51 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 GLSLDITORACTIONHANDLER_H
+#define GLSLDITORACTIONHANDLER_H
+
+#include <texteditor/texteditoractionhandler.h>
+
+namespace GLSLEditor {
+namespace Internal {
+
+class GLSLEditorActionHandler : public TextEditor::TextEditorActionHandler
+{
+ Q_OBJECT
+
+public:
+ GLSLEditorActionHandler();
+
+ void createActions();
+};
+
+} // namespace Internal
+} // namespace GLSLEditor
+
+#endif // GLSLDITORACTIONHANDLER_H
diff --git a/src/plugins/glsleditor/glsleditorconstants.h b/src/plugins/glsleditor/glsleditorconstants.h
new file mode 100644
index 0000000000..e9d1f045d2
--- /dev/null
+++ b/src/plugins/glsleditor/glsleditorconstants.h
@@ -0,0 +1,64 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 GLSLEDITOR_CONSTANTS_H
+#define GLSLEDITOR_CONSTANTS_H
+
+#include <QtCore/QtGlobal>
+
+namespace GLSLEditor {
+namespace Constants {
+
+// menus
+const char * const M_CONTEXT = "GLSL Editor.ContextMenu";
+const char * const M_TOOLS_GLSL = "GLSLEditor.Tools.Menu";
+
+const char * const SEPARATOR1 = "GLSLEditor.Separator1";
+const char * const SEPARATOR2 = "GLSLEditor.Separator2";
+const char * const M_REFACTORING_MENU_INSERTION_POINT = "GLSLEditor.RefactorGroup";
+
+const char * const RUN_SEP = "GLSLEditor.Run.Separator";
+const char * const C_GLSLEDITOR_ID = "GLSLEditor.GLSLEditor";
+const char * const C_GLSLEDITOR_DISPLAY_NAME = QT_TRANSLATE_NOOP("OpenWith::Editors", "GLSL Editor");
+const char * const TASK_INDEX = "GLSLEditor.TaskIndex";
+const char * const TASK_SEARCH = "GLSLEditor.TaskSearch";
+
+const char * const GLSL_MIMETYPE = "application/x-glsl";
+const char * const GLSL_MIMETYPE_VERT = "text/x-glsl-vert";
+const char * const GLSL_MIMETYPE_FRAG = "text/x-glsl-frag";
+const char * const GLSL_MIMETYPE_VERT_ES = "text/x-glsl-es-vert";
+const char * const GLSL_MIMETYPE_FRAG_ES = "text/x-glsl-es-frag";
+
+const char * const WIZARD_CATEGORY_GLSL = "U.GLSL";
+const char * const WIZARD_TR_CATEGORY_GLSL = QT_TRANSLATE_NOOP("GLSLEditor", "GLSL");
+
+} // namespace Constants
+} // namespace GLSLEditor
+
+#endif // GLSLEDITOR_CONSTANTS_H
diff --git a/src/plugins/glsleditor/glsleditoreditable.cpp b/src/plugins/glsleditor/glsleditoreditable.cpp
new file mode 100644
index 0000000000..7c2f95c169
--- /dev/null
+++ b/src/plugins/glsleditor/glsleditoreditable.cpp
@@ -0,0 +1,59 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "glsleditoreditable.h"
+#include "glsleditor.h"
+#include "glsleditorconstants.h"
+
+#include <texteditor/texteditorconstants.h>
+#include <qmldesigner/qmldesignerconstants.h>
+
+#include <coreplugin/mimedatabase.h>
+#include <coreplugin/icore.h>
+#include <coreplugin/designmode.h>
+#include <coreplugin/modemanager.h>
+#include <coreplugin/coreconstants.h>
+
+namespace GLSLEditor {
+namespace Internal {
+
+GLSLEditorEditable::GLSLEditorEditable(GLSLTextEditor *editor)
+ : BaseTextEditorEditable(editor)
+{
+ m_context.add(GLSLEditor::Constants::C_GLSLEDITOR_ID);
+ m_context.add(TextEditor::Constants::C_TEXTEDITOR);
+}
+
+QString GLSLEditorEditable::preferredModeType() const
+{
+ return QString();
+}
+
+} // namespace Internal
+} // namespace GLSLEditor
diff --git a/src/plugins/glsleditor/glsleditoreditable.h b/src/plugins/glsleditor/glsleditoreditable.h
new file mode 100644
index 0000000000..e286d5091b
--- /dev/null
+++ b/src/plugins/glsleditor/glsleditoreditable.h
@@ -0,0 +1,62 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 GLSLEDITOREDITABLE_H
+#define GLSLEDITOREDITABLE_H
+
+#include <texteditor/basetexteditor.h>
+
+namespace GLSLEditor {
+class GLSLTextEditor;
+
+namespace Internal {
+
+class GLSLEditorEditable : public TextEditor::BaseTextEditorEditable
+{
+ Q_OBJECT
+
+public:
+ explicit GLSLEditorEditable(GLSLTextEditor *);
+ Core::Context context() const;
+
+ bool duplicateSupported() const { return true; }
+ Core::IEditor *duplicate(QWidget *parent);
+ QString id() const;
+ bool isTemporary() const { return false; }
+ virtual bool open(const QString & fileName);
+ virtual QString preferredModeType() const;
+
+private:
+ Core::Context m_context;
+};
+
+} // namespace Internal
+} // namespace GLSLEditor
+
+#endif // GLSLEDITOREDITABLE_H
diff --git a/src/plugins/glsleditor/glsleditorfactory.cpp b/src/plugins/glsleditor/glsleditorfactory.cpp
new file mode 100644
index 0000000000..06cd4edf7d
--- /dev/null
+++ b/src/plugins/glsleditor/glsleditorfactory.cpp
@@ -0,0 +1,104 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "glsleditorfactory.h"
+#include "glsleditoreditable.h"
+#include "glsleditor.h"
+#include "glsleditoractionhandler.h"
+#include "glsleditorconstants.h"
+#include "glsleditorplugin.h"
+
+#include <extensionsystem/pluginmanager.h>
+#include <extensionsystem/pluginspec.h>
+
+#include <coreplugin/icore.h>
+#include <coreplugin/editormanager/editormanager.h>
+
+#include <QtCore/QFileInfo>
+#include <QtCore/QDebug>
+#include <QtCore/QSettings>
+#include <QtGui/QMessageBox>
+#include <QtGui/QPushButton>
+#include <QtGui/QMainWindow>
+
+using namespace GLSLEditor::Internal;
+using namespace GLSLEditor::Constants;
+
+GLSLEditorFactory::GLSLEditorFactory(QObject *parent)
+ : Core::IEditorFactory(parent)
+{
+ m_mimeTypes
+ << QLatin1String(GLSLEditor::Constants::GLSL_MIMETYPE)
+ << QLatin1String(GLSLEditor::Constants::GLSL_MIMETYPE_VERT)
+ << QLatin1String(GLSLEditor::Constants::GLSL_MIMETYPE_FRAG)
+ << QLatin1String(GLSLEditor::Constants::GLSL_MIMETYPE_VERT_ES)
+ << QLatin1String(GLSLEditor::Constants::GLSL_MIMETYPE_FRAG_ES)
+ ;
+}
+
+GLSLEditorFactory::~GLSLEditorFactory()
+{
+}
+
+QString GLSLEditorFactory::id() const
+{
+ return QLatin1String(C_GLSLEDITOR_ID);
+}
+
+QString GLSLEditorFactory::displayName() const
+{
+ return tr(C_GLSLEDITOR_DISPLAY_NAME);
+}
+
+
+Core::IFile *GLSLEditorFactory::open(const QString &fileName)
+{
+ Core::IEditor *iface = Core::EditorManager::instance()->openEditor(fileName, id());
+ if (!iface) {
+ qWarning() << "QmlEditorFactory::open: openEditor failed for " << fileName;
+ return 0;
+ }
+ return iface->file();
+}
+
+Core::IEditor *GLSLEditorFactory::createEditor(QWidget *parent)
+{
+ GLSLEditor::GLSLTextEditor *rc = new GLSLEditor::GLSLTextEditor(parent);
+ GLSLEditorPlugin::instance()->initializeEditor(rc);
+ return rc->editableInterface();
+}
+
+QStringList GLSLEditorFactory::mimeTypes() const
+{
+ return m_mimeTypes;
+}
+
+void GLSLEditorFactory::updateEditorInfoBar(Core::IEditor *)
+{
+}
diff --git a/src/plugins/glsleditor/glsleditorfactory.h b/src/plugins/glsleditor/glsleditorfactory.h
new file mode 100644
index 0000000000..12ad9decc8
--- /dev/null
+++ b/src/plugins/glsleditor/glsleditorfactory.h
@@ -0,0 +1,71 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 GLSLEDITORFACTORY_H
+#define GLSLEDITORFACTORY_H
+
+#include <coreplugin/editormanager/ieditorfactory.h>
+
+#include <QtCore/QStringList>
+
+namespace TextEditor {
+class TextEditorActionHandler;
+}
+
+namespace GLSLEditor {
+namespace Internal {
+
+class GLSLEditorActionHandler;
+
+class GLSLEditorFactory : public Core::IEditorFactory
+{
+ Q_OBJECT
+
+public:
+ GLSLEditorFactory(QObject *parent);
+ ~GLSLEditorFactory();
+
+ virtual QStringList mimeTypes() const;
+ // IEditorFactory
+ QString id() const;
+ QString displayName() const;
+ Core::IFile *open(const QString &fileName);
+ Core::IEditor *createEditor(QWidget *parent);
+
+private slots:
+ void updateEditorInfoBar(Core::IEditor *editor);
+
+private:
+ QStringList m_mimeTypes;
+};
+
+} // namespace Internal
+} // namespace GLSLEditor
+
+#endif // GLSLEDITORFACTORY_H
diff --git a/src/plugins/glsleditor/glsleditorplugin.cpp b/src/plugins/glsleditor/glsleditorplugin.cpp
new file mode 100644
index 0000000000..62fbc9c8bf
--- /dev/null
+++ b/src/plugins/glsleditor/glsleditorplugin.cpp
@@ -0,0 +1,316 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "glsleditorplugin.h"
+#include "glsleditor.h"
+#include "glsleditorconstants.h"
+#include "glsleditorfactory.h"
+#include "glslcodecompletion.h"
+#include "glslfilewizard.h"
+#include "glslhoverhandler.h"
+
+#include <coreplugin/icore.h>
+#include <coreplugin/coreconstants.h>
+#include <coreplugin/mimedatabase.h>
+#include <coreplugin/uniqueidmanager.h>
+#include <coreplugin/fileiconprovider.h>
+#include <coreplugin/actionmanager/actionmanager.h>
+#include <coreplugin/actionmanager/actioncontainer.h>
+#include <coreplugin/actionmanager/command.h>
+#include <coreplugin/editormanager/editormanager.h>
+#include <projectexplorer/taskhub.h>
+#include <extensionsystem/pluginmanager.h>
+#include <texteditor/fontsettings.h>
+#include <texteditor/storagesettings.h>
+#include <texteditor/texteditorconstants.h>
+#include <texteditor/texteditorsettings.h>
+#include <texteditor/textfilewizard.h>
+#include <texteditor/texteditoractionhandler.h>
+#include <texteditor/completionsupport.h>
+#include <utils/qtcassert.h>
+
+#include <glsl/glslengine.h>
+#include <glsl/glslparser.h>
+#include <glsl/glsllexer.h>
+
+#include <QtCore/QtPlugin>
+#include <QtCore/QDebug>
+#include <QtCore/QSettings>
+#include <QtCore/QDir>
+#include <QtCore/QCoreApplication>
+#include <QtCore/QTimer>
+#include <QtGui/QMenu>
+#include <QtGui/QAction>
+
+using namespace GLSLEditor;
+using namespace GLSLEditor::Internal;
+using namespace GLSLEditor::Constants;
+
+GLSLEditorPlugin *GLSLEditorPlugin::m_instance = 0;
+
+GLSLEditorPlugin::InitFile::~InitFile()
+{
+ delete engine;
+}
+
+GLSLEditorPlugin::GLSLEditorPlugin() :
+ m_editor(0),
+ m_actionHandler(0)
+{
+ m_instance = this;
+}
+
+GLSLEditorPlugin::~GLSLEditorPlugin()
+{
+ removeObject(m_editor);
+ delete m_actionHandler;
+ m_instance = 0;
+}
+
+/*! Copied from cppplugin.cpp */
+static inline
+Core::Command *createSeparator(Core::ActionManager *am,
+ QObject *parent,
+ Core::Context &context,
+ const char *id)
+{
+ QAction *separator = new QAction(parent);
+ separator->setSeparator(true);
+ return am->registerAction(separator, Core::Id(id), context);
+}
+
+bool GLSLEditorPlugin::initialize(const QStringList & /*arguments*/, QString *error_message)
+{
+ Core::ICore *core = Core::ICore::instance();
+ if (!core->mimeDatabase()->addMimeTypes(QLatin1String(":/glsleditor/GLSLEditor.mimetypes.xml"), error_message))
+ return false;
+
+ parseGlslFile(QLatin1String("glsl_120.frag"), &m_glsl_120_frag);
+ parseGlslFile(QLatin1String("glsl_120.vert"), &m_glsl_120_vert);
+ parseGlslFile(QLatin1String("glsl_120_common.glsl"), &m_glsl_120_common);
+ parseGlslFile(QLatin1String("glsl_es_100.frag"), &m_glsl_es_100_frag);
+ parseGlslFile(QLatin1String("glsl_es_100.vert"), &m_glsl_es_100_vert);
+ parseGlslFile(QLatin1String("glsl_es_100_common.glsl"), &m_glsl_es_100_common);
+
+
+// m_modelManager = new ModelManager(this);
+// addAutoReleasedObject(m_modelManager);
+
+ addAutoReleasedObject(new GLSLHoverHandler(this));
+
+ Core::Context context(GLSLEditor::Constants::C_GLSLEDITOR_ID);
+
+ m_editor = new GLSLEditorFactory(this);
+ addObject(m_editor);
+
+ CodeCompletion *completion = new CodeCompletion(this);
+ addAutoReleasedObject(completion);
+
+ m_actionHandler = new TextEditor::TextEditorActionHandler(GLSLEditor::Constants::C_GLSLEDITOR_ID,
+ TextEditor::TextEditorActionHandler::Format
+ | TextEditor::TextEditorActionHandler::UnCommentSelection
+ | TextEditor::TextEditorActionHandler::UnCollapseAll);
+ m_actionHandler->initializeActions();
+
+ Core::ActionManager *am = core->actionManager();
+ Core::ActionContainer *contextMenu = am->createMenu(GLSLEditor::Constants::M_CONTEXT);
+ Core::ActionContainer *glslToolsMenu = am->createMenu(Core::Id(Constants::M_TOOLS_GLSL));
+ glslToolsMenu->setOnAllDisabledBehavior(Core::ActionContainer::Hide);
+ QMenu *menu = glslToolsMenu->menu();
+ //: GLSL sub-menu in the Tools menu
+ menu->setTitle(tr("GLSL"));
+ am->actionContainer(Core::Constants::M_TOOLS)->addMenu(glslToolsMenu);
+
+ Core::Command *cmd = 0;
+
+ // Insert marker for "Refactoring" menu:
+ Core::Context globalContext(Core::Constants::C_GLOBAL);
+ Core::Command *sep = createSeparator(am, this, globalContext,
+ Constants::SEPARATOR1);
+ sep->action()->setObjectName(Constants::M_REFACTORING_MENU_INSERTION_POINT);
+ contextMenu->addAction(sep);
+ contextMenu->addAction(createSeparator(am, this, globalContext,
+ Constants::SEPARATOR2));
+
+ cmd = am->command(TextEditor::Constants::UN_COMMENT_SELECTION);
+ contextMenu->addAction(cmd);
+
+ // Set completion settings and keep them up to date
+ TextEditor::TextEditorSettings *textEditorSettings = TextEditor::TextEditorSettings::instance();
+ completion->setCompletionSettings(textEditorSettings->completionSettings());
+ connect(textEditorSettings, SIGNAL(completionSettingsChanged(TextEditor::CompletionSettings)),
+ completion, SLOT(setCompletionSettings(TextEditor::CompletionSettings)));
+
+ error_message->clear();
+
+ Core::FileIconProvider *iconProvider = Core::FileIconProvider::instance();
+ Core::MimeDatabase *mimeDatabase = Core::ICore::instance()->mimeDatabase();
+ iconProvider->registerIconOverlayForMimeType(QIcon(QLatin1String(":/glsleditor/images/glslfile.png")),
+ mimeDatabase->findByType(QLatin1String(GLSLEditor::Constants::GLSL_MIMETYPE)));
+ iconProvider->registerIconOverlayForMimeType(QIcon(QLatin1String(":/glsleditor/images/glslfile.png")),
+ mimeDatabase->findByType(QLatin1String(GLSLEditor::Constants::GLSL_MIMETYPE_VERT)));
+ iconProvider->registerIconOverlayForMimeType(QIcon(QLatin1String(":/glsleditor/images/glslfile.png")),
+ mimeDatabase->findByType(QLatin1String(GLSLEditor::Constants::GLSL_MIMETYPE_FRAG)));
+ iconProvider->registerIconOverlayForMimeType(QIcon(QLatin1String(":/glsleditor/images/glslfile.png")),
+ mimeDatabase->findByType(QLatin1String(GLSLEditor::Constants::GLSL_MIMETYPE_VERT_ES)));
+ iconProvider->registerIconOverlayForMimeType(QIcon(QLatin1String(":/glsleditor/images/glslfile.png")),
+ mimeDatabase->findByType(QLatin1String(GLSLEditor::Constants::GLSL_MIMETYPE_FRAG_ES)));
+
+ Core::BaseFileWizardParameters fragWizardParameters(Core::IWizard::FileWizard);
+ fragWizardParameters.setCategory(QLatin1String(Constants::WIZARD_CATEGORY_GLSL));
+ fragWizardParameters.setDisplayCategory(QCoreApplication::translate("GLSLEditor", Constants::WIZARD_TR_CATEGORY_GLSL));
+ fragWizardParameters.setDescription
+ (tr("Creates a fragment shader in the OpenGL/ES 2.0 Shading "
+ "Language (GLSL/ES). Fragment shaders generate the final "
+ "pixel colors for triangles, points, and lines rendered "
+ "with OpenGL."));
+ fragWizardParameters.setDisplayName(tr("Fragment shader (OpenGL/ES 2.0)"));
+ fragWizardParameters.setId(QLatin1String("F.GLSL"));
+ addAutoReleasedObject(new GLSLFileWizard(fragWizardParameters, GLSLFileWizard::FragmentShaderES, core));
+
+ Core::BaseFileWizardParameters vertWizardParameters(Core::IWizard::FileWizard);
+ vertWizardParameters.setCategory(QLatin1String(Constants::WIZARD_CATEGORY_GLSL));
+ vertWizardParameters.setDisplayCategory(QCoreApplication::translate("GLSLEditor", Constants::WIZARD_TR_CATEGORY_GLSL));
+ vertWizardParameters.setDescription
+ (tr("Creates a vertex shader in the OpenGL/ES 2.0 Shading "
+ "Language (GLSL/ES). Vertex shaders transform the "
+ "positions, normals, and texture co-ordinates of "
+ "triangles, points, and lines rendered with OpenGL."));
+ vertWizardParameters.setDisplayName(tr("Vertex shader (OpenGL/ES 2.0)"));
+ vertWizardParameters.setId(QLatin1String("G.GLSL"));
+ addAutoReleasedObject(new GLSLFileWizard(vertWizardParameters, GLSLFileWizard::VertexShaderES, core));
+
+ fragWizardParameters.setDescription
+ (tr("Creates a fragment shader in the Desktop OpenGL Shading "
+ "Language (GLSL). Fragment shaders generate the final "
+ "pixel colors for triangles, points, and lines rendered "
+ "with OpenGL."));
+ fragWizardParameters.setDisplayName(tr("Fragment shader (Desktop OpenGL)"));
+ fragWizardParameters.setId(QLatin1String("J.GLSL"));
+ addAutoReleasedObject(new GLSLFileWizard(fragWizardParameters, GLSLFileWizard::FragmentShaderDesktop, core));
+
+ vertWizardParameters.setDescription
+ (tr("Creates a vertex shader in the Desktop OpenGL Shading "
+ "Language (GLSL). Vertex shaders transform the "
+ "positions, normals, and texture co-ordinates of "
+ "triangles, points, and lines rendered with OpenGL."));
+ vertWizardParameters.setDisplayName(tr("Vertex shader (Desktop OpenGL)"));
+ vertWizardParameters.setId(QLatin1String("K.GLSL"));
+ addAutoReleasedObject(new GLSLFileWizard(vertWizardParameters, GLSLFileWizard::VertexShaderDesktop, core));
+
+ return true;
+}
+
+void GLSLEditorPlugin::extensionsInitialized()
+{
+}
+
+ExtensionSystem::IPlugin::ShutdownFlag GLSLEditorPlugin::aboutToShutdown()
+{
+ // delete GLSL::Icons::instance(); // delete object held by singleton
+
+ return IPlugin::aboutToShutdown();
+}
+
+void GLSLEditorPlugin::initializeEditor(GLSLEditor::GLSLTextEditor *editor)
+{
+ QTC_ASSERT(m_instance, /**/);
+
+ m_actionHandler->setupActions(editor);
+
+ TextEditor::TextEditorSettings::instance()->initializeEditor(editor);
+
+// // auto completion
+ connect(editor, SIGNAL(requestAutoCompletion(TextEditor::ITextEditable*, bool)),
+ TextEditor::CompletionSupport::instance(), SLOT(autoComplete(TextEditor::ITextEditable*, bool)));
+
+// // quick fix
+// connect(editor, SIGNAL(requestQuickFix(TextEditor::ITextEditable*)),
+// this, SLOT(quickFix(TextEditor::ITextEditable*)));
+}
+
+
+Core::Command *GLSLEditorPlugin::addToolAction(QAction *a, Core::ActionManager *am,
+ Core::Context &context, const QString &name,
+ Core::ActionContainer *c1, const QString &keySequence)
+{
+ Core::Command *command = am->registerAction(a, name, context);
+ if (!keySequence.isEmpty())
+ command->setDefaultKeySequence(QKeySequence(keySequence));
+ c1->addAction(command);
+ return command;
+}
+
+QByteArray GLSLEditorPlugin::glslFile(const QString &fileName)
+{
+ QString path = Core::ICore::instance()->resourcePath();
+ path += QLatin1String("/glsl/");
+ path += fileName;
+ QFile file(path);
+ if (file.open(QFile::ReadOnly))
+ return file.readAll();
+ return QByteArray();
+}
+
+void GLSLEditorPlugin::parseGlslFile(const QString &fileName, InitFile *initFile)
+{
+ // Parse the builtins for any langugage variant so we can use all keywords.
+ const unsigned variant = GLSL::Lexer::Variant_All;
+
+ const QByteArray code = glslFile(fileName);
+ initFile->engine = new GLSL::Engine();
+ GLSL::Parser parser(initFile->engine, code.constData(), code.size(), variant);
+ initFile->ast = parser.parse();
+}
+
+const GLSLEditorPlugin::InitFile *GLSLEditorPlugin::fragmentShaderInit(int variant) const
+{
+ if (variant & GLSL::Lexer::Variant_GLSL_120)
+ return &m_glsl_120_frag;
+ else
+ return &m_glsl_es_100_frag;
+}
+
+const GLSLEditorPlugin::InitFile *GLSLEditorPlugin::vertexShaderInit(int variant) const
+{
+ if (variant & GLSL::Lexer::Variant_GLSL_120)
+ return &m_glsl_120_vert;
+ else
+ return &m_glsl_es_100_vert;
+}
+
+const GLSLEditorPlugin::InitFile *GLSLEditorPlugin::shaderInit(int variant) const
+{
+ if (variant & GLSL::Lexer::Variant_GLSL_120)
+ return &m_glsl_120_common;
+ else
+ return &m_glsl_es_100_common;
+}
+
+Q_EXPORT_PLUGIN(GLSLEditorPlugin)
diff --git a/src/plugins/glsleditor/glsleditorplugin.h b/src/plugins/glsleditor/glsleditorplugin.h
new file mode 100644
index 0000000000..d9ddbfb0d7
--- /dev/null
+++ b/src/plugins/glsleditor/glsleditorplugin.h
@@ -0,0 +1,126 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 GLSLEDITORPLUGIN_H
+#define GLSLEDITORPLUGIN_H
+
+#include <extensionsystem/iplugin.h>
+#include <coreplugin/icontext.h>
+#include <QtCore/QPointer>
+#include <glsl/glsl.h>
+
+QT_FORWARD_DECLARE_CLASS(QAction)
+QT_FORWARD_DECLARE_CLASS(QTimer)
+
+namespace TextEditor {
+class TextEditorActionHandler;
+} // namespace TextEditor
+
+namespace Core {
+class Command;
+class ActionContainer;
+class ActionManager;
+}
+
+namespace TextEditor {
+class ITextEditable;
+}
+
+namespace GLSL {
+class ModelManagerInterface;
+}
+
+namespace GLSLEditor {
+
+class GLSLTextEditor;
+
+namespace Internal {
+
+class GLSLEditorFactory;
+class GLSLPreviewRunner;
+class GLSLQuickFixCollector;
+
+class GLSLEditorPlugin : public ExtensionSystem::IPlugin
+{
+ Q_OBJECT
+
+public:
+ GLSLEditorPlugin();
+ virtual ~GLSLEditorPlugin();
+
+ // IPlugin
+ bool initialize(const QStringList &arguments, QString *errorMessage = 0);
+ void extensionsInitialized();
+ ShutdownFlag aboutToShutdown();
+
+ static GLSLEditorPlugin *instance()
+ { return m_instance; }
+
+ void initializeEditor(GLSLEditor::GLSLTextEditor *editor);
+
+ struct InitFile {
+ GLSL::Engine *engine;
+ GLSL::TranslationUnitAST *ast;
+
+ InitFile(GLSL::Engine *engine = 0, GLSL::TranslationUnitAST *ast = 0)
+ : engine(engine), ast(ast) {}
+
+ ~InitFile();
+ };
+
+ const InitFile *fragmentShaderInit(int variant) const;
+ const InitFile *vertexShaderInit(int variant) const;
+ const InitFile *shaderInit(int variant) const;
+
+private:
+ QByteArray glslFile(const QString &fileName);
+ void parseGlslFile(const QString &fileName, InitFile *initFile);
+
+ Core::Command *addToolAction(QAction *a, Core::ActionManager *am, Core::Context &context, const QString &name,
+ Core::ActionContainer *c1, const QString &keySequence);
+
+ static GLSLEditorPlugin *m_instance;
+
+ GLSLEditorFactory *m_editor;
+ TextEditor::TextEditorActionHandler *m_actionHandler;
+
+ QPointer<TextEditor::ITextEditable> m_currentTextEditable;
+
+ InitFile m_glsl_120_frag;
+ InitFile m_glsl_120_vert;
+ InitFile m_glsl_120_common;
+ InitFile m_glsl_es_100_frag;
+ InitFile m_glsl_es_100_vert;
+ InitFile m_glsl_es_100_common;
+};
+
+} // namespace Internal
+} // namespace GLSLEditor
+
+#endif // GLSLEDITORPLUGIN_H
diff --git a/src/plugins/glsleditor/glslfilewizard.cpp b/src/plugins/glsleditor/glslfilewizard.cpp
new file mode 100644
index 0000000000..c31b5f3bf1
--- /dev/null
+++ b/src/plugins/glsleditor/glslfilewizard.cpp
@@ -0,0 +1,160 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "glsleditorconstants.h"
+#include "glslfilewizard.h"
+
+#include <utils/filewizarddialog.h>
+#include <utils/qtcassert.h>
+#include <utils/filewizarddialog.h>
+
+#include <QtCore/QFileInfo>
+#include <QtCore/QTextStream>
+#include <QtGui/QWizard>
+#include <QtGui/QPushButton>
+
+namespace {
+class GLSLFileWizardDialog : public Utils::FileWizardDialog
+{
+ Q_OBJECT
+public:
+ GLSLFileWizardDialog(QWidget *parent = 0)
+ : Utils::FileWizardDialog(parent)
+ {
+ }
+};
+} // anonymous namespace
+
+using namespace GLSLEditor;
+
+GLSLFileWizard::GLSLFileWizard(const BaseFileWizardParameters &parameters,
+ ShaderType shaderType, QObject *parent):
+ Core::BaseFileWizard(parameters, parent),
+ m_shaderType(shaderType)
+{
+}
+
+Core::GeneratedFiles GLSLFileWizard::generateFiles(const QWizard *w,
+ QString * /*errorMessage*/) const
+{
+ const GLSLFileWizardDialog *wizardDialog = qobject_cast<const GLSLFileWizardDialog *>(w);
+ const QString path = wizardDialog->path();
+ const QString name = wizardDialog->fileName();
+
+ const QString fileName = Core::BaseFileWizard::buildFileName(path, name, preferredSuffix(m_shaderType));
+
+ Core::GeneratedFile file(fileName);
+ file.setContents(fileContents(fileName, m_shaderType));
+ file.setAttributes(Core::GeneratedFile::OpenEditorAttribute);
+ return Core::GeneratedFiles() << file;
+}
+
+QString GLSLFileWizard::fileContents(const QString &, ShaderType shaderType) const
+{
+ QString contents;
+ QTextStream str(&contents);
+
+ switch (shaderType) {
+ case GLSLFileWizard::VertexShaderES:
+ str << QLatin1String("attribute highp vec4 qt_Vertex;\n")
+ << QLatin1String("attribute highp vec4 qt_MultiTexCoord0;\n")
+ << QLatin1String("uniform highp mat4 qt_ModelViewProjectionMatrix;\n")
+ << QLatin1String("varying highp vec4 qt_TexCoord0;\n")
+ << QLatin1String("\n")
+ << QLatin1String("void main(void)\n")
+ << QLatin1String("{\n")
+ << QLatin1String(" gl_Position = qt_ModelViewProjectionMatrix * qt_Vertex;\n")
+ << QLatin1String(" qt_TexCoord0 = qt_MultiTexCoord0;\n")
+ << QLatin1String("}\n");
+ break;
+ case GLSLFileWizard::FragmentShaderES:
+ str << QLatin1String("uniform sampler2D qt_Texture0;\n")
+ << QLatin1String("varying highp vec4 qt_TexCoord0;\n")
+ << QLatin1String("\n")
+ << QLatin1String("void main(void)\n")
+ << QLatin1String("{\n")
+ << QLatin1String(" gl_FragColor = texture2D(qt_Texture0, qt_TexCoord0.st);\n")
+ << QLatin1String("}\n");
+ break;
+ case GLSLFileWizard::VertexShaderDesktop:
+ str << QLatin1String("attribute vec4 qt_Vertex;\n")
+ << QLatin1String("attribute vec4 qt_MultiTexCoord0;\n")
+ << QLatin1String("uniform mat4 qt_ModelViewProjectionMatrix;\n")
+ << QLatin1String("varying vec4 qt_TexCoord0;\n")
+ << QLatin1String("\n")
+ << QLatin1String("void main(void)\n")
+ << QLatin1String("{\n")
+ << QLatin1String(" gl_Position = qt_ModelViewProjectionMatrix * qt_Vertex;\n")
+ << QLatin1String(" qt_TexCoord0 = qt_MultiTexCoord0;\n")
+ << QLatin1String("}\n");
+ break;
+ case GLSLFileWizard::FragmentShaderDesktop:
+ str << QLatin1String("uniform sampler2D qt_Texture0;\n")
+ << QLatin1String("varying vec4 qt_TexCoord0;\n")
+ << QLatin1String("\n")
+ << QLatin1String("void main(void)\n")
+ << QLatin1String("{\n")
+ << QLatin1String(" gl_FragColor = texture2D(qt_Texture0, qt_TexCoord0.st);\n")
+ << QLatin1String("}\n");
+ break;
+ default: break;
+ }
+
+ return contents;
+}
+
+QWizard *GLSLFileWizard::createWizardDialog(QWidget *parent, const QString &defaultPath,
+ const WizardPageList &extensionPages) const
+{
+ GLSLFileWizardDialog *wizardDialog = new GLSLFileWizardDialog(parent);
+ wizardDialog->setWindowTitle(tr("New %1").arg(displayName()));
+ setupWizard(wizardDialog);
+ wizardDialog->setPath(defaultPath);
+ foreach (QWizardPage *p, extensionPages)
+ BaseFileWizard::applyExtensionPageShortTitle(wizardDialog, wizardDialog->addPage(p));
+ return wizardDialog;
+}
+
+QString GLSLFileWizard::preferredSuffix(ShaderType shaderType) const
+{
+ switch (shaderType) {
+ case GLSLFileWizard::VertexShaderES:
+ return QLatin1String("vsh");
+ case GLSLFileWizard::FragmentShaderES:
+ return QLatin1String("fsh");
+ case GLSLFileWizard::VertexShaderDesktop:
+ return QLatin1String("vert");
+ case GLSLFileWizard::FragmentShaderDesktop:
+ return QLatin1String("frag");
+ default:
+ return QLatin1String("glsl");
+ }
+}
+
+#include "glslfilewizard.moc"
diff --git a/src/plugins/glsleditor/glslfilewizard.h b/src/plugins/glsleditor/glslfilewizard.h
new file mode 100644
index 0000000000..2133ef26a5
--- /dev/null
+++ b/src/plugins/glsleditor/glslfilewizard.h
@@ -0,0 +1,73 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 GLSLFILEWIZARD_H
+#define GLSLFILEWIZARD_H
+
+#include <coreplugin/basefilewizard.h>
+
+namespace GLSLEditor {
+
+class GLSLFileWizard: public Core::BaseFileWizard
+{
+ Q_OBJECT
+
+public:
+ typedef Core::BaseFileWizardParameters BaseFileWizardParameters;
+
+ enum ShaderType
+ {
+ VertexShaderES,
+ FragmentShaderES,
+ VertexShaderDesktop,
+ FragmentShaderDesktop
+ };
+
+ explicit GLSLFileWizard(const BaseFileWizardParameters &parameters,
+ ShaderType shaderType, QObject *parent = 0);
+
+protected:
+ QString fileContents(const QString &baseName, ShaderType shaderType) const;
+
+ virtual QWizard *createWizardDialog(QWidget *parent,
+ const QString &defaultPath,
+ const WizardPageList &extensionPages) const;
+
+ virtual Core::GeneratedFiles generateFiles(const QWizard *w,
+ QString *errorMessage) const;
+
+ virtual QString preferredSuffix(ShaderType shaderType) const;
+
+private:
+ ShaderType m_shaderType;
+};
+
+} // namespace GLSLEditor
+
+#endif // GLSLFILEWIZARD_H
diff --git a/src/plugins/glsleditor/glslhighlighter.cpp b/src/plugins/glsleditor/glslhighlighter.cpp
new file mode 100644
index 0000000000..6d5edb802b
--- /dev/null
+++ b/src/plugins/glsleditor/glslhighlighter.cpp
@@ -0,0 +1,404 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "glslhighlighter.h"
+#include "glsleditor.h"
+#include <glsl/glsllexer.h>
+#include <glsl/glslparser.h>
+#include <texteditor/basetextdocumentlayout.h>
+
+#include <QtCore/QDebug>
+
+using namespace GLSLEditor;
+using namespace GLSLEditor::Internal;
+using namespace TextEditor;
+
+Highlighter::Highlighter(GLSLTextEditor *editor, QTextDocument *parent)
+ : TextEditor::SyntaxHighlighter(parent), m_editor(editor)
+{
+}
+
+Highlighter::~Highlighter()
+{
+
+}
+
+void Highlighter::setFormats(const QVector<QTextCharFormat> &formats)
+{
+ qCopy(formats.begin(), formats.end(), m_formats);
+}
+
+void Highlighter::highlightBlock(const QString &text)
+{
+ const int previousState = previousBlockState();
+ int state = 0, initialBraceDepth = 0;
+ if (previousState != -1) {
+ state = previousState & 0xff;
+ initialBraceDepth = previousState >> 8;
+ }
+
+ int braceDepth = initialBraceDepth;
+
+ const QByteArray data = text.toLatin1();
+ GLSL::Lexer lex(/*engine=*/ 0, data.constData(), data.size());
+ lex.setState(state);
+ lex.setScanKeywords(false);
+ lex.setScanComments(true);
+ const int variant = m_editor->languageVariant();
+ lex.setVariant(variant);
+
+ int initialState = state;
+
+ QList<GLSL::Token> tokens;
+ GLSL::Token tk;
+ do {
+ lex.yylex(&tk);
+ tokens.append(tk);
+ } while (tk.isNot(GLSL::Parser::EOF_SYMBOL));
+
+ state = lex.state(); // refresh the state
+
+ int foldingIndent = initialBraceDepth;
+ if (TextBlockUserData *userData = BaseTextDocumentLayout::testUserData(currentBlock())) {
+ userData->setFoldingIndent(0);
+ userData->setFoldingStartIncluded(false);
+ userData->setFoldingEndIncluded(false);
+ }
+
+ if (tokens.isEmpty()) {
+ setCurrentBlockState(previousState);
+ BaseTextDocumentLayout::clearParentheses(currentBlock());
+ if (text.length()) // the empty line can still contain whitespace
+ setFormat(0, text.length(), m_formats[GLSLVisualWhitespace]);
+ BaseTextDocumentLayout::setFoldingIndent(currentBlock(), foldingIndent);
+ return;
+ }
+
+ const int firstNonSpace = tokens.first().begin();
+
+ Parentheses parentheses;
+ parentheses.reserve(20); // assume wizard level ;-)
+
+ bool highlightAsPreprocessor = false;
+
+ for (int i = 0; i < tokens.size(); ++i) {
+ const GLSL::Token &tk = tokens.at(i);
+
+ int previousTokenEnd = 0;
+ if (i != 0) {
+ // mark the whitespaces
+ previousTokenEnd = tokens.at(i - 1).begin() +
+ tokens.at(i - 1).length;
+ }
+
+ if (previousTokenEnd != tk.begin()) {
+ setFormat(previousTokenEnd, tk.begin() - previousTokenEnd,
+ m_formats[GLSLVisualWhitespace]);
+ }
+
+ if (tk.is(GLSL::Parser::T_LEFT_PAREN) || tk.is(GLSL::Parser::T_LEFT_BRACE) || tk.is(GLSL::Parser::T_LEFT_BRACKET)) {
+ const QChar c = text.at(tk.begin());
+ parentheses.append(Parenthesis(Parenthesis::Opened, c, tk.begin()));
+ if (tk.is(GLSL::Parser::T_LEFT_BRACE)) {
+ ++braceDepth;
+
+ // if a folding block opens at the beginning of a line, treat the entire line
+ // as if it were inside the folding block
+ if (tk.begin() == firstNonSpace) {
+ ++foldingIndent;
+ BaseTextDocumentLayout::userData(currentBlock())->setFoldingStartIncluded(true);
+ }
+ }
+ } else if (tk.is(GLSL::Parser::T_RIGHT_PAREN) || tk.is(GLSL::Parser::T_RIGHT_BRACE) || tk.is(GLSL::Parser::T_RIGHT_BRACKET)) {
+ const QChar c = text.at(tk.begin());
+ parentheses.append(Parenthesis(Parenthesis::Closed, c, tk.begin()));
+ if (tk.is(GLSL::Parser::T_RIGHT_BRACE)) {
+ --braceDepth;
+ if (braceDepth < foldingIndent) {
+ // unless we are at the end of the block, we reduce the folding indent
+ if (i == tokens.size()-1 || tokens.at(i+1).is(GLSL::Parser::T_SEMICOLON))
+ BaseTextDocumentLayout::userData(currentBlock())->setFoldingEndIncluded(true);
+ else
+ foldingIndent = qMin(braceDepth, foldingIndent);
+ }
+ }
+ }
+
+ bool highlightCurrentWordAsPreprocessor = highlightAsPreprocessor;
+
+ if (highlightAsPreprocessor)
+ highlightAsPreprocessor = false;
+
+ if (false /* && i == 0 && tk.is(GLSL::Parser::T_POUND)*/) {
+ highlightLine(text, tk.begin(), tk.length, m_formats[GLSLPreprocessorFormat]);
+ highlightAsPreprocessor = true;
+
+ } else if (highlightCurrentWordAsPreprocessor && isPPKeyword(text.midRef(tk.begin(), tk.length)))
+ setFormat(tk.begin(), tk.length, m_formats[GLSLPreprocessorFormat]);
+
+ else if (tk.is(GLSL::Parser::T_NUMBER))
+ setFormat(tk.begin(), tk.length, m_formats[GLSLNumberFormat]);
+
+ else if (tk.is(GLSL::Parser::T_COMMENT)) {
+ highlightLine(text, tk.begin(), tk.length, m_formats[GLSLCommentFormat]);
+
+ // we need to insert a close comment parenthesis, if
+ // - the line starts in a C Comment (initalState != 0)
+ // - the first token of the line is a T_COMMENT (i == 0 && tk.is(T_COMMENT))
+ // - is not a continuation line (tokens.size() > 1 || ! state)
+ if (initialState && i == 0 && (tokens.size() > 1 || ! state)) {
+ --braceDepth;
+ // unless we are at the end of the block, we reduce the folding indent
+ if (i == tokens.size()-1)
+ BaseTextDocumentLayout::userData(currentBlock())->setFoldingEndIncluded(true);
+ else
+ foldingIndent = qMin(braceDepth, foldingIndent);
+ const int tokenEnd = tk.begin() + tk.length - 1;
+ parentheses.append(Parenthesis(Parenthesis::Closed, QLatin1Char('-'), tokenEnd));
+
+ // clear the initial state.
+ initialState = 0;
+ }
+
+ } else if (tk.is(GLSL::Parser::T_IDENTIFIER)) {
+ int kind = lex.findKeyword(data.constData() + tk.position, tk.length);
+ if (kind == GLSL::Parser::T_RESERVED)
+ setFormat(tk.position, tk.length, m_formats[GLSLReservedKeyword]);
+ else if (kind != GLSL::Parser::T_IDENTIFIER)
+ setFormat(tk.position, tk.length, m_formats[GLSLKeywordFormat]);
+ }
+ }
+
+ // mark the trailing white spaces
+ {
+ const GLSL::Token tk = tokens.last();
+ const int lastTokenEnd = tk.begin() + tk.length;
+ if (text.length() > lastTokenEnd)
+ highlightLine(text, lastTokenEnd, text.length() - lastTokenEnd, QTextCharFormat());
+ }
+
+ if (! initialState && state && ! tokens.isEmpty()) {
+ parentheses.append(Parenthesis(Parenthesis::Opened, QLatin1Char('+'),
+ tokens.last().begin()));
+ ++braceDepth;
+ }
+
+ BaseTextDocumentLayout::setParentheses(currentBlock(), parentheses);
+
+ // if the block is ifdefed out, we only store the parentheses, but
+
+ // do not adjust the brace depth.
+ if (BaseTextDocumentLayout::ifdefedOut(currentBlock())) {
+ braceDepth = initialBraceDepth;
+ foldingIndent = initialBraceDepth;
+ }
+
+ BaseTextDocumentLayout::setFoldingIndent(currentBlock(), foldingIndent);
+
+ // optimization: if only the brace depth changes, we adjust subsequent blocks
+ // to have QSyntaxHighlighter stop the rehighlighting
+ int currentState = currentBlockState();
+ if (currentState != -1) {
+ int oldState = currentState & 0xff;
+ int oldBraceDepth = currentState >> 8;
+ if (oldState == lex.state() && oldBraceDepth != braceDepth) {
+ int delta = braceDepth - oldBraceDepth;
+ QTextBlock block = currentBlock().next();
+ while (block.isValid() && block.userState() != -1) {
+ BaseTextDocumentLayout::changeBraceDepth(block, delta);
+ BaseTextDocumentLayout::changeFoldingIndent(block, delta);
+ block = block.next();
+ }
+ }
+ }
+
+ setCurrentBlockState((braceDepth << 8) | lex.state());
+}
+
+void Highlighter::highlightLine(const QString &text, int position, int length,
+ const QTextCharFormat &format)
+{
+ const QTextCharFormat visualSpaceFormat = m_formats[GLSLVisualWhitespace];
+
+ const int end = position + length;
+ int index = position;
+
+ while (index != end) {
+ const bool isSpace = text.at(index).isSpace();
+ const int start = index;
+
+ do { ++index; }
+ while (index != end && text.at(index).isSpace() == isSpace);
+
+ const int tokenLength = index - start;
+ if (isSpace)
+ setFormat(start, tokenLength, visualSpaceFormat);
+ else if (format.isValid())
+ setFormat(start, tokenLength, format);
+ }
+}
+
+bool Highlighter::isPPKeyword(const QStringRef &text) const
+{
+ switch (text.length())
+ {
+ case 2:
+ if (text.at(0) == 'i' && text.at(1) == 'f')
+ return true;
+ break;
+
+ case 4:
+ if (text.at(0) == 'e' && text == QLatin1String("elif"))
+ return true;
+ else if (text.at(0) == 'e' && text == QLatin1String("else"))
+ return true;
+ break;
+
+ case 5:
+ if (text.at(0) == 'i' && text == QLatin1String("ifdef"))
+ return true;
+ else if (text.at(0) == 'u' && text == QLatin1String("undef"))
+ return true;
+ else if (text.at(0) == 'e' && text == QLatin1String("endif"))
+ return true;
+ else if (text.at(0) == 'e' && text == QLatin1String("error"))
+ return true;
+ break;
+
+ case 6:
+ if (text.at(0) == 'i' && text == QLatin1String("ifndef"))
+ return true;
+ if (text.at(0) == 'i' && text == QLatin1String("import"))
+ return true;
+ else if (text.at(0) == 'd' && text == QLatin1String("define"))
+ return true;
+ else if (text.at(0) == 'p' && text == QLatin1String("pragma"))
+ return true;
+ break;
+
+ case 7:
+ if (text.at(0) == 'i' && text == QLatin1String("include"))
+ return true;
+ else if (text.at(0) == 'w' && text == QLatin1String("warning"))
+ return true;
+ break;
+
+ case 12:
+ if (text.at(0) == 'i' && text == QLatin1String("include_next"))
+ return true;
+ break;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+#if 0
+void Highlighter::highlightBlock(const QString &text)
+{
+ const int previousState = previousBlockState();
+ int state = 0, initialBraceDepth = 0;
+ if (previousState != -1) {
+ state = previousState & 0xff;
+ initialBraceDepth = previousState >> 8;
+ }
+
+ int braceDepth = initialBraceDepth;
+
+ Parentheses parentheses;
+ parentheses.reserve(20); // assume wizard level ;-)
+
+ const QByteArray data = text.toLatin1();
+ GLSL::Lexer lex(/*engine=*/ 0, data.constData(), data.size());
+ lex.setState(qMax(0, previousState));
+ lex.setScanKeywords(false);
+ lex.setScanComments(true);
+ const int variant = m_editor->languageVariant();
+ lex.setVariant(variant);
+
+ int foldingIndent = initialBraceDepth;
+ if (TextBlockUserData *userData = BaseTextDocumentLayout::testUserData(currentBlock())) {
+ userData->setFoldingIndent(0);
+ userData->setFoldingStartIncluded(false);
+ userData->setFoldingEndIncluded(false);
+ }
+
+ QList<GLSL::Token> tokens;
+ GLSL::Token tk;
+ do {
+ lex.yylex(&tk);
+ tokens.append(tk);
+ } while (tk.isNot(GLSL::Parser::EOF_SYMBOL));
+
+ for (int i = 0; i < tokens.size(); ++i) {
+ const GLSL::Token &tk = tokens.at(i);
+
+ if (tk.is(GLSL::Parser::T_NUMBER))
+ setFormat(tk.position, tk.length, m_formats[GLSLNumberFormat]);
+ else if (tk.is(GLSL::Parser::T_COMMENT))
+ setFormat(tk.position, tk.length, Qt::darkGreen); // ### FIXME: m_formats[GLSLCommentFormat]);
+ else if (tk.is(GLSL::Parser::T_IDENTIFIER)) {
+ int kind = lex.findKeyword(data.constData() + tk.position, tk.length);
+ if (kind == GLSL::Parser::T_RESERVED)
+ setFormat(tk.position, tk.length, m_formats[GLSLReservedKeyword]);
+ else if (kind != GLSL::Parser::T_IDENTIFIER)
+ setFormat(tk.position, tk.length, m_formats[GLSLKeywordFormat]);
+ } else if (tk.is(GLSL::Parser::T_LEFT_PAREN) || tk.is(GLSL::Parser::T_LEFT_BRACE) || tk.is(GLSL::Parser::T_LEFT_BRACKET)) {
+ const QChar c = text.at(tk.begin());
+ parentheses.append(Parenthesis(Parenthesis::Opened, c, tk.begin()));
+ if (tk.is(GLSL::Parser::T_LEFT_BRACE)) {
+ ++braceDepth;
+
+ // if a folding block opens at the beginning of a line, treat the entire line
+ // as if it were inside the folding block
+// if (tk.begin() == firstNonSpace) {
+// ++foldingIndent;
+// BaseTextDocumentLayout::userData(currentBlock())->setFoldingStartIncluded(true);
+// }
+ }
+ } else if (tk.is(GLSL::Parser::T_RIGHT_PAREN) || tk.is(GLSL::Parser::T_RIGHT_BRACE) || tk.is(GLSL::Parser::T_RIGHT_BRACKET)) {
+ const QChar c = text.at(tk.begin());
+ parentheses.append(Parenthesis(Parenthesis::Closed, c, tk.begin()));
+ if (tk.is(GLSL::Parser::T_RIGHT_BRACE)) {
+ --braceDepth;
+ if (braceDepth < foldingIndent) {
+ // unless we are at the end of the block, we reduce the folding indent
+ if (i == tokens.size()-1 || tokens.at(i+1).is(GLSL::Parser::T_SEMICOLON))
+ BaseTextDocumentLayout::userData(currentBlock())->setFoldingEndIncluded(true);
+ else
+ foldingIndent = qMin(braceDepth, foldingIndent);
+ }
+ }
+ }
+
+ } while (tk.isNot(GLSL::Parser::EOF_SYMBOL));
+ setCurrentBlockState((braceDepth << 8) | lex.state());
+}
+#endif
diff --git a/src/plugins/glsleditor/glslhighlighter.h b/src/plugins/glsleditor/glslhighlighter.h
new file mode 100644
index 0000000000..71d43b9d35
--- /dev/null
+++ b/src/plugins/glsleditor/glslhighlighter.h
@@ -0,0 +1,82 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** No Commercial Usage
+**
+** This file 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.
+**
+**************************************************************************/
+#ifndef GLSLHIGHLIGHTER_H
+#define GLSLHIGHLIGHTER_H
+
+#include <texteditor/syntaxhighlighter.h>
+
+namespace GLSLEditor {
+class GLSLTextEditor;
+
+namespace Internal {
+
+class Highlighter : public TextEditor::SyntaxHighlighter
+{
+ Q_OBJECT
+
+public:
+ enum Formats {
+ GLSLNumberFormat,
+ GLSLStringFormat,
+ GLSLTypeFormat,
+ GLSLKeywordFormat,
+ GLSLOperatorFormat,
+ GLSLPreprocessorFormat,
+ GLSLLabelFormat,
+ GLSLCommentFormat,
+ GLSLDoxygenCommentFormat,
+ GLSLDoxygenTagFormat,
+ GLSLVisualWhitespace,
+ GLSLReservedKeyword,
+ NumGLSLFormats
+ };
+
+ explicit Highlighter(GLSLTextEditor *editor, QTextDocument *parent);
+ virtual ~Highlighter();
+
+ void setFormats(const QVector<QTextCharFormat> &formats);
+
+protected:
+ void highlightBlock(const QString &text);
+ void highlightLine(const QString &text, int position, int length, const QTextCharFormat &format);
+ bool isPPKeyword(const QStringRef &text) const;
+
+private:
+ QTextCharFormat m_formats[NumGLSLFormats];
+ GLSLTextEditor *m_editor;
+};
+
+} // namespace Internal
+} // namespace GLSLEditor
+
+#endif // GLSLHIGHLIGHTER_H
diff --git a/src/plugins/glsleditor/glslhoverhandler.cpp b/src/plugins/glsleditor/glslhoverhandler.cpp
new file mode 100644
index 0000000000..90a91db243
--- /dev/null
+++ b/src/plugins/glsleditor/glslhoverhandler.cpp
@@ -0,0 +1,77 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** No Commercial Usage
+**
+** This file 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.
+**
+**************************************************************************/
+
+#include "glslhoverhandler.h"
+#include "glsleditor.h"
+
+#include <coreplugin/editormanager/ieditor.h>
+#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/helpmanager.h>
+#include <extensionsystem/pluginmanager.h>
+#include <texteditor/itexteditor.h>
+#include <texteditor/basetexteditor.h>
+
+#include <QtGui/QTextCursor>
+#include <QtCore/QUrl>
+
+using namespace GLSLEditor;
+using namespace GLSLEditor::Internal;
+using namespace Core;
+
+GLSLHoverHandler::GLSLHoverHandler(QObject *parent) : BaseHoverHandler(parent)
+{}
+
+GLSLHoverHandler::~GLSLHoverHandler()
+{}
+
+bool GLSLHoverHandler::acceptEditor(IEditor *editor)
+{
+ if (qobject_cast<GLSLEditorEditable *>(editor) != 0)
+ return true;
+ return false;
+}
+
+void GLSLHoverHandler::identifyMatch(TextEditor::ITextEditor *editor, int pos)
+{
+ if (GLSLTextEditor *glslEditor = qobject_cast<GLSLTextEditor *>(editor->widget())) {
+ if (! glslEditor->extraSelectionTooltip(pos).isEmpty()) {
+ setToolTip(glslEditor->extraSelectionTooltip(pos));
+ }
+ }
+}
+
+void GLSLHoverHandler::decorateToolTip()
+{
+ if (Qt::mightBeRichText(toolTip()))
+ setToolTip(Qt::escape(toolTip()));
+}
diff --git a/src/plugins/glsleditor/glslhoverhandler.h b/src/plugins/glsleditor/glslhoverhandler.h
new file mode 100644
index 0000000000..08e3ed7271
--- /dev/null
+++ b/src/plugins/glsleditor/glslhoverhandler.h
@@ -0,0 +1,64 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 GLSLHOVERHANDLER_H
+#define GLSLHOVERHANDLER_H
+
+#include <texteditor/basehoverhandler.h>
+
+#include <QtCore/QObject>
+
+namespace Core {
+class IEditor;
+}
+
+namespace TextEditor {
+class ITextEditor;
+}
+
+namespace GLSLEditor {
+namespace Internal {
+
+class GLSLHoverHandler : public TextEditor::BaseHoverHandler
+{
+ Q_OBJECT
+public:
+ GLSLHoverHandler(QObject *parent = 0);
+ virtual ~GLSLHoverHandler();
+
+private:
+ virtual bool acceptEditor(Core::IEditor *editor);
+ virtual void identifyMatch(TextEditor::ITextEditor *editor, int pos);
+ virtual void decorateToolTip();
+};
+
+} // namespace Internal
+} // namespace GLSLEditor
+
+#endif // GLSLHOVERHANDLER_H
diff --git a/src/plugins/glsleditor/glslindenter.cpp b/src/plugins/glsleditor/glslindenter.cpp
new file mode 100644
index 0000000000..86a216164e
--- /dev/null
+++ b/src/plugins/glsleditor/glslindenter.cpp
@@ -0,0 +1,116 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "glslindenter.h"
+
+#include <cpptools/cppcodeformatter.h>
+#include <texteditor/basetexteditor.h>
+#include <texteditor/tabsettings.h>
+
+#include <QtCore/QChar>
+#include <QtGui/QTextDocument>
+#include <QtGui/QTextBlock>
+#include <QtGui/QTextCursor>
+
+using namespace GLSLEditor;
+using namespace Internal;
+
+GLSLIndenter::GLSLIndenter()
+{}
+
+GLSLIndenter::~GLSLIndenter()
+{}
+
+bool GLSLIndenter::isElectricCharacter(const QChar &ch) const
+{
+ if (ch == QLatin1Char('{') ||
+ ch == QLatin1Char('}') ||
+ ch == QLatin1Char(':') ||
+ ch == QLatin1Char('#')) {
+ return true;
+ }
+ return false;
+}
+
+void GLSLIndenter::indentBlock(QTextDocument *doc,
+ const QTextBlock &block,
+ const QChar &typedChar,
+ TextEditor::BaseTextEditor *editor)
+{
+ Q_UNUSED(doc)
+
+ const TextEditor::TabSettings &ts = editor->tabSettings();
+ CppTools::QtStyleCodeFormatter codeFormatter(ts);
+
+ codeFormatter.updateStateUntil(block);
+ int indent;
+ int padding;
+ codeFormatter.indentFor(block, &indent, &padding);
+
+ // only reindent the current line when typing electric characters if the
+ // indent is the same it would be if the line were empty
+ if (isElectricCharacter(typedChar)) {
+ int newlineIndent;
+ int newlinePadding;
+ codeFormatter.indentForNewLineAfter(block.previous(), &newlineIndent, &newlinePadding);
+ if (ts.indentationColumn(block.text()) != newlineIndent + newlinePadding)
+ return;
+ }
+
+ ts.indentLine(block, indent + padding, padding);
+}
+
+void GLSLIndenter::indent(QTextDocument *doc,
+ const QTextCursor &cursor,
+ const QChar &typedChar,
+ TextEditor::BaseTextEditor *editor)
+{
+ if (cursor.hasSelection()) {
+ QTextBlock block = doc->findBlock(cursor.selectionStart());
+ const QTextBlock end = doc->findBlock(cursor.selectionEnd()).next();
+
+ const TextEditor::TabSettings &ts = editor->tabSettings();
+ CppTools::QtStyleCodeFormatter codeFormatter(ts);
+ codeFormatter.updateStateUntil(block);
+
+ QTextCursor tc = editor->textCursor();
+ tc.beginEditBlock();
+ do {
+ int indent;
+ int padding;
+ codeFormatter.indentFor(block, &indent, &padding);
+ ts.indentLine(block, indent + padding, padding);
+ codeFormatter.updateLineStateChange(block);
+ block = block.next();
+ } while (block.isValid() && block != end);
+ tc.endEditBlock();
+ } else {
+ indentBlock(doc, cursor.block(), typedChar, editor);
+ }
+}
diff --git a/src/plugins/glsleditor/glslindenter.h b/src/plugins/glsleditor/glslindenter.h
new file mode 100644
index 0000000000..85ac0c7f8f
--- /dev/null
+++ b/src/plugins/glsleditor/glslindenter.h
@@ -0,0 +1,63 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** No Commercial Usage
+**
+** This file 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.
+**
+**************************************************************************/
+
+#ifndef GLSLINDENTER_H
+#define GLSLINDENTER_H
+
+#include <texteditor/indenter.h>
+
+namespace GLSLEditor {
+namespace Internal {
+
+class GLSLIndenter : public TextEditor::Indenter
+{
+public:
+ GLSLIndenter();
+ virtual ~GLSLIndenter();
+
+ virtual bool isElectricCharacter(const QChar &ch) const;
+ virtual void indentBlock(QTextDocument *doc,
+ const QTextBlock &block,
+ const QChar &typedChar,
+ TextEditor::BaseTextEditor *editor);
+
+ virtual void indent(QTextDocument *doc,
+ const QTextCursor &cursor,
+ const QChar &typedChar,
+ TextEditor::BaseTextEditor *editor);
+};
+
+} // Internal
+} // GLSLEditor
+
+#endif // GLSLINDENTER_H
diff --git a/src/plugins/glsleditor/images/attribute.png b/src/plugins/glsleditor/images/attribute.png
new file mode 100644
index 0000000000..94f20ac42a
--- /dev/null
+++ b/src/plugins/glsleditor/images/attribute.png
Binary files differ
diff --git a/src/plugins/glsleditor/images/const.png b/src/plugins/glsleditor/images/const.png
new file mode 100644
index 0000000000..25fc49c659
--- /dev/null
+++ b/src/plugins/glsleditor/images/const.png
Binary files differ
diff --git a/src/plugins/glsleditor/images/func.png b/src/plugins/glsleditor/images/func.png
new file mode 100644
index 0000000000..e515e76e61
--- /dev/null
+++ b/src/plugins/glsleditor/images/func.png
Binary files differ
diff --git a/src/plugins/glsleditor/images/glslfile.png b/src/plugins/glsleditor/images/glslfile.png
new file mode 100644
index 0000000000..83c2606009
--- /dev/null
+++ b/src/plugins/glsleditor/images/glslfile.png
Binary files differ
diff --git a/src/plugins/glsleditor/images/keyword.png b/src/plugins/glsleditor/images/keyword.png
new file mode 100644
index 0000000000..e5a51858d9
--- /dev/null
+++ b/src/plugins/glsleditor/images/keyword.png
Binary files differ
diff --git a/src/plugins/glsleditor/images/other.png b/src/plugins/glsleditor/images/other.png
new file mode 100644
index 0000000000..18d2941572
--- /dev/null
+++ b/src/plugins/glsleditor/images/other.png
Binary files differ
diff --git a/src/plugins/glsleditor/images/type.png b/src/plugins/glsleditor/images/type.png
new file mode 100644
index 0000000000..88432d2cb1
--- /dev/null
+++ b/src/plugins/glsleditor/images/type.png
Binary files differ
diff --git a/src/plugins/glsleditor/images/uniform.png b/src/plugins/glsleditor/images/uniform.png
new file mode 100644
index 0000000000..c6452fc8c6
--- /dev/null
+++ b/src/plugins/glsleditor/images/uniform.png
Binary files differ
diff --git a/src/plugins/glsleditor/images/var.png b/src/plugins/glsleditor/images/var.png
new file mode 100644
index 0000000000..089cfb45e5
--- /dev/null
+++ b/src/plugins/glsleditor/images/var.png
Binary files differ
diff --git a/src/plugins/glsleditor/images/varying.png b/src/plugins/glsleditor/images/varying.png
new file mode 100644
index 0000000000..c2551c0025
--- /dev/null
+++ b/src/plugins/glsleditor/images/varying.png
Binary files differ
diff --git a/src/plugins/helloworld/HelloWorld.pluginspec b/src/plugins/helloworld/HelloWorld.pluginspec
deleted file mode 100644
index 03f52311c4..0000000000
--- a/src/plugins/helloworld/HelloWorld.pluginspec
+++ /dev/null
@@ -1,18 +0,0 @@
-<plugin name="HelloWorld" version="2.0.95" compatVersion="2.0.95" experimental="true">
- <vendor>Nokia Corporation</vendor>
- <copyright>(C) 2010 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>Hello World sample plugin.</description>
- <url>http://qt.nokia.com</url>
- <dependencyList>
- <dependency name="Core" version="2.0.95"/>
- </dependencyList>
-</plugin>
diff --git a/src/plugins/helloworld/HelloWorld.pluginspec.in b/src/plugins/helloworld/HelloWorld.pluginspec.in
new file mode 100644
index 0000000000..0bdabd0118
--- /dev/null
+++ b/src/plugins/helloworld/HelloWorld.pluginspec.in
@@ -0,0 +1,18 @@
+<plugin name=\"HelloWorld\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\" experimental=\"true\">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2010 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>Hello World sample plugin.</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/helloworld/helloworld.pro b/src/plugins/helloworld/helloworld.pro
index aae1323868..9ef9b48f33 100644
--- a/src/plugins/helloworld/helloworld.pro
+++ b/src/plugins/helloworld/helloworld.pro
@@ -9,5 +9,3 @@ HEADERS += helloworldplugin.h \
SOURCES += helloworldplugin.cpp \
helloworldwindow.cpp
-
-OTHER_FILES += helloworld.pluginspec
diff --git a/src/plugins/helloworld/helloworldplugin.cpp b/src/plugins/helloworld/helloworldplugin.cpp
index d7e7f31e0c..d36452d713 100644
--- a/src/plugins/helloworld/helloworldplugin.cpp
+++ b/src/plugins/helloworld/helloworldplugin.cpp
@@ -35,9 +35,9 @@
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
-#include <coreplugin/basemode.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/icore.h>
+#include <coreplugin/imode.h>
#include <coreplugin/modemanager.h>
#include <coreplugin/uniqueidmanager.h>
@@ -48,7 +48,29 @@
#include <QtGui/QMessageBox>
#include <QtGui/QPushButton>
-using namespace HelloWorld::Internal;
+namespace HelloWorld {
+namespace Internal {
+
+/*! A mode with a push button based on BaseMode. */
+
+class HelloMode : public Core::IMode
+{
+public:
+ HelloMode() : m_widget(new QPushButton(tr("Hello World PushButton!"))) {}
+
+ QString displayName() const { return tr("Hello world!"); }
+ QIcon icon() const { return QIcon(); }
+ int priority() const { return 0; }
+ QWidget *widget() { return m_widget; }
+ QString id() const { return QLatin1String("HelloWorld.HelloWorldMode"); }
+ QString type() const { return QLatin1String("HelloWorld.HelloWorldMode"); }
+ Core::Context context() const { return Core::Context("HelloWorld.MainView"); };
+ QString contextHelpId() const { return QString(); }
+
+private:
+ QWidget *m_widget;
+};
+
/*! Constructs the Hello World plugin. Normally plugins don't do anything in
their constructor except for initializing their member variables. The
@@ -80,7 +102,7 @@ bool HelloWorldPlugin::initialize(const QStringList &arguments, QString *error_m
// Get the primary access point to the workbench.
Core::ICore *core = Core::ICore::instance();
- // Create a unique context id for our own view, that will be used for the
+ // Create a unique context for our own view, that will be used for the
// menu entry later.
Core::Context context("HelloWorld.MainView");
@@ -111,15 +133,8 @@ bool HelloWorldPlugin::initialize(const QStringList &arguments, QString *error_m
// Add a mode with a push button based on BaseMode. Like the BaseView,
// it will unregister itself from the plugin manager when it is deleted.
- Core::BaseMode *baseMode = new Core::BaseMode;
- baseMode->setId(QLatin1String("HelloWorld.HelloWorldMode"));
- baseMode->setType(QLatin1String("HelloWorld.HelloWorldMode"));
- baseMode->setDisplayName(tr("Hello world!"));
- baseMode->setIcon(QIcon());
- baseMode->setPriority(0);
- baseMode->setWidget(new QPushButton(tr("Hello World PushButton!")));
- baseMode->setContext(context);
- addAutoReleasedObject(baseMode);
+ Core::IMode *helloMode = new HelloMode;
+ addAutoReleasedObject(helloMode);
// Add the Hello World action command to the mode manager (with 0 priority)
Core::ModeManager *modeManager = core->modeManager();
@@ -151,4 +166,7 @@ void HelloWorldPlugin::sayHelloWorld()
0, tr("Hello World!"), tr("Hello World! Beautiful day today, isn't it?"));
}
-Q_EXPORT_PLUGIN(HelloWorldPlugin)
+} // namespace Internal
+} // namespace HelloWorld
+
+Q_EXPORT_PLUGIN(HelloWorld::Internal::HelloWorldPlugin)
diff --git a/src/plugins/helloworld/helloworldplugin.h b/src/plugins/helloworld/helloworldplugin.h
index 2ed5b7daa6..3bbeb03fc9 100644
--- a/src/plugins/helloworld/helloworldplugin.h
+++ b/src/plugins/helloworld/helloworldplugin.h
@@ -54,8 +54,6 @@ public:
private slots:
void sayHelloWorld();
-
-private:
};
} // namespace Internal
diff --git a/src/plugins/helloworld/helloworldwindow.h b/src/plugins/helloworld/helloworldwindow.h
index 11b7f99811..0357cbb660 100644
--- a/src/plugins/helloworld/helloworldwindow.h
+++ b/src/plugins/helloworld/helloworldwindow.h
@@ -36,7 +36,7 @@
#include <QtGui/QWidget>
-QT_FORWARD_DECLARE_CLASS(QLabel);
+QT_FORWARD_DECLARE_CLASS(QLabel)
namespace HelloWorld {
namespace Internal {
diff --git a/src/plugins/help/Help.pluginspec b/src/plugins/help/Help.pluginspec
deleted file mode 100644
index 0056c12689..0000000000
--- a/src/plugins/help/Help.pluginspec
+++ /dev/null
@@ -1,21 +0,0 @@
-<plugin name="Help" version="2.0.95" compatVersion="2.0.95">
- <vendor>Nokia Corporation</vendor>
- <copyright>(C) 2010 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>
- <category>Qt Creator</category>
- <description>Help system.</description>
- <url>http://qt.nokia.com</url>
- <dependencyList>
- <dependency name="Core" version="2.0.95"/>
- <dependency name="Find" version="2.0.95"/>
- <dependency name="Locator" version="2.0.95"/>
- </dependencyList>
-</plugin>
diff --git a/src/plugins/help/Help.pluginspec.in b/src/plugins/help/Help.pluginspec.in
new file mode 100644
index 0000000000..cbaaea2f52
--- /dev/null
+++ b/src/plugins/help/Help.pluginspec.in
@@ -0,0 +1,21 @@
+<plugin name=\"Help\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2010 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>
+ <category>Qt Creator</category>
+ <description>Help system.</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"Find\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"Locator\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/help/centralwidget.cpp b/src/plugins/help/centralwidget.cpp
index db9c01dd1f..76078350aa 100644
--- a/src/plugins/help/centralwidget.cpp
+++ b/src/plugins/help/centralwidget.cpp
@@ -33,8 +33,8 @@
#include "centralwidget.h"
-#include "helpmanager.h"
#include "helpviewer.h"
+#include "localhelpmanager.h"
#include "topicchooser.h"
#include <QtCore/QEvent>
diff --git a/src/plugins/help/generalsettingspage.cpp b/src/plugins/help/generalsettingspage.cpp
index 720997cad9..108f665055 100644
--- a/src/plugins/help/generalsettingspage.cpp
+++ b/src/plugins/help/generalsettingspage.cpp
@@ -36,8 +36,8 @@
#include "bookmarkmanager.h"
#include "centralwidget.h"
#include "helpconstants.h"
-#include "helpmanager.h"
#include "helpviewer.h"
+#include "localhelpmanager.h"
#include "xbelsupport.h"
#include <coreplugin/coreconstants.h>
@@ -58,6 +58,7 @@
using namespace Help::Internal;
GeneralSettingsPage::GeneralSettingsPage()
+ : m_ui(0)
{
m_font = qApp->font();
#if !defined(QT_NO_WEBKIT)
@@ -94,10 +95,10 @@ QIcon GeneralSettingsPage::categoryIcon() const
QWidget *GeneralSettingsPage::createPage(QWidget *parent)
{
QWidget *widget = new QWidget(parent);
-
- m_ui.setupUi(widget);
- m_ui.sizeComboBox->setEditable(false);
- m_ui.styleComboBox->setEditable(false);
+ m_ui = new Ui::GeneralSettingsPage;
+ m_ui->setupUi(widget);
+ m_ui->sizeComboBox->setEditable(false);
+ m_ui->styleComboBox->setEditable(false);
Core::HelpManager *manager = Core::HelpManager::instance();
m_font = qVariantValue<QFont>(manager->customValue(QLatin1String("font"),
@@ -113,58 +114,60 @@ QWidget *GeneralSettingsPage::createPage(QWidget *parent)
m_homePage = manager->customValue(QLatin1String("DefaultHomePage"),
Help::Constants::AboutBlank).toString();
}
- m_ui.homePageLineEdit->setText(m_homePage);
+ m_ui->homePageLineEdit->setText(m_homePage);
const int startOption = manager->customValue(QLatin1String("StartOption"),
Help::Constants::ShowLastPages).toInt();
- m_ui.helpStartComboBox->setCurrentIndex(startOption);
+ m_ui->helpStartComboBox->setCurrentIndex(startOption);
m_contextOption = manager->customValue(QLatin1String("ContextHelpOption"),
Help::Constants::SideBySideIfPossible).toInt();
- m_ui.contextHelpComboBox->setCurrentIndex(m_contextOption);
+ m_ui->contextHelpComboBox->setCurrentIndex(m_contextOption);
- connect(m_ui.currentPageButton, SIGNAL(clicked()), this, SLOT(setCurrentPage()));
- connect(m_ui.blankPageButton, SIGNAL(clicked()), this, SLOT(setBlankPage()));
- connect(m_ui.defaultPageButton, SIGNAL(clicked()), this, SLOT(setDefaultPage()));
+ connect(m_ui->currentPageButton, SIGNAL(clicked()), this, SLOT(setCurrentPage()));
+ connect(m_ui->blankPageButton, SIGNAL(clicked()), this, SLOT(setBlankPage()));
+ connect(m_ui->defaultPageButton, SIGNAL(clicked()), this, SLOT(setDefaultPage()));
HelpViewer *viewer = CentralWidget::instance()->currentHelpViewer();
if (!viewer)
- m_ui.currentPageButton->setEnabled(false);
+ m_ui->currentPageButton->setEnabled(false);
- m_ui.errorLabel->setVisible(false);
- connect(m_ui.importButton, SIGNAL(clicked()), this, SLOT(importBookmarks()));
- connect(m_ui.exportButton, SIGNAL(clicked()), this, SLOT(exportBookmarks()));
+ m_ui->errorLabel->setVisible(false);
+ connect(m_ui->importButton, SIGNAL(clicked()), this, SLOT(importBookmarks()));
+ connect(m_ui->exportButton, SIGNAL(clicked()), this, SLOT(exportBookmarks()));
if (m_searchKeywords.isEmpty()) {
- QTextStream(&m_searchKeywords) << ' ' << m_ui.contextHelpLabel->text()
- << ' ' << m_ui.startPageLabel->text() << ' ' << m_ui.homePageLabel->text()
- << ' ' << m_ui.bookmarkGroupBox->title();
+ QTextStream(&m_searchKeywords) << ' ' << m_ui->contextHelpLabel->text()
+ << ' ' << m_ui->startPageLabel->text() << ' ' << m_ui->homePageLabel->text()
+ << ' ' << m_ui->bookmarkGroupBox->title();
m_searchKeywords.remove(QLatin1Char('&'));
}
m_returnOnClose = manager->customValue(QLatin1String("ReturnOnClose"),
false).toBool();
- m_ui.m_returnOnClose->setChecked(m_returnOnClose);
+ m_ui->m_returnOnClose->setChecked(m_returnOnClose);
return widget;
}
void GeneralSettingsPage::apply()
{
+ if (!m_ui) // page was never shown
+ return;
QFont newFont;
- const QString &family = m_ui.familyComboBox->currentFont().family();
+ const QString &family = m_ui->familyComboBox->currentFont().family();
newFont.setFamily(family);
int fontSize = 14;
- int currentIndex = m_ui.sizeComboBox->currentIndex();
+ int currentIndex = m_ui->sizeComboBox->currentIndex();
if (currentIndex != -1)
- fontSize = m_ui.sizeComboBox->itemData(currentIndex).toInt();
+ fontSize = m_ui->sizeComboBox->itemData(currentIndex).toInt();
newFont.setPointSize(fontSize);
QString fontStyle = QLatin1String("Normal");
- currentIndex = m_ui.styleComboBox->currentIndex();
+ currentIndex = m_ui->styleComboBox->currentIndex();
if (currentIndex != -1)
- fontStyle = m_ui.styleComboBox->itemText(currentIndex);
+ fontStyle = m_ui->styleComboBox->itemText(currentIndex);
newFont.setBold(m_fontDatabase.bold(family, fontStyle));
if (fontStyle.contains(QLatin1String("Italic")))
newFont.setStyle(QFont::StyleItalic);
@@ -184,15 +187,15 @@ void GeneralSettingsPage::apply()
emit fontChanged();
}
- QString homePage = m_ui.homePageLineEdit->text();
+ QString homePage = m_ui->homePageLineEdit->text();
if (homePage.isEmpty())
homePage = Help::Constants::AboutBlank;
manager->setCustomValue(QLatin1String("HomePage"), homePage);
- const int startOption = m_ui.helpStartComboBox->currentIndex();
+ const int startOption = m_ui->helpStartComboBox->currentIndex();
manager->setCustomValue(QLatin1String("StartOption"), startOption);
- const int helpOption = m_ui.contextHelpComboBox->currentIndex();
+ const int helpOption = m_ui->contextHelpComboBox->currentIndex();
if (m_contextOption != helpOption) {
m_contextOption = helpOption;
manager->setCustomValue(QLatin1String("ContextHelpOption"), helpOption);
@@ -205,7 +208,7 @@ void GeneralSettingsPage::apply()
emit contextHelpOptionChanged();
}
- const bool close = m_ui.m_returnOnClose->isChecked();
+ const bool close = m_ui->m_returnOnClose->isChecked();
if (m_returnOnClose != close) {
m_returnOnClose = close;
manager->setCustomValue(QLatin1String("ReturnOnClose"), close);
@@ -217,24 +220,24 @@ void GeneralSettingsPage::setCurrentPage()
{
HelpViewer *viewer = CentralWidget::instance()->currentHelpViewer();
if (viewer)
- m_ui.homePageLineEdit->setText(viewer->source().toString());
+ m_ui->homePageLineEdit->setText(viewer->source().toString());
}
void GeneralSettingsPage::setBlankPage()
{
- m_ui.homePageLineEdit->setText(Help::Constants::AboutBlank);
+ m_ui->homePageLineEdit->setText(Help::Constants::AboutBlank);
}
void GeneralSettingsPage::setDefaultPage()
{
const QString &defaultHomePage = Core::HelpManager::instance()
->customValue(QLatin1String("DefaultHomePage"), QString()).toString();
- m_ui.homePageLineEdit->setText(defaultHomePage);
+ m_ui->homePageLineEdit->setText(defaultHomePage);
}
void GeneralSettingsPage::importBookmarks()
{
- m_ui.errorLabel->setVisible(false);
+ m_ui->errorLabel->setVisible(false);
QString fileName = QFileDialog::getOpenFileName(0, tr("Import Bookmarks"),
QDir::currentPath(), tr("Files (*.xbel)"));
@@ -250,13 +253,13 @@ void GeneralSettingsPage::importBookmarks()
return;
}
- m_ui.errorLabel->setVisible(true);
- m_ui.errorLabel->setText(tr("There was an error while importing bookmarks!"));
+ m_ui->errorLabel->setVisible(true);
+ m_ui->errorLabel->setText(tr("There was an error while importing bookmarks!"));
}
void GeneralSettingsPage::exportBookmarks()
{
- m_ui.errorLabel->setVisible(false);
+ m_ui->errorLabel->setVisible(false);
QString fileName = QFileDialog::getSaveFileName(0, tr("Save File"),
"untitled.xbel", tr("Files (*.xbel)"));
@@ -281,18 +284,18 @@ void GeneralSettingsPage::updateFontSize()
if (pointSizes.empty())
pointSizes = QFontDatabase::standardSizes();
- m_ui.sizeComboBox->clear();
- m_ui.sizeComboBox->setCurrentIndex(-1);
- m_ui.sizeComboBox->setEnabled(!pointSizes.empty());
+ m_ui->sizeComboBox->clear();
+ m_ui->sizeComboBox->setCurrentIndex(-1);
+ m_ui->sizeComboBox->setEnabled(!pointSizes.empty());
// try to maintain selection or select closest.
if (!pointSizes.empty()) {
QString n;
foreach (int pointSize, pointSizes)
- m_ui.sizeComboBox->addItem(n.setNum(pointSize), QVariant(pointSize));
+ m_ui->sizeComboBox->addItem(n.setNum(pointSize), QVariant(pointSize));
const int closestIndex = closestPointSizeIndex(m_font.pointSize());
if (closestIndex != -1)
- m_ui.sizeComboBox->setCurrentIndex(closestIndex);
+ m_ui->sizeComboBox->setCurrentIndex(closestIndex);
}
}
@@ -301,32 +304,32 @@ void GeneralSettingsPage::updateFontStyle()
const QString &fontStyle = m_fontDatabase.styleString(m_font);
const QStringList &styles = m_fontDatabase.styles(m_font.family());
- m_ui.styleComboBox->clear();
- m_ui.styleComboBox->setCurrentIndex(-1);
- m_ui.styleComboBox->setEnabled(!styles.empty());
+ m_ui->styleComboBox->clear();
+ m_ui->styleComboBox->setCurrentIndex(-1);
+ m_ui->styleComboBox->setEnabled(!styles.empty());
if (!styles.empty()) {
int normalIndex = -1;
const QString normalStyle = QLatin1String("Normal");
foreach (const QString &style, styles) {
// try to maintain selection or select 'normal' preferably
- const int newIndex = m_ui.styleComboBox->count();
- m_ui.styleComboBox->addItem(style);
+ const int newIndex = m_ui->styleComboBox->count();
+ m_ui->styleComboBox->addItem(style);
if (fontStyle == style) {
- m_ui.styleComboBox->setCurrentIndex(newIndex);
+ m_ui->styleComboBox->setCurrentIndex(newIndex);
} else {
if (fontStyle == normalStyle)
normalIndex = newIndex;
}
}
- if (m_ui.styleComboBox->currentIndex() == -1 && normalIndex != -1)
- m_ui.styleComboBox->setCurrentIndex(normalIndex);
+ if (m_ui->styleComboBox->currentIndex() == -1 && normalIndex != -1)
+ m_ui->styleComboBox->setCurrentIndex(normalIndex);
}
}
void GeneralSettingsPage::updateFontFamily()
{
- m_ui.familyComboBox->setCurrentFont(m_font);
+ m_ui->familyComboBox->setCurrentFont(m_font);
}
int GeneralSettingsPage::closestPointSizeIndex(int desiredPointSize) const
@@ -335,9 +338,9 @@ int GeneralSettingsPage::closestPointSizeIndex(int desiredPointSize) const
int closestIndex = -1;
int closestAbsError = 0xFFFF;
- const int pointSizeCount = m_ui.sizeComboBox->count();
+ const int pointSizeCount = m_ui->sizeComboBox->count();
for (int i = 0; i < pointSizeCount; i++) {
- const int itemPointSize = m_ui.sizeComboBox->itemData(i).toInt();
+ const int itemPointSize = m_ui->sizeComboBox->itemData(i).toInt();
const int absError = qAbs(desiredPointSize - itemPointSize);
if (absError < closestAbsError) {
closestIndex = i;
@@ -357,3 +360,11 @@ bool GeneralSettingsPage::matches(const QString &s) const
{
return m_searchKeywords.contains(s, Qt::CaseInsensitive);
}
+
+void GeneralSettingsPage::finish()
+{
+ if (!m_ui) // page was never shown
+ return;
+ delete m_ui;
+ m_ui = 0;
+}
diff --git a/src/plugins/help/generalsettingspage.h b/src/plugins/help/generalsettingspage.h
index e8ac4031f0..9efa1f9573 100644
--- a/src/plugins/help/generalsettingspage.h
+++ b/src/plugins/help/generalsettingspage.h
@@ -57,7 +57,7 @@ public:
QWidget *createPage(QWidget *parent);
void apply();
- void finish() {}
+ void finish();
virtual bool matches(const QString &s) const;
signals:
@@ -89,7 +89,7 @@ private:
bool m_returnOnClose;
QString m_searchKeywords;
- Ui::GeneralSettingsPage m_ui;
+ Ui::GeneralSettingsPage *m_ui;
};
} // Internal
diff --git a/src/plugins/help/help.pro b/src/plugins/help/help.pro
index 451fc5d3d3..c5616d2df1 100644
--- a/src/plugins/help/help.pro
+++ b/src/plugins/help/help.pro
@@ -2,6 +2,8 @@ TEMPLATE = lib
TARGET = Help
QT += network
+INCLUDEPATH += $$PWD
+
include(../../qtcreatorplugin.pri)
include(help_dependencies.pri)
@@ -17,7 +19,7 @@ HEADERS += \
helpconstants.h \
helpfindsupport.h \
helpindexfilter.h \
- helpmanager.h \
+ localhelpmanager.h \
helpmode.h \
helpplugin.h \
helpviewer.h \
@@ -38,7 +40,7 @@ SOURCES += \
generalsettingspage.cpp \
helpfindsupport.cpp \
helpindexfilter.cpp \
- helpmanager.cpp \
+ localhelpmanager.cpp \
helpmode.cpp \
helpplugin.cpp \
helpviewer.cpp \
@@ -64,5 +66,3 @@ include(../../shared/help/help.pri)
contains(QT_CONFIG, webkit) {
QT += webkit
}
-
-OTHER_FILES += Help.pluginspec
diff --git a/src/plugins/help/helpconstants.h b/src/plugins/help/helpconstants.h
index b512bd5656..417562ac98 100644
--- a/src/plugins/help/helpconstants.h
+++ b/src/plugins/help/helpconstants.h
@@ -35,6 +35,7 @@
#define HELPCONSTANTS_H
#include <QtCore/QtGlobal>
+#include <QtCore/QLatin1String>
namespace Help {
namespace Constants {
diff --git a/src/plugins/help/helpindexfilter.cpp b/src/plugins/help/helpindexfilter.cpp
index d17f03efc8..a49da8f00f 100644
--- a/src/plugins/help/helpindexfilter.cpp
+++ b/src/plugins/help/helpindexfilter.cpp
@@ -46,7 +46,7 @@ using namespace Locator;
using namespace Help;
using namespace Help::Internal;
-Q_DECLARE_METATYPE(ILocatorFilter*);
+Q_DECLARE_METATYPE(ILocatorFilter*)
HelpIndexFilter::HelpIndexFilter()
{
diff --git a/src/plugins/help/helpmanager.cpp b/src/plugins/help/helpmanager.cpp
deleted file mode 100644
index f45430efa5..0000000000
--- a/src/plugins/help/helpmanager.cpp
+++ /dev/null
@@ -1,115 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#include "helpmanager.h"
-#include "bookmarkmanager.h"
-
-#include <coreplugin/coreconstants.h>
-#include <coreplugin/helpmanager.h>
-
-#include <QtCore/QMutexLocker>
-
-#include <QtHelp/QHelpEngine>
-
-using namespace Help::Internal;
-
-QMutex LocalHelpManager::m_guiMutex;
-QHelpEngine* LocalHelpManager::m_guiEngine = 0;
-
-QMutex LocalHelpManager::m_bkmarkMutex;
-BookmarkManager* LocalHelpManager::m_bookmarkManager = 0;
-
-LocalHelpManager::LocalHelpManager(QObject *parent)
- : QObject(parent)
- , m_guiNeedsSetup(true)
- , m_needsCollectionFile(true)
-{
-}
-
-LocalHelpManager::~LocalHelpManager()
-{
- if (m_bookmarkManager) {
- m_bookmarkManager->saveBookmarks();
- delete m_bookmarkManager;
- m_bookmarkManager = 0;
- }
-
- delete m_guiEngine;
- m_guiEngine = 0;
-}
-
-void LocalHelpManager::setupGuiHelpEngine()
-{
- if (m_needsCollectionFile) {
- m_needsCollectionFile = false;
- helpEngine().setCollectionFile(Core::HelpManager::collectionFilePath());
- }
-
- if (m_guiNeedsSetup) {
- m_guiNeedsSetup = false;
- helpEngine().setupData();
- }
-}
-
-void LocalHelpManager::setEngineNeedsUpdate()
-{
- m_guiNeedsSetup = true;
-}
-
-QHelpEngine &LocalHelpManager::helpEngine()
-{
- if (!m_guiEngine) {
- QMutexLocker _(&m_guiMutex);
- if (!m_guiEngine) {
- m_guiEngine = new QHelpEngine("");
- m_guiEngine->setAutoSaveFilter(false);
- }
- }
- return *m_guiEngine;
-}
-
-BookmarkManager& LocalHelpManager::bookmarkManager()
-{
- if (!m_bookmarkManager) {
- QMutexLocker _(&m_bkmarkMutex);
- if (!m_bookmarkManager) {
- m_bookmarkManager = new BookmarkManager;
- m_bookmarkManager->setupBookmarkModels();
- const QString &url = QString::fromLatin1("qthelp://com.nokia.qtcreator."
- "%1%2%3/doc/index.html").arg(IDE_VERSION_MAJOR).arg(IDE_VERSION_MINOR)
- .arg(IDE_VERSION_RELEASE);
- helpEngine().setCustomValue(QLatin1String("DefaultHomePage"), url);
- }
- }
- return *m_bookmarkManager;
-}
diff --git a/src/plugins/help/helpmode.cpp b/src/plugins/help/helpmode.cpp
index 24d005f05b..3980c5fe18 100644
--- a/src/plugins/help/helpmode.cpp
+++ b/src/plugins/help/helpmode.cpp
@@ -34,19 +34,16 @@
#include "helpmode.h"
#include "helpconstants.h"
+#include <QtGui/QIcon>
#include <QtGui/QWidget>
using namespace Help;
using namespace Help::Internal;
-HelpMode::HelpMode(QWidget *widget, QObject *parent)
- : BaseMode(parent)
+HelpMode::HelpMode(QObject *parent)
+ : Core::IMode(parent),
+ m_widget(0),
+ m_icon(QLatin1String(":/fancyactionbar/images/mode_Reference.png"))
{
- setDisplayName(tr("Help"));
- setId(QLatin1String(Constants::ID_MODE_HELP));
- setIcon(QIcon(QLatin1String(":/fancyactionbar/images/mode_Reference.png")));
- setPriority(Constants::P_MODE_HELP);
- setWidget(widget);
+ setObjectName(QLatin1String("HelpMode"));
}
-
-
diff --git a/src/plugins/help/helpmode.h b/src/plugins/help/helpmode.h
index cd355cbad4..d7e8f8ecd2 100644
--- a/src/plugins/help/helpmode.h
+++ b/src/plugins/help/helpmode.h
@@ -34,19 +34,35 @@
#ifndef HELPMODE_H
#define HELPMODE_H
-#include <coreplugin/basemode.h>
+#include "helpmode.h"
+#include "helpconstants.h"
-QT_FORWARD_DECLARE_CLASS(QWidget)
+#include <coreplugin/imode.h>
+
+#include <QtCore/QString>
+#include <QtGui/QIcon>
namespace Help {
namespace Internal {
-class HelpMode : public Core::BaseMode
+class HelpMode : public Core::IMode
{
- Q_OBJECT
-
public:
- explicit HelpMode(QWidget *widget, QObject *parent = 0);
+ HelpMode(QObject *parent = 0);
+
+ QString displayName() const { return tr("Help"); }
+ QIcon icon() const { return m_icon; }
+ int priority() const { return Constants::P_MODE_HELP; }
+ QWidget *widget() { return m_widget; }
+ QString id() const { return QLatin1String(Constants::ID_MODE_HELP); }
+ QString type() const { return QString(); }
+ Core::Context context() const { return Core::Context(Constants::C_MODE_HELP); }
+ QString contextHelpId() const { return QString(); }
+ void setWidget(QWidget *widget) { m_widget = widget; }
+
+private:
+ QWidget *m_widget;
+ QIcon m_icon;
};
} // namespace Internal
diff --git a/src/plugins/help/helpplugin.cpp b/src/plugins/help/helpplugin.cpp
index 32cb53a71e..e77aba1690 100644
--- a/src/plugins/help/helpplugin.cpp
+++ b/src/plugins/help/helpplugin.cpp
@@ -43,10 +43,10 @@
#include "helpconstants.h"
#include "helpfindsupport.h"
#include "helpindexfilter.h"
-#include "helpmanager.h"
#include "helpmode.h"
#include "helpviewer.h"
#include "indexwindow.h"
+#include "localhelpmanager.h"
#include "openpagesmanager.h"
#include "openpagesmodel.h"
#include "remotehelpfilter.h"
@@ -55,6 +55,7 @@
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/command.h>
+#include <coreplugin/uniqueidmanager.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
@@ -154,7 +155,7 @@ bool HelpPlugin::initialize(const QStringList &arguments, QString *error)
Core::Context globalcontext(Core::Constants::C_GLOBAL);
Core::Context modecontext(Constants::C_MODE_HELP);
- const QString &locale = qApp->property("qtc_locale").toString();
+ const QString &locale = m_core->userInterfaceLanguage();
if (!locale.isEmpty()) {
QTranslator *qtr = new QTranslator(this);
QTranslator *qhelptr = new QTranslator(this);
@@ -270,23 +271,18 @@ bool HelpPlugin::initialize(const QStringList &arguments, QString *error)
action = new QAction(tr("Increase Font Size"), this);
cmd = am->registerAction(action, TextEditor::Constants::INCREASE_FONT_SIZE,
modecontext);
- cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl++")));
connect(action, SIGNAL(triggered()), m_centralWidget, SLOT(zoomIn()));
advancedMenu->addAction(cmd, Core::Constants::G_EDIT_FONT);
action = new QAction(tr("Decrease Font Size"), this);
cmd = am->registerAction(action, TextEditor::Constants::DECREASE_FONT_SIZE,
modecontext);
- cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+-")));
connect(action, SIGNAL(triggered()), m_centralWidget, SLOT(zoomOut()));
advancedMenu->addAction(cmd, Core::Constants::G_EDIT_FONT);
action = new QAction(tr("Reset Font Size"), this);
cmd = am->registerAction(action, TextEditor::Constants::RESET_FONT_SIZE,
modecontext);
-#ifndef Q_WS_MAC
- cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+0")));
-#endif
connect(action, SIGNAL(triggered()), m_centralWidget, SLOT(resetZoom()));
advancedMenu->addAction(cmd, Core::Constants::G_EDIT_FONT);
}
@@ -308,14 +304,6 @@ bool HelpPlugin::initialize(const QStringList &arguments, QString *error)
windowMenu->addAction(ctrlShiftTab, Core::Constants::G_WINDOW_NAVIGATE);
connect(action, SIGNAL(triggered()), &OpenPagesManager::instance(),
SLOT(gotoNextPage()));
-
-#ifdef Q_WS_MAC
- ctrlTab->setDefaultKeySequence(QKeySequence(tr("Alt+Tab")));
- ctrlShiftTab->setDefaultKeySequence(QKeySequence(tr("Alt+Shift+Tab")));
-#else
- ctrlTab->setDefaultKeySequence(QKeySequence(tr("Ctrl+Tab")));
- ctrlShiftTab->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+Tab")));
-#endif
}
Aggregation::Aggregate *agg = new Aggregation::Aggregate;
@@ -358,18 +346,18 @@ bool HelpPlugin::initialize(const QStringList &arguments, QString *error)
Core::IMode*)), this, SLOT(modeChanged(Core::IMode*, Core::IMode*)));
m_externalWindow = new ExternalHelpWindow;
+ m_mode = new HelpMode;
if (contextHelpOption() == Help::Constants::ExternalHelpAlways) {
- m_mode = new HelpMode(new QWidget);
+ m_mode->setWidget(new QWidget);
m_mode->setEnabled(false);
m_externalHelpBar->setVisible(true);
m_externalWindow->setCentralWidget(m_splitter);
QTimer::singleShot(0, this, SLOT(showExternalWindow()));
} else {
- m_mode = new HelpMode(m_splitter);
+ m_mode->setWidget(m_splitter);
m_internalHelpBar->setVisible(true);
}
addAutoReleasedObject(m_mode);
- m_mode->setContext(modecontext);
return true;
}
@@ -586,15 +574,16 @@ void HelpPlugin::createRightPaneContextViewer()
Aggregation::Aggregate *agg = new Aggregation::Aggregate();
agg->add(m_helpViewerForSideBar);
agg->add(new HelpViewerFindSupport(m_helpViewerForSideBar));
+
+ Core::Context context(Constants::C_HELP_SIDEBAR);
m_core->addContextObject(new Core::BaseContext(m_helpViewerForSideBar,
- Core::Context(Constants::C_HELP_SIDEBAR), this));
+ context, this));
QAction *copy = new QAction(this);
Core::Command *cmd = m_core->actionManager()->registerAction(copy,
- Core::Constants::COPY, Core::Context(Constants::C_HELP_SIDEBAR));
+ Core::Constants::COPY, context);
copy->setText(cmd->action()->text());
copy->setIcon(cmd->action()->icon());
-
connect(copy, SIGNAL(triggered()), m_helpViewerForSideBar, SLOT(copy()));
next->setEnabled(m_helpViewerForSideBar->isForwardAvailable());
@@ -607,11 +596,51 @@ void HelpPlugin::createRightPaneContextViewer()
connect(m_helpViewerForSideBar, SIGNAL(backwardAvailable(bool)), back,
SLOT(setEnabled(bool)));
+ Core::ActionManager *am = m_core->actionManager();
+ if (Core::ActionContainer *advancedMenu = am->actionContainer(M_EDIT_ADVANCED)) {
+ // reuse TextEditor constants to avoid a second pair of menu actions
+ QAction *action = new QAction(tr("Increase Font Size"), this);
+ cmd = am->registerAction(action, TextEditor::Constants::INCREASE_FONT_SIZE,
+ context);
+ connect(action, SIGNAL(triggered()), this, SLOT(scaleRightPaneUp()));
+ advancedMenu->addAction(cmd, Core::Constants::G_EDIT_FONT);
+
+ action = new QAction(tr("Decrease Font Size"), this);
+ cmd = am->registerAction(action, TextEditor::Constants::DECREASE_FONT_SIZE,
+ context);
+ connect(action, SIGNAL(triggered()), this, SLOT(scaleRightPaneDown()));
+ advancedMenu->addAction(cmd, Core::Constants::G_EDIT_FONT);
+
+ action = new QAction(tr("Reset Font Size"), this);
+ cmd = am->registerAction(action, TextEditor::Constants::RESET_FONT_SIZE,
+ context);
+ connect(action, SIGNAL(triggered()), this, SLOT(resetRightPaneScale()));
+ advancedMenu->addAction(cmd, Core::Constants::G_EDIT_FONT);
+ }
+
// force setup, as we might have never switched to full help mode
// thus the help engine might still run without collection file setup
m_helpManager->setupGuiHelpEngine();
}
+void HelpPlugin::scaleRightPaneUp()
+{
+ if (m_helpViewerForSideBar)
+ m_helpViewerForSideBar->scaleUp();
+}
+
+void HelpPlugin::scaleRightPaneDown()
+{
+ if (m_helpViewerForSideBar)
+ m_helpViewerForSideBar->scaleDown();
+}
+
+void HelpPlugin::resetRightPaneScale()
+{
+ if (m_helpViewerForSideBar)
+ m_helpViewerForSideBar->resetScale();
+}
+
void HelpPlugin::activateHelpMode()
{
if (contextHelpOption() != Help::Constants::ExternalHelpAlways)
diff --git a/src/plugins/help/helpplugin.h b/src/plugins/help/helpplugin.h
index 8a576ccfe0..c388b8f0ff 100644
--- a/src/plugins/help/helpplugin.h
+++ b/src/plugins/help/helpplugin.h
@@ -119,6 +119,10 @@ private slots:
void openFindToolBar();
+ void scaleRightPaneUp();
+ void scaleRightPaneDown();
+ void resetRightPaneScale();
+
private:
void setupUi();
void resetFilter();
diff --git a/src/plugins/help/helpviewer.cpp b/src/plugins/help/helpviewer.cpp
index 1df33e5a62..449ed8310b 100644
--- a/src/plugins/help/helpviewer.cpp
+++ b/src/plugins/help/helpviewer.cpp
@@ -33,7 +33,7 @@
#include "helpviewer.h"
#include "helpconstants.h"
-#include "helpmanager.h"
+#include "localhelpmanager.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QFileInfo>
@@ -55,9 +55,10 @@ const QString HelpViewer::AboutBlankPage =
QCoreApplication::translate("HelpViewer", "<title>about:blank</title>");
const QString HelpViewer::PageNotFoundMessage =
- QCoreApplication::translate("HelpViewer", "<title>Error 404...</title><div "
- "align=\"center\"><br><br><h1>The page could not be found</h1><br><h3>'%1'"
- "</h3></div>");
+ QCoreApplication::translate("HelpViewer", "<html><head><meta http-equiv=\""
+ "content-type\" content=\"text/html; charset=UTF-8\"><title>Error 404...</title>"
+ "</head><body><div align=\"center\"><br><br><h1>The page could not be found</h1>"
+ "<br><h3>'%1'</h3></div></body>");
struct ExtensionMap {
const char *extension;
diff --git a/src/plugins/help/helpviewer_qtb.cpp b/src/plugins/help/helpviewer_qtb.cpp
index aded86391e..ee4ce93809 100644
--- a/src/plugins/help/helpviewer_qtb.cpp
+++ b/src/plugins/help/helpviewer_qtb.cpp
@@ -37,7 +37,7 @@
#include "helpconstants.h"
#include "helpviewer_p.h"
-#include "helpmanager.h"
+#include "localhelpmanager.h"
#include <QtGui/QApplication>
#include <QtGui/QClipboard>
diff --git a/src/plugins/help/helpviewer_qwv.cpp b/src/plugins/help/helpviewer_qwv.cpp
index 56f6d35bcf..6ea9e54092 100644
--- a/src/plugins/help/helpviewer_qwv.cpp
+++ b/src/plugins/help/helpviewer_qwv.cpp
@@ -37,7 +37,7 @@
#include "centralwidget.h"
#include "helpconstants.h"
-#include "helpmanager.h"
+#include "localhelpmanager.h"
#include "openpagesmanager.h"
#include <QtCore/QFileInfo>
diff --git a/src/plugins/help/localhelpmanager.cpp b/src/plugins/help/localhelpmanager.cpp
new file mode 100644
index 0000000000..c3d154969d
--- /dev/null
+++ b/src/plugins/help/localhelpmanager.cpp
@@ -0,0 +1,115 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** No Commercial Usage
+**
+** This file 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.
+**
+**************************************************************************/
+
+#include "localhelpmanager.h"
+#include "bookmarkmanager.h"
+
+#include <coreplugin/coreconstants.h>
+#include <coreplugin/helpmanager.h>
+
+#include <QtCore/QMutexLocker>
+
+#include <QtHelp/QHelpEngine>
+
+using namespace Help::Internal;
+
+QMutex LocalHelpManager::m_guiMutex;
+QHelpEngine* LocalHelpManager::m_guiEngine = 0;
+
+QMutex LocalHelpManager::m_bkmarkMutex;
+BookmarkManager* LocalHelpManager::m_bookmarkManager = 0;
+
+LocalHelpManager::LocalHelpManager(QObject *parent)
+ : QObject(parent)
+ , m_guiNeedsSetup(true)
+ , m_needsCollectionFile(true)
+{
+}
+
+LocalHelpManager::~LocalHelpManager()
+{
+ if (m_bookmarkManager) {
+ m_bookmarkManager->saveBookmarks();
+ delete m_bookmarkManager;
+ m_bookmarkManager = 0;
+ }
+
+ delete m_guiEngine;
+ m_guiEngine = 0;
+}
+
+void LocalHelpManager::setupGuiHelpEngine()
+{
+ if (m_needsCollectionFile) {
+ m_needsCollectionFile = false;
+ helpEngine().setCollectionFile(Core::HelpManager::collectionFilePath());
+ }
+
+ if (m_guiNeedsSetup) {
+ m_guiNeedsSetup = false;
+ helpEngine().setupData();
+ }
+}
+
+void LocalHelpManager::setEngineNeedsUpdate()
+{
+ m_guiNeedsSetup = true;
+}
+
+QHelpEngine &LocalHelpManager::helpEngine()
+{
+ if (!m_guiEngine) {
+ QMutexLocker _(&m_guiMutex);
+ if (!m_guiEngine) {
+ m_guiEngine = new QHelpEngine("");
+ m_guiEngine->setAutoSaveFilter(false);
+ }
+ }
+ return *m_guiEngine;
+}
+
+BookmarkManager& LocalHelpManager::bookmarkManager()
+{
+ if (!m_bookmarkManager) {
+ QMutexLocker _(&m_bkmarkMutex);
+ if (!m_bookmarkManager) {
+ m_bookmarkManager = new BookmarkManager;
+ m_bookmarkManager->setupBookmarkModels();
+ const QString &url = QString::fromLatin1("qthelp://com.nokia.qtcreator."
+ "%1%2%3/doc/index.html").arg(IDE_VERSION_MAJOR).arg(IDE_VERSION_MINOR)
+ .arg(IDE_VERSION_RELEASE);
+ helpEngine().setCustomValue(QLatin1String("DefaultHomePage"), url);
+ }
+ }
+ return *m_bookmarkManager;
+}
diff --git a/src/plugins/help/helpmanager.h b/src/plugins/help/localhelpmanager.h
index 9d935b7435..9d935b7435 100644
--- a/src/plugins/help/helpmanager.h
+++ b/src/plugins/help/localhelpmanager.h
diff --git a/src/plugins/help/openpagesmanager.cpp b/src/plugins/help/openpagesmanager.cpp
index bf5ccb09b0..f1746a1b50 100644
--- a/src/plugins/help/openpagesmanager.cpp
+++ b/src/plugins/help/openpagesmanager.cpp
@@ -35,8 +35,8 @@
#include "centralwidget.h"
#include "helpconstants.h"
-#include "helpmanager.h"
#include "helpviewer.h"
+#include "localhelpmanager.h"
#include "openpagesmodel.h"
#include "openpagesswitcher.h"
#include "openpageswidget.h"
diff --git a/src/plugins/help/searchwidget.cpp b/src/plugins/help/searchwidget.cpp
index 5b49eb7a66..8ea21aabc2 100644
--- a/src/plugins/help/searchwidget.cpp
+++ b/src/plugins/help/searchwidget.cpp
@@ -32,7 +32,7 @@
**************************************************************************/
#include "searchwidget.h"
-#include "helpmanager.h"
+#include "localhelpmanager.h"
#include "openpagesmanager.h"
#include <coreplugin/icore.h>
diff --git a/src/plugins/imageviewer/ImageViewer.pluginspec b/src/plugins/imageviewer/ImageViewer.pluginspec
deleted file mode 100644
index 75783cee3e..0000000000
--- a/src/plugins/imageviewer/ImageViewer.pluginspec
+++ /dev/null
@@ -1,19 +0,0 @@
-<plugin name="ImageViewer" version="2.0.95" compatVersion="2.0.95">
- <vendor>Nokia Corporation</vendor>
- <copyright>(C) 2010 Denis Mingulov</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>
- <category>Qt Creator</category>
- <description>Image Viewer component.</description>
- <url>http://qt.nokia.com</url>
- <dependencyList>
- <dependency name="Core" version="2.0.95"/>
- </dependencyList>
-</plugin>
diff --git a/src/plugins/imageviewer/ImageViewer.pluginspec.in b/src/plugins/imageviewer/ImageViewer.pluginspec.in
new file mode 100644
index 0000000000..8cead354be
--- /dev/null
+++ b/src/plugins/imageviewer/ImageViewer.pluginspec.in
@@ -0,0 +1,19 @@
+<plugin name=\"ImageViewer\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2010 Denis Mingulov</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>
+ <category>Qt Creator</category>
+ <description>Image Viewer component.</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/imageviewer/imageviewer.pro b/src/plugins/imageviewer/imageviewer.pro
index 41d64bfb11..40a15d89b7 100644
--- a/src/plugins/imageviewer/imageviewer.pro
+++ b/src/plugins/imageviewer/imageviewer.pro
@@ -24,7 +24,6 @@ RESOURCES += \
imageviewer.qrc
OTHER_FILES += \
- ImageViewer.pluginspec \
ImageViewer.mimetypes.xml
contains(QT_CONFIG, svg):QT += svg
diff --git a/src/plugins/locator/Locator.pluginspec b/src/plugins/locator/Locator.pluginspec
deleted file mode 100644
index 0883c3fc9d..0000000000
--- a/src/plugins/locator/Locator.pluginspec
+++ /dev/null
@@ -1,19 +0,0 @@
-<plugin name="Locator" version="2.0.95" compatVersion="2.0.95">
- <vendor>Nokia Corporation</vendor>
- <copyright>(C) 2010 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>
- <category>Qt Creator</category>
- <description>Provides the Locator widget and the hooks for Locator filter implementations.</description>
- <url>http://qt.nokia.com</url>
- <dependencyList>
- <dependency name="Core" version="2.0.95"/>
- </dependencyList>
-</plugin>
diff --git a/src/plugins/locator/Locator.pluginspec.in b/src/plugins/locator/Locator.pluginspec.in
new file mode 100644
index 0000000000..d6a99570fb
--- /dev/null
+++ b/src/plugins/locator/Locator.pluginspec.in
@@ -0,0 +1,19 @@
+<plugin name=\"Locator\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2010 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>
+ <category>Qt Creator</category>
+ <description>Provides the Locator widget and the hooks for Locator filter implementations.</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/locator/locator.pri b/src/plugins/locator/locator.pri
index 1eb758b80e..541771da51 100644
--- a/src/plugins/locator/locator.pri
+++ b/src/plugins/locator/locator.pri
@@ -1,3 +1,3 @@
include(locator_dependencies.pri)
-LIBS *= -l$$qtLibraryTarget(Locator)
+LIBS *= -l$$qtLibraryName(Locator)
diff --git a/src/plugins/locator/locator.pro b/src/plugins/locator/locator.pro
index 7844b742aa..2d81975fa5 100644
--- a/src/plugins/locator/locator.pro
+++ b/src/plugins/locator/locator.pro
@@ -32,5 +32,3 @@ FORMS += settingspage.ui \
filesystemfilter.ui \
directoryfilter.ui
RESOURCES += locator.qrc
-
-OTHER_FILES += Locator.pluginspec
diff --git a/src/plugins/locator/locatorfiltersfilter.cpp b/src/plugins/locator/locatorfiltersfilter.cpp
index b2ceb548a1..8d25c5b257 100644
--- a/src/plugins/locator/locatorfiltersfilter.cpp
+++ b/src/plugins/locator/locatorfiltersfilter.cpp
@@ -40,7 +40,7 @@
using namespace Locator;
using namespace Locator::Internal;
-Q_DECLARE_METATYPE(ILocatorFilter*);
+Q_DECLARE_METATYPE(ILocatorFilter*)
LocatorFiltersFilter::LocatorFiltersFilter(LocatorPlugin *plugin,
LocatorWidget *locatorWidget):
diff --git a/src/plugins/locator/locatorplugin.cpp b/src/plugins/locator/locatorplugin.cpp
index 6812bda82c..0c7736bd46 100644
--- a/src/plugins/locator/locatorplugin.cpp
+++ b/src/plugins/locator/locatorplugin.cpp
@@ -40,11 +40,6 @@
#include "filesystemfilter.h"
#include "settingspage.h"
-#include <QtCore/QSettings>
-#include <QtCore/QtPlugin>
-#include <QtCore/QFuture>
-#include <QtCore/QFutureWatcher>
-
#include <coreplugin/statusbarwidget.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/settingsdatabase.h>
@@ -58,6 +53,12 @@
#include <extensionsystem/pluginmanager.h>
#include <qtconcurrent/QtConcurrentTools>
+#include <QtCore/QSettings>
+#include <QtCore/QtPlugin>
+#include <QtCore/QFuture>
+#include <QtCore/QFutureWatcher>
+#include <QtGui/QAction>
+
/*!
\namespace Locator
The Locator namespace provides the hooks for Locator content.
@@ -146,6 +147,7 @@ void LocatorPlugin::extensionsInitialized()
{
m_filters = ExtensionSystem::PluginManager::instance()->getObjects<ILocatorFilter>();
qSort(m_filters.begin(), m_filters.end(), filterLessThan);
+ setFilters(m_filters);
}
void LocatorPlugin::startSettingsLoad()
diff --git a/src/plugins/locator/locatorwidget.cpp b/src/plugins/locator/locatorwidget.cpp
index a60054705a..2cfbc07624 100644
--- a/src/plugins/locator/locatorwidget.cpp
+++ b/src/plugins/locator/locatorwidget.cpp
@@ -41,6 +41,8 @@
#include <extensionsystem/pluginmanager.h>
#include <coreplugin/icore.h>
#include <coreplugin/modemanager.h>
+#include <coreplugin/actionmanager/actionmanager.h>
+#include <coreplugin/actionmanager/command.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/fileiconprovider.h>
#include <utils/filterlineedit.h>
@@ -67,8 +69,8 @@
#include <QtGui/QScrollBar>
#include <QtGui/QTreeView>
-Q_DECLARE_METATYPE(Locator::ILocatorFilter*);
-Q_DECLARE_METATYPE(Locator::FilterEntry);
+Q_DECLARE_METATYPE(Locator::ILocatorFilter*)
+Q_DECLARE_METATYPE(Locator::FilterEntry)
namespace Locator {
namespace Internal {
@@ -325,12 +327,41 @@ LocatorWidget::LocatorWidget(LocatorPlugin *qop) :
void LocatorWidget::updateFilterList()
{
m_filterMenu->clear();
+
+ // update actions and menu
+ Core::ActionManager *am = Core::ICore::instance()->actionManager();
+ QMap<QString, QAction *> actionCopy = m_filterActionMap;
+ m_filterActionMap.clear();
+ // register new actions, update existent
foreach (ILocatorFilter *filter, m_locatorPlugin->filters()) {
- if (!filter->shortcutString().isEmpty() && !filter->isHidden()) {
- QAction *action = m_filterMenu->addAction(filter->displayName(), this, SLOT(filterSelected()));
+ if (filter->shortcutString().isEmpty() || filter->isHidden())
+ continue;
+ QString locatorId = QLatin1String("Locator.") + filter->id();
+ QAction *action = 0;
+ Core::Command *cmd = 0;
+ if (!actionCopy.contains(filter->id())) {
+ // register new action
+ action = new QAction(filter->displayName(), this);
+ cmd = am->registerAction(action, locatorId,
+ Core::Context(Core::Constants::C_GLOBAL));
+ cmd->setAttribute(Core::Command::CA_UpdateText);
+ connect(action, SIGNAL(triggered()), this, SLOT(filterSelected()));
action->setData(qVariantFromValue(filter));
+ } else {
+ action = actionCopy.take(filter->id());
+ action->setText(filter->displayName());
+ cmd = am->command(locatorId);
}
+ m_filterActionMap.insert(filter->id(), action);
+ m_filterMenu->addAction(cmd->action());
+ }
+
+ // unregister actions that are deleted now
+ foreach (const QString &id, actionCopy.keys()) {
+ am->unregisterAction(actionCopy.value(id), QString(QLatin1String("Locator.") + id));
}
+ qDeleteAll(actionCopy);
+
m_filterMenu->addSeparator();
m_filterMenu->addAction(m_refreshAction);
m_filterMenu->addAction(m_configureAction);
@@ -408,12 +439,15 @@ QList<ILocatorFilter*> LocatorWidget::filtersFor(const QString &text, QString &s
prefix = text.left(whiteSpace);
if (!prefix.isEmpty()) {
prefix = prefix.toLower();
+ QList<ILocatorFilter *> prefixFilters;
foreach (ILocatorFilter *filter, filters) {
if (prefix == filter->shortcutString()) {
searchText = text.mid(whiteSpace+1);
- return QList<ILocatorFilter*>() << filter;
+ prefixFilters << filter;
}
}
+ if (!prefixFilters.isEmpty())
+ return prefixFilters;
}
searchText = text;
QList<ILocatorFilter*> activeFilters;
diff --git a/src/plugins/locator/locatorwidget.h b/src/plugins/locator/locatorwidget.h
index 4b288f9b15..8fa1c0cbb0 100644
--- a/src/plugins/locator/locatorwidget.h
+++ b/src/plugins/locator/locatorwidget.h
@@ -95,6 +95,7 @@ private:
Utils::FilterLineEdit *m_fileLineEdit;
QTimer *m_showPopupTimer;
QFutureWatcher<FilterEntry> *m_entriesWatcher;
+ QMap<QString, QAction *> m_filterActionMap;
};
} // namespace Internal
diff --git a/src/plugins/locator/opendocumentsfilter.cpp b/src/plugins/locator/opendocumentsfilter.cpp
index 8f5ca37ff6..d996112f55 100644
--- a/src/plugins/locator/opendocumentsfilter.cpp
+++ b/src/plugins/locator/opendocumentsfilter.cpp
@@ -36,8 +36,6 @@
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
-Q_DECLARE_METATYPE(Core::IEditor*);
-
using namespace Core;
using namespace Locator;
using namespace Locator::Internal;
diff --git a/src/plugins/mercurial/Mercurial.pluginspec b/src/plugins/mercurial/Mercurial.pluginspec
deleted file mode 100644
index 9169cb2418..0000000000
--- a/src/plugins/mercurial/Mercurial.pluginspec
+++ /dev/null
@@ -1,22 +0,0 @@
-<plugin name="Mercurial" version="2.0.95" compatVersion="2.0.95">
- <vendor>Brian McGillion</vendor>
- <copyright>(C) 2008-2009 Brian McGillion</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>
- <category>Version Control</category>
- <description>Mercurial integration.</description>
- <url>http://qt.nokia.com</url>
- <dependencyList>
- <dependency name="TextEditor" version="2.0.95"/>
- <dependency name="ProjectExplorer" version="2.0.95"/>
- <dependency name="Core" version="2.0.95"/>
- <dependency name="VCSBase" version="2.0.95"/>
- </dependencyList>
-</plugin>
diff --git a/src/plugins/mercurial/Mercurial.pluginspec.in b/src/plugins/mercurial/Mercurial.pluginspec.in
new file mode 100644
index 0000000000..8ff246b0de
--- /dev/null
+++ b/src/plugins/mercurial/Mercurial.pluginspec.in
@@ -0,0 +1,22 @@
+<plugin name=\"Mercurial\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Brian McGillion</vendor>
+ <copyright>(C) 2008-2009 Brian McGillion</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>
+ <category>Version Control</category>
+ <description>Mercurial integration.</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name=\"TextEditor\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"ProjectExplorer\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"VCSBase\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/mercurial/mercurial.pro b/src/plugins/mercurial/mercurial.pro
index 9b52048b32..f532f20471 100644
--- a/src/plugins/mercurial/mercurial.pro
+++ b/src/plugins/mercurial/mercurial.pro
@@ -31,7 +31,6 @@ HEADERS += mercurialplugin.h \
clonewizardpage.h \
clonewizard.h \
mercurialsettings.h
-OTHER_FILES += Mercurial.pluginspec
FORMS += optionspage.ui \
revertdialog.ui \
srcdestdialog.ui \
diff --git a/src/plugins/mercurial/mercurialplugin.cpp b/src/plugins/mercurial/mercurialplugin.cpp
index 094592df15..b764fdfdcd 100644
--- a/src/plugins/mercurial/mercurialplugin.cpp
+++ b/src/plugins/mercurial/mercurialplugin.cpp
@@ -46,7 +46,7 @@
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/command.h>
-#include <coreplugin/basemode.h>
+#include <coreplugin/uniqueidmanager.h>
#include <coreplugin/vcsmanager.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/icore.h>
diff --git a/src/plugins/mercurial/optionspage.cpp b/src/plugins/mercurial/optionspage.cpp
index 805a7bcdfe..298ed0bd86 100644
--- a/src/plugins/mercurial/optionspage.cpp
+++ b/src/plugins/mercurial/optionspage.cpp
@@ -77,12 +77,18 @@ void OptionsPageWidget::setSettings(const MercurialSettings &s)
QString OptionsPageWidget::searchKeywords() const
{
QString rc;
- QTextStream(&rc) << ' ' << m_ui.mercurialCommandLabel->text()
- << ' ' << m_ui.showLogEntriesLabel->text()
- << ' ' << m_ui.timeoutSecondsLabel->text()
- << ' ' << m_ui.promptOnSubmitCheckBox->text()
- << ' ' << m_ui.defaultUsernameLabel->text()
- << ' ' << m_ui.defaultEmailLabel->text();
+ QLatin1Char sep(' ');
+ QTextStream(&rc)
+ << sep << m_ui.configGroupBox->title()
+ << sep << m_ui.mercurialCommandLabel->text()
+ << sep << m_ui.userGroupBox->title()
+ << sep << m_ui.defaultUsernameLabel->text()
+ << sep << m_ui.defaultEmailLabel->text()
+ << sep << m_ui.miscGroupBox->title()
+ << sep << m_ui.showLogEntriesLabel->text()
+ << sep << m_ui.timeoutSecondsLabel->text()
+ << sep << m_ui.promptOnSubmitCheckBox->text()
+ ;
rc.remove(QLatin1Char('&'));
return rc;
}
diff --git a/src/plugins/mercurial/optionspage.ui b/src/plugins/mercurial/optionspage.ui
index 248dbeeeb5..a55ca08eae 100644
--- a/src/plugins/mercurial/optionspage.ui
+++ b/src/plugins/mercurial/optionspage.ui
@@ -15,7 +15,7 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
- <widget class="QGroupBox" name="configgroupBox">
+ <widget class="QGroupBox" name="configGroupBox">
<property name="title">
<string>Configuration</string>
</property>
@@ -28,7 +28,7 @@
</widget>
</item>
<item row="0" column="1">
- <widget class="Utils::PathChooser" name="commandChooser"/>
+ <widget class="Utils::PathChooser" name="commandChooser" native="true"/>
</item>
</layout>
</widget>
@@ -147,6 +147,10 @@
<extends>QWidget</extends>
<header location="global">utils/pathchooser.h</header>
<container>1</container>
+ <slots>
+ <signal>editingFinished()</signal>
+ <signal>browsingFinished()</signal>
+ </slots>
</customwidget>
</customwidgets>
<resources/>
diff --git a/src/plugins/perforce/Perforce.pluginspec b/src/plugins/perforce/Perforce.pluginspec
deleted file mode 100644
index e5c3d4b901..0000000000
--- a/src/plugins/perforce/Perforce.pluginspec
+++ /dev/null
@@ -1,22 +0,0 @@
-<plugin name="Perforce" version="2.0.95" compatVersion="2.0.95">
- <vendor>Nokia Corporation</vendor>
- <copyright>(C) 2010 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>
- <category>Version Control</category>
- <description>Perforce integration.</description>
- <url>http://qt.nokia.com</url>
- <dependencyList>
- <dependency name="TextEditor" version="2.0.95"/>
- <dependency name="ProjectExplorer" version="2.0.95"/>
- <dependency name="Core" version="2.0.95"/>
- <dependency name="VCSBase" version="2.0.95"/>
- </dependencyList>
-</plugin>
diff --git a/src/plugins/perforce/Perforce.pluginspec.in b/src/plugins/perforce/Perforce.pluginspec.in
new file mode 100644
index 0000000000..7a48f43351
--- /dev/null
+++ b/src/plugins/perforce/Perforce.pluginspec.in
@@ -0,0 +1,22 @@
+<plugin name=\"Perforce\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2010 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>
+ <category>Version Control</category>
+ <description>Perforce integration.</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name=\"TextEditor\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"ProjectExplorer\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"VCSBase\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/perforce/perforce.pro b/src/plugins/perforce/perforce.pro
index 27d398f0f3..7754b7fae5 100644
--- a/src/plugins/perforce/perforce.pro
+++ b/src/plugins/perforce/perforce.pro
@@ -36,5 +36,3 @@ FORMS += settingspage.ui \
submitpanel.ui
RESOURCES += perforce.qrc
-
-OTHER_FILES += Perforce.pluginspec
diff --git a/src/plugins/perforce/perforceplugin.cpp b/src/plugins/perforce/perforceplugin.cpp
index 399fd8c31f..2d63c2b6e8 100644
--- a/src/plugins/perforce/perforceplugin.cpp
+++ b/src/plugins/perforce/perforceplugin.cpp
@@ -45,6 +45,7 @@
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/command.h>
+#include <coreplugin/uniqueidmanager.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/filemanager.h>
@@ -937,13 +938,13 @@ bool PerforcePlugin::vcsMove(const QString &workingDir, const QString &from, con
QStringList args;
args << QLatin1String("edit") << from;
const PerforceResponse editResult = runP4Cmd(workingDir, args,
- CommandToWindow|StdOutToWindow|StdErrToWindow|ErrorToWindow);
+ RunFullySynchronous|CommandToWindow|StdOutToWindow|StdErrToWindow|ErrorToWindow);
if (editResult.error)
return false;
args.clear();
args << QLatin1String("move") << from << to;
const PerforceResponse moveResult = runP4Cmd(workingDir, args,
- CommandToWindow|StdOutToWindow|StdErrToWindow|ErrorToWindow);
+ RunFullySynchronous|CommandToWindow|StdOutToWindow|StdErrToWindow|ErrorToWindow);
return !moveResult.error;
}
diff --git a/src/plugins/perforce/perforcesettings.cpp b/src/plugins/perforce/perforcesettings.cpp
index fbec369127..8aa4d2debf 100644
--- a/src/plugins/perforce/perforcesettings.cpp
+++ b/src/plugins/perforce/perforcesettings.cpp
@@ -86,7 +86,7 @@ bool Settings::equals(const Settings &rhs) const
&& p4Client == rhs.p4Client && p4User == rhs.p4User
&& timeOutS == rhs.timeOutS && promptToSubmit == rhs.promptToSubmit
&& autoOpen == rhs.autoOpen;
-};
+}
QStringList Settings::commonP4Arguments() const
{
diff --git a/src/plugins/perforce/perforcesettings.h b/src/plugins/perforce/perforcesettings.h
index ab5ff7c848..53068bfe8f 100644
--- a/src/plugins/perforce/perforcesettings.h
+++ b/src/plugins/perforce/perforcesettings.h
@@ -86,7 +86,7 @@ inline bool operator!=(const Settings &s1, const Settings &s2) { return !s1.equa
* "-d" option, so that running p4 in "/depot/dev/foo" results in "-d $HOME/dev/foo". */
class PerforceSettings {
- Q_DISABLE_COPY(PerforceSettings);
+ Q_DISABLE_COPY(PerforceSettings)
public:
PerforceSettings();
~PerforceSettings();
diff --git a/src/plugins/perforce/perforceversioncontrol.cpp b/src/plugins/perforce/perforceversioncontrol.cpp
index 411764d950..20d9696059 100644
--- a/src/plugins/perforce/perforceversioncontrol.cpp
+++ b/src/plugins/perforce/perforceversioncontrol.cpp
@@ -82,7 +82,7 @@ Core::IVersionControl::SettingsFlags PerforceVersionControl::settingsFlags() con
if (m_plugin->settings().autoOpen())
rc|= AutoOpen;
return rc;
-};
+}
bool PerforceVersionControl::vcsAdd(const QString &fileName)
{
diff --git a/src/plugins/perforce/settingspage.cpp b/src/plugins/perforce/settingspage.cpp
index 13fd2321cd..cc2c20762c 100644
--- a/src/plugins/perforce/settingspage.cpp
+++ b/src/plugins/perforce/settingspage.cpp
@@ -121,10 +121,20 @@ void SettingsPageWidget::setStatusError(const QString &t)
QString SettingsPageWidget::searchKeywords() const
{
QString rc;
- QTextStream(&rc) << m_ui.promptToSubmitCheckBox->text()
- << ' ' << m_ui.commandLabel << m_ui.environmentGroupBox->title()
- << ' ' << m_ui.clientLabel->text() << ' ' << m_ui.userLabel->text()
- << ' ' << m_ui.portLabel->text();
+ QLatin1Char sep(' ');
+ QTextStream(&rc)
+ << sep << m_ui.configGroupBox->title()
+ << sep << m_ui.commandLabel->text()
+ << sep << m_ui.environmentGroupBox->title()
+ << sep << m_ui.portLabel->text()
+ << sep << m_ui.clientLabel->text()
+ << sep << m_ui.userLabel->text()
+ << sep << m_ui.miscGroupBox->title()
+ << sep << m_ui.logCountLabel->text()
+ << sep << m_ui.timeOutLabel->text()
+ << sep << m_ui.promptToSubmitCheckBox->text()
+ << sep << m_ui.autoOpenCheckBox->text()
+ ;
rc.remove(QLatin1Char('&'));
return rc;
}
diff --git a/src/plugins/perforce/settingspage.ui b/src/plugins/perforce/settingspage.ui
index e62622038b..cd59e33784 100644
--- a/src/plugins/perforce/settingspage.ui
+++ b/src/plugins/perforce/settingspage.ui
@@ -2,6 +2,14 @@
<ui version="4.0">
<class>Perforce::Internal::SettingsPage</class>
<widget class="QWidget" name="Perforce::Internal::SettingsPage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>306</width>
+ <height>516</height>
+ </rect>
+ </property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="configGroupBox">
@@ -37,12 +45,6 @@
<bool>false</bool>
</property>
<layout class="QGridLayout">
- <property name="margin">
- <number>9</number>
- </property>
- <property name="spacing">
- <number>6</number>
- </property>
<item row="1" column="1">
<widget class="QLineEdit" name="clientLineEdit"/>
</item>
@@ -77,7 +79,7 @@
</widget>
</item>
<item>
- <widget class="QGroupBox" name="miscgroupBox">
+ <widget class="QGroupBox" name="miscGroupBox">
<property name="title">
<string>Miscellaneous</string>
</property>
diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
index b8bd93bfd3..ed90b1e75d 100644
--- a/src/plugins/plugins.pro
+++ b/src/plugins/plugins.pro
@@ -19,7 +19,6 @@ SUBDIRS = plugin_coreplugin \
plugin_cvs \
plugin_cpptools \
plugin_qt4projectmanager \
-# plugin_snippets \ # buggy and annoying
plugin_locator \
plugin_debugger \
# plugin_qtestlib \ # this seems to be dead
@@ -33,9 +32,11 @@ SUBDIRS = plugin_coreplugin \
plugin_resourceeditor \
plugin_genericprojectmanager \
plugin_qmljseditor \
+ plugin_glsleditor \
plugin_mercurial \
plugin_classview \
plugin_tasklist \
+ plugin_qmljstools \
debugger/dumper.pro
include(../../qtcreator.pri)
@@ -49,7 +50,7 @@ contains(QT_CONFIG, declarative) {
exists($${QT_PRIVATE_HEADERS}/QtDeclarative/private/qdeclarativecontext_p.h) {
minQtVersion(4, 7, 1) {
- SUBDIRS += plugin_qmldesigner
+ SUBDIRS += plugin_qmldesigner
} else {
warning()
warning("QmlDesigner plugin has been disabled.")
@@ -63,6 +64,8 @@ contains(QT_CONFIG, declarative) {
}
}
+include (debugger/lldb/guest/qtcreator-lldb.pri)
+
plugin_coreplugin.subdir = coreplugin
plugin_welcome.subdir = welcome
@@ -89,7 +92,7 @@ plugin_imageviewer.subdir = imageviewer
plugin_imageviewer.depends = plugin_coreplugin
plugin_designer.subdir = designer
-plugin_designer.depends = plugin_coreplugin plugin_cppeditor plugin_projectexplorer
+plugin_designer.depends = plugin_coreplugin plugin_cpptools plugin_projectexplorer plugin_texteditor
plugin_vcsbase.subdir = vcsbase
plugin_vcsbase.depends = plugin_find
@@ -127,7 +130,6 @@ plugin_qt4projectmanager.subdir = qt4projectmanager
plugin_qt4projectmanager.depends = plugin_texteditor
plugin_qt4projectmanager.depends += plugin_projectexplorer
plugin_qt4projectmanager.depends += plugin_cpptools
-plugin_qt4projectmanager.depends += plugin_cppeditor
plugin_qt4projectmanager.depends += plugin_designer
plugin_qt4projectmanager.depends += plugin_debugger
plugin_qt4projectmanager.depends += plugin_qmljseditor
@@ -146,11 +148,6 @@ plugin_bookmarks.depends = plugin_projectexplorer
plugin_bookmarks.depends += plugin_coreplugin
plugin_bookmarks.depends += plugin_texteditor
-plugin_snippets.subdir = snippets
-plugin_snippets.depends = plugin_projectexplorer
-plugin_snippets.depends += plugin_coreplugin
-plugin_snippets.depends += plugin_texteditor
-
plugin_debugger.subdir = debugger
plugin_debugger.depends = plugin_projectexplorer
plugin_debugger.depends += plugin_coreplugin
@@ -182,24 +179,29 @@ plugin_regexp.depends = plugin_coreplugin
plugin_cpaster.subdir = cpaster
plugin_cpaster.depends = plugin_texteditor
plugin_cpaster.depends += plugin_coreplugin
-plugin_cpaster.depends += plugin_projectexplorer
plugin_cmakeprojectmanager.subdir = cmakeprojectmanager
plugin_cmakeprojectmanager.depends = plugin_texteditor
plugin_cmakeprojectmanager.depends += plugin_projectexplorer
plugin_cmakeprojectmanager.depends += plugin_cpptools
-plugin_cmakeprojectmanager.depends += plugin_cppeditor
+plugin_cmakeprojectmanager.depends += plugin_designer
plugin_genericprojectmanager.subdir = genericprojectmanager
plugin_genericprojectmanager.depends = plugin_texteditor
plugin_genericprojectmanager.depends += plugin_projectexplorer
plugin_genericprojectmanager.depends += plugin_cpptools
-plugin_genericprojectmanager.depends += plugin_cppeditor
plugin_qmljseditor.subdir = qmljseditor
plugin_qmljseditor.depends = plugin_texteditor
plugin_qmljseditor.depends += plugin_coreplugin
plugin_qmljseditor.depends += plugin_projectexplorer
+plugin_qmljseditor.depends += plugin_qmljstools
+
+plugin_glsleditor.subdir = glsleditor
+plugin_glsleditor.depends = plugin_texteditor
+plugin_glsleditor.depends += plugin_coreplugin
+plugin_glsleditor.depends += plugin_projectexplorer
+plugin_glsleditor.depends += plugin_cpptools
plugin_qmlprojectmanager.subdir = qmlprojectmanager
plugin_qmlprojectmanager.depends = plugin_texteditor
@@ -232,3 +234,8 @@ plugin_classview.depends += plugin_texteditor
plugin_tasklist.subdir = tasklist
plugin_tasklist.depends = plugin_coreplugin
plugin_tasklist.depends += plugin_projectexplorer
+
+plugin_qmljstools.subdir = qmljstools
+plugin_qmljstools.depends = plugin_projectexplorer
+plugin_qmljstools.depends += plugin_coreplugin
+plugin_qmljstools.depends += plugin_texteditor
diff --git a/src/plugins/projectexplorer/ProjectExplorer.pluginspec b/src/plugins/projectexplorer/ProjectExplorer.pluginspec
deleted file mode 100644
index cbd5b7d77b..0000000000
--- a/src/plugins/projectexplorer/ProjectExplorer.pluginspec
+++ /dev/null
@@ -1,26 +0,0 @@
-<plugin name="ProjectExplorer" version="2.0.95" compatVersion="2.0.95">
- <vendor>Nokia Corporation</vendor>
- <copyright>(C) 2010 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>
- <category>Qt Creator</category>
- <description>ProjectExplorer framework that can be extended with different kind of project types.</description>
- <url>http://qt.nokia.com</url>
- <dependencyList>
- <dependency name="Core" version="2.0.95"/>
- <dependency name="Find" version="2.0.95"/>
- <dependency name="Locator" version="2.0.95"/>
- <dependency name="TextEditor" version="2.0.95"/>
- </dependencyList>
- <argumentList>
- <argument name="-customwizard-verbose">Verbose loading of custom wizards</argument>
- <argument name="-lastsession">Restore the last session</argument>
- </argumentList>
-</plugin>
diff --git a/src/plugins/projectexplorer/ProjectExplorer.pluginspec.in b/src/plugins/projectexplorer/ProjectExplorer.pluginspec.in
new file mode 100644
index 0000000000..f51d62df10
--- /dev/null
+++ b/src/plugins/projectexplorer/ProjectExplorer.pluginspec.in
@@ -0,0 +1,26 @@
+<plugin name=\"ProjectExplorer\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2010 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>
+ <category>Qt Creator</category>
+ <description>ProjectExplorer framework that can be extended with different kind of project types.</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"Find\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"Locator\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"TextEditor\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+ <argumentList>
+ <argument name=\"-customwizard-verbose\">Verbose loading of custom wizards</argument>
+ <argument name=\"-lastsession\">Restore the last session</argument>
+ </argumentList>
+</plugin>
diff --git a/src/plugins/projectexplorer/abstractprocessstep.cpp b/src/plugins/projectexplorer/abstractprocessstep.cpp
index 70b9fc94b7..2a7ace8167 100644
--- a/src/plugins/projectexplorer/abstractprocessstep.cpp
+++ b/src/plugins/projectexplorer/abstractprocessstep.cpp
@@ -39,11 +39,11 @@
#include "target.h"
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
-#include <QtCore/QProcess>
#include <QtCore/QEventLoop>
#include <QtCore/QTimer>
-#include <QtGui/QTextDocument>
+#include <QtCore/QDir>
using namespace ProjectExplorer;
@@ -70,21 +70,6 @@ AbstractProcessStep::~AbstractProcessStep()
delete m_outputParserChain;
}
-void AbstractProcessStep::setCommand(const QString &cmd)
-{
- m_command = cmd;
-}
-
-QString AbstractProcessStep::command() const
-{
- return m_command;
-}
-
-QString AbstractProcessStep::workingDirectory() const
-{
- return m_workingDirectory;
-}
-
void AbstractProcessStep::setOutputParser(ProjectExplorer::IOutputParser *parser)
{
delete m_outputParserChain;
@@ -113,36 +98,11 @@ ProjectExplorer::IOutputParser *AbstractProcessStep::outputParser() const
return m_outputParserChain;
}
-void AbstractProcessStep::setWorkingDirectory(const QString &workingDirectory)
-{
- m_workingDirectory = workingDirectory;
-}
-
-void AbstractProcessStep::setArguments(const QStringList &arguments)
-{
- m_arguments = arguments;
-}
-
-QStringList AbstractProcessStep::arguments() const
-{
- return m_arguments;
-}
-
-void AbstractProcessStep::setEnabled(bool b)
-{
- m_enabled = b;
-}
-
void AbstractProcessStep::setIgnoreReturnValue(bool b)
{
m_ignoreReturnValue = b;
}
-void AbstractProcessStep::setEnvironment(Utils::Environment env)
-{
- m_environment = env;
-}
-
bool AbstractProcessStep::init()
{
return true;
@@ -155,13 +115,13 @@ void AbstractProcessStep::run(QFutureInterface<bool> &fi)
fi.reportResult(true);
return;
}
- QDir wd(m_environment.expandVariables(m_workingDirectory));
+ QDir wd(m_param.effectiveWorkingDirectory());
if (!wd.exists())
wd.mkpath(wd.absolutePath());
- m_process = new QProcess();
+ m_process = new Utils::QtcProcess();
m_process->setWorkingDirectory(wd.absolutePath());
- m_process->setEnvironment(m_environment.toStringList());
+ m_process->setEnvironment(m_param.environment());
connect(m_process, SIGNAL(readyReadStandardOutput()),
this, SLOT(processReadyReadStdOutput()),
@@ -174,7 +134,8 @@ void AbstractProcessStep::run(QFutureInterface<bool> &fi)
this, SLOT(slotProcessFinished(int, QProcess::ExitStatus)),
Qt::DirectConnection);
- m_process->start(expandedCommand(), m_environment.expandVariables(m_arguments));
+ m_process->setCommand(m_param.effectiveCommand(), m_param.effectiveArguments());
+ m_process->start();
if (!m_process->waitForStarted()) {
processStartupFailed();
delete m_process;
@@ -215,32 +176,31 @@ void AbstractProcessStep::run(QFutureInterface<bool> &fi)
void AbstractProcessStep::processStarted()
{
emit addOutput(tr("Starting: \"%1\" %2\n")
- .arg(QDir::toNativeSeparators(expandedCommand()),
- m_environment.expandVariables(m_arguments).join(QChar(' '))),
+ .arg(QDir::toNativeSeparators(m_param.effectiveCommand()),
+ m_param.prettyArguments()),
BuildStep::MessageOutput);
}
void AbstractProcessStep::processFinished(int exitCode, QProcess::ExitStatus status)
{
- QString command = expandedCommand();
+ QString command = QDir::toNativeSeparators(m_param.effectiveCommand());
if (status == QProcess::NormalExit && exitCode == 0) {
- emit addOutput(tr("The process \"%1\" exited normally.")
- .arg(QDir::toNativeSeparators(command)),
+ emit addOutput(tr("The process \"%1\" exited normally.").arg(command),
BuildStep::MessageOutput);
} else if (status == QProcess::NormalExit) {
emit addOutput(tr("The process \"%1\" exited with code %2.")
- .arg(QDir::toNativeSeparators(command), QString::number(m_process->exitCode())),
+ .arg(command, QString::number(m_process->exitCode())),
BuildStep::ErrorMessageOutput);
} else {
- emit addOutput(tr("The process \"%1\" crashed.").arg(QDir::toNativeSeparators(command)), BuildStep::ErrorMessageOutput);
+ emit addOutput(tr("The process \"%1\" crashed.").arg(command), BuildStep::ErrorMessageOutput);
}
}
void AbstractProcessStep::processStartupFailed()
{
- emit addOutput(tr("Could not start process \"%1\" %2").
- arg(QDir::toNativeSeparators(expandedCommand()),
- m_environment.expandVariables(m_arguments).join(QChar(' '))),
+ emit addOutput(tr("Could not start process \"%1\" %2")
+ .arg(QDir::toNativeSeparators(m_param.effectiveCommand()),
+ m_param.prettyArguments()),
BuildStep::ErrorMessageOutput);
}
@@ -356,12 +316,3 @@ void AbstractProcessStep::slotProcessFinished(int, QProcess::ExitStatus)
m_eventLoop->exit(0);
}
-
-QString AbstractProcessStep::expandedCommand() const
-{
- QString command = m_environment.searchInPath(
- m_command, QStringList() << m_environment.expandVariables(m_workingDirectory));
- if (command.isEmpty())
- command = m_command;
- return command;
-}
diff --git a/src/plugins/projectexplorer/abstractprocessstep.h b/src/plugins/projectexplorer/abstractprocessstep.h
index e5cd82e6ea..535495dd28 100644
--- a/src/plugins/projectexplorer/abstractprocessstep.h
+++ b/src/plugins/projectexplorer/abstractprocessstep.h
@@ -35,11 +35,13 @@
#define ABSTRACTPROCESSSTEP_H
#include "buildstep.h"
+#include "processparameters.h"
#include <utils/environment.h>
+#include <utils/qtcprocess.h>
+
#include <QtCore/QString>
-#include <QtCore/QProcess>
QT_BEGIN_NAMESPACE
class QEventLoop;
@@ -55,7 +57,7 @@ class IOutputParser;
It should be used as a base class if your buildstep just needs to run a process.
Usage:
- Use setCommand(), setArguments(), setWorkingDirectory() to specify the process you want to run
+ Use processParameters() to configure the process you want to run
(you need to do that before calling AbstractProcessStep::init()).
Inside YourBuildStep::init() call AbstractProcessStep::init().
Inside YourBuildStep::run() call AbstractProcessStep::run(), which automatically starts the proces
@@ -86,34 +88,19 @@ public:
virtual BuildStepConfigWidget *createConfigWidget() = 0;
virtual bool immutable() const = 0;
- /// setCommand() sets the executable to run in the \p buildConfiguration
- /// should be called from init()
- void setCommand(const QString &cmd);
- QString command() const;
-
- /// sets the workingDirectory for the process for a buildConfiguration
- /// should be called from init()
- void setWorkingDirectory(const QString &workingDirectory);
-
- /// sets the command line arguments used by the process for a \p buildConfiguration
- /// should be called from init()
- void setArguments(const QStringList &arguments);
- QStringList arguments() const;
-
/// enables or disables a BuildStep
/// Disabled BuildSteps immediately return true from their run method
/// should be called from init()
- void setEnabled(bool b);
+ void setEnabled(bool b) { m_enabled = b; }
+
+ /// obtain a reference to the parameters for the actual process to run.
+ /// should be used in init()
+ ProcessParameters *processParameters() { return &m_param; }
/// If ignoreReturnValue is set to true, then the abstractprocess step will
/// return success even if the return value indicates otherwise
/// should be called from init
void setIgnoreReturnValue(bool b);
- /// Set the Environment for running the command
- /// should be called from init()
- void setEnvironment(Utils::Environment env);
-
- QString workingDirectory() const;
// derived classes needs to call this function
/// Delete all existing output parsers and start a new chain with the
@@ -127,9 +114,6 @@ protected:
AbstractProcessStep(BuildStepList *bsl, const QString &id);
AbstractProcessStep(BuildStepList *bsl, AbstractProcessStep *bs);
- /// Get the fully expanded command name to run:
- QString expandedCommand() const;
-
/// Called after the process is started
/// the default implementation adds a process started message to the output message
virtual void processStarted();
@@ -159,18 +143,15 @@ private slots:
void taskAdded(const ProjectExplorer::Task &task);
void outputAdded(const QString &string, ProjectExplorer::BuildStep::OutputFormat format);
-private:
+private:
QTimer *m_timer;
QFutureInterface<bool> *m_futureInterface;
- QString m_workingDirectory;
- QString m_command;
- QStringList m_arguments;
+ ProcessParameters m_param;
bool m_enabled;
bool m_ignoreReturnValue;
- QProcess *m_process;
+ Utils::QtcProcess *m_process;
QEventLoop *m_eventLoop;
- Utils::Environment m_environment;
ProjectExplorer::IOutputParser *m_outputParserChain;
};
diff --git a/src/plugins/projectexplorer/allprojectsfilter.h b/src/plugins/projectexplorer/allprojectsfilter.h
index 8b545f6e83..e7bc575237 100644
--- a/src/plugins/projectexplorer/allprojectsfilter.h
+++ b/src/plugins/projectexplorer/allprojectsfilter.h
@@ -38,7 +38,6 @@
#include <QtCore/QFutureInterface>
#include <QtCore/QString>
-#include <QtGui/QWidget>
namespace ProjectExplorer {
diff --git a/src/plugins/projectexplorer/allprojectsfind.cpp b/src/plugins/projectexplorer/allprojectsfind.cpp
index d01cb995b7..541889f6c7 100644
--- a/src/plugins/projectexplorer/allprojectsfind.cpp
+++ b/src/plugins/projectexplorer/allprojectsfind.cpp
@@ -36,13 +36,15 @@
#include "project.h"
#include "session.h"
#include "projectexplorer.h"
+#include "editorconfiguration.h"
#include <utils/qtcassert.h>
+#include <texteditor/itexteditor.h>
+#include <coreplugin/editormanager/editormanager.h>
-#include <QtCore/QDebug>
-#include <QtCore/QFileInfo>
#include <QtCore/QSettings>
#include <QtCore/QRegExp>
+
#include <QtGui/QGridLayout>
#include <QtGui/QLabel>
@@ -76,33 +78,46 @@ bool AllProjectsFind::isEnabled() const
&& m_plugin->session()->projects().count() > 0;
}
-Utils::FileIterator *AllProjectsFind::files()
+QList<Project *> AllProjectsFind::projects() const
{
Q_ASSERT(m_plugin->session());
+ return m_plugin->session()->projects();
+}
+
+Utils::FileIterator *AllProjectsFind::files() const
+{
QList<QRegExp> filterRegs;
QStringList nameFilters = fileNameFilters();
foreach (const QString &filter, nameFilters) {
filterRegs << QRegExp(filter, Qt::CaseInsensitive, QRegExp::Wildcard);
}
- QStringList files;
- QStringList projectFiles;
- foreach (const Project *project, m_plugin->session()->projects()) {
- projectFiles = project->files(Project::AllFiles);
+ QMap<QString, QTextCodec *> openEditorEncodings = TextEditor::ITextEditor::openedTextEditorsEncodings();
+ QMap<QString, QTextCodec *> encodings;
+ foreach (const Project *project, projects()) {
+ QStringList projectFiles = project->files(Project::AllFiles);
+ QStringList filteredFiles;
if (!filterRegs.isEmpty()) {
foreach (const QString &file, projectFiles) {
foreach (const QRegExp &reg, filterRegs) {
if (reg.exactMatch(file) || reg.exactMatch(QFileInfo(file).fileName())) {
- files.append(file);
+ filteredFiles.append(file);
break;
}
}
}
} else {
- files += projectFiles;
+ filteredFiles = projectFiles;
+ }
+ foreach (const QString &fileName, filteredFiles) {
+ QTextCodec *codec = openEditorEncodings.value(fileName);
+ if (!codec)
+ codec = project->editorConfiguration()->defaultTextCodec();
+ if (!codec)
+ codec = Core::EditorManager::instance()->defaultTextEncoding();
+ encodings.insert(fileName, codec);
}
}
- files.removeDuplicates();
- return new Utils::FileIterator(files);
+ return new Utils::FileIterator(encodings.keys(), encodings.values());
}
QWidget *AllProjectsFind::createConfigWidget()
diff --git a/src/plugins/projectexplorer/allprojectsfind.h b/src/plugins/projectexplorer/allprojectsfind.h
index 9a1ccd73f2..6dd9d78fb2 100644
--- a/src/plugins/projectexplorer/allprojectsfind.h
+++ b/src/plugins/projectexplorer/allprojectsfind.h
@@ -34,16 +34,14 @@
#ifndef ALLPROJECTSFIND_H
#define ALLPROJECTSFIND_H
-#include <find/ifindfilter.h>
-#include <find/searchresultwindow.h>
#include <texteditor/basefilefind.h>
#include <QtCore/QPointer>
-
namespace ProjectExplorer {
class ProjectExplorerPlugin;
+class Project;
namespace Internal {
@@ -64,7 +62,8 @@ public:
void readSettings(QSettings *settings);
protected:
- Utils::FileIterator *files();
+ virtual QList<Project *> projects() const;
+ Utils::FileIterator *files() const;
private:
ProjectExplorerPlugin *m_plugin;
diff --git a/src/plugins/projectexplorer/applicationlauncher.h b/src/plugins/projectexplorer/applicationlauncher.h
index ffdad99521..d4432fa77c 100644
--- a/src/plugins/projectexplorer/applicationlauncher.h
+++ b/src/plugins/projectexplorer/applicationlauncher.h
@@ -36,12 +36,10 @@
#include "projectexplorer_export.h"
-#include <QtCore/QObject>
-#include <QtCore/QStringList>
#include <QtCore/QProcess>
namespace Utils {
-class ConsoleProcess;
+class Environment;
}
namespace ProjectExplorer {
@@ -61,10 +59,10 @@ public:
~ApplicationLauncher();
void setWorkingDirectory(const QString &dir);
- void setEnvironment(const QStringList &env);
+ void setEnvironment(const Utils::Environment &env);
void start(Mode mode, const QString &program,
- const QStringList &args = QStringList());
+ const QString &args = QString());
void stop();
bool isRunning() const;
qint64 applicationPID() const;
diff --git a/src/plugins/projectexplorer/applicationlauncher_win.cpp b/src/plugins/projectexplorer/applicationlauncher_win.cpp
index 4958242af3..1177202a0d 100644
--- a/src/plugins/projectexplorer/applicationlauncher_win.cpp
+++ b/src/plugins/projectexplorer/applicationlauncher_win.cpp
@@ -73,13 +73,13 @@ void ApplicationLauncher::setWorkingDirectory(const QString &dir)
d->m_consoleProcess.setWorkingDirectory(dir);
}
-void ApplicationLauncher::setEnvironment(const QStringList &env)
+void ApplicationLauncher::setEnvironment(const Utils::Environment &env)
{
d->m_winGuiProcess.setEnvironment(env);
d->m_consoleProcess.setEnvironment(env);
}
-void ApplicationLauncher::start(Mode mode, const QString &program, const QStringList &args)
+void ApplicationLauncher::start(Mode mode, const QString &program, const QString &args)
{
d->m_currentMode = mode;
if (mode == Gui) {
diff --git a/src/plugins/projectexplorer/applicationlauncher_x11.cpp b/src/plugins/projectexplorer/applicationlauncher_x11.cpp
index d6d5725ae7..af39cff76c 100644
--- a/src/plugins/projectexplorer/applicationlauncher_x11.cpp
+++ b/src/plugins/projectexplorer/applicationlauncher_x11.cpp
@@ -36,6 +36,8 @@
#include <coreplugin/icore.h>
+#include <utils/qtcprocess.h>
+
#include <QtCore/QTimer>
#include <QtCore/QTextCodec>
@@ -44,7 +46,7 @@ namespace ProjectExplorer {
struct ApplicationLauncherPrivate {
ApplicationLauncherPrivate();
- QProcess m_guiProcess;
+ Utils::QtcProcess m_guiProcess;
Utils::ConsoleProcess m_consoleProcess;
ApplicationLauncher::Mode m_currentMode;
@@ -91,17 +93,18 @@ void ApplicationLauncher::setWorkingDirectory(const QString &dir)
d->m_consoleProcess.setWorkingDirectory(dir);
}
-void ApplicationLauncher::setEnvironment(const QStringList &env)
+void ApplicationLauncher::setEnvironment(const Utils::Environment &env)
{
d->m_guiProcess.setEnvironment(env);
d->m_consoleProcess.setEnvironment(env);
}
-void ApplicationLauncher::start(Mode mode, const QString &program, const QStringList &args)
+void ApplicationLauncher::start(Mode mode, const QString &program, const QString &args)
{
d->m_currentMode = mode;
if (mode == Gui) {
- d->m_guiProcess.start(program, args);
+ d->m_guiProcess.setCommand(program, args);
+ d->m_guiProcess.start();
} else {
d->m_consoleProcess.start(program, args);
}
diff --git a/src/plugins/projectexplorer/applicationrunconfiguration.cpp b/src/plugins/projectexplorer/applicationrunconfiguration.cpp
index 018192f51f..1123b565ab 100644
--- a/src/plugins/projectexplorer/applicationrunconfiguration.cpp
+++ b/src/plugins/projectexplorer/applicationrunconfiguration.cpp
@@ -32,17 +32,13 @@
**************************************************************************/
#include "applicationrunconfiguration.h"
+#include "buildconfiguration.h"
-#include "environment.h"
+#include <coreplugin/variablemanager.h>
-#include <projectexplorer/projectexplorerconstants.h>
-#include <utils/qtcassert.h>
+#include <utils/stringutils.h>
-#include <QtCore/QDir>
-#include <QtGui/QLabel>
-
-using namespace ProjectExplorer;
-using namespace ProjectExplorer::Internal;
+namespace ProjectExplorer {
/// LocalApplicationRunConfiguration
@@ -60,102 +56,26 @@ LocalApplicationRunConfiguration::~LocalApplicationRunConfiguration()
{
}
-/// LocalApplicationRunControlFactory
-
-LocalApplicationRunControlFactory::LocalApplicationRunControlFactory()
-{
-}
+namespace Internal {
-LocalApplicationRunControlFactory::~LocalApplicationRunControlFactory()
-{
-}
+class VarManMacroExpander : public Utils::AbstractQtcMacroExpander {
+public:
+ virtual bool resolveMacro(const QString &name, QString *ret)
+ {
+ *ret = Core::VariableManager::instance()->value(name);
+ return !ret->isEmpty();
+ }
+};
-bool LocalApplicationRunControlFactory::canRun(ProjectExplorer::RunConfiguration *runConfiguration, const QString &mode) const
-{
- return (mode == ProjectExplorer::Constants::RUNMODE)
- && (qobject_cast<LocalApplicationRunConfiguration *>(runConfiguration) != 0);
-}
-
-QString LocalApplicationRunControlFactory::displayName() const
-{
- return tr("Run");
-}
+} // namespace Internal
-RunControl *LocalApplicationRunControlFactory::create(ProjectExplorer::RunConfiguration *runConfiguration, const QString &mode)
+Utils::AbstractMacroExpander *LocalApplicationRunConfiguration::macroExpander() const
{
- QTC_ASSERT(canRun(runConfiguration, mode), return 0);
- return new LocalApplicationRunControl(qobject_cast<LocalApplicationRunConfiguration *>(runConfiguration), mode);
-}
-
-QWidget *LocalApplicationRunControlFactory::createConfigurationWidget(RunConfiguration *runConfiguration)
-{
- Q_UNUSED(runConfiguration)
- return new QLabel("TODO add Configuration widget");
-}
-
-// ApplicationRunControl
-
-LocalApplicationRunControl::LocalApplicationRunControl(LocalApplicationRunConfiguration *rc, QString mode)
- : RunControl(rc, mode)
-{
- Utils::Environment env = rc->environment();
- QString dir = rc->workingDirectory();
- m_applicationLauncher.setEnvironment(env.toStringList());
- m_applicationLauncher.setWorkingDirectory(dir);
-
- m_executable = rc->executable();
- m_runMode = static_cast<ApplicationLauncher::Mode>(rc->runMode());
- m_commandLineArguments = rc->commandLineArguments();
-
- connect(&m_applicationLauncher, SIGNAL(appendMessage(QString,bool)),
- this, SLOT(slotAppendMessage(QString,bool)));
- connect(&m_applicationLauncher, SIGNAL(appendOutput(QString, bool)),
- this, SLOT(slotAddToOutputWindow(QString, bool)));
- connect(&m_applicationLauncher, SIGNAL(processExited(int)),
- this, SLOT(processExited(int)));
- connect(&m_applicationLauncher, SIGNAL(bringToForegroundRequested(qint64)),
- this, SLOT(bringApplicationToForeground(qint64)));
-}
+ if (BuildConfiguration *bc = activeBuildConfiguration())
+ return bc->macroExpander();
-LocalApplicationRunControl::~LocalApplicationRunControl()
-{
-}
-
-void LocalApplicationRunControl::start()
-{
- m_applicationLauncher.start(m_runMode, m_executable, m_commandLineArguments);
- emit started();
-
- emit appendMessage(this, tr("Starting %1...").arg(QDir::toNativeSeparators(m_executable)), false);
-}
-
-LocalApplicationRunControl::StopResult LocalApplicationRunControl::stop()
-{
- m_applicationLauncher.stop();
- return StoppedSynchronously;
-}
-
-bool LocalApplicationRunControl::isRunning() const
-{
- return m_applicationLauncher.isRunning();
-}
-
-void LocalApplicationRunControl::slotAppendMessage(const QString &err,
- bool isError)
-{
- emit appendMessage(this, err, isError);
- emit finished();
-}
-
-void LocalApplicationRunControl::slotAddToOutputWindow(const QString &line,
- bool isError)
-{
- emit addToOutputWindowInline(this, line, isError);
-}
-
-void LocalApplicationRunControl::processExited(int exitCode)
-{
- emit appendMessage(this, tr("%1 exited with code %2").arg(QDir::toNativeSeparators(m_executable)).arg(exitCode), false);
- emit finished();
+ static Internal::VarManMacroExpander mx;
+ return &mx;
}
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/applicationrunconfiguration.h b/src/plugins/projectexplorer/applicationrunconfiguration.h
index 9b9d37b5fc..dcb1329d08 100644
--- a/src/plugins/projectexplorer/applicationrunconfiguration.h
+++ b/src/plugins/projectexplorer/applicationrunconfiguration.h
@@ -34,12 +34,13 @@
#ifndef APPLICATIONRUNCONFIGURATION_H
#define APPLICATIONRUNCONFIGURATION_H
-#include <projectexplorer/toolchain.h>
+#include <projectexplorer/toolchaintype.h>
#include "runconfiguration.h"
#include "applicationlauncher.h"
namespace Utils {
+class AbstractMacroExpander;
class Environment;
}
@@ -58,52 +59,19 @@ public:
virtual QString executable() const = 0;
virtual RunMode runMode() const = 0;
virtual QString workingDirectory() const = 0;
- virtual QStringList commandLineArguments() const = 0;
+ virtual QString commandLineArguments() const = 0;
virtual Utils::Environment environment() const = 0;
virtual QString dumperLibrary() const = 0;
virtual QStringList dumperLibraryLocations() const = 0;
- virtual ProjectExplorer::ToolChain::ToolChainType toolChainType() const = 0;
+ virtual ProjectExplorer::ToolChainType toolChainType() const = 0;
protected:
- LocalApplicationRunConfiguration(Target *target, const QString &id);
- LocalApplicationRunConfiguration(Target *target, LocalApplicationRunConfiguration *rc);
-};
-
-namespace Internal {
-
-class LocalApplicationRunControlFactory : public IRunControlFactory
-{
- Q_OBJECT
-public:
- LocalApplicationRunControlFactory ();
- virtual ~LocalApplicationRunControlFactory();
- virtual bool canRun(RunConfiguration *runConfiguration, const QString &mode) const;
- virtual QString displayName() const;
- virtual RunControl* create(RunConfiguration *runConfiguration, const QString &mode);
- virtual QWidget *createConfigurationWidget(RunConfiguration *runConfiguration);
-};
+ explicit LocalApplicationRunConfiguration(Target *target, const QString &id);
+ explicit LocalApplicationRunConfiguration(Target *target, LocalApplicationRunConfiguration *rc);
-class LocalApplicationRunControl : public RunControl
-{
- Q_OBJECT
-public:
- LocalApplicationRunControl(LocalApplicationRunConfiguration *runConfiguration, QString mode);
- virtual ~LocalApplicationRunControl();
- virtual void start();
- virtual StopResult stop();
- virtual bool isRunning() const;
-private slots:
- void processExited(int exitCode);
- void slotAddToOutputWindow(const QString &line, bool isError);
- void slotAppendMessage(const QString &err, bool isError);
-private:
- ProjectExplorer::ApplicationLauncher m_applicationLauncher;
- QString m_executable;
- QStringList m_commandLineArguments;
- ProjectExplorer::ApplicationLauncher::Mode m_runMode;
+ Utils::AbstractMacroExpander *macroExpander() const;
};
-} // namespace Internal
} // namespace ProjectExplorer
#endif // APPLICATIONRUNCONFIGURATION_H
diff --git a/src/plugins/projectexplorer/baseprojectwizarddialog.cpp b/src/plugins/projectexplorer/baseprojectwizarddialog.cpp
index 0d06d89feb..b7768692ac 100644
--- a/src/plugins/projectexplorer/baseprojectwizarddialog.cpp
+++ b/src/plugins/projectexplorer/baseprojectwizarddialog.cpp
@@ -48,14 +48,12 @@ struct BaseProjectWizardDialogPrivate {
const int desiredIntroPageId;
Utils::ProjectIntroPage *introPage;
int introPageId;
- int lastId;
};
BaseProjectWizardDialogPrivate::BaseProjectWizardDialogPrivate(Utils::ProjectIntroPage *page, int id) :
desiredIntroPageId(id),
introPage(page),
- introPageId(-1),
- lastId(-1)
+ introPageId(-1)
{
}
@@ -86,7 +84,7 @@ void BaseProjectWizardDialog::init()
}
wizardProgress()->item(d->introPageId)->setTitle(tr("Location"));
connect(this, SIGNAL(accepted()), this, SLOT(slotAccepted()));
- connect(this, SIGNAL(currentIdChanged(int)), this, SLOT(slotBaseCurrentIdChanged(int)));
+ connect(this, SIGNAL(nextClicked()), this, SLOT(nextClicked()));
}
BaseProjectWizardDialog::~BaseProjectWizardDialog()
@@ -129,12 +127,11 @@ void BaseProjectWizardDialog::slotAccepted()
}
}
-void BaseProjectWizardDialog::slotBaseCurrentIdChanged(int id)
+void BaseProjectWizardDialog::nextClicked()
{
- if (d->lastId == d->introPageId) {
- emit introPageLeft(d->introPage->projectName(), d->introPage->path());
+ if (currentId() == d->introPageId) {
+ emit projectParametersChanged(d->introPage->projectName(), d->introPage->path());
}
- d->lastId = id;
}
Utils::ProjectIntroPage *BaseProjectWizardDialog::introPage() const
diff --git a/src/plugins/projectexplorer/baseprojectwizarddialog.h b/src/plugins/projectexplorer/baseprojectwizarddialog.h
index e363e535bc..7490cb5666 100644
--- a/src/plugins/projectexplorer/baseprojectwizarddialog.h
+++ b/src/plugins/projectexplorer/baseprojectwizarddialog.h
@@ -77,14 +77,14 @@ public slots:
void setProjectName(const QString &name);
signals:
- void introPageLeft(const QString &projectName, const QString &path);
+ void projectParametersChanged(const QString &projectName, const QString &path);
protected:
Utils::ProjectIntroPage *introPage() const;
private slots:
void slotAccepted();
- void slotBaseCurrentIdChanged(int);
+ void nextClicked();
private:
void init();
diff --git a/src/plugins/projectexplorer/buildconfigdialog.cpp b/src/plugins/projectexplorer/buildconfigdialog.cpp
deleted file mode 100644
index 784e5bcd46..0000000000
--- a/src/plugins/projectexplorer/buildconfigdialog.cpp
+++ /dev/null
@@ -1,124 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#include "buildconfigdialog.h"
-#include "project.h"
-#include "runconfiguration.h"
-#include "buildconfiguration.h"
-#include "target.h"
-
-#include <QtGui/QVBoxLayout>
-#include <QtGui/QPushButton>
-#include <QtGui/QDialogButtonBox>
-#include <QtGui/QLabel>
-#include <QtGui/QComboBox>
-#include <QtGui/QFormLayout>
-
-namespace ProjectExplorer {
-namespace Internal {
-
-BuildConfigDialog::BuildConfigDialog(Project *project, QWidget *parent)
- : QDialog(parent),
- m_project(project)
-{
- QVBoxLayout *vlayout = new QVBoxLayout;
- setLayout(vlayout);
- QDialogButtonBox *buttonBox = new QDialogButtonBox;
- m_changeBuildConfiguration = buttonBox->addButton(tr("Change build configuration && continue"),
- QDialogButtonBox::ActionRole);
- m_cancel = buttonBox->addButton(tr("Cancel"),
- QDialogButtonBox::RejectRole);
- m_justContinue = buttonBox->addButton(tr("Continue anyway"),
- QDialogButtonBox::AcceptRole);
- connect(m_changeBuildConfiguration, SIGNAL(clicked()), this, SLOT(buttonClicked()));
- connect(m_cancel, SIGNAL(clicked()), this, SLOT(buttonClicked()));
- connect(m_justContinue, SIGNAL(clicked()), this, SLOT(buttonClicked()));
- setWindowTitle(tr("Run configuration does not match build configuration"));
- QLabel *shortText = new QLabel(tr(
- "The active build configuration builds a target "
- "that cannot be used by the active run configuration."
- ));
- vlayout->addWidget(shortText);
- QLabel *descriptiveText = new QLabel(tr(
- "This can happen if the active build configuration "
- "uses the wrong Qt version and/or tool chain for the active run configuration "
- "(for example, running in Symbian emulator requires building with the WINSCW tool chain)."
- ));
- descriptiveText->setWordWrap(true);
- vlayout->addWidget(descriptiveText);
- m_configCombo = new QComboBox;
-
- RunConfiguration *activeRun = m_project->activeTarget()->activeRunConfiguration();
- foreach (BuildConfiguration *config, m_project->activeTarget()->buildConfigurations()) {
- if (activeRun->isEnabled(config)) {
- m_configCombo->addItem(config->displayName(), QVariant::fromValue(config));
- }
- }
- if (m_configCombo->count() == 0) {
- m_configCombo->addItem(tr("No valid build configuration found."));
- m_configCombo->setEnabled(false);
- m_changeBuildConfiguration->setEnabled(false);
- }
-
- QFormLayout *formlayout = new QFormLayout;
- formlayout->addRow(tr("Active run configuration"),
- // ^ avoiding a new translatable string for active run configuration
- new QLabel(activeRun->displayName()));
- formlayout->addRow(tr("Choose build configuration:"), m_configCombo);
- vlayout->addLayout(formlayout);
- vlayout->addWidget(buttonBox);
- m_cancel->setDefault(true);
-}
-
-BuildConfiguration *BuildConfigDialog::selectedBuildConfiguration() const
-{
- int index = m_configCombo->currentIndex();
- if (index < 0)
- return 0;
- return m_configCombo->itemData(index, Qt::UserRole).value<BuildConfiguration*>();
-}
-
-void BuildConfigDialog::buttonClicked()
-{
- QPushButton *button = qobject_cast<QPushButton *>(sender());
- if (button == m_changeBuildConfiguration) {
- done(ChangeBuild);
- } else if (button == m_cancel) {
- done(Cancel);
- } else if (button == m_justContinue) {
- done(Continue);
- }
-}
-
-} // namespace Internal
-} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/buildconfigdialog.h b/src/plugins/projectexplorer/buildconfigdialog.h
deleted file mode 100644
index 26ab581dea..0000000000
--- a/src/plugins/projectexplorer/buildconfigdialog.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#ifndef BUILDCONFIGDIALOG_H
-#define BUILDCONFIGDIALOG_H
-
-#include <QtGui/QDialog>
-
-QT_BEGIN_NAMESPACE
-class QAction;
-class QComboBox;
-QT_END_NAMESPACE
-
-namespace ProjectExplorer {
-class Project;
-class BuildConfiguration;
-
-namespace Internal {
-
-class BuildConfigDialog : public QDialog
-{
- Q_OBJECT
-public:
- enum DialogResult {
- ChangeBuild = 10,
- Cancel = 11,
- Continue = 12
- };
- explicit BuildConfigDialog(Project *project, QWidget *parent = 0);
-
- BuildConfiguration *selectedBuildConfiguration() const;
-
-private slots:
- void buttonClicked();
-
-private:
- Project *m_project;
- QPushButton *m_changeBuildConfiguration;
- QPushButton *m_cancel;
- QPushButton *m_justContinue;
- QComboBox *m_configCombo;
-};
-
-} // namespace Internal
-} // namespace ProjectExplorer
-
-#endif // BUILDCONFIGDIALOG_H
diff --git a/src/plugins/projectexplorer/buildconfiguration.cpp b/src/plugins/projectexplorer/buildconfiguration.cpp
index a8378fb6ec..319d58e311 100644
--- a/src/plugins/projectexplorer/buildconfiguration.cpp
+++ b/src/plugins/projectexplorer/buildconfiguration.cpp
@@ -40,6 +40,8 @@
#include "target.h"
#include "project.h"
+#include <coreplugin/variablemanager.h>
+
#include <QtCore/QProcess>
using namespace ProjectExplorer;
@@ -55,7 +57,8 @@ const char * const USER_ENVIRONMENT_CHANGES_KEY("ProjectExplorer.BuildConfigurat
BuildConfiguration::BuildConfiguration(Target *target, const QString &id) :
ProjectConfiguration(target, id),
- m_clearSystemEnvironment(false)
+ m_clearSystemEnvironment(false),
+ m_macroExpander(this)
{
Q_ASSERT(target);
BuildStepList *bsl = new BuildStepList(this, QLatin1String(Constants::BUILDSTEPS_BUILD));
@@ -71,7 +74,8 @@ BuildConfiguration::BuildConfiguration(Target *target, const QString &id) :
BuildConfiguration::BuildConfiguration(Target *target, BuildConfiguration *source) :
ProjectConfiguration(target, source),
m_clearSystemEnvironment(source->m_clearSystemEnvironment),
- m_userEnvironmentChanges(source->m_userEnvironmentChanges)
+ m_userEnvironmentChanges(source->m_userEnvironmentChanges),
+ m_macroExpander(this)
{
Q_ASSERT(target);
// Do not clone stepLists here, do that in the derived constructor instead
@@ -152,10 +156,6 @@ Utils::Environment BuildConfiguration::baseEnvironment() const
Utils::Environment result;
if (useSystemEnvironment())
result = Utils::Environment(QProcess::systemEnvironment());
-
- result.set(QLatin1String("BUILDDIR"), QDir::toNativeSeparators(target()->project()->projectDirectory()));
- result.set(QLatin1String("SOURCEDIR"), QDir::toNativeSeparators(target()->project()->projectDirectory()));
-
return result;
}
@@ -211,6 +211,20 @@ void BuildConfiguration::cloneSteps(BuildConfiguration *source)
}
}
+bool BuildConfigMacroExpander::resolveMacro(const QString &name, QString *ret)
+{
+ if (name == QLatin1String("sourceDir")) {
+ *ret = QDir::toNativeSeparators(m_bc->target()->project()->projectDirectory());
+ return true;
+ }
+ if (name == QLatin1String("buildDir")) {
+ *ret = QDir::toNativeSeparators(m_bc->buildDirectory());
+ return true;
+ }
+ *ret = Core::VariableManager::instance()->value(name);
+ return !ret->isEmpty();
+}
+
///
// IBuildConfigurationFactory
///
diff --git a/src/plugins/projectexplorer/buildconfiguration.h b/src/plugins/projectexplorer/buildconfiguration.h
index 695a92a6f5..7ea8778f3d 100644
--- a/src/plugins/projectexplorer/buildconfiguration.h
+++ b/src/plugins/projectexplorer/buildconfiguration.h
@@ -35,22 +35,31 @@
#define BUILDCONFIGURATION_H
#include "projectexplorer_export.h"
+#include "projectconfiguration.h"
+#include <utils/stringutils.h>
#include <utils/environment.h>
#include <QtCore/QString>
#include <QtCore/QStringList>
-#include <QtCore/QList>
-#include <QtCore/QObject>
-#include "projectconfiguration.h"
+
namespace ProjectExplorer {
+class BuildConfiguration;
class BuildStepList;
class Target;
class IOutputParser;
+class BuildConfigMacroExpander : public Utils::AbstractQtcMacroExpander {
+public:
+ BuildConfigMacroExpander(BuildConfiguration *bc) : m_bc(bc) {}
+ virtual bool resolveMacro(const QString &name, QString *ret);
+private:
+ BuildConfiguration *m_bc;
+};
+
class PROJECTEXPLORER_EXPORT BuildConfiguration : public ProjectConfiguration
{
Q_OBJECT
@@ -84,6 +93,8 @@ public:
Target *target() const;
+ Utils::AbstractMacroExpander *macroExpander() { return &m_macroExpander; }
+
signals:
void environmentChanged();
void buildDirectoryChanged();
@@ -100,6 +111,7 @@ private:
bool m_clearSystemEnvironment;
QList<Utils::EnvironmentItem> m_userEnvironmentChanges;
QList<BuildStepList *> m_stepLists;
+ BuildConfigMacroExpander m_macroExpander;
};
class PROJECTEXPLORER_EXPORT IBuildConfigurationFactory :
@@ -130,6 +142,9 @@ signals:
} // namespace ProjectExplorer
-Q_DECLARE_METATYPE(ProjectExplorer::BuildConfiguration *);
+Q_DECLARE_METATYPE(ProjectExplorer::BuildConfiguration *)
+
+// Default directory to run custom (build) commands in.
+#define DEFAULT_WORKING_DIR "%{buildDir}"
#endif // BUILDCONFIGURATION_H
diff --git a/src/plugins/projectexplorer/buildsettingspropertiespage.cpp b/src/plugins/projectexplorer/buildsettingspropertiespage.cpp
index 5198bac472..19aae3e7e6 100644
--- a/src/plugins/projectexplorer/buildsettingspropertiespage.cpp
+++ b/src/plugins/projectexplorer/buildsettingspropertiespage.cpp
@@ -262,7 +262,7 @@ void BuildSettingsWidget::updateBuildSettings()
m_removeButton->setEnabled(m_target->buildConfigurations().size() > 1);
// Add pages
- BuildConfigWidget *generalConfigWidget = m_target->project()->createConfigWidget();
+ BuildConfigWidget *generalConfigWidget = m_target->createConfigWidget();
addSubWidget(generalConfigWidget);
addSubWidget(new BuildStepsPage(m_target, QLatin1String(Constants::BUILDSTEPS_BUILD)));
diff --git a/src/plugins/projectexplorer/buildsettingspropertiespage.h b/src/plugins/projectexplorer/buildsettingspropertiespage.h
index 95256b0f98..2743bb0e06 100644
--- a/src/plugins/projectexplorer/buildsettingspropertiespage.h
+++ b/src/plugins/projectexplorer/buildsettingspropertiespage.h
@@ -37,6 +37,7 @@
#include "iprojectproperties.h"
#include <QtGui/QWidget>
+#include <QtGui/QIcon>
QT_BEGIN_NAMESPACE
class QComboBox;
diff --git a/src/plugins/projectexplorer/buildsteplist.h b/src/plugins/projectexplorer/buildsteplist.h
index 2e1187d6d1..719ab323aa 100644
--- a/src/plugins/projectexplorer/buildsteplist.h
+++ b/src/plugins/projectexplorer/buildsteplist.h
@@ -87,6 +87,6 @@ private:
} // namespace ProjectExplorer
-Q_DECLARE_METATYPE(ProjectExplorer::BuildStepList *);
+Q_DECLARE_METATYPE(ProjectExplorer::BuildStepList *)
#endif // PROJECTEXPLORER_BUILDSTEPLIST_H
diff --git a/src/plugins/projectexplorer/buildstepspage.cpp b/src/plugins/projectexplorer/buildstepspage.cpp
index b7432e4985..0982a9a3db 100644
--- a/src/plugins/projectexplorer/buildstepspage.cpp
+++ b/src/plugins/projectexplorer/buildstepspage.cpp
@@ -42,6 +42,7 @@
#include <coreplugin/icore.h>
#include <extensionsystem/pluginmanager.h>
#include <utils/qtcassert.h>
+#include <utils/detailswidget.h>
#include <QtCore/QSignalMapper>
@@ -167,11 +168,7 @@ void BuildStepListWidget::addBuildStepWidget(int pos, BuildStep *step)
// layout
Utils::FadingPanel *toolWidget = new Utils::FadingPanel(s.detailsWidget);
-#ifdef Q_WS_MAC
- QSize buttonSize(20, 20);
-#else
QSize buttonSize(20, 26);
-#endif
s.upButton = new QToolButton(toolWidget);
s.upButton->setAutoRaise(true);
diff --git a/src/plugins/projectexplorer/buildstepspage.h b/src/plugins/projectexplorer/buildstepspage.h
index bd3ac5b0e1..d2ae10cb56 100644
--- a/src/plugins/projectexplorer/buildstepspage.h
+++ b/src/plugins/projectexplorer/buildstepspage.h
@@ -38,8 +38,6 @@
#include "deployconfiguration.h"
#include "namedwidget.h"
-#include <utils/detailswidget.h>
-
QT_BEGIN_NAMESPACE
class QPushButton;
class QToolButton;
@@ -48,6 +46,10 @@ class QVBoxLayout;
class QSignalMapper;
QT_END_NAMESPACE
+namespace Utils {
+class DetailsWidget;
+}
+
namespace ProjectExplorer {
class Target;
diff --git a/src/plugins/projectexplorer/copytaskhandler.cpp b/src/plugins/projectexplorer/copytaskhandler.cpp
index d5fdd8c35d..03f88ce4df 100644
--- a/src/plugins/projectexplorer/copytaskhandler.cpp
+++ b/src/plugins/projectexplorer/copytaskhandler.cpp
@@ -37,6 +37,7 @@
#include <coreplugin/coreconstants.h>
+#include <QtCore/QDir>
#include <QtGui/QAction>
#include <QtGui/QApplication>
#include <QtGui/QClipboard>
@@ -52,16 +53,18 @@ void CopyTaskHandler::handle(const ProjectExplorer::Task &task)
QString type;
switch (task.type) {
case Task::Error:
- type = tr("error: ", "Task is of type error");
+ //: Task is of type: error
+ type = tr("error: ");
break;
case Task::Warning:
- type = tr("warning: ", "Task is of type warning");
+ //: Task is of type: warning
+ type = tr("warning: ");
break;
default:
break;
}
- QApplication::clipboard()->setText(task.file + ':' +
+ QApplication::clipboard()->setText(QDir::toNativeSeparators(task.file) + ':' +
QString::number(task.line) + ": "
+ type + task.description);
}
diff --git a/src/plugins/projectexplorer/copytaskhandler.h b/src/plugins/projectexplorer/copytaskhandler.h
index f3ad9e4081..31cee5f9e8 100644
--- a/src/plugins/projectexplorer/copytaskhandler.h
+++ b/src/plugins/projectexplorer/copytaskhandler.h
@@ -34,14 +34,12 @@
#ifndef PROJECTEXPLORER_COPYTASKHANDLER_H
#define PROJECTEXPLORER_COPYTASKHANDLER_H
-#include "projectexplorer_export.h"
-
#include "itaskhandler.h"
namespace ProjectExplorer {
namespace Internal {
-class PROJECTEXPLORER_EXPORT CopyTaskHandler : public ITaskHandler
+class CopyTaskHandler : public ITaskHandler
{
Q_OBJECT
diff --git a/src/plugins/projectexplorer/currentprojectfilter.cpp b/src/plugins/projectexplorer/currentprojectfilter.cpp
index b2f632db7c..c47c0d77ca 100644
--- a/src/plugins/projectexplorer/currentprojectfilter.cpp
+++ b/src/plugins/projectexplorer/currentprojectfilter.cpp
@@ -34,12 +34,8 @@
#include "currentprojectfilter.h"
#include "projectexplorer.h"
#include "project.h"
-#include "session.h"
#include <QtCore/QtDebug>
-#include <QtCore/QThread>
-#include <QtCore/QTimer>
-#include <QtCore/QVariant>
using namespace Core;
using namespace Locator;
diff --git a/src/plugins/projectexplorer/currentprojectfilter.h b/src/plugins/projectexplorer/currentprojectfilter.h
index b309d13cf7..83af636bdf 100644
--- a/src/plugins/projectexplorer/currentprojectfilter.h
+++ b/src/plugins/projectexplorer/currentprojectfilter.h
@@ -36,8 +36,6 @@
#include <locator/basefilefilter.h>
-#include <QtCore/QString>
-#include <QtCore/QByteArray>
#include <QtCore/QFutureInterface>
namespace ProjectExplorer {
diff --git a/src/plugins/projectexplorer/currentprojectfind.cpp b/src/plugins/projectexplorer/currentprojectfind.cpp
index e174e3ee5a..267f84ce2c 100644
--- a/src/plugins/projectexplorer/currentprojectfind.cpp
+++ b/src/plugins/projectexplorer/currentprojectfind.cpp
@@ -34,16 +34,11 @@
#include "currentprojectfind.h"
#include "projectexplorer.h"
-#include "project.h"
#include <utils/qtcassert.h>
#include <QtCore/QDebug>
-#include <QtCore/QFileInfo>
#include <QtCore/QSettings>
-#include <QtCore/QRegExp>
-#include <QtGui/QGridLayout>
-#include <QtGui/QLabel>
using namespace Find;
using namespace ProjectExplorer;
@@ -51,9 +46,8 @@ using namespace ProjectExplorer::Internal;
using namespace TextEditor;
CurrentProjectFind::CurrentProjectFind(ProjectExplorerPlugin *plugin, SearchResultWindow *resultWindow)
- : BaseFileFind(resultWindow),
- m_plugin(plugin),
- m_configWidget(0)
+ : AllProjectsFind(plugin, resultWindow),
+ m_plugin(plugin)
{
connect(m_plugin, SIGNAL(currentProjectChanged(ProjectExplorer::Project*)),
this, SIGNAL(changed()));
@@ -74,50 +68,9 @@ bool CurrentProjectFind::isEnabled() const
return m_plugin->currentProject() != 0 && BaseFileFind::isEnabled();
}
-Utils::FileIterator *CurrentProjectFind::files()
+QList<Project *> CurrentProjectFind::projects() const
{
- Project *project = m_plugin->currentProject();
- Q_ASSERT(project);
- QList<QRegExp> filterRegs;
- QStringList nameFilters = fileNameFilters();
- foreach (const QString &filter, nameFilters) {
- filterRegs << QRegExp(filter, Qt::CaseInsensitive, QRegExp::Wildcard);
- }
- QStringList files;
- if (!filterRegs.isEmpty()) {
- foreach (const QString &file, project->files(Project::AllFiles)) {
- foreach (const QRegExp &reg, filterRegs) {
- if (reg.exactMatch(file) || reg.exactMatch(QFileInfo(file).fileName())) {
- files.append(file);
- break;
- }
- }
- }
- } else {
- files += project->files(Project::AllFiles);
- }
- files.removeDuplicates();
- return new Utils::FileIterator(files);
-}
-
-QWidget *CurrentProjectFind::createConfigWidget()
-{
- if (!m_configWidget) {
- m_configWidget = new QWidget;
- QGridLayout * const layout = new QGridLayout(m_configWidget);
- layout->setMargin(0);
- m_configWidget->setLayout(layout);
- QLabel * const filePatternLabel = new QLabel(tr("File &pattern:"));
- filePatternLabel->setMinimumWidth(80);
- filePatternLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
- filePatternLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
- QWidget *patternWidget = createPatternWidget();
- filePatternLabel->setBuddy(patternWidget);
- layout->addWidget(filePatternLabel, 0, 0, Qt::AlignRight);
- layout->addWidget(patternWidget, 0, 1);
- m_configWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
- }
- return m_configWidget;
+ return QList<Project *>() << m_plugin->currentProject();
}
void CurrentProjectFind::writeSettings(QSettings *settings)
diff --git a/src/plugins/projectexplorer/currentprojectfind.h b/src/plugins/projectexplorer/currentprojectfind.h
index 49448962e0..1b95635ace 100644
--- a/src/plugins/projectexplorer/currentprojectfind.h
+++ b/src/plugins/projectexplorer/currentprojectfind.h
@@ -34,11 +34,7 @@
#ifndef CURRENTPROJECTFIND_H
#define CURRENTPROJECTFIND_H
-#include <find/ifindfilter.h>
-#include <find/searchresultwindow.h>
-#include <texteditor/basefilefind.h>
-
-#include <QtCore/QPointer>
+#include "allprojectsfind.h"
QT_BEGIN_NAMESPACE
class QWidget;
@@ -47,10 +43,11 @@ QT_END_NAMESPACE
namespace ProjectExplorer {
class ProjectExplorerPlugin;
+class Project;
namespace Internal {
-class CurrentProjectFind : public TextEditor::BaseFileFind
+class CurrentProjectFind : public AllProjectsFind
{
Q_OBJECT
@@ -62,16 +59,14 @@ public:
bool isEnabled() const;
- QWidget *createConfigWidget();
void writeSettings(QSettings *settings);
void readSettings(QSettings *settings);
protected:
- Utils::FileIterator *files();
+ QList<Project *> projects() const;
private:
ProjectExplorerPlugin *m_plugin;
- QPointer<QWidget> m_configWidget;
};
} // namespace Internal
diff --git a/src/plugins/projectexplorer/customexecutableconfigurationwidget.cpp b/src/plugins/projectexplorer/customexecutableconfigurationwidget.cpp
new file mode 100644
index 0000000000..c5f78c3023
--- /dev/null
+++ b/src/plugins/projectexplorer/customexecutableconfigurationwidget.cpp
@@ -0,0 +1,265 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "customexecutableconfigurationwidget.h"
+#include "customexecutablerunconfiguration.h"
+#include "target.h"
+#include "project.h"
+#include "environmenteditmodel.h"
+
+#include <utils/detailswidget.h>
+#include <utils/environment.h>
+#include <utils/pathchooser.h>
+#include <utils/debuggerlanguagechooser.h>
+
+#include <QtGui/QCheckBox>
+#include <QtGui/QComboBox>
+#include <QtGui/QFormLayout>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QLabel>
+#include <QtGui/QLineEdit>
+
+namespace ProjectExplorer {
+namespace Internal {
+
+class CustomDirectoryPathChooser : public Utils::PathChooser
+{
+public:
+ CustomDirectoryPathChooser(QWidget *parent)
+ : Utils::PathChooser(parent)
+ {
+ }
+ virtual bool validatePath(const QString &path, QString *errorMessage = 0)
+ {
+ Q_UNUSED(path)
+ Q_UNUSED(errorMessage)
+ return true;
+ }
+};
+
+CustomExecutableConfigurationWidget::CustomExecutableConfigurationWidget(CustomExecutableRunConfiguration *rc)
+ : m_ignoreChange(false), m_runConfiguration(rc)
+{
+ QFormLayout *layout = new QFormLayout;
+ layout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
+ layout->setMargin(0);
+
+ m_executableChooser = new Utils::PathChooser(this);
+ m_executableChooser->setEnvironment(rc->environment());
+ m_executableChooser->setExpectedKind(Utils::PathChooser::Command);
+ layout->addRow(tr("Executable:"), m_executableChooser);
+
+ m_commandLineArgumentsLineEdit = new QLineEdit(this);
+ m_commandLineArgumentsLineEdit->setMinimumWidth(200); // this shouldn't be fixed here...
+ layout->addRow(tr("Arguments:"), m_commandLineArgumentsLineEdit);
+
+ m_workingDirectory = new CustomDirectoryPathChooser(this);
+ m_workingDirectory->setExpectedKind(Utils::PathChooser::Directory);
+ m_workingDirectory->setBaseDirectory(rc->target()->project()->projectDirectory());
+ m_workingDirectory->setEnvironment(rc->environment());
+ layout->addRow(tr("Working directory:"), m_workingDirectory);
+
+ m_useTerminalCheck = new QCheckBox(tr("Run in &Terminal"), this);
+ layout->addRow(QString(), m_useTerminalCheck);
+
+ QWidget *debuggerLabelWidget = new QWidget(this);
+ QVBoxLayout *debuggerLabelLayout = new QVBoxLayout(debuggerLabelWidget);
+ debuggerLabelLayout->setMargin(0);
+ debuggerLabelLayout->setSpacing(0);
+ debuggerLabelWidget->setLayout(debuggerLabelLayout);
+ QLabel *debuggerLabel = new QLabel(tr("Debugger:"), this);
+ debuggerLabelLayout->addWidget(debuggerLabel);
+ debuggerLabelLayout->addStretch(10);
+
+ m_debuggerLanguageChooser = new Utils::DebuggerLanguageChooser(this);
+ layout->addRow(debuggerLabelWidget, m_debuggerLanguageChooser);
+
+ m_debuggerLanguageChooser->setCppChecked(m_runConfiguration->useCppDebugger());
+ m_debuggerLanguageChooser->setQmlChecked(m_runConfiguration->useQmlDebugger());
+ m_debuggerLanguageChooser->setQmlDebugServerPort(m_runConfiguration->qmlDebugServerPort());
+
+ QVBoxLayout *vbox = new QVBoxLayout(this);
+ vbox->setMargin(0);
+
+ m_detailsContainer = new Utils::DetailsWidget(this);
+ m_detailsContainer->setState(Utils::DetailsWidget::NoSummary);
+ vbox->addWidget(m_detailsContainer);
+
+ QWidget *detailsWidget = new QWidget(m_detailsContainer);
+ m_detailsContainer->setWidget(detailsWidget);
+ detailsWidget->setLayout(layout);
+
+ QLabel *environmentLabel = new QLabel(this);
+ environmentLabel->setText(tr("Run Environment"));
+ QFont f = environmentLabel->font();
+ f.setBold(true);
+ f.setPointSizeF(f.pointSizeF() *1.2);
+ environmentLabel->setFont(f);
+ vbox->addWidget(environmentLabel);
+
+ QWidget *baseEnvironmentWidget = new QWidget;
+ QHBoxLayout *baseEnvironmentLayout = new QHBoxLayout(baseEnvironmentWidget);
+ baseEnvironmentLayout->setMargin(0);
+ QLabel *label = new QLabel(tr("Base environment for this runconfiguration:"), this);
+ baseEnvironmentLayout->addWidget(label);
+ m_baseEnvironmentComboBox = new QComboBox(this);
+ m_baseEnvironmentComboBox->addItems(QStringList()
+ << tr("Clean Environment")
+ << tr("System Environment")
+ << tr("Build Environment"));
+ m_baseEnvironmentComboBox->setCurrentIndex(rc->baseEnvironmentBase());
+ connect(m_baseEnvironmentComboBox, SIGNAL(currentIndexChanged(int)),
+ this, SLOT(baseEnvironmentSelected(int)));
+ baseEnvironmentLayout->addWidget(m_baseEnvironmentComboBox);
+ baseEnvironmentLayout->addStretch(10);
+
+ m_environmentWidget = new EnvironmentWidget(this, baseEnvironmentWidget);
+ m_environmentWidget->setBaseEnvironment(rc->baseEnvironment());
+ m_environmentWidget->setBaseEnvironmentText(rc->baseEnvironmentText());
+ m_environmentWidget->setUserChanges(rc->userEnvironmentChanges());
+ vbox->addWidget(m_environmentWidget);
+
+ changed();
+
+ connect(m_executableChooser, SIGNAL(changed(QString)),
+ this, SLOT(executableEdited()));
+ connect(m_commandLineArgumentsLineEdit, SIGNAL(textEdited(const QString&)),
+ this, SLOT(argumentsEdited(const QString&)));
+ connect(m_workingDirectory, SIGNAL(changed(QString)),
+ this, SLOT(workingDirectoryEdited()));
+ connect(m_useTerminalCheck, SIGNAL(toggled(bool)),
+ this, SLOT(termToggled(bool)));
+
+ connect(m_debuggerLanguageChooser, SIGNAL(cppLanguageToggled(bool)),
+ this, SLOT(useCppDebuggerToggled(bool)));
+ connect(m_debuggerLanguageChooser, SIGNAL(qmlLanguageToggled(bool)),
+ this, SLOT(useQmlDebuggerToggled(bool)));
+ connect(m_debuggerLanguageChooser, SIGNAL(qmlDebugServerPortChanged(uint)),
+ this, SLOT(qmlDebugServerPortChanged(uint)));
+
+ connect(m_runConfiguration, SIGNAL(changed()), this, SLOT(changed()));
+
+ connect(m_environmentWidget, SIGNAL(userChangesChanged()),
+ this, SLOT(userChangesChanged()));
+
+ connect(m_runConfiguration, SIGNAL(baseEnvironmentChanged()),
+ this, SLOT(baseEnvironmentChanged()));
+ connect(m_runConfiguration, SIGNAL(userEnvironmentChangesChanged(QList<Utils::EnvironmentItem>)),
+ this, SLOT(userEnvironmentChangesChanged()));
+}
+
+void CustomExecutableConfigurationWidget::userChangesChanged()
+{
+ m_runConfiguration->setUserEnvironmentChanges(m_environmentWidget->userChanges());
+}
+
+void CustomExecutableConfigurationWidget::baseEnvironmentSelected(int index)
+{
+ m_ignoreChange = true;
+ m_runConfiguration->setBaseEnvironmentBase(CustomExecutableRunConfiguration::BaseEnvironmentBase(index));
+
+ m_environmentWidget->setBaseEnvironment(m_runConfiguration->baseEnvironment());
+ m_environmentWidget->setBaseEnvironmentText(m_runConfiguration->baseEnvironmentText());
+ m_ignoreChange = false;
+}
+
+void CustomExecutableConfigurationWidget::useCppDebuggerToggled(bool toggled)
+{
+ m_runConfiguration->setUseCppDebugger(toggled);
+}
+
+void CustomExecutableConfigurationWidget::useQmlDebuggerToggled(bool toggled)
+{
+ m_runConfiguration->setUseQmlDebugger(toggled);
+}
+
+void CustomExecutableConfigurationWidget::qmlDebugServerPortChanged(uint port)
+{
+ m_runConfiguration->setQmlDebugServerPort(port);
+}
+
+void CustomExecutableConfigurationWidget::baseEnvironmentChanged()
+{
+ if (m_ignoreChange)
+ return;
+
+ int index = CustomExecutableRunConfiguration::BaseEnvironmentBase(
+ m_runConfiguration->baseEnvironmentBase());
+ m_baseEnvironmentComboBox->setCurrentIndex(index);
+ m_environmentWidget->setBaseEnvironment(m_runConfiguration->baseEnvironment());
+ m_environmentWidget->setBaseEnvironmentText(m_runConfiguration->baseEnvironmentText());
+}
+
+void CustomExecutableConfigurationWidget::userEnvironmentChangesChanged()
+{
+ m_environmentWidget->setUserChanges(m_runConfiguration->userEnvironmentChanges());
+}
+
+
+void CustomExecutableConfigurationWidget::executableEdited()
+{
+ m_ignoreChange = true;
+ m_runConfiguration->setExecutable(m_executableChooser->rawPath());
+ m_ignoreChange = false;
+}
+void CustomExecutableConfigurationWidget::argumentsEdited(const QString &arguments)
+{
+ m_ignoreChange = true;
+ m_runConfiguration->setCommandLineArguments(arguments);
+ m_ignoreChange = false;
+}
+void CustomExecutableConfigurationWidget::workingDirectoryEdited()
+{
+ m_ignoreChange = true;
+ m_runConfiguration->setBaseWorkingDirectory(m_workingDirectory->rawPath());
+ m_ignoreChange = false;
+}
+
+void CustomExecutableConfigurationWidget::termToggled(bool on)
+{
+ m_ignoreChange = true;
+ m_runConfiguration->setRunMode(on ? LocalApplicationRunConfiguration::Console
+ : LocalApplicationRunConfiguration::Gui);
+ m_ignoreChange = false;
+}
+
+void CustomExecutableConfigurationWidget::changed()
+{
+ // We triggered the change, don't update us
+ if (m_ignoreChange)
+ return;
+
+ m_executableChooser->setPath(m_runConfiguration->rawExecutable());
+ m_commandLineArgumentsLineEdit->setText(m_runConfiguration->rawCommandLineArguments());
+ m_workingDirectory->setPath(m_runConfiguration->baseWorkingDirectory());
+ m_useTerminalCheck->setChecked(m_runConfiguration->runMode() == LocalApplicationRunConfiguration::Console);
+}
+
+} // namespace Internal
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/customexecutableconfigurationwidget.h b/src/plugins/projectexplorer/customexecutableconfigurationwidget.h
new file mode 100644
index 0000000000..2a510d0378
--- /dev/null
+++ b/src/plugins/projectexplorer/customexecutableconfigurationwidget.h
@@ -0,0 +1,95 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 CUSTOMEXECUTABLECONFIGURATIONWIDGET_H
+#define CUSTOMEXECUTABLECONFIGURATIONWIDGET_H
+
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+class QCheckBox;
+class QLineEdit;
+class QComboBox;
+class QLabel;
+class QAbstractButton;
+QT_END_NAMESPACE
+
+namespace Utils {
+class DetailsWidget;
+class PathChooser;
+class DebuggerLanguageChooser;
+}
+
+namespace ProjectExplorer {
+class CustomExecutableRunConfiguration;
+class EnvironmentWidget;
+
+namespace Internal {
+
+class CustomExecutableConfigurationWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ CustomExecutableConfigurationWidget(CustomExecutableRunConfiguration *rc);
+
+private slots:
+ void changed();
+
+ void executableEdited();
+ void argumentsEdited(const QString &arguments);
+ void workingDirectoryEdited();
+ void termToggled(bool);
+
+ void userChangesChanged();
+ void baseEnvironmentChanged();
+ void userEnvironmentChangesChanged();
+ void baseEnvironmentSelected(int index);
+ void useCppDebuggerToggled(bool toggled);
+ void useQmlDebuggerToggled(bool toggled);
+ void qmlDebugServerPortChanged(uint port);
+
+private:
+ bool m_ignoreChange;
+ CustomExecutableRunConfiguration *m_runConfiguration;
+ Utils::PathChooser *m_executableChooser;
+ QLineEdit *m_userName;
+ QLineEdit *m_commandLineArgumentsLineEdit;
+ Utils::PathChooser *m_workingDirectory;
+ QCheckBox *m_useTerminalCheck;
+ ProjectExplorer::EnvironmentWidget *m_environmentWidget;
+ QComboBox *m_baseEnvironmentComboBox;
+ Utils::DetailsWidget *m_detailsContainer;
+ Utils::DebuggerLanguageChooser *m_debuggerLanguageChooser;
+};
+
+} // namespace Internal
+} // namespace ProjectExplorer
+
+#endif // CUSTOMEXECUTABLECONFIGURATIONWIDGET_H
diff --git a/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp b/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp
index 88424c55a4..12005417e1 100644
--- a/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp
+++ b/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp
@@ -32,28 +32,23 @@
**************************************************************************/
#include "customexecutablerunconfiguration.h"
+#include "customexecutableconfigurationwidget.h"
+#include "toolchaintype.h"
#include <coreplugin/icore.h>
#include <projectexplorer/buildconfiguration.h>
-#include <projectexplorer/environmenteditmodel.h>
#include <projectexplorer/debugginghelper.h>
#include <projectexplorer/target.h>
-#include <projectexplorer/project.h>
-#include <utils/detailswidget.h>
-#include <utils/environment.h>
-#include <utils/pathchooser.h>
-#include <utils/debuggerlanguagechooser.h>
-#include <QtCore/QDir>
-#include <QtGui/QCheckBox>
-#include <QtGui/QComboBox>
+#include <utils/qtcprocess.h>
+
#include <QtGui/QDialog>
#include <QtGui/QDialogButtonBox>
-#include <QtGui/QFormLayout>
-#include <QtGui/QHBoxLayout>
#include <QtGui/QLabel>
-#include <QtGui/QLineEdit>
#include <QtGui/QMainWindow>
+#include <QtGui/QVBoxLayout>
+
+#include <QtCore/QDir>
using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;
@@ -67,221 +62,6 @@ const char * const WORKING_DIRECTORY_KEY("ProjectExplorer.CustomExecutableRunCon
const char * const USE_TERMINAL_KEY("ProjectExplorer.CustomExecutableRunConfiguration.UseTerminal");
const char * const USER_ENVIRONMENT_CHANGES_KEY("ProjectExplorer.CustomExecutableRunConfiguration.UserEnvironmentChanges");
const char * const BASE_ENVIRONMENT_BASE_KEY("ProjectExplorer.CustomExecutableRunConfiguration.BaseEnvironmentBase");
-
-const char * const DEFAULT_WORKING_DIR("$BUILDDIR");
-}
-
-class CustomDirectoryPathChooser : public Utils::PathChooser
-{
-public:
- CustomDirectoryPathChooser(QWidget *parent)
- : Utils::PathChooser(parent)
- {
- }
- virtual bool validatePath(const QString &path, QString *errorMessage = 0)
- {
- Q_UNUSED(path)
- Q_UNUSED(errorMessage)
- return true;
- }
-};
-
-CustomExecutableConfigurationWidget::CustomExecutableConfigurationWidget(CustomExecutableRunConfiguration *rc)
- : m_ignoreChange(false), m_runConfiguration(rc)
-{
- QFormLayout *layout = new QFormLayout;
- layout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
- layout->setMargin(0);
-
- m_executableChooser = new Utils::PathChooser(this);
- m_executableChooser->setEnvironment(rc->environment());
- m_executableChooser->setExpectedKind(Utils::PathChooser::Command);
- layout->addRow(tr("Executable:"), m_executableChooser);
-
- m_commandLineArgumentsLineEdit = new QLineEdit(this);
- m_commandLineArgumentsLineEdit->setMinimumWidth(200); // this shouldn't be fixed here...
- layout->addRow(tr("Arguments:"), m_commandLineArgumentsLineEdit);
-
- m_workingDirectory = new CustomDirectoryPathChooser(this);
- m_workingDirectory->setExpectedKind(Utils::PathChooser::Directory);
- m_workingDirectory->setBaseDirectory(rc->target()->project()->projectDirectory());
- m_workingDirectory->setEnvironment(rc->environment());
- layout->addRow(tr("Working directory:"), m_workingDirectory);
-
- m_useTerminalCheck = new QCheckBox(tr("Run in &Terminal"), this);
- layout->addRow(QString(), m_useTerminalCheck);
-
- QWidget *debuggerLabelWidget = new QWidget(this);
- QVBoxLayout *debuggerLabelLayout = new QVBoxLayout(debuggerLabelWidget);
- debuggerLabelLayout->setMargin(0);
- debuggerLabelLayout->setSpacing(0);
- debuggerLabelWidget->setLayout(debuggerLabelLayout);
- QLabel *debuggerLabel = new QLabel(tr("Debugger:"), this);
- debuggerLabelLayout->addWidget(debuggerLabel);
- debuggerLabelLayout->addStretch(10);
-
- m_debuggerLanguageChooser = new Utils::DebuggerLanguageChooser(this);
- layout->addRow(debuggerLabelWidget, m_debuggerLanguageChooser);
-
- m_debuggerLanguageChooser->setCppChecked(m_runConfiguration->useCppDebugger());
- m_debuggerLanguageChooser->setQmlChecked(m_runConfiguration->useQmlDebugger());
- m_debuggerLanguageChooser->setQmlDebugServerPort(m_runConfiguration->qmlDebugServerPort());
-
- QVBoxLayout *vbox = new QVBoxLayout(this);
- vbox->setMargin(0);
-
- m_detailsContainer = new Utils::DetailsWidget(this);
- m_detailsContainer->setState(Utils::DetailsWidget::NoSummary);
- vbox->addWidget(m_detailsContainer);
-
- QWidget *detailsWidget = new QWidget(m_detailsContainer);
- m_detailsContainer->setWidget(detailsWidget);
- detailsWidget->setLayout(layout);
-
- QLabel *environmentLabel = new QLabel(this);
- environmentLabel->setText(tr("Run Environment"));
- QFont f = environmentLabel->font();
- f.setBold(true);
- f.setPointSizeF(f.pointSizeF() *1.2);
- environmentLabel->setFont(f);
- vbox->addWidget(environmentLabel);
-
- QWidget *baseEnvironmentWidget = new QWidget;
- QHBoxLayout *baseEnvironmentLayout = new QHBoxLayout(baseEnvironmentWidget);
- baseEnvironmentLayout->setMargin(0);
- QLabel *label = new QLabel(tr("Base environment for this runconfiguration:"), this);
- baseEnvironmentLayout->addWidget(label);
- m_baseEnvironmentComboBox = new QComboBox(this);
- m_baseEnvironmentComboBox->addItems(QStringList()
- << tr("Clean Environment")
- << tr("System Environment")
- << tr("Build Environment"));
- m_baseEnvironmentComboBox->setCurrentIndex(rc->baseEnvironmentBase());
- connect(m_baseEnvironmentComboBox, SIGNAL(currentIndexChanged(int)),
- this, SLOT(baseEnvironmentSelected(int)));
- baseEnvironmentLayout->addWidget(m_baseEnvironmentComboBox);
- baseEnvironmentLayout->addStretch(10);
-
- m_environmentWidget = new EnvironmentWidget(this, baseEnvironmentWidget);
- m_environmentWidget->setBaseEnvironment(rc->baseEnvironment());
- m_environmentWidget->setBaseEnvironmentText(rc->baseEnvironmentText());
- m_environmentWidget->setUserChanges(rc->userEnvironmentChanges());
- vbox->addWidget(m_environmentWidget);
-
- changed();
-
- connect(m_executableChooser, SIGNAL(changed(QString)),
- this, SLOT(executableEdited()));
- connect(m_commandLineArgumentsLineEdit, SIGNAL(textEdited(const QString&)),
- this, SLOT(argumentsEdited(const QString&)));
- connect(m_workingDirectory, SIGNAL(changed(QString)),
- this, SLOT(workingDirectoryEdited()));
- connect(m_useTerminalCheck, SIGNAL(toggled(bool)),
- this, SLOT(termToggled(bool)));
-
- connect(m_debuggerLanguageChooser, SIGNAL(cppLanguageToggled(bool)),
- this, SLOT(useCppDebuggerToggled(bool)));
- connect(m_debuggerLanguageChooser, SIGNAL(qmlLanguageToggled(bool)),
- this, SLOT(useQmlDebuggerToggled(bool)));
- connect(m_debuggerLanguageChooser, SIGNAL(qmlDebugServerPortChanged(uint)),
- this, SLOT(qmlDebugServerPortChanged(uint)));
-
- connect(m_runConfiguration, SIGNAL(changed()), this, SLOT(changed()));
-
- connect(m_environmentWidget, SIGNAL(userChangesChanged()),
- this, SLOT(userChangesChanged()));
-
- connect(m_runConfiguration, SIGNAL(baseEnvironmentChanged()),
- this, SLOT(baseEnvironmentChanged()));
- connect(m_runConfiguration, SIGNAL(userEnvironmentChangesChanged(QList<Utils::EnvironmentItem>)),
- this, SLOT(userEnvironmentChangesChanged()));
-}
-
-void CustomExecutableConfigurationWidget::userChangesChanged()
-{
- m_runConfiguration->setUserEnvironmentChanges(m_environmentWidget->userChanges());
-}
-
-void CustomExecutableConfigurationWidget::baseEnvironmentSelected(int index)
-{
- m_ignoreChange = true;
- m_runConfiguration->setBaseEnvironmentBase(CustomExecutableRunConfiguration::BaseEnvironmentBase(index));
-
- m_environmentWidget->setBaseEnvironment(m_runConfiguration->baseEnvironment());
- m_environmentWidget->setBaseEnvironmentText(m_runConfiguration->baseEnvironmentText());
- m_ignoreChange = false;
-}
-
-void CustomExecutableConfigurationWidget::useCppDebuggerToggled(bool toggled)
-{
- m_runConfiguration->setUseCppDebugger(toggled);
-}
-
-void CustomExecutableConfigurationWidget::useQmlDebuggerToggled(bool toggled)
-{
- m_runConfiguration->setUseQmlDebugger(toggled);
-}
-
-void CustomExecutableConfigurationWidget::qmlDebugServerPortChanged(uint port)
-{
- m_runConfiguration->setQmlDebugServerPort(port);
-}
-
-void CustomExecutableConfigurationWidget::baseEnvironmentChanged()
-{
- if (m_ignoreChange)
- return;
-
- int index = CustomExecutableRunConfiguration::BaseEnvironmentBase(
- m_runConfiguration->baseEnvironmentBase());
- m_baseEnvironmentComboBox->setCurrentIndex(index);
- m_environmentWidget->setBaseEnvironment(m_runConfiguration->baseEnvironment());
- m_environmentWidget->setBaseEnvironmentText(m_runConfiguration->baseEnvironmentText());
-}
-
-void CustomExecutableConfigurationWidget::userEnvironmentChangesChanged()
-{
- m_environmentWidget->setUserChanges(m_runConfiguration->userEnvironmentChanges());
-}
-
-
-void CustomExecutableConfigurationWidget::executableEdited()
-{
- m_ignoreChange = true;
- m_runConfiguration->setExecutable(m_executableChooser->rawPath());
- m_ignoreChange = false;
-}
-void CustomExecutableConfigurationWidget::argumentsEdited(const QString &arguments)
-{
- m_ignoreChange = true;
- m_runConfiguration->setBaseCommandLineArguments(arguments);
- m_ignoreChange = false;
-}
-void CustomExecutableConfigurationWidget::workingDirectoryEdited()
-{
- m_ignoreChange = true;
- m_runConfiguration->setBaseWorkingDirectory(m_workingDirectory->rawPath());
- m_ignoreChange = false;
-}
-
-void CustomExecutableConfigurationWidget::termToggled(bool on)
-{
- m_ignoreChange = true;
- m_runConfiguration->setRunMode(on ? LocalApplicationRunConfiguration::Console
- : LocalApplicationRunConfiguration::Gui);
- m_ignoreChange = false;
-}
-
-void CustomExecutableConfigurationWidget::changed()
-{
- // We triggered the change, don't update us
- if (m_ignoreChange)
- return;
-
- m_executableChooser->setPath(m_runConfiguration->rawExecutable());
- m_commandLineArgumentsLineEdit->setText(Utils::Environment::joinArgumentList(m_runConfiguration->baseCommandLineArguments()));
- m_workingDirectory->setPath(m_runConfiguration->baseWorkingDirectory());
- m_useTerminalCheck->setChecked(m_runConfiguration->runMode() == LocalApplicationRunConfiguration::Console);
}
void CustomExecutableRunConfiguration::ctor()
@@ -341,7 +121,8 @@ void CustomExecutableRunConfiguration::activeBuildConfigurationChanged()
QString CustomExecutableRunConfiguration::executable() const
{
Utils::Environment env = environment();
- QString exec = env.searchInPath(m_executable, QStringList() << workingDirectory());
+ QString exec = env.searchInPath(Utils::expandMacros(m_executable, macroExpander()),
+ QStringList() << workingDirectory());
if (exec.isEmpty() || !QFileInfo(exec).exists()) {
// Oh the executable doesn't exists, ask the user.
@@ -361,7 +142,7 @@ QString CustomExecutableRunConfiguration::executable() const
QString oldExecutable = m_executable;
QString oldWorkingDirectory = m_workingDirectory;
- QStringList oldCmdArguments = m_cmdArguments;
+ QString oldCmdArguments = m_cmdArguments;
if (dialog.exec()) {
return executable();
@@ -374,7 +155,7 @@ QString CustomExecutableRunConfiguration::executable() const
return QString();
}
}
- return exec;
+ return QDir::cleanPath(exec);
}
QString CustomExecutableRunConfiguration::rawExecutable() const
@@ -394,7 +175,8 @@ LocalApplicationRunConfiguration::RunMode CustomExecutableRunConfiguration::runM
QString CustomExecutableRunConfiguration::workingDirectory() const
{
- return environment().expandVariables(baseWorkingDirectory());
+ return QDir::cleanPath(environment().expandVariables(
+ Utils::expandMacros(baseWorkingDirectory(), macroExpander())));
}
QString CustomExecutableRunConfiguration::baseWorkingDirectory() const
@@ -403,12 +185,12 @@ QString CustomExecutableRunConfiguration::baseWorkingDirectory() const
}
-QStringList CustomExecutableRunConfiguration::commandLineArguments() const
+QString CustomExecutableRunConfiguration::commandLineArguments() const
{
- return environment().expandVariables(baseCommandLineArguments());
+ return Utils::QtcProcess::expandMacros(m_cmdArguments, macroExpander());
}
-QStringList CustomExecutableRunConfiguration::baseCommandLineArguments() const
+QString CustomExecutableRunConfiguration::rawCommandLineArguments() const
{
return m_cmdArguments;
}
@@ -495,7 +277,7 @@ QVariantMap CustomExecutableRunConfiguration::toMap() const
bool CustomExecutableRunConfiguration::fromMap(const QVariantMap &map)
{
m_executable = map.value(QLatin1String(EXECUTABLE_KEY)).toString();
- m_cmdArguments = map.value(QLatin1String(ARGUMENTS_KEY)).toStringList();
+ m_cmdArguments = map.value(QLatin1String(ARGUMENTS_KEY)).toString();
m_workingDirectory = map.value(QLatin1String(WORKING_DIRECTORY_KEY)).toString();
m_runMode = map.value(QLatin1String(USE_TERMINAL_KEY)).toBool() ? Console : Gui;
m_userEnvironmentChanges = Utils::EnvironmentItem::fromStringList(map.value(QLatin1String(USER_ENVIRONMENT_CHANGES_KEY)).toStringList());
@@ -514,9 +296,9 @@ void CustomExecutableRunConfiguration::setExecutable(const QString &executable)
emit changed();
}
-void CustomExecutableRunConfiguration::setBaseCommandLineArguments(const QString &commandLineArguments)
+void CustomExecutableRunConfiguration::setCommandLineArguments(const QString &commandLineArguments)
{
- m_cmdArguments = Utils::Environment::parseCombinedArgString(commandLineArguments);
+ m_cmdArguments = commandLineArguments;
emit changed();
}
@@ -551,9 +333,9 @@ QStringList CustomExecutableRunConfiguration::dumperLibraryLocations() const
return ProjectExplorer::DebuggingHelperLibrary::locationsByInstallData(qtInstallData);
}
-ProjectExplorer::ToolChain::ToolChainType CustomExecutableRunConfiguration::toolChainType() const
+ProjectExplorer::ToolChainType CustomExecutableRunConfiguration::toolChainType() const
{
- return ProjectExplorer::ToolChain::UNKNOWN;
+ return ProjectExplorer::ToolChain_UNKNOWN;
}
// Factory
diff --git a/src/plugins/projectexplorer/customexecutablerunconfiguration.h b/src/plugins/projectexplorer/customexecutablerunconfiguration.h
index 8371be5802..16591e9889 100644
--- a/src/plugins/projectexplorer/customexecutablerunconfiguration.h
+++ b/src/plugins/projectexplorer/customexecutablerunconfiguration.h
@@ -36,26 +36,11 @@
#include "applicationrunconfiguration.h"
+#include <utils/environment.h>
+
#include <QtCore/QVariantMap>
-#include <QtGui/QWidget>
-
-QT_BEGIN_NAMESPACE
-class QCheckBox;
-class QLineEdit;
-class QComboBox;
-class QLabel;
-class QAbstractButton;
-QT_END_NAMESPACE
-
-namespace Utils {
-class DetailsWidget;
-class PathChooser;
-class DebuggerLanguageChooser;
-}
namespace ProjectExplorer {
-
-class EnvironmentWidget;
class Target;
namespace Internal {
@@ -80,7 +65,6 @@ public:
* ask the user if none is specified
*/
QString executable() const;
- QString rawExecutable() const;
/** Returns whether this runconfiguration ever was configured with a executable
*/
@@ -88,14 +72,14 @@ public:
LocalApplicationRunConfiguration::RunMode runMode() const;
QString workingDirectory() const;
- QStringList commandLineArguments() const;
+ QString commandLineArguments() const;
Utils::Environment environment() const;
QWidget *createConfigurationWidget();
QString dumperLibrary() const;
QStringList dumperLibraryLocations() const;
- ProjectExplorer::ToolChain::ToolChainType toolChainType() const;
+ ProjectExplorer::ToolChainType toolChainType() const;
QVariantMap toMap() const;
@@ -127,16 +111,17 @@ private:
QList<Utils::EnvironmentItem> userEnvironmentChanges() const;
void setExecutable(const QString &executable);
- void setBaseCommandLineArguments(const QString &commandLineArguments);
- QStringList baseCommandLineArguments() const;
- QString baseWorkingDirectory() const;
+ QString rawExecutable() const;
+ void setCommandLineArguments(const QString &commandLineArguments);
+ QString rawCommandLineArguments() const;
void setBaseWorkingDirectory(const QString &workingDirectory);
+ QString baseWorkingDirectory() const;
void setUserName(const QString &name);
void setRunMode(RunMode runMode);
QString m_executable;
QString m_workingDirectory;
- QStringList m_cmdArguments;
+ QString m_cmdArguments;
RunMode m_runMode;
bool m_userSetName;
QString m_userName;
@@ -164,46 +149,6 @@ public:
RunConfiguration *clone(Target *parent, RunConfiguration *source);
};
-namespace Internal {
-
-class CustomExecutableConfigurationWidget : public QWidget
-{
- Q_OBJECT
-
-public:
- CustomExecutableConfigurationWidget(CustomExecutableRunConfiguration *rc);
-
-private slots:
- void changed();
-
- void executableEdited();
- void argumentsEdited(const QString &arguments);
- void workingDirectoryEdited();
- void termToggled(bool);
-
- void userChangesChanged();
- void baseEnvironmentChanged();
- void userEnvironmentChangesChanged();
- void baseEnvironmentSelected(int index);
- void useCppDebuggerToggled(bool toggled);
- void useQmlDebuggerToggled(bool toggled);
- void qmlDebugServerPortChanged(uint port);
-
-private:
- bool m_ignoreChange;
- CustomExecutableRunConfiguration *m_runConfiguration;
- Utils::PathChooser *m_executableChooser;
- QLineEdit *m_userName;
- QLineEdit *m_commandLineArgumentsLineEdit;
- Utils::PathChooser *m_workingDirectory;
- QCheckBox *m_useTerminalCheck;
- ProjectExplorer::EnvironmentWidget *m_environmentWidget;
- QComboBox *m_baseEnvironmentComboBox;
- Utils::DetailsWidget *m_detailsContainer;
- Utils::DebuggerLanguageChooser *m_debuggerLanguageChooser;
-};
-
-} // namespace Internal
} // namespace ProjectExplorer
#endif // CUSTOMEXECUTABLERUNCONFIGURATION_H
diff --git a/src/plugins/projectexplorer/customwizard/customwizard.cpp b/src/plugins/projectexplorer/customwizard/customwizard.cpp
index a454e60ae8..6534bf2d87 100644
--- a/src/plugins/projectexplorer/customwizard/customwizard.cpp
+++ b/src/plugins/projectexplorer/customwizard/customwizard.cpp
@@ -507,7 +507,7 @@ void CustomProjectWizard::initProjectWizardDialog(BaseProjectWizardDialog *w,
w->setPath(defaultPath);
w->setProjectName(BaseProjectWizardDialog::uniqueProjectName(defaultPath));
- connect(w, SIGNAL(introPageLeft(QString,QString)), this, SLOT(introPageLeft(QString,QString)));
+ connect(w, SIGNAL(projectParametersChanged(QString,QString)), this, SLOT(projectParametersChanged(QString,QString)));
if (CustomWizardPrivate::verbose)
qDebug() << "initProjectWizardDialog" << w << w->pageIds();
@@ -553,7 +553,7 @@ bool CustomProjectWizard::postGenerateFiles(const QWizard *, const Core::Generat
return CustomProjectWizard::postGenerateOpen(l, errorMessage);
}
-void CustomProjectWizard::introPageLeft(const QString &project, const QString & path)
+void CustomProjectWizard::projectParametersChanged(const QString &project, const QString & path)
{
// Make '%ProjectName%' available in base replacements.
context()->baseReplacements.insert(QLatin1String("ProjectName"), project);
diff --git a/src/plugins/projectexplorer/customwizard/customwizard.h b/src/plugins/projectexplorer/customwizard/customwizard.h
index 0954648634..f88e7d8200 100644
--- a/src/plugins/projectexplorer/customwizard/customwizard.h
+++ b/src/plugins/projectexplorer/customwizard/customwizard.h
@@ -174,7 +174,7 @@ protected:
const WizardPageList &extensionPages) const;
private slots:
- void introPageLeft(const QString &project, const QString &path);
+ void projectParametersChanged(const QString &project, const QString &path);
};
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/customwizard/customwizardparameters.cpp b/src/plugins/projectexplorer/customwizard/customwizardparameters.cpp
index ac57a594aa..ec31166738 100644
--- a/src/plugins/projectexplorer/customwizard/customwizardparameters.cpp
+++ b/src/plugins/projectexplorer/customwizard/customwizardparameters.cpp
@@ -392,7 +392,7 @@ static ParseState nextOpeningState(ParseState in, const QStringRef &name)
break;
}
return ParseError;
-};
+}
// Switch parser state depending on closing element name.
static ParseState nextClosingState(ParseState in, const QStringRef &name)
@@ -458,7 +458,7 @@ static ParseState nextClosingState(ParseState in, const QStringRef &name)
break;
}
return ParseError;
-};
+}
// Parse kind attribute
static inline Core::IWizard::WizardKind kindAttribute(const QXmlStreamReader &r)
@@ -511,10 +511,9 @@ static inline QString attributeValue(const QXmlStreamReader &r, const char *name
}
// Return locale language attribute "de_UTF8" -> "de", empty string for "C"
-static inline QString localeLanguage()
+static inline QString languageSetting()
{
- QLocale loc;
- QString name = loc.name();
+ QString name = Core::ICore::instance()->userInterfaceLanguage();
const int underScorePos = name.indexOf(QLatin1Char('_'));
if (underScorePos != -1)
name.truncate(underScorePos);
@@ -542,7 +541,7 @@ CustomWizardParameters::ParseResult
clear();
bp->clear();
bp->setKind(Core::IWizard::ProjectWizard);
- const QString language = localeLanguage();
+ const QString language = languageSetting();
CustomWizardField field;
do {
token = reader.readNext();
diff --git a/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.h b/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.h
index b6dd428664..197b5fc656 100644
--- a/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.h
+++ b/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.h
@@ -39,7 +39,7 @@
namespace Core {
class GeneratedFile;
-};
+}
namespace ProjectExplorer {
namespace Internal {
diff --git a/src/plugins/projectexplorer/debugginghelper.h b/src/plugins/projectexplorer/debugginghelper.h
index efb73ca510..5d1db10bf8 100644
--- a/src/plugins/projectexplorer/debugginghelper.h
+++ b/src/plugins/projectexplorer/debugginghelper.h
@@ -36,7 +36,6 @@
#include "projectexplorer_export.h"
-#include <utils/environment.h>
#include <utils/buildablehelperlibrary.h>
#include <QtCore/QString>
diff --git a/src/plugins/projectexplorer/deployconfiguration.h b/src/plugins/projectexplorer/deployconfiguration.h
index 84d6ab4ead..2b80455251 100644
--- a/src/plugins/projectexplorer/deployconfiguration.h
+++ b/src/plugins/projectexplorer/deployconfiguration.h
@@ -41,8 +41,6 @@
#include <QtCore/QString>
#include <QtCore/QStringList>
-#include <QtCore/QList>
-#include <QtCore/QObject>
namespace ProjectExplorer {
@@ -120,6 +118,6 @@ public:
} // namespace ProjectExplorer
-Q_DECLARE_METATYPE(ProjectExplorer::DeployConfiguration *);
+Q_DECLARE_METATYPE(ProjectExplorer::DeployConfiguration *)
#endif // PROJECTEXPLORER_DEPLOYCONFIGURATION_H
diff --git a/src/plugins/projectexplorer/editorconfiguration.cpp b/src/plugins/projectexplorer/editorconfiguration.cpp
index 555cb5e302..49924c63b5 100644
--- a/src/plugins/projectexplorer/editorconfiguration.cpp
+++ b/src/plugins/projectexplorer/editorconfiguration.cpp
@@ -32,7 +32,7 @@
**************************************************************************/
#include "editorconfiguration.h"
-#include <coreplugin/icore.h>
+
#include <QtCore/QTextCodec>
using namespace ProjectExplorer;
diff --git a/src/plugins/projectexplorer/environmenteditmodel.cpp b/src/plugins/projectexplorer/environmenteditmodel.cpp
index 30217145f1..ceb26e98a2 100644
--- a/src/plugins/projectexplorer/environmenteditmodel.cpp
+++ b/src/plugins/projectexplorer/environmenteditmodel.cpp
@@ -295,14 +295,13 @@ QModelIndex EnvironmentModel::addVariable()
QModelIndex EnvironmentModel::addVariable(const Utils::EnvironmentItem &item)
{
- int insertPos = findInResultInsertPosition(item.name);
// Return existing index if the name is already in the result set:
- if (insertPos < m_resultEnvironment.size()
- && m_resultEnvironment.key(m_resultEnvironment.constBegin() + insertPos) == item.name) {
- return index(insertPos, 0, QModelIndex());
- }
+ int pos = findInResult(item.name);
+ if (pos >= 0 && pos < m_resultEnvironment.size())
+ return index(pos, 0, QModelIndex());
+ int insertPos = findInResultInsertPosition(item.name);
int changePos = findInChanges(item.name);
if (m_baseEnvironment.hasKey(item.name)) {
// We previously unset this!
diff --git a/src/plugins/projectexplorer/filewatcher.h b/src/plugins/projectexplorer/filewatcher.h
index 77f25a6f2e..8de9a242d0 100644
--- a/src/plugins/projectexplorer/filewatcher.h
+++ b/src/plugins/projectexplorer/filewatcher.h
@@ -43,7 +43,6 @@
#include <QtCore/QMap>
QT_BEGIN_NAMESPACE
-class QTimer;
class QFileSystemWatcher;
QT_END_NAMESPACE
diff --git a/src/plugins/projectexplorer/foldernavigationwidget.cpp b/src/plugins/projectexplorer/foldernavigationwidget.cpp
index c8e7df7753..5a74b2c2b5 100644
--- a/src/plugins/projectexplorer/foldernavigationwidget.cpp
+++ b/src/plugins/projectexplorer/foldernavigationwidget.cpp
@@ -44,6 +44,7 @@
#include <utils/environment.h>
#include <utils/pathchooser.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <utils/unixutils.h>
#include <utils/consoleprocess.h>
@@ -442,8 +443,8 @@ void FolderNavigationWidget::openTerminal(const QString &path)
const QString terminalEmulator = QString::fromLocal8Bit(qgetenv("COMSPEC"));
const QStringList args; // none
#else
- QStringList args = Utils::ConsoleProcess::terminalEmulator(
- Core::ICore::instance()->settings()).split(QLatin1Char(' '));
+ QStringList args = Utils::QtcProcess::splitArgs(
+ Utils::ConsoleProcess::terminalEmulator(Core::ICore::instance()->settings()));
const QString terminalEmulator = args.takeFirst();
const QString shell = QString::fromLocal8Bit(qgetenv("SHELL"));
args.append(shell);
diff --git a/src/plugins/projectexplorer/gccparser.cpp b/src/plugins/projectexplorer/gccparser.cpp
index 4fabe312db..d9d4786103 100644
--- a/src/plugins/projectexplorer/gccparser.cpp
+++ b/src/plugins/projectexplorer/gccparser.cpp
@@ -36,6 +36,8 @@
#include "taskwindow.h"
#include "projectexplorerconstants.h"
+#include <QtCore/QDir>
+
using namespace ProjectExplorer;
namespace {
@@ -104,7 +106,7 @@ void GccParser::stdError(const QString &line)
int lineno = m_regExp.cap(3).toInt();
Task task(Task::Unknown,
m_regExp.cap(8) /* description */,
- filename, lineno,
+ QDir::fromNativeSeparators(filename), lineno,
Constants::TASK_CATEGORY_COMPILE);
if (m_regExp.cap(7) == QLatin1String("warning"))
task.type = Task::Warning;
@@ -122,7 +124,7 @@ void GccParser::stdError(const QString &line)
} else if (m_regExpIncluded.indexIn(lne) > -1) {
emit addTask(Task(Task::Unknown,
lne /* description */,
- m_regExpIncluded.cap(1) /* filename */,
+ QDir::fromNativeSeparators(m_regExpIncluded.cap(1)) /* filename */,
m_regExpIncluded.cap(3).toInt() /* linenumber */,
Constants::TASK_CATEGORY_COMPILE));
return;
diff --git a/src/plugins/projectexplorer/gnumakeparser.cpp b/src/plugins/projectexplorer/gnumakeparser.cpp
index 617035655e..308d4c3dd9 100644
--- a/src/plugins/projectexplorer/gnumakeparser.cpp
+++ b/src/plugins/projectexplorer/gnumakeparser.cpp
@@ -46,7 +46,7 @@ namespace {
const char * const MAKE_PATTERN("^(([A-Za-z]:)?[/\\\\][^:]*[/\\\\])?(mingw(32|64)-|g)?make(.exe)?(\\[\\d+\\])?:\\s");
}
-GnuMakeParser::GnuMakeParser(const QString &dir) :
+GnuMakeParser::GnuMakeParser() :
m_suppressIssues(false),
m_fatalErrorCount(0)
{
@@ -58,12 +58,17 @@ GnuMakeParser::GnuMakeParser(const QString &dir) :
m_makeLine.setMinimal(true);
m_makefileError.setPattern(QLatin1String("^(.*):(\\d+):\\s\\*\\*\\*\\s(.*)$"));
m_makefileError.setMinimal(true);
- addDirectory(dir);
}
-int GnuMakeParser::fatalErrors() const
+void GnuMakeParser::setWorkingDirectory(const QString &workingDirectory)
{
- return m_fatalErrorCount;
+ addDirectory(workingDirectory);
+ IOutputParser::setWorkingDirectory(workingDirectory);
+}
+
+bool GnuMakeParser::hasFatalErrors() const
+{
+ return (m_fatalErrorCount > 0) || IOutputParser::hasFatalErrors();
}
void GnuMakeParser::stdOutput(const QString &line)
@@ -91,7 +96,7 @@ void GnuMakeParser::stdError(const QString &line)
m_suppressIssues = true;
addTask(Task(Task::Error,
m_makefileError.cap(3),
- m_makefileError.cap(1),
+ QDir::fromNativeSeparators(m_makefileError.cap(1)),
m_makefileError.cap(2).toInt(),
Constants::TASK_CATEGORY_BUILDSYSTEM));
}
diff --git a/src/plugins/projectexplorer/gnumakeparser.h b/src/plugins/projectexplorer/gnumakeparser.h
index 4dcc7f972d..b24c97a008 100644
--- a/src/plugins/projectexplorer/gnumakeparser.h
+++ b/src/plugins/projectexplorer/gnumakeparser.h
@@ -46,14 +46,16 @@ class PROJECTEXPLORER_EXPORT GnuMakeParser : public ProjectExplorer::IOutputPars
Q_OBJECT
public:
- explicit GnuMakeParser(const QString &dir = QString());
+ explicit GnuMakeParser();
virtual void stdOutput(const QString &line);
virtual void stdError(const QString &line);
+ virtual void setWorkingDirectory(const QString &workingDirectory);
+
QStringList searchDirectories() const;
- int fatalErrors() const;
+ bool hasFatalErrors() const;
public slots:
virtual void taskAdded(const ProjectExplorer::Task &task);
diff --git a/src/plugins/projectexplorer/ioutputparser.cpp b/src/plugins/projectexplorer/ioutputparser.cpp
index 5fab294ce4..a506d4247c 100644
--- a/src/plugins/projectexplorer/ioutputparser.cpp
+++ b/src/plugins/projectexplorer/ioutputparser.cpp
@@ -32,7 +32,9 @@
**************************************************************************/
#include "ioutputparser.h"
-#include "utils/qtcassert.h"
+#include "task.h"
+
+#include <utils/qtcassert.h>
namespace ProjectExplorer {
@@ -105,4 +107,15 @@ void IOutputParser::taskAdded(const ProjectExplorer::Task &task)
emit addTask(task);
}
+bool IOutputParser::hasFatalErrors() const
+{
+ return false || (m_parser && m_parser->hasFatalErrors());
+}
+
+void IOutputParser::setWorkingDirectory(const QString &workingDirectory)
+{
+ if (m_parser)
+ m_parser->setWorkingDirectory(workingDirectory);
+}
+
}
diff --git a/src/plugins/projectexplorer/ioutputparser.h b/src/plugins/projectexplorer/ioutputparser.h
index 9dc063ad08..eb24d094f7 100644
--- a/src/plugins/projectexplorer/ioutputparser.h
+++ b/src/plugins/projectexplorer/ioutputparser.h
@@ -35,13 +35,12 @@
#define IOUTPUTPARSER_H
#include "projectexplorer_export.h"
-#include "task.h"
#include "buildstep.h"
-#include <QtCore/QObject>
#include <QtCore/QString>
namespace ProjectExplorer {
+class Task;
class PROJECTEXPLORER_EXPORT IOutputParser : public QObject
{
@@ -68,6 +67,11 @@ public:
/// Called once for each line if standard error to parse.
virtual void stdError(const QString &line);
+ // This is mainly a symbian specific quirk
+ virtual bool hasFatalErrors() const;
+ // For GnuMakeParser
+ virtual void setWorkingDirectory(const QString &workingDirectory);
+
signals:
/// Should be emitted whenever some additional information should be
/// added to the output.
diff --git a/src/plugins/projectexplorer/iprojectmanager.h b/src/plugins/projectexplorer/iprojectmanager.h
index d4bf3b50f8..1071a04c0a 100644
--- a/src/plugins/projectexplorer/iprojectmanager.h
+++ b/src/plugins/projectexplorer/iprojectmanager.h
@@ -36,9 +36,11 @@
#include "projectexplorer_export.h"
-#include <coreplugin/icontext.h>
#include <QtCore/QObject>
+namespace Core {
+class Context;
+}
namespace ProjectExplorer {
class Project;
diff --git a/src/plugins/projectexplorer/iprojectproperties.h b/src/plugins/projectexplorer/iprojectproperties.h
index 5c516d68bb..4bb8c847b3 100644
--- a/src/plugins/projectexplorer/iprojectproperties.h
+++ b/src/plugins/projectexplorer/iprojectproperties.h
@@ -36,7 +36,9 @@
#include "projectexplorer_export.h"
-#include <QtGui/QIcon>
+#include <QtCore/QObject>
+
+QT_FORWARD_DECLARE_CLASS(QIcon)
namespace ProjectExplorer {
class Project;
diff --git a/src/plugins/projectexplorer/ldparser.cpp b/src/plugins/projectexplorer/ldparser.cpp
index 9d212a480b..2b40e0e9a0 100644
--- a/src/plugins/projectexplorer/ldparser.cpp
+++ b/src/plugins/projectexplorer/ldparser.cpp
@@ -35,6 +35,8 @@
#include "projectexplorerconstants.h"
#include "taskwindow.h"
+#include <QtCore/QDir>
+
using namespace ProjectExplorer;
namespace {
@@ -102,7 +104,7 @@ void LdParser::stdError(const QString &line)
&& !m_regExpLinker.cap(4).startsWith(QLatin1String("(.text+0x")))
filename = m_regExpLinker.cap(4);
QString description = m_regExpLinker.cap(8).trimmed();
- Task task(Task::Error, description, filename, lineno,
+ Task task(Task::Error, description, QDir::fromNativeSeparators(filename), lineno,
Constants::TASK_CATEGORY_COMPILE);
if (m_regExpInFunction.indexIn(description) > -1 ||
description.startsWith(QLatin1String("At global scope")) ||
diff --git a/src/plugins/projectexplorer/linuxiccparser.cpp b/src/plugins/projectexplorer/linuxiccparser.cpp
index 8baf6e760e..0fc9cda0bc 100644
--- a/src/plugins/projectexplorer/linuxiccparser.cpp
+++ b/src/plugins/projectexplorer/linuxiccparser.cpp
@@ -35,7 +35,8 @@
#include "ldparser.h"
#include "taskwindow.h"
#include "projectexplorerconstants.h"
-#include <QtCore/QDebug>
+
+#include <QtCore/QDir>
using namespace ProjectExplorer;
@@ -75,7 +76,8 @@ void LinuxIccParser::stdError(const QString &line)
if (m_expectFirstLine && m_firstLine.indexIn(line) != -1) {
// Clear out old task
m_temporary = ProjectExplorer::Task(Task::Unknown, m_firstLine.cap(6).trimmed(),
- m_firstLine.cap(1), m_firstLine.cap(2).toInt(),
+ QDir::fromNativeSeparators(m_firstLine.cap(1)),
+ m_firstLine.cap(2).toInt(),
QLatin1String(Constants::TASK_CATEGORY_COMPILE));
QString category = m_firstLine.cap(4);
if (category == QLatin1String("error"))
diff --git a/src/plugins/projectexplorer/localapplicationruncontrol.cpp b/src/plugins/projectexplorer/localapplicationruncontrol.cpp
new file mode 100644
index 0000000000..c7cd867def
--- /dev/null
+++ b/src/plugins/projectexplorer/localapplicationruncontrol.cpp
@@ -0,0 +1,141 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "localapplicationruncontrol.h"
+#include "applicationrunconfiguration.h"
+#include "projectexplorerconstants.h"
+
+#include <utils/qtcassert.h>
+#include <utils/environment.h>
+
+#include <QtGui/QLabel>
+#include <QtCore/QDir>
+
+namespace ProjectExplorer {
+namespace Internal {
+
+LocalApplicationRunControlFactory::LocalApplicationRunControlFactory()
+{
+}
+
+LocalApplicationRunControlFactory::~LocalApplicationRunControlFactory()
+{
+}
+
+bool LocalApplicationRunControlFactory::canRun(ProjectExplorer::RunConfiguration *runConfiguration, const QString &mode) const
+{
+ return (mode == ProjectExplorer::Constants::RUNMODE)
+ && (qobject_cast<LocalApplicationRunConfiguration *>(runConfiguration) != 0);
+}
+
+QString LocalApplicationRunControlFactory::displayName() const
+{
+ return tr("Run");
+}
+
+RunControl *LocalApplicationRunControlFactory::create(ProjectExplorer::RunConfiguration *runConfiguration, const QString &mode)
+{
+ QTC_ASSERT(canRun(runConfiguration, mode), return 0);
+ return new LocalApplicationRunControl(qobject_cast<LocalApplicationRunConfiguration *>(runConfiguration), mode);
+}
+
+QWidget *LocalApplicationRunControlFactory::createConfigurationWidget(RunConfiguration *runConfiguration)
+{
+ Q_UNUSED(runConfiguration)
+ return new QLabel("TODO add Configuration widget");
+}
+
+// ApplicationRunControl
+
+LocalApplicationRunControl::LocalApplicationRunControl(LocalApplicationRunConfiguration *rc, QString mode)
+ : RunControl(rc, mode)
+{
+ Utils::Environment env = rc->environment();
+ QString dir = rc->workingDirectory();
+ m_applicationLauncher.setEnvironment(env);
+ m_applicationLauncher.setWorkingDirectory(dir);
+
+ m_executable = rc->executable();
+ m_runMode = static_cast<ApplicationLauncher::Mode>(rc->runMode());
+ m_commandLineArguments = rc->commandLineArguments();
+
+ connect(&m_applicationLauncher, SIGNAL(appendMessage(QString,bool)),
+ this, SLOT(slotAppendMessage(QString,bool)));
+ connect(&m_applicationLauncher, SIGNAL(appendOutput(QString, bool)),
+ this, SLOT(slotAddToOutputWindow(QString, bool)));
+ connect(&m_applicationLauncher, SIGNAL(processExited(int)),
+ this, SLOT(processExited(int)));
+ connect(&m_applicationLauncher, SIGNAL(bringToForegroundRequested(qint64)),
+ this, SLOT(bringApplicationToForeground(qint64)));
+}
+
+LocalApplicationRunControl::~LocalApplicationRunControl()
+{
+}
+
+void LocalApplicationRunControl::start()
+{
+ m_applicationLauncher.start(m_runMode, m_executable, m_commandLineArguments);
+ emit started();
+
+ emit appendMessage(this, tr("Starting %1...").arg(QDir::toNativeSeparators(m_executable)), false);
+}
+
+LocalApplicationRunControl::StopResult LocalApplicationRunControl::stop()
+{
+ m_applicationLauncher.stop();
+ return StoppedSynchronously;
+}
+
+bool LocalApplicationRunControl::isRunning() const
+{
+ return m_applicationLauncher.isRunning();
+}
+
+void LocalApplicationRunControl::slotAppendMessage(const QString &err,
+ bool isError)
+{
+ emit appendMessage(this, err, isError);
+ emit finished();
+}
+
+void LocalApplicationRunControl::slotAddToOutputWindow(const QString &line,
+ bool isError)
+{
+ emit addToOutputWindowInline(this, line, isError);
+}
+
+void LocalApplicationRunControl::processExited(int exitCode)
+{
+ emit appendMessage(this, tr("%1 exited with code %2").arg(QDir::toNativeSeparators(m_executable)).arg(exitCode), false);
+ emit finished();
+}
+
+} // namespace Internal
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/localapplicationruncontrol.h b/src/plugins/projectexplorer/localapplicationruncontrol.h
new file mode 100644
index 0000000000..3445b05301
--- /dev/null
+++ b/src/plugins/projectexplorer/localapplicationruncontrol.h
@@ -0,0 +1,76 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 LOCALAPPLICATIONRUNCONTROL_H
+#define LOCALAPPLICATIONRUNCONTROL_H
+
+#include "runconfiguration.h"
+#include "applicationlauncher.h"
+
+namespace ProjectExplorer {
+
+class LocalApplicationRunConfiguration;
+namespace Internal {
+
+class LocalApplicationRunControlFactory : public IRunControlFactory
+{
+ Q_OBJECT
+public:
+ LocalApplicationRunControlFactory ();
+ virtual ~LocalApplicationRunControlFactory();
+ virtual bool canRun(RunConfiguration *runConfiguration, const QString &mode) const;
+ virtual QString displayName() const;
+ virtual RunControl* create(RunConfiguration *runConfiguration, const QString &mode);
+ virtual QWidget *createConfigurationWidget(RunConfiguration *runConfiguration);
+};
+
+class LocalApplicationRunControl : public RunControl
+{
+ Q_OBJECT
+public:
+ LocalApplicationRunControl(LocalApplicationRunConfiguration *runConfiguration, QString mode);
+ virtual ~LocalApplicationRunControl();
+ virtual void start();
+ virtual StopResult stop();
+ virtual bool isRunning() const;
+private slots:
+ void processExited(int exitCode);
+ void slotAddToOutputWindow(const QString &line, bool isError);
+ void slotAppendMessage(const QString &err, bool isError);
+private:
+ ProjectExplorer::ApplicationLauncher m_applicationLauncher;
+ QString m_executable;
+ QString m_commandLineArguments;
+ ProjectExplorer::ApplicationLauncher::Mode m_runMode;
+};
+
+} // namespace Internal
+} // namespace ProjectExplorer
+
+#endif // LOCALAPPLICATIONRUNCONTROL_H
diff --git a/src/plugins/projectexplorer/miniprojecttargetselector.cpp b/src/plugins/projectexplorer/miniprojecttargetselector.cpp
index ffbea24b42..586928b06f 100644
--- a/src/plugins/projectexplorer/miniprojecttargetselector.cpp
+++ b/src/plugins/projectexplorer/miniprojecttargetselector.cpp
@@ -41,7 +41,6 @@
#include <utils/stylehelper.h>
#include <coreplugin/icore.h>
-#include <coreplugin/mainwindow.h>
#include <coreplugin/coreconstants.h>
#include <projectexplorer/projectexplorer.h>
@@ -61,6 +60,7 @@
#include <QtGui/QPainter>
#include <QtGui/QAction>
#include <QtGui/QItemDelegate>
+#include <QtGui/QMainWindow>
#include <QtGui/QApplication>
@@ -586,7 +586,7 @@ void MiniProjectTargetSelector::updateAction()
QIcon targetIcon = style()->standardIcon(QStyle::SP_ComputerIcon);
const int extrawidth = 110; // Size of margins + icon width
- // Some fudge numbers to ensure the menu doesnt grow unbounded
+ // Some fudge numbers to ensure the menu does not grow unbounded
int maxLength = fontMetrics().averageCharWidth() * 140;
if (project) {
diff --git a/src/plugins/projectexplorer/msvcparser.cpp b/src/plugins/projectexplorer/msvcparser.cpp
index eaaa2428b6..85f47079ca 100644
--- a/src/plugins/projectexplorer/msvcparser.cpp
+++ b/src/plugins/projectexplorer/msvcparser.cpp
@@ -43,7 +43,7 @@ using namespace ProjectExplorer;
MsvcParser::MsvcParser()
{
- setObjectName(QLatin1String("MavcParser"));
+ setObjectName(QLatin1String("MsvcParser"));
m_compileRegExp.setPattern(QString::fromLatin1("^") + QLatin1String(FILE_POS_PATTERN)
+ QLatin1String(" : .*(warning|error) (")
+ QLatin1String(ERROR_PATTERN) + QLatin1String(".*)$"));
diff --git a/src/plugins/projectexplorer/outputformatter.cpp b/src/plugins/projectexplorer/outputformatter.cpp
index b181278bfe..bb213d5cda 100644
--- a/src/plugins/projectexplorer/outputformatter.cpp
+++ b/src/plugins/projectexplorer/outputformatter.cpp
@@ -37,6 +37,9 @@
#include <texteditor/texteditorsettings.h>
#include <QtGui/QPlainTextEdit>
+#include <QtGui/QColor>
+
+#include <QtCore/QString>
using namespace ProjectExplorer;
using namespace TextEditor;
@@ -98,7 +101,6 @@ QColor OutputFormatter::mixColors(const QColor &a, const QColor &b)
(a.blue() + 2* b.blue()) / 3, (a.alpha() + 2 * b.alpha()) / 3);
}
-
void OutputFormatter::initFormats()
{
QPalette p = plainTextEdit()->palette();
diff --git a/src/plugins/projectexplorer/outputformatter.h b/src/plugins/projectexplorer/outputformatter.h
index bda5ef57f6..8b318f00c3 100644
--- a/src/plugins/projectexplorer/outputformatter.h
+++ b/src/plugins/projectexplorer/outputformatter.h
@@ -37,12 +37,11 @@
#include "projectexplorer_export.h"
#include <QtCore/QObject>
-#include <QtCore/QString>
-#include <QtGui/QColor>
-QT_FORWARD_DECLARE_CLASS(QMouseEvent);
-QT_FORWARD_DECLARE_CLASS(QPlainTextEdit);
-QT_FORWARD_DECLARE_CLASS(QTextCharFormat);
+QT_FORWARD_DECLARE_CLASS(QMouseEvent)
+QT_FORWARD_DECLARE_CLASS(QPlainTextEdit)
+QT_FORWARD_DECLARE_CLASS(QTextCharFormat)
+QT_FORWARD_DECLARE_CLASS(QColor)
namespace ProjectExplorer {
diff --git a/src/plugins/projectexplorer/outputwindow.cpp b/src/plugins/projectexplorer/outputwindow.cpp
index 3f9572520c..321f46b599 100644
--- a/src/plugins/projectexplorer/outputwindow.cpp
+++ b/src/plugins/projectexplorer/outputwindow.cpp
@@ -91,9 +91,6 @@ OutputPane::OutputPane() :
m_runIcon.addFile(Constants::ICON_RUN);
m_runIcon.addFile(Constants::ICON_RUN_SMALL);
- m_debugIcon.addFile(Constants::ICON_DEBUG);
- m_debugIcon.addFile(Constants::ICON_DEBUG_SMALL);
-
// Rerun
m_reRunButton->setIcon(m_runIcon);
m_reRunButton->setToolTip(tr("Re-run this run-configuration"));
@@ -397,8 +394,8 @@ void OutputPane::tabChanged(int i)
RunControl *rc = m_runControlTabs.at(index).runControl;
m_stopAction->setEnabled(rc->isRunning());
- m_reRunButton->setEnabled(!rc->isRunning() && rc->runMode() == Constants::RUNMODE);
- m_reRunButton->setIcon(rc->runMode() == Constants::DEBUGMODE ? m_debugIcon : m_runIcon);
+ m_reRunButton->setEnabled(!rc->isRunning());
+ m_reRunButton->setIcon(m_runIcon);
}
}
@@ -408,7 +405,7 @@ void OutputPane::runControlStarted()
if (current && current == sender()) {
m_reRunButton->setEnabled(false);
m_stopAction->setEnabled(true);
- m_reRunButton->setIcon(current->runMode() == Constants::DEBUGMODE ? m_debugIcon : m_runIcon);
+ m_reRunButton->setIcon(m_runIcon);
}
}
@@ -427,9 +424,9 @@ void OutputPane::runControlFinished()
<< " current " << current << m_runControlTabs.size();
if (current && current == sender()) {
- m_reRunButton->setEnabled(current->runMode() == Constants::RUNMODE);
+ m_reRunButton->setEnabled(true);
m_stopAction->setEnabled(false);
- m_reRunButton->setIcon(current->runMode() == Constants::DEBUGMODE ? m_debugIcon : m_runIcon);
+ m_reRunButton->setIcon(m_runIcon);
}
// Check for asynchronous close. Close the tab.
if (m_runControlTabs.at(senderIndex).asyncClosing)
@@ -572,6 +569,27 @@ void OutputWindow::mouseMoveEvent(QMouseEvent *e)
QPlainTextEdit::mouseMoveEvent(e);
}
+void OutputWindow::resizeEvent(QResizeEvent *e)
+{
+ //Keep scrollbar at bottom of window while resizing, to ensure we keep scrolling
+ //This can happen if window is resized while building, or if the horizontal scrollbar appears
+ bool atBottom = isScrollbarAtBottom();
+ QPlainTextEdit::resizeEvent(e);
+ if (atBottom)
+ scrollToBottom();
+}
+
+void OutputWindow::keyPressEvent(QKeyEvent *ev)
+{
+ QPlainTextEdit::keyPressEvent(ev);
+
+ //Ensure we scroll also on Ctrl+Home or Ctrl+End
+ if (ev->matches(QKeySequence::MoveToStartOfDocument))
+ verticalScrollBar()->triggerAction(QAbstractSlider::SliderToMinimum);
+ else if (ev->matches(QKeySequence::MoveToEndOfDocument))
+ verticalScrollBar()->triggerAction(QAbstractSlider::SliderToMaximum);
+}
+
OutputFormatter *OutputWindow::formatter() const
{
return m_formatter;
diff --git a/src/plugins/projectexplorer/outputwindow.h b/src/plugins/projectexplorer/outputwindow.h
index d51ce9bcb9..f374bcf7d6 100644
--- a/src/plugins/projectexplorer/outputwindow.h
+++ b/src/plugins/projectexplorer/outputwindow.h
@@ -143,7 +143,6 @@ private:
QToolButton *m_reRunButton;
QToolButton *m_stopButton;
QIcon m_runIcon;
- QIcon m_debugIcon;
};
@@ -179,6 +178,8 @@ protected:
virtual void mousePressEvent(QMouseEvent *e);
virtual void mouseReleaseEvent(QMouseEvent *e);
virtual void mouseMoveEvent(QMouseEvent *e);
+ virtual void resizeEvent(QResizeEvent *e);
+ virtual void keyPressEvent(QKeyEvent *ev);
private slots:
void updateWordWrapMode();
diff --git a/src/plugins/projectexplorer/pluginfilefactory.h b/src/plugins/projectexplorer/pluginfilefactory.h
index 63a70de7d8..47be98bbcc 100644
--- a/src/plugins/projectexplorer/pluginfilefactory.h
+++ b/src/plugins/projectexplorer/pluginfilefactory.h
@@ -36,7 +36,6 @@
#include <coreplugin/ifilefactory.h>
-#include <QtCore/QObject>
#include <QtCore/QStringList>
namespace ProjectExplorer {
diff --git a/src/plugins/projectexplorer/processparameters.cpp b/src/plugins/projectexplorer/processparameters.cpp
new file mode 100644
index 0000000000..448d17f67c
--- /dev/null
+++ b/src/plugins/projectexplorer/processparameters.cpp
@@ -0,0 +1,149 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "processparameters.h"
+
+#include <utils/stringutils.h>
+#include <utils/qtcprocess.h>
+
+#include <QtCore/QFileInfo>
+#include <QtCore/QDir>
+
+using namespace ProjectExplorer;
+
+ProcessParameters::ProcessParameters() :
+ m_macroExpander(0),
+ m_commandMissing(false)
+{
+}
+
+void ProcessParameters::setCommand(const QString &cmd)
+{
+ m_command = cmd;
+ m_effectiveCommand.clear();
+}
+
+void ProcessParameters::setArguments(const QString &arguments)
+{
+ m_arguments = arguments;
+ m_effectiveArguments.clear();
+}
+
+void ProcessParameters::setWorkingDirectory(const QString &workingDirectory)
+{
+ m_workingDirectory = workingDirectory;
+ m_effectiveWorkingDirectory.clear();
+}
+
+QString ProcessParameters::effectiveWorkingDirectory() const
+{
+ if (m_effectiveWorkingDirectory.isEmpty()) {
+ QString wds = m_workingDirectory;
+ if (m_macroExpander)
+ Utils::expandMacros(&wds, m_macroExpander);
+ m_effectiveWorkingDirectory = QDir::cleanPath(m_environment.expandVariables(wds));
+ }
+ return m_effectiveWorkingDirectory;
+}
+
+QString ProcessParameters::effectiveCommand() const
+{
+ if (m_effectiveCommand.isEmpty()) {
+ QString cmd = m_command;
+ if (m_macroExpander)
+ Utils::expandMacros(&cmd, m_macroExpander);
+ m_effectiveCommand = QDir::cleanPath(m_environment.searchInPath(
+ cmd, QStringList() << effectiveWorkingDirectory()));
+ m_commandMissing = m_effectiveCommand.isEmpty();
+ if (m_commandMissing)
+ m_effectiveCommand = cmd;
+ }
+ return m_effectiveCommand;
+}
+
+bool ProcessParameters::commandMissing() const
+{
+ effectiveCommand();
+ return m_commandMissing;
+}
+
+QString ProcessParameters::effectiveArguments() const
+{
+ if (m_effectiveArguments.isEmpty()) {
+ m_effectiveArguments = m_arguments;
+ if (m_macroExpander)
+ Utils::expandMacros(&m_effectiveArguments, m_macroExpander);
+ }
+ return m_effectiveArguments;
+}
+
+QString ProcessParameters::prettyCommand() const
+{
+ QString cmd = m_command;
+ if (m_macroExpander)
+ Utils::expandMacros(&cmd, m_macroExpander);
+ return QFileInfo(cmd).fileName();
+}
+
+QString ProcessParameters::prettyArguments() const
+{
+ QString margs = effectiveArguments();
+ QString workDir = effectiveWorkingDirectory();
+#ifdef Q_OS_WIN
+ QString args;
+#else
+ QStringList args;
+#endif
+ Utils::QtcProcess::SplitError err;
+ args = Utils::QtcProcess::prepareArgs(margs, &err, &m_environment, &workDir);
+ if (err != Utils::QtcProcess::SplitOk)
+ return margs; // Sorry, too complex - just fall back.
+#ifdef Q_OS_WIN
+ return args;
+#else
+ return Utils::QtcProcess::joinArgs(args);
+#endif
+}
+
+QString ProcessParameters::summary(const QString &displayName) const
+{
+ return QString::fromLatin1("<b>%1:</b> %2 %3")
+ .arg(displayName,
+ Utils::QtcProcess::quoteArg(prettyCommand()),
+ prettyArguments());
+}
+
+QString ProcessParameters::summaryInWorkdir(const QString &displayName) const
+{
+ return QString::fromLatin1("<b>%1:</b> %2 %3 in %4")
+ .arg(displayName,
+ Utils::QtcProcess::quoteArg(prettyCommand()),
+ prettyArguments(),
+ QDir::toNativeSeparators(effectiveWorkingDirectory()));
+}
diff --git a/src/plugins/projectexplorer/processparameters.h b/src/plugins/projectexplorer/processparameters.h
new file mode 100644
index 0000000000..1b7e739d42
--- /dev/null
+++ b/src/plugins/projectexplorer/processparameters.h
@@ -0,0 +1,109 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 PROCESSPARAMETERS_H
+#define PROCESSPARAMETERS_H
+
+#include "projectexplorer_export.h"
+
+#include <utils/environment.h>
+
+namespace Utils {
+class AbstractMacroExpander;
+}
+
+namespace ProjectExplorer {
+
+/*!
+ ProcessParameters aggregates all parameters needed to start a process.
+
+ It offers a set of functions which expand macros and environment variables
+ inside the raw parameters to obtain final values for starting a process
+ or for display purposes.
+*/
+
+class PROJECTEXPLORER_EXPORT ProcessParameters
+{
+public:
+ ProcessParameters();
+
+ /// setCommand() sets the executable to run
+ void setCommand(const QString &cmd);
+ QString command() const { return m_command; }
+
+ /// sets the command line arguments used by the process
+ void setArguments(const QString &arguments);
+ QString arguments() const { return m_arguments; }
+
+ /// sets the workingDirectory for the process for a buildConfiguration
+ /// should be called from init()
+ void setWorkingDirectory(const QString &workingDirectory);
+ QString workingDirectory() const { return m_workingDirectory; }
+
+ /// Set the Environment for running the command
+ /// should be called from init()
+ void setEnvironment(const Utils::Environment &env) { m_environment = env; }
+ Utils::Environment environment() const { return m_environment; }
+
+ /// Set the macro expander to use on the command, arguments and working dir.
+ /// Note that the caller retains ownership of the object.
+ void setMacroExpander(Utils::AbstractMacroExpander *mx) { m_macroExpander = mx; }
+ Utils::AbstractMacroExpander *macroExpander() const { return m_macroExpander; }
+
+ /// Get the fully expanded working directory:
+ QString effectiveWorkingDirectory() const;
+ /// Get the fully expanded command name to run:
+ QString effectiveCommand() const;
+ /// Get the fully expanded arguments to use:
+ QString effectiveArguments() const;
+
+ /// True if effectiveCommand() would return only a fallback
+ bool commandMissing() const;
+
+ QString prettyCommand() const;
+ QString prettyArguments() const;
+ QString summary(const QString &displayName) const;
+ QString summaryInWorkdir(const QString &displayName) const;
+
+private:
+ QString m_workingDirectory;
+ QString m_command;
+ QString m_arguments;
+ Utils::Environment m_environment;
+ Utils::AbstractMacroExpander *m_macroExpander;
+
+ mutable QString m_effectiveWorkingDirectory;
+ mutable QString m_effectiveCommand;
+ mutable QString m_effectiveArguments;
+ mutable bool m_commandMissing;
+};
+
+} // namespace ProjectExplorer
+
+#endif // PROCESSPARAMETERS_H
diff --git a/src/plugins/projectexplorer/processstep.cpp b/src/plugins/projectexplorer/processstep.cpp
index 9dd5583343..78680399b1 100644
--- a/src/plugins/projectexplorer/processstep.cpp
+++ b/src/plugins/projectexplorer/processstep.cpp
@@ -37,6 +37,7 @@
#include "buildconfiguration.h"
#include <coreplugin/ifile.h>
+#include <utils/qtcprocess.h>
#include <utils/qtcassert.h>
#include <QtCore/QDebug>
@@ -82,7 +83,7 @@ void ProcessStep::ctor()
//: Default ProcessStep display name
setDefaultDisplayName(tr("Custom Process Step"));
if (m_workingDirectory.isEmpty())
- m_workingDirectory = QLatin1String("$BUILDDIR");
+ m_workingDirectory = QLatin1String(DEFAULT_WORKING_DIR);
}
ProcessStep::~ProcessStep()
@@ -92,12 +93,13 @@ ProcessStep::~ProcessStep()
bool ProcessStep::init()
{
BuildConfiguration *bc = buildConfiguration();
- setEnvironment(bc->environment());
-
- AbstractProcessStep::setWorkingDirectory(workingDirectory());
- AbstractProcessStep::setCommand(m_command);
+ ProcessParameters *pp = processParameters();
+ pp->setMacroExpander(bc->macroExpander());
+ pp->setEnvironment(bc->environment());
+ pp->setWorkingDirectory(workingDirectory());
+ pp->setCommand(m_command);
+ pp->setArguments(m_arguments);
AbstractProcessStep::setEnabled(m_enabled);
- AbstractProcessStep::setArguments(m_arguments);
setOutputParser(bc->createOutputParser());
return AbstractProcessStep::init();
}
@@ -122,7 +124,7 @@ QString ProcessStep::command() const
return m_command;
}
-QStringList ProcessStep::arguments() const
+QString ProcessStep::arguments() const
{
return m_arguments;
}
@@ -142,7 +144,7 @@ void ProcessStep::setCommand(const QString &command)
m_command = command;
}
-void ProcessStep::setArguments(const QStringList &arguments)
+void ProcessStep::setArguments(const QString &arguments)
{
m_arguments = arguments;
}
@@ -155,7 +157,7 @@ void ProcessStep::setEnabled(bool enabled)
void ProcessStep::setWorkingDirectory(const QString &workingDirectory)
{
if (workingDirectory.isEmpty())
- m_workingDirectory = QLatin1String("$BUILDDIR");
+ m_workingDirectory = QLatin1String(DEFAULT_WORKING_DIR);
else
m_workingDirectory = workingDirectory;
}
@@ -174,7 +176,7 @@ QVariantMap ProcessStep::toMap() const
bool ProcessStep::fromMap(const QVariantMap &map)
{
setCommand(map.value(QLatin1String(PROCESS_COMMAND_KEY)).toString());
- setArguments(map.value(QLatin1String(PROCESS_ARGUMENTS_KEY)).toStringList());
+ setArguments(map.value(QLatin1String(PROCESS_ARGUMENTS_KEY)).toString());
setWorkingDirectory(map.value(QLatin1String(PROCESS_WORKINGDIRECTORY_KEY)).toString());
setEnabled(map.value(QLatin1String(PROCESS_ENABLED_KEY), false).toBool());
return AbstractProcessStep::fromMap(map);
@@ -271,12 +273,18 @@ void ProcessStepConfigWidget::updateDetails()
{
QString displayName = m_step->displayName();
if (displayName.isEmpty())
- displayName = "Custom Process Step";
- m_summaryText = tr("<b>%1</b> %2 %3 %4")
- .arg(displayName,
- m_step->command(),
- m_step->arguments().join(QString(QLatin1Char(' '))),
- m_step->enabled() ? QString() : tr("(disabled)"));
+ displayName = tr("Custom Process Step");
+ ProcessParameters param;
+ param.setMacroExpander(m_step->buildConfiguration()->macroExpander());
+ param.setEnvironment(m_step->buildConfiguration()->environment());
+ param.setWorkingDirectory(m_step->workingDirectory());
+ param.setCommand(m_step->command());
+ param.setArguments(m_step->arguments());
+ m_summaryText = param.summary(displayName);
+ if (!m_step->enabled()) {
+ //: %1 is the custom process step summary
+ m_summaryText = tr("%1 (disabled)").arg(m_summaryText);
+ }
emit updateSummary();
}
@@ -293,7 +301,7 @@ void ProcessStepConfigWidget::init()
m_ui.workingDirectory->setEnvironment(m_step->buildConfiguration()->environment());
m_ui.workingDirectory->setPath(m_step->workingDirectory());
- m_ui.commandArgumentsLineEdit->setText(m_step->arguments().join(QString(QLatin1Char(' '))));
+ m_ui.commandArgumentsLineEdit->setText(m_step->arguments());
m_ui.enabledCheckBox->setChecked(m_step->enabled());
updateDetails();
@@ -317,8 +325,7 @@ void ProcessStepConfigWidget::workingDirectoryLineEditTextEdited()
void ProcessStepConfigWidget::commandArgumentsLineEditTextEdited()
{
- m_step->setArguments(m_ui.commandArgumentsLineEdit->text().split(QLatin1Char(' '),
- QString::SkipEmptyParts));
+ m_step->setArguments(m_ui.commandArgumentsLineEdit->text());
updateDetails();
}
diff --git a/src/plugins/projectexplorer/processstep.h b/src/plugins/projectexplorer/processstep.h
index 3d358eee16..b69c17b651 100644
--- a/src/plugins/projectexplorer/processstep.h
+++ b/src/plugins/projectexplorer/processstep.h
@@ -77,12 +77,12 @@ public:
virtual bool immutable() const;
QString command() const;
- QStringList arguments() const;
+ QString arguments() const;
bool enabled() const;
QString workingDirectory() const;
void setCommand(const QString &command);
- void setArguments(const QStringList &arguments);
+ void setArguments(const QString &arguments);
void setEnabled(bool enabled);
void setWorkingDirectory(const QString &workingDirectory);
@@ -98,7 +98,7 @@ private:
void ctor();
QString m_command;
- QStringList m_arguments;
+ QString m_arguments;
QString m_workingDirectory;
Utils::Environment m_env;
bool m_enabled;
diff --git a/src/plugins/projectexplorer/project.cpp b/src/plugins/projectexplorer/project.cpp
index b7b0d808a8..7aecc28ea3 100644
--- a/src/plugins/projectexplorer/project.cpp
+++ b/src/plugins/projectexplorer/project.cpp
@@ -264,9 +264,6 @@ bool Project::fromMap(const QVariantMap &map)
d->m_editorConfiguration->fromMap(values);
}
- int previousFileVersion = map.value(QLatin1String(Constants::USERFILE_PREVIOUS_VERSION_KEY),
- std::numeric_limits<int>::max()).toInt();
-
bool ok;
int maxI(map.value(QLatin1String(TARGET_COUNT_KEY), 0).toInt(&ok));
if (!ok || maxI < 0)
@@ -283,9 +280,19 @@ bool Project::fromMap(const QVariantMap &map)
qWarning() << key << "was not found in data.";
return false;
}
- QVariantMap targetMap = map.value(key).toMap();
- targetMap.insert(Constants::USERFILE_PREVIOUS_VERSION_KEY, previousFileVersion);
- Target *t(targetFactory()->restore(this, targetMap));
+ QVariantMap targetMap = map.value(key).toMap();
+
+ QList<ITargetFactory *> factories =
+ ExtensionSystem::PluginManager::instance()->getObjects<ITargetFactory>();
+
+ Target *t = 0;
+ foreach (ITargetFactory *factory, factories) {
+ if (factory->canRestore(this, targetMap)) {
+ t = factory->restore(this, targetMap);
+ break;
+ }
+ }
+
if (!t) {
qWarning() << "Restoration of a target failed! (Continuing)";
continue;
diff --git a/src/plugins/projectexplorer/project.h b/src/plugins/projectexplorer/project.h
index 3e36f8c13d..03707bb812 100644
--- a/src/plugins/projectexplorer/project.h
+++ b/src/plugins/projectexplorer/project.h
@@ -98,12 +98,9 @@ public:
void setActiveTarget(Target *target);
Target *target(const QString &id) const;
- virtual ITargetFactory *targetFactory() const = 0;
-
void saveSettings();
bool restoreSettings();
- virtual BuildConfigWidget *createConfigWidget() = 0;
virtual QList<BuildConfigWidget*> subConfigWidgets();
virtual ProjectNode *rootProjectNode() const = 0;
diff --git a/src/plugins/projectexplorer/projectconfiguration.cpp b/src/plugins/projectexplorer/projectconfiguration.cpp
index cb52a39143..ce0a2a70f1 100644
--- a/src/plugins/projectexplorer/projectconfiguration.cpp
+++ b/src/plugins/projectexplorer/projectconfiguration.cpp
@@ -103,7 +103,9 @@ bool ProjectConfiguration::fromMap(const QVariantMap &map)
{
m_id = map.value(QLatin1String(CONFIGURATION_ID_KEY), QString()).toString();
m_displayName = map.value(QLatin1String(DISPLAY_NAME_KEY), QString()).toString();
- m_defaultDisplayName = map.value(QLatin1String(DEFAULT_DISPLAY_NAME_KEY), m_displayName).toString();
+ m_defaultDisplayName = map.value(QLatin1String(DEFAULT_DISPLAY_NAME_KEY),
+ m_defaultDisplayName.isEmpty() ?
+ m_displayName : m_defaultDisplayName).toString();
return !m_id.isEmpty();
}
diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp
index bf76ba9627..3b733d6d07 100644
--- a/src/plugins/projectexplorer/projectexplorer.cpp
+++ b/src/plugins/projectexplorer/projectexplorer.cpp
@@ -42,7 +42,7 @@
#include "copytaskhandler.h"
#include "showineditortaskhandler.h"
#include "vcsannotatetaskhandler.h"
-#include "applicationrunconfiguration.h"
+#include "localapplicationruncontrol.h"
#include "allprojectsfilter.h"
#include "allprojectsfind.h"
#include "buildmanager.h"
@@ -69,6 +69,7 @@
#include "runsettingspropertiespage.h"
#include "scriptwrappers.h"
#include "session.h"
+#include "projectnodes.h"
#include "sessiondialog.h"
#include "target.h"
#include "projectexplorersettingspage.h"
@@ -76,20 +77,21 @@
#include "projectwelcomepagewidget.h"
#include "corelistenercheckingforrunningbuild.h"
#include "buildconfiguration.h"
-#include "buildconfigdialog.h"
#include "miniprojecttargetselector.h"
#include "taskhub.h"
+#include "publishing/ipublishingwizardfactory.h"
+#include "publishing/publishingwizardselectiondialog.h"
-#include <coreplugin/basemode.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/filemanager.h>
#include <coreplugin/icore.h>
-#include <coreplugin/mainwindow.h>
+#include <coreplugin/imode.h>
#include <coreplugin/mimedatabase.h>
#include <coreplugin/modemanager.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/command.h>
+#include <coreplugin/uniqueidmanager.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/editormanager/ieditorfactory.h>
@@ -100,6 +102,7 @@
#include <coreplugin/iversioncontrol.h>
#include <welcome/welcomemode.h>
#include <extensionsystem/pluginmanager.h>
+#include <find/searchresultwindow.h>
#include <utils/consoleprocess.h>
#include <utils/qtcassert.h>
#include <utils/parameteraction.h>
@@ -115,9 +118,11 @@
#include <QtGui/QFileDialog>
#include <QtGui/QMenu>
#include <QtGui/QMessageBox>
+#include <QtGui/QMainWindow>
+#include <QtGui/QWizard>
-Q_DECLARE_METATYPE(Core::IEditorFactory*);
-Q_DECLARE_METATYPE(Core::IExternalEditor*);
+Q_DECLARE_METATYPE(Core::IEditorFactory*)
+Q_DECLARE_METATYPE(Core::IExternalEditor*)
namespace {
bool debug = false;
@@ -155,15 +160,16 @@ struct ProjectExplorerPluginPrivate {
Utils::ParameterAction *m_deployAction;
Utils::ParameterAction *m_deployActionContextMenu;
QAction *m_deploySessionAction;
+ Utils::ParameterAction *m_publishAction;
Utils::ParameterAction *m_cleanAction;
Utils::ParameterAction *m_cleanActionContextMenu;
QAction *m_cleanSessionAction;
QAction *m_runAction;
QAction *m_runActionContextMenu;
QAction *m_cancelBuildAction;
- QAction *m_debugAction;
QAction *m_addNewFileAction;
QAction *m_addExistingFilesAction;
+ QAction *m_addNewSubprojectAction;
QAction *m_removeFileAction;
QAction *m_removeProjectAction;
QAction *m_deleteFileAction;
@@ -199,7 +205,7 @@ struct ProjectExplorerPluginPrivate {
Internal::ProjectExplorerSettings m_projectExplorerSettings;
Internal::ProjectWelcomePage *m_welcomePage;
- Core::BaseMode * m_projectsMode;
+ Core::IMode *m_projectsMode;
};
ProjectExplorerPluginPrivate::ProjectExplorerPluginPrivate() :
@@ -210,6 +216,25 @@ ProjectExplorerPluginPrivate::ProjectExplorerPluginPrivate() :
{
}
+class ProjectsMode : public Core::IMode
+{
+public:
+ ProjectsMode(QWidget *proWindow) : m_widget(proWindow) {}
+
+ QString displayName() const { return tr("Projects"); }
+ QIcon icon() const { return QIcon(QLatin1String(":/fancyactionbar/images/mode_Project.png")); }
+ int priority() const { return Constants::P_MODE_SESSION; }
+ QWidget *widget() { return m_widget; }
+ QString id() const { return QLatin1String(Constants::MODE_SESSION); }
+ QString type() const { return QString(); }
+ Core::Context context() const { return Core::Context(Constants::C_PROJECTEXPLORER); }
+ QString contextHelpId() const { return QLatin1String("Managing Projects"); }
+
+private:
+ QWidget *m_widget;
+ QIcon m_icon;
+};
+
} // namespace ProjectExplorer
using namespace ProjectExplorer;
@@ -278,17 +303,10 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
d->m_proWindow = new ProjectWindow;
Core::Context globalcontext(Core::Constants::C_GLOBAL);
- Core::Context pecontext(Constants::C_PROJECTEXPLORER);
-
- d->m_projectsMode = new Core::BaseMode;
- d->m_projectsMode->setDisplayName(tr("Projects"));
- d->m_projectsMode->setId(QLatin1String(Constants::MODE_SESSION));
- d->m_projectsMode->setIcon(QIcon(QLatin1String(":/fancyactionbar/images/mode_Project.png")));
- d->m_projectsMode->setPriority(Constants::P_MODE_SESSION);
- d->m_projectsMode->setWidget(d->m_proWindow);
- d->m_projectsMode->setContext(pecontext);
+ Core::Context projecTreeContext(Constants::C_PROJECT_TREE);
+
+ d->m_projectsMode = new ProjectsMode(d->m_proWindow);
d->m_projectsMode->setEnabled(session()->startupProject());
- d->m_projectsMode->setContextHelpId(QLatin1String("Managing Projects"));
addAutoReleasedObject(d->m_projectsMode);
d->m_proWindow->layout()->addWidget(new Core::FindToolBarPlaceHolder(d->m_proWindow));
@@ -342,20 +360,20 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
// context menus
Core::ActionContainer *msessionContextMenu =
am->createMenu(Constants::M_SESSIONCONTEXT);
- Core::ActionContainer *mproject =
+ Core::ActionContainer *mprojectContextMenu =
am->createMenu(Constants::M_PROJECTCONTEXT);
- Core::ActionContainer *msubProject =
+ Core::ActionContainer *msubProjectContextMenu =
am->createMenu(Constants::M_SUBPROJECTCONTEXT);
- Core::ActionContainer *mfolder =
+ Core::ActionContainer *mfolderContextMenu =
am->createMenu(Constants::M_FOLDERCONTEXT);
- Core::ActionContainer *mfilec =
+ Core::ActionContainer *mfileContextMenu =
am->createMenu(Constants::M_FILECONTEXT);
d->m_sessionContextMenu = msessionContextMenu->menu();
- d->m_projectMenu = mproject->menu();
- d->m_subProjectMenu = msubProject->menu();
- d->m_folderMenu = mfolder->menu();
- d->m_fileMenu = mfilec->menu();
+ d->m_projectMenu = mprojectContextMenu->menu();
+ d->m_subProjectMenu = msubProjectContextMenu->menu();
+ d->m_folderMenu = mfolderContextMenu->menu();
+ d->m_fileMenu = mfileContextMenu->menu();
Core::ActionContainer *mfile =
am->actionContainer(Core::Constants::M_FILE);
@@ -397,31 +415,31 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
msessionContextMenu->appendGroup(Constants::G_SESSION_OTHER);
msessionContextMenu->appendGroup(Constants::G_SESSION_CONFIG);
- mproject->appendGroup(Constants::G_PROJECT_FIRST);
- mproject->appendGroup(Constants::G_PROJECT_BUILD);
- mproject->appendGroup(Constants::G_PROJECT_RUN);
- mproject->appendGroup(Constants::G_PROJECT_FILES);
- mproject->appendGroup(Constants::G_PROJECT_OTHER);
- mproject->appendGroup(Constants::G_PROJECT_CONFIG);
+ mprojectContextMenu->appendGroup(Constants::G_PROJECT_FIRST);
+ mprojectContextMenu->appendGroup(Constants::G_PROJECT_BUILD);
+ mprojectContextMenu->appendGroup(Constants::G_PROJECT_RUN);
+ mprojectContextMenu->appendGroup(Constants::G_PROJECT_FILES);
+ mprojectContextMenu->appendGroup(Constants::G_PROJECT_OTHER);
+ mprojectContextMenu->appendGroup(Constants::G_PROJECT_CONFIG);
- msubProject->appendGroup(Constants::G_PROJECT_FIRST);
- msubProject->appendGroup(Constants::G_PROJECT_BUILD);
- msubProject->appendGroup(Constants::G_PROJECT_FILES);
- msubProject->appendGroup(Constants::G_PROJECT_OTHER);
- msubProject->appendGroup(Constants::G_PROJECT_CONFIG);
+ msubProjectContextMenu->appendGroup(Constants::G_PROJECT_FIRST);
+ msubProjectContextMenu->appendGroup(Constants::G_PROJECT_BUILD);
+ msubProjectContextMenu->appendGroup(Constants::G_PROJECT_FILES);
+ msubProjectContextMenu->appendGroup(Constants::G_PROJECT_OTHER);
+ msubProjectContextMenu->appendGroup(Constants::G_PROJECT_CONFIG);
- mfolder->appendGroup(Constants::G_FOLDER_FILES);
- mfolder->appendGroup(Constants::G_FOLDER_OTHER);
- mfolder->appendGroup(Constants::G_FOLDER_CONFIG);
+ mfolderContextMenu->appendGroup(Constants::G_FOLDER_FILES);
+ mfolderContextMenu->appendGroup(Constants::G_FOLDER_OTHER);
+ mfolderContextMenu->appendGroup(Constants::G_FOLDER_CONFIG);
- mfilec->appendGroup(Constants::G_FILE_OPEN);
- mfilec->appendGroup(Constants::G_FILE_OTHER);
- mfilec->appendGroup(Constants::G_FILE_CONFIG);
+ mfileContextMenu->appendGroup(Constants::G_FILE_OPEN);
+ mfileContextMenu->appendGroup(Constants::G_FILE_OTHER);
+ mfileContextMenu->appendGroup(Constants::G_FILE_CONFIG);
// "open with" submenu
Core::ActionContainer * const openWith =
am->createMenu(ProjectExplorer::Constants::M_OPENFILEWITHCONTEXT);
- openWith->setEmptyAction(Core::ActionContainer::EA_None);
+ openWith->setOnAllDisabledBehavior(Core::ActionContainer::Show);
d->m_openWithMenu = openWith->menu();
d->m_openWithMenu->setTitle(tr("Open With"));
@@ -442,17 +460,17 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
sep = new QAction(this);
sep->setSeparator(true);
- cmd = am->registerAction(sep, Core::Id("ProjectExplorer.Files.Sep"), globalcontext);
+ cmd = am->registerAction(sep, Core::Id("ProjectExplorer.Files.Sep"), projecTreeContext);
msessionContextMenu->addAction(cmd, Constants::G_SESSION_FILES);
- mproject->addAction(cmd, Constants::G_PROJECT_FILES);
- msubProject->addAction(cmd, Constants::G_PROJECT_FILES);
+ mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
+ msubProjectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
sep = new QAction(this);
sep->setSeparator(true);
- cmd = am->registerAction(sep, Core::Id("ProjectExplorer.Config.Sep"), globalcontext);
+ cmd = am->registerAction(sep, Core::Id("ProjectExplorer.Config.Sep"), projecTreeContext);
msessionContextMenu->addAction(cmd, Constants::G_SESSION_CONFIG);
- mproject->addAction(cmd, Constants::G_PROJECT_CONFIG);
- msubProject->addAction(cmd, Constants::G_PROJECT_CONFIG);
+ mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_CONFIG);
+ msubProjectContextMenu->addAction(cmd, Constants::G_PROJECT_CONFIG);
sep = new QAction(this);
sep->setSeparator(true);
@@ -464,14 +482,14 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
cmd = am->registerAction(sep, Core::Id("ProjectExplorer.Other.Sep"), globalcontext);
mbuild->addAction(cmd, Constants::G_BUILD_OTHER);
msessionContextMenu->addAction(cmd, Constants::G_SESSION_OTHER);
- mproject->addAction(cmd, Constants::G_PROJECT_OTHER);
- msubProject->addAction(cmd, Constants::G_PROJECT_OTHER);
+ mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_OTHER);
+ msubProjectContextMenu->addAction(cmd, Constants::G_PROJECT_OTHER);
sep = new QAction(this);
sep->setSeparator(true);
cmd = am->registerAction(sep, Core::Id("ProjectExplorer.Run.Sep"), globalcontext);
mbuild->addAction(cmd, Constants::G_BUILD_RUN);
- mproject->addAction(cmd, Constants::G_PROJECT_RUN);
+ mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_RUN);
sep = new QAction(this);
sep->setSeparator(true);
@@ -504,32 +522,34 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
// Default open action
d->m_openFileAction = new QAction(tr("Open File"), this);
cmd = am->registerAction(d->m_openFileAction, ProjectExplorer::Constants::OPENFILE,
- globalcontext);
- mfilec->addAction(cmd, Constants::G_FILE_OPEN);
+ projecTreeContext);
+ mfileContextMenu->addAction(cmd, Constants::G_FILE_OPEN);
d->m_showInGraphicalShell = new QAction(FolderNavigationWidget::msgGraphicalShellAction(), this);
cmd = am->registerAction(d->m_showInGraphicalShell, ProjectExplorer::Constants::SHOWINGRAPHICALSHELL,
- globalcontext);
- mfilec->addAction(cmd, Constants::G_FILE_OPEN);
- mfolder->addAction(cmd, Constants::G_FOLDER_FILES);
+ projecTreeContext);
+ mfileContextMenu->addAction(cmd, Constants::G_FILE_OPEN);
+ mfolderContextMenu->addAction(cmd, Constants::G_FOLDER_FILES);
d->m_openTerminalHere = new QAction(FolderNavigationWidget::msgTerminalAction(), this);
cmd = am->registerAction(d->m_openTerminalHere, ProjectExplorer::Constants::OPENTERMIANLHERE,
- globalcontext);
- mfilec->addAction(cmd, Constants::G_FILE_OPEN);
- mfolder->addAction(cmd, Constants::G_FOLDER_FILES);
+ projecTreeContext);
+ mfileContextMenu->addAction(cmd, Constants::G_FILE_OPEN);
+ mfolderContextMenu->addAction(cmd, Constants::G_FOLDER_FILES);
// Open With menu
- mfilec->addMenu(openWith, ProjectExplorer::Constants::G_FILE_OPEN);
+ mfileContextMenu->addMenu(openWith, ProjectExplorer::Constants::G_FILE_OPEN);
// recent projects menu
Core::ActionContainer *mrecent =
am->createMenu(Constants::M_RECENTPROJECTS);
mrecent->menu()->setTitle(tr("Recent P&rojects"));
+ mrecent->setOnAllDisabledBehavior(Core::ActionContainer::Show);
mfile->addMenu(mrecent, Core::Constants::G_FILE_OPEN);
connect(mfile->menu(), SIGNAL(aboutToShow()),
this, SLOT(updateRecentProjectMenu()));
+ // XXX same action?
// unload action
d->m_unloadAction = new Utils::ParameterAction(tr("Close Project"), tr("Close Project \"%1\""),
Utils::ParameterAction::EnabledWithParameter, this);
@@ -537,7 +557,6 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
cmd->setAttribute(Core::Command::CA_UpdateText);
cmd->setDefaultText(d->m_unloadAction->text());
mfile->addAction(cmd, Core::Constants::G_FILE_PROJECT);
- mproject->addAction(cmd, Constants::G_PROJECT_FILES);
// unload session action
d->m_clearSession = new QAction(tr("Close All Projects"), this);
@@ -548,6 +567,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
// session menu
Core::ActionContainer *msession = am->createMenu(Constants::M_SESSION);
msession->menu()->setTitle(tr("Session"));
+ msession->setOnAllDisabledBehavior(Core::ActionContainer::Show);
mfile->addMenu(msession, Core::Constants::G_FILE_PROJECT);
d->m_sessionMenu = msession->menu();
connect(mfile->menu(), SIGNAL(aboutToShow()),
@@ -611,6 +631,14 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
cmd->setDefaultText(d->m_deployAction->text());
mbuild->addAction(cmd, Constants::G_BUILD_PROJECT);
+ // Publish action
+ d->m_publishAction = new Utils::ParameterAction(tr("Publish Project..."), tr("Publish Project \"%1\"..."),
+ Utils::ParameterAction::AlwaysEnabled, this);
+ cmd = am->registerAction(d->m_publishAction, Constants::PUBLISH, globalcontext);
+ cmd->setAttribute(Core::Command::CA_UpdateText);
+ cmd->setDefaultText(d->m_publishAction->text());
+ mbuild->addAction(cmd, Constants::G_BUILD_PROJECT);
+
// clean action
d->m_cleanAction = new Utils::ParameterAction(tr("Clean Project"), tr("Clean Project \"%1\""),
Utils::ParameterAction::AlwaysEnabled, this);
@@ -622,34 +650,34 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
// build action (context menu)
d->m_buildActionContextMenu = new Utils::ParameterAction(tr("Build Project"), tr("Build Project \"%1\""),
Utils::ParameterAction::AlwaysEnabled, this);
- cmd = am->registerAction(d->m_buildActionContextMenu, Constants::BUILDCM, globalcontext);
+ cmd = am->registerAction(d->m_buildActionContextMenu, Constants::BUILDCM, projecTreeContext);
cmd->setAttribute(Core::Command::CA_UpdateText);
cmd->setDefaultText(d->m_buildActionContextMenu->text());
- mproject->addAction(cmd, Constants::G_PROJECT_BUILD);
+ mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_BUILD);
// rebuild action (context menu)
d->m_rebuildActionContextMenu = new Utils::ParameterAction(tr("Rebuild Project"), tr("Rebuild Project \"%1\""),
Utils::ParameterAction::AlwaysEnabled, this);
- cmd = am->registerAction(d->m_rebuildActionContextMenu, Constants::REBUILDCM, globalcontext);
+ cmd = am->registerAction(d->m_rebuildActionContextMenu, Constants::REBUILDCM, projecTreeContext);
cmd->setAttribute(Core::Command::CA_UpdateText);
cmd->setDefaultText(d->m_rebuildActionContextMenu->text());
- mproject->addAction(cmd, Constants::G_PROJECT_BUILD);
+ mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_BUILD);
// deploy action (context menu)
d->m_deployActionContextMenu = new Utils::ParameterAction(tr("Deploy Project"), tr("Deploy Project \"%1\""),
Utils::ParameterAction::AlwaysEnabled, this);
- cmd = am->registerAction(d->m_deployActionContextMenu, Constants::DEPLOYCM, globalcontext);
+ cmd = am->registerAction(d->m_deployActionContextMenu, Constants::DEPLOYCM, projecTreeContext);
cmd->setAttribute(Core::Command::CA_UpdateText);
cmd->setDefaultText(d->m_deployActionContextMenu->text());
- mproject->addAction(cmd, Constants::G_PROJECT_BUILD);
+ mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_BUILD);
// clean action (context menu)
d->m_cleanActionContextMenu = new Utils::ParameterAction(tr("Clean Project"), tr("Clean Project \"%1\""),
Utils::ParameterAction::AlwaysEnabled, this);
- cmd = am->registerAction(d->m_cleanActionContextMenu, Constants::CLEANCM, globalcontext);
+ cmd = am->registerAction(d->m_cleanActionContextMenu, Constants::CLEANCM, projecTreeContext);
cmd->setAttribute(Core::Command::CA_UpdateText);
cmd->setDefaultText(d->m_cleanActionContextMenu->text());
- mproject->addAction(cmd, Constants::G_PROJECT_BUILD);
+ mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_BUILD);
// build without dependencies action
d->m_buildProjectOnlyAction = new QAction(tr("Build Without Dependencies"), this);
@@ -680,65 +708,63 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
modeManager->addAction(cmd, Constants::P_ACTION_RUN);
d->m_runActionContextMenu = new QAction(runIcon, tr("Run"), this);
- cmd = am->registerAction(d->m_runActionContextMenu, Constants::RUNCONTEXTMENU, globalcontext);
- mproject->addAction(cmd, Constants::G_PROJECT_RUN);
+ cmd = am->registerAction(d->m_runActionContextMenu, Constants::RUNCONTEXTMENU, projecTreeContext);
+ mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_RUN);
// cancel build action
d->m_cancelBuildAction = new QAction(tr("Cancel Build"), this);
cmd = am->registerAction(d->m_cancelBuildAction, Constants::CANCELBUILD, globalcontext);
mbuild->addAction(cmd, Constants::G_BUILD_CANCEL);
- // debug action
- QIcon debuggerIcon(":/projectexplorer/images/debugger_start_small.png");
- debuggerIcon.addFile(":/projectexplorer/images/debugger_start.png");
- d->m_debugAction = new QAction(debuggerIcon, tr("Start Debugging"), this);
- cmd = am->registerAction(d->m_debugAction, Constants::DEBUG, globalcontext);
- cmd->setAttribute(Core::Command::CA_UpdateText);
- cmd->setAttribute(Core::Command::CA_UpdateIcon);
- cmd->setDefaultText(tr("Start Debugging"));
- cmd->setDefaultKeySequence(QKeySequence(Constants::DEBUG_KEY));
- mstartdebugging->addAction(cmd, Core::Constants::G_DEFAULT_ONE);
- modeManager->addAction(cmd, Constants::P_ACTION_DEBUG);
-
// add new file action
d->m_addNewFileAction = new QAction(tr("Add New..."), this);
cmd = am->registerAction(d->m_addNewFileAction, ProjectExplorer::Constants::ADDNEWFILE,
- globalcontext);
- mproject->addAction(cmd, Constants::G_PROJECT_FILES);
- msubProject->addAction(cmd, Constants::G_PROJECT_FILES);
- mfolder->addAction(cmd, Constants::G_FOLDER_FILES);
+ projecTreeContext);
+ mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
+ msubProjectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
+ mfolderContextMenu->addAction(cmd, Constants::G_FOLDER_FILES);
// add existing file action
d->m_addExistingFilesAction = new QAction(tr("Add Existing Files..."), this);
cmd = am->registerAction(d->m_addExistingFilesAction, ProjectExplorer::Constants::ADDEXISTINGFILES,
- globalcontext);
- mproject->addAction(cmd, Constants::G_PROJECT_FILES);
- msubProject->addAction(cmd, Constants::G_PROJECT_FILES);
- mfolder->addAction(cmd, Constants::G_FOLDER_FILES);
+ projecTreeContext);
+ mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
+ msubProjectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
+ mfolderContextMenu->addAction(cmd, Constants::G_FOLDER_FILES);
+
+ // new subproject action
+ d->m_addNewSubprojectAction = new QAction(tr("New Subproject..."), this);
+ cmd = am->registerAction(d->m_addNewSubprojectAction, ProjectExplorer::Constants::ADDNEWSUBPROJECT,
+ projecTreeContext);
+ mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
+ msubProjectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
+
+ // unload project again, in right position
+ mprojectContextMenu->addAction(am->command(Constants::UNLOAD), Constants::G_PROJECT_FILES);
// remove file action
d->m_removeFileAction = new QAction(tr("Remove File..."), this);
cmd = am->registerAction(d->m_removeFileAction, ProjectExplorer::Constants::REMOVEFILE,
- globalcontext);
- mfilec->addAction(cmd, Constants::G_FILE_OTHER);
+ projecTreeContext);
+ mfileContextMenu->addAction(cmd, Constants::G_FILE_OTHER);
//: Remove project from parent profile (Project explorer view); will not physically delete any files.
d->m_removeProjectAction = new QAction(tr("Remove Project..."), this);
cmd = am->registerAction(d->m_removeProjectAction, ProjectExplorer::Constants::REMOVEPROJECT,
- globalcontext);
- msubProject->addAction(cmd, Constants::G_PROJECT_FILES);
+ projecTreeContext);
+ msubProjectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
// delete file action
d->m_deleteFileAction = new QAction(tr("Delete File..."), this);
cmd = am->registerAction(d->m_deleteFileAction, ProjectExplorer::Constants::DELETEFILE,
- globalcontext);
- mfilec->addAction(cmd, Constants::G_FILE_OTHER);
+ projecTreeContext);
+ mfileContextMenu->addAction(cmd, Constants::G_FILE_OTHER);
// renamefile action
d->m_renameFileAction = new QAction(tr("Rename"), this);
cmd = am->registerAction(d->m_renameFileAction, ProjectExplorer::Constants::RENAMEFILE,
- globalcontext);
- mfilec->addAction(cmd, Constants::G_FILE_OTHER);
+ projecTreeContext);
+ mfileContextMenu->addAction(cmd, Constants::G_FILE_OTHER);
// Not yet used by anyone, so hide for now
// mfolder->addAction(cmd, Constants::G_FOLDER_FILES);
// msubProject->addAction(cmd, Constants::G_FOLDER_FILES);
@@ -747,8 +773,8 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
// set startup project action
d->m_setStartupProjectAction = new QAction(tr("Set as Startup Project"), this);
cmd = am->registerAction(d->m_setStartupProjectAction, ProjectExplorer::Constants::SETSTARTUP,
- globalcontext);
- mproject->addAction(cmd, Constants::G_PROJECT_FIRST);
+ projecTreeContext);
+ mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_FIRST);
// target selector
d->m_projectSelectorAction = new QAction(this);
@@ -823,6 +849,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
connect(d->m_deployAction, SIGNAL(triggered()), this, SLOT(deployProject()));
connect(d->m_deployActionContextMenu, SIGNAL(triggered()), this, SLOT(deployProjectContextMenu()));
connect(d->m_deploySessionAction, SIGNAL(triggered()), this, SLOT(deploySession()));
+ connect(d->m_publishAction, SIGNAL(triggered()), this, SLOT(publishProject()));
connect(d->m_cleanProjectOnlyAction, SIGNAL(triggered()), this, SLOT(cleanProjectOnly()));
connect(d->m_cleanAction, SIGNAL(triggered()), this, SLOT(cleanProject()));
connect(d->m_cleanActionContextMenu, SIGNAL(triggered()), this, SLOT(cleanProjectContextMenu()));
@@ -830,11 +857,11 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
connect(d->m_runAction, SIGNAL(triggered()), this, SLOT(runProject()));
connect(d->m_runActionContextMenu, SIGNAL(triggered()), this, SLOT(runProjectContextMenu()));
connect(d->m_cancelBuildAction, SIGNAL(triggered()), this, SLOT(cancelBuild()));
- connect(d->m_debugAction, SIGNAL(triggered()), this, SLOT(debugProject()));
connect(d->m_unloadAction, SIGNAL(triggered()), this, SLOT(unloadProject()));
connect(d->m_clearSession, SIGNAL(triggered()), this, SLOT(clearSession()));
connect(d->m_addNewFileAction, SIGNAL(triggered()), this, SLOT(addNewFile()));
connect(d->m_addExistingFilesAction, SIGNAL(triggered()), this, SLOT(addExistingFiles()));
+ connect(d->m_addNewSubprojectAction, SIGNAL(triggered()), this, SLOT(addNewSubproject()));
connect(d->m_removeProjectAction, SIGNAL(triggered()), this, SLOT(removeProject()));
connect(d->m_openFileAction, SIGNAL(triggered()), this, SLOT(openFile()));
connect(d->m_showInGraphicalShell, SIGNAL(triggered()), this, SLOT(showInGraphicalShell()));
@@ -844,6 +871,8 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
connect(d->m_renameFileAction, SIGNAL(triggered()), this, SLOT(renameFile()));
connect(d->m_setStartupProjectAction, SIGNAL(triggered()), this, SLOT(setStartupProject()));
+ connect(this, SIGNAL(updateRunActions()), this, SLOT(slotUpdateRunActions()));
+
updateActions();
connect(Core::ICore::instance(), SIGNAL(coreAboutToOpen()),
@@ -1021,6 +1050,19 @@ void ProjectExplorerPlugin::setStartupProject(Project *project)
updateActions();
}
+void ProjectExplorerPlugin::publishProject()
+{
+ const Project * const project = d->m_session->startupProject();
+ QTC_ASSERT(project, return);
+ PublishingWizardSelectionDialog selectionDialog(project);
+ if (selectionDialog.exec() == QDialog::Accepted) {
+ QWizard * const publishingWizard
+ = selectionDialog.createSelectedWizard();
+ publishingWizard->exec();
+ delete publishingWizard;
+ }
+}
+
void ProjectExplorerPlugin::savePersistentSettings()
{
if (debug)
@@ -1257,7 +1299,7 @@ void ProjectExplorerPlugin::restoreSession()
}
}
- Core::ICore::instance()->openFiles(combinedList, Core::ICore::CanContainLineNumbers);
+ Core::ICore::instance()->openFiles(combinedList, Core::ICore::OpenFilesFlags(Core::ICore::CanContainLineNumbers | Core::ICore::SwitchMode));
updateActions();
}
@@ -1305,7 +1347,7 @@ void ProjectExplorerPlugin::showContextMenu(const QPoint &globalPos, Node *node)
contextMenu = d->m_sessionContextMenu;
}
- updateContextMenuActions(node);
+ updateContextMenuActions();
if (contextMenu && contextMenu->actions().count() > 0) {
contextMenu->popup(globalPos);
}
@@ -1356,7 +1398,7 @@ void ProjectExplorerPlugin::startRunControl(RunControl *runControl, const QStrin
this, SLOT(runControlFinished()));
runControl->start();
- updateRunActions();
+ emit updateRunActions();
}
void ProjectExplorerPlugin::buildQueueFinished(bool success)
@@ -1415,6 +1457,7 @@ void ProjectExplorerPlugin::setCurrent(Project *project, QString filePath, Node
if (debug)
qDebug() << "ProjectExplorer - currentNodeChanged(" << (node ? node->path() : "0") << ", " << (project ? project->displayName() : "0") << ")";
emit currentNodeChanged(d->m_currentNode, project);
+ updateContextMenuActions();
}
if (projectChanged) {
if (debug)
@@ -1476,6 +1519,8 @@ void ProjectExplorerPlugin::updateActions()
d->m_cleanSessionAction->setEnabled(hasProjects && !building);
d->m_cancelBuildAction->setEnabled(building);
+ d->m_publishAction->setEnabled(hasProjects);
+
d->m_projectSelectorAction->setEnabled(!session()->projects().isEmpty());
d->m_projectSelectorActionMenu->setEnabled(!session()->projects().isEmpty());
@@ -1667,12 +1712,12 @@ void ProjectExplorerPlugin::cleanSession()
void ProjectExplorerPlugin::runProject()
{
- runProjectImpl(startupProject(), ProjectExplorer::Constants::RUNMODE);
+ runProject(startupProject(), ProjectExplorer::Constants::RUNMODE);
}
void ProjectExplorerPlugin::runProjectContextMenu()
{
- runProjectImpl(d->m_currentProject, ProjectExplorer::Constants::RUNMODE);
+ runProject(d->m_currentProject, ProjectExplorer::Constants::RUNMODE);
}
bool ProjectExplorerPlugin::hasBuildSettings(Project *pro)
@@ -1713,15 +1758,13 @@ bool ProjectExplorerPlugin::hasDeploySettings(Project *pro)
return false;
}
-void ProjectExplorerPlugin::runProjectImpl(Project *pro, QString mode)
+void ProjectExplorerPlugin::runProject(Project *pro, QString mode)
{
if (!pro)
return;
- if (!pro->activeTarget()->activeRunConfiguration()->isEnabled()) {
- if (!showBuildConfigDialog())
- return;
- }
+ if (!pro->activeTarget()->activeRunConfiguration()->isEnabled())
+ return;
QStringList stepIds;
if (d->m_projectExplorerSettings.deployBeforeRun) {
@@ -1742,46 +1785,12 @@ void ProjectExplorerPlugin::runProjectImpl(Project *pro, QString mode)
} else {
executeRunConfiguration(pro->activeTarget()->activeRunConfiguration(), mode);
}
- updateRunActions();
-}
-
-void ProjectExplorerPlugin::debugProject()
-{
- Project *pro = startupProject();
- if (!pro)
- return;
-
- runProjectImpl(pro, ProjectExplorer::Constants::DEBUGMODE);
-}
-
-bool ProjectExplorerPlugin::showBuildConfigDialog()
-{
- Project *pro = startupProject();
- BuildConfigDialog *dialog = new BuildConfigDialog(pro,
- Core::ICore::instance()->mainWindow());
- dialog->exec();
- BuildConfiguration *otherConfig = dialog->selectedBuildConfiguration();
- int result = dialog->result();
- dialog->deleteLater();
- switch (result) {
- case BuildConfigDialog::ChangeBuild:
- if (otherConfig) {
- pro->activeTarget()->setActiveBuildConfiguration(otherConfig);
- return true;
- }
- return false;
- case BuildConfigDialog::Cancel:
- return false;
- case BuildConfigDialog::Continue:
- return true;
- default:
- return false;
- }
+ emit updateRunActions();
}
void ProjectExplorerPlugin::runControlFinished()
{
- updateRunActions();
+ emit updateRunActions();
}
void ProjectExplorerPlugin::startupProjectChanged()
@@ -1808,7 +1817,7 @@ void ProjectExplorerPlugin::startupProjectChanged()
activeTargetChanged();
- updateRunActions();
+ emit updateRunActions();
}
void ProjectExplorerPlugin::activeTargetChanged()
@@ -1844,14 +1853,14 @@ void ProjectExplorerPlugin::activeRunConfigurationChanged()
return;
if (previousRunConfiguration) {
disconnect(previousRunConfiguration, SIGNAL(isEnabledChanged(bool)),
- this, SLOT(updateRunActions()));
+ this, SIGNAL(updateRunActions()));
}
previousRunConfiguration = rc;
if (rc) {
connect(rc, SIGNAL(isEnabledChanged(bool)),
- this, SLOT(updateRunActions()));
+ this, SIGNAL(updateRunActions()));
}
- updateRunActions();
+ emit updateRunActions();
}
// NBS TODO implement more than one runner
@@ -1891,43 +1900,28 @@ void ProjectExplorerPlugin::updateDeployActions()
d->m_deploySessionAction->setEnabled(hasProjects && !building);
- updateRunActions();
+ emit updateRunActions();
}
-void ProjectExplorerPlugin::updateRunActions()
+bool ProjectExplorerPlugin::canRun(Project *project, const QString &runMode)
{
- const Project *project = startupProject();
-
if (!project ||
!project->activeTarget() ||
!project->activeTarget()->activeRunConfiguration()) {
-
- d->m_runAction->setToolTip(tr("Cannot run without a project."));
- d->m_debugAction->setToolTip(tr("Cannot debug without a project."));
-
- d->m_runAction->setEnabled(false);
- d->m_debugAction->setEnabled(false);
- return;
+ return false;
}
- d->m_runAction->setToolTip(QString());
- d->m_debugAction->setToolTip(QString());
-
RunConfiguration *activeRC = project->activeTarget()->activeRunConfiguration();
- bool canRun = findRunControlFactory(activeRC, ProjectExplorer::Constants::RUNMODE)
+ bool canRun = findRunControlFactory(activeRC, runMode)
&& activeRC->isEnabled();
- const bool canDebug = findRunControlFactory(activeRC, ProjectExplorer::Constants::DEBUGMODE)
- && activeRC->isEnabled();
const bool building = d->m_buildManager->isBuilding();
+ return (canRun && !building);
+}
- d->m_runAction->setEnabled(canRun && !building);
-
- canRun = session()->startupProject() && findRunControlFactory(activeRC, ProjectExplorer::Constants::RUNMODE);
-
- d->m_runActionContextMenu->setEnabled(canRun && !building);
-
- d->m_debugAction->setEnabled(canDebug && !building);
-
+void ProjectExplorerPlugin::slotUpdateRunActions()
+{
+ Project *project = startupProject();
+ d->m_runAction->setEnabled(canRun(project, ProjectExplorer::Constants::RUNMODE));
}
void ProjectExplorerPlugin::cancelBuild()
@@ -2017,23 +2011,27 @@ void ProjectExplorerPlugin::invalidateProject(Project *project)
updateActions();
}
-void ProjectExplorerPlugin::updateContextMenuActions(Node *node)
+void ProjectExplorerPlugin::updateContextMenuActions()
{
d->m_addExistingFilesAction->setEnabled(false);
d->m_addNewFileAction->setEnabled(false);
+ d->m_addNewSubprojectAction->setEnabled(false);
d->m_removeFileAction->setEnabled(false);
d->m_deleteFileAction->setEnabled(false);
+ d->m_renameFileAction->setEnabled(false);
d->m_addExistingFilesAction->setVisible(true);
d->m_removeFileAction->setVisible(true);
d->m_deleteFileAction->setVisible(true);
- if (node->projectNode()) {
+ if (d->m_currentNode && d->m_currentNode->projectNode()) {
QList<ProjectNode::ProjectAction> actions =
- d->m_currentNode->projectNode()->supportedActions(node);
+ d->m_currentNode->projectNode()->supportedActions(d->m_currentNode);
if (qobject_cast<FolderNode*>(d->m_currentNode)) {
d->m_addNewFileAction->setEnabled(actions.contains(ProjectNode::AddNewFile));
+ d->m_addNewSubprojectAction->setEnabled(d->m_currentNode->nodeType() == ProjectNodeType
+ && actions.contains(ProjectNode::AddSubProject));
d->m_addExistingFilesAction->setEnabled(actions.contains(ProjectNode::AddExistingFile));
d->m_renameFileAction->setEnabled(actions.contains(ProjectNode::Rename));
} else if (qobject_cast<FileNode*>(d->m_currentNode)) {
@@ -2054,12 +2052,11 @@ void ProjectExplorerPlugin::updateContextMenuActions(Node *node)
}
}
-void ProjectExplorerPlugin::addNewFile()
+QString ProjectExplorerPlugin::directoryFor(Node *node)
{
- QTC_ASSERT(d->m_currentNode, return)
- QString path = d->m_currentNode->path();
+ QString path = node->path();
QString location;
- FolderNode *folder = qobject_cast<FolderNode *>(d->m_currentNode);
+ FolderNode *folder = qobject_cast<FolderNode *>(node);
if (path.contains("#") && folder) {
// Virtual Folder case
// We figure out a commonPath from the subfolders
@@ -2074,10 +2071,32 @@ void ProjectExplorerPlugin::addNewFile()
QFileInfo fi(path);
location = (fi.isDir() ? fi.absoluteFilePath() : fi.absolutePath());
}
+ return location;
+}
+
+void ProjectExplorerPlugin::addNewFile()
+{
+ QTC_ASSERT(d->m_currentNode, return)
+ QString location = directoryFor(d->m_currentNode);
+
Core::ICore::instance()->showNewItemDialog(tr("New File", "Title of dialog"),
- Core::IWizard::wizardsOfKind(Core::IWizard::FileWizard)
- + Core::IWizard::wizardsOfKind(Core::IWizard::ClassWizard),
+ Core::IWizard::wizardsOfKind(Core::IWizard::FileWizard)
+ + Core::IWizard::wizardsOfKind(Core::IWizard::ClassWizard),
+ location);
+}
+
+void ProjectExplorerPlugin::addNewSubproject()
+{
+ QTC_ASSERT(d->m_currentNode, return)
+ QString location = directoryFor(d->m_currentNode);
+
+ if (d->m_currentNode->nodeType() == ProjectNodeType
+ && d->m_currentNode->projectNode()->supportedActions(
+ d->m_currentNode->projectNode()).contains(ProjectNode::AddSubProject)) {
+ Core::ICore::instance()->showNewItemDialog(tr("New Subproject", "Title of dialog"),
+ Core::IWizard::wizardsOfKind(Core::IWizard::ProjectWizard),
location);
+ }
}
void ProjectExplorerPlugin::addExistingFiles()
@@ -2086,8 +2105,7 @@ void ProjectExplorerPlugin::addExistingFiles()
ProjectNode *projectNode = qobject_cast<ProjectNode*>(d->m_currentNode->projectNode());
Core::ICore *core = Core::ICore::instance();
- QFileInfo fi(d->m_currentNode->path());
- const QString dir = (fi.isDir() ? fi.absoluteFilePath() : fi.absolutePath());
+ const QString dir = directoryFor(d->m_currentNode);
QStringList fileNames = QFileDialog::getOpenFileNames(core->mainWindow(), tr("Add Existing Files"), dir);
if (fileNames.isEmpty())
return;
@@ -2159,13 +2177,13 @@ void ProjectExplorerPlugin::showInGraphicalShell()
{
QTC_ASSERT(d->m_currentNode, return)
FolderNavigationWidget::showInGraphicalShell(Core::ICore::instance()->mainWindow(),
- d->m_currentNode->path());
+ directoryFor(d->m_currentNode));
}
void ProjectExplorerPlugin::openTerminalHere()
{
QTC_ASSERT(d->m_currentNode, return)
- FolderNavigationWidget::openTerminal(d->m_currentNode->path());
+ FolderNavigationWidget::openTerminal(directoryFor(d->m_currentNode));
}
void ProjectExplorerPlugin::removeFile()
@@ -2259,7 +2277,7 @@ void ProjectExplorerPlugin::renameFile(Node *node, const QString &to)
FileNode *fileNode = qobject_cast<FileNode *>(node);
if (!fileNode)
return;
- QString orgFilePath = node->path();
+ QString orgFilePath = QFileInfo(node->path()).absoluteFilePath();
QString dir = QFileInfo(orgFilePath).absolutePath();
QString newFilePath = dir + "/" + to;
Core::ICore *core = Core::ICore::instance();
diff --git a/src/plugins/projectexplorer/projectexplorer.h b/src/plugins/projectexplorer/projectexplorer.h
index d45ed0119b..1d061662e7 100644
--- a/src/plugins/projectexplorer/projectexplorer.h
+++ b/src/plugins/projectexplorer/projectexplorer.h
@@ -116,6 +116,9 @@ public:
static QStringList projectFilePatterns();
bool coreAboutToClose();
+ bool canRun(Project *pro, const QString &runMode);
+ void runProject(Project *pro, QString mode);
+
signals:
void aboutToShowContextMenu(ProjectExplorer::Project *project,
ProjectExplorer::Node *node);
@@ -130,6 +133,8 @@ signals:
void settingsChanged();
+ void updateRunActions();
+
public slots:
void openOpenProjectDialog();
@@ -153,7 +158,6 @@ private slots:
void cleanProjectContextMenu();
void cleanSession();
void cancelBuild();
- void debugProject();
void loadAction();
void unloadProject();
void clearSession();
@@ -173,6 +177,7 @@ private slots:
void addNewFile();
void addExistingFiles();
+ void addNewSubproject();
void removeProject();
void openFile();
void showInGraphicalShell();
@@ -198,13 +203,15 @@ private slots:
void activeRunConfigurationChanged();
void updateDeployActions();
- void updateRunActions();
+ void slotUpdateRunActions();
void loadProject(const QString &project) { openProject(project); }
void currentModeChanged(Core::IMode *mode, Core::IMode *oldMode);
void updateActions();
void loadCustomWizards();
+ void publishProject();
+
#ifdef WITH_TESTS
void testGccOutputParsers_data();
void testGccOutputParsers();
@@ -222,17 +229,15 @@ private slots:
#endif
private:
+ QString directoryFor(Node *node);
void deploy(QList<Project *>);
int queue(QList<Project *>, QStringList stepIds);
- void updateContextMenuActions(Node *node);
+ void updateContextMenuActions();
bool parseArguments(const QStringList &arguments, QString *error);
- void runProjectImpl(Project *pro, QString mode);
void executeRunConfiguration(RunConfiguration *, const QString &mode);
bool hasBuildSettings(Project *pro);
bool hasDeploySettings(Project *pro);
- bool showBuildConfigDialog();
-
void setCurrent(Project *project, QString filePath, Node *node);
QStringList allFilesWithDependencies(Project *pro);
diff --git a/src/plugins/projectexplorer/projectexplorer.pri b/src/plugins/projectexplorer/projectexplorer.pri
index fa0891a5fa..8b464277e4 100644
--- a/src/plugins/projectexplorer/projectexplorer.pri
+++ b/src/plugins/projectexplorer/projectexplorer.pri
@@ -1,2 +1,2 @@
include(projectexplorer_dependencies.pri)
-LIBS *= -l$$qtLibraryTarget(ProjectExplorer)
+LIBS *= -l$$qtLibraryName(ProjectExplorer)
diff --git a/src/plugins/projectexplorer/projectexplorer.pro b/src/plugins/projectexplorer/projectexplorer.pro
index 2b395948d5..3336419882 100644
--- a/src/plugins/projectexplorer/projectexplorer.pro
+++ b/src/plugins/projectexplorer/projectexplorer.pro
@@ -85,14 +85,20 @@ HEADERS += projectexplorer.h \
targetsettingswidget.h \
doubletabwidget.h \
buildenvironmentwidget.h \
- buildconfigdialog.h \
ldparser.h \
linuxiccparser.h \
outputformatter.h \
runconfigurationmodel.h \
buildconfigurationmodel.h \
+ processparameters.h \
abstractprocessstep.h \
- taskhub.h
+ taskhub.h \
+ localapplicationruncontrol.h \
+ customexecutableconfigurationwidget.h \
+ sessionnodeimpl.h \
+ publishing/publishingwizardselectiondialog.h \
+ publishing/ipublishingwizardfactory.h
+
SOURCES += projectexplorer.cpp \
projectwindow.cpp \
buildmanager.cpp \
@@ -163,13 +169,18 @@ SOURCES += projectexplorer.cpp \
targetsettingswidget.cpp \
doubletabwidget.cpp \
buildenvironmentwidget.cpp \
- buildconfigdialog.cpp \
ldparser.cpp \
linuxiccparser.cpp \
outputformatter.cpp \
runconfigurationmodel.cpp \
buildconfigurationmodel.cpp \
- taskhub.cpp
+ taskhub.cpp \
+ processparameters.cpp \
+ localapplicationruncontrol.cpp \
+ customexecutableconfigurationwidget.cpp \
+ sessionnodeimpl.cpp \
+ publishing/publishingwizardselectiondialog.cpp
+
FORMS += processstep.ui \
editorsettingspropertiespage.ui \
runsettingspropertiespage.ui \
@@ -179,7 +190,8 @@ FORMS += processstep.ui \
projectexplorersettingspage.ui \
projectwelcomepagewidget.ui \
targetsettingswidget.ui \
- doubletabwidget.ui
+ doubletabwidget.ui \
+ publishing/publishingwizardselectiondialog.ui
equals(TEST, 1) {
SOURCES += \
@@ -198,4 +210,3 @@ win32 {
}
RESOURCES += projectexplorer.qrc
DEFINES += PROJECTEXPLORER_LIBRARY
-OTHER_FILES += ProjectExplorer.pluginspec
diff --git a/src/plugins/projectexplorer/projectexplorerconstants.h b/src/plugins/projectexplorer/projectexplorerconstants.h
index c8033e35f8..18cc6522d9 100644
--- a/src/plugins/projectexplorer/projectexplorerconstants.h
+++ b/src/plugins/projectexplorer/projectexplorerconstants.h
@@ -61,6 +61,7 @@ const char * const DEPLOYPROJECTONLY = "ProjectExplorer.DeployProjectOnly";
const char * const DEPLOY = "ProjectExplorer.Deploy";
const char * const DEPLOYCM = "ProjectExplorer.DeployCM";
const char * const DEPLOYSESSION = "ProjectExplorer.DeploySession";
+const char * const PUBLISH = "ProjectExplorer.Publish";
const char * const CLEANPROJECTONLY = "ProjectExplorer.CleanProjectOnly";
const char * const CLEAN = "ProjectExplorer.Clean";
const char * const CLEANCM = "ProjectExplorer.CleanCM";
@@ -72,12 +73,12 @@ const char * const RUNCONFIGURATIONMENU = "ProjectExplorer.RunConfigurationMenu"
const char * const RUN = "ProjectExplorer.Run";
const char * const RUNCONTEXTMENU = "ProjectExplorer.RunContextMenu";
const char * const STOP = "ProjectExplorer.Stop";
-const char * const DEBUG = "ProjectExplorer.Debug";
const char * const DEPENDENCIES = "ProjectExplorer.Dependencies";
const char * const FINDINALLPROJECTS = "ProjectExplorer.FindInAllProjects";
const char * const SHOWPROPERTIES = "ProjectExplorer.ShowProperties";
const char * const ADDNEWFILE = "ProjectExplorer.AddNewFile";
const char * const ADDEXISTINGFILES = "ProjectExplorer.AddExistingFiles";
+const char * const ADDNEWSUBPROJECT = "ProjectExplorer.AddNewSubproject";
const char * const REMOVEPROJECT = "ProjectExplorer.RemoveProject";
const char * const OPENFILE = "ProjectExplorer.OpenFile";
const char * const SHOWINGRAPHICALSHELL = "ProjectExplorer.ShowInGraphicalShell";
@@ -93,21 +94,21 @@ const char * const SHOW_TASK_OUTPUT = "ProjectExplorer.ShowTaskOutput";
// Run modes
const char * const RUNMODE = "ProjectExplorer.RunMode";
-const char * const DEBUGMODE = "ProjectExplorer.DebugMode";
const char * const SELECTTARGET = "ProjectExplorer.SelectTarget";
// action priorities
const int P_ACTION_RUN = 100;
-const int P_ACTION_DEBUG = 90;
const int P_ACTION_BUILDSESSION = 80;
// context
const char * const C_PROJECTEXPLORER = "Project Explorer";
+const char * const C_PROJECT_TREE = "ProjectExplorer.ProjectTreeContext";
// languages
const char * const LANG_CXX = "CXX";
+const char * const LANG_QMLJS = "QMLJS";
// menus
const char * const M_RECENTPROJECTS = "ProjectExplorer.Menu.Recent";
@@ -218,24 +219,12 @@ const char * const BUILDSTEPS_CLEAN = "ProjectExplorer.BuildSteps.Clean";
const char * const BUILDSTEPS_BUILD = "ProjectExplorer.BuildSteps.Build";
const char * const BUILDSTEPS_DEPLOY = "ProjectExplorer.BuildSteps.Deploy";
-// .user file accessor keys:
-const char * const USERFILE_WAS_UPDATED_KEY = "ProjectExplorer.Project.Updater.DidUpdate";
-const char * const USERFILE_PREVIOUS_VERSION_KEY = "ProjectExplorer.Project.Updater.PreviousVersion";
-const char * const USERFILE_VERSION_KEY = "ProjectExplorer.Project.Updater.FileVersion";
-const char * const USERFILE_BACKUP_FILENAME_KEY = "ProjectExplorer.Project.Updater.PreviousVersion";
-
// Deploy Configuration id:
const char * const DEFAULT_DEPLOYCONFIGURATION_ID = "ProjectExplorer.DefaultDeployConfiguration";
// Run Configuration defaults:
const int QML_DEFAULT_DEBUG_SERVER_PORT = 3768;
-#ifdef Q_OS_MAC
-const char * const DEBUG_KEY = "Ctrl+Y";
-#else
-const char * const DEBUG_KEY = "F5";
-#endif
-
} // namespace Constants
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/projectexplorersettingspage.cpp b/src/plugins/projectexplorer/projectexplorersettingspage.cpp
index 39cf8159ef..564dcaa34b 100644
--- a/src/plugins/projectexplorer/projectexplorersettingspage.cpp
+++ b/src/plugins/projectexplorer/projectexplorersettingspage.cpp
@@ -120,7 +120,23 @@ void ProjectExplorerSettingsWidget::slotDirectoryButtonGroupChanged()
QString ProjectExplorerSettingsWidget::searchKeywords() const
{
- return QLatin1String("jom") + QLatin1Char(' ') + m_ui.directoryGroupBox->title();
+ if (m_searchKeywords.isEmpty()) {
+ QLatin1Char sep(' ');
+ m_searchKeywords = m_ui.directoryGroupBox->title()
+ + sep + m_ui.currentDirectoryRadioButton->text()
+ + sep + m_ui.directoryRadioButton->text()
+ + sep + m_ui.buildAndRunGroupBox->title()
+ + sep + m_ui.saveAllFilesCheckBox->text()
+ + sep + m_ui.buildProjectBeforeDeployCheckBox->text()
+ + sep + m_ui.deployProjectBeforeRunCheckBox->text()
+ + sep + m_ui.showCompileOutputCheckBox->text()
+ + sep + m_ui.cleanOldAppOutputCheckBox->text()
+ + sep + m_ui.wrapAppOutputCheckBox->text()
+ + sep + m_ui.jomLabel->text()
+ ;
+ m_searchKeywords.remove(QLatin1Char('&'));
+ }
+ return m_searchKeywords;
}
// ------------------ ProjectExplorerSettingsPage
diff --git a/src/plugins/projectexplorer/projectexplorersettingspage.h b/src/plugins/projectexplorer/projectexplorersettingspage.h
index df73dbeb79..8fd4f99d31 100644
--- a/src/plugins/projectexplorer/projectexplorersettingspage.h
+++ b/src/plugins/projectexplorer/projectexplorersettingspage.h
@@ -67,6 +67,7 @@ private:
void setJomVisible(bool);
Ui::ProjectExplorerSettingsPageUi m_ui;
+ mutable QString m_searchKeywords;
};
class ProjectExplorerSettingsPage : public Core::IOptionsPage
diff --git a/src/plugins/projectexplorer/projectmodels.cpp b/src/plugins/projectexplorer/projectmodels.cpp
index a72d630311..c01cd7920b 100644
--- a/src/plugins/projectexplorer/projectmodels.cpp
+++ b/src/plugins/projectexplorer/projectmodels.cpp
@@ -44,10 +44,8 @@
#include <QtCore/QDebug>
#include <QtCore/QFileInfo>
-#include <QtGui/QApplication>
+#include <QtGui/QFont>
#include <QtGui/QIcon>
-#include <QtGui/QMessageBox>
-#include <QtGui/QStyle>
using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;
@@ -165,6 +163,12 @@ FlatModel::FlatModel(SessionNode *rootNode, QObject *parent)
NodesWatcher *watcher = new NodesWatcher(this);
m_rootNode->registerWatcher(watcher);
+ connect(watcher, SIGNAL(aboutToChangeHasBuildTargets(ProjectExplorer::ProjectNode*)),
+ this, SLOT(aboutToHasBuildTargetsChanged(ProjectExplorer::ProjectNode*)));
+
+ connect(watcher, SIGNAL(hasBuildTargetsChanged(ProjectExplorer::ProjectNode*)),
+ this, SLOT(hasBuildTargetsChanged(ProjectExplorer::ProjectNode*)));
+
connect(watcher, SIGNAL(foldersAboutToBeAdded(FolderNode *, const QList<FolderNode*> &)),
this, SLOT(foldersAboutToBeAdded(FolderNode *, const QList<FolderNode*> &)));
connect(watcher, SIGNAL(foldersAdded()),
@@ -528,10 +532,19 @@ bool FlatModel::filter(Node *node) const
if (m_filterGeneratedFiles)
isHidden = fileNode->isGenerated();
}
-
return isHidden;
}
+bool isSorted(const QList<Node *> &nodes)
+{
+ int size = nodes.size();
+ for (int i = 0; i < size -1; ++i) {
+ if (!sortNodes(nodes.at(i), nodes.at(i+1)))
+ return false;
+ }
+ return true;
+}
+
/// slots and all the fun
void FlatModel::added(FolderNode* parentNode, const QList<Node*> &newNodeList)
{
@@ -546,6 +559,21 @@ void FlatModel::added(FolderNode* parentNode, const QList<Node*> &newNodeList)
QList<Node *>::const_iterator oldIter = oldNodeList.constBegin();
QList<Node *>::const_iterator newIter = newNodeList.constBegin();
+ Q_ASSERT(isSorted(oldNodeList));
+ Q_ASSERT(isSorted(newNodeList));
+
+ QSet<Node *> emptyDifference;
+ emptyDifference = oldNodeList.toSet();
+ emptyDifference.subtract(newNodeList.toSet());
+ if (!emptyDifference.isEmpty()) {
+ // This should not happen...
+ qDebug() << "FlatModel::added, old Node list should be subset of newNode list, found files in old list which were not part of new list";
+ foreach (Node *n, emptyDifference) {
+ qDebug()<<n->path();
+ }
+ Q_ASSERT(false);
+ }
+
// optimization, check for old list is empty
if (oldIter == oldNodeList.constEnd()) {
// New Node List is empty, nothing added which intrest us
@@ -611,11 +639,27 @@ void FlatModel::removed(FolderNode* parentNode, const QList<Node*> &newNodeList)
QHash<FolderNode*, QList<Node*> >::const_iterator it = m_childNodes.constFind(parentNode);
if (it == m_childNodes.constEnd())
return;
+
QList<Node *> oldNodeList = it.value();
// Compare lists and emit signals, and modify m_childNodes on the fly
QList<Node *>::const_iterator oldIter = oldNodeList.constBegin();
QList<Node *>::const_iterator newIter = newNodeList.constBegin();
+ Q_ASSERT(isSorted(oldNodeList));
+ Q_ASSERT(isSorted(newNodeList));
+
+ QSet<Node *> emptyDifference;
+ emptyDifference = newNodeList.toSet();
+ emptyDifference.subtract(oldNodeList.toSet());
+ if (!emptyDifference.isEmpty()) {
+ // This should not happen...
+ qDebug() << "FlatModel::removed, new Node list should be subset of oldNode list, found files in new list which were not part of old list";
+ foreach (Node *n, emptyDifference) {
+ qDebug()<<n->path();
+ }
+ Q_ASSERT(false);
+ }
+
// optimization, check for new list is empty
if (newIter == newNodeList.constEnd()) {
// New Node List is empty, everything removed
@@ -673,6 +717,31 @@ void FlatModel::removed(FolderNode* parentNode, const QList<Node*> &newNodeList)
}
}
+void FlatModel::aboutToHasBuildTargetsChanged(ProjectExplorer::ProjectNode* node)
+{
+ if (!m_filterProjects)
+ return;
+ FolderNode *folder = visibleFolderNode(node->parentFolderNode());
+ QList<Node *> newNodeList = childNodes(folder, QSet<Node *>() << node);
+ removed(folder, newNodeList);
+
+ QList<Node *> staleFolders;
+ recursiveAddFolderNodesImpl(node, &staleFolders);
+ foreach (Node *n, staleFolders)
+ if (FolderNode *fn = qobject_cast<FolderNode *>(n))
+ m_childNodes.remove(fn);
+}
+
+void FlatModel::hasBuildTargetsChanged(ProjectExplorer::ProjectNode *node)
+{
+ if (!m_filterProjects)
+ return;
+ // we are only interested if we filter
+ FolderNode *folder = visibleFolderNode(node->parentFolderNode());
+ QList<Node *> newNodeList = childNodes(folder);
+ added(folder, newNodeList);
+}
+
void FlatModel::foldersAboutToBeAdded(FolderNode *parentFolder, const QList<FolderNode*> &newFolders)
{
Q_UNUSED(newFolders)
diff --git a/src/plugins/projectexplorer/projectmodels.h b/src/plugins/projectexplorer/projectmodels.h
index 10d702a0f1..bb543533ec 100644
--- a/src/plugins/projectexplorer/projectmodels.h
+++ b/src/plugins/projectexplorer/projectmodels.h
@@ -82,6 +82,8 @@ public slots:
void setGeneratedFilesFilterEnabled(bool filter);
private slots:
+ void aboutToHasBuildTargetsChanged(ProjectExplorer::ProjectNode *node);
+ void hasBuildTargetsChanged(ProjectExplorer::ProjectNode *node);
void foldersAboutToBeAdded(FolderNode *parentFolder, const QList<FolderNode*> &newFolders);
void foldersAdded();
diff --git a/src/plugins/projectexplorer/projectnodes.cpp b/src/plugins/projectexplorer/projectnodes.cpp
index ab229af2ee..8c91989ba9 100644
--- a/src/plugins/projectexplorer/projectnodes.cpp
+++ b/src/plugins/projectexplorer/projectnodes.cpp
@@ -245,6 +245,18 @@ QList<ProjectNode*> ProjectNode::subProjectNodes() const
return m_subProjectNodes;
}
+void ProjectNode::aboutToChangeHasBuildTargets()
+{
+ foreach (NodesWatcher *watcher, watchers())
+ emit watcher->aboutToChangeHasBuildTargets(this);
+}
+
+void ProjectNode::hasBuildTargetsChanged()
+{
+ foreach (NodesWatcher *watcher, watchers())
+ emit watcher->hasBuildTargetsChanged(this);
+}
+
/*!
\function bool ProjectNode::addSubProjects(const QStringList &)
*/
diff --git a/src/plugins/projectexplorer/projectnodes.h b/src/plugins/projectexplorer/projectnodes.h
index 36e674808d..9bfb98c770 100644
--- a/src/plugins/projectexplorer/projectnodes.h
+++ b/src/plugins/projectexplorer/projectnodes.h
@@ -182,6 +182,8 @@ public:
// determines if the project will be shown in the flat view
// TODO find a better name
+ void aboutToChangeHasBuildTargets();
+ void hasBuildTargetsChanged();
virtual bool hasBuildTargets() const = 0;
virtual QList<ProjectAction> supportedActions(Node *node) const = 0;
@@ -274,6 +276,10 @@ public:
explicit NodesWatcher(QObject *parent = 0);
signals:
+ // projects
+ void aboutToChangeHasBuildTargets(ProjectExplorer::ProjectNode*);
+ void hasBuildTargetsChanged(ProjectExplorer::ProjectNode *node);
+
// folders & projects
void foldersAboutToBeAdded(FolderNode *parentFolder,
const QList<FolderNode*> &newFolders);
diff --git a/src/plugins/projectexplorer/projecttreewidget.cpp b/src/plugins/projectexplorer/projecttreewidget.cpp
index edb67f1a18..8f7a60fafa 100644
--- a/src/plugins/projectexplorer/projecttreewidget.cpp
+++ b/src/plugins/projectexplorer/projecttreewidget.cpp
@@ -34,6 +34,7 @@
#include "projecttreewidget.h"
#include "projectexplorer.h"
+#include "projectnodes.h"
#include "project.h"
#include "session.h"
#include "projectexplorerconstants.h"
@@ -42,6 +43,8 @@
#include <coreplugin/coreconstants.h>
#include <coreplugin/icore.h>
#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/icontext.h>
+
#include <utils/qtcassert.h>
#include <utils/navigationtreeview.h>
@@ -49,6 +52,7 @@
#include <QtCore/QSettings>
#include <QtGui/QHeaderView>
+#include <QtGui/QTreeView>
#include <QtGui/QVBoxLayout>
#include <QtGui/QToolButton>
#include <QtGui/QFocusEvent>
@@ -71,7 +75,18 @@ public:
setEditTriggers(QAbstractItemView::EditKeyPressed);
setContextMenuPolicy(Qt::CustomContextMenu);
// setExpandsOnDoubleClick(false);
+ Core::Context context(Constants::C_PROJECT_TREE);
+ m_context = new Core::BaseContext(this, context);
+ Core::ICore::instance()->addContextObject(m_context);
+ }
+ ~ProjectTreeView()
+ {
+ Core::ICore::instance()->removeContextObject(m_context);
+ delete m_context;
}
+
+private:
+ Core::BaseContext *m_context;
};
/*!
diff --git a/src/plugins/projectexplorer/projecttreewidget.h b/src/plugins/projectexplorer/projecttreewidget.h
index eb4bdd6ccf..fcd5054a74 100644
--- a/src/plugins/projectexplorer/projecttreewidget.h
+++ b/src/plugins/projectexplorer/projecttreewidget.h
@@ -37,7 +37,9 @@
#include <coreplugin/inavigationwidgetfactory.h>
#include <QtGui/QWidget>
-#include <QtGui/QTreeView>
+#include <QtCore/QModelIndex>
+
+QT_FORWARD_DECLARE_CLASS(QTreeView)
namespace ProjectExplorer {
diff --git a/src/plugins/projectexplorer/projectwelcomepagewidget.cpp b/src/plugins/projectexplorer/projectwelcomepagewidget.cpp
index 8242812ab1..c8f94c2776 100644
--- a/src/plugins/projectexplorer/projectwelcomepagewidget.cpp
+++ b/src/plugins/projectexplorer/projectwelcomepagewidget.cpp
@@ -40,7 +40,6 @@
#include <coreplugin/modemanager.h>
#include <coreplugin/icore.h>
#include <coreplugin/dialogs/iwizard.h>
-#include <coreplugin/mainwindow.h>
#include <coreplugin/filemanager.h>
#include <utils/stringutils.h>
@@ -49,7 +48,6 @@
#include <QtCore/QDir>
#include <QtCore/QPair>
#include <QtGui/QLabel>
-#include <QtGui/QTreeWidgetItem>
#include <QtCore/QDebug>
diff --git a/src/plugins/projectexplorer/projectwindow.cpp b/src/plugins/projectexplorer/projectwindow.cpp
index 3cd19fe54e..81abe2717b 100644
--- a/src/plugins/projectexplorer/projectwindow.cpp
+++ b/src/plugins/projectexplorer/projectwindow.cpp
@@ -36,36 +36,24 @@
#include "doubletabwidget.h"
#include "project.h"
-#include "environment.h"
#include "projectexplorer.h"
#include "projectexplorerconstants.h"
-#include "iprojectproperties.h"
#include "session.h"
-#include "target.h"
#include "projecttreewidget.h"
-#include "runconfiguration.h"
-#include "buildsettingspropertiespage.h"
-#include "runsettingspropertiespage.h"
+#include "iprojectproperties.h"
#include "targetsettingspanel.h"
-#include <coreplugin/minisplitter.h>
-#include <coreplugin/fileiconprovider.h>
#include <coreplugin/icore.h>
#include <coreplugin/ifile.h>
#include <extensionsystem/pluginmanager.h>
#include <utils/qtcassert.h>
-#include <utils/styledbar.h>
#include <utils/stylehelper.h>
#include <QtGui/QApplication>
-#include <QtGui/QBoxLayout>
-#include <QtGui/QComboBox>
-#include <QtGui/QScrollArea>
+#include <QtGui/QGridLayout>
#include <QtGui/QLabel>
#include <QtGui/QPainter>
#include <QtGui/QStackedWidget>
-#include <QtGui/QPaintEvent>
-#include <QtGui/QMenu>
using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;
@@ -233,7 +221,8 @@ void PanelsWidget::addPanelWidget(IPropertiesPanel *panel, int row)
ProjectWindow::ProjectWindow(QWidget *parent)
: QWidget(parent),
- m_currentWidget(0)
+ m_currentWidget(0),
+ m_previousTargetSubIndex(-1)
{
ProjectExplorer::SessionManager *session = ProjectExplorerPlugin::instance()->session();
@@ -379,11 +368,19 @@ void ProjectWindow::showProperties(int index, int subIndex)
// Set up custom panels again:
int pos = 0;
IPanelFactory *fac = 0;
+ // remember previous sub index state of target settings page
+ if (TargetSettingsPanelWidget *previousPanelWidget
+ = qobject_cast<TargetSettingsPanelWidget*>(m_currentWidget)) {
+ m_previousTargetSubIndex = previousPanelWidget->currentSubIndex();
+ }
if (project->supportedTargetIds().count() > 1) {
if (subIndex == 0) {
// Targets page
removeCurrentWidget();
- m_currentWidget = new TargetSettingsPanelWidget(project);
+ TargetSettingsPanelWidget *panelWidget = new TargetSettingsPanelWidget(project);
+ if (m_previousTargetSubIndex >= 0)
+ panelWidget->setCurrentSubIndex(m_previousTargetSubIndex);
+ m_currentWidget = panelWidget;
m_centralWidget->addWidget(m_currentWidget);
m_centralWidget->setCurrentWidget(m_currentWidget);
}
diff --git a/src/plugins/projectexplorer/projectwindow.h b/src/plugins/projectexplorer/projectwindow.h
index 42d0864d0c..c1d2ba10cf 100644
--- a/src/plugins/projectexplorer/projectwindow.h
+++ b/src/plugins/projectexplorer/projectwindow.h
@@ -98,6 +98,7 @@ private:
QStackedWidget *m_centralWidget;
QWidget *m_currentWidget;
QList<ProjectExplorer::Project *> m_tabIndexToProject;
+ int m_previousTargetSubIndex;
};
} // namespace Internal
diff --git a/src/plugins/projectexplorer/publishing/ipublishingwizardfactory.h b/src/plugins/projectexplorer/publishing/ipublishingwizardfactory.h
new file mode 100644
index 0000000000..18acd0d55b
--- /dev/null
+++ b/src/plugins/projectexplorer/publishing/ipublishingwizardfactory.h
@@ -0,0 +1,96 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 IPUBLISHING_WIZARD_FACTORY_H
+#define IPUBLISHING_WIZARD_FACTORY_H
+
+#include <projectexplorer/projectexplorer_export.h>
+
+#include <extensionsystem/pluginmanager.h>
+
+#include <QtCore/QList>
+#include <QtGui/QWizard>
+
+namespace ProjectExplorer {
+class Project;
+
+/*!
+ \class ProjectExplorer::IPublishingWizardFactory
+
+ \brief Provides an interface for creating wizards to publish a project.
+
+ A class implementing this interface is used to create an associated wizard
+ that allows users to publish their project to a remote facility, e.g. an
+ app store.
+ Such a wizard would typically transform the project's content into
+ a form expected by that facility ("packaging") and also upload it, if possible.
+
+ The factory objects have to be added to the global object pool via
+ \c ExtensionSystem::PluginManager::addObject().
+ \sa ExtensionSystem::PluginManager::addObject()
+*/
+
+class PROJECTEXPLORER_EXPORT IPublishingWizardFactory : public QObject
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(IPublishingWizardFactory)
+public:
+ /*!
+ A short, one-line description of the type of wizard that this
+ factory can create.
+ */
+ virtual QString displayName() const=0;
+
+ /*!
+ A longer description explaining the exact purpose of the wizard
+ created by this factory.
+ */
+ virtual QString description() const=0;
+
+ /*!
+ Returns true iff the type of wizard that this factory can create
+ is available for the given project.
+ */
+ virtual bool canCreateWizard(const Project *project) const=0;
+
+ /*!
+ Creates a wizard that can publish the given project.
+ Behavior is undefined if canCreateWizard() returns false for
+ that project.
+ \return The newly created publishing wizard
+ \sa canCreateWizard()
+ */
+ virtual QWizard *createWizard(const Project *project) const=0;
+
+protected:
+ IPublishingWizardFactory(QObject *parent = 0) : QObject(parent) {}
+};
+
+} // namespace ProjectExplorer
+
+#endif // IPUBLISHING_WIZARD_FACTORY_H
diff --git a/src/plugins/projectexplorer/publishing/publishingwizardselectiondialog.cpp b/src/plugins/projectexplorer/publishing/publishingwizardselectiondialog.cpp
new file mode 100644
index 0000000000..bf8df3da43
--- /dev/null
+++ b/src/plugins/projectexplorer/publishing/publishingwizardselectiondialog.cpp
@@ -0,0 +1,89 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "publishingwizardselectiondialog.h"
+#include "ui_publishingwizardselectiondialog.h"
+
+#include "ipublishingwizardfactory.h"
+
+#include <extensionsystem/pluginmanager.h>
+#include <projectexplorer/project.h>
+#include <utils/qtcassert.h>
+
+#include <QtGui/QPushButton>
+
+namespace ProjectExplorer {
+namespace Internal {
+
+PublishingWizardSelectionDialog::PublishingWizardSelectionDialog(const Project *project,
+ QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::PublishingWizardSelectionDialog),
+ m_project(project)
+{
+ ui->setupUi(this);
+ ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Start Wizard"));
+ const QList<IPublishingWizardFactory *> &factories
+ = ExtensionSystem::PluginManager::instance()->getObjects<IPublishingWizardFactory>();
+ foreach (const IPublishingWizardFactory * const factory, factories) {
+ if (factory->canCreateWizard(project)) {
+ m_factories << factory;
+ ui->serviceComboBox->addItem(factory->displayName());
+ }
+ }
+ if (!m_factories.isEmpty()) {
+ connect(ui->serviceComboBox, SIGNAL(currentIndexChanged(int)),
+ SLOT(handleWizardIndexChanged(int)));
+ ui->serviceComboBox->setCurrentIndex(0);
+ handleWizardIndexChanged(ui->serviceComboBox->currentIndex());
+ } else {
+ ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
+ ui->descriptionTextArea->appendHtml(QLatin1String("<font color=\"red\">")
+ + tr("Publishing is currently not possible for project '%1'.")
+ .arg(project->displayName())
+ + QLatin1String("</font>"));
+ }
+}
+
+PublishingWizardSelectionDialog::~PublishingWizardSelectionDialog()
+{
+ delete ui;
+}
+
+QWizard *PublishingWizardSelectionDialog::createSelectedWizard() const
+{
+ return m_factories.at(ui->serviceComboBox->currentIndex())->createWizard(m_project);
+}
+
+void PublishingWizardSelectionDialog::handleWizardIndexChanged(int index)
+{
+ ui->descriptionTextArea->setPlainText(m_factories.at(index)->description());
+}
+
+} // namespace Internal
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/publishing/publishingwizardselectiondialog.h b/src/plugins/projectexplorer/publishing/publishingwizardselectiondialog.h
new file mode 100644
index 0000000000..aaff3282fc
--- /dev/null
+++ b/src/plugins/projectexplorer/publishing/publishingwizardselectiondialog.h
@@ -0,0 +1,68 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 PUBLISHINGWIZARDSELECTIONDIALOG_H
+#define PUBLISHINGWIZARDSELECTIONDIALOG_H
+
+#include <QtCore/QList>
+#include <QtGui/QDialog>
+
+QT_FORWARD_DECLARE_CLASS(QWizard)
+
+namespace ProjectExplorer {
+class IPublishingWizardFactory;
+class Project;
+namespace Internal {
+namespace Ui {
+class PublishingWizardSelectionDialog;
+}
+
+class PublishingWizardSelectionDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit PublishingWizardSelectionDialog(const Project *project,
+ QWidget *parent = 0);
+ ~PublishingWizardSelectionDialog();
+ QWizard *createSelectedWizard() const;
+
+private slots:
+ void handleWizardIndexChanged(int index);
+
+private:
+ Ui::PublishingWizardSelectionDialog *ui;
+
+ const Project * const m_project;
+ QList<const IPublishingWizardFactory *> m_factories;
+};
+
+} // namespace Internal
+} // namespace ProjectExplorer
+
+#endif // PUBLISHINGWIZARDSELECTIONDIALOG_H
diff --git a/src/plugins/projectexplorer/publishing/publishingwizardselectiondialog.ui b/src/plugins/projectexplorer/publishing/publishingwizardselectiondialog.ui
new file mode 100644
index 0000000000..84078fb7c2
--- /dev/null
+++ b/src/plugins/projectexplorer/publishing/publishingwizardselectiondialog.ui
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ProjectExplorer::Internal::PublishingWizardSelectionDialog</class>
+ <widget class="QDialog" name="ProjectExplorer::Internal::PublishingWizardSelectionDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>409</width>
+ <height>330</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Publishing Wizard Selection</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Available Wizards:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="serviceComboBox"/>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QPlainTextEdit" name="descriptionTextArea">
+ <property name="readOnly">
+ <bool>true</bool>
+ </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>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>ProjectExplorer::Internal::PublishingWizardSelectionDialog</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>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>ProjectExplorer::Internal::PublishingWizardSelectionDialog</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>
+ </connections>
+</ui>
diff --git a/src/plugins/projectexplorer/runconfiguration.h b/src/plugins/projectexplorer/runconfiguration.h
index 2e9d969608..0f3c492fbe 100644
--- a/src/plugins/projectexplorer/runconfiguration.h
+++ b/src/plugins/projectexplorer/runconfiguration.h
@@ -61,7 +61,7 @@ class OutputFormatter;
* That is the lifetime of the RunConfiguration might exceed the life of the target.
* The user might still have a RunControl running (or output tab of that RunControl open)
* and yet unloaded the target.
- * Also a RunConfiguration might be already removed from the list of RunConfigurations
+ * Also a RunConfiguration might be already removed from the list of RunConfigurations
* for a target, but stil be runnable via the output tab.
*/
class PROJECTEXPLORER_EXPORT RunConfiguration : public ProjectConfiguration
@@ -184,7 +184,7 @@ class PROJECTEXPLORER_EXPORT RunControl : public QObject
public:
enum StopResult {
StoppedSynchronously, // Stopped.
- AsynchronousStop, // Stop sequence has been started
+ AsynchronousStop // Stop sequence has been started
};
explicit RunControl(RunConfiguration *runConfiguration, QString mode);
diff --git a/src/plugins/projectexplorer/runsettingspropertiespage.cpp b/src/plugins/projectexplorer/runsettingspropertiespage.cpp
index c40ebdb14a..3a9b2df983 100644
--- a/src/plugins/projectexplorer/runsettingspropertiespage.cpp
+++ b/src/plugins/projectexplorer/runsettingspropertiespage.cpp
@@ -64,7 +64,7 @@ struct FactoryAndId
} // namespace Internal
} // namespace ProjectExplorer
-Q_DECLARE_METATYPE(ProjectExplorer::Internal::FactoryAndId);
+Q_DECLARE_METATYPE(ProjectExplorer::Internal::FactoryAndId)
using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;
diff --git a/src/plugins/projectexplorer/runsettingspropertiespage.h b/src/plugins/projectexplorer/runsettingspropertiespage.h
index 2393e47d7b..ba038070a6 100644
--- a/src/plugins/projectexplorer/runsettingspropertiespage.h
+++ b/src/plugins/projectexplorer/runsettingspropertiespage.h
@@ -37,6 +37,7 @@
#include "iprojectproperties.h"
#include <QtGui/QWidget>
+#include <QtGui/QIcon>
QT_BEGIN_NAMESPACE
class QMenu;
diff --git a/src/plugins/projectexplorer/session.cpp b/src/plugins/projectexplorer/session.cpp
index 180bd5884a..f9e1e758e8 100644
--- a/src/plugins/projectexplorer/session.cpp
+++ b/src/plugins/projectexplorer/session.cpp
@@ -32,6 +32,7 @@
**************************************************************************/
#include "session.h"
+#include "sessionnodeimpl.h"
#include "project.h"
#include "projectexplorer.h"
@@ -115,7 +116,6 @@ private:
using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;
-
void SessionFile::sessionLoadingProgress()
{
future.setProgressValue(future.progressValue() + 1);
@@ -159,18 +159,6 @@ bool SessionFile::load(const QString &fileName)
QStringList fileList =
reader.restoreValue(QLatin1String("ProjectList")).toStringList();
- QString configDir = QFileInfo(m_core->settings()->fileName()).path();
- QMutableStringListIterator it(fileList);
- while (it.hasNext()) {
- const QString &file = it.next();
- if (QFileInfo(file).isRelative()) {
- // We used to write relative paths into the session file
- // relative to the session files, and those were stored in the
- // config dir
- it.setValue(configDir + QLatin1Char('/') + file);
- }
- }
-
int openEditorsCount = reader.restoreValue(QLatin1String("OpenEditors")).toInt();
future.setProgressRange(0, fileList.count() + openEditorsCount + 2);
@@ -321,28 +309,6 @@ void SessionFile::clearFailedProjectFileNames()
m_failedProjects.clear();
}
-Internal::SessionNodeImpl::SessionNodeImpl(SessionManager *manager)
- : ProjectExplorer::SessionNode(manager->currentSession(), manager)
-{
- setFileName("session");
-}
-
-void Internal::SessionNodeImpl::addProjectNode(ProjectNode *projectNode)
-{
- addProjectNodes(QList<ProjectNode*>() << projectNode);
-}
-
-void Internal::SessionNodeImpl::removeProjectNode(ProjectNode *projectNode)
-{
- removeProjectNodes(QList<ProjectNode*>() << projectNode);
-}
-
-void Internal::SessionNodeImpl::setFileName(const QString &fileName)
-{
- setPath(fileName);
- setDisplayName(fileName);
-}
-
/* --------------------------------- */
SessionManager::SessionManager(QObject *parent)
@@ -350,26 +316,8 @@ SessionManager::SessionManager(QObject *parent)
m_core(Core::ICore::instance()),
m_file(new SessionFile),
m_sessionNode(new Internal::SessionNodeImpl(this)),
- m_currentEditor(0),
m_virginSession(true)
{
- // Create qtcreator dir if it doesn't yet exist
- QString configDir = QFileInfo(m_core->settings()->fileName()).path();
-
- QFileInfo fi(configDir + "/qtcreator/");
- if (!fi.exists()) {
- QDir dir;
- dir.mkpath(configDir + "/qtcreator");
-
- // Move sessions to that directory
- foreach (const QString &session, sessions()) {
- QFile file(configDir + QLatin1Char('/') + session + QLatin1String(".qws"));
- if (file.exists())
- if (file.copy(configDir + QLatin1String("/qtcreator/") + session + QLatin1String(".qws")))
- file.remove();
- }
- }
-
connect(m_core->modeManager(), SIGNAL(currentModeChanged(Core::IMode*)),
this, SLOT(saveActiveMode(Core::IMode*)));
@@ -379,8 +327,6 @@ SessionManager::SessionManager(QObject *parent)
this, SLOT(setEditorCodec(Core::IEditor *, QString)));
connect(ProjectExplorerPlugin::instance(), SIGNAL(currentProjectChanged(ProjectExplorer::Project *)),
this, SLOT(updateWindowTitle()));
- connect(em, SIGNAL(currentEditorChanged(Core::IEditor*)),
- this, SLOT(handleCurrentEditorChange(Core::IEditor*)));
connect(em, SIGNAL(editorOpened(Core::IEditor*)),
this, SLOT(markSessionFileDirty()));
connect(em, SIGNAL(editorsClosed(QList<Core::IEditor*>)),
@@ -894,40 +840,19 @@ QString SessionManager::currentSession() const
return m_file->fileName();
}
-void SessionManager::handleCurrentEditorChange(Core::IEditor *editor)
-{
- if (editor != m_currentEditor) {
- if (m_currentEditor)
- disconnect(m_currentEditor, SIGNAL(changed()), this, SLOT(updateWindowTitle()));
- if (editor)
- connect(editor, SIGNAL(changed()), this, SLOT(updateWindowTitle()));
- m_currentEditor = editor;
- }
- updateWindowTitle();
-}
-
void SessionManager::updateWindowTitle()
{
- QString windowTitle = tr("Qt Creator");
if (isDefaultSession(m_sessionName)) {
if (Project *currentProject = ProjectExplorerPlugin::instance()->currentProject())
- windowTitle.prepend(currentProject->displayName() + " - ");
+ m_core->editorManager()->setWindowTitleAddition(currentProject->displayName());
+ else
+ m_core->editorManager()->setWindowTitleAddition("");
} else {
QString sessionName = m_sessionName;
if (sessionName.isEmpty())
sessionName = tr("Untitled");
- windowTitle.prepend(sessionName + " - ");
- }
- if (m_core->editorManager()->currentEditor()) {
- QFileInfo fi(m_core->editorManager()->currentEditor()->file()->fileName());
- QString fileName = fi.fileName();
- if (!fileName.isEmpty())
- windowTitle.prepend(fileName + " - ");
- m_core->mainWindow()->setWindowFilePath(fi.absoluteFilePath());
- } else {
- m_core->mainWindow()->setWindowFilePath(QString());
+ m_core->editorManager()->setWindowTitleAddition(sessionName);
}
- m_core->mainWindow()->setWindowTitle(windowTitle);
}
void SessionManager::updateName(const QString &session)
@@ -1027,7 +952,7 @@ QStringList SessionManager::sessions() const
{
if (m_sessions.isEmpty()) {
// We are not initialized yet, so do that now
- QDir sessionDir(QFileInfo(m_core->settings()->fileName()).path()+ "/qtcreator/");
+ QDir sessionDir(Core::ICore::instance()->userResourcePath());
QList<QFileInfo> sessionFiles = sessionDir.entryInfoList(QStringList() << QLatin1String("*.qws"), QDir::NoFilter, QDir::Time);
Q_FOREACH(const QFileInfo& fileInfo, sessionFiles) {
if (fileInfo.completeBaseName() != "default")
diff --git a/src/plugins/projectexplorer/session.h b/src/plugins/projectexplorer/session.h
index 04df619bed..375c2a1f1a 100644
--- a/src/plugins/projectexplorer/session.h
+++ b/src/plugins/projectexplorer/session.h
@@ -35,16 +35,15 @@
#define SESSION_H
#include "projectexplorer_export.h"
-#include "projectnodes.h"
#include <QtCore/QHash>
-#include <QtCore/QList>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QPointer>
QT_BEGIN_NAMESPACE
class QAbstractItemModel;
+class QTimer;
QT_END_NAMESPACE
namespace Core {
@@ -62,23 +61,8 @@ class SessionNode;
class SessionManager;
namespace Internal {
-
class SessionFile;
-
-// Must be in header as otherwise moc has issues
-// with ProjectExplorer::SessionNode on msvc2005
-class SessionNodeImpl : public ProjectExplorer::SessionNode
-{
- Q_OBJECT
-public:
- SessionNodeImpl(SessionManager *manager);
-
- void addProjectNode(ProjectNode *projectNode);
- void removeProjectNode(ProjectNode *projectNode);
-
- void setFileName(const QString &fileName);
-};
-
+class SessionNodeImpl;
} // namespace Internal
// TODO the interface of this class is not really great
@@ -175,7 +159,6 @@ private slots:
void saveActiveMode(Core::IMode *mode);
void clearProjectFileCache();
void setEditorCodec(Core::IEditor *editor, const QString &fileName);
- void handleCurrentEditorChange(Core::IEditor *editor);
void updateWindowTitle();
void markSessionFileDirty(bool makeDefaultVirginDirty = true);
@@ -196,7 +179,6 @@ private:
Internal::SessionFile *m_file;
Internal::SessionNodeImpl *m_sessionNode;
- QPointer<Core::IEditor> m_currentEditor;
QString m_sessionName;
bool m_virginSession;
diff --git a/src/plugins/projectexplorer/sessionnodeimpl.cpp b/src/plugins/projectexplorer/sessionnodeimpl.cpp
new file mode 100644
index 0000000000..2f2696b076
--- /dev/null
+++ b/src/plugins/projectexplorer/sessionnodeimpl.cpp
@@ -0,0 +1,59 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "sessionnodeimpl.h"
+#include "session.h"
+
+namespace ProjectExplorer {
+namespace Internal {
+
+SessionNodeImpl::SessionNodeImpl(SessionManager *manager)
+ : ProjectExplorer::SessionNode(manager->currentSession(), manager)
+{
+ setFileName(QLatin1String("session"));
+}
+
+void SessionNodeImpl::addProjectNode(ProjectNode *projectNode)
+{
+ addProjectNodes(QList<ProjectNode*>() << projectNode);
+}
+
+void SessionNodeImpl::removeProjectNode(ProjectNode *projectNode)
+{
+ removeProjectNodes(QList<ProjectNode*>() << projectNode);
+}
+
+void SessionNodeImpl::setFileName(const QString &fileName)
+{
+ setPath(fileName);
+ setDisplayName(fileName);
+}
+
+} // namespace Internal
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/sessionnodeimpl.h b/src/plugins/projectexplorer/sessionnodeimpl.h
new file mode 100644
index 0000000000..2ec2631846
--- /dev/null
+++ b/src/plugins/projectexplorer/sessionnodeimpl.h
@@ -0,0 +1,61 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** No Commercial Usage
+**
+** This file 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.
+**
+**************************************************************************/
+
+#ifndef SESSIONNODEIMPL_H
+#define SESSIONNODEIMPL_H
+
+#include "projectnodes.h"
+
+namespace ProjectExplorer {
+class SessionManager;
+
+namespace Internal {
+
+// Must be in a header as otherwise moc has issues
+// with ProjectExplorer::SessionNode on msvc2005
+class SessionNodeImpl : public ProjectExplorer::SessionNode
+{
+ Q_OBJECT
+public:
+ explicit SessionNodeImpl(SessionManager *manager);
+
+ void addProjectNode(ProjectNode *projectNode);
+ void removeProjectNode(ProjectNode *projectNode);
+
+ void setFileName(const QString &fileName);
+};
+
+} // namespace Internal
+} // namespace ProjectExplorer
+
+#endif // SESSIONNODEIMPL_H
diff --git a/src/plugins/projectexplorer/showineditortaskhandler.cpp b/src/plugins/projectexplorer/showineditortaskhandler.cpp
index 01103e4fca..b693b3c9d8 100644
--- a/src/plugins/projectexplorer/showineditortaskhandler.cpp
+++ b/src/plugins/projectexplorer/showineditortaskhandler.cpp
@@ -36,7 +36,6 @@
#include "projectexplorerconstants.h"
#include "task.h"
-#include <coreplugin/editormanager/editormanager.h>
#include <texteditor/basetexteditor.h>
#include <QtGui/QAction>
diff --git a/src/plugins/projectexplorer/showineditortaskhandler.h b/src/plugins/projectexplorer/showineditortaskhandler.h
index bd5ab4ea13..0db9f6550d 100644
--- a/src/plugins/projectexplorer/showineditortaskhandler.h
+++ b/src/plugins/projectexplorer/showineditortaskhandler.h
@@ -34,14 +34,12 @@
#ifndef PROJECTEXPLORER_SHOWINEDITORTASKHANDLER_H
#define PROJECTEXPLORER_SHOWINEDITORTASKHANDLER_H
-#include "projectexplorer_export.h"
-
#include "itaskhandler.h"
namespace ProjectExplorer {
namespace Internal {
-class PROJECTEXPLORER_EXPORT ShowInEditorTaskHandler : public ITaskHandler
+class ShowInEditorTaskHandler : public ITaskHandler
{
Q_OBJECT
diff --git a/src/plugins/projectexplorer/showoutputtaskhandler.h b/src/plugins/projectexplorer/showoutputtaskhandler.h
index 4366d580e7..4053a4eb90 100644
--- a/src/plugins/projectexplorer/showoutputtaskhandler.h
+++ b/src/plugins/projectexplorer/showoutputtaskhandler.h
@@ -34,8 +34,6 @@
#ifndef PROJECTEXPLORER_SHOWOUTPUTTASKHANDLER_H
#define PROJECTEXPLORER_SHOWOUTPUTTASKHANDLER_H
-#include "projectexplorer_export.h"
-
#include "itaskhandler.h"
namespace ProjectExplorer {
@@ -43,7 +41,7 @@ namespace Internal {
class CompileOutputWindow;
-class PROJECTEXPLORER_EXPORT ShowOutputTaskHandler : public ITaskHandler
+class ShowOutputTaskHandler : public ITaskHandler
{
Q_OBJECT
diff --git a/src/plugins/projectexplorer/target.cpp b/src/plugins/projectexplorer/target.cpp
index 6ed786b13a..01e8d9cecf 100644
--- a/src/plugins/projectexplorer/target.cpp
+++ b/src/plugins/projectexplorer/target.cpp
@@ -382,9 +382,6 @@ bool Target::fromMap(const QVariantMap &map)
if (!ProjectConfiguration::fromMap(map))
return false;
- int fileVersion = map.value(Constants::USERFILE_PREVIOUS_VERSION_KEY,
- std::numeric_limits<int>::max()).toInt();
-
bool ok;
int bcCount(map.value(QLatin1String(BC_COUNT_KEY), 0).toInt(&ok));
if (!ok || bcCount < 0)
@@ -399,9 +396,7 @@ bool Target::fromMap(const QVariantMap &map)
const QString key(QString::fromLatin1(BC_KEY_PREFIX) + QString::number(i));
if (!map.contains(key))
return false;
- QVariantMap targetMap = map.value(key).toMap();
- targetMap.insert(Constants::USERFILE_PREVIOUS_VERSION_KEY, fileVersion);
- BuildConfiguration *bc(buildConfigurationFactory()->restore(this, targetMap));
+ BuildConfiguration *bc(buildConfigurationFactory()->restore(this, map.value(key).toMap()));
if (!bc)
continue;
addBuildConfiguration(bc);
diff --git a/src/plugins/projectexplorer/target.h b/src/plugins/projectexplorer/target.h
index 17601f8b9f..941f2126ee 100644
--- a/src/plugins/projectexplorer/target.h
+++ b/src/plugins/projectexplorer/target.h
@@ -51,6 +51,7 @@ class IBuildConfigurationFactory;
class DeployConfigurationFactory;
class IRunConfigurationFactory;
class Project;
+class BuildConfigWidget;
class TargetPrivate;
@@ -61,6 +62,8 @@ class PROJECTEXPLORER_EXPORT Target : public ProjectConfiguration
public:
virtual ~Target();
+ virtual BuildConfigWidget *createConfigWidget() = 0;
+
virtual Project *project() const;
// Build configuration
@@ -156,6 +159,8 @@ public:
explicit ITargetFactory(QObject *parent = 0);
virtual ~ITargetFactory();
+ virtual bool supportsTargetId(const QString &id) const = 0;
+
// used to show the list of possible additons to a target, returns a list of types
virtual QStringList availableCreationIds(Project *parent) const = 0;
// used to translate the types to names to display to the user
diff --git a/src/plugins/projectexplorer/targetsettingspanel.cpp b/src/plugins/projectexplorer/targetsettingspanel.cpp
index 5a5c72174a..ded4b7fa64 100644
--- a/src/plugins/projectexplorer/targetsettingspanel.cpp
+++ b/src/plugins/projectexplorer/targetsettingspanel.cpp
@@ -204,7 +204,17 @@ void TargetSettingsPanelWidget::currentTargetChanged(int targetIndex, int subInd
void TargetSettingsPanelWidget::addTarget(QAction *action)
{
QString id = action->data().toString();
- Target *target(m_project->targetFactory()->create(m_project, id));
+ QList<ITargetFactory *> factories =
+ ExtensionSystem::PluginManager::instance()->getObjects<ITargetFactory>();
+
+ Target *target = 0;
+ foreach (ITargetFactory *fac, factories) {
+ if (fac->canCreate(m_project, id)) {
+ target = fac->create(m_project, id);
+ break;
+ }
+ }
+
if (!target)
return;
m_project->addTarget(target);
@@ -271,8 +281,20 @@ void TargetSettingsPanelWidget::updateTargetAddAndRemoveButtons()
m_addMenu->clear();
+ QList<ITargetFactory *> factories =
+ ExtensionSystem::PluginManager::instance()->getObjects<ITargetFactory>();
+
foreach (const QString &id, m_project->possibleTargetIds()) {
- QString displayName = m_project->targetFactory()->displayNameForId(id);
+ QString displayName;
+ foreach (ITargetFactory *fac, factories) {
+ if (fac->supportsTargetId(id)) {
+ displayName = fac->displayNameForId(id);
+ break;
+ }
+ }
+ if (displayName.isEmpty())
+ continue;
+
QAction *action = new QAction(displayName, m_addMenu);
action->setData(QVariant(id));
bool added = false;
@@ -289,3 +311,13 @@ void TargetSettingsPanelWidget::updateTargetAddAndRemoveButtons()
m_selector->setAddButtonEnabled(!m_addMenu->actions().isEmpty());
m_selector->setRemoveButtonEnabled(m_project->targets().count() > 1);
}
+
+int TargetSettingsPanelWidget::currentSubIndex() const
+{
+ return m_selector->currentSubIndex();
+}
+
+void TargetSettingsPanelWidget::setCurrentSubIndex(int subIndex)
+{
+ m_selector->setCurrentSubIndex(subIndex);
+}
diff --git a/src/plugins/projectexplorer/targetsettingspanel.h b/src/plugins/projectexplorer/targetsettingspanel.h
index 274aa7a588..454130524a 100644
--- a/src/plugins/projectexplorer/targetsettingspanel.h
+++ b/src/plugins/projectexplorer/targetsettingspanel.h
@@ -61,6 +61,9 @@ public:
void setupUi();
+ int currentSubIndex() const;
+ void setCurrentSubIndex(int subIndex);
+
private slots:
void currentTargetChanged(int targetIndex, int subIndex);
void removeTarget();
diff --git a/src/plugins/projectexplorer/taskwindow.cpp b/src/plugins/projectexplorer/taskwindow.cpp
index 8937572d01..770dc08568 100644
--- a/src/plugins/projectexplorer/taskwindow.cpp
+++ b/src/plugins/projectexplorer/taskwindow.cpp
@@ -59,8 +59,7 @@
#include <QtGui/QToolButton>
namespace {
-const int TASK_ICON_SIZE = 16;
-const int TASK_ICON_MARGIN = 2;
+const int ELLIPSIS_GRADIENT_WIDTH = 16;
}
namespace ProjectExplorer {
@@ -75,25 +74,6 @@ public:
void keyPressEvent(QKeyEvent *e);
};
-class TaskDelegate : public QStyledItemDelegate
-{
- Q_OBJECT
-public:
- TaskDelegate(QObject * parent = 0);
- ~TaskDelegate();
- void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
- QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
-
- // TaskView uses this method if the size of the taskview changes
- void emitSizeHintChanged(const QModelIndex &index);
-
-public slots:
- void currentChanged(const QModelIndex &current, const QModelIndex &previous);
-
-private:
- void generateGradientPixmap(int width, int height, QColor color, bool selected) const;
-};
-
class TaskWindowContext : public Core::IContext
{
public:
@@ -126,8 +106,8 @@ public:
void removeTask(const Task &task);
void clearTasks(const QString &categoryId = QString());
- int sizeOfFile();
- int sizeOfLineNumber();
+ int sizeOfFile(const QFont &font);
+ int sizeOfLineNumber(const QFont &font);
void setFileNotFound(const QModelIndex &index, bool b);
enum Roles { File = Qt::UserRole, Line, Description, FileNotFound, Type, Category, Icon, Task_t };
@@ -146,11 +126,13 @@ private:
QHash<QString,bool> m_fileNotFound;
int m_maxSizeOfFileName;
+ QString m_fileMeasurementFont;
const QIcon m_errorIcon;
const QIcon m_warningIcon;
int m_taskCount;
int m_errorTaskCount;
int m_sizeOfLineNumber;
+ QString m_lineMeasurementFont;
};
class TaskFilterModel : public QSortFilterProxyModel
@@ -188,6 +170,97 @@ private:
QStringList m_categoryIds;
};
+class TaskDelegate : public QStyledItemDelegate
+{
+ Q_OBJECT
+
+public:
+ TaskDelegate(QObject * parent = 0);
+ ~TaskDelegate();
+ void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
+ QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
+
+ // TaskView uses this method if the size of the taskview changes
+ void emitSizeHintChanged(const QModelIndex &index);
+
+public slots:
+ void currentChanged(const QModelIndex &current, const QModelIndex &previous);
+
+private:
+ void generateGradientPixmap(int width, int height, QColor color, bool selected) const;
+
+ /*
+ Collapsed:
+ +----------------------------------------------------------------------------------------------------+
+ | TASKICONAREA TEXTAREA FILEAREA LINEAREA |
+ +----------------------------------------------------------------------------------------------------+
+
+ Expanded:
+ +----------------------------------------------------------------------------------------------------+
+ | TASKICONICON TEXTAREA FILEAREA LINEAREA |
+ | more text -------------------------------------------------------------------------> |
+ +----------------------------------------------------------------------------------------------------+
+ */
+ class Positions
+ {
+ public:
+ Positions(const QStyleOptionViewItemV4 &options, TaskModel *model) :
+ m_totalWidth(options.rect.width()),
+ m_maxFileLength(model->sizeOfFile(options.font)),
+ m_maxLineLength(model->sizeOfLineNumber(options.font)),
+ m_realFileLength(m_maxFileLength),
+ m_top(options.rect.top()),
+ m_bottom(options.rect.bottom())
+ {
+ int flexibleArea = lineAreaLeft() - textAreaLeft() - ITEM_SPACING;
+ if (m_maxFileLength > flexibleArea / 2)
+ m_realFileLength = flexibleArea / 2;
+ m_fontHeight = QFontMetrics(options.font).height();
+ }
+
+ int top() const { return m_top + ITEM_MARGIN; }
+ int left() const { return ITEM_MARGIN; }
+ int right() const { return m_totalWidth - ITEM_MARGIN; }
+ int bottom() const { return m_bottom; }
+ int firstLineHeight() const { return m_fontHeight + 1; }
+ int minimumHeight() const { return taskIconHeight() + 2 * ITEM_MARGIN; }
+
+ int taskIconLeft() const { return left(); }
+ int taskIconWidth() const { return TASK_ICON_SIZE; }
+ int taskIconHeight() const { return TASK_ICON_SIZE; }
+ int taskIconRight() const { return taskIconLeft() + taskIconWidth(); }
+ QRect taskIcon() const { return QRect(taskIconLeft(), top(), taskIconWidth(), taskIconHeight()); }
+
+ int textAreaLeft() const { return taskIconRight() + ITEM_SPACING; }
+ int textAreaWidth() const { return textAreaRight() - textAreaLeft(); }
+ int textAreaRight() const { return fileAreaLeft() - ITEM_SPACING; }
+ QRect textArea() const { return QRect(textAreaLeft(), top(), textAreaWidth(), firstLineHeight()); }
+
+ int fileAreaLeft() const { return fileAreaRight() - fileAreaWidth(); }
+ int fileAreaWidth() const { return m_realFileLength; }
+ int fileAreaRight() const { return lineAreaLeft() - ITEM_SPACING; }
+ QRect fileArea() const { return QRect(fileAreaLeft(), top(), fileAreaWidth(), firstLineHeight()); }
+
+ int lineAreaLeft() const { return lineAreaRight() - lineAreaWidth(); }
+ int lineAreaWidth() const { return m_maxLineLength; }
+ int lineAreaRight() const { return right(); }
+ QRect lineArea() const { return QRect(lineAreaLeft(), top(), lineAreaWidth(), firstLineHeight()); }
+
+ private:
+ int m_totalWidth;
+ int m_maxFileLength;
+ int m_maxLineLength;
+ int m_realFileLength;
+ int m_top;
+ int m_bottom;
+ int m_fontHeight;
+
+ static const int TASK_ICON_SIZE = 16;
+ static const int ITEM_MARGIN = 2;
+ static const int ITEM_SPACING = 2 * ITEM_MARGIN;
+ };
+};
+
TaskView::TaskView(QWidget *parent)
: QListView(parent)
{
@@ -227,7 +300,6 @@ TaskModel::TaskModel() :
m_errorTaskCount(0),
m_sizeOfLineNumber(0)
{
-
}
int TaskModel::taskCount()
@@ -292,14 +364,7 @@ void TaskModel::addTask(const Task &task)
m_tasks.append(task);
endInsertRows();
- QFont font;
- QFontMetrics fm(font);
- QString filename = task.file;
- const int pos = filename.lastIndexOf(QLatin1Char('/'));
- if (pos != -1)
- filename = task.file.mid(pos +1);
-
- m_maxSizeOfFileName = qMax(m_maxSizeOfFileName, fm.width(filename));
+ m_maxSizeOfFileName = 0;
++m_taskCount;
if (task.type == Task::Error)
++m_errorTaskCount;
@@ -434,16 +499,32 @@ QString TaskModel::categoryDisplayName(const QString &categoryId) const
return m_categories.value(categoryId);
}
-int TaskModel::sizeOfFile()
+int TaskModel::sizeOfFile(const QFont &font)
{
+ QString fontKey = font.key();
+ if (m_maxSizeOfFileName > 0 && fontKey == m_fileMeasurementFont)
+ return m_maxSizeOfFileName;
+
+ QFontMetrics fm(font);
+ m_fileMeasurementFont = fontKey;
+
+ foreach (const Task & t, m_tasks) {
+ QString filename = t.file;
+ const int pos = filename.lastIndexOf(QLatin1Char('/'));
+ if (pos != -1)
+ filename = filename.mid(pos +1);
+
+ m_maxSizeOfFileName = qMax(m_maxSizeOfFileName, fm.width(filename));
+ }
return m_maxSizeOfFileName;
}
-int TaskModel::sizeOfLineNumber()
+int TaskModel::sizeOfLineNumber(const QFont &font)
{
- if (m_sizeOfLineNumber == 0) {
- QFont font;
+ QString fontKey = font.key();
+ if (m_sizeOfLineNumber == 0 || fontKey != m_lineMeasurementFont) {
QFontMetrics fm(font);
+ m_lineMeasurementFont = fontKey;
m_sizeOfLineNumber = fm.width("8888");
}
return m_sizeOfLineNumber;
@@ -893,11 +974,12 @@ QSize TaskDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelInd
int fontHeight = fm.height();
int fontLeading = fm.leading();
- QSize s;
- s.setWidth(option.rect.width());
const QAbstractItemView * view = qobject_cast<const QAbstractItemView *>(opt.widget);
TaskModel *model = static_cast<TaskFilterModel *>(view->model())->taskModel();
- int width = opt.rect.width() - model->sizeOfFile() - model->sizeOfLineNumber() - 12 - 22;
+ Positions positions(option, model);
+
+ QSize s;
+ s.setWidth(option.rect.width());
if (view->selectionModel()->currentIndex() == index) {
QString description = index.data(TaskModel::Description).toString();
// Layout the description
@@ -910,7 +992,7 @@ QSize TaskDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelInd
QTextLine line = tl.createLine();
if (!line.isValid())
break;
- line.setLineWidth(width);
+ line.setLineWidth(positions.textAreaWidth());
height += leading;
line.setPosition(QPoint(0, height));
height += static_cast<int>(line.height());
@@ -921,8 +1003,8 @@ QSize TaskDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelInd
} else {
s.setHeight(fontHeight + 3);
}
- if (s.height() < TASK_ICON_SIZE + 2 * TASK_ICON_MARGIN)
- s.setHeight(TASK_ICON_SIZE + 2 * TASK_ICON_MARGIN);
+ if (s.height() < positions.minimumHeight())
+ s.setHeight(positions.minimumHeight());
return s;
}
@@ -969,23 +1051,26 @@ void TaskDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
painter->setPen(textColor);
TaskModel *model = static_cast<TaskFilterModel *>(view->model())->taskModel();
+ Positions positions(opt, model);
+
+ // Paint TaskIconArea:
QIcon icon = index.data(TaskModel::Icon).value<QIcon>();
- painter->drawPixmap(TASK_ICON_MARGIN, opt.rect.top() + TASK_ICON_MARGIN, icon.pixmap(TASK_ICON_SIZE, TASK_ICON_SIZE));
+ painter->drawPixmap(positions.left(), positions.top(),
+ icon.pixmap(positions.taskIconWidth(), positions.taskIconHeight()));
- int width = opt.rect.width() - model->sizeOfFile() - model->sizeOfLineNumber() - 12 - 22;
+ // Paint TextArea:
if (!selected) {
// in small mode we lay out differently
QString bottom = index.data(TaskModel::Description).toString().split('\n').first();
- painter->drawText(22, 2 + opt.rect.top() + fm.ascent(), bottom);
- if (fm.width(bottom) > width) {
+ painter->setClipRect(positions.textArea());
+ painter->drawText(positions.textAreaLeft(), positions.top() + fm.ascent(), bottom);
+ if (fm.width(bottom) > positions.textAreaWidth()) {
// draw a gradient to mask the text
- int gwidth = opt.rect.right() + 1 - width;
- QLinearGradient lg(QPoint(width, 0), QPoint(width+gwidth, 0));
- QColor c = backgroundColor;
- c.setAlpha(0);
- lg.setColorAt(0, c);
- lg.setColorAt(20.0/gwidth, backgroundColor);
- painter->fillRect(width, 2 + opt.rect.top(), gwidth, fm.height() + 1, lg);
+ int gradientStart = positions.textAreaRight() - ELLIPSIS_GRADIENT_WIDTH + 1;
+ QLinearGradient lg(gradientStart, 0, gradientStart + ELLIPSIS_GRADIENT_WIDTH, 0);
+ lg.setColorAt(0, Qt::transparent);
+ lg.setColorAt(1, backgroundColor);
+ painter->fillRect(gradientStart, positions.top(), ELLIPSIS_GRADIENT_WIDTH, positions.firstLineHeight(), lg);
}
} else {
// Description
@@ -1001,14 +1086,13 @@ void TaskDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
QTextLine line = tl.createLine();
if (!line.isValid())
break;
- line.setLineWidth(width);
+ line.setLineWidth(positions.textAreaWidth());
height += leading;
line.setPosition(QPoint(0, height));
height += static_cast<int>(line.height());
}
tl.endLayout();
- tl.draw(painter, QPoint(22, 2 + opt.rect.top()));
- //painter->drawText(22, 2 + opt.rect.top() + fm.ascent(), description);
+ tl.draw(painter, QPoint(positions.textAreaLeft(), positions.top()));
QColor mix;
mix.setRgb( static_cast<int>(0.7 * textColor.red() + 0.3 * backgroundColor.red()),
@@ -1017,27 +1101,42 @@ void TaskDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
painter->setPen(mix);
const QString directory = QDir::toNativeSeparators(index.data(TaskModel::File).toString());
- int secondBaseLine = 2 + fm.ascent() + opt.rect.top() + height + leading; //opt.rect.top() + fm.ascent() + fm.height() + 6;
+ int secondBaseLine = positions.top() + fm.ascent() + height + leading;
if (index.data(TaskModel::FileNotFound).toBool()) {
QString fileNotFound = tr("File not found: %1").arg(directory);
painter->setPen(Qt::red);
- painter->drawText(22, secondBaseLine, fileNotFound);
+ painter->drawText(positions.textAreaLeft(), secondBaseLine, fileNotFound);
} else {
- painter->drawText(22, secondBaseLine, directory);
+ painter->drawText(positions.textAreaLeft(), secondBaseLine, directory);
}
}
-
painter->setPen(textColor);
- // Assemble string for the right side
- // just filename + linenumer
+
+ // Paint FileArea
QString file = index.data(TaskModel::File).toString();
const int pos = file.lastIndexOf(QLatin1Char('/'));
if (pos != -1)
file = file.mid(pos +1);
- painter->drawText(width + 22 + 4, 2 + opt.rect.top() + fm.ascent(), file);
+ const int realFileWidth = fm.width(file);
+ painter->setClipRect(positions.fileArea());
+ painter->drawText(qMin(positions.fileAreaLeft(), positions.fileAreaRight() - realFileWidth),
+ positions.top() + fm.ascent(), file);
+ if (realFileWidth > positions.fileAreaWidth()) {
+ // draw a gradient to mask the text
+ int gradientStart = positions.fileAreaLeft() - 1;
+ QLinearGradient lg(gradientStart + ELLIPSIS_GRADIENT_WIDTH, 0, gradientStart, 0);
+ lg.setColorAt(0, Qt::transparent);
+ lg.setColorAt(1, backgroundColor);
+ painter->fillRect(gradientStart, positions.top(), ELLIPSIS_GRADIENT_WIDTH, positions.firstLineHeight(), lg);
+ }
+
+ // Paint LineArea
+ QString lineText = index.data(TaskModel::Line).toString();
+ painter->setClipRect(positions.lineArea());
+ const int realLineWidth = fm.width(lineText);
+ painter->drawText(positions.lineAreaRight() - realLineWidth, positions.top() + fm.ascent(), lineText);
+ painter->setClipRect(opt.rect);
- QString topRight = index.data(TaskModel::Line).toString();
- painter->drawText(opt.rect.right() - fm.width(topRight) - 6 , 2 + opt.rect.top() + fm.ascent(), topRight);
// Separator lines
painter->setPen(QColor::fromRgb(150,150,150));
painter->drawLine(0, opt.rect.bottom(), opt.rect.right(), opt.rect.bottom());
diff --git a/src/plugins/projectexplorer/toolchain.cpp b/src/plugins/projectexplorer/toolchain.cpp
index 2a8e21c30a..6317965f40 100644
--- a/src/plugins/projectexplorer/toolchain.cpp
+++ b/src/plugins/projectexplorer/toolchain.cpp
@@ -39,8 +39,8 @@
#include "msvcparser.h"
#include "linuxiccparser.h"
-
#include <utils/synchronousprocess.h>
+#include <utils/qtcprocess.h>
#include <QtCore/QDebug>
#include <QtCore/QFileInfo>
@@ -123,10 +123,10 @@ QStringList ToolChain::availableMSVCVersions(bool amd64)
return rc;
}
-QList<ToolChain::ToolChainType> ToolChain::supportedToolChains()
+QList<ToolChainType> ToolChain::supportedToolChains()
{
- QList<ToolChain::ToolChainType> toolChains;
- for (int i = 0; i < LAST_VALID; ++i) {
+ QList<ToolChainType> toolChains;
+ for (int i = 0; i < ToolChain_LAST_VALID; ++i) {
toolChains.append(ToolChainType(i));
}
return toolChains;
@@ -135,35 +135,39 @@ QList<ToolChain::ToolChainType> ToolChain::supportedToolChains()
QString ToolChain::toolChainName(ToolChainType tc)
{
switch (tc) {
- case GCC:
+ case ToolChain_GCC:
return QCoreApplication::translate("ToolChain", "GCC");
- case LINUX_ICC:
+ case ToolChain_LINUX_ICC:
return QCoreApplication::translate("ToolChain", "Intel C++ Compiler (Linux)");
- case MinGW:
+ case ToolChain_MinGW:
return QString::fromLatin1("MinGW");
- case MSVC:
+ case ToolChain_MSVC:
return QCoreApplication::translate("ToolChain", "Microsoft Visual C++");
- case WINCE:
+ case ToolChain_WINCE:
return QCoreApplication::translate("ToolChain", "Windows CE");
- case WINSCW:
+ case ToolChain_WINSCW:
return QCoreApplication::translate("ToolChain", "WINSCW");
- case GCCE:
+ case ToolChain_GCCE:
return QCoreApplication::translate("ToolChain", "GCCE");
- case GCCE_GNUPOC:
+ case ToolChain_GCCE_GNUPOC:
return QCoreApplication::translate("ToolChain", "GCCE/GnuPoc");
- case RVCT_ARMV5_GNUPOC:
+ case ToolChain_RVCT_ARMV5_GNUPOC:
return QCoreApplication::translate("ToolChain", "RVCT (ARMV6)/GnuPoc");
- case RVCT_ARMV5:
- return QCoreApplication::translate("ToolChain", "RVCT (ARMV5)");
- case RVCT_ARMV6:
- return QCoreApplication::translate("ToolChain", "RVCT (ARMV6)");
- case GCC_MAEMO:
+ case ToolChain_RVCT2_ARMV5:
+ return QCoreApplication::translate("ToolChain", "RVCT 2 (ARMV5)");
+ case ToolChain_RVCT2_ARMV6:
+ return QCoreApplication::translate("ToolChain", "RVCT 2 (ARMV6)");
+ case ToolChain_RVCT4_ARMV5:
+ return QCoreApplication::translate("ToolChain", "RVCT 4 (ARMV5)");
+ case ToolChain_RVCT4_ARMV6:
+ return QCoreApplication::translate("ToolChain", "RVCT 4 (ARMV6)");
+ case ToolChain_GCC_MAEMO:
return QCoreApplication::translate("ToolChain", "GCC for Maemo");
- case OTHER:
+ case ToolChain_OTHER:
return QCoreApplication::translate("ToolChain", "Other");
- case INVALID:
+ case ToolChain_INVALID:
return QCoreApplication::translate("ToolChain", "<Invalid>");
- case UNKNOWN:
+ case ToolChain_UNKNOWN:
break;
default:
Q_ASSERT("Missing name for Toolchaintype");
@@ -177,9 +181,9 @@ GccToolChain::GccToolChain(const QString &gcc)
}
-ToolChain::ToolChainType GccToolChain::type() const
+ToolChainType GccToolChain::type() const
{
- return ToolChain::GCC;
+ return ToolChain_GCC;
}
static QByteArray gccPredefinedMacros(const QString &gcc, const QStringList &env)
@@ -337,9 +341,9 @@ MinGWToolChain::MinGWToolChain(const QString &gcc, const QString &mingwPath)
}
-ToolChain::ToolChainType MinGWToolChain::type() const
+ToolChainType MinGWToolChain::type() const
{
- return ToolChain::MinGW;
+ return ToolChain_MinGW;
}
bool MinGWToolChain::equals(const ToolChain *other) const
@@ -374,9 +378,9 @@ LinuxIccToolChain::LinuxIccToolChain()
{
}
-ToolChain::ToolChainType LinuxIccToolChain::type() const
+ToolChainType LinuxIccToolChain::type() const
{
- return ToolChain::LINUX_ICC;
+ return ToolChain_LINUX_ICC;
}
IOutputParser *LinuxIccToolChain::outputParser() const
@@ -591,9 +595,9 @@ MSVCToolChain::MSVCToolChain(const Installation &in) :
qDebug() << "\nMSVCToolChain::CT\n" << m_installation;
}
-ToolChain::ToolChainType MSVCToolChain::type() const
+ToolChainType MSVCToolChain::type() const
{
- return ToolChain::MSVC;
+ return ToolChain_MSVC;
}
bool MSVCToolChain::equals(const ToolChain *other) const
@@ -772,16 +776,16 @@ MSVCToolChain::StringStringPairList MSVCToolChain::readEnvironmentSettingI(const
if (!tf.open())
return StringStringPairList();
const QString filename = tf.fileName();
- QByteArray call = "call \"";
- call += varsBat.toLocal8Bit();
- call += '"';
+ QByteArray call = "call ";
+ call += Utils::QtcProcess::quoteArg(varsBat).toLocal8Bit();
if (!args.isEmpty()) {
call += ' ';
- call += args.join(QString(QLatin1Char(' '))).toLocal8Bit();
+ call += Utils::QtcProcess::joinArgs(args).toLocal8Bit();
}
call += "\r\n";
tf.write(call);
- const QByteArray redirect = "set > \"" + QDir::toNativeSeparators(tempOutputFileName).toLocal8Bit() + "\"\r\n";
+ const QByteArray redirect = "set > " + Utils::QtcProcess::quoteArg(
+ QDir::toNativeSeparators(tempOutputFileName)).toLocal8Bit() + "\r\n";
tf.write(redirect);
tf.flush();
tf.waitForBytesWritten(30000);
@@ -874,9 +878,9 @@ WinCEToolChain::WinCEToolChain(const Installation &in, const QString &platform)
{
}
-ToolChain::ToolChainType WinCEToolChain::type() const
+ToolChainType WinCEToolChain::type() const
{
- return ToolChain::WINCE;
+ return ToolChain_WINCE;
}
bool WinCEToolChain::equals(const ToolChain *other) const
diff --git a/src/plugins/projectexplorer/toolchain.h b/src/plugins/projectexplorer/toolchain.h
index b3573d9857..3578e8fe00 100644
--- a/src/plugins/projectexplorer/toolchain.h
+++ b/src/plugins/projectexplorer/toolchain.h
@@ -35,6 +35,7 @@
#define TOOLCHAIN_H
#include "projectexplorer_export.h"
+#include "toolchaintype.h"
#include <utils/environment.h>
@@ -77,26 +78,6 @@ private:
class PROJECTEXPLORER_EXPORT ToolChain
{
public:
- enum ToolChainType
- {
- GCC = 0,
- LINUX_ICC = 1,
- MinGW = 2,
- MSVC = 3,
- WINCE = 4,
- WINSCW = 5,
- GCCE = 6,
- RVCT_ARMV5 = 7,
- RVCT_ARMV6 = 8,
- GCC_MAEMO = 9,
- GCCE_GNUPOC = 10,
- RVCT_ARMV5_GNUPOC = 11,
- LAST_VALID = 11,
- OTHER = 200,
- UNKNOWN = 201,
- INVALID = 202
- };
-
virtual QByteArray predefinedMacros() = 0;
virtual QList<HeaderPath> systemHeaderPaths() = 0;
virtual void addToEnvironment(Utils::Environment &env) = 0;
@@ -116,7 +97,7 @@ public:
static ToolChain *createWinCEToolChain(const QString &name, const QString &platform);
static QStringList availableMSVCVersions();
static QStringList availableMSVCVersions(bool amd64); // filter 32/64bit apart
- static QList<ToolChain::ToolChainType> supportedToolChains();
+ static QList<ToolChainType> supportedToolChains();
static QString toolChainName(ToolChainType tc);
@@ -261,6 +242,6 @@ private:
}
-Q_DECLARE_METATYPE(ProjectExplorer::ToolChain::ToolChainType);
+Q_DECLARE_METATYPE(ProjectExplorer::ToolChainType)
#endif // TOOLCHAIN_H
diff --git a/src/plugins/projectexplorer/toolchaintype.h b/src/plugins/projectexplorer/toolchaintype.h
new file mode 100644
index 0000000000..de0347d758
--- /dev/null
+++ b/src/plugins/projectexplorer/toolchaintype.h
@@ -0,0 +1,59 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 TOOLCHAINTYPE_H
+#define TOOLCHAINTYPE_H
+
+namespace ProjectExplorer {
+
+enum ToolChainType
+{
+ ToolChain_GCC = 0,
+ ToolChain_LINUX_ICC = 1,
+ ToolChain_MinGW = 2,
+ ToolChain_MSVC = 3,
+ ToolChain_WINCE = 4,
+ ToolChain_WINSCW = 5,
+ ToolChain_GCCE = 6,
+ ToolChain_RVCT2_ARMV5 = 7,
+ ToolChain_RVCT2_ARMV6 = 8,
+ ToolChain_GCC_MAEMO = 9,
+ ToolChain_GCCE_GNUPOC = 10,
+ ToolChain_RVCT_ARMV5_GNUPOC = 11,
+ ToolChain_RVCT4_ARMV5 = 12,
+ ToolChain_RVCT4_ARMV6 = 13,
+ ToolChain_LAST_VALID = 13,
+ ToolChain_OTHER = 200,
+ ToolChain_UNKNOWN = 201,
+ ToolChain_INVALID = 202
+};
+
+} // namespace ProjectExplorer
+
+#endif // TOOLCHAINTYPE_H
diff --git a/src/plugins/projectexplorer/userfileaccessor.cpp b/src/plugins/projectexplorer/userfileaccessor.cpp
index b4557221fb..48cd623f59 100644
--- a/src/plugins/projectexplorer/userfileaccessor.cpp
+++ b/src/plugins/projectexplorer/userfileaccessor.cpp
@@ -40,14 +40,15 @@
#include "projectexplorersettings.h"
#include "projectexplorerconstants.h"
#include "target.h"
-#include "toolchain.h"
+#include "toolchaintype.h"
#include <coreplugin/icore.h>
-#include <coreplugin/mainwindow.h>
#include <coreplugin/ifile.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <QtGui/QApplication>
+#include <QtGui/QMainWindow>
#include <QtCore/QFile>
#include <QtGui/QMessageBox>
#include <QtNetwork/QHostInfo>
@@ -55,8 +56,11 @@
using namespace ProjectExplorer;
namespace {
+const char * const USERFILE_VERSION_KEY = "ProjectExplorer.Project.Updater.FileVersion";
const char * const USERFILE_ENVIRONMENT_ID_KEY = "ProjectExplorer.Project.Updater.EnvironmentId";
+const char * const USERFILE_PROP = "qtcUserFileName";
+
const char * const PROJECT_FILE_POSTFIX(".user");
// Version 0 is used in Qt Creator 1.3.x and
@@ -222,6 +226,28 @@ public:
QVariantMap update(Project *project, const QVariantMap &map);
};
+// Version 8 reflects the change of environment variable expansion rules,
+// turning some env variables into expandos, the change of argument quoting rules,
+// and the change of VariableManager's expansion syntax.
+class Version8Handler : public UserFileVersionHandler
+{
+public:
+ int userFileVersion() const
+ {
+ return 8;
+ }
+
+ QString displayUserFileVersion() const
+ {
+ // pre5 because we renamed 2.2 to 2.1 later, so people already have 2.2pre4 files
+ return QLatin1String("2.2pre5");
+ }
+
+ QVariantMap update(Project *project, const QVariantMap &map);
+};
+
+} // namespace
+
//
// Helper functions:
//
@@ -241,7 +267,57 @@ static QString fileNameFor(const QString &name)
return baseName + QLatin1String(PROJECT_FILE_POSTFIX);
}
-} // namespace
+QT_BEGIN_NAMESPACE
+
+class HandlerNode {
+public:
+ QSet<QString> strings;
+ QHash<QString, HandlerNode> children;
+};
+Q_DECLARE_TYPEINFO(HandlerNode, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+static HandlerNode buildHandlerNodes(const char * const **keys)
+{
+ HandlerNode ret;
+ while (const char *rname = *(*keys)++) {
+ QString name = QLatin1String(rname);
+ if (name.endsWith(QLatin1Char('.'))) {
+ HandlerNode sub = buildHandlerNodes(keys);
+ foreach (const QString &key, name.split(QLatin1Char('|')))
+ ret.children.insert(key, sub);
+ } else {
+ ret.strings.insert(name);
+ }
+ }
+ return ret;
+}
+
+static QVariantMap processHandlerNodes(const HandlerNode &node, const QVariantMap &map,
+ QVariant (*handler)(const QVariant &var))
+{
+ QVariantMap result;
+ QMapIterator<QString, QVariant> it(map);
+ while (it.hasNext()) {
+ it.next();
+ const QString &key = it.key();
+ if (node.strings.contains(key)) {
+ result.insert(key, handler(it.value()));
+ goto handled;
+ }
+ if (it.value().type() == QVariant::Map)
+ for (QHash<QString, HandlerNode>::ConstIterator subit = node.children.constBegin();
+ subit != node.children.constEnd(); ++subit)
+ if (key.startsWith(subit.key())) {
+ result.insert(key, processHandlerNodes(subit.value(), it.value().toMap(), handler));
+ goto handled;
+ }
+ result.insert(key, it.value());
+ handled: ;
+ }
+ return result;
+}
// -------------------------------------------------------------------------
// UserFileVersionHandler
@@ -296,6 +372,7 @@ UserFileAccessor::UserFileAccessor() :
addVersionHandler(new Version5Handler);
addVersionHandler(new Version6Handler);
addVersionHandler(new Version7Handler);
+ addVersionHandler(new Version8Handler);
}
UserFileAccessor::~UserFileAccessor()
@@ -308,21 +385,75 @@ QVariantMap UserFileAccessor::restoreSettings(Project *project)
if (m_lastVersion < 0 || !project)
return QVariantMap();
+ PersistentSettingsReader reader;
+
QString fileName = fileNameFor(project->file()->fileName());
- if (!QFile::exists(fileName))
+ if (!reader.load(fileName))
return QVariantMap();
- PersistentSettingsReader reader;
- reader.load(fileName);
-
QVariantMap map(reader.restoreValues());
// Get and verify file version:
- const int fileVersion = map.value(QLatin1String(Constants::USERFILE_VERSION_KEY), 0).toInt();
- if (fileVersion < m_firstVersion || fileVersion > m_lastVersion + 1) {
- qWarning() << "File version" << fileVersion << "is not supported.";
+ int fileVersion = map.value(QLatin1String(USERFILE_VERSION_KEY), 0).toInt();
+ if (fileVersion < m_firstVersion) {
+ qWarning() << "File version" << fileVersion << "too old.";
return QVariantMap();
}
+ bool skipBackup = false;
+ if (fileVersion > m_lastVersion + 1) {
+ int oldFileVersion = fileVersion;
+ int newestFileVersion = -1;
+ QString newestFileName;
+ QFileInfo qfi(fileName);
+ foreach (const QString &de, qfi.absoluteDir().entryList(
+ QStringList() << (qfi.fileName() + ".*"))) {
+ QString extension = de.mid(qfi.fileName().length() + 1);
+ QString oldFileName = fileName + '.' + extension;
+ // This is a quick check to identify old versions.
+ for (fileVersion = m_lastVersion; fileVersion >= m_firstVersion; --fileVersion)
+ if (extension == m_handlers.value(fileVersion)->displayUserFileVersion()) {
+ if (fileVersion > newestFileVersion) {
+ newestFileVersion = fileVersion;
+ newestFileName = oldFileName;
+ }
+ goto found;
+ }
+ // This is an expensive check needed to identify our own and newer versions
+ // (as we don't know what extensions will be assigned in the future).
+ if (reader.load(oldFileName)) {
+ map = reader.restoreValues();
+ fileVersion = map.value(QLatin1String(USERFILE_VERSION_KEY), 0).toInt();
+ if (fileVersion == m_lastVersion + 1) {
+ fileName = oldFileName;
+ goto gotFile;
+ }
+ }
+ found: ;
+ }
+ if (newestFileVersion < 0) {
+ qWarning() << "File version" << oldFileVersion << "too new.";
+ return QVariantMap();
+ }
+ fileName = newestFileName;
+ fileVersion = newestFileVersion;
+ if (!reader.load(fileName))
+ return QVariantMap();
+ map = reader.restoreValues();
+ gotFile:
+ QMessageBox::information(Core::ICore::instance()->mainWindow(),
+ QApplication::translate("ProjectExplorer::UserFileAccessor",
+ "Using Old Project Settings File"),
+ QApplication::translate("ProjectExplorer::UserFileAccessor",
+ "A versioned backup of the .user settings file will be used, "
+ "because the non-versioned file was created by an incompatible "
+ "newer version of Qt Creator.\n"
+ "Project settings changes made since the last time this version "
+ "of Qt Creator was used with this project are ignored, and changes "
+ "made now will <b>not</b> be propagated to the newer version."),
+ QMessageBox::Ok);
+ project->setProperty(USERFILE_PROP, fileName);
+ skipBackup = true;
+ }
// Verify environment Id:
QUuid fileEnvironmentId(map.value(QLatin1String(USERFILE_ENVIRONMENT_ID_KEY)).toString());
@@ -350,21 +481,16 @@ QVariantMap UserFileAccessor::restoreSettings(Project *project)
}
// Do we need to do a update?
- if (fileVersion != m_lastVersion + 1) {
- map.insert(QLatin1String(Constants::USERFILE_WAS_UPDATED_KEY), true);
+ if (fileVersion != m_lastVersion + 1 && !skipBackup) {
const QString backupFileName = fileName + '.' + m_handlers.value(fileVersion)->displayUserFileVersion();
- map.insert(QLatin1String(Constants::USERFILE_BACKUP_FILENAME_KEY), backupFileName);
QFile::remove(backupFileName); // Remove because copy doesn't overwrite
QFile::copy(fileName, backupFileName);
}
- map.insert(QLatin1String(Constants::USERFILE_PREVIOUS_VERSION_KEY), fileVersion);
// Update:
for (int i = fileVersion; i <= m_lastVersion; ++i)
map = m_handlers.value(i)->update(project, map);
- map.insert(QLatin1String(Constants::USERFILE_VERSION_KEY), m_lastVersion + 1);
-
return map;
}
@@ -378,11 +504,13 @@ bool UserFileAccessor::saveSettings(Project *project, const QVariantMap &map)
for (QVariantMap::const_iterator i = map.constBegin(); i != map.constEnd(); ++i)
writer.saveValue(i.key(), i.value());
- writer.saveValue(QLatin1String(Constants::USERFILE_VERSION_KEY), m_lastVersion + 1);
+ writer.saveValue(QLatin1String(USERFILE_VERSION_KEY), m_lastVersion + 1);
writer.saveValue(QLatin1String(USERFILE_ENVIRONMENT_ID_KEY),
ProjectExplorerPlugin::instance()->projectExplorerSettings().environmentId.toString());
- return writer.save(fileNameFor(project->file()->fileName()), "QtCreatorProject");
+ QString fileName = project->property(USERFILE_PROP).toString();
+ return writer.save(fileName.isEmpty() ? fileNameFor(project->file()->fileName()) : fileName,
+ "QtCreatorProject");
}
void UserFileAccessor::addVersionHandler(UserFileVersionHandler *handler)
@@ -427,15 +555,17 @@ QVariantMap Version0Handler::convertBuildConfigurations(Project *project, const
// Find a valid Id to use:
QString id;
- if (project->id() == QLatin1String("GenericProjectManager.GenericProject"))
+ if (project->id() == QLatin1String("GenericProjectManager.GenericProject")) {
id = QLatin1String("GenericProjectManager.GenericBuildConfiguration");
- else if (project->id() == QLatin1String("CMakeProjectManager.CMakeProject"))
+ } else if (project->id() == QLatin1String("CMakeProjectManager.CMakeProject")) {
id = QLatin1String("CMakeProjectManager.CMakeBuildConfiguration");
- else if (project->id() == QLatin1String("Qt4ProjectManager.Qt4Project"))
+ } else if (project->id() == QLatin1String("Qt4ProjectManager.Qt4Project")) {
+ result.insert(QLatin1String("Qt4ProjectManager.Qt4BuildConfiguration.NeedsV0Update"), QVariant());
id = QLatin1String("Qt4ProjectManager.Qt4BuildConfiguration");
- else
+ } else {
return QVariantMap(); // QmlProjects do not(/no longer) have BuildConfigurations,
// or we do not know how to handle this.
+ }
result.insert(QLatin1String("ProjectExplorer.ProjectConfiguration.Id"), id);
for (QVariantMap::const_iterator i = map.constBegin(); i != map.constEnd(); ++i) {
@@ -846,13 +976,13 @@ QVariantMap Version0Handler::update(Project *project, const QVariantMap &map)
if (!ok) {
QString toolChainName(toolchain.toString());
if (toolChainName == QLatin1String("gcc"))
- type = ToolChain::GCC;
+ type = ProjectExplorer::ToolChain_GCC;
else if (toolChainName == QLatin1String("mingw"))
- type = ToolChain::MinGW;
+ type = ProjectExplorer::ToolChain_MinGW;
else if (toolChainName == QLatin1String("msvc"))
- type = ToolChain::MSVC;
+ type = ProjectExplorer::ToolChain_MSVC;
else if (toolChainName == QLatin1String("wince"))
- type = ToolChain::WINCE;
+ type = ProjectExplorer::ToolChain_WINCE;
}
result.insert(QLatin1String("GenericProjectManager.GenericProject.Toolchain"), type);
}
@@ -1423,3 +1553,306 @@ QVariantMap Version7Handler::update(Project *, const QVariantMap &map)
}
return result;
}
+
+// -------------------------------------------------------------------------
+// Version8Handler
+// -------------------------------------------------------------------------
+
+// Argument list reinterpretation
+
+static const char * const argListKeys[] = {
+ "ProjectExplorer.Project.Target.",
+ "ProjectExplorer.Target.BuildConfiguration."
+ "|ProjectExplorer.Target.DeployConfiguration.",
+ "ProjectExplorer.BuildConfiguration.BuildStepList.",
+ "ProjectExplorer.BuildStepList.Step.",
+ "GenericProjectManager.GenericMakeStep.MakeArguments",
+ "QtProjectManager.QMakeBuildStep.QMakeArguments",
+ "Qt4ProjectManager.MakeStep.MakeArguments",
+ "CMakeProjectManager.MakeStep.AdditionalArguments",
+ 0,
+ 0,
+ 0,
+ "ProjectExplorer.Target.RunConfiguration.",
+ "ProjectExplorer.CustomExecutableRunConfiguration.Arguments",
+ "Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments",
+ "CMakeProjectManager.CMakeRunConfiguration.Arguments",
+ 0,
+ 0,
+ 0
+};
+
+static const char * const lameArgListKeys[] = {
+ "ProjectExplorer.Project.Target.",
+ "ProjectExplorer.Target.BuildConfiguration."
+ "|ProjectExplorer.Target.DeployConfiguration.",
+ "ProjectExplorer.BuildConfiguration.BuildStepList.",
+ "ProjectExplorer.BuildStepList.Step.",
+ "ProjectExplorer.ProcessStep.Arguments",
+ 0,
+ 0,
+ 0,
+ "ProjectExplorer.Target.RunConfiguration.",
+ "Qt4ProjectManager.MaemoRunConfiguration.Arguments",
+ "Qt4ProjectManager.S60DeviceRunConfiguration.CommandLineArguments",
+ "QmlProjectManager.QmlRunConfiguration.QDeclarativeViewerArguments",
+ 0,
+ 0,
+ 0
+};
+
+#ifdef Q_OS_UNIX
+inline static bool isSpecialChar(ushort c)
+{
+ // Chars that should be quoted (TM). This includes:
+ static const uchar iqm[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xdf, 0x07, 0x00, 0xd8,
+ 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x78
+ }; // 0-32 \'"$`<>|;&(){}*?#!~[]
+
+ return (c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7)));
+}
+
+inline static bool hasSpecialChars(const QString &arg)
+{
+ for (int x = arg.length() - 1; x >= 0; --x)
+ if (isSpecialChar(arg.unicode()[x].unicode()))
+ return true;
+ return false;
+}
+#endif
+
+// These were split according to sane (even if a bit arcane) rules
+static QVariant version8ArgNodeHandler(const QVariant &var)
+{
+ QString ret;
+ foreach (const QVariant &svar, var.toList()) {
+#ifdef Q_OS_UNIX
+ // We don't just addArg, so we don't disarm existing env expansions.
+ // This is a bit fuzzy logic ...
+ QString s = svar.toString();
+ s.replace(QLatin1Char('\\'), QLatin1String("\\\\"));
+ s.replace(QLatin1Char('"'), QLatin1String("\\\""));
+ s.replace(QLatin1Char('`'), QLatin1String("\\`"));
+ if (s != svar.toString() || hasSpecialChars(s))
+ s.prepend(QLatin1Char('"')).append(QLatin1Char('"'));
+ Utils::QtcProcess::addArgs(&ret, s);
+#else
+ // Under windows, env expansions cannot be quoted anyway.
+ Utils::QtcProcess::addArg(&ret, svar.toString());
+#endif
+ }
+ return QVariant(ret);
+}
+
+// These were just split on whitespace
+static QVariant version8LameArgNodeHandler(const QVariant &var)
+{
+ QString ret;
+ foreach (const QVariant &svar, var.toList())
+ Utils::QtcProcess::addArgs(&ret, svar.toString());
+ return QVariant(ret);
+}
+
+// Environment variable reinterpretation
+
+static const char * const envExpandedKeys[] = {
+ "ProjectExplorer.Project.Target.",
+ "ProjectExplorer.Target.BuildConfiguration."
+ "|ProjectExplorer.Target.DeployConfiguration.",
+ "ProjectExplorer.BuildConfiguration.BuildStepList.",
+ "ProjectExplorer.BuildStepList.Step.",
+ "ProjectExplorer.ProcessStep.WorkingDirectory",
+ "ProjectExplorer.ProcessStep.Command",
+ "ProjectExplorer.ProcessStep.Arguments",
+ "GenericProjectManager.GenericMakeStep.MakeCommand",
+ "GenericProjectManager.GenericMakeStep.MakeArguments",
+ "GenericProjectManager.GenericMakeStep.BuildTargets",
+ "QtProjectManager.QMakeBuildStep.QMakeArguments",
+ "Qt4ProjectManager.MakeStep.MakeCommand",
+ "Qt4ProjectManager.MakeStep.MakeArguments",
+ "CMakeProjectManager.MakeStep.AdditionalArguments",
+ "CMakeProjectManager.MakeStep.BuildTargets",
+ 0,
+ 0,
+ "Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory",
+ 0,
+ "ProjectExplorer.Target.RunConfiguration.",
+ "ProjectExplorer.CustomExecutableRunConfiguration.WorkingDirectory",
+ "ProjectExplorer.CustomExecutableRunConfiguration.Executable",
+ "ProjectExplorer.CustomExecutableRunConfiguration.Arguments",
+ "Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory",
+ "Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments",
+ "Qt4ProjectManager.MaemoRunConfiguration.Arguments",
+ "Qt4ProjectManager.S60DeviceRunConfiguration.CommandLineArguments",
+ "CMakeProjectManager.CMakeRunConfiguration.UserWorkingDirectory",
+ "CMakeProjectManager.CMakeRunConfiguration.Arguments",
+ 0,
+ 0,
+ 0
+};
+
+static QString version8NewVar(const QString &old)
+{
+ QString ret = old;
+#ifdef Q_OS_UNIX
+ ret.prepend(QLatin1String("${"));
+ ret.append(QLatin1Char('}'));
+#else
+ ret.prepend(QLatin1Char('%'));
+ ret.append(QLatin1Char('%'));
+#endif
+ return ret;
+}
+
+// Translate DOS-like env var expansions into Unix-like ones and vice versa.
+// On the way, change {SOURCE,BUILD}DIR env expansions to %{}-expandos
+static QVariant version8EnvNodeTransform(const QVariant &var)
+{
+ QString result = var.toString();
+
+ result.replace(QRegExp(QLatin1String("%SOURCEDIR%|\\$(SOURCEDIR\\b|\\{SOURCEDIR\\})")),
+ QLatin1String("%{sourceDir}"));
+ result.replace(QRegExp(QLatin1String("%BUILDDIR%|\\$(BUILDDIR\\b|\\{BUILDDIR\\})")),
+ QLatin1String("%{buildDir}"));
+#ifdef Q_OS_UNIX
+ for (int vStart = -1, i = 0; i < result.length(); ) {
+ QChar c = result.at(i++);
+ if (c == QLatin1Char('%')) {
+ if (vStart > 0 && vStart < i - 1) {
+ QString nv = version8NewVar(result.mid(vStart, i - 1 - vStart));
+ result.replace(vStart - 1, i - vStart + 1, nv);
+ i = vStart - 1 + nv.length();
+ vStart = -1;
+ } else {
+ vStart = i;
+ }
+ } else if (vStart > 0) {
+ // Sanity check so we don't catch too much garbage
+ if (!c.isLetterOrNumber() && c != QLatin1Char('_'))
+ vStart = -1;
+ }
+ }
+#else
+ enum { BASE, OPTIONALVARIABLEBRACE, VARIABLE, BRACEDVARIABLE } state = BASE;
+ int vStart = -1;
+
+ for (int i = 0; i < result.length();) {
+ QChar c = result.at(i++);
+ if (state == BASE) {
+ if (c == QLatin1Char('$'))
+ state = OPTIONALVARIABLEBRACE;
+ } else if (state == OPTIONALVARIABLEBRACE) {
+ if (c == QLatin1Char('{')) {
+ state = BRACEDVARIABLE;
+ vStart = i;
+ } else if (c.isLetterOrNumber() || c == QLatin1Char('_')) {
+ state = VARIABLE;
+ vStart = i - 1;
+ } else {
+ state = BASE;
+ }
+ } else if (state == BRACEDVARIABLE) {
+ if (c == QLatin1Char('}')) {
+ QString nv = version8NewVar(result.mid(vStart, i - 1 - vStart));
+ result.replace(vStart - 2, i - vStart + 2, nv);
+ i = vStart + nv.length();
+ state = BASE;
+ }
+ } else if (state == VARIABLE) {
+ if (!c.isLetterOrNumber() && c != QLatin1Char('_')) {
+ QString nv = version8NewVar(result.mid(vStart, i - 1 - vStart));
+ result.replace(vStart - 1, i - vStart, nv);
+ i = vStart - 1 + nv.length(); // On the same char - could be next expansion.
+ state = BASE;
+ }
+ }
+ }
+ if (state == VARIABLE) {
+ QString nv = version8NewVar(result.mid(vStart));
+ result.truncate(vStart - 1);
+ result += nv;
+ }
+#endif
+
+ return QVariant(result);
+}
+
+static QVariant version8EnvNodeHandler(const QVariant &var)
+{
+ if (var.type() != QVariant::List)
+ return version8EnvNodeTransform(var);
+
+ QVariantList vl;
+ foreach (const QVariant &svar, var.toList())
+ vl << version8EnvNodeTransform(svar);
+ return vl;
+}
+
+// VariableManager expando reinterpretation
+
+static const char * const varExpandedKeys[] = {
+ "ProjectExplorer.Project.Target.",
+ "ProjectExplorer.Target.BuildConfiguration."
+ "|ProjectExplorer.Target.DeployConfiguration.",
+ "ProjectExplorer.BuildConfiguration.BuildStepList.",
+ "ProjectExplorer.BuildStepList.Step.",
+ "GenericProjectManager.GenericMakeStep.MakeCommand",
+ "GenericProjectManager.GenericMakeStep.MakeArguments",
+ "GenericProjectManager.GenericMakeStep.BuildTargets",
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+// Translate old-style ${} var expansions into new-style %{} ones
+static QVariant version8VarNodeHandler(const QVariant &var)
+{
+ static const char * const vars[] = {
+ "absoluteFilePath",
+ "absolutePath",
+ "baseName",
+ "canonicalPath",
+ "canonicalFilePath",
+ "completeBaseName",
+ "completeSuffix",
+ "fileName",
+ "filePath",
+ "path",
+ "suffix"
+ };
+ static QSet<QString> map;
+ if (map.isEmpty())
+ for (unsigned i = 0; i < sizeof(vars)/sizeof(vars[0]); i++)
+ map.insert(QLatin1String("CURRENT_DOCUMENT:") + QLatin1String(vars[i]));
+
+ QString str = var.toString();
+ int pos = 0;
+ forever {
+ int openPos = str.indexOf(QLatin1String("${"), pos);
+ if (openPos < 0)
+ break;
+ int varPos = openPos + 2;
+ int closePos = str.indexOf(QLatin1Char('}'), varPos);
+ if (closePos < 0)
+ break;
+ if (map.contains(str.mid(varPos, closePos - varPos)))
+ str[openPos] = QLatin1Char('%');
+ pos = closePos + 1;
+ }
+ return QVariant(str);
+}
+
+QVariantMap Version8Handler::update(Project *, const QVariantMap &map)
+{
+ const char * const *p1 = argListKeys;
+ QVariantMap rmap1 = processHandlerNodes(buildHandlerNodes(&p1), map, version8ArgNodeHandler);
+ const char * const *p2 = lameArgListKeys;
+ QVariantMap rmap2 = processHandlerNodes(buildHandlerNodes(&p2), rmap1, version8LameArgNodeHandler);
+ const char * const *p3 = envExpandedKeys;
+ QVariantMap rmap3 = processHandlerNodes(buildHandlerNodes(&p3), rmap2, version8EnvNodeHandler);
+ const char * const *p4 = varExpandedKeys;
+ return processHandlerNodes(buildHandlerNodes(&p4), rmap3, version8VarNodeHandler);
+}
diff --git a/src/plugins/projectexplorer/vcsannotatetaskhandler.h b/src/plugins/projectexplorer/vcsannotatetaskhandler.h
index a72d10b451..1d175ce0c2 100644
--- a/src/plugins/projectexplorer/vcsannotatetaskhandler.h
+++ b/src/plugins/projectexplorer/vcsannotatetaskhandler.h
@@ -34,8 +34,6 @@
#ifndef PROJECTEXPLORER_VCSANNOTATETASKHANDLER_H
#define PROJECTEXPLORER_VCSANNOTATETASKHANDLER_H
-#include "projectexplorer_export.h"
-
#include "itaskhandler.h"
namespace Core {
@@ -45,7 +43,7 @@ class IVersionControl;
namespace ProjectExplorer {
namespace Internal {
-class PROJECTEXPLORER_EXPORT VcsAnnotateTaskHandler : public ITaskHandler
+class VcsAnnotateTaskHandler : public ITaskHandler
{
Q_OBJECT
diff --git a/src/plugins/projectexplorer/winguiprocess.cpp b/src/plugins/projectexplorer/winguiprocess.cpp
index 5f59a60ca1..15f961a242 100644
--- a/src/plugins/projectexplorer/winguiprocess.cpp
+++ b/src/plugins/projectexplorer/winguiprocess.cpp
@@ -34,6 +34,8 @@
#include "winguiprocess.h"
#include "consoleprocess.h"
+#include <utils/qtcprocess.h>
+
#include <QtCore/QDir>
using namespace ProjectExplorer::Internal;
@@ -50,7 +52,7 @@ WinGuiProcess::~WinGuiProcess()
stop();
}
-bool WinGuiProcess::start(const QString &program, const QStringList &args)
+bool WinGuiProcess::start(const QString &program, const QString &args)
{
m_program = program;
m_args = args;
@@ -116,11 +118,14 @@ void WinGuiProcess::run()
const bool dbgInterface = setupDebugInterface(bufferReadyEvent, dataReadyEvent, sharedFile, sharedMem);
- const QString cmdLine = createWinCommandline(m_program, m_args);
+ QString pcmd, pargs;
+ QtcProcess::prepareCommand(m_program, m_args, &pcmd, &pargs, &m_environment, &m_workingDir);
+ const QString cmdLine = createWinCommandline(pcmd, pargs);
+ const QStringList env = m_environment.toStringList();
started = CreateProcessW(0, (WCHAR*)cmdLine.utf16(),
0, 0, TRUE, CREATE_UNICODE_ENVIRONMENT,
- environment().isEmpty() ? 0
- : createWinEnvironment(fixWinEnvironment(environment())).data(),
+ env.isEmpty() ? 0
+ : createWinEnvironment(fixWinEnvironment(env)).data(),
workingDirectory().isEmpty() ? 0
: (WCHAR*)QDir::convertSeparators(workingDirectory()).utf16(),
&si, m_pid);
diff --git a/src/plugins/projectexplorer/winguiprocess.h b/src/plugins/projectexplorer/winguiprocess.h
index e0a4213aa3..ef6f226d64 100644
--- a/src/plugins/projectexplorer/winguiprocess.h
+++ b/src/plugins/projectexplorer/winguiprocess.h
@@ -57,7 +57,7 @@ public:
explicit WinGuiProcess(QObject *parent = 0);
virtual ~WinGuiProcess();
- bool start(const QString &program, const QStringList &args);
+ bool start(const QString &program, const QString &args);
void stop();
bool isRunning() const;
@@ -75,7 +75,7 @@ private:
PROCESS_INFORMATION *m_pid;
QString m_program;
- QStringList m_args;
+ QString m_args;
unsigned long m_exitCode;
};
diff --git a/src/plugins/qmldesigner/QmlDesigner.pluginspec b/src/plugins/qmldesigner/QmlDesigner.pluginspec
deleted file mode 100644
index 2924831e76..0000000000
--- a/src/plugins/qmldesigner/QmlDesigner.pluginspec
+++ /dev/null
@@ -1,27 +0,0 @@
-<plugin name="QmlDesigner" version="2.0.95" compatVersion="2.0.95">
- <vendor>Nokia Corporation</vendor>
- <copyright>(C) 2010 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>
- <category>Qt Quick</category>
- <description>Visual Designer for QML files.</description>
- <url>http://qt.nokia.com</url>
- <dependencyList>
- <dependency name="Core" version="2.0.95"/>
- <dependency name="TextEditor" version="2.0.95"/>
- <dependency name="QmlJSEditor" version="2.0.95"/>
- </dependencyList>
-</plugin>
diff --git a/src/plugins/qmldesigner/QmlDesigner.pluginspec.in b/src/plugins/qmldesigner/QmlDesigner.pluginspec.in
new file mode 100644
index 0000000000..1f6c9bfde0
--- /dev/null
+++ b/src/plugins/qmldesigner/QmlDesigner.pluginspec.in
@@ -0,0 +1,27 @@
+<plugin name=\"QmlDesigner\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2010 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>
+ <category>Qt Quick</category>
+ <description>Visual Designer for QML files.</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"TextEditor\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"QmlJSEditor\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/qmldesigner/components/formeditor/abstractformeditortool.h b/src/plugins/qmldesigner/components/formeditor/abstractformeditortool.h
index 9530379fdd..8b5133c35f 100644
--- a/src/plugins/qmldesigner/components/formeditor/abstractformeditortool.h
+++ b/src/plugins/qmldesigner/components/formeditor/abstractformeditortool.h
@@ -81,6 +81,8 @@ public:
virtual void formEditorItemsChanged(const QList<FormEditorItem*> &itemList) = 0;
+ virtual void instancesCompleted(const QList<FormEditorItem*> &itemList) = 0;
+
void setItems(const QList<FormEditorItem*> &itemList);
QList<FormEditorItem*> items() const;
diff --git a/src/plugins/qmldesigner/components/formeditor/anchortool.cpp b/src/plugins/qmldesigner/components/formeditor/anchortool.cpp
index 81a0f976af..ae981e8bd6 100644
--- a/src/plugins/qmldesigner/components/formeditor/anchortool.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/anchortool.cpp
@@ -217,6 +217,10 @@ void AnchorTool::formEditorItemsChanged(const QList<FormEditorItem*> &)
m_anchorIndicator.updateItems(view()->scene()->allFormEditorItems());
}
+void AnchorTool::instancesCompleted(const QList<FormEditorItem*> &/*itemList*/)
+{
+}
+
AnchorLineHandleItem* AnchorTool::topAnchorLineHandleItem(const QList<QGraphicsItem*> & itemList)
{
foreach (QGraphicsItem *item, itemList) {
diff --git a/src/plugins/qmldesigner/components/formeditor/anchortool.h b/src/plugins/qmldesigner/components/formeditor/anchortool.h
index 78ca3a84da..c9d8d31861 100644
--- a/src/plugins/qmldesigner/components/formeditor/anchortool.h
+++ b/src/plugins/qmldesigner/components/formeditor/anchortool.h
@@ -74,6 +74,8 @@ public:
void formEditorItemsChanged(const QList<FormEditorItem*> &itemList);
+ void instancesCompleted(const QList<FormEditorItem*> &itemList);
+
static AnchorLineHandleItem* topAnchorLineHandleItem(const QList<QGraphicsItem*> & itemList);
private slots:
diff --git a/src/plugins/qmldesigner/components/formeditor/dragtool.cpp b/src/plugins/qmldesigner/components/formeditor/dragtool.cpp
index ba87f52b73..d5f7f673b6 100644
--- a/src/plugins/qmldesigner/components/formeditor/dragtool.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/dragtool.cpp
@@ -35,7 +35,6 @@
#include "formeditorscene.h"
#include "formeditorview.h"
-#include "modelutilities.h"
#include "itemutilfunctions.h"
#include <customdraganddrop.h>
#include <metainfo.h>
@@ -47,13 +46,24 @@
#include <QGraphicsSceneMouseEvent>
#include <QtDebug>
#include <QMessageBox>
+#include <QTimer>
namespace QmlDesigner {
+namespace Internal {
+void TimerHandler::clearMoveDelay()
+{
+ m_dragTool->clearMoveDelay();
+}
+
+}
+
DragTool::DragTool(FormEditorView *editorView)
: AbstractFormEditorTool(editorView),
m_moveManipulator(editorView->scene()->manipulatorLayerItem(), editorView),
- m_selectionIndicator(editorView->scene()->manipulatorLayerItem())
+ m_selectionIndicator(editorView->scene()->manipulatorLayerItem()),
+ m_timerHandler(new Internal::TimerHandler(this)),
+ m_blockMove(false)
{
// view()->setCursor(Qt::SizeAllCursor);
}
@@ -151,8 +161,7 @@ void DragTool::createQmlItemNode(const ItemLibraryEntry &itemLibraryEntry, QmlIt
Q_ASSERT(m_dragNode.modelNode().isValid());
QList<QmlItemNode> nodeList;
- nodeList.append(m_dragNode);
- view()->setSelectedQmlItemNodes(nodeList);
+ nodeList.append(m_dragNode);
m_selectionIndicator.setItems(scene()->itemsForQmlItemNodes(nodeList));
QmlDesignerItemLibraryDragAndDrop::CustomDragAndDrop::hide();
@@ -172,7 +181,6 @@ void DragTool::createQmlItemNodeFromImage(const QString &imageName, QmlItemNode
QList<QmlItemNode> nodeList;
nodeList.append(m_dragNode);
- view()->setSelectedQmlItemNodes(nodeList);
m_selectionIndicator.setItems(scene()->itemsForQmlItemNodes(nodeList));
QmlDesignerItemLibraryDragAndDrop::CustomDragAndDrop::hide();
@@ -202,6 +210,21 @@ void DragTool::formEditorItemsChanged(const QList<FormEditorItem*> & itemList)
}
}
+void DragTool::instancesCompleted(const QList<FormEditorItem*> &itemList)
+{
+ foreach (FormEditorItem* item, itemList)
+ if (item->qmlItemNode() == m_dragNode)
+ clearMoveDelay();
+}
+
+void DragTool::clearMoveDelay()
+{
+ if (!m_blockMove)
+ return;
+ m_blockMove = false;
+ if (m_dragNode.isValid())
+ beginWithPoint(m_startPoint);
+}
void DragTool::dropEvent(QGraphicsSceneDragDropEvent * event)
{
@@ -215,15 +238,46 @@ void DragTool::dropEvent(QGraphicsSceneDragDropEvent * event)
} catch (RewritingException &e) {
QMessageBox::warning(0, "Error", e.description());
}
+ if (m_dragNode.isValid()) {
+ QList<QmlItemNode> nodeList;
+ nodeList.append(m_dragNode);
+ view()->setSelectedQmlItemNodes(nodeList);
+ }
m_dragNode = ModelNode();
view()->changeToSelectionTool();
}
}
+static ItemLibraryEntry itemLibraryEntryFromData(const QByteArray &data)
+{
+ QDataStream stream(data);
+
+ ItemLibraryEntry itemLibraryEntry;
+ stream >> itemLibraryEntry;
+
+ return itemLibraryEntry;
+}
+
void DragTool::dragEnterEvent(QGraphicsSceneDragDropEvent * event)
{
if (event->mimeData()->hasFormat("application/vnd.bauhaus.itemlibraryinfo") ||
event->mimeData()->hasFormat("application/vnd.bauhaus.libraryresource")) {
+ m_blockMove = false;
+ if (event->mimeData()->hasFormat("application/vnd.bauhaus.itemlibraryinfo")) {
+ Q_ASSERT(!event->mimeData()->data("application/vnd.bauhaus.itemlibraryinfo").isEmpty());
+ ItemLibraryEntry itemLibraryEntry = itemLibraryEntryFromData(event->mimeData()->data("application/vnd.bauhaus.itemlibraryinfo"));
+ if (!itemLibraryEntry.requiredImport().isEmpty()) {
+ const QString newImportUrl = itemLibraryEntry.requiredImport();
+ const QString newImportVersion = QString("%1.%2").arg(QString::number(itemLibraryEntry.majorVersion()), QString::number(itemLibraryEntry.minorVersion()));
+ Import newImport = Import::createLibraryImport(newImportUrl, newImportVersion);
+
+ if (!view()->model()->imports().contains(newImport)) {
+ view()->model()->addImport(newImport);
+ }
+
+ }
+ }
+
if (!m_rewriterTransaction.isValid()) {
view()->clearSelectedModelNodes();
m_rewriterTransaction = view()->beginRewriterTransaction();
@@ -253,18 +307,10 @@ void DragTool::dragLeaveEvent(QGraphicsSceneDragDropEvent * event)
}
}
-static ItemLibraryEntry itemLibraryEntryFromData(const QByteArray &data)
-{
- QDataStream stream(data);
-
- ItemLibraryEntry itemLibraryEntry;
- stream >> itemLibraryEntry;
-
- return itemLibraryEntry;
-}
-
void DragTool::dragMoveEvent(QGraphicsSceneDragDropEvent * event)
{
+ if (m_blockMove)
+ return;
if (event->mimeData()->hasFormat("application/vnd.bauhaus.itemlibraryinfo") ||
event->mimeData()->hasFormat("application/vnd.bauhaus.libraryresource")) {
event->accept();
@@ -288,7 +334,7 @@ void DragTool::dragMoveEvent(QGraphicsSceneDragDropEvent * event)
FormEditorItem *parentItem = calculateContainer(event->scenePos());
if (!parentItem)
return;
- QmlItemNode parentNode; //get possible container parentNode
+ QmlItemNode parentNode;
if (parentItem)
parentNode = parentItem->qmlItemNode();
@@ -301,8 +347,9 @@ void DragTool::dragMoveEvent(QGraphicsSceneDragDropEvent * event)
QString imageName = QString::fromLatin1((event->mimeData()->data("application/vnd.bauhaus.libraryresource")));
createQmlItemNodeFromImage(imageName, parentNode, event->scenePos());
} else Q_ASSERT(false);
- if (m_dragNode.isValid())
- beginWithPoint(event->scenePos());
+ m_blockMove = true;
+ m_startPoint = event->scenePos();
+ QTimer::singleShot(1000, m_timerHandler.data(), SLOT(clearMoveDelay()));
}
}
if (event->mimeData()->hasFormat("application/vnd.bauhaus.libraryresource")) {
diff --git a/src/plugins/qmldesigner/components/formeditor/dragtool.h b/src/plugins/qmldesigner/components/formeditor/dragtool.h
index da45baaa76..08c7b2359f 100644
--- a/src/plugins/qmldesigner/components/formeditor/dragtool.h
+++ b/src/plugins/qmldesigner/components/formeditor/dragtool.h
@@ -40,16 +40,35 @@
#include "resizeindicator.h"
#include <QHash>
+#include <QObject>
+#include <QScopedPointer>
namespace QmlDesigner {
+class DragTool;
+
+namespace Internal {
+
+class TimerHandler : public QObject
+{
+ Q_OBJECT
+
+public:
+ TimerHandler(DragTool *tool) : QObject(), m_dragTool(tool) {}
+public slots:
+ void clearMoveDelay();
+
+private:
+ DragTool *m_dragTool;
+};
+}
class DragTool : public AbstractFormEditorTool
{
public:
DragTool(FormEditorView* editorView);
- ~DragTool();
+ virtual ~DragTool();
void mousePressEvent(const QList<QGraphicsItem*> &itemList,
QGraphicsSceneMouseEvent *event);
@@ -85,6 +104,10 @@ public:
void formEditorItemsChanged(const QList<FormEditorItem*> &itemList);
+ void instancesCompleted(const QList<FormEditorItem*> &itemList);
+
+ void clearMoveDelay();
+
protected:
@@ -103,7 +126,11 @@ private:
QWeakPointer<FormEditorItem> m_movingItem;
RewriterTransaction m_rewriterTransaction;
QmlItemNode m_dragNode;
+ QScopedPointer<Internal::TimerHandler> m_timerHandler;
+ bool m_blockMove;
+ QPointF m_startPoint;
};
+
}
#endif // DRAGTOOL_H
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp b/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp
index b797c2f4b0..a6e357349d 100644
--- a/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp
@@ -38,7 +38,8 @@
#include <modelnode.h>
#include <nodemetainfo.h>
-#include <widgetqueryview.h>
+#include <qmlanchors.h>
+
#include <QGraphicsSceneMouseEvent>
#include <QDebug>
@@ -76,10 +77,7 @@ void FormEditorItem::setup()
{
if (qmlItemNode().hasInstanceParent()) {
setParentItem(scene()->itemForQmlItemNode(qmlItemNode().instanceParent().toQmlItemNode()));
- setVisible(true);
setOpacity(qmlItemNode().instanceValue("opacity").toDouble());
- } else if (!qmlItemNode().isRootNode()){
- setVisible(false);
}
setFlag(QGraphicsItem::ItemClipsChildrenToShape, qmlItemNode().instanceValue("clip").toBool());
@@ -274,13 +272,10 @@ void FormEditorItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *,
return;
painter->save();
- painter->setRenderHint(QPainter::Antialiasing, true);
if (isContentVisible())
qmlItemNode().paintInstance(painter);
- painter->setRenderHint(QPainter::Antialiasing, false);
-
if (!qmlItemNode().isRootModelNode())
paintBoundingRect(painter);
@@ -365,7 +360,7 @@ QList<FormEditorItem*> FormEditorItem::childFormEditorItems() const
bool FormEditorItem::isContainer() const
{
- return qmlItemNode().modelNode().metaInfo().isContainer();
+ return true;
}
QmlItemNode FormEditorItem::qmlItemNode() const
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp
index 27d663c7d3..3e78e8b65b 100644
--- a/src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp
@@ -148,7 +148,6 @@ void FormEditorScene::synchronizeTransformation(const QmlItemNode &qmlItemNode)
{
FormEditorItem *item = itemForQmlItemNode(qmlItemNode);
item->updateGeometry();
- item->update();
if (qmlItemNode.isRootNode()) {
QRectF sceneRect(qmlItemNode.instanceBoundingRect());
@@ -179,8 +178,6 @@ void FormEditorScene::synchronizeOtherProperty(const QmlItemNode &qmlItemNode, c
if (propertyName == "visible")
item->setContentVisible(qmlItemNode.instanceValue("visible").toBool());
- if (item)
- item->update();
}
}
@@ -346,16 +343,8 @@ void FormEditorScene::reparentItem(const QmlItemNode &node, const QmlItemNode &n
if (newParent.isValid() && hasItemForQmlItemNode(newParent))
parentItem = itemForQmlItemNode(newParent);
- if (item->parentItem() != parentItem) {
- item->setParentItem(parentItem);
- if (parentItem) {
- item->setVisible(true);
- } else {
- item->setVisible(false);
- }
-
- item->update();
- }
+ item->setParentItem(0);
+ item->setParentItem(parentItem);
}
FormEditorItem* FormEditorScene::rootFormEditorItem() const
@@ -384,7 +373,6 @@ void FormEditorScene::clearFormEditorItems()
foreach (QGraphicsItem *item, itemList) {
if (qgraphicsitem_cast<FormEditorItem* >(item)) {
item->setParentItem(0);
- item->setVisible(false);
}
}
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp
index a886c89263..6009e5b0e8 100644
--- a/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp
@@ -44,7 +44,6 @@
#include "formeditorscene.h"
#include <rewritertransaction.h>
#include <modelnode.h>
-#include <modelutilities.h>
#include <itemlibraryinfo.h>
#include <metainfo.h>
#include <model.h>
@@ -54,6 +53,7 @@
#include <QString>
#include <QDir>
#include <QAction>
+#include <QTimer>
#include <zoomaction.h>
#include <nodeabstractproperty.h>
#include <nodelistproperty.h>
@@ -148,6 +148,16 @@ void FormEditorView::modelAboutToBeDetached(Model *model)
QmlModelView::modelAboutToBeDetached(model);
}
+void FormEditorView::importAdded(const Import &)
+{
+ reset();
+}
+
+void FormEditorView::importRemoved(const Import &)
+{
+ reset();
+}
+
void FormEditorView::nodeAboutToBeRemoved(const ModelNode &removedNode)
{
QmlItemNode qmlItemNode(removedNode);
@@ -440,6 +450,20 @@ void FormEditorView::auxiliaryDataChanged(const ModelNode &node, const QString &
}
}
+void FormEditorView::instancesCompleted(const QVector<ModelNode> &completedNodeList)
+{
+ QList<FormEditorItem*> itemNodeList;
+ foreach (const ModelNode &node, completedNodeList) {
+ QmlItemNode qmlItemNode(node);
+ if (qmlItemNode.isValid() && scene()->hasItemForQmlItemNode(qmlItemNode)) {
+ scene()->synchronizeParent(qmlItemNode);
+ itemNodeList.append(scene()->itemForQmlItemNode(qmlItemNode));
+ }
+ }
+ currentTool()->instancesCompleted(itemNodeList);
+}
+
+
void FormEditorView::customNotification(const AbstractView *view, const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> &data)
{
if (identifier == "__start rewriter transaction__") {
@@ -455,6 +479,46 @@ void FormEditorView::customNotification(const AbstractView *view, const QString
m_formEditorWidget->setFeedbackNode(QmlItemNode());
}
+ if (identifier == "__instance information changed__") {
+ QList<FormEditorItem*> itemNodeList;
+
+ foreach (const ModelNode &node, nodeList) {
+ QmlItemNode qmlItemNode(node);
+ if (qmlItemNode.isValid() && scene()->hasItemForQmlItemNode(qmlItemNode)) {
+ scene()->synchronizeTransformation(qmlItemNode);
+ itemNodeList.append(scene()->itemForQmlItemNode(qmlItemNode));
+ }
+ }
+
+ m_currentTool->formEditorItemsChanged(itemNodeList);
+
+ }
+
+ if (identifier == "__instance render pixmap changed__") {
+ QList<FormEditorItem*> itemNodeList;
+
+ foreach (const ModelNode &node, nodeList) {
+ QmlItemNode qmlItemNode(node);
+ if (qmlItemNode.isValid() && scene()->hasItemForQmlItemNode(qmlItemNode)) {
+ scene()->itemForQmlItemNode(qmlItemNode)->update();
+ }
+ }
+ }
+
+ if (identifier == "__instance children changed__") {
+ QList<FormEditorItem*> itemNodeList;
+
+ foreach (const ModelNode &node, nodeList) {
+ QmlItemNode qmlItemNode(node);
+ if (qmlItemNode.isValid() && scene()->hasItemForQmlItemNode(qmlItemNode)) {
+ scene()->synchronizeParent(qmlItemNode);
+ itemNodeList.append(scene()->itemForQmlItemNode(qmlItemNode));
+ }
+ }
+
+ m_currentTool->formEditorItemsChanged(itemNodeList);
+ }
+
QmlModelView::customNotification(view, identifier, nodeList, data);
}
@@ -513,26 +577,6 @@ QmlItemNode findRecursiveQmlItemNode(const QmlObjectNode &firstQmlObjectNode)
return QmlItemNode();
}
-void FormEditorView::transformChanged(const QmlObjectNode &qmlObjectNode, const QString &/*propertyName*/)
-{
- QmlItemNode itemNode = qmlObjectNode.toQmlItemNode();
- if (itemNode.isValid() && scene()->hasItemForQmlItemNode(itemNode)) {
- m_scene->synchronizeTransformation(itemNode);
- m_currentTool->formEditorItemsChanged(QList<FormEditorItem*>() << m_scene->itemForQmlItemNode(itemNode));
- }
-
- scene()->update();
-}
-
-void FormEditorView::parentChanged(const QmlObjectNode &qmlObjectNode)
-{
- QmlItemNode itemNode = qmlObjectNode.toQmlItemNode();
- if (itemNode.isValid() && scene()->hasItemForQmlItemNode(itemNode)) {
- scene()->synchronizeParent(itemNode);
- m_currentTool->formEditorItemsChanged(QList<FormEditorItem*>() << m_scene->itemForQmlItemNode(itemNode));
- }
-}
-
void FormEditorView::otherPropertyChanged(const QmlObjectNode &qmlObjectNode, const QString &propertyName)
{
Q_ASSERT(qmlObjectNode.isValid());
@@ -560,7 +604,6 @@ void FormEditorView::stateChanged(const QmlModelState &newQmlModelState, const Q
{
QmlModelView::stateChanged(newQmlModelState, oldQmlModelState);
-
m_formEditorWidget->anchorToolAction()->setEnabled(newQmlModelState.isBaseState());
if (!newQmlModelState.isBaseState() && currentTool() == m_anchorTool) {
@@ -573,6 +616,23 @@ void FormEditorView::stateChanged(const QmlModelState &newQmlModelState, const Q
// m_currentTool->formEditorItemsChanged(itemList);
}
+void FormEditorView::reset()
+{
+ QTimer::singleShot(200, this, SLOT(delayedReset()));
+}
+
+void FormEditorView::delayedReset()
+{
+ m_selectionTool->clear();
+ m_moveTool->clear();
+ m_resizeTool->clear();
+ m_anchorTool->clear();
+ m_dragTool->clear();
+ m_scene->clearFormEditorItems();
+ if (rootQmlObjectNode().toQmlItemNode().isValid())
+ setupFormEditorItemTree(rootQmlObjectNode().toQmlItemNode());
+}
+
}
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorview.h b/src/plugins/qmldesigner/components/formeditor/formeditorview.h
index ae0923371c..0dc7d41ad6 100644
--- a/src/plugins/qmldesigner/components/formeditor/formeditorview.h
+++ b/src/plugins/qmldesigner/components/formeditor/formeditorview.h
@@ -70,6 +70,9 @@ public:
void modelAttached(Model *model);
void modelAboutToBeDetached(Model *model);
+ void importAdded(const Import &import);
+ void importRemoved(const Import &import);
+
void nodeCreated(const ModelNode &createdNode);
void nodeAboutToBeRemoved(const ModelNode &removedNode);
void nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange);
@@ -105,6 +108,8 @@ public:
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);
+ void instancesCompleted(const QVector<ModelNode> &completedNodeList);
+
double margins() const;
double spacing() const;
void deActivateItemCreator();
@@ -116,12 +121,12 @@ signals:
void ItemCreatorDeActivated();
protected:
- void transformChanged(const QmlObjectNode &qmlObjectNode, const QString &propertyName);
- void parentChanged(const QmlObjectNode &qmlObjectNode);
void otherPropertyChanged(const QmlObjectNode &qmlObjectNode, const QString &propertyName);
void stateChanged(const QmlModelState &newQmlModelState, const QmlModelState &oldQmlModelState);
+ void reset();
protected slots:
+ void delayedReset();
QList<ModelNode> adjustStatesForModelNodes(const QList<ModelNode> &nodeList) const;
void updateGraphicsIndicators();
void setSelectOnlyContentItemsAction(bool selectOnlyContentItems);
diff --git a/src/plugins/qmldesigner/components/formeditor/itemcreatortool.cpp b/src/plugins/qmldesigner/components/formeditor/itemcreatortool.cpp
index c4f9c4ec62..a5f24ebbe9 100644
--- a/src/plugins/qmldesigner/components/formeditor/itemcreatortool.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/itemcreatortool.cpp
@@ -36,7 +36,7 @@
#include "formeditorview.h"
#include <metainfo.h>
-#include <itemlibrary.h>
+#include <itemlibrarywidget.h>
#include <QApplication>
#include <QGraphicsSceneMouseEvent>
@@ -143,6 +143,10 @@ void ItemCreatorTool::formEditorItemsChanged(const QList<FormEditorItem*> &/*ite
{
}
+void ItemCreatorTool::instancesCompleted(const QList<FormEditorItem*> &/*itemList*/)
+{
+}
+
void ItemCreatorTool::setItemString(const QString &itemString)
{
m_itemString = itemString;
@@ -178,7 +182,8 @@ void ItemCreatorTool::createAtItem(const QRectF &rect)
return;
if (list.first() == "item") {
RewriterTransaction transaction = view()->beginRewriterTransaction();
- ItemLibraryEntry itemLibraryEntry = view()->model()->metaInfo().itemLibraryInfo()->entry(list.at(1));
+ Q_ASSERT(false); //this code is out of date
+ ItemLibraryEntry itemLibraryEntry; //= view()->model()->metaInfo().itemLibraryInfo()->entry(list.at(1));
QmlItemNode newNode = view()->createQmlItemNode(itemLibraryEntry, pos, parentNode);
newNode.modelNode().variantProperty("width") = rect.width();
newNode.modelNode().variantProperty("height") = rect.height();
diff --git a/src/plugins/qmldesigner/components/formeditor/itemcreatortool.h b/src/plugins/qmldesigner/components/formeditor/itemcreatortool.h
index 4338853fa9..d45517d8c3 100644
--- a/src/plugins/qmldesigner/components/formeditor/itemcreatortool.h
+++ b/src/plugins/qmldesigner/components/formeditor/itemcreatortool.h
@@ -71,6 +71,8 @@ public:
void formEditorItemsChanged(const QList<FormEditorItem*> &itemList);
+ void instancesCompleted(const QList<FormEditorItem*> &itemList);
+
void setItemString(const QString &itemString);
FormEditorItem* calculateContainer(const QPointF &point);
diff --git a/src/plugins/qmldesigner/components/formeditor/itemutilfunctions.cpp b/src/plugins/qmldesigner/components/formeditor/itemutilfunctions.cpp
index 411eaed975..6a8941de82 100644
--- a/src/plugins/qmldesigner/components/formeditor/itemutilfunctions.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/itemutilfunctions.cpp
@@ -32,7 +32,6 @@
**************************************************************************/
#include "itemutilfunctions.h"
-#include <modelutilities.h>
#include <formeditorscene.h>
#include <QRectF>
diff --git a/src/plugins/qmldesigner/components/formeditor/movetool.cpp b/src/plugins/qmldesigner/components/formeditor/movetool.cpp
index 0440106538..ed47e49e49 100644
--- a/src/plugins/qmldesigner/components/formeditor/movetool.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/movetool.cpp
@@ -36,7 +36,6 @@
#include "formeditorscene.h"
#include "formeditorview.h"
#include "formeditorwidget.h"
-#include "modelutilities.h"
#include "itemutilfunctions.h"
#include "resizehandleitem.h"
@@ -238,6 +237,10 @@ void MoveTool::selectedItemsChanged(const QList<FormEditorItem*> &itemList)
updateMoveManipulator();
}
+void MoveTool::instancesCompleted(const QList<FormEditorItem*> & /*itemList*/)
+{
+}
+
bool MoveTool::haveSameParent(const QList<FormEditorItem*> &itemList)
{
if (itemList.isEmpty())
diff --git a/src/plugins/qmldesigner/components/formeditor/movetool.h b/src/plugins/qmldesigner/components/formeditor/movetool.h
index 83166b3679..93b5d57d77 100644
--- a/src/plugins/qmldesigner/components/formeditor/movetool.h
+++ b/src/plugins/qmldesigner/components/formeditor/movetool.h
@@ -68,9 +68,9 @@ public:
void selectedItemsChanged(const QList<FormEditorItem*> &itemList);
- void updateMoveManipulator();
-
+ void instancesCompleted(const QList<FormEditorItem*> &/*itemList*/);
+ void updateMoveManipulator();
void beginWithPoint(const QPointF &beginPoint);
diff --git a/src/plugins/qmldesigner/components/formeditor/resizetool.cpp b/src/plugins/qmldesigner/components/formeditor/resizetool.cpp
index 2e3b46387d..be0d97f9a6 100644
--- a/src/plugins/qmldesigner/components/formeditor/resizetool.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/resizetool.cpp
@@ -184,4 +184,8 @@ void ResizeTool::formEditorItemsChanged(const QList<FormEditorItem*> &itemList)
m_resizeIndicator.updateItems(itemList);
}
+ void ResizeTool::instancesCompleted(const QList<FormEditorItem*> &/*itemList*/)
+ {
+ }
+
}
diff --git a/src/plugins/qmldesigner/components/formeditor/resizetool.h b/src/plugins/qmldesigner/components/formeditor/resizetool.h
index b802c7d0c2..67affded71 100644
--- a/src/plugins/qmldesigner/components/formeditor/resizetool.h
+++ b/src/plugins/qmldesigner/components/formeditor/resizetool.h
@@ -69,6 +69,8 @@ public:
void formEditorItemsChanged(const QList<FormEditorItem*> &itemList);
+ void instancesCompleted(const QList<FormEditorItem*> &itemList);
+
private:
SelectionIndicator m_selectionIndicator;
ResizeIndicator m_resizeIndicator;
diff --git a/src/plugins/qmldesigner/components/formeditor/scaleitem.h b/src/plugins/qmldesigner/components/formeditor/scaleitem.h
index 88351675c9..5e72d50b80 100644
--- a/src/plugins/qmldesigner/components/formeditor/scaleitem.h
+++ b/src/plugins/qmldesigner/components/formeditor/scaleitem.h
@@ -52,6 +52,6 @@ private:
ScaleIndicator* m_indicator;
};
-};
+}
#endif // SCALEITEM_H
diff --git a/src/plugins/qmldesigner/components/formeditor/selectiontool.cpp b/src/plugins/qmldesigner/components/formeditor/selectiontool.cpp
index f95ab3c501..241bc697bf 100644
--- a/src/plugins/qmldesigner/components/formeditor/selectiontool.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/selectiontool.cpp
@@ -265,6 +265,10 @@ void SelectionTool::formEditorItemsChanged(const QList<FormEditorItem*> &itemLis
m_resizeIndicator.updateItems(itemList);
}
+void SelectionTool::instancesCompleted(const QList<FormEditorItem*> &/*itemList*/)
+{
+}
+
void SelectionTool::selectUnderPoint(QGraphicsSceneMouseEvent *event)
{
m_singleSelectionManipulator.begin(event->scenePos());
diff --git a/src/plugins/qmldesigner/components/formeditor/selectiontool.h b/src/plugins/qmldesigner/components/formeditor/selectiontool.h
index 35f193b415..5135c4052a 100644
--- a/src/plugins/qmldesigner/components/formeditor/selectiontool.h
+++ b/src/plugins/qmldesigner/components/formeditor/selectiontool.h
@@ -80,6 +80,8 @@ public:
void formEditorItemsChanged(const QList<FormEditorItem*> &itemList);
+ void instancesCompleted(const QList<FormEditorItem*> &itemList);
+
void selectUnderPoint(QGraphicsSceneMouseEvent *event);
void setSelectOnlyContentItems(bool selectOnlyContentItems);
diff --git a/src/plugins/qmldesigner/components/formeditor/zoomaction.cpp b/src/plugins/qmldesigner/components/formeditor/zoomaction.cpp
index 3a149c1290..6faec6d67e 100644
--- a/src/plugins/qmldesigner/components/formeditor/zoomaction.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/zoomaction.cpp
@@ -103,6 +103,7 @@ QWidget *ZoomAction::createWidget(QWidget *parent)
connect(comboBox, SIGNAL(currentIndexChanged(int)), SLOT(emitZoomLevelChanged(int)));
connect(this, SIGNAL(indexChanged(int)), comboBox, SLOT(setCurrentIndex(int)));
+ comboBox->setProperty("hideborder", true);
return comboBox;
}
diff --git a/src/plugins/qmldesigner/components/integration/componentview.cpp b/src/plugins/qmldesigner/components/integration/componentview.cpp
index f41fc1e70e..cc4531e3c0 100644
--- a/src/plugins/qmldesigner/components/integration/componentview.cpp
+++ b/src/plugins/qmldesigner/components/integration/componentview.cpp
@@ -155,7 +155,7 @@ void ComponentView::nodeRemoved(const ModelNode & /*removedNode*/, const NodeAbs
// }
// }
//}
-
+void ComponentView::nodeAboutToBeReparented(const ModelNode &/*node*/, const NodeAbstractProperty &/*newPropertyParent*/, const NodeAbstractProperty &/*oldPropertyParent*/, AbstractView::PropertyChangeFlags /*propertyChange*/) {}
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*/) {}
@@ -164,7 +164,8 @@ void ComponentView::variantPropertiesChanged(const QList<VariantProperty>& /*pro
void ComponentView::bindingPropertiesChanged(const QList<BindingProperty>& /*propertyList*/, PropertyChangeFlags /*propertyChange*/) {}
void ComponentView::rootNodeTypeChanged(const QString &/*type*/, int /*majorVersion*/, int /*minorVersion*/) {}
void ComponentView::scriptFunctionsChanged(const ModelNode &/*node*/, const QStringList &/*scriptFunctionList*/) {}
-void ComponentView::instancePropertyChange(const QList<QPair<ModelNode, QString> > &/*propertyList*/) {};
+void ComponentView::instancePropertyChange(const QList<QPair<ModelNode, QString> > &/*propertyList*/) {}
+void ComponentView::instancesCompleted(const QVector<ModelNode> &/*completedNodeList*/) {}
void ComponentView::selectedNodesChanged(const QList<ModelNode> &/*selectedNodeList*/,
@@ -174,7 +175,6 @@ void ComponentView::fileUrlChanged(const QUrl &/*oldUrl*/, const QUrl &/*newUrl*
void ComponentView::nodeOrderChanged(const NodeListProperty &/*listProperty*/, const ModelNode & /*movedNode*/, int /*oldIndex*/) {}
-void ComponentView::importsChanged() {}
void ComponentView::auxiliaryDataChanged(const ModelNode &/*node*/, const QString &/*name*/, const QVariant &/*data*/) {}
diff --git a/src/plugins/qmldesigner/components/integration/componentview.h b/src/plugins/qmldesigner/components/integration/componentview.h
index 3c89842c20..e73958d4e1 100644
--- a/src/plugins/qmldesigner/components/integration/componentview.h
+++ b/src/plugins/qmldesigner/components/integration/componentview.h
@@ -63,6 +63,7 @@ public:
void nodeCreated(const ModelNode &createdNode);
void nodeAboutToBeRemoved(const ModelNode &removedNode);
void nodeRemoved(const ModelNode &removedNode, const NodeAbstractProperty &parentProperty, PropertyChangeFlags propertyChange);
+ void nodeAboutToBeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::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);
@@ -72,6 +73,7 @@ public:
void rootNodeTypeChanged(const QString &type, int majorVersion, int minorVersion);
void scriptFunctionsChanged(const ModelNode &node, const QStringList &scriptFunctionList);
void instancePropertyChange(const QList<QPair<ModelNode, QString> > &propertyList);
+ void instancesCompleted(const QVector<ModelNode> &completedNodeList);
void selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
const QList<ModelNode> &lastSelectedNodeList);
@@ -80,8 +82,6 @@ public:
void nodeOrderChanged(const NodeListProperty &listProperty, const ModelNode &movedNode, 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);
diff --git a/src/plugins/qmldesigner/components/integration/designdocumentcontroller.cpp b/src/plugins/qmldesigner/components/integration/designdocumentcontroller.cpp
index 4a8068b9e6..67a887f2ed 100644
--- a/src/plugins/qmldesigner/components/integration/designdocumentcontroller.cpp
+++ b/src/plugins/qmldesigner/components/integration/designdocumentcontroller.cpp
@@ -39,9 +39,10 @@
#include "model/viewlogger.h"
#include <allpropertiesbox.h>
-#include <itemlibrary.h>
+#include <itemlibraryview.h>
+#include <itemlibrarywidget.h>
#include <navigatorview.h>
-#include <stateseditorwidget.h>
+#include <stateseditorview.h>
#include <formeditorview.h>
#include <formeditorwidget.h>
#include <basetexteditmodifier.h>
@@ -88,10 +89,10 @@ class DesignDocumentControllerPrivate {
public:
QWeakPointer<FormEditorView> formEditorView;
- QWeakPointer<ItemLibrary> itemLibrary;
+ QWeakPointer<ItemLibraryView> itemLibraryView;
QWeakPointer<NavigatorView> navigator;
QWeakPointer<AllPropertiesBox> allPropertiesBox;
- QWeakPointer<StatesEditorWidget> statesEditorWidget;
+ QWeakPointer<StatesEditorView> statesEditorView;
QWeakPointer<QStackedWidget> stackedWidget;
QWeakPointer<NodeInstanceView> nodeInstanceView;
@@ -194,9 +195,9 @@ QList<RewriterView::Error> DesignDocumentController::qmlErrors() const
return m_d->rewriterView->errors();
}
-void DesignDocumentController::setItemLibrary(ItemLibrary* itemLibrary)
+void DesignDocumentController::setItemLibraryView(ItemLibraryView* itemLibraryView)
{
- m_d->itemLibrary = itemLibrary;
+ m_d->itemLibraryView = itemLibraryView;
}
void DesignDocumentController::setNavigator(NavigatorView* navigatorView)
@@ -209,9 +210,9 @@ void DesignDocumentController::setAllPropertiesBox(AllPropertiesBox* allProperti
m_d->allPropertiesBox = allPropertiesBox;
}
-void DesignDocumentController::setStatesEditorWidget(StatesEditorWidget* statesEditorWidget)
+void DesignDocumentController::setStatesEditorView(StatesEditorView* statesEditorView)
{
- m_d->statesEditorWidget = statesEditorWidget;
+ m_d->statesEditorView = statesEditorView;
}
void DesignDocumentController::setFormEditorView(FormEditorView *formEditorView)
@@ -250,8 +251,8 @@ void DesignDocumentController::setFileName(const QString &fileName)
if (m_d->model)
m_d->model->setFileUrl(m_d->searchPath);
- if (m_d->itemLibrary)
- m_d->itemLibrary->setResourcePath(QFileInfo(fileName).absolutePath());
+ if (m_d->itemLibraryView)
+ m_d->itemLibraryView->widget()->setResourcePath(QFileInfo(fileName).absolutePath());
emit displayNameChanged(displayName());
}
@@ -358,8 +359,7 @@ void DesignDocumentController::loadCurrentModel()
m_d->model->attachView(m_d->nodeInstanceView.data());
m_d->model->attachView(m_d->navigator.data());
- m_d->itemLibrary->setItemLibraryInfo(m_d->model->metaInfo().itemLibraryInfo());
- m_d->itemLibrary->setResourcePath(QFileInfo(m_d->fileName).absolutePath());
+ m_d->itemLibraryView->widget()->setResourcePath(QFileInfo(m_d->fileName).absolutePath());
if (!m_d->componentAction) {
m_d->componentAction = new ComponentAction(m_d->formEditorView->widget());
@@ -370,16 +370,17 @@ void DesignDocumentController::loadCurrentModel()
// Disable switching between in file components for the time being
m_d->componentAction->setVisible(false);
- connect(m_d->itemLibrary.data(), SIGNAL(itemActivated(const QString&)), m_d->formEditorView.data(), SLOT(activateItemCreator(const QString&)));
+ connect(m_d->itemLibraryView->widget(), SIGNAL(itemActivated(const QString&)), m_d->formEditorView.data(), SLOT(activateItemCreator(const QString&)));
m_d->model->attachView(m_d->formEditorView.data());
+ m_d->model->attachView(m_d->itemLibraryView.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->model->attachView(m_d->statesEditorView.data());
m_d->allPropertiesBox->setModel(m_d->model.data());
@@ -629,7 +630,7 @@ void DesignDocumentController::paste()
int offset = double(qrand()) / RAND_MAX * 20 - 10;
foreach (const ModelNode &node, selectedNodes) {
- QString defaultProperty(targetNode.metaInfo().defaultProperty());
+ QString defaultProperty(targetNode.metaInfo().defaultPropertyName());
ModelNode pastedNode(view.insertModel(node));
pastedNodeList.append(pastedNode);
scatterItem(pastedNode, targetNode, offset);
@@ -662,7 +663,7 @@ void DesignDocumentController::paste()
targetNode = targetNode.parentProperty().parentModelNode();
- QString defaultProperty(targetNode.metaInfo().defaultProperty());
+ QString defaultProperty(targetNode.metaInfo().defaultPropertyName());
scatterItem(pastedNode, targetNode);
if (targetNode.nodeListProperty(defaultProperty).isValid()) {
diff --git a/src/plugins/qmldesigner/components/integration/designdocumentcontroller.h b/src/plugins/qmldesigner/components/integration/designdocumentcontroller.h
index a9703cc213..392a29e1b1 100644
--- a/src/plugins/qmldesigner/components/integration/designdocumentcontroller.h
+++ b/src/plugins/qmldesigner/components/integration/designdocumentcontroller.h
@@ -55,10 +55,10 @@ class ModelNode;
class TextModifier;
class QmlObjectNode;
class RewriterView;
-class ItemLibrary;
+class ItemLibraryView;
class NavigatorView;
class AllPropertiesBox;
-class StatesEditorWidget;
+class StatesEditorView;
class FormEditorView;
class DesignDocumentController: public QObject
@@ -93,10 +93,10 @@ public:
QString contextHelpId() const;
QList<RewriterView::Error> qmlErrors() const;
- void setItemLibrary(ItemLibrary* itemLibrary);
+ void setItemLibraryView(ItemLibraryView* itemLibraryView);
void setNavigator(NavigatorView* navigatorView);
void setAllPropertiesBox(AllPropertiesBox* allPropertiesBox);
- void setStatesEditorWidget(StatesEditorWidget* statesEditorWidget);
+ void setStatesEditorView(StatesEditorView* statesEditorView);
void setFormEditorView(FormEditorView *formEditorView);
void setNodeInstanceView(NodeInstanceView *nodeInstanceView);
diff --git a/src/plugins/qmldesigner/components/integration/designdocumentcontrollerview.cpp b/src/plugins/qmldesigner/components/integration/designdocumentcontrollerview.cpp
index 4f49b2a29d..eb3b70eeb3 100644
--- a/src/plugins/qmldesigner/components/integration/designdocumentcontrollerview.cpp
+++ b/src/plugins/qmldesigner/components/integration/designdocumentcontrollerview.cpp
@@ -44,21 +44,22 @@
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::rootNodeTypeChanged(const QString & /*type*/, int /*majorVersion*/, int /*minorVersion*/) {};
+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::nodeAboutToBeReparented(const ModelNode & /*node*/, const NodeAbstractProperty & /*newPropertyParent*/, const NodeAbstractProperty & /*oldPropertyParent*/, 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::rootNodeTypeChanged(const QString & /*type*/, int /*majorVersion*/, int /*minorVersion*/) {}
void DesignDocumentControllerView::selectedNodesChanged(const QList<ModelNode> & /*selectedNodeList*/,
- const QList<ModelNode> & /*lastSelectedNodeList*/) {};
+ const QList<ModelNode> & /*lastSelectedNodeList*/) {}
-void DesignDocumentControllerView::nodeOrderChanged(const NodeListProperty & /*listProperty*/, const ModelNode & /*movedNode*/, int /*oldIndex*/) {};
+void DesignDocumentControllerView::nodeOrderChanged(const NodeListProperty & /*listProperty*/, const ModelNode & /*movedNode*/, int /*oldIndex*/) {}
void DesignDocumentControllerView::scriptFunctionsChanged(const ModelNode &/*node*/, const QStringList &/*scriptFunctionList*/)
{
@@ -68,6 +69,11 @@ void DesignDocumentControllerView::instancePropertyChange(const QList<QPair<Mode
{
}
+void DesignDocumentControllerView::instancesCompleted(const QVector<ModelNode> &/*completedNodeList*/)
+{
+
+}
+
static QStringList arrayToStringList(const QByteArray &byteArray)
{
QString str(QString::fromLatin1(byteArray));
diff --git a/src/plugins/qmldesigner/components/integration/designdocumentcontrollerview.h b/src/plugins/qmldesigner/components/integration/designdocumentcontrollerview.h
index 6a2555f4f8..3e7766f035 100644
--- a/src/plugins/qmldesigner/components/integration/designdocumentcontrollerview.h
+++ b/src/plugins/qmldesigner/components/integration/designdocumentcontrollerview.h
@@ -49,6 +49,7 @@ public:
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 nodeAboutToBeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::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);
@@ -63,7 +64,7 @@ public:
virtual void nodeOrderChanged(const NodeListProperty &listProperty, const ModelNode &movedNode, int oldIndex);
virtual void scriptFunctionsChanged(const ModelNode &node, const QStringList &scriptFunctionList);
void instancePropertyChange(const QList<QPair<ModelNode, QString> > &propertyList);
-
+ void instancesCompleted(const QVector<ModelNode> &completedNodeList);
ModelNode insertModel(const ModelNode &modelNode)
{ return m_modelMerger.insertModel(modelNode); }
diff --git a/src/plugins/qmldesigner/components/integration/integrationcore.cpp b/src/plugins/qmldesigner/components/integration/integrationcore.cpp
index 5484d16cde..507e4b1233 100644
--- a/src/plugins/qmldesigner/components/integration/integrationcore.cpp
+++ b/src/plugins/qmldesigner/components/integration/integrationcore.cpp
@@ -33,7 +33,7 @@
#include "integrationcore.h"
#include "pluginmanager.h"
-#include "itemlibrary.h"
+#include "itemlibraryview.h"
#include "navigatorwidget.h"
#include "metainfo.h"
diff --git a/src/plugins/qmldesigner/components/integration/integrationcore.h b/src/plugins/qmldesigner/components/integration/integrationcore.h
index 9280298e35..05b4bf87a7 100644
--- a/src/plugins/qmldesigner/components/integration/integrationcore.h
+++ b/src/plugins/qmldesigner/components/integration/integrationcore.h
@@ -43,7 +43,7 @@ QT_END_NAMESPACE
namespace QmlDesigner {
-class ItemLibrary;
+class ItemLibraryWidget;
class FormWindowManager;
class PluginManager;
class CorePrivate;
diff --git a/src/plugins/qmldesigner/components/itemlibrary/images/item-default-icon.png b/src/plugins/qmldesigner/components/itemlibrary/images/item-default-icon.png
index 82c6ef1a41..5000ba2600 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/images/item-default-icon.png
+++ b/src/plugins/qmldesigner/components/itemlibrary/images/item-default-icon.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/itemlibrary/images/item-invalid-icon.png b/src/plugins/qmldesigner/components/itemlibrary/images/item-invalid-icon.png
new file mode 100644
index 0000000000..e87fd3a0b5
--- /dev/null
+++ b/src/plugins/qmldesigner/components/itemlibrary/images/item-invalid-icon.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrary.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrary.cpp
deleted file mode 100644
index d8250ff176..0000000000
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrary.cpp
+++ /dev/null
@@ -1,335 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#include "itemlibrary.h"
-
-#include <utils/filterlineedit.h>
-#include "itemlibrarywidgets.h"
-#include "itemlibrarymodel.h"
-#include "itemlibraryimageprovider.h"
-#include "customdraganddrop.h"
-
-#include <QFileInfo>
-#include <QFileIconProvider>
-#include <QDirModel>
-#include <QStackedWidget>
-#include <QGridLayout>
-#include <QTabBar>
-#include <QImageReader>
-#include <QMimeData>
-#include <QWheelEvent>
-
-#include <QDeclarativeView>
-#include <QDeclarativeItem>
-#include <private/qdeclarativeengine_p.h>
-
-
-namespace QmlDesigner {
-
-class MyFileIconProvider : public QFileIconProvider
-{
-public:
- MyFileIconProvider(const QSize &iconSize)
- : QFileIconProvider(),
- m_iconSize(iconSize)
- {}
-
- virtual QIcon icon ( const QFileInfo & info ) const
- {
- QPixmap pixmap(info.absoluteFilePath());
- if (pixmap.isNull()) {
- QIcon defaultIcon(QFileIconProvider::icon(info));
- pixmap = defaultIcon.pixmap(defaultIcon.actualSize(m_iconSize));
- }
-
- if (pixmap.width() == m_iconSize.width()
- && pixmap.height() == m_iconSize.height())
- return pixmap;
-
- if ((pixmap.width() > m_iconSize.width())
- || (pixmap.height() > m_iconSize.height()))
- return pixmap.scaled(m_iconSize, Qt::KeepAspectRatio,
- Qt::SmoothTransformation);
-
- QPoint offset((m_iconSize.width() - pixmap.width()) / 2,
- (m_iconSize.height() - pixmap.height()) / 2);
- QImage newIcon(m_iconSize, QImage::Format_ARGB32_Premultiplied);
- newIcon.fill(Qt::transparent);
- QPainter painter(&newIcon);
- painter.drawPixmap(offset, pixmap);
- return QPixmap::fromImage(newIcon);
- }
-
-private:
- QSize m_iconSize;
-};
-
-
-// ---------- ItemLibraryPrivate
-class ItemLibraryPrivate {
-public:
- ItemLibraryPrivate(QObject *object);
-
- Internal::ItemLibraryModel *m_itemLibraryModel;
- QDirModel *m_resourcesDirModel;
-
- QStackedWidget *m_stackedWidget;
- Utils::FilterLineEdit *m_lineEdit;
- QDeclarativeView *m_itemsView;
- Internal::ItemLibraryTreeView *m_resourcesView;
- QWeakPointer<ItemLibraryInfo> m_itemLibraryInfo;
-
- QSize m_itemIconSize, m_resIconSize;
- MyFileIconProvider m_iconProvider;
-};
-
-ItemLibraryPrivate::ItemLibraryPrivate(QObject *object) :
- m_itemLibraryModel(0),
- m_resourcesDirModel(0),
- m_stackedWidget(0),
- m_lineEdit(0),
- m_itemsView(0),
- m_resourcesView(0),
- m_itemIconSize(24, 24),
- m_resIconSize(24, 24),
- m_iconProvider(m_resIconSize)
-{
- Q_UNUSED(object);
-}
-
-ItemLibrary::ItemLibrary(QWidget *parent) :
- QFrame(parent),
- m_d(new ItemLibraryPrivate(this))
-{
- setWindowTitle(tr("Library", "Title of library view"));
-
- /* create Items view and its model */
- m_d->m_itemsView = new QDeclarativeView(this);
- m_d->m_itemsView->setAttribute(Qt::WA_OpaquePaintEvent);
- m_d->m_itemsView->setAttribute(Qt::WA_NoSystemBackground);
- m_d->m_itemsView->setAcceptDrops(false);
- m_d->m_itemsView->setFocusPolicy(Qt::ClickFocus);
- m_d->m_itemsView->setResizeMode(QDeclarativeView::SizeRootObjectToView);
- m_d->m_itemLibraryModel = new Internal::ItemLibraryModel(QDeclarativeEnginePrivate::getScriptEngine(m_d->m_itemsView->engine()), this);
- m_d->m_itemLibraryModel->setItemIconSize(m_d->m_itemIconSize);
-
- QDeclarativeContext *rootContext = m_d->m_itemsView->rootContext();
- rootContext->setContextProperty(QLatin1String("itemLibraryModel"), m_d->m_itemLibraryModel);
- rootContext->setContextProperty(QLatin1String("itemLibraryIconWidth"), m_d->m_itemIconSize.width());
- rootContext->setContextProperty(QLatin1String("itemLibraryIconHeight"), m_d->m_itemIconSize.height());
-
- QColor highlightColor = palette().highlight().color();
- if (0.5*highlightColor.saturationF()+0.75-highlightColor.valueF() < 0)
- highlightColor.setHsvF(highlightColor.hsvHueF(),0.1 + highlightColor.saturationF()*2.0, highlightColor.valueF());
- m_d->m_itemsView->rootContext()->setContextProperty(QLatin1String("highlightColor"), highlightColor);
-
- // loading the qml has to come after all needed context properties are set
- m_d->m_itemsView->setSource(QUrl("qrc:/ItemLibrary/qml/ItemsView.qml"));
-
- QDeclarativeItem *rootItem = qobject_cast<QDeclarativeItem*>(m_d->m_itemsView->rootObject());
- connect(rootItem, SIGNAL(itemSelected(int)), this, SLOT(showItemInfo(int)));
- connect(rootItem, SIGNAL(itemDragged(int)), this, SLOT(startDragAndDrop(int)));
- connect(this, SIGNAL(scrollItemsView(QVariant)), rootItem, SLOT(scrollView(QVariant)));
- connect(this, SIGNAL(resetItemsView()), rootItem, SLOT(resetView()));
-
- /* create Resources view and its model */
- m_d->m_resourcesDirModel = new QDirModel(this);
- m_d->m_resourcesDirModel->setIconProvider(&m_d->m_iconProvider);
- m_d->m_resourcesView = new Internal::ItemLibraryTreeView(this);
- m_d->m_resourcesView->setModel(m_d->m_resourcesDirModel);
- m_d->m_resourcesView->setIconSize(m_d->m_resIconSize);
-
- /* create image provider for loading item icons */
- m_d->m_itemsView->engine()->addImageProvider(QLatin1String("qmldesigner_itemlibrary"), new Internal::ItemLibraryImageProvider);
-
- /* other widgets */
- QTabBar *tabBar = new QTabBar(this);
- tabBar->addTab(tr("Items", "Title of library items view"));
- tabBar->addTab(tr("Resources", "Title of library resources view"));
- tabBar->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
-
- m_d->m_lineEdit = new Utils::FilterLineEdit(this);
- m_d->m_lineEdit->setObjectName(QLatin1String("itemLibrarySearchInput"));
- m_d->m_lineEdit->setPlaceholderText(tr("<Filter>", "Library search input hint text"));
- m_d->m_lineEdit->setDragEnabled(false);
- m_d->m_lineEdit->setMinimumWidth(75);
- m_d->m_lineEdit->setTextMargins(0, 0, 20, 0);
- QWidget *lineEditFrame = new QWidget(this);
- lineEditFrame->setObjectName(QLatin1String("itemLibrarySearchInputFrame"));
- QGridLayout *lineEditLayout = new QGridLayout(lineEditFrame);
- lineEditLayout->setMargin(2);
- lineEditLayout->setSpacing(0);
- lineEditLayout->addItem(new QSpacerItem(5, 3, QSizePolicy::Fixed, QSizePolicy::Fixed), 0, 0, 1, 3);
- lineEditLayout->addItem(new QSpacerItem(5, 5, QSizePolicy::Fixed, QSizePolicy::Fixed), 1, 0);
- lineEditLayout->addWidget(m_d->m_lineEdit, 1, 1, 1, 1);
- lineEditLayout->addItem(new QSpacerItem(5, 5, QSizePolicy::Fixed, QSizePolicy::Fixed), 1, 2);
- connect(m_d->m_lineEdit, SIGNAL(filterChanged(QString)), this, SLOT(setSearchFilter(QString)));
-
- m_d->m_stackedWidget = new QStackedWidget(this);
- m_d->m_stackedWidget->addWidget(m_d->m_itemsView);
- m_d->m_stackedWidget->addWidget(m_d->m_resourcesView);
- connect(tabBar, SIGNAL(currentChanged(int)),
- m_d->m_stackedWidget, SLOT(setCurrentIndex(int)));
- connect(tabBar, SIGNAL(currentChanged(int)),
- this, SLOT(updateSearch()));
-
- QWidget *spacer = new QWidget(this);
- spacer->setObjectName(QLatin1String("itemLibrarySearchInputSpacer"));
- spacer->setFixedHeight(4);
-
- QGridLayout *layout = new QGridLayout(this);
- layout->setContentsMargins(0, 0, 0, 0);
- layout->setSpacing(0);
- layout->addWidget(tabBar, 0, 0, 1, 1);
- layout->addWidget(spacer, 1, 0);
- layout->addWidget(lineEditFrame, 2, 0, 1, 1);
- layout->addWidget(m_d->m_stackedWidget, 3, 0, 1, 1);
-
- setResourcePath(QDir::currentPath());
- setSearchFilter(QString());
-
- /* style sheets */
- {
- QFile file(":/qmldesigner/stylesheet.css");
- file.open(QFile::ReadOnly);
- QString styleSheet = QLatin1String(file.readAll());
- setStyleSheet(styleSheet);
- }
-
- {
- QFile file(":/qmldesigner/scrollbar.css");
- file.open(QFile::ReadOnly);
- QString styleSheet = QLatin1String(file.readAll());
- m_d->m_resourcesView->setStyleSheet(styleSheet);
- }
-}
-
-ItemLibrary::~ItemLibrary()
-{
- /* workaround: delete the items view before the model is deleted.
- This prevents qml warnings when the item library is destructed. */
- delete m_d->m_itemsView;
- delete m_d->m_resourcesView;
- delete m_d;
-}
-
-void ItemLibrary::setItemLibraryInfo(ItemLibraryInfo *itemLibraryInfo)
-{
- if (m_d->m_itemLibraryInfo.data() == itemLibraryInfo)
- return;
-
- if (m_d->m_itemLibraryInfo)
- disconnect(m_d->m_itemLibraryInfo.data(), SIGNAL(entriesChanged()),
- this, SLOT(updateModel()));
- m_d->m_itemLibraryInfo = itemLibraryInfo;
- if (itemLibraryInfo)
- connect(m_d->m_itemLibraryInfo.data(), SIGNAL(entriesChanged()),
- this, SLOT(updateModel()));
-
- updateModel();
- updateSearch();
-}
-
-void ItemLibrary::setSearchFilter(const QString &searchFilter)
-{
- if (m_d->m_stackedWidget->currentIndex() == 0) {
- m_d->m_itemLibraryModel->setSearchText(searchFilter);
- emit resetItemsView();
- m_d->m_itemsView->update();
- } else {
- QStringList nameFilterList;
- if (searchFilter.contains('.')) {
- nameFilterList.append(QString("*%1*").arg(searchFilter));
- } else {
- foreach (const QByteArray &extension, QImageReader::supportedImageFormats()) {
- nameFilterList.append(QString("*%1*.%2").arg(searchFilter, QString::fromAscii(extension)));
- }
- }
-
- m_d->m_resourcesDirModel->setFilter(QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot);
- m_d->m_resourcesDirModel->setNameFilters(nameFilterList);
- m_d->m_resourcesView->expandToDepth(1);
- m_d->m_resourcesView->scrollToTop();
- }
-}
-
-void ItemLibrary::updateModel()
-{
- m_d->m_itemLibraryModel->update(m_d->m_itemLibraryInfo.data());
- updateSearch();
-}
-
-void ItemLibrary::updateSearch()
-{
- setSearchFilter(m_d->m_lineEdit->text());
-}
-
-void ItemLibrary::setResourcePath(const QString &resourcePath)
-{
- if (m_d->m_resourcesView->model() == m_d->m_resourcesDirModel)
- m_d->m_resourcesView->setRootIndex(m_d->m_resourcesDirModel->index(resourcePath));
- updateSearch();
-}
-
-void ItemLibrary::startDragAndDrop(int itemLibId)
-{
- QMimeData *mimeData = m_d->m_itemLibraryModel->getMimeData(itemLibId);
- CustomItemLibraryDrag *drag = new CustomItemLibraryDrag(this);
- const QImage image = qvariant_cast<QImage>(mimeData->imageData());
-
- drag->setPixmap(m_d->m_itemLibraryModel->getIcon(itemLibId).pixmap(32, 32));
- drag->setPreview(QPixmap::fromImage(image));
- drag->setMimeData(mimeData);
-
- QDeclarativeItem *rootItem = qobject_cast<QDeclarativeItem*>(m_d->m_itemsView->rootObject());
- connect(rootItem, SIGNAL(stopDragAndDrop()), drag, SLOT(stopDrag()));
-
- drag->exec();
-}
-
-void ItemLibrary::showItemInfo(int /*itemLibId*/)
-{
-// qDebug() << "showing item info about id" << itemLibId;
-}
-
-void ItemLibrary::wheelEvent(QWheelEvent *event)
-{
- if (m_d->m_stackedWidget->currentIndex() == 0 &&
- m_d->m_itemsView->rect().contains(event->pos())) {
- emit scrollItemsView(event->delta());
- event->accept();
- } else
- QFrame::wheelEvent(event);
-}
-
-}
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrary.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibrary.h
deleted file mode 100644
index ca1a764f1c..0000000000
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrary.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#ifndef ITEMLIBRARY_H
-#define ITEMLIBRARY_H
-
-#include "itemlibraryinfo.h"
-#include <QtGui/QFrame>
-
-namespace QmlDesigner {
-
-class ItemLibraryPrivate;
-class MetaInfo;
-class ItemLibraryEntry;
-
-class ItemLibrary : public QFrame
-{
- Q_OBJECT
- Q_DISABLE_COPY(ItemLibrary)
-
-public:
- ItemLibrary(QWidget *parent = 0);
- virtual ~ItemLibrary();
-
- void setItemLibraryInfo(ItemLibraryInfo *itemLibraryInfo);
-
-public Q_SLOTS:
- void setSearchFilter(const QString &searchFilter);
- void updateModel();
- void updateSearch();
-
- void setResourcePath(const QString &resourcePath);
-
- void startDragAndDrop(int itemLibId);
- void showItemInfo(int itemLibId);
-
-protected:
- void wheelEvent(QWheelEvent *event);
-
-signals:
- void itemActivated(const QString& itemName);
- void scrollItemsView(QVariant delta);
- void resetItemsView();
-
-private:
- ItemLibraryPrivate *m_d;
-};
-
-}
-
-#endif // ITEMLIBRARY_H
-
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrary.pri b/src/plugins/qmldesigner/components/itemlibrary/itemlibrary.pri
index 4cd2f619cd..919e7fafe4 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrary.pri
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrary.pri
@@ -6,8 +6,8 @@ VPATH += $$PWD
INCLUDEPATH += $$PWD
# Input
-HEADERS += itemlibrary.h customdraganddrop.h itemlibrarymodel.h itemlibrarywidgets.h itemlibraryimageprovider.h
-SOURCES += itemlibrary.cpp customdraganddrop.cpp itemlibrarymodel.cpp itemlibrarywidgets.cpp itemlibraryimageprovider.cpp
+HEADERS += itemlibraryview.h itemlibrarywidget.h customdraganddrop.h itemlibrarymodel.h itemlibrarycomponents.h itemlibraryimageprovider.h
+SOURCES += itemlibraryview.cpp itemlibrarywidget.cpp customdraganddrop.cpp itemlibrarymodel.cpp itemlibrarycomponents.cpp itemlibraryimageprovider.cpp
RESOURCES += itemlibrary.qrc
OTHER_FILES += \
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrary.qrc b/src/plugins/qmldesigner/components/itemlibrary/itemlibrary.qrc
index e4d27b0476..1343c93988 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrary.qrc
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrary.qrc
@@ -8,6 +8,7 @@
<file>qml/Selector.qml</file>
<file>images/item-default-icon.png</file>
+ <file>images/item-invalid-icon.png</file>
</qresource>
</RCC>
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarycomponents.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarycomponents.cpp
new file mode 100644
index 0000000000..2dc32604a9
--- /dev/null
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarycomponents.cpp
@@ -0,0 +1,207 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** No Commercial Usage
+**
+** This file 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.
+**
+**************************************************************************/
+
+#include "itemlibrarycomponents.h"
+#include "customdraganddrop.h"
+
+#include <QtCore/QMimeData>
+#include <QtCore/QDebug>
+
+#include <QtGui/QImage>
+#include <QtGui/QPixmap>
+#include <QtGui/QDrag>
+#include <QPainter>
+#include <QLabel>
+#include <itemlibraryinfo.h>
+#include <QDirModel>
+#include <QProxyStyle>
+
+enum { debug = 0 };
+
+namespace QmlDesigner {
+
+namespace Internal {
+
+static void drawSelectionBackground(QPainter *painter, const QStyleOption &option)
+{
+ painter->save();
+ QLinearGradient gradient;
+ QColor highlight = option.palette.highlight().color();
+ gradient.setColorAt(0, highlight.lighter(130));
+ gradient.setColorAt(1, highlight.darker(130));
+ gradient.setStart(option.rect.topLeft());
+ gradient.setFinalStop(option.rect.bottomLeft());
+ painter->fillRect(option.rect, gradient);
+ painter->setPen(highlight.lighter());
+ painter->drawLine(option.rect.topLeft(),option.rect.topRight());
+ painter->setPen(highlight.darker());
+ painter->drawLine(option.rect.bottomLeft(),option.rect.bottomRight());
+ painter->restore();
+}
+
+// This style basically allows us to span the entire row
+// including the arrow indicators which would otherwise not be
+// drawn by the delegate
+class TreeViewStyle : public QProxyStyle
+{
+public:
+ void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget * = 0) const
+ {
+ if (element == QStyle::PE_PanelItemViewRow) {
+ if (option->state & QStyle::State_Selected)
+ drawSelectionBackground(painter, *option);
+ }
+ }
+ int styleHint(StyleHint hint, const QStyleOption *option = 0, const QWidget *widget = 0, QStyleHintReturn *returnData = 0) const {
+ if (hint == SH_ItemView_ShowDecorationSelected)
+ return 0;
+ else
+ return QProxyStyle::styleHint(hint, option, widget, returnData);
+ }
+};
+
+ItemLibraryTreeView::ItemLibraryTreeView(QWidget *parent) :
+ QTreeView(parent)
+{
+ setDragEnabled(true);
+ setDragDropMode(QAbstractItemView::DragOnly);
+ setUniformRowHeights(true);
+ connect(this, SIGNAL(clicked(const QModelIndex &)), this, SLOT(activateItem(const QModelIndex &)));
+ setHeaderHidden(true);
+ setIndentation(20);
+ setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ setAttribute(Qt::WA_MacShowFocusRect, false);
+
+ TreeViewStyle *style = new TreeViewStyle;
+ setStyle(style);
+ style->setParent(this);
+ m_delegate = new ResourceItemDelegate(this);
+ setItemDelegateForColumn(0, m_delegate);
+}
+
+// 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;
+
+ 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();
+ }
+}
+
+void ItemLibraryTreeView::setModel(QAbstractItemModel *model)
+{
+ QDirModel *dirModel = dynamic_cast<QDirModel *>(model);
+ if (dirModel) {
+ QTreeView::setModel(model);
+ m_delegate->setModel(dirModel);
+ setColumnHidden(1, true);
+ setColumnHidden(2, true);
+ setColumnHidden(3, true);
+ setSortingEnabled(true);
+ }
+}
+
+void ItemLibraryTreeView::activateItem( const QModelIndex & /*index*/)
+{
+ QMimeData *mimeData = model()->mimeData(selectedIndexes());
+ if (!mimeData)
+ return;
+
+ QString name;
+ 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);
+ }
+}
+
+void ResourceItemDelegate::paint(QPainter *painter,
+ const QStyleOptionViewItem &option, const QModelIndex &index) const
+{
+ if (option.state & QStyle::State_Selected)
+ drawSelectionBackground(painter, option);
+
+ painter->save();
+
+ QIcon icon(m_model->fileIcon(index));
+ QPixmap pixmap(icon.pixmap(icon.availableSizes().front()));
+ painter->drawPixmap(option.rect.x(),option.rect.y()+2,pixmap);
+ QString myString(m_model->fileName(index));
+
+ // Check text length does not exceed available space
+ int extraSpace=12+pixmap.width();
+ QFontMetrics fm(option.font);
+ myString = fm.elidedText(myString,Qt::ElideMiddle,option.rect.width()-extraSpace);
+
+ painter->drawText(option.rect.bottomLeft()+QPoint(3+pixmap.width(),-8),myString);
+
+ painter->restore();
+}
+
+QSize ResourceItemDelegate::sizeHint(const QStyleOptionViewItem &/*option*/,
+ const QModelIndex &index) const
+{
+ QIcon icon(m_model->fileIcon(index));
+ return icon.availableSizes().front() + QSize(25, 4);
+}
+
+void ResourceItemDelegate::setModel(QDirModel *model)
+{
+ m_model = model;
+}
+
+} // namespace Internal
+
+} // namespace QmlDesigner
+
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidgets.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarycomponents.h
index f239434d4b..f239434d4b 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidgets.h
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarycomponents.h
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp
index 6343a2949c..3261dda244 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp
@@ -33,6 +33,8 @@
#include "itemlibrarymodel.h"
#include "itemlibraryinfo.h"
+#include <model.h>
+#include <nodemetainfo.h>
#include <QVariant>
#include <QMimeData>
@@ -305,16 +307,13 @@ void ItemLibrarySectionModel::updateItemIconSize(const QSize &itemIconSize)
}
}
-
bool ItemLibrarySectionModel::operator<(const ItemLibrarySectionModel &other) const
{
+ if (sectionName() == QLatin1String("QML Components")) //Qml Components always come first
+ return true;
return sectionName() < other.sectionName();
}
-
-
-
-
ItemLibraryModel::ItemLibraryModel(QScriptEngine *scriptEngine, QObject *parent)
: ItemLibrarySortedModel<ItemLibrarySectionModel>(parent),
m_scriptEngine(scriptEngine),
@@ -385,7 +384,12 @@ bool ItemLibraryModel::isItemVisible(int itemLibId)
return elementModel(sectionLibId)->isItemVisible(itemLibId);
}
-void ItemLibraryModel::update(ItemLibraryInfo *itemLibraryInfo)
+QString entryToImport(const ItemLibraryEntry &entry)
+{
+ return entry.requiredImport() + " " + QString::number(entry.majorVersion()) + "." + QString::number(entry.minorVersion());
+}
+
+void ItemLibraryModel::update(ItemLibraryInfo *itemLibraryInfo, Model *model)
{
QMap<QString, int> sections;
@@ -394,36 +398,46 @@ void ItemLibraryModel::update(ItemLibraryInfo *itemLibraryInfo)
m_sections.clear();
m_nextLibId = 0;
- foreach (ItemLibraryEntry entry, itemLibraryInfo->entries()) {
- QString itemSectionName = entry.category();
- ItemLibrarySectionModel *sectionModel;
- ItemLibraryItemModel *itemModel;
- int itemId = m_nextLibId++, sectionId;
-
- if (sections.contains(itemSectionName)) {
- sectionId = sections.value(itemSectionName);
- sectionModel = elementModel(sectionId);
- } else {
- sectionId = m_nextLibId++;
- sectionModel = new ItemLibrarySectionModel(m_scriptEngine.data(), sectionId, itemSectionName, this);
- addElement(sectionModel, sectionId);
- sections.insert(itemSectionName, sectionId);
- }
-
- m_itemInfos.insert(itemId, entry);
+ QStringList imports;
+ foreach (const Import &import, model->imports())
+ if (import.isLibraryImport())
+ imports << import.url() + " " + import.version();
- itemModel = new ItemLibraryItemModel(m_scriptEngine.data(), itemId, entry.name());
-
- // delayed creation of (default) icons
- if (entry.iconPath().isEmpty())
- entry.setIconPath(QLatin1String(":/ItemLibrary/images/item-default-icon.png"));
- if (entry.dragIcon().isNull())
- entry.setDragIcon(createDragPixmap(getWidth(entry), getHeight(entry)));
+ foreach (ItemLibraryEntry entry, itemLibraryInfo->entries()) {
- itemModel->setItemIconPath(entry.iconPath());
- itemModel->setItemIconSize(m_itemIconSize);
- sectionModel->addSectionEntry(itemModel);
- m_sections.insert(itemId, sectionId);
+ bool valid = model->metaInfo(entry.typeName(), entry.majorVersion(), entry.minorVersion()).isValid();
+
+ if (valid && (entry.requiredImport().isEmpty() || imports.contains(entryToImport(entry), Qt::CaseInsensitive))) {
+ QString itemSectionName = entry.category();
+ ItemLibrarySectionModel *sectionModel;
+ ItemLibraryItemModel *itemModel;
+ int itemId = m_nextLibId++, sectionId;
+
+ if (sections.contains(itemSectionName)) {
+ sectionId = sections.value(itemSectionName);
+ sectionModel = elementModel(sectionId);
+ } else {
+ sectionId = m_nextLibId++;
+ sectionModel = new ItemLibrarySectionModel(m_scriptEngine.data(), sectionId, itemSectionName, this);
+ addElement(sectionModel, sectionId);
+ sections.insert(itemSectionName, sectionId);
+ }
+
+ m_itemInfos.insert(itemId, entry);
+
+ itemModel = new ItemLibraryItemModel(m_scriptEngine.data(), itemId, entry.name());
+
+ // delayed creation of (default) icons
+ if (entry.iconPath().isEmpty())
+ entry.setIconPath(QLatin1String(":/ItemLibrary/images/item-default-icon.png"));
+ if (entry.dragIcon().isNull())
+ entry.setDragIcon(createDragPixmap(getWidth(entry), getHeight(entry)));
+
+ itemModel->setItemIconPath(entry.iconPath());
+ itemModel->setItemIconSize(m_itemIconSize);
+ sectionModel->addSectionEntry(itemModel);
+ m_sections.insert(itemId, sectionId);
+ }
}
updateVisibility();
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.h
index 83b14e0f32..4f8f78947a 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.h
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.h
@@ -40,12 +40,13 @@
#include <QScriptEngine>
#include <private/qdeclarativelistmodel_p.h>
-QT_FORWARD_DECLARE_CLASS(QMimeData);
+QT_FORWARD_DECLARE_CLASS(QMimeData)
namespace QmlDesigner {
class ItemLibraryInfo;
class ItemLibraryEntry;
+class Model;
namespace Internal {
@@ -135,7 +136,7 @@ public:
QString searchText() const;
- void update(ItemLibraryInfo *itemLibraryInfo);
+ void update(ItemLibraryInfo *itemLibraryInfo, Model *model);
QString getTypeName(int libId);
QMimeData *getMimeData(int libId);
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp
new file mode 100644
index 0000000000..9083876949
--- /dev/null
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp
@@ -0,0 +1,136 @@
+#include "itemlibraryview.h"
+#include "itemlibrarywidget.h"
+#include <import.h>
+
+namespace QmlDesigner {
+
+ItemLibraryView::ItemLibraryView(QObject* parent) : AbstractView(parent), m_widget(new ItemLibraryWidget)
+{
+
+}
+
+ItemLibraryView::~ItemLibraryView()
+{
+
+}
+
+ItemLibraryWidget *ItemLibraryView::widget()
+{
+ return m_widget.data();
+}
+
+void ItemLibraryView::modelAttached(Model *model)
+{
+ AbstractView::modelAttached(model);
+ m_widget->setModel(model);
+ updateImports();
+}
+
+void ItemLibraryView::modelAboutToBeDetached(Model *model)
+{
+ AbstractView::modelAboutToBeDetached(model);
+ m_widget->setModel(0);
+}
+
+void ItemLibraryView::importAdded(const Import &)
+{
+ updateImports();
+}
+
+void ItemLibraryView::importRemoved(const Import &)
+{
+ updateImports();
+}
+
+void ItemLibraryView::nodeCreated(const ModelNode &)
+{
+
+}
+
+void ItemLibraryView::nodeRemoved(const ModelNode &, const NodeAbstractProperty &, PropertyChangeFlags)
+{
+
+}
+
+void ItemLibraryView::propertiesRemoved(const QList<AbstractProperty> &)
+{
+
+}
+
+void ItemLibraryView::variantPropertiesChanged(const QList<VariantProperty> &, PropertyChangeFlags)
+{
+
+}
+
+void ItemLibraryView::bindingPropertiesChanged(const QList<BindingProperty> &, PropertyChangeFlags)
+{
+
+}
+
+void ItemLibraryView::nodeAboutToBeRemoved(const ModelNode &)
+{
+
+}
+
+void ItemLibraryView::nodeOrderChanged(const NodeListProperty &, const ModelNode &, int)
+{
+
+}
+
+void ItemLibraryView::nodeAboutToBeReparented(const ModelNode &, const NodeAbstractProperty &, const NodeAbstractProperty &, AbstractView::PropertyChangeFlags)
+{
+
+}
+
+void ItemLibraryView::nodeReparented(const ModelNode &, const NodeAbstractProperty &, const NodeAbstractProperty &, AbstractView::PropertyChangeFlags)
+{
+
+}
+
+void ItemLibraryView::rootNodeTypeChanged(const QString &, int , int )
+{
+
+}
+
+void ItemLibraryView::nodeIdChanged(const ModelNode &, const QString &, const QString& )
+{
+
+}
+
+void ItemLibraryView::propertiesAboutToBeRemoved(const QList<AbstractProperty>& )
+{
+
+}
+
+void ItemLibraryView::selectedNodesChanged(const QList<ModelNode> &,
+ const QList<ModelNode> &)
+{
+
+}
+
+void ItemLibraryView::auxiliaryDataChanged(const ModelNode &, const QString &, const QVariant &)
+{
+
+}
+
+void ItemLibraryView::scriptFunctionsChanged(const ModelNode &, const QStringList &)
+{
+
+}
+
+void ItemLibraryView::instancePropertyChange(const QList<QPair<ModelNode, QString> > &)
+{
+
+}
+
+void ItemLibraryView::instancesCompleted(const QVector<ModelNode> &)
+{
+
+}
+
+void ItemLibraryView::updateImports()
+{
+ m_widget->updateModel();
+}
+
+} //QmlDesigner
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.h
new file mode 100644
index 0000000000..1b09ec3c6b
--- /dev/null
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.h
@@ -0,0 +1,90 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 ITEMLIBRARYVIEW_H
+#define ITEMLIBRARYVIEW_H
+
+#include <abstractview.h>
+
+#include <QWeakPointer>
+
+
+namespace QmlDesigner {
+
+class ItemLibraryWidget;
+
+
+class ItemLibraryView : public AbstractView
+{
+ Q_OBJECT
+
+public:
+ ItemLibraryView(QObject* parent = 0);
+ ~ItemLibraryView();
+
+ ItemLibraryWidget *widget();
+
+ // AbstractView
+ void modelAttached(Model *model);
+ void modelAboutToBeDetached(Model *model);
+
+ void importAdded(const Import &import);
+ void importRemoved(const Import &import);
+
+ void nodeCreated(const ModelNode &createdNode);
+ void nodeRemoved(const ModelNode &removedNode, const NodeAbstractProperty &parentProperty, PropertyChangeFlags propertyChange);
+ void propertiesRemoved(const QList<AbstractProperty> &propertyList);
+ void variantPropertiesChanged(const QList<VariantProperty> &propertyList, PropertyChangeFlags propertyChange);
+ void bindingPropertiesChanged(const QList<BindingProperty> &propertyList, PropertyChangeFlags propertyChange);
+
+ void nodeAboutToBeRemoved(const ModelNode &removedNode);
+ void nodeOrderChanged(const NodeListProperty &listProperty, const ModelNode &movedNode, int oldIndex);
+
+ void nodeAboutToBeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange);
+ void nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange);
+ void rootNodeTypeChanged(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 scriptFunctionsChanged(const ModelNode &node, const QStringList &scriptFunctionList);
+ void instancePropertyChange(const QList<QPair<ModelNode, QString> > &propertyList);
+ void instancesCompleted(const QVector<ModelNode> &completedNodeList);
+
+protected:
+ void updateImports();
+
+private:
+ QWeakPointer<ItemLibraryWidget> m_widget;
+};
+
+}
+#endif // ITEMLIBRARYVIEW_H
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp
new file mode 100644
index 0000000000..d4a05c969c
--- /dev/null
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp
@@ -0,0 +1,487 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** No Commercial Usage
+**
+** This file 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.
+**
+**************************************************************************/
+
+#include "itemlibrarywidget.h"
+
+#include <utils/filterlineedit.h>
+#include <coreplugin/coreconstants.h>
+#include "itemlibrarycomponents.h"
+#include "itemlibrarymodel.h"
+#include "itemlibraryimageprovider.h"
+#include "customdraganddrop.h"
+#include <model.h>
+#include <metainfo.h>
+
+#include <QFileInfo>
+#include <QFileIconProvider>
+#include <QDirModel>
+#include <QStackedWidget>
+#include <QGridLayout>
+#include <QTabBar>
+#include <QImageReader>
+#include <QMimeData>
+#include <QWheelEvent>
+#include <QMenu>
+#include <QApplication>
+
+#include <QDeclarativeView>
+#include <QDeclarativeItem>
+#include <private/qdeclarativeengine_p.h>
+
+
+namespace QmlDesigner {
+
+class MyFileIconProvider : public QFileIconProvider
+{
+public:
+ MyFileIconProvider(const QSize &iconSize)
+ : QFileIconProvider(),
+ m_iconSize(iconSize)
+ {}
+
+ virtual QIcon icon ( const QFileInfo & info ) const
+ {
+ QPixmap pixmap(info.absoluteFilePath());
+ if (pixmap.isNull()) {
+ QIcon defaultIcon(QFileIconProvider::icon(info));
+ pixmap = defaultIcon.pixmap(defaultIcon.actualSize(m_iconSize));
+ }
+
+ if (pixmap.width() == m_iconSize.width()
+ && pixmap.height() == m_iconSize.height())
+ return pixmap;
+
+ if ((pixmap.width() > m_iconSize.width())
+ || (pixmap.height() > m_iconSize.height()))
+ return pixmap.scaled(m_iconSize, Qt::KeepAspectRatio,
+ Qt::SmoothTransformation);
+
+ QPoint offset((m_iconSize.width() - pixmap.width()) / 2,
+ (m_iconSize.height() - pixmap.height()) / 2);
+ QImage newIcon(m_iconSize, QImage::Format_ARGB32_Premultiplied);
+ newIcon.fill(Qt::transparent);
+ QPainter painter(&newIcon);
+ painter.drawPixmap(offset, pixmap);
+ return QPixmap::fromImage(newIcon);
+ }
+
+private:
+ QSize m_iconSize;
+};
+
+
+// ---------- ItemLibraryPrivate
+class ItemLibraryWidgetPrivate {
+public:
+ ItemLibraryWidgetPrivate(QObject *object);
+
+ Internal::ItemLibraryModel *m_itemLibraryModel;
+ QDirModel *m_resourcesDirModel;
+
+ QStackedWidget *m_stackedWidget;
+ Utils::FilterLineEdit *m_lineEdit;
+ QDeclarativeView *m_itemsView;
+ Internal::ItemLibraryTreeView *m_resourcesView;
+ QWeakPointer<ItemLibraryInfo> m_itemLibraryInfo;
+
+ QSize m_itemIconSize, m_resIconSize;
+ MyFileIconProvider m_iconProvider;
+ Model *model;
+};
+
+ItemLibraryWidgetPrivate::ItemLibraryWidgetPrivate(QObject *object) :
+ m_itemLibraryModel(0),
+ m_resourcesDirModel(0),
+ m_stackedWidget(0),
+ m_lineEdit(0),
+ m_itemsView(0),
+ m_resourcesView(0),
+ m_itemIconSize(24, 24),
+ m_resIconSize(24, 24),
+ m_iconProvider(m_resIconSize),
+ model(0)
+{
+ Q_UNUSED(object);
+}
+
+ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) :
+ QFrame(parent),
+ m_d(new ItemLibraryWidgetPrivate(this)),
+ m_filterFlag(QtBasic)
+{
+ setWindowTitle(tr("Library", "Title of library view"));
+
+ /* create Items view and its model */
+ m_d->m_itemsView = new QDeclarativeView(this);
+ m_d->m_itemsView->setAttribute(Qt::WA_OpaquePaintEvent);
+ m_d->m_itemsView->setAttribute(Qt::WA_NoSystemBackground);
+ m_d->m_itemsView->setAcceptDrops(false);
+ m_d->m_itemsView->setFocusPolicy(Qt::ClickFocus);
+ m_d->m_itemsView->setResizeMode(QDeclarativeView::SizeRootObjectToView);
+ m_d->m_itemLibraryModel = new Internal::ItemLibraryModel(QDeclarativeEnginePrivate::getScriptEngine(m_d->m_itemsView->engine()), this);
+ m_d->m_itemLibraryModel->setItemIconSize(m_d->m_itemIconSize);
+
+ QDeclarativeContext *rootContext = m_d->m_itemsView->rootContext();
+ rootContext->setContextProperty(QLatin1String("itemLibraryModel"), m_d->m_itemLibraryModel);
+ rootContext->setContextProperty(QLatin1String("itemLibraryIconWidth"), m_d->m_itemIconSize.width());
+ rootContext->setContextProperty(QLatin1String("itemLibraryIconHeight"), m_d->m_itemIconSize.height());
+
+ QColor highlightColor = palette().highlight().color();
+ if (0.5*highlightColor.saturationF()+0.75-highlightColor.valueF() < 0)
+ highlightColor.setHsvF(highlightColor.hsvHueF(),0.1 + highlightColor.saturationF()*2.0, highlightColor.valueF());
+ m_d->m_itemsView->rootContext()->setContextProperty(QLatin1String("highlightColor"), highlightColor);
+
+ // loading the qml has to come after all needed context properties are set
+ m_d->m_itemsView->setSource(QUrl("qrc:/ItemLibrary/qml/ItemsView.qml"));
+
+ QDeclarativeItem *rootItem = qobject_cast<QDeclarativeItem*>(m_d->m_itemsView->rootObject());
+ connect(rootItem, SIGNAL(itemSelected(int)), this, SLOT(showItemInfo(int)));
+ connect(rootItem, SIGNAL(itemDragged(int)), this, SLOT(startDragAndDrop(int)));
+ connect(this, SIGNAL(scrollItemsView(QVariant)), rootItem, SLOT(scrollView(QVariant)));
+ connect(this, SIGNAL(resetItemsView()), rootItem, SLOT(resetView()));
+
+ /* create Resources view and its model */
+ m_d->m_resourcesDirModel = new QDirModel(this);
+ m_d->m_resourcesDirModel->setIconProvider(&m_d->m_iconProvider);
+ m_d->m_resourcesView = new Internal::ItemLibraryTreeView(this);
+ m_d->m_resourcesView->setModel(m_d->m_resourcesDirModel);
+ m_d->m_resourcesView->setIconSize(m_d->m_resIconSize);
+
+ /* create image provider for loading item icons */
+ m_d->m_itemsView->engine()->addImageProvider(QLatin1String("qmldesigner_itemlibrary"), new Internal::ItemLibraryImageProvider);
+
+ /* other widgets */
+ QTabBar *tabBar = new QTabBar(this);
+ tabBar->addTab(tr("Items", "Title of library items view"));
+ tabBar->addTab(tr("Resources", "Title of library resources view"));
+ tabBar->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+
+ m_d->m_lineEdit = new Utils::FilterLineEdit(this);
+ m_d->m_lineEdit->setObjectName(QLatin1String("itemLibrarySearchInput"));
+ m_d->m_lineEdit->setPlaceholderText(tr("<Filter>", "Library search input hint text"));
+ m_d->m_lineEdit->setDragEnabled(false);
+ m_d->m_lineEdit->setMinimumWidth(75);
+ m_d->m_lineEdit->setTextMargins(0, 0, 20, 0);
+ QWidget *lineEditFrame = new QWidget(this);
+ lineEditFrame->setObjectName(QLatin1String("itemLibrarySearchInputFrame"));
+ QGridLayout *lineEditLayout = new QGridLayout(lineEditFrame);
+ lineEditLayout->setMargin(2);
+ lineEditLayout->setSpacing(0);
+ lineEditLayout->addItem(new QSpacerItem(5, 3, QSizePolicy::Fixed, QSizePolicy::Fixed), 0, 0, 1, 3);
+ lineEditLayout->addItem(new QSpacerItem(5, 5, QSizePolicy::Fixed, QSizePolicy::Fixed), 1, 0);
+ lineEditLayout->addWidget(m_d->m_lineEdit, 1, 1, 1, 1);
+ lineEditLayout->addItem(new QSpacerItem(5, 5, QSizePolicy::Fixed, QSizePolicy::Fixed), 1, 2);
+ connect(m_d->m_lineEdit, SIGNAL(filterChanged(QString)), this, SLOT(setSearchFilter(QString)));
+
+ m_d->m_stackedWidget = new QStackedWidget(this);
+ m_d->m_stackedWidget->addWidget(m_d->m_itemsView);
+ m_d->m_stackedWidget->addWidget(m_d->m_resourcesView);
+ connect(tabBar, SIGNAL(currentChanged(int)),
+ m_d->m_stackedWidget, SLOT(setCurrentIndex(int)));
+ connect(tabBar, SIGNAL(currentChanged(int)),
+ this, SLOT(updateSearch()));
+
+ QWidget *spacer = new QWidget(this);
+ spacer->setObjectName(QLatin1String("itemLibrarySearchInputSpacer"));
+ spacer->setFixedHeight(4);
+
+ QGridLayout *layout = new QGridLayout(this);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+ layout->addWidget(tabBar, 0, 0, 1, 1);
+ layout->addWidget(spacer, 1, 0);
+ layout->addWidget(lineEditFrame, 2, 0, 1, 1);
+ layout->addWidget(m_d->m_stackedWidget, 3, 0, 1, 1);
+
+ setResourcePath(QDir::currentPath());
+ setSearchFilter(QString());
+
+ /* style sheets */
+ {
+ QFile file(":/qmldesigner/stylesheet.css");
+ file.open(QFile::ReadOnly);
+ QString styleSheet = QLatin1String(file.readAll());
+ setStyleSheet(styleSheet);
+ }
+
+ {
+ QFile file(":/qmldesigner/scrollbar.css");
+ file.open(QFile::ReadOnly);
+ QString styleSheet = QLatin1String(file.readAll());
+ m_d->m_resourcesView->setStyleSheet(styleSheet);
+ }
+}
+
+ItemLibraryWidget::~ItemLibraryWidget()
+{
+ /* workaround: delete the items view before the model is deleted.
+ This prevents qml warnings when the item library is destructed. */
+ delete m_d->m_itemsView;
+ delete m_d->m_resourcesView;
+ delete m_d;
+}
+
+void ItemLibraryWidget::setItemLibraryInfo(ItemLibraryInfo *itemLibraryInfo)
+{
+ if (m_d->m_itemLibraryInfo.data() == itemLibraryInfo)
+ return;
+
+ if (m_d->m_itemLibraryInfo)
+ disconnect(m_d->m_itemLibraryInfo.data(), SIGNAL(entriesChanged()),
+ this, SLOT(updateModel()));
+ m_d->m_itemLibraryInfo = itemLibraryInfo;
+ if (itemLibraryInfo)
+ connect(m_d->m_itemLibraryInfo.data(), SIGNAL(entriesChanged()),
+ this, SLOT(updateModel()));
+
+ updateModel();
+ updateSearch();
+}
+
+void ItemLibraryWidget::updateImports()
+{
+ FilterChangeFlag filter;
+ filter = QtBasic;
+ if (m_d->model) {
+ QStringList imports;
+ foreach (const Import &import, m_d->model->imports())
+ if (import.isLibraryImport())
+ imports << import.url();
+ if (imports.contains("Qt.labs.Symbian", Qt::CaseInsensitive))
+ filter = Symbian;
+ if (imports.contains("com.Meego", Qt::CaseInsensitive))
+ filter = Meego;
+ }
+
+ setImportFilter(filter);
+}
+
+QList<QToolButton *> ItemLibraryWidget::createToolBarWidgets()
+{
+ QList<QToolButton *> buttons;
+ buttons << new QToolButton();
+ buttons.first()->setText("I ");
+ buttons.first()->setIcon(QIcon(QLatin1String(Core::Constants::ICON_FILTER)));
+ buttons.first()->setToolTip("Manage imports for components");
+ buttons.first()->setPopupMode(QToolButton::InstantPopup);
+ QMenu * menu = new QMenu;
+ QAction * basicQtAction = new QAction(menu);
+ basicQtAction->setCheckable(true);
+ basicQtAction->setText("Basic Qt Quick only");
+ QAction * symbianAction = new QAction(menu);
+ symbianAction->setCheckable(true);
+ symbianAction->setText("Symbian Components");
+ QAction * meegoAction= new QAction(menu);
+ meegoAction->setCheckable(true);
+ meegoAction->setText("Meego Components");
+ menu->addAction(basicQtAction);
+ menu->addAction(meegoAction);
+ menu->addAction(symbianAction);
+ buttons.first()->setMenu(menu);
+
+ connect(basicQtAction, SIGNAL(toggled(bool)), this, SLOT(onQtBasicOnlyChecked(bool)));
+ connect(this, SIGNAL(qtBasicOnlyChecked(bool)), basicQtAction, SLOT(setChecked(bool)));
+
+ connect(symbianAction, SIGNAL(toggled(bool)), this, SLOT(onSymbianChecked(bool)));
+ connect(this, SIGNAL(symbianChecked(bool)), symbianAction, SLOT(setChecked(bool)));
+
+ connect(meegoAction, SIGNAL(toggled(bool)), this, SLOT(onMeegoChecked(bool)));
+ connect(this, SIGNAL(meegoChecked(bool)), meegoAction, SLOT(setChecked(bool)));
+
+ updateImports();
+
+ return buttons;
+}
+
+void ItemLibraryWidget::setSearchFilter(const QString &searchFilter)
+{
+ if (m_d->m_stackedWidget->currentIndex() == 0) {
+ m_d->m_itemLibraryModel->setSearchText(searchFilter);
+ emit resetItemsView();
+ m_d->m_itemsView->update();
+ } else {
+ QStringList nameFilterList;
+ if (searchFilter.contains('.')) {
+ nameFilterList.append(QString("*%1*").arg(searchFilter));
+ } else {
+ foreach (const QByteArray &extension, QImageReader::supportedImageFormats()) {
+ nameFilterList.append(QString("*%1*.%2").arg(searchFilter, QString::fromAscii(extension)));
+ }
+ }
+
+ m_d->m_resourcesDirModel->setFilter(QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot);
+ m_d->m_resourcesDirModel->setNameFilters(nameFilterList);
+ m_d->m_resourcesView->expandToDepth(1);
+ m_d->m_resourcesView->scrollToTop();
+ }
+}
+
+void ItemLibraryWidget::setModel(Model *model)
+{
+ m_d->model = model;
+ if (!model)
+ return;
+ setItemLibraryInfo(model->metaInfo().itemLibraryInfo());
+ updateModel();
+}
+
+
+void ItemLibraryWidget::setImportFilter(FilterChangeFlag flag)
+{
+
+ static bool block = false;
+ if (!m_d->model)
+ return;
+ if (flag == m_filterFlag)
+ return;
+
+ if (block == true)
+ return;
+
+ QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
+
+ block = true;
+ if (flag == QtBasic) {
+ removeImport(QLatin1String("com.meego"));
+ removeImport(QLatin1String("Qt.labs.Symbian"));
+ emit qtBasicOnlyChecked(true);
+ emit meegoChecked(false);
+ emit symbianChecked(false);
+ } else if (flag == Symbian) {
+ removeImport(QLatin1String("com.meego"));
+ addImport(QLatin1String("Qt.labs.Symbian"), QLatin1String("1.0"));
+ emit qtBasicOnlyChecked(false);
+ emit meegoChecked(false);
+ emit symbianChecked(true);
+ } else if (flag == Meego) {
+ removeImport(QLatin1String("Qt.labs.Symbian"));
+ addImport(QLatin1String("com.meego"), QLatin1String("1.0"));
+ emit qtBasicOnlyChecked(false);
+ emit meegoChecked(true);
+ emit symbianChecked(false);
+ }
+ QApplication::restoreOverrideCursor();
+ block = false;
+ m_filterFlag = flag;
+}
+
+void ItemLibraryWidget::onQtBasicOnlyChecked(bool b)
+{
+ if (b)
+ setImportFilter(QtBasic);
+
+}
+
+void ItemLibraryWidget::onMeegoChecked(bool b)
+{
+ if (b)
+ setImportFilter(Meego);
+}
+
+void ItemLibraryWidget::onSymbianChecked(bool b)
+{
+ if (b)
+ setImportFilter(Symbian);
+}
+
+
+
+void ItemLibraryWidget::updateModel()
+{
+ m_d->m_itemLibraryModel->update(m_d->m_itemLibraryInfo.data(), m_d->model);
+ updateImports();
+ updateSearch();
+}
+
+void ItemLibraryWidget::updateSearch()
+{
+ setSearchFilter(m_d->m_lineEdit->text());
+}
+
+void ItemLibraryWidget::setResourcePath(const QString &resourcePath)
+{
+ if (m_d->m_resourcesView->model() == m_d->m_resourcesDirModel)
+ m_d->m_resourcesView->setRootIndex(m_d->m_resourcesDirModel->index(resourcePath));
+ updateSearch();
+}
+
+void ItemLibraryWidget::startDragAndDrop(int itemLibId)
+{
+ QMimeData *mimeData = m_d->m_itemLibraryModel->getMimeData(itemLibId);
+ CustomItemLibraryDrag *drag = new CustomItemLibraryDrag(this);
+ const QImage image = qvariant_cast<QImage>(mimeData->imageData());
+
+ drag->setPixmap(m_d->m_itemLibraryModel->getIcon(itemLibId).pixmap(32, 32));
+ drag->setPreview(QPixmap::fromImage(image));
+ drag->setMimeData(mimeData);
+
+ QDeclarativeItem *rootItem = qobject_cast<QDeclarativeItem*>(m_d->m_itemsView->rootObject());
+ connect(rootItem, SIGNAL(stopDragAndDrop()), drag, SLOT(stopDrag()));
+
+ drag->exec();
+}
+
+void ItemLibraryWidget::showItemInfo(int /*itemLibId*/)
+{
+// qDebug() << "showing item info about id" << itemLibId;
+}
+
+void ItemLibraryWidget::wheelEvent(QWheelEvent *event)
+{
+ if (m_d->m_stackedWidget->currentIndex() == 0 &&
+ m_d->m_itemsView->rect().contains(event->pos())) {
+ emit scrollItemsView(event->delta());
+ event->accept();
+ } else
+ QFrame::wheelEvent(event);
+}
+
+ void ItemLibraryWidget::removeImport(const QString &name)
+ {
+ if (!m_d->model)
+ return;
+ foreach (const Import &import, m_d->model->imports())
+ if (import.isLibraryImport() && import.url().compare(name, Qt::CaseInsensitive) == 0)
+ m_d->model->removeImport(import);
+ }
+
+ void ItemLibraryWidget::addImport(const QString &name, const QString &version)
+ {
+ if (!m_d->model)
+ return;
+
+ m_d->model->addImport(Import::createLibraryImport(name, version));
+
+ }
+
+}
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h
new file mode 100644
index 0000000000..3e9c5ae096
--- /dev/null
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h
@@ -0,0 +1,107 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** No Commercial Usage
+**
+** This file 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.
+**
+**************************************************************************/
+
+#ifndef ITEMLIBRARYWIDGET_H
+#define ITEMLIBRARYWIDGET_H
+
+#include "itemlibraryinfo.h"
+#include <QtGui/QFrame>
+#include <QtGui/QToolButton>
+
+namespace QmlDesigner {
+
+class ItemLibraryWidgetPrivate;
+class MetaInfo;
+class ItemLibraryEntry;
+class Model;
+
+class ItemLibraryWidget : public QFrame
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(ItemLibraryWidget)
+
+ enum FilterChangeFlag {
+ QtBasic = 0x0,
+ Meego = 0x1,
+ Symbian = 0x2
+ };
+
+public:
+ ItemLibraryWidget(QWidget *parent = 0);
+ virtual ~ItemLibraryWidget();
+
+ void setItemLibraryInfo(ItemLibraryInfo *itemLibraryInfo);
+ QList<QToolButton *> createToolBarWidgets();
+
+ void updateImports();
+
+public Q_SLOTS:
+ void setSearchFilter(const QString &searchFilter);
+ void updateModel();
+ void updateSearch();
+
+ void setResourcePath(const QString &resourcePath);
+
+ void startDragAndDrop(int itemLibId);
+ void showItemInfo(int itemLibId);
+
+ void setModel(Model *model);
+
+ void setImportFilter(FilterChangeFlag flag);
+
+ void onQtBasicOnlyChecked(bool b);
+ void onMeegoChecked(bool b);
+ void onSymbianChecked(bool b);
+
+protected:
+ void wheelEvent(QWheelEvent *event);
+ void removeImport(const QString &name);
+ void addImport(const QString &name, const QString &version);
+
+signals:
+ void itemActivated(const QString& itemName);
+ void scrollItemsView(QVariant delta);
+ void resetItemsView();
+ void qtBasicOnlyChecked(bool b);
+ void meegoChecked(bool b);
+ void symbianChecked(bool b);
+
+private:
+ ItemLibraryWidgetPrivate *m_d;
+ FilterChangeFlag m_filterFlag;
+};
+
+}
+
+#endif // ITEMLIBRARYWIDGET_H
+
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidgets.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidgets.cpp
deleted file mode 100644
index 5d29ea81cb..0000000000
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidgets.cpp
+++ /dev/null
@@ -1,208 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#include "itemlibrarywidgets.h"
-#include "itemlibrary.h"
-#include "customdraganddrop.h"
-
-#include <QtCore/QMimeData>
-#include <QtCore/QDebug>
-
-#include <QtGui/QImage>
-#include <QtGui/QPixmap>
-#include <QtGui/QDrag>
-#include <QPainter>
-#include <QLabel>
-#include <itemlibraryinfo.h>
-#include <QDirModel>
-#include <QProxyStyle>
-
-enum { debug = 0 };
-
-namespace QmlDesigner {
-
-namespace Internal {
-
-static void drawSelectionBackground(QPainter *painter, const QStyleOption &option)
-{
- painter->save();
- QLinearGradient gradient;
- QColor highlight = option.palette.highlight().color();
- gradient.setColorAt(0, highlight.lighter(130));
- gradient.setColorAt(1, highlight.darker(130));
- gradient.setStart(option.rect.topLeft());
- gradient.setFinalStop(option.rect.bottomLeft());
- painter->fillRect(option.rect, gradient);
- painter->setPen(highlight.lighter());
- painter->drawLine(option.rect.topLeft(),option.rect.topRight());
- painter->setPen(highlight.darker());
- painter->drawLine(option.rect.bottomLeft(),option.rect.bottomRight());
- painter->restore();
-}
-
-// This style basically allows us to span the entire row
-// including the arrow indicators which would otherwise not be
-// drawn by the delegate
-class TreeViewStyle : public QProxyStyle
-{
-public:
- void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget * = 0) const
- {
- if (element == QStyle::PE_PanelItemViewRow) {
- if (option->state & QStyle::State_Selected)
- drawSelectionBackground(painter, *option);
- }
- }
- int styleHint(StyleHint hint, const QStyleOption *option = 0, const QWidget *widget = 0, QStyleHintReturn *returnData = 0) const {
- if (hint == SH_ItemView_ShowDecorationSelected)
- return 0;
- else
- return QProxyStyle::styleHint(hint, option, widget, returnData);
- }
-};
-
-ItemLibraryTreeView::ItemLibraryTreeView(QWidget *parent) :
- QTreeView(parent)
-{
- setDragEnabled(true);
- setDragDropMode(QAbstractItemView::DragOnly);
- setUniformRowHeights(true);
- connect(this, SIGNAL(clicked(const QModelIndex &)), this, SLOT(activateItem(const QModelIndex &)));
- setHeaderHidden(true);
- setIndentation(20);
- setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
- setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
- setAttribute(Qt::WA_MacShowFocusRect, false);
-
- TreeViewStyle *style = new TreeViewStyle;
- setStyle(style);
- style->setParent(this);
- m_delegate = new ResourceItemDelegate(this);
- setItemDelegateForColumn(0, m_delegate);
-}
-
-// 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;
-
- 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();
- }
-}
-
-void ItemLibraryTreeView::setModel(QAbstractItemModel *model)
-{
- QDirModel *dirModel = dynamic_cast<QDirModel *>(model);
- if (dirModel) {
- QTreeView::setModel(model);
- m_delegate->setModel(dirModel);
- setColumnHidden(1, true);
- setColumnHidden(2, true);
- setColumnHidden(3, true);
- setSortingEnabled(true);
- }
-}
-
-void ItemLibraryTreeView::activateItem( const QModelIndex & /*index*/)
-{
- QMimeData *mimeData = model()->mimeData(selectedIndexes());
- if (!mimeData)
- return;
-
- QString name;
- 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);
- }
-}
-
-void ResourceItemDelegate::paint(QPainter *painter,
- const QStyleOptionViewItem &option, const QModelIndex &index) const
-{
- if (option.state & QStyle::State_Selected)
- drawSelectionBackground(painter, option);
-
- painter->save();
-
- QIcon icon(m_model->fileIcon(index));
- QPixmap pixmap(icon.pixmap(icon.availableSizes().front()));
- painter->drawPixmap(option.rect.x(),option.rect.y()+2,pixmap);
- QString myString(m_model->fileName(index));
-
- // Check text length does not exceed available space
- int extraSpace=12+pixmap.width();
- QFontMetrics fm(option.font);
- myString = fm.elidedText(myString,Qt::ElideMiddle,option.rect.width()-extraSpace);
-
- painter->drawText(option.rect.bottomLeft()+QPoint(3+pixmap.width(),-8),myString);
-
- painter->restore();
-}
-
-QSize ResourceItemDelegate::sizeHint(const QStyleOptionViewItem &/*option*/,
- const QModelIndex &index) const
-{
- QIcon icon(m_model->fileIcon(index));
- return icon.availableSizes().front() + QSize(25, 4);
-}
-
-void ResourceItemDelegate::setModel(QDirModel *model)
-{
- m_model = model;
-}
-
-} // namespace Internal
-
-} // namespace QmlDesigner
-
diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp
index 2f4ac34e4e..f3da42422d 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp
+++ b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp
@@ -37,7 +37,6 @@
#include <nodelistproperty.h>
#include <nodeproperty.h>
#include <metainfo.h>
-#include <propertymetainfo.h>
#include <qgraphicswidget.h>
#include <abstractview.h>
#include <rewriterview.h>
@@ -141,7 +140,7 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *data,
if (!parentNode.metaInfo().hasDefaultProperty())
return false;
targetIndex -= visibleProperties(parentNode).count();
- parentPropertyName = parentNode.metaInfo().defaultProperty();
+ parentPropertyName = parentNode.metaInfo().defaultPropertyName();
}
else {
parentItemIndex = parentIndex.parent();
@@ -185,7 +184,7 @@ NavigatorTreeModel::ItemRow NavigatorTreeModel::createItemRow(const ModelNode &n
{
Q_ASSERT(node.isValid());
- uint hash = qHash(node);
+ uint hash = node.internalId();
const bool dropEnabled = node.metaInfo().isValid();
@@ -194,6 +193,10 @@ NavigatorTreeModel::ItemRow NavigatorTreeModel::createItemRow(const ModelNode &n
idItem->setDropEnabled(dropEnabled);
idItem->setEditable(true);
idItem->setData(hash, NavigatorRole);
+ if (node.metaInfo().isValid())
+ idItem->setToolTip(node.type());
+ else
+ idItem->setToolTip(tr("unkown item: ") + node.type());
# ifdef _LOCK_ITEMS_
QStandardItem *lockItem = new QStandardItem;
@@ -238,6 +241,10 @@ void NavigatorTreeModel::updateItemRow(const ModelNode &node, ItemRow items)
items.idItem->setText(node.id());
items.visibilityItem->setCheckState(node.auxiliaryData("invisible").toBool() ? Qt::Unchecked : Qt::Checked);
+ if (node.metaInfo().isValid())
+ items.idItem->setToolTip(node.type());
+ else
+ items.idItem->setToolTip(tr("unkown item: ") + node.type());
blockItemChangedSignal(blockSignal);
}
@@ -297,7 +304,7 @@ void NavigatorTreeModel::handleChangedItem(QStandardItem *item)
return;
uint nodeHash = item->data(NavigatorRole).toUInt();
- Q_ASSERT(nodeHash && containsNodeHash(nodeHash));
+ Q_ASSERT(containsNodeHash(nodeHash));
ModelNode node = nodeForHash(nodeHash);
ItemRow itemRow = itemRowForNode(node);
@@ -390,14 +397,13 @@ ModelNode NavigatorTreeModel::nodeForIndex(const QModelIndex &index) const
{
Q_ASSERT(index.isValid());
uint hash = index.data(NavigatorRole).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));
+ return m_nodeHash.keys().contains(node.internalId());
}
bool NavigatorTreeModel::isNodeInvisible(const QModelIndex &index) const
@@ -421,7 +427,7 @@ bool NavigatorTreeModel::isNodeInvisible(const ModelNode &node) const
void NavigatorTreeModel::addSubTree(const ModelNode &node)
{
Q_ASSERT(node.isValid());
- Q_ASSERT(!containsNodeHash(qHash(node)));
+ Q_ASSERT(!containsNodeHash(node.internalId()));
//updateItemRow(node, newRow);
@@ -432,7 +438,7 @@ void NavigatorTreeModel::addSubTree(const ModelNode &node)
}
ItemRow newRow = createItemRow(node);
- m_nodeHash.insert(qHash(node), node);
+ m_nodeHash.insert(node.internalId(), node);
m_nodeItemHash.insert(node, newRow);
updateItemRow(node, newRow);
@@ -479,14 +485,14 @@ void NavigatorTreeModel::removeSubTree(const ModelNode &node)
qDeleteAll(rowList);
- m_nodeHash.remove(qHash(node));
+ m_nodeHash.remove(node.internalId());
m_nodeItemHash.remove(node);
}
void NavigatorTreeModel::moveNodesInteractive(NodeAbstractProperty parentProperty, const QList<ModelNode> &modelNodes, int targetIndex)
{
try {
- QString propertyQmlType = qmlTypeInQtContainer(parentProperty.metaInfo().type());
+ QString propertyQmlType = qmlTypeInQtContainer(parentProperty.parentModelNode().metaInfo().propertyTypeName(parentProperty.name()));
RewriterTransaction transaction = m_view->beginRewriterTransaction();
foreach (const ModelNode &node, modelNodes) {
@@ -543,7 +549,7 @@ QList<ModelNode> NavigatorTreeModel::modelNodeChildren(const ModelNode &parentNo
QStringList properties;
if (parentNode.metaInfo().hasDefaultProperty())
- properties << parentNode.metaInfo().defaultProperty();
+ properties << parentNode.metaInfo().defaultPropertyName();
properties << visibleProperties(parentNode);
@@ -569,7 +575,7 @@ QString NavigatorTreeModel::qmlTypeInQtContainer(const QString &qtContainerType)
if (typeName.endsWith('*'))
typeName.chop(1);
- return m_view->model()->metaInfo().fromQtTypes(typeName);
+ return typeName;
}
@@ -577,16 +583,16 @@ QStringList NavigatorTreeModel::visibleProperties(const ModelNode &node) const
{
QStringList propertyList;
- foreach (PropertyMetaInfo propertyMetaInfo, node.metaInfo().properties().values()) {
- if (!m_hiddenProperties.contains(propertyMetaInfo.name()) &&
- propertyMetaInfo.name() != node.metaInfo().defaultProperty() &&
- propertyMetaInfo.isReadable() &&
- propertyMetaInfo.isWriteable()) {
+ foreach (const QString &propertyName, node.metaInfo().propertyNames()) {
+ if (!propertyName.contains('.') && //do not show any dot properties, since they are tricky and unlikely to make sense
+ node.metaInfo().propertyIsWritable(propertyName) && !m_hiddenProperties.contains(propertyName) &&
+ !node.metaInfo().propertyIsEnumType(propertyName) && //Some enums have the same name as Qml types (e. g. Flow)
+ propertyName != node.metaInfo().defaultPropertyName()) { // TODO: ask the node instances
- QString qmlType = qmlTypeInQtContainer(propertyMetaInfo.type());
- if (node.metaInfo().metaInfo().hasNodeMetaInfo(qmlType) &&
- node.metaInfo().metaInfo().nodeMetaInfo(qmlType).isSubclassOf("QGraphicsObject", -1, -1)) {
- propertyList << propertyMetaInfo.name();
+ QString qmlType = qmlTypeInQtContainer(node.metaInfo().propertyTypeName(propertyName));
+ if (node.model()->metaInfo(qmlType).isValid() &&
+ node.model()->metaInfo(qmlType).isSubclassOf("QGraphicsObject", -1, -1)) {
+ propertyList.append(propertyName);
}
}
}
diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreeview.cpp b/src/plugins/qmldesigner/components/navigator/navigatortreeview.cpp
index a5557609ef..7e3118b544 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatortreeview.cpp
+++ b/src/plugins/qmldesigner/components/navigator/navigatortreeview.cpp
@@ -33,6 +33,8 @@
#include "navigatortreeview.h"
+#include <qmath.h>
+
#include "navigatorview.h"
#include "navigatortreemodel.h"
#include "navigatorwidget.h"
@@ -41,6 +43,58 @@
#include <nodeproperty.h>
#include "metainfo.h"
#include <QLineEdit>
+#include <QPen>
+#include <QPixmapCache>
+
+
+static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen)
+{
+ const qreal radiusBase = qMax(qreal(1), maxRadius);
+
+ QString key = QLatin1String("WaveUnderline-Bauhaus");
+
+ QPixmap pixmap;
+ if (QPixmapCache::find(key, pixmap))
+ return pixmap;
+
+ const qreal halfPeriod = qMax(qreal(2), qreal(radiusBase * 1.61803399)); // the golden ratio
+ const int width = qCeil(100 / (2 * halfPeriod)) * (2 * halfPeriod);
+ const int radius = qFloor(radiusBase);
+
+ QPainterPath path;
+
+ qreal xs = 0;
+ qreal ys = radius;
+
+ while (xs < width) {
+ xs += halfPeriod;
+ ys = -ys;
+ path.quadTo(xs - halfPeriod / 2, ys, xs, 0);
+ }
+
+ pixmap = QPixmap(width, radius * 2);
+ pixmap.fill(Qt::transparent);
+ {
+ QPen wavePen = pen;
+ wavePen.setCapStyle(Qt::SquareCap);
+
+ // This is to protect against making the line too fat, as happens on Mac OS X
+ // due to it having a rather thick width for the regular underline.
+ const qreal maxPenWidth = .8 * radius;
+ if (wavePen.widthF() > maxPenWidth)
+ wavePen.setWidth(maxPenWidth);
+
+ QPainter imgPainter(&pixmap);
+ imgPainter.setPen(wavePen);
+ imgPainter.setRenderHint(QPainter::Antialiasing);
+ imgPainter.translate(0, radius);
+ imgPainter.drawPath(path);
+ }
+
+ QPixmapCache::insert(key, pixmap);
+
+ return pixmap;
+}
namespace QmlDesigner {
@@ -124,7 +178,7 @@ NavigatorTreeView::NavigatorTreeView(QWidget *parent)
TreeViewStyle *style = new TreeViewStyle;
setStyle(style);
style->setParent(this);
-};
+}
QSize IconCheckboxItemDelegate::sizeHint(const QStyleOptionViewItem &option,
const QModelIndex &index) const
@@ -173,7 +227,8 @@ void NameItemDelegate::paint(QPainter *painter,
QPoint displayStringOffset;
painter->save();
-
+ QFontMetrics fm(option.font);
+ int width = 0;
if (index.data(Qt::UserRole).isValid()) {
int pixmapSide = 16;
@@ -184,28 +239,24 @@ void NameItemDelegate::paint(QPainter *painter,
ModelNode node = m_TreeModel->nodeForIndex(index);
QIcon icon;
- if (node.metaInfo().isValid()) {
- icon=node.metaInfo().icon();
- if (icon.isNull())
- {
- // if node has no own icon, search for it in the itemlibrary
- const NodeMetaInfo typeInfo = node.metaInfo();
- const ItemLibraryInfo *libraryInfo = node.metaInfo().metaInfo().itemLibraryInfo();
- QList <ItemLibraryEntry> infoList = libraryInfo->entriesForType(typeInfo.typeName(),
- typeInfo.majorVersion(),
- typeInfo.minorVersion());
- foreach (const ItemLibraryEntry &entry, infoList) {
- if (!icon.isNull()) {
- icon = entry.icon();
- break;
- }
+ if (node.isValid()) {
+ // if node has no own icon, search for it in the itemlibrary
+ const ItemLibraryInfo *libraryInfo = node.model()->metaInfo().itemLibraryInfo();
+ QList <ItemLibraryEntry> infoList = libraryInfo->entriesForType(node.type(),
+ node.majorVersion(),
+ node.minorVersion());
+ foreach (const ItemLibraryEntry &entry, infoList) {
+ if (icon.isNull()) {
+ icon = entry.icon();
+ break;
}
}
}
-
- // if the library was also empty, use the default icon
- if (icon.isNull())
- icon = QIcon(QLatin1String(":/ItemLibrary/images/item-default-icon.png"));
+ // if the library was also empty, use the default icon
+ if (icon.isNull())
+ icon = QIcon(QLatin1String(":/ItemLibrary/images/item-default-icon.png"));
+ if (!node.metaInfo().isValid())
+ icon = QIcon(QLatin1String(":/ItemLibrary/images/item-invalid-icon.png"));
// If no icon is present, leave an empty space of 24 pixels anyway
QPixmap pixmap = icon.pixmap(pixmapSide, pixmapSide);
@@ -217,16 +268,33 @@ void NameItemDelegate::paint(QPainter *painter,
// Check text length does not exceed available space
int extraSpace=12+pixmapSide;
- QFontMetrics fm(option.font);
+
displayString = fm.elidedText(displayString,Qt::ElideMiddle,option.rect.width()-extraSpace);
displayStringOffset = QPoint(5+pixmapSide,-5);
+ width = fm.width(displayString);
}
else {
displayString = index.data(Qt::DisplayRole).toString();
displayStringOffset = QPoint(0, -2);
}
- painter->drawText(option.rect.bottomLeft()+displayStringOffset,displayString);
+ QPoint pos = option.rect.bottomLeft() + displayStringOffset;
+ painter->drawText(pos, displayString);
+
+ ModelNode node = m_TreeModel->nodeForIndex(index);
+
+ if (!node.isValid() ||!node.metaInfo().isValid()) {
+ painter->translate(0, pos.y() + 1);
+ QPen pen;
+ pen.setColor(Qt::red);
+
+ const qreal underlineOffset = fm.underlinePos();
+ const QPixmap wave = generateWavyPixmap(qMax(underlineOffset, pen.widthF()), pen);
+ const int descent = fm.descent();
+
+ painter->setBrushOrigin(painter->brushOrigin().x(), 0);
+ painter->fillRect(pos.x(), 0, qCeil(width), qMin(wave.height(), descent), wave);
+ }
painter->restore();
}
diff --git a/src/plugins/qmldesigner/components/navigator/navigatorview.cpp b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp
index 7c3a20a202..b959794a65 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatorview.cpp
+++ b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp
@@ -108,6 +108,17 @@ void NavigatorView::modelAboutToBeDetached(Model *model)
AbstractView::modelAboutToBeDetached(model);
}
+void NavigatorView::importAdded(const Import &)
+{
+ treeWidget()->update();
+}
+
+void NavigatorView::importRemoved(const Import &)
+{
+ treeWidget()->update();
+}
+
+
void NavigatorView::nodeCreated(const ModelNode & /*createdNode*/)
{
}
@@ -134,6 +145,10 @@ void NavigatorView::nodeAboutToBeRemoved(const ModelNode &removedNode)
m_treeModel->removeSubTree(removedNode);
}
+void NavigatorView::nodeAboutToBeReparented(const ModelNode &/*node*/, const NodeAbstractProperty &/*newPropertyParent*/, const NodeAbstractProperty &/*oldPropertyParent*/, AbstractView::PropertyChangeFlags /*propertyChange*/)
+{
+}
+
void NavigatorView::nodeReparented(const ModelNode &node, const NodeAbstractProperty & /*newPropertyParent*/, const NodeAbstractProperty & /*oldPropertyParent*/, AbstractView::PropertyChangeFlags /*propertyChange*/)
{
bool blocked = blockSelectionChangedSignal(true);
@@ -198,6 +213,10 @@ void NavigatorView::instancePropertyChange(const QList<QPair<ModelNode, QString>
{
}
+void NavigatorView::instancesCompleted(const QVector<ModelNode> &/*completedNodeList*/)
+{
+}
+
void NavigatorView::nodeOrderChanged(const NodeListProperty &listProperty, const ModelNode &node, int oldIndex)
{
if (m_treeModel->isInTree(node))
diff --git a/src/plugins/qmldesigner/components/navigator/navigatorview.h b/src/plugins/qmldesigner/components/navigator/navigatorview.h
index 02a67a4f7c..d27e096d61 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatorview.h
+++ b/src/plugins/qmldesigner/components/navigator/navigatorview.h
@@ -66,6 +66,9 @@ public:
void modelAttached(Model *model);
void modelAboutToBeDetached(Model *model);
+ void importAdded(const Import &import);
+ void importRemoved(const Import &import);
+
void nodeCreated(const ModelNode &createdNode);
void nodeRemoved(const ModelNode &removedNode, const NodeAbstractProperty &parentProperty, PropertyChangeFlags propertyChange);
void propertiesRemoved(const QList<AbstractProperty> &propertyList);
@@ -73,9 +76,9 @@ public:
void bindingPropertiesChanged(const QList<BindingProperty> &propertyList, PropertyChangeFlags propertyChange);
void nodeAboutToBeRemoved(const ModelNode &removedNode);
- void nodeReparented(const ModelNode &node, const ModelNode &oldParent, const ModelNode &newParent);
void nodeOrderChanged(const NodeListProperty &listProperty, const ModelNode &movedNode, int oldIndex);
+ void nodeAboutToBeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange);
void nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange);
void rootNodeTypeChanged(const QString &type, int majorVersion, int minorVersion);
void nodeIdChanged(const ModelNode& node, const QString& newId, const QString& oldId);
@@ -86,6 +89,7 @@ public:
void auxiliaryDataChanged(const ModelNode &node, const QString &name, const QVariant &data);
void scriptFunctionsChanged(const ModelNode &node, const QStringList &scriptFunctionList);
void instancePropertyChange(const QList<QPair<ModelNode, QString> > &propertyList);
+ void instancesCompleted(const QVector<ModelNode> &completedNodeList);
private slots:
// void handleChangedItem(QStandardItem * item);
diff --git a/src/plugins/qmldesigner/components/propertyeditor/basiclayouts.h b/src/plugins/qmldesigner/components/propertyeditor/basiclayouts.h
index d2420b4a8d..d39bc36e7a 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/basiclayouts.h
+++ b/src/plugins/qmldesigner/components/propertyeditor/basiclayouts.h
@@ -172,9 +172,9 @@ public:
QT_END_NAMESPACE
-QML_DECLARE_TYPE(QBoxLayoutObject);
-QML_DECLARE_TYPE(QHBoxLayoutObject);
-QML_DECLARE_TYPE(QVBoxLayoutObject);
+QML_DECLARE_TYPE(QBoxLayoutObject)
+QML_DECLARE_TYPE(QHBoxLayoutObject)
+QML_DECLARE_TYPE(QVBoxLayoutObject)
class BasicLayouts {
diff --git a/src/plugins/qmldesigner/components/propertyeditor/basicwidgets.cpp b/src/plugins/qmldesigner/components/propertyeditor/basicwidgets.cpp
index d22c446ea6..ec87e5b8e7 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/basicwidgets.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/basicwidgets.cpp
@@ -652,7 +652,7 @@ public:
protected:
void paintEvent(QPaintEvent *event)
- {
+ {
QFontMetrics fm(font());
if (fm.width(text()) > (contentsRect().width() - 6) && text().length() > 4) {
QPainter p(this);
@@ -783,6 +783,43 @@ private:
QUrl _url;
};
+class AnimatedToolButton : public QToolButton
+{
+
+Q_OBJECT
+
+ Q_PROPERTY(QUrl hoverIconFromFile READ hoverIconFromFile WRITE setHoverIconFromFile)
+
+public:
+ AnimatedToolButton( QWidget * parent = 0 ) : QToolButton(parent)
+ {}
+
+private:
+ QUrl hoverIconFromFile() const
+ { return m_hoverIconUrl; }
+
+ void setHoverIconFromFile(const QUrl &url)
+ { m_hoverIconUrl= url;
+ m_hoverIcon = QIcon(m_hoverIconUrl.toLocalFile());
+ }
+
+ void leaveEvent(QEvent *)
+ {
+ setIcon(m_icon);
+ }
+
+ void enterEvent(QEvent *)
+ {
+ m_icon = icon();
+ setIcon(m_hoverIcon);
+ }
+
+ QUrl m_hoverIconUrl;
+ QIcon m_hoverIcon;
+ QIcon m_icon;
+
+};
+
class QComboBoxDeclarativeUI : public QObject
{
Q_OBJECT
@@ -1357,10 +1394,11 @@ public:
QT_END_NAMESPACE
-QML_DECLARE_TYPE(QTabObject);
-QML_DECLARE_TYPE(MyGroupBox);
-QML_DECLARE_TYPE(WidgetLoader);
-QML_DECLARE_TYPE(WidgetFrame);
+QML_DECLARE_TYPE(QTabObject)
+QML_DECLARE_TYPE(MyGroupBox)
+QML_DECLARE_TYPE(WidgetLoader)
+QML_DECLARE_TYPE(WidgetFrame)
+QML_DECLARE_TYPE(AnimatedToolButton)
void BasicWidgets::registerDeclarativeTypes()
{
@@ -1403,6 +1441,7 @@ void BasicWidgets::registerDeclarativeTypes()
qmlRegisterType<QFrame>("Bauhaus",1,0,"QFrame");
qmlRegisterType<WidgetFrame>("Bauhaus",1,0,"WidgetFrame");
qmlRegisterType<WidgetLoader>("Bauhaus",1,0,"WidgetLoader");
+ qmlRegisterType<AnimatedToolButton>("Bauhaus",1,0,"AnimatedToolButton");
qmlRegisterExtendedType<MyGroupBox,QGroupBoxDeclarativeUI>("Bauhaus",1,0,"QExtGroupBox");
qmlRegisterExtendedType<QTabWidget,QTabWidgetDeclarativeUI>("Bauhaus",1,0,"QTabWidget");
qmlRegisterExtendedType<QScrollArea,QScrollAreaDeclarativeUI>("Bauhaus",1,0,"QScrollArea");
diff --git a/src/plugins/qmldesigner/components/propertyeditor/basicwidgets.h b/src/plugins/qmldesigner/components/propertyeditor/basicwidgets.h
index eee24931fc..0b227b7163 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/basicwidgets.h
+++ b/src/plugins/qmldesigner/components/propertyeditor/basicwidgets.h
@@ -61,42 +61,42 @@
#include "filewidget.h"
#include "layoutwidget.h"
-QML_DECLARE_TYPE(QWidget);
+QML_DECLARE_TYPE(QWidget)
//display
-QML_DECLARE_TYPE(QLabel);
-QML_DECLARE_TYPE(QProgressBar);
-QML_DECLARE_TYPE(QLCDNumber);
+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);
+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);
+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);
+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 {
@@ -105,15 +105,15 @@ public:
Action(QObject *parent = 0) : QAction(parent) {}
};
-QML_DECLARE_TYPE(QMenu);
-QML_DECLARE_TYPE(Action);
+QML_DECLARE_TYPE(QMenu)
+QML_DECLARE_TYPE(Action)
-//QML_DECLARE_TYPE(QToolBox);
+//QML_DECLARE_TYPE(QToolBox)
//itemviews
-//QML_DECLARE_TYPE(QListView);
-//QML_DECLARE_TYPE(QTreeView);
-//QML_DECLARE_TYPE(QTableView);
+//QML_DECLARE_TYPE(QListView)
+//QML_DECLARE_TYPE(QTreeView)
+//QML_DECLARE_TYPE(QTableView)
//top-level windows?
class BasicWidgets {
diff --git a/src/plugins/qmldesigner/components/propertyeditor/behaviordialog.cpp b/src/plugins/qmldesigner/components/propertyeditor/behaviordialog.cpp
index 27679d1b8d..fcf5195b00 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/behaviordialog.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/behaviordialog.cpp
@@ -177,4 +177,4 @@ void BehaviorDialog::reject()
QDialog::reject();
}
-};
+}
diff --git a/src/plugins/qmldesigner/components/propertyeditor/behaviordialog.h b/src/plugins/qmldesigner/components/propertyeditor/behaviordialog.h
index 7f1d63d18b..832f10da26 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/behaviordialog.h
+++ b/src/plugins/qmldesigner/components/propertyeditor/behaviordialog.h
@@ -96,8 +96,8 @@ private:
};
-};
+}
-QML_DECLARE_TYPE(QmlDesigner::BehaviorWidget);
+QML_DECLARE_TYPE(QmlDesigner::BehaviorWidget)
#endif// BEHAVIORDIALOG_H
diff --git a/src/plugins/qmldesigner/components/propertyeditor/colorwidget.cpp b/src/plugins/qmldesigner/components/propertyeditor/colorwidget.cpp
deleted file mode 100644
index 6f97136909..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/colorwidget.cpp
+++ /dev/null
@@ -1,993 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#include "colorwidget.h"
-#include <modelnode.h>
-#include <abstractview.h>
-#include <nodeproperty.h>
-#include <nodelistproperty.h>
-#include <variantproperty.h>
-#include <qmlobjectnode.h>
-#include <qmlitemnode.h>
-#include <QGradient>
-#include <metainfo.h>
-#include <rewritingexception.h>
-
-#include <QHBoxLayout>
-#include <QLabel>
-#include <QToolButton>
-#include <QGradient>
-#include <QPainter>
-#include <QDoubleSpinBox>
-#include <QGridLayout>
-#include <QPushButton>
-#include <QDialogButtonBox>
-#include <QGraphicsEffect>
-#include <QMessageBox>
-
-static inline int clamp(int x, int lower, int upper)
-{
- if (x < lower)
- x = lower;
- if (x > upper)
- x = upper;
- return x;
-}
-
-static inline QString properName(const QColor &color)
-{
- QString s;
- if (color.alpha() == 255)
- s.sprintf("#%02x%02x%02x", color.red(), color.green(), color.blue());
- else
- s.sprintf("#%02x%02x%02x%02x", color.alpha(), color.red(), color.green(), color.blue());
- return s;
-}
-
-static inline QColor properColor(const QString &str)
-{
- if (str.isEmpty())
- return QColor();
- int lalpha = 255;
- QString lcolorStr = str;
- if (lcolorStr.at(0) == '#' && lcolorStr.length() == 9) {
- QString alphaStr = lcolorStr;
- alphaStr.truncate(3);
- lcolorStr.remove(0, 3);
- lcolorStr = "#" + lcolorStr;
- alphaStr.remove(0,1);
- bool v;
- lalpha = alphaStr.toInt(&v, 16);
- if (!v)
- lalpha = 255;
- }
- QColor lcolor(lcolorStr);
- if (lcolorStr.contains('#'))
- lcolor.setAlpha(lalpha);
- return lcolor;
-}
-
-static inline bool isColorString(const QString &colorString)
-{
- bool ok = true;
- if (colorString.size() == 9 && colorString.at(0) == QLatin1Char('#')) {
- // #rgba
- for (int i = 1; i < 9; ++i) {
- const QChar c = colorString.at(i);
- if ((c >= QLatin1Char('0') && c <= QLatin1Char('9'))
- || (c >= QLatin1Char('a') && c <= QLatin1Char('f'))
- || (c >= QLatin1Char('A') && c <= QLatin1Char('F')))
- continue;
- ok = false;
- break;
- }
- } else {
- ok = QColor::isValidColor(colorString);
- }
-
- return ok;
-}
-
-static inline QPixmap tilePixMap(int size)
-{
- const int checkerbordSize= size;
- 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);
- return tilePixmap;
-}
-
-namespace QmlDesigner {
-
-void ColorWidget::registerDeclarativeTypes() {
- qmlRegisterType<QmlDesigner::ColorButton>("Bauhaus",1,0,"ColorButton");
- qmlRegisterType<QmlDesigner::HueControl>("Bauhaus",1,0,"HueControl");
- qmlRegisterType<QmlDesigner::ColorBox>("Bauhaus",1,0,"ColorBox");
- qmlRegisterType<QmlDesigner::GradientLine>("Bauhaus",1,0,"GradientLine");
-}
-
-void ColorButton::setColor(const QString &colorStr)
-{
- if (m_colorString == colorStr)
- return;
-
-
- setEnabled(isColorString(colorStr));
-
- m_colorString = colorStr;
- update();
- emit colorChanged();
-}
-
-QColor ColorButton::convertedColor() const
-{
- return properColor(m_colorString);
-}
-
-void ColorButton::paintEvent(QPaintEvent *event)
-{
- QToolButton::paintEvent(event);
- if (!isEnabled())
- return;
-
- QColor color = properColor(m_colorString);
-
- QPainter p(this);
-
-
- QRect r(0, 0, width() - 2, height() - 2);
- p.drawTiledPixmap(r.adjusted(1, 1, -1, -1), tilePixMap(9));
- if (isEnabled())
- p.setBrush(color);
- else
- p.setBrush(Qt::transparent);
-
- if (color.value() > 80)
- p.setPen(QColor(0x444444));
- else
- p.setPen(QColor(0x9e9e9e));
- p.drawRect(r.translated(1, 1));
-
- if (m_showArrow) {
- p.setRenderHint(QPainter::Antialiasing, true);
- QVector<QPointF> points;
- if (isChecked()) {
- points.append(QPointF(2, 3));
- points.append(QPointF(8, 3));
- points.append(QPointF(5, 9));
- } else {
- points.append(QPointF(8, 6));
- points.append(QPointF(2, 9));
- points.append(QPointF(2, 3));
- }
- p.translate(0.5, 0.5);
- p.setBrush(QColor(0xaaaaaa));
- p.setPen(QColor(0x444444));
- p.drawPolygon(points);
- }
-}
-
-
-void HueControl::setCurrent(int y)
-{
- y = clamp(y, 0, 120);
- int oldAlpha = m_color.alpha();
- m_color.setHsv((y * 359)/120, m_color.hsvSaturation(), m_color.value());
- m_color.setAlpha(oldAlpha);
- update(); // redraw pointer
- emit hueChanged(m_color.hsvHue());
-}
-
-void HueControl::setHue(int newHue)
-{
- if (m_color.hsvHue() == newHue)
- return;
- m_color.setHsv(newHue, m_color.hsvSaturation(), m_color.value());
- update();
- emit hueChanged(m_color.hsvHue());
-}
-
-void HueControl::paintEvent(QPaintEvent *event)
-{
- QWidget::paintEvent(event);
-
- QPainter p(this);
-
- int localHeight = 120;
-
- if (m_cache.isNull()) {
- m_cache = QPixmap(10, localHeight);
-
- QPainter cacheP(&m_cache);
-
- for (int i = 0; i < localHeight; i++)
- {
- QColor c;
- c.setHsv( (i*359) / 120.0, 255,255);
- cacheP.fillRect(0, i, 10, i + 1, c);
- }
- }
-
- //p.setPen(QColor(0x404040));
- //p.drawRect(QRect(1, 1, width() - 1, height() - 1).adjusted(10, 5, -20, -5));
-
- p.drawPixmap(0, 5, m_cache);
-
- QVector<QPointF> points;
-
- int y = m_color.hueF() * 120 + 5;
-
- points.append(QPointF(5, y));
- points.append(QPointF(15, y + 5));
- points.append(QPointF(15, y - 5));
-
-
- p.setRenderHint(QPainter::Antialiasing, true);
- p.translate(0.5, 1.5);
- p.setPen(QColor(0, 0, 0, 120));
- p.drawPolygon(points);
- p.translate(0, -1);
- p.setPen(0x222222);
- p.setBrush(QColor(0x707070));
- p.drawPolygon(points);
-}
-
-void HueControl::mousePressEvent(QMouseEvent *e)
-{
- // The current cell marker is set to the cell the mouse is pressed in
- QPoint pos = e->pos();
- m_mousePressed = true;
- setCurrent(pos.y() - 5);
-}
-
-void HueControl::mouseReleaseEvent(QMouseEvent * /* event */)
-{
- m_mousePressed = false;
-}
-
-void HueControl::mouseMoveEvent(QMouseEvent *e)
-{
- if (!m_mousePressed)
- return;
- QPoint pos = e->pos();
- setCurrent(pos.y() - 5);
-}
-
-void ColorBox::setHue(int newHue)
-{
- if (m_color.hsvHue() == newHue)
- return;
-
- int oldAlpha = m_color.alpha();
- m_color.setHsv(newHue,m_color.hsvSaturation(),m_color.value());
- m_color.setAlpha(oldAlpha);
- update();
- emit hueChanged();
- emit colorChanged();
-}
-
-int ColorBox::hue() const
-{
- int retval = m_color.hsvHue();
- if (retval<0) retval=0;
- if (retval>359) retval=359;
- return retval;
-}
-
-void ColorBox::setAlpha(int newAlpha)
-{
- if (m_color.alpha() == newAlpha)
- return;
-
- m_color.setAlpha(newAlpha);
- update();
- emit alphaChanged();
- emit colorChanged();
-}
-
-QString ColorBox::strColor() const
-{
- return properName(m_color);
-}
-
-void ColorBox::setStrColor(const QString &colorStr)
-{
- if (properName(m_color) == colorStr)
- return;
-
- setColor(properColor(colorStr));
-}
-
-void ColorBox::setColor(const QColor &color)
-{
- if (m_color == color)
- return;
-
- int oldsaturation = m_color.hsvSaturation();
- int oldvalue = m_color.value();
- int oldhue = m_color.hsvHue();
- int oldAlpha = m_color.alpha();
- m_color=color;
- update();
- if (oldhue != m_color.hsvHue()) emit hueChanged();
- if (oldsaturation != saturation()) emit saturationChanged();
- if (oldvalue != value()) emit valueChanged();
- if (oldAlpha != alpha()) emit alphaChanged();
-}
-
-void ColorBox::setSaturation(int newsaturation)
-{
- if (m_color.hsvSaturation()==newsaturation) return;
- int oldAlpha = m_color.alpha();
- m_color.setHsv(m_color.hsvHue(),newsaturation,m_color.value());
- m_color.setAlpha(oldAlpha);
- update();
- emit saturationChanged();
- emit colorChanged();
-}
-
-void ColorBox::setCurrent(int x, int y)
-{
- QColor newColor;
- x = clamp(x, 0, 120);
- y = clamp(y, 0, 120);
- int oldAlpha = m_color.alpha();
- newColor.setHsv(hue(), (x*255) / 120, 255 - (y*255) / 120);
- newColor.setAlpha(oldAlpha);
- setColor(newColor);
-}
-
-void ColorBox::setValue(int newvalue)
-{
- if (m_color.value()==newvalue) return;
- int oldAlpha = m_color.alpha();
- m_color.setHsv(m_color.hsvHue(),m_color.hsvSaturation(),newvalue);
- m_color.setAlpha(oldAlpha);
- update();
- emit valueChanged();
- emit colorChanged();
-}
-
-void ColorBox::paintEvent(QPaintEvent *event)
-{
- QWidget::paintEvent(event);
-
- QPainter p(this);
-
- if ((m_color.saturation()>1) && (m_color.value()>1))
- m_saturatedColor.setHsv(m_color.hsvHue(),255,255);
-
- if ((hue() != m_lastHue) || (m_cache.isNull())) {
- m_lastHue = hue();
-
- int fixedHue = clamp(m_lastHue, 0, 359);
-
- m_cache = QPixmap(120, 120);
-
- int height = 120;
- int width = 120;
-
- QPainter chacheP(&m_cache);
-
- for (int y = 0; y < height; y++)
- for (int x = 0; x < width; x++)
- {
- QColor c;
- c.setHsv(fixedHue, (x*255) / width, 255 - (y*255) / height);
- chacheP.setPen(c);
- chacheP.drawPoint(x ,y);
- }
- }
- p.drawPixmap(5, 5, m_cache);
-
- int x = clamp(m_color.hsvSaturationF() * 120, 0, 119) + 5;
- int y = clamp(120 - m_color.valueF() * 120, 0, 119) + 5;
-
- p.setPen(QColor(255, 255, 255, 50));
- p.drawLine(5, y, x-1, y);
- p.drawLine(x+1, y, width()-7, y);
- p.drawLine(x, 5, x, y-1);
- p.drawLine(x, y+1, x, height()-7);
-
-}
-
-void ColorBox::mousePressEvent(QMouseEvent *e)
-{
- // The current cell marker is set to the cell the mouse is pressed in
- QPoint pos = e->pos();
- m_mousePressed = true;
- setCurrent(pos.x() - 5, pos.y() - 5);
-}
-
-void ColorBox::mouseReleaseEvent(QMouseEvent * /* event */)
-{
- if (m_mousePressed)
- emit colorChanged();
- m_mousePressed = false;
-}
-
-void ColorBox::mouseMoveEvent(QMouseEvent *e)
-{
- if (!m_mousePressed)
- return;
- QPoint pos = e->pos();
- setCurrent(pos.x() - 5, pos.y() - 5);
-}
-
-void GradientLine::setItemNode(const QVariant &itemNode)
-{
-
- if (!itemNode.value<ModelNode>().isValid())
- return;
- m_itemNode = itemNode.value<ModelNode>();
- m_useGradient = false;
- setupGradient();
- emit itemNodeChanged();
-}
-
-void GradientLine::setGradient(const QLinearGradient &gradient)
-{
- m_gradient = gradient;
- m_useGradient = false;
- setupGradient();
- emit gradientChanged();
-
-}
-
-static inline QColor invertColor(const QColor color)
-{
- QColor c = color.toHsv();
- c.setHsv(c.hue(), c.saturation(), 255 - c.value());
- return c;
-}
-
-GradientLine::GradientLine(QWidget *parent) :
- QWidget(parent),
- m_activeColor(Qt::black),
- m_gradientName("gradient"),
- m_colorIndex(0),
- m_dragActive(false),
- m_yOffset(0),
- m_create(false),
- m_active(false),
- m_dragOff(false),
- m_useGradient(true)
-{
- setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
- setFocusPolicy(Qt::StrongFocus);
- setFixedHeight(50);
- setMinimumWidth(160);
- resize(160, 50);
- m_colorList << m_activeColor << QColor(Qt::white);
- m_stops << 0 << 1;
- updateGradient();
- setCurrentIndex(0);
-}
-
-void GradientLine::setGradientName(const QString &newName)
-{
- if (newName == m_gradientName)
- return;
- m_gradientName = newName;
- setup();
- emit gradientNameChanged();
-}
-
-void GradientLine::setActiveColor(const QColor &newColor)
-{
- if (newColor.name() == m_activeColor.name() && newColor.alpha() == m_activeColor.alpha())
- return;
-
- m_activeColor = newColor;
- m_colorList.removeAt(currentColorIndex());
- m_colorList.insert(currentColorIndex(), m_activeColor);
- updateGradient();
- update();
-}
-
-void GradientLine::setupGradient()
-{
- if (m_useGradient) {
- m_colorList.clear();
- m_stops.clear();
- foreach (const QGradientStop &stop, m_gradient.stops()) {
- m_stops << stop.first;
- m_colorList << stop.second;
- }
- } else {
- ModelNode modelNode = m_itemNode.modelNode();
- if (!modelNode.isValid())
- return;
- m_colorList.clear();
- m_stops.clear();
-
- if (modelNode.hasProperty(m_gradientName)) { //gradient exists
-
- ModelNode gradientNode = modelNode.nodeProperty(m_gradientName).modelNode();
- QList<ModelNode> stopList = gradientNode.nodeListProperty("stops").toModelNodeList();
-
- foreach (const ModelNode &stopNode, stopList) {
- QmlObjectNode stopObjectNode = stopNode;
- if (stopObjectNode.isValid()) {
- m_stops << stopObjectNode.instanceValue("position").toReal();
- m_colorList << stopObjectNode.instanceValue("color").value<QColor>();
- }
- }
- } else {
- m_colorList << m_activeColor << QColor(Qt::black);
- m_stops << 0 << 1;
- }
- }
-}
-
-void GradientLine::deleteGradient()
-{
- if (!m_itemNode.isValid())
- return;
-
- if (!m_itemNode.modelNode().metaInfo().hasProperty(m_gradientName))
- return;
-
- ModelNode modelNode = m_itemNode.modelNode();
-
- if (m_itemNode.isInBaseState()) {
- if (modelNode.hasProperty(m_gradientName)) {
- RewriterTransaction transaction = m_itemNode.modelNode().view()->beginRewriterTransaction();
- ModelNode gradientNode = modelNode.nodeProperty(m_gradientName).modelNode();
- if (QmlObjectNode(gradientNode).isValid())
- QmlObjectNode(gradientNode).destroy();
- }
- }
-}
-
-bool GradientLine::event(QEvent *event)
-{
- if (event->type() == QEvent::ShortcutOverride)
- if (static_cast<QKeyEvent*>(event)->matches(QKeySequence::Delete)) {
- event->accept();
- return true;
- }
-
- return QWidget::event(event);
-}
-
-void GradientLine::keyPressEvent(QKeyEvent * event)
-{
- if (event->matches(QKeySequence::Delete)) {
- if ((currentColorIndex()) != 0 && (currentColorIndex() < m_stops.size() - 1)) {
- m_dragActive = false;
- m_stops.removeAt(currentColorIndex());
- m_colorList.removeAt(currentColorIndex());
- updateGradient();
- setCurrentIndex(0);
- //delete item
- }
- } else {
- QWidget::keyPressEvent(event);
- }
-}
-
-void GradientLine::paintEvent(QPaintEvent *event)
-{
- QWidget::paintEvent(event);
-
- QPainter p(this);
-
- if (!isEnabled()) {
- p.setBrush(Qt::NoBrush);
- p.setPen(QColor(0x444444));
- p.drawRect(9, 31, width() - 14, height() - 32);
-
- p.drawTiledPixmap(10, 32, width() - 16, height() - 34, tilePixMap(8));
- } else {
-
- QLinearGradient linearGradient(QPointF(0, 0), QPointF(width(), 0));
-
- for (int i =0; i < m_stops.size(); i++)
- linearGradient.setColorAt(m_stops.at(i), m_colorList.at(i));
-
- p.setBrush(Qt::NoBrush);
- p.setPen(QColor(0x444444));
- p.drawRect(9, 31, width() - 14, height() - 32);
-
-
- p.drawTiledPixmap(9, 31, width() - 16, height() - 34, tilePixMap(8));
-
- p.setBrush(linearGradient);
- p.setPen(QColor(0x222222));
- p.drawRect(8, 30, width() - 14, height() - 32);
- p.setPen(QColor(255, 255, 255, 40));
- p.drawRect(9, 31, width() - 16, height() - 34);
-
- p.setPen(Qt::black);
-
- for (int i =0; i < m_colorList.size(); i++) {
- int localYOffset = 0;
- QColor arrowColor(Qt::black);
- if (i == currentColorIndex()) {
- localYOffset = m_yOffset;
- arrowColor = QColor(0x909090);
- }
- p.setPen(arrowColor);
- if (i == 0 || i == (m_colorList.size() - 1))
- localYOffset = 0;
-
- int pos = qreal((width() - 16)) * m_stops.at(i) + 9;
- p.setBrush(arrowColor);
- QVector<QPointF> points;
- points.append(QPointF(pos + 0.5, 28.5 + localYOffset)); //triangle
- points.append(QPointF(pos - 3.5, 22.5 + localYOffset));
- points.append(QPointF(pos + 4.5, 22.5 + localYOffset));
- p.setRenderHint(QPainter::Antialiasing, true);
- p.drawPolygon(points);
- p.setRenderHint(QPainter::Antialiasing, false);
- p.setBrush(Qt::NoBrush);
- p.setPen(QColor(0x424242));
- p.drawRect(pos - 4, 9 + localYOffset, 10, 11);
-
- p.drawTiledPixmap(pos - 4, 9 + localYOffset, 9, 10, tilePixMap(5));
- p.setPen(QColor(0x424242));
- p.setBrush(m_colorList.at(i));
- p.drawRect(pos - 5, 8 + localYOffset, 10, 11);
- p.setBrush(Qt::NoBrush);
- p.setPen(QColor(255, 255, 255, 30));
- p.drawRect(pos - 4, 9 + localYOffset, 8, 9);
- }
- }
-}
-
-void GradientLine::mousePressEvent(QMouseEvent *event)
-{
- if (event->button() == Qt::LeftButton) {
- event->accept();
- int xPos = event->pos().x();
- int yPos = event->pos().y();
-
- int draggedIndex = -1;
- m_create = false;
- m_dragActive = false;
- if ((yPos > 10) && (yPos < 30))
- for (int i =0; i < m_stops.size(); i++) {
- int pos = qreal((width() - 16)) * m_stops.at(i) + 9;
- if (((xPos + 5) > pos) && ((xPos - 5) < pos)) {
- draggedIndex = i;
- m_dragActive = true;
- m_dragStart = event->pos();
- setCurrentIndex(draggedIndex);
- update();
- }
- }
- if (draggedIndex == -1)
- m_create = true;
- }
- setFocus(Qt::MouseFocusReason);
-}
-
-void GradientLine::mouseDoubleClickEvent(QMouseEvent *event)
-{
- event->accept();
- m_dragActive = false;
- m_create = false;
- emit openColorDialog(event->pos());
-}
-
-void GradientLine::mouseReleaseEvent(QMouseEvent *event)
-{
- if (event->button() == Qt::LeftButton) {
- event->accept();
- if (m_dragActive == false && m_create) {
- qreal stopPos = qreal(event->pos().x() - 9) / qreal((width() - 15));
- int index = -1;
- for (int i =0; i < m_stops.size() - 1; i++) {
- if ((stopPos > m_stops.at(i)) && (index == -1))
- index = i +1;
- }
- if (index != -1 && (m_useGradient || m_itemNode.isInBaseState())) { //creating of items only in base state
- m_stops.insert(index, stopPos);
- m_colorList.insert(index, QColor(Qt::white));
- setCurrentIndex(index);
- }
- }
- }
- m_dragActive = false;
- m_yOffset = 0;
- updateGradient();
- update();
- setFocus(Qt::MouseFocusReason);
-}
-
-void GradientLine::mouseMoveEvent(QMouseEvent *event)
-{
- if (m_dragActive) {
- event->accept();
- int xPos = event->pos().x();
- int pos = qreal((width() - 20)) * m_stops.at(currentColorIndex()) + 8;
- int offset = m_dragOff ? 2 : 20;
- if (xPos < pos + offset && xPos > pos - offset) {
- m_dragOff = false;
- int xDistance = event->pos().x() - m_dragStart.x();
- qreal distance = qreal(xDistance) / qreal((width() - 20));
- qreal newStop = m_stops.at(currentColorIndex()) + distance;
- if ((newStop >=0) && (newStop <= 1))
- m_stops[currentColorIndex()] = newStop;
- m_yOffset += event->pos().y() - m_dragStart.y();
- if (m_yOffset > 0 || !(m_itemNode.isInBaseState() || m_useGradient)) { //deleting only in base state
- m_yOffset = 0;
- } else if ((m_yOffset < - 12) && (currentColorIndex()) != 0 && (currentColorIndex() < m_stops.size() - 1)) {
- m_yOffset = 0;
- m_dragActive = false;
- m_stops.removeAt(currentColorIndex());
- m_colorList.removeAt(currentColorIndex());
- updateGradient();
- setCurrentIndex(0);
- //delete item
- }
- } else {
- m_dragOff = true;
- }
- m_dragStart = event->pos();
- update();
- }
-}
-
-void GradientLine::setup()
-{
-
-}
-
-static inline QColor normalizeColor(const QColor &color)
-{
- QColor newColor = QColor(color.name());
- newColor.setAlpha(color.alpha());
- return newColor;
-}
-
-static inline qreal roundReal(qreal real)
-{
- int i = real * 100;
- return qreal(i) / 100;
-}
-
-void GradientLine::updateGradient()
-{
- if (m_useGradient) {
- QGradientStops stops;
- for (int i = 0;i < m_stops.size(); i++) {
- stops.append(QPair<qreal, QColor>(m_stops.at(i), m_colorList.at(i)));
- }
- m_gradient.setStops(stops);
- emit gradientChanged();
- } else {
- if (!active())
- return;
- try {
- RewriterTransaction transaction = m_itemNode.modelNode().view()->beginRewriterTransaction();
- if (!m_itemNode.isValid())
- return;
-
- if (!m_itemNode.modelNode().metaInfo().hasProperty(m_gradientName))
- return;
-
- ModelNode modelNode = m_itemNode.modelNode();
-
- QString oldId;
- if (m_itemNode.isInBaseState()) {
- if (modelNode.hasProperty(m_gradientName)) {
- oldId = modelNode.nodeProperty(m_gradientName).modelNode().id();
- modelNode.removeProperty(m_gradientName);
- }
-
- ModelNode gradientNode = modelNode.view()->createModelNode("Qt/Gradient", 4, 7);
-
- if (!oldId.isNull())
- gradientNode.setId(oldId);
-
- for (int i = 0;i < m_stops.size(); i++) {
- ModelNode gradientStopNode = modelNode.view()->createModelNode("Qt/GradientStop", 4, 7);
- gradientStopNode.variantProperty("position") = roundReal(m_stops.at(i));
- gradientStopNode.variantProperty("color") = normalizeColor(m_colorList.at(i));
- gradientNode.nodeListProperty("stops").reparentHere(gradientStopNode);
- }
- modelNode.nodeProperty(m_gradientName).reparentHere(gradientNode);
- } else { //state
- if (!modelNode.hasProperty(m_gradientName)) {
- qWarning(" GradientLine::updateGradient: no gradient in state");
- return;
- }
- ModelNode gradientNode = modelNode.nodeProperty(m_gradientName).modelNode();
- QList<ModelNode> stopList = gradientNode.nodeListProperty("stops").toModelNodeList();
- for (int i = 0;i < m_stops.size(); i++) {
- QmlObjectNode stopObjectNode = stopList.at(i);
- stopObjectNode.setVariantProperty("position", roundReal(m_stops.at(i)));
- stopObjectNode.setVariantProperty("color", normalizeColor(m_colorList.at(i)));
- }
- }
- }
- catch (RewritingException &e) {
- QMessageBox::warning(0, "Error", e.description());
- }
- }
-}
-
-void GradientLine::setCurrentIndex(int i)
-{
- if (i == m_colorIndex)
- return;
- m_colorIndex = i;
- m_activeColor = m_colorList.at(i);
- emit activeColorChanged();
- update();
-}
-
-BauhausColorDialog::BauhausColorDialog(QWidget *parent) : QFrame(parent )
-{
-
- setFrameStyle(QFrame::NoFrame);
- setFrameShape(QFrame::StyledPanel);
- setFrameShadow(QFrame::Sunken);
-
- QGraphicsDropShadowEffect *dropShadowEffect = new QGraphicsDropShadowEffect;
- dropShadowEffect->setBlurRadius(6);
- dropShadowEffect->setOffset(2, 2);
- setGraphicsEffect(dropShadowEffect);
- setAutoFillBackground(true);
-
- m_hueControl = new HueControl(this);
- m_colorBox = new ColorBox(this);
-
- QWidget *colorFrameWidget = new QWidget(this);
- QVBoxLayout* vBox = new QVBoxLayout(colorFrameWidget);
- colorFrameWidget->setLayout(vBox);
- vBox->setSpacing(0);
- vBox->setMargin(0);
- vBox->setContentsMargins(0,5,0,28);
-
- m_beforeColorWidget = new QFrame(colorFrameWidget);
- m_beforeColorWidget->setFixedSize(30, 18);
- m_beforeColorWidget->setAutoFillBackground(true);
- //m_beforeColorWidget->setFrameShape(QFrame::StyledPanel);
- m_currentColorWidget = new QFrame(colorFrameWidget);
- m_currentColorWidget->setFixedSize(30, 18);
- m_currentColorWidget->setAutoFillBackground(true);
- //m_currentColorWidget->setFrameShape(QFrame::StyledPanel);
-
- vBox->addWidget(m_beforeColorWidget);
- vBox->addWidget(m_currentColorWidget);
-
-
- m_rSpinBox = new QDoubleSpinBox(this);
- m_gSpinBox = new QDoubleSpinBox(this);
- m_bSpinBox = new QDoubleSpinBox(this);
- m_alphaSpinBox = new QDoubleSpinBox(this);
-
- QGridLayout *gridLayout = new QGridLayout(this);
- gridLayout->setSpacing(4);
- gridLayout->setVerticalSpacing(4);
- gridLayout->setMargin(4);
- setLayout(gridLayout);
-
- gridLayout->addWidget(m_colorBox, 0, 0, 4, 1);
- gridLayout->addWidget(m_hueControl, 0, 1, 4, 1);
-
- gridLayout->addWidget(colorFrameWidget, 0, 2, 2, 1);
-
-
- gridLayout->addWidget(new QLabel("R", this), 0, 3, 1, 1);
- gridLayout->addWidget(new QLabel("G", this), 1, 3, 1, 1);
- gridLayout->addWidget(new QLabel("B", this), 2, 3, 1, 1);
- gridLayout->addWidget(new QLabel("A", this), 3, 3, 1, 1);
-
- gridLayout->addWidget(m_rSpinBox, 0, 4, 1, 1);
- gridLayout->addWidget(m_gSpinBox, 1, 4, 1, 1);
- gridLayout->addWidget(m_bSpinBox, 2, 4, 1, 1);
- gridLayout->addWidget(m_alphaSpinBox, 3, 4, 1, 1);
-
- QDialogButtonBox *buttonBox = new QDialogButtonBox(this);
-
- QPushButton *cancelButton = buttonBox->addButton(QDialogButtonBox::Cancel);
- QPushButton *applyButton = buttonBox->addButton(QDialogButtonBox::Apply);
-
- gridLayout->addWidget(buttonBox, 4, 0, 1, 2);
-
- resize(sizeHint());
-
- connect(m_colorBox, SIGNAL(colorChanged()), this, SLOT(onColorBoxChanged()));
- connect(m_alphaSpinBox, SIGNAL(valueChanged(double)), this, SLOT(spinBoxChanged()));
- connect(m_rSpinBox, SIGNAL(valueChanged(double)), this, SLOT(spinBoxChanged()));
- connect(m_gSpinBox, SIGNAL(valueChanged(double)), this, SLOT(spinBoxChanged()));
- connect(m_bSpinBox, SIGNAL(valueChanged(double)), this, SLOT(spinBoxChanged()));
- connect(m_hueControl, SIGNAL(hueChanged(int)), this, SLOT(onHueChanged(int)));
-
- connect(applyButton, SIGNAL(pressed()), this, SLOT(onAccept()));
- connect(cancelButton, SIGNAL(pressed()), this, SIGNAL(rejected()));
-
- m_alphaSpinBox->setMaximum(1);
- m_rSpinBox->setMaximum(1);
- m_gSpinBox->setMaximum(1);
- m_bSpinBox->setMaximum(1);
- m_alphaSpinBox->setSingleStep(0.1);
- m_rSpinBox->setSingleStep(0.1);
- m_gSpinBox->setSingleStep(0.1);
- m_bSpinBox->setSingleStep(0.1);
-
- m_blockUpdate = false;
-
-}
-
-void BauhausColorDialog::setupColor(const QColor &color)
-{
- QPalette pal = m_beforeColorWidget->palette();
- pal.setColor(QPalette::Background, color);
- m_beforeColorWidget->setPalette(pal);
- setColor(color);
-}
-
-void BauhausColorDialog::spinBoxChanged()
-{
- if (m_blockUpdate)
- return;
- QColor newColor;
- newColor.setAlphaF(m_alphaSpinBox->value());
- newColor.setRedF(m_rSpinBox->value());
- newColor.setGreenF(m_gSpinBox->value());
- newColor.setBlueF(m_bSpinBox->value());
- setColor(newColor);
-}
-
-void BauhausColorDialog::onColorBoxChanged()
-{
- if (m_blockUpdate)
- return;
-
- setColor(m_colorBox->color());
-}
-
-void BauhausColorDialog::setupWidgets()
-{
- m_blockUpdate = true;
- m_hueControl->setHue(m_color.hsvHue());
- m_alphaSpinBox->setValue(m_color.alphaF());
- m_rSpinBox->setValue(m_color.redF());
- m_gSpinBox->setValue(m_color.greenF());
- m_bSpinBox->setValue(m_color.blueF());
- m_colorBox->setColor(m_color);
- QPalette pal = m_currentColorWidget->palette();
- pal.setColor(QPalette::Background, m_color);
- m_currentColorWidget->setPalette(pal);
- m_blockUpdate = false;
-}
-
-}
diff --git a/src/plugins/qmldesigner/components/propertyeditor/colorwidget.h b/src/plugins/qmldesigner/components/propertyeditor/colorwidget.h
deleted file mode 100644
index 64e7a86989..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/colorwidget.h
+++ /dev/null
@@ -1,322 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#ifndef COLORWIDGET_H
-#define COLORWIDGET_H
-
-#include <QWeakPointer>
-#include <QtGui/QWidget>
-#include <QLabel>
-#include <QToolButton>
-#include <QMouseEvent>
-#include <modelnode.h>
-#include <qdeclarative.h>
-#include <propertyeditorvalue.h>
-#include <qmlitemnode.h>
-#include <QDialog>
-#include <QLinearGradient>
-
-QT_BEGIN_NAMESPACE
-class QtColorButton;
-class QToolButton;
-class QDoubleSpinBox;
-QT_END_NAMESPACE
-
-namespace QmlDesigner {
-
-class ColorButton : public QToolButton {
-
-Q_OBJECT
-
-Q_PROPERTY(QString color READ color WRITE setColor NOTIFY colorChanged)
-Q_PROPERTY(bool noColor READ noColor WRITE setNoColor)
-Q_PROPERTY(bool showArrow READ showArrow WRITE setShowArrow)
-
-public:
- ColorButton(QWidget *parent = 0) : QToolButton (parent), m_colorString("#ffffff"), m_noColor(false), m_showArrow(true) {}
-
- void setColor(const QString &colorStr);
- QString color() const { return m_colorString; }
- QColor convertedColor() const;
- bool noColor() const { return m_noColor; }
- void setNoColor(bool f) { m_noColor = f; update(); }
- bool showArrow() const { return m_showArrow; }
- void setShowArrow(bool b) { m_showArrow = b; }
-
-signals:
- void colorChanged();
-
-protected:
- void paintEvent(QPaintEvent *event);
-private:
- QString m_colorString;
- bool m_noColor;
- bool m_showArrow;
-};
-
-class ColorBox : public QWidget
-{
-Q_OBJECT
-
-Q_PROPERTY(QString strColor READ strColor WRITE setStrColor NOTIFY colorChanged)
-Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
-Q_PROPERTY(int hue READ hue WRITE setHue NOTIFY hueChanged)
-Q_PROPERTY(int saturation READ saturation WRITE setSaturation NOTIFY saturationChanged)
-Q_PROPERTY(int value READ value WRITE setValue NOTIFY valueChanged)
-Q_PROPERTY(int alpha READ alpha WRITE setAlpha NOTIFY alphaChanged)
-
-public:
- ColorBox(QWidget *parent = 0) : QWidget(parent), m_color(Qt::white), m_saturatedColor(Qt::white), m_lastHue(0)
- {
- setFixedWidth(130);
- setFixedHeight(130);
- }
-
- void setHue(int newHue);
- int hue() const;
- void setAlpha(int newAlpha);
- int alpha() const { return m_color.alpha(); }
- void setStrColor(const QString &colorStr);
- void setColor(const QColor &color);
- QString strColor() const;
- QColor color() const { return m_color; }
- int saturation() const { return m_color.hsvSaturation(); }
- void setSaturation(int newsaturation);
- int value() const { return m_color.value(); }
- void setValue(int newvalue);
-
-signals:
- void colorChanged();
- void hueChanged();
- void saturationChanged();
- void valueChanged();
- void alphaChanged();
-
-protected:
- void paintEvent(QPaintEvent *event);
-
- void mousePressEvent(QMouseEvent *);
- void mouseReleaseEvent(QMouseEvent *);
- void mouseMoveEvent(QMouseEvent *);
- void setCurrent(int x, int y);
-
-private:
- QColor m_color;
- QColor m_saturatedColor;
- bool m_mousePressed;
- int m_lastHue;
- QPixmap m_cache;
-};
-
-class HueControl : public QWidget
-{
-Q_OBJECT
-
-Q_PROPERTY(qreal hue READ hue WRITE setHue NOTIFY hueChanged)
-
-public:
-
- HueControl(QWidget *parent = 0) : QWidget(parent), m_color(Qt::white), m_mousePressed(false)
- {
- setFixedWidth(28);
- setFixedHeight(130);
- }
-
- void setHue(int newHue);
- int hue() const { return m_color.hsvHue(); }
-
-signals:
- void hueChanged(int hue);
-
-protected:
- void paintEvent(QPaintEvent *);
- void mousePressEvent(QMouseEvent *);
- void mouseReleaseEvent(QMouseEvent *);
- void mouseMoveEvent(QMouseEvent *);
- void setCurrent(int y);
-
-private:
- QColor m_color;
- bool m_mousePressed;
- QPixmap m_cache;
-};
-
-class GradientLine : public QWidget {
-
- Q_OBJECT
- Q_PROPERTY(QColor activeColor READ activeColor WRITE setActiveColor NOTIFY activeColorChanged)
- Q_PROPERTY(QVariant itemNode READ itemNode WRITE setItemNode NOTIFY itemNodeChanged)
- Q_PROPERTY(QString gradientName READ gradientName WRITE setGradientName NOTIFY gradientNameChanged)
- Q_PROPERTY(bool active READ active WRITE setActive)
- Q_PROPERTY(QLinearGradient gradient READ gradient WRITE setGradient NOTIFY gradientChanged)
-
-public:
- GradientLine(QWidget *parent = 0);
-
- QVariant itemNode() const { return QVariant::fromValue(m_itemNode.modelNode()); }
- void setItemNode(const QVariant &itemNode);
- QString gradientName() const { return m_gradientName; }
- void setGradientName(const QString &newName);
- QColor activeColor() const { return m_activeColor; }
- void setActiveColor(const QColor &newColor);
- bool active() const { return m_active; }
- void setActive(bool a) { m_active = a; }
- QLinearGradient gradient() const { return m_gradient; }
- void setGradient(const QLinearGradient &);
-
-public slots:
- void setupGradient();
- void deleteGradient();
-
-signals:
- void activeColorChanged();
- void itemNodeChanged();
- void gradientNameChanged();
- void gradientChanged();
- void openColorDialog(const QPoint &pos);
-protected:
- bool event(QEvent *event);
- void keyPressEvent(QKeyEvent * event);
- void paintEvent(QPaintEvent *event);
- void mousePressEvent(QMouseEvent *event);
- void mouseDoubleClickEvent(QMouseEvent *event);
- void mouseReleaseEvent(QMouseEvent *);
- void mouseMoveEvent(QMouseEvent *);
-
-private:
- void setup();
- void updateGradient();
- int currentColorIndex() const { return m_colorIndex; }
- void setCurrentIndex(int i);
-
- QColor m_activeColor;
- QmlItemNode m_itemNode;
- QString m_gradientName;
- QList<QColor> m_colorList;
- QList<qreal> m_stops;
- int m_colorIndex;
- bool m_dragActive;
- QPoint m_dragStart;
- QLinearGradient m_gradient;
- int m_yOffset;
- bool m_create;
- bool m_active;
- bool m_dragOff;
- bool m_useGradient;
-
-};
-
-class BauhausColorDialog : public QFrame {
-
- Q_OBJECT
-
- Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
-
-public:
- BauhausColorDialog(QWidget *parent = 0);
-
- QColor color() const { return m_color; }
-
- void setupColor(const QColor &color);
-
- void setColor(const QColor &color)
- {
- if (color == m_color)
- return;
-
- m_color = color;
- setupWidgets();
- emit colorChanged();
- }
-
-public slots:
- void changeColor(const QColor &color) { setColor(color); }
- void spinBoxChanged();
- void onColorBoxChanged();
- void onHueChanged(int newHue)
- {
- if (m_blockUpdate)
- return;
-
- if (m_color.hsvHue() == newHue)
- return;
- m_color.setHsv(newHue, m_color.hsvSaturation(), m_color.value());
- setupWidgets();
- emit colorChanged();
- }
- void onAccept()
- {
- emit accepted(m_color);
- }
-
-signals:
- void colorChanged();
- void accepted(const QColor &color);
- void rejected();
-
-protected:
- void setupWidgets();
-
-private:
- QFrame *m_beforeColorWidget;
- QFrame *m_currentColorWidget;
- ColorBox *m_colorBox;
- HueControl *m_hueControl;
-
- QDoubleSpinBox *m_rSpinBox;
- QDoubleSpinBox *m_gSpinBox;
- QDoubleSpinBox *m_bSpinBox;
- QDoubleSpinBox *m_alphaSpinBox;
-
- QColor m_color;
- bool m_blockUpdate;
-
-};
-
-
-class ColorWidget {
-
-public:
- static void registerDeclarativeTypes();
-
-
-};
-
-
-} //QmlDesigner
-
-QML_DECLARE_TYPE(QmlDesigner::ColorButton);
-QML_DECLARE_TYPE(QmlDesigner::HueControl);
-QML_DECLARE_TYPE(QmlDesigner::ColorBox);
-
-#endif //COLORWIDGET_H
diff --git a/src/plugins/qmldesigner/components/propertyeditor/fontwidget.h b/src/plugins/qmldesigner/components/propertyeditor/fontwidget.h
index b17d559017..a11d09f618 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/fontwidget.h
+++ b/src/plugins/qmldesigner/components/propertyeditor/fontwidget.h
@@ -102,6 +102,6 @@ private: //variables
} // namespace QmlDesigner
-QML_DECLARE_TYPE(QmlDesigner::FontWidget);
+QML_DECLARE_TYPE(QmlDesigner::FontWidget)
#endif // FONTWIDGET_H
diff --git a/src/plugins/qmldesigner/components/propertyeditor/gradientdialog.cpp b/src/plugins/qmldesigner/components/propertyeditor/gradientdialog.cpp
deleted file mode 100644
index 9ab1786c61..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/gradientdialog.cpp
+++ /dev/null
@@ -1,353 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 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
deleted file mode 100644
index 5c9b91ad39..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/gradientdialog.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 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
deleted file mode 100644
index 5edeb799d6..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/gradientdialog.ui
+++ /dev/null
@@ -1,122 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <comment>*********************************************************************
-**
-** Copyright (C) 2010 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
deleted file mode 100644
index 7b6401847b..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/gradienteditor.cpp
+++ /dev/null
@@ -1,933 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 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
deleted file mode 100644
index b6b0fe056a..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/gradienteditor.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 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
deleted file mode 100644
index 7c152c9873..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/gradienteditor.ui
+++ /dev/null
@@ -1,1255 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <comment>*********************************************************************
-**
-** Copyright (C) 2010 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/gradientlineqmladaptor.cpp b/src/plugins/qmldesigner/components/propertyeditor/gradientlineqmladaptor.cpp
new file mode 100644
index 0000000000..67b1dfcc5a
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/gradientlineqmladaptor.cpp
@@ -0,0 +1,153 @@
+#include "gradientlineqmladaptor.h"
+
+#include <qdeclarative.h>
+#include <QMessageBox>
+
+#include <nodeproperty.h>
+#include <nodelistproperty.h>
+#include <nodemetainfo.h>
+#include <abstractview.h>
+#include <rewritingexception.h>
+#include <variantproperty.h>
+
+namespace QmlDesigner {
+
+GradientLineQmlAdaptor::GradientLineQmlAdaptor(QWidget *parent) :
+ QmlEditorWidgets::GradientLine(parent)
+{
+ connect(this, SIGNAL(gradientChanged()), this, SLOT(writeGradient()));
+}
+
+void GradientLineQmlAdaptor::setItemNode(const QVariant &itemNode)
+{
+
+ if (!itemNode.value<ModelNode>().isValid())
+ return;
+ m_itemNode = itemNode.value<ModelNode>();
+ setupGradient();
+ emit itemNodeChanged();
+}
+
+static inline QColor normalizeColor(const QColor &color)
+{
+ QColor newColor = QColor(color.name());
+ newColor.setAlpha(color.alpha());
+ return newColor;
+}
+
+static inline qreal roundReal(qreal real)
+{
+ int i = real * 100;
+ return qreal(i) / 100;
+}
+
+void GradientLineQmlAdaptor::setupGradient()
+{
+ ModelNode modelNode = m_itemNode.modelNode();
+ QLinearGradient newGradient;
+ QVector<QGradientStop> stops;
+
+ if (!modelNode.isValid())
+ return;
+
+ if (modelNode.hasProperty(gradientName())) { //gradient exists
+
+ ModelNode gradientNode = modelNode.nodeProperty(gradientName()).modelNode();
+ QList<ModelNode> stopList = gradientNode.nodeListProperty("stops").toModelNodeList();
+
+ foreach (const ModelNode &stopNode, stopList) {
+ QmlObjectNode stopObjectNode = stopNode;
+ if (stopObjectNode.isValid()) {
+ qreal position = stopObjectNode.instanceValue("position").toReal();
+ QColor color = stopObjectNode.instanceValue("color").value<QColor>();
+ stops.append( QPair<qreal, QColor>(position, color));
+ }
+ }
+ } else {
+ stops.append( QPair<qreal, QColor>(0, activeColor()));
+ stops.append( QPair<qreal, QColor>(1, QColor(Qt::black)));
+ }
+
+ newGradient.setStops(stops);
+ setGradient(newGradient);
+}
+
+void GradientLineQmlAdaptor::writeGradient()
+{
+ if (!active())
+ return;
+
+ if (!m_itemNode.isValid())
+ return;
+
+ if (!m_itemNode.modelNode().metaInfo().hasProperty(gradientName()))
+ return;
+ try {
+ RewriterTransaction transaction = m_itemNode.modelNode().view()->beginRewriterTransaction();
+
+ ModelNode modelNode = m_itemNode.modelNode();
+
+ QString oldId;
+ QVector<QGradientStop> stops = gradient().stops();
+ if (m_itemNode.isInBaseState()) {
+ if (modelNode.hasProperty(gradientName())) {
+ oldId = modelNode.nodeProperty(gradientName()).modelNode().id();
+ modelNode.removeProperty(gradientName());
+ }
+
+ ModelNode gradientNode = modelNode.view()->createModelNode("Qt/Gradient", 4, 7);
+
+ if (!oldId.isNull())
+ gradientNode.setId(oldId);
+
+ for (int i = 0;i < stops.size(); i++) {
+ ModelNode gradientStopNode = modelNode.view()->createModelNode("Qt/GradientStop", 4, 7);
+ gradientStopNode.variantProperty("position") = roundReal(stops.at(i).first);
+ gradientStopNode.variantProperty("color") = normalizeColor(stops.at(i).second);
+ gradientNode.nodeListProperty("stops").reparentHere(gradientStopNode);
+ }
+ modelNode.nodeProperty(gradientName()).reparentHere(gradientNode);
+ } else { //state
+ if (!modelNode.hasProperty(gradientName())) {
+ qWarning(" GradientLine::updateGradient: no gradient in state");
+ return;
+ }
+ ModelNode gradientNode = modelNode.nodeProperty(gradientName()).modelNode();
+ QList<ModelNode> stopList = gradientNode.nodeListProperty("stops").toModelNodeList();
+ for (int i = 0;i < stops.size(); i++) {
+ QmlObjectNode stopObjectNode = stopList.at(i);
+ stopObjectNode.setVariantProperty("position", roundReal(stops.at(i).first));
+ stopObjectNode.setVariantProperty("color", normalizeColor(stops.at(i).second));
+ }
+ }
+ }
+ catch (RewritingException &e) {
+ QMessageBox::warning(0, "Error", e.description());
+ }
+}
+
+void GradientLineQmlAdaptor::deleteGradient()
+{
+ if (!m_itemNode.isValid())
+ return;
+
+ if (!m_itemNode.modelNode().metaInfo().hasProperty(gradientName()))
+ return;
+
+ ModelNode modelNode = m_itemNode.modelNode();
+
+ if (m_itemNode.isInBaseState()) {
+ if (modelNode.hasProperty(gradientName())) {
+ RewriterTransaction transaction = m_itemNode.modelNode().view()->beginRewriterTransaction();
+ ModelNode gradientNode = modelNode.nodeProperty(gradientName()).modelNode();
+ if (QmlObjectNode(gradientNode).isValid())
+ QmlObjectNode(gradientNode).destroy();
+ }
+ }
+}
+
+void GradientLineQmlAdaptor::registerDeclarativeType() {
+ qmlRegisterType<QmlDesigner::GradientLineQmlAdaptor>("Bauhaus",1,0,"GradientLine");
+}
+
+} //QmlDesigner
diff --git a/src/plugins/qmldesigner/components/propertyeditor/gradientlineqmladaptor.h b/src/plugins/qmldesigner/components/propertyeditor/gradientlineqmladaptor.h
new file mode 100644
index 0000000000..5923f528c2
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/gradientlineqmladaptor.h
@@ -0,0 +1,39 @@
+#ifndef GRADIENTLINEQMLADAPTOR_H
+#define GRADIENTLINEQMLADAPTOR_H
+
+#include <qmleditorwidgets/gradientline.h>
+#include <propertyeditorvalue.h>
+#include <qmlitemnode.h>
+
+namespace QmlDesigner {
+
+class GradientLineQmlAdaptor : public QmlEditorWidgets::GradientLine
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QVariant itemNode READ itemNode WRITE setItemNode NOTIFY itemNodeChanged)
+
+public:
+ explicit GradientLineQmlAdaptor(QWidget *parent = 0);
+
+ static void registerDeclarativeType();
+
+signals:
+ void itemNodeChanged();
+
+public slots:
+ void setupGradient();
+ void writeGradient();
+ void deleteGradient();
+
+private:
+ QVariant itemNode() const { return QVariant::fromValue(m_itemNode.modelNode()); }
+ void setItemNode(const QVariant &itemNode);
+
+ QmlItemNode m_itemNode;
+
+};
+
+} //QmlDesigner
+
+#endif // GRADIENTLINEQMLADAPTOR_H
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.cpp
index f3f3a076da..4515ea2656 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.cpp
@@ -36,13 +36,10 @@
#include <nodemetainfo.h>
#include <metainfo.h>
-#include <propertymetainfo.h>
-
#include <invalididexception.h>
#include <rewritingexception.h>
#include <invalidnodestateexception.h>
#include <variantproperty.h>
-#include <propertymetainfo.h>
#include <bindingproperty.h>
@@ -54,7 +51,8 @@
#include "basicwidgets.h"
#include "resetwidget.h"
#include "qlayoutobject.h"
-#include "colorwidget.h"
+#include <qmleditorwidgets/colorwidgets.h>
+#include "gradientlineqmladaptor.h"
#include "behaviordialog.h"
#include "qproxylayoutitem.h"
#include "fontwidget.h"
@@ -67,6 +65,7 @@
#include <QtCore/QFileSystemWatcher>
#include <QtCore/QFileInfo>
#include <QtCore/QDebug>
+#include <QtCore/QTimer>
#include <QtDeclarative/QDeclarativeView>
#include <QtDeclarative/QDeclarativeContext>
#include <QtGui/QVBoxLayout>
@@ -179,7 +178,7 @@ void PropertyEditor::NodeType::setup(const QmlObjectNode &fxObjectNode, const QS
QDeclarativeContext *ctxt = m_view->rootContext();
if (fxObjectNode.isValid()) {
- foreach (const QString &propertyName, fxObjectNode.modelNode().metaInfo().properties(true).keys())
+ foreach (const QString &propertyName, fxObjectNode.modelNode().metaInfo().propertyNames())
createPropertyEditorValue(fxObjectNode, propertyName, fxObjectNode.instanceValue(propertyName), &m_backendValuesPropertyMap, propertyEditor);
// className
@@ -229,10 +228,10 @@ void PropertyEditor::NodeType::initialSetup(const QString &typeName, const QUrl
{
QDeclarativeContext *ctxt = m_view->rootContext();
- NodeMetaInfo metaInfo = propertyEditor->model()->metaInfo().nodeMetaInfo(typeName, 4, 7);
+ NodeMetaInfo metaInfo = propertyEditor->model()->metaInfo(typeName, 4, 7);
- foreach (const QString &propertyName, metaInfo.properties(true).keys())
- setupPropertyEditorValue(propertyName, &m_backendValuesPropertyMap, propertyEditor, metaInfo.property(propertyName, true).type());
+ foreach (const QString &propertyName, metaInfo.propertyNames())
+ setupPropertyEditorValue(propertyName, &m_backendValuesPropertyMap, propertyEditor, metaInfo.propertyTypeName(propertyName));
PropertyEditorValue *valueObject = qobject_cast<PropertyEditorValue*>(QDeclarativeMetaType::toQObject(m_backendValuesPropertyMap.value("className")));
if (!valueObject)
@@ -273,7 +272,9 @@ PropertyEditor::PropertyEditor(QWidget *parent) :
m_timerId(0),
m_stackedWidget(new StackedWidget(parent)),
m_currentType(0),
- m_locked(false)
+ m_locked(false),
+ m_setupCompleted(false),
+ m_singleShotTimer(new QTimer(this))
{
m_updateShortcut = new QShortcut(QKeySequence("F5"), m_stackedWidget);
connect(m_updateShortcut, SIGNAL(activated()), this, SLOT(reloadQml()));
@@ -295,13 +296,14 @@ PropertyEditor::PropertyEditor(QWidget *parent) :
BasicLayouts::registerDeclarativeTypes();
ResetWidget::registerDeclarativeType();
QLayoutObject::registerDeclarativeType();
- ColorWidget::registerDeclarativeTypes();
+ QmlEditorWidgets::ColorWidgets::registerDeclarativeTypes();
BehaviorDialog::registerDeclarativeType();
QProxyLayoutItem::registerDeclarativeTypes();
PropertyEditorValue::registerDeclarativeTypes();
FontWidget::registerDeclarativeTypes();
SiblingComboBox::registerDeclarativeTypes();
OriginWidget::registerDeclarativeType();
+ GradientLineQmlAdaptor::registerDeclarativeType();
}
}
@@ -338,7 +340,6 @@ void PropertyEditor::setupPane(const QString &typeName)
type->initialSetup(typeName, qmlSpecificsFile, this);
ctxt->setContextProperty("finishedNotify", QVariant(true) );
}
- m_stackedWidget->setCurrentWidget(type->m_view);
}
void PropertyEditor::changeValue(const QString &propertyName)
@@ -390,8 +391,8 @@ void PropertyEditor::changeValue(const QString &propertyName)
QVariant castedValue;
- if (fxObjectNode.modelNode().metaInfo().isValid() && fxObjectNode.modelNode().metaInfo().property(propertyName, true).isValid()) {
- castedValue = fxObjectNode.modelNode().metaInfo().property(propertyName, true).castedValue(value->value());
+ if (fxObjectNode.modelNode().metaInfo().isValid() && fxObjectNode.modelNode().metaInfo().hasProperty(propertyName)) {
+ castedValue = fxObjectNode.modelNode().metaInfo().propertyCastedValue(propertyName, value->value());
} else {
qWarning() << "PropertyEditor:" <<propertyName << "cannot be casted (metainfo)";
return ;
@@ -402,8 +403,8 @@ void PropertyEditor::changeValue(const QString &propertyName)
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
+ if (fxObjectNode.modelNode().metaInfo().isValid() && fxObjectNode.modelNode().metaInfo().hasProperty(propertyName))
+ if (fxObjectNode.modelNode().metaInfo().propertyTypeName(propertyName) == 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());
@@ -450,13 +451,13 @@ void PropertyEditor::changeExpression(const QString &name)
QmlObjectNode fxObjectNode(m_selectedNode);
PropertyEditorValue *value = qobject_cast<PropertyEditorValue*>(QDeclarativeMetaType::toQObject(m_currentType->m_backendValuesPropertyMap.value(underscoreName)));
- if (fxObjectNode.modelNode().metaInfo().isValid() && fxObjectNode.modelNode().metaInfo().property(name).isValid()) {
- if (fxObjectNode.modelNode().metaInfo().property(name).type() == QLatin1String("QColor")) {
+ if (fxObjectNode.modelNode().metaInfo().isValid() && fxObjectNode.modelNode().metaInfo().hasProperty(name)) {
+ if (fxObjectNode.modelNode().metaInfo().propertyTypeName(name) == QLatin1String("QColor")) {
if (QColor(value->expression().remove('"')).isValid()) {
fxObjectNode.setVariantProperty(name, QColor(value->expression().remove('"')));
return;
}
- } else if (fxObjectNode.modelNode().metaInfo().property(name).type() == QLatin1String("bool")) {
+ } else if (fxObjectNode.modelNode().metaInfo().propertyTypeName(name) == QLatin1String("bool")) {
if (value->expression().compare("false", Qt::CaseInsensitive) == 0 || value->expression().compare("true", Qt::CaseInsensitive) == 0) {
if (value->expression().compare("true", Qt::CaseInsensitive) == 0)
fxObjectNode.setVariantProperty(name, true);
@@ -464,14 +465,14 @@ void PropertyEditor::changeExpression(const QString &name)
fxObjectNode.setVariantProperty(name, false);
return;
}
- } else if (fxObjectNode.modelNode().metaInfo().property(name).type() == QLatin1String("int")) {
+ } else if (fxObjectNode.modelNode().metaInfo().propertyTypeName(name) == QLatin1String("int")) {
bool ok;
int intValue = value->expression().toInt(&ok);
if (ok) {
fxObjectNode.setVariantProperty(name, intValue);
return;
}
- } else if (fxObjectNode.modelNode().metaInfo().property(name).type() == QLatin1String("qreal")) {
+ } else if (fxObjectNode.modelNode().metaInfo().propertyTypeName(name) == QLatin1String("qreal")) {
bool ok;
qreal realValue = value->expression().toFloat(&ok);
if (ok) {
@@ -505,6 +506,16 @@ void PropertyEditor::updateSize()
frame->resize(m_stackedWidget->size());
}
+void PropertyEditor::setupPanes()
+{
+ QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
+ setupPane("Qt/Rectangle");
+ setupPane("Qt/Text");
+ resetView();
+ m_setupCompleted = true;
+ QApplication::restoreOverrideCursor();
+}
+
void PropertyEditor::otherPropertyChanged(const QmlObjectNode &fxObjectNode, const QString &propertyName)
{
QmlModelView::otherPropertyChanged(fxObjectNode, propertyName);
@@ -565,20 +576,19 @@ QString templateGeneration(NodeMetaInfo type, NodeMetaInfo superType, const QmlO
qmlTemplate += QLatin1String("layout: VerticalLayout {\n");
QList<QString> orderedList;
- orderedList = type.properties(true).keys();
+ orderedList = type.propertyNames();
qSort(orderedList);
foreach (const QString &name, orderedList) {
- const PropertyMetaInfo propertyMetaInfo(type.property(name, true));
QString properName = name;
properName.replace(".", "_");
- QString typeName = propertyMetaInfo.type();
+ QString typeName = type.propertyTypeName(name);
//alias resolution only possible with instance
if (typeName == QLatin1String("alias") && objectNode.isValid())
typeName = objectNode.instanceType(name);
- if (!superType.hasProperty(name, true)) {
+ if (!superType.hasProperty(name) && type.propertyIsWritable(name)) {
if (typeName == "int") {
qmlTemplate += QString(QLatin1String(
"IntEditor { backendValue: backendValues.%2\n caption: \"%1\"\nbaseStateFlag: isBaseState\nslider: false\n}"
@@ -638,7 +648,7 @@ void PropertyEditor::resetView()
if (m_selectedNode.isValid() && !QFileInfo(qmlSpecificsFile.toLocalFile()).exists() && m_selectedNode.metaInfo().isValid()) {
//do magic !!
- specificQmlData = templateGeneration(m_selectedNode.metaInfo(), model()->metaInfo().nodeMetaInfo(specificsClassName), m_selectedNode);
+ specificQmlData = templateGeneration(m_selectedNode.metaInfo(), model()->metaInfo(specificsClassName), m_selectedNode);
}
NodeType *type = m_typeHash.value(qmlFile.toString());
@@ -728,11 +738,13 @@ void PropertyEditor::modelAttached(Model *model)
m_locked = true;
- setupPane("Qt/Rectangle");
- setupPane("Qt/Text");
- setupPane("Qt/TextInput");
- setupPane("Qt/TextEdit");
resetView();
+ if (!m_setupCompleted) {
+ m_singleShotTimer->setSingleShot(true);
+ m_singleShotTimer->setInterval(1000);
+ connect(m_singleShotTimer, SIGNAL(timeout()), this, SLOT(setupPanes()));
+ m_singleShotTimer->start();
+ }
m_locked = false;
}
@@ -871,6 +883,8 @@ void PropertyEditor::reloadQml()
QString PropertyEditor::qmlFileName(const NodeMetaInfo &nodeInfo) const
{
+ if (nodeInfo.typeName().split('/').last() == "QDeclarativeItem")
+ return "Qt/ItemPane.qml";
return nodeInfo.typeName() + QLatin1String("Pane.qml");
}
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.h b/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.h
index 86d98d985d..0f7516430e 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.h
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.h
@@ -39,6 +39,7 @@
#include <QHash>
#include <QDeclarativePropertyMap>
#include <QStackedWidget>
+#include <QTimer>
#include "qmlanchorbindingproxy.h"
#include "designerpropertymap.h"
@@ -48,6 +49,7 @@
QT_BEGIN_NAMESPACE
class QShortcut;
class QStackedWidget;
+class QTimer;
QT_END_NAMESPACE
class PropertyEditorValue;
@@ -121,6 +123,7 @@ private slots:
void changeValue(const QString &name);
void changeExpression(const QString &name);
void updateSize();
+ void setupPanes();
private: //functions
QString qmlFileName(const NodeMetaInfo &nodeInfo) const;
@@ -143,6 +146,8 @@ private: //variables
QHash<QString, NodeType *> m_typeHash;
NodeType *m_currentType;
bool m_locked;
+ bool m_setupCompleted;
+ QTimer *m_singleShotTimer;
};
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.pri b/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.pri
index af7187bbca..14cb33579a 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.pri
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.pri
@@ -1,6 +1,5 @@
VPATH += $$PWD
INCLUDEPATH += $$PWD
-include($$PWD/qtgradienteditor/qtgradienteditor.pri)
SOURCES += propertyeditor.cpp \
qmlanchorbindingproxy.cpp \
allpropertiesbox.cpp \
@@ -8,7 +7,6 @@ SOURCES += propertyeditor.cpp \
qlayoutobject.cpp \
basiclayouts.cpp \
basicwidgets.cpp \
- colorwidget.cpp \
behaviordialog.cpp \
qproxylayoutitem.cpp \
layoutwidget.cpp \
@@ -19,7 +17,8 @@ SOURCES += propertyeditor.cpp \
siblingcombobox.cpp \
propertyeditortransaction.cpp \
propertyeditorcontextobject.cpp \
- declarativewidgetview.cpp
+ declarativewidgetview.cpp \
+ gradientlineqmladaptor.cpp
HEADERS += propertyeditor.h \
qmlanchorbindingproxy.h \
@@ -28,7 +27,6 @@ HEADERS += propertyeditor.h \
qlayoutobject.h \
basiclayouts.h \
basicwidgets.h \
- colorwidget.h \
behaviordialog.h \
qproxylayoutitem.h \
layoutwidget.h \
@@ -40,7 +38,8 @@ HEADERS += propertyeditor.h \
propertyeditortransaction.h \
designerpropertymap.h \
propertyeditorcontextobject.h \
- declarativewidgetview.h
+ declarativewidgetview.h \
+ gradientlineqmladaptor.h
QT += declarative
RESOURCES += propertyeditor.qrc
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditortransaction.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditortransaction.cpp
index ef6360f8b4..61845a6acf 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditortransaction.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditortransaction.cpp
@@ -11,6 +11,8 @@ PropertyEditorTransaction::PropertyEditorTransaction(QmlDesigner::PropertyEditor
void PropertyEditorTransaction::start()
{
+ if (!m_propertyEditor->model())
+ return;
if (m_rewriterTransaction.isValid())
m_rewriterTransaction.commit();
m_rewriterTransaction = m_propertyEditor->beginRewriterTransaction();
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp
index 6dd15a008f..9b5479b929 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp
@@ -38,7 +38,6 @@
#include <model.h>
#include <nodemetainfo.h>
#include <metainfo.h>
-#include <propertymetainfo.h>
#include <nodeproperty.h>
#include <qmlobjectnode.h>
@@ -57,8 +56,8 @@ PropertyEditorValue::PropertyEditorValue(QObject *parent)
QVariant PropertyEditorValue::value() const
{
QVariant returnValue = m_value;
- if (modelNode().isValid() && modelNode().metaInfo().isValid() && modelNode().metaInfo().property(name()).isValid())
- if (modelNode().metaInfo().property(name()).type() == QLatin1String("QUrl")) {
+ if (modelNode().isValid() && modelNode().metaInfo().isValid() && modelNode().metaInfo().hasProperty(name()))
+ if (modelNode().metaInfo().propertyTypeName(name()) == QLatin1String("QUrl")) {
returnValue = returnValue.toUrl().toString();
}
return returnValue;
@@ -101,8 +100,8 @@ void PropertyEditorValue::setValueWithEmit(const QVariant &value)
{
if (m_value != value) {
QVariant newValue = value;
- if (modelNode().isValid() && modelNode().metaInfo().isValid() && modelNode().metaInfo().property(name()).isValid())
- if (modelNode().metaInfo().property(name()).type() == QLatin1String("QUrl")) {
+ if (modelNode().isValid() && modelNode().metaInfo().isValid() && modelNode().metaInfo().hasProperty(name()))
+ if (modelNode().metaInfo().propertyTypeName(name()) == QLatin1String("QUrl")) {
newValue = QUrl(newValue.toString());
}
@@ -276,7 +275,7 @@ void PropertyEditorNodeWrapper::add(const QString &type)
if ((m_editorValue && m_editorValue->modelNode().isValid())) {
if (propertyType.isEmpty())
- propertyType = m_editorValue->modelNode().metaInfo().property(m_editorValue->name()).type();
+ propertyType = m_editorValue->modelNode().metaInfo().propertyTypeName(m_editorValue->name());
while (propertyType.contains('*')) //strip star
propertyType.chop(1);
m_modelNode = m_editorValue->modelNode().view()->createModelNode(propertyType, 4, 7);
@@ -336,7 +335,7 @@ void PropertyEditorNodeWrapper::setup()
foreach (QObject *object, m_valuesPropertyMap.children())
delete object;
- foreach (const QString &propertyName, m_modelNode.metaInfo().properties().keys()) {
+ foreach (const QString &propertyName, m_modelNode.metaInfo().propertyNames()) {
if (fxObjectNode.isValid()) {
PropertyEditorValue *valueObject = new PropertyEditorValue(&m_valuesPropertyMap);
valueObject->setName(propertyName);
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.h b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.h
index 7839625435..a542050988 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.h
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.h
@@ -144,12 +144,12 @@ private: //variables
bool m_isInModel;
bool m_isBound;
bool m_isValid; // if the property value belongs to a non-existing complexProperty it is invalid
- PropertyEditorNodeWrapper *m_complexNode;
+ PropertyEditorNodeWrapper *m_complexNode;
};
-QML_DECLARE_TYPE(PropertyEditorValue);
-QML_DECLARE_TYPE(PropertyEditorNodeWrapper);
-QML_DECLARE_TYPE(QDeclarativePropertyMap);
+QML_DECLARE_TYPE(PropertyEditorValue)
+QML_DECLARE_TYPE(PropertyEditorNodeWrapper)
+QML_DECLARE_TYPE(QDeclarativePropertyMap)
#endif // PROPERTYEDITORVALUE_H
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qlayoutobject.h b/src/plugins/qmldesigner/components/propertyeditor/qlayoutobject.h
index 803316e062..b6286db9e5 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/qlayoutobject.h
+++ b/src/plugins/qmldesigner/components/propertyeditor/qlayoutobject.h
@@ -57,7 +57,7 @@ public:
QT_END_NAMESPACE
-QML_DECLARE_TYPE(QLayoutObject);
+QML_DECLARE_TYPE(QLayoutObject)
QT_END_HEADER
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qmlanchorbindingproxy.h b/src/plugins/qmldesigner/components/propertyeditor/qmlanchorbindingproxy.h
index 49439ac048..0e878b8b8f 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/qmlanchorbindingproxy.h
+++ b/src/plugins/qmldesigner/components/propertyeditor/qmlanchorbindingproxy.h
@@ -54,7 +54,7 @@ class QmlAnchorBindingProxy : public QObject
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 hasParent READ hasParent NOTIFY parentChanged)
Q_PROPERTY(QVariant topTarget READ topTarget WRITE setTopTarget NOTIFY topTargetChanged)
Q_PROPERTY(QVariant bottomTarget READ bottomTarget WRITE setBottomTarget NOTIFY bottomTargetChanged)
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qproxylayoutitem.h b/src/plugins/qmldesigner/components/propertyeditor/qproxylayoutitem.h
index 552fa6896b..54f1292a9a 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/qproxylayoutitem.h
+++ b/src/plugins/qmldesigner/components/propertyeditor/qproxylayoutitem.h
@@ -96,8 +96,8 @@ private:
QT_END_NAMESPACE
-QML_DECLARE_TYPE(QProxyLayout);
-QML_DECLARE_TYPE(QProxyLayoutItem);
+QML_DECLARE_TYPE(QProxyLayout)
+QML_DECLARE_TYPE(QProxyLayoutItem)
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
deleted file mode 100644
index 29d1d4439a..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/down.png
+++ /dev/null
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
deleted file mode 100644
index 4231bd9a90..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/edit.png
+++ /dev/null
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
deleted file mode 100644
index df2a147d24..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/editdelete.png
+++ /dev/null
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
deleted file mode 100644
index d6f233d739..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/minus.png
+++ /dev/null
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
deleted file mode 100644
index 40df1134f8..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/plus.png
+++ /dev/null
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
deleted file mode 100644
index 104c0a23d2..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/spreadpad.png
+++ /dev/null
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
deleted file mode 100644
index 17b82b711a..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/spreadreflect.png
+++ /dev/null
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
deleted file mode 100644
index 7aea898b1d..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/spreadrepeat.png
+++ /dev/null
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
deleted file mode 100644
index 5479811df6..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/typeconical.png
+++ /dev/null
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
deleted file mode 100644
index dbd8a1f5a1..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/typelinear.png
+++ /dev/null
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
deleted file mode 100644
index dc5888dca7..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/typeradial.png
+++ /dev/null
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
deleted file mode 100644
index e437312217..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/up.png
+++ /dev/null
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
deleted file mode 100644
index 2e586fc7bf..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/zoomin.png
+++ /dev/null
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
deleted file mode 100644
index a736d39343..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/images/zoomout.png
+++ /dev/null
Binary files differ
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtcolorbutton.cpp b/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtcolorbutton.cpp
deleted file mode 100644
index 13b13e3511..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtcolorbutton.cpp
+++ /dev/null
@@ -1,272 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 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
deleted file mode 100644
index 6a2d209bc0..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtcolorbutton.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 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
deleted file mode 100644
index 0e41068f8a..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtcolorbutton.pri
+++ /dev/null
@@ -1,4 +0,0 @@
-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
deleted file mode 100644
index a35374fed2..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtcolorline.cpp
+++ /dev/null
@@ -1,1122 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 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
deleted file mode 100644
index 00cce433bf..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtcolorline.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 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
deleted file mode 100644
index 093290f4ca..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientdialog.cpp
+++ /dev/null
@@ -1,353 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 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
deleted file mode 100644
index 7be1e337b8..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientdialog.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 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
deleted file mode 100644
index a9a25511bd..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientdialog.ui
+++ /dev/null
@@ -1,121 +0,0 @@
-<ui version="4.0" >
- <comment>*********************************************************************
-**
-** Copyright (C) 2010 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
deleted file mode 100644
index bee2dc5900..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradienteditor.cpp
+++ /dev/null
@@ -1,952 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 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
deleted file mode 100644
index 4892a20469..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradienteditor.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 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
deleted file mode 100644
index 4cf059e1f2..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradienteditor.pri
+++ /dev/null
@@ -1,33 +0,0 @@
-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
deleted file mode 100644
index cce7ba6224..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradienteditor.qrc
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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
deleted file mode 100644
index b82654664a..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradienteditor.ui
+++ /dev/null
@@ -1,1377 +0,0 @@
-<ui version="4.0" >
- <comment>*********************************************************************
-**
-** Copyright (C) 2010 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
deleted file mode 100644
index eeecf5802c..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientmanager.cpp
+++ /dev/null
@@ -1,135 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 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
deleted file mode 100644
index f5c8e91777..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientmanager.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 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
deleted file mode 100644
index c6eb3a0988..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientstopscontroller.cpp
+++ /dev/null
@@ -1,724 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 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
deleted file mode 100644
index bf1b9d1185..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientstopscontroller.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 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
deleted file mode 100644
index 252f82c261..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientstopsmodel.cpp
+++ /dev/null
@@ -1,477 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 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
deleted file mode 100644
index e9d87a9835..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientstopsmodel.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 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
deleted file mode 100644
index 74448c3878..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientstopswidget.cpp
+++ /dev/null
@@ -1,1154 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 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
deleted file mode 100644
index 85dc507424..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientstopswidget.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 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
deleted file mode 100644
index 9fa03244d5..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientutils.cpp
+++ /dev/null
@@ -1,420 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 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
deleted file mode 100644
index 3bcd3541da..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientutils.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 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
deleted file mode 100644
index 0d73c3327b..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientview.cpp
+++ /dev/null
@@ -1,292 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 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
deleted file mode 100644
index 5bce4c6c8c..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientview.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 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
deleted file mode 100644
index af7267ea2b..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientview.ui
+++ /dev/null
@@ -1,135 +0,0 @@
-<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
deleted file mode 100644
index dfe05037d1..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientviewdialog.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 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
deleted file mode 100644
index acafa53605..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientviewdialog.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 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
deleted file mode 100644
index d1376dc408..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientviewdialog.ui
+++ /dev/null
@@ -1,121 +0,0 @@
-<ui version="4.0" >
- <comment>*********************************************************************
-**
-** Copyright (C) 2010 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
deleted file mode 100644
index 50e09928d8..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientwidget.cpp
+++ /dev/null
@@ -1,815 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 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
deleted file mode 100644
index 8d20fa5fc7..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/qtgradienteditor/qtgradientwidget.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 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
index 41f8737021..7af9ebfdf4 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/resetwidget.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/resetwidget.cpp
@@ -44,7 +44,7 @@
#include <QDebug>
#include <QApplication>
-QML_DECLARE_TYPE(QmlDesigner::ResetWidget);
+QML_DECLARE_TYPE(QmlDesigner::ResetWidget)
namespace QmlDesigner {
diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditorimageprovider.cpp b/src/plugins/qmldesigner/components/stateseditor/stateseditorimageprovider.cpp
index ef471b8d8d..883842bf94 100644
--- a/src/plugins/qmldesigner/components/stateseditor/stateseditorimageprovider.cpp
+++ b/src/plugins/qmldesigner/components/stateseditor/stateseditorimageprovider.cpp
@@ -33,34 +33,40 @@
#include "stateseditorimageprovider.h"
#include "stateseditorview.h"
+#include <QtDebug>
+
namespace QmlDesigner {
namespace Internal {
-StatesEditorImageProvider::StatesEditorImageProvider(StatesEditorView *view) :
- QDeclarativeImageProvider(QDeclarativeImageProvider::Pixmap),
- m_view(view)
+StatesEditorImageProvider::StatesEditorImageProvider() :
+ QDeclarativeImageProvider(QDeclarativeImageProvider::Image)
{
}
-QPixmap StatesEditorImageProvider::requestPixmap(const QString &id, QSize *size, const QSize &requestedSize)
+QImage StatesEditorImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
+{
+ QSize newSize = requestedSize;
+
+ if (newSize.isEmpty())
+ newSize = QSize (100, 100);
+
+ QImage image = m_imageHash.value(id, QImage(newSize, QImage::Format_ARGB32));
+ image.fill(0xFFFFFFFF);
+
+ *size = image.size();
+
+ return image;
+}
+
+void StatesEditorImageProvider::setImage(const QString &id, const QImage &image)
{
- if (!m_view.isNull()) {
- // discard the count number (see StatesEditorModel m_updateCounter)
- QString s = id.mid(0, id.lastIndexOf(QLatin1Char('-')));
+ m_imageHash.insert(id, image);
+}
- bool ok = false;
- int state = s.toInt(&ok);
- if (ok) {
- QPixmap pm = m_view->renderState(state);
- if (size)
- *size = pm.size();
- if (requestedSize.isValid())
- return pm.scaled(requestedSize);
- return pm;
- }
- }
- return QPixmap();
+void StatesEditorImageProvider::removeImage(const QString &id)
+{
+ m_imageHash.remove(id);
}
}
diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditorimageprovider.h b/src/plugins/qmldesigner/components/stateseditor/stateseditorimageprovider.h
index b943cd61bb..930e9bda69 100644
--- a/src/plugins/qmldesigner/components/stateseditor/stateseditorimageprovider.h
+++ b/src/plugins/qmldesigner/components/stateseditor/stateseditorimageprovider.h
@@ -35,8 +35,7 @@
#define STATESEDITORIMAGEPROVIDER_H
#include <QDeclarativeImageProvider>
-
-#include <QWeakPointer>
+#include <QHash>
namespace QmlDesigner {
@@ -47,12 +46,15 @@ class StatesEditorView;
class StatesEditorImageProvider : public QDeclarativeImageProvider
{
public:
- StatesEditorImageProvider(StatesEditorView *view);
+ StatesEditorImageProvider();
+
+ QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize);
- QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize);
+ void setImage(const QString &id, const QImage &image);
+ void removeImage(const QString &id);
private:
- QWeakPointer<StatesEditorView> m_view;
+ QHash<QString, QImage> m_imageHash;
};
}
diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.cpp b/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.cpp
index 6a56a3069f..600ae94508 100644
--- a/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.cpp
+++ b/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.cpp
@@ -37,122 +37,143 @@
#include <QtCore/QDebug>
#include <QMessageBox>
+#include <nodelistproperty.h>
+#include <modelnode.h>
+#include <variantproperty.h>
+
enum {
debug = false
};
namespace QmlDesigner {
-namespace Internal {
-StatesEditorModel::StatesEditorModel(QObject *parent) :
- QAbstractListModel(parent),
- m_updateCounter(0)
+StatesEditorModel::StatesEditorModel(StatesEditorView *view)
+ : QAbstractListModel(view),
+ m_statesEditorView(view),
+ m_updateCounter(0)
{
QHash<int, QByteArray> roleNames;
roleNames.insert(StateNameRole, "stateName");
roleNames.insert(StateImageSourceRole, "stateImageSource");
+ roleNames.insert(NodeId, "nodeId");
setRoleNames(roleNames);
}
int StatesEditorModel::count() const
{
- return m_stateNames.count();
+ return rowCount();
+}
+
+QModelIndex StatesEditorModel::index(int row, int column, const QModelIndex &parent) const
+{
+ if (m_statesEditorView.isNull())
+ return QModelIndex();
+
+
+ int internalId = 0;
+ if (row > 0)
+ internalId = m_statesEditorView->rootModelNode().nodeListProperty("states").at(row - 1).internalId();
+
+ return hasIndex(row, column, parent) ? createIndex(row, column, internalId) : QModelIndex();
}
int StatesEditorModel::rowCount(const QModelIndex &parent) const
{
- if (parent.isValid())
+ if (parent.isValid() || m_statesEditorView.isNull() || !m_statesEditorView->model())
return 0;
- return m_stateNames.count();
+
+ if (!m_statesEditorView->rootModelNode().hasNodeListProperty("states"))
+ return 1;
+
+ return m_statesEditorView->rootModelNode().nodeListProperty("states").count() + 1;
+}
+
+void StatesEditorModel::reset()
+{
+ QAbstractListModel::reset();
}
QVariant StatesEditorModel::data(const QModelIndex &index, int role) const
{
- if (index.parent().isValid() || index.column() != 0)
+ if (index.parent().isValid() || index.column() != 0 || m_statesEditorView.isNull() || !m_statesEditorView->hasModelNodeForInternalId(index.internalId()))
return QVariant();
- QVariant result;
+ ModelNode stateNode;
+
+ if (index.internalId() > 0)
+ stateNode = m_statesEditorView->modelNodeForInternalId(index.internalId());
+
switch (role) {
case StateNameRole: {
- if (index.row()==0)
- result = QString(tr("base state", "Implicit default state"));
- else
- result = m_stateNames.at(index.row());
- break;
- }
- case StateImageSourceRole: {
- if (!m_statesView.isNull())
- return QString("image://qmldesigner_stateseditor/%1-%2").arg(index.row()).arg(m_updateCounter);
- break;
+ if (index.row() == 0) {
+ return QString(tr("base state", "Implicit default state"));
+ } else {
+ if (stateNode.hasVariantProperty("name")) {
+ return stateNode.variantProperty("name").value();
+ } else {
+ return QVariant();
+ }
+ }
+
}
+ case StateImageSourceRole: return QString("image://qmldesigner_stateseditor/%1").arg(index.internalId());
+ case NodeId : return index.internalId();
}
- 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();
+ return QVariant();
}
-void StatesEditorModel::removeState(int i)
+void StatesEditorModel::insertState(int stateIndex)
{
- beginRemoveRows(QModelIndex(), i, i);
+ if (stateIndex >= 0) {
- m_stateNames.removeAt(i);
+ const int index = stateIndex + 1;
+ beginInsertRows(QModelIndex(), index, index);
- endRemoveRows();
+ endInsertRows();
- emit dataChanged(createIndex(i, 0), createIndex(i, 0));
- emit countChanged();
+ emit dataChanged(createIndex(index, 0), createIndex(index, 0));
+ emit countChanged();
+ }
}
-void StatesEditorModel::renameState(int i, const QString &newName)
+void StatesEditorModel::updateState(int stateIndex)
{
- Q_ASSERT(i > 0 && i < m_stateNames.count());
-
- if (m_stateNames[i] != newName) {
- if (m_stateNames.contains(newName) || newName.isEmpty()) {
- QMessageBox::warning(0, tr("Invalid state name"),
- newName.isEmpty() ?
- tr("The empty string as a name is reserved for the base state.") :
- tr("Name already used in another state"));
- } else {
- m_stateNames.replace(i, newName);
- m_statesView->renameState(i,newName);
-
- emit dataChanged(createIndex(i, 0), createIndex(i, 0));
- }
+ if (stateIndex >= 0) {
+ const int index = stateIndex + 1;
+
+ emit dataChanged(createIndex(index, 0), createIndex(index, 0));
}
}
-void StatesEditorModel::updateState(int i)
+void StatesEditorModel::removeState(int stateIndex)
{
- Q_ASSERT(i >= 0 && i < m_stateNames.count());
+ if (stateIndex >= 0) {
+ const int index = stateIndex + 1;
+ beginRemoveRows(QModelIndex(), index, index);
- // QML images with the same URL are always cached, so this changes the URL each
- // time to ensure the image is loaded from the StatesImageProvider and not the
- // cache.
- // TODO: only increase imageId when the scene has changed so that we can load
- // from the cache instead where possible.
- if (++m_updateCounter == INT_MAX)
- m_updateCounter = 0;
- emit dataChanged(createIndex(i, 0), createIndex(i, 0));
+ endRemoveRows();
+
+ emit dataChanged(createIndex(index, 0), createIndex(index, 0));
+ emit countChanged();
+ }
}
-void StatesEditorModel::setStatesEditorView(StatesEditorView *statesView)
-{
- m_statesView = statesView;
+void StatesEditorModel::renameState(int nodeId, const QString &newName)
+{
+ if (newName.isEmpty() ||! m_statesEditorView->validStateName(newName)) {
+ QMessageBox::warning(0, tr("Invalid state name"),
+ newName.isEmpty() ?
+ tr("The empty string as a name is reserved for the base state.") :
+ tr("Name already used in another state"));
+ } else {
+ m_statesEditorView->renameState(nodeId, newName);
+ }
+
}
void StatesEditorModel::emitChangedToState(int n)
@@ -160,5 +181,4 @@ 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
index 35ceb7c68e..7988042703 100644
--- a/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.h
+++ b/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.h
@@ -37,11 +37,10 @@
#include <QAbstractListModel>
#include <QWeakPointer>
-#include <stateseditorview.h>
namespace QmlDesigner {
-namespace Internal {
+class StatesEditorView;
class StatesEditorModel : public QAbstractListModel
{
@@ -52,33 +51,34 @@ class StatesEditorModel : public QAbstractListModel
enum {
StateNameRole = Qt::DisplayRole,
StateImageSourceRole = Qt::UserRole,
+ NodeId
};
public:
- StatesEditorModel(QObject *parent);
+ StatesEditorModel(StatesEditorView *view);
int count() const;
+ QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) 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 insertState(int stateIndex);
+ void removeState(int stateIndex);
+ void updateState(int stateIndex);
+ Q_INVOKABLE void renameState(int nodeId, const QString &newName);
void emitChangedToState(int n);
+ void reset();
+
signals:
void countChanged();
void changedToState(int n);
private:
- QList<QString> m_stateNames;
- QWeakPointer<StatesEditorView> m_statesView;
+ QWeakPointer<StatesEditorView> m_statesEditorView;
int m_updateCounter;
};
-} // 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
index c8dce87666..8dfe371aa4 100644
--- a/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp
+++ b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp
@@ -32,6 +32,7 @@
**************************************************************************/
#include "stateseditorview.h"
+#include "stateseditorwidget.h"
#include "stateseditormodel.h"
#include <customnotifications.h>
#include <rewritingexception.h>
@@ -42,6 +43,8 @@
#include <QDebug>
#include <math.h>
+#include <nodemetainfo.h>
+
#include <variantproperty.h>
#include <nodelistproperty.h>
@@ -50,140 +53,126 @@ enum {
};
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) :
+StatesEditorView::StatesEditorView(QObject *parent) :
QmlModelView(parent),
- m_editorModel(editorModel),
- m_attachedToModel(false), m_settingSilentState(false)
+ m_statesEditorModel(new StatesEditorModel(this)),
+ m_lastIndex(-1)
{
- Q_ASSERT(m_editorModel);
+ Q_ASSERT(m_statesEditorModel);
// base state
- m_thumbnailsToUpdate.append(false);
}
-void StatesEditorView::setCurrentStateSilent(int index)
+StatesEditorWidget *StatesEditorView::widget()
{
- m_settingSilentState = true;
- if (debug)
- qDebug() << __FUNCTION__ << index;
-
- Q_ASSERT(index >= 0 && index < m_modelStates.count());
-
- // TODO
- QmlModelState state(m_modelStates.at(index));
- if (!state.isValid()) {
- m_settingSilentState = false;
- return;
- }
- if (state == currentState()) {
- m_settingSilentState = false;
- return;
- }
-
- nodeInstanceView()->setBlockStatePropertyChanges(true);
-
- QmlModelView::activateState(state);
-
- nodeInstanceView()->setBlockStatePropertyChanges(false);
+ if (m_statesEditorWidget.isNull())
+ m_statesEditorWidget = new StatesEditorWidget(this, m_statesEditorModel.data());
- m_settingSilentState = false;
+ return m_statesEditorWidget.data();
}
-void StatesEditorView::setCurrentState(int index)
+void StatesEditorView::removeState(int nodeId)
{
- if (debug)
- qDebug() << __FUNCTION__ << index;
+ try {
+ if (nodeId > 0 && hasModelNodeForInternalId(nodeId)) {
+ ModelNode stateNode(modelNodeForInternalId(nodeId));
+ Q_ASSERT(stateNode.metaInfo().isSubclassOf("QtQuick/State", 4, 7));
+ NodeListProperty parentProperty = stateNode.parentProperty().toNodeListProperty();
+
+ if (parentProperty.count() <= 1) {
+ setCurrentState(baseState());
+ } else if (parentProperty.isValid()){
+ int index = parentProperty.indexOf(stateNode);
+ if (index == 0) {
+ setCurrentState(parentProperty.at(1));
+ } else {
+ setCurrentState(parentProperty.at(index - 1));
+ }
+ }
- // happens to be the case for an invalid document / no base state
- if (m_modelStates.isEmpty())
- return;
- Q_ASSERT(index < m_modelStates.count());
- if (index == -1)
- return;
+ stateNode.destroy();
+ }
+ } catch (RewritingException &e) {
+ QMessageBox::warning(0, "Error", e.description());
+ }
+}
- if (m_modelStates.indexOf(currentState()) == index)
+void StatesEditorView::synchonizeCurrentStateFromWidget()
+{
+ if (!model())
return;
+ int internalId = m_statesEditorWidget->currentStateInternalId();
- QmlModelState state(m_modelStates.at(index));
- Q_ASSERT(state.isValid());
- QmlModelView::setCurrentState(state);
+ if (internalId > 0 && hasModelNodeForInternalId(internalId)) {
+ ModelNode node = modelNodeForInternalId(internalId);
+ QmlModelState modelState(node);
+ if (modelState.isValid() && modelState != currentState())
+ setCurrentState(modelState);
+ } else {
+ setCurrentState(baseState());
+ }
}
-void StatesEditorView::createState(const QString &name)
+void StatesEditorView::createNewState()
{
- if (debug)
- qDebug() << __FUNCTION__ << name;
-
- try {
- model()->addImport(Import::createLibraryImport("Qt", "4.7"));
- stateRootNode().states().addState(name);
- } catch (RewritingException &e) {
- QMessageBox::warning(0, "Error", e.description());
+ if (currentState().isBaseState()) {
+ addState();
+ } else {
+ duplicateCurrentState();
}
}
-void StatesEditorView::removeState(int index)
+void StatesEditorView::addState()
{
- if (debug)
- qDebug() << __FUNCTION__ << index;
+ // can happen when root node is e.g. a ListModel
+ if (!rootQmlItemNode().isValid())
+ return;
- Q_ASSERT(index > 0 && index < m_modelStates.size());
- QmlModelState state = m_modelStates.at(index);
- Q_ASSERT(state.isValid());
+ QStringList modelStateNames = rootStateGroup().names();
- setCurrentState(0);
+ QString newStateName;
+ int index = 1;
+ while (true) {
+ newStateName = tr("State%1", "Default name for newly created states").arg(index++);
+ if (!modelStateNames.contains(newStateName))
+ break;
+ }
try {
- m_modelStates.removeAll(state);
- state.destroy();
- m_thumbnailsToUpdate.removeAt(index);
-
- m_editorModel->removeState(index);
-
- int newIndex = (index < m_modelStates.count()) ? index : m_modelStates.count() - 1;
- setCurrentState(newIndex);
+ if (rootStateGroup().allStates().count() < 1)
+ model()->addImport(Import::createLibraryImport("QtQuick", "1.0"));
+ ModelNode newState = rootStateGroup().addState(newStateName);
+ setCurrentState(newState);
} catch (RewritingException &e) {
QMessageBox::warning(0, "Error", e.description());
}
}
-void StatesEditorView::renameState(int index, const QString &newName)
+void StatesEditorView::resetModel()
{
- if (debug)
- qDebug() << __FUNCTION__ << index << newName;
+ if (m_statesEditorModel)
+ m_statesEditorModel->reset();
- Q_ASSERT(index > 0 && index < m_modelStates.size());
- QmlModelState state = m_modelStates.at(index);
- Q_ASSERT(state.isValid());
-
- try {
- if (state.name() != newName) {
- // Jump to base state for the change
- QmlModelState oldState = currentState();
- setCurrentStateSilent(0);
- state.setName(newName);
- setCurrentState(m_modelStates.indexOf(oldState));
+ if (m_statesEditorWidget) {
+ if (currentState().isBaseState()) {
+ m_statesEditorWidget->setCurrentStateInternalId(currentState().modelNode().internalId());
+ } else {
+ m_statesEditorWidget->setCurrentStateInternalId(0);
}
- } catch (RewritingException &e) {
- QMessageBox::warning(0, "Error", e.description());
}
}
-void StatesEditorView::duplicateCurrentState(int index)
+void StatesEditorView::duplicateCurrentState()
{
- if (debug)
- qDebug() << __FUNCTION__ << index;
+ QmlModelState state = currentState();
- Q_ASSERT(index > 0 && index < m_modelStates.size());
+ Q_ASSERT(!state.isBaseState());
- QmlModelState state = m_modelStates.at(index);
- Q_ASSERT(state.isValid());
QString newName = state.name();
// Strip out numbers at the end of the string
@@ -193,267 +182,180 @@ void StatesEditorView::duplicateCurrentState(int index)
newName = newName.left(numberIndex);
int i = 1;
- QStringList stateNames = state.stateGroup().names();
+ QStringList stateNames = rootStateGroup().names();
while (stateNames.contains(newName + QString::number(i)))
i++;
- state.duplicate(newName + QString::number(i));
+
+ QmlModelState newState = state.duplicate(newName + QString::number(i));
+ setCurrentState(newState);
}
-void StatesEditorView::modelAttached(Model *model)
+bool StatesEditorView::validStateName(const QString &name) const
{
- if (debug)
- qDebug() << __FUNCTION__;
+ if (name == tr("base state"))
+ return false;
+ QList<QmlModelState> modelStates = rootStateGroup().allStates();
+ foreach (const QmlModelState &state, modelStates) {
+ if (state.name() == name)
+ return false;
+ }
+ return true;
+}
+void StatesEditorView::renameState(int nodeId, const QString &newName)
+{
+ if (hasModelNodeForInternalId(nodeId)) {
+ QmlModelState state(modelNodeForInternalId(nodeId));
+ try {
+ if (state.isValid() && state.name() != newName) {
+ // Jump to base state for the change
+ QmlModelState oldState = currentState();
+ setCurrentState(baseState());
+ state.setName(newName);
+ setCurrentState(oldState);
+ }
+ } catch (RewritingException &e) {
+ QMessageBox::warning(0, "Error", e.description());
+ }
+ }
+}
+
+void StatesEditorView::modelAttached(Model *model)
+{
if (model == QmlModelView::model())
return;
Q_ASSERT(model);
QmlModelView::modelAttached(model);
- clearModelStates();
- // Add base state
- if (!baseState().isValid())
- return;
-
- m_modelStates.insert(0, baseState());
- m_thumbnailsToUpdate.insert(0, false);
- m_attachedToModel = true;
- m_editorModel->insertState(0, baseState().name());
-
- // Add custom states
- m_stateRootNode = QmlItemNode(rootModelNode());
- if (!m_stateRootNode.isValid())
- return;
-
- for (int i = 0; i < m_stateRootNode.states().allStates().size(); ++i) {
- QmlModelState state = QmlItemNode(rootModelNode()).states().allStates().at(i);
- insertModelState(i, state);
- }
-
- for (int i = 0; i < m_modelStates.count(); ++i)
- m_editorModel->updateState(i); //refres all states
+ resetModel();
}
void StatesEditorView::modelAboutToBeDetached(Model *model)
{
- if (debug)
- qDebug() << __FUNCTION__;
-
- m_attachedToModel = false;
-
- clearModelStates();
-
QmlModelView::modelAboutToBeDetached(model);
+ resetModel();
}
void StatesEditorView::propertiesAboutToBeRemoved(const QList<AbstractProperty> &propertyList)
{
- if (debug)
- qDebug() << __FUNCTION__;
-
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);
- }
- } else {
- 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);
- }
- }
+ if (property.name() == "states" && property.parentModelNode().isRootNode())
+ m_statesEditorModel->reset();
}
- QmlModelView::propertiesAboutToBeRemoved(propertyList);
}
-void StatesEditorView::propertiesRemoved(const QList<AbstractProperty> &propertyList)
-{
- if (debug)
- qDebug() << __FUNCTION__;
-
- QmlModelView::propertiesRemoved(propertyList);
-}
-void StatesEditorView::variantPropertiesChanged(const QList<VariantProperty> &propertyList, PropertyChangeFlags propertyChange)
+void StatesEditorView::variantPropertiesChanged(const QList<VariantProperty> &propertyList, PropertyChangeFlags /*propertyChange*/)
{
- if (debug)
- qDebug() << __FUNCTION__;
-
- 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());
+ if (property.name() == "name" && property.parentModelNode().hasParentProperty()) {
+ NodeAbstractProperty parentProperty = property.parentModelNode().parentProperty();
+ if (parentProperty.name() == "states" && parentProperty.parentModelNode().isRootNode()) {
+ m_statesEditorModel->updateState(parentProperty.indexOf(property.parentModelNode()));
+ }
}
}
}
+
void StatesEditorView::nodeAboutToBeRemoved(const ModelNode &removedNode)
{
- if (debug)
- qDebug() << __FUNCTION__;
-
- if (removedNode.parentProperty().parentModelNode() == m_stateRootNode
- && QmlModelState(removedNode).isValid()) {
- removeModelState(removedNode);
+ if (removedNode.hasParentProperty()) {
+ const NodeAbstractProperty propertyParent = removedNode.parentProperty();
+ if (propertyParent.parentModelNode().isRootNode() && propertyParent.name() == "states") {
+ m_lastIndex = propertyParent.indexOf(removedNode);
+ }
}
+}
- QmlModelView::nodeAboutToBeRemoved(removedNode);
-
- if (QmlModelState(removedNode).isValid()) {
- startUpdateTimer(modelStateIndex(removedNode) + 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::nodeRemoved(const ModelNode & /*removedNode*/, const NodeAbstractProperty &parentProperty, PropertyChangeFlags /*propertyChange*/)
+{
+ if (parentProperty.isValid() && parentProperty.parentModelNode().isRootNode() && parentProperty.name() == "states") {
+ m_statesEditorModel->removeState(m_lastIndex);
+ m_lastIndex = -1;
}
}
-
-void StatesEditorView::nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange)
+void StatesEditorView::nodeAboutToBeReparented(const ModelNode &node, const NodeAbstractProperty &/*newPropertyParent*/, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags /*propertyChange*/)
{
- if (debug)
- qDebug() << __FUNCTION__;
+ if (oldPropertyParent.isValid() && oldPropertyParent.parentModelNode().isRootNode() && oldPropertyParent.name() == "states")
+ m_lastIndex = oldPropertyParent.indexOf(node);
+}
- QmlModelView::nodeReparented(node, newPropertyParent, oldPropertyParent, propertyChange);
- // this would be sliding
- Q_ASSERT(newPropertyParent != oldPropertyParent);
+void StatesEditorView::nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags /*propertyChange*/)
+{
+ if (oldPropertyParent.isValid() && oldPropertyParent.parentModelNode().isRootNode() && oldPropertyParent.name() == "states")
+ m_statesEditorModel->removeState(m_lastIndex);
- 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";
- }
- }
+ m_lastIndex = -1;
- 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";
- }
- }
+ if (newPropertyParent.isValid() && newPropertyParent.parentModelNode().isRootNode() && newPropertyParent.name() == "states") {
+ int index = newPropertyParent.indexOf(node);
+ m_statesEditorModel->insertState(index);
}
}
-void StatesEditorView::nodeOrderChanged(const NodeListProperty &listProperty, const ModelNode &movedNode, int oldIndex)
+void StatesEditorView::nodeOrderChanged(const NodeListProperty &listProperty, const ModelNode & /*movedNode*/, int /*oldIndex*/)
{
- if (debug)
- qDebug() << __FUNCTION__;
-
- QmlModelView::nodeOrderChanged(listProperty, movedNode, oldIndex);
- if (listProperty.parentModelNode() == m_stateRootNode
- && listProperty.name() == "states") {
-
- int newIndex = listProperty.toModelNodeList().indexOf(movedNode);
- Q_ASSERT(newIndex >= 0);
-
- QmlModelState state = QmlModelState(movedNode);
- if (state.isValid()) {
- Q_ASSERT(oldIndex == modelStateIndex(state));
- removeModelState(state);
- insertModelState(newIndex, state);
- Q_ASSERT(newIndex == modelStateIndex(state));
- }
- }
+ if (listProperty.isValid() && listProperty.parentModelNode().isRootNode() && listProperty.name() == "states")
+ resetModel();
}
void StatesEditorView::nodeInstancePropertyChanged(const ModelNode &node, const QString &propertyName)
{
- if (!m_settingSilentState) {
- QmlModelState state = QmlModelState(node);
- if (state.isValid())
- {
- if (m_modelStates.contains(state))
- m_thumbnailsToUpdate[m_modelStates.indexOf(state)] = true;
- } else //a change to the base state update all
- m_thumbnailsToUpdate[0] = true;
-
- }
-
// sets currentState() used in sceneChanged
QmlModelView::nodeInstancePropertyChanged(node, propertyName);
-
- if (!m_settingSilentState)
- sceneChanged();
}
void StatesEditorView::stateChanged(const QmlModelState &newQmlModelState, const QmlModelState &oldQmlModelState)
{
- if (debug)
- qDebug() << __FUNCTION__;
-
- QmlModelView::stateChanged(newQmlModelState, oldQmlModelState);
-
- if (!m_settingSilentState) {
- if (newQmlModelState.isBaseState())
- m_editorModel->emitChangedToState(0);
- else
- m_editorModel->emitChangedToState(m_modelStates.indexOf(newQmlModelState));
+ if (newQmlModelState.isBaseState()) {
+ m_statesEditorWidget->setCurrentStateInternalId(0);
+ } else {
+ m_statesEditorWidget->setCurrentStateInternalId(newQmlModelState.modelNode().internalId());
}
+ QmlModelView::stateChanged(newQmlModelState, oldQmlModelState);
}
void StatesEditorView::transformChanged(const QmlObjectNode &qmlObjectNode, const QString &propertyName)
{
- if (debug)
- qDebug() << __FUNCTION__;
-
QmlModelView::transformChanged(qmlObjectNode, propertyName);
}
void StatesEditorView::parentChanged(const QmlObjectNode &qmlObjectNode)
{
- if (debug)
- qDebug() << __FUNCTION__;
-
QmlModelView::parentChanged(qmlObjectNode);
}
void StatesEditorView::otherPropertyChanged(const QmlObjectNode &qmlObjectNode, const QString &propertyName)
{
- if (debug)
- qDebug() << __FUNCTION__;
-
QmlModelView::otherPropertyChanged(qmlObjectNode, propertyName);
}
-void StatesEditorView::customNotification(const AbstractView * view, const QString & identifier, const QList<ModelNode> & nodeList, const QList<QVariant> & data)
+void StatesEditorView::customNotification(const AbstractView * view, const QString & identifier, const QList<ModelNode> & nodeList, const QList<QVariant> &imageList)
{
if (debug)
qDebug() << __FUNCTION__;
- if (identifier == "__end rewriter transaction__")
- {
- if (m_thumbnailsToUpdate[0])
- {
- for (int i = 0; i < m_modelStates.count(); ++i) {
- m_thumbnailsToUpdate[i] = false;
- startUpdateTimer(i, 0);
- }
- } else
- for (int i = 1; i< m_thumbnailsToUpdate.count(); i++)
- if (m_thumbnailsToUpdate[i]) {
- m_thumbnailsToUpdate[i] = false;
- startUpdateTimer(i,0);
- }
- }
+ if (identifier == "__state preview updated__") {
+ if (nodeList.size() != imageList.size())
+ return;
+
+// if (++m_updateCounter == INT_MAX)
+// m_updateCounter = 0;
+
+ for (int i = 0; i < nodeList.size(); i++) {
+ QmlModelState modelState(nodeList.at(i));
+ }
- QmlModelView::customNotification(view, identifier, nodeList, data);
+ // emit dataChanged(createIndex(i, 0), createIndex(i, 0));
+
+ } else {
+ QmlModelView::customNotification(view, identifier, nodeList, imageList);
+ }
}
void StatesEditorView::scriptFunctionsChanged(const ModelNode &node, const QStringList &scriptFunctionList)
@@ -479,167 +381,4 @@ void StatesEditorView::selectedNodesChanged(const QList<ModelNode> &/*selectedNo
}
-
-QPixmap StatesEditorView::renderState(int i)
-{
- if (debug)
- qDebug() << __FUNCTION__ << i;
-
- if (!m_attachedToModel)
- return QPixmap();
-
- Q_ASSERT(i >= 0 && i < m_modelStates.size());
- 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();
-
-
- QSizeF pixmapSize(nodeInstanceView()->sceneRect().size());
- if (pixmapSize.width() > 100 || pixmapSize.height() > 100) // sensible maximum size
- pixmapSize.scale(QSize(100, 100), Qt::KeepAspectRatio);
- QSize cutSize(floor(pixmapSize.width()),floor(pixmapSize.height()));
- pixmapSize.setWidth(ceil(pixmapSize.width()));
- pixmapSize.setHeight(ceil(pixmapSize.height()));
- QPixmap pixmap(pixmapSize.toSize());
-
- QPainter painter(&pixmap);
- painter.drawTiledPixmap(pixmap.rect(), tilePixmap);
- nodeInstanceView()->render(&painter, pixmap.rect(), nodeInstanceView()->sceneRect());
-
- setCurrentStateSilent(m_modelStates.indexOf(oldState));
-
- Q_ASSERT(oldState == currentState());
-
- return pixmap.copy(0,0,cutSize.width(),cutSize.height());
-}
-
-void StatesEditorView::sceneChanged()
-{
- if (debug)
- qDebug() << __FUNCTION__;
-
- // If we are in base state we have to update the pixmaps of all states,
- // otherwise only the pixmap for the current state
-
- // TODO: Since a switch to the base state also results in nodePropertyChanged and
- // therefore sceneChanged calls, we're rendering too much here
-
- 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 (debug)
- qDebug() << __FUNCTION__ << i << offset;
-
- if (i < 0 || i > m_modelStates.count())
- return;
-
- if (i < m_updateTimerIdList.size() && m_updateTimerIdList.at(i) != 0)
- return;
- // TODO: Add an offset so not all states are rendered at once
-
-
- 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)
-{
- if (debug)
- qDebug() << __FUNCTION__ << i << state.name();
-
- 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());
- m_thumbnailsToUpdate.append(false);
-}
-
-void StatesEditorView::removeModelState(const QmlModelState &state)
-{
- if (debug)
- qDebug() << __FUNCTION__ << state.name();
-
- Q_ASSERT(state.isValid());
- Q_ASSERT(!state.isBaseState());
- int index = m_modelStates.indexOf(state);
- if (index != -1) {
- m_modelStates.removeOne(state);
- m_thumbnailsToUpdate.removeAt(index);
-
- if (m_updateTimerIdList.contains(index)) {
- killTimer(m_updateTimerIdList[index]);
- m_updateTimerIdList[index] = 0;
- }
- m_editorModel->removeState(index);
- }
-}
-
-void StatesEditorView::clearModelStates()
-{
- if (debug)
- qDebug() << __FUNCTION__;
-
-
- // Remove all states
- const int modelStateCount = m_modelStates.size();
- for (int i=modelStateCount-1; i>=0; --i) {
- m_modelStates.removeAt(i);
- m_thumbnailsToUpdate.removeAt(i);
- m_editorModel->removeState(i);
- }
-}
-
-// index without base state
-int StatesEditorView::modelStateIndex(const QmlModelState &state)
-{
- return m_modelStates.indexOf(state) - 1;
-}
-
-void StatesEditorView::timerEvent(QTimerEvent *event)
-{
- if (debug)
- qDebug() << __FUNCTION__;
-
- 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
index 4e40d27200..9ec167f39e 100644
--- a/src/plugins/qmldesigner/components/stateseditor/stateseditorview.h
+++ b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.h
@@ -38,26 +38,18 @@
namespace QmlDesigner {
-namespace Internal {
class StatesEditorModel;
+class StatesEditorWidget;
class StatesEditorView : public QmlModelView {
Q_OBJECT
public:
- explicit StatesEditorView(StatesEditorModel *model, QObject *parent = 0);
+ explicit StatesEditorView(QObject *parent = 0);
- void setCurrentState(int index);
- void setCurrentStateSilent(int index);
- 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; }
- bool isAttachedToModel() const { return m_attachedToModel; }
+ void renameState(int nodeId,const QString &newName);
+ bool validStateName(const QString &name) const;
void nodeInstancePropertyChanged(const ModelNode &node, const QString &propertyName);
@@ -65,13 +57,15 @@ public:
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 nodeRemoved(const ModelNode &removedNode, const NodeAbstractProperty &parentProperty, PropertyChangeFlags propertyChange);
+ void nodeAboutToBeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange);
void nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange);
void nodeOrderChanged(const NodeListProperty &listProperty, const ModelNode &movedNode, int oldIndex);
+
// QmlModelView
void stateChanged(const QmlModelState &newQmlModelState, const QmlModelState &oldQmlModelState);
void transformChanged(const QmlObjectNode &qmlObjectNode, const QString &propertyName);
@@ -84,34 +78,24 @@ public:
void bindingPropertiesChanged(const QList<BindingProperty> &propertyList, PropertyChangeFlags propertyChange);
void selectedNodesChanged(const QList<ModelNode> &selectedNodeList, const QList<ModelNode> &lastSelectedNodeList);
+ StatesEditorWidget *widget();
-protected:
- void timerEvent(QTimerEvent*);
-
-private slots:
- void sceneChanged();
+public slots:
+ void synchonizeCurrentStateFromWidget();
+ void createNewState();
+ void removeState(int nodeId);
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);
+ void resetModel();
+ void addState();
+ void duplicateCurrentState();
- QList<QmlModelState> m_modelStates;
- StatesEditorModel *m_editorModel;
- QmlItemNode m_stateRootNode;
-
- QList<int> m_updateTimerIdList;
- QmlModelState m_oldRewriterAmendState;
- bool m_attachedToModel;
- bool m_settingSilentState;
-
- QList<bool> m_thumbnailsToUpdate;
+private:
+ QWeakPointer<StatesEditorModel> m_statesEditorModel;
+ QWeakPointer<StatesEditorWidget> m_statesEditorWidget;
+ int m_lastIndex;
};
-} // 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
index 31e34c588c..cbb4a4f03d 100644
--- a/src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.cpp
+++ b/src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.cpp
@@ -59,139 +59,58 @@ enum {
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(int);
- void duplicateCurrentState();
-
-private:
- StatesEditorWidget *m_q;
- QWeakPointer<Model> model;
- QWeakPointer<QDeclarativeView> 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->rootObject());
- Q_ASSERT(listView->rootObject()->property("currentStateIndex").isValid());
- return listView->rootObject()->property("currentStateIndex").toInt();
-}
-
-void StatesEditorWidgetPrivate::setCurrentIndex(int i)
-{
- listView->rootObject()->setProperty("currentStateIndex", i);
-}
-
-bool StatesEditorWidgetPrivate::validStateName(const QString &name) const
+int StatesEditorWidget::currentStateInternalId() 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;
-}
+ Q_ASSERT(m_declarativeView->rootObject());
+ Q_ASSERT(m_declarativeView->rootObject()->property("currentStateInternalId").isValid());
-void StatesEditorWidgetPrivate::currentStateChanged()
-{
- if (statesEditorView->isAttachedToModel())
- statesEditorView->setCurrentState(currentIndex());
+ return m_declarativeView->rootObject()->property("currentStateInternalId").toInt();
}
-void StatesEditorWidgetPrivate::addState()
+void StatesEditorWidget::setCurrentStateInternalId(int internalId)
{
- // can happen when root node is e.g. a ListModel
- if (!statesEditorView->stateRootNode().isValid())
- return;
-
- QStringList modelStateNames = statesEditorView->stateRootNode().states().names();
-
- QString newStateName;
- int index = 1;
- while (1) {
- newStateName = tr("State%1", "Default name for newly created states").arg(index++);
- if (!modelStateNames.contains(newStateName))
- break;
- }
- statesEditorView->createState(newStateName);
+ m_declarativeView->rootObject()->setProperty("currentStateInternalId", internalId);
}
-void StatesEditorWidgetPrivate::removeState(int i)
+StatesEditorWidget::StatesEditorWidget(StatesEditorView *statesEditorView, StatesEditorModel *statesEditorModel):
+ QWidget()
{
- statesEditorView->removeState(i);
-}
+ m_declarativeView = new QDeclarativeView(this);
-void StatesEditorWidgetPrivate::duplicateCurrentState()
-{
- statesEditorView->duplicateCurrentState(currentIndex());
-}
-
-} // namespace Internal
+ m_declarativeView->engine()->addImageProvider(
+ QLatin1String("qmldesigner_stateseditor"), new Internal::StatesEditorImageProvider);
-StatesEditorWidget::StatesEditorWidget(QWidget *parent):
- QWidget(parent),
- m_d(new Internal::StatesEditorWidgetPrivate(this))
-{
- m_d->statesEditorModel = new Internal::StatesEditorModel(this);
- m_d->listView = new QDeclarativeView(this);
- m_d->listView->setAcceptDrops(false);
+ m_declarativeView->setAcceptDrops(false);
QVBoxLayout *layout = new QVBoxLayout(this);
layout->setMargin(0);
layout->setSpacing(0);
- layout->addWidget(m_d->listView.data());
+ layout->addWidget(m_declarativeView.data());
- m_d->listView->setResizeMode(QDeclarativeView::SizeRootObjectToView);
+ m_declarativeView->setResizeMode(QDeclarativeView::SizeRootObjectToView);
- m_d->listView->rootContext()->setContextProperty(QLatin1String("statesEditorModel"), m_d->statesEditorModel.data());
+ m_declarativeView->rootContext()->setContextProperty(QLatin1String("statesEditorModel"), statesEditorModel);
QColor highlightColor = palette().highlight().color();
if (0.5*highlightColor.saturationF()+0.75-highlightColor.valueF() < 0)
highlightColor.setHsvF(highlightColor.hsvHueF(),0.1 + highlightColor.saturationF()*2.0, highlightColor.valueF());
- m_d->listView->rootContext()->setContextProperty(QLatin1String("highlightColor"), highlightColor);
+ m_declarativeView->rootContext()->setContextProperty(QLatin1String("highlightColor"), highlightColor);
// Work around ASSERT in the internal QGraphicsScene that happens when
// the scene is created + items set dirty in one event loop run (BAUHAUS-459)
- QApplication::processEvents();
+ //QApplication::processEvents();
- m_d->listView->setSource(QUrl("qrc:/stateseditor/stateslist.qml"));
+ m_declarativeView->setSource(QUrl("qrc:/stateseditor/stateslist.qml"));
- if (!m_d->listView->rootObject())
+ if (!m_declarativeView->rootObject())
throw InvalidQmlSourceException(__LINE__, __FUNCTION__, __FILE__);
- m_d->listView->setFocusPolicy(Qt::ClickFocus);
- QApplication::sendEvent(m_d->listView->scene(), new QEvent(QEvent::WindowActivate));
+ m_declarativeView->setFocusPolicy(Qt::ClickFocus);
+ QApplication::sendEvent(m_declarativeView->scene(), new QEvent(QEvent::WindowActivate));
- connect(m_d->listView->rootObject(), SIGNAL(currentStateIndexChanged()), m_d, SLOT(currentStateChanged()));
- connect(m_d->listView->rootObject(), SIGNAL(createNewState()), m_d, SLOT(addState()));
- connect(m_d->listView->rootObject(), SIGNAL(duplicateCurrentState()), m_d, SLOT(duplicateCurrentState()));
- connect(m_d->listView->rootObject(), SIGNAL(deleteState(int)), m_d, SLOT(removeState(int)));
+ connect(m_declarativeView->rootObject(), SIGNAL(currentStateInternalIdChanged()), statesEditorView, SLOT(synchonizeCurrentStateFromWidget()));
+ connect(m_declarativeView->rootObject(), SIGNAL(createNewState()), statesEditorView, SLOT(createNewState()));
+ connect(m_declarativeView->rootObject(), SIGNAL(deleteState(int)), statesEditorView, SLOT(removeState(int)));
setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred));
@@ -200,27 +119,8 @@ StatesEditorWidget::StatesEditorWidget(QWidget *parent):
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->listView->engine()->addImageProvider(
- QLatin1String("qmldesigner_stateseditor"), new Internal::StatesEditorImageProvider(m_d->statesEditorView.data()));
-
- 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
{
@@ -228,5 +128,3 @@ QSize StatesEditorWidget::sizeHint() const
}
}
-
-#include "stateseditorwidget.moc"
diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.h b/src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.h
index 33af0ee584..a6e061764c 100644
--- a/src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.h
+++ b/src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.h
@@ -37,31 +37,34 @@
#include <QtGui/QWidget>
#include <QtGui/QListWidgetItem>
+QT_BEGIN_NAMESPACE
+class QDeclarativeView;
+QT_END_NAMESPACE
+
namespace QmlDesigner {
-class FormWindow;
class Model;
class ModelState;
+class StatesEditorModel;
+class StatesEditorView;
-namespace Internal {
-class StatesEditorWidgetPrivate;
-}
class StatesEditorWidget : public QWidget
{
Q_OBJECT
public:
- StatesEditorWidget(QWidget *parent = 0);
+ StatesEditorWidget(StatesEditorView *m_statesEditorView, StatesEditorModel *statesEditorModel);
virtual ~StatesEditorWidget();
- void setup(Model *model);
-
QSize sizeHint() const;
+ int currentStateInternalId() const;
+ void setCurrentStateInternalId(int internalId);
+
private:
- friend class Internal::StatesEditorWidgetPrivate;
- class Internal::StatesEditorWidgetPrivate *m_d;
+ QWeakPointer<QDeclarativeView> m_declarativeView;
+ QWeakPointer<StatesEditorView> m_statesEditorView;
};
}
diff --git a/src/plugins/qmldesigner/components/stateseditor/stateslist.qml b/src/plugins/qmldesigner/components/stateseditor/stateslist.qml
index 2a552c32bb..19b6bfb068 100644
--- a/src/plugins/qmldesigner/components/stateseditor/stateslist.qml
+++ b/src/plugins/qmldesigner/components/stateseditor/stateslist.qml
@@ -3,28 +3,18 @@ import Qt 4.7
Rectangle {
id: root
- property int currentStateIndex : 0
+ property int currentStateInternalId : 0
signal createNewState
- signal deleteState(int index)
+ signal deleteState(int nodeId)
signal duplicateCurrentState
signal startRenaming
color: "#4f4f4f";
property color colorAlpha: "#994f4f4f";
- function adjustCurrentStateIndex() {
- if (currentStateIndex >= statesEditorModel.count)
- currentStateIndex = statesEditorModel.count-1;
- }
-
Connections {
target: statesEditorModel
- onCountChanged: adjustCurrentStateIndex()
- }
-
- Connections {
- target: statesEditorModel
- onChangedToState: root.currentStateIndex = n;
+ onChangedToState: root.currentStateInternalId = n;
}
signal unFocus
@@ -33,9 +23,9 @@ Rectangle {
hoverEnabled:true
onExited: root.unFocus();
}
- onCurrentStateIndexChanged: {
- if (currentStateIndex <= 0)
- currentStateIndex = 0;
+ onCurrentStateInternalIdChanged: {
+ if (currentStateInternalId <= 0)
+ currentStateInternalId = 0;
else
unFocus();
@@ -97,7 +87,7 @@ Rectangle {
height: img.height + txt.height + 29 //(index==0?29:25)
//y:(index==0?0:4)
- property bool isCurrentState: root.currentStateIndex == index;
+ property bool isCurrentState: root.currentStateInternalId == nodeId;
onXChanged: scrollBarAdjuster.adjustScrollBar();
onIsCurrentStateChanged: scrollBarAdjuster.adjustScrollBar();
@@ -115,7 +105,7 @@ Rectangle {
Connections {
target: root
- onStartRenaming: if (root.currentStateIndex == index) startRenaming();
+ onStartRenaming: if (root.currentStateInternalId == index) startRenaming();
}
function startRenaming() {
@@ -160,7 +150,7 @@ Rectangle {
anchors.fill: container
onClicked: {
root.unFocus();
- root.currentStateIndex = index;
+ root.currentStateInternalId = nodeId;
}
}
@@ -184,7 +174,7 @@ Rectangle {
anchors.topMargin: 2
anchors.horizontalCenter: textLimits.horizontalCenter
id: txt
- color: root.currentStateIndex==index ? "white" : "#E1E1E1";
+ color: root.currentStateInternalId==nodeId ? "white" : "#E1E1E1";
text: stateName
width:parent.width
elide:Qt.ElideMiddle
@@ -205,9 +195,9 @@ Rectangle {
id: txtRegion
anchors.fill:parent
onClicked: {
- if (root.currentStateIndex != index)
+ if (root.currentStateInternalId != nodeId)
root.unFocus();
- root.currentStateIndex = index;
+ root.currentStateInternalId = nodeId;
}
onDoubleClicked: if (index!=0) {
startRenaming();
@@ -233,7 +223,7 @@ Rectangle {
function unFocus() {
if (visible) {
visible=false;
- statesEditorModel.renameState(index, stateNameInput.text);
+ statesEditorModel.renameState(nodeId, stateNameInput.text);
}
}
@@ -273,7 +263,7 @@ Rectangle {
onAccepted: {
if (stateNameEditor.visible) {
stateNameEditor.visible = false;
- statesEditorModel.renameState(index,text);
+ statesEditorModel.renameState(nodeId,text);
}
}
}
@@ -285,7 +275,7 @@ Rectangle {
Item {
id: removeState
- visible: (index != 0 && root.currentStateIndex==index)
+ visible: (index != 0 && root.currentStateInternalId==nodeId)
anchors.right: parent.right
anchors.top: parent.top
@@ -372,7 +362,7 @@ Rectangle {
onClicked: {
root.unFocus();
- root.deleteState(index);
+ root.deleteState(nodeId);
horizontalScrollbar.contentSizeDecreased();
}
onPressed: {parent.state="Pressed"}
@@ -569,12 +559,10 @@ Rectangle {
onClicked: {
// force close textinput
root.unFocus();
- if (root.currentStateIndex == 0)
root.createNewState(); //create new state
- else
- root.duplicateCurrentState(); //duplicate current state
+
// select the new state
- root.currentStateIndex = statesEditorModel.count - 1;
+ // root.currentStateInternalId = statesEditorModel.count - 1;
// this should happen automatically
if (floatingNewStateBox.visible)
diff --git a/src/plugins/qmldesigner/designercore/designercore.pri b/src/plugins/qmldesigner/designercore/designercore.pri
index 885e6cb2ea..4124021fe2 100644
--- a/src/plugins/qmldesigner/designercore/designercore.pri
+++ b/src/plugins/qmldesigner/designercore/designercore.pri
@@ -2,7 +2,7 @@ include($$PWD/filemanager/filemanager.pri)
include (../config.pri)
QT += script \
- declarative
+ network
DEFINES += TEST_EXPORTS
INCLUDEPATH += $$PWD \
@@ -11,10 +11,8 @@ DEPENDPATH += $$PWD $$PWD/include
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 \
@@ -27,15 +25,9 @@ SOURCES += $$PWD/model/abstractview.cpp \
$$PWD/model/propertycontainer.cpp \
$$PWD/pluginmanager/widgetpluginmanager.cpp \
$$PWD/pluginmanager/widgetpluginpath.cpp \
- $$PWD/instances/nodeinstance.cpp \
+ $$PWD/instances/servernodeinstance.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 \
@@ -95,23 +87,53 @@ SOURCES += $$PWD/model/abstractview.cpp \
$$PWD/instances/nodeinstancemetaobject.cpp \
$$PWD/instances/behaviornodeinstance.cpp \
$$PWD/instances/nodeinstancesignalspy.cpp \
- $$PWD/instances/positionernodeinstance.cpp
-
+ $$PWD/instances/positionernodeinstance.cpp \
+ $$PWD/instances/nodeinstanceserver.cpp \
+ $$PWD/instances/declarativedesignercommunicationinterface.cpp \
+ $$PWD/instances/createinstancescommand.cpp \
+ $$PWD/instances/nodeinstanceserverinterface.cpp \
+ $$PWD/instances/nodeinstance.cpp \
+ $$PWD/instances/propertyvaluecontainer.cpp \
+ $$PWD/instances/childrenchangeeventfilter.cpp \
+ $$PWD/instances/propertybindingcontainer.cpp \
+ $$PWD/instances/propertyabstractcontainer.cpp \
+ $$PWD/instances/createscenecommand.cpp \
+ $$PWD/instances/instancecontainer.cpp \
+ $$PWD/instances/changefileurlcommand.cpp \
+ $$PWD/instances/clearscenecommand.cpp \
+ $$PWD/instances/reparentcontainer.cpp \
+ $$PWD/instances/reparentinstancescommand.cpp \
+ $$PWD/instances/changevaluescommand.cpp \
+ $$PWD/instances/changebindingscommand.cpp \
+ $$PWD/instances/changeidscommand.cpp \
+ $$PWD/instances/idcontainer.cpp \
+ $$PWD/instances/removeinstancescommand.cpp \
+ $$PWD/instances/removepropertiescommand.cpp \
+ $$PWD/instances/valueschangedcommand.cpp \
+ $$PWD/instances/pixmapchangedcommand.cpp \
+ $$PWD/instances/informationchangedcommand.cpp \
+ $$PWD/instances/informationcontainer.cpp \
+ $$PWD/instances/changestatecommand.cpp \
+ $$PWD/instances/nodeinstanceserverproxy.cpp \
+ $$PWD/instances/nodeinstanceclientproxy.cpp \
+ $$PWD/instances/addimportcommand.cpp \
+ $$PWD/instances/childrenchangedcommand.cpp \
+ $$PWD/instances/statepreviewimagechangedcommand.cpp \
+ $$PWD/instances/imagecontainer.cpp \
+ $$PWD/instances/completecomponentcommand.cpp \
+ $$PWD/instances/componentcompletedcommand.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 \
@@ -120,15 +142,9 @@ HEADERS += $$PWD/include/corelib_global.h \
$$PWD/model/propertyparser.h \
$$PWD/pluginmanager/widgetpluginmanager.h \
$$PWD/pluginmanager/widgetpluginpath.h \
- $$PWD/include/nodeinstance.h \
+ $$PWD/instances/servernodeinstance.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 \
@@ -189,14 +205,45 @@ HEADERS += $$PWD/include/corelib_global.h \
$$PWD/instances/nodeinstancemetaobject.h \
$$PWD/instances/behaviornodeinstance.h \
$$PWD/instances/nodeinstancesignalspy.h \
- $$PWD/instances/positionernodeinstance.h
-
+ $$PWD/instances/positionernodeinstance.h \
+ $$PWD/instances/nodeinstanceserver.h \
+ $$PWD/instances/declarativedesignercommunicationinterface.h \
+ $$PWD/instances/createinstancescommand.h \
+ $$PWD/include/nodeinstanceserverinterface.h \
+ $$PWD/include/nodeinstance.h \
+ $$PWD/include/propertyvaluecontainer.h \
+ $$PWD/instances/childrenchangeeventfilter.h \
+ $$PWD/include/propertybindingcontainer.h \
+ $$PWD/include/propertyabstractcontainer.h \
+ $$PWD/instances/createscenecommand.h \
+ $$PWD/instances/instancecontainer.h \
+ $$PWD/instances/changefileurlcommand.h \
+ $$PWD/instances/clearscenecommand.h \
+ $$PWD/instances/reparentcontainer.h \
+ $$PWD/instances/reparentinstancescommand.h \
+ $$PWD/instances/changevaluescommand.h \
+ $$PWD/instances/changebindingscommand.h \
+ $$PWD/instances/changeidscommand.h \
+ $$PWD/instances/idcontainer.h \
+ $$PWD/instances/removeinstancescommand.h \
+ $$PWD/instances/removepropertiescommand.h \
+ $$PWD/include/nodeinstanceclientinterface.h \
+ $$PWD/instances/valueschangedcommand.h \
+ $$PWD/instances/pixmapchangedcommand.h \
+ $$PWD/instances/informationchangedcommand.h \
+ $$PWD/instances/informationcontainer.h \
+ $$PWD/include/commondefines.h \
+ $$PWD/instances/changestatecommand.h \
+ $$PWD/instances/nodeinstanceserverproxy.h \
+ $$PWD/instances/nodeinstanceclientproxy.h \
+ $$PWD/instances/addimportcommand.h \
+ $$PWD/instances/childrenchangedcommand.h \
+ $$PWD/instances/statepreviewimagechangedcommand.h \
+ $$PWD/instances/imagecontainer.h \
+ $$PWD/instances/completecomponentcommand.h \
+ $$PWD/instances/componentcompletedcommand.h
contains(CONFIG, plugin) {
# If core.pri has been included in the qmldesigner plugin
SOURCES += $$PWD/model/basetexteditmodifier.cpp
HEADERS += $$PWD/include/basetexteditmodifier.h
}
-
-DISTFILES += $$PWD/metafile/widget.metafile
-RESOURCES += $$PWD/designercore.qrc
-OTHER_FILES += $$PWD/metainfo/gui.metainfo
diff --git a/src/plugins/qmldesigner/designercore/designercore.qrc b/src/plugins/qmldesigner/designercore/designercore.qrc
deleted file mode 100644
index d79916781d..0000000000
--- a/src/plugins/qmldesigner/designercore/designercore.qrc
+++ /dev/null
@@ -1,6 +0,0 @@
- <!DOCTYPE RCC>
-<RCC version="1.0">
- <qresource>
- <file>metainfo/gui.metainfo</file>
- </qresource>
- </RCC>
diff --git a/src/plugins/qmldesigner/designercore/exceptions/exceptions.pri b/src/plugins/qmldesigner/designercore/exceptions/exceptions.pri
new file mode 100644
index 0000000000..848d7808fc
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/exceptions/exceptions.pri
@@ -0,0 +1,2 @@
+SOURCES += $$PWD/exception.cpp
+SOURCES += $$PWD/invalidnodeinstanceexception.cpp
diff --git a/src/plugins/qmldesigner/designercore/include/abstractproperty.h b/src/plugins/qmldesigner/designercore/include/abstractproperty.h
index a11cf64410..6fdb665604 100644
--- a/src/plugins/qmldesigner/designercore/include/abstractproperty.h
+++ b/src/plugins/qmldesigner/designercore/include/abstractproperty.h
@@ -56,7 +56,6 @@ namespace QmlDesigner {
class Model;
class ModelNode;
class AbstractView;
-class PropertyMetaInfo;
class CORESHARED_EXPORT VariantProperty;
class CORESHARED_EXPORT NodeListProperty;
class CORESHARED_EXPORT NodeAbstractProperty;
@@ -92,7 +91,6 @@ public:
ModelNode parentModelNode() const;
QmlObjectNode parentQmlObjectNode() const;
- PropertyMetaInfo metaInfo() const;
bool isDefaultProperty() const;
VariantProperty toVariantProperty() const;
NodeListProperty toNodeListProperty() const;
diff --git a/src/plugins/qmldesigner/designercore/include/abstractview.h b/src/plugins/qmldesigner/designercore/include/abstractview.h
index 03040e74fe..ab5fb90bcd 100644
--- a/src/plugins/qmldesigner/designercore/include/abstractview.h
+++ b/src/plugins/qmldesigner/designercore/include/abstractview.h
@@ -65,15 +65,15 @@ class CORESHARED_EXPORT AbstractView : public QObject
{
Q_OBJECT
public:
- Q_FLAGS(PropertyChangeFlag PropertyChangeFlags);
+ Q_FLAGS(PropertyChangeFlag PropertyChangeFlags)
typedef QWeakPointer<AbstractView> Pointer;
enum PropertyChangeFlag {
NoAdditionalChanges = 0x0,
PropertiesAdded = 0x1,
- EmptyPropertiesRemoved = 0x2,
+ EmptyPropertiesRemoved = 0x2
};
- Q_DECLARE_FLAGS(PropertyChangeFlags, PropertyChangeFlag);
+ Q_DECLARE_FLAGS(PropertyChangeFlags, PropertyChangeFlag)
AbstractView(QObject *parent = 0)
: QObject(parent) {}
@@ -101,6 +101,9 @@ public:
ModelNode modelNodeForId(const QString &id);
bool hasId(const QString &id) const;
+ ModelNode modelNodeForInternalId(qint32 internalId);
+ bool hasModelNodeForInternalId(qint32 internalId) const;
+
QList<ModelNode> allModelNodes();
void emitCustomNotification(const QString &identifier);
@@ -108,6 +111,7 @@ public:
void emitCustomNotification(const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> &data);
void emitInstancePropertyChange(const QList<QPair<ModelNode, QString> > &propertyList);
+ void emitInstancesCompleted(const QVector<ModelNode> &nodeList);
virtual void modelAttached(Model *model);
virtual void modelAboutToBeDetached(Model *model);
@@ -115,6 +119,7 @@ public:
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 nodeAboutToBeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::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;
@@ -124,6 +129,8 @@ public:
virtual void rootNodeTypeChanged(const QString &type, int majorVersion, int minorVersion) = 0;
virtual void instancePropertyChange(const QList<QPair<ModelNode, QString> > &propertyList) = 0;
+ virtual void instancesCompleted(const QVector<ModelNode> &completedNodeList) = 0;
+
virtual void selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
const QList<ModelNode> &lastSelectedNodeList) = 0;
diff --git a/src/plugins/qmldesigner/designercore/include/commondefines.h b/src/plugins/qmldesigner/designercore/include/commondefines.h
new file mode 100644
index 0000000000..095e3f6a4e
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/include/commondefines.h
@@ -0,0 +1,31 @@
+#ifndef COMMONDEFINES_H
+#define COMMONDEFINES_H
+
+#include <QMetaType>
+
+namespace QmlDesigner {
+
+enum InformationName
+{
+ NoName,
+ Size,
+ BoundingRect,
+ Transform,
+ HasAnchor,
+ Anchor,
+ InstanceTypeForProperty,
+ PenWidth,
+ Position,
+ IsInPositioner,
+ SceneTransform,
+ IsResizable,
+ IsMovable,
+ IsAnchoredByChildren,
+ IsAnchoredBySibling,
+ HasContent,
+ HasBindingForProperty
+};
+
+}
+
+#endif // COMMONDEFINES_H
diff --git a/src/plugins/qmldesigner/designercore/include/enumeratormetainfo.h b/src/plugins/qmldesigner/designercore/include/enumeratormetainfo.h
deleted file mode 100644
index aca7ab7175..0000000000
--- a/src/plugins/qmldesigner/designercore/include/enumeratormetainfo.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#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;
- QString valueToString(int value) 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/designercore/include/import.h b/src/plugins/qmldesigner/designercore/include/import.h
index 5d5c76b4d8..4d3a27c866 100644
--- a/src/plugins/qmldesigner/designercore/include/import.h
+++ b/src/plugins/qmldesigner/designercore/include/import.h
@@ -35,6 +35,7 @@
#define IMPORT_H
#include <QtCore/QString>
+#include <QStringList>
#include "corelib_global.h"
@@ -43,8 +44,8 @@ namespace QmlDesigner {
class CORESHARED_EXPORT Import
{
public:
- static Import createLibraryImport(const QString &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 createLibraryImport(const QString &url, const QString &version = QString(), const QString &alias = QString(), const QStringList &importPaths = QStringList());
+ static Import createFileImport(const QString &file, const QString &version = QString(), const QString &alias = QString(), const QStringList &importPaths = QStringList());
static Import empty();
bool isEmpty() const { return m_url.isEmpty() && m_file.isEmpty(); }
@@ -57,19 +58,21 @@ public:
QString file() const { return m_file; }
QString version() const { return m_version; }
QString alias() const { return m_alias; }
+ QStringList importPaths() const { return m_importPathList; }
QString toString(bool addSemicolon = false) const;
bool operator==(const Import &other) const;
private:
- Import(const QString &url, const QString &file, const QString &version, const QString &alias);
+ Import(const QString &url, const QString &file, const QString &version, const QString &alias, const QStringList &importPaths);
private:
QString m_url;
QString m_file;
QString m_version;
QString m_alias;
+ QStringList m_importPathList;
};
CORESHARED_EXPORT uint qHash(const Import &import);
diff --git a/src/plugins/qmldesigner/designercore/include/itemlibraryinfo.h b/src/plugins/qmldesigner/designercore/include/itemlibraryinfo.h
index 01000dd86e..1ce82aac8e 100644
--- a/src/plugins/qmldesigner/designercore/include/itemlibraryinfo.h
+++ b/src/plugins/qmldesigner/designercore/include/itemlibraryinfo.h
@@ -45,7 +45,7 @@ namespace Internal {
class ItemLibraryEntryData;
class ItemLibraryInfoPrivate;
-
+class MetaInfoPrivate;
}
class ItemLibraryEntry;
@@ -72,6 +72,7 @@ public:
QString category() const;
QIcon dragIcon() const;
QString qml() const;
+ QString requiredImport() const;
ItemLibraryEntry(const ItemLibraryEntry &other);
ItemLibraryEntry& operator=(const ItemLibraryEntry &other);
@@ -86,8 +87,10 @@ public:
void addProperty(const Property &p);
void addProperty(QString &name, QString &type, QString &value);
void setDragIcon(const QIcon &icon);
+ void setIcon(const QIcon &icon);
void setCategory(const QString &category);
void setQml(const QString &qml);
+ void setRequiredImport(const QString &requiredImport);
private:
QExplicitlySharedDataPointer<Internal::ItemLibraryEntryData> m_data;
};
@@ -105,7 +108,7 @@ public:
ItemLibraryEntry entry(const QString &name) const;
void addEntry(const ItemLibraryEntry &entry);
- bool removeEntry(const QString &name);
+ bool containsEntry(const ItemLibraryEntry &entry);
void clearEntries();
signals:
diff --git a/src/plugins/qmldesigner/designercore/include/metainfo.h b/src/plugins/qmldesigner/designercore/include/metainfo.h
index 2892e9c5fa..efdb60b8a7 100644
--- a/src/plugins/qmldesigner/designercore/include/metainfo.h
+++ b/src/plugins/qmldesigner/designercore/include/metainfo.h
@@ -42,10 +42,7 @@
#include <QtCore/QSharedPointer>
#include <nodemetainfo.h>
-#include "propertymetainfo.h"
#include "itemlibraryinfo.h"
-#include "enumeratormetainfo.h"
-
namespace QmlDesigner {
@@ -70,7 +67,6 @@ class CORESHARED_EXPORT MetaInfo
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:
@@ -78,17 +74,7 @@ public:
~MetaInfo();
MetaInfo& operator=(const MetaInfo &other);
- bool hasNodeMetaInfo(const QString &typeName, int majorVersion = -1, int minorVersion = -1) const;
- NodeMetaInfo nodeMetaInfo(const QString &typeName, int majorVersion = -1, int minorVersion = -1) const;
-
- bool hasEnumerator(const QString &enumeratorName) const;
- EnumeratorMetaInfo enumerator(const QString &enumeratorName) const;
-
ItemLibraryInfo *itemLibraryInfo() const;
-
- QString fromQtTypes(const QString &type) const;
-
-
public:
static MetaInfo global();
static void clearGlobal();
@@ -96,12 +82,6 @@ public:
static void setPluginPaths(const QStringList &paths);
private:
- void addNodeInfo(NodeMetaInfo &info);
- void removeNodeInfo(NodeMetaInfo &info);
-
- EnumeratorMetaInfo addEnumerator(const QString &enumeratorScope, const QString &enumeratorName);
- EnumeratorMetaInfo addFlag(const QString &enumeratorScope, const QString &enumeratorName);
-
bool isGlobal() const;
private:
diff --git a/src/plugins/qmldesigner/designercore/include/metainfoparser.h b/src/plugins/qmldesigner/designercore/include/metainfoparser.h
index d1536b8f23..a3d834bd35 100644
--- a/src/plugins/qmldesigner/designercore/include/metainfoparser.h
+++ b/src/plugins/qmldesigner/designercore/include/metainfoparser.h
@@ -42,8 +42,6 @@
namespace QmlDesigner {
-class NodeMetaInfo;
-class EnumeratorMetaInfo;
class ItemLibraryEntry;
namespace Internal {
@@ -61,14 +59,8 @@ protected:
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 handleNodeItemLibraryEntryElement(QXmlStreamReader &reader, const QString &className);
- void handleAbstractPropertyElement(QXmlStreamReader &reader, NodeMetaInfo &nodeMetaInfo);
- void handleAbstractPropertyDefaultValueElement(QXmlStreamReader &reader, NodeMetaInfo &nodeMetaInfo);
+ void handleNodeItemLibraryEntryElement(QXmlStreamReader &reader, const QString &className, const QIcon &icon);
void handleItemLibraryEntryPropertyElement(QXmlStreamReader &reader, ItemLibraryEntry &itemLibraryEntry);
private:
diff --git a/src/plugins/qmldesigner/designercore/include/model.h b/src/plugins/qmldesigner/designercore/include/model.h
index 4ee6527e80..1170a90098 100644
--- a/src/plugins/qmldesigner/designercore/include/model.h
+++ b/src/plugins/qmldesigner/designercore/include/model.h
@@ -59,9 +59,11 @@ class AbstractView;
class WidgetQueryView;
class NodeStateChangeSet;
class MetaInfo;
+class NodeMetaInfo;
class ModelState;
class NodeAnchors;
class AbstractProperty;
+class RewriterView;
typedef QList<QPair<QString, QVariant> > PropertyListType;
@@ -92,6 +94,7 @@ public:
const MetaInfo metaInfo() const;
MetaInfo metaInfo();
+ NodeMetaInfo metaInfo(const QString &typeName, int majorVersion = -1, int minorVersion = -1);
void setMetaInfo(const MetaInfo &metaInfo);
void attachView(AbstractView *view);
@@ -104,6 +107,8 @@ public:
void addImport(const Import &import);
void removeImport(const Import &import);
+ RewriterView *rewriterView() const;
+
protected:
Model();
diff --git a/src/plugins/qmldesigner/designercore/include/modelnode.h b/src/plugins/qmldesigner/designercore/include/modelnode.h
index 82aad8ba81..d9486595f0 100644
--- a/src/plugins/qmldesigner/designercore/include/modelnode.h
+++ b/src/plugins/qmldesigner/designercore/include/modelnode.h
@@ -65,7 +65,6 @@ class AbstractView;
class NodeListProperty;
class NodeProperty;
class NodeAbstractProperty;
-class NodeInstance;
class ModelNode;
CORESHARED_EXPORT QList<Internal::InternalNodePointer> toInternalNodeList(const QList<ModelNode> &nodeList);
@@ -170,6 +169,8 @@ public:
void setAuxiliaryData(const QString &name, const QVariant &data);
bool hasAuxiliaryData(const QString &name) const;
+ qint32 internalId() const;
+
private: // functions
Internal::InternalNodePointer internalNode() const;
QString generateNewId() const;
diff --git a/src/plugins/qmldesigner/designercore/include/modelutilities.h b/src/plugins/qmldesigner/designercore/include/modelutilities.h
deleted file mode 100644
index d99b8fe7e4..0000000000
--- a/src/plugins/qmldesigner/designercore/include/modelutilities.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#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/designercore/include/nodeabstractproperty.h b/src/plugins/qmldesigner/designercore/include/nodeabstractproperty.h
index 156b318169..ed40cf9e7b 100644
--- a/src/plugins/qmldesigner/designercore/include/nodeabstractproperty.h
+++ b/src/plugins/qmldesigner/designercore/include/nodeabstractproperty.h
@@ -53,6 +53,8 @@ public:
NodeAbstractProperty(const NodeAbstractProperty &property, AbstractView *view);
void reparentHere(const ModelNode &modelNode);
bool isEmpty() const;
+ int count() const;
+ int indexOf(const ModelNode &node) const;
QList<ModelNode> allSubNodes();
diff --git a/src/plugins/qmldesigner/designercore/include/nodeinstance.h b/src/plugins/qmldesigner/designercore/include/nodeinstance.h
index dd6e40a9a4..265fac48ca 100644
--- a/src/plugins/qmldesigner/designercore/include/nodeinstance.h
+++ b/src/plugins/qmldesigner/designercore/include/nodeinstance.h
@@ -31,179 +31,74 @@
**
**************************************************************************/
-#ifndef NODEINSTANCE_H
-#define NODEINSTANCE_H
+#ifndef PROXYNODEINSTANCE_H
+#define PROXYNODEINSTANCE_H
-#include "corelib_global.h"
#include <QSharedPointer>
-#include <QHash>
-#include <QRectF>
-#include <propertymetainfo.h>
-#include <qmlanchors.h>
+#include <QTransform>
+#include <QPointF>
+#include <QSizeF>
+#include <QPair>
-QT_BEGIN_NAMESPACE
-class QPainter;
-class QStyleOptionGraphicsItem;
-class QDeclarativeContext;
-class QGraphicsItem;
-class QGraphicsTransform;
-QT_END_NAMESPACE
+#include "commondefines.h"
namespace QmlDesigner {
class ModelNode;
class NodeInstanceView;
-class Preview;
-class NodeMetaInfo;
-class NodeState;
-class WidgetQueryView;
+class ProxyNodeInstanceData;
-
-namespace Internal {
- class ObjectNodeInstance;
- class QmlGraphicsItemNodeInstance;
- class QmlPropertyChangesNodeInstance;
- class GraphicsObjectNodeInstance;
- class QmlStateNodeInstance;
-}
-
-class CORESHARED_EXPORT NodeInstance
+class 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::GraphicsObjectNodeInstance;
- friend class QmlDesigner::Internal::ObjectNodeInstance;
- friend class QmlDesigner::Internal::QmlPropertyChangesNodeInstance;
- friend class QmlDesigner::Internal::QmlStateNodeInstance;
-
+ friend class NodeInstanceView;
public:
+ static NodeInstance create(const ModelNode &node);
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;
-
-
- bool isTopLevel() const;
-
- bool isQmlGraphicsItem() const;
- bool isGraphicsScene() const;
- bool isGraphicsView() const;
- bool isGraphicsWidget() const;
- bool isProxyWidget() const;
- bool isWidget() const;
- bool isQDeclarativeView() const;
- bool isGraphicsObject() const;
- bool isTransition() const;
- bool isPositioner() 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;
- QString instanceType(const QString &name) const;
-
- bool hasBindingForProperty(const QString &name) const;
-
bool isValid() const;
void makeInvalid();
+ QRectF boundingRect() const;
bool hasContent() const;
- bool isResizable() const;
- bool isMovable() const;
- bool isInPositioner() const;
-
- bool isWrappingThisObject(QObject *object) const;
-
- QVariant resetVariant(const QString &name) const;
-
- bool hasAnchor(const QString &name) const;
bool isAnchoredBySibling() const;
bool isAnchoredByChildren() const;
- QPair<QString, NodeInstance> anchor(const QString &name) const;
-
+ bool isMovable() const;
+ bool isResizable() const;
+ QTransform transform() const;
+ QTransform sceneTransform() const;
+ bool isInPositioner() const;
+ QPointF position() const;
+ QSizeF size() const;
int penWidth() const;
+ void paint(QPainter *painter);
- static void registerDeclarativeTypes();
-
- void doComponentComplete();
-
- QString id() const;
-
-#ifdef QTCREATOR_TEST
- QObject* testHandle() const;
- Internal::ObjectNodeInstance* internalInstance() const;
-#endif
-private: // functions
- NodeInstance(const QSharedPointer<Internal::ObjectNodeInstance> &abstractInstance);
-
- void setModelNode(const ModelNode &node);
-
- 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);
-
- void resetProperty(const QString &name);
- void refreshProperty(const QString &name);
-
- void activateState();
- void deactivateState();
- void refreshState();
-
- bool updateStateVariant(const NodeInstance &target, const QString &propertyName, const QVariant &value);
- bool updateStateBinding(const NodeInstance &target, const QString &propertyName, const QString &expression);
- bool resetStateProperty(const NodeInstance &target, const QString &propertyName, const QVariant &resetValue);
-
- static NodeInstance create(NodeInstanceView *nodeInstanceView, const ModelNode &node, QObject *objectToBeWrapped);
- static NodeInstance create(NodeInstanceView *nodeInstanceView, const NodeMetaInfo &metaInfo, QDeclarativeContext *context);
-
- void setDeleteHeldInstance(bool deleteInstance);
- void reparent(const NodeInstance &oldParentInstance, const QString &oldParentProperty, const NodeInstance &newParentInstance, const QString &newParentProperty);
-
-
- void setId(const QString &id);
-
- static QSharedPointer<Internal::ObjectNodeInstance> createInstance(const NodeMetaInfo &metaInfo, QDeclarativeContext *context, QObject *objectToBeWrapped);
- QSharedPointer<Internal::QmlGraphicsItemNodeInstance> qmlGraphicsItemNodeInstance() const;
+ QVariant property(const QString &name) const;
+ bool hasBindingForProperty(const QString &name) const;
+ QPair<QString, qint32> anchor(const QString &name) const;
+ bool hasAnchor(const QString &name) const;
+ QString instanceType(const QString &name) const;
- void paintUpdate();
+ qint32 parentId() const;
+protected:
+ void setProperty(const QString &name, const QVariant &value);
+ void setInformation(InformationName name,
+ const QVariant &information,
+ const QVariant &secondInformation,
+ const QVariant &thirdInformation);
- QObject *internalObject() const; // should be not used outside of the nodeinstances!!!!
+ void setParentId(qint32 instanceId);
+ void setRenderImage(const QImage &image);
+ NodeInstance(ProxyNodeInstanceData *d);
+ qint32 instanceId() const;
-private: // variables
- QSharedPointer<Internal::ObjectNodeInstance> m_nodeInstance;
+private:
+ QSharedPointer<ProxyNodeInstanceData> d;
};
-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
+#endif // PROXYNODEINSTANCE_H
diff --git a/src/plugins/qmldesigner/designercore/include/nodeinstanceclientinterface.h b/src/plugins/qmldesigner/designercore/include/nodeinstanceclientinterface.h
new file mode 100644
index 0000000000..671282231f
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/include/nodeinstanceclientinterface.h
@@ -0,0 +1,32 @@
+#ifndef NODEINSTANCECLIENTINTERFACE_H
+#define NODEINSTANCECLIENTINTERFACE_H
+
+#include <QtGlobal>
+
+namespace QmlDesigner {
+
+class ValuesChangedCommand;
+class PixmapChangedCommand;
+class InformationChangedCommand;
+class ChildrenChangedCommand;
+class StatePreviewImageChangedCommand;
+class ComponentCompletedCommand;
+
+class NodeInstanceClientInterface
+{
+public:
+ virtual void informationChanged(const InformationChangedCommand &command) = 0;
+ virtual void valuesChanged(const ValuesChangedCommand &command) = 0;
+ virtual void pixmapChanged(const PixmapChangedCommand &command) = 0;
+ virtual void childrenChanged(const ChildrenChangedCommand &command) = 0;
+ virtual void statePreviewImagesChanged(const StatePreviewImageChangedCommand &command) = 0;
+ virtual void componentCompleted(const ComponentCompletedCommand &command) = 0;
+
+ virtual void flush() {};
+ virtual qint64 bytesToWrite() const {return 0;}
+
+};
+
+}
+
+#endif // NODEINSTANCECLIENTINTERFACE_H
diff --git a/src/plugins/qmldesigner/designercore/include/nodeinstanceserverinterface.h b/src/plugins/qmldesigner/designercore/include/nodeinstanceserverinterface.h
new file mode 100644
index 0000000000..dc6d57d400
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/include/nodeinstanceserverinterface.h
@@ -0,0 +1,52 @@
+#ifndef NODEINSTANCESERVERINTERFACE_H
+#define NODEINSTANCESERVERINTERFACE_H
+
+#include <QObject>
+
+namespace QmlDesigner {
+
+class PropertyAbstractContainer;
+class PropertyBindingContainer;
+class PropertyValueContainer;
+
+class ChangeFileUrlCommand;
+class ChangeValuesCommand;
+class ChangeBindingsCommand;
+class CreateSceneCommand;
+class CreateInstancesCommand;
+class ClearSceneCommand;
+class ReparentInstancesCommand;
+class ChangeIdsCommand;
+class RemoveInstancesCommand;
+class RemovePropertiesCommand;
+class ChangeStateCommand;
+class AddImportCommand;
+class CompleteComponentCommand;
+
+class NodeInstanceServerInterface : public QObject
+{
+ Q_OBJECT
+public:
+ explicit NodeInstanceServerInterface(QObject *parent = 0);
+
+ virtual void createInstances(const CreateInstancesCommand &command) = 0;
+ virtual void changeFileUrl(const ChangeFileUrlCommand &command) = 0;
+ virtual void createScene(const CreateSceneCommand &command) = 0;
+ virtual void clearScene(const ClearSceneCommand &command) = 0;
+ virtual void removeInstances(const RemoveInstancesCommand &command) = 0;
+ virtual void removeProperties(const RemovePropertiesCommand &command) = 0;
+ virtual void changePropertyBindings(const ChangeBindingsCommand &command) = 0;
+ virtual void changePropertyValues(const ChangeValuesCommand &command) = 0;
+ virtual void reparentInstances(const ReparentInstancesCommand &command) = 0;
+ virtual void changeIds(const ChangeIdsCommand &command) = 0;
+ virtual void changeState(const ChangeStateCommand &command) = 0;
+ virtual void addImport(const AddImportCommand &command) = 0;
+ virtual void completeComponent(const CompleteComponentCommand &command) = 0;
+
+ virtual void setBlockUpdates(bool /*block*/) {}
+
+ static void registerCommands();
+};
+
+}
+#endif // NODEINSTANCESERVERINTERFACE_H
diff --git a/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h b/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h
index d8cfe5a69f..b885fd1d28 100644
--- a/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h
+++ b/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h
@@ -39,35 +39,45 @@
#include <modelnode.h>
#include <nodeinstance.h>
+#include <nodeinstanceclientinterface.h>
#include <QHash>
+#include <QSet>
#include <QWeakPointer>
+#include <QRectF>
+#include <QTimer>
QT_BEGIN_NAMESPACE
class QDeclarativeEngine;
class QGraphicsView;
class QFileSystemWatcher;
+class QPainter;
QT_END_NAMESPACE
-
namespace QmlDesigner {
-namespace Internal {
- class ChildrenChangeEventFilter;
- class QmlStateNodeInstance;
-}
-
-class CORESHARED_EXPORT NodeInstanceView : public AbstractView
+class NodeInstanceServerInterface;
+class CreateSceneCommand;
+class CreateInstancesCommand;
+class ClearSceneCommand;
+class ReparentInstancesCommand;
+class ChangeFileUrlCommand;
+class ChangeValuesCommand;
+class ChangeBindingsCommand;
+class ChangeIdsCommand;
+class RemoveInstancesCommand;
+class RemovePropertiesCommand;
+class AddImportCommand;
+class CompleteComponentCommand;
+
+class CORESHARED_EXPORT NodeInstanceView : public AbstractView, public NodeInstanceClientInterface
{
Q_OBJECT
friend class NodeInstance;
- friend class Internal::ObjectNodeInstance;
- friend class Internal::QmlStateNodeInstance;
public:
typedef QWeakPointer<NodeInstanceView> Pointer;
- typedef QPair<QWeakPointer<QObject>, QString> ObjectPropertyPair;
NodeInstanceView(QObject *parent = 0);
~NodeInstanceView();
@@ -77,11 +87,11 @@ public:
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 nodeAboutToBeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange);
void nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange);
void rootNodeTypeChanged(const QString &type, int majorVersion, int minorVersion);
void fileUrlChanged(const QUrl &oldUrl, const QUrl &newUrl);
@@ -90,82 +100,89 @@ public:
void selectedNodesChanged(const QList<ModelNode> &selectedNodeList, const QList<ModelNode> &lastSelectedNodeList);
void scriptFunctionsChanged(const ModelNode &node, const QStringList &scriptFunctionList);
void instancePropertyChange(const QList<QPair<ModelNode, QString> > &propertyList);
-
+ void instancesCompleted(const QVector<ModelNode> &completedNodeList);
+ void importAdded(const Import &import);
+ void importRemoved(const Import &import);
QList<NodeInstance> instances() const;
- NodeInstance instanceForNode(const ModelNode &node);
- bool hasInstanceForNode(const ModelNode &node);
-
- NodeInstance instanceForObject(QObject *object);
- bool hasInstanceForObject(QObject *object);
+ NodeInstance instanceForNode(const ModelNode &node) const ;
+ bool hasInstanceForNode(const ModelNode &node) const;
- void render(QPainter *painter, const QRectF &target=QRectF(), const QRectF &source=QRect(), Qt::AspectRatioMode aspectRatioMode=Qt::KeepAspectRatio);
+ NodeInstance instanceForId(qint32 id) const;
+ bool hasInstanceForId(qint32 id) const;
QRectF sceneRect() const;
- void notifyPropertyChange(const ModelNode &modelNode, const QString &propertyName);
-
- void setBlockStatePropertyChanges(bool block);
+ void setBlockUpdates(bool block);
NodeInstance activeStateInstance() const;
void activateState(const NodeInstance &instance);
void activateBaseState();
-private slots:
- void emitParentChanged(QObject *child);
- void refreshLocalFileProperty(const QString &path);
+ void valuesChanged(const ValuesChangedCommand &command);
+ void pixmapChanged(const PixmapChangedCommand &command);
+ void informationChanged(const InformationChangedCommand &command);
+ void childrenChanged(const ChildrenChangedCommand &command);
+ void statePreviewImagesChanged(const StatePreviewImageChangedCommand &command);
+ void componentCompleted(const ComponentCompletedCommand &command);
private: // functions
NodeInstance rootNodeInstance() const;
- NodeInstance loadNode(const ModelNode &rootNode, QObject *objectToBeWrapped = 0);
- void loadModel(Model *model);
+ NodeInstance loadNode(const ModelNode &node);
+
void loadNodes(const QList<ModelNode> &nodeList);
void removeAllInstanceNodeRelationships();
void removeRecursiveChildRelationship(const ModelNode &removedNode);
- void insertInstanceNodeRelationship(const ModelNode &node, const NodeInstance &instance);
+ void insertInstanceRelationships(const NodeInstance &instance);
void removeInstanceNodeRelationship(const ModelNode &node);
- QDeclarativeEngine *engine();
- Internal::ChildrenChangeEventFilter *childrenChangeEventFilter();
void removeInstanceAndSubInstances(const ModelNode &node);
- void setInstancePropertyVariant(const VariantProperty &property);
- void setInstancePropertyBinding(const BindingProperty &property);
- void resetInstanceProperty(const AbstractProperty &property);
-
void setStateInstance(const NodeInstance &stateInstance);
void clearStateInstance();
- QFileSystemWatcher *fileSystemWatcher();
+ NodeInstanceServerInterface *nodeInstanceServer() const;
+
+ CreateSceneCommand createCreateSceneCommand() const;
+ ClearSceneCommand createClearSceneCommand() const;
+ CreateInstancesCommand createCreateInstancesCommand(const QList<NodeInstance> &instanceList) const;
+ CompleteComponentCommand createComponentCompleteCommand(const QList<NodeInstance> &instanceList) const;
+ ComponentCompletedCommand createComponentCompletedCommand(const QList<NodeInstance> &instanceList) const;
+ ReparentInstancesCommand createReparentInstancesCommand(const QList<NodeInstance> &instanceList) const;
+ ReparentInstancesCommand createReparentInstancesCommand(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent) const;
+ ChangeFileUrlCommand createChangeFileUrlCommand(const QUrl &fileUrl) const;
+ ChangeValuesCommand createChangeValueCommand(const QList<VariantProperty> &propertyList) const;
+ ChangeBindingsCommand createChangeBindingCommand(const QList<BindingProperty> &propertyList) const;
+ ChangeIdsCommand createChangeIdsCommand(const QList<NodeInstance> &instanceList) const;
+ RemoveInstancesCommand createRemoveInstancesCommand(const QList<ModelNode> &nodeList) const;
+ RemoveInstancesCommand createRemoveInstancesCommand(const ModelNode &node) const;
+ RemovePropertiesCommand createRemovePropertiesCommand(const QList<AbstractProperty> &propertyList) const;
+ AddImportCommand createImportCommand(const Import &import);
+
+ void resetHorizontalAnchors(const ModelNode &node);
+ void resetVerticalAnchors(const ModelNode &node);
- void addFilePropertyToFileSystemWatcher(QObject *object, const QString &propertyName, const QString &path);
- void removeFilePropertyFromFileSystemWatcher(QObject *object, const QString &propertyName, const QString &path);
+private slots:
+ void restartProcess();
+ void restartProcessDelayed();
private: //variables
NodeInstance m_rootNodeInstance;
NodeInstance m_activeStateInstance;
- QScopedPointer<QGraphicsView> m_graphicsView;
QHash<ModelNode, NodeInstance> m_nodeInstanceHash;
- QHash<QObject*, NodeInstance> m_objectInstanceHash; // This is purely internal. Might contain dangling pointers!
- QMultiHash<QString, ObjectPropertyPair> m_fileSystemWatcherHash;
- QWeakPointer<QDeclarativeEngine> m_engine;
- QWeakPointer<Internal::ChildrenChangeEventFilter> m_childrenChangeEventFilter;
-
- QWeakPointer<QmlModelView> m_qmlModelView;
-
- QWeakPointer<QFileSystemWatcher> m_fileSystemWatcher;
-
- bool m_blockStatePropertyChanges;
-
+ QHash<qint32, NodeInstance> m_idInstanceHash; // This is purely internal. Might contain dangling pointers!
+ uint m_blockUpdates;
+ QWeakPointer<NodeInstanceServerInterface> m_nodeInstanceServer;
+ QTimer m_resetTimer;
};
-} // namespace NodeInstanceView
+} // namespace ProxyNodeInstanceView
#endif // NODEINSTANCEVIEW_H
diff --git a/src/plugins/qmldesigner/designercore/include/nodelistproperty.h b/src/plugins/qmldesigner/designercore/include/nodelistproperty.h
index 200c913cd9..f4267efc66 100644
--- a/src/plugins/qmldesigner/designercore/include/nodelistproperty.h
+++ b/src/plugins/qmldesigner/designercore/include/nodelistproperty.h
@@ -63,8 +63,7 @@ public:
const QList<QmlObjectNode> toQmlObjectNodeList() const;
void slide(int, int) const;
void reparentHere(const ModelNode &modelNode);
-
- bool isEmpty() const;
+ ModelNode at(int index) const;
protected:
NodeListProperty(const QString &propertyName, const Internal::InternalNodePointer &internalNode, Model* model, AbstractView *view);
diff --git a/src/plugins/qmldesigner/designercore/include/nodemetainfo.h b/src/plugins/qmldesigner/designercore/include/nodemetainfo.h
index dba8c9d404..ae7270d4d6 100644
--- a/src/plugins/qmldesigner/designercore/include/nodemetainfo.h
+++ b/src/plugins/qmldesigner/designercore/include/nodemetainfo.h
@@ -49,87 +49,62 @@ QT_END_NAMESPACE
namespace QmlDesigner {
class MetaInfo;
+class Model;
class AbstractProperty;
namespace Internal {
class MetaInfoPrivate;
class MetaInfoParser;
- class NodeMetaInfoData;
class SubComponentManagerPrivate;
class ItemLibraryEntryData;
+ class NodeMetaInfoPrivate;
}
-class PropertyMetaInfo;
-
class CORESHARED_EXPORT NodeMetaInfo
{
- friend class QmlDesigner::MetaInfo;
- friend class QmlDesigner::Internal::ItemLibraryEntryData;
- 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(Model *model, QString type, int maj, int min);
+
~NodeMetaInfo();
NodeMetaInfo(const NodeMetaInfo &other);
NodeMetaInfo &operator=(const NodeMetaInfo &other);
bool isValid() const;
- MetaInfo metaInfo() const;
-
- PropertyMetaInfo property(const QString &propertyName, bool resolveDotSyntax = false) const;
+ bool isComponent() const;
+ bool hasProperty(const QString &propertyName) const;
+ QStringList propertyNames() const;
+ QStringList directPropertyNames() const;
+ QString defaultPropertyName() const;
+ bool hasDefaultProperty() const;
+ QString propertyTypeName(const QString &propertyName) const;
+ bool propertyIsWritable(const QString &propertyName) const;
+ bool propertyIsListProperty(const QString &propertyName) const;
+ bool propertyIsEnumType(const QString &propertyName) const;
+ QString propertyEnumScope(const QString &propertyName) const;
+ QStringList propertyKeysForEnum(const QString &propertyName) const;
+ QVariant propertyCastedValue(const QString &propertyName, const QVariant &value) const;
QList<NodeMetaInfo> superClasses() const;
NodeMetaInfo directSuperClass() const;
- QHash<QString,PropertyMetaInfo> properties(bool resolveDotSyntax = false) const;
QString typeName() const;
int majorVersion() const;
int minorVersion() const;
- bool availableInVersion(int majorVersion, int minorVersion) const;
-
- bool hasDefaultProperty() const;
- QString defaultProperty() const;
+ QString componentSource() const;
+ QString componentFileName() const;
- bool hasProperty(const QString &propertyName, bool resolveDotSyntax = false) const;
- bool isContainer() const;
- bool isComponent() const;
+ bool availableInVersion(int majorVersion, int minorVersion) const;
bool isSubclassOf(const QString& type, int majorVersion, int minorVersio) const;
- QString componentString() const;
- QIcon icon() const;
+ static void clearCache();
private:
- NodeMetaInfo();
- NodeMetaInfo(const MetaInfo &metaInfo);
-
- void setInvalid();
- void setType(const QString &typeName, int majorVersion, int minorVersion);
- void addProperty(const PropertyMetaInfo &property);
- void setIsContainer(bool isContainer);
- void setIcon(const QIcon &icon);
- void setQmlFile(const QString &filePath);
- void setDefaultProperty(const QString &defaultProperty);
- void setSuperClass(const QString &typeName, int majorVersion = -1, int minorVersion = -1);
-
- bool hasLocalProperty(const QString &propertyName, bool resolveDotSyntax = false) const;
- QHash<QString,PropertyMetaInfo> dotProperties() const;
-
-private:
- QExplicitlySharedDataPointer<Internal::NodeMetaInfoData> m_data;
+ QSharedPointer<Internal::NodeMetaInfoPrivate> m_privateData;
};
-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);
-}
+} //QmlDesigner
#endif // NODEMETAINFO_H
diff --git a/src/plugins/qmldesigner/designercore/include/propertyabstractcontainer.h b/src/plugins/qmldesigner/designercore/include/propertyabstractcontainer.h
new file mode 100644
index 0000000000..7d5b141368
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/include/propertyabstractcontainer.h
@@ -0,0 +1,40 @@
+#ifndef PROPERTYABSTRACTCONTAINER_H
+#define PROPERTYABSTRACTCONTAINER_H
+
+#include <QDataStream>
+#include <qmetatype.h>
+#include <QString>
+
+
+namespace QmlDesigner {
+
+class PropertyAbstractContainer;
+
+QDataStream &operator<<(QDataStream &out, const PropertyAbstractContainer &container);
+QDataStream &operator>>(QDataStream &in, PropertyAbstractContainer &container);
+
+class PropertyAbstractContainer
+{
+
+ friend QDataStream &operator<<(QDataStream &out, const PropertyAbstractContainer &container);
+ friend QDataStream &operator>>(QDataStream &in, PropertyAbstractContainer &container);
+public:
+ PropertyAbstractContainer();
+ PropertyAbstractContainer(qint32 instanceId, const QString &name, const QString &dynamicTypeName);
+
+ qint32 instanceId() const;
+ QString name() const;
+ bool isDynamic() const;
+ QString dynamicTypeName() const;
+
+private:
+ qint32 m_instanceId;
+ QString m_name;
+ QString m_dynamicTypeName;
+};
+
+
+} // namespace QmlDesigner
+
+Q_DECLARE_METATYPE(QmlDesigner::PropertyAbstractContainer)
+#endif // PROPERTYABSTRACTCONTAINER_H
diff --git a/src/plugins/qmldesigner/designercore/include/propertybindingcontainer.h b/src/plugins/qmldesigner/designercore/include/propertybindingcontainer.h
new file mode 100644
index 0000000000..68d75bce9c
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/include/propertybindingcontainer.h
@@ -0,0 +1,38 @@
+#ifndef PROPERTYBINDINGCONTAINER_H
+#define PROPERTYBINDINGCONTAINER_H
+
+#include <QDataStream>
+#include <qmetatype.h>
+#include <QString>
+
+
+namespace QmlDesigner {
+
+class PropertyBindingContainer
+{
+ friend QDataStream &operator>>(QDataStream &in, PropertyBindingContainer &container);
+
+public:
+ PropertyBindingContainer();
+ PropertyBindingContainer(qint32 instanceId, const QString &name, const QString &expression, const QString &dynamicTypeName);
+
+ qint32 instanceId() const;
+ QString name() const;
+ QString expression() const;
+ bool isDynamic() const;
+ QString dynamicTypeName() const;
+
+private:
+ qint32 m_instanceId;
+ QString m_name;
+ QString m_expression;
+ QString m_dynamicTypeName;
+};
+
+QDataStream &operator<<(QDataStream &out, const PropertyBindingContainer &container);
+QDataStream &operator>>(QDataStream &in, PropertyBindingContainer &container);
+
+} // namespace QmlDesigner
+
+Q_DECLARE_METATYPE(QmlDesigner::PropertyBindingContainer)
+#endif // PROPERTYBINDINGCONTAINER_H
diff --git a/src/plugins/qmldesigner/designercore/include/propertycontainer.h b/src/plugins/qmldesigner/designercore/include/propertycontainer.h
index 04a7a69180..5eabbf1849 100644
--- a/src/plugins/qmldesigner/designercore/include/propertycontainer.h
+++ b/src/plugins/qmldesigner/designercore/include/propertycontainer.h
@@ -41,8 +41,6 @@
#include <QDataStream>
#include <QVariant>
-#include <enumeratormetainfo.h>
-
namespace QmlDesigner {
class PropertyContainer;
diff --git a/src/plugins/qmldesigner/designercore/include/propertymetainfo.h b/src/plugins/qmldesigner/designercore/include/propertymetainfo.h
deleted file mode 100644
index 17f155883a..0000000000
--- a/src/plugins/qmldesigner/designercore/include/propertymetainfo.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#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/designercore/include/propertyvaluecontainer.h b/src/plugins/qmldesigner/designercore/include/propertyvaluecontainer.h
new file mode 100644
index 0000000000..5948ec8241
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/include/propertyvaluecontainer.h
@@ -0,0 +1,42 @@
+#ifndef PROPERTYVALUECONTAINER_H
+#define PROPERTYVALUECONTAINER_H
+
+#include <QDataStream>
+#include <QMetaType>
+#include <QVariant>
+#include <QString>
+
+#include "commondefines.h"
+
+namespace QmlDesigner {
+
+
+class PropertyValueContainer
+{
+ friend QDataStream &operator>>(QDataStream &in, PropertyValueContainer &container);
+
+public:
+ PropertyValueContainer();
+ PropertyValueContainer(qint32 instanceId, const QString &name, const QVariant &value, const QString &dynamicTypeName);
+
+ qint32 instanceId() const;
+ QString name() const;
+ QVariant value() const;
+ bool isDynamic() const;
+ QString dynamicTypeName() const;
+
+private:
+ qint32 m_instanceId;
+ QString m_name;
+ QVariant m_value;
+ QString m_dynamicTypeName;
+};
+
+QDataStream &operator<<(QDataStream &out, const PropertyValueContainer &container);
+QDataStream &operator>>(QDataStream &in, PropertyValueContainer &container);
+
+} // namespace QmlDesigner
+
+Q_DECLARE_METATYPE(QmlDesigner::PropertyValueContainer)
+
+#endif // PROPERTYVALUECONTAINER_H
diff --git a/src/plugins/qmldesigner/designercore/include/qmlitemnode.h b/src/plugins/qmldesigner/designercore/include/qmlitemnode.h
index e98c1667e3..fe0d12a117 100644
--- a/src/plugins/qmldesigner/designercore/include/qmlitemnode.h
+++ b/src/plugins/qmldesigner/designercore/include/qmlitemnode.h
@@ -84,7 +84,7 @@ public:
int instancePenWidth() const;
- void paintInstance(QPainter *painter) const;
+ void paintInstance(QPainter *painter);
void selectNode();
void deselectNode();
@@ -102,6 +102,8 @@ CORESHARED_EXPORT uint qHash(const QmlItemNode &node);
class CORESHARED_EXPORT QmlModelStateGroup
{
friend class QmlItemNode;
+ friend class QmlModelView;
+
public:
QmlModelStateGroup() : m_modelNode(ModelNode()) {}
diff --git a/src/plugins/qmldesigner/designercore/include/qmlmodelview.h b/src/plugins/qmldesigner/designercore/include/qmlmodelview.h
index 35300579da..aa80c299d1 100644
--- a/src/plugins/qmldesigner/designercore/include/qmlmodelview.h
+++ b/src/plugins/qmldesigner/designercore/include/qmlmodelview.h
@@ -58,6 +58,7 @@ public:
QmlModelState currentState() const;
QmlModelState baseState() const;
+ QmlModelStateGroup rootStateGroup() const;
QmlObjectNode createQmlObjectNode(const QString &typeString,
int majorVersion,
@@ -94,9 +95,11 @@ public:
virtual void nodeInstancePropertyChanged(const ModelNode &node, const QString &propertyName);
void instancePropertyChange(const QList<QPair<ModelNode, QString> > &propertyList);
+ void instancesCompleted(const QVector<ModelNode> &completedNodeList);
void nodeCreated(const ModelNode &createdNode);
void nodeRemoved(const ModelNode &removedNode, const NodeAbstractProperty &parentProperty, PropertyChangeFlags propertyChange);
+ void nodeAboutToBeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange);
void nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange);
void propertiesAboutToBeRemoved(const QList<AbstractProperty> &propertyList);
void rootNodeTypeChanged(const QString &type, int majorVersion, int minorVersion);
diff --git a/src/plugins/qmldesigner/designercore/include/qmlobjectnode.h b/src/plugins/qmldesigner/designercore/include/qmlobjectnode.h
index 484ad999f6..13629a9112 100644
--- a/src/plugins/qmldesigner/designercore/include/qmlobjectnode.h
+++ b/src/plugins/qmldesigner/designercore/include/qmlobjectnode.h
@@ -39,6 +39,8 @@
#include "qmlstate.h"
#include "qmlchangeset.h"
+#include <nodeinstance.h>
+
namespace QmlDesigner {
class QmlItemNode;
diff --git a/src/plugins/qmldesigner/designercore/include/rewriterview.h b/src/plugins/qmldesigner/designercore/include/rewriterview.h
index 521403ada4..b47f1f656b 100644
--- a/src/plugins/qmldesigner/designercore/include/rewriterview.h
+++ b/src/plugins/qmldesigner/designercore/include/rewriterview.h
@@ -47,6 +47,13 @@
#include <modelnode.h>
#include <QScopedPointer>
+namespace QmlJS {
+
+class DiagnosticMessage;
+class LookupContext;
+class Document;
+}
+
namespace QmlDesigner {
@@ -60,7 +67,6 @@ class ModelNodePositionStorage;
} //Internal
-
class CORESHARED_EXPORT RewriterView : public AbstractView
{
Q_OBJECT
@@ -81,7 +87,7 @@ public:
public:
Error();
- Error(const QDeclarativeError &qmlError);
+ Error(const QmlJS::DiagnosticMessage &qmlError, const QUrl &document);
Error(const QString &shortDescription);
Error(Exception *exception);
@@ -124,6 +130,7 @@ public:
void propertiesRemoved(const QList<AbstractProperty>& propertyList);
void variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags propertyChange);
void bindingPropertiesChanged(const QList<BindingProperty>& propertyList, PropertyChangeFlags propertyChange);
+ void nodeAboutToBeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::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 nodeOrderChanged(const NodeListProperty &listProperty, const ModelNode &movedNode, int oldIndex);
@@ -132,6 +139,7 @@ public:
void scriptFunctionsChanged(const ModelNode &node, const QStringList &scriptFunctionList);
void instancePropertyChange(const QList<QPair<ModelNode, QString> > &propertyList);
+ void instancesCompleted(const QVector<ModelNode> &completedNodeList);
void importAdded(const Import &import);
void importRemoved(const Import &import);
@@ -166,6 +174,9 @@ public:
bool renameId(const QString& oldId, const QString& newId);
+ QmlJS::LookupContext *lookupContext() const;
+ QmlJS::Document *document() const;
+
signals:
void errorsChanged(const QList<RewriterView::Error> &errors);
diff --git a/src/plugins/qmldesigner/designercore/instances/addimportcommand.cpp b/src/plugins/qmldesigner/designercore/instances/addimportcommand.cpp
new file mode 100644
index 0000000000..bb132896d0
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/addimportcommand.cpp
@@ -0,0 +1,65 @@
+#include "addimportcommand.h"
+
+namespace QmlDesigner {
+
+AddImportCommand::AddImportCommand()
+{
+}
+
+AddImportCommand::AddImportCommand(const QUrl &url, const QString &fileName, const QString &version, const QString &alias, const QStringList &importPathList)
+ : m_url(url),
+ m_fileName(fileName),
+ m_version(version),
+ m_alias(alias),
+ m_importPathList(importPathList)
+{
+}
+
+QUrl AddImportCommand::url() const
+{
+ return m_url;
+}
+
+QString AddImportCommand::fileName() const
+{
+ return m_fileName;
+}
+
+QString AddImportCommand::version() const
+{
+ return m_version;
+}
+
+QString AddImportCommand::alias() const
+{
+ return m_alias;
+}
+
+QStringList AddImportCommand::importPaths() const
+{
+ return m_importPathList;
+}
+
+QDataStream &operator<<(QDataStream &out, const AddImportCommand &command)
+{
+ out << command.url();
+ out << command.fileName();
+ out << command.version();
+ out << command.alias();
+ out << command.importPaths();
+
+ return out;
+}
+
+QDataStream &operator>>(QDataStream &in, AddImportCommand &command)
+{
+ in >> command.m_url;
+ in >> command.m_fileName;
+ in >> command.m_version;
+ in >> command.m_alias;
+ in >> command.m_importPathList;
+
+ return in;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/addimportcommand.h b/src/plugins/qmldesigner/designercore/instances/addimportcommand.h
new file mode 100644
index 0000000000..748e40b47f
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/addimportcommand.h
@@ -0,0 +1,39 @@
+#ifndef ADDIMPORTCOMMAND_H
+#define ADDIMPORTCOMMAND_H
+
+#include <QMetaType>
+#include <QUrl>
+#include <QString>
+#include <QStringList>
+
+namespace QmlDesigner {
+
+class AddImportCommand
+{
+ friend QDataStream &operator>>(QDataStream &in, AddImportCommand &command);
+public:
+ AddImportCommand();
+ AddImportCommand(const QUrl &url, const QString &fileName, const QString &version, const QString &alias, const QStringList &mportPathList);
+
+ QUrl url() const;
+ QString fileName() const;
+ QString version() const;
+ QString alias() const;
+ QStringList importPaths() const;
+
+private:
+ QUrl m_url;
+ QString m_fileName;
+ QString m_version;
+ QString m_alias;
+ QStringList m_importPathList;
+};
+
+QDataStream &operator<<(QDataStream &out, const AddImportCommand &command);
+QDataStream &operator>>(QDataStream &in, AddImportCommand &command);
+
+} // namespace QmlDesigner
+
+Q_DECLARE_METATYPE(QmlDesigner::AddImportCommand)
+
+#endif // ADDIMPORTCOMMAND_H
diff --git a/src/plugins/qmldesigner/designercore/instances/behaviornodeinstance.cpp b/src/plugins/qmldesigner/designercore/instances/behaviornodeinstance.cpp
index 7ea3f08fb4..77d82443c7 100644
--- a/src/plugins/qmldesigner/designercore/instances/behaviornodeinstance.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/behaviornodeinstance.cpp
@@ -13,23 +13,15 @@ BehaviorNodeInstance::BehaviorNodeInstance(QObject *object)
{
}
-BehaviorNodeInstance::Pointer BehaviorNodeInstance::create(const NodeMetaInfo &nodeMetaInfo, QDeclarativeContext *context, QObject *objectToBeWrapped)
+BehaviorNodeInstance::Pointer BehaviorNodeInstance::create(QObject *object)
{
- QObject *object = 0;
- if (objectToBeWrapped)
- object = objectToBeWrapped;
- else
- object = createObject(nodeMetaInfo, context);
-
QDeclarativeBehavior* behavior = qobject_cast<QDeclarativeBehavior*>(object);
+
if (behavior == 0)
throw InvalidNodeInstanceException(__LINE__, __FUNCTION__, __FILE__);
Pointer instance(new BehaviorNodeInstance(behavior));
- if (objectToBeWrapped)
- instance->setDeleteHeldInstance(false); // the object isn't owned
-
instance->populateResetValueHash();
behavior->setEnabled(false);
diff --git a/src/plugins/qmldesigner/designercore/instances/behaviornodeinstance.h b/src/plugins/qmldesigner/designercore/instances/behaviornodeinstance.h
index 9addf049d5..62951653f6 100644
--- a/src/plugins/qmldesigner/designercore/instances/behaviornodeinstance.h
+++ b/src/plugins/qmldesigner/designercore/instances/behaviornodeinstance.h
@@ -14,7 +14,7 @@ public:
BehaviorNodeInstance(QObject *object);
- static Pointer create(const NodeMetaInfo &metaInfo, QDeclarativeContext *context, QObject *objectToBeWrapped);
+ static Pointer create(QObject *objectToBeWrapped);
void setPropertyVariant(const QString &name, const QVariant &value);
void setPropertyBinding(const QString &name, const QString &expression);
diff --git a/src/plugins/qmldesigner/designercore/instances/changebindingscommand.cpp b/src/plugins/qmldesigner/designercore/instances/changebindingscommand.cpp
new file mode 100644
index 0000000000..9d8c5decc7
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/changebindingscommand.cpp
@@ -0,0 +1,32 @@
+#include "changebindingscommand.h"
+
+namespace QmlDesigner {
+
+ChangeBindingsCommand::ChangeBindingsCommand()
+{
+}
+
+ChangeBindingsCommand::ChangeBindingsCommand(const QVector<PropertyBindingContainer> &bindingChangeVector)
+ : m_bindingChangeVector (bindingChangeVector)
+{
+}
+
+QVector<PropertyBindingContainer> ChangeBindingsCommand::bindingChanges() const
+{
+ return m_bindingChangeVector;
+}
+
+QDataStream &operator<<(QDataStream &out, const ChangeBindingsCommand &command)
+{
+ out << command.bindingChanges();
+
+ return out;
+}
+
+QDataStream &operator>>(QDataStream &in, ChangeBindingsCommand &command)
+{
+ in >> command.m_bindingChangeVector;
+
+ return in;
+}
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/changebindingscommand.h b/src/plugins/qmldesigner/designercore/instances/changebindingscommand.h
new file mode 100644
index 0000000000..ab3f310d18
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/changebindingscommand.h
@@ -0,0 +1,32 @@
+#ifndef CHANGEBINDINGSCOMMAND_H
+#define CHANGEBINDINGSCOMMAND_H
+
+#include <QMetaType>
+#include <QVector>
+
+#include "propertybindingcontainer.h"
+
+namespace QmlDesigner {
+
+class ChangeBindingsCommand
+{
+ friend QDataStream &operator>>(QDataStream &in, ChangeBindingsCommand &command);
+
+public:
+ ChangeBindingsCommand();
+ ChangeBindingsCommand(const QVector<PropertyBindingContainer> &bindingChangeVector);
+
+ QVector<PropertyBindingContainer> bindingChanges() const;
+
+private:
+ QVector<PropertyBindingContainer> m_bindingChangeVector;
+};
+
+QDataStream &operator<<(QDataStream &out, const ChangeBindingsCommand &command);
+QDataStream &operator>>(QDataStream &in, ChangeBindingsCommand &command);
+
+} // namespace QmlDesigner
+
+Q_DECLARE_METATYPE(QmlDesigner::ChangeBindingsCommand)
+
+#endif // CHANGEBINDINGSCOMMAND_H
diff --git a/src/plugins/qmldesigner/designercore/instances/changefileurlcommand.cpp b/src/plugins/qmldesigner/designercore/instances/changefileurlcommand.cpp
new file mode 100644
index 0000000000..39939102ac
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/changefileurlcommand.cpp
@@ -0,0 +1,33 @@
+#include "changefileurlcommand.h"
+
+namespace QmlDesigner {
+
+ChangeFileUrlCommand::ChangeFileUrlCommand()
+{
+}
+
+ChangeFileUrlCommand::ChangeFileUrlCommand(const QUrl &fileUrl)
+ : m_fileUrl(fileUrl)
+{
+}
+
+QUrl ChangeFileUrlCommand::fileUrl() const
+{
+ return m_fileUrl;
+}
+
+QDataStream &operator<<(QDataStream &out, const ChangeFileUrlCommand &command)
+{
+ out << command.fileUrl();
+
+ return out;
+}
+
+QDataStream &operator>>(QDataStream &in, ChangeFileUrlCommand &command)
+{
+ in >> command.m_fileUrl;
+
+ return in;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/changefileurlcommand.h b/src/plugins/qmldesigner/designercore/instances/changefileurlcommand.h
new file mode 100644
index 0000000000..3a31c5b89e
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/changefileurlcommand.h
@@ -0,0 +1,30 @@
+#ifndef CHANGEFILEURLCOMMAND_H
+#define CHANGEFILEURLCOMMAND_H
+
+#include <qmetatype.h>
+#include <QUrl>
+
+namespace QmlDesigner {
+
+class ChangeFileUrlCommand
+{
+ friend QDataStream &operator>>(QDataStream &in, ChangeFileUrlCommand &command);
+public:
+ ChangeFileUrlCommand();
+ ChangeFileUrlCommand(const QUrl &fileUrl);
+
+ QUrl fileUrl() const;
+
+private:
+ QUrl m_fileUrl;
+};
+
+
+QDataStream &operator<<(QDataStream &out, const ChangeFileUrlCommand &command);
+QDataStream &operator>>(QDataStream &in, ChangeFileUrlCommand &command);
+
+} // namespace QmlDesigner
+
+Q_DECLARE_METATYPE(QmlDesigner::ChangeFileUrlCommand)
+
+#endif // CHANGEFILEURLCOMMAND_H
diff --git a/src/plugins/qmldesigner/designercore/instances/changeidscommand.cpp b/src/plugins/qmldesigner/designercore/instances/changeidscommand.cpp
new file mode 100644
index 0000000000..0d15a6b2bf
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/changeidscommand.cpp
@@ -0,0 +1,33 @@
+#include "changeidscommand.h"
+
+namespace QmlDesigner {
+
+ChangeIdsCommand::ChangeIdsCommand()
+{
+}
+
+ChangeIdsCommand::ChangeIdsCommand(const QVector<IdContainer> &idVector)
+ : m_idVector(idVector)
+{
+}
+
+QVector<IdContainer> ChangeIdsCommand::ids() const
+{
+ return m_idVector;
+}
+
+QDataStream &operator<<(QDataStream &out, const ChangeIdsCommand &command)
+{
+ out << command.ids();
+
+ return out;
+}
+
+QDataStream &operator>>(QDataStream &in, ChangeIdsCommand &command)
+{
+ in >> command.m_idVector;
+
+ return in;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/changeidscommand.h b/src/plugins/qmldesigner/designercore/instances/changeidscommand.h
new file mode 100644
index 0000000000..a80e980209
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/changeidscommand.h
@@ -0,0 +1,32 @@
+#ifndef CHANGEIDSCOMMAND_H
+#define CHANGEIDSCOMMAND_H
+
+#include <QMetaType>
+#include <QVector>
+
+
+#include "idcontainer.h"
+
+namespace QmlDesigner {
+
+class ChangeIdsCommand
+{
+ friend QDataStream &operator>>(QDataStream &in, ChangeIdsCommand &command);
+public:
+ ChangeIdsCommand();
+ ChangeIdsCommand(const QVector<IdContainer> &idVector);
+
+ QVector<IdContainer> ids() const;
+
+private:
+ QVector<IdContainer> m_idVector;
+};
+
+QDataStream &operator<<(QDataStream &out, const ChangeIdsCommand &command);
+QDataStream &operator>>(QDataStream &in, ChangeIdsCommand &command);
+
+} // namespace QmlDesigner
+
+Q_DECLARE_METATYPE(QmlDesigner::ChangeIdsCommand)
+
+#endif // CHANGEIDSCOMMAND_H
diff --git a/src/plugins/qmldesigner/designercore/instances/changestatecommand.cpp b/src/plugins/qmldesigner/designercore/instances/changestatecommand.cpp
new file mode 100644
index 0000000000..43f4902b6b
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/changestatecommand.cpp
@@ -0,0 +1,34 @@
+#include "changestatecommand.h"
+
+namespace QmlDesigner {
+
+ChangeStateCommand::ChangeStateCommand()
+ : m_stateInstanceId(-1)
+{
+}
+
+ChangeStateCommand::ChangeStateCommand(qint32 stateInstanceId)
+ : m_stateInstanceId(stateInstanceId)
+{
+}
+
+qint32 ChangeStateCommand::stateInstanceId() const
+{
+ return m_stateInstanceId;
+}
+
+QDataStream &operator<<(QDataStream &out, const ChangeStateCommand &command)
+{
+ out << command.stateInstanceId();
+
+ return out;
+}
+
+QDataStream &operator>>(QDataStream &in, ChangeStateCommand &command)
+{
+ in >> command.m_stateInstanceId;
+
+ return in;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/changestatecommand.h b/src/plugins/qmldesigner/designercore/instances/changestatecommand.h
new file mode 100644
index 0000000000..66f1748228
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/changestatecommand.h
@@ -0,0 +1,32 @@
+#ifndef CHANGESTATECOMMAND_H
+#define CHANGESTATECOMMAND_H
+
+#include <QMetaType>
+#include <QVector>
+
+#include "propertyvaluecontainer.h"
+
+namespace QmlDesigner {
+
+class ChangeStateCommand
+{
+ friend QDataStream &operator>>(QDataStream &in, ChangeStateCommand &command);
+
+public:
+ ChangeStateCommand();
+ ChangeStateCommand(qint32 stateInstanceId);
+
+ qint32 stateInstanceId() const;
+
+private:
+ qint32 m_stateInstanceId;
+};
+
+QDataStream &operator<<(QDataStream &out, const ChangeStateCommand &command);
+QDataStream &operator>>(QDataStream &in, ChangeStateCommand &command);
+
+} // namespace QmlDesigner
+
+Q_DECLARE_METATYPE(QmlDesigner::ChangeStateCommand)
+
+#endif // CHANGESTATECOMMAND_H
diff --git a/src/plugins/qmldesigner/designercore/instances/changevaluescommand.cpp b/src/plugins/qmldesigner/designercore/instances/changevaluescommand.cpp
new file mode 100644
index 0000000000..f00ebffa1c
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/changevaluescommand.cpp
@@ -0,0 +1,33 @@
+#include "changevaluescommand.h"
+
+namespace QmlDesigner {
+
+ChangeValuesCommand::ChangeValuesCommand()
+{
+}
+
+ChangeValuesCommand::ChangeValuesCommand(const QVector<PropertyValueContainer> &valueChangeVector)
+ : m_valueChangeVector (valueChangeVector)
+{
+}
+
+QVector<PropertyValueContainer> ChangeValuesCommand::valueChanges() const
+{
+ return m_valueChangeVector;
+}
+
+QDataStream &operator<<(QDataStream &out, const ChangeValuesCommand &command)
+{
+ out << command.valueChanges();
+
+ return out;
+}
+
+QDataStream &operator>>(QDataStream &in, ChangeValuesCommand &command)
+{
+ in >> command.m_valueChangeVector;
+
+ return in;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/changevaluescommand.h b/src/plugins/qmldesigner/designercore/instances/changevaluescommand.h
new file mode 100644
index 0000000000..eb8932a710
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/changevaluescommand.h
@@ -0,0 +1,32 @@
+#ifndef CHANGEVALUESCOMMAND_H
+#define CHANGEVALUESCOMMAND_H
+
+#include <QMetaType>
+#include <QVector>
+
+#include "propertyvaluecontainer.h"
+
+namespace QmlDesigner {
+
+class ChangeValuesCommand
+{
+ friend QDataStream &operator>>(QDataStream &in, ChangeValuesCommand &command);
+
+public:
+ ChangeValuesCommand();
+ ChangeValuesCommand(const QVector<PropertyValueContainer> &valueChangeVector);
+
+ QVector<PropertyValueContainer> valueChanges() const;
+
+private:
+ QVector<PropertyValueContainer> m_valueChangeVector;
+};
+
+QDataStream &operator<<(QDataStream &out, const ChangeValuesCommand &command);
+QDataStream &operator>>(QDataStream &in, ChangeValuesCommand &command);
+
+} // namespace QmlDesigner
+
+Q_DECLARE_METATYPE(QmlDesigner::ChangeValuesCommand)
+
+#endif // CHANGEVALUESCOMMAND_H
diff --git a/src/plugins/qmldesigner/designercore/instances/childrenchangedcommand.cpp b/src/plugins/qmldesigner/designercore/instances/childrenchangedcommand.cpp
new file mode 100644
index 0000000000..bd89b4496a
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/childrenchangedcommand.cpp
@@ -0,0 +1,42 @@
+#include "childrenchangedcommand.h"
+
+namespace QmlDesigner {
+
+ChildrenChangedCommand::ChildrenChangedCommand()
+ : m_parentInstanceId(-1)
+{
+}
+
+ChildrenChangedCommand::ChildrenChangedCommand(qint32 parentInstanceId, const QVector<qint32> &children)
+ : m_parentInstanceId(parentInstanceId),
+ m_childrenVector(children)
+{
+}
+
+QVector<qint32> ChildrenChangedCommand::childrenInstances() const
+{
+ return m_childrenVector;
+}
+
+qint32 ChildrenChangedCommand::parentInstanceId() const
+{
+ return m_parentInstanceId;
+}
+
+QDataStream &operator<<(QDataStream &out, const ChildrenChangedCommand &command)
+{
+ out << command.parentInstanceId();
+ out << command.childrenInstances();
+
+ return out;
+}
+
+QDataStream &operator>>(QDataStream &in, ChildrenChangedCommand &command)
+{
+ in >> command.m_parentInstanceId;
+ in >> command.m_childrenVector;
+
+ return in;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/childrenchangedcommand.h b/src/plugins/qmldesigner/designercore/instances/childrenchangedcommand.h
new file mode 100644
index 0000000000..1b3c45706c
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/childrenchangedcommand.h
@@ -0,0 +1,32 @@
+#ifndef CHILDRENCHANGEDCOMMAND_H
+#define CHILDRENCHANGEDCOMMAND_H
+
+#include <QMetaType>
+#include <QVector>
+
+
+namespace QmlDesigner {
+
+class ChildrenChangedCommand
+{
+ friend QDataStream &operator>>(QDataStream &in, ChildrenChangedCommand &command);
+public:
+ ChildrenChangedCommand();
+ ChildrenChangedCommand(qint32 parentInstanceId, const QVector<qint32> &childrenInstances);
+
+ QVector<qint32> childrenInstances() const;
+ qint32 parentInstanceId() const;
+
+private:
+ qint32 m_parentInstanceId;
+ QVector<qint32> m_childrenVector;
+};
+
+QDataStream &operator<<(QDataStream &out, const ChildrenChangedCommand &command);
+QDataStream &operator>>(QDataStream &in, ChildrenChangedCommand &command);
+
+} // namespace QmlDesigner
+
+Q_DECLARE_METATYPE(QmlDesigner::ChildrenChangedCommand)
+
+#endif // CHILDRENCHANGEDCOMMAND_H
diff --git a/src/plugins/qmldesigner/designercore/instances/childrenchangeeventfilter.cpp b/src/plugins/qmldesigner/designercore/instances/childrenchangeeventfilter.cpp
new file mode 100644
index 0000000000..a8fbaf4965
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/childrenchangeeventfilter.cpp
@@ -0,0 +1,29 @@
+#include "childrenchangeeventfilter.h"
+
+#include <QEvent>
+
+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:
+ {
+ QChildEvent *childEvent = static_cast<QChildEvent*>(event);
+ emit childrenChanged(childEvent->child()); break;
+ }
+ default: break;
+ }
+
+ return false;
+}
+} // namespace Internal
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/childrenchangeeventfilter.h b/src/plugins/qmldesigner/designercore/instances/childrenchangeeventfilter.h
new file mode 100644
index 0000000000..59dcc72ed9
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/childrenchangeeventfilter.h
@@ -0,0 +1,27 @@
+#ifndef CHILDRENCHANGEEVENTFILTER_H
+#define CHILDRENCHANGEEVENTFILTER_H
+
+#include <QObject>
+
+namespace QmlDesigner {
+namespace Internal {
+
+class ChildrenChangeEventFilter : public QObject
+{
+ Q_OBJECT
+public:
+ ChildrenChangeEventFilter(QObject *parent);
+
+
+signals:
+ void childrenChanged(QObject *object);
+
+protected:
+ bool eventFilter(QObject *object, QEvent *event);
+
+};
+
+} // namespace Internal
+} // namespace QmlDesigner
+
+#endif // CHILDRENCHANGEEVENTFILTER_H
diff --git a/src/plugins/qmldesigner/designercore/instances/clearscenecommand.cpp b/src/plugins/qmldesigner/designercore/instances/clearscenecommand.cpp
new file mode 100644
index 0000000000..21e349fd53
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/clearscenecommand.cpp
@@ -0,0 +1,19 @@
+#include "clearscenecommand.h"
+
+namespace QmlDesigner {
+
+ClearSceneCommand::ClearSceneCommand()
+{
+}
+
+QDataStream &operator<<(QDataStream &out, const ClearSceneCommand &/*command*/)
+{
+ return out;
+}
+
+QDataStream &operator>>(QDataStream &in, ClearSceneCommand &/*command*/)
+{
+ return in;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/clearscenecommand.h b/src/plugins/qmldesigner/designercore/instances/clearscenecommand.h
new file mode 100644
index 0000000000..2e593971f5
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/clearscenecommand.h
@@ -0,0 +1,21 @@
+#ifndef CLEARSCENECOMMAND_H
+#define CLEARSCENECOMMAND_H
+
+#include <qmetatype.h>
+
+namespace QmlDesigner {
+
+class ClearSceneCommand
+{
+public:
+ ClearSceneCommand();
+};
+
+QDataStream &operator<<(QDataStream &out, const ClearSceneCommand &command);
+QDataStream &operator>>(QDataStream &in, ClearSceneCommand &command);
+
+} // namespace QmlDesigner
+
+Q_DECLARE_METATYPE(QmlDesigner::ClearSceneCommand)
+
+#endif // CLEARSCENECOMMAND_H
diff --git a/src/plugins/qmldesigner/designercore/instances/completecomponentcommand.cpp b/src/plugins/qmldesigner/designercore/instances/completecomponentcommand.cpp
new file mode 100644
index 0000000000..91fbef062e
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/completecomponentcommand.cpp
@@ -0,0 +1,33 @@
+#include "completecomponentcommand.h"
+
+namespace QmlDesigner {
+
+CompleteComponentCommand::CompleteComponentCommand()
+{
+}
+
+CompleteComponentCommand::CompleteComponentCommand(const QVector<qint32> &container)
+ : m_instanceVector(container)
+{
+}
+
+QVector<qint32> CompleteComponentCommand::instances() const
+{
+ return m_instanceVector;
+}
+
+QDataStream &operator<<(QDataStream &out, const CompleteComponentCommand &command)
+{
+ out << command.instances();
+
+ return out;
+}
+
+QDataStream &operator>>(QDataStream &in, CompleteComponentCommand &command)
+{
+ in >> command.m_instanceVector;
+
+ return in;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/completecomponentcommand.h b/src/plugins/qmldesigner/designercore/instances/completecomponentcommand.h
new file mode 100644
index 0000000000..d085135fe2
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/completecomponentcommand.h
@@ -0,0 +1,30 @@
+#ifndef COMPLETECOMPONENT_H
+#define COMPLETECOMPONENT_H
+
+#include <QMetaType>
+#include <QVector>
+
+namespace QmlDesigner {
+
+class CompleteComponentCommand
+{
+ friend QDataStream &operator>>(QDataStream &in, CompleteComponentCommand &command);
+
+public:
+ CompleteComponentCommand();
+ CompleteComponentCommand(const QVector<qint32> &container);
+
+ QVector<qint32> instances() const;
+
+private:
+ QVector<qint32> m_instanceVector;
+};
+
+QDataStream &operator<<(QDataStream &out, const CompleteComponentCommand &command);
+QDataStream &operator>>(QDataStream &in, CompleteComponentCommand &command);
+
+} // namespace QmlDesigner
+
+Q_DECLARE_METATYPE(QmlDesigner::CompleteComponentCommand)
+
+#endif // COMPLETECOMPONENT_H
diff --git a/src/plugins/qmldesigner/designercore/instances/componentcompletedcommand.cpp b/src/plugins/qmldesigner/designercore/instances/componentcompletedcommand.cpp
new file mode 100644
index 0000000000..e209574e03
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/componentcompletedcommand.cpp
@@ -0,0 +1,34 @@
+#include "componentcompletedcommand.h"
+
+namespace QmlDesigner {
+
+ComponentCompletedCommand::ComponentCompletedCommand()
+{
+}
+
+ComponentCompletedCommand::ComponentCompletedCommand(const QVector<qint32> &container)
+ : m_instanceVector(container)
+{
+}
+
+QVector<qint32> ComponentCompletedCommand::instances() const
+{
+ return m_instanceVector;
+}
+
+QDataStream &operator<<(QDataStream &out, const ComponentCompletedCommand &command)
+{
+ out << command.instances();
+
+ return out;
+}
+
+QDataStream &operator>>(QDataStream &in, ComponentCompletedCommand &command)
+{
+ in >> command.m_instanceVector;
+
+ return in;
+}
+
+} // namespace QmlDesigner
+
diff --git a/src/plugins/qmldesigner/designercore/instances/componentcompletedcommand.h b/src/plugins/qmldesigner/designercore/instances/componentcompletedcommand.h
new file mode 100644
index 0000000000..e9d1b1cd00
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/componentcompletedcommand.h
@@ -0,0 +1,29 @@
+#ifndef COMPONENTCOMPLETEDCOMMAND_H
+#define COMPONENTCOMPLETEDCOMMAND_H
+#include <QMetaType>
+#include <QVector>
+
+namespace QmlDesigner {
+
+class ComponentCompletedCommand
+{
+ friend QDataStream &operator>>(QDataStream &in, ComponentCompletedCommand &command);
+
+public:
+ ComponentCompletedCommand();
+ ComponentCompletedCommand(const QVector<qint32> &container);
+
+ QVector<qint32> instances() const;
+
+private:
+ QVector<qint32> m_instanceVector;
+};
+
+QDataStream &operator<<(QDataStream &out, const ComponentCompletedCommand &command);
+QDataStream &operator>>(QDataStream &in, ComponentCompletedCommand &command);
+
+} // namespace QmlDesigner
+
+Q_DECLARE_METATYPE(QmlDesigner::ComponentCompletedCommand)
+
+#endif // COMPONENTCOMPLETEDCOMMAND_H
diff --git a/src/plugins/qmldesigner/designercore/instances/componentnodeinstance.cpp b/src/plugins/qmldesigner/designercore/instances/componentnodeinstance.cpp
index 986108d02f..c8f2b2263f 100644
--- a/src/plugins/qmldesigner/designercore/instances/componentnodeinstance.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/componentnodeinstance.cpp
@@ -52,23 +52,15 @@ QDeclarativeComponent *ComponentNodeInstance::component() const
return static_cast<QDeclarativeComponent*>(object());
}
-ComponentNodeInstance::Pointer ComponentNodeInstance::create(const NodeMetaInfo &/*metaInfo*/, QDeclarativeContext *context, QObject *objectToBeWrapped)
+ComponentNodeInstance::Pointer ComponentNodeInstance::create(QObject *object)
{
- QDeclarativeComponent *component = 0;
- if (objectToBeWrapped)
- component = qobject_cast<QDeclarativeComponent *>(objectToBeWrapped);
- else
- component = new QDeclarativeComponent(context->engine());
+ QDeclarativeComponent *component = qobject_cast<QDeclarativeComponent *>(object);
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;
@@ -83,16 +75,17 @@ void ComponentNodeInstance::setPropertyVariant(const QString &name, const QVaria
{
if (name == "__component_data") {
QByteArray data(value.toByteArray());
- QByteArray imports;
- foreach(const Import &import, modelNode().model()->imports()) {
- imports.append(import.toString(true).toLatin1());
+ QByteArray importArray;
+ foreach(const QString &import, nodeInstanceServer()->imports()) {
+ importArray.append(import.toUtf8());
}
- data.prepend(imports);
+ data.prepend(importArray);
- component()->setData(data, nodeInstanceView()->model()->fileUrl());
+ component()->setData(data, nodeInstanceServer()->fileUrl());
}
+
if (component()->isError()) {
qDebug() << value;
foreach(const QDeclarativeError &error, component()->errors())
@@ -100,5 +93,6 @@ void ComponentNodeInstance::setPropertyVariant(const QString &name, const QVaria
}
}
+
} // Internal
} // QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/componentnodeinstance.h b/src/plugins/qmldesigner/designercore/instances/componentnodeinstance.h
index 22c69fc38e..0456f2662d 100644
--- a/src/plugins/qmldesigner/designercore/instances/componentnodeinstance.h
+++ b/src/plugins/qmldesigner/designercore/instances/componentnodeinstance.h
@@ -49,7 +49,7 @@ public:
typedef QSharedPointer<ComponentNodeInstance> Pointer;
typedef QWeakPointer<ComponentNodeInstance> WeakPointer;
ComponentNodeInstance(QDeclarativeComponent *component);
- static Pointer create(const NodeMetaInfo &metaInfo, QDeclarativeContext *context, QObject *objectToBeWrapped);
+ static Pointer create(QObject *objectToBeWrapped);
void setPropertyVariant(const QString &name, const QVariant &value);
diff --git a/src/plugins/qmldesigner/designercore/instances/createinstancescommand.cpp b/src/plugins/qmldesigner/designercore/instances/createinstancescommand.cpp
new file mode 100644
index 0000000000..2d1f5ac6f9
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/createinstancescommand.cpp
@@ -0,0 +1,35 @@
+#include "createinstancescommand.h"
+
+#include <QDataStream>
+
+namespace QmlDesigner {
+
+CreateInstancesCommand::CreateInstancesCommand()
+{
+}
+
+CreateInstancesCommand::CreateInstancesCommand(const QVector<InstanceContainer> &container)
+ : m_instanceVector(container)
+{
+}
+
+QVector<InstanceContainer> CreateInstancesCommand::instances() const
+{
+ return m_instanceVector;
+}
+
+QDataStream &operator<<(QDataStream &out, const CreateInstancesCommand &command)
+{
+ out << command.instances();
+
+ return out;
+}
+
+QDataStream &operator>>(QDataStream &in, CreateInstancesCommand &command)
+{
+ in >> command.m_instanceVector;
+
+ return in;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/createinstancescommand.h b/src/plugins/qmldesigner/designercore/instances/createinstancescommand.h
new file mode 100644
index 0000000000..87b137d0bf
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/createinstancescommand.h
@@ -0,0 +1,32 @@
+#ifndef CREATEINSTANCESCOMMAND_H
+#define CREATEINSTANCESCOMMAND_H
+
+#include <QMetaType>
+#include <QVector>
+
+#include "instancecontainer.h"
+
+namespace QmlDesigner {
+
+class CreateInstancesCommand
+{
+ friend QDataStream &operator>>(QDataStream &in, CreateInstancesCommand &command);
+
+public:
+ CreateInstancesCommand();
+ CreateInstancesCommand(const QVector<InstanceContainer> &container);
+
+ QVector<InstanceContainer> instances() const;
+
+private:
+ QVector<InstanceContainer> m_instanceVector;
+};
+
+QDataStream &operator<<(QDataStream &out, const CreateInstancesCommand &command);
+QDataStream &operator>>(QDataStream &in, CreateInstancesCommand &command);
+
+} // namespace QmlDesigner
+
+Q_DECLARE_METATYPE(QmlDesigner::CreateInstancesCommand)
+
+#endif // CREATEINSTANCESCOMMAND_H
diff --git a/src/plugins/qmldesigner/designercore/instances/createscenecommand.cpp b/src/plugins/qmldesigner/designercore/instances/createscenecommand.cpp
new file mode 100644
index 0000000000..75fef072fe
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/createscenecommand.cpp
@@ -0,0 +1,19 @@
+#include "createscenecommand.h"
+
+namespace QmlDesigner {
+
+CreateSceneCommand::CreateSceneCommand()
+{
+}
+
+QDataStream &operator<<(QDataStream &out, const CreateSceneCommand &/*command*/)
+{
+ return out;
+}
+
+QDataStream &operator>>(QDataStream &in, CreateSceneCommand &/*command*/)
+{
+ return in;
+}
+
+}
diff --git a/src/plugins/qmldesigner/designercore/instances/createscenecommand.h b/src/plugins/qmldesigner/designercore/instances/createscenecommand.h
new file mode 100644
index 0000000000..6e1ec4af66
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/createscenecommand.h
@@ -0,0 +1,23 @@
+#ifndef CREATESCENECOMMAND_H
+#define CREATESCENECOMMAND_H
+
+#include <qmetatype.h>
+
+namespace QmlDesigner {
+
+class CreateSceneCommand
+{
+ friend QDataStream &operator>>(QDataStream &in, CreateSceneCommand &command);
+
+public:
+ CreateSceneCommand();
+};
+
+QDataStream &operator<<(QDataStream &out, const CreateSceneCommand &command);
+QDataStream &operator>>(QDataStream &in, CreateSceneCommand &command);
+
+}
+
+Q_DECLARE_METATYPE(QmlDesigner::CreateSceneCommand)
+
+#endif // CREATESCENECOMMAND_H
diff --git a/src/plugins/qmldesigner/designercore/instances/declarativedesignercommunicationinterface.cpp b/src/plugins/qmldesigner/designercore/instances/declarativedesignercommunicationinterface.cpp
new file mode 100644
index 0000000000..35c792778d
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/declarativedesignercommunicationinterface.cpp
@@ -0,0 +1,6 @@
+#include "declarativedesignercommunicationinterface.h"
+
+DeclarativeDesignerCommunicationInterface::DeclarativeDesignerCommunicationInterface(QObject *parent) :
+ QObject(parent)
+{
+}
diff --git a/src/plugins/qmldesigner/designercore/instances/declarativedesignercommunicationinterface.h b/src/plugins/qmldesigner/designercore/instances/declarativedesignercommunicationinterface.h
new file mode 100644
index 0000000000..d22316faad
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/declarativedesignercommunicationinterface.h
@@ -0,0 +1,18 @@
+#ifndef DECLARATIVEDESIGNERCOMMUNICATIONINTERFACE_H
+#define DECLARATIVEDESIGNERCOMMUNICATIONINTERFACE_H
+
+#include <QObject>
+
+class DeclarativeDesignerCommunicationInterface : public QObject
+{
+ Q_OBJECT
+public:
+ explicit DeclarativeDesignerCommunicationInterface(QObject *parent = 0);
+
+signals:
+
+public slots:
+
+};
+
+#endif // DECLARATIVEDESIGNERCOMMUNICATIONINTERFACE_H
diff --git a/src/plugins/qmldesigner/designercore/instances/dummynodeinstance.cpp b/src/plugins/qmldesigner/designercore/instances/dummynodeinstance.cpp
index 693e477509..3896d6f25f 100644
--- a/src/plugins/qmldesigner/designercore/instances/dummynodeinstance.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/dummynodeinstance.cpp
@@ -36,7 +36,6 @@
#include <nodemetainfo.h>
#include <invalidnodeinstanceexception.h>
-#include <propertymetainfo.h>
namespace QmlDesigner {
namespace Internal {
@@ -55,11 +54,6 @@ void DummyNodeInstance::paint(QPainter * /*painter*/) const
{
}
-bool DummyNodeInstance::isTopLevel() const
-{
- return false;
-}
-
QRectF DummyNodeInstance::boundingRect() const
{
return QRectF();
diff --git a/src/plugins/qmldesigner/designercore/instances/dummynodeinstance.h b/src/plugins/qmldesigner/designercore/instances/dummynodeinstance.h
index 29f5f76058..3df19659c3 100644
--- a/src/plugins/qmldesigner/designercore/instances/dummynodeinstance.h
+++ b/src/plugins/qmldesigner/designercore/instances/dummynodeinstance.h
@@ -51,8 +51,6 @@ public:
void paint(QPainter *painter) const;
- bool isTopLevel() const;
-
QRectF boundingRect() const;
QPointF position() const;
QSizeF size() const;
diff --git a/src/plugins/qmldesigner/designercore/instances/graphicsobjectnodeinstance.cpp b/src/plugins/qmldesigner/designercore/instances/graphicsobjectnodeinstance.cpp
index d58b5df5ac..65c887e34d 100644
--- a/src/plugins/qmldesigner/designercore/instances/graphicsobjectnodeinstance.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/graphicsobjectnodeinstance.cpp
@@ -38,13 +38,14 @@
#include "private/qgraphicsitem_p.h"
#include <QStyleOptionGraphicsItem>
#include "nodemetainfo.h"
+#include <QPixmap>
+#include <QSizeF>
namespace QmlDesigner {
namespace Internal {
-GraphicsObjectNodeInstance::GraphicsObjectNodeInstance(QGraphicsObject *graphicsObject, bool hasContent)
+GraphicsObjectNodeInstance::GraphicsObjectNodeInstance(QGraphicsObject *graphicsObject)
: ObjectNodeInstance(graphicsObject),
- m_hasContent(hasContent),
m_isMovable(true)
{
}
@@ -63,6 +64,25 @@ bool GraphicsObjectNodeInstance::hasContent() const
return m_hasContent;
}
+QList<ServerNodeInstance> GraphicsObjectNodeInstance::childItems() const
+{
+ QList<ServerNodeInstance> instanceList;
+ foreach(QGraphicsItem *item, graphicsObject()->childItems())
+ {
+ QGraphicsObject *childObject = item->toGraphicsObject();
+ if (childObject && nodeInstanceServer()->hasInstanceForObject(childObject)) {
+ instanceList.append(nodeInstanceServer()->instanceForObject(childObject));
+ }
+ }
+
+ return instanceList;
+}
+
+void GraphicsObjectNodeInstance::setHasContent(bool hasContent)
+{
+ m_hasContent = hasContent;
+}
+
QPointF GraphicsObjectNodeInstance::position() const
{
return graphicsObject()->pos();
@@ -75,10 +95,10 @@ QSizeF GraphicsObjectNodeInstance::size() const
QTransform GraphicsObjectNodeInstance::transform() const
{
- if (!nodeInstanceView()->hasInstanceForNode(modelNode()))
+ if (!nodeInstanceServer()->hasInstanceForObject(object()))
return sceneTransform();
- NodeInstance nodeInstanceParent = nodeInstanceView()->instanceForNode(modelNode()).parent();
+ ServerNodeInstance nodeInstanceParent = nodeInstanceServer()->instanceForObject(object()).parent();
if (!nodeInstanceParent.isValid())
return sceneTransform();
@@ -143,12 +163,6 @@ QRectF GraphicsObjectNodeInstance::boundingRect() const
return graphicsObject()->boundingRect();
}
-bool GraphicsObjectNodeInstance::isTopLevel() const
-{
- Q_ASSERT(graphicsObject());
- return !graphicsObject()->parentItem();
-}
-
bool GraphicsObjectNodeInstance::isGraphicsObject() const
{
return true;
@@ -159,6 +173,11 @@ void GraphicsObjectNodeInstance::setPropertyVariant(const QString &name, const Q
ObjectNodeInstance::setPropertyVariant(name, value);
}
+void GraphicsObjectNodeInstance::setPropertyBinding(const QString &name, const QString &expression)
+{
+ ObjectNodeInstance::setPropertyBinding(name, expression);
+}
+
QVariant GraphicsObjectNodeInstance::property(const QString &name) const
{
return ObjectNodeInstance::property(name);
@@ -175,11 +194,39 @@ void initOption(QGraphicsItem *item, QStyleOptionGraphicsItem *option, const QTr
privateItem->initStyleOption(option, transform, QRegion());
}
+QImage GraphicsObjectNodeInstance::renderImage() const
+{
+ QRectF boundingRect = graphicsObject()->boundingRect();
+ QSize boundingSize = boundingRect.size().toSize();
+
+ QImage image(boundingSize, QImage::Format_ARGB32);
+
+ if (image.isNull())
+ return image;
+
+ image.fill(Qt::transparent);
+
+ QPainter painter(&image);
+ painter.translate(-boundingRect.topLeft());
+
+ if (hasContent()) {
+ QStyleOptionGraphicsItem option;
+ initOption(graphicsObject(), &option, painter.transform());
+ graphicsObject()->paint(&painter, &option);
+
+ }
+
+ foreach(QGraphicsItem *graphicsItem, graphicsObject()->childItems())
+ paintRecursively(graphicsItem, &painter);
+
+ return image;
+}
+
void GraphicsObjectNodeInstance::paintRecursively(QGraphicsItem *graphicsItem, QPainter *painter) const
{
QGraphicsObject *graphicsObject = graphicsItem->toGraphicsObject();
if (graphicsObject) {
- if (nodeInstanceView()->hasInstanceForObject(graphicsObject))
+ if (nodeInstanceServer()->hasInstanceForObject(graphicsObject))
return; //we already keep track of this object elsewhere
}
@@ -197,39 +244,6 @@ void GraphicsObjectNodeInstance::paintRecursively(QGraphicsItem *graphicsItem, Q
}
}
-void GraphicsObjectNodeInstance::paint(QPainter *painter) const
-{
- if (graphicsObject()) {
- painter->save();
- if (hasContent()) {
- QStyleOptionGraphicsItem option;
- initOption(graphicsObject(), &option, painter->transform());
- graphicsObject()->paint(painter, &option);
-
- }
-
- foreach(QGraphicsItem *graphicsItem, graphicsObject()->childItems())
- paintRecursively(graphicsItem, painter);
-
- painter->restore();
- }
-}
-
-QPair<QGraphicsObject*, bool> GraphicsObjectNodeInstance::createGraphicsObject(const NodeMetaInfo &metaInfo, QDeclarativeContext *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);
-
- return qMakePair(graphicsObject, hasContent);
-}
-
void GraphicsObjectNodeInstance::paintUpdate()
{
graphicsObject()->update();
diff --git a/src/plugins/qmldesigner/designercore/instances/graphicsobjectnodeinstance.h b/src/plugins/qmldesigner/designercore/instances/graphicsobjectnodeinstance.h
index 9bc4612843..3d6544afc5 100644
--- a/src/plugins/qmldesigner/designercore/instances/graphicsobjectnodeinstance.h
+++ b/src/plugins/qmldesigner/designercore/instances/graphicsobjectnodeinstance.h
@@ -46,11 +46,9 @@ namespace Internal {
class GraphicsObjectNodeInstance : public ObjectNodeInstance
{
public:
- GraphicsObjectNodeInstance(QGraphicsObject *graphicsObject, bool hasContent);
+ GraphicsObjectNodeInstance(QGraphicsObject *graphicsObject);
+ QImage renderImage() const;
- void paint(QPainter *painter) const;
-
- bool isTopLevel() const;
bool isGraphicsObject() const;
QRectF boundingRect() const;
@@ -72,19 +70,24 @@ public:
bool equalGraphicsItem(QGraphicsItem *item) const;
void setPropertyVariant(const QString &name, const QVariant &value);
+ void setPropertyBinding(const QString &name, const QString &expression);
QVariant property(const QString &name) const;
bool hasContent() const;
+ QList<ServerNodeInstance> childItems() const;
+
void paintUpdate();
bool isMovable() const;
void setMovable(bool movable);
+
protected:
+ void setHasContent(bool hasContent);
QGraphicsObject *graphicsObject() const;
void paintRecursively(QGraphicsItem *graphicsItem, QPainter *painter) const;
- static QPair<QGraphicsObject*, bool> createGraphicsObject(const NodeMetaInfo &metaInfo, QDeclarativeContext *context);
+
private: // variables
bool m_hasContent;
bool m_isMovable;
diff --git a/src/plugins/qmldesigner/designercore/instances/graphicsscenenodeinstance.cpp b/src/plugins/qmldesigner/designercore/instances/graphicsscenenodeinstance.cpp
deleted file mode 100644
index 90892ae9e3..0000000000
--- a/src/plugins/qmldesigner/designercore/instances/graphicsscenenodeinstance.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#include "graphicsscenenodeinstance.h"
-
-#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, QDeclarativeContext *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*/)
-{
-
-}
-
-
-}
-}
diff --git a/src/plugins/qmldesigner/designercore/instances/graphicsscenenodeinstance.h b/src/plugins/qmldesigner/designercore/instances/graphicsscenenodeinstance.h
deleted file mode 100644
index 3abd50dcde..0000000000
--- a/src/plugins/qmldesigner/designercore/instances/graphicsscenenodeinstance.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#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, QDeclarativeContext *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);
-
-protected:
- GraphicsSceneNodeInstance(QGraphicsScene *scene);
- QGraphicsScene *graphicsScene() const;
-};
-
-}
-}
-#endif // GRAPHICSSCENENODEINSTANCE_H
diff --git a/src/plugins/qmldesigner/designercore/instances/graphicsviewnodeinstance.cpp b/src/plugins/qmldesigner/designercore/instances/graphicsviewnodeinstance.cpp
deleted file mode 100644
index cfbe832361..0000000000
--- a/src/plugins/qmldesigner/designercore/instances/graphicsviewnodeinstance.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#include "graphicsviewnodeinstance.h"
-
-#include <QDeclarativeEngine>
-#include <invalidnodeinstanceexception.h>
-
-namespace QmlDesigner {
-namespace Internal {
-
-GraphicsViewNodeInstance::GraphicsViewNodeInstance(QGraphicsView *view)
- : WidgetNodeInstance(view)
-{
-}
-
-
-GraphicsViewNodeInstance::Pointer GraphicsViewNodeInstance::create(const NodeMetaInfo &nodeMetaInfo,
- QDeclarativeContext *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/designercore/instances/graphicsviewnodeinstance.h b/src/plugins/qmldesigner/designercore/instances/graphicsviewnodeinstance.h
deleted file mode 100644
index 26be5670b8..0000000000
--- a/src/plugins/qmldesigner/designercore/instances/graphicsviewnodeinstance.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#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, QDeclarativeContext *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/designercore/instances/graphicswidgetnodeinstance.cpp b/src/plugins/qmldesigner/designercore/instances/graphicswidgetnodeinstance.cpp
deleted file mode 100644
index 022c528032..0000000000
--- a/src/plugins/qmldesigner/designercore/instances/graphicswidgetnodeinstance.cpp
+++ /dev/null
@@ -1,187 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#include "graphicswidgetnodeinstance.h"
-#include "graphicsscenenodeinstance.h"
-
-#include "objectnodeinstance.h"
-
-#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, QDeclarativeContext *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/designercore/instances/graphicswidgetnodeinstance.h b/src/plugins/qmldesigner/designercore/instances/graphicswidgetnodeinstance.h
deleted file mode 100644
index 92ad3badae..0000000000
--- a/src/plugins/qmldesigner/designercore/instances/graphicswidgetnodeinstance.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#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, QDeclarativeContext *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/designercore/instances/idcontainer.cpp b/src/plugins/qmldesigner/designercore/instances/idcontainer.cpp
new file mode 100644
index 0000000000..691e67e583
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/idcontainer.cpp
@@ -0,0 +1,41 @@
+#include "idcontainer.h"
+
+namespace QmlDesigner {
+
+IdContainer::IdContainer()
+ : m_instanceId(-1)
+{
+}
+
+IdContainer::IdContainer(qint32 instanceId, const QString &id)
+ : m_instanceId(instanceId),
+ m_id(id)
+{
+}
+
+qint32 IdContainer::instanceId() const
+{
+ return m_instanceId;
+}
+
+QString IdContainer::id() const
+{
+ return m_id;
+}
+
+QDataStream &operator<<(QDataStream &out, const IdContainer &container)
+{
+ out << container.instanceId();
+ out << container.id();
+
+ return out;
+}
+
+QDataStream &operator>>(QDataStream &in, IdContainer &container)
+{
+ in >> container.m_instanceId;
+ in >> container.m_id;
+
+ return in;
+}
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/idcontainer.h b/src/plugins/qmldesigner/designercore/instances/idcontainer.h
new file mode 100644
index 0000000000..603cb06384
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/idcontainer.h
@@ -0,0 +1,34 @@
+#ifndef IDCONTAINER_H
+#define IDCONTAINER_H
+
+#include <QDataStream>
+#include <qmetatype.h>
+#include <QString>
+
+
+namespace QmlDesigner {
+
+class IdContainer
+{
+ friend QDataStream &operator>>(QDataStream &in, IdContainer &container);
+
+public:
+ IdContainer();
+ IdContainer(qint32 instanceId, const QString &id);
+
+ qint32 instanceId() const;
+ QString id() const;
+
+private:
+ qint32 m_instanceId;
+ QString m_id;
+};
+
+QDataStream &operator<<(QDataStream &out, const IdContainer &container);
+QDataStream &operator>>(QDataStream &in, IdContainer &container);
+
+} // namespace QmlDesigner
+
+Q_DECLARE_METATYPE(QmlDesigner::IdContainer)
+
+#endif // IDCONTAINER_H
diff --git a/src/plugins/qmldesigner/designercore/instances/imagecontainer.cpp b/src/plugins/qmldesigner/designercore/instances/imagecontainer.cpp
new file mode 100644
index 0000000000..715eca30c8
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/imagecontainer.cpp
@@ -0,0 +1,62 @@
+#include "imagecontainer.h"
+
+namespace QmlDesigner {
+
+ImageContainer::ImageContainer()
+ : m_instanceId(-1)
+{
+}
+
+ImageContainer::ImageContainer(qint32 instanceId, const QImage &image)
+ : m_image(image), m_instanceId(instanceId)
+{
+}
+
+qint32 ImageContainer::instanceId() const
+{
+ return m_instanceId;
+}
+
+QImage ImageContainer::image() const
+{
+ return m_image;
+}
+
+QDataStream &operator<<(QDataStream &out, const ImageContainer &container)
+{
+ out << container.instanceId();
+
+ const QImage image = container.image();
+ const QByteArray data(reinterpret_cast<const char*>(image.constBits()), image.byteCount());
+
+ out << qint32(image.bytesPerLine());
+ out << image.size();
+ out << qint32(image.format());
+ out << qint32(image.byteCount());
+ out.writeRawData(reinterpret_cast<const char*>(image.constBits()), image.byteCount());
+
+ return out;
+}
+
+QDataStream &operator>>(QDataStream &in, ImageContainer &container)
+{
+
+ qint32 byteSize;
+ qint32 bytesPerLine;
+ QSize imageSize;
+ qint32 format;
+
+ in >> container.m_instanceId;
+
+ in >> bytesPerLine;
+ in >> imageSize;
+ in >> format;
+ in >> byteSize;
+
+ container.m_image = QImage(imageSize, QImage::Format(format));
+ in.readRawData(reinterpret_cast<char*>(container.m_image.bits()), byteSize);
+
+ return in;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/imagecontainer.h b/src/plugins/qmldesigner/designercore/instances/imagecontainer.h
new file mode 100644
index 0000000000..a31029577c
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/imagecontainer.h
@@ -0,0 +1,31 @@
+#ifndef IMAGECONTAINER_H
+#define IMAGECONTAINER_H
+
+#include <QMetaType>
+#include <QImage>
+
+namespace QmlDesigner {
+
+class ImageContainer
+{
+ friend QDataStream &operator>>(QDataStream &in, ImageContainer &container);
+public:
+ ImageContainer();
+ ImageContainer(qint32 instanceId, const QImage &image);
+
+ qint32 instanceId() const;
+ QImage image() const;
+
+private:
+ QImage m_image;
+ qint32 m_instanceId;
+};
+
+QDataStream &operator<<(QDataStream &out, const ImageContainer &container);
+QDataStream &operator>>(QDataStream &in, ImageContainer &container);
+
+} // namespace QmlDesigner
+
+Q_DECLARE_METATYPE(QmlDesigner::ImageContainer)
+
+#endif // IMAGECONTAINER_H
diff --git a/src/plugins/qmldesigner/designercore/instances/informationchangedcommand.cpp b/src/plugins/qmldesigner/designercore/instances/informationchangedcommand.cpp
new file mode 100644
index 0000000000..0445769e1a
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/informationchangedcommand.cpp
@@ -0,0 +1,37 @@
+#include "informationchangedcommand.h"
+
+#include <QMetaType>
+
+#include "propertyvaluecontainer.h"
+
+namespace QmlDesigner {
+
+InformationChangedCommand::InformationChangedCommand()
+{
+}
+
+InformationChangedCommand::InformationChangedCommand(const QVector<InformationContainer> &informationVector)
+ : m_informationVector(informationVector)
+{
+}
+
+QVector<InformationContainer> InformationChangedCommand::informations() const
+{
+ return m_informationVector;
+}
+
+QDataStream &operator<<(QDataStream &out, const InformationChangedCommand &command)
+{
+ out << command.informations();
+
+ return out;
+}
+
+QDataStream &operator>>(QDataStream &in, InformationChangedCommand &command)
+{
+ in >> command.m_informationVector;
+
+ return in;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/informationchangedcommand.h b/src/plugins/qmldesigner/designercore/instances/informationchangedcommand.h
new file mode 100644
index 0000000000..94ba7e1f22
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/informationchangedcommand.h
@@ -0,0 +1,32 @@
+#ifndef INFORMATIONCHANGEDCOMMAND_H
+#define INFORMATIONCHANGEDCOMMAND_H
+
+#include <QMetaType>
+#include <QVector>
+
+#include "informationcontainer.h"
+
+namespace QmlDesigner {
+
+class InformationChangedCommand
+{
+ friend QDataStream &operator>>(QDataStream &in, InformationChangedCommand &command);
+
+public:
+ InformationChangedCommand();
+ InformationChangedCommand(const QVector<InformationContainer> &informationVector);
+
+ QVector<InformationContainer> informations() const;
+
+private:
+ QVector<InformationContainer> m_informationVector;
+};
+
+QDataStream &operator<<(QDataStream &out, const InformationChangedCommand &command);
+QDataStream &operator>>(QDataStream &in, InformationChangedCommand &command);
+
+} // namespace QmlDesigner
+
+Q_DECLARE_METATYPE(QmlDesigner::InformationChangedCommand)
+
+#endif // INFORMATIONCHANGEDCOMMAND_H
diff --git a/src/plugins/qmldesigner/designercore/instances/informationcontainer.cpp b/src/plugins/qmldesigner/designercore/instances/informationcontainer.cpp
new file mode 100644
index 0000000000..6ca4103527
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/informationcontainer.cpp
@@ -0,0 +1,72 @@
+#include "informationcontainer.h"
+
+namespace QmlDesigner {
+
+InformationContainer::InformationContainer()
+ : m_instanceId(-1),
+ m_name(NoName)
+{
+}
+
+InformationContainer::InformationContainer(qint32 instanceId,
+ InformationName name,
+ const QVariant &information,
+ const QVariant &secondInformation,
+ const QVariant &thirdInformation)
+ : m_instanceId(instanceId),
+ m_name(name),
+ m_information(information),
+ m_secondInformation(secondInformation),
+ m_thirdInformation(thirdInformation)
+{
+}
+
+qint32 InformationContainer::instanceId() const
+{
+ return m_instanceId;
+}
+
+InformationName InformationContainer::name() const
+{
+ return InformationName(m_name);
+}
+
+QVariant InformationContainer::information() const
+{
+ return m_information;
+}
+
+QVariant InformationContainer::secondInformation() const
+{
+ return m_secondInformation;
+}
+
+QVariant InformationContainer::thirdInformation() const
+{
+ return m_thirdInformation;
+}
+
+QDataStream &operator<<(QDataStream &out, const InformationContainer &container)
+{
+ out << container.instanceId();//
+ out << container.m_name;
+ out << container.information();
+ out << container.secondInformation();
+ out << container.thirdInformation();
+
+ return out;
+}
+
+QDataStream &operator>>(QDataStream &in, InformationContainer &container)
+{
+
+ in >> container.m_instanceId;
+ in >> container.m_name;
+ in >> container.m_information;
+ in >> container.m_secondInformation;
+ in >> container.m_thirdInformation;
+
+ return in;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/informationcontainer.h b/src/plugins/qmldesigner/designercore/instances/informationcontainer.h
new file mode 100644
index 0000000000..11a967f8b3
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/informationcontainer.h
@@ -0,0 +1,47 @@
+#ifndef INFORMATIONCONTAINER_H
+#define INFORMATIONCONTAINER_H
+
+#include <QDataStream>
+#include <QMetaType>
+#include <QVariant>
+#include <QString>
+
+#include "commondefines.h"
+
+namespace QmlDesigner {
+
+class InformationContainer
+{
+ friend QDataStream &operator>>(QDataStream &in, InformationContainer &container);
+ friend QDataStream &operator<<(QDataStream &out, const InformationContainer &container);
+
+public:
+ InformationContainer();
+ InformationContainer(qint32 instanceId,
+ InformationName name,
+ const QVariant &information,
+ const QVariant &secondInformation = QVariant(),
+ const QVariant &thirdInformation = QVariant());
+
+ qint32 instanceId() const;
+ InformationName name() const;
+ QVariant information() const;
+ QVariant secondInformation() const;
+ QVariant thirdInformation() const;
+
+private:
+ qint32 m_instanceId;
+ qint32 m_name;
+ QVariant m_information;
+ QVariant m_secondInformation;
+ QVariant m_thirdInformation;
+};
+
+QDataStream &operator<<(QDataStream &out, const InformationContainer &container);
+QDataStream &operator>>(QDataStream &in, InformationContainer &container);
+
+} // namespace QmlDesigner
+
+Q_DECLARE_METATYPE(QmlDesigner::InformationContainer)
+
+#endif // INFORMATIONCONTAINER_H
diff --git a/src/plugins/qmldesigner/designercore/instances/instancecontainer.cpp b/src/plugins/qmldesigner/designercore/instances/instancecontainer.cpp
new file mode 100644
index 0000000000..d0831480e2
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/instancecontainer.cpp
@@ -0,0 +1,62 @@
+#include "instancecontainer.h"
+
+namespace QmlDesigner {
+
+InstanceContainer::InstanceContainer()
+ : m_instanceId(-1), m_majorNumber(-1), m_minorNumber(-1)
+{
+}
+
+InstanceContainer::InstanceContainer(qint32 instanceId, const QString &type, int majorNumber, int minorNumber, const QString &componentPath)
+ : m_instanceId(instanceId), m_type(type), m_majorNumber(majorNumber), m_minorNumber(minorNumber), m_componentPath(componentPath)
+{
+}
+
+qint32 InstanceContainer::instanceId() const
+{
+ return m_instanceId;
+}
+
+QString InstanceContainer::type() const
+{
+ return m_type;
+}
+
+int InstanceContainer::majorNumber() const
+{
+ return m_majorNumber;
+}
+
+int InstanceContainer::minorNumber() const
+{
+ return m_minorNumber;
+}
+
+QString InstanceContainer::componentPath() const
+{
+ return m_componentPath;
+}
+
+QDataStream &operator<<(QDataStream &out, const InstanceContainer &container)
+{
+ out << container.instanceId();
+ out << container.type();
+ out << container.majorNumber();
+ out << container.minorNumber();
+ out << container.componentPath();
+
+ return out;
+}
+
+
+QDataStream &operator>>(QDataStream &in, InstanceContainer &container)
+{
+ in >> container.m_instanceId;
+ in >> container.m_type;
+ in >> container.m_majorNumber;
+ in >> container.m_minorNumber;
+ in >> container.m_componentPath;
+
+ return in;
+}
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/instancecontainer.h b/src/plugins/qmldesigner/designercore/instances/instancecontainer.h
new file mode 100644
index 0000000000..3944cf7283
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/instancecontainer.h
@@ -0,0 +1,39 @@
+#ifndef INSTANCECONTAINER_H
+#define INSTANCECONTAINER_H
+
+#include <qmetatype.h>
+#include <QString>
+
+namespace QmlDesigner {
+
+class InstanceContainer;
+
+QDataStream &operator<<(QDataStream &out, const InstanceContainer &container);
+QDataStream &operator>>(QDataStream &in, InstanceContainer &container);
+
+class InstanceContainer
+{
+ friend QDataStream &operator>>(QDataStream &in, InstanceContainer &container);
+
+public:
+ InstanceContainer();
+ InstanceContainer(qint32 instanceId, const QString &type, int majorNumber, int minorNumber, const QString &componentPath);
+
+ qint32 instanceId() const;
+ QString type() const;
+ int majorNumber() const;
+ int minorNumber() const;
+ QString componentPath() const;
+
+private:
+ qint32 m_instanceId;
+ QString m_type;
+ int m_majorNumber;
+ int m_minorNumber;
+ QString m_componentPath;
+};
+
+} // namespace QmlDesigner
+
+Q_DECLARE_METATYPE(QmlDesigner::InstanceContainer)
+#endif // INSTANCECONTAINER_H
diff --git a/src/plugins/qmldesigner/designercore/instances/instances.pri b/src/plugins/qmldesigner/designercore/instances/instances.pri
new file mode 100644
index 0000000000..060f8ed144
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/instances.pri
@@ -0,0 +1,93 @@
+INCLUDEPATH += $$PWD/
+INCLUDEPATH += $$PWD/../include
+
+
+HEADERS += $$PWD/behaviornodeinstance.h
+HEADERS += $$PWD/componentcompletedcommand.h
+HEADERS += $$PWD//completecomponentcommand.h
+HEADERS += $$PWDstatepreviewimagechangedcommand.h
+HEADERS += $$PWD//imagecontainer.h
+HEADERS += $$PWD/childrenchangedcommand.h
+HEADERS += $$PWD/addimportcommand.h
+HEADERS += $$PWD/changebindingscommand.h
+HEADERS += $$PWD/changefileurlcommand.h
+HEADERS += $$PWD/changeidscommand.h
+HEADERS += $$PWD/changestatecommand.h
+HEADERS += $$PWD/changevaluescommand.h
+HEADERS += $$PWD/childrenchangeeventfilter.h
+HEADERS += $$PWD/clearscenecommand.h
+HEADERS += $$PWD/componentnodeinstance.h
+HEADERS += $$PWD/createinstancescommand.h
+HEADERS += $$PWD/createscenecommand.h
+HEADERS += $$PWD/declarativedesignercommunicationinterface.h
+HEADERS += $$PWD/dummynodeinstance.h
+HEADERS += $$PWD/graphicsobjectnodeinstance.h
+HEADERS += $$PWD/idcontainer.h
+HEADERS += $$PWD/informationchangedcommand.h
+HEADERS += $$PWD/informationcontainer.h
+HEADERS += $$PWD/instancecontainer.h
+HEADERS += $$PWD/nodeinstanceclientproxy.h
+HEADERS += $$PWD/nodeinstancemetaobject.h
+HEADERS += $$PWD/nodeinstanceserver.h
+HEADERS += $$PWD/nodeinstancesignalspy.h
+HEADERS += $$PWD/objectnodeinstance.h
+HEADERS += $$PWD/pixmapchangedcommand.h
+HEADERS += $$PWD/positionernodeinstance.h
+HEADERS += $$PWD/qmlgraphicsitemnodeinstance.h
+HEADERS += $$PWD/qmlpropertychangesnodeinstance.h
+HEADERS += $$PWD/qmlstatenodeinstance.h
+HEADERS += $$PWD/qmltransitionnodeinstance.h
+HEADERS += $$PWD/removeinstancescommand.h
+HEADERS += $$PWD/removepropertiescommand.h
+HEADERS += $$PWD/reparentcontainer.h
+HEADERS += $$PWD/reparentinstancescommand.h
+HEADERS += $$PWD/servernodeinstance.h
+HEADERS += $$PWD/valueschangedcommand.h
+HEADERS += $$PWD/../include/nodeinstanceserverinterface.h
+
+
+SOURCES += $$PWD/behaviornodeinstance.cpp
+SOURCES += $$PWD/componentcompletedcommand.cpp
+SOURCES += $$PWD/completecomponentcommand.cpp
+SOURCES += $$PWD/statepreviewimagechangedcommand.cpp
+SOURCES += $$PWD/imagecontainer.cpp
+SOURCES += $$PWD/childrenchangedcommand.cpp
+SOURCES += $$PWD/addimportcommand.cpp
+SOURCES += $$PWD/changebindingscommand.cpp
+SOURCES += $$PWD/changefileurlcommand.cpp
+SOURCES += $$PWD/changeidscommand.cpp
+SOURCES += $$PWD/changestatecommand.cpp
+SOURCES += $$PWD/changevaluescommand.cpp
+SOURCES += $$PWD/childrenchangeeventfilter.cpp
+SOURCES += $$PWD/clearscenecommand.cpp
+SOURCES += $$PWD/componentnodeinstance.cpp
+SOURCES += $$PWD/createinstancescommand.cpp
+SOURCES += $$PWD/createscenecommand.cpp
+SOURCES += $$PWD/declarativedesignercommunicationinterface.cpp
+SOURCES += $$PWD/dummynodeinstance.cpp
+SOURCES += $$PWD/graphicsobjectnodeinstance.cpp
+SOURCES += $$PWD/idcontainer.cpp
+SOURCES += $$PWD/informationchangedcommand.cpp
+SOURCES += $$PWD/informationcontainer.cpp
+SOURCES += $$PWD/instancecontainer.cpp
+SOURCES += $$PWD/nodeinstanceclientproxy.cpp
+SOURCES += $$PWD/nodeinstancemetaobject.cpp
+SOURCES += $$PWD/nodeinstanceserver.cpp
+SOURCES += $$PWD/nodeinstanceserverinterface.cpp
+SOURCES += $$PWD/nodeinstancesignalspy.cpp
+SOURCES += $$PWD/objectnodeinstance.cpp
+SOURCES += $$PWD/pixmapchangedcommand.cpp
+SOURCES += $$PWD/positionernodeinstance.cpp
+SOURCES += $$PWD/propertyabstractcontainer.cpp
+SOURCES += $$PWD/propertybindingcontainer.cpp
+SOURCES += $$PWD/propertyvaluecontainer.cpp
+SOURCES += $$PWD/qmlgraphicsitemnodeinstance.cpp
+SOURCES += $$PWD/qmlpropertychangesnodeinstance.cpp
+SOURCES += $$PWD/qmlstatenodeinstance.cpp
+SOURCES += $$PWD/qmltransitionnodeinstance.cpp
+SOURCES += $$PWD/removeinstancescommand.cpp
+SOURCES += $$PWD/removepropertiescommand.cpp
+SOURCES += $$PWD/reparentcontainer.cpp
+SOURCES += $$PWD/reparentinstancescommand.cpp
+SOURCES += $$PWD/servernodeinstance.cpp
+SOURCES += $$PWD/valueschangedcommand.cpp
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp
index cbb1f1faad..c75b9855cc 100644
--- a/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp
@@ -33,664 +33,313 @@
#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 "positionernodeinstance.h"
-#include "behaviornodeinstance.h"
-#include "qmlstatenodeinstance.h"
-#include "nodeabstractproperty.h"
-#include "variantproperty.h"
-
-#include <invalidnodeinstanceexception.h>
-
-#include <QHash>
-#include <QSet>
-
-#include <QtDeclarative/QDeclarativeEngine>
-
-/*!
- \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
-*/
+#include <QPainter>
+#include <modelnode.h>
+#include "commondefines.h"
-namespace QmlDesigner {
+#include <QtDebug>
-/*!
-\brief Constructor - creates a invalid NodeInstance
+namespace QmlDesigner {
+class ProxyNodeInstanceData
+{
+public:
+ ProxyNodeInstanceData()
+ : parentInstanceId(-1),
+ penWidth(1),
+ isAnchoredBySibling(false),
+ isAnchoredByChildren(false),
+ hasContent(false),
+ isMovable(false),
+ isResizable(false),
+ isInPositioner(false)
+ {}
+
+ qint32 parentInstanceId;
+ ModelNode modelNode;
+ QRectF boundingRect;
+ QPointF position;
+ QSizeF size;
+ QTransform transform;
+ QTransform sceneTransform;
+ int penWidth;
+ bool isAnchoredBySibling;
+ bool isAnchoredByChildren;
+ bool hasContent;
+ bool isMovable;
+ bool isResizable;
+ bool isInPositioner;
+
+
+ QHash<QString, QVariant> propertyValues;
+ QHash<QString, bool> hasBindingForProperty;
+ QHash<QString, bool> hasAnchors;
+ QHash<QString, QString> instanceTypes;
+
+ QImage renderImage;
+ QHash<QString, QPair<QString, qint32> > anchors;
+};
-\see NodeInstanceView
-*/
NodeInstance::NodeInstance()
{
}
-/*!
-\brief Destructor
-
-*/
-NodeInstance::~NodeInstance()
+NodeInstance::NodeInstance(ProxyNodeInstanceData *dPointer)
+ : d(dPointer)
{
}
-/*!
-\brief Constructor - creates a valid NodeInstance
-
-*/
-NodeInstance::NodeInstance(const Internal::ObjectNodeInstance::Pointer &abstractInstance)
- : m_nodeInstance(abstractInstance)
+NodeInstance NodeInstance::create(const ModelNode &node)
{
+ ProxyNodeInstanceData *d = new ProxyNodeInstanceData;
-}
-
+ d->modelNode = node;
-NodeInstance::NodeInstance(const NodeInstance &other)
- : m_nodeInstance(other.m_nodeInstance)
-{
-}
-
-NodeInstance &NodeInstance::operator=(const NodeInstance &other)
-{
- m_nodeInstance = other.m_nodeInstance;
- return *this;
+ return NodeInstance(d);
}
-/*!
-\brief Paints the NodeInstance with this painter.
-\param painter used QPainter
-*/
-void NodeInstance::paint(QPainter *painter) const
+NodeInstance::~NodeInstance()
{
- m_nodeInstance->paint(painter);
}
-/*!
-\brief Creates a new NodeInstace for this NodeMetaInfo
-
-\param metaInfo MetaInfo for which a Instance should be created
-\param context QDeclarativeContext which should be used
-\returns Internal Pointer of a NodeInstance
-\see NodeMetaInfo
-*/
-Internal::ObjectNodeInstance::Pointer NodeInstance::createInstance(const NodeMetaInfo &metaInfo,
- QDeclarativeContext *context, QObject *objectToBeWrapped)
-{
- Internal::ObjectNodeInstance::Pointer instance;
-
- if (!metaInfo.isValid())
- instance = Internal::DummyNodeInstance::create();
- else if (metaInfo.isSubclassOf("Qt/PathView", 4, 7))
- instance = Internal::DummyNodeInstance::create();
- else if (metaInfo.isSubclassOf("Qt/QWidget", 4, 7))
- instance = Internal::DummyNodeInstance::create();
- else if (metaInfo.isSubclassOf("Qt/QGraphicsView", 4, 7))
- instance = Internal::GraphicsViewNodeInstance::create(metaInfo, context, objectToBeWrapped);
- else if (metaInfo.isSubclassOf("Qt/QDeclarativeView", 4, 7))
- instance = Internal::QDeclarativeViewNodeInstance::create(metaInfo, context, objectToBeWrapped);
- else if (metaInfo.isSubclassOf("Qt/QGraphicsWidget", 4, 7))
- instance = Internal::DummyNodeInstance::create();
- else if (metaInfo.isSubclassOf("QDeclarativeBasePositioner", 4, 7))
- instance = Internal::PositionerNodeInstance::create(metaInfo, context, objectToBeWrapped);
- else if (metaInfo.isSubclassOf("Qt/Item", 4, 7))
- instance = Internal::QmlGraphicsItemNodeInstance::create(metaInfo, context, objectToBeWrapped);
- else if (metaInfo.isSubclassOf("Qt/QGraphicsScene", 4, 7))
- instance = Internal::GraphicsSceneNodeInstance::create(metaInfo, context, objectToBeWrapped);
- else if (metaInfo.isSubclassOf("Qt/Component", 4, 7))
- instance = Internal::ComponentNodeInstance::create(metaInfo, context, objectToBeWrapped);
- else if (metaInfo.isSubclassOf("Qt/PropertyChanges", 4, 7))
- instance = Internal::QmlPropertyChangesNodeInstance::create(metaInfo, context, objectToBeWrapped);
- else if (metaInfo.isSubclassOf("Qt/State", 4, 7))
- instance = Internal::QmlStateNodeInstance::create(metaInfo, context, objectToBeWrapped);
- else if (metaInfo.isSubclassOf("Qt/Transition", 4, 7))
- instance = Internal::QmlTransitionNodeInstance::create(metaInfo, context, objectToBeWrapped);
- else if (metaInfo.isSubclassOf("Qt/Behavior", 4, 7))
- instance = Internal::BehaviorNodeInstance::create(metaInfo, context, objectToBeWrapped);
- else if (metaInfo.isSubclassOf("Qt/QtObject", 4, 7))
- instance = Internal::ObjectNodeInstance::create(metaInfo, context, objectToBeWrapped);
- else
- instance = Internal::DummyNodeInstance::create();
-
-
- return instance;
-}
-
-
-
-NodeInstance NodeInstance::create(NodeInstanceView *nodeInstanceView, const ModelNode &node, QObject *objectToBeWrapped)
+NodeInstance::NodeInstance(const NodeInstance &other)
+ : d(other.d)
{
- 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
-
- QDeclarativeContext *context = nodeInstanceView->engine()->rootContext();
-
- NodeInstance instance(createInstance(node.metaInfo(), context, objectToBeWrapped));
-
- instance.m_nodeInstance->setModelNode(node);
-
- instance.m_nodeInstance->setNodeInstanceView(nodeInstanceView);
-
- instance.m_nodeInstance->initializePropertyWatcher(instance.m_nodeInstance);
-
- instance.setId(node.id());
-
- //QObject::connect(instance.internalObject(), SIGNAL(destroyed(QObject*)), nodeInstanceView, SLOT(removeIdFromContext(QObject*)));
-
- 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, QDeclarativeContext *context)
+NodeInstance &NodeInstance::operator=(const NodeInstance &other)
{
- NodeInstance instance(createInstance(metaInfo, context, 0));
- instance.m_nodeInstance->setNodeInstanceView(nodeInstanceView);
-
- return instance;
+ d = other.d;
+ return *this;
}
-/*!
-\brief Returns the ModelNode of this NodeInstance.
-\returns ModelNode of this NodeState
-*/
ModelNode NodeInstance::modelNode() const
{
- if (m_nodeInstance.isNull())
+ if (d) {
+ return d->modelNode;
+ } else {
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->nodeInstanceParentForObject(m_nodeInstance->parent());
-}
-
-bool NodeInstance::hasParent() const
-{
- return m_nodeInstance->parent();
-}
-
-/*!
-\brief Returns if the NodeInstance is a QDeclarativeItem.
-\returns true if this NodeInstance is a QDeclarativeItem
-*/
-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 QDeclarativeView.
-\returns true if this NodeInstance is a QDeclarativeView
-*/
-bool NodeInstance::isQDeclarativeView() const
-{
- return m_nodeInstance->isQDeclarativeView();
-}
-
-bool NodeInstance::isGraphicsObject() const
-{
- return m_nodeInstance->isGraphicsObject();
-}
-
-bool NodeInstance::isTransition() const
-{
- return m_nodeInstance->isTransition();
-}
-
-bool NodeInstance::isPositioner() const
-{
- return m_nodeInstance->isPositioner();
-}
-
-/*!
-\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, expression);
-}
-
-void NodeInstance::resetProperty(const QString &name)
-{
- m_nodeInstance->resetProperty(name);
-}
-
-void NodeInstance::refreshProperty(const QString &name)
-{
- m_nodeInstance->refreshProperty(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);
-}
-
-bool NodeInstance::hasBindingForProperty(const QString &name) const
-{
- return m_nodeInstance->hasBindingForProperty(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 the type of the property of this NodeInstance.
-*/
-QString NodeInstance::instanceType(const QString &name) const
+qint32 NodeInstance::instanceId() const
{
- return m_nodeInstance->instanceType(name);
+ if (d) {
+ return d->modelNode.internalId();
+ } else {
+ return -1;
+ }
}
-/*!
-\brief Returns if the NodeInstance is valid.
-\returns true if the NodeInstance is valid
-*/
bool NodeInstance::isValid() const
{
- return m_nodeInstance && internalObject();
+ return instanceId() >= 0 && modelNode().isValid();
}
void NodeInstance::makeInvalid()
{
- if (m_nodeInstance)
- m_nodeInstance->destroy();
- m_nodeInstance.clear();
+ if (d)
+ d->modelNode = ModelNode();
}
-bool NodeInstance::hasContent() const
-{
- return m_nodeInstance->hasContent();
-}
-
-bool NodeInstance::isResizable() const
-{
- return m_nodeInstance->isResizable();
-}
-
-bool NodeInstance::isMovable() const
-{
- return m_nodeInstance->isMovable();
-}
-
-bool NodeInstance::isInPositioner() const
-{
- return m_nodeInstance->isInPositioner();
-}
-
-bool NodeInstance::hasAnchor(const QString &name) const
+QRectF NodeInstance::boundingRect() const
{
- return m_nodeInstance->hasAnchor(name);
+ if (isValid()) {
+ return d->boundingRect;
+ } else {
+ return QRectF();
+ }
}
-int NodeInstance::penWidth() const
+bool NodeInstance::hasContent() const
{
- return m_nodeInstance->penWidth();
+ if (isValid()) {
+ return d->hasContent;
+ } else {
+ return false;
+ }
}
bool NodeInstance::isAnchoredBySibling() const
{
- return m_nodeInstance->isAnchoredBySibling();
+ if (isValid()) {
+ return d->isAnchoredBySibling;
+ } else {
+ return false;
+ }
}
bool NodeInstance::isAnchoredByChildren() const
{
- return m_nodeInstance->isAnchoredByChildren();
-}
-
-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();
-}
-
-bool NodeInstance::isWrappingThisObject(QObject *object) const
-{
- return internalObject() && internalObject() == object;
+ if (isValid()) {
+ return d->isAnchoredByChildren;
+ } else {
+ return false;
+ }
}
-/*!
-\brief Returns the position in parent coordiantes.
-\returns QPointF of the position of the instance.
-*/
-QPointF NodeInstance::position() const
+bool NodeInstance::isMovable() const
{
- return m_nodeInstance->position();
+ if (isValid()) {
+ return d->isMovable;
+ } else {
+ return false;
+ }
}
-/*!
-\brief Returns the size in local coordiantes.
-\returns QSizeF of the size of the instance.
-*/
-QSizeF NodeInstance::size() const
+bool NodeInstance::isResizable() 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;
+ if (isValid()) {
+ return d->isResizable;
+ } else {
+ return false;
+ }
}
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();
+ if (isValid()) {
+ return d->transform;
+ } else {
+ return QTransform();
+ }
}
-
QTransform NodeInstance::sceneTransform() const
{
- return m_nodeInstance->sceneTransform();
+ if (isValid()) {
+ return d->sceneTransform;
+ } else {
+ return QTransform();
+ }
}
-
-double NodeInstance::rotation() const
+bool NodeInstance::isInPositioner() const
{
- return m_nodeInstance->rotation();
+ if (isValid()) {
+ return d->isInPositioner;
+ } else {
+ return false;
+ }
}
-double NodeInstance::scale() const
+QPointF NodeInstance::position() const
{
- return m_nodeInstance->scale();
+ if (isValid()) {
+ return d->position;
+ } else {
+ return QPointF();
+ }
}
-QList<QGraphicsTransform *> NodeInstance::transformations() const
+QSizeF NodeInstance::size() const
{
- return m_nodeInstance->transformations();
+ if (isValid()) {
+ return d->size;
+ } else {
+ return QSizeF();
+ }
}
-QPointF NodeInstance::transformOriginPoint() const
+int NodeInstance::penWidth() const
{
- return m_nodeInstance->transformOriginPoint();
+ if (isValid()) {
+ return d->penWidth;
+ } else {
+ return 1;
+ }
}
-double NodeInstance::zValue() const
+void NodeInstance::paint(QPainter *painter)
{
- return m_nodeInstance->zValue();
+ if (isValid() && !d->renderImage.isNull())
+ painter->drawImage(boundingRect().topLeft(), d->renderImage);
}
-/*!
-\brief Returns the opacity of the instance.
-\returns 0.0 mean transparent and 1.0 opaque.
-*/
-double NodeInstance::opacity() const
+QVariant NodeInstance::property(const QString &name) const
{
- return m_nodeInstance->opacity();
-}
-
+ if (isValid())
+ return d->propertyValues.value(name);
-void NodeInstance::setDeleteHeldInstance(bool deleteInstance)
-{
- m_nodeInstance->setDeleteHeldInstance(deleteInstance);
+ return QVariant();
}
-
-void NodeInstance::paintUpdate()
+bool NodeInstance::hasBindingForProperty(const QString &name) const
{
- m_nodeInstance->paintUpdate();
-}
-
+ if (isValid())
+ return d->hasBindingForProperty.value(name, false);
-Internal::QmlGraphicsItemNodeInstance::Pointer NodeInstance::qmlGraphicsItemNodeInstance() const
-{
- return m_nodeInstance.dynamicCast<Internal::QmlGraphicsItemNodeInstance>();
+ return false;
}
-QObject *NodeInstance::internalObject() const
+QString NodeInstance::instanceType(const QString &name) const
{
- if (m_nodeInstance.isNull())
- return 0;
+ if (isValid())
+ return d->instanceTypes.value(name);
- return m_nodeInstance->object();
+ return QString();
}
-void NodeInstance::activateState()
+qint32 NodeInstance::parentId() const
{
- m_nodeInstance->activateState();
+ if (isValid()) {
+ return d->parentInstanceId;
+ } else {
+ return false;
+ }
}
-void NodeInstance::deactivateState()
+bool NodeInstance::hasAnchor(const QString &name) const
{
- m_nodeInstance->deactivateState();
-}
+ if (isValid())
+ return d->hasAnchors.value(name, false);
-bool NodeInstance::updateStateVariant(const NodeInstance &target, const QString &propertyName, const QVariant &value)
-{
- return m_nodeInstance->updateStateVariant(target, propertyName, value);
+ return false;
}
-bool NodeInstance::updateStateBinding(const NodeInstance &target, const QString &propertyName, const QString &expression)
+QPair<QString, qint32> NodeInstance::anchor(const QString &name) const
{
- return m_nodeInstance->updateStateBinding(target, propertyName, expression);
-}
+ if (isValid())
+ return d->anchors.value(name, QPair<QString, qint32>(QString(), qint32(-1)));
-QVariant NodeInstance::resetVariant(const QString &propertyName) const
-{
- return m_nodeInstance->resetValue(propertyName);
+ return QPair<QString, qint32>(QString(), -1);
}
-bool NodeInstance::resetStateProperty(const NodeInstance &target, const QString &propertyName, const QVariant &resetValue)
+void NodeInstance::setProperty(const QString &name, const QVariant &value)
{
- return m_nodeInstance->resetStateProperty(target, propertyName, resetValue);
+ d->propertyValues.insert(name, value);
}
-/*!
- Makes types used in node instances known to the Qml engine. To be called once at initialization time.
-*/
-void NodeInstance::registerDeclarativeTypes()
+void NodeInstance::setRenderImage(const QImage &image)
{
-// qmlRegisterType<QmlDesigner::Internal::QmlPropertyChangesObject>();
+ d->renderImage = image;
}
-void NodeInstance::doComponentComplete()
+void NodeInstance::setParentId(qint32 instanceId)
{
- m_nodeInstance->doComponentComplete();
+ d->parentInstanceId = instanceId;
}
-QString NodeInstance::id() const
+void NodeInstance::setInformation(InformationName name, const QVariant &information, const QVariant &secondInformation, const QVariant &thirdInformation)
{
- return m_nodeInstance->id();
+ switch (name) {
+ case Size: d->size = information.toSizeF(); break;
+ case BoundingRect: d->boundingRect = information.toRectF(); break;
+ case Transform: d->transform = information.value<QTransform>(); break;
+ case PenWidth: d->penWidth = information.toInt(); break;
+ case Position: d->position = information.toPointF(); break;
+ case IsInPositioner: d->isInPositioner = information.toBool(); break;
+ case SceneTransform: d->sceneTransform = information.value<QTransform>(); break;
+ case IsResizable: d->isResizable = information.toBool(); break;
+ case IsMovable: d->isMovable = information.toBool(); break;
+ case IsAnchoredByChildren: d->isAnchoredByChildren = information.toBool(); break;
+ case IsAnchoredBySibling: d->isAnchoredBySibling = information.toBool(); break;
+ case HasContent: d->hasContent = information.toBool(); break;
+ case HasAnchor: d->hasAnchors.insert(information.toString(), secondInformation.toBool());break;
+ case Anchor: d->anchors.insert(information.toString(), qMakePair(secondInformation.toString(), thirdInformation.value<qint32>())); break;
+ case InstanceTypeForProperty: d->instanceTypes.insert(information.toString(), secondInformation.toString()); break;
+ case HasBindingForProperty: d->hasBindingForProperty.insert(information.toString(), secondInformation.toBool()); break;
+ case NoName:
+ default: break;
+ }
}
-#ifdef QTCREATOR_TEST
-QObject* NodeInstance::testHandle() const
-{
- return internalObject();
-}
-Internal::ObjectNodeInstance* NodeInstance::internalInstance() const
-{
- return m_nodeInstance.data();
}
-
-#endif
-
-} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceclientproxy.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceclientproxy.cpp
new file mode 100644
index 0000000000..0520c98b24
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceclientproxy.cpp
@@ -0,0 +1,183 @@
+#include "nodeinstanceclientproxy.h"
+
+#include <QLocalSocket>
+#include <QVariant>
+#include <QCoreApplication>
+#include <QStringList>
+
+#include "nodeinstanceserver.h"
+
+#include "propertyabstractcontainer.h"
+#include "propertyvaluecontainer.h"
+#include "propertybindingcontainer.h"
+#include "instancecontainer.h"
+#include "createinstancescommand.h"
+#include "createscenecommand.h"
+#include "changevaluescommand.h"
+#include "changebindingscommand.h"
+#include "changefileurlcommand.h"
+#include "removeinstancescommand.h"
+#include "clearscenecommand.h"
+#include "removepropertiescommand.h"
+#include "reparentinstancescommand.h"
+#include "changeidscommand.h"
+#include "changestatecommand.h"
+#include "addimportcommand.h"
+#include "completecomponentcommand.h"
+
+#include "informationchangedcommand.h"
+#include "pixmapchangedcommand.h"
+#include "valueschangedcommand.h"
+#include "childrenchangedcommand.h"
+#include "imagecontainer.h"
+#include "statepreviewimagechangedcommand.h"
+#include "componentcompletedcommand.h"
+
+namespace QmlDesigner {
+
+NodeInstanceClientProxy::NodeInstanceClientProxy(QObject *parent)
+ : QObject(parent),
+ m_nodeinstanceServer(new NodeInstanceServer(this)),
+ m_blockSize(0)
+{
+ m_socket = new QLocalSocket(this);
+ connect(m_socket, SIGNAL(readyRead()), this, SLOT(readDataStream()));
+ connect(m_socket, SIGNAL(error(QLocalSocket::LocalSocketError)), QCoreApplication::instance(), SLOT(quit()));
+ connect(m_socket, SIGNAL(disconnected()), QCoreApplication::instance(), SLOT(quit()));
+ m_socket->connectToServer(QCoreApplication::arguments().at(1), QIODevice::ReadWrite | QIODevice::Unbuffered);
+ m_socket->waitForConnected(-1);
+}
+
+void NodeInstanceClientProxy::writeCommand(const QVariant &command)
+{
+ QByteArray block;
+ QDataStream out(&block, QIODevice::WriteOnly);
+ out << quint32(0);
+ out << command;
+ out.device()->seek(0);
+ out << quint32(block.size() - sizeof(quint32));
+
+ m_socket->write(block);
+}
+
+void NodeInstanceClientProxy::informationChanged(const InformationChangedCommand &command)
+{
+ writeCommand(QVariant::fromValue(command));
+}
+
+void NodeInstanceClientProxy::valuesChanged(const ValuesChangedCommand &command)
+{
+ writeCommand(QVariant::fromValue(command));
+}
+
+void NodeInstanceClientProxy::pixmapChanged(const PixmapChangedCommand &command)
+{
+ writeCommand(QVariant::fromValue(command));
+}
+
+void NodeInstanceClientProxy::childrenChanged(const ChildrenChangedCommand &command)
+{
+ writeCommand(QVariant::fromValue(command));
+}
+
+void NodeInstanceClientProxy::statePreviewImagesChanged(const StatePreviewImageChangedCommand &command)
+{
+ writeCommand(QVariant::fromValue(command));
+}
+
+void NodeInstanceClientProxy::componentCompleted(const ComponentCompletedCommand &command)
+{
+ writeCommand(QVariant::fromValue(command));
+}
+
+void NodeInstanceClientProxy::flush()
+{
+}
+
+qint64 NodeInstanceClientProxy::bytesToWrite() const
+{
+ return m_socket->bytesToWrite();
+}
+
+void NodeInstanceClientProxy::readDataStream()
+{
+ QList<QVariant> commandList;
+
+ while (!m_socket->atEnd()) {
+ if (m_socket->bytesAvailable() < int(sizeof(quint32)))
+ break;
+
+ QDataStream in(m_socket);
+
+ if (m_blockSize == 0) {
+ in >> m_blockSize;
+ }
+
+ if (m_socket->bytesAvailable() < m_blockSize)
+ break;
+
+ QVariant command;
+ in >> command;
+ m_blockSize = 0;
+
+ Q_ASSERT(in.status() == QDataStream::Ok);
+
+ commandList.append(command);
+ }
+
+ foreach (const QVariant &command, commandList) {
+ dispatchCommand(command);
+ }
+}
+
+NodeInstanceServerInterface *NodeInstanceClientProxy::nodeInstanceServer() const
+{
+ return m_nodeinstanceServer;
+}
+
+void NodeInstanceClientProxy::dispatchCommand(const QVariant &command)
+{
+ static const int createInstancesCommandType = QMetaType::type("CreateInstancesCommand");
+ static const int changeFileUrlCommandType = QMetaType::type("ChangeFileUrlCommand");
+ static const int createSceneCommandType = QMetaType::type("CreateSceneCommand");
+ static const int clearSceneCommandType = QMetaType::type("ClearSceneCommand");
+ static const int removeInstancesCommandType = QMetaType::type("RemoveInstancesCommand");
+ static const int removePropertiesCommandType = QMetaType::type("RemovePropertiesCommand");
+ static const int changeBindingsCommandType = QMetaType::type("ChangeBindingsCommand");
+ static const int changeValuesCommandType = QMetaType::type("ChangeValuesCommand");
+ static const int reparentInstancesCommandType = QMetaType::type("ReparentInstancesCommand");
+ static const int changeIdsCommandType = QMetaType::type("ChangeIdsCommand");
+ static const int changeStateCommandType = QMetaType::type("ChangeStateCommand");
+ static const int addImportCommandType = QMetaType::type("AddImportCommand");
+ static const int completeComponentCommandType = QMetaType::type("CompleteComponentCommand");
+
+ if (command.userType() == createInstancesCommandType)
+ nodeInstanceServer()->createInstances(command.value<CreateInstancesCommand>());
+ else if (command.userType() == changeFileUrlCommandType)
+ nodeInstanceServer()->changeFileUrl(command.value<ChangeFileUrlCommand>());
+ else if (command.userType() == createSceneCommandType)
+ nodeInstanceServer()->createScene(command.value<CreateSceneCommand>());
+ else if (command.userType() == clearSceneCommandType)
+ nodeInstanceServer()->clearScene(command.value<ClearSceneCommand>());
+ else if (command.userType() == removeInstancesCommandType)
+ nodeInstanceServer()->removeInstances(command.value<RemoveInstancesCommand>());
+ else if (command.userType() == removePropertiesCommandType)
+ nodeInstanceServer()->removeProperties(command.value<RemovePropertiesCommand>());
+ else if (command.userType() == changeBindingsCommandType)
+ nodeInstanceServer()->changePropertyBindings(command.value<ChangeBindingsCommand>());
+ else if (command.userType() == changeValuesCommandType)
+ nodeInstanceServer()->changePropertyValues(command.value<ChangeValuesCommand>());
+ else if (command.userType() == reparentInstancesCommandType)
+ nodeInstanceServer()->reparentInstances(command.value<ReparentInstancesCommand>());
+ else if (command.userType() == changeIdsCommandType)
+ nodeInstanceServer()->changeIds(command.value<ChangeIdsCommand>());
+ else if (command.userType() == changeStateCommandType)
+ nodeInstanceServer()->changeState(command.value<ChangeStateCommand>());
+ else if (command.userType() == addImportCommandType)
+ nodeInstanceServer()->addImport(command.value<AddImportCommand>());
+ else if (command.userType() == completeComponentCommandType)
+ nodeInstanceServer()->completeComponent(command.value<CompleteComponentCommand>());
+ else
+ Q_ASSERT(false);
+}
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceclientproxy.h b/src/plugins/qmldesigner/designercore/instances/nodeinstanceclientproxy.h
new file mode 100644
index 0000000000..3fc1e0a466
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceclientproxy.h
@@ -0,0 +1,49 @@
+#ifndef NODEINSTANCECLIENTPROXY_H
+#define NODEINSTANCECLIENTPROXY_H
+
+#include "nodeinstanceclientinterface.h"
+
+#include <QObject>
+
+QT_BEGIN_NAMESPACE
+class QLocalSocket;
+QT_END_NAMESPACE
+
+namespace QmlDesigner {
+
+class NodeInstanceServerInterface;
+
+class NodeInstanceClientProxy : public QObject, public NodeInstanceClientInterface
+{
+ Q_OBJECT
+
+public:
+ NodeInstanceClientProxy(QObject *parent = 0);
+
+ void informationChanged(const InformationChangedCommand &command);
+ void valuesChanged(const ValuesChangedCommand &command);
+ void pixmapChanged(const PixmapChangedCommand &command);
+ void childrenChanged(const ChildrenChangedCommand &command);
+ void statePreviewImagesChanged(const StatePreviewImageChangedCommand &command);
+ void componentCompleted(const ComponentCompletedCommand &command);
+
+ void flush();
+ qint64 bytesToWrite() const;
+
+protected:
+ void writeCommand(const QVariant &command);
+ void dispatchCommand(const QVariant &command);
+ NodeInstanceServerInterface *nodeInstanceServer() const;
+
+private slots:
+ void readDataStream();
+
+private:
+ QLocalSocket *m_socket;
+ NodeInstanceServerInterface *m_nodeinstanceServer;
+ quint32 m_blockSize;
+};
+
+} // namespace QmlDesigner
+
+#endif // NODEINSTANCECLIENTPROXY_H
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstancemetaobject.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstancemetaobject.cpp
index 6d0a53514e..c2cb706e97 100644
--- a/src/plugins/qmldesigner/designercore/instances/nodeinstancemetaobject.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstancemetaobject.cpp
@@ -11,7 +11,7 @@ namespace Internal {
NodeInstanceMetaObject::NodeInstanceMetaObject(const ObjectNodeInstance::Pointer &nodeInstance, QDeclarativeEngine *engine)
: QDeclarativeOpenMetaObject(nodeInstance->object(), new QDeclarativeOpenMetaObjectType(nodeInstance->object()->metaObject(), engine)),
m_nodeInstance(nodeInstance),
- m_context(nodeInstance->modelNode().isRootNode() ? nodeInstance->context() : 0)
+ m_context(nodeInstance->isRootNodeInstance() ? nodeInstance->context() : 0)
{
setCached(true);
}
@@ -59,55 +59,29 @@ int NodeInstanceMetaObject::metaCall(QMetaObject::Call call, int id, void **a)
oldValue = property(id).read(m_nodeInstance->object());
}
- if (( call == QMetaObject::ReadProperty || call == QMetaObject::WriteProperty)
- && id >= type()->propertyOffset()) {
- int propId = id - type()->propertyOffset();
- if (call == QMetaObject::ReadProperty) {
- propertyRead(propId);
- *reinterpret_cast<QVariant *>(a[0]) = value(propId);
- } else if (call == QMetaObject::WriteProperty) {
- if (value(propId) != *reinterpret_cast<QVariant *>(a[0])) {
- propertyWrite(propId);
- setValue(propId, *reinterpret_cast<QVariant *>(a[0]));
- dynamicPropertyWritten(propId);
- notifyPropertyChange(id);
- activate(object(), type()->signalOffset() + propId, 0);
- }
- }
- } else {
- if (!QObjectPrivate::get(object())->wasDeleted) {
- if (parent())
- metaCallReturnValue = parent()->metaCall(call, id, a);
- else
- metaCallReturnValue = object()->qt_metacall(call, id, a);
- }
+ if (parent() && id < parent()->propertyOffset())
+ metaCallReturnValue = parent()->metaCall(call, id, a);
+ else
+ metaCallReturnValue = QDeclarativeOpenMetaObject::metaCall(call, id, a);
- if (call == QMetaObject::WriteProperty
+ if (metaCallReturnValue >= 0
+ && call == QMetaObject::WriteProperty
&& !property(id).hasNotifySignal()
&& oldValue != property(id).read(m_nodeInstance->object()))
- notifyPropertyChange(id);
- }
+ notifyPropertyChange(id);
return metaCallReturnValue;
-
-}
-
-void NodeInstanceMetaObject::dynamicPropertyWritten(int propertyId)
-{
-
- if (m_context)
- m_context->setContextProperty(name(propertyId), value(propertyId));
}
void NodeInstanceMetaObject::notifyPropertyChange(int id)
{
ObjectNodeInstance::Pointer objectNodeInstance = m_nodeInstance.toStrongRef();
- if (objectNodeInstance && objectNodeInstance->nodeInstanceView()) {
+ if (objectNodeInstance && objectNodeInstance->nodeInstanceServer()) {
if (id < type()->propertyOffset()) {
- objectNodeInstance->nodeInstanceView()->notifyPropertyChange(objectNodeInstance->modelNode(), m_prefix + property(id).name());
+ objectNodeInstance->nodeInstanceServer()->notifyPropertyChange(objectNodeInstance->instanceId(), m_prefix + property(id).name());
} else {
- objectNodeInstance->nodeInstanceView()->notifyPropertyChange(objectNodeInstance->modelNode(), m_prefix + name(id - type()->propertyOffset()));
+ objectNodeInstance->nodeInstanceServer()->notifyPropertyChange(objectNodeInstance->instanceId(), m_prefix + name(id - type()->propertyOffset()));
}
}
}
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstancemetaobject.h b/src/plugins/qmldesigner/designercore/instances/nodeinstancemetaobject.h
index 795c517189..7307cc45b2 100644
--- a/src/plugins/qmldesigner/designercore/instances/nodeinstancemetaobject.h
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstancemetaobject.h
@@ -20,7 +20,6 @@ public:
protected:
int metaCall(QMetaObject::Call _c, int _id, void **_a);
- void dynamicPropertyWritten(int);
void notifyPropertyChange(int id);
private:
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceserver.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserver.cpp
new file mode 100644
index 0000000000..93ef09ea38
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserver.cpp
@@ -0,0 +1,827 @@
+#include "nodeinstanceserver.h"
+
+#include <QGraphicsItem>
+#include <private/qgraphicsitem_p.h>
+#include <private/qgraphicsscene_p.h>
+#include <QDeclarativeEngine>
+#include <QDeclarativeView>
+#include <QFileSystemWatcher>
+#include <QUrl>
+#include <QSet>
+#include <QVariant>
+#include <QMetaType>
+#include <QDeclarativeComponent>
+
+#include "servernodeinstance.h"
+#include "childrenchangeeventfilter.h"
+#include "propertyabstractcontainer.h"
+#include "propertybindingcontainer.h"
+#include "propertyvaluecontainer.h"
+#include "instancecontainer.h"
+#include "createinstancescommand.h"
+#include "changefileurlcommand.h"
+#include "clearscenecommand.h"
+#include "reparentinstancescommand.h"
+#include "changevaluescommand.h"
+#include "changebindingscommand.h"
+#include "changeidscommand.h"
+#include "removeinstancescommand.h"
+#include "nodeinstanceclientinterface.h"
+#include "removepropertiescommand.h"
+#include "valueschangedcommand.h"
+#include "informationchangedcommand.h"
+#include "pixmapchangedcommand.h"
+#include "commondefines.h"
+#include "childrenchangeeventfilter.h"
+#include "changestatecommand.h"
+#include "addimportcommand.h"
+#include "childrenchangedcommand.h"
+#include "completecomponentcommand.h"
+#include "componentcompletedcommand.h"
+
+#include <iostream>
+#include <stdio.h>
+
+
+namespace QmlDesigner {
+
+NodeInstanceServer::NodeInstanceServer(NodeInstanceClientInterface *nodeInstanceClient) :
+ NodeInstanceServerInterface(),
+ m_childrenChangeEventFilter(new Internal::ChildrenChangeEventFilter(this)),
+ m_nodeInstanceClient(nodeInstanceClient),
+ m_timer(0),
+ m_slowRenderTimer(false)
+{
+ connect(m_childrenChangeEventFilter.data(), SIGNAL(childrenChanged(QObject*)), this, SLOT(emitParentChanged(QObject*)));
+}
+
+NodeInstanceServer::~NodeInstanceServer()
+{
+ delete m_declarativeView.data();
+}
+
+void NodeInstanceServer::createInstances(const CreateInstancesCommand &command)
+{
+ Q_ASSERT(m_declarativeView);
+ QList<ServerNodeInstance> instanceList;
+ foreach(const InstanceContainer &instanceContainer, command.instances()) {
+ ServerNodeInstance instance = ServerNodeInstance::create(this, instanceContainer);
+ insertInstanceRelationship(instance);
+ instanceList.append(instance);
+ instance.internalObject()->installEventFilter(childrenChangeEventFilter());
+ if (instanceContainer.instanceId() == 0) {
+ m_rootNodeInstance = instance;
+ QGraphicsObject *rootGraphicsObject = qobject_cast<QGraphicsObject*>(instance.internalObject());
+ if (rootGraphicsObject) {
+ m_declarativeView->scene()->addItem(rootGraphicsObject);
+ m_declarativeView->setSceneRect(rootGraphicsObject->boundingRect());
+ }
+
+ }
+ }
+
+ nodeInstanceClient()->valuesChanged(createValuesChangedCommand(instanceList));
+ nodeInstanceClient()->informationChanged(createAllInformationChangedCommand(instanceList, true));
+ nodeInstanceClient()->pixmapChanged(createPixmapChangedCommand(instanceList));
+
+ startRenderTimer();
+}
+
+ServerNodeInstance NodeInstanceServer::instanceForId(qint32 id) const
+{
+ if (id < 0)
+ return ServerNodeInstance();
+
+ Q_ASSERT(m_idInstanceHash.contains(id));
+ return m_idInstanceHash.value(id);
+}
+
+bool NodeInstanceServer::hasInstanceForId(qint32 id) const
+{
+ if (id < 0)
+ return false;
+
+ return m_idInstanceHash.contains(id);
+}
+
+ServerNodeInstance NodeInstanceServer::instanceForObject(QObject *object) const
+{
+ Q_ASSERT(m_objectInstanceHash.contains(object));
+ return m_objectInstanceHash.value(object);
+}
+
+bool NodeInstanceServer::hasInstanceForObject(QObject *object) const
+{
+ if (object == 0)
+ return false;
+
+ return m_objectInstanceHash.contains(object);
+}
+
+void NodeInstanceServer::startRenderTimer()
+{
+ if (m_slowRenderTimer)
+ stopRenderTimer();
+
+ if (m_timer == 0)
+ m_timer = startTimer(16);
+
+ m_slowRenderTimer = false;
+}
+
+void NodeInstanceServer::slowDownRenderTimer()
+{
+ if (!m_slowRenderTimer)
+ stopRenderTimer();
+
+ if (m_timer == 0)
+ m_timer = startTimer(1000);
+
+ m_slowRenderTimer = true;
+}
+
+void NodeInstanceServer::stopRenderTimer()
+{
+ if (m_timer) {
+ killTimer(m_timer);
+ m_timer = 0;
+ }
+}
+
+void NodeInstanceServer::createScene(const CreateSceneCommand &/*command*/)
+{
+ Q_ASSERT(!m_declarativeView);
+ m_declarativeView = new QDeclarativeView;
+ m_declarativeView->setAttribute(Qt::WA_DontShowOnScreen, true);
+ m_declarativeView->setViewportUpdateMode(QGraphicsView::NoViewportUpdate);
+ m_declarativeView->show();
+
+ if (!m_fileUrl.isEmpty())
+ engine()->setBaseUrl(m_fileUrl);
+
+ static_cast<QGraphicsScenePrivate*>(QObjectPrivate::get(m_declarativeView->scene()))->processDirtyItemsEmitted = true;
+
+ startRenderTimer();
+}
+
+void NodeInstanceServer::clearScene(const ClearSceneCommand &/*command*/)
+{
+ stopRenderTimer();
+
+ removeAllInstanceRelationships();
+ m_fileSystemWatcherHash.clear();
+ m_rootNodeInstance.makeInvalid();
+ m_changedPropertyList.clear();
+ m_fileUrl.clear();
+
+ delete m_declarativeView.data();
+}
+
+void NodeInstanceServer::removeInstances(const RemoveInstancesCommand &command)
+{
+ foreach(qint32 instanceId, command.instanceIds()) {
+ removeInstanceRelationsip(instanceId);
+ }
+
+ startRenderTimer();
+}
+
+void NodeInstanceServer::removeProperties(const RemovePropertiesCommand &command)
+{
+ foreach(const PropertyAbstractContainer &container, command.properties())
+ resetInstanceProperty(container);
+
+ startRenderTimer();
+}
+
+void NodeInstanceServer::reparentInstances(const ReparentInstancesCommand &command)
+{
+ foreach(const ReparentContainer &container, command.reparentInstances()) {
+ ServerNodeInstance instance = instanceForId(container.instanceId());
+ if (instance.isValid()) {
+ instance.reparent(instanceForId(container.oldParentInstanceId()), container.oldParentProperty(), instanceForId(container.newParentInstanceId()), container.newParentProperty());
+ }
+ }
+
+ startRenderTimer();
+}
+
+void NodeInstanceServer::changeState(const ChangeStateCommand &command)
+{
+ if (hasInstanceForId(command.stateInstanceId())) {
+ if (activeStateInstance().isValid())
+ activeStateInstance().deactivateState();
+ ServerNodeInstance instance = instanceForId(command.stateInstanceId());
+ instance.activateState();
+ } else {
+ if (activeStateInstance().isValid())
+ activeStateInstance().deactivateState();
+ }
+
+ startRenderTimer();
+}
+
+void NodeInstanceServer::completeComponent(const CompleteComponentCommand &command)
+{
+ foreach(qint32 instanceId, command.instances()) {
+ if (hasInstanceForId(instanceId)) {
+ ServerNodeInstance instance = instanceForId(instanceId);
+ instance.doComponentComplete();
+ m_componentCompletedVector.append(instanceId);
+ }
+ }
+}
+
+void NodeInstanceServer::addImport(const AddImportCommand &command)
+{
+ QString importStatement = QString("import ");
+
+ if (!command.fileName().isEmpty())
+ importStatement += '"' + command.fileName() + '"';
+ else if (!command.url().isEmpty())
+ importStatement += command.url().toString();
+
+ if (!command.version().isEmpty())
+ importStatement += " " + command.version();
+
+ if (!command.alias().isEmpty())
+ importStatement += " as " + command.alias();
+
+ m_importList.append(importStatement);
+
+ QDeclarativeComponent importComponent(engine(), 0);
+ QString componentString = QString("import Qt 4.7\n%1\n Item{}\n").arg(importStatement);
+
+ foreach(const QString &importPath, command.importPaths()) {
+ engine()->addImportPath(importPath);
+ engine()->addPluginPath(importPath);
+ }
+
+ qDebug() << __FUNCTION__ << fileUrl().resolved(QUrl("content/samegame.js")) << componentString;
+
+ importComponent.setData(componentString.toUtf8(), QUrl());
+
+ if (!importComponent.errorString().isEmpty())
+ qDebug() << "QmlDesigner.NodeInstances: import wrong: " << importComponent.errorString();
+}
+
+void NodeInstanceServer::changeFileUrl(const ChangeFileUrlCommand &command)
+{
+ m_fileUrl = command.fileUrl();
+
+ if (engine())
+ engine()->setBaseUrl(m_fileUrl);
+
+ startRenderTimer();
+}
+
+void NodeInstanceServer::changePropertyValues(const ChangeValuesCommand &command)
+{
+ foreach(const PropertyValueContainer &container, command.valueChanges())
+ setInstancePropertyVariant(container);
+
+ startRenderTimer();
+}
+
+
+void NodeInstanceServer::changePropertyBindings(const ChangeBindingsCommand &command)
+{
+ foreach(const PropertyBindingContainer &container, command.bindingChanges())
+ setInstancePropertyBinding(container);
+
+ startRenderTimer();
+}
+
+void NodeInstanceServer::changeIds(const ChangeIdsCommand &command)
+{
+ foreach(const IdContainer &container, command.ids()) {
+ if (hasInstanceForId(container.instanceId()))
+ instanceForId(container.instanceId()).setId(container.id());
+ }
+
+ startRenderTimer();
+}
+
+QDeclarativeEngine *NodeInstanceServer::engine() const
+{
+ if (m_declarativeView)
+ return m_declarativeView->engine();
+
+ return 0;
+}
+
+void NodeInstanceServer::removeAllInstanceRelationships()
+{
+ // prevent destroyed() signals calling back
+
+ foreach (ServerNodeInstance instance, m_objectInstanceHash.values()) {
+ if (instance.isValid())
+ instance.setId(QString());
+ }
+
+ //first the root object
+ if (rootNodeInstance().internalObject())
+ rootNodeInstance().internalObject()->disconnect();
+
+ rootNodeInstance().makeInvalid();
+
+
+ foreach (ServerNodeInstance instance, m_objectInstanceHash.values()) {
+ if (instance.internalObject())
+ instance.internalObject()->disconnect();
+ instance.makeInvalid();
+ }
+
+ m_idInstanceHash.clear();
+ m_objectInstanceHash.clear();
+}
+
+
+QFileSystemWatcher *NodeInstanceServer::fileSystemWatcher()
+{
+ if (m_fileSystemWatcher.isNull()) {
+ m_fileSystemWatcher = new QFileSystemWatcher(this);
+ connect(m_fileSystemWatcher.data(), SIGNAL(fileChanged(QString)), this, SLOT(refreshLocalFileProperty(QString)));
+ }
+
+ return m_fileSystemWatcher.data();
+}
+
+Internal::ChildrenChangeEventFilter *NodeInstanceServer::childrenChangeEventFilter() const
+{
+ return m_childrenChangeEventFilter.data();
+}
+
+void NodeInstanceServer::addFilePropertyToFileSystemWatcher(QObject *object, const QString &propertyName, const QString &path)
+{
+ m_fileSystemWatcherHash.insert(path, ObjectPropertyPair(object, propertyName));
+ fileSystemWatcher()->addPath(path);
+
+}
+
+void NodeInstanceServer::removeFilePropertyFromFileSystemWatcher(QObject *object, const QString &propertyName, const QString &path)
+{
+ fileSystemWatcher()->removePath(path);
+ m_fileSystemWatcherHash.remove(path, ObjectPropertyPair(object, propertyName));
+}
+
+void NodeInstanceServer::refreshLocalFileProperty(const QString &path)
+{
+ if (m_fileSystemWatcherHash.contains(path)) {
+ QList<ObjectPropertyPair> objectPropertyPairList = m_fileSystemWatcherHash.values();
+ foreach(const ObjectPropertyPair &objectPropertyPair, objectPropertyPairList) {
+ QObject *object = objectPropertyPair.first.data();
+ QString propertyName = objectPropertyPair.second;
+
+ if (hasInstanceForObject(object)) {
+ instanceForObject(object).refreshProperty(propertyName);
+ }
+ }
+ }
+}
+
+void NodeInstanceServer::addChangedProperty(const InstancePropertyPair &property)
+{
+ if (!m_changedPropertyList.contains(property))
+ m_changedPropertyList.append(property);
+}
+
+void NodeInstanceServer::emitParentChanged(QObject *child)
+{
+ if (hasInstanceForObject(child)) {
+ addChangedProperty(InstancePropertyPair(instanceForObject(child), "parent"));
+ }
+}
+
+Internal::ChildrenChangeEventFilter *NodeInstanceServer::childrenChangeEventFilter()
+{
+ if (m_childrenChangeEventFilter.isNull()) {
+ m_childrenChangeEventFilter = new Internal::ChildrenChangeEventFilter(this);
+ connect(m_childrenChangeEventFilter.data(), SIGNAL(childrenChanged(QObject*)), this, SLOT(emitParentChanged(QObject*)));
+ }
+
+ return m_childrenChangeEventFilter.data();
+}
+
+void NodeInstanceServer::resetInstanceProperty(const PropertyAbstractContainer &propertyContainer)
+{
+ if (hasInstanceForId(propertyContainer.instanceId())) { // TODO ugly workaround
+ ServerNodeInstance instance = instanceForId(propertyContainer.instanceId());
+ Q_ASSERT(instance.isValid());
+
+ const QString name = propertyContainer.name();
+
+ if (activeStateInstance().isValid() && !instance.isSubclassOf("Qt/PropertyChanges")) {
+ bool statePropertyWasReseted = activeStateInstance().resetStateProperty(instance, name, instance.resetVariant(name));
+ if (!statePropertyWasReseted)
+ instance.resetProperty(name);
+ } else {
+ instance.resetProperty(name);
+ }
+ }
+}
+
+
+void NodeInstanceServer::setInstancePropertyBinding(const PropertyBindingContainer &bindingContainer)
+{
+ if (hasInstanceForId(bindingContainer.instanceId())) {
+ ServerNodeInstance instance = instanceForId(bindingContainer.instanceId());
+
+ const QString name = bindingContainer.name();
+ const QString expression = bindingContainer.expression();
+
+
+ if (activeStateInstance().isValid() && !instance.isSubclassOf("Qt/PropertyChanges")) {
+ bool stateBindingWasUpdated = activeStateInstance().updateStateBinding(instance, name, expression);
+ if (!stateBindingWasUpdated) {
+ if (bindingContainer.isDynamic())
+ instance.setPropertyDynamicBinding(name, bindingContainer.dynamicTypeName(), expression);
+ else
+ instance.setPropertyBinding(name, expression);
+ }
+ } else {
+ if (bindingContainer.isDynamic())
+ instance.setPropertyDynamicBinding(name, bindingContainer.dynamicTypeName(), expression);
+ else
+ instance.setPropertyBinding(name, expression);
+ }
+ }
+}
+
+
+void NodeInstanceServer::removeProperties(const QList<PropertyAbstractContainer> &propertyList)
+{
+ foreach (const PropertyAbstractContainer &property, propertyList)
+ resetInstanceProperty(property);
+}
+
+void NodeInstanceServer::setInstancePropertyVariant(const PropertyValueContainer &valueContainer)
+{
+ if (hasInstanceForId(valueContainer.instanceId())) {
+ ServerNodeInstance instance = instanceForId(valueContainer.instanceId());
+
+
+ const QString name = valueContainer.name();
+ const QVariant value = valueContainer.value();
+
+
+ if (activeStateInstance().isValid() && !instance.isSubclassOf("Qt/PropertyChanges")) {
+ bool stateValueWasUpdated = activeStateInstance().updateStateVariant(instance, name, value);
+ if (!stateValueWasUpdated) {
+ if (valueContainer.isDynamic())
+ instance.setPropertyDynamicVariant(name, valueContainer.dynamicTypeName(), value);
+ else
+ instance.setPropertyVariant(name, value);
+ }
+ } else { //base state
+ if (valueContainer.isDynamic())
+ instance.setPropertyDynamicVariant(name, valueContainer.dynamicTypeName(), value);
+ else
+ instance.setPropertyVariant(name, value);
+ }
+
+// instance.paintUpdate();
+ }
+}
+
+
+QUrl NodeInstanceServer::fileUrl() const
+{
+ return m_fileUrl;
+}
+
+ServerNodeInstance NodeInstanceServer::activeStateInstance() const
+{
+ return m_activeStateInstance;
+}
+
+ServerNodeInstance NodeInstanceServer::rootNodeInstance() const
+{
+ return m_rootNodeInstance;
+}
+
+void NodeInstanceServer::setStateInstance(const ServerNodeInstance &stateInstance)
+{
+ m_activeStateInstance = stateInstance;
+}
+
+void NodeInstanceServer::clearStateInstance()
+{
+ m_activeStateInstance = ServerNodeInstance();
+}
+
+void NodeInstanceServer::timerEvent(QTimerEvent *event)
+{
+ if (event->timerId() == m_timer) {
+ findItemChangesAndSendChangeCommands();
+ }
+
+ NodeInstanceServerInterface::timerEvent(event);
+}
+
+NodeInstanceClientInterface *NodeInstanceServer::nodeInstanceClient() const
+{
+ return m_nodeInstanceClient;
+}
+
+void NodeInstanceServer::sendChildrenChangedCommand(const QList<ServerNodeInstance> childList)
+{
+ QSet<ServerNodeInstance> parentSet;
+ QList<ServerNodeInstance> noParentList;
+
+ foreach (const ServerNodeInstance &child, childList) {
+ if (!child.hasParent())
+ noParentList.append(child);
+ else
+ parentSet.insert(child.parent());
+ }
+
+
+ foreach (const ServerNodeInstance &parent, parentSet)
+ nodeInstanceClient()->childrenChanged(createChildrenChangedCommand(parent, parent.childItems()));
+
+ if (!noParentList.isEmpty())
+ nodeInstanceClient()->childrenChanged(createChildrenChangedCommand(ServerNodeInstance(), noParentList));
+
+}
+
+ChildrenChangedCommand NodeInstanceServer::createChildrenChangedCommand(const ServerNodeInstance &parentInstance, const QList<ServerNodeInstance> &instanceList) const
+{
+ QVector<qint32> instanceVector;
+
+ foreach(const ServerNodeInstance &instance, instanceList)
+ instanceVector.append(instance.instanceId());
+
+ return ChildrenChangedCommand(parentInstance.instanceId(), instanceVector);
+}
+
+InformationChangedCommand NodeInstanceServer::createAllInformationChangedCommand(const QList<ServerNodeInstance> &instanceList, bool initial) const
+{
+ QVector<InformationContainer> informationVector;
+
+ foreach(const ServerNodeInstance &instance, instanceList) {
+ informationVector.append(InformationContainer(instance.instanceId(), Position, instance.position()));
+ informationVector.append(InformationContainer(instance.instanceId(), Transform, instance.transform()));
+ informationVector.append(InformationContainer(instance.instanceId(), SceneTransform, instance.sceneTransform()));
+ informationVector.append(InformationContainer(instance.instanceId(), Size, instance.size()));
+ informationVector.append(InformationContainer(instance.instanceId(), BoundingRect, instance.boundingRect()));
+ informationVector.append(InformationContainer(instance.instanceId(), Transform, instance.transform()));
+ informationVector.append(InformationContainer(instance.instanceId(), HasContent, instance.hasContent()));
+ informationVector.append(InformationContainer(instance.instanceId(), IsMovable, instance.isMovable()));
+ informationVector.append(InformationContainer(instance.instanceId(), IsResizable, instance.isResizable()));
+ informationVector.append(InformationContainer(instance.instanceId(), IsInPositioner, instance.isInPositioner()));
+ informationVector.append(InformationContainer(instance.instanceId(), PenWidth, instance.penWidth()));
+ informationVector.append(InformationContainer(instance.instanceId(), IsAnchoredByChildren, instance.isAnchoredByChildren()));
+ informationVector.append(InformationContainer(instance.instanceId(), IsAnchoredBySibling, instance.isAnchoredBySibling()));
+
+ informationVector.append(InformationContainer(instance.instanceId(), HasAnchor, QString("anchors.fill"), instance.hasAnchor("anchors.fill")));
+ informationVector.append(InformationContainer(instance.instanceId(), HasAnchor, QString("anchors.centerIn"), instance.hasAnchor("anchors.centerIn")));
+ informationVector.append(InformationContainer(instance.instanceId(), HasAnchor, QString("anchors.right"), instance.hasAnchor("anchors.right")));
+ informationVector.append(InformationContainer(instance.instanceId(), HasAnchor, QString("anchors.top"), instance.hasAnchor("anchors.top")));
+ informationVector.append(InformationContainer(instance.instanceId(), HasAnchor, QString("anchors.left"), instance.hasAnchor("anchors.left")));
+ informationVector.append(InformationContainer(instance.instanceId(), HasAnchor, QString("anchors.bottom"), instance.hasAnchor("anchors.bottom")));
+ informationVector.append(InformationContainer(instance.instanceId(), HasAnchor, QString("anchors.horizontalCenter"), instance.hasAnchor("anchors.horizontalCenter")));
+ informationVector.append(InformationContainer(instance.instanceId(), HasAnchor, QString("anchors.verticalCenter"), instance.hasAnchor("anchors.verticalCenter")));
+ informationVector.append(InformationContainer(instance.instanceId(), HasAnchor, QString("anchors.baseline"), instance.hasAnchor("anchors.baseline")));
+
+ QPair<QString, ServerNodeInstance> anchorPair = instance.anchor("anchors.fill");
+ informationVector.append(InformationContainer(instance.instanceId(), Anchor, QString("anchors.fill"), anchorPair.first, anchorPair.second.instanceId()));
+
+ anchorPair = instance.anchor("anchors.centerIn");
+ informationVector.append(InformationContainer(instance.instanceId(), Anchor, QString("anchors.centerIn"), anchorPair.first, anchorPair.second.instanceId()));
+
+ anchorPair = instance.anchor("anchors.right");
+ informationVector.append(InformationContainer(instance.instanceId(), Anchor, QString("anchors.right"), anchorPair.first, anchorPair.second.instanceId()));
+
+ anchorPair = instance.anchor("anchors.top");
+ informationVector.append(InformationContainer(instance.instanceId(), Anchor, QString("anchors.top"), anchorPair.first, anchorPair.second.instanceId()));
+
+ anchorPair = instance.anchor("anchors.left");
+ informationVector.append(InformationContainer(instance.instanceId(), Anchor, QString("anchors.left"), anchorPair.first, anchorPair.second.instanceId()));
+
+ anchorPair = instance.anchor("anchors.bottom");
+ informationVector.append(InformationContainer(instance.instanceId(), Anchor, QString("anchors.bottom"), anchorPair.first, anchorPair.second.instanceId()));
+
+ anchorPair = instance.anchor("anchors.horizontalCenter");
+ informationVector.append(InformationContainer(instance.instanceId(), Anchor, QString("anchors.horizontalCenter"), anchorPair.first, anchorPair.second.instanceId()));
+
+ anchorPair = instance.anchor("anchors.verticalCenter");
+ informationVector.append(InformationContainer(instance.instanceId(), Anchor, QString("anchors.verticalCenter"), anchorPair.first, anchorPair.second.instanceId()));
+
+ anchorPair = instance.anchor("anchors.baseline");
+ informationVector.append(InformationContainer(instance.instanceId(), Anchor, QString("anchors.baseline"), anchorPair.first, anchorPair.second.instanceId()));
+
+ QStringList propertyNames = instance.propertyNames();
+
+ if (initial) {
+ foreach (const QString &propertyName,propertyNames)
+ informationVector.append(InformationContainer(instance.instanceId(), InstanceTypeForProperty, propertyName, instance.instanceType(propertyName)));
+ }
+
+ foreach (const QString &propertyName,instance.propertyNames()) {
+ bool hasChanged = false;
+ bool hasBinding = instance.hasBindingForProperty(propertyName, &hasChanged);
+ if (hasChanged)
+ informationVector.append(InformationContainer(instance.instanceId(), HasBindingForProperty, propertyName, hasBinding));
+ }
+
+ }
+
+ return InformationChangedCommand(informationVector);
+}
+
+ValuesChangedCommand NodeInstanceServer::createValuesChangedCommand(const QList<ServerNodeInstance> &instanceList) const
+{
+ QVector<PropertyValueContainer> valueVector;
+
+ foreach(const ServerNodeInstance &instance, instanceList) {
+ foreach(const QString &propertyName, instance.propertyNames()) {
+ QVariant propertyValue = instance.property(propertyName);
+ if (propertyValue.type() < QVariant::UserType)
+ valueVector.append(PropertyValueContainer(instance.instanceId(), propertyName, propertyValue, QString()));
+ }
+ }
+
+ return ValuesChangedCommand(valueVector);
+}
+
+ValuesChangedCommand NodeInstanceServer::createValuesChangedCommand(const QVector<InstancePropertyPair> &propertyList) const
+{
+ QVector<PropertyValueContainer> valueVector;
+
+ foreach (const InstancePropertyPair &property, propertyList) {
+ const QString propertyName = property.second;
+ const ServerNodeInstance instance = property.first;
+
+ if( instance.isValid()) {
+ QVariant propertyValue = instance.property(propertyName);
+ if (propertyValue.type() < QVariant::UserType)
+ valueVector.append(PropertyValueContainer(instance.instanceId(), propertyName, propertyValue, QString()));
+ }
+ }
+
+ return ValuesChangedCommand(valueVector);
+}
+
+QStringList NodeInstanceServer::imports() const
+{
+ return m_importList;
+}
+
+void NodeInstanceServer::notifyPropertyChange(qint32 instanceid, const QString &propertyName)
+{
+ if (hasInstanceForId(instanceid))
+ addChangedProperty(InstancePropertyPair(instanceForId(instanceid), propertyName));
+}
+
+void NodeInstanceServer::insertInstanceRelationship(const ServerNodeInstance &instance)
+{
+ Q_ASSERT(instance.isValid());
+ Q_ASSERT(!m_idInstanceHash.contains(instance.instanceId()));
+ Q_ASSERT(!m_objectInstanceHash.contains(instance.internalObject()));
+ m_objectInstanceHash.insert(instance.internalObject(), instance);
+ m_idInstanceHash.insert(instance.instanceId(), instance);
+}
+
+void NodeInstanceServer::removeInstanceRelationsip(qint32 instanceId)
+{
+ if (hasInstanceForId(instanceId)) {
+ ServerNodeInstance instance = instanceForId(instanceId);
+ if (instance.isValid())
+ instance.setId(QString());
+ m_idInstanceHash.remove(instanceId);
+ m_objectInstanceHash.remove(instance.internalObject());
+ instance.makeInvalid();
+ }
+}
+
+PixmapChangedCommand NodeInstanceServer::createPixmapChangedCommand(const QList<ServerNodeInstance> &instanceList) const
+{
+ QVector<ImageContainer> imageVector;
+
+ foreach (const ServerNodeInstance &instance, instanceList)
+ imageVector.append(ImageContainer(instance.instanceId(), instance.renderImage()));
+
+ return PixmapChangedCommand(imageVector);
+}
+
+bool NodeInstanceServer::nonInstanceChildIsDirty(QGraphicsObject *graphicsObject) const
+{
+ QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(graphicsObject);
+ if (d->dirtyChildren) {
+ foreach(QGraphicsItem *child, graphicsObject->childItems()) {
+ QGraphicsObject *childGraphicsObject = child->toGraphicsObject();
+ if (hasInstanceForObject(childGraphicsObject))
+ continue;
+
+ QGraphicsItemPrivate *childPrivate = QGraphicsItemPrivate::get(child);
+ if (childPrivate->dirty || nonInstanceChildIsDirty(childGraphicsObject))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void NodeInstanceServer::resetAllItems()
+{
+// m_declarativeView->scene()->update();
+// m_declarativeView->viewport()->repaint();
+ static_cast<QGraphicsScenePrivate*>(QObjectPrivate::get(m_declarativeView->scene()))->processDirtyItemsEmitted = true;
+
+ foreach (QGraphicsItem *item, m_declarativeView->items())
+ static_cast<QGraphicsScenePrivate*>(QObjectPrivate::get(m_declarativeView->scene()))->resetDirtyItem(item);
+}
+
+void NodeInstanceServer::findItemChangesAndSendChangeCommands()
+{
+ static bool inFunction = false;
+ if (!inFunction && nodeInstanceClient()->bytesToWrite() < 100000) {
+ inFunction = true;
+
+ QSet<ServerNodeInstance> dirtyInstanceSet;
+ QSet<ServerNodeInstance> informationChangedInstanceSet;
+ QVector<InstancePropertyPair> propertyChangedList;
+ QSet<ServerNodeInstance> parentChangedSet;
+ bool adjustSceneRect = false;
+
+ if (m_declarativeView) {
+ foreach (QGraphicsItem *item, m_declarativeView->items()) {
+ QGraphicsObject *graphicsObject = item->toGraphicsObject();
+ if (graphicsObject && hasInstanceForObject(graphicsObject)) {
+ ServerNodeInstance instance = instanceForObject(graphicsObject);
+ QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(item);
+
+ if (d->dirtySceneTransform || d->geometryChanged || d->dirty)
+ informationChangedInstanceSet.insert(instance);
+
+ if((d->dirty && d->notifyBoundingRectChanged)|| (d->dirty && !d->dirtySceneTransform) || nonInstanceChildIsDirty(graphicsObject))
+ dirtyInstanceSet.insert(instance);
+
+ if (d->geometryChanged) {
+ if (instance.isRootNodeInstance())
+ m_declarativeView->scene()->setSceneRect(item->boundingRect());
+ }
+
+ }
+ }
+
+ foreach (const InstancePropertyPair& property, m_changedPropertyList) {
+ const ServerNodeInstance instance = property.first;
+ const QString propertyName = property.second;
+
+ if (instance.isRootNodeInstance() && (propertyName == "width" || propertyName == "height"))
+ adjustSceneRect = true;
+
+ if (propertyName.contains("anchors") && informationChangedInstanceSet.contains(instance))
+ informationChangedInstanceSet.insert(instance);
+
+ if (propertyName == "width" || propertyName == "height")
+ dirtyInstanceSet.insert(instance);
+
+ if (propertyName == "parent") {
+ informationChangedInstanceSet.insert(instance);
+ parentChangedSet.insert(instance);
+ } else {
+ propertyChangedList.append(property);
+ }
+ }
+
+ m_changedPropertyList.clear();
+ resetAllItems();
+
+ if (!informationChangedInstanceSet.isEmpty())
+ nodeInstanceClient()->informationChanged(createAllInformationChangedCommand(informationChangedInstanceSet.toList()));
+
+ if (!propertyChangedList.isEmpty())
+ nodeInstanceClient()->valuesChanged(createValuesChangedCommand(propertyChangedList));
+
+ if (!parentChangedSet.isEmpty())
+ sendChildrenChangedCommand(parentChangedSet.toList());
+
+ if (!m_componentCompletedVector.isEmpty())
+ nodeInstanceClient()->componentCompleted(ComponentCompletedCommand(m_componentCompletedVector));
+ m_componentCompletedVector.clear();
+
+ if (!dirtyInstanceSet.isEmpty())
+ nodeInstanceClient()->pixmapChanged(createPixmapChangedCommand(dirtyInstanceSet.toList()));
+
+ if (adjustSceneRect) {
+ QRectF boundingRect = m_rootNodeInstance.boundingRect();
+ if (boundingRect.isValid()) {
+ m_declarativeView->setSceneRect(boundingRect);
+ }
+ }
+
+ slowDownRenderTimer();
+ nodeInstanceClient()->flush();
+ }
+
+ inFunction = false;
+ }
+
+}
+}
+
+
+
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceserver.h b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserver.h
new file mode 100644
index 0000000000..f4fe0aa5a7
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserver.h
@@ -0,0 +1,137 @@
+#ifndef NODEINSTANCESERVER_H
+#define NODEINSTANCESERVER_H
+
+#include <QUrl>
+#include <QVector>
+#include <QStringList>
+
+#include <nodeinstanceserverinterface.h>
+#include "servernodeinstance.h"
+
+QT_BEGIN_NAMESPACE
+class QFileSystemWatcher;
+class QDeclarativeView;
+class QDeclarativeEngine;
+class QGraphicsObject;
+QT_END_NAMESPACE
+
+namespace QmlDesigner {
+
+class NodeInstanceClientInterface;
+class ValuesChangedCommand;
+class PixmapChangedCommand;
+class InformationChangedCommand;
+class ChildrenChangedCommand;
+
+namespace Internal {
+ class ChildrenChangeEventFilter;
+}
+
+class NodeInstanceServer : public NodeInstanceServerInterface
+{
+ Q_OBJECT
+public:
+ typedef QPair<QWeakPointer<QObject>, QString> ObjectPropertyPair;
+ typedef QPair<qint32, QString> IdPropertyPair;
+ typedef QPair<ServerNodeInstance, QString> InstancePropertyPair;
+ explicit NodeInstanceServer(NodeInstanceClientInterface *nodeInstanceClient);
+ ~NodeInstanceServer();
+
+ void createInstances(const CreateInstancesCommand &command);
+ void changeFileUrl(const ChangeFileUrlCommand &command);
+ void changePropertyValues(const ChangeValuesCommand &command);
+ void changePropertyBindings(const ChangeBindingsCommand &command);
+ void changeIds(const ChangeIdsCommand &command);
+ void createScene(const CreateSceneCommand &command);
+ void clearScene(const ClearSceneCommand &command);
+ void removeInstances(const RemoveInstancesCommand &command);
+ void removeProperties(const RemovePropertiesCommand &command);
+ void reparentInstances(const ReparentInstancesCommand &command);
+ void changeState(const ChangeStateCommand &command);
+ void addImport(const AddImportCommand &command);
+ void completeComponent(const CompleteComponentCommand &command);
+
+ ServerNodeInstance instanceForId(qint32 id) const;
+ bool hasInstanceForId(qint32 id) const;
+
+ ServerNodeInstance instanceForObject(QObject *object) const;
+ bool hasInstanceForObject(QObject *object) const;
+
+ QDeclarativeEngine *engine() const;
+
+ void removeAllInstanceRelationships();
+
+ QFileSystemWatcher *fileSystemWatcher();
+ Internal::ChildrenChangeEventFilter *childrenChangeEventFilter() const;
+ void addFilePropertyToFileSystemWatcher(QObject *object, const QString &propertyName, const QString &path);
+ void removeFilePropertyFromFileSystemWatcher(QObject *object, const QString &propertyName, const QString &path);
+
+ QUrl fileUrl() const;
+
+ ServerNodeInstance activeStateInstance() const;
+ void setStateInstance(const ServerNodeInstance &stateInstance);
+ void clearStateInstance();
+
+ ServerNodeInstance rootNodeInstance() const;
+
+ void notifyPropertyChange(qint32 instanceid, const QString &propertyName);
+
+ QStringList imports() const;
+
+public slots:
+ void refreshLocalFileProperty(const QString &path);
+ void emitParentChanged(QObject *child);
+
+protected:
+ Internal::ChildrenChangeEventFilter *childrenChangeEventFilter();
+ void resetInstanceProperty(const PropertyAbstractContainer &propertyContainer);
+ void setInstancePropertyBinding(const PropertyBindingContainer &bindingContainer);
+ void setInstancePropertyVariant(const PropertyValueContainer &valueContainer);
+ void removeProperties(const QList<PropertyAbstractContainer> &propertyList);
+
+ void insertInstanceRelationship(const ServerNodeInstance &instance);
+ void removeInstanceRelationsip(qint32 instanceId);
+
+ NodeInstanceClientInterface *nodeInstanceClient() const;
+
+ void timerEvent(QTimerEvent *);
+
+ bool nonInstanceChildIsDirty(QGraphicsObject *graphicsObject) const;
+ void findItemChangesAndSendChangeCommands();
+ void resetAllItems();
+
+ ValuesChangedCommand createValuesChangedCommand(const QList<ServerNodeInstance> &instanceList) const;
+ ValuesChangedCommand createValuesChangedCommand(const QVector<InstancePropertyPair> &propertyList) const;
+ PixmapChangedCommand createPixmapChangedCommand(const QList<ServerNodeInstance> &instanceList) const;
+ InformationChangedCommand createAllInformationChangedCommand(const QList<ServerNodeInstance> &instanceList, bool initial = false) const;
+ ChildrenChangedCommand createChildrenChangedCommand(const ServerNodeInstance &parentInstance, const QList<ServerNodeInstance> &instanceList) const;
+
+ void sendChildrenChangedCommand(const QList<ServerNodeInstance> childList);
+
+ void addChangedProperty(const InstancePropertyPair &property);
+
+ void startRenderTimer();
+ void slowDownRenderTimer();
+ void stopRenderTimer();
+
+private:
+ ServerNodeInstance m_rootNodeInstance;
+ ServerNodeInstance m_activeStateInstance;
+ QHash<qint32, ServerNodeInstance> m_idInstanceHash;
+ QHash<QObject*, ServerNodeInstance> m_objectInstanceHash;
+ QMultiHash<QString, ObjectPropertyPair> m_fileSystemWatcherHash;
+ QWeakPointer<QFileSystemWatcher> m_fileSystemWatcher;
+ QWeakPointer<QDeclarativeView> m_declarativeView;
+ QWeakPointer<Internal::ChildrenChangeEventFilter> m_childrenChangeEventFilter;
+ QUrl m_fileUrl;
+ NodeInstanceClientInterface *m_nodeInstanceClient;
+ int m_timer;
+ bool m_slowRenderTimer;
+ QVector<InstancePropertyPair> m_changedPropertyList;
+ QVector<qint32> m_componentCompletedVector;
+ QStringList m_importList;
+};
+
+}
+
+#endif // NODEINSTANCESERVER_H
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverinterface.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverinterface.cpp
new file mode 100644
index 0000000000..d4a567d20c
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverinterface.cpp
@@ -0,0 +1,130 @@
+#include "nodeinstanceserverinterface.h"
+#include <qmetatype.h>
+
+#include "propertyabstractcontainer.h"
+#include "propertyvaluecontainer.h"
+#include "propertybindingcontainer.h"
+#include "instancecontainer.h"
+#include "createinstancescommand.h"
+#include "createscenecommand.h"
+#include "changevaluescommand.h"
+#include "changebindingscommand.h"
+#include "changefileurlcommand.h"
+#include "removeinstancescommand.h"
+#include "clearscenecommand.h"
+#include "removepropertiescommand.h"
+#include "reparentinstancescommand.h"
+#include "changeidscommand.h"
+#include "changestatecommand.h"
+#include "completecomponentcommand.h"
+
+#include "informationchangedcommand.h"
+#include "pixmapchangedcommand.h"
+#include "valueschangedcommand.h"
+#include "addimportcommand.h"
+#include "childrenchangedcommand.h"
+#include "imagecontainer.h"
+#include "statepreviewimagechangedcommand.h"
+#include "componentcompletedcommand.h"
+
+
+namespace QmlDesigner {
+
+static bool isRegistered=false;
+
+NodeInstanceServerInterface::NodeInstanceServerInterface(QObject *parent) :
+ QObject(parent)
+{
+ registerCommands();
+}
+
+void NodeInstanceServerInterface::registerCommands()
+{
+ if (isRegistered)
+ return;
+
+ isRegistered = true;
+
+ qRegisterMetaType<CreateInstancesCommand>("CreateInstancesCommand");
+ qRegisterMetaTypeStreamOperators<CreateInstancesCommand>("CreateInstancesCommand");
+
+ qRegisterMetaType<ClearSceneCommand>("ClearSceneCommand");
+ qRegisterMetaTypeStreamOperators<ClearSceneCommand>("ClearSceneCommand");
+
+ qRegisterMetaType<CreateSceneCommand>("CreateSceneCommand");
+ qRegisterMetaTypeStreamOperators<CreateSceneCommand>("CreateSceneCommand");
+
+ qRegisterMetaType<ChangeBindingsCommand>("ChangeBindingsCommand");
+ qRegisterMetaTypeStreamOperators<ChangeBindingsCommand>("ChangeBindingsCommand");
+
+ qRegisterMetaType<ChangeValuesCommand>("ChangeValuesCommand");
+ qRegisterMetaTypeStreamOperators<ChangeValuesCommand>("ChangeValuesCommand");
+
+ qRegisterMetaType<ChangeFileUrlCommand>("ChangeFileUrlCommand");
+ qRegisterMetaTypeStreamOperators<ChangeFileUrlCommand>("ChangeFileUrlCommand");
+
+ qRegisterMetaType<ChangeStateCommand>("ChangeStateCommand");
+ qRegisterMetaTypeStreamOperators<PropertyAbstractContainer>("ChangeStateCommand");
+
+ qRegisterMetaType<RemoveInstancesCommand>("RemoveInstancesCommand");
+ qRegisterMetaTypeStreamOperators<RemoveInstancesCommand>("RemoveInstancesCommand");
+
+ qRegisterMetaType<RemovePropertiesCommand>("RemovePropertiesCommand");
+ qRegisterMetaTypeStreamOperators<RemovePropertiesCommand>("RemovePropertiesCommand");
+
+ qRegisterMetaType<ReparentInstancesCommand>("ReparentInstancesCommand");
+ qRegisterMetaTypeStreamOperators<ReparentInstancesCommand>("ReparentInstancesCommand");
+
+ qRegisterMetaType<ChangeIdsCommand>("ChangeIdsCommand");
+ qRegisterMetaTypeStreamOperators<ChangeIdsCommand>("ChangeIdsCommand");
+
+ qRegisterMetaType<ChangeStateCommand>("ChangeStateCommand");
+ qRegisterMetaTypeStreamOperators<ChangeStateCommand>("ChangeStateCommand");
+
+ qRegisterMetaType<InformationChangedCommand>("InformationChangedCommand");
+ qRegisterMetaTypeStreamOperators<InformationChangedCommand>("InformationChangedCommand");
+
+ qRegisterMetaType<ValuesChangedCommand>("ValuesChangedCommand");
+ qRegisterMetaTypeStreamOperators<ValuesChangedCommand>("ValuesChangedCommand");
+
+ qRegisterMetaType<PixmapChangedCommand>("PixmapChangedCommand");
+ qRegisterMetaTypeStreamOperators<PixmapChangedCommand>("PixmapChangedCommand");
+
+ qRegisterMetaType<InformationContainer>("InformationContainer");
+ qRegisterMetaTypeStreamOperators<InformationContainer>("InformationContainer");
+
+ qRegisterMetaType<PropertyValueContainer>("PropertyValueContainer");
+ qRegisterMetaTypeStreamOperators<PropertyValueContainer>("PropertyValueContainer");
+
+ qRegisterMetaType<PropertyBindingContainer>("PropertyBindingContainer");
+ qRegisterMetaTypeStreamOperators<PropertyBindingContainer>("PropertyBindingContainer");
+
+ qRegisterMetaType<PropertyAbstractContainer>("PropertyAbstractContainer");
+ qRegisterMetaTypeStreamOperators<PropertyAbstractContainer>("PropertyAbstractContainer");
+
+ qRegisterMetaType<InstanceContainer>("InstanceContainer");
+ qRegisterMetaTypeStreamOperators<InstanceContainer>("InstanceContainer");
+
+ qRegisterMetaType<IdContainer>("IdContainer");
+ qRegisterMetaTypeStreamOperators<IdContainer>("IdContainer");
+
+ qRegisterMetaType<AddImportCommand>("AddImportCommand");
+ qRegisterMetaTypeStreamOperators<AddImportCommand>("AddImportCommand");
+
+ qRegisterMetaType<ChildrenChangedCommand>("ChildrenChangedCommand");
+ qRegisterMetaTypeStreamOperators<ChildrenChangedCommand>("ChildrenChangedCommand");
+
+ qRegisterMetaType<ImageContainer>("ImageContainer");
+ qRegisterMetaTypeStreamOperators<ImageContainer>("ImageContainer");
+
+ qRegisterMetaType<StatePreviewImageChangedCommand>("StatePreviewImageChangedCommand");
+ qRegisterMetaTypeStreamOperators<StatePreviewImageChangedCommand>("StatePreviewImageChangedCommand");
+
+ qRegisterMetaType<CompleteComponentCommand>("CompleteComponentCommand");
+ qRegisterMetaTypeStreamOperators<CompleteComponentCommand>("CompleteComponentCommand");
+
+ qRegisterMetaType<ComponentCompletedCommand>("ComponentCompletedCommand");
+ qRegisterMetaTypeStreamOperators<ComponentCompletedCommand>("ComponentCompletedCommand");
+}
+
+}
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp
new file mode 100644
index 0000000000..69b0209d24
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp
@@ -0,0 +1,226 @@
+#include "nodeinstanceserverproxy.h"
+
+#include <QLocalServer>
+#include <QLocalSocket>
+#include <QProcess>
+#include <QCoreApplication>
+#include <QUuid>
+
+#include "propertyabstractcontainer.h"
+#include "propertyvaluecontainer.h"
+#include "propertybindingcontainer.h"
+#include "instancecontainer.h"
+#include "createinstancescommand.h"
+#include "createscenecommand.h"
+#include "changevaluescommand.h"
+#include "changebindingscommand.h"
+#include "changefileurlcommand.h"
+#include "removeinstancescommand.h"
+#include "clearscenecommand.h"
+#include "removepropertiescommand.h"
+#include "reparentinstancescommand.h"
+#include "changeidscommand.h"
+#include "changestatecommand.h"
+#include "addimportcommand.h"
+#include "completecomponentcommand.h"
+
+#include "informationchangedcommand.h"
+#include "pixmapchangedcommand.h"
+#include "valueschangedcommand.h"
+#include "childrenchangedcommand.h"
+#include "imagecontainer.h"
+#include "statepreviewimagechangedcommand.h"
+#include "componentcompletedcommand.h"
+
+#include "nodeinstanceview.h"
+#include "nodeinstanceclientproxy.h"
+
+namespace QmlDesigner {
+
+NodeInstanceServerProxy::NodeInstanceServerProxy(NodeInstanceView *nodeInstanceView)
+ : NodeInstanceServerInterface(nodeInstanceView),
+ m_localServer(new QLocalServer(this)),
+ m_nodeInstanceView(nodeInstanceView),
+ m_blockSize(0)
+{
+ QString socketToken(QUuid::createUuid().toString());
+
+ m_localServer->listen(socketToken);
+ m_localServer->setMaxPendingConnections(1);
+
+ m_qmlPuppetProcess = new QProcess(QCoreApplication::instance());
+ connect(m_qmlPuppetProcess.data(), SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(processFinished(int,QProcess::ExitStatus)));
+ m_qmlPuppetProcess->setProcessChannelMode(QProcess::ForwardedChannels);
+ m_qmlPuppetProcess->start(QString("%1/%2").arg(QCoreApplication::applicationDirPath()).arg("qmlpuppet"), QStringList() << socketToken);
+ connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(deleteLater()));
+ m_qmlPuppetProcess->waitForStarted();
+ Q_ASSERT(m_qmlPuppetProcess->state() == QProcess::Running);
+
+ if (!m_localServer->hasPendingConnections())
+ m_localServer->waitForNewConnection(-1);
+
+ m_socket = m_localServer->nextPendingConnection();
+ Q_ASSERT(m_socket);
+ connect(m_socket.data(), SIGNAL(readyRead()), this, SLOT(readDataStream()));
+ m_localServer->close();
+}
+
+NodeInstanceServerProxy::~NodeInstanceServerProxy()
+{
+ if (m_qmlPuppetProcess) {
+ m_qmlPuppetProcess->blockSignals(true);
+ m_qmlPuppetProcess->terminate();
+ }
+}
+
+void NodeInstanceServerProxy::dispatchCommand(const QVariant &command)
+{
+ static const int informationChangedCommandType = QMetaType::type("InformationChangedCommand");
+ static const int valuesChangedCommandType = QMetaType::type("ValuesChangedCommand");
+ static const int pixmapChangedCommandType = QMetaType::type("PixmapChangedCommand");
+ static const int childrenChangedCommandType = QMetaType::type("ChildrenChangedCommand");
+ static const int statePreviewImageChangedCommandType = QMetaType::type("StatePreviewImageChangedCommand");
+ static const int componentCompletedCommandType = QMetaType::type("ComponentCompletedCommand");
+
+ if (command.userType() == informationChangedCommandType)
+ nodeInstanceClient()->informationChanged(command.value<InformationChangedCommand>());
+ else if (command.userType() == valuesChangedCommandType)
+ nodeInstanceClient()->valuesChanged(command.value<ValuesChangedCommand>());
+ else if (command.userType() == pixmapChangedCommandType)
+ nodeInstanceClient()->pixmapChanged(command.value<PixmapChangedCommand>());
+ else if (command.userType() == childrenChangedCommandType)
+ nodeInstanceClient()->childrenChanged(command.value<ChildrenChangedCommand>());
+ else if (command.userType() == statePreviewImageChangedCommandType)
+ nodeInstanceClient()->statePreviewImagesChanged(command.value<StatePreviewImageChangedCommand>());
+ else if (command.userType() == componentCompletedCommandType)
+ nodeInstanceClient()->componentCompleted(command.value<ComponentCompletedCommand>());
+ else
+ Q_ASSERT(false);
+}
+
+NodeInstanceClientInterface *NodeInstanceServerProxy::nodeInstanceClient() const
+{
+ return m_nodeInstanceView.data();
+}
+
+void NodeInstanceServerProxy::setBlockUpdates(bool block)
+{
+ m_socket->blockSignals(block);
+}
+
+void NodeInstanceServerProxy::writeCommand(const QVariant &command)
+{
+ Q_ASSERT(m_socket.data());
+
+ QByteArray block;
+ QDataStream out(&block, QIODevice::WriteOnly);
+ out << quint32(0);
+ out << command;
+ out.device()->seek(0);
+ out << quint32(block.size() - sizeof(quint32));
+
+ m_socket->write(block);
+}
+
+void NodeInstanceServerProxy::processFinished(int /*exitCode*/, QProcess::ExitStatus /* exitStatus */)
+{
+ m_socket->close();
+ emit processCrashed();
+}
+
+void NodeInstanceServerProxy::readDataStream()
+{
+ QList<QVariant> commandList;
+
+ while (!m_socket->atEnd()) {
+ if (m_socket->bytesAvailable() < int(sizeof(quint32)))
+ break;
+
+ QDataStream in(m_socket.data());
+
+ if (m_blockSize == 0) {
+ in >> m_blockSize;
+ }
+
+ if (m_socket->bytesAvailable() < m_blockSize)
+ break;
+
+ QVariant command;
+ in >> command;
+ m_blockSize = 0;
+
+ Q_ASSERT(in.status() == QDataStream::Ok);
+
+ commandList.append(command);
+ }
+
+ foreach (const QVariant &command, commandList) {
+ dispatchCommand(command);
+ }
+}
+
+void NodeInstanceServerProxy::createInstances(const CreateInstancesCommand &command)
+{
+ writeCommand(QVariant::fromValue(command));
+}
+
+void NodeInstanceServerProxy::changeFileUrl(const ChangeFileUrlCommand &command)
+{
+ writeCommand(QVariant::fromValue(command));
+}
+
+void NodeInstanceServerProxy::createScene(const CreateSceneCommand &command)
+{
+ writeCommand(QVariant::fromValue(command));
+}
+
+void NodeInstanceServerProxy::clearScene(const ClearSceneCommand &command)
+{
+ writeCommand(QVariant::fromValue(command));
+}
+
+void NodeInstanceServerProxy::removeInstances(const RemoveInstancesCommand &command)
+{
+ writeCommand(QVariant::fromValue(command));
+}
+
+void NodeInstanceServerProxy::removeProperties(const RemovePropertiesCommand &command)
+{
+ writeCommand(QVariant::fromValue(command));
+}
+
+void NodeInstanceServerProxy::changePropertyBindings(const ChangeBindingsCommand &command)
+{
+ writeCommand(QVariant::fromValue(command));
+}
+
+void NodeInstanceServerProxy::changePropertyValues(const ChangeValuesCommand &command)
+{
+ writeCommand(QVariant::fromValue(command));
+}
+
+void NodeInstanceServerProxy::reparentInstances(const ReparentInstancesCommand &command)
+{
+ writeCommand(QVariant::fromValue(command));
+}
+
+void NodeInstanceServerProxy::changeIds(const ChangeIdsCommand &command)
+{
+ writeCommand(QVariant::fromValue(command));
+}
+
+void NodeInstanceServerProxy::changeState(const ChangeStateCommand &command)
+{
+ writeCommand(QVariant::fromValue(command));
+}
+
+void NodeInstanceServerProxy::addImport(const AddImportCommand &command)
+{
+ writeCommand(QVariant::fromValue(command));
+}
+
+void NodeInstanceServerProxy::completeComponent(const CompleteComponentCommand &command)
+{
+ writeCommand(QVariant::fromValue(command));
+}
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.h b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.h
new file mode 100644
index 0000000000..f4d4b3ab98
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.h
@@ -0,0 +1,66 @@
+#ifndef NODEINSTANCESERVERPROXY_H
+#define NODEINSTANCESERVERPROXY_H
+
+#include "nodeinstanceserverinterface.h"
+
+#include <QDataStream>
+#include <QWeakPointer>
+#include <QProcess>
+
+QT_BEGIN_NAMESPACE
+class QLocalServer;
+class QLocalSocket;
+class QProcess;
+QT_END_NAMESPACE
+
+namespace QmlDesigner {
+
+class NodeInstanceClientInterface;
+class NodeInstanceView;
+class NodeInstanceClientProxy;
+
+class NodeInstanceServerProxy : public NodeInstanceServerInterface
+{
+ Q_OBJECT
+public:
+ explicit NodeInstanceServerProxy(NodeInstanceView *nodeInstanceView);
+ ~NodeInstanceServerProxy();
+ void createInstances(const CreateInstancesCommand &command);
+ void changeFileUrl(const ChangeFileUrlCommand &command);
+ void createScene(const CreateSceneCommand &command);
+ void clearScene(const ClearSceneCommand &command);
+ void removeInstances(const RemoveInstancesCommand &command);
+ void removeProperties(const RemovePropertiesCommand &command);
+ void changePropertyBindings(const ChangeBindingsCommand &command);
+ void changePropertyValues(const ChangeValuesCommand &command);
+ void reparentInstances(const ReparentInstancesCommand &command);
+ void changeIds(const ChangeIdsCommand &command);
+ void changeState(const ChangeStateCommand &command);
+ void addImport(const AddImportCommand &command);
+ void completeComponent(const CompleteComponentCommand &command);
+
+ void setBlockUpdates(bool block);
+
+protected:
+ void writeCommand(const QVariant &command);
+ void dispatchCommand(const QVariant &command);
+ NodeInstanceClientInterface *nodeInstanceClient() const;
+
+signals:
+ void processCrashed();
+
+private slots:
+ void processFinished(int exitCode, QProcess::ExitStatus exitStatus);
+ void readDataStream();
+
+private:
+ QWeakPointer<QLocalServer> m_localServer;
+ QWeakPointer<QLocalSocket> m_socket;
+ QWeakPointer<NodeInstanceView> m_nodeInstanceView;
+ QWeakPointer<QProcess> m_qmlPuppetProcess;
+ quint32 m_blockSize;
+};
+
+} // namespace QmlDesigner
+
+#endif // NODEINSTANCESERVERPROXY_H
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstancesignalspy.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstancesignalspy.cpp
index 70a10a7544..d2ff7586a7 100644
--- a/src/plugins/qmldesigner/designercore/instances/nodeinstancesignalspy.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstancesignalspy.cpp
@@ -26,10 +26,10 @@ void NodeInstanceSignalSpy::setObjectNodeInstance(const ObjectNodeInstance::Poin
void NodeInstanceSignalSpy::registerObject(QObject *spiedObject, const QString &prefix)
{
- if (registeredObjectList.contains(spiedObject)) // prevent cycles
+ if (m_registeredObjectList.contains(spiedObject)) // prevent cycles
return;
- registeredObjectList.append(spiedObject);
+ m_registeredObjectList.append(spiedObject);
for (int index = QObject::staticMetaObject.propertyOffset();
index < spiedObject->metaObject()->propertyCount();
index++) {
@@ -79,8 +79,8 @@ int NodeInstanceSignalSpy::qt_metacall(QMetaObject::Call call, int methodId, voi
if (call == QMetaObject::InvokeMetaMethod && methodId > QObject::staticMetaObject.methodCount()) {
ObjectNodeInstance::Pointer nodeInstance = m_objectNodeInstance.toStrongRef();
- if (nodeInstance && nodeInstance->nodeInstanceView() && nodeInstance->modelNode().isValid()) {
- nodeInstance->nodeInstanceView()->notifyPropertyChange(nodeInstance->modelNode(), m_indexPropertyHash.value(methodId));
+ if (nodeInstance && nodeInstance->nodeInstanceServer() && nodeInstance->isValid()) {
+ nodeInstance->nodeInstanceServer()->notifyPropertyChange(nodeInstance->instanceId(), m_indexPropertyHash.value(methodId));
}
}
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstancesignalspy.h b/src/plugins/qmldesigner/designercore/instances/nodeinstancesignalspy.h
index 94cef6d232..85cc4d7981 100644
--- a/src/plugins/qmldesigner/designercore/instances/nodeinstancesignalspy.h
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstancesignalspy.h
@@ -27,8 +27,9 @@ protected:
private:
int methodeOffset;
QHash<int, QString> m_indexPropertyHash;
- QObjectList registeredObjectList;
+ QObjectList m_registeredObjectList;
ObjectNodeInstanceWeakPointer m_objectNodeInstance;
+ QMetaObject m_metaObject;
};
} // namespace Internal
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
index fcef236ab7..7a190addca 100644
--- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
@@ -46,9 +46,7 @@
#include <model.h>
#include <modelnode.h>
-#include <propertymetainfo.h>
#include <metainfo.h>
-#include <nodeinstance.h>
#include <typeinfo>
#include <iwidgetplugin.h>
@@ -59,9 +57,30 @@
#include "nodeabstractproperty.h"
#include "nodelistproperty.h"
-#include "objectnodeinstance.h"
-
-#include "qmlmodelview.h"
+#include <nodeinstanceserverinterface.h>
+
+#include "createscenecommand.h"
+#include "createinstancescommand.h"
+#include "clearscenecommand.h"
+#include "changefileurlcommand.h"
+#include "reparentinstancescommand.h"
+#include "changevaluescommand.h"
+#include "changebindingscommand.h"
+#include "changeidscommand.h"
+#include "removeinstancescommand.h"
+#include "removepropertiescommand.h"
+#include "valueschangedcommand.h"
+#include "pixmapchangedcommand.h"
+#include "informationchangedcommand.h"
+#include "changestatecommand.h"
+#include "addimportcommand.h"
+#include "childrenchangedcommand.h"
+#include "imagecontainer.h"
+#include "statepreviewimagechangedcommand.h"
+#include "completecomponentcommand.h"
+#include "componentcompletedcommand.h"
+
+#include "nodeinstanceserverproxy.h"
enum {
debug = false
@@ -94,15 +113,11 @@ d too.
\see ~NodeInstanceView setRenderOffScreen
*/
NodeInstanceView::NodeInstanceView(QObject *parent)
- : AbstractView(parent),
- m_graphicsView(new QGraphicsView),
- m_blockStatePropertyChanges(false)
+ : AbstractView(parent)
{
- m_graphicsView->setAttribute(Qt::WA_DontShowOnScreen, true);
- m_graphicsView->setOptimizationFlags(QGraphicsView::DontSavePainterState);
- m_graphicsView->setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
- m_graphicsView->setScene(new QGraphicsScene(m_graphicsView.data()));
- m_graphicsView->scene()->setItemIndexMethod(QGraphicsScene::NoIndex);
+ m_resetTimer.setInterval(200);
+ m_resetTimer.setSingleShot(true);
+ connect(&m_resetTimer, SIGNAL(timeout()), this, SLOT(restartProcessDelayed()));
}
@@ -112,6 +127,7 @@ NodeInstanceView::NodeInstanceView(QObject *parent)
NodeInstanceView::~NodeInstanceView()
{
removeAllInstanceNodeRelationships();
+ delete nodeInstanceServer();
}
/*! \name Overloaded Notifiers
@@ -126,18 +142,46 @@ NodeInstanceView::~NodeInstanceView()
void NodeInstanceView::modelAttached(Model *model)
{
AbstractView::modelAttached(model);
- engine()->setBaseUrl(model->fileUrl());
- loadModel(model);
+ m_nodeInstanceServer = new NodeInstanceServerProxy(this);
+ connect(m_nodeInstanceServer.data(), SIGNAL(processCrashed()), this, SLOT(restartProcess()));
+
+ setBlockUpdates(true);
+ nodeInstanceServer()->createScene(createCreateSceneCommand());
+
+ nodeInstanceServer()->changeFileUrl(createChangeFileUrlCommand(model->fileUrl()));
+ foreach(const Import &import, model->imports())
+ nodeInstanceServer()->addImport(createImportCommand(import));
+
+ loadNodes(allModelNodes());
+
+ setBlockUpdates(false);
}
void NodeInstanceView::modelAboutToBeDetached(Model * model)
{
removeAllInstanceNodeRelationships();
+ nodeInstanceServer()->clearScene(createClearSceneCommand());
+ delete nodeInstanceServer();
AbstractView::modelAboutToBeDetached(model);
- delete m_engine.data();
}
+void NodeInstanceView::restartProcess()
+{
+ setBlockUpdates(true);
+ Model *oldModel = model();
+ if (oldModel) {
+ oldModel->detachView(this);
+ oldModel->attachView(this);
+ }
+ setBlockUpdates(false);
+}
+
+void NodeInstanceView::restartProcessDelayed()
+{
+ m_resetTimer.start();
+}
+
/*! \brief Notifing the view that a node was created.
A NodeInstance will be created for the new created ModelNode.
\param createdNode New created ModelNode.
@@ -145,9 +189,9 @@ void NodeInstanceView::modelAboutToBeDetached(Model * model)
void NodeInstanceView::nodeCreated(const ModelNode &createdNode)
{
NodeInstance instance = loadNode(createdNode);
-
- if (instance.isValid())
- instance.doComponentComplete();
+ nodeInstanceServer()->createInstances(createCreateInstancesCommand(QList<NodeInstance>() << instance));
+ nodeInstanceServer()->changePropertyValues(createChangeValueCommand(createdNode.variantProperties()));
+ nodeInstanceServer()->completeComponent(createComponentCompleteCommand(QList<NodeInstance>() << instance));
}
/*! \brief Notifing the view that a node was created.
@@ -155,6 +199,7 @@ void NodeInstanceView::nodeCreated(const ModelNode &createdNode)
*/
void NodeInstanceView::nodeAboutToBeRemoved(const ModelNode &removedNode)
{
+ nodeInstanceServer()->removeInstances(createRemoveInstancesCommand(removedNode));
removeInstanceAndSubInstances(removedNode);
}
@@ -162,116 +207,103 @@ void NodeInstanceView::nodeRemoved(const ModelNode &/*removedNode*/, const NodeA
{
}
-/*! \brief Notifing the view that a AbstractProperty was added to a ModelNode.
-
- The property will be set for the NodeInstance.
-
-\param state ModelNode to which the Property belongs
-\param property AbstractProperty which was added
-\see AbstractProperty NodeInstance ModelNode
-*/
-
-void NodeInstanceView::propertiesAboutToBeRemoved(const QList<AbstractProperty>& propertyList)
+void NodeInstanceView::resetHorizontalAnchors(const ModelNode &modelNode)
{
- foreach (const AbstractProperty &property, propertyList) {
- resetInstanceProperty(property);
+ QList<BindingProperty> bindingList;
+ QList<VariantProperty> valueList;
- if (property.isNodeAbstractProperty()) {
- foreach (const ModelNode &subNode, property.toNodeAbstractProperty().allSubNodes())
- removeInstanceNodeRelationship(subNode);
- }
+ if (modelNode.hasBindingProperty("x")) {
+ bindingList.append(modelNode.bindingProperty("x"));
+ } else if (modelNode.hasVariantProperty("x")) {
+ valueList.append(modelNode.variantProperty("x"));
}
-}
-
-void NodeInstanceView::propertiesRemoved(const QList<AbstractProperty>& /*propertyList*/)
-{
-}
-void NodeInstanceView::resetInstanceProperty(const AbstractProperty &property)
-{
- if (hasInstanceForNode(property.parentModelNode())) { // TODO ugly workaround
- NodeInstance instance = instanceForNode(property.parentModelNode());
- Q_ASSERT(instance.isValid());
- const QString name = property.name();
- if (activeStateInstance().isValid() && !property.parentModelNode().metaInfo().isSubclassOf("PropertyChange", 4, 7)) {
- bool statePropertyWasReseted = activeStateInstance().resetStateProperty(instance, name, instance.resetVariant(name));
- if (!statePropertyWasReseted)
- instance.resetProperty(name);
- } else {
- instance.resetProperty(name);
- }
+ if (modelNode.hasBindingProperty("width")) {
+ bindingList.append(modelNode.bindingProperty("width"));
+ } else if (modelNode.hasVariantProperty("width")) {
+ valueList.append(modelNode.variantProperty("width"));
}
-}
-void NodeInstanceView::setInstancePropertyBinding(const BindingProperty &property)
-{
- NodeInstance instance = instanceForNode(property.parentModelNode());
+ if (!valueList.isEmpty())
+ nodeInstanceServer()->changePropertyValues(createChangeValueCommand(valueList));
- const QString name = property.name();
- const QString expression = property.expression();
+ if (!bindingList.isEmpty())
+ nodeInstanceServer()->changePropertyBindings(createChangeBindingCommand(bindingList));
+}
- if (activeStateInstance().isValid() && !property.parentModelNode().metaInfo().isSubclassOf("PropertyChange", 4, 7)) {
- bool stateBindingWasUpdated = activeStateInstance().updateStateBinding(instance, name, expression);
- if (!stateBindingWasUpdated) {
- if (property.isDynamic())
- instance.setPropertyDynamicBinding(name, property.dynamicTypeName(), expression);
- else
- instance.setPropertyBinding(name, expression);
- }
- } else {
- if (property.isDynamic())
- instance.setPropertyDynamicBinding(name, property.dynamicTypeName(), expression);
- else
- instance.setPropertyBinding(name, expression);
- }
+void NodeInstanceView::resetVerticalAnchors(const ModelNode &modelNode)
+{
+ QList<BindingProperty> bindingList;
+ QList<VariantProperty> valueList;
+ if (modelNode.hasBindingProperty("yx")) {
+ bindingList.append(modelNode.bindingProperty("yx"));
+ } else if (modelNode.hasVariantProperty("y")) {
+ valueList.append(modelNode.variantProperty("y"));
+ }
- if (property.parentModelNode().isRootNode()
- && (name == "width" || name == "height")) {
- QGraphicsObject *rootGraphicsObject = qobject_cast<QGraphicsObject*>(instance.internalObject());
- if (rootGraphicsObject) {
- m_graphicsView->setSceneRect(rootGraphicsObject->boundingRect());
- }
+ if (modelNode.hasBindingProperty("height")) {
+ bindingList.append(modelNode.bindingProperty("height"));
+ } else if (modelNode.hasVariantProperty("height")) {
+ valueList.append(modelNode.variantProperty("height"));
}
- instance.paintUpdate();
+ if (!valueList.isEmpty())
+ nodeInstanceServer()->changePropertyValues(createChangeValueCommand(valueList));
+ if (!bindingList.isEmpty())
+ nodeInstanceServer()->changePropertyBindings(createChangeBindingCommand(bindingList));
}
-void NodeInstanceView::setInstancePropertyVariant(const VariantProperty &property)
+void NodeInstanceView::propertiesAboutToBeRemoved(const QList<AbstractProperty>& propertyList)
{
- NodeInstance instance = instanceForNode(property.parentModelNode());
-
- const QString name = property.name();
- const QVariant value = property.value();
+ QList<ModelNode> nodeList;
+ QList<AbstractProperty> nonNodePropertyList;
- if (activeStateInstance().isValid() && !property.parentModelNode().metaInfo().isSubclassOf("PropertyChange", 4, 7)) {
- bool stateValueWasUpdated = activeStateInstance().updateStateVariant(instance, name, value);
- if (!stateValueWasUpdated) {
- if (property.isDynamic())
- instance.setPropertyDynamicVariant(name, property.dynamicTypeName(), value);
- else
- instance.setPropertyVariant(name, value);
+ foreach (const AbstractProperty &property, propertyList) {
+ if (property.isNodeAbstractProperty()) {
+ nodeList.append(property.toNodeAbstractProperty().allSubNodes());
+ } else {
+ nonNodePropertyList.append(property);
}
- } else { //base state
- if (property.isDynamic())
- instance.setPropertyDynamicVariant(name, property.dynamicTypeName(), value);
- else
- instance.setPropertyVariant(name, value);
}
+ nodeInstanceServer()->removeInstances(createRemoveInstancesCommand(nodeList));
+ nodeInstanceServer()->removeProperties(createRemovePropertiesCommand(nonNodePropertyList));
- if (property.parentModelNode().isRootNode()
- && (name == "width" || name == "height")) {
- QGraphicsObject *rootGraphicsObject = qobject_cast<QGraphicsObject*>(instance.internalObject());
- if (rootGraphicsObject) {
- m_graphicsView->setSceneRect(rootGraphicsObject->boundingRect());
+ foreach (const AbstractProperty &property, propertyList) {
+ const QString &name = property.name();
+ if (name == "anchors.fill") {
+ resetHorizontalAnchors(property.parentModelNode());
+ resetVerticalAnchors(property.parentModelNode());
+ } else if (name == "anchors.centerIn") {
+ resetHorizontalAnchors(property.parentModelNode());
+ resetVerticalAnchors(property.parentModelNode());
+ } else if (name == "anchors.top") {
+ resetVerticalAnchors(property.parentModelNode());
+ } else if (name == "anchors.left") {
+ resetHorizontalAnchors(property.parentModelNode());
+ } else if (name == "anchors.right") {
+ resetHorizontalAnchors(property.parentModelNode());
+ } else if (name == "anchors.bottom") {
+ resetVerticalAnchors(property.parentModelNode());
+ } else if (name == "anchors.horizontalCenter") {
+ resetHorizontalAnchors(property.parentModelNode());
+ } else if (name == "anchors.verticalCenter") {
+ resetVerticalAnchors(property.parentModelNode());
+ } else if (name == "anchors.baseline") {
+ resetVerticalAnchors(property.parentModelNode());
}
}
- instance.paintUpdate();
+ foreach (const ModelNode &node, nodeList)
+ removeInstanceNodeRelationship(node);
+}
+
+void NodeInstanceView::propertiesRemoved(const QList<AbstractProperty>& /*propertyList*/)
+{
}
void NodeInstanceView::removeInstanceAndSubInstances(const ModelNode &node)
@@ -287,19 +319,20 @@ void NodeInstanceView::removeInstanceAndSubInstances(const ModelNode &node)
void NodeInstanceView::rootNodeTypeChanged(const QString &/*type*/, int /*majorVersion*/, int /*minorVersion*/)
{
+ nodeInstanceServer()->clearScene(createClearSceneCommand());
removeAllInstanceNodeRelationships();
QList<ModelNode> nodeList;
nodeList.append(allModelNodes());
+ nodeInstanceServer()->createScene(createCreateSceneCommand());
loadNodes(nodeList);
}
void NodeInstanceView::bindingPropertiesChanged(const QList<BindingProperty>& propertyList, PropertyChangeFlags /*propertyChange*/)
{
- foreach (const BindingProperty &property, propertyList)
- setInstancePropertyBinding(property);
+ nodeInstanceServer()->changePropertyBindings(createChangeBindingCommand(propertyList));
}
/*! \brief Notifing the view that a AbstractProperty value was changed to a ModelNode.
@@ -315,8 +348,7 @@ void NodeInstanceView::bindingPropertiesChanged(const QList<BindingProperty>& pr
void NodeInstanceView::variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags /*propertyChange*/)
{
- foreach (const VariantProperty &property, propertyList)
- setInstancePropertyVariant(property);
+ nodeInstanceServer()->changePropertyValues(createChangeValueCommand(propertyList));
}
/*! \brief Notifing the view that a ModelNode has a new Parent.
@@ -332,39 +364,59 @@ void NodeInstanceView::variantPropertiesChanged(const QList<VariantProperty>& pr
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());
+ nodeInstanceServer()->reparentInstances(createReparentInstancesCommand(node, newPropertyParent, oldPropertyParent));
+// 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*/)
+void NodeInstanceView::nodeAboutToBeReparented(const ModelNode &/*node*/, const NodeAbstractProperty &/*newPropertyParent*/, const NodeAbstractProperty &/*oldPropertyParent*/, AbstractView::PropertyChangeFlags /*propertyChange*/)
+{
+}
+
+
+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());
+ //engine()->setBaseUrl(model()->fileUrl());
+
+ //TODO reload the whole scene
+ nodeInstanceServer()->changeFileUrl(createChangeFileUrlCommand(newUrl));
}
-void NodeInstanceView::nodeIdChanged(const ModelNode& node, const QString& newId, const QString& /*oldId*/)
+void NodeInstanceView::nodeIdChanged(const ModelNode& node, const QString& /*newId*/, const QString& /*oldId*/)
{
if (hasInstanceForNode(node)) {
NodeInstance instance = instanceForNode(node);
-
- instance.setId(newId);
+ nodeInstanceServer()->changeIds(createChangeIdsCommand(QList<NodeInstance>() << instance));
}
}
void NodeInstanceView::nodeOrderChanged(const NodeListProperty & listProperty,
const ModelNode & /*movedNode*/, int /*oldIndex*/)
{
+ QVector<ReparentContainer> containerList;
+ QString propertyName = listProperty.name();
+ qint32 containerInstanceId = -1;
+ ModelNode containerNode = listProperty.parentModelNode();
+ if (hasInstanceForNode(containerNode))
+ containerInstanceId = instanceForNode(containerNode).instanceId();
+
foreach(const ModelNode &node, listProperty.toModelNodeList()) {
- NodeInstance instance = instanceForNode(node);
- if (instance.isValid())
- instance.reparent(instance.parent(), listProperty.name(), instance.parent(), listProperty.name());
+ qint32 instanceId = -1;
+ if (hasInstanceForNode(node)) {
+ instanceId = instanceForNode(node).instanceId();
+ ReparentContainer container(instanceId, containerInstanceId, propertyName, containerInstanceId, propertyName);
+ containerList.append(container);
+ }
}
+
+ nodeInstanceServer()->reparentInstances(ReparentInstancesCommand(containerList));
}
/*! \brief Notifing the view that the selection has been changed.
@@ -391,66 +443,71 @@ void NodeInstanceView::instancePropertyChange(const QList<QPair<ModelNode, QStri
}
+void NodeInstanceView::instancesCompleted(const QVector<ModelNode> &/*completedNodeList*/)
+{
+}
+
+void NodeInstanceView::importAdded(const Import & /*import*/)
+{
+ restartProcessDelayed();
+}
+
+void NodeInstanceView::importRemoved(const Import &/*import*/)
+{
+ restartProcessDelayed();
+}
//\}
void NodeInstanceView::loadNodes(const QList<ModelNode> &nodeList)
{
+ QList<NodeInstance> instanceList;
+
foreach (const ModelNode &node, nodeList)
- loadNode(node);
+ instanceList.append(loadNode(node));
- foreach (const ModelNode &node, nodeList) {
- if (node.hasParentProperty())
- instanceForNode(node).reparent(NodeInstance(), QString(), instanceForNode(node.parentProperty().parentModelNode()), node.parentProperty().name());
- }
+
+ QList<VariantProperty> variantPropertyList;
+ QList<BindingProperty> bindingPropertyList;
foreach (const ModelNode &node, nodeList) {
- foreach (const BindingProperty &property, node.bindingProperties())
- instanceForNode(node).setPropertyBinding(property.name(), property.expression());
+ variantPropertyList.append(node.variantProperties());
+ bindingPropertyList.append(node.bindingProperties());
}
- QListIterator<ModelNode> listIterator(nodeList);
- listIterator.toBack();
-
- while (listIterator.hasPrevious())
- instanceForNode(listIterator.previous()).doComponentComplete();
-}
-
-// TODO: Set base state as current model state
-void NodeInstanceView::loadModel(Model *model)
-{
- removeAllInstanceNodeRelationships();
-
- engine()->rootContext()->setBaseUrl(model->fileUrl());
-
- loadNodes(allModelNodes());
+ nodeInstanceServer()->createInstances(createCreateInstancesCommand(instanceList));
+ nodeInstanceServer()->reparentInstances(createReparentInstancesCommand(instanceList));
+ nodeInstanceServer()->changeIds(createChangeIdsCommand(instanceList));
+ nodeInstanceServer()->changePropertyValues(createChangeValueCommand(variantPropertyList));
+ nodeInstanceServer()->changePropertyBindings(createChangeBindingCommand(bindingPropertyList));
+ nodeInstanceServer()->completeComponent(createComponentCompleteCommand(instanceList));
}
void NodeInstanceView::removeAllInstanceNodeRelationships()
{
// prevent destroyed() signals calling back
- foreach (NodeInstance instance, m_objectInstanceHash.values()) {
- if (instance.isValid())
- instance.setId(QString());
- }
+// foreach (NodeInstance instance, m_objectInstanceHash.values()) {
+// if (instance.isValid())
+// instance.setId(QString());
+// }
- //first the root object
- if (rootNodeInstance().internalObject())
- rootNodeInstance().internalObject()->disconnect();
+// //first the root object
+// if (rootNodeInstance().internalObject())
+// rootNodeInstance().internalObject()->disconnect();
- rootNodeInstance().makeInvalid();
+// rootNodeInstance().makeInvalid();
- foreach (NodeInstance instance, m_objectInstanceHash.values()) {
- if (instance.internalObject())
- instance.internalObject()->disconnect();
+ foreach (NodeInstance instance, m_idInstanceHash.values()) {
+// if (instance.internalObject())
+// instance.internalObject()->disconnect();
instance.makeInvalid();
- }
+ }
m_nodeInstanceHash.clear();
- m_objectInstanceHash.clear();
+ m_idInstanceHash.clear();
}
/*! \brief Returns a List of all NodeInstances
@@ -471,7 +528,7 @@ QList<NodeInstance> NodeInstanceView::instances() const
\returns NodeStance for ModelNode.
\see NodeInstance
*/
-NodeInstance NodeInstanceView::instanceForNode(const ModelNode &node)
+NodeInstance NodeInstanceView::instanceForNode(const ModelNode &node) const
{
Q_ASSERT(node.isValid());
Q_ASSERT(m_nodeInstanceHash.contains(node));
@@ -479,25 +536,25 @@ NodeInstance NodeInstanceView::instanceForNode(const ModelNode &node)
return m_nodeInstanceHash.value(node);
}
-bool NodeInstanceView::hasInstanceForNode(const ModelNode &node)
+bool NodeInstanceView::hasInstanceForNode(const ModelNode &node) const
{
return m_nodeInstanceHash.contains(node);
}
-NodeInstance NodeInstanceView::instanceForObject(QObject *object)
+NodeInstance NodeInstanceView::instanceForId(qint32 id) const
{
- if (object == 0)
+ if (id < 0)
return NodeInstance();
- return m_objectInstanceHash.value(object);
+ return m_idInstanceHash.value(id);
}
-bool NodeInstanceView::hasInstanceForObject(QObject *object)
+bool NodeInstanceView::hasInstanceForId(qint32 id) const
{
- if (object == 0)
+ if (id < 0)
return false;
- return m_objectInstanceHash.contains(object);
+ return m_idInstanceHash.contains(id);
}
@@ -540,58 +597,36 @@ NodeInstance NodeInstanceView::rootNodeInstance() const
-void NodeInstanceView::insertInstanceNodeRelationship(const ModelNode &node, const NodeInstance &instance)
+void NodeInstanceView::insertInstanceRelationships(const NodeInstance &instance)
{
- instance.internalObject()->installEventFilter(childrenChangeEventFilter());
-
-
- Q_ASSERT(!m_nodeInstanceHash.contains(node));
- m_nodeInstanceHash.insert(node, instance);
- m_objectInstanceHash.insert(instance.internalObject(), instance);
-}
-
-QDeclarativeEngine *NodeInstanceView::engine()
-{
- if (m_engine.isNull())
- m_engine = new QDeclarativeEngine(this);
- 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(emitParentChanged(QObject*)));
- }
-
- return m_childrenChangeEventFilter.data();
+ Q_ASSERT(instance.instanceId() >=0);
+ Q_ASSERT(!m_nodeInstanceHash.contains(instance.modelNode()));
+ Q_ASSERT(!m_idInstanceHash.contains(instance.instanceId()));
+ m_nodeInstanceHash.insert(instance.modelNode(), instance);
+ m_idInstanceHash.insert(instance.instanceId(), instance);
}
void NodeInstanceView::removeInstanceNodeRelationship(const ModelNode &node)
{
Q_ASSERT(m_nodeInstanceHash.contains(node));
NodeInstance instance = instanceForNode(node);
- if (instance.isValid())
- instance.setId(QString());
- m_objectInstanceHash.remove(instanceForNode(node).internalObject());
+// if (instance.isValid())
+// instance.setId(QString());
+ m_idInstanceHash.remove(instanceForNode(node).instanceId());
m_nodeInstanceHash.remove(node);
instance.makeInvalid();
}
-void NodeInstanceView::notifyPropertyChange(const ModelNode &node, const QString &propertyName)
+void NodeInstanceView::setBlockUpdates(bool block)
{
- if (m_blockStatePropertyChanges)
- return;
- if (!node.isValid())
- return;
-
- emitInstancePropertyChange(QList<QPair<ModelNode, QString> >() << qMakePair(node, propertyName));
-}
+ if (m_blockUpdates == 0 && block == true)
+ m_nodeInstanceServer->setBlockUpdates(true);
-
-void NodeInstanceView::setBlockStatePropertyChanges(bool block)
-{
- m_blockStatePropertyChanges = block;
+ if (block) {
+ m_blockUpdates++;
+ } else if (m_blockUpdates > 0) {
+ m_blockUpdates--;
+ }
}
void NodeInstanceView::setStateInstance(const NodeInstance &stateInstance)
@@ -609,26 +644,20 @@ NodeInstance NodeInstanceView::activeStateInstance() const
return m_activeStateInstance;
}
-void NodeInstanceView::emitParentChanged(QObject *child)
+NodeInstanceServerInterface *NodeInstanceView::nodeInstanceServer() const
{
- if (hasInstanceForObject(child)) {
- notifyPropertyChange(instanceForObject(child).modelNode(), "parent");
- }
+ return m_nodeInstanceServer.data();
}
-NodeInstance NodeInstanceView::loadNode(const ModelNode &node, QObject *objectToBeWrapped)
+
+NodeInstance NodeInstanceView::loadNode(const ModelNode &node)
{
- NodeInstance instance(NodeInstance::create(this, node, objectToBeWrapped));
+ NodeInstance instance(NodeInstance::create(node));
- insertInstanceNodeRelationship(node, instance);
+ insertInstanceRelationships(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;
@@ -636,22 +665,24 @@ NodeInstance NodeInstanceView::loadNode(const ModelNode &node, QObject *objectTo
void NodeInstanceView::activateState(const NodeInstance &instance)
{
- activateBaseState();
- NodeInstance stateInstance(instance);
- stateInstance.activateState();
+ nodeInstanceServer()->changeState(ChangeStateCommand(instance.instanceId()));
+// activateBaseState();
+// NodeInstance stateInstance(instance);
+// stateInstance.activateState();
}
void NodeInstanceView::activateBaseState()
{
- if (activeStateInstance().isValid())
- activeStateInstance().deactivateState();
+ nodeInstanceServer()->changeState(ChangeStateCommand(-1));
+// if (activeStateInstance().isValid())
+// activeStateInstance().deactivateState();
}
void NodeInstanceView::removeRecursiveChildRelationship(const ModelNode &removedNode)
{
- if (hasInstanceForNode(removedNode)) {
- instanceForNode(removedNode).setId(QString());
- }
+// if (hasInstanceForNode(removedNode)) {
+// instanceForNode(removedNode).setId(QString());
+// }
foreach (const ModelNode &childNode, removedNode.allDirectSubModelNodes())
removeRecursiveChildRelationship(childNode);
@@ -659,66 +690,297 @@ void NodeInstanceView::removeRecursiveChildRelationship(const ModelNode &removed
removeInstanceNodeRelationship(removedNode);
}
-void NodeInstanceView::render(QPainter * painter, const QRectF &target, const QRectF &source, Qt::AspectRatioMode aspectRatioMode)
+QRectF NodeInstanceView::sceneRect() const
+{
+ if (rootNodeInstance().isValid())
+ return rootNodeInstance().boundingRect();
+
+ return QRectF();
+}
+
+CreateSceneCommand NodeInstanceView::createCreateSceneCommand() const
{
- 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();
+ return CreateSceneCommand();
+}
+ClearSceneCommand NodeInstanceView::createClearSceneCommand() const
+{
+ return ClearSceneCommand();
+}
+
+CompleteComponentCommand NodeInstanceView::createComponentCompleteCommand(const QList<NodeInstance> &instanceList) const
+{
+ QVector<qint32> containerList;
+ foreach(const NodeInstance &instance, instanceList) {
+ if (instance.instanceId() >= 0)
+ containerList.append(instance.instanceId());
}
+
+ return CompleteComponentCommand(containerList);
}
+ComponentCompletedCommand NodeInstanceView::createComponentCompletedCommand(const QList<NodeInstance> &instanceList) const
+{
+ QVector<qint32> containerList;
+ foreach(const NodeInstance &instance, instanceList) {
+ if (instance.instanceId() >= 0)
+ containerList.append(instance.instanceId());
+ }
-QRectF NodeInstanceView::sceneRect() const
+ return ComponentCompletedCommand(containerList);
+}
+
+CreateInstancesCommand NodeInstanceView::createCreateInstancesCommand(const QList<NodeInstance> &instanceList) const
{
- if (m_graphicsView)
- return rootNodeInstance().boundingRect();
+ QVector<InstanceContainer> containerList;
+ foreach(const NodeInstance &instance, instanceList) {
+ InstanceContainer container(instance.instanceId(), instance.modelNode().type(), instance.modelNode().majorVersion(), instance.modelNode().minorVersion(), instance.modelNode().metaInfo().componentFileName());
+ containerList.append(container);
+ }
- return QRectF();
+ return CreateInstancesCommand(containerList);
+}
+
+ReparentInstancesCommand NodeInstanceView::createReparentInstancesCommand(const QList<NodeInstance> &instanceList) const
+{
+ QVector<ReparentContainer> containerList;
+ foreach(const NodeInstance &instance, instanceList) {
+ if (instance.modelNode().hasParentProperty()) {
+ NodeAbstractProperty parentProperty = instance.modelNode().parentProperty();
+ ReparentContainer container(instance.instanceId(), -1, QString(), instanceForNode(parentProperty.parentModelNode()).instanceId(), parentProperty.name());
+ containerList.append(container);
+ }
+ }
+
+ return ReparentInstancesCommand(containerList);
+}
+
+ReparentInstancesCommand NodeInstanceView::createReparentInstancesCommand(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent) const
+{
+ QVector<ReparentContainer> containerList;
+
+ qint32 newParentInstanceId = -1;
+ qint32 oldParentInstanceId = -1;
+
+ if (newPropertyParent.isValid() && hasInstanceForNode(newPropertyParent.parentModelNode()))
+ newParentInstanceId = instanceForNode(newPropertyParent.parentModelNode()).instanceId();
+
+
+ if (oldPropertyParent.isValid() && hasInstanceForNode(oldPropertyParent.parentModelNode()))
+ oldParentInstanceId = instanceForNode(oldPropertyParent.parentModelNode()).instanceId();
+
+
+ ReparentContainer container(instanceForNode(node).instanceId(), oldParentInstanceId, oldPropertyParent.name(), newParentInstanceId, newPropertyParent.name());
+
+ containerList.append(container);
+
+ return ReparentInstancesCommand(containerList);
+}
+
+ChangeFileUrlCommand NodeInstanceView::createChangeFileUrlCommand(const QUrl &fileUrl) const
+{
+ return ChangeFileUrlCommand(fileUrl);
+}
+
+ChangeValuesCommand NodeInstanceView::createChangeValueCommand(const QList<VariantProperty>& propertyList) const
+{
+ QVector<PropertyValueContainer> containerList;
+
+ foreach(const VariantProperty &property, propertyList) {
+ ModelNode node = property.parentModelNode();
+ if (node.isValid() && hasInstanceForNode(node)) {
+ NodeInstance instance = instanceForNode(node);
+ PropertyValueContainer container(instance.instanceId(), property.name(), property.value(), property.dynamicTypeName());
+ containerList.append(container);
+ }
+
+ }
+
+ return ChangeValuesCommand(containerList);
+}
+
+ChangeBindingsCommand NodeInstanceView::createChangeBindingCommand(const QList<BindingProperty> &propertyList) const
+{
+ QVector<PropertyBindingContainer> containerList;
+
+ foreach(const BindingProperty &property, propertyList) {
+ ModelNode node = property.parentModelNode();
+ if (node.isValid() && hasInstanceForNode(node)) {
+ NodeInstance instance = instanceForNode(node);
+ PropertyBindingContainer container(instance.instanceId(), property.name(), property.expression(), property.dynamicTypeName());
+ containerList.append(container);
+ }
+
+ }
+
+ return ChangeBindingsCommand(containerList);
+}
+
+ChangeIdsCommand NodeInstanceView::createChangeIdsCommand(const QList<NodeInstance> &instanceList) const
+{
+ QVector<IdContainer> containerList;
+ foreach(const NodeInstance &instance, instanceList) {
+ QString id = instance.modelNode().id();
+ if (!id.isEmpty()) {
+ IdContainer container(instance.instanceId(), id);
+ containerList.append(container);
+ }
+ }
+
+ return ChangeIdsCommand(containerList);
+}
+
+
+
+RemoveInstancesCommand NodeInstanceView::createRemoveInstancesCommand(const QList<ModelNode> &nodeList) const
+{
+ QVector<qint32> idList;
+ foreach(const ModelNode &node, nodeList) {
+ if (node.isValid() && hasInstanceForNode(node)) {
+ NodeInstance instance = instanceForNode(node);
+
+ if (instance.instanceId() >= 0) {
+ idList.append(instance.instanceId());
+ }
+ }
+ }
+
+ return RemoveInstancesCommand(idList);
}
+RemoveInstancesCommand NodeInstanceView::createRemoveInstancesCommand(const ModelNode &node) const
+{
+ QVector<qint32> idList;
+
+ if (node.isValid() && hasInstanceForNode(node))
+ idList.append(instanceForNode(node).instanceId());
-QFileSystemWatcher *NodeInstanceView::fileSystemWatcher()
+ return RemoveInstancesCommand(idList);
+}
+
+RemovePropertiesCommand NodeInstanceView::createRemovePropertiesCommand(const QList<AbstractProperty> &propertyList) const
{
- if (m_fileSystemWatcher.isNull()) {
- m_fileSystemWatcher = new QFileSystemWatcher(this);
- connect(m_fileSystemWatcher.data(), SIGNAL(fileChanged(QString)), this, SLOT(refreshLocalFileProperty(QString)));
+ QVector<PropertyAbstractContainer> containerList;
+
+ foreach(const AbstractProperty &property, propertyList) {
+ ModelNode node = property.parentModelNode();
+ if (node.isValid() && hasInstanceForNode(node)) {
+ NodeInstance instance = instanceForNode(node);
+ PropertyAbstractContainer container(instance.instanceId(), property.name(), property.dynamicTypeName());
+ containerList.append(container);
+ }
+
}
- return m_fileSystemWatcher.data();
+ return RemovePropertiesCommand(containerList);
+}
+
+AddImportCommand NodeInstanceView::createImportCommand(const Import &import)
+{
+ return AddImportCommand(import.url(), import.file(), import.version(), import.alias(), import.importPaths());
}
-void NodeInstanceView::addFilePropertyToFileSystemWatcher(QObject *object, const QString &propertyName, const QString &path)
+void NodeInstanceView::valuesChanged(const ValuesChangedCommand &command)
{
- m_fileSystemWatcherHash.insert(path, ObjectPropertyPair(object, propertyName));
- fileSystemWatcher()->addPath(path);
+ if (!model())
+ return;
+
+ QList<QPair<ModelNode, QString> > valuePropertyChangeList;
+
+ foreach(const PropertyValueContainer &container, command.valueChanges()) {
+ if (hasInstanceForId(container.instanceId())) {
+ NodeInstance instance = instanceForId(container.instanceId());
+ if (instance.isValid()) {
+ instance.setProperty(container.name(), container.value());
+ valuePropertyChangeList.append(qMakePair(instance.modelNode(), container.name()));
+ }
+ }
+ }
+ if (!valuePropertyChangeList.isEmpty())
+ emitInstancePropertyChange(valuePropertyChangeList);
}
-void NodeInstanceView::removeFilePropertyFromFileSystemWatcher(QObject *object, const QString &propertyName, const QString &path)
+void NodeInstanceView::pixmapChanged(const PixmapChangedCommand &command)
{
- fileSystemWatcher()->removePath(path);
- m_fileSystemWatcherHash.remove(path, ObjectPropertyPair(object, propertyName));
+ if (!model())
+ return;
+
+ QSet<ModelNode> renderImageChangeSet;
+
+ foreach (const ImageContainer &container, command.images()) {
+ if (hasInstanceForId(container.instanceId())) {
+ NodeInstance instance = instanceForId(container.instanceId());
+ if (instance.isValid()) {
+ instance.setRenderImage(container.image());
+ renderImageChangeSet.insert(instance.modelNode());
+ }
+ }
+ }
+
+ if (!renderImageChangeSet.isEmpty())
+ emitCustomNotification("__instance render pixmap changed__", renderImageChangeSet.toList());
}
-void NodeInstanceView::refreshLocalFileProperty(const QString &path)
+void NodeInstanceView::informationChanged(const InformationChangedCommand &command)
{
- if (m_fileSystemWatcherHash.contains(path)) {
- QList<ObjectPropertyPair> objectPropertyPairList = m_fileSystemWatcherHash.values();
- foreach(const ObjectPropertyPair &objectPropertyPair, objectPropertyPairList) {
- QObject *object = objectPropertyPair.first.data();
- QString propertyName = objectPropertyPair.second;
+ if (!model())
+ return;
- if (hasInstanceForObject(object)) {
- instanceForObject(object).refreshProperty(propertyName);
+ QList<ModelNode> informationChangedList;
+
+ foreach(const InformationContainer &container, command.informations()) {
+ if (hasInstanceForId(container.instanceId())) {
+ NodeInstance instance = instanceForId(container.instanceId());
+ if (instance.isValid()) {
+ instance.setInformation(container.name(), container.information(), container.secondInformation(), container.thirdInformation());
+ informationChangedList.append(instance.modelNode());
}
}
}
+
+ if (!informationChangedList.isEmpty())
+ emitCustomNotification("__instance information changed__", informationChangedList);
+}
+
+void NodeInstanceView::statePreviewImagesChanged(const StatePreviewImageChangedCommand &/*command*/)
+{
+
+}
+
+void NodeInstanceView::componentCompleted(const ComponentCompletedCommand &command)
+{
+ if (!model())
+ return;
+
+ QVector<ModelNode> nodeVector;
+
+ foreach(const qint32 &instanceId, command.instances()) {
+ if (hasModelNodeForInternalId(instanceId)) {
+ nodeVector.append(modelNodeForInternalId(instanceId));
+ }
+ }
+
+ if (!nodeVector.isEmpty())
+ emitInstancesCompleted(nodeVector);
+}
+
+void NodeInstanceView::childrenChanged(const ChildrenChangedCommand &command)
+{
+ if (!model())
+ return;
+
+ QList<ModelNode> childNodeList;
+
+ foreach(qint32 instanceId, command.childrenInstances()) {
+ if (hasInstanceForId(instanceId)) {
+ NodeInstance instance = instanceForId(instanceId);
+ instance.setParentId(command.parentInstanceId());
+ childNodeList.append(instance.modelNode());
+ }
+ }
+
+ if (!childNodeList.isEmpty())
+ emitCustomNotification("__instance children changed__", childNodeList);
}
}
diff --git a/src/plugins/qmldesigner/designercore/instances/objectnodeinstance.cpp b/src/plugins/qmldesigner/designercore/instances/objectnodeinstance.cpp
index ef05842b00..e26ae3e080 100644
--- a/src/plugins/qmldesigner/designercore/instances/objectnodeinstance.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/objectnodeinstance.cpp
@@ -35,12 +35,6 @@
#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 <invalidreparentingexception.h>
#include <invalidnodeinstanceexception.h>
@@ -50,7 +44,6 @@
#include <variantproperty.h>
#include <nodelistproperty.h>
#include <metainfo.h>
-#include <propertymetainfo.h>
#include <QEvent>
#include <QGraphicsScene>
@@ -65,6 +58,7 @@
#ifndef QT_NO_WEBKIT
#include <QGraphicsWebView>
#endif
+#include <QGraphicsObject>
#include <QTextDocument>
@@ -80,30 +74,9 @@
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:
- {
- QChildEvent *childEvent = static_cast<QChildEvent*>(event);
- emit childrenChanged(childEvent->child()); break;
- }
- default: break;
- }
-
- return false;
-}
-
ObjectNodeInstance::ObjectNodeInstance(QObject *object)
- : m_deleteHeldInstance(true),
+ : m_instanceId(-1),
+ m_deleteHeldInstance(true),
m_object(object),
m_metaObject(0),
m_isInPositioner(false)
@@ -122,13 +95,8 @@ void ObjectNodeInstance::destroy()
// Remove from old property
if (object()) {
setId(QString());
- if (modelNode().isValid() && modelNode().parentProperty().isValid()) {
- NodeAbstractProperty parentProperty = modelNode().parentProperty();
- ModelNode parentNode = parentProperty.parentModelNode();
- if (parentNode.isValid() && nodeInstanceView()->hasInstanceForNode(parentNode)) {
- NodeInstance parentInstance = nodeInstanceView()->instanceForNode(parentNode);
- reparent(parentInstance, parentProperty.name(), NodeInstance() , QString());
- }
+ if (m_instanceId >= 0) {
+ reparent(parentInstance(), m_parentProperty, ObjectNodeInstance::Pointer(), QString());
}
}
@@ -140,28 +108,29 @@ void ObjectNodeInstance::destroy()
}
m_metaObject = 0;
+ m_instanceId = -1;
}
-ModelNode ObjectNodeInstance::modelNode() const
+void ObjectNodeInstance::setInstanceId(qint32 id)
{
- return m_modelNode;
+ m_instanceId = id;
}
-void ObjectNodeInstance::setModelNode(const ModelNode &node)
+qint32 ObjectNodeInstance::instanceId() const
{
- m_modelNode = node;
+ return m_instanceId;
}
-NodeInstanceView *ObjectNodeInstance::nodeInstanceView() const
+NodeInstanceServer *ObjectNodeInstance::nodeInstanceServer() const
{
- return m_nodeInstanceView.data();
+ return m_nodeInstanceServer.data();
}
-void ObjectNodeInstance::setNodeInstanceView(NodeInstanceView *view)
+void ObjectNodeInstance::setNodeInstanceServer(NodeInstanceServer *server)
{
- Q_ASSERT(!m_nodeInstanceView.data());
+ Q_ASSERT(!m_nodeInstanceServer.data());
- m_nodeInstanceView = view;
+ m_nodeInstanceServer = server;
}
static bool hasPropertiesWitoutNotifications(const QMetaObject *metaObject)
@@ -176,19 +145,15 @@ static bool hasPropertiesWitoutNotifications(const QMetaObject *metaObject)
void ObjectNodeInstance::initializePropertyWatcher(const ObjectNodeInstance::Pointer &objectNodeInstance)
{
- if (!objectNodeInstance->modelNode().metaInfo().isComponent()) { // TODO: this is a nasty workaround which needs to be removed
- const QMetaObject *metaObject = objectNodeInstance->object()->metaObject();
- m_metaObject = new NodeInstanceMetaObject(objectNodeInstance, nodeInstanceView()->engine());
- for(int propertyIndex = QObject::staticMetaObject.propertyCount(); propertyIndex < metaObject->propertyCount(); propertyIndex++) {
- if (QDeclarativeMetaType::isQObject(metaObject->property(propertyIndex).userType())) {
- QObject *propertyObject = QDeclarativeMetaType::toQObject(metaObject->property(propertyIndex).read(objectNodeInstance->object()));
- if (propertyObject && hasPropertiesWitoutNotifications(propertyObject->metaObject())) {
- new NodeInstanceMetaObject(objectNodeInstance, propertyObject, metaObject->property(propertyIndex).name(), nodeInstanceView()->engine());
- }
+ const QMetaObject *metaObject = objectNodeInstance->object()->metaObject();
+ m_metaObject = new NodeInstanceMetaObject(objectNodeInstance, nodeInstanceServer()->engine());
+ for(int propertyIndex = QObject::staticMetaObject.propertyCount(); propertyIndex < metaObject->propertyCount(); propertyIndex++) {
+ if (QDeclarativeMetaType::isQObject(metaObject->property(propertyIndex).userType())) {
+ QObject *propertyObject = QDeclarativeMetaType::toQObject(metaObject->property(propertyIndex).read(objectNodeInstance->object()));
+ if (propertyObject && hasPropertiesWitoutNotifications(propertyObject->metaObject())) {
+ new NodeInstanceMetaObject(objectNodeInstance, propertyObject, metaObject->property(propertyIndex).name(), nodeInstanceServer()->engine());
}
}
- } else {
- qWarning() << "dynamic properties are not supported for components";
}
m_signalSpy.setObjectNodeInstance(objectNodeInstance);
@@ -217,35 +182,6 @@ 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::isQDeclarativeView() const
-{
- return false;
-}
bool ObjectNodeInstance::isGraphicsObject() const
{
@@ -329,9 +265,9 @@ bool ObjectNodeInstance::isAnchoredByChildren() const
return false;
}
-QPair<QString, NodeInstance> ObjectNodeInstance::anchor(const QString &/*name*/) const
+QPair<QString, ServerNodeInstance> ObjectNodeInstance::anchor(const QString &/*name*/) const
{
- return qMakePair(QString(), NodeInstance());
+ return qMakePair(QString(), ServerNodeInstance());
}
@@ -388,10 +324,10 @@ void ObjectNodeInstance::removeFromOldProperty(QObject *object, QObject *oldPare
return;
if (isList(property)) {
- removeObjectFromList(property, object, nodeInstanceView()->engine());
+ removeObjectFromList(property, object, nodeInstanceServer()->engine());
} else if (isObject(property)) {
- if (nodeInstanceView()->hasInstanceForObject(oldParent)) {
- nodeInstanceView()->instanceForObject(oldParent).resetProperty(oldParentProperty);
+ if (nodeInstanceServer()->hasInstanceForObject(oldParent)) {
+ nodeInstanceServer()->instanceForObject(oldParent).resetProperty(oldParentProperty);
}
}
@@ -424,14 +360,16 @@ void ObjectNodeInstance::addToNewProperty(QObject *object, QObject *newParent, c
Q_ASSERT(objectToVariant(object).isValid());
}
-void ObjectNodeInstance::reparent(const NodeInstance &oldParentInstance, const QString &oldParentProperty, const NodeInstance &newParentInstance, const QString &newParentProperty)
+void ObjectNodeInstance::reparent(const ObjectNodeInstance::Pointer &oldParentInstance, const QString &oldParentProperty, const ObjectNodeInstance::Pointer &newParentInstance, const QString &newParentProperty)
{
- if (oldParentInstance.isValid()) {
- removeFromOldProperty(object(), oldParentInstance.internalObject(), oldParentProperty);
+ if (oldParentInstance) {
+ removeFromOldProperty(object(), oldParentInstance->object(), oldParentProperty);
+ m_parentProperty.clear();
}
- if (newParentInstance.isValid()) {
- addToNewProperty(object(), newParentInstance.internalObject(), newParentProperty);
+ if (newParentInstance) {
+ m_parentProperty = newParentProperty;
+ addToNewProperty(object(), newParentInstance->object(), newParentProperty);
}
refreshBindings(context()->engine()->rootContext());
@@ -448,22 +386,23 @@ void ObjectNodeInstance::setPropertyVariant(const QString &name, const QVariant
if (oldValue.type() == QVariant::Url) {
QUrl url = oldValue.toUrl();
QString path = url.toLocalFile();
- if (QFileInfo(path).exists() && nodeInstanceView() && !path.isEmpty())
- nodeInstanceView()->removeFilePropertyFromFileSystemWatcher(object(), name, path);
+ if (QFileInfo(path).exists() && nodeInstanceServer() && !path.isEmpty())
+ nodeInstanceServer()->removeFilePropertyFromFileSystemWatcher(object(), name, path);
}
- property.write(value);
+ bool isWritten = property.write(value);
+
+ if (!isWritten)
+ qDebug() << "ObjectNodeInstance.setPropertyVariant: Cannot be written: " << object() << name << value;
QVariant newValue = property.read();
if (newValue.type() == QVariant::Url) {
QUrl url = newValue.toUrl();
QString path = url.toLocalFile();
- if (QFileInfo(path).exists() && nodeInstanceView() && !path.isEmpty())
- nodeInstanceView()->addFilePropertyToFileSystemWatcher(object(), name, path);
+ if (QFileInfo(path).exists() && nodeInstanceServer() && !path.isEmpty())
+ nodeInstanceServer()->addFilePropertyToFileSystemWatcher(object(), name, path);
}
-
-
}
void ObjectNodeInstance::setPropertyBinding(const QString &name, const QString &expression)
@@ -474,16 +413,17 @@ void ObjectNodeInstance::setPropertyBinding(const QString &name, const QString &
return;
if (property.isProperty()) {
- QDeclarativeBinding *binding = new QDeclarativeBinding(expression, object(), context());
+ QDeclarativeBinding *binding = new QDeclarativeBinding(expression, object(), context(), object());
binding->setTarget(property);
binding->setNotifyOnValueChanged(true);
QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::setBinding(property, binding);
if (oldBinding)
oldBinding->destroy();
binding->update();
+ if (binding->hasError())
+ qDebug() <<" ObjectNodeInstance.setPropertyBinding has Error: " << object() << name << expression;
} else {
- qWarning() << "Cannot set binding for property" << name << ": property is unknown for type"
- << (modelNode().isValid() ? modelNode().type() : "unknown");
+ qWarning() << "ObjectNodeInstance.setPropertyBinding: Cannot set binding for property" << name << ": property is unknown for type";
}
}
@@ -515,17 +455,6 @@ void ObjectNodeInstance::resetProperty(const QString &name)
doResetProperty("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::refreshProperty(const QString &name)
{
QDeclarativeProperty property(object(), name, context());
@@ -549,10 +478,18 @@ void ObjectNodeInstance::refreshProperty(const QString &name)
property.write(oldValue);
}
-bool ObjectNodeInstance::hasBindingForProperty(const QString &name) const
+bool ObjectNodeInstance::hasBindingForProperty(const QString &name, bool *hasChanged) const
{
QDeclarativeProperty property(object(), name, context());
+ bool hasBinding = QDeclarativePropertyPrivate::binding(property);
+
+ if (hasChanged) {
+ *hasChanged = hasBinding != m_hasBindingHash.value(name, false);
+ if (*hasChanged)
+ m_hasBindingHash.insert(name, hasBinding);
+ }
+
return QDeclarativePropertyPrivate::binding(property);
}
@@ -569,8 +506,8 @@ void ObjectNodeInstance::doResetProperty(const QString &propertyName)
if (oldValue.type() == QVariant::Url) {
QUrl url = oldValue.toUrl();
QString path = url.toLocalFile();
- if (QFileInfo(path).exists() && nodeInstanceView())
- nodeInstanceView()->removeFilePropertyFromFileSystemWatcher(object(), propertyName, path);
+ if (QFileInfo(path).exists() && nodeInstanceServer())
+ nodeInstanceServer()->removeFilePropertyFromFileSystemWatcher(object(), propertyName, path);
}
@@ -594,6 +531,7 @@ void ObjectNodeInstance::doResetProperty(const QString &propertyName)
} else if (property.isWritable()) {
if (property.read() == resetValue(propertyName))
return;
+
property.write(resetValue(propertyName));
}
}
@@ -617,7 +555,7 @@ QVariant ObjectNodeInstance::property(const QString &name) const
return QVariant();
if (url.scheme() == "file") {
- int basePathLength = nodeInstanceView()->model()->fileUrl().toLocalFile().lastIndexOf('/');
+ int basePathLength = nodeInstanceServer()->fileUrl().toLocalFile().lastIndexOf('/');
return QUrl(url.toLocalFile().mid(basePathLength + 1));
}
}
@@ -625,6 +563,44 @@ QVariant ObjectNodeInstance::property(const QString &name) const
return property.read();
}
+QStringList allPropertyNames(QObject *object, const QString &baseName = QString(), QObjectList *inspectedObjects = new QObjectList)
+{
+ QStringList propertyNameList;
+
+
+ if (inspectedObjects== 0 || inspectedObjects->contains(object))
+ return propertyNameList;
+
+ inspectedObjects->append(object);
+
+
+ const QMetaObject *metaObject = object->metaObject();
+ for (int index = 0; index < metaObject->propertyCount(); ++index) {
+ QMetaProperty metaProperty = metaObject->property(index);
+ QDeclarativeProperty declarativeProperty(object, QLatin1String(metaProperty.name()));
+ if (declarativeProperty.isValid() && declarativeProperty.propertyTypeCategory() == QDeclarativeProperty::Object) {
+ if (declarativeProperty.name() != "parent") {
+ QObject *childObject = QDeclarativeMetaType::toQObject(declarativeProperty.read());
+ if (childObject)
+ propertyNameList.append(allPropertyNames(childObject, baseName + QString::fromUtf8(metaProperty.name()) + '.', inspectedObjects));
+ }
+ } else if (QDeclarativeValueTypeFactory::valueType(metaProperty.userType())) {
+ QDeclarativeValueType *valueType = QDeclarativeValueTypeFactory::valueType(metaProperty.userType());
+ valueType->setValue(metaProperty.read(object));
+ propertyNameList.append(allPropertyNames(valueType, baseName + QString::fromUtf8(metaProperty.name()) + '.', inspectedObjects));
+ } else {
+ propertyNameList.append(baseName + QString::fromUtf8(metaProperty.name()));
+ }
+ }
+
+ return propertyNameList;
+}
+
+QStringList ObjectNodeInstance::propertyNames() const
+{
+ return allPropertyNames(object());
+}
+
QString ObjectNodeInstance::instanceType(const QString &name) const
{
QDeclarativeProperty property(object(), name, context());
@@ -633,6 +609,10 @@ QString ObjectNodeInstance::instanceType(const QString &name) const
return property.propertyTypeName();
}
+QList<ServerNodeInstance> ObjectNodeInstance::childItems() const
+{
+ return QList<ServerNodeInstance>();
+}
void ObjectNodeInstance::setDeleteHeldInstance(bool deleteInstance)
{
@@ -644,19 +624,10 @@ bool ObjectNodeInstance::deleteHeldInstance() const
return m_deleteHeldInstance;
}
-ObjectNodeInstance::Pointer ObjectNodeInstance::create(const NodeMetaInfo &nodeMetaInfo, QDeclarativeContext *context, QObject *objectToBeWrapped)
+ObjectNodeInstance::Pointer ObjectNodeInstance::create(QObject *object)
{
- 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;
@@ -703,8 +674,10 @@ void allSubObject(QObject *object, QObjectList &objectList)
if (metaProperty.isReadable()
&& metaProperty.isWritable()
&& QDeclarativeMetaType::isQObject(metaProperty.userType())) {
- QObject *propertyObject = QDeclarativeMetaType::toQObject(metaProperty.read(object));
- allSubObject(propertyObject, objectList);
+ if (metaProperty.name() != QLatin1String("parent")) {
+ QObject *propertyObject = QDeclarativeMetaType::toQObject(metaProperty.read(object));
+ allSubObject(propertyObject, objectList);
+ }
}
@@ -748,7 +721,7 @@ static void disableTiledBackingStore(QObject *object)
#endif
}
-void ObjectNodeInstance::tweakObjects(QObject *object)
+void tweakObjects(QObject *object)
{
QObjectList objectList;
allSubObject(object, objectList);
@@ -758,56 +731,49 @@ void ObjectNodeInstance::tweakObjects(QObject *object)
}
}
-/*!
- \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 *ObjectNodeInstance::createInstance(const NodeMetaInfo &metaInfo, QDeclarativeContext *context)
+QObject *createComponent(const QString &componentPath, QDeclarativeContext *context)
{
- if (!metaInfo.isValid()) {
- qWarning() << "NodeMetaInfo is invalid";
- return 0; // maybe we should return a new QObject?
- }
+ QDeclarativeComponent component(context->engine(), QUrl::fromLocalFile(componentPath));
+ QDeclarativeContext *newContext = new QDeclarativeContext(context);
+ QObject *object = component.beginCreate(newContext);
+ tweakObjects(object);
+ component.completeCreate();
+ newContext->setParent(object);
+
+ return object;
+}
+QObject *createPrimitive(const QString &typeName, int majorNumber, int minorNumber, QDeclarativeContext *context)
+{
QObject *object = 0;
- if (metaInfo.isComponent()) {
- // qml component
- // TODO: This is maybe expensive ...
- QDeclarativeComponent component(context->engine(), QUrl::fromLocalFile(metaInfo.componentString()));
- QDeclarativeContext *newContext = new QDeclarativeContext(context);
- object = component.beginCreate(newContext);
- component.completeCreate();
- newContext->setParent(object);
+ QDeclarativeType *type = QDeclarativeMetaType::qmlType(typeName.toUtf8(), majorNumber, minorNumber);
+ if (type) {
+ object = type->create();
} else {
- // primitive
- QDeclarativeType *type = QDeclarativeMetaType::qmlType(metaInfo.typeName().toAscii(), metaInfo.majorVersion(), metaInfo.minorVersion());
- if (type) {
- object = type->create();
- } else {
- qWarning() << "QuickDesigner: Cannot create an object of type"
- << QString("%1 %2,%3").arg(metaInfo.typeName(), metaInfo.majorVersion(), metaInfo.minorVersion())
- << "- type isn't known to declarative meta type system";
- }
-
- if (object && context)
- QDeclarativeEngine::setContextForObject(object, context);
+ qWarning() << "QuickDesigner: Cannot create an object of type"
+ << QString("%1 %2,%3").arg(typeName).arg(majorNumber).arg(minorNumber)
+ << "- type isn't known to declarative meta type system";
}
- QDeclarativeEngine::setObjectOwnership(object, QDeclarativeEngine::CppOwnership);
-
tweakObjects(object);
+ if (object && context)
+ QDeclarativeEngine::setContextForObject(object, context);
+
return object;
}
-QObject* ObjectNodeInstance::createObject(const NodeMetaInfo &metaInfo, QDeclarativeContext *context)
+QObject* ObjectNodeInstance::createObject(const QString &typeName, int majorNumber, int minorNumber, const QString &componentPath, QDeclarativeContext *context)
{
- QObject *object = createInstance(metaInfo, context);
+ QObject *object = 0;
+ if (componentPath.isEmpty()) {
+ object = createPrimitive(typeName, majorNumber, minorNumber, context);
+ } else {
+ object = createComponent(componentPath, context);
+ }
- if (object == 0)
- throw InvalidNodeInstanceException(__LINE__, __FUNCTION__, __FILE__);
+ QDeclarativeEngine::setObjectOwnership(object, QDeclarativeEngine::CppOwnership);
return object;
}
@@ -853,15 +819,15 @@ QDeclarativeContext *ObjectNodeInstance::context() const
QDeclarativeContext *context = QDeclarativeEngine::contextForObject(object());
if (context)
return context;
- else if (nodeInstanceView())
- return nodeInstanceView()->engine()->rootContext();
+ else if (nodeInstanceServer())
+ return nodeInstanceServer()->engine()->rootContext();
return 0;
}
QDeclarativeEngine *ObjectNodeInstance::engine() const
{
- return nodeInstanceView()->engine();
+ return nodeInstanceServer()->engine();
}
void ObjectNodeInstance::paintUpdate()
@@ -876,21 +842,29 @@ void ObjectNodeInstance::deactivateState()
{
}
-QStringList propertyNameForWritableProperties(QObject *object, const QString &baseName = QString())
+QStringList propertyNameForWritableProperties(QObject *object, const QString &baseName = QString(), QObjectList *inspectedObjects = new QObjectList())
{
QStringList propertyNameList;
+ if (inspectedObjects == 0 || inspectedObjects->contains(object))
+ return propertyNameList;
+
+ inspectedObjects->append(object);
+
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 = QDeclarativeMetaType::toQObject(metaProperty.read(object));
- if (childObject)
- propertyNameList.append(propertyNameForWritableProperties(childObject, baseName + QString::fromUtf8(metaProperty.name()) + '.'));
+ QDeclarativeProperty declarativeProperty(object, QLatin1String(metaProperty.name()));
+ if (declarativeProperty.isValid() && declarativeProperty.isWritable() && declarativeProperty.propertyTypeCategory() == QDeclarativeProperty::Object) {
+ if (declarativeProperty.name() != "parent") {
+ QObject *childObject = QDeclarativeMetaType::toQObject(declarativeProperty.read());
+ if (childObject)
+ propertyNameList.append(propertyNameForWritableProperties(childObject, baseName + QString::fromUtf8(metaProperty.name()) + '.', inspectedObjects));
+ }
} else if (QDeclarativeValueTypeFactory::valueType(metaProperty.userType())) {
QDeclarativeValueType *valueType = QDeclarativeValueTypeFactory::valueType(metaProperty.userType());
valueType->setValue(metaProperty.read(object));
- propertyNameList.append(propertyNameForWritableProperties(valueType, baseName + QString::fromUtf8(metaProperty.name()) + '.'));
+ propertyNameList.append(propertyNameForWritableProperties(valueType, baseName + QString::fromUtf8(metaProperty.name()) + '.', inspectedObjects));
} else if (metaProperty.isReadable() && metaProperty.isWritable()) {
propertyNameList.append(baseName + QString::fromUtf8(metaProperty.name()));
}
@@ -915,13 +889,13 @@ QVariant ObjectNodeInstance::resetValue(const QString &propertyName) const
return m_resetValueHash.value(propertyName);
}
-void ObjectNodeInstance::paint(QPainter * /*painter*/) const
+void ObjectNodeInstance::paint(QPainter * /*painter*/)
{
}
-bool ObjectNodeInstance::isTopLevel() const
+QImage ObjectNodeInstance::renderImage() const
{
- return false;
+ return QImage();
}
QObject *ObjectNodeInstance::parent() const
@@ -932,6 +906,31 @@ QObject *ObjectNodeInstance::parent() const
return object()->parent();
}
+QObject *parentObject(QObject *object)
+{
+ QGraphicsObject *graphicsObject = qobject_cast<QGraphicsObject*>(object);
+ if (graphicsObject)
+ return graphicsObject->parentObject();
+
+ return object->parent();
+}
+
+ObjectNodeInstance::Pointer ObjectNodeInstance::parentInstance() const
+{
+ QObject *parentHolder = parent();
+ if (!nodeInstanceServer())
+ return Pointer();
+
+ while (parentHolder) {
+ if (nodeInstanceServer()->hasInstanceForObject(parentHolder))
+ return nodeInstanceServer()->instanceForObject(parentHolder).internalInstance();
+
+ parentHolder = parentObject(parentHolder);
+ }
+
+ return Pointer();
+}
+
QRectF ObjectNodeInstance::boundingRect() const
{
return QRect();
@@ -952,26 +951,14 @@ int ObjectNodeInstance::penWidth() const
return 0;
}
-static bool metaObjectHasNotPropertyName(NodeInstanceMetaObject *metaObject, const QString &propertyName)
-{
- for (int i = 0; i < metaObject->count(); i++) {
- if (metaObject->name(i) == propertyName)
- return false;
- }
-
- return true;
-}
-
void ObjectNodeInstance::createDynamicProperty(const QString &name, const QString &/*typeName*/)
{
if (m_metaObject == 0) {
- qWarning() << "dynamic properties are not supported for components";
+ qWarning() << "ObjectNodeInstance.createDynamicProperty: No Metaobject.";
return;
}
-
- if (metaObjectHasNotPropertyName(m_metaObject, name))
- m_metaObject->createNewProperty(name);
+ m_metaObject->createNewProperty(name);
}
/**
@@ -985,48 +972,34 @@ void ObjectNodeInstance::refreshBindings(QDeclarativeContext *context)
context->setContextProperty(QString("__dummy_%1").arg(i++), true);
}
-bool ObjectNodeInstance::updateStateVariant(const NodeInstance &/*target*/, const QString &/*propertyName*/, const QVariant &/*value*/)
+bool ObjectNodeInstance::updateStateVariant(const ObjectNodeInstance::Pointer &/*target*/, const QString &/*propertyName*/, const QVariant &/*value*/)
{
return false;
}
-bool ObjectNodeInstance::updateStateBinding(const NodeInstance &/*target*/, const QString &/*propertyName*/, const QString &/*expression*/)
+bool ObjectNodeInstance::updateStateBinding(const ObjectNodeInstance::Pointer &/*target*/, const QString &/*propertyName*/, const QString &/*expression*/)
{
return false;
}
-bool ObjectNodeInstance::resetStateProperty(const NodeInstance &/*target*/, const QString &/*propertyName*/, const QVariant &/*resetValue*/)
+bool ObjectNodeInstance::resetStateProperty(const ObjectNodeInstance::Pointer &/*target*/, const QString &/*propertyName*/, const QVariant &/*resetValue*/)
{
return false;
}
-
-NodeInstance ObjectNodeInstance::nodeInstanceParentForObject(QObject *currentObject) const
+void ObjectNodeInstance::doComponentComplete()
{
- if (!currentObject) //this should not happen! warning?
- return NodeInstance();
- if (nodeInstanceView()->hasInstanceForObject(currentObject))
- return nodeInstanceView()->instanceForObject(currentObject);
-
- //Maybe the object has been reparented inside a component and we
- //do not keep track of the parent?
- //In this case we iterate until we find a parent we keep track of,
- //parent() gets 0
-
- QObject* parentObject;
- QGraphicsObject *graphicsObject = qobject_cast<QGraphicsObject*>(currentObject);
- if (graphicsObject)
- parentObject = graphicsObject->parentItem()->toGraphicsObject();
- else
- parentObject = currentObject->parent();
-
- return nodeInstanceParentForObject(parentObject);
}
-void ObjectNodeInstance::doComponentComplete()
+bool ObjectNodeInstance::isRootNodeInstance() const
{
+ return nodeInstanceServer()->rootNodeInstance().isWrappingThisObject(object());
+}
+bool ObjectNodeInstance::isValid() const
+{
+ return instanceId() >= 0 && object();
}
}
diff --git a/src/plugins/qmldesigner/designercore/instances/objectnodeinstance.h b/src/plugins/qmldesigner/designercore/instances/objectnodeinstance.h
index c3ffe6e671..cb7cb49152 100644
--- a/src/plugins/qmldesigner/designercore/instances/objectnodeinstance.h
+++ b/src/plugins/qmldesigner/designercore/instances/objectnodeinstance.h
@@ -36,12 +36,10 @@
#include <QPainter>
#include <QStyleOptionGraphicsItem>
-#include "modelnode.h"
#include <QSharedPointer>
#include <QScopedPointer>
#include <QWeakPointer>
-#include <propertymetainfo.h>
-#include <nodeinstanceview.h>
+#include "nodeinstanceserver.h"
#include "nodeinstancemetaobject.h"
#include "nodeinstancesignalspy.h"
@@ -56,6 +54,8 @@ QT_END_NAMESPACE
namespace QmlDesigner {
+class NodeInstanceServer;
+
namespace Internal {
@@ -65,22 +65,6 @@ class GraphicsViewNodeInstance;
class GraphicsSceneNodeInstance;
class ProxyWidgetNodeInstance;
class WidgetNodeInstance;
-class QDeclarativeViewNodeInstance;
-
-class ChildrenChangeEventFilter : public QObject
-{
- Q_OBJECT
-public:
- ChildrenChangeEventFilter(QObject *parent);
-
-
-signals:
- void childrenChanged(QObject *object);
-
-protected:
- bool eventFilter(QObject *object, QEvent *event);
-
-};
class ObjectNodeInstance
{
@@ -93,32 +77,28 @@ public:
void destroy();
//void setModelNode(const ModelNode &node);
- static Pointer create(const NodeMetaInfo &metaInfo, QDeclarativeContext *context, QObject *objectToBeWrapped);
+ static Pointer create(QObject *objectToBeWrapped);
+ static QObject* createObject(const QString &typeName, int majorNumber, int minorNumber, const QString &componentPath, QDeclarativeContext *context);
- ModelNode modelNode() const;
- void setModelNode(const ModelNode &node);
+ void setInstanceId(qint32 id);
+ qint32 instanceId() const;
- NodeInstanceView *nodeInstanceView() const;
- void setNodeInstanceView(NodeInstanceView *view);
+ NodeInstanceServer *nodeInstanceServer() const;
+ void setNodeInstanceServer(NodeInstanceServer *server);
virtual void initializePropertyWatcher(const Pointer &objectNodeInstance);
- virtual void paint(QPainter *painter) const;
-
- virtual bool isTopLevel() const;
+ virtual void paint(QPainter *painter);
+ virtual QImage renderImage() const;
virtual QObject *parent() const;
- virtual void reparent(const NodeInstance &oldParentInstance, const QString &oldParentProperty, const NodeInstance &newParentInstance, const QString &newParentProperty);
+ Pointer parentInstance() const;
+
+ virtual void reparent(const ObjectNodeInstance::Pointer &oldParentInstance, const QString &oldParentProperty, const ObjectNodeInstance::Pointer &newParentInstance, const QString &newParentProperty);
void setId(const QString &id);
QString id() const;
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 isQDeclarativeView() const;
virtual bool isGraphicsObject() const;
virtual bool isTransition() const;
virtual bool isPositioner() const;
@@ -138,7 +118,7 @@ public:
virtual int penWidth() const;
virtual bool hasAnchor(const QString &name) const;
- virtual QPair<QString, NodeInstance> anchor(const QString &name) const;
+ virtual QPair<QString, ServerNodeInstance> anchor(const QString &name) const;
virtual bool isAnchoredBySibling() const;
virtual bool isAnchoredByChildren() const;
@@ -154,6 +134,9 @@ public:
virtual void resetProperty(const QString &name);
virtual void refreshProperty(const QString &name);
virtual QString instanceType(const QString &name) const;
+ QStringList propertyNames() const;
+
+ virtual QList<ServerNodeInstance> childItems() const;
void createDynamicProperty(const QString &name, const QString &typeName);
void setDeleteHeldInstance(bool deleteInstance);
@@ -176,30 +159,24 @@ public:
bool isInPositioner() const;
void setInPositioner(bool isInPositioner);
- bool hasBindingForProperty(const QString &name) const;
+ bool hasBindingForProperty(const QString &name, bool *hasChanged = 0) const;
QDeclarativeContext *context() const;
QDeclarativeEngine *engine() const;
- virtual bool updateStateVariant(const NodeInstance &target, const QString &propertyName, const QVariant &value);
- virtual bool updateStateBinding(const NodeInstance &target, const QString &propertyName, const QString &expression);
- virtual bool resetStateProperty(const NodeInstance &target, const QString &propertyName, const QVariant &resetValue);
-
- static void tweakObjects(QObject *object);
+ virtual bool updateStateVariant(const ObjectNodeInstance::Pointer &target, const QString &propertyName, const QVariant &value);
+ virtual bool updateStateBinding(const ObjectNodeInstance::Pointer &target, const QString &propertyName, const QString &expression);
+ virtual bool resetStateProperty(const ObjectNodeInstance::Pointer &target, const QString &propertyName, const QVariant &resetValue);
- NodeInstance nodeInstanceParentForObject(QObject *currentObject) const;
+ bool isValid() const;
+ bool isRootNodeInstance() const;
virtual void doComponentComplete();
-protected:
- static QObject *createInstance(const NodeMetaInfo &metaInfo, QDeclarativeContext *parentContext);
-
- static QObject* createObject(const NodeMetaInfo &metaInfo, QDeclarativeContext *context);
+protected:
void doResetProperty(const QString &propertyName);
- 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 QDeclarativeProperty &metaProperty);
@@ -208,11 +185,13 @@ private:
static void refreshBindings(QDeclarativeContext *context);
QHash<QString, QVariant> m_resetValueHash;
- QHash<QString, NodeInstance> m_modelAbstractPropertyHash;
- ModelNode m_modelNode;
+ QHash<QString, ServerNodeInstance> m_modelAbstractPropertyHash;
+ mutable QHash<QString, bool> m_hasBindingHash;
+ qint32 m_instanceId;
QString m_id;
- QWeakPointer<NodeInstanceView> m_nodeInstanceView;
+ QWeakPointer<NodeInstanceServer> m_nodeInstanceServer;
+ QString m_parentProperty;
bool m_deleteHeldInstance;
QWeakPointer<QObject> m_object;
NodeInstanceMetaObject *m_metaObject;
diff --git a/src/plugins/qmldesigner/designercore/instances/pixmapchangedcommand.cpp b/src/plugins/qmldesigner/designercore/instances/pixmapchangedcommand.cpp
new file mode 100644
index 0000000000..690dc00d9c
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/pixmapchangedcommand.cpp
@@ -0,0 +1,37 @@
+#include "pixmapchangedcommand.h"
+
+#include <QtDebug>
+
+#include <QVarLengthArray>
+
+namespace QmlDesigner {
+
+PixmapChangedCommand::PixmapChangedCommand()
+{
+}
+
+PixmapChangedCommand::PixmapChangedCommand(const QVector<ImageContainer> &imageVector)
+ : m_imageVector(imageVector)
+{
+}
+
+QVector<ImageContainer> PixmapChangedCommand::images() const
+{
+ return m_imageVector;
+}
+
+QDataStream &operator<<(QDataStream &out, const PixmapChangedCommand &command)
+{
+ out << command.images();
+
+ return out;
+}
+
+QDataStream &operator>>(QDataStream &in, PixmapChangedCommand &command)
+{
+ in >> command.m_imageVector;
+
+ return in;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/pixmapchangedcommand.h b/src/plugins/qmldesigner/designercore/instances/pixmapchangedcommand.h
new file mode 100644
index 0000000000..5140de6832
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/pixmapchangedcommand.h
@@ -0,0 +1,29 @@
+#ifndef PIXMAPCHANGEDCOMMAND_H
+#define PIXMAPCHANGEDCOMMAND_H
+
+#include <QMetaType>
+#include "imagecontainer.h"
+
+namespace QmlDesigner {
+
+class PixmapChangedCommand
+{
+ friend QDataStream &operator>>(QDataStream &in, PixmapChangedCommand &command);
+public:
+ PixmapChangedCommand();
+ PixmapChangedCommand(const QVector<ImageContainer> &imageVector);
+
+ QVector<ImageContainer> images() const;
+
+private:
+ QVector<ImageContainer> m_imageVector;
+};
+
+QDataStream &operator<<(QDataStream &out, const PixmapChangedCommand &command);
+QDataStream &operator>>(QDataStream &in, PixmapChangedCommand &command);
+
+} // namespace QmlDesigner
+
+Q_DECLARE_METATYPE(QmlDesigner::PixmapChangedCommand)
+
+#endif // PIXMAPCHANGEDCOMMAND_H
diff --git a/src/plugins/qmldesigner/designercore/instances/positionernodeinstance.cpp b/src/plugins/qmldesigner/designercore/instances/positionernodeinstance.cpp
index ecc8ee3e8f..5d78b025b3 100644
--- a/src/plugins/qmldesigner/designercore/instances/positionernodeinstance.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/positionernodeinstance.cpp
@@ -5,8 +5,8 @@
namespace QmlDesigner {
namespace Internal {
-PositionerNodeInstance::PositionerNodeInstance(QDeclarativeBasePositioner *item, bool hasContent)
- : QmlGraphicsItemNodeInstance(item, hasContent)
+PositionerNodeInstance::PositionerNodeInstance(QDeclarativeBasePositioner *item)
+ : QmlGraphicsItemNodeInstance(item)
{
}
@@ -36,26 +36,19 @@ void PositionerNodeInstance::setPropertyBinding(const QString &name, const QStri
QmlGraphicsItemNodeInstance::setPropertyBinding(name, expression);
}
-PositionerNodeInstance::Pointer PositionerNodeInstance::create(const NodeMetaInfo &metaInfo, QDeclarativeContext *context, QObject *objectToBeWrapped)
-{
- QPair<QGraphicsObject*, bool> objectPair;
-
- if (objectToBeWrapped)
- objectPair = qMakePair(qobject_cast<QGraphicsObject*>(objectToBeWrapped), false);
- else
- objectPair = GraphicsObjectNodeInstance::createGraphicsObject(metaInfo, context);
-
- QDeclarativeBasePositioner *positioner = dynamic_cast<QDeclarativeBasePositioner*>(objectPair.first);
+PositionerNodeInstance::Pointer PositionerNodeInstance::create(QObject *object)
+{
+ QDeclarativeBasePositioner *positioner = qobject_cast<QDeclarativeBasePositioner*>(object);
if (positioner == 0)
throw InvalidNodeInstanceException(__LINE__, __FUNCTION__, __FILE__);
- Pointer instance(new PositionerNodeInstance(positioner, objectPair.second));
+ Pointer instance(new PositionerNodeInstance(positioner));
- static_cast<QDeclarativeParserStatus*>(positioner)->classBegin();
+ instance->setHasContent(!positioner->flags().testFlag(QGraphicsItem::ItemHasNoContents));
+ positioner->setFlag(QGraphicsItem::ItemHasNoContents, false);
- if (objectToBeWrapped)
- instance->setDeleteHeldInstance(false); // the object isn't owned
+ static_cast<QDeclarativeParserStatus*>(positioner)->classBegin();
instance->populateResetValueHash();
diff --git a/src/plugins/qmldesigner/designercore/instances/positionernodeinstance.h b/src/plugins/qmldesigner/designercore/instances/positionernodeinstance.h
index 628b0d1607..5b6d6e2d41 100644
--- a/src/plugins/qmldesigner/designercore/instances/positionernodeinstance.h
+++ b/src/plugins/qmldesigner/designercore/instances/positionernodeinstance.h
@@ -16,7 +16,7 @@ public:
typedef QSharedPointer<PositionerNodeInstance> Pointer;
typedef QWeakPointer<PositionerNodeInstance> WeakPointer;
- static Pointer create(const NodeMetaInfo &metaInfo, QDeclarativeContext *context, QObject *objectToBeWrapped);
+ static Pointer create(QObject *objectToBeWrapped);
void setPropertyVariant(const QString &name, const QVariant &value);
void setPropertyBinding(const QString &name, const QString &expression);
@@ -27,7 +27,7 @@ public:
protected:
- PositionerNodeInstance(QDeclarativeBasePositioner *item, bool hasContent);
+ PositionerNodeInstance(QDeclarativeBasePositioner *item);
};
} // namespace Internal
diff --git a/src/plugins/qmldesigner/designercore/instances/propertyabstractcontainer.cpp b/src/plugins/qmldesigner/designercore/instances/propertyabstractcontainer.cpp
new file mode 100644
index 0000000000..040cf5833c
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/propertyabstractcontainer.cpp
@@ -0,0 +1,55 @@
+#include "propertyabstractcontainer.h"
+
+namespace QmlDesigner {
+
+PropertyAbstractContainer::PropertyAbstractContainer()
+ : m_instanceId(-1)
+{
+}
+
+PropertyAbstractContainer::PropertyAbstractContainer(qint32 instanceId, const QString &name, const QString &dynamicTypeName)
+ : m_instanceId(instanceId),
+ m_name(name),
+ m_dynamicTypeName(dynamicTypeName)
+{
+}
+
+qint32 PropertyAbstractContainer::instanceId() const
+{
+ return m_instanceId;
+}
+
+QString PropertyAbstractContainer::name() const
+{
+ return m_name;
+}
+
+bool PropertyAbstractContainer::isDynamic() const
+{
+ return !m_dynamicTypeName.isEmpty();
+}
+
+QString PropertyAbstractContainer::dynamicTypeName() const
+{
+ return m_dynamicTypeName;
+}
+
+QDataStream &operator<<(QDataStream &out, const PropertyAbstractContainer &container)
+{
+ out << container.instanceId();
+ out << container.name();
+ out << container.dynamicTypeName();
+
+ return out;
+}
+
+QDataStream &operator>>(QDataStream &in, PropertyAbstractContainer &container)
+{
+ in >> container.m_instanceId;
+ in >> container.m_name;
+ in >> container.m_dynamicTypeName;
+
+ return in;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/propertybindingcontainer.cpp b/src/plugins/qmldesigner/designercore/instances/propertybindingcontainer.cpp
new file mode 100644
index 0000000000..966ca22dce
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/propertybindingcontainer.cpp
@@ -0,0 +1,64 @@
+#include "propertybindingcontainer.h"
+
+
+namespace QmlDesigner {
+
+PropertyBindingContainer::PropertyBindingContainer()
+ : m_instanceId(-1)
+{
+}
+
+PropertyBindingContainer::PropertyBindingContainer(qint32 instanceId, const QString &name, const QString &expression, const QString &dynamicTypeName)
+ : m_instanceId(instanceId),
+ m_name(name),
+ m_expression(expression),
+ m_dynamicTypeName(dynamicTypeName)
+{
+}
+
+qint32 PropertyBindingContainer::instanceId() const
+{
+ return m_instanceId;
+}
+
+QString PropertyBindingContainer::name() const
+{
+ return m_name;
+}
+
+QString PropertyBindingContainer::expression() const
+{
+ return m_expression;
+}
+
+bool PropertyBindingContainer::isDynamic() const
+{
+ return !m_dynamicTypeName.isEmpty();
+}
+
+QString PropertyBindingContainer::dynamicTypeName() const
+{
+ return m_dynamicTypeName;
+}
+
+QDataStream &operator<<(QDataStream &out, const PropertyBindingContainer &container)
+{
+ out << container.instanceId();
+ out << container.name();
+ out << container.expression();
+ out << container.dynamicTypeName();
+
+ return out;
+}
+
+QDataStream &operator>>(QDataStream &in, PropertyBindingContainer &container)
+{
+ in >> container.m_instanceId;
+ in >> container.m_name;
+ in >> container.m_expression;
+ in >> container.m_dynamicTypeName;
+
+ return in;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/propertyvaluecontainer.cpp b/src/plugins/qmldesigner/designercore/instances/propertyvaluecontainer.cpp
new file mode 100644
index 0000000000..640e32bfcd
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/propertyvaluecontainer.cpp
@@ -0,0 +1,63 @@
+#include "propertyvaluecontainer.h"
+
+namespace QmlDesigner {
+
+PropertyValueContainer::PropertyValueContainer()
+ : m_instanceId(-1)
+{
+}
+
+PropertyValueContainer::PropertyValueContainer(qint32 instanceId, const QString &name, const QVariant &value, const QString &dynamicTypeName)
+ : m_instanceId(instanceId),
+ m_name(name),
+ m_value(value),
+ m_dynamicTypeName(dynamicTypeName)
+{
+}
+
+qint32 PropertyValueContainer::instanceId() const
+{
+ return m_instanceId;
+}
+
+QString PropertyValueContainer::name() const
+{
+ return m_name;
+}
+
+QVariant PropertyValueContainer::value() const
+{
+ return m_value;
+}
+
+bool PropertyValueContainer::isDynamic() const
+{
+ return !m_dynamicTypeName.isEmpty();
+}
+
+QString PropertyValueContainer::dynamicTypeName() const
+{
+ return m_dynamicTypeName;
+}
+
+QDataStream &operator<<(QDataStream &out, const PropertyValueContainer &container)
+{
+ out << container.instanceId();
+ out << container.name();
+ out << container.value();
+ out << container.dynamicTypeName();
+
+ return out;
+}
+
+QDataStream &operator>>(QDataStream &in, PropertyValueContainer &container)
+{
+ in >> container.m_instanceId;
+ in >> container.m_name;
+ in >> container.m_value;
+ in >> container.m_dynamicTypeName;
+
+ return in;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/proxywidgetnodeinstance.cpp b/src/plugins/qmldesigner/designercore/instances/proxywidgetnodeinstance.cpp
deleted file mode 100644
index 7bb1ff56ae..0000000000
--- a/src/plugins/qmldesigner/designercore/instances/proxywidgetnodeinstance.cpp
+++ /dev/null
@@ -1,85 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#include "proxywidgetnodeinstance.h"
-
-#include <QGraphicsProxyWidget>
-#include <private/qdeclarativemetatype_p.h>
-
-namespace QmlDesigner {
-namespace Internal {
-
-
-ProxyWidgetNodeInstance::ProxyWidgetNodeInstance(QGraphicsProxyWidget *widget)
- : GraphicsWidgetNodeInstance(widget)
-{
-}
-
-
-ProxyWidgetNodeInstance::Pointer ProxyWidgetNodeInstance::create(const QString &typeName)
-{
- QObject *object = QDeclarativeMetaType::qmlType(typeName.toLatin1(), 4, 7)->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/designercore/instances/proxywidgetnodeinstance.h b/src/plugins/qmldesigner/designercore/instances/proxywidgetnodeinstance.h
deleted file mode 100644
index 193516047a..0000000000
--- a/src/plugins/qmldesigner/designercore/instances/proxywidgetnodeinstance.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#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/designercore/instances/qmlgraphicsitemnodeinstance.cpp b/src/plugins/qmldesigner/designercore/instances/qmlgraphicsitemnodeinstance.cpp
index df0de8e2b1..f832f16628 100644
--- a/src/plugins/qmldesigner/designercore/instances/qmlgraphicsitemnodeinstance.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/qmlgraphicsitemnodeinstance.cpp
@@ -32,12 +32,8 @@
**************************************************************************/
#include "qmlgraphicsitemnodeinstance.h"
-#include "qmlviewnodeinstance.h"
-#include "graphicsscenenodeinstance.h"
-
#include <invalidnodeinstanceexception.h>
-#include <propertymetainfo.h>
#include "bindingproperty.h"
#include "variantproperty.h"
@@ -59,11 +55,15 @@
namespace QmlDesigner {
namespace Internal {
-QmlGraphicsItemNodeInstance::QmlGraphicsItemNodeInstance(QDeclarativeItem *item, bool hasContent)
- : GraphicsObjectNodeInstance(item, hasContent),
+QmlGraphicsItemNodeInstance::QmlGraphicsItemNodeInstance(QDeclarativeItem *item)
+ : GraphicsObjectNodeInstance(item),
m_hasHeight(false),
m_hasWidth(false),
- m_isResizable(true)
+ m_isResizable(true),
+ m_x(0.0),
+ m_y(0.0),
+ m_width(0.0),
+ m_height(0.0)
{
}
@@ -71,30 +71,23 @@ QmlGraphicsItemNodeInstance::~QmlGraphicsItemNodeInstance()
{
}
-QmlGraphicsItemNodeInstance::Pointer QmlGraphicsItemNodeInstance::create(const NodeMetaInfo &metaInfo, QDeclarativeContext *context, QObject *objectToBeWrapped)
+QmlGraphicsItemNodeInstance::Pointer QmlGraphicsItemNodeInstance::create(QObject *object)
{
- QPair<QGraphicsObject*, bool> objectPair;
-
- if (objectToBeWrapped)
- objectPair = qMakePair(qobject_cast<QGraphicsObject*>(objectToBeWrapped), false);
- else
- objectPair = GraphicsObjectNodeInstance::createGraphicsObject(metaInfo, context);
-
- QDeclarativeItem *qmlGraphicsItem = dynamic_cast<QDeclarativeItem*>(objectPair.first);
+ QDeclarativeItem *qmlGraphicsItem = dynamic_cast<QDeclarativeItem*>(object);
if (qmlGraphicsItem == 0)
throw InvalidNodeInstanceException(__LINE__, __FUNCTION__, __FILE__);
- Pointer instance(new QmlGraphicsItemNodeInstance(qmlGraphicsItem, objectPair.second));
+ Pointer instance(new QmlGraphicsItemNodeInstance(qmlGraphicsItem));
+
+ instance->setHasContent(!qmlGraphicsItem->flags().testFlag(QGraphicsItem::ItemHasNoContents));
+ qmlGraphicsItem->setFlag(QGraphicsItem::ItemHasNoContents, false);
if (qmlGraphicsItem->inherits("QDeclarativeText"))
instance->setResizable(false);
static_cast<QDeclarativeParserStatus*>(qmlGraphicsItem)->classBegin();
- if (objectToBeWrapped)
- instance->setDeleteHeldInstance(false); // the object isn't owned
-
instance->populateResetValueHash();
return instance;
@@ -107,12 +100,12 @@ bool QmlGraphicsItemNodeInstance::isQmlGraphicsItem() const
QSizeF QmlGraphicsItemNodeInstance::size() const
{
- if (modelNode().isValid()) {
+ if (isValid()) {
double implicitWidth = qmlGraphicsItem()->implicitWidth();
if (!m_hasWidth
&& implicitWidth // WORKAROUND
&& implicitWidth != qmlGraphicsItem()->width()
- && !modelNode().hasBindingProperty("width")) {
+ && !hasBindingForProperty("width")) {
qmlGraphicsItem()->blockSignals(true);
qmlGraphicsItem()->setWidth(implicitWidth);
qmlGraphicsItem()->blockSignals(false);
@@ -122,7 +115,7 @@ QSizeF QmlGraphicsItemNodeInstance::size() const
if (!m_hasHeight
&& implicitWidth // WORKAROUND
&& implicitHeight != qmlGraphicsItem()->height()
- && !modelNode().hasBindingProperty("height")) {
+ && !hasBindingForProperty("height")) {
qmlGraphicsItem()->blockSignals(true);
qmlGraphicsItem()->setHeight(implicitHeight);
qmlGraphicsItem()->blockSignals(false);
@@ -130,7 +123,7 @@ QSizeF QmlGraphicsItemNodeInstance::size() const
}
- if (modelNode().isRootNode()) {
+ if (isRootNodeInstance()) {
if (!m_hasWidth) {
qmlGraphicsItem()->blockSignals(true);
if (qmlGraphicsItem()->width() < 10.)
@@ -151,12 +144,12 @@ QSizeF QmlGraphicsItemNodeInstance::size() const
QRectF QmlGraphicsItemNodeInstance::boundingRect() const
{
- if (modelNode().isValid()) {
+ if (isValid()) {
double implicitWidth = qmlGraphicsItem()->implicitWidth();
if (!m_hasWidth
&& implicitWidth // WORKAROUND
&& implicitWidth != qmlGraphicsItem()->width()
- && !modelNode().hasBindingProperty("width")) {
+ && !hasBindingForProperty("width")) {
qmlGraphicsItem()->blockSignals(true);
qmlGraphicsItem()->setWidth(implicitWidth);
qmlGraphicsItem()->blockSignals(false);
@@ -164,9 +157,9 @@ QRectF QmlGraphicsItemNodeInstance::boundingRect() const
double implicitHeight = qmlGraphicsItem()->implicitHeight();
if (!m_hasHeight
- && implicitHeight // WORKAROUND
+ && implicitWidth // WORKAROUND
&& implicitHeight != qmlGraphicsItem()->height()
- && !modelNode().hasBindingProperty("height")) {
+ && !hasBindingForProperty("height")) {
qmlGraphicsItem()->blockSignals(true);
qmlGraphicsItem()->setHeight(implicitHeight);
qmlGraphicsItem()->blockSignals(false);
@@ -174,7 +167,7 @@ QRectF QmlGraphicsItemNodeInstance::boundingRect() const
}
- if (modelNode().isRootNode()) {
+ if (isRootNodeInstance()) {
if (!m_hasWidth) {
qmlGraphicsItem()->blockSignals(true);
if (qmlGraphicsItem()->width() < 10.)
@@ -196,29 +189,13 @@ QRectF QmlGraphicsItemNodeInstance::boundingRect() const
return QRectF();
}
-//QVariant anchorLineFor(QDeclarativeItem *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 == "state")
return; // states are only set by us
if (name == "height") {
+ m_height = value.toDouble();
if (value.isValid())
m_hasHeight = true;
else
@@ -226,12 +203,19 @@ void QmlGraphicsItemNodeInstance::setPropertyVariant(const QString &name, const
}
if (name == "width") {
+ m_width = value.toDouble();
if (value.isValid())
m_hasWidth = true;
else
m_hasWidth = false;
}
+ if (name == "x")
+ m_x = value.toDouble();
+
+ if (name == "y")
+ m_y = value.toDouble();
+
GraphicsObjectNodeInstance::setPropertyVariant(name, value);
refresh();
@@ -247,7 +231,7 @@ void QmlGraphicsItemNodeInstance::setPropertyBinding(const QString &name, const
QVariant QmlGraphicsItemNodeInstance::property(const QString &name) const
{
- if (name == "width" && modelNode().isValid() && !modelNode().hasBindingProperty("width")) {
+ if (name == "width" && !hasBindingForProperty("width")) {
double implicitWidth = qmlGraphicsItem()->implicitWidth();
if (!m_hasWidth
&& implicitWidth // WORKAROUND
@@ -258,7 +242,7 @@ QVariant QmlGraphicsItemNodeInstance::property(const QString &name) const
}
}
- if (name == "height" && modelNode().isValid() && !modelNode().hasBindingProperty("height")) {
+ if (name == "height" && !hasBindingForProperty("height")) {
double implicitHeight = qmlGraphicsItem()->implicitHeight();
if (!m_hasHeight
&& implicitHeight // WORKAROUND
@@ -274,36 +258,22 @@ QVariant QmlGraphicsItemNodeInstance::property(const QString &name) const
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());
+ setPropertyVariant("x", m_x);
+ if (m_width > 0.0) {
+ setPropertyVariant("width", m_width);
+ } 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());
+ setPropertyVariant("y", m_y);
+ if (m_height > 0.0) {
+ setPropertyVariant("height", m_height);
+ } else {
+ setPropertyVariant("height", qmlGraphicsItem()->implicitWidth());
+ }
}
static void repositioning(QDeclarativeItem *item)
@@ -332,6 +302,8 @@ void QmlGraphicsItemNodeInstance::doComponentComplete()
static_cast<QDeclarativeParserStatus*>(qmlGraphicsItem())->componentComplete();
QGraphicsItemPrivate::get(qmlGraphicsItem())->sendParentChangeNotification = 1;
}
+
+ graphicsObject()->update();
}
bool QmlGraphicsItemNodeInstance::isResizable() const
@@ -355,14 +327,23 @@ int QmlGraphicsItemNodeInstance::penWidth() const
void QmlGraphicsItemNodeInstance::resetProperty(const QString &name)
{
- if (name == "height")
+ if (name == "height") {
m_hasHeight = false;
+ m_height = 0.0;
+ }
- if (name == "width")
+ if (name == "width") {
m_hasWidth = false;
+ m_width = 0.0;
+ }
+
+ if (name == "x")
+ m_x = 0.0;
+
+ if (name == "y")
+ m_y = 0.0;
- GraphicsObjectNodeInstance::resetProperty(name);
if (name == "anchors.fill") {
anchors()->resetFill();
resetHorizontal();
@@ -393,139 +374,35 @@ void QmlGraphicsItemNodeInstance::resetProperty(const QString &name)
anchors()->resetBaseline();
resetVertical();
}
+
+ GraphicsObjectNodeInstance::resetProperty(name);
}
-void QmlGraphicsItemNodeInstance::reparent(const NodeInstance &oldParentInstance, const QString &oldParentProperty, const NodeInstance &newParentInstance, const QString &newParentProperty)
+void QmlGraphicsItemNodeInstance::reparent(const ObjectNodeInstance::Pointer &oldParentInstance, const QString &oldParentProperty, const ObjectNodeInstance::Pointer &newParentInstance, const QString &newParentProperty)
{
- if (oldParentInstance.isValid() && oldParentInstance.isPositioner()) {
+ if (oldParentInstance && oldParentInstance->isPositioner()) {
setInPositioner(false);
setMovable(true);
}
GraphicsObjectNodeInstance::reparent(oldParentInstance, oldParentProperty, newParentInstance, newParentProperty);
- if (newParentInstance.isValid() && newParentInstance.isPositioner()) {
+ if (newParentInstance && newParentInstance->isPositioner()) {
setInPositioner(true);
setMovable(false);
}
+ if (oldParentInstance && oldParentInstance->isPositioner() && !(newParentInstance && newParentInstance->isPositioner())) {
+ if (!hasBindingForProperty("x"))
+ setPropertyVariant("x", m_x);
+
+ if (!hasBindingForProperty("y"))
+ setPropertyVariant("y", m_y);
+ }
+
refresh();
}
-//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());
-// anchors()->setProperty("top", anchorLineFor(qmlGraphicsItemInstance->qmlGraphicsItem(), anchorLine));
-// }
-// } else {
-// if (anchors()->usedAnchors().testFlag(QDeclarativeAnchors::HasTopAnchor)) {
-// 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());
-// anchors()->setProperty("left", anchorLineFor(qmlGraphicsItemInstance->qmlGraphicsItem(), anchorLine));
-// }
-// } else {
-// if (anchors()->usedAnchors().testFlag(QDeclarativeAnchors::HasLeftAnchor)) {
-// 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());
-// anchors()->setProperty("right", anchorLineFor(qmlGraphicsItemInstance->qmlGraphicsItem(), anchorLine));
-// }
-// } else {
-// if (anchors()->usedAnchors().testFlag(QDeclarativeAnchors::HasRightAnchor)) {
-// 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());
-// anchors()->setProperty("bottom", anchorLineFor(qmlGraphicsItemInstance->qmlGraphicsItem(), anchorLine));
-// }
-// } else {
-// if (anchors()->usedAnchors().testFlag(QDeclarativeAnchors::HasBottomAnchor)) {
-// 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());
-// anchors()->setProperty("horizontalCenter", anchorLineFor(qmlGraphicsItemInstance->qmlGraphicsItem(), anchorLine));
-// }
-// } else {
-// if (anchors()->usedAnchors().testFlag(QDeclarativeAnchors::HasHCenterAnchor)) {
-// 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());
-// anchors()->setProperty("verticalCenter",anchorLineFor(qmlGraphicsItemInstance->qmlGraphicsItem(), anchorLine));
-// }
-// } else {
-// if (anchors()->usedAnchors().testFlag(QDeclarativeAnchors::HasVCenterAnchor)) {
-// anchors()->resetVerticalCenter();
-// setPropertyValue("y", modelNode().property("y").value());
-// setPropertyValue("height", modelNode().property("height").value());
-// }
-// }
-//
-//
-// anchors()->setTopMargin(anchors.margin(AnchorLine::Top));
-// anchors()->setLeftMargin(anchors.margin(AnchorLine::Left));
-// anchors()->setBottomMargin(anchors.margin(AnchorLine::Bottom));
-// anchors()->setRightMargin(anchors.margin(AnchorLine::Right));
-// anchors()->setHorizontalCenterOffset(anchors.margin(AnchorLine::HorizontalCenter));
-// anchors()->setVerticalCenterOffset(anchors.margin(AnchorLine::VerticalCenter));
-//}
-
QDeclarativeAnchors::Anchor anchorLineFlagForName(const QString &name)
{
if (name == "anchors.top")
@@ -584,7 +461,7 @@ bool isValidAnchorName(const QString &name)
return anchorNameList.contains(name);
}
-QPair<QString, NodeInstance> QmlGraphicsItemNodeInstance::anchor(const QString &name) const
+QPair<QString, ServerNodeInstance> QmlGraphicsItemNodeInstance::anchor(const QString &name) const
{
if (!isValidAnchorName(name) || !hasAnchor(name))
return GraphicsObjectNodeInstance::anchor(name);
@@ -609,8 +486,8 @@ QPair<QString, NodeInstance> QmlGraphicsItemNodeInstance::anchor(const QString &
}
- if (targetObject && nodeInstanceView()->hasInstanceForObject(targetObject)) {
- return qMakePair(targetName, nodeInstanceView()->instanceForObject(targetObject));
+ if (targetObject && nodeInstanceServer()->hasInstanceForObject(targetObject)) {
+ return qMakePair(targetName, nodeInstanceServer()->instanceForObject(targetObject));
} else {
return GraphicsObjectNodeInstance::anchor(name);
}
diff --git a/src/plugins/qmldesigner/designercore/instances/qmlgraphicsitemnodeinstance.h b/src/plugins/qmldesigner/designercore/instances/qmlgraphicsitemnodeinstance.h
index 9c90754ee1..d220fc8498 100644
--- a/src/plugins/qmldesigner/designercore/instances/qmlgraphicsitemnodeinstance.h
+++ b/src/plugins/qmldesigner/designercore/instances/qmlgraphicsitemnodeinstance.h
@@ -50,7 +50,7 @@ public:
~QmlGraphicsItemNodeInstance();
- static Pointer create(const NodeMetaInfo &metaInfo, QDeclarativeContext *context, QObject *objectToBeWrapped);
+ static Pointer create(QObject *objectToBeWrapped);
bool isQmlGraphicsItem() const;
@@ -64,12 +64,12 @@ public:
QVariant property(const QString &name) const;
void resetProperty(const QString &name);
- void reparent(const NodeInstance &oldParentInstance, const QString &oldParentProperty, const NodeInstance &newParentInstance, const QString &newParentProperty);
+ void reparent(const ObjectNodeInstance::Pointer &oldParentInstance, const QString &oldParentProperty, const ObjectNodeInstance::Pointer &newParentInstance, const QString &newParentProperty);
int penWidth() const;
bool hasAnchor(const QString &name) const;
- QPair<QString, NodeInstance> anchor(const QString &name) const;
+ QPair<QString, ServerNodeInstance> anchor(const QString &name) const;
bool isAnchoredBySibling() const;
bool isAnchoredByChildren() const;
void doComponentComplete();
@@ -78,7 +78,7 @@ public:
void setResizable(bool resizeable);
protected:
- QmlGraphicsItemNodeInstance(QDeclarativeItem *item, bool hasContent);
+ QmlGraphicsItemNodeInstance(QDeclarativeItem *item);
QDeclarativeItem *qmlGraphicsItem() const;
QDeclarativeAnchors *anchors() const;
void resetHorizontal();
@@ -89,7 +89,10 @@ private: //variables
bool m_hasHeight;
bool m_hasWidth;
bool m_isResizable;
-
+ double m_x;
+ double m_y;
+ double m_width;
+ double m_height;
};
}
diff --git a/src/plugins/qmldesigner/designercore/instances/qmlpropertychangesnodeinstance.cpp b/src/plugins/qmldesigner/designercore/instances/qmlpropertychangesnodeinstance.cpp
index 76d3bd4718..be6b992e6f 100644
--- a/src/plugins/qmldesigner/designercore/instances/qmlpropertychangesnodeinstance.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/qmlpropertychangesnodeinstance.cpp
@@ -40,6 +40,8 @@
#include <metainfo.h>
#include <QMutableListIterator>
+#include "invalidnodeinstanceexception.h"
+
#include <private/qdeclarativestate_p_p.h>
#include <private/qdeclarativepropertychanges_p.h>
#include <private/qdeclarativeproperty_p.h>
@@ -180,16 +182,17 @@ QmlPropertyChangesNodeInstance::QmlPropertyChangesNodeInstance(QDeclarativePrope
{
}
-QmlPropertyChangesNodeInstance::Pointer
- QmlPropertyChangesNodeInstance::create(const NodeMetaInfo & /*metaInfo*/,
- QDeclarativeContext *context,
- QObject *objectToBeWrapped)
+QmlPropertyChangesNodeInstance::Pointer QmlPropertyChangesNodeInstance::create(QObject *object)
{
- Q_ASSERT(!objectToBeWrapped);
+ QDeclarativePropertyChanges *propertyChange = qobject_cast<QDeclarativePropertyChanges*>(object);
+
+ if (propertyChange == 0)
+ throw InvalidNodeInstanceException(__LINE__, __FUNCTION__, __FILE__);
+
+ Pointer instance(new QmlPropertyChangesNodeInstance(propertyChange));
+
+ instance->populateResetValueHash();
- QDeclarativePropertyChanges *object = new QDeclarativePropertyChanges;
- QDeclarativeEngine::setContextForObject(object, context);
- Pointer instance(new QmlPropertyChangesNodeInstance(object));
return instance;
}
@@ -202,8 +205,8 @@ void QmlPropertyChangesNodeInstance::setPropertyVariant(const QString &name, con
} else {
changesObject()->changeValue(name.toLatin1(), value);
QObject *targetObject = changesObject()->object();
- if (targetObject && nodeInstanceView()->activeStateInstance().isWrappingThisObject(changesObject()->state())) {
- NodeInstance targetInstance = nodeInstanceView()->instanceForObject(targetObject);
+ if (targetObject && nodeInstanceServer()->activeStateInstance().isWrappingThisObject(changesObject()->state())) {
+ ServerNodeInstance targetInstance = nodeInstanceServer()->instanceForObject(targetObject);
targetInstance.setPropertyVariant(name, value);
}
}
@@ -231,11 +234,11 @@ void QmlPropertyChangesNodeInstance::resetProperty(const QString &name)
}
-void QmlPropertyChangesNodeInstance::reparent(const NodeInstance &oldParentInstance, const QString &oldParentProperty, const NodeInstance &newParentInstance, const QString &newParentProperty)
+void QmlPropertyChangesNodeInstance::reparent(const ServerNodeInstance &oldParentInstance, const QString &oldParentProperty, const ServerNodeInstance &newParentInstance, const QString &newParentProperty)
{
changesObject()->detachFromState();
- ObjectNodeInstance::reparent(oldParentInstance, oldParentProperty, newParentInstance, newParentProperty);
+ ObjectNodeInstance::reparent(oldParentInstance.internalInstance(), oldParentProperty, newParentInstance.internalInstance(), newParentProperty);
changesObject()->attachToState();
}
diff --git a/src/plugins/qmldesigner/designercore/instances/qmlpropertychangesnodeinstance.h b/src/plugins/qmldesigner/designercore/instances/qmlpropertychangesnodeinstance.h
index 6f8228a520..f1900e1dc3 100644
--- a/src/plugins/qmldesigner/designercore/instances/qmlpropertychangesnodeinstance.h
+++ b/src/plugins/qmldesigner/designercore/instances/qmlpropertychangesnodeinstance.h
@@ -128,14 +128,14 @@ public:
typedef QSharedPointer<QmlPropertyChangesNodeInstance> Pointer;
typedef QWeakPointer<QmlPropertyChangesNodeInstance> WeakPointer;
- static Pointer create(const NodeMetaInfo &metaInfo, QDeclarativeContext *context, QObject *objectToBeWrapped);
+ static Pointer create(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 reparent(const NodeInstance &oldParentInstance, const QString &oldParentProperty, const NodeInstance &newParentInstance, const QString &newParentProperty);
+ void reparent(const ServerNodeInstance &oldParentInstance, const QString &oldParentProperty, const ServerNodeInstance &newParentInstance, const QString &newParentProperty);
protected:
QmlPropertyChangesNodeInstance(QDeclarativePropertyChanges *object);
diff --git a/src/plugins/qmldesigner/designercore/instances/qmlstatenodeinstance.cpp b/src/plugins/qmldesigner/designercore/instances/qmlstatenodeinstance.cpp
index b6dcc6b5e2..c560e5f28e 100644
--- a/src/plugins/qmldesigner/designercore/instances/qmlstatenodeinstance.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/qmlstatenodeinstance.cpp
@@ -39,6 +39,8 @@
#include "qmlpropertychangesnodeinstance.h"
#include <private/qdeclarativestateoperations_p.h>
+#include <invalidnodeinstanceexception.h>
+
namespace QmlDesigner {
namespace Internal {
@@ -54,14 +56,12 @@ QmlStateNodeInstance::QmlStateNodeInstance(QDeclarativeState *object) :
}
QmlStateNodeInstance::Pointer
- QmlStateNodeInstance::create(const NodeMetaInfo &metaInfo,
- QDeclarativeContext *context,
- QObject *objectToBeWrapped)
+ QmlStateNodeInstance::create(QObject *object)
{
- Q_ASSERT(!objectToBeWrapped);
- QObject *object = createObject(metaInfo, context);
QDeclarativeState *stateObject = qobject_cast<QDeclarativeState*>(object);
- Q_ASSERT(stateObject);
+
+ if (stateObject == 0)
+ throw InvalidNodeInstanceException(__LINE__, __FUNCTION__, __FILE__);
Pointer instance(new QmlStateNodeInstance(stateObject));
@@ -74,7 +74,7 @@ void QmlStateNodeInstance::activateState()
{
if (stateGroup()) {
if (!isStateActive()) {
- nodeInstanceView()->setStateInstance(nodeInstanceView()->instanceForNode(modelNode()));
+ nodeInstanceServer()->setStateInstance(nodeInstanceServer()->instanceForObject(object()));
stateGroup()->setState(property("name").toString());
}
}
@@ -84,7 +84,7 @@ void QmlStateNodeInstance::deactivateState()
{
if (stateGroup()) {
if (isStateActive()) {
- nodeInstanceView()->clearStateInstance();
+ nodeInstanceServer()->clearStateInstance();
stateGroup()->setState(QString());
}
}
@@ -104,14 +104,19 @@ QDeclarativeStateGroup *QmlStateNodeInstance::stateGroup() const
bool QmlStateNodeInstance::isStateActive() const
{
+ qDebug() << stateObject();
+ qDebug() << stateGroup();
+ if (stateGroup())
+ qDebug() << "state name" << stateGroup()->state() << property("name");
return stateObject() && stateGroup() && stateGroup()->state() == property("name");
}
void QmlStateNodeInstance::setPropertyVariant(const QString &name, const QVariant &value)
{
- bool hasParent = modelNode().hasParentProperty();
- bool isStateOfTheRootModelNode = !hasParent || (hasParent && modelNode().parentProperty().parentModelNode().isRootNode());
- if (name == "when" && isStateOfTheRootModelNode)
+ qDebug() << __FUNCTION__ << stateObject() << name << value;
+ bool hasParent = parent();
+ bool isStateOfTheRootModelNode = parentInstance() && parentInstance()->isRootNodeInstance();
+ if (name == "when" && (!hasParent || isStateOfTheRootModelNode))
return;
ObjectNodeInstance::setPropertyVariant(name, value);
@@ -119,27 +124,27 @@ void QmlStateNodeInstance::setPropertyVariant(const QString &name, const QVarian
void QmlStateNodeInstance::setPropertyBinding(const QString &name, const QString &expression)
{
- bool hasParent = modelNode().hasParentProperty();
- bool isStateOfTheRootModelNode = !hasParent || (hasParent && modelNode().parentProperty().parentModelNode().isRootNode());
- if (name == "when" && isStateOfTheRootModelNode)
+ bool hasParent = parent();
+ bool isStateOfTheRootModelNode = parentInstance() && parentInstance()->isRootNodeInstance();
+ if (name == "when" && (!hasParent || isStateOfTheRootModelNode))
return;
ObjectNodeInstance::setPropertyBinding(name, expression);
}
-bool QmlStateNodeInstance::updateStateVariant(const NodeInstance &target, const QString &propertyName, const QVariant &value)
+bool QmlStateNodeInstance::updateStateVariant(const ObjectNodeInstance::Pointer &target, const QString &propertyName, const QVariant &value)
{
- return stateObject()->changeValueInRevertList(target.internalObject(), propertyName.toLatin1(), value);
+ return stateObject()->changeValueInRevertList(target->object(), propertyName.toLatin1(), value);
}
-bool QmlStateNodeInstance::updateStateBinding(const NodeInstance &target, const QString &propertyName, const QString &expression)
+bool QmlStateNodeInstance::updateStateBinding(const ObjectNodeInstance::Pointer &target, const QString &propertyName, const QString &expression)
{
- return stateObject()->changeValueInRevertList(target.internalObject(), propertyName.toLatin1(), expression);
+ return stateObject()->changeValueInRevertList(target->object(), propertyName.toLatin1(), expression);
}
-bool QmlStateNodeInstance::resetStateProperty(const NodeInstance &target, const QString &propertyName, const QVariant & /* resetValue */)
+bool QmlStateNodeInstance::resetStateProperty(const ObjectNodeInstance::Pointer &target, const QString &propertyName, const QVariant & /* resetValue */)
{
- return stateObject()->removeEntryFromRevertList(target.internalObject(), propertyName.toLatin1());
+ return stateObject()->removeEntryFromRevertList(target->object(), propertyName.toLatin1());
}
} // namespace Internal
diff --git a/src/plugins/qmldesigner/designercore/instances/qmlstatenodeinstance.h b/src/plugins/qmldesigner/designercore/instances/qmlstatenodeinstance.h
index 2a76ee3772..71251c6110 100644
--- a/src/plugins/qmldesigner/designercore/instances/qmlstatenodeinstance.h
+++ b/src/plugins/qmldesigner/designercore/instances/qmlstatenodeinstance.h
@@ -51,7 +51,7 @@ public:
typedef QSharedPointer<QmlStateNodeInstance> Pointer;
typedef QWeakPointer<QmlStateNodeInstance> WeakPointer;
- static Pointer create(const NodeMetaInfo &metaInfo, QDeclarativeContext *context, QObject *objectToBeWrapped);
+ static Pointer create(QObject *objectToBeWrapped);
void setPropertyVariant(const QString &name, const QVariant &value);
void setPropertyBinding(const QString &name, const QString &expression);
@@ -59,9 +59,9 @@ public:
void activateState();
void deactivateState();
- bool updateStateVariant(const NodeInstance &target, const QString &propertyName, const QVariant &value);
- bool updateStateBinding(const NodeInstance &target, const QString &propertyName, const QString &expression);
- bool resetStateProperty(const NodeInstance &target, const QString &propertyName, const QVariant &resetValue);
+ bool updateStateVariant(const ObjectNodeInstance::Pointer &target, const QString &propertyName, const QVariant &value);
+ bool updateStateBinding(const ObjectNodeInstance::Pointer &target, const QString &propertyName, const QString &expression);
+ bool resetStateProperty(const ObjectNodeInstance::Pointer &target, const QString &propertyName, const QVariant &resetValue);
protected:
diff --git a/src/plugins/qmldesigner/designercore/instances/qmltransitionnodeinstance.cpp b/src/plugins/qmldesigner/designercore/instances/qmltransitionnodeinstance.cpp
index 4b05430f05..80d807ad80 100644
--- a/src/plugins/qmldesigner/designercore/instances/qmltransitionnodeinstance.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/qmltransitionnodeinstance.cpp
@@ -44,23 +44,14 @@ QmlTransitionNodeInstance::QmlTransitionNodeInstance(QDeclarativeTransition *tra
{
}
-QmlTransitionNodeInstance::Pointer QmlTransitionNodeInstance::create(const NodeMetaInfo &nodeMetaInfo, QDeclarativeContext *context, QObject *objectToBeWrapped)
+QmlTransitionNodeInstance::Pointer QmlTransitionNodeInstance::create(QObject *object)
{
- QObject *object = 0;
- if (objectToBeWrapped)
- object = objectToBeWrapped;
- else
- object = createObject(nodeMetaInfo, context);
-
QDeclarativeTransition *transition = qobject_cast<QDeclarativeTransition*>(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");
diff --git a/src/plugins/qmldesigner/designercore/instances/qmltransitionnodeinstance.h b/src/plugins/qmldesigner/designercore/instances/qmltransitionnodeinstance.h
index 64defca1d0..1a3c17ea01 100644
--- a/src/plugins/qmldesigner/designercore/instances/qmltransitionnodeinstance.h
+++ b/src/plugins/qmldesigner/designercore/instances/qmltransitionnodeinstance.h
@@ -49,7 +49,7 @@ public:
typedef QSharedPointer<QmlTransitionNodeInstance> Pointer;
typedef QWeakPointer<QmlTransitionNodeInstance> WeakPointer;
- static Pointer create(const NodeMetaInfo &metaInfo, QDeclarativeContext *context, QObject *objectToBeWrapped);
+ static Pointer create(QObject *objectToBeWrapped);
void setPropertyVariant(const QString &name, const QVariant &value);
diff --git a/src/plugins/qmldesigner/designercore/instances/qmlviewnodeinstance.cpp b/src/plugins/qmldesigner/designercore/instances/qmlviewnodeinstance.cpp
deleted file mode 100644
index d169425175..0000000000
--- a/src/plugins/qmldesigner/designercore/instances/qmlviewnodeinstance.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#include "qmlviewnodeinstance.h"
-
-#include <QDeclarativeView>
-#include <QDeclarativeItem>
-
-#include <invalidnodeinstanceexception.h>
-
-namespace QmlDesigner {
-namespace Internal {
-
-QDeclarativeViewNodeInstance::QDeclarativeViewNodeInstance(QDeclarativeView *view)
- : GraphicsViewNodeInstance(view)
-{
-}
-
-
-QDeclarativeViewNodeInstance::Pointer QDeclarativeViewNodeInstance::create(const NodeMetaInfo &nodeMetaInfo, QDeclarativeContext *context, QObject *objectToBeWrapped)
-{
- QObject *object = 0;
- if (objectToBeWrapped)
- object = objectToBeWrapped;
- else
- createObject(nodeMetaInfo, context);
-
- QDeclarativeView* view = qobject_cast<QDeclarativeView*>(object);
- if (view == 0)
- throw InvalidNodeInstanceException(__LINE__, __FUNCTION__, __FILE__);
-
- Pointer instance(new QDeclarativeViewNodeInstance(view));
-
- if (objectToBeWrapped)
- instance->setDeleteHeldInstance(false); // the object isn't owned
-
- instance->populateResetValueHash();
-
- return instance;
-}
-
-QDeclarativeView* QDeclarativeViewNodeInstance::view() const
-{
- QDeclarativeView* view = qobject_cast<QDeclarativeView*>(widget());
- Q_ASSERT(view);
- return view;
-}
-
-bool QDeclarativeViewNodeInstance::isQDeclarativeView() const
-{
- return true;
-}
-
-void QDeclarativeViewNodeInstance::addItem(QDeclarativeItem *item)
-{
- QDeclarativeItem *rootItem = qobject_cast<QDeclarativeItem *>(view()->rootObject());
- Q_ASSERT_X(rootItem, Q_FUNC_INFO, "root item is QDeclarativeItem based");
- item->setParent(rootItem);
-}
-
-}
-}
diff --git a/src/plugins/qmldesigner/designercore/instances/qmlviewnodeinstance.h b/src/plugins/qmldesigner/designercore/instances/qmlviewnodeinstance.h
deleted file mode 100644
index 18633adde4..0000000000
--- a/src/plugins/qmldesigner/designercore/instances/qmlviewnodeinstance.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#ifndef QMLVIEWNODEINSTANCE_H
-#define QMLVIEWNODEINSTANCE_H
-
-#include <QWeakPointer>
-#include <QDeclarativeView>
-#include <QDeclarativeItem>
-
-#include "graphicsviewnodeinstance.h"
-
-namespace QmlDesigner {
-namespace Internal {
-
-class QDeclarativeViewNodeInstance : public GraphicsViewNodeInstance
-{
-public:
- typedef QSharedPointer<QDeclarativeViewNodeInstance> Pointer;
- typedef QWeakPointer<QDeclarativeViewNodeInstance> WeakPointer;
-
- static Pointer create(const NodeMetaInfo &metaInfo, QDeclarativeContext *context, QObject *objectToBeWrapped);
-
- bool isQDeclarativeView() const;
-
- void addItem(QDeclarativeItem *item);
-
-protected:
- QDeclarativeViewNodeInstance(QDeclarativeView *view);
-
- QDeclarativeView* view() const;
-};
-
-}
-}
-#endif // QMLVIEWNODEINSTANCE_H
diff --git a/src/plugins/qmldesigner/designercore/instances/removeinstancescommand.cpp b/src/plugins/qmldesigner/designercore/instances/removeinstancescommand.cpp
new file mode 100644
index 0000000000..e235365fee
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/removeinstancescommand.cpp
@@ -0,0 +1,33 @@
+#include "removeinstancescommand.h"
+
+namespace QmlDesigner {
+
+RemoveInstancesCommand::RemoveInstancesCommand()
+{
+}
+
+RemoveInstancesCommand::RemoveInstancesCommand(const QVector<qint32> &idVector)
+ : m_instanceIdVector(idVector)
+{
+}
+
+QVector<qint32> RemoveInstancesCommand::instanceIds() const
+{
+ return m_instanceIdVector;
+}
+
+QDataStream &operator<<(QDataStream &out, const RemoveInstancesCommand &command)
+{
+ out << command.instanceIds();
+
+ return out;
+}
+
+QDataStream &operator>>(QDataStream &in, RemoveInstancesCommand &command)
+{
+ in >> command.m_instanceIdVector;
+
+ return in;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/removeinstancescommand.h b/src/plugins/qmldesigner/designercore/instances/removeinstancescommand.h
new file mode 100644
index 0000000000..4bcb9afffb
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/removeinstancescommand.h
@@ -0,0 +1,32 @@
+#ifndef REMOVEINSTANCESCOMMAND_H
+#define REMOVEINSTANCESCOMMAND_H
+
+#include <QMetaType>
+#include <QVector>
+
+#include "instancecontainer.h"
+
+namespace QmlDesigner {
+
+class RemoveInstancesCommand
+{
+ friend QDataStream &operator>>(QDataStream &in, RemoveInstancesCommand &command);
+
+public:
+ RemoveInstancesCommand();
+ RemoveInstancesCommand(const QVector<qint32> &idVector);
+
+ QVector<qint32> instanceIds() const;
+
+private:
+ QVector<qint32> m_instanceIdVector;
+};
+
+QDataStream &operator<<(QDataStream &out, const RemoveInstancesCommand &command);
+QDataStream &operator>>(QDataStream &in, RemoveInstancesCommand &command);
+
+} // namespace QmlDesigner
+
+Q_DECLARE_METATYPE(QmlDesigner::RemoveInstancesCommand)
+
+#endif // REMOVEINSTANCESCOMMAND_H
diff --git a/src/plugins/qmldesigner/designercore/instances/removepropertiescommand.cpp b/src/plugins/qmldesigner/designercore/instances/removepropertiescommand.cpp
new file mode 100644
index 0000000000..08f687e61e
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/removepropertiescommand.cpp
@@ -0,0 +1,33 @@
+#include "removepropertiescommand.h"
+
+namespace QmlDesigner {
+
+RemovePropertiesCommand::RemovePropertiesCommand()
+{
+}
+
+RemovePropertiesCommand::RemovePropertiesCommand(const QVector<PropertyAbstractContainer> &properties)
+ : m_properties(properties)
+{
+}
+
+QVector<PropertyAbstractContainer> RemovePropertiesCommand::properties() const
+{
+ return m_properties;
+}
+
+QDataStream &operator<<(QDataStream &out, const RemovePropertiesCommand &command)
+{
+ out << command.properties();
+
+ return out;
+}
+
+QDataStream &operator>>(QDataStream &in, RemovePropertiesCommand &command)
+{
+ in >> command.m_properties;
+
+ return in;
+}
+
+}
diff --git a/src/plugins/qmldesigner/designercore/instances/removepropertiescommand.h b/src/plugins/qmldesigner/designercore/instances/removepropertiescommand.h
new file mode 100644
index 0000000000..b2997efe6a
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/removepropertiescommand.h
@@ -0,0 +1,31 @@
+#ifndef REMOVEPROPERTIESCOMMAND_H
+#define REMOVEPROPERTIESCOMMAND_H
+
+#include <QMetaType>
+#include <QVector>
+
+#include "propertyabstractcontainer.h"
+
+namespace QmlDesigner {
+
+class RemovePropertiesCommand
+{
+ friend QDataStream &operator>>(QDataStream &in, RemovePropertiesCommand &command);
+public:
+ RemovePropertiesCommand();
+ RemovePropertiesCommand(const QVector<PropertyAbstractContainer> &properties);
+
+ QVector<PropertyAbstractContainer> properties() const;
+
+private:
+ QVector<PropertyAbstractContainer> m_properties;
+};
+
+QDataStream &operator<<(QDataStream &out, const RemovePropertiesCommand &command);
+QDataStream &operator>>(QDataStream &in, RemovePropertiesCommand &command);
+
+}
+
+Q_DECLARE_METATYPE(QmlDesigner::RemovePropertiesCommand)
+
+#endif // REMOVEPROPERTIESCOMMAND_H
diff --git a/src/plugins/qmldesigner/designercore/instances/reparentcontainer.cpp b/src/plugins/qmldesigner/designercore/instances/reparentcontainer.cpp
new file mode 100644
index 0000000000..f422dfc53a
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/reparentcontainer.cpp
@@ -0,0 +1,72 @@
+#include "reparentcontainer.h"
+
+namespace QmlDesigner {
+
+ReparentContainer::ReparentContainer()
+ : m_instanceId(-1),
+ m_oldParentInstanceId(-1),
+ m_newParentInstanceId(-1)
+{
+}
+
+ReparentContainer::ReparentContainer(qint32 instanceId,
+ qint32 oldParentInstanceId,
+ const QString &oldParentProperty,
+ qint32 newParentInstanceId,
+ const QString &newParentProperty)
+ : m_instanceId(instanceId),
+ m_oldParentInstanceId(oldParentInstanceId),
+ m_oldParentProperty(oldParentProperty),
+ m_newParentInstanceId(newParentInstanceId),
+ m_newParentProperty(newParentProperty)
+{
+}
+
+qint32 ReparentContainer::instanceId() const
+{
+ return m_instanceId;
+}
+
+qint32 ReparentContainer::oldParentInstanceId() const
+{
+ return m_oldParentInstanceId;
+}
+
+QString ReparentContainer::oldParentProperty() const
+{
+ return m_oldParentProperty;
+}
+
+qint32 ReparentContainer::newParentInstanceId() const
+{
+ return m_newParentInstanceId;
+}
+
+QString ReparentContainer::newParentProperty() const
+{
+ return m_newParentProperty;
+}
+
+QDataStream &operator<<(QDataStream &out, const ReparentContainer &container)
+{
+ out << container.instanceId();
+ out << container.oldParentInstanceId();
+ out << container.oldParentProperty();
+ out << container.newParentInstanceId();
+ out << container.newParentProperty();
+
+ return out;
+}
+
+QDataStream &operator>>(QDataStream &in, ReparentContainer &container)
+{
+ in >> container.m_instanceId;
+ in >> container.m_oldParentInstanceId;
+ in >> container.m_oldParentProperty;
+ in >> container.m_newParentInstanceId;
+ in >> container.m_newParentProperty;
+
+ return in;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/reparentcontainer.h b/src/plugins/qmldesigner/designercore/instances/reparentcontainer.h
new file mode 100644
index 0000000000..2333751574
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/reparentcontainer.h
@@ -0,0 +1,38 @@
+#ifndef REPARENTCONTAINER_H
+#define REPARENTCONTAINER_H
+
+#include <qmetatype.h>
+
+namespace QmlDesigner {
+
+class ReparentContainer
+{
+ friend QDataStream &operator>>(QDataStream &in, ReparentContainer &container);
+public:
+ ReparentContainer();
+ ReparentContainer(qint32 instanceId,
+ qint32 oldParentInstanceId,
+ const QString &oldParentProperty,
+ qint32 newParentInstanceId,
+ const QString &newParentProperty);
+
+ qint32 instanceId() const;
+ qint32 oldParentInstanceId() const;
+ QString oldParentProperty() const;
+ qint32 newParentInstanceId() const;
+ QString newParentProperty() const;
+
+private:
+ qint32 m_instanceId;
+ qint32 m_oldParentInstanceId;
+ QString m_oldParentProperty;
+ qint32 m_newParentInstanceId;
+ QString m_newParentProperty;
+};
+
+QDataStream &operator<<(QDataStream &out, const ReparentContainer &container);
+QDataStream &operator>>(QDataStream &in, ReparentContainer &container);
+
+} // namespace QmlDesigner
+
+#endif // REPARENTCONTAINER_H
diff --git a/src/plugins/qmldesigner/designercore/instances/reparentinstancescommand.cpp b/src/plugins/qmldesigner/designercore/instances/reparentinstancescommand.cpp
new file mode 100644
index 0000000000..52393d8908
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/reparentinstancescommand.cpp
@@ -0,0 +1,34 @@
+#include "reparentinstancescommand.h"
+
+namespace QmlDesigner {
+
+ReparentInstancesCommand::ReparentInstancesCommand()
+{
+}
+
+ReparentInstancesCommand::ReparentInstancesCommand(const QVector<ReparentContainer> &container)
+ : m_reparentInstanceVector(container)
+{
+}
+
+QVector<ReparentContainer> ReparentInstancesCommand::reparentInstances() const
+{
+ return m_reparentInstanceVector;
+}
+
+
+QDataStream &operator<<(QDataStream &out, const ReparentInstancesCommand &command)
+{
+ out << command.reparentInstances();
+
+ return out;
+}
+
+QDataStream &operator>>(QDataStream &in, ReparentInstancesCommand &command)
+{
+ in >> command.m_reparentInstanceVector;
+
+ return in;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/reparentinstancescommand.h b/src/plugins/qmldesigner/designercore/instances/reparentinstancescommand.h
new file mode 100644
index 0000000000..338ad660ad
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/reparentinstancescommand.h
@@ -0,0 +1,32 @@
+#ifndef REPARENTINSTANCESCOMMAND_H
+#define REPARENTINSTANCESCOMMAND_H
+
+#include <QMetaType>
+#include <QVector>
+
+#include "reparentcontainer.h"
+
+namespace QmlDesigner {
+
+class ReparentInstancesCommand
+{
+ friend QDataStream &operator>>(QDataStream &in, ReparentInstancesCommand &command);
+
+public:
+ ReparentInstancesCommand();
+ ReparentInstancesCommand(const QVector<ReparentContainer> &container);
+
+ QVector<ReparentContainer> reparentInstances() const;
+
+private:
+ QVector<ReparentContainer> m_reparentInstanceVector;
+};
+
+QDataStream &operator<<(QDataStream &out, const ReparentInstancesCommand &command);
+QDataStream &operator>>(QDataStream &in, ReparentInstancesCommand &command);
+
+} //
+
+Q_DECLARE_METATYPE(QmlDesigner::ReparentInstancesCommand)
+
+#endif // REPARENTINSTANCESCOMMAND_H
diff --git a/src/plugins/qmldesigner/designercore/instances/servernodeinstance.cpp b/src/plugins/qmldesigner/designercore/instances/servernodeinstance.cpp
new file mode 100644
index 0000000000..b8f14ceb3c
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/servernodeinstance.cpp
@@ -0,0 +1,596 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "servernodeinstance.h"
+
+#include "objectnodeinstance.h"
+#include "qmlgraphicsitemnodeinstance.h"
+#include "dummynodeinstance.h"
+#include "componentnodeinstance.h"
+#include "qmltransitionnodeinstance.h"
+#include "qmlpropertychangesnodeinstance.h"
+#include "positionernodeinstance.h"
+#include "behaviornodeinstance.h"
+#include "qmlstatenodeinstance.h"
+
+#include "nodeinstanceserver.h"
+#include "instancecontainer.h"
+
+#include <invalidnodeinstanceexception.h>
+
+#include <QHash>
+#include <QSet>
+
+#include <QtDeclarative/QDeclarativeEngine>
+
+/*!
+ \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
+*/
+ServerNodeInstance::ServerNodeInstance()
+{
+}
+
+/*!
+\brief Destructor
+
+*/
+ServerNodeInstance::~ServerNodeInstance()
+{
+}
+
+/*!
+\brief Constructor - creates a valid NodeInstance
+
+*/
+ServerNodeInstance::ServerNodeInstance(const Internal::ObjectNodeInstance::Pointer &abstractInstance)
+ : m_nodeInstance(abstractInstance)
+{
+
+}
+
+
+ServerNodeInstance::ServerNodeInstance(const ServerNodeInstance &other)
+ : m_nodeInstance(other.m_nodeInstance)
+{
+}
+
+ServerNodeInstance &ServerNodeInstance::operator=(const ServerNodeInstance &other)
+{
+ m_nodeInstance = other.m_nodeInstance;
+ return *this;
+}
+
+/*!
+\brief Paints the NodeInstance with this painter.
+\param painter used QPainter
+*/
+void ServerNodeInstance::paint(QPainter *painter)
+{
+ m_nodeInstance->paint(painter);
+}
+
+QImage ServerNodeInstance::renderImage() const
+{
+ return m_nodeInstance->renderImage();
+}
+
+bool ServerNodeInstance::isRootNodeInstance() const
+{
+ return isValid() && m_nodeInstance->isRootNodeInstance();
+}
+
+bool ServerNodeInstance::isSubclassOf(QObject *object, const QByteArray &superTypeName)
+{
+ if (object == 0)
+ return false;
+
+ const QMetaObject *metaObject = object->metaObject();
+
+ while (metaObject) {
+ QDeclarativeType *qmlType = QDeclarativeMetaType::qmlType(metaObject);
+ if (qmlType && qmlType->qmlTypeName() == superTypeName) // ignore version numbers
+ return true;
+
+ if (metaObject->className() == superTypeName)
+ return true;
+
+ metaObject = metaObject->superClass();
+ }
+
+ return false;
+}
+
+bool ServerNodeInstance::isSubclassOf(const QString &superTypeName) const
+{
+ return isSubclassOf(internalObject(), superTypeName.toUtf8());
+}
+
+/*!
+\brief Creates a new NodeInstace for this NodeMetaInfo
+
+\param metaInfo MetaInfo for which a Instance should be created
+\param context QDeclarativeContext which should be used
+\returns Internal Pointer of a NodeInstance
+\see NodeMetaInfo
+*/
+Internal::ObjectNodeInstance::Pointer ServerNodeInstance::createInstance(QObject *objectToBeWrapped)
+{
+ Internal::ObjectNodeInstance::Pointer instance;
+
+ if (objectToBeWrapped == 0)
+ instance = Internal::DummyNodeInstance::create();
+ else if (isSubclassOf(objectToBeWrapped, "QDeclarativeBasePositioner"))
+ instance = Internal::PositionerNodeInstance::create(objectToBeWrapped);
+ else if (isSubclassOf(objectToBeWrapped, "QDeclarativeItem"))
+ instance = Internal::QmlGraphicsItemNodeInstance::create(objectToBeWrapped);
+ else if (isSubclassOf(objectToBeWrapped, "QDeclarativeComponent"))
+ instance = Internal::ComponentNodeInstance::create(objectToBeWrapped);
+ else if (isSubclassOf(objectToBeWrapped, "QDeclarativePropertyChanges"))
+ instance = Internal::QmlPropertyChangesNodeInstance::create(objectToBeWrapped);
+ else if (isSubclassOf(objectToBeWrapped, "QDeclarativeState"))
+ instance = Internal::QmlStateNodeInstance::create(objectToBeWrapped);
+ else if (isSubclassOf(objectToBeWrapped, "QDeclarativeTransition"))
+ instance = Internal::QmlTransitionNodeInstance::create(objectToBeWrapped);
+ else if (isSubclassOf(objectToBeWrapped, "QDeclarativeBehavior"))
+ instance = Internal::BehaviorNodeInstance::create(objectToBeWrapped);
+ else if (isSubclassOf(objectToBeWrapped, "QObject"))
+ instance = Internal::ObjectNodeInstance::create(objectToBeWrapped);
+ else
+ instance = Internal::DummyNodeInstance::create();
+
+
+ return instance;
+}
+
+ServerNodeInstance ServerNodeInstance::create(NodeInstanceServer *nodeInstanceServer, const InstanceContainer &instanceContainer)
+{
+ Q_ASSERT(instanceContainer.instanceId() != -1);
+ Q_ASSERT(nodeInstanceServer);
+
+ QDeclarativeContext *context = nodeInstanceServer->engine()->rootContext();
+
+ QObject *object = Internal::ObjectNodeInstance::createObject(instanceContainer.type(), instanceContainer.majorNumber(), instanceContainer.minorNumber(), instanceContainer.componentPath(), context);
+
+ ServerNodeInstance instance(createInstance(object));
+
+ instance.internalInstance()->setInstanceId(instanceContainer.instanceId());
+
+ instance.internalInstance()->setNodeInstanceServer(nodeInstanceServer);
+
+ instance.internalInstance()->initializePropertyWatcher(instance.m_nodeInstance);
+
+ //QObject::connect(instance.internalObject(), SIGNAL(destroyed(QObject*)), nodeInstanceView, SLOT(removeIdFromContext(QObject*)));
+
+ return instance;
+}
+
+
+void ServerNodeInstance::reparent(const ServerNodeInstance &oldParentInstance, const QString &oldParentProperty, const ServerNodeInstance &newParentInstance, const QString &newParentProperty)
+{
+ m_nodeInstance->reparent(oldParentInstance.m_nodeInstance, oldParentProperty, newParentInstance.m_nodeInstance, newParentProperty);
+}
+
+/*!
+\brief Returns the parent NodeInstance of this NodeInstance.
+
+ If there is not parent than the parent is invalid.
+
+\returns Parent NodeInstance.
+*/
+ServerNodeInstance ServerNodeInstance::parent() const
+{
+ return m_nodeInstance->parentInstance();
+}
+
+bool ServerNodeInstance::hasParent() const
+{
+ return m_nodeInstance->parent();
+}
+
+bool ServerNodeInstance::isValid() const
+{
+ return m_nodeInstance && m_nodeInstance->isValid();
+}
+
+
+/*!
+\brief Returns if the NodeInstance is a QGraphicsItem.
+\returns true if this NodeInstance is a QGraphicsItem
+*/
+bool ServerNodeInstance::equalGraphicsItem(QGraphicsItem *item) const
+{
+ return m_nodeInstance->equalGraphicsItem(item);
+}
+
+/*!
+\brief Returns the bounding rect of the NodeInstance.
+\returns QRectF of the NodeInstance
+*/
+QRectF ServerNodeInstance::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 ServerNodeInstance::setPropertyVariant(const QString &name, const QVariant &value)
+{
+ m_nodeInstance->setPropertyVariant(name, value);
+
+}
+
+void ServerNodeInstance::setPropertyDynamicVariant(const QString &name, const QString &typeName, const QVariant &value)
+{
+ m_nodeInstance->createDynamicProperty(name, typeName);
+ m_nodeInstance->setPropertyVariant(name, value);
+}
+
+void ServerNodeInstance::setPropertyBinding(const QString &name, const QString &expression)
+{
+ m_nodeInstance->setPropertyBinding(name, expression);
+}
+
+void ServerNodeInstance::setPropertyDynamicBinding(const QString &name, const QString &typeName, const QString &expression)
+{
+ m_nodeInstance->createDynamicProperty(name, typeName);
+ m_nodeInstance->setPropertyBinding(name, expression);
+}
+
+void ServerNodeInstance::resetProperty(const QString &name)
+{
+ m_nodeInstance->resetProperty(name);
+}
+
+void ServerNodeInstance::refreshProperty(const QString &name)
+{
+ m_nodeInstance->refreshProperty(name);
+}
+
+void ServerNodeInstance::setId(const QString &id)
+{
+ m_nodeInstance->setId(id);
+}
+
+/*!
+\brief Returns the property value of the property of this NodeInstance.
+\returns QVariant value
+*/
+QVariant ServerNodeInstance::property(const QString &name) const
+{
+ return m_nodeInstance->property(name);
+}
+
+QStringList ServerNodeInstance::propertyNames() const
+{
+ return m_nodeInstance->propertyNames();
+}
+
+bool ServerNodeInstance::hasBindingForProperty(const QString &name, bool *hasChanged) const
+{
+ return m_nodeInstance->hasBindingForProperty(name, hasChanged);
+}
+
+/*!
+\brief Returns the property default value of the property of this NodeInstance.
+\returns QVariant default value which is the reset value to
+*/
+QVariant ServerNodeInstance::defaultValue(const QString &name) const
+{
+ return m_nodeInstance->resetValue(name);
+}
+
+/*!
+\brief Returns the type of the property of this NodeInstance.
+*/
+QString ServerNodeInstance::instanceType(const QString &name) const
+{
+ return m_nodeInstance->instanceType(name);
+}
+
+void ServerNodeInstance::makeInvalid()
+{
+ if (m_nodeInstance)
+ m_nodeInstance->destroy();
+ m_nodeInstance.clear();
+}
+
+bool ServerNodeInstance::hasContent() const
+{
+ return m_nodeInstance->hasContent();
+}
+
+bool ServerNodeInstance::isResizable() const
+{
+ return m_nodeInstance->isResizable();
+}
+
+bool ServerNodeInstance::isMovable() const
+{
+ return m_nodeInstance->isMovable();
+}
+
+bool ServerNodeInstance::isInPositioner() const
+{
+ return m_nodeInstance->isInPositioner();
+}
+
+bool ServerNodeInstance::hasAnchor(const QString &name) const
+{
+ return m_nodeInstance->hasAnchor(name);
+}
+
+int ServerNodeInstance::penWidth() const
+{
+ return m_nodeInstance->penWidth();
+}
+
+bool ServerNodeInstance::isAnchoredBySibling() const
+{
+ return m_nodeInstance->isAnchoredBySibling();
+}
+
+bool ServerNodeInstance::isAnchoredByChildren() const
+{
+ return m_nodeInstance->isAnchoredByChildren();
+}
+
+QPair<QString, ServerNodeInstance> ServerNodeInstance::anchor(const QString &name) const
+{
+ return m_nodeInstance->anchor(name);
+}
+
+QDebug operator<<(QDebug debug, const ServerNodeInstance &instance)
+{
+ if (instance.isValid()) {
+ debug.nospace() << "ServerNodeInstance("
+ << instance.instanceId() << ", "
+ << instance.internalObject() << ", "
+ << instance.id() << ", "
+ << instance.parent() << ')';
+ } else {
+ debug.nospace() << "ServerNodeInstance(invalid)";
+ }
+
+ return debug.space();
+}
+
+uint qHash(const ServerNodeInstance &instance)
+{
+ return ::qHash(instance.instanceId());
+}
+
+bool operator==(const ServerNodeInstance &first, const ServerNodeInstance &second)
+{
+ return first.instanceId() == second.instanceId();
+}
+
+bool ServerNodeInstance::isWrappingThisObject(QObject *object) const
+{
+ return internalObject() && internalObject() == object;
+}
+
+/*!
+\brief Returns the position in parent coordiantes.
+\returns QPointF of the position of the instance.
+*/
+QPointF ServerNodeInstance::position() const
+{
+ return m_nodeInstance->position();
+}
+
+/*!
+\brief Returns the size in local coordiantes.
+\returns QSizeF of the size of the instance.
+*/
+QSizeF ServerNodeInstance::size() const
+{
+ QSizeF instanceSize = m_nodeInstance->size();
+
+ return instanceSize;
+}
+
+QTransform ServerNodeInstance::transform() const
+{
+ return m_nodeInstance->transform();
+}
+
+/*!
+\brief Returns the transform matrix of the instance.
+\returns QTransform of the instance.
+*/
+QTransform ServerNodeInstance::customTransform() const
+{
+ return m_nodeInstance->customTransform();
+}
+
+QTransform ServerNodeInstance::sceneTransform() const
+{
+ return m_nodeInstance->sceneTransform();
+}
+
+double ServerNodeInstance::rotation() const
+{
+ return m_nodeInstance->rotation();
+}
+
+double ServerNodeInstance::scale() const
+{
+ return m_nodeInstance->scale();
+}
+
+QList<QGraphicsTransform *> ServerNodeInstance::transformations() const
+{
+ return m_nodeInstance->transformations();
+}
+
+QPointF ServerNodeInstance::transformOriginPoint() const
+{
+ return m_nodeInstance->transformOriginPoint();
+}
+
+double ServerNodeInstance::zValue() const
+{
+ return m_nodeInstance->zValue();
+}
+
+/*!
+\brief Returns the opacity of the instance.
+\returns 0.0 mean transparent and 1.0 opaque.
+*/
+double ServerNodeInstance::opacity() const
+{
+ return m_nodeInstance->opacity();
+}
+
+
+void ServerNodeInstance::setDeleteHeldInstance(bool deleteInstance)
+{
+ m_nodeInstance->setDeleteHeldInstance(deleteInstance);
+}
+
+
+void ServerNodeInstance::paintUpdate()
+{
+ m_nodeInstance->paintUpdate();
+}
+
+
+Internal::QmlGraphicsItemNodeInstance::Pointer ServerNodeInstance::qmlGraphicsItemNodeInstance() const
+{
+ return m_nodeInstance.dynamicCast<Internal::QmlGraphicsItemNodeInstance>();
+}
+
+QObject *ServerNodeInstance::internalObject() const
+{
+ if (m_nodeInstance.isNull())
+ return 0;
+
+ return m_nodeInstance->object();
+}
+
+void ServerNodeInstance::activateState()
+{
+ m_nodeInstance->activateState();
+}
+
+void ServerNodeInstance::deactivateState()
+{
+ m_nodeInstance->deactivateState();
+}
+
+bool ServerNodeInstance::updateStateVariant(const ServerNodeInstance &target, const QString &propertyName, const QVariant &value)
+{
+ return m_nodeInstance->updateStateVariant(target.internalInstance(), propertyName, value);
+}
+
+bool ServerNodeInstance::updateStateBinding(const ServerNodeInstance &target, const QString &propertyName, const QString &expression)
+{
+ return m_nodeInstance->updateStateBinding(target.internalInstance(), propertyName, expression);
+}
+
+QVariant ServerNodeInstance::resetVariant(const QString &propertyName) const
+{
+ return m_nodeInstance->resetValue(propertyName);
+}
+
+bool ServerNodeInstance::resetStateProperty(const ServerNodeInstance &target, const QString &propertyName, const QVariant &resetValue)
+{
+ return m_nodeInstance->resetStateProperty(target.internalInstance(), propertyName, resetValue);
+}
+
+/*!
+ Makes types used in node instances known to the Qml engine. To be called once at initialization time.
+*/
+void ServerNodeInstance::registerDeclarativeTypes()
+{
+// qmlRegisterType<QmlDesigner::Internal::QmlPropertyChangesObject>();
+}
+
+void ServerNodeInstance::doComponentComplete()
+{
+ m_nodeInstance->doComponentComplete();
+}
+
+QList<ServerNodeInstance> ServerNodeInstance::childItems() const
+{
+ return m_nodeInstance->childItems();
+}
+
+QString ServerNodeInstance::id() const
+{
+ return m_nodeInstance->id();
+}
+
+qint32 ServerNodeInstance::instanceId() const
+{
+ if (isValid()) {
+ return m_nodeInstance->instanceId();
+ } else {
+ return -1;
+ }
+}
+
+QObject* ServerNodeInstance::testHandle() const
+{
+ return internalObject();
+}
+
+Internal::ObjectNodeInstance::Pointer ServerNodeInstance::internalInstance() const
+{
+ return m_nodeInstance;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/servernodeinstance.h b/src/plugins/qmldesigner/designercore/instances/servernodeinstance.h
new file mode 100644
index 0000000000..e7c1476f1a
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/servernodeinstance.h
@@ -0,0 +1,193 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 SERVERNODEINSTANCE_H
+#define SERVERNODEINSTANCE_H
+
+#include "corelib_global.h"
+#include <QSharedPointer>
+#include <QHash>
+#include <QRectF>
+
+#include <nodeinstanceserverinterface.h>
+#include <propertyvaluecontainer.h>
+
+QT_BEGIN_NAMESPACE
+class QPainter;
+class QStyleOptionGraphicsItem;
+class QDeclarativeContext;
+class QGraphicsItem;
+class QGraphicsTransform;
+QT_END_NAMESPACE
+
+namespace QmlDesigner {
+
+class NodeInstanceServer;
+class InstanceContainer;
+
+namespace Internal {
+ class ObjectNodeInstance;
+ class QmlGraphicsItemNodeInstance;
+ class QmlPropertyChangesNodeInstance;
+ class GraphicsObjectNodeInstance;
+ class QmlStateNodeInstance;
+}
+
+class CORESHARED_EXPORT ServerNodeInstance
+{
+ friend CORESHARED_EXPORT class NodeInstanceServer;
+ friend class QHash<qint32, ServerNodeInstance>;
+ friend CORESHARED_EXPORT uint qHash(const ServerNodeInstance &instance);
+ friend CORESHARED_EXPORT bool operator==(const ServerNodeInstance &first, const ServerNodeInstance &second);
+ friend CORESHARED_EXPORT QDebug operator<<(QDebug debug, const ServerNodeInstance &instance);
+ friend CORESHARED_EXPORT class NodeMetaInfo;
+ friend class QmlDesigner::Internal::QmlGraphicsItemNodeInstance;
+ friend class QmlDesigner::Internal::GraphicsObjectNodeInstance;
+ friend class QmlDesigner::Internal::ObjectNodeInstance;
+ friend class QmlDesigner::Internal::QmlPropertyChangesNodeInstance;
+ friend class QmlDesigner::Internal::QmlStateNodeInstance;
+
+public:
+ ServerNodeInstance();
+ ~ServerNodeInstance();
+ ServerNodeInstance(const ServerNodeInstance &other);
+ ServerNodeInstance& operator=(const ServerNodeInstance &other);
+
+ void paint(QPainter *painter);
+ QImage renderImage() const;
+
+ ServerNodeInstance parent() const;
+ bool hasParent() 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;
+ QString instanceType(const QString &name) const;
+ QStringList propertyNames() const;
+
+
+ bool hasBindingForProperty(const QString &name, bool *hasChanged = 0) const;
+
+ bool isValid() const;
+ void makeInvalid();
+ bool hasContent() const;
+ bool isResizable() const;
+ bool isMovable() const;
+ bool isInPositioner() const;
+
+ bool isSubclassOf(const QString &superTypeName) const;
+ bool isRootNodeInstance() const;
+
+ bool isWrappingThisObject(QObject *object) const;
+
+ QVariant resetVariant(const QString &name) const;
+
+ bool hasAnchor(const QString &name) const;
+ bool isAnchoredBySibling() const;
+ bool isAnchoredByChildren() const;
+ QPair<QString, ServerNodeInstance> anchor(const QString &name) const;
+
+ int penWidth() const;
+
+ static void registerDeclarativeTypes();
+
+ void doComponentComplete();
+
+ QList<ServerNodeInstance> childItems() const;
+
+ QString id() const;
+ qint32 instanceId() const;
+
+ QObject* testHandle() const;
+ QSharedPointer<Internal::ObjectNodeInstance> internalInstance() const;
+
+private: // functions
+ ServerNodeInstance(const QSharedPointer<Internal::ObjectNodeInstance> &abstractInstance);
+
+ 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);
+
+ void resetProperty(const QString &name);
+ void refreshProperty(const QString &name);
+
+ void activateState();
+ void deactivateState();
+ void refreshState();
+
+ bool updateStateVariant(const ServerNodeInstance &target, const QString &propertyName, const QVariant &value);
+ bool updateStateBinding(const ServerNodeInstance &target, const QString &propertyName, const QString &expression);
+ bool resetStateProperty(const ServerNodeInstance &target, const QString &propertyName, const QVariant &resetValue);
+
+ static ServerNodeInstance create(NodeInstanceServer *nodeInstanceServer, const InstanceContainer &instanceContainer);
+
+ void setDeleteHeldInstance(bool deleteInstance);
+ void reparent(const ServerNodeInstance &oldParentInstance, const QString &oldParentProperty, const ServerNodeInstance &newParentInstance, const QString &newParentProperty);
+
+
+ void setId(const QString &id);
+
+ static QSharedPointer<Internal::ObjectNodeInstance> createInstance(QObject *objectToBeWrapped);
+ QSharedPointer<Internal::QmlGraphicsItemNodeInstance> qmlGraphicsItemNodeInstance() const;
+
+ void paintUpdate();
+
+ static bool isSubclassOf(QObject *object, const QByteArray &superTypeName);
+
+
+ QObject *internalObject() const; // should be not used outside of the nodeinstances!!!!
+
+private: // variables
+ QSharedPointer<Internal::ObjectNodeInstance> m_nodeInstance;
+};
+
+CORESHARED_EXPORT uint qHash(const ServerNodeInstance &instance);
+CORESHARED_EXPORT bool operator==(const ServerNodeInstance &first, const ServerNodeInstance &second);
+CORESHARED_EXPORT QDebug operator<<(QDebug debug, const ServerNodeInstance &instance);
+}
+
+Q_DECLARE_METATYPE(QmlDesigner::ServerNodeInstance)
+
+#endif // SERVERNODEINSTANCE_H
diff --git a/src/plugins/qmldesigner/designercore/instances/statepreviewimagechangedcommand.cpp b/src/plugins/qmldesigner/designercore/instances/statepreviewimagechangedcommand.cpp
new file mode 100644
index 0000000000..31422ccd18
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/statepreviewimagechangedcommand.cpp
@@ -0,0 +1,32 @@
+#include "statepreviewimagechangedcommand.h"
+
+namespace QmlDesigner {
+
+StatePreviewImageChangedCommand::StatePreviewImageChangedCommand()
+{
+}
+
+StatePreviewImageChangedCommand::StatePreviewImageChangedCommand(const QVector<ImageContainer> &imageVector)
+ : m_previewVector(imageVector)
+{
+}
+
+QVector<ImageContainer> StatePreviewImageChangedCommand::previews()const
+{
+ return m_previewVector;
+}
+
+QDataStream &operator<<(QDataStream &out, const StatePreviewImageChangedCommand &command)
+{
+ out << command.previews();
+
+ return out;
+}
+
+QDataStream &operator>>(QDataStream &in, StatePreviewImageChangedCommand &command)
+{
+ in >> command.m_previewVector;
+
+ return in;
+}
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/statepreviewimagechangedcommand.h b/src/plugins/qmldesigner/designercore/instances/statepreviewimagechangedcommand.h
new file mode 100644
index 0000000000..a6383d2882
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/statepreviewimagechangedcommand.h
@@ -0,0 +1,30 @@
+#ifndef STATEPREVIEWIMAGECHANGEDCOMMAND_H
+#define STATEPREVIEWIMAGECHANGEDCOMMAND_H
+
+#include <QMetaType>
+
+#include "imagecontainer.h"
+
+namespace QmlDesigner {
+
+class StatePreviewImageChangedCommand
+{
+ friend QDataStream &operator>>(QDataStream &in, StatePreviewImageChangedCommand &command);
+public:
+ StatePreviewImageChangedCommand();
+ StatePreviewImageChangedCommand(const QVector<ImageContainer> &imageVector);
+
+ QVector<ImageContainer> previews() const;
+
+private:
+ QVector<ImageContainer> m_previewVector;
+};
+
+QDataStream &operator<<(QDataStream &out, const StatePreviewImageChangedCommand &command);
+QDataStream &operator>>(QDataStream &in, StatePreviewImageChangedCommand &command);
+
+} // namespace QmlDesigner
+
+Q_DECLARE_METATYPE(QmlDesigner::StatePreviewImageChangedCommand)
+
+#endif // STATEPREVIEWIMAGECHANGEDCOMMAND_H
diff --git a/src/plugins/qmldesigner/designercore/instances/valueschangedcommand.cpp b/src/plugins/qmldesigner/designercore/instances/valueschangedcommand.cpp
new file mode 100644
index 0000000000..996e167873
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/valueschangedcommand.cpp
@@ -0,0 +1,33 @@
+#include "valueschangedcommand.h"
+
+namespace QmlDesigner {
+
+ValuesChangedCommand::ValuesChangedCommand()
+{
+}
+
+ValuesChangedCommand::ValuesChangedCommand(const QVector<PropertyValueContainer> &valueChangeVector)
+ : m_valueChangeVector (valueChangeVector)
+{
+}
+
+QVector<PropertyValueContainer> ValuesChangedCommand::valueChanges() const
+{
+ return m_valueChangeVector;
+}
+
+QDataStream &operator<<(QDataStream &out, const ValuesChangedCommand &command)
+{
+ out << command.valueChanges();
+
+ return out;
+}
+
+QDataStream &operator>>(QDataStream &in, ValuesChangedCommand &command)
+{
+ in >> command.m_valueChangeVector;
+
+ return in;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/valueschangedcommand.h b/src/plugins/qmldesigner/designercore/instances/valueschangedcommand.h
new file mode 100644
index 0000000000..f41f650ff6
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/valueschangedcommand.h
@@ -0,0 +1,33 @@
+#ifndef VALUESCHANGEDCOMMAND_H
+#define VALUESCHANGEDCOMMAND_H
+
+#include <QMetaType>
+#include <QVector>
+
+#include "propertyvaluecontainer.h"
+
+namespace QmlDesigner {
+
+class ValuesChangedCommand
+{
+ friend QDataStream &operator>>(QDataStream &in, ValuesChangedCommand &command);
+
+public:
+ ValuesChangedCommand();
+ ValuesChangedCommand(const QVector<PropertyValueContainer> &valueChangeVector);
+
+ QVector<PropertyValueContainer> valueChanges() const;
+
+private:
+ QVector<PropertyValueContainer> m_valueChangeVector;
+};
+
+QDataStream &operator<<(QDataStream &out, const ValuesChangedCommand &command);
+QDataStream &operator>>(QDataStream &in, ValuesChangedCommand &command);
+
+} // namespace QmlDesigner
+
+Q_DECLARE_METATYPE(QmlDesigner::ValuesChangedCommand)
+
+
+#endif // VALUESCHANGEDCOMMAND_H
diff --git a/src/plugins/qmldesigner/designercore/instances/widgetnodeinstance.cpp b/src/plugins/qmldesigner/designercore/instances/widgetnodeinstance.cpp
deleted file mode 100644
index eefb210b16..0000000000
--- a/src/plugins/qmldesigner/designercore/instances/widgetnodeinstance.cpp
+++ /dev/null
@@ -1,156 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#include "widgetnodeinstance.h"
-
-#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, QDeclarativeContext *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/designercore/instances/widgetnodeinstance.h b/src/plugins/qmldesigner/designercore/instances/widgetnodeinstance.h
deleted file mode 100644
index c9b10636be..0000000000
--- a/src/plugins/qmldesigner/designercore/instances/widgetnodeinstance.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#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, QDeclarativeContext *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/designercore/metainfo/enumeratormetainfo.cpp b/src/plugins/qmldesigner/designercore/metainfo/enumeratormetainfo.cpp
deleted file mode 100644
index 40fb74b5c8..0000000000
--- a/src/plugins/qmldesigner/designercore/metainfo/enumeratormetainfo.cpp
+++ /dev/null
@@ -1,162 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#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);
-}
-
-QString EnumeratorMetaInfo::valueToString(int value) const
-{
- return m_data->elements.key(value);
-}
-
-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/designercore/metainfo/gui.metainfo b/src/plugins/qmldesigner/designercore/metainfo/gui.metainfo
deleted file mode 100644
index b2affa6a8b..0000000000
--- a/src/plugins/qmldesigner/designercore/metainfo/gui.metainfo
+++ /dev/null
@@ -1,229 +0,0 @@
-<!-- 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>
- <enumerator name="Type" scope="QEasingCurve">
- <element name="Linear" value="0" />
- <element name="InQuad" value="1" />
- <element name="OutQuad" value="2" />
- <element name="InOutQuad" value="3" />
- <element name="OutInQuad" value="4" />
- <element name="InCubic" value="5" />
- <element name="OutCubic" value="6" />
- <element name="InOutCubic" value="7" />
- <element name="OutInCubic" value="8" />
- <element name="InQuart" value="9" />
- <element name="OutQuart" value="10" />
- <element name="InOutQuart" value="11" />
- <element name="OutInQuart" value="12" />
- <element name="InQuint" value="13" />
- <element name="OutQuint" value="14" />
- <element name="InOutQuint" value="15" />
- <element name="OutInQuint" value="16" />
- <element name="InSine" value="17" />
- <element name="OutSine" value="18" />
- <element name="InOutSine" value="19" />
- <element name="OutInSine" value="20" />
- <element name="InExpo" value="21" />
- <element name="OutExpo" value="22" />
- <element name="InOutExpo" value="23" />
- <element name="OutInExpo" value="24" />
- <element name="InCirc" value="25" />
- <element name="OutCirc" value="26" />
- <element name="InOutCirc" value="27" />
- <element name="OutInCirc" value="28" />
- <element name="InElastic" value="29" />
- <element name="OutElastic" value="30" />
- <element name="InOutElastic" value="31" />
- <element name="OutInElastic" value="32" />
- <element name="InBack" value="33" />
- <element name="OutBack" value="34" />
- <element name="InOutBack" value="35" />
- <element name="OutInBack" value="36" />
- <element name="InBounce" value="37" />
- <element name="OutBounce" value="38" />
- <element name="InOutBounce" value="39" />
- <element name="OutInBounce" value="40" />
- <element name="InCurve" value="41" />
- <element name="OutCurve" value="42" />
- <element name="SineCurve" value="43" />
- <element name="CosineCurve" value="44" />
- <element name="Custom" value="45" />
- <element name="NCurveTypes" value="46" />
- </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>
-</metainfo>
diff --git a/src/plugins/qmldesigner/designercore/metainfo/itemlibraryinfo.cpp b/src/plugins/qmldesigner/designercore/metainfo/itemlibraryinfo.cpp
index 7cc90e260d..907cea9c94 100644
--- a/src/plugins/qmldesigner/designercore/metainfo/itemlibraryinfo.cpp
+++ b/src/plugins/qmldesigner/designercore/metainfo/itemlibraryinfo.cpp
@@ -55,6 +55,7 @@ public:
QIcon dragIcon;
QList<PropertyContainer> properties;
QString qml;
+ QString requiredImport;
};
class ItemLibraryInfoPrivate
@@ -89,6 +90,11 @@ void ItemLibraryEntry::setDragIcon(const QIcon &icon)
m_data->dragIcon = icon;
}
+void ItemLibraryEntry::setIcon(const QIcon &icon)
+{
+ m_data->icon = icon;
+}
+
QIcon ItemLibraryEntry::dragIcon() const
{
return m_data->dragIcon;
@@ -128,6 +134,11 @@ QString ItemLibraryEntry::qml() const
return m_data->qml;
}
+QString ItemLibraryEntry::requiredImport() const
+{
+ return m_data->requiredImport;
+}
+
int ItemLibraryEntry::majorVersion() const
{
return m_data->majorVersion;
@@ -180,6 +191,11 @@ void ItemLibraryEntry::setQml(const QString &qml)
m_data->qml = qml;
}
+void ItemLibraryEntry::setRequiredImport(const QString &requiredImport)
+{
+ m_data->requiredImport = requiredImport;
+}
+
void ItemLibraryEntry::addProperty(QString &name, QString &type, QString &value)
{
Property property;
@@ -197,6 +213,8 @@ QDataStream& operator<<(QDataStream& stream, const ItemLibraryEntry &itemLibrary
stream << itemLibraryEntry.iconPath();
stream << itemLibraryEntry.category();
stream << itemLibraryEntry.dragIcon();
+ stream << itemLibraryEntry.requiredImport();
+
stream << itemLibraryEntry.m_data->properties;
return stream;
@@ -212,6 +230,8 @@ QDataStream& operator>>(QDataStream& stream, ItemLibraryEntry &itemLibraryEntry)
stream >> itemLibraryEntry.m_data->iconPath;
stream >> itemLibraryEntry.m_data->category;
stream >> itemLibraryEntry.m_data->dragIcon;
+ stream >> itemLibraryEntry.m_data->requiredImport;
+
stream >> itemLibraryEntry.m_data->properties;
return stream;
@@ -237,8 +257,8 @@ QList<ItemLibraryEntry> ItemLibraryInfo::entriesForType(const QString &typeName,
foreach (const ItemLibraryEntry &entry, m_d->nameToEntryHash.values()) {
if (entry.typeName() == typeName
- && entry.majorVersion() == majorVersion
- && entry.minorVersion() == minorVersion)
+ && entry.majorVersion() >= majorVersion
+ && entry.minorVersion() >= minorVersion)
entries += entry;
}
@@ -267,25 +287,25 @@ QList<ItemLibraryEntry> ItemLibraryInfo::entries() const
return list;
}
+static inline QString keyForEntry(const ItemLibraryEntry &entry)
+{
+ return entry.name() + entry.category();
+}
+
void ItemLibraryInfo::addEntry(const ItemLibraryEntry &entry)
{
- if (m_d->nameToEntryHash.contains(entry.name()))
+ const QString key = keyForEntry(entry);
+ if (m_d->nameToEntryHash.contains(key))
throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
- m_d->nameToEntryHash.insert(entry.name(), entry);
+ m_d->nameToEntryHash.insert(key, entry);
emit entriesChanged();
}
-bool ItemLibraryInfo::removeEntry(const QString &name)
+bool ItemLibraryInfo::containsEntry(const ItemLibraryEntry &entry)
{
- if (m_d->nameToEntryHash.remove(name)) {
- emit entriesChanged();
- return true;
- }
- if (m_d->baseInfo)
- return m_d->baseInfo->removeEntry(name);
-
- return false;
+ const QString key = keyForEntry(entry);
+ return m_d->nameToEntryHash.contains(key);
}
void ItemLibraryInfo::clearEntries()
diff --git a/src/plugins/qmldesigner/designercore/metainfo/metainfo.cpp b/src/plugins/qmldesigner/designercore/metainfo/metainfo.cpp
index eb6b1ab154..e21b45a7cd 100644
--- a/src/plugins/qmldesigner/designercore/metainfo/metainfo.cpp
+++ b/src/plugins/qmldesigner/designercore/metainfo/metainfo.cpp
@@ -37,7 +37,6 @@
#include "modelnode.h"
#include "invalidmodelnodeexception.h"
#include "invalidargumentexception.h"
-#include "propertymetainfo.h"
#include "metainfoparser.h"
#include "iwidgetplugin.h"
@@ -47,11 +46,6 @@
#include <QtDebug>
#include <QPair>
#include <QtAlgorithms>
-#include <QMetaProperty>
-#include <QDeclarativeEngine>
-
-#include <private/qdeclarativemetatype_p.h>
-#include <private/qdeclarativeanchors_p.h>
enum {
debug = false
@@ -72,22 +66,9 @@ public:
void clear();
void initialize();
- void loadPlugins(QDeclarativeEngine *engine);
- 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;
-
- QList<QDeclarativeType*> qmlTypes();
- void typeInfo(const QMetaObject *qMetaObject, QString *typeName, int *majorVersion = 0, int *minorVersion = 0) const;
void parseXmlFiles();
- QMultiHash<QString, NodeMetaInfo> m_nodeMetaInfoHash;
- QHash<QString, EnumeratorMetaInfo> m_enumeratorMetaInfoHash;
- QHash<QString, QString> m_QtTypesToQmlTypes;
QScopedPointer<ItemLibraryInfo> m_itemLibraryInfo;
MetaInfo *m_q;
@@ -105,49 +86,16 @@ MetaInfoPrivate::MetaInfoPrivate(MetaInfo *q) :
void MetaInfoPrivate::clear()
{
- m_nodeMetaInfoHash.clear();
- m_enumeratorMetaInfoHash.clear();
m_itemLibraryInfo->clearEntries();
m_isInitialized = false;
}
void MetaInfoPrivate::initialize()
{
- // make sure QmlGraphicsItemsModule gets initialized, that is
- // QmlGraphicsItemsModule::defineModule called
- QDeclarativeEngine engine;
- Q_UNUSED(engine);
-
- loadPlugins(&engine);
- parseQmlTypes();
- parseNonQmlTypes();
parseXmlFiles();
- parseValueTypes();
-
m_isInitialized = true;
}
-void MetaInfoPrivate::loadPlugins(QDeclarativeEngine *engine)
-{
- // hack to load plugins
- QDeclarativeComponent pluginComponent(engine, 0);
-
- QStringList pluginList;
- pluginList += "import Qt 4.7";
- pluginList += "import QtWebKit 1.0";
-
- // load maybe useful plugins
- pluginList += "import Qt.labs.folderlistmodel 1.0";
- pluginList += "import Qt.labs.gestures 1.0";
- pluginList += "import Qt.multimedia 4.7";
- pluginList += "import Qt.labs.particles 1.0";
-
- QString componentString = QString("%1\n Item {}\n").arg(pluginList.join("\n"));
-
-
- pluginComponent.setData(componentString.toLatin1(), QUrl());
-}
-
QString static inline stripPrefix(const QString &typeName)
{
QStringList list = typeName.split('/');
@@ -156,131 +104,6 @@ QString static inline stripPrefix(const QString &typeName)
return typeName;
}
-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()) {
- QMetaEnum qEnumerator = qProperty.enumerator();
- EnumeratorMetaInfo enumerator = m_q->addEnumerator(qEnumerator.scope(), qEnumerator.name());
-
- enumerator.setValid(qEnumerator.isValid());
- enumerator.setIsFlagType(qEnumerator.isFlag());
- QString scope = qEnumerator.scope();
- if (m_QtTypesToQmlTypes.contains(scope))
- scope = stripPrefix(m_QtTypesToQmlTypes.value(scope));
-
- enumerator.setScope(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");
-
- QString typeName;
- int majorVersion = -1;
- int minorVersion = -1;
- typeInfo(qMetaObject, &typeName, &majorVersion, &minorVersion);
-
- if (typeName.isEmpty()) {
- qWarning() << "Meta type system: Registered class has no name.";
- return;
- }
-
- NodeMetaInfo existingInfo = m_q->nodeMetaInfo(typeName, majorVersion, minorVersion);
- if (existingInfo.isValid()
- && existingInfo.majorVersion() == majorVersion
- && existingInfo.minorVersion() == minorVersion) {
- return;
- }
-
- NodeMetaInfo nodeMetaInfo(*m_q);
- nodeMetaInfo.setType(typeName, majorVersion, minorVersion);
- parseProperties(nodeMetaInfo, qMetaObject);
- parseClassInfo(nodeMetaInfo, qMetaObject);
-
- QString superTypeName;
- int superTypeMajorVersion = -1;
- int superTypeMinorVersion = -1;
-
- if (qMetaObject->superClass()) {
- typeInfo(qMetaObject->superClass(), &superTypeName, &superTypeMajorVersion, &superTypeMinorVersion);
- nodeMetaInfo.setSuperClass(superTypeName, superTypeMajorVersion, superTypeMinorVersion);
- }
- if (debug)
- qDebug() << "adding non qml type" << nodeMetaInfo.typeName() << nodeMetaInfo.majorVersion() << nodeMetaInfo.minorVersion()
- << ", parent type" << superTypeName << superTypeMajorVersion << superTypeMinorVersion;
-
- m_q->addNodeInfo(nodeMetaInfo);
-
- if (const QMetaObject *superClass = qMetaObject->superClass())
- parseNonQmlClassRecursively(superClass);
-}
-
-QList<QDeclarativeType*> MetaInfoPrivate::qmlTypes()
-{
- QList<QDeclarativeType*> list;
- foreach (QDeclarativeType *type, QDeclarativeMetaType::qmlTypes()) {
- if (!type->qmlTypeName().startsWith("Bauhaus/")
- && !type->qmlTypeName().startsWith("QmlProject/"))
- list += type;
- }
- return list;
-}
-
-
static inline bool isDepricatedQtType(const QString &typeName)
{
if (typeName.length() < 8)
@@ -289,168 +112,13 @@ static inline bool isDepricatedQtType(const QString &typeName)
return typeName.contains("QtQuick/");
}
-void MetaInfoPrivate::typeInfo(const QMetaObject *qMetaObject, QString *typeName, int *majorVersion, int *minorVersion) const
-{
- Q_ASSERT(typeName);
-
- if (!qMetaObject)
- return;
-
- *typeName = qMetaObject->className();
- int majVersion = -1;
- int minVersion = -1;
- QDeclarativeType *qmlType = QDeclarativeMetaType::qmlType(qMetaObject);
- if (qmlType) {
- if (!qmlType->qmlTypeName().isEmpty()) {
- *typeName = qmlType->qmlTypeName();
- majVersion = qmlType->majorVersion();
- minVersion = qmlType->minorVersion();
- }
- if (isDepricatedQtType(qmlType->qmlTypeName())) { //### todo there has to be an alternative
- QString properTypeName = qmlType->qmlTypeName();
- properTypeName.replace("QtQuick/", "Qt/");
- *typeName = properTypeName;
- majVersion = 1;
- minVersion = 0;
- }
- }
- if (majorVersion)
- *majorVersion = majVersion;
- if (minorVersion)
- *minorVersion = minVersion;
-}
-
-void MetaInfoPrivate::parseValueTypes()
-{
- QStringList valueTypes;
- //there is no global list of all supported value types
- valueTypes << "QFont"
- << "QPoint"
- << "QPointF"
- << "QRect"
- << "QRectF"
- << "QSize"
- << "QSizeF"
- << "QVector3D"
- << "QEasingCurve";
-
- foreach (const QString &type, valueTypes) {
- NodeMetaInfo nodeMetaInfo(*m_q);
- nodeMetaInfo.setType(type, -1, -1);
- 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 == "underline")
- propertyInfo.setType("bool");
- else if (propertyName == "strikeout")
- 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");
- } else if (type == ("QEasingCurve")) {
- if (propertyName == "type") {
- propertyInfo.setEnumType("true");
- propertyInfo.setType("QEasingCurve::Type");
- propertyInfo.setEnumerator(m_q->enumerator("QEasingCurve::Type"));
- }
- }
- propertyInfo.setValid(true);
- propertyInfo.setReadable(true);
- propertyInfo.setWritable(true);
- nodeMetaInfo.addProperty(propertyInfo);
- }
- if (debug)
- qDebug() << "adding value type" << nodeMetaInfo.typeName();
- m_q->addNodeInfo(nodeMetaInfo);
- }
-}
-
-void MetaInfoPrivate::parseQmlTypes()
-{
- foreach (QDeclarativeType *qmlType, qmlTypes()) {
- const QString qtTypeName(qmlType->typeName());
- const QString qmlTypeName(qmlType->qmlTypeName());
-
- if (!isDepricatedQtType(qmlType->qmlTypeName()))
- m_QtTypesToQmlTypes.insert(qtTypeName, qmlTypeName);
- }
- foreach (QDeclarativeType *qmlType, 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;
-
- // we ignore the depricated Qt/ namespace
- if (isDepricatedQtType(qmlType->qmlTypeName()))
- continue;
-
- NodeMetaInfo nodeMetaInfo(*m_q);
- nodeMetaInfo.setType(qmlType->qmlTypeName(), qmlType->majorVersion(), qmlType->minorVersion());
-
- parseProperties(nodeMetaInfo, qMetaObject);
- if (qmlType->baseMetaObject() != qMetaObject) {
- // type is declared with Q_DECLARE_EXTENDED_TYPE
- parseProperties(nodeMetaInfo, qmlType->baseMetaObject());
- }
-
- parseClassInfo(nodeMetaInfo, qMetaObject);
-
- QString superTypeName;
- int superTypeMajorVersion = -1;
- int superTypeMinorVersion = -1;
- if (const QMetaObject *superClassObject = qmlType->baseMetaObject()->superClass())
- typeInfo(superClassObject, &superTypeName, &superTypeMajorVersion, &superTypeMinorVersion);
-
- if (!superTypeName.isEmpty())
- nodeMetaInfo.setSuperClass(superTypeName, superTypeMajorVersion, superTypeMinorVersion);
-
- if (debug) {
- qDebug() << "adding qml type" << nodeMetaInfo.typeName() << nodeMetaInfo.majorVersion() << nodeMetaInfo.minorVersion()
- << ", super class" << superTypeName << superTypeMajorVersion << superTypeMinorVersion;
- }
-
- m_q->addNodeInfo(nodeMetaInfo);
- }
-}
-
-void MetaInfoPrivate::parseNonQmlTypes()
-{
- foreach (QDeclarativeType *qmlType, qmlTypes()) {
- if (qmlType->qmlTypeName().startsWith("Bauhaus/")
- || qmlType->qmlTypeName().startsWith("QmlProject/"))
- continue;
- if (qmlType->metaObject()->superClass())
- parseNonQmlClassRecursively(qmlType->metaObject()->superClass());
- }
-
- parseNonQmlClassRecursively(&QDeclarativeAnchors::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());
}
@@ -468,18 +136,6 @@ 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
*/
/*!
@@ -516,75 +172,6 @@ MetaInfo& MetaInfo::operator=(const MetaInfo &other)
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
-{
- foreach (const NodeMetaInfo &info, m_p->m_nodeMetaInfoHash.values(typeName)) {
- if (info.availableInVersion(majorVersion, minorVersion)) { {
- 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
-{
- NodeMetaInfo returnInfo;
- foreach (const NodeMetaInfo &info, m_p->m_nodeMetaInfoHash.values(typeName)) {
- if (info.availableInVersion(majorVersion, minorVersion)) {
- if (!returnInfo.isValid()
- || returnInfo.majorVersion() < info.majorVersion()
- || (returnInfo.majorVersion() == info.minorVersion()
- && returnInfo.minorVersion() < info.minorVersion()))
- returnInfo = info;
- }
- }
- if (!returnInfo.isValid()
- && !isGlobal())
- return global().nodeMetaInfo(typeName);
-
- return returnInfo;
-}
-
-QString MetaInfo::fromQtTypes(const QString &type) const
-{
- if (m_p->m_QtTypesToQmlTypes.contains(type))
- return m_p->m_QtTypesToQmlTypes.value(type);
- if (!isGlobal())
- return global().fromQtTypes(type);
- return type;
-}
-
-/*!
- \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();
-}
-
ItemLibraryInfo *MetaInfo::itemLibraryInfo() const
{
return m_p->m_itemLibraryInfo.data();
@@ -623,67 +210,6 @@ void MetaInfo::setPluginPaths(const QStringList &paths)
s_pluginDirs = paths;
}
-void MetaInfo::addNodeInfo(NodeMetaInfo &nodeInfo)
-{
- if (nodeInfo.typeName().isEmpty() || nodeInfo.metaInfo() != *this)
- throw new InvalidArgumentException(__LINE__, __FUNCTION__, __FILE__, QLatin1String("nodeInfo"));
-
-
- m_p->m_nodeMetaInfoHash.insertMulti(nodeInfo.typeName(), nodeInfo);
-}
-
-void MetaInfo::removeNodeInfo(NodeMetaInfo &info)
-{
- if (!info.isValid()) {
- qWarning() << "NodeMetaInfo is invalid";
- return;
- }
-
- if (m_p->m_nodeMetaInfoHash.contains(info.typeName())
- && m_p->m_nodeMetaInfoHash.remove(info.typeName(), info)) {
-
- foreach (const ItemLibraryEntry &entry,
- m_p->m_itemLibraryInfo->entriesForType(info.typeName(), info.majorVersion(), info.minorVersion())) {
- m_p->m_itemLibraryInfo->removeEntry(entry.name());
- }
-
- } else if (!isGlobal()) {
- global().removeNodeInfo(info);
- } else {
- Q_ASSERT_X(0, Q_FUNC_INFO, "Node meta info not in db");
- }
-
- info.setInvalid();
-}
-
-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;
-}
-
bool MetaInfo::isGlobal() const
{
return (this->m_p == s_global.m_p);
diff --git a/src/plugins/qmldesigner/designercore/metainfo/metainfoparser.cpp b/src/plugins/qmldesigner/designercore/metainfo/metainfoparser.cpp
index a1d21bdac1..ff0215c8c1 100644
--- a/src/plugins/qmldesigner/designercore/metainfo/metainfoparser.cpp
+++ b/src/plugins/qmldesigner/designercore/metainfo/metainfoparser.cpp
@@ -34,7 +34,6 @@
#include "metainfoparser.h"
#include "metainfo.h"
-#include "propertymetainfo.h"
#include "model/propertyparser.h"
#include <QXmlStreamReader>
#include <QString>
@@ -45,14 +44,6 @@
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)
@@ -94,123 +85,61 @@ 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();
+ const QIcon icon = QIcon(attributes.value("icon").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 {
- nodeMetaInfo = MetaInfo(m_metaInfo);
- nodeMetaInfo.setType(className, 1, 0);
- m_metaInfo.addNodeInfo(nodeMetaInfo);
- qWarning() << "Metainfo: " << className << " does not exist";
- /*while (!reader.atEnd() && !(reader.isEndElement() && reader.name() == "node"))
- reader.readNext();*/
- }
-
- if (attributes.hasAttribute("isContainer")) {
- const QString isContainer = attributes.value("isContainer").toString();
- nodeMetaInfo.setIsContainer(stringToBool(isContainer));
- }
-
- 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();
- handleAbstractPropertyElement(reader, nodeMetaInfo);
- handleAbstractPropertyDefaultValueElement(reader, nodeMetaInfo);
- handleNodeItemLibraryEntryElement(reader, className);
+ handleNodeItemLibraryEntryElement(reader, className, icon);
}
}
-void MetaInfoParser::handleNodeItemLibraryEntryElement(QXmlStreamReader &reader, const QString & className)
+void MetaInfoParser::handleNodeItemLibraryEntryElement(QXmlStreamReader &reader, const QString &className, const QIcon &icon)
{
if (reader.isStartElement() && reader.name() == "itemlibraryentry")
{
+ const QString versionNumber = reader.attributes().value("version").toString();
+
+ int major = 1;
+ int minor = 0;
+
+ if (!versionNumber.isEmpty()) {
+ int val;
+ bool ok;
+ if (versionNumber.contains('.')) {
+ val = versionNumber.split('.').first().toInt(&ok);
+ major = ok ? val : major;
+ val = versionNumber.split('.').last().toInt(&ok);
+ minor = ok ? val : minor;
+ } else {
+ val = versionNumber.toInt(&ok);
+ major = ok ? val : major;
+ }
+ }
+
const QString name = reader.attributes().value("name").toString();
- const NodeMetaInfo typeInfo = m_metaInfo.nodeMetaInfo(className);
ItemLibraryEntry entry;
- entry.setType(typeInfo.typeName(), typeInfo.majorVersion(), typeInfo.minorVersion());
+ entry.setType(className, major, minor);
entry.setName(name);
+ entry.setIcon(icon);
- QString iconPath = reader.attributes().value("icon").toString();
+ QString iconPath = reader.attributes().value("libraryIcon").toString();
if (!iconPath.isEmpty())
entry.setIconPath(iconPath);
@@ -218,6 +147,12 @@ void MetaInfoParser::handleNodeItemLibraryEntryElement(QXmlStreamReader &reader,
if (!category.isEmpty())
entry.setCategory(category);
+ QString requiredImport = reader.attributes().value("requiredImport").toString();
+ if (!requiredImport.isEmpty())
+ entry.setRequiredImport(requiredImport);
+
+ qDebug() << entry.requiredImport();
+
while (!reader.atEnd() && !(reader.isEndElement() && reader.name() == "itemlibraryentry")) {
reader.readNext();
handleItemLibraryEntryPropertyElement(reader, entry);
@@ -241,93 +176,6 @@ void MetaInfoParser::handleItemLibraryEntryPropertyElement(QXmlStreamReader &rea
}
}
-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())
diff --git a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp
index b10395e15b..23d5cd5763 100644
--- a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp
+++ b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp
@@ -34,11 +34,11 @@
#include "nodemetainfo.h"
#include "model.h"
#include "widgetqueryview.h"
-#include "nodeinstance.h"
#include "invalidargumentexception.h"
#include "metainfo.h"
-#include "propertymetainfo.h"
+#include <model.h>
+#include <rewriterview.h>
#include <QSharedData>
#include <QtDebug>
@@ -47,49 +47,26 @@
#include <QDeclarativeEngine>
#include <QDeclarativeComponent>
+#include <qmljs/qmljslookupcontext.h>
+#include <qmljs/qmljsdocument.h>
+#include <qmljs/qmljsinterpreter.h>
+#include <qmljs/qmljsbind.h>
+#include <qmljs/parser/qmljsast_p.h>
#include <private/qdeclarativemetatype_p.h>
+#include <private/qdeclarativestringconverters_p.h>
namespace QmlDesigner {
namespace Internal {
-class NodeMetaInfoData : public QSharedData
+struct TypeDescription
{
-public:
- typedef enum {
- No = -1,
- Unknown = 0,
- Yes = 1,
- } TristateBoolean;
-
-public:
- NodeMetaInfoData(const MetaInfo &metaInfo) :
- metaInfo(metaInfo),
- isContainer(false),
- isFXItem(Unknown),
- icon(),
- category("misc")
- { }
-
- MetaInfo metaInfo;
- QString typeName;
- bool isContainer;
- TristateBoolean isFXItem;
- QHash<QString, PropertyMetaInfo> propertyMetaInfoHash;
- QIcon icon;
- QString category;
- QString qmlFile;
- QString defaultProperty;
-
- QString superClassType;
- int superClassMajorVersion;
- int superClassMinorVersion;
-
- int majorVersion;
+ QString className;
int minorVersion;
+ int majorVersion;
};
-} // namespace Internal
+} //Internal
/*!
\class QmlDesigner::NodeMetaInfo
@@ -108,493 +85,909 @@ NodeMetaInfo object will result in an InvalidMetaInfoException being thrown.
\see QmlDesigner::MetaInfo, QmlDesigner::PropertyMetaInfo, QmlDesigner::EnumeratorMetaInfo
*/
-NodeMetaInfo::NodeMetaInfo()
- : m_data(0)
+namespace Internal {
+
+using namespace QmlJS;
+
+typedef QPair<QString, QString> PropertyInfo;
+
+class PropertyMemberProcessor : public Interpreter::MemberProcessor
{
- // create invalid node
-}
+public:
+ virtual bool processProperty(const QString &name, const Interpreter::Value *value)
+ {
+ const Interpreter::ASTPropertyReference *ref = dynamic_cast<const Interpreter::ASTPropertyReference*>(value);
+ if (ref) {
+ QString type = "unkown";
+ if (ref->ast()->memberType)
+ type = ref->ast()->memberType->asString();
+ m_properties.append(qMakePair(name, type));
+ } else {
+ if (const Interpreter::QmlObjectValue * ov = dynamic_cast<const Interpreter::QmlObjectValue *>(value)) {
+ QString qualifiedTypeName = ov->packageName().isEmpty() ? ov->className() : ov->packageName() + "/" + ov->className();
+ m_properties.append(qMakePair(name, qualifiedTypeName));
+ } else {
+ Interpreter::TypeId typeId;
+ QString typeName = typeId(value);
+ if (typeName == QLatin1String("number")) {
+ if (value->asRealValue()) {
+ typeName = "real";
+ } else {
+ typeName = "int";
+ }
+ }
+ m_properties.append(qMakePair(name, typeName));
+ }
+ }
+ return true;
+ }
-NodeMetaInfo::NodeMetaInfo(const MetaInfo &metaInfo)
- : m_data(new Internal::NodeMetaInfoData(metaInfo))
+ QList<PropertyInfo> properties() const { return m_properties; }
+
+private:
+ QList<PropertyInfo> m_properties;
+};
+
+static inline bool isValueType(const QString &type)
{
+ QStringList objectValuesList;
+ objectValuesList << "QFont" << "QPoint" << "QPointF" << "QSize" << "QSizeF" << "QVector3D" << "QVector2D";
+ return objectValuesList.contains(type);
}
-NodeMetaInfo::~NodeMetaInfo()
+const Interpreter::QmlObjectValue *findQmlPrototype(const Interpreter::ObjectValue *ov, LookupContext *context)
{
+ if (!ov)
+ return 0;
+
+ const Interpreter::QmlObjectValue * qmlValue = dynamic_cast<const Interpreter::QmlObjectValue *>(ov);
+ if (qmlValue)
+ return qmlValue;
+
+ return findQmlPrototype(ov->prototype(context->context()), context);
}
-/*!
- \brief Creates a copy of the handle.
- */
-NodeMetaInfo::NodeMetaInfo(const NodeMetaInfo &other)
- : m_data(other.m_data)
+QStringList prototypes(const Interpreter::ObjectValue *ov, LookupContext::Ptr context, bool versions = false)
{
+ QStringList list;
+ if (!ov)
+ return list;
+ ov = ov->prototype(context->context());
+ while (ov) {
+ const Interpreter::QmlObjectValue * qmlValue = dynamic_cast<const Interpreter::QmlObjectValue *>(ov);
+ if (qmlValue) {
+ if (versions) {
+ list << qmlValue->packageName() + "/" + qmlValue->className() +
+ " " + QString::number(qmlValue->version().majorVersion()) +
+ "." + QString::number(qmlValue->version().minorVersion());
+ } else {
+ list << qmlValue->packageName() + "/" + qmlValue->className();
+ }
+ } else {
+ if (versions) {
+ list << ov->className() + " -1.-1";
+ } else {
+ list << ov->className();
+ }
+ }
+ ov = ov->prototype(context->context());
+ }
+ return list;
}
-/*!
- \brief Copies the handle.
- */
-NodeMetaInfo &NodeMetaInfo::operator=(const NodeMetaInfo &other)
+QList<PropertyInfo> getObjectTypes(const Interpreter::ObjectValue *ov, LookupContext *context, bool local = false);
+
+QList<PropertyInfo> getQmlTypes(const Interpreter::QmlObjectValue *ov, LookupContext *context, bool local = false)
{
- if (this != &other)
- this->m_data = other.m_data;
+ QList<PropertyInfo> list;
+ if (!ov)
+ return list;
- return *this;
+ PropertyMemberProcessor processor;
+ ov->processMembers(&processor);
+
+ QList<PropertyInfo> newList = processor.properties();
+
+ foreach (PropertyInfo property, newList) {
+ QString name = property.first;
+ if (!ov->isWritable(name) && ov->isPointer(name)) {
+ //dot property
+ const Interpreter::QmlObjectValue * qmlValue = dynamic_cast<const Interpreter::QmlObjectValue *>(ov->property(name, context->context()));
+ if (qmlValue) {
+ QList<PropertyInfo> dotProperties = getQmlTypes(qmlValue, context);
+ foreach (const PropertyInfo &propertyInfo, dotProperties) {
+ QString dotName = propertyInfo.first;
+ QString type = propertyInfo.second;
+ dotName = name + '.' + dotName;
+ list.append(qMakePair(dotName, type));
+ }
+ }
+ }
+ if (isValueType(ov->propertyType(name))) {
+ const Interpreter::ObjectValue *dotObjectValue = dynamic_cast<const Interpreter::ObjectValue *>(ov->property(name, context->context()));
+ if (dotObjectValue) {
+ QList<PropertyInfo> dotProperties = getObjectTypes(dotObjectValue, context);
+ foreach (const PropertyInfo &propertyInfo, dotProperties) {
+ QString dotName = propertyInfo.first;
+ QString type = propertyInfo.second;
+ dotName = name + '.' + dotName;
+ list.append(qMakePair(dotName, type));
+ }
+ }
+ }
+ QString type = property.second;
+ if (!ov->isPointer(name) && !ov->isListProperty(name))
+ type = ov->propertyType(name);
+ list.append(qMakePair(name, type));
+ }
+
+ if (!local) {
+ const Interpreter::ObjectValue* prototype = ov->prototype(context->context());
+
+ const Interpreter::QmlObjectValue * qmlObjectValue = dynamic_cast<const Interpreter::QmlObjectValue *>(prototype);
+
+ if (qmlObjectValue) {
+ list << getQmlTypes(qmlObjectValue, context);
+ } else {
+ list << getObjectTypes(prototype, context);
+ }
+ }
+
+ return list;
}
-/*!
- \brief Returns whether the meta information system knows about this type.
- */
-bool NodeMetaInfo::isValid() const
+QList<PropertyInfo> getTypes(const Interpreter::ObjectValue *ov, LookupContext *context, bool local = false)
{
- return (m_data.data() != 0);
+ QList<PropertyInfo> list;
+
+ const Interpreter::QmlObjectValue * qmlObjectValue = dynamic_cast<const Interpreter::QmlObjectValue *>(ov);
+
+ if (qmlObjectValue) {
+ list << getQmlTypes(qmlObjectValue, context, local);
+ } else {
+ list << getObjectTypes(ov, context, local);
+ }
+
+ return list;
}
-MetaInfo NodeMetaInfo::metaInfo() const
+QList<PropertyInfo> getObjectTypes(const Interpreter::ObjectValue *ov, LookupContext *context, bool local)
{
- if (!isValid()) {
- qWarning() << "NodeMetaInfo is invalid";
- return MetaInfo();
+ QList<PropertyInfo> list;
+ if (!ov)
+ return list;
+ PropertyMemberProcessor processor;
+ ov->processMembers(&processor);
+
+ list << processor.properties();
+
+ if (!local) {
+ const Interpreter::ObjectValue* prototype = ov->prototype(context->context());
+
+ const Interpreter::QmlObjectValue * qmlObjectValue = dynamic_cast<const Interpreter::QmlObjectValue *>(prototype);
+
+ if (qmlObjectValue) {
+ list << getQmlTypes(qmlObjectValue, context);
+ } else {
+ list << getObjectTypes(prototype, context);
+ }
}
- return m_data->metaInfo;
+ return list;
}
-/*!
- \brief Returns all (direct and indirect) ancestor types.
-
- \throws InvalidMetaInfoException if the object is not valid
- */
-QList<NodeMetaInfo> NodeMetaInfo::superClasses() const
+class NodeMetaInfoPrivate
{
- if (!isValid()) {
- qWarning() << "NodeMetaInfo is invalid";
- return QList<NodeMetaInfo>();
+public:
+ typedef QSharedPointer<NodeMetaInfoPrivate> Pointer;
+ NodeMetaInfoPrivate();
+ ~NodeMetaInfoPrivate() {}
+
+ bool isValid() const;
+
+ bool isComponent() const
+ {
+ return m_isComponent;
+ }
+
+ QStringList properties() const
+ {
+ return m_properties;
}
- QList<NodeMetaInfo> types;
+ QStringList localProperties() const
+ {
+ return m_localProperties;
+ }
- NodeMetaInfo superType = directSuperClass();
- if (superType.isValid()) {
- types += superType;
- types += superType.superClasses();
+ QString defaultPropertyName() const
+ {
+ return m_defaultPropertyName;
}
- return types;
-}
+ QString propertyType(const QString &propertyName) const;
-/*!
- \brief Returns direct ancestor type. An invalid type if there is none.
- */
-NodeMetaInfo NodeMetaInfo::directSuperClass() const
+ void setupPrototypes();
+ QList<TypeDescription> prototypes() const;
+
+ bool isPropertyWritable(const QString &propertyName) const;
+ bool isPropertyPointer(const QString &propertyName) const;
+ bool isPropertyList(const QString &propertyName) const;
+ bool isPropertyEnum(const QString &propertyName) const;
+ QString propertyEnumScope(const QString &propertyName) const;
+ QStringList keysForEnum(const QString &enumName) const;
+ bool cleverCheckType(const QString &otherType) const;
+ QVariant::Type variantTypeId(const QString &properyName) const;
+
+ int majorVersion() const
+ { return m_majorVersion; }
+
+ int minorVersion() const
+ { return m_minorVersion; }
+
+ QString qualfiedTypeName() const
+ { return m_qualfiedTypeName; }
+
+ Model *model() const
+ { return m_model; }
+
+ QString packageName() const;
+
+ QString componentSource() const;
+ QString componentFileName() const;
+
+ static Pointer create(Model *model, const QString &type, int maj = -1, int min = -1);
+
+ QSet<QString> prototypeCache()
+ {
+ return m_prototypeCache;
+ }
+
+ static void clearCache()
+ {
+ m_nodeMetaInfoCache.clear();
+ }
+
+private:
+ NodeMetaInfoPrivate(Model *model, QString type, int maj = -1, int min = -1);
+
+ const QmlJS::Interpreter::QmlObjectValue *getQmlObjectValue() const;
+ const QmlJS::Interpreter::ObjectValue *getObjectValue() const;
+ void setupPropertyInfo(QList<PropertyInfo> propertyInfos);
+ void setupLocalPropertyInfo(QList<PropertyInfo> propertyInfos);
+ QString lookupName() const;
+ QStringList lookupNameComponent() const;
+ const QmlJS::Interpreter::QmlObjectValue *getNearestQmlObjectValue() const;
+
+ QString m_qualfiedTypeName;
+ int m_majorVersion;
+ int m_minorVersion;
+ bool m_isValid;
+ bool m_isComponent;
+ QStringList m_properties;
+ QStringList m_propertyTypes;
+ QStringList m_localProperties;
+ QString m_defaultPropertyName;
+ QList<TypeDescription> m_prototypes;
+ QSet<QString> m_prototypeCache;
+
+ //storing the pointer would not be save
+ QmlJS::LookupContext *lookupContext() const;
+ QmlJS::Document *document() const;
+
+ QPointer<Model> m_model;
+ static QHash<QString, Pointer> m_nodeMetaInfoCache;
+};
+
+QHash<QString, NodeMetaInfoPrivate::Pointer> NodeMetaInfoPrivate::m_nodeMetaInfoCache;
+
+
+static inline QString stringIdentifier( const QString &type, int maj, int min)
{
- if (!isValid()) {
- qWarning() << "NodeMetaInfo is invalid";
- return NodeMetaInfo();
- }
+ return type + QString::number(maj) + "_" + QString::number(min);
+}
- if (!m_data->superClassType.isEmpty()) {
- int superClassMajorVersion = m_data->superClassMajorVersion;
- int superClassMinorVersion = m_data->superClassMinorVersion;
- if (superClassMajorVersion == -1) {
- // If we don't know the version of the super type, assume that it's the same like our version.
- superClassMajorVersion = majorVersion();
- superClassMinorVersion = minorVersion();
+NodeMetaInfoPrivate::Pointer NodeMetaInfoPrivate::create(Model *model, const QString &type, int maj, int min)
+{
+ if (m_nodeMetaInfoCache.contains(stringIdentifier(type, maj, min))) {
+ const Pointer &info = m_nodeMetaInfoCache.value(stringIdentifier(type, maj, min));
+ if (info->model() == model) {
+ return info;
+ } else {
+ m_nodeMetaInfoCache.clear();
}
- return m_data->metaInfo.nodeMetaInfo(m_data->superClassType,
- superClassMajorVersion, superClassMinorVersion);
}
- return NodeMetaInfo();
+
+ Pointer newData(new NodeMetaInfoPrivate(model, type, maj, min));
+ if (newData->isValid())
+ m_nodeMetaInfoCache.insert(stringIdentifier(type, maj, min), newData);
+ return newData;
}
-/*!
- \brief Returns meta information for all properties, including properties inherited from base types.
+NodeMetaInfoPrivate::NodeMetaInfoPrivate() : m_isValid(false)
+{
- 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
+NodeMetaInfoPrivate::NodeMetaInfoPrivate(Model *model, QString type, int maj, int min) :
+ m_qualfiedTypeName(type), m_majorVersion(maj),
+ m_minorVersion(min), m_isValid(true), m_isComponent(false),
+ m_model(model)
{
- if (!isValid()) {
- qWarning() << "NodeMetaInfo is invalid";
- return QHash<QString,PropertyMetaInfo>();
+ if (!lookupContext()) {
+ m_isValid = false;
+ return;
}
- QHash<QString,PropertyMetaInfo> propertiesInfo;
- propertiesInfo = m_data->propertyMetaInfoHash;
-
- foreach (const NodeMetaInfo &nodeInfo, superClasses()) {
- 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 (const Interpreter::QmlObjectValue *objectValue = getQmlObjectValue()) {
+ setupPropertyInfo(getTypes(objectValue, lookupContext()));
+ setupLocalPropertyInfo(getTypes(objectValue, lookupContext(), true));
+ m_defaultPropertyName = objectValue->defaultPropertyName();
+ setupPrototypes();
+ return;
}
- if (resolveDotSyntax) {
- QHashIterator<QString,PropertyMetaInfo> iter(dotProperties());
- while (iter.hasNext()) {
- iter.next();
- if (!propertiesInfo.contains(iter.key()))
- propertiesInfo.insert(iter.key(), iter.value());
+ m_qualfiedTypeName = m_qualfiedTypeName.split('/').last();
+ if (const Interpreter::ObjectValue *objectValue = getObjectValue()) {
+ if (const Interpreter::QmlObjectValue *qmlValue = dynamic_cast<const Interpreter::QmlObjectValue *>(objectValue)) {
+ m_majorVersion = qmlValue->version().majorVersion();
+ m_minorVersion = qmlValue->version().minorVersion();
+ m_qualfiedTypeName = qmlValue->packageName() + '/' + qmlValue->className();
+ } else {
+ m_isComponent = true;
}
+ setupPropertyInfo(getTypes(objectValue, lookupContext()));
+ setupLocalPropertyInfo(getTypes(objectValue, lookupContext(), true));
+ m_defaultPropertyName = lookupContext()->context()->defaultPropertyName(objectValue);
+ setupPrototypes();
+ return;
}
- return propertiesInfo;
+ m_isValid = false;
}
-/*!
- \brief Returns meta information for all dot properties, including properties inherited from base types.
+const QmlJS::Interpreter::QmlObjectValue *NodeMetaInfoPrivate::getQmlObjectValue() const
+{
+ return lookupContext()->engine()->cppQmlTypes().types().value(lookupName());
+}
- */
-QHash<QString,PropertyMetaInfo> NodeMetaInfo::dotProperties() const
+const QmlJS::Interpreter::ObjectValue *NodeMetaInfoPrivate::getObjectValue() const
{
- if (!isValid()) {
- qWarning() << "NodeMetaInfo is invalid";
- return QHash<QString,PropertyMetaInfo>();
- }
+ return lookupContext()->context()->lookupType(document(), lookupNameComponent());
+}
- QHash<QString,PropertyMetaInfo> propertiesInfo;
+QmlJS::LookupContext *NodeMetaInfoPrivate::lookupContext() const
+{
+ if (m_model && m_model->rewriterView()) {
+ return m_model->rewriterView()->lookupContext();
+ }
+ return 0;
+}
- 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();
+QmlJS::Document *NodeMetaInfoPrivate::document() const
+{
+ if (m_model && m_model->rewriterView()) {
+ return m_model->rewriterView()->document();
+ }
+ return 0;
+}
- NodeMetaInfo nodeInfo(m_data->metaInfo.nodeMetaInfo(m_data->metaInfo.fromQtTypes(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());
- }
- }
- }
+void NodeMetaInfoPrivate::setupLocalPropertyInfo(QList<PropertyInfo> localPropertyInfos)
+{
+ foreach (const PropertyInfo &propertyInfo, localPropertyInfos) {
+ m_localProperties.append(propertyInfo.first);
}
- return propertiesInfo;
}
-/*!
- \brief Returns meta information for a property. An invalid PropertyMetaInfo object if the given property name is unknown.
+void NodeMetaInfoPrivate::setupPropertyInfo(QList<PropertyInfo> propertyInfos)
+{
+ foreach (const PropertyInfo &propertyInfo, propertyInfos) {
+ m_properties.append(propertyInfo.first);
+ m_propertyTypes.append(propertyInfo.second);
+ }
+}
- \throws InvalidMetaInfoException if the object is not valid
- */
-PropertyMetaInfo NodeMetaInfo::property(const QString &propertyName, bool resolveDotSyntax) const
+bool NodeMetaInfoPrivate::isPropertyWritable(const QString &propertyName) const
{
- if (!isValid()) {
- qWarning() << "NodeMetaInfo is invalid";
- return PropertyMetaInfo();
- }
-
- 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(m_data->metaInfo.fromQtTypes(propertyType), majorVersion(), minorVersion());
- if (!nodeInfo.isValid()) {
- qWarning() << "no type info available for" << propertyType;
- break;
- }
- }
+ if (!isValid())
+ return false;
- return PropertyMetaInfo();
- } else {
- PropertyMetaInfo propertyMetaInfo;
+ if (propertyName.contains('.')) {
+ const QString objectName = propertyName.split(".").first();
+ const QString rawPropertyName = propertyName.split(".").last();
+ const QString objectType = propertyType(objectName);
- if (hasLocalProperty(propertyName)) {
- propertyMetaInfo = m_data->propertyMetaInfoHash.value(propertyName, PropertyMetaInfo());
- } else {
- foreach (const NodeMetaInfo &superTypeMetaInfo, superClasses()) {
- Q_ASSERT(superTypeMetaInfo.isValid());
- propertyMetaInfo = superTypeMetaInfo.property(propertyName);
- if (propertyMetaInfo.isValid())
- break;
- }
+ if (isValueType(objectType)) {
+ return true;
}
- return propertyMetaInfo;
+ QSharedPointer<NodeMetaInfoPrivate> objectInfo(create(m_model, objectType));
+ if (objectInfo->isValid())
+ return objectInfo->isPropertyWritable(rawPropertyName);
+ else
+ return true;
}
+
+ const QmlJS::Interpreter::QmlObjectValue *qmlObjectValue = getNearestQmlObjectValue();
+ if (!qmlObjectValue)
+ return true;
+ if (qmlObjectValue->hasProperty(propertyName))
+ return qmlObjectValue->isWritable(propertyName);
+ else
+ return true; //all properties of components are writable
}
-/*!
- \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
+bool NodeMetaInfoPrivate::isPropertyList(const QString &propertyName) const
{
- if (!isValid()) {
- qWarning() << "NodeMetaInfo is invalid";
+ if (!isValid())
return false;
+
+ if (propertyName.contains('.')) {
+ const QString objectName = propertyName.split(".").first();
+ const QString rawPropertyName = propertyName.split(".").last();
+ const QString objectType = propertyType(objectName);
+
+ if (isValueType(objectType)) {
+ return false;
+ }
+
+ QSharedPointer<NodeMetaInfoPrivate> objectInfo(create(m_model, objectType));
+ if (objectInfo->isValid())
+ return objectInfo->isPropertyList(rawPropertyName);
+ else
+ return true;
}
- 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);
+ const QmlJS::Interpreter::QmlObjectValue *qmlObjectValue = getNearestQmlObjectValue();
+ if (!qmlObjectValue)
+ return false;
+ return qmlObjectValue->isListProperty(propertyName);
+}
- if (!propInfo.isValid())
- break;
+bool NodeMetaInfoPrivate::isPropertyPointer(const QString &propertyName) const
+{
+ if (!isValid())
+ return false;
- if (i + 1 == partCount)
- return true;
+ if (propertyName.contains('.')) {
+ const QString objectName = propertyName.split(".").first();
+ const QString rawPropertyName = propertyName.split(".").last();
+ const QString objectType = propertyType(objectName);
- QString propertyType = propInfo.type();
- if (propertyType.right(1) == "*")
- propertyType = propertyType.left(propertyType.size() - 1).trimmed();
- nodeInfo = m_data->metaInfo.nodeMetaInfo(m_data->metaInfo.fromQtTypes(propertyType), majorVersion(), minorVersion());
- if (!nodeInfo.isValid()) {
- qWarning() << "no type info available for" << propertyType;
- break;
- }
+ if (isValueType(objectType)) {
+ return false;
}
+ QSharedPointer<NodeMetaInfoPrivate> objectInfo(create(m_model, objectType));
+ if (objectInfo->isValid())
+ return objectInfo->isPropertyPointer(rawPropertyName);
+ else
+ return true;
+ }
+
+ const QmlJS::Interpreter::QmlObjectValue *qmlObjectValue = getNearestQmlObjectValue();
+ if (!qmlObjectValue)
return false;
- } else {
- return m_data->propertyMetaInfoHash.contains(propertyName);
+ return qmlObjectValue->isPointer(propertyName);
+}
+
+bool NodeMetaInfoPrivate::isPropertyEnum(const QString &propertyName) const
+{
+ if (!isValid())
+ return false;
+
+ if (propertyName.contains('.')) {
+ const QString objectName = propertyName.split(".").first();
+ const QString rawPropertyName = propertyName.split(".").last();
+ const QString objectType = propertyType(objectName);
+
+ if (isValueType(objectType)) {
+ return false;
+ }
+
+ QSharedPointer<NodeMetaInfoPrivate> objectInfo(create(m_model, objectType));
+ if (objectInfo->isValid())
+ return objectInfo->isPropertyEnum(rawPropertyName);
+ else
+ return true;
}
+
+ QList<const Interpreter::ObjectValue *> objects;
+ objects = Interpreter::PrototypeIterator(getNearestQmlObjectValue(), lookupContext()->context()).all();
+
+ //We have to run the prototype chain
+ foreach (const Interpreter::ObjectValue *ov, objects) {
+ if (const Interpreter::QmlObjectValue * qmlValue = dynamic_cast<const Interpreter::QmlObjectValue *>(ov)) {
+ if (qmlValue->isEnum(propertyType(propertyName)))
+ return true;
+ }
+ }
+
+ return false;
}
-/*!
- \brief Returns whether the type has a (inherited or not inherited) property.
+QString NodeMetaInfoPrivate::propertyEnumScope(const QString &propertyName) const
+{
+ if (!isValid())
+ return QString();
+
+ if (propertyName.contains('.')) {
+ const QString objectName = propertyName.split(".").first();
+ const QString rawPropertyName = propertyName.split(".").last();
+ const QString objectType = propertyType(objectName);
+
+ if (isValueType(objectType)) {
+ return QString();
+ }
- \throws InvalidMetaInfoException if the object is not valid
- */
-bool NodeMetaInfo::hasProperty(const QString &propertyName, bool resolveDotSyntax) const
+ QSharedPointer<NodeMetaInfoPrivate> objectInfo(create(m_model, objectType));
+ if (objectInfo->isValid())
+ return objectInfo->propertyEnumScope(rawPropertyName);
+ else
+ return QString();
+ }
+
+ QList<const Interpreter::ObjectValue *> objects;
+ objects = Interpreter::PrototypeIterator(getNearestQmlObjectValue(), lookupContext()->context()).all();
+
+ //We have to run the prototype chain
+ foreach (const Interpreter::ObjectValue *ov, objects) {
+ if (const Interpreter::QmlObjectValue * qmlValue = dynamic_cast<const Interpreter::QmlObjectValue *>(ov)) {
+ if (qmlValue->isEnum(propertyType(propertyName)))
+ return qmlValue->className();
+ }
+ }
+
+ return QString();
+}
+
+bool NodeMetaInfoPrivate::cleverCheckType(const QString &otherType) const
{
- if (!isValid()) {
- qWarning() << "NodeMetaInfo is invalid";
+ if (otherType == qualfiedTypeName())
+ return true;
+
+ if (isComponent())
return false;
+ QStringList split = otherType.split('/');
+ QString package;
+ QString typeName = otherType;
+ if (split.count() > 1) {
+ package = split.first();
+ typeName = split.at(1);
}
+ if (packageName() == package)
+ return QString(package + "/" + typeName) == qualfiedTypeName();
- if (hasLocalProperty(propertyName, resolveDotSyntax))
- return true;
+ const QString convertedName = getQmlObjectValue()->nameInPackage(package);
+ return QString(package + "/" + typeName) == QString(package + "/" + convertedName);
+}
- if (directSuperClass().isValid() && directSuperClass().hasProperty(propertyName, resolveDotSyntax))
- return true;
+QVariant::Type NodeMetaInfoPrivate::variantTypeId(const QString &properyName) const
+{
+ QString typeName = propertyType(properyName);
+ if (typeName == "string")
+ return QVariant::String;
- return false;
+ if (typeName == "color")
+ return QVariant::Color;
+
+ if (typeName == "int")
+ return QVariant::Int;
+
+ if (typeName == "url")
+ return QVariant::Url;
+
+ if (typeName == "real")
+ return QVariant::Double;
+
+ if (typeName == "bool")
+ return QVariant::Bool;
+
+ if (typeName == "boolean")
+ return QVariant::Bool;
+
+ if (typeName == "date")
+ return QVariant::Date;
+
+ if (typeName == "alias")
+ return QVariant::UserType;
+
+ if (typeName == "var")
+ return QVariant::UserType;
+
+ return QVariant::nameToType(typeName.toLatin1().data());
}
-void NodeMetaInfo::addProperty(const PropertyMetaInfo &property)
+
+QStringList NodeMetaInfoPrivate::keysForEnum(const QString &enumName) const
{
- if (!isValid()) {
- qWarning() << "NodeMetaInfo is invalid";
- return;
+ if (!isValid())
+ return QStringList();
+
+ return getNearestQmlObjectValue()->keysForEnum(enumName);
+}
+
+QString NodeMetaInfoPrivate::packageName() const
+{
+ if (!isComponent())
+ return getQmlObjectValue()->packageName();
+ return QString();
+}
+
+QString NodeMetaInfoPrivate::componentSource() const
+{
+ if (isComponent()) {
+ const Interpreter::ASTObjectValue * astObjectValue = dynamic_cast<const Interpreter::ASTObjectValue *>(getObjectValue());
+ if (astObjectValue)
+ return astObjectValue->document()->source().mid(astObjectValue->typeName()->identifierToken.begin(),
+ astObjectValue->initializer()->rbraceToken.end());
}
+ return QString();
+}
- m_data->propertyMetaInfoHash.insert(property.name(), property);
+QString NodeMetaInfoPrivate::componentFileName() const
+{
+ if (isComponent()) {
+ const Interpreter::ASTObjectValue * astObjectValue = dynamic_cast<const Interpreter::ASTObjectValue *>(getObjectValue());
+ if (astObjectValue) {
+ QString fileName;
+ int line;
+ int column;
+ if (astObjectValue->getSourceLocation(&fileName, &line, &column))
+ return fileName;
+ }
+ }
+ return QString();
}
-/*!
- \brief Returns the name of the qml type.
- This is not necessarily the class name: E.g. the class defining "Item" is QDeclarativeItem.
+QString NodeMetaInfoPrivate::lookupName() const
+{
+ QString tempString = m_qualfiedTypeName;
+ tempString.replace('/', '.');
+ if (!tempString.contains('.'))
+ tempString.prepend('.');
+ tempString.append(' ');
- \throws InvalidMetaInfoException if the object is not valid
- */
-QString NodeMetaInfo::typeName() const
+ tempString.append(QString::number(m_majorVersion));
+ tempString.append('.');
+ tempString.append(QString::number(m_minorVersion));
+
+ return tempString;
+}
+
+QStringList NodeMetaInfoPrivate::lookupNameComponent() const
{
- if (!isValid()) {
+ QString tempString = m_qualfiedTypeName;
+ tempString.replace('/', '.');
+
+ return tempString.split(".");
+}
+
+bool NodeMetaInfoPrivate::isValid() const
+{
+ return m_isValid && lookupContext() && document();
+}
+
+QString NodeMetaInfoPrivate::propertyType(const QString &propertyName) const
+{
+ if (!m_properties.contains(propertyName))
return QString();
+ return m_propertyTypes.at(m_properties.indexOf(propertyName));
+}
+
+void NodeMetaInfoPrivate::setupPrototypes()
+{
+ QList<const Interpreter::ObjectValue *> objects;
+ if (m_isComponent)
+ objects = Interpreter::PrototypeIterator(getObjectValue(), lookupContext()->context()).all();
+ else
+ objects = Interpreter::PrototypeIterator(getQmlObjectValue(), lookupContext()->context()).all();
+ foreach (const Interpreter::ObjectValue *ov, objects) {
+ TypeDescription description;
+ description.className = ov->className();
+ description.minorVersion = -1;
+ description.majorVersion = -1;
+ if (const Interpreter::QmlObjectValue * qmlValue = dynamic_cast<const Interpreter::QmlObjectValue *>(ov)) {
+ description.minorVersion = qmlValue->version().minorVersion();
+ description.majorVersion = qmlValue->version().majorVersion();
+ if (!qmlValue->packageName().isEmpty())
+ description.className = qmlValue->packageName() + "/" + description.className;
+ }
+ m_prototypes.append(description);
}
- 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
+QList<TypeDescription> NodeMetaInfoPrivate::prototypes() const
{
- if (!isValid()) {
- return -1;
- }
+ return m_prototypes;
+}
- return m_data->majorVersion;
+const QmlJS::Interpreter::QmlObjectValue *NodeMetaInfoPrivate::getNearestQmlObjectValue() const
+{
+ if (m_isComponent)
+ return findQmlPrototype(getObjectValue(), lookupContext());
+ return getQmlObjectValue();
}
+} //namespace Internal
-/*!
- \brief Returns the name of the minor number of the qml type to which the type is used.
+NodeMetaInfo::NodeMetaInfo() : m_privateData(new Internal::NodeMetaInfoPrivate())
+{
- \throws InvalidMetaInfoException if the object is not valid
-*/
-int NodeMetaInfo::minorVersion() const
+}
+
+NodeMetaInfo::NodeMetaInfo(Model *model, QString type, int maj, int min) : m_privateData(Internal::NodeMetaInfoPrivate::create(model, type, maj, min))
{
- if (!isValid()) {
- return -1;
- }
- return m_data->minorVersion;
}
-bool NodeMetaInfo::availableInVersion(int majorVersion, int minorVersion) const
+NodeMetaInfo::~NodeMetaInfo()
{
- return ((majorVersion > m_data->majorVersion)
- || (majorVersion == m_data->majorVersion && minorVersion >= m_data->minorVersion))
- || (majorVersion == -1 && minorVersion == -1);
}
-bool NodeMetaInfo::hasDefaultProperty() const
+NodeMetaInfo::NodeMetaInfo(const NodeMetaInfo &other)
+ : m_privateData(other.m_privateData)
{
- if (!isValid()) {
- return false;
- }
+}
+
+NodeMetaInfo &NodeMetaInfo::operator=(const NodeMetaInfo &other)
+{
+ if (this != &other)
+ this->m_privateData = other.m_privateData;
- return !m_data->defaultProperty.isNull();
+ return *this;
}
-QString NodeMetaInfo::defaultProperty() const
+bool NodeMetaInfo::isValid() const
{
- if (!isValid()) {
- return QString();
- }
+ return m_privateData->isValid();
+}
- return m_data->defaultProperty;
+bool NodeMetaInfo::isComponent() const
+{
+ return m_privateData->isComponent();
}
-void NodeMetaInfo::setDefaultProperty(const QString &defaultProperty)
+bool NodeMetaInfo::hasProperty(const QString &propertyName) const
{
- if (!isValid()) {
- return;
- }
+ return propertyNames().contains(propertyName);
+}
- m_data->defaultProperty = defaultProperty;
+QStringList NodeMetaInfo::propertyNames() const
+{
+ return m_privateData->properties();
}
-void NodeMetaInfo::setSuperClass(const QString &typeName, int majorVersion, int minorVersion)
+QStringList NodeMetaInfo::directPropertyNames() const
{
- if (!isValid()) {
- return;
- }
- m_data->superClassType = typeName;
- m_data->superClassMajorVersion = majorVersion;
- m_data->superClassMinorVersion = minorVersion;
+ return m_privateData->localProperties();
}
-void NodeMetaInfo::setInvalid()
+QString NodeMetaInfo::defaultPropertyName() const
{
- if (!isValid())
- return;
+ return m_privateData->defaultPropertyName();
+}
- m_data = 0;
+bool NodeMetaInfo::hasDefaultProperty() const
+{
+ return !defaultPropertyName().isEmpty();
}
-void NodeMetaInfo::setType(const QString &typeName, int majorVersion, int minorVersion)
+QString NodeMetaInfo::propertyTypeName(const QString &propertyName) const
{
- if (!isValid()) {
- qWarning() << "NodeMetaInfo is invalid";
- return;
- }
- m_data->typeName = typeName;
- m_data->majorVersion = majorVersion;
- m_data->minorVersion = minorVersion;
+ return m_privateData->propertyType(propertyName);
}
-uint qHash(const NodeMetaInfo &nodeMetaInfo)
+bool NodeMetaInfo::propertyIsWritable(const QString &propertyName) const
{
- if (!nodeMetaInfo.isValid())
- return 0;
- return qHash(nodeMetaInfo.m_data->typeName);
+ return m_privateData->isPropertyWritable(propertyName);
}
-bool operator==(const NodeMetaInfo &firstNodeInfo,
- const NodeMetaInfo &secondNodeInfo)
+bool NodeMetaInfo::propertyIsListProperty(const QString &propertyName) const
{
- if (!firstNodeInfo.isValid() || !secondNodeInfo.isValid())
- return false;
- return firstNodeInfo.m_data->typeName == secondNodeInfo.m_data->typeName;
+ return m_privateData->isPropertyList(propertyName);
}
-/*!
- \brief Returns whether objects of these type can have children.
+bool NodeMetaInfo::propertyIsEnumType(const QString &propertyName) const
+{
+ return m_privateData->isPropertyEnum(propertyName);
+}
- \throws InvalidMetaInfoException if the object is not valid
- */
-bool NodeMetaInfo::isContainer() const
+QString NodeMetaInfo::propertyEnumScope(const QString &propertyName) const
{
- // TODO KAI: Is this too generic?
- if (!isValid()) {
- qWarning() << "NodeMetaInfo is invalid";
- return false;
- }
- return m_data->isContainer;
+ return m_privateData->propertyEnumScope(propertyName);
}
-void NodeMetaInfo::setIsContainer(bool isContainer)
+QStringList NodeMetaInfo::propertyKeysForEnum(const QString &propertyName) const
{
- if (!isValid()) {
- qWarning() << "NodeMetaInfo is invalid";
- return;
- }
- m_data->isContainer = isContainer;
+ return m_privateData->keysForEnum(propertyTypeName(propertyName));
}
-QString NodeMetaInfo::componentString() const
+QVariant NodeMetaInfo::propertyCastedValue(const QString &propertyName, const QVariant &value) const
{
- if (!isValid()) {
- qWarning() << "NodeMetaInfo is invalid";
- return QString();
+
+ QVariant variant = value;
+ if (propertyIsEnumType(propertyName)) {
+ return variant;
}
- return m_data->qmlFile;
+
+ const QString typeName = propertyTypeName(propertyName);
+
+ QVariant::Type typeId = m_privateData->variantTypeId(propertyName);
+
+ if (variant.type() == QVariant::UserType && variant.userType() == ModelNode::variantUserType()) {
+ return variant;
+ } else if (typeId == QVariant::UserType && typeName == QLatin1String("QVariant")) {
+ return variant;
+ } else if (typeId == QVariant::UserType && typeName == QLatin1String("variant")) {
+ return variant;
+ } else if (typeId == QVariant::UserType && typeName == 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 (typeName == "var" || typeName == "variant") {
+ return variant;
+ } else if (typeName == "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 QDeclarativeStringConverters::variantFromString(variant.toString());
+
}
-QIcon NodeMetaInfo::icon() const
+QList<NodeMetaInfo> NodeMetaInfo::superClasses() const
{
- if (!isValid()) {
- qWarning() << "NodeMetaInfo is invalid";
- return QIcon();
+ QList<NodeMetaInfo> list;
+
+ foreach (const Internal::TypeDescription &type, m_privateData->prototypes()) {
+ list.append(NodeMetaInfo(m_privateData->model(), type.className, type.majorVersion, type.minorVersion));
}
- return m_data->icon;
+ return list;
}
-void NodeMetaInfo::setIcon(const QIcon &icon)
+NodeMetaInfo NodeMetaInfo::directSuperClass() const
{
- if (!isValid()) {
- qWarning() << "NodeMetaInfo is invalid";
- return;
- }
- m_data->icon = icon;
+ QList<NodeMetaInfo> superClassesList = superClasses();
+ if (superClassesList.count() > 1)
+ return superClassesList.at(1);
+ return NodeMetaInfo();
}
-bool NodeMetaInfo::isComponent() const
+QString NodeMetaInfo::typeName() const
{
- if (!isValid()) {
- qWarning() << "NodeMetaInfo is invalid";
- return false;
- }
+ return m_privateData->qualfiedTypeName();
+}
+int NodeMetaInfo::majorVersion() const
+{
+ return m_privateData->majorVersion();
+}
+int NodeMetaInfo::minorVersion() const
+{
+ return m_privateData->minorVersion();
+}
- return !m_data->qmlFile.isEmpty();
+QString NodeMetaInfo::componentSource() const
+{
+ return m_privateData->componentSource();
}
-/*!
- \brief Returns whether the type inherits from a type.
+QString NodeMetaInfo::componentFileName() const
+{
+ return NodeMetaInfo::m_privateData->componentFileName();
+}
+
+bool NodeMetaInfo::availableInVersion(int majorVersion, int minorVersion) const
+{
+ return ((majorVersion > m_privateData->majorVersion())
+ || (majorVersion == m_privateData->majorVersion() && minorVersion >= m_privateData->minorVersion()))
+ || (majorVersion == -1 && minorVersion == -1);
+}
- \throws InvalidMetaInfoException if the object is not valid
- */
bool NodeMetaInfo::isSubclassOf(const QString &type, int majorVersion, int minorVersion) const
{
if (!isValid()) {
@@ -606,45 +999,22 @@ bool NodeMetaInfo::isSubclassOf(const QString &type, int majorVersion, int minor
&& availableInVersion(majorVersion, minorVersion))
return true;
+ if (m_privateData->prototypeCache().contains(Internal::stringIdentifier(type, majorVersion, minorVersion)))
+ return true; //take a shortcut - optimization
+
foreach (const NodeMetaInfo &superClass, superClasses()) {
- if (superClass.typeName() == type
- && superClass.availableInVersion(majorVersion, minorVersion))
+ if (superClass.m_privateData->cleverCheckType(type)
+ && superClass.availableInVersion(majorVersion, minorVersion)) {
+ m_privateData->prototypeCache().insert(Internal::stringIdentifier(type, majorVersion, minorVersion));
return true;
+ }
}
return false;
}
-void NodeMetaInfo::setQmlFile(const QString &filePath)
+void NodeMetaInfo::clearCache()
{
- if (!isValid()) {
- qWarning() << "NodeMetaInfo is invalid";
- return;
- }
- 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;
-//}
+ Internal::NodeMetaInfoPrivate::clearCache();
+}
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/metainfo/propertymetainfo.cpp b/src/plugins/qmldesigner/designercore/metainfo/propertymetainfo.cpp
deleted file mode 100644
index c2a5e82775..0000000000
--- a/src/plugins/qmldesigner/designercore/metainfo/propertymetainfo.cpp
+++ /dev/null
@@ -1,447 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#include "propertymetainfo.h"
-
-#include <QSharedData>
-
-#include "invalidmetainfoexception.h"
-#include "metainfo.h"
-#include "modelnode.h"
-
-#include <private/qdeclarativevaluetype_p.h>
-#include <private/qdeclarativestringconverters_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__);
- }
-
- QScopedPointer<QDeclarativeValueType> valueType(QDeclarativeValueTypeFactory::valueType(variantTypeId()));
- return valueType;
-}
-
-/*!
- \brief Returns whether the propery is a QDeclarativeList.
- */
-bool PropertyMetaInfo::isListProperty() const
-{
- if (!isValid()) {
- Q_ASSERT_X(isValid(), Q_FUNC_INFO, "");
- throw InvalidMetaInfoException(__LINE__, Q_FUNC_INFO, __FILE__);
- }
-
- return type().contains("QDeclarativeList") ||
- type().contains("alias"); //### this is a nasty hack - we have to get instances in to resolve this properly
-}
-
-/*!
- \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 QDeclarativeStringConverters::variantFromString(variant.toString());
-}
-
-}
diff --git a/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp b/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp
index f19656fff9..9b97d1060b 100644
--- a/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp
+++ b/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp
@@ -119,7 +119,6 @@ SubComponentManagerPrivate::SubComponentManagerPrivate(MetaInfo metaInfo, SubCom
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 QDeclarativeDomImport &import)
@@ -169,7 +168,6 @@ void SubComponentManagerPrivate::removeImport(int pos)
foreach (const QFileInfo &monitoredFile, watchedFiles(canonicalDirPath)) {
if (!m_dirToQualifier.contains(canonicalDirPath))
- m_watcher.removePath(monitoredFile.filePath());
unregisterQmlFile(monitoredFile, import.qualifier());
}
} else {
@@ -256,14 +254,12 @@ void SubComponentManagerPrivate::parseDirectory(const QString &canonicalDirPath,
}
// oldFileInfo > newFileInfo
parseFile(newFileInfo.filePath(), addToLibrary, qualification);
- m_watcher.addPath(oldFileInfo.filePath());
++newIter;
}
while (oldIter != monitoredList.constEnd()) {
foreach (const QString &qualifier, m_dirToQualifier.value(canonicalDirPath))
unregisterQmlFile(*oldIter, qualifier);
- m_watcher.removePath(oldIter->filePath());
++oldIter;
}
@@ -271,7 +267,6 @@ void SubComponentManagerPrivate::parseDirectory(const QString &canonicalDirPath,
parseFile(newIter->filePath(), addToLibrary, qualification);
if (debug)
qDebug() << "m_watcher.addPath(" << newIter->filePath() << ')';
- m_watcher.addPath(newIter->filePath());
++newIter;
}
}
@@ -323,11 +318,6 @@ void SubComponentManagerPrivate::unregisterQmlFile(const QFileInfo &fileInfo, co
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);
- }
}
static inline bool isDepricatedQtType(const QString &typeName)
@@ -340,7 +330,7 @@ static inline bool isDepricatedQtType(const QString &typeName)
void SubComponentManagerPrivate::registerQmlFile(const QFileInfo &fileInfo, const QString &qualifier,
- const QDeclarativeDomDocument &document, bool addToLibrary)
+ const QDeclarativeDomDocument &, bool addToLibrary)
{
QString componentName = fileInfo.baseName();
@@ -354,66 +344,16 @@ void SubComponentManagerPrivate::registerQmlFile(const QFileInfo &fileInfo, cons
if (debug)
qDebug() << "SubComponentManager" << __FUNCTION__ << componentName;
- if (m_metaInfo.hasNodeMetaInfo(componentName) && addToLibrary) {
- NodeMetaInfo nodeInfo = m_metaInfo.nodeMetaInfo(componentName);
- m_metaInfo.removeNodeInfo(nodeInfo);
- }
-
- const QDeclarativeDomObject rootObject = document.rootObject();
-
- NodeMetaInfo nodeInfo(m_metaInfo);
- nodeInfo.setType(componentName, -1, -1);
- nodeInfo.setQmlFile(fileInfo.filePath());
- if (!isDepricatedQtType(rootObject.objectType())) {
- nodeInfo.setSuperClass(rootObject.objectType(),
- rootObject.objectTypeMajorVersion(),
- rootObject.objectTypeMinorVersion());
- } else {
- QString properClassName = rootObject.objectType();
- properClassName.replace("QtQuick/", "Qt/");
- nodeInfo.setSuperClass(properClassName,
- 1,
- 0);
- }
-
if (addToLibrary) {
// Add file components to the library
ItemLibraryEntry itemLibraryEntry;
- itemLibraryEntry.setType(nodeInfo.typeName(), nodeInfo.majorVersion(), nodeInfo.minorVersion());
+ itemLibraryEntry.setType(componentName, -1, -1);
itemLibraryEntry.setName(componentName);
- itemLibraryEntry.setCategory(tr("QML Components"));
- m_metaInfo.itemLibraryInfo()->addEntry(itemLibraryEntry);
- }
-
- m_metaInfo.addNodeInfo(nodeInfo);
-
- //document.rootObject().d
-
- foreach (const QDeclarativeDomDynamicProperty &dynamicProperty, document.rootObject().dynamicProperties()) {
- Q_ASSERT(!dynamicProperty.propertyName().isEmpty());
- Q_ASSERT(!dynamicProperty.propertyTypeName().isEmpty());
-
- if (dynamicProperty.isDefaultProperty())
- nodeInfo.setDefaultProperty(dynamicProperty.propertyName());
-
- PropertyMetaInfo propertyMetaInfo;
- propertyMetaInfo.setName(dynamicProperty.propertyName());
- propertyMetaInfo.setType(dynamicProperty.propertyTypeName());
- propertyMetaInfo.setValid(true);
- propertyMetaInfo.setReadable(true);
- propertyMetaInfo.setWritable(true);
-
- QDeclarativeDomProperty defaultValue = dynamicProperty.defaultValue();
- if (defaultValue.value().isLiteral()) {
- QVariant defaultValueVariant(defaultValue.value().toLiteral().literal());
- defaultValueVariant.convert((QVariant::Type) dynamicProperty.propertyType());
- propertyMetaInfo.setDefaultValue(nodeInfo, defaultValueVariant);
- }
+ itemLibraryEntry.setCategory("QML Components");
- nodeInfo.addProperty(propertyMetaInfo);
+ if (!m_metaInfo.itemLibraryInfo()->containsEntry(itemLibraryEntry))
+ m_metaInfo.itemLibraryInfo()->addEntry(itemLibraryEntry);
}
- if (!nodeInfo.hasDefaultProperty())
- nodeInfo.setDefaultProperty(nodeInfo.directSuperClass().defaultProperty());
}
} // namespace Internal
@@ -495,7 +435,6 @@ void SubComponentManager::update(const QUrl &filePath, const QList<QDeclarativeD
}
if (!newDir.filePath().isEmpty()) {
- m_d->m_watcher.addPath(newDir.filePath());
m_d->m_dirToQualifier.insertMulti(newDir.canonicalFilePath(), QString());
}
}
diff --git a/src/plugins/qmldesigner/designercore/model/abstractproperty.cpp b/src/plugins/qmldesigner/designercore/model/abstractproperty.cpp
index f6891ea524..83e685e159 100644
--- a/src/plugins/qmldesigner/designercore/model/abstractproperty.cpp
+++ b/src/plugins/qmldesigner/designercore/model/abstractproperty.cpp
@@ -229,20 +229,11 @@ 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, true);
-}
-
-/*!
\brief returns whether 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;
+ return ModelNode(m_internalNode, m_model.data(), view()).metaInfo().defaultPropertyName() == m_propertyName;
}
VariantProperty AbstractProperty::toVariantProperty() const
diff --git a/src/plugins/qmldesigner/designercore/model/abstractview.cpp b/src/plugins/qmldesigner/designercore/model/abstractview.cpp
index 8bf197d58c..9cf2104d39 100644
--- a/src/plugins/qmldesigner/designercore/model/abstractview.cpp
+++ b/src/plugins/qmldesigner/designercore/model/abstractview.cpp
@@ -338,6 +338,16 @@ bool AbstractView::hasId(const QString &id) const
return model()->m_d->hasId(id);
}
+ModelNode AbstractView::modelNodeForInternalId(qint32 internalId)
+{
+ return ModelNode(model()->m_d->nodeForInternalId(internalId), model(), this);
+}
+
+bool AbstractView::hasModelNodeForInternalId(qint32 internalId) const
+{
+ return model()->m_d->hasNodeForInternalId(internalId);
+}
+
QmlModelView *AbstractView::toQmlModelView()
{
return qobject_cast<QmlModelView*>(this);
@@ -387,6 +397,12 @@ void AbstractView::emitInstancePropertyChange(const QList<QPair<ModelNode, QStri
model()->m_d->notifyInstancePropertyChange(propertyList);
}
+void AbstractView::emitInstancesCompleted(const QVector<ModelNode> &nodeVector)
+{
+ if (model() && nodeInstanceView() == this)
+ model()->m_d->notifyInstancesCompleted(nodeVector);
+}
+
void AbstractView::changeRootNodeType(const QString &type, int majorVersion, int minorVersion)
{
Internal::WriteLocker locker(m_model.data());
diff --git a/src/plugins/qmldesigner/designercore/model/basetexteditmodifier.cpp b/src/plugins/qmldesigner/designercore/model/basetexteditmodifier.cpp
index 270d409650..280208156e 100644
--- a/src/plugins/qmldesigner/designercore/model/basetexteditmodifier.cpp
+++ b/src/plugins/qmldesigner/designercore/model/basetexteditmodifier.cpp
@@ -74,7 +74,7 @@ int BaseTextEditModifier::indentDepth() const
bool BaseTextEditModifier::renameId(const QString &oldId, const QString &newId)
{
- if (QmlJSEditor::Internal::QmlJSTextEditor *qmljse = qobject_cast<QmlJSEditor::Internal::QmlJSTextEditor*>(plainTextEdit())) {
+ if (QmlJSEditor::QmlJSTextEditor *qmljse = qobject_cast<QmlJSEditor::QmlJSTextEditor*>(plainTextEdit())) {
qmljse->renameId(oldId, newId);
return true;
} else {
diff --git a/src/plugins/qmldesigner/designercore/model/bindingproperty.cpp b/src/plugins/qmldesigner/designercore/model/bindingproperty.cpp
index 29d5309ef4..2697c78289 100644
--- a/src/plugins/qmldesigner/designercore/model/bindingproperty.cpp
+++ b/src/plugins/qmldesigner/designercore/model/bindingproperty.cpp
@@ -201,7 +201,6 @@ QList<ModelNode> BindingProperty::resolveToModelNodeList() const
}
void BindingProperty::setDynamicTypeNameAndExpression(const QString &typeName, const QString &expression)
-
{
Internal::WriteLocker locker(model());
if (!isValid())
diff --git a/src/plugins/qmldesigner/designercore/model/import.cpp b/src/plugins/qmldesigner/designercore/model/import.cpp
index e3e9fe285a..8edde3bc5f 100644
--- a/src/plugins/qmldesigner/designercore/model/import.cpp
+++ b/src/plugins/qmldesigner/designercore/model/import.cpp
@@ -37,26 +37,27 @@
namespace QmlDesigner {
-Import Import::createLibraryImport(const QString &url, const QString &version, const QString &alias)
+Import Import::createLibraryImport(const QString &url, const QString &version, const QString &alias, const QStringList &importPaths)
{
- return Import(url, QString(), version, alias);
+ return Import(url, QString(), version, alias, importPaths);
}
-Import Import::createFileImport(const QString &file, const QString &version, const QString &alias)
+Import Import::createFileImport(const QString &file, const QString &version, const QString &alias, const QStringList &importPaths)
{
- return Import(QString(), file, version, alias);
+ return Import(QString(), file, version, alias, importPaths);
}
Import Import::empty()
{
- return Import(QString(), QString(), QString(), QString());
+ return Import(QString(), QString(), QString(), QString(), QStringList());
}
-Import::Import(const QString &url, const QString &file, const QString &version, const QString &alias):
+Import::Import(const QString &url, const QString &file, const QString &version, const QString &alias, const QStringList &importPaths):
m_url(url),
m_file(file),
m_version(version),
- m_alias(alias)
+ m_alias(alias),
+ m_importPathList(importPaths)
{
}
diff --git a/src/plugins/qmldesigner/designercore/model/internalnode.cpp b/src/plugins/qmldesigner/designercore/model/internalnode.cpp
index 1d7953458f..263474bd9a 100644
--- a/src/plugins/qmldesigner/designercore/model/internalnode.cpp
+++ b/src/plugins/qmldesigner/designercore/model/internalnode.cpp
@@ -54,22 +54,24 @@ namespace Internal {
InternalNode::InternalNode() :
m_majorVersion(0),
m_minorVersion(0),
- m_valid(false)
+ m_valid(false),
+ m_internalId(-1)
{
}
-InternalNode::InternalNode(const QString &typeName,int majorVersion, int minorVersion):
+InternalNode::InternalNode(const QString &typeName,int majorVersion, int minorVersion, qint32 internalId):
m_typeName(typeName),
m_majorVersion(majorVersion),
m_minorVersion(minorVersion),
- m_valid(true)
+ m_valid(true),
+ m_internalId(internalId)
{
}
-InternalNode::Pointer InternalNode::create(const QString &type,int majorVersion, int minorVersion)
+InternalNode::Pointer InternalNode::create(const QString &type,int majorVersion, int minorVersion, qint32 internalId)
{
- InternalNode *newPointer(new InternalNode(type, majorVersion, minorVersion));
+ InternalNode *newPointer(new InternalNode(type, majorVersion, minorVersion, internalId));
InternalNode::Pointer smartPointer(newPointer);
newPointer->setInternalWeakPointer(smartPointer);
@@ -162,7 +164,10 @@ void InternalNode::setId(const QString& id)
uint qHash(const InternalNodePointer& node)
{
- return ::qHash(node.data());
+ if (node.isNull())
+ return ::qHash(-1);
+
+ return ::qHash(node->internalId());
}
QVariant InternalNode::auxiliaryData(const QString &name) const
@@ -314,7 +319,13 @@ QList<InternalNode::Pointer> InternalNode::allDirectSubNodes() const
bool operator <(const InternalNode::Pointer &firstNode, const InternalNode::Pointer &secondNode)
{
- return firstNode.data() < secondNode.data();
+ if (firstNode.isNull())
+ return true;
+
+ if (secondNode.isNull())
+ return false;
+
+ return firstNode->internalId() < secondNode->internalId();
}
void InternalNode::setScriptFunctions(const QStringList &scriptFunctionList)
@@ -327,5 +338,10 @@ QStringList InternalNode::scriptFunctions() const
return m_scriptFunctionList;
}
+qint32 InternalNode::internalId() const
+{
+ return m_internalId;
+}
+
}
}
diff --git a/src/plugins/qmldesigner/designercore/model/internalnode_p.h b/src/plugins/qmldesigner/designercore/model/internalnode_p.h
index 92f41479b4..e2cbd43cfb 100644
--- a/src/plugins/qmldesigner/designercore/model/internalnode_p.h
+++ b/src/plugins/qmldesigner/designercore/model/internalnode_p.h
@@ -68,7 +68,7 @@ public:
explicit InternalNode();
- static Pointer create(const QString &typeName, int majorVersion, int minorVersion);
+ static Pointer create(const QString &typeName, int majorVersion, int minorVersion, qint32 internalId);
QString type() const;
void setType(const QString &newType);
@@ -120,11 +120,13 @@ public:
void setScriptFunctions(const QStringList &scriptFunctionList);
QStringList scriptFunctions() const;
+ qint32 internalId() const;
+
protected:
Pointer internalPointer() const;
void setInternalWeakPointer(const Pointer &pointer);
void removeProperty(const QString &name);
- explicit InternalNode(const QString &type, int majorVersion, int minorVersion);
+ explicit InternalNode(const QString &type, int majorVersion, int minorVersion, qint32 internalId);
private:
QString m_typeName;
@@ -139,6 +141,7 @@ private:
int m_minorVersion;
bool m_valid;
+ qint32 m_internalId;
QHash<QString, InternalPropertyPointer> m_namePropertyHash;
QStringList m_scriptFunctionList;
@@ -146,7 +149,6 @@ private:
uint qHash(const InternalNodePointer& node);
bool operator <(const InternalNodePointer &firstNode, const InternalNodePointer &secondNode);
-
} // Internal
} // QtQmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/model/internalnodeabstractproperty.h b/src/plugins/qmldesigner/designercore/model/internalnodeabstractproperty.h
index eb9f86633b..682c3954aa 100644
--- a/src/plugins/qmldesigner/designercore/model/internalnodeabstractproperty.h
+++ b/src/plugins/qmldesigner/designercore/model/internalnodeabstractproperty.h
@@ -54,6 +54,8 @@ public:
virtual QList<InternalNodePointer> allDirectSubNodes() const = 0;
virtual bool isEmpty() const = 0;
+ virtual int count() const = 0;
+ virtual int indexOf(const InternalNodePointer &node) const = 0;
virtual bool isValid() const;
protected:
diff --git a/src/plugins/qmldesigner/designercore/model/internalnodelistproperty.cpp b/src/plugins/qmldesigner/designercore/model/internalnodelistproperty.cpp
index d96ec752fe..21aaad25fc 100644
--- a/src/plugins/qmldesigner/designercore/model/internalnodelistproperty.cpp
+++ b/src/plugins/qmldesigner/designercore/model/internalnodelistproperty.cpp
@@ -63,6 +63,25 @@ bool InternalNodeListProperty::isEmpty() const
return m_nodeList.isEmpty();
}
+int InternalNodeListProperty::count() const
+{
+ return m_nodeList.count();
+}
+
+int InternalNodeListProperty::indexOf(const InternalNode::Pointer &node) const
+{
+ if (node.isNull())
+ return -1;
+
+ return m_nodeList.indexOf(node);
+}
+
+InternalNode::Pointer InternalNodeListProperty::at(int index) const
+{
+ Q_ASSERT(index >=0 || index < m_nodeList.count());
+ return InternalNode::Pointer(m_nodeList.at(index));
+}
+
bool InternalNodeListProperty::isNodeListProperty() const
{
return true;
diff --git a/src/plugins/qmldesigner/designercore/model/internalnodelistproperty.h b/src/plugins/qmldesigner/designercore/model/internalnodelistproperty.h
index f43e722fd5..dc5f8a8f12 100644
--- a/src/plugins/qmldesigner/designercore/model/internalnodelistproperty.h
+++ b/src/plugins/qmldesigner/designercore/model/internalnodelistproperty.h
@@ -52,6 +52,9 @@ public:
bool isValid() const;
bool isEmpty() const;
+ int count() const;
+ int indexOf(const InternalNodePointer &node) const;
+ InternalNodePointer at(int index) const;
bool isNodeListProperty() const;
diff --git a/src/plugins/qmldesigner/designercore/model/internalnodeproperty.cpp b/src/plugins/qmldesigner/designercore/model/internalnodeproperty.cpp
index 7ed3dde05a..0c058ab2f7 100644
--- a/src/plugins/qmldesigner/designercore/model/internalnodeproperty.cpp
+++ b/src/plugins/qmldesigner/designercore/model/internalnodeproperty.cpp
@@ -57,6 +57,22 @@ bool InternalNodeProperty::isEmpty() const
return m_node.isNull();
}
+int InternalNodeProperty::count() const
+{
+ if (isEmpty())
+ return 0;
+
+ return 1;
+}
+
+int InternalNodeProperty::indexOf(const InternalNode::Pointer &node) const
+{
+ if (!node.isNull() && node == m_node)
+ return 0;
+
+ return -1;
+}
+
bool InternalNodeProperty::isValid() const
{
return InternalProperty::isValid() && isNodeProperty();
diff --git a/src/plugins/qmldesigner/designercore/model/internalnodeproperty.h b/src/plugins/qmldesigner/designercore/model/internalnodeproperty.h
index c7a9196e43..4e39695d15 100644
--- a/src/plugins/qmldesigner/designercore/model/internalnodeproperty.h
+++ b/src/plugins/qmldesigner/designercore/model/internalnodeproperty.h
@@ -48,6 +48,8 @@ public:
bool isValid() const;
bool isEmpty() const;
+ int count() const;
+ int indexOf(const InternalNodePointer &node) const;
bool isNodeProperty() const;
QList<InternalNodePointer> allSubNodes() const;
diff --git a/src/plugins/qmldesigner/designercore/model/internalproperty.cpp b/src/plugins/qmldesigner/designercore/model/internalproperty.cpp
index 79ca05dabc..5b8e1ec5fa 100644
--- a/src/plugins/qmldesigner/designercore/model/internalproperty.cpp
+++ b/src/plugins/qmldesigner/designercore/model/internalproperty.cpp
@@ -36,7 +36,6 @@
#include "internalvariantproperty.h"
#include "internalnodelistproperty.h"
#include "internalnodeproperty.h"
-#include "propertyparser.h"
#include "internalnode_p.h"
#include <QVariant>
#include <QString>
diff --git a/src/plugins/qmldesigner/designercore/model/model.cpp b/src/plugins/qmldesigner/designercore/model/model.cpp
index 329dc7eba4..75ed3563b5 100644
--- a/src/plugins/qmldesigner/designercore/model/model.cpp
+++ b/src/plugins/qmldesigner/designercore/model/model.cpp
@@ -50,8 +50,8 @@
#include "abstractview.h"
#include "nodeinstanceview.h"
#include "metainfo.h"
+#include "nodemetainfo.h"
#include "model_p.h"
-#include "modelutilities.h"
#include "subcomponentmanager.h"
#include "variantparser.h"
#include "internalproperty.h"
@@ -92,9 +92,10 @@ namespace Internal {
ModelPrivate::ModelPrivate(Model *model) :
m_q(model),
- m_writeLock(false)
+ m_writeLock(false),
+ m_internalIdCounter(1)
{
- m_rootInternalNode = createNode("Qt/Item", 4, 7, PropertyListType());
+ m_rootInternalNode = createNode("Qt/Item", 4, 7, PropertyListType(), true);
}
ModelPrivate::~ModelPrivate()
@@ -108,6 +109,16 @@ void ModelPrivate::detachAllViews()
detachView(view.data(), true);
m_viewList.clear();
+
+ if (m_rewriterView) {
+ m_rewriterView->modelAboutToBeDetached(m_q);
+ m_rewriterView.clear();
+ }
+
+ if (m_nodeInstanceView) {
+ m_nodeInstanceView->modelAboutToBeDetached(m_q);
+ m_nodeInstanceView.clear();
+ }
}
Model *ModelPrivate::create(QString type, int major, int minor)
@@ -152,13 +163,14 @@ void ModelPrivate::notifyImportAdded(const Import &import)
resetModel = true;
}
- if (rewriterView())
- foreach (const QWeakPointer<AbstractView> &view, m_viewList)
- view->importAdded(import);
+ NodeMetaInfo::clearCache();
if (nodeInstanceView())
nodeInstanceView()->importAdded(import);
+ foreach (const QWeakPointer<AbstractView> &view, m_viewList)
+ view->importAdded(import);
+
if (resetModel) {
resetModelByRewriter(description);
}
@@ -178,12 +190,14 @@ void ModelPrivate::notifyImportRemoved(const Import &import)
resetModel = true;
}
- foreach (const QWeakPointer<AbstractView> &view, m_viewList)
- view->importRemoved(import);
+ NodeMetaInfo::clearCache();
if (nodeInstanceView())
nodeInstanceView()->importRemoved(import);
+ foreach (const QWeakPointer<AbstractView> &view, m_viewList)
+ view->importRemoved(import);
+
if (resetModel) {
resetModelByRewriter(description);
}
@@ -209,12 +223,18 @@ void ModelPrivate::setFileUrl(const QUrl &fileUrl)
InternalNode::Pointer ModelPrivate::createNode(const QString &typeString,
int majorVersion,
int minorVersion,
- const QList<QPair<QString, QVariant> > &propertyList)
+ const QList<QPair<QString, QVariant> > &propertyList,
+ bool isRootNode)
{
if (typeString.isEmpty())
throw InvalidArgumentException(__LINE__, __FUNCTION__, __FILE__, tr("invalid type"));
- InternalNode::Pointer newInternalNodePointer = InternalNode::create(typeString, majorVersion, minorVersion);
+ qint32 internalId = 0;
+
+ if (!isRootNode)
+ internalId = m_internalIdCounter++;
+
+ InternalNode::Pointer newInternalNodePointer = InternalNode::create(typeString, majorVersion, minorVersion, internalId);
typedef QPair<QString, QVariant> PropertyPair;
@@ -224,6 +244,7 @@ InternalNode::Pointer ModelPrivate::createNode(const QString &typeString,
}
m_nodeSet.insert(newInternalNodePointer);
+ m_internalIdNodeHash.insert(newInternalNodePointer->internalId(), newInternalNodePointer);
notifyNodeCreated(newInternalNodePointer);
@@ -240,6 +261,7 @@ void ModelPrivate::removeNodeFromModel(const InternalNodePointer &node)
m_idNodeHash.remove(node->id());
node->setValid(false);
m_nodeSet.remove(node);
+ m_internalIdNodeHash.remove(node->internalId());
}
void ModelPrivate::removeAllSubNodes(const InternalNode::Pointer &node)
@@ -400,6 +422,35 @@ void ModelPrivate::notifyInstancePropertyChange(const QList<QPair<ModelNode, QSt
}
}
+void ModelPrivate::notifyInstancesCompleted(const QVector<ModelNode> &nodeVector)
+{
+ bool resetModel = false;
+ QString description;
+
+ QVector<Internal::InternalNode::Pointer> internalVector(toInternalNodeVector(nodeVector));
+
+ try {
+ if (rewriterView())
+ rewriterView()->instancesCompleted(toModelNodeVector(internalVector, rewriterView()));
+ } catch (RewritingException &e) {
+ description = e.description();
+ resetModel = true;
+ }
+
+ foreach (const QWeakPointer<AbstractView> &view, m_viewList) {
+ Q_ASSERT(view != 0);
+ view->instancesCompleted(toModelNodeVector(internalVector, view.data()));
+ }
+
+ if (nodeInstanceView()) {
+ nodeInstanceView()->instancesCompleted(toModelNodeVector(internalVector, nodeInstanceView()));
+ }
+
+ if (resetModel) {
+ resetModelByRewriter(description);
+ }
+}
+
void ModelPrivate::notifyCustomNotification(const AbstractView *senderView, const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> &data)
{
bool resetModel = false;
@@ -822,6 +873,64 @@ void ModelPrivate::notifyVariantPropertiesChanged(const InternalNodePointer &int
}
}
+void ModelPrivate::notifyNodeAboutToBeReparent(const InternalNodePointer &internalNodePointer, const InternalNodeAbstractPropertyPointer &newPropertyParent, const InternalNodePointer &oldParent, const QString &oldPropertyName, AbstractView::PropertyChangeFlags propertyChange)
+{
+ bool resetModel = false;
+ QString description;
+
+ try {
+ if (rewriterView()) {
+ NodeAbstractProperty newProperty;
+ NodeAbstractProperty oldProperty;
+
+ if (!oldPropertyName.isEmpty() && oldParent->isValid())
+ oldProperty = NodeAbstractProperty(oldPropertyName, oldParent, model(), rewriterView());
+
+ if (!newPropertyParent.isNull())
+ newProperty = NodeAbstractProperty(newPropertyParent, model(), rewriterView());
+ ModelNode node(internalNodePointer, model(), rewriterView());
+ rewriterView()->nodeAboutToBeReparented(node, newProperty, oldProperty, propertyChange);
+ }
+ } catch (RewritingException &e) {
+ description = e.description();
+ resetModel = true;
+ }
+
+ 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->nodeAboutToBeReparented(node, newProperty, oldProperty, propertyChange);
+
+ }
+
+ if (nodeInstanceView()) {
+ NodeAbstractProperty newProperty;
+ NodeAbstractProperty oldProperty;
+
+ if (!oldPropertyName.isEmpty() && oldParent->isValid())
+ oldProperty = NodeAbstractProperty(oldPropertyName, oldParent, model(), nodeInstanceView());
+
+ if (!newPropertyParent.isNull())
+ newProperty = NodeAbstractProperty(newPropertyParent, model(), nodeInstanceView());
+ ModelNode node(internalNodePointer, model(), nodeInstanceView());
+ nodeInstanceView()->nodeAboutToBeReparented(node, newProperty, oldProperty, propertyChange);
+ }
+
+ if (resetModel) {
+ resetModelByRewriter(description);
+ }
+}
+
+
void ModelPrivate::notifyNodeReparent(const InternalNode::Pointer &internalNodePointer, const InternalNodeAbstractProperty::Pointer &newPropertyParent, const InternalNodePointer &oldParent, const QString &oldPropertyName, AbstractView::PropertyChangeFlags propertyChange)
{
bool resetModel = false;
@@ -954,6 +1063,15 @@ QList<ModelNode> ModelPrivate::toModelNodeList(const QList<InternalNode::Pointer
return newNodeList;
}
+QVector<ModelNode> ModelPrivate::toModelNodeVector(const QVector<InternalNode::Pointer> &nodeVector, AbstractView *view) const
+{
+ QVector<ModelNode> newNodeVector;
+ foreach (const Internal::InternalNode::Pointer &node, nodeVector)
+ newNodeVector.append(ModelNode(node, model(), view));
+
+ return newNodeVector;
+}
+
QList<Internal::InternalNode::Pointer> ModelPrivate::toInternalNodeList(const QList<ModelNode> &nodeList) const
{
QList<Internal::InternalNode::Pointer> newNodeList;
@@ -963,6 +1081,15 @@ QList<Internal::InternalNode::Pointer> ModelPrivate::toInternalNodeList(const QL
return newNodeList;
}
+QVector<Internal::InternalNode::Pointer> ModelPrivate::toInternalNodeVector(const QVector<ModelNode> &nodeVector) const
+{
+ QVector<Internal::InternalNode::Pointer> newNodeVector;
+ foreach (const ModelNode &node, nodeVector)
+ newNodeVector.append(node.internalNode());
+
+ return newNodeVector;
+}
+
void ModelPrivate::changeSelectedNodes(const QList<InternalNode::Pointer> &newSelectedNodeList,
const QList<InternalNode::Pointer> &oldSelectedNodeList)
{
@@ -1107,6 +1234,9 @@ void ModelPrivate::reparentNode(const InternalNode::Pointer &newParentNode, cons
InternalNodeAbstractProperty::Pointer newParentProperty(newParentNode->nodeAbstractProperty(name));
Q_ASSERT(!newParentProperty.isNull());
+
+ notifyNodeAboutToBeReparent(node, newParentProperty, oldParentNode, oldParentPropertyName, propertyChange);
+
if (newParentProperty)
node->setParentProperty(newParentProperty);
@@ -1161,15 +1291,6 @@ void ModelPrivate::changeNodeOrder(const InternalNode::Pointer &internalParentNo
notifyNodeOrderChanged(nodeList, internalNode, from);
}
-void ModelPrivate::setRootNode(const InternalNode::Pointer& newRootNode)
-{
- removeNode(m_rootInternalNode);
- m_rootInternalNode = newRootNode;
-
- if (!m_rootInternalNode.isNull() && m_rootInternalNode->isValid())
- notifyNodeCreated(m_rootInternalNode);
-}
-
void ModelPrivate::setRewriterView(RewriterView *rewriterView)
{
if (rewriterView == m_rewriterView.data())
@@ -1220,6 +1341,16 @@ bool ModelPrivate::hasId(const QString &id) const
return m_idNodeHash.contains(id);
}
+InternalNodePointer ModelPrivate::nodeForInternalId(qint32 internalId) const
+{
+ return m_internalIdNodeHash.value(internalId);
+}
+
+bool ModelPrivate::hasNodeForInternalId(qint32 internalId) const
+{
+ return m_internalIdNodeHash.contains(internalId);
+}
+
QList<InternalNodePointer> ModelPrivate::allNodes() const
{
// the item must be ordered!
@@ -1380,6 +1511,11 @@ void Model::removeImport(const Import &import)
m_d->removeImport(import);
}
+RewriterView *Model::rewriterView() const
+{
+ return m_d->rewriterView();
+}
+
#if 0
/*!
\brief Creates a new empty model
@@ -1430,6 +1566,11 @@ const MetaInfo Model::metaInfo() const
return m_d->metaInfo();
}
+NodeMetaInfo Model::metaInfo(const QString &typeName, int majorVersion, int minorVersion)
+{
+ return NodeMetaInfo(this, typeName, majorVersion, minorVersion);
+}
+
/*!
\brief Sets a specific Metainfo on this Model
*/
diff --git a/src/plugins/qmldesigner/designercore/model/model_p.h b/src/plugins/qmldesigner/designercore/model/model_p.h
index f72d35df34..cc68d2bf0f 100644
--- a/src/plugins/qmldesigner/designercore/model/model_p.h
+++ b/src/plugins/qmldesigner/designercore/model/model_p.h
@@ -105,7 +105,8 @@ public:
InternalNodePointer createNode(const QString &typeString,
int majorVersion,
int minorVersion,
- const QList<QPair<QString, QVariant> > &propertyList);
+ const QList<QPair<QString, QVariant> > &propertyList,
+ bool isRootNode = false);
/*factory methods for internal use in model and rewriter*/
@@ -128,6 +129,7 @@ public:
void setModel(Model *q) { m_q = q; }
void notifyNodeCreated(const InternalNodePointer &newInternalNodePointer);
+ void notifyNodeAboutToBeReparent(const InternalNodePointer &internalNodePointer, const InternalNodeAbstractPropertyPointer &newPropertyParent, const InternalNodePointer &oldParent, const QString &oldPropertyName, AbstractView::PropertyChangeFlags propertyChange);
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);
@@ -146,7 +148,7 @@ public:
void notifyCustomNotification(const AbstractView *senderView, const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> &data);
void notifyInstancePropertyChange(const QList<QPair<ModelNode, QString> > &propertyList);
-
+ void notifyInstancesCompleted(const QVector<ModelNode> &nodeList);
void setSelectedNodes(const QList<InternalNodePointer> &selectedNodeList);
@@ -157,7 +159,6 @@ public:
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);
void resetModelByRewriter(const QString &description);
@@ -190,6 +191,9 @@ public:
InternalNodePointer nodeForId(const QString &id) const;
bool hasId(const QString &id) const;
+ InternalNodePointer nodeForInternalId(qint32 internalId) const;
+ bool hasNodeForInternalId(qint32 internalId) const;
+
QList<InternalNodePointer> allNodes() const;
bool isWriteLocked() const;
@@ -207,6 +211,8 @@ private: //functions
void removeNodeFromModel(const InternalNodePointer &node);
QList<InternalNodePointer> toInternalNodeList(const QList<ModelNode> &nodeList) const;
QList<ModelNode> toModelNodeList(const QList<InternalNodePointer> &nodeList, AbstractView *view) const;
+ QVector<ModelNode> toModelNodeVector(const QVector<InternalNodePointer> &nodeVector, AbstractView *view) const;
+ QVector<InternalNodePointer> toInternalNodeVector(const QVector<ModelNode> &nodeVector) const;
private:
Model *m_q;
@@ -216,6 +222,7 @@ private:
QList<QWeakPointer<AbstractView> > m_viewList;
QList<InternalNodePointer> m_selectedNodeList;
QHash<QString,InternalNodePointer> m_idNodeHash;
+ QHash<qint32, InternalNodePointer> m_internalIdNodeHash;
QSet<InternalNodePointer> m_nodeSet;
InternalNodePointer m_rootInternalNode;
@@ -225,7 +232,8 @@ private:
QWeakPointer<Model> m_masterModel;
QWeakPointer<RewriterView> m_rewriterView;
QWeakPointer<NodeInstanceView> m_nodeInstanceView;
- bool m_writeLock;
+ bool m_writeLock;
+ qint32 m_internalIdCounter;
};
}
diff --git a/src/plugins/qmldesigner/designercore/model/modelnode.cpp b/src/plugins/qmldesigner/designercore/model/modelnode.cpp
index 0341b395e3..1ac1c7a594 100644
--- a/src/plugins/qmldesigner/designercore/model/modelnode.cpp
+++ b/src/plugins/qmldesigner/designercore/model/modelnode.cpp
@@ -167,15 +167,14 @@ QString ModelNode::validId()
static bool idIsQmlKeyWord(const QString& id)
{
QStringList keywords;
- keywords << "import" << "property" << "signal"
- << "as" << "on" << "list";
+ keywords << "import" << "as";
return keywords.contains(id);
}
static bool idContainsWrongLetter(const QString& id)
{
- static QRegExp idExpr(QLatin1String("[a-z][a-zA-Z0-9_]*"));
+ static QRegExp idExpr(QLatin1String("[a-z_][a-zA-Z0-9_]*"));
return !idExpr.exactMatch(id);
}
@@ -633,7 +632,7 @@ bool operator ==(const ModelNode &firstNode, const ModelNode &secondNode)
throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
}
- return firstNode.m_internalNode.data() == secondNode.m_internalNode.data();
+ return firstNode.internalId() == secondNode.internalId();
}
/*!
@@ -646,7 +645,7 @@ bool operator !=(const ModelNode &firstNode, const ModelNode &secondNode)
throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
}
- return firstNode.m_internalNode != secondNode.m_internalNode;
+ return firstNode.internalId() != secondNode.internalId();
}
bool operator <(const ModelNode &firstNode, const ModelNode &secondNode)
@@ -656,7 +655,7 @@ bool operator <(const ModelNode &firstNode, const ModelNode &secondNode)
throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
}
- return firstNode.internalNode().data() < secondNode.internalNode().data();
+ return firstNode.internalId() < secondNode.internalId();
}
@@ -676,7 +675,7 @@ uint qHash(const ModelNode &node)
// Q_ASSERT_X(node.isValid(), Q_FUNC_INFO, "model node is invalid");
// throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
// }
- return ::qHash(node.m_internalNode.data());
+ return ::qHash(node.internalId());
}
/*!
@@ -734,16 +733,14 @@ 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());
+
+ return NodeMetaInfo(model(), type(), majorVersion(), minorVersion());
}
/*! \brief has a node the selection of the model
@@ -840,7 +837,7 @@ QDebug operator<<(QDebug debug, const ModelNode &modelNode)
{
if (modelNode.isValid()) {
debug.nospace() << "ModelNode("
- << modelNode.internalNode().data() << ", "
+ << modelNode.internalId() << ", "
<< modelNode.type() << ", "
<< modelNode.id() << ')';
} else {
@@ -931,4 +928,12 @@ QStringList ModelNode::scriptFunctions() const
return internalNode()->scriptFunctions();
}
+qint32 ModelNode::internalId() const
+{
+ if (m_internalNode.isNull())
+ return -1;
+
+ return m_internalNode->internalId();
+}
+
}
diff --git a/src/plugins/qmldesigner/designercore/model/modelutilities.cpp b/src/plugins/qmldesigner/designercore/model/modelutilities.cpp
deleted file mode 100644
index acb4363204..0000000000
--- a/src/plugins/qmldesigner/designercore/model/modelutilities.cpp
+++ /dev/null
@@ -1,129 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#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, 7)->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/designercore/model/nodeabstractproperty.cpp b/src/plugins/qmldesigner/designercore/model/nodeabstractproperty.cpp
index 1dfc141867..c75631941e 100644
--- a/src/plugins/qmldesigner/designercore/model/nodeabstractproperty.cpp
+++ b/src/plugins/qmldesigner/designercore/model/nodeabstractproperty.cpp
@@ -67,7 +67,7 @@ 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?
+ reparentHere(modelNode, parentModelNode().metaInfo().propertyIsListProperty(name())); //we could use the metasystem instead?
}
void NodeAbstractProperty::reparentHere(const ModelNode &modelNode, bool isNodeList)
@@ -110,6 +110,24 @@ bool NodeAbstractProperty::isEmpty() const
return property->isEmpty();
}
+int NodeAbstractProperty::indexOf(const ModelNode &node) const
+{
+ Internal::InternalNodeAbstractProperty::Pointer property = internalNode()->nodeAbstractProperty(name());
+ if (property.isNull())
+ return 0;
+
+ return property->indexOf(node.internalNode());
+}
+
+int NodeAbstractProperty::count() const
+{
+ Internal::InternalNodeAbstractProperty::Pointer property = internalNode()->nodeAbstractProperty(name());
+ if (property.isNull())
+ return 0;
+ else
+ return property->count();
+}
+
QList<ModelNode> NodeAbstractProperty::allSubNodes()
{
if (!internalNode()
diff --git a/src/plugins/qmldesigner/designercore/model/nodelistproperty.cpp b/src/plugins/qmldesigner/designercore/model/nodelistproperty.cpp
index 8c666ac4a7..ea0e95b84c 100644
--- a/src/plugins/qmldesigner/designercore/model/nodelistproperty.cpp
+++ b/src/plugins/qmldesigner/designercore/model/nodelistproperty.cpp
@@ -119,12 +119,17 @@ void NodeListProperty::reparentHere(const ModelNode &modelNode)
NodeAbstractProperty::reparentHere(modelNode, true);
}
-bool NodeListProperty::isEmpty() const
+ModelNode NodeListProperty::at(int index) const
{
if (!isValid())
throw InvalidPropertyException(__LINE__, __FUNCTION__, __FILE__, "<invalid node list property>");
- return toModelNodeList().empty();
-}
+ Internal::InternalNodeListProperty::Pointer internalProperty = internalNode()->nodeListProperty(name());
+ if (internalProperty)
+ return ModelNode(internalProperty->at(index), model(), view());
+
+
+ return ModelNode();
+}
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/model/propertyparser.cpp b/src/plugins/qmldesigner/designercore/model/propertyparser.cpp
index cf38111a3d..19472c77ea 100644
--- a/src/plugins/qmldesigner/designercore/model/propertyparser.cpp
+++ b/src/plugins/qmldesigner/designercore/model/propertyparser.cpp
@@ -44,23 +44,8 @@ namespace QmlDesigner {
namespace Internal {
namespace PropertyParser {
-static QVariant fromEnum(const QString &string, const QString &type, const MetaInfo &metaInfo)
+QVariant read(const QString &typeStr, const QString &str, const 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);
}
diff --git a/src/plugins/qmldesigner/designercore/model/qmlanchors.cpp b/src/plugins/qmldesigner/designercore/model/qmlanchors.cpp
index 11ea5dc638..20f3abbd6e 100644
--- a/src/plugins/qmldesigner/designercore/model/qmlanchors.cpp
+++ b/src/plugins/qmldesigner/designercore/model/qmlanchors.cpp
@@ -314,10 +314,10 @@ AnchorLine::Type QmlAnchors::possibleAnchorLines(AnchorLine::Type sourceAnchorLi
AnchorLine QmlAnchors::instanceAnchor(AnchorLine::Type sourceAnchorLine) const
{
- QPair<QString, NodeInstance> targetAnchorLinePair;
+ QPair<QString, qint32> targetAnchorLinePair;
if (qmlItemNode().nodeInstance().hasAnchor("anchors.fill") && (sourceAnchorLine & AnchorLine::Fill)) {
targetAnchorLinePair = qmlItemNode().nodeInstance().anchor("anchors.fill");
- targetAnchorLinePair.first = lineTypeToString(sourceAnchorLine);
+ targetAnchorLinePair.first = lineTypeToString(sourceAnchorLine); // TODO: looks wrong
} else if (qmlItemNode().nodeInstance().hasAnchor("anchors.centerIn") && (sourceAnchorLine & AnchorLine::Center)) {
targetAnchorLinePair = qmlItemNode().nodeInstance().anchor("anchors.centerIn");
targetAnchorLinePair.first = lineTypeToString(sourceAnchorLine);
@@ -330,10 +330,10 @@ AnchorLine QmlAnchors::instanceAnchor(AnchorLine::Type sourceAnchorLine) const
if (targetAnchorLine == AnchorLine::Invalid )
return AnchorLine();
- if (!targetAnchorLinePair.second.isValid()) //there might be no node instance for the parent
+ if (targetAnchorLinePair.second < 0) //there might be no node instance for the parent
return AnchorLine();
- return AnchorLine(QmlItemNode(qmlItemNode().nodeForInstance(targetAnchorLinePair.second)), targetAnchorLine);
+ return AnchorLine(QmlItemNode(qmlItemNode().nodeForInstance(qmlItemNode().qmlModelView()->nodeInstanceView()->instanceForId(targetAnchorLinePair.second))), targetAnchorLine);
}
void QmlAnchors::removeAnchor(AnchorLine::Type sourceAnchorLine)
diff --git a/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp
index 1895b993d0..499566a5de 100644
--- a/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp
+++ b/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp
@@ -217,7 +217,7 @@ bool QmlItemNode::instanceIsResizable() const
bool QmlItemNode::instanceIsInPositioner() const
{
- return nodeInstance().isInPositioner();
+ return nodeInstance().isInPositioner();
}
QRectF QmlItemNode::instanceBoundingRect() const
@@ -250,7 +250,7 @@ int QmlItemNode::instancePenWidth() const
return nodeInstance().penWidth();
}
-void QmlItemNode::paintInstance(QPainter *painter) const
+void QmlItemNode::paintInstance(QPainter *painter)
{
if (nodeInstance().isValid())
nodeInstance().paint(painter);
diff --git a/src/plugins/qmldesigner/designercore/model/qmlmodelview.cpp b/src/plugins/qmldesigner/designercore/model/qmlmodelview.cpp
index 4a204feca4..06437aeeb2 100644
--- a/src/plugins/qmldesigner/designercore/model/qmlmodelview.cpp
+++ b/src/plugins/qmldesigner/designercore/model/qmlmodelview.cpp
@@ -35,7 +35,6 @@
#include "qmlobjectnode.h"
#include "qmlitemnode.h"
#include "itemlibraryinfo.h"
-#include "modelutilities.h"
#include "mathutils.h"
#include "invalididexception.h"
#include <QDir>
@@ -45,10 +44,6 @@
#include "nodeabstractproperty.h"
#include "variantproperty.h"
-enum {
- debug = false
-};
-
namespace QmlDesigner {
@@ -75,6 +70,11 @@ QmlModelState QmlModelView::baseState() const
return QmlModelState::createBaseState(this);
}
+QmlModelStateGroup QmlModelView::rootStateGroup() const
+{
+ return QmlModelStateGroup(rootModelNode());
+}
+
QmlObjectNode QmlModelView::createQmlObjectNode(const QString &typeString,
int majorVersion,
int minorVersion,
@@ -283,16 +283,19 @@ QmlObjectNode QmlModelView::fxObjectNodeForId(const QString &id)
void QmlModelView::customNotification(const AbstractView * /* view */, const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> & /* data */)
{
- if (debug)
- qDebug() << this << __FUNCTION__ << identifier << nodeList;
-
if (identifier == "__state changed__") {
- QmlModelState state(nodeList.first());
- if (state.isValid()) {
- activateState(state);
- } else {
- activateState(baseState());
- }
+ QmlModelState newState(nodeList.first());
+ QmlModelState oldState = currentState();
+
+ if (!newState.isValid())
+ newState = baseState();
+
+ activateState(newState);
+
+ m_state = newState;
+
+ if (newState != oldState)
+ stateChanged(newState, oldState);
}
}
@@ -331,7 +334,8 @@ static bool isTransformProperty(const QString &name)
<< "scale"
<< "transformOrigin"
<< "paintedWidth"
- << "paintedHeight");
+ << "paintedHeight"
+ << "border.width");
return transformProperties.contains(name);
}
@@ -344,6 +348,7 @@ void QmlModelView::nodeOrderChanged(const NodeListProperty &/*listProperty*/, co
void QmlModelView::nodeCreated(const ModelNode &/*createdNode*/) {}
void QmlModelView::nodeAboutToBeRemoved(const ModelNode &/*removedNode*/) {}
void QmlModelView::nodeRemoved(const ModelNode &/*removedNode*/, const NodeAbstractProperty &/*parentProperty*/, PropertyChangeFlags /*propertyChange*/) {}
+void QmlModelView::nodeAboutToBeReparented(const ModelNode &/*node*/, const NodeAbstractProperty &/*newPropertyParent*/, const NodeAbstractProperty &/*oldPropertyParent*/, AbstractView::PropertyChangeFlags /*propertyChange*/) {}
void QmlModelView::nodeReparented(const ModelNode &/*node*/, const NodeAbstractProperty &/*newPropertyParent*/, const NodeAbstractProperty &/*oldPropertyParent*/, AbstractView::PropertyChangeFlags /*propertyChange*/) {}
void QmlModelView::nodeIdChanged(const ModelNode& /*node*/, const QString& /*newId*/, const QString& /*oldId*/) {}
void QmlModelView::propertiesAboutToBeRemoved(const QList<AbstractProperty>& /*propertyList*/) {}
@@ -361,12 +366,12 @@ void QmlModelView::instancePropertyChange(const QList<QPair<ModelNode, QString>
nodeInstancePropertyChanged(propertyPair.first, propertyPair.second);
}
}
+void QmlModelView::instancesCompleted(const QVector<ModelNode> &/*completedNodeList*/)
+{
+}
void QmlModelView::nodeInstancePropertyChanged(const ModelNode &node, const QString &propertyName)
{
- if (debug)
- qDebug() << this << __FUNCTION__ << node << propertyName;
-
QmlObjectNode qmlObjectNode(node);
if (!qmlObjectNode.isValid())
@@ -376,17 +381,12 @@ void QmlModelView::nodeInstancePropertyChanged(const ModelNode &node, const QStr
transformChanged(qmlObjectNode, propertyName);
else if (propertyName == "parent")
parentChanged(qmlObjectNode);
- else if (propertyName == "state")
- changeToState(node, qmlObjectNode.instanceValue(propertyName).toString());
else
otherPropertyChanged(qmlObjectNode, propertyName);
}
void QmlModelView::activateState(const QmlModelState &state)
{
- if (debug)
- qDebug() << this << __FUNCTION__ << state;
-
if (!state.isValid())
return;
@@ -395,7 +395,7 @@ void QmlModelView::activateState(const QmlModelState &state)
m_state = state; //This is hacky. m_state should be controlled by the instances
//### todo: If the state thumbnail code gets refactored.
- // this is not neccessary anymore.
+ // this is not necessary anymore.
NodeInstance newStateInstance = instanceForModelNode(state.modelNode());
@@ -409,9 +409,6 @@ void QmlModelView::activateState(const QmlModelState &state)
void QmlModelView::changeToState(const ModelNode &node, const QString &stateName)
{
- if (debug)
- qDebug() << this << __FUNCTION__ << node << stateName;
-
QmlItemNode itemNode(node);
QmlModelState newState;
@@ -441,10 +438,8 @@ void QmlModelView::otherPropertyChanged(const QmlObjectNode &/*qmlObjectNode*/,
{
}
-void QmlModelView::stateChanged(const QmlModelState &newQmlModelState, const QmlModelState &oldQmlModelState)
+void QmlModelView::stateChanged(const QmlModelState &/*newQmlModelState*/, const QmlModelState &/*oldQmlModelState*/)
{
- if (debug)
- qDebug() << this << __FUNCTION__ << oldQmlModelState << "to" << newQmlModelState;
}
} //QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp
index 6624627d38..5837958b04 100644
--- a/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp
+++ b/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp
@@ -424,7 +424,7 @@ bool QmlObjectNode::hasNodeParent() const
bool QmlObjectNode::hasInstanceParent() const
{
- return nodeInstance().hasParent();
+ return nodeInstance().parentId() >= 0 && qmlModelView()->nodeInstanceView()->hasInstanceForId(nodeInstance().parentId());
}
@@ -435,7 +435,10 @@ void QmlObjectNode::setParentProperty(const NodeAbstractProperty &parentProeprty
QmlObjectNode QmlObjectNode::instanceParent() const
{
- return nodeForInstance(nodeInstance().parent());
+ if (hasInstanceParent())
+ return nodeForInstance(qmlModelView()->nodeInstanceView()->instanceForId(nodeInstance().parentId()));
+
+ return QmlObjectNode();
}
void QmlObjectNode::setId(const QString &id)
@@ -460,7 +463,7 @@ bool QmlObjectNode::hasDefaultProperty() const
QString QmlObjectNode::defaultProperty() const
{
- return modelNode().metaInfo().defaultProperty();
+ return modelNode().metaInfo().defaultPropertyName();
}
void QmlObjectNode::setParent(QmlObjectNode newParent)
diff --git a/src/plugins/qmldesigner/designercore/model/qmltextgenerator.cpp b/src/plugins/qmldesigner/designercore/model/qmltextgenerator.cpp
index 3b11a043e2..81bfcc04a0 100644
--- a/src/plugins/qmldesigner/designercore/model/qmltextgenerator.cpp
+++ b/src/plugins/qmldesigner/designercore/model/qmltextgenerator.cpp
@@ -39,7 +39,7 @@
#include "nodelistproperty.h"
#include "qmltextgenerator.h"
#include "variantproperty.h"
-#include <propertymetainfo.h>
+#include <nodemetainfo.h>
#include "model.h"
using namespace QmlDesigner;
@@ -99,8 +99,11 @@ QString QmlTextGenerator::toQml(const AbstractProperty &property, int indentDept
if (property.name() == QLatin1String("id"))
return stringValue;
- if (variantProperty.metaInfo().isValid() && variantProperty.metaInfo().isEnumType()) {
- return variantProperty.metaInfo().enumerator().scope() + '.' + stringValue;
+ if (false) {
+ }
+ if (variantProperty.parentModelNode().metaInfo().isValid() &&
+ variantProperty.parentModelNode().metaInfo().propertyIsEnumType(variantProperty.name())) {
+ return variantProperty.parentModelNode().metaInfo().propertyEnumScope(variantProperty.name()) + '.' + stringValue;
} else {
switch (value.type()) {
diff --git a/src/plugins/qmldesigner/designercore/model/rewriteaction.cpp b/src/plugins/qmldesigner/designercore/model/rewriteaction.cpp
index 012ffd45ee..125bf25848 100644
--- a/src/plugins/qmldesigner/designercore/model/rewriteaction.cpp
+++ b/src/plugins/qmldesigner/designercore/model/rewriteaction.cpp
@@ -35,7 +35,6 @@
#include "nodeabstractproperty.h"
#include "nodelistproperty.h"
-#include "propertymetainfo.h"
#include "nodemetainfo.h"
#include "rewriteaction.h"
@@ -331,7 +330,7 @@ bool MoveNodeRewriteAction::execute(QmlRefactoring &refactoring,
const int newTrailingNodeLocation = m_newTrailingNode.isValid() ? positionStore.nodeOffset(m_newTrailingNode) : -1;
bool result = false;
- bool inDefaultProperty = (m_movingNode.parentProperty().parentModelNode().metaInfo().defaultProperty() == m_movingNode.parentProperty().name());
+ bool inDefaultProperty = (m_movingNode.parentProperty().parentModelNode().metaInfo().defaultPropertyName() == m_movingNode.parentProperty().name());
result = refactoring.moveObjectBeforeObject(movingNodeLocation, newTrailingNodeLocation, inDefaultProperty);
if (!result) {
diff --git a/src/plugins/qmldesigner/designercore/model/rewriterview.cpp b/src/plugins/qmldesigner/designercore/model/rewriterview.cpp
index f68a7b6966..7b357f6d8a 100644
--- a/src/plugins/qmldesigner/designercore/model/rewriterview.cpp
+++ b/src/plugins/qmldesigner/designercore/model/rewriterview.cpp
@@ -36,6 +36,8 @@
#include <filemanager/firstdefinitionfinder.h>
#include <customnotifications.h>
+#include <qmljs/parser/qmljsengine_p.h>
+
#include "rewriterview.h"
#include "rewritingexception.h"
#include "textmodifier.h"
@@ -46,6 +48,8 @@
#include "nodeproperty.h"
#include "invalidmodelnodeexception.h"
+
+
using namespace QmlDesigner::Internal;
namespace QmlDesigner {
@@ -66,12 +70,12 @@ RewriterView::Error::Error(Exception *exception):
{
}
-RewriterView::Error::Error(const QDeclarativeError &qmlError):
+RewriterView::Error::Error(const QmlJS::DiagnosticMessage &qmlError, const QUrl &document):
m_type(ParseError),
- m_line(qmlError.line()),
- m_column(qmlError.column()),
- m_description(qmlError.description()),
- m_url(qmlError.url())
+ m_line(qmlError.loc.startLine),
+ m_column(qmlError.loc.startColumn),
+ m_description(qmlError.message),
+ m_url(document)
{
}
@@ -275,6 +279,11 @@ void RewriterView::nodeReparented(const ModelNode &node, const NodeAbstractPrope
applyChanges();
}
+void RewriterView::nodeAboutToBeReparented(const ModelNode &/*node*/, const NodeAbstractProperty &/*newPropertyParent*/, const NodeAbstractProperty &/*oldPropertyParent*/, AbstractView::PropertyChangeFlags /*propertyChange*/)
+{
+}
+
+
void RewriterView::importAdded(const Import &import)
{
Q_ASSERT(textModifier());
@@ -380,6 +389,10 @@ void RewriterView::instancePropertyChange(const QList<QPair<ModelNode, QString>
{
}
+void RewriterView::instancesCompleted(const QVector<ModelNode> &/*completedNodeList*/)
+{
+}
+
void RewriterView::selectedNodesChanged(const QList<ModelNode> & /* selectedNodeList, */, const QList<ModelNode> & /*lastSelectedNodeList */)
{
@@ -567,6 +580,16 @@ bool RewriterView::renameId(const QString& oldId, const QString& newId)
return false;
}
+QmlJS::LookupContext *RewriterView::lookupContext() const
+{
+ return textToModelMerger()->lookupContext();
+}
+
+QmlJS::Document *RewriterView::document() const
+{
+ return textToModelMerger()->document();
+}
+
void RewriterView::qmlTextChanged()
{
if (inErrorState())
diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
index dda98cc48e..d5cc0e662c 100644
--- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
+++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
@@ -49,9 +49,8 @@
#include <qmljs/qmljslink.h>
#include <qmljs/qmljsscopebuilder.h>
#include <qmljs/parser/qmljsast_p.h>
+#include <qmljs/qmljscheck.h>
-#include <QtDeclarative/QDeclarativeComponent>
-#include <QtDeclarative/QDeclarativeEngine>
#include <QtCore/QSet>
#include <QtGui/QMessageBox>
@@ -231,6 +230,7 @@ public:
: m_snapshot(snapshot)
, m_doc(doc)
, m_context(new Interpreter::Context)
+ , m_lookupContext(LookupContext::create(doc, snapshot, QList<AST::Node*>()))
, m_link(m_context, doc, snapshot, importPaths)
, m_scopeBuilder(m_context, doc, snapshot)
{
@@ -259,8 +259,8 @@ public:
typeName = fixUpPackeNameForQtQuick(qmlValue->packageName()) + QLatin1String("/") + qmlValue->className();
//### todo this is just a hack to support QtQuick 1.0
- majorVersion = fixUpMajorVersionForQtQuick(qmlValue->packageName(), qmlValue->version().major());
- minorVersion = fixUpMinorVersionForQtQuick(qmlValue->packageName(), qmlValue->version().minor());
+ majorVersion = fixUpMajorVersionForQtQuick(qmlValue->packageName(), qmlValue->version().majorVersion());
+ minorVersion = fixUpMinorVersionForQtQuick(qmlValue->packageName(), qmlValue->version().minorVersion());
} else {
for (UiQualifiedId *iter = astTypeNode; iter; iter = iter->next)
if (!iter->next && iter->name)
@@ -376,10 +376,12 @@ public:
if (objectValue && objectValue->prototype(m_context) == m_context->engine()->arrayPrototype())
return true;
- for (const Interpreter::ObjectValue *iter = containingObject; iter; iter = iter->prototype(m_context)) {
- if (iter->property(name, m_context) == m_context->engine()->arrayPrototype())
+ Interpreter::PrototypeIterator iter(containingObject, m_context);
+ while (iter.hasNext()) {
+ const Interpreter::ObjectValue *proto = iter.next();
+ if (proto->property(name, m_context) == m_context->engine()->arrayPrototype())
return true;
- if (const Interpreter::QmlObjectValue *qmlIter = dynamic_cast<const Interpreter::QmlObjectValue *>(iter)) {
+ if (const Interpreter::QmlObjectValue *qmlIter = dynamic_cast<const Interpreter::QmlObjectValue *>(proto)) {
if (qmlIter->isListProperty(name))
return true;
}
@@ -401,12 +403,8 @@ public:
return hasQuotes ? QVariant(cleanedValue) : cleverConvert(cleanedValue);
}
- for (const Interpreter::ObjectValue *iter = containingObject; iter; iter = iter->prototype(m_context)) {
- if (iter->lookupMember(name, m_context, false)) {
- containingObject = iter;
- break;
- }
- }
+ if (containingObject)
+ containingObject->lookupMember(name, m_context, &containingObject);
if (const Interpreter::QmlObjectValue * qmlObject = dynamic_cast<const Interpreter::QmlObjectValue *>(containingObject)) {
const QString typeName = qmlObject->propertyType(name);
@@ -450,12 +448,8 @@ public:
return QVariant();
}
- for (const Interpreter::ObjectValue *iter = containingObject; iter; iter = iter->prototype(m_context)) {
- if (iter->lookupMember(name, m_context, false)) {
- containingObject = iter;
- break;
- }
- }
+ if (containingObject)
+ containingObject->lookupMember(name, m_context, &containingObject);
const Interpreter::QmlObjectValue * lhsQmlObject = dynamic_cast<const Interpreter::QmlObjectValue *>(containingObject);
if (!lhsQmlObject)
return QVariant();
@@ -477,15 +471,8 @@ public:
rhsValueName = memberExp->name->asString();
}
- if (!rhsValueObject)
- return QVariant();
-
- for (const Interpreter::ObjectValue *iter = rhsValueObject; iter; iter = iter->prototype(m_context)) {
- if (iter->lookupMember(rhsValueName, m_context, false)) {
- rhsValueObject = iter;
- break;
- }
- }
+ if (rhsValueObject)
+ rhsValueObject->lookupMember(rhsValueName, m_context, &rhsValueObject);
const Interpreter::QmlObjectValue *rhsQmlObjectValue = dynamic_cast<const Interpreter::QmlObjectValue *>(rhsValueObject);
if (!rhsQmlObjectValue)
@@ -497,10 +484,15 @@ public:
return QVariant();
}
+
+ LookupContext::Ptr lookupContext() const
+ { return m_lookupContext; }
+
private:
Snapshot m_snapshot;
Document::Ptr m_doc;
Interpreter::Context *m_context;
+ LookupContext::Ptr m_lookupContext;
Link m_link;
ScopeBuilder m_scopeBuilder;
};
@@ -556,13 +548,19 @@ void TextToModelMerger::setupImports(const Document::Ptr &doc,
if (import->fileName) {
const QString strippedFileName = stripQuotes(import->fileName->asString());
const Import newImport = Import::createFileImport(strippedFileName,
- version, as);
+ version, as, m_rewriterView->textModifier()->importPaths());
if (!existingImports.removeOne(newImport))
differenceHandler.modelMissesImport(newImport);
} else {
+ QString importUri = flatten(import->importUri);
+ if (importUri == QLatin1String("QtQuick") && version == QLatin1String("1.0")) {
+ importUri = QLatin1String("Qt");
+ version = QLatin1String("4.7");
+ }
+
const Import newImport =
- Import::createLibraryImport(flatten(import->importUri), version, as);
+ Import::createLibraryImport(importUri, version, as, m_rewriterView->textModifier()->importPaths());
if (!existingImports.removeOne(newImport))
differenceHandler.modelMissesImport(newImport);
@@ -581,27 +579,6 @@ bool TextToModelMerger::load(const QString &data, DifferenceHandler &differenceH
const QStringList importPaths = m_rewriterView->textModifier()->importPaths();
setActive(true);
- { // Have the QML engine check if the document is valid:
- QDeclarativeEngine engine;
- engine.setOutputWarningsToStandardError(false);
- QDeclarativeComponent comp(&engine);
- comp.setData(data.toUtf8(), url);
- if (comp.status() == QDeclarativeComponent::Error) {
- QList<RewriterView::Error> errors;
- foreach (const QDeclarativeError &error, comp.errors())
- errors.append(RewriterView::Error(error));
- m_rewriterView->setErrors(errors);
- setActive(false);
- return false;
- } else if (comp.status() == QDeclarativeComponent::Loading) {
- // Probably loading remote components. Previous DOM behaviour was:
- QList<RewriterView::Error> errors;
- errors.append(RewriterView::Error());
- m_rewriterView->setErrors(errors);
- setActive(false);
- return false;
- }
- }
try {
Snapshot snapshot = m_rewriterView->textModifier()->getSnapshot();
@@ -609,8 +586,32 @@ bool TextToModelMerger::load(const QString &data, DifferenceHandler &differenceH
Document::Ptr doc = Document::create(fileName.isEmpty() ? QLatin1String("<internal>") : fileName);
doc->setSource(data);
doc->parseQml();
+
+ if (!doc->isParsedCorrectly()) {
+ QList<RewriterView::Error> errors;
+ foreach (const QmlJS::DiagnosticMessage &message, doc->diagnosticMessages())
+ errors.append(RewriterView::Error(message, QUrl::fromLocalFile(doc->fileName())));
+ m_rewriterView->setErrors(errors);
+ setActive(false);
+ return false;
+ }
snapshot.insert(doc);
ReadingContext ctxt(snapshot, doc, importPaths);
+ m_lookupContext = ctxt.lookupContext();
+ m_document = doc;
+
+ QList<RewriterView::Error> errors;
+ Check check(doc, snapshot, m_lookupContext->context());
+ check.setIgnoreTypeErrors(true);
+ foreach (const QmlJS::DiagnosticMessage &diagnosticMessage, check())
+ if (diagnosticMessage.isError())
+ errors.append(RewriterView::Error(diagnosticMessage, QUrl::fromLocalFile(doc->fileName())));
+
+ if (!errors.isEmpty()) {
+ m_rewriterView->setErrors(errors);
+ setActive(false);
+ return false;
+ }
setupImports(doc, differenceHandler);
@@ -762,7 +763,7 @@ void TextToModelMerger::syncNode(ModelNode &modelNode,
const QVariant variantValue = convertDynamicPropertyValueToVariant(astValue, astType);
syncVariantProperty(modelProperty, variantValue, astType, differenceHandler);
} else {
- syncExpressionProperty(modelProperty, astValue, differenceHandler);
+ syncExpressionProperty(modelProperty, astValue, astType, differenceHandler);
}
modelPropertyNames.remove(astName);
} else {
@@ -854,12 +855,12 @@ QString TextToModelMerger::syncScriptBinding(ModelNode &modelNode,
const QVariant enumValue = context->convertToEnum(script->statement, prefix, script->qualifiedId);
if (enumValue.isValid()) { // It is a qualified enum:
AbstractProperty modelProperty = modelNode.property(astPropertyName);
- syncVariantProperty(modelProperty, enumValue, QString(), differenceHandler);
+ syncVariantProperty(modelProperty, enumValue, QString(), differenceHandler); // TODO: parse type
return astPropertyName;
} else { // Not an enum, so:
if (modelNode.type() == QLatin1String("Qt/PropertyChanges") || context->lookupProperty(prefix, script->qualifiedId)) {
AbstractProperty modelProperty = modelNode.property(astPropertyName);
- syncExpressionProperty(modelProperty, astValue, differenceHandler);
+ syncExpressionProperty(modelProperty, astValue, QString(), differenceHandler); // TODO: parse type
return astPropertyName;
} else {
qWarning() << "Skipping invalid expression property" << astPropertyName
@@ -918,15 +919,18 @@ void TextToModelMerger::syncNodeProperty(AbstractProperty &modelProperty,
void TextToModelMerger::syncExpressionProperty(AbstractProperty &modelProperty,
const QString &javascript,
+ const QString &astType,
DifferenceHandler &differenceHandler)
{
if (modelProperty.isBindingProperty()) {
BindingProperty bindingProperty = modelProperty.toBindingProperty();
- if (bindingProperty.expression() != javascript) {
- differenceHandler.bindingExpressionsDiffer(bindingProperty, javascript);
+ if (bindingProperty.expression() != javascript
+ || !astType.isEmpty() != bindingProperty.isDynamic()
+ || astType != bindingProperty.dynamicTypeName()) {
+ differenceHandler.bindingExpressionsDiffer(bindingProperty, javascript, astType);
}
} else {
- differenceHandler.shouldBeBindingProperty(modelProperty, javascript);
+ differenceHandler.shouldBeBindingProperty(modelProperty, javascript, astType);
}
}
@@ -1043,14 +1047,17 @@ void ModelValidator::importAbsentInQMl(const Import &import)
}
void ModelValidator::bindingExpressionsDiffer(BindingProperty &modelProperty,
- const QString &javascript)
+ const QString &javascript,
+ const QString &astType)
{
Q_ASSERT(modelProperty.expression() == javascript);
+ Q_ASSERT(modelProperty.dynamicTypeName() == astType);
Q_ASSERT(0);
}
void ModelValidator::shouldBeBindingProperty(AbstractProperty &modelProperty,
- const QString &/*javascript*/)
+ const QString &/*javascript*/,
+ const QString &/*astType*/)
{
Q_ASSERT(modelProperty.isBindingProperty());
Q_ASSERT(0);
@@ -1143,17 +1150,27 @@ void ModelAmender::importAbsentInQMl(const Import &import)
}
void ModelAmender::bindingExpressionsDiffer(BindingProperty &modelProperty,
- const QString &javascript)
+ const QString &javascript,
+ const QString &astType)
{
- modelProperty.toBindingProperty().setExpression(javascript);
+ if (astType.isEmpty()) {
+ modelProperty.setExpression(javascript);
+ } else {
+ modelProperty.setDynamicTypeNameAndExpression(astType, javascript);
+ }
}
void ModelAmender::shouldBeBindingProperty(AbstractProperty &modelProperty,
- const QString &javascript)
+ const QString &javascript,
+ const QString &astType)
{
ModelNode theNode = modelProperty.parentModelNode();
BindingProperty newModelProperty = theNode.bindingProperty(modelProperty.name());
- newModelProperty.setExpression(javascript);
+ if (astType.isEmpty()) {
+ newModelProperty.setExpression(javascript);
+ } else {
+ newModelProperty.setDynamicTypeNameAndExpression(astType, javascript);
+ }
}
void ModelAmender::shouldBeNodeListProperty(AbstractProperty &modelProperty,
diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h
index 12ae671f49..ed69cbbcc6 100644
--- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h
+++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h
@@ -39,7 +39,9 @@
#include "nodelistproperty.h"
#include "modelnode.h"
+#include <qmljs/qmljslookupcontext.h>
#include <qmljs/qmljsdocument.h>
+#include <qmljs/qmljslookupcontext.h>
#include <QtCore/QStringList>
@@ -67,6 +69,12 @@ public:
RewriterView *view() const
{ return m_rewriterView; }
+ QmlJS::LookupContext *lookupContext() const
+ { return m_lookupContext.data(); }
+
+ QmlJS::Document *document() const
+ { return m_document.data(); }
+
protected:
void setActive(bool active);
@@ -88,6 +96,7 @@ public:
DifferenceHandler &differenceHandler);
void syncExpressionProperty(AbstractProperty &modelProperty,
const QString &javascript,
+ const QString &astType,
DifferenceHandler &differenceHandler);
void syncArrayProperty(AbstractProperty &modelProperty,
const QList<QmlJS::AST::UiObjectMember *> &arrayMembers,
@@ -125,6 +134,8 @@ private:
private:
RewriterView *m_rewriterView;
bool m_isActive;
+ QmlJS::LookupContext::Ptr m_lookupContext;
+ QmlJS::Document::Ptr m_document;
};
class DifferenceHandler
@@ -139,9 +150,11 @@ public:
virtual void modelMissesImport(const Import &import) = 0;
virtual void importAbsentInQMl(const Import &import) = 0;
virtual void bindingExpressionsDiffer(BindingProperty &modelProperty,
- const QString &javascript) = 0;
+ const QString &javascript,
+ const QString &astType) = 0;
virtual void shouldBeBindingProperty(AbstractProperty &modelProperty,
- const QString &javascript) = 0;
+ const QString &javascript,
+ const QString &astType) = 0;
virtual void shouldBeNodeListProperty(AbstractProperty &modelProperty,
const QList<QmlJS::AST::UiObjectMember *> arrayMembers,
ReadingContext *context) = 0;
@@ -183,9 +196,11 @@ public:
virtual void modelMissesImport(const Import &import);
virtual void importAbsentInQMl(const Import &import);
virtual void bindingExpressionsDiffer(BindingProperty &modelProperty,
- const QString &javascript);
+ const QString &javascript,
+ const QString &astType);
virtual void shouldBeBindingProperty(AbstractProperty &modelProperty,
- const QString &javascript);
+ const QString &javascript,
+ const QString &astType);
virtual void shouldBeNodeListProperty(AbstractProperty &modelProperty,
const QList<QmlJS::AST::UiObjectMember *> arrayMembers,
ReadingContext *context);
@@ -224,9 +239,11 @@ public:
virtual void modelMissesImport(const Import &import);
virtual void importAbsentInQMl(const Import &import);
virtual void bindingExpressionsDiffer(BindingProperty &modelProperty,
- const QString &javascript);
+ const QString &javascript,
+ const QString &astType);
virtual void shouldBeBindingProperty(AbstractProperty &modelProperty,
- const QString &javascript);
+ const QString &javascript,
+ const QString &astType);
virtual void shouldBeNodeListProperty(AbstractProperty &modelProperty,
const QList<QmlJS::AST::UiObjectMember *> arrayMembers,
ReadingContext *context);
diff --git a/src/plugins/qmldesigner/designercore/model/viewlogger.cpp b/src/plugins/qmldesigner/designercore/model/viewlogger.cpp
index 7cb7f89300..5efc2712bb 100644
--- a/src/plugins/qmldesigner/designercore/model/viewlogger.cpp
+++ b/src/plugins/qmldesigner/designercore/model/viewlogger.cpp
@@ -114,6 +114,12 @@ void ViewLogger::nodeRemoved(const ModelNode &removedNode, const NodeAbstractPro
m_output << time() << indent("nodeRemoved:") << removedNode << parentProperty << serialize(propertyChange) << endl;
}
+void ViewLogger::nodeAboutToBeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange)
+{
+ m_output << time() << indent("nodeAboutToBeReparented:") << node << "\t" << newPropertyParent << "\t" << oldPropertyParent << "\t" << 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;
@@ -210,6 +216,14 @@ void ViewLogger::instancePropertyChange(const QList<QPair<ModelNode, QString> >
m_output << time() << indent("property: ") << propertyPair.first << propertyPair.second << endl;
}
+void ViewLogger::instancesCompleted(const QVector<ModelNode> &completedNodeList)
+{
+ m_output << time() << indent("instancesCompleted:") << endl;
+
+ foreach(const ModelNode &node, completedNodeList)
+ m_output << time() << indent("node: ") << node << endl;
+
+}
} // namespace Internal
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/model/viewlogger.h b/src/plugins/qmldesigner/designercore/model/viewlogger.h
index 73451e019a..cda87e2b22 100644
--- a/src/plugins/qmldesigner/designercore/model/viewlogger.h
+++ b/src/plugins/qmldesigner/designercore/model/viewlogger.h
@@ -54,6 +54,7 @@ public:
void nodeCreated(const ModelNode &createdNode);
void nodeAboutToBeRemoved(const ModelNode &removedNode);
void nodeRemoved(const ModelNode &removedNode, const NodeAbstractProperty &parentProperty, PropertyChangeFlags propertyChange);
+ void nodeAboutToBeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::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);
@@ -76,7 +77,7 @@ public:
void customNotification(const AbstractView *view, const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> &data);
void scriptFunctionsChanged(const ModelNode &node, const QStringList &scriptFunctionList);
void instancePropertyChange(const QList<QPair<ModelNode, QString> > &propertyList);
-
+ void instancesCompleted(const QVector<ModelNode> &completedNodeList);
protected:
QString time() const;
diff --git a/src/plugins/qmldesigner/designmodewidget.cpp b/src/plugins/qmldesigner/designmodewidget.cpp
index 3f48418b93..c00af1a864 100644
--- a/src/plugins/qmldesigner/designmodewidget.cpp
+++ b/src/plugins/qmldesigner/designmodewidget.cpp
@@ -39,6 +39,9 @@
#include <model.h>
#include <rewriterview.h>
#include <formeditorwidget.h>
+#include <stateseditorwidget.h>
+#include <itemlibrarywidget.h>
+
#include <coreplugin/coreconstants.h>
#include <coreplugin/modemanager.h>
@@ -76,8 +79,6 @@ using Core::EditorManager;
using namespace QmlDesigner;
-Q_DECLARE_METATYPE(Core::IEditor*)
-
enum {
debug = false
};
@@ -93,13 +94,12 @@ namespace QmlDesigner {
namespace Internal {
DocumentWarningWidget::DocumentWarningWidget(DesignModeWidget *parent) :
- QFrame(parent),
+ Utils::FakeToolTip(parent),
m_errorMessage(new QLabel("Placeholder", this)),
m_goToError(new QLabel(this)),
m_designModeWidget(parent)
{
- setFrameStyle(QFrame::Panel | QFrame::Raised);
- setLineWidth(1);
+ setWindowFlags(Qt::Widget); //We only want the visual style from a ToolTip
setForegroundRole(QPalette::ToolTipText);
setBackgroundRole(QPalette::ToolTipBase);
setAutoFillBackground(true);
@@ -132,6 +132,27 @@ void DocumentWarningWidget::setError(const RewriterView::Error &error)
resize(layout()->totalSizeHint());
}
+class ItemLibrarySideBarItem : public Core::SideBarItem
+{
+public:
+ explicit ItemLibrarySideBarItem(ItemLibraryWidget *widget, const QString &id);
+ virtual ~ItemLibrarySideBarItem();
+
+ virtual QList<QToolButton *> createToolBarWidgets();
+};
+
+ItemLibrarySideBarItem::ItemLibrarySideBarItem(ItemLibraryWidget *widget, const QString &id) : Core::SideBarItem(widget, id) {}
+
+ItemLibrarySideBarItem::~ItemLibrarySideBarItem()
+{
+
+}
+
+QList<QToolButton *> ItemLibrarySideBarItem::createToolBarWidgets()
+{
+ return qobject_cast<ItemLibraryWidget*>(widget())->createToolBarWidgets();
+}
+
void DocumentWarningWidget::goToError()
{
m_designModeWidget->textEditor()->gotoLine(m_error.line(), m_error.column());
@@ -217,8 +238,8 @@ void DesignModeWidget::toggleSidebars()
m_leftSideBar->setVisible(m_showSidebars);
if (m_rightSideBar)
m_rightSideBar->setVisible(m_showSidebars);
- if (!m_statesEditorWidget.isNull())
- m_statesEditorWidget->setVisible(m_showSidebars);
+ if (!m_statesEditorView.isNull())
+ m_statesEditorView->widget()->setVisible(m_showSidebars);
}
@@ -267,8 +288,8 @@ void DesignModeWidget::showEditor(Core::IEditor *editor)
newDocument->setNodeInstanceView(m_nodeInstanceView.data());
newDocument->setAllPropertiesBox(m_allPropertiesBox.data());
newDocument->setNavigator(m_navigator.data());
- newDocument->setStatesEditorWidget(m_statesEditorWidget.data());
- newDocument->setItemLibrary(m_itemLibrary.data());
+ newDocument->setStatesEditorView(m_statesEditorView.data());
+ newDocument->setItemLibraryView(m_itemLibraryView.data());
newDocument->setFormEditorView(m_formEditorView.data());
@@ -454,7 +475,7 @@ void DesignModeWidget::enable()
qDebug() << Q_FUNC_INFO;
m_warningWidget->setVisible(false);
m_formEditorView->widget()->setEnabled(true);
- m_statesEditorWidget->setEnabled(true);
+ m_statesEditorView->widget()->setEnabled(true);
m_leftSideBar->setEnabled(true);
m_rightSideBar->setEnabled(true);
m_isDisabled = false;
@@ -469,7 +490,7 @@ void DesignModeWidget::disable(const QList<RewriterView::Error> &errors)
m_warningWidget->setVisible(true);
m_warningWidget->move(width() / 2, height() / 2);
m_formEditorView->widget()->setEnabled(false);
- m_statesEditorWidget->setEnabled(false);
+ m_statesEditorView->widget()->setEnabled(false);
m_leftSideBar->setEnabled(false);
m_rightSideBar->setEnabled(false);
m_isDisabled = true;
@@ -631,9 +652,9 @@ void DesignModeWidget::setup()
// Sidebar takes ownership
m_navigator = new NavigatorView;
m_allPropertiesBox = new AllPropertiesBox;
- m_itemLibrary = new ItemLibrary;
+ m_itemLibraryView = new ItemLibraryView(this);
- m_statesEditorWidget = new StatesEditorWidget(this);
+ m_statesEditorView = new StatesEditorView(this);
m_formEditorView = new FormEditorView(this);
@@ -647,7 +668,7 @@ void DesignModeWidget::setup()
m_warningWidget->setVisible(false);
Core::SideBarItem *navigatorItem = new Core::SideBarItem(m_navigator->widget(), QLatin1String(SB_NAVIGATOR));
- Core::SideBarItem *libraryItem = new Core::SideBarItem(m_itemLibrary.data(), QLatin1String(SB_LIBRARY));
+ Core::SideBarItem *libraryItem = new ItemLibrarySideBarItem(m_itemLibraryView->widget(), QLatin1String(SB_LIBRARY));
Core::SideBarItem *propertiesItem = new Core::SideBarItem(m_allPropertiesBox.data(), QLatin1String(SB_PROPERTIES));
// default items
@@ -674,6 +695,9 @@ void DesignModeWidget::setup()
connect(m_leftSideBar, SIGNAL(availableItemsChanged()), SLOT(updateAvailableSidebarItemsRight()));
connect(m_rightSideBar, SIGNAL(availableItemsChanged()), SLOT(updateAvailableSidebarItemsLeft()));
+ connect(Core::ICore::instance(), SIGNAL(coreAboutToClose()),
+ this, SLOT(deleteSidebarWidgets()));
+
m_fakeToolBar->setToolbarCreationFlags(Core::EditorToolBar::FlagsStandalone);
//m_fakeToolBar->addEditor(textEditor()); ### what does this mean?
m_fakeToolBar->setNavigationVisible(false);
@@ -688,7 +712,7 @@ void DesignModeWidget::setup()
rightLayout->setSpacing(0);
rightLayout->addWidget(m_fakeToolBar);
//### we now own these here
- rightLayout->addWidget(m_statesEditorWidget.data());
+ rightLayout->addWidget(m_statesEditorView->widget());
FormEditorContext *context = new FormEditorContext(m_formEditorView->widget());
Core::ICore::instance()->addContextObject(context);
@@ -718,7 +742,7 @@ void DesignModeWidget::setup()
mainLayout->addWidget(m_mainSplitter);
m_warningWidget->setVisible(false);
- m_statesEditorWidget->setEnabled(true);
+ m_statesEditorView->widget()->setEnabled(true);
m_leftSideBar->setEnabled(true);
m_rightSideBar->setEnabled(true);
m_leftSideBar->setCloseWhenEmpty(true);
@@ -742,6 +766,14 @@ void DesignModeWidget::updateAvailableSidebarItemsLeft()
m_leftSideBar->setUnavailableItemIds(m_rightSideBar->unavailableItemIds());
}
+void DesignModeWidget::deleteSidebarWidgets()
+{
+ delete m_leftSideBar;
+ delete m_rightSideBar;
+ m_leftSideBar = 0;
+ m_rightSideBar = 0;
+}
+
void DesignModeWidget::resizeEvent(QResizeEvent *event)
{
if (m_warningWidget)
diff --git a/src/plugins/qmldesigner/designmodewidget.h b/src/plugins/qmldesigner/designmodewidget.h
index 4f08f57175..4f7cdd28ba 100644
--- a/src/plugins/qmldesigner/designmodewidget.h
+++ b/src/plugins/qmldesigner/designmodewidget.h
@@ -36,20 +36,20 @@
#include <coreplugin/minisplitter.h>
#include <coreplugin/editormanager/ieditor.h>
+#include <utils/faketooltip.h>
#include <texteditor/itexteditor.h>
#include <integrationcore.h>
#include <allpropertiesbox.h>
#include <designdocumentcontroller.h>
-#include <itemlibrary.h>
+#include <itemlibraryview.h>
#include <navigatorwidget.h>
#include <navigatorview.h>
-#include <stateseditorwidget.h>
+#include <stateseditorview.h>
#include <modelnode.h>
#include <formeditorview.h>
-
#include <QWeakPointer>
#include <QDeclarativeError>
#include <QtCore/QHash>
@@ -75,13 +75,15 @@ namespace Core {
namespace QmlDesigner {
+class ItemLibraryWidget;
+
namespace Internal {
class DesignMode;
class DocumentWidget;
class DesignModeWidget;
-class DocumentWarningWidget : public QFrame
+class DocumentWarningWidget : public Utils::FakeToolTip
{
Q_OBJECT
Q_DISABLE_COPY(DocumentWarningWidget)
@@ -152,6 +154,8 @@ private slots:
void updateAvailableSidebarItemsLeft();
void updateAvailableSidebarItemsRight();
+ void deleteSidebarWidgets();
+
protected:
void resizeEvent(QResizeEvent *event);
@@ -176,10 +180,10 @@ private:
QAction *m_toggleLeftSidebarAction;
QAction *m_toggleRightSidebarAction;
- QWeakPointer<ItemLibrary> m_itemLibrary;
+ QWeakPointer<ItemLibraryView> m_itemLibraryView;
QWeakPointer<NavigatorView> m_navigator;
QWeakPointer<AllPropertiesBox> m_allPropertiesBox;
- QWeakPointer<StatesEditorWidget> m_statesEditorWidget;
+ QWeakPointer<StatesEditorView> m_statesEditorView;
QWeakPointer<FormEditorView> m_formEditorView;
QWeakPointer<NodeInstanceView> m_nodeInstanceView;
diff --git a/src/plugins/qmldesigner/meegoplugin/images/button.png b/src/plugins/qmldesigner/meegoplugin/images/button.png
new file mode 100644
index 0000000000..8306aa97e7
--- /dev/null
+++ b/src/plugins/qmldesigner/meegoplugin/images/button.png
Binary files differ
diff --git a/src/plugins/qmldesigner/meegoplugin/images/button16.png b/src/plugins/qmldesigner/meegoplugin/images/button16.png
new file mode 100644
index 0000000000..c8c9684ab5
--- /dev/null
+++ b/src/plugins/qmldesigner/meegoplugin/images/button16.png
Binary files differ
diff --git a/src/plugins/qmldesigner/meegoplugin/images/checkbox.png b/src/plugins/qmldesigner/meegoplugin/images/checkbox.png
new file mode 100644
index 0000000000..df91fb6458
--- /dev/null
+++ b/src/plugins/qmldesigner/meegoplugin/images/checkbox.png
Binary files differ
diff --git a/src/plugins/qmldesigner/meegoplugin/images/checkbox16.png b/src/plugins/qmldesigner/meegoplugin/images/checkbox16.png
new file mode 100644
index 0000000000..e522c0113f
--- /dev/null
+++ b/src/plugins/qmldesigner/meegoplugin/images/checkbox16.png
Binary files differ
diff --git a/src/plugins/qmldesigner/meegoplugin/images/item-icon.png b/src/plugins/qmldesigner/meegoplugin/images/item-icon.png
new file mode 100644
index 0000000000..fc53d38ae7
--- /dev/null
+++ b/src/plugins/qmldesigner/meegoplugin/images/item-icon.png
Binary files differ
diff --git a/src/plugins/qmldesigner/meegoplugin/images/item-icon16.png b/src/plugins/qmldesigner/meegoplugin/images/item-icon16.png
new file mode 100644
index 0000000000..7d2d7a5050
--- /dev/null
+++ b/src/plugins/qmldesigner/meegoplugin/images/item-icon16.png
Binary files differ
diff --git a/src/plugins/qmldesigner/meegoplugin/images/label.png b/src/plugins/qmldesigner/meegoplugin/images/label.png
new file mode 100644
index 0000000000..e622f68687
--- /dev/null
+++ b/src/plugins/qmldesigner/meegoplugin/images/label.png
Binary files differ
diff --git a/src/plugins/qmldesigner/meegoplugin/images/label16.png b/src/plugins/qmldesigner/meegoplugin/images/label16.png
new file mode 100644
index 0000000000..0478d429f6
--- /dev/null
+++ b/src/plugins/qmldesigner/meegoplugin/images/label16.png
Binary files differ
diff --git a/src/plugins/qmldesigner/meegoplugin/images/lineedit.png b/src/plugins/qmldesigner/meegoplugin/images/lineedit.png
new file mode 100644
index 0000000000..f521cd513e
--- /dev/null
+++ b/src/plugins/qmldesigner/meegoplugin/images/lineedit.png
Binary files differ
diff --git a/src/plugins/qmldesigner/meegoplugin/images/lineedit16.png b/src/plugins/qmldesigner/meegoplugin/images/lineedit16.png
new file mode 100644
index 0000000000..549803910d
--- /dev/null
+++ b/src/plugins/qmldesigner/meegoplugin/images/lineedit16.png
Binary files differ
diff --git a/src/plugins/qmldesigner/meegoplugin/images/progressbar.png b/src/plugins/qmldesigner/meegoplugin/images/progressbar.png
new file mode 100644
index 0000000000..9d1f1df7ed
--- /dev/null
+++ b/src/plugins/qmldesigner/meegoplugin/images/progressbar.png
Binary files differ
diff --git a/src/plugins/qmldesigner/meegoplugin/images/progressbar16.png b/src/plugins/qmldesigner/meegoplugin/images/progressbar16.png
new file mode 100644
index 0000000000..297ca1c906
--- /dev/null
+++ b/src/plugins/qmldesigner/meegoplugin/images/progressbar16.png
Binary files differ
diff --git a/src/plugins/qmldesigner/meegoplugin/images/radiobutton.png b/src/plugins/qmldesigner/meegoplugin/images/radiobutton.png
new file mode 100644
index 0000000000..52cd6a514a
--- /dev/null
+++ b/src/plugins/qmldesigner/meegoplugin/images/radiobutton.png
Binary files differ
diff --git a/src/plugins/qmldesigner/meegoplugin/images/radiobutton16.png b/src/plugins/qmldesigner/meegoplugin/images/radiobutton16.png
new file mode 100644
index 0000000000..af09affb92
--- /dev/null
+++ b/src/plugins/qmldesigner/meegoplugin/images/radiobutton16.png
Binary files differ
diff --git a/src/plugins/qmldesigner/meegoplugin/images/slider.png b/src/plugins/qmldesigner/meegoplugin/images/slider.png
new file mode 100644
index 0000000000..687185bffd
--- /dev/null
+++ b/src/plugins/qmldesigner/meegoplugin/images/slider.png
Binary files differ
diff --git a/src/plugins/qmldesigner/meegoplugin/images/slider16.png b/src/plugins/qmldesigner/meegoplugin/images/slider16.png
new file mode 100644
index 0000000000..3a2fbe8d0f
--- /dev/null
+++ b/src/plugins/qmldesigner/meegoplugin/images/slider16.png
Binary files differ
diff --git a/src/plugins/qmldesigner/meegoplugin/meego.metainfo b/src/plugins/qmldesigner/meegoplugin/meego.metainfo
new file mode 100644
index 0000000000..fdd8fdb6f4
--- /dev/null
+++ b/src/plugins/qmldesigner/meegoplugin/meego.metainfo
@@ -0,0 +1,27 @@
+<metainfo>
+ <node name="Label" icon=":/meegoplugin/images/label16.png">
+ <itemlibraryentry name="Label" category="Components MeeGo" libraryIcon=":/meegoplugin/images/label.png" requiredImport="com.meego">
+ <property name="text" type="QString" value="Label"/>
+ </itemlibraryentry>
+ </node>
+ <node name="Button" icon=":/meegoplugin/images/button16.png">
+ <itemlibraryentry name="Button" category="Components MeeGo" libraryIcon=":/meegoplugin/images/button.png" requiredImport="com.meego">
+ </itemlibraryentry>
+ </node>
+ <node name="Slider" icon=":/meegoplugin/images/slider16.png">
+ <itemlibraryentry name="Slider" category="Components MeeGo" libraryIcon=":/meegoplugin/images/slider.png" requiredImport="com.meego">
+ </itemlibraryentry>
+ </node>
+ <node name="CheckBox" icon=":/meegoplugin/images/checkbox16.png">
+ <itemlibraryentry name="CheckBox" category="Components MeeGo" libraryIcon=":/meegoplugin/images/checkbox.png" requiredImport="com.meego">
+ </itemlibraryentry>
+ </node>
+ <node name="Spinner" icon=":/meegoplugin/images/item-icon16.png">
+ <itemlibraryentry name="Spinner" category="Components MeeGo" libraryIcon=":/meegoplugin/images/item-icon.png" requiredImport="com.meego">
+ </itemlibraryentry>
+ </node>
+ <node name="LineEdit" icon=":/meegoplugin/images/lineedit16.png">
+ <itemlibraryentry name="LineEdit" category="Components MeeGo" libraryIcon=":/meegoplugin/images/lineedit.png" requiredImport="com.meego">
+ </itemlibraryentry>
+ </node>
+</metainfo>
diff --git a/src/plugins/qmldesigner/meegoplugin/meegoplugin.cpp b/src/plugins/qmldesigner/meegoplugin/meegoplugin.cpp
new file mode 100644
index 0000000000..6eaaa0c564
--- /dev/null
+++ b/src/plugins/qmldesigner/meegoplugin/meegoplugin.cpp
@@ -0,0 +1,54 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "meegoplugin.h"
+#include <widgetplugin_helper.h>
+#include <QtCore/QtPlugin>
+
+namespace QmlDesigner {
+
+
+MeegoPlugin::MeegoPlugin()
+{
+}
+
+QString MeegoPlugin::pluginName()
+{
+ return ("MeegoPlugin");
+}
+
+QString MeegoPlugin::metaInfo()
+{
+ return QString(":/meegoplugin/meego.metainfo");
+}
+
+}
+
+Q_EXPORT_PLUGIN(QmlDesigner::MeegoPlugin)
+
diff --git a/src/plugins/qmldesigner/meegoplugin/meegoplugin.h b/src/plugins/qmldesigner/meegoplugin/meegoplugin.h
new file mode 100644
index 0000000000..3e05d60075
--- /dev/null
+++ b/src/plugins/qmldesigner/meegoplugin/meegoplugin.h
@@ -0,0 +1,58 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 MEEGOPLUGIN_H
+#define MEEGOPLUGIN_H
+
+#include <iwidgetplugin.h>
+#include <QtDeclarative/qdeclarative.h>
+
+QT_BEGIN_NAMESPACE
+QT_END_NAMESPACE
+
+namespace QmlDesigner {
+
+class MeegoPlugin : public QObject, QmlDesigner::IWidgetPlugin
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(MeegoPlugin)
+ Q_INTERFACES(QmlDesigner::IWidgetPlugin)
+public:
+ MeegoPlugin();
+ ~MeegoPlugin() {}
+
+ QString metaInfo();
+ QString pluginName();
+
+};
+
+} // namespace QmlDesigner
+
+
+#endif // MEEGOPLUGIN_H
diff --git a/src/plugins/qmldesigner/meegoplugin/meegoplugin.pri b/src/plugins/qmldesigner/meegoplugin/meegoplugin.pri
new file mode 100644
index 0000000000..04abc89874
--- /dev/null
+++ b/src/plugins/qmldesigner/meegoplugin/meegoplugin.pri
@@ -0,0 +1,17 @@
+TARGET = meegoplugin
+TEMPLATE = lib
+CONFIG += plugin
+
+QT += script \
+ declarative
+
+include (../designercore/iwidgetplugin.pri)
+
+DEFINES += SYMBIAN_LIBRARY
+SOURCES += $$PWD/meegoplugin.cpp
+
+HEADERS += $$PWD/meegoplugin.h $$PWD/../designercore/include/iwidgetplugin.h
+
+RESOURCES += $$PWD/meegoplugin.qrc
+
+OTHER_FILES += $$PWD/meego.metainfo
diff --git a/src/plugins/qmldesigner/meegoplugin/meegoplugin.pro b/src/plugins/qmldesigner/meegoplugin/meegoplugin.pro
new file mode 100644
index 0000000000..7781017a17
--- /dev/null
+++ b/src/plugins/qmldesigner/meegoplugin/meegoplugin.pro
@@ -0,0 +1,4 @@
+include(../../../../qtcreator.pri)
+include(../../../private_headers.pri)
+include(meegoplugin.pri)
+include(plugindestdir.pri)
diff --git a/src/plugins/qmldesigner/meegoplugin/meegoplugin.qrc b/src/plugins/qmldesigner/meegoplugin/meegoplugin.qrc
new file mode 100644
index 0000000000..d46243ec9e
--- /dev/null
+++ b/src/plugins/qmldesigner/meegoplugin/meegoplugin.qrc
@@ -0,0 +1,21 @@
+<RCC>
+ <qresource prefix="/meegoplugin">
+ <file>meego.metainfo</file>
+ <file>images/item-icon16.png</file>
+ <file>images/item-icon.png</file>
+ <file>images/button.png</file>
+ <file>images/button16.png</file>
+ <file>images/checkbox.png</file>
+ <file>images/checkbox16.png</file>
+ <file>images/label.png</file>
+ <file>images/label16.png</file>
+ <file>images/lineedit.png</file>
+ <file>images/lineedit16.png</file>
+ <file>images/progressbar.png</file>
+ <file>images/progressbar16.png</file>
+ <file>images/radiobutton.png</file>
+ <file>images/radiobutton16.png</file>
+ <file>images/slider.png</file>
+ <file>images/slider16.png</file>
+ </qresource>
+</RCC>
diff --git a/src/plugins/qmldesigner/meegoplugin/plugindestdir.pri b/src/plugins/qmldesigner/meegoplugin/plugindestdir.pri
new file mode 100644
index 0000000000..24f0c19b72
--- /dev/null
+++ b/src/plugins/qmldesigner/meegoplugin/plugindestdir.pri
@@ -0,0 +1,5 @@
+macx {
+ DESTDIR = $$IDE_LIBRARY_PATH/QmlDesigner
+} else {
+ DESTDIR = $$IDE_BUILD_TREE/lib/qmldesigner
+}
diff --git a/src/plugins/qmldesigner/qmldesigner.pro b/src/plugins/qmldesigner/qmldesigner.pro
index 9ce8190cc4..1c1a3735f3 100644
--- a/src/plugins/qmldesigner/qmldesigner.pro
+++ b/src/plugins/qmldesigner/qmldesigner.pro
@@ -1,3 +1,3 @@
TEMPLATE = subdirs
-SUBDIRS = qmldesignerplugin.pro qtquickplugin
+SUBDIRS = qmldesignerplugin.pro qtquickplugin symbianplugin meegoplugin
diff --git a/src/plugins/qmldesigner/qmldesignerplugin.cpp b/src/plugins/qmldesigner/qmldesignerplugin.cpp
index 41c54f58fa..ac7c50d1ef 100644
--- a/src/plugins/qmldesigner/qmldesignerplugin.cpp
+++ b/src/plugins/qmldesigner/qmldesignerplugin.cpp
@@ -44,6 +44,7 @@
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
+#include <coreplugin/uniqueidmanager.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/designmode.h>
#include <coreplugin/dialogs/iwizard.h>
diff --git a/src/plugins/qmldesigner/qmldesignerplugin.pro b/src/plugins/qmldesigner/qmldesignerplugin.pro
index 8d563ddf94..ad7cf4efbf 100644
--- a/src/plugins/qmldesigner/qmldesignerplugin.pro
+++ b/src/plugins/qmldesigner/qmldesignerplugin.pro
@@ -34,5 +34,3 @@ SOURCES += qmldesignerplugin.cpp \
styledoutputpaneplaceholder.cpp
FORMS += settingspage.ui
-
-OTHER_FILES += QmlDesigner.pluginspec
diff --git a/src/plugins/qmldesigner/qtquickplugin/qtquickplugin.cpp b/src/plugins/qmldesigner/qtquickplugin/qtquickplugin.cpp
index 13ea0b65dc..fd41919148 100644
--- a/src/plugins/qmldesigner/qtquickplugin/qtquickplugin.cpp
+++ b/src/plugins/qmldesigner/qtquickplugin/qtquickplugin.cpp
@@ -42,6 +42,7 @@ namespace QmlDesigner {
QtQuickPlugin::QtQuickPlugin()
{
+
qmlRegisterType<QDeclarativePen>("Qt", 4, 7, "Pen");
qmlRegisterType<QDeclarativeScaleGrid>("Qt", 4, 7, "ScaleGrid");
}
diff --git a/src/plugins/qmldesigner/qtquickplugin/quick.metainfo b/src/plugins/qmldesigner/qtquickplugin/quick.metainfo
index 781e6352cb..0f834f6771 100644
--- a/src/plugins/qmldesigner/qtquickplugin/quick.metainfo
+++ b/src/plugins/qmldesigner/qtquickplugin/quick.metainfo
@@ -1,43 +1,35 @@
<metainfo>
- <node name="Qt/Item" isContainer="true" icon=":/qtquickplugin/images/item-icon16.png">
- <propertyDefaultValue name="width" type="int" defaultValue="600"/>
- <propertyDefaultValue name="height" type="int" defaultValue="400"/>
- <itemlibraryentry name="Item" category="Qt - Basic" icon=":/qtquickplugin/images/item-icon.png">
+ <node name="Qt/Item" icon=":/qtquickplugin/images/item-icon16.png">
+ <itemlibraryentry name="Item" category="Qt Quick - Basic" libraryIcon=":/qtquickplugin/images/item-icon.png" version="4.7">
<property name="width" type="int" value="200"/>
<property name="height" type="int" value="200"/>
</itemlibraryentry>
</node>
- <node name="Qt/Rectangle" category="Qt - Basic" isContainer="true" icon=":/qtquickplugin/images/rect-icon16.png">
- <itemlibraryentry name="Rectangle" category="Qt - Basic" icon=":/qtquickplugin/images/rect-icon.png">
- <property name="width" type="int" value="100"/>
- <property name="height" type="int" value="100"/>
+ <node name="Qt/Rectangle" icon=":/qtquickplugin/images/rect-icon16.png">
+ <itemlibraryentry name="Rectangle" category="Qt Quick - Basic" libraryIcon=":/qtquickplugin/images/rect-icon.png" version="4.7">
<property name="color" type="QColor" value="#ffffff"/>
+ <property name="width" type="int" value="200"/>
+ <property name="height" type="int" value="200"/>
</itemlibraryentry>
</node>
<node name="Qt/Text" icon=":/qtquickplugin/images/text-icon16.png">
- <propertyDefaultValue name="width" type="int" defaultValue="80"/>
- <propertyDefaultValue name="height" type="int" defaultValue="20"/>
- <itemlibraryentry name="Text" category="Qt - Basic" icon=":/qtquickplugin/images/text-icon.png">
+ <itemlibraryentry name="Text" category="Qt Quick - Basic" libraryIcon=":/qtquickplugin/images/text-icon.png" version="4.7">
<property name="width" type="int" value="80"/>
<property name="height" type="int" value="20"/>
<property name="text" type="QString" value="text"/>
<property name="font.pixelSize" type="int" value="12"/>
</itemlibraryentry>
</node>
- <node name="Qt/TextEdit" isContainer="false" icon=":/qtquickplugin/images/text-edit-icon16.png">
- <propertyDefaultValue name="width" type="int" defaultValue="80"/>
- <propertyDefaultValue name="height" type="int" defaultValue="20"/>
- <itemlibraryentry name="Text Edit" category="Qt - Basic" icon=":/qtquickplugin/images/text-edit-icon.png">
+ <node name="Qt/TextEdit" icon=":/qtquickplugin/images/text-edit-icon16.png">
+ <itemlibraryentry name="Text Edit" category="Qt Quick - Basic" libraryIcon=":/qtquickplugin/images/text-edit-icon.png" version="4.7">
<property name="width" type="int" value="80"/>
<property name="height" type="int" value="20"/>
<property name="text" type="QString" value="textEdit"/>
<property name="font.pixelSize" type="int" value="12"/>
</itemlibraryentry>
</node>
- <node name="Qt/TextInput" isContainer="false" icon=":/qtquickplugin/images/text-input-icon16.png">
- <propertyDefaultValue name="width" type="int" defaultValue="80"/>
- <propertyDefaultValue name="height" type="int" defaultValue="20"/>
- <itemlibraryentry name="Text Input" category="Qt - Basic" icon=":/qtquickplugin/images/text-input-icon.png">
+ <node name="Qt/TextInput" icon=":/qtquickplugin/images/text-input-icon16.png">
+ <itemlibraryentry name="Text Input" category="Qt Quick - Basic" libraryIcon=":/qtquickplugin/images/text-input-icon.png" version="4.7">
<property name="width" type="int" value="80"/>
<property name="height" type="int" value="20"/>
<property name="text" type="QString" value="textInput"/>
@@ -45,82 +37,93 @@
</itemlibraryentry>
</node>
<node name="Qt/MouseArea" icon=":/qtquickplugin/images/mouse-area-icon16.png">
- <itemlibraryentry name="Mouse Area" category="Qt - Interaction" icon=":/qtquickplugin/images/mouse-area-icon.png">
+ <itemlibraryentry name="Mouse Area" category="Qt Quick - Basic" libraryIcon=":/qtquickplugin/images/mouse-area-icon.png" version="4.7">
<property name="width" type="int" value="100"/>
<property name="height" type="int" value="100"/>
</itemlibraryentry>
</node>
- <node name="Qt/Image" isContainer="true" icon=":/qtquickplugin/images/image-icon16.png">
- <propertyDefaultValue name="width" type="int" defaultValue="200"/>
- <propertyDefaultValue name="height" type="int" defaultValue="200"/>
- <itemlibraryentry name="Image" category="Qt - Basic" icon=":/qtquickplugin/images/image-icon.png">
+ <node name="Qt/Image" icon=":/qtquickplugin/images/image-icon16.png">
+ <itemlibraryentry name="Image" category="Qt Quick - Basic" libraryIcon=":/qtquickplugin/images/image-icon.png" version="4.7">
<property name="width" type="int" value="100"/>
<property name="height" type="int" value="100"/>
<property name="source" type="QUrl" value="qrc:/qtquickplugin/images/template_image.png"/>
</itemlibraryentry>
</node>
<node name="Qt/BorderImage" icon=":/qtquickplugin/images/border-image-icon16.png">
- <propertyDefaultValue name="width" type="int" defaultValue="200"/>
- <propertyDefaultValue name="height" type="int" defaultValue="200"/>
- <itemlibraryentry name="Border Image" category="Qt - Basic" icon=":/qtquickplugin/images/border-image-icon.png">
+ <itemlibraryentry name="Border Image" category="Qt Quick - Basic" libraryIcon=":/qtquickplugin/images/border-image-icon.png" version="4.7">
<property name="width" type="int" value="100"/>
<property name="height" type="int" value="100"/>
<property name="source" type="QUrl" value="qrc:/qtquickplugin/images/template_image.png"/>
</itemlibraryentry>
</node>
<node name="Qt/Flickable" icon=":/qtquickplugin/images/flickable-icon16.png">
- <propertyDefaultValue name="width" type="int" defaultValue="300"/>
- <propertyDefaultValue name="height" type="int" defaultValue="300"/>
- <itemlibraryentry name="Flickable" category="Qt - Widgets" icon=":/qtquickplugin/images/flickable-icon.png">
+ <itemlibraryentry name="Flickable" category="Qt Quick - Basic" libraryIcon=":/qtquickplugin/images/flickable-icon.png" version="4.7">
<property name="width" type="int" value="300"/>
<property name="height" type="int" value="300"/>
</itemlibraryentry>
</node>
<node name="Qt/Flipable" icon=":/qtquickplugin/images/flipable-icon16.png">
- <propertyDefaultValue name="width" type="int" defaultValue="300"/>
- <propertyDefaultValue name="height" type="int" defaultValue="300"/>
- <itemlibraryentry name="Flipable" category="Qt - Widgets" icon=":/qtquickplugin/images/flipable-icon.png">
+ <itemlibraryentry name="Flipable" category="Qt Quick - Basic" libraryIcon=":/qtquickplugin/images/flipable-icon.png" version="4.7">
<property name="width" type="int" value="300"/>
<property name="height" type="int" value="300"/>
</itemlibraryentry>
</node>
<node name="Qt/GridView" icon=":/qtquickplugin/images/gridview-icon16.png">
- <itemlibraryentry name="Grid View" category="Qt - Views" icon=":/qtquickplugin/images/gridview-icon.png">
+ <itemlibraryentry name="Grid View" category="Qt Quick - Views" libraryIcon=":/qtquickplugin/images/gridview-icon.png" version="4.7">
<property name="width" type="int" value="300"/>
<property name="height" type="int" value="300"/>
</itemlibraryentry>
</node>
<node name="Qt/ListView" icon=":/qtquickplugin/images/listview-icon16.png">
- <itemlibraryentry name="List View" category="Qt - Views" icon=":/qtquickplugin/images/listview-icon.png">
+ <itemlibraryentry name="List View" category="Qt Quick - Views" libraryIcon=":/qtquickplugin/images/listview-icon.png" version="4.7">
<property name="width" type="int" value="300"/>
<property name="height" type="int" value="300"/>
</itemlibraryentry>
</node>
<node name="Qt/PathView" icon=":/qtquickplugin/images/pathview-icon16.png">
- <itemlibraryentry name="Path View" category="Qt - Views" icon=":/qtquickplugin/images/pathview-icon.png">
+ <itemlibraryentry name="Path View" category="Qt Quick - Views" libraryIcon=":/qtquickplugin/images/pathview-icon.png" version="4.7">
<property name="width" type="int" value="300"/>
<property name="height" type="int" value="300"/>
</itemlibraryentry>
</node>
<node name="Qt/FocusScope" icon=":/qtquickplugin/images/focusscope-icon16.png">
- <propertyDefaultValue name="width" type="int" defaultValue="100"/>
- <propertyDefaultValue name="height" type="int" defaultValue="100"/>
- <itemlibraryentry name="Focus Scope" category="Qt - Interaction" icon=":/qtquickplugin/images/focusscope-icon.png">
+ <itemlibraryentry name="Focus Scope" category="Qt Quick - Basic" libraryIcon=":/qtquickplugin/images/focusscope-icon.png" version="4.7">
<property name="width" type="int" value="100"/>
<property name="height" type="int" value="100"/>
</itemlibraryentry>
</node>
-
<node name="QtWebKit/WebView" icon=":/qtquickplugin/images/webview-icon16.png">
- <propertyDefaultValue name="width" type="int" defaultValue="300"/>
- <propertyDefaultValue name="height" type="int" defaultValue="300"/>
- <itemlibraryentry name="Web View" category="Qt - Widgets" icon=":/qtquickplugin/images/webview-icon.png">
+ <itemlibraryentry name="Web View" category="Qt Quick - Basic" libraryIcon=":/qtquickplugin/images/webview-icon.png" version="1.0">
<property name="width" type="int" value="300"/>
<property name="height" type="int" value="300"/>
<property name="url" type="QString" value="http://qt.nokia.com"/>
</itemlibraryentry>
</node>
-</metainfo>
+ <node name="Qt/Row" icon=":/qtquickplugin/images/item-icon16.png">
+ <itemlibraryentry name="Row" category="Qt Quick - Positioner" libraryIcon=":/qtquickplugin/images/item-icon.png" version="4.7">
+ <property name="width" type="int" value="400"/>
+ <property name="height" type="int" value="200"/>
+ </itemlibraryentry>
+ </node>
+ <node name="Qt/Column" icon=":/qtquickplugin/images/item-icon16.png">
+ <itemlibraryentry name="Column" category="Qt Quick - Positioner" libraryIcon=":/qtquickplugin/images/item-icon.png" version="4.7">
+ <property name="width" type="int" value="200"/>
+ <property name="height" type="int" value="400"/>
+ </itemlibraryentry>
+ </node>
+ <node name="Qt/Grid" icon=":/qtquickplugin/images/item-icon16.png">
+ <itemlibraryentry name="Grid" category="Qt Quick - Positioner" libraryIcon=":/qtquickplugin/images/item-icon.png" version="4.7">
+ <property name="width" type="int" value="400"/>
+ <property name="height" type="int" value="400"/>
+ </itemlibraryentry>
+ </node>
+ <node name="Qt/Flow" icon=":/qtquickplugin/images/item-icon16.png">
+ <itemlibraryentry name="Flow" category="Qt Quick - Positioner" libraryIcon=":/qtquickplugin/images/item-icon.png" version="4.7">
+ <property name="width" type="int" value="400"/>
+ <property name="height" type="int" value="400"/>
+ </itemlibraryentry>
+ </node>
+ </metainfo>
diff --git a/src/plugins/qmldesigner/settingspage.cpp b/src/plugins/qmldesigner/settingspage.cpp
index 0df70b369a..9bb1d1cca2 100644
--- a/src/plugins/qmldesigner/settingspage.cpp
+++ b/src/plugins/qmldesigner/settingspage.cpp
@@ -66,8 +66,8 @@ QString SettingsPageWidget::searchKeywords() const
{
QString rc;
QTextStream(&rc)
- << ' ' << m_ui.snapMarginLabel
- << ' ' << m_ui.itemSpacingLabel;
+ << ' ' << m_ui.snapMarginLabel->text()
+ << ' ' << m_ui.itemSpacingLabel->text();
rc.remove(QLatin1Char('&'));
return rc;
}
@@ -113,6 +113,8 @@ QWidget *SettingsPage::createPage(QWidget *parent)
void SettingsPage::apply()
{
+ if (!m_widget) // page was never shown
+ return;
BauhausPlugin::pluginInstance()->setSettings(m_widget->settings());
}
diff --git a/src/plugins/qmldesigner/symbianplugin/images/button.png b/src/plugins/qmldesigner/symbianplugin/images/button.png
new file mode 100644
index 0000000000..8306aa97e7
--- /dev/null
+++ b/src/plugins/qmldesigner/symbianplugin/images/button.png
Binary files differ
diff --git a/src/plugins/qmldesigner/symbianplugin/images/button16.png b/src/plugins/qmldesigner/symbianplugin/images/button16.png
new file mode 100644
index 0000000000..c8c9684ab5
--- /dev/null
+++ b/src/plugins/qmldesigner/symbianplugin/images/button16.png
Binary files differ
diff --git a/src/plugins/qmldesigner/symbianplugin/images/checkbox.png b/src/plugins/qmldesigner/symbianplugin/images/checkbox.png
new file mode 100644
index 0000000000..df91fb6458
--- /dev/null
+++ b/src/plugins/qmldesigner/symbianplugin/images/checkbox.png
Binary files differ
diff --git a/src/plugins/qmldesigner/symbianplugin/images/checkbox16.png b/src/plugins/qmldesigner/symbianplugin/images/checkbox16.png
new file mode 100644
index 0000000000..e522c0113f
--- /dev/null
+++ b/src/plugins/qmldesigner/symbianplugin/images/checkbox16.png
Binary files differ
diff --git a/src/plugins/qmldesigner/symbianplugin/images/item-icon.png b/src/plugins/qmldesigner/symbianplugin/images/item-icon.png
new file mode 100644
index 0000000000..fc53d38ae7
--- /dev/null
+++ b/src/plugins/qmldesigner/symbianplugin/images/item-icon.png
Binary files differ
diff --git a/src/plugins/qmldesigner/symbianplugin/images/item-icon16.png b/src/plugins/qmldesigner/symbianplugin/images/item-icon16.png
new file mode 100644
index 0000000000..7d2d7a5050
--- /dev/null
+++ b/src/plugins/qmldesigner/symbianplugin/images/item-icon16.png
Binary files differ
diff --git a/src/plugins/qmldesigner/symbianplugin/images/label.png b/src/plugins/qmldesigner/symbianplugin/images/label.png
new file mode 100644
index 0000000000..e622f68687
--- /dev/null
+++ b/src/plugins/qmldesigner/symbianplugin/images/label.png
Binary files differ
diff --git a/src/plugins/qmldesigner/symbianplugin/images/label16.png b/src/plugins/qmldesigner/symbianplugin/images/label16.png
new file mode 100644
index 0000000000..0478d429f6
--- /dev/null
+++ b/src/plugins/qmldesigner/symbianplugin/images/label16.png
Binary files differ
diff --git a/src/plugins/qmldesigner/symbianplugin/images/lineedit.png b/src/plugins/qmldesigner/symbianplugin/images/lineedit.png
new file mode 100644
index 0000000000..f521cd513e
--- /dev/null
+++ b/src/plugins/qmldesigner/symbianplugin/images/lineedit.png
Binary files differ
diff --git a/src/plugins/qmldesigner/symbianplugin/images/lineedit16.png b/src/plugins/qmldesigner/symbianplugin/images/lineedit16.png
new file mode 100644
index 0000000000..549803910d
--- /dev/null
+++ b/src/plugins/qmldesigner/symbianplugin/images/lineedit16.png
Binary files differ
diff --git a/src/plugins/qmldesigner/symbianplugin/images/progressbar.png b/src/plugins/qmldesigner/symbianplugin/images/progressbar.png
new file mode 100644
index 0000000000..9d1f1df7ed
--- /dev/null
+++ b/src/plugins/qmldesigner/symbianplugin/images/progressbar.png
Binary files differ
diff --git a/src/plugins/qmldesigner/symbianplugin/images/progressbar16.png b/src/plugins/qmldesigner/symbianplugin/images/progressbar16.png
new file mode 100644
index 0000000000..297ca1c906
--- /dev/null
+++ b/src/plugins/qmldesigner/symbianplugin/images/progressbar16.png
Binary files differ
diff --git a/src/plugins/qmldesigner/symbianplugin/images/radiobutton.png b/src/plugins/qmldesigner/symbianplugin/images/radiobutton.png
new file mode 100644
index 0000000000..52cd6a514a
--- /dev/null
+++ b/src/plugins/qmldesigner/symbianplugin/images/radiobutton.png
Binary files differ
diff --git a/src/plugins/qmldesigner/symbianplugin/images/radiobutton16.png b/src/plugins/qmldesigner/symbianplugin/images/radiobutton16.png
new file mode 100644
index 0000000000..af09affb92
--- /dev/null
+++ b/src/plugins/qmldesigner/symbianplugin/images/radiobutton16.png
Binary files differ
diff --git a/src/plugins/qmldesigner/symbianplugin/images/slider.png b/src/plugins/qmldesigner/symbianplugin/images/slider.png
new file mode 100644
index 0000000000..687185bffd
--- /dev/null
+++ b/src/plugins/qmldesigner/symbianplugin/images/slider.png
Binary files differ
diff --git a/src/plugins/qmldesigner/symbianplugin/images/slider16.png b/src/plugins/qmldesigner/symbianplugin/images/slider16.png
new file mode 100644
index 0000000000..3a2fbe8d0f
--- /dev/null
+++ b/src/plugins/qmldesigner/symbianplugin/images/slider16.png
Binary files differ
diff --git a/src/plugins/qmldesigner/symbianplugin/plugindestdir.pri b/src/plugins/qmldesigner/symbianplugin/plugindestdir.pri
new file mode 100644
index 0000000000..24f0c19b72
--- /dev/null
+++ b/src/plugins/qmldesigner/symbianplugin/plugindestdir.pri
@@ -0,0 +1,5 @@
+macx {
+ DESTDIR = $$IDE_LIBRARY_PATH/QmlDesigner
+} else {
+ DESTDIR = $$IDE_BUILD_TREE/lib/qmldesigner
+}
diff --git a/src/plugins/qmldesigner/symbianplugin/symbian.metainfo b/src/plugins/qmldesigner/symbianplugin/symbian.metainfo
new file mode 100644
index 0000000000..dc2d8e403a
--- /dev/null
+++ b/src/plugins/qmldesigner/symbianplugin/symbian.metainfo
@@ -0,0 +1,49 @@
+<metainfo>
+ <node name="Label" icon=":/symbianplugin/images/label16.png">
+ <itemlibraryentry name="Label" category="Components Symbian" libraryIcon=":/symbianplugin/images/label.png" version="1.0" requiredImport="Qt.labs.Symbian">
+ <property name="width" type="int" value="100"/>
+ <property name="height" type="int" value="30"/>
+ <property name="text" type="QString" value="Label"/>
+ </itemlibraryentry>
+ </node>
+ <node name="Button" icon=":/symbianplugin/images/button16.png">
+ <itemlibraryentry name="Button" category="Components Symbian" libraryIcon=":/symbianplugin/images/button.png" version="1.0" requiredImport="Qt.labs.Symbian">
+ <property name="width" type="int" value="100"/>
+ <property name="height" type="int" value="30"/>
+ <property name="text" type="QString" value="Button"/>
+ </itemlibraryentry>
+ </node>
+ <node name="Slider" icon=":/symbianplugin/images/slider16.png">
+ </node>
+ <node name="CheckBox" icon=":/symbianplugin/images/checkbox16.png">
+ <itemlibraryentry name="CheckBox" category="Components Symbian" libraryIcon=":/symbianplugin/images/checkbox.png" version="1.0" requiredImport="Qt.labs.Symbian">
+ <property name="width" type="int" value="180"/>
+ <property name="height" type="int" value="30"/>
+ <property name="text" type="QString" value="CheckBox"/>
+ </itemlibraryentry>
+ </node>
+ <node name="RadioButton" icon=":/symbianplugin/images/radiobutton16.png">
+ <itemlibraryentry name="RadioButton" category="Components Symbian" libraryIcon=":/symbianplugin/images/radiobutton.png" version="1.0" requiredImport="Qt.labs.Symbian">
+ <property name="width" type="int" value="180"/>
+ <property name="height" type="int" value="30"/>
+ <property name="text" type="QString" value="RadioButton"/>
+ </itemlibraryentry>
+ </node>
+ <node name="Spinner" icon=":/symbianplugin/images/item-icon16.png">
+ </node>
+ <node name="Switch" icon=":/symbianplugin/images/item-icon16.png">
+ </node>
+ <node name="LineEdit" icon=":/symbianplugin/images/lineedit16.png">
+ <itemlibraryentry name="LineEdit" category="Components Symbian" libraryIcon=":/symbianplugin/images/lineedit.png" version="1.0" requiredImport="Qt.labs.Symbian">
+ <property name="width" type="int" value="100"/>
+ <property name="height" type="int" value="30"/>
+ <property name="text" type="QString" value="LineEdit"/>
+ </itemlibraryentry>
+ </node>
+ <node name="ProgressBar" icon=":/symbianplugin/images/progressbar16.png">
+ <itemlibraryentry name="ProgressBar" category="Components Symbian" libraryIcon=":/symbianplugin/images/progressbar.png" version="1.0" requiredImport="Qt.labs.Symbian">
+ <property name="width" type="int" value="100"/>
+ <property name="height" type="int" value="30"/>
+ </itemlibraryentry>
+ </node>
+</metainfo>
diff --git a/src/plugins/qmldesigner/symbianplugin/symbianplugin.cpp b/src/plugins/qmldesigner/symbianplugin/symbianplugin.cpp
new file mode 100644
index 0000000000..ef157bf62b
--- /dev/null
+++ b/src/plugins/qmldesigner/symbianplugin/symbianplugin.cpp
@@ -0,0 +1,54 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "symbianplugin.h"
+#include <widgetplugin_helper.h>
+#include <QtCore/QtPlugin>
+
+namespace QmlDesigner {
+
+
+SymbianPlugin::SymbianPlugin()
+{
+}
+
+QString SymbianPlugin::pluginName()
+{
+ return ("SymbianPlugin");
+}
+
+QString SymbianPlugin::metaInfo()
+{
+ return QString(":/symbianplugin/symbian.metainfo");
+}
+
+}
+
+Q_EXPORT_PLUGIN(QmlDesigner::SymbianPlugin)
+
diff --git a/src/plugins/qmldesigner/symbianplugin/symbianplugin.h b/src/plugins/qmldesigner/symbianplugin/symbianplugin.h
new file mode 100644
index 0000000000..2ce37d4c64
--- /dev/null
+++ b/src/plugins/qmldesigner/symbianplugin/symbianplugin.h
@@ -0,0 +1,62 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** No Commercial Usage
+**
+** This file 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.
+**
+**************************************************************************/
+
+#ifndef SymbianPLUGIN_H
+#define SymbianPLUGIN_H
+
+#include <iwidgetplugin.h>
+#include <QtDeclarative/qdeclarative.h>
+
+QT_BEGIN_NAMESPACE
+QT_END_NAMESPACE
+
+namespace QmlDesigner {
+
+class SymbianPlugin : public QObject, QmlDesigner::IWidgetPlugin
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(SymbianPlugin)
+ Q_INTERFACES(QmlDesigner::IWidgetPlugin)
+public:
+ SymbianPlugin();
+ ~SymbianPlugin() {}
+
+ QString metaInfo();
+ QString pluginName();
+
+};
+
+} // namespace QmlDesigner
+
+
+#endif // SymbianPLUGIN_H
diff --git a/src/plugins/qmldesigner/symbianplugin/symbianplugin.pri b/src/plugins/qmldesigner/symbianplugin/symbianplugin.pri
new file mode 100644
index 0000000000..28d6323c68
--- /dev/null
+++ b/src/plugins/qmldesigner/symbianplugin/symbianplugin.pri
@@ -0,0 +1,17 @@
+TARGET = symbianplugin
+TEMPLATE = lib
+CONFIG += plugin
+
+QT += script \
+ declarative
+
+include (../designercore/iwidgetplugin.pri)
+
+DEFINES += SYMBIAN_LIBRARY
+SOURCES += $$PWD/symbianplugin.cpp
+
+HEADERS += $$PWD/symbianplugin.h $$PWD/../designercore/include/iwidgetplugin.h
+
+RESOURCES += $$PWD/symbianplugin.qrc
+
+OTHER_FILES += $$PWD/symbian.metainfo
diff --git a/src/plugins/qmldesigner/symbianplugin/symbianplugin.pro b/src/plugins/qmldesigner/symbianplugin/symbianplugin.pro
new file mode 100644
index 0000000000..6ff795d27a
--- /dev/null
+++ b/src/plugins/qmldesigner/symbianplugin/symbianplugin.pro
@@ -0,0 +1,4 @@
+include(../../../../qtcreator.pri)
+include(../../../private_headers.pri)
+include(symbianplugin.pri)
+include(plugindestdir.pri)
diff --git a/src/plugins/qmldesigner/symbianplugin/symbianplugin.qrc b/src/plugins/qmldesigner/symbianplugin/symbianplugin.qrc
new file mode 100644
index 0000000000..f476fa1d77
--- /dev/null
+++ b/src/plugins/qmldesigner/symbianplugin/symbianplugin.qrc
@@ -0,0 +1,21 @@
+<RCC>
+ <qresource prefix="/symbianplugin">
+ <file>symbian.metainfo</file>
+ <file>images/item-icon16.png</file>
+ <file>images/item-icon.png</file>
+ <file>images/button.png</file>
+ <file>images/button16.png</file>
+ <file>images/checkbox16.png</file>
+ <file>images/checkbox.png</file>
+ <file>images/label.png</file>
+ <file>images/label16.png</file>
+ <file>images/lineedit.png</file>
+ <file>images/lineedit16.png</file>
+ <file>images/progressbar.png</file>
+ <file>images/progressbar16.png</file>
+ <file>images/radiobutton.png</file>
+ <file>images/radiobutton16.png</file>
+ <file>images/slider.png</file>
+ <file>images/slider16.png</file>
+ </qresource>
+</RCC>
diff --git a/src/plugins/qmljseditor/QmlJSEditor.pluginspec b/src/plugins/qmljseditor/QmlJSEditor.pluginspec
deleted file mode 100644
index 25c21db845..0000000000
--- a/src/plugins/qmljseditor/QmlJSEditor.pluginspec
+++ /dev/null
@@ -1,21 +0,0 @@
-<plugin name="QmlJSEditor" version="2.0.95" compatVersion="2.0.95">
- <vendor>Nokia Corporation</vendor>
- <copyright>(C) 2010 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>
- <category>Qt Quick</category>
- <description>Editor for QML and JavaScript.</description>
- <url>http://qt.nokia.com</url>
- <dependencyList>
- <dependency name="Core" version="2.0.95"/>
- <dependency name="TextEditor" version="2.0.95"/>
- <dependency name="ProjectExplorer" version="2.0.95"/>
- </dependencyList>
-</plugin>
diff --git a/src/plugins/qmljseditor/QmlJSEditor.pluginspec.in b/src/plugins/qmljseditor/QmlJSEditor.pluginspec.in
new file mode 100644
index 0000000000..b70f1f8e07
--- /dev/null
+++ b/src/plugins/qmljseditor/QmlJSEditor.pluginspec.in
@@ -0,0 +1,22 @@
+<plugin name=\"QmlJSEditor\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2010 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>
+ <category>Qt Quick</category>
+ <description>Editor for QML and JavaScript.</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"TextEditor\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"ProjectExplorer\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"QmlJSTools\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/qmljseditor/jsfilewizard.cpp b/src/plugins/qmljseditor/jsfilewizard.cpp
new file mode 100644
index 0000000000..db161119a4
--- /dev/null
+++ b/src/plugins/qmljseditor/jsfilewizard.cpp
@@ -0,0 +1,140 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "qmljseditorconstants.h"
+#include "jsfilewizard.h"
+
+#include <utils/filewizarddialog.h>
+#include <utils/qtcassert.h>
+#include <utils/filewizarddialog.h>
+
+#include <QtCore/QFileInfo>
+#include <QtCore/QTextStream>
+#include <QtGui/QWizard>
+#include <QtGui/QPushButton>
+#include <QtGui/QBoxLayout>
+#include <QtGui/QCheckBox>
+
+namespace {
+class JsFileOptionsPage : public QWizardPage
+{
+ Q_OBJECT
+public:
+ JsFileOptionsPage()
+ {
+ setTitle(tr("Options"));
+
+ QVBoxLayout *layout = new QVBoxLayout;
+ m_statelessLibrary = new QCheckBox(tr("Stateless library"));
+ m_statelessLibrary->setToolTip(
+ tr("Usually each QML component instance has a unique copy of\n"
+ "imported JavaScript libraries. Indicating that a library is\n"
+ "stateless means that a single instance will be shared among\n"
+ "all components. Stateless libraries will not be able to access\n"
+ "QML component instance objects and properties directly."));
+ layout->addWidget(m_statelessLibrary);
+ setLayout(layout);
+ }
+
+ bool statelessLibrary() const
+ {
+ return m_statelessLibrary->isChecked();
+ }
+
+private:
+ QCheckBox *m_statelessLibrary;
+};
+
+class JsFileWizardDialog : public Utils::FileWizardDialog
+{
+ Q_OBJECT
+public:
+ JsFileWizardDialog(QWidget *parent = 0)
+ : Utils::FileWizardDialog(parent)
+ , m_optionsPage(new JsFileOptionsPage)
+ {
+ addPage(m_optionsPage);
+ }
+
+ JsFileOptionsPage *m_optionsPage;
+};
+} // anonymous namespace
+
+using namespace QmlJSEditor;
+
+JsFileWizard::JsFileWizard(const BaseFileWizardParameters &parameters,
+ QObject *parent):
+ Core::BaseFileWizard(parameters, parent)
+{
+}
+
+Core::GeneratedFiles JsFileWizard::generateFiles(const QWizard *w,
+ QString * /*errorMessage*/) const
+{
+ const JsFileWizardDialog *wizardDialog = qobject_cast<const JsFileWizardDialog *>(w);
+ const QString path = wizardDialog->path();
+ const QString name = wizardDialog->fileName();
+
+ const QString mimeType = QLatin1String(Constants::JS_MIMETYPE);
+ const QString fileName = Core::BaseFileWizard::buildFileName(path, name, preferredSuffix(mimeType));
+
+ Core::GeneratedFile file(fileName);
+ file.setContents(fileContents(fileName, wizardDialog->m_optionsPage->statelessLibrary()));
+ file.setAttributes(Core::GeneratedFile::OpenEditorAttribute);
+ return Core::GeneratedFiles() << file;
+}
+
+QString JsFileWizard::fileContents(const QString &, bool statelessLibrary) const
+{
+ QString contents;
+ QTextStream str(&contents);
+
+ if (statelessLibrary) {
+ str << QLatin1String(".pragma library\n\n");
+ }
+ str << QLatin1String("function func() {\n")
+ << QLatin1String("\n")
+ << QLatin1String("}\n");
+
+ return contents;
+}
+
+QWizard *JsFileWizard::createWizardDialog(QWidget *parent, const QString &defaultPath,
+ const WizardPageList &extensionPages) const
+{
+ JsFileWizardDialog *wizardDialog = new JsFileWizardDialog(parent);
+ wizardDialog->setWindowTitle(tr("New %1").arg(displayName()));
+ setupWizard(wizardDialog);
+ wizardDialog->setPath(defaultPath);
+ foreach (QWizardPage *p, extensionPages)
+ BaseFileWizard::applyExtensionPageShortTitle(wizardDialog, wizardDialog->addPage(p));
+ return wizardDialog;
+}
+
+#include "jsfilewizard.moc"
diff --git a/src/plugins/qmljseditor/jsfilewizard.h b/src/plugins/qmljseditor/jsfilewizard.h
new file mode 100644
index 0000000000..f6a0f39f8a
--- /dev/null
+++ b/src/plugins/qmljseditor/jsfilewizard.h
@@ -0,0 +1,60 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 JSFILEWIZARD_H
+#define JSFILEWIZARD_H
+
+#include <coreplugin/basefilewizard.h>
+
+namespace QmlJSEditor {
+
+class JsFileWizard: public Core::BaseFileWizard
+{
+ Q_OBJECT
+
+public:
+ typedef Core::BaseFileWizardParameters BaseFileWizardParameters;
+
+ explicit JsFileWizard(const BaseFileWizardParameters &parameters,
+ QObject *parent = 0);
+
+protected:
+ QString fileContents(const QString &baseName, bool statelessLibrary) const;
+
+ virtual QWizard *createWizardDialog(QWidget *parent,
+ const QString &defaultPath,
+ const WizardPageList &extensionPages) const;
+
+ virtual Core::GeneratedFiles generateFiles(const QWizard *w,
+ QString *errorMessage) const;
+};
+
+} // namespace QmlJSEditor
+
+#endif // JSFILEWIZARD_H
diff --git a/src/plugins/qmljseditor/qmljsautocompleter.cpp b/src/plugins/qmljseditor/qmljsautocompleter.cpp
new file mode 100644
index 0000000000..feca7631de
--- /dev/null
+++ b/src/plugins/qmljseditor/qmljsautocompleter.cpp
@@ -0,0 +1,291 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "qmljsautocompleter.h"
+
+#include <qmljs/qmljsscanner.h>
+
+#include <QtCore/QChar>
+#include <QtCore/QLatin1Char>
+#include <QtGui/QTextDocument>
+#include <QtGui/QTextCursor>
+#include <QtGui/QTextBlock>
+
+using namespace QmlJSEditor;
+using namespace Internal;
+using namespace QmlJS;
+
+static int blockStartState(const QTextBlock &block)
+{
+ int state = block.previous().userState();
+
+ if (state == -1)
+ return 0;
+ else
+ return state & 0xff;
+}
+
+static Token tokenUnderCursor(const QTextCursor &cursor)
+{
+ const QString blockText = cursor.block().text();
+ const int blockState = blockStartState(cursor.block());
+
+ Scanner tokenize;
+ const QList<Token> tokens = tokenize(blockText, blockState);
+ const int pos = cursor.positionInBlock();
+
+ int tokenIndex = 0;
+ for (; tokenIndex < tokens.size(); ++tokenIndex) {
+ const Token &token = tokens.at(tokenIndex);
+
+ if (token.is(Token::Comment) || token.is(Token::String)) {
+ if (pos > token.begin() && pos <= token.end())
+ break;
+ } else {
+ if (pos >= token.begin() && pos < token.end())
+ break;
+ }
+ }
+
+ if (tokenIndex != tokens.size())
+ return tokens.at(tokenIndex);
+
+ return Token();
+}
+
+static bool shouldInsertMatchingText(QChar lookAhead)
+{
+ switch (lookAhead.unicode()) {
+ case '{': case '}':
+ case ']': case ')':
+ case ';': case ',':
+ case '"': case '\'':
+ return true;
+
+ default:
+ if (lookAhead.isSpace())
+ return true;
+
+ return false;
+ } // switch
+}
+
+static bool shouldInsertMatchingText(const QTextCursor &tc)
+{
+ QTextDocument *doc = tc.document();
+ return shouldInsertMatchingText(doc->characterAt(tc.selectionEnd()));
+}
+
+static bool shouldInsertNewline(const QTextCursor &tc)
+{
+ QTextDocument *doc = tc.document();
+ int pos = tc.selectionEnd();
+
+ // count the number of empty lines.
+ int newlines = 0;
+ for (int e = doc->characterCount(); pos != e; ++pos) {
+ const QChar ch = doc->characterAt(pos);
+
+ if (! ch.isSpace())
+ break;
+ else if (ch == QChar::ParagraphSeparator)
+ ++newlines;
+ }
+
+ if (newlines <= 1 && doc->characterAt(pos) != QLatin1Char('}'))
+ return true;
+
+ return false;
+}
+
+static bool isCompleteStringLiteral(const QStringRef &text)
+{
+ if (text.length() < 2)
+ return false;
+
+ const QChar quote = text.at(0);
+
+ if (text.at(text.length() - 1) == quote)
+ return text.at(text.length() - 2) != QLatin1Char('\\'); // ### not exactly.
+
+ return false;
+}
+
+AutoCompleter::AutoCompleter()
+{}
+
+AutoCompleter::~AutoCompleter()
+{}
+
+bool AutoCompleter::contextAllowsAutoParentheses(const QTextCursor &cursor,
+ const QString &textToInsert) const
+{
+ QChar ch;
+
+ if (! textToInsert.isEmpty())
+ ch = textToInsert.at(0);
+
+ switch (ch.unicode()) {
+ case '\'':
+ case '"':
+
+ case '(':
+ case '[':
+ case '{':
+
+ case ')':
+ case ']':
+ case '}':
+
+ case ';':
+ break;
+
+ default:
+ if (ch.isNull())
+ break;
+
+ return false;
+ } // end of switch
+
+ const Token token = tokenUnderCursor(cursor);
+ switch (token.kind) {
+ case Token::Comment:
+ return false;
+
+ case Token::String: {
+ const QString blockText = cursor.block().text();
+ const QStringRef tokenText = blockText.midRef(token.offset, token.length);
+ QChar quote = tokenText.at(0);
+ // if a string literal doesn't start with a quote, it must be multiline
+ if (quote != QLatin1Char('"') && quote != QLatin1Char('\'')) {
+ const int startState = blockStartState(cursor.block());
+ if (startState == Scanner::MultiLineStringDQuote)
+ quote = QLatin1Char('"');
+ else if (startState == Scanner::MultiLineStringSQuote)
+ quote = QLatin1Char('\'');
+ }
+
+ // never insert ' into string literals, it adds spurious ' when writing contractions
+ if (ch == QLatin1Char('\''))
+ return false;
+
+ if (ch != quote || isCompleteStringLiteral(tokenText))
+ break;
+
+ return false;
+ }
+
+ default:
+ break;
+ } // end of switch
+
+ return true;
+}
+
+bool AutoCompleter::contextAllowsElectricCharacters(const QTextCursor &cursor) const
+{
+ Token token = tokenUnderCursor(cursor);
+ switch (token.kind) {
+ case Token::Comment:
+ case Token::String:
+ return false;
+ default:
+ return true;
+ }
+}
+
+bool AutoCompleter::isInComment(const QTextCursor &cursor) const
+{
+ return tokenUnderCursor(cursor).is(Token::Comment);
+}
+
+QString AutoCompleter::insertMatchingBrace(const QTextCursor &cursor,
+ const QString &text,
+ QChar,
+ int *skippedChars) const
+{
+ if (text.length() != 1)
+ return QString();
+
+ if (! shouldInsertMatchingText(cursor))
+ return QString();
+
+ const QChar la = cursor.document()->characterAt(cursor.position());
+
+ const QChar ch = text.at(0);
+ switch (ch.unicode()) {
+ case '\'':
+ if (la != ch)
+ return QString(ch);
+ ++*skippedChars;
+ break;
+
+ case '"':
+ if (la != ch)
+ return QString(ch);
+ ++*skippedChars;
+ break;
+
+ case '(':
+ return QString(QLatin1Char(')'));
+
+ case '[':
+ return QString(QLatin1Char(']'));
+
+ case '{':
+ return QString(); // nothing to do.
+
+ case ')':
+ case ']':
+ case '}':
+ case ';':
+ if (la == ch)
+ ++*skippedChars;
+ break;
+
+ default:
+ break;
+ } // end of switch
+
+ return QString();
+}
+
+QString AutoCompleter::insertParagraphSeparator(const QTextCursor &cursor) const
+{
+ if (shouldInsertNewline(cursor)) {
+ QTextCursor selCursor = cursor;
+ selCursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
+ if (! selCursor.selectedText().trimmed().isEmpty())
+ return QString();
+
+ return QLatin1String("}\n");
+ }
+
+ return QLatin1String("}");
+}
diff --git a/src/plugins/qmljseditor/qmljsautocompleter.h b/src/plugins/qmljseditor/qmljsautocompleter.h
new file mode 100644
index 0000000000..6a26e524a8
--- /dev/null
+++ b/src/plugins/qmljseditor/qmljsautocompleter.h
@@ -0,0 +1,62 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** No Commercial Usage
+**
+** This file 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.
+**
+**************************************************************************/
+
+#ifndef QMLJSAUTOCOMPLETER_H
+#define QMLJSAUTOCOMPLETER_H
+
+#include <texteditor/autocompleter.h>
+
+namespace QmlJSEditor {
+namespace Internal {
+
+class AutoCompleter : public TextEditor::AutoCompleter
+{
+public:
+ AutoCompleter();
+ virtual ~AutoCompleter();
+
+ virtual bool contextAllowsAutoParentheses(const QTextCursor &cursor,
+ const QString &textToInsert = QString()) const;
+ virtual bool contextAllowsElectricCharacters(const QTextCursor &cursor) const;
+ virtual bool isInComment(const QTextCursor &cursor) const;
+ virtual QString insertMatchingBrace(const QTextCursor &tc,
+ const QString &text,
+ QChar la,
+ int *skippedChars) const;
+ virtual QString insertParagraphSeparator(const QTextCursor &tc) const;
+};
+
+} // Internal
+} // QmlJSEditor
+
+#endif // QMLJSAUTOCOMPLETER_H
diff --git a/src/plugins/qmljseditor/qmljscodecompletion.cpp b/src/plugins/qmljseditor/qmljscodecompletion.cpp
index fd628ac37e..7f46be938a 100644
--- a/src/plugins/qmljseditor/qmljscodecompletion.cpp
+++ b/src/plugins/qmljseditor/qmljscodecompletion.cpp
@@ -34,6 +34,7 @@
#include "qmljscodecompletion.h"
#include "qmlexpressionundercursor.h"
#include "qmljseditor.h"
+#include "qmljseditorconstants.h"
#include <qmljs/qmljsmodelmanagerinterface.h>
#include <qmljs/parser/qmljsast_p.h>
@@ -50,11 +51,13 @@
#include <coreplugin/editormanager/editormanager.h>
#include <utils/faketooltip.h>
+#include <utils/qtcassert.h>
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
#include <QtCore/QDir>
#include <QtCore/QDebug>
+#include <QtCore/QDirIterator>
#include <QtGui/QApplication>
#include <QtGui/QDesktopWidget>
@@ -489,7 +492,7 @@ CodeCompletion::CodeCompletion(ModelManagerInterface *modelManager, QObject *par
m_editor(0),
m_startPosition(0),
m_restartCompletion(false),
- m_snippetsParser(Core::ICore::instance()->resourcePath() + QLatin1String("/snippets/qml.xml"))
+ m_snippetProvider(Constants::QML_SNIPPETS_GROUP_ID, iconForColor(Qt::red), SnippetOrder)
{
Q_ASSERT(modelManager);
}
@@ -524,6 +527,7 @@ bool CodeCompletion::triggersCompletion(TextEditor::ITextEditable *editor)
QTextCursor tc = ed->textCursor();
QTextBlock block = tc.block();
const int column = tc.positionInBlock();
+ const QChar ch = block.text().at(column - 1);
const int blockState = qMax(0, block.previous().userState()) & 0xff;
const QString blockText = block.text();
@@ -531,12 +535,15 @@ bool CodeCompletion::triggersCompletion(TextEditor::ITextEditable *editor)
const QList<Token> tokens = scanner(blockText, blockState);
foreach (const Token &tk, tokens) {
if (column >= tk.begin() && column <= tk.end()) {
+ if (ch == QLatin1Char('/') && tk.is(Token::String))
+ return true; // path completion inside string literals
if (tk.is(Token::Comment) || tk.is(Token::String))
return false;
- else
- break;
+ break;
}
}
+ if (ch == QLatin1Char('/'))
+ return false;
}
return true;
}
@@ -549,7 +556,7 @@ bool CodeCompletion::maybeTriggersCompletion(TextEditor::ITextEditable *editor)
const int cursorPosition = editor->position();
const QChar ch = editor->characterAt(cursorPosition - 1);
- if (ch == QLatin1Char('(') || ch == QLatin1Char('.'))
+ if (ch == QLatin1Char('(') || ch == QLatin1Char('.') || ch == QLatin1Char('/'))
return true;
if (completionSettings().m_completionTrigger != TextEditor::AutomaticCompletion)
return false;
@@ -613,6 +620,46 @@ static bool isLiteral(AST::Node *ast)
return false;
}
+bool CodeCompletion::completeUrl(const QString &relativeBasePath, const QString &urlString)
+{
+ const QUrl url(urlString);
+ QString fileName = url.toLocalFile();
+ if (fileName.isEmpty())
+ return false;
+
+ return completeFileName(relativeBasePath, fileName);
+}
+
+bool CodeCompletion::completeFileName(const QString &relativeBasePath, const QString &fileName,
+ const QStringList &patterns)
+{
+ const QFileInfo fileInfo(fileName);
+ QString directoryPrefix;
+ if (fileInfo.isRelative()) {
+ directoryPrefix = relativeBasePath;
+ directoryPrefix += QDir::separator();
+ directoryPrefix += fileInfo.path();
+ } else {
+ directoryPrefix = fileInfo.path();
+ }
+ if (!QFileInfo(directoryPrefix).exists())
+ return false;
+
+ QDirIterator dirIterator(directoryPrefix, patterns, QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot);
+ while (dirIterator.hasNext()) {
+ dirIterator.next();
+ const QString fileName = dirIterator.fileName();
+
+ TextEditor::CompletionItem item(this);
+ item.text += fileName;
+ // ### Icon for file completions
+ item.icon = iconForColor(Qt::darkBlue);
+ m_completions.append(item);
+ }
+
+ return !m_completions.isEmpty();
+}
+
void CodeCompletion::addCompletions(const QHash<QString, const Interpreter::Value *> &newCompletions,
const QIcon &icon, int order)
{
@@ -642,7 +689,7 @@ void CodeCompletion::addCompletions(const QStringList &newCompletions,
void CodeCompletion::addCompletionsPropertyLhs(
const QHash<QString, const Interpreter::Value *> &newCompletions,
- const QIcon &icon, int order)
+ const QIcon &icon, int order, bool afterOn)
{
QHashIterator<QString, const Interpreter::Value *> it(newCompletions);
while (it.hasNext()) {
@@ -650,15 +697,19 @@ void CodeCompletion::addCompletionsPropertyLhs(
TextEditor::CompletionItem item(this);
item.text = it.key();
+
+ QLatin1String postfix(": ");
+ if (afterOn)
+ postfix = QLatin1String(" {");
if (const Interpreter::QmlObjectValue *qmlValue = dynamic_cast<const Interpreter::QmlObjectValue *>(it.value())) {
// to distinguish "anchors." from "gradient:" we check if the right hand side
// type is instantiatable or is the prototype of an instantiatable object
if (qmlValue->hasChildInPackage())
- item.text.append(QLatin1String(": "));
+ item.text.append(postfix);
else
item.text.append(QLatin1Char('.'));
} else {
- item.text.append(QLatin1String(": "));
+ item.text.append(postfix);
}
item.icon = icon;
item.order = order;
@@ -666,6 +717,27 @@ void CodeCompletion::addCompletionsPropertyLhs(
}
}
+static const Interpreter::Value *getPropertyValue(
+ const Interpreter::ObjectValue *object,
+ const QStringList &propertyNames,
+ const Interpreter::Context *context)
+{
+ if (propertyNames.isEmpty() || !object)
+ return 0;
+
+ const Interpreter::Value *value = object;
+ foreach (const QString &name, propertyNames) {
+ if (const Interpreter::ObjectValue *objectValue = value->asObjectValue()) {
+ value = objectValue->property(name, context);
+ if (!value)
+ return 0;
+ } else {
+ return 0;
+ }
+ }
+ return value;
+}
+
int CodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
{
m_restartCompletion = false;
@@ -717,8 +789,41 @@ int CodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
if (contextFinder.isInQmlContext())
qmlScopeType = context->lookupType(document.data(), contextFinder.qmlObjectTypeName());
- if (completionOperator.isSpace() || completionOperator.isNull() || isDelimiter(completionOperator) ||
- (completionOperator == QLatin1Char('(') && m_startPosition != editor->position())) {
+ if (contextFinder.isInStringLiteral()) {
+ // get the text of the literal up to the cursor position
+ QTextCursor tc = edit->textCursor();
+ QmlExpressionUnderCursor expressionUnderCursor;
+ expressionUnderCursor(tc);
+ QString literalText = expressionUnderCursor.text();
+ QTC_ASSERT(!literalText.isEmpty() && (
+ literalText.at(0) == QLatin1Char('"')
+ || literalText.at(0) == QLatin1Char('\'')), return -1);
+ literalText = literalText.mid(1);
+
+ if (contextFinder.isInImport()) {
+ QStringList patterns;
+ patterns << QLatin1String("*.qml") << QLatin1String("*.js");
+ if (completeFileName(document->path(), literalText, patterns))
+ return m_startPosition;
+ return -1;
+ }
+
+ const Interpreter::Value *value = getPropertyValue(qmlScopeType, contextFinder.bindingPropertyName(), context);
+ if (!value) {
+ // do nothing
+ } else if (value->asUrlValue()) {
+ if (completeUrl(document->path(), literalText))
+ return m_startPosition;
+ }
+
+ // ### enum completion?
+
+ // completion gets triggered for / in string literals, if we don't
+ // return here, this will mean the snippet completion pops up for
+ // each / in a string literal that is not triggering file completion
+ return -1;
+ } else if (completionOperator.isSpace() || completionOperator.isNull() || isDelimiter(completionOperator) ||
+ (completionOperator == QLatin1Char('(') && m_startPosition != editor->position())) {
bool doGlobalCompletion = true;
bool doQmlKeywordCompletion = true;
@@ -739,7 +844,7 @@ int CodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
idPropertyCompletion.order = PropertyOrder;
m_completions.append(idPropertyCompletion);
- addCompletionsPropertyLhs(enumerateProperties(qmlScopeType), symbolIcon, PropertyOrder);
+ addCompletionsPropertyLhs(enumerateProperties(qmlScopeType), symbolIcon, PropertyOrder, contextFinder.isAfterOnInLhsOfBinding());
if (const Interpreter::ObjectValue *qmlTypes = context->scopeChain().qmlTypes)
addCompletions(enumerateProperties(qmlTypes), symbolIcon, TypeOrder);
@@ -752,28 +857,16 @@ int CodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
if (contextFinder.isInRhsOfBinding() && qmlScopeType) {
doQmlKeywordCompletion = false;
- if (!contextFinder.bindingPropertyName().isEmpty()) {
- const Interpreter::Value *value = qmlScopeType;
- foreach (const QString &name, contextFinder.bindingPropertyName()) {
- if (const Interpreter::ObjectValue *objectValue = value->asObjectValue()) {
- value = objectValue->property(name, context);
- if (!value)
- break;
- } else {
- value = 0;
- break;
- }
- }
-
- if (const Interpreter::QmlEnumValue *enumValue = dynamic_cast<const Interpreter::QmlEnumValue *>(value)) {
- foreach (const QString &key, enumValue->keys()) {
- TextEditor::CompletionItem item(this);
- item.text = key;
- item.data = QString("\"%1\"").arg(key);
- item.icon = symbolIcon;
- item.order = EnumValueOrder;
- m_completions.append(item);
- }
+ // complete enum values for enum properties
+ const Interpreter::Value *value = getPropertyValue(qmlScopeType, contextFinder.bindingPropertyName(), context);
+ if (const Interpreter::QmlEnumValue *enumValue = dynamic_cast<const Interpreter::QmlEnumValue *>(value)) {
+ foreach (const QString &key, enumValue->keys()) {
+ TextEditor::CompletionItem item(this);
+ item.text = key;
+ item.data = QString("\"%1\"").arg(key);
+ item.icon = symbolIcon;
+ item.order = EnumValueOrder;
+ m_completions.append(item);
}
}
}
@@ -829,7 +922,7 @@ int CodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
if (value && completionOperator == QLatin1Char('.')) { // member completion
EnumerateProperties enumerateProperties(context);
if (contextFinder.isInLhsOfBinding() && qmlScopeType && expressionUnderCursor.text().at(0).isLower())
- addCompletionsPropertyLhs(enumerateProperties(value), symbolIcon, PropertyOrder);
+ addCompletionsPropertyLhs(enumerateProperties(value), symbolIcon, PropertyOrder, contextFinder.isAfterOnInLhsOfBinding());
else
addCompletions(enumerateProperties(value), symbolIcon, SymbolOrder);
} else if (value && completionOperator == QLatin1Char('(') && m_startPosition == editor->position()) {
@@ -864,7 +957,7 @@ int CodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
}
if (isQmlFile && (completionOperator.isNull() || completionOperator.isSpace() || isDelimiter(completionOperator))) {
- m_completions.append(m_snippetsParser.execute(this, iconForColor(Qt::red), SnippetOrder));
+ m_completions.append(m_snippetProvider.getSnippets(this));
}
if (! m_completions.isEmpty())
diff --git a/src/plugins/qmljseditor/qmljscodecompletion.h b/src/plugins/qmljseditor/qmljscodecompletion.h
index 6538ee8ee3..98821f579f 100644
--- a/src/plugins/qmljseditor/qmljscodecompletion.h
+++ b/src/plugins/qmljseditor/qmljscodecompletion.h
@@ -36,7 +36,7 @@
#include <qmljs/qmljsdocument.h>
#include <texteditor/icompletioncollector.h>
-#include <texteditor/snippetsparser.h>
+#include <texteditor/snippets/snippetcollector.h>
#include <QtCore/QDateTime>
#include <QtCore/QPointer>
@@ -85,19 +85,23 @@ private:
bool maybeTriggersCompletion(TextEditor::ITextEditable *editor);
bool isDelimiter(QChar ch) const;
+ bool completeUrl(const QString &relativeBasePath, const QString &urlString);
+ bool completeFileName(const QString &relativeBasePath, const QString &fileName,
+ const QStringList &patterns = QStringList());
+
void addCompletions(const QHash<QString, const QmlJS::Interpreter::Value *> &newCompletions,
const QIcon &icon, int relevance);
void addCompletions(const QStringList &newCompletions,
const QIcon &icon, int relevance);
void addCompletionsPropertyLhs(
const QHash<QString, const QmlJS::Interpreter::Value *> &newCompletions,
- const QIcon &icon, int relevance);
+ const QIcon &icon, int relevance, bool afterOn);
QmlJS::ModelManagerInterface *m_modelManager;
TextEditor::ITextEditable *m_editor;
int m_startPosition;
bool m_restartCompletion;
- TextEditor::SnippetsParser m_snippetsParser;
+ TextEditor::SnippetCollector m_snippetProvider;
QList<TextEditor::CompletionItem> m_completions;
QPointer<FunctionArgumentWidget> m_functionArgumentWidget;
};
diff --git a/src/plugins/qmljseditor/qmljscomponentfromobjectdef.cpp b/src/plugins/qmljseditor/qmljscomponentfromobjectdef.cpp
index 8aa7801799..f5a4a0023e 100644
--- a/src/plugins/qmljseditor/qmljscomponentfromobjectdef.cpp
+++ b/src/plugins/qmljseditor/qmljscomponentfromobjectdef.cpp
@@ -33,12 +33,12 @@
#include "qmljscomponentfromobjectdef.h"
#include "qmljscomponentnamedialog.h"
-#include "qmljsrefactoringchanges.h"
#include <coreplugin/ifile.h>
#include <qmljs/parser/qmljsast_p.h>
#include <qmljs/qmljsdocument.h>
+#include <qmljstools/qmljsrefactoringchanges.h>
#include <QtCore/QCoreApplication>
#include <QtCore/QDir>
@@ -47,6 +47,7 @@
using namespace QmlJS::AST;
using namespace QmlJSEditor;
using namespace QmlJSEditor::Internal;
+using namespace QmlJSTools;
namespace {
@@ -90,7 +91,7 @@ static QString getIdProperty(UiObjectDefinition *def)
class Operation: public QmlJSQuickFixOperation
{
UiObjectDefinition *m_objDef;
- QString m_componentName;
+ QString m_idName, m_componentName;
public:
Operation(const QmlJSQuickFixState &state, UiObjectDefinition *objDef)
@@ -99,12 +100,13 @@ public:
{
Q_ASSERT(m_objDef != 0);
- m_componentName = getIdProperty(m_objDef);
+ m_idName = getIdProperty(m_objDef);
- if (m_componentName.isEmpty()) {
+ if (m_idName.isEmpty()) {
setDescription(QCoreApplication::translate("QmlJSEditor::ComponentFromObjectDef",
"Move Component into separate file"));
} else {
+ m_componentName = m_idName;
m_componentName[0] = m_componentName.at(0).toUpper();
setDescription(QCoreApplication::translate("QmlJSEditor::ComponentFromObjectDef",
"Move Component into '%1.qml'").arg(m_componentName));
@@ -142,8 +144,13 @@ public:
if (!refactoring->createFile(newFileName, txt))
return;
+ QString replacement = componentName + QLatin1String(" {\n");
+ if (!m_idName.isEmpty())
+ replacement += QLatin1String("id: ") + m_idName
+ + QLatin1Char('\n');
+
Utils::ChangeSet changes;
- changes.replace(start, end, componentName + QLatin1String(" {\n"));
+ changes.replace(start, end, replacement);
currentFile->change(changes);
currentFile->indent(Range(start, end + 1));
}
diff --git a/src/plugins/qmljseditor/qmljseditor.cpp b/src/plugins/qmljseditor/qmljseditor.cpp
index 50912dc1c2..4ed8f993da 100644
--- a/src/plugins/qmljseditor/qmljseditor.cpp
+++ b/src/plugins/qmljseditor/qmljseditor.cpp
@@ -32,43 +32,47 @@
**************************************************************************/
#include "qmljseditor.h"
+#include "qmljseditoreditable.h"
#include "qmljseditorconstants.h"
#include "qmljshighlighter.h"
#include "qmljseditorplugin.h"
-#include "qmljsmodelmanager.h"
-#include "qmljseditorcodeformatter.h"
#include "qmljsquickfix.h"
#include "qmloutlinemodel.h"
#include "qmljsfindreferences.h"
+#include "qmljssemantichighlighter.h"
+#include "qmljsindenter.h"
+#include "qmljsautocompleter.h"
#include <qmljs/qmljsbind.h>
-#include <qmljs/qmljscheck.h>
+#include <qmljs/qmljsevaluate.h>
#include <qmljs/qmljsdocument.h>
#include <qmljs/qmljsicontextpane.h>
#include <qmljs/qmljslookupcontext.h>
-#include <qmljs/qmljslink.h>
+#include <qmljs/qmljsmodelmanagerinterface.h>
#include <qmljs/parser/qmljsastvisitor_p.h>
#include <qmljs/parser/qmljsast_p.h>
#include <qmljs/parser/qmljsengine_p.h>
+#include <qmljstools/qmljsqtstylecodeformatter.h>
+
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
+#include <coreplugin/uniqueidmanager.h>
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/icore.h>
-#include <coreplugin/coreconstants.h>
-#include <coreplugin/modemanager.h>
-#include <coreplugin/designmode.h>
#include <coreplugin/mimedatabase.h>
#include <extensionsystem/pluginmanager.h>
#include <texteditor/basetextdocument.h>
#include <texteditor/fontsettings.h>
+#include <texteditor/tabsettings.h>
#include <texteditor/texteditorconstants.h>
#include <texteditor/texteditorsettings.h>
#include <texteditor/syntaxhighlighter.h>
#include <texteditor/refactoroverlay.h>
#include <texteditor/tooltip/tooltip.h>
#include <qmldesigner/qmldesignerconstants.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <utils/changeset.h>
#include <utils/uncommentselection.h>
@@ -87,46 +91,14 @@
enum {
UPDATE_DOCUMENT_DEFAULT_INTERVAL = 100,
UPDATE_USES_DEFAULT_INTERVAL = 150,
- UPDATE_OUTLINE_INTERVAL = 500, // msecs after new semantic info has been arrived / cursor has moved
+ UPDATE_OUTLINE_INTERVAL = 500 // msecs after new semantic info has been arrived / cursor has moved
};
using namespace QmlJS;
using namespace QmlJS::AST;
+using namespace QmlJSEditor;
using namespace QmlJSEditor::Internal;
-static int blockStartState(const QTextBlock &block)
-{
- int state = block.userState();
-
- if (state == -1)
- return 0;
- else
- return state & 0xff;
-}
-
-static bool shouldInsertMatchingText(QChar lookAhead)
-{
- switch (lookAhead.unicode()) {
- case '{': case '}':
- case ']': case ')':
- case ';': case ',':
- case '"': case '\'':
- return true;
-
- default:
- if (lookAhead.isSpace())
- return true;
-
- return false;
- } // switch
-}
-
-static bool shouldInsertMatchingText(const QTextCursor &tc)
-{
- QTextDocument *doc = tc.document();
- return shouldInsertMatchingText(doc->characterAt(tc.selectionEnd()));
-}
-
namespace {
class FindIdDeclarations: protected Visitor
@@ -631,51 +603,6 @@ int SemanticInfo::revision() const
return 0;
}
-QmlJSEditorEditable::QmlJSEditorEditable(QmlJSTextEditor *editor)
- : BaseTextEditorEditable(editor)
-{
- m_context.add(QmlJSEditor::Constants::C_QMLJSEDITOR_ID);
- m_context.add(TextEditor::Constants::C_TEXTEDITOR);
-}
-
-// Use preferred mode from Bauhaus settings
-static bool openInDesignMode()
-{
- static bool bauhausDetected = false;
- static bool bauhausPresent = false;
- // Check if Bauhaus is loaded, that is, a Design mode widget is
- // registered for the QML mime type.
- if (!bauhausDetected) {
- if (const Core::IMode *dm = Core::ModeManager::instance()->mode(QLatin1String(Core::Constants::MODE_DESIGN)))
- if (const Core::DesignMode *designMode = qobject_cast<const Core::DesignMode *>(dm))
- bauhausPresent = designMode->registeredMimeTypes().contains(QLatin1String(QmlJSEditor::Constants::QML_MIMETYPE));
- bauhausDetected = true;
- }
- if (!bauhausPresent)
- return false;
-
- return bool(QmlDesigner::Constants::QML_OPENDESIGNMODE_DEFAULT);
-}
-
-QString QmlJSEditorEditable::preferredModeType() const
-{
- Core::ModeManager *modeManager = Core::ModeManager::instance();
- if (modeManager->currentMode()
- && (modeManager->currentMode()->type() == Core::Constants::MODE_DESIGN_TYPE
- || modeManager->currentMode()->type() == Core::Constants::MODE_EDIT_TYPE))
- {
- return modeManager->currentMode()->type();
- }
-
- // if we are in other mode than edit or design, use the hard-coded default.
- // because the editor opening decision is modal, it would be confusing to
- // have the user also access to this failsafe setting.
- if (editor()->mimeType() == QLatin1String(QmlJSEditor::Constants::QML_MIMETYPE)
- && openInDesignMode())
- return QLatin1String(Core::Constants::MODE_DESIGN_TYPE);
- return QString();
-}
-
QmlJSTextEditor::QmlJSTextEditor(QWidget *parent) :
TextEditor::BaseTextEditor(parent),
m_outlineCombo(0),
@@ -685,7 +612,7 @@ QmlJSTextEditor::QmlJSTextEditor(QWidget *parent) :
m_updateSelectedElements(false),
m_findReferences(new FindReferences(this))
{
- qRegisterMetaType<QmlJSEditor::Internal::SemanticInfo>("QmlJSEditor::Internal::SemanticInfo");
+ qRegisterMetaType<QmlJSEditor::SemanticInfo>("QmlJSEditor::SemanticInfo");
m_semanticHighlighter = new SemanticHighlighter(this);
m_semanticHighlighter->start();
@@ -693,6 +620,8 @@ QmlJSTextEditor::QmlJSTextEditor(QWidget *parent) :
setParenthesesMatchingEnabled(true);
setMarksVisible(true);
setCodeFoldingSupported(true);
+ setIndenter(new Indenter);
+ setAutoCompleter(new AutoCompleter);
m_updateDocumentTimer = new QTimer(this);
m_updateDocumentTimer->setInterval(UPDATE_DOCUMENT_DEFAULT_INTERVAL);
@@ -750,11 +679,11 @@ QmlJSTextEditor::QmlJSTextEditor(QWidget *parent) :
connect(this->document(), SIGNAL(modificationChanged(bool)), this, SLOT(modificationChanged(bool)));
}
- connect(m_semanticHighlighter, SIGNAL(changed(QmlJSEditor::Internal::SemanticInfo)),
- this, SLOT(updateSemanticInfo(QmlJSEditor::Internal::SemanticInfo)));
+ connect(m_semanticHighlighter, SIGNAL(changed(QmlJSEditor::SemanticInfo)),
+ this, SLOT(updateSemanticInfo(QmlJSEditor::SemanticInfo)));
- connect(this, SIGNAL(refactorMarkerClicked(TextEditor::Internal::RefactorMarker)),
- SLOT(onRefactorMarkerClicked(TextEditor::Internal::RefactorMarker)));
+ connect(this, SIGNAL(refactorMarkerClicked(TextEditor::RefactorMarker)),
+ SLOT(onRefactorMarkerClicked(TextEditor::RefactorMarker)));
setRequestMarkEnabled(true);
}
@@ -878,16 +807,13 @@ void QmlJSTextEditor::onDocumentUpdated(QmlJS::Document::Ptr doc)
{
if (file()->fileName() != doc->fileName()
|| doc->editorRevision() != document()->revision()) {
- // didn't get the currently open, or an up to date document.
- // trigger a semantic rehighlight anyway, after a time
- m_semanticRehighlightTimer->start();
return;
}
if (doc->ast()) {
// got a correctly parsed (or recovered) file.
- const SemanticHighlighter::Source source = currentSource(/*force = */ true);
+ const SemanticHighlighterSource source = currentSource(/*force = */ true);
m_semanticHighlighter->rehighlight(source);
} else {
// show parsing errors
@@ -988,21 +914,21 @@ void QmlJSTextEditor::updateCursorPositionNow()
m_contextPane->apply(editableInterface(), semanticInfo().document, LookupContext::Ptr(),newNode, false);
if (m_contextPane->isAvailable(editableInterface(), semanticInfo().document, newNode) &&
!m_contextPane->widget()->isVisible()) {
- QList<TextEditor::Internal::RefactorMarker> markers;
+ QList<TextEditor::RefactorMarker> markers;
if (UiObjectMember *m = newNode->uiObjectMemberCast()) {
const int start = qualifiedTypeNameId(m)->identifierToken.begin();
for (UiQualifiedId *q = qualifiedTypeNameId(m); q; q = q->next) {
if (! q->next) {
const int end = q->identifierToken.end();
if (position() >= start && position() <= end) {
- TextEditor::Internal::RefactorMarker marker;
+ TextEditor::RefactorMarker marker;
QTextCursor tc(document());
tc.setPosition(end);
marker.cursor = tc;
marker.tooltip = tr("Show Qt Quick ToolBar");
markers.append(marker);
} else {
- QList<TextEditor::Internal::RefactorMarker> markers;
+ QList<TextEditor::RefactorMarker> markers;
setRefactorMarkers(markers);
}
}
@@ -1010,7 +936,7 @@ void QmlJSTextEditor::updateCursorPositionNow()
}
setRefactorMarkers(markers);
} else if (oldNode != newNode) {
- QList<TextEditor::Internal::RefactorMarker> markers;
+ QList<TextEditor::RefactorMarker> markers;
setRefactorMarkers(markers);
}
m_oldCursorPosition = position();
@@ -1131,11 +1057,13 @@ protected:
{
Bind *bind = m_lookupContext->document()->bind();
const Interpreter::ObjectValue *objValue = bind->findQmlObject(ast);
- QStringList prototypes;
+ if (!objValue)
+ return false;
- while (objValue) {
- prototypes.append(objValue->className());
- objValue = objValue->prototype(m_lookupContext->context());
+ QStringList prototypes;
+ foreach (const Interpreter::ObjectValue *value,
+ Interpreter::PrototypeIterator(objValue, m_lookupContext->context()).all()) {
+ prototypes.append(value->className());
}
return prototypes.contains(QString("QGraphicsObject"));
@@ -1260,27 +1188,7 @@ void QmlJSTextEditor::setFontSettings(const TextEditor::FontSettings &fs)
if (!highlighter)
return;
- /*
- NumberFormat,
- StringFormat,
- TypeFormat,
- KeywordFormat,
- LabelFormat,
- CommentFormat,
- VisualWhitespace,
- */
- static QVector<QString> categories;
- if (categories.isEmpty()) {
- categories << QLatin1String(TextEditor::Constants::C_NUMBER)
- << QLatin1String(TextEditor::Constants::C_STRING)
- << QLatin1String(TextEditor::Constants::C_TYPE)
- << QLatin1String(TextEditor::Constants::C_KEYWORD)
- << QLatin1String(TextEditor::Constants::C_FIELD)
- << QLatin1String(TextEditor::Constants::C_COMMENT)
- << QLatin1String(TextEditor::Constants::C_VISUAL_WHITESPACE);
- }
-
- highlighter->setFormats(fs.toTextCharFormats(categories));
+ highlighter->setFormats(fs.toTextCharFormats(highlighterFormatCategories()));
highlighter->rehighlight();
m_occurrencesFormat = fs.toTextCharFormat(QLatin1String(TextEditor::Constants::C_OCCURRENCES));
@@ -1310,15 +1218,6 @@ QString QmlJSTextEditor::wordUnderCursor() const
return word;
}
-bool QmlJSTextEditor::isElectricCharacter(QChar ch) const
-{
- if (ch == QLatin1Char('}')
- || ch == QLatin1Char(']')
- || ch == QLatin1Char(':'))
- return true;
- return false;
-}
-
bool QmlJSTextEditor::isClosingBrace(const QList<Token> &tokens) const
{
@@ -1331,19 +1230,6 @@ bool QmlJSTextEditor::isClosingBrace(const QList<Token> &tokens) const
return false;
}
-void QmlJSTextEditor::indentBlock(QTextDocument *doc, QTextBlock block, QChar typedChar)
-{
- Q_UNUSED(doc)
- Q_UNUSED(typedChar)
-
- const TextEditor::TabSettings &ts = tabSettings();
- QmlJSEditor::QtStyleCodeFormatter codeFormatter(ts);
-
- codeFormatter.updateStateUntil(block);
- const int depth = codeFormatter.indentFor(block);
- ts.indentLine(block, depth);
-}
-
TextEditor::BaseTextEditorEditable *QmlJSTextEditor::createEditableInterface()
{
QmlJSEditorEditable *editable = new QmlJSEditorEditable(this);
@@ -1406,7 +1292,8 @@ TextEditor::BaseTextEditor::Link QmlJSTextEditor::findLinkAt(const QTextCursor &
}
LookupContext::Ptr lookupContext = semanticInfo.lookupContext(semanticInfo.astPath(cursorPosition));
- const Interpreter::Value *value = lookupContext->evaluate(node);
+ Evaluate evaluator(lookupContext->context());
+ const Interpreter::Value *value = evaluator.reference(node);
QString fileName;
int line = 0, column = 0;
@@ -1458,7 +1345,7 @@ void QmlJSTextEditor::showContextPane()
Node *newNode = m_semanticInfo.declaringMemberNoProperties(position());
m_contextPane->apply(editableInterface(), m_semanticInfo.document, m_semanticInfo.lookupContext(), newNode, false, true);
m_oldCursorPosition = position();
- QList<TextEditor::Internal::RefactorMarker> markers;
+ QList<TextEditor::RefactorMarker> markers;
setRefactorMarkers(markers);
}
}
@@ -1572,200 +1459,6 @@ void QmlJSTextEditor::unCommentSelection()
Utils::unCommentSelection(this);
}
-static bool isCompleteStringLiteral(const QStringRef &text)
-{
- if (text.length() < 2)
- return false;
-
- const QChar quote = text.at(0);
-
- if (text.at(text.length() - 1) == quote)
- return text.at(text.length() - 2) != QLatin1Char('\\'); // ### not exactly.
-
- return false;
-}
-
-static Token tokenUnderCursor(const QTextCursor &cursor)
-{
- const QString blockText = cursor.block().text();
- const int blockState = blockStartState(cursor.block());
-
- Scanner tokenize;
- const QList<Token> tokens = tokenize(blockText, blockState);
- const int pos = cursor.positionInBlock();
-
- int tokenIndex = 0;
- for (; tokenIndex < tokens.size(); ++tokenIndex) {
- const Token &token = tokens.at(tokenIndex);
-
- if (token.is(Token::Comment) || token.is(Token::String)) {
- if (pos > token.begin() && pos <= token.end())
- break;
- } else {
- if (pos >= token.begin() && pos < token.end())
- break;
- }
- }
-
- if (tokenIndex != tokens.size())
- return tokens.at(tokenIndex);
-
- return Token();
-}
-
-bool QmlJSTextEditor::contextAllowsAutoParentheses(const QTextCursor &cursor, const QString &textToInsert) const
-{
- QChar ch;
-
- if (! textToInsert.isEmpty())
- ch = textToInsert.at(0);
-
- switch (ch.unicode()) {
- case '\'':
- case '"':
-
- case '(':
- case '[':
- case '{':
-
- case ')':
- case ']':
- case '}':
-
- case ';':
- break;
-
- default:
- if (ch.isNull())
- break;
-
- return false;
- } // end of switch
-
- const Token token = tokenUnderCursor(cursor);
- switch (token.kind) {
- case Token::Comment:
- return false;
-
- case Token::String: {
- const QString blockText = cursor.block().text();
- const QStringRef tokenText = blockText.midRef(token.offset, token.length);
- const QChar quote = tokenText.at(0);
-
- if (ch != quote || isCompleteStringLiteral(tokenText))
- break;
-
- return false;
- }
-
- default:
- break;
- } // end of switch
-
- return true;
-}
-
-bool QmlJSTextEditor::contextAllowsElectricCharacters(const QTextCursor &cursor) const
-{
- Token token = tokenUnderCursor(cursor);
- switch (token.kind) {
- case Token::Comment:
- case Token::String:
- return false;
- default:
- return true;
- }
-}
-
-bool QmlJSTextEditor::isInComment(const QTextCursor &cursor) const
-{
- return tokenUnderCursor(cursor).is(Token::Comment);
-}
-
-QString QmlJSTextEditor::insertMatchingBrace(const QTextCursor &tc, const QString &text, QChar, int *skippedChars) const
-{
- if (text.length() != 1)
- return QString();
-
- if (! shouldInsertMatchingText(tc))
- return QString();
-
- const QChar la = characterAt(tc.position());
-
- const QChar ch = text.at(0);
- switch (ch.unicode()) {
- case '\'':
- if (la != ch)
- return QString(ch);
- ++*skippedChars;
- break;
-
- case '"':
- if (la != ch)
- return QString(ch);
- ++*skippedChars;
- break;
-
- case '(':
- return QString(QLatin1Char(')'));
-
- case '[':
- return QString(QLatin1Char(']'));
-
- case '{':
- return QString(); // nothing to do.
-
- case ')':
- case ']':
- case '}':
- case ';':
- if (la == ch)
- ++*skippedChars;
- break;
-
- default:
- break;
- } // end of switch
-
- return QString();
-}
-
-static bool shouldInsertNewline(const QTextCursor &tc)
-{
- QTextDocument *doc = tc.document();
- int pos = tc.selectionEnd();
-
- // count the number of empty lines.
- int newlines = 0;
- for (int e = doc->characterCount(); pos != e; ++pos) {
- const QChar ch = doc->characterAt(pos);
-
- if (! ch.isSpace())
- break;
- else if (ch == QChar::ParagraphSeparator)
- ++newlines;
- }
-
- if (newlines <= 1 && doc->characterAt(pos) != QLatin1Char('}'))
- return true;
-
- return false;
-}
-
-QString QmlJSTextEditor::insertParagraphSeparator(const QTextCursor &tc) const
-{
- if (shouldInsertNewline(tc)) {
- QTextCursor cursor = tc;
- cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
- if (! cursor.selectedText().trimmed().isEmpty())
- return QString();
-
- return QLatin1String("}\n");
- }
-
- return QLatin1String("}");
-}
-
void QmlJSTextEditor::forceSemanticRehighlight()
{
m_semanticHighlighter->rehighlight(currentSource(/* force = */ true));
@@ -1816,7 +1509,7 @@ void QmlJSTextEditor::updateSemanticInfo(const SemanticInfo &semanticInfo)
setExtraSelections(CodeWarningsSelection, selections);
}
-void QmlJSTextEditor::onRefactorMarkerClicked(const TextEditor::Internal::RefactorMarker &)
+void QmlJSTextEditor::onRefactorMarkerClicked(const TextEditor::RefactorMarker &)
{
showContextPane();
}
@@ -1859,7 +1552,31 @@ bool QmlJSTextEditor::hideContextPane()
return b;
}
-SemanticHighlighter::Source QmlJSTextEditor::currentSource(bool force)
+QVector<QString> QmlJSTextEditor::highlighterFormatCategories()
+{
+ /*
+ NumberFormat,
+ StringFormat,
+ TypeFormat,
+ KeywordFormat,
+ LabelFormat,
+ CommentFormat,
+ VisualWhitespace,
+ */
+ static QVector<QString> categories;
+ if (categories.isEmpty()) {
+ categories << QLatin1String(TextEditor::Constants::C_NUMBER)
+ << QLatin1String(TextEditor::Constants::C_STRING)
+ << QLatin1String(TextEditor::Constants::C_TYPE)
+ << QLatin1String(TextEditor::Constants::C_KEYWORD)
+ << QLatin1String(TextEditor::Constants::C_FIELD)
+ << QLatin1String(TextEditor::Constants::C_COMMENT)
+ << QLatin1String(TextEditor::Constants::C_VISUAL_WHITESPACE);
+ }
+ return categories;
+}
+
+SemanticHighlighterSource QmlJSTextEditor::currentSource(bool force)
{
int line = 0, column = 0;
convertPosition(position(), &line, &column);
@@ -1872,119 +1589,8 @@ SemanticHighlighter::Source QmlJSTextEditor::currentSource(bool force)
code = toPlainText(); // get the source code only when needed.
const unsigned revision = document()->revision();
- SemanticHighlighter::Source source(snapshot, fileName, code,
+ SemanticHighlighterSource source(snapshot, fileName, code,
line, column, revision);
source.force = force;
return source;
}
-
-SemanticHighlighter::SemanticHighlighter(QObject *parent)
- : QThread(parent),
- m_done(false),
- m_modelManager(0)
-{
-}
-
-SemanticHighlighter::~SemanticHighlighter()
-{
-}
-
-void SemanticHighlighter::abort()
-{
- QMutexLocker locker(&m_mutex);
- m_done = true;
- m_condition.wakeOne();
-}
-
-void SemanticHighlighter::rehighlight(const Source &source)
-{
- QMutexLocker locker(&m_mutex);
- m_source = source;
- m_condition.wakeOne();
-}
-
-bool SemanticHighlighter::isOutdated()
-{
- QMutexLocker locker(&m_mutex);
- const bool outdated = ! m_source.fileName.isEmpty() || m_done;
- return outdated;
-}
-
-void SemanticHighlighter::run()
-{
- setPriority(QThread::LowestPriority);
-
- forever {
- m_mutex.lock();
-
- while (! (m_done || ! m_source.fileName.isEmpty()))
- m_condition.wait(&m_mutex);
-
- const bool done = m_done;
- const Source source = m_source;
- m_source.clear();
-
- m_mutex.unlock();
-
- if (done)
- break;
-
- const SemanticInfo info = semanticInfo(source);
-
- if (! isOutdated()) {
- m_mutex.lock();
- m_lastSemanticInfo = info;
- m_mutex.unlock();
-
- emit changed(info);
- }
- }
-}
-
-SemanticInfo SemanticHighlighter::semanticInfo(const Source &source)
-{
- m_mutex.lock();
- const int revision = m_lastSemanticInfo.revision();
- m_mutex.unlock();
-
- Snapshot snapshot;
- Document::Ptr doc;
-
- if (! source.force && revision == source.revision) {
- m_mutex.lock();
- snapshot = m_lastSemanticInfo.snapshot;
- doc = m_lastSemanticInfo.document;
- m_mutex.unlock();
- }
-
- if (! doc) {
- snapshot = source.snapshot;
- doc = snapshot.documentFromSource(source.code, source.fileName);
- doc->setEditorRevision(source.revision);
- doc->parse();
- snapshot.insert(doc);
- }
-
- SemanticInfo semanticInfo;
- semanticInfo.snapshot = snapshot;
- semanticInfo.document = doc;
-
- Interpreter::Context *ctx = new Interpreter::Context;
- Link link(ctx, doc, snapshot, ModelManagerInterface::instance()->importPaths());
- semanticInfo.m_context = QSharedPointer<const QmlJS::Interpreter::Context>(ctx);
- semanticInfo.semanticMessages = link.diagnosticMessages();
-
- QStringList importPaths;
- if (m_modelManager)
- importPaths = m_modelManager->importPaths();
- Check checker(doc, snapshot, ctx);
- semanticInfo.semanticMessages.append(checker());
-
- return semanticInfo;
-}
-
-void SemanticHighlighter::setModelManager(QmlJS::ModelManagerInterface *modelManager)
-{
- m_modelManager = modelManager;
-}
-
diff --git a/src/plugins/qmljseditor/qmljseditor.h b/src/plugins/qmljseditor/qmljseditor.h
index 99b8234fb1..2fec131344 100644
--- a/src/plugins/qmljseditor/qmljseditor.h
+++ b/src/plugins/qmljseditor/qmljseditor.h
@@ -42,10 +42,8 @@
#include <texteditor/basetexteditor.h>
#include <texteditor/quickfix.h>
-#include <QtCore/QWaitCondition>
+#include <QtCore/QSharedPointer>
#include <QtCore/QModelIndex>
-#include <QtCore/QMutex>
-#include <QtCore/QThread>
QT_BEGIN_NAMESPACE
class QComboBox;
@@ -66,34 +64,16 @@ namespace QmlJS {
The top-level namespace of the QmlJSEditor plug-in.
*/
namespace QmlJSEditor {
-class Highlighter;
+class QmlJSEditorEditable;
class FindReferences;
namespace Internal {
-
-class QmlJSTextEditor;
class QmlOutlineModel;
+class SemanticHighlighter;
+struct SemanticHighlighterSource;
+} // namespace Internal
-class QmlJSEditorEditable : public TextEditor::BaseTextEditorEditable
-{
- Q_OBJECT
-
-public:
- QmlJSEditorEditable(QmlJSTextEditor *);
- Core::Context context() const;
-
- bool duplicateSupported() const { return true; }
- Core::IEditor *duplicate(QWidget *parent);
- QString id() const;
- bool isTemporary() const { return false; }
- virtual bool open(const QString & fileName);
- virtual QString preferredModeType() const;
-
-private:
- Core::Context m_context;
-};
-
-struct Declaration
+struct QMLJSEDITOR_EXPORT Declaration
{
QString text;
int startLine;
@@ -109,7 +89,7 @@ struct Declaration
{ }
};
-class Range
+class QMLJSEDITOR_EXPORT Range
{
public:
Range(): ast(0) {}
@@ -120,8 +100,6 @@ public: // attributes
QTextCursor end;
};
-class SemanticHighlighter;
-
class QMLJSEDITOR_EXPORT SemanticInfo
{
public:
@@ -156,75 +134,7 @@ public: // attributes
private:
QSharedPointer<const QmlJS::Interpreter::Context> m_context;
- friend class SemanticHighlighter;
-};
-
-class SemanticHighlighter: public QThread
-{
- Q_OBJECT
-
-public:
- SemanticHighlighter(QObject *parent = 0);
- virtual ~SemanticHighlighter();
-
- void abort();
-
- struct Source
- {
- QmlJS::Snapshot snapshot;
- QString fileName;
- QString code;
- int line;
- int column;
- int revision;
- bool force;
-
- Source()
- : line(0), column(0), revision(0), force(false)
- { }
-
- Source(const QmlJS::Snapshot &snapshot,
- const QString &fileName,
- const QString &code,
- int line, int column,
- int revision)
- : snapshot(snapshot), fileName(fileName),
- code(code), line(line), column(column),
- revision(revision), force(false)
- { }
-
- void clear()
- {
- snapshot = QmlJS::Snapshot();
- fileName.clear();
- code.clear();
- line = 0;
- column = 0;
- revision = 0;
- force = false;
- }
- };
-
- void rehighlight(const Source &source);
- void setModelManager(QmlJS::ModelManagerInterface *modelManager);
-
-Q_SIGNALS:
- void changed(const QmlJSEditor::Internal::SemanticInfo &semanticInfo);
-
-protected:
- virtual void run();
-
-private:
- bool isOutdated();
- SemanticInfo semanticInfo(const Source &source);
-
-private:
- QMutex m_mutex;
- QWaitCondition m_condition;
- bool m_done;
- Source m_source;
- SemanticInfo m_lastSemanticInfo;
- QmlJS::ModelManagerInterface *m_modelManager;
+ friend class Internal::SemanticHighlighter;
};
class QMLJSEDITOR_EXPORT QmlJSTextEditor : public TextEditor::BaseTextEditor
@@ -241,7 +151,7 @@ public:
int editorRevision() const;
bool isOutdated() const;
- QmlOutlineModel *outlineModel() const;
+ Internal::QmlOutlineModel *outlineModel() const;
QModelIndex outlineModelIndex();
bool updateSelectedElements() const;
@@ -249,7 +159,10 @@ public:
void renameId(const QString &oldId, const QString &newId);
+ static QVector<QString> highlighterFormatCategories();
+
public slots:
+ void forceSemanticRehighlight();
void followSymbolUnderCursor();
void findUsages();
void showContextPane();
@@ -279,10 +192,9 @@ private slots:
void renameIdUnderCursor();
void semanticRehighlight();
- void forceSemanticRehighlight();
- void updateSemanticInfo(const QmlJSEditor::Internal::SemanticInfo &semanticInfo);
+ void updateSemanticInfo(const QmlJSEditor::SemanticInfo &semanticInfo);
void onCursorPositionChanged();
- void onRefactorMarkerClicked(const TextEditor::Internal::RefactorMarker &marker);
+ void onRefactorMarkerClicked(const TextEditor::RefactorMarker &marker);
void performQuickFix(int index);
@@ -296,22 +208,13 @@ protected:
void createToolBar(QmlJSEditorEditable *editable);
TextEditor::BaseTextEditor::Link findLinkAt(const QTextCursor &cursor, bool resolveTarget = true);
- //// brace matching
- virtual bool contextAllowsAutoParentheses(const QTextCursor &cursor, const QString &textToInsert = QString()) const;
- virtual bool contextAllowsElectricCharacters(const QTextCursor &cursor) const;
- virtual bool isInComment(const QTextCursor &cursor) const;
- virtual QString insertMatchingBrace(const QTextCursor &tc, const QString &text, QChar la, int *skippedChars) const;
- virtual QString insertParagraphSeparator(const QTextCursor &tc) const;
-
private:
- virtual bool isElectricCharacter(QChar ch) const;
- virtual void indentBlock(QTextDocument *doc, QTextBlock block, QChar typedChar);
bool isClosingBrace(const QList<QmlJS::Token> &tokens) const;
void setSelectedElements();
QString wordUnderCursor() const;
- SemanticHighlighter::Source currentSource(bool force = false);
+ Internal::SemanticHighlighterSource currentSource(bool force = false);
QModelIndex indexForPosition(unsigned cursorPosition, const QModelIndex &rootIndex = QModelIndex()) const;
bool hideContextPane();
@@ -324,14 +227,14 @@ private:
QTimer *m_updateOutlineIndexTimer;
QTimer *m_cursorPositionTimer;
QComboBox *m_outlineCombo;
- QmlOutlineModel *m_outlineModel;
+ Internal::QmlOutlineModel *m_outlineModel;
QModelIndex m_outlineModelIndex;
QmlJS::ModelManagerInterface *m_modelManager;
QTextCharFormat m_occurrencesFormat;
QTextCharFormat m_occurrencesUnusedFormat;
QTextCharFormat m_occurrenceRenameFormat;
- SemanticHighlighter *m_semanticHighlighter;
+ Internal::SemanticHighlighter *m_semanticHighlighter;
SemanticInfo m_semanticInfo;
QList<TextEditor::QuickFixOperation::Ptr> m_quickFixes;
@@ -343,7 +246,6 @@ private:
FindReferences *m_findReferences;
};
-} // namespace Internal
} // namespace QmlJSEditor
#endif // QMLJSEDITOR_H
diff --git a/src/plugins/qmljseditor/qmljseditor.pri b/src/plugins/qmljseditor/qmljseditor.pri
index 3bf969a302..aac9022e3e 100644
--- a/src/plugins/qmljseditor/qmljseditor.pri
+++ b/src/plugins/qmljseditor/qmljseditor.pri
@@ -1,3 +1,3 @@
include(qmljseditor_dependencies.pri)
-LIBS *= -l$$qtLibraryTarget(QmlJSEditor)
+LIBS *= -l$$qtLibraryName(QmlJSEditor)
diff --git a/src/plugins/qmljseditor/qmljseditor.pro b/src/plugins/qmljseditor/qmljseditor.pro
index 8a6c725379..6d08513810 100644
--- a/src/plugins/qmljseditor/qmljseditor.pro
+++ b/src/plugins/qmljseditor/qmljseditor.pro
@@ -19,20 +19,23 @@ HEADERS += \
qmlfilewizard.h \
qmljshighlighter.h \
qmljshoverhandler.h \
- qmljsmodelmanager.h \
qmljspreviewrunner.h \
qmljsquickfix.h \
- qmljsrefactoringchanges.h \
qmljscomponentfromobjectdef.h \
qmljsoutline.h \
qmloutlinemodel.h \
qmltaskmanager.h \
- qmljseditorcodeformatter.h \
qmljsoutlinetreeview.h \
quicktoolbarsettingspage.h \
quicktoolbar.h \
qmljscomponentnamedialog.h \
- qmljsfindreferences.h
+ qmljsfindreferences.h \
+ qmljseditoreditable.h \
+ qmljssemantichighlighter.h \
+ qmljsindenter.h \
+ qmljsautocompleter.h \
+ jsfilewizard.h \
+ qmljssnippetprovider.h
SOURCES += \
qmljscodecompletion.cpp \
@@ -44,24 +47,27 @@ SOURCES += \
qmlfilewizard.cpp \
qmljshighlighter.cpp \
qmljshoverhandler.cpp \
- qmljsmodelmanager.cpp \
qmljspreviewrunner.cpp \
qmljsquickfix.cpp \
- qmljsrefactoringchanges.cpp \
qmljscomponentfromobjectdef.cpp \
qmljsoutline.cpp \
qmloutlinemodel.cpp \
qmltaskmanager.cpp \
qmljsquickfixes.cpp \
- qmljseditorcodeformatter.cpp \
qmljsoutlinetreeview.cpp \
quicktoolbarsettingspage.cpp \
quicktoolbar.cpp \
qmljscomponentnamedialog.cpp \
- qmljsfindreferences.cpp
+ qmljsfindreferences.cpp \
+ qmljseditoreditable.cpp \
+ qmljssemantichighlighter.cpp \
+ qmljsindenter.cpp \
+ qmljsautocompleter.cpp \
+ jsfilewizard.cpp \
+ qmljssnippetprovider.cpp
RESOURCES += qmljseditor.qrc
-OTHER_FILES += QmlJSEditor.pluginspec QmlJSEditor.mimetypes.xml
+OTHER_FILES += QmlJSEditor.mimetypes.xml
FORMS += \
quicktoolbarsettingspage.ui \
diff --git a/src/plugins/qmljseditor/qmljseditor_dependencies.pri b/src/plugins/qmljseditor/qmljseditor_dependencies.pri
index 97beaaa746..5634e49ad4 100644
--- a/src/plugins/qmljseditor/qmljseditor_dependencies.pri
+++ b/src/plugins/qmljseditor/qmljseditor_dependencies.pri
@@ -1,6 +1,6 @@
include(../../plugins/coreplugin/coreplugin.pri)
include(../../plugins/texteditor/texteditor.pri)
include(../../plugins/projectexplorer/projectexplorer.pri)
-include(../../libs/qmljs/qmljs.pri)
+include(../../plugins/qmljstools/qmljstools.pri)
include(../../libs/utils/utils.pri)
include(../../libs/qmleditorwidgets/qmleditorwidgets.pri)
diff --git a/src/plugins/qmljseditor/qmljseditorcodeformatter.cpp b/src/plugins/qmljseditor/qmljseditorcodeformatter.cpp
deleted file mode 100644
index ef99e98c41..0000000000
--- a/src/plugins/qmljseditor/qmljseditorcodeformatter.cpp
+++ /dev/null
@@ -1,363 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#include "qmljseditorcodeformatter.h"
-
-#include <texteditor/tabsettings.h>
-
-#include <QtCore/QDebug>
-
-using namespace QmlJS;
-using namespace QmlJSEditor;
-using namespace TextEditor;
-
-QtStyleCodeFormatter::QtStyleCodeFormatter()
- : m_indentSize(4)
-{
-}
-
-QtStyleCodeFormatter::QtStyleCodeFormatter(const TextEditor::TabSettings &tabSettings)
- : m_indentSize(tabSettings.m_indentSize)
-{
- setTabSize(tabSettings.m_tabSize);
-}
-
-void QtStyleCodeFormatter::setIndentSize(int size)
-{
- m_indentSize = size;
-}
-
-void QtStyleCodeFormatter::saveBlockData(QTextBlock *block, const BlockData &data) const
-{
- TextBlockUserData *userData = BaseTextDocumentLayout::userData(*block);
- QmlJSCodeFormatterData *cppData = static_cast<QmlJSCodeFormatterData *>(userData->codeFormatterData());
- if (!cppData) {
- cppData = new QmlJSCodeFormatterData;
- userData->setCodeFormatterData(cppData);
- }
- cppData->m_data = data;
-}
-
-bool QtStyleCodeFormatter::loadBlockData(const QTextBlock &block, BlockData *data) const
-{
- TextBlockUserData *userData = BaseTextDocumentLayout::testUserData(block);
- if (!userData)
- return false;
- QmlJSCodeFormatterData *cppData = static_cast<QmlJSCodeFormatterData *>(userData->codeFormatterData());
- if (!cppData)
- return false;
-
- *data = cppData->m_data;
- return true;
-}
-
-void QtStyleCodeFormatter::saveLexerState(QTextBlock *block, int state) const
-{
- BaseTextDocumentLayout::setLexerState(*block, state);
-}
-
-int QtStyleCodeFormatter::loadLexerState(const QTextBlock &block) const
-{
- return BaseTextDocumentLayout::lexerState(block);
-}
-
-void QtStyleCodeFormatter::onEnter(int newState, int *indentDepth, int *savedIndentDepth) const
-{
- const State &parentState = state();
- const Token &tk = currentToken();
- const int tokenPosition = column(tk.begin());
- const bool firstToken = (tokenIndex() == 0);
- const bool lastToken = (tokenIndex() == tokenCount() - 1);
-
- switch (newState) {
- case objectdefinition_open: {
- // special case for things like "gradient: Gradient {"
- if (parentState.type == binding_assignment)
- *savedIndentDepth = state(1).savedIndentDepth;
-
- if (firstToken)
- *savedIndentDepth = tokenPosition;
-
- *indentDepth = *savedIndentDepth + m_indentSize;
- break;
- }
-
- case binding_or_objectdefinition:
- if (firstToken)
- *indentDepth = *savedIndentDepth = tokenPosition;
- break;
-
- case binding_assignment:
- if (lastToken)
- *indentDepth = *savedIndentDepth + 4;
- else
- *indentDepth = column(tokenAt(tokenIndex() + 1).begin());
- break;
-
- case expression_or_objectdefinition:
- *indentDepth = tokenPosition;
- break;
-
- case expression:
- // expression_or_objectdefinition has already consumed the first token
- // ternary already adjusts indents nicely
- if (parentState.type != expression_or_objectdefinition
- && parentState.type != binding_assignment
- && parentState.type != ternary_op) {
- *indentDepth += 2 * m_indentSize;
- }
- if (!firstToken && parentState.type != expression_or_objectdefinition) {
- *indentDepth = tokenPosition;
- }
- break;
-
- case expression_maybe_continuation:
- // set indent depth to indent we'd get if the expression ended here
- for (int i = 1; state(i).type != topmost_intro; ++i) {
- const int type = state(i).type;
- if (isExpressionEndState(type) && !isBracelessState(type)) {
- *indentDepth = state(i - 1).savedIndentDepth;
- break;
- }
- }
- break;
-
- case bracket_open:
- if (parentState.type == expression && state(1).type == binding_assignment) {
- *savedIndentDepth = state(2).savedIndentDepth;
- *indentDepth = *savedIndentDepth + m_indentSize;
- } else if (!lastToken) {
- *indentDepth = tokenPosition + 1;
- } else {
- *indentDepth = *savedIndentDepth + m_indentSize;
- }
- break;
-
- case function_start:
- if (parentState.type == expression) {
- // undo the continuation indent of the expression
- *indentDepth = parentState.savedIndentDepth;
- *savedIndentDepth = *indentDepth;
- }
- break;
-
- case do_statement_while_paren_open:
- case statement_with_condition_paren_open:
- case signal_arglist_open:
- case function_arglist_open:
- case paren_open:
- case condition_paren_open:
- if (!lastToken)
- *indentDepth = tokenPosition + 1;
- else
- *indentDepth += m_indentSize;
- break;
-
- case ternary_op:
- if (!lastToken)
- *indentDepth = tokenPosition + tk.length + 1;
- else
- *indentDepth += m_indentSize;
- break;
-
- case jsblock_open:
- // closing brace should be aligned to case
- if (parentState.type == case_cont) {
- *savedIndentDepth = parentState.savedIndentDepth;
- break;
- }
- // fallthrough
- case substatement_open:
- // special case for foo: {
- if (parentState.type == binding_assignment && state(1).type == binding_or_objectdefinition)
- *savedIndentDepth = state(1).savedIndentDepth;
- *indentDepth = *savedIndentDepth + m_indentSize;
- break;
-
- case statement_with_condition:
- case statement_with_block:
- case if_statement:
- case do_statement:
- case switch_statement:
- if (firstToken || parentState.type == binding_assignment)
- *savedIndentDepth = tokenPosition;
- // ### continuation
- *indentDepth = *savedIndentDepth; // + 2*m_indentSize;
- break;
-
- case maybe_else: {
- // set indent to outermost braceless savedIndent
- int outermostBraceless = 0;
- while (isBracelessState(state(outermostBraceless + 1).type))
- ++outermostBraceless;
- *indentDepth = state(outermostBraceless).savedIndentDepth;
- // this is where the else should go, if one appears - aligned to if_statement
- *savedIndentDepth = state().savedIndentDepth;
- break;
- }
-
- case condition_open:
- // fixed extra indent when continuing 'if (', but not for 'else if ('
- if (tokenPosition <= *indentDepth + m_indentSize)
- *indentDepth += 2*m_indentSize;
- else
- *indentDepth = tokenPosition + 1;
- break;
-
- case case_start:
- *savedIndentDepth = tokenPosition;
- break;
-
- case case_cont:
- *indentDepth += m_indentSize;
- break;
-
- case multiline_comment_start:
- *indentDepth = tokenPosition + 2;
- break;
-
- case multiline_comment_cont:
- *indentDepth = tokenPosition;
- break;
- }
-}
-
-void QtStyleCodeFormatter::adjustIndent(const QList<Token> &tokens, int lexerState, int *indentDepth) const
-{
- Q_UNUSED(lexerState)
-
- State topState = state();
- State previousState = state(1);
-
- // adjusting the indentDepth here instead of in enter() gives 'else if' the correct indentation
- // ### could be moved?
- if (topState.type == substatement)
- *indentDepth += m_indentSize;
-
- // keep user-adjusted indent in multiline comments
- if (topState.type == multiline_comment_start
- || topState.type == multiline_comment_cont) {
- if (!tokens.isEmpty()) {
- *indentDepth = column(tokens.at(0).begin());
- return;
- }
- }
-
- const int kind = extendedTokenKind(tokenAt(0));
- switch (kind) {
- case LeftBrace:
- if (topState.type == substatement
- || topState.type == binding_assignment
- || topState.type == case_cont) {
- *indentDepth = topState.savedIndentDepth;
- }
- break;
- case RightBrace: {
- if (topState.type == jsblock_open && previousState.type == case_cont) {
- *indentDepth = previousState.savedIndentDepth;
- break;
- }
- for (int i = 0; state(i).type != topmost_intro; ++i) {
- const int type = state(i).type;
- if (type == objectdefinition_open
- || type == jsblock_open
- || type == substatement_open) {
- *indentDepth = state(i).savedIndentDepth;
- break;
- }
- }
- break;
- }
- case RightBracket:
- for (int i = 0; state(i).type != topmost_intro; ++i) {
- const int type = state(i).type;
- if (type == bracket_open) {
- *indentDepth = state(i).savedIndentDepth;
- break;
- }
- }
- break;
-
- case LeftBracket:
- case LeftParenthesis:
- case Delimiter:
- if (topState.type == expression_maybe_continuation)
- *indentDepth = topState.savedIndentDepth;
- break;
-
- case Else:
- if (topState.type == maybe_else) {
- *indentDepth = topState.savedIndentDepth;
- } else if (topState.type == expression_maybe_continuation) {
- bool hasElse = false;
- for (int i = 1; state(i).type != topmost_intro; ++i) {
- const int type = state(i).type;
- if (type == else_clause)
- hasElse = true;
- if (type == if_statement) {
- if (hasElse) {
- hasElse = false;
- } else {
- *indentDepth = state(i).savedIndentDepth;
- break;
- }
- }
- }
- }
- break;
-
- case Colon:
- if (topState.type == ternary_op) {
- *indentDepth -= 2;
- }
- break;
-
- case Question:
- if (topState.type == expression_maybe_continuation)
- *indentDepth = topState.savedIndentDepth;
- break;
-
- case Default:
- case Case:
- for (int i = 0; state(i).type != topmost_intro; ++i) {
- const int type = state(i).type;
- if (type == switch_statement || type == case_cont) {
- *indentDepth = state(i).savedIndentDepth;
- break;
- } else if (type == topmost_intro) {
- break;
- }
- }
- break;
- }
-}
diff --git a/src/plugins/qmljseditor/qmljseditorcodeformatter.h b/src/plugins/qmljseditor/qmljseditorcodeformatter.h
deleted file mode 100644
index 741e9ac8d3..0000000000
--- a/src/plugins/qmljseditor/qmljseditorcodeformatter.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#ifndef QMLJSEDITORCODEFORMATTER_H
-#define QMLJSEDITORCODEFORMATTER_H
-
-#include "qmljseditor_global.h"
-
-#include <texteditor/basetextdocumentlayout.h>
-#include <qmljs/qmljscodeformatter.h>
-
-namespace TextEditor {
- class TabSettings;
-}
-
-namespace QmlJSEditor {
-
-class QMLJSEDITOR_EXPORT QtStyleCodeFormatter : public QmlJS::CodeFormatter
-{
-public:
- QtStyleCodeFormatter();
- explicit QtStyleCodeFormatter(const TextEditor::TabSettings &tabSettings);
-
- void setIndentSize(int size);
-
-protected:
- virtual void onEnter(int newState, int *indentDepth, int *savedIndentDepth) const;
- virtual void adjustIndent(const QList<QmlJS::Token> &tokens, int lexerState, int *indentDepth) const;
-
- virtual void saveBlockData(QTextBlock *block, const BlockData &data) const;
- virtual bool loadBlockData(const QTextBlock &block, BlockData *data) const;
-
- virtual void saveLexerState(QTextBlock *block, int state) const;
- virtual int loadLexerState(const QTextBlock &block) const;
-
-private:
- int m_indentSize;
-
- class QmlJSCodeFormatterData: public TextEditor::CodeFormatterData
- {
- public:
- QmlJS::CodeFormatter::BlockData m_data;
- };
-};
-
-} // namespace QmlJSEditor
-
-#endif // QMLJSEDITORCODEFORMATTER_H
diff --git a/src/plugins/qmljseditor/qmljseditorconstants.h b/src/plugins/qmljseditor/qmljseditorconstants.h
index c13164a885..a2df8bf36e 100644
--- a/src/plugins/qmljseditor/qmljseditorconstants.h
+++ b/src/plugins/qmljseditor/qmljseditorconstants.h
@@ -50,7 +50,6 @@ const char * const M_REFACTORING_MENU_INSERTION_POINT = "QmlJSEditor.RefactorGro
const char * const RUN_SEP = "QmlJSEditor.Run.Separator";
const char * const C_QMLJSEDITOR_ID = "QMLProjectManager.QMLJSEditor";
const char * const C_QMLJSEDITOR_DISPLAY_NAME = QT_TRANSLATE_NOOP("OpenWith::Editors", "QMLJS Editor");
-const char * const TASK_INDEX = "QmlJSEditor.TaskIndex";
const char * const TASK_SEARCH = "QmlJSEditor.TaskSearch";
const char * const FOLLOW_SYMBOL_UNDER_CURSOR = "QmlJSEditor.FollowSymbolUnderCursor";
@@ -65,6 +64,7 @@ const char *const TASK_CATEGORY_QML = "Task.Category.Qml";
const char * const WIZARD_CATEGORY_QML = "S.Qml";
const char * const WIZARD_TR_CATEGORY_QML = QT_TRANSLATE_NOOP("QmlJsEditor", "QML");
+const char * const QML_SNIPPETS_GROUP_ID = "QML";
} // namespace Constants
} // namespace QmlJSEditor
diff --git a/src/plugins/qmljseditor/qmljseditoreditable.cpp b/src/plugins/qmljseditor/qmljseditoreditable.cpp
new file mode 100644
index 0000000000..aabb07c1d4
--- /dev/null
+++ b/src/plugins/qmljseditor/qmljseditoreditable.cpp
@@ -0,0 +1,92 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "qmljseditoreditable.h"
+#include "qmljseditor.h"
+#include "qmljseditorconstants.h"
+
+#include <texteditor/texteditorconstants.h>
+#include <qmldesigner/qmldesignerconstants.h>
+#include <projectexplorer/projectexplorerconstants.h>
+
+#include <coreplugin/mimedatabase.h>
+#include <coreplugin/icore.h>
+#include <coreplugin/designmode.h>
+#include <coreplugin/modemanager.h>
+#include <coreplugin/coreconstants.h>
+
+namespace QmlJSEditor {
+
+QmlJSEditorEditable::QmlJSEditorEditable(QmlJSTextEditor *editor)
+ : BaseTextEditorEditable(editor)
+{
+ m_context.add(QmlJSEditor::Constants::C_QMLJSEDITOR_ID);
+ m_context.add(TextEditor::Constants::C_TEXTEDITOR);
+ m_context.add(ProjectExplorer::Constants::LANG_QMLJS);
+}
+
+// Use preferred mode from Bauhaus settings
+static bool openInDesignMode()
+{
+ static bool bauhausDetected = false;
+ static bool bauhausPresent = false;
+ // Check if Bauhaus is loaded, that is, a Design mode widget is
+ // registered for the QML mime type.
+ if (!bauhausDetected) {
+ if (const Core::IMode *dm = Core::ModeManager::instance()->mode(QLatin1String(Core::Constants::MODE_DESIGN)))
+ if (const Core::DesignMode *designMode = qobject_cast<const Core::DesignMode *>(dm))
+ bauhausPresent = designMode->registeredMimeTypes().contains(QLatin1String(QmlJSEditor::Constants::QML_MIMETYPE));
+ bauhausDetected = true;
+ }
+ if (!bauhausPresent)
+ return false;
+
+ return bool(QmlDesigner::Constants::QML_OPENDESIGNMODE_DEFAULT);
+}
+
+QString QmlJSEditorEditable::preferredModeType() const
+{
+ Core::ModeManager *modeManager = Core::ModeManager::instance();
+ if (modeManager->currentMode()
+ && (modeManager->currentMode()->type() == Core::Constants::MODE_DESIGN_TYPE
+ || modeManager->currentMode()->type() == Core::Constants::MODE_EDIT_TYPE))
+ {
+ return modeManager->currentMode()->type();
+ }
+
+ // if we are in other mode than edit or design, use the hard-coded default.
+ // because the editor opening decision is modal, it would be confusing to
+ // have the user also access to this failsafe setting.
+ if (editor()->mimeType() == QLatin1String(QmlJSEditor::Constants::QML_MIMETYPE)
+ && openInDesignMode())
+ return QLatin1String(Core::Constants::MODE_DESIGN_TYPE);
+ return QString();
+}
+
+} // namespace QmlJSEditor
diff --git a/src/plugins/qmljseditor/qmljseditoreditable.h b/src/plugins/qmljseditor/qmljseditoreditable.h
new file mode 100644
index 0000000000..c30433ea96
--- /dev/null
+++ b/src/plugins/qmljseditor/qmljseditoreditable.h
@@ -0,0 +1,60 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 QMLJSEDITOREDITABLE_H
+#define QMLJSEDITOREDITABLE_H
+
+#include "qmljseditor_global.h"
+#include <texteditor/basetexteditor.h>
+
+namespace QmlJSEditor {
+class QmlJSTextEditor;
+
+class QMLJSEDITOR_EXPORT QmlJSEditorEditable : public TextEditor::BaseTextEditorEditable
+{
+ Q_OBJECT
+
+public:
+ explicit QmlJSEditorEditable(QmlJSTextEditor *);
+ Core::Context context() const;
+
+ bool duplicateSupported() const { return true; }
+ Core::IEditor *duplicate(QWidget *parent);
+ QString id() const;
+ bool isTemporary() const { return false; }
+ virtual bool open(const QString & fileName);
+ virtual QString preferredModeType() const;
+
+private:
+ Core::Context m_context;
+};
+
+} // namespace QmlJSEditor
+
+#endif // QMLJSEDITOREDITABLE_H
diff --git a/src/plugins/qmljseditor/qmljseditorfactory.cpp b/src/plugins/qmljseditor/qmljseditorfactory.cpp
index 0e1967bb4f..6c76a01d23 100644
--- a/src/plugins/qmljseditor/qmljseditorfactory.cpp
+++ b/src/plugins/qmljseditor/qmljseditorfactory.cpp
@@ -32,6 +32,7 @@
**************************************************************************/
#include "qmljseditorfactory.h"
+#include "qmljseditoreditable.h"
#include "qmljseditor.h"
#include "qmljseditoractionhandler.h"
#include "qmljseditorconstants.h"
@@ -81,6 +82,7 @@ namespace {
}
}
+using namespace QmlJSEditor;
using namespace QmlJSEditor::Internal;
using namespace QmlJSEditor::Constants;
@@ -128,7 +130,7 @@ Core::IEditor *QmlJSEditorFactory::createEditor(QWidget *parent)
SLOT(updateEditorInfoBar(Core::IEditor*)));
}
}
- QmlJSTextEditor *rc = new QmlJSTextEditor(parent);
+ QmlJSEditor::QmlJSTextEditor *rc = new QmlJSEditor::QmlJSTextEditor(parent);
QmlJSEditorPlugin::instance()->initializeEditor(rc);
return rc->editableInterface();
}
diff --git a/src/plugins/qmljseditor/qmljseditorplugin.cpp b/src/plugins/qmljseditor/qmljseditorplugin.cpp
index 3c8c101a4c..fdc5c6dd5b 100644
--- a/src/plugins/qmljseditor/qmljseditorplugin.cpp
+++ b/src/plugins/qmljseditor/qmljseditorplugin.cpp
@@ -38,16 +38,19 @@
#include "qmljseditorfactory.h"
#include "qmljscodecompletion.h"
#include "qmljshoverhandler.h"
-#include "qmljsmodelmanager.h"
#include "qmlfilewizard.h"
+#include "jsfilewizard.h"
#include "qmljsoutline.h"
#include "qmljspreviewrunner.h"
#include "qmljsquickfix.h"
-#include "qmljs/qmljsicons.h"
+#include "qmljssnippetprovider.h"
#include "qmltaskmanager.h"
#include "quicktoolbar.h"
#include "quicktoolbarsettingspage.h"
+#include <qmljs/qmljsicons.h>
+#include <qmljs/qmljsmodelmanagerinterface.h>
+
#include <qmldesigner/qmldesignerconstants.h>
#include <coreplugin/icore.h>
@@ -129,21 +132,29 @@ bool QmlJSEditorPlugin::initialize(const QStringList & /*arguments*/, QString *e
if (!core->mimeDatabase()->addMimeTypes(QLatin1String(":/qmljseditor/QmlJSEditor.mimetypes.xml"), error_message))
return false;
- m_modelManager = new ModelManager(this);
- addAutoReleasedObject(m_modelManager);
+ m_modelManager = QmlJS::ModelManagerInterface::instance();
+ addAutoReleasedObject(new QmlJSSnippetProvider);
Core::Context context(QmlJSEditor::Constants::C_QMLJSEDITOR_ID);
m_editor = new QmlJSEditorFactory(this);
addObject(m_editor);
- Core::BaseFileWizardParameters wizardParameters(Core::IWizard::FileWizard);
- wizardParameters.setCategory(QLatin1String(Constants::WIZARD_CATEGORY_QML));
- wizardParameters.setDisplayCategory(QCoreApplication::translate("QmlJsEditor", Constants::WIZARD_TR_CATEGORY_QML));
- wizardParameters.setDescription(tr("Creates a QML file."));
- wizardParameters.setDisplayName(tr("QML File"));
- wizardParameters.setId(QLatin1String("Q.Qml"));
- addAutoReleasedObject(new QmlFileWizard(wizardParameters, core));
+ Core::BaseFileWizardParameters qmlWizardParameters(Core::IWizard::FileWizard);
+ qmlWizardParameters.setCategory(QLatin1String(Constants::WIZARD_CATEGORY_QML));
+ qmlWizardParameters.setDisplayCategory(QCoreApplication::translate("QmlJsEditor", Constants::WIZARD_TR_CATEGORY_QML));
+ qmlWizardParameters.setDescription(tr("Creates a QML file."));
+ qmlWizardParameters.setDisplayName(tr("QML File"));
+ qmlWizardParameters.setId(QLatin1String("Q.Qml"));
+ addAutoReleasedObject(new QmlFileWizard(qmlWizardParameters, core));
+
+ Core::BaseFileWizardParameters jsWizardParameters(Core::IWizard::FileWizard);
+ jsWizardParameters.setCategory(QLatin1String(Constants::WIZARD_CATEGORY_QML));
+ jsWizardParameters.setDisplayCategory(QCoreApplication::translate("QmlJsEditor", Constants::WIZARD_TR_CATEGORY_QML));
+ jsWizardParameters.setDescription(tr("Creates a JavaScript file."));
+ jsWizardParameters.setDisplayName(tr("JS File"));
+ jsWizardParameters.setId(QLatin1String("Z.Js"));
+ addAutoReleasedObject(new JsFileWizard(jsWizardParameters, core));
m_actionHandler = new TextEditor::TextEditorActionHandler(QmlJSEditor::Constants::C_QMLJSEDITOR_ID,
TextEditor::TextEditorActionHandler::Format
@@ -154,10 +165,10 @@ bool QmlJSEditorPlugin::initialize(const QStringList & /*arguments*/, QString *e
Core::ActionManager *am = core->actionManager();
Core::ActionContainer *contextMenu = am->createMenu(QmlJSEditor::Constants::M_CONTEXT);
Core::ActionContainer *qmlToolsMenu = am->createMenu(Core::Id(Constants::M_TOOLS_QML));
+ qmlToolsMenu->setOnAllDisabledBehavior(Core::ActionContainer::Hide);
QMenu *menu = qmlToolsMenu->menu();
//: QML sub-menu in the Tools menu
menu->setTitle(tr("QML"));
- menu->setEnabled(true);
am->actionContainer(Core::Constants::M_TOOLS)->addMenu(qmlToolsMenu);
Core::Command *cmd;
@@ -234,6 +245,8 @@ bool QmlJSEditorPlugin::initialize(const QStringList & /*arguments*/, QString *e
addAutoReleasedObject(new QuickToolBar);
addAutoReleasedObject(new Internal::QuickToolBarSettingsPage);
+ connect(core->editorManager(), SIGNAL(currentEditorChanged(Core::IEditor*)), SLOT(currentEditorChanged(Core::IEditor*)));
+
return true;
}
@@ -251,7 +264,7 @@ ExtensionSystem::IPlugin::ShutdownFlag QmlJSEditorPlugin::aboutToShutdown()
return IPlugin::aboutToShutdown();
}
-void QmlJSEditorPlugin::initializeEditor(QmlJSEditor::Internal::QmlJSTextEditor *editor)
+void QmlJSEditorPlugin::initializeEditor(QmlJSEditor::QmlJSTextEditor *editor)
{
QTC_ASSERT(m_instance, /**/);
@@ -261,7 +274,7 @@ void QmlJSEditorPlugin::initializeEditor(QmlJSEditor::Internal::QmlJSTextEditor
// auto completion
connect(editor, SIGNAL(requestAutoCompletion(TextEditor::ITextEditable*, bool)),
- TextEditor::Internal::CompletionSupport::instance(), SLOT(autoComplete(TextEditor::ITextEditable*, bool)));
+ TextEditor::CompletionSupport::instance(), SLOT(autoComplete(TextEditor::ITextEditable*, bool)));
// quick fix
connect(editor, SIGNAL(requestQuickFix(TextEditor::ITextEditable*)),
@@ -327,10 +340,20 @@ void QmlJSEditorPlugin::quickFixNow()
// ### FIXME: m_quickFixTimer->start(QUICKFIX_INTERVAL);
m_quickFixTimer->stop();
} else {
- TextEditor::Internal::CompletionSupport::instance()->quickFix(m_currentTextEditable);
+ TextEditor::CompletionSupport::instance()->quickFix(m_currentTextEditable);
}
}
}
}
+void QmlJSEditorPlugin::currentEditorChanged(Core::IEditor *editor)
+{
+ if (! editor)
+ return;
+
+ else if (QmlJSTextEditor *textEditor = qobject_cast<QmlJSTextEditor *>(editor->widget())) {
+ textEditor->forceSemanticRehighlight();
+ }
+}
+
Q_EXPORT_PLUGIN(QmlJSEditorPlugin)
diff --git a/src/plugins/qmljseditor/qmljseditorplugin.h b/src/plugins/qmljseditor/qmljseditorplugin.h
index 2650090a78..176214a622 100644
--- a/src/plugins/qmljseditor/qmljseditorplugin.h
+++ b/src/plugins/qmljseditor/qmljseditorplugin.h
@@ -49,6 +49,7 @@ namespace Core {
class Command;
class ActionContainer;
class ActionManager;
+class IEditor;
}
namespace TextEditor {
@@ -62,11 +63,11 @@ namespace QmlJS {
namespace QmlJSEditor {
class QmlFileWizard;
+class QmlJSTextEditor;
namespace Internal {
class QmlJSEditorFactory;
-class QmlJSTextEditor;
class QmlJSPreviewRunner;
class QmlJSQuickFixCollector;
class QmlTaskManager;
@@ -89,7 +90,7 @@ public:
QmlJSQuickFixCollector *quickFixCollector() const;
- void initializeEditor(QmlJSTextEditor *editor);
+ void initializeEditor(QmlJSEditor::QmlJSTextEditor *editor);
public Q_SLOTS:
void followSymbolUnderCursor();
@@ -99,6 +100,7 @@ public Q_SLOTS:
private Q_SLOTS:
void quickFix(TextEditor::ITextEditable *editable);
void quickFixNow();
+ void currentEditorChanged(Core::IEditor *editor);
private:
Core::Command *addToolAction(QAction *a, Core::ActionManager *am, Core::Context &context, const QString &name,
diff --git a/src/plugins/qmljseditor/qmljsfindreferences.cpp b/src/plugins/qmljseditor/qmljsfindreferences.cpp
index ab42e834ed..dda11a747d 100644
--- a/src/plugins/qmljseditor/qmljsfindreferences.cpp
+++ b/src/plugins/qmljseditor/qmljsfindreferences.cpp
@@ -68,21 +68,6 @@ using namespace QmlJS::Interpreter;
using namespace QmlJS::AST;
using namespace QmlJSEditor;
-static const ObjectValue *prototypeWithMember(const Context *context, const ObjectValue *object, const QString &name)
-{
- if (!object)
- return 0;
- const Value *value = object->property(name, context);
- if (!value)
- return 0;
- forever {
- const ObjectValue *prototype = object->prototype(context);
- if (!prototype || prototype->property(name, context) != value)
- return object;
- object = prototype;
- }
-}
-
namespace {
// ### These visitors could be useful in general
@@ -221,6 +206,11 @@ protected:
virtual bool visit(AST::FunctionDeclaration *node)
{
+ return visit(static_cast<FunctionExpression *>(node));
+ }
+
+ virtual bool visit(AST::FunctionExpression *node)
+ {
if (node->name && node->name->asString() == _name) {
if (checkLookup())
_usages.append(node->identifierToken);
@@ -265,7 +255,9 @@ private:
{
if (!s)
return false;
- return prototypeWithMember(_context, s, _name) == _scope;
+ const ObjectValue *definingObject;
+ s->lookupMember(_name, _context, &definingObject);
+ return definingObject == _scope;
}
bool checkQmlScope()
@@ -346,6 +338,11 @@ protected:
virtual bool visit(AST::FunctionDeclaration *node)
{
+ return visit(static_cast<FunctionExpression *>(node));
+ }
+
+ virtual bool visit(AST::FunctionExpression *node)
+ {
Node::accept(node->formals, this);
_result.append(node);
Node::accept(node->body, this);
@@ -439,10 +436,13 @@ protected:
return true;
}
- // ### Misses function declaration, var declaration
-
virtual bool visit(FunctionDeclaration *node)
{
+ return visit(static_cast<FunctionExpression *>(node));
+ }
+
+ virtual bool visit(FunctionExpression *node)
+ {
if (containsOffset(node->identifierToken)) {
_result.second = node->name->asString();
return false;
@@ -610,7 +610,7 @@ static void find_helper(QFutureInterface<FindReferences::Usage> &future,
}
if (!scope)
return;
- scope = prototypeWithMember(&context, scope, name);
+ scope->lookupMember(name, &context, &scope);
if (!scope)
return;
diff --git a/src/plugins/qmljseditor/qmljshighlighter.cpp b/src/plugins/qmljseditor/qmljshighlighter.cpp
index b6f022209f..b4dcca3a05 100644
--- a/src/plugins/qmljseditor/qmljshighlighter.cpp
+++ b/src/plugins/qmljseditor/qmljshighlighter.cpp
@@ -142,9 +142,12 @@ void Highlighter::highlightBlock(const QString &text)
break;
case Token::Identifier: {
+ if (!m_qmlEnabled)
+ break;
+
const QStringRef spell = text.midRef(token.offset, token.length);
- if (m_qmlEnabled && maybeQmlKeyword(spell)) {
+ if (maybeQmlKeyword(spell)) {
// check the previous token
if (index == 0 || tokens.at(index - 1).isNot(Token::Dot)) {
if (index + 1 == tokens.size() || tokens.at(index + 1).isNot(Token::Colon)) {
@@ -152,7 +155,7 @@ void Highlighter::highlightBlock(const QString &text)
break;
}
}
- } else if (m_qmlEnabled && index > 0 && maybeQmlBuiltinType(spell)) {
+ } else if (index > 0 && maybeQmlBuiltinType(spell)) {
const Token &previousToken = tokens.at(index - 1);
if (previousToken.is(Token::Identifier) && text.at(previousToken.offset) == QLatin1Char('p')
&& text.midRef(previousToken.offset, previousToken.length) == QLatin1String("property")) {
@@ -161,9 +164,10 @@ void Highlighter::highlightBlock(const QString &text)
}
}
- if (index + 1 < tokens.size()) {
- const Token &nextToken = tokens.at(index + 1);
+ if (!spell.isEmpty() && spell.at(0).isUpper())
+ setFormat(token.offset, token.length, m_formats[TypeFormat]);
+ if (index + 1 < tokens.size()) {
bool maybeBinding = (index == 0 || checkStartOfBinding(tokens.at(index - 1)));
bool maybeOnBinding = false;
if (index > 0) {
@@ -174,11 +178,7 @@ void Highlighter::highlightBlock(const QString &text)
}
}
- if (text.at(token.offset).isUpper()
- && (nextToken.is(Token::LeftBrace)
- || text.midRef(nextToken.offset, nextToken.length) == QLatin1String("on"))) {
- setFormat(token.offset, token.length, m_formats[TypeFormat]);
- } else if (maybeBinding || maybeOnBinding) {
+ if (maybeBinding || maybeOnBinding) {
Token::Kind expectedTerminator = Token::Colon;
if (maybeOnBinding)
expectedTerminator = Token::LeftBrace;
@@ -196,7 +196,14 @@ void Highlighter::highlightBlock(const QString &text)
// it's a binding.
for (int i = start; i <= index; ++i) {
const Token &tok = tokens.at(i);
- setFormat(tok.offset, tok.length, m_formats[FieldFormat]);
+ if (tok.kind == Token::Dot)
+ continue;
+ const QStringRef tokSpell = text.midRef(tok.offset, tok.length);
+ if (!tokSpell.isEmpty() && tokSpell.at(0).isUpper()) {
+ setFormat(tok.offset, tok.length, m_formats[TypeFormat]);
+ } else {
+ setFormat(tok.offset, tok.length, m_formats[FieldFormat]);
+ }
}
break;
} else {
diff --git a/src/plugins/qmljseditor/qmljshoverhandler.cpp b/src/plugins/qmljseditor/qmljshoverhandler.cpp
index 3bd0b774b3..736f2a38fd 100644
--- a/src/plugins/qmljseditor/qmljshoverhandler.cpp
+++ b/src/plugins/qmljseditor/qmljshoverhandler.cpp
@@ -32,6 +32,7 @@
**************************************************************************/
#include "qmljseditor.h"
+#include "qmljseditoreditable.h"
#include "qmlexpressionundercursor.h"
#include "qmljshoverhandler.h"
@@ -108,33 +109,36 @@ void HoverHandler::identifyMatch(TextEditor::ITextEditor *editor, int pos)
if (!m_modelManager)
return;
- QmlJSTextEditor *qmlEditor = qobject_cast<QmlJSTextEditor *>(editor->widget());
+ QmlJSEditor::QmlJSTextEditor *qmlEditor = qobject_cast<QmlJSEditor::QmlJSTextEditor *>(editor->widget());
if (!qmlEditor)
return;
- if (!matchDiagnosticMessage(qmlEditor, pos)) {
- const SemanticInfo &semanticInfo = qmlEditor->semanticInfo();
- if (! semanticInfo.isValid() || semanticInfo.revision() != qmlEditor->editorRevision())
- return;
+ if (matchDiagnosticMessage(qmlEditor, pos))
+ return;
+
+ const QmlJSEditor::SemanticInfo &semanticInfo = qmlEditor->semanticInfo();
+ if (! semanticInfo.isValid() || semanticInfo.revision() != qmlEditor->editorRevision())
+ return;
- QList<AST::Node *> astPath = semanticInfo.astPath(pos);
- if (astPath.isEmpty())
- return;
+ QList<AST::Node *> astPath = semanticInfo.astPath(pos);
+ if (astPath.isEmpty())
+ return;
- const Document::Ptr qmlDocument = semanticInfo.document;
- LookupContext::Ptr lookupContext = semanticInfo.lookupContext(astPath);
+ const Document::Ptr qmlDocument = semanticInfo.document;
+ LookupContext::Ptr lookupContext = semanticInfo.lookupContext(astPath);
- if (!matchColorItem(lookupContext, qmlDocument, astPath, pos)) {
- handleOrdinaryMatch(lookupContext, semanticInfo.nodeUnderCursor(pos));
- const QString &helpId = qmlHelpId(toolTip());
- if (!helpId.isEmpty())
- setLastHelpItemIdentified(TextEditor::HelpItem(helpId, toolTip(),
- TextEditor::HelpItem::QML));
- }
- }
+ if (matchColorItem(lookupContext, qmlDocument, astPath, pos))
+ return;
+
+ AST::Node *node = semanticInfo.nodeUnderCursor(pos);
+ handleOrdinaryMatch(lookupContext, node);
+
+ TextEditor::HelpItem helpItem = qmlHelpItem(lookupContext, node);
+ if (!helpItem.helpId().isEmpty())
+ setLastHelpItemIdentified(helpItem);
}
-bool HoverHandler::matchDiagnosticMessage(QmlJSTextEditor *qmlEditor, int pos)
+bool HoverHandler::matchDiagnosticMessage(QmlJSEditor::QmlJSTextEditor *qmlEditor, int pos)
{
foreach (const QTextEdit::ExtraSelection &sel,
qmlEditor->extraSelections(TextEditor::BaseTextEditor::CodeWarningsSelection)) {
@@ -240,18 +244,16 @@ void HoverHandler::prettyPrintTooltip(const QmlJS::Interpreter::Value *value,
return;
if (const Interpreter::ObjectValue *objectValue = value->asObjectValue()) {
- bool found = false;
- do {
- const QString className = objectValue->className();
+ Interpreter::PrototypeIterator iter(objectValue, context);
+ while (iter.hasNext()) {
+ const Interpreter::ObjectValue *prototype = iter.next();
+ const QString className = prototype->className();
if (! className.isEmpty()) {
- found = !qmlHelpId(className).isEmpty();
- if (toolTip().isEmpty() || found)
- setToolTip(className);
+ setToolTip(className);
+ break;
}
-
- objectValue = objectValue->prototype(context);
- } while (objectValue && !found);
+ }
} else if (const Interpreter::QmlEnumValue *enumValue =
dynamic_cast<const Interpreter::QmlEnumValue *>(value)) {
setToolTip(enumValue->name());
@@ -264,10 +266,74 @@ void HoverHandler::prettyPrintTooltip(const QmlJS::Interpreter::Value *value,
}
}
-QString HoverHandler::qmlHelpId(const QString &itemName) const
+// if node refers to a property, its name and defining object are returned - otherwise zero
+static const Interpreter::ObjectValue *isMember(const LookupContext::Ptr &lookupContext,
+ AST::Node *node, QString *name)
{
- QString helpId(QLatin1String("QML.") + itemName);
- if (!Core::HelpManager::instance()->linksForIdentifier(helpId).isEmpty())
- return helpId;
- return QString();
+ const Interpreter::ObjectValue *owningObject = 0;
+ if (AST::IdentifierExpression *identExp = AST::cast<AST::IdentifierExpression *>(node)) {
+ if (!identExp->name)
+ return 0;
+ *name = identExp->name->asString();
+ lookupContext->context()->lookup(*name, &owningObject);
+ } else if (AST::FieldMemberExpression *fme = AST::cast<AST::FieldMemberExpression *>(node)) {
+ if (!fme->base || !fme->name)
+ return 0;
+ *name = fme->name->asString();
+ const Interpreter::Value *base = lookupContext->evaluate(fme->base);
+ if (!base)
+ return 0;
+ owningObject = base->asObjectValue();
+ if (owningObject)
+ owningObject->lookupMember(*name, lookupContext->context(), &owningObject);
+ } else if (AST::UiQualifiedId *qid = AST::cast<AST::UiQualifiedId *>(node)) {
+ if (!qid->name)
+ return 0;
+ *name = qid->name->asString();
+ const Interpreter::Value *value = lookupContext->context()->lookup(*name, &owningObject);
+ for (AST::UiQualifiedId *it = qid->next; it; it = it->next) {
+ if (!value)
+ return 0;
+ const Interpreter::ObjectValue *next = value->asObjectValue();
+ if (!next || !it->name)
+ return 0;
+ *name = it->name->asString();
+ value = next->lookupMember(*name, lookupContext->context(), &owningObject);
+ }
+ }
+ return owningObject;
+}
+
+TextEditor::HelpItem HoverHandler::qmlHelpItem(const LookupContext::Ptr &lookupContext,
+ AST::Node *node) const
+{
+ QString name;
+ if (const Interpreter::ObjectValue *scope = isMember(lookupContext, node, &name)) {
+ // maybe it's a type?
+ if (!name.isEmpty() && name.at(0).isUpper()) {
+ const QString maybeHelpId(QLatin1String("QML.") + name);
+ if (!Core::HelpManager::instance()->linksForIdentifier(maybeHelpId).isEmpty())
+ return TextEditor::HelpItem(maybeHelpId, name, TextEditor::HelpItem::QmlComponent);
+ }
+
+ // otherwise, it's probably a property
+ const Interpreter::ObjectValue *lastScope;
+ scope->lookupMember(name, lookupContext->context(), &lastScope);
+ Interpreter::PrototypeIterator iter(scope, lookupContext->context());
+ while (iter.hasNext()) {
+ const Interpreter::ObjectValue *cur = iter.next();
+
+ const QString className = cur->className();
+ if (!className.isEmpty()) {
+ const QString maybeHelpId(className + QLatin1String("::") + name);
+ if (!Core::HelpManager::instance()->linksForIdentifier(maybeHelpId).isEmpty())
+ return TextEditor::HelpItem(maybeHelpId, name, TextEditor::HelpItem::QmlProperty);
+ }
+
+ if (cur == lastScope)
+ break;
+ }
+ }
+
+ return TextEditor::HelpItem();
}
diff --git a/src/plugins/qmljseditor/qmljshoverhandler.h b/src/plugins/qmljseditor/qmljshoverhandler.h
index e54f9a2daa..e35d8e3f64 100644
--- a/src/plugins/qmljseditor/qmljshoverhandler.h
+++ b/src/plugins/qmljseditor/qmljshoverhandler.h
@@ -53,10 +53,11 @@ class ITextEditor;
}
namespace QmlJSEditor {
+class QmlJSTextEditor;
+
namespace Internal {
class SemanticInfo;
-class QmlJSTextEditor;
class HoverHandler : public TextEditor::BaseHoverHandler
{
@@ -71,7 +72,7 @@ private:
virtual void identifyMatch(TextEditor::ITextEditor *editor, int pos);
virtual void operateTooltip(TextEditor::ITextEditor *editor, const QPoint &point);
- bool matchDiagnosticMessage(QmlJSTextEditor *qmlEditor, int pos);
+ bool matchDiagnosticMessage(QmlJSEditor::QmlJSTextEditor *qmlEditor, int pos);
bool matchColorItem(const QmlJS::LookupContext::Ptr &lookupContext,
const QmlJS::Document::Ptr &qmlDocument,
const QList<QmlJS::AST::Node *> &astPath,
@@ -82,7 +83,8 @@ private:
void prettyPrintTooltip(const QmlJS::Interpreter::Value *value,
const QmlJS::Interpreter::Context *context);
- QString qmlHelpId(const QString &itemName) const;
+ TextEditor::HelpItem qmlHelpItem(const QmlJS::LookupContext::Ptr &lookupContext,
+ QmlJS::AST::Node *node) const;
QmlJS::ModelManagerInterface *m_modelManager;
QColor m_colorTip;
diff --git a/src/plugins/qmljseditor/qmljsindenter.cpp b/src/plugins/qmljseditor/qmljsindenter.cpp
new file mode 100644
index 0000000000..ac288f236d
--- /dev/null
+++ b/src/plugins/qmljseditor/qmljsindenter.cpp
@@ -0,0 +1,74 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "qmljsindenter.h"
+
+#include <qmljstools/qmljsqtstylecodeformatter.h>
+#include <texteditor/basetexteditor.h>
+#include <texteditor/tabsettings.h>
+
+#include <QtCore/QChar>
+#include <QtGui/QTextDocument>
+#include <QtGui/QTextBlock>
+#include <QtGui/QTextCursor>
+
+using namespace QmlJSEditor;
+using namespace Internal;
+
+Indenter::Indenter()
+{}
+
+Indenter::~Indenter()
+{}
+
+bool Indenter::isElectricCharacter(const QChar &ch) const
+{
+ if (ch == QLatin1Char('}')
+ || ch == QLatin1Char(']')
+ || ch == QLatin1Char(':'))
+ return true;
+ return false;
+}
+
+void Indenter::indentBlock(QTextDocument *doc,
+ const QTextBlock &block,
+ const QChar &typedChar,
+ TextEditor::BaseTextEditor *editor)
+{
+ Q_UNUSED(doc)
+ Q_UNUSED(typedChar)
+ Q_UNUSED(editor)
+
+ const TextEditor::TabSettings &ts = editor->tabSettings();
+ QmlJSTools::QtStyleCodeFormatter codeFormatter(ts);
+
+ codeFormatter.updateStateUntil(block);
+ const int depth = codeFormatter.indentFor(block);
+ ts.indentLine(block, depth);
+}
diff --git a/src/plugins/qmljseditor/qmljsindenter.h b/src/plugins/qmljseditor/qmljsindenter.h
new file mode 100644
index 0000000000..cf23112b73
--- /dev/null
+++ b/src/plugins/qmljseditor/qmljsindenter.h
@@ -0,0 +1,54 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 QMLJSINDENTER_H
+#define QMLJSINDENTER_H
+
+#include <texteditor/indenter.h>
+
+namespace QmlJSEditor {
+namespace Internal {
+
+class Indenter : public TextEditor::Indenter
+{
+public:
+ Indenter();
+ virtual ~Indenter();
+
+ virtual bool isElectricCharacter(const QChar &ch) const;
+ virtual void indentBlock(QTextDocument *doc,
+ const QTextBlock &block,
+ const QChar &typedChar,
+ TextEditor::BaseTextEditor *editor);
+};
+
+} // Internal
+} // QmlJSEditor
+
+#endif // QMLJSINDENTER_H
diff --git a/src/plugins/qmljseditor/qmljsmodelmanager.cpp b/src/plugins/qmljseditor/qmljsmodelmanager.cpp
deleted file mode 100644
index b78adb3a3f..0000000000
--- a/src/plugins/qmljseditor/qmljsmodelmanager.cpp
+++ /dev/null
@@ -1,575 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#include "qmljseditorconstants.h"
-#include "qmljsmodelmanager.h"
-#include "qmljseditor.h"
-
-#include <coreplugin/icore.h>
-#include <coreplugin/editormanager/editormanager.h>
-#include <coreplugin/progressmanager/progressmanager.h>
-#include <coreplugin/messagemanager.h>
-#include <coreplugin/mimedatabase.h>
-#include <qmljs/qmljsinterpreter.h>
-#include <qmljs/qmljsbind.h>
-#include <qmljs/parser/qmldirparser_p.h>
-#include <texteditor/itexteditor.h>
-#include <projectexplorer/project.h>
-#include <projectexplorer/projectexplorer.h>
-
-#include <QDir>
-#include <QFile>
-#include <QFileInfo>
-#include <QLibraryInfo>
-#include <QtConcurrentRun>
-#include <qtconcurrent/runextensions.h>
-#include <QTextStream>
-#include <QCoreApplication>
-
-#include <QDebug>
-
-using namespace QmlJS;
-using namespace QmlJSEditor;
-using namespace QmlJSEditor::Internal;
-
-static QStringList environmentImportPaths();
-
-ModelManager::ModelManager(QObject *parent):
- ModelManagerInterface(parent),
- m_core(Core::ICore::instance())
-{
- m_synchronizer.setCancelOnWait(true);
-
- qRegisterMetaType<QmlJS::Document::Ptr>("QmlJS::Document::Ptr");
- qRegisterMetaType<QmlJS::LibraryInfo>("QmlJS::LibraryInfo");
-
- loadQmlTypeDescriptions();
-
- m_defaultImportPaths << environmentImportPaths();
- m_defaultImportPaths << QLibraryInfo::location(QLibraryInfo::ImportsPath);
-}
-
-void ModelManager::loadQmlTypeDescriptions()
-{
- loadQmlTypeDescriptions(Core::ICore::instance()->resourcePath());
- loadQmlTypeDescriptions(Core::ICore::instance()->userResourcePath());
-}
-
-void ModelManager::loadQmlTypeDescriptions(const QString &resourcePath)
-{
- const QDir typeFileDir(resourcePath + QLatin1String("/qml-type-descriptions"));
- const QStringList xmlExtensions = QStringList() << QLatin1String("*.xml");
- const QFileInfoList xmlFiles = typeFileDir.entryInfoList(xmlExtensions,
- QDir::Files,
- QDir::Name);
-
- const QStringList errors = Interpreter::CppQmlTypesLoader::load(xmlFiles);
- foreach (const QString &error, errors)
- qWarning() << qPrintable(error);
-
- // disabled for now: Prefer the xml file until the type dumping functionality
- // has been moved into Qt.
- // loads the builtin types
- //loadQmlPluginTypes(QString());
-}
-
-ModelManagerInterface::WorkingCopy ModelManager::workingCopy() const
-{
- WorkingCopy workingCopy;
- Core::EditorManager *editorManager = m_core->editorManager();
-
- foreach (Core::IEditor *editor, editorManager->openedEditors()) {
- const QString key = editor->file()->fileName();
-
- if (TextEditor::ITextEditor *textEditor = qobject_cast<TextEditor::ITextEditor*>(editor)) {
- if (QmlJSTextEditor *ed = qobject_cast<QmlJSTextEditor *>(textEditor->widget())) {
- workingCopy.insert(key, ed->toPlainText(), ed->document()->revision());
- }
- }
- }
-
- return workingCopy;
-}
-
-Snapshot ModelManager::snapshot() const
-{
- QMutexLocker locker(&m_mutex);
-
- return _snapshot;
-}
-
-void ModelManager::updateSourceFiles(const QStringList &files,
- bool emitDocumentOnDiskChanged)
-{
- refreshSourceFiles(files, emitDocumentOnDiskChanged);
-}
-
-QFuture<void> ModelManager::refreshSourceFiles(const QStringList &sourceFiles,
- bool emitDocumentOnDiskChanged)
-{
- if (sourceFiles.isEmpty()) {
- return QFuture<void>();
- }
-
- QFuture<void> result = QtConcurrent::run(&ModelManager::parse,
- workingCopy(), sourceFiles,
- this,
- emitDocumentOnDiskChanged);
-
- if (m_synchronizer.futures().size() > 10) {
- QList<QFuture<void> > futures = m_synchronizer.futures();
-
- m_synchronizer.clearFutures();
-
- foreach (QFuture<void> future, futures) {
- if (! (future.isFinished() || future.isCanceled()))
- m_synchronizer.addFuture(future);
- }
- }
-
- m_synchronizer.addFuture(result);
-
- if (sourceFiles.count() > 1) {
- m_core->progressManager()->addTask(result, tr("Indexing"),
- QmlJSEditor::Constants::TASK_INDEX);
- }
-
- return result;
-}
-
-void ModelManager::fileChangedOnDisk(const QString &path)
-{
- QtConcurrent::run(&ModelManager::parse,
- workingCopy(), QStringList() << path,
- this, true);
-}
-
-void ModelManager::removeFiles(const QStringList &files)
-{
- emit aboutToRemoveFiles(files);
-
- QMutexLocker locker(&m_mutex);
-
- foreach (const QString &file, files)
- _snapshot.remove(file);
-}
-
-QList<ModelManager::ProjectInfo> ModelManager::projectInfos() const
-{
- QMutexLocker locker(&m_mutex);
-
- return m_projects.values();
-}
-
-ModelManager::ProjectInfo ModelManager::projectInfo(ProjectExplorer::Project *project) const
-{
- QMutexLocker locker(&m_mutex);
-
- return m_projects.value(project, ProjectInfo(project));
-}
-
-void ModelManager::updateProjectInfo(const ProjectInfo &pinfo)
-{
- if (! pinfo.isValid())
- return;
-
- {
- QMutexLocker locker(&m_mutex);
- m_projects.insert(pinfo.project, pinfo);
- }
-
- updateImportPaths();
-}
-
-void ModelManager::emitDocumentChangedOnDisk(Document::Ptr doc)
-{ emit documentChangedOnDisk(doc); }
-
-void ModelManager::updateDocument(Document::Ptr doc)
-{
- {
- QMutexLocker locker(&m_mutex);
- _snapshot.insert(doc);
- }
- emit documentUpdated(doc);
-}
-
-void ModelManager::updateLibraryInfo(const QString &path, const LibraryInfo &info)
-{
- {
- QMutexLocker locker(&m_mutex);
- _snapshot.insertLibraryInfo(path, info);
- }
- emit libraryInfoUpdated(path, info);
-}
-
-static QStringList qmlFilesInDirectory(const QString &path)
-{
- // ### It would suffice to build pattern once. This function needs to be thread-safe.
- Core::MimeDatabase *db = Core::ICore::instance()->mimeDatabase();
- Core::MimeType jsSourceTy = db->findByType(QmlJSEditor::Constants::JS_MIMETYPE);
- Core::MimeType qmlSourceTy = db->findByType(QmlJSEditor::Constants::QML_MIMETYPE);
-
- QStringList pattern;
- foreach (const Core::MimeGlobPattern &glob, jsSourceTy.globPatterns())
- pattern << glob.regExp().pattern();
- foreach (const Core::MimeGlobPattern &glob, qmlSourceTy.globPatterns())
- pattern << glob.regExp().pattern();
-
- QStringList files;
-
- const QDir dir(path);
- foreach (const QFileInfo &fi, dir.entryInfoList(pattern, QDir::Files))
- files += fi.absoluteFilePath();
-
- return files;
-}
-
-static void findNewImplicitImports(const Document::Ptr &doc, const Snapshot &snapshot,
- QStringList *importedFiles, QSet<QString> *scannedPaths)
-{
- // scan files that could be implicitly imported
- // it's important we also do this for JS files, otherwise the isEmpty check will fail
- if (snapshot.documentsInDirectory(doc->path()).isEmpty()) {
- if (! scannedPaths->contains(doc->path())) {
- *importedFiles += qmlFilesInDirectory(doc->path());
- scannedPaths->insert(doc->path());
- }
- }
-}
-
-static void findNewFileImports(const Document::Ptr &doc, const Snapshot &snapshot,
- QStringList *importedFiles, QSet<QString> *scannedPaths)
-{
- // scan files and directories that are explicitly imported
- foreach (const Interpreter::ImportInfo &import, doc->bind()->imports()) {
- const QString &importName = import.name();
- if (import.type() == Interpreter::ImportInfo::FileImport) {
- if (! snapshot.document(importName))
- *importedFiles += importName;
- } else if (import.type() == Interpreter::ImportInfo::DirectoryImport) {
- if (snapshot.documentsInDirectory(importName).isEmpty()) {
- if (! scannedPaths->contains(importName)) {
- *importedFiles += qmlFilesInDirectory(importName);
- scannedPaths->insert(importName);
- }
- }
- }
- }
-}
-
-static void findNewLibraryImports(const Document::Ptr &doc, const Snapshot &snapshot,
- ModelManager *modelManager,
- QStringList *importedFiles, QSet<QString> *scannedPaths)
-{
- // scan library imports
- const QStringList importPaths = modelManager->importPaths();
- foreach (const Interpreter::ImportInfo &import, doc->bind()->imports()) {
- if (import.type() != Interpreter::ImportInfo::LibraryImport)
- continue;
- foreach (const QString &importPath, importPaths) {
- QDir dir(importPath);
- dir.cd(import.name());
- const QString targetPath = dir.absolutePath();
-
- // if we know there is a library, done
- if (snapshot.libraryInfo(targetPath).isValid())
- break;
-
- // if there is a qmldir file, we found a new library!
- if (dir.exists("qmldir")) {
- QFile qmldirFile(dir.filePath("qmldir"));
- qmldirFile.open(QFile::ReadOnly);
- QString qmldirData = QString::fromUtf8(qmldirFile.readAll());
-
- QmlDirParser qmldirParser;
- qmldirParser.setSource(qmldirData);
- qmldirParser.parse();
-
- modelManager->updateLibraryInfo(QFileInfo(qmldirFile).absolutePath(),
- LibraryInfo(qmldirParser));
-
- // scan the qml files in the library
- foreach (const QmlDirParser::Component &component, qmldirParser.components()) {
- if (! component.fileName.isEmpty()) {
- QFileInfo componentFileInfo(dir.filePath(component.fileName));
- const QString path = componentFileInfo.absolutePath();
- if (! scannedPaths->contains(path)) {
- *importedFiles += qmlFilesInDirectory(path);
- scannedPaths->insert(path);
- }
- }
- }
- }
- }
- }
-}
-
-void ModelManager::parse(QFutureInterface<void> &future,
- WorkingCopy workingCopy,
- QStringList files,
- ModelManager *modelManager,
- bool emitDocChangedOnDisk)
-{
- Core::MimeDatabase *db = Core::ICore::instance()->mimeDatabase();
- Core::MimeType jsSourceTy = db->findByType(QLatin1String("application/javascript"));
- Core::MimeType qmlSourceTy = db->findByType(QLatin1String("application/x-qml"));
-
- int progressRange = files.size();
- future.setProgressRange(0, progressRange);
-
- Snapshot snapshot = modelManager->_snapshot;
-
- // paths we have scanned for files and added to the files list
- QSet<QString> scannedPaths;
-
- for (int i = 0; i < files.size(); ++i) {
- future.setProgressValue(qreal(i) / files.size() * progressRange);
-
- const QString fileName = files.at(i);
-
- const QFileInfo fileInfo(fileName);
- Core::MimeType fileMimeTy = db->findByFile(fileInfo);
-
- bool isQmlFile = true;
-
- if (matchesMimeType(fileMimeTy, jsSourceTy))
- isQmlFile = false;
-
- else if (! matchesMimeType(fileMimeTy, qmlSourceTy))
- continue; // skip it. it's not a QML or a JS file.
-
- QString contents;
- int documentRevision = 0;
-
- if (workingCopy.contains(fileName)) {
- QPair<QString, int> entry = workingCopy.get(fileName);
- contents = entry.first;
- documentRevision = entry.second;
- } else {
- QFile inFile(fileName);
-
- if (inFile.open(QIODevice::ReadOnly)) {
- QTextStream ins(&inFile);
- contents = ins.readAll();
- inFile.close();
- }
- }
-
- Document::Ptr doc = Document::create(fileName);
- doc->setEditorRevision(documentRevision);
- doc->setSource(contents);
- doc->parse();
-
- // get list of referenced files not yet in snapshot or in directories already scanned
- QStringList importedFiles;
- findNewImplicitImports(doc, snapshot, &importedFiles, &scannedPaths);
- findNewFileImports(doc, snapshot, &importedFiles, &scannedPaths);
- findNewLibraryImports(doc, snapshot, modelManager, &importedFiles, &scannedPaths);
-
- // add new files to parse list
- foreach (const QString &file, importedFiles) {
- if (! files.contains(file))
- files.append(file);
- }
-
- modelManager->updateDocument(doc);
- if (emitDocChangedOnDisk)
- modelManager->emitDocumentChangedOnDisk(doc);
- }
-
- future.setProgressValue(progressRange);
-}
-
-// Check whether fileMimeType is the same or extends knownMimeType
-bool ModelManager::matchesMimeType(const Core::MimeType &fileMimeType, const Core::MimeType &knownMimeType)
-{
- Core::MimeDatabase *db = Core::ICore::instance()->mimeDatabase();
-
- const QStringList knownTypeNames = QStringList(knownMimeType.type()) + knownMimeType.aliases();
-
- foreach (const QString knownTypeName, knownTypeNames)
- if (fileMimeType.matchesType(knownTypeName))
- return true;
-
- // recursion to parent types of fileMimeType
- foreach (const QString &parentMimeType, fileMimeType.subClassesOf()) {
- if (matchesMimeType(db->findByType(parentMimeType), knownMimeType))
- return true;
- }
-
- return false;
-}
-
-QStringList ModelManager::importPaths() const
-{
- return m_allImportPaths;
-}
-
-static QStringList environmentImportPaths()
-{
- QStringList paths;
-
- QByteArray envImportPath = qgetenv("QML_IMPORT_PATH");
-
-#if defined(Q_OS_WIN)
- QLatin1Char pathSep(';');
-#else
- QLatin1Char pathSep(':');
-#endif
- foreach (const QString &path, QString::fromLatin1(envImportPath).split(pathSep, QString::SkipEmptyParts)) {
- QString canonicalPath = QDir(path).canonicalPath();
- if (!canonicalPath.isEmpty() && !paths.contains(canonicalPath))
- paths.append(canonicalPath);
- }
-
- return paths;
-}
-
-void ModelManager::loadPluginTypes(const QString &libraryPath, const QString &importPath, const QString &importUri)
-{
- // make sure loading is always triggered in ModelManager's thread
- metaObject()->invokeMethod(this, "onLoadPluginTypes",
- Q_ARG(QString, libraryPath),
- Q_ARG(QString, importPath),
- Q_ARG(QString, importUri));
-}
-
-void ModelManager::onLoadPluginTypes(const QString &libraryPath, const QString &importPath, const QString &importUri)
-{
- const QString canonicalLibraryPath = QDir::cleanPath(libraryPath);
- if (m_runningQmldumps.values().contains(canonicalLibraryPath))
- return;
- if (_snapshot.libraryInfo(canonicalLibraryPath).isDumped())
- return;
-
- ProjectExplorer::Project *activeProject = ProjectExplorer::ProjectExplorerPlugin::instance()->startupProject();
- if (!activeProject)
- return;
-
- ProjectInfo info = projectInfo(activeProject);
-
- if (info.qmlDumpPath.isEmpty())
- return;
-
- QProcess *process = new QProcess(this);
- process->setEnvironment(info.qmlDumpEnvironment.toStringList());
- connect(process, SIGNAL(finished(int)), SLOT(qmlPluginTypeDumpDone(int)));
- connect(process, SIGNAL(error(QProcess::ProcessError)), SLOT(qmlPluginTypeDumpError(QProcess::ProcessError)));
- QStringList args;
- args << importPath;
- args << importUri;
- process->start(info.qmlDumpPath, args);
- m_runningQmldumps.insert(process, canonicalLibraryPath);
-}
-
-void ModelManager::updateImportPaths()
-{
- m_allImportPaths.clear();
- QMapIterator<ProjectExplorer::Project *, ProjectInfo> it(m_projects);
- while (it.hasNext()) {
- it.next();
- m_allImportPaths += it.value().importPaths;
- }
- m_allImportPaths += m_defaultImportPaths;
- m_allImportPaths.removeDuplicates();
-
- // check if any file in the snapshot imports something new in the new paths
- Snapshot snapshot = _snapshot;
- QStringList importedFiles;
- QSet<QString> scannedPaths;
- foreach (const Document::Ptr &doc, snapshot)
- findNewLibraryImports(doc, snapshot, this, &importedFiles, &scannedPaths);
-
- updateSourceFiles(importedFiles, true);
-}
-
-static QString qmldumpErrorMessage(const QString &libraryPath, const QString &error)
-{
- return ModelManager::tr("Type dump of QML plugin in %0 failed.\nErrors:\n%1\n").arg(libraryPath, error);
-}
-
-void ModelManager::qmlPluginTypeDumpDone(int exitCode)
-{
- QProcess *process = qobject_cast<QProcess *>(sender());
- if (!process)
- return;
- process->deleteLater();
-
- const QString libraryPath = m_runningQmldumps.take(process);
- LibraryInfo libraryInfo = _snapshot.libraryInfo(libraryPath);
- libraryInfo.setDumped(true);
-
- if (exitCode != 0) {
- Core::MessageManager *messageManager = Core::MessageManager::instance();
- messageManager->printToOutputPane(qmldumpErrorMessage(libraryPath, process->readAllStandardError()));
- }
-
- const QByteArray output = process->readAllStandardOutput();
- QMap<QString, Interpreter::FakeMetaObject *> newObjects;
- const QString error = Interpreter::CppQmlTypesLoader::parseQmlTypeXml(output, &newObjects);
-
- if (exitCode == 0 && error.isEmpty()) {
- // convert from QList<T *> to QList<const T *>
- QList<const Interpreter::FakeMetaObject *> objectsList;
- QMapIterator<QString, Interpreter::FakeMetaObject *> it(newObjects);
- while (it.hasNext()) {
- it.next();
- objectsList.append(it.value());
- }
- libraryInfo.setMetaObjects(objectsList);
- if (libraryPath.isEmpty())
- Interpreter::CppQmlTypesLoader::builtinObjects.append(objectsList);
- }
-
- if (!libraryPath.isEmpty())
- updateLibraryInfo(libraryPath, libraryInfo);
-}
-
-void ModelManager::qmlPluginTypeDumpError(QProcess::ProcessError)
-{
- QProcess *process = qobject_cast<QProcess *>(sender());
- if (!process)
- return;
- process->deleteLater();
-
- const QString libraryPath = m_runningQmldumps.take(process);
-
- Core::MessageManager *messageManager = Core::MessageManager::instance();
- messageManager->printToOutputPane(qmldumpErrorMessage(libraryPath, process->readAllStandardError()));
-
- if (!libraryPath.isEmpty()) {
- LibraryInfo libraryInfo = _snapshot.libraryInfo(libraryPath);
- libraryInfo.setDumped(true);
- updateLibraryInfo(libraryPath, libraryInfo);
- }
-}
diff --git a/src/plugins/qmljseditor/qmljsmodelmanager.h b/src/plugins/qmljseditor/qmljsmodelmanager.h
deleted file mode 100644
index 9a7846d28c..0000000000
--- a/src/plugins/qmljseditor/qmljsmodelmanager.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#ifndef QMLJSMODELMANAGER_H
-#define QMLJSMODELMANAGER_H
-
-#include <qmljs/qmljsmodelmanagerinterface.h>
-#include <qmljs/qmljsdocument.h>
-
-#include <QFuture>
-#include <QFutureSynchronizer>
-#include <QMutex>
-#include <QProcess>
-
-namespace Core {
-class ICore;
-class MimeType;
-}
-
-namespace QmlJSEditor {
-namespace Internal {
-
-class ModelManager: public QmlJS::ModelManagerInterface
-{
- Q_OBJECT
-
-public:
- ModelManager(QObject *parent = 0);
-
- virtual WorkingCopy workingCopy() const;
- virtual QmlJS::Snapshot snapshot() const;
-
- virtual void updateSourceFiles(const QStringList &files,
- bool emitDocumentOnDiskChanged);
- virtual void fileChangedOnDisk(const QString &path);
- virtual void removeFiles(const QStringList &files);
-
- virtual QList<ProjectInfo> projectInfos() const;
- virtual ProjectInfo projectInfo(ProjectExplorer::Project *project) const;
- virtual void updateProjectInfo(const ProjectInfo &pinfo);
-
- void updateDocument(QmlJS::Document::Ptr doc);
- void updateLibraryInfo(const QString &path, const QmlJS::LibraryInfo &info);
- void emitDocumentChangedOnDisk(QmlJS::Document::Ptr doc);
-
- virtual QStringList importPaths() const;
-
- virtual void loadPluginTypes(const QString &libraryPath, const QString &importPath, const QString &importUri);
-
-Q_SIGNALS:
- void projectPathChanged(const QString &projectPath);
-
-private Q_SLOTS:
- void onLoadPluginTypes(const QString &libraryPath, const QString &importPath, const QString &importUri);
- void qmlPluginTypeDumpDone(int exitCode);
- void qmlPluginTypeDumpError(QProcess::ProcessError error);
-
-protected:
- QFuture<void> refreshSourceFiles(const QStringList &sourceFiles,
- bool emitDocumentOnDiskChanged);
-
- static void parse(QFutureInterface<void> &future,
- WorkingCopy workingCopy,
- QStringList files,
- ModelManager *modelManager,
- bool emitDocChangedOnDisk);
-
- void loadQmlTypeDescriptions();
- void loadQmlTypeDescriptions(const QString &path);
-
- void updateImportPaths();
-
-private:
- static bool matchesMimeType(const Core::MimeType &fileMimeType, const Core::MimeType &knownMimeType);
-
- mutable QMutex m_mutex;
- Core::ICore *m_core;
- QmlJS::Snapshot _snapshot;
- QStringList m_allImportPaths;
- QStringList m_defaultImportPaths;
- QHash<QProcess *, QString> m_runningQmldumps;
-
- QFutureSynchronizer<void> m_synchronizer;
-
- // project integration
- QMap<ProjectExplorer::Project *, ProjectInfo> m_projects;
-};
-
-} // namespace Internal
-} // namespace QmlJSEditor
-
-#endif // QMLJSMODELMANAGER_H
diff --git a/src/plugins/qmljseditor/qmljsoutline.cpp b/src/plugins/qmljseditor/qmljsoutline.cpp
index b1465819de..fcfdb885fc 100644
--- a/src/plugins/qmljseditor/qmljsoutline.cpp
+++ b/src/plugins/qmljseditor/qmljsoutline.cpp
@@ -1,5 +1,6 @@
#include "qmljsoutline.h"
#include "qmloutlinemodel.h"
+#include "qmljseditoreditable.h"
#include "qmljsoutlinetreeview.h"
#include <coreplugin/icore.h>
diff --git a/src/plugins/qmljseditor/qmljsoutline.h b/src/plugins/qmljseditor/qmljsoutline.h
index c54fc36b15..87430cb4dc 100644
--- a/src/plugins/qmljseditor/qmljsoutline.h
+++ b/src/plugins/qmljseditor/qmljsoutline.h
@@ -13,7 +13,7 @@ class IEditor;
namespace QmlJS {
class Editor;
-};
+}
namespace QmlJSEditor {
namespace Internal {
diff --git a/src/plugins/qmljseditor/qmljsoutlinetreeview.cpp b/src/plugins/qmljseditor/qmljsoutlinetreeview.cpp
index 0267619559..e0828ab840 100644
--- a/src/plugins/qmljseditor/qmljsoutlinetreeview.cpp
+++ b/src/plugins/qmljseditor/qmljsoutlinetreeview.cpp
@@ -1,79 +1,11 @@
#include "qmljsoutlinetreeview.h"
#include "qmloutlinemodel.h"
-#include <QtCore/QDebug>
-#include <QtGui/QApplication>
-#include <QtGui/QPainter>
+#include <utils/annotateditemdelegate.h>
namespace QmlJSEditor {
namespace Internal {
-QmlJSOutlineItemDelegate::QmlJSOutlineItemDelegate(QObject *parent) :
- QStyledItemDelegate(parent)
-{
-}
-
-QSize QmlJSOutlineItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
-{
- QStyleOptionViewItemV4 opt = option;
- initStyleOption(&opt, index);
-
- const QString annotation = index.data(QmlOutlineModel::AnnotationRole).toString();
- if (!annotation.isEmpty())
- opt.text += " " + annotation;
-
- QStyle *style = QApplication::style();
- return style->sizeFromContents(QStyle::CT_ItemViewItem, &opt, QSize(), 0);
-}
-
-void QmlJSOutlineItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
- const QModelIndex &index) const
-{
- QStyleOptionViewItemV4 opt = option;
- initStyleOption(&opt, index);
-
- if (opt.state & QStyle::State_Selected)
- painter->fillRect(opt.rect, option.palette.highlight());
-
- const QString typeString = index.data(Qt::DisplayRole).toString();
- QString annotationString = index.data(QmlOutlineModel::AnnotationRole).toString();
-
- QStyle *style = QApplication::style();
-
- style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, 0);
-
- if (!annotationString.isEmpty()) {
-
- int newlinePos = annotationString.indexOf(QLatin1Char('\n'));
- if (newlinePos != -1) {
- // print first line with '...' at end
- const QChar ellipsisChar(0x2026);
- annotationString = annotationString.left(newlinePos) + ellipsisChar;
- }
-
- QPalette::ColorRole textColorRole = QPalette::Text;
- if (option.state & QStyle::State_Selected) {
- textColorRole = QPalette::HighlightedText;
- }
-
- // calculate sizes of icon, type.
- QPixmap iconPixmap = opt.icon.pixmap(opt.rect.size());
- QRect iconRect = style->itemPixmapRect(opt.rect, Qt::AlignLeft, iconPixmap);
- QRect typeRect = style->itemTextRect(opt.fontMetrics, opt.rect, Qt::AlignLeft, true, typeString);
- QRect annotationRect = style->itemTextRect(opt.fontMetrics, opt.rect, Qt::AlignLeft | Qt::AlignBottom, true,
- annotationString);
-
- static int space = opt.fontMetrics.width(" ");
- annotationRect.adjust(iconRect.width() + typeRect.width() + space, 0,
- iconRect.width() + typeRect.width() + space, 0);
-
- QPalette disabledPalette(opt.palette);
- disabledPalette.setCurrentColorGroup(QPalette::Disabled);
- style->drawItemText(painter, annotationRect, Qt::AlignLeft, disabledPalette, true,
- annotationString, textColorRole);
- }
-}
-
QmlJSOutlineTreeView::QmlJSOutlineTreeView(QWidget *parent) :
Utils::NavigationTreeView(parent)
{
@@ -88,7 +20,9 @@ QmlJSOutlineTreeView::QmlJSOutlineTreeView(QWidget *parent) :
setRootIsDecorated(false);
- QmlJSOutlineItemDelegate *itemDelegate = new QmlJSOutlineItemDelegate(this);
+ Utils::AnnotatedItemDelegate *itemDelegate = new Utils::AnnotatedItemDelegate(this);
+ itemDelegate->setDelimiter(QLatin1String(" "));
+ itemDelegate->setAnnotationRole(QmlOutlineModel::AnnotationRole);
setItemDelegateForColumn(0, itemDelegate);
}
diff --git a/src/plugins/qmljseditor/qmljsoutlinetreeview.h b/src/plugins/qmljseditor/qmljsoutlinetreeview.h
index 23fb29ca37..a16afad081 100644
--- a/src/plugins/qmljseditor/qmljsoutlinetreeview.h
+++ b/src/plugins/qmljseditor/qmljsoutlinetreeview.h
@@ -2,21 +2,10 @@
#define QMLJSOUTLINETREEVIEW_H
#include <utils/navigationtreeview.h>
-#include <QtGui/QStyledItemDelegate>
namespace QmlJSEditor {
namespace Internal {
-class QmlJSOutlineItemDelegate : public QStyledItemDelegate
-{
-public:
- explicit QmlJSOutlineItemDelegate(QObject *parent = 0);
-
- QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
- void paint(QPainter *painter, const QStyleOptionViewItem &option,
- const QModelIndex &index) const;
-};
-
class QmlJSOutlineTreeView : public Utils::NavigationTreeView
{
Q_OBJECT
diff --git a/src/plugins/qmljseditor/qmljspreviewrunner.cpp b/src/plugins/qmljseditor/qmljspreviewrunner.cpp
index 2ad6c1cf71..4536f56b95 100644
--- a/src/plugins/qmljseditor/qmljspreviewrunner.cpp
+++ b/src/plugins/qmljseditor/qmljspreviewrunner.cpp
@@ -34,6 +34,7 @@
#include "qmljspreviewrunner.h"
#include <utils/environment.h>
+#include <utils/qtcprocess.h>
#include <utils/synchronousprocess.h>
#include <QtGui/QMessageBox>
@@ -54,7 +55,7 @@ QmlJSPreviewRunner::QmlJSPreviewRunner(QObject *parent) :
m_qmlViewerDefaultPath = Utils::SynchronousProcess::locateBinary(searchPath, QLatin1String("qmlviewer"));
Utils::Environment environment = Utils::Environment::systemEnvironment();
- m_applicationLauncher.setEnvironment(environment.toStringList());
+ m_applicationLauncher.setEnvironment(environment);
}
bool QmlJSPreviewRunner::isReady() const
@@ -67,7 +68,7 @@ void QmlJSPreviewRunner::run(const QString &filename)
QString errorMessage;
if (!filename.isEmpty()) {
m_applicationLauncher.start(ProjectExplorer::ApplicationLauncher::Gui, m_qmlViewerDefaultPath,
- QStringList() << filename);
+ Utils::QtcProcess::quoteArg(filename));
} else {
errorMessage = "No file specified.";
diff --git a/src/plugins/qmljseditor/qmljsquickfix.cpp b/src/plugins/qmljseditor/qmljsquickfix.cpp
index 08082e86eb..4adb0fb0e1 100644
--- a/src/plugins/qmljseditor/qmljsquickfix.cpp
+++ b/src/plugins/qmljseditor/qmljsquickfix.cpp
@@ -34,7 +34,6 @@
#include "qmljsquickfix.h"
#include "qmljscomponentfromobjectdef.h"
#include "qmljseditor.h"
-#include "qmljsrefactoringchanges.h"
#include "qmljs/parser/qmljsast_p.h"
#include <extensionsystem/iplugin.h>
@@ -48,6 +47,7 @@ using namespace QmlJS;
using namespace QmlJS::AST;
using namespace QmlJSEditor;
using namespace QmlJSEditor::Internal;
+using namespace QmlJSTools;
using namespace TextEditor;
using TextEditor::RefactoringChanges;
diff --git a/src/plugins/qmljseditor/qmljsquickfix.h b/src/plugins/qmljseditor/qmljsquickfix.h
index 74551c8c56..a9a3e7e5d3 100644
--- a/src/plugins/qmljseditor/qmljsquickfix.h
+++ b/src/plugins/qmljseditor/qmljsquickfix.h
@@ -35,11 +35,11 @@
#define QMLJSQUICKFIX_H
#include "qmljseditor.h"
-#include "qmljsrefactoringchanges.h"
#include <texteditor/quickfix.h>
#include <qmljs/parser/qmljsastfwd_p.h>
#include <qmljs/qmljsdocument.h>
+#include <qmljstools/qmljsrefactoringchanges.h>
namespace ExtensionSystem {
class IPlugin;
@@ -69,7 +69,7 @@ public:
/// Creates a new state for the given editor.
QmlJSQuickFixState(TextEditor::BaseTextEditor *editor);
- Internal::SemanticInfo semanticInfo() const;
+ SemanticInfo semanticInfo() const;
/// \returns the snapshot holding the document of the editor.
QmlJS::Snapshot snapshot() const;
@@ -77,10 +77,10 @@ public:
/// \returns the document of the editor
QmlJS::Document::Ptr document() const;
- const QmlJSRefactoringFile currentFile() const;
+ const QmlJSTools::QmlJSRefactoringFile currentFile() const;
private:
- Internal::SemanticInfo _semanticInfo;
+ SemanticInfo _semanticInfo;
};
/*!
@@ -109,7 +109,8 @@ public:
protected:
typedef Utils::ChangeSet::Range Range;
- virtual void performChanges(QmlJSRefactoringFile *currentFile, QmlJSRefactoringChanges *refactoring) = 0;
+ virtual void performChanges(QmlJSTools::QmlJSRefactoringFile *currentFile,
+ QmlJSTools::QmlJSRefactoringChanges *refactoring) = 0;
/// \returns A const-reference to the state of the operation.
const QmlJSQuickFixState &state() const;
diff --git a/src/plugins/qmljseditor/qmljsquickfixes.cpp b/src/plugins/qmljseditor/qmljsquickfixes.cpp
index 134093e5f9..60ffbbdb18 100644
--- a/src/plugins/qmljseditor/qmljsquickfixes.cpp
+++ b/src/plugins/qmljseditor/qmljsquickfixes.cpp
@@ -34,11 +34,11 @@
#include "qmljsquickfix.h"
#include "qmljscomponentfromobjectdef.h"
#include "qmljseditor.h"
-#include "qmljsrefactoringchanges.h"
#include <extensionsystem/iplugin.h>
#include <extensionsystem/pluginmanager.h>
#include <qmljs/parser/qmljsast_p.h>
+#include <qmljstools/qmljsrefactoringchanges.h>
#include <QtGui/QApplication>
@@ -46,6 +46,7 @@ using namespace QmlJS;
using namespace QmlJS::AST;
using namespace QmlJSEditor;
using namespace QmlJSEditor::Internal;
+using namespace QmlJSTools;
using namespace TextEditor;
using TextEditor::RefactoringChanges;
diff --git a/src/plugins/qmljseditor/qmljsrefactoringchanges.cpp b/src/plugins/qmljseditor/qmljsrefactoringchanges.cpp
deleted file mode 100644
index 9e9fc99fec..0000000000
--- a/src/plugins/qmljseditor/qmljsrefactoringchanges.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#include "qmljsrefactoringchanges.h"
-#include "qmljseditorcodeformatter.h"
-
-#include <qmljs/parser/qmljsast_p.h>
-#include <qmljs/qmljsmodelmanagerinterface.h>
-#include <texteditor/texteditorsettings.h>
-#include <texteditor/tabsettings.h>
-
-using namespace QmlJS;
-using namespace QmlJSEditor;
-
-QmlJSRefactoringChanges::QmlJSRefactoringChanges(ModelManagerInterface *modelManager,
- const Snapshot &snapshot)
- : m_modelManager(modelManager)
- , m_snapshot(snapshot)
-{
- Q_ASSERT(modelManager);
-}
-
-const Snapshot &QmlJSRefactoringChanges::snapshot() const
-{
- return m_snapshot;
-}
-
-QmlJSRefactoringFile QmlJSRefactoringChanges::file(const QString &fileName)
-{
- return QmlJSRefactoringFile(fileName, this);
-}
-
-void QmlJSRefactoringChanges::indentSelection(const QTextCursor &selection) const
-{
- // ### shares code with QmlJSTextEditor::indent
- QTextDocument *doc = selection.document();
-
- QTextBlock block = doc->findBlock(selection.selectionStart());
- const QTextBlock end = doc->findBlock(selection.selectionEnd()).next();
-
- const TextEditor::TabSettings &tabSettings(TextEditor::TextEditorSettings::instance()->tabSettings());
- QtStyleCodeFormatter codeFormatter(tabSettings);
- codeFormatter.updateStateUntil(block);
-
- do {
- tabSettings.indentLine(block, codeFormatter.indentFor(block));
- codeFormatter.updateLineStateChange(block);
- block = block.next();
- } while (block.isValid() && block != end);
-}
-
-void QmlJSRefactoringChanges::fileChanged(const QString &fileName)
-{
- m_modelManager->updateSourceFiles(QStringList(fileName), true);
-}
-
-
-QmlJSRefactoringFile::QmlJSRefactoringFile()
-{ }
-
-QmlJSRefactoringFile::QmlJSRefactoringFile(const QString &fileName, QmlJSRefactoringChanges *refactoringChanges)
- : RefactoringFile(fileName, refactoringChanges)
-{ }
-
-QmlJSRefactoringFile::QmlJSRefactoringFile(TextEditor::BaseTextEditor *editor, QmlJS::Document::Ptr document)
- : RefactoringFile()
- , m_qmljsDocument(document)
-{
- m_fileName = document->fileName();
- m_editor = editor;
-}
-
-Document::Ptr QmlJSRefactoringFile::qmljsDocument() const
-{
- if (!m_qmljsDocument) {
- const QString source = document()->toPlainText();
- const QString name = fileName();
- const Snapshot &snapshot = refactoringChanges()->snapshot();
-
- m_qmljsDocument = snapshot.documentFromSource(source, name);
- m_qmljsDocument->parse();
- }
-
- return m_qmljsDocument;
-}
-
-unsigned QmlJSRefactoringFile::startOf(const AST::SourceLocation &loc) const
-{
- return position(loc.startLine, loc.startColumn);
-}
-
-bool QmlJSRefactoringFile::isCursorOn(AST::UiObjectMember *ast) const
-{
- const unsigned pos = cursor().position();
-
- return ast->firstSourceLocation().begin() <= pos
- && pos <= ast->lastSourceLocation().end();
-}
-
-bool QmlJSRefactoringFile::isCursorOn(AST::UiQualifiedId *ast) const
-{
- const unsigned pos = cursor().position();
-
- if (ast->identifierToken.begin() > pos)
- return false;
-
- AST::UiQualifiedId *last = ast;
- while (last->next)
- last = last->next;
-
- return pos <= ast->identifierToken.end();
-}
-
-QmlJSRefactoringChanges *QmlJSRefactoringFile::refactoringChanges() const
-{
- return static_cast<QmlJSRefactoringChanges *>(m_refactoringChanges);
-}
diff --git a/src/plugins/qmljseditor/qmljsrefactoringchanges.h b/src/plugins/qmljseditor/qmljsrefactoringchanges.h
deleted file mode 100644
index 834d0f89c9..0000000000
--- a/src/plugins/qmljseditor/qmljsrefactoringchanges.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#ifndef QMLREFACTORINGCHANGES_H
-#define QMLREFACTORINGCHANGES_H
-
-#include <qmljs/qmljsdocument.h>
-
-#include <texteditor/refactoringchanges.h>
-
-namespace QmlJS {
-class ModelManagerInterface;
-} // namespace QmlJS
-
-namespace QmlJSEditor {
-
-class QmlJSRefactoringChanges;
-
-class QmlJSRefactoringFile: public TextEditor::RefactoringFile
-{
-public:
- QmlJSRefactoringFile();
- QmlJSRefactoringFile(const QString &fileName, QmlJSRefactoringChanges *refactoringChanges);
- QmlJSRefactoringFile(TextEditor::BaseTextEditor *editor, QmlJS::Document::Ptr document);
-
- QmlJS::Document::Ptr qmljsDocument() const;
-
- /*!
- \returns the offset in the document for the start position of the given
- source location.
- */
- unsigned startOf(const QmlJS::AST::SourceLocation &loc) const;
-
- bool isCursorOn(QmlJS::AST::UiObjectMember *ast) const;
- bool isCursorOn(QmlJS::AST::UiQualifiedId *ast) const;
-
-private:
- QmlJSRefactoringChanges *refactoringChanges() const;
-
- mutable QmlJS::Document::Ptr m_qmljsDocument;
-};
-
-
-class QmlJSRefactoringChanges: public TextEditor::RefactoringChanges
-{
-public:
- QmlJSRefactoringChanges(QmlJS::ModelManagerInterface *modelManager,
- const QmlJS::Snapshot &snapshot);
-
- const QmlJS::Snapshot &snapshot() const;
-
- QmlJSRefactoringFile file(const QString &fileName);
-
-private:
- virtual void indentSelection(const QTextCursor &selection) const;
- virtual void fileChanged(const QString &fileName);
-
-private:
- QmlJS::ModelManagerInterface *m_modelManager;
- QmlJS::Snapshot m_snapshot;
-};
-
-} // namespace QmlJSEditor
-
-#endif // QMLREFACTORINGCHANGES_H
diff --git a/src/plugins/qmljseditor/qmljssemantichighlighter.cpp b/src/plugins/qmljseditor/qmljssemantichighlighter.cpp
new file mode 100644
index 0000000000..927878aa2c
--- /dev/null
+++ b/src/plugins/qmljseditor/qmljssemantichighlighter.cpp
@@ -0,0 +1,152 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "qmljssemantichighlighter.h"
+
+#include <qmljs/qmljsmodelmanagerinterface.h>
+#include <qmljs/qmljsdocument.h>
+#include <qmljs/qmljscheck.h>
+#include <qmljs/qmljsinterpreter.h>
+#include <qmljs/qmljslink.h>
+
+namespace QmlJSEditor {
+namespace Internal {
+
+SemanticHighlighter::SemanticHighlighter(QObject *parent)
+ : QThread(parent),
+ m_done(false),
+ m_modelManager(0)
+{
+}
+
+SemanticHighlighter::~SemanticHighlighter()
+{
+}
+
+void SemanticHighlighter::abort()
+{
+ QMutexLocker locker(&m_mutex);
+ m_done = true;
+ m_condition.wakeOne();
+}
+
+void SemanticHighlighter::rehighlight(const SemanticHighlighterSource &source)
+{
+ QMutexLocker locker(&m_mutex);
+ m_source = source;
+ m_condition.wakeOne();
+}
+
+bool SemanticHighlighter::isOutdated()
+{
+ QMutexLocker locker(&m_mutex);
+ const bool outdated = ! m_source.fileName.isEmpty() || m_done;
+ return outdated;
+}
+
+void SemanticHighlighter::run()
+{
+ setPriority(QThread::LowestPriority);
+
+ forever {
+ m_mutex.lock();
+
+ while (! (m_done || ! m_source.fileName.isEmpty()))
+ m_condition.wait(&m_mutex);
+
+ const bool done = m_done;
+ const SemanticHighlighterSource source = m_source;
+ m_source.clear();
+
+ m_mutex.unlock();
+
+ if (done)
+ break;
+
+ const SemanticInfo info = semanticInfo(source);
+
+ if (! isOutdated()) {
+ m_mutex.lock();
+ m_lastSemanticInfo = info;
+ m_mutex.unlock();
+
+ emit changed(info);
+ }
+ }
+}
+
+SemanticInfo SemanticHighlighter::semanticInfo(const SemanticHighlighterSource &source)
+{
+ m_mutex.lock();
+ const int revision = m_lastSemanticInfo.revision();
+ m_mutex.unlock();
+
+ QmlJS::Snapshot snapshot;
+ QmlJS::Document::Ptr doc;
+
+ if (! source.force && revision == source.revision) {
+ m_mutex.lock();
+ snapshot = m_lastSemanticInfo.snapshot;
+ doc = m_lastSemanticInfo.document;
+ m_mutex.unlock();
+ }
+
+ if (! doc) {
+ snapshot = source.snapshot;
+ doc = snapshot.documentFromSource(source.code, source.fileName);
+ doc->setEditorRevision(source.revision);
+ doc->parse();
+ snapshot.insert(doc);
+ }
+
+ SemanticInfo semanticInfo;
+ semanticInfo.snapshot = snapshot;
+ semanticInfo.document = doc;
+
+ QmlJS::Interpreter::Context *ctx = new QmlJS::Interpreter::Context;
+ QmlJS::Link link(ctx, doc, snapshot, QmlJS::ModelManagerInterface::instance()->importPaths());
+ semanticInfo.m_context = QSharedPointer<const QmlJS::Interpreter::Context>(ctx);
+ semanticInfo.semanticMessages = link.diagnosticMessages();
+
+ QStringList importPaths;
+ if (m_modelManager)
+ importPaths = m_modelManager->importPaths();
+ QmlJS::Check checker(doc, snapshot, ctx);
+ semanticInfo.semanticMessages.append(checker());
+
+ return semanticInfo;
+}
+
+void SemanticHighlighter::setModelManager(QmlJS::ModelManagerInterface *modelManager)
+{
+ m_modelManager = modelManager;
+}
+
+} // namespace Internal
+} // namespace QmlJSEditor
diff --git a/src/plugins/qmljseditor/qmljssemantichighlighter.h b/src/plugins/qmljseditor/qmljssemantichighlighter.h
new file mode 100644
index 0000000000..dff097ba7f
--- /dev/null
+++ b/src/plugins/qmljseditor/qmljssemantichighlighter.h
@@ -0,0 +1,113 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 SEMANTICHIGHLIGHTER_H
+#define SEMANTICHIGHLIGHTER_H
+
+#include "qmljseditor.h"
+
+#include <QtCore/QWaitCondition>
+#include <QtCore/QModelIndex>
+#include <QtCore/QMutex>
+#include <QtCore/QThread>
+
+namespace QmlJSEditor {
+namespace Internal {
+
+struct SemanticHighlighterSource
+{
+ QmlJS::Snapshot snapshot;
+ QString fileName;
+ QString code;
+ int line;
+ int column;
+ int revision;
+ bool force;
+
+ SemanticHighlighterSource()
+ : line(0), column(0), revision(0), force(false)
+ { }
+
+ SemanticHighlighterSource(const QmlJS::Snapshot &snapshot,
+ const QString &fileName,
+ const QString &code,
+ int line, int column,
+ int revision)
+ : snapshot(snapshot), fileName(fileName),
+ code(code), line(line), column(column),
+ revision(revision), force(false)
+ { }
+
+ void clear()
+ {
+ snapshot = QmlJS::Snapshot();
+ fileName.clear();
+ code.clear();
+ line = 0;
+ column = 0;
+ revision = 0;
+ force = false;
+ }
+};
+
+class SemanticHighlighter: public QThread
+{
+ Q_OBJECT
+
+public:
+ SemanticHighlighter(QObject *parent = 0);
+ virtual ~SemanticHighlighter();
+
+ void abort();
+ void rehighlight(const SemanticHighlighterSource &source);
+ void setModelManager(QmlJS::ModelManagerInterface *modelManager);
+
+Q_SIGNALS:
+ void changed(const QmlJSEditor::SemanticInfo &semanticInfo);
+
+protected:
+ virtual void run();
+
+private:
+ bool isOutdated();
+ SemanticInfo semanticInfo(const SemanticHighlighterSource &source);
+
+private:
+ QMutex m_mutex;
+ QWaitCondition m_condition;
+ bool m_done;
+ SemanticHighlighterSource m_source;
+ SemanticInfo m_lastSemanticInfo;
+ QmlJS::ModelManagerInterface *m_modelManager;
+};
+
+} // namespace Internal
+} // namespace QmlJSEditor
+
+#endif // SEMANTICHIGHLIGHTER_H
diff --git a/src/plugins/qmljseditor/qmljssnippetprovider.cpp b/src/plugins/qmljseditor/qmljssnippetprovider.cpp
new file mode 100644
index 0000000000..9c24e19730
--- /dev/null
+++ b/src/plugins/qmljseditor/qmljssnippetprovider.cpp
@@ -0,0 +1,72 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "qmljssnippetprovider.h"
+#include "qmljshighlighter.h"
+#include "qmljseditor.h"
+#include "qmljsindenter.h"
+#include "qmljsautocompleter.h"
+#include "qmljseditorconstants.h"
+
+#include <texteditor/texteditorsettings.h>
+#include <texteditor/fontsettings.h>
+#include <texteditor/texteditorconstants.h>
+#include <texteditor/snippets/snippeteditor.h>
+
+#include <QtCore/QLatin1String>
+
+using namespace QmlJSEditor;
+using namespace Internal;
+
+QmlJSSnippetProvider::QmlJSSnippetProvider() :
+ TextEditor::ISnippetProvider()
+{}
+
+QmlJSSnippetProvider::~QmlJSSnippetProvider()
+{}
+
+QString QmlJSSnippetProvider::groupId() const
+{
+ return QLatin1String(Constants::QML_SNIPPETS_GROUP_ID);
+}
+
+QString QmlJSSnippetProvider::displayName() const
+{
+ return tr("QML");
+}
+
+void QmlJSSnippetProvider::decorateEditor(TextEditor::SnippetEditor *editor) const
+{
+ Highlighter *highlighter = new Highlighter;
+ const TextEditor::FontSettings &fs = TextEditor::TextEditorSettings::instance()->fontSettings();
+ highlighter->setFormats(fs.toTextCharFormats(QmlJSTextEditor::highlighterFormatCategories()));
+ editor->setSyntaxHighlighter(highlighter);
+ editor->setIndenter(new Indenter);
+ editor->setAutoCompleter(new AutoCompleter);
+}
diff --git a/src/plugins/qmljseditor/qmljssnippetprovider.h b/src/plugins/qmljseditor/qmljssnippetprovider.h
new file mode 100644
index 0000000000..f3b7b18550
--- /dev/null
+++ b/src/plugins/qmljseditor/qmljssnippetprovider.h
@@ -0,0 +1,53 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 QMLJSSNIPPETEDITORDECORATOR_H
+#define QMLJSSNIPPETEDITORDECORATOR_H
+
+#include <texteditor/snippets/isnippetprovider.h>
+
+namespace QmlJSEditor {
+namespace Internal {
+
+class QmlJSSnippetProvider : public TextEditor::ISnippetProvider
+{
+public:
+ QmlJSSnippetProvider();
+ virtual ~QmlJSSnippetProvider();
+
+public:
+ virtual QString groupId() const;
+ virtual QString displayName() const;
+ virtual void decorateEditor(TextEditor::SnippetEditor *editor) const;
+};
+
+} // Internal
+} // QmlJSEditor
+
+#endif // QMLJSSNIPPETEDITORDECORATOR_H
diff --git a/src/plugins/qmljseditor/qmloutlinemodel.cpp b/src/plugins/qmljseditor/qmloutlinemodel.cpp
index a004804868..5e25a81037 100644
--- a/src/plugins/qmljseditor/qmloutlinemodel.cpp
+++ b/src/plugins/qmljseditor/qmloutlinemodel.cpp
@@ -1,12 +1,12 @@
#include "qmloutlinemodel.h"
#include "qmljseditor.h"
-#include "qmljsrefactoringchanges.h"
#include <qmljs/parser/qmljsastvisitor_p.h>
#include <qmljs/qmljsinterpreter.h>
#include <qmljs/qmljslookupcontext.h>
#include <qmljs/qmljsmodelmanagerinterface.h>
#include <qmljs/qmljsrewriter.h>
+#include <qmljstools/qmljsrefactoringchanges.h>
#include <utils/qtcassert.h>
@@ -17,6 +17,7 @@
using namespace QmlJS;
using namespace QmlJSEditor::Internal;
+using namespace QmlJSTools;
enum {
debug = false
@@ -367,6 +368,10 @@ void QmlOutlineModel::update(const SemanticInfo &semanticInfo)
m_treePos.append(0);
m_currentItem = invisibleRootItem();
+ // resetModel() actually gives better average performance
+ // then the incremental updates.
+ beginResetModel();
+
m_typeToIcon.clear();
m_itemToNode.clear();
m_itemToIdNode.clear();
@@ -376,6 +381,8 @@ void QmlOutlineModel::update(const SemanticInfo &semanticInfo)
QmlOutlineModelSync syncModel(this);
syncModel(m_semanticInfo.document);
+ endResetModel();
+
emit updated();
}
@@ -519,6 +526,7 @@ AST::Node *QmlOutlineModel::nodeForIndex(const QModelIndex &index) const
QTC_ASSERT(index.isValid() && (index.model() == this), return 0);
if (index.isValid()) {
QmlOutlineItem *item = static_cast<QmlOutlineItem*>(itemFromIndex(index));
+ QTC_ASSERT(item, return 0);
QTC_ASSERT(m_itemToNode.contains(item), return 0);
return m_itemToNode.value(item);
}
diff --git a/src/plugins/qmljseditor/qmloutlinemodel.h b/src/plugins/qmljseditor/qmloutlinemodel.h
index 0da121abf2..88273adc1c 100644
--- a/src/plugins/qmljseditor/qmloutlinemodel.h
+++ b/src/plugins/qmljseditor/qmloutlinemodel.h
@@ -51,7 +51,7 @@ public:
enum ItemTypes {
ElementType,
- ElementBindingType, // might contain elements as childs
+ ElementBindingType, // might contain elements as children
NonElementBindingType // can be filtered out
};
diff --git a/src/plugins/qmljseditor/quicktoolbar.cpp b/src/plugins/qmljseditor/quicktoolbar.cpp
index e7676332d0..b53344a75c 100644
--- a/src/plugins/qmljseditor/quicktoolbar.cpp
+++ b/src/plugins/qmljseditor/quicktoolbar.cpp
@@ -43,16 +43,14 @@ static inline const Interpreter::ObjectValue * getPropertyChangesTarget(Node *no
for (UiObjectMemberList *members = initializer->members; members; members = members->next) {
if (UiScriptBinding *scriptBinding = cast<UiScriptBinding *>(members->member)) {
if (scriptBinding->qualifiedId
- && scriptBinding->qualifiedId->name->asString() == QLatin1String("target")
- && ! scriptBinding->qualifiedId->next) {
- if (ExpressionStatement *expressionStatement = cast<ExpressionStatement *>(scriptBinding->statement)) {
- Evaluate evaluator(lookupContext->context());
- const Interpreter::Value *targetValue = evaluator(expressionStatement->expression);
- if (const Interpreter::ObjectValue *targetObject = Interpreter::value_cast<const Interpreter::ObjectValue *>(targetValue)) {
- return targetObject;
- } else {
- return 0;
- }
+ && scriptBinding->qualifiedId->name->asString() == QLatin1String("target")
+ && ! scriptBinding->qualifiedId->next) {
+ Evaluate evaluator(lookupContext->context());
+ const Interpreter::Value *targetValue = evaluator(scriptBinding->statement);
+ if (const Interpreter::ObjectValue *targetObject = Interpreter::value_cast<const Interpreter::ObjectValue *>(targetValue)) {
+ return targetObject;
+ } else {
+ return 0;
}
}
}
@@ -115,19 +113,21 @@ void QuickToolBar::apply(TextEditor::BaseTextEditorEditable *editor, Document::P
const Interpreter::ObjectValue *scopeObject = document->bind()->findQmlObject(node);
- if (!lookupContext.isNull()) {
+ if (!lookupContext.isNull() && scopeObject) {
m_prototypes.clear();
- while (scopeObject) {
- m_prototypes.append(scopeObject->className());
- scopeObject = scopeObject->prototype(lookupContext->context());
+ foreach (const Interpreter::ObjectValue *object,
+ Interpreter::PrototypeIterator(scopeObject, lookupContext->context()).all()) {
+ m_prototypes.append(object->className());
}
if (m_prototypes.contains("PropertyChanges")) {
const Interpreter::ObjectValue *targetObject = getPropertyChangesTarget(node, lookupContext);
m_prototypes.clear();
- while (targetObject) {
- m_prototypes.append(targetObject->className());
- targetObject = targetObject->prototype(lookupContext->context());
+ if (targetObject) {
+ foreach (const Interpreter::ObjectValue *object,
+ Interpreter::PrototypeIterator(targetObject, lookupContext->context()).all()) {
+ m_prototypes.append(object->className());
+ }
}
}
}
diff --git a/src/plugins/qmljseditor/quicktoolbarsettingspage.cpp b/src/plugins/qmljseditor/quicktoolbarsettingspage.cpp
index 83dad4abdd..0c6c3af269 100644
--- a/src/plugins/qmljseditor/quicktoolbarsettingspage.cpp
+++ b/src/plugins/qmljseditor/quicktoolbarsettingspage.cpp
@@ -110,8 +110,8 @@ QString QuickToolBarSettingsPageWidget::searchKeywords() const
{
QString rc;
QTextStream(&rc)
- << ' ' << m_ui.textEditHelperCheckBox
- << ' ' << m_ui.textEditHelperCheckBoxPin;
+ << ' ' << m_ui.textEditHelperCheckBox->text()
+ << ' ' << m_ui.textEditHelperCheckBoxPin->text();
rc.remove(QLatin1Char('&'));
return rc;
}
@@ -165,6 +165,8 @@ QWidget *QuickToolBarSettingsPage::createPage(QWidget *parent)
void QuickToolBarSettingsPage::apply()
{
+ if (!m_widget) // page was never shown
+ return;
m_widget->settings().set();
}
diff --git a/src/plugins/qmljsinspector/QmlJSInspector.pluginspec b/src/plugins/qmljsinspector/QmlJSInspector.pluginspec
deleted file mode 100644
index cd15a9bc1c..0000000000
--- a/src/plugins/qmljsinspector/QmlJSInspector.pluginspec
+++ /dev/null
@@ -1,30 +0,0 @@
-<plugin name="QmlJSInspector" version="2.0.92" compatVersion="2.0.95">
- <vendor>Nokia Corporation</vendor>
- <copyright>(C) 2010 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>
- <category>Qt Quick</category>
- <description>Debugger for QML files</description>
- <url>http://qt.nokia.com</url>
- <dependencyList>
- <dependency name="QmlProjectManager" version="2.0.95"/>
- <dependency name="ProjectExplorer" version="2.0.95"/>
- <dependency name="CppTools" version="2.0.95"/>
- <dependency name="CppEditor" version="2.0.95"/>
- <dependency name="Debugger" version="2.0.95"/>
- <dependency name="QmlJSEditor" version="2.0.95"/>
- </dependencyList>
-</plugin>
diff --git a/src/plugins/qmljsinspector/QmlJSInspector.pluginspec.in b/src/plugins/qmljsinspector/QmlJSInspector.pluginspec.in
new file mode 100644
index 0000000000..65d6a45f84
--- /dev/null
+++ b/src/plugins/qmljsinspector/QmlJSInspector.pluginspec.in
@@ -0,0 +1,30 @@
+<plugin name=\"QmlJSInspector\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2010 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>
+ <category>Qt Quick</category>
+ <description>Debugger for QML files</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name=\"QmlProjectManager\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"ProjectExplorer\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"CppTools\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"CppEditor\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"Debugger\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"QmlJSEditor\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/qmljsinspector/images/app-on-top.png b/src/plugins/qmljsinspector/images/app-on-top.png
new file mode 100644
index 0000000000..ddec5400c6
--- /dev/null
+++ b/src/plugins/qmljsinspector/images/app-on-top.png
Binary files differ
diff --git a/src/plugins/qmljsinspector/qmlinspectortoolbar.cpp b/src/plugins/qmljsinspector/qmlinspectortoolbar.cpp
index 42581c7087..aeacc9e551 100644
--- a/src/plugins/qmljsinspector/qmlinspectortoolbar.cpp
+++ b/src/plugins/qmljsinspector/qmlinspectortoolbar.cpp
@@ -35,20 +35,21 @@
#include "qmljsinspectorconstants.h"
#include "qmljstoolbarcolorbox.h"
-#include <extensionsystem/pluginmanager.h>
-#include <coreplugin/icore.h>
-#include <projectexplorer/projectexplorerconstants.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
+#include <coreplugin/uniqueidmanager.h>
+#include <coreplugin/icore.h>
+#include <extensionsystem/pluginmanager.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <utils/styledbar.h>
#include <utils/filterlineedit.h>
-#include <QHBoxLayout>
#include <QAction>
-#include <QToolButton>
-#include <QMenu>
#include <QActionGroup>
+#include <QHBoxLayout>
+#include <QMenu>
+#include <QToolButton>
namespace QmlJSInspector {
namespace Internal {
@@ -62,14 +63,13 @@ static QToolButton *createToolButton(QAction *action)
QmlInspectorToolbar::QmlInspectorToolbar(QObject *parent) :
QObject(parent),
+ m_fromQmlAction(0),
m_observerModeAction(0),
-// m_reloadAction(0),
m_playAction(0),
m_selectAction(0),
m_zoomAction(0),
m_colorPickerAction(0),
- m_toQmlAction(0),
- m_fromQmlAction(0),
+ m_showAppOnTopAction(0),
m_defaultAnimSpeedAction(0),
m_halfAnimSpeedAction(0),
m_fourthAnimSpeedAction(0),
@@ -86,22 +86,17 @@ QmlInspectorToolbar::QmlInspectorToolbar(QObject *parent) :
m_activeTool(NoTool),
m_barWidget(0)
{
-
}
void QmlInspectorToolbar::setEnabled(bool value)
{
- m_observerModeAction->setEnabled(value);
- //m_toQmlAction->setEnabled(value);
m_fromQmlAction->setEnabled(value);
-
-// m_reloadAction->setEnabled(value);
+ m_showAppOnTopAction->setEnabled(value);
+ m_observerModeAction->setEnabled(value);
m_playAction->setEnabled(value);
m_selectAction->setEnabled(value);
m_zoomAction->setEnabled(value);
m_colorPickerAction->setEnabled(value);
- //m_toQmlAction->setEnabled(value);
- m_fromQmlAction->setEnabled(value);
m_colorBox->setEnabled(value);
}
@@ -177,70 +172,90 @@ void QmlInspectorToolbar::setDesignModeBehavior(bool inDesignMode)
m_emitSignals = true;
}
+void QmlInspectorToolbar::setShowAppOnTop(bool showAppOnTop)
+{
+ m_emitSignals = false;
+ m_showAppOnTopAction->setChecked(showAppOnTop);
+ m_emitSignals = true;
+}
+
void QmlInspectorToolbar::createActions(const Core::Context &context)
{
Core::ICore *core = Core::ICore::instance();
Core::ActionManager *am = core->actionManager();
- m_fromQmlAction = new QAction(QIcon(QLatin1String(":/qml/images/from-qml-small.png")), tr("Apply Changes on Save"), this);
-// m_reloadAction = new QAction(QIcon(QLatin1String(":/qml/images/reload.png")), tr("Reload QML"), this);
-
- m_observerModeAction = new QAction(QIcon(QLatin1String(":/qml/images/observermode.png")), tr("Observer Mode"), this);
- m_playAction = new QAction(m_pauseIcon, tr("Play/Pause Animations"), this);
- m_selectAction = new QAction(QIcon(QLatin1String(":/qml/images/select-small.png")), tr("Select"), this);
- m_zoomAction = new QAction(QIcon(QLatin1String(":/qml/images/zoom-small.png")), tr("Zoom"), this);
- m_colorPickerAction = new QAction(QIcon(QLatin1String(":/qml/images/color-picker-small.png")), tr("Color Picker"), this);
- m_toQmlAction = new QAction(QIcon(QLatin1String(":/qml/images/to-qml-small.png")), tr("Live Preview Changes in QML Viewer"), this);
+ m_fromQmlAction =
+ new QAction(QIcon(QLatin1String(":/qml/images/from-qml-small.png")),
+ tr("Apply Changes on Save"), this);
+ m_showAppOnTopAction =
+ new QAction(QIcon(QLatin1String(":/qml/images/app-on-top.png")),
+ tr("Show application on top"), this);
+ m_observerModeAction =
+ new QAction(QIcon(QLatin1String(":/qml/images/observermode.png")),
+ tr("Observer Mode"), this);
+ m_playAction =
+ new QAction(m_pauseIcon, tr("Play/Pause Animations"), this);
+ m_selectAction =
+ new QAction(QIcon(QLatin1String(":/qml/images/select-small.png")),
+ tr("Select"), this);
+ m_zoomAction =
+ new QAction(QIcon(QLatin1String(":/qml/images/zoom-small.png")),
+ tr("Zoom"), this);
+ m_colorPickerAction =
+ new QAction(QIcon(QLatin1String(":/qml/images/color-picker-small.png")),
+ tr("Color Picker"), this);
+ m_fromQmlAction->setCheckable(true);
+ m_fromQmlAction->setChecked(true);
+ m_showAppOnTopAction->setCheckable(true);
+ m_showAppOnTopAction->setChecked(false);
m_observerModeAction->setCheckable(true);
m_observerModeAction->setChecked(false);
m_selectAction->setCheckable(true);
m_zoomAction->setCheckable(true);
m_colorPickerAction->setCheckable(true);
- m_fromQmlAction->setCheckable(true);
- m_fromQmlAction->setChecked(true);
-
am->registerAction(m_observerModeAction, QmlJSInspector::Constants::DESIGNMODE_ACTION, context);
-// am->registerAction(m_reloadAction, QmlJSInspector::Constants::RELOAD_ACTION, context);
am->registerAction(m_playAction, QmlJSInspector::Constants::PLAY_ACTION, context);
am->registerAction(m_selectAction, QmlJSInspector::Constants::SELECT_ACTION, context);
am->registerAction(m_zoomAction, QmlJSInspector::Constants::ZOOM_ACTION, context);
am->registerAction(m_colorPickerAction, QmlJSInspector::Constants::COLOR_PICKER_ACTION, context);
- am->registerAction(m_toQmlAction, QmlJSInspector::Constants::TO_QML_ACTION, context);
am->registerAction(m_fromQmlAction, QmlJSInspector::Constants::FROM_QML_ACTION, context);
+ am->registerAction(m_showAppOnTopAction,
+ QmlJSInspector::Constants::SHOW_APP_ON_TOP_ACTION, context);
m_barWidget = new Utils::StyledBar;
m_barWidget->setSingleRow(true);
m_barWidget->setProperty("topBorder", true);
- QHBoxLayout *configBarLayout = new QHBoxLayout(m_barWidget);
- configBarLayout->setMargin(0);
- configBarLayout->setSpacing(5);
-
QMenu *playSpeedMenu = new QMenu(m_barWidget);
QActionGroup *playSpeedMenuActions = new QActionGroup(this);
playSpeedMenuActions->setExclusive(true);
playSpeedMenu->addAction(tr("Animation Speed"));
playSpeedMenu->addSeparator();
- m_defaultAnimSpeedAction = playSpeedMenu->addAction(tr("1x"), this, SLOT(changeToDefaultAnimSpeed()));
+ m_defaultAnimSpeedAction =
+ playSpeedMenu->addAction(tr("1x"), this, SLOT(changeToDefaultAnimSpeed()));
m_defaultAnimSpeedAction->setCheckable(true);
m_defaultAnimSpeedAction->setChecked(true);
playSpeedMenuActions->addAction(m_defaultAnimSpeedAction);
- m_halfAnimSpeedAction = playSpeedMenu->addAction(tr("0.5x"), this, SLOT(changeToHalfAnimSpeed()));
+ m_halfAnimSpeedAction =
+ playSpeedMenu->addAction(tr("0.5x"), this, SLOT(changeToHalfAnimSpeed()));
m_halfAnimSpeedAction->setCheckable(true);
playSpeedMenuActions->addAction(m_halfAnimSpeedAction);
- m_fourthAnimSpeedAction = playSpeedMenu->addAction(tr("0.25x"), this, SLOT(changeToFourthAnimSpeed()));
+ m_fourthAnimSpeedAction =
+ playSpeedMenu->addAction(tr("0.25x"), this, SLOT(changeToFourthAnimSpeed()));
m_fourthAnimSpeedAction->setCheckable(true);
playSpeedMenuActions->addAction(m_fourthAnimSpeedAction);
- m_eighthAnimSpeedAction = playSpeedMenu->addAction(tr("0.125x"), this, SLOT(changeToEighthAnimSpeed()));
+ m_eighthAnimSpeedAction =
+ playSpeedMenu->addAction(tr("0.125x"), this, SLOT(changeToEighthAnimSpeed()));
m_eighthAnimSpeedAction->setCheckable(true);
playSpeedMenuActions->addAction(m_eighthAnimSpeedAction);
- m_tenthAnimSpeedAction = playSpeedMenu->addAction(tr("0.1x"), this, SLOT(changeToTenthAnimSpeed()));
+ m_tenthAnimSpeedAction =
+ playSpeedMenu->addAction(tr("0.1x"), this, SLOT(changeToTenthAnimSpeed()));
m_tenthAnimSpeedAction->setCheckable(true);
playSpeedMenuActions->addAction(m_tenthAnimSpeedAction);
@@ -249,22 +264,30 @@ void QmlInspectorToolbar::createActions(const Core::Context &context)
m_menuPauseAction->setIcon(m_pauseIcon);
playSpeedMenuActions->addAction(m_menuPauseAction);
-// configBarLayout->addWidget(createToolButton(am->command(ProjectExplorer::Constants::DEBUG)->action()));
-// configBarLayout->addWidget(createToolButton(am->command(ProjectExplorer::Constants::STOP)->action()));
- configBarLayout->addWidget(createToolButton(am->command(QmlJSInspector::Constants::FROM_QML_ACTION)->action()));
-// configBarLayout->addWidget(createToolButton(am->command(QmlJSInspector::Constants::RELOAD_ACTION)->action()));
+ QHBoxLayout *configBarLayout = new QHBoxLayout(m_barWidget);
+ configBarLayout->setMargin(0);
+ configBarLayout->setSpacing(5);
+
+ configBarLayout->addWidget(
+ createToolButton(am->command(QmlJSInspector::Constants::FROM_QML_ACTION)->action()));
+ configBarLayout->addWidget(
+ createToolButton(
+ am->command(QmlJSInspector::Constants::SHOW_APP_ON_TOP_ACTION)->action()));
configBarLayout->addSpacing(10);
- configBarLayout->addWidget(createToolButton(am->command(QmlJSInspector::Constants::DESIGNMODE_ACTION)->action()));
+ configBarLayout->addWidget(
+ createToolButton(
+ am->command(QmlJSInspector::Constants::DESIGNMODE_ACTION)->action()));
m_playButton = createToolButton(am->command(QmlJSInspector::Constants::PLAY_ACTION)->action());
m_playButton->setMenu(playSpeedMenu);
configBarLayout->addWidget(m_playButton);
- //configBarLayout->addWidget(createToolButton(am->command(QmlJSInspector::Constants::PAUSE_ACTION)->action()));
-
- configBarLayout->addWidget(createToolButton(am->command(QmlJSInspector::Constants::SELECT_ACTION)->action()));
-
- configBarLayout->addWidget(createToolButton(am->command(QmlJSInspector::Constants::ZOOM_ACTION)->action()));
- configBarLayout->addWidget(createToolButton(am->command(QmlJSInspector::Constants::COLOR_PICKER_ACTION)->action()));
+ configBarLayout->addWidget(
+ createToolButton(am->command(QmlJSInspector::Constants::SELECT_ACTION)->action()));
+ configBarLayout->addWidget(
+ createToolButton(am->command(QmlJSInspector::Constants::ZOOM_ACTION)->action()));
+ configBarLayout->addWidget(
+ createToolButton(
+ am->command(QmlJSInspector::Constants::COLOR_PICKER_ACTION)->action()));
m_colorBox = new ToolBarColorBox(m_barWidget);
m_colorBox->setMinimumSize(20, 20);
@@ -272,28 +295,18 @@ void QmlInspectorToolbar::createActions(const Core::Context &context)
m_colorBox->setInnerBorderColor(QColor(192,192,192));
m_colorBox->setOuterBorderColor(QColor(58,58,58));
configBarLayout->addWidget(m_colorBox);
- //configBarLayout->addWidget(createToolButton(am->command(QmlJSInspector::Constants::TO_QML_ACTION)->action()));
-
- //m_filterLineEdit = new Utils::FilterLineEdit(m_barWidget);
-
configBarLayout->addStretch();
- //configBarLayout->addWidget(m_filterLineEdit);
setEnabled(false);
+ connect(m_fromQmlAction, SIGNAL(triggered()), SLOT(activateFromQml()));
+ connect(m_showAppOnTopAction, SIGNAL(triggered()), SLOT(showAppOnTopClick()));
connect(m_observerModeAction, SIGNAL(triggered()), SLOT(activateDesignModeOnClick()));
-// connect(m_reloadAction, SIGNAL(triggered()), SIGNAL(reloadSelected()));
-
- connect(m_colorPickerAction, SIGNAL(triggered()), SLOT(activateColorPickerOnClick()));
-
connect(m_playAction, SIGNAL(triggered()), SLOT(activatePlayOnClick()));
-
- connect(m_zoomAction, SIGNAL(triggered()), SLOT(activateZoomOnClick()));
connect(m_colorPickerAction, SIGNAL(triggered()), SLOT(activateColorPickerOnClick()));
connect(m_selectAction, SIGNAL(triggered()), SLOT(activateSelectToolOnClick()));
-
- //connect(m_toQmlAction, SIGNAL(triggered()), SLOT(activateToQml()));
- connect(m_fromQmlAction, SIGNAL(triggered()), SLOT(activateFromQml()));
+ connect(m_zoomAction, SIGNAL(triggered()), SLOT(activateZoomOnClick()));
+ connect(m_colorPickerAction, SIGNAL(triggered()), SLOT(activateColorPickerOnClick()));
}
QWidget *QmlInspectorToolbar::widget() const
@@ -335,7 +348,6 @@ void QmlInspectorToolbar::activateDesignModeOnClick()
{
bool checked = m_observerModeAction->isChecked();
-// m_reloadAction->setEnabled(true);
m_playAction->setEnabled(checked);
m_selectAction->setEnabled(checked);
m_zoomAction->setEnabled(checked);
@@ -416,9 +428,10 @@ void QmlInspectorToolbar::activateZoomOnClick()
}
}
-void QmlInspectorToolbar::setLivePreviewChecked(bool value)
+void QmlInspectorToolbar::showAppOnTopClick()
{
- m_fromQmlAction->setChecked(value);
+ if (m_emitSignals)
+ emit showAppOnTopSelected(m_showAppOnTopAction->isChecked());
}
void QmlInspectorToolbar::setSelectedColor(const QColor &color)
@@ -432,11 +445,5 @@ void QmlInspectorToolbar::activateFromQml()
emit applyChangesFromQmlFileTriggered(m_fromQmlAction->isChecked());
}
-void QmlInspectorToolbar::activateToQml()
-{
- if (m_emitSignals)
- emit applyChangesToQmlFileSelected();
-}
-
} // namespace Internal
} // namespace QmlJSInspector
diff --git a/src/plugins/qmljsinspector/qmlinspectortoolbar.h b/src/plugins/qmljsinspector/qmlinspectortoolbar.h
index 487567c09b..69dab06b50 100644
--- a/src/plugins/qmljsinspector/qmlinspectortoolbar.h
+++ b/src/plugins/qmljsinspector/qmlinspectortoolbar.h
@@ -40,6 +40,7 @@
QT_FORWARD_DECLARE_CLASS(QAction)
QT_FORWARD_DECLARE_CLASS(QColor)
QT_FORWARD_DECLARE_CLASS(QToolButton)
+
namespace Core {
class Context;
}
@@ -83,12 +84,11 @@ public slots:
void activateZoomTool();
void setAnimationSpeed(qreal slowdownFactor);
void setDesignModeBehavior(bool inDesignMode);
+ void setShowAppOnTop(bool showAppOnTop);
void setSelectedColor(const QColor &color);
- void setLivePreviewChecked(bool value);
-
signals:
- void animationSpeedChanged(qreal slowdownFactor = 1.0f);
+ void applyChangesFromQmlFileTriggered(bool isChecked);
void designModeSelected(bool checked);
void reloadSelected();
@@ -96,8 +96,8 @@ signals:
void selectToolSelected();
void zoomToolSelected();
- void applyChangesToQmlFileSelected();
- void applyChangesFromQmlFileTriggered(bool isChecked);
+ void showAppOnTopSelected(bool isChecked);
+ void animationSpeedChanged(qreal slowdownFactor = 1.0f);
private slots:
void activateDesignModeOnClick();
@@ -106,6 +106,8 @@ private slots:
void activateSelectToolOnClick();
void activateZoomOnClick();
+ void showAppOnTopClick();
+
void changeToDefaultAnimSpeed();
void changeToHalfAnimSpeed();
void changeToFourthAnimSpeed();
@@ -113,20 +115,19 @@ private slots:
void changeToTenthAnimSpeed();
void activateFromQml();
- void activateToQml();
void updatePlayAction();
void updatePauseAction();
private:
+ QAction *m_fromQmlAction;
QAction *m_observerModeAction;
-// QAction *m_reloadAction;
QAction *m_playAction;
QAction *m_selectAction;
QAction *m_zoomAction;
QAction *m_colorPickerAction;
- QAction *m_toQmlAction;
- QAction *m_fromQmlAction;
+
+ QAction *m_showAppOnTopAction;
QAction *m_defaultAnimSpeedAction;
QAction *m_halfAnimSpeedAction;
@@ -149,8 +150,6 @@ private:
DesignTool m_activeTool;
Utils::StyledBar *m_barWidget;
- Utils::FilterLineEdit *m_filterLineEdit;
-
};
} // namespace Internal
diff --git a/src/plugins/qmljsinspector/qmljsclientproxy.cpp b/src/plugins/qmljsinspector/qmljsclientproxy.cpp
index 83ae3768d5..3f10321e3b 100644
--- a/src/plugins/qmljsinspector/qmljsclientproxy.cpp
+++ b/src/plugins/qmljsinspector/qmljsclientproxy.cpp
@@ -57,48 +57,49 @@ using namespace QmlJSInspector::Internal;
ClientProxy::ClientProxy(Debugger::QmlAdapter *adapter, QObject *parent)
: QObject(parent)
, m_adapter(adapter)
- , m_client(m_adapter->client())
- , m_designClient(0)
+ , m_engineClient(m_adapter->client())
+ , m_observerClient(0)
, m_engineQuery(0)
, m_contextQuery(0)
, m_isConnected(false)
{
m_requestObjectsTimer.setSingleShot(true);
m_requestObjectsTimer.setInterval(3000);
- connect(m_client, SIGNAL(newObjects()), this, SLOT(newObjects()));
+ connect(m_engineClient, SIGNAL(newObjects()), this, SLOT(newObjects()));
connect(&m_requestObjectsTimer, SIGNAL(timeout()), this, SLOT(refreshObjectTree()));
connectToServer();
}
void ClientProxy::connectToServer()
{
- m_designClient = new QmlJSObserverClient(m_adapter->connection(), this);
+ m_observerClient = new QmlJSObserverClient(m_adapter->connection(), this);
-
- m_adapter->logServiceStatusChange(m_designClient->name(), m_designClient->status());
-
- connect(m_designClient, SIGNAL(connectedStatusChanged(QDeclarativeDebugClient::Status)),
+ connect(m_observerClient, SIGNAL(connectedStatusChanged(QDeclarativeDebugClient::Status)),
this, SLOT(clientStatusChanged(QDeclarativeDebugClient::Status)));
- connect(m_designClient, SIGNAL(currentObjectsChanged(QList<int>)),
+ connect(m_observerClient, SIGNAL(currentObjectsChanged(QList<int>)),
SLOT(onCurrentObjectsChanged(QList<int>)));
- connect(m_designClient, SIGNAL(colorPickerActivated()),
+ connect(m_observerClient, SIGNAL(colorPickerActivated()),
SIGNAL(colorPickerActivated()));
- connect(m_designClient, SIGNAL(zoomToolActivated()),
+ connect(m_observerClient, SIGNAL(zoomToolActivated()),
SIGNAL(zoomToolActivated()));
- connect(m_designClient, SIGNAL(selectToolActivated()),
+ connect(m_observerClient, SIGNAL(selectToolActivated()),
SIGNAL(selectToolActivated()));
- connect(m_designClient, SIGNAL(selectMarqueeToolActivated()),
+ connect(m_observerClient, SIGNAL(selectMarqueeToolActivated()),
SIGNAL(selectMarqueeToolActivated()));
- connect(m_designClient, SIGNAL(animationSpeedChanged(qreal)),
+ connect(m_observerClient, SIGNAL(animationSpeedChanged(qreal)),
SIGNAL(animationSpeedChanged(qreal)));
- connect(m_designClient, SIGNAL(designModeBehaviorChanged(bool)),
+ connect(m_observerClient, SIGNAL(designModeBehaviorChanged(bool)),
SIGNAL(designModeBehaviorChanged(bool)));
- connect(m_designClient, SIGNAL(reloaded()), this,
+ connect(m_observerClient, SIGNAL(showAppOnTopChanged(bool)),
+ SIGNAL(showAppOnTopChanged(bool)));
+ connect(m_observerClient, SIGNAL(reloaded()), this,
SIGNAL(serverReloaded()));
- connect(m_designClient, SIGNAL(selectedColorChanged(QColor)),
+ connect(m_observerClient, SIGNAL(selectedColorChanged(QColor)),
SIGNAL(selectedColorChanged(QColor)));
- connect(m_designClient, SIGNAL(contextPathUpdated(QStringList)),
+ connect(m_observerClient, SIGNAL(contextPathUpdated(QStringList)),
SIGNAL(contextPathUpdated(QStringList)));
+ connect(m_observerClient, SIGNAL(logActivity(QString,QString)),
+ m_adapter, SLOT(logServiceActivity(QString,QString)));
updateConnected();
}
@@ -117,30 +118,32 @@ void ClientProxy::clientStatusChanged(QDeclarativeDebugClient::Status status)
void ClientProxy::disconnectFromServer()
{
- if (m_designClient) {
- disconnect(m_designClient, SIGNAL(connectedStatusChanged(QDeclarativeDebugClient::Status)),
+ if (m_observerClient) {
+ disconnect(m_observerClient, SIGNAL(connectedStatusChanged(QDeclarativeDebugClient::Status)),
this, SLOT(clientStatusChanged(QDeclarativeDebugClient::Status)));
- disconnect(m_designClient, SIGNAL(currentObjectsChanged(QList<int>)),
+ disconnect(m_observerClient, SIGNAL(currentObjectsChanged(QList<int>)),
this, SLOT(onCurrentObjectsChanged(QList<int>)));
- disconnect(m_designClient, SIGNAL(colorPickerActivated()),
+ disconnect(m_observerClient, SIGNAL(colorPickerActivated()),
this, SIGNAL(colorPickerActivated()));
- disconnect(m_designClient, SIGNAL(zoomToolActivated()),
+ disconnect(m_observerClient, SIGNAL(zoomToolActivated()),
this, SIGNAL(zoomToolActivated()));
- disconnect(m_designClient, SIGNAL(selectToolActivated()),
+ disconnect(m_observerClient, SIGNAL(selectToolActivated()),
this, SIGNAL(selectToolActivated()));
- disconnect(m_designClient, SIGNAL(selectMarqueeToolActivated()),
+ disconnect(m_observerClient, SIGNAL(selectMarqueeToolActivated()),
this, SIGNAL(selectMarqueeToolActivated()));
- disconnect(m_designClient, SIGNAL(animationSpeedChanged(qreal)),
+ disconnect(m_observerClient, SIGNAL(animationSpeedChanged(qreal)),
this, SIGNAL(animationSpeedChanged(qreal)));
- disconnect(m_designClient, SIGNAL(designModeBehaviorChanged(bool)),
+ disconnect(m_observerClient, SIGNAL(designModeBehaviorChanged(bool)),
this, SIGNAL(designModeBehaviorChanged(bool)));
- disconnect(m_designClient, SIGNAL(selectedColorChanged(QColor)),
+ disconnect(m_observerClient, SIGNAL(selectedColorChanged(QColor)),
this, SIGNAL(selectedColorChanged(QColor)));
- disconnect(m_designClient, SIGNAL(contextPathUpdated(QStringList)),
+ disconnect(m_observerClient, SIGNAL(contextPathUpdated(QStringList)),
this, SIGNAL(contextPathUpdated(QStringList)));
+ disconnect(m_observerClient, SIGNAL(logActivity(QString,QString)),
+ m_adapter, SLOT(logServiceActivity(QString,QString)));
- delete m_designClient;
- m_designClient = 0;
+ delete m_observerClient;
+ m_observerClient = 0;
}
if (m_engineQuery)
@@ -167,7 +170,7 @@ void ClientProxy::refreshObjectTree()
}
}
-void ClientProxy::onCurrentObjectsChanged(const QList< int >& debugIds, bool requestIfNeeded)
+void ClientProxy::onCurrentObjectsChanged(const QList<int> &debugIds, bool requestIfNeeded)
{
QList<QDeclarativeDebugObjectReference> selectedItems;
@@ -191,8 +194,15 @@ void ClientProxy::onCurrentObjectsChanged(const QList< int >& debugIds, bool req
void ClientProxy::setSelectedItemsByObjectId(const QList<QDeclarativeDebugObjectReference> &objectRefs)
{
- if (isConnected())
- m_designClient->setSelectedItemsByObjectId(objectRefs);
+ if (isConnected()) {
+ QList<int> debugIds;
+
+ foreach (const QDeclarativeDebugObjectReference &ref, objectRefs) {
+ debugIds << ref.debugId();
+ }
+
+ m_observerClient->setCurrentObjects(debugIds);
+ }
}
QDeclarativeDebugObjectReference ClientProxy::objectReferenceForId(int debugId) const
@@ -282,7 +292,7 @@ bool ClientProxy::setBindingForObject(int objectDebugId,
if (propertyName == QLatin1String("id"))
return false; // Crashes the QMLViewer.
- bool result = m_client->setBindingForObject(objectDebugId, propertyName, value.toString(), isLiteralValue);
+ bool result = m_engineClient->setBindingForObject(objectDebugId, propertyName, value.toString(), isLiteralValue);
return result;
}
@@ -293,7 +303,7 @@ bool ClientProxy::setMethodBodyForObject(int objectDebugId, const QString &metho
qDebug() << "setMethodBodyForObject():" << objectDebugId << methodName << methodBody;
if (objectDebugId == -1)
return 0;
- return m_client->setMethodBody(objectDebugId, methodName, methodBody);
+ return m_engineClient->setMethodBody(objectDebugId, methodName, methodBody);
}
bool ClientProxy::resetBindingForObject(int objectDebugId, const QString& propertyName)
@@ -303,7 +313,7 @@ bool ClientProxy::resetBindingForObject(int objectDebugId, const QString& proper
if (objectDebugId == -1)
return false;
// if (propertyName == QLatin1String("id")) return false;
- return m_client->resetBindingForObject(objectDebugId, propertyName);
+ return m_engineClient->resetBindingForObject(objectDebugId, propertyName);
}
QDeclarativeDebugExpressionQuery *ClientProxy::queryExpressionResult(int objectDebugId, const QString &expr, QObject *parent)
@@ -311,14 +321,14 @@ QDeclarativeDebugExpressionQuery *ClientProxy::queryExpressionResult(int objectD
if (debug)
qDebug() << "queryExpressionResult():" << objectDebugId << expr << parent;
if (objectDebugId != -1)
- return m_client->queryExpressionResult(objectDebugId,expr,parent);
+ return m_engineClient->queryExpressionResult(objectDebugId,expr,parent);
return 0;
}
void ClientProxy::clearComponentCache()
{
if (isConnected())
- m_designClient->clearComponentCache();
+ m_observerClient->clearComponentCache();
}
void ClientProxy::queryEngineContext(int id)
@@ -331,7 +341,7 @@ void ClientProxy::queryEngineContext(int id)
m_contextQuery = 0;
}
- m_contextQuery = m_client->queryRootContexts(QDeclarativeDebugEngineReference(id), this);
+ m_contextQuery = m_engineClient->queryRootContexts(QDeclarativeDebugEngineReference(id), this);
if (!m_contextQuery->isWaiting())
contextChanged();
else
@@ -351,14 +361,14 @@ void ClientProxy::contextChanged()
m_objectTreeQuery.clear();
m_requestObjectsTimer.stop();
- fetchContextObjectRecusrsive(rootContext);
+ fetchContextObjectRecursive(rootContext);
}
}
-void ClientProxy::fetchContextObjectRecusrsive(const QDeclarativeDebugContextReference& context)
+void ClientProxy::fetchContextObjectRecursive(const QDeclarativeDebugContextReference& context)
{
foreach (const QDeclarativeDebugObjectReference & obj, context.objects()) {
- QDeclarativeDebugObjectQuery* query = m_client->queryObjectRecursive(obj, this);
+ QDeclarativeDebugObjectQuery* query = m_engineClient->queryObjectRecursive(obj, this);
if (!query->isWaiting()) {
query->deleteLater(); //ignore errors;
} else {
@@ -369,7 +379,7 @@ void ClientProxy::fetchContextObjectRecusrsive(const QDeclarativeDebugContextRef
}
}
foreach (const QDeclarativeDebugContextReference& child, context.contexts()) {
- fetchContextObjectRecusrsive(child);
+ fetchContextObjectRecursive(child);
}
}
@@ -398,10 +408,10 @@ void ClientProxy::objectTreeFetched(QDeclarativeDebugQuery::State state)
emit objectTreeUpdated();
if (isConnected()) {
- if (!m_designClient->selectedItemIds().isEmpty())
- onCurrentObjectsChanged(m_designClient->selectedItemIds(), false);
+ if (!m_observerClient->currentObjects().isEmpty())
+ onCurrentObjectsChanged(m_observerClient->currentObjects(), false);
- m_designClient->setObjectIdList(m_rootObjects);
+ m_observerClient->setObjectIdList(m_rootObjects);
}
}
}
@@ -414,7 +424,7 @@ void ClientProxy::buildDebugIdHashRecursive(const QDeclarativeDebugObjectReferen
int rev = 0;
// handle the case where the url contains the revision number encoded. (for object created by the debugger)
- static QRegExp rx("^file://(.*)_(\\d+):(\\d+)$");
+ static QRegExp rx("(.*)_(\\d+):(\\d+)$");
if (rx.exactMatch(filename)) {
filename = rx.cap(1);
rev = rx.cap(2).toInt();
@@ -443,73 +453,79 @@ void ClientProxy::buildDebugIdHashRecursive(const QDeclarativeDebugObjectReferen
void ClientProxy::reloadQmlViewer()
{
if (isConnected())
- m_designClient->reloadViewer();
+ m_observerClient->reloadViewer();
}
void ClientProxy::setDesignModeBehavior(bool inDesignMode)
{
if (isConnected())
- m_designClient->setDesignModeBehavior(inDesignMode);
+ m_observerClient->setDesignModeBehavior(inDesignMode);
}
void ClientProxy::setAnimationSpeed(qreal slowdownFactor)
{
if (isConnected())
- m_designClient->setAnimationSpeed(slowdownFactor);
+ m_observerClient->setAnimationSpeed(slowdownFactor);
}
void ClientProxy::changeToColorPickerTool()
{
if (isConnected())
- m_designClient->changeToColorPickerTool();
+ m_observerClient->changeToColorPickerTool();
}
void ClientProxy::changeToZoomTool()
{
if (isConnected())
- m_designClient->changeToZoomTool();
+ m_observerClient->changeToZoomTool();
}
void ClientProxy::changeToSelectTool()
{
if (isConnected())
- m_designClient->changeToSelectTool();
+ m_observerClient->changeToSelectTool();
}
void ClientProxy::changeToSelectMarqueeTool()
{
if (isConnected())
- m_designClient->changeToSelectMarqueeTool();
+ m_observerClient->changeToSelectMarqueeTool();
+}
+
+void ClientProxy::showAppOnTop(bool showOnTop)
+{
+ if (isConnected())
+ m_observerClient->showAppOnTop(showOnTop);
}
void ClientProxy::createQmlObject(const QString &qmlText, int parentDebugId,
const QStringList &imports, const QString &filename)
{
if (isConnected())
- m_designClient->createQmlObject(qmlText, parentDebugId, imports, filename);
+ m_observerClient->createQmlObject(qmlText, parentDebugId, imports, filename);
}
void ClientProxy::destroyQmlObject(int debugId)
{
if (isConnected())
- m_designClient->destroyQmlObject(debugId);
+ m_observerClient->destroyQmlObject(debugId);
}
void ClientProxy::reparentQmlObject(int debugId, int newParent)
{
if (isConnected())
- m_designClient->reparentQmlObject(debugId, newParent);
+ m_observerClient->reparentQmlObject(debugId, newParent);
}
void ClientProxy::setContextPathIndex(int contextIndex)
{
if (isConnected())
- m_designClient->setContextPathIndex(contextIndex);
+ m_observerClient->setContextPathIndex(contextIndex);
}
void ClientProxy::updateConnected()
{
- bool isConnected = m_designClient && m_designClient->status() == QDeclarativeDebugClient::Enabled
- && m_client && m_client->status() == QDeclarativeEngineDebug::Enabled;
+ bool isConnected = m_observerClient && m_observerClient->status() == QDeclarativeDebugClient::Enabled
+ && m_engineClient && m_engineClient->status() == QDeclarativeEngineDebug::Enabled;
if (isConnected != m_isConnected) {
m_isConnected = isConnected;
@@ -531,7 +547,7 @@ void ClientProxy::reloadEngines()
emit aboutToReloadEngines();
- m_engineQuery = m_client->queryAvailableEngines(this);
+ m_engineQuery = m_engineClient->queryAvailableEngines(this);
if (!m_engineQuery->isWaiting())
updateEngineList();
else
diff --git a/src/plugins/qmljsinspector/qmljsclientproxy.h b/src/plugins/qmljsinspector/qmljsclientproxy.h
index 0ba91d2d24..5038f334ca 100644
--- a/src/plugins/qmljsinspector/qmljsclientproxy.h
+++ b/src/plugins/qmljsinspector/qmljsclientproxy.h
@@ -104,6 +104,7 @@ signals:
void zoomToolActivated();
void animationSpeedChanged(qreal slowdownFactor);
void designModeBehaviorChanged(bool inDesignMode);
+ void showAppOnTopChanged(bool showAppOnTop);
void serverReloaded();
void selectedColorChanged(const QColor &color);
void contextPathUpdated(const QStringList &contextPath);
@@ -119,6 +120,7 @@ public slots:
void changeToZoomTool();
void changeToSelectTool();
void changeToSelectMarqueeTool();
+ void showAppOnTop(bool showOnTop);
void createQmlObject(const QString &qmlText, int parentDebugId,
const QStringList &imports, const QString &filename = QString());
void destroyQmlObject(int debugId);
@@ -135,7 +137,7 @@ private slots:
void onCurrentObjectsChanged(const QList<int> &debugIds, bool requestIfNeeded = true);
void updateEngineList();
void objectTreeFetched(QDeclarativeDebugQuery::State state = QDeclarativeDebugQuery::Completed);
- void fetchContextObjectRecusrsive(const QmlJsDebugClient::QDeclarativeDebugContextReference& context);
+ void fetchContextObjectRecursive(const QmlJsDebugClient::QDeclarativeDebugContextReference& context);
void newObjects();
private:
@@ -146,12 +148,12 @@ private:
QDeclarativeDebugObjectReference objectReferenceForId(int debugId, const QDeclarativeDebugObjectReference &ref) const;
private:
- Q_DISABLE_COPY(ClientProxy);
+ Q_DISABLE_COPY(ClientProxy)
void buildDebugIdHashRecursive(const QDeclarativeDebugObjectReference &ref);
Debugger::QmlAdapter *m_adapter;
- QDeclarativeEngineDebug *m_client;
- QmlJSObserverClient *m_designClient;
+ QDeclarativeEngineDebug *m_engineClient;
+ QmlJSObserverClient *m_observerClient;
QDeclarativeDebugEnginesQuery *m_engineQuery;
QDeclarativeDebugRootContextQuery *m_contextQuery;
diff --git a/src/plugins/qmljsinspector/qmljsinspector.cpp b/src/plugins/qmljsinspector/qmljsinspector.cpp
index 3445c5c6e7..c879645db3 100644
--- a/src/plugins/qmljsinspector/qmljsinspector.cpp
+++ b/src/plugins/qmljsinspector/qmljsinspector.cpp
@@ -30,6 +30,7 @@
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
+
#include "qmljsinspectorconstants.h"
#include "qmljsinspector.h"
#include "qmlinspectortoolbar.h"
@@ -40,29 +41,19 @@
#include "qmljsinspectorsettings.h"
#include "qmljsobjecttree.h"
-#include <qmljseditor/qmljseditorconstants.h>
-
-#include <qmljseditor/qmljseditor.h>
#include <qmljs/qmljsmodelmanagerinterface.h>
#include <qmljs/qmljsdocument.h>
-
#include <qmljs/parser/qmljsast_p.h>
-#include <debugger/debuggerrunner.h>
+#include <qmljseditor/qmljseditorconstants.h>
+#include <qmljseditor/qmljseditor.h>
#include <debugger/debuggerconstants.h>
-#include <debugger/debuggerengine.h>
#include <debugger/debuggermainwindow.h>
#include <debugger/debuggerplugin.h>
-#include <debugger/debuggerrunner.h>
-#include <debugger/debuggeruiswitcher.h>
-#include <debugger/debuggerconstants.h>
-#include <debugger/qml/qmlengine.h>
#include <utils/qtcassert.h>
#include <utils/styledbar.h>
-#include <utils/fancymainwindow.h>
#include <coreplugin/icontext.h>
-#include <coreplugin/basemode.h>
#include <coreplugin/findplaceholder.h>
#include <coreplugin/minisplitter.h>
#include <coreplugin/outputpane.h>
@@ -114,7 +105,6 @@
using namespace QmlJS;
using namespace QmlJS::AST;
using namespace QmlJSInspector::Internal;
-using namespace Debugger::Internal;
enum {
MaxConnectionAttempts = 50,
@@ -137,11 +127,11 @@ InspectorUi::InspectorUi(QObject *parent)
, m_toolbar(0)
, m_crumblePath(0)
, m_objectTreeWidget(0)
- , m_inspectorDockWidget(0)
, m_settings(new InspectorSettings(this))
, m_clientProxy(0)
, m_qmlEngine(0)
, m_debugQuery(0)
+ , m_lastSelectedDebugId(-1)
, m_debugProject(0)
{
m_instance = this;
@@ -168,30 +158,34 @@ void InspectorUi::restoreSettings()
m_settings->restoreSettings(Core::ICore::instance()->settings());
}
-void InspectorUi::setDebuggerEngine(Debugger::QmlEngine *qmlEngine)
+void InspectorUi::setDebuggerEngine(QObject *qmlEngine)
{
if (m_qmlEngine && !qmlEngine) {
- disconnect(m_qmlEngine, SIGNAL(tooltipRequested(QPoint, TextEditor::ITextEditor*, int)),
- this, SLOT(showDebuggerTooltip(QPoint, TextEditor::ITextEditor*, int)));
+ disconnect(m_qmlEngine,
+ SIGNAL(tooltipRequested(QPoint,TextEditor::ITextEditor*,int)),
+ this, SLOT(showDebuggerTooltip(QPoint,TextEditor::ITextEditor*,int)));
}
m_qmlEngine = qmlEngine;
if (m_qmlEngine) {
- connect(m_qmlEngine, SIGNAL(tooltipRequested(QPoint, TextEditor::ITextEditor*, int)),
- this, SLOT(showDebuggerTooltip(QPoint, TextEditor::ITextEditor*, int)));
+ connect(m_qmlEngine,
+ SIGNAL(tooltipRequested(QPoint,TextEditor::ITextEditor*,int)),
+ this, SLOT(showDebuggerTooltip(QPoint,TextEditor::ITextEditor*,int)));
}
}
-Debugger::QmlEngine *InspectorUi::debuggerEngine() const
+QObject *InspectorUi::debuggerEngine() const
{
return m_qmlEngine;
}
-void InspectorUi::showDebuggerTooltip(const QPoint &mousePos, TextEditor::ITextEditor *editor, int cursorPos)
+void InspectorUi::showDebuggerTooltip(const QPoint &mousePos, TextEditor::ITextEditor *editor,
+ int cursorPos)
{
Q_UNUSED(mousePos);
if (m_clientProxy && editor->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID) {
- QmlJSEditor::Internal::QmlJSTextEditor *qmlEditor = static_cast<QmlJSEditor::Internal::QmlJSTextEditor*>(editor->widget());
+ QmlJSEditor::QmlJSTextEditor *qmlEditor =
+ static_cast<QmlJSEditor::QmlJSTextEditor*>(editor->widget());
QTextCursor tc(qmlEditor->document());
tc.setPosition(cursorPos);
@@ -223,27 +217,32 @@ void InspectorUi::showDebuggerTooltip(const QPoint &mousePos, TextEditor::ITextE
query = QString("\"id:") + ref.idString() + doubleQuote;
} else {
if ((qmlNode->kind == QmlJS::AST::Node::Kind_IdentifierExpression) ||
- (qmlNode->kind == QmlJS::AST::Node::Kind_FieldMemberExpression)) {
+ (qmlNode->kind == QmlJS::AST::Node::Kind_FieldMemberExpression)) {
tc.setPosition(qmlNode->expressionCast()->firstSourceLocation().begin());
- tc.setPosition(qmlNode->expressionCast()->lastSourceLocation().end(),QTextCursor::KeepAnchor);
+ tc.setPosition(qmlNode->expressionCast()->lastSourceLocation().end(),
+ QTextCursor::KeepAnchor);
QString refToLook = tc.selectedText();
if ((qmlNode->kind == QmlJS::AST::Node::Kind_IdentifierExpression) &&
- (m_clientProxy->objectReferenceForId(refToLook).debugId() == -1)) {
+ (m_clientProxy->objectReferenceForId(refToLook).debugId() == -1)) {
query = doubleQuote + QString("local: ") + refToLook + doubleQuote;
foreach(QDeclarativeDebugPropertyReference property, ref.properties()) {
- if (property.name() == wordAtCursor && !property.valueTypeName().isEmpty()) {
- query = doubleQuote + property.name() + QLatin1Char(':') + doubleQuote + QLatin1Char('+') + property.name();
+ if (property.name() == wordAtCursor
+ && !property.valueTypeName().isEmpty()) {
+ query = doubleQuote + property.name() + QLatin1Char(':')
+ + doubleQuote + QLatin1Char('+') + property.name();
break;
}
}
}
else
- query =doubleQuote + refToLook + QLatin1Char(':') + doubleQuote + QLatin1Char('+') + refToLook;
+ query = doubleQuote + refToLook + QLatin1Char(':') + doubleQuote
+ + QLatin1Char('+') + refToLook;
} else {
// show properties
foreach(QDeclarativeDebugPropertyReference property, ref.properties()) {
if (property.name() == wordAtCursor && !property.valueTypeName().isEmpty()) {
- query = doubleQuote + property.name() + QLatin1Char(':') + doubleQuote + QLatin1Char('+') + property.name();
+ query = doubleQuote + property.name() + QLatin1Char(':')
+ + doubleQuote + QLatin1Char('+') + property.name();
break;
}
}
@@ -252,7 +251,8 @@ void InspectorUi::showDebuggerTooltip(const QPoint &mousePos, TextEditor::ITextE
if (!query.isEmpty()) {
m_debugQuery = m_clientProxy->queryExpressionResult(ref.debugId(),query);
- connect(m_debugQuery,SIGNAL(stateChanged(QDeclarativeDebugQuery::State)),this,SLOT(debugQueryUpdated(QDeclarativeDebugQuery::State)));
+ connect(m_debugQuery, SIGNAL(stateChanged(QDeclarativeDebugQuery::State)),
+ this, SLOT(debugQueryUpdated(QDeclarativeDebugQuery::State)));
}
}
}
@@ -268,7 +268,8 @@ void InspectorUi::debugQueryUpdated(QDeclarativeDebugQuery::State newState)
if (!text.isEmpty())
QToolTip::showText(QCursor::pos(), text);
- disconnect(m_debugQuery,SIGNAL(stateChanged(QDeclarativeDebugQuery::State)),this,SLOT(debugQueryUpdated(QDeclarativeDebugQuery::State)));
+ disconnect(m_debugQuery, SIGNAL(stateChanged(QDeclarativeDebugQuery::State)),
+ this, SLOT(debugQueryUpdated(QDeclarativeDebugQuery::State)));
}
bool InspectorUi::isConnected() const
@@ -281,7 +282,7 @@ void InspectorUi::connected(ClientProxy *clientProxy)
m_clientProxy = clientProxy;
connect(m_clientProxy, SIGNAL(selectedItemsChanged(QList<QDeclarativeDebugObjectReference>)),
- SLOT(setSelectedItemsByObjectReference(QList<QDeclarativeDebugObjectReference>)));
+ SLOT(gotoObjectReferenceDefinition(QList<QDeclarativeDebugObjectReference>)));
connect(m_clientProxy, SIGNAL(enginesChanged()), SLOT(updateEngineList()));
connect(m_clientProxy, SIGNAL(serverReloaded()), this, SLOT(serverReloaded()));
@@ -290,13 +291,15 @@ void InspectorUi::connected(ClientProxy *clientProxy)
m_debugProject = ProjectExplorer::ProjectExplorerPlugin::instance()->startupProject();
if (m_debugProject->activeTarget()
- && m_debugProject->activeTarget()->activeBuildConfiguration())
+ && m_debugProject->activeTarget()->activeBuildConfiguration())
{
- ProjectExplorer::BuildConfiguration *bc = m_debugProject->activeTarget()->activeBuildConfiguration();
+ ProjectExplorer::BuildConfiguration *bc
+ = m_debugProject->activeTarget()->activeBuildConfiguration();
m_debugProjectBuildDir = bc->buildDirectory();
}
connect(m_debugProject, SIGNAL(destroyed()), SLOT(currentDebugProjectRemoved()));
+ m_projectFinder.setProjectDirectory(m_debugProject->projectDirectory());
setupToolbar(true);
resetViews();
@@ -314,7 +317,7 @@ void InspectorUi::connected(ClientProxy *clientProxy)
void InspectorUi::disconnected()
{
disconnect(m_clientProxy, SIGNAL(selectedItemsChanged(QList<QDeclarativeDebugObjectReference>)),
- this, SLOT(setSelectedItemsByObjectReference(QList<QDeclarativeDebugObjectReference>)));
+ this, SLOT(gotoObjectReferenceDefinition(QList<QDeclarativeDebugObjectReference>)));
disconnect(m_clientProxy, SIGNAL(enginesChanged()), this, SLOT(updateEngineList()));
disconnect(m_clientProxy, SIGNAL(serverReloaded()), this, SLOT(serverReloaded()));
@@ -354,6 +357,18 @@ void InspectorUi::updateEngineList()
void InspectorUi::changeSelectedItems(const QList<QDeclarativeDebugObjectReference> &objects)
{
+ if (m_lastSelectedDebugId >= 0) {
+ foreach (const QDeclarativeDebugObjectReference &ref, objects) {
+ if (ref.debugId() == m_lastSelectedDebugId) {
+ // this is only the 'call back' after we have programatically set a new cursor
+ // position in
+ m_lastSelectedDebugId = -1;
+ return;
+ }
+ }
+ m_lastSelectedDebugId = -1;
+ }
+
m_clientProxy->setSelectedItemsByObjectId(objects);
}
@@ -367,11 +382,13 @@ void InspectorUi::initializeDocuments()
if (!m_listeningToEditorManager) {
m_listeningToEditorManager = true;
- connect(em, SIGNAL(editorAboutToClose(Core::IEditor*)), SLOT(removePreviewForEditor(Core::IEditor*)));
- connect(em, SIGNAL(editorOpened(Core::IEditor*)), SLOT(createPreviewForEditor(Core::IEditor*)));
+ connect(em, SIGNAL(editorAboutToClose(Core::IEditor*)),
+ this, SLOT(removePreviewForEditor(Core::IEditor*)));
+ connect(em, SIGNAL(editorOpened(Core::IEditor*)),
+ this, SLOT(createPreviewForEditor(Core::IEditor*)));
connect(modelManager(),
SIGNAL(documentChangedOnDisk(QmlJS::Document::Ptr)),
- SLOT(updatePendingPreviewDocuments(QmlJS::Document::Ptr)));
+ this, SLOT(updatePendingPreviewDocuments(QmlJS::Document::Ptr)));
}
// initial update
@@ -407,10 +424,10 @@ QmlJSLiveTextPreview *InspectorUi::createPreviewForEditor(Core::IEditor *newEdit
QmlJSLiveTextPreview *preview = 0;
if (m_clientProxy
- && m_clientProxy->isConnected()
- && newEditor
- && newEditor->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID
- )
+ && m_clientProxy->isConnected()
+ && newEditor
+ && newEditor->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID
+ )
{
QString filename = newEditor->file()->fileName();
QmlJS::Document::Ptr doc = modelManager()->snapshot().document(filename);
@@ -437,7 +454,8 @@ QmlJSLiveTextPreview *InspectorUi::createPreviewForEditor(Core::IEditor *newEdit
connect(preview,
SIGNAL(selectedItemsChanged(QList<QDeclarativeDebugObjectReference>)),
SLOT(changeSelectedItems(QList<QDeclarativeDebugObjectReference>)));
- connect(preview, SIGNAL(reloadQmlViewerRequested()), m_clientProxy, SLOT(reloadQmlViewer()));
+ connect(preview, SIGNAL(reloadQmlViewerRequested()),
+ m_clientProxy, SLOT(reloadQmlViewer()));
connect(preview, SIGNAL(disableLivePreviewRequested()), SLOT(disableLivePreview()));
m_textPreviews.insert(newEditor->file()->fileName(), preview);
@@ -465,52 +483,8 @@ void InspectorUi::reloadQmlViewer()
m_clientProxy->reloadQmlViewer();
}
-void InspectorUi::setSimpleDockWidgetArrangement(const Debugger::DebuggerLanguages &activeLanguages)
-{
- Debugger::DebuggerUISwitcher *uiSwitcher = Debugger::DebuggerUISwitcher::instance();
- Utils::FancyMainWindow *mw = uiSwitcher->mainWindow();
-
- mw->setTrackingEnabled(false);
-
- if (activeLanguages.testFlag(Debugger::CppLanguage) && activeLanguages.testFlag(Debugger::QmlLanguage)) {
- // cpp + qml
- QList<QDockWidget *> dockWidgets = mw->dockWidgets();
- foreach (QDockWidget *dockWidget, dockWidgets) {
- dockWidget->setFloating(false);
- mw->removeDockWidget(dockWidget);
- }
- foreach (QDockWidget *dockWidget, dockWidgets) {
- if (dockWidget == uiSwitcher->outputWindow()) {
- mw->addDockWidget(Qt::TopDockWidgetArea, dockWidget);
- } else {
- mw->addDockWidget(Qt::BottomDockWidgetArea, dockWidget);
- }
-
- if (dockWidget == m_inspectorDockWidget) {
- dockWidget->show();
- } else {
- dockWidget->hide();
- }
- }
-
- uiSwitcher->stackWindow()->show();
- uiSwitcher->watchWindow()->show();
- uiSwitcher->breakWindow()->show();
- uiSwitcher->threadsWindow()->show();
- uiSwitcher->snapshotsWindow()->show();
- m_inspectorDockWidget->show();
-
- mw->splitDockWidget(mw->toolBarDockWidget(), uiSwitcher->stackWindow(), Qt::Vertical);
- mw->splitDockWidget(uiSwitcher->stackWindow(), uiSwitcher->watchWindow(), Qt::Horizontal);
- mw->tabifyDockWidget(uiSwitcher->watchWindow(), uiSwitcher->breakWindow());
- mw->tabifyDockWidget(uiSwitcher->watchWindow(), m_inspectorDockWidget);
-
- }
-
- mw->setTrackingEnabled(true);
-}
-
-void InspectorUi::setSelectedItemsByObjectReference(QList<QDeclarativeDebugObjectReference> objectReferences)
+void InspectorUi::gotoObjectReferenceDefinition(QList<QDeclarativeDebugObjectReference>
+ objectReferences)
{
if (objectReferences.length())
gotoObjectReferenceDefinition(objectReferences.first());
@@ -540,53 +514,21 @@ void InspectorUi::gotoObjectReferenceDefinition(const QDeclarativeDebugObjectRef
if (source.lineNumber() < 0 || !QFile::exists(fileName))
return;
-
- // do some extra checking for filenames with shadow builds - we don't want to
- // open the shadow build file, but the real one by default.
- if (isShadowBuildProject()) {
- fileName = filenameForShadowBuildFile(fileName);
- }
+ fileName = m_projectFinder.findFile(fileName);
Core::EditorManager *editorManager = Core::EditorManager::instance();
Core::IEditor *editor = editorManager->openEditor(fileName);
TextEditor::ITextEditor *textEditor = qobject_cast<TextEditor::ITextEditor*>(editor);
if (textEditor) {
+ m_lastSelectedDebugId = obj.debugId();
+
editorManager->addCurrentPositionToNavigationHistory();
textEditor->gotoLine(source.lineNumber());
textEditor->widget()->setFocus();
}
}
-QString InspectorUi::filenameForShadowBuildFile(const QString &filename) const
-{
- if (!debugProject() || !isShadowBuildProject())
- return filename;
-
- QDir projectDir(debugProject()->projectDirectory());
- QDir buildDir(debugProjectBuildDirectory());
- QFileInfo fileInfo(filename);
-
- if (projectDir.exists() && buildDir.exists() && fileInfo.exists()) {
- if (fileInfo.absoluteFilePath().startsWith(buildDir.canonicalPath())) {
- QString fileRelativePath = fileInfo.canonicalFilePath().mid(debugProjectBuildDirectory().length());
-
-#ifdef Q_OS_MACX
- // Qt Quick Applications by default copy the qml directory to buildDir()/X.app/Contents/Resources
- static QRegExp resourceBundlePattern(QLatin1String("^.*\\.app/Contents/Resources/"));
- fileRelativePath.remove(resourceBundlePattern);
-#endif
-
- QFileInfo projectFile(projectDir.canonicalPath() + QLatin1Char('/') + fileRelativePath);
-
- if (projectFile.exists())
- return projectFile.canonicalFilePath();
- }
-
- }
- return filename;
-}
-
bool InspectorUi::addQuotesForData(const QVariant &value) const
{
switch (value.type()) {
@@ -603,8 +545,6 @@ bool InspectorUi::addQuotesForData(const QVariant &value) const
void InspectorUi::setupDockWidgets()
{
- Debugger::DebuggerUISwitcher *uiSwitcher = Debugger::DebuggerUISwitcher::instance();
-
m_toolbar->createActions(Core::Context(Debugger::Constants::C_QMLDEBUGGER));
m_toolbar->setObjectName("QmlInspectorToolbar");
@@ -617,7 +557,7 @@ void InspectorUi::setupDockWidgets()
QWidget *observerWidget = new QWidget;
observerWidget->setWindowTitle(tr("QML Observer"));
- observerWidget->setObjectName(QLatin1String("QMLObserver"));
+ observerWidget->setObjectName(Debugger::Constants::DOCKWIDGET_QML_INSPECTOR);
QVBoxLayout *wlay = new QVBoxLayout(observerWidget);
wlay->setMargin(0);
@@ -627,12 +567,10 @@ void InspectorUi::setupDockWidgets()
wlay->addWidget(m_objectTreeWidget);
wlay->addWidget(m_crumblePath);
-
- m_inspectorDockWidget = uiSwitcher->createDockWidget(Debugger::QmlLanguage,
- observerWidget, Qt::BottomDockWidgetArea);
- m_inspectorDockWidget->setObjectName(Debugger::Constants::DOCKWIDGET_QML_INSPECTOR);
- m_inspectorDockWidget->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);
- m_inspectorDockWidget->setTitleBarWidget(new QWidget(m_inspectorDockWidget));
+ Debugger::DebuggerMainWindow *mw = Debugger::DebuggerPlugin::mainWindow();
+ QDockWidget *dock = mw->createDockWidget(Debugger::QmlLanguage, observerWidget);
+ dock->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);
+ dock->setTitleBarWidget(new QWidget(dock));
}
void InspectorUi::crumblePathElementClicked(int pathIndex)
@@ -699,7 +637,8 @@ void InspectorUi::updatePendingPreviewDocuments(QmlJS::Document::Ptr doc)
if (idx == -1)
return;
- QList<Core::IEditor *> editors = Core::EditorManager::instance()->editorsForFileName(doc->fileName());
+ QList<Core::IEditor *> editors
+ = Core::EditorManager::instance()->editorsForFileName(doc->fileName());
if (editors.isEmpty())
return;
@@ -722,47 +661,81 @@ void InspectorUi::disableLivePreview()
void InspectorUi::setupToolbar(bool doConnect)
{
if (doConnect) {
- connect(m_clientProxy, SIGNAL(connected()), this, SLOT(enable()));
- connect(m_clientProxy, SIGNAL(disconnected()), this, SLOT(disable()));
-
- connect(m_toolbar, SIGNAL(designModeSelected(bool)), m_clientProxy, SLOT(setDesignModeBehavior(bool)));
- connect(m_toolbar, SIGNAL(reloadSelected()), m_clientProxy, SLOT(reloadQmlViewer()));
- connect(m_toolbar, SIGNAL(animationSpeedChanged(qreal)), m_clientProxy, SLOT(setAnimationSpeed(qreal)));
- connect(m_toolbar, SIGNAL(colorPickerSelected()), m_clientProxy, SLOT(changeToColorPickerTool()));
- connect(m_toolbar, SIGNAL(zoomToolSelected()), m_clientProxy, SLOT(changeToZoomTool()));
- connect(m_toolbar, SIGNAL(selectToolSelected()), m_clientProxy, SLOT(changeToSelectTool()));
- connect(m_toolbar, SIGNAL(applyChangesFromQmlFileTriggered(bool)), this, SLOT(setApplyChangesToQmlObserver(bool)));
-
- connect(this, SIGNAL(livePreviewActivated(bool)), m_toolbar, SLOT(setLivePreviewChecked(bool)));
- connect(m_clientProxy, SIGNAL(colorPickerActivated()), m_toolbar, SLOT(activateColorPicker()));
- connect(m_clientProxy, SIGNAL(selectToolActivated()), m_toolbar, SLOT(activateSelectTool()));
- connect(m_clientProxy, SIGNAL(zoomToolActivated()), m_toolbar, SLOT(activateZoomTool()));
- connect(m_clientProxy, SIGNAL(designModeBehaviorChanged(bool)), m_toolbar, SLOT(setDesignModeBehavior(bool)));
- connect(m_clientProxy, SIGNAL(selectedColorChanged(QColor)), m_toolbar, SLOT(setSelectedColor(QColor)));
-
- connect(m_clientProxy, SIGNAL(animationSpeedChanged(qreal)), m_toolbar, SLOT(setAnimationSpeed(qreal)));
+ connect(m_clientProxy, SIGNAL(connected()),
+ this, SLOT(enable()));
+ connect(m_clientProxy, SIGNAL(disconnected()),
+ this, SLOT(disable()));
+
+ connect(m_toolbar, SIGNAL(designModeSelected(bool)),
+ m_clientProxy, SLOT(setDesignModeBehavior(bool)));
+ connect(m_toolbar, SIGNAL(reloadSelected()),
+ m_clientProxy, SLOT(reloadQmlViewer()));
+ connect(m_toolbar, SIGNAL(animationSpeedChanged(qreal)),
+ m_clientProxy, SLOT(setAnimationSpeed(qreal)));
+ connect(m_toolbar, SIGNAL(colorPickerSelected()),
+ m_clientProxy, SLOT(changeToColorPickerTool()));
+ connect(m_toolbar, SIGNAL(zoomToolSelected()),
+ m_clientProxy, SLOT(changeToZoomTool()));
+ connect(m_toolbar, SIGNAL(selectToolSelected()),
+ m_clientProxy, SLOT(changeToSelectTool()));
+ connect(m_toolbar, SIGNAL(applyChangesFromQmlFileTriggered(bool)),
+ this, SLOT(setApplyChangesToQmlObserver(bool)));
+ connect(m_toolbar, SIGNAL(showAppOnTopSelected(bool)),
+ m_clientProxy, SLOT(showAppOnTop(bool)));
+
+ connect(m_clientProxy, SIGNAL(colorPickerActivated()),
+ m_toolbar, SLOT(activateColorPicker()));
+ connect(m_clientProxy, SIGNAL(selectToolActivated()),
+ m_toolbar, SLOT(activateSelectTool()));
+ connect(m_clientProxy, SIGNAL(zoomToolActivated()),
+ m_toolbar, SLOT(activateZoomTool()));
+ connect(m_clientProxy, SIGNAL(designModeBehaviorChanged(bool)),
+ m_toolbar, SLOT(setDesignModeBehavior(bool)));
+ connect(m_clientProxy, SIGNAL(showAppOnTopChanged(bool)),
+ m_toolbar, SLOT(setShowAppOnTop(bool)));
+ connect(m_clientProxy, SIGNAL(selectedColorChanged(QColor)),
+ m_toolbar, SLOT(setSelectedColor(QColor)));
+
+ connect(m_clientProxy, SIGNAL(animationSpeedChanged(qreal)),
+ m_toolbar, SLOT(setAnimationSpeed(qreal)));
enable();
} else {
disconnect(m_clientProxy, SIGNAL(connected()), this, SLOT(enable()));
disconnect(m_clientProxy, SIGNAL(disconnected()), this, SLOT(disable()));
- disconnect(m_toolbar, SIGNAL(designModeSelected(bool)), m_clientProxy, SLOT(setDesignModeBehavior(bool)));
- disconnect(m_toolbar, SIGNAL(reloadSelected()), m_clientProxy, SLOT(reloadQmlViewer()));
- disconnect(m_toolbar, SIGNAL(animationSpeedChanged(qreal)), m_clientProxy, SLOT(setAnimationSpeed(qreal)));
- disconnect(m_toolbar, SIGNAL(colorPickerSelected()), m_clientProxy, SLOT(changeToColorPickerTool()));
- disconnect(m_toolbar, SIGNAL(zoomToolSelected()), m_clientProxy, SLOT(changeToZoomTool()));
- disconnect(m_toolbar, SIGNAL(selectToolSelected()), m_clientProxy, SLOT(changeToSelectTool()));
- disconnect(m_toolbar, SIGNAL(applyChangesFromQmlFileTriggered(bool)), this, SLOT(setApplyChangesToQmlObserver(bool)));
-
- disconnect(this, SIGNAL(livePreviewActivated(bool)), m_toolbar, SLOT(setLivePreviewChecked(bool)));
- disconnect(m_clientProxy, SIGNAL(colorPickerActivated()), m_toolbar, SLOT(activateColorPicker()));
- disconnect(m_clientProxy, SIGNAL(selectToolActivated()), m_toolbar, SLOT(activateSelectTool()));
- disconnect(m_clientProxy, SIGNAL(zoomToolActivated()), m_toolbar, SLOT(activateZoomTool()));
- disconnect(m_clientProxy, SIGNAL(designModeBehaviorChanged(bool)), m_toolbar, SLOT(setDesignModeBehavior(bool)));
- disconnect(m_clientProxy, SIGNAL(selectedColorChanged(QColor)), m_toolbar, SLOT(setSelectedColor(QColor)));
-
- disconnect(m_clientProxy, SIGNAL(animationSpeedChanged(qreal)), m_toolbar, SLOT(setAnimationSpeed(qreal)));
+ disconnect(m_toolbar, SIGNAL(designModeSelected(bool)),
+ m_clientProxy, SLOT(setDesignModeBehavior(bool)));
+ disconnect(m_toolbar, SIGNAL(reloadSelected()),
+ m_clientProxy, SLOT(reloadQmlViewer()));
+ disconnect(m_toolbar, SIGNAL(animationSpeedChanged(qreal)),
+ m_clientProxy, SLOT(setAnimationSpeed(qreal)));
+ disconnect(m_toolbar, SIGNAL(colorPickerSelected()),
+ m_clientProxy, SLOT(changeToColorPickerTool()));
+ disconnect(m_toolbar, SIGNAL(zoomToolSelected()),
+ m_clientProxy, SLOT(changeToZoomTool()));
+ disconnect(m_toolbar, SIGNAL(selectToolSelected()),
+ m_clientProxy, SLOT(changeToSelectTool()));
+ disconnect(m_toolbar, SIGNAL(applyChangesFromQmlFileTriggered(bool)),
+ this, SLOT(setApplyChangesToQmlObserver(bool)));
+ disconnect(m_toolbar, SIGNAL(showAppOnTopSelected(bool)),
+ m_clientProxy, SLOT(showAppOnTop(bool)));
+
+ disconnect(m_clientProxy, SIGNAL(colorPickerActivated()),
+ m_toolbar, SLOT(activateColorPicker()));
+ disconnect(m_clientProxy, SIGNAL(selectToolActivated()),
+ m_toolbar, SLOT(activateSelectTool()));
+ disconnect(m_clientProxy, SIGNAL(zoomToolActivated()),
+ m_toolbar, SLOT(activateZoomTool()));
+ disconnect(m_clientProxy, SIGNAL(designModeBehaviorChanged(bool)),
+ m_toolbar, SLOT(setDesignModeBehavior(bool)));
+ disconnect(m_clientProxy, SIGNAL(showAppOnTopChanged(bool)),
+ m_toolbar, SLOT(setShowAppOnTop(bool)));
+ disconnect(m_clientProxy, SIGNAL(selectedColorChanged(QColor)),
+ m_toolbar, SLOT(setSelectedColor(QColor)));
+
+ disconnect(m_clientProxy, SIGNAL(animationSpeedChanged(qreal)),
+ m_toolbar, SLOT(setAnimationSpeed(qreal)));
disable();
}
diff --git a/src/plugins/qmljsinspector/qmljsinspector.h b/src/plugins/qmljsinspector/qmljsinspector.h
index 6ac90e7f76..24807e2892 100644
--- a/src/plugins/qmljsinspector/qmljsinspector.h
+++ b/src/plugins/qmljsinspector/qmljsinspector.h
@@ -36,9 +36,9 @@
#include "qmljsprivateapi.h"
-#include <coreplugin/basemode.h>
#include <debugger/debuggerconstants.h>
#include <qmlprojectmanager/qmlprojectrunconfiguration.h>
+#include <utils/fileinprojectfinder.h>
#include <qmljs/qmljsdocument.h>
#include <qmljs/parser/qmljsastfwd_p.h>
@@ -63,12 +63,6 @@ namespace QmlJS {
class ModelManagerInterface;
}
-namespace Debugger {
- class QmlEngine;
-}
-
-QT_FORWARD_DECLARE_CLASS(QDockWidget)
-
namespace QmlJSInspector {
namespace Internal {
@@ -110,15 +104,14 @@ public:
bool isConnected() const;
void connected(ClientProxy *clientProxy);
void disconnected();
- void setDebuggerEngine(Debugger::QmlEngine *qmlEngine);
- Debugger::QmlEngine *debuggerEngine() const;
+ void setDebuggerEngine(QObject *qmlEngine);
+ QObject *debuggerEngine() const;
signals:
void statusMessage(const QString &text);
void livePreviewActivated(bool isActivated);
public slots:
- void setSimpleDockWidgetArrangement(const Debugger::DebuggerLanguages &activeLanguages);
void reloadQmlViewer();
void serverReloaded();
void setApplyChangesToQmlObserver(bool applyChanges);
@@ -127,8 +120,7 @@ private slots:
void enable();
void disable();
void gotoObjectReferenceDefinition(const QDeclarativeDebugObjectReference &obj);
-
- void setSelectedItemsByObjectReference(QList<QDeclarativeDebugObjectReference> objectReferences);
+ void gotoObjectReferenceDefinition(QList<QDeclarativeDebugObjectReference> objectReferences);
void changeSelectedItems(const QList<QDeclarativeDebugObjectReference> &objects);
void updateEngineList();
@@ -161,12 +153,12 @@ private:
QmlInspectorToolbar *m_toolbar;
ContextCrumblePath *m_crumblePath;
QmlJSObjectTree *m_objectTreeWidget;
- QDockWidget *m_inspectorDockWidget;
InspectorSettings *m_settings;
ClientProxy *m_clientProxy;
- Debugger::QmlEngine *m_qmlEngine;
+ QObject *m_qmlEngine;
QDeclarativeDebugExpressionQuery *m_debugQuery;
+ int m_lastSelectedDebugId;
// Qml/JS integration
QHash<QString, QmlJSLiveTextPreview *> m_textPreviews;
@@ -177,6 +169,7 @@ private:
QString m_debugProjectBuildDir;
QStringList m_pendingPreviewDocumentNames;
+ Utils::FileInProjectFinder m_projectFinder;
static InspectorUi *m_instance;
};
@@ -184,4 +177,4 @@ private:
} // Internal
} // QmlJSInspector
-#endif
+#endif // QMLJSINSPECTOR_H
diff --git a/src/plugins/qmljsinspector/qmljsinspector.pro b/src/plugins/qmljsinspector/qmljsinspector.pro
index 3ae7bab149..61e71483f3 100644
--- a/src/plugins/qmljsinspector/qmljsinspector.pro
+++ b/src/plugins/qmljsinspector/qmljsinspector.pro
@@ -35,7 +35,6 @@ qmljsobjecttree.cpp
include(../../libs/qmljsdebugclient/qmljsdebugclient-lib.pri)
-OTHER_FILES += QmlJSInspector.pluginspec
RESOURCES += qmljsinspector.qrc
include(../../qtcreatorplugin.pri)
diff --git a/src/plugins/qmljsinspector/qmljsinspector.qrc b/src/plugins/qmljsinspector/qmljsinspector.qrc
index 9881cc0498..f1e4ceb212 100644
--- a/src/plugins/qmljsinspector/qmljsinspector.qrc
+++ b/src/plugins/qmljsinspector/qmljsinspector.qrc
@@ -19,5 +19,6 @@
<file>images/select-marquee-small.png</file>
<file>images/color-picker-small-hicontrast.png</file>
<file>images/observermode.png</file>
+ <file>images/app-on-top.png</file>
</qresource>
</RCC>
diff --git a/src/plugins/qmljsinspector/qmljsinspectorconstants.h b/src/plugins/qmljsinspector/qmljsinspectorconstants.h
index 98039f2781..ef1f2f019a 100644
--- a/src/plugins/qmljsinspector/qmljsinspectorconstants.h
+++ b/src/plugins/qmljsinspector/qmljsinspectorconstants.h
@@ -47,7 +47,6 @@ const char * const INFO_EXPERIMENTAL = "QmlInspector.Experimental";
const char * const INFO_OUT_OF_SYNC = "QmlInspector.OutOfSyncWarning";
const char * const DESIGNMODE_ACTION = "QmlInspector.DesignMode";
-//const char * const RELOAD_ACTION = "QmlInspector.Reload";
const char * const PLAY_ACTION = "QmlInspector.Play";
const char * const SELECT_ACTION = "QmlInspector.Select";
const char * const SELECT_MARQUEE_ACTION = "QmlInspector.SelectMarquee";
@@ -55,6 +54,7 @@ const char * const ZOOM_ACTION = "QmlInspector.Zoom";
const char * const COLOR_PICKER_ACTION = "QmlInspector.ColorPicker";
const char * const TO_QML_ACTION = "QmlInspector.ToQml";
const char * const FROM_QML_ACTION = "QmlInspector.FromQml";
+const char * const SHOW_APP_ON_TOP_ACTION = "QmlInspector.ShowAppOnTop";
// settings
const char * const S_QML_INSPECTOR = "QML.Inspector";
diff --git a/src/plugins/qmljsinspector/qmljsinspectorplugin.cpp b/src/plugins/qmljsinspector/qmljsinspectorplugin.cpp
index c9a0053bf2..8451a7db42 100644
--- a/src/plugins/qmljsinspector/qmljsinspectorplugin.cpp
+++ b/src/plugins/qmljsinspector/qmljsinspectorplugin.cpp
@@ -37,10 +37,8 @@
#include "qmljsclientproxy.h"
#include "qmlinspectortoolbar.h"
-#include <debugger/debuggeruiswitcher.h>
#include <debugger/debuggerconstants.h>
#include <debugger/qml/qmladapter.h>
-#include <debugger/qml/qmlengine.h>
#include <qmlprojectmanager/qmlproject.h>
#include <qmljseditor/qmljseditorconstants.h>
@@ -49,7 +47,11 @@
#include <coreplugin/icore.h>
#include <coreplugin/icontext.h>
+#include <coreplugin/imode.h>
#include <coreplugin/coreconstants.h>
+#include <coreplugin/modemanager.h>
+
+#include <utils/qtcassert.h>
#include <QtCore/QStringList>
#include <QtCore/QtPlugin>
@@ -63,19 +65,10 @@
using namespace QmlJSInspector::Internal;
using namespace QmlJSInspector::Constants;
-namespace {
-
-InspectorPlugin *g_instance = 0; // the global QML/JS inspector instance
-
-} // end of anonymous namespace
-
InspectorPlugin::InspectorPlugin()
: IPlugin()
, m_clientProxy(0)
{
- Q_ASSERT(! g_instance);
- g_instance = this;
-
m_inspectorUi = new InspectorUi(this);
}
@@ -88,11 +81,6 @@ QmlJS::ModelManagerInterface *InspectorPlugin::modelManager() const
return ExtensionSystem::PluginManager::instance()->getObject<QmlJS::ModelManagerInterface>();
}
-InspectorPlugin *InspectorPlugin::instance()
-{
- return g_instance;
-}
-
InspectorUi *InspectorPlugin::inspector() const
{
return m_inspectorUi;
@@ -119,7 +107,9 @@ void InspectorPlugin::extensionsInitialized()
connect(pluginManager, SIGNAL(objectAdded(QObject*)), SLOT(objectAdded(QObject*)));
connect(pluginManager, SIGNAL(aboutToRemoveObject(QObject*)), SLOT(aboutToRemoveObject(QObject*)));
- m_inspectorUi->setupUi();
+ Core::ICore *core = Core::ICore::instance();
+ connect(core->modeManager(), SIGNAL(currentModeAboutToChange(Core::IMode*)),
+ this, SLOT(modeAboutToChange(Core::IMode*)));
}
void InspectorPlugin::objectAdded(QObject *object)
@@ -135,10 +125,8 @@ void InspectorPlugin::objectAdded(QObject *object)
return;
}
- Debugger::QmlEngine *engine = qobject_cast<Debugger::QmlEngine*>(object);
- if (engine) {
- m_inspectorUi->setDebuggerEngine(engine);
- }
+ if (object->objectName() == QLatin1String("QmlEngine"))
+ m_inspectorUi->setDebuggerEngine(object);
}
void InspectorPlugin::aboutToRemoveObject(QObject *obj)
@@ -160,4 +148,18 @@ void InspectorPlugin::clientProxyConnected()
m_inspectorUi->connected(m_clientProxy);
}
+void InspectorPlugin::modeAboutToChange(Core::IMode *newMode)
+{
+ QTC_ASSERT(newMode, return);
+
+ if (newMode->id() == Debugger::Constants::MODE_DEBUG) {
+ m_inspectorUi->setupUi();
+
+ // make sure we're not called again
+ Core::ICore *core = Core::ICore::instance();
+ disconnect(core->modeManager(), SIGNAL(currentModeAboutToChange(Core::IMode*)),
+ this, SLOT(modeAboutToChange(Core::IMode*)));
+ }
+}
+
Q_EXPORT_PLUGIN(InspectorPlugin)
diff --git a/src/plugins/qmljsinspector/qmljsinspectorplugin.h b/src/plugins/qmljsinspector/qmljsinspectorplugin.h
index 24d34d16c1..10e089b6da 100644
--- a/src/plugins/qmljsinspector/qmljsinspectorplugin.h
+++ b/src/plugins/qmljsinspector/qmljsinspectorplugin.h
@@ -35,21 +35,14 @@
#include <extensionsystem/iplugin.h>
#include <qmljs/qmljsmodelmanagerinterface.h>
-#include <debugger/debuggerconstants.h>
#include <QtCore/QObject>
#include <QtCore/QPointer>
#include <QtCore/QTimer>
-QT_FORWARD_DECLARE_CLASS(QStringList)
-
namespace Core {
- class IMode;
-}
-
-namespace ProjectExplorer {
- class Project;
-}
+class IMode;
+} // namespace Core
namespace QmlJSInspector {
namespace Internal {
@@ -65,7 +58,7 @@ public:
InspectorPlugin();
virtual ~InspectorPlugin();
- static InspectorPlugin *instance();
+ //static InspectorPlugin *instance();
QmlJS::ModelManagerInterface *modelManager() const;
InspectorUi *inspector() const;
@@ -79,6 +72,7 @@ private slots:
void objectAdded(QObject *object);
void aboutToRemoveObject(QObject *obj);
void clientProxyConnected();
+ void modeAboutToChange(Core::IMode *mode);
private:
void createActions();
@@ -88,7 +82,7 @@ private:
InspectorUi *m_inspectorUi;
};
-} // end of namespace Internal
-} // end of QmlJSInspector
+} // namespace Internal
+} // namespace QmlJSInspector
#endif // QMLINSPECTORPLUGIN_H
diff --git a/src/plugins/qmljsinspector/qmljsinspectorsettings.h b/src/plugins/qmljsinspector/qmljsinspectorsettings.h
index 6028602640..94296e037e 100644
--- a/src/plugins/qmljsinspector/qmljsinspectorsettings.h
+++ b/src/plugins/qmljsinspector/qmljsinspectorsettings.h
@@ -43,6 +43,8 @@ namespace Internal {
class InspectorSettings : public QObject
{
+ Q_OBJECT
+
public:
InspectorSettings(QObject *parent = 0);
~InspectorSettings();
diff --git a/src/plugins/qmljsinspector/qmljslivetextpreview.cpp b/src/plugins/qmljsinspector/qmljslivetextpreview.cpp
index cba197382f..e6cdfd5d29 100644
--- a/src/plugins/qmljsinspector/qmljslivetextpreview.cpp
+++ b/src/plugins/qmljsinspector/qmljslivetextpreview.cpp
@@ -132,7 +132,7 @@ QmlJS::ModelManagerInterface *QmlJSLiveTextPreview::modelManager()
void QmlJSLiveTextPreview::associateEditor(Core::IEditor *editor)
{
if (editor->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID) {
- QmlJSEditor::Internal::QmlJSTextEditor* qmljsEditor = qobject_cast<QmlJSEditor::Internal::QmlJSTextEditor*>(editor->widget());
+ QmlJSEditor::QmlJSTextEditor* qmljsEditor = qobject_cast<QmlJSEditor::QmlJSTextEditor*>(editor->widget());
if (qmljsEditor && !m_editors.contains(qmljsEditor)) {
qmljsEditor->setUpdateSelectedElements(true);
m_editors << qmljsEditor;
@@ -146,7 +146,7 @@ void QmlJSLiveTextPreview::associateEditor(Core::IEditor *editor)
void QmlJSLiveTextPreview::unassociateEditor(Core::IEditor *oldEditor)
{
if (oldEditor && oldEditor->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID) {
- QmlJSEditor::Internal::QmlJSTextEditor* qmljsEditor = qobject_cast<QmlJSEditor::Internal::QmlJSTextEditor*>(oldEditor->widget());
+ QmlJSEditor::QmlJSTextEditor* qmljsEditor = qobject_cast<QmlJSEditor::QmlJSTextEditor*>(oldEditor->widget());
if (qmljsEditor && m_editors.contains(qmljsEditor)) {
m_editors.removeOne(qmljsEditor);
qmljsEditor->setUpdateSelectedElements(false);
@@ -521,12 +521,6 @@ void QmlJSLiveTextPreview::documentChanged(QmlJS::Document::Ptr doc)
if (doc->fileName() != m_previousDoc->fileName() || m_clientProxy.isNull())
return;
- Core::ICore *core = Core::ICore::instance();
- const int dbgcontext = core->uniqueIDManager()->uniqueIdentifier(Debugger::Constants::C_DEBUGMODE);
-
- if (!core->hasContext(dbgcontext))
- return;
-
bool experimentalWarningShown = false;
if (m_applyChangesToQmlObserver) {
@@ -594,7 +588,7 @@ void QmlJSLiveTextPreview::showSyncWarning(UnsyncronizableChangeType unsyncroniz
errorMessage.append(tr("You can continue debugging, but behavior can be unexpected."));
- em->showEditorInfoBar(Constants::INFO_OUT_OF_SYNC, errorMessage, tr("Reload"), this, SLOT(reloadQmlViewer()));
+ em->showEditorInfoBar(Constants::INFO_OUT_OF_SYNC, errorMessage);
}
void QmlJSLiveTextPreview::reloadQmlViewer()
@@ -634,12 +628,12 @@ void QmlJSLiveTextPreview::setClientProxy(ClientProxy *clientProxy)
connect(m_clientProxy.data(), SIGNAL(objectTreeUpdated()),
SLOT(updateDebugIds()));
- foreach(QWeakPointer<QmlJSEditor::Internal::QmlJSTextEditor> qmlEditor, m_editors) {
+ foreach(QWeakPointer<QmlJSEditor::QmlJSTextEditor> qmlEditor, m_editors) {
if (qmlEditor)
qmlEditor.data()->setUpdateSelectedElements(true);
}
} else {
- foreach(QWeakPointer<QmlJSEditor::Internal::QmlJSTextEditor> qmlEditor, m_editors) {
+ foreach(QWeakPointer<QmlJSEditor::QmlJSTextEditor> qmlEditor, m_editors) {
if (qmlEditor)
qmlEditor.data()->setUpdateSelectedElements(false);
}
diff --git a/src/plugins/qmljsinspector/qmljslivetextpreview.h b/src/plugins/qmljsinspector/qmljslivetextpreview.h
index 118289a772..08358cf9d1 100644
--- a/src/plugins/qmljsinspector/qmljslivetextpreview.h
+++ b/src/plugins/qmljsinspector/qmljslivetextpreview.h
@@ -52,10 +52,8 @@ namespace QmlJS {
}
namespace QmlJSEditor {
-namespace Internal {
class QmlJSTextEditor;
}
-}
namespace QmlJSInspector {
namespace Internal {
@@ -118,7 +116,7 @@ private:
QmlJS::Document::Ptr m_initialDoc; //the document that was loaded by the server
QString m_filename;
- QList<QWeakPointer<QmlJSEditor::Internal::QmlJSTextEditor> > m_editors;
+ QList<QWeakPointer<QmlJSEditor::QmlJSTextEditor> > m_editors;
bool m_applyChangesToQmlObserver;
QmlJS::Document::Ptr m_docWithUnappliedChanges;
diff --git a/src/plugins/qmljsinspector/qmljsobserverclient.cpp b/src/plugins/qmljsinspector/qmljsobserverclient.cpp
index aef5b97238..ae9c03473b 100644
--- a/src/plugins/qmljsinspector/qmljsobserverclient.cpp
+++ b/src/plugins/qmljsinspector/qmljsobserverclient.cpp
@@ -70,21 +70,27 @@ void QmlJSObserverClient::messageReceived(const QByteArray &message)
if (type == "CURRENT_OBJECTS_CHANGED") {
int objectCount;
ds >> objectCount;
- m_selectedItemIds.clear();
+
+ log(LogReceive, QString("%1 %2 [list of debug ids]").arg(QString(type),
+ QString::number(objectCount)));
+
+ m_currentDebugIds.clear();
for(int i = 0; i < objectCount; ++i) {
int debugId;
ds >> debugId;
if (debugId != -1) {
- m_selectedItemIds << debugId;
+ m_currentDebugIds << debugId;
}
}
- emit currentObjectsChanged(m_selectedItemIds);
+ emit currentObjectsChanged(m_currentDebugIds);
} else if (type == "TOOL_CHANGED") {
int toolId;
ds >> toolId;
+ log(LogReceive, QString("%1 %2").arg(QString(type), QString::number(toolId)));
+
if (toolId == Constants::ColorPickerMode) {
emit colorPickerActivated();
} else if (toolId == Constants::ZoomMode) {
@@ -97,44 +103,74 @@ void QmlJSObserverClient::messageReceived(const QByteArray &message)
} else if (type == "ANIMATION_SPEED_CHANGED") {
qreal slowdownFactor;
ds >> slowdownFactor;
+
+ log(LogReceive, QString("%1 %2").arg(QString(type), QString::number(slowdownFactor)));
+
emit animationSpeedChanged(slowdownFactor);
} else if (type == "SET_DESIGN_MODE") {
bool inDesignMode;
ds >> inDesignMode;
+
+ log(LogReceive, QString("%1 %2").arg(QString(type), inDesignMode ? "true" : "false"));
+
emit designModeBehaviorChanged(inDesignMode);
+ } else if (type == "SHOW_APP_ON_TOP") {
+ bool showAppOnTop;
+ ds >> showAppOnTop;
+
+ log(LogReceive, QString("%1 %2").arg(QString(type), showAppOnTop ? "true" : "false"));
+
+ emit showAppOnTopChanged(showAppOnTop);
} else if (type == "RELOADED") {
+
+ log(LogReceive, type);
+
emit reloaded();
} else if (type == "COLOR_CHANGED") {
QColor col;
ds >> col;
+
+ log(LogReceive, QString("%1 %2").arg(QString(type), col.name()));
+
emit selectedColorChanged(col);
} else if (type == "CONTEXT_PATH_UPDATED") {
QStringList contextPath;
ds >> contextPath;
+
+ log(LogReceive, QString("%1 %2").arg(QString(type), contextPath.join(", ")));
+
emit contextPathUpdated(contextPath);
}
}
-QList<int> QmlJSObserverClient::selectedItemIds() const
+QList<int> QmlJSObserverClient::currentObjects() const
{
- return m_selectedItemIds;
+ return m_currentDebugIds;
}
-void QmlJSObserverClient::setSelectedItemsByObjectId(const QList<QDeclarativeDebugObjectReference> &objects)
-{
+void QmlJSObserverClient::setCurrentObjects(const QList<int> &debugIds) {
if (!m_connection || !m_connection->isConnected())
return;
+ if (debugIds == m_currentDebugIds)
+ return;
+
+ m_currentDebugIds = debugIds;
+
QByteArray message;
QDataStream ds(&message, QIODevice::WriteOnly);
- ds << QByteArray("SET_CURRENT_OBJECTS")
- << objects.length();
+ QByteArray cmd = "SET_CURRENT_OBJECTS";
+ ds << cmd
+ << debugIds.length();
- foreach(const QDeclarativeDebugObjectReference &ref, objects) {
- ds << ref.debugId();
+ foreach (int id, debugIds) {
+ ds << id;
}
+ log(LogSend, QString("%1 %2 [list of ids]").arg(QString(cmd),
+ QString::number(debugIds.length())));
+
sendMessage(message);
}
@@ -159,7 +195,8 @@ void QmlJSObserverClient::setObjectIdList(const QList<QDeclarativeDebugObjectRef
recurseObjectIdList(ref, debugIds, objectIds);
}
- ds << QByteArray("OBJECT_ID_LIST")
+ QByteArray cmd = "OBJECT_ID_LIST";
+ ds << cmd
<< debugIds.length();
Q_ASSERT(debugIds.length() == objectIds.length());
@@ -168,6 +205,9 @@ void QmlJSObserverClient::setObjectIdList(const QList<QDeclarativeDebugObjectRef
ds << debugIds[i] << objectIds[i];
}
+ log(LogSend, QString("%1 %2 [list of debug / object ids]").arg(QString(cmd),
+ QString::number(debugIds.length())));
+
sendMessage(message);
}
@@ -179,8 +219,12 @@ void QmlJSObserverClient::setContextPathIndex(int contextPathIndex)
QByteArray message;
QDataStream ds(&message, QIODevice::WriteOnly);
- ds << QByteArray("SET_CONTEXT_PATH_IDX")
+ QByteArray cmd = "SET_CONTEXT_PATH_IDX";
+ ds << cmd
<< contextPathIndex;
+
+ log(LogSend, QString("%1 %2").arg(QString(cmd), contextPathIndex));
+
sendMessage(message);
}
@@ -192,7 +236,11 @@ void QmlJSObserverClient::clearComponentCache()
QByteArray message;
QDataStream ds(&message, QIODevice::WriteOnly);
- ds << QByteArray("CLEAR_COMPONENT_CACHE");
+ QByteArray cmd = "CLEAR_COMPONENT_CACHE";
+ ds << cmd;
+
+ log(LogSend, cmd);
+
sendMessage(message);
}
@@ -204,7 +252,11 @@ void QmlJSObserverClient::reloadViewer()
QByteArray message;
QDataStream ds(&message, QIODevice::WriteOnly);
- ds << QByteArray("RELOAD");
+ QByteArray cmd = "RELOAD";
+ ds << cmd;
+
+ log(LogSend, cmd);
+
sendMessage(message);
}
@@ -216,9 +268,12 @@ void QmlJSObserverClient::setDesignModeBehavior(bool inDesignMode)
QByteArray message;
QDataStream ds(&message, QIODevice::WriteOnly);
- ds << QByteArray("SET_DESIGN_MODE")
+ QByteArray cmd = "SET_DESIGN_MODE";
+ ds << cmd
<< inDesignMode;
+ log(LogSend, QString("%1 %2").arg(QString(cmd), inDesignMode ? "true" : "false"));
+
sendMessage(message);
}
@@ -230,8 +285,13 @@ void QmlJSObserverClient::setAnimationSpeed(qreal slowdownFactor)
QByteArray message;
QDataStream ds(&message, QIODevice::WriteOnly);
- ds << QByteArray("SET_ANIMATION_SPEED")
+ QByteArray cmd = "SET_ANIMATION_SPEED";
+ ds << cmd
<< slowdownFactor;
+
+
+ log(LogSend, QString("%1 %2").arg(QString(cmd), QString::number(slowdownFactor)));
+
sendMessage(message);
}
@@ -243,8 +303,13 @@ void QmlJSObserverClient::changeToColorPickerTool()
QByteArray message;
QDataStream ds(&message, QIODevice::WriteOnly);
- ds << QByteArray("CHANGE_TOOL")
- << QByteArray("COLOR_PICKER");
+ QByteArray cmd = "CHANGE_TOOL";
+ QByteArray tool = "COLOR_PICKER";
+ ds << cmd
+ << tool;
+
+ log(LogSend, QString("%1 %2").arg(QString(cmd), QString(tool)));
+
sendMessage(message);
}
@@ -256,8 +321,13 @@ void QmlJSObserverClient::changeToSelectTool()
QByteArray message;
QDataStream ds(&message, QIODevice::WriteOnly);
- ds << QByteArray("CHANGE_TOOL")
- << QByteArray("SELECT");
+ QByteArray cmd = "CHANGE_TOOL";
+ QByteArray tool = "SELECT";
+ ds << cmd
+ << tool;
+
+ log(LogSend, QString("%1 %2").arg(QString(cmd), QString(tool)));
+
sendMessage(message);
}
@@ -269,8 +339,13 @@ void QmlJSObserverClient::changeToSelectMarqueeTool()
QByteArray message;
QDataStream ds(&message, QIODevice::WriteOnly);
- ds << QByteArray("CHANGE_TOOL")
- << QByteArray("SELECT_MARQUEE");
+ QByteArray cmd = "CHANGE_TOOL";
+ QByteArray tool = "SELECT_MARQUEE";
+ ds << cmd
+ << tool;
+
+ log(LogSend, QString("%1 %2").arg(QString(cmd), QString(tool)));
+
sendMessage(message);
}
@@ -282,8 +357,29 @@ void QmlJSObserverClient::changeToZoomTool()
QByteArray message;
QDataStream ds(&message, QIODevice::WriteOnly);
- ds << QByteArray("CHANGE_TOOL")
- << QByteArray("ZOOM");
+ QByteArray cmd = "CHANGE_TOOL";
+ QByteArray tool = "ZOOM";
+ ds << cmd
+ << tool;
+
+ log(LogSend, QString("%1 %2").arg(QString(cmd), QString(tool)));
+
+ sendMessage(message);
+}
+
+void QmlJSObserverClient::showAppOnTop(bool showOnTop)
+{
+ if (!m_connection || !m_connection->isConnected())
+ return;
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+
+ QByteArray cmd = "SHOW_APP_ON_TOP";
+ ds << showOnTop;
+
+ log(LogSend, QString("%1 %2").arg(QString(cmd), showOnTop ? "true" : "false"));
+
sendMessage(message);
}
@@ -296,12 +392,16 @@ void QmlJSObserverClient::createQmlObject(const QString &qmlText, int parentDebu
QByteArray message;
QDataStream ds(&message, QIODevice::WriteOnly);
- ds << QByteArray("CREATE_OBJECT")
+ QByteArray cmd = "CREATE_OBJECT";
+ ds << cmd
<< qmlText
<< parentDebugId
<< imports
<< filename;
+ log(LogSend, QString("%1 %2 %3 [%4] %5").arg(QString(cmd), qmlText, QString::number(parentDebugId),
+ imports.join(","), filename));
+
sendMessage(message);
}
@@ -312,7 +412,10 @@ void QmlJSObserverClient::destroyQmlObject(int debugId)
QByteArray message;
QDataStream ds(&message, QIODevice::WriteOnly);
- ds << QByteArray("DESTROY_OBJECT") << debugId;
+ QByteArray cmd = "DESTROY_OBJECT";
+ ds << cmd << debugId;
+
+ log(LogSend, QString("%1 %2").arg(QString(cmd), debugId));
sendMessage(message);
}
@@ -324,10 +427,14 @@ void QmlJSObserverClient::reparentQmlObject(int debugId, int newParent)
QByteArray message;
QDataStream ds(&message, QIODevice::WriteOnly);
- ds << QByteArray("MOVE_OBJECT")
+ QByteArray cmd = "MOVE_OBJECT";
+ ds << cmd
<< debugId
<< newParent;
+ log(LogSend, QString("%1 %2 %3").arg(QString(cmd), QString::number(debugId),
+ QString::number(newParent)));
+
sendMessage(message);
}
@@ -348,6 +455,17 @@ void QmlJSObserverClient::applyChangesFromQmlFile()
// TODO
}
+void QmlJSObserverClient::log(LogDirection direction, const QString &message)
+{
+ QString msg;
+ if (direction == LogSend) {
+ msg += " sending ";
+ } else {
+ msg += " receiving ";
+ }
+ msg += message;
+ emit logActivity(name(), msg);
+}
} // namespace Internal
} // namespace QmlJSInspector
diff --git a/src/plugins/qmljsinspector/qmljsobserverclient.h b/src/plugins/qmljsinspector/qmljsobserverclient.h
index 2c7753a439..0d132b3ceb 100644
--- a/src/plugins/qmljsinspector/qmljsobserverclient.h
+++ b/src/plugins/qmljsinspector/qmljsobserverclient.h
@@ -54,7 +54,7 @@ public:
explicit QmlJSObserverClient(QDeclarativeDebugConnection *client,
QObject *parent = 0);
- void setSelectedItemsByObjectId(const QList<QDeclarativeDebugObjectReference> &objects);
+ void setCurrentObjects(const QList<int> &debugIds);
void reloadViewer();
void setDesignModeBehavior(bool inDesignMode);
void setAnimationSpeed(qreal slowdownFactor);
@@ -62,6 +62,7 @@ public:
void changeToSelectTool();
void changeToSelectMarqueeTool();
void changeToZoomTool();
+ void showAppOnTop(bool showOnTop);
void createQmlObject(const QString &qmlText, int parentDebugId,
const QStringList &imports, const QString &filename);
@@ -71,7 +72,7 @@ public:
void applyChangesToQmlFile();
void applyChangesFromQmlFile();
- QList<int> selectedItemIds() const;
+ QList<int> currentObjects() const;
// ### Qt 4.8: remove if we can have access to qdeclarativecontextdata or id's
void setObjectIdList(const QList<QDeclarativeDebugObjectReference> &objectRoots);
@@ -90,15 +91,25 @@ signals:
void zoomToolActivated();
void animationSpeedChanged(qreal slowdownFactor);
void designModeBehaviorChanged(bool inDesignMode);
- void reloaded(); // the server has reloaded the document
+ void showAppOnTopChanged(bool showAppOnTop);
+ void reloaded(); // the server has reloadetd he document
void contextPathUpdated(const QStringList &path);
+ void logActivity(QString client, QString message);
+
protected:
virtual void statusChanged(Status);
virtual void messageReceived(const QByteArray &);
private:
- QList<int> m_selectedItemIds;
+ enum LogDirection {
+ LogSend,
+ LogReceive
+ };
+
+ void log(LogDirection direction, const QString &str);
+
+ QList<int> m_currentDebugIds;
QDeclarativeDebugConnection *m_connection;
};
diff --git a/src/plugins/qmljsinspector/qmljstoolbarcolorbox.h b/src/plugins/qmljsinspector/qmljstoolbarcolorbox.h
index 4ffef1eb05..1fd1f41ad5 100644
--- a/src/plugins/qmljsinspector/qmljstoolbarcolorbox.h
+++ b/src/plugins/qmljsinspector/qmljstoolbarcolorbox.h
@@ -37,8 +37,8 @@
#include <QColor>
#include <QPoint>
-QT_FORWARD_DECLARE_CLASS(QContextMenuEvent);
-QT_FORWARD_DECLARE_CLASS(QAction);
+QT_FORWARD_DECLARE_CLASS(QContextMenuEvent)
+QT_FORWARD_DECLARE_CLASS(QAction)
namespace QmlJSInspector {
diff --git a/src/plugins/qmljstools/QmlJSTools.pluginspec.in b/src/plugins/qmljstools/QmlJSTools.pluginspec.in
new file mode 100644
index 0000000000..169376d347
--- /dev/null
+++ b/src/plugins/qmljstools/QmlJSTools.pluginspec.in
@@ -0,0 +1,21 @@
+<plugin name=\"QmlJSTools\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2010 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>
+ <category>Qt Quick</category>
+ <description>Tools for analyzing Qml/JS code.</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name=\"TextEditor\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"ProjectExplorer\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"Locator\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/qmljstools/qmljsfunctionfilter.cpp b/src/plugins/qmljstools/qmljsfunctionfilter.cpp
new file mode 100644
index 0000000000..2dab4c42c8
--- /dev/null
+++ b/src/plugins/qmljstools/qmljsfunctionfilter.cpp
@@ -0,0 +1,115 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "qmljsfunctionfilter.h"
+#include "qmljslocatordata.h"
+
+#include <texteditor/itexteditor.h>
+#include <texteditor/basetexteditor.h>
+
+#include <QtCore/QStringMatcher>
+
+using namespace QmlJSTools::Internal;
+
+Q_DECLARE_METATYPE(LocatorData::Entry)
+
+FunctionFilter::FunctionFilter(LocatorData *data, QObject *parent)
+ : Locator::ILocatorFilter(parent)
+ , m_data(data)
+{
+ setShortcutString(QString(QLatin1Char('m')));
+ setIncludedByDefault(false);
+}
+
+FunctionFilter::~FunctionFilter()
+{ }
+
+void FunctionFilter::refresh(QFutureInterface<void> &)
+{
+}
+
+static bool compareLexigraphically(const Locator::FilterEntry &a,
+ const Locator::FilterEntry &b)
+{
+ return a.displayName < b.displayName;
+}
+
+QList<Locator::FilterEntry> FunctionFilter::matchesFor(QFutureInterface<Locator::FilterEntry> &future, const QString &origEntry)
+{
+ QString entry = trimWildcards(origEntry);
+ QList<Locator::FilterEntry> goodEntries;
+ QList<Locator::FilterEntry> betterEntries;
+ const QChar asterisk = QLatin1Char('*');
+ QStringMatcher matcher(entry, Qt::CaseInsensitive);
+ const QRegExp regexp(asterisk + entry+ asterisk, Qt::CaseInsensitive, QRegExp::Wildcard);
+ if (!regexp.isValid())
+ return goodEntries;
+ bool hasWildcard = (entry.contains(asterisk) || entry.contains('?'));
+
+ QHashIterator<QString, QList<LocatorData::Entry> > it(m_data->entries());
+ while (it.hasNext()) {
+ if (future.isCanceled())
+ break;
+
+ it.next();
+
+ const QList<LocatorData::Entry> items = it.value();
+ foreach (const LocatorData::Entry &info, items) {
+ if (info.type != LocatorData::Function)
+ continue;
+ if ((hasWildcard && regexp.exactMatch(info.symbolName))
+ || (!hasWildcard && matcher.indexIn(info.symbolName) != -1)) {
+
+ QVariant id = qVariantFromValue(info);
+ Locator::FilterEntry filterEntry(this, info.displayName, id/*, info.icon*/);
+ filterEntry.extraInfo = info.extraInfo;
+
+ if (info.symbolName.startsWith(entry))
+ betterEntries.append(filterEntry);
+ else
+ goodEntries.append(filterEntry);
+ }
+ }
+ }
+
+ if (goodEntries.size() < 1000)
+ qSort(goodEntries.begin(), goodEntries.end(), compareLexigraphically);
+ if (betterEntries.size() < 1000)
+ qSort(betterEntries.begin(), betterEntries.end(), compareLexigraphically);
+
+ betterEntries += goodEntries;
+ return betterEntries;
+}
+
+void FunctionFilter::accept(Locator::FilterEntry selection) const
+{
+ const LocatorData::Entry entry = qvariant_cast<LocatorData::Entry>(selection.internalData);
+ TextEditor::BaseTextEditor::openEditorAt(entry.fileName, entry.line, entry.column,
+ QString(), Core::EditorManager::ModeSwitch);
+}
diff --git a/src/plugins/qmljstools/qmljsfunctionfilter.h b/src/plugins/qmljstools/qmljsfunctionfilter.h
new file mode 100644
index 0000000000..d79fed8eb9
--- /dev/null
+++ b/src/plugins/qmljstools/qmljsfunctionfilter.h
@@ -0,0 +1,61 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 QMLJSFUNCTIONFILTER_H
+#define QMLJSFUNCTIONFILTER_H
+
+#include <locator/ilocatorfilter.h>
+
+namespace QmlJSTools {
+namespace Internal {
+
+class LocatorData;
+
+class FunctionFilter : public Locator::ILocatorFilter
+{
+ Q_OBJECT
+public:
+ explicit FunctionFilter(LocatorData *data, QObject *parent = 0);
+ ~FunctionFilter();
+
+ QString displayName() const { return tr("Functions"); }
+ QString id() const { return QLatin1String("Functions"); }
+ Priority priority() const { return Medium; }
+ QList<Locator::FilterEntry> matchesFor(QFutureInterface<Locator::FilterEntry> &future, const QString &entry);
+ void accept(Locator::FilterEntry selection) const;
+ void refresh(QFutureInterface<void> &future);
+
+private:
+ LocatorData *m_data;
+};
+
+} // namespace Internal
+} // namespace QmlJSTools
+
+#endif // QMLJSFUNCTIONFILTER_H
diff --git a/src/plugins/qmljstools/qmljslocatordata.cpp b/src/plugins/qmljstools/qmljslocatordata.cpp
new file mode 100644
index 0000000000..4b9b45e24a
--- /dev/null
+++ b/src/plugins/qmljstools/qmljslocatordata.cpp
@@ -0,0 +1,218 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "qmljslocatordata.h"
+
+#include <qmljs/qmljsmodelmanagerinterface.h>
+#include <qmljs/qmljsbind.h>
+#include <qmljs/qmljsinterpreter.h>
+#include <qmljs/parser/qmljsast_p.h>
+
+using namespace QmlJSTools::Internal;
+using namespace QmlJS;
+using namespace QmlJS::Interpreter;
+using namespace QmlJS::AST;
+
+LocatorData::LocatorData(QObject *parent)
+ : QObject(parent)
+{
+ QmlJS::ModelManagerInterface *manager = QmlJS::ModelManagerInterface::instance();
+
+ connect(manager, SIGNAL(documentUpdated(QmlJS::Document::Ptr)),
+ this, SLOT(onDocumentUpdated(QmlJS::Document::Ptr)));
+ connect(manager, SIGNAL(aboutToRemoveFiles(QStringList)),
+ this, SLOT(onAboutToRemoveFiles(QStringList)));
+}
+
+LocatorData::~LocatorData()
+{}
+
+namespace {
+static QString findId(UiObjectInitializer *initializer)
+{
+ if (!initializer)
+ return QString();
+ for (UiObjectMemberList *member = initializer->members; member; member = member->next) {
+ if (UiScriptBinding *script = cast<UiScriptBinding *>(member->member)) {
+ if (!script->qualifiedId || !script->qualifiedId->name || script->qualifiedId->next)
+ continue;
+ if (script->qualifiedId->name->asString() != QLatin1String("id"))
+ continue;
+ if (ExpressionStatement *expStmt = cast<ExpressionStatement *>(script->statement)) {
+ if (IdentifierExpression *identExp = cast<IdentifierExpression *>(expStmt->expression)) {
+ if (identExp->name)
+ return identExp->name->asString();
+ }
+ }
+ }
+ }
+ return QString();
+}
+
+class FunctionFinder : protected AST::Visitor
+{
+ QList<LocatorData::Entry> m_entries;
+ Document::Ptr m_doc;
+ QString m_context;
+ QString m_documentContext;
+
+public:
+ FunctionFinder()
+ {}
+
+ QList<LocatorData::Entry> run(const Document::Ptr &doc)
+ {
+ m_doc = doc;
+ if (!doc->componentName().isEmpty()) {
+ m_documentContext = doc->componentName();
+ } else {
+ m_documentContext = QFileInfo(doc->fileName()).fileName();
+ }
+ accept(doc->ast(), m_documentContext);
+ return m_entries;
+ }
+
+protected:
+ QString contextString(const QString &extra)
+ {
+ return QString("%1, %2").arg(extra, m_documentContext);
+ }
+
+ LocatorData::Entry basicEntry(SourceLocation loc)
+ {
+ LocatorData::Entry entry;
+ entry.type = LocatorData::Function;
+ entry.extraInfo = m_context;
+ entry.fileName = m_doc->fileName();
+ entry.line = loc.startLine;
+ entry.column = loc.startColumn - 1;
+ return entry;
+ }
+
+ void accept(Node *ast, const QString &context)
+ {
+ const QString old = m_context;
+ m_context = context;
+ Node::accept(ast, this);
+ m_context = old;
+ }
+
+ bool visit(FunctionDeclaration *ast)
+ {
+ return visit(static_cast<FunctionExpression *>(ast));
+ }
+
+ bool visit(FunctionExpression *ast)
+ {
+ if (!ast->name)
+ return true;
+
+ LocatorData::Entry entry = basicEntry(ast->identifierToken);
+
+ entry.type = LocatorData::Function;
+ entry.displayName = ast->name->asString();
+ entry.displayName += QLatin1Char('(');
+ for (FormalParameterList *it = ast->formals; it; it = it->next) {
+ if (it != ast->formals)
+ entry.displayName += QLatin1String(", ");
+ if (it->name)
+ entry.displayName += it->name->asString();
+ }
+ entry.displayName += QLatin1Char(')');
+ entry.symbolName = entry.displayName;
+
+ m_entries += entry;
+
+ accept(ast->body, contextString(QString("function %1").arg(entry.displayName)));
+ return false;
+ }
+
+ bool visit(UiScriptBinding *ast)
+ {
+ if (!ast->qualifiedId)
+ return true;
+ const QString qualifiedIdString = Bind::toString(ast->qualifiedId);
+
+ if (cast<Block *>(ast->statement)) {
+ LocatorData::Entry entry = basicEntry(ast->qualifiedId->identifierToken);
+ entry.displayName = qualifiedIdString;
+ entry.symbolName = qualifiedIdString;
+ m_entries += entry;
+ }
+
+ accept(ast->statement, contextString(Bind::toString(ast->qualifiedId)));
+ return false;
+ }
+
+ bool visit(UiObjectBinding *ast)
+ {
+ if (!ast->qualifiedTypeNameId)
+ return true;
+
+ QString context = Bind::toString(ast->qualifiedTypeNameId);
+ const QString id = findId(ast->initializer);
+ if (!id.isEmpty())
+ context = QString("%1 (%2)").arg(id, context);
+ accept(ast->initializer, contextString(context));
+ return false;
+ }
+
+ bool visit(UiObjectDefinition *ast)
+ {
+ if (!ast->qualifiedTypeNameId)
+ return true;
+
+ QString context = Bind::toString(ast->qualifiedTypeNameId);
+ const QString id = findId(ast->initializer);
+ if (!id.isEmpty())
+ context = QString("%1 (%2)").arg(id, context);
+ accept(ast->initializer, contextString(context));
+ return false;
+ }
+};
+} // anonymous namespace
+
+QHash<QString, QList<LocatorData::Entry> > LocatorData::entries() const
+{
+ return m_entries;
+}
+
+void LocatorData::onDocumentUpdated(const QmlJS::Document::Ptr &doc)
+{
+ QList<Entry> entries = FunctionFinder().run(doc);
+ m_entries.insert(doc->fileName(), entries);
+}
+
+void LocatorData::onAboutToRemoveFiles(const QStringList &files)
+{
+ foreach (const QString &file, files) {
+ m_entries.remove(file);
+ }
+}
+
diff --git a/src/plugins/qmljstools/qmljslocatordata.h b/src/plugins/qmljstools/qmljslocatordata.h
new file mode 100644
index 0000000000..906e3920cc
--- /dev/null
+++ b/src/plugins/qmljstools/qmljslocatordata.h
@@ -0,0 +1,78 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 QMLJSLOCATORDATA_H
+#define QMLJSLOCATORDATA_H
+
+#include <qmljs/qmljsdocument.h>
+
+#include <QtCore/QObject>
+#include <QtCore/QHash>
+
+namespace QmlJSTools {
+namespace Internal {
+
+class LocatorData : public QObject
+{
+ Q_OBJECT
+public:
+ explicit LocatorData(QObject *parent = 0);
+ ~LocatorData();
+
+ enum EntryType
+ {
+ Function
+ };
+
+ class Entry
+ {
+ public:
+ EntryType type;
+ QString symbolName;
+ QString displayName;
+ QString extraInfo;
+ QString fileName;
+ int line;
+ int column;
+ };
+
+ QHash<QString, QList<Entry> > entries() const;
+
+private slots:
+ void onDocumentUpdated(const QmlJS::Document::Ptr &doc);
+ void onAboutToRemoveFiles(const QStringList &files);
+
+private:
+ QHash<QString, QList<Entry> > m_entries;
+};
+
+} // namespace Internal
+} // namespace QmlJSTools
+
+#endif // QMLJSLOCATORDATA_H
diff --git a/src/plugins/qmljstools/qmljsmodelmanager.cpp b/src/plugins/qmljstools/qmljsmodelmanager.cpp
new file mode 100644
index 0000000000..69f43c5579
--- /dev/null
+++ b/src/plugins/qmljstools/qmljsmodelmanager.cpp
@@ -0,0 +1,539 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** No Commercial Usage
+**
+** This file 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.
+**
+**************************************************************************/
+
+#include "qmljsmodelmanager.h"
+#include "qmljstoolsconstants.h"
+#include "qmljsplugindumper.h"
+
+#include <coreplugin/icore.h>
+#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/progressmanager/progressmanager.h>
+#include <coreplugin/mimedatabase.h>
+#include <qmljs/qmljsinterpreter.h>
+#include <qmljs/qmljsbind.h>
+#include <qmljs/parser/qmldirparser_p.h>
+#include <texteditor/itexteditor.h>
+#include <texteditor/basetexteditor.h>
+#include <projectexplorer/project.h>
+#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/projectexplorerconstants.h>
+
+#include <QDir>
+#include <QFile>
+#include <QFileInfo>
+#include <QLibraryInfo>
+#include <QtConcurrentRun>
+#include <qtconcurrent/runextensions.h>
+#include <QTextStream>
+#include <QCoreApplication>
+
+#include <QDebug>
+
+using namespace QmlJS;
+using namespace QmlJSTools;
+using namespace QmlJSTools::Internal;
+
+static QStringList environmentImportPaths();
+
+ModelManager::ModelManager(QObject *parent):
+ ModelManagerInterface(parent),
+ m_core(Core::ICore::instance()),
+ m_pluginDumper(new PluginDumper(this))
+{
+ m_synchronizer.setCancelOnWait(true);
+
+ qRegisterMetaType<QmlJS::Document::Ptr>("QmlJS::Document::Ptr");
+ qRegisterMetaType<QmlJS::LibraryInfo>("QmlJS::LibraryInfo");
+
+ loadQmlTypeDescriptions();
+
+ m_defaultImportPaths << environmentImportPaths();
+ updateImportPaths();
+}
+
+void ModelManager::loadQmlTypeDescriptions()
+{
+ if (Core::ICore::instance()) {
+ loadQmlTypeDescriptions(Core::ICore::instance()->resourcePath());
+ loadQmlTypeDescriptions(Core::ICore::instance()->userResourcePath());
+ }
+}
+
+void ModelManager::loadQmlTypeDescriptions(const QString &resourcePath)
+{
+ const QDir typeFileDir(resourcePath + QLatin1String("/qml-type-descriptions"));
+ const QStringList xmlExtensions = QStringList() << QLatin1String("*.xml");
+ const QFileInfoList xmlFiles = typeFileDir.entryInfoList(xmlExtensions,
+ QDir::Files,
+ QDir::Name);
+
+ const QStringList errors = Interpreter::CppQmlTypesLoader::load(xmlFiles);
+ foreach (const QString &error, errors)
+ qWarning() << qPrintable(error);
+
+ // disabled for now: Prefer the xml file until the type dumping functionality
+ // has been moved into Qt.
+ // loads the builtin types
+ //loadQmlPluginTypes(QString());
+}
+
+ModelManagerInterface::WorkingCopy ModelManager::workingCopy() const
+{
+ WorkingCopy workingCopy;
+ if (!m_core)
+ return workingCopy;
+
+ Core::EditorManager *editorManager = m_core->editorManager();
+
+ foreach (Core::IEditor *editor, editorManager->openedEditors()) {
+ const QString key = editor->file()->fileName();
+
+ if (TextEditor::ITextEditor *textEditor = qobject_cast<TextEditor::ITextEditor*>(editor)) {
+ if (textEditor->context().contains(ProjectExplorer::Constants::LANG_QMLJS)) {
+ if (TextEditor::BaseTextEditor *ed = qobject_cast<TextEditor::BaseTextEditor *>(textEditor->widget())) {
+ workingCopy.insert(key, ed->toPlainText(), ed->document()->revision());
+ }
+ }
+ }
+ }
+
+ return workingCopy;
+}
+
+Snapshot ModelManager::snapshot() const
+{
+ QMutexLocker locker(&m_mutex);
+
+ return _snapshot;
+}
+
+void ModelManager::updateSourceFiles(const QStringList &files,
+ bool emitDocumentOnDiskChanged)
+{
+ refreshSourceFiles(files, emitDocumentOnDiskChanged);
+}
+
+QFuture<void> ModelManager::refreshSourceFiles(const QStringList &sourceFiles,
+ bool emitDocumentOnDiskChanged)
+{
+ if (sourceFiles.isEmpty()) {
+ return QFuture<void>();
+ }
+
+ QFuture<void> result = QtConcurrent::run(&ModelManager::parse,
+ workingCopy(), sourceFiles,
+ this,
+ emitDocumentOnDiskChanged);
+
+ if (m_synchronizer.futures().size() > 10) {
+ QList<QFuture<void> > futures = m_synchronizer.futures();
+
+ m_synchronizer.clearFutures();
+
+ foreach (QFuture<void> future, futures) {
+ if (! (future.isFinished() || future.isCanceled()))
+ m_synchronizer.addFuture(future);
+ }
+ }
+
+ m_synchronizer.addFuture(result);
+
+ if (sourceFiles.count() > 1) {
+ m_core->progressManager()->addTask(result, tr("Indexing"),
+ Constants::TASK_INDEX);
+ }
+
+ return result;
+}
+
+void ModelManager::fileChangedOnDisk(const QString &path)
+{
+ QtConcurrent::run(&ModelManager::parse,
+ workingCopy(), QStringList() << path,
+ this, true);
+}
+
+void ModelManager::removeFiles(const QStringList &files)
+{
+ emit aboutToRemoveFiles(files);
+
+ QMutexLocker locker(&m_mutex);
+
+ foreach (const QString &file, files)
+ _snapshot.remove(file);
+}
+
+QList<ModelManager::ProjectInfo> ModelManager::projectInfos() const
+{
+ QMutexLocker locker(&m_mutex);
+
+ return m_projects.values();
+}
+
+ModelManager::ProjectInfo ModelManager::projectInfo(ProjectExplorer::Project *project) const
+{
+ QMutexLocker locker(&m_mutex);
+
+ return m_projects.value(project, ProjectInfo(project));
+}
+
+void ModelManager::updateProjectInfo(const ProjectInfo &pinfo)
+{
+ if (! pinfo.isValid())
+ return;
+
+ Snapshot snapshot;
+ ProjectInfo oldInfo;
+ {
+ QMutexLocker locker(&m_mutex);
+ oldInfo = m_projects.value(pinfo.project);
+ m_projects.insert(pinfo.project, pinfo);
+ snapshot = _snapshot;
+
+ if (oldInfo.qmlDumpPath != pinfo.qmlDumpPath)
+ m_pluginDumper->scheduleCompleteRedump();
+ }
+
+ updateImportPaths();
+
+ // remove files that are no longer in the project and have been deleted
+ QStringList deletedFiles;
+ foreach (const QString &oldFile, oldInfo.sourceFiles) {
+ if (snapshot.document(oldFile)
+ && !pinfo.sourceFiles.contains(oldFile)
+ && !QFile::exists(oldFile)) {
+ deletedFiles += oldFile;
+ }
+ }
+ removeFiles(deletedFiles);
+
+ // parse any files not yet in the snapshot
+ QStringList newFiles;
+ foreach (const QString &file, pinfo.sourceFiles) {
+ if (!snapshot.document(file))
+ newFiles += file;
+ }
+ updateSourceFiles(newFiles, false);
+}
+
+void ModelManager::emitDocumentChangedOnDisk(Document::Ptr doc)
+{ emit documentChangedOnDisk(doc); }
+
+void ModelManager::updateDocument(Document::Ptr doc)
+{
+ {
+ QMutexLocker locker(&m_mutex);
+ _snapshot.insert(doc);
+ }
+ emit documentUpdated(doc);
+}
+
+void ModelManager::updateLibraryInfo(const QString &path, const LibraryInfo &info)
+{
+ {
+ QMutexLocker locker(&m_mutex);
+ _snapshot.insertLibraryInfo(path, info);
+ }
+ emit libraryInfoUpdated(path, info);
+}
+
+static QStringList qmlFilesInDirectory(const QString &path)
+{
+ QStringList pattern;
+ if (Core::ICore::instance()) {
+ // ### It would suffice to build pattern once. This function needs to be thread-safe.
+ Core::MimeDatabase *db = Core::ICore::instance()->mimeDatabase();
+ Core::MimeType jsSourceTy = db->findByType(Constants::JS_MIMETYPE);
+ Core::MimeType qmlSourceTy = db->findByType(Constants::QML_MIMETYPE);
+
+ QStringList pattern;
+ foreach (const Core::MimeGlobPattern &glob, jsSourceTy.globPatterns())
+ pattern << glob.regExp().pattern();
+ foreach (const Core::MimeGlobPattern &glob, qmlSourceTy.globPatterns())
+ pattern << glob.regExp().pattern();
+ } else {
+ pattern << "*.qml" << "*.js";
+ }
+
+ QStringList files;
+
+ const QDir dir(path);
+ foreach (const QFileInfo &fi, dir.entryInfoList(pattern, QDir::Files))
+ files += fi.absoluteFilePath();
+
+ return files;
+}
+
+static void findNewImplicitImports(const Document::Ptr &doc, const Snapshot &snapshot,
+ QStringList *importedFiles, QSet<QString> *scannedPaths)
+{
+ // scan files that could be implicitly imported
+ // it's important we also do this for JS files, otherwise the isEmpty check will fail
+ if (snapshot.documentsInDirectory(doc->path()).isEmpty()) {
+ if (! scannedPaths->contains(doc->path())) {
+ *importedFiles += qmlFilesInDirectory(doc->path());
+ scannedPaths->insert(doc->path());
+ }
+ }
+}
+
+static void findNewFileImports(const Document::Ptr &doc, const Snapshot &snapshot,
+ QStringList *importedFiles, QSet<QString> *scannedPaths)
+{
+ // scan files and directories that are explicitly imported
+ foreach (const Interpreter::ImportInfo &import, doc->bind()->imports()) {
+ const QString &importName = import.name();
+ if (import.type() == Interpreter::ImportInfo::FileImport) {
+ if (! snapshot.document(importName))
+ *importedFiles += importName;
+ } else if (import.type() == Interpreter::ImportInfo::DirectoryImport) {
+ if (snapshot.documentsInDirectory(importName).isEmpty()) {
+ if (! scannedPaths->contains(importName)) {
+ *importedFiles += qmlFilesInDirectory(importName);
+ scannedPaths->insert(importName);
+ }
+ }
+ }
+ }
+}
+
+static void findNewLibraryImports(const Document::Ptr &doc, const Snapshot &snapshot,
+ ModelManager *modelManager,
+ QStringList *importedFiles, QSet<QString> *scannedPaths)
+{
+ // scan library imports
+ const QStringList importPaths = modelManager->importPaths();
+ foreach (const Interpreter::ImportInfo &import, doc->bind()->imports()) {
+ if (import.type() != Interpreter::ImportInfo::LibraryImport)
+ continue;
+ foreach (const QString &importPath, importPaths) {
+ QDir dir(importPath);
+ dir.cd(import.name());
+ const QString targetPath = dir.absolutePath();
+
+ // if we know there is a library, done
+ if (snapshot.libraryInfo(targetPath).isValid())
+ break;
+
+ // if there is a qmldir file, we found a new library!
+ if (dir.exists("qmldir")) {
+ QFile qmldirFile(dir.filePath("qmldir"));
+ qmldirFile.open(QFile::ReadOnly);
+ QString qmldirData = QString::fromUtf8(qmldirFile.readAll());
+
+ QmlDirParser qmldirParser;
+ qmldirParser.setSource(qmldirData);
+ qmldirParser.parse();
+
+ modelManager->updateLibraryInfo(QFileInfo(qmldirFile).absolutePath(),
+ LibraryInfo(qmldirParser));
+
+ // scan the qml files in the library
+ foreach (const QmlDirParser::Component &component, qmldirParser.components()) {
+ if (! component.fileName.isEmpty()) {
+ QFileInfo componentFileInfo(dir.filePath(component.fileName));
+ const QString path = componentFileInfo.absolutePath();
+ if (! scannedPaths->contains(path)) {
+ *importedFiles += qmlFilesInDirectory(path);
+ scannedPaths->insert(path);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+static bool suffixMatches(const QString &fileName, const Core::MimeType &mimeType)
+{
+ foreach (const QString &suffix, mimeType.suffixes()) {
+ if (fileName.endsWith(suffix, Qt::CaseInsensitive))
+ return true;
+ }
+ return false;
+}
+
+void ModelManager::parse(QFutureInterface<void> &future,
+ WorkingCopy workingCopy,
+ QStringList files,
+ ModelManager *modelManager,
+ bool emitDocChangedOnDisk)
+{
+ Core::MimeDatabase *db = 0;
+ Core::MimeType jsSourceTy;
+ Core::MimeType qmlSourceTy;
+ if (Core::ICore::instance()) {
+ db = Core::ICore::instance()->mimeDatabase();
+ jsSourceTy = db->findByType(QLatin1String("application/javascript"));
+ qmlSourceTy = db->findByType(QLatin1String("application/x-qml"));
+ }
+
+ int progressRange = files.size();
+ future.setProgressRange(0, progressRange);
+
+ Snapshot snapshot = modelManager->_snapshot;
+
+ // paths we have scanned for files and added to the files list
+ QSet<QString> scannedPaths;
+
+ for (int i = 0; i < files.size(); ++i) {
+ future.setProgressValue(qreal(i) / files.size() * progressRange);
+
+ const QString fileName = files.at(i);
+
+ bool isQmlFile = true;
+ if (db) {
+ if (suffixMatches(fileName, jsSourceTy)) {
+ isQmlFile = false;
+ } else if (! suffixMatches(fileName, qmlSourceTy)) {
+ continue; // skip it. it's not a QML or a JS file.
+ }
+ } else {
+ if (fileName.contains(QLatin1String(".js"), Qt::CaseInsensitive))
+ isQmlFile = false;
+ else if (!fileName.contains(QLatin1String(".qml"), Qt::CaseInsensitive))
+ continue;
+ }
+
+ QString contents;
+ int documentRevision = 0;
+
+ if (workingCopy.contains(fileName)) {
+ QPair<QString, int> entry = workingCopy.get(fileName);
+ contents = entry.first;
+ documentRevision = entry.second;
+ } else {
+ QFile inFile(fileName);
+
+ if (inFile.open(QIODevice::ReadOnly)) {
+ QTextStream ins(&inFile);
+ contents = ins.readAll();
+ inFile.close();
+ }
+ }
+
+ Document::Ptr doc = Document::create(fileName);
+ doc->setEditorRevision(documentRevision);
+ doc->setSource(contents);
+ doc->parse();
+
+ // get list of referenced files not yet in snapshot or in directories already scanned
+ QStringList importedFiles;
+ findNewImplicitImports(doc, snapshot, &importedFiles, &scannedPaths);
+ findNewFileImports(doc, snapshot, &importedFiles, &scannedPaths);
+ findNewLibraryImports(doc, snapshot, modelManager, &importedFiles, &scannedPaths);
+
+ // add new files to parse list
+ foreach (const QString &file, importedFiles) {
+ if (! files.contains(file))
+ files.append(file);
+ }
+
+ modelManager->updateDocument(doc);
+ if (emitDocChangedOnDisk)
+ modelManager->emitDocumentChangedOnDisk(doc);
+ }
+
+ future.setProgressValue(progressRange);
+}
+
+// Check whether fileMimeType is the same or extends knownMimeType
+bool ModelManager::matchesMimeType(const Core::MimeType &fileMimeType, const Core::MimeType &knownMimeType)
+{
+ Core::MimeDatabase *db = Core::ICore::instance()->mimeDatabase();
+
+ const QStringList knownTypeNames = QStringList(knownMimeType.type()) + knownMimeType.aliases();
+
+ foreach (const QString knownTypeName, knownTypeNames)
+ if (fileMimeType.matchesType(knownTypeName))
+ return true;
+
+ // recursion to parent types of fileMimeType
+ foreach (const QString &parentMimeType, fileMimeType.subClassesOf()) {
+ if (matchesMimeType(db->findByType(parentMimeType), knownMimeType))
+ return true;
+ }
+
+ return false;
+}
+
+QStringList ModelManager::importPaths() const
+{
+ return m_allImportPaths;
+}
+
+static QStringList environmentImportPaths()
+{
+ QStringList paths;
+
+ QByteArray envImportPath = qgetenv("QML_IMPORT_PATH");
+
+#if defined(Q_OS_WIN)
+ QLatin1Char pathSep(';');
+#else
+ QLatin1Char pathSep(':');
+#endif
+ foreach (const QString &path, QString::fromLatin1(envImportPath).split(pathSep, QString::SkipEmptyParts)) {
+ QString canonicalPath = QDir(path).canonicalPath();
+ if (!canonicalPath.isEmpty() && !paths.contains(canonicalPath))
+ paths.append(canonicalPath);
+ }
+
+ return paths;
+}
+
+void ModelManager::updateImportPaths()
+{
+ m_allImportPaths.clear();
+ QMapIterator<ProjectExplorer::Project *, ProjectInfo> it(m_projects);
+ while (it.hasNext()) {
+ it.next();
+ m_allImportPaths += it.value().importPaths;
+ }
+ m_allImportPaths += m_defaultImportPaths;
+ m_allImportPaths.removeDuplicates();
+
+ // check if any file in the snapshot imports something new in the new paths
+ Snapshot snapshot = _snapshot;
+ QStringList importedFiles;
+ QSet<QString> scannedPaths;
+ foreach (const Document::Ptr &doc, snapshot)
+ findNewLibraryImports(doc, snapshot, this, &importedFiles, &scannedPaths);
+
+ updateSourceFiles(importedFiles, true);
+}
+
+void ModelManager::loadPluginTypes(const QString &libraryPath, const QString &importPath, const QString &importUri)
+{
+ m_pluginDumper->loadPluginTypes(libraryPath, importPath, importUri);
+}
diff --git a/src/plugins/qmljstools/qmljsmodelmanager.h b/src/plugins/qmljstools/qmljsmodelmanager.h
new file mode 100644
index 0000000000..a80f18cdca
--- /dev/null
+++ b/src/plugins/qmljstools/qmljsmodelmanager.h
@@ -0,0 +1,122 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** No Commercial Usage
+**
+** This file 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.
+**
+**************************************************************************/
+
+#ifndef QMLJSMODELMANAGER_H
+#define QMLJSMODELMANAGER_H
+
+#include "qmljstools_global.h"
+
+#include <qmljs/qmljsmodelmanagerinterface.h>
+#include <qmljs/qmljsdocument.h>
+
+#include <QFuture>
+#include <QFutureSynchronizer>
+#include <QMutex>
+#include <QProcess>
+
+namespace Core {
+class ICore;
+class MimeType;
+}
+
+namespace QmlJSTools {
+namespace Internal {
+
+class PluginDumper;
+
+class QMLJSTOOLS_EXPORT ModelManager: public QmlJS::ModelManagerInterface
+{
+ Q_OBJECT
+
+public:
+ ModelManager(QObject *parent = 0);
+
+ virtual WorkingCopy workingCopy() const;
+ virtual QmlJS::Snapshot snapshot() const;
+
+ virtual void updateSourceFiles(const QStringList &files,
+ bool emitDocumentOnDiskChanged);
+ virtual void fileChangedOnDisk(const QString &path);
+ virtual void removeFiles(const QStringList &files);
+
+ virtual QList<ProjectInfo> projectInfos() const;
+ virtual ProjectInfo projectInfo(ProjectExplorer::Project *project) const;
+ virtual void updateProjectInfo(const ProjectInfo &pinfo);
+
+ void updateDocument(QmlJS::Document::Ptr doc);
+ void updateLibraryInfo(const QString &path, const QmlJS::LibraryInfo &info);
+ void emitDocumentChangedOnDisk(QmlJS::Document::Ptr doc);
+
+ virtual QStringList importPaths() const;
+
+ virtual void loadPluginTypes(const QString &libraryPath, const QString &importPath, const QString &importUri);
+
+Q_SIGNALS:
+ void projectPathChanged(const QString &projectPath);
+
+protected:
+ QFuture<void> refreshSourceFiles(const QStringList &sourceFiles,
+ bool emitDocumentOnDiskChanged);
+
+ static void parse(QFutureInterface<void> &future,
+ WorkingCopy workingCopy,
+ QStringList files,
+ ModelManager *modelManager,
+ bool emitDocChangedOnDisk);
+
+ void loadQmlTypeDescriptions();
+ void loadQmlTypeDescriptions(const QString &path);
+
+ void updateImportPaths();
+
+private:
+ static bool matchesMimeType(const Core::MimeType &fileMimeType, const Core::MimeType &knownMimeType);
+
+ mutable QMutex m_mutex;
+ Core::ICore *m_core;
+ QmlJS::Snapshot _snapshot;
+ QStringList m_allImportPaths;
+ QStringList m_defaultImportPaths;
+
+ QFutureSynchronizer<void> m_synchronizer;
+
+ // project integration
+ QMap<ProjectExplorer::Project *, ProjectInfo> m_projects;
+
+ PluginDumper *m_pluginDumper;
+};
+
+} // namespace Internal
+} // namespace QmlJSTools
+
+#endif // QMLJSMODELMANAGER_H
diff --git a/src/plugins/qmljstools/qmljsplugindumper.cpp b/src/plugins/qmljstools/qmljsplugindumper.cpp
new file mode 100644
index 0000000000..bc514fc54c
--- /dev/null
+++ b/src/plugins/qmljstools/qmljsplugindumper.cpp
@@ -0,0 +1,386 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "qmljsplugindumper.h"
+#include "qmljsmodelmanager.h"
+
+#include <qmljs/qmljsdocument.h>
+#include <qmljs/qmljsinterpreter.h>
+#include <projectexplorer/filewatcher.h>
+#include <projectexplorer/projectexplorer.h>
+#include <coreplugin/messagemanager.h>
+
+#include <QtCore/QDir>
+
+using namespace QmlJS;
+using namespace QmlJSTools;
+using namespace QmlJSTools::Internal;
+
+PluginDumper::PluginDumper(ModelManager *modelManager)
+ : QObject(modelManager)
+ , m_modelManager(modelManager)
+ , m_pluginWatcher(new ProjectExplorer::FileWatcher(this))
+{
+ connect(m_pluginWatcher, SIGNAL(fileChanged(QString)), SLOT(pluginChanged(QString)));
+}
+
+void PluginDumper::loadPluginTypes(const QString &libraryPath, const QString &importPath, const QString &importUri)
+{
+ // move to the owning thread
+ metaObject()->invokeMethod(this, "onLoadPluginTypes",
+ Q_ARG(QString, libraryPath),
+ Q_ARG(QString, importPath),
+ Q_ARG(QString, importUri));
+}
+
+void PluginDumper::onLoadPluginTypes(const QString &libraryPath, const QString &importPath, const QString &importUri)
+{
+ const QString canonicalLibraryPath = QDir::cleanPath(libraryPath);
+ if (m_runningQmldumps.values().contains(canonicalLibraryPath))
+ return;
+ const Snapshot snapshot = m_modelManager->snapshot();
+ const LibraryInfo libraryInfo = snapshot.libraryInfo(canonicalLibraryPath);
+ if (libraryInfo.dumpStatus() != LibraryInfo::DumpNotStartedOrRunning)
+ return;
+
+ // avoid inserting the same plugin twice
+ int index;
+ for (index = 0; index < m_plugins.size(); ++index) {
+ if (m_plugins.at(index).qmldirPath == libraryPath)
+ break;
+ }
+ if (index == m_plugins.size())
+ m_plugins.append(Plugin());
+
+ Plugin &plugin = m_plugins[index];
+ plugin.qmldirPath = canonicalLibraryPath;
+ plugin.importPath = importPath;
+ plugin.importUri = importUri;
+
+ // watch plugin libraries
+ foreach (const QmlDirParser::Plugin &plugin, snapshot.libraryInfo(canonicalLibraryPath).plugins()) {
+ const QString pluginLibrary = resolvePlugin(canonicalLibraryPath, plugin.path, plugin.name);
+ m_pluginWatcher->addFile(pluginLibrary);
+ m_libraryToPluginIndex.insert(pluginLibrary, index);
+ }
+
+ // watch library xml file
+ if (plugin.hasPredumpedXmlFile()) {
+ const QString &path = plugin.predumpedXmlFilePath();
+ m_pluginWatcher->addFile(path);
+ m_libraryToPluginIndex.insert(path, index);
+ }
+
+ dump(plugin);
+}
+
+void PluginDumper::scheduleCompleteRedump()
+{
+ metaObject()->invokeMethod(this, "dumpAllPlugins", Qt::QueuedConnection);
+}
+
+void PluginDumper::dumpAllPlugins()
+{
+ foreach (const Plugin &plugin, m_plugins)
+ dump(plugin);
+}
+
+static QString qmldumpErrorMessage(const QString &libraryPath, const QString &error)
+{
+ return PluginDumper::tr("Type dump of QML plugin in %0 failed.\nErrors:\n%1\n").arg(libraryPath, error);
+}
+
+static QString qmldumpFailedMessage()
+{
+ return PluginDumper::tr("Type dump of C++ plugin failed.\nCheck 'General Messages' output pane for details.");
+}
+
+static QList<const Interpreter::FakeMetaObject *> parseHelper(const QByteArray &xml, QString *error)
+{
+ QList<const Interpreter::FakeMetaObject *> ret;
+ QMap<QString, Interpreter::FakeMetaObject *> newObjects;
+ *error = Interpreter::CppQmlTypesLoader::parseQmlTypeXml(xml, &newObjects);
+
+ if (error->isEmpty()) {
+ // convert from QList<T *> to QList<const T *>
+ QMapIterator<QString, Interpreter::FakeMetaObject *> it(newObjects);
+ while (it.hasNext()) {
+ it.next();
+ ret.append(it.value());
+ }
+ }
+ return ret;
+}
+
+void PluginDumper::qmlPluginTypeDumpDone(int exitCode)
+{
+ QProcess *process = qobject_cast<QProcess *>(sender());
+ if (!process)
+ return;
+ process->deleteLater();
+
+ const QString libraryPath = m_runningQmldumps.take(process);
+ const Snapshot snapshot = m_modelManager->snapshot();
+ LibraryInfo libraryInfo = snapshot.libraryInfo(libraryPath);
+
+ if (exitCode != 0) {
+ Core::MessageManager *messageManager = Core::MessageManager::instance();
+ messageManager->printToOutputPane(qmldumpErrorMessage(libraryPath, process->readAllStandardError()));
+ libraryInfo.setDumpStatus(LibraryInfo::DumpError, qmldumpFailedMessage());
+ }
+
+ const QByteArray output = process->readAllStandardOutput();
+ QString error;
+ QList<const Interpreter::FakeMetaObject *> objectsList = parseHelper(output, &error);
+ if (exitCode == 0 && !error.isEmpty()) {
+ libraryInfo.setDumpStatus(LibraryInfo::DumpError, tr("Type dump of C++ plugin failed. Parse error:\n'%1'").arg(error));
+ }
+
+ if (exitCode == 0 && error.isEmpty()) {
+ libraryInfo.setMetaObjects(objectsList);
+ if (libraryPath.isEmpty())
+ Interpreter::CppQmlTypesLoader::builtinObjects.append(objectsList);
+ libraryInfo.setDumpStatus(LibraryInfo::DumpDone);
+ }
+
+ if (!libraryPath.isEmpty())
+ m_modelManager->updateLibraryInfo(libraryPath, libraryInfo);
+}
+
+void PluginDumper::qmlPluginTypeDumpError(QProcess::ProcessError)
+{
+ QProcess *process = qobject_cast<QProcess *>(sender());
+ if (!process)
+ return;
+ process->deleteLater();
+
+ const QString libraryPath = m_runningQmldumps.take(process);
+
+ Core::MessageManager *messageManager = Core::MessageManager::instance();
+ messageManager->printToOutputPane(qmldumpErrorMessage(libraryPath, process->readAllStandardError()));
+
+ if (!libraryPath.isEmpty()) {
+ const Snapshot snapshot = m_modelManager->snapshot();
+ LibraryInfo libraryInfo = snapshot.libraryInfo(libraryPath);
+ libraryInfo.setDumpStatus(LibraryInfo::DumpError, qmldumpFailedMessage());
+ m_modelManager->updateLibraryInfo(libraryPath, libraryInfo);
+ }
+}
+
+void PluginDumper::pluginChanged(const QString &pluginLibrary)
+{
+ const int pluginIndex = m_libraryToPluginIndex.value(pluginLibrary, -1);
+ if (pluginIndex == -1)
+ return;
+
+ const Plugin &plugin = m_plugins.at(pluginIndex);
+ dump(plugin);
+}
+
+void PluginDumper::dump(const Plugin &plugin)
+{
+ if (plugin.hasPredumpedXmlFile()) {
+ const Snapshot snapshot = m_modelManager->snapshot();
+ LibraryInfo libraryInfo = snapshot.libraryInfo(plugin.qmldirPath);
+ if (!libraryInfo.isValid())
+ return;
+
+ const QString &path = plugin.predumpedXmlFilePath();
+ QFile libraryXmlFile(path);
+ if (!libraryXmlFile.open(QFile::ReadOnly | QFile::Text)) {
+ libraryInfo.setDumpStatus(LibraryInfo::DumpError,
+ tr("Could not open file '%1' for reading.").arg(path));
+ m_modelManager->updateLibraryInfo(plugin.qmldirPath, libraryInfo);
+ return;
+ }
+
+ const QByteArray xml = libraryXmlFile.readAll();
+ libraryXmlFile.close();
+
+ QString error;
+ const QList<const Interpreter::FakeMetaObject *> objectsList = parseHelper(xml, &error);
+
+ if (error.isEmpty()) {
+ libraryInfo.setMetaObjects(objectsList);
+ libraryInfo.setDumpStatus(LibraryInfo::DumpDone);
+ } else {
+ libraryInfo.setDumpStatus(LibraryInfo::DumpError,
+ tr("Failed to parse '%1'.\nError: %2").arg(path, error));
+ }
+ m_modelManager->updateLibraryInfo(plugin.qmldirPath, libraryInfo);
+ return;
+ }
+
+ ProjectExplorer::Project *activeProject = ProjectExplorer::ProjectExplorerPlugin::instance()->startupProject();
+ if (!activeProject)
+ return;
+
+ ModelManagerInterface::ProjectInfo info = m_modelManager->projectInfo(activeProject);
+
+ if (info.qmlDumpPath.isEmpty()) {
+ const Snapshot snapshot = m_modelManager->snapshot();
+ LibraryInfo libraryInfo = snapshot.libraryInfo(plugin.qmldirPath);
+ if (!libraryInfo.isValid())
+ return;
+
+ libraryInfo.setDumpStatus(LibraryInfo::DumpError,
+ tr("Could not locate the helper application for dumping type information from C++ plugins.\n"
+ "Please build the debugging helpers on the Qt version options page."));
+ m_modelManager->updateLibraryInfo(plugin.qmldirPath, libraryInfo);
+ return;
+ }
+
+ QProcess *process = new QProcess(this);
+ process->setEnvironment(info.qmlDumpEnvironment.toStringList());
+ connect(process, SIGNAL(finished(int)), SLOT(qmlPluginTypeDumpDone(int)));
+ connect(process, SIGNAL(error(QProcess::ProcessError)), SLOT(qmlPluginTypeDumpError(QProcess::ProcessError)));
+ QStringList args;
+ args << plugin.importPath;
+ args << plugin.importUri;
+ process->start(info.qmlDumpPath, args);
+ m_runningQmldumps.insert(process, plugin.qmldirPath);
+}
+
+/*!
+ Returns the result of the merge of \a baseName with \a path, \a suffixes, and \a prefix.
+ The \a prefix must contain the dot.
+
+ \a qmldirPath is the location of the qmldir file.
+
+ Adapted from QDeclarativeImportDatabase::resolvePlugin.
+*/
+QString PluginDumper::resolvePlugin(const QDir &qmldirPath, const QString &qmldirPluginPath,
+ const QString &baseName, const QStringList &suffixes,
+ const QString &prefix)
+{
+ QStringList searchPaths;
+ searchPaths.append(QLatin1String("."));
+
+ bool qmldirPluginPathIsRelative = QDir::isRelativePath(qmldirPluginPath);
+ if (!qmldirPluginPathIsRelative)
+ searchPaths.prepend(qmldirPluginPath);
+
+ foreach (const QString &pluginPath, searchPaths) {
+
+ QString resolvedPath;
+
+ if (pluginPath == QLatin1String(".")) {
+ if (qmldirPluginPathIsRelative)
+ resolvedPath = qmldirPath.absoluteFilePath(qmldirPluginPath);
+ else
+ resolvedPath = qmldirPath.absolutePath();
+ } else {
+ resolvedPath = pluginPath;
+ }
+
+ QDir dir(resolvedPath);
+ foreach (const QString &suffix, suffixes) {
+ QString pluginFileName = prefix;
+
+ pluginFileName += baseName;
+ pluginFileName += suffix;
+
+ QFileInfo fileInfo(dir, pluginFileName);
+
+ if (fileInfo.exists())
+ return fileInfo.absoluteFilePath();
+ }
+ }
+
+ return QString();
+}
+
+/*!
+ Returns the result of the merge of \a baseName with \a dir and the platform suffix.
+
+ Adapted from QDeclarativeImportDatabase::resolvePlugin.
+
+ \table
+ \header \i Platform \i Valid suffixes
+ \row \i Windows \i \c .dll
+ \row \i Unix/Linux \i \c .so
+ \row \i AIX \i \c .a
+ \row \i HP-UX \i \c .sl, \c .so (HP-UXi)
+ \row \i Mac OS X \i \c .dylib, \c .bundle, \c .so
+ \row \i Symbian \i \c .dll
+ \endtable
+
+ Version number on unix are ignored.
+*/
+QString PluginDumper::resolvePlugin(const QDir &qmldirPath, const QString &qmldirPluginPath,
+ const QString &baseName)
+{
+#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
+ return resolvePlugin(qmldirPath, qmldirPluginPath, baseName,
+ QStringList()
+ << QLatin1String("d.dll") // try a qmake-style debug build first
+ << QLatin1String(".dll"));
+#elif defined(Q_OS_DARWIN)
+ return resolvePlugin(qmldirPath, qmldirPluginPath, baseName,
+ QStringList()
+ << QLatin1String("_debug.dylib") // try a qmake-style debug build first
+ << QLatin1String(".dylib")
+ << QLatin1String(".so")
+ << QLatin1String(".bundle"),
+ QLatin1String("lib"));
+#else // Generic Unix
+ QStringList validSuffixList;
+
+# if defined(Q_OS_HPUX)
+/*
+ See "HP-UX Linker and Libraries User's Guide", section "Link-time Differences between PA-RISC and IPF":
+ "In PA-RISC (PA-32 and PA-64) shared libraries are suffixed with .sl. In IPF (32-bit and 64-bit),
+ the shared libraries are suffixed with .so. For compatibility, the IPF linker also supports the .sl suffix."
+ */
+ validSuffixList << QLatin1String(".sl");
+# if defined __ia64
+ validSuffixList << QLatin1String(".so");
+# endif
+# elif defined(Q_OS_AIX)
+ validSuffixList << QLatin1String(".a") << QLatin1String(".so");
+# elif defined(Q_OS_UNIX)
+ validSuffixList << QLatin1String(".so");
+# endif
+
+ // Examples of valid library names:
+ // libfoo.so
+
+ return resolvePlugin(qmldirPath, qmldirPluginPath, baseName, validSuffixList, QLatin1String("lib"));
+#endif
+}
+
+bool PluginDumper::Plugin::hasPredumpedXmlFile() const
+{
+ return QFileInfo(predumpedXmlFilePath()).isFile();
+}
+
+QString PluginDumper::Plugin::predumpedXmlFilePath() const
+{
+ return QString("%1%2library.xml").arg(qmldirPath, QDir::separator());
+}
diff --git a/src/plugins/qmljstools/qmljsplugindumper.h b/src/plugins/qmljstools/qmljsplugindumper.h
new file mode 100644
index 0000000000..3e75c1fd20
--- /dev/null
+++ b/src/plugins/qmljstools/qmljsplugindumper.h
@@ -0,0 +1,98 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 QMLJSPLUGINDUMPER_H
+#define QMLJSPLUGINDUMPER_H
+
+#include <QtCore/QObject>
+#include <QtCore/QHash>
+#include <QtCore/QProcess>
+
+QT_BEGIN_NAMESPACE
+class QDir;
+QT_END_NAMESPACE
+
+namespace ProjectExplorer {
+class FileWatcher;
+}
+
+namespace QmlJSTools {
+namespace Internal {
+
+class ModelManager;
+
+class PluginDumper : public QObject
+{
+ Q_OBJECT
+public:
+ explicit PluginDumper(ModelManager *modelManager);
+
+public:
+ void loadPluginTypes(const QString &libraryPath, const QString &importPath,
+ const QString &importUri);
+ void scheduleCompleteRedump();
+
+private slots:
+ void onLoadPluginTypes(const QString &libraryPath, const QString &importPath,
+ const QString &importUri);
+ void dumpAllPlugins();
+ void qmlPluginTypeDumpDone(int exitCode);
+ void qmlPluginTypeDumpError(QProcess::ProcessError error);
+ void pluginChanged(const QString &pluginLibrary);
+
+private:
+ class Plugin {
+ public:
+ QString qmldirPath;
+ QString importPath;
+ QString importUri;
+
+ bool hasPredumpedXmlFile() const;
+ QString predumpedXmlFilePath() const;
+ };
+
+ void dump(const Plugin &plugin);
+ QString resolvePlugin(const QDir &qmldirPath, const QString &qmldirPluginPath,
+ const QString &baseName);
+ QString resolvePlugin(const QDir &qmldirPath, const QString &qmldirPluginPath,
+ const QString &baseName, const QStringList &suffixes,
+ const QString &prefix = QString());
+
+private:
+ ModelManager *m_modelManager;
+ ProjectExplorer::FileWatcher *m_pluginWatcher;
+ QHash<QProcess *, QString> m_runningQmldumps;
+ QList<Plugin> m_plugins;
+ QHash<QString, int> m_libraryToPluginIndex;
+};
+
+} // namespace Internal
+} // namespace QmlJSTools
+
+#endif // QMLJSPLUGINDUMPER_H
diff --git a/src/plugins/qmljstools/qmljsqtstylecodeformatter.cpp b/src/plugins/qmljstools/qmljsqtstylecodeformatter.cpp
new file mode 100644
index 0000000000..c66ecd7b78
--- /dev/null
+++ b/src/plugins/qmljstools/qmljsqtstylecodeformatter.cpp
@@ -0,0 +1,363 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** No Commercial Usage
+**
+** This file 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.
+**
+**************************************************************************/
+
+#include "qmljsqtstylecodeformatter.h"
+
+#include <texteditor/tabsettings.h>
+
+#include <QtCore/QDebug>
+
+using namespace QmlJS;
+using namespace QmlJSTools;
+using namespace TextEditor;
+
+QtStyleCodeFormatter::QtStyleCodeFormatter()
+ : m_indentSize(4)
+{
+}
+
+QtStyleCodeFormatter::QtStyleCodeFormatter(const TextEditor::TabSettings &tabSettings)
+ : m_indentSize(tabSettings.m_indentSize)
+{
+ setTabSize(tabSettings.m_tabSize);
+}
+
+void QtStyleCodeFormatter::setIndentSize(int size)
+{
+ m_indentSize = size;
+}
+
+void QtStyleCodeFormatter::saveBlockData(QTextBlock *block, const BlockData &data) const
+{
+ TextBlockUserData *userData = BaseTextDocumentLayout::userData(*block);
+ QmlJSCodeFormatterData *cppData = static_cast<QmlJSCodeFormatterData *>(userData->codeFormatterData());
+ if (!cppData) {
+ cppData = new QmlJSCodeFormatterData;
+ userData->setCodeFormatterData(cppData);
+ }
+ cppData->m_data = data;
+}
+
+bool QtStyleCodeFormatter::loadBlockData(const QTextBlock &block, BlockData *data) const
+{
+ TextBlockUserData *userData = BaseTextDocumentLayout::testUserData(block);
+ if (!userData)
+ return false;
+ QmlJSCodeFormatterData *cppData = static_cast<QmlJSCodeFormatterData *>(userData->codeFormatterData());
+ if (!cppData)
+ return false;
+
+ *data = cppData->m_data;
+ return true;
+}
+
+void QtStyleCodeFormatter::saveLexerState(QTextBlock *block, int state) const
+{
+ BaseTextDocumentLayout::setLexerState(*block, state);
+}
+
+int QtStyleCodeFormatter::loadLexerState(const QTextBlock &block) const
+{
+ return BaseTextDocumentLayout::lexerState(block);
+}
+
+void QtStyleCodeFormatter::onEnter(int newState, int *indentDepth, int *savedIndentDepth) const
+{
+ const State &parentState = state();
+ const Token &tk = currentToken();
+ const int tokenPosition = column(tk.begin());
+ const bool firstToken = (tokenIndex() == 0);
+ const bool lastToken = (tokenIndex() == tokenCount() - 1);
+
+ switch (newState) {
+ case objectdefinition_open: {
+ // special case for things like "gradient: Gradient {"
+ if (parentState.type == binding_assignment)
+ *savedIndentDepth = state(1).savedIndentDepth;
+
+ if (firstToken)
+ *savedIndentDepth = tokenPosition;
+
+ *indentDepth = *savedIndentDepth + m_indentSize;
+ break;
+ }
+
+ case binding_or_objectdefinition:
+ if (firstToken)
+ *indentDepth = *savedIndentDepth = tokenPosition;
+ break;
+
+ case binding_assignment:
+ if (lastToken)
+ *indentDepth = *savedIndentDepth + 4;
+ else
+ *indentDepth = column(tokenAt(tokenIndex() + 1).begin());
+ break;
+
+ case expression_or_objectdefinition:
+ *indentDepth = tokenPosition;
+ break;
+
+ case expression:
+ // expression_or_objectdefinition has already consumed the first token
+ // ternary already adjusts indents nicely
+ if (parentState.type != expression_or_objectdefinition
+ && parentState.type != binding_assignment
+ && parentState.type != ternary_op) {
+ *indentDepth += 2 * m_indentSize;
+ }
+ if (!firstToken && parentState.type != expression_or_objectdefinition) {
+ *indentDepth = tokenPosition;
+ }
+ break;
+
+ case expression_maybe_continuation:
+ // set indent depth to indent we'd get if the expression ended here
+ for (int i = 1; state(i).type != topmost_intro; ++i) {
+ const int type = state(i).type;
+ if (isExpressionEndState(type) && !isBracelessState(type)) {
+ *indentDepth = state(i - 1).savedIndentDepth;
+ break;
+ }
+ }
+ break;
+
+ case bracket_open:
+ if (parentState.type == expression && state(1).type == binding_assignment) {
+ *savedIndentDepth = state(2).savedIndentDepth;
+ *indentDepth = *savedIndentDepth + m_indentSize;
+ } else if (!lastToken) {
+ *indentDepth = tokenPosition + 1;
+ } else {
+ *indentDepth = *savedIndentDepth + m_indentSize;
+ }
+ break;
+
+ case function_start:
+ if (parentState.type == expression) {
+ // undo the continuation indent of the expression
+ *indentDepth = parentState.savedIndentDepth;
+ *savedIndentDepth = *indentDepth;
+ }
+ break;
+
+ case do_statement_while_paren_open:
+ case statement_with_condition_paren_open:
+ case signal_arglist_open:
+ case function_arglist_open:
+ case paren_open:
+ case condition_paren_open:
+ if (!lastToken)
+ *indentDepth = tokenPosition + 1;
+ else
+ *indentDepth += m_indentSize;
+ break;
+
+ case ternary_op:
+ if (!lastToken)
+ *indentDepth = tokenPosition + tk.length + 1;
+ else
+ *indentDepth += m_indentSize;
+ break;
+
+ case jsblock_open:
+ // closing brace should be aligned to case
+ if (parentState.type == case_cont) {
+ *savedIndentDepth = parentState.savedIndentDepth;
+ break;
+ }
+ // fallthrough
+ case substatement_open:
+ // special case for foo: {
+ if (parentState.type == binding_assignment && state(1).type == binding_or_objectdefinition)
+ *savedIndentDepth = state(1).savedIndentDepth;
+ *indentDepth = *savedIndentDepth + m_indentSize;
+ break;
+
+ case statement_with_condition:
+ case statement_with_block:
+ case if_statement:
+ case do_statement:
+ case switch_statement:
+ if (firstToken || parentState.type == binding_assignment)
+ *savedIndentDepth = tokenPosition;
+ // ### continuation
+ *indentDepth = *savedIndentDepth; // + 2*m_indentSize;
+ break;
+
+ case maybe_else: {
+ // set indent to outermost braceless savedIndent
+ int outermostBraceless = 0;
+ while (isBracelessState(state(outermostBraceless + 1).type))
+ ++outermostBraceless;
+ *indentDepth = state(outermostBraceless).savedIndentDepth;
+ // this is where the else should go, if one appears - aligned to if_statement
+ *savedIndentDepth = state().savedIndentDepth;
+ break;
+ }
+
+ case condition_open:
+ // fixed extra indent when continuing 'if (', but not for 'else if ('
+ if (tokenPosition <= *indentDepth + m_indentSize)
+ *indentDepth += 2*m_indentSize;
+ else
+ *indentDepth = tokenPosition + 1;
+ break;
+
+ case case_start:
+ *savedIndentDepth = tokenPosition;
+ break;
+
+ case case_cont:
+ *indentDepth += m_indentSize;
+ break;
+
+ case multiline_comment_start:
+ *indentDepth = tokenPosition + 2;
+ break;
+
+ case multiline_comment_cont:
+ *indentDepth = tokenPosition;
+ break;
+ }
+}
+
+void QtStyleCodeFormatter::adjustIndent(const QList<Token> &tokens, int lexerState, int *indentDepth) const
+{
+ Q_UNUSED(lexerState)
+
+ State topState = state();
+ State previousState = state(1);
+
+ // adjusting the indentDepth here instead of in enter() gives 'else if' the correct indentation
+ // ### could be moved?
+ if (topState.type == substatement)
+ *indentDepth += m_indentSize;
+
+ // keep user-adjusted indent in multiline comments
+ if (topState.type == multiline_comment_start
+ || topState.type == multiline_comment_cont) {
+ if (!tokens.isEmpty()) {
+ *indentDepth = column(tokens.at(0).begin());
+ return;
+ }
+ }
+
+ const int kind = extendedTokenKind(tokenAt(0));
+ switch (kind) {
+ case LeftBrace:
+ if (topState.type == substatement
+ || topState.type == binding_assignment
+ || topState.type == case_cont) {
+ *indentDepth = topState.savedIndentDepth;
+ }
+ break;
+ case RightBrace: {
+ if (topState.type == jsblock_open && previousState.type == case_cont) {
+ *indentDepth = previousState.savedIndentDepth;
+ break;
+ }
+ for (int i = 0; state(i).type != topmost_intro; ++i) {
+ const int type = state(i).type;
+ if (type == objectdefinition_open
+ || type == jsblock_open
+ || type == substatement_open) {
+ *indentDepth = state(i).savedIndentDepth;
+ break;
+ }
+ }
+ break;
+ }
+ case RightBracket:
+ for (int i = 0; state(i).type != topmost_intro; ++i) {
+ const int type = state(i).type;
+ if (type == bracket_open) {
+ *indentDepth = state(i).savedIndentDepth;
+ break;
+ }
+ }
+ break;
+
+ case LeftBracket:
+ case LeftParenthesis:
+ case Delimiter:
+ if (topState.type == expression_maybe_continuation)
+ *indentDepth = topState.savedIndentDepth;
+ break;
+
+ case Else:
+ if (topState.type == maybe_else) {
+ *indentDepth = topState.savedIndentDepth;
+ } else if (topState.type == expression_maybe_continuation) {
+ bool hasElse = false;
+ for (int i = 1; state(i).type != topmost_intro; ++i) {
+ const int type = state(i).type;
+ if (type == else_clause)
+ hasElse = true;
+ if (type == if_statement) {
+ if (hasElse) {
+ hasElse = false;
+ } else {
+ *indentDepth = state(i).savedIndentDepth;
+ break;
+ }
+ }
+ }
+ }
+ break;
+
+ case Colon:
+ if (topState.type == ternary_op) {
+ *indentDepth -= 2;
+ }
+ break;
+
+ case Question:
+ if (topState.type == expression_maybe_continuation)
+ *indentDepth = topState.savedIndentDepth;
+ break;
+
+ case Default:
+ case Case:
+ for (int i = 0; state(i).type != topmost_intro; ++i) {
+ const int type = state(i).type;
+ if (type == switch_statement || type == case_cont) {
+ *indentDepth = state(i).savedIndentDepth;
+ break;
+ } else if (type == topmost_intro) {
+ break;
+ }
+ }
+ break;
+ }
+}
diff --git a/src/plugins/qmljstools/qmljsqtstylecodeformatter.h b/src/plugins/qmljstools/qmljsqtstylecodeformatter.h
new file mode 100644
index 0000000000..640a93ac28
--- /dev/null
+++ b/src/plugins/qmljstools/qmljsqtstylecodeformatter.h
@@ -0,0 +1,78 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** No Commercial Usage
+**
+** This file 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.
+**
+**************************************************************************/
+
+#ifndef QMLJSQTSTYLECODEFORMATTER_H
+#define QMLJSQTSTYLECODEFORMATTER_H
+
+#include "qmljstools_global.h"
+
+#include <texteditor/basetextdocumentlayout.h>
+#include <qmljs/qmljscodeformatter.h>
+
+namespace TextEditor {
+ class TabSettings;
+}
+
+namespace QmlJSTools {
+
+class QMLJSTOOLS_EXPORT QtStyleCodeFormatter : public QmlJS::CodeFormatter
+{
+public:
+ QtStyleCodeFormatter();
+ explicit QtStyleCodeFormatter(const TextEditor::TabSettings &tabSettings);
+
+ void setIndentSize(int size);
+
+protected:
+ virtual void onEnter(int newState, int *indentDepth, int *savedIndentDepth) const;
+ virtual void adjustIndent(const QList<QmlJS::Token> &tokens, int lexerState, int *indentDepth) const;
+
+ virtual void saveBlockData(QTextBlock *block, const BlockData &data) const;
+ virtual bool loadBlockData(const QTextBlock &block, BlockData *data) const;
+
+ virtual void saveLexerState(QTextBlock *block, int state) const;
+ virtual int loadLexerState(const QTextBlock &block) const;
+
+private:
+ int m_indentSize;
+
+ class QmlJSCodeFormatterData: public TextEditor::CodeFormatterData
+ {
+ public:
+ QmlJS::CodeFormatter::BlockData m_data;
+ };
+};
+
+} // namespace QmlJSTools
+
+#endif // QMLJSQTSTYLECODEFORMATTER_H
diff --git a/src/plugins/qmljstools/qmljsrefactoringchanges.cpp b/src/plugins/qmljstools/qmljsrefactoringchanges.cpp
new file mode 100644
index 0000000000..f7eee45185
--- /dev/null
+++ b/src/plugins/qmljstools/qmljsrefactoringchanges.cpp
@@ -0,0 +1,147 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** No Commercial Usage
+**
+** This file 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.
+**
+**************************************************************************/
+
+#include "qmljsrefactoringchanges.h"
+#include "qmljsqtstylecodeformatter.h"
+
+#include <qmljs/parser/qmljsast_p.h>
+#include <qmljs/qmljsmodelmanagerinterface.h>
+#include <texteditor/texteditorsettings.h>
+#include <texteditor/tabsettings.h>
+
+using namespace QmlJS;
+using namespace QmlJSTools;
+
+QmlJSRefactoringChanges::QmlJSRefactoringChanges(ModelManagerInterface *modelManager,
+ const Snapshot &snapshot)
+ : m_modelManager(modelManager)
+ , m_snapshot(snapshot)
+{
+ Q_ASSERT(modelManager);
+}
+
+const Snapshot &QmlJSRefactoringChanges::snapshot() const
+{
+ return m_snapshot;
+}
+
+QmlJSRefactoringFile QmlJSRefactoringChanges::file(const QString &fileName)
+{
+ return QmlJSRefactoringFile(fileName, this);
+}
+
+void QmlJSRefactoringChanges::indentSelection(const QTextCursor &selection) const
+{
+ // ### shares code with QmlJSTextEditor::indent
+ QTextDocument *doc = selection.document();
+
+ QTextBlock block = doc->findBlock(selection.selectionStart());
+ const QTextBlock end = doc->findBlock(selection.selectionEnd()).next();
+
+ const TextEditor::TabSettings &tabSettings(TextEditor::TextEditorSettings::instance()->tabSettings());
+ QtStyleCodeFormatter codeFormatter(tabSettings);
+ codeFormatter.updateStateUntil(block);
+
+ do {
+ tabSettings.indentLine(block, codeFormatter.indentFor(block));
+ codeFormatter.updateLineStateChange(block);
+ block = block.next();
+ } while (block.isValid() && block != end);
+}
+
+void QmlJSRefactoringChanges::fileChanged(const QString &fileName)
+{
+ m_modelManager->updateSourceFiles(QStringList(fileName), true);
+}
+
+
+QmlJSRefactoringFile::QmlJSRefactoringFile()
+{ }
+
+QmlJSRefactoringFile::QmlJSRefactoringFile(const QString &fileName, QmlJSRefactoringChanges *refactoringChanges)
+ : RefactoringFile(fileName, refactoringChanges)
+{ }
+
+QmlJSRefactoringFile::QmlJSRefactoringFile(TextEditor::BaseTextEditor *editor, QmlJS::Document::Ptr document)
+ : RefactoringFile()
+ , m_qmljsDocument(document)
+{
+ m_fileName = document->fileName();
+ m_editor = editor;
+}
+
+Document::Ptr QmlJSRefactoringFile::qmljsDocument() const
+{
+ if (!m_qmljsDocument) {
+ const QString source = document()->toPlainText();
+ const QString name = fileName();
+ const Snapshot &snapshot = refactoringChanges()->snapshot();
+
+ m_qmljsDocument = snapshot.documentFromSource(source, name);
+ m_qmljsDocument->parse();
+ }
+
+ return m_qmljsDocument;
+}
+
+unsigned QmlJSRefactoringFile::startOf(const AST::SourceLocation &loc) const
+{
+ return position(loc.startLine, loc.startColumn);
+}
+
+bool QmlJSRefactoringFile::isCursorOn(AST::UiObjectMember *ast) const
+{
+ const unsigned pos = cursor().position();
+
+ return ast->firstSourceLocation().begin() <= pos
+ && pos <= ast->lastSourceLocation().end();
+}
+
+bool QmlJSRefactoringFile::isCursorOn(AST::UiQualifiedId *ast) const
+{
+ const unsigned pos = cursor().position();
+
+ if (ast->identifierToken.begin() > pos)
+ return false;
+
+ AST::UiQualifiedId *last = ast;
+ while (last->next)
+ last = last->next;
+
+ return pos <= ast->identifierToken.end();
+}
+
+QmlJSRefactoringChanges *QmlJSRefactoringFile::refactoringChanges() const
+{
+ return static_cast<QmlJSRefactoringChanges *>(m_refactoringChanges);
+}
diff --git a/src/plugins/qmljstools/qmljsrefactoringchanges.h b/src/plugins/qmljstools/qmljsrefactoringchanges.h
new file mode 100644
index 0000000000..11a64f1476
--- /dev/null
+++ b/src/plugins/qmljstools/qmljsrefactoringchanges.h
@@ -0,0 +1,97 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** No Commercial Usage
+**
+** This file 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.
+**
+**************************************************************************/
+
+#ifndef QMLREFACTORINGCHANGES_H
+#define QMLREFACTORINGCHANGES_H
+
+#include "qmljstools_global.h"
+
+#include <qmljs/qmljsdocument.h>
+
+#include <texteditor/refactoringchanges.h>
+
+namespace QmlJS {
+class ModelManagerInterface;
+} // namespace QmlJS
+
+namespace QmlJSTools {
+
+class QmlJSRefactoringChanges;
+
+class QMLJSTOOLS_EXPORT QmlJSRefactoringFile: public TextEditor::RefactoringFile
+{
+public:
+ QmlJSRefactoringFile();
+ QmlJSRefactoringFile(const QString &fileName, QmlJSRefactoringChanges *refactoringChanges);
+ QmlJSRefactoringFile(TextEditor::BaseTextEditor *editor, QmlJS::Document::Ptr document);
+
+ QmlJS::Document::Ptr qmljsDocument() const;
+
+ /*!
+ \returns the offset in the document for the start position of the given
+ source location.
+ */
+ unsigned startOf(const QmlJS::AST::SourceLocation &loc) const;
+
+ bool isCursorOn(QmlJS::AST::UiObjectMember *ast) const;
+ bool isCursorOn(QmlJS::AST::UiQualifiedId *ast) const;
+
+private:
+ QmlJSRefactoringChanges *refactoringChanges() const;
+
+ mutable QmlJS::Document::Ptr m_qmljsDocument;
+};
+
+
+class QMLJSTOOLS_EXPORT QmlJSRefactoringChanges: public TextEditor::RefactoringChanges
+{
+public:
+ QmlJSRefactoringChanges(QmlJS::ModelManagerInterface *modelManager,
+ const QmlJS::Snapshot &snapshot);
+
+ const QmlJS::Snapshot &snapshot() const;
+
+ QmlJSRefactoringFile file(const QString &fileName);
+
+private:
+ virtual void indentSelection(const QTextCursor &selection) const;
+ virtual void fileChanged(const QString &fileName);
+
+private:
+ QmlJS::ModelManagerInterface *m_modelManager;
+ QmlJS::Snapshot m_snapshot;
+};
+
+} // namespace QmlJSTools
+
+#endif // QMLREFACTORINGCHANGES_H
diff --git a/src/plugins/qmljstools/qmljstools-lib.pri b/src/plugins/qmljstools/qmljstools-lib.pri
new file mode 100644
index 0000000000..14e1c763de
--- /dev/null
+++ b/src/plugins/qmljstools/qmljstools-lib.pri
@@ -0,0 +1,26 @@
+!dll {
+ DEFINES += QMLJSTOOLS_STATIC
+}
+
+DEPENDPATH += $$PWD
+INCLUDEPATH += $$PWD/..
+
+HEADERS += \
+ $$PWD/qmljstools_global.h \
+ $$PWD/qmljstoolsplugin.h \
+ $$PWD/qmljstoolsconstants.h \
+ $$PWD/qmljsmodelmanager.h \
+ $$PWD/qmljsqtstylecodeformatter.h \
+ $$PWD/qmljsrefactoringchanges.h \
+ $$PWD/qmljsplugindumper.h \
+ $$PWD/qmljsfunctionfilter.h \
+ $$PWD/qmljslocatordata.h
+
+SOURCES += \
+ $$PWD/qmljstoolsplugin.cpp \
+ $$PWD/qmljsmodelmanager.cpp \
+ $$PWD/qmljsqtstylecodeformatter.cpp \
+ $$PWD/qmljsrefactoringchanges.cpp \
+ $$PWD/qmljsplugindumper.cpp \
+ $$PWD/qmljsfunctionfilter.cpp \
+ $$PWD/qmljslocatordata.cpp
diff --git a/src/plugins/qmljstools/qmljstools.pri b/src/plugins/qmljstools/qmljstools.pri
new file mode 100644
index 0000000000..196d757a14
--- /dev/null
+++ b/src/plugins/qmljstools/qmljstools.pri
@@ -0,0 +1,6 @@
+include(qmljstools_dependencies.pri)
+
+DEPENDPATH += $$PWD
+INCLUDEPATH += $$PWD/..
+
+LIBS *= -l$$qtLibraryName(QmlJSTools)
diff --git a/src/plugins/qmljstools/qmljstools.pro b/src/plugins/qmljstools/qmljstools.pro
new file mode 100644
index 0000000000..86426bb3b7
--- /dev/null
+++ b/src/plugins/qmljstools/qmljstools.pro
@@ -0,0 +1,10 @@
+TEMPLATE = lib
+TARGET = QmlJSTools
+include(../../qtcreatorplugin.pri)
+include(qmljstools_dependencies.pri)
+
+# DEFINES += QT_NO_CAST_FROM_ASCII
+DEFINES += QT_NO_CAST_TO_ASCII
+DEFINES += QMLJSTOOLS_LIBRARY
+
+include(qmljstools-lib.pri)
diff --git a/src/plugins/qmljstools/qmljstools_dependencies.pri b/src/plugins/qmljstools/qmljstools_dependencies.pri
new file mode 100644
index 0000000000..81d08c633d
--- /dev/null
+++ b/src/plugins/qmljstools/qmljstools_dependencies.pri
@@ -0,0 +1,3 @@
+include($$IDE_SOURCE_TREE/src/libs/qmljs/qmljs.pri)
+include($$IDE_SOURCE_TREE/src/plugins/projectexplorer/projectexplorer.pri)
+include($$IDE_SOURCE_TREE/src/plugins/texteditor/texteditor.pri)
diff --git a/src/plugins/qmljstools/qmljstools_global.h b/src/plugins/qmljstools/qmljstools_global.h
new file mode 100644
index 0000000000..bc16c2f0dc
--- /dev/null
+++ b/src/plugins/qmljstools/qmljstools_global.h
@@ -0,0 +1,43 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 QMLJSTOOLS_GLOBAL_H
+#define QMLJSTOOLS_GLOBAL_H
+
+#include <QtGlobal>
+
+#if defined(QMLJSTOOLS_LIBRARY)
+# define QMLJSTOOLS_EXPORT Q_DECL_EXPORT
+#elif defined(QMLJSTOOLS_STATIC)
+# define QMLJSTOOLS_EXPORT
+#else
+# define QMLJSTOOLS_EXPORT Q_DECL_IMPORT
+#endif
+
+#endif // QMLJSTOOLS_GLOBAL_H
diff --git a/src/plugins/qmljstools/qmljstoolsconstants.h b/src/plugins/qmljstools/qmljstoolsconstants.h
new file mode 100644
index 0000000000..d30315f6ec
--- /dev/null
+++ b/src/plugins/qmljstools/qmljstoolsconstants.h
@@ -0,0 +1,46 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 QMLJSTOOLS_CONSTANTS_H
+#define QMLJSTOOLS_CONSTANTS_H
+
+#include <QtCore/QtGlobal>
+
+namespace QmlJSTools {
+namespace Constants {
+
+const char * const QML_MIMETYPE = "application/x-qml";
+const char * const JS_MIMETYPE = "application/javascript";
+
+const char * const TASK_INDEX = "QmlJSEditor.TaskIndex";
+
+} // namespace Constants
+} // namespace QmlJSEditor
+
+#endif // QMLJSTOOLS_CONSTANTS_H
diff --git a/src/plugins/qmljstools/qmljstoolsplugin.cpp b/src/plugins/qmljstools/qmljstoolsplugin.cpp
new file mode 100644
index 0000000000..7c6b30584e
--- /dev/null
+++ b/src/plugins/qmljstools/qmljstoolsplugin.cpp
@@ -0,0 +1,95 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "qmljstoolsplugin.h"
+#include "qmljsmodelmanager.h"
+#include "qmljsfunctionfilter.h"
+#include "qmljslocatordata.h"
+
+#include <extensionsystem/pluginmanager.h>
+
+#include <coreplugin/icore.h>
+
+#include <QtCore/QtPlugin>
+#include <QtCore/QFileInfo>
+#include <QtCore/QDir>
+#include <QtCore/QDebug>
+#include <QtCore/QSettings>
+
+using namespace QmlJSTools::Internal;
+
+enum { debug = 0 };
+
+QmlJSToolsPlugin *QmlJSToolsPlugin::m_instance = 0;
+
+QmlJSToolsPlugin::QmlJSToolsPlugin()
+ : m_modelManager(0)
+{
+ m_instance = this;
+}
+
+QmlJSToolsPlugin::~QmlJSToolsPlugin()
+{
+ m_instance = 0;
+ m_modelManager = 0; // deleted automatically
+}
+
+bool QmlJSToolsPlugin::initialize(const QStringList &arguments, QString *error)
+{
+ Q_UNUSED(arguments)
+ Q_UNUSED(error)
+// Core::ICore *core = Core::ICore::instance();
+
+ // Objects
+ m_modelManager = new ModelManager(this);
+// Core::VCSManager *vcsManager = core->vcsManager();
+// Core::FileManager *fileManager = core->fileManager();
+// connect(vcsManager, SIGNAL(repositoryChanged(QString)),
+// m_modelManager, SLOT(updateModifiedSourceFiles()));
+// connect(fileManager, SIGNAL(filesChangedInternally(QStringList)),
+// m_modelManager, SLOT(updateSourceFiles(QStringList)));
+ addAutoReleasedObject(m_modelManager);
+
+ LocatorData *locatorData = new LocatorData;
+ addAutoReleasedObject(locatorData);
+ addAutoReleasedObject(new FunctionFilter(locatorData));
+
+ return true;
+}
+
+void QmlJSToolsPlugin::extensionsInitialized()
+{
+}
+
+ExtensionSystem::IPlugin::ShutdownFlag QmlJSToolsPlugin::aboutToShutdown()
+{
+ return SynchronousShutdown;
+}
+
+Q_EXPORT_PLUGIN(QmlJSToolsPlugin)
diff --git a/src/plugins/qmljstools/qmljstoolsplugin.h b/src/plugins/qmljstools/qmljstoolsplugin.h
new file mode 100644
index 0000000000..4d6890539b
--- /dev/null
+++ b/src/plugins/qmljstools/qmljstoolsplugin.h
@@ -0,0 +1,73 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 QMLJSTOOLS_H
+#define QMLJSTOOLS_H
+
+#include <extensionsystem/iplugin.h>
+#include <projectexplorer/projectexplorer.h>
+
+#include <QtGui/QTextDocument>
+#include <QtCore/QSharedPointer>
+
+QT_BEGIN_NAMESPACE
+class QFileInfo;
+class QDir;
+QT_END_NAMESPACE
+
+namespace QmlJSTools {
+namespace Internal {
+
+class ModelManager;
+
+class QmlJSToolsPlugin : public ExtensionSystem::IPlugin
+{
+ Q_DISABLE_COPY(QmlJSToolsPlugin)
+ Q_OBJECT
+public:
+ static QmlJSToolsPlugin *instance() { return m_instance; }
+
+ QmlJSToolsPlugin();
+ ~QmlJSToolsPlugin();
+
+ bool initialize(const QStringList &arguments, QString *error_message);
+ void extensionsInitialized();
+ ShutdownFlag aboutToShutdown();
+ ModelManager *modelManager() { return m_modelManager; }
+
+private:
+ ModelManager *m_modelManager;
+
+ static QmlJSToolsPlugin *m_instance;
+};
+
+} // namespace Internal
+} // namespace CppTools
+
+#endif // QMLJSTOOLS_H
diff --git a/src/plugins/qmlprojectmanager/QmlProjectManager.pluginspec b/src/plugins/qmlprojectmanager/QmlProjectManager.pluginspec
deleted file mode 100644
index d848b89067..0000000000
--- a/src/plugins/qmlprojectmanager/QmlProjectManager.pluginspec
+++ /dev/null
@@ -1,23 +0,0 @@
-<plugin name="QmlProjectManager" version="2.0.95" compatVersion="2.0.95">
- <vendor>Nokia Corporation</vendor>
- <copyright>(C) 2010 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>
- <category>Qt Quick</category>
- <description>Qt Quick support</description>
- <url>http://qt.nokia.com</url>
- <dependencyList>
- <dependency name="ProjectExplorer" version="2.0.95"/>
- <dependency name="TextEditor" version="2.0.95"/>
- <dependency name="QmlJSEditor" version="2.0.95"/>
- <dependency name="Debugger" version="2.0.95" />
- <dependency name="Qt4ProjectManager" version="2.0.95" />
- </dependencyList>
-</plugin>
diff --git a/src/plugins/qmlprojectmanager/QmlProjectManager.pluginspec.in b/src/plugins/qmlprojectmanager/QmlProjectManager.pluginspec.in
new file mode 100644
index 0000000000..249636e1fc
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/QmlProjectManager.pluginspec.in
@@ -0,0 +1,23 @@
+<plugin name=\"QmlProjectManager\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2010 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>
+ <category>Qt Quick</category>
+ <description>Qt Quick support</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name=\"ProjectExplorer\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"TextEditor\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"QmlJSEditor\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"Debugger\" version=\"$$QTCREATOR_VERSION\" />
+ <dependency name=\"Qt4ProjectManager\" version=\"$$QTCREATOR_VERSION\" />
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/qmlprojectmanager/fileformat/filefilteritems.cpp b/src/plugins/qmlprojectmanager/fileformat/filefilteritems.cpp
index 85bcff190d..f5e9c78afd 100644
--- a/src/plugins/qmlprojectmanager/fileformat/filefilteritems.cpp
+++ b/src/plugins/qmlprojectmanager/fileformat/filefilteritems.cpp
@@ -50,7 +50,21 @@ void FileFilterBaseItem::setFilter(const QString &filter)
m_filter = filter;
m_regExpList.clear();
+ m_fileSuffixes.clear();
+
foreach (const QString &pattern, filter.split(QLatin1Char(';'))) {
+ if (pattern.isEmpty())
+ continue;
+ // decide if it's a canonical pattern like *.x
+ if (pattern.startsWith(QLatin1String("*."))) {
+ const QString suffix = pattern.right(pattern.size() - 1);
+ if (!suffix.contains(QLatin1Char('*'))
+ && !suffix.contains(QLatin1Char('?'))
+ && !suffix.contains(QLatin1Char('['))) {
+ m_fileSuffixes << suffix;
+ continue;
+ }
+ }
m_regExpList << QRegExp(pattern, Qt::CaseInsensitive, QRegExp::Wildcard);
}
@@ -116,16 +130,9 @@ bool FileFilterBaseItem::matchesFile(const QString &filePath) const
return true;
}
- bool regexMatches = false;
const QString &fileName = QFileInfo(filePath).fileName();
- foreach (const QRegExp &exp, m_regExpList) {
- if (exp.exactMatch(fileName)) {
- regexMatches = true;
- break;
- }
- }
- if (!regexMatches)
+ if (!fileMatches(fileName))
return false;
const QDir fileDir = QFileInfo(filePath).absoluteDir();
@@ -176,7 +183,7 @@ void FileFilterBaseItem::updateFileListNow()
foreach (const QString &explicitPath, m_explicitFiles) {
newFiles << absolutePath(explicitPath);
}
- if (!m_regExpList.isEmpty() && m_explicitFiles.isEmpty())
+ if ((!m_fileSuffixes.isEmpty() || !m_regExpList.isEmpty()) && m_explicitFiles.isEmpty())
newFiles += filesInSubTree(QDir(m_defaultDir), QDir(projectDir), &dirsToBeWatched);
if (newFiles != m_files) {
@@ -202,6 +209,23 @@ void FileFilterBaseItem::updateFileListNow()
m_dirWatcher.addDirectories(watchDirs.toList());
}
+bool FileFilterBaseItem::fileMatches(const QString &fileName) const
+{
+ foreach (const QString &suffix, m_fileSuffixes) {
+ if (fileName.endsWith(suffix, Qt::CaseInsensitive)) {
+ return true;
+ }
+ }
+
+ foreach (const QRegExp &filter, m_regExpList) {
+ if (filter.exactMatch(fileName)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
QSet<QString> FileFilterBaseItem::filesInSubTree(const QDir &rootDir, const QDir &dir, QSet<QString> *parsedDirs)
{
QSet<QString> fileSet;
@@ -211,12 +235,9 @@ QSet<QString> FileFilterBaseItem::filesInSubTree(const QDir &rootDir, const QDir
foreach (const QFileInfo &file, dir.entryInfoList(QDir::Files)) {
const QString fileName = file.fileName();
- foreach (const QRegExp &filter, m_regExpList) {
- if (filter.exactMatch(fileName)) {
- fileSet.insert(file.absoluteFilePath());
- break;
- }
- }
+
+ if (fileMatches(fileName))
+ fileSet.insert(file.absoluteFilePath());
}
if (recursive()) {
@@ -275,5 +296,16 @@ void CssFileFilterItem::setFilter(const QString &filter)
emit filterChanged();
}
+OtherFileFilterItem::OtherFileFilterItem(QObject *parent)
+ : FileFilterBaseItem(parent)
+{
+}
+
+void OtherFileFilterItem::setFilter(const QString &filter)
+{
+ FileFilterBaseItem::setFilter(filter);
+ emit filterChanged();
+}
+
} // namespace QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/fileformat/filefilteritems.h b/src/plugins/qmlprojectmanager/fileformat/filefilteritems.h
index 42a244e5d4..ac007d1f38 100644
--- a/src/plugins/qmlprojectmanager/fileformat/filefilteritems.h
+++ b/src/plugins/qmlprojectmanager/fileformat/filefilteritems.h
@@ -56,12 +56,15 @@ private:
QString absolutePath(const QString &path) const;
QString absoluteDir() const;
+ bool fileMatches(const QString &fileName) const;
QSet<QString> filesInSubTree(const QDir &rootDir, const QDir &dir, QSet<QString> *parsedDirs = 0);
QString m_rootDir;
QString m_defaultDir;
QString m_filter;
+ // simple "*.png" patterns are stored in m_fileSuffixes, otherwise store in m_regExpList
+ QList<QString> m_fileSuffixes;
QList<QRegExp> m_regExpList;
enum RecursiveOption {
@@ -128,11 +131,25 @@ public:
CssFileFilterItem(QObject *parent = 0);
};
+class OtherFileFilterItem : public FileFilterBaseItem {
+ Q_OBJECT
+ Q_PROPERTY(QString filter READ filter WRITE setFilter NOTIFY filterChanged)
+
+ void setFilter(const QString &filter);
+
+signals:
+ void filterChanged();
+
+public:
+ OtherFileFilterItem(QObject *parent = 0);
+};
+
} // namespace QmlProjectManager
QML_DECLARE_TYPE(QmlProjectManager::QmlFileFilterItem)
QML_DECLARE_TYPE(QmlProjectManager::JsFileFilterItem)
QML_DECLARE_TYPE(QmlProjectManager::ImageFileFilterItem)
QML_DECLARE_TYPE(QmlProjectManager::CssFileFilterItem)
+QML_DECLARE_TYPE(QmlProjectManager::OtherFileFilterItem)
#endif // FILEFILTERITEMS_HPROJECTITEM_H
diff --git a/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp b/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp
index 46b624fec4..220deb62c3 100644
--- a/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp
+++ b/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp
@@ -10,11 +10,17 @@ void QmlProjectFileFormat::registerDeclarativeTypes()
{
qmlRegisterType<QmlProjectManager::QmlProjectContentItem>();
qmlRegisterType<QmlProjectManager::QmlProjectItem>("QmlProject",1,0,"Project");
+ qmlRegisterType<QmlProjectManager::QmlProjectItem>("QmlProject",1,1,"Project");
qmlRegisterType<QmlProjectManager::QmlFileFilterItem>("QmlProject",1,0,"QmlFiles");
+ qmlRegisterType<QmlProjectManager::QmlFileFilterItem>("QmlProject",1,1,"QmlFiles");
qmlRegisterType<QmlProjectManager::JsFileFilterItem>("QmlProject",1,0,"JavaScriptFiles");
+ qmlRegisterType<QmlProjectManager::JsFileFilterItem>("QmlProject",1,1,"JavaScriptFiles");
qmlRegisterType<QmlProjectManager::ImageFileFilterItem>("QmlProject",1,0,"ImageFiles");
+ qmlRegisterType<QmlProjectManager::ImageFileFilterItem>("QmlProject",1,1,"ImageFiles");
qmlRegisterType<QmlProjectManager::CssFileFilterItem>("QmlProject",1,0,"CssFiles");
+ qmlRegisterType<QmlProjectManager::CssFileFilterItem>("QmlProject",1,1,"CssFiles");
+ qmlRegisterType<QmlProjectManager::OtherFileFilterItem>("QmlProject",1,1,"Files");
}
} // namespace QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.cpp b/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.cpp
index 8abc6eac7d..a0a7b275bb 100644
--- a/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.cpp
+++ b/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.cpp
@@ -11,6 +11,7 @@ public:
QString sourceDirectory;
QStringList importPaths;
QStringList absoluteImportPaths;
+ QString mainFile;
QList<QmlFileFilterItem*> qmlFileFilters() const;
@@ -148,6 +149,21 @@ bool QmlProjectItem::matchesFile(const QString &filePath) const
return false;
}
+QString QmlProjectItem::mainFile() const
+{
+ Q_D(const QmlProjectItem);
+ return d->mainFile;
+}
+
+void QmlProjectItem::setMainFile(const QString &mainFilePath)
+{
+ Q_D(QmlProjectItem);
+ if (mainFilePath == d->mainFile)
+ return;
+ d->mainFile = mainFilePath;
+ emit mainFileChanged();
+}
+
} // namespace QmlProjectManager
#include "qmlprojectitem.moc"
diff --git a/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.h b/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.h
index 32a2f1df53..5b92169792 100644
--- a/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.h
+++ b/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.h
@@ -25,8 +25,9 @@ class QmlProjectItem : public QObject {
Q_PROPERTY(QDeclarativeListProperty<QmlProjectManager::QmlProjectContentItem> content READ content DESIGNABLE false)
Q_PROPERTY(QString sourceDirectory READ sourceDirectory NOTIFY sourceDirectoryChanged)
Q_PROPERTY(QStringList importPaths READ importPaths WRITE setImportPaths NOTIFY importPathsChanged)
+ Q_PROPERTY(QString mainFile READ mainFile WRITE setMainFile NOTIFY mainFileChanged)
- Q_CLASSINFO("DefaultProperty", "content");
+ Q_CLASSINFO("DefaultProperty", "content")
public:
QmlProjectItem(QObject *parent = 0);
@@ -43,10 +44,15 @@ public:
QStringList files() const;
bool matchesFile(const QString &filePath) const;
+ QString mainFile() const;
+ void setMainFile(const QString &mainFilePath);
+
+
signals:
void qmlFilesChanged(const QSet<QString> &, const QSet<QString> &);
void sourceDirectoryChanged();
void importPathsChanged();
+ void mainFileChanged();
protected:
QmlProjectItemPrivate *d_ptr;
@@ -54,8 +60,8 @@ protected:
} // namespace QmlProjectManager
-QML_DECLARE_TYPE(QmlProjectManager::QmlProjectItem);
-QML_DECLARE_TYPE(QmlProjectManager::QmlProjectContentItem);
-Q_DECLARE_METATYPE(QList<QmlProjectManager::QmlProjectContentItem *>);
+QML_DECLARE_TYPE(QmlProjectManager::QmlProjectItem)
+QML_DECLARE_TYPE(QmlProjectManager::QmlProjectContentItem)
+Q_DECLARE_METATYPE(QList<QmlProjectManager::QmlProjectContentItem *>)
#endif // QMLPROJECTITEM_H
diff --git a/src/plugins/qmlprojectmanager/qmlproject.cpp b/src/plugins/qmlprojectmanager/qmlproject.cpp
index 9a9a4ed679..bf225b79c1 100644
--- a/src/plugins/qmlprojectmanager/qmlproject.cpp
+++ b/src/plugins/qmlprojectmanager/qmlproject.cpp
@@ -36,6 +36,7 @@
#include "qmlprojectmanagerconstants.h"
#include "fileformat/qmlprojectitem.h"
#include "qmlprojectrunconfiguration.h"
+#include "qmlprojecttarget.h"
#include <coreplugin/icore.h>
#include <coreplugin/messagemanager.h>
@@ -55,8 +56,7 @@ QmlProject::QmlProject(Internal::Manager *manager, const QString &fileName)
: m_manager(manager),
m_fileName(fileName),
m_modelManager(ExtensionSystem::PluginManager::instance()->getObject<QmlJS::ModelManagerInterface>()),
- m_fileWatcher(new ProjectExplorer::FileWatcher(this)),
- m_targetFactory(new Internal::QmlProjectTargetFactory(this))
+ m_fileWatcher(new ProjectExplorer::FileWatcher(this))
{
setSupportedTargetIds(QSet<QString>() << QLatin1String(Constants::QML_VIEWER_TARGET_ID));
QFileInfo fileInfo(m_fileName);
@@ -162,6 +162,13 @@ QStringList QmlProject::files() const
return files;
}
+QString QmlProject::mainFile() const
+{
+ if (m_projectItem)
+ return m_projectItem.data()->mainFile();
+ return QString();
+}
+
bool QmlProject::validProjectFile() const
{
return !m_projectItem.isNull();
@@ -237,21 +244,11 @@ QList<ProjectExplorer::Project *> QmlProject::dependsOn()
return QList<Project *>();
}
-ProjectExplorer::BuildConfigWidget *QmlProject::createConfigWidget()
-{
- return 0;
-}
-
QList<ProjectExplorer::BuildConfigWidget*> QmlProject::subConfigWidgets()
{
return QList<ProjectExplorer::BuildConfigWidget*>();
}
-Internal::QmlProjectTargetFactory *QmlProject::targetFactory() const
-{
- return m_targetFactory;
-}
-
Internal::QmlProjectTarget *QmlProject::activeTarget() const
{
return static_cast<Internal::QmlProjectTarget *>(Project::activeTarget());
@@ -273,7 +270,9 @@ bool QmlProject::fromMap(const QVariantMap &map)
return false;
if (targets().isEmpty()) {
- Internal::QmlProjectTarget *target(targetFactory()->create(this, QLatin1String(Constants::QML_VIEWER_TARGET_ID)));
+ Internal::QmlProjectTargetFactory *factory
+ = ExtensionSystem::PluginManager::instance()->getObject<Internal::QmlProjectTargetFactory>();
+ Internal::QmlProjectTarget *target = factory->create(this, QLatin1String(Constants::QML_VIEWER_TARGET_ID));
addTarget(target);
}
diff --git a/src/plugins/qmlprojectmanager/qmlproject.h b/src/plugins/qmlprojectmanager/qmlproject.h
index 065213a883..a437878287 100644
--- a/src/plugins/qmlprojectmanager/qmlproject.h
+++ b/src/plugins/qmlprojectmanager/qmlproject.h
@@ -76,12 +76,10 @@ public:
QString id() const;
Core::IFile *file() const;
Internal::Manager *projectManager() const;
- Internal::QmlProjectTargetFactory *targetFactory() const;
Internal::QmlProjectTarget *activeTarget() const;
QList<ProjectExplorer::Project *> dependsOn();
- ProjectExplorer::BuildConfigWidget *createConfigWidget();
QList<ProjectExplorer::BuildConfigWidget*> subConfigWidgets();
Internal::QmlProjectNode *rootProjectNode() const;
@@ -101,6 +99,7 @@ public:
QDir projectDir() const;
QStringList files() const;
+ QString mainFile() const;
QStringList importPaths() const;
bool addFiles(const QStringList &filePaths);
@@ -132,8 +131,6 @@ private:
ProjectExplorer::FileWatcher *m_fileWatcher;
Internal::QmlProjectNode *m_rootNode;
- Internal::QmlProjectTargetFactory *m_targetFactory;
-
};
} // namespace QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/qmlprojectapplicationwizard.cpp b/src/plugins/qmlprojectmanager/qmlprojectapplicationwizard.cpp
index caacb45a86..d95e8477a6 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectapplicationwizard.cpp
+++ b/src/plugins/qmlprojectmanager/qmlprojectapplicationwizard.cpp
@@ -35,6 +35,7 @@
#include "qmlprojectconstants.h"
+#include <coreplugin/coreconstants.h>
#include <projectexplorer/customwizard/customwizard.h>
#include <qt4projectmanager/qt4projectmanagerconstants.h>
@@ -43,6 +44,7 @@
#include <QtGui/QPainter>
#include <QtGui/QPixmap>
+#include <QtCore/QDir>
#include <QtCore/QTextStream>
#include <QtCore/QCoreApplication>
@@ -145,12 +147,16 @@ Core::GeneratedFiles QmlProjectApplicationWizard::generateFiles(const QWizard *w
out
//: Comment added to generated .qmlproject file
- << "/* " << tr("File generated by QtCreator", "qmlproject Template") << " */" << endl
+ << "/* "
+ << tr("File generated by QtCreator, version %1",
+ "qmlproject Template").arg(Core::Constants::IDE_VERSION_LONG) << " */" << endl
<< endl
- << "import QmlProject 1.0" << endl
+ << "import QmlProject 1.1" << endl
<< endl
<< "Project {" << endl
//: Comment added to generated .qmlproject file
+ << " mainFile: \"" << QDir(projectPath).relativeFilePath(mainFileName) << "\"" << endl
+ << endl
<< " /* " << tr("Include .qml, .js, and image files from current directory and subdirectories", "qmlproject Template") << " */" << endl
<< " QmlFiles {" << endl
<< " directory: \".\"" << endl
diff --git a/src/plugins/qmlprojectmanager/qmlprojectmanager.h b/src/plugins/qmlprojectmanager/qmlprojectmanager.h
index b8870e3bd5..323a97e34a 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectmanager.h
+++ b/src/plugins/qmlprojectmanager/qmlprojectmanager.h
@@ -35,6 +35,7 @@
#define QMLPROJECTMANAGER_H
#include <projectexplorer/iprojectmanager.h>
+#include <coreplugin/icontext.h>
namespace QmlProjectManager {
diff --git a/src/plugins/qmlprojectmanager/qmlprojectmanager.pri b/src/plugins/qmlprojectmanager/qmlprojectmanager.pri
index fc1adf24f3..948a5f9cc6 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectmanager.pri
+++ b/src/plugins/qmlprojectmanager/qmlprojectmanager.pri
@@ -1,2 +1,2 @@
include(qmlprojectmanager_dependencies.pri)
-LIBS *= -l$$qtLibraryTarget(QmlProjectManager)
+LIBS *= -l$$qtLibraryName(QmlProjectManager)
diff --git a/src/plugins/qmlprojectmanager/qmlprojectmanager.pro b/src/plugins/qmlprojectmanager/qmlprojectmanager.pro
index d18c79999b..d328ba303b 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectmanager.pro
+++ b/src/plugins/qmlprojectmanager/qmlprojectmanager.pro
@@ -20,7 +20,8 @@ HEADERS += qmlproject.h \
qmlprojectapplicationwizard.h \
qmlprojectmanager_global.h \
qmlprojectmanagerconstants.h \
- qmlprojecttarget.h
+ qmlprojecttarget.h \
+ qmlprojectrunconfigurationwidget.h
SOURCES += qmlproject.cpp \
qmlprojectplugin.cpp \
@@ -31,9 +32,9 @@ SOURCES += qmlproject.cpp \
qmlprojectrunconfiguration.cpp \
qmlprojectrunconfigurationfactory.cpp \
qmlprojectapplicationwizard.cpp \
- qmlprojecttarget.cpp
+ qmlprojecttarget.cpp \
+ qmlprojectrunconfigurationwidget.cpp
RESOURCES += qmlproject.qrc
-OTHER_FILES += QmlProjectManager.pluginspec \
- QmlProject.mimetypes.xml
+OTHER_FILES += QmlProject.mimetypes.xml
diff --git a/src/plugins/qmlprojectmanager/qmlprojectmanagerconstants.h b/src/plugins/qmlprojectmanager/qmlprojectmanagerconstants.h
index aecb86b0e6..1a2c2b3a0f 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectmanagerconstants.h
+++ b/src/plugins/qmlprojectmanager/qmlprojectmanagerconstants.h
@@ -43,6 +43,8 @@ const char * const QML_VIEWER_ARGUMENTS_KEY = "QmlProjectManager.QmlRunConfigura
const char * const QML_VIEWER_TARGET_ID = "QmlProjectManager.QmlTarget";
const char * const QML_VIEWER_TARGET_DISPLAY_NAME = "QML Viewer";
const char * const QML_MAINSCRIPT_KEY = "QmlProjectManager.QmlRunConfiguration.MainScript";
+const char * const USER_ENVIRONMENT_CHANGES_KEY("QmlProjectManager.QmlRunConfiguration.UserEnvironmentChanges");
+
} // namespace Constants
} // namespace QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp b/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp
index 5eb2c036e2..ea203cbac9 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp
+++ b/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp
@@ -80,6 +80,7 @@ bool QmlProjectPlugin::initialize(const QStringList &, QString *errorMessage)
addAutoReleasedObject(new Internal::QmlProjectRunConfigurationFactory);
addAutoReleasedObject(new Internal::QmlRunControlFactory);
addAutoReleasedObject(new QmlProjectApplicationWizard);
+ addAutoReleasedObject(new QmlProjectTargetFactory);
QmlProjectFileFormat::registerDeclarativeTypes();
diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp
index d7db2022e3..311947a44b 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp
+++ b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp
@@ -34,39 +34,31 @@
#include "qmlprojectrunconfiguration.h"
#include "qmlproject.h"
#include "qmlprojectmanagerconstants.h"
-#include "qmlprojecttarget.h"
-#include "projectexplorer/projectexplorer.h"
+#include "qmlprojectrunconfigurationwidget.h"
#include <coreplugin/mimedatabase.h>
-#include <projectexplorer/buildconfiguration.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/icore.h>
-#include <coreplugin/ifile.h>
-#include <utils/synchronousprocess.h>
-#include <utils/pathchooser.h>
-#include <utils/debuggerlanguagechooser.h>
-#include <utils/detailswidget.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <qt4projectmanager/qtversionmanager.h>
-#include <qt4projectmanager/qt4projectmanagerconstants.h>
-#include <qt4projectmanager/qmlobservertool.h>
#include <qt4projectmanager/qtoutputformatter.h>
+#include <qt4projectmanager/qt4projectmanagerconstants.h>
+
+using Core::EditorManager;
+using Core::ICore;
+using Core::IEditor;
+using Qt4ProjectManager::QtVersionManager;
-#include <QFormLayout>
-#include <QComboBox>
-#include <QCoreApplication>
-#include <QLineEdit>
-#include <QPushButton>
-#include <QSpinBox>
-#include <QStringListModel>
-#include <QDebug>
+using namespace QmlProjectManager::Internal;
namespace QmlProjectManager {
-QmlProjectRunConfiguration::QmlProjectRunConfiguration(Internal::QmlProjectTarget *parent) :
+const char * const M_CURRENT_FILE = "CurrentFile";
+
+QmlProjectRunConfiguration::QmlProjectRunConfiguration(QmlProjectTarget *parent) :
ProjectExplorer::RunConfiguration(parent, QLatin1String(Constants::QML_RC_ID)),
m_qtVersionId(-1),
- m_fileListModel(new QStringListModel(this)),
m_projectTarget(parent),
m_usingCurrentFile(true),
m_isEnabled(false)
@@ -75,15 +67,17 @@ QmlProjectRunConfiguration::QmlProjectRunConfiguration(Internal::QmlProjectTarge
updateQtVersions();
}
-QmlProjectRunConfiguration::QmlProjectRunConfiguration(Internal::QmlProjectTarget *parent, QmlProjectRunConfiguration *source) :
+QmlProjectRunConfiguration::QmlProjectRunConfiguration(QmlProjectTarget *parent,
+ QmlProjectRunConfiguration *source) :
ProjectExplorer::RunConfiguration(parent, source),
m_qtVersionId(source->m_qtVersionId),
+ m_scriptFile(source->m_scriptFile),
m_qmlViewerArgs(source->m_qmlViewerArgs),
- m_fileListModel(new QStringListModel(this)),
- m_projectTarget(parent)
+ m_projectTarget(parent),
+ m_usingCurrentFile(source->m_usingCurrentFile),
+ m_userEnvironmentChanges(source->m_userEnvironmentChanges)
{
ctor();
- setMainScript(source->m_scriptFile);
updateQtVersions();
}
@@ -100,11 +94,11 @@ void QmlProjectRunConfiguration::ctor()
setUseCppDebugger(false);
setUseQmlDebugger(true);
- Core::EditorManager *em = Core::EditorManager::instance();
+ EditorManager *em = Core::EditorManager::instance();
connect(em, SIGNAL(currentEditorChanged(Core::IEditor*)),
this, SLOT(changeCurrentFile(Core::IEditor*)));
- Qt4ProjectManager::QtVersionManager *qtVersions = Qt4ProjectManager::QtVersionManager::instance();
+ QtVersionManager *qtVersions = QtVersionManager::instance();
connect(qtVersions, SIGNAL(qtVersionsChanged(QList<int>)), this, SLOT(updateQtVersions()));
setDisplayName(tr("QML Viewer", "QMLRunConfiguration display name."));
@@ -114,9 +108,9 @@ QmlProjectRunConfiguration::~QmlProjectRunConfiguration()
{
}
-Internal::QmlProjectTarget *QmlProjectRunConfiguration::qmlTarget() const
+QmlProjectTarget *QmlProjectRunConfiguration::qmlTarget() const
{
- return static_cast<Internal::QmlProjectTarget *>(target());
+ return static_cast<QmlProjectTarget *>(target());
}
QString QmlProjectRunConfiguration::viewerPath() const
@@ -139,23 +133,20 @@ QString QmlProjectRunConfiguration::observerPath() const
}
}
-QStringList QmlProjectRunConfiguration::viewerArguments() const
+QString QmlProjectRunConfiguration::viewerArguments() const
{
- QStringList args;
-
// arguments in .user file
- if (!m_qmlViewerArgs.isEmpty())
- args.append(m_qmlViewerArgs.split(QLatin1Char(' ')));
+ QString args = m_qmlViewerArgs;
// arguments from .qmlproject file
foreach (const QString &importPath, qmlTarget()->qmlProject()->importPaths()) {
- args.append(QLatin1String("-I"));
- args.append(importPath);
+ Utils::QtcProcess::addArg(&args, "-I");
+ Utils::QtcProcess::addArg(&args, importPath);
}
- const QString s = mainScript();
- if (! s.isEmpty())
- args.append(s);
+ const QString &s = mainScript();
+ if (!s.isEmpty())
+ Utils::QtcProcess::addArg(&args, s);
return args;
}
@@ -177,6 +168,8 @@ void QmlProjectRunConfiguration::setQtVersionId(int id)
m_qtVersionId = id;
qmlTarget()->qmlProject()->refresh(QmlProject::Configuration);
+ if (m_configurationWidget)
+ m_configurationWidget.data()->updateQtVersionComboBox();
}
Qt4ProjectManager::QtVersion *QmlProjectRunConfiguration::qtVersion() const
@@ -184,83 +177,18 @@ Qt4ProjectManager::QtVersion *QmlProjectRunConfiguration::qtVersion() const
if (m_qtVersionId == -1)
return 0;
- Qt4ProjectManager::QtVersionManager *versionManager = Qt4ProjectManager::QtVersionManager::instance();
+ QtVersionManager *versionManager = QtVersionManager::instance();
Qt4ProjectManager::QtVersion *version = versionManager->version(m_qtVersionId);
QTC_ASSERT(version, return 0);
return version;
}
-static bool caseInsensitiveLessThan(const QString &s1, const QString &s2)
-{
- return s1.toLower() < s2.toLower();
-}
-
QWidget *QmlProjectRunConfiguration::createConfigurationWidget()
{
- Utils::DetailsWidget *detailsWidget = new Utils::DetailsWidget();
- detailsWidget->setState(Utils::DetailsWidget::NoSummary);
-
- QWidget *formWidget = new QWidget(detailsWidget);
- detailsWidget->setWidget(formWidget);
- QFormLayout *form = new QFormLayout(formWidget);
- form->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
-
- m_fileListCombo = new QComboBox;
- m_fileListCombo.data()->setModel(m_fileListModel);
- updateFileComboBox();
-
- connect(m_fileListCombo.data(), SIGNAL(activated(QString)), this, SLOT(setMainScript(QString)));
- connect(ProjectExplorer::ProjectExplorerPlugin::instance(), SIGNAL(fileListChanged()), SLOT(updateFileComboBox()));
-
- m_qtVersionComboBox = new QComboBox;
- m_qtVersionComboBox.data()->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
- connect(m_qtVersionComboBox.data(), SIGNAL(activated(int)), this, SLOT(onQtVersionSelectionChanged()));
-
- QPushButton *pushButton = new QPushButton;
- pushButton->setText(tr("Manage Qt versions"));
- connect(pushButton, SIGNAL(clicked()), this, SLOT(manageQtVersions()));
-
- QHBoxLayout *qtVersionLayout = new QHBoxLayout;
- qtVersionLayout->addWidget(m_qtVersionComboBox.data());
- qtVersionLayout->addWidget(pushButton);
-
- QLineEdit *qmlViewerArgs = new QLineEdit;
- qmlViewerArgs->setText(m_qmlViewerArgs);
- connect(qmlViewerArgs, SIGNAL(textChanged(QString)), this, SLOT(onViewerArgsChanged()));
-
- form->addRow(tr("Qt version:"), qtVersionLayout);
- form->addRow(tr("Arguments:"), qmlViewerArgs);
-
- QWidget *debuggerLabelWidget = new QWidget;
- QVBoxLayout *debuggerLabelLayout = new QVBoxLayout(debuggerLabelWidget);
- debuggerLabelLayout->setMargin(0);
- debuggerLabelLayout->setSpacing(0);
- debuggerLabelWidget->setLayout(debuggerLabelLayout);
- QLabel *debuggerLabel = new QLabel(tr("Debugger:"));
- debuggerLabelLayout->addWidget(debuggerLabel);
- debuggerLabelLayout->addStretch(10);
-
- Utils::DebuggerLanguageChooser *debuggerLanguageChooser = new Utils::DebuggerLanguageChooser(formWidget);
-
- form->addRow(tr("Main QML file:"), m_fileListCombo.data());
- form->addRow(debuggerLabelWidget, debuggerLanguageChooser);
-
- debuggerLanguageChooser->setCppChecked(useCppDebugger());
- debuggerLanguageChooser->setQmlChecked(useQmlDebugger());
- debuggerLanguageChooser->setQmlDebugServerPort(qmlDebugServerPort());
-
- connect(debuggerLanguageChooser, SIGNAL(cppLanguageToggled(bool)),
- this, SLOT(useCppDebuggerToggled(bool)));
- connect(debuggerLanguageChooser, SIGNAL(qmlLanguageToggled(bool)),
- this, SLOT(useQmlDebuggerToggled(bool)));
- connect(debuggerLanguageChooser, SIGNAL(qmlDebugServerPortChanged(uint)),
- this, SLOT(qmlDebugServerPortChanged(uint)));
-
- updateQtVersions();
- updateEnabled();
-
- return detailsWidget;
+ QTC_ASSERT(m_configurationWidget.isNull(), return m_configurationWidget.data());
+ m_configurationWidget = new QmlProjectRunConfigurationWidget(this);
+ return m_configurationWidget.data();
}
ProjectExplorer::OutputFormatter *QmlProjectRunConfiguration::createOutputFormatter() const
@@ -268,90 +196,65 @@ ProjectExplorer::OutputFormatter *QmlProjectRunConfiguration::createOutputFormat
return new Qt4ProjectManager::QtOutputFormatter(qmlTarget()->qmlProject());
}
-QString QmlProjectRunConfiguration::mainScript() const
+QmlProjectRunConfiguration::MainScriptSource QmlProjectRunConfiguration::mainScriptSource() const
{
- if (m_usingCurrentFile)
- return m_currentFileFilename;
-
- return m_mainScriptFilename;
+ if (m_usingCurrentFile) {
+ return FileInEditor;
+ }
+ if (!m_mainScriptFilename.isEmpty()) {
+ return FileInSettings;
+ }
+ return FileInProjectFile;
}
-void QmlProjectRunConfiguration::updateFileComboBox()
+/**
+ Returns absolute path to main script file.
+ */
+QString QmlProjectRunConfiguration::mainScript() const
{
- if (m_fileListCombo.isNull())
- return;
-
- QDir projectDir = qmlTarget()->qmlProject()->projectDir();
- QStringList files;
-
- files.append(CURRENT_FILE);
- int currentIndex = -1;
- QStringList sortedFiles = qmlTarget()->qmlProject()->files();
- qStableSort(sortedFiles.begin(), sortedFiles.end(), caseInsensitiveLessThan);
-
- foreach (const QString &fn, sortedFiles) {
- QFileInfo fileInfo(fn);
- if (fileInfo.suffix() != QLatin1String("qml"))
- continue;
-
- QString fileName = projectDir.relativeFilePath(fn);
- if (fileName == m_scriptFile)
- currentIndex = files.size();
+ if (m_usingCurrentFile) {
+ return m_currentFileFilename;
+ }
- files.append(fileName);
+ if (!m_mainScriptFilename.isEmpty()) {
+ return m_mainScriptFilename;
}
- m_fileListModel->setStringList(files);
- if (currentIndex != -1)
- m_fileListCombo.data()->setCurrentIndex(currentIndex);
- else
- m_fileListCombo.data()->setCurrentIndex(0);
+ QString path = qmlTarget()->qmlProject()->mainFile();
+ if (QFileInfo(path).isAbsolute()) {
+ return path;
+ } else {
+ return qmlTarget()->qmlProject()->projectDir().absoluteFilePath(path);
+ }
}
-void QmlProjectRunConfiguration::setMainScript(const QString &scriptFile)
+void QmlProjectRunConfiguration::setScriptSource(MainScriptSource source,
+ const QString &settingsPath)
{
- m_scriptFile = scriptFile;
- // replace with locale-agnostic string
- if (m_scriptFile == CURRENT_FILE)
+ if (source == FileInEditor) {
m_scriptFile = M_CURRENT_FILE;
-
- if (m_scriptFile.isEmpty() || m_scriptFile == M_CURRENT_FILE) {
+ m_mainScriptFilename.clear();
m_usingCurrentFile = true;
- changeCurrentFile(Core::EditorManager::instance()->currentEditor());
- } else {
+ } else if (source == FileInProjectFile) {
+ m_scriptFile.clear();
+ m_mainScriptFilename.clear();
+ m_usingCurrentFile = false;
+ } else { // FileInSettings
+ m_scriptFile = settingsPath;
+ m_mainScriptFilename
+ = qmlTarget()->qmlProject()->projectDir().absoluteFilePath(m_scriptFile);
m_usingCurrentFile = false;
- m_mainScriptFilename = qmlTarget()->qmlProject()->projectDir().absoluteFilePath(scriptFile);
- updateEnabled();
}
-}
-
-void QmlProjectRunConfiguration::onQtVersionSelectionChanged()
-{
- QVariant data = m_qtVersionComboBox.data()->itemData(m_qtVersionComboBox.data()->currentIndex());
- QTC_ASSERT(data.isValid() && data.canConvert(QVariant::Int), return)
- setQtVersionId(data.toInt());
updateEnabled();
+ if (m_configurationWidget)
+ m_configurationWidget.data()->updateFileComboBox();
}
-void QmlProjectRunConfiguration::onViewerArgsChanged()
-{
- if (QLineEdit *lineEdit = qobject_cast<QLineEdit*>(sender()))
- m_qmlViewerArgs = lineEdit->text();
-}
-
-void QmlProjectRunConfiguration::useCppDebuggerToggled(bool toggled)
-{
- setUseCppDebugger(toggled);
-}
-
-void QmlProjectRunConfiguration::useQmlDebuggerToggled(bool toggled)
+Utils::Environment QmlProjectRunConfiguration::environment() const
{
- setUseQmlDebugger(toggled);
-}
-
-void QmlProjectRunConfiguration::qmlDebugServerPortChanged(uint port)
-{
- setQmlDebugServerPort(port);
+ Utils::Environment env = baseEnvironment();
+ env.modify(userEnvironmentChanges());
+ return env;
}
QVariantMap QmlProjectRunConfiguration::toMap() const
@@ -361,6 +264,8 @@ QVariantMap QmlProjectRunConfiguration::toMap() const
map.insert(QLatin1String(Constants::QML_VIEWER_QT_KEY), m_qtVersionId);
map.insert(QLatin1String(Constants::QML_VIEWER_ARGUMENTS_KEY), m_qmlViewerArgs);
map.insert(QLatin1String(Constants::QML_MAINSCRIPT_KEY), m_scriptFile);
+ map.insert(QLatin1String(Constants::USER_ENVIRONMENT_CHANGES_KEY),
+ Utils::EnvironmentItem::toStringList(m_userEnvironmentChanges));
return map;
}
@@ -369,9 +274,18 @@ bool QmlProjectRunConfiguration::fromMap(const QVariantMap &map)
setQtVersionId(map.value(QLatin1String(Constants::QML_VIEWER_QT_KEY), -1).toInt());
m_qmlViewerArgs = map.value(QLatin1String(Constants::QML_VIEWER_ARGUMENTS_KEY)).toString();
m_scriptFile = map.value(QLatin1String(Constants::QML_MAINSCRIPT_KEY), M_CURRENT_FILE).toString();
+ m_userEnvironmentChanges = Utils::EnvironmentItem::fromStringList(
+ map.value(QLatin1String(Constants::USER_ENVIRONMENT_CHANGES_KEY)).toStringList());
+
updateQtVersions();
- setMainScript(m_scriptFile);
+ if (m_scriptFile == M_CURRENT_FILE) {
+ setScriptSource(FileInEditor);
+ } else if (m_scriptFile.isEmpty()) {
+ setScriptSource(FileInProjectFile);
+ } else {
+ setScriptSource(FileInSettings, m_scriptFile);
+ }
return RunConfiguration::fromMap(map);
}
@@ -386,19 +300,21 @@ void QmlProjectRunConfiguration::updateEnabled()
bool qmlFileFound = false;
if (m_usingCurrentFile) {
Core::IEditor *editor = Core::EditorManager::instance()->currentEditor();
+ Core::MimeDatabase *db = ICore::instance()->mimeDatabase();
if (editor) {
m_currentFileFilename = editor->file()->fileName();
- if (Core::ICore::instance()->mimeDatabase()->findByFile(mainScript()).type() == QLatin1String("application/x-qml"))
+ if (db->findByFile(mainScript()).type() == QLatin1String("application/x-qml"))
qmlFileFound = true;
}
if (!editor
- || Core::ICore::instance()->mimeDatabase()->findByFile(mainScript()).type() == QLatin1String("application/x-qmlproject")) {
- // find a qml file with lowercase filename. This is slow but only done in initialization/other border cases.
+ || db->findByFile(mainScript()).type() == QLatin1String("application/x-qmlproject")) {
+ // find a qml file with lowercase filename. This is slow, but only done
+ // in initialization/other border cases.
foreach(const QString &filename, m_projectTarget->qmlProject()->files()) {
const QFileInfo fi(filename);
if (!filename.isEmpty() && fi.baseName()[0].isLower()
- && Core::ICore::instance()->mimeDatabase()->findByFile(fi).type() == QLatin1String("application/x-qml"))
+ && db->findByFile(fi).type() == QLatin1String("application/x-qml"))
{
m_currentFileFilename = filename;
qmlFileFound = true;
@@ -408,7 +324,7 @@ void QmlProjectRunConfiguration::updateEnabled()
}
}
} else { // use default one
- qmlFileFound = !m_mainScriptFilename.isEmpty();
+ qmlFileFound = !mainScript().isEmpty();
}
bool newValue = (QFileInfo(viewerPath()).exists()
@@ -422,7 +338,7 @@ void QmlProjectRunConfiguration::updateEnabled()
void QmlProjectRunConfiguration::updateQtVersions()
{
- Qt4ProjectManager::QtVersionManager *qtVersions = Qt4ProjectManager::QtVersionManager::instance();
+ QtVersionManager *qtVersions = QtVersionManager::instance();
//
// update m_qtVersionId
@@ -441,37 +357,6 @@ void QmlProjectRunConfiguration::updateQtVersions()
}
updateEnabled();
-
- if (!m_qtVersionComboBox)
- return;
-
- //
- // update combobox
- //
- m_qtVersionComboBox.data()->clear();
-
- foreach (Qt4ProjectManager::QtVersion *version, qtVersions->validVersions()) {
- if (isValidVersion(version)) {
- m_qtVersionComboBox.data()->addItem(version->displayName(), version->uniqueId());
- }
- }
-
- if (m_qtVersionId != -1) {
- int index = m_qtVersionComboBox.data()->findData(m_qtVersionId);
- QTC_ASSERT(index >= 0, return);
- m_qtVersionComboBox.data()->setCurrentIndex(index);
- } else {
- m_qtVersionComboBox.data()->addItem(tr("Invalid Qt version"), -1);
- m_qtVersionComboBox.data()->setCurrentIndex(0);
- }
-
-}
-
-void QmlProjectRunConfiguration::manageQtVersions()
-{
- Core::ICore *core = Core::ICore::instance();
- core->showOptionsDialog(Qt4ProjectManager::Constants::QT_SETTINGS_CATEGORY,
- Qt4ProjectManager::Constants::QTVERSION_SETTINGS_PAGE_ID);
}
bool QmlProjectRunConfiguration::isValidVersion(Qt4ProjectManager::QtVersion *version)
@@ -485,4 +370,27 @@ bool QmlProjectRunConfiguration::isValidVersion(Qt4ProjectManager::QtVersion *ve
return false;
}
+Utils::Environment QmlProjectRunConfiguration::baseEnvironment() const
+{
+ Utils::Environment env;
+ if (qtVersion())
+ env = qtVersion()->qmlToolsEnvironment();
+ return env;
+}
+
+void QmlProjectRunConfiguration::setUserEnvironmentChanges(const QList<Utils::EnvironmentItem> &diff)
+{
+ if (m_userEnvironmentChanges != diff) {
+ m_userEnvironmentChanges = diff;
+ if (m_configurationWidget)
+ m_configurationWidget.data()->userEnvironmentChangesChanged();
+ }
+}
+
+QList<Utils::EnvironmentItem> QmlProjectRunConfiguration::userEnvironmentChanges() const
+{
+ return m_userEnvironmentChanges;
+}
+
+
} // namespace QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h
index 78c51704c4..bd5b13b274 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h
+++ b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h
@@ -40,31 +40,34 @@
#include <QComboBox>
#include <QLabel>
-QT_FORWARD_DECLARE_CLASS(QStringListModel);
+QT_FORWARD_DECLARE_CLASS(QStringListModel)
namespace Core {
class IEditor;
}
+namespace Utils {
+ class Environment;
+ class EnvironmentItem;
+}
+
namespace Qt4ProjectManager {
-class QtVersion;
+ class QtVersion;
}
namespace QmlProjectManager {
namespace Internal {
-class QmlProjectTarget;
-class QmlProjectRunConfigurationFactory;
+ class QmlProjectTarget;
+ class QmlProjectRunConfigurationFactory;
+ class QmlProjectRunConfigurationWidget;
}
-const char * const CURRENT_FILE = QT_TRANSLATE_NOOP("QmlManager", "<Current File>");
-const char * const M_CURRENT_FILE = "CurrentFile";
-
-
class QMLPROJECTMANAGER_EXPORT QmlProjectRunConfiguration : public ProjectExplorer::RunConfiguration
{
Q_OBJECT
friend class Internal::QmlProjectRunConfigurationFactory;
+ friend class Internal::QmlProjectRunConfigurationWidget;
// used in qmldumptool.cpp
Q_PROPERTY(int qtVersionId READ qtVersionId)
@@ -75,42 +78,41 @@ public:
Internal::QmlProjectTarget *qmlTarget() const;
- bool isEnabled(ProjectExplorer::BuildConfiguration *bc) const;
-
QString viewerPath() const;
QString observerPath() const;
- QStringList viewerArguments() const;
+ QString viewerArguments() const;
QString workingDirectory() const;
int qtVersionId() const;
Qt4ProjectManager::QtVersion *qtVersion() const;
+ enum MainScriptSource {
+ FileInEditor,
+ FileInProjectFile,
+ FileInSettings
+ };
+ MainScriptSource mainScriptSource() const;
+ void setScriptSource(MainScriptSource source, const QString &settingsPath = QString());
+
+ QString mainScript() const;
+
+ Utils::Environment environment() const;
+
// RunConfiguration
+ bool isEnabled(ProjectExplorer::BuildConfiguration *bc) const;
virtual QWidget *createConfigurationWidget();
-
ProjectExplorer::OutputFormatter *createOutputFormatter() const;
-
QVariantMap toMap() const;
public slots:
void changeCurrentFile(Core::IEditor*);
private slots:
- QString mainScript() const;
- void setMainScript(const QString &scriptFile);
- void updateFileComboBox();
-
void updateEnabled();
-
- void onQtVersionSelectionChanged();
- void onViewerArgsChanged();
- void useCppDebuggerToggled(bool toggled);
- void useQmlDebuggerToggled(bool toggled);
- void qmlDebugServerPortChanged(uint port);
void updateQtVersions();
- void manageQtVersions();
protected:
- QmlProjectRunConfiguration(Internal::QmlProjectTarget *parent, QmlProjectRunConfiguration *source);
+ QmlProjectRunConfiguration(Internal::QmlProjectTarget *parent,
+ QmlProjectRunConfiguration *source);
virtual bool fromMap(const QVariantMap &map);
void setEnabled(bool value);
@@ -119,6 +121,10 @@ private:
static bool isValidVersion(Qt4ProjectManager::QtVersion *version);
void setQtVersionId(int id);
+ Utils::Environment baseEnvironment() const;
+ void setUserEnvironmentChanges(const QList<Utils::EnvironmentItem> &diff);
+ QList<Utils::EnvironmentItem> userEnvironmentChanges() const;
+
// absolute path to current file (if being used)
QString m_currentFileFilename;
// absolute path to selected main script (if being used)
@@ -128,16 +134,13 @@ private:
QString m_scriptFile;
QString m_qmlViewerArgs;
- QStringListModel *m_fileListModel;
- // weakpointer is used to make sure we don't try to manipulate
- // widget which was deleted already, as can be the case here.
- QWeakPointer<QComboBox> m_qtVersionComboBox;
- QWeakPointer<QComboBox> m_fileListCombo;
-
Internal::QmlProjectTarget *m_projectTarget;
+ QWeakPointer<Internal::QmlProjectRunConfigurationWidget> m_configurationWidget;
bool m_usingCurrentFile;
bool m_isEnabled;
+
+ QList<Utils::EnvironmentItem> m_userEnvironmentChanges;
};
} // namespace QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfigurationwidget.cpp b/src/plugins/qmlprojectmanager/qmlprojectrunconfigurationwidget.cpp
new file mode 100644
index 0000000000..cb1eb2ad10
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/qmlprojectrunconfigurationwidget.cpp
@@ -0,0 +1,317 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "qmlprojectrunconfigurationwidget.h"
+#include "qmlprojectrunconfiguration.h"
+#include "qmlprojecttarget.h"
+#include "qmlproject.h"
+
+#include <coreplugin/icore.h>
+#include <projectexplorer/environmenteditmodel.h>
+#include <projectexplorer/projectexplorer.h>
+#include <utils/debuggerlanguagechooser.h>
+#include <utils/detailswidget.h>
+#include <utils/qtcassert.h>
+#include <qt4projectmanager/qt4projectmanagerconstants.h>
+#include <qt4projectmanager/qtversionmanager.h>
+
+#include <QLineEdit>
+#include <QFormLayout>
+#include <QPushButton>
+#include <QStandardItemModel>
+
+using Core::ICore;
+using Utils::DebuggerLanguageChooser;
+using Qt4ProjectManager::QtVersionManager;
+
+namespace QmlProjectManager {
+namespace Internal {
+
+QmlProjectRunConfigurationWidget::QmlProjectRunConfigurationWidget(QmlProjectRunConfiguration *rc) :
+ m_runConfiguration(rc),
+ m_qtVersionComboBox(0),
+ m_fileListCombo(0),
+ m_fileListModel(new QStandardItemModel(this))
+{
+ QVBoxLayout *layout = new QVBoxLayout(this);
+
+ //
+ // Qt Version, Arguments
+ //
+
+ Utils::DetailsWidget *detailsWidget = new Utils::DetailsWidget();
+ detailsWidget->setState(Utils::DetailsWidget::NoSummary);
+
+ QWidget *formWidget = new QWidget(detailsWidget);
+ detailsWidget->setWidget(formWidget);
+ QFormLayout *form = new QFormLayout(formWidget);
+ form->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
+
+ m_fileListCombo = new QComboBox;
+ m_fileListCombo->setModel(m_fileListModel);
+
+ connect(m_fileListCombo, SIGNAL(activated(int)), this, SLOT(setMainScript(int)));
+ connect(ProjectExplorer::ProjectExplorerPlugin::instance(), SIGNAL(fileListChanged()),
+ SLOT(updateFileComboBox()));
+
+ m_qtVersionComboBox = new QComboBox;
+ m_qtVersionComboBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
+ connect(m_qtVersionComboBox, SIGNAL(activated(int)),
+ this, SLOT(onQtVersionSelectionChanged()));
+
+ QPushButton *pushButton = new QPushButton;
+ pushButton->setText(tr("Manage Qt versions"));
+ connect(pushButton, SIGNAL(clicked()), this, SLOT(manageQtVersions()));
+
+ QHBoxLayout *qtVersionLayout = new QHBoxLayout;
+ qtVersionLayout->addWidget(m_qtVersionComboBox);
+ qtVersionLayout->addWidget(pushButton);
+
+ QLineEdit *qmlViewerArgs = new QLineEdit;
+ qmlViewerArgs->setText(rc->m_qmlViewerArgs);
+ connect(qmlViewerArgs, SIGNAL(textChanged(QString)), this, SLOT(onViewerArgsChanged()));
+
+ form->addRow(tr("Qt version:"), qtVersionLayout);
+ form->addRow(tr("Arguments:"), qmlViewerArgs);
+ form->addRow(tr("Main QML file:"), m_fileListCombo);
+
+ layout->addWidget(detailsWidget);
+
+ updateFileComboBox();
+ updateQtVersionComboBox();
+
+ //
+ // Debugging
+ //
+
+ QWidget *debuggerLabelWidget = new QWidget;
+ QVBoxLayout *debuggerLabelLayout = new QVBoxLayout(debuggerLabelWidget);
+ debuggerLabelLayout->setMargin(0);
+ debuggerLabelLayout->setSpacing(0);
+ debuggerLabelWidget->setLayout(debuggerLabelLayout);
+ QLabel *debuggerLabel = new QLabel(tr("Debugger:"));
+ debuggerLabelLayout->addWidget(debuggerLabel);
+ debuggerLabelLayout->addStretch(10);
+
+ DebuggerLanguageChooser *debuggerLanguageChooser = new DebuggerLanguageChooser(formWidget);
+ form->addRow(debuggerLabelWidget, debuggerLanguageChooser);
+
+ debuggerLanguageChooser->setCppChecked(rc->useCppDebugger());
+ debuggerLanguageChooser->setQmlChecked(rc->useQmlDebugger());
+ debuggerLanguageChooser->setQmlDebugServerPort(rc->qmlDebugServerPort());
+
+ connect(debuggerLanguageChooser, SIGNAL(cppLanguageToggled(bool)),
+ this, SLOT(useCppDebuggerToggled(bool)));
+ connect(debuggerLanguageChooser, SIGNAL(qmlLanguageToggled(bool)),
+ this, SLOT(useQmlDebuggerToggled(bool)));
+ connect(debuggerLanguageChooser, SIGNAL(qmlDebugServerPortChanged(uint)),
+ this, SLOT(qmlDebugServerPortChanged(uint)));
+
+ QtVersionManager *qtVersions = QtVersionManager::instance();
+ connect(qtVersions, SIGNAL(qtVersionsChanged(QList<int>)),
+ this, SLOT(updateQtVersionComboBox()));
+
+ //
+ // Environment
+ //
+
+ QLabel *environmentLabel = new QLabel(this);
+ environmentLabel->setText(tr("Run Environment"));
+ QFont f = environmentLabel->font();
+ f.setBold(true);
+ f.setPointSizeF(f.pointSizeF() *1.2);
+ environmentLabel->setFont(f);
+
+ layout->addWidget(environmentLabel);
+
+ QWidget *baseEnvironmentWidget = new QWidget;
+ QHBoxLayout *baseEnvironmentLayout = new QHBoxLayout(baseEnvironmentWidget);
+ baseEnvironmentLayout->setMargin(0);
+ m_environmentWidget = new ProjectExplorer::EnvironmentWidget(this, baseEnvironmentWidget);
+ m_environmentWidget->setBaseEnvironment(rc->baseEnvironment());
+ m_environmentWidget->setBaseEnvironmentText(tr("System Environment"));
+ m_environmentWidget->setUserChanges(rc->userEnvironmentChanges());
+
+ connect(m_environmentWidget, SIGNAL(userChangesChanged()),
+ this, SLOT(userChangesChanged()));
+
+
+ layout->addWidget(m_environmentWidget);
+}
+
+static bool caseInsensitiveLessThan(const QString &s1, const QString &s2)
+{
+ return s1.toLower() < s2.toLower();
+}
+
+void QmlProjectRunConfigurationWidget::updateFileComboBox()
+{
+ QmlProject *project = m_runConfiguration->qmlTarget()->qmlProject();
+ QDir projectDir = project->projectDir();
+
+ m_fileListModel->clear();
+ m_fileListModel->appendRow(new QStandardItem(CURRENT_FILE));
+ QModelIndex currentIndex;
+ QModelIndex fileInQmlProjectIndex;
+
+ const QString mainScriptInFilePath = projectDir.absoluteFilePath(project->mainFile());
+
+ QStringList sortedFiles = project->files();
+ if (!sortedFiles.contains(mainScriptInFilePath))
+ sortedFiles += mainScriptInFilePath;
+
+ // make paths relative to project directory
+ QStringList relativeFiles;
+ foreach (const QString &fn, sortedFiles) {
+ relativeFiles += projectDir.relativeFilePath(fn);
+ }
+ sortedFiles = relativeFiles;
+
+ qStableSort(sortedFiles.begin(), sortedFiles.end(), caseInsensitiveLessThan);
+
+ QString mainScriptPath;
+ if (m_runConfiguration->mainScriptSource() != QmlProjectRunConfiguration::FileInEditor)
+ mainScriptPath = projectDir.relativeFilePath(m_runConfiguration->mainScript());
+
+ foreach (const QString &fn, sortedFiles) {
+ QFileInfo fileInfo(fn);
+ if (fileInfo.suffix() != QLatin1String("qml"))
+ continue;
+
+ QStandardItem *item = new QStandardItem(fn);
+ m_fileListModel->appendRow(item);
+
+ if (mainScriptPath == fn)
+ currentIndex = item->index();
+
+ if (mainScriptInFilePath == fn)
+ fileInQmlProjectIndex = item->index();
+ }
+
+ if (currentIndex.isValid()) {
+ m_fileListCombo->setCurrentIndex(currentIndex.row());
+ } else {
+ m_fileListCombo->setCurrentIndex(0);
+ }
+
+ if (fileInQmlProjectIndex.isValid()) {
+ QFont font;
+ font.setBold(true);
+ m_fileListModel->setData(fileInQmlProjectIndex, font, Qt::FontRole);
+ }
+}
+
+void QmlProjectRunConfigurationWidget::setMainScript(int index)
+{
+ QmlProject *project = m_runConfiguration->qmlTarget()->qmlProject();
+ QDir projectDir = project->projectDir();
+ if (index == 0) {
+ m_runConfiguration->setScriptSource(QmlProjectRunConfiguration::FileInEditor);
+ } else {
+ const QString path = m_fileListModel->data(m_fileListModel->index(index, 0)).toString();
+ if (projectDir.relativeFilePath(project->mainFile()) == path) {
+ m_runConfiguration->setScriptSource(QmlProjectRunConfiguration::FileInProjectFile);
+ } else {
+ m_runConfiguration->setScriptSource(QmlProjectRunConfiguration::FileInSettings, path);
+ }
+ }
+}
+
+void QmlProjectRunConfigurationWidget::onQtVersionSelectionChanged()
+{
+ QVariant data = m_qtVersionComboBox->itemData(m_qtVersionComboBox->currentIndex());
+ QTC_ASSERT(data.isValid() && data.canConvert(QVariant::Int), return)
+ m_runConfiguration->setQtVersionId(data.toInt());
+ m_runConfiguration->updateEnabled();
+}
+
+void QmlProjectRunConfigurationWidget::onViewerArgsChanged()
+{
+ if (QLineEdit *lineEdit = qobject_cast<QLineEdit*>(sender()))
+ m_runConfiguration->m_qmlViewerArgs = lineEdit->text();
+}
+
+void QmlProjectRunConfigurationWidget::useCppDebuggerToggled(bool toggled)
+{
+ m_runConfiguration->setUseCppDebugger(toggled);
+ m_runConfiguration->updateEnabled();
+}
+
+void QmlProjectRunConfigurationWidget::useQmlDebuggerToggled(bool toggled)
+{
+ m_runConfiguration->setUseQmlDebugger(toggled);
+ m_runConfiguration->updateEnabled();
+}
+
+void QmlProjectRunConfigurationWidget::qmlDebugServerPortChanged(uint port)
+{
+ m_runConfiguration->setQmlDebugServerPort(port);
+}
+
+void QmlProjectRunConfigurationWidget::manageQtVersions()
+{
+ ICore *core = ICore::instance();
+ core->showOptionsDialog(Qt4ProjectManager::Constants::QT_SETTINGS_CATEGORY,
+ Qt4ProjectManager::Constants::QTVERSION_SETTINGS_PAGE_ID);
+}
+
+void QmlProjectRunConfigurationWidget::updateQtVersionComboBox()
+{
+ m_qtVersionComboBox->clear();
+
+ QtVersionManager *qtVersions = QtVersionManager::instance();
+ foreach (Qt4ProjectManager::QtVersion *version, qtVersions->validVersions()) {
+ if (m_runConfiguration->isValidVersion(version)) {
+ m_qtVersionComboBox->addItem(version->displayName(), version->uniqueId());
+ }
+ }
+
+ if (m_runConfiguration->m_qtVersionId != -1) {
+ int index = m_qtVersionComboBox->findData(m_runConfiguration->m_qtVersionId);
+ QTC_ASSERT(index >= 0, return);
+ m_qtVersionComboBox->setCurrentIndex(index);
+ } else {
+ m_qtVersionComboBox->addItem(tr("Invalid Qt version"), -1);
+ m_qtVersionComboBox->setCurrentIndex(0);
+ }
+}
+
+void QmlProjectRunConfigurationWidget::userChangesChanged()
+{
+ m_runConfiguration->setUserEnvironmentChanges(m_environmentWidget->userChanges());
+}
+
+void QmlProjectRunConfigurationWidget::userEnvironmentChangesChanged()
+{
+ m_environmentWidget->setUserChanges(m_runConfiguration->userEnvironmentChanges());
+}
+
+
+} // namespace Internal
+} // namespace QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfigurationwidget.h b/src/plugins/qmlprojectmanager/qmlprojectrunconfigurationwidget.h
new file mode 100644
index 0000000000..d9c413a9b2
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/qmlprojectrunconfigurationwidget.h
@@ -0,0 +1,93 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** No Commercial Usage
+**
+** This file 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.
+**
+**************************************************************************/
+
+#ifndef QMLPROJECTRUNCONFIGURATIONWIDGET_H
+#define QMLPROJECTRUNCONFIGURATIONWIDGET_H
+
+#include <QWidget>
+
+QT_FORWARD_DECLARE_CLASS(QComboBox)
+QT_FORWARD_DECLARE_CLASS(QStandardItemModel)
+
+namespace ProjectExplorer {
+
+class EnvironmentWidget;
+
+} // namespace Qt4ProjectManager
+
+namespace QmlProjectManager {
+
+class QmlProjectRunConfiguration;
+
+namespace Internal {
+
+const char * const CURRENT_FILE = QT_TRANSLATE_NOOP("QmlManager", "<Current File>");
+
+class QmlProjectRunConfigurationWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ explicit QmlProjectRunConfigurationWidget(QmlProjectRunConfiguration *rc);
+
+public slots:
+ void updateQtVersionComboBox();
+ void userEnvironmentChangesChanged();
+ void updateFileComboBox();
+
+private slots:
+
+ void setMainScript(int index);
+ void onQtVersionSelectionChanged();
+ void onViewerArgsChanged();
+ void useCppDebuggerToggled(bool toggled);
+ void useQmlDebuggerToggled(bool toggled);
+ void qmlDebugServerPortChanged(uint port);
+
+ void userChangesChanged();
+
+ void manageQtVersions();
+
+private:
+ QmlProjectRunConfiguration *m_runConfiguration;
+
+ QComboBox *m_qtVersionComboBox;
+ QComboBox *m_fileListCombo;
+ QStandardItemModel *m_fileListModel;
+
+ ProjectExplorer::EnvironmentWidget *m_environmentWidget;
+};
+
+} // namespace Internal
+} // namespace QmlProjectManager
+
+#endif // QMLPROJECTRUNCONFIGURATIONWIDGET_H
diff --git a/src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp b/src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp
index cc2b36d3e8..895836f793 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp
+++ b/src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp
@@ -38,15 +38,14 @@
#include <coreplugin/modemanager.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/applicationlauncher.h>
-#include <projectexplorer/toolchain.h>
#include <qt4projectmanager/qtversionmanager.h>
#include <utils/environment.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <debugger/debuggerrunner.h>
#include <debugger/debuggerplugin.h>
#include <debugger/debuggerconstants.h>
-#include <debugger/debuggeruiswitcher.h>
#include <debugger/debuggerengine.h>
#include <qmljsinspector/qmljsinspectorconstants.h>
#include <qt4projectmanager/qtversionmanager.h>
@@ -68,8 +67,7 @@ namespace Internal {
QmlRunControl::QmlRunControl(QmlProjectRunConfiguration *runConfiguration, QString mode)
: RunControl(runConfiguration, mode)
{
- if (Qt4ProjectManager::QtVersion *qtVersion = runConfiguration->qtVersion())
- m_applicationLauncher.setEnvironment(qtVersion->qmlToolsEnvironment().toStringList());
+ m_applicationLauncher.setEnvironment(runConfiguration->environment());
m_applicationLauncher.setWorkingDirectory(runConfiguration->workingDirectory());
if (mode == ProjectExplorer::Constants::RUNMODE) {
@@ -101,7 +99,7 @@ void QmlRunControl::start()
emit started();
emit appendMessage(this, tr("Starting %1 %2").arg(QDir::toNativeSeparators(m_executable),
- m_commandLineArguments.join(QLatin1String(" "))), false);
+ m_commandLineArguments), false);
}
RunControl::StopResult QmlRunControl::stop()
@@ -149,23 +147,22 @@ QmlRunControlFactory::~QmlRunControlFactory()
bool QmlRunControlFactory::canRun(RunConfiguration *runConfiguration,
const QString &mode) const
{
- QmlProjectRunConfiguration *config = qobject_cast<QmlProjectRunConfiguration*>(runConfiguration);
- if (mode == ProjectExplorer::Constants::RUNMODE) {
+ QmlProjectRunConfiguration *config =
+ qobject_cast<QmlProjectRunConfiguration*>(runConfiguration);
+ if (mode == ProjectExplorer::Constants::RUNMODE)
return config != 0 && !config->viewerPath().isEmpty();
- } else {
- bool qmlDebugSupportInstalled = Debugger::DebuggerUISwitcher::instance()->supportedLanguages()
- & Debugger::QmlLanguage;
-
- if (config && qmlDebugSupportInstalled) {
- if (!config->observerPath().isEmpty()) {
- return true;
- }
-
- if (config->qtVersion() && Qt4ProjectManager::QmlObserverTool::canBuild(config->qtVersion())) {
- return true;
- } else {
- return false;
- }
+
+ bool qmlDebugSupportInstalled =
+ Debugger::DebuggerPlugin::isActiveDebugLanguage(Debugger::QmlLanguage);
+
+ if (config && qmlDebugSupportInstalled) {
+ if (!config->observerPath().isEmpty())
+ return true;
+
+ if (config->qtVersion() && Qt4ProjectManager::QmlObserverTool::canBuild(config->qtVersion())) {
+ return true;
+ } else {
+ return false;
}
}
@@ -181,7 +178,7 @@ RunControl *QmlRunControlFactory::create(RunConfiguration *runConfiguration,
RunControl *runControl = 0;
if (mode == ProjectExplorer::Constants::RUNMODE) {
runControl = new QmlRunControl(config, mode);
- } else if (mode == ProjectExplorer::Constants::DEBUGMODE) {
+ } else if (mode == Debugger::Constants::DEBUGMODE) {
runControl = createDebugRunControl(config);
}
return runControl;
@@ -206,10 +203,10 @@ ProjectExplorer::RunControl *QmlRunControlFactory::createDebugRunControl(QmlProj
params.qmlServerAddress = "127.0.0.1";
params.qmlServerPort = runConfig->qmlDebugServerPort();
params.processArgs = runConfig->viewerArguments();
- params.processArgs.append(QLatin1String("-qmljsdebugger=port:") + QString::number(runConfig->qmlDebugServerPort()));
+ Utils::QtcProcess::addArg(&params.processArgs,
+ QLatin1String("-qmljsdebugger=port:") + QString::number(runConfig->qmlDebugServerPort()));
params.workingDirectory = runConfig->workingDirectory();
- if (Qt4ProjectManager::QtVersion *qtVersion = runConfig->qtVersion())
- params.environment = qtVersion->qmlToolsEnvironment().toStringList();
+ params.environment = runConfig->environment();
params.displayName = runConfig->displayName();
if (params.executable.isEmpty()) {
@@ -217,8 +214,7 @@ ProjectExplorer::RunControl *QmlRunControlFactory::createDebugRunControl(QmlProj
return 0;
}
- Debugger::DebuggerRunControl *debuggerRunControl = Debugger::DebuggerPlugin::createDebugger(params, runConfig);
- return debuggerRunControl;
+ return Debugger::DebuggerPlugin::createDebugger(params, runConfig);
}
void QmlRunControlFactory::showQmlObserverToolWarning() {
diff --git a/src/plugins/qmlprojectmanager/qmlprojectruncontrol.h b/src/plugins/qmlprojectmanager/qmlprojectruncontrol.h
index a3d3cca6bb..a0fe39f1ba 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectruncontrol.h
+++ b/src/plugins/qmlprojectmanager/qmlprojectruncontrol.h
@@ -65,7 +65,7 @@ private:
ProjectExplorer::ApplicationLauncher m_applicationLauncher;
QString m_executable;
- QStringList m_commandLineArguments;
+ QString m_commandLineArguments;
};
class QmlRunControlFactory : public ProjectExplorer::IRunControlFactory {
diff --git a/src/plugins/qmlprojectmanager/qmlprojecttarget.cpp b/src/plugins/qmlprojectmanager/qmlprojecttarget.cpp
index 74e5c5b05c..cc7f03972c 100644
--- a/src/plugins/qmlprojectmanager/qmlprojecttarget.cpp
+++ b/src/plugins/qmlprojectmanager/qmlprojecttarget.cpp
@@ -57,6 +57,11 @@ QmlProjectTarget::~QmlProjectTarget()
{
}
+ProjectExplorer::BuildConfigWidget *QmlProjectTarget::createConfigWidget()
+{
+ return 0;
+}
+
QmlProject *QmlProjectTarget::qmlProject() const
{
return static_cast<QmlProject *>(project());
@@ -98,6 +103,11 @@ QmlProjectTargetFactory::~QmlProjectTargetFactory()
{
}
+bool QmlProjectTargetFactory::supportsTargetId(const QString &id) const
+{
+ return id == QLatin1String(Constants::QML_VIEWER_TARGET_ID);
+}
+
QStringList QmlProjectTargetFactory::availableCreationIds(ProjectExplorer::Project *parent) const
{
if (!qobject_cast<QmlProject *>(parent))
@@ -126,13 +136,13 @@ QmlProjectTarget *QmlProjectTargetFactory::create(ProjectExplorer::Project *pare
if (!canCreate(parent, id))
return 0;
QmlProject *qmlproject(static_cast<QmlProject *>(parent));
- QmlProjectTarget *t(new QmlProjectTarget(qmlproject));
+ QmlProjectTarget *target = new QmlProjectTarget(qmlproject);
// Add RunConfiguration (QML does not have BuildConfigurations)
- QmlProjectRunConfiguration *runConf(new QmlProjectRunConfiguration(t));
- t->addRunConfiguration(runConf);
+ QmlProjectRunConfiguration *runConf = new QmlProjectRunConfiguration(target);
+ target->addRunConfiguration(runConf);
- return t;
+ return target;
}
bool QmlProjectTargetFactory::canRestore(ProjectExplorer::Project *parent, const QVariantMap &map) const
diff --git a/src/plugins/qmlprojectmanager/qmlprojecttarget.h b/src/plugins/qmlprojectmanager/qmlprojecttarget.h
index c01d86b677..fcb9000ea4 100644
--- a/src/plugins/qmlprojectmanager/qmlprojecttarget.h
+++ b/src/plugins/qmlprojectmanager/qmlprojecttarget.h
@@ -56,6 +56,8 @@ public:
explicit QmlProjectTarget(QmlProject *parent);
~QmlProjectTarget();
+ ProjectExplorer::BuildConfigWidget *createConfigWidget();
+
QmlProject *qmlProject() const;
ProjectExplorer::IBuildConfigurationFactory *buildConfigurationFactory() const;
@@ -73,6 +75,7 @@ public:
explicit QmlProjectTargetFactory(QObject *parent = 0);
~QmlProjectTargetFactory();
+ bool supportsTargetId(const QString &id) const;
QStringList availableCreationIds(ProjectExplorer::Project *parent) const;
QString displayNameForId(const QString &id) const;
diff --git a/src/plugins/qt4projectmanager/Qt4ProjectManager.pluginspec b/src/plugins/qt4projectmanager/Qt4ProjectManager.pluginspec
deleted file mode 100644
index 0a6749c901..0000000000
--- a/src/plugins/qt4projectmanager/Qt4ProjectManager.pluginspec
+++ /dev/null
@@ -1,24 +0,0 @@
-<plugin name="Qt4ProjectManager" version="2.0.95" compatVersion="2.0.95">
- <vendor>Nokia Corporation</vendor>
- <copyright>(C) 2010 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>
- <category>Build Systems</category>
- <description>Provides project type for Qt 4 pro files and tools.</description>
- <url>http://qt.nokia.com</url>
- <dependencyList>
- <dependency name="TextEditor" version="2.0.95"/>
- <dependency name="ProjectExplorer" version="2.0.95"/>
- <dependency name="CppTools" version="2.0.95"/>
- <dependency name="CppEditor" version="2.0.95"/>
- <dependency name="Designer" version="2.0.95"/>
- <dependency name="Debugger" version="2.0.95"/>
- </dependencyList>
-</plugin>
diff --git a/src/plugins/qt4projectmanager/Qt4ProjectManager.pluginspec.in b/src/plugins/qt4projectmanager/Qt4ProjectManager.pluginspec.in
new file mode 100644
index 0000000000..3f03fb2b83
--- /dev/null
+++ b/src/plugins/qt4projectmanager/Qt4ProjectManager.pluginspec.in
@@ -0,0 +1,23 @@
+<plugin name=\"Qt4ProjectManager\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2010 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>
+ <category>Build Systems</category>
+ <description>Provides project type for Qt 4 pro files and tools.</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name=\"TextEditor\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"ProjectExplorer\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"CppTools\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"Designer\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"Debugger\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/qt4projectmanager/addlibrarywizard.cpp b/src/plugins/qt4projectmanager/addlibrarywizard.cpp
index 74476153f0..9f60e2aafd 100644
--- a/src/plugins/qt4projectmanager/addlibrarywizard.cpp
+++ b/src/plugins/qt4projectmanager/addlibrarywizard.cpp
@@ -58,29 +58,18 @@ AddLibraryWizard::AddLibraryWizard(const QString &fileName, QWidget *parent) :
Utils::Wizard(parent), m_proFile(fileName)
{
setWindowTitle(tr("Add Library"));
- setAutomaticProgressCreationEnabled(false);
m_libraryTypePage = new LibraryTypePage(this);
m_detailsPage = new DetailsPage(this);
m_summaryPage = new SummaryPage(this);
- setPage(LibraryTypePageId, m_libraryTypePage);
- setPage(DetailsPageId, m_detailsPage);
- setPage(SummaryPageId, m_summaryPage);
+ const int libraryTypePageId = addPage(m_libraryTypePage);
+ const int detailsPageId = addPage(m_detailsPage);
+ const int summaryPageId = addPage(m_summaryPage);
Utils::WizardProgress *progress = wizardProgress();
- Utils::WizardProgressItem *kindItem = progress->addItem(tr("Type"));
-
- Utils::WizardProgressItem *detailsItem = progress->addItem(tr("Details"));
- Utils::WizardProgressItem *summaryItem = progress->addItem(tr("Summary"));
-
- kindItem->addPage(LibraryTypePageId);
- detailsItem->addPage(DetailsPageId);
- summaryItem->addPage(SummaryPageId);
-
- kindItem->setNextItems(QList<Utils::WizardProgressItem *>() << detailsItem);
- detailsItem->setNextItems(QList<Utils::WizardProgressItem *>() << summaryItem);
-
- setStartId(LibraryTypePageId);
+ progress->item(libraryTypePageId)->setTitle(tr("Type"));
+ progress->item(detailsPageId)->setTitle(tr("Details"));
+ progress->item(summaryPageId)->setTitle(tr("Summary"));
}
AddLibraryWizard::~AddLibraryWizard()
@@ -112,18 +101,17 @@ LibraryTypePage::LibraryTypePage(AddLibraryWizard *parent)
QVBoxLayout *layout = new QVBoxLayout(this);
- m_systemRadio = new QRadioButton(tr("System library"), this);
- m_systemRadio->setChecked(true);
- layout->addWidget(m_systemRadio);
+ m_internalRadio = new QRadioButton(tr("Internal library"), this);
+ layout->addWidget(m_internalRadio);
- QLabel *systemLabel = new QLabel(tr("Links to a system library."
- "\nNeither the path to the "
- "library nor the path to its "
- "includes is added to the .pro file."));
+ QLabel *internalLabel = new QLabel(tr("Links to a library "
+ "that is located in your build "
+ "tree.\nAdds the library and "
+ "include paths to the .pro file."));
- systemLabel->setWordWrap(true);
- systemLabel->setAttribute(Qt::WA_MacSmallSize, true);
- layout->addWidget(systemLabel);
+ internalLabel->setWordWrap(true);
+ internalLabel->setAttribute(Qt::WA_MacSmallSize, true);
+ layout->addWidget(internalLabel);
m_externalRadio = new QRadioButton(tr("External library"), this);
layout->addWidget(m_externalRadio);
@@ -137,31 +125,45 @@ LibraryTypePage::LibraryTypePage(AddLibraryWizard *parent)
externalLabel->setAttribute(Qt::WA_MacSmallSize, true);
layout->addWidget(externalLabel);
- m_internalRadio = new QRadioButton(tr("Internal library"), this);
- layout->addWidget(m_internalRadio);
+ m_systemRadio = new QRadioButton(tr("System library"), this);
+ layout->addWidget(m_systemRadio);
- QLabel *internalLabel = new QLabel(tr("Links to a library "
- "that is located in your build "
- "tree.\nAdds the library and "
- "include paths to the .pro file."));
+ QLabel *systemLabel = new QLabel(tr("Links to a system library."
+ "\nNeither the path to the "
+ "library nor the path to its "
+ "includes is added to the .pro file."));
- internalLabel->setWordWrap(true);
- internalLabel->setAttribute(Qt::WA_MacSmallSize, true);
- layout->addWidget(internalLabel);
+ systemLabel->setWordWrap(true);
+ systemLabel->setAttribute(Qt::WA_MacSmallSize, true);
+ layout->addWidget(systemLabel);
+
+ m_packageRadio = new QRadioButton(tr("System package"), this);
+ layout->addWidget(m_packageRadio);
+
+ QLabel *packageLabel = new QLabel(tr("Links to a system library using pkg-config."));
+
+ packageLabel->setWordWrap(true);
+ packageLabel->setAttribute(Qt::WA_MacSmallSize, true);
+ layout->addWidget(packageLabel);
+
+#ifdef Q_OS_WIN
+ m_packageRadio->setVisible(false);
+ packageLabel->setVisible(false);
+#endif
+
+ // select the default
+ m_internalRadio->setChecked(true);
}
AddLibraryWizard::LibraryKind LibraryTypePage::libraryKind() const
{
if (m_internalRadio->isChecked())
return AddLibraryWizard::InternalLibrary;
+ if (m_externalRadio->isChecked())
+ return AddLibraryWizard::ExternalLibrary;
if (m_systemRadio->isChecked())
return AddLibraryWizard::SystemLibrary;
- return AddLibraryWizard::ExternalLibrary;
-}
-
-int LibraryTypePage::nextId() const
-{
- return AddLibraryWizard::DetailsPageId;
+ return AddLibraryWizard::PackageLibrary;
}
/////////////
@@ -180,11 +182,6 @@ bool DetailsPage::isComplete() const
return false;
}
-int DetailsPage::nextId() const
-{
- return AddLibraryWizard::SummaryPageId;
-}
-
QString DetailsPage::snippet() const
{
if (m_libraryDetailsController)
@@ -201,10 +198,10 @@ void DetailsPage::initializePage()
QString title;
QString subTitle;
switch (m_libraryWizard->libraryKind()) {
- case AddLibraryWizard::SystemLibrary:
- title = tr("System Library");
- subTitle = tr("Specify the library to link to");
- m_libraryDetailsController = new SystemLibraryDetailsController(
+ case AddLibraryWizard::InternalLibrary:
+ title = tr("Internal Library");
+ subTitle = tr("Choose the project file of the library to link to");
+ m_libraryDetailsController = new InternalLibraryDetailsController(
m_libraryDetailsWidget, m_libraryWizard->proFile(), this);
break;
case AddLibraryWizard::ExternalLibrary:
@@ -213,10 +210,16 @@ void DetailsPage::initializePage()
m_libraryDetailsController = new ExternalLibraryDetailsController(
m_libraryDetailsWidget, m_libraryWizard->proFile(), this);
break;
- case AddLibraryWizard::InternalLibrary:
- title = tr("Internal Library");
- subTitle = tr("Choose the project file of the library to link to");
- m_libraryDetailsController = new InternalLibraryDetailsController(
+ case AddLibraryWizard::SystemLibrary:
+ title = tr("System Library");
+ subTitle = tr("Specify the library to link to");
+ m_libraryDetailsController = new SystemLibraryDetailsController(
+ m_libraryDetailsWidget, m_libraryWizard->proFile(), this);
+ break;
+ case AddLibraryWizard::PackageLibrary:
+ title = tr("System Package");
+ subTitle = tr("Specify the package to link to");
+ m_libraryDetailsController = new PackageLibraryDetailsController(
m_libraryDetailsWidget, m_libraryWizard->proFile(), this);
break;
default:
@@ -261,6 +264,7 @@ void SummaryPage::initializePage()
str << "<code>";
QString text = m_snippet;
text.replace(QLatin1Char('\n'), QLatin1String("<br>"));
+ text.replace(QLatin1Char(' '), QLatin1String("&nbsp;"));
str << text;
str << "</code>";
}
diff --git a/src/plugins/qt4projectmanager/addlibrarywizard.h b/src/plugins/qt4projectmanager/addlibrarywizard.h
index acddb49c77..d9c8db5ef6 100644
--- a/src/plugins/qt4projectmanager/addlibrarywizard.h
+++ b/src/plugins/qt4projectmanager/addlibrarywizard.h
@@ -27,16 +27,11 @@ class AddLibraryWizard : public Utils::Wizard
{
Q_OBJECT
public:
- enum PageId {
- LibraryTypePageId,
- DetailsPageId,
- SummaryPageId
- };
-
enum LibraryKind {
- SystemLibrary,
+ InternalLibrary,
ExternalLibrary,
- InternalLibrary
+ SystemLibrary,
+ PackageLibrary
};
enum LinkageType {
@@ -84,12 +79,12 @@ class LibraryTypePage : public QWizardPage
public:
LibraryTypePage(AddLibraryWizard *parent);
AddLibraryWizard::LibraryKind libraryKind() const;
- virtual int nextId() const;
private:
- QRadioButton *m_systemRadio;
- QRadioButton *m_externalRadio;
QRadioButton *m_internalRadio;
+ QRadioButton *m_externalRadio;
+ QRadioButton *m_systemRadio;
+ QRadioButton *m_packageRadio;
};
class DetailsPage : public QWizardPage
@@ -98,7 +93,6 @@ class DetailsPage : public QWizardPage
public:
DetailsPage(AddLibraryWizard *parent);
virtual void initializePage();
- virtual int nextId() const;
virtual bool isComplete() const;
QString snippet() const;
diff --git a/src/plugins/qt4projectmanager/externaleditors.cpp b/src/plugins/qt4projectmanager/externaleditors.cpp
index f4c5e19547..08f118eded 100644
--- a/src/plugins/qt4projectmanager/externaleditors.cpp
+++ b/src/plugins/qt4projectmanager/externaleditors.cpp
@@ -83,15 +83,15 @@ static inline QString msgAppNotFound(const QString &id)
static const char * const linguistBinaryC = "Linguist";
static const char * const designerBinaryC = "Designer";
-// Mac: Change the call 'Foo.app/Contents/MacOS/Foo <file>' to
-// 'open Foo.app <file>'. Do this ONLY if you do not want to have
-// command line arguments
+// Mac: Change the call 'Foo.app/Contents/MacOS/Foo <filelist>' to
+// 'open -a Foo.app <filelist>'. doesn't support generic command line arguments
static void createMacOpenCommand(QString *binary, QStringList *arguments)
{
const int appFolderIndex = binary->lastIndexOf(QLatin1String("/Contents/MacOS/"));
if (appFolderIndex != -1) {
binary->truncate(appFolderIndex);
arguments->push_front(*binary);
+ arguments->push_front(QLatin1String("-a"));
*binary = QLatin1String("open");
}
}
diff --git a/src/plugins/qt4projectmanager/gettingstartedwelcomepagewidget.cpp b/src/plugins/qt4projectmanager/gettingstartedwelcomepagewidget.cpp
index 4c494198a5..0fc30d8cf4 100644
--- a/src/plugins/qt4projectmanager/gettingstartedwelcomepagewidget.cpp
+++ b/src/plugins/qt4projectmanager/gettingstartedwelcomepagewidget.cpp
@@ -37,8 +37,9 @@
#include <coreplugin/icore.h>
#include <coreplugin/helpmanager.h>
#include <coreplugin/coreconstants.h>
-#include <coreplugin/mainwindow.h>
+#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/rssfetcher.h>
+#include <coreplugin/dialogs/iwizard.h>
#include <projectexplorer/projectexplorer.h>
#include <utils/pathchooser.h>
@@ -63,8 +64,6 @@
#include <QtGui/QMenu>
#include <QtGui/QDesktopServices>
-using namespace Core::Internal;
-
namespace Qt4ProjectManager {
namespace Internal {
@@ -136,8 +135,8 @@ GettingStartedWelcomePageWidget::GettingStartedWelcomePageWidget(QWidget *parent
ui->openProjectButton->setIcon(
QIcon::fromTheme(QLatin1String("document-open"), ui->openProjectButton->icon()));
- m_rssFetcher = new RssFetcher;
- connect (m_rssFetcher, SIGNAL(rssItemReady(const RssItem&)), SLOT(addToFeatures(const RssItem&)));
+ m_rssFetcher = new Core::RssFetcher;
+ connect (m_rssFetcher, SIGNAL(rssItemReady(Core::RssItem)), SLOT(addToFeatures(Core::RssItem)));
connect (m_rssFetcher, SIGNAL(finished(bool)), SLOT(showFeature()), Qt::QueuedConnection);
connect(this, SIGNAL(startRssFetching(QUrl)), m_rssFetcher, SLOT(fetch(QUrl)), Qt::QueuedConnection);
m_rssFetcher->start(QThread::LowestPriority);
@@ -439,8 +438,8 @@ void GettingStartedWelcomePageWidget::slotOpenExample()
if(!QFile::exists(tryFile))
tryFile = proFileInfo.path() + '/' + proFileInfo.baseName() + ".cpp";
}
- Core::ICore::instance()->openFiles(files, Core::ICore::SwitchMode);
- if (!helpFile.isEmpty())
+ Core::ICore::instance()->openFiles(files, static_cast<Core::ICore::OpenFilesFlags>(Core::ICore::SwitchMode | Core::ICore::StopOnLoadFail));
+ if (!tryFile.isEmpty() && Core::EditorManager::instance()->hasEditor(tryFile) && !helpFile.isEmpty())
slotOpenContextHelpPage(helpFile);
}
@@ -526,7 +525,7 @@ QStringList GettingStartedWelcomePageWidget::tipsOfTheDay()
return tips;
}
-void GettingStartedWelcomePageWidget::addToFeatures(const RssItem &feature)
+void GettingStartedWelcomePageWidget::addToFeatures(const Core::RssItem &feature)
{
m_featuredItems.append(feature);
if (m_featuredItems.count() > 1) {
@@ -545,7 +544,7 @@ void GettingStartedWelcomePageWidget::showFeature(int feature)
m_currentFeature = rand()%m_featuredItems.count();
}
- RssItem item = m_featuredItems.at(m_currentFeature);
+ const Core::RssItem &item = m_featuredItems.at(m_currentFeature);
ui->featuredTextLabel->setTextFormat(Qt::RichText);
QString text = QString::fromLatin1("<b style='color: rgb(85, 85, 85);'>%1</b><br><b>%2</b><br/><br/>%3").arg(item.category).arg(item.title).arg(item.description);
ui->featuredTextLabel->setText(text);
diff --git a/src/plugins/qt4projectmanager/gettingstartedwelcomepagewidget.h b/src/plugins/qt4projectmanager/gettingstartedwelcomepagewidget.h
index 73e2479446..ccf2a154bd 100644
--- a/src/plugins/qt4projectmanager/gettingstartedwelcomepagewidget.h
+++ b/src/plugins/qt4projectmanager/gettingstartedwelcomepagewidget.h
@@ -46,14 +46,10 @@ class QMenu;
QT_END_NAMESPACE
namespace Core {
- namespace Internal {
- class RssFetcher;
- class RssItem;
- }
+class RssFetcher;
+class RssItem;
}
-using namespace Core::Internal;
-
namespace Qt4ProjectManager {
namespace Internal {
@@ -102,7 +98,7 @@ private slots:
void slotNextFeature();
void slotPrevFeature();
void slotCreateNewProject();
- void addToFeatures(const RssItem&);
+ void addToFeatures(const Core::RssItem&);
void showFeature(int feature = -1);
signals:
@@ -115,8 +111,8 @@ private:
Ui::GettingStartedWelcomePageWidget *ui;
int m_currentTip;
int m_currentFeature;
- QList<Core::Internal::RssItem> m_featuredItems;
- Core::Internal::RssFetcher *m_rssFetcher;
+ QList<Core::RssItem> m_featuredItems;
+ Core::RssFetcher *m_rssFetcher;
};
} // namespace Internal
diff --git a/src/plugins/qt4projectmanager/librarydetailscontroller.cpp b/src/plugins/qt4projectmanager/librarydetailscontroller.cpp
index 3cf3e5dbec..8767cf6961 100644
--- a/src/plugins/qt4projectmanager/librarydetailscontroller.cpp
+++ b/src/plugins/qt4projectmanager/librarydetailscontroller.cpp
@@ -53,10 +53,15 @@ LibraryDetailsController::LibraryDetailsController(
Qt4BuildConfiguration *qt4BuildConfiguration =
qobject_cast<Qt4BuildConfiguration *>(project->activeTarget()->activeBuildConfiguration());
// if its toolchain is maemo behave the same as we would be on linux
- if (qt4BuildConfiguration && qt4BuildConfiguration->toolChainType() == ProjectExplorer::ToolChain::GCC_MAEMO)
+ if (qt4BuildConfiguration && qt4BuildConfiguration->toolChainType() == ProjectExplorer::ToolChain_GCC_MAEMO)
m_creatorPlatform = CreatorLinux;
#endif
+ setPlatformsVisible(true);
+ setLinkageGroupVisible(true);
+ setMacLibraryGroupVisible(true);
+ setPackageLineEditVisible(false);
+
if (creatorPlatform() == CreatorMac)
setMacLibraryRadiosVisible(false);
@@ -230,6 +235,11 @@ void LibraryDetailsController::showMacLibraryType(
libraryDetailsWidget()->macGroupBox->setTitle(libraryTypeTitle);
}
+void LibraryDetailsController::setPlatformsVisible(bool ena)
+{
+ libraryDetailsWidget()->platformGroupBox->setVisible(ena);
+}
+
void LibraryDetailsController::setLinkageRadiosVisible(bool ena)
{
m_linkageRadiosVisible = ena;
@@ -237,6 +247,12 @@ void LibraryDetailsController::setLinkageRadiosVisible(bool ena)
libraryDetailsWidget()->dynamicRadio->setVisible(ena);
}
+void LibraryDetailsController::setLinkageGroupVisible(bool ena)
+{
+ setLinkageRadiosVisible(ena);
+ libraryDetailsWidget()->linkageGroupBox->setVisible(ena);
+}
+
void LibraryDetailsController::setMacLibraryRadiosVisible(bool ena)
{
m_macLibraryRadiosVisible = ena;
@@ -244,6 +260,12 @@ void LibraryDetailsController::setMacLibraryRadiosVisible(bool ena)
libraryDetailsWidget()->libraryRadio->setVisible(ena);
}
+void LibraryDetailsController::setMacLibraryGroupVisible(bool ena)
+{
+ setMacLibraryRadiosVisible(ena);
+ libraryDetailsWidget()->macGroupBox->setVisible(ena);
+}
+
void LibraryDetailsController::setLibraryPathChooserVisible(bool ena)
{
libraryDetailsWidget()->libraryPathChooser->setVisible(ena);
@@ -256,6 +278,12 @@ void LibraryDetailsController::setLibraryComboBoxVisible(bool ena)
libraryDetailsWidget()->libraryLabel->setVisible(ena);
}
+void LibraryDetailsController::setPackageLineEditVisible(bool ena)
+{
+ libraryDetailsWidget()->packageLineEdit->setVisible(ena);
+ libraryDetailsWidget()->packageLabel->setVisible(ena);
+}
+
void LibraryDetailsController::setIncludePathVisible(bool ena)
{
m_includePathVisible = ena;
@@ -737,6 +765,65 @@ QString NonInternalLibraryDetailsController::snippet() const
/////////////
+PackageLibraryDetailsController::PackageLibraryDetailsController(
+ Ui::LibraryDetailsWidget *libraryDetails,
+ const QString &proFile, QObject *parent)
+ : NonInternalLibraryDetailsController(libraryDetails, proFile, parent)
+{
+ setPlatformsVisible(false);
+ setIncludePathVisible(false);
+ setWindowsGroupVisible(false);
+ setLinkageGroupVisible(false);
+ setMacLibraryGroupVisible(false);
+ setLibraryPathChooserVisible(false);
+ setPackageLineEditVisible(true);
+
+ connect(libraryDetailsWidget()->packageLineEdit, SIGNAL(textChanged(QString)),
+ this, SIGNAL(completeChanged()));
+
+ updateGui();
+}
+
+bool PackageLibraryDetailsController::isComplete() const
+{
+ return !libraryDetailsWidget()->packageLineEdit->text().isEmpty();
+}
+
+QString PackageLibraryDetailsController::snippet() const
+{
+ QString snippetMessage;
+ QTextStream str(&snippetMessage);
+ str << "\n";
+ if (!isLinkPackageGenerated())
+ str << "unix: CONFIG += link_pkgconfig\n";
+ str << "unix: PKGCONFIG += " << libraryDetailsWidget()->packageLineEdit->text() << "\n";
+ return snippetMessage;
+}
+
+bool PackageLibraryDetailsController::isLinkPackageGenerated() const
+{
+ const ProjectExplorer::Project *project =
+ ProjectExplorer::ProjectExplorerPlugin::instance()->session()->projectForFile(proFile());
+ if (!project)
+ return false;
+
+ const Qt4ProFileNode *rootProject = qobject_cast<const Qt4ProFileNode *>(project->rootProjectNode());
+ if (!rootProject)
+ return false;
+
+ const Qt4ProFileNode *currentProject = rootProject->findProFileFor(proFile());
+ if (!currentProject)
+ return false;
+
+ const QStringList configVar = currentProject->variableValue(ConfigVar);
+ if (configVar.contains(QLatin1String("link_pkgconfig")))
+ return true;
+
+ return false;
+}
+
+/////////////
+
SystemLibraryDetailsController::SystemLibraryDetailsController(
Ui::LibraryDetailsWidget *libraryDetails,
const QString &proFile, QObject *parent)
diff --git a/src/plugins/qt4projectmanager/librarydetailscontroller.h b/src/plugins/qt4projectmanager/librarydetailscontroller.h
index e0afd57091..ec4d235bfd 100644
--- a/src/plugins/qt4projectmanager/librarydetailscontroller.h
+++ b/src/plugins/qt4projectmanager/librarydetailscontroller.h
@@ -51,10 +51,14 @@ protected:
void setIgnoreGuiSignals(bool ignore);
+ void setPlatformsVisible(bool ena);
void setLinkageRadiosVisible(bool ena);
+ void setLinkageGroupVisible(bool ena);
void setMacLibraryRadiosVisible(bool ena);
+ void setMacLibraryGroupVisible(bool ena);
void setLibraryPathChooserVisible(bool ena);
void setLibraryComboBoxVisible(bool ena);
+ void setPackageLineEditVisible(bool ena);
void setIncludePathVisible(bool ena);
void setWindowsGroupVisible(bool ena);
void setRemoveSuffixVisible(bool ena);
@@ -113,6 +117,19 @@ private slots:
void slotLibraryPathChanged();
};
+class PackageLibraryDetailsController : public NonInternalLibraryDetailsController
+{
+ Q_OBJECT
+public:
+ explicit PackageLibraryDetailsController(Ui::LibraryDetailsWidget *libraryDetails,
+ const QString &proFile,
+ QObject *parent = 0);
+ virtual bool isComplete() const;
+ virtual QString snippet() const;
+private:
+ bool isLinkPackageGenerated() const;
+};
+
class SystemLibraryDetailsController : public NonInternalLibraryDetailsController
{
Q_OBJECT
diff --git a/src/plugins/qt4projectmanager/librarydetailswidget.ui b/src/plugins/qt4projectmanager/librarydetailswidget.ui
index af3be9bc3a..bd581d35d3 100644
--- a/src/plugins/qt4projectmanager/librarydetailswidget.ui
+++ b/src/plugins/qt4projectmanager/librarydetailswidget.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>368</width>
- <height>306</height>
+ <width>455</width>
+ <height>370</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_2">
@@ -33,16 +33,26 @@
<item row="1" column="1">
<widget class="Qt4ProjectManager::Internal::LibraryPathChooser" name="libraryPathChooser" native="true"/>
</item>
- <item row="2" column="0">
+ <item row="3" column="0">
<widget class="QLabel" name="includeLabel">
<property name="text">
<string>Include path:</string>
</property>
</widget>
</item>
- <item row="2" column="1">
+ <item row="3" column="1">
<widget class="Utils::PathChooser" name="includePathChooser" native="true"/>
</item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="packageLabel">
+ <property name="text">
+ <string>Package:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLineEdit" name="packageLineEdit"/>
+ </item>
</layout>
</item>
<item row="1" column="0">
diff --git a/src/plugins/qt4projectmanager/makestep.cpp b/src/plugins/qt4projectmanager/makestep.cpp
index c7597b7e9f..1f3b1869d9 100644
--- a/src/plugins/qt4projectmanager/makestep.cpp
+++ b/src/plugins/qt4projectmanager/makestep.cpp
@@ -39,13 +39,12 @@
#include "qt4buildconfiguration.h"
#include "qt4projectmanagerconstants.h"
#include "qtparser.h"
-#include "qt-s60/abldparser.h"
-#include "qt-s60/sbsv2parser.h"
+#include <projectexplorer/toolchain.h>
#include <projectexplorer/buildsteplist.h>
-#include <projectexplorer/gnumakeparser.h>
#include <projectexplorer/projectexplorer.h>
#include <extensionsystem/pluginmanager.h>
+#include <utils/qtcprocess.h>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
@@ -116,7 +115,7 @@ QVariantMap MakeStep::toMap() const
bool MakeStep::fromMap(const QVariantMap &map)
{
m_makeCmd = map.value(QLatin1String(MAKE_COMMAND_KEY)).toString();
- m_userArgs = map.value(QLatin1String(MAKE_ARGUMENTS_KEY)).toStringList();
+ m_userArgs = map.value(QLatin1String(MAKE_ARGUMENTS_KEY)).toString();
m_clean = map.value(QLatin1String(CLEAN_KEY)).toBool();
return ProjectExplorer::AbstractProcessStep::fromMap(map);
@@ -125,75 +124,75 @@ bool MakeStep::fromMap(const QVariantMap &map)
bool MakeStep::init()
{
Qt4BuildConfiguration *bc = qt4BuildConfiguration();
+ ProjectExplorer::ProcessParameters *pp = processParameters();
+ pp->setMacroExpander(bc->macroExpander());
+
Utils::Environment environment = bc->environment();
- setEnvironment(environment);
+ pp->setEnvironment(environment);
QString workingDirectory;
if (bc->subNodeBuild())
workingDirectory = bc->subNodeBuild()->buildDir();
else
workingDirectory = bc->buildDirectory();
- setWorkingDirectory(workingDirectory);
+ pp->setWorkingDirectory(workingDirectory);
QString makeCmd = bc->makeCommand();
if (!m_makeCmd.isEmpty())
makeCmd = m_makeCmd;
- if (!QFileInfo(makeCmd).isAbsolute()) {
- // Try to detect command in environment
- const QString tmp = environment.searchInPath(makeCmd);
- if (tmp.isEmpty()) {
- emit addOutput(tr("Could not find make command: %1 in the build environment").arg(makeCmd), BuildStep::ErrorOutput);
- return false;
- }
- makeCmd = tmp;
- }
- setCommand(makeCmd);
+ pp->setCommand(makeCmd);
// If we are cleaning, then make can fail with a error code, but that doesn't mean
// we should stop the clean queue
// That is mostly so that rebuild works on a already clean project
setIgnoreReturnValue(m_clean);
- QStringList args = m_userArgs;
+
+ QString args;
+
+ ProjectExplorer::ToolChain *toolchain = bc->toolChain();
+
+ if (bc->subNodeBuild()){
+ if(!bc->subNodeBuild()->makefile().isEmpty()) {
+ Utils::QtcProcess::addArg(&args, QLatin1String("-f"));
+ Utils::QtcProcess::addArg(&args, bc->subNodeBuild()->makefile());
+ }
+ } else if (!bc->makefile().isEmpty()) {
+ Utils::QtcProcess::addArg(&args, QLatin1String("-f"));
+ Utils::QtcProcess::addArg(&args, bc->makefile());
+ }
+
+ Utils::QtcProcess::addArgs(&args, m_userArgs);
+
if (!m_clean) {
if (!bc->defaultMakeTarget().isEmpty())
- args << bc->defaultMakeTarget();
+ Utils::QtcProcess::addArg(&args, bc->defaultMakeTarget());
}
// -w option enables "Enter"/"Leaving directory" messages, which we need for detecting the
// absolute file path
// FIXME doing this without the user having a way to override this is rather bad
// so we only do it for unix and if the user didn't override the make command
// but for now this is the least invasive change
- ProjectExplorer::ToolChain *toolchain = bc->toolChain();
if (toolchain) {
- if (toolchain->type() != ProjectExplorer::ToolChain::MSVC &&
- toolchain->type() != ProjectExplorer::ToolChain::WINCE) {
+ if (toolchain->type() != ProjectExplorer::ToolChain_MSVC &&
+ toolchain->type() != ProjectExplorer::ToolChain_WINCE) {
if (m_makeCmd.isEmpty())
- args << "-w";
+ Utils::QtcProcess::addArg(&args, QLatin1String("-w"));
}
}
setEnabled(true);
- setArguments(args);
-
- m_gnuMakeParser = 0;
-
- if (bc->qtVersion()->supportsTargetId(Qt4ProjectManager::Constants::S60_DEVICE_TARGET_ID) ||
- bc->qtVersion()->supportsTargetId(Qt4ProjectManager::Constants::S60_EMULATOR_TARGET_ID)) {
- if (bc->qtVersion()->isBuildWithSymbianSbsV2()) {
- setOutputParser(new SbsV2Parser);
- } else {
- setOutputParser(new AbldParser);
- m_gnuMakeParser = new ProjectExplorer::GnuMakeParser(workingDirectory);
- appendOutputParser(m_gnuMakeParser);
- }
- } else {
- setOutputParser(new ProjectExplorer::GnuMakeParser(workingDirectory));
- }
- appendOutputParser(new QtParser);
+ pp->setArguments(args);
+ ProjectExplorer::IOutputParser *parser = bc->qtVersion()->createOutputParser();
+ Q_ASSERT(parser);
+ parser->appendOutputParser(new QtParser);
if (toolchain)
- appendOutputParser(toolchain->outputParser());
+ parser->appendOutputParser(toolchain->outputParser());
+
+ parser->setWorkingDirectory(workingDirectory);
+
+ setOutputParser(parser);
return AbstractProcessStep::init();
}
@@ -211,8 +210,8 @@ void MakeStep::run(QFutureInterface<bool> & fi)
bool MakeStep::processSucceeded(int exitCode, QProcess::ExitStatus status)
{
// Symbian does retun 0, even on failed makes! So we check for fatal make errors here.
- if (m_gnuMakeParser)
- return m_gnuMakeParser->fatalErrors() == 0;
+ if (outputParser() && outputParser()->hasFatalErrors())
+ return false;
return AbstractProcessStep::processSucceeded(exitCode, status);
}
@@ -227,12 +226,12 @@ ProjectExplorer::BuildStepConfigWidget *MakeStep::createConfigWidget()
return new MakeStepConfigWidget(this);
}
-QStringList MakeStep::userArguments()
+QString MakeStep::userArguments()
{
return m_userArgs;
}
-void MakeStep::setUserArguments(const QStringList &arguments)
+void MakeStep::setUserArguments(const QString &arguments)
{
m_userArgs = arguments;
emit userArgumentsChanged();
@@ -285,38 +284,36 @@ void MakeStepConfigWidget::updateMakeOverrideLabel()
void MakeStepConfigWidget::updateDetails()
{
Qt4BuildConfiguration *bc = m_makeStep->qt4BuildConfiguration();
- QString workingDirectory = bc->buildDirectory();
+ ProjectExplorer::ProcessParameters param;
+ param.setMacroExpander(bc->macroExpander());
+ param.setWorkingDirectory(bc->buildDirectory());
+ param.setEnvironment(bc->environment());
QString makeCmd = bc->makeCommand();
if (!m_makeStep->m_makeCmd.isEmpty())
makeCmd = m_makeStep->m_makeCmd;
- if (!QFileInfo(makeCmd).isAbsolute()) {
- Utils::Environment environment = bc->environment();
- // Try to detect command in environment
- const QString tmp = environment.searchInPath(makeCmd);
- if (tmp.isEmpty()) {
- m_summaryText = tr("<b>Make:</b> %1 not found in the environment.").arg(makeCmd);
- emit updateSummary();
- return;
- }
- makeCmd = tmp;
+ param.setCommand(makeCmd);
+ if (param.commandMissing()) {
+ m_summaryText = tr("<b>Make:</b> %1 not found in the environment.").arg(makeCmd);
+ emit updateSummary();
+ return;
}
// -w option enables "Enter"/"Leaving directory" messages, which we need for detecting the
// absolute file path
// FIXME doing this without the user having a way to override this is rather bad
// so we only do it for unix and if the user didn't override the make command
// but for now this is the least invasive change
- QStringList args = m_makeStep->userArguments();
- ProjectExplorer::ToolChain::ToolChainType t = ProjectExplorer::ToolChain::UNKNOWN;
+ QString args = m_makeStep->userArguments();
+ ProjectExplorer::ToolChainType t = ProjectExplorer::ToolChain_UNKNOWN;
ProjectExplorer::ToolChain *toolChain = bc->toolChain();
if (toolChain)
t = toolChain->type();
- if (t != ProjectExplorer::ToolChain::MSVC && t != ProjectExplorer::ToolChain::WINCE) {
+ if (t != ProjectExplorer::ToolChain_MSVC && t != ProjectExplorer::ToolChain_WINCE) {
if (m_makeStep->m_makeCmd.isEmpty())
- args << "-w";
+ Utils::QtcProcess::addArg(&args, QLatin1String("-w"));
}
- m_summaryText = tr("<b>Make:</b> %1 %2 in %3").arg(QFileInfo(makeCmd).fileName(), args.join(" "),
- QDir::toNativeSeparators(workingDirectory));
+ param.setArguments(args);
+ m_summaryText = param.summaryInWorkdir(displayName());
emit updateSummary();
}
@@ -334,8 +331,7 @@ void MakeStepConfigWidget::userArgumentsChanged()
{
if (m_ignoreChange)
return;
- const QStringList &makeArguments = m_makeStep->userArguments();
- m_ui->makeArgumentsLineEdit->setText(Utils::Environment::joinArgumentList(makeArguments));
+ m_ui->makeArgumentsLineEdit->setText(m_makeStep->userArguments());
updateDetails();
}
@@ -346,8 +342,7 @@ void MakeStepConfigWidget::init()
const QString &makeCmd = m_makeStep->m_makeCmd;
m_ui->makePathChooser->setPath(makeCmd);
- const QStringList &makeArguments = m_makeStep->userArguments();
- m_ui->makeArgumentsLineEdit->setText(Utils::Environment::joinArgumentList(makeArguments));
+ m_ui->makeArgumentsLineEdit->setText(m_makeStep->userArguments());
updateDetails();
}
@@ -360,8 +355,7 @@ void MakeStepConfigWidget::makeEdited()
void MakeStepConfigWidget::makeArgumentsLineEdited()
{
m_ignoreChange = true;
- m_makeStep->setUserArguments(
- Utils::Environment::parseCombinedArgString(m_ui->makeArgumentsLineEdit->text()));
+ m_makeStep->setUserArguments(m_ui->makeArgumentsLineEdit->text());
m_ignoreChange = false;
updateDetails();
}
diff --git a/src/plugins/qt4projectmanager/makestep.h b/src/plugins/qt4projectmanager/makestep.h
index a8dcca8494..f107883b87 100644
--- a/src/plugins/qt4projectmanager/makestep.h
+++ b/src/plugins/qt4projectmanager/makestep.h
@@ -51,9 +51,10 @@ class Project;
}
namespace Qt4ProjectManager {
-namespace Internal {
class Qt4BuildConfiguration;
+namespace Internal {
+
class MakeStepFactory : public ProjectExplorer::IBuildStepFactory
{
Q_OBJECT
@@ -87,7 +88,7 @@ public:
explicit MakeStep(ProjectExplorer::BuildStepList *bsl);
virtual ~MakeStep();
- Internal::Qt4BuildConfiguration *qt4BuildConfiguration() const;
+ Qt4BuildConfiguration *qt4BuildConfiguration() const;
virtual bool init();
virtual void run(QFutureInterface<bool> &);
@@ -95,8 +96,8 @@ public:
virtual ProjectExplorer::BuildStepConfigWidget *createConfigWidget();
virtual bool immutable() const;
- QStringList userArguments();
- void setUserArguments(const QStringList &arguments);
+ QString userArguments();
+ void setUserArguments(const QString &arguments);
void setClean(bool clean);
QVariantMap toMap() const;
@@ -112,9 +113,8 @@ protected:
private:
void ctor();
bool m_clean;
- QStringList m_userArgs;
+ QString m_userArgs;
QString m_makeCmd;
- ProjectExplorer::GnuMakeParser * m_gnuMakeParser;
};
class MakeStepConfigWidget : public ProjectExplorer::BuildStepConfigWidget
diff --git a/src/plugins/qt4projectmanager/profilecompletion.cpp b/src/plugins/qt4projectmanager/profilecompletion.cpp
new file mode 100644
index 0000000000..9d3f706d8a
--- /dev/null
+++ b/src/plugins/qt4projectmanager/profilecompletion.cpp
@@ -0,0 +1,189 @@
+#include "profilecompletion.h"
+#include "profileeditor.h"
+#include "profilekeywords.h"
+#include <texteditor/itexteditor.h>
+#include <texteditor/completionsettings.h>
+#include <cplusplus/Icons.h>
+#include <QDebug>
+
+using namespace Qt4ProjectManager::Internal;
+
+ProFileCompletion::ProFileCompletion(QObject *parent) :
+ TextEditor::ICompletionCollector(parent),
+ m_editor(0),
+ m_startPosition(-1),
+ m_variableIcon(CPlusPlus::Icons().iconForType(CPlusPlus::Icons::VarPublicIconType)),
+ m_functionIcon(CPlusPlus::Icons().iconForType(CPlusPlus::Icons::FuncPublicIconType))
+{
+}
+
+ProFileCompletion::~ProFileCompletion()
+{
+
+}
+
+QList<TextEditor::CompletionItem> ProFileCompletion::getCompletions()
+{
+ QList<TextEditor::CompletionItem> completionItems;
+ completions(&completionItems);
+
+ return completionItems;
+}
+
+bool ProFileCompletion::shouldRestartCompletion()
+{
+ return false;
+}
+
+TextEditor::ITextEditable *ProFileCompletion::editor() const
+{
+ return m_editor;
+}
+
+int ProFileCompletion::startPosition() const
+{
+ return m_startPosition;
+}
+
+bool ProFileCompletion::supportsEditor(TextEditor::ITextEditable *editor)
+{
+ if (qobject_cast<ProFileEditorEditable *>(editor))
+ return true;
+ return false;
+}
+
+bool ProFileCompletion::triggersCompletion(TextEditor::ITextEditable *editor)
+{
+ m_editor = editor;
+ const int pos = editor->position();
+
+ if (completionSettings().m_completionTrigger == TextEditor::AutomaticCompletion) {
+ QChar characterUnderCursor = editor->characterAt(pos);
+ if (!characterUnderCursor.isLetterOrNumber()) {
+ m_startPosition = findStartOfName();
+ if (pos - m_startPosition >= 3 && !isInComment())
+ return true;
+ }
+ }
+ return false;
+}
+
+int ProFileCompletion::findStartOfName(int pos) const
+{
+ if (pos == -1)
+ pos = m_editor->position();
+ QChar chr;
+
+ // Skip to the start of a name
+ do {
+ chr = m_editor->characterAt(--pos);
+ } while (chr.isLetterOrNumber() || chr == QLatin1Char('_'));
+
+ return pos + 1;
+}
+
+bool ProFileCompletion::isInComment() const
+{
+ const int beginOfLinePosition = m_editor->position(TextEditor::ITextEditor::StartOfLine);
+ const QString lineBeginning = m_editor->textAt(beginOfLinePosition,
+ m_startPosition - beginOfLinePosition);
+ if (lineBeginning.contains(QLatin1Char('#')))
+ return true;
+ return false;
+}
+
+int ProFileCompletion::startCompletion(TextEditor::ITextEditable *editor)
+{
+ m_editor = editor;
+ m_startPosition = findStartOfName();
+
+ return m_startPosition;
+}
+
+void ProFileCompletion::completions(QList<TextEditor::CompletionItem> *completions)
+{
+ const int length = m_editor->position() - m_startPosition;
+ if (length < 0)
+ return;
+
+ if (isInComment())
+ return;
+
+ const QString key = m_editor->textAt(m_startPosition, length);
+
+ QList<TextEditor::CompletionItem> items;
+ QStringList keywords = ProFileKeywords::variables()
+ + ProFileKeywords::functions();
+// qSort(keywords);
+ for (int i = 0; i < keywords.count(); i++) {
+ TextEditor::CompletionItem item(this);
+ item.text = keywords[i];
+ item.data = QVariant::fromValue(item.text);
+ item.icon = ProFileKeywords::isFunction(item.text)
+ ? m_functionIcon : m_variableIcon;
+ items.append(item);
+ }
+
+ filter(items, completions, key);
+}
+
+bool ProFileCompletion::typedCharCompletes(const TextEditor::CompletionItem &item, QChar typedChar)
+{
+ // only '(' in case of a function
+ if (typedChar == QLatin1Char('(') && ProFileKeywords::isFunction(item.text))
+ return true;
+ return false;
+}
+
+void ProFileCompletion::complete(const TextEditor::CompletionItem &item, QChar typedChar)
+{
+ Q_UNUSED(typedChar)
+
+ int replaceLength = m_editor->position() - m_startPosition;
+ if (replaceLength < 0)
+ return;
+
+ QString toInsert = item.text;
+ int cursorOffset = 0;
+ if (ProFileKeywords::isFunction(toInsert)
+ && completionSettings().m_autoInsertBrackets) {
+ if (completionSettings().m_spaceAfterFunctionName) {
+ if (m_editor->textAt(m_editor->position(), 2) == QLatin1String(" (")) {
+ cursorOffset = 2;
+ } else if (m_editor->characterAt(m_editor->position()) == QLatin1Char('(')
+ || m_editor->characterAt(m_editor->position()) == QLatin1Char(' ')) {
+ replaceLength += 1;
+ toInsert += QLatin1String(" (");
+ } else {
+ toInsert += QLatin1String(" ()");
+ cursorOffset = -1;
+ }
+ } else {
+ if (m_editor->characterAt(m_editor->position()) == QLatin1Char('(')) {
+ cursorOffset = 1;
+ } else {
+ toInsert += QLatin1String("()");
+ cursorOffset = -1;
+ }
+ }
+ }
+
+ m_editor->setCurPos(m_startPosition);
+ m_editor->replace(replaceLength, toInsert);
+ if (cursorOffset)
+ m_editor->setCurPos(m_editor->position() + cursorOffset);
+}
+
+bool ProFileCompletion::partiallyComplete(const QList<TextEditor::CompletionItem> &completionItems)
+{
+ if (completionItems.count() == 1) {
+ complete(completionItems.first(), QChar());
+ return true;
+ }
+
+ return TextEditor::ICompletionCollector::partiallyComplete(completionItems);
+}
+
+void ProFileCompletion::cleanup()
+{
+}
diff --git a/src/plugins/qt4projectmanager/profilecompletion.h b/src/plugins/qt4projectmanager/profilecompletion.h
new file mode 100644
index 0000000000..cdbec85adf
--- /dev/null
+++ b/src/plugins/qt4projectmanager/profilecompletion.h
@@ -0,0 +1,45 @@
+#ifndef PROFILECOMPLETION_H
+#define PROFILECOMPLETION_H
+
+#include <texteditor/icompletioncollector.h>
+
+namespace Qt4ProjectManager {
+
+namespace Internal {
+
+class ProFileCompletion : public TextEditor::ICompletionCollector
+{
+ Q_OBJECT
+public:
+ ProFileCompletion(QObject *parent = 0);
+
+ virtual ~ProFileCompletion();
+
+ virtual QList<TextEditor::CompletionItem> getCompletions();
+ virtual bool shouldRestartCompletion();
+
+ virtual TextEditor::ITextEditable *editor() const;
+ virtual int startPosition() const;
+
+ virtual bool supportsEditor(TextEditor::ITextEditable *editor);
+ virtual bool triggersCompletion(TextEditor::ITextEditable *editor);
+ virtual int startCompletion(TextEditor::ITextEditable *editor);
+ virtual void completions(QList<TextEditor::CompletionItem> *completions);
+ virtual bool typedCharCompletes(const TextEditor::CompletionItem &item, QChar typedChar);
+ virtual void complete(const TextEditor::CompletionItem &item, QChar typedChar);
+ virtual bool partiallyComplete(const QList<TextEditor::CompletionItem> &completionItems);
+ virtual void cleanup();
+private:
+ int findStartOfName(int pos = -1) const;
+ bool isInComment() const;
+
+ TextEditor::ITextEditable *m_editor;
+ int m_startPosition;
+ const QIcon m_variableIcon;
+ const QIcon m_functionIcon;
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // PROFILECOMPLETION_H
diff --git a/src/plugins/qt4projectmanager/profileeditor.cpp b/src/plugins/qt4projectmanager/profileeditor.cpp
index f596e41f8a..a3ec035266 100644
--- a/src/plugins/qt4projectmanager/profileeditor.cpp
+++ b/src/plugins/qt4projectmanager/profileeditor.cpp
@@ -41,6 +41,7 @@
#include <coreplugin/icore.h>
#include <coreplugin/actionmanager/actionmanager.h>
+#include <coreplugin/uniqueidmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <texteditor/fontsettings.h>
#include <texteditor/texteditoractionhandler.h>
@@ -48,6 +49,7 @@
#include <texteditor/texteditorsettings.h>
#include <QtCore/QFileInfo>
+#include <QtCore/QDir>
#include <QtGui/QMenu>
using namespace Qt4ProjectManager;
@@ -111,6 +113,95 @@ void ProFileEditor::unCommentSelection()
Utils::unCommentSelection(this, m_commentDefinition);
}
+static bool isValidFileNameChar(const QChar &c)
+{
+ if (c.isLetterOrNumber()
+ || c == QLatin1Char('.')
+ || c == QLatin1Char('_')
+ || c == QLatin1Char('-')
+ || c == QLatin1Char('/')
+ || c == QLatin1Char('\\'))
+ return true;
+ return false;
+}
+
+ProFileEditor::Link ProFileEditor::findLinkAt(const QTextCursor &cursor,
+ bool /* resolveTarget */)
+{
+ Link link;
+
+ int lineNumber = 0, positionInBlock = 0;
+ convertPosition(cursor.position(), &lineNumber, &positionInBlock);
+
+ const QString block = cursor.block().text();
+
+ // check if the current position is commented out
+ const int hashPos = block.indexOf(QLatin1Char('#'));
+ if (hashPos >= 0 && hashPos < positionInBlock)
+ return link;
+
+ // find the beginning of a filename
+ QString buffer;
+ int beginPos = positionInBlock - 1;
+ while (beginPos >= 0) {
+ QChar c = block.at(beginPos);
+ if (isValidFileNameChar(c)) {
+ buffer.prepend(c);
+ beginPos--;
+ } else {
+ break;
+ }
+ }
+
+ // find the end of a filename
+ int endPos = positionInBlock;
+ while (endPos < block.count()) {
+ QChar c = block.at(endPos);
+ if (isValidFileNameChar(c)) {
+ buffer.append(c);
+ endPos++;
+ } else {
+ break;
+ }
+ }
+
+ if (buffer.isEmpty())
+ return link;
+
+ // remove trailing '\' since it can be line continuation char
+ if (buffer.at(buffer.size() - 1) == QLatin1Char('\\')) {
+ buffer.chop(1);
+ endPos--;
+ }
+
+ // if the buffer starts with $$PWD accept it
+ if (buffer.startsWith(QLatin1String("PWD/")) ||
+ buffer.startsWith(QLatin1String("PWD\\"))) {
+ if (beginPos > 0 && block.mid(beginPos - 1, 2) == QLatin1String("$$")) {
+ beginPos -=2;
+ buffer = buffer.mid(4);
+ }
+ }
+
+ QDir dir(QFileInfo(file()->fileName()).absolutePath());
+ QString fileName = dir.filePath(buffer);
+ QFileInfo fi(fileName);
+ if (fi.exists()) {
+ if (fi.isDir()) {
+ QDir subDir(fi.absoluteFilePath());
+ QString subProject = subDir.filePath(subDir.dirName() + QLatin1String(".pro"));
+ if (QFileInfo(subProject).exists())
+ fileName = subProject;
+ else
+ return link;
+ }
+ link.fileName = fileName;
+ link.begin = cursor.position() - positionInBlock + beginPos + 1;
+ link.end = cursor.position() - positionInBlock + endPos;
+ }
+ return link;
+}
+
TextEditor::BaseTextEditorEditable *ProFileEditor::createEditableInterface()
{
return new ProFileEditorEditable(this);
@@ -173,6 +264,11 @@ void ProFileEditor::addLibrary()
editable->insert(snippet);
}
+void ProFileEditor::jumpToFile()
+{
+ openLink(findLinkAt(textCursor()));
+}
+
//
// ProFileDocument
//
diff --git a/src/plugins/qt4projectmanager/profileeditor.h b/src/plugins/qt4projectmanager/profileeditor.h
index 3d09aec109..8a2cd09b37 100644
--- a/src/plugins/qt4projectmanager/profileeditor.h
+++ b/src/plugins/qt4projectmanager/profileeditor.h
@@ -57,6 +57,8 @@ class ProFileEditor;
class ProFileEditorEditable : public TextEditor::BaseTextEditorEditable
{
+ Q_OBJECT
+
public:
ProFileEditorEditable(ProFileEditor *);
Core::Context context() const;
@@ -86,12 +88,14 @@ public:
void unCommentSelection();
protected:
+ virtual Link findLinkAt(const QTextCursor &, bool resolveTarget = true);
TextEditor::BaseTextEditorEditable *createEditableInterface();
void contextMenuEvent(QContextMenuEvent *);
public slots:
virtual void setFontSettings(const TextEditor::FontSettings &);
void addLibrary();
+ void jumpToFile();
private:
ProFileEditorFactory *m_factory;
diff --git a/src/plugins/qt4projectmanager/profileeditorfactory.cpp b/src/plugins/qt4projectmanager/profileeditorfactory.cpp
index 1d0a601e4b..4a0fc539af 100644
--- a/src/plugins/qt4projectmanager/profileeditorfactory.cpp
+++ b/src/plugins/qt4projectmanager/profileeditorfactory.cpp
@@ -41,6 +41,7 @@
#include <coreplugin/editormanager/editormanager.h>
#include <texteditor/texteditoractionhandler.h>
#include <texteditor/texteditorsettings.h>
+#include <texteditor/completionsupport.h>
#include <QtCore/QFileInfo>
#include <QtGui/QAction>
@@ -87,9 +88,13 @@ Core::IFile *ProFileEditorFactory::open(const QString &fileName)
Core::IEditor *ProFileEditorFactory::createEditor(QWidget *parent)
{
- ProFileEditor *rc = new ProFileEditor(parent, this, m_actionHandler);
- TextEditor::TextEditorSettings::instance()->initializeEditor(rc);
- return rc->editableInterface();
+ ProFileEditor *editor = new ProFileEditor(parent, this, m_actionHandler);
+ TextEditor::TextEditorSettings::instance()->initializeEditor(editor);
+
+ // auto completion
+ connect(editor, SIGNAL(requestAutoCompletion(TextEditor::ITextEditable*, bool)),
+ TextEditor::CompletionSupport::instance(), SLOT(autoComplete(TextEditor::ITextEditable*, bool)));
+ return editor->editableInterface();
}
QStringList ProFileEditorFactory::mimeTypes() const
diff --git a/src/plugins/qt4projectmanager/profilehighlighter.cpp b/src/plugins/qt4projectmanager/profilehighlighter.cpp
index 7a63758462..a3b60bda85 100644
--- a/src/plugins/qt4projectmanager/profilehighlighter.cpp
+++ b/src/plugins/qt4projectmanager/profilehighlighter.cpp
@@ -32,6 +32,7 @@
**************************************************************************/
#include "profilehighlighter.h"
+#include "profilekeywords.h"
#include <QtCore/QRegExp>
#include <QtGui/QColor>
@@ -40,125 +41,6 @@
using namespace Qt4ProjectManager::Internal;
-const char *const variables[] = {
- "CCFLAG",
- "CONFIG",
- "DEFINES",
- "DEF_FILE",
- "DEPENDPATH",
- "DEPLOYMENT",
- "DESTDIR",
- "DESTDIR_TARGET",
- "DISTFILES",
- "DLLDESTDIR",
- "FORMS",
- "HEADERS",
- "ICON",
- "INCLUDEPATH",
- "INSTALLS",
- "LEXSOURCES",
- "LIBS",
- "MAKEFILE",
- "MOBILITY",
- "MOC_DIR",
- "OBJECTIVE_HEADERS",
- "OBJECTIVE_SOURCES",
- "OBJECTS",
- "OBJECTS_DIR",
- "OBJMOC",
- "OTHER_FILES",
- "PKGCONFIG",
- "POST_TARGETDEPS",
- "PRECOMPILED_HEADER",
- "PRE_TARGETDEPS",
- "QMAKE",
- "QMAKESPEC",
- "QT",
- "RCC_DIR",
- "RC_FILE",
- "REQUIRES",
- "RESOURCES",
- "RES_FILE",
- "SOURCES",
- "SRCMOC",
- "STATECHARTS",
- "SUBDIRS",
- "TARGET",
- "TARGET.CAPABILITY",
- "TARGET.EPOCHEAPSIZE",
- "TARGET.UID3",
- "TARGET_EXT",
- "TARGET_x",
- "TARGET_x.y.z",
- "TEMPLATE",
- "TRANSLATIONS",
- "UI_DIR",
- "UI_HEADERS_DIR",
- "UI_SOURCES_DIR",
- "VER_MAJ",
- "VER_MIN",
- "VER_PAT",
- "VERSION",
- "VPATH",
- "YACCSOURCES",
- 0
-};
-
-const char *const functions[] = {
- "basename",
- "contains",
- "count",
- "dirname",
- "error",
- "exists",
- "find",
- "for",
- "include",
- "infile",
- "isEmpty",
- "join",
- "member",
- "message",
- "prompt",
- "quote",
- "sprintf",
- "system",
- "unique",
- "warning",
- 0
-};
-
-struct KeywordHelper
-{
- inline KeywordHelper(const QString &word) : needle(word) {}
- const QString needle;
-};
-
-static bool operator<(const KeywordHelper &helper, const char *kw)
-{
- return helper.needle < QLatin1String(kw);
-}
-
-static bool operator<(const char *kw, const KeywordHelper &helper)
-{
- return QLatin1String(kw) < helper.needle;
-}
-
-static bool isVariable(const QString &word)
-{
- const char *const *start = &variables[0];
- const char *const *end = &variables[sizeof variables / sizeof variables[0] - 1];
- const char *const *kw = qBinaryFind(start, end, KeywordHelper(word));
- return *kw != 0;
-}
-
-static bool isFunction(const QString &word)
-{
- const char *const *start = &functions[0];
- const char *const *end = &functions[sizeof functions / sizeof functions[0] - 1];
- const char *const *kw = qBinaryFind(start, end, KeywordHelper(word));
- return *kw != 0;
-}
ProFileHighlighter::ProFileHighlighter(QTextDocument *document) :
TextEditor::SyntaxHighlighter(document)
@@ -183,12 +65,12 @@ void ProFileHighlighter::highlightBlock(const QString &text)
if (c.isLetter() || c == '_' || c == '.' || c.isDigit()) {
buf += c;
setFormat(i - buf.length()+1, buf.length(), emptyFormat);
- if (!buf.isEmpty() && isFunction(buf))
+ if (!buf.isEmpty() && ProFileKeywords::isFunction(buf))
setFormat(i - buf.length()+1, buf.length(), m_formats[ProfileFunctionFormat]);
- else if (!buf.isEmpty() && isVariable(buf))
+ else if (!buf.isEmpty() && ProFileKeywords::isVariable(buf))
setFormat(i - buf.length()+1, buf.length(), m_formats[ProfileVariableFormat]);
} else if (c == '(') {
- if (!buf.isEmpty() && isFunction(buf))
+ if (!buf.isEmpty() && ProFileKeywords::isFunction(buf))
setFormat(i - buf.length(), buf.length(), m_formats[ProfileFunctionFormat]);
buf.clear();
} else if (c == '#') {
@@ -196,7 +78,7 @@ void ProFileHighlighter::highlightBlock(const QString &text)
setFormat(i, 1, m_formats[ProfileCommentFormat]);
buf.clear();
} else {
- if (!buf.isEmpty() && isVariable(buf))
+ if (!buf.isEmpty() && ProFileKeywords::isVariable(buf))
setFormat(i - buf.length(), buf.length(), m_formats[ProfileVariableFormat]);
buf.clear();
}
diff --git a/src/plugins/qt4projectmanager/profilekeywords.cpp b/src/plugins/qt4projectmanager/profilekeywords.cpp
new file mode 100644
index 0000000000..1e0ee9b65d
--- /dev/null
+++ b/src/plugins/qt4projectmanager/profilekeywords.cpp
@@ -0,0 +1,167 @@
+#include "profilekeywords.h"
+
+using namespace Qt4ProjectManager::Internal;
+
+static const char *const variableKeywords[] = {
+ "CCFLAG",
+ "CONFIG",
+ "DEFINES",
+ "DEF_FILE",
+ "DEPENDPATH",
+ "DEPLOYMENT",
+ "DESTDIR",
+ "DESTDIR_TARGET",
+ "DISTFILES",
+ "DLLDESTDIR",
+ "FORMS",
+ "HEADERS",
+ "ICON",
+ "INCLUDEPATH",
+ "INSTALLS",
+ "LEXSOURCES",
+ "LIBS",
+ "MAKEFILE",
+ "MOBILITY",
+ "MOC_DIR",
+ "OBJECTIVE_HEADERS",
+ "OBJECTIVE_SOURCES",
+ "OBJECTS",
+ "OBJECTS_DIR",
+ "OBJMOC",
+ "OTHER_FILES",
+ "PKGCONFIG",
+ "POST_TARGETDEPS",
+ "PRECOMPILED_HEADER",
+ "PRE_TARGETDEPS",
+ "QMAKE",
+ "QMAKESPEC",
+ "QT",
+ "RCC_DIR",
+ "RC_FILE",
+ "REQUIRES",
+ "RESOURCES",
+ "RES_FILE",
+ "SOURCES",
+ "SRCMOC",
+ "STATECHARTS",
+ "SUBDIRS",
+ "TARGET",
+ "TARGET.CAPABILITY",
+ "TARGET.EPOCHEAPSIZE",
+ "TARGET.UID3",
+ "TARGET_EXT",
+ "TARGET_x",
+ "TARGET_x.y.z",
+ "TEMPLATE",
+ "TRANSLATIONS",
+ "UI_DIR",
+ "UI_HEADERS_DIR",
+ "UI_SOURCES_DIR",
+ "VER_MAJ",
+ "VER_MIN",
+ "VER_PAT",
+ "VERSION",
+ "VPATH",
+ "YACCSOURCES",
+ 0
+};
+
+static const char *const functionKeywords[] = {
+ "basename",
+ "contains",
+ "count",
+ "dirname",
+ "error",
+ "exists",
+ "find",
+ "for",
+ "include",
+ "infile",
+ "isEmpty",
+ "join",
+ "member",
+ "message",
+ "prompt",
+ "quote",
+ "sprintf",
+ "system",
+ "unique",
+ "warning",
+ 0
+};
+
+class ProFileKeywordsImplementation
+{
+public:
+ static ProFileKeywordsImplementation *instance();
+ QStringList variables();
+ QStringList functions();
+ bool isVariable(const QString &word);
+ bool isFunction(const QString &word);
+private:
+ ProFileKeywordsImplementation();
+ static ProFileKeywordsImplementation *m_instance;
+ QStringList m_variables;
+ QStringList m_functions;
+};
+
+ProFileKeywordsImplementation *ProFileKeywordsImplementation::m_instance = 0;
+
+ProFileKeywordsImplementation *ProFileKeywordsImplementation::instance()
+{
+ if (!m_instance)
+ m_instance = new ProFileKeywordsImplementation();
+ return m_instance;
+}
+
+QStringList ProFileKeywordsImplementation::variables()
+{
+ return m_variables;
+}
+
+QStringList ProFileKeywordsImplementation::functions()
+{
+ return m_functions;
+}
+
+bool ProFileKeywordsImplementation::isVariable(const QString &word)
+{
+ return m_variables.contains(word);
+}
+
+bool ProFileKeywordsImplementation::isFunction(const QString &word)
+{
+ return m_functions.contains(word);
+}
+
+ProFileKeywordsImplementation::ProFileKeywordsImplementation()
+{
+ for (uint i = 0; i < sizeof variableKeywords / sizeof variableKeywords[0] - 1; i++)
+ m_variables.append(QLatin1String(variableKeywords[i]));
+ for (uint i = 0; i < sizeof functionKeywords / sizeof functionKeywords[0] - 1; i++)
+ m_functions.append(QLatin1String(functionKeywords[i]));
+}
+
+ProFileKeywords::ProFileKeywords()
+{
+}
+
+QStringList ProFileKeywords::variables()
+{
+ return ProFileKeywordsImplementation::instance()->variables();
+}
+
+QStringList ProFileKeywords::functions()
+{
+ return ProFileKeywordsImplementation::instance()->functions();
+}
+
+bool ProFileKeywords::isVariable(const QString &word)
+{
+ return ProFileKeywordsImplementation::instance()->isVariable(word);
+}
+
+bool ProFileKeywords::isFunction(const QString &word)
+{
+ return ProFileKeywordsImplementation::instance()->isFunction(word);
+}
diff --git a/src/plugins/qt4projectmanager/profilekeywords.h b/src/plugins/qt4projectmanager/profilekeywords.h
new file mode 100644
index 0000000000..411d98d348
--- /dev/null
+++ b/src/plugins/qt4projectmanager/profilekeywords.h
@@ -0,0 +1,24 @@
+#ifndef PROFILEKEYWORDS_H
+#define PROFILEKEYWORDS_H
+
+#include <QtCore/QStringList>
+
+namespace Qt4ProjectManager {
+
+namespace Internal {
+
+class ProFileKeywords
+{
+public:
+ static QStringList variables();
+ static QStringList functions();
+ static bool isVariable(const QString &word);
+ static bool isFunction(const QString &word);
+private:
+ ProFileKeywords();
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // PROFILEKEYWORDS_H
diff --git a/src/plugins/qt4projectmanager/qmakeparser.cpp b/src/plugins/qt4projectmanager/qmakeparser.cpp
index 339b9227fd..22b602bf4b 100644
--- a/src/plugins/qt4projectmanager/qmakeparser.cpp
+++ b/src/plugins/qt4projectmanager/qmakeparser.cpp
@@ -37,6 +37,7 @@
#include <projectexplorer/taskwindow.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <utils/qtcassert.h>
+#include <QDir>
using namespace Qt4ProjectManager;
using namespace Qt4ProjectManager::Internal;
@@ -45,6 +46,9 @@ using ProjectExplorer::Task;
QMakeParser::QMakeParser()
{
setObjectName(QLatin1String("QMakeParser"));
+
+ m_error.setPattern("^(.+):(\\d+):\\s(.+)$");
+ m_error.setMinimal(true);
}
void QMakeParser::stdError(const QString &line)
@@ -59,5 +63,127 @@ void QMakeParser::stdError(const QString &line)
ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
return;
}
+ if (lne.startsWith(QLatin1String("Project WARNING:"))) {
+ const QString description = lne.mid(17);
+ emit addTask(Task(Task::Warning,
+ description,
+ QString() /* filename */,
+ -1 /* linenumber */,
+ ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
+ return;
+ }
+ if (m_error.indexIn(lne) > -1) {
+ QString fileName = QDir::fromNativeSeparators(m_error.cap(1));
+ Task::TaskType type = Task::Error;
+ if (fileName.startsWith("WARNING: ")) {
+ type = Task::Warning;
+ fileName = fileName.mid(9);
+ } else if (fileName.startsWith("ERROR: ")) {
+ fileName = fileName.mid(7);
+ }
+ emit addTask(Task(type,
+ m_error.cap(3) /* description */,
+ fileName,
+ m_error.cap(2).toInt() /* line */,
+ ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
+ return;
+ }
IOutputParser::stdError(line);
}
+
+
+// Unit tests:
+
+#ifdef WITH_TESTS
+# include <QTest>
+
+# include "qt4projectmanagerplugin.h"
+
+# include "projectexplorer/outputparser_test.h"
+
+using namespace Qt4ProjectManager::Internal;
+using namespace ProjectExplorer;
+
+void Qt4ProjectManagerPlugin::testQmakeOutputParsers_data()
+{
+ QTest::addColumn<QString>("input");
+ QTest::addColumn<OutputParserTester::Channel>("inputChannel");
+ QTest::addColumn<QString>("childStdOutLines");
+ QTest::addColumn<QString>("childStdErrLines");
+ QTest::addColumn<QList<ProjectExplorer::Task> >("tasks");
+ QTest::addColumn<QString>("outputLines");
+
+
+ QTest::newRow("pass-through stdout")
+ << QString::fromLatin1("Sometext") << OutputParserTester::STDOUT
+ << QString::fromLatin1("Sometext") << QString()
+ << QList<ProjectExplorer::Task>()
+ << QString();
+ QTest::newRow("pass-through stderr")
+ << QString::fromLatin1("Sometext") << OutputParserTester::STDERR
+ << QString() << QString::fromLatin1("Sometext")
+ << QList<ProjectExplorer::Task>()
+ << QString();
+
+ QTest::newRow("qMake error")
+ << QString::fromLatin1("Project ERROR: undefined file")
+ << OutputParserTester::STDERR
+ << QString() << QString()
+ << (QList<ProjectExplorer::Task>()
+ << Task(Task::Error,
+ QLatin1String("undefined file"),
+ QString(), -1,
+ ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM))
+ << QString();
+
+ QTest::newRow("qMake Parse Error")
+ << QString::fromLatin1("e:\\project.pro:14: Parse Error ('sth odd')")
+ << OutputParserTester::STDERR
+ << QString() << QString()
+ << (QList<ProjectExplorer::Task>()
+ << Task(Task::Error,
+ QLatin1String("Parse Error ('sth odd')"),
+ QDir::fromNativeSeparators(QLatin1String("e:\\project.pro")),
+ 14,
+ ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM))
+ << QString();
+
+ QTest::newRow("qMake warning")
+ << QString::fromLatin1("Project WARNING: bearer module might require ReadUserData capability")
+ << OutputParserTester::STDERR
+ << QString() << QString()
+ << (QList<ProjectExplorer::Task>()
+ << Task(Task::Warning,
+ QLatin1String("bearer module might require ReadUserData capability"),
+ QString(), -1,
+ ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM))
+ << QString();
+
+ QTest::newRow("qMake warning with location")
+ << QString::fromLatin1("WARNING: e:\\NokiaQtSDK\\Simulator\\Qt\\msvc2008\\lib\\qtmaind.prl:1: Unescaped backslashes are deprecated.")
+ << OutputParserTester::STDERR
+ << QString() << QString()
+ << (QList<ProjectExplorer::Task>()
+ << Task(Task::Warning,
+ QLatin1String("Unescaped backslashes are deprecated."),
+ QLatin1String("e:/NokiaQtSDK/Simulator/Qt/msvc2008/lib/qtmaind.prl"), 1,
+ ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM))
+ << QString();
+}
+
+void Qt4ProjectManagerPlugin::testQmakeOutputParsers()
+{
+ OutputParserTester testbench;
+ testbench.appendOutputParser(new QMakeParser);
+ QFETCH(QString, input);
+ QFETCH(OutputParserTester::Channel, inputChannel);
+ QFETCH(QList<Task>, tasks);
+ QFETCH(QString, childStdOutLines);
+ QFETCH(QString, childStdErrLines);
+ QFETCH(QString, outputLines);
+
+ testbench.testParsing(input, inputChannel,
+ tasks, childStdOutLines, childStdErrLines,
+ outputLines);
+}
+#endif
diff --git a/src/plugins/qt4projectmanager/qmakeparser.h b/src/plugins/qt4projectmanager/qmakeparser.h
index ecfe0d8eef..b72ed98076 100644
--- a/src/plugins/qt4projectmanager/qmakeparser.h
+++ b/src/plugins/qt4projectmanager/qmakeparser.h
@@ -36,6 +36,8 @@
#include <projectexplorer/ioutputparser.h>
+#include <QtCore/QRegExp>
+
namespace Qt4ProjectManager {
namespace Internal {
@@ -46,6 +48,9 @@ class QMakeParser : public ProjectExplorer::IOutputParser
public:
QMakeParser();
virtual void stdError(const QString &line);
+
+private:
+ QRegExp m_error;
};
} // namesapce Internal
diff --git a/src/plugins/qt4projectmanager/qmakestep.cpp b/src/plugins/qt4projectmanager/qmakestep.cpp
index 5167f77c0c..c88ac22710 100644
--- a/src/plugins/qt4projectmanager/qmakestep.cpp
+++ b/src/plugins/qt4projectmanager/qmakestep.cpp
@@ -34,6 +34,7 @@
#include "qmakestep.h"
#include "projectexplorer/projectexplorerconstants.h"
+#include <proparser/profileevaluator.h>
#include "qmakeparser.h"
#include "qt4buildconfiguration.h"
#include "qt4project.h"
@@ -46,6 +47,7 @@
#include <coreplugin/icore.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <QtCore/QDir>
#include <QtCore/QFile>
@@ -105,29 +107,34 @@ Qt4BuildConfiguration *QMakeStep::qt4BuildConfiguration() const
/// config arguemnts
/// moreArguments
/// user arguments
-QStringList QMakeStep::allArguments()
+QString QMakeStep::allArguments(bool shorted)
{
- QStringList additonalArguments = m_userArgs;
+ QString additonalArguments = m_userArgs;
Qt4BuildConfiguration *bc = qt4BuildConfiguration();
QStringList arguments;
if (bc->subNodeBuild())
arguments << QDir::toNativeSeparators(bc->subNodeBuild()->path());
+ else if (shorted)
+ arguments << QDir::toNativeSeparators(QFileInfo(
+ buildConfiguration()->target()->project()->file()->fileName()).fileName());
else
arguments << QDir::toNativeSeparators(buildConfiguration()->target()->project()->file()->fileName());
arguments << "-r";
- if (!additonalArguments.contains("-spec"))
- arguments << "-spec" << bc->qtVersion()->mkspec();
+ for (Utils::QtcProcess::ArgIterator ait(&additonalArguments); ait.next(); )
+ if (ait.value() == QLatin1String("-spec"))
+ goto haveSpec;
+ arguments << "-spec" << bc->qtVersion()->mkspec();
+ haveSpec:
// Find out what flags we pass on to qmake
arguments << bc->configCommandLineArguments();
- if (!additonalArguments.isEmpty())
- arguments << additonalArguments;
-
arguments << moreArguments();
- return arguments;
+ QString args = Utils::QtcProcess::joinArgs(arguments);
+ Utils::QtcProcess::addArgs(&args, additonalArguments);
+ return args;
}
///
@@ -140,12 +147,11 @@ QStringList QMakeStep::moreArguments()
Qt4BuildConfiguration *bc = qt4BuildConfiguration();
QStringList arguments;
#if defined(Q_OS_WIN) || defined(Q_OS_MAC)
- ToolChain::ToolChainType type = bc->toolChainType();
- if (type == ToolChain::GCC_MAEMO)
+ const ProjectExplorer::ToolChainType type = bc->toolChainType();
+ if (type == ProjectExplorer::ToolChain_GCC_MAEMO)
arguments << QLatin1String("-unix");
#endif
- if (bc->target()->id() == Constants::S60_DEVICE_TARGET_ID
- || bc->target()->id() == Constants::S60_EMULATOR_TARGET_ID) {
+ if (!bc->qtVersion()->supportsShadowBuilds()) {
// We have a target which does not allow shadow building.
// But we really don't want to have the build artefacts in the source dir
// so we try to hack around it, to make the common cases work.
@@ -169,8 +175,9 @@ bool QMakeStep::init()
Qt4BuildConfiguration *qt4bc = qt4BuildConfiguration();
const QtVersion *qtVersion = qt4bc->qtVersion();
- QStringList args = allArguments();
+ QString args = allArguments();
QString workingDirectory;
+
if (qt4bc->subNodeBuild())
workingDirectory = qt4bc->subNodeBuild()->buildDir();
else
@@ -180,10 +187,24 @@ bool QMakeStep::init()
// Check whether we need to run qmake
m_needToRunQMake = true;
- if (QDir(workingDirectory).exists(QLatin1String("Makefile"))) {
- QString qmakePath = QtVersionManager::findQMakeBinaryFromMakefile(workingDirectory);
+ QString makefile = workingDirectory;
+
+ if (qt4bc->subNodeBuild()) {
+ if (!qt4bc->subNodeBuild()->makefile().isEmpty()) {
+ makefile.append(qt4bc->subNodeBuild()->makefile());
+ } else {
+ makefile.append("/Makefile");
+ }
+ } else if (!qt4bc->makefile().isEmpty()) {
+ makefile.append(qt4bc->makefile());
+ } else {
+ makefile.append("/Makefile");
+ }
+
+ if (QFileInfo(makefile).exists()) {
+ QString qmakePath = QtVersionManager::findQMakeBinaryFromMakefile(makefile);
if (qtVersion->qmakeCommand() == qmakePath) {
- m_needToRunQMake = !qt4bc->compareToImportFrom(workingDirectory);
+ m_needToRunQMake = !qt4bc->compareToImportFrom(makefile);
}
}
@@ -193,10 +214,12 @@ bool QMakeStep::init()
}
setEnabled(m_needToRunQMake);
- setWorkingDirectory(workingDirectory);
- setCommand(program);
- setArguments(args);
- setEnvironment(qt4bc->environment());
+ ProcessParameters *pp = processParameters();
+ pp->setMacroExpander(qt4bc->macroExpander());
+ pp->setWorkingDirectory(workingDirectory);
+ pp->setCommand(program);
+ pp->setArguments(args);
+ pp->setEnvironment(qt4bc->environment());
setOutputParser(new QMakeParser);
@@ -276,7 +299,7 @@ bool QMakeStep::processSucceeded(int exitCode, QProcess::ExitStatus status)
return result;
}
-void QMakeStep::setUserArguments(const QStringList &arguments)
+void QMakeStep::setUserArguments(const QString &arguments)
{
if (m_userArgs == arguments)
return;
@@ -291,14 +314,24 @@ void QMakeStep::setUserArguments(const QStringList &arguments)
QStringList QMakeStep::parserArguments()
{
QStringList result;
- foreach (const QString &str, allArguments()) {
- if (str.contains("="))
- result << str;
+ for (Utils::QtcProcess::ConstArgIterator ait(allArguments()); ait.next(); ) {
+ const QString &arg = ait.value();
+ if (arg.contains(QLatin1Char('='))) {
+ result << arg;
+ } else {
+ for (int i = 0; i < ProFileOption::modeMapSize; ++i) {
+ // Workaround: Apple GCC does not like ProFileOption::modeMap[i], because the array's bounds are not known
+ if (QLatin1String((&ProFileOption::modeMap[0] + i)->qmakeOption) == arg) {
+ result << arg;
+ break;
+ }
+ }
+ }
}
return result;
}
-QStringList QMakeStep::userArguments()
+QString QMakeStep::userArguments()
{
return m_userArgs;
}
@@ -313,7 +346,7 @@ QVariantMap QMakeStep::toMap() const
bool QMakeStep::fromMap(const QVariantMap &map)
{
- m_userArgs = map.value(QLatin1String(QMAKE_ARGUMENTS_KEY)).toStringList();
+ m_userArgs = map.value(QLatin1String(QMAKE_ARGUMENTS_KEY)).toString();
m_forced = map.value(QLatin1String(QMAKE_FORCED_KEY), false).toBool();
return BuildStep::fromMap(map);
}
@@ -340,8 +373,7 @@ QMakeStepConfigWidget::QMakeStepConfigWidget(QMakeStep *step)
void QMakeStepConfigWidget::init()
{
- QString qmakeArgs = Utils::Environment::joinArgumentList(m_step->userArguments());
- m_ui.qmakeAdditonalArgumentsLineEdit->setText(qmakeArgs);
+ m_ui.qmakeAdditonalArgumentsLineEdit->setText(m_step->userArguments());
qmakeBuildConfigChanged();
@@ -384,8 +416,7 @@ void QMakeStepConfigWidget::userArgumentsChanged()
{
if (m_ignoreChange)
return;
- QString qmakeArgs = Utils::Environment::joinArgumentList(m_step->userArguments());
- m_ui.qmakeAdditonalArgumentsLineEdit->setText(qmakeArgs);
+ m_ui.qmakeAdditonalArgumentsLineEdit->setText(m_step->userArguments());
updateSummaryLabel();
updateEffectiveQMakeCall();
}
@@ -393,8 +424,7 @@ void QMakeStepConfigWidget::userArgumentsChanged()
void QMakeStepConfigWidget::qmakeArgumentsLineEdited()
{
m_ignoreChange = true;
- m_step->setUserArguments(
- Utils::Environment::parseCombinedArgString(m_ui.qmakeAdditonalArgumentsLineEdit->text()));
+ m_step->setUserArguments(m_ui.qmakeAdditonalArgumentsLineEdit->text());
m_ignoreChange = false;
updateSummaryLabel();
@@ -437,16 +467,11 @@ void QMakeStepConfigWidget::updateSummaryLabel()
return;
}
- QStringList args = m_step->allArguments();
// We don't want the full path to the .pro file
- const QString projectFileName = m_step->buildConfiguration()->target()->project()->file()->fileName();
- int index = args.indexOf(projectFileName);
- if (index != -1)
- args[index] = QFileInfo(projectFileName).fileName();
-
+ QString args = m_step->allArguments(true);
// And we only use the .pro filename not the full path
QString program = QFileInfo(qtVersion->qmakeCommand()).fileName();
- m_summaryText = tr("<b>qmake:</b> %1 %2").arg(program, args.join(QString(QLatin1Char(' '))));
+ m_summaryText = tr("<b>qmake:</b> %1 %2").arg(program, args);
emit updateSummary();
}
@@ -456,7 +481,7 @@ void QMakeStepConfigWidget::updateEffectiveQMakeCall()
Qt4BuildConfiguration *qt4bc = m_step->qt4BuildConfiguration();
const QtVersion *qtVersion = qt4bc->qtVersion();
QString program = QFileInfo(qtVersion->qmakeCommand()).fileName();
- m_ui.qmakeArgumentsEdit->setPlainText(program + QLatin1Char(' ') + Utils::Environment::joinArgumentList(m_step->allArguments()));
+ m_ui.qmakeArgumentsEdit->setPlainText(program + QLatin1Char(' ') + m_step->allArguments());
}
////
diff --git a/src/plugins/qt4projectmanager/qmakestep.h b/src/plugins/qt4projectmanager/qmakestep.h
index 96188af596..d844c44f87 100644
--- a/src/plugins/qt4projectmanager/qmakestep.h
+++ b/src/plugins/qt4projectmanager/qmakestep.h
@@ -48,9 +48,9 @@ class Project;
namespace Qt4ProjectManager {
class Qt4Project;
+class Qt4BuildConfiguration;
namespace Internal {
-class Qt4BuildConfiguration;
class QMakeStepFactory : public ProjectExplorer::IBuildStepFactory
{
@@ -81,7 +81,7 @@ public:
explicit QMakeStep(ProjectExplorer::BuildStepList *parent);
virtual ~QMakeStep();
- Internal::Qt4BuildConfiguration *qt4BuildConfiguration() const;
+ Qt4BuildConfiguration *qt4BuildConfiguration() const;
virtual bool init();
virtual void run(QFutureInterface<bool> &);
virtual ProjectExplorer::BuildStepConfigWidget *createConfigWidget();
@@ -90,11 +90,11 @@ public:
bool forced();
// TODO clean up those functions
- QStringList allArguments();
+ QString allArguments(bool shorted = false);
QStringList moreArguments();
QStringList parserArguments();
- QStringList userArguments();
- void setUserArguments(const QStringList &arguments);
+ QString userArguments();
+ void setUserArguments(const QString &arguments);
QVariantMap toMap() const;
@@ -116,7 +116,7 @@ private:
QStringList m_lastEnv;
bool m_forced;
bool m_needToRunQMake; // set in init(), read in run()
- QStringList m_userArgs;
+ QString m_userArgs;
bool m_scriptTemplate;
QList<ProjectExplorer::Task> m_tasks;
};
diff --git a/src/plugins/qt4projectmanager/qmldumptool.cpp b/src/plugins/qt4projectmanager/qmldumptool.cpp
index 42efc8901b..c16a15e672 100644
--- a/src/plugins/qt4projectmanager/qmldumptool.cpp
+++ b/src/plugins/qt4projectmanager/qmldumptool.cpp
@@ -56,7 +56,7 @@ using namespace Qt4ProjectManager;
class QmlDumpBuildTask;
typedef QHash<int, QmlDumpBuildTask *> QmlDumpByVersion;
-Q_GLOBAL_STATIC(QmlDumpByVersion, qmlDumpBuilds);
+Q_GLOBAL_STATIC(QmlDumpByVersion, qmlDumpBuilds)
// A task suitable to be run by QtConcurrent to build qmldump.
class QmlDumpBuildTask : public QObject {
diff --git a/src/plugins/qt4projectmanager/qmlobservertool.cpp b/src/plugins/qt4projectmanager/qmlobservertool.cpp
index 63bcd42d19..3c37fa3f49 100644
--- a/src/plugins/qt4projectmanager/qmlobservertool.cpp
+++ b/src/plugins/qt4projectmanager/qmlobservertool.cpp
@@ -128,83 +128,24 @@ QString QmlObserverTool::copy(const QString &qtInstallData, QString *errorMessag
{
const QStringList directories = QmlObserverTool::installDirectories(qtInstallData);
- QStringList files;
- files << QLatin1String("main.cpp") << QLatin1String("qmlobserver.pro")
- << QLatin1String("deviceorientation.cpp") << QLatin1String("deviceorientation.h")
- << QLatin1String("deviceorientation_maemo5.cpp") << QLatin1String("Info_mac.plist")
- << QLatin1String("loggerwidget.cpp") << QLatin1String("loggerwidget.h")
- << QLatin1String("proxysettings.cpp") << QLatin1String("proxysettings.h")
- << QLatin1String("proxysettings.ui") << QLatin1String("proxysettings_maemo5.ui")
- << QLatin1String("qdeclarativetester.cpp") << QLatin1String("qdeclarativetester.h")
- << QLatin1String("qml.icns") << QLatin1String("qml.pri")
- << QLatin1String("qmlruntime.cpp") << QLatin1String("qmlruntime.h")
- << QLatin1String("qmlruntime.qrc") << QLatin1String("recopts.ui")
- << QLatin1String("recopts_maemo5.ui")
- << QLatin1String("texteditautoresizer_maemo5.h")
- << QLatin1String("content/Browser.qml") << QLatin1String("content/images/folder.png")
- << QLatin1String("content/images/titlebar.png") << QLatin1String("content/images/titlebar.sci")
- << QLatin1String("content/images/up.png")
- << QLatin1String("LICENSE.LGPL") << QLatin1String("LGPL_EXCEPTION.TXT");
-
- QStringList debuggerLibFiles;
- debuggerLibFiles << QLatin1String("jsdebuggeragent.cpp")
- << QLatin1String("qdeclarativeobserverservice.cpp") << QLatin1String("qdeclarativeviewobserver.cpp")
- << QLatin1String("qdeclarativeviewobserver_p.h") << QLatin1String("qmljsdebugger.pri")
- << QLatin1String("qmljsdebugger.pro") << QLatin1String("qmljsdebugger-lib.pri")
- << QLatin1String("include/jsdebuggeragent.h") << QLatin1String("include/qdeclarativeobserverservice.h")
- << QLatin1String("include/qdeclarativeviewobserver.h") << QLatin1String("include/qmljsdebugger_global.h")
- << QLatin1String("include/qmlobserverconstants.h")
- << QLatin1String("include/qt_private/qdeclarativedebughelper_p.h")
- << QLatin1String("include/qt_private/qdeclarativedebugservice_p.h");
-
- QStringList debuggerLibEditorFiles;
- debuggerLibEditorFiles << QLatin1String("abstractformeditortool.cpp") << QLatin1String("abstractformeditortool.h")
- << QLatin1String("boundingrecthighlighter.cpp") << QLatin1String("boundingrecthighlighter.h")
- << QLatin1String("colorpickertool.cpp") << QLatin1String("colorpickertool.h")
- << QLatin1String("editor.pri") << QLatin1String("editor.qrc")
- << QLatin1String("layeritem.cpp") << QLatin1String("layeritem.h")
- << QLatin1String("qmltoolbar.cpp") << QLatin1String("qmltoolbar.h")
- << QLatin1String("rubberbandselectionmanipulator.cpp")
- << QLatin1String("rubberbandselectionmanipulator.h") << QLatin1String("selectionindicator.cpp")
- << QLatin1String("selectionindicator.h") << QLatin1String("selectionrectangle.cpp")
- << QLatin1String("selectionrectangle.h") << QLatin1String("selectiontool.cpp")
- << QLatin1String("selectiontool.h") << QLatin1String("singleselectionmanipulator.cpp")
- << QLatin1String("singleselectionmanipulator.h") << QLatin1String("subcomponenteditortool.cpp")
- << QLatin1String("subcomponenteditortool.h") << QLatin1String("subcomponentmasklayeritem.cpp")
- << QLatin1String("subcomponentmasklayeritem.h") << QLatin1String("toolbarcolorbox.cpp")
- << QLatin1String("toolbarcolorbox.h") << QLatin1String("zoomtool.cpp")
- << QLatin1String("zoomtool.h") << QLatin1String("images/color-picker.png")
- << QLatin1String("images/color-picker-24.png") << QLatin1String("images/color-picker-hicontrast.png")
- << QLatin1String("images/from-qml.png") << QLatin1String("images/from-qml-24.png")
- << QLatin1String("images/observermode.png") << QLatin1String("images/observermode-24.png")
- << QLatin1String("images/pause.png") << QLatin1String("images/pause-24.png")
- << QLatin1String("images/play.png") << QLatin1String("images/play-24.png")
- << QLatin1String("images/reload.png") << QLatin1String("images/resize_handle.png")
- << QLatin1String("images/select.png") << QLatin1String("images/select-24.png")
- << QLatin1String("images/select-marquee.png") << QLatin1String("images/select-marquee-24.png")
- << QLatin1String("images/to-qml.png") << QLatin1String("images/to-qml-24.png")
- << QLatin1String("images/zoom.png") << QLatin1String("images/zoom-24.png");
-
QString sourcePath = Core::ICore::instance()->resourcePath() + QLatin1String("/qml/qmlobserver/");
QString libSourcePath = Core::ICore::instance()->resourcePath() + QLatin1String("/qml/qmljsdebugger/");
- QString libEditorSourcePath = Core::ICore::instance()->resourcePath() + QLatin1String("/qml/qmljsdebugger/editor/");
+
+ QStringList observerFiles = recursiveFileList(QDir(sourcePath));
+ QStringList qmljsDebuggerFiles = recursiveFileList(QDir(libSourcePath));
// Try to find a writeable directory.
foreach(const QString &directory, directories) {
- if (!mkpath(directory + QLatin1String("/content/images"), errorMessage)
- || !mkpath(directory + QLatin1String("/images"), errorMessage)
- || !mkpath(directory + QLatin1String("/qmljsdebugger/editor/images"), errorMessage)
- || !mkpath(directory + QLatin1String("/qmljsdebugger/include"), errorMessage)
- || !mkpath(directory + QLatin1String("/qmljsdebugger/include/qt_private"), errorMessage))
- {
+ if (!mkpath(directory, errorMessage)) {
continue;
} else {
errorMessage->clear();
}
- if (copyFiles(sourcePath, files, directory, errorMessage)
- && copyFiles(libSourcePath, debuggerLibFiles, directory + QLatin1String("/qmljsdebugger/"), errorMessage)
- && copyFiles(libEditorSourcePath, debuggerLibEditorFiles, directory + QLatin1String("/qmljsdebugger/editor/"), errorMessage))
+ qDebug() << observerFiles;
+ if (copyFiles(sourcePath, observerFiles, directory, errorMessage)
+ && copyFiles(libSourcePath, qmljsDebuggerFiles,
+ directory + QLatin1String("/qmljsdebugger/"), errorMessage))
{
errorMessage->clear();
return directory;
@@ -216,6 +157,24 @@ QString QmlObserverTool::copy(const QString &qtInstallData, QString *errorMessag
return QString();
}
+QStringList QmlObserverTool::recursiveFileList(const QDir &dir, const QString &prefix)
+{
+ QStringList files;
+
+ QString _prefix = prefix;
+ if (!_prefix.isEmpty() && !_prefix.endsWith('/')) {
+ _prefix = _prefix + '/';
+ }
+ foreach (const QString &fileName, dir.entryList(QDir::Files)) {
+ files << _prefix + fileName;
+ }
+
+ foreach (const QString &subDir, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) {
+ files += recursiveFileList(QDir(dir.absoluteFilePath(subDir)), _prefix + subDir);
+ }
+ return files;
+}
+
QStringList QmlObserverTool::installDirectories(const QString &qtInstallData)
{
const QChar slash = QLatin1Char('/');
diff --git a/src/plugins/qt4projectmanager/qmlobservertool.h b/src/plugins/qt4projectmanager/qmlobservertool.h
index 06dec0cec6..5f35e3843d 100644
--- a/src/plugins/qt4projectmanager/qmlobservertool.h
+++ b/src/plugins/qt4projectmanager/qmlobservertool.h
@@ -37,6 +37,8 @@
#include <utils/buildablehelperlibrary.h>
#include "qt4projectmanager_global.h"
+QT_FORWARD_DECLARE_CLASS(QDir)
+
namespace Utils {
class Environment;
}
@@ -67,6 +69,7 @@ public:
static QString copy(const QString &qtInstallData, QString *errorMessage);
private:
+ static QStringList recursiveFileList(const QDir &dir, const QString &prefix = QString());
static QStringList installDirectories(const QString &qtInstallData);
};
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoconfigtestdialog.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemoconfigtestdialog.cpp
index 6a455cd84f..047e9b2606 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemoconfigtestdialog.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoconfigtestdialog.cpp
@@ -37,9 +37,9 @@
#include "maemodeviceconfigurations.h"
#include "maemoglobal.h"
+#include "maemousedportsgatherer.h"
-#include <coreplugin/ssh/sshconnection.h>
-#include <coreplugin/ssh/sshremoteprocess.h>
+#include <coreplugin/ssh/sshremoteprocessrunner.h>
#include <QtGui/QPalette>
#include <QtGui/QPushButton>
@@ -53,6 +53,7 @@ MaemoConfigTestDialog::MaemoConfigTestDialog(const MaemoDeviceConfig &config, QW
: QDialog(parent)
, m_ui(new Ui_MaemoConfigTestDialog)
, m_config(config)
+ , m_portsGatherer(new MaemoUsedPortsGatherer(this))
{
setAttribute(Qt::WA_DeleteOnClose);
@@ -60,6 +61,10 @@ MaemoConfigTestDialog::MaemoConfigTestDialog(const MaemoDeviceConfig &config, QW
m_closeButton = m_ui->buttonBox->button(QDialogButtonBox::Close);
connect(m_closeButton, SIGNAL(clicked()), SLOT(stopConfigTest()));
+ connect(m_portsGatherer, SIGNAL(error(QString)),
+ SLOT(handlePortListFailure(QString)));
+ connect(m_portsGatherer, SIGNAL(portListReady()),
+ SLOT(handlePortListReady()));
startConfigTest();
}
@@ -71,63 +76,60 @@ MaemoConfigTestDialog::~MaemoConfigTestDialog()
void MaemoConfigTestDialog::startConfigTest()
{
- if (m_infoProcess)
+ if (m_testProcessRunner)
return;
+ m_currentTest = GeneralTest;
m_ui->testResultEdit->setPlainText(tr("Testing configuration..."));
m_closeButton->setText(tr("Stop Test"));
- m_connection = SshConnection::create();
- connect(m_connection.data(), SIGNAL(connected()), this,
- SLOT(handleConnected()));
- connect(m_connection.data(), SIGNAL(error(Core::SshError)), this,
- SLOT(handleConnectionError()));
- m_connection->connectToHost(m_config.server);
-}
-
-void MaemoConfigTestDialog::handleConnected()
-{
- if (!m_connection)
- return;
+ m_testProcessRunner = SshRemoteProcessRunner::create(m_config.server);
+ connect(m_testProcessRunner.data(), SIGNAL(connectionError(Core::SshError)),
+ this, SLOT(handleConnectionError()));
+ connect(m_testProcessRunner.data(), SIGNAL(processClosed(int)), this,
+ SLOT(handleTestProcessFinished(int)));
+ connect(m_testProcessRunner.data(),
+ SIGNAL(processOutputAvailable(QByteArray)), this,
+ SLOT(processSshOutput(QByteArray)));
QLatin1String sysInfoCmd("uname -rsm");
QLatin1String qtInfoCmd("dpkg-query -W -f '${Package} ${Version} ${Status}\n' 'libqt*' "
"|grep ' installed$'");
QString command(sysInfoCmd + " && " + qtInfoCmd);
- m_infoProcess = m_connection->createRemoteProcess(command.toUtf8());
- connect(m_infoProcess.data(), SIGNAL(closed(int)), this,
- SLOT(handleInfoProcessFinished(int)));
- connect(m_infoProcess.data(), SIGNAL(outputAvailable(QByteArray)), this,
- SLOT(processSshOutput(QByteArray)));
- m_infoProcess->start();
+ m_testProcessRunner->run(command.toUtf8());
}
void MaemoConfigTestDialog::handleConnectionError()
{
- if (!m_connection)
+ if (!m_testProcessRunner)
return;
QString output = tr("Could not connect to host: %1")
- .arg(m_connection->errorString());
+ .arg(m_testProcessRunner->connection()->errorString());
if (m_config.type == MaemoDeviceConfig::Simulator)
output += tr("\nDid you start Qemu?");
m_ui->testResultEdit->setPlainText(output);
stopConfigTest();
}
-void MaemoConfigTestDialog::handleInfoProcessFinished(int exitStatus)
+void MaemoConfigTestDialog::handleTestProcessFinished(int exitStatus)
{
- if (!m_connection)
+ if (!m_testProcessRunner)
return;
Q_ASSERT(exitStatus == SshRemoteProcess::FailedToStart
|| exitStatus == SshRemoteProcess::KilledBySignal
|| exitStatus == SshRemoteProcess::ExitedNormally);
- if (!m_infoProcess)
- return;
+ if (m_currentTest == GeneralTest)
+ handleGeneralTestResult(exitStatus);
+ else
+ handleMadDeveloperTestResult(exitStatus);
+}
+void MaemoConfigTestDialog::handleGeneralTestResult(int exitStatus)
+{
if (exitStatus != SshRemoteProcess::ExitedNormally
- || m_infoProcess->exitCode() != 0) {
+ || m_testProcessRunner->process()->exitCode() != 0) {
m_ui->testResultEdit->setPlainText(tr("Remote process failed: %1")
- .arg(m_infoProcess->errorString()));
+ .arg(m_testProcessRunner->process()->errorString()));
} else {
const QString &output = parseTestOutput();
if (!m_qtVersionOk) {
@@ -137,30 +139,55 @@ void MaemoConfigTestDialog::handleInfoProcessFinished(int exitStatus)
m_ui->testResultEdit->setPlainText(output);
}
+ m_currentTest = MadDeveloperTest;
+ disconnect(m_testProcessRunner.data(),
+ SIGNAL(processOutputAvailable(QByteArray)), this,
+ SLOT(processSshOutput(QByteArray)));
const QByteArray command = "test -x " + MaemoGlobal::remoteSudo().toUtf8();
- m_madDeveloperTestProcess = m_connection->createRemoteProcess(command);
- connect(m_madDeveloperTestProcess.data(), SIGNAL(closed(int)), this,
- SLOT(handleMadDeveloperTestProcessFinished(int)));
- m_madDeveloperTestProcess->start();
+ m_testProcessRunner->run(command);
}
-void MaemoConfigTestDialog::handleMadDeveloperTestProcessFinished(int exitStatus)
+void MaemoConfigTestDialog::handleMadDeveloperTestResult(int exitStatus)
{
- if (!m_connection)
- return;
-
- Q_ASSERT(exitStatus == SshRemoteProcess::FailedToStart
- || exitStatus == SshRemoteProcess::KilledBySignal
- || exitStatus == SshRemoteProcess::ExitedNormally);
-
if (exitStatus != SshRemoteProcess::ExitedNormally) {
m_ui->testResultEdit->setPlainText(tr("Remote process failed: %1")
- .arg(m_madDeveloperTestProcess->errorString()));
- } else if (m_madDeveloperTestProcess->exitCode() != 0) {
+ .arg(m_testProcessRunner->process()->errorString()));
+ } else if (m_testProcessRunner->process()->exitCode() != 0) {
m_ui->errorLabel->setText(m_ui->errorLabel->text()
+ QLatin1String("<br>") + tr("Mad Developer is not installed.<br>"
"You will not be able to deploy to this device."));
}
+ if (m_config.freePorts().hasMore())
+ m_portsGatherer->start(m_testProcessRunner->connection(),
+ m_config.freePorts());
+ else
+ finish();
+}
+
+void MaemoConfigTestDialog::handlePortListFailure(const QString &errMsg)
+{
+ m_ui->testResultEdit->appendPlainText(tr("Error retrieving list of used ports: %1")
+ .arg(errMsg));
+ finish();
+}
+
+void MaemoConfigTestDialog::handlePortListReady()
+{
+ const QList<int> &usedPorts = m_portsGatherer->usedPorts();
+ QString output;
+ if (usedPorts.isEmpty()) {
+ output = tr("All specified ports are available.");
+ } else {
+ output = tr("The following supposedly free ports are being used on the device:");
+ foreach (const int port, usedPorts)
+ output += QLatin1Char(' ') + QString::number(port);
+ }
+ m_ui->testResultEdit->appendPlainText(output);
+ finish();
+}
+
+void MaemoConfigTestDialog::finish()
+{
if (m_ui->errorLabel->text().isEmpty()) {
QPalette palette = m_ui->errorLabel->palette();
palette.setColor(m_ui->errorLabel->foregroundRole(),
@@ -173,13 +200,10 @@ void MaemoConfigTestDialog::handleMadDeveloperTestProcessFinished(int exitStatus
void MaemoConfigTestDialog::stopConfigTest()
{
- if (m_infoProcess)
- disconnect(m_infoProcess.data(), 0, this, 0);
- if (m_madDeveloperTestProcess)
- disconnect(m_madDeveloperTestProcess.data(), 0, this, 0);
- if (m_connection)
- disconnect(m_connection.data(), 0, this, 0);
-
+ if (m_testProcessRunner) {
+ disconnect(m_testProcessRunner.data(), 0, this, 0);
+ m_testProcessRunner = SshRemoteProcessRunner::Ptr();
+ }
m_deviceTestOutput.clear();
m_closeButton->setText(tr("Close"));
}
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoconfigtestdialog.h b/src/plugins/qt4projectmanager/qt-maemo/maemoconfigtestdialog.h
index 3a1f0f2306..5089266a4a 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemoconfigtestdialog.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoconfigtestdialog.h
@@ -44,14 +44,14 @@ class Ui_MaemoConfigTestDialog;
QT_END_NAMESPACE
namespace Core {
- class SshConnection;
- class SshRemoteProcess;
+ class SshRemoteProcessRunner;
} // namespace Core
namespace Qt4ProjectManager {
namespace Internal {
class MaemoDeviceConfig;
+class MaemoUsedPortsGatherer;
/**
* A dialog that runs a test of a device configuration.
@@ -66,24 +66,29 @@ public:
private slots:
void stopConfigTest();
void processSshOutput(const QByteArray &output);
- void handleConnected();
void handleConnectionError();
- void handleInfoProcessFinished(int exitStatus);
- void handleMadDeveloperTestProcessFinished(int exitStatus);
+ void handleTestProcessFinished(int exitStatus);
+ void handlePortListReady();
+ void handlePortListFailure(const QString &errMsg);
private:
void startConfigTest();
QString parseTestOutput();
+ void handleGeneralTestResult(int exitStatus);
+ void handleMadDeveloperTestResult(int exitStatus);
+ void finish();
Ui_MaemoConfigTestDialog *m_ui;
QPushButton *m_closeButton;
const MaemoDeviceConfig &m_config;
- QSharedPointer<Core::SshConnection> m_connection;
- QSharedPointer<Core::SshRemoteProcess> m_infoProcess;
- QSharedPointer<Core::SshRemoteProcess> m_madDeveloperTestProcess;
+ QSharedPointer<Core::SshRemoteProcessRunner> m_testProcessRunner;
QString m_deviceTestOutput;
bool m_qtVersionOk;
+ MaemoUsedPortsGatherer *const m_portsGatherer;
+
+ enum DeviceTest { GeneralTest, MadDeveloperTest };
+ DeviceTest m_currentTest;
};
} // namespace Internal
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoconfigtestdialog.ui b/src/plugins/qt4projectmanager/qt-maemo/maemoconfigtestdialog.ui
index e91549702c..9afda1b87f 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemoconfigtestdialog.ui
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoconfigtestdialog.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>661</width>
- <height>324</height>
+ <width>684</width>
+ <height>544</height>
</rect>
</property>
<property name="windowTitle">
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoconstants.h b/src/plugins/qt4projectmanager/qt-maemo/maemoconstants.h
index a426269f61..1e62e7fe0d 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemoconstants.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoconstants.h
@@ -39,14 +39,6 @@
namespace Qt4ProjectManager {
namespace Internal {
-enum QemuStatus {
- QemuStarting,
- QemuFailedToStart,
- QemuFinished,
- QemuCrashed,
- QemuUserReason
-};
-
#define PREFIX "Qt4ProjectManager.MaemoRunConfiguration"
#ifdef Q_OS_WIN32
@@ -74,6 +66,13 @@ static const QLatin1String UserEnvironmentChangesKey(PREFIX ".UserEnvironmentCha
static const QLatin1String UseRemoteGdbKey(PREFIX ".UseRemoteGdb");
} // namespace Internal
+
+namespace Constants {
+const char * const MAEMO_SETTINGS_CATEGORY = "X.Maemo";
+const char * const MAEMO_SETTINGS_TR_CATEGORY = QT_TRANSLATE_NOOP("Qt4ProjectManager", "Maemo");
+const char * const MAEMO_SETTINGS_CATEGORY_ICON = ":/projectexplorer/images/MaemoDevice.png";
+}
+
} // namespace Qt4ProjectManager
#endif // MAEMOCONSTANTS_H
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodebugsupport.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemodebugsupport.cpp
index abac864fa0..12b0ba8bd2 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemodebugsupport.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodebugsupport.cpp
@@ -37,22 +37,23 @@
#include "maemodeployables.h"
#include "maemodeploystep.h"
#include "maemoglobal.h"
-#include "maemorunconfiguration.h"
#include "maemosshrunner.h"
+#include "maemousedportsgatherer.h"
#include <coreplugin/ssh/sftpchannel.h>
#include <debugger/debuggerplugin.h>
#include <debugger/debuggerrunner.h>
#include <debugger/debuggerengine.h>
-#include <projectexplorer/toolchain.h>
+#include <projectexplorer/toolchaintype.h>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
+#define ASSERT_STATE(state) ASSERT_STATE_GENERIC(State, state, m_state)
+
using namespace Core;
using namespace Debugger;
-using namespace Debugger::Internal;
using namespace ProjectExplorer;
namespace Qt4ProjectManager {
@@ -67,12 +68,12 @@ RunControl *MaemoDebugSupport::createDebugRunControl(MaemoRunConfiguration *runC
= runConfig->debuggingType();
if (debuggingType != MaemoRunConfiguration::DebugCppOnly) {
params.qmlServerAddress = runConfig->deviceConfig().server.host;
- params.qmlServerPort = qmlServerPort(runConfig);
+ params.qmlServerPort = -1;
}
if (debuggingType != MaemoRunConfiguration::DebugQmlOnly) {
params.processArgs = runConfig->arguments();
params.sysRoot = runConfig->sysRoot();
- params.toolChainType = ToolChain::GCC_MAEMO;
+ params.toolChainType = ProjectExplorer::ToolChain_GCC_MAEMO;
params.dumperLibrary = runConfig->dumperLib();
params.remoteDumperLib = uploadDir(devConf).toUtf8() + '/'
+ QFileInfo(runConfig->dumperLib()).fileName().toUtf8();
@@ -81,10 +82,12 @@ RunControl *MaemoDebugSupport::createDebugRunControl(MaemoRunConfiguration *runC
params.executable = runConfig->remoteExecutableFilePath();
params.debuggerCommand
= MaemoGlobal::remoteCommandPrefix(runConfig->remoteExecutableFilePath())
- + environment(runConfig) + QLatin1String(" /usr/bin/gdb");
+ + environment(runConfig->debuggingType(), runConfig->userEnvironmentChanges())
+ + QLatin1String(" /usr/bin/gdb");
params.connParams = devConf.server;
params.localMountDir = runConfig->localDirToMountForRemoteGdb();
- params.remoteMountPoint = MaemoGlobal::remoteProjectSourcesMountPoint();
+ params.remoteMountPoint
+ = runConfig->remoteProjectSourcesMountPoint();
const QString execDirAbs
= QDir::fromNativeSeparators(QFileInfo(runConfig->localExecutableFilePath()).path());
const QString execDirRel
@@ -95,10 +98,10 @@ RunControl *MaemoDebugSupport::createDebugRunControl(MaemoRunConfiguration *runC
params.startMode = AttachToRemote;
params.executable = runConfig->localExecutableFilePath();
params.debuggerCommand = runConfig->gdbCmd();
- params.remoteChannel = devConf.server.host + QLatin1Char(':')
- + QString::number(gdbServerPort(runConfig));
+ params.remoteChannel = devConf.server.host + QLatin1String(":-1");
params.useServerStartScript = true;
params.remoteArchitecture = QLatin1String("arm");
+ params.gnuTarget = QLatin1String("arm-none-linux-gnueabi");
}
} else {
params.startMode = AttachToRemote;
@@ -113,11 +116,12 @@ RunControl *MaemoDebugSupport::createDebugRunControl(MaemoRunConfiguration *runC
MaemoDebugSupport::MaemoDebugSupport(MaemoRunConfiguration *runConfig,
DebuggerRunControl *runControl)
: QObject(runControl), m_runControl(runControl), m_runConfig(runConfig),
- m_deviceConfig(m_runConfig->deviceConfig()),
- m_runner(new MaemoSshRunner(this, m_runConfig, true)),
- m_qmlOnlyDebugging(m_runConfig->debuggingType() == MaemoRunConfiguration::DebugQmlOnly)
+ m_runner(new MaemoSshRunner(this, runConfig, true)),
+ m_debuggingType(runConfig->debuggingType()),
+ m_dumperLib(runConfig->dumperLib()),
+ m_state(Inactive), m_gdbServerPort(-1), m_qmlPort(-1)
{
- connect(m_runControl, SIGNAL(engineRequestSetup()), this,
+ connect(m_runControl->engine(), SIGNAL(requestRemoteSetup()), this,
SLOT(handleAdapterSetupRequested()));
connect(m_runControl, SIGNAL(finished()), this,
SLOT(handleDebuggingFinished()));
@@ -125,17 +129,14 @@ MaemoDebugSupport::MaemoDebugSupport(MaemoRunConfiguration *runConfig,
MaemoDebugSupport::~MaemoDebugSupport()
{
- stopSsh();
+ setState(Inactive);
}
void MaemoDebugSupport::handleAdapterSetupRequested()
{
- if (!m_deviceConfig.isValid()) {
- handleAdapterSetupFailed(tr("No device configuration set for run configuration."));
- return;
- }
- m_adapterStarted = false;
- m_stopped = false;
+ ASSERT_STATE(Inactive);
+
+ setState(StartingRunner);
m_runControl->showMessage(tr("Preparing remote side ..."), AppStuff);
disconnect(m_runner, 0, this, 0);
connect(m_runner, SIGNAL(error(QString)), this,
@@ -149,19 +150,36 @@ void MaemoDebugSupport::handleAdapterSetupRequested()
void MaemoDebugSupport::handleSshError(const QString &error)
{
- if (!m_stopped && !m_adapterStarted)
+ if (m_state == Debugging) {
+ m_runControl->showMessage(tr("SSH connection error: %1").arg(error),
+ AppError);
+ } else if (m_state != Inactive) {
handleAdapterSetupFailed(error);
+ }
}
void MaemoDebugSupport::startExecution()
{
- if (m_stopped)
+ if (m_state == Inactive)
return;
- const QString &dumperLib = m_runConfig->dumperLib();
- if (!m_qmlOnlyDebugging && !dumperLib.isEmpty()
- && m_runConfig->deployStep()->currentlyNeedsDeployment(m_deviceConfig.server.host,
- MaemoDeployable(dumperLib, uploadDir(m_deviceConfig)))) {
+ ASSERT_STATE(StartingRunner);
+
+ if (!useGdb() && m_debuggingType != MaemoRunConfiguration::DebugQmlOnly) {
+ if (!setPort(m_gdbServerPort))
+ return;
+ }
+ if (m_debuggingType != MaemoRunConfiguration::DebugCppOnly) {
+ if (!setPort(m_qmlPort))
+ return;
+ }
+
+ if (m_debuggingType != MaemoRunConfiguration::DebugQmlOnly
+ && !m_dumperLib.isEmpty()
+ && m_runConfig
+ && m_runConfig->deployStep()->currentlyNeedsDeployment(m_runner->deviceConfig().server.host,
+ MaemoDeployable(m_dumperLib, uploadDir(m_runner->deviceConfig())))) {
+ setState(InitializingUploader);
m_uploader = m_runner->connection()->createSftpChannel();
connect(m_uploader.data(), SIGNAL(initialized()), this,
SLOT(handleSftpChannelInitialized()));
@@ -171,43 +189,49 @@ void MaemoDebugSupport::startExecution()
this, SLOT(handleSftpJobFinished(Core::SftpJobId, QString)));
m_uploader->initialize();
} else {
+ setState(DumpersUploaded);
startDebugging();
}
}
void MaemoDebugSupport::handleSftpChannelInitialized()
{
- if (m_stopped)
+ if (m_state == Inactive)
return;
- const QString dumperLib = m_runConfig->dumperLib();
- const QString fileName = QFileInfo(dumperLib).fileName();
- const QString remoteFilePath = uploadDir(m_deviceConfig) + '/' + fileName;
- m_uploadJob = m_uploader->uploadFile(dumperLib, remoteFilePath,
+ ASSERT_STATE(InitializingUploader);
+
+ const QString fileName = QFileInfo(m_dumperLib).fileName();
+ const QString remoteFilePath
+ = uploadDir(m_runner->deviceConfig()) + '/' + fileName;
+ m_uploadJob = m_uploader->uploadFile(m_dumperLib, remoteFilePath,
SftpOverwriteExisting);
if (m_uploadJob == SftpInvalidJob) {
handleAdapterSetupFailed(tr("Upload failed: Could not open file '%1'")
- .arg(dumperLib));
+ .arg(m_dumperLib));
} else {
+ setState(UploadingDumpers);
m_runControl->showMessage(tr("Started uploading debugging helpers ('%1').")
- .arg(dumperLib), AppStuff);
+ .arg(m_dumperLib), AppStuff);
}
}
void MaemoDebugSupport::handleSftpChannelInitializationFailed(const QString &error)
{
- if (m_stopped)
+ if (m_state == Inactive)
return;
-
+ ASSERT_STATE(InitializingUploader);
handleAdapterSetupFailed(error);
}
void MaemoDebugSupport::handleSftpJobFinished(Core::SftpJobId job,
const QString &error)
{
- if (m_stopped)
+ if (m_state == Inactive)
return;
+ ASSERT_STATE(UploadingDumpers);
+
if (job != m_uploadJob) {
qWarning("Warning: Unknown debugging helpers upload job %d finished.", job);
return;
@@ -217,8 +241,11 @@ void MaemoDebugSupport::handleSftpJobFinished(Core::SftpJobId job,
handleAdapterSetupFailed(tr("Could not upload debugging helpers: %1.")
.arg(error));
} else {
- m_runConfig->deployStep()->setDeployed(m_deviceConfig.server.host,
- MaemoDeployable(m_runConfig->dumperLib(), uploadDir(m_deviceConfig)));
+ setState(DumpersUploaded);
+ if (m_runConfig) {
+ m_runConfig->deployStep()->setDeployed(m_runner->deviceConfig().server.host,
+ MaemoDeployable(m_dumperLib, uploadDir(m_runner->deviceConfig())));
+ }
m_runControl->showMessage(tr("Finished uploading debugging helpers."), AppStuff);
startDebugging();
}
@@ -227,43 +254,55 @@ void MaemoDebugSupport::handleSftpJobFinished(Core::SftpJobId job,
void MaemoDebugSupport::startDebugging()
{
+ ASSERT_STATE(DumpersUploaded);
+
if (useGdb()) {
handleAdapterSetupDone();
} else {
+ setState(StartingRemoteProcess);
m_gdbserverOutput.clear();
connect(m_runner, SIGNAL(remoteErrorOutput(QByteArray)), this,
SLOT(handleRemoteErrorOutput(QByteArray)));
connect(m_runner, SIGNAL(remoteOutput(QByteArray)), this,
SLOT(handleRemoteOutput(QByteArray)));
- const QString &remoteExe = m_runConfig->remoteExecutableFilePath();
+ const QString &remoteExe = m_runner->remoteExecutable();
const QString cmdPrefix = MaemoGlobal::remoteCommandPrefix(remoteExe);
- const QString env = environment(m_runConfig);
- const QString args = m_runConfig->arguments().join(QLatin1String(" "));
- const QString remoteCommandLine = m_qmlOnlyDebugging
- ? QString::fromLocal8Bit("%1 %2 %3 %4").arg(cmdPrefix).arg(env)
- .arg(remoteExe).arg(args)
- : QString::fromLocal8Bit("%1 %2 gdbserver :%3 %4 %5")
- .arg(cmdPrefix).arg(env).arg(gdbServerPort(m_runConfig))
- .arg(remoteExe).arg(args);
+ const QString env
+ = environment(m_debuggingType, m_runner->userEnvChanges());
+ const QString args = m_runner->arguments();
+ const QString remoteCommandLine
+ = m_debuggingType == MaemoRunConfiguration::DebugQmlOnly
+ ? QString::fromLocal8Bit("%1 %2 %3 %4").arg(cmdPrefix).arg(env)
+ .arg(remoteExe).arg(args)
+ : QString::fromLocal8Bit("%1 %2 gdbserver :%3 %4 %5")
+ .arg(cmdPrefix).arg(env).arg(m_gdbServerPort)
+ .arg(remoteExe).arg(args);
m_runner->startExecution(remoteCommandLine.toUtf8());
}
}
void MaemoDebugSupport::handleDebuggingFinished()
{
- m_stopped = true;
- stopSsh();
+ setState(Inactive);
}
void MaemoDebugSupport::handleRemoteOutput(const QByteArray &output)
{
- m_runControl->showMessage(QString::fromUtf8(output), AppOutput);
+ ASSERT_STATE(QList<State>() << Inactive << Debugging);
+ if (m_runControl)
+ m_runControl->showMessage(QString::fromUtf8(output), AppOutput);
}
void MaemoDebugSupport::handleRemoteErrorOutput(const QByteArray &output)
{
+ ASSERT_STATE(QList<State>() << Inactive << StartingRemoteProcess << Debugging);
+
+ if (!m_runControl)
+ return;
+
m_runControl->showMessage(QString::fromUtf8(output), AppOutput);
- if (!m_adapterStarted && !useGdb() && !m_qmlOnlyDebugging) {
+ if (m_state == StartingRemoteProcess
+ && m_debuggingType != MaemoRunConfiguration::DebugQmlOnly) {
m_gdbserverOutput += output;
if (m_gdbserverOutput.contains("Listening on port")) {
handleAdapterSetupDone();
@@ -274,54 +313,45 @@ void MaemoDebugSupport::handleRemoteErrorOutput(const QByteArray &output)
void MaemoDebugSupport::handleProgressReport(const QString &progressOutput)
{
- m_runControl->showMessage(progressOutput, AppStuff);
-}
-
-void MaemoDebugSupport::stopSsh()
-{
- //disconnect(m_runner, 0, this, 0);
- if (m_uploader) {
- disconnect(m_uploader.data(), 0, this, 0);
- m_uploader->closeChannel();
- }
- m_runner->stop();
+ if (m_runControl)
+ m_runControl->showMessage(progressOutput, AppStuff);
}
void MaemoDebugSupport::handleAdapterSetupFailed(const QString &error)
{
- m_runControl->handleRemoteSetupFailed(tr("Initial setup failed: %1").arg(error));
- m_stopped = true;
- stopSsh();
+ setState(Inactive);
+ m_runControl->engine()->handleRemoteSetupFailed(tr("Initial setup failed: %1").arg(error));
}
void MaemoDebugSupport::handleAdapterSetupDone()
{
- m_adapterStarted = true;
- m_runControl->handleRemoteSetupDone();
-}
-
-int MaemoDebugSupport::gdbServerPort(const MaemoRunConfiguration *rc)
-{
- return rc->freePorts().getNext();
+ setState(Debugging);
+ m_runControl->engine()->handleRemoteSetupDone(m_gdbServerPort, m_qmlPort);
}
-int MaemoDebugSupport::qmlServerPort(const MaemoRunConfiguration *rc)
+void MaemoDebugSupport::setState(State newState)
{
- MaemoPortList portList = rc->freePorts();
- if (rc->debuggingType() != MaemoRunConfiguration::DebugQmlOnly)
- portList.getNext();
- return portList.getNext();
+ if (m_state == newState)
+ return;
+ m_state = newState;
+ if (m_state == Inactive) {
+ if (m_uploader) {
+ disconnect(m_uploader.data(), 0, this, 0);
+ m_uploader->closeChannel();
+ }
+ m_runner->stop();
+ }
}
-QString MaemoDebugSupport::environment(const MaemoRunConfiguration *rc)
+QString MaemoDebugSupport::environment(MaemoRunConfiguration::DebuggingType debuggingType,
+ const QList<Utils::EnvironmentItem> &userEnvChanges)
{
- QList<Utils::EnvironmentItem> env = rc->userEnvironmentChanges();
// FIXME: this must use command line argument instead: -qmljsdebugger=port:1234.
- if (rc->debuggingType() != MaemoRunConfiguration::DebugCppOnly) {
+ if (debuggingType != MaemoRunConfiguration::DebugCppOnly) {
// env << Utils::EnvironmentItem(QLatin1String(Debugger::Constants::E_QML_DEBUG_SERVER_PORT),
// QString::number(qmlServerPort(rc)));
}
- return MaemoGlobal::remoteEnvironment(env);
+ return MaemoGlobal::remoteEnvironment(userEnvChanges);
}
QString MaemoDebugSupport::uploadDir(const MaemoDeviceConfig &devConf)
@@ -332,7 +362,17 @@ QString MaemoDebugSupport::uploadDir(const MaemoDeviceConfig &devConf)
bool MaemoDebugSupport::useGdb() const
{
return m_runControl->engine()->startParameters().startMode == StartRemoteGdb
- && !m_qmlOnlyDebugging;
+ && m_debuggingType != MaemoRunConfiguration::DebugQmlOnly;
+}
+
+bool MaemoDebugSupport::setPort(int &port)
+{
+ port = m_runner->usedPortsGatherer()->getNextFreePort(m_runner->freePorts());
+ if (port == -1) {
+ handleAdapterSetupFailed(tr("Not enough free ports on device for debugging."));
+ return false;
+ }
+ return true;
}
} // namespace Internal
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodebugsupport.h b/src/plugins/qt4projectmanager/qt-maemo/maemodebugsupport.h
index d4849aa659..bc202a4c6e 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemodebugsupport.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodebugsupport.h
@@ -35,11 +35,13 @@
#ifndef MAEMODEBUGSUPPORT_H
#define MAEMODEBUGSUPPORT_H
-#include "maemodeviceconfigurations.h"
+#include "maemorunconfiguration.h"
#include <coreplugin/ssh/sftpdefs.h>
+#include <utils/environment.h>
#include <QtCore/QObject>
+#include <QtCore/QPointer>
#include <QtCore/QSharedPointer>
namespace Core { class SftpChannel; }
@@ -81,27 +83,33 @@ private slots:
void handleProgressReport(const QString &progressOutput);
private:
- static int gdbServerPort(const MaemoRunConfiguration *rc);
- static int qmlServerPort(const MaemoRunConfiguration *rc);
- static QString environment(const MaemoRunConfiguration *rc);
+ enum State {
+ Inactive, StartingRunner, InitializingUploader, UploadingDumpers,
+ DumpersUploaded, StartingRemoteProcess, Debugging
+ };
+
+ static QString environment(MaemoRunConfiguration::DebuggingType debuggingType,
+ const QList<Utils::EnvironmentItem> &userEnvChanges);
- void stopSsh();
void handleAdapterSetupFailed(const QString &error);
void handleAdapterSetupDone();
void startDebugging();
bool useGdb() const;
+ void setState(State newState);
+ bool setPort(int &port);
- Debugger::DebuggerRunControl * const m_runControl;
- MaemoRunConfiguration * const m_runConfig;
- const MaemoDeviceConfig m_deviceConfig;
+ const QPointer<Debugger::DebuggerRunControl> m_runControl;
+ const QPointer<MaemoRunConfiguration> m_runConfig;
MaemoSshRunner * const m_runner;
- const bool m_qmlOnlyDebugging;
+ const MaemoRunConfiguration::DebuggingType m_debuggingType;
+ const QString m_dumperLib;
QSharedPointer<Core::SftpChannel> m_uploader;
Core::SftpJobId m_uploadJob;
- bool m_adapterStarted;
- bool m_stopped;
QByteArray m_gdbserverOutput;
+ State m_state;
+ int m_gdbServerPort;
+ int m_qmlPort;
};
} // namespace Internal
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeployablelistmodel.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemodeployablelistmodel.cpp
index 9a3637e4b0..0ee1c8f4ed 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemodeployablelistmodel.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeployablelistmodel.cpp
@@ -33,26 +33,36 @@
#include "maemodeployablelistmodel.h"
-#include "maemoprofilewrapper.h"
+#include "maemotoolchain.h"
+
+#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/session.h>
+#include <qt4projectmanager/qt4buildconfiguration.h>
+#include <qt4projectmanager/qt4target.h>
+
+#include <utils/qtcassert.h>
-#include <QtCore/QCryptographicHash>
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
+#include <QtGui/QBrush>
+#include <QtGui/QImageReader>
namespace Qt4ProjectManager {
namespace Internal {
+namespace {
+const QLatin1String RemoteIconPath("/usr/share/icons/hicolor/64x64/apps");
+} // anonymous namespace
MaemoDeployableListModel::MaemoDeployableListModel(const Qt4ProFileNode *proFileNode,
- const QSharedPointer<ProFileOption> &proFileOption,
ProFileUpdateSetting updateSetting, QObject *parent)
: QAbstractTableModel(parent),
m_projectType(proFileNode->projectType()),
m_proFilePath(proFileNode->path()),
m_projectName(proFileNode->displayName()),
m_targetInfo(proFileNode->targetInformation()),
+ m_installsList(proFileNode->installsList()),
+ m_config(proFileNode->variableValue(ConfigVar)),
m_modified(false),
- m_proFileWrapper(new MaemoProFileWrapper(m_proFilePath,
- proFileNode->buildDir(), proFileOption)),
m_proFileUpdateSetting(updateSetting),
m_hasTargetPath(false)
{
@@ -65,43 +75,26 @@ bool MaemoDeployableListModel::buildModel()
{
m_deployables.clear();
- const MaemoProFileWrapper::InstallsList &installs = m_proFileWrapper->installs();
- m_hasTargetPath = !installs.targetPath.isEmpty();
+ m_hasTargetPath = !m_installsList.targetPath.isEmpty();
if (!m_hasTargetPath && m_proFileUpdateSetting == UpdateProFile) {
const QString remoteDirSuffix
= QLatin1String(m_projectType == LibraryTemplate
? "/lib" : "/bin");
- const QString remoteDirMaemo5
- = QLatin1String("/opt/usr") + remoteDirSuffix;
- const QString remoteDirMaemo6
- = QLatin1String("/usr/local") + remoteDirSuffix;
- m_deployables.prepend(MaemoDeployable(localExecutableFilePath(),
- remoteDirMaemo5));
- QFile projectFile(m_proFilePath);
- if (!projectFile.open(QIODevice::WriteOnly | QIODevice::Append)) {
- qWarning("Error updating .pro file.");
- return false;
- }
- QString proFileTemplate = QLatin1String("\nunix:!symbian {\n"
- " maemo5 {\n target.path = maemo5path\n } else {\n"
- " target.path = maemo6path\n }\n"
- " INSTALLS += target\n}");
- proFileTemplate.replace(QLatin1String("maemo5path"), remoteDirMaemo5);
- proFileTemplate.replace(QLatin1String("maemo6path"), remoteDirMaemo6);
- if (!projectFile.write(proFileTemplate.toLocal8Bit())) {
- qWarning("Error updating .pro file.");
- return false;
- }
+ const QString remoteDir = QLatin1String("target.path = ")
+ + installPrefix() + remoteDirSuffix;
+ const QStringList deployInfo = QStringList() << remoteDir
+ << QLatin1String("INSTALLS += target");
+ return addLinesToProFile(deployInfo);
} else {
m_deployables.prepend(MaemoDeployable(localExecutableFilePath(),
- installs.targetPath));
+ m_installsList.targetPath));
}
- foreach (const MaemoProFileWrapper::InstallsElem &elem, installs.normalElems) {
+ foreach (const InstallsItem &elem, m_installsList.items) {
foreach (const QString &file, elem.files)
m_deployables << MaemoDeployable(file, elem.path);
}
- m_modified = true; // ???
+ m_modified = true;
return true;
}
@@ -111,43 +104,6 @@ MaemoDeployable MaemoDeployableListModel::deployableAt(int row) const
return m_deployables.at(row);
}
-bool MaemoDeployableListModel::addDeployable(const MaemoDeployable &deployable,
- QString *error)
-{
- if (m_deployables.contains(deployable)) {
- *error = tr("File already in list.");
- return false;
- }
-
- if (!m_proFileWrapper->addInstallsElem(deployable.remoteDir,
- deployable.localFilePath)) {
- *error = tr("Failed to update .pro file.");
- return false;
- }
-
- beginInsertRows(QModelIndex(), rowCount(), rowCount());
- m_deployables << deployable;
- endInsertRows();
- return true;
-}
-
-bool MaemoDeployableListModel::removeDeployableAt(int row, QString *error)
-{
- Q_ASSERT(row > 0 && row < rowCount());
-
- const MaemoDeployable &deployable = deployableAt(row);
- if (!m_proFileWrapper->removeInstallsElem(deployable.remoteDir,
- deployable.localFilePath)) {
- *error = tr("Could not update .pro file.");
- return false;
- }
-
- beginRemoveRows(QModelIndex(), row, row);
- m_deployables.removeAt(row);
- endRemoveRows();
- return true;
-}
-
int MaemoDeployableListModel::rowCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : m_deployables.count();
@@ -163,6 +119,16 @@ QVariant MaemoDeployableListModel::data(const QModelIndex &index, int role) cons
if (!index.isValid() || index.row() >= rowCount())
return QVariant();
+ if (isEditable(index)) {
+ if (role == Qt::DisplayRole)
+ return tr("<no target path set>");
+ if (role == Qt::ForegroundRole) {
+ QBrush brush;
+ brush.setColor("red");
+ return brush;
+ }
+ }
+
const MaemoDeployable &d = deployableAt(index.row());
if (index.column() == 0 && role == Qt::DisplayRole)
return QDir::toNativeSeparators(d.localFilePath);
@@ -174,27 +140,22 @@ QVariant MaemoDeployableListModel::data(const QModelIndex &index, int role) cons
Qt::ItemFlags MaemoDeployableListModel::flags(const QModelIndex &index) const
{
Qt::ItemFlags parentFlags = QAbstractTableModel::flags(index);
-// if (index.column() == 1)
-// return parentFlags | Qt::ItemIsEditable;
+ if (isEditable(index))
+ return parentFlags | Qt::ItemIsEditable;
return parentFlags;
}
bool MaemoDeployableListModel::setData(const QModelIndex &index,
const QVariant &value, int role)
{
- if (!index.isValid() || index.row() >= rowCount() || index.column() != 1
- || role != Qt::EditRole)
+ if (!isEditable(index) || role != Qt::EditRole)
return false;
-
- MaemoDeployable &deployable = m_deployables[index.row()];
- const QString &newRemoteDir = value.toString();
- if (!m_proFileWrapper->replaceInstallPath(deployable.remoteDir,
- deployable.localFilePath, newRemoteDir)) {
- qWarning("Error: Could not update .pro file");
+ const QString &remoteDir = value.toString();
+ if (!addLinesToProFile(QStringList()
+ << QString::fromLocal8Bit("target.path = %1").arg(remoteDir)
+ << QLatin1String("INSTALLS += target")))
return false;
- }
-
- deployable.remoteDir = newRemoteDir;
+ m_deployables.first().remoteDir = remoteDir;
emit dataChanged(index, index);
return true;
}
@@ -217,10 +178,8 @@ QString MaemoDeployableListModel::localExecutableFilePath() const
QString fileName;
if (isLib) {
fileName += QLatin1String("lib");
- const QStringList &config
- = m_proFileWrapper->varValues(QLatin1String("CONFIG"));
- isStatic = config.contains(QLatin1String("static"))
- || config.contains(QLatin1String("staticlib"));
+ isStatic = m_config.contains(QLatin1String("static"))
+ || m_config.contains(QLatin1String("staticlib"));
}
fileName += m_targetInfo.target;
if (isLib)
@@ -248,5 +207,164 @@ void MaemoDeployableListModel::setProFileUpdateSetting(ProFileUpdateSetting upda
buildModel();
}
+bool MaemoDeployableListModel::isEditable(const QModelIndex &index) const
+{
+ return index.row() == 0 && index.column() == 1
+ && m_deployables.first().remoteDir.isEmpty();
+}
+
+QString MaemoDeployableListModel::localDesktopFilePath() const
+{
+ if (m_projectType == LibraryTemplate)
+ return QString();
+ foreach (const MaemoDeployable &d, m_deployables) {
+ if (QFileInfo(d.localFilePath).fileName() == m_projectName + QLatin1String(".desktop"))
+ return d.localFilePath;
+ }
+ return QString();
+}
+
+bool MaemoDeployableListModel::addDesktopFile(QString &error)
+{
+ if (!canAddDesktopFile())
+ return true;
+ const QString desktopFilePath = QFileInfo(m_proFilePath).path()
+ + QLatin1Char('/') + m_projectName + QLatin1String(".desktop");
+ QFile desktopFile(desktopFilePath);
+ const bool existsAlready = desktopFile.exists();
+ if (!desktopFile.open(QIODevice::ReadWrite)) {
+ error = tr("Failed to open '%1': %2")
+ .arg(desktopFilePath, desktopFile.errorString());
+ return false;
+ }
+
+ const QByteArray desktopTemplate("[Desktop Entry]\nEncoding=UTF-8\n"
+ "Version=1.0\nType=Application\nTerminal=false\nName=%1\nExec=%2\n"
+ "Icon=%1\nX-Window-Icon=\nX-HildonDesk-ShowInToolbar=true\n"
+ "X-Osso-Type=application/x-executable\n");
+ const QString contents = existsAlready
+ ? QString::fromUtf8(desktopFile.readAll())
+ : QString::fromLocal8Bit(desktopTemplate)
+ .arg(m_projectName, remoteExecutableFilePath());
+ desktopFile.resize(0);
+ const QByteArray &contentsAsByteArray = contents.toUtf8();
+ if (desktopFile.write(contentsAsByteArray) != contentsAsByteArray.count()
+ || !desktopFile.flush()) {
+ error = tr("Could not write '%1': %2")
+ .arg(desktopFilePath, desktopFile.errorString());
+ return false;
+ }
+
+ const MaemoToolChain *const tc = maemoToolchain();
+ QTC_ASSERT(tc, return false);
+ QString remoteDir = QLatin1String("/usr/share/applications");
+ if (tc->version() == MaemoToolChain::Maemo5)
+ remoteDir += QLatin1String("/hildon");
+ const QLatin1String filesLine("desktopfile.files = $${TARGET}.desktop");
+ const QString pathLine = QLatin1String("desktopfile.path = ") + remoteDir;
+ const QLatin1String installsLine("INSTALLS += desktopfile");
+ if (!addLinesToProFile(QStringList() << filesLine << pathLine
+ << installsLine)) {
+ error = tr("Error writing project file.");
+ return false;
+ }
+
+ beginInsertRows(QModelIndex(), rowCount(), rowCount());
+ m_deployables << MaemoDeployable(desktopFilePath, remoteDir);
+ endInsertRows();
+ return true;
+}
+
+bool MaemoDeployableListModel::addIcon(const QString &fileName, QString &error)
+{
+ if (!canAddIcon())
+ return true;
+
+ const QString filesLine = QLatin1String("icon.files = ") + fileName;
+ const QString pathLine = QLatin1String("icon.path = ") + RemoteIconPath;
+ const QLatin1String installsLine("INSTALLS += icon");
+ if (!addLinesToProFile(QStringList() << filesLine << pathLine
+ << installsLine)) {
+ error = tr("Error writing project file.");
+ return false;
+ }
+
+ beginInsertRows(QModelIndex(), rowCount(), rowCount());
+ const QString filePath = QFileInfo(m_proFilePath).path()
+ + QLatin1Char('/') + fileName;
+ m_deployables << MaemoDeployable(filePath, RemoteIconPath);
+ endInsertRows();
+ return true;
+}
+
+QString MaemoDeployableListModel::remoteIconFilePath() const
+{
+ if (m_projectType == LibraryTemplate)
+ return QString();
+ const QList<QByteArray> &imageTypes = QImageReader::supportedImageFormats();
+ foreach (const MaemoDeployable &d, m_deployables) {
+ const QByteArray extension
+ = QFileInfo(d.localFilePath).suffix().toLocal8Bit();
+ if (d.remoteDir.startsWith(RemoteIconPath)
+ && imageTypes.contains(extension))
+ return d.remoteDir + QLatin1Char('/')
+ + QFileInfo(d.localFilePath).fileName();
+ }
+ return QString();
+}
+
+bool MaemoDeployableListModel::addLinesToProFile(const QStringList &lines)
+{
+ QFile projectFile(m_proFilePath);
+ if (!projectFile.open(QIODevice::WriteOnly | QIODevice::Append)) {
+ qWarning("Error opening .pro file for writing.");
+ return false;
+ }
+ const QLatin1String separator("\n ");
+ const QString proFileString = QString(QLatin1Char('\n') + proFileScope()
+ + QLatin1String(" {") + separator + lines.join(separator)
+ + QLatin1String("\n}\n"));
+ const QByteArray &proFileByteArray = proFileString.toLocal8Bit();
+ if (projectFile.write(proFileByteArray) != proFileByteArray.count()
+ || !projectFile.flush()) {
+ qWarning("Error updating .pro file.");
+ return false;
+ }
+ return true;
+}
+
+const MaemoToolChain *MaemoDeployableListModel::maemoToolchain() const
+{
+ const ProjectExplorer::Project *const activeProject
+ = ProjectExplorer::ProjectExplorerPlugin::instance()->session()->startupProject();
+ QTC_ASSERT(activeProject, return 0);
+ const Qt4Target *const activeTarget
+ = qobject_cast<Qt4Target *>(activeProject->activeTarget());
+ QTC_ASSERT(activeTarget, return 0);
+ const Qt4BuildConfiguration *const bc
+ = activeTarget->activeBuildConfiguration();
+ QTC_ASSERT(bc, return 0);
+ const MaemoToolChain *const tc
+ = dynamic_cast<MaemoToolChain *>(bc->toolChain());
+ QTC_ASSERT(tc, return 0);
+ return tc;
+}
+
+QString MaemoDeployableListModel::proFileScope() const
+{
+ const MaemoToolChain *const tc = maemoToolchain();
+ QTC_ASSERT(tc, return QString());
+ return QLatin1String(tc->version() == MaemoToolChain::Maemo5
+ ? "maemo5" : "unix:!symbian:!maemo5");
+}
+
+QString MaemoDeployableListModel::installPrefix() const
+{
+ const MaemoToolChain *const tc = maemoToolchain();
+ QTC_ASSERT(tc, return QString());
+ return QLatin1String(tc->version() == MaemoToolChain::Maemo5
+ ? "/opt/usr" : "/usr");
+}
+
} // namespace Qt4ProjectManager
} // namespace Internal
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeployablelistmodel.h b/src/plugins/qt4projectmanager/qt-maemo/maemodeployablelistmodel.h
index f562406627..dc7a5e6c34 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemodeployablelistmodel.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeployablelistmodel.h
@@ -42,16 +42,11 @@
#include <QtCore/QHash>
#include <QtCore/QList>
#include <QtCore/QScopedPointer>
-#include <QtCore/QSharedPointer>
#include <QtCore/QString>
-QT_BEGIN_NAMESPACE
-struct ProFileOption;
-QT_END_NAMESPACE
-
namespace Qt4ProjectManager {
namespace Internal {
-class MaemoProFileWrapper;
+class MaemoToolChain;
class MaemoDeployableListModel : public QAbstractTableModel
{
@@ -62,15 +57,12 @@ public:
};
MaemoDeployableListModel(const Qt4ProFileNode *proFileNode,
- const QSharedPointer<ProFileOption> &proFileOption,
ProFileUpdateSetting updateSetting, QObject *parent);
~MaemoDeployableListModel();
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
MaemoDeployable deployableAt(int row) const;
- bool addDeployable(const MaemoDeployable &deployable, QString *error);
- bool removeDeployableAt(int row, QString *error);
bool isModified() const { return m_modified; }
void setUnModified() { m_modified = false; }
QString localExecutableFilePath() const;
@@ -78,7 +70,16 @@ public:
QString projectName() const { return m_projectName; }
QString projectDir() const;
QString proFilePath() const { return m_proFilePath; }
+ bool isApplicationProject() const { return m_projectType == ApplicationTemplate; }
+ QString applicationName() const { return m_targetInfo.target; }
bool hasTargetPath() const { return m_hasTargetPath; }
+ bool canAddDesktopFile() const { return isApplicationProject() && !hasDesktopFile(); }
+ QString localDesktopFilePath() const;
+ bool hasDesktopFile() const { return !localDesktopFilePath().isEmpty(); }
+ bool addDesktopFile(QString &error);
+ bool canAddIcon() const { return isApplicationProject() && remoteIconFilePath().isEmpty(); }
+ bool addIcon(const QString &fileName, QString &error);
+ QString remoteIconFilePath() const;
ProFileUpdateSetting proFileUpdateSetting() const {
return m_proFileUpdateSetting;
}
@@ -94,15 +95,21 @@ private:
virtual bool setData(const QModelIndex &index, const QVariant &value,
int role = Qt::EditRole);
+ bool isEditable(const QModelIndex &index) const;
bool buildModel();
+ bool addLinesToProFile(const QStringList &lines);
+ const MaemoToolChain *maemoToolchain() const;
+ QString proFileScope() const;
+ QString installPrefix() const;
const Qt4ProjectType m_projectType;
const QString m_proFilePath;
const QString m_projectName;
const TargetInformation m_targetInfo;
+ const InstallsList m_installsList;
+ const QStringList m_config;
QList<MaemoDeployable> m_deployables;
mutable bool m_modified;
- const QScopedPointer<MaemoProFileWrapper> m_proFileWrapper;
ProFileUpdateSetting m_proFileUpdateSetting;
bool m_hasTargetPath;
};
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeployables.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemodeployables.cpp
index d1e9d5d3d4..84a20d16bb 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemodeployables.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeployables.cpp
@@ -67,9 +67,12 @@ MaemoDeployables::~MaemoDeployables() {}
void MaemoDeployables::init()
{
- connect(qt4BuildConfiguration()->qt4Target()->qt4Project(),
- SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode*)),
- m_updateTimer, SLOT(start()));
+ Qt4Project *pro = qt4BuildConfiguration()->qt4Target()->qt4Project();
+ connect(pro, SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode*,bool)),
+ m_updateTimer, SLOT(start()));
+
+ // TODO do we want to disable the view
+
createModels();
}
@@ -84,12 +87,8 @@ void MaemoDeployables::createModels()
if (!rootNode) // Happens on project creation by wizard.
return;
m_updateTimer->stop();
- m_proFileOption = QSharedPointer<ProFileOption>(new ProFileOption);
- m_proFileOption->properties
- = qt4BuildConfiguration()->qtVersion()->versionInfo();
- m_proFileOption->target_mode = ProFileOption::TARG_UNIX_MODE;
disconnect(qt4BuildConfiguration()->qt4Target()->qt4Project(),
- SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode*)),
+ SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode*,bool)),
m_updateTimer, SLOT(start()));
beginResetModel();
qDeleteAll(m_listModels);
@@ -121,8 +120,8 @@ void MaemoDeployables::createModels()
endResetModel();
connect(qt4BuildConfiguration()->qt4Target()->qt4Project(),
- SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode*)),
- m_updateTimer, SLOT(start()));
+ SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode*,bool)),
+ m_updateTimer, SLOT(start()));
}
void MaemoDeployables::createModels(const Qt4ProFileNode *proFileNode)
@@ -137,8 +136,7 @@ void MaemoDeployables::createModels(const Qt4ProFileNode *proFileNode)
= it != m_updateSettings.end()
? it.value() : MaemoDeployableListModel::AskToUpdateProFile;
MaemoDeployableListModel *const newModel
- = new MaemoDeployableListModel(proFileNode, m_proFileOption,
- updateSetting, this);
+ = new MaemoDeployableListModel(proFileNode, updateSetting, this);
m_listModels << newModel;
break;
}
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeployables.h b/src/plugins/qt4projectmanager/qt-maemo/maemodeployables.h
index c7c3921841..9d3f797bef 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemodeployables.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeployables.h
@@ -48,17 +48,15 @@
#include <QtCore/QAbstractListModel>
#include <QtCore/QHash>
#include <QtCore/QList>
-#include <QtCore/QSharedPointer>
-QT_FORWARD_DECLARE_CLASS(QTimer);
-QT_FORWARD_DECLARE_STRUCT(ProFileOption)
+QT_FORWARD_DECLARE_CLASS(QTimer)
namespace ProjectExplorer { class BuildStep; }
namespace Qt4ProjectManager {
-namespace Internal {
-
class Qt4BuildConfiguration;
+
+namespace Internal {
class Qt4ProFileNode;
class MaemoDeployables : public QAbstractListModel
@@ -88,7 +86,6 @@ private:
const Qt4BuildConfiguration *qt4BuildConfiguration() const;
QList<MaemoDeployableListModel *> m_listModels;
- QSharedPointer<ProFileOption> m_proFileOption;
UpdateSettingsMap m_updateSettings;
const ProjectExplorer::BuildStep * const m_buildStep;
QTimer *const m_updateTimer;
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeploystep.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemodeploystep.cpp
index 4252d3eb8b..208491fa43 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemodeploystep.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeploystep.cpp
@@ -34,7 +34,6 @@
#include "maemodeploystep.h"
#include "maemoconstants.h"
-#include "maemodeployables.h"
#include "maemodeploystepwidget.h"
#include "maemodeviceconfiglistmodel.h"
#include "maemoglobal.h"
@@ -42,6 +41,7 @@
#include "maemoremotemounter.h"
#include "maemorunconfiguration.h"
#include "maemotoolchain.h"
+#include "maemousedportsgatherer.h"
#include <coreplugin/ssh/sftpchannel.h>
#include <coreplugin/ssh/sshconnection.h>
@@ -59,6 +59,8 @@
#include <QtCore/QFileInfo>
#include <QtCore/QTimer>
+#define ASSERT_STATE(state) ASSERT_STATE_GENERIC(State, state, m_state)
+
using namespace Core;
using namespace ProjectExplorer;
@@ -69,34 +71,41 @@ namespace { const int DefaultMountPort = 1050; }
const QLatin1String MaemoDeployStep::Id("Qt4ProjectManager.MaemoDeployStep");
MaemoDeployStep::MaemoDeployStep(ProjectExplorer::BuildStepList *parent)
- : BuildStep(parent, Id), m_deployables(new MaemoDeployables(this))
+ : BuildStep(parent, Id)
{
ctor();
}
MaemoDeployStep::MaemoDeployStep(ProjectExplorer::BuildStepList *parent,
MaemoDeployStep *other)
- : BuildStep(parent, other), m_deployables(new MaemoDeployables(this)),
- m_lastDeployed(other->m_lastDeployed)
+ : BuildStep(parent, other), m_lastDeployed(other->m_lastDeployed)
{
ctor();
}
-MaemoDeployStep::~MaemoDeployStep()
-{
- delete m_deployables;
-}
+MaemoDeployStep::~MaemoDeployStep() { }
void MaemoDeployStep::ctor()
{
//: MaemoDeployStep default display name
setDefaultDisplayName(tr("Deploy to Maemo device"));
- m_connecting = false;
+ // A MaemoDeployables object is only dependent on the active build
+ // configuration and therefore can (and should) be shared among all
+ // deploy steps.
+ const QList<DeployConfiguration *> &deployConfigs
+ = target()->deployConfigurations();
+ if (deployConfigs.isEmpty()) {
+ m_deployables = QSharedPointer<MaemoDeployables>(new MaemoDeployables(this));
+ } else {
+ const MaemoDeployStep *const other
+ = MaemoGlobal::buildStep<MaemoDeployStep>(deployConfigs.first());
+ m_deployables = other->deployables();
+ }
+
+ m_state = Inactive;
m_needsInstall = false;
- m_stopped = false;
m_deviceConfigModel = new MaemoDeviceConfigListModel(this);
- m_canStart = true;
m_sysrootInstaller = new QProcess(this);
connect(m_sysrootInstaller, SIGNAL(finished(int,QProcess::ExitStatus)),
this, SLOT(handleSysrootInstallerFinished()));
@@ -104,9 +113,6 @@ void MaemoDeployStep::ctor()
SLOT(handleSysrootInstallerOutput()));
connect(m_sysrootInstaller, SIGNAL(readyReadStandardError()), this,
SLOT(handleSysrootInstallerErrorOutput()));
- m_cleanupTimer = new QTimer(this);
- connect(m_cleanupTimer, SIGNAL(timeout()), this,
- SLOT(handleCleanupTimeout()));
m_mounter = new MaemoRemoteMounter(this);
connect(m_mounter, SIGNAL(mounted()), this, SLOT(handleMounted()));
connect(m_mounter, SIGNAL(unmounted()), this, SLOT(handleUnmounted()));
@@ -116,6 +122,11 @@ void MaemoDeployStep::ctor()
SLOT(handleProgressReport(QString)));
connect(m_mounter, SIGNAL(debugOutput(QString)), this,
SLOT(handleMountDebugOutput(QString)));
+ m_portsGatherer = new MaemoUsedPortsGatherer(this);
+ connect(m_portsGatherer, SIGNAL(error(QString)), this,
+ SLOT(handlePortsGathererError(QString)));
+ connect(m_portsGatherer, SIGNAL(portListReady()), this,
+ SLOT(handlePortListReady()));
}
bool MaemoDeployStep::init()
@@ -129,7 +140,6 @@ void MaemoDeployStep::run(QFutureInterface<bool> &fi)
QTimer::singleShot(0, this, SLOT(start()));
MaemoDeployEventHandler eventHandler(this, fi);
- connect (&eventHandler, SIGNAL(destroyed()), this, SLOT(stop()));
}
BuildStepConfigWidget *MaemoDeployStep::createConfigWidget()
@@ -204,9 +214,8 @@ const MaemoPackageCreationStep *MaemoDeployStep::packagingStep() const
void MaemoDeployStep::raiseError(const QString &errorString)
{
- disconnect(m_connection.data(), 0, this, 0);
emit addTask(Task(Task::Error, errorString, QString(), -1,
- Constants::TASK_CATEGORY_BUILDSYSTEM));
+ ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
emit error();
}
@@ -217,40 +226,46 @@ void MaemoDeployStep::writeOutput(const QString &text, OutputFormat format)
void MaemoDeployStep::stop()
{
- if (m_stopped)
+ if (m_state == StopRequested || m_state == Inactive)
return;
- const bool remoteProcessRunning
- = (m_deviceInstaller && m_deviceInstaller->isRunning())
- || m_currentDeviceDeployAction;
- const bool isActive = remoteProcessRunning || m_connecting
- || m_needsInstall || !m_filesToCopy.isEmpty();
- if (!isActive) {
- if (m_connection)
- disconnect(m_connection.data(), 0, this, 0);
- return;
- }
-
- if (remoteProcessRunning) {
- const QByteArray programToKill
- = m_currentDeviceDeployAction ? "/bin/cp" : "/usr/bin/dpkg";
- const QByteArray cmdLine = "pkill " + programToKill
- + "; sleep 1; pkill -9 " + programToKill;
+ const State oldState = m_state;
+ setState(StopRequested);
+ switch (oldState) {
+ case InstallingToSysroot:
+ if (m_needsInstall)
+ m_sysrootInstaller->terminate();
+ break;
+ case Connecting:
+ m_connection->disconnectFromHost();
+ setState(Inactive);
+ break;
+ case InstallingToDevice:
+ case CopyingFile: {
+ const QByteArray programToKill = oldState == CopyingFile
+ ? " cp " : "dpkg";
+ const QByteArray killCommand
+ = MaemoGlobal::remoteSudo().toUtf8() + " pkill -f ";
+ const QByteArray cmdLine = killCommand + programToKill + "; sleep 1; "
+ + killCommand + "-9 " + programToKill;
SshRemoteProcess::Ptr killProc
= m_connection->createRemoteProcess(cmdLine);
killProc->start();
+ break;
+ }
+ case Uploading:
+ m_uploader->closeChannel();
+ break;
+ case UnmountingOldDirs:
+ case UnmountingCurrentDirs:
+ case UnmountingCurrentMounts:
+ case GatheringPorts:
+ case Mounting:
+ case InitializingSftp:
+ break; // Nothing to do here.
+ default:
+ Q_ASSERT_X(false, Q_FUNC_INFO, "Missing switch case.");
}
- m_stopped = true;
- m_unmountState = CurrentMountsUnmount;
- m_canStart = false;
- m_needsInstall = false;
- m_filesToCopy.clear();
- m_connecting = false;
- m_sysrootInstaller->terminate();
- m_sysrootInstaller->waitForFinished(500);
- m_sysrootInstaller->kill();
- m_cleanupTimer->start(5000);
- m_mounter->stop();
}
QString MaemoDeployStep::uploadDir() const
@@ -281,15 +296,15 @@ MaemoDeviceConfig MaemoDeployStep::deviceConfig() const
void MaemoDeployStep::start()
{
- if (!m_canStart) {
- raiseError(tr("Cannot start deployment, as the clean-up from the last time has not finished yet."));
+ if (m_state != Inactive) {
+ raiseError(tr("Cannot deploy: Still cleaning up from last time."));
+ emit done();
return;
}
- m_cleanupTimer->stop();
- m_stopped = false;
if (!deviceConfig().isValid()) {
raiseError(tr("Deployment failed: No valid device set."));
+ emit done();
return;
}
@@ -324,137 +339,192 @@ void MaemoDeployStep::start()
void MaemoDeployStep::handleConnectionFailure()
{
- m_connecting = false;
- if (m_stopped) {
- m_canStart = true;
+ if (m_state == Inactive)
return;
- }
- raiseError(tr("Could not connect to host: %1")
- .arg(m_connection->errorString()));
+
+ const QString errorMsg = m_state == Connecting
+ ? MaemoGlobal::failedToConnectToServerMessage(m_connection, deviceConfig())
+ : tr("Connection error: %1").arg(m_connection->errorString());
+ raiseError(errorMsg);
+ setState(Inactive);
}
void MaemoDeployStep::handleSftpChannelInitialized()
{
- if (m_stopped) {
- m_canStart = true;
- return;
+ ASSERT_STATE(QList<State>() << InitializingSftp << StopRequested);
+
+ switch (m_state) {
+ case InitializingSftp: {
+ const QString filePath = packagingStep()->packageFilePath();
+ const QString filePathNative = QDir::toNativeSeparators(filePath);
+ const QString fileName = QFileInfo(filePath).fileName();
+ const QString remoteFilePath = uploadDir() + QLatin1Char('/') + fileName;
+ const SftpJobId job = m_uploader->uploadFile(filePath,
+ remoteFilePath, SftpOverwriteExisting);
+ if (job == SftpInvalidJob) {
+ raiseError(tr("Upload failed: Could not open file '%1'")
+ .arg(filePathNative));
+ setState(Inactive);
+ } else {
+ setState(Uploading);
+ writeOutput(tr("Started uploading file '%1'.").arg(filePathNative));
+ }
+ break;
}
-
- const QString filePath = packagingStep()->packageFilePath();
- const QString filePathNative = QDir::toNativeSeparators(filePath);
- const QString fileName = QFileInfo(filePath).fileName();
- const QString remoteFilePath = uploadDir() + QLatin1Char('/') + fileName;
- const SftpJobId job = m_uploader->uploadFile(filePath,
- remoteFilePath, SftpOverwriteExisting);
- if (job == SftpInvalidJob) {
- raiseError(tr("Upload failed: Could not open file '%1'")
- .arg(filePathNative));
- } else {
- writeOutput(tr("Started uploading file '%1'.").arg(filePathNative));
+ case StopRequested:
+ setState(Inactive);
+ break;
+ default:
+ break;
}
}
void MaemoDeployStep::handleSftpChannelInitializationFailed(const QString &error)
{
- if (m_stopped) {
- m_canStart = true;
- return;
+ ASSERT_STATE(QList<State>() << InitializingSftp << StopRequested);
+
+ switch (m_state) {
+ case InitializingSftp:
+ case StopRequested:
+ raiseError(tr("Could not set up SFTP connection: %1").arg(error));
+ setState(Inactive);
+ break;
+ default:
+ break;
}
- raiseError(tr("Could not set up SFTP connection: %1").arg(error));
}
void MaemoDeployStep::handleSftpJobFinished(Core::SftpJobId,
const QString &error)
{
- if (m_stopped) {
- m_canStart = true;
- return;
- }
+ ASSERT_STATE(QList<State>() << Uploading << StopRequested);
const QString filePathNative
= QDir::toNativeSeparators(packagingStep()->packageFilePath());
if (!error.isEmpty()) {
raiseError(tr("Failed to upload file %1: %2")
.arg(filePathNative, error));
- return;
+ if (m_state == Uploading)
+ setState(Inactive);
+ } else if (m_state == Uploading) {
+ writeOutput(tr("Successfully uploaded file '%1'.")
+ .arg(filePathNative));
+ const QString remoteFilePath
+ = uploadDir() + QLatin1Char('/') + QFileInfo(filePathNative).fileName();
+ runDpkg(remoteFilePath);
}
+}
- writeOutput(tr("Successfully uploaded file '%1'.")
- .arg(filePathNative));
- const QString remoteFilePath
- = uploadDir() + QLatin1Char('/') + QFileInfo(filePathNative).fileName();
- runDpkg(remoteFilePath);
+void MaemoDeployStep::handleSftpChannelClosed()
+{
+ ASSERT_STATE(StopRequested);
+ setState(Inactive);
}
void MaemoDeployStep::handleMounted()
{
- if (m_stopped) {
- m_mounter->unmount();
- return;
- }
+ ASSERT_STATE(QList<State>() << Mounting << StopRequested << Inactive);
- if (m_needsInstall) {
- const QString remoteFilePath = deployMountPoint() + QLatin1Char('/')
- + QFileInfo(packagingStep()->packageFilePath()).fileName();
- runDpkg(remoteFilePath);
- } else {
- copyNextFileToDevice();
+ switch (m_state) {
+ case Mounting:
+ if (m_needsInstall) {
+ const QString remoteFilePath = deployMountPoint() + QLatin1Char('/')
+ + QFileInfo(packagingStep()->packageFilePath()).fileName();
+ runDpkg(remoteFilePath);
+ } else {
+ setState(CopyingFile);
+ copyNextFileToDevice();
+ }
+ break;
+ case StopRequested:
+ unmount();
+ break;
+ case Inactive:
+ default:
+ break;
}
}
void MaemoDeployStep::handleUnmounted()
{
- if (m_stopped) {
- m_mounter->resetMountSpecifications();
- m_canStart = true;
- return;
- }
+ ASSERT_STATE(QList<State>() << UnmountingOldDirs << UnmountingCurrentDirs
+ << UnmountingCurrentMounts << StopRequested << Inactive);
- switch (m_unmountState) {
- case OldDirsUnmount:
-#if 0 // TODO: Disabled for 2.1. Re-enable later or throw away for good.
+ switch (m_state) {
+ case StopRequested:
+ m_mounter->resetMountSpecifications();
+ setState(Inactive);
+ break;
+ case UnmountingOldDirs:
if (toolChain()->allowsRemoteMounts())
setupMount();
else
-#endif
prepareSftpConnection();
break;
- case CurrentDirsUnmount:
- m_mounter->mount();
+ case UnmountingCurrentDirs:
+ setState(GatheringPorts);
+ m_portsGatherer->start(m_connection, deviceConfig().freePorts());
break;
- case CurrentMountsUnmount:
+ case UnmountingCurrentMounts:
writeOutput(tr("Deployment finished."));
- emit done();
+ setState(Inactive);
+ break;
+ case Inactive:
+ default:
break;
}
}
void MaemoDeployStep::handleMountError(const QString &errorMsg)
{
- if (m_stopped)
- m_canStart = true;
- else
+ ASSERT_STATE(QList<State>() << UnmountingOldDirs << UnmountingCurrentDirs
+ << UnmountingCurrentMounts << Mounting << StopRequested << Inactive);
+
+ switch (m_state) {
+ case UnmountingOldDirs:
+ case UnmountingCurrentDirs:
+ case UnmountingCurrentMounts:
+ case StopRequested:
raiseError(errorMsg);
+ setState(Inactive);
+ break;
+ case Inactive:
+ default:
+ break;
+ }
}
void MaemoDeployStep::handleMountDebugOutput(const QString &output)
{
- if (!m_stopped)
+ ASSERT_STATE(QList<State>() << UnmountingOldDirs << UnmountingCurrentDirs
+ << UnmountingCurrentMounts << Mounting << StopRequested << Inactive);
+
+ switch (m_state) {
+ case UnmountingOldDirs:
+ case UnmountingCurrentDirs:
+ case UnmountingCurrentMounts:
+ case StopRequested:
writeOutput(output, ErrorOutput);
+ break;
+ case Inactive:
+ default:
+ break;
+ }
}
void MaemoDeployStep::setupMount()
{
+ ASSERT_STATE(UnmountingOldDirs);
+ setState(UnmountingCurrentDirs);
+
Q_ASSERT(m_needsInstall || !m_filesToCopy.isEmpty());
m_mounter->resetMountSpecifications();
m_mounter->setToolchain(toolChain());
- m_mounter->setPortList(deviceConfig().freePorts());
if (m_needsInstall) {
const QString localDir
= QFileInfo(packagingStep()->packageFilePath()).absolutePath();
const MaemoMountSpecification mountSpec(localDir, deployMountPoint());
- if (!addMountSpecification(mountSpec))
- return;
+ m_mounter->addMountSpecification(mountSpec, true);
} else {
#ifdef Q_OS_WIN
bool drivesToMount[26];
@@ -476,27 +546,20 @@ void MaemoDeployStep::setupMount()
+ QLatin1Char(driveLetter);
const MaemoMountSpecification mountSpec(localDir.left(3),
mountPoint);
- if (!addMountSpecification(mountSpec))
- return;
+ m_mounter->addMountSpecification(mountSpec, true);
drivesToMount[index] = true;
}
#else
- if (!addMountSpecification(MaemoMountSpecification(QLatin1String("/"),
- deployMountPoint())))
- return;
+ m_mounter->addMountSpecification(MaemoMountSpecification(QLatin1String("/"),
+ deployMountPoint()), true);
#endif
}
- m_unmountState = CurrentDirsUnmount;
- m_mounter->unmount();
+ unmount();
}
void MaemoDeployStep::prepareSftpConnection()
{
- // TODO: Close channel when upload has finished/failed/etc.
- if (m_uploader) {
- disconnect(m_uploader.data(), 0, this, 0);
- m_uploader->closeChannel();
- }
+ setState(InitializingSftp);
m_uploader = m_connection->createSftpChannel();
connect(m_uploader.data(), SIGNAL(initialized()), this,
SLOT(handleSftpChannelInitialized()));
@@ -504,11 +567,16 @@ void MaemoDeployStep::prepareSftpConnection()
SLOT(handleSftpChannelInitializationFailed(QString)));
connect(m_uploader.data(), SIGNAL(finished(Core::SftpJobId, QString)),
this, SLOT(handleSftpJobFinished(Core::SftpJobId, QString)));
+ connect(m_uploader.data(), SIGNAL(closed()), this,
+ SLOT(handleSftpChannelClosed()));
m_uploader->initialize();
}
void MaemoDeployStep::installToSysroot()
{
+ ASSERT_STATE(Inactive);
+ setState(InstallingToSysroot);
+
if (m_needsInstall) {
writeOutput(tr("Installing package to sysroot ..."));
const MaemoToolChain * const tc = toolChain();
@@ -539,8 +607,8 @@ void MaemoDeployStep::installToSysroot()
ErrorMessageOutput);
}
QCoreApplication::processEvents();
- if (m_stopped) {
- m_canStart = true;
+ if (m_state == StopRequested) {
+ setState(Inactive);
return;
}
}
@@ -550,8 +618,10 @@ void MaemoDeployStep::installToSysroot()
void MaemoDeployStep::handleSysrootInstallerFinished()
{
- if (m_stopped) {
- m_canStart = true;
+ ASSERT_STATE(QList<State>() << InstallingToSysroot << StopRequested);
+
+ if (m_state == StopRequested) {
+ setState(Inactive);
return;
}
@@ -565,7 +635,9 @@ void MaemoDeployStep::handleSysrootInstallerFinished()
void MaemoDeployStep::connectToDevice()
{
- m_connecting = false;
+ ASSERT_STATE(QList<State>() << Inactive << InstallingToSysroot);
+ setState(Connecting);
+
const bool canReUse = m_connection
&& m_connection->state() == SshConnection::Connected
&& m_connection->connectionParameters() == deviceConfig().server;
@@ -576,36 +648,39 @@ void MaemoDeployStep::connectToDevice()
connect(m_connection.data(), SIGNAL(error(Core::SshError)), this,
SLOT(handleConnectionFailure()));
if (canReUse) {
- unmountOldDirs();
+ handleConnected();
} else {
writeOutput(tr("Connecting to device..."));
- m_connecting = true;
m_connection->connectToHost(deviceConfig().server);
}
}
void MaemoDeployStep::handleConnected()
{
- if (m_stopped) {
- m_canStart = true;
- return;
- }
+ ASSERT_STATE(QList<State>() << Connecting << StopRequested);
- unmountOldDirs();
+ if (m_state == Connecting)
+ unmountOldDirs();
}
void MaemoDeployStep::unmountOldDirs()
{
- m_unmountState = OldDirsUnmount;
+ setState(UnmountingOldDirs);
m_mounter->setConnection(m_connection);
- m_mounter->unmount();
+ unmount();
}
void MaemoDeployStep::runDpkg(const QString &packageFilePath)
{
+ ASSERT_STATE(QList<State>() << Mounting << Uploading);
+ const bool removeAfterInstall = m_state == Uploading;
+ setState(InstallingToDevice);
+
writeOutput(tr("Installing package to device..."));
- const QByteArray cmd = MaemoGlobal::remoteSudo().toUtf8() + " dpkg -i "
+ QByteArray cmd = MaemoGlobal::remoteSudo().toUtf8() + " dpkg -i "
+ packageFilePath.toUtf8();
+ if (removeAfterInstall)
+ cmd += " && (rm " + packageFilePath.toUtf8() + " || :)";
m_deviceInstaller = m_connection->createRemoteProcess(cmd);
connect(m_deviceInstaller.data(), SIGNAL(closed(int)), this,
SLOT(handleInstallationFinished(int)));
@@ -619,11 +694,25 @@ void MaemoDeployStep::runDpkg(const QString &packageFilePath)
void MaemoDeployStep::handleProgressReport(const QString &progressMsg)
{
- writeOutput(progressMsg);
+ ASSERT_STATE(QList<State>() << UnmountingOldDirs << UnmountingCurrentDirs
+ << UnmountingCurrentMounts << Mounting << StopRequested << Inactive);
+
+ switch (m_state) {
+ case UnmountingOldDirs:
+ case UnmountingCurrentDirs:
+ case UnmountingCurrentMounts:
+ case StopRequested:
+ writeOutput(progressMsg);
+ break;
+ case Inactive:
+ default:
+ break;
+ }
}
void MaemoDeployStep::copyNextFileToDevice()
{
+ ASSERT_STATE(CopyingFile);
Q_ASSERT(!m_filesToCopy.isEmpty());
Q_ASSERT(!m_currentDeviceDeployAction);
const MaemoDeployable d = m_filesToCopy.takeFirst();
@@ -651,63 +740,49 @@ void MaemoDeployStep::copyNextFileToDevice()
copyProcess->start();
}
-bool MaemoDeployStep::addMountSpecification(const MaemoMountSpecification &mountSpec)
-{
- if (!m_mounter->addMountSpecification(mountSpec, true)) {
- raiseError(tr("Device has not enough free ports for deployment."));
- return false;
- }
- return true;
-}
-
void MaemoDeployStep::handleCopyProcessFinished(int exitStatus)
{
- if (m_stopped) {
- m_mounter->unmount();
- return;
- }
+ ASSERT_STATE(QList<State>() << CopyingFile << StopRequested << Inactive);
- Q_ASSERT(m_currentDeviceDeployAction);
- const QString localFilePath = m_currentDeviceDeployAction->first.localFilePath;
- if (exitStatus != SshRemoteProcess::ExitedNormally
- || m_currentDeviceDeployAction->second->exitCode() != 0) {
- raiseError(tr("Copying file '%1' failed.").arg(localFilePath));
- m_mounter->unmount();
- m_currentDeviceDeployAction.reset(0);
- } else {
- writeOutput(tr("Successfully copied file '%1'.").arg(localFilePath));
- setDeployed(m_connection->connectionParameters().host,
- m_currentDeviceDeployAction->first);
- m_currentDeviceDeployAction.reset(0);
- if (m_filesToCopy.isEmpty()) {
- writeOutput(tr("All files copied."));
- m_unmountState = CurrentMountsUnmount;
- m_mounter->unmount();
+ switch (m_state) {
+ case CopyingFile: {
+ Q_ASSERT(m_currentDeviceDeployAction);
+ const QString localFilePath
+ = m_currentDeviceDeployAction->first.localFilePath;
+ if (exitStatus != SshRemoteProcess::ExitedNormally
+ || m_currentDeviceDeployAction->second->exitCode() != 0) {
+ raiseError(tr("Copying file '%1' failed.").arg(localFilePath));
+ m_currentDeviceDeployAction.reset(0);
+ setState(UnmountingCurrentMounts);
+ unmount();
} else {
- copyNextFileToDevice();
- }
- }
-}
-
-void MaemoDeployStep::handleCleanupTimeout()
-{
- m_cleanupTimer->stop();
- if (!m_canStart) {
- m_canStart = true;
- disconnect(m_connection.data(), 0, this, 0);
- if (m_deviceInstaller)
- disconnect(m_deviceInstaller.data(), 0, this, 0);
- if (m_currentDeviceDeployAction) {
- disconnect(m_currentDeviceDeployAction->second.data(), 0, this, 0);
+ writeOutput(tr("Successfully copied file '%1'.").arg(localFilePath));
+ setDeployed(m_connection->connectionParameters().host,
+ m_currentDeviceDeployAction->first);
m_currentDeviceDeployAction.reset(0);
+ if (m_filesToCopy.isEmpty()) {
+ writeOutput(tr("All files copied."));
+ setState(UnmountingCurrentMounts);
+ unmount();
+ } else {
+ copyNextFileToDevice();
+ }
}
+ break;
+ }
+ case StopRequested:
+ unmount();
+ break;
+ case Inactive:
+ default:
+ break;
}
}
QString MaemoDeployStep::deployMountPoint() const
{
return MaemoGlobal::homeDirOnDevice(deviceConfig().server.uname)
- + QLatin1String("/deployMountPoint");
+ + QLatin1String("/deployMountPoint_") + packagingStep()->projectName();
}
const MaemoToolChain *MaemoDeployStep::toolChain() const
@@ -719,53 +794,146 @@ const MaemoToolChain *MaemoDeployStep::toolChain() const
void MaemoDeployStep::handleSysrootInstallerOutput()
{
- if (!m_stopped) {
+ ASSERT_STATE(QList<State>() << InstallingToSysroot << StopRequested);
+
+ switch (m_state) {
+ case InstallingToSysroot:
+ case StopRequested:
writeOutput(QString::fromLocal8Bit(m_sysrootInstaller->readAllStandardOutput()),
NormalOutput);
+ break;
+ default:
+ break;
}
}
void MaemoDeployStep::handleSysrootInstallerErrorOutput()
{
- if (!m_stopped) {
+ ASSERT_STATE(QList<State>() << InstallingToSysroot << StopRequested);
+
+ switch (m_state) {
+ case InstallingToSysroot:
+ case StopRequested:
writeOutput(QString::fromLocal8Bit(m_sysrootInstaller->readAllStandardError()),
BuildStep::ErrorOutput);
+ break;
+ default:
+ break;
}
}
void MaemoDeployStep::handleInstallationFinished(int exitStatus)
{
- if (m_stopped) {
- m_mounter->unmount();
- return;
+ ASSERT_STATE(QList<State>() << InstallingToDevice << StopRequested
+ << Inactive);
+
+ switch (m_state) {
+ case InstallingToDevice:
+ if (exitStatus != SshRemoteProcess::ExitedNormally
+ || m_deviceInstaller->exitCode() != 0) {
+ raiseError(tr("Installing package failed."));
+ } else {
+ m_needsInstall = false;
+ setDeployed(m_connection->connectionParameters().host,
+ MaemoDeployable(packagingStep()->packageFilePath(), QString()));
+ writeOutput(tr("Package installed."));
+ }
+ setState(UnmountingCurrentMounts);
+ unmount();
+ break;
+ case StopRequested:
+ unmount();
+ break;
+ case Inactive:
+ default:
+ break;
+ }
+}
+
+void MaemoDeployStep::handlePortsGathererError(const QString &errorMsg)
+{
+ ASSERT_STATE(QList<State>() << GatheringPorts << StopRequested << Inactive);
+
+ if (m_state != Inactive) {
+ raiseError(errorMsg);
+ setState(Inactive);
}
+}
- if (exitStatus != SshRemoteProcess::ExitedNormally
- || m_deviceInstaller->exitCode() != 0) {
- raiseError(tr("Installing package failed."));
+void MaemoDeployStep::handlePortListReady()
+{
+ ASSERT_STATE(QList<State>() << GatheringPorts << StopRequested);
+
+ if (m_state == GatheringPorts) {
+ setState(Mounting);
+ m_freePorts = deviceConfig().freePorts();
+ m_mounter->mount(&m_freePorts, m_portsGatherer);
} else {
+ setState(Inactive);
+ }
+}
+
+void MaemoDeployStep::setState(State newState)
+{
+ if (newState == m_state)
+ return;
+ m_state = newState;
+ if (m_state == Inactive) {
m_needsInstall = false;
- setDeployed(m_connection->connectionParameters().host,
- MaemoDeployable(packagingStep()->packageFilePath(), QString()));
- writeOutput(tr("Package installed."));
+ m_filesToCopy.clear();
+ m_currentDeviceDeployAction.reset(0);
+ if (m_connection)
+ disconnect(m_connection.data(), 0, this, 0);
+ if (m_uploader) {
+ disconnect(m_uploader.data(), 0, this, 0);
+ m_uploader->closeChannel();
+ }
+ if (m_deviceInstaller)
+ disconnect(m_deviceInstaller.data(), 0, this, 0);
+ emit done();
}
- m_unmountState = CurrentMountsUnmount;
- m_mounter->unmount();
+}
+
+void MaemoDeployStep::unmount()
+{
+ if (m_mounter->hasValidMountSpecifications())
+ m_mounter->unmount();
+ else
+ handleUnmounted();
}
void MaemoDeployStep::handleDeviceInstallerOutput(const QByteArray &output)
{
- writeOutput(QString::fromUtf8(output), NormalOutput);
+ ASSERT_STATE(QList<State>() << InstallingToDevice << StopRequested);
+
+ switch (m_state) {
+ case InstallingToDevice:
+ case StopRequested:
+ writeOutput(QString::fromUtf8(output), NormalOutput);
+ break;
+ default:
+ break;
+ }
}
void MaemoDeployStep::handleDeviceInstallerErrorOutput(const QByteArray &output)
{
- writeOutput(QString::fromUtf8(output), ErrorOutput);
+ ASSERT_STATE(QList<State>() << InstallingToDevice << StopRequested);
+
+ switch (m_state) {
+ case InstallingToDevice:
+ case StopRequested:
+ writeOutput(QString::fromUtf8(output), ErrorOutput);
+ break;
+ default:
+ break;
+ }
}
MaemoDeployEventHandler::MaemoDeployEventHandler(MaemoDeployStep *deployStep,
QFutureInterface<bool> &future)
- : m_deployStep(deployStep), m_future(future), m_eventLoop(new QEventLoop)
+ : m_deployStep(deployStep), m_future(future), m_eventLoop(new QEventLoop),
+ m_error(false)
{
connect(m_deployStep, SIGNAL(done()), this, SLOT(handleDeployingDone()));
connect(m_deployStep, SIGNAL(error()), this, SLOT(handleDeployingFailed()));
@@ -777,18 +945,21 @@ MaemoDeployEventHandler::MaemoDeployEventHandler(MaemoDeployStep *deployStep,
void MaemoDeployEventHandler::handleDeployingDone()
{
- m_eventLoop->exit(0);
+ m_eventLoop->exit(m_error ? 1 : 0);
}
void MaemoDeployEventHandler::handleDeployingFailed()
{
- m_eventLoop->exit(1);
+ m_error = true;
}
void MaemoDeployEventHandler::checkForCanceled()
{
- if (m_future.isCanceled())
- handleDeployingFailed();
+ if (!m_error && m_future.isCanceled()) {
+ QMetaObject::invokeMethod(m_deployStep, "stop");
+ m_error = true;
+ handleDeployingDone();
+ }
}
} // namespace Internal
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeploystep.h b/src/plugins/qt4projectmanager/qt-maemo/maemodeploystep.h
index d28dd5557d..5f65ede125 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemodeploystep.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeploystep.h
@@ -35,6 +35,7 @@
#define MAEMODEPLOYSTEP_H
#include "maemodeployable.h"
+#include "maemodeployables.h"
#include "maemodeviceconfigurations.h"
#include "maemomountspecification.h"
@@ -62,10 +63,10 @@ class SshRemoteProcess;
namespace Qt4ProjectManager {
namespace Internal {
class MaemoRemoteMounter;
-class MaemoDeployables;
class MaemoDeviceConfigListModel;
class MaemoPackageCreationStep;
class MaemoToolChain;
+class MaemoUsedPortsGatherer;
class MaemoDeployStep : public ProjectExplorer::BuildStep
{
@@ -80,19 +81,20 @@ public:
bool currentlyNeedsDeployment(const QString &host,
const MaemoDeployable &deployable) const;
void setDeployed(const QString &host, const MaemoDeployable &deployable);
- MaemoDeployables *deployables() const { return m_deployables; }
+ QSharedPointer<MaemoDeployables> deployables() const { return m_deployables; }
QSharedPointer<Core::SshConnection> sshConnection() const { return m_connection; }
bool isDeployToSysrootEnabled() const { return m_deployToSysroot; }
void setDeployToSysrootEnabled(bool deploy) { m_deployToSysroot = deploy; }
+ Q_INVOKABLE void stop();
+
signals:
void done();
void error();
private slots:
void start();
- void stop();
void handleConnected();
void handleConnectionFailure();
void handleMounted();
@@ -101,18 +103,27 @@ private slots:
void handleMountDebugOutput(const QString &output);
void handleProgressReport(const QString &progressMsg);
void handleCopyProcessFinished(int exitStatus);
- void handleCleanupTimeout();
void handleSysrootInstallerFinished();
void handleSysrootInstallerOutput();
void handleSysrootInstallerErrorOutput();
void handleSftpChannelInitialized();
void handleSftpChannelInitializationFailed(const QString &error);
void handleSftpJobFinished(Core::SftpJobId job, const QString &error);
+ void handleSftpChannelClosed();
void handleInstallationFinished(int exitStatus);
void handleDeviceInstallerOutput(const QByteArray &output);
void handleDeviceInstallerErrorOutput(const QByteArray &output);
+ void handlePortsGathererError(const QString &errorMsg);
+ void handlePortListReady();
private:
+ enum State {
+ Inactive, StopRequested, InstallingToSysroot, Connecting,
+ UnmountingOldDirs, UnmountingCurrentDirs, GatheringPorts, Mounting,
+ InstallingToDevice, UnmountingCurrentMounts, CopyingFile,
+ InitializingSftp, Uploading
+ };
+
MaemoDeployStep(ProjectExplorer::BuildStepList *bc,
MaemoDeployStep *other);
virtual bool init();
@@ -131,7 +142,6 @@ private:
QString deployMountPoint() const;
const MaemoToolChain *toolChain() const;
void copyNextFileToDevice();
- bool addMountSpecification(const MaemoMountSpecification &mountSpec);
void installToSysroot();
QString uploadDir() const;
void connectToDevice();
@@ -139,30 +149,29 @@ private:
void setupMount();
void prepareSftpConnection();
void runDpkg(const QString &packageFilePath);
+ void setState(State newState);
+ void unmount();
static const QLatin1String Id;
- MaemoDeployables * const m_deployables;
+ QSharedPointer<MaemoDeployables> m_deployables;
QSharedPointer<Core::SshConnection> m_connection;
QProcess *m_sysrootInstaller;
typedef QPair<MaemoDeployable, QSharedPointer<Core::SshRemoteProcess> > DeviceDeployAction;
QScopedPointer<DeviceDeployAction> m_currentDeviceDeployAction;
QList<MaemoDeployable> m_filesToCopy;
MaemoRemoteMounter *m_mounter;
- QTimer *m_cleanupTimer;
- bool m_canStart;
bool m_deployToSysroot;
- enum UnmountState { OldDirsUnmount, CurrentDirsUnmount, CurrentMountsUnmount };
- UnmountState m_unmountState;
QSharedPointer<Core::SftpChannel> m_uploader;
QSharedPointer<Core::SshRemoteProcess> m_deviceInstaller;
- bool m_stopped;
bool m_needsInstall;
- bool m_connecting;
typedef QPair<MaemoDeployable, QString> DeployablePerHost;
QHash<DeployablePerHost, QDateTime> m_lastDeployed;
MaemoDeviceConfigListModel *m_deviceConfigModel;
+ MaemoUsedPortsGatherer *m_portsGatherer;
+ MaemoPortList m_freePorts;
+ State m_state;
};
class MaemoDeployEventHandler : public QObject
@@ -178,9 +187,10 @@ private slots:
void checkForCanceled();
private:
- const MaemoDeployStep * const m_deployStep;
+ MaemoDeployStep * const m_deployStep;
const QFutureInterface<bool> m_future;
QEventLoop * const m_eventLoop;
+ bool m_error;
};
} // namespace Internal
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeploystepwidget.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemodeploystepwidget.cpp
index 55c9d39b1c..37e1aa4117 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemodeploystepwidget.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeploystepwidget.cpp
@@ -11,6 +11,10 @@
#include <projectexplorer/target.h>
#include <utils/qtcassert.h>
+#include <QtGui/QFileDialog>
+#include <QtGui/QMessageBox>
+#include <QtGui/QPixmap>
+
namespace Qt4ProjectManager {
namespace Internal {
@@ -20,17 +24,20 @@ MaemoDeployStepWidget::MaemoDeployStepWidget(MaemoDeployStep *step) :
m_step(step)
{
ui->setupUi(this);
- ui->modelComboBox->setModel(m_step->deployables());
- connect(m_step->deployables(), SIGNAL(modelAboutToBeReset()),
+ ui->modelComboBox->setModel(m_step->deployables().data());
+ connect(m_step->deployables().data(), SIGNAL(modelAboutToBeReset()),
SLOT(handleModelListToBeReset()));
// Queued connection because of race condition with combo box's reaction
// to modelReset().
- connect(m_step->deployables(), SIGNAL(modelReset()),
+ connect(m_step->deployables().data(), SIGNAL(modelReset()),
SLOT(handleModelListReset()), Qt::QueuedConnection);
connect(ui->modelComboBox, SIGNAL(currentIndexChanged(int)),
SLOT(setModel(int)));
+ connect(ui->addDesktopFileButton, SIGNAL(clicked()),
+ SLOT(addDesktopFile()));
+ connect(ui->addIconButton, SIGNAL(clicked()), SLOT(addIcon()));
handleModelListReset();
}
@@ -97,7 +104,10 @@ void MaemoDeployStepWidget::setDeployToSysroot(bool doDeploy)
void MaemoDeployStepWidget::handleModelListToBeReset()
{
+ ui->tableView->reset(); // Otherwise we'll crash if the user is currently editing.
ui->tableView->setModel(0);
+ ui->addDesktopFileButton->setEnabled(false);
+ ui->addIconButton->setEnabled(false);
}
void MaemoDeployStepWidget::handleModelListReset()
@@ -113,10 +123,75 @@ void MaemoDeployStepWidget::handleModelListReset()
void MaemoDeployStepWidget::setModel(int row)
{
+ bool canAddDesktopFile = false;
+ bool canAddIconFile = false;
if (row != -1) {
- ui->tableView->setModel(m_step->deployables()->modelAt(row));
+ MaemoDeployableListModel *const model
+ = m_step->deployables()->modelAt(row);
+ ui->tableView->setModel(model);
ui->tableView->resizeRowsToContents();
+ canAddDesktopFile = model->canAddDesktopFile();
+ canAddIconFile = model->canAddIcon();
+ }
+ ui->addDesktopFileButton->setEnabled(canAddDesktopFile);
+ ui->addIconButton->setEnabled(canAddIconFile);
+}
+
+void MaemoDeployStepWidget::addDesktopFile()
+{
+ const int modelRow = ui->modelComboBox->currentIndex();
+ if (modelRow == -1)
+ return;
+ MaemoDeployableListModel *const model
+ = m_step->deployables()->modelAt(modelRow);
+ QString error;
+ if (!model->addDesktopFile(error)) {
+ QMessageBox::warning(this, tr("Could not create desktop file"),
+ tr("Error creating desktop file: %1").arg(error));
+ }
+ ui->addDesktopFileButton->setEnabled(model->canAddDesktopFile());
+ ui->tableView->resizeRowsToContents();
+}
+
+void MaemoDeployStepWidget::addIcon()
+{
+ const int modelRow = ui->modelComboBox->currentIndex();
+ if (modelRow == -1)
+ return;
+
+ MaemoDeployableListModel *const model
+ = m_step->deployables()->modelAt(modelRow);
+ const QString origFilePath = QFileDialog::getOpenFileName(this,
+ tr("Choose Icon (will be scaled to 64x64 pixels, if necessary)"),
+ model->projectDir(), QLatin1String("(*.png)"));
+ if (origFilePath.isEmpty())
+ return;
+ QPixmap pixmap(origFilePath);
+ if (pixmap.isNull()) {
+ QMessageBox::critical(this, tr("Invalid Icon"),
+ tr("Unable to read image"));
+ return;
+ }
+ const QSize iconSize(64, 64);
+ if (pixmap.size() != iconSize)
+ pixmap = pixmap.scaled(iconSize);
+ const QString newFileName = model->projectName() + QLatin1Char('.')
+ + QFileInfo(origFilePath).suffix();
+ const QString newFilePath = model->projectDir() + QLatin1Char('/')
+ + newFileName;
+ if (!pixmap.save(newFilePath)) {
+ QMessageBox::critical(this, tr("Failed to Save Icon"),
+ tr("Could not save icon to '%1'.").arg(newFilePath));
+ return;
+ }
+
+ QString error;
+ if (!model->addIcon(newFileName, error)) {
+ QMessageBox::critical(this, tr("Could Not Add Icon"),
+ tr("Error adding icon: %1").arg(error));
}
+ ui->addIconButton->setEnabled(model->canAddIcon());
+ ui->tableView->resizeRowsToContents();
}
} // namespace Internal
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeploystepwidget.h b/src/plugins/qt4projectmanager/qt-maemo/maemodeploystepwidget.h
index 28c0f00d30..516f40a15d 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemodeploystepwidget.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeploystepwidget.h
@@ -29,6 +29,8 @@ private:
Q_SLOT void setModel(int row);
Q_SLOT void handleModelListToBeReset();
Q_SLOT void handleModelListReset();
+ Q_SLOT void addDesktopFile();
+ Q_SLOT void addIcon();
virtual void init();
virtual QString summaryText() const;
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeploystepwidget.ui b/src/plugins/qt4projectmanager/qt-maemo/maemodeploystepwidget.ui
index 73d802db90..8c00209b6e 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemodeploystepwidget.ui
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeploystepwidget.ui
@@ -13,7 +13,7 @@
<property name="windowTitle">
<string>Form</string>
</property>
- <layout class="QVBoxLayout" name="verticalLayout">
+ <layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
@@ -107,41 +107,76 @@
</layout>
</item>
<item>
- <widget class="QTableView" name="tableView">
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>150</height>
- </size>
- </property>
- <property name="textElideMode">
- <enum>Qt::ElideMiddle</enum>
- </property>
- <property name="horizontalScrollMode">
- <enum>QAbstractItemView::ScrollPerPixel</enum>
- </property>
- <property name="showGrid">
- <bool>false</bool>
- </property>
- <property name="wordWrap">
- <bool>false</bool>
- </property>
- <attribute name="horizontalHeaderDefaultSectionSize">
- <number>400</number>
- </attribute>
- <attribute name="horizontalHeaderHighlightSections">
- <bool>false</bool>
- </attribute>
- <attribute name="horizontalHeaderMinimumSectionSize">
- <number>100</number>
- </attribute>
- <attribute name="horizontalHeaderStretchLastSection">
- <bool>true</bool>
- </attribute>
- <attribute name="verticalHeaderVisible">
- <bool>false</bool>
- </attribute>
- </widget>
+ <layout class="QHBoxLayout" name="horizontalLayout_4">
+ <item>
+ <widget class="QTableView" name="tableView">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>150</height>
+ </size>
+ </property>
+ <property name="textElideMode">
+ <enum>Qt::ElideMiddle</enum>
+ </property>
+ <property name="horizontalScrollMode">
+ <enum>QAbstractItemView::ScrollPerPixel</enum>
+ </property>
+ <property name="showGrid">
+ <bool>false</bool>
+ </property>
+ <property name="wordWrap">
+ <bool>false</bool>
+ </property>
+ <attribute name="horizontalHeaderDefaultSectionSize">
+ <number>400</number>
+ </attribute>
+ <attribute name="horizontalHeaderHighlightSections">
+ <bool>false</bool>
+ </attribute>
+ <attribute name="horizontalHeaderMinimumSectionSize">
+ <number>100</number>
+ </attribute>
+ <attribute name="horizontalHeaderStretchLastSection">
+ <bool>true</bool>
+ </attribute>
+ <attribute name="verticalHeaderVisible">
+ <bool>false</bool>
+ </attribute>
+ </widget>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QPushButton" name="addDesktopFileButton">
+ <property name="text">
+ <string>Add Desktop File</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="addIconButton">
+ <property name="text">
+ <string>Add Launcher Icon ...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
</item>
</layout>
</widget>
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurations.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurations.cpp
index 8d9256506f..cdb03a51c4 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurations.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurations.cpp
@@ -64,6 +64,7 @@ namespace {
const QLatin1String PasswordKey("Password");
const QLatin1String TimeoutKey("Timeout");
const QLatin1String InternalIdKey("InternalId");
+ const QLatin1String DefaultKeyFilePathKey("DefaultKeyFile");
const QString DefaultKeyFile =
QDesktopServices::storageLocation(QDesktopServices::HomeLocation)
@@ -78,7 +79,7 @@ namespace {
const AuthType DefaultAuthType(Core::SshConnectionParameters::AuthByKey);
const int DefaultTimeout(30);
const MaemoDeviceConfig::DeviceType DefaultDeviceType(MaemoDeviceConfig::Physical);
-};
+}
class DevConfIdMatcher
{
@@ -139,7 +140,7 @@ private:
{
const int startPort = parsePort();
if (atEnd() || nextChar() != '-') {
- m_portList.addPort(startPort);
+ m_portList.addPort(startPort);
return;
}
++m_pos;
@@ -185,7 +186,8 @@ MaemoDeviceConfig::MaemoDeviceConfig(const QString &name, MaemoDeviceConfig::Dev
server.port = defaultSshPort(type);
server.uname = DefaultUserName;
server.authType = DefaultAuthType;
- server.privateKeyFile = DefaultKeyFile;
+ server.privateKeyFile
+ = MaemoDeviceConfigurations::instance().defaultSshKeyFilePath();
server.timeout = DefaultTimeout;
}
@@ -283,6 +285,7 @@ void MaemoDeviceConfigurations::save()
QSettings *settings = Core::ICore::instance()->settings();
settings->beginGroup(SettingsGroup);
settings->setValue(IdCounterKey, m_nextId);
+ settings->setValue(DefaultKeyFilePathKey, m_defaultSshKeyFilePath);
settings->beginWriteArray(ConfigListKey, m_devConfigs.count());
for (int i = 0; i < m_devConfigs.count(); ++i) {
settings->setArrayIndex(i);
@@ -303,6 +306,8 @@ void MaemoDeviceConfigurations::load()
QSettings *settings = Core::ICore::instance()->settings();
settings->beginGroup(SettingsGroup);
m_nextId = settings->value(IdCounterKey, 1).toULongLong();
+ m_defaultSshKeyFilePath
+ = settings->value(DefaultKeyFilePathKey, DefaultKeyFile).toString();
int count = settings->beginReadArray(ConfigListKey);
for (int i = 0; i < count; ++i) {
settings->setArrayIndex(i);
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurations.h b/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurations.h
index 1426d16718..84160b134f 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurations.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurations.h
@@ -72,6 +72,19 @@ public:
m_ranges.removeFirst();
return next;
}
+ QString toString() const
+ {
+ QString stringRep;
+ foreach (const Range &range, m_ranges) {
+ stringRep += QString::number(range.first);
+ if (range.second != range.first)
+ stringRep += QLatin1Char('-') + QString::number(range.second);
+ stringRep += QLatin1Char(',');
+ }
+ if (!stringRep.isEmpty())
+ stringRep.remove(stringRep.length() - 1, 1); // Trailing comma.
+ return stringRep;
+ }
private:
QList<Range> m_ranges;
@@ -124,11 +137,16 @@ class MaemoDeviceConfigurations : public QObject
public:
static MaemoDeviceConfigurations &instance(QObject *parent = 0);
+
QList<MaemoDeviceConfig> devConfigs() const { return m_devConfigs; }
void setDevConfigs(const QList<MaemoDeviceConfig> &devConfigs);
+
MaemoDeviceConfig find(const QString &name) const;
MaemoDeviceConfig find(quint64 id) const;
+ void setDefaultSshKeyFilePath(const QString &path) { m_defaultSshKeyFilePath = path; }
+ QString defaultSshKeyFilePath() const { return m_defaultSshKeyFilePath; }
+
signals:
void updated();
@@ -140,6 +158,7 @@ private:
static MaemoDeviceConfigurations *m_instance;
QList<MaemoDeviceConfig> m_devConfigs;
quint64 m_nextId;
+ QString m_defaultSshKeyFilePath;
friend class MaemoDeviceConfig;
};
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurationssettingswidget.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurationssettingswidget.cpp
new file mode 100644
index 0000000000..23142e3434
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurationssettingswidget.cpp
@@ -0,0 +1,507 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of Qt Creator.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file 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 "maemodeviceconfigurationssettingswidget.h"
+
+#include "ui_maemodeviceconfigurationssettingswidget.h"
+
+#include "maemoconfigtestdialog.h"
+#include "maemodeviceconfigurations.h"
+#include "maemoremoteprocessesdialog.h"
+#include "maemosshconfigdialog.h"
+
+#include <coreplugin/icore.h>
+#include <coreplugin/ssh/sshremoteprocessrunner.h>
+
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+#include <QtCore/QRegExp>
+#include <QtCore/QSettings>
+#include <QtCore/QTextStream>
+
+#include <QtGui/QFileDialog>
+#include <QtGui/QMessageBox>
+#include <QtGui/QIntValidator>
+
+#include <algorithm>
+
+using namespace Core;
+
+namespace Qt4ProjectManager {
+namespace Internal {
+namespace {
+const QLatin1String LastDeviceConfigIndexKey("LastDisplayedMaemoDeviceConfig");
+} // anonymous namespace
+
+bool configNameExists(const QList<MaemoDeviceConfig> &devConfs,
+ const QString &name)
+{
+ return std::find_if(devConfs.constBegin(), devConfs.constEnd(),
+ DevConfNameMatcher(name)) != devConfs.constEnd();
+}
+
+class NameValidator : public QValidator
+{
+public:
+ NameValidator(const QList<MaemoDeviceConfig> &devConfs, QWidget *parent = 0)
+ : QValidator(parent), m_devConfs(devConfs)
+ {
+ }
+
+ void setDisplayName(const QString &name) { m_oldName = name; }
+
+ virtual State validate(QString &input, int & /* pos */) const
+ {
+ if (input.trimmed().isEmpty()
+ || (input != m_oldName && configNameExists(m_devConfs, input)))
+ return Intermediate;
+ return Acceptable;
+ }
+
+ virtual void fixup(QString &input) const
+ {
+ int dummy = 0;
+ if (validate(input, dummy) != Acceptable)
+ input = m_oldName;
+ }
+
+private:
+ QString m_oldName;
+ const QList<MaemoDeviceConfig> &m_devConfs;
+};
+
+
+MaemoDeviceConfigurationsSettingsWidget::MaemoDeviceConfigurationsSettingsWidget(QWidget *parent)
+ : QWidget(parent),
+ m_ui(new Ui_MaemoDeviceConfigurationsSettingsWidget),
+ m_devConfs(MaemoDeviceConfigurations::instance().devConfigs()),
+ m_nameValidator(new NameValidator(m_devConfs, this)),
+ m_saveSettingsRequested(false)
+{
+ initGui();
+}
+
+MaemoDeviceConfigurationsSettingsWidget::~MaemoDeviceConfigurationsSettingsWidget()
+{
+ if (m_saveSettingsRequested) {
+ Core::ICore::instance()->settings()->setValue(LastDeviceConfigIndexKey,
+ m_ui->configurationComboBox->currentIndex());
+ MaemoDeviceConfigurations::instance().setDevConfigs(m_devConfs);
+ }
+ delete m_ui;
+}
+
+QString MaemoDeviceConfigurationsSettingsWidget::searchKeywords() const
+{
+ QString rc;
+ QTextStream(&rc) << m_ui->configurationLabel->text()
+ << ' ' << m_ui->sshPortLabel->text()
+ << ' ' << m_ui->keyButton->text()
+ << ' ' << m_ui->passwordButton->text()
+ << ' ' << m_ui->authTypeLabel->text()
+ << ' ' << m_ui->connectionTimeoutLabel->text()
+ << ' ' << m_ui->deviceButton->text()
+ << ' ' << m_ui->simulatorButton->text()
+ << ' ' << m_ui->deviceTypeLabel->text()
+ << ' ' << m_ui->deviceNameLabel->text()
+ << ' ' << m_ui->hostNameLabel->text()
+ << ' ' << m_ui->keyLabel->text()
+ << ' ' << m_ui->nameLineEdit->text()
+ << ' ' << m_ui->passwordLabel->text()
+ << ' ' << m_ui->freePortsLabel->text()
+ << ' ' << m_ui->portsWarningLabel->text()
+ << ' ' << m_ui->pwdLineEdit->text()
+ << ' ' << m_ui->timeoutSpinBox->value()
+ << ' ' << m_ui->userLineEdit->text()
+ << ' ' << m_ui->userNameLabel->text();
+ rc.remove(QLatin1Char('&'));
+ return rc;
+}
+
+void MaemoDeviceConfigurationsSettingsWidget::initGui()
+{
+ m_ui->setupUi(this);
+ m_ui->nameLineEdit->setValidator(m_nameValidator);
+ m_ui->keyFileLineEdit->setExpectedKind(Utils::PathChooser::File);
+ QRegExpValidator * const portsValidator
+ = new QRegExpValidator(QRegExp(MaemoDeviceConfig::portsRegExpr()), this);
+ m_ui->portsLineEdit->setValidator(portsValidator);
+ connect(m_ui->makeKeyFileDefaultButton, SIGNAL(clicked()),
+ SLOT(setDefaultKeyFilePath()));
+ foreach (const MaemoDeviceConfig &devConf, m_devConfs)
+ m_ui->configurationComboBox->addItem(devConf.name);
+ connect(m_ui->configurationComboBox, SIGNAL(currentIndexChanged(int)),
+ SLOT(currentConfigChanged(int)));
+ const int lastIndex = Core::ICore::instance()->settings()
+ ->value(LastDeviceConfigIndexKey, 0).toInt();
+ if (lastIndex < m_ui->configurationComboBox->count())
+ m_ui->configurationComboBox->setCurrentIndex(lastIndex);
+ currentConfigChanged(m_ui->configurationComboBox->currentIndex());
+}
+
+void MaemoDeviceConfigurationsSettingsWidget::addConfig()
+{
+ const QString prefix = tr("New Device Configuration %1", "Standard "
+ "Configuration name with number");
+ int suffix = 1;
+ QString newName;
+ bool isUnique = false;
+ do {
+ newName = prefix.arg(QString::number(suffix++));
+ isUnique = !configNameExists(m_devConfs, newName);
+ } while (!isUnique);
+
+ m_devConfs.append(MaemoDeviceConfig(newName, MaemoDeviceConfig::Physical));
+ m_ui->configurationComboBox->addItem(newName);
+ m_ui->removeConfigButton->setEnabled(true);
+ m_ui->configurationComboBox->setCurrentIndex(m_ui->configurationComboBox->count()-1);
+ m_ui->configurationComboBox->setFocus();
+}
+
+void MaemoDeviceConfigurationsSettingsWidget::deleteConfig()
+{
+ const int selectedItem = m_ui->configurationComboBox->currentIndex();
+ m_devConfs.removeAt(selectedItem);
+ m_ui->configurationComboBox->removeItem(selectedItem);
+ Q_ASSERT(m_ui->configurationComboBox->count() == m_devConfs.count());
+}
+
+void MaemoDeviceConfigurationsSettingsWidget::display(const MaemoDeviceConfig &devConfig)
+{
+ MaemoDeviceConfig *otherConfig;
+ if (devConfig.type == MaemoDeviceConfig::Physical) {
+ m_lastConfigHW = devConfig;
+ m_lastConfigSim
+ = MaemoDeviceConfig(devConfig.name, MaemoDeviceConfig::Simulator);
+ otherConfig = &m_lastConfigSim;
+ m_ui->deviceButton->setChecked(true);
+ } else {
+ m_lastConfigSim = devConfig;
+ m_lastConfigHW
+ = MaemoDeviceConfig(devConfig.name, MaemoDeviceConfig::Physical);
+ otherConfig = &m_lastConfigHW;
+ m_ui->simulatorButton->setChecked(true);
+ }
+ otherConfig->server.authType = devConfig.server.authType;
+ otherConfig->server.timeout = devConfig.server.timeout;
+ otherConfig->server.pwd = devConfig.server.pwd;
+ otherConfig->server.privateKeyFile = devConfig.server.privateKeyFile;
+ otherConfig->internalId = devConfig.internalId;
+
+ if (devConfig.server.authType == Core::SshConnectionParameters::AuthByPwd)
+ m_ui->passwordButton->setChecked(true);
+ else
+ m_ui->keyButton->setChecked(true);
+ m_ui->detailsWidget->setEnabled(true);
+ m_nameValidator->setDisplayName(devConfig.name);
+ m_ui->timeoutSpinBox->setValue(devConfig.server.timeout);
+ fillInValues();
+}
+
+void MaemoDeviceConfigurationsSettingsWidget::fillInValues()
+{
+ m_ui->nameLineEdit->setText(currentConfig().name);
+ m_ui->hostLineEdit->setText(currentConfig().server.host);
+ m_ui->sshPortSpinBox->setValue(currentConfig().server.port);
+ m_ui->portsLineEdit->setText(currentConfig().portsSpec);
+ m_ui->timeoutSpinBox->setValue(currentConfig().server.timeout);
+ m_ui->userLineEdit->setText(currentConfig().server.uname);
+ m_ui->pwdLineEdit->setText(currentConfig().server.pwd);
+ m_ui->keyFileLineEdit->setPath(currentConfig().server.privateKeyFile);
+ m_ui->showPasswordCheckBox->setChecked(false);
+ updatePortsWarningLabel();
+ const bool isSimulator
+ = currentConfig().type == MaemoDeviceConfig::Simulator;
+ m_ui->hostLineEdit->setReadOnly(isSimulator);
+ m_ui->sshPortSpinBox->setReadOnly(isSimulator);
+}
+
+void MaemoDeviceConfigurationsSettingsWidget::saveSettings()
+{
+ // We must defer this step because of a stupid bug on MacOS. See QTCREATORBUG-1675.
+ m_saveSettingsRequested = true;
+}
+
+MaemoDeviceConfig &MaemoDeviceConfigurationsSettingsWidget::currentConfig()
+{
+ Q_ASSERT(m_ui->configurationComboBox->count() == m_devConfs.count());
+ const int currenIndex = m_ui->configurationComboBox->currentIndex();
+ Q_ASSERT(currenIndex != -1);
+ Q_ASSERT(currenIndex < m_devConfs.count());
+ return m_devConfs[currenIndex];
+}
+
+void MaemoDeviceConfigurationsSettingsWidget::configNameEditingFinished()
+{
+ if (m_ui->configurationComboBox->count() == 0)
+ return;
+
+ const QString &newName = m_ui->nameLineEdit->text();
+ const int currentIndex = m_ui->configurationComboBox->currentIndex();
+ m_ui->configurationComboBox->setItemData(currentIndex, newName, Qt::DisplayRole);
+ currentConfig().name = newName;
+ m_nameValidator->setDisplayName(newName);
+}
+
+void MaemoDeviceConfigurationsSettingsWidget::deviceTypeChanged()
+{
+ const MaemoDeviceConfig::DeviceType devType =
+ m_ui->deviceButton->isChecked()
+ ? MaemoDeviceConfig::Physical
+ : MaemoDeviceConfig::Simulator;
+ if (currentConfig().type == devType)
+ return;
+
+ const QString name = currentConfig().name;
+ if (devType == MaemoDeviceConfig::Simulator) {
+ m_lastConfigHW = currentConfig();
+ currentConfig() = m_lastConfigSim;
+ } else {
+ m_lastConfigSim = currentConfig();
+ currentConfig() = m_lastConfigHW;
+ }
+ currentConfig().name = name;
+ fillInValues();
+}
+
+void MaemoDeviceConfigurationsSettingsWidget::authenticationTypeChanged()
+{
+ const bool usePassword = m_ui->passwordButton->isChecked();
+ currentConfig().server.authType
+ = usePassword ? Core::SshConnectionParameters::AuthByPwd : Core::SshConnectionParameters::AuthByKey;
+ m_ui->pwdLineEdit->setEnabled(usePassword);
+ m_ui->passwordLabel->setEnabled(usePassword);
+ m_ui->keyFileLineEdit->setEnabled(!usePassword);
+ m_ui->keyLabel->setEnabled(!usePassword);
+ m_ui->makeKeyFileDefaultButton->setEnabled(!usePassword);
+}
+
+void MaemoDeviceConfigurationsSettingsWidget::hostNameEditingFinished()
+{
+ currentConfig().server.host = m_ui->hostLineEdit->text();
+}
+
+void MaemoDeviceConfigurationsSettingsWidget::sshPortEditingFinished()
+{
+ currentConfig().server.port = m_ui->sshPortSpinBox->value();
+}
+
+void MaemoDeviceConfigurationsSettingsWidget::handleFreePortsChanged()
+{
+ currentConfig().portsSpec = m_ui->portsLineEdit->text();
+ updatePortsWarningLabel();
+}
+
+void MaemoDeviceConfigurationsSettingsWidget::timeoutEditingFinished()
+{
+ currentConfig().server.timeout = m_ui->timeoutSpinBox->value();
+}
+
+void MaemoDeviceConfigurationsSettingsWidget::userNameEditingFinished()
+{
+ currentConfig().server.uname = m_ui->userLineEdit->text();
+}
+
+void MaemoDeviceConfigurationsSettingsWidget::passwordEditingFinished()
+{
+ currentConfig().server.pwd = m_ui->pwdLineEdit->text();
+}
+
+void MaemoDeviceConfigurationsSettingsWidget::keyFileEditingFinished()
+{
+ currentConfig().server.privateKeyFile = m_ui->keyFileLineEdit->path();
+}
+
+void MaemoDeviceConfigurationsSettingsWidget::showPassword(bool showClearText)
+{
+ m_ui->pwdLineEdit->setEchoMode(showClearText
+ ? QLineEdit::Normal : QLineEdit::Password);
+}
+
+void MaemoDeviceConfigurationsSettingsWidget::testConfig()
+{
+ QDialog *dialog = new MaemoConfigTestDialog(currentConfig(), this);
+ dialog->open();
+}
+
+void MaemoDeviceConfigurationsSettingsWidget::showGenerateSshKeyDialog()
+{
+ MaemoSshConfigDialog dialog(this);
+ dialog.exec();
+}
+
+void MaemoDeviceConfigurationsSettingsWidget::showRemoteProcesses()
+{
+ MaemoRemoteProcessesDialog dlg(currentConfig().server, this);
+ dlg.exec();
+}
+
+void MaemoDeviceConfigurationsSettingsWidget::setDefaultKeyFilePath()
+{
+ MaemoDeviceConfigurations::instance()
+ .setDefaultSshKeyFilePath(m_ui->keyFileLineEdit->path());
+}
+
+void MaemoDeviceConfigurationsSettingsWidget::setPrivateKey(const QString &path)
+{
+ m_ui->keyFileLineEdit->setPath(path);
+ keyFileEditingFinished();
+}
+
+void MaemoDeviceConfigurationsSettingsWidget::deployKey()
+{
+ if (m_keyDeployer)
+ return;
+
+ const QString &dir
+ = QFileInfo(currentConfig().server.privateKeyFile).path();
+ QString publicKeyFileName = QFileDialog::getOpenFileName(this,
+ tr("Choose Public Key File"), dir,
+ tr("Public Key Files(*.pub);;All Files (*)"));
+ if (publicKeyFileName.isEmpty())
+ return;
+
+ QFile keyFile(publicKeyFileName);
+ QByteArray key;
+ const bool keyFileAccessible = keyFile.open(QIODevice::ReadOnly);
+ if (keyFileAccessible)
+ key = keyFile.readAll();
+ if (!keyFileAccessible || keyFile.error() != QFile::NoError) {
+ QMessageBox::critical(this, tr("Deployment Failed"),
+ tr("Could not read public key file '%1'.").arg(publicKeyFileName));
+ return;
+ }
+
+ disconnect(m_ui->deployKeyButton, 0, this, 0);
+ m_ui->deployKeyButton->setText(tr("Stop Deploying"));
+ connect(m_ui->deployKeyButton, SIGNAL(clicked()), this,
+ SLOT(stopDeploying()));
+
+ m_keyDeployer = SshRemoteProcessRunner::create(currentConfig().server);
+ connect(m_keyDeployer.data(), SIGNAL(connectionError(Core::SshError)), this,
+ SLOT(handleConnectionFailure()));
+ connect(m_keyDeployer.data(), SIGNAL(processClosed(int)), this,
+ SLOT(handleKeyUploadFinished(int)));
+ const QByteArray command = "test -d .ssh "
+ "|| mkdir .ssh && chmod 0700 .ssh && echo '"
+ + key + "' >> .ssh/authorized_keys";
+ m_keyDeployer->run(command);
+}
+
+void MaemoDeviceConfigurationsSettingsWidget::handleConnectionFailure()
+{
+ if (!m_keyDeployer)
+ return;
+
+ QMessageBox::critical(this, tr("Deployment Failed"),
+ tr("Could not connect to host: %1")
+ .arg(m_keyDeployer->connection()->errorString()));
+ stopDeploying();
+}
+
+void MaemoDeviceConfigurationsSettingsWidget::handleKeyUploadFinished(int exitStatus)
+{
+ Q_ASSERT(exitStatus == SshRemoteProcess::FailedToStart
+ || exitStatus == SshRemoteProcess::KilledBySignal
+ || exitStatus == SshRemoteProcess::ExitedNormally);
+
+ if (!m_keyDeployer)
+ return;
+
+ if (exitStatus == SshRemoteProcess::ExitedNormally
+ && m_keyDeployer->process()->exitCode() == 0) {
+ QMessageBox::information(this, tr("Deployment Succeeded"),
+ tr("Key was successfully deployed."));
+ } else {
+ QMessageBox::critical(this, tr("Deployment Failed"),
+ tr("Key deployment failed: %1.")
+ .arg(m_keyDeployer->process()->errorString()));
+ }
+ stopDeploying();
+}
+
+void MaemoDeviceConfigurationsSettingsWidget::stopDeploying()
+{
+ if (m_keyDeployer) {
+ disconnect(m_keyDeployer.data(), 0, this, 0);
+ m_keyDeployer = SshRemoteProcessRunner::Ptr();
+ }
+ m_ui->deployKeyButton->disconnect();
+ m_ui->deployKeyButton->setText(tr("Deploy Public Key ..."));
+ connect(m_ui->deployKeyButton, SIGNAL(clicked()), this, SLOT(deployKey()));
+}
+
+void MaemoDeviceConfigurationsSettingsWidget::currentConfigChanged(int index)
+{
+ stopDeploying();
+ if (index == -1) {
+ m_ui->removeConfigButton->setEnabled(false);
+ m_ui->testConfigButton->setEnabled(false);
+ m_ui->generateKeyButton->setEnabled(false);
+ m_ui->deployKeyButton->setEnabled(false);
+ clearDetails();
+ m_ui->detailsWidget->setEnabled(false);
+ } else {
+ m_ui->removeConfigButton->setEnabled(true);
+ m_ui->testConfigButton->setEnabled(true);
+ m_ui->generateKeyButton->setEnabled(true);
+ m_ui->deployKeyButton->setEnabled(true);
+ m_ui->configurationComboBox->setCurrentIndex(index);
+ display(currentConfig());
+ }
+}
+
+void MaemoDeviceConfigurationsSettingsWidget::clearDetails()
+{
+ m_ui->hostLineEdit->clear();
+ m_ui->sshPortSpinBox->clear();
+ m_ui->timeoutSpinBox->clear();
+ m_ui->userLineEdit->clear();
+ m_ui->pwdLineEdit->clear();
+ m_ui->portsLineEdit->clear();
+ m_ui->portsWarningLabel->clear();
+}
+
+void MaemoDeviceConfigurationsSettingsWidget::updatePortsWarningLabel()
+{
+ if (currentConfig().freePorts().hasMore()) {
+ m_ui->portsWarningLabel->clear();
+ } else {
+ m_ui->portsWarningLabel->setText(QLatin1String("<font color=\"red\">")
+ + tr("You will need at least one port.") + QLatin1String("</font>"));
+ }
+}
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurationssettingswidget.h b/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurationssettingswidget.h
new file mode 100644
index 0000000000..83bf92bac9
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurationssettingswidget.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of Qt Creator.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file 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 MAEMODEVICECONFIGURATIONSSETTINGSWIDGET_H
+#define MAEMODEVICECONFIGURATIONSSETTINGSWIDGET_H
+
+#include "maemodeviceconfigurations.h"
+
+#include <QtCore/QList>
+#include <QtCore/QSharedPointer>
+#include <QtCore/QString>
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+class QLineEdit;
+
+class Ui_MaemoDeviceConfigurationsSettingsWidget;
+QT_END_NAMESPACE
+
+namespace Core {
+class SshRemoteProcessRunner;
+}
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+class NameValidator;
+
+class MaemoDeviceConfigurationsSettingsWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ MaemoDeviceConfigurationsSettingsWidget(QWidget *parent);
+ ~MaemoDeviceConfigurationsSettingsWidget();
+
+ void saveSettings();
+ QString searchKeywords() const;
+
+private slots:
+ void currentConfigChanged(int index);
+ void addConfig();
+ void deleteConfig();
+ void configNameEditingFinished();
+ void deviceTypeChanged();
+ void authenticationTypeChanged();
+ void hostNameEditingFinished();
+ void sshPortEditingFinished();
+ void timeoutEditingFinished();
+ void userNameEditingFinished();
+ void passwordEditingFinished();
+ void keyFileEditingFinished();
+ void showPassword(bool showClearText);
+ void handleFreePortsChanged();
+ void showRemoteProcesses();
+ void setDefaultKeyFilePath();
+
+ // For configuration testing.
+ void testConfig();
+
+ void showGenerateSshKeyDialog();
+ void setPrivateKey(const QString &path);
+
+ // For key deploying.
+ void deployKey();
+ void stopDeploying();
+ void handleConnectionFailure();
+ void handleKeyUploadFinished(int exitStatus);
+
+private:
+ void initGui();
+ void display(const MaemoDeviceConfig &devConfig);
+ MaemoDeviceConfig &currentConfig();
+ void clearDetails();
+ QString parseTestOutput();
+ void fillInValues();
+ void updatePortsWarningLabel();
+
+ Ui_MaemoDeviceConfigurationsSettingsWidget *m_ui;
+ QList<MaemoDeviceConfig> m_devConfs;
+ MaemoDeviceConfig m_lastConfigHW;
+ MaemoDeviceConfig m_lastConfigSim;
+ NameValidator * const m_nameValidator;
+ QSharedPointer<Core::SshRemoteProcessRunner> m_keyDeployer;
+ bool m_saveSettingsRequested;
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // MAEMODEVICECONFIGURATIONSSETTINGSWIDGET_H
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurationssettingswidget.ui b/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurationssettingswidget.ui
new file mode 100644
index 0000000000..0dca479178
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurationssettingswidget.ui
@@ -0,0 +1,816 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MaemoDeviceConfigurationsSettingsWidget</class>
+ <widget class="QWidget" name="MaemoDeviceConfigurationsSettingsWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>602</width>
+ <height>421</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Maemo Device Configurations</string>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <layout class="QFormLayout" name="formLayout">
+ <property name="fieldGrowthPolicy">
+ <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
+ </property>
+ <item row="0" column="0">
+ <widget class="QLabel" name="configurationLabel">
+ <property name="text">
+ <string>&amp;Configuration:</string>
+ </property>
+ <property name="buddy">
+ <cstring>configurationComboBox</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="configurationComboBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="editable">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QFrame" name="frame">
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QWidget" name="detailsWidget" native="true">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <layout class="QFormLayout" name="formLayout_2">
+ <item row="0" column="0">
+ <widget class="QLabel" name="deviceNameLabel">
+ <property name="text">
+ <string>&amp;Name</string>
+ </property>
+ <property name="buddy">
+ <cstring>nameLineEdit</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="nameLineEdit"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="deviceTypeLabel">
+ <property name="text">
+ <string>Device type:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QWidget" name="deviceTypeButtonsWidget" native="true">
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QRadioButton" name="deviceButton">
+ <property name="text">
+ <string>Remote device</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="simulatorButton">
+ <property name="text">
+ <string>Maemo &amp;emulator</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="authTypeLabel">
+ <property name="text">
+ <string>Authentication type:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QWidget" name="authTypeButtonsWidget" native="true">
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QRadioButton" name="passwordButton">
+ <property name="text">
+ <string>Password</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="keyButton">
+ <property name="text">
+ <string>&amp;Key</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="hostNameLabel">
+ <property name="text">
+ <string>&amp;Host name:</string>
+ </property>
+ <property name="buddy">
+ <cstring>hostLineEdit</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QLineEdit" name="hostLineEdit">
+ <property name="placeholderText">
+ <string>IP or host name of the device</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0">
+ <widget class="QLabel" name="sshPortLabel">
+ <property name="text">
+ <string>&amp;SSH port:</string>
+ </property>
+ <property name="buddy">
+ <cstring>sshPortSpinBox</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout_4">
+ <item>
+ <widget class="QSpinBox" name="sshPortSpinBox">
+ <property name="minimum">
+ <number>0</number>
+ </property>
+ <property name="maximum">
+ <number>65535</number>
+ </property>
+ <property name="value">
+ <number>22</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item row="5" column="0">
+ <widget class="QLabel" name="freePortsLabel">
+ <property name="text">
+ <string>Free ports:</string>
+ </property>
+ <property name="buddy">
+ <cstring>portsLineEdit</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout_7">
+ <item>
+ <widget class="QLineEdit" name="portsLineEdit">
+ <property name="toolTip">
+ <string>You can enter lists and ranges like this: 1024,1026-1028,1030</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="portsWarningLabel">
+ <property name="text">
+ <string>TextLabel</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item row="6" column="0">
+ <widget class="QLabel" name="connectionTimeoutLabel">
+ <property name="text">
+ <string>Connection time&amp;out:</string>
+ </property>
+ <property name="buddy">
+ <cstring>timeoutSpinBox</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout_5">
+ <item>
+ <widget class="QSpinBox" name="timeoutSpinBox">
+ <property name="suffix">
+ <string>s</string>
+ </property>
+ <property name="maximum">
+ <number>10000</number>
+ </property>
+ <property name="singleStep">
+ <number>10</number>
+ </property>
+ <property name="value">
+ <number>1000</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item row="7" column="0">
+ <widget class="QLabel" name="userNameLabel">
+ <property name="text">
+ <string>&amp;Username:</string>
+ </property>
+ <property name="buddy">
+ <cstring>userLineEdit</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="1">
+ <widget class="QLineEdit" name="userLineEdit"/>
+ </item>
+ <item row="8" column="0">
+ <widget class="QLabel" name="passwordLabel">
+ <property name="text">
+ <string>&amp;Password:</string>
+ </property>
+ <property name="buddy">
+ <cstring>pwdLineEdit</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout_6">
+ <item>
+ <widget class="QLineEdit" name="pwdLineEdit">
+ <property name="echoMode">
+ <enum>QLineEdit::Password</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="showPasswordCheckBox">
+ <property name="text">
+ <string>Show password</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="9" column="0">
+ <widget class="QLabel" name="keyLabel">
+ <property name="text">
+ <string>Private key &amp;file:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="9" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout_8">
+ <item>
+ <widget class="Utils::PathChooser" name="keyFileLineEdit" native="true"/>
+ </item>
+ <item>
+ <widget class="QPushButton" name="makeKeyFileDefaultButton">
+ <property name="text">
+ <string>Set as Default</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QPushButton" name="addConfigButton">
+ <property name="text">
+ <string>&amp;Add</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="removeConfigButton">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>&amp;Remove</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="testConfigButton">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>&amp;Test</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="generateKeyButton">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>&amp;Generate SSH Key ...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="deployKeyButton">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>&amp;Deploy Public Key ...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="remoteProcessesButton">
+ <property name="text">
+ <string>Remote Processes ...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>Utils::PathChooser</class>
+ <extends>QWidget</extends>
+ <header location="global">utils/pathchooser.h</header>
+ <container>1</container>
+ <slots>
+ <signal>editingFinished()</signal>
+ <signal>browsingFinished()</signal>
+ </slots>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>deviceButton</sender>
+ <signal>clicked(bool)</signal>
+ <receiver>MaemoDeviceConfigurationsSettingsWidget</receiver>
+ <slot>deviceTypeChanged()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>231</x>
+ <y>99</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>511</x>
+ <y>279</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>hostLineEdit</sender>
+ <signal>editingFinished()</signal>
+ <receiver>MaemoDeviceConfigurationsSettingsWidget</receiver>
+ <slot>hostNameEditingFinished()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>335</x>
+ <y>148</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>424</x>
+ <y>231</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>userLineEdit</sender>
+ <signal>editingFinished()</signal>
+ <receiver>MaemoDeviceConfigurationsSettingsWidget</receiver>
+ <slot>userNameEditingFinished()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>430</x>
+ <y>274</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>422</x>
+ <y>301</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>pwdLineEdit</sender>
+ <signal>editingFinished()</signal>
+ <receiver>MaemoDeviceConfigurationsSettingsWidget</receiver>
+ <slot>passwordEditingFinished()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>306</x>
+ <y>302</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>423</x>
+ <y>336</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>simulatorButton</sender>
+ <signal>clicked(bool)</signal>
+ <receiver>MaemoDeviceConfigurationsSettingsWidget</receiver>
+ <slot>deviceTypeChanged()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>335</x>
+ <y>99</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>426</x>
+ <y>87</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>addConfigButton</sender>
+ <signal>clicked()</signal>
+ <receiver>MaemoDeviceConfigurationsSettingsWidget</receiver>
+ <slot>addConfig()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>465</x>
+ <y>27</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>516</x>
+ <y>118</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>removeConfigButton</sender>
+ <signal>clicked()</signal>
+ <receiver>MaemoDeviceConfigurationsSettingsWidget</receiver>
+ <slot>deleteConfig()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>473</x>
+ <y>61</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>513</x>
+ <y>101</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>passwordButton</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>MaemoDeviceConfigurationsSettingsWidget</receiver>
+ <slot>authenticationTypeChanged()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>231</x>
+ <y>122</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>513</x>
+ <y>240</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>keyFileLineEdit</sender>
+ <signal>editingFinished()</signal>
+ <receiver>MaemoDeviceConfigurationsSettingsWidget</receiver>
+ <slot>keyFileEditingFinished()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>430</x>
+ <y>323</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>257</x>
+ <y>185</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>keyFileLineEdit</sender>
+ <signal>browsingFinished()</signal>
+ <receiver>MaemoDeviceConfigurationsSettingsWidget</receiver>
+ <slot>keyFileEditingFinished()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>430</x>
+ <y>323</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>257</x>
+ <y>185</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>testConfigButton</sender>
+ <signal>clicked()</signal>
+ <receiver>MaemoDeviceConfigurationsSettingsWidget</receiver>
+ <slot>testConfig()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>473</x>
+ <y>90</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>428</x>
+ <y>351</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>deployKeyButton</sender>
+ <signal>clicked()</signal>
+ <receiver>MaemoDeviceConfigurationsSettingsWidget</receiver>
+ <slot>deployKey()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>473</x>
+ <y>148</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>510</x>
+ <y>351</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>keyButton</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>MaemoDeviceConfigurationsSettingsWidget</receiver>
+ <slot>authenticationTypeChanged()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>335</x>
+ <y>122</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>525</x>
+ <y>351</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>nameLineEdit</sender>
+ <signal>editingFinished()</signal>
+ <receiver>MaemoDeviceConfigurationsSettingsWidget</receiver>
+ <slot>configNameEditingFinished()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>237</x>
+ <y>75</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>330</x>
+ <y>332</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>generateKeyButton</sender>
+ <signal>clicked()</signal>
+ <receiver>MaemoDeviceConfigurationsSettingsWidget</receiver>
+ <slot>showGenerateSshKeyDialog()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>585</x>
+ <y>131</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>358</x>
+ <y>0</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>timeoutSpinBox</sender>
+ <signal>editingFinished()</signal>
+ <receiver>MaemoDeviceConfigurationsSettingsWidget</receiver>
+ <slot>timeoutEditingFinished()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>217</x>
+ <y>245</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>6</x>
+ <y>333</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>timeoutSpinBox</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>MaemoDeviceConfigurationsSettingsWidget</receiver>
+ <slot>timeoutEditingFinished()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>217</x>
+ <y>245</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>0</x>
+ <y>299</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>sshPortSpinBox</sender>
+ <signal>editingFinished()</signal>
+ <receiver>MaemoDeviceConfigurationsSettingsWidget</receiver>
+ <slot>sshPortEditingFinished()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>210</x>
+ <y>189</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>4</x>
+ <y>211</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>sshPortSpinBox</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>MaemoDeviceConfigurationsSettingsWidget</receiver>
+ <slot>sshPortEditingFinished()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>210</x>
+ <y>189</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>3</x>
+ <y>136</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>showPasswordCheckBox</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>MaemoDeviceConfigurationsSettingsWidget</receiver>
+ <slot>showPassword(bool)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>429</x>
+ <y>301</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>3</x>
+ <y>262</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>portsLineEdit</sender>
+ <signal>editingFinished()</signal>
+ <receiver>MaemoDeviceConfigurationsSettingsWidget</receiver>
+ <slot>handleFreePortsChanged()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>259</x>
+ <y>218</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>0</x>
+ <y>393</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>remoteProcessesButton</sender>
+ <signal>clicked()</signal>
+ <receiver>MaemoDeviceConfigurationsSettingsWidget</receiver>
+ <slot>showRemoteProcesses()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>591</x>
+ <y>198</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>598</x>
+ <y>378</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+ <slots>
+ <slot>configNameEditingFinished()</slot>
+ <slot>deviceTypeChanged()</slot>
+ <slot>hostNameEditingFinished()</slot>
+ <slot>sshPortEditingFinished()</slot>
+ <slot>timeoutEditingFinished()</slot>
+ <slot>userNameEditingFinished()</slot>
+ <slot>passwordEditingFinished()</slot>
+ <slot>addConfig()</slot>
+ <slot>selectionChanged()</slot>
+ <slot>deleteConfig()</slot>
+ <slot>authenticationTypeChanged()</slot>
+ <slot>keyFileEditingFinished()</slot>
+ <slot>testConfig()</slot>
+ <slot>deployKey()</slot>
+ <slot>gdbServerPortEditingFinished()</slot>
+ <slot>currentConfigChanged(int)</slot>
+ <slot>showGenerateSshKeyDialog()</slot>
+ <slot>showPassword(bool)</slot>
+ <slot>handleFreePortsChanged()</slot>
+ <slot>showRemoteProcesses()</slot>
+ </slots>
+</ui>
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeviceenvreader.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemodeviceenvreader.cpp
index 9275ec81d3..25ff7ba7a4 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemodeviceenvreader.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeviceenvreader.cpp
@@ -37,8 +37,7 @@
#include "maemoglobal.h"
#include "maemorunconfiguration.h"
-#include <coreplugin/ssh/sshconnection.h>
-#include <coreplugin/ssh/sshremoteprocess.h>
+#include <coreplugin/ssh/sshremoteprocessrunner.h>
namespace Qt4ProjectManager {
namespace Internal {
@@ -60,71 +59,53 @@ MaemoDeviceEnvReader::~MaemoDeviceEnvReader()
void MaemoDeviceEnvReader::start()
{
m_stop = false;
- if (m_connection)
- disconnect(m_connection.data(), 0, this, 0);
-
- const bool reuse = m_connection
- && m_connection->state() == Core::SshConnection::Connected
- && m_connection->connectionParameters() == m_devConfig.server;
-
- if (!reuse)
- m_connection = Core::SshConnection::create();
-
- connect(m_connection.data(), SIGNAL(connected()), this,
- SLOT(executeRemoteCall()));
- connect(m_connection.data(), SIGNAL(error(Core::SshError)), this,
+ if (!m_remoteProcessRunner
+ || m_remoteProcessRunner->connection()->state() != Core::SshConnection::Connected
+ || m_remoteProcessRunner->connection()->connectionParameters() != m_devConfig.server) {
+ m_remoteProcessRunner
+ = Core::SshRemoteProcessRunner::create(m_devConfig.server);
+ }
+ connect(m_remoteProcessRunner.data(),
+ SIGNAL(connectionError(Core::SshError)), this,
SLOT(handleConnectionFailure()));
-
- if (reuse)
- executeRemoteCall();
- else
- m_connection->connectToHost(m_devConfig.server);
+ connect(m_remoteProcessRunner.data(), SIGNAL(processClosed(int)), this,
+ SLOT(remoteProcessFinished(int)));
+ connect(m_remoteProcessRunner.data(),
+ SIGNAL(processOutputAvailable(QByteArray)), this,
+ SLOT(remoteOutput(QByteArray)));
+ connect(m_remoteProcessRunner.data(),
+ SIGNAL(processErrorOutputAvailable(QByteArray)), this,
+ SLOT(remoteErrorOutput(QByteArray)));
+ const QByteArray remoteCall = MaemoGlobal::remoteSourceProfilesCommand()
+ .toUtf8() + "; env";
+ m_remoteOutput.clear();
+ m_remoteProcessRunner->run(remoteCall);
}
void MaemoDeviceEnvReader::stop()
{
m_stop = true;
-
- if (m_connection)
- disconnect(m_connection.data(), 0, this, 0);
- if (m_remoteProcess) {
- disconnect(m_remoteProcess.data());
- m_remoteProcess->closeChannel();
- }
+ if (m_remoteProcessRunner)
+ disconnect(m_remoteProcessRunner.data(), 0, this, 0);
}
-void MaemoDeviceEnvReader::executeRemoteCall()
+void MaemoDeviceEnvReader::handleConnectionFailure()
{
if (m_stop)
return;
- const QByteArray remoteCall = MaemoGlobal::remoteSourceProfilesCommand()
- .toUtf8() + "; env";
- m_remoteProcess = m_connection->createRemoteProcess(remoteCall);
-
- connect(m_remoteProcess.data(), SIGNAL(closed(int)), this,
- SLOT(remoteProcessFinished(int)));
- connect(m_remoteProcess.data(), SIGNAL(outputAvailable(QByteArray)), this,
- SLOT(remoteOutput(QByteArray)));
- connect(m_remoteProcess.data(), SIGNAL(errorOutputAvailable(QByteArray)), this,
- SLOT(remoteErrorOutput(QByteArray)));
-
- m_remoteOutput.clear();
- m_remoteErrorOutput.clear();
- m_remoteProcess->start();
-}
-
-void MaemoDeviceEnvReader::handleConnectionFailure()
-{
- emit error(tr("Could not connect to host: %1")
- .arg(m_connection->errorString()));
- setFinished();
+ disconnect(m_remoteProcessRunner.data(), 0, this, 0);
+ emit error(tr("Connection error: %1")
+ .arg(m_remoteProcessRunner->connection()->errorString()));
+ emit finished();
}
void MaemoDeviceEnvReader::handleCurrentDeviceConfigChanged()
{
m_devConfig = m_runConfig->deviceConfig();
+ if (m_remoteProcessRunner)
+ disconnect(m_remoteProcessRunner.data(), 0, this, 0);
m_env.clear();
setFinished();
}
@@ -138,6 +119,7 @@ void MaemoDeviceEnvReader::remoteProcessFinished(int exitCode)
if (m_stop)
return;
+ disconnect(m_remoteProcessRunner.data(), 0, this, 0);
m_env.clear();
if (exitCode == Core::SshRemoteProcess::ExitedNormally) {
if (!m_remoteOutput.isEmpty()) {
@@ -146,7 +128,7 @@ void MaemoDeviceEnvReader::remoteProcessFinished(int exitCode)
}
} else {
QString errorMsg = tr("Error running remote process: %1")
- .arg(m_remoteProcess->errorString());
+ .arg(m_remoteProcessRunner->process()->errorString());
if (!m_remoteErrorOutput.isEmpty()) {
errorMsg += tr("\nRemote stderr was: '%1'")
.arg(QString::fromUtf8(m_remoteErrorOutput));
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeviceenvreader.h b/src/plugins/qt4projectmanager/qt-maemo/maemodeviceenvreader.h
index d31c6b0427..31d7f4c0bc 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemodeviceenvreader.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeviceenvreader.h
@@ -42,8 +42,7 @@
#include <QtCore/QObject>
namespace Core {
- class SshConnection;
- class SshRemoteProcess;
+ class SshRemoteProcessRunner;
}
namespace Qt4ProjectManager {
@@ -68,7 +67,6 @@ signals:
void error(const QString &error);
private slots:
- void executeRemoteCall();
void handleConnectionFailure();
void handleCurrentDeviceConfigChanged();
@@ -85,8 +83,7 @@ private:
Utils::Environment m_env;
MaemoDeviceConfig m_devConfig;
MaemoRunConfiguration *m_runConfig;
- QSharedPointer<Core::SshConnection> m_connection;
- QSharedPointer<Core::SshRemoteProcess> m_remoteProcess;
+ QSharedPointer<Core::SshRemoteProcessRunner> m_remoteProcessRunner;
};
} // Internal
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoglobal.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemoglobal.cpp
index 1cadb0e25f..bc677cff89 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemoglobal.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoglobal.cpp
@@ -33,10 +33,25 @@
#include "maemoglobal.h"
+#include "maemoconstants.h"
+#include "maemodeviceconfigurations.h"
+
+#include <coreplugin/ssh/sshconnection.h>
+#include <utils/environment.h>
+
+#include <QtCore/QCoreApplication>
+#include <QtGui/QDesktopServices>
+#include <QtCore/QDir>
+#include <QtCore/QProcess>
#include <QtCore/QString>
+#define TR(text) QCoreApplication::translate("Qt4ProjectManager::Internal::MaemoGlobal", text)
+
namespace Qt4ProjectManager {
namespace Internal {
+namespace {
+static const QLatin1String binQmake("/bin/qmake" EXEC_SUFFIX);
+}
QString MaemoGlobal::homeDirOnDevice(const QString &uname)
{
@@ -75,9 +90,83 @@ QString MaemoGlobal::remoteEnvironment(const QList<Utils::EnvironmentItem> &list
return env.mid(0, env.size() - 1);
}
-QString MaemoGlobal::remoteProjectSourcesMountPoint()
+QString MaemoGlobal::failedToConnectToServerMessage(const Core::SshConnection::Ptr &connection,
+ const MaemoDeviceConfig &deviceConfig)
+{
+ QString errorMsg = TR("Could not connect to host: %1")
+ .arg(connection->errorString());
+
+ if (deviceConfig.type == MaemoDeviceConfig::Simulator) {
+ if (connection->errorState() == Core::SshTimeoutError
+ || connection->errorState() == Core::SshSocketError) {
+ errorMsg += TR("\nDid you start Qemu?");
+ }
+ } else if (connection->errorState() == Core::SshTimeoutError) {
+ errorMsg += TR("\nIs the device connected and set up for network access?");
+ }
+ return errorMsg;
+}
+
+QString MaemoGlobal::maddeRoot(const QString &qmakePath)
+{
+ QDir dir(QDir::cleanPath(qmakePath).remove(binQmake));
+ dir.cdUp(); dir.cdUp();
+ return dir.absolutePath();
+}
+
+QString MaemoGlobal::targetName(const QString &qmakePath)
+{
+ const QString target = QDir::cleanPath(qmakePath).remove(binQmake);
+ return target.mid(target.lastIndexOf(QLatin1Char('/')) + 1);
+}
+
+bool MaemoGlobal::removeRecursively(const QString &filePath, QString &error)
+{
+ QFileInfo fileInfo(filePath);
+ if (!fileInfo.exists())
+ return true;
+ QFile::setPermissions(filePath, fileInfo.permissions() | QFile::WriteUser);
+ if (fileInfo.isDir()) {
+ QDir dir(filePath);
+ QStringList fileNames = dir.entryList(QDir::Files | QDir::Hidden
+ | QDir::System | QDir::Dirs | QDir::NoDotAndDotDot);
+ foreach (const QString &fileName, fileNames) {
+ if (!removeRecursively(filePath + QLatin1Char('/') + fileName, error))
+ return false;
+ }
+ dir.cdUp();
+ if (!dir.rmdir(fileInfo.fileName())) {
+ error = TR("Failed to remove directory '%1'.")
+ .arg(QDir::toNativeSeparators(filePath));
+ return false;
+ }
+ } else {
+ if (!QFile::remove(filePath)) {
+ error = TR("Failed to remove file '%1'.")
+ .arg(QDir::toNativeSeparators(filePath));
+ return false;
+ }
+ }
+ return true;
+}
+
+void MaemoGlobal::callMaddeShellScript(QProcess &proc, const QString &maddeRoot,
+ const QString &command, const QStringList &args)
{
- return QLatin1String("/tmp/gdbSourcesDir");
+ QString actualCommand = command;
+ QStringList actualArgs = args;
+#ifdef Q_OS_WIN
+ Utils::Environment env(proc.systemEnvironment());
+ env.prependOrSetPath(maddeRoot + QLatin1String("/bin"));
+ env.prependOrSet(QLatin1String("HOME"),
+ QDesktopServices::storageLocation(QDesktopServices::HomeLocation));
+ proc.setEnvironment(env.toStringList());
+ actualArgs.prepend(command);
+ actualCommand = maddeRoot + QLatin1String("/bin/sh.exe");
+#else
+ Q_UNUSED(maddeRoot);
+#endif
+ proc.start(actualCommand, actualArgs);
}
} // namespace Internal
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoglobal.h b/src/plugins/qt4projectmanager/qt-maemo/maemoglobal.h
index 4523bd16ee..efa49d9585 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemoglobal.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoglobal.h
@@ -41,13 +41,21 @@
#include <projectexplorer/projectexplorerconstants.h>
#include <QtCore/QList>
+#include <QtCore/QSharedPointer>
+
+#define ASSERT_STATE_GENERIC(State, expected, actual) \
+ MaemoGlobal::assertState<State>(expected, actual, Q_FUNC_INFO)
QT_BEGIN_NAMESPACE
+class QProcess;
class QString;
QT_END_NAMESPACE
+namespace Core { class SshConnection; }
+
namespace Qt4ProjectManager {
namespace Internal {
+class MaemoDeviceConfig;
class MaemoGlobal
{
@@ -56,8 +64,15 @@ public:
static QString remoteSudo();
static QString remoteCommandPrefix(const QString &commandFilePath);
static QString remoteEnvironment(const QList<Utils::EnvironmentItem> &list);
- static QString remoteProjectSourcesMountPoint();
static QString remoteSourceProfilesCommand();
+ static QString failedToConnectToServerMessage(const QSharedPointer<Core::SshConnection> &connection,
+ const MaemoDeviceConfig &deviceConfig);
+ static QString maddeRoot(const QString &qmakePath);
+ static QString targetName(const QString &qmakePath);
+
+ static bool removeRecursively(const QString &filePath, QString &error);
+ static void callMaddeShellScript(QProcess &proc, const QString &maddeRoot,
+ const QString &command, const QStringList &args);
template<class T> static T *buildStep(const ProjectExplorer::DeployConfiguration *dc)
{
@@ -71,6 +86,21 @@ public:
}
return 0;
}
+
+ template<typename State> static void assertState(State expected,
+ State actual, const char *func)
+ {
+ assertState(QList<State>() << expected, actual, func);
+ }
+
+ template<typename State> static void assertState(const QList<State> &expected,
+ State actual, const char *func)
+ {
+ if (!expected.contains(actual)) {
+ qWarning("Warning: Unexpected state %d in function %s.",
+ actual, func);
+ }
+ }
};
} // namespace Internal
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemomanager.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemomanager.cpp
index 04c6430bb0..ace6c27f0f 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemomanager.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemomanager.cpp
@@ -36,10 +36,12 @@
#include "maemoconstants.h"
#include "maemodeploystepfactory.h"
#include "maemodeviceconfigurations.h"
+#include "maemoglobal.h"
#include "maemopackagecreationfactory.h"
+#include "maemopublishingwizardfactories.h"
#include "maemoqemumanager.h"
#include "maemorunfactories.h"
-#include "maemosettingspage.h"
+#include "maemosettingspages.h"
#include "maemotemplatesmanager.h"
#include "maemotoolchain.h"
@@ -64,7 +66,9 @@ MaemoManager::MaemoManager()
, m_runConfigurationFactory(new MaemoRunConfigurationFactory(this))
, m_packageCreationFactory(new MaemoPackageCreationFactory(this))
, m_deployStepFactory(new MaemoDeployStepFactory(this))
- , m_settingsPage(new MaemoSettingsPage(this))
+ , m_deviceConfigurationsSettingsPage(new MaemoDeviceConfigurationsSettingsPage(this))
+ , m_qemuSettingsPage(new MaemoQemuSettingsPage(this))
+ , m_publishingFactoryFremantleFree(new MaemoPublishingWizardFactoryFremantleFree(this))
{
Q_ASSERT(!m_instance);
@@ -78,17 +82,22 @@ MaemoManager::MaemoManager()
pluginManager->addObject(m_runConfigurationFactory);
pluginManager->addObject(m_packageCreationFactory);
pluginManager->addObject(m_deployStepFactory);
- pluginManager->addObject(m_settingsPage);
+ pluginManager->addObject(m_deviceConfigurationsSettingsPage);
+ pluginManager->addObject(m_qemuSettingsPage);
+ pluginManager->addObject(m_publishingFactoryFremantleFree);
}
MaemoManager::~MaemoManager()
{
+ // TODO: Remove in reverse order of adding.
PluginManager *pluginManager = PluginManager::instance();
pluginManager->removeObject(m_runControlFactory);
pluginManager->removeObject(m_runConfigurationFactory);
pluginManager->removeObject(m_deployStepFactory);
pluginManager->removeObject(m_packageCreationFactory);
- pluginManager->removeObject(m_settingsPage);
+ pluginManager->removeObject(m_deviceConfigurationsSettingsPage);
+ pluginManager->removeObject(m_qemuSettingsPage);
+ pluginManager->removeObject(m_publishingFactoryFremantleFree);
m_instance = 0;
}
@@ -106,25 +115,14 @@ bool MaemoManager::isValidMaemoQtVersion(const QtVersion *version) const
QDir dir(path);
const QByteArray target = dir.dirName().toAscii();
dir.cdUp(); dir.cdUp();
- QString madAdminCommand(dir.absolutePath() + QLatin1String("/bin/mad-admin"));
+ const QString madAdminCommand(dir.absolutePath() + QLatin1String("/bin/mad-admin"));
if (!QFileInfo(madAdminCommand).exists())
return false;
QProcess madAdminProc;
- QStringList arguments(QLatin1String("list"));
-
-#ifdef Q_OS_WIN
- QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
- env.insert(QLatin1String("PATH"),
- QDir::toNativeSeparators(dir.absolutePath() % QLatin1String("/bin"))
- % QLatin1Char(';') % env.value(QLatin1String("PATH")));
- madAdminProc.setProcessEnvironment(env);
-
- arguments.prepend(madAdminCommand);
- madAdminCommand = dir.absolutePath() + QLatin1String("/bin/sh.exe");
-#endif
-
- madAdminProc.start(madAdminCommand, arguments);
+ const QStringList arguments(QLatin1String("list"));
+ MaemoGlobal::callMaddeShellScript(madAdminProc, dir.absolutePath(),
+ madAdminCommand, arguments);
if (!madAdminProc.waitForStarted() || !madAdminProc.waitForFinished())
return false;
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemomanager.h b/src/plugins/qt4projectmanager/qt-maemo/maemomanager.h
index f80ebb9cbc..0491bfee26 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemomanager.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemomanager.h
@@ -47,10 +47,12 @@ namespace Internal {
class MaemoDeployStepFactory;
class MaemoPackageCreationFactory;
+class MaemoPublishingWizardFactoryFremantleFree;
class MaemoRunControlFactory;
class MaemoRunConfigurationFactory;
-class MaemoSettingsPage;
+class MaemoDeviceConfigurationsSettingsPage;
class MaemoQemuManager;
+class MaemoQemuSettingsPage;
class MaemoManager : public QObject
{
@@ -64,7 +66,8 @@ public:
bool isValidMaemoQtVersion(const Qt4ProjectManager::QtVersion *version) const;
ToolChain *maemoToolChain(const Qt4ProjectManager::QtVersion *version) const;
- MaemoSettingsPage *settingsPage() const { return m_settingsPage; }
+ MaemoDeviceConfigurationsSettingsPage *deviceConfigurationsSettingsPage() const { return m_deviceConfigurationsSettingsPage; }
+ MaemoQemuSettingsPage *qemuSettingsPage() const { return m_qemuSettingsPage; }
private:
static MaemoManager *m_instance;
@@ -73,8 +76,10 @@ private:
MaemoRunConfigurationFactory *m_runConfigurationFactory;
MaemoPackageCreationFactory *m_packageCreationFactory;
MaemoDeployStepFactory *m_deployStepFactory;
- MaemoSettingsPage *m_settingsPage;
+ MaemoDeviceConfigurationsSettingsPage *m_deviceConfigurationsSettingsPage;
+ MaemoQemuSettingsPage *m_qemuSettingsPage;
MaemoQemuManager *m_qemuRuntimeManager;
+ MaemoPublishingWizardFactoryFremantleFree *m_publishingFactoryFremantleFree;
};
} // namespace Internal
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationstep.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationstep.cpp
index 871cd461ba..c2a67b0090 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationstep.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationstep.cpp
@@ -46,7 +46,6 @@
#include "maemodeploystep.h"
#include "maemoglobal.h"
#include "maemopackagecreationwidget.h"
-#include "maemoprofilewrapper.h"
#include "maemotemplatesmanager.h"
#include "maemotoolchain.h"
@@ -55,10 +54,10 @@
#include <qt4buildconfiguration.h>
#include <qt4project.h>
#include <qt4target.h>
+#include <utils/environment.h>
#include <QtCore/QDateTime>
#include <QtCore/QProcess>
-#include <QtCore/QProcessEnvironment>
#include <QtCore/QRegExp>
#include <QtCore/QStringBuilder>
#include <QtGui/QWidget>
@@ -160,8 +159,8 @@ bool MaemoPackageCreationStep::createPackage(QProcess *buildProc)
emit addOutput(tr("Creating package file ..."), MessageOutput);
checkProjectName();
QString error;
- if (!preparePackagingProcess(buildProc, maemoToolChain(), buildDirectory(),
- &error)) {
+ if (!preparePackagingProcess(buildProc, qt4BuildConfiguration(),
+ buildDirectory(), &error)) {
raiseError(error);
return false;
}
@@ -173,8 +172,34 @@ bool MaemoPackageCreationStep::createPackage(QProcess *buildProc)
if (!copyDebianFiles(inSourceBuild))
return false;
- if (!runCommand(buildProc, QLatin1String("dpkg-buildpackage -nc -uc -us")))
+ const QString maddeRoot = maemoToolChain()->maddeRoot();
+ const QString madCommand = maddeRoot + QLatin1String("/bin/mad");
+ const QStringList args = QStringList() << QLatin1String("-t")
+ << maemoToolChain()->targetName() << QLatin1String("dpkg-buildpackage")
+ << QLatin1String("-nc") << QLatin1String("-uc") << QLatin1String("-us");
+ const QString cmdLine = madCommand + QLatin1Char(' ')
+ + args.join(QLatin1String(" "));
+ emit addOutput(tr("Package Creation: Running command '%1'.").arg(cmdLine),
+ BuildStep::MessageOutput);
+ MaemoGlobal::callMaddeShellScript(*buildProc, maddeRoot, madCommand, args);
+ if (!buildProc->waitForStarted()) {
+ raiseError(tr("Packaging failed."),
+ tr("Packaging error: Could not start command '%1'. Reason: %2")
+ .arg(cmdLine, buildProc->errorString()));
return false;
+ }
+ buildProc->waitForFinished(-1);
+ if (buildProc->error() != QProcess::UnknownError
+ || buildProc->exitCode() != 0) {
+ QString mainMessage = tr("Packaging Error: Command '%1' failed.")
+ .arg(cmdLine);
+ if (buildProc->error() != QProcess::UnknownError)
+ mainMessage += tr(" Reason: %1").arg(buildProc->errorString());
+ else
+ mainMessage += tr("Exit code: %1").arg(buildProc->exitCode());
+ raiseError(mainMessage);
+ return false;
+ }
// Workaround for non-working dh_builddeb --destdir=.
if (!QDir(buildDirectory()).isRoot()) {
@@ -231,9 +256,10 @@ bool MaemoPackageCreationStep::copyDebianFiles(bool inSourceBuild)
.arg(QDir::toNativeSeparators(debianDirPath)));
return false;
}
- if (!removeDirectory(debianDirPath)) {
+ QString error;
+ if (!MaemoGlobal::removeRecursively(debianDirPath, error)) {
raiseError(tr("Packaging failed."),
- tr("Could not remove directory '%1'.").arg(debianDirPath));
+ tr("Could not remove directory '%1': %2").arg(debianDirPath, error));
return false;
}
QDir buildDir(buildDirectory());
@@ -246,10 +272,6 @@ bool MaemoPackageCreationStep::copyDebianFiles(bool inSourceBuild)
->debianDirPath(buildConfiguration()->target()->project());
QDir templatesDir(templatesDirPath);
const QStringList &files = templatesDir.entryList(QDir::Files);
- const bool harmattanWorkaroundNeeded
- = maemoToolChain()->version() == MaemoToolChain::Maemo6
- && !qt4BuildConfiguration()->qt4Target()->qt4Project()
- ->applicationProFiles().isEmpty();
foreach (const QString &fileName, files) {
const QString srcFile
= templatesDirPath + QLatin1Char('/') + fileName;
@@ -262,13 +284,8 @@ bool MaemoPackageCreationStep::copyDebianFiles(bool inSourceBuild)
return false;
}
- // Workaround for Harmattan icon bug
- if (fileName == QLatin1String("rules")) {
- if (harmattanWorkaroundNeeded)
- addWorkaroundForHarmattanBug(destFile);
- QFile rulesFile(destFile);
- rulesFile.setPermissions(rulesFile.permissions() | QFile::ExeUser);
- }
+ if (fileName == QLatin1String("rules"))
+ updateDesktopFiles(destFile);
}
QFile magicFile(magicFilePath);
@@ -281,55 +298,6 @@ bool MaemoPackageCreationStep::copyDebianFiles(bool inSourceBuild)
return true;
}
-bool MaemoPackageCreationStep::removeDirectory(const QString &dirPath)
-{
- QDir dir(dirPath);
- if (!dir.exists())
- return true;
-
- const QStringList &files
- = dir.entryList(QDir::Files | QDir::Hidden | QDir::System);
- foreach (const QString &fileName, files) {
- if (!dir.remove(fileName))
- return false;
- }
-
- const QStringList &subDirs
- = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
- foreach (const QString &subDirName, subDirs) {
- if (!removeDirectory(dirPath + QLatin1Char('/') + subDirName))
- return false;
- }
-
- return dir.rmdir(dirPath);
-}
-
-bool MaemoPackageCreationStep::runCommand(QProcess *buildProc,
- const QString &command)
-{
- emit addOutput(tr("Package Creation: Running command '%1'.").arg(command), BuildStep::MessageOutput);
- buildProc->start(packagingCommand(maemoToolChain(), command));
- if (!buildProc->waitForStarted()) {
- raiseError(tr("Packaging failed."),
- tr("Packaging error: Could not start command '%1'. Reason: %2")
- .arg(command).arg(buildProc->errorString()));
- return false;
- }
- buildProc->waitForFinished(-1);
- if (buildProc->error() != QProcess::UnknownError
- || buildProc->exitCode() != 0) {
- QString mainMessage = tr("Packaging Error: Command '%1' failed.")
- .arg(command);
- if (buildProc->error() != QProcess::UnknownError)
- mainMessage += tr(" Reason: %1").arg(buildProc->errorString());
- else
- mainMessage += tr("Exit code: %1").arg(buildProc->exitCode());
- raiseError(mainMessage);
- return false;
- }
- return true;
-}
-
void MaemoPackageCreationStep::handleBuildOutput()
{
QProcess * const buildProc = qobject_cast<QProcess *>(sender());
@@ -399,7 +367,8 @@ QString MaemoPackageCreationStep::targetRoot() const
bool MaemoPackageCreationStep::packagingNeeded() const
{
- const MaemoDeployables * const deployables = deployStep()->deployables();
+ const QSharedPointer<MaemoDeployables> &deployables
+ = deployStep()->deployables();
QFileInfo packageInfo(packageFilePath());
if (!packageInfo.exists() || deployables->isModified())
return true;
@@ -492,8 +461,14 @@ void MaemoPackageCreationStep::raiseError(const QString &shortMsg,
}
bool MaemoPackageCreationStep::preparePackagingProcess(QProcess *proc,
- const MaemoToolChain *tc, const QString &workingDir, QString *error)
+ const Qt4BuildConfiguration *bc, const QString &workingDir, QString *error)
{
+ const MaemoToolChain * const tc
+ = dynamic_cast<const MaemoToolChain *>(bc->toolChain());
+ if (!tc) {
+ *error = tr("Build configuration has no Maemo toolchain.");
+ return false;
+ }
QFile configFile(tc->targetRoot() % QLatin1String("/config.sh"));
if (!configFile.open(QIODevice::ReadOnly)) {
*error = tr("Cannot open MADDE config file '%1'.")
@@ -501,19 +476,19 @@ bool MaemoPackageCreationStep::preparePackagingProcess(QProcess *proc,
return false;
}
- QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
+ Utils::Environment env = bc->environment();
const QString &path
= QDir::toNativeSeparators(tc->maddeRoot() + QLatin1Char('/'));
-
- const QLatin1String key("PATH");
- QString colon = QLatin1String(":");
#ifdef Q_OS_WIN
- colon = QLatin1String(";");
- env.insert(key, path % QLatin1String("bin") % colon % env.value(key));
+ env.prependOrSetPath(path % QLatin1String("bin"));
#endif
+ env.prependOrSetPath(tc->targetRoot() % QLatin1String("/bin"));
+ env.prependOrSetPath(path % QLatin1String("madbin"));
- env.insert(key, tc->targetRoot() % "/bin" % colon % env.value(key));
- env.insert(key, path % QLatin1String("madbin") % colon % env.value(key));
+ if (bc->qmakeBuildConfiguration() & QtVersion::DebugBuild) {
+ env.appendOrSet(QLatin1String("DEB_BUILD_OPTIONS"),
+ QLatin1String("nostrip"), QLatin1String(" "));
+ }
QString perlLib
= QDir::fromNativeSeparators(path % QLatin1String("madlib/perl5"));
@@ -521,21 +496,19 @@ bool MaemoPackageCreationStep::preparePackagingProcess(QProcess *proc,
perlLib = perlLib.remove(QLatin1Char(':'));
perlLib = perlLib.prepend(QLatin1Char('/'));
#endif
- env.insert(QLatin1String("PERL5LIB"), perlLib);
- env.insert(QLatin1String("PWD"), workingDir);
+ env.set(QLatin1String("PERL5LIB"), perlLib);
+ env.set(QLatin1String("PWD"), workingDir);
const QRegExp envPattern(QLatin1String("([^=]+)=[\"']?([^;\"']+)[\"']? ;.*"));
QByteArray line;
do {
line = configFile.readLine(200);
if (envPattern.exactMatch(line))
- env.insert(envPattern.cap(1), envPattern.cap(2));
+ env.set(envPattern.cap(1), envPattern.cap(2));
} while (!line.isEmpty());
- proc->setProcessEnvironment(env);
+ proc->setEnvironment(env.toStringList());
proc->setWorkingDirectory(workingDir);
- proc->start("cd " + workingDir);
- proc->waitForFinished();
return true;
}
@@ -580,9 +553,10 @@ QString MaemoPackageCreationStep::packageFileName(const ProjectExplorer::Project
% QLatin1String("_armel.deb");
}
-void MaemoPackageCreationStep::addWorkaroundForHarmattanBug(const QString &rulesFilePath)
+void MaemoPackageCreationStep::updateDesktopFiles(const QString &rulesFilePath)
{
QFile rulesFile(rulesFilePath);
+ rulesFile.setPermissions(rulesFile.permissions() | QFile::ExeUser);
if (!rulesFile.open(QIODevice::ReadWrite)) {
qWarning("Cannot open rules file for Maemo6 icon path adaptation.");
return;
@@ -597,36 +571,70 @@ void MaemoPackageCreationStep::addWorkaroundForHarmattanBug(const QString &rules
QString desktopFileDir = QFileInfo(rulesFile).dir().path()
+ QLatin1Char('/') + projectName()
+ QLatin1String("/usr/share/applications/");
+ if (maemoToolChain()->version() == MaemoToolChain::Maemo5)
+ desktopFileDir += QLatin1String("hildon/");
#ifdef Q_OS_WIN
desktopFileDir.remove(QLatin1Char(':'));
desktopFileDir.prepend(QLatin1Char('/'));
#endif
- const QList<Qt4ProFileNode *> &proFiles = qt4BuildConfiguration()
- ->qt4Target()->qt4Project()->applicationProFiles();
int insertPos = makeInstallEol + 1;
- foreach (const Qt4ProFileNode * const proFile, proFiles) {
- const QString appName = proFile->targetInformation().target;
- const QByteArray lineBefore("Icon=" + appName.toUtf8());
- const QByteArray lineAfter("Icon=/usr/share/icons/hicolor/64x64/apps/"
- + appName.toUtf8() + ".png");
- const QString desktopFilePath
- = desktopFileDir + appName + QLatin1String(".desktop");
- const QString tmpFile
- = desktopFileDir + appName + QLatin1String(".sed");
- const QByteArray sedCmd = "\tsed 's:" + lineBefore + ':' + lineAfter
- + ":' " + desktopFilePath.toLocal8Bit() + " > "
- + tmpFile.toLocal8Bit() + " || echo -n\n";
- const QByteArray mvCmd = "\tmv " + tmpFile.toLocal8Bit() + ' '
- + desktopFilePath.toLocal8Bit() + " || echo -n\n";
- content.insert(insertPos, sedCmd);
- insertPos += sedCmd.length();
- content.insert(insertPos, mvCmd);
- insertPos += mvCmd.length();
+ for (int i = 0; i < deployStep()->deployables()->modelCount(); ++i) {
+ const MaemoDeployableListModel * const model
+ = deployStep()->deployables()->modelAt(i);
+ if (!model->hasDesktopFile())
+ continue;
+ if (maemoToolChain()->version() == MaemoToolChain::Maemo6) {
+ addWorkaroundForHarmattanBug(content, insertPos,
+ model, desktopFileDir);
+ }
+ const QString executableFilePath = model->remoteExecutableFilePath();
+ if (executableFilePath.isEmpty()) {
+ qDebug("%s: Skipping subproject %s with missing deployment information.",
+ Q_FUNC_INFO, qPrintable(model->proFilePath()));
+ continue;
+ }
+ const QByteArray lineBefore("Exec=.*");
+ const QByteArray lineAfter("Exec=" + executableFilePath.toUtf8());
+ const QString desktopFilePath = desktopFileDir
+ + model->applicationName() + QLatin1String(".desktop");
+ addSedCmdToRulesFile(content, insertPos, desktopFilePath, lineBefore,
+ lineAfter);
}
rulesFile.resize(0);
rulesFile.write(content);
}
+void MaemoPackageCreationStep::addWorkaroundForHarmattanBug(QByteArray &rulesFileContent,
+ int &insertPos, const MaemoDeployableListModel *model,
+ const QString &desktopFileDir)
+{
+ const QString iconFilePath = model->remoteIconFilePath();
+ if (iconFilePath.isEmpty())
+ return;
+ const QByteArray lineBefore("^Icon=.*");
+ const QByteArray lineAfter("Icon=" + iconFilePath.toUtf8());
+ const QString desktopFilePath
+ = desktopFileDir + model->applicationName() + QLatin1String(".desktop");
+ addSedCmdToRulesFile(rulesFileContent, insertPos, desktopFilePath,
+ lineBefore, lineAfter);
+}
+
+void MaemoPackageCreationStep::addSedCmdToRulesFile(QByteArray &rulesFileContent,
+ int &insertPos, const QString &desktopFilePath, const QByteArray &oldString,
+ const QByteArray &newString)
+{
+ const QString tmpFilePath = desktopFilePath + QLatin1String(".sed");
+ const QByteArray sedCmd = "\tsed 's:" + oldString + ':' + newString
+ + ":' " + desktopFilePath.toLocal8Bit() + " > "
+ + tmpFilePath.toLocal8Bit() + " || echo -n\n";
+ const QByteArray mvCmd = "\tmv " + tmpFilePath.toLocal8Bit() + ' '
+ + desktopFilePath.toLocal8Bit() + " || echo -n\n";
+ rulesFileContent.insert(insertPos, sedCmd);
+ insertPos += sedCmd.length();
+ rulesFileContent.insert(insertPos, mvCmd);
+ insertPos += mvCmd.length();
+}
+
const QLatin1String MaemoPackageCreationStep::CreatePackageId("Qt4ProjectManager.MaemoPackageCreationStep");
} // namespace Internal
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationstep.h b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationstep.h
index bacd7ec477..79c9529000 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationstep.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationstep.h
@@ -51,12 +51,13 @@ class QProcess;
QT_END_NAMESPACE
namespace Qt4ProjectManager {
-namespace Internal {
+class Qt4BuildConfiguration;
+namespace Internal {
class MaemoDeployStep;
+class MaemoDeployableListModel;
class MaemoToolChain;
class MaemoProFileWrapper;
-class Qt4BuildConfiguration;
class MaemoPackageCreationStep : public ProjectExplorer::BuildStep
{
@@ -75,14 +76,16 @@ public:
const MaemoToolChain *maemoToolChain() const;
- static bool preparePackagingProcess(QProcess *proc, const MaemoToolChain *tc,
- const QString &workingDir, QString *error);
+ static bool preparePackagingProcess(QProcess *proc,
+ const Qt4BuildConfiguration *bc, const QString &workingDir,
+ QString *error);
static QString packagingCommand(const MaemoToolChain *tc,
const QString &commandName);
static QString packageName(const ProjectExplorer::Project *project);
static QString packageFileName(const ProjectExplorer::Project *project,
const QString &version);
- static bool removeDirectory(const QString &dirPath);
+
+ QString projectName() const;
static const QLatin1String DefaultVersionNumber;
@@ -108,7 +111,6 @@ private:
bool createPackage(QProcess *buildProc);
bool copyDebianFiles(bool inSourceBuild);
- bool runCommand(QProcess *buildProc, const QString &command);
QString maddeRoot() const;
QString targetRoot() const;
static QString nativePath(const QFile &file);
@@ -118,11 +120,16 @@ private:
void raiseError(const QString &shortMsg,
const QString &detailedMsg = QString());
QString buildDirectory() const;
- QString projectName() const;
const Qt4BuildConfiguration *qt4BuildConfiguration() const;
MaemoDeployStep * deployStep() const;
void checkProjectName();
- void addWorkaroundForHarmattanBug(const QString &rulesFilePath);
+ void updateDesktopFiles(const QString &rulesFilePath);
+ void addWorkaroundForHarmattanBug(QByteArray &rulesFileContent,
+ int &insertPos, const MaemoDeployableListModel *model,
+ const QString &desktopFileDir);
+ void addSedCmdToRulesFile(QByteArray &rulesFileContent, int &insertPos,
+ const QString &desktopFilePath, const QByteArray &oldString,
+ const QByteArray &newString);
static const QLatin1String CreatePackageId;
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.cpp
index d7a3f11949..43e630da7a 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.cpp
@@ -57,6 +57,8 @@
#include <QtGui/QImageReader>
#include <QtGui/QMessageBox>
+using namespace ProjectExplorer;
+
namespace Qt4ProjectManager {
namespace Internal {
@@ -71,17 +73,20 @@ MaemoPackageCreationWidget::MaemoPackageCreationWidget(MaemoPackageCreationStep
QTimer::singleShot(0, this, SLOT(initGui()));
}
+MaemoPackageCreationWidget::~MaemoPackageCreationWidget()
+{
+ delete m_ui;
+}
+
void MaemoPackageCreationWidget::init()
{
}
void MaemoPackageCreationWidget::initGui()
{
- const ProjectExplorer::Project * const project
- = m_step->buildConfiguration()->target()->project();
- updateDebianFileList(project);
- updateVersionInfo(project);
- updatePackageManagerIcon(project);
+ updateDebianFileList(thisProject());
+ updateVersionInfo(thisProject());
+ handleControlFileUpdate(thisProject());
connect(m_step, SIGNAL(packageFilePathChanged()), this,
SIGNAL(updateSummary()));
connect(m_step, SIGNAL(qtVersionChanged()), this,
@@ -96,14 +101,16 @@ void MaemoPackageCreationWidget::initGui()
SLOT(updateVersionInfo(const ProjectExplorer::Project*)));
connect(MaemoTemplatesManager::instance(),
SIGNAL(controlChanged(const ProjectExplorer::Project*)), this,
- SLOT(updatePackageManagerIcon(const ProjectExplorer::Project*)));
+ SLOT(handleControlFileUpdate(const ProjectExplorer::Project*)));
+ connect(m_ui->nameLineEdit, SIGNAL(editingFinished()), SLOT(setName()));
+ m_ui->shortDescriptionLineEdit->setMaxLength(60);
+ connect(m_ui->shortDescriptionLineEdit, SIGNAL(editingFinished()),
+ SLOT(setShortDescription()));
}
void MaemoPackageCreationWidget::updateDebianFileList(const ProjectExplorer::Project *project)
{
- const ProjectExplorer::Project * const ourProject
- = m_step->buildConfiguration()->target()->project();
- if (ourProject == project)
+ if (thisProject() == project)
m_ui->debianFilesComboBox->clear();
const QStringList &debianFiles = MaemoTemplatesManager::instance()
->debianFiles(project);
@@ -115,7 +122,7 @@ void MaemoPackageCreationWidget::updateDebianFileList(const ProjectExplorer::Pro
void MaemoPackageCreationWidget::updateVersionInfo(const ProjectExplorer::Project *project)
{
- if (project != m_step->buildConfiguration()->target()->project())
+ if (project != thisProject())
return;
QString error;
@@ -131,18 +138,37 @@ void MaemoPackageCreationWidget::updateVersionInfo(const ProjectExplorer::Projec
m_ui->patch->setValue(list.value(2, QLatin1String("0")).toInt());
}
-void MaemoPackageCreationWidget::updatePackageManagerIcon(const ProjectExplorer::Project *project)
+void MaemoPackageCreationWidget::handleControlFileUpdate(const Project *project)
{
- if (project != m_step->buildConfiguration()->target()->project())
+ if (project != thisProject())
return;
+ updatePackageManagerIcon(project);
+ updateName(project);
+ updateShortDescription(project);
+}
+void MaemoPackageCreationWidget::updatePackageManagerIcon(const Project *project)
+{
QString error;
const QIcon &icon
= MaemoTemplatesManager::instance()->packageManagerIcon(project, &error);
- if (!error.isEmpty())
+ if (!error.isEmpty()) {
QMessageBox::critical(this, tr("Could not read icon"), error);
- else
+ } else {
m_ui->packageManagerIconButton->setIcon(icon);
+ m_ui->packageManagerIconButton->setIconSize(m_ui->packageManagerIconButton->size());
+ }
+}
+
+void MaemoPackageCreationWidget::updateName(const Project *project)
+{
+ m_ui->nameLineEdit->setText(MaemoTemplatesManager::instance()->name(project));
+}
+
+void MaemoPackageCreationWidget::updateShortDescription(const Project *project)
+{
+ m_ui->shortDescriptionLineEdit
+ ->setText(MaemoTemplatesManager::instance()->shortDescription(project));
}
void MaemoPackageCreationWidget::setPackageManagerIcon()
@@ -153,15 +179,34 @@ void MaemoPackageCreationWidget::setPackageManagerIcon()
imageFilter += "*." + QString::fromAscii(imageType) + QLatin1Char(' ');
imageFilter += QLatin1Char(')');
const QString iconFileName = QFileDialog::getOpenFileName(this,
- tr("Choose Image"), QString(), imageFilter);
+ tr("Choose Image (will be scaled to 48x48 pixels if necessary)"),
+ QString(), imageFilter);
if (!iconFileName.isEmpty()) {
QString error;
- if (!MaemoTemplatesManager::instance()->setPackageManagerIcon(m_step->
- buildConfiguration()->target()->project(), iconFileName, &error))
+ if (!MaemoTemplatesManager::instance()->setPackageManagerIcon(thisProject(),
+ iconFileName, &error))
QMessageBox::critical(this, tr("Could Not Set New Icon"), error);
}
}
+void MaemoPackageCreationWidget::setName()
+{
+ if (!MaemoTemplatesManager::instance()->setName(thisProject(),
+ m_ui->nameLineEdit->text())) {
+ QMessageBox::critical(this, tr("File Error"),
+ tr("Could not set project name."));
+ }
+}
+
+void MaemoPackageCreationWidget::setShortDescription()
+{
+ if (!MaemoTemplatesManager::instance()->setShortDescription(thisProject(),
+ m_ui->shortDescriptionLineEdit->text())) {
+ QMessageBox::critical(this, tr("File Error"),
+ tr("Could not set project description."));
+ }
+}
+
void MaemoPackageCreationWidget::handleToolchainChanged()
{
if (!m_step->maemoToolChain())
@@ -209,13 +254,18 @@ void MaemoPackageCreationWidget::versionInfoChanged()
void MaemoPackageCreationWidget::editDebianFile()
{
- const QString debianFilePath = MaemoTemplatesManager::instance()
- ->debianDirPath(m_step->buildConfiguration()->target()->project())
- + QLatin1Char('/') + m_ui->debianFilesComboBox->currentText();
+ const QString debianFilePath
+ = MaemoTemplatesManager::instance()->debianDirPath(thisProject())
+ + QLatin1Char('/') + m_ui->debianFilesComboBox->currentText();
Core::EditorManager::instance()->openEditor(debianFilePath,
QString(),
Core::EditorManager::ModeSwitch);
}
+Project *MaemoPackageCreationWidget::thisProject() const
+{
+ return m_step->buildConfiguration()->target()->project();
+}
+
} // namespace Internal
} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.h b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.h
index 1bf2bb7e29..b12714616d 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.h
@@ -57,6 +57,7 @@ class MaemoPackageCreationWidget : public ProjectExplorer::BuildStepConfigWidget
Q_OBJECT
public:
MaemoPackageCreationWidget(MaemoPackageCreationStep *step);
+ ~MaemoPackageCreationWidget();
virtual void init();
virtual QString summaryText() const;
@@ -67,13 +68,20 @@ private slots:
void editDebianFile();
void versionInfoChanged();
void initGui();
- void updateDebianFileList(const ProjectExplorer::Project *project);
- void updateVersionInfo(const ProjectExplorer::Project *project);
- void updatePackageManagerIcon(const ProjectExplorer::Project *project);
+ void updateDebianFileList(const ProjectExplorer::Project *thisProject);
+ void updateVersionInfo(const ProjectExplorer::Project *thisProject);
+ void handleControlFileUpdate(const ProjectExplorer::Project *thisProject);
void setPackageManagerIcon();
+ void setName();
+ void setShortDescription();
void handleToolchainChanged();
private:
+ void updatePackageManagerIcon(const ProjectExplorer::Project *thisProject);
+ void updateName(const ProjectExplorer::Project *thisProject);
+ void updateShortDescription(const ProjectExplorer::Project *thisProject);
+ ProjectExplorer::Project *thisProject() const;
+
MaemoPackageCreationStep * const m_step;
Ui::MaemoPackageCreationWidget * const m_ui;
};
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.ui b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.ui
index 795021c7d3..0eabf98803 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.ui
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>505</width>
- <height>162</height>
+ <width>584</width>
+ <height>230</height>
</rect>
</property>
<property name="sizePolicy">
@@ -28,21 +28,21 @@
</widget>
</item>
<item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
<layout class="QFormLayout" name="formLayout">
- <item row="0" column="0">
+ <item row="0" column="1">
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="0">
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
@@ -61,7 +61,7 @@
</property>
</widget>
</item>
- <item row="0" column="1">
+ <item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_2">
@@ -156,27 +156,47 @@
</item>
</layout>
</item>
- <item row="1" column="0">
- <widget class="QLabel" name="editDebianFileLabel">
+ <item row="3" column="0">
+ <widget class="QLabel" name="nameLabel">
<property name="text">
- <string>&lt;b&gt;Adapt Debian file:&lt;/b&gt;</string>
+ <string>&lt;b&gt;Name for Package Manager:&lt;/b&gt;</string>
</property>
</widget>
</item>
- <item row="1" column="1">
- <layout class="QHBoxLayout" name="horizontalLayout">
+ <item row="3" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
- <widget class="QComboBox" name="debianFilesComboBox"/>
+ <widget class="QLineEdit" name="nameLineEdit"/>
</item>
<item>
- <widget class="QPushButton" name="editDebianFileButton">
- <property name="text">
- <string>Edit</string>
+ <spacer name="horizontalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
</property>
- </widget>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
</item>
+ </layout>
+ </item>
+ <item row="4" column="0">
+ <widget class="QLabel" name="shortDescriptionLabel">
+ <property name="text">
+ <string>&lt;b&gt;Short description for Package Manager:&lt;/b&gt;</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
- <spacer name="horizontalSpacer">
+ <widget class="QLineEdit" name="shortDescriptionLineEdit"/>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
@@ -190,17 +210,38 @@
</item>
</layout>
</item>
- <item row="2" column="0">
+ <item row="5" column="0">
<widget class="QLabel" name="packageManagerIconLabel">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>48</height>
+ </size>
+ </property>
<property name="text">
<string>&lt;b&gt;Package Manager icon:&lt;/b&gt;</string>
</property>
</widget>
</item>
- <item row="2" column="1">
+ <item row="5" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QToolButton" name="packageManagerIconButton">
+ <property name="minimumSize">
+ <size>
+ <width>48</width>
+ <height>48</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>48</width>
+ <height>48</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Size is 48x48 pixels</string>
+ </property>
<property name="text">
<string/>
</property>
@@ -221,6 +262,40 @@
</item>
</layout>
</item>
+ <item row="6" column="0">
+ <widget class="QLabel" name="editDebianFileLabel">
+ <property name="text">
+ <string>&lt;b&gt;Adapt Debian file:&lt;/b&gt;</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QComboBox" name="debianFilesComboBox"/>
+ </item>
+ <item>
+ <widget class="QPushButton" name="editDebianFileButton">
+ <property name="text">
+ <string>Edit</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
</layout>
</item>
</layout>
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoprofilesupdatedialog.ui b/src/plugins/qt4projectmanager/qt-maemo/maemoprofilesupdatedialog.ui
index 7cd4b6a497..cbc51fb91f 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemoprofilesupdatedialog.ui
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoprofilesupdatedialog.ui
@@ -29,14 +29,14 @@
<item>
<widget class="QPushButton" name="checkAllButton">
<property name="text">
- <string>Check all</string>
+ <string>&amp;Check all</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="uncheckAllButton">
<property name="text">
- <string>Uncheck All</string>
+ <string>&amp;Uncheck All</string>
</property>
</widget>
</item>
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoprofilewrapper.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemoprofilewrapper.cpp
deleted file mode 100644
index 2e70d891d1..0000000000
--- a/src/plugins/qt4projectmanager/qt-maemo/maemoprofilewrapper.cpp
+++ /dev/null
@@ -1,302 +0,0 @@
-#include "maemoprofilewrapper.h"
-
-#include <prowriter.h>
-#include <qt4projectmanager/profilereader.h>
-
-#include <QtCore/QCryptographicHash>
-#include <QtCore/QFile>
-#include <QtCore/QFileInfo>
-
-namespace Qt4ProjectManager {
-namespace Internal {
-
-namespace {
- QString pathVar(const QString &var)
- {
- return var + QLatin1String(".path");
- }
-
- QString filesVar(const QString &var)
- {
- return var + QLatin1String(".files");
- }
-
- const QLatin1String InstallsVar("INSTALLS");
- const QLatin1String TargetVar("target");
-}
-
-
-MaemoProFileWrapper::MaemoProFileWrapper(const QString &proFileName,
- const QString &buildDir, const QSharedPointer<ProFileOption> &proFileOption)
- : m_proFileName(proFileName), m_proDir(QFileInfo(m_proFileName).dir()),
- m_buildDir(buildDir), m_proFileOption(proFileOption)
-{
- parseProFile(ParseFromFile);
-}
-
-MaemoProFileWrapper::~MaemoProFileWrapper() {}
-
-void MaemoProFileWrapper::reload()
-{
- parseProFile(ParseFromFile);
-}
-
-MaemoProFileWrapper::InstallsList MaemoProFileWrapper::installs() const
-{
- InstallsList list;
-
- const QStringList &elemList = varValues(InstallsVar);
- foreach (const QString &elem, elemList) {
- const QStringList &paths = varValues(pathVar(elem));
- if (paths.count() != 1) {
- qWarning("Error: Variable %s has %d values.",
- qPrintable(pathVar(elem)), paths.count());
- continue;
- }
-
- const QStringList &files
- = m_proFileReader->absoluteFileValues(filesVar(elem),
- m_proDir.path(), QStringList() << m_proDir.path(), 0);
-
- if (elem == TargetVar) {
- if (!list.targetPath.isEmpty()) {
- qWarning("Error: More than one target in INSTALLS list.");
- continue;
- }
- list.targetPath = paths.first();
- } else {
- if (files.isEmpty())
- continue;
- list.normalElems << InstallsElem(elem, paths.first(), files);
- }
- }
-
- return list;
-}
-
-bool MaemoProFileWrapper::addInstallsElem(const QString &path,
- const QString &absFilePath, const QString &var)
-{
- QString varName = var;
- if (varName.isEmpty()) {
- QCryptographicHash elemHash(QCryptographicHash::Md5);
- elemHash.addData(absFilePath.toUtf8());
- varName = QString::fromAscii(elemHash.result().toHex());
- }
-
- // TODO: Use lower-level calls here to make operation atomic.
- if (varName != TargetVar && !addFile(filesVar(varName), absFilePath))
- return false;
- return addVarValue(pathVar(varName), path)
- && addVarValue(InstallsVar, varName);
-}
-
-bool MaemoProFileWrapper::addInstallsTarget(const QString &path)
-{
- return addInstallsElem(path, QString(), TargetVar);
-}
-
-bool MaemoProFileWrapper::removeInstallsElem(const QString &path,
- const QString &file)
-{
- const InstallsElem &elem = findInstallsElem(path, file);
- if (elem.varName.isEmpty())
- return false;
-
- // TODO: Use lower-level calls here to make operation atomic.
- if (elem.varName != TargetVar && !removeFile(filesVar(elem.varName), file))
- return false;
- if (elem.files.count() <= 1) {
- if (!removeVarValue(pathVar(elem.varName), path))
- return false;
- if (!removeVarValue(InstallsVar, elem.varName))
- return false;
- }
- return true;
-}
-
-bool MaemoProFileWrapper::replaceInstallPath(const QString &oldPath,
- const QString &file, const QString &newPath)
-{
- const InstallsElem &elem = findInstallsElem(oldPath, file);
- if (elem.varName.isEmpty())
- return false;
-
- // Simple case: Variable has only one file, so just replace the path.
- if (elem.varName == TargetVar || elem.files.count() == 1)
- return replaceVarValue(pathVar(elem.varName), oldPath, newPath);
-
- // Complicated case: Variable has other files, so remove our file from it
- // and introduce a new one.
- if (!removeInstallsElem(oldPath, file))
- return false;
- return addInstallsElem(newPath, file);
-}
-
-QStringList MaemoProFileWrapper::varValues(const QString &var) const
-{
- return m_proFileReader->values(var);
-}
-
-bool MaemoProFileWrapper::addVarValue(const QString &var, const QString &value)
-{
- if (varValues(var).contains(value))
- return true;
-
- if (!readProFileContents())
- return false;
- ProWriter::addVarValues(m_proFile, &m_proFileContents, m_proDir,
- QStringList(value), var);
- parseProFile(ParseFromLines);
- return writeProFileContents();
-}
-
-bool MaemoProFileWrapper::addFile(const QString &var, const QString &absFilePath)
-{
- if (!readProFileContents())
- return false;
- ProWriter::addFiles(m_proFile, &m_proFileContents, m_proDir,
- QStringList(absFilePath), var);
- parseProFile(ParseFromLines);
- return writeProFileContents();
-}
-
-bool MaemoProFileWrapper::removeVarValue(const QString &var, const QString &value)
-{
- if (!readProFileContents())
- return false;
- const bool success = ProWriter::removeVarValues(m_proFile,
- &m_proFileContents, m_proDir, QStringList(value), QStringList(var))
- .isEmpty();
- if (success) {
- parseProFile(ParseFromLines);
- return writeProFileContents();
- } else {
- parseProFile(ParseFromFile);
- return false;
- }
-}
-
-bool MaemoProFileWrapper::removeFile(const QString &var, const QString &absFilePath)
-{
- if (!readProFileContents())
- return false;
- const bool success = ProWriter::removeFiles(m_proFile, &m_proFileContents,
- m_proDir, QStringList(absFilePath), QStringList(var)).isEmpty();
- if (success) {
- parseProFile(ParseFromLines);
- return writeProFileContents();
- } else {
- parseProFile(ParseFromFile);
- return false;
- }
-}
-
-bool MaemoProFileWrapper::replaceVarValue(const QString &var,
- const QString &oldValue, const QString &newValue)
-{
- if (!readProFileContents())
- return false;
- const bool success = ProWriter::removeVarValues(m_proFile,
- &m_proFileContents, m_proDir, QStringList(oldValue), QStringList(var))
- .isEmpty();
- if (!success) {
- parseProFile(ParseFromFile);
- return false;
- }
- ProWriter::addVarValues(m_proFile, &m_proFileContents, m_proDir,
- QStringList(newValue), var);
- parseProFile(ParseFromLines);
- return writeProFileContents();
-}
-
-QString MaemoProFileWrapper::absFilePath(const QString &relFilePath) const
-{
- // I'd rather use QDir::cleanPath(), but that doesn't work well
- // enough for redundant ".." dirs.
- QFileInfo fi(relFilePath);
- return fi.isAbsolute() ? fi.canonicalFilePath()
- : QFileInfo(m_proFile->directoryName() + '/' + relFilePath)
- .canonicalFilePath();
-}
-
-void MaemoProFileWrapper::parseProFile(ParseType type) const
-{
- if (m_proFileReader)
- m_proFile->deref();
- m_proFileReader.reset(new ProFileReader(m_proFileOption.data()));
- m_proFileReader->setOutputDir(m_buildDir);
- m_proFileReader->setCumulative(false);
- // TODO: Set output dir to build dir?
- if (type == ParseFromLines) {
- m_proFile = m_proFileReader->parsedProBlock(m_proFileName,
- m_proFileContents.join("\n"));
- } else {
- m_proFileContents.clear();
- m_proFile = m_proFileReader->parsedProFile(m_proFileName);
- }
-
- if (!m_proFile) {
- qWarning("Fatal: Could not parse .pro file '%s'.",
- qPrintable(m_proFileName));
- return;
- }
-
- m_proFileReader->accept(m_proFile);
-}
-
-bool MaemoProFileWrapper::writeProFileContents()
-{
- QFile proFileOnDisk(m_proFileName);
- if (!proFileOnDisk.open(QIODevice::WriteOnly)) {
- parseProFile(ParseFromFile);
- return false;
- }
-
- // TODO: Disconnect and reconnect FS watcher here.
- proFileOnDisk.write(m_proFileContents.join("\n").toLatin1());
- proFileOnDisk.close();
- if (proFileOnDisk.error() != QFile::NoError) {
- parseProFile(ParseFromFile);
- return false;
- }
- return true;
-}
-
-bool MaemoProFileWrapper::readProFileContents()
-{
- if (!m_proFileContents.isEmpty())
- return true;
-
- QFile proFileOnDisk(m_proFileName);
- if (!proFileOnDisk.open(QIODevice::ReadOnly))
- return false;
- const QString proFileContents
- = QString::fromLatin1(proFileOnDisk.readAll());
- if (proFileOnDisk.error() != QFile::NoError)
- return false;
- m_proFileContents = proFileContents.split('\n');
- return true;
-}
-
-MaemoProFileWrapper::InstallsElem MaemoProFileWrapper::findInstallsElem(const QString &path,
- const QString &file) const
-{
- const QStringList &elems = varValues(InstallsVar);
- foreach (const QString &elem, elems) {
- const QStringList &elemPaths = varValues(pathVar(elem));
- if (elemPaths.count() != 1 || elemPaths.first() != path)
- continue;
- if (elem == TargetVar)
- return InstallsElem(elem, path, QStringList());
- const QStringList &elemFiles = varValues(filesVar(elem));
- foreach (const QString &elemFile, elemFiles) {
- if (absFilePath(elemFile) == file)
- return InstallsElem(elem, path, elemFiles);
- }
- }
- return InstallsElem(QString(), QString(), QStringList());
-}
-
-} // namespace Internal
-} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoprofilewrapper.h b/src/plugins/qt4projectmanager/qt-maemo/maemoprofilewrapper.h
deleted file mode 100644
index 58480fa3e2..0000000000
--- a/src/plugins/qt4projectmanager/qt-maemo/maemoprofilewrapper.h
+++ /dev/null
@@ -1,81 +0,0 @@
-#ifndef PROFILEWRAPPER_H
-#define PROFILEWRAPPER_H
-
-#include <QtCore/QDir>
-#include <QtCore/QScopedPointer>
-#include <QtCore/QSharedPointer>
-#include <QtCore/QString>
-#include <QtCore/QString>
-
-QT_BEGIN_NAMESPACE
-class ProFile;
-struct ProFileOption;
-QT_END_NAMESPACE
-
-namespace Qt4ProjectManager {
-namespace Internal {
-class ProFileReader;
-
-class MaemoProFileWrapper
-{
-public:
- MaemoProFileWrapper(const QString &proFileName, const QString &buildDir,
- const QSharedPointer<ProFileOption> &proFileOption);
- ~MaemoProFileWrapper();
-
- void reload();
-
- struct InstallsElem {
- InstallsElem(QString v, QString p, QStringList f)
- : varName(v), path(p), files(f) {}
- QString varName;
- QString path;
- QStringList files;
- };
-
- struct InstallsList {
- QString targetPath;
- QList<InstallsElem> normalElems;
- };
-
- // High-level functions for dealing with INSTALLS stuff.
- InstallsList installs() const;
- bool addInstallsElem(const QString &path, const QString &file,
- const QString &var = QString()); // Empty var means make the name up.
- bool addInstallsTarget(const QString &path);
- bool removeInstallsElem(const QString &path, const QString &file);
- bool replaceInstallPath(const QString &oldPath, const QString &file,
- const QString &newPath);
-
- // Lower-level functions working on arbitrary variables.
- QStringList varValues(const QString &var) const;
- bool addVarValue(const QString &var, const QString &value);
- bool addFile(const QString &var, const QString &absFilePath);
- bool removeVarValue(const QString &var, const QString &value);
- bool removeFile(const QString &var, const QString &absFilePath);
- bool replaceVarValue(const QString &var, const QString &oldValue,
- const QString &newValue);
-
- QString absFilePath(const QString &relFilePath) const;
-
-private:
- enum ParseType { ParseFromFile, ParseFromLines };
- void parseProFile(ParseType type) const;
- bool writeProFileContents();
- bool readProFileContents();
- InstallsElem findInstallsElem(const QString &path,
- const QString &file) const;
-
- const QString m_proFileName;
- const QDir m_proDir;
- const QString m_buildDir;
- const QSharedPointer<ProFileOption> m_proFileOption;
- mutable QStringList m_proFileContents;
- mutable QScopedPointer<ProFileReader> m_proFileReader;
- mutable ProFile *m_proFile;
-};
-
-} // namespace Internal
-} // namespace Qt4ProjectManager
-
-#endif // PROFILEWRAPPER_H
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopublishedprojectmodel.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemopublishedprojectmodel.cpp
new file mode 100644
index 0000000000..625f3e65a4
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopublishedprojectmodel.cpp
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of Qt Creator.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file 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 "maemopublishedprojectmodel.h"
+
+#include <QtCore/QFileInfo>
+
+namespace Qt4ProjectManager {
+namespace Internal {
+namespace {
+const int IncludeColumn = 2;
+} // anonymous namespace
+
+MaemoPublishedProjectModel::MaemoPublishedProjectModel(QObject *parent)
+ : QFileSystemModel(parent)
+{
+ setFilter(filter() | QDir::Hidden | QDir::System);
+}
+
+void MaemoPublishedProjectModel::initFilesToExclude()
+{
+ initFilesToExclude(rootPath());
+}
+
+void MaemoPublishedProjectModel::initFilesToExclude(const QString &filePath)
+{
+ QFileInfo fi(filePath);
+ if (fi.isDir()) {
+ const QStringList fileNames = QDir(filePath).entryList(QDir::Files
+ | QDir::Dirs | QDir::NoDotAndDotDot | QDir::System | QDir::Hidden);
+ foreach (const QString &fileName, fileNames)
+ initFilesToExclude(filePath + QLatin1Char('/') + fileName);
+ } else {
+ const QString &fileName = fi.fileName();
+ if (fi.isHidden() || fileName.endsWith(QLatin1String(".o"))
+ || fileName == QLatin1String("Makefile")
+ || fileName.contains(QLatin1String(".pro.user"))
+ || fileName.contains(QLatin1String(".so"))
+ || fileName.endsWith(QLatin1String(".a"))) {
+ m_filesToExclude.insert(filePath);
+ }
+ }
+}
+
+int MaemoPublishedProjectModel::columnCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent);
+ return IncludeColumn + 1;
+}
+
+int MaemoPublishedProjectModel::rowCount(const QModelIndex &parent) const
+{
+ if (isDir(parent) && m_filesToExclude.contains(filePath(parent)))
+ return 0;
+ return QFileSystemModel::rowCount(parent);
+}
+
+QVariant MaemoPublishedProjectModel::headerData(int section,
+ Qt::Orientation orientation, int role) const
+{
+ if (orientation != Qt::Horizontal || section != IncludeColumn)
+ return QFileSystemModel::headerData(section, orientation, role);
+ return tr("Include in package");
+}
+
+Qt::ItemFlags MaemoPublishedProjectModel::flags(const QModelIndex &index) const
+{
+ if (index.column() != IncludeColumn)
+ return QFileSystemModel::flags(index);
+ return Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
+}
+
+QVariant MaemoPublishedProjectModel::data(const QModelIndex &index,
+ int role) const
+{
+ if (index.column() != IncludeColumn)
+ return QFileSystemModel::data(index, role);
+ const bool include = !m_filesToExclude.contains(filePath(index));
+ if (role == Qt::DisplayRole)
+ return include ? tr("Include") : tr("Don't include");
+ else if (role == Qt::CheckStateRole)
+ return include ? Qt::Checked : Qt::Unchecked;
+ else
+ return QVariant();
+}
+
+bool MaemoPublishedProjectModel::setData(const QModelIndex &index,
+ const QVariant &value, int role)
+{
+ if (index.column() != IncludeColumn)
+ return QFileSystemModel::setData(index, value, role);
+ if (role == Qt::CheckStateRole) {
+ if (value == Qt::Checked) {
+ m_filesToExclude.remove(filePath(index));
+ } else {
+ m_filesToExclude.insert(filePath(index));
+ }
+ if (isDir(index))
+ emit layoutChanged();
+ return true;
+ }
+ return false;
+}
+
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopublishedprojectmodel.h b/src/plugins/qt4projectmanager/qt-maemo/maemopublishedprojectmodel.h
new file mode 100644
index 0000000000..51de90c3d0
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopublishedprojectmodel.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of Qt Creator.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file 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 MAEMOPUBLISHEDPROJECTMODEL_H
+#define MAEMOPUBLISHEDPROJECTMODEL_H
+
+#include <QtCore/QSet>
+#include <QtCore/QStringList>
+#include <QtGui/QFileSystemModel>
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+class MaemoPublishedProjectModel : public QFileSystemModel
+{
+ Q_OBJECT
+public:
+ explicit MaemoPublishedProjectModel(QObject *parent = 0);
+ void initFilesToExclude();
+ QStringList filesToExclude() const { return m_filesToExclude.toList(); }
+
+private:
+ virtual int columnCount(const QModelIndex &parent) const;
+ virtual int rowCount(const QModelIndex &parent) const;
+ virtual QVariant headerData(int section, Qt::Orientation orientation,
+ int role) const;
+ virtual QVariant data(const QModelIndex &index, int role) const;
+ virtual bool setData(const QModelIndex &index, const QVariant &value,
+ int role);
+ virtual Qt::ItemFlags flags(const QModelIndex &index) const;
+
+ void initFilesToExclude(const QString &filePath);
+
+ QSet<QString> m_filesToExclude;
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // MAEMOPUBLISHEDPROJECTMODEL_H
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopublisherfremantlefree.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemopublisherfremantlefree.cpp
new file mode 100644
index 0000000000..a71da734b1
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopublisherfremantlefree.cpp
@@ -0,0 +1,634 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "maemopublisherfremantlefree.h"
+
+#include "maemodeployablelistmodel.h"
+#include "maemodeploystep.h"
+#include "maemoglobal.h"
+#include "maemopackagecreationstep.h"
+#include "maemopublishingfileselectiondialog.h"
+#include "maemotemplatesmanager.h"
+#include "maemotoolchain.h"
+
+#include <coreplugin/ifile.h>
+#include <projectexplorer/project.h>
+#include <projectexplorer/target.h>
+#include <qt4projectmanager/qmakestep.h>
+#include <qt4projectmanager/qt4buildconfiguration.h>
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDir>
+#include <QtCore/QFileInfo>
+#include <QtCore/QStringList>
+#include <QtGui/QIcon>
+
+#define ASSERT_STATE(state) ASSERT_STATE_GENERIC(State, state, m_state)
+
+using namespace Core;
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+MaemoPublisherFremantleFree::MaemoPublisherFremantleFree(const ProjectExplorer::Project *project,
+ QObject *parent) :
+ QObject(parent),
+ m_project(project),
+ m_state(Inactive),
+ m_sshParams(SshConnectionParameters::DefaultProxy)
+{
+ m_sshParams.authType = SshConnectionParameters::AuthByKey;
+ m_sshParams.timeout = 30;
+ m_sshParams.port = 22;
+ m_process = new QProcess(this);
+ connect(m_process, SIGNAL(finished(int,QProcess::ExitStatus)),
+ SLOT(handleProcessFinished()));
+ connect(m_process, SIGNAL(error(QProcess::ProcessError)),
+ SLOT(handleProcessError(QProcess::ProcessError)));
+ connect(m_process, SIGNAL(readyReadStandardOutput()),
+ SLOT(handleProcessStdOut()));
+ connect(m_process, SIGNAL(readyReadStandardError()),
+ SLOT(handleProcessStdErr()));
+}
+
+MaemoPublisherFremantleFree::~MaemoPublisherFremantleFree()
+{
+ ASSERT_STATE(Inactive);
+ m_process->kill();
+}
+
+void MaemoPublisherFremantleFree::publish()
+{
+ createPackage();
+}
+
+void MaemoPublisherFremantleFree::setSshParams(const QString &hostName,
+ const QString &userName, const QString &keyFile, const QString &remoteDir)
+{
+ Q_ASSERT(m_doUpload);
+ m_sshParams.host = hostName;
+ m_sshParams.uname = userName;
+ m_sshParams.privateKeyFile = keyFile;
+ m_remoteDir = remoteDir;
+}
+
+void MaemoPublisherFremantleFree::cancel()
+{
+ finishWithFailure(tr("Canceled."), tr("Publishing canceled by user."));
+}
+
+void MaemoPublisherFremantleFree::createPackage()
+{
+ setState(CopyingProjectDir);
+
+ const QStringList &problems = findProblems();
+ if (!problems.isEmpty()) {
+ const QLatin1String separator("\n- ");
+ finishWithFailure(tr("The project is missing some information "
+ "important to publishing:") + separator + problems.join(separator),
+ tr("Publishing failed: Missing project information."));
+ return;
+ }
+
+ m_tmpProjectDir = tmpDirContainer() + QLatin1Char('/')
+ + m_project->displayName();
+ if (QFileInfo(tmpDirContainer()).exists()) {
+ emit progressReport(tr("Removing left-over temporary directory ..."));
+ QString error;
+ if (!MaemoGlobal::removeRecursively(tmpDirContainer(), error)) {
+ finishWithFailure(tr("Error removing temporary directory: %1").arg(error),
+ tr("Publishing failed: Could not create source package."));
+ return;
+ }
+ }
+
+ emit progressReport(tr("Setting up temporary directory ..."));
+ if (!QDir::temp().mkdir(QFileInfo(tmpDirContainer()).fileName())) {
+ finishWithFailure(tr("Error: Could not create temporary directory."),
+ tr("Publishing failed: Could not create source package."));
+ return;
+ }
+ if (!copyRecursively(m_project->projectDirectory(), m_tmpProjectDir)) {
+ finishWithFailure(tr("Error: Could not copy project directory"),
+ tr("Publishing failed: Could not create source package."));
+ return;
+ }
+ if (!fixNewlines()) {
+ finishWithFailure(tr("Error: Could not fix newlines"),
+ tr("Publishing failed: Could not create source package."));
+ return;
+ }
+
+ QString error;
+ if (!updateDesktopFiles(&error)) {
+ finishWithFailure(error,
+ tr("Publishing failed: Could not create package."));
+ return;
+ }
+
+ emit progressReport(tr("Cleaning up temporary directory ..."));
+ if (!MaemoPackageCreationStep::preparePackagingProcess(m_process,
+ m_buildConfig, m_tmpProjectDir, &error)) {
+ finishWithFailure(tr("Error preparing packaging process: %1").arg(error),
+ tr("Publishing failed: Could not create package."));
+ return;
+ }
+
+ setState(RunningQmake);
+ ProjectExplorer::AbstractProcessStep * const qmakeStep
+ = m_buildConfig->qmakeStep();
+ qmakeStep->init();
+ const ProjectExplorer::ProcessParameters * const pp
+ = qmakeStep->processParameters();
+ m_process->start(pp->effectiveCommand() + QLatin1String(" ")
+ + pp->effectiveArguments());
+}
+
+bool MaemoPublisherFremantleFree::copyRecursively(const QString &srcFilePath,
+ const QString &tgtFilePath)
+{
+ if (m_state == Inactive)
+ return true;
+
+ QFileInfo srcFileInfo(srcFilePath);
+ if (srcFileInfo.isDir()) {
+ if (srcFileInfo == QFileInfo(m_project->projectDirectory()
+ + QLatin1String("/debian")))
+ return true;
+ QString actualSourcePath = srcFilePath;
+ QString actualTargetPath = tgtFilePath;
+
+ if (srcFileInfo.fileName() == QLatin1String("qtc_packaging")) {
+ actualSourcePath += QLatin1String("/debian_fremantle");
+ actualTargetPath.replace(QRegExp(QLatin1String("qtc_packaging$")),
+ QLatin1String("debian"));
+ }
+
+ QDir targetDir(actualTargetPath);
+ targetDir.cdUp();
+ if (!targetDir.mkdir(QFileInfo(actualTargetPath).fileName())) {
+ emit progressReport(tr("Failed to create directory '%1'.")
+ .arg(QDir::toNativeSeparators(actualTargetPath)), ErrorOutput);
+ return false;
+ }
+ QDir sourceDir(actualSourcePath);
+ QStringList fileNames = sourceDir.entryList(QDir::Files | QDir::Hidden
+ | QDir::System | QDir::Dirs | QDir::NoDotAndDotDot);
+ foreach (const QString &fileName, fileNames) {
+ if (!copyRecursively(actualSourcePath + QLatin1Char('/') + fileName,
+ actualTargetPath + QLatin1Char('/') + fileName))
+ return false;
+ }
+ } else {
+ if (!QFile::copy(srcFilePath, tgtFilePath)) {
+ emit progressReport(tr("Could not copy file '%1' to '%2'.")
+ .arg(QDir::toNativeSeparators(srcFilePath),
+ QDir::toNativeSeparators(tgtFilePath)));
+ return false;
+ }
+ QCoreApplication::processEvents();
+
+ if (tgtFilePath == m_tmpProjectDir + QLatin1String("/debian/rules")) {
+ QFile rulesFile(tgtFilePath);
+ if (!rulesFile.open(QIODevice::ReadWrite)) {
+ emit progressReport(tr("Error: Cannot open file '%1'.")
+ .arg(QDir::toNativeSeparators(tgtFilePath)));
+ return false;
+ }
+ QByteArray rulesContents = rulesFile.readAll();
+ rulesContents.replace("$(MAKE) clean", "# $(MAKE) clean");
+ rulesContents.replace("# Add here commands to configure the package.",
+ "qmake " + QFileInfo(m_project->file()->fileName()).fileName().toLocal8Bit());
+ rulesFile.resize(0);
+ rulesFile.write(rulesContents);
+ }
+ }
+ return true;
+}
+
+bool MaemoPublisherFremantleFree::fixNewlines()
+{
+ QDir debianDir(m_tmpProjectDir + QLatin1String("/debian"));
+ const QStringList &fileNames = debianDir.entryList(QDir::Files);
+ foreach (const QString &fileName, fileNames) {
+ QFile file(debianDir.filePath(fileName));
+ if (!file.open(QIODevice::ReadWrite))
+ return false;
+ QByteArray contents = file.readAll();
+ const QByteArray crlf("\r\n");
+ if (!contents.contains(crlf))
+ continue;
+ contents.replace(crlf, "\n");
+ file.resize(0);
+ file.write(contents);
+ }
+ return true;
+}
+
+void MaemoPublisherFremantleFree::handleProcessError(QProcess::ProcessError error)
+{
+ if (error == QProcess::FailedToStart)
+ handleProcessFinished(true);
+}
+
+void MaemoPublisherFremantleFree::handleProcessFinished()
+{
+ handleProcessFinished(false);
+}
+
+void MaemoPublisherFremantleFree::handleProcessStdOut()
+{
+ if (m_state == RunningQmake || m_state == RunningMakeDistclean
+ || m_state == BuildingPackage) {
+ emit progressReport(QString::fromLocal8Bit(m_process->readAllStandardOutput()),
+ ToolStatusOutput);
+ }
+}
+
+void MaemoPublisherFremantleFree::handleProcessStdErr()
+{
+ if (m_state == RunningQmake || m_state == RunningMakeDistclean
+ || m_state == BuildingPackage) {
+ emit progressReport(QString::fromLocal8Bit(m_process->readAllStandardError()),
+ ToolErrorOutput);
+ }
+}
+
+void MaemoPublisherFremantleFree::handleProcessFinished(bool failedToStart)
+{
+ ASSERT_STATE(QList<State>() << RunningQmake << RunningMakeDistclean
+ << BuildingPackage << Inactive);
+
+ switch (m_state) {
+ case RunningQmake:
+ if (failedToStart || m_process->exitStatus() != QProcess::NormalExit
+ ||m_process->exitCode() != 0) {
+ runDpkgBuildPackage();
+ } else {
+ setState(RunningMakeDistclean);
+ m_process->start(m_buildConfig->makeCommand(),
+ QStringList() << QLatin1String("distclean"));
+ }
+ break;
+ case RunningMakeDistclean:
+ runDpkgBuildPackage();
+ break;
+ case BuildingPackage: {
+ QString error;
+ if (failedToStart) {
+ error = tr("Error: Failed to start dpkg-buildpackage.");
+ } else if (m_process->exitStatus() != QProcess::NormalExit
+ || m_process->exitCode() != 0) {
+ error = tr("Error: dpkg-buildpackage did not succeed.");
+ }
+
+ if (!error.isEmpty()) {
+ finishWithFailure(error, tr("Package creation failed."));
+ return;
+ }
+
+ QDir dir(tmpDirContainer());
+ const QStringList &fileNames = dir.entryList(QDir::Files);
+ foreach (const QString &fileName, fileNames) {
+ const QString filePath
+ = tmpDirContainer() + QLatin1Char('/') + fileName;
+ if (fileName.endsWith(QLatin1String(".dsc")))
+ m_filesToUpload.append(filePath);
+ else
+ m_filesToUpload.prepend(filePath);
+ }
+ if (!m_doUpload) {
+ emit progressReport(tr("Done."));
+ QStringList nativeFilePaths;
+ foreach (const QString &filePath, m_filesToUpload)
+ nativeFilePaths << QDir::toNativeSeparators(filePath);
+ m_resultString = tr("Packaging finished successfully. "
+ "The following files were created:\n")
+ + nativeFilePaths.join(QLatin1String("\n"));
+ setState(Inactive);
+ } else {
+ uploadPackage();
+ }
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+void MaemoPublisherFremantleFree::runDpkgBuildPackage()
+{
+ MaemoPublishingFileSelectionDialog d(m_tmpProjectDir);
+ if (d.exec() == QDialog::Rejected) {
+ cancel();
+ return;
+ }
+ foreach (const QString &filePath, d.filesToExclude()) {
+ QString error;
+ if (!MaemoGlobal::removeRecursively(filePath, error)) {
+ finishWithFailure(error,
+ tr("Publishing failed: Could not create package."));
+ }
+ }
+
+ if (m_state == Inactive)
+ return;
+ setState(BuildingPackage);
+ emit progressReport(tr("Building source package..."));
+ const MaemoToolChain * const tc
+ = dynamic_cast<MaemoToolChain *>(m_buildConfig->toolChain());
+ const QStringList args = QStringList() << QLatin1String("-t")
+ << tc->targetName() << QLatin1String("dpkg-buildpackage")
+ << QLatin1String("-S") << QLatin1String("-us") << QLatin1String("-uc");
+ const QString madCommand = tc->maddeRoot() + QLatin1String("/bin/mad");
+ MaemoGlobal::callMaddeShellScript(*m_process, tc->maddeRoot(), madCommand, args);
+}
+
+// We have to implement the SCP protocol, because the maemo.org
+// webmaster refuses to enable SFTP "for security reasons" ...
+void MaemoPublisherFremantleFree::uploadPackage()
+{
+ m_uploader = SshRemoteProcessRunner::create(m_sshParams);
+ connect(m_uploader.data(), SIGNAL(processStarted()),
+ SLOT(handleScpStarted()));
+ connect(m_uploader.data(), SIGNAL(connectionError(Core::SshError)),
+ SLOT(handleConnectionError()));
+ connect(m_uploader.data(), SIGNAL(processClosed(int)),
+ SLOT(handleUploadJobFinished(int)));
+ connect(m_uploader.data(), SIGNAL(processOutputAvailable(QByteArray)),
+ SLOT(handleScpStdOut(QByteArray)));
+ emit progressReport(tr("Starting scp ..."));
+ setState(StartingScp);
+ m_uploader->run("scp -td " + m_remoteDir.toUtf8());
+}
+
+void MaemoPublisherFremantleFree::handleScpStarted()
+{
+ ASSERT_STATE(QList<State>() << StartingScp << Inactive);
+
+ if (m_state == StartingScp)
+ prepareToSendFile();
+}
+
+void MaemoPublisherFremantleFree::handleConnectionError()
+{
+ if (m_state != Inactive) {
+ finishWithFailure(tr("SSH error: %1").arg(m_uploader->connection()->errorString()),
+ tr("Upload failed."));
+ }
+}
+
+void MaemoPublisherFremantleFree::handleUploadJobFinished(int exitStatus)
+{
+ ASSERT_STATE(QList<State>() << PreparingToUploadFile << UploadingFile
+ << Inactive);
+
+ if (m_state != Inactive && (exitStatus != SshRemoteProcess::ExitedNormally
+ || m_uploader->process()->exitCode() != 0)) {
+ QString error;
+ if (exitStatus != SshRemoteProcess::ExitedNormally) {
+ error = tr("Error uploading file: %1")
+ .arg(m_uploader->process()->errorString());
+ } else {
+ error = tr("Error uploading file.");
+ }
+ finishWithFailure(error, tr("Upload failed."));
+ }
+}
+
+void MaemoPublisherFremantleFree::prepareToSendFile()
+{
+ if (m_filesToUpload.isEmpty()) {
+ emit progressReport(tr("All files uploaded."));
+ m_resultString = tr("Upload succeeded. You should shortly "
+ "receive an email informing you about the outcome "
+ "of the build process.");
+ setState(Inactive);
+ return;
+ }
+
+ setState(PreparingToUploadFile);
+ const QString &nextFilePath = m_filesToUpload.first();
+ emit progressReport(tr("Uploading file %1 ...")
+ .arg(QDir::toNativeSeparators(nextFilePath)));
+ QFileInfo info(nextFilePath);
+ m_uploader->process()->sendInput("C0644 " + QByteArray::number(info.size())
+ + ' ' + info.fileName().toUtf8() + '\n');
+}
+
+void MaemoPublisherFremantleFree::sendFile()
+{
+ Q_ASSERT(!m_filesToUpload.isEmpty());
+ Q_ASSERT(m_state == PreparingToUploadFile);
+
+ setState(UploadingFile);
+ const QString filePath = m_filesToUpload.takeFirst();
+ QFile file(filePath);
+ if (!file.open(QIODevice::ReadOnly)) {
+ finishWithFailure(tr("Cannot open file for reading: %1")
+ .arg(file.errorString()), tr("Upload failed."));
+ return;
+ }
+ qint64 bytesToSend = file.size();
+ while (bytesToSend > 0) {
+ const QByteArray &data
+ = file.read(qMin(bytesToSend, Q_INT64_C(1024*1024)));
+ if (data.count() == 0) {
+ finishWithFailure(tr("Cannot read file: %1").arg(file.errorString()),
+ tr("Upload failed."));
+ return;
+ }
+ m_uploader->process()->sendInput(data);
+ bytesToSend -= data.size();
+ QCoreApplication::processEvents();
+ if (m_state == Inactive)
+ return;
+ }
+ m_uploader->process()->sendInput(QByteArray(1, '\0'));
+}
+
+void MaemoPublisherFremantleFree::handleScpStdOut(const QByteArray &output)
+{
+ ASSERT_STATE(QList<State>() << PreparingToUploadFile << UploadingFile
+ << Inactive);
+
+ if (m_state == Inactive)
+ return;
+
+ m_scpOutput += output;
+ if (m_scpOutput == QByteArray(1, '\0')) {
+ m_scpOutput.clear();
+ switch (m_state) {
+ case PreparingToUploadFile:
+ sendFile();
+ break;
+ case UploadingFile:
+ prepareToSendFile();
+ break;
+ default:
+ break;
+ }
+ } else if (m_scpOutput.endsWith('\n')) {
+ const QByteArray error = m_scpOutput.mid(1, m_scpOutput.count() - 2);
+ QString progressError;
+ if (!error.isEmpty()) {
+ progressError = tr("Error uploading file: %1")
+ .arg(QString::fromUtf8(error));
+ } else {
+ progressError = tr("Error uploading file.");
+ }
+ finishWithFailure(progressError, tr("Upload failed."));
+ }
+}
+
+QString MaemoPublisherFremantleFree::tmpDirContainer() const
+{
+ return QDir::tempPath() + QLatin1String("/qtc_packaging_")
+ + m_project->displayName();
+}
+
+void MaemoPublisherFremantleFree::finishWithFailure(const QString &progressMsg,
+ const QString &resultMsg)
+{
+ if (!progressMsg.isEmpty())
+ emit progressReport(progressMsg, ErrorOutput);
+ m_resultString = resultMsg;
+ setState(Inactive);
+}
+
+bool MaemoPublisherFremantleFree::updateDesktopFiles(QString *error) const
+{
+ bool success = true;
+ MaemoDeployStep * const deployStep
+ = MaemoGlobal::buildStep<MaemoDeployStep>(m_buildConfig->target()
+ ->activeDeployConfiguration());
+ for (int i = 0; i < deployStep->deployables()->modelCount(); ++i) {
+ const MaemoDeployableListModel * const model
+ = deployStep->deployables()->modelAt(i);
+ QString desktopFilePath = model->localDesktopFilePath();
+ if (desktopFilePath.isEmpty())
+ continue;
+ desktopFilePath.replace(model->projectDir(), m_tmpProjectDir);
+ QFile desktopFile(desktopFilePath);
+ const QString executableFilePath = model->remoteExecutableFilePath();
+ if (executableFilePath.isEmpty()) {
+ qDebug("%s: Skipping subproject %s with missing deployment information.",
+ Q_FUNC_INFO, qPrintable(model->proFilePath()));
+ continue;
+ }
+ if (!desktopFile.exists() || !desktopFile.open(QIODevice::ReadWrite)) {
+ success = false;
+ if (error) {
+ *error = tr("Failed to adapt desktop file '%1'.")
+ .arg(desktopFilePath);
+ }
+ continue;
+ }
+ QByteArray desktopFileContents = desktopFile.readAll();
+ bool fileNeedsUpdate = addOrReplaceDesktopFileValue(desktopFileContents,
+ "Exec", executableFilePath.toUtf8());
+ if (fileNeedsUpdate) {
+ desktopFile.resize(0);
+ desktopFile.write(desktopFileContents);
+ }
+ }
+ return success;
+}
+
+bool MaemoPublisherFremantleFree::addOrReplaceDesktopFileValue(QByteArray &fileContent,
+ const QByteArray &key, const QByteArray &newValue) const
+{
+ const int keyPos = fileContent.indexOf(key + '=');
+ if (keyPos == -1) {
+ if (!fileContent.endsWith('\n'))
+ fileContent += '\n';
+ fileContent += key + '=' + newValue + '\n';
+ return true;
+ }
+ int nextNewlinePos = fileContent.indexOf('\n', keyPos);
+ if (nextNewlinePos == -1)
+ nextNewlinePos = fileContent.count();
+ const int replacePos = keyPos + key.count() + 1;
+ const int replaceCount = nextNewlinePos - replacePos;
+ const QByteArray &oldValue = fileContent.mid(replacePos, replaceCount);
+ if (oldValue == newValue)
+ return false;
+ fileContent.replace(replacePos, replaceCount, newValue);
+ return true;
+}
+
+QStringList MaemoPublisherFremantleFree::findProblems() const
+{
+ QStringList problems;
+ const MaemoTemplatesManager * const templatesManager
+ = MaemoTemplatesManager::instance();
+ const QString &description = templatesManager->shortDescription(m_project);
+ if (description.trimmed().isEmpty()) {
+ problems << tr("The package description is empty.");
+ } else if (description.contains(QLatin1String("insert up to"))) {
+ problems << tr("The package description is '%1', which is probably "
+ "not what you want.").arg(description);
+ }
+ QString dummy;
+ if (templatesManager->packageManagerIcon(m_project, &dummy).isNull())
+ problems << tr("You have not set an icon for the package manager.");
+ return problems;
+}
+
+void MaemoPublisherFremantleFree::setState(State newState)
+{
+ if (m_state == newState)
+ return;
+ const State oldState = m_state;
+ m_state = newState;
+ if (m_state == Inactive) {
+ switch (oldState) {
+ case RunningQmake:
+ case RunningMakeDistclean:
+ case BuildingPackage:
+ disconnect(m_process, 0, this, 0);
+ m_process->terminate();
+ break;
+ case StartingScp:
+ case PreparingToUploadFile:
+ case UploadingFile:
+ // TODO: Can we ensure the remote scp exits, e.g. by sending
+ // an illegal sequence of bytes? (Probably not, if
+ // we are currently uploading a file.)
+ disconnect(m_uploader.data(), 0, this, 0);
+ m_uploader = SshRemoteProcessRunner::Ptr();
+ break;
+ default:
+ break;
+ }
+ emit finished();
+ }
+}
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopublisherfremantlefree.h b/src/plugins/qt4projectmanager/qt-maemo/maemopublisherfremantlefree.h
new file mode 100644
index 0000000000..c075bc4d12
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopublisherfremantlefree.h
@@ -0,0 +1,122 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 MAEMOPUBLISHERFREMANTLEFREE_H
+#define MAEMOPUBLISHERFREMANTLEFREE_H
+
+#include <coreplugin/ssh/sshremoteprocessrunner.h>
+
+#include <QtCore/QObject>
+#include <QtCore/QProcess>
+
+namespace ProjectExplorer {
+class Project;
+}
+
+namespace Qt4ProjectManager {
+class Qt4BuildConfiguration;
+namespace Internal {
+
+class MaemoPublisherFremantleFree : public QObject
+{
+ Q_OBJECT
+public:
+ enum OutputType {
+ StatusOutput, ErrorOutput, ToolStatusOutput, ToolErrorOutput
+ };
+
+ explicit MaemoPublisherFremantleFree(const ProjectExplorer::Project *project,
+ QObject *parent = 0);
+ ~MaemoPublisherFremantleFree();
+
+ void publish();
+ void cancel();
+
+ void setBuildConfiguration(const Qt4BuildConfiguration *buildConfig) { m_buildConfig = buildConfig; }
+ void setDoUpload(bool doUpload) { m_doUpload = doUpload; }
+ void setSshParams(const QString &hostName, const QString &userName,
+ const QString &keyFile, const QString &remoteDir);
+
+ QString resultString() const { return m_resultString; }
+
+signals:
+ void progressReport(const QString &text,
+ MaemoPublisherFremantleFree::OutputType = StatusOutput);
+ void finished();
+
+private slots:
+ void handleProcessFinished();
+ void handleProcessStdOut();
+ void handleProcessStdErr();
+ void handleProcessError(QProcess::ProcessError error);
+ void handleScpStarted();
+ void handleConnectionError();
+ void handleUploadJobFinished(int exitStatus);
+ void handleScpStdOut(const QByteArray &output);
+
+private:
+ enum State {
+ Inactive, CopyingProjectDir, RunningQmake, RunningMakeDistclean,
+ BuildingPackage, StartingScp, PreparingToUploadFile, UploadingFile
+ };
+
+ void setState(State newState);
+ void createPackage();
+ void uploadPackage();
+ bool copyRecursively(const QString &srcFilePath,
+ const QString &tgtFilePath);
+ bool fixNewlines();
+ void handleProcessFinished(bool failedToStart);
+ void runDpkgBuildPackage();
+ QString tmpDirContainer() const;
+ void prepareToSendFile();
+ void sendFile();
+ void finishWithFailure(const QString &progressMsg, const QString &resultMsg);
+ bool updateDesktopFiles(QString *error = 0) const;
+ bool addOrReplaceDesktopFileValue(QByteArray &fileContent,
+ const QByteArray &key, const QByteArray &newValue) const;
+ QStringList findProblems() const;
+
+ const ProjectExplorer::Project * const m_project;
+ bool m_doUpload;
+ const Qt4BuildConfiguration *m_buildConfig;
+ State m_state;
+ QString m_tmpProjectDir;
+ QProcess *m_process;
+ Core::SshConnectionParameters m_sshParams;
+ QString m_remoteDir;
+ QSharedPointer<Core::SshRemoteProcessRunner> m_uploader;
+ QByteArray m_scpOutput;
+ QList<QString> m_filesToUpload;
+ QString m_resultString;
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // MAEMOPUBLISHERFREMANTLEFREE_H
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopublishingbuildsettingspagefremantlefree.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemopublishingbuildsettingspagefremantlefree.cpp
new file mode 100644
index 0000000000..5f50f3c830
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopublishingbuildsettingspagefremantlefree.cpp
@@ -0,0 +1,108 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "maemopublishingbuildsettingspagefremantlefree.h"
+#include "ui_maemopublishingbuildsettingspagefremantlefree.h"
+
+#include "maemopublisherfremantlefree.h"
+#include "maemotoolchain.h"
+
+#include <projectexplorer/project.h>
+#include <projectexplorer/target.h>
+#include <qt4projectmanager/qt4buildconfiguration.h>
+#include <qt4projectmanager/qt4projectmanagerconstants.h>
+#include <utils/qtcassert.h>
+
+using namespace ProjectExplorer;
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+MaemoPublishingBuildSettingsPageFremantleFree::MaemoPublishingBuildSettingsPageFremantleFree(const Project *project,
+ MaemoPublisherFremantleFree *publisher, QWidget *parent) :
+ QWizardPage(parent),
+ m_publisher(publisher),
+ ui(new Ui::MaemoPublishingWizardPageFremantleFree)
+{
+ ui->setupUi(this);
+ collectBuildConfigurations(project);
+ QTC_ASSERT(!m_buildConfigs.isEmpty(), return);
+ foreach (const Qt4BuildConfiguration * const bc, m_buildConfigs) {
+ ui->buildConfigComboBox->addItem(bc->displayName());
+ }
+ ui->buildConfigComboBox->setSizeAdjustPolicy(QComboBox::AdjustToContentsOnFirstShow);
+ ui->buildConfigComboBox->setCurrentIndex(0);
+ connect(ui->skipUploadCheckBox, SIGNAL(toggled(bool)),
+ SLOT(handleNoUploadSettingChanged()));
+}
+
+MaemoPublishingBuildSettingsPageFremantleFree::~MaemoPublishingBuildSettingsPageFremantleFree()
+{
+ delete ui;
+}
+
+void MaemoPublishingBuildSettingsPageFremantleFree::collectBuildConfigurations(const Project *project)
+{
+ foreach (const Target *const target, project->targets()) {
+ if (target->id() != QLatin1String(Constants::MAEMO_DEVICE_TARGET_ID))
+ continue;
+ foreach (BuildConfiguration * const bc, target->buildConfigurations()) {
+ Qt4BuildConfiguration * const qt4Bc
+ = qobject_cast<Qt4BuildConfiguration *>(bc);
+ if (!qt4Bc)
+ continue;
+ const MaemoToolChain * const tc
+ = dynamic_cast<MaemoToolChain *>(qt4Bc->toolChain());
+ if (!tc)
+ continue;
+ if (tc->version() == MaemoToolChain::Maemo5)
+ m_buildConfigs << qt4Bc;
+ }
+ break;
+ }
+}
+
+bool MaemoPublishingBuildSettingsPageFremantleFree::validatePage()
+{
+ m_publisher->setBuildConfiguration(m_buildConfigs.at(ui->buildConfigComboBox->currentIndex()));
+ m_publisher->setDoUpload(!skipUpload());
+ return true;
+}
+
+void MaemoPublishingBuildSettingsPageFremantleFree::handleNoUploadSettingChanged()
+{
+ setCommitPage(skipUpload());
+}
+
+bool MaemoPublishingBuildSettingsPageFremantleFree::skipUpload() const
+{
+ return ui->skipUploadCheckBox->isChecked();
+}
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopublishingbuildsettingspagefremantlefree.h b/src/plugins/qt4projectmanager/qt-maemo/maemopublishingbuildsettingspagefremantlefree.h
new file mode 100644
index 0000000000..0c25f5b608
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopublishingbuildsettingspagefremantlefree.h
@@ -0,0 +1,72 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 MAEMOPUBLISHINGBUILDSETTINGSPAGEFREMANTLEFREE_H
+#define MAEMOPUBLISHINGBUILDSETTINGSPAGEFREMANTLEFREE_H
+
+#include <QtCore/QList>
+#include <QtGui/QWizardPage>
+
+QT_BEGIN_NAMESPACE
+namespace Ui {
+ class MaemoPublishingWizardPageFremantleFree;
+}
+QT_END_NAMESPACE
+
+namespace ProjectExplorer { class Project; }
+
+namespace Qt4ProjectManager {
+class Qt4BuildConfiguration;
+
+namespace Internal {
+class MaemoPublisherFremantleFree;
+
+class MaemoPublishingBuildSettingsPageFremantleFree : public QWizardPage
+{
+ Q_OBJECT
+
+public:
+ explicit MaemoPublishingBuildSettingsPageFremantleFree(const ProjectExplorer::Project *project,
+ MaemoPublisherFremantleFree *publisher, QWidget *parent = 0);
+ ~MaemoPublishingBuildSettingsPageFremantleFree();
+
+private:
+ Q_SLOT void handleNoUploadSettingChanged();
+ virtual bool validatePage();
+ void collectBuildConfigurations(const ProjectExplorer::Project *project);
+ bool skipUpload() const;
+
+ QList<Qt4BuildConfiguration *> m_buildConfigs;
+ MaemoPublisherFremantleFree * const m_publisher;
+ Ui::MaemoPublishingWizardPageFremantleFree *ui;
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // MAEMOPUBLISHINGBUILDSETTINGSPAGEFREMANTLEFREE_H
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopublishingbuildsettingspagefremantlefree.ui b/src/plugins/qt4projectmanager/qt-maemo/maemopublishingbuildsettingspagefremantlefree.ui
new file mode 100644
index 0000000000..99406007d6
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopublishingbuildsettingspagefremantlefree.ui
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MaemoPublishingWizardPageFremantleFree</class>
+ <widget class="QWizardPage" name="MaemoPublishingWizardPageFremantleFree">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>433</width>
+ <height>149</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>WizardPage</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="buildConfigLabel">
+ <property name="text">
+ <string>Choose build configuration:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="buildConfigComboBox"/>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="Line" name="line">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="skipUploadCheckBox">
+ <property name="text">
+ <string>Only create source package, don't upload</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>78</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopublishingfileselectiondialog.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemopublishingfileselectiondialog.cpp
new file mode 100644
index 0000000000..ed123a76d5
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopublishingfileselectiondialog.cpp
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of Qt Creator.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file 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 "maemopublishingfileselectiondialog.h"
+#include "ui_maemopublishingfileselectiondialog.h"
+
+#include "maemopublishedprojectmodel.h"
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+MaemoPublishingFileSelectionDialog::MaemoPublishingFileSelectionDialog(const QString &projectPath,
+ QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::MaemoPublishingFileSelectionDialog)
+{
+ ui->setupUi(this);
+ m_projectModel = new MaemoPublishedProjectModel(this);
+ const QModelIndex rootIndex = m_projectModel->setRootPath(projectPath);
+ m_projectModel->initFilesToExclude();
+ ui->projectView->setModel(m_projectModel);
+ ui->projectView->setRootIndex(rootIndex);
+ ui->projectView->header()->setResizeMode(0, QHeaderView::ResizeToContents);
+}
+
+MaemoPublishingFileSelectionDialog::~MaemoPublishingFileSelectionDialog()
+{
+ delete ui;
+}
+
+QStringList MaemoPublishingFileSelectionDialog::filesToExclude() const
+{
+ return m_projectModel->filesToExclude();
+}
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopublishingfileselectiondialog.h b/src/plugins/qt4projectmanager/qt-maemo/maemopublishingfileselectiondialog.h
new file mode 100644
index 0000000000..b1d1e4dc18
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopublishingfileselectiondialog.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of Qt Creator.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file 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 MAEMOPUBLISHINGFILESELECTIONDIALOG_H
+#define MAEMOPUBLISHINGFILESELECTIONDIALOG_H
+
+#include <QtCore/QStringList>
+#include <QtGui/QDialog>
+
+QT_BEGIN_NAMESPACE
+namespace Ui {
+ class MaemoPublishingFileSelectionDialog;
+}
+QT_END_NAMESPACE
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+class MaemoPublishingFileSelectionDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit MaemoPublishingFileSelectionDialog(const QString &projectPath,
+ QWidget *parent = 0);
+ ~MaemoPublishingFileSelectionDialog();
+ QStringList filesToExclude() const;
+
+private:
+ Ui::MaemoPublishingFileSelectionDialog *ui;
+ class MaemoPublishedProjectModel *m_projectModel;
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // MAEMOPUBLISHINGFILESELECTIONDIALOG_H
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopublishingfileselectiondialog.ui b/src/plugins/qt4projectmanager/qt-maemo/maemopublishingfileselectiondialog.ui
new file mode 100644
index 0000000000..a66247f9ee
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopublishingfileselectiondialog.ui
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MaemoPublishingFileSelectionDialog</class>
+ <widget class="QDialog" name="MaemoPublishingFileSelectionDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>704</width>
+ <height>528</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Choose Package Contents</string>
+ </property>
+ <property name="modal">
+ <bool>false</bool>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>&lt;b&gt;Please select the files you want to be included in the source tarball.&lt;/b&gt;
+</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QTreeView" name="projectView"/>
+ </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>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>MaemoPublishingFileSelectionDialog</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>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>MaemoPublishingFileSelectionDialog</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>
+ </connections>
+</ui>
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopublishingresultpagefremantlefree.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemopublishingresultpagefremantlefree.cpp
new file mode 100644
index 0000000000..32de977d43
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopublishingresultpagefremantlefree.cpp
@@ -0,0 +1,105 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "maemopublishingresultpagefremantlefree.h"
+#include "ui_maemopublishingresultpagefremantlefree.h"
+
+#include <QtGui/QAbstractButton>
+
+namespace Qt4ProjectManager {
+namespace Internal {
+typedef MaemoPublisherFremantleFree MPFF;
+
+MaemoPublishingResultPageFremantleFree::MaemoPublishingResultPageFremantleFree(MPFF *publisher,
+ QWidget *parent) : QWizardPage(parent), m_publisher(publisher),
+ ui(new Ui::MaemoPublishingResultPageFremantleFree)
+{
+ m_lastOutputType = MPFF::StatusOutput;
+ ui->setupUi(this);
+}
+
+MaemoPublishingResultPageFremantleFree::~MaemoPublishingResultPageFremantleFree()
+{
+ delete ui;
+}
+
+void MaemoPublishingResultPageFremantleFree::initializePage()
+{
+ cancelButton()->disconnect();
+ connect(cancelButton(), SIGNAL(clicked()), SLOT(handleCancelRequest()));
+ connect(m_publisher, SIGNAL(finished()), SLOT(handleFinished()));
+ connect(m_publisher,
+ SIGNAL(progressReport(QString, MaemoPublisherFremantleFree::OutputType)),
+ SLOT(handleProgress(QString, MaemoPublisherFremantleFree::OutputType)));
+ m_publisher->publish();
+}
+
+void MaemoPublishingResultPageFremantleFree::handleFinished()
+{
+ handleProgress(m_publisher->resultString(), MPFF::StatusOutput);
+ m_isComplete = true;
+ cancelButton()->setEnabled(false);
+ emit completeChanged();
+}
+
+void MaemoPublishingResultPageFremantleFree::handleProgress(const QString &text,
+ MPFF::OutputType type)
+{
+ const QString color = QLatin1String(type == MPFF::StatusOutput
+ || type == MPFF::ToolStatusOutput ? "blue" : "red");
+ ui->progressTextEdit->setTextColor(QColor(color));
+ const bool bold = type == MPFF::StatusOutput
+ || type == MPFF::ErrorOutput ? true : false;
+ QFont font = ui->progressTextEdit->currentFont();
+ font.setBold(bold);
+ ui->progressTextEdit->setCurrentFont(font);
+
+ if (type == MPFF::StatusOutput || type == MPFF::ErrorOutput
+ || m_lastOutputType == MPFF::StatusOutput
+ || m_lastOutputType == MPFF::ErrorOutput) {
+ ui->progressTextEdit->append(text);
+ } else {
+ ui->progressTextEdit->insertPlainText(text);
+ }
+ ui->progressTextEdit->moveCursor(QTextCursor::End);
+ m_lastOutputType = type;
+}
+
+void MaemoPublishingResultPageFremantleFree::handleCancelRequest()
+{
+ cancelButton()->setEnabled(false);
+ m_publisher->cancel();
+}
+
+QAbstractButton *MaemoPublishingResultPageFremantleFree::cancelButton() const
+{
+ return wizard()->button(QWizard::CancelButton);
+}
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopublishingresultpagefremantlefree.h b/src/plugins/qt4projectmanager/qt-maemo/maemopublishingresultpagefremantlefree.h
new file mode 100644
index 0000000000..cb0501c3a8
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopublishingresultpagefremantlefree.h
@@ -0,0 +1,78 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** No Commercial Usage
+**
+** This file 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.
+**
+**************************************************************************/
+#ifndef MAEMOPUBLISHINGRESULTPAGEFREMANTLEFREE_H
+#define MAEMOPUBLISHINGRESULTPAGEFREMANTLEFREE_H
+
+#include "maemopublisherfremantlefree.h"
+#include <QtGui/QWizardPage>
+
+QT_BEGIN_NAMESPACE
+namespace Ui {
+ class MaemoPublishingResultPageFremantleFree;
+}
+QT_END_NAMESPACE
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+class MaemoPublishingResultPageFremantleFree : public QWizardPage
+{
+ Q_OBJECT
+
+public:
+ explicit MaemoPublishingResultPageFremantleFree(MaemoPublisherFremantleFree *publisher,
+ QWidget *parent = 0);
+ ~MaemoPublishingResultPageFremantleFree();
+
+private slots:
+ void handleFinished();
+ void handleProgress(const QString &text,
+ MaemoPublisherFremantleFree::OutputType type);
+ void handleCancelRequest();
+
+private:
+ virtual bool isComplete() const { return m_isComplete; }
+ virtual void initializePage();
+
+ QAbstractButton *cancelButton() const;
+
+ MaemoPublisherFremantleFree * const m_publisher;
+ bool m_isComplete;
+ MaemoPublisherFremantleFree::OutputType m_lastOutputType;
+ Ui::MaemoPublishingResultPageFremantleFree *ui;
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // MAEMOPUBLISHINGRESULTPAGEFREMANTLEFREE_H
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopublishingresultpagefremantlefree.ui b/src/plugins/qt4projectmanager/qt-maemo/maemopublishingresultpagefremantlefree.ui
new file mode 100644
index 0000000000..f7f429ccf8
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopublishingresultpagefremantlefree.ui
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MaemoPublishingResultPageFremantleFree</class>
+ <widget class="QWizardPage" name="MaemoPublishingResultPageFremantleFree">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>414</width>
+ <height>337</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>WizardPage</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QGroupBox" name="progressGroupBox">
+ <property name="title">
+ <string>Progress</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QTextEdit" name="progressTextEdit"/>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopublishinguploadsettingspagefremantlefree.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemopublishinguploadsettingspagefremantlefree.cpp
new file mode 100644
index 0000000000..608598a461
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopublishinguploadsettingspagefremantlefree.cpp
@@ -0,0 +1,71 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "maemopublishinguploadsettingspagefremantlefree.h"
+#include "ui_maemopublishinguploadsettingspagefremantlefree.h"
+
+#include "maemopublisherfremantlefree.h"
+
+#include <utils/pathchooser.h>
+
+#include <QtCore/QDir>
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+MaemoPublishingUploadSettingsPageFremantleFree::MaemoPublishingUploadSettingsPageFremantleFree(MaemoPublisherFremantleFree *publisher,
+ QWidget *parent) :
+ QWizardPage(parent),
+ m_publisher(publisher),
+ ui(new Ui::MaemoPublishingUploadSettingsPageFremantleFree)
+{
+ ui->setupUi(this);
+ setTitle(tr("Publishing to Fremantle's \"Extras-devel/free\" Repository"));
+ setSubTitle(tr("Upload options"));
+ ui->privateKeyPathChooser->setExpectedKind(Utils::PathChooser::File);
+ ui->privateKeyPathChooser->setPromptDialogTitle(tr("Choose a private key file"));
+ ui->privateKeyPathChooser->setPath(QDir::toNativeSeparators(QDir::homePath() + QLatin1String("/.ssh/id_rsa")));
+ ui->serverAddressLineEdit->setText(QLatin1String("drop.maemo.org"));
+ ui->targetDirectoryOnServerLineEdit->setText(QLatin1String("/var/www/extras-devel/incoming-builder/fremantle/"));
+}
+
+MaemoPublishingUploadSettingsPageFremantleFree::~MaemoPublishingUploadSettingsPageFremantleFree()
+{
+ delete ui;
+}
+
+bool MaemoPublishingUploadSettingsPageFremantleFree::validatePage()
+{
+ m_publisher->setSshParams(ui->serverAddressLineEdit->text(),
+ ui->garageAccountLineEdit->text(), ui->privateKeyPathChooser->path(),
+ ui->targetDirectoryOnServerLineEdit->text());
+ return true;
+}
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopublishinguploadsettingspagefremantlefree.h b/src/plugins/qt4projectmanager/qt-maemo/maemopublishinguploadsettingspagefremantlefree.h
new file mode 100644
index 0000000000..1ecba224c5
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopublishinguploadsettingspagefremantlefree.h
@@ -0,0 +1,63 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 MAEMOPUBLISHINGUPLOADSETTINGSWIZARDPAGE_H
+#define MAEMOPUBLISHINGUPLOADSETTINGSWIZARDPAGE_H
+
+#include <QtGui/QWizardPage>
+
+QT_BEGIN_NAMESPACE
+namespace Ui {
+ class MaemoPublishingUploadSettingsPageFremantleFree;
+}
+QT_END_NAMESPACE
+
+namespace Qt4ProjectManager {
+namespace Internal {
+class MaemoPublisherFremantleFree;
+
+class MaemoPublishingUploadSettingsPageFremantleFree : public QWizardPage
+{
+ Q_OBJECT
+
+public:
+ explicit MaemoPublishingUploadSettingsPageFremantleFree(MaemoPublisherFremantleFree *publisher,
+ QWidget *parent = 0);
+ ~MaemoPublishingUploadSettingsPageFremantleFree();
+
+private:
+ virtual bool validatePage();
+
+ MaemoPublisherFremantleFree * const m_publisher;
+ Ui::MaemoPublishingUploadSettingsPageFremantleFree *ui;
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // MAEMOPUBLISHINGUPLOADSETTINGSWIZARDPAGE_H
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopublishinguploadsettingspagefremantlefree.ui b/src/plugins/qt4projectmanager/qt-maemo/maemopublishinguploadsettingspagefremantlefree.ui
new file mode 100644
index 0000000000..48064654d3
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopublishinguploadsettingspagefremantlefree.ui
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MaemoPublishingUploadSettingsPageFremantleFree</class>
+ <widget class="QWizardPage" name="MaemoPublishingUploadSettingsPageFremantleFree">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>636</width>
+ <height>128</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>WizardPage</string>
+ </property>
+ <property name="title">
+ <string>Upload Settings</string>
+ </property>
+ <layout class="QFormLayout" name="formLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="accountNameLabel">
+ <property name="text">
+ <string>Garage account name:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QLineEdit" name="garageAccountLineEdit"/>
+ </item>
+ <item>
+ <widget class="QLabel" name="getAccountLabel">
+ <property name="text">
+ <string>&lt;a href=&quot;https://garage.maemo.org/account/register.php&quot;&gt;Get an account&lt;/a&gt;</string>
+ </property>
+ <property name="openExternalLinks">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>&lt;a href=&quot;https://garage.maemo.org/extras-assistant/index.php&quot;&gt;Request upload rights&lt;/a&gt;</string>
+ </property>
+ <property name="openExternalLinks">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="keyFileLabel">
+ <property name="text">
+ <string>Private key file:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="Utils::PathChooser" name="privateKeyPathChooser" native="true"/>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="serverAddressLabel">
+ <property name="text">
+ <string>Server address:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLineEdit" name="serverAddressLineEdit"/>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="targetDirectoryOnServerLabel">
+ <property name="text">
+ <string>Target directory on server:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QLineEdit" name="targetDirectoryOnServerLineEdit"/>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>Utils::PathChooser</class>
+ <extends>QWidget</extends>
+ <header location="global">utils/pathchooser.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopublishingwizardfactories.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemopublishingwizardfactories.cpp
new file mode 100644
index 0000000000..422e449fa0
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopublishingwizardfactories.cpp
@@ -0,0 +1,95 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "maemopublishingwizardfactories.h"
+
+#include "maemopublishingwizardfremantlefree.h"
+#include "maemotoolchain.h"
+
+#include <projectexplorer/target.h>
+#include <qt4projectmanager/qmakestep.h>
+#include <qt4projectmanager/qt4project.h>
+#include <qt4projectmanager/qt4projectmanagerconstants.h>
+
+using namespace ProjectExplorer;
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+MaemoPublishingWizardFactoryFremantleFree::MaemoPublishingWizardFactoryFremantleFree(QObject *parent)
+ : IPublishingWizardFactory(parent)
+{
+}
+
+QString MaemoPublishingWizardFactoryFremantleFree::displayName() const
+{
+ return tr("Publish for \"Fremantle Extras-devel free\" repository");
+}
+
+QString MaemoPublishingWizardFactoryFremantleFree::description() const
+{
+ return tr("This wizard will create a source archive and optionally upload "
+ "it to a build server, where the project will be compiled and "
+ "packaged and then moved to the \"Extras-devel free\" "
+ "repository, from where users can install it onto their N900 "
+ "devices. For the upload functionality, an account at "
+ "garage.maemo.org is required.");
+}
+
+bool MaemoPublishingWizardFactoryFremantleFree::canCreateWizard(const Project *project) const
+{
+ if (!qobject_cast<const Qt4Project *>(project))
+ return false;
+ foreach (const Target *const target, project->targets()) {
+ if (target->id() != QLatin1String(Constants::MAEMO_DEVICE_TARGET_ID))
+ continue;
+ foreach (const BuildConfiguration *const bc, target->buildConfigurations()) {
+ const Qt4BuildConfiguration *const qt4Bc
+ = qobject_cast<const Qt4BuildConfiguration *>(bc);
+ if (!qt4Bc)
+ continue;
+ const MaemoToolChain * const tc
+ = dynamic_cast<MaemoToolChain *>(qt4Bc->toolChain());
+ if (!tc)
+ continue;
+ if (tc->version() == MaemoToolChain::Maemo5)
+ return true;
+ }
+ break;
+ }
+ return false;
+}
+
+QWizard *MaemoPublishingWizardFactoryFremantleFree::createWizard(const Project *project) const
+{
+ Q_ASSERT(canCreateWizard(project));
+ return new MaemoPublishingWizardFremantleFree(project);
+}
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopublishingwizardfactories.h b/src/plugins/qt4projectmanager/qt-maemo/maemopublishingwizardfactories.h
new file mode 100644
index 0000000000..dbbc30df57
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopublishingwizardfactories.h
@@ -0,0 +1,57 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 MAEMOPUBLISHINGSERVICE_H
+#define MAEMOPUBLISHINGSERVICE_H
+
+#include <projectexplorer/publishing/ipublishingwizardfactory.h>
+
+namespace Core {
+class SshRemoteProcessRunner;
+}
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+class MaemoPublishingWizardFactoryFremantleFree
+ : public ProjectExplorer::IPublishingWizardFactory
+{
+ Q_OBJECT
+public:
+ explicit MaemoPublishingWizardFactoryFremantleFree(QObject *parent =0);
+private:
+ virtual QString displayName() const;
+ virtual QString description() const;
+ virtual bool canCreateWizard(const ProjectExplorer::Project *project) const;
+ virtual QWizard *createWizard(const ProjectExplorer::Project *project) const;
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // MAEMOPUBLISHINGSERVICE_H
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopublishingwizardfremantlefree.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemopublishingwizardfremantlefree.cpp
new file mode 100644
index 0000000000..510001ddd2
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopublishingwizardfremantlefree.cpp
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of Qt Creator.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file 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 "maemopublishingwizardfremantlefree.h"
+
+#include "maemopublishingresultpagefremantlefree.h"
+#include "maemopublisherfremantlefree.h"
+#include "maemopublishinguploadsettingspagefremantlefree.h"
+#include "maemopublishingbuildsettingspagefremantlefree.h"
+
+using namespace ProjectExplorer;
+
+namespace Qt4ProjectManager {
+namespace Internal {
+namespace {
+enum PageId { BuildSettingsPageId, UploadSettingsPageId, ResultPageId };
+} // anonymous namespace
+
+MaemoPublishingWizardFremantleFree::MaemoPublishingWizardFremantleFree(const Project *project,
+ QWidget *parent) :
+ QWizard(parent),
+ m_project(project),
+ m_publisher(new MaemoPublisherFremantleFree(project, this))
+{
+ setOption(NoCancelButton, false);
+ const QString titleText
+ = tr("Publishing to Fremantle's \"Extras-devel free\" Repository");
+ m_buildSettingsPage
+ = new MaemoPublishingBuildSettingsPageFremantleFree(project, m_publisher);
+ m_buildSettingsPage->setTitle(titleText);
+ m_buildSettingsPage->setSubTitle(tr("Build Settings"));
+ setPage(BuildSettingsPageId, m_buildSettingsPage);
+ m_uploadSettingsPage
+ = new MaemoPublishingUploadSettingsPageFremantleFree(m_publisher);
+ m_uploadSettingsPage->setTitle(titleText);
+ m_uploadSettingsPage->setSubTitle(tr("Upload Settings"));
+ m_uploadSettingsPage->setCommitPage(true);
+ setPage(UploadSettingsPageId, m_uploadSettingsPage);
+ m_resultPage = new MaemoPublishingResultPageFremantleFree(m_publisher);
+ m_resultPage->setTitle(titleText);
+ m_resultPage->setSubTitle(tr("Result"));
+ setPage(ResultPageId, m_resultPage);
+}
+
+int MaemoPublishingWizardFremantleFree::nextId() const
+{
+ if (currentPage()->isCommitPage())
+ return ResultPageId;
+ return QWizard::nextId();
+}
+
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopublishingwizardfremantlefree.h b/src/plugins/qt4projectmanager/qt-maemo/maemopublishingwizardfremantlefree.h
new file mode 100644
index 0000000000..0158fd7dc4
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopublishingwizardfremantlefree.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of Qt Creator.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file 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 MAEMOPUBLISHINGWIZARDFREMANTLEFREE_H
+#define MAEMOPUBLISHINGWIZARDFREMANTLEFREE_H
+
+#include <QtGui/QWizard>
+
+namespace ProjectExplorer {
+class Project;
+}
+
+namespace Qt4ProjectManager {
+namespace Internal {
+class MaemoPublishingResultPageFremantleFree;
+class MaemoPublisherFremantleFree;
+class MaemoPublishingUploadSettingsPageFremantleFree;
+class MaemoPublishingBuildSettingsPageFremantleFree;
+
+class MaemoPublishingWizardFremantleFree : public QWizard
+{
+ Q_OBJECT
+public:
+ explicit MaemoPublishingWizardFremantleFree(const ProjectExplorer::Project *project,
+ QWidget *parent = 0);
+
+private:
+ virtual int nextId() const;
+
+ const ProjectExplorer::Project * const m_project;
+ MaemoPublisherFremantleFree * const m_publisher;
+ MaemoPublishingBuildSettingsPageFremantleFree *m_buildSettingsPage;
+ MaemoPublishingUploadSettingsPageFremantleFree *m_uploadSettingsPage;
+ MaemoPublishingResultPageFremantleFree *m_resultPage;
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // MAEMOPUBLISHINGWIZARDFREMANTLEFREE_H
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoqemumanager.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemoqemumanager.cpp
index 85919a6eb8..e2f93e1549 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemoqemumanager.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoqemumanager.cpp
@@ -33,6 +33,10 @@
#include "maemoqemumanager.h"
+#include "maemoglobal.h"
+#include "maemomanager.h"
+#include "maemoqemuruntimeparser.h"
+#include "maemosettingspages.h"
#include "maemorunconfiguration.h"
#include "maemotoolchain.h"
#include "qtversionmanager.h"
@@ -41,6 +45,7 @@
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
+#include <coreplugin/uniqueidmanager.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/icore.h>
#include <coreplugin/icontext.h>
@@ -54,14 +59,11 @@
#include <QtCore/QList>
#include <QtCore/QSet>
#include <QtCore/QStringBuilder>
-#include <QtCore/QTextStream>
#include <QtGui/QAction>
#include <QtGui/QDesktopServices>
#include <QtGui/QMessageBox>
-#include <QtXml/QXmlStreamReader>
-
#include <limits.h>
using namespace ProjectExplorer;
@@ -71,7 +73,6 @@ using namespace Qt4ProjectManager::Internal;
MaemoQemuManager *MaemoQemuManager::m_instance = 0;
const QSize iconSize = QSize(24, 20);
-const QLatin1String binQmake("/bin/qmake" EXEC_SUFFIX);
MaemoQemuManager::MaemoQemuManager(QObject *parent)
: QObject(parent)
@@ -146,9 +147,9 @@ MaemoQemuManager &MaemoQemuManager::instance(QObject *parent)
return *m_instance;
}
-bool MaemoQemuManager::runtimeForQtVersion(int uniqueId, Runtime *rt) const
+bool MaemoQemuManager::runtimeForQtVersion(int uniqueId, MaemoQemuRuntime *rt) const
{
- *rt = m_runtimes.value(uniqueId, Runtime());
+ *rt = m_runtimes.value(uniqueId, MaemoQemuRuntime());
return rt->isValid();
}
@@ -159,14 +160,9 @@ void MaemoQemuManager::qtVersionsChanged(const QList<int> &uniqueIds)
if (manager->isValidId(uniqueId)) {
QtVersion *version = manager->version(uniqueId);
if (version->supportsTargetId(Constants::MAEMO_DEVICE_TARGET_ID)) {
- const QString &qmake = version->qmakeCommand();
- const QString &runtimeRoot = runtimeForQtVersion(qmake);
- if (!runtimeRoot.isEmpty()) {
- Runtime runtime(runtimeRoot);
- if (QFile::exists(runtimeRoot))
- fillRuntimeInformation(&runtime);
- runtime.m_watchPath =
- runtimeRoot.left(runtimeRoot.lastIndexOf(QLatin1Char('/')));
+ MaemoQemuRuntime runtime
+ = MaemoQemuRuntimeParser::parseRuntime(version);
+ if (runtime.isValid()) {
m_runtimes.insert(uniqueId, runtime);
if (!m_runtimeRootWatcher->directories().contains(runtime.m_watchPath))
m_runtimeRootWatcher->addPath(runtime.m_watchPath);
@@ -227,7 +223,7 @@ void MaemoQemuManager::projectChanged(ProjectExplorer::Project *project)
bool targetIsMaemo(const QString &id)
{
- return id == QLatin1String(Constants::MAEMO_DEVICE_TARGET_ID);
+ return id == QLatin1String(Qt4ProjectManager::Constants::MAEMO_DEVICE_TARGET_ID);
}
void MaemoQemuManager::targetAdded(ProjectExplorer::Target *target)
@@ -362,39 +358,10 @@ void MaemoQemuManager::startRuntime()
}
m_runningQtId = version->uniqueId();
- const QString root
- = QDir::toNativeSeparators(maddeRoot(version->qmakeCommand())
- + QLatin1Char('/'));
- const Runtime rt = m_runtimes.value(version->uniqueId());
- QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
-#ifdef Q_OS_WIN
- const QLatin1Char colon(';');
- const QLatin1String key("PATH");
- env.insert(key, root % QLatin1String("bin") % colon % env.value(key));
- env.insert(key, root % QLatin1String("madlib") % colon % env.value(key));
-#endif
- for (QHash<QString, QString>::ConstIterator it = rt.m_environment.constBegin();
- it != rt.m_environment.constEnd(); ++it)
- env.insert(it.key(), it.value());
- m_qemuProcess->setProcessEnvironment(env);
+ const MaemoQemuRuntime rt = m_runtimes.value(version->uniqueId());
+ m_qemuProcess->setProcessEnvironment(rt.environment());
m_qemuProcess->setWorkingDirectory(rt.m_root);
-
- // This is complex because of extreme MADDE weirdness.
- const bool pathIsRelative = QFileInfo(rt.m_bin).isRelative();
- const QString app =
-#ifdef Q_OS_WIN
- root % (pathIsRelative
- ? QLatin1String("madlib/") % rt.m_bin // Fremantle.
- : rt.m_bin) // Haramattan.
- % QLatin1String(".exe");
-#else
- pathIsRelative
- ? root % QLatin1String("madlib/") % rt.m_bin // Fremantle.
- : rt.m_bin; // Haramattan.
-#endif
-
- m_qemuProcess->start(app % QLatin1Char(' ') % rt.m_args,
- QIODevice::ReadWrite);
+ m_qemuProcess->start(rt.m_bin % QLatin1Char(' ') % rt.m_args);
if (!m_qemuProcess->waitForStarted())
return;
@@ -444,31 +411,27 @@ void MaemoQemuManager::qemuProcessError(QProcess::ProcessError error)
void MaemoQemuManager::qemuStatusChanged(QemuStatus status, const QString &error)
{
- QString message;
bool running = false;
-
switch (status) {
case QemuStarting:
running = true;
break;
case QemuFailedToStart:
- message = tr("Qemu failed to start: %1").arg(error);
+ QMessageBox::warning(0, tr("Qemu error"),
+ tr("Qemu failed to start: %1"));
break;
case QemuCrashed:
- message = tr("Qemu crashed");
+ MaemoManager::instance().qemuSettingsPage()->showQemuCrashDialog();
break;
case QemuFinished:
- message = error;
- break;
case QemuUserReason:
- message = error;
+ if (!error.isEmpty())
+ QMessageBox::warning(0, tr("Qemu error"), error);
break;
default:
Q_ASSERT(!"Missing handling of Qemu status");
}
- if (!message.isEmpty())
- QMessageBox::warning(0, tr("Qemu error"), message);
updateStarterIcon(running);
}
@@ -481,14 +444,14 @@ void MaemoQemuManager::qemuOutput()
void MaemoQemuManager::runtimeRootChanged(const QString &directory)
{
QList<int> uniqueIds;
- QMap<int, Runtime>::const_iterator it;
+ QMap<int, MaemoQemuRuntime>::const_iterator it;
for (it = m_runtimes.constBegin(); it != m_runtimes.constEnd(); ++it) {
if (QDir(it.value().m_watchPath) == QDir(directory))
uniqueIds.append(it.key());
}
foreach (int uniqueId, uniqueIds) {
- Runtime runtime = m_runtimes.value(uniqueId, Runtime());
+ MaemoQemuRuntime runtime = m_runtimes.value(uniqueId, MaemoQemuRuntime());
if (runtime.isValid()) {
if (QFile::exists(runtime.m_root)) {
// nothing changed, so we can remove it
@@ -511,7 +474,7 @@ void MaemoQemuManager::runtimeFolderChanged(const QString &directory)
{
if (QFile::exists(directory + QLatin1String("/information"))) {
QList<int> uniqueIds;
- QMap<int, Runtime>::const_iterator it;
+ QMap<int, MaemoQemuRuntime>::const_iterator it;
for (it = m_runtimes.constBegin(); it != m_runtimes.constEnd(); ++it) {
if (QDir(it.value().m_root) == QDir(directory))
uniqueIds.append(it.key());
@@ -559,7 +522,7 @@ void MaemoQemuManager::toggleStarterButton(Target *target)
if (m_runningQtId == uniqueId)
isRunning = false;
- m_qemuAction->setEnabled(m_runtimes.value(uniqueId, Runtime()).isValid()
+ m_qemuAction->setEnabled(m_runtimes.value(uniqueId, MaemoQemuRuntime()).isValid()
&& targetUsesMatchingRuntimeConfig(target) && !isRunning);
m_qemuAction->setVisible(!m_runtimes.isEmpty() && sessionHasMaemoTarget());
}
@@ -589,7 +552,7 @@ bool MaemoQemuManager::targetUsesMatchingRuntimeConfig(Target *target,
if (!bc)
return false;
QtVersion *version = bc->qtVersion();
- if (!version || !m_runtimes.value(version->uniqueId(), Runtime()).isValid())
+ if (!version || !m_runtimes.value(version->uniqueId(), MaemoQemuRuntime()).isValid())
return false;
if (qtVersion)
@@ -598,154 +561,6 @@ bool MaemoQemuManager::targetUsesMatchingRuntimeConfig(Target *target,
return config.isValid() && config.type == MaemoDeviceConfig::Simulator;
}
-QString MaemoQemuManager::maddeRoot(const QString &qmake) const
-{
- QDir dir(QDir::cleanPath(qmake).remove(binQmake));
- dir.cdUp(); dir.cdUp();
- return dir.absolutePath();
-}
-
-QString MaemoQemuManager::targetRoot(const QString &qmake) const
-{
- const QString target = QDir::cleanPath(qmake).remove(binQmake);
- return target.mid(target.lastIndexOf(QLatin1Char('/')) + 1);
-}
-
-bool MaemoQemuManager::fillRuntimeInformation(Runtime *runtime) const
-{
- const QStringList files = QDir(runtime->m_root).entryList(QDir::Files
- | QDir::NoSymLinks | QDir::NoDotAndDotDot);
-
- // we need at least the information file
- const QLatin1String infoFile("information");
- if (files.contains(infoFile)) {
- QFile file(runtime->m_root + QLatin1Char('/') + infoFile);
- if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
- QMap<QString, QString> map;
- QTextStream stream(&file);
- while (!stream.atEnd()) {
- const QString &line = stream.readLine().trimmed();
- const int index = line.indexOf(QLatin1Char('='));
- map.insert(line.mid(0, index).remove(QLatin1Char('\'')),
- line.mid(index + 1).remove(QLatin1Char('\'')));
- }
-
- runtime->m_bin = map.value(QLatin1String("qemu"));
- runtime->m_args = map.value(QLatin1String("qemu_args"));
- setEnvironment(runtime, map.value(QLatin1String("libpath")));
- runtime->m_sshPort = map.value(QLatin1String("sshport"));
- runtime->m_freePorts = MaemoPortList();
- int i = 2;
- while (true) {
- const QString port = map.value(QLatin1String("redirport")
- + QString::number(i++));
- if (port.isEmpty())
- break;
- runtime->m_freePorts.addPort(port.toInt());
- }
- return true;
- }
- }
- return false;
-}
-
-void MaemoQemuManager::setEnvironment(Runtime *runTime,
- const QString &envSpec) const
-{
- QString remainingEnvSpec = envSpec;
- QString currentKey;
- while (true) {
- const int nextEqualsSignPos
- = remainingEnvSpec.indexOf(QLatin1Char('='));
- if (nextEqualsSignPos == -1) {
- if (!currentKey.isEmpty())
- runTime->m_environment.insert(currentKey, remainingEnvSpec);
- break;
- }
- const int keyStartPos
- = remainingEnvSpec.lastIndexOf(QRegExp(QLatin1String("\\s")),
- nextEqualsSignPos) + 1;
- if (!currentKey.isEmpty()) {
- const int valueEndPos
- = remainingEnvSpec.lastIndexOf(QRegExp(QLatin1String("\\S")),
- qMax(0, keyStartPos - 1)) + 1;
- runTime->m_environment.insert(currentKey,
- remainingEnvSpec.left(valueEndPos));
- }
- currentKey = remainingEnvSpec.mid(keyStartPos,
- nextEqualsSignPos - keyStartPos);
- remainingEnvSpec.remove(0, nextEqualsSignPos + 1);
- }
-}
-
-QString MaemoQemuManager::runtimeForQtVersion(const QString &qmakeCommand) const
-{
- const QString &target = targetRoot(qmakeCommand);
- const QString &madRoot = maddeRoot(qmakeCommand);
-
- QString madCommand = madRoot + QLatin1String("/bin/mad");
- if (!QFileInfo(madCommand).exists())
- return QString();
-
- QProcess madProc;
- QStringList arguments(QLatin1String("info"));
-
-#ifdef Q_OS_WIN
- QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
- env.insert("HOME",
- QDesktopServices::storageLocation(QDesktopServices::HomeLocation));
- env.insert(QLatin1String("PATH"),
- QDir::toNativeSeparators(madRoot % QLatin1String("/bin"))
- % QLatin1Char(';') % env.value(QLatin1String("PATH")));
-
- madProc.setProcessEnvironment(env);
-
- arguments.prepend(madCommand);
- madCommand = madRoot + QLatin1String("/bin/sh.exe");
-#endif
-
- madProc.start(madCommand, arguments);
- if (!madProc.waitForStarted() || !madProc.waitForFinished())
- return QString();
-
- QStringList installedRuntimes;
- QString targetRuntime;
- QXmlStreamReader infoReader(madProc.readAllStandardOutput());
- while (!infoReader.atEnd() && !installedRuntimes.contains(targetRuntime)) {
- if (infoReader.readNext() == QXmlStreamReader::StartElement) {
- if (targetRuntime.isEmpty()
- && infoReader.name() == QLatin1String("target")) {
- const QXmlStreamAttributes &attrs = infoReader.attributes();
- if (attrs.value(QLatin1String("target_id")) == target)
- targetRuntime = attrs.value("runtime_id").toString();
- } else if (infoReader.name() == QLatin1String("runtime")) {
- const QXmlStreamAttributes attrs = infoReader.attributes();
- while (!infoReader.atEnd()) {
- if (infoReader.readNext() == QXmlStreamReader::EndElement
- && infoReader.name() == QLatin1String("runtime"))
- break;
- if (infoReader.tokenType() == QXmlStreamReader::StartElement
- && infoReader.name() == QLatin1String("installed")) {
- if (infoReader.readNext() == QXmlStreamReader::Characters
- && infoReader.text() == QLatin1String("true")) {
- if (attrs.hasAttribute(QLatin1String("runtime_id")))
- installedRuntimes << attrs.value(QLatin1String("runtime_id")).toString();
- else if (attrs.hasAttribute(QLatin1String("id"))) {
- // older MADDE seems to use only id
- installedRuntimes << attrs.value(QLatin1String("id")).toString();
- }
- }
- break;
- }
- }
- }
- }
- }
- if (installedRuntimes.contains(targetRuntime))
- return madRoot + QLatin1String("/runtimes/") + targetRuntime;
- return QString();
-}
-
void MaemoQemuManager::notify(const QList<int> uniqueIds)
{
qtVersionsChanged(uniqueIds);
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoqemumanager.h b/src/plugins/qt4projectmanager/qt-maemo/maemoqemumanager.h
index 00545a448a..299d217459 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemoqemumanager.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoqemumanager.h
@@ -35,18 +35,17 @@
#define QEMURUNTIMEMANAGER_H
#include "maemoconstants.h"
-#include "maemodeviceconfigurations.h"
+#include "maemoqemuruntime.h"
-#include <QtCore/QHash>
#include <QtCore/QMap>
#include <QtCore/QObject>
#include <QtCore/QProcess>
#include <QtGui/QIcon>
-QT_FORWARD_DECLARE_CLASS(QAction);
+QT_FORWARD_DECLARE_CLASS(QAction)
QT_FORWARD_DECLARE_CLASS(QFileSystemWatcher)
-QT_FORWARD_DECLARE_CLASS(QStringList);
+QT_FORWARD_DECLARE_CLASS(QStringList)
namespace ProjectExplorer {
class BuildConfiguration;
@@ -60,23 +59,6 @@ namespace Qt4ProjectManager {
namespace Internal {
class MaemoRunConfiguration;
-struct Runtime
-{
- Runtime() {}
- Runtime(const QString &root)
- : m_root(root) {}
- bool isValid() const {
- return !m_bin.isEmpty();
- }
-
- QString m_bin;
- QString m_root;
- QString m_args;
- QString m_sshPort;
- QString m_watchPath;
- QHash<QString, QString> m_environment;
- MaemoPortList m_freePorts;
-};
class MaemoQemuManager : public QObject
{
@@ -85,7 +67,7 @@ class MaemoQemuManager : public QObject
public:
static MaemoQemuManager& instance(QObject *parent = 0);
- bool runtimeForQtVersion(int uniqueId, Runtime *rt) const;
+ bool runtimeForQtVersion(int uniqueId, MaemoQemuRuntime *rt) const;
signals:
void qemuProcessStatus(QemuStatus, const QString &error = QString());
@@ -134,13 +116,6 @@ private:
bool targetUsesMatchingRuntimeConfig(ProjectExplorer::Target *target,
QtVersion **qtVersion = 0);
- QString maddeRoot(const QString &qmake) const;
- QString targetRoot(const QString &qmake) const;
-
- bool fillRuntimeInformation(Runtime *runtime) const;
- void setEnvironment(Runtime *runTime, const QString &envSpec) const;
- QString runtimeForQtVersion(const QString &qmakeCommand) const;
-
void notify(const QList<int> uniqueIds);
void toggleDeviceConnections(MaemoRunConfiguration *mrc, bool connect);
@@ -151,13 +126,13 @@ private:
int m_runningQtId;
bool m_userTerminated;
QIcon m_qemuStarterIcon;
- QMap<int, Runtime> m_runtimes;
+ QMap<int, MaemoQemuRuntime> m_runtimes;
static MaemoQemuManager *m_instance;
QFileSystemWatcher *m_runtimeRootWatcher;
QFileSystemWatcher *m_runtimeFolderWatcher;
};
- } // namespace Qt4ProjectManager
} // namespace Internal
+} // namespace Qt4ProjectManager
#endif // QEMURUNTIMEMANAGER_H
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoqemuruntime.h b/src/plugins/qt4projectmanager/qt-maemo/maemoqemuruntime.h
new file mode 100644
index 0000000000..9448ba1bd8
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoqemuruntime.h
@@ -0,0 +1,87 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+**
+**************************************************************************/
+#ifndef MAEMOQEMURUNTIME_H
+#define MAEMOQEMURUNTIME_H
+
+#include "maemodeviceconfigurations.h"
+#include "maemoqemusettings.h"
+
+#include <QtCore/QHash>
+#include <QtCore/QList>
+#include <QtCore/QPair>
+#include <QtCore/QProcessEnvironment>
+#include <QtCore/QString>
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+enum QemuStatus {
+ QemuStarting,
+ QemuFailedToStart,
+ QemuFinished,
+ QemuCrashed,
+ QemuUserReason
+};
+
+struct MaemoQemuRuntime
+{
+ typedef QPair<QString, QString> Variable;
+
+ MaemoQemuRuntime() {}
+ MaemoQemuRuntime(const QString &root) : m_root(root) {}
+ bool isValid() const {
+ return !m_bin.isEmpty();
+ }
+ QProcessEnvironment environment() const {
+ QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
+ foreach (const Variable &var, m_normalVars)
+ env.insert(var.first, var.second);
+ QHash<MaemoQemuSettings::OpenGlMode, QString>::ConstIterator it
+ = m_openGlBackendVarValues.find(MaemoQemuSettings::openGlMode());
+ if (it != m_openGlBackendVarValues.constEnd())
+ env.insert(m_openGlBackendVarName, it.value());
+ return env;
+ }
+
+ QString m_name;
+ QString m_bin;
+ QString m_root;
+ QString m_args;
+ QString m_sshPort;
+ QString m_watchPath;
+ MaemoPortList m_freePorts;
+ QList<Variable> m_normalVars;
+ QString m_openGlBackendVarName;
+ QHash<MaemoQemuSettings::OpenGlMode, QString> m_openGlBackendVarValues;
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // MAEMOQEMURUNTIME_H
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoqemuruntimeparser.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemoqemuruntimeparser.cpp
new file mode 100644
index 0000000000..f5ef2fe82e
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoqemuruntimeparser.cpp
@@ -0,0 +1,432 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+**
+**************************************************************************/
+#include "maemoqemuruntimeparser.h"
+
+#include "maemoglobal.h"
+#include "maemoqemusettings.h"
+
+#include <qt4projectmanager/qtversionmanager.h>
+#include <utils/qtcassert.h>
+
+#include <QtCore/QDir>
+#include <QtCore/QProcess>
+#include <QtCore/QStringList>
+#include <QtCore/QTextStream>
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+class MaemoQemuRuntimeParserV1 : public MaemoQemuRuntimeParser
+{
+public:
+ MaemoQemuRuntimeParserV1(const QString &madInfoOutput,
+ const QString &targetName, const QString &maddeRoot);
+ MaemoQemuRuntime parseRuntime();
+
+private:
+ void fillRuntimeInformation(MaemoQemuRuntime *runtime) const;
+ void setEnvironment(MaemoQemuRuntime *runTime, const QString &envSpec) const;
+};
+
+class MaemoQemuRuntimeParserV2 : public MaemoQemuRuntimeParser
+{
+public:
+ MaemoQemuRuntimeParserV2(const QString &madInfoOutput,
+ const QString &targetName, const QString &maddeRoot);
+ MaemoQemuRuntime parseRuntime();
+
+private:
+ struct Port {
+ Port() : port(-1), ssh(false) {}
+ int port;
+ bool ssh;
+ };
+
+ void handleTargetTag(QString &runtimeName);
+ MaemoQemuRuntime handleRuntimeTag();
+ void handleEnvironmentTag(MaemoQemuRuntime &runtime);
+ void handleVariableTag(MaemoQemuRuntime &runtime);
+ QList<Port> handleTcpPortListTag();
+ Port handlePortTag();
+ MaemoQemuSettings::OpenGlMode openGlTagToEnum(const QString &tag) const;
+};
+
+MaemoQemuRuntimeParser::MaemoQemuRuntimeParser(const QString &madInfoOutput,
+ const QString &targetName, const QString &maddeRoot)
+ : m_targetName(targetName),
+ m_maddeRoot(maddeRoot),
+ m_madInfoReader(madInfoOutput)
+{
+}
+
+MaemoQemuRuntime MaemoQemuRuntimeParser::parseRuntime(const QtVersion *qtVersion)
+{
+ MaemoQemuRuntime runtime;
+ const QString maddeRootPath
+ = MaemoGlobal::maddeRoot(qtVersion->qmakeCommand());
+ const QString madCommand = maddeRootPath + QLatin1String("/bin/mad");
+ if (!QFileInfo(madCommand).exists())
+ return runtime;
+ QProcess madProc;
+ MaemoGlobal::callMaddeShellScript(madProc, maddeRootPath, madCommand,
+ QStringList() << QLatin1String("info"));
+ if (!madProc.waitForStarted() || !madProc.waitForFinished())
+ return runtime;
+ const QByteArray &madInfoOutput = madProc.readAllStandardOutput();
+ const QString &targetName
+ = MaemoGlobal::targetName(qtVersion->qmakeCommand());
+ runtime = MaemoQemuRuntimeParserV2(madInfoOutput, targetName, maddeRootPath)
+ .parseRuntime();
+ if (!runtime.m_name.isEmpty()) {
+ runtime.m_root = maddeRootPath + QLatin1String("/runtimes/")
+ + runtime.m_name;
+ } else {
+ runtime = MaemoQemuRuntimeParserV1(madInfoOutput, targetName,
+ maddeRootPath).parseRuntime();
+ }
+ runtime.m_watchPath = runtime.m_root
+ .left(runtime.m_root.lastIndexOf(QLatin1Char('/')));
+
+ return runtime;
+}
+
+MaemoQemuRuntimeParserV1::MaemoQemuRuntimeParserV1(const QString &madInfoOutput,
+ const QString &targetName, const QString &maddeRoot)
+ : MaemoQemuRuntimeParser(madInfoOutput, targetName, maddeRoot)
+{
+}
+
+MaemoQemuRuntime MaemoQemuRuntimeParserV1::parseRuntime()
+{
+ QStringList installedRuntimes;
+ QString targetRuntime;
+ while (!m_madInfoReader.atEnd() && !installedRuntimes.contains(targetRuntime)) {
+ if (m_madInfoReader.readNext() == QXmlStreamReader::StartElement) {
+ if (targetRuntime.isEmpty()
+ && m_madInfoReader.name() == QLatin1String("target")) {
+ const QXmlStreamAttributes &attrs = m_madInfoReader.attributes();
+ if (attrs.value(QLatin1String("target_id")) == m_targetName)
+ targetRuntime = attrs.value("runtime_id").toString();
+ } else if (m_madInfoReader.name() == QLatin1String("runtime")) {
+ const QXmlStreamAttributes attrs = m_madInfoReader.attributes();
+ while (!m_madInfoReader.atEnd()) {
+ if (m_madInfoReader.readNext() == QXmlStreamReader::EndElement
+ && m_madInfoReader.name() == QLatin1String("runtime"))
+ break;
+ if (m_madInfoReader.tokenType() == QXmlStreamReader::StartElement
+ && m_madInfoReader.name() == QLatin1String("installed")) {
+ if (m_madInfoReader.readNext() == QXmlStreamReader::Characters
+ && m_madInfoReader.text() == QLatin1String("true")) {
+ if (attrs.hasAttribute(QLatin1String("runtime_id")))
+ installedRuntimes << attrs.value(QLatin1String("runtime_id")).toString();
+ else if (attrs.hasAttribute(QLatin1String("id"))) {
+ // older MADDE seems to use only id
+ installedRuntimes << attrs.value(QLatin1String("id")).toString();
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ MaemoQemuRuntime runtime;
+ if (installedRuntimes.contains(targetRuntime)) {
+ runtime.m_name = targetRuntime;
+ runtime.m_root = m_maddeRoot + QLatin1String("/runtimes/")
+ + targetRuntime;
+ fillRuntimeInformation(&runtime);
+ }
+ return runtime;
+
+}
+
+void MaemoQemuRuntimeParserV1::fillRuntimeInformation(MaemoQemuRuntime *runtime) const
+{
+ const QStringList files = QDir(runtime->m_root).entryList(QDir::Files
+ | QDir::NoSymLinks | QDir::NoDotAndDotDot);
+
+ const QLatin1String infoFile("information");
+ if (files.contains(infoFile)) {
+ QFile file(runtime->m_root + QLatin1Char('/') + infoFile);
+ if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ QMap<QString, QString> map;
+ QTextStream stream(&file);
+ while (!stream.atEnd()) {
+ const QString &line = stream.readLine().trimmed();
+ const int index = line.indexOf(QLatin1Char('='));
+ map.insert(line.mid(0, index).remove(QLatin1Char('\'')),
+ line.mid(index + 1).remove(QLatin1Char('\'')));
+ }
+
+ runtime->m_bin = map.value(QLatin1String("qemu"));
+ runtime->m_args = map.value(QLatin1String("qemu_args"));
+ setEnvironment(runtime, map.value(QLatin1String("libpath")));
+ runtime->m_sshPort = map.value(QLatin1String("sshport"));
+ runtime->m_freePorts = MaemoPortList();
+ int i = 2;
+ while (true) {
+ const QString port = map.value(QLatin1String("redirport")
+ + QString::number(i++));
+ if (port.isEmpty())
+ break;
+ runtime->m_freePorts.addPort(port.toInt());
+ }
+
+ // This is complex because of extreme MADDE weirdness.
+ const QString root = m_maddeRoot + QLatin1Char('/');
+ const bool pathIsRelative = QFileInfo(runtime->m_bin).isRelative();
+ runtime->m_bin =
+ #ifdef Q_OS_WIN
+ root + (pathIsRelative
+ ? QLatin1String("madlib/") + runtime->m_bin // Fremantle.
+ : runtime->m_bin) // Harmattan.
+ + QLatin1String(".exe");
+ #else
+ pathIsRelative
+ ? root + QLatin1String("madlib/") + runtime->m_bin // Fremantle.
+ : runtime->m_bin; // Harmattan.
+ #endif
+ }
+ }
+}
+
+void MaemoQemuRuntimeParserV1::setEnvironment(MaemoQemuRuntime *runTime,
+ const QString &envSpec) const
+{
+ QString remainingEnvSpec = envSpec;
+ QString currentKey;
+ while (true) {
+ const int nextEqualsSignPos
+ = remainingEnvSpec.indexOf(QLatin1Char('='));
+ if (nextEqualsSignPos == -1) {
+ if (!currentKey.isEmpty())
+ runTime->m_normalVars << MaemoQemuRuntime::Variable(currentKey,
+ remainingEnvSpec);
+ break;
+ }
+ const int keyStartPos
+ = remainingEnvSpec.lastIndexOf(QRegExp(QLatin1String("\\s")),
+ nextEqualsSignPos) + 1;
+ if (!currentKey.isEmpty()) {
+ const int valueEndPos
+ = remainingEnvSpec.lastIndexOf(QRegExp(QLatin1String("\\S")),
+ qMax(0, keyStartPos - 1)) + 1;
+ runTime->m_normalVars << MaemoQemuRuntime::Variable(currentKey,
+ remainingEnvSpec.left(valueEndPos));
+ }
+ currentKey = remainingEnvSpec.mid(keyStartPos,
+ nextEqualsSignPos - keyStartPos);
+ remainingEnvSpec.remove(0, nextEqualsSignPos + 1);
+ }
+}
+
+
+MaemoQemuRuntimeParserV2::MaemoQemuRuntimeParserV2(const QString &madInfoOutput,
+ const QString &targetName, const QString &maddeRoot)
+ : MaemoQemuRuntimeParser(madInfoOutput, targetName, maddeRoot)
+{
+}
+
+MaemoQemuRuntime MaemoQemuRuntimeParserV2::parseRuntime()
+{
+ QString runtimeName;
+ QList<MaemoQemuRuntime> runtimes;
+ while (m_madInfoReader.readNextStartElement()) {
+ if (m_madInfoReader.name() == QLatin1String("madde")) {
+ while (m_madInfoReader.readNextStartElement()) {
+ if (m_madInfoReader.name() == QLatin1String("targets")) {
+ while (m_madInfoReader.readNextStartElement())
+ handleTargetTag(runtimeName);
+ } else if (m_madInfoReader.name() == QLatin1String("runtimes")) {
+ while (m_madInfoReader.readNextStartElement()) {
+ const MaemoQemuRuntime &rt = handleRuntimeTag();
+ if (!rt.m_name.isEmpty() && !rt.m_bin.isEmpty()
+ && !rt.m_args.isEmpty()) {
+ runtimes << rt;
+ }
+ }
+ } else {
+ m_madInfoReader.skipCurrentElement();
+ }
+ }
+ }
+ }
+ foreach (const MaemoQemuRuntime &rt, runtimes) {
+ if (rt.m_name == runtimeName)
+ return rt;
+ }
+ return MaemoQemuRuntime();
+}
+
+void MaemoQemuRuntimeParserV2::handleTargetTag(QString &runtimeName)
+{
+ const QXmlStreamAttributes &attrs = m_madInfoReader.attributes();
+ if (m_madInfoReader.name() == QLatin1String("target") && runtimeName.isEmpty()
+ && attrs.value(QLatin1String("name")) == m_targetName
+ && attrs.value(QLatin1String("installed")) == QLatin1String("true")) {
+ while (m_madInfoReader.readNextStartElement()) {
+ if (m_madInfoReader.name() == QLatin1String("runtime"))
+ runtimeName = m_madInfoReader.readElementText();
+ else
+ m_madInfoReader.skipCurrentElement();
+ }
+ } else {
+ m_madInfoReader.skipCurrentElement();
+ }
+}
+
+MaemoQemuRuntime MaemoQemuRuntimeParserV2::handleRuntimeTag()
+{
+ MaemoQemuRuntime runtime;
+ const QXmlStreamAttributes &attrs = m_madInfoReader.attributes();
+ if (m_madInfoReader.name() != QLatin1String("runtime")
+ || attrs.value(QLatin1String("installed")) != QLatin1String("true")) {
+ m_madInfoReader.skipCurrentElement();
+ return runtime;
+ }
+ runtime.m_name = attrs.value(QLatin1String("name")).toString();
+ while (m_madInfoReader.readNextStartElement()) {
+ if (m_madInfoReader.name() == QLatin1String("exec-path")) {
+ runtime.m_bin = m_madInfoReader.readElementText();
+ } else if (m_madInfoReader.name() == QLatin1String("args")) {
+ runtime.m_args = m_madInfoReader.readElementText();
+ } else if (m_madInfoReader.name() == QLatin1String("environment")) {
+ handleEnvironmentTag(runtime);
+ } else if (m_madInfoReader.name() == QLatin1String("tcpportmap")) {
+ const QList<Port> &ports = handleTcpPortListTag();
+ foreach (const Port &port, ports) {
+ if (port.ssh)
+ runtime.m_sshPort = QString::number(port.port);
+ else
+ runtime.m_freePorts.addPort(port.port);
+ }
+ } else {
+ m_madInfoReader.skipCurrentElement();
+ }
+ }
+ return runtime;
+}
+
+void MaemoQemuRuntimeParserV2::handleEnvironmentTag(MaemoQemuRuntime &runtime)
+{
+ while (m_madInfoReader.readNextStartElement())
+ handleVariableTag(runtime);
+
+#ifdef Q_OS_WIN
+ const QString root = QDir::toNativeSeparators(m_maddeRoot)
+ + QLatin1Char('/');
+ const QLatin1Char colon(';');
+ const QLatin1String key("PATH");
+ QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
+ runtime.m_normalVars << MaemoQemuRuntime::Variable(key,
+ root + QLatin1String("bin") + colon + env.value(key));
+ runtime.m_normalVars << MaemoQemuRuntime::Variable(key,
+ root + QLatin1String("madlib") + colon + env.value(key));
+#endif
+}
+
+void MaemoQemuRuntimeParserV2::handleVariableTag(MaemoQemuRuntime &runtime)
+{
+ if (m_madInfoReader.name() != QLatin1String("variable")) {
+ m_madInfoReader.skipCurrentElement();
+ return;
+ }
+
+ const bool isGlBackend = m_madInfoReader.attributes().value(QLatin1String("purpose"))
+ == QLatin1String("glbackend");
+ QString varName;
+ QString varValue;
+ while (m_madInfoReader.readNextStartElement()) {
+ const QXmlStreamAttributes &attrs = m_madInfoReader.attributes();
+ if (m_madInfoReader.name() == QLatin1String("name")) {
+ varName = m_madInfoReader.readElementText();
+ } else if (m_madInfoReader.name() == QLatin1String("value")
+ && attrs.value(QLatin1String("set")) != QLatin1String("false")) {
+ varValue = m_madInfoReader.readElementText();
+ if (isGlBackend) {
+ MaemoQemuSettings::OpenGlMode openGlMode
+ = openGlTagToEnum(attrs.value(QLatin1String("option")).toString());
+ runtime.m_openGlBackendVarValues.insert(openGlMode, varValue);
+ }
+ } else {
+ m_madInfoReader.skipCurrentElement();
+ }
+ }
+
+ if (varName.isEmpty())
+ return;
+ if (isGlBackend) {
+ runtime.m_openGlBackendVarName = varName;
+ } else {
+ runtime.m_normalVars << MaemoQemuRuntime::Variable(varName, varValue);
+ }
+}
+
+QList<MaemoQemuRuntimeParserV2::Port> MaemoQemuRuntimeParserV2::handleTcpPortListTag()
+{
+ QList<Port> ports;
+ while (m_madInfoReader.readNextStartElement()) {
+ const Port &port = handlePortTag();
+ if (port.port != -1)
+ ports << port;
+ }
+ return ports;
+}
+
+MaemoQemuRuntimeParserV2::Port MaemoQemuRuntimeParserV2::handlePortTag()
+{
+ Port port;
+ if (m_madInfoReader.name() == QLatin1String("port")) {
+ const QXmlStreamAttributes &attrs = m_madInfoReader.attributes();
+ port.ssh = attrs.value(QLatin1String("service")) == QLatin1String("ssh");
+ while (m_madInfoReader.readNextStartElement()) {
+ if (m_madInfoReader.name() == QLatin1String("host"))
+ port.port = m_madInfoReader.readElementText().toInt();
+ else
+ m_madInfoReader.skipCurrentElement();
+ }
+ }
+ return port;
+}
+
+MaemoQemuSettings::OpenGlMode MaemoQemuRuntimeParserV2::openGlTagToEnum(const QString &tag) const
+{
+ if (tag == QLatin1String("hardware-acceleration"))
+ return MaemoQemuSettings::HardwareAcceleration;
+ if (tag == QLatin1String("software-rendering"))
+ return MaemoQemuSettings::SoftwareRendering;
+ if (tag == QLatin1String("autodetect"))
+ return MaemoQemuSettings::AutoDetect;
+ QTC_ASSERT(false, return MaemoQemuSettings::AutoDetect);
+}
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoqemuruntimeparser.h b/src/plugins/qt4projectmanager/qt-maemo/maemoqemuruntimeparser.h
new file mode 100644
index 0000000000..2936735536
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoqemuruntimeparser.h
@@ -0,0 +1,58 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+**
+**************************************************************************/
+#ifndef MAEMOQEMURUNTIMEPARSER_H
+#define MAEMOQEMURUNTIMEPARSER_H
+
+#include "maemoqemuruntime.h"
+
+#include <QtCore/QString>
+#include <QtXml/QXmlStreamReader>
+
+namespace Qt4ProjectManager {
+class QtVersion;
+namespace Internal {
+
+class MaemoQemuRuntimeParser
+{
+public:
+ static MaemoQemuRuntime parseRuntime(const QtVersion *qtVersion);
+
+protected:
+ MaemoQemuRuntimeParser(const QString &madInfoOutput,
+ const QString &targetName, const QString &maddeRoot);
+
+ const QString m_targetName;
+ const QString m_maddeRoot;
+ QXmlStreamReader m_madInfoReader;
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // MAEMOQEMURUNTIMEPARSER_H
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoqemusettings.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemoqemusettings.cpp
new file mode 100644
index 0000000000..d953cd8475
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoqemusettings.cpp
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of Qt Creator.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file 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 "maemoqemusettings.h"
+
+#include <coreplugin/icore.h>
+
+#include <QtCore/QSettings>
+
+namespace Qt4ProjectManager {
+namespace Internal {
+namespace {
+const QString SettingsGroup = QLatin1String("Maemo Qemu Settings");
+const QString OpenGlModeKey = QLatin1String("OpenGl Mode");
+} // anonymous namespace
+
+MaemoQemuSettings::OpenGlMode MaemoQemuSettings::openGlMode()
+{
+ if (!m_initialized) {
+ QSettings *settings = Core::ICore::instance()->settings();
+ settings->beginGroup(SettingsGroup);
+ m_openGlMode = static_cast<OpenGlMode>(settings->value(OpenGlModeKey, AutoDetect).toInt());
+ settings->endGroup();
+ m_initialized = true;
+ }
+ return m_openGlMode;
+}
+
+void MaemoQemuSettings::setOpenGlMode(OpenGlMode openGlMode)
+{
+ Q_ASSERT(m_initialized);
+ m_openGlMode = openGlMode;
+ QSettings *settings = Core::ICore::instance()->settings();
+ settings->beginGroup(SettingsGroup);
+ settings->setValue(OpenGlModeKey, m_openGlMode);
+ settings->endGroup();
+}
+
+bool MaemoQemuSettings::m_initialized = false;
+MaemoQemuSettings::OpenGlMode MaemoQemuSettings::m_openGlMode;
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoqemusettings.h b/src/plugins/qt4projectmanager/qt-maemo/maemoqemusettings.h
new file mode 100644
index 0000000000..2bb24e5ce7
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoqemusettings.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of Qt Creator.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file 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 MAEMOQEMUSETTINGS_H
+#define MAEMOQEMUSETTINGS_H
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+class MaemoQemuSettings
+{
+public:
+ enum OpenGlMode { HardwareAcceleration, SoftwareRendering, AutoDetect };
+
+ static OpenGlMode openGlMode();
+ static void setOpenGlMode(OpenGlMode openGlMode);
+
+private:
+ MaemoQemuSettings();
+
+ static bool m_initialized;
+ static OpenGlMode m_openGlMode;
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // MAEMOQEMUSETTINGS_H
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoqemusettingswidget.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemoqemusettingswidget.cpp
new file mode 100644
index 0000000000..569781e919
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoqemusettingswidget.cpp
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file 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 "maemoqemusettingswidget.h"
+#include "ui_maemoqemusettingswidget.h"
+
+#include "maemoqemusettings.h"
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+MaemoQemuSettingsWidget::MaemoQemuSettingsWidget(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::MaemoQemuSettingsWidget)
+{
+ ui->setupUi(this);
+ switch (MaemoQemuSettings::openGlMode()) {
+ case MaemoQemuSettings::HardwareAcceleration:
+ ui->hardwareAccelerationButton->setChecked(true);
+ break;
+ case MaemoQemuSettings::SoftwareRendering:
+ ui->softwareRenderingButton->setChecked(true);
+ break;
+ case MaemoQemuSettings::AutoDetect:
+ ui->autoDetectButton->setChecked(true);
+ break;
+ }
+}
+
+MaemoQemuSettingsWidget::~MaemoQemuSettingsWidget()
+{
+ delete ui;
+}
+
+QString MaemoQemuSettingsWidget::keywords() const
+{
+ const QChar space = QLatin1Char(' ');
+ QString keywords = ui->groupBox->title() + space
+ + ui->hardwareAccelerationButton->text() + space
+ + ui->softwareRenderingButton->text() + space
+ + ui->autoDetectButton->text();
+ keywords.remove(QLatin1Char('&'));
+ return keywords;
+}
+
+void MaemoQemuSettingsWidget::saveSettings()
+{
+ const MaemoQemuSettings::OpenGlMode openGlMode
+ = ui->hardwareAccelerationButton->isChecked()
+ ? MaemoQemuSettings::HardwareAcceleration
+ : ui->softwareRenderingButton->isChecked()
+ ? MaemoQemuSettings::SoftwareRendering
+ : MaemoQemuSettings::AutoDetect;
+ MaemoQemuSettings::setOpenGlMode(openGlMode);
+}
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoqemusettingswidget.h b/src/plugins/qt4projectmanager/qt-maemo/maemoqemusettingswidget.h
new file mode 100644
index 0000000000..1d337a55da
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoqemusettingswidget.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file 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 MAEMOQEMUSETTINGSWIDGET_H
+#define MAEMOQEMUSETTINGSWIDGET_H
+
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+namespace Ui {
+ class MaemoQemuSettingsWidget;
+}
+QT_END_NAMESPACE
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+class MaemoQemuSettingsWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit MaemoQemuSettingsWidget(QWidget *parent = 0);
+ ~MaemoQemuSettingsWidget();
+ void saveSettings();
+ QString keywords() const;
+
+private:
+ Ui::MaemoQemuSettingsWidget *ui;
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // MAEMOQEMUSETTINGSWIDGET_H
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoqemusettingswidget.ui b/src/plugins/qt4projectmanager/qt-maemo/maemoqemusettingswidget.ui
new file mode 100644
index 0000000000..3915e1feda
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoqemusettingswidget.ui
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MaemoQemuSettingsWidget</class>
+ <widget class="QWidget" name="MaemoQemuSettingsWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>OpenGL Mode</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QRadioButton" name="hardwareAccelerationButton">
+ <property name="text">
+ <string>&amp;Hardware Acceleration</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="softwareRenderingButton">
+ <property name="text">
+ <string>&amp;Software Rendering</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="autoDetectButton">
+ <property name="text">
+ <string>&amp;Auto-detect</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoremotemounter.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemoremotemounter.cpp
index 774faa9e8d..e2bb2b03e4 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemoremotemounter.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoremotemounter.cpp
@@ -35,6 +35,7 @@
#include "maemoglobal.h"
#include "maemotoolchain.h"
+#include "maemousedportsgatherer.h"
#include <coreplugin/ssh/sftpchannel.h>
#include <coreplugin/ssh/sshconnection.h>
@@ -43,7 +44,7 @@
#include <QtCore/QTimer>
-#define ASSERT_STATE(state) assertState(state, Q_FUNC_INFO)
+#define ASSERT_STATE(state) ASSERT_STATE_GENERIC(State, state, m_state)
using namespace Core;
@@ -51,7 +52,7 @@ namespace Qt4ProjectManager {
namespace Internal {
MaemoRemoteMounter::MaemoRemoteMounter(QObject *parent)
- : QObject(parent), m_toolChain(0), m_utfsServerTimer(new QTimer(this)),
+ : QObject(parent), m_utfsServerTimer(new QTimer(this)),
m_uploadJobId(SftpInvalidJob), m_state(Inactive)
{
connect(m_utfsServerTimer, SIGNAL(timeout()), this,
@@ -63,26 +64,26 @@ MaemoRemoteMounter::~MaemoRemoteMounter()
killAllUtfsServers();
}
-void MaemoRemoteMounter::setConnection(const Core::SshConnection::Ptr &connection)
+void MaemoRemoteMounter::setConnection(const SshConnection::Ptr &connection)
{
ASSERT_STATE(Inactive);
-
m_connection = connection;
}
-bool MaemoRemoteMounter::addMountSpecification(const MaemoMountSpecification &mountSpec,
+void MaemoRemoteMounter::setToolchain(const MaemoToolChain *toolChain)
+{
+ ASSERT_STATE(Inactive);
+ m_remoteMountsAllowed = toolChain->allowsRemoteMounts();
+ m_maddeRoot = toolChain->maddeRoot();
+}
+
+void MaemoRemoteMounter::addMountSpecification(const MaemoMountSpecification &mountSpec,
bool mountAsRoot)
{
- Q_ASSERT(m_toolChain);
ASSERT_STATE(Inactive);
- if (m_toolChain->allowsRemoteMounts() && mountSpec.isValid()) {
- if (!m_portList.hasMore())
- return false;
- else
- m_mountSpecs << MountInfo(mountSpec, m_portList.getNext(), mountAsRoot);
- }
- return true;
+ if (m_remoteMountsAllowed && mountSpec.isValid())
+ m_mountSpecs << MountInfo(mountSpec, mountAsRoot);
}
bool MaemoRemoteMounter::hasValidMountSpecifications() const
@@ -90,7 +91,8 @@ bool MaemoRemoteMounter::hasValidMountSpecifications() const
return !m_mountSpecs.isEmpty();
}
-void MaemoRemoteMounter::mount()
+void MaemoRemoteMounter::mount(MaemoPortList *freePorts,
+ const MaemoUsedPortsGatherer *portsGatherer)
{
ASSERT_STATE(Inactive);
Q_ASSERT(m_utfsServers.isEmpty());
@@ -101,6 +103,8 @@ void MaemoRemoteMounter::mount()
emit reportProgress(tr("No directories to mount"));
emit mounted();
} else {
+ m_freePorts = freePorts;
+ m_portsGatherer = portsGatherer;
deployUtfsClient();
}
}
@@ -117,7 +121,7 @@ void MaemoRemoteMounter::unmount()
QString remoteCall;
for (int i = 0; i < m_mountSpecs.count(); ++i) {
- remoteCall += QString::fromLocal8Bit("%1 umount %2;")
+ remoteCall += QString::fromLocal8Bit("%1 umount %2 && %1 rmdir %2;")
.arg(MaemoGlobal::remoteSudo(),
m_mountSpecs.at(i).mountSpec.remoteMountPoint);
}
@@ -209,7 +213,7 @@ void MaemoRemoteMounter::handleUploaderInitialized()
SIGNAL(finished(Core::SftpJobId, QString)), this,
SLOT(handleUploadFinished(Core::SftpJobId, QString)));
const QString localFile
- = m_toolChain->maddeRoot() + QLatin1String("/madlib/armel/utfs-client");
+ = m_maddeRoot + QLatin1String("/madlib/armel/utfs-client");
m_uploadJobId = m_utfsClientUploader->uploadFile(localFile,
utfsClientOnDevice(), SftpOverwriteExisting);
if (m_uploadJobId == SftpInvalidJob) {
@@ -251,7 +255,15 @@ void MaemoRemoteMounter::startUtfsClients()
const QLatin1String andOp(" && ");
QString remoteCall = chmodFuse + andOp + chmodUtfsClient;
for (int i = 0; i < m_mountSpecs.count(); ++i) {
- const MountInfo &mountInfo = m_mountSpecs.at(i);
+ MountInfo &mountInfo = m_mountSpecs[i];
+ mountInfo.remotePort
+ = m_portsGatherer->getNextFreePort(m_freePorts);
+ if (mountInfo.remotePort == -1) {
+ setState(Inactive);
+ emit error(tr("Error: Not enough free ports on device to fulfill all mount requests."));
+ return;
+ }
+
const MaemoMountSpecification &mountSpec = mountInfo.mountSpec;
const QString mkdir = QString::fromLocal8Bit("%1 mkdir -p %2")
.arg(MaemoGlobal::remoteSudo(), mountSpec.remoteMountPoint);
@@ -370,7 +382,6 @@ void MaemoRemoteMounter::handleUtfsServerError(QProcess::ProcessError)
.arg(QString::fromLocal8Bit(errorOutput));
}
killAllUtfsServers();
- killUtfsClients();
emit error(tr("Error running UTFS server: %1").arg(errorString));
setState(Inactive);
@@ -403,7 +414,7 @@ QString MaemoRemoteMounter::utfsClientOnDevice() const
QString MaemoRemoteMounter::utfsServer() const
{
- return m_toolChain->maddeRoot() + QLatin1String("/madlib/utfs-server");
+ return m_maddeRoot + QLatin1String("/madlib/utfs-server");
}
void MaemoRemoteMounter::killAllUtfsServers()
@@ -428,24 +439,11 @@ void MaemoRemoteMounter::handleUtfsServerTimeout()
return;
killAllUtfsServers();
- killUtfsClients();
emit error(tr("Timeout waiting for UTFS servers to connect."));
setState(Inactive);
}
-void MaemoRemoteMounter::assertState(State expectedState, const char *func)
-{
- assertState(QList<State>() << expectedState, func);
-}
-
-void MaemoRemoteMounter::assertState(const QList<State> &expectedStates,
- const char *func)
-{
- QTC_ASSERT(expectedStates.contains(m_state),
- qDebug("Unexpected state %d at %s.", m_state, func))
-}
-
void MaemoRemoteMounter::setState(State newState)
{
if (newState == Inactive) {
@@ -466,15 +464,5 @@ void MaemoRemoteMounter::setState(State newState)
m_state = newState;
}
-// TODO: Perhaps remove this one again, since it might interfere with
-// an unrelated application
-void MaemoRemoteMounter::killUtfsClients()
-{
- const SshRemoteProcess::Ptr utfsClientKiller
- = m_connection->createRemoteProcess("pkill utfs-client; sleep 1; "
- "pkill -9 utfs-client");
- utfsClientKiller->start();
-}
-
} // namespace Internal
} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoremotemounter.h b/src/plugins/qt4projectmanager/qt-maemo/maemoremotemounter.h
index 32f4ed04b7..b62dff9c87 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemoremotemounter.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoremotemounter.h
@@ -45,7 +45,7 @@
#include <QtCore/QSharedPointer>
#include <QtCore/QString>
-QT_FORWARD_DECLARE_CLASS(QTimer);
+QT_FORWARD_DECLARE_CLASS(QTimer)
namespace Core {
class SftpChannel;
@@ -56,6 +56,7 @@ class SshRemoteProcess;
namespace Qt4ProjectManager {
namespace Internal {
class MaemoToolChain;
+class MaemoUsedPortsGatherer;
class MaemoRemoteMounter : public QObject
{
@@ -63,24 +64,25 @@ class MaemoRemoteMounter : public QObject
public:
MaemoRemoteMounter(QObject *parent);
~MaemoRemoteMounter();
- void setToolchain(const MaemoToolChain *toolchain) { m_toolChain = toolchain; }
- void setPortList(const MaemoPortList &portList) { m_portList = portList; }
- bool addMountSpecification(const MaemoMountSpecification &mountSpec,
+
+ // Must already be connected.
+ void setConnection(const QSharedPointer<Core::SshConnection> &connection);
+
+ void setToolchain(const MaemoToolChain *toolChain);
+ void addMountSpecification(const MaemoMountSpecification &mountSpec,
bool mountAsRoot);
bool hasValidMountSpecifications() const;
void resetMountSpecifications() { m_mountSpecs.clear(); }
- void mount();
+ void mount(MaemoPortList *freePorts,
+ const MaemoUsedPortsGatherer *portsGatherer);
void unmount();
void stop();
- // Must be connected already.
- void setConnection(const QSharedPointer<Core::SshConnection> &connection);
-
signals:
void mounted();
void unmounted();
void error(const QString &reason);
- void reportProgress(const QString &progressOutput); // TODO: No progress output when there's nothingt to mount
+ void reportProgress(const QString &progressOutput);
void debugOutput(const QString &output);
private slots:
@@ -105,27 +107,23 @@ private:
UtfsClientsStarting, UtfsClientsStarted, UtfsServersStarted
};
- void assertState(State expectedState, const char *func);
- void assertState(const QList<State> &expectedStates, const char *func);
void setState(State newState);
void deployUtfsClient();
void startUtfsClients();
void killUtfsServer(QProcess *proc);
void killAllUtfsServers();
- void killUtfsClients();
QString utfsClientOnDevice() const;
QString utfsServer() const;
- const MaemoToolChain *m_toolChain;
QTimer * const m_utfsServerTimer;
struct MountInfo {
- MountInfo(const MaemoMountSpecification &m, int port, bool root)
- : mountSpec(m), remotePort(port), mountAsRoot(root) {}
+ MountInfo(const MaemoMountSpecification &m, bool root)
+ : mountSpec(m), mountAsRoot(root), remotePort(-1) {}
MaemoMountSpecification mountSpec;
- int remotePort;
bool mountAsRoot;
+ int remotePort;
};
QSharedPointer<Core::SshConnection> m_connection;
@@ -140,7 +138,10 @@ private:
QByteArray m_utfsClientStderr;
QByteArray m_umountStderr;
- MaemoPortList m_portList;
+ MaemoPortList *m_freePorts;
+ const MaemoUsedPortsGatherer *m_portsGatherer;
+ bool m_remoteMountsAllowed;
+ QString m_maddeRoot;
State m_state;
};
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoremotemountsmodel.h b/src/plugins/qt4projectmanager/qt-maemo/maemoremotemountsmodel.h
index 60f9bf3e4b..fdb2955438 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemoremotemountsmodel.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoremotemountsmodel.h
@@ -47,12 +47,13 @@ namespace Internal {
class MaemoRemoteMountsModel : public QAbstractTableModel
{
Q_OBJECT
-public:
+public:
explicit MaemoRemoteMountsModel(QObject *parent = 0);
int mountSpecificationCount() const { return m_mountSpecs.count(); }
int validMountSpecificationCount() const;
MaemoMountSpecification mountSpecificationAt(int pos) const { return m_mountSpecs.at(pos); }
bool hasValidMountSpecifications() const;
+ const QList<MaemoMountSpecification> &mountSpecs() const { return m_mountSpecs; }
void addMountSpecification(const QString &localDir);
void removeMountSpecificationAt(int pos);
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoremoteprocessesdialog.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemoremoteprocessesdialog.cpp
new file mode 100644
index 0000000000..a4bd624e82
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoremoteprocessesdialog.cpp
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of Qt Creator.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file 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 "maemoremoteprocessesdialog.h"
+#include "ui_maemoremoteprocessesdialog.h"
+
+#include "maemoremoteprocesslist.h"
+
+#include <QtGui/QMessageBox>
+#include <QtGui/QSortFilterProxyModel>
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+MaemoRemoteProcessesDialog::MaemoRemoteProcessesDialog(const Core::SshConnectionParameters &params,
+ QWidget *parent) :
+ QDialog(parent),
+ m_ui(new Ui::MaemoRemoteProcessesDialog),
+ m_processList(new MaemoRemoteProcessList(params, this)),
+ m_proxyModel(new QSortFilterProxyModel(this))
+{
+ m_ui->setupUi(this);
+ m_ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
+ m_proxyModel->setSourceModel(m_processList);
+ m_proxyModel->setDynamicSortFilter(true);
+ m_proxyModel->setFilterKeyColumn(1);
+ m_ui->tableView->setModel(m_proxyModel);
+ connect(m_ui->processFilterLineEdit, SIGNAL(textChanged(QString)),
+ m_proxyModel, SLOT(setFilterRegExp(QString)));
+ m_ui->processFilterLineEdit->setText(QLatin1String("[^ ]+"));
+ connect(m_ui->tableView->selectionModel(),
+ SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
+ SLOT(handleSelectionChanged()));
+ connect(m_ui->updateListButton, SIGNAL(clicked()),
+ SLOT(updateProcessList()));
+ connect(m_ui->killProcessButton, SIGNAL(clicked()), SLOT(killProcess()));
+ connect(m_processList, SIGNAL(error(QString)),
+ SLOT(handleRemoteError(QString)));
+ connect(m_processList, SIGNAL(modelReset()),
+ SLOT(handleProcessListUpdated()));
+ connect(m_processList, SIGNAL(processKilled()),
+ SLOT(handleProcessKilled()), Qt::QueuedConnection);
+ connect(m_proxyModel, SIGNAL(layoutChanged()),
+ SLOT(handleProcessListUpdated()));
+ handleSelectionChanged();
+ updateProcessList();
+}
+
+MaemoRemoteProcessesDialog::~MaemoRemoteProcessesDialog()
+{
+ delete m_ui;
+}
+
+void MaemoRemoteProcessesDialog::handleRemoteError(const QString &errorMsg)
+{
+ QMessageBox::critical(this, tr("Remote error"), errorMsg);
+ m_ui->updateListButton->setEnabled(true);
+ handleSelectionChanged();
+}
+
+void MaemoRemoteProcessesDialog::handleProcessListUpdated()
+{
+ m_ui->updateListButton->setEnabled(true);
+ m_ui->tableView->resizeRowsToContents();
+ handleSelectionChanged();
+}
+
+void MaemoRemoteProcessesDialog::updateProcessList()
+{
+ m_ui->updateListButton->setEnabled(false);
+ m_ui->killProcessButton->setEnabled(false);
+ m_processList->update();
+}
+
+void MaemoRemoteProcessesDialog::killProcess()
+{
+ const QModelIndexList &indexes
+ = m_ui->tableView->selectionModel()->selectedIndexes();
+ if (indexes.empty())
+ return;
+ m_ui->updateListButton->setEnabled(false);
+ m_ui->killProcessButton->setEnabled(false);
+ m_processList->killProcess(m_proxyModel->mapToSource(indexes.first()).row());
+}
+
+void MaemoRemoteProcessesDialog::handleProcessKilled()
+{
+ updateProcessList();
+}
+
+void MaemoRemoteProcessesDialog::handleSelectionChanged()
+{
+ m_ui->killProcessButton->setEnabled(m_ui->tableView->selectionModel()->hasSelection());
+}
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoremoteprocessesdialog.h b/src/plugins/qt4projectmanager/qt-maemo/maemoremoteprocessesdialog.h
new file mode 100644
index 0000000000..ac30b31fcd
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoremoteprocessesdialog.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of Qt Creator.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file 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 MAEMOREMOTEPROCESSDIALOG_H
+#define MAEMOREMOTEPROCESSDIALOG_H
+
+#include <QtGui/QDialog>
+#include <coreplugin/ssh/sshconnection.h>
+
+QT_BEGIN_NAMESPACE
+namespace Ui {
+ class MaemoRemoteProcessesDialog;
+}
+class QSortFilterProxyModel;
+QT_END_NAMESPACE
+
+namespace Qt4ProjectManager {
+namespace Internal {
+class MaemoRemoteProcessList;
+
+class MaemoRemoteProcessesDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit MaemoRemoteProcessesDialog(const Core::SshConnectionParameters &params,
+ QWidget *parent = 0);
+ ~MaemoRemoteProcessesDialog();
+
+private slots:
+ void updateProcessList();
+ void killProcess();
+ void handleRemoteError(const QString &errorMsg);
+ void handleProcessListUpdated();
+ void handleProcessKilled();
+ void handleSelectionChanged();
+
+private:
+ Ui::MaemoRemoteProcessesDialog *m_ui;
+ MaemoRemoteProcessList *const m_processList;
+ QSortFilterProxyModel *const m_proxyModel;
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // MAEMOREMOTEPROCESSDIALOG_H
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoremoteprocessesdialog.ui b/src/plugins/qt4projectmanager/qt-maemo/maemoremoteprocessesdialog.ui
new file mode 100644
index 0000000000..90fad49638
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoremoteprocessesdialog.ui
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MaemoRemoteProcessesDialog</class>
+ <widget class="QDialog" name="MaemoRemoteProcessesDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>766</width>
+ <height>684</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>List of Remote Processes</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QLabel" name="filterLabel">
+ <property name="text">
+ <string>&amp;Filter by process name:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="processFilterLineEdit"/>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QTableView" name="tableView">
+ <property name="showGrid">
+ <bool>false</bool>
+ </property>
+ <property name="sortingEnabled">
+ <bool>true</bool>
+ </property>
+ <attribute name="horizontalHeaderDefaultSectionSize">
+ <number>100</number>
+ </attribute>
+ <attribute name="horizontalHeaderStretchLastSection">
+ <bool>true</bool>
+ </attribute>
+ <attribute name="verticalHeaderVisible">
+ <bool>false</bool>
+ </attribute>
+ </widget>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QPushButton" name="updateListButton">
+ <property name="text">
+ <string>&amp;Update List</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="killProcessButton">
+ <property name="text">
+ <string>&amp;Kill Selected Process</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Close</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>MaemoRemoteProcessesDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>257</x>
+ <y>290</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>MaemoRemoteProcessesDialog</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>
+ </connections>
+</ui>
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoremoteprocesslist.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemoremoteprocesslist.cpp
new file mode 100644
index 0000000000..212b6ae5f6
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoremoteprocesslist.cpp
@@ -0,0 +1,248 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of Qt Creator.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file 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 "maemoremoteprocesslist.h"
+
+#include <coreplugin/ssh/sshremoteprocessrunner.h>
+
+#include <QtCore/QStringList>
+
+using namespace Core;
+
+namespace Qt4ProjectManager {
+namespace Internal {
+namespace {
+const QByteArray LineSeparator1("---");
+const QByteArray LineSeparator2("QTCENDOFLINE---");
+const QByteArray LineSeparator = LineSeparator1 + LineSeparator2;
+} // anonymous namespace
+
+MaemoRemoteProcessList::MaemoRemoteProcessList(const Core::SshConnectionParameters &params,
+ QObject *parent)
+ : QAbstractTableModel(parent),
+ m_process(SshRemoteProcessRunner::create(params)),
+ m_state(Inactive)
+{
+}
+
+MaemoRemoteProcessList::~MaemoRemoteProcessList() {}
+
+void MaemoRemoteProcessList::update()
+{
+ if (m_state != Inactive) {
+ qDebug("%s: Did not expect state to be %d.", Q_FUNC_INFO, m_state);
+ stop();
+ }
+ beginResetModel();
+ m_remoteProcs.clear();
+ const QByteArray command = QByteArray()
+ + "sep1=" + LineSeparator1 + '\n'
+ + "sep2=" + LineSeparator2 + '\n'
+ + "pidlist=`ls /proc |grep -E '^[[:digit:]]+$' |sort -n`; "
+ + "for pid in $pidlist\n"
+ + "do\n"
+ + " echo -n \"$pid \"\n"
+ + " tr '\\0' ' ' < /proc/$pid/cmdline\n"
+ + " echo -n \"$sep1$sep2\"\n"
+ + "done\n"
+ + "echo ''";
+ startProcess(command, Listing);
+}
+
+void MaemoRemoteProcessList::killProcess(int row)
+{
+ Q_ASSERT(row >= 0 && row < m_remoteProcs.count());
+ const QByteArray command
+ = "kill -9 " + QByteArray::number(m_remoteProcs.at(row).pid);
+ startProcess(command, Killing);
+}
+
+void MaemoRemoteProcessList::startProcess(const QByteArray &cmdLine,
+ State newState)
+{
+ if (m_state != Inactive) {
+ qDebug("%s: Did not expect state to be %d.", Q_FUNC_INFO, m_state);
+ stop();
+ }
+ m_state = newState;
+ connect(m_process.data(), SIGNAL(connectionError(Core::SshError)),
+ SLOT(handleConnectionError()));
+ connect(m_process.data(), SIGNAL(processOutputAvailable(QByteArray)),
+ SLOT(handleRemoteStdOut(QByteArray)));
+ connect(m_process.data(),
+ SIGNAL(processErrorOutputAvailable(QByteArray)),
+ SLOT(handleRemoteStdErr(QByteArray)));
+ connect(m_process.data(), SIGNAL(processClosed(int)),
+ SLOT(handleRemoteProcessFinished(int)));
+ m_remoteStdout.clear();
+ m_remoteStderr.clear();
+ m_errorMsg.clear();
+ m_process->run(cmdLine);
+}
+
+void MaemoRemoteProcessList::handleConnectionError()
+{
+ if (m_state == Inactive)
+ return;
+
+ emit error(tr("Connection failure: %1")
+ .arg(m_process->connection()->errorString()));
+ stop();
+}
+
+void MaemoRemoteProcessList::handleRemoteStdOut(const QByteArray &output)
+{
+ if (m_state == Listing)
+ m_remoteStdout += output;
+}
+
+void MaemoRemoteProcessList::handleRemoteStdErr(const QByteArray &output)
+{
+ if (m_state != Inactive)
+ m_remoteStderr += output;
+}
+
+void MaemoRemoteProcessList::handleRemoteProcessFinished(int exitStatus)
+{
+ if (m_state == Inactive)
+ return;
+
+ switch (exitStatus) {
+ case SshRemoteProcess::FailedToStart:
+ m_errorMsg = tr("Error: Remote process failed to start: %1")
+ .arg(m_process->process()->errorString());
+ break;
+ case SshRemoteProcess::KilledBySignal:
+ m_errorMsg = tr("Error: Remote process crashed: %1")
+ .arg(m_process->process()->errorString());
+ break;
+ case SshRemoteProcess::ExitedNormally:
+ if (m_process->process()->exitCode() == 0) {
+ if (m_state == Listing)
+ buildProcessList();
+ } else {
+ m_errorMsg = tr("Remote process failed.");
+ }
+ break;
+ default:
+ Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid exit status");
+ }
+
+ if (!m_errorMsg.isEmpty()) {
+ if (!m_remoteStderr.isEmpty()) {
+ m_errorMsg += tr("\nRemote stderr was: %1")
+ .arg(QString::fromUtf8(m_remoteStderr));
+ }
+ emit error(m_errorMsg);
+ }
+ stop();
+}
+
+void MaemoRemoteProcessList::stop()
+{
+ if (m_state == Inactive)
+ return;
+
+ disconnect(m_process.data(), 0, this, 0);
+ if (m_state == Listing)
+ endResetModel();
+ else if (m_errorMsg.isEmpty())
+ emit processKilled();
+ m_state = Inactive;
+}
+
+void MaemoRemoteProcessList::buildProcessList()
+{
+ const QString remoteOutput = QString::fromUtf8(m_remoteStdout);
+ const QStringList &lines
+ = remoteOutput.split(QString::fromUtf8(LineSeparator));
+ foreach (const QString &line, lines) {
+ const int pidEndPos = line.indexOf(' ');
+ if (pidEndPos == -1)
+ continue;
+ bool isNumber;
+ const int pid = line.left(pidEndPos).toInt(&isNumber);
+ if (!isNumber) {
+ qDebug("%s: Non-integer value where pid was expected. Line was: '%s'",
+ Q_FUNC_INFO, qPrintable(line));
+ continue;
+ }
+ m_remoteProcs << RemoteProc(pid, line.mid(pidEndPos));
+ }
+}
+
+int MaemoRemoteProcessList::rowCount(const QModelIndex &parent) const
+{
+ return parent.isValid() ? 0 : m_remoteProcs.count();
+}
+
+int MaemoRemoteProcessList::columnCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent);
+ return 2;
+}
+
+QVariant MaemoRemoteProcessList::headerData(int section,
+ Qt::Orientation orientation, int role) const
+{
+ if (orientation != Qt::Horizontal || role != Qt::DisplayRole
+ || section < 0 || section >= columnCount())
+ return QVariant();
+ if (section == 0)
+ return tr("PID");
+ else
+ return tr("Command Line");
+}
+
+QVariant MaemoRemoteProcessList::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid() || index.row() >= rowCount(index.parent())
+ || index.column() >= columnCount() || role != Qt::DisplayRole)
+ return QVariant();
+ const RemoteProc &proc = m_remoteProcs.at(index.row());
+ if (index.column() == 0)
+ return proc.pid;
+ else
+ return proc.cmdLine;
+}
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoremoteprocesslist.h b/src/plugins/qt4projectmanager/qt-maemo/maemoremoteprocesslist.h
new file mode 100644
index 0000000000..61e811d285
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoremoteprocesslist.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of Qt Creator.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file 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 MAEMOREMOTEPROCESSLIST_H
+#define MAEMOREMOTEPROCESSLIST_H
+
+#include <QtCore/QAbstractTableModel>
+#include <QtCore/QByteArray>
+#include <QtCore/QList>
+#include <QtCore/QSharedPointer>
+#include <QtCore/QString>
+#include <coreplugin/ssh/sshconnection.h>
+#include <coreplugin/ssh/sshremoteprocessrunner.h>
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+class MaemoRemoteProcessList : public QAbstractTableModel
+{
+ Q_OBJECT
+public:
+ explicit MaemoRemoteProcessList(const Core::SshConnectionParameters &params,
+ QObject *parent = 0);
+ ~MaemoRemoteProcessList();
+ void update();
+ void killProcess(int row);
+
+signals:
+ void error(const QString &errorMsg);
+ void processKilled();
+
+private slots:
+ void handleRemoteStdOut(const QByteArray &output);
+ void handleRemoteStdErr(const QByteArray &output);
+ void handleConnectionError();
+ void handleRemoteProcessFinished(int exitStatus);
+
+private:
+ enum State { Inactive, Listing, Killing };
+
+ virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ virtual int columnCount(const QModelIndex &parent = QModelIndex()) const;
+ virtual QVariant data(const QModelIndex &index,
+ int role = Qt::DisplayRole) const;
+ virtual QVariant headerData(int section, Qt::Orientation orientation,
+ int role = Qt::DisplayRole) const;
+
+ void buildProcessList();
+ void stop();
+ void startProcess(const QByteArray &cmdLine, State newState);
+
+ const QSharedPointer<Core::SshRemoteProcessRunner> m_process;
+ QByteArray m_remoteStdout;
+ QByteArray m_remoteStderr;
+ QString m_errorMsg;
+ State m_state;
+
+ struct RemoteProc {
+ RemoteProc(int pid, const QString &cmdLine)
+ : pid(pid), cmdLine(cmdLine) {}
+ int pid;
+ QString cmdLine;
+ };
+ QList<RemoteProc> m_remoteProcs;
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // MAEMOREMOTEPROCESSLIST_H
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.cpp
index 477eb3e42d..e8b8043b12 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.cpp
@@ -53,6 +53,7 @@
#include <qt4projectmanager/qt4project.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <QtCore/QStringBuilder>
@@ -60,7 +61,7 @@ namespace Qt4ProjectManager {
namespace Internal {
namespace {
-const bool DefaultUseRemoteGdbValue = false; // TODO: Make true once it works reliably on Windows
+const bool DefaultUseRemoteGdbValue = false;
} // anonymous namespace
using namespace ProjectExplorer;
@@ -71,6 +72,7 @@ MaemoRunConfiguration::MaemoRunConfiguration(Qt4Target *parent,
, m_proFilePath(proFilePath)
, m_useRemoteGdb(DefaultUseRemoteGdbValue)
, m_baseEnvironmentBase(SystemEnvironmentBase)
+ , m_validParse(parent->qt4Project()->validParse(m_proFilePath))
{
init();
}
@@ -85,6 +87,7 @@ MaemoRunConfiguration::MaemoRunConfiguration(Qt4Target *parent,
, m_baseEnvironmentBase(source->m_baseEnvironmentBase)
, m_systemEnvironment(source->m_systemEnvironment)
, m_userEnvironmentChanges(source->m_userEnvironmentChanges)
+ , m_validParse(source->m_validParse)
{
init();
}
@@ -101,9 +104,11 @@ void MaemoRunConfiguration::init()
this, SLOT(handleDeployConfigChanged()));
handleDeployConfigChanged();
- connect(qt4Target()->qt4Project(),
- SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode*)),
- this, SLOT(proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode*)));
+ Qt4Project *pro = qt4Target()->qt4Project();
+ connect(pro, SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode*,bool)),
+ this, SLOT(proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode*,bool)));
+ connect(pro, SIGNAL(proFileInvalidated(Qt4ProjectManager::Internal::Qt4ProFileNode *)),
+ this, SLOT(proFileInvalidated(Qt4ProjectManager::Internal::Qt4ProFileNode*)));
}
MaemoRunConfiguration::~MaemoRunConfiguration()
@@ -120,12 +125,11 @@ Qt4BuildConfiguration *MaemoRunConfiguration::activeQt4BuildConfiguration() cons
return static_cast<Qt4BuildConfiguration *>(activeBuildConfiguration());
}
-bool MaemoRunConfiguration::isEnabled(ProjectExplorer::BuildConfiguration *config) const
+bool MaemoRunConfiguration::isEnabled(ProjectExplorer::BuildConfiguration * /* config */) const
{
- Qt4BuildConfiguration *qt4bc = qobject_cast<Qt4BuildConfiguration*>(config);
- QTC_ASSERT(qt4bc, return false);
- ToolChain::ToolChainType type = qt4bc->toolChainType();
- return type == ToolChain::GCC_MAEMO;
+ if (!m_validParse)
+ return false;
+ return true;
}
QWidget *MaemoRunConfiguration::createConfigurationWidget()
@@ -138,10 +142,28 @@ ProjectExplorer::OutputFormatter *MaemoRunConfiguration::createOutputFormatter()
return new QtOutputFormatter(qt4Target()->qt4Project());
}
-void MaemoRunConfiguration::proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode *pro)
+void MaemoRunConfiguration::handleParseState(bool success)
+{
+ bool enabled = isEnabled();
+ m_validParse = success;
+ if (enabled != isEnabled()) {
+ emit isEnabledChanged(!enabled);
+ }
+}
+
+void MaemoRunConfiguration::proFileInvalidated(Qt4ProjectManager::Internal::Qt4ProFileNode *pro)
+{
+ if (m_proFilePath != pro->path())
+ return;
+ handleParseState(false);
+}
+
+void MaemoRunConfiguration::proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode *pro, bool success)
{
- if (m_proFilePath == pro->path())
+ if (m_proFilePath == pro->path()) {
+ handleParseState(success);
emit targetInformationChanged();
+ }
}
QVariantMap MaemoRunConfiguration::toMap() const
@@ -163,7 +185,7 @@ bool MaemoRunConfiguration::fromMap(const QVariantMap &map)
if (!RunConfiguration::fromMap(map))
return false;
- m_arguments = map.value(ArgumentsKey).toStringList();
+ m_arguments = map.value(ArgumentsKey).toString();
const QDir dir = QDir(target()->project()->projectDirectory());
m_proFilePath = dir.filePath(map.value(ProFileKey).toString());
m_useRemoteGdb = map.value(UseRemoteGdbKey, DefaultUseRemoteGdbValue).toBool();
@@ -174,6 +196,8 @@ bool MaemoRunConfiguration::fromMap(const QVariantMap &map)
SystemEnvironmentBase).toInt());
m_remoteMounts->fromMap(map);
+ m_validParse = qt4Target()->qt4Project()->validParse(m_proFilePath);
+
setDefaultDisplayName(defaultDisplayName());
return true;
@@ -238,7 +262,7 @@ const QString MaemoRunConfiguration::targetRoot() const
return QString();
}
-const QStringList MaemoRunConfiguration::arguments() const
+const QString MaemoRunConfiguration::arguments() const
{
return m_arguments;
}
@@ -269,6 +293,13 @@ QString MaemoRunConfiguration::localDirToMountForRemoteGdb() const
? projectDir : projectDir.left(lastSeparatorPos);
}
+QString MaemoRunConfiguration::remoteProjectSourcesMountPoint() const
+{
+ return MaemoGlobal::homeDirOnDevice(deviceConfig().server.uname)
+ + QLatin1String("/gdbSourcesDir_")
+ + QFileInfo(localExecutableFilePath()).fileName();
+}
+
QString MaemoRunConfiguration::localExecutableFilePath() const
{
TargetInformation ti = qt4Target()->qt4Project()->rootProjectNode()
@@ -290,7 +321,7 @@ MaemoPortList MaemoRunConfiguration::freePorts() const
const MaemoDeviceConfig &devConfig = deviceConfig();
const Qt4BuildConfiguration * const qt4bc = activeQt4BuildConfiguration();
if (devConfig.type == MaemoDeviceConfig::Simulator && qt4bc) {
- Runtime rt;
+ MaemoQemuRuntime rt;
const int id = qt4bc->qtVersion()->uniqueId();
if (MaemoQemuManager::instance().runtimeForQtVersion(id, &rt))
return rt.m_freePorts;
@@ -303,7 +334,7 @@ bool MaemoRunConfiguration::useRemoteGdb() const
return m_useRemoteGdb && toolchain()->allowsRemoteMounts();
}
-void MaemoRunConfiguration::setArguments(const QStringList &args)
+void MaemoRunConfiguration::setArguments(const QString &args)
{
m_arguments = args;
}
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.h b/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.h
index 3bbf32a5b3..491f6c180a 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.h
@@ -49,13 +49,13 @@ QT_FORWARD_DECLARE_CLASS(QWidget)
namespace Qt4ProjectManager {
+class Qt4BuildConfiguration;
class Qt4Project;
+class Qt4Target;
namespace Internal {
-class Qt4BuildConfiguration;
class Qt4ProFileNode;
-class Qt4Target;
class MaemoDeviceConfigListModel;
class MaemoDeployStep;
@@ -80,6 +80,7 @@ public:
MaemoRunConfiguration(Qt4Target *parent, const QString &proFilePath);
virtual ~MaemoRunConfiguration();
+ using ProjectExplorer::RunConfiguration::isEnabled;
bool isEnabled(ProjectExplorer::BuildConfiguration *config) const;
QWidget *createConfigurationWidget();
ProjectExplorer::OutputFormatter *createOutputFormatter() const;
@@ -95,8 +96,8 @@ public:
QString remoteExecutableFilePath() const;
const QString sysRoot() const;
const QString targetRoot() const;
- const QStringList arguments() const;
- void setArguments(const QStringList &args);
+ const QString arguments() const;
+ void setArguments(const QString &args);
MaemoDeviceConfig deviceConfig() const;
MaemoPortList freePorts() const;
bool useRemoteGdb() const;
@@ -107,6 +108,7 @@ public:
const QString gdbCmd() const;
const QString dumperLib() const;
QString localDirToMountForRemoteGdb() const;
+ QString remoteProjectSourcesMountPoint() const;
virtual QVariantMap toMap() const;
@@ -139,23 +141,25 @@ protected:
QString defaultDisplayName();
private slots:
- void proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode *pro);
+ void proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode *pro, bool success);
+ void proFileInvalidated(Qt4ProjectManager::Internal::Qt4ProFileNode *pro);
void updateDeviceConfigurations();
void handleDeployConfigChanged();
private:
void init();
+ void handleParseState(bool success);
-private:
QString m_proFilePath;
mutable QString m_gdbPath;
MaemoRemoteMountsModel *m_remoteMounts;
- QStringList m_arguments;
+ QString m_arguments;
bool m_useRemoteGdb;
BaseEnvironmentBase m_baseEnvironmentBase;
Utils::Environment m_systemEnvironment;
QList<Utils::EnvironmentItem> m_userEnvironmentChanges;
+ bool m_validParse;
};
} // namespace Internal
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemorunconfigurationwidget.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemorunconfigurationwidget.cpp
index f5bbb17e71..da20acae0b 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemorunconfigurationwidget.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemorunconfigurationwidget.cpp
@@ -41,7 +41,7 @@
#include "maemomanager.h"
#include "maemoremotemountsmodel.h"
#include "maemorunconfiguration.h"
-#include "maemosettingspage.h"
+#include "maemosettingspages.h"
#include "maemotoolchain.h"
#include <coreplugin/coreconstants.h>
@@ -96,7 +96,18 @@ MaemoRunConfigurationWidget::MaemoRunConfigurationWidget(
connect(m_runConfiguration->qt4Target(),
SIGNAL(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*)),
this, SLOT(handleBuildConfigChanged()));
+
+ connect(m_runConfiguration, SIGNAL(isEnabledChanged(bool)),
+ this, SLOT(runConfigurationEnabledChange(bool)));
+
handleBuildConfigChanged();
+
+ setEnabled(m_runConfiguration->isEnabled());
+}
+
+void MaemoRunConfigurationWidget::runConfigurationEnabledChange(bool enabled)
+{
+ setEnabled(enabled);
}
void MaemoRunConfigurationWidget::addGenericWidgets(QVBoxLayout *mainLayout)
@@ -126,7 +137,7 @@ void MaemoRunConfigurationWidget::addGenericWidgets(QVBoxLayout *mainLayout)
formLayout->addRow(tr("Executable on host:"), m_localExecutableLabel);
m_remoteExecutableLabel = new QLabel;
formLayout->addRow(tr("Executable on device:"), m_remoteExecutableLabel);
- m_argsLineEdit = new QLineEdit(m_runConfiguration->arguments().join(" "));
+ m_argsLineEdit = new QLineEdit(m_runConfiguration->arguments());
formLayout->addRow(tr("Arguments:"), m_argsLineEdit);
QHBoxLayout * const debugButtonsLayout = new QHBoxLayout;
@@ -148,9 +159,9 @@ void MaemoRunConfigurationWidget::addGenericWidgets(QVBoxLayout *mainLayout)
}
connect(addDevConfLabel, SIGNAL(linkActivated(QString)), this,
- SLOT(showSettingsDialog(QString)));
+ SLOT(showDeviceConfigurationsDialog(QString)));
connect(debuggerConfLabel, SIGNAL(linkActivated(QString)), this,
- SLOT(showSettingsDialog(QString)));
+ SLOT(showDeviceConfigurationsDialog(QString)));
connect(m_argsLineEdit, SIGNAL(textEdited(QString)), this,
SLOT(argumentsEdited(QString)));
connect(m_debugCppOnlyButton, SIGNAL(toggled(bool)), this,
@@ -161,7 +172,7 @@ void MaemoRunConfigurationWidget::addGenericWidgets(QVBoxLayout *mainLayout)
SLOT(handleDebuggingTypeChanged()));
connect(m_runConfiguration, SIGNAL(targetInformationChanged()), this,
SLOT(updateTargetInformation()));
- connect(m_runConfiguration->deployStep()->deployables(),
+ connect(m_runConfiguration->deployStep()->deployables().data(),
SIGNAL(modelReset()), this, SLOT(handleDeploySpecsChanged()));
handleDeploySpecsChanged();
}
@@ -282,7 +293,7 @@ void MaemoRunConfigurationWidget::addEnvironmentWidgets(QVBoxLayout *mainLayout)
void MaemoRunConfigurationWidget::argumentsEdited(const QString &text)
{
- m_runConfiguration->setArguments(text.split(' ', QString::SkipEmptyParts));
+ m_runConfiguration->setArguments(text);
}
void MaemoRunConfigurationWidget::updateTargetInformation()
@@ -325,10 +336,11 @@ void MaemoRunConfigurationWidget::handleToolchainChanged()
m_runConfiguration->updateFactoryState();
}
-void MaemoRunConfigurationWidget::showSettingsDialog(const QString &link)
+void MaemoRunConfigurationWidget::showDeviceConfigurationsDialog(const QString &link)
{
if (link == QLatin1String("deviceconfig")) {
- MaemoSettingsPage *page = MaemoManager::instance().settingsPage();
+ MaemoDeviceConfigurationsSettingsPage *page
+ = MaemoManager::instance().deviceConfigurationsSettingsPage();
Core::ICore::instance()->showOptionsDialog(page->category(), page->id());
} else if (link == QLatin1String("debugger")) {
Core::ICore::instance()->showOptionsDialog(QLatin1String("O.Debugger"),
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemorunconfigurationwidget.h b/src/plugins/qt4projectmanager/qt-maemo/maemorunconfigurationwidget.h
index e97c10712e..1066a82328 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemorunconfigurationwidget.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemorunconfigurationwidget.h
@@ -60,22 +60,23 @@ class EnvironmentWidget;
namespace Utils { class DetailsWidget; }
namespace Qt4ProjectManager {
-namespace Internal {
+class Qt4BuildConfiguration;
+namespace Internal {
class MaemoDeviceEnvReader;
class MaemoRunConfiguration;
-class Qt4BuildConfiguration;
class MaemoRunConfigurationWidget : public QWidget
{
Q_OBJECT
public:
explicit MaemoRunConfigurationWidget(MaemoRunConfiguration *runConfiguration,
- QWidget *parent = 0);
+ QWidget *parent = 0);
private slots:
+ void runConfigurationEnabledChange(bool enabled);
void argumentsEdited(const QString &args);
- void showSettingsDialog(const QString &link);
+ void showDeviceConfigurationsDialog(const QString &link);
void updateTargetInformation();
void handleCurrentDeviceConfigChanged();
void addMount();
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoruncontrol.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemoruncontrol.cpp
index 74c3fd1d90..388450e41c 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemoruncontrol.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoruncontrol.cpp
@@ -40,7 +40,6 @@
#include "maemosshrunner.h"
#include <projectexplorer/projectexplorerconstants.h>
-#include <projectexplorer/toolchain.h>
#include <utils/qtcassert.h>
#include <QtGui/QMessageBox>
@@ -51,13 +50,10 @@ namespace Qt4ProjectManager {
namespace Internal {
using ProjectExplorer::RunConfiguration;
-using ProjectExplorer::ToolChain;
MaemoRunControl::MaemoRunControl(RunConfiguration *rc)
: RunControl(rc, ProjectExplorer::Constants::RUNMODE)
- , m_runConfig(qobject_cast<MaemoRunConfiguration *>(rc))
- , m_devConfig(m_runConfig ? m_runConfig->deviceConfig() : MaemoDeviceConfig())
- , m_runner(new MaemoSshRunner(this, m_runConfig, false))
+ , m_runner(new MaemoSshRunner(this, qobject_cast<MaemoRunConfiguration *>(rc), false))
, m_running(false)
{
}
@@ -69,32 +65,24 @@ MaemoRunControl::~MaemoRunControl()
void MaemoRunControl::start()
{
- if (!m_devConfig.isValid()) {
- handleError(tr("No device configuration set for run configuration."));
- } else if (!m_runConfig) {
- handleError(tr("Run configuration no longer available."));
- } else {
- m_running = true;
- emit started();
- disconnect(m_runner, 0, this, 0);
- connect(m_runner, SIGNAL(error(QString)), this,
- SLOT(handleSshError(QString)));
- connect(m_runner, SIGNAL(readyForExecution()), this,
- SLOT(startExecution()));
- connect(m_runner, SIGNAL(remoteErrorOutput(QByteArray)), this,
- SLOT(handleRemoteErrorOutput(QByteArray)));
- connect(m_runner, SIGNAL(remoteOutput(QByteArray)), this,
- SLOT(handleRemoteOutput(QByteArray)));
- connect(m_runner, SIGNAL(remoteProcessStarted()), this,
- SLOT(handleRemoteProcessStarted()));
- connect(m_runner, SIGNAL(remoteProcessFinished(qint64)), this,
- SLOT(handleRemoteProcessFinished(qint64)));
- connect(m_runner, SIGNAL(reportProgress(QString)), this,
- SLOT(handleProgressReport(QString)));
- connect(m_runner, SIGNAL(mountDebugOutput(QString)), this,
- SLOT(handleMountDebugOutput(QString)));
- m_runner->start();
- }
+ m_running = true;
+ emit started();
+ disconnect(m_runner, 0, this, 0);
+ connect(m_runner, SIGNAL(error(QString)), SLOT(handleSshError(QString)));
+ connect(m_runner, SIGNAL(readyForExecution()), SLOT(startExecution()));
+ connect(m_runner, SIGNAL(remoteErrorOutput(QByteArray)),
+ SLOT(handleRemoteErrorOutput(QByteArray)));
+ connect(m_runner, SIGNAL(remoteOutput(QByteArray)),
+ SLOT(handleRemoteOutput(QByteArray)));
+ connect(m_runner, SIGNAL(remoteProcessStarted()),
+ SLOT(handleRemoteProcessStarted()));
+ connect(m_runner, SIGNAL(remoteProcessFinished(qint64)),
+ SLOT(handleRemoteProcessFinished(qint64)));
+ connect(m_runner, SIGNAL(reportProgress(QString)),
+ SLOT(handleProgressReport(QString)));
+ connect(m_runner, SIGNAL(mountDebugOutput(QString)),
+ SLOT(handleMountDebugOutput(QString)));
+ m_runner->start();
}
ProjectExplorer::RunControl::StopResult MaemoRunControl::stop()
@@ -112,12 +100,11 @@ void MaemoRunControl::handleSshError(const QString &error)
void MaemoRunControl::startExecution()
{
emit appendMessage(this, tr("Starting remote process ..."), false);
- const QString &remoteExe = m_runConfig->remoteExecutableFilePath();
m_runner->startExecution(QString::fromLocal8Bit("%1 %2 %3 %4")
- .arg(MaemoGlobal::remoteCommandPrefix(remoteExe))
- .arg(MaemoGlobal::remoteEnvironment(m_runConfig->userEnvironmentChanges()))
- .arg(remoteExe)
- .arg(m_runConfig->arguments().join(QLatin1String(" "))).toUtf8());
+ .arg(MaemoGlobal::remoteCommandPrefix(m_runner->remoteExecutable()))
+ .arg(MaemoGlobal::remoteEnvironment(m_runner->userEnvChanges()))
+ .arg(m_runner->remoteExecutable())
+ .arg(m_runner->arguments()).toUtf8());
}
void MaemoRunControl::handleRemoteProcessFinished(qint64 exitCode)
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoruncontrol.h b/src/plugins/qt4projectmanager/qt-maemo/maemoruncontrol.h
index 111fc99465..6eca721c82 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemoruncontrol.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoruncontrol.h
@@ -35,11 +35,8 @@
#ifndef MAEMORUNCONTROL_H
#define MAEMORUNCONTROL_H
-#include "maemodeviceconfigurations.h"
-
#include <projectexplorer/runconfiguration.h>
-#include <QtCore/QPointer>
#include <QtCore/QString>
namespace Qt4ProjectManager {
@@ -72,8 +69,6 @@ private:
void setFinished();
void handleError(const QString &errString);
- QPointer<MaemoRunConfiguration> m_runConfig;
- const MaemoDeviceConfig m_devConfig;
MaemoSshRunner * const m_runner;
bool m_running;
};
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemorunfactories.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemorunfactories.cpp
index d13f8639c0..e5f67c5eaf 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemorunfactories.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemorunfactories.cpp
@@ -42,6 +42,7 @@
#include "maemotoolchain.h"
#include <projectexplorer/projectexplorerconstants.h>
+#include <debugger/debuggerconstants.h>
#include <qt4projectmanager/qt4project.h>
#include <qt4projectmanager/qt4projectmanagerconstants.h>
@@ -168,15 +169,13 @@ bool MaemoRunControlFactory::canRun(RunConfiguration *runConfiguration,
return false;
const int freePortCount = maemoRunConfig->freePorts().count();
-#if 0 // TODO: Enable if deployment-via-mount is enabled again, otherwise throw away.
if (maemoRunConfig->toolchain()->allowsRemoteMounts() && freePortCount == 0)
return false;
-#endif
const int mountDirCount
= maemoRunConfig->toolchain()->allowsRemoteMounts()
? maemoRunConfig->remoteMounts()->validMountSpecificationCount()
: 0;
- if (mode == ProjectExplorer::Constants::DEBUGMODE)
+ if (mode == Debugger::Constants::DEBUGMODE)
return freePortCount >= mountDirCount + maemoRunConfig->portsUsedByDebuggers();
if (mode == ProjectExplorer::Constants::RUNMODE)
return freePortCount >= mountDirCount;
@@ -187,7 +186,7 @@ RunControl* MaemoRunControlFactory::create(RunConfiguration *runConfig,
const QString &mode)
{
Q_ASSERT(mode == ProjectExplorer::Constants::RUNMODE
- || mode == ProjectExplorer::Constants::DEBUGMODE);
+ || mode == Debugger::Constants::DEBUGMODE);
Q_ASSERT(canRun(runConfig, mode));
MaemoRunConfiguration *rc = qobject_cast<MaemoRunConfiguration *>(runConfig);
Q_ASSERT(rc);
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemosettingspage.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemosettingspage.cpp
deleted file mode 100644
index 7d3025a1ba..0000000000
--- a/src/plugins/qt4projectmanager/qt-maemo/maemosettingspage.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Qt Assistant of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file 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 "maemosettingspage.h"
-
-#include "maemosettingswidget.h"
-
-#include <projectexplorer/projectexplorerconstants.h>
-
-#include <QtCore/QCoreApplication>
-
-namespace Qt4ProjectManager {
-namespace Internal {
-
-MaemoSettingsPage::MaemoSettingsPage(QObject *parent)
- : Core::IOptionsPage(parent)
-{
-}
-
-MaemoSettingsPage::~MaemoSettingsPage()
-{
-}
-
-QString MaemoSettingsPage::id() const
-{
- return QLatin1String("ZZ.Maemo Device Configurations");
-}
-
-QString MaemoSettingsPage::displayName() const
-{
- return tr("Maemo Device Configurations");
-}
-
-QString MaemoSettingsPage::category() const
-{
- using namespace ProjectExplorer;
- return QLatin1String(Constants::PROJECTEXPLORER_SETTINGS_CATEGORY);
-}
-
-QString MaemoSettingsPage::displayCategory() const
-{
- return QCoreApplication::translate("ProjectExplorer",
- ProjectExplorer::Constants::PROJECTEXPLORER_SETTINGS_CATEGORY);
-}
-
-QIcon MaemoSettingsPage::categoryIcon() const
-{
- using namespace ProjectExplorer;
- return QIcon(QLatin1String(Constants::PROJECTEXPLORER_SETTINGS_CATEGORY_ICON));
-}
-
-bool MaemoSettingsPage::matches(const QString &searchKeyWord) const
-{
- return m_keywords.contains(searchKeyWord, Qt::CaseInsensitive);
-}
-
-QWidget *MaemoSettingsPage::createPage(QWidget *parent)
-{
- m_widget = new MaemoSettingsWidget(parent);
- if (m_keywords.isEmpty())
- m_keywords = m_widget->searchKeywords();
- return m_widget;
-}
-
-void MaemoSettingsPage::apply()
-{
- m_widget->saveSettings();
-}
-
-void MaemoSettingsPage::finish()
-{
-}
-
-} // namespace Internal
-} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemosettingspage.h b/src/plugins/qt4projectmanager/qt-maemo/maemosettingspage.h
deleted file mode 100644
index dcc90a50fc..0000000000
--- a/src/plugins/qt4projectmanager/qt-maemo/maemosettingspage.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Qt Assistant of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file 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 MAEMOSETTINGSPAGE_H
-#define MAEMOSETTINGSPAGE_H
-
-#include <coreplugin/dialogs/ioptionspage.h>
-
-namespace Qt4ProjectManager{
-namespace Internal {
-
-class MaemoSettingsWidget;
-
-class MaemoSettingsPage : public Core::IOptionsPage
-{
- Q_OBJECT
-public:
- MaemoSettingsPage(QObject *parent);
- ~MaemoSettingsPage();
-
- virtual QString id() const;
- virtual QString displayName() const;
- virtual QString category() const;
- virtual QString displayCategory() const;
- virtual QIcon categoryIcon() const;
- virtual bool matches(const QString &searchKeyWord) const;
- virtual QWidget *createPage(QWidget *parent);
- virtual void apply();
- virtual void finish();
-
-private:
- QString m_keywords;
- MaemoSettingsWidget *m_widget;
-};
-
-} // namespace Internal
-} // namespace Qt4ProjectManager
-
-#endif // MAEMOSETTINGSPAGE_H
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemosettingspages.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemosettingspages.cpp
new file mode 100644
index 0000000000..7670d57dba
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemosettingspages.cpp
@@ -0,0 +1,238 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file 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 "maemosettingspages.h"
+
+#include "maemoconstants.h"
+#include "maemodeviceconfigurationssettingswidget.h"
+#include "maemoqemusettings.h"
+#include "maemoqemusettingswidget.h"
+
+#include <coreplugin/icore.h>
+
+#include <QtCore/QCoreApplication>
+#include <QtGui/QDialog>
+#include <QtGui/QDialogButtonBox>
+#include <QtGui/QFrame>
+#include <QtGui/QLabel>
+#include <QtGui/QVBoxLayout>
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+MaemoDeviceConfigurationsSettingsPage::MaemoDeviceConfigurationsSettingsPage(QObject *parent)
+ : Core::IOptionsPage(parent)
+{
+}
+
+MaemoDeviceConfigurationsSettingsPage::~MaemoDeviceConfigurationsSettingsPage()
+{
+}
+
+QString MaemoDeviceConfigurationsSettingsPage::id() const
+{
+ return QLatin1String("ZZ.Maemo Device Configurations");
+}
+
+QString MaemoDeviceConfigurationsSettingsPage::displayName() const
+{
+ return tr("Maemo Device Configurations");
+}
+
+QString MaemoDeviceConfigurationsSettingsPage::category() const
+{
+ return QLatin1String(Constants::MAEMO_SETTINGS_CATEGORY);
+}
+
+QString MaemoDeviceConfigurationsSettingsPage::displayCategory() const
+{
+ return QCoreApplication::translate("Qt4ProjectManager",
+ Constants::MAEMO_SETTINGS_TR_CATEGORY);
+}
+
+QIcon MaemoDeviceConfigurationsSettingsPage::categoryIcon() const
+{
+ return QIcon(QLatin1String(Constants::MAEMO_SETTINGS_CATEGORY_ICON));
+}
+
+bool MaemoDeviceConfigurationsSettingsPage::matches(const QString &searchKeyWord) const
+{
+ return m_keywords.contains(searchKeyWord, Qt::CaseInsensitive);
+}
+
+QWidget *MaemoDeviceConfigurationsSettingsPage::createPage(QWidget *parent)
+{
+ m_widget = new MaemoDeviceConfigurationsSettingsWidget(parent);
+ if (m_keywords.isEmpty())
+ m_keywords = m_widget->searchKeywords();
+ return m_widget;
+}
+
+void MaemoDeviceConfigurationsSettingsPage::apply()
+{
+ m_widget->saveSettings();
+}
+
+void MaemoDeviceConfigurationsSettingsPage::finish()
+{
+}
+
+
+MaemoQemuSettingsPage::MaemoQemuSettingsPage(QObject *parent)
+ : Core::IOptionsPage(parent)
+{
+}
+
+MaemoQemuSettingsPage::~MaemoQemuSettingsPage()
+{
+}
+
+QString MaemoQemuSettingsPage::id() const
+{
+ return QLatin1String("ZZ.Qemu Settings");
+}
+
+QString MaemoQemuSettingsPage::displayName() const
+{
+ return tr("Qemu Settings");
+}
+
+QString MaemoQemuSettingsPage::category() const
+{
+ return QLatin1String(Constants::MAEMO_SETTINGS_CATEGORY);
+}
+
+QString MaemoQemuSettingsPage::displayCategory() const
+{
+ return QCoreApplication::translate("Qt4ProjectManager",
+ Constants::MAEMO_SETTINGS_TR_CATEGORY);
+}
+
+QIcon MaemoQemuSettingsPage::categoryIcon() const
+{
+ return QIcon(QLatin1String(Constants::MAEMO_SETTINGS_CATEGORY_ICON));
+}
+
+bool MaemoQemuSettingsPage::matches(const QString &searchKeyWord) const
+{
+ return m_widget->keywords().contains(searchKeyWord, Qt::CaseInsensitive);
+}
+
+QWidget *MaemoQemuSettingsPage::createPage(QWidget *parent)
+{
+ m_widget = new MaemoQemuSettingsWidget(parent);
+ return m_widget;
+}
+
+void MaemoQemuSettingsPage::apply()
+{
+ m_widget->saveSettings();
+}
+
+void MaemoQemuSettingsPage::finish()
+{
+}
+
+
+class MaemoQemuCrashDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ MaemoQemuCrashDialog(MaemoQemuSettingsPage *settingsPage)
+ : m_settingsPage(settingsPage)
+ {
+ setWindowTitle(tr("Qemu error"));
+ QString message = tr("Qemu crashed.");
+ const MaemoQemuSettings::OpenGlMode openGlMode
+ = MaemoQemuSettings::openGlMode();
+ const QString linkString = QLatin1String("<p><a href=\"dummy\">")
+ + tr("Click here to change the OpenGL mode.")
+ + QLatin1String("</a>");
+ if (openGlMode == MaemoQemuSettings::HardwareAcceleration) {
+ message += tr("<p>You have configured Qemu to use OpenGL "
+ "hardware acceleration, which might not be supported by "
+ "your system. You could try using software rendering instead.");
+ message += linkString;
+ } else if (openGlMode == MaemoQemuSettings::AutoDetect) {
+ message += tr("<p>Qemu is currently configured to auto-detect the "
+ "OpenGL mode, which is known to not work in some cases."
+ "You might want to use software rendering instead.");
+ message += linkString;
+ }
+ QLabel * const messageLabel = new QLabel(message, this);
+ messageLabel->setWordWrap(true);
+ messageLabel->setTextFormat(Qt::RichText);
+ connect(messageLabel, SIGNAL(linkActivated(QString)),
+ SLOT(showSettingsPage()));
+ QVBoxLayout *mainLayout = new QVBoxLayout(this);
+ mainLayout->addWidget(messageLabel);
+ QFrame * const separator = new QFrame;
+ separator->setFrameShape(QFrame::HLine);
+ separator->setFrameShadow(QFrame::Sunken);
+ mainLayout->addWidget(separator);
+ QDialogButtonBox * const buttonBox = new QDialogButtonBox;
+ buttonBox->addButton(QDialogButtonBox::Ok);
+ connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
+ mainLayout->addWidget(buttonBox);
+ }
+
+private:
+ Q_SLOT void showSettingsPage()
+ {
+ Core::ICore::instance()->showOptionsDialog(m_settingsPage->category(),
+ m_settingsPage->id());
+ accept();
+ }
+
+ MaemoQemuSettingsPage * const m_settingsPage;
+};
+
+
+void MaemoQemuSettingsPage::showQemuCrashDialog()
+{
+ MaemoQemuCrashDialog dlg(this);
+ dlg.exec();
+}
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#include "maemosettingspages.moc"
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemosettingspages.h b/src/plugins/qt4projectmanager/qt-maemo/maemosettingspages.h
new file mode 100644
index 0000000000..07440e1348
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemosettingspages.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file 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 MAEMOSETTINGSPAGES_H
+#define MAEMOSETTINGSPAGES_H
+
+#include <coreplugin/dialogs/ioptionspage.h>
+
+namespace Qt4ProjectManager{
+namespace Internal {
+
+class MaemoDeviceConfigurationsSettingsWidget;
+class MaemoQemuSettingsWidget;
+
+class MaemoDeviceConfigurationsSettingsPage : public Core::IOptionsPage
+{
+ Q_OBJECT
+public:
+ MaemoDeviceConfigurationsSettingsPage(QObject *parent);
+ ~MaemoDeviceConfigurationsSettingsPage();
+
+ virtual QString id() const;
+ virtual QString displayName() const;
+ virtual QString category() const;
+ virtual QString displayCategory() const;
+ virtual QIcon categoryIcon() const;
+ virtual bool matches(const QString &searchKeyWord) const;
+ virtual QWidget *createPage(QWidget *parent);
+ virtual void apply();
+ virtual void finish();
+
+private:
+ QString m_keywords;
+ MaemoDeviceConfigurationsSettingsWidget *m_widget;
+};
+
+class MaemoQemuSettingsPage : public Core::IOptionsPage
+{
+ Q_OBJECT
+public:
+ MaemoQemuSettingsPage(QObject *parent);
+ ~MaemoQemuSettingsPage();
+
+ virtual QString id() const;
+ virtual QString displayName() const;
+ virtual QString category() const;
+ virtual QString displayCategory() const;
+ virtual QIcon categoryIcon() const;
+ virtual bool matches(const QString &searchKeyWord) const;
+ virtual QWidget *createPage(QWidget *parent);
+ virtual void apply();
+ virtual void finish();
+
+ void showQemuCrashDialog();
+
+private:
+ QString m_keywords;
+ MaemoQemuSettingsWidget *m_widget;
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // MAEMOSETTINGSPAGES_H
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemosettingswidget.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemosettingswidget.cpp
deleted file mode 100644
index 6dc30094fe..0000000000
--- a/src/plugins/qt4projectmanager/qt-maemo/maemosettingswidget.cpp
+++ /dev/null
@@ -1,491 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of Qt Creator.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file 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 "maemosettingswidget.h"
-
-#include "ui_maemosettingswidget.h"
-
-#include "maemoconfigtestdialog.h"
-#include "maemodeviceconfigurations.h"
-#include "maemosshconfigdialog.h"
-
-#include <coreplugin/ssh/sshconnection.h>
-#include <coreplugin/ssh/sshremoteprocess.h>
-
-#include <QtCore/QFile>
-#include <QtCore/QFileInfo>
-#include <QtCore/QRegExp>
-#include <QtCore/QTextStream>
-
-#include <QtGui/QFileDialog>
-#include <QtGui/QMessageBox>
-#include <QtGui/QIntValidator>
-
-#include <algorithm>
-
-using namespace Core;
-
-namespace Qt4ProjectManager {
-namespace Internal {
-
-bool configNameExists(const QList<MaemoDeviceConfig> &devConfs,
- const QString &name)
-{
- return std::find_if(devConfs.constBegin(), devConfs.constEnd(),
- DevConfNameMatcher(name)) != devConfs.constEnd();
-}
-
-class NameValidator : public QValidator
-{
-public:
- NameValidator(const QList<MaemoDeviceConfig> &devConfs)
- : m_devConfs(devConfs)
- {
- }
-
- void setDisplayName(const QString &name) { m_oldName = name; }
-
- virtual State validate(QString &input, int & /* pos */) const
- {
- if (input.trimmed().isEmpty()
- || (input != m_oldName && configNameExists(m_devConfs, input)))
- return Intermediate;
- return Acceptable;
- }
-
- virtual void fixup(QString &input) const
- {
- int dummy = 0;
- if (validate(input, dummy) != Acceptable)
- input = m_oldName;
- }
-
-private:
- QString m_oldName;
- const QList<MaemoDeviceConfig> &m_devConfs;
-};
-
-
-MaemoSettingsWidget::MaemoSettingsWidget(QWidget *parent)
- : QWidget(parent),
- m_ui(new Ui_MaemoSettingsWidget),
- m_devConfs(MaemoDeviceConfigurations::instance().devConfigs()),
- m_nameValidator(new NameValidator(m_devConfs)),
- m_saveSettingsRequested(false)
-{
- initGui();
-}
-
-MaemoSettingsWidget::~MaemoSettingsWidget()
-{
- if (m_saveSettingsRequested)
- MaemoDeviceConfigurations::instance().setDevConfigs(m_devConfs);
- delete m_ui;
-}
-
-QString MaemoSettingsWidget::searchKeywords() const
-{
- QString rc;
- QTextStream(&rc) << m_ui->configurationLabel->text()
- << ' ' << m_ui->sshPortLabel->text()
- << ' ' << m_ui->keyButton->text()
- << ' ' << m_ui->passwordButton->text()
- << ' ' << m_ui->authTypeLabel->text()
- << ' ' << m_ui->connectionTimeoutLabel->text()
- << ' ' << m_ui->deviceButton->text()
- << ' ' << m_ui->simulatorButton->text()
- << ' ' << m_ui->deviceTypeLabel->text()
- << ' ' << m_ui->deviceNameLabel->text()
- << ' ' << m_ui->hostNameLabel->text()
- << ' ' << m_ui->keyLabel->text()
- << ' ' << m_ui->nameLineEdit->text()
- << ' ' << m_ui->passwordLabel->text()
- << ' ' << m_ui->freePortsLabel->text()
- << ' ' << m_ui->portsWarningLabel->text()
- << ' ' << m_ui->pwdLineEdit->text()
- << ' ' << m_ui->timeoutSpinBox->value()
- << ' ' << m_ui->userLineEdit->text()
- << ' ' << m_ui->userNameLabel->text();
- rc.remove(QLatin1Char('&'));
- return rc;
-}
-
-void MaemoSettingsWidget::initGui()
-{
- m_ui->setupUi(this);
- m_ui->nameLineEdit->setValidator(m_nameValidator);
- m_ui->keyFileLineEdit->setExpectedKind(Utils::PathChooser::File);
- QRegExpValidator * const portsValidator
- = new QRegExpValidator(QRegExp(MaemoDeviceConfig::portsRegExpr()), this);
- m_ui->portsLineEdit->setValidator(portsValidator);
- foreach (const MaemoDeviceConfig &devConf, m_devConfs)
- m_ui->configurationComboBox->addItem(devConf.name);
- connect(m_ui->configurationComboBox, SIGNAL(currentIndexChanged(int)),
- SLOT(currentConfigChanged(int)));
- currentConfigChanged(m_ui->configurationComboBox->currentIndex());
-}
-
-void MaemoSettingsWidget::addConfig()
-{
- const QString prefix = tr("New Device Configuration %1", "Standard "
- "Configuration name with number");
- int suffix = 1;
- QString newName;
- bool isUnique = false;
- do {
- newName = prefix.arg(QString::number(suffix++));
- isUnique = !configNameExists(m_devConfs, newName);
- } while (!isUnique);
-
- m_devConfs.append(MaemoDeviceConfig(newName, MaemoDeviceConfig::Physical));
- m_ui->configurationComboBox->addItem(newName);
- m_ui->removeConfigButton->setEnabled(true);
- m_ui->configurationComboBox->setCurrentIndex(m_ui->configurationComboBox->count()-1);
- m_ui->configurationComboBox->setFocus();
-}
-
-void MaemoSettingsWidget::deleteConfig()
-{
- const int selectedItem = m_ui->configurationComboBox->currentIndex();
- m_devConfs.removeAt(selectedItem);
- m_ui->configurationComboBox->removeItem(selectedItem);
- Q_ASSERT(m_ui->configurationComboBox->count() == m_devConfs.count());
-}
-
-void MaemoSettingsWidget::display(const MaemoDeviceConfig &devConfig)
-{
- MaemoDeviceConfig *otherConfig;
- if (devConfig.type == MaemoDeviceConfig::Physical) {
- m_lastConfigHW = devConfig;
- m_lastConfigSim
- = MaemoDeviceConfig(devConfig.name, MaemoDeviceConfig::Simulator);
- otherConfig = &m_lastConfigSim;
- m_ui->deviceButton->setChecked(true);
- } else {
- m_lastConfigSim = devConfig;
- m_lastConfigHW
- = MaemoDeviceConfig(devConfig.name, MaemoDeviceConfig::Physical);
- otherConfig = &m_lastConfigHW;
- m_ui->simulatorButton->setChecked(true);
- }
- otherConfig->server.authType = devConfig.server.authType;
- otherConfig->server.timeout = devConfig.server.timeout;
- otherConfig->server.pwd = devConfig.server.pwd;
- otherConfig->server.privateKeyFile = devConfig.server.privateKeyFile;
- otherConfig->internalId = devConfig.internalId;
-
- if (devConfig.server.authType == Core::SshConnectionParameters::AuthByPwd)
- m_ui->passwordButton->setChecked(true);
- else
- m_ui->keyButton->setChecked(true);
- m_ui->detailsWidget->setEnabled(true);
- m_nameValidator->setDisplayName(devConfig.name);
- m_ui->timeoutSpinBox->setValue(devConfig.server.timeout);
- fillInValues();
-}
-
-void MaemoSettingsWidget::fillInValues()
-{
- m_ui->nameLineEdit->setText(currentConfig().name);
- m_ui->hostLineEdit->setText(currentConfig().server.host);
- m_ui->sshPortSpinBox->setValue(currentConfig().server.port);
- m_ui->portsLineEdit->setText(currentConfig().portsSpec);
- m_ui->timeoutSpinBox->setValue(currentConfig().server.timeout);
- m_ui->userLineEdit->setText(currentConfig().server.uname);
- m_ui->pwdLineEdit->setText(currentConfig().server.pwd);
- m_ui->keyFileLineEdit->setPath(currentConfig().server.privateKeyFile);
- m_ui->showPasswordCheckBox->setChecked(false);
- updatePortsWarningLabel();
- const bool isSimulator
- = currentConfig().type == MaemoDeviceConfig::Simulator;
- m_ui->hostLineEdit->setReadOnly(isSimulator);
- m_ui->sshPortSpinBox->setReadOnly(isSimulator);
-}
-
-void MaemoSettingsWidget::saveSettings()
-{
- // We must defer this step because of a stupid bug on MacOS. See QTCREATORBUG-1675.
- m_saveSettingsRequested = true;
-}
-
-MaemoDeviceConfig &MaemoSettingsWidget::currentConfig()
-{
- Q_ASSERT(m_ui->configurationComboBox->count() == m_devConfs.count());
- const int currenIndex = m_ui->configurationComboBox->currentIndex();
- Q_ASSERT(currenIndex != -1);
- Q_ASSERT(currenIndex < m_devConfs.count());
- return m_devConfs[currenIndex];
-}
-
-void MaemoSettingsWidget::configNameEditingFinished()
-{
- if (m_ui->configurationComboBox->count() == 0)
- return;
-
- const QString &newName = m_ui->nameLineEdit->text();
- const int currentIndex = m_ui->configurationComboBox->currentIndex();
- m_ui->configurationComboBox->setItemData(currentIndex, newName, Qt::DisplayRole);
- currentConfig().name = newName;
- m_nameValidator->setDisplayName(newName);
-}
-
-void MaemoSettingsWidget::deviceTypeChanged()
-{
- const QString name = currentConfig().name;
- const MaemoDeviceConfig::DeviceType devType =
- m_ui->deviceButton->isChecked()
- ? MaemoDeviceConfig::Physical
- : MaemoDeviceConfig::Simulator;
-
- if (devType == MaemoDeviceConfig::Simulator) {
- m_lastConfigHW = currentConfig();
- currentConfig() = m_lastConfigSim;
- } else {
- m_lastConfigSim = currentConfig();
- currentConfig() = m_lastConfigHW;
- }
- currentConfig().name = name;
- fillInValues();
-}
-
-void MaemoSettingsWidget::authenticationTypeChanged()
-{
- const bool usePassword = m_ui->passwordButton->isChecked();
- currentConfig().server.authType
- = usePassword ? Core::SshConnectionParameters::AuthByPwd : Core::SshConnectionParameters::AuthByKey;
- m_ui->pwdLineEdit->setEnabled(usePassword);
- m_ui->passwordLabel->setEnabled(usePassword);
- m_ui->keyFileLineEdit->setEnabled(!usePassword);
- m_ui->keyLabel->setEnabled(!usePassword);
-}
-
-void MaemoSettingsWidget::hostNameEditingFinished()
-{
- currentConfig().server.host = m_ui->hostLineEdit->text();
-}
-
-void MaemoSettingsWidget::sshPortEditingFinished()
-{
- currentConfig().server.port = m_ui->sshPortSpinBox->value();
-}
-
-void MaemoSettingsWidget::handleFreePortsChanged()
-{
- currentConfig().portsSpec = m_ui->portsLineEdit->text();
- updatePortsWarningLabel();
-}
-
-void MaemoSettingsWidget::timeoutEditingFinished()
-{
- currentConfig().server.timeout = m_ui->timeoutSpinBox->value();
-}
-
-void MaemoSettingsWidget::userNameEditingFinished()
-{
- currentConfig().server.uname = m_ui->userLineEdit->text();
-}
-
-void MaemoSettingsWidget::passwordEditingFinished()
-{
- currentConfig().server.pwd = m_ui->pwdLineEdit->text();
-}
-
-void MaemoSettingsWidget::keyFileEditingFinished()
-{
- currentConfig().server.privateKeyFile = m_ui->keyFileLineEdit->path();
-}
-
-void MaemoSettingsWidget::showPassword(bool showClearText)
-{
- m_ui->pwdLineEdit->setEchoMode(showClearText
- ? QLineEdit::Normal : QLineEdit::Password);
-}
-
-void MaemoSettingsWidget::testConfig()
-{
- QDialog *dialog = new MaemoConfigTestDialog(currentConfig(), this);
- dialog->open();
-}
-
-void MaemoSettingsWidget::showGenerateSshKeyDialog()
-{
- MaemoSshConfigDialog dialog(this);
- dialog.exec();
-}
-
-void MaemoSettingsWidget::setPrivateKey(const QString &path)
-{
- m_ui->keyFileLineEdit->setPath(path);
- keyFileEditingFinished();
-}
-
-void MaemoSettingsWidget::deployKey()
-{
- if (m_keyDeployer)
- return;
-
- disconnect(m_ui->deployKeyButton, 0, this, 0);
- m_ui->deployKeyButton->setText(tr("Stop Deploying"));
- connect(m_ui->deployKeyButton, SIGNAL(clicked()), this,
- SLOT(stopDeploying()));
- m_connection = SshConnection::create();
- connect(m_connection.data(), SIGNAL(connected()), this,
- SLOT(handleConnected()));
- connect(m_connection.data(), SIGNAL(error(Core::SshError)), this,
- SLOT(handleConnectionFailure()));
- m_connection->connectToHost(currentConfig().server);
-}
-
-void MaemoSettingsWidget::handleConnected()
-{
- if (!m_connection)
- return;
-
- const QString &dir
- = QFileInfo(currentConfig().server.privateKeyFile).path();
- QString publicKeyFileName = QFileDialog::getOpenFileName(this,
- tr("Choose Public Key File"), dir,
- tr("Public Key Files(*.pub);;All Files (*)"));
- if (publicKeyFileName.isEmpty()) {
- stopDeploying();
- return;
- }
-
- QFile keyFile(publicKeyFileName);
- QByteArray key;
- const bool keyFileAccessible = keyFile.open(QIODevice::ReadOnly);
- if (keyFileAccessible)
- key = keyFile.readAll();
- if (!keyFileAccessible || keyFile.error() != QFile::NoError) {
- QMessageBox::critical(this, tr("Deployment Failed"),
- tr("Could not read public key file '%1'.").arg(publicKeyFileName));
- stopDeploying();
- return;
- }
-
- const QByteArray command = "test -d .ssh "
- "|| mkdir .ssh && chmod 0700 .ssh && echo '"
- + key + "' >> .ssh/authorized_keys";
- m_keyDeployer = m_connection->createRemoteProcess(command);
- connect(m_keyDeployer.data(), SIGNAL(closed(int)), this,
- SLOT(handleKeyUploadFinished(int)));
- m_keyDeployer->start();
-}
-
-void MaemoSettingsWidget::handleConnectionFailure()
-{
- if (!m_connection)
- return;
-
- QMessageBox::critical(this, tr("Deployment Failed"),
- tr("Could not connect to host: %1").arg(m_connection->errorString()));
- stopDeploying();
-}
-
-void MaemoSettingsWidget::handleKeyUploadFinished(int exitStatus)
-{
- Q_ASSERT(exitStatus == SshRemoteProcess::FailedToStart
- || exitStatus == SshRemoteProcess::KilledBySignal
- || exitStatus == SshRemoteProcess::ExitedNormally);
-
- if (!m_connection)
- return;
-
- if (exitStatus == SshRemoteProcess::ExitedNormally
- && m_keyDeployer->exitCode() == 0) {
- QMessageBox::information(this, tr("Deployment Succeeded"),
- tr("Key was successfully deployed."));
- } else {
- QMessageBox::critical(this, tr("Deployment Failed"),
- tr("Key deployment failed: %1.").arg(m_keyDeployer->errorString()));
- }
- stopDeploying();
-}
-
-void MaemoSettingsWidget::stopDeploying()
-{
- if (m_keyDeployer) {
- disconnect(m_keyDeployer.data(), 0, this, 0);
- m_keyDeployer = SshRemoteProcess::Ptr();
- }
- if (m_connection)
- disconnect(m_connection.data(), 0, this, 0);
- m_ui->deployKeyButton->disconnect();
- m_ui->deployKeyButton->setText(tr("Deploy Public Key ..."));
- connect(m_ui->deployKeyButton, SIGNAL(clicked()), this, SLOT(deployKey()));
-}
-
-void MaemoSettingsWidget::currentConfigChanged(int index)
-{
- stopDeploying();
- if (index == -1) {
- m_ui->removeConfigButton->setEnabled(false);
- m_ui->testConfigButton->setEnabled(false);
- m_ui->generateKeyButton->setEnabled(false);
- m_ui->deployKeyButton->setEnabled(false);
- clearDetails();
- m_ui->detailsWidget->setEnabled(false);
- } else {
- m_ui->removeConfigButton->setEnabled(true);
- m_ui->testConfigButton->setEnabled(true);
- m_ui->generateKeyButton->setEnabled(true);
- m_ui->deployKeyButton->setEnabled(true);
- m_ui->configurationComboBox->setCurrentIndex(index);
- display(currentConfig());
- }
-}
-
-void MaemoSettingsWidget::clearDetails()
-{
- m_ui->hostLineEdit->clear();
- m_ui->sshPortSpinBox->clear();
- m_ui->timeoutSpinBox->clear();
- m_ui->userLineEdit->clear();
- m_ui->pwdLineEdit->clear();
- m_ui->portsLineEdit->clear();
- m_ui->portsWarningLabel->clear();
-}
-
-void MaemoSettingsWidget::updatePortsWarningLabel()
-{
- if (currentConfig().freePorts().hasMore()) {
- m_ui->portsWarningLabel->clear();
- } else {
- m_ui->portsWarningLabel->setText(QLatin1String("<font color=\"red\">")
- + tr("You will need at least one port.") + QLatin1String("</font>"));
- }
-}
-
-} // namespace Internal
-} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemosettingswidget.h b/src/plugins/qt4projectmanager/qt-maemo/maemosettingswidget.h
deleted file mode 100644
index ae9048c042..0000000000
--- a/src/plugins/qt4projectmanager/qt-maemo/maemosettingswidget.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of Qt Creator.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file 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 MAEMOSETTINGSWIDGET_H
-#define MAEMOSETTINGSWIDGET_H
-
-#include "maemodeviceconfigurations.h"
-
-#include <QtCore/QList>
-#include <QtCore/QSharedPointer>
-#include <QtCore/QString>
-#include <QtGui/QWidget>
-
-QT_BEGIN_NAMESPACE
-class QLineEdit;
-
-class Ui_MaemoSettingsWidget;
-QT_END_NAMESPACE
-
-namespace Core {
-class SshConnection;
-class SshRemoteProcess;
-}
-
-namespace Qt4ProjectManager {
-namespace Internal {
-
-class MaemoSshRunner;
-class NameValidator;
-
-class MaemoSettingsWidget : public QWidget
-{
- Q_OBJECT
-public:
- MaemoSettingsWidget(QWidget *parent);
- ~MaemoSettingsWidget();
-
- void saveSettings();
- QString searchKeywords() const;
-
-private slots:
- void currentConfigChanged(int index);
- void addConfig();
- void deleteConfig();
- void configNameEditingFinished();
- void deviceTypeChanged();
- void authenticationTypeChanged();
- void hostNameEditingFinished();
- void sshPortEditingFinished();
- void timeoutEditingFinished();
- void userNameEditingFinished();
- void passwordEditingFinished();
- void keyFileEditingFinished();
- void showPassword(bool showClearText);
- void handleFreePortsChanged();
-
- // For configuration testing.
- void testConfig();
-
- void showGenerateSshKeyDialog();
- void setPrivateKey(const QString &path);
-
- // For key deploying.
- void deployKey();
- void stopDeploying();
- void handleConnected();
- void handleConnectionFailure();
- void handleKeyUploadFinished(int exitStatus);
-
-private:
- void initGui();
- void display(const MaemoDeviceConfig &devConfig);
- MaemoDeviceConfig &currentConfig();
- void clearDetails();
- QString parseTestOutput();
- void fillInValues();
- void updatePortsWarningLabel();
-
- Ui_MaemoSettingsWidget *m_ui;
- QList<MaemoDeviceConfig> m_devConfs;
- MaemoDeviceConfig m_lastConfigHW;
- MaemoDeviceConfig m_lastConfigSim;
- NameValidator * const m_nameValidator;
- QSharedPointer<Core::SshConnection> m_connection;
- QSharedPointer<Core::SshRemoteProcess> m_keyDeployer;
- bool m_saveSettingsRequested;
-};
-
-} // namespace Internal
-} // namespace Qt4ProjectManager
-
-#endif // MAEMOSETTINGSWIDGET_H
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemosettingswidget.ui b/src/plugins/qt4projectmanager/qt-maemo/maemosettingswidget.ui
deleted file mode 100644
index b2f03d3e76..0000000000
--- a/src/plugins/qt4projectmanager/qt-maemo/maemosettingswidget.ui
+++ /dev/null
@@ -1,760 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>MaemoSettingsWidget</class>
- <widget class="QWidget" name="MaemoSettingsWidget">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>602</width>
- <height>421</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Maemo Device Configurations</string>
- </property>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <layout class="QVBoxLayout" name="verticalLayout_3">
- <item>
- <layout class="QFormLayout" name="formLayout">
- <property name="fieldGrowthPolicy">
- <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
- </property>
- <item row="0" column="0">
- <widget class="QLabel" name="configurationLabel">
- <property name="text">
- <string>Configuration:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QComboBox" name="configurationComboBox">
- <property name="sizePolicy">
- <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="editable">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <widget class="QFrame" name="frame">
- <property name="frameShape">
- <enum>QFrame::StyledPanel</enum>
- </property>
- <property name="frameShadow">
- <enum>QFrame::Raised</enum>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_2">
- <item>
- <widget class="QWidget" name="detailsWidget" native="true">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <layout class="QFormLayout" name="formLayout_2">
- <property name="fieldGrowthPolicy">
- <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
- </property>
- <item row="0" column="0">
- <widget class="QLabel" name="deviceNameLabel">
- <property name="text">
- <string>Name</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QLineEdit" name="nameLineEdit"/>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="deviceTypeLabel">
- <property name="text">
- <string>Device type:</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QWidget" name="deviceTypeButtonsWidget" native="true">
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <property name="margin">
- <number>0</number>
- </property>
- <item>
- <widget class="QRadioButton" name="deviceButton">
- <property name="text">
- <string>Remote device</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QRadioButton" name="simulatorButton">
- <property name="text">
- <string>Maemo emulator</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="authTypeLabel">
- <property name="text">
- <string>Authentication type:</string>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QWidget" name="authTypeButtonsWidget" native="true">
- <layout class="QHBoxLayout" name="horizontalLayout_3">
- <property name="margin">
- <number>0</number>
- </property>
- <item>
- <widget class="QRadioButton" name="passwordButton">
- <property name="text">
- <string>Password</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QRadioButton" name="keyButton">
- <property name="text">
- <string>Key</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item row="3" column="0">
- <widget class="QLabel" name="hostNameLabel">
- <property name="text">
- <string>Host name:</string>
- </property>
- </widget>
- </item>
- <item row="3" column="1">
- <widget class="QLineEdit" name="hostLineEdit">
- <property name="placeholderText">
- <string>IP or host name of the device</string>
- </property>
- </widget>
- </item>
- <item row="4" column="0">
- <widget class="QLabel" name="sshPortLabel">
- <property name="text">
- <string>SSH port:</string>
- </property>
- </widget>
- </item>
- <item row="4" column="1">
- <layout class="QHBoxLayout" name="horizontalLayout_4">
- <item>
- <widget class="QSpinBox" name="sshPortSpinBox">
- <property name="minimum">
- <number>0</number>
- </property>
- <property name="maximum">
- <number>65535</number>
- </property>
- <property name="value">
- <number>22</number>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer_3">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- <item row="5" column="0">
- <widget class="QLabel" name="freePortsLabel">
- <property name="text">
- <string>Free ports:</string>
- </property>
- </widget>
- </item>
- <item row="5" column="1">
- <layout class="QHBoxLayout" name="horizontalLayout_7">
- <item>
- <widget class="QLineEdit" name="portsLineEdit">
- <property name="toolTip">
- <string>You can enter lists and ranges like this: 1024,1026-1028,1030</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="portsWarningLabel">
- <property name="text">
- <string>TextLabel</string>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer_2">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- <item row="6" column="0">
- <widget class="QLabel" name="connectionTimeoutLabel">
- <property name="text">
- <string>Connection timeout:</string>
- </property>
- </widget>
- </item>
- <item row="6" column="1">
- <layout class="QHBoxLayout" name="horizontalLayout_5">
- <item>
- <widget class="QSpinBox" name="timeoutSpinBox">
- <property name="suffix">
- <string>s</string>
- </property>
- <property name="maximum">
- <number>10000</number>
- </property>
- <property name="singleStep">
- <number>10</number>
- </property>
- <property name="value">
- <number>1000</number>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- <item row="7" column="0">
- <widget class="QLabel" name="userNameLabel">
- <property name="text">
- <string>Username:</string>
- </property>
- </widget>
- </item>
- <item row="7" column="1">
- <widget class="QLineEdit" name="userLineEdit"/>
- </item>
- <item row="8" column="0">
- <widget class="QLabel" name="passwordLabel">
- <property name="text">
- <string>Password:</string>
- </property>
- </widget>
- </item>
- <item row="8" column="1">
- <layout class="QHBoxLayout" name="horizontalLayout_6">
- <item>
- <widget class="QLineEdit" name="pwdLineEdit">
- <property name="echoMode">
- <enum>QLineEdit::Password</enum>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QCheckBox" name="showPasswordCheckBox">
- <property name="text">
- <string>Show password</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item row="9" column="0">
- <widget class="QLabel" name="keyLabel">
- <property name="text">
- <string>Private key file:</string>
- </property>
- </widget>
- </item>
- <item row="9" column="1">
- <widget class="Utils::PathChooser" name="keyFileLineEdit" native="true"/>
- </item>
- </layout>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <widget class="QPushButton" name="addConfigButton">
- <property name="text">
- <string>Add</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="removeConfigButton">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="text">
- <string>Remove</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="testConfigButton">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="text">
- <string>Test</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="generateKeyButton">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="text">
- <string>Generate SSH Key ...</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="deployKeyButton">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="text">
- <string>Deploy Public Key ...</string>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- <customwidgets>
- <customwidget>
- <class>Utils::PathChooser</class>
- <extends>QWidget</extends>
- <header location="global">utils/pathchooser.h</header>
- <container>1</container>
- <slots>
- <signal>editingFinished()</signal>
- <signal>browsingFinished()</signal>
- </slots>
- </customwidget>
- </customwidgets>
- <resources/>
- <connections>
- <connection>
- <sender>deviceButton</sender>
- <signal>clicked(bool)</signal>
- <receiver>MaemoSettingsWidget</receiver>
- <slot>deviceTypeChanged()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>231</x>
- <y>99</y>
- </hint>
- <hint type="destinationlabel">
- <x>511</x>
- <y>279</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>hostLineEdit</sender>
- <signal>editingFinished()</signal>
- <receiver>MaemoSettingsWidget</receiver>
- <slot>hostNameEditingFinished()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>335</x>
- <y>148</y>
- </hint>
- <hint type="destinationlabel">
- <x>424</x>
- <y>231</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>userLineEdit</sender>
- <signal>editingFinished()</signal>
- <receiver>MaemoSettingsWidget</receiver>
- <slot>userNameEditingFinished()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>425</x>
- <y>302</y>
- </hint>
- <hint type="destinationlabel">
- <x>422</x>
- <y>301</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>pwdLineEdit</sender>
- <signal>editingFinished()</signal>
- <receiver>MaemoSettingsWidget</receiver>
- <slot>passwordEditingFinished()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>297</x>
- <y>334</y>
- </hint>
- <hint type="destinationlabel">
- <x>423</x>
- <y>336</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>simulatorButton</sender>
- <signal>clicked(bool)</signal>
- <receiver>MaemoSettingsWidget</receiver>
- <slot>deviceTypeChanged()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>335</x>
- <y>99</y>
- </hint>
- <hint type="destinationlabel">
- <x>426</x>
- <y>87</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>addConfigButton</sender>
- <signal>clicked()</signal>
- <receiver>MaemoSettingsWidget</receiver>
- <slot>addConfig()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>465</x>
- <y>27</y>
- </hint>
- <hint type="destinationlabel">
- <x>516</x>
- <y>118</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>removeConfigButton</sender>
- <signal>clicked()</signal>
- <receiver>MaemoSettingsWidget</receiver>
- <slot>deleteConfig()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>473</x>
- <y>61</y>
- </hint>
- <hint type="destinationlabel">
- <x>513</x>
- <y>101</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>passwordButton</sender>
- <signal>toggled(bool)</signal>
- <receiver>MaemoSettingsWidget</receiver>
- <slot>authenticationTypeChanged()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>231</x>
- <y>122</y>
- </hint>
- <hint type="destinationlabel">
- <x>513</x>
- <y>240</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>keyFileLineEdit</sender>
- <signal>editingFinished()</signal>
- <receiver>MaemoSettingsWidget</receiver>
- <slot>keyFileEditingFinished()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>425</x>
- <y>356</y>
- </hint>
- <hint type="destinationlabel">
- <x>257</x>
- <y>185</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>keyFileLineEdit</sender>
- <signal>browsingFinished()</signal>
- <receiver>MaemoSettingsWidget</receiver>
- <slot>keyFileEditingFinished()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>425</x>
- <y>356</y>
- </hint>
- <hint type="destinationlabel">
- <x>257</x>
- <y>185</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>testConfigButton</sender>
- <signal>clicked()</signal>
- <receiver>MaemoSettingsWidget</receiver>
- <slot>testConfig()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>473</x>
- <y>90</y>
- </hint>
- <hint type="destinationlabel">
- <x>428</x>
- <y>351</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>deployKeyButton</sender>
- <signal>clicked()</signal>
- <receiver>MaemoSettingsWidget</receiver>
- <slot>deployKey()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>473</x>
- <y>148</y>
- </hint>
- <hint type="destinationlabel">
- <x>510</x>
- <y>351</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>keyButton</sender>
- <signal>toggled(bool)</signal>
- <receiver>MaemoSettingsWidget</receiver>
- <slot>authenticationTypeChanged()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>335</x>
- <y>122</y>
- </hint>
- <hint type="destinationlabel">
- <x>525</x>
- <y>351</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>nameLineEdit</sender>
- <signal>editingFinished()</signal>
- <receiver>MaemoSettingsWidget</receiver>
- <slot>configNameEditingFinished()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>237</x>
- <y>75</y>
- </hint>
- <hint type="destinationlabel">
- <x>330</x>
- <y>332</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>generateKeyButton</sender>
- <signal>clicked()</signal>
- <receiver>MaemoSettingsWidget</receiver>
- <slot>showGenerateSshKeyDialog()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>585</x>
- <y>131</y>
- </hint>
- <hint type="destinationlabel">
- <x>358</x>
- <y>0</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>timeoutSpinBox</sender>
- <signal>editingFinished()</signal>
- <receiver>MaemoSettingsWidget</receiver>
- <slot>timeoutEditingFinished()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>237</x>
- <y>270</y>
- </hint>
- <hint type="destinationlabel">
- <x>6</x>
- <y>333</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>timeoutSpinBox</sender>
- <signal>valueChanged(int)</signal>
- <receiver>MaemoSettingsWidget</receiver>
- <slot>timeoutEditingFinished()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>237</x>
- <y>270</y>
- </hint>
- <hint type="destinationlabel">
- <x>0</x>
- <y>299</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>sshPortSpinBox</sender>
- <signal>editingFinished()</signal>
- <receiver>MaemoSettingsWidget</receiver>
- <slot>sshPortEditingFinished()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>228</x>
- <y>200</y>
- </hint>
- <hint type="destinationlabel">
- <x>4</x>
- <y>211</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>sshPortSpinBox</sender>
- <signal>valueChanged(int)</signal>
- <receiver>MaemoSettingsWidget</receiver>
- <slot>sshPortEditingFinished()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>230</x>
- <y>204</y>
- </hint>
- <hint type="destinationlabel">
- <x>3</x>
- <y>136</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>showPasswordCheckBox</sender>
- <signal>toggled(bool)</signal>
- <receiver>MaemoSettingsWidget</receiver>
- <slot>showPassword(bool)</slot>
- <hints>
- <hint type="sourcelabel">
- <x>424</x>
- <y>332</y>
- </hint>
- <hint type="destinationlabel">
- <x>3</x>
- <y>262</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>portsLineEdit</sender>
- <signal>editingFinished()</signal>
- <receiver>MaemoSettingsWidget</receiver>
- <slot>handleFreePortsChanged()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>184</x>
- <y>225</y>
- </hint>
- <hint type="destinationlabel">
- <x>0</x>
- <y>393</y>
- </hint>
- </hints>
- </connection>
- </connections>
- <slots>
- <slot>configNameEditingFinished()</slot>
- <slot>deviceTypeChanged()</slot>
- <slot>hostNameEditingFinished()</slot>
- <slot>sshPortEditingFinished()</slot>
- <slot>timeoutEditingFinished()</slot>
- <slot>userNameEditingFinished()</slot>
- <slot>passwordEditingFinished()</slot>
- <slot>addConfig()</slot>
- <slot>selectionChanged()</slot>
- <slot>deleteConfig()</slot>
- <slot>authenticationTypeChanged()</slot>
- <slot>keyFileEditingFinished()</slot>
- <slot>testConfig()</slot>
- <slot>deployKey()</slot>
- <slot>gdbServerPortEditingFinished()</slot>
- <slot>currentConfigChanged(int)</slot>
- <slot>showGenerateSshKeyDialog()</slot>
- <slot>showPassword(bool)</slot>
- <slot>handleFreePortsChanged()</slot>
- </slots>
-</ui>
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemosshconfigdialog.ui b/src/plugins/qt4projectmanager/qt-maemo/maemosshconfigdialog.ui
index d85c4764d0..d3acf09585 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemosshconfigdialog.ui
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemosshconfigdialog.ui
@@ -44,7 +44,10 @@
</sizepolicy>
</property>
<property name="text">
- <string>Key size:</string>
+ <string>Key &amp;size:</string>
+ </property>
+ <property name="buddy">
+ <cstring>comboBox</cstring>
</property>
</widget>
</item>
@@ -98,7 +101,7 @@
</sizepolicy>
</property>
<property name="text">
- <string>RSA</string>
+ <string>&amp;RSA</string>
</property>
<property name="checked">
<bool>true</bool>
@@ -114,7 +117,7 @@
</sizepolicy>
</property>
<property name="text">
- <string>DSA</string>
+ <string>&amp;DSA</string>
</property>
</widget>
</item>
@@ -175,7 +178,7 @@
<item>
<widget class="QPushButton" name="generateButton">
<property name="text">
- <string>Generate SSH Key</string>
+ <string>&amp;Generate SSH Key</string>
</property>
</widget>
</item>
@@ -198,7 +201,7 @@
<bool>false</bool>
</property>
<property name="text">
- <string>Save Public Key...</string>
+ <string>Save P&amp;ublic Key...</string>
</property>
</widget>
</item>
@@ -208,7 +211,7 @@
<bool>false</bool>
</property>
<property name="text">
- <string>Save Private Key...</string>
+ <string>Save Pr&amp;ivate Key...</string>
</property>
</widget>
</item>
@@ -235,7 +238,7 @@
<item>
<widget class="QPushButton" name="closeButton">
<property name="text">
- <string>Close</string>
+ <string>&amp;Close</string>
</property>
</widget>
</item>
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemosshrunner.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemosshrunner.cpp
index db29a62e82..8e4e0fca97 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemosshrunner.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemosshrunner.cpp
@@ -40,6 +40,7 @@
#include "maemoremotemounter.h"
#include "maemoremotemountsmodel.h"
#include "maemorunconfiguration.h"
+#include "maemousedportsgatherer.h"
#include <coreplugin/ssh/sshconnection.h>
#include <coreplugin/ssh/sshremoteprocess.h>
@@ -48,7 +49,7 @@
#include <limits>
-#define ASSERT_STATE(state) assertState(state, Q_FUNC_INFO)
+#define ASSERT_STATE(state) ASSERT_STATE_GENERIC(State, state, m_state)
using namespace Core;
@@ -57,16 +58,25 @@ namespace Internal {
MaemoSshRunner::MaemoSshRunner(QObject *parent,
MaemoRunConfiguration *runConfig, bool debugging)
- : QObject(parent), m_runConfig(runConfig),
+ : QObject(parent),
m_mounter(new MaemoRemoteMounter(this)),
+ m_portsGatherer(new MaemoUsedPortsGatherer(this)),
m_devConfig(runConfig->deviceConfig()),
- m_debugging(debugging), m_state(Inactive)
+ m_remoteExecutable(runConfig->remoteExecutableFilePath()),
+ m_appArguments(runConfig->arguments()),
+ m_userEnvChanges(runConfig->userEnvironmentChanges()),
+ m_initialFreePorts(runConfig->freePorts()),
+ m_mountSpecs(runConfig->remoteMounts()->mountSpecs()),
+ m_state(Inactive)
{
- m_procsToKill
- << QFileInfo(m_runConfig->localExecutableFilePath()).fileName()
- << QLatin1String("utfs-client");
- if (debugging)
- m_procsToKill << QLatin1String("gdbserver");
+ m_connection = runConfig->deployStep()->sshConnection();
+ m_mounter->setToolchain(runConfig->toolchain());
+ if (debugging && runConfig->useRemoteGdb()) {
+ m_mountSpecs << MaemoMountSpecification(runConfig->localDirToMountForRemoteGdb(),
+ runConfig->remoteProjectSourcesMountPoint());
+ }
+
+ m_procsToKill << QFileInfo(m_remoteExecutable).fileName();
connect(m_mounter, SIGNAL(mounted()), this, SLOT(handleMounted()));
connect(m_mounter, SIGNAL(unmounted()), this, SLOT(handleUnmounted()));
connect(m_mounter, SIGNAL(error(QString)), this,
@@ -75,6 +85,10 @@ MaemoSshRunner::MaemoSshRunner(QObject *parent,
SIGNAL(reportProgress(QString)));
connect(m_mounter, SIGNAL(debugOutput(QString)), this,
SIGNAL(mountDebugOutput(QString)));
+ connect(m_portsGatherer, SIGNAL(error(QString)), this,
+ SLOT(handlePortsGathererError(QString)));
+ connect(m_portsGatherer, SIGNAL(portListReady()), this,
+ SLOT(handleUsedPortsAvailable()));
}
MaemoSshRunner::~MaemoSshRunner() {}
@@ -83,11 +97,20 @@ void MaemoSshRunner::start()
{
ASSERT_STATE(QList<State>() << Inactive << StopRequested);
+ if (m_remoteExecutable.isEmpty()) {
+ emitError(tr("Cannot run: No remote executable set."));
+ return;
+ }
+ if (!m_devConfig.isValid()) {
+ emitError(tr("Cannot run: No device configuration set."));
+ return;
+ }
+
setState(Connecting);
m_exitStatus = -1;
+ m_freePorts = m_initialFreePorts;
if (m_connection)
disconnect(m_connection.data(), 0, this, 0);
- m_connection = m_runConfig->deployStep()->sshConnection();
const bool reUse = isConnectionUsable();
if (!reUse)
m_connection = SshConnection::create();
@@ -95,7 +118,7 @@ void MaemoSshRunner::start()
SLOT(handleConnected()));
connect(m_connection.data(), SIGNAL(error(Core::SshError)), this,
SLOT(handleConnectionFailure()));
- if (reUse) {
+ if (reUse) {
handleConnected();
} else {
emit reportProgress(tr("Connecting to device..."));
@@ -129,9 +152,10 @@ void MaemoSshRunner::handleConnectionFailure()
if (m_state == Inactive)
qWarning("Unexpected state %d in %s.", m_state, Q_FUNC_INFO);
- const QString errorTemplate = m_state == Connecting
- ? tr("Could not connect to host: %1") : tr("Connection failed: %1");
- emitError(errorTemplate.arg(m_connection->errorString()));
+ const QString errorMsg = m_state == Connecting
+ ? MaemoGlobal::failedToConnectToServerMessage(m_connection, m_devConfig)
+ : tr("Connection error: %1").arg(m_connection->errorString());
+ emitError(errorMsg);
}
void MaemoSshRunner::cleanup()
@@ -190,37 +214,15 @@ void MaemoSshRunner::handleUnmounted()
switch (m_state) {
case PreRunCleaning: {
- m_mounter->resetMountSpecifications();
- MaemoPortList portList = m_devConfig.freePorts();
- if (m_debugging) { // gdbserver and QML inspector need one port each.
- MaemoRunConfiguration::DebuggingType debuggingType
- = m_runConfig->debuggingType();
- if (debuggingType != MaemoRunConfiguration::DebugQmlOnly
- && !m_runConfig->useRemoteGdb())
- portList.getNext();
- if (debuggingType != MaemoRunConfiguration::DebugCppOnly)
- portList.getNext();
- }
- m_mounter->setToolchain(m_runConfig->toolchain());
- m_mounter->setPortList(portList);
- const MaemoRemoteMountsModel * const remoteMounts
- = m_runConfig->remoteMounts();
- for (int i = 0; i < remoteMounts->mountSpecificationCount(); ++i) {
- if (!addMountSpecification(remoteMounts->mountSpecificationAt(i)))
- return;
- }
- if (m_debugging && m_runConfig->useRemoteGdb()) {
- if (!addMountSpecification(MaemoMountSpecification(
- m_runConfig->localDirToMountForRemoteGdb(),
- MaemoGlobal::remoteProjectSourcesMountPoint())))
- return;
- }
+ for (int i = 0; i < m_mountSpecs.count(); ++i)
+ m_mounter->addMountSpecification(m_mountSpecs.at(i), false);
setState(PreMountUnmounting);
unmount();
break;
}
case PreMountUnmounting:
- mount();
+ setState(GatheringPorts);
+ m_portsGatherer->start(m_connection, m_freePorts);
break;
case PostRunCleaning:
case StopRequested: {
@@ -263,11 +265,6 @@ void MaemoSshRunner::startExecution(const QByteArray &remoteCall)
{
ASSERT_STATE(ReadyForExecution);
- if (m_runConfig->remoteExecutableFilePath().isEmpty()) {
- emitError(tr("Cannot run: No remote executable set."));
- return;
- }
-
m_runner = m_connection->createRemoteProcess(remoteCall);
connect(m_runner.data(), SIGNAL(started()), this,
SIGNAL(remoteProcessStarted()));
@@ -295,38 +292,17 @@ void MaemoSshRunner::handleRemoteProcessFinished(int exitStatus)
}
}
-bool MaemoSshRunner::addMountSpecification(const MaemoMountSpecification &mountSpec)
-{
- if (!m_mounter->addMountSpecification(mountSpec, false)) {
- emitError(tr("The device does not have enough free ports "
- "for this run configuration."));
- return false;
- }
- return true;
-}
-
bool MaemoSshRunner::isConnectionUsable() const
{
return m_connection && m_connection->state() == SshConnection::Connected
&& m_connection->connectionParameters() == m_devConfig.server;
}
-void MaemoSshRunner::assertState(State expectedState, const char *func)
-{
- assertState(QList<State>() << expectedState, func);
-}
-
-void MaemoSshRunner::assertState(const QList<State> &expectedStates,
- const char *func)
-{
- if (!expectedStates.contains(m_state))
- qWarning("Unexpected state %d at %s.", m_state, func);
-}
-
void MaemoSshRunner::setState(State newState)
{
if (newState == Inactive) {
m_mounter->setConnection(SshConnection::Ptr());
+ m_portsGatherer->stop();
if (m_connection) {
disconnect(m_connection.data(), 0, this, 0);
m_connection = SshConnection::Ptr();
@@ -350,7 +326,7 @@ void MaemoSshRunner::mount()
setState(Mounting);
if (m_mounter->hasValidMountSpecifications()) {
emit reportProgress(tr("Mounting host directories..."));
- m_mounter->mount();
+ m_mounter->mount(freePorts(), m_portsGatherer);
} else {
handleMounted();
}
@@ -381,6 +357,21 @@ void MaemoSshRunner::unmount()
}
}
+void MaemoSshRunner::handlePortsGathererError(const QString &errorMsg)
+{
+ emitError(errorMsg);
+}
+
+void MaemoSshRunner::handleUsedPortsAvailable()
+{
+ ASSERT_STATE(QList<State>() << GatheringPorts << StopRequested);
+
+ if (m_state == StopRequested) {
+ setState(Inactive);
+ } else {
+ mount();
+ }
+}
const qint64 MaemoSshRunner::InvalidExitCode
= std::numeric_limits<qint64>::min();
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemosshrunner.h b/src/plugins/qt4projectmanager/qt-maemo/maemosshrunner.h
index 2c756a2382..dba27d2e18 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemosshrunner.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemosshrunner.h
@@ -38,6 +38,8 @@
#include "maemodeviceconfigurations.h"
#include "maemomountspecification.h"
+#include <utils/environment.h>
+
#include <QtCore/QObject>
#include <QtCore/QSharedPointer>
#include <QtCore/QStringList>
@@ -51,6 +53,7 @@ namespace Qt4ProjectManager {
namespace Internal {
class MaemoRemoteMounter;
class MaemoRunConfiguration;
+class MaemoUsedPortsGatherer;
class MaemoSshRunner : public QObject
{
@@ -67,6 +70,13 @@ public:
QSharedPointer<Core::SshConnection> connection() const { return m_connection; }
+ const MaemoUsedPortsGatherer *usedPortsGatherer() const { return m_portsGatherer; }
+ MaemoPortList *freePorts() { return &m_freePorts; }
+ MaemoDeviceConfig deviceConfig() const { return m_devConfig; }
+ QString remoteExecutable() const { return m_remoteExecutable; }
+ QString arguments() const { return m_appArguments; }
+ QList<Utils::EnvironmentItem> userEnvChanges() const { return m_userEnvChanges; }
+
static const qint64 InvalidExitCode;
signals:
@@ -87,35 +97,39 @@ private slots:
void handleMounted();
void handleUnmounted();
void handleMounterError(const QString &errorMsg);
+ void handlePortsGathererError(const QString &errorMsg);
+ void handleUsedPortsAvailable();
private:
enum State { Inactive, Connecting, PreRunCleaning, PostRunCleaning,
PreMountUnmounting, Mounting, ReadyForExecution,
- ProcessStarting, StopRequested
+ ProcessStarting, StopRequested, GatheringPorts
};
- void assertState(State expectedState, const char *func);
- void assertState(const QList<State> &expectedStates, const char *func);
void setState(State newState);
void emitError(const QString &errorMsg);
void cleanup();
- bool addMountSpecification(const MaemoMountSpecification &mountSpec);
bool isConnectionUsable() const;
void mount();
void unmount();
- MaemoRunConfiguration * const m_runConfig; // TODO this pointer can be invalid
MaemoRemoteMounter * const m_mounter;
+ MaemoUsedPortsGatherer * const m_portsGatherer;
const MaemoDeviceConfig m_devConfig;
+ const QString m_remoteExecutable;
+ const QString m_appArguments;
+ const QList<Utils::EnvironmentItem> m_userEnvChanges;
+ const MaemoPortList m_initialFreePorts;
+ QList<MaemoMountSpecification> m_mountSpecs;
QSharedPointer<Core::SshConnection> m_connection;
QSharedPointer<Core::SshRemoteProcess> m_runner;
QSharedPointer<Core::SshRemoteProcess> m_cleaner;
QStringList m_procsToKill;
+ MaemoPortList m_freePorts;
int m_exitStatus;
- const bool m_debugging;
State m_state;
};
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemotemplatesmanager.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemotemplatesmanager.cpp
index ed18e98c0c..ea0893c26f 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemotemplatesmanager.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemotemplatesmanager.cpp
@@ -65,7 +65,9 @@ namespace Qt4ProjectManager {
namespace Internal {
namespace {
-const QByteArray IconFieldName("XB-Maemo-Icon-26:");
+const QByteArray IconFieldName("XB-Maemo-Icon-26");
+const QByteArray NameFieldName("XB-Maemo-Display-Name");
+const QByteArray ShortDescriptionFieldName("Description");
const QLatin1String PackagingDirName("qtc_packaging");
const QLatin1String DebianDirNameFremantle("debian_fremantle");
} // anonymous namespace
@@ -119,7 +121,7 @@ bool MaemoTemplatesManager::handleTarget(ProjectExplorer::Target *target)
const Qt4Target * const qt4Target = qobject_cast<Qt4Target *>(target);
const MaemoDeployStep * const deployStep
= MaemoGlobal::buildStep<MaemoDeployStep>(qt4Target->activeDeployConfiguration());
- connect(deployStep->deployables(), SIGNAL(modelReset()), this,
+ connect(deployStep->deployables().data(), SIGNAL(modelReset()), this,
SLOT(handleProFileUpdated()), Qt::QueuedConnection);
Project * const project = target->project();
@@ -159,13 +161,15 @@ bool MaemoTemplatesManager::createDebianTemplatesIfNecessary(const ProjectExplor
QString error;
const Qt4Target * const qt4Target = qobject_cast<const Qt4Target *>(target);
Q_ASSERT_X(qt4Target, Q_FUNC_INFO, "Target ID does not match actual type.");
+ const Qt4BuildConfiguration * const bc
+ = qt4Target->activeBuildConfiguration();
const MaemoToolChain * const tc
- = dynamic_cast<MaemoToolChain *>(qt4Target->activeBuildConfiguration()->toolChain());
+ = dynamic_cast<MaemoToolChain *>(bc->toolChain());
if (!tc) {
qDebug("Maemo target has no Maemo toolchain.");
return false;
}
- if (!MaemoPackageCreationStep::preparePackagingProcess(&dh_makeProc, tc,
+ if (!MaemoPackageCreationStep::preparePackagingProcess(&dh_makeProc, bc,
projectDir.path() + QLatin1Char('/') + PackagingDirName, &error)) {
raiseError(error);
return false;
@@ -173,7 +177,8 @@ bool MaemoTemplatesManager::createDebianTemplatesIfNecessary(const ProjectExplor
const QString dhMakeDebianDir = projectDir.path() + QLatin1Char('/')
+ PackagingDirName + QLatin1String("/debian");
- MaemoPackageCreationStep::removeDirectory(dhMakeDebianDir);
+ QString removeError;
+ MaemoGlobal::removeRecursively(dhMakeDebianDir, removeError);
const QString command = QLatin1String("dh_make -s -n -p ")
+ MaemoPackageCreationStep::packageName(project) + QLatin1Char('_')
+ MaemoPackageCreationStep::DefaultVersionNumber;
@@ -195,7 +200,7 @@ bool MaemoTemplatesManager::createDebianTemplatesIfNecessary(const ProjectExplor
if (!QFile::rename(dhMakeDebianDir, debianDirPath(project))) {
raiseError(tr("Unable to move new debian directory to '%1'.")
.arg(QDir::toNativeSeparators(debianDirPath(project))));
- MaemoPackageCreationStep::removeDirectory(dhMakeDebianDir);
+ MaemoGlobal::removeRecursively(dhMakeDebianDir, removeError);
return false;
}
@@ -225,7 +230,6 @@ bool MaemoTemplatesManager::adaptRulesFile(const Project *project)
QByteArray rulesContents = rulesFile.readAll();
rulesContents.replace("DESTDIR", "INSTALL_ROOT");
rulesContents.replace("dh_shlibdeps", "# dh_shlibdeps");
- rulesContents.replace("dh_strip", "# dh_strip");
// rulesContents.replace("$(MAKE) clean", "# $(MAKE) clean");
// const Qt4Project * const qt4Project
// = static_cast<const Qt4Project *>(project);
@@ -262,6 +266,8 @@ bool MaemoTemplatesManager::adaptControlFile(const Project *project)
adaptControlFileField(controlContents, "Section", "user/hidden");
adaptControlFileField(controlContents, "Priority", "optional");
+ adaptControlFileField(controlContents, NameFieldName,
+ project->displayName().toUtf8());
const int buildDependsOffset = controlContents.indexOf("Build-Depends:");
if (buildDependsOffset == -1) {
qDebug("Unexpected: no Build-Depends field in debian control file.");
@@ -287,21 +293,29 @@ bool MaemoTemplatesManager::adaptControlFile(const Project *project)
return true;
}
-void MaemoTemplatesManager::adaptControlFileField(QByteArray &document,
+bool MaemoTemplatesManager::adaptControlFileField(QByteArray &document,
const QByteArray &fieldName, const QByteArray &newFieldValue)
{
QByteArray adaptedLine = fieldName + ": " + newFieldValue;
const int lineOffset = document.indexOf(fieldName + ":");
if (lineOffset == -1) {
document.append(adaptedLine).append('\n');
- } else {
- int newlineOffset = document.indexOf('\n', lineOffset);
- if (newlineOffset == -1) {
- newlineOffset = document.length();
- adaptedLine += '\n';
- }
- document.replace(lineOffset, newlineOffset - lineOffset, adaptedLine);
+ return true;
+ }
+
+ int newlineOffset = document.indexOf('\n', lineOffset);
+ bool updated = false;
+ if (newlineOffset == -1) {
+ newlineOffset = document.length();
+ adaptedLine += '\n';
+ updated = true;
}
+ const int replaceCount = newlineOffset - lineOffset;
+ if (!updated && document.mid(lineOffset, replaceCount) != adaptedLine)
+ updated = true;
+ if (updated)
+ document.replace(lineOffset, replaceCount, adaptedLine);
+ return updated;
}
bool MaemoTemplatesManager::updateDesktopFiles(const Qt4Target *target)
@@ -339,7 +353,7 @@ bool MaemoTemplatesManager::updateDesktopFile(const Qt4Target *target,
= existsAlready ? desktopFile.readAll() : desktopTemplate;
QString executable;
- const MaemoDeployables * const deployables
+ const QSharedPointer<MaemoDeployables> &deployables
= MaemoGlobal::buildStep<MaemoDeployStep>(target->activeDeployConfiguration())
->deployables();
for (int i = 0; i < deployables->modelCount(); ++i) {
@@ -474,36 +488,10 @@ bool MaemoTemplatesManager::setVersion(const Project *project,
QIcon MaemoTemplatesManager::packageManagerIcon(const Project *project,
QString *error) const
{
- QSharedPointer<QFile> controlFile
- = openFile(controlFilePath(project), QIODevice::ReadOnly, error);
- if (!controlFile)
- return QIcon();
-
- bool iconFieldFound = false;
- QByteArray currentLine;
- while (!iconFieldFound && !controlFile->atEnd()) {
- currentLine = controlFile->readLine();
- iconFieldFound = currentLine.startsWith(IconFieldName);
- }
- if (!iconFieldFound)
+ const QByteArray &base64Icon
+ = controlFileFieldValue(project, IconFieldName, true);
+ if (base64Icon.isEmpty())
return QIcon();
-
- int pos = IconFieldName.length();
- currentLine = currentLine.trimmed();
- QByteArray base64Icon;
- do {
- while (pos < currentLine.length())
- base64Icon += currentLine.at(pos++);
- do
- currentLine = controlFile->readLine();
- while (currentLine.startsWith('#'));
- if (currentLine.isEmpty() || !isspace(currentLine.at(0)))
- break;
- currentLine = currentLine.trimmed();
- if (currentLine.isEmpty())
- break;
- pos = 0;
- } while (true);
QPixmap pixmap;
if (!pixmap.loadFromData(QByteArray::fromBase64(base64Icon))) {
*error = tr("Invalid icon data in Debian control file.");
@@ -536,16 +524,17 @@ bool MaemoTemplatesManager::setPackageManagerIcon(const Project *project,
buffer.close();
iconAsBase64 = iconAsBase64.toBase64();
QByteArray contents = controlFile->readAll();
- const int iconFieldPos = contents.startsWith(IconFieldName)
- ? 0 : contents.indexOf('\n' + IconFieldName);
+ const QByteArray iconFieldNameWithColon = IconFieldName + ':';
+ const int iconFieldPos = contents.startsWith(iconFieldNameWithColon)
+ ? 0 : contents.indexOf('\n' + iconFieldNameWithColon);
if (iconFieldPos == -1) {
if (!contents.endsWith('\n'))
contents += '\n';
- contents.append(IconFieldName).append(' ').append(iconAsBase64)
+ contents.append(iconFieldNameWithColon).append(' ').append(iconAsBase64)
.append('\n');
} else {
- const int oldIconStartPos
- = (iconFieldPos != 0) + iconFieldPos + IconFieldName.length();
+ const int oldIconStartPos = (iconFieldPos != 0) + iconFieldPos
+ + iconFieldNameWithColon.length();
int nextEolPos = contents.indexOf('\n', oldIconStartPos);
while (nextEolPos != -1 && nextEolPos != contents.length() - 1
&& contents.at(nextEolPos + 1) != '\n'
@@ -568,6 +557,43 @@ bool MaemoTemplatesManager::setPackageManagerIcon(const Project *project,
return true;
}
+QString MaemoTemplatesManager::name(const Project *project) const
+{
+ return QString::fromUtf8(controlFileFieldValue(project, NameFieldName, false));
+}
+
+bool MaemoTemplatesManager::setName(const Project *project, const QString &name)
+{
+ return setFieldValue(project, NameFieldName, name.toUtf8());
+}
+
+QString MaemoTemplatesManager::shortDescription(const Project *project) const
+{
+ return QString::fromUtf8(controlFileFieldValue(project,
+ ShortDescriptionFieldName, false));
+}
+
+bool MaemoTemplatesManager::setShortDescription(const Project *project,
+ const QString &description)
+{
+ return setFieldValue(project, ShortDescriptionFieldName,
+ description.toUtf8());
+}
+
+bool MaemoTemplatesManager::setFieldValue(const Project *project,
+ const QByteArray &fieldName, const QByteArray &fieldValue)
+{
+ QFile controlFile(controlFilePath(project));
+ if (!controlFile.open(QIODevice::ReadWrite))
+ return false;
+ QByteArray contents = controlFile.readAll();
+ if (adaptControlFileField(contents, fieldName, fieldValue)) {
+ controlFile.resize(0);
+ controlFile.write(contents);
+ }
+ return true;
+}
+
QStringList MaemoTemplatesManager::debianFiles(const Project *project) const
{
return QDir(debianDirPath(project))
@@ -590,6 +616,44 @@ QString MaemoTemplatesManager::controlFilePath(const Project *project) const
return debianDirPath(project) + QLatin1String("/control");
}
+QByteArray MaemoTemplatesManager::controlFileFieldValue(const Project *project,
+ const QString &key, bool multiLine) const
+{
+ QByteArray value;
+ QFile controlFile(controlFilePath(project));
+ if (!controlFile.open(QIODevice::ReadOnly))
+ return value;
+ const QByteArray &contents = controlFile.readAll();
+ const int keyPos = contents.indexOf(key.toUtf8() + ':');
+ if (keyPos == -1)
+ return value;
+ int valueStartPos = keyPos + key.length() + 1;
+ int valueEndPos = contents.indexOf('\n', keyPos);
+ if (valueEndPos == -1)
+ valueEndPos = contents.count();
+ value = contents.mid(valueStartPos, valueEndPos - valueStartPos).trimmed();
+ if (multiLine) {
+ Q_FOREVER {
+ valueStartPos = valueEndPos + 1;
+ if (valueStartPos >= contents.count())
+ break;
+ const char firstChar = contents.at(valueStartPos);
+ if (firstChar == '#' || isspace(firstChar)) {
+ valueEndPos = contents.indexOf('\n', valueStartPos);
+ if (valueEndPos == -1)
+ valueEndPos = contents.count();
+ if (firstChar != '#') {
+ value += contents.mid(valueStartPos,
+ valueEndPos - valueStartPos).trimmed();
+ }
+ } else {
+ break;
+ }
+ }
+ }
+ return value;
+}
+
void MaemoTemplatesManager::raiseError(const QString &reason)
{
QMessageBox::critical(0, tr("Error creating Maemo templates"), reason);
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemotemplatesmanager.h b/src/plugins/qt4projectmanager/qt-maemo/maemotemplatesmanager.h
index 000de47ee9..afc2ee1062 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemotemplatesmanager.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemotemplatesmanager.h
@@ -40,7 +40,7 @@
#include <QtCore/QSharedPointer>
#include <QtGui/QIcon>
-QT_FORWARD_DECLARE_CLASS(QFileSystemWatcher);
+QT_FORWARD_DECLARE_CLASS(QFileSystemWatcher)
namespace ProjectExplorer {
class Project;
@@ -50,10 +50,10 @@ class Target;
namespace Qt4ProjectManager {
class Qt4Project;
+class Qt4Target;
namespace Internal {
class Qt4ProFileNode;
-class Qt4Target;
class MaemoTemplatesManager : public QObject
{
@@ -75,6 +75,14 @@ public:
bool setPackageManagerIcon(const ProjectExplorer::Project *project,
const QString &iconFilePath, QString *error) const;
+ QString name(const ProjectExplorer::Project *project) const;
+ bool setName(const ProjectExplorer::Project *project,
+ const QString &name);
+
+ QString shortDescription(const ProjectExplorer::Project *project) const;
+ bool setShortDescription(const ProjectExplorer::Project *project,
+ const QString &description);
+
signals:
void debianDirContentsChanged(const ProjectExplorer::Project *project);
void changeLogChanged(const ProjectExplorer::Project *project);
@@ -102,10 +110,14 @@ private:
int &lineEndPos, int &valuePos);
bool adaptRulesFile(const ProjectExplorer::Project *project);
bool adaptControlFile(const ProjectExplorer::Project *project);
- void adaptControlFileField(QByteArray &document, const QByteArray &fieldName,
+ bool adaptControlFileField(QByteArray &document, const QByteArray &fieldName,
const QByteArray &newFieldValue);
QSharedPointer<QFile> openFile(const QString &filePath,
QIODevice::OpenMode mode, QString *error) const;
+ bool setFieldValue(const ProjectExplorer::Project *project,
+ const QByteArray &fieldName, const QByteArray &fieldValue);
+ QByteArray controlFileFieldValue(const ProjectExplorer::Project *project,
+ const QString &key, bool multiLine) const;
static MaemoTemplatesManager *m_instance;
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemotoolchain.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemotoolchain.cpp
index 31cd51941f..2e700e9b33 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemotoolchain.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemotoolchain.cpp
@@ -53,9 +53,9 @@ MaemoToolChain::~MaemoToolChain()
{
}
-ToolChain::ToolChainType MaemoToolChain::type() const
+ProjectExplorer::ToolChainType MaemoToolChain::type() const
{
- return ToolChain::GCC_MAEMO;
+ return ProjectExplorer::ToolChain_GCC_MAEMO;
}
void MaemoToolChain::addToEnvironment(Utils::Environment &env)
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemotoolchain.h b/src/plugins/qt4projectmanager/qt-maemo/maemotoolchain.h
index 82d6d8e788..3627925b05 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemotoolchain.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemotoolchain.h
@@ -47,7 +47,7 @@ public:
virtual ~MaemoToolChain();
void addToEnvironment(Utils::Environment &env);
- ProjectExplorer::ToolChain::ToolChainType type() const;
+ ProjectExplorer::ToolChainType type() const;
QString makeCommand() const;
QString maddeRoot() const;
@@ -59,10 +59,7 @@ public:
enum MaemoVersion { Maemo5, Maemo6 };
MaemoVersion version() const;
bool allowsRemoteMounts() const { return version() == Maemo5; }
-
- // TODO: Perhaps re-enable when we deploy via UTFS again, otherwise throw the whole function away.
- bool allowsPackagingDisabling() const { return /* version() == Maemo5 */ false; }
-
+ bool allowsPackagingDisabling() const { return version() == Maemo5; }
bool allowsQmlDebugging() const { return version() == Maemo6; }
protected:
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemousedportsgatherer.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemousedportsgatherer.cpp
new file mode 100644
index 0000000000..78b6617bc4
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemousedportsgatherer.cpp
@@ -0,0 +1,170 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Creator.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file 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 "maemousedportsgatherer.h"
+
+#include "maemoglobal.h"
+
+#include <coreplugin/ssh/sshremoteprocessrunner.h>
+
+using namespace Core;
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+MaemoUsedPortsGatherer::MaemoUsedPortsGatherer(QObject *parent) :
+ QObject(parent), m_running(false)
+{
+}
+
+MaemoUsedPortsGatherer::~MaemoUsedPortsGatherer() {}
+
+void MaemoUsedPortsGatherer::start(const Core::SshConnection::Ptr &connection,
+ const MaemoPortList &portList)
+{
+ if (m_running)
+ qWarning("Unexpected call of %s in running state", Q_FUNC_INFO);
+ m_usedPorts.clear();
+ m_remoteStdout.clear();
+ m_remoteStderr.clear();
+ m_procRunner = SshRemoteProcessRunner::create(connection);
+ connect(m_procRunner.data(), SIGNAL(connectionError(Core::SshError)),
+ SLOT(handleConnectionError()));
+ connect(m_procRunner.data(), SIGNAL(processClosed(int)),
+ SLOT(handleProcessClosed(int)));
+ connect(m_procRunner.data(), SIGNAL(processOutputAvailable(QByteArray)),
+ SLOT(handleRemoteStdOut(QByteArray)));
+ connect(m_procRunner.data(), SIGNAL(processErrorOutputAvailable(QByteArray)),
+ SLOT(handleRemoteStdErr(QByteArray)));
+ const QString command = MaemoGlobal::remoteSudo()
+ + QLatin1String(" lsof -nPi4tcp:") + portList.toString()
+ + QLatin1String(" -F n |grep '^n' |sed -r 's/[^:]*:([[:digit:]]+).*/\\1/g' |sort -n |uniq");
+ m_procRunner->run(command.toUtf8());
+ m_running = true;
+}
+
+void MaemoUsedPortsGatherer::stop()
+{
+ if (!m_running)
+ return;
+ m_running = false;
+ disconnect(m_procRunner->connection().data(), 0, this, 0);
+ if (m_procRunner->process())
+ m_procRunner->process()->closeChannel();
+}
+
+int MaemoUsedPortsGatherer::getNextFreePort(MaemoPortList *freePorts) const
+{
+ while (freePorts->hasMore()) {
+ const int port = freePorts->getNext();
+ if (!m_usedPorts.contains(port))
+ return port;
+ }
+ return -1;
+}
+
+void MaemoUsedPortsGatherer::setupUsedPorts()
+{
+ const QList<QByteArray> &portStrings = m_remoteStdout.split('\n');
+ foreach (const QByteArray &portString, portStrings) {
+ if (portString.isEmpty())
+ continue;
+ bool ok;
+ const int port = portString.toInt(&ok);
+ if (ok) {
+ m_usedPorts << port;
+ } else {
+ qWarning("%s: Unexpected string '%s' is not a port.",
+ Q_FUNC_INFO, portString.data());
+ }
+ }
+ emit portListReady();
+}
+
+void MaemoUsedPortsGatherer::handleConnectionError()
+{
+ if (!m_running)
+ return;
+ emit error(tr("Connection error: %1").
+ arg(m_procRunner->connection()->errorString()));
+ stop();
+}
+
+void MaemoUsedPortsGatherer::handleProcessClosed(int exitStatus)
+{
+ if (!m_running)
+ return;
+ QString errMsg;
+ switch (exitStatus) {
+ case SshRemoteProcess::FailedToStart:
+ errMsg = tr("Could not start remote process: %1")
+ .arg(m_procRunner->process()->errorString());
+ break;
+ case SshRemoteProcess::KilledBySignal:
+ errMsg = tr("Remote process crashed: %1")
+ .arg(m_procRunner->process()->errorString());
+ break;
+ case SshRemoteProcess::ExitedNormally:
+ if (m_procRunner->process()->exitCode() == 0) {
+ setupUsedPorts();
+ } else {
+ errMsg = tr("Remote process failed: %1")
+ .arg(m_procRunner->process()->errorString());
+ }
+ break;
+ default:
+ Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid exit status");
+ }
+
+ if (!errMsg.isEmpty()) {
+ if (!m_remoteStderr.isEmpty()) {
+ errMsg += tr("\nRemote error output was: %1")
+ .arg(QString::fromUtf8(m_remoteStderr));
+ }
+ emit error(errMsg);
+ }
+ stop();
+}
+
+void MaemoUsedPortsGatherer::handleRemoteStdOut(const QByteArray &output)
+{
+ m_remoteStdout += output;
+}
+
+void MaemoUsedPortsGatherer::handleRemoteStdErr(const QByteArray &output)
+{
+ m_remoteStderr += output;
+}
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemousedportsgatherer.h b/src/plugins/qt4projectmanager/qt-maemo/maemousedportsgatherer.h
new file mode 100644
index 0000000000..fdf1062861
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemousedportsgatherer.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Creator.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file 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 MAEMOUSEDPORTSGATHERER_H
+#define MAEMOUSEDPORTSGATHERER_H
+
+#include "maemodeviceconfigurations.h"
+
+#include <QtCore/QList>
+#include <QtCore/QObject>
+#include <QtCore/QSharedPointer>
+#include <QtCore/QString>
+
+namespace Core {
+class SshConnection;
+class SshRemoteProcessRunner;
+}
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+class MaemoUsedPortsGatherer : public QObject
+{
+ Q_OBJECT
+public:
+ explicit MaemoUsedPortsGatherer(QObject *parent = 0);
+ ~MaemoUsedPortsGatherer();
+ void start(const QSharedPointer<Core::SshConnection> &connection,
+ const MaemoPortList &portList);
+ void stop();
+ int getNextFreePort(MaemoPortList *freePorts) const; // returns -1 if no more are left
+ QList<int> usedPorts() const { return m_usedPorts; }
+
+signals:
+ void error(const QString &errMsg);
+ void portListReady();
+
+private slots:
+ void handleConnectionError();
+ void handleProcessClosed(int exitStatus);
+ void handleRemoteStdOut(const QByteArray &output);
+ void handleRemoteStdErr(const QByteArray &output);
+
+private:
+ void setupUsedPorts();
+
+ QSharedPointer<Core::SshRemoteProcessRunner> m_procRunner;
+ QList<int> m_usedPorts;
+ QByteArray m_remoteStdout;
+ QByteArray m_remoteStderr;
+ bool m_running;
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // MAEMOUSEDPORTSGATHERER_H
diff --git a/src/plugins/qt4projectmanager/qt-maemo/qt-maemo.pri b/src/plugins/qt4projectmanager/qt-maemo/qt-maemo.pri
index 4b7608e007..297a0ce4d6 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/qt-maemo.pri
+++ b/src/plugins/qt4projectmanager/qt-maemo/qt-maemo.pri
@@ -7,8 +7,8 @@ HEADERS += \
$$PWD/maemorunconfigurationwidget.h \
$$PWD/maemoruncontrol.h \
$$PWD/maemorunfactories.h \
- $$PWD/maemosettingspage.h \
- $$PWD/maemosettingswidget.h \
+ $$PWD/maemosettingspages.h \
+ $$PWD/maemodeviceconfigurationssettingswidget.h \
$$PWD/maemosshconfigdialog.h \
$$PWD/maemotoolchain.h \
$$PWD/maemopackagecreationstep.h \
@@ -16,7 +16,6 @@ HEADERS += \
$$PWD/maemopackagecreationwidget.h \
$$PWD/maemodeployablelistmodel.h \
$$PWD/maemoqemumanager.h \
- $$PWD/maemoprofilewrapper.h \
$$PWD/maemodeployables.h \
$$PWD/maemodeployable.h \
$$PWD/maemodeploystep.h \
@@ -31,7 +30,22 @@ HEADERS += \
$$PWD/maemotemplatesmanager.h \
$$PWD/maemomountspecification.h \
$$PWD/maemoremotemounter.h \
- $$PWD/maemoprofilesupdatedialog.h
+ $$PWD/maemoprofilesupdatedialog.h \
+ $$PWD/maemousedportsgatherer.h \
+ $$PWD/maemoremoteprocesslist.h \
+ $$PWD/maemoremoteprocessesdialog.h \
+ $$PWD/maemopublishingwizardfactories.h \
+ $$PWD/maemopublishingbuildsettingspagefremantlefree.h \
+ $$PWD/maemopublishingfileselectiondialog.h \
+ $$PWD/maemopublishedprojectmodel.h \
+ $$PWD/maemopublishinguploadsettingspagefremantlefree.h \
+ $$PWD/maemopublishingwizardfremantlefree.h \
+ $$PWD/maemopublishingresultpagefremantlefree.h \
+ $$PWD/maemopublisherfremantlefree.h \
+ $$PWD/maemoqemuruntime.h \
+ $$PWD/maemoqemuruntimeparser.h \
+ $$PWD/maemoqemusettingswidget.h \
+ $$PWD/maemoqemusettings.h
SOURCES += \
$$PWD/maemoconfigtestdialog.cpp \
@@ -41,8 +55,8 @@ SOURCES += \
$$PWD/maemorunconfigurationwidget.cpp \
$$PWD/maemoruncontrol.cpp \
$$PWD/maemorunfactories.cpp \
- $$PWD/maemosettingspage.cpp \
- $$PWD/maemosettingswidget.cpp \
+ $$PWD/maemosettingspages.cpp \
+ $$PWD/maemodeviceconfigurationssettingswidget.cpp \
$$PWD/maemosshconfigdialog.cpp \
$$PWD/maemotoolchain.cpp \
$$PWD/maemopackagecreationstep.cpp \
@@ -50,7 +64,6 @@ SOURCES += \
$$PWD/maemopackagecreationwidget.cpp \
$$PWD/maemodeployablelistmodel.cpp \
$$PWD/maemoqemumanager.cpp \
- $$PWD/maemoprofilewrapper.cpp \
$$PWD/maemodeployables.cpp \
$$PWD/maemodeploystep.cpp \
$$PWD/maemodeploystepwidget.cpp \
@@ -64,14 +77,34 @@ SOURCES += \
$$PWD/maemotemplatesmanager.cpp \
$$PWD/maemomountspecification.cpp \
$$PWD/maemoremotemounter.cpp \
- $$PWD/maemoprofilesupdatedialog.cpp
+ $$PWD/maemoprofilesupdatedialog.cpp \
+ $$PWD/maemousedportsgatherer.cpp \
+ $$PWD/maemoremoteprocesslist.cpp \
+ $$PWD/maemoremoteprocessesdialog.cpp \
+ $$PWD/maemopublishingwizardfactories.cpp \
+ $$PWD/maemopublishingbuildsettingspagefremantlefree.cpp \
+ $$PWD/maemopublishingfileselectiondialog.cpp \
+ $$PWD/maemopublishedprojectmodel.cpp \
+ $$PWD/maemopublishinguploadsettingspagefremantlefree.cpp \
+ $$PWD/maemopublishingwizardfremantlefree.cpp \
+ $$PWD/maemopublishingresultpagefremantlefree.cpp \
+ $$PWD/maemopublisherfremantlefree.cpp \
+ $$PWD/maemoqemuruntimeparser.cpp \
+ $$PWD/maemoqemusettingswidget.cpp \
+ $$PWD/maemoqemusettings.cpp
FORMS += \
$$PWD/maemoconfigtestdialog.ui \
- $$PWD/maemosettingswidget.ui \
+ $$PWD/maemodeviceconfigurationssettingswidget.ui \
$$PWD/maemosshconfigdialog.ui \
$$PWD/maemopackagecreationwidget.ui \
$$PWD/maemodeploystepwidget.ui \
- $$PWD/maemoprofilesupdatedialog.ui
+ $$PWD/maemoprofilesupdatedialog.ui \
+ $$PWD/maemoremoteprocessesdialog.ui \
+ $$PWD/maemopublishingbuildsettingspagefremantlefree.ui \
+ $$PWD/maemopublishingfileselectiondialog.ui \
+ $$PWD/maemopublishinguploadsettingspagefremantlefree.ui \
+ $$PWD/maemopublishingresultpagefremantlefree.ui \
+ $$PWD/maemoqemusettingswidget.ui
RESOURCES += $$PWD/qt-maemo.qrc
diff --git a/src/plugins/qt4projectmanager/qt-s60/abldparser.cpp b/src/plugins/qt4projectmanager/qt-s60/abldparser.cpp
index 5abfadc11b..85708cb059 100644
--- a/src/plugins/qt4projectmanager/qt-s60/abldparser.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/abldparser.cpp
@@ -36,6 +36,8 @@
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/taskwindow.h>
+#include <QtCore/QDir>
+
using namespace Qt4ProjectManager;
using namespace ProjectExplorer;
using namespace ProjectExplorer::Constants;
@@ -77,7 +79,7 @@ void AbldParser::stdOutput(const QString &line)
if (m_perlIssue.indexIn(lne) > -1) {
m_waitingForStdOutContinuation = true;
- m_currentFile = m_perlIssue.cap(2);
+ m_currentFile = QDir::fromNativeSeparators(m_perlIssue.cap(2));
m_currentLine = m_perlIssue.cap(3).toInt();
Task task(Task::Unknown,
@@ -147,7 +149,7 @@ void AbldParser::stdError(const QString &line)
}
if (lne.startsWith(QLatin1String("MMPFILE \""))) {
- m_currentFile = lne.mid(9, lne.size() - 10);
+ m_currentFile = QDir::fromNativeSeparators(lne.mid(9, lne.size() - 10));
m_waitingForStdErrContinuation = false;
return;
}
diff --git a/src/plugins/qt4projectmanager/qt-s60/certificatepathchooser.cpp b/src/plugins/qt4projectmanager/qt-s60/certificatepathchooser.cpp
new file mode 100644
index 0000000000..3d0bbf873e
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-s60/certificatepathchooser.cpp
@@ -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.
+**
+**************************************************************************/
+
+#include "certificatepathchooser.h"
+
+#include <QMessageBox>
+
+#include "s60certificateinfo.h"
+
+using namespace Qt4ProjectManager;
+using namespace Qt4ProjectManager::Internal;
+
+CertificatePathChooser::CertificatePathChooser(QWidget *parent) :
+ Utils::PathChooser(parent)
+{
+}
+
+bool CertificatePathChooser::validatePath(const QString &path, QString *errorMessage)
+{
+ if (Utils::PathChooser::validatePath(path, errorMessage)) {
+ QScopedPointer<Qt4ProjectManager::Internal::S60CertificateInfo>
+ certInfoPtr(new Qt4ProjectManager::Internal::S60CertificateInfo(path));
+ if (certInfoPtr.data()->validateCertificate()
+ == Qt4ProjectManager::Internal::S60CertificateInfo::CertificateValid) {
+ if (errorMessage)
+ *errorMessage = certInfoPtr.data()->toHtml();
+ return true;
+ } else {
+ if (errorMessage)
+ *errorMessage = certInfoPtr.data()->errorString();
+ }
+ }
+ return false;
+}
diff --git a/src/plugins/qt4projectmanager/qt-s60/certificatepathchooser.h b/src/plugins/qt4projectmanager/qt-s60/certificatepathchooser.h
new file mode 100644
index 0000000000..c335d72c5b
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-s60/certificatepathchooser.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 CERTIFICATEPATHCHOOSER_H
+#define CERTIFICATEPATHCHOOSER_H
+
+#include "utils/pathchooser.h"
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+class CertificatePathChooser : public Utils::PathChooser
+{
+ Q_DISABLE_COPY(CertificatePathChooser)
+ Q_OBJECT
+public:
+ explicit CertificatePathChooser(QWidget *parent = 0);
+
+ virtual bool validatePath(const QString &path, QString *errorMessage = 0);
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // CERTIFICATEPATHCHOOSER_H
diff --git a/src/plugins/qt4projectmanager/qt-s60/gccetoolchain.cpp b/src/plugins/qt4projectmanager/qt-s60/gccetoolchain.cpp
index d881632ff3..238e504651 100644
--- a/src/plugins/qt4projectmanager/qt-s60/gccetoolchain.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/gccetoolchain.cpp
@@ -71,7 +71,7 @@ static QString gcceCommand(const QString &dir)
// The GccToolChain base class constructor wants to know the gcc command
GCCEToolChain *GCCEToolChain::create(const S60Devices::Device &device,
const QString &gcceRoot,
- ProjectExplorer::ToolChain::ToolChainType type)
+ ProjectExplorer::ToolChainType type)
{
const QString gccCommand = gcceCommand(gcceRoot);
const QFileInfo gccCommandFi(gccCommand);
@@ -82,18 +82,18 @@ GCCEToolChain *GCCEToolChain::create(const S60Devices::Device &device,
GCCEToolChain::GCCEToolChain(const S60Devices::Device &device,
const QString &gcceBinPath,
const QString &gcceCommand,
- ProjectExplorer::ToolChain::ToolChainType type) :
+ ProjectExplorer::ToolChainType type) :
GccToolChain(gcceCommand),
m_mixin(device),
m_type(type),
m_gcceBinPath(gcceBinPath)
{
- QTC_ASSERT(m_type == ProjectExplorer::ToolChain::GCCE || m_type == ProjectExplorer::ToolChain::GCCE_GNUPOC, return)
+ QTC_ASSERT(m_type == ProjectExplorer::ToolChain_GCCE || m_type == ProjectExplorer::ToolChain_GCCE_GNUPOC, return)
if (debug)
qDebug() << "GCCEToolChain on" << m_type << gcceCommand << gcceBinPath << m_mixin.device();
}
-ToolChain::ToolChainType GCCEToolChain::type() const
+ProjectExplorer::ToolChainType GCCEToolChain::type() const
{
return m_type;
}
@@ -114,10 +114,10 @@ QList<HeaderPath> GCCEToolChain::systemHeaderPaths()
if (m_systemHeaderPaths.isEmpty()) {
GccToolChain::systemHeaderPaths();
switch (m_type) {
- case ProjectExplorer::ToolChain::GCCE:
+ case ProjectExplorer::ToolChain_GCCE:
m_systemHeaderPaths += m_mixin.epocHeaderPaths();
break;
- case ProjectExplorer::ToolChain::GCCE_GNUPOC:
+ case ProjectExplorer::ToolChain_GCCE_GNUPOC:
m_systemHeaderPaths += m_mixin.gnuPocHeaderPaths();
break;
default:
@@ -135,10 +135,10 @@ void GCCEToolChain::addToEnvironment(Utils::Environment &env)
if (!m_gcceBinPath.isEmpty())
env.prependOrSetPath(m_gcceBinPath);
switch (m_type) {
- case ProjectExplorer::ToolChain::GCCE:
+ case ProjectExplorer::ToolChain_GCCE:
m_mixin.addEpocToEnvironment(&env);
break;
- case ProjectExplorer::ToolChain::GCCE_GNUPOC:
+ case ProjectExplorer::ToolChain_GCCE_GNUPOC:
m_mixin.addGnuPocToEnvironment(&env);
break;
default:
@@ -152,7 +152,11 @@ void GCCEToolChain::addToEnvironment(Utils::Environment &env)
QString GCCEToolChain::makeCommand() const
{
+#if defined (Q_OS_WIN)
+ return QLatin1String("make.exe");
+#else
return QLatin1String("make");
+#endif
}
bool GCCEToolChain::equals(const ToolChain *otherIn) const
diff --git a/src/plugins/qt4projectmanager/qt-s60/gccetoolchain.h b/src/plugins/qt4projectmanager/qt-s60/gccetoolchain.h
index 2d4a43429c..f51bd4bd95 100644
--- a/src/plugins/qt4projectmanager/qt-s60/gccetoolchain.h
+++ b/src/plugins/qt4projectmanager/qt-s60/gccetoolchain.h
@@ -46,16 +46,16 @@ class GCCEToolChain : public ProjectExplorer::GccToolChain
explicit GCCEToolChain(const S60Devices::Device &device,
const QString &gcceBinPath,
const QString &gcceCommand,
- ProjectExplorer::ToolChain::ToolChainType type);
+ ProjectExplorer::ToolChainType type);
public:
static GCCEToolChain *create(const S60Devices::Device &device,
const QString &gcceRoot,
- ProjectExplorer::ToolChain::ToolChainType type);
+ ProjectExplorer::ToolChainType type);
QByteArray predefinedMacros();
virtual QList<ProjectExplorer::HeaderPath> systemHeaderPaths();
virtual void addToEnvironment(Utils::Environment &env);
- virtual ProjectExplorer::ToolChain::ToolChainType type() const;
+ virtual ProjectExplorer::ToolChainType type() const;
virtual QString makeCommand() const;
protected:
@@ -64,7 +64,7 @@ protected:
private:
QString gcceVersion() const;
const S60ToolChainMixin m_mixin;
- const ProjectExplorer::ToolChain::ToolChainType m_type;
+ const ProjectExplorer::ToolChainType m_type;
const QString m_gcceBinPath;
mutable QString m_gcceVersion;
};
diff --git a/src/plugins/qt4projectmanager/qt-s60/passphraseforkeydialog.cpp b/src/plugins/qt4projectmanager/qt-s60/passphraseforkeydialog.cpp
index daeac5dfe8..a0cf50ad20 100644
--- a/src/plugins/qt4projectmanager/qt-s60/passphraseforkeydialog.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/passphraseforkeydialog.cpp
@@ -33,74 +33,68 @@
#include "passphraseforkeydialog.h"
+#include <QtGui/QCheckBox>
#include <QtGui/QDialogButtonBox>
#include <QtGui/QLabel>
-#include <QtGui/QFormLayout>
#include <QtGui/QLineEdit>
-#include <QtGui/QCheckBox>
+#include <QtGui/QPushButton>
+#include <QtGui/QVBoxLayout>
using namespace Qt4ProjectManager;
-PassphraseForKeyDialog::PassphraseForKeyDialog(const QString &keyName, QWidget *parent)
- : QDialog(parent)
+PassphraseForKeyDialog::PassphraseForKeyDialog(const QString &keyName, QWidget *parent) :
+ QDialog(parent),
+ m_buttonBox(0),
+ m_saveCheckBox(0),
+ m_passphraseEdit(0)
{
- QFormLayout *formLayout = new QFormLayout(this);
- setLayout(formLayout);
+ QVBoxLayout *layout = new QVBoxLayout(this);
+
+ QHBoxLayout *hPasswordLayout = new QHBoxLayout;
QLabel *passphraseLabel = new QLabel(this);
passphraseLabel->setText(tr("Passphrase:"));
- passphraseLabel->setObjectName(QString::fromUtf8("passphraseLabel"));
-
- formLayout->setWidget(0, QFormLayout::LabelRole, passphraseLabel);
-
- QLineEdit *passphraseLineEdit = new QLineEdit(this);
- passphraseLineEdit->setObjectName(QString::fromUtf8("passphraseLineEdit"));
- passphraseLineEdit->setEchoMode(QLineEdit::Password);
-
- connect(passphraseLineEdit, SIGNAL(textChanged(QString)), this, SLOT(setPassphrase(QString)));
+ hPasswordLayout->addWidget(passphraseLabel);
- formLayout->setWidget(0, QFormLayout::FieldRole, passphraseLineEdit);
+ m_passphraseEdit = new QLineEdit(this);
+ m_passphraseEdit->setEchoMode(QLineEdit::Password);
+ connect(m_passphraseEdit, SIGNAL(textChanged(QString)), this, SLOT(passphraseChanged()));
+ hPasswordLayout->addWidget(m_passphraseEdit);
- m_checkBox = new QCheckBox(this);
- m_checkBox->setText(tr("Save passphrase"));
- m_checkBox->setObjectName(QString::fromUtf8("checkBox"));
- m_checkBox->setToolTip(tr("This is an insecure option. The password will be saved as a plain text."));
+ m_saveCheckBox = new QCheckBox(this);
+ m_saveCheckBox->setText(tr("Save passphrase"));
+ m_saveCheckBox->setToolTip(tr("This is an insecure option. The password will be saved as plain text."));
- formLayout->setWidget(1, QFormLayout::LabelRole, m_checkBox);
+ m_buttonBox = new QDialogButtonBox(this);
+ m_buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
- QDialogButtonBox *buttonBox = new QDialogButtonBox(this);
- buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
- buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
+ connect(m_buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
+ connect(m_buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
- connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
- connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
+ layout->addLayout(hPasswordLayout);
+ layout->addWidget(m_saveCheckBox);
+ layout->addItem(new QSpacerItem(0, 10));
+ layout->addWidget(m_buttonBox);
- formLayout->setWidget(2, QFormLayout::FieldRole, buttonBox);
setWindowTitle(tr("Passphrase for %1").arg(keyName));
- setFixedSize( sizeHint() );
-}
+ setFixedSize(sizeHint());
-void PassphraseForKeyDialog::accept()
-{
- done(1);
-}
-
-void PassphraseForKeyDialog::reject()
-{
- done(0);
+ passphraseChanged();
}
-void PassphraseForKeyDialog::setPassphrase(const QString &passphrase)
+void PassphraseForKeyDialog::passphraseChanged()
{
- m_passphrase = passphrase;
+ // We tried the empty passphrase when we get here, so disallow it
+ Q_ASSERT(m_buttonBox->button(QDialogButtonBox::Ok));
+ m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!m_passphraseEdit->text().isEmpty());
}
QString PassphraseForKeyDialog::passphrase() const
{
- return m_passphrase;
+ return m_passphraseEdit->text();
}
bool PassphraseForKeyDialog::savePassphrase() const
{
- return m_checkBox->isChecked();
+ return m_saveCheckBox->isChecked();
}
diff --git a/src/plugins/qt4projectmanager/qt-s60/passphraseforkeydialog.h b/src/plugins/qt4projectmanager/qt-s60/passphraseforkeydialog.h
index 90dbd7e35a..b1a7cb6cbe 100644
--- a/src/plugins/qt4projectmanager/qt-s60/passphraseforkeydialog.h
+++ b/src/plugins/qt4projectmanager/qt-s60/passphraseforkeydialog.h
@@ -36,7 +36,9 @@
#include <QtGui/QDialog>
-QT_FORWARD_DECLARE_CLASS(QCheckBox);
+QT_FORWARD_DECLARE_CLASS(QCheckBox)
+QT_FORWARD_DECLARE_CLASS(QDialogButtonBox)
+QT_FORWARD_DECLARE_CLASS(QLineEdit)
namespace Qt4ProjectManager {
@@ -50,14 +52,12 @@ public:
bool savePassphrase() const;
protected slots:
- void accept();
- void reject();
- void setPassphrase(const QString &passphrase);
+ void passphraseChanged();
private:
- QCheckBox *m_checkBox;
-
- QString m_passphrase;
+ QDialogButtonBox *m_buttonBox;
+ QCheckBox *m_saveCheckBox;
+ QLineEdit *m_passphraseEdit;
};
} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt-s60/qt-s60.pri b/src/plugins/qt4projectmanager/qt-s60/qt-s60.pri
index b31d1cc49f..ed097c0cee 100644
--- a/src/plugins/qt4projectmanager/qt-s60/qt-s60.pri
+++ b/src/plugins/qt4projectmanager/qt-s60/qt-s60.pri
@@ -18,10 +18,14 @@ SOURCES += $$PWD/s60devices.cpp \
$$PWD/winscwparser.cpp \
$$PWD/s60createpackagestep.cpp \
$$PWD/s60deploystep.cpp \
- $$PWD/signsisparser.cpp \
+ $$PWD/s60createpackageparser.cpp \
$$PWD/passphraseforkeydialog.cpp \
$$PWD/s60deployconfiguration.cpp \
- $$PWD/s60deployconfigurationwidget.cpp
+ $$PWD/s60deployconfigurationwidget.cpp \
+ $$PWD/s60certificateinfo.cpp \
+ $$PWD/certificatepathchooser.cpp \
+ $$PWD/s60symbiancertificate.cpp \
+ $$PWD/s60certificatedetailsdialog.cpp
HEADERS += $$PWD/s60devices.h \
$$PWD/s60devicespreferencepane.h \
$$PWD/s60manager.h \
@@ -39,9 +43,14 @@ HEADERS += $$PWD/s60devices.h \
$$PWD/winscwparser.h \
$$PWD/s60createpackagestep.h \
$$PWD/s60deploystep.h \
- $$PWD/signsisparser.h \
+ $$PWD/s60createpackageparser.h \
$$PWD/passphraseforkeydialog.h \
$$PWD/s60deployconfiguration.h \
- $$PWD/s60deployconfigurationwidget.h
+ $$PWD/s60deployconfigurationwidget.h \
+ $$PWD/s60certificateinfo.h \
+ $$PWD/certificatepathchooser.h \
+ $$PWD/s60symbiancertificate.h \
+ $$PWD/s60certificatedetailsdialog.h
FORMS += $$PWD/s60devicespreferencepane.ui \
- $$PWD/s60createpackagestep.ui
+ $$PWD/s60createpackagestep.ui \
+ $$PWD/s60certificatedetailsdialog.ui
diff --git a/src/plugins/qt4projectmanager/qt-s60/rvctparser.cpp b/src/plugins/qt4projectmanager/qt-s60/rvctparser.cpp
index 6a3faa00f2..5e469dd722 100644
--- a/src/plugins/qt4projectmanager/qt-s60/rvctparser.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/rvctparser.cpp
@@ -35,6 +35,8 @@
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/taskwindow.h>
+#include <QtCore/QDir>
+
using namespace ProjectExplorer;
using namespace ProjectExplorer::Constants;
using namespace Qt4ProjectManager;
@@ -84,7 +86,8 @@ void RvctParser::stdError(const QString &line)
m_task = new Task(Task::Unknown,
m_warningOrError.cap(5) /* description */,
- m_warningOrError.cap(1) /* file */, m_warningOrError.cap(2).toInt() /* line */,
+ QDir::fromNativeSeparators(m_warningOrError.cap(1)) /* file */,
+ m_warningOrError.cap(2).toInt() /* line */,
TASK_CATEGORY_COMPILE);
if (m_warningOrError.cap(4) == "Warning")
m_task->type = Task::Warning;
diff --git a/src/plugins/qt4projectmanager/qt-s60/rvcttoolchain.cpp b/src/plugins/qt4projectmanager/qt-s60/rvcttoolchain.cpp
index 79f5a70115..3bf1e361db 100644
--- a/src/plugins/qt4projectmanager/qt-s60/rvcttoolchain.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/rvcttoolchain.cpp
@@ -48,7 +48,19 @@ using namespace Qt4ProjectManager::Internal;
static const char rvctBinaryC[] = "armcc";
-RVCTToolChain::RVCTToolChain(const S60Devices::Device &device, ToolChain::ToolChainType type) :
+static inline QStringList headerPathToStringList(const QList<ProjectExplorer::HeaderPath> &hl)
+{
+ QStringList rc;
+ foreach (const ProjectExplorer::HeaderPath &hp, hl)
+ rc.push_back(hp.path());
+ return rc;
+}
+
+// ==========================================================================
+// RVCTToolChain
+// ==========================================================================
+
+RVCTToolChain::RVCTToolChain(const S60Devices::Device &device, ProjectExplorer::ToolChainType type) :
m_mixin(device),
m_type(type),
m_versionUpToDate(false),
@@ -58,41 +70,77 @@ RVCTToolChain::RVCTToolChain(const S60Devices::Device &device, ToolChain::ToolCh
{
}
-// Return the environment variable indicating the RVCT version
-// 'RVCT<major><minor>BIN'
-QByteArray RVCTToolChain::rvctBinEnvironmentVariable()
+QSet<QPair<int, int> > RVCTToolChain::configuredRvctVersions()
{
- static QByteArray binVar;
- // Grep the environment list
- if (binVar.isEmpty()) {
- const QRegExp regex(QLatin1String("^(RVCT\\d\\dBIN)=.*$"));
- QTC_ASSERT(regex.isValid(), return QByteArray());
- foreach(const QString &v, QProcessEnvironment::systemEnvironment().toStringList()) {
+ static QSet<QPair<int, int> > result;
+
+ if (result.isEmpty()) {
+ QRegExp regex(QLatin1String("^RVCT(\\d)(\\d)BIN=.*$"));
+ Q_ASSERT(regex.isValid());
+ QStringList environment = QProcessEnvironment::systemEnvironment().toStringList();
+ foreach (const QString &v, environment) {
if (regex.exactMatch(v)) {
- binVar = regex.cap(1).toLocal8Bit();
- break;
+ int major = regex.cap(1).toInt();
+ int minor = regex.cap(2).toInt();
+ result.insert(qMakePair(major, minor));
}
}
}
- return binVar;
+ return result;
+}
+
+QStringList RVCTToolChain::configuredEnvironment()
+{
+ updateVersion();
+
+ if (m_additionalEnvironment.isEmpty()) {
+ const QString binVarName = QString::fromLocal8Bit(rvctBinEnvironmentVariable());
+ const QString varName = binVarName.left(binVarName.count() - 3 /* BIN */);
+ QStringList environment = QProcessEnvironment::systemEnvironment().toStringList();
+ foreach (const QString &v, environment) {
+ if ((v.startsWith(varName) && !v.startsWith(binVarName))
+ || v.startsWith(QLatin1String("ARMLMD_LICENSE_FILE="))) {
+ m_additionalEnvironment.append(v);
+ }
+ }
+ }
+ return m_additionalEnvironment;
+}
+
+// Return the environment variable indicating the RVCT version
+// 'RVCT<major><minor>BIN'
+QByteArray RVCTToolChain::rvctBinEnvironmentVariableForVersion(int major)
+{
+ QSet<QPair<int, int> > versions = configuredRvctVersions();
+
+ for (QSet<QPair<int, int> >::const_iterator it = versions.constBegin();
+ it != versions.constEnd(); ++it) {
+ if (it->first == major) {
+ if (it->first < 0 || it->first > 9) continue;
+ if (it->second < 0 || it->second > 9) continue;
+ QByteArray result = "RVCT..BIN";
+ result[4] = '0' + it->first;
+ result[5] = '0' + it->second;
+ return result;
+ }
+ }
+ return QByteArray();
}
-// Return binary path as pointed to by RVCT<X><X>BIN
QString RVCTToolChain::rvctBinPath()
{
- static QString binPath;
- if (binPath.isEmpty()) {
+ if (m_binPath.isEmpty()) {
const QByteArray binVar = rvctBinEnvironmentVariable();
if (!binVar.isEmpty()) {
const QByteArray binPathB = qgetenv(binVar);
if (!binPathB.isEmpty()) {
const QFileInfo fi(QString::fromLocal8Bit(binPathB));
if (fi.isDir())
- binPath = fi.absoluteFilePath();
+ m_binPath = fi.absoluteFilePath();
}
}
}
- return binPath;
+ return m_binPath;
}
// Return binary expanded by path or resort to PATH
@@ -106,7 +154,7 @@ QString RVCTToolChain::rvctBinary()
return binPath.isEmpty() ? executable : (binPath + QLatin1Char('/') + executable);
}
-ToolChain::ToolChainType RVCTToolChain::type() const
+ProjectExplorer::ToolChainType RVCTToolChain::type() const
{
return m_type;
}
@@ -125,7 +173,7 @@ void RVCTToolChain::updateVersion()
addToEnvironment(env);
armcc.setEnvironment(env.toStringList());
const QString binary = rvctBinary();
- armcc.start(rvctBinary(), QStringList());
+ armcc.start(binary, QStringList());
if (!armcc.waitForStarted()) {
qWarning("Unable to run rvct binary '%s' when trying to determine version.", qPrintable(binary));
return;
@@ -147,36 +195,32 @@ void RVCTToolChain::updateVersion()
QTC_ASSERT(versionRegExp.isValid(), return);
if (versionRegExp.indexIn(versionLine) != -1) {
m_major = versionRegExp.cap(1).toInt();
- m_minor = versionRegExp.cap(2).toInt();
- m_build = versionRegExp.cap(3).toInt();
+ m_minor = versionRegExp.cap(2).toInt();
+ m_build = versionRegExp.cap(3).toInt();
}
}
QByteArray RVCTToolChain::predefinedMacros()
{
- // see http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0205f/Babbacdb.html
+ // see http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0205f/Babbacdb.html (version 2.2)
+ // and http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0491b/BABJFEFG.html (version 4.0)
updateVersion();
- QByteArray ba = QString::fromLatin1(
- "#define __arm__arm__\n"
- "#define __ARMCC_VERSION %1%2%3%4\n"
- "#define __ARRAY_OPERATORS\n"
- "#define _BOOL\n"
- "#define c_plusplus\n"
- "#define __cplusplus\n"
- "#define __CC_ARM\n"
- "#define __EDG__\n"
- "#define __STDC__\n"
- "#define __STDC_VERSION__\n"
- "#define __TARGET_FEATURE_DOUBLEWORD\n"
- "#define __TARGET_FEATURE_DSPMUL\n"
- "#define __TARGET_FEATURE_HALFWORD\n"
- "#define __TARGET_FEATURE_THUMB\n"
- "#define _WCHAR_T\n"
- "#define __SYMBIAN32__\n"
- ).arg(m_major, 1, 10, QLatin1Char('0'))
- .arg(m_minor, 1, 10, QLatin1Char('0'))
- .arg("0")
- .arg(m_build, 3, 10, QLatin1Char('0')).toLatin1();
+ QByteArray ba("#define __ARRAY_OPERATORS\n"
+ "#define _BOOL\n"
+ "#define __cplusplus\n"
+ "#define __CC_ARM 1\n"
+ "#define __EDG__\n"
+ "#define __STDC__\n"
+ "#define __STDC_VERSION__\n"
+ "#define __sizeof_int 4"
+ "#define __sizeof_long 4"
+ "#define __sizeof_ptr 4"
+ "#define __TARGET_FEATURE_DOUBLEWORD\n"
+ "#define __TARGET_FEATURE_DSPMUL\n"
+ "#define __TARGET_FEATURE_HALFWORD\n"
+ "#define __TARGET_FEATURE_THUMB\n"
+ "#define _WCHAR_T\n"
+ "#define __SYMBIAN32__\n");
return ba;
}
@@ -184,12 +228,11 @@ QList<HeaderPath> RVCTToolChain::systemHeaderPaths()
{
if (m_systemHeaderPaths.isEmpty()) {
updateVersion();
- Utils::Environment env = Utils::Environment::systemEnvironment();
- QString rvctInclude = env.value(QString::fromLatin1("RVCT%1%2INC").arg(m_major).arg(m_minor));
+ QString rvctInclude = qgetenv(QString::fromLatin1("RVCT%1%2INC").arg(m_major).arg(m_minor).toLatin1());
if (!rvctInclude.isEmpty())
m_systemHeaderPaths.append(HeaderPath(rvctInclude, HeaderPath::GlobalHeaderPath));
switch (m_type) {
- case ProjectExplorer::ToolChain::RVCT_ARMV5_GNUPOC:
+ case ProjectExplorer::ToolChain_RVCT_ARMV5_GNUPOC:
m_systemHeaderPaths += m_mixin.gnuPocRvctHeaderPaths(m_major, m_minor);
break;
default:
@@ -200,17 +243,9 @@ QList<HeaderPath> RVCTToolChain::systemHeaderPaths()
return m_systemHeaderPaths;
}
-static inline QStringList headerPathToStringList(const QList<ProjectExplorer::HeaderPath> &hl)
-{
- QStringList rc;
- foreach(const ProjectExplorer::HeaderPath &hp, hl)
- rc.push_back(hp.path());
- return rc;
-}
-
// Expand an RVCT variable, such as RVCT22BIN, by some new values
void RVCTToolChain::addToRVCTPathVariable(const QString &postfix, const QStringList &values,
- Utils::Environment &env) const
+ Utils::Environment &env) const
{
// get old values
const QChar separator = QLatin1Char(',');
@@ -244,8 +279,19 @@ QStringList RVCTToolChain::libPaths()
void RVCTToolChain::addToEnvironment(Utils::Environment &env)
{
updateVersion();
+
+ // Push additional configuration variables for the compiler through:
+ QStringList additionalVariables = configuredEnvironment();
+ foreach (const QString &var, additionalVariables) {
+ int pos = var.indexOf(QLatin1Char('='));
+ Q_ASSERT(pos >= 0);
+ const QString key = var.left(pos);
+ const QString value = var.mid(pos + 1);
+ env.set(key, value);
+ }
+
switch (m_type) {
- case ProjectExplorer::ToolChain::RVCT_ARMV5_GNUPOC: {
+ case ProjectExplorer::ToolChain_RVCT_ARMV5_GNUPOC: {
m_mixin.addGnuPocToEnvironment(&env);
// setup RVCT22INC, LIB
addToRVCTPathVariable(QLatin1String("INC"),
@@ -254,24 +300,31 @@ void RVCTToolChain::addToEnvironment(Utils::Environment &env)
addToRVCTPathVariable(QLatin1String("LIB"),
libPaths() + m_mixin.gnuPocRvctLibPaths(5, true),
env);
- // Add rvct to path and set locale to 'C'
- const QString binPath = rvctBinPath();
- if (!binPath.isEmpty())
- env.prependOrSetPath(binPath);
- env.set(QLatin1String("LANG"), QString(QLatin1Char('C')));
- }
+ }
break;
default:
m_mixin.addEpocToEnvironment(&env);
break;
}
- // we currently support RVCT v2.2 only:
- env.set(QLatin1String("QT_RVCT_VERSION"), QLatin1String("2.2"));
+
+ const QString binPath = rvctBinPath();
+ env.set(rvctBinEnvironmentVariable(), QDir::toNativeSeparators(binPath));
+
+ // Add rvct to path and set locale to 'C'
+ if (!binPath.isEmpty())
+ env.prependOrSetPath(binPath);
+ env.set(QLatin1String("LANG"), QString(QLatin1Char('C')));
+
+ env.set(QLatin1String("QT_RVCT_VERSION"), QString::fromLatin1("%1.%2").arg(m_major).arg(m_minor));
}
QString RVCTToolChain::makeCommand() const
{
+#if defined(Q_OS_WIN)
+ return QLatin1String("make.exe");
+#else
return QLatin1String("make");
+#endif
}
ProjectExplorer::IOutputParser *RVCTToolChain::outputParser() const
@@ -279,11 +332,71 @@ ProjectExplorer::IOutputParser *RVCTToolChain::outputParser() const
return new RvctParser;
}
-bool RVCTToolChain::equals(const ToolChain *otherIn) const
+// ==========================================================================
+// RVCT2ToolChain
+// ==========================================================================
+
+RVCT2ToolChain::RVCT2ToolChain(const S60Devices::Device &device, ProjectExplorer::ToolChainType type) :
+ RVCTToolChain(device, type)
+{ }
+
+QByteArray RVCT2ToolChain::rvctBinEnvironmentVariable()
+{
+ return rvctBinEnvironmentVariableForVersion(2);
+}
+
+QByteArray RVCT2ToolChain::predefinedMacros()
+{
+ QByteArray result = RVCTToolChain::predefinedMacros();
+ result.append(QString::fromLatin1("#define __arm__arm__\n"
+ "#define __ARMCC_VERSION %1%2%3%4\n"
+ "#define c_plusplus\n"
+ )
+ .arg(m_major, 1, 10, QLatin1Char('0'))
+ .arg(m_minor, 1, 10, QLatin1Char('0'))
+ .arg("0")
+ .arg(m_build, 3, 10, QLatin1Char('0')).toLatin1());
+ return result;
+}
+
+bool RVCT2ToolChain::equals(const ToolChain *otherIn) const
{
if (otherIn->type() != type())
return false;
- const RVCTToolChain *other = static_cast<const RVCTToolChain *>(otherIn);
+ const RVCT2ToolChain *other = static_cast<const RVCT2ToolChain *>(otherIn);
return other->m_mixin == m_mixin;
}
+// ==========================================================================
+// RVCT4ToolChain
+// ==========================================================================
+
+RVCT4ToolChain::RVCT4ToolChain(const S60Devices::Device &device,
+ ProjectExplorer::ToolChainType type) :
+ RVCT2ToolChain(device, type)
+{ }
+
+QByteArray RVCT4ToolChain::rvctBinEnvironmentVariable()
+{
+ return rvctBinEnvironmentVariableForVersion(4);
+}
+
+QByteArray RVCT4ToolChain::predefinedMacros()
+{
+ QByteArray result = RVCTToolChain::predefinedMacros();
+ result.append(QString::fromLatin1("#define __arm__\n"
+ "#define __ARMCC_VERSION %1%2%3\n")
+ .arg(m_major, 1, 10, QLatin1Char('0'))
+ .arg(m_minor, 1, 10, QLatin1Char('0'))
+ .arg(m_build, 3, 10, QLatin1Char('0')).toLatin1());
+ return result;
+}
+
+
+bool RVCT4ToolChain::equals(const ToolChain *otherIn) const
+{
+ if (otherIn->type() != type())
+ return false;
+ const RVCT4ToolChain *other = static_cast<const RVCT4ToolChain *>(otherIn);
+ return other->m_mixin == m_mixin;
+}
diff --git a/src/plugins/qt4projectmanager/qt-s60/rvcttoolchain.h b/src/plugins/qt4projectmanager/qt-s60/rvcttoolchain.h
index 0638821b7d..14020acf90 100644
--- a/src/plugins/qt4projectmanager/qt-s60/rvcttoolchain.h
+++ b/src/plugins/qt4projectmanager/qt-s60/rvcttoolchain.h
@@ -41,42 +41,90 @@
namespace Qt4ProjectManager {
namespace Internal {
+// ==========================================================================
+// RVCTToolChain
+// ==========================================================================
+
class RVCTToolChain : public ProjectExplorer::ToolChain
{
public:
explicit RVCTToolChain(const S60Devices::Device &device,
- ProjectExplorer::ToolChain::ToolChainType type);
- virtual QByteArray predefinedMacros();
+ ProjectExplorer::ToolChainType type);
+ QByteArray predefinedMacros();
QList<ProjectExplorer::HeaderPath> systemHeaderPaths();
void addToEnvironment(Utils::Environment &env);
- ProjectExplorer::ToolChain::ToolChainType type() const;
+ ProjectExplorer::ToolChainType type() const;
QString makeCommand() const;
ProjectExplorer::IOutputParser *outputParser() const;
+ static QSet<QPair<int, int> > configuredRvctVersions();
+
// Return the environment variable indicating the RVCT version
- // 'RVCT<major><minor>BIN' and its setting
- static QByteArray rvctBinEnvironmentVariable();
- static QString rvctBinPath();
- static QString rvctBinary();
+ // 'RVCT2<minor>BIN' and its setting
+ virtual QByteArray rvctBinEnvironmentVariable() = 0;
+
+ QString rvctBinPath();
+ QString rvctBinary();
protected:
- bool equals(const ToolChain *other) const;
+ bool equals(const ToolChain *other) const = 0;
-private:
+ QStringList configuredEnvironment();
+
+ QByteArray rvctBinEnvironmentVariableForVersion(int major);
void addToRVCTPathVariable(const QString &postfix, const QStringList &values,
Utils::Environment &env) const;
- static QStringList libPaths();
+ QStringList libPaths();
void updateVersion();
+ QByteArray m_predefinedMacros;
+ QList<ProjectExplorer::HeaderPath> m_systemHeaderPaths;
+
const S60ToolChainMixin m_mixin;
- const ProjectExplorer::ToolChain::ToolChainType m_type;
+ const ProjectExplorer::ToolChainType m_type;
bool m_versionUpToDate;
int m_major;
int m_minor;
int m_build;
- QByteArray m_predefinedMacros;
- QList<ProjectExplorer::HeaderPath> m_systemHeaderPaths;
+private:
+ QString m_binPath;
+ QStringList m_additionalEnvironment;
+};
+
+// ==========================================================================
+// RVCT2ToolChain
+// ==========================================================================
+
+class RVCT2ToolChain : public RVCTToolChain
+{
+public:
+ explicit RVCT2ToolChain(const S60Devices::Device &device,
+ ProjectExplorer::ToolChainType type);
+ QByteArray rvctBinEnvironmentVariable();
+
+ QByteArray predefinedMacros();
+
+protected:
+ bool equals(const ToolChain *other) const;
+};
+
+// ==========================================================================
+// RVCT4ToolChain
+// ==========================================================================
+
+class RVCT4ToolChain : public RVCT2ToolChain
+{
+public:
+ explicit RVCT4ToolChain(const S60Devices::Device &device,
+ ProjectExplorer::ToolChainType type);
+
+ QByteArray rvctBinEnvironmentVariable();
+
+ QByteArray predefinedMacros();
+
+protected:
+ bool equals(const ToolChain *other) const;
};
} // namespace Internal
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60certificatedetailsdialog.cpp b/src/plugins/qt4projectmanager/qt-s60/s60certificatedetailsdialog.cpp
new file mode 100644
index 0000000000..6844b5aa96
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-s60/s60certificatedetailsdialog.cpp
@@ -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.
+**
+**************************************************************************/
+
+#include "s60certificatedetailsdialog.h"
+#include "ui_s60certificatedetailsdialog.h"
+
+using namespace Qt4ProjectManager;
+using namespace Qt4ProjectManager::Internal;
+
+struct S60CertificateDetailsDialogPrivate
+{
+ S60CertificateDetailsDialogPrivate(){};
+ Ui::S60CertificateDetailsDialog m_ui;
+};
+
+S60CertificateDetailsDialog::S60CertificateDetailsDialog(QWidget *parent) :
+ QDialog(parent),
+ m_d(new S60CertificateDetailsDialogPrivate)
+{
+ m_d->m_ui.setupUi(this);
+ connect(m_d->m_ui.buttonBox, SIGNAL(clicked(QAbstractButton*)), this, SLOT(close()));
+}
+
+S60CertificateDetailsDialog::~S60CertificateDetailsDialog()
+{
+ delete m_d;
+}
+
+void S60CertificateDetailsDialog::setText(const QString &text)
+{
+ m_d->m_ui.textBrowser->setText(text);
+}
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60certificatedetailsdialog.h b/src/plugins/qt4projectmanager/qt-s60/s60certificatedetailsdialog.h
new file mode 100644
index 0000000000..f7b3121923
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-s60/s60certificatedetailsdialog.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 S60CERTIFICATEDETAILSDIALOG_H
+#define S60CERTIFICATEDETAILSDIALOG_H
+
+#include <QDialog>
+
+struct S60CertificateDetailsDialogPrivate;
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+class S60CertificateDetailsDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit S60CertificateDetailsDialog(QWidget *parent = 0);
+ ~S60CertificateDetailsDialog();
+
+ void setText(const QString &text);
+
+private:
+ S60CertificateDetailsDialogPrivate *m_d;
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // S60CERTIFICATEDETAILSDIALOG_H
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60certificatedetailsdialog.ui b/src/plugins/qt4projectmanager/qt-s60/s60certificatedetailsdialog.ui
new file mode 100644
index 0000000000..fbe2c75958
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-s60/s60certificatedetailsdialog.ui
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>S60CertificateDetailsDialog</class>
+ <widget class="QDialog" name="S60CertificateDetailsDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Certificate's details</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QTextBrowser" name="textBrowser"/>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Close</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60certificateinfo.cpp b/src/plugins/qt4projectmanager/qt-s60/s60certificateinfo.cpp
new file mode 100644
index 0000000000..f6462bdcee
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-s60/s60certificateinfo.cpp
@@ -0,0 +1,231 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "s60certificateinfo.h"
+
+#include <QDateTime>
+#include <QFileInfo>
+#include <QCoreApplication>
+#include <QTextStream>
+
+#include "s60symbiancertificate.h"
+
+using namespace Qt4ProjectManager;
+using namespace Qt4ProjectManager::Internal;
+
+namespace {
+ const char * const SIMPLE_DATE_FORMAT = "dd.MM.yyyy";
+}
+
+struct Capability {
+ const char *name;
+ const int value;
+};
+
+static const Capability capability[] =
+{
+ { "LocalServices", S60CertificateInfo::LocalServices },
+ { "Location", S60CertificateInfo::Location },
+ { "NetworkServices", S60CertificateInfo::NetworkServices },
+ { "ReadUserData", S60CertificateInfo::ReadUserData },
+ { "UserEnvironment", S60CertificateInfo::UserEnvironment },
+ { "WriteUserData", S60CertificateInfo::WriteUserData },
+ { "PowerMgmt", S60CertificateInfo::PowerMgmt },
+ { "ProtServ", S60CertificateInfo::ProtServ },
+ { "ReadDeviceData", S60CertificateInfo::ReadDeviceData },
+ { "SurroundingsDD", S60CertificateInfo::SurroundingsDD },
+ { "SwEvent", S60CertificateInfo::SwEvent },
+ { "TrustedUI", S60CertificateInfo::TrustedUI },
+ { "WriteDeviceData", S60CertificateInfo::WriteDeviceData },
+ { "CommDD", S60CertificateInfo::CommDD },
+ { "DiskAdmin", S60CertificateInfo::DiskAdmin },
+ { "NetworkControl", S60CertificateInfo::NetworkControl },
+ { "MultimediaDD", S60CertificateInfo::MultimediaDD },
+ { "AllFiles", S60CertificateInfo::AllFiles },
+ { "DRM", S60CertificateInfo::DRM },
+ { "TCB", S60CertificateInfo::TCB }
+};
+
+QStringList createCapabilityList(uint capabilities)
+{
+ const int capabilityCount = sizeof(capability)/sizeof(capability[0]);
+ QStringList capabilityList;
+ for(int i = 0; i < capabilityCount; ++i)
+ if (capabilities&capability[i].value)
+ capabilityList << QLatin1String(capability[i].name);
+ return capabilityList;
+}
+
+S60CertificateInfo::S60CertificateInfo(const QString &filePath, QObject* parent)
+ : QObject(parent),
+ m_certificate(new S60SymbianCertificate(filePath)),
+ m_filePath(filePath),
+ m_capabilities(NoInformation)
+{
+ if (!m_certificate->isValid())
+ return;
+
+ m_imeiList = m_certificate->subjectInfo(QLatin1String("1.2.826.0.1.1796587.1.1.1.1"));
+
+ const QStringList capabilityList(m_certificate->subjectInfo(QLatin1String("1.2.826.0.1.1796587.1.1.1.6")));
+ if (capabilityList.isEmpty())
+ m_capabilities = 0;
+ else
+ m_capabilities = capabilityList.at(0).toLong();
+}
+
+S60CertificateInfo::~S60CertificateInfo()
+{
+ delete m_certificate;
+}
+
+S60CertificateInfo::CertificateState S60CertificateInfo::validateCertificate()
+{
+ CertificateState result = CertificateValid;
+ if (m_certificate->isValid()) {
+ QDateTime currentTime(QDateTime::currentDateTimeUtc());
+ QDateTime endTime(m_certificate->endTime());
+ QDateTime startTime(m_certificate->startTime());
+ if (currentTime > endTime) {
+ m_errorString = tr("The \"%1\" certificate has already expired and cannot be used."
+ "\nExpiration date: %2.")
+ .arg(QFileInfo(m_filePath).fileName())
+ .arg(endTime.toLocalTime().toString(QLatin1String(SIMPLE_DATE_FORMAT)));
+ result = CertificateError;
+ } else if (currentTime < startTime) {
+ m_errorString = tr("The \"%1\" certificate is not yet valid.\nValid from: %2.")
+ .arg(QFileInfo(m_filePath).fileName())
+ .arg(startTime.toLocalTime().toString(QLatin1String(SIMPLE_DATE_FORMAT)));
+ result = CertificateWarning; //This certificate may be valid in the near future
+ }
+ } else {
+ m_errorString = tr("The \"%1\" certificate is not a valid X.509 certificate.")
+ .arg(QFileInfo(m_filePath).baseName());
+ result = CertificateError;
+ }
+ return result;
+}
+
+bool S60CertificateInfo::compareCapabilities(const QStringList &givenCaps, QStringList &unsupportedCaps) const
+{
+ if (!m_certificate->isValid())
+ return false;
+ unsupportedCaps.clear();
+ if (capabilitiesSupported() == NoInformation)
+ return true;
+
+ QStringList capabilities(createCapabilityList(capabilitiesSupported()));
+ foreach (QString capability, givenCaps) {
+ if (!capabilities.contains(capability, Qt::CaseInsensitive))
+ unsupportedCaps << capability;
+ }
+ return true;
+}
+
+QString S60CertificateInfo::errorString() const
+{
+ return m_errorString.isEmpty()?m_certificate->errorString():m_errorString;
+}
+
+QStringList S60CertificateInfo::devicesSupported() const
+{
+ return m_imeiList;
+}
+
+quint32 S60CertificateInfo::capabilitiesSupported() const
+{
+ return m_capabilities;
+}
+
+bool S60CertificateInfo::isDeveloperCertificate() const
+{
+ return !devicesSupported().isEmpty() || capabilitiesSupported();
+}
+
+QString S60CertificateInfo::toHtml(bool keepShort)
+{
+ if (!m_certificate->isValid())
+ return errorString();
+
+ QString htmlString;
+ QTextStream str(&htmlString);
+ str << "<html><body><table>"
+ << "<tr><td><b>" << tr("Type: ") << "</b></td>";
+
+ if (isDeveloperCertificate())
+ str << "<td>" << tr("Developer certificate") << "</td>";
+ if (m_certificate->isSelfSigned())
+ str << "<td>" << tr("Self signed certificate") << "</td>";
+ str << "</tr>";
+
+ QString issuer;
+ QStringList issuerOrganizationList(m_certificate->issuerInfo("X520.Organization"));
+ if (!issuerOrganizationList.isEmpty())
+ issuer = issuerOrganizationList.join(QString(" "));
+
+ QString subject;
+ QStringList subjectOrganizationList(m_certificate->subjectInfo("X520.Organization"));
+ if (!subjectOrganizationList.isEmpty())
+ subject = subjectOrganizationList.join(QString(" "));
+
+ QDateTime startDate(m_certificate->startTime().toLocalTime());
+ QDateTime endDate(m_certificate->endTime().toLocalTime());
+
+ str << "<tr><td><b>" << tr("Issued by: ")
+ << "</b></td><td>" << issuer << "</td></tr>"
+ << "<tr><td><b>" << tr("Issued to: ")
+ << "</b></td><td>" << subject << "</td></tr>"
+ << "<tr><td><b>" << tr("Valid from: ")
+ << "</b></td><td>" << startDate.toString(QLatin1String(SIMPLE_DATE_FORMAT)) << "</td></tr>"
+ << "<tr><td><b>" << tr("Valid to: ")
+ << "</b></td><td>" << endDate.toString(QLatin1String(SIMPLE_DATE_FORMAT)) << "</td></tr>";
+
+ if (capabilitiesSupported()) {
+ QStringList capabilities(createCapabilityList(capabilitiesSupported()));
+ capabilities.sort();
+ str << "<tr><td><b>" << tr("Capabilities: ")
+ << "</b></td><td><i>" << capabilities.join(" ") << "</i></td></tr>";
+ }
+
+ const QStringList &imeiList(devicesSupported());
+ if (!imeiList.isEmpty()) {
+ QString imeiListString;
+ QString space(" ");
+ int MAX_DISPLAYED_IMEI_COUNT = 30;
+ if (imeiList.count() > MAX_DISPLAYED_IMEI_COUNT && keepShort) {//1000 items would be too much :)
+ for (int i = 0; i < MAX_DISPLAYED_IMEI_COUNT; ++i)
+ imeiListString += imeiList.at(i) + space;
+ imeiListString.replace(imeiListString.length()-1, 1, QString("..."));
+ } else
+ imeiListString = imeiList.join(space);
+ str << "<tr><td><b>" << tr("Supporting %n device(s): ", "", imeiList.count())
+ << "</b></td><td>" << imeiListString << "</td></tr>";
+ }
+ return htmlString;
+}
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60certificateinfo.h b/src/plugins/qt4projectmanager/qt-s60/s60certificateinfo.h
new file mode 100644
index 0000000000..609a280437
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-s60/s60certificateinfo.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 S60CERTIFICATEINFO_H
+#define S60CERTIFICATEINFO_H
+
+#include <QtCore/QObject>
+#include <QtCore/QStringList>
+#include <QtCore/QtGlobal>
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+class S60SymbianCertificate;
+
+class S60CertificateInfo : public QObject
+{
+ Q_OBJECT
+
+public:
+ enum CertificateState {
+ CertificateValid,
+ CertificateWarning,
+ CertificateError
+ };
+
+ enum S60Capability {
+ TCB = 1 << (31-0),
+ CommDD = 1 << (31-1),
+ PowerMgmt = 1 << (31-2),
+ MultimediaDD = 1 << (31-3),
+ ReadDeviceData = 1 << (31-4),
+ WriteDeviceData = 1 << (31-5),
+ DRM = 1 << (31-6),
+ TrustedUI = 1 << (31-7),
+ ProtServ = 1 << (31-8),
+ DiskAdmin = 1 << (31-9),
+ NetworkControl = 1 << (31-10),
+ AllFiles = 1 << (31-11),
+ SwEvent = 1 << (31-12),
+ NetworkServices = 1 << (31-13),
+ LocalServices = 1 << (31-14),
+ ReadUserData = 1 << (31-15),
+ WriteUserData = 1 << (31-16),
+ Location = 1 << (31-17),
+ SurroundingsDD = 1 << (31-18),
+ UserEnvironment = 1 << (31-19),
+
+ NoInformation = 0
+ };
+
+ explicit S60CertificateInfo(const QString &filePath, QObject* parent = 0);
+ ~S60CertificateInfo();
+
+ CertificateState validateCertificate();
+ QStringList devicesSupported() const;
+ quint32 capabilitiesSupported() const;
+ QString toHtml(bool keepShort = true);
+ QString errorString() const;
+ bool isDeveloperCertificate() const;
+
+ bool compareCapabilities(const QStringList &givenCaps, QStringList &unsupportedCaps) const;
+
+private:
+ S60SymbianCertificate *m_certificate;
+ QString m_filePath;
+ QString m_errorString;
+ QStringList m_imeiList;
+ quint32 m_capabilities;
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectExplorer
+
+#endif // S60CERTIFICATEINFO_H
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60createpackageparser.cpp b/src/plugins/qt4projectmanager/qt-s60/s60createpackageparser.cpp
new file mode 100644
index 0000000000..79cc48244c
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-s60/s60createpackageparser.cpp
@@ -0,0 +1,130 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "s60createpackageparser.h"
+
+#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/taskwindow.h>
+
+
+#include <QDebug>
+
+using namespace Qt4ProjectManager::Internal;
+
+S60CreatePackageParser::S60CreatePackageParser(const QString &packageName) :
+ m_packageName(packageName),
+ m_needPassphrase(false)
+{
+ setObjectName(QLatin1String("S60CreatePackageParser"));
+ m_signSis.setPattern("^\\s*(error\\s?:\\s?)+(.+)$");
+ m_signSis.setMinimal(true);
+ m_signSis.setCaseSensitivity(Qt::CaseInsensitive);
+}
+
+bool S60CreatePackageParser::parseLine(const QString &line)
+{
+ if (line.startsWith("Patching: ")) {
+ m_patchingLines.append(line.mid(10).trimmed());
+ return true;
+ }
+ if (!m_patchingLines.isEmpty()) {
+ emit packageWasPatched(m_packageName, m_patchingLines);
+
+ QString lines = m_patchingLines.join("\n");
+ m_patchingLines.clear();
+ //: %1 package name, %2 will be replaced by a list of patching lines.
+ QString message = tr("The binary package '%1' was patched to be installable after being self-signed!\n%2\n"
+ "Use a developer certificate or any other signing option to prevent "
+ "this patching from happening.").
+ arg(m_packageName, lines);
+ ProjectExplorer::Task task(ProjectExplorer::Task::Warning, message, QString(), -1,
+ ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM);
+
+ QTextLayout::FormatRange fr;
+ fr.start = message.indexOf(lines);
+ fr.length = lines.length();
+ fr.format.setFontItalic(true);
+ task.formats.append(fr);
+
+ emit addTask(task);
+ }
+
+ if (m_signSis.indexIn(line) > -1) {
+ QString errorMessage(m_signSis.cap(2));
+ if (errorMessage.contains(QLatin1String("bad password"))
+ || errorMessage.contains(QLatin1String("bad decrypt")))
+ m_needPassphrase = true;
+ else if (errorMessage.contains(QLatin1String("Cannot open file"))
+ && errorMessage.contains(QLatin1String("smartinstaller")))
+ emit addTask(ProjectExplorer::Task(ProjectExplorer::Task::Error,
+ tr("Cannot create Smart Installer package "
+ "as the Smart Installer's base file is missing. "
+ "Please ensure that it is located in the SDK."),
+ QString(), -1,
+ ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
+ else
+ emit addTask(ProjectExplorer::Task(ProjectExplorer::Task::Error, errorMessage, QString(), -1,
+ ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
+ return true;
+ }
+ return false;
+}
+
+void S60CreatePackageParser::stdOutput(const QString &line)
+{
+ if (!parseLine(line))
+ IOutputParser::stdOutput(line);
+}
+
+void S60CreatePackageParser::stdError(const QString &line)
+{
+ if (!parseLine(line))
+ IOutputParser::stdError(line);
+}
+
+bool S60CreatePackageParser::needPassphrase() const
+{
+ return m_needPassphrase;
+}
+
+/* STDOUT:
+make[1]: Entering directory `C:/temp/test/untitled131'
+createpackage.bat -g untitled131_template.pkg RELEASE-armv5
+Auto-patching capabilities for self signed package.
+
+Patching package file and relevant binaries...
+Patching: Removed dependency to qt.sis (0x2001E61C) to avoid installation issues in case qt.sis is also patched.
+
+
+NOTE: A patched package may not work as expected due to reduced capabilities and other modifications,
+ so it should not be used for any kind of Symbian signing or distribution!
+ Use a proper certificate to avoid the need to patch the package.
+
+Processing untitled131_release-armv5.pkg...
+*/
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60createpackageparser.h b/src/plugins/qt4projectmanager/qt-s60/s60createpackageparser.h
new file mode 100644
index 0000000000..a4ac55265a
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-s60/s60createpackageparser.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 SIGNSISPARSER_H
+#define SIGNSISPARSER_H
+
+#include <projectexplorer/ioutputparser.h>
+
+#include <QtCore/QRegExp>
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+class S60CreatePackageParser : public ProjectExplorer::IOutputParser
+{
+ Q_OBJECT
+
+public:
+ S60CreatePackageParser(const QString &packageName);
+
+ virtual void stdOutput(const QString &line);
+ virtual void stdError(const QString &line);
+
+ bool needPassphrase() const;
+
+signals:
+ void packageWasPatched(const QString &, const QStringList &pachingLines);
+
+private:
+ bool parseLine(const QString &line);
+
+ const QString m_packageName;
+
+ QRegExp m_signSis;
+ QStringList m_patchingLines;
+
+ bool m_needPassphrase;
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectExplorer
+
+
+#endif // SIGNSISPARSER_H
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.cpp b/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.cpp
index b8f4b0a2b8..eea53b4c58 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.cpp
@@ -37,10 +37,16 @@
#include "qt4buildconfiguration.h"
#include "qt4nodes.h"
#include "qt4project.h"
+#include "s60createpackageparser.h"
#include "abldparser.h"
#include "sbsv2parser.h"
-#include "signsisparser.h"
#include "passphraseforkeydialog.h"
+#include "s60certificateinfo.h"
+#include "s60certificatedetailsdialog.h"
+
+#include <coreplugin/coreconstants.h>
+
+#include <utils/checkablemessagebox.h>
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/buildsteplist.h>
@@ -57,6 +63,7 @@
#include <QSettings>
#include <QMessageBox>
+using namespace Qt4ProjectManager;
using namespace Qt4ProjectManager::Internal;
namespace {
@@ -65,6 +72,8 @@ namespace {
const char * const CERTIFICATE_KEY("Qt4ProjectManager.S60CreatePackageStep.Certificate");
const char * const KEYFILE_KEY("Qt4ProjectManager.S60CreatePackageStep.Keyfile");
const char * const SMART_INSTALLER_KEY("Qt4ProjectManager.S60CreatorPackageStep.SmartInstaller");
+ const char * const PATCH_WARNING_SHOWN_KEY("Qt4ProjectManager.S60CreatorPackageStep.PatchWarningShown");
+ const char * const SUPPRESS_PATCH_WARNING_DIALOG_KEY("Qt4ProjectManager.S60CreatorPackageStep.SuppressPatchWarningDialog");
const char * const MAKE_PASSPHRASE_ARGUMENT("QT_SIS_PASSPHRASE=");
const char * const MAKE_KEY_ARGUMENT("QT_SIS_KEY=");
@@ -80,8 +89,10 @@ S60CreatePackageStep::S60CreatePackageStep(ProjectExplorer::BuildStepList *bsl)
m_timer(0),
m_eventLoop(0),
m_futureInterface(0),
- m_errorType(ErrorNone),
- m_settings(0)
+ m_passphrases(0),
+ m_parser(0),
+ m_suppressPatchWarningDialog(false),
+ m_patchWarningDialog(0)
{
ctor_package();
}
@@ -97,8 +108,10 @@ S60CreatePackageStep::S60CreatePackageStep(ProjectExplorer::BuildStepList *bsl,
m_timer(0),
m_eventLoop(0),
m_futureInterface(0),
- m_errorType(ErrorNone),
- m_settings(0)
+ m_passphrases(0),
+ m_parser(0),
+ m_suppressPatchWarningDialog(false),
+ m_patchWarningDialog(0)
{
ctor_package();
}
@@ -111,8 +124,10 @@ S60CreatePackageStep::S60CreatePackageStep(ProjectExplorer::BuildStepList *bsl,
m_timer(0),
m_eventLoop(0),
m_futureInterface(0),
- m_errorType(ErrorNone),
- m_settings(0)
+ m_passphrases(0),
+ m_parser(0),
+ m_suppressPatchWarningDialog(false),
+ m_patchWarningDialog(0)
{
ctor_package();
}
@@ -123,22 +138,26 @@ void S60CreatePackageStep::ctor_package()
setDefaultDisplayName(tr("Create SIS Package"));
connect(this, SIGNAL(badPassphrase()),
this, SLOT(definePassphrase()), Qt::QueuedConnection);
+ connect(this, SIGNAL(warnAboutPatching()),
+ this, SLOT(handleWarnAboutPatching()), Qt::QueuedConnection);
- m_settings = new QSettings(QSettings::IniFormat, QSettings::UserScope,
+ m_passphrases = new QSettings(QSettings::IniFormat, QSettings::UserScope,
QLatin1String("Nokia"), QLatin1String("QtCreatorKeys"), this);
}
S60CreatePackageStep::~S60CreatePackageStep()
{
+ delete m_patchWarningDialog;
}
QVariantMap S60CreatePackageStep::toMap() const
{
QVariantMap map(BuildStep::toMap());
- map.insert(QLatin1String(SIGNMODE_KEY), (int)m_signingMode);
+ map.insert(QLatin1String(SIGNMODE_KEY), static_cast<int>(m_signingMode));
map.insert(QLatin1String(CERTIFICATE_KEY), m_customSignaturePath);
map.insert(QLatin1String(KEYFILE_KEY), m_customKeyPath);
map.insert(QLatin1String(SMART_INSTALLER_KEY), m_createSmartInstaller);
+ map.insert(QLatin1String(SUPPRESS_PATCH_WARNING_DIALOG_KEY), m_suppressPatchWarningDialog);
return map;
}
@@ -148,6 +167,8 @@ bool S60CreatePackageStep::fromMap(const QVariantMap &map)
m_customSignaturePath = map.value(QLatin1String(CERTIFICATE_KEY)).toString();
setCustomKeyPath(map.value(QLatin1String(KEYFILE_KEY)).toString());
m_createSmartInstaller = map.value(QLatin1String(SMART_INSTALLER_KEY), false).toBool();
+ m_suppressPatchWarningDialog = map.value(QLatin1String(SUPPRESS_PATCH_WARNING_DIALOG_KEY),
+ false).toBool();
return BuildStep::fromMap(map);
}
@@ -163,8 +184,12 @@ bool S60CreatePackageStep::init()
QList<Qt4ProFileNode *> nodes = pro->leafProFiles();
m_workingDirectories.clear();
- foreach (Qt4ProFileNode *node, nodes)
+ QStringList projectCapabilities;
+ foreach (Qt4ProFileNode *node, nodes) {
+ projectCapabilities += node->symbianCapabilities();
m_workingDirectories << node->buildDir();
+ }
+ projectCapabilities.removeDuplicates();
m_makeCmd = qt4BuildConfiguration()->makeCommand();
if (!QFileInfo(m_makeCmd).isAbsolute()) {
@@ -177,77 +202,101 @@ bool S60CreatePackageStep::init()
m_makeCmd = tmp;
}
- m_environment = qt4BuildConfiguration()->environment();
-
- m_args.clear();
- if (m_createSmartInstaller) {
- if(signingMode() == NotSigned)
- m_args << QLatin1String("unsigned_installer_sis");
- else
- m_args << QLatin1String("installer_sis");
- } else if (signingMode() == NotSigned)
- m_args << QLatin1String("unsigned_sis");
- else
- m_args << QLatin1String("sis");
-
- if (signingMode() == SignCustom) {
- m_args << QLatin1String(MAKE_CERTIFICATE_ARGUMENT) + QDir::toNativeSeparators(customSignaturePath())
- << QLatin1String(MAKE_KEY_ARGUMENT) + QDir::toNativeSeparators(customKeyPath());
-
- setPassphrase(loadPassphraseForKey(m_keyId));
-
- if (!passphrase().isEmpty()) {
- m_args << QLatin1String(MAKE_PASSPHRASE_ARGUMENT) + passphrase();
- }
- }
+ if (signingMode() == SignCustom && !validateCustomSigningResources(projectCapabilities))
+ return false;
- delete m_outputParserChain;
- if (qt4BuildConfiguration()->qtVersion()->isBuildWithSymbianSbsV2())
- m_outputParserChain = new Qt4ProjectManager::SbsV2Parser;
- else
- m_outputParserChain = new Qt4ProjectManager::AbldParser;
- m_outputParserChain->appendOutputParser(new ProjectExplorer::GnuMakeParser);
- m_outputParserChain->appendOutputParser(new Qt4ProjectManager::SignsisParser);
+ m_environment = qt4BuildConfiguration()->environment();
- connect(m_outputParserChain, SIGNAL(addOutput(QString, ProjectExplorer::BuildStep::OutputFormat)),
- this, SLOT(outputAdded(QString, ProjectExplorer::BuildStep::OutputFormat)));
- connect(m_outputParserChain, SIGNAL(addTask(ProjectExplorer::Task)),
- this, SLOT(taskAdded(ProjectExplorer::Task)), Qt::DirectConnection);
+ m_cancel = false;
return true;
}
void S60CreatePackageStep::definePassphrase()
{
+ Q_ASSERT(!m_cancel);
PassphraseForKeyDialog *passwordDialog
= new PassphraseForKeyDialog(QFileInfo(customKeyPath()).fileName());
if (passwordDialog->exec()) {
- setPassphrase(passwordDialog->passphrase());
+ QString newPassphrase = passwordDialog->passphrase();
+ setPassphrase(newPassphrase);
if (passwordDialog->savePassphrase())
- savePassphraseForKey(m_keyId, passphrase());
- } else
- m_errorType = ErrorUndefined;
+ savePassphraseForKey(m_keyId, newPassphrase);
+ } else {
+ m_cancel = true;
+ }
delete passwordDialog;
- passwordDialog = 0;
m_waitCondition.wakeAll();
}
+void S60CreatePackageStep::packageWasPatched(const QString &package, const QStringList &changes)
+{
+ m_packageChanges.append(qMakePair(package, changes));
+}
+
+void S60CreatePackageStep::handleWarnAboutPatching()
+{
+ if (!m_suppressPatchWarningDialog && !m_packageChanges.isEmpty()) {
+ if (m_patchWarningDialog){
+ m_patchWarningDialog->raise();
+ return;
+ }
+
+ m_patchWarningDialog = new Utils::CheckableMessageBox(0);
+ connect(m_patchWarningDialog, SIGNAL(finished(int)), this, SLOT(packageWarningDialogDone()));
+
+ QString title;
+ QString text;
+ const QString &url = QString::fromLatin1("qthelp://com.nokia.qtcreator.%1%2%3/doc/creator-run-settings.html#capabilities-and-signing").
+ arg(IDE_VERSION_MAJOR).arg(IDE_VERSION_MINOR).arg(IDE_VERSION_RELEASE);
+ if (m_packageChanges.count() == 1) {
+ title = tr("A Package was modified");
+ text = tr("<p>Qt modified your package <b>%1</b>.</p>"
+ "<p><em>These changes were not part of your build system</em> but are required to "
+ "make sure the <em>self-signed</em> package can be installed successfully on a "
+ "device.</p>"
+ "<p>Check the Build Issues for more details on the modifications made.</p>"
+ "<p>Please see <a href=\"%2\">"
+ "the documentation</a> for other signing options. These will prevent "
+ "this patching from happening.</p>").arg(m_packageChanges.at(0).first, url);
+ } else {
+ title = tr("Several Packages were modified");
+ text = tr("<p>Qt modified some of your packages.</p>"
+ "<p><em>These changes were not part of your build system</em> but are required to "
+ "make sure the <em>self-signed</em> packages can be installed successfully.</p>"
+ "<p>Check the Build Issues for more details on the modifications made.</p>"
+ "<p>Please see <a href=\"%1\">"
+ "the documentation</a> for other signing options. These will prevent "
+ "this patching from happening.</p>").arg(url);
+ }
+ m_patchWarningDialog->setWindowTitle(title);
+ m_patchWarningDialog->setText(text);
+ m_patchWarningDialog->setCheckBoxText(tr("Ignore patching for this packaging step."));
+ m_patchWarningDialog->setIconPixmap(QMessageBox::standardIcon(QMessageBox::Warning));
+ m_patchWarningDialog->setChecked(m_suppressPatchWarningDialog);
+ m_patchWarningDialog->setStandardButtons(QDialogButtonBox::Ok);
+ m_patchWarningDialog->open();
+ }
+}
+
void S60CreatePackageStep::savePassphraseForKey(const QString &keyId, const QString &passphrase)
{
- m_settings->beginGroup("keys");
+ m_passphrases->beginGroup("keys");
if (passphrase.isEmpty())
- m_settings->remove(keyId);
+ m_passphrases->remove(keyId);
else
- m_settings->setValue(keyId, obfuscatePassphrase(passphrase, keyId));
- m_settings->endGroup();
+ m_passphrases->setValue(keyId, obfuscatePassphrase(passphrase, keyId));
+ m_passphrases->endGroup();
}
QString S60CreatePackageStep::loadPassphraseForKey(const QString &keyId)
{
- m_settings->beginGroup("keys");
- QString passphrase = elucidatePassphrase(m_settings->value(keyId, QByteArray()).toByteArray(), keyId);
- m_settings->endGroup();
+ if (keyId.isEmpty())
+ return QString();
+ m_passphrases->beginGroup("keys");
+ QString passphrase = elucidatePassphrase(m_passphrases->value(keyId, QByteArray()).toByteArray(), keyId);
+ m_passphrases->endGroup();
return passphrase;
}
@@ -265,46 +314,38 @@ QByteArray S60CreatePackageStep::obfuscatePassphrase(const QString &passphrase,
QString S60CreatePackageStep::elucidatePassphrase(QByteArray obfuscatedPassphrase, const QString &key) const
{
QByteArray byteArray = QByteArray::fromBase64(obfuscatedPassphrase);
+ if (byteArray.isEmpty())
+ return QString();
+
char *data = byteArray.data();
const QChar *keyData = key.data();
int keyDataSize = key.size();
for (int i = 0; i < byteArray.size(); ++i)
data[i] = data[i]^keyData[i%keyDataSize].toAscii();
- return byteArray.data();
+ return QString::fromUtf8(byteArray.data());
}
void S60CreatePackageStep::run(QFutureInterface<bool> &fi)
{
- m_futureInterface = &fi;
-
if (m_workingDirectories.isEmpty()) {
fi.reportResult(true);
return;
}
- // Setup everything...
- m_process = new QProcess();
- m_process->setEnvironment(m_environment.toStringList());
-
- connect(m_process, SIGNAL(readyReadStandardOutput()),
- this, SLOT(processReadyReadStdOutput()),
- Qt::DirectConnection);
- connect(m_process, SIGNAL(readyReadStandardError()),
- this, SLOT(processReadyReadStdError()),
- Qt::DirectConnection);
-
- connect(m_process, SIGNAL(finished(int, QProcess::ExitStatus)),
- this, SLOT(slotProcessFinished(int, QProcess::ExitStatus)),
- Qt::DirectConnection);
-
m_timer = new QTimer();
connect(m_timer, SIGNAL(timeout()), this, SLOT(checkForCancel()), Qt::DirectConnection);
m_timer->start(500);
m_eventLoop = new QEventLoop;
bool returnValue = false;
- if (startProcess())
- returnValue = m_eventLoop->exec();
+ if (!createOnePackage()) {
+ fi.reportResult(false);
+ return;
+ }
+
+ Q_ASSERT(!m_futureInterface);
+ m_futureInterface = &fi;
+ returnValue = m_eventLoop->exec();
// Finished
m_timer->stop();
@@ -315,81 +356,83 @@ void S60CreatePackageStep::run(QFutureInterface<bool> &fi)
m_process = 0;
delete m_eventLoop;
m_eventLoop = 0;
- fi.reportResult(returnValue);
+
m_futureInterface = 0;
- return;
+ if (returnValue)
+ emit warnAboutPatching();
+ fi.reportResult(returnValue);
}
-void S60CreatePackageStep::slotProcessFinished(int, QProcess::ExitStatus)
+bool S60CreatePackageStep::createOnePackage()
{
- QString line = QString::fromLocal8Bit(m_process->readAllStandardError());
- if (!line.isEmpty())
- stdError(line);
-
- line = QString::fromLocal8Bit(m_process->readAllStandardOutput());
- if (!line.isEmpty())
- stdOutput(line);
+ // Setup arguments:
+ m_args.clear();
+ if (m_createSmartInstaller) {
+ if (signingMode() == NotSigned)
+ m_args << QLatin1String("unsigned_installer_sis");
+ else
+ m_args << QLatin1String("installer_sis");
+ } else if (signingMode() == NotSigned)
+ m_args << QLatin1String("unsigned_sis");
+ else
+ m_args << QLatin1String("sis");
- bool returnValue = false;
- if (m_process->exitStatus() == QProcess::NormalExit && m_process->exitCode() == 0) {
- emit addOutput(tr("The process \"%1\" exited normally.")
- .arg(QDir::toNativeSeparators(m_makeCmd)),
- BuildStep::MessageOutput);
- returnValue = true;
- } else if (m_process->exitStatus() == QProcess::NormalExit) {
- emit addOutput(tr("The process \"%1\" exited with code %2.")
- .arg(QDir::toNativeSeparators(m_makeCmd), QString::number(m_process->exitCode())),
- BuildStep::ErrorMessageOutput);
- } else {
- emit addOutput(tr("The process \"%1\" crashed.").arg(QDir::toNativeSeparators(m_makeCmd)), BuildStep::ErrorMessageOutput);
- }
+ if (signingMode() == SignCustom) {
+ m_args << QLatin1String(MAKE_CERTIFICATE_ARGUMENT) + QDir::toNativeSeparators(customSignaturePath())
+ << QLatin1String(MAKE_KEY_ARGUMENT) + QDir::toNativeSeparators(customKeyPath());
- switch (m_errorType) {
- case ErrorUndefined:
- m_eventLoop->exit(false);
- return;
- case ErrorBadPassphrase: {
- emit badPassphrase();
- QMutexLocker locker(&m_mutex);
- //waiting for the user to input new passphrase or to abort
- m_waitCondition.wait(&m_mutex);
- if( m_errorType == ErrorUndefined ) {
- m_eventLoop->exit(false);
- return;
- } else {
- QRegExp passphraseRegExp("^"+QLatin1String(MAKE_PASSPHRASE_ARGUMENT)+"(.+)$");
- int index = m_args.indexOf(passphraseRegExp);
- if (index>=0)
- m_args.removeAt(index);
- if (!passphrase().isEmpty())
- m_args << QLatin1String(MAKE_PASSPHRASE_ARGUMENT) + passphrase();
- }
- break;
- }
- default:
- m_workingDirectories.removeFirst();
- break;
- }
+ setPassphrase(loadPassphraseForKey(m_keyId));
- if (m_workingDirectories.isEmpty() || !returnValue) {
- m_eventLoop->exit(returnValue);
- } else {
- // Success, do next
- if (!startProcess())
- m_eventLoop->exit(returnValue);
+ if (!passphrase().isEmpty())
+ m_args << QLatin1String(MAKE_PASSPHRASE_ARGUMENT) + passphrase();
}
-}
-bool S60CreatePackageStep::startProcess()
-{
- m_errorType = ErrorNone;
+ // Setup working directory:
QString workingDirectory = m_workingDirectories.first();
QDir wd(workingDirectory);
if (!wd.exists())
wd.mkpath(wd.absolutePath());
- m_process->setWorkingDirectory(workingDirectory);
+
+ // Setup process...
+ Q_ASSERT(!m_process);
+ m_process = new QProcess();
+ m_process->setEnvironment(m_environment.toStringList());
+
+ connect(m_process, SIGNAL(readyReadStandardOutput()),
+ this, SLOT(processReadyReadStdOutput()),
+ Qt::DirectConnection);
+ connect(m_process, SIGNAL(readyReadStandardError()),
+ this, SLOT(processReadyReadStdError()),
+ Qt::DirectConnection);
+
+ connect(m_process, SIGNAL(finished(int, QProcess::ExitStatus)),
+ this, SLOT(packageDone(int, QProcess::ExitStatus)),
+ Qt::DirectConnection);
+
+ m_process->setWorkingDirectory(wd.absolutePath());
+
+ // Setup parsers:
+ Q_ASSERT(!m_outputParserChain);
+ if (!qt4BuildConfiguration()->qtVersion()->isBuildWithSymbianSbsV2()) {
+ m_outputParserChain = new Qt4ProjectManager::AbldParser;
+ m_outputParserChain->appendOutputParser(new ProjectExplorer::GnuMakeParser);
+ } else {
+ m_outputParserChain = new ProjectExplorer::GnuMakeParser();
+ }
+ Q_ASSERT(!m_parser);
+ m_parser = new S60CreatePackageParser(wd.absolutePath());
+ m_outputParserChain->appendOutputParser(m_parser);
+ m_outputParserChain->setWorkingDirectory(wd.absolutePath());
+
+ connect(m_outputParserChain, SIGNAL(addOutput(QString,ProjectExplorer::BuildStep::OutputFormat)),
+ this, SIGNAL(addOutput(QString,ProjectExplorer::BuildStep::OutputFormat)));
+ connect(m_outputParserChain, SIGNAL(addTask(ProjectExplorer::Task)),
+ this, SIGNAL(addTask(ProjectExplorer::Task)), Qt::DirectConnection);
+
+ connect(m_parser, SIGNAL(packageWasPatched(QString,QStringList)),
+ this, SLOT(packageWasPatched(QString,QStringList)), Qt::DirectConnection);
// Go for it!
m_process->start(m_makeCmd, m_args);
@@ -408,6 +451,134 @@ bool S60CreatePackageStep::startProcess()
return true;
}
+bool S60CreatePackageStep::validateCustomSigningResources(const QStringList &capabilitiesInPro)
+{
+ Q_ASSERT(signingMode() == SignCustom);
+
+ QString errorString;
+ if (customSignaturePath().isEmpty())
+ errorString = tr("Certificate file has not heen defined. "
+ "Please define certificate file in the project's options.");
+ else if (!QFileInfo(customSignaturePath()).exists())
+ errorString = tr("Certificate file \"%1\" does not exist. "
+ "Please define certificate file in the project's options.").arg(customSignaturePath());
+
+ if (customKeyPath().isEmpty())
+ errorString = tr("Key file has not heen defined. "
+ "Please define certificate file in the project's options.");
+ else if (!QFileInfo(customKeyPath()).exists())
+ errorString = tr("Key file \"%1\" does not exist. "
+ "Please define certificate file in the project's options.").arg(customKeyPath());
+
+ if (!errorString.isEmpty()) {
+ reportPackageStepIssue(errorString, true);
+ return false;
+ }
+ QScopedPointer<S60CertificateInfo> certInfoPtr(new S60CertificateInfo(customSignaturePath()));
+ S60CertificateInfo::CertificateState certState = certInfoPtr.data()->validateCertificate();
+ switch (certState) {
+ case S60CertificateInfo::CertificateError:
+ reportPackageStepIssue(certInfoPtr.data()->errorString(), true);
+ return false;
+ case S60CertificateInfo::CertificateWarning:
+ reportPackageStepIssue(certInfoPtr.data()->errorString(), false);
+ break;
+ default:
+ break;
+ }
+
+ QStringList unsupportedCaps;
+ if (certInfoPtr.data()->compareCapabilities(capabilitiesInPro, unsupportedCaps)) {
+ if (!unsupportedCaps.isEmpty()) {
+ QString message = tr("The created package will not install on a "
+ "device as some of the defined capabilities "
+ "are not supported by the certificate: %1")
+ .arg(unsupportedCaps.join(" "));
+ reportPackageStepIssue(message, true);
+ return false;
+ }
+
+ } else
+ reportPackageStepIssue(certInfoPtr.data()->errorString(), false);
+ return true;
+}
+
+void S60CreatePackageStep::reportPackageStepIssue(const QString &message, bool isError )
+{
+ emit addOutput(message, isError?
+ BuildStep::ErrorMessageOutput:
+ BuildStep::MessageOutput);
+ emit addTask(ProjectExplorer::Task(isError?
+ ProjectExplorer::Task::Error:
+ ProjectExplorer::Task::Warning,
+ message,
+ QString(), -1,
+ ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
+}
+
+void S60CreatePackageStep::packageWarningDialogDone()
+{
+ if (m_patchWarningDialog)
+ m_suppressPatchWarningDialog = m_patchWarningDialog->isChecked();
+ if (m_suppressPatchWarningDialog) {
+ m_patchWarningDialog->deleteLater();
+ m_patchWarningDialog = 0;
+ }
+}
+
+void S60CreatePackageStep::packageDone(int exitCode, QProcess::ExitStatus status)
+{
+ QString line = QString::fromLocal8Bit(m_process->readAllStandardError());
+ if (!line.isEmpty())
+ stdError(line);
+
+ line = QString::fromLocal8Bit(m_process->readAllStandardOutput());
+ if (!line.isEmpty())
+ stdOutput(line);
+
+ if (status == QProcess::NormalExit && exitCode == 0) {
+ emit addOutput(tr("The process \"%1\" exited normally.")
+ .arg(QDir::toNativeSeparators(m_makeCmd)),
+ BuildStep::MessageOutput);
+ } else if (status == QProcess::NormalExit) {
+ emit addOutput(tr("The process \"%1\" exited with code %2.")
+ .arg(QDir::toNativeSeparators(m_makeCmd), QString::number(exitCode)),
+ BuildStep::ErrorMessageOutput);
+ } else {
+ emit addOutput(tr("The process \"%1\" crashed.").arg(QDir::toNativeSeparators(m_makeCmd)), BuildStep::ErrorMessageOutput);
+ }
+
+ bool needPassphrase = m_parser->needPassphrase();
+
+ // Clean up:
+ delete m_outputParserChain;
+ m_outputParserChain = 0;
+ m_parser = 0;
+ delete m_process;
+ m_process = 0;
+
+ // Process next directories:
+ if (needPassphrase) {
+ emit badPassphrase();
+ QMutexLocker locker(&m_mutex);
+ m_waitCondition.wait(&m_mutex);
+ } else {
+ if (status != QProcess::NormalExit || exitCode != 0) {
+ m_eventLoop->exit(false);
+ return;
+ }
+
+ m_workingDirectories.removeFirst();
+ if (m_workingDirectories.isEmpty()) {
+ m_eventLoop->exit(true);
+ return;
+ }
+ }
+
+ if (m_cancel || !createOnePackage())
+ m_eventLoop->exit(false);
+}
+
void S60CreatePackageStep::processReadyReadStdOutput()
{
m_process->setReadChannel(QProcess::StandardOutput);
@@ -442,35 +613,21 @@ void S60CreatePackageStep::stdError(const QString &line)
void S60CreatePackageStep::checkForCancel()
{
- if (m_futureInterface->isCanceled() && m_timer->isActive()) {
+ if (m_futureInterface->isCanceled()
+ && m_timer && m_timer->isActive()) {
m_timer->stop();
- m_process->terminate();
- m_process->waitForFinished(5000);
- m_process->kill();
- }
-}
-
-void S60CreatePackageStep::taskAdded(const ProjectExplorer::Task &task)
-{
- ProjectExplorer::Task editable(task);
- QString filePath = QDir::cleanPath(task.file.trimmed());
- if (!filePath.isEmpty() && !QDir::isAbsolutePath(filePath)) {
- // TODO which kind of tasks do we get from package building?
- // No absoulte path
- }
- if (task.type == ProjectExplorer::Task::Error) {
- if (task.description.contains(QLatin1String("bad password"))
- || task.description.contains(QLatin1String("bad decrypt")))
- m_errorType = ErrorBadPassphrase;
- else if (m_errorType == ErrorNone)
- m_errorType = ErrorUndefined;
+ if (m_process) {
+ m_process->terminate();
+ m_process->waitForFinished(5000);
+ m_process->kill();
+ }
+ m_eventLoop->exit(false);
}
- emit addTask(editable);
}
QString S60CreatePackageStep::generateKeyId(const QString &keyPath) const
{
- if (keyPath.isEmpty())
+ if (keyPath.isNull())
return QString();
QFile file(keyPath);
@@ -482,11 +639,6 @@ QString S60CreatePackageStep::generateKeyId(const QString &keyPath) const
QCryptographicHash::Md5).toHex();
}
-void S60CreatePackageStep::outputAdded(const QString &string, ProjectExplorer::BuildStep::OutputFormat format)
-{
- emit addOutput(string, format);
-}
-
bool S60CreatePackageStep::immutable() const
{
return false;
@@ -535,6 +687,8 @@ QString S60CreatePackageStep::passphrase() const
void S60CreatePackageStep::setPassphrase(const QString &passphrase)
{
+ if (passphrase.isEmpty())
+ return;
m_passphrase = passphrase;
}
@@ -561,13 +715,13 @@ void S60CreatePackageStep::setCreatesSmartInstaller(bool value)
void S60CreatePackageStep::resetPassphrases()
{
- m_settings->beginGroup("keys");
- QStringList keys = m_settings->allKeys();
+ m_passphrases->beginGroup("keys");
+ QStringList keys = m_passphrases->allKeys();
foreach (QString key, keys) {
- m_settings->setValue(key, "");
+ m_passphrases->setValue(key, "");
}
- m_settings->remove("");
- m_settings->endGroup();
+ m_passphrases->remove("");
+ m_passphrases->endGroup();
}
// #pragma mark -- S60SignBuildStepFactory
@@ -649,8 +803,16 @@ S60CreatePackageStepConfigWidget::S60CreatePackageStepConfigWidget(S60CreatePack
{
m_ui.setupUi(this);
m_ui.signaturePath->setExpectedKind(Utils::PathChooser::File);
+ m_ui.signaturePath->setPromptDialogFilter(QLatin1String("*.cer *.crt *.der *.pem"));
m_ui.keyFilePath->setExpectedKind(Utils::PathChooser::File);
updateUi();
+
+ bool enableCertDetails = m_signStep->signingMode() == S60CreatePackageStep::SignCustom
+ && m_ui.signaturePath->isValid();
+ m_ui.certificateDetails->setEnabled(enableCertDetails);
+
+ connect(m_ui.certificateDetails, SIGNAL(clicked()),
+ this, SLOT(displayCertificateDetails()));
connect(m_ui.customCertificateButton, SIGNAL(clicked()),
this, SLOT(updateFromUi()));
connect(m_ui.selfSignedButton, SIGNAL(clicked()),
@@ -658,7 +820,7 @@ S60CreatePackageStepConfigWidget::S60CreatePackageStepConfigWidget(S60CreatePack
connect(m_ui.notSignedButton, SIGNAL(clicked()),
this, SLOT(updateFromUi()));
connect(m_ui.signaturePath, SIGNAL(changed(QString)),
- this, SLOT(updateFromUi()));
+ this, SLOT(signatureChanged(QString)));
connect(m_ui.keyFilePath, SIGNAL(changed(QString)),
this, SLOT(updateFromUi()));
connect(m_ui.smartInstaller, SIGNAL(clicked()),
@@ -667,24 +829,54 @@ S60CreatePackageStepConfigWidget::S60CreatePackageStepConfigWidget(S60CreatePack
this, SLOT(resetPassphrases()));
}
+void S60CreatePackageStepConfigWidget::signatureChanged(QString certFile)
+{
+ m_ui.certificateDetails->setEnabled(m_ui.signaturePath->isValid());
+
+ if (!certFile.isEmpty() && m_ui.keyFilePath->path().isEmpty()) {
+ /* If a cert file is selected and there is not key file inserted,
+ then we check if there is a .key or .pem file in the folder with
+ the same base name as the cert file. This file is probably a key
+ file for this cert and the key field is then populated automatically
+ */
+ QFileInfo certFileInfo(certFile);
+ QDir directory = QDir(certFileInfo.absolutePath());
+ QString keyFile(certFileInfo.baseName() + QLatin1String(".key"));
+ QString pemFile(certFileInfo.baseName() + QLatin1String(".pem"));
+ QStringList files;
+ QStringList keys;
+ keys << keyFile << pemFile;
+ files = directory.entryList(QStringList(keys),
+ QDir::Files | QDir::NoSymLinks);
+
+ if (files.isEmpty())
+ m_ui.keyFilePath->setInitialBrowsePathBackup(certFileInfo.path());
+ else
+ m_ui.keyFilePath->setPath(directory.filePath(files[0]));
+ }
+ updateFromUi();
+}
+
void S60CreatePackageStepConfigWidget::updateUi()
{
-
switch(m_signStep->signingMode()) {
case S60CreatePackageStep::SignCustom:
m_ui.selfSignedButton->setChecked(false);
m_ui.customCertificateButton->setChecked(true);
m_ui.notSignedButton->setChecked(false);
+ m_ui.certificateDetails->setEnabled(m_ui.signaturePath->isValid());
break;
case S60CreatePackageStep::NotSigned:
m_ui.selfSignedButton->setChecked(false);
m_ui.customCertificateButton->setChecked(false);
m_ui.notSignedButton->setChecked(true);
+ m_ui.certificateDetails->setEnabled(false);
break;
default:
m_ui.selfSignedButton->setChecked(true);
m_ui.customCertificateButton->setChecked(false);
m_ui.notSignedButton->setChecked(false);
+ m_ui.certificateDetails->setEnabled(false);
break;
}
bool customSigned = m_signStep->signingMode() == S60CreatePackageStep::SignCustom;
@@ -713,6 +905,17 @@ void S60CreatePackageStepConfigWidget::updateFromUi()
updateUi();
}
+void S60CreatePackageStepConfigWidget::displayCertificateDetails()
+{
+ S60CertificateInfo *certificateInformation = new S60CertificateInfo(m_ui.signaturePath->path());
+ certificateInformation->devicesSupported().sort();
+
+ S60CertificateDetailsDialog dialog;
+ dialog.setText(certificateInformation->toHtml(false));
+ dialog.exec();
+ delete certificateInformation;
+}
+
void S60CreatePackageStepConfigWidget::resetPassphrases()
{
QMessageBox msgBox(QMessageBox::Question, tr("Reset Passphrases"),
@@ -727,8 +930,13 @@ QString S60CreatePackageStepConfigWidget::summaryText() const
QString text;
switch(m_signStep->signingMode()) {
case S60CreatePackageStep::SignCustom:
- text = tr("signed with certificate %1 and key file %2")
- .arg(m_signStep->customSignaturePath(), m_signStep->customKeyPath());
+ if (!m_signStep->customSignaturePath().isEmpty()
+ && !m_signStep->customKeyPath().isEmpty())
+ text = tr("signed with \"%1\" certificate and \"%2\" key file")
+ .arg(QFileInfo(m_signStep->customSignaturePath()).fileName(),
+ QFileInfo(m_signStep->customKeyPath()).fileName());
+ else
+ text = tr("signed with a certificate and a key that need to be defined");
break;
case S60CreatePackageStep::NotSigned:
text = tr("not signed");
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.h b/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.h
index c465ef6c0a..0430fc62b5 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.h
+++ b/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.h
@@ -46,9 +46,15 @@ QT_BEGIN_NAMESPACE
class QSettings;
QT_END_NAMESPACE
+namespace Utils {
+class CheckableMessageBox;
+} // namespace Utils
+
namespace Qt4ProjectManager {
namespace Internal {
+class S60CreatePackageParser;
+
class S60CreatePackageStepFactory : public ProjectExplorer::IBuildStepFactory
{
Q_OBJECT
@@ -75,6 +81,7 @@ class S60CreatePackageStep : public ProjectExplorer::BuildStep
{
Q_OBJECT
friend class S60CreatePackageStepFactory;
+
public:
enum SigningMode {
SignSelf = 0,
@@ -109,6 +116,7 @@ public:
signals:
void badPassphrase();
+ void warnAboutPatching();
protected:
S60CreatePackageStep(ProjectExplorer::BuildStepList *bsl, S60CreatePackageStep *bs);
@@ -118,24 +126,24 @@ protected:
Qt4BuildConfiguration *qt4BuildConfiguration() const;
private slots:
- void slotProcessFinished(int, QProcess::ExitStatus);
+ void packageWarningDialogDone();
+ void packageDone(int, QProcess::ExitStatus);
void processReadyReadStdOutput();
void processReadyReadStdError();
- void taskAdded(const ProjectExplorer::Task &task);
- void outputAdded(const QString &string, ProjectExplorer::BuildStep::OutputFormat format);
void checkForCancel();
void definePassphrase();
-private:
- enum ErrorType {
- ErrorNone = 0,
- ErrorUndefined,
- ErrorBadPassphrase
- };
+ void packageWasPatched(const QString &, const QStringList &);
+ void handleWarnAboutPatching();
+private:
void stdOutput(const QString &line);
void stdError(const QString &line);
- bool startProcess();
+
+ void reportPackageStepIssue(const QString &message, bool isError );
+ void setupProcess();
+ bool createOnePackage();
+ bool validateCustomSigningResources(const QStringList &capabilitiesInPro);
QString generateKeyId(const QString &keyPath) const;
QString loadPassphraseForKey(const QString &keyId);
@@ -163,12 +171,18 @@ private:
QTimer *m_timer;
QEventLoop *m_eventLoop;
QFutureInterface<bool> *m_futureInterface;
- ErrorType m_errorType;
QWaitCondition m_waitCondition;
QMutex m_mutex;
- QSettings *m_settings;
+ bool m_cancel;
+
+ QSettings *m_passphrases;
+ S60CreatePackageParser *m_parser;
+ QList<QPair<QString, QStringList> > m_packageChanges;
+
+ bool m_suppressPatchWarningDialog;
+ Utils::CheckableMessageBox *m_patchWarningDialog;
};
class S60CreatePackageStepConfigWidget : public ProjectExplorer::BuildStepConfigWidget
@@ -184,6 +198,8 @@ private slots:
void updateUi();
void updateFromUi();
void resetPassphrases();
+ void signatureChanged(QString certFile);
+ void displayCertificateDetails();
private:
S60CreatePackageStep *m_signStep;
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.ui b/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.ui
index b9eccf5ad1..4b45e615c4 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.ui
+++ b/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.ui
@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>517</width>
- <height>135</height>
+ <height>156</height>
</rect>
</property>
<property name="windowTitle">
@@ -87,9 +87,9 @@
</widget>
</item>
<item row="0" column="1">
- <widget class="Utils::PathChooser" name="signaturePath" native="true">
+ <widget class="CertificatePathChooser" name="signaturePath" native="true">
<property name="promptDialogTitle" stdset="0">
- <string>Choose certificate file (.cer)</string>
+ <string>Choose certificate file</string>
</property>
</widget>
</item>
@@ -127,6 +127,19 @@
</widget>
</item>
<item>
+ <widget class="QPushButton" name="certificateDetails">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="toolTip">
+ <string/>
+ </property>
+ <property name="text">
+ <string>Certificate's details</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@@ -167,6 +180,12 @@
<signal>browsingFinished()</signal>
</slots>
</customwidget>
+ <customwidget>
+ <class>CertificatePathChooser</class>
+ <extends>QWidget</extends>
+ <header location="global">qt4projectmanager/qt-s60/certificatepathchooser.h</header>
+ <container>1</container>
+ </customwidget>
</customwidgets>
<resources/>
<connections/>
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60deployconfiguration.cpp b/src/plugins/qt4projectmanager/qt-s60/s60deployconfiguration.cpp
index 12fe307a69..82b735c7a1 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60deployconfiguration.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/s60deployconfiguration.cpp
@@ -33,34 +33,19 @@
#include "s60deployconfiguration.h"
#include "s60deployconfigurationwidget.h"
-#include "s60devicerunconfiguration.h"
-
#include "qt4project.h"
#include "qt4target.h"
-#include "s60devices.h"
-#include "s60manager.h"
#include "qt4projectmanagerconstants.h"
-#include "qtversionmanager.h"
-#include "profilereader.h"
-#include "s60manager.h"
-#include "s60devices.h"
-#include "symbiandevicemanager.h"
#include "qt4buildconfiguration.h"
-#include "qt4projectmanagerconstants.h"
#include "s60createpackagestep.h"
-#include "qtoutputformatter.h"
-#include <coreplugin/icore.h>
-#include <coreplugin/messagemanager.h>
-#include <coreplugin/progressmanager/progressmanager.h>
#include <utils/qtcassert.h>
-#include <utils/pathchooser.h>
+#include <symbianutils/symbiandevicemanager.h>
+
#include <projectexplorer/buildsteplist.h>
-#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/project.h>
-#include <projectexplorer/buildconfiguration.h>
-#include <QFileInfo>
+#include <QtCore/QFileInfo>
using namespace ProjectExplorer;
using namespace Qt4ProjectManager;
@@ -116,7 +101,11 @@ S60DeployConfiguration::S60DeployConfiguration(Target *target, S60DeployConfigur
void S60DeployConfiguration::ctor()
{
setDefaultDisplayName(defaultDisplayName());
- connect(qt4Target()->qt4Project(), SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode*)),
+ // TODO disable S60 Deploy Configuration while parsing
+ // requires keeping track of the parsing state of the project
+// connect(qt4Target()->qt4Project(), SIGNAL(proFileInvalidated(Qt4ProjectManager::Internal::Qt4ProFileNode*)),
+// this, SLOT(targetInformationInvalidated()));
+ connect(qt4Target()->qt4Project(), SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode*,bool)),
this, SIGNAL(targetInformationChanged()));
connect(qt4Target(), SIGNAL(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*)),
this, SLOT(updateActiveBuildConfiguration(ProjectExplorer::BuildConfiguration*)));
@@ -244,23 +233,24 @@ bool S60DeployConfiguration::isSigned() const
return false;
}
-ProjectExplorer::ToolChain::ToolChainType S60DeployConfiguration::toolChainType() const
+ProjectExplorer::ToolChainType S60DeployConfiguration::toolChainType() const
{
if (Qt4BuildConfiguration *bc = qobject_cast<Qt4BuildConfiguration *>(target()->activeBuildConfiguration()))
return bc->toolChainType();
- return ProjectExplorer::ToolChain::INVALID;
+ return ProjectExplorer::ToolChain_INVALID;
}
QString S60DeployConfiguration::symbianPlatform() const
{
const Qt4BuildConfiguration *qt4bc = qt4Target()->activeBuildConfiguration();
switch (qt4bc->toolChainType()) {
- case ToolChain::GCCE:
- case ToolChain::GCCE_GNUPOC:
+ case ProjectExplorer::ToolChain_GCCE:
+ case ProjectExplorer::ToolChain_GCCE_GNUPOC:
return QLatin1String("gcce");
- case ToolChain::RVCT_ARMV5:
+ case ProjectExplorer::ToolChain_RVCT2_ARMV5:
+ case ProjectExplorer::ToolChain_RVCT4_ARMV5:
return QLatin1String("armv5");
- default: // including ToolChain::RVCT_ARMV6_GNUPOC:
+ default: // including ProjectExplorer::RVCT_ARMV6_GNUPOC:
return QLatin1String("armv6");
}
}
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60deployconfiguration.h b/src/plugins/qt4projectmanager/qt-s60/s60deployconfiguration.h
index 2b6d74622f..92e8106e98 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60deployconfiguration.h
+++ b/src/plugins/qt4projectmanager/qt-s60/s60deployconfiguration.h
@@ -35,16 +35,19 @@
#define S60DEPLOYCONFIGURATION_H
#include <projectexplorer/deployconfiguration.h>
-#include <projectexplorer/buildconfiguration.h>
-#include <projectexplorer/runconfiguration.h>
-#include <projectexplorer/toolchain.h>
+#include <projectexplorer/toolchaintype.h>
+
+namespace ProjectExplorer {
+class BuildConfiguration;
+class RunConfiguration;
+}
namespace Qt4ProjectManager {
class QtVersion;
+class Qt4Target;
namespace Internal {
class Qt4ProFileNode;
-class Qt4Target;
class S60DeployConfigurationFactory;
class S60DeviceRunConfiguration;
@@ -54,7 +57,7 @@ class S60DeployConfiguration : public ProjectExplorer::DeployConfiguration
friend class S60DeployConfigurationFactory;
public:
- S60DeployConfiguration(ProjectExplorer::Target *parent);
+ explicit S60DeployConfiguration(ProjectExplorer::Target *parent);
virtual ~S60DeployConfiguration();
bool isEnabled(ProjectExplorer::BuildConfiguration *configuration) const;
@@ -63,7 +66,7 @@ public:
const QtVersion *qtVersion() const;
Qt4Target *qt4Target() const;
- ProjectExplorer::ToolChain::ToolChainType toolChainType() const;
+ ProjectExplorer::ToolChainType toolChainType() const;
QString serialPortName() const;
void setSerialPortName(const QString &name);
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60deployconfigurationwidget.cpp b/src/plugins/qt4projectmanager/qt-s60/s60deployconfigurationwidget.cpp
index bb5837a9b1..12112bb4d8 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60deployconfigurationwidget.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/s60deployconfigurationwidget.cpp
@@ -36,11 +36,11 @@
#include "s60devicerunconfiguration.h"
#include "s60runconfigbluetoothstarter.h"
-#include "bluetoothlistener_gui.h"
-#include "s60manager.h"
-#include "launcher.h"
-#include "bluetoothlistener.h"
-#include "symbiandevicemanager.h"
+#include <symbianutils/bluetoothlistener_gui.h>
+
+#include <symbianutils/launcher.h>
+#include <symbianutils/bluetoothlistener.h>
+#include <symbianutils/symbiandevicemanager.h>
#include <utils/detailswidget.h>
#include <utils/qtcassert.h>
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60deployconfigurationwidget.h b/src/plugins/qt4projectmanager/qt-s60/s60deployconfigurationwidget.h
index 762b8be80a..7b20ce4fa7 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60deployconfigurationwidget.h
+++ b/src/plugins/qt4projectmanager/qt-s60/s60deployconfigurationwidget.h
@@ -34,11 +34,11 @@
#ifndef S60DEPLOYCONFIGURATIONWIDGET_H
#define S60DEPLOYCONFIGURATIONWIDGET_H
+#include <projectexplorer/deployconfiguration.h>
+
#include <QtGui/QWidget>
#include <QtCore/QPointer>
-#include <projectexplorer/deployconfiguration.h>
-
QT_BEGIN_NAMESPACE
class QLabel;
class QLineEdit;
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60deploystep.cpp b/src/plugins/qt4projectmanager/qt-s60/s60deploystep.cpp
index 08b6f8408d..2b8b776107 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60deploystep.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/s60deploystep.cpp
@@ -36,25 +36,25 @@
#include "qt4buildconfiguration.h"
#include "s60deployconfiguration.h"
#include "s60devicerunconfiguration.h"
-#include "symbiandevicemanager.h"
#include "s60runconfigbluetoothstarter.h"
-#include <QtGui/QMessageBox>
-#include <QtGui/QMainWindow>
-#include <QtCore/QCoreApplication>
-#include <QtCore/QTimer>
-#include <QDateTime>
-#include <QFile>
-#include <QFileInfo>
-#include <QDir>
-
#include <coreplugin/icore.h>
#include <projectexplorer/buildsteplist.h>
#include <projectexplorer/target.h>
-#include <projectexplorer/ioutputparser.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <qt4projectmanagerconstants.h>
+#include <symbianutils/launcher.h>
+#include <symbianutils/symbiandevicemanager.h>
+
+#include <QtGui/QMessageBox>
+#include <QtGui/QMainWindow>
+
+#include <QtCore/QTimer>
+#include <QtCore/QDateTime>
+#include <QtCore/QDir>
+#include <QtCore/QEventLoop>
+
using namespace ProjectExplorer;
using namespace Qt4ProjectManager::Internal;
@@ -149,7 +149,7 @@ bool S60DeployStep::init()
delete m_launcher;
m_launcher = 0;
appendMessage(message, true);
- return false;
+ return true;
}
// Prompt the user to start up the Blue tooth connection
const trk::PromptStartCommunicationResult src =
@@ -161,7 +161,7 @@ bool S60DeployStep::init()
delete m_launcher;
m_launcher = 0;
appendMessage(message, true);
- return false;
+ return true;
}
return true;
}
@@ -215,20 +215,29 @@ bool S60DeployStep::processPackageName(QString &errorMessage)
void S60DeployStep::start()
{
- if (m_serialPortName.isEmpty()) {
- appendMessage(tr("There is no device plugged in."), true);
+ QString errorMessage;
+
+ if (m_serialPortName.isEmpty() || !m_launcher) {
+ errorMessage = tr("No device is connected. Please connect a device and try again.");
+ appendMessage(errorMessage, true);
+ emit addTask(ProjectExplorer::Task(ProjectExplorer::Task::Error,
+ errorMessage,
+ QString(), -1,
+ ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
emit finished();
return;
}
- QString errorMessage;
-
// make sure we have the right name of the sis package
if (processPackageName(errorMessage)) {
startDeployment();
} else {
errorMessage = tr("Failed to find package %1").arg(errorMessage);
appendMessage(errorMessage, true);
+ emit addTask(ProjectExplorer::Task(ProjectExplorer::Task::Error,
+ errorMessage,
+ QString(), -1,
+ ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
stop();
emit finished();
}
@@ -422,6 +431,10 @@ BuildStepConfigWidget *S60DeployStep::createConfigWidget()
return new S60DeployStepWidget();
}
+S60DeployStepWidget::S60DeployStepWidget() : ProjectExplorer::BuildStepConfigWidget()
+{
+}
+
void S60DeployStepWidget::init()
{
}
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60deploystep.h b/src/plugins/qt4projectmanager/qt-s60/s60deploystep.h
index e97883ee62..e72d4373b1 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60deploystep.h
+++ b/src/plugins/qt4projectmanager/qt-s60/s60deploystep.h
@@ -31,20 +31,21 @@
**
**************************************************************************/
-
#ifndef S60DeployStep_H
#define S60DeployStep_H
#include <projectexplorer/buildstep.h>
-#include "launcher.h"
-
#include <QtCore/QString>
-#include <QtCore/QEventLoop>
+
+QT_FORWARD_DECLARE_CLASS(QEventLoop)
namespace SymbianUtils {
class SymbianDevice;
}
+namespace trk{
+class Launcher;
+}
namespace ProjectExplorer {
class IOutputParser;
@@ -61,7 +62,7 @@ class S60DeployStepFactory : public ProjectExplorer::IBuildStepFactory
Q_OBJECT
public:
explicit S60DeployStepFactory(QObject *parent = 0);
- ~S60DeployStepFactory();
+ virtual ~S60DeployStepFactory();
// used to show the list of possible additons to a target, returns a list of types
QStringList availableCreationIds(ProjectExplorer::BuildStepList *parent) const;
@@ -155,13 +156,11 @@ class S60DeployStepWidget : public ProjectExplorer::BuildStepConfigWidget
{
Q_OBJECT
public:
- S60DeployStepWidget()
- : ProjectExplorer::BuildStepConfigWidget()
- {}
+ S60DeployStepWidget();
+
void init();
QString summaryText() const;
QString displayName() const;
-
};
} // Internal
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp
index aa01a1cdc2..89efb168c4 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp
@@ -36,34 +36,28 @@
#include "s60deployconfiguration.h"
#include "qt4project.h"
#include "qt4target.h"
-#include "qtversionmanager.h"
-#include "profilereader.h"
#include "s60manager.h"
#include "s60devices.h"
#include "s60runconfigbluetoothstarter.h"
-#include "bluetoothlistener_gui.h"
-#include "symbiandevicemanager.h"
-#include "qt4buildconfiguration.h"
#include "qt4projectmanagerconstants.h"
-#include "s60createpackagestep.h"
#include "qtoutputformatter.h"
+#include <symbianutils/bluetoothlistener_gui.h>
+#include <symbianutils/launcher.h>
+#include <symbianutils/symbiandevicemanager.h>
+
+#include <utils/qtcassert.h>
+
#include <coreplugin/icore.h>
-#include <coreplugin/messagemanager.h>
#include <coreplugin/progressmanager/progressmanager.h>
-#include <utils/qtcassert.h>
-#include <utils/pathchooser.h>
-#include <projectexplorer/buildsteplist.h>
-#include <projectexplorer/deployconfiguration.h>
-#include <projectexplorer/projectexplorerconstants.h>
-#include <projectexplorer/project.h>
#include <debugger/debuggerengine.h>
-#include <debugger/debuggerplugin.h>
#include <QtGui/QMessageBox>
#include <QtGui/QMainWindow>
-#include <QtCore/QCoreApplication>
+#include <QtCore/QFileInfo>
+#include <QtCore/QDateTime>
+#include <QtCore/QDir>
using namespace ProjectExplorer;
using namespace Qt4ProjectManager;
@@ -111,17 +105,19 @@ QString pathToId(const QString &path)
// ======== S60DeviceRunConfiguration
-S60DeviceRunConfiguration::S60DeviceRunConfiguration(Target *parent, const QString &proFilePath) :
+S60DeviceRunConfiguration::S60DeviceRunConfiguration(Qt4Target *parent, const QString &proFilePath) :
RunConfiguration(parent, QLatin1String(S60_DEVICE_RC_ID)),
- m_proFilePath(proFilePath)
+ m_proFilePath(proFilePath),
+ m_validParse(parent->qt4Project()->validParse(proFilePath))
{
ctor();
}
-S60DeviceRunConfiguration::S60DeviceRunConfiguration(Target *target, S60DeviceRunConfiguration *source) :
+S60DeviceRunConfiguration::S60DeviceRunConfiguration(Qt4Target *target, S60DeviceRunConfiguration *source) :
RunConfiguration(target, source),
m_proFilePath(source->m_proFilePath),
- m_commandLineArguments(source->m_commandLineArguments)
+ m_commandLineArguments(source->m_commandLineArguments),
+ m_validParse(source->m_validParse)
{
ctor();
}
@@ -134,12 +130,35 @@ void S60DeviceRunConfiguration::ctor()
else
//: S60 device runconfiguration default display name (no profile set)
setDefaultDisplayName(tr("Run on Symbian device"));
+
+ Qt4Project *pro = qt4Target()->qt4Project();
+ connect(pro, SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode*,bool)),
+ this, SLOT(proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode*,bool)));
+ connect(pro, SIGNAL(proFileInvalidated(Qt4ProjectManager::Internal::Qt4ProFileNode *)),
+ this, SLOT(proFileInvalidated(Qt4ProjectManager::Internal::Qt4ProFileNode *)));
+}
+
+void S60DeviceRunConfiguration::handleParserState(bool success)
+{
+ bool enabled = isEnabled();
+ m_validParse = success;
+ if (enabled != isEnabled())
+ emit isEnabledChanged(!enabled);
}
-void S60DeviceRunConfiguration::proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode *pro)
+void S60DeviceRunConfiguration::proFileInvalidated(Qt4ProjectManager::Internal::Qt4ProFileNode *pro)
{
- if (m_proFilePath == pro->path())
- emit targetInformationChanged();
+ if (m_proFilePath != pro->path())
+ return;
+ handleParserState(false);
+}
+
+void S60DeviceRunConfiguration::proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode *pro, bool success)
+{
+ if (m_proFilePath != pro->path())
+ return;
+ handleParserState(success);
+ emit targetInformationChanged();
}
S60DeviceRunConfiguration::~S60DeviceRunConfiguration()
@@ -151,30 +170,34 @@ Qt4Target *S60DeviceRunConfiguration::qt4Target() const
return static_cast<Qt4Target *>(target());
}
-ProjectExplorer::ToolChain::ToolChainType S60DeviceRunConfiguration::toolChainType(
+ProjectExplorer::ToolChainType S60DeviceRunConfiguration::toolChainType(
ProjectExplorer::BuildConfiguration *configuration) const
{
if (Qt4BuildConfiguration *bc = qobject_cast<Qt4BuildConfiguration *>(configuration))
return bc->toolChainType();
- return ProjectExplorer::ToolChain::INVALID;
+ return ProjectExplorer::ToolChain_INVALID;
}
-ProjectExplorer::ToolChain::ToolChainType S60DeviceRunConfiguration::toolChainType() const
+ProjectExplorer::ToolChainType S60DeviceRunConfiguration::toolChainType() const
{
if (Qt4BuildConfiguration *bc = qobject_cast<Qt4BuildConfiguration *>(target()->activeBuildConfiguration()))
return bc->toolChainType();
- return ProjectExplorer::ToolChain::INVALID;
+ return ProjectExplorer::ToolChain_INVALID;
}
bool S60DeviceRunConfiguration::isEnabled(ProjectExplorer::BuildConfiguration *configuration) const
{
+ if (!m_validParse)
+ return false;
const Qt4BuildConfiguration *qt4bc = static_cast<const Qt4BuildConfiguration *>(configuration);
switch (qt4bc->toolChainType()) {
- case ToolChain::GCCE:
- case ToolChain::RVCT_ARMV5:
- case ToolChain::RVCT_ARMV6:
- case ToolChain::GCCE_GNUPOC:
- case ToolChain::RVCT_ARMV5_GNUPOC:
+ case ProjectExplorer::ToolChain_GCCE:
+ case ProjectExplorer::ToolChain_RVCT2_ARMV5:
+ case ProjectExplorer::ToolChain_RVCT2_ARMV6:
+ case ProjectExplorer::ToolChain_RVCT4_ARMV5:
+ case ProjectExplorer::ToolChain_RVCT4_ARMV6:
+ case ProjectExplorer::ToolChain_GCCE_GNUPOC:
+ case ProjectExplorer::ToolChain_RVCT_ARMV5_GNUPOC:
return true;
default:
break;
@@ -208,12 +231,15 @@ bool S60DeviceRunConfiguration::fromMap(const QVariantMap &map)
const QDir projectDir = QDir(target()->project()->projectDirectory());
m_proFilePath = projectDir.filePath(map.value(QLatin1String(PRO_FILE_KEY)).toString());
- m_commandLineArguments = map.value(QLatin1String(COMMAND_LINE_ARGUMENTS_KEY)).toStringList();
+ m_commandLineArguments = map.value(QLatin1String(COMMAND_LINE_ARGUMENTS_KEY)).toString();
if (m_proFilePath.isEmpty())
return false;
if (!QFileInfo(m_proFilePath).exists())
return false;
+
+ m_validParse = qt4Target()->qt4Project()->validParse(m_proFilePath);
+
setDefaultDisplayName(tr("%1 on Symbian Device").arg(QFileInfo(m_proFilePath).completeBaseName()));
return RunConfiguration::fromMap(map);
@@ -255,13 +281,14 @@ QString S60DeviceRunConfiguration::symbianTarget() const
return isDebug() ? QLatin1String("udeb") : QLatin1String("urel");
}
-static inline QString symbianPlatformForToolChain(ProjectExplorer::ToolChain::ToolChainType t)
+static inline QString symbianPlatformForToolChain(ProjectExplorer::ToolChainType t)
{
switch (t) {
- case ProjectExplorer::ToolChain::GCCE:
- case ProjectExplorer::ToolChain::GCCE_GNUPOC:
+ case ProjectExplorer::ToolChain_GCCE:
+ case ProjectExplorer::ToolChain_GCCE_GNUPOC:
return QLatin1String("gcce");
- case ProjectExplorer::ToolChain::RVCT_ARMV5:
+ case ProjectExplorer::ToolChain_RVCT2_ARMV5:
+ case ProjectExplorer::ToolChain_RVCT4_ARMV5:
return QLatin1String("armv5");
default: // including ProjectExplorer::RVCT_ARMV6_GNUPOC:
break;
@@ -269,7 +296,7 @@ static inline QString symbianPlatformForToolChain(ProjectExplorer::ToolChain::To
return QLatin1String("armv6");
}
-/* Grep a package file for the '.exe' file. Curently for use on Linux only
+/* Grep a package file for the '.exe' file. Currently for use on Linux only
* as the '.pkg'-files on Windows do not contain drive letters, which is not
* handled here. \code
; Executable and default resource files
@@ -301,41 +328,40 @@ static inline QString executableFromPackageUnix(const QString &packageFileName)
static inline QString localExecutableFromDevice(const QtVersion *qtv,
const QString &symbianTarget, /* udeb/urel */
const QString &targetName,
- ProjectExplorer::ToolChain::ToolChainType t)
+ ProjectExplorer::ToolChainType t)
{
QTC_ASSERT(qtv, return QString(); )
- const S60Devices::Device device = S60Manager::instance()->deviceForQtVersion(qtv);
+ const S60Devices::Device device = S60Manager::instance()->deviceForQtVersion(qtv);
QString localExecutable;
QTextStream(&localExecutable) << device.epocRoot << "/epoc32/release/"
- << symbianPlatformForToolChain(t)
- << '/' << symbianTarget << '/' << targetName
- << ".exe";
+ << symbianPlatformForToolChain(t)
+ << '/' << symbianTarget << '/' << targetName
+ << ".exe";
return localExecutable;
}
QString S60DeviceRunConfiguration::localExecutableFileName() const
{
- const ProjectExplorer::ToolChain::ToolChainType toolChain = toolChainType();
+ const ProjectExplorer::ToolChainType toolChain = toolChainType();
switch (toolChain) {
- case ToolChain::GCCE_GNUPOC:
- case ToolChain::RVCT_ARMV5_GNUPOC: {
+ case ProjectExplorer::ToolChain_GCCE_GNUPOC:
+ case ProjectExplorer::ToolChain_RVCT_ARMV5_GNUPOC: {
TargetInformation ti = qt4Target()->qt4Project()->rootProjectNode()->targetInformation(projectFilePath());
if (!ti.valid)
return QString();
return executableFromPackageUnix(ti.buildDir + QLatin1Char('/') + ti.target + QLatin1String("_template.pkg"));
}
- break;
- case ProjectExplorer::ToolChain::RVCT_ARMV5:
- case ProjectExplorer::ToolChain::RVCT_ARMV6:
+ case ProjectExplorer::ToolChain_RVCT2_ARMV5:
+ case ProjectExplorer::ToolChain_RVCT2_ARMV6:
return localExecutableFromDevice(qtVersion(), symbianTarget(), targetName(), toolChain);
break;
- case ProjectExplorer::ToolChain::GCCE: {
- // As of 4.7.0, qmake-gcce-Raptor builds were changed to put all executables into 'armv5'
+ case ProjectExplorer::ToolChain_GCCE: {
+ // As of 4.7.1, qmake-gcce-Raptor builds were changed to put all executables into 'armv5'
const QtVersion *qtv = qtVersion();
QTC_ASSERT(qtv, return QString(); )
return qtv->isBuildWithSymbianSbsV2() ?
- localExecutableFromDevice(qtv, symbianTarget(), targetName(), ProjectExplorer::ToolChain::RVCT_ARMV5) :
+ localExecutableFromDevice(qtv, symbianTarget(), targetName(), ProjectExplorer::ToolChain_RVCT2_ARMV5) :
localExecutableFromDevice(qtv, symbianTarget(), targetName(), toolChain);
}
break;
@@ -371,12 +397,12 @@ QString S60DeviceRunConfiguration::projectFilePath() const
return m_proFilePath;
}
-QStringList S60DeviceRunConfiguration::commandLineArguments() const
+QString S60DeviceRunConfiguration::commandLineArguments() const
{
return m_commandLineArguments;
}
-void S60DeviceRunConfiguration::setCommandLineArguments(const QStringList &args)
+void S60DeviceRunConfiguration::setCommandLineArguments(const QString &args)
{
m_commandLineArguments = args;
}
@@ -470,8 +496,7 @@ RunConfiguration *S60DeviceRunConfigurationFactory::clone(Target *parent, RunCon
S60DeviceRunControl::S60DeviceRunControl(RunConfiguration *runConfiguration, QString mode) :
RunControl(runConfiguration, mode),
- m_toolChain(ProjectExplorer::ToolChain::INVALID),
- m_handleDeviceRemoval(true),
+ m_toolChain(ProjectExplorer::ToolChain_INVALID),
m_launcher(0)
{
// connect for automatically reporting the "finished deploy" state to the progress manager
@@ -518,7 +543,7 @@ void S60DeviceRunControl::start()
emit started();
if (m_serialPortName.isEmpty()) {
m_launchProgress->reportCanceled();
- appendMessage(this, tr("There is no device plugged in."), true);
+ appendMessage(this, tr("No device is connected. Please connect a device and try again."), true);
emit finished();
return;
}
@@ -609,7 +634,6 @@ void S60DeviceRunControl::printConnectFailed(const QString &errorMessage)
void S60DeviceRunControl::launcherFinished()
{
- m_handleDeviceRemoval = false;
trk::Launcher::releaseToDeviceManager(m_launcher);
m_launcher->deleteLater();
m_launcher = 0;
@@ -675,7 +699,10 @@ void S60DeviceRunControl::printApplicationOutput(const QString &output, bool onS
void S60DeviceRunControl::deviceRemoved(const SymbianUtils::SymbianDevice &d)
{
- if (m_handleDeviceRemoval && d.portName() == m_serialPortName) {
+ if (m_launcher && d.portName() == m_serialPortName) {
+ trk::Launcher::releaseToDeviceManager(m_launcher);
+ m_launcher->deleteLater();
+ m_launcher = 0;
appendMessage(this, tr("The device '%1' has been disconnected").arg(d.friendlyName()), true);
emit finished();
}
@@ -785,7 +812,6 @@ S60DeviceDebugRunControl::S60DeviceDebugRunControl(S60DeviceRunConfiguration *rc
arg(localExecutable(rc));
emit appendMessage(this, msg, true);
}
- connect(this, SIGNAL(finished()), this, SLOT(slotFinished()));
}
void S60DeviceDebugRunControl::start()
@@ -802,13 +828,6 @@ void S60DeviceDebugRunControl::start()
settingsCategory, settingsPage);
return;
}
- m_debugProgress.reset(new QFutureInterface<void>);
- Core::ICore::instance()->progressManager()->addTask(m_debugProgress->future(),
- tr("Debugging"),
- QLatin1String("Symbian.Debug"));
- m_debugProgress->setProgressRange(0, PROGRESS_MAX);
- m_debugProgress->setProgressValue(0);
- m_debugProgress->reportStarted();
emit appendMessage(this, tr("Launching debugger..."), false);
Debugger::DebuggerRunControl::start();
@@ -817,21 +836,3 @@ void S60DeviceDebugRunControl::start()
S60DeviceDebugRunControl::~S60DeviceDebugRunControl()
{
}
-
-RunControl::StopResult S60DeviceDebugRunControl::stop()
-{
- if (!m_debugProgress.isNull()) {
- m_debugProgress->reportCanceled();
- m_debugProgress.reset();
- }
- return Debugger::DebuggerRunControl::stop();
-}
-
-void S60DeviceDebugRunControl::slotFinished()
-{
- if (!m_debugProgress.isNull()) {
- m_debugProgress->setProgressValue(PROGRESS_MAX);
- m_debugProgress->reportFinished();
- m_debugProgress.reset();
- }
-}
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h
index dbcd252de6..bf052ea1d1 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h
+++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h
@@ -34,37 +34,33 @@
#ifndef S60DEVICERUNCONFIGURATION_H
#define S60DEVICERUNCONFIGURATION_H
-#include "launcher.h"
-
#include <debugger/debuggerrunner.h>
#include <projectexplorer/runconfiguration.h>
-#include <projectexplorer/toolchain.h>
+#include <projectexplorer/toolchaintype.h>
-#include <QtCore/QProcess>
#include <QtCore/QFutureInterface>
-#include <QtCore/QSharedPointer>
#include <QtCore/QScopedPointer>
+#include <QtCore/QStringList>
QT_BEGIN_NAMESPACE
class QMessageBox;
class QWidget;
QT_END_NAMESPACE
-namespace Debugger {
-class DebuggerStartParameters;
-class DebuggerRunControl;
-}
-
namespace SymbianUtils {
class SymbianDevice;
}
+namespace trk {
+class Launcher;
+}
+
namespace Qt4ProjectManager {
class QtVersion;
+class Qt4Target;
namespace Internal {
class Qt4ProFileNode;
-class Qt4Target;
class S60DeviceRunConfigurationFactory;
class S60DeviceRunConfiguration : public ProjectExplorer::RunConfiguration
@@ -73,23 +69,24 @@ class S60DeviceRunConfiguration : public ProjectExplorer::RunConfiguration
friend class S60DeviceRunConfigurationFactory;
public:
- S60DeviceRunConfiguration(ProjectExplorer::Target *parent, const QString &proFilePath);
+ S60DeviceRunConfiguration(Qt4ProjectManager::Qt4Target *parent, const QString &proFilePath);
virtual ~S60DeviceRunConfiguration();
Qt4Target *qt4Target() const;
const QtVersion *qtVersion() const;
+ using ProjectExplorer::RunConfiguration::isEnabled;
bool isEnabled(ProjectExplorer::BuildConfiguration *configuration) const;
QWidget *createConfigurationWidget();
ProjectExplorer::OutputFormatter *createOutputFormatter() const;
- QStringList commandLineArguments() const;
- void setCommandLineArguments(const QStringList &args);
+ QString commandLineArguments() const;
+ void setCommandLineArguments(const QString &args);
QString projectFilePath() const;
- ProjectExplorer::ToolChain::ToolChainType toolChainType() const;
+ ProjectExplorer::ToolChainType toolChainType() const;
QString targetName() const;
QString localExecutableFileName() const;
@@ -100,22 +97,25 @@ public:
QVariantMap toMap() const;
- void proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode *pro);
-
signals:
void targetInformationChanged();
protected:
- S60DeviceRunConfiguration(ProjectExplorer::Target *parent, S60DeviceRunConfiguration *source);
+ S60DeviceRunConfiguration(Qt4ProjectManager::Qt4Target *parent, S60DeviceRunConfiguration *source);
QString defaultDisplayName() const;
virtual bool fromMap(const QVariantMap &map);
+private slots:
+ void proFileInvalidated(Qt4ProjectManager::Internal::Qt4ProFileNode *pro);
+ void proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode *pro, bool success);
private:
- ProjectExplorer::ToolChain::ToolChainType toolChainType(ProjectExplorer::BuildConfiguration *configuration) const;
+ ProjectExplorer::ToolChainType toolChainType(ProjectExplorer::BuildConfiguration *configuration) const;
void ctor();
+ void handleParserState(bool sucess);
QString m_proFilePath;
- QStringList m_commandLineArguments;
+ QString m_commandLineArguments;
+ bool m_validParse;
};
class S60DeviceRunConfigurationFactory : public ProjectExplorer::IRunConfigurationFactory
@@ -182,15 +182,14 @@ private:
void startLaunching();
bool setupLauncher(QString &errorMessage);
- ProjectExplorer::ToolChain::ToolChainType m_toolChain;
+ ProjectExplorer::ToolChainType m_toolChain;
QString m_serialPortName;
QString m_serialPortFriendlyName;
QString m_targetName;
- QStringList m_commandLineArguments;
+ QString m_commandLineArguments;
QString m_executableFileName;
QString m_qtDir;
QString m_qtBinPath;
- bool m_handleDeviceRemoval;
trk::Launcher *m_launcher;
char m_installationDrive;
};
@@ -206,15 +205,9 @@ public:
const QString &mode);
virtual ~S60DeviceDebugRunControl();
virtual void start();
- virtual StopResult stop();
-
-private slots:
- void slotFinished();
private:
static Debugger::DebuggerStartParameters s60DebuggerStartParams(const S60DeviceRunConfiguration *rc);
-
- QScopedPointer<QFutureInterface<void> > m_debugProgress;
};
} // namespace Internal
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp
index 4148dc534b..8c18937d67 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp
@@ -36,16 +36,10 @@
#include <utils/detailswidget.h>
-#include <QtGui/QLabel>
#include <QtGui/QLineEdit>
#include <QtGui/QVBoxLayout>
#include <QtGui/QHBoxLayout>
#include <QtGui/QFormLayout>
-#include <QtGui/QStyle>
-#include <QtGui/QApplication>
-#include <QtGui/QSpacerItem>
-#include <QtGui/QMainWindow>
-#include <QtGui/QMessageBox>
namespace Qt4ProjectManager {
namespace Internal {
@@ -56,7 +50,7 @@ S60DeviceRunConfigurationWidget::S60DeviceRunConfigurationWidget(
: QWidget(parent),
m_runConfiguration(runConfiguration),
m_detailsWidget(new Utils::DetailsWidget),
- m_argumentsLineEdit(new QLineEdit(m_runConfiguration->commandLineArguments().join(QString(QLatin1Char(' ')))))
+ m_argumentsLineEdit(new QLineEdit(m_runConfiguration->commandLineArguments()))
{
m_detailsWidget->setState(Utils::DetailsWidget::NoSummary);
QVBoxLayout *mainBoxLayout = new QVBoxLayout();
@@ -77,17 +71,21 @@ S60DeviceRunConfigurationWidget::S60DeviceRunConfigurationWidget(
connect(m_argumentsLineEdit, SIGNAL(textEdited(QString)),
this, SLOT(argumentsEdited(QString)));
+
+ connect(m_runConfiguration, SIGNAL(isEnabledChanged(bool)),
+ this, SLOT(runConfigurationEnabledChange(bool)));
+
+ setEnabled(m_runConfiguration->isEnabled());
}
void S60DeviceRunConfigurationWidget::argumentsEdited(const QString &text)
{
- const QString trimmed = text.trimmed();
- if (trimmed.isEmpty()) {
- m_runConfiguration->setCommandLineArguments(QStringList());
- } else {
- m_runConfiguration->setCommandLineArguments(trimmed.split(QLatin1Char(' '),
- QString::SkipEmptyParts));
- }
+ m_runConfiguration->setCommandLineArguments(text.trimmed());
+}
+
+void S60DeviceRunConfigurationWidget::runConfigurationEnabledChange(bool enabled)
+{
+ setEnabled(enabled);
}
} // namespace Internal
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.h b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.h
index 49f579ce26..d37361fff3 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.h
+++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.h
@@ -54,10 +54,10 @@ class S60DeviceRunConfigurationWidget : public QWidget
Q_OBJECT
public:
explicit S60DeviceRunConfigurationWidget(S60DeviceRunConfiguration *runConfiguration,
- QWidget *parent = 0);
-
+ QWidget *parent = 0);
private slots:
void argumentsEdited(const QString &text);
+ void runConfigurationEnabledChange(bool enabled);
private:
S60DeviceRunConfiguration *m_runConfiguration;
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devices.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devices.cpp
index 2c16152158..7829f758c7 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60devices.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/s60devices.cpp
@@ -32,7 +32,6 @@
**************************************************************************/
#include "s60devices.h"
-#include "gccetoolchain.h"
#include <utils/environment.h>
@@ -559,10 +558,12 @@ void S60ToolChainMixin::addEpocToEnvironment(Utils::Environment *env) const
if (epocDir.exists(QLatin1String("epoc32/gcc/bin")))
env->prependOrSetPath(epocDir.filePath(QLatin1String("epoc32/gcc/bin"))); // e.g. cpp.exe, *NOT* gcc.exe
// Find perl in the special Symbian flavour:
- if (epocDir.exists(QLatin1String("../../tools/perl/bin")))
- env->prependOrSetPath(epocDir.filePath(QLatin1String("../../tools/perl/bin")));
- else
+ if (epocDir.exists(QLatin1String("../../tools/perl/bin"))) {
+ epocDir.cd(QLatin1String("../../tools/perl/bin"));
+ env->prependOrSetPath(epocDir.absolutePath());
+ } else {
env->prependOrSetPath(epocDir.filePath(QLatin1String("perl/bin")));
+ }
addBaseToEnvironment(env);
}
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicespreferencepane.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicespreferencepane.cpp
index 9d7a557cdb..b4b672e778 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60devicespreferencepane.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/s60devicespreferencepane.cpp
@@ -33,7 +33,6 @@
#include "s60devicespreferencepane.h"
#include "ui_s60devicespreferencepane.h"
-#include "s60devices.h"
#include <qt4projectmanager/qt4projectmanagerconstants.h>
@@ -416,7 +415,8 @@ QWidget *S60DevicesPreferencePane::createPage(QWidget *parent)
void S60DevicesPreferencePane::apply()
{
- QTC_ASSERT(m_widget, return)
+ if (!m_widget) // page was never shown
+ return;
m_devices->setDevices(m_widget->devices());
}
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.cpp
index 2a9514b514..1d04d69130 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.cpp
@@ -35,25 +35,15 @@
#include "qt4project.h"
#include "qt4target.h"
-#include "qtversionmanager.h"
-#include "profilereader.h"
#include "s60manager.h"
-#include "s60devices.h"
-#include "qt4buildconfiguration.h"
#include "qt4projectmanagerconstants.h"
#include "qtoutputformatter.h"
-#include <coreplugin/icore.h>
-#include <coreplugin/messagemanager.h>
#include <utils/qtcassert.h>
#include <utils/detailswidget.h>
-#include <projectexplorer/projectexplorerconstants.h>
-#include <projectexplorer/project.h>
-#include <projectexplorer/persistentsettings.h>
#include <QtGui/QLabel>
#include <QtGui/QVBoxLayout>
-#include <QtGui/QLineEdit>
#include <QtGui/QFormLayout>
using namespace ProjectExplorer;
@@ -82,16 +72,18 @@ QString pathToId(const QString &path)
// ======== S60EmulatorRunConfiguration
-S60EmulatorRunConfiguration::S60EmulatorRunConfiguration(Target *parent, const QString &proFilePath) :
+S60EmulatorRunConfiguration::S60EmulatorRunConfiguration(Qt4Target *parent, const QString &proFilePath) :
RunConfiguration(parent, QLatin1String(S60_EMULATOR_RC_ID)),
- m_proFilePath(proFilePath)
+ m_proFilePath(proFilePath),
+ m_validParse(parent->qt4Project()->validParse(proFilePath))
{
ctor();
}
-S60EmulatorRunConfiguration::S60EmulatorRunConfiguration(Target *parent, S60EmulatorRunConfiguration *source) :
+S60EmulatorRunConfiguration::S60EmulatorRunConfiguration(Qt4Target *parent, S60EmulatorRunConfiguration *source) :
RunConfiguration(parent, source),
- m_proFilePath(source->m_proFilePath)
+ m_proFilePath(source->m_proFilePath),
+ m_validParse(source->m_validParse)
{
ctor();
}
@@ -104,8 +96,11 @@ void S60EmulatorRunConfiguration::ctor()
else
//: S60 emulator run configuration default display name (no pro-file name)
setDefaultDisplayName(tr("Run on Symbian Emulator"));
- connect(qt4Target()->qt4Project(), SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode*)),
- this, SLOT(proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode*)));
+ Qt4Project *pro = qt4Target()->qt4Project();
+ connect(pro, SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode*,bool)),
+ this, SLOT(proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode*,bool)));
+ connect(pro, SIGNAL(proFileInvalidated(Qt4ProjectManager::Internal::Qt4ProFileNode *)),
+ this, SLOT(proFileInvalidated(Qt4ProjectManager::Internal::Qt4ProFileNode *)));
}
@@ -113,10 +108,28 @@ S60EmulatorRunConfiguration::~S60EmulatorRunConfiguration()
{
}
-void S60EmulatorRunConfiguration::proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode *pro)
+void S60EmulatorRunConfiguration::handleParserState(bool success)
{
- if (m_proFilePath == pro->path())
- emit targetInformationChanged();
+ bool enabled = isEnabled();
+ m_validParse = success;
+ if (enabled != isEnabled()) {
+ emit isEnabledChanged(!enabled);
+ }
+}
+
+void S60EmulatorRunConfiguration::proFileInvalidated(Qt4ProjectManager::Internal::Qt4ProFileNode *pro)
+{
+ if (m_proFilePath != pro->path())
+ return;
+ handleParserState(false);
+}
+
+void S60EmulatorRunConfiguration::proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode *pro, bool success)
+{
+ if (m_proFilePath != pro->path())
+ return;
+ handleParserState(success);
+ emit targetInformationChanged();
}
Qt4Target *S60EmulatorRunConfiguration::qt4Target() const
@@ -126,10 +139,12 @@ Qt4Target *S60EmulatorRunConfiguration::qt4Target() const
bool S60EmulatorRunConfiguration::isEnabled(ProjectExplorer::BuildConfiguration *configuration) const
{
+ if (!m_validParse)
+ return false;
Qt4BuildConfiguration *qt4bc = qobject_cast<Qt4BuildConfiguration *>(configuration);
QTC_ASSERT(qt4bc, return false);
- ToolChain::ToolChainType type = qt4bc->toolChainType();
- return type == ToolChain::WINSCW;
+ const ProjectExplorer::ToolChainType type = qt4bc->toolChainType();
+ return type == ProjectExplorer::ToolChain_WINSCW;
}
QWidget *S60EmulatorRunConfiguration::createConfigurationWidget()
@@ -157,6 +172,9 @@ bool S60EmulatorRunConfiguration::fromMap(const QVariantMap &map)
if (m_proFilePath.isEmpty())
return false;
+
+ m_validParse = qt4Target()->qt4Project()->validParse(m_proFilePath);
+
//: S60 emulator run configuration default display name, %1 is base pro-File name
setDefaultDisplayName(tr("%1 in Symbian Emulator").arg(QFileInfo(m_proFilePath).completeBaseName()));
@@ -207,6 +225,11 @@ S60EmulatorRunConfigurationWidget::S60EmulatorRunConfigurationWidget(S60Emulator
connect(m_runConfiguration, SIGNAL(targetInformationChanged()),
this, SLOT(updateTargetInformation()));
+
+ connect(m_runConfiguration, SIGNAL(isEnabledChanged(bool)),
+ this, SLOT(runConfigurationEnabledChange(bool)));
+
+ setEnabled(m_runConfiguration->isEnabled());
}
void S60EmulatorRunConfigurationWidget::updateTargetInformation()
@@ -214,6 +237,11 @@ void S60EmulatorRunConfigurationWidget::updateTargetInformation()
m_executableLabel->setText(m_runConfiguration->executable());
}
+void S60EmulatorRunConfigurationWidget::runConfigurationEnabledChange(bool enabled)
+{
+ setEnabled(enabled);
+}
+
// ======== S60EmulatorRunConfigurationFactory
S60EmulatorRunConfigurationFactory::S60EmulatorRunConfigurationFactory(QObject *parent)
@@ -302,7 +330,7 @@ S60EmulatorRunControl::S60EmulatorRunControl(S60EmulatorRunConfiguration *runCon
// stuff like the EPOCROOT and EPOCDEVICE env variable
Utils::Environment env = Utils::Environment::systemEnvironment();
runConfiguration->qt4Target()->activeBuildConfiguration()->toolChain()->addToEnvironment(env);
- m_applicationLauncher.setEnvironment(env.toStringList());
+ m_applicationLauncher.setEnvironment(env);
m_executable = runConfiguration->executable();
connect(&m_applicationLauncher, SIGNAL(applicationError(QString)),
@@ -317,7 +345,7 @@ S60EmulatorRunControl::S60EmulatorRunControl(S60EmulatorRunConfiguration *runCon
void S60EmulatorRunControl::start()
{
- m_applicationLauncher.start(ApplicationLauncher::Gui, m_executable, QStringList());
+ m_applicationLauncher.start(ApplicationLauncher::Gui, m_executable, QString());
emit started();
emit appendMessage(this, tr("Starting %1...").arg(QDir::toNativeSeparators(m_executable)), false);
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.h b/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.h
index aa53fa163d..b1ab903469 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.h
+++ b/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.h
@@ -51,10 +51,10 @@ class DetailsWidget;
namespace Qt4ProjectManager {
class Qt4Project;
+class Qt4Target;
namespace Internal {
class Qt4ProFileNode;
-class Qt4Target;
class S60EmulatorRunConfigurationFactory;
class S60EmulatorRunConfiguration : public ProjectExplorer::RunConfiguration
@@ -63,11 +63,12 @@ class S60EmulatorRunConfiguration : public ProjectExplorer::RunConfiguration
friend class S60EmulatorRunConfigurationFactory;
public:
- S60EmulatorRunConfiguration(ProjectExplorer::Target *parent, const QString &proFilePath);
+ S60EmulatorRunConfiguration(Qt4ProjectManager::Qt4Target *parent, const QString &proFilePath);
virtual ~S60EmulatorRunConfiguration();
Qt4Target *qt4Target() const;
+ using ProjectExplorer::RunConfiguration::isEnabled;
bool isEnabled(ProjectExplorer::BuildConfiguration *configuration) const;
QWidget *createConfigurationWidget();
@@ -81,17 +82,20 @@ signals:
void targetInformationChanged();
private slots:
- void proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode *pro);
+ void proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode *pro, bool success);
+ void proFileInvalidated(Qt4ProjectManager::Internal::Qt4ProFileNode *pro);
protected:
- S60EmulatorRunConfiguration(ProjectExplorer::Target *parent, S60EmulatorRunConfiguration *source);
+ S60EmulatorRunConfiguration(Qt4ProjectManager::Qt4Target *parent, S60EmulatorRunConfiguration *source);
virtual bool fromMap(const QVariantMap &map);
private:
void ctor();
+ void handleParserState(bool sucess);
void updateTarget();
QString m_proFilePath;
+ bool m_validParse;
};
class S60EmulatorRunConfigurationWidget : public QWidget
@@ -103,6 +107,7 @@ public:
private slots:
void updateTargetInformation();
+ void runConfigurationEnabledChange(bool enabled);
private:
S60EmulatorRunConfiguration *m_runConfiguration;
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60manager.cpp b/src/plugins/qt4projectmanager/qt-s60/s60manager.cpp
index b7c6bec538..ced7efa170 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60manager.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/s60manager.cpp
@@ -35,7 +35,6 @@
#include "qtversionmanager.h"
#include "s60devicespreferencepane.h"
-#include "symbiandevicemanager.h"
#include "winscwtoolchain.h"
#include "gccetoolchain.h"
#include "rvcttoolchain.h"
@@ -44,17 +43,16 @@
#include "s60createpackagestep.h"
#include "s60deploystep.h"
+#include <symbianutils/symbiandevicemanager.h>
+
#include <coreplugin/icore.h>
#include <extensionsystem/pluginmanager.h>
#include <projectexplorer/projectexplorerconstants.h>
-#include <projectexplorer/toolchain.h>
-#include <debugger/debuggerplugin.h>
#include <utils/qtcassert.h>
#include <QtGui/QMainWindow>
#include <QtCore/QDir>
-#include <QtCore/QFileInfo>
namespace {
const char S60_AUTODETECTION_SOURCE[] = "QTS60";
@@ -127,11 +125,10 @@ S60Manager::S60Manager(QObject *parent)
addAutoReleasedObject(new S60CreatePackageStepFactory);
addAutoReleasedObject(new S60DeployStepFactory);
- if (Debugger::DebuggerPlugin::instance())
- addAutoReleasedObject(new RunControlFactory<S60DeviceDebugRunControl,
- S60DeviceRunConfiguration>
- (QLatin1String(ProjectExplorer::Constants::DEBUGMODE),
- tr("Debug on Device"), parent));
+ addAutoReleasedObject(new RunControlFactory<S60DeviceDebugRunControl,
+ S60DeviceRunConfiguration>
+ (QLatin1String(Debugger::Constants::DEBUGMODE),
+ tr("Debug on Device"), parent));
updateQtVersions();
connect(m_devices, SIGNAL(qtVersionsChanged()),
this, SLOT(updateQtVersions()));
@@ -148,9 +145,14 @@ S60Manager::~S60Manager()
}
}
-bool S60Manager::hasRvctCompiler()
+bool S60Manager::hasRvct2Compiler()
+{
+ return RVCT2ToolChain::configuredRvctVersions().contains(qMakePair(2, 2));
+}
+
+bool S60Manager::hasRvct4Compiler()
{
- return !RVCTToolChain::rvctBinEnvironmentVariable().isEmpty();
+ return RVCT2ToolChain::configuredRvctVersions().contains(qMakePair(2, 2));
}
void S60Manager::addAutoReleasedObject(QObject *o)
@@ -230,21 +232,28 @@ ProjectExplorer::ToolChain *S60Manager::createWINSCWToolChain(const Qt4ProjectMa
ProjectExplorer::ToolChain *S60Manager::createGCCEToolChain(const Qt4ProjectManager::QtVersion *version) const
{
Q_ASSERT(version);
- return GCCEToolChain::create(deviceForQtVersion(version), version->gcceDirectory(), ProjectExplorer::ToolChain::GCCE);
+ return GCCEToolChain::create(deviceForQtVersion(version), version->gcceDirectory(), ProjectExplorer::ToolChain_GCCE);
}
ProjectExplorer::ToolChain *S60Manager::createGCCE_GnuPocToolChain(const Qt4ProjectManager::QtVersion *version) const
{
Q_ASSERT(version);
- return GCCEToolChain::create(deviceForQtVersion(version), version->gcceDirectory(), ProjectExplorer::ToolChain::GCCE_GNUPOC);
+ return GCCEToolChain::create(deviceForQtVersion(version), version->gcceDirectory(), ProjectExplorer::ToolChain_GCCE_GNUPOC);
}
ProjectExplorer::ToolChain *S60Manager::createRVCTToolChain(
const Qt4ProjectManager::QtVersion *version,
- ProjectExplorer::ToolChain::ToolChainType type) const
+ ProjectExplorer::ToolChainType type) const
{
Q_ASSERT(version);
- return new RVCTToolChain(deviceForQtVersion(version), type);
+ if (type == ProjectExplorer::ToolChain_RVCT2_ARMV5
+ || type == ProjectExplorer::ToolChain_RVCT2_ARMV6
+ || type == ProjectExplorer::ToolChain_RVCT_ARMV5_GNUPOC)
+ return new RVCT2ToolChain(deviceForQtVersion(version), type);
+ if (type == ProjectExplorer::ToolChain_RVCT4_ARMV5
+ || type == ProjectExplorer::ToolChain_RVCT4_ARMV6)
+ return new RVCT4ToolChain(deviceForQtVersion(version), type);
+ return 0;
}
S60Devices::Device S60Manager::deviceForQtVersion(const Qt4ProjectManager::QtVersion *version) const
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60manager.h b/src/plugins/qt4projectmanager/qt-s60/s60manager.h
index f4dee26143..d7e2411eb4 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60manager.h
+++ b/src/plugins/qt4projectmanager/qt-s60/s60manager.h
@@ -36,10 +36,14 @@
#include "s60devices.h"
-#include <projectexplorer/toolchain.h>
+#include <projectexplorer/toolchaintype.h>
#include <QtCore/QObject>
+namespace ProjectExplorer {
+class ToolChain;
+}
+
namespace Qt4ProjectManager {
class QtVersion;
namespace Internal {
@@ -57,13 +61,14 @@ public:
ProjectExplorer::ToolChain *createGCCEToolChain(const Qt4ProjectManager::QtVersion *version) const;
ProjectExplorer::ToolChain *createGCCE_GnuPocToolChain(const Qt4ProjectManager::QtVersion *version) const;
ProjectExplorer::ToolChain *createRVCTToolChain(const Qt4ProjectManager::QtVersion *version,
- ProjectExplorer::ToolChain::ToolChainType type) const;
+ ProjectExplorer::ToolChainType type) const;
S60Devices *devices() const { return m_devices; }
S60Devices::Device deviceForQtVersion(const Qt4ProjectManager::QtVersion *version) const;
QString deviceIdFromDetectionSource(const QString &autoDetectionSource) const;
- static bool hasRvctCompiler();
+ static bool hasRvct2Compiler();
+ static bool hasRvct4Compiler();
private slots:
void updateQtVersions();
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60projectchecker.cpp b/src/plugins/qt4projectmanager/qt-s60/s60projectchecker.cpp
index 65dbcf4915..a03799d1ac 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60projectchecker.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/s60projectchecker.cpp
@@ -36,7 +36,6 @@
#include <projectexplorer/projectexplorerconstants.h>
#include <qt4projectmanager/qt-s60/s60manager.h>
#include <qt4projectmanager/qt4project.h>
-#include <qt4projectmanager/qtversionmanager.h>
#include <QtCore/QCoreApplication>
@@ -72,16 +71,27 @@ S60ProjectChecker::reportIssues(const QString &proFile, const QtVersion *version
"The \"Open C/C++ plugin\" is not installed in the Symbian SDK or the Symbian SDK path is misconfigured for Qt version %1.").arg(version->displayName()),
QString(), -1, ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
}
- // Warn of strange characters in project name:
- QString projectPath = proFile;
+
+ // Warn of strange characters in project name and path:
+ const QString projectName = proFile.mid(proFile.lastIndexOf(QLatin1Char('/')) + 1);
+ QString projectPath = proFile.left(proFile.lastIndexOf(QLatin1Char('/')));
#if defined (Q_OS_WIN)
if (projectPath.at(1) == QChar(':') && projectPath.at(0).toUpper() >= QChar('A') && projectPath.at(0).toUpper() <= QChar('Z'))
projectPath = projectPath.mid(2);
#endif
- if (projectPath.contains(QRegExp("[^a-zA-Z0-9./]"))) {
+ if (projectPath.contains(QLatin1Char(' '))) {
+ results.append(Task(Task::Warning,
+ QCoreApplication::translate("ProjectExplorer::Internal::S60ProjectChecker",
+ "The Symbian toolchain does not handle spaces "
+ "in the project path '%1'.").arg(projectPath),
+ QString(), -1, ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
+ }
+ if (projectName.contains(QRegExp("[^a-zA-Z0-9.]"))) {
results.append(Task(Task::Warning,
QCoreApplication::translate("ProjectExplorer::Internal::S60ProjectChecker",
- "The Symbian toolchain does not handle special characters in a project path well."),
+ "The Symbian toolchain does not handle special "
+ "characters in the project name '%1' well.")
+ .arg(projectName),
QString(), -1, ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
}
return results;
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60runconfigbluetoothstarter.cpp b/src/plugins/qt4projectmanager/qt-s60/s60runconfigbluetoothstarter.cpp
index cec95b00bd..82fb7c1c1b 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60runconfigbluetoothstarter.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/s60runconfigbluetoothstarter.cpp
@@ -32,9 +32,9 @@
**************************************************************************/
#include "s60runconfigbluetoothstarter.h"
-#include "bluetoothlistener.h"
-#include "symbiandevicemanager.h"
-#include "trkdevice.h"
+#include <symbianutils/bluetoothlistener.h>
+#include <symbianutils/symbiandevicemanager.h>
+#include <symbianutils/trkdevice.h>
#include <coreplugin/icore.h>
#include <coreplugin/messagemanager.h>
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60runconfigbluetoothstarter.h b/src/plugins/qt4projectmanager/qt-s60/s60runconfigbluetoothstarter.h
index b9d008d75f..10cfb05fe6 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60runconfigbluetoothstarter.h
+++ b/src/plugins/qt4projectmanager/qt-s60/s60runconfigbluetoothstarter.h
@@ -34,8 +34,8 @@
#ifndef S60RUNCONFIGBLUETOOTHSTARTER_H
#define S60RUNCONFIGBLUETOOTHSTARTER_H
-#include "communicationstarter.h"
-#include "bluetoothlistener_gui.h"
+#include <symbianutils/communicationstarter.h>
+#include <symbianutils/bluetoothlistener_gui.h>
namespace Qt4ProjectManager {
namespace Internal {
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60symbiancertificate.cpp b/src/plugins/qt4projectmanager/qt-s60/s60symbiancertificate.cpp
new file mode 100644
index 0000000000..384f4394e9
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-s60/s60symbiancertificate.cpp
@@ -0,0 +1,848 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "s60symbiancertificate.h"
+
+#include <botan/x509_obj.h>
+#include <botan/x509_ext.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/stl_util.h>
+#include <botan/parsing.h>
+#include <botan/bigint.h>
+#include <botan/oids.h>
+#include <botan/pem.h>
+#include <botan/sha160.h>
+#include <botan/oids.h>
+#include <botan/libstate.h>
+#include <botan/bit_ops.h>
+#include <algorithm>
+#include <memory>
+
+using namespace Botan;
+using namespace Qt4ProjectManager;
+using namespace Qt4ProjectManager::Internal;
+
+namespace {
+ const char * const CERT_IMEI_FIELD_NAME = "1.2.826.0.1.1796587.1.1.1.1";
+ const char * const CERT_CAPABILITY_FIELD_NAME = "1.2.826.0.1.1796587.1.1.1.6";
+}
+
+// ======== S60CertificateExtension
+
+/*
+* X.509 S60 Certificate Extension
+*/
+class S60CertificateExtension : Certificate_Extension
+{
+public:
+ OID oid_of() const;
+
+ virtual S60CertificateExtension* copy() const = 0;
+ virtual ~S60CertificateExtension() {}
+protected:
+ friend class S60Extensions;
+ virtual bool should_encode() const { return false; }
+ virtual MemoryVector<byte> encode_inner() const = 0;
+ virtual void decode_inner(const MemoryRegion<byte>&) = 0;
+};
+
+// ======== S60DeviceIdListConstraint
+
+class S60DeviceIdListConstraint : public S60CertificateExtension
+{
+public:
+ S60CertificateExtension* copy() const { return new S60DeviceIdListConstraint(imei_list); }
+
+ S60DeviceIdListConstraint() {}
+ S60DeviceIdListConstraint(const std::vector<ASN1_String>& o) : imei_list(o) {}
+
+ std::vector<ASN1_String> get_imei_list() const { return imei_list; }
+private:
+ std::string config_id() const { return "deviceid_list_constraint"; }
+ std::string oid_name() const { return CERT_IMEI_FIELD_NAME; }
+
+ MemoryVector<byte> encode_inner() const;
+ void decode_inner(const MemoryRegion<byte>&);
+ void contents_to(Data_Store&, Data_Store&) const;
+
+ std::vector<ASN1_String> imei_list;
+};
+
+/*
+* Encode the extension
+*/
+MemoryVector<byte> S60DeviceIdListConstraint::encode_inner() const
+{
+ qFatal("Encoding S60 extensions is not supported.");
+ return MemoryVector<byte>();
+}
+
+/*
+* Decode the extension
+*/
+#include "botan/hex.h"
+void S60DeviceIdListConstraint::decode_inner(const MemoryRegion<byte>& in)
+{
+ BER_Decoder(in)
+ .start_cons(SEQUENCE)
+ .decode_list(imei_list)
+ .end_cons();
+}
+
+/*
+* Return a textual representation
+*/
+void S60DeviceIdListConstraint::contents_to(Data_Store& subject, Data_Store&) const
+{
+ for(u32bit j = 0; j != imei_list.size(); ++j)
+ subject.add(CERT_IMEI_FIELD_NAME, imei_list[j].value());
+}
+
+// ======== S60CapabilityConstraint
+
+class S60CapabilityConstraint : public S60CertificateExtension
+{
+public:
+ S60CertificateExtension* copy() const { return new S60CapabilityConstraint(capabilities); }
+
+ S60CapabilityConstraint() {}
+ S60CapabilityConstraint(const SecureVector<byte>& o) : capabilities(o) {}
+
+ SecureVector<byte> get_capability_list() const { return capabilities; }
+private:
+ std::string config_id() const { return "capability_constraint"; }
+ std::string oid_name() const { return "CERT_CAPABILITY_FIELD_NAME"; }
+
+ MemoryVector<byte> encode_inner() const;
+ void decode_inner(const MemoryRegion<byte>&);
+ void contents_to(Data_Store&, Data_Store&) const;
+
+ SecureVector<byte> capabilities;
+};
+
+/*
+* Encode the extension
+*/
+MemoryVector<byte> S60CapabilityConstraint::encode_inner() const
+{
+ qFatal("Encoding S60 extensions is not supported.");
+ return MemoryVector<byte>();
+}
+
+/*
+* Decode the extension
+*/
+void S60CapabilityConstraint::decode_inner(const MemoryRegion<byte>& in)
+{
+ BER_Decoder(in)
+ .decode(capabilities, BIT_STRING)
+ .verify_end();
+}
+
+/*
+* Return a textual representation
+*/
+void S60CapabilityConstraint::contents_to(Data_Store& subject, Data_Store&) const
+{
+ quint32 capabilitiesValue = 0;
+ for(u32bit j = 0; j != sizeof(quint32); ++j) {
+ quint32 capabilitie(capabilities[sizeof(quint32)-1-j]);
+ capabilitiesValue |= capabilitie << 8*j;
+ }
+ subject.add(CERT_CAPABILITY_FIELD_NAME, capabilitiesValue);
+}
+
+// ======== S60Extensions
+
+class S60Extensions : public ASN1_Object
+{
+public:
+ void encode_into(class DER_Encoder&) const;
+ void decode_from(class BER_Decoder&);
+
+ void contents_to(Data_Store&, Data_Store&) const;
+
+ void add(Certificate_Extension* extn)
+ { extensions.push_back(extn); }
+
+ S60Extensions& operator=(const S60Extensions&);
+
+ S60Extensions(const S60Extensions&);
+ S60Extensions(bool st = true) : should_throw(st) {}
+ ~S60Extensions();
+private:
+ static Certificate_Extension* get_extension(const OID&);
+
+ std::vector<Certificate_Extension*> extensions;
+ bool should_throw;
+};
+
+/*
+* S60Extensions Copy Constructor
+*/
+S60Extensions::S60Extensions(const S60Extensions& extensions) : ASN1_Object()
+{
+ *this = extensions;
+}
+
+/*
+* Extensions Assignment Operator
+*/
+S60Extensions& S60Extensions::operator=(const S60Extensions& other)
+{
+ for(u32bit j = 0; j != extensions.size(); ++j)
+ delete extensions[j];
+ extensions.clear();
+
+ for(u32bit j = 0; j != other.extensions.size(); ++j)
+ extensions.push_back(other.extensions[j]->copy());
+
+ return (*this);
+}
+
+/*
+* Return the OID of this extension
+*/
+OID Certificate_Extension::oid_of() const
+{
+ return OIDS::lookup(oid_name());
+}
+
+/*
+* Encode an Extensions list
+*/
+void S60Extensions::encode_into(DER_Encoder& to_object) const
+{
+ Q_UNUSED(to_object);
+ qFatal("Encoding S60 extensions is not supported.");
+}
+
+/*
+* Decode a list of Extensions
+*/
+void S60Extensions::decode_from(BER_Decoder& from_source)
+{
+ for(u32bit j = 0; j != extensions.size(); ++j)
+ delete extensions[j];
+ extensions.clear();
+
+ BER_Decoder sequence = from_source.start_cons(SEQUENCE);
+ while(sequence.more_items())
+ {
+ OID oid;
+ MemoryVector<byte> value;
+ bool critical;
+
+ sequence.start_cons(SEQUENCE)
+ .decode(oid)
+ .decode_optional(critical, BOOLEAN, UNIVERSAL, false)
+ .decode(value, OCTET_STRING)
+ .verify_end()
+ .end_cons();
+
+ S60CertificateExtension* ext = 0;
+ if (OIDS::name_of(oid, CERT_IMEI_FIELD_NAME))
+ ext = new S60DeviceIdListConstraint();
+
+ if (OIDS::name_of(oid, CERT_CAPABILITY_FIELD_NAME))
+ ext = new S60CapabilityConstraint();
+
+ if(!ext)
+ {
+ if(!critical || !should_throw)
+ continue;
+
+ throw Decoding_Error("Encountered unknown X.509 extension marked "
+ "as critical; OID = " + oid.as_string());
+ }
+ ext->decode_inner(value);
+ extensions.push_back(ext);
+ }
+ sequence.verify_end();
+}
+
+/*
+* Write the extensions to an info store
+*/
+void S60Extensions::contents_to(Data_Store& subject_info,
+ Data_Store& issuer_info) const
+{
+ for(u32bit j = 0; j != extensions.size(); ++j)
+ extensions[j]->contents_to(subject_info, issuer_info);
+}
+
+/*
+* Delete an Extensions list
+*/
+S60Extensions::~S60Extensions()
+{
+ for(u32bit j = 0; j != extensions.size(); ++j)
+ delete extensions[j];
+}
+
+
+
+// ======== S60SymbianCertificatePrivate
+
+class S60SymbianCertificatePrivate : private Botan::X509_Object
+{
+public:
+ /**
+ * Get the issuer certificate DN.
+ * @return the issuer DN of this certificate
+ */
+ Botan::X509_DN issuerDn() const;
+
+ /**
+ * Get the subject certificate DN.
+ * @return the subject DN of this certificate
+ */
+ Botan::X509_DN subjectDn() const;
+
+ /**
+ * Get a value for a specific subject_info parameter name.
+ * @param name the name of the paramter to look up. Possible names are
+ * "X509.Certificate.version", "X509.Certificate.serial",
+ * "X509.Certificate.start", "X509.Certificate.end",
+ * "X509.Certificate.v2.key_id", "X509.Certificate.public_key",
+ * "X509v3.BasicConstraints.path_constraint",
+ * "X509v3.BasicConstraints.is_ca", "X509v3.ExtendedKeyUsage",
+ * "X509v3.CertificatePolicies", "X509v3.SubjectKeyIdentifier" or
+ * "X509.Certificate.serial".
+ * @return the value(s) of the specified parameter
+ */
+ std::vector<std::string> subjectInfo(const std::string& name) const;
+
+ /**
+ * Get a value for a specific subject_info parameter name.
+ * @param name the name of the paramter to look up. Possible names are
+ * "X509.Certificate.v2.key_id" or "X509v3.AuthorityKeyIdentifier".
+ * @return the value(s) of the specified parameter
+ */
+ std::vector<std::string> issuerInfo(const std::string& name) const;
+
+ /**
+ * Get the notBefore of the certificate.
+ * @return the notBefore of the certificate
+ */
+ std::string startTime() const;
+
+ /**
+ * Get the notAfter of the certificate.
+ * @return the notAfter of the certificate
+ */
+ std::string endTime() const;
+
+ /**
+ * Get the X509 version of this certificate object.
+ * @return the X509 version
+ */
+ Botan::u32bit x509Version() const;
+
+ /**
+ * Get the serial number of this certificate.
+ * @return the certificates serial number
+ */
+ Botan::MemoryVector<Botan::byte> serialNumber() const;
+
+ /**
+ * Check whether this certificate is self signed.
+ * @return true if this certificate is self signed
+ */
+ bool isSelfSigned() const { return m_selfSigned; }
+
+ /**
+ * Check whether this certificate is a CA certificate.
+ * @return true if this certificate is a CA certificate
+ */
+ bool isCaCert() const;
+
+ /**
+ * Get the key constraints as defined in the KeyUsage extension of this
+ * certificate.
+ * @return the key constraints
+ */
+ Botan::Key_Constraints constraints() const;
+
+ /**
+ * Get the key constraints as defined in the ExtendedKeyUsage
+ * extension of this
+ * certificate.
+ * @return the key constraints
+ */
+ std::vector<std::string> exConstraints() const;
+
+ /**
+ * Get the policies as defined in the CertificatePolicies extension
+ * of this certificate.
+ * @return the certificate policies
+ */
+ std::vector<std::string> policies() const;
+
+ /**
+ * Check to certificates for equality.
+ * @return true both certificates are (binary) equal
+ */
+ bool operator==(const S60SymbianCertificatePrivate& other) const;
+
+ /**
+ * Create a certificate from a file containing the DER or PEM
+ * encoded certificate.
+ * @param filename the name of the certificate file
+ */
+ S60SymbianCertificatePrivate(const std::string& filename);
+
+private:
+ Botan::X509_DN createDn(const Botan::Data_Store& info) const;
+
+protected:
+ friend class X509_CA;
+ S60SymbianCertificatePrivate() {}
+
+ void force_decode();
+
+protected:
+ Botan::Data_Store m_subject;
+ Botan::Data_Store m_issuer;
+ bool m_selfSigned;
+};
+
+/*
+* Lookup each OID in the vector
+*/
+std::vector<std::string> lookup_oids(const std::vector<std::string>& in)
+{
+ std::vector<std::string> out;
+
+ std::vector<std::string>::const_iterator i = in.begin();
+ while(i != in.end())
+ {
+ out.push_back(OIDS::lookup(OID(*i)));
+ ++i;
+ }
+ return out;
+}
+
+/*
+* S60SymbianCertificate Constructor
+*/
+S60SymbianCertificatePrivate::S60SymbianCertificatePrivate(const std::string& in) :
+ X509_Object(in, "CERTIFICATE/X509 CERTIFICATE")
+{
+ m_selfSigned = false;
+
+ do_decode();
+}
+
+/*
+* Decode the TBSCertificate data
+*/
+void S60SymbianCertificatePrivate::force_decode()
+{
+ u32bit version;
+ BigInt serial_bn;
+ AlgorithmIdentifier sig_algo_inner;
+ X509_DN dn_issuer, dn_subject;
+ X509_Time start, end;
+
+ BER_Decoder tbs_cert(tbs_bits);
+
+ tbs_cert.decode_optional(version, ASN1_Tag(0),
+ ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC))
+ .decode(serial_bn)
+ .decode(sig_algo_inner)
+ .decode(dn_issuer)
+ .start_cons(SEQUENCE)
+ .decode(start)
+ .decode(end)
+ .verify_end()
+ .end_cons()
+ .decode(dn_subject);
+
+ if(version > 2)
+ throw Decoding_Error("Unknown X.509 cert version " + to_string(version));
+ if(sig_algo != sig_algo_inner)
+ throw Decoding_Error("Algorithm identifier mismatch");
+
+ m_selfSigned = (dn_subject == dn_issuer);
+
+ m_subject.add(dn_subject.contents());
+ m_issuer.add(dn_issuer.contents());
+
+ BER_Object public_key = tbs_cert.get_next_object();
+ if(public_key.type_tag != SEQUENCE || public_key.class_tag != CONSTRUCTED)
+ throw Decoding_Error("Unexpected tag for public key");
+
+ MemoryVector<byte> v2_issuer_key_id, v2_subject_key_id;
+
+ tbs_cert.decode_optional_string(v2_issuer_key_id, BIT_STRING, 1);
+ tbs_cert.decode_optional_string(v2_subject_key_id, BIT_STRING, 2);
+
+ BER_Object v3_exts_data = tbs_cert.get_next_object();
+ if(v3_exts_data.type_tag == 3 &&
+ v3_exts_data.class_tag == ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC))
+ {
+ S60Extensions s60extensions(false);
+
+ BER_Decoder(v3_exts_data.value).decode(s60extensions).verify_end();
+
+ s60extensions.contents_to(m_subject, m_issuer);
+
+ Extensions extensions(false);
+
+ BER_Decoder(v3_exts_data.value).decode(extensions).verify_end();
+
+ extensions.contents_to(m_subject, m_issuer);
+ }
+ else if(v3_exts_data.type_tag != NO_OBJECT)
+ throw Decoding_Error("Unknown tag in X.509 cert");
+
+ if(tbs_cert.more_items())
+ throw Decoding_Error("TBSCertificate has more items that expected");
+
+ m_subject.add("X509.Certificate.version", version);
+ m_subject.add("X509.Certificate.serial", BigInt::encode(serial_bn));
+ m_subject.add("X509.Certificate.start", start.readable_string());
+ m_subject.add("X509.Certificate.end", end.readable_string());
+
+ m_issuer.add("X509.Certificate.v2.key_id", v2_issuer_key_id);
+ m_subject.add("X509.Certificate.v2.key_id", v2_subject_key_id);
+
+ if(isCaCert() &&
+ !m_subject.has_value("X509v3.BasicConstraints.path_constraint"))
+ {
+ u32bit limit = (x509Version() < 3) ? NO_CERT_PATH_LIMIT : 0;
+ m_subject.add("X509v3.BasicConstraints.path_constraint", limit);
+ }
+}
+
+/*
+* Return the X.509 version in use
+*/
+u32bit S60SymbianCertificatePrivate::x509Version() const
+{
+ return (m_subject.get1_u32bit("X509.Certificate.version") + 1);
+}
+
+/*
+* Return the time this cert becomes valid
+*/
+std::string S60SymbianCertificatePrivate::startTime() const
+{
+ return m_subject.get1("X509.Certificate.start");
+}
+
+/*
+* Return the time this cert becomes invalid
+*/
+std::string S60SymbianCertificatePrivate::endTime() const
+{
+ return m_subject.get1("X509.Certificate.end");
+}
+
+/*
+* Return information about the subject
+*/
+std::vector<std::string>
+S60SymbianCertificatePrivate::subjectInfo(const std::string& what) const
+{
+ return m_subject.get(X509_DN::deref_info_field(what));
+}
+
+/*
+* Return information about the issuer
+*/
+std::vector<std::string>
+S60SymbianCertificatePrivate::issuerInfo(const std::string& what) const
+{
+ return m_issuer.get(X509_DN::deref_info_field(what));
+}
+
+/*
+* Check if the certificate is for a CA
+*/
+bool S60SymbianCertificatePrivate::isCaCert() const
+{
+ if(!m_subject.get1_u32bit("X509v3.BasicConstraints.is_ca"))
+ return false;
+ if((constraints() & KEY_CERT_SIGN) || (constraints() == NO_CONSTRAINTS))
+ return true;
+ return false;
+}
+
+/*
+* Return the key usage constraints
+*/
+Key_Constraints S60SymbianCertificatePrivate::constraints() const
+{
+ return Key_Constraints(m_subject.get1_u32bit("X509v3.KeyUsage",
+ NO_CONSTRAINTS));
+}
+
+/*
+* Return the list of extended key usage OIDs
+*/
+std::vector<std::string> S60SymbianCertificatePrivate::exConstraints() const
+{
+ return lookup_oids(m_subject.get("X509v3.ExtendedKeyUsage"));
+}
+
+/*
+* Return the list of certificate policies
+*/
+std::vector<std::string> S60SymbianCertificatePrivate::policies() const
+{
+ return lookup_oids(m_subject.get("X509v3.CertificatePolicies"));
+}
+
+/*
+* Return the certificate serial number
+*/
+MemoryVector<byte> S60SymbianCertificatePrivate::serialNumber() const
+{
+ return m_subject.get1_memvec("X509.Certificate.serial");
+}
+
+/*
+* Return the distinguished name of the issuer
+*/
+X509_DN S60SymbianCertificatePrivate::issuerDn() const
+{
+ return createDn(m_issuer);
+}
+
+/*
+* Return the distinguished name of the subject
+*/
+X509_DN S60SymbianCertificatePrivate::subjectDn() const
+{
+ return createDn(m_subject);
+}
+
+/*
+* Compare two certificates for equality
+*/
+bool S60SymbianCertificatePrivate::operator==(const S60SymbianCertificatePrivate& other) const
+{
+ return (sig == other.sig &&
+ sig_algo == other.sig_algo &&
+ m_selfSigned == other.m_selfSigned &&
+ m_issuer == other.m_issuer &&
+ m_subject == other.m_subject);
+}
+
+/*
+* X.509 Certificate Comparison
+*/
+bool operator!=(const S60SymbianCertificatePrivate& cert1, const S60SymbianCertificatePrivate& cert2)
+{
+ return !(cert1 == cert2);
+}
+
+/*
+* Create and populate a X509_DN
+*/
+X509_DN S60SymbianCertificatePrivate::createDn(const Data_Store& info) const
+{
+ class DN_Matcher : public Data_Store::Matcher
+ {
+ public:
+ bool operator()(const std::string& key, const std::string&) const
+ {
+ if(key.find("X520.") != std::string::npos)
+ return true;
+ return false;
+ }
+ };
+
+ std::multimap<std::string, std::string> names =
+ info.search_with(DN_Matcher());
+
+ X509_DN dn;
+
+ std::multimap<std::string, std::string>::iterator j;
+ for(j = names.begin(); j != names.end(); ++j)
+ dn.add_attribute(j->first, j->second);
+
+ return dn;
+}
+
+/*
+* Create and populate an AlternativeName
+*/
+AlternativeName create_alt_name(const Data_Store& info)
+{
+ class AltName_Matcher : public Data_Store::Matcher
+ {
+ public:
+ bool operator()(const std::string& key, const std::string&) const
+ {
+ for(u32bit j = 0; j != matches.size(); ++j)
+ if(key.compare(matches[j]) == 0)
+ return true;
+ return false;
+ }
+
+ AltName_Matcher(const std::string& match_any_of)
+ {
+ matches = split_on(match_any_of, '/');
+ }
+ private:
+ std::vector<std::string> matches;
+ };
+
+ std::multimap<std::string, std::string> names =
+ info.search_with(AltName_Matcher("RFC822/DNS/URI/IP"));
+
+ AlternativeName alt_name;
+
+ std::multimap<std::string, std::string>::iterator j;
+ for(j = names.begin(); j != names.end(); ++j)
+ alt_name.add_attribute(j->first, j->second);
+
+ return alt_name;
+}
+
+// ======== S60SymbianCertificate
+
+S60SymbianCertificate::S60SymbianCertificate(const QString &filename) : m_d(0)
+{
+ S60SymbianCertificatePrivate *certificate = 0;
+ try {
+ certificate = new S60SymbianCertificatePrivate(filename.toStdString());
+ m_d = certificate;
+ certificate = 0;
+ } catch (Botan::Exception &e) {
+ m_errorString = QLatin1String(e.what());
+ }
+ delete certificate;
+}
+
+S60SymbianCertificate::~S60SymbianCertificate()
+{
+ delete m_d;
+}
+
+bool S60SymbianCertificate::isValid() const
+{
+ return m_d != 0;
+}
+
+QString S60SymbianCertificate::errorString() const
+{
+ return m_errorString;
+}
+
+QStringList S60SymbianCertificate::subjectInfo(const QString &name)
+{
+ Q_ASSERT(m_d);
+ QStringList result;
+ try {
+ std::vector<std::string> subjectInfo(m_d->subjectInfo(name.toStdString()));
+ std::vector<std::string>::const_iterator i;
+ for(i = subjectInfo.begin(); i != subjectInfo.end(); ++i)
+ result << QString::fromStdString(*i);
+ } catch (Botan::Exception &e) {
+ m_errorString = QString::fromLatin1(e.what());
+ }
+ return result;
+}
+
+QStringList S60SymbianCertificate::issuerInfo(const QString &name)
+{
+ Q_ASSERT(m_d);
+ QStringList result;
+ try {
+ std::vector<std::string> issuerInfo(m_d->issuerInfo(name.toStdString()));
+
+ std::vector<std::string>::const_iterator i;
+ for(i = issuerInfo.begin(); i != issuerInfo.end(); ++i)
+ result << QString::fromStdString(*i);
+ } catch (Botan::Exception &e) {
+ m_errorString = QString::fromLatin1(e.what());
+ }
+ return result;
+}
+
+QDateTime S60SymbianCertificate::parseTime(const std::string &time)
+{
+ QDateTime result;
+ try {
+ const char * const CERTIFICATE_DATE_FORMAT = "yyyy/M/d h:mm:ss UTC";
+ QDateTime dateTime = QDateTime::fromString(QString::fromStdString(time),
+ QLatin1String(CERTIFICATE_DATE_FORMAT));
+ result = QDateTime(dateTime.date(), dateTime.time(), Qt::UTC);
+ } catch (Botan::Exception &e) {
+ m_errorString = QString::fromLatin1(e.what());
+ }
+ return result;
+}
+
+QDateTime S60SymbianCertificate::startTime()
+{
+ Q_ASSERT(m_d);
+ return parseTime(m_d->startTime());
+}
+
+QDateTime S60SymbianCertificate::endTime()
+{
+ Q_ASSERT(m_d);
+ return parseTime(m_d->endTime());
+}
+
+quint32 S60SymbianCertificate::certificateVersion()
+{
+ Q_ASSERT(m_d);
+ quint32 version = 0;
+ try {
+ version = static_cast<quint32>(m_d->x509Version());
+ } catch (Botan::Exception &e) {
+ m_errorString = QString::fromLatin1(e.what());
+ }
+ return version;
+}
+
+bool S60SymbianCertificate::isSelfSigned()
+{
+ Q_ASSERT(m_d);
+ return m_d->isSelfSigned();
+}
+
+bool S60SymbianCertificate::isCaCert()
+{
+ Q_ASSERT(m_d);
+ bool isCaCertificate = false;
+ try {
+ isCaCertificate = m_d->isCaCert();
+ } catch (Botan::Exception &e) {
+ m_errorString = QString::fromLatin1(e.what());
+ }
+ return isCaCertificate;
+}
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60symbiancertificate.h b/src/plugins/qt4projectmanager/qt-s60/s60symbiancertificate.h
new file mode 100644
index 0000000000..d8ff463d11
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-s60/s60symbiancertificate.h
@@ -0,0 +1,72 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 S60SYMBIANCERTIFICATE_H
+#define S60SYMBIANCERTIFICATE_H
+
+#include <QStringList>
+#include <QDateTime>
+
+class S60SymbianCertificatePrivate;
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+class S60SymbianCertificate
+{
+public:
+ explicit S60SymbianCertificate(const QString &filename);
+ ~S60SymbianCertificate();
+
+ bool isValid() const;
+
+ QString errorString() const;
+
+ QStringList subjectInfo(const QString &name);
+ QStringList issuerInfo(const QString &name);
+
+ QDateTime startTime();
+ QDateTime endTime();
+
+ quint32 certificateVersion();
+ bool isSelfSigned();
+ bool isCaCert();
+
+private:
+ QDateTime parseTime(const std::string &time);
+
+protected:
+ S60SymbianCertificatePrivate const *m_d;
+ QString m_errorString;
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // S60SYMBIANCERTIFICATE_H
diff --git a/src/plugins/qt4projectmanager/qt-s60/sbsv2parser.cpp b/src/plugins/qt4projectmanager/qt-s60/sbsv2parser.cpp
index d002a4a0aa..eb9d458a43 100644
--- a/src/plugins/qt4projectmanager/qt-s60/sbsv2parser.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/sbsv2parser.cpp
@@ -34,13 +34,8 @@
#include "sbsv2parser.h"
#include <extensionsystem/pluginmanager.h>
-#include <projectexplorer/gnumakeparser.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/taskhub.h>
-#include <projectexplorer/taskwindow.h>
-
-#include <QtCore/QFile>
-#include <QtCore/QFileInfo>
using namespace Qt4ProjectManager;
using namespace ProjectExplorer;
@@ -69,7 +64,7 @@ void SbsV2Parser::stdOutput(const QString &line)
{
// Eat most output!
if (line.startsWith(QLatin1String("sbs: build log in "))) {
- QString logfile = line.mid(18).trimmed();
+ QString logfile = QDir::fromNativeSeparators(line.mid(18).trimmed());
parseLogFile(logfile);
addTask(ProjectExplorer::Task(Task::Unknown, tr("SBSv2 build log"),
logfile, -1,
diff --git a/src/plugins/qt4projectmanager/qt-s60/signsisparser.cpp b/src/plugins/qt4projectmanager/qt-s60/signsisparser.cpp
deleted file mode 100644
index 8f184346fb..0000000000
--- a/src/plugins/qt4projectmanager/qt-s60/signsisparser.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-
-#include "signsisparser.h"
-
-#include <projectexplorer/projectexplorerconstants.h>
-#include <projectexplorer/taskwindow.h>
-
-using namespace Qt4ProjectManager;
-using namespace ProjectExplorer;
-using namespace ProjectExplorer::Constants;
-
-SignsisParser::SignsisParser()
-{
- m_signSis.setPattern("^(error):([A-Z\\d]+):(.+)$");
- m_signSis.setMinimal(true);
-}
-
-void SignsisParser::stdOutput(const QString &line)
-{
- QString lne = line.trimmed();
-
- if (m_signSis.indexIn(lne) > -1) {
- QString errorDescription(m_signSis.cap(3));
- int index = errorDescription.indexOf(QLatin1String("error:"));
- if (index >= 0) {
- stdOutput(errorDescription.mid(index));
- errorDescription = errorDescription.left(index);
- }
- Task task(Task::Error,
- errorDescription /* description */,
- QString(), -1,
- TASK_CATEGORY_BUILDSYSTEM);
- emit addTask(task);
- }
- IOutputParser::stdOutput(line);
-}
-
-void SignsisParser::stdError(const QString &line)
-{
- stdOutput(line);
- IOutputParser::stdError(line);
-}
diff --git a/src/plugins/qt4projectmanager/qt-s60/signsisparser.h b/src/plugins/qt4projectmanager/qt-s60/signsisparser.h
deleted file mode 100644
index 85529a5d02..0000000000
--- a/src/plugins/qt4projectmanager/qt-s60/signsisparser.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef SIGNSISPARSER_H
-#define SIGNSISPARSER_H
-
-#include <projectexplorer/ioutputparser.h>
-
-#include <QtCore/QRegExp>
-
-namespace Qt4ProjectManager {
-
-class SignsisParser : public ProjectExplorer::IOutputParser
-{
- Q_OBJECT
-
-public:
- SignsisParser();
-
- virtual void stdOutput(const QString & line);
- virtual void stdError(const QString & line);
-
-private:
- QRegExp m_signSis;
-};
-
-} // namespace Qt4ProjectExplorer
-
-
-#endif // SIGNSISPARSER_H
diff --git a/src/plugins/qt4projectmanager/qt-s60/winscwparser.cpp b/src/plugins/qt4projectmanager/qt-s60/winscwparser.cpp
index 06d940e653..bed7268d40 100644
--- a/src/plugins/qt4projectmanager/qt-s60/winscwparser.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/winscwparser.cpp
@@ -32,8 +32,10 @@
**************************************************************************/
#include "winscwparser.h"
+
#include <projectexplorer/projectexplorerconstants.h>
-#include <projectexplorer/taskwindow.h>
+
+#include <QtCore/QDir>
using namespace Qt4ProjectManager;
using namespace ProjectExplorer;
@@ -58,7 +60,7 @@ void WinscwParser::stdOutput(const QString &line)
if (m_compilerProblem.indexIn(lne) > -1) {
Task task(Task::Error,
m_compilerProblem.cap(3) /* description */,
- m_compilerProblem.cap(1) /* filename */,
+ QDir::fromNativeSeparators(m_compilerProblem.cap(1)) /* filename */,
m_compilerProblem.cap(2).toInt() /* linenumber */,
TASK_CATEGORY_COMPILE);
if (task.description.startsWith(QLatin1String("warning: "))) {
@@ -78,7 +80,7 @@ void WinscwParser::stdError(const QString &line)
if (m_linkerProblem.indexIn(lne) > -1) {
emit addTask(Task(Task::Error,
m_linkerProblem.cap(2) /* description */,
- m_linkerProblem.cap(1) /* filename */,
+ QDir::fromNativeSeparators(m_linkerProblem.cap(1)) /* filename */,
-1 /* linenumber */,
TASK_CATEGORY_COMPILE));
return;
diff --git a/src/plugins/qt4projectmanager/qt-s60/winscwtoolchain.cpp b/src/plugins/qt4projectmanager/qt-s60/winscwtoolchain.cpp
index 45219538de..0e33d2ef05 100644
--- a/src/plugins/qt4projectmanager/qt-s60/winscwtoolchain.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/winscwtoolchain.cpp
@@ -51,9 +51,9 @@ WINSCWToolChain::WINSCWToolChain(const S60Devices::Device &device, const QString
}
-ToolChain::ToolChainType WINSCWToolChain::type() const
+ProjectExplorer::ToolChainType WINSCWToolChain::type() const
{
- return ToolChain::WINSCW;
+ return ProjectExplorer::ToolChain_WINSCW;
}
QByteArray WINSCWToolChain::predefinedMacros()
diff --git a/src/plugins/qt4projectmanager/qt-s60/winscwtoolchain.h b/src/plugins/qt4projectmanager/qt-s60/winscwtoolchain.h
index 2807135cdb..641abb06e2 100644
--- a/src/plugins/qt4projectmanager/qt-s60/winscwtoolchain.h
+++ b/src/plugins/qt4projectmanager/qt-s60/winscwtoolchain.h
@@ -48,7 +48,7 @@ public:
QByteArray predefinedMacros();
QList<ProjectExplorer::HeaderPath> systemHeaderPaths();
void addToEnvironment(Utils::Environment &env);
- ProjectExplorer::ToolChain::ToolChainType type() const;
+ ProjectExplorer::ToolChainType type() const;
QString makeCommand() const;
ProjectExplorer::IOutputParser *outputParser() const;
diff --git a/src/plugins/qt4projectmanager/qt4buildconfiguration.cpp b/src/plugins/qt4projectmanager/qt4buildconfiguration.cpp
index 866728a83d..7300f21c08 100644
--- a/src/plugins/qt4projectmanager/qt4buildconfiguration.cpp
+++ b/src/plugins/qt4projectmanager/qt4buildconfiguration.cpp
@@ -41,6 +41,7 @@
#include "makestep.h"
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <limits>
#include <projectexplorer/buildsteplist.h>
#include <projectexplorer/projectexplorerconstants.h>
@@ -122,8 +123,6 @@ bool Qt4BuildConfiguration::fromMap(const QVariantMap &map)
if (!BuildConfiguration::fromMap(map))
return false;
- int fileVersion = map.value(ProjectExplorer::Constants::USERFILE_PREVIOUS_VERSION_KEY,
- std::numeric_limits<int>::max()).toInt();
m_shadowBuild = map.value(QLatin1String(USE_SHADOW_BUILD_KEY), true).toBool();
m_buildDirectory = map.value(QLatin1String(BUILD_DIRECTORY_KEY), qt4Target()->defaultBuildDirectory()).toString();
m_qtVersionId = map.value(QLatin1String(QT_VERSION_ID_KEY)).toInt();
@@ -146,7 +145,7 @@ bool Qt4BuildConfiguration::fromMap(const QVariantMap &map)
}
QtVersion *version = qtVersion();
- if (fileVersion >= 1) { // we are not upgrading from pre-targets!
+ if (!map.contains(QLatin1String("Qt4ProjectManager.Qt4BuildConfiguration.NeedsV0Update"))) { // we are not upgrading from pre-targets!
if (version->isValid() && !version->supportedTargetIds().contains(target()->id())) {
qWarning() << "Buildconfiguration" << displayName() << ": Qt" << version->displayName() << "not supported by target" << target()->id();
return false;
@@ -161,11 +160,11 @@ bool Qt4BuildConfiguration::fromMap(const QVariantMap &map)
if (version->isValid())
m_shadowBuild = (m_shadowBuild && version->supportsShadowBuilds());
- QList<ToolChain::ToolChainType> possibleTcs(qt4Target()->filterToolChainTypes(qtVersion()->possibleToolChainTypes()));
+ QList<ProjectExplorer::ToolChainType> possibleTcs(qt4Target()->filterToolChainTypes(qtVersion()->possibleToolChainTypes()));
if (!possibleTcs.contains(toolChainType()))
setToolChainType(qt4Target()->preferredToolChainType(possibleTcs));
- if (toolChainType() == ToolChain::INVALID) {
+ if (toolChainType() == ProjectExplorer::ToolChain_INVALID) {
qWarning() << "No toolchain available for" << qtVersion()->displayName() << "used in" << target()->id() << "!";
return false;
}
@@ -216,10 +215,6 @@ Utils::Environment Qt4BuildConfiguration::baseEnvironment() const
Utils::Environment env = BuildConfiguration::baseEnvironment();
qtVersion()->addToEnvironment(env);
- // We can't call buildDirectory() since that uses environment() to expand,
- // thus calling baseEnvironment() again
- env.set(QLatin1String("BUILDDIR"), QDir::toNativeSeparators(env.expandVariables(rawBuildDirectory())));
-
ToolChain *tc = toolChain();
if (tc)
tc->addToEnvironment(env);
@@ -302,7 +297,7 @@ void Qt4BuildConfiguration::setShadowBuildAndDirectory(bool shadowBuild, const Q
ProjectExplorer::ToolChain *Qt4BuildConfiguration::toolChain() const
{
- ToolChain::ToolChainType tct = toolChainType();
+ const ProjectExplorer::ToolChainType tct = toolChainType();
return qtVersion()->toolChain(tct);
}
@@ -329,20 +324,27 @@ QString Qt4BuildConfiguration::defaultMakeTarget() const
const QtVersion::QmakeBuildConfigs buildConfig = qmakeBuildConfiguration();
switch (tc->type()) {
- case ToolChain::GCCE:
+ case ProjectExplorer::ToolChain_GCCE:
return symbianMakeTarget(buildConfig, QLatin1String("gcce"));
- case ToolChain::RVCT_ARMV5:
+ case ProjectExplorer::ToolChain_RVCT2_ARMV5:
+ case ProjectExplorer::ToolChain_RVCT4_ARMV5:
return symbianMakeTarget(buildConfig, QLatin1String("armv5"));
- case ToolChain::RVCT_ARMV6:
+ case ProjectExplorer::ToolChain_RVCT2_ARMV6:
+ case ProjectExplorer::ToolChain_RVCT4_ARMV6:
return symbianMakeTarget(buildConfig, QLatin1String("armv6"));
- case ToolChain::RVCT_ARMV5_GNUPOC:
- case ToolChain::GCCE_GNUPOC:
+ case ProjectExplorer::ToolChain_RVCT_ARMV5_GNUPOC:
+ case ProjectExplorer::ToolChain_GCCE_GNUPOC:
default:
break;
}
return QString();
}
+QString Qt4BuildConfiguration::makefile() const
+{
+ return qt4Target()->qt4Project()->rootProjectNode()->makefile();
+}
+
QtVersion *Qt4BuildConfiguration::qtVersion() const
{
QtVersionManager *vm = QtVersionManager::instance();
@@ -358,11 +360,11 @@ void Qt4BuildConfiguration::setQtVersion(QtVersion *version)
m_qtVersionId = version->uniqueId();
- if (!version->possibleToolChainTypes().contains(ProjectExplorer::ToolChain::ToolChainType(m_toolChainType))) {
- QList<ToolChain::ToolChainType> candidates =
+ if (!version->possibleToolChainTypes().contains(ProjectExplorer::ToolChainType(m_toolChainType))) {
+ QList<ProjectExplorer::ToolChainType> candidates =
qt4Target()->filterToolChainTypes(qtVersion()->possibleToolChainTypes());
if (candidates.isEmpty())
- m_toolChainType = ToolChain::INVALID;
+ m_toolChainType = ProjectExplorer::ToolChain_INVALID;
else
m_toolChainType = candidates.first();
}
@@ -375,7 +377,7 @@ void Qt4BuildConfiguration::setQtVersion(QtVersion *version)
emitBuildDirectoryChanged();
}
-void Qt4BuildConfiguration::setToolChainType(ProjectExplorer::ToolChain::ToolChainType type)
+void Qt4BuildConfiguration::setToolChainType(ProjectExplorer::ToolChainType type)
{
if (!qt4Target()->filterToolChainTypes(qtVersion()->possibleToolChainTypes()).contains(type)
|| m_toolChainType == type)
@@ -389,9 +391,9 @@ void Qt4BuildConfiguration::setToolChainType(ProjectExplorer::ToolChain::ToolCha
emitBuildDirectoryChanged();
}
-ProjectExplorer::ToolChain::ToolChainType Qt4BuildConfiguration::toolChainType() const
+ProjectExplorer::ToolChainType Qt4BuildConfiguration::toolChainType() const
{
- return ToolChain::ToolChainType(m_toolChainType);
+ return ProjectExplorer::ToolChainType(m_toolChainType);
}
QtVersion::QmakeBuildConfigs Qt4BuildConfiguration::qmakeBuildConfiguration() const
@@ -483,33 +485,34 @@ void Qt4BuildConfiguration::qtVersionsChanged(const QList<int> &changedVersions)
}
// returns true if both are equal
-bool Qt4BuildConfiguration::compareToImportFrom(const QString &workingDirectory)
+bool Qt4BuildConfiguration::compareToImportFrom(const QString &makefile)
{
QMakeStep *qs = qmakeStep();
- if (QDir(workingDirectory).exists(QLatin1String("Makefile")) && qs) {
- QString qmakePath = QtVersionManager::findQMakeBinaryFromMakefile(workingDirectory);
+ if (QFileInfo(makefile).exists() && qs) {
+ QString qmakePath = QtVersionManager::findQMakeBinaryFromMakefile(makefile);
QtVersion *version = qtVersion();
if (version->qmakeCommand() == qmakePath) {
// same qtversion
- QPair<QtVersion::QmakeBuildConfigs, QStringList> result =
- QtVersionManager::scanMakeFile(workingDirectory, version->defaultBuildConfig());
+ QPair<QtVersion::QmakeBuildConfigs, QString> result =
+ QtVersionManager::scanMakeFile(makefile, version->defaultBuildConfig());
if (qmakeBuildConfiguration() == result.first) {
// The qmake Build Configuration are the same,
// now compare arguments lists
// we have to compare without the spec/platform cmd argument
// and compare that on its own
- QString actualSpec = extractSpecFromArgumentList(qs->userArguments(), workingDirectory, version);
+ QString workingDirectory = QFileInfo(makefile).absolutePath();
+ QString userArgs = qs->userArguments();
+ QStringList actualArgs;
+ QString actualSpec = extractSpecFromArguments(&userArgs, workingDirectory, version, &actualArgs);
if (actualSpec.isEmpty()) {
// Easy one: the user has chosen not to override the settings
actualSpec = version->mkspec();
}
+ actualArgs += qs->moreArguments();
-
- QString parsedSpec = extractSpecFromArgumentList(result.second, workingDirectory, version);
- QStringList actualArgs = qs->moreArguments();
- actualArgs << qs->userArguments();
- actualArgs = removeSpecFromArgumentList(actualArgs);
- QStringList parsedArgs = removeSpecFromArgumentList(result.second);
+ QString qmakeArgs = result.second;
+ QStringList parsedArgs;
+ QString parsedSpec = extractSpecFromArguments(&qmakeArgs, workingDirectory, version, &parsedArgs);
if (debug) {
qDebug()<<"Actual args:"<<actualArgs;
@@ -554,59 +557,53 @@ bool Qt4BuildConfiguration::compareToImportFrom(const QString &workingDirectory)
return false;
}
-QStringList Qt4BuildConfiguration::removeQMLInspectorFromArgumentList(const QStringList &old)
+void Qt4BuildConfiguration::removeQMLInspectorFromArguments(QString *args)
{
- QStringList result;
- foreach (const QString &str, old)
- if (!str.startsWith(QLatin1String(Constants::QMAKEVAR_QMLJSDEBUGGER_PATH)))
- result << str;
- return result;
+ for (Utils::QtcProcess::ArgIterator ait(args); ait.next(); )
+ if (ait.value().startsWith(QLatin1String(Constants::QMAKEVAR_QMLJSDEBUGGER_PATH)))
+ ait.deleteArg();
}
-// We match -spec and -platfrom separetly
-// We ignore -cache, because qmake contained a bug that it didn't
-// mention the -cache in the Makefile
-// That means changing the -cache option in the additional arguments
-// does not automatically rerun qmake. Alas, we could try more
-// intelligent matching for -cache, but i guess people rarely
-// do use that.
-
-QStringList Qt4BuildConfiguration::removeSpecFromArgumentList(const QStringList &old)
+QString Qt4BuildConfiguration::extractSpecFromArguments(QString *args,
+ const QString &directory, const QtVersion *version,
+ QStringList *outArgs)
{
- if (!old.contains("-spec") && !old.contains("-platform") && !old.contains("-cache"))
- return old;
- QStringList newList;
+ QString parsedSpec;
+
bool ignoreNext = false;
- foreach(const QString &item, old) {
+ bool nextIsSpec = false;
+ for (Utils::QtcProcess::ArgIterator ait(args); ait.next(); ) {
if (ignoreNext) {
ignoreNext = false;
- } else if (item == "-spec" || item == "-platform" || item == "-cache") {
+ ait.deleteArg();
+ } else if (nextIsSpec) {
+ nextIsSpec = false;
+ parsedSpec = QDir::cleanPath(ait.value());
+ ait.deleteArg();
+ } else if (ait.value() == QLatin1String("-spec") || ait.value() == QLatin1String("-platform")) {
+ nextIsSpec = true;
+ ait.deleteArg();
+ } else if (ait.value() == QLatin1String("-cache")) {
+ // We ignore -cache, because qmake contained a bug that it didn't
+ // mention the -cache in the Makefile.
+ // That means changing the -cache option in the additional arguments
+ // does not automatically rerun qmake. Alas, we could try more
+ // intelligent matching for -cache, but i guess people rarely
+ // do use that.
ignoreNext = true;
- } else {
- newList << item;
+ ait.deleteArg();
+ } else if (outArgs && ait.isSimple()) {
+ outArgs->append(ait.value());
}
}
- return newList;
-}
-
-QString Qt4BuildConfiguration::extractSpecFromArgumentList(const QStringList &list, QString directory, QtVersion *version)
-{
- int index = list.indexOf("-spec");
- if (index == -1)
- index = list.indexOf("-platform");
- if (index == -1)
- return QString();
-
- ++index;
- if (index >= list.length())
+ if (parsedSpec.isEmpty())
return QString();
QString baseMkspecDir = version->versionInfo().value("QMAKE_MKSPECS");
if (baseMkspecDir.isEmpty())
baseMkspecDir = version->versionInfo().value("QT_INSTALL_DATA") + "/mkspecs";
- QString parsedSpec = QDir::cleanPath(list.at(index));
#ifdef Q_OS_WIN
baseMkspecDir = baseMkspecDir.toLower();
parsedSpec = parsedSpec.toLower();
@@ -733,7 +730,7 @@ BuildConfiguration *Qt4BuildConfigurationFactory::create(ProjectExplorer::Target
QtVersion *version = QtVersionManager::instance()->version(info.versionId);
Q_ASSERT(version);
- Qt4Target *qt4Target(static_cast<Qt4Target *>(parent));
+ Qt4Target *qt4Target = static_cast<Qt4Target *>(parent);
bool ok;
QString buildConfigurationName = QInputDialog::getText(0,
@@ -749,12 +746,12 @@ BuildConfiguration *Qt4BuildConfigurationFactory::create(ProjectExplorer::Target
qt4Target->addQt4BuildConfiguration(tr("%1 Debug").arg(buildConfigurationName),
version,
(version->defaultBuildConfig() | QtVersion::DebugBuild),
- QStringList(), QString());
+ QString(), QString());
BuildConfiguration *bc =
qt4Target->addQt4BuildConfiguration(tr("%1 Release").arg(buildConfigurationName),
version,
(version->defaultBuildConfig() & ~QtVersion::DebugBuild),
- QStringList(), QString());
+ QString(), QString());
return bc;
}
diff --git a/src/plugins/qt4projectmanager/qt4buildconfiguration.h b/src/plugins/qt4projectmanager/qt4buildconfiguration.h
index d591903554..0753f79c0d 100644
--- a/src/plugins/qt4projectmanager/qt4buildconfiguration.h
+++ b/src/plugins/qt4projectmanager/qt4buildconfiguration.h
@@ -37,22 +37,27 @@
#include "qtversionmanager.h"
#include <projectexplorer/buildconfiguration.h>
-#include <projectexplorer/toolchain.h>
+#include <projectexplorer/toolchaintype.h>
+
+namespace ProjectExplorer {
+class ToolChain;
+}
namespace Qt4ProjectManager {
class QMakeStep;
class MakeStep;
+class Qt4Target;
namespace Internal {
class Qt4ProFileNode;
class Qt4BuildConfigurationFactory;
-class Qt4Target;
+}
class Qt4BuildConfiguration : public ProjectExplorer::BuildConfiguration
{
Q_OBJECT
- friend class Qt4BuildConfigurationFactory;
+ friend class Internal::Qt4BuildConfigurationFactory;
public:
explicit Qt4BuildConfiguration(Qt4Target *target);
@@ -75,8 +80,8 @@ public:
void setQtVersion(QtVersion *);
ProjectExplorer::ToolChain *toolChain() const;
- void setToolChainType(ProjectExplorer::ToolChain::ToolChainType type);
- ProjectExplorer::ToolChain::ToolChainType toolChainType() const;
+ void setToolChainType(ProjectExplorer::ToolChainType type);
+ ProjectExplorer::ToolChainType toolChainType() const;
QtVersion::QmakeBuildConfigs qmakeBuildConfiguration() const;
void setQMakeBuildConfiguration(QtVersion::QmakeBuildConfigs config);
@@ -106,11 +111,13 @@ public:
QString makeCommand() const;
QString defaultMakeTarget() const;
+ QString makefile() const;
- bool compareToImportFrom(const QString &workingDirectory);
- static QStringList removeQMLInspectorFromArgumentList(const QStringList &old);
- static QStringList removeSpecFromArgumentList(const QStringList &old);
- static QString extractSpecFromArgumentList(const QStringList &list, QString directory, QtVersion *version);
+ bool compareToImportFrom(const QString &makefile);
+ static void removeQMLInspectorFromArguments(QString *args);
+ static QString extractSpecFromArguments(QString *arguments,
+ const QString &directory, const QtVersion *version,
+ QStringList *outArgs = 0);
QVariantMap toMap() const;
@@ -131,7 +138,7 @@ signals:
/// emitted if the build configuration changed in a way that
/// should trigger a reevaluation of all .pro files
- void proFileEvaluateNeeded(Qt4ProjectManager::Internal::Qt4BuildConfiguration *);
+ void proFileEvaluateNeeded(Qt4ProjectManager::Qt4BuildConfiguration *);
void buildDirectoryInitialized();
@@ -158,6 +165,7 @@ private:
Qt4ProjectManager::Internal::Qt4ProFileNode *m_subNodeBuild;
};
+namespace Internal {
class Qt4BuildConfigurationFactory : public ProjectExplorer::IBuildConfigurationFactory
{
Q_OBJECT
@@ -194,7 +202,7 @@ private:
QMap<QString, VersionInfo> m_versions;
};
-} // namespace Qt4ProjectManager
} // namespace Internal
+} // namespace Qt4ProjectManager
#endif // QT4BUILDCONFIGURATION_H
diff --git a/src/plugins/qt4projectmanager/qt4nodes.cpp b/src/plugins/qt4projectmanager/qt4nodes.cpp
index f2e5d08d1c..52d0335d1d 100644
--- a/src/plugins/qt4projectmanager/qt4nodes.cpp
+++ b/src/plugins/qt4projectmanager/qt4nodes.cpp
@@ -150,7 +150,7 @@ Q_GLOBAL_STATIC_WITH_INITIALIZER(Qt4NodeStaticData, qt4NodeStaticData, {
x->projectIcon.addPixmap(projectPixmap);
qAddPostRoutine(clearQt4NodeStaticData);
-});
+})
static void clearQt4NodeStaticData()
{
@@ -959,14 +959,14 @@ bool Qt4PriFileNode::priFileWritable(const QString &path)
const QString dir = QFileInfo(path).dir().path();
Core::ICore *core = Core::ICore::instance();
Core::IVersionControl *versionControl = core->vcsManager()->findVersionControlForDirectory(dir);
- switch (Core::EditorManager::promptReadOnlyFile(path, versionControl, core->mainWindow(), false)) {
- case Core::EditorManager::RO_OpenVCS:
+ switch (Core::FileManager::promptReadOnlyFile(path, versionControl, core->mainWindow(), false)) {
+ case Core::FileManager::RO_OpenVCS:
if (!versionControl->vcsOpen(path)) {
QMessageBox::warning(core->mainWindow(), tr("Failed!"), tr("Could not open the file for edit with VCS."));
return false;
}
break;
- case Core::EditorManager::RO_MakeWriteable: {
+ case Core::FileManager::RO_MakeWriteable: {
const bool permsOk = QFile::setPermissions(path, QFile::permissions(path) | QFile::WriteUser);
if (!permsOk) {
QMessageBox::warning(core->mainWindow(), tr("Failed!"), tr("Could not set permissions to writable."));
@@ -974,8 +974,8 @@ bool Qt4PriFileNode::priFileWritable(const QString &path)
}
break;
}
- case Core::EditorManager::RO_SaveAs:
- case Core::EditorManager::RO_Cancel:
+ case Core::FileManager::RO_SaveAs:
+ case Core::FileManager::RO_Cancel:
return false;
}
return true;
@@ -1058,7 +1058,7 @@ void Qt4PriFileNode::changeFiles(const FileType fileType,
QFileInfo fi(m_projectFilePath);
if (!fi.isWritable()) {
// Try via vcs manager
- Core::VCSManager *vcsManager = Core::ICore::instance()->vcsManager();
+ Core::VcsManager *vcsManager = Core::ICore::instance()->vcsManager();
Core::IVersionControl *versionControl = vcsManager->findVersionControlForDirectory(fi.absolutePath());
if (!versionControl || versionControl->vcsOpen(m_projectFilePath)) {
bool makeWritable = QFile::setPermissions(m_projectFilePath, fi.permissions() | QFile::WriteUser);
@@ -1108,7 +1108,9 @@ void Qt4PriFileNode::changeFiles(const FileType fileType,
}
// save file
+ Core::ICore::instance()->fileManager()->expectFileChange(m_projectFilePath);
save(lines);
+ Core::ICore::instance()->fileManager()->unexpectFileChange(m_projectFilePath);
// This is a hack.
// We are saving twice in a very short timeframe, once the editor and once the ProFile.
@@ -1176,6 +1178,7 @@ QStringList Qt4PriFileNode::varNames(ProjectExplorer::FileType type)
break;
default:
vars << QLatin1String("OTHER_FILES");
+ vars << QLatin1String("ICON");
break;
}
return vars;
@@ -1250,6 +1253,55 @@ TargetInformation Qt4ProFileNode::targetInformation(const QString &fileName) con
return qt4ProFileNode->targetInformation();
}
+QString Qt4ProFileNode::makefile() const
+{
+ if (m_varValues[Makefile].isEmpty())
+ return QString();
+ return m_varValues[Makefile].first();
+}
+
+QStringList Qt4ProFileNode::symbianCapabilities() const
+{
+ QStringList lowerCasedResult;
+
+ QStringList all;
+ all << "LocalServices" << "UserEnvironment" << "NetworkServices"
+ << "ReadUserData" << "WriteUserData" << "Location" << "SwEvent"
+ << "SurroundingsDD" << "ProtServ" << "PowerMgmt" << "ReadDeviceData"
+ << "WriteDeviceData" << "TrustedUI" << "NetworkControl"
+ << "MultimediaDD"<< "CommDD" << "DiskAdmin" << "AllFiles" << "DRM" << "TCB";
+
+ foreach (const QString &cap, m_varValues[SymbianCapabilities]) {
+ QString capability = cap.toLower();
+ if (capability.startsWith("-")) {
+ lowerCasedResult.removeAll(capability.mid(1));
+ } else if (capability == "all") {
+ foreach (const QString &a, all)
+ if (!lowerCasedResult.contains(a, Qt::CaseInsensitive))
+ lowerCasedResult << a.toLower();
+ } else {
+ lowerCasedResult << cap;
+ }
+ }
+ QStringList result; //let's make the result pretty
+ int index;
+ foreach (QString lowerCase, lowerCasedResult) {
+ for (int i = 0; i < all.count(); ++i) {
+ index = -1;
+ if (QString::compare(lowerCase, all.at(i),
+ Qt::CaseInsensitive) == 0) {
+ index = i;
+ break;
+ }
+ }
+ if (index != -1)
+ result << all.at(index);
+ else
+ result << lowerCase; //strange capability!
+ }
+ return result;
+}
+
/*!
\class Qt4ProFileNode
Implements abstract ProjectNode class
@@ -1259,6 +1311,7 @@ Qt4ProFileNode::Qt4ProFileNode(Qt4Project *project,
QObject *parent)
: Qt4PriFileNode(project, this, filePath),
m_projectType(InvalidProject),
+ m_validParse(false),
m_readerExact(0),
m_readerCumulative(0)
{
@@ -1310,7 +1363,12 @@ void Qt4ProFileNode::buildStateChanged(ProjectExplorer::Project *project)
bool Qt4ProFileNode::hasBuildTargets() const
{
- return (projectType() == ApplicationTemplate) || (projectType() == LibraryTemplate);
+ return hasBuildTargets(projectType());
+}
+
+bool Qt4ProFileNode::hasBuildTargets(Qt4ProjectType projectType) const
+{
+ return (projectType == ApplicationTemplate || projectType == LibraryTemplate);
}
Qt4ProjectType Qt4ProFileNode::projectType() const
@@ -1323,8 +1381,44 @@ QStringList Qt4ProFileNode::variableValue(const Qt4Variable var) const
return m_varValues.value(var);
}
+void Qt4ProFileNode::emitProFileUpdated()
+{
+ foreach (NodesWatcher *watcher, watchers())
+ if (Qt4NodesWatcher *qt4Watcher = qobject_cast<Qt4NodesWatcher*>(watcher))
+ emit qt4Watcher->proFileUpdated(this, m_validParse);
+
+ foreach (ProjectNode *subNode, subProjectNodes()) {
+ if (Qt4ProFileNode *node = qobject_cast<Qt4ProFileNode *>(subNode)) {
+ node->emitProFileUpdated();
+ }
+ }
+}
+
+
+void Qt4ProFileNode::emitProFileInvalidated()
+{
+ foreach (NodesWatcher *watcher, watchers())
+ if (Qt4NodesWatcher *qt4Watcher = qobject_cast<Qt4NodesWatcher*>(watcher))
+ emit qt4Watcher->proFileInvalidated(this);
+
+ foreach (ProjectNode *subNode, subProjectNodes()) {
+ if (Qt4ProFileNode *node = qobject_cast<Qt4ProFileNode *>(subNode)) {
+ node->emitProFileInvalidated();
+ }
+ }
+}
+
+bool Qt4ProFileNode::validParse() const
+{
+ return m_validParse;
+}
+
void Qt4ProFileNode::scheduleUpdate()
{
+ if (m_validParse) {
+ m_validParse = false;
+ emitProFileInvalidated();
+ }
m_project->scheduleAsyncUpdate(this);
}
@@ -1332,12 +1426,20 @@ void Qt4ProFileNode::asyncUpdate()
{
m_project->incrementPendingEvaluateFutures();
setupReader();
+ m_parseFutureWatcher.waitForFinished();
QFuture<bool> future = QtConcurrent::run(&Qt4ProFileNode::asyncEvaluate, this);
m_parseFutureWatcher.setFuture(future);
}
void Qt4ProFileNode::update()
{
+ if (m_validParse) {
+ m_validParse = false;
+ foreach (NodesWatcher *watcher, watchers())
+ if (Qt4NodesWatcher *qt4Watcher = qobject_cast<Qt4NodesWatcher*>(watcher))
+ emit qt4Watcher->proFileInvalidated(this);
+ }
+
setupReader();
bool parserError = evaluate();
applyEvaluate(!parserError, false);
@@ -1420,6 +1522,9 @@ void Qt4ProFileNode::applyEvaluate(bool parseResult, bool async)
m_project->proFileParseError(tr("Error while parsing file %1. Giving up.").arg(m_projectFilePath));
invalidate();
}
+ foreach (NodesWatcher *watcher, watchers())
+ if (Qt4NodesWatcher *qt4Watcher = qobject_cast<Qt4NodesWatcher*>(watcher))
+ emit qt4Watcher->proFileUpdated(this, false);
return;
}
@@ -1443,8 +1548,17 @@ void Qt4ProFileNode::applyEvaluate(bool parseResult, bool async)
Qt4ProjectType oldType = m_projectType;
// probably all subfiles/projects have changed anyway ...
clear();
+ bool changesHasBuildTargets = hasBuildTargets() ^ hasBuildTargets(projectType);
+
+ if (changesHasBuildTargets)
+ aboutToChangeHasBuildTargets();
+
m_projectType = projectType;
- // really emit here? or at the end? Noone is connected to this signal at the moment
+
+ if (changesHasBuildTargets)
+ hasBuildTargetsChanged();
+
+ // really emit here? or at the end? Nobody is connected to this signal at the moment
// so we kind of can ignore that question for now
foreach (NodesWatcher *watcher, watchers())
if (Qt4NodesWatcher *qt4Watcher = qobject_cast<Qt4NodesWatcher*>(watcher))
@@ -1508,7 +1622,7 @@ void Qt4ProFileNode::applyEvaluate(bool parseResult, bool async)
if (existingAtEnd && newExactAtEnd && newCumlativeAtEnd)
break; // we are done, hurray!
- // So this is one giant loop comparing 3 lists at once and sorting the comparision
+ // So this is one giant loop comparing 3 lists at once and sorting the comparison
// into mainly 2 buckets: toAdd and toRemove
// We need to distinguish between nodes that came from exact and cumalative
// parsing, since the update call is diffrent for them
@@ -1618,6 +1732,8 @@ void Qt4ProFileNode::applyEvaluate(bool parseResult, bool async)
// update TargetInformation
m_qt4targetInformation = targetInformation(m_readerExact);
+ setupInstallsList(m_readerExact);
+
// update other variables
QHash<Qt4Variable, QStringList> newVarValues;
@@ -1635,9 +1751,17 @@ void Qt4ProFileNode::applyEvaluate(bool parseResult, bool async)
newVarValues[ConfigVar] = m_readerExact->values(QLatin1String("CONFIG"));
newVarValues[QmlImportPathVar] = m_readerExact->absolutePathValues(
QLatin1String("QML_IMPORT_PATH"), m_projectDir);
+ newVarValues[Makefile] = m_readerExact->values("MAKEFILE");
+ // We use the cumulative parse so that we get the capabilities for symbian even if
+ // a different target is selected and the capabilities are set in a symbian scope
+
+ if (m_readerCumulative)
+ newVarValues[SymbianCapabilities] = m_readerCumulative->values("TARGET.CAPABILITY");
+
if (m_varValues != newVarValues) {
m_varValues = newVarValues;
+
foreach (NodesWatcher *watcher, watchers())
if (Qt4NodesWatcher *qt4Watcher = qobject_cast<Qt4NodesWatcher*>(watcher))
emit qt4Watcher->variablesChanged(this, m_varValues, newVarValues);
@@ -1646,9 +1770,11 @@ void Qt4ProFileNode::applyEvaluate(bool parseResult, bool async)
createUiCodeModelSupport();
updateUiFiles();
+ m_validParse = true;
+
foreach (NodesWatcher *watcher, watchers())
if (Qt4NodesWatcher *qt4Watcher = qobject_cast<Qt4NodesWatcher*>(watcher))
- emit qt4Watcher->proFileUpdated(this);
+ emit qt4Watcher->proFileUpdated(this, parseResult);
m_project->destroyProFileReader(m_readerExact);
if (m_readerCumulative)
@@ -1814,7 +1940,7 @@ QStringList Qt4ProFileNode::includePaths(ProFileReader *reader) const
paths.append(reader->absolutePathValues(QLatin1String("INCLUDEPATH"), m_projectDir));
// paths already contains moc dir and ui dir, due to corrrectly parsing uic.prf and moc.prf
// except if those directories don't exist at the time of parsing
- // thus we add those directories manually (without checking for existance)
+ // thus we add those directories manually (without checking for existence)
paths << mocDirPath(reader) << uiDirPath(reader);
paths.removeDuplicates();
return paths;
@@ -1946,6 +2072,55 @@ TargetInformation Qt4ProFileNode::targetInformation() const
return m_qt4targetInformation;
}
+void Qt4ProFileNode::setupInstallsList(const ProFileReader *reader)
+{
+ m_installsList.clear();
+ if (!reader)
+ return;
+ const QStringList &itemList = reader->values(QLatin1String("INSTALLS"));
+ foreach (const QString &item, itemList) {
+ QString itemPath;
+ const QString pathVar = item + QLatin1String(".path");
+ const QStringList &itemPaths = reader->values(pathVar);
+ if (itemPaths.count() != 1) {
+ qDebug("Invalid RHS: Variable '%s' has %d values.",
+ qPrintable(pathVar), itemPaths.count());
+ if (itemPaths.isEmpty()) {
+ qDebug("%s: Ignoring INSTALLS item '%s', because it has no path.",
+ qPrintable(m_projectFilePath), qPrintable(item));
+ continue;
+ }
+ }
+ itemPath = itemPaths.last();
+
+ const QStringList &itemFiles
+ = reader->absoluteFileValues(item + QLatin1String(".files"),
+ m_projectDir, QStringList() << m_projectDir, 0);
+ if (item == QLatin1String("target")) {
+ if (!m_installsList.targetPath.isEmpty())
+ qDebug("%s: Overwriting existing target.path in INSTALLS list.",
+ qPrintable(m_projectFilePath));
+ m_installsList.targetPath = itemPath;
+ } else {
+ if (itemFiles.isEmpty()) {
+ // TODO: Fix QMAKE_SUBSTITUTES handling in pro file reader, then uncomment again
+// if (!reader->values(item + QLatin1String(".CONFIG"))
+// .contains(QLatin1String("no_check_exist"))) {
+// qDebug("%s: Ignoring INSTALLS item '%s', because it has no files.",
+// qPrintable(m_projectFilePath), qPrintable(item));
+// }
+ continue;
+ }
+ m_installsList.items << InstallsItem(itemPath, itemFiles);
+ }
+ }
+}
+
+InstallsList Qt4ProFileNode::installsList() const
+{
+ return m_installsList;
+}
+
QString Qt4ProFileNode::buildDir() const
{
const QDir srcDirRoot = QFileInfo(m_project->rootProjectNode()->path()).absoluteDir();
diff --git a/src/plugins/qt4projectmanager/qt4nodes.h b/src/plugins/qt4projectmanager/qt4nodes.h
index 95f8fa7610..cf811d7539 100644
--- a/src/plugins/qt4projectmanager/qt4nodes.h
+++ b/src/plugins/qt4projectmanager/qt4nodes.h
@@ -99,7 +99,9 @@ enum Qt4Variable {
PrecompiledHeaderVar,
LibDirectoriesVar,
ConfigVar,
- QmlImportPathVar
+ QmlImportPathVar,
+ Makefile,
+ SymbianCapabilities
};
class Qt4PriFileNode;
@@ -251,6 +253,18 @@ struct TargetInformation
};
+struct InstallsItem {
+ InstallsItem(QString p, QStringList f) : path(p), files(f) {}
+ QString path;
+ QStringList files;
+};
+
+struct InstallsList {
+ void clear() { targetPath.clear(); items.clear(); }
+ QString targetPath;
+ QList<InstallsItem> items;
+};
+
// Implements ProjectNode for qt4 pro files
class Qt4ProFileNode : public Qt4PriFileNode
{
@@ -282,9 +296,20 @@ public:
TargetInformation targetInformation(const QString &fileName) const;
TargetInformation targetInformation() const;
+ InstallsList installsList() const;
+
+ QString makefile() const;
+ QStringList symbianCapabilities() const;
+
void update();
void scheduleUpdate();
+ void emitProFileInvalidated();
+ void emitProFileUpdated();
+
+ bool validParse() const;
+
+ bool hasBuildTargets(Qt4ProjectType projectType) const;
public slots:
void asyncUpdate();
@@ -310,6 +335,7 @@ private:
QStringList libDirectories(ProFileReader *reader) const;
QStringList subDirsPaths(ProFileReader *reader) const;
TargetInformation targetInformation(ProFileReader *reader) const;
+ void setupInstallsList(const ProFileReader *reader);
void invalidate();
@@ -318,8 +344,11 @@ private:
QMap<QString, QDateTime> m_uitimestamps;
TargetInformation m_qt4targetInformation;
+ InstallsList m_installsList;
friend class Qt4NodeHierarchy;
+ bool m_validParse;
+
// Async stuff
QFutureWatcher<bool> m_parseFutureWatcher;
ProFileReader *m_readerExact;
@@ -342,7 +371,8 @@ signals:
const QHash<Qt4Variable, QStringList> &oldValues,
const QHash<Qt4Variable, QStringList> &newValues);
- void proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode *projectNode);
+ void proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode *projectNode, bool success);
+ void proFileInvalidated(Qt4ProjectManager::Internal::Qt4ProFileNode *projectNode);
private:
// let them emit signals
diff --git a/src/plugins/qt4projectmanager/qt4project.cpp b/src/plugins/qt4projectmanager/qt4project.cpp
index e52cc6a7b4..4fc67eb505 100644
--- a/src/plugins/qt4projectmanager/qt4project.cpp
+++ b/src/plugins/qt4projectmanager/qt4project.cpp
@@ -53,6 +53,7 @@
#include <extensionsystem/pluginmanager.h>
#include <cpptools/cppmodelmanagerinterface.h>
#include <qmljs/qmljsmodelmanagerinterface.h>
+#include <projectexplorer/toolchain.h>
#include <projectexplorer/buildenvironmentwidget.h>
#include <projectexplorer/customexecutablerunconfiguration.h>
#include <projectexplorer/projectexplorer.h>
@@ -252,7 +253,6 @@ Qt4Project::Qt4Project(Qt4Manager *manager, const QString& fileName) :
m_manager(manager),
m_rootProjectNode(0),
m_nodesWatcher(new Internal::Qt4NodesWatcher(this)),
- m_targetFactory(new Qt4TargetFactory(this)),
m_fileInfo(new Qt4ProjectFile(this, fileName, this)),
m_projectFiles(new Qt4ProjectFiles),
m_proFileOption(0),
@@ -297,7 +297,7 @@ bool Qt4Project::fromMap(const QVariantMap &map)
// Prune targets without buildconfigurations:
// This can happen esp. when updating from a old version of Qt Creator
- QList<Target *>ts(targets());
+ QList<Target *>ts = targets();
foreach (Target *t, ts) {
if (t->buildConfigurations().isEmpty()) {
qWarning() << "Removing" << t->id() << "since it has no buildconfigurations!";
@@ -334,6 +334,17 @@ bool Qt4Project::fromMap(const QVariantMap &map)
setSupportedTargetIds(QtVersionManager::instance()->supportedTargetIds());
+
+ connect(m_nodesWatcher, SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode*,bool)),
+ this, SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode *,bool)));
+
+ connect(m_nodesWatcher, SIGNAL(proFileInvalidated(Qt4ProjectManager::Internal::Qt4ProFileNode*)),
+ this, SIGNAL(proFileInvalidated(Qt4ProjectManager::Internal::Qt4ProFileNode*)));
+
+ // Now we emit update once :)
+ m_rootProjectNode->emitProFileUpdated();
+
+
// Setup Qt versions supported (== possible targets).
connect(this, SIGNAL(addedTarget(ProjectExplorer::Target*)),
this, SLOT(onAddedTarget(ProjectExplorer::Target*)));
@@ -341,20 +352,12 @@ bool Qt4Project::fromMap(const QVariantMap &map)
connect(QtVersionManager::instance(), SIGNAL(qtVersionsChanged(QList<int>)),
this, SLOT(qtVersionsChanged()));
- connect(m_nodesWatcher, SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode *)),
- this, SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode *)));
-
connect(this, SIGNAL(activeTargetChanged(ProjectExplorer::Target*)),
this, SLOT(activeTargetWasChanged()));
return true;
}
-Qt4TargetFactory *Qt4Project::targetFactory() const
-{
- return m_targetFactory;
-}
-
Qt4Target *Qt4Project::activeTarget() const
{
return static_cast<Qt4Target *>(Project::activeTarget());
@@ -367,11 +370,11 @@ void Qt4Project::onAddedTarget(ProjectExplorer::Target *t)
Q_ASSERT(qt4target);
connect(qt4target, SIGNAL(buildDirectoryInitialized()),
this, SIGNAL(buildDirectoryInitialized()));
- connect(qt4target, SIGNAL(proFileEvaluateNeeded(Qt4ProjectManager::Internal::Qt4Target*)),
- this, SLOT(proFileEvaluateNeeded(Qt4ProjectManager::Internal::Qt4Target*)));
+ connect(qt4target, SIGNAL(proFileEvaluateNeeded(Qt4ProjectManager::Qt4Target*)),
+ this, SLOT(proFileEvaluateNeeded(Qt4ProjectManager::Qt4Target*)));
}
-void Qt4Project::proFileEvaluateNeeded(Qt4ProjectManager::Internal::Qt4Target *target)
+void Qt4Project::proFileEvaluateNeeded(Qt4ProjectManager::Qt4Target *target)
{
if (activeTarget() == target)
scheduleAsyncUpdate();
@@ -577,17 +580,12 @@ void Qt4Project::updateCppCodeModel()
void Qt4Project::updateQmlJSCodeModel()
{
- if (m_projectFiles->files[QMLType].isEmpty())
- return;
-
QmlJS::ModelManagerInterface *modelManager = QmlJS::ModelManagerInterface::instance();
if (!modelManager)
return;
QmlJS::ModelManagerInterface::ProjectInfo projectInfo = modelManager->projectInfo(this);
-
- // Not essential since the QmlJS engine parses required files on demand.
- //projectInfo.sourceFiles = ...
+ projectInfo.sourceFiles = m_projectFiles->files[QMLType];
FindQt4ProFiles findQt4ProFiles;
QList<Qt4ProFileNode *> proFiles = findQt4ProFiles(rootProjectNode());
@@ -622,6 +620,7 @@ void Qt4Project::update()
if (debug)
qDebug()<<"Doing sync update";
m_rootProjectNode->update();
+
if (debug)
qDebug()<<"State is now Base";
m_asyncUpdateState = Base;
@@ -629,6 +628,9 @@ void Qt4Project::update()
void Qt4Project::scheduleAsyncUpdate(Qt4ProFileNode *node)
{
+ if (m_asyncUpdateState == ShuttingDown)
+ return;
+
if (debug)
qDebug()<<"schduleAsyncUpdate (node)";
Q_ASSERT(m_asyncUpdateState != NoState);
@@ -695,6 +697,9 @@ void Qt4Project::scheduleAsyncUpdate()
{
if (debug)
qDebug()<<"scheduleAsyncUpdate";
+ if (m_asyncUpdateState == ShuttingDown)
+ return;
+
Q_ASSERT(m_asyncUpdateState != NoState);
if (m_cancelEvaluate) { // we are in progress of canceling
// and will start the evaluation after that
@@ -707,12 +712,14 @@ void Qt4Project::scheduleAsyncUpdate()
qDebug()<<" update in progress, canceling and setting state to full update pending";
m_cancelEvaluate = true;
m_asyncUpdateState = AsyncFullUpdatePending;
+ m_rootProjectNode->emitProFileInvalidated();
return;
}
if (debug)
qDebug()<<" starting timer for full update, setting state to full update pending";
m_partialEvaluate.clear();
+ m_rootProjectNode->emitProFileInvalidated();
m_asyncUpdateState = AsyncFullUpdatePending;
m_asyncUpdateTimer.start();
@@ -756,7 +763,7 @@ void Qt4Project::decrementPendingEvaluateFutures()
qDebug()<<" Oh update is pending start the timer";
m_asyncUpdateTimer.start();
} else if (m_asyncUpdateState != ShuttingDown){
- // After beeing done, we need to call:
+ // After being done, we need to call:
updateFileList();
updateCodeModels();
if (debug)
@@ -950,9 +957,12 @@ Qt4ProFileNode *Qt4Project::rootProjectNode() const
return m_rootProjectNode;
}
-BuildConfigWidget *Qt4Project::createConfigWidget()
+bool Qt4Project::validParse(const QString &proFilePath) const
{
- return new Qt4ProjectConfigWidget(this);
+ if (!m_rootProjectNode)
+ return false;
+ const Qt4ProFileNode *node = m_rootProjectNode->findProFileFor(proFilePath);
+ return node && node->validParse();
}
QList<BuildConfigWidget*> Qt4Project::subConfigWidgets()
diff --git a/src/plugins/qt4projectmanager/qt4project.h b/src/plugins/qt4projectmanager/qt4project.h
index 6b4d317050..7a025770c4 100644
--- a/src/plugins/qt4projectmanager/qt4project.h
+++ b/src/plugins/qt4projectmanager/qt4project.h
@@ -155,19 +155,17 @@ public:
ProjectExplorer::IProjectManager *projectManager() const;
Qt4Manager *qt4ProjectManager() const;
- Internal::Qt4TargetFactory *targetFactory() const;
-
- Internal::Qt4Target *activeTarget() const;
+ Qt4Target *activeTarget() const;
QList<Core::IFile *> dependencies(); //NBS remove
QList<ProjectExplorer::Project *>dependsOn();
Internal::Qt4ProFileNode *rootProjectNode() const;
+ bool validParse(const QString &proFilePath) const;
virtual QStringList files(FilesMode fileMode) const;
virtual QString generatedUiHeader(const QString &formFile) const;
- ProjectExplorer::BuildConfigWidget *createConfigWidget();
QList<ProjectExplorer::BuildConfigWidget*> subConfigWidgets();
QList<Internal::Qt4ProFileNode *> leafProFiles() const;
@@ -200,8 +198,8 @@ public:
void updateFileList();
signals:
- /// emitted after parse
- void proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode *node);
+ void proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode *node, bool);
+ void proFileInvalidated(Qt4ProjectManager::Internal::Qt4ProFileNode *node);
void buildDirectoryInitialized();
public slots:
@@ -212,7 +210,7 @@ protected:
virtual bool fromMap(const QVariantMap &map);
private slots:
- void proFileEvaluateNeeded(Qt4ProjectManager::Internal::Qt4Target *target);
+ void proFileEvaluateNeeded(Qt4ProjectManager::Qt4Target *target);
void asyncUpdate();
@@ -243,7 +241,6 @@ private:
Qt4Manager *m_manager;
Internal::Qt4ProFileNode *m_rootProjectNode;
Internal::Qt4NodesWatcher *m_nodesWatcher;
- Internal::Qt4TargetFactory *m_targetFactory;
Qt4ProjectFile *m_fileInfo;
diff --git a/src/plugins/qt4projectmanager/qt4projectconfigwidget.cpp b/src/plugins/qt4projectmanager/qt4projectconfigwidget.cpp
index 8becdca46a..857d12781c 100644
--- a/src/plugins/qt4projectmanager/qt4projectconfigwidget.cpp
+++ b/src/plugins/qt4projectmanager/qt4projectconfigwidget.cpp
@@ -36,16 +36,19 @@
#include "makestep.h"
#include "qmakestep.h"
#include "qt4project.h"
+#include "qt4target.h"
#include "qt4projectmanagerconstants.h"
#include "qt4projectmanager.h"
#include "qt4buildconfiguration.h"
#include "ui_qt4projectconfigwidget.h"
#include <coreplugin/icore.h>
-#include <coreplugin/mainwindow.h>
+
+#include <projectexplorer/toolchain.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/buildconfiguration.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <extensionsystem/pluginmanager.h>
#include <QtGui/QFileDialog>
@@ -60,12 +63,11 @@ using namespace Qt4ProjectManager;
using namespace Qt4ProjectManager::Internal;
using ProjectExplorer::ToolChain;
-Qt4ProjectConfigWidget::Qt4ProjectConfigWidget(Qt4Project *project)
+Qt4ProjectConfigWidget::Qt4ProjectConfigWidget(Qt4Target *target)
: BuildConfigWidget(),
m_buildConfiguration(0),
m_ignoreChange(false)
{
- Q_UNUSED(project);
QVBoxLayout *vbox = new QVBoxLayout(this);
vbox->setMargin(0);
m_detailsContainer = new Utils::DetailsWidget(this);
@@ -81,7 +83,7 @@ Qt4ProjectConfigWidget::Qt4ProjectConfigWidget(Qt4Project *project)
m_ui->shadowBuildDirEdit->setPromptDialogTitle(tr("Shadow Build Directory"));
m_ui->shadowBuildDirEdit->setExpectedKind(Utils::PathChooser::Directory);
- m_ui->shadowBuildDirEdit->setBaseDirectory(project->projectDirectory());
+ m_ui->shadowBuildDirEdit->setBaseDirectory(target->qt4Project()->projectDirectory());
connect(m_ui->shadowBuildCheckBox, SIGNAL(clicked(bool)),
this, SLOT(shadowBuildClicked(bool)));
@@ -104,10 +106,10 @@ Qt4ProjectConfigWidget::Qt4ProjectConfigWidget(Qt4Project *project)
connect(m_ui->manageQtVersionPushButtons, SIGNAL(clicked()),
this, SLOT(manageQtVersions()));
- connect(project, SIGNAL(environmentChanged()),
+ connect(target->qt4Project(), SIGNAL(environmentChanged()),
this, SLOT(environmentChanged()));
- connect(project, SIGNAL(buildDirectoryInitialized()),
+ connect(target->qt4Project(), SIGNAL(buildDirectoryInitialized()),
this, SLOT(updateImportLabel()));
}
@@ -307,16 +309,26 @@ void Qt4ProjectConfigWidget::updateImportLabel()
{
bool visible = false;
bool targetMatches = false;
+ bool incompatibleBuild = false;
QtVersionManager *vm = QtVersionManager::instance();
// we only show if we actually have a qmake and makestep
if (m_buildConfiguration->qmakeStep() && m_buildConfiguration->makeStep()) {
- QString qmakePath = QtVersionManager::findQMakeBinaryFromMakefile(m_buildConfiguration->buildDirectory());
+ QString makefile = m_buildConfiguration->buildDirectory();
+ if (m_buildConfiguration->makefile().isEmpty())
+ makefile.append("/Makefile");
+ else
+ makefile.append(m_buildConfiguration->makefile());
+
+ QString qmakePath = QtVersionManager::findQMakeBinaryFromMakefile(makefile);
QtVersion *version = m_buildConfiguration->qtVersion();
// check that there's a makefile
if (!qmakePath.isEmpty()) {
- // and that the qmake path is different from the current version
- if (qmakePath != (version ? version->qmakeCommand() : QString())) {
+ // Is it from the same build?
+ if (!QtVersionManager::makefileIsFor(makefile, m_buildConfiguration->target()->project()->file()->fileName())) {
+ incompatibleBuild = true;
+ } else if (qmakePath != (version ? version->qmakeCommand() : QString())) {
+ // and that the qmake path is different from the current version
// import enable
visible = true;
QtVersion *newVersion = vm->qtVersionForQMakeBinary(qmakePath);
@@ -330,11 +342,9 @@ void Qt4ProjectConfigWidget::updateImportLabel()
delete newVersion;
} else {
// check that the qmake flags, arguments match
- visible = !m_buildConfiguration->compareToImportFrom(m_buildConfiguration->buildDirectory());
+ visible = !m_buildConfiguration->compareToImportFrom(makefile);
targetMatches = true;
}
- } else {
- visible = false;
}
}
@@ -344,7 +354,14 @@ void Qt4ProjectConfigWidget::updateImportLabel()
QList<ProjectExplorer::Task> issues = m_buildConfiguration->qtVersion()->reportIssues(m_buildConfiguration->target()->project()->file()->fileName(),
buildDirectory);
- if (!issues.isEmpty()) {
+ if (incompatibleBuild) {
+ m_ui->problemLabel->setVisible(true);
+ m_ui->warningLabel->setVisible(true);
+ m_ui->importLabel->setVisible(false);
+ m_ui->problemLabel->setText(tr("An build for a different project exists in %1, which will be overwritten.",
+ "%1 build directory").
+ arg(m_ui->shadowBuildDirEdit->path()));
+ } else if (!issues.isEmpty()) {
m_ui->problemLabel->setVisible(true);
m_ui->warningLabel->setVisible(true);
m_ui->importLabel->setVisible(visible);
@@ -389,7 +406,13 @@ void Qt4ProjectConfigWidget::importLabelClicked()
return;
QString directory = m_buildConfiguration->buildDirectory();
if (!directory.isEmpty()) {
- QString qmakePath = QtVersionManager::findQMakeBinaryFromMakefile(directory);
+ QString makefile = directory;
+ if (m_buildConfiguration->makefile().isEmpty())
+ makefile.append("/Makefile");
+ else
+ makefile.append(m_buildConfiguration->makefile());
+
+ QString qmakePath = QtVersionManager::findQMakeBinaryFromMakefile(makefile);
if (!qmakePath.isEmpty()) {
QtVersionManager *vm = QtVersionManager::instance();
QtVersion *version = vm->qtVersionForQMakeBinary(qmakePath);
@@ -398,20 +421,22 @@ void Qt4ProjectConfigWidget::importLabelClicked()
vm->addVersion(version);
}
- QPair<QtVersion::QmakeBuildConfigs, QStringList> result =
+ QPair<QtVersion::QmakeBuildConfigs, QString> result =
QtVersionManager::scanMakeFile(directory, version->defaultBuildConfig());
QtVersion::QmakeBuildConfigs qmakeBuildConfig = result.first;
- QStringList additionalArguments = Qt4BuildConfiguration::removeSpecFromArgumentList(result.second);
- QString parsedSpec = Qt4BuildConfiguration::extractSpecFromArgumentList(result.second, directory, version);
+
+ QString aa = result.second;
+ QString parsedSpec = Qt4BuildConfiguration::extractSpecFromArguments(&aa, directory, version);
QString versionSpec = version->mkspec();
+ QString additionalArguments;
if (parsedSpec.isEmpty() || parsedSpec == versionSpec || parsedSpec == "default") {
// using the default spec, don't modify additional arguments
} else {
- additionalArguments.prepend(parsedSpec);
- additionalArguments.prepend("-spec");
+ additionalArguments = "-spec " + Utils::QtcProcess::quoteArg(parsedSpec);
}
+ Utils::QtcProcess::addArgs(&additionalArguments, aa);
- additionalArguments = Qt4BuildConfiguration::removeQMLInspectorFromArgumentList(additionalArguments);
+ Qt4BuildConfiguration::removeQMLInspectorFromArguments(&additionalArguments);
// So we got all the information now apply it...
m_buildConfiguration->setQtVersion(version);
@@ -425,16 +450,25 @@ void Qt4ProjectConfigWidget::importLabelClicked()
// If we are switching to BuildAll we want "release" in there and no "debug"
// or "debug" in there and no "release"
// If we are switching to not BuildAl we want neither "release" nor "debug" in there
- QStringList makeCmdArguments = makeStep->userArguments();
bool debug = qmakeBuildConfig & QtVersion::DebugBuild;
- if (qmakeBuildConfig & QtVersion::BuildAll) {
- makeCmdArguments.removeAll(debug ? "release" : "debug");
- if (!makeCmdArguments.contains(debug ? "debug" : "release"))
- makeCmdArguments.append(debug ? "debug" : "release");
- } else {
- makeCmdArguments.removeAll("debug");
- makeCmdArguments.removeAll("release");
+ bool haveTag = !(qmakeBuildConfig & QtVersion::BuildAll);
+ QString makeCmdArguments = makeStep->userArguments();
+ Utils::QtcProcess::ArgIterator ait(&makeCmdArguments);
+ while (ait.next()) {
+ if (ait.value() == QLatin1String("debug")) {
+ if (!haveTag && debug)
+ haveTag = true;
+ else
+ ait.deleteArg();
+ } else if (ait.value() == QLatin1String("release")) {
+ if (!haveTag && !debug)
+ haveTag = true;
+ else
+ ait.deleteArg();
+ }
}
+ if (!haveTag)
+ ait.appendArg(QLatin1String(debug ? "debug" : "release"));
makeStep->setUserArguments(makeCmdArguments);
}
}
@@ -471,8 +505,8 @@ void Qt4ProjectConfigWidget::toolChainTypeChanged()
if (m_ignoreChange)
return;
for (int i=0; i < m_ui->toolChainComboBox->count(); ++i) {
- ProjectExplorer::ToolChain::ToolChainType tt =
- m_ui->toolChainComboBox->itemData(i, Qt::UserRole).value<ProjectExplorer::ToolChain::ToolChainType>();
+ ProjectExplorer::ToolChainType tt =
+ m_ui->toolChainComboBox->itemData(i, Qt::UserRole).value<ProjectExplorer::ToolChainType>();
if (tt == m_buildConfiguration->toolChainType()) {
m_ignoreChange = true;
m_ui->toolChainComboBox->setCurrentIndex(i);
@@ -484,12 +518,12 @@ void Qt4ProjectConfigWidget::toolChainTypeChanged()
void Qt4ProjectConfigWidget::updateToolChainCombo()
{
m_ui->toolChainComboBox->clear();
- QList<ProjectExplorer::ToolChain::ToolChainType> toolchains =
+ QList<ProjectExplorer::ToolChainType> toolchains =
m_buildConfiguration->qtVersion()->possibleToolChainTypes();
toolchains = m_buildConfiguration->qt4Target()->filterToolChainTypes(toolchains);
- foreach (ToolChain::ToolChainType toolchain, toolchains)
+ foreach (ProjectExplorer::ToolChainType toolchain, toolchains)
m_ui->toolChainComboBox->addItem(ToolChain::toolChainName(toolchain), qVariantFromValue(toolchain));
m_ui->toolChainComboBox->setEnabled(toolchains.size() > 1);
@@ -502,9 +536,9 @@ void Qt4ProjectConfigWidget::toolChainSelected(int index)
{
if (m_ignoreChange)
return;
- ProjectExplorer::ToolChain::ToolChainType selectedToolChainType =
+ ProjectExplorer::ToolChainType selectedToolChainType =
m_ui->toolChainComboBox->itemData(index,
- Qt::UserRole).value<ProjectExplorer::ToolChain::ToolChainType>();
+ Qt::UserRole).value<ProjectExplorer::ToolChainType>();
m_ignoreChange = true;
m_buildConfiguration->setToolChainType(selectedToolChainType);
m_ignoreChange = false;
diff --git a/src/plugins/qt4projectmanager/qt4projectconfigwidget.h b/src/plugins/qt4projectmanager/qt4projectconfigwidget.h
index 161cbb2340..1012f4c042 100644
--- a/src/plugins/qt4projectmanager/qt4projectconfigwidget.h
+++ b/src/plugins/qt4projectmanager/qt4projectconfigwidget.h
@@ -45,12 +45,11 @@ namespace Utils {
}
namespace Qt4ProjectManager {
-
-class Qt4Project;
-
-namespace Internal {
+class Qt4Target;
class Qt4BuildConfiguration;
+class Qt4Target;
+namespace Internal {
namespace Ui {
class Qt4ProjectConfigWidget;
}
@@ -59,7 +58,7 @@ class Qt4ProjectConfigWidget : public ProjectExplorer::BuildConfigWidget
{
Q_OBJECT
public:
- explicit Qt4ProjectConfigWidget(Qt4Project *project);
+ explicit Qt4ProjectConfigWidget(Qt4Target *target);
~Qt4ProjectConfigWidget();
QString displayName() const;
diff --git a/src/plugins/qt4projectmanager/qt4projectmanager.pri b/src/plugins/qt4projectmanager/qt4projectmanager.pri
index 34db66a9c4..d3f03488b5 100644
--- a/src/plugins/qt4projectmanager/qt4projectmanager.pri
+++ b/src/plugins/qt4projectmanager/qt4projectmanager.pri
@@ -1,3 +1,3 @@
include(qt4projectmanager_dependencies.pri)
-LIBS *= -l$$qtLibraryTarget(Qt4ProjectManager)
+LIBS *= -l$$qtLibraryName(Qt4ProjectManager)
diff --git a/src/plugins/qt4projectmanager/qt4projectmanager.pro b/src/plugins/qt4projectmanager/qt4projectmanager.pro
index e456017ebe..9e221211fd 100644
--- a/src/plugins/qt4projectmanager/qt4projectmanager.pro
+++ b/src/plugins/qt4projectmanager/qt4projectmanager.pro
@@ -41,6 +41,8 @@ HEADERS += qt4deployconfiguration.h \
wizards/abstractmobileapp.h \
wizards/qmlstandaloneapp.h \
wizards/abstractmobileappwizard.h \
+ wizards/subdirsprojectwizard.h \
+ wizards/subdirsprojectwizarddialog.h \
qt4projectmanagerconstants.h \
makestep.h \
qmakestep.h \
@@ -63,7 +65,9 @@ HEADERS += qt4deployconfiguration.h \
findqt4profiles.h \
qt4projectmanager_global.h \
qmldumptool.h \
- qmlobservertool.h
+ qmlobservertool.h \
+ profilecompletion.h \
+ profilekeywords.h
SOURCES += qt4projectmanagerplugin.cpp \
qt4deployconfiguration.cpp \
qtparser.cpp \
@@ -101,6 +105,8 @@ SOURCES += qt4projectmanagerplugin.cpp \
wizards/abstractmobileapp.cpp \
wizards/qmlstandaloneapp.cpp \
wizards/abstractmobileappwizard.cpp \
+ wizards/subdirsprojectwizard.cpp \
+ wizards/subdirsprojectwizarddialog.cpp \
makestep.cpp \
qmakestep.cpp \
qt4runconfiguration.cpp \
@@ -121,7 +127,9 @@ SOURCES += qt4projectmanagerplugin.cpp \
librarydetailscontroller.cpp \
findqt4profiles.cpp \
qmldumptool.cpp \
- qmlobservertool.cpp
+ qmlobservertool.cpp \
+ profilecompletion.cpp \
+ profilekeywords.cpp
FORMS += makestep.ui \
qmakestep.ui \
qt4projectconfigwidget.ui \
@@ -131,8 +139,10 @@ FORMS += makestep.ui \
wizards/testwizardpage.ui \
wizards/targetsetuppage.ui \
wizards/qmlstandaloneappwizardsourcespage.ui \
- wizards/mobileappwizardoptionspage.ui \
wizards/mobilelibrarywizardoptionpage.ui \
+ wizards/mobileappwizardgenericoptionspage.ui \
+ wizards/mobileappwizardsymbianoptionspage.ui \
+ wizards/mobileappwizardmaemooptionspage.ui \
librarydetailswidget.ui
RESOURCES += qt4projectmanager.qrc \
wizards/wizards.qrc
@@ -142,4 +152,4 @@ include(qt-s60/qt-s60.pri)
include(qt-maemo/qt-maemo.pri)
include(customwidgetwizard/customwidgetwizard.pri)
DEFINES += QT_NO_CAST_TO_ASCII
-OTHER_FILES += Qt4ProjectManager.pluginspec Qt4ProjectManager.mimetypes.xml
+OTHER_FILES += Qt4ProjectManager.mimetypes.xml
diff --git a/src/plugins/qt4projectmanager/qt4projectmanager_dependencies.pri b/src/plugins/qt4projectmanager/qt4projectmanager_dependencies.pri
index 9fe2506a39..17ef00b7ae 100644
--- a/src/plugins/qt4projectmanager/qt4projectmanager_dependencies.pri
+++ b/src/plugins/qt4projectmanager/qt4projectmanager_dependencies.pri
@@ -1,6 +1,5 @@
include(../../plugins/projectexplorer/projectexplorer.pri)
include(../../plugins/cpptools/cpptools.pri)
-include(../../plugins/cppeditor/cppeditor.pri)
include(../../plugins/designer/designer.pri)
include(../../plugins/debugger/debugger.pri)
include(../../libs/symbianutils/symbianutils.pri)
diff --git a/src/plugins/qt4projectmanager/qt4projectmanagerconstants.h b/src/plugins/qt4projectmanager/qt4projectmanagerconstants.h
index 78f6384dac..7ce0b39f84 100644
--- a/src/plugins/qt4projectmanager/qt4projectmanagerconstants.h
+++ b/src/plugins/qt4projectmanager/qt4projectmanagerconstants.h
@@ -69,6 +69,8 @@ const char * const BUILDSUBDIR = "Qt4Builder.BuildSubDir";
const char * const REBUILDSUBDIR = "Qt4Builder.RebuildSubDir";
const char * const CLEANSUBDIR = "Qt4Builder.CleanSubDir";
const char * const ADDLIBRARY = "Qt4.AddLibrary";
+const char * const JUMP_TO_FILE = "Qt4.JumpToFile";
+const char * const SEPARATOR = "Qt4.Separator";
//configurations
const char * const CONFIG_DEBUG = "debug";
@@ -110,11 +112,11 @@ const char * const PROFILE_EVALUATE = "Qt4ProjectManager.ProFileEvaluate";
const char * const QT4PROJECT_ID("Qt4ProjectManager.Qt4Project");
// Targets
-const char * const DESKTOP_TARGET_ID("Qt4ProjectManager.Target.DesktopTarget");
-const char * const S60_EMULATOR_TARGET_ID("Qt4ProjectManager.Target.S60EmulatorTarget");
-const char * const S60_DEVICE_TARGET_ID("Qt4ProjectManager.Target.S60DeviceTarget");
-const char * const MAEMO_DEVICE_TARGET_ID("Qt4ProjectManager.Target.MaemoDeviceTarget");
-const char * const QT_SIMULATOR_TARGET_ID("Qt4ProjectManager.Target.QtSimulatorTarget");
+const char * const DESKTOP_TARGET_ID = "Qt4ProjectManager.Target.DesktopTarget";
+const char * const S60_EMULATOR_TARGET_ID = "Qt4ProjectManager.Target.S60EmulatorTarget";
+const char * const S60_DEVICE_TARGET_ID = "Qt4ProjectManager.Target.S60DeviceTarget";
+const char * const MAEMO_DEVICE_TARGET_ID = "Qt4ProjectManager.Target.MaemoDeviceTarget";
+const char * const QT_SIMULATOR_TARGET_ID = "Qt4ProjectManager.Target.QtSimulatorTarget";
// ICONS
const char * const ICON_QT_PROJECT = ":/qt4projectmanager/images/qt_project.png";
diff --git a/src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp b/src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp
index f5e6171a37..f06d3b610e 100644
--- a/src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp
+++ b/src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp
@@ -42,6 +42,7 @@
#include "wizards/librarywizard.h"
#include "wizards/testwizard.h"
#include "wizards/emptyprojectwizard.h"
+#include "wizards/subdirsprojectwizard.h"
#include "wizards/qmlstandaloneappwizard.h"
#include "customwidgetwizard/customwidgetwizard.h"
#include "profileeditorfactory.h"
@@ -54,6 +55,7 @@
#include "qtoptionspage.h"
#include "externaleditors.h"
#include "gettingstartedwelcomepage.h"
+#include "profilecompletion.h"
#include "qt-maemo/maemomanager.h"
#include "qt-s60/s60manager.h"
@@ -74,6 +76,7 @@
#include <coreplugin/editormanager/editormanager.h>
#include <texteditor/texteditoractionhandler.h>
#include <texteditor/texteditorconstants.h>
+#include <texteditor/texteditorsettings.h>
#ifdef WITH_TESTS
# include <QTest>
@@ -134,20 +137,12 @@ bool Qt4ProjectManagerPlugin::initialize(const QStringList &arguments, QString *
addObject(m_proFileEditorFactory);
addAutoReleasedObject(new EmptyProjectWizard);
-
- GuiAppWizard *guiWizard = new GuiAppWizard;
- addAutoReleasedObject(guiWizard);
-
- ConsoleAppWizard *consoleWizard = new ConsoleAppWizard;
- addAutoReleasedObject(consoleWizard);
-
- MobileAppWizard *mobileWizard = new MobileAppWizard;
- addAutoReleasedObject(mobileWizard);
-
+ addAutoReleasedObject(new SubdirsProjectWizard);
+ addAutoReleasedObject(new GuiAppWizard);
+ addAutoReleasedObject(new ConsoleAppWizard);
+ addAutoReleasedObject(new MobileAppWizard);
addAutoReleasedObject(new QmlStandaloneAppWizard());
-
- LibraryWizard *libWizard = new LibraryWizard;
- addAutoReleasedObject(libWizard);
+ addAutoReleasedObject(new LibraryWizard);
addAutoReleasedObject(new TestWizard);
addAutoReleasedObject(new CustomWidgetWizard);
@@ -156,6 +151,7 @@ bool Qt4ProjectManagerPlugin::initialize(const QStringList &arguments, QString *
addAutoReleasedObject(new QMakeStepFactory);
addAutoReleasedObject(new MakeStepFactory);
+ addAutoReleasedObject(new Qt4TargetFactory);
addAutoReleasedObject(new Qt4RunConfigurationFactory);
#ifdef Q_OS_MAC
@@ -168,6 +164,14 @@ bool Qt4ProjectManagerPlugin::initialize(const QStringList &arguments, QString *
addAutoReleasedObject(new S60Manager);
addAutoReleasedObject(new MaemoManager);
+ ProFileCompletion *completion = new ProFileCompletion;
+ addAutoReleasedObject(completion);
+ // Set completion settings and keep them up to date
+ TextEditor::TextEditorSettings *textEditorSettings = TextEditor::TextEditorSettings::instance();
+ completion->setCompletionSettings(textEditorSettings->completionSettings());
+ connect(textEditorSettings, SIGNAL(completionSettingsChanged(TextEditor::CompletionSettings)),
+ completion, SLOT(setCompletionSettings(TextEditor::CompletionSettings)));
+
new ProFileCacheManager(this);
// TODO reenable
@@ -236,19 +240,31 @@ bool Qt4ProjectManagerPlugin::initialize(const QStringList &arguments, QString *
Core::Command *cmd;
- cmd = am->command(TextEditor::Constants::UN_COMMENT_SELECTION);
- contextMenu->addAction(cmd);
+ Core::Context proFileEditorContext = Core::Context(Qt4ProjectManager::Constants::C_PROFILEEDITOR);
- Core::Context proFileEditorContext = Core::Context(Qt4ProjectManager::Constants::PROJECT_ID);
+ QAction *jumpToFile = new QAction(tr("Jump to File Under Cursor"), this);
+ cmd = am->registerAction(jumpToFile,
+ Constants::JUMP_TO_FILE, proFileEditorContext);
+ cmd->setDefaultKeySequence(QKeySequence(Qt::Key_F2));
+ connect(jumpToFile, SIGNAL(triggered()),
+ this, SLOT(jumpToFile()));
+ contextMenu->addAction(cmd);
QAction *addLibrary = new QAction(tr("Add Library..."), this);
cmd = am->registerAction(addLibrary,
Constants::ADDLIBRARY, proFileEditorContext);
- //cmd->setDefaultKeySequence(QKeySequence(Qt::Key_F2));
connect(addLibrary, SIGNAL(triggered()),
this, SLOT(addLibrary()));
contextMenu->addAction(cmd);
+ QAction *separator = new QAction(this);
+ separator->setSeparator(true);
+ contextMenu->addAction(am->registerAction(separator,
+ Core::Id(Constants::SEPARATOR), proFileEditorContext));
+
+ cmd = am->command(TextEditor::Constants::UN_COMMENT_SELECTION);
+ contextMenu->addAction(cmd);
+
return true;
}
@@ -310,6 +326,14 @@ void Qt4ProjectManagerPlugin::addLibrary()
editor->addLibrary();
}
+void Qt4ProjectManagerPlugin::jumpToFile()
+{
+ Core::EditorManager *em = Core::EditorManager::instance();
+ ProFileEditor *editor = qobject_cast<ProFileEditor*>(em->currentEditor()->widget());
+ if (editor)
+ editor->jumpToFile();
+}
+
#ifdef WITH_TESTS
void Qt4ProjectManagerPlugin::testBasicProjectLoading()
{
diff --git a/src/plugins/qt4projectmanager/qt4projectmanagerplugin.h b/src/plugins/qt4projectmanager/qt4projectmanagerplugin.h
index 94d1155d90..24ac8dbb2a 100644
--- a/src/plugins/qt4projectmanager/qt4projectmanagerplugin.h
+++ b/src/plugins/qt4projectmanager/qt4projectmanagerplugin.h
@@ -54,12 +54,6 @@ class QtVersionManager;
namespace Internal {
class ProFileEditorFactory;
-class ConsoleAppWizard;
-class GuiAppWizard;
-class EmptyProjectWizard;
-class QMakeStepFactory;
-class MakeStepFactory;
-class EmbeddedPropertiesPage;
class GettingStartedWelcomePage;
class Qt4ProjectManagerPlugin : public ExtensionSystem::IPlugin
@@ -79,6 +73,7 @@ private slots:
void currentProjectChanged();
void buildStateChanged(ProjectExplorer::Project *pro);
void addLibrary();
+ void jumpToFile();
#ifdef WITH_TESTS
void testBasicProjectLoading(); // Test fails!
@@ -91,6 +86,8 @@ private slots:
void testSbsV2OutputParsers();
void testRvctOutputParser_data();
void testRvctOutputParser();
+ void testQmakeOutputParsers_data();
+ void testQmakeOutputParsers();
#endif
private:
diff --git a/src/plugins/qt4projectmanager/qt4runconfiguration.cpp b/src/plugins/qt4projectmanager/qt4runconfiguration.cpp
index 6b2d59fc94..445158d224 100644
--- a/src/plugins/qt4projectmanager/qt4runconfiguration.cpp
+++ b/src/plugins/qt4projectmanager/qt4runconfiguration.cpp
@@ -51,6 +51,7 @@
#include <projectexplorer/environmenteditmodel.h>
#include <projectexplorer/persistentsettings.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <utils/pathchooser.h>
#include <utils/detailswidget.h>
#include <utils/debuggerlanguagechooser.h>
@@ -79,7 +80,6 @@ const char * const USE_TERMINAL_KEY("Qt4ProjectManager.Qt4RunConfiguration.UseTe
const char * const USE_DYLD_IMAGE_SUFFIX_KEY("Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix");
const char * const USER_ENVIRONMENT_CHANGES_KEY("Qt4ProjectManager.Qt4RunConfiguration.UserEnvironmentChanges");
const char * const BASE_ENVIRONMENT_BASE_KEY("Qt4ProjectManager.Qt4RunConfiguration.BaseEnvironmentBase");
-const char * const USER_SET_WORKING_DIRECTORY_KEY("Qt4ProjectManager.Qt4RunConfiguration.UserSetWorkingDirectory");
const char * const USER_WORKING_DIRECTORY_KEY("Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory");
QString pathFromId(const QString &id)
@@ -105,8 +105,8 @@ Qt4RunConfiguration::Qt4RunConfiguration(Qt4Target *parent, const QString &proFi
m_proFilePath(proFilePath),
m_runMode(Gui),
m_isUsingDyldImageSuffix(false),
- m_userSetWokingDirectory(false),
- m_baseEnvironmentBase(Qt4RunConfiguration::BuildEnvironmentBase)
+ m_baseEnvironmentBase(Qt4RunConfiguration::BuildEnvironmentBase),
+ m_parseSuccess(parent->qt4Project()->validParse(m_proFilePath))
{
ctor();
}
@@ -117,10 +117,10 @@ Qt4RunConfiguration::Qt4RunConfiguration(Qt4Target *parent, Qt4RunConfiguration
m_proFilePath(source->m_proFilePath),
m_runMode(source->m_runMode),
m_isUsingDyldImageSuffix(source->m_isUsingDyldImageSuffix),
- m_userSetWokingDirectory(source->m_userSetWokingDirectory),
m_userWorkingDirectory(source->m_userWorkingDirectory),
m_userEnvironmentChanges(source->m_userEnvironmentChanges),
- m_baseEnvironmentBase(source->m_baseEnvironmentBase)
+ m_baseEnvironmentBase(source->m_baseEnvironmentBase),
+ m_parseSuccess(source->m_parseSuccess)
{
ctor();
}
@@ -134,36 +134,34 @@ Qt4Target *Qt4RunConfiguration::qt4Target() const
return static_cast<Qt4Target *>(target());
}
-bool Qt4RunConfiguration::isEnabled(ProjectExplorer::BuildConfiguration *configuration) const
-{
- Qt4BuildConfiguration *qt4bc = qobject_cast<Qt4BuildConfiguration *>(configuration);
- QTC_ASSERT(qt4bc, return false);
-
- using namespace ProjectExplorer;
- ToolChain::ToolChainType type = qt4bc->toolChainType();
- bool enabled;
- switch (type) {
- case ToolChain::MSVC: case ToolChain::WINCE:
- case ToolChain::GCC: case ToolChain::MinGW:
- case ToolChain::GCCE_GNUPOC: case ToolChain::RVCT_ARMV5_GNUPOC:
- case ToolChain::OTHER: case ToolChain::UNKNOWN:
- case ToolChain::LINUX_ICC:
- case ToolChain::INVALID:
- enabled = true;
- break;
- case ToolChain::WINSCW: case ToolChain::GCCE:
- case ToolChain::RVCT_ARMV5: case ToolChain::RVCT_ARMV6:
- case ToolChain::GCC_MAEMO:
- enabled = false;
- break;
- }
- return enabled;
+bool Qt4RunConfiguration::isEnabled(ProjectExplorer::BuildConfiguration * /* configuration */) const
+{
+ if (!m_parseSuccess)
+ return false;
+ return true;
+}
+
+void Qt4RunConfiguration::handleParseState(bool success)
+{
+ bool enabled = isEnabled();
+ m_parseSuccess = success;
+ if (enabled != isEnabled())
+ emit isEnabledChanged(!enabled);
}
-void Qt4RunConfiguration::proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode *pro)
+void Qt4RunConfiguration::proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode *pro, bool success)
{
- if (m_proFilePath == pro->path())
- emit effectiveTargetInformationChanged();
+ if (m_proFilePath != pro->path())
+ return;
+ handleParseState(success);
+ emit effectiveTargetInformationChanged();
+}
+
+void Qt4RunConfiguration::proFileInvalidated(Qt4ProjectManager::Internal::Qt4ProFileNode *pro)
+{
+ if (pro->path() != m_proFilePath)
+ return;
+ handleParseState(false);
}
void Qt4RunConfiguration::ctor()
@@ -172,9 +170,11 @@ void Qt4RunConfiguration::ctor()
connect(qt4Target(), SIGNAL(environmentChanged()),
this, SIGNAL(baseEnvironmentChanged()));
+ connect(qt4Target()->qt4Project(), SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode*,bool)),
+ this, SLOT(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode*,bool)));
- connect(qt4Target()->qt4Project(), SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode*)),
- this, SLOT(proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode*)));
+ connect(qt4Target()->qt4Project(), SIGNAL(proFileInvalidated(Qt4ProjectManager::Internal::Qt4ProFileNode*)),
+ this, SLOT(proFileInvalidated(Qt4ProjectManager::Internal::Qt4ProFileNode*)));
}
//////
@@ -205,7 +205,7 @@ Qt4RunConfigurationWidget::Qt4RunConfigurationWidget(Qt4RunConfiguration *qt4Run
toplayout->addRow(tr("Executable:"), m_executableLineEdit);
QLabel *argumentsLabel = new QLabel(tr("Arguments:"), this);
- m_argumentsLineEdit = new QLineEdit(Utils::Environment::joinArgumentList(qt4RunConfiguration->baseCommandLineArguments()), this);
+ m_argumentsLineEdit = new QLineEdit(qt4RunConfiguration->rawCommandLineArguments(), this);
argumentsLabel->setBuddy(m_argumentsLineEdit);
toplayout->addRow(argumentsLabel, m_argumentsLineEdit);
@@ -285,6 +285,8 @@ Qt4RunConfigurationWidget::Qt4RunConfigurationWidget(Qt4RunConfiguration *qt4Run
m_environmentWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
vboxTopLayout->addWidget(m_environmentWidget);
+ setEnabled(m_qt4RunConfiguration->isEnabled());
+
connect(m_workingDirectoryEdit, SIGNAL(changed(QString)),
this, SLOT(workDirectoryEdited()));
@@ -309,7 +311,7 @@ Qt4RunConfigurationWidget::Qt4RunConfigurationWidget(Qt4RunConfiguration *qt4Run
connect(qt4RunConfiguration, SIGNAL(baseWorkingDirectoryChanged(QString)),
this, SLOT(workingDirectoryChanged(QString)));
- connect(qt4RunConfiguration, SIGNAL(baseCommandLineArgumentsChanged(QString)),
+ connect(qt4RunConfiguration, SIGNAL(commandLineArgumentsChanged(QString)),
this, SLOT(commandLineArgumentsChanged(QString)));
connect(qt4RunConfiguration, SIGNAL(runModeChanged(ProjectExplorer::LocalApplicationRunConfiguration::RunMode)),
this, SLOT(runModeChanged(ProjectExplorer::LocalApplicationRunConfiguration::RunMode)));
@@ -323,6 +325,11 @@ Qt4RunConfigurationWidget::Qt4RunConfigurationWidget(Qt4RunConfiguration *qt4Run
connect(qt4RunConfiguration, SIGNAL(baseEnvironmentChanged()),
this, SLOT(baseEnvironmentChanged()));
+
+ connect(qt4RunConfiguration, SIGNAL(isEnabledChanged(bool)),
+ this, SLOT(runConfigurationEnabledChange(bool)));
+
+ setEnabled(qt4RunConfiguration->isEnabled());
}
Qt4RunConfigurationWidget::~Qt4RunConfigurationWidget()
@@ -378,6 +385,11 @@ void Qt4RunConfigurationWidget::userChangesEdited()
m_ignoreChange = false;
}
+void Qt4RunConfigurationWidget::runConfigurationEnabledChange(bool enabled)
+{
+ setEnabled(enabled);
+}
+
void Qt4RunConfigurationWidget::workDirectoryEdited()
{
if (m_ignoreChange)
@@ -397,7 +409,7 @@ void Qt4RunConfigurationWidget::workingDirectoryReseted()
void Qt4RunConfigurationWidget::argumentsEdited(const QString &args)
{
m_ignoreChange = true;
- m_qt4RunConfiguration->setBaseCommandLineArguments(args);
+ m_qt4RunConfiguration->setCommandLineArguments(args);
m_ignoreChange = false;
}
@@ -480,7 +492,6 @@ QVariantMap Qt4RunConfiguration::toMap() const
map.insert(QLatin1String(USE_DYLD_IMAGE_SUFFIX_KEY), m_isUsingDyldImageSuffix);
map.insert(QLatin1String(USER_ENVIRONMENT_CHANGES_KEY), Utils::EnvironmentItem::toStringList(m_userEnvironmentChanges));
map.insert(QLatin1String(BASE_ENVIRONMENT_BASE_KEY), m_baseEnvironmentBase);
- map.insert(QLatin1String(USER_SET_WORKING_DIRECTORY_KEY), m_userSetWokingDirectory);
map.insert(QLatin1String(USER_WORKING_DIRECTORY_KEY), m_userWorkingDirectory);
return map;
}
@@ -488,17 +499,18 @@ QVariantMap Qt4RunConfiguration::toMap() const
bool Qt4RunConfiguration::fromMap(const QVariantMap &map)
{
const QDir projectDir = QDir(target()->project()->projectDirectory());
- m_commandLineArguments = map.value(QLatin1String(COMMAND_LINE_ARGUMENTS_KEY)).toStringList();
+ m_commandLineArguments = map.value(QLatin1String(COMMAND_LINE_ARGUMENTS_KEY)).toString();
m_proFilePath = projectDir.filePath(map.value(QLatin1String(PRO_FILE_KEY)).toString());
m_runMode = map.value(QLatin1String(USE_TERMINAL_KEY), false).toBool() ? Console : Gui;
m_isUsingDyldImageSuffix = map.value(QLatin1String(USE_DYLD_IMAGE_SUFFIX_KEY), false).toBool();
- m_userSetWokingDirectory = map.value(QLatin1String(USER_SET_WORKING_DIRECTORY_KEY), false).toBool();
m_userWorkingDirectory = map.value(QLatin1String(USER_WORKING_DIRECTORY_KEY)).toString();
m_userEnvironmentChanges = Utils::EnvironmentItem::fromStringList(map.value(QLatin1String(USER_ENVIRONMENT_CHANGES_KEY)).toStringList());
m_baseEnvironmentBase = static_cast<BaseEnvironmentBase>(map.value(QLatin1String(BASE_ENVIRONMENT_BASE_KEY), static_cast<int>(Qt4RunConfiguration::BuildEnvironmentBase)).toInt());
+ m_parseSuccess = qt4Target()->qt4Project()->validParse(m_proFilePath);
+
return RunConfiguration::fromMap(map);
}
@@ -529,13 +541,14 @@ void Qt4RunConfiguration::setUsingDyldImageSuffix(bool state)
QString Qt4RunConfiguration::workingDirectory() const
{
- return environment().expandVariables(baseWorkingDirectory());
+ return QDir::cleanPath(environment().expandVariables(
+ Utils::expandMacros(baseWorkingDirectory(), macroExpander())));
}
QString Qt4RunConfiguration::baseWorkingDirectory() const
{
// if the user overrode us, then return his working directory
- if (m_userSetWokingDirectory)
+ if (!m_userWorkingDirectory.isEmpty())
return m_userWorkingDirectory;
// else what the pro file reader tells us
@@ -546,12 +559,12 @@ QString Qt4RunConfiguration::baseWorkingDirectory() const
return ti.workingDir;
}
-QStringList Qt4RunConfiguration::commandLineArguments() const
+QString Qt4RunConfiguration::commandLineArguments() const
{
- return environment().expandVariables(baseCommandLineArguments());
+ return Utils::QtcProcess::expandMacros(m_commandLineArguments, macroExpander());
}
-QStringList Qt4RunConfiguration::baseCommandLineArguments() const
+QString Qt4RunConfiguration::rawCommandLineArguments() const
{
return m_commandLineArguments;
}
@@ -615,21 +628,19 @@ void Qt4RunConfiguration::setUserEnvironmentChanges(const QList<Utils::Environme
void Qt4RunConfiguration::setBaseWorkingDirectory(const QString &wd)
{
- if (wd.isEmpty()) {
- m_userSetWokingDirectory = false;
- m_userWorkingDirectory.clear();
- emit baseWorkingDirectoryChanged(workingDirectory());
- } else {
- m_userSetWokingDirectory = true;
- m_userWorkingDirectory = wd;
- emit baseWorkingDirectoryChanged(m_userWorkingDirectory);
- }
+ const QString &oldWorkingDirectory = workingDirectory();
+
+ m_userWorkingDirectory = wd;
+
+ const QString &newWorkingDirectory = workingDirectory();
+ if (oldWorkingDirectory != newWorkingDirectory)
+ emit baseWorkingDirectoryChanged(newWorkingDirectory);
}
-void Qt4RunConfiguration::setBaseCommandLineArguments(const QString &argumentsString)
+void Qt4RunConfiguration::setCommandLineArguments(const QString &argumentsString)
{
- m_commandLineArguments = Utils::Environment::parseCombinedArgString(argumentsString);
- emit baseCommandLineArgumentsChanged(argumentsString);
+ m_commandLineArguments = argumentsString;
+ emit commandLineArgumentsChanged(argumentsString);
}
void Qt4RunConfiguration::setRunMode(RunMode runMode)
@@ -681,7 +692,7 @@ Qt4RunConfiguration::BaseEnvironmentBase Qt4RunConfiguration::baseEnvironmentBas
{
return m_baseEnvironmentBase;
}
-ProjectExplorer::ToolChain::ToolChainType Qt4RunConfiguration::toolChainType() const
+ProjectExplorer::ToolChainType Qt4RunConfiguration::toolChainType() const
{
Qt4BuildConfiguration *qt4bc = qt4Target()->activeBuildConfiguration();
return qt4bc->toolChainType();
diff --git a/src/plugins/qt4projectmanager/qt4runconfiguration.h b/src/plugins/qt4projectmanager/qt4runconfiguration.h
index 2fe08831bf..a20424ad99 100644
--- a/src/plugins/qt4projectmanager/qt4runconfiguration.h
+++ b/src/plugins/qt4projectmanager/qt4runconfiguration.h
@@ -35,6 +35,9 @@
#define QT4RUNCONFIGURATION_H
#include <projectexplorer/applicationrunconfiguration.h>
+
+#include <utils/environment.h>
+
#include <QtCore/QStringList>
#include <QtGui/QWidget>
@@ -56,14 +59,13 @@ namespace ProjectExplorer {
}
namespace Qt4ProjectManager {
-
class Qt4Project;
+class Qt4Target;
namespace Internal {
class Qt4PriFileNode;
class Qt4ProFileNode;
class Qt4RunConfigurationFactory;
-class Qt4Target;
class Qt4RunConfiguration : public ProjectExplorer::LocalApplicationRunConfiguration
{
@@ -79,16 +81,17 @@ public:
Qt4Target *qt4Target() const;
virtual bool isEnabled(ProjectExplorer::BuildConfiguration *configuration) const;
+ using ProjectExplorer::LocalApplicationRunConfiguration::isEnabled;
virtual QWidget *createConfigurationWidget();
virtual QString executable() const;
virtual RunMode runMode() const;
virtual QString workingDirectory() const;
- virtual QStringList commandLineArguments() const;
+ virtual QString commandLineArguments() const;
virtual Utils::Environment environment() const;
virtual QString dumperLibrary() const;
virtual QStringList dumperLibraryLocations() const;
- virtual ProjectExplorer::ToolChain::ToolChainType toolChainType() const;
+ virtual ProjectExplorer::ToolChainType toolChainType() const;
bool isUsingDyldImageSuffix() const;
void setUsingDyldImageSuffix(bool state);
@@ -101,7 +104,7 @@ public:
ProjectExplorer::OutputFormatter *createOutputFormatter() const;
signals:
- void baseCommandLineArgumentsChanged(const QString&);
+ void commandLineArgumentsChanged(const QString&);
void baseWorkingDirectoryChanged(const QString&);
void runModeChanged(ProjectExplorer::LocalApplicationRunConfiguration::RunMode runMode);
void usingDyldImageSuffixChanged(bool);
@@ -112,18 +115,20 @@ signals:
void effectiveTargetInformationChanged();
private slots:
- void proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode *pro);
+ void proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode *pro, bool success);
+ void proFileInvalidated(Qt4ProjectManager::Internal::Qt4ProFileNode *pro);
protected:
Qt4RunConfiguration(Qt4Target *parent, Qt4RunConfiguration *source);
virtual bool fromMap(const QVariantMap &map);
private:
+ void handleParseState(bool success);
void setRunMode(RunMode runMode);
void setBaseWorkingDirectory(const QString &workingDirectory);
QString baseWorkingDirectory() const;
- void setBaseCommandLineArguments(const QString &argumentsString);
- QStringList baseCommandLineArguments() const;
+ void setCommandLineArguments(const QString &argumentsString);
+ QString rawCommandLineArguments() const;
enum BaseEnvironmentBase { CleanEnvironmentBase = 0,
SystemEnvironmentBase = 1,
BuildEnvironmentBase = 2 };
@@ -139,17 +144,17 @@ private:
QList<Utils::EnvironmentItem> userEnvironmentChanges() const;
void updateTarget();
- QStringList m_commandLineArguments;
+ QString m_commandLineArguments;
QString m_proFilePath; // Full path to the Application Pro File
// Cached startup sub project information
ProjectExplorer::LocalApplicationRunConfiguration::RunMode m_runMode;
bool m_userSetName;
bool m_isUsingDyldImageSuffix;
- bool m_userSetWokingDirectory;
QString m_userWorkingDirectory;
QList<Utils::EnvironmentItem> m_userEnvironmentChanges;
BaseEnvironmentBase m_baseEnvironmentBase;
+ bool m_parseSuccess;
};
class Qt4RunConfigurationWidget : public QWidget
@@ -163,7 +168,9 @@ public:
protected:
void showEvent(QShowEvent *event);
void hideEvent(QHideEvent *event);
+
private slots:
+ void runConfigurationEnabledChange(bool);
void workDirectoryEdited();
void workingDirectoryReseted();
void argumentsEdited(const QString &arguments);
diff --git a/src/plugins/qt4projectmanager/qt4target.cpp b/src/plugins/qt4projectmanager/qt4target.cpp
index 9f2dc39aa5..e7d7a37eb2 100644
--- a/src/plugins/qt4projectmanager/qt4target.cpp
+++ b/src/plugins/qt4projectmanager/qt4target.cpp
@@ -48,10 +48,11 @@
#include "qt-s60/s60emulatorrunconfiguration.h"
#include "qt-s60/s60createpackagestep.h"
#include "qt-s60/s60deploystep.h"
+#include "qt4projectconfigwidget.h"
#include <projectexplorer/buildsteplist.h>
#include <projectexplorer/customexecutablerunconfiguration.h>
-#include <projectexplorer/toolchain.h>
+#include <projectexplorer/toolchaintype.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <coreplugin/coreconstants.h>
#include <symbianutils/symbiandevicemanager.h>
@@ -111,12 +112,31 @@ Qt4TargetFactory::~Qt4TargetFactory()
{
}
+bool Qt4TargetFactory::supportsTargetId(const QString &id) const
+{
+ QSet<QString> ids;
+ ids << QLatin1String("Qt4ProjectManager.Target.DesktopTarget")
+ << QLatin1String("Qt4ProjectManager.Target.S60EmulatorTarget")
+ << QLatin1String("Qt4ProjectManager.Target.S60DeviceTarget")
+ << QLatin1String("Qt4ProjectManager.Target.MaemoDeviceTarget")
+ << QLatin1String("Qt4ProjectManager.Target.QtSimulatorTarget");
+ return ids.contains(id);
+}
+
QStringList Qt4TargetFactory::availableCreationIds(ProjectExplorer::Project *parent) const
{
if (!qobject_cast<Qt4Project *>(parent))
return QStringList();
- return parent->possibleTargetIds().toList();
+ QSet<QString> ids;
+ ids << QLatin1String("Qt4ProjectManager.Target.DesktopTarget")
+ << QLatin1String("Qt4ProjectManager.Target.S60EmulatorTarget")
+ << QLatin1String("Qt4ProjectManager.Target.S60DeviceTarget")
+ << QLatin1String("Qt4ProjectManager.Target.MaemoDeviceTarget")
+ << QLatin1String("Qt4ProjectManager.Target.QtSimulatorTarget");
+
+
+ return parent->possibleTargetIds().intersect(ids).toList();
}
QString Qt4TargetFactory::displayNameForId(const QString &id) const
@@ -266,6 +286,11 @@ Qt4Target::~Qt4Target()
{
}
+ProjectExplorer::BuildConfigWidget *Qt4Target::createConfigWidget()
+{
+ return new Qt4ProjectConfigWidget(this);
+}
+
Qt4BuildConfiguration *Qt4Target::activeBuildConfiguration() const
{
return static_cast<Qt4BuildConfiguration *>(Target::activeBuildConfiguration());
@@ -278,7 +303,7 @@ Qt4Project *Qt4Target::qt4Project() const
Qt4BuildConfiguration *Qt4Target::addQt4BuildConfiguration(QString displayName, QtVersion *qtversion,
QtVersion::QmakeBuildConfigs qmakeBuildConfiguration,
- QStringList additionalArguments,
+ QString additionalArguments,
QString directory)
{
Q_ASSERT(qtversion);
@@ -301,20 +326,20 @@ Qt4BuildConfiguration *Qt4Target::addQt4BuildConfiguration(QString displayName,
MakeStep* cleanStep = new MakeStep(cleanSteps);
cleanStep->setClean(true);
- cleanStep->setUserArguments(QStringList() << "clean");
+ cleanStep->setUserArguments("clean");
cleanSteps->insertStep(0, cleanStep);
if (!additionalArguments.isEmpty())
qmakeStep->setUserArguments(additionalArguments);
// set some options for qmake and make
if (qmakeBuildConfiguration & QtVersion::BuildAll) // debug_and_release => explicit targets
- makeStep->setUserArguments(QStringList() << (debug ? "debug" : "release"));
+ makeStep->setUserArguments(debug ? "debug" : "release");
bc->setQMakeBuildConfiguration(qmakeBuildConfiguration);
// Finally set the qt version & ToolChain
bc->setQtVersion(qtversion);
- ToolChain::ToolChainType defaultTc = preferredToolChainType(filterToolChainTypes(bc->qtVersion()->possibleToolChainTypes()));
+ ProjectExplorer::ToolChainType defaultTc = preferredToolChainType(filterToolChainTypes(bc->qtVersion()->possibleToolChainTypes()));
bc->setToolChainType(defaultTc);
if (!directory.isEmpty())
bc->setShadowBuildAndDirectory(directory != project()->projectDirectory(), directory);
@@ -346,27 +371,27 @@ void Qt4Target::addRunConfigurationForPath(const QString &proFilePath)
addRunConfiguration(new MaemoRunConfiguration(this, proFilePath));
}
-QList<ToolChain::ToolChainType> Qt4Target::filterToolChainTypes(const QList<ToolChain::ToolChainType> &candidates) const
+QList<ProjectExplorer::ToolChainType> Qt4Target::filterToolChainTypes(const QList<ProjectExplorer::ToolChainType> &candidates) const
{
- QList<ToolChain::ToolChainType> tmp(candidates);
+ QList<ProjectExplorer::ToolChainType> tmp(candidates);
if (id() == QLatin1String(Constants::S60_EMULATOR_TARGET_ID)) {
- if (tmp.contains(ToolChain::WINSCW))
- return QList<ToolChain::ToolChainType>() << ToolChain::WINSCW;
+ if (tmp.contains(ProjectExplorer::ToolChain_WINSCW))
+ return QList<ProjectExplorer::ToolChainType>() << ProjectExplorer::ToolChain_WINSCW;
else
- return QList<ToolChain::ToolChainType>();
+ return QList<ProjectExplorer::ToolChainType>();
} else if (id() == QLatin1String(Constants::S60_DEVICE_TARGET_ID)) {
- tmp.removeAll(ToolChain::WINSCW);
+ tmp.removeAll(ProjectExplorer::ToolChain_WINSCW);
return tmp;
}
return tmp;
}
-ToolChain::ToolChainType Qt4Target::preferredToolChainType(const QList<ToolChain::ToolChainType> &candidates) const
+ProjectExplorer::ToolChainType Qt4Target::preferredToolChainType(const QList<ProjectExplorer::ToolChainType> &candidates) const
{
- ToolChain::ToolChainType preferredType = ToolChain::INVALID;
+ ProjectExplorer::ToolChainType preferredType = ProjectExplorer::ToolChain_INVALID;
if (id() == QLatin1String(Constants::S60_EMULATOR_TARGET_ID) &&
- candidates.contains(ToolChain::WINSCW))
- preferredType = ToolChain::WINSCW;
+ candidates.contains(ProjectExplorer::ToolChain_WINSCW))
+ preferredType = ProjectExplorer::ToolChain_WINSCW;
if (!candidates.isEmpty())
preferredType = candidates.at(0);
return preferredType;
@@ -426,8 +451,8 @@ void Qt4Target::onAddedBuildConfiguration(ProjectExplorer::BuildConfiguration *b
Q_ASSERT(qt4bc);
connect(qt4bc, SIGNAL(buildDirectoryInitialized()),
this, SIGNAL(buildDirectoryInitialized()));
- connect(qt4bc, SIGNAL(proFileEvaluateNeeded(Qt4ProjectManager::Internal::Qt4BuildConfiguration *)),
- this, SLOT(onProFileEvaluateNeeded(Qt4ProjectManager::Internal::Qt4BuildConfiguration *)));
+ connect(qt4bc, SIGNAL(proFileEvaluateNeeded(Qt4ProjectManager::Qt4BuildConfiguration *)),
+ this, SLOT(onProFileEvaluateNeeded(Qt4ProjectManager::Qt4BuildConfiguration *)));
}
void Qt4Target::onAddedDeployConfiguration(ProjectExplorer::DeployConfiguration *dc)
@@ -448,7 +473,7 @@ void Qt4Target::slotUpdateDeviceInformation()
}
}
-void Qt4Target::onProFileEvaluateNeeded(Qt4ProjectManager::Internal::Qt4BuildConfiguration *bc)
+void Qt4Target::onProFileEvaluateNeeded(Qt4ProjectManager::Qt4BuildConfiguration *bc)
{
if (bc && bc == activeBuildConfiguration())
emit proFileEvaluateNeeded(this);
diff --git a/src/plugins/qt4projectmanager/qt4target.h b/src/plugins/qt4projectmanager/qt4target.h
index d7847d15d3..200ac51f87 100644
--- a/src/plugins/qt4projectmanager/qt4target.h
+++ b/src/plugins/qt4projectmanager/qt4target.h
@@ -51,58 +51,60 @@ class Qt4DeployConfigurationFactory;
struct BuildConfigurationInfo {
explicit BuildConfigurationInfo(QtVersion *v = 0, QtVersion::QmakeBuildConfigs bc = QtVersion::QmakeBuildConfig(0),
- const QStringList &aa = QStringList(), const QString &d = QString()) :
+ const QString &aa = QString(), const QString &d = QString()) :
version(v), buildConfig(bc), additionalArguments(aa), directory(d)
{ }
QtVersion *version;
QtVersion::QmakeBuildConfigs buildConfig;
- QStringList additionalArguments;
+ QString additionalArguments;
QString directory;
};
+}
class Qt4Target : public ProjectExplorer::Target
{
Q_OBJECT
- friend class Qt4TargetFactory;
+ friend class Internal::Qt4TargetFactory;
public:
explicit Qt4Target(Qt4Project *parent, const QString &id);
virtual ~Qt4Target();
+ ProjectExplorer::BuildConfigWidget *createConfigWidget();
+
Qt4BuildConfiguration *activeBuildConfiguration() const;
Qt4ProjectManager::Qt4Project *qt4Project() const;
- Internal::Qt4BuildConfiguration *addQt4BuildConfiguration(QString displayName,
+ Qt4BuildConfiguration *addQt4BuildConfiguration(QString displayName,
QtVersion *qtversion,
QtVersion::QmakeBuildConfigs qmakeBuildConfiguration,
- QStringList additionalArguments,
+ QString additionalArguments,
QString directory);
void addRunConfigurationForPath(const QString &proFilePath);
Internal::Qt4BuildConfigurationFactory *buildConfigurationFactory() const;
ProjectExplorer::DeployConfigurationFactory *deployConfigurationFactory() const;
- QList<ProjectExplorer::ToolChain::ToolChainType> filterToolChainTypes(const QList<ProjectExplorer::ToolChain::ToolChainType> &candidates) const;
- ProjectExplorer::ToolChain::ToolChainType preferredToolChainType(const QList<ProjectExplorer::ToolChain::ToolChainType> &candidates) const;
+ QList<ProjectExplorer::ToolChainType> filterToolChainTypes(const QList<ProjectExplorer::ToolChainType> &candidates) const;
+ ProjectExplorer::ToolChainType preferredToolChainType(const QList<ProjectExplorer::ToolChainType> &candidates) const;
QString defaultBuildDirectory() const;
static QString defaultShadowBuildDirectory(const QString &projectLocation, const QString &id);
+ bool fromMap(const QVariantMap &map);
+
signals:
void buildDirectoryInitialized();
/// emitted if the build configuration changed in a way that
/// should trigger a reevaluation of all .pro files
- void proFileEvaluateNeeded(Qt4ProjectManager::Internal::Qt4Target *);
-
-protected:
- bool fromMap(const QVariantMap &map);
+ void proFileEvaluateNeeded(Qt4ProjectManager::Qt4Target *);
private slots:
void updateQtVersion();
void onAddedBuildConfiguration(ProjectExplorer::BuildConfiguration *bc);
void onAddedDeployConfiguration(ProjectExplorer::DeployConfiguration *dc);
void slotUpdateDeviceInformation();
- void onProFileEvaluateNeeded(Qt4ProjectManager::Internal::Qt4BuildConfiguration *bc);
+ void onProFileEvaluateNeeded(Qt4ProjectManager::Qt4BuildConfiguration *bc);
void emitProFileEvaluateNeeded();
void updateToolTipAndIcon();
@@ -114,6 +116,7 @@ private:
Internal::Qt4DeployConfigurationFactory *m_deployConfigurationFactory;
};
+namespace Internal {
class Qt4TargetFactory : public ProjectExplorer::ITargetFactory
{
Q_OBJECT
@@ -122,18 +125,19 @@ public:
Qt4TargetFactory(QObject *parent = 0);
~Qt4TargetFactory();
+ virtual bool supportsTargetId(const QString &id) const;
+
QStringList availableCreationIds(ProjectExplorer::Project *parent) const;
QString displayNameForId(const QString &id) const;
bool canCreate(ProjectExplorer::Project *parent, const QString &id) const;
- Internal::Qt4Target *create(ProjectExplorer::Project *parent, const QString &id);
- Internal::Qt4Target *create(ProjectExplorer::Project *parent, const QString &id, QList<QtVersion *> versions);
- Internal::Qt4Target *create(ProjectExplorer::Project *parent, const QString &id, QList<BuildConfigurationInfo> infos);
+ Qt4ProjectManager::Qt4Target *create(ProjectExplorer::Project *parent, const QString &id);
+ Qt4ProjectManager::Qt4Target *create(ProjectExplorer::Project *parent, const QString &id, QList<QtVersion *> versions);
+ Qt4ProjectManager::Qt4Target *create(ProjectExplorer::Project *parent, const QString &id, QList<Internal::BuildConfigurationInfo> infos);
bool canRestore(ProjectExplorer::Project *parent, const QVariantMap &map) const;
- Internal::Qt4Target *restore(ProjectExplorer::Project *parent, const QVariantMap &map);
+ Qt4ProjectManager::Qt4Target *restore(ProjectExplorer::Project *parent, const QVariantMap &map);
};
-
-} // namespace Internal
+}
} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qtmodulesinfo.cpp b/src/plugins/qt4projectmanager/qtmodulesinfo.cpp
index a67f373062..4692a5ccb8 100644
--- a/src/plugins/qt4projectmanager/qtmodulesinfo.cpp
+++ b/src/plugins/qt4projectmanager/qtmodulesinfo.cpp
@@ -129,19 +129,19 @@ const itemVectorType itemVector()
Q_GLOBAL_STATIC_WITH_INITIALIZER(itemVectorType, staticItemVector, {
*x = itemVector();
-});
+})
Q_GLOBAL_STATIC_WITH_INITIALIZER(QStringList, staticModulesList, {
const itemVectorType * const itemVector = staticItemVector();
for (int i = 0; i < itemVector->count(); i++)
x->append(QString::fromLatin1(itemVector->at(i)->config));
-});
+})
Q_GLOBAL_STATIC_WITH_INITIALIZER(itemHashType, staticItemHash, {
const itemVectorType * const itemVector = staticItemVector();
for (int i = 0; i < itemVector->count(); i++)
x->insert(QString::fromLatin1(itemVector->at(i)->config), itemVector->at(i));
-});
+})
QStringList QtModulesInfo::modules()
{
diff --git a/src/plugins/qt4projectmanager/qtoptionspage.cpp b/src/plugins/qt4projectmanager/qtoptionspage.cpp
index 38f153b255..0fb72d60f3 100644
--- a/src/plugins/qt4projectmanager/qtoptionspage.cpp
+++ b/src/plugins/qt4projectmanager/qtoptionspage.cpp
@@ -41,6 +41,7 @@
#include "qmlobservertool.h"
#include <projectexplorer/debugginghelper.h>
+#include <projectexplorer/toolchaintype.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/icore.h>
#include <coreplugin/progressmanager/progressmanager.h>
@@ -136,6 +137,8 @@ QWidget *QtOptionsPage::createPage(QWidget *parent)
void QtOptionsPage::apply()
{
+ if (!m_widget) // page was never shown
+ return;
m_widget->finish();
QtVersionManager *vm = QtVersionManager::instance();
@@ -562,8 +565,8 @@ void QtOptionsPageWidget::showEnvironmentPage(QTreeWidgetItem *item)
{
if (item) {
int index = indexForTreeItem(item);
- m_ui->errorLabel->setText("");
if (index < 0) {
+ m_ui->errorLabel->setText("");
makeMSVCVisible(false);
makeMingwVisible(false);
makeS60Visible(false);
@@ -571,24 +574,20 @@ void QtOptionsPageWidget::showEnvironmentPage(QTreeWidgetItem *item)
return;
}
const QSharedPointerQtVersion qtVersion = m_versions.at(index);
- QList<ProjectExplorer::ToolChain::ToolChainType> types = qtVersion->possibleToolChainTypes();
+ QList<ProjectExplorer::ToolChainType> types = qtVersion->possibleToolChainTypes();
QSet<QString> targets = qtVersion->supportedTargetIds();
makeDebuggingHelperVisible(qtVersion->supportsBinaryDebuggingHelper());
if (types.isEmpty()) {
makeMSVCVisible(false);
makeMingwVisible(false);
makeS60Visible(false);
- if (!m_versions.at(index)->isValid())
- m_ui->errorLabel->setText(m_versions.at(index)->invalidReason());
- else
- m_ui->errorLabel->setText(tr("This Qt Version has a unknown toolchain."));
- } else if (types.contains(ProjectExplorer::ToolChain::MinGW)) {
+ } else if (types.contains(ProjectExplorer::ToolChain_MinGW)) {
makeMSVCVisible(false);
makeMingwVisible(true);
makeS60Visible(false);
m_ui->mingwPath->setPath(m_versions.at(index)->mingwDirectory());
- } else if (types.contains(ProjectExplorer::ToolChain::MSVC) ||
- types.contains(ProjectExplorer::ToolChain::WINCE)) {
+ } else if (types.contains(ProjectExplorer::ToolChain_MSVC) ||
+ types.contains(ProjectExplorer::ToolChain_WINCE)) {
makeMSVCVisible(false);
makeMingwVisible(false);
makeS60Visible(false);
@@ -624,23 +623,7 @@ void QtOptionsPageWidget::showEnvironmentPage(QTreeWidgetItem *item)
makeS60Visible(false);
}
- if (m_ui->errorLabel->text().isEmpty()) {
- QString envs;
- if (targets.contains(Constants::DESKTOP_TARGET_ID))
- envs = tr("Desktop", "Qt Version is meant for the desktop");
- else if (targets.contains(Constants::S60_DEVICE_TARGET_ID) ||
- targets.contains(Constants::S60_EMULATOR_TARGET_ID))
- envs = tr("Symbian", "Qt Version is meant for Symbian");
- else if (targets.contains(Constants::MAEMO_DEVICE_TARGET_ID))
- envs = tr("Maemo", "Qt Version is meant for Maemo");
- else if (targets.contains(Constants::QT_SIMULATOR_TARGET_ID))
- envs = tr("Qt Simulator", "Qt Version is meant for Qt Simulator");
- else
- envs = tr("unkown", "No idea what this Qt Version is meant for!");
- m_ui->errorLabel->setText(tr("Found Qt version %1, using mkspec %2 (%3)")
- .arg(m_versions.at(index)->qtVersionString(),
- m_versions.at(index)->mkspec(), envs));
- }
+ m_ui->errorLabel->setText(m_versions.at(index)->description());
} else {
makeMSVCVisible(false);
makeMingwVisible(false);
@@ -723,6 +706,7 @@ void QtOptionsPageWidget::updateCurrentQtName()
return;
m_versions[currentItemIndex]->setDisplayName(m_ui->nameEdit->text());
currentItem->setText(0, m_versions[currentItemIndex]->displayName());
+ m_ui->errorLabel->setText(m_versions.at(currentItemIndex)->description());
}
@@ -878,11 +862,17 @@ QList<QSharedPointerQtVersion> QtOptionsPageWidget::versions() const
QString QtOptionsPageWidget::searchKeywords() const
{
QString rc;
- QTextStream(&rc) << ' ' << m_ui->mingwLabel->text()
- << ' ' << m_ui->msvcLabel->text()
- << ' ' << m_ui->gcceLabel->text()
- << ' ' << m_ui->mwcLabel->text()
- << ' ' << m_ui->debuggingHelperLabel->text();
+ QLatin1Char sep(' ');
+ QTextStream(&rc)
+ << sep << m_ui->versionNameLabel->text()
+ << sep << m_ui->pathLabel->text()
+ << sep << m_ui->mingwLabel->text()
+ << sep << m_ui->msvcLabel->text()
+ << sep << m_ui->s60SDKLabel->text()
+ << sep << m_ui->gcceLabel->text()
+ << sep << m_ui->mwcLabel->text()
+ << sep << m_ui->sbsV2Label->text()
+ << sep << m_ui->debuggingHelperLabel->text();
rc.remove(QLatin1Char('&'));
return rc;
}
diff --git a/src/plugins/qt4projectmanager/qtoutputformatter.cpp b/src/plugins/qt4projectmanager/qtoutputformatter.cpp
index 84cd8803d7..78b3b0b1df 100644
--- a/src/plugins/qt4projectmanager/qtoutputformatter.cpp
+++ b/src/plugins/qt4projectmanager/qtoutputformatter.cpp
@@ -40,18 +40,24 @@
#include <QtCore/QFileInfo>
#include <QtCore/QUrl>
#include <QtGui/QPlainTextEdit>
+#include <QtGui/QTextCursor>
using namespace ProjectExplorer;
using namespace Qt4ProjectManager;
QtOutputFormatter::QtOutputFormatter(ProjectExplorer::Project *project)
: OutputFormatter()
- , m_qmlError(QLatin1String("(file:///.+:\\d+:\\d+):"))
+ , m_qmlError(QLatin1String("^(file:///.+" // file url
+ ":\\d+" // colon, line
+ "(?::\\d+)?)" // colon, column (optional)
+ ":")) // colon
, m_qtError(QLatin1String("Object::.*in (.*:\\d+)"))
, m_qtAssert(QLatin1String("^ASSERT: .* in file (.+, line \\d+)$"))
, m_qtTestFail(QLatin1String("^ Loc: \\[(.*)\\]$"))
, m_project(project)
{
+ if(project)
+ m_projectFinder.setProjectDirectory(project->projectDirectory());
}
LinkResult QtOutputFormatter::matchLine(const QString &line) const
@@ -177,58 +183,29 @@ void QtOutputFormatter::appendLine(QTextCursor &cursor, LinkResult lr, const QSt
cursor.insertText(line.mid(lr.end), normalFormat);
}
-// Map absolute path in shadow build / in the deployment folder to the path in the project directory
-//
-// Input is e.g.
-// C:/app-build-desktop/qml/app/main.qml (shadow build directory)
-// C:/Private/e3026d63/qml/app/main.qml (Application data folder on Symbian device)
-// /Users/x/app-build-desktop/App.app/Contents/Resources/qml/App/main.qml (folder on Mac OS X)
-// which should be mapped to
-// $PROJECTDIR/qml/app/main.qml
-QString QtOutputFormatter::pathInSourceDirectory(const QString &originalFilePath)
+void QtOutputFormatter::handleLink(const QString &href)
{
- QTC_ASSERT(QFileInfo(originalFilePath).isAbsolute(), return originalFilePath);
-
- if (!m_project)
- return originalFilePath;
-
- const QString projectDirectory = m_project.data()->projectDirectory();
-
- QTC_ASSERT(!projectDirectory.isEmpty(), return originalFilePath);
- QTC_ASSERT(!projectDirectory.endsWith(QLatin1Char('/')), return originalFilePath);
-
- const QChar separator = QLatin1Char('/');
+ if (!href.isEmpty()) {
+ const QRegExp qmlLineColumnLink(QLatin1String("^(file:///.+)" // file url
+ ":(\\d+)" // line
+ ":(\\d+)$")); // column
- if (originalFilePath.startsWith(projectDirectory + separator)) {
- return originalFilePath;
- }
+ if (qmlLineColumnLink.indexIn(href) != -1) {
+ const QString fileName = QUrl(qmlLineColumnLink.cap(1)).toLocalFile();
+ const int line = qmlLineColumnLink.cap(2).toInt();
+ const int column = qmlLineColumnLink.cap(3).toInt();
+ TextEditor::BaseTextEditor::openEditorAt(m_projectFinder.findFile(fileName), line, column - 1);
- // Strip directories one by one from the beginning of the path,
- // and see if the new relative path exists in the build directory.
- if (originalFilePath.contains(separator)) {
- for (int pos = originalFilePath.indexOf(separator); pos != -1; pos = originalFilePath.indexOf(separator, pos + 1)) {
- QString candidate = originalFilePath;
- candidate.remove(0, pos);
- candidate.prepend(projectDirectory);
- QFileInfo candidateInfo(candidate);
- if (candidateInfo.exists() && candidateInfo.isFile())
- return candidate;
+ return;
}
- }
-
- return originalFilePath;
-}
-void QtOutputFormatter::handleLink(const QString &href)
-{
- if (!href.isEmpty()) {
- const QRegExp qmlErrorLink(QLatin1String("^(file:///.+):(\\d+):(\\d+)"));
+ const QRegExp qmlLineLink(QLatin1String("^(file:///.+)" // file url
+ ":(\\d+)$")); // line
- if (qmlErrorLink.indexIn(href) != -1) {
- const QString fileName = QUrl(qmlErrorLink.cap(1)).toLocalFile();
- const int line = qmlErrorLink.cap(2).toInt();
- const int column = qmlErrorLink.cap(3).toInt();
- TextEditor::BaseTextEditor::openEditorAt(pathInSourceDirectory(fileName), line, column - 1);
+ if (qmlLineLink.indexIn(href) != -1) {
+ const QString fileName = QUrl(qmlLineLink.cap(1)).toLocalFile();
+ const int line = qmlLineLink.cap(2).toInt();
+ TextEditor::BaseTextEditor::openEditorAt(m_projectFinder.findFile(fileName), line);
return;
}
@@ -256,7 +233,7 @@ void QtOutputFormatter::handleLink(const QString &href)
if (!fileName.isEmpty()) {
QFileInfo fi(fileName);
if (fi.isRelative()) {
- // Yeah fileName is relative, no suprise
+ // Yeah fileName is relative, no surprise
ProjectExplorer::Project *pro = m_project.data();
if (pro) {
QString baseName = fi.fileName();
@@ -270,7 +247,7 @@ void QtOutputFormatter::handleLink(const QString &href)
}
} else if (!fi.exists()) {
// map possible on-device path to source path
- fileName = pathInSourceDirectory(fileName);
+ fileName = m_projectFinder.findFile(fileName);
}
TextEditor::BaseTextEditor::openEditorAt(fileName, line, 0);
return;
diff --git a/src/plugins/qt4projectmanager/qtoutputformatter.h b/src/plugins/qt4projectmanager/qtoutputformatter.h
index 0322b60306..3f19b01cf8 100644
--- a/src/plugins/qt4projectmanager/qtoutputformatter.h
+++ b/src/plugins/qt4projectmanager/qtoutputformatter.h
@@ -37,9 +37,12 @@
#include "qt4projectmanager_global.h"
#include <projectexplorer/outputformatter.h>
+#include <utils/fileinprojectfinder.h>
+
#include <QtCore/QRegExp>
-#include <QtCore/QSharedPointer>
-#include <QtGui/QTextCharFormat>
+#include <QtCore/QWeakPointer>
+
+QT_FORWARD_DECLARE_CLASS(QTextCursor)
namespace ProjectExplorer {
class Project;
@@ -67,7 +70,6 @@ public:
private:
LinkResult matchLine(const QString &line) const;
void appendLine(QTextCursor & cursor, LinkResult lr, const QString &line, bool onStdError);
- QString pathInSourceDirectory(const QString &originalFilePath);
QRegExp m_qmlError;
QRegExp m_qtError;
@@ -76,6 +78,7 @@ private:
QWeakPointer<ProjectExplorer::Project> m_project;
QString m_lastLine;
QString m_deferedText;
+ Utils::FileInProjectFinder m_projectFinder;
};
diff --git a/src/plugins/qt4projectmanager/qtuicodemodelsupport.cpp b/src/plugins/qt4projectmanager/qtuicodemodelsupport.cpp
index 10a15335ea..ba33fb7cad 100644
--- a/src/plugins/qt4projectmanager/qtuicodemodelsupport.cpp
+++ b/src/plugins/qt4projectmanager/qtuicodemodelsupport.cpp
@@ -37,169 +37,32 @@
#include "qt4project.h"
#include "qt4target.h"
-#include <QtCore/QProcess>
-
using namespace Qt4ProjectManager;
using namespace Internal;
-enum { debug = 0 };
-
Qt4UiCodeModelSupport::Qt4UiCodeModelSupport(CppTools::CppModelManagerInterface *modelmanager,
Qt4Project *project,
const QString &source,
const QString &uiHeaderFile)
- : CppTools::AbstractEditorSupport(modelmanager),
- m_project(project),
- m_sourceName(source),
- m_fileName(uiHeaderFile),
- m_updateIncludingFiles(false)
-{
- if (debug)
- qDebug()<<"ctor Qt4UiCodeModelSupport for"<<m_sourceName<<uiHeaderFile;
- init();
-}
-
-Qt4UiCodeModelSupport::~Qt4UiCodeModelSupport()
+ : CppTools::UiCodeModelSupport(modelmanager, source, uiHeaderFile),
+ m_project(project)
{
- if (debug)
- qDebug()<<"dtor ~Qt4UiCodeModelSupport for"<<m_sourceName;
-}
-
-void Qt4UiCodeModelSupport::init()
-{
- QDateTime sourceTime = QFileInfo(m_sourceName).lastModified();
- QFileInfo uiHeaderFileInfo(m_fileName);
- QDateTime uiHeaderTime = uiHeaderFileInfo.exists() ? uiHeaderFileInfo.lastModified() : QDateTime();
- if (uiHeaderTime.isValid() && (uiHeaderTime > sourceTime)) {
- QFile file(m_fileName);
- if (file.open(QFile::ReadOnly)) {
- if (debug)
- qDebug()<<"ui*h file is more recent then source file, using information from ui*h file"<<m_fileName;
- QTextStream stream(&file);
- m_contents = stream.readAll().toUtf8();
- m_cacheTime = uiHeaderTime;
- return;
- }
- }
- if (debug)
- qDebug()<<"ui*h file not found, or not recent enough, trying to create it on the fly";
- QFile file(m_sourceName);
- if (file.open(QFile::ReadOnly)) {
- QTextStream stream(&file);
- const QString contents = stream.readAll();
- if (runUic(contents)) {
- if (debug)
- qDebug()<<"created on the fly";
- return;
- } else {
- // uic run was unsuccesfull
- if (debug)
- qDebug()<<"uic run wasn't succesfull";
- m_cacheTime = QDateTime();
- m_contents = QByteArray();
- // and if the header file wasn't there, next time we need to update
- // all of the files that include this header
- if (!uiHeaderFileInfo.exists())
- m_updateIncludingFiles = true;
- return;
- }
- } else {
- if (debug)
- qDebug()<<"Could open "<<m_sourceName<<"needed for the cpp model";
- m_contents = QByteArray();
- }
-}
-
-QByteArray Qt4UiCodeModelSupport::contents() const
-{
- return m_contents;
}
-QString Qt4UiCodeModelSupport::fileName() const
-{
- return m_fileName;
-}
-
-void Qt4UiCodeModelSupport::setFileName(const QString &name)
+Qt4UiCodeModelSupport::~Qt4UiCodeModelSupport()
{
- if (m_fileName == name && m_cacheTime.isValid())
- return;
-
- if (debug)
- qDebug() << "Qt4UiCodeModelSupport::setFileName"<<name;
- m_fileName = name;
- m_contents.clear();
- m_cacheTime = QDateTime();
- init();
}
-bool Qt4UiCodeModelSupport::runUic(const QString &ui) const
+QString Qt4UiCodeModelSupport::uicCommand() const
{
Qt4BuildConfiguration *qt4bc = m_project->activeTarget()->activeBuildConfiguration();
- QProcess uic;
- uic.setEnvironment(qt4bc->environment().toStringList());
- const QString uicCommand = qt4bc->qtVersion()->uicCommand();
- if (debug)
- qDebug() << "Qt4UiCodeModelSupport::runUic " << uicCommand << " on " << ui.size() << " bytes";
- uic.start(uicCommand, QStringList(), QIODevice::ReadWrite);
- if (!uic.waitForStarted())
- return false;
- uic.write(ui.toUtf8());
- uic.closeWriteChannel();
- if (uic.waitForFinished() && uic.exitStatus() == QProcess::NormalExit && uic.exitCode() == 0) {
- m_contents = uic.readAllStandardOutput();
- m_cacheTime = QDateTime::currentDateTime();
- if (debug)
- qDebug() << "ok" << m_contents.size() << "bytes.";
- return true;
- } else {
- if (debug)
- qDebug() << "failed" << uic.readAllStandardError();
- uic.kill();
- }
- return false;
+ return qt4bc->qtVersion()->uicCommand();
}
-void Qt4UiCodeModelSupport::updateFromEditor(const QString &formEditorContents)
+QStringList Qt4UiCodeModelSupport::environment() const
{
- if (runUic(formEditorContents)) {
- updateDocument();
- }
-}
-
-void Qt4UiCodeModelSupport::updateFromBuild()
-{
- if (debug)
- qDebug()<<"Qt4UiCodeModelSupport::updateFromBuild() for file"<<m_sourceName;
- // This is mostly a fall back for the cases when uic couldn't be run
- // it pays special attention to the case where a ui_*h was newly created
- QDateTime sourceTime = QFileInfo(m_sourceName).lastModified();
- if (m_cacheTime.isValid() && m_cacheTime >= sourceTime) {
- if (debug)
- qDebug()<<"Cache is still more recent then source";
- return;
- } else {
- QFileInfo fi(m_fileName);
- QDateTime uiHeaderTime = fi.exists() ? fi.lastModified() : QDateTime();
- if (uiHeaderTime.isValid() && (uiHeaderTime > sourceTime)) {
- if (m_cacheTime >= uiHeaderTime)
- return;
- if (debug)
- qDebug()<<"found ui*h updating from it";
-
- QFile file(m_fileName);
- if (file.open(QFile::ReadOnly)) {
- QTextStream stream(&file);
- m_contents = stream.readAll().toUtf8();
- m_cacheTime = uiHeaderTime;
- updateDocument();
- return;
- }
- }
- if (debug)
- qDebug()<<"ui*h not found or not more recent then source not changing anything";
- }
+ Qt4BuildConfiguration *qt4bc = m_project->activeTarget()->activeBuildConfiguration();
+ return qt4bc->environment().toStringList();
}
-
diff --git a/src/plugins/qt4projectmanager/qtuicodemodelsupport.h b/src/plugins/qt4projectmanager/qtuicodemodelsupport.h
index 792b859b6c..8216990df8 100644
--- a/src/plugins/qt4projectmanager/qtuicodemodelsupport.h
+++ b/src/plugins/qt4projectmanager/qtuicodemodelsupport.h
@@ -34,37 +34,25 @@
#ifndef QTUICODEMODELSUPPORT_H
#define QTUICODEMODELSUPPORT_H
-#include <cpptools/cppmodelmanagerinterface.h>
-
-#include <QtCore/QDateTime>
+#include <cpptools/uicodecompletionsupport.h>
namespace Qt4ProjectManager {
class Qt4Project;
namespace Internal {
-class Qt4UiCodeModelSupport : public CppTools::AbstractEditorSupport
+class Qt4UiCodeModelSupport : public CppTools::UiCodeModelSupport
{
public:
Qt4UiCodeModelSupport(CppTools::CppModelManagerInterface *modelmanager,
Qt4Project *project,
const QString &sourceFile,
const QString &uiHeaderFile);
- ~Qt4UiCodeModelSupport();
- void setFileName(const QString &name);
- void setSourceName(const QString &name);
- virtual QByteArray contents() const;
- virtual QString fileName() const;
- void updateFromEditor(const QString &formEditorContents);
- void updateFromBuild();
+ virtual ~Qt4UiCodeModelSupport();
+protected:
+ virtual QString uicCommand() const;
+ virtual QStringList environment() const;
private:
- void init();
- bool runUic(const QString &ui) const;
Qt4Project *m_project;
- QString m_sourceName;
- QString m_fileName;
- mutable bool m_updateIncludingFiles;
- mutable QByteArray m_contents;
- mutable QDateTime m_cacheTime;
};
diff --git a/src/plugins/qt4projectmanager/qtversionmanager.cpp b/src/plugins/qt4projectmanager/qtversionmanager.cpp
index bf7fcea2b3..f1d3c1b888 100644
--- a/src/plugins/qt4projectmanager/qtversionmanager.cpp
+++ b/src/plugins/qt4projectmanager/qtversionmanager.cpp
@@ -40,10 +40,13 @@
#include "qt-maemo/maemomanager.h"
#include "qt-s60/s60manager.h"
#include "qt-s60/s60projectchecker.h"
+#include "qt-s60/abldparser.h"
+#include "qt-s60/sbsv2parser.h"
#include "qmlobservertool.h"
#include "qmldumptool.h"
#include <projectexplorer/debugginghelper.h>
+#include <projectexplorer/gnumakeparser.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/cesdkhandler.h>
@@ -52,8 +55,11 @@
#include <coreplugin/icore.h>
#include <coreplugin/helpmanager.h>
#include <extensionsystem/pluginmanager.h>
-#include <help/helpmanager.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
+#ifdef Q_OS_WIN
+# include <utils/winutils.h>
+#endif
#include <QtCore/QFile>
#include <QtCore/QProcess>
@@ -65,10 +71,6 @@
#include <QtGui/QApplication>
#include <QtGui/QDesktopServices>
-#ifdef Q_OS_WIN32
-#include <windows.h>
-#endif
-
using namespace Qt4ProjectManager;
using namespace Qt4ProjectManager::Internal;
@@ -552,7 +554,8 @@ QtVersion::QtVersion(const QString &name, const QString &qmakeCommand, int id,
m_defaultConfigIsDebugAndRelease(true),
m_hasExamples(false),
m_hasDemos(false),
- m_hasDocumentation(false)
+ m_hasDocumentation(false),
+ m_isBuildUsingSbsV2(false)
{
if (id == -1)
m_id = getUniqueId();
@@ -576,7 +579,8 @@ QtVersion::QtVersion(const QString &name, const QString &qmakeCommand,
m_defaultConfigIsDebugAndRelease(true),
m_hasExamples(false),
m_hasDemos(false),
- m_hasDocumentation(false)
+ m_hasDocumentation(false),
+ m_isBuildUsingSbsV2(false)
{
m_id = getUniqueId();
setQMakeCommand(qmakeCommand);
@@ -596,7 +600,8 @@ QtVersion::QtVersion(const QString &qmakeCommand, bool isAutodetected, const QSt
m_defaultConfigIsDebugAndRelease(true),
m_hasExamples(false),
m_hasDemos(false),
- m_hasDocumentation(false)
+ m_hasDocumentation(false),
+ m_isBuildUsingSbsV2(false)
{
m_id = getUniqueId();
setQMakeCommand(qmakeCommand);
@@ -616,7 +621,8 @@ QtVersion::QtVersion()
m_defaultConfigIsDebugAndRelease(true),
m_hasExamples(false),
m_hasDemos(false),
- m_hasDocumentation(false)
+ m_hasDocumentation(false),
+ m_isBuildUsingSbsV2(false)
{
setQMakeCommand(QString());
}
@@ -674,6 +680,21 @@ bool QtVersion::supportsShadowBuilds() const
return true;
}
+ProjectExplorer::IOutputParser *QtVersion::createOutputParser() const
+{
+ if (supportsTargetId(Qt4ProjectManager::Constants::S60_DEVICE_TARGET_ID) ||
+ supportsTargetId(Qt4ProjectManager::Constants::S60_EMULATOR_TARGET_ID)) {
+ if (isBuildWithSymbianSbsV2()) {
+ return new SbsV2Parser;
+ } else {
+ ProjectExplorer::IOutputParser *parser = new AbldParser;
+ parser->appendOutputParser(new ProjectExplorer::GnuMakeParser);
+ return parser;
+ }
+ }
+ return new ProjectExplorer::GnuMakeParser;
+}
+
QList<ProjectExplorer::Task>
QtVersion::reportIssues(const QString &proFile, const QString &buildDir)
{
@@ -829,12 +850,12 @@ void QtVersion::updateSourcePath()
// That is returns the directory
// To find out whether we already have a qtversion for that directory call
// QtVersion *QtVersionManager::qtVersionForDirectory(const QString directory);
-QString QtVersionManager::findQMakeBinaryFromMakefile(const QString &directory)
+QString QtVersionManager::findQMakeBinaryFromMakefile(const QString &makefile)
{
bool debugAdding = false;
- QFile makefile(directory + "/Makefile" );
- if (makefile.exists() && makefile.open(QFile::ReadOnly)) {
- QTextStream ts(&makefile);
+ QFile fi(makefile);
+ if (fi.exists() && fi.open(QFile::ReadOnly)) {
+ QTextStream ts(&fi);
QRegExp r1("QMAKE\\s*=(.*)");
while (!ts.atEnd()) {
QString line = ts.readLine();
@@ -880,43 +901,38 @@ void dumpQMakeAssignments(const QList<QMakeAssignment> &list)
}
}
-bool QtVersionManager::makefileIsFor(const QString &directory, const QString &proFile)
+bool QtVersionManager::makefileIsFor(const QString &makefile, const QString &proFile)
{
if (proFile.isEmpty())
return true;
- QString line = findQMakeLine(directory, QLatin1String("# Project:")).trimmed();
+ QString line = findQMakeLine(makefile, QLatin1String("# Project:")).trimmed();
if (line.isEmpty())
return false;
-
line = line.mid(line.indexOf(QChar(':')) + 1);
line = line.trimmed();
- QFileInfo srcFileInfo(QDir(directory), line);
+ QFileInfo srcFileInfo(QFileInfo(makefile).absoluteDir(), line);
QFileInfo proFileInfo(proFile);
return srcFileInfo == proFileInfo;
}
-QPair<QtVersion::QmakeBuildConfigs, QStringList> QtVersionManager::scanMakeFile(const QString &directory, QtVersion::QmakeBuildConfigs defaultBuildConfig)
+QPair<QtVersion::QmakeBuildConfigs, QString> QtVersionManager::scanMakeFile(const QString &makefile, QtVersion::QmakeBuildConfigs defaultBuildConfig)
{
if (debug)
qDebug()<<"ScanMakeFile, the gory details:";
QtVersion::QmakeBuildConfigs result = defaultBuildConfig;
- QStringList result2;
+ QString result2;
- QString line = findQMakeLine(directory, QLatin1String("# Command:"));
+ QString line = findQMakeLine(makefile, QLatin1String("# Command:"));
if (!line.isEmpty()) {
if (debug)
qDebug()<<"Found line"<<line;
line = trimLine(line);
- QStringList parts = splitLine(line);
- if (debug)
- qDebug()<<"Split into"<<parts;
QList<QMakeAssignment> assignments;
QList<QMakeAssignment> afterAssignments;
- QStringList additionalArguments;
- parseParts(parts, &assignments, &afterAssignments, &additionalArguments);
+ parseArgs(line, &assignments, &afterAssignments, &result2);
if (debug) {
dumpQMakeAssignments(assignments);
@@ -932,13 +948,12 @@ QPair<QtVersion::QmakeBuildConfigs, QStringList> QtVersionManager::scanMakeFile(
if (debug)
dumpQMakeAssignments(assignments);
- result2.append(additionalArguments);
foreach(const QMakeAssignment &qa, assignments)
- result2.append(qa.variable + qa.op + qa.value);
+ Utils::QtcProcess::addArg(&result2, qa.variable + qa.op + qa.value);
if (!afterAssignments.isEmpty()) {
- result2.append("-after");
+ Utils::QtcProcess::addArg(&result2, QLatin1String("-after"));
foreach(const QMakeAssignment &qa, afterAssignments)
- result2.append(qa.variable + qa.op + qa.value);
+ Utils::QtcProcess::addArg(&result2, qa.variable + qa.op + qa.value);
}
}
@@ -956,11 +971,11 @@ QPair<QtVersion::QmakeBuildConfigs, QStringList> QtVersionManager::scanMakeFile(
return qMakePair(result, result2);
}
-QString QtVersionManager::findQMakeLine(const QString &directory, const QString &key)
+QString QtVersionManager::findQMakeLine(const QString &makefile, const QString &key)
{
- QFile makefile(directory + QLatin1String("/Makefile" ));
- if (makefile.exists() && makefile.open(QFile::ReadOnly)) {
- QTextStream ts(&makefile);
+ QFile fi(makefile);
+ if (fi.exists() && fi.open(QFile::ReadOnly)) {
+ QTextStream ts(&fi);
while (!ts.atEnd()) {
const QString line = ts.readLine();
if (line.startsWith(key))
@@ -979,57 +994,23 @@ QString QtVersionManager::trimLine(const QString line)
return line.mid(firstSpace).trimmed();
}
-QStringList QtVersionManager::splitLine(const QString &line)
-{
- // Split on each " ", except on those which are escaped
- // On Unix also remove all escaping
- // On Windows also, but different escaping
- bool escape = false;
- QString currentWord;
- QStringList results;
- int length = line.length();
- for (int i=0; i<length; ++i) {
-#ifdef Q_OS_WIN
- if (line.at(i) == '"') {
- escape = !escape;
- } else if (escape || line.at(i) != ' ') {
- currentWord += line.at(i);
- } else if (!currentWord.isEmpty()) {
- results << currentWord;
- currentWord.clear();
- }
-#else
- if (escape) {
- currentWord += line.at(i);
- escape = false;
- } else if (line.at(i) == ' ') {
- if (!currentWord.isEmpty()) {
- results << currentWord;
- currentWord.clear();
- }
- } else if (line.at(i) == '\\') {
- escape = true;
- } else {
- currentWord += line.at(i);
- }
-#endif
- }
- return results;
-}
-
-void QtVersionManager::parseParts(const QStringList &parts, QList<QMakeAssignment> *assignments, QList<QMakeAssignment> *afterAssignments, QStringList *additionalArguments)
+void QtVersionManager::parseArgs(const QString &args, QList<QMakeAssignment> *assignments, QList<QMakeAssignment> *afterAssignments, QString *additionalArguments)
{
QRegExp regExp("([^\\s\\+-]*)\\s*(\\+=|=|-=|~=)(.*)");
bool after = false;
bool ignoreNext = false;
- foreach (const QString &part, parts) {
+ *additionalArguments = args;
+ Utils::QtcProcess::ArgIterator ait(additionalArguments);
+ while (ait.next()) {
if (ignoreNext) {
// Ignoring
ignoreNext = false;
- } else if (part == "-after") {
+ ait.deleteArg();
+ } else if (ait.value() == QLatin1String("-after")) {
after = true;
- } else if(part.contains('=')) {
- if (regExp.exactMatch(part)) {
+ ait.deleteArg();
+ } else if (ait.value().contains(QLatin1Char('='))) {
+ if (regExp.exactMatch(ait.value())) {
QMakeAssignment qa;
qa.variable = regExp.cap(1);
qa.op = regExp.cap(2);
@@ -1041,21 +1022,23 @@ void QtVersionManager::parseParts(const QStringList &parts, QList<QMakeAssignmen
} else {
qDebug()<<"regexp did not match";
}
- } else if (part == "-o") {
+ ait.deleteArg();
+ } else if (ait.value() == QLatin1String("-o")) {
ignoreNext = true;
- } else {
- additionalArguments->append(part);
- }
- }
+ ait.deleteArg();
#if defined(Q_OS_WIN32)
- additionalArguments->removeAll("-win32");
+ } else if (ait.value() == QLatin1String("-win32")) {
#elif defined(Q_OS_MAC)
- additionalArguments->removeAll("-macx");
+ } else if (ait.value() == QLatin1String("-macx")) {
#elif defined(Q_OS_QNX6)
- additionalArguments->removeAll("-qnx6");
+ } else if (ait.value() == QLatin1String("-qnx6")) {
#else
- additionalArguments->removeAll("-unix");
+ } else if (ait.value() == QLatin1String("-unix")) {
#endif
+ ait.deleteArg();
+ }
+ }
+ ait.deleteArg(); // The .pro file is always the last arg
}
/// This function extracts all the CONFIG+=debug, CONFIG+=release
@@ -1317,7 +1300,7 @@ QList<QSharedPointer<ProjectExplorer::ToolChain> > QtVersion::toolChains() const
return m_toolChains;
}
-ProjectExplorer::ToolChain *QtVersion::toolChain(ProjectExplorer::ToolChain::ToolChainType type) const
+ProjectExplorer::ToolChain *QtVersion::toolChain(ProjectExplorer::ToolChainType type) const
{
foreach(const QSharedPointer<ProjectExplorer::ToolChain> &tcptr, toolChains())
if (tcptr->type() == type)
@@ -1325,9 +1308,9 @@ ProjectExplorer::ToolChain *QtVersion::toolChain(ProjectExplorer::ToolChain::Too
return 0;
}
-QList<ProjectExplorer::ToolChain::ToolChainType> QtVersion::possibleToolChainTypes() const
+QList<ProjectExplorer::ToolChainType> QtVersion::possibleToolChainTypes() const
{
- QList<ProjectExplorer::ToolChain::ToolChainType> types;
+ QList<ProjectExplorer::ToolChainType> types;
foreach(const QSharedPointer<ProjectExplorer::ToolChain> &tc, toolChains())
types << tc->type();
return types;
@@ -1471,16 +1454,19 @@ void QtVersion::updateToolChainAndMkspec() const
# ifdef Q_OS_WIN
m_targetIds.insert(QLatin1String(Constants::S60_DEVICE_TARGET_ID));
m_toolChains << ToolChainPtr(s60mgr->createGCCEToolChain(this));
- if (S60Manager::hasRvctCompiler())
- m_toolChains << ToolChainPtr(s60mgr->createRVCTToolChain(this, ProjectExplorer::ToolChain::RVCT_ARMV5))
- << ToolChainPtr(s60mgr->createRVCTToolChain(this, ProjectExplorer::ToolChain::RVCT_ARMV6));
+ if (S60Manager::hasRvct2Compiler())
+ m_toolChains << ToolChainPtr(s60mgr->createRVCTToolChain(this, ProjectExplorer::ToolChain_RVCT2_ARMV5))
+ << ToolChainPtr(s60mgr->createRVCTToolChain(this, ProjectExplorer::ToolChain_RVCT2_ARMV6));
+ if (S60Manager::hasRvct4Compiler())
+ m_toolChains << ToolChainPtr(s60mgr->createRVCTToolChain(this, ProjectExplorer::ToolChain_RVCT4_ARMV5))
+ << ToolChainPtr(s60mgr->createRVCTToolChain(this, ProjectExplorer::ToolChain_RVCT4_ARMV6));
if (!mwcDirectory().isEmpty()) {
m_toolChains << ToolChainPtr(s60mgr->createWINSCWToolChain(this));
m_targetIds.insert(QLatin1String(Constants::S60_EMULATOR_TARGET_ID));
}
# else
- if (S60Manager::hasRvctCompiler())
- m_toolChains << ToolChainPtr(s60mgr->createRVCTToolChain(this, ProjectExplorer::ToolChain::RVCT_ARMV5_GNUPOC));
+ if (S60Manager::hasRvct2Compiler())
+ m_toolChains << ToolChainPtr(s60mgr->createRVCTToolChain(this, ProjectExplorer::ToolChain_RVCT_ARMV5_GNUPOC));
m_toolChains << ToolChainPtr(s60mgr->createGCCE_GnuPocToolChain(this));
m_targetIds.insert(QLatin1String(Constants::S60_DEVICE_TARGET_ID));
# endif
@@ -1655,6 +1641,29 @@ QString QtVersion::invalidReason() const
return QString();
}
+QString QtVersion::description() const
+{
+ if (!isValid())
+ return invalidReason();
+ if (possibleToolChainTypes().isEmpty())
+ return QCoreApplication::translate("QtVersion", "This Qt Version has a unknown toolchain.");
+ QSet<QString> targets = supportedTargetIds();
+ QString envs;
+ if (targets.contains(Constants::DESKTOP_TARGET_ID))
+ envs = QCoreApplication::translate("QtVersion", "Desktop", "Qt Version is meant for the desktop");
+ else if (targets.contains(Constants::S60_DEVICE_TARGET_ID) ||
+ targets.contains(Constants::S60_EMULATOR_TARGET_ID))
+ envs = QCoreApplication::translate("QtVersion", "Symbian", "Qt Version is meant for Symbian");
+ else if (targets.contains(Constants::MAEMO_DEVICE_TARGET_ID))
+ envs = QCoreApplication::translate("QtVersion", "Maemo", "Qt Version is meant for Maemo");
+ else if (targets.contains(Constants::QT_SIMULATOR_TARGET_ID))
+ envs = QCoreApplication::translate("QtVersion", "Qt Simulator", "Qt Version is meant for Qt Simulator");
+ else
+ envs = QCoreApplication::translate("QtVersion", "unkown", "No idea what this Qt Version is meant for!");
+ return QCoreApplication::translate("QtVersion", "Qt version %1, using mkspec %2 (%3)")
+ .arg(qtVersionString(), mkspec(), envs);
+}
+
QtVersion::QmakeBuildConfigs QtVersion::defaultBuildConfig() const
{
updateToolChainAndMkspec();
@@ -1732,24 +1741,26 @@ QStringList QtVersion::debuggingHelperLibraryLocations() const
bool QtVersion::supportsBinaryDebuggingHelper() const
{
- foreach (ProjectExplorer::ToolChain::ToolChainType type, possibleToolChainTypes())
+ foreach (ProjectExplorer::ToolChainType type, possibleToolChainTypes())
switch (type) {
- case ProjectExplorer::ToolChain::GCC:
- case ProjectExplorer::ToolChain::LINUX_ICC:
- case ProjectExplorer::ToolChain::MinGW:
- case ProjectExplorer::ToolChain::MSVC:
- case ProjectExplorer::ToolChain::WINCE:
- case ProjectExplorer::ToolChain::GCC_MAEMO:
- case ProjectExplorer::ToolChain::OTHER:
- case ProjectExplorer::ToolChain::UNKNOWN:
+ case ProjectExplorer::ToolChain_GCC:
+ case ProjectExplorer::ToolChain_LINUX_ICC:
+ case ProjectExplorer::ToolChain_MinGW:
+ case ProjectExplorer::ToolChain_MSVC:
+ case ProjectExplorer::ToolChain_WINCE:
+ case ProjectExplorer::ToolChain_GCC_MAEMO:
+ case ProjectExplorer::ToolChain_OTHER:
+ case ProjectExplorer::ToolChain_UNKNOWN:
return true;
- case ProjectExplorer::ToolChain::WINSCW:
- case ProjectExplorer::ToolChain::GCCE :
- case ProjectExplorer::ToolChain::RVCT_ARMV5:
- case ProjectExplorer::ToolChain::RVCT_ARMV6:
- case ProjectExplorer::ToolChain::GCCE_GNUPOC:
- case ProjectExplorer::ToolChain::RVCT_ARMV5_GNUPOC:
- case ProjectExplorer::ToolChain::INVALID:
+ case ProjectExplorer::ToolChain_WINSCW:
+ case ProjectExplorer::ToolChain_GCCE :
+ case ProjectExplorer::ToolChain_RVCT2_ARMV5:
+ case ProjectExplorer::ToolChain_RVCT2_ARMV6:
+ case ProjectExplorer::ToolChain_RVCT4_ARMV5:
+ case ProjectExplorer::ToolChain_RVCT4_ARMV6:
+ case ProjectExplorer::ToolChain_GCCE_GNUPOC:
+ case ProjectExplorer::ToolChain_RVCT_ARMV5_GNUPOC:
+ case ProjectExplorer::ToolChain_INVALID:
break;
}
return false;
@@ -1809,22 +1820,11 @@ QString QtVersion::examplesPath() const
bool QtVersion::isQt64Bit() const
{
- const QString make = qmakeCommand();
-// qDebug() << make;
- bool isAmd64 = false;
-#ifdef Q_OS_WIN32
-# ifdef __GNUC__ // MinGW lacking some definitions/winbase.h
-# define SCS_64BIT_BINARY 6
-# endif
- DWORD binaryType = 0;
- bool success = GetBinaryTypeW(reinterpret_cast<const TCHAR*>(make.utf16()), &binaryType) != 0;
- if (success && binaryType == SCS_64BIT_BINARY)
- isAmd64=true;
-// qDebug() << "isAmd64:" << isAmd64 << binaryType;
- return isAmd64;
+#ifdef Q_OS_WIN
+ const QString qmake = qmakeCommand();
+ return qmake.isEmpty() ? false : Utils::winIs64BitBinary(qmake);
#else
- Q_UNUSED(isAmd64)
- return false;
+ return false;
#endif
}
@@ -1851,7 +1851,7 @@ bool QtVersion::buildDebuggingHelperLibrary(QFutureInterface<void> &future,
return false;
}
tc->addToEnvironment(env);
- const QString target = (tc->type() == ToolChain::GCC_MAEMO ? QLatin1String("-unix") : QLatin1String(""));
+ const QString target = (tc->type() == ProjectExplorer::ToolChain_GCC_MAEMO ? QLatin1String("-unix") : QLatin1String(""));
// invalidate cache
m_versionInfoUpToDate = false;
diff --git a/src/plugins/qt4projectmanager/qtversionmanager.h b/src/plugins/qt4projectmanager/qtversionmanager.h
index 22a5191e33..0bf978b62e 100644
--- a/src/plugins/qt4projectmanager/qtversionmanager.h
+++ b/src/plugins/qt4projectmanager/qtversionmanager.h
@@ -35,6 +35,8 @@
#define QTVERSIONMANAGER_H
#include "qt4projectmanager_global.h"
+
+#include <projectexplorer/ioutputparser.h>
#include <projectexplorer/taskwindow.h>
#include <projectexplorer/toolchain.h>
#include <projectexplorer/task.h>
@@ -44,6 +46,14 @@
#include <QtCore/QSharedPointer>
#include <QtCore/QFutureInterface>
+namespace ProjectExplorer {
+class ToolChain;
+}
+
+namespace Utils {
+class Environment;
+}
+
namespace Qt4ProjectManager {
namespace Internal {
@@ -67,6 +77,7 @@ public:
bool isValid() const; //TOOD check that the dir exists and the name is non empty
QString invalidReason() const;
+ QString description() const;
bool isAutodetected() const { return m_isAutodetected; }
QString autodetectionSource() const { return m_autodetectionSource; }
@@ -82,8 +93,8 @@ public:
QSet<QString> supportedTargetIds() const;
bool supportsMobileTarget() const;
- QList<ProjectExplorer::ToolChain::ToolChainType> possibleToolChainTypes() const;
- ProjectExplorer::ToolChain *toolChain(ProjectExplorer::ToolChain::ToolChainType type) const;
+ QList<ProjectExplorer::ToolChainType> possibleToolChainTypes() const;
+ ProjectExplorer::ToolChain *toolChain(ProjectExplorer::ToolChainType type) const;
/// @returns the name of the mkspec, which is generally not enough
/// to pass to qmake.
@@ -168,6 +179,8 @@ public:
/// warnings and finally info items.
QList<ProjectExplorer::Task> reportIssues(const QString &proFile, const QString &buildDir);
+ ProjectExplorer::IOutputParser *createOutputParser() const;
+
private:
QList<QSharedPointer<ProjectExplorer::ToolChain> > toolChains() const;
static int getUniqueId();
@@ -260,9 +273,9 @@ public:
QSet<QString> supportedTargetIds() const;
// Static Methods
- static bool makefileIsFor(const QString &directory, const QString &proFile);
- static QPair<QtVersion::QmakeBuildConfigs, QStringList> scanMakeFile(const QString &directory,
- QtVersion::QmakeBuildConfigs defaultBuildConfig);
+ static bool makefileIsFor(const QString &makefile, const QString &proFile);
+ static QPair<QtVersion::QmakeBuildConfigs, QString> scanMakeFile(const QString &makefile,
+ QtVersion::QmakeBuildConfigs defaultBuildConfig);
static QString findQMakeBinaryFromMakefile(const QString &directory);
bool isValidId(int id) const;
@@ -277,11 +290,10 @@ private:
static bool equals(QtVersion *a, QtVersion *b);
static QString findQMakeLine(const QString &directory, const QString &key);
static QString trimLine(const QString line);
- static QStringList splitLine(const QString &line);
- static void parseParts(const QStringList &parts,
- QList<QMakeAssignment> *assignments,
- QList<QMakeAssignment> *afterAssignments,
- QStringList *additionalArguments);
+ static void parseArgs(const QString &args,
+ QList<QMakeAssignment> *assignments,
+ QList<QMakeAssignment> *afterAssignments,
+ QString *additionalArguments);
static QtVersion::QmakeBuildConfigs qmakeBuildConfigFromCmdArgs(QList<QMakeAssignment> *assignments,
QtVersion::QmakeBuildConfigs defaultBuildConfig);
// Used by QtOptionsPage
diff --git a/src/plugins/qt4projectmanager/wizards/abstractmobileapp.cpp b/src/plugins/qt4projectmanager/wizards/abstractmobileapp.cpp
index af7b1c96a6..96121c483e 100644
--- a/src/plugins/qt4projectmanager/wizards/abstractmobileapp.cpp
+++ b/src/plugins/qt4projectmanager/wizards/abstractmobileapp.cpp
@@ -161,20 +161,22 @@ QString AbstractMobileApp::path(int fileType) const
const QString originsRootShared = templatesRoot() + QLatin1String("shared/");
const QString mainCppFileName = QLatin1String("main.cpp");
const QString symbianIconFileName = QLatin1String("symbianicon.svg");
+ QString cleanProjectName = m_projectName;
+ cleanProjectName.replace(QLatin1Char('-'), QString());
switch (fileType) {
case MainCpp: return outputPathBase() + mainCppFileName;
case MainCppOrigin: return originsRootApp + mainCppFileName;
- case AppPro: return outputPathBase() + m_projectName + QLatin1String(".pro");
+ case AppPro: return outputPathBase() + cleanProjectName + QLatin1String(".pro");
case AppProOrigin: return originsRootApp + QLatin1String("app.pro");
case AppProPath: return outputPathBase();
- case Desktop: return outputPathBase() + m_projectName + QLatin1String(".desktop");
+ case Desktop: return outputPathBase() + cleanProjectName + QLatin1String(".desktop");
case DesktopOrigin: return originsRootShared + QLatin1String("app.desktop");
case DeploymentPri: return outputPathBase() + DeploymentPriFileName;
case DeploymentPriOrigin: return originsRootShared + DeploymentPriFileName;
- case SymbianSvgIcon: return outputPathBase() + projectName() + QLatin1String(".svg");
+ case SymbianSvgIcon: return outputPathBase() + cleanProjectName + QLatin1String(".svg");
case SymbianSvgIconOrigin: return !m_symbianSvgIcon.isEmpty() ? m_symbianSvgIcon
: originsRootShared + symbianIconFileName;
- case MaemoPngIcon: return outputPathBase() + projectName() + QLatin1String(".png");
+ case MaemoPngIcon: return outputPathBase() + cleanProjectName + QLatin1String(".png");
case MaemoPngIconOrigin: return !m_maemoPngIcon.isEmpty() ? m_maemoPngIcon
: originsRootShared + QLatin1String("maemoicon.png");
default: return pathExtended(fileType);
diff --git a/src/plugins/qt4projectmanager/wizards/abstractmobileapp.h b/src/plugins/qt4projectmanager/wizards/abstractmobileapp.h
index 220c9177ad..f17fee2468 100644
--- a/src/plugins/qt4projectmanager/wizards/abstractmobileapp.h
+++ b/src/plugins/qt4projectmanager/wizards/abstractmobileapp.h
@@ -40,7 +40,7 @@
#include <coreplugin/basefilewizard.h>
#endif // CREATORLESSTEST
-QT_FORWARD_DECLARE_CLASS(QTextStream);
+QT_FORWARD_DECLARE_CLASS(QTextStream)
namespace Qt4ProjectManager {
namespace Internal {
@@ -73,6 +73,8 @@ struct AbstractGeneratedFileInfo
class AbstractMobileApp : public QObject
{
+ Q_OBJECT
+
public:
enum ScreenOrientation {
ScreenOrientationLockLandscape,
diff --git a/src/plugins/qt4projectmanager/wizards/abstractmobileappwizard.cpp b/src/plugins/qt4projectmanager/wizards/abstractmobileappwizard.cpp
index d3e5edcc4c..b65cf45bf7 100644
--- a/src/plugins/qt4projectmanager/wizards/abstractmobileappwizard.cpp
+++ b/src/plugins/qt4projectmanager/wizards/abstractmobileappwizard.cpp
@@ -40,6 +40,7 @@
#include <extensionsystem/pluginmanager.h>
#include <qt4projectmanager/qt4project.h>
#include <qt4projectmanager/qt4projectmanager.h>
+#include <qt4projectmanager/qt4projectmanagerconstants.h>
#include <QtGui/QIcon>
@@ -52,13 +53,107 @@ AbstractMobileAppWizardDialog::AbstractMobileAppWizardDialog(QWidget *parent)
m_targetsPage = new TargetSetupPage;
resize(900, 450);
m_targetsPage->setImportDirectoryBrowsingEnabled(false);
- int pageId = addPage(m_targetsPage);
- wizardProgress()->item(pageId)->setTitle(tr("Qt Versions"));
- m_optionsPage = new MobileAppWizardOptionsPage;
- pageId = addPage(m_optionsPage);
- wizardProgress()->item(pageId)->setTitle(tr("Application Options"));
+ m_targetsPageId = addPageWithTitle(m_targetsPage, tr("Qt Versions"));
+ m_genericOptionsPage = new MobileAppWizardGenericOptionsPage;
+ m_genericOptionsPageId = addPageWithTitle(m_genericOptionsPage,
+ tr("Mobile Options"));
+ m_symbianOptionsPage = new MobileAppWizardSymbianOptionsPage;
+ m_symbianOptionsPageId = addPageWithTitle(m_symbianOptionsPage,
+ QLatin1String(" ") + tr("Symbian Specific"));
+ m_maemoOptionsPage = new MobileAppWizardMaemoOptionsPage;
+ m_maemoOptionsPageId = addPageWithTitle(m_maemoOptionsPage,
+ QLatin1String(" ") + tr("Maemo Specific"));
+
+ m_targetItem = wizardProgress()->item(m_targetsPageId);
+ m_genericItem = wizardProgress()->item(m_genericOptionsPageId);
+ m_symbianItem = wizardProgress()->item(m_symbianOptionsPageId);
+ m_maemoItem = wizardProgress()->item(m_maemoOptionsPageId);
+
+ m_targetItem->setNextShownItem(0);
+ m_genericItem->setNextShownItem(0);
+ m_symbianItem->setNextShownItem(0);
}
+int AbstractMobileAppWizardDialog::addPageWithTitle(QWizardPage *page, const QString &title)
+{
+ const int pageId = addPage(page);
+ wizardProgress()->item(pageId)->setTitle(title);
+ return pageId;
+}
+
+int AbstractMobileAppWizardDialog::nextId() const
+{
+ const bool symbianTargetSelected =
+ m_targetsPage->isTargetSelected(QLatin1String(Constants::S60_EMULATOR_TARGET_ID))
+ || m_targetsPage->isTargetSelected(QLatin1String(Constants::S60_DEVICE_TARGET_ID));
+ const bool maemoTargetSelected =
+ m_targetsPage->isTargetSelected(QLatin1String(Constants::MAEMO_DEVICE_TARGET_ID));
+
+ if (currentPage() == m_targetsPage) {
+ if (symbianTargetSelected || maemoTargetSelected)
+ return m_genericOptionsPageId;
+ else
+ return idOfNextGenericPage();
+ } else if (currentPage() == m_genericOptionsPage) {
+ if (symbianTargetSelected)
+ return m_symbianOptionsPageId;
+ else
+ return m_maemoOptionsPageId;
+ } else if (currentPage() == m_symbianOptionsPage) {
+ if (maemoTargetSelected)
+ return m_maemoOptionsPageId;
+ else
+ return idOfNextGenericPage();
+ } else {
+ return BaseProjectWizardDialog::nextId();
+ }
+}
+
+void AbstractMobileAppWizardDialog::initializePage(int id)
+{
+ if (id == startId()) {
+ m_targetItem->setNextItems(QList<Utils::WizardProgressItem *>() << m_genericItem << itemOfNextGenericPage());
+ m_genericItem->setNextItems(QList<Utils::WizardProgressItem *>() << m_symbianItem << m_maemoItem);
+ m_symbianItem->setNextItems(QList<Utils::WizardProgressItem *>() << m_maemoItem << itemOfNextGenericPage());
+ } else if (id == m_genericOptionsPageId) {
+ const bool symbianTargetSelected =
+ m_targetsPage->isTargetSelected(QLatin1String(Constants::S60_EMULATOR_TARGET_ID))
+ || m_targetsPage->isTargetSelected(QLatin1String(Constants::S60_DEVICE_TARGET_ID));
+ const bool maemoTargetSelected =
+ m_targetsPage->isTargetSelected(QLatin1String(Constants::MAEMO_DEVICE_TARGET_ID));
+
+ QList<Utils::WizardProgressItem *> order;
+ order << m_genericItem;
+ if (symbianTargetSelected)
+ order << m_symbianItem;
+ if (maemoTargetSelected)
+ order << m_maemoItem;
+ order << itemOfNextGenericPage();
+
+ for (int i = 0; i < order.count() - 1; i++)
+ order.at(i)->setNextShownItem(order.at(i + 1));
+ }
+ BaseProjectWizardDialog::initializePage(id);
+}
+
+void AbstractMobileAppWizardDialog::cleanupPage(int id)
+{
+ if (id == m_genericOptionsPageId) {
+ m_genericItem->setNextShownItem(0);
+ m_symbianItem->setNextShownItem(0);
+ }
+ BaseProjectWizardDialog::cleanupPage(id);
+}
+
+int AbstractMobileAppWizardDialog::idOfNextGenericPage() const
+{
+ return pageIds().at(pageIds().indexOf(m_maemoOptionsPageId) + 1);
+}
+
+Utils::WizardProgressItem *AbstractMobileAppWizardDialog::itemOfNextGenericPage() const
+{
+ return wizardProgress()->item(idOfNextGenericPage());
+}
AbstractMobileAppWizard::AbstractMobileAppWizard(const Core::BaseFileWizardParameters &params,
QObject *parent) : Core::BaseFileWizard(params, parent)
@@ -72,11 +167,11 @@ QWizard *AbstractMobileAppWizard::createWizardDialog(QWidget *parent,
= createWizardDialogInternal(parent);
wdlg->setPath(defaultPath);
wdlg->setProjectName(ProjectExplorer::BaseProjectWizardDialog::uniqueProjectName(defaultPath));
- wdlg->m_optionsPage->setSymbianSvgIcon(app()->symbianSvgIcon());
- wdlg->m_optionsPage->setMaemoPngIcon(app()->maemoPngIcon());
- wdlg->m_optionsPage->setOrientation(app()->orientation());
- wdlg->m_optionsPage->setNetworkEnabled(app()->networkEnabled());
- connect(wdlg, SIGNAL(introPageLeft(QString, QString)),
+ wdlg->m_genericOptionsPage->setOrientation(app()->orientation());
+ wdlg->m_symbianOptionsPage->setSvgIcon(app()->symbianSvgIcon());
+ wdlg->m_symbianOptionsPage->setNetworkEnabled(app()->networkEnabled());
+ wdlg->m_maemoOptionsPage->setPngIcon(app()->maemoPngIcon());
+ connect(wdlg, SIGNAL(projectParametersChanged(QString, QString)),
SLOT(useProjectPath(QString, QString)));
foreach (QWizardPage *p, extensionPages)
BaseFileWizard::applyExtensionPageShortTitle(wdlg, wdlg->addPage(p));
@@ -89,11 +184,11 @@ Core::GeneratedFiles AbstractMobileAppWizard::generateFiles(const QWizard *wizar
prepareGenerateFiles(wizard, errorMessage);
const AbstractMobileAppWizardDialog *wdlg
= qobject_cast<const AbstractMobileAppWizardDialog*>(wizard);
- app()->setSymbianTargetUid(wdlg->m_optionsPage->symbianUid());
- app()->setSymbianSvgIcon(wdlg->m_optionsPage->symbianSvgIcon());
- app()->setMaemoPngIcon(wdlg->m_optionsPage->maemoPngIcon());
- app()->setOrientation(wdlg->m_optionsPage->orientation());
- app()->setNetworkEnabled(wdlg->m_optionsPage->networkEnabled());
+ app()->setOrientation(wdlg->m_genericOptionsPage->orientation());
+ app()->setSymbianTargetUid(wdlg->m_symbianOptionsPage->symbianUid());
+ app()->setSymbianSvgIcon(wdlg->m_symbianOptionsPage->svgIcon());
+ app()->setNetworkEnabled(wdlg->m_symbianOptionsPage->networkEnabled());
+ app()->setMaemoPngIcon(wdlg->m_maemoOptionsPage->pngIcon());
return app()->generateFiles(errorMessage);
}
@@ -116,7 +211,7 @@ bool AbstractMobileAppWizard::postGenerateFiles(const QWizard *w,
void AbstractMobileAppWizard::useProjectPath(const QString &projectName,
const QString &projectPath)
{
- wizardDialog()->m_optionsPage->setSymbianUid(app()->symbianUidForPath(projectPath + projectName));
+ wizardDialog()->m_symbianOptionsPage->setSymbianUid(app()->symbianUidForPath(projectPath + projectName));
app()->setProjectName(projectName);
app()->setProjectPath(projectPath);
wizardDialog()->m_targetsPage->setProFilePath(app()->path(AbstractMobileApp::AppPro));
diff --git a/src/plugins/qt4projectmanager/wizards/abstractmobileappwizard.h b/src/plugins/qt4projectmanager/wizards/abstractmobileappwizard.h
index 993ced1f26..0a8601ab62 100644
--- a/src/plugins/qt4projectmanager/wizards/abstractmobileappwizard.h
+++ b/src/plugins/qt4projectmanager/wizards/abstractmobileappwizard.h
@@ -41,16 +41,41 @@ namespace Qt4ProjectManager {
namespace Internal {
class AbstractMobileApp;
+class MobileAppWizardGenericOptionsPage;
+class MobileAppWizardSymbianOptionsPage;
+class MobileAppWizardMaemoOptionsPage;
-class AbstractMobileAppWizardDialog : public ProjectExplorer::BaseProjectWizardDialog
+class AbstractMobileAppWizardDialog : public ProjectExplorer::BaseProjectWizardDialog
{
Q_OBJECT
protected:
explicit AbstractMobileAppWizardDialog(QWidget *parent = 0);
public:
- class MobileAppWizardOptionsPage *m_optionsPage;
+ MobileAppWizardGenericOptionsPage *m_genericOptionsPage;
+ MobileAppWizardSymbianOptionsPage *m_symbianOptionsPage;
+ MobileAppWizardMaemoOptionsPage *m_maemoOptionsPage;
class TargetSetupPage *m_targetsPage;
+
+protected:
+ int addPageWithTitle(QWizardPage *page, const QString &title);
+ virtual void initializePage(int id);
+ virtual void cleanupPage(int id);
+
+private:
+ virtual int nextId() const;
+
+ int idOfNextGenericPage() const;
+ Utils::WizardProgressItem *itemOfNextGenericPage() const;
+
+ int m_genericOptionsPageId;
+ int m_symbianOptionsPageId;
+ int m_maemoOptionsPageId;
+ int m_targetsPageId;
+ Utils::WizardProgressItem *m_targetItem;
+ Utils::WizardProgressItem *m_genericItem;
+ Utils::WizardProgressItem *m_symbianItem;
+ Utils::WizardProgressItem *m_maemoItem;
};
class AbstractMobileAppWizard : public Core::BaseFileWizard
diff --git a/src/plugins/qt4projectmanager/wizards/emptyprojectwizard.cpp b/src/plugins/qt4projectmanager/wizards/emptyprojectwizard.cpp
index ca109a9275..d0888a7056 100644
--- a/src/plugins/qt4projectmanager/wizards/emptyprojectwizard.cpp
+++ b/src/plugins/qt4projectmanager/wizards/emptyprojectwizard.cpp
@@ -74,7 +74,7 @@ Core::GeneratedFiles
const QString profileName = Core::BaseFileWizard::buildFileName(projectPath, params.fileName, profileSuffix());
Core::GeneratedFile profile(profileName);
- profile.setAttributes(Core::GeneratedFile::OpenProjectAttribute);
+ profile.setAttributes(Core::GeneratedFile::OpenProjectAttribute | Core::GeneratedFile::OpenEditorAttribute);
return Core::GeneratedFiles() << profile;
}
diff --git a/src/plugins/qt4projectmanager/wizards/librarywizarddialog.cpp b/src/plugins/qt4projectmanager/wizards/librarywizarddialog.cpp
index 29525f5686..aacd7769b2 100644
--- a/src/plugins/qt4projectmanager/wizards/librarywizarddialog.cpp
+++ b/src/plugins/qt4projectmanager/wizards/librarywizarddialog.cpp
@@ -156,7 +156,18 @@ LibraryWizardDialog::LibraryWizardDialog(const QString &templateName,
setIntroDescription(tr("This wizard generates a C++ library project."));
m_targetPageId = addTargetSetupPage();
+ Utils::WizardProgressItem *targetItem = wizardProgress()->item(m_targetPageId);
+
+ m_mobilePageId = addPage(m_mobilePage);
+ Utils::WizardProgressItem *mobileItem = wizardProgress()->item(m_mobilePageId);
+ mobileItem->setTitle(QLatin1String(" ") + tr("Symbian Specific"));
+
m_modulesPageId = addModulesPage();
+ Utils::WizardProgressItem *modulesItem = wizardProgress()->item(m_modulesPageId);
+
+ targetItem->setNextItems(QList<Utils::WizardProgressItem *>()
+ << mobileItem << modulesItem);
+ targetItem->setNextShownItem(0);
m_filesPage->setNamespacesEnabled(true);
m_filesPage->setFormFileInputVisible(false);
@@ -165,9 +176,6 @@ LibraryWizardDialog::LibraryWizardDialog(const QString &templateName,
m_filesPageId = addPage(m_filesPage);
wizardProgress()->item(m_filesPageId)->setTitle(tr("Details"));
- m_mobilePageId = addPage(m_mobilePage);
- wizardProgress()->item(m_mobilePageId)->setTitle(tr("Symbian Specific"));
-
connect(this, SIGNAL(currentIdChanged(int)), this, SLOT(slotCurrentIdChanged(int)));
foreach (QWizardPage *p, extensionPages)
diff --git a/src/plugins/qt4projectmanager/wizards/mobileapp.cpp b/src/plugins/qt4projectmanager/wizards/mobileapp.cpp
index 482c4202ca..06cbe80e29 100644
--- a/src/plugins/qt4projectmanager/wizards/mobileapp.cpp
+++ b/src/plugins/qt4projectmanager/wizards/mobileapp.cpp
@@ -142,7 +142,7 @@ QString MobileApp::mainWindowClassName() const
int MobileApp::stubVersionMinor() const { return StubVersion; }
-const int MobileApp::StubVersion = 1;
+const int MobileApp::StubVersion = 2;
} // namespace Internal
} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/wizards/mobileapp.h b/src/plugins/qt4projectmanager/wizards/mobileapp.h
index 2c89027cce..07b7310ec9 100644
--- a/src/plugins/qt4projectmanager/wizards/mobileapp.h
+++ b/src/plugins/qt4projectmanager/wizards/mobileapp.h
@@ -44,7 +44,7 @@ struct MobileAppGeneratedFileInfo : AbstractGeneratedFileInfo
enum ExtendedFileType {
MainWindowCppFile = ExtendedFile,
MainWindowHFile,
- MainWindowUiFile,
+ MainWindowUiFile
};
MobileAppGeneratedFileInfo() : AbstractGeneratedFileInfo() {}
@@ -60,7 +60,7 @@ public:
MainWindowH,
MainWindowHOrigin,
MainWindowUi,
- MainWindowUiOrigin,
+ MainWindowUiOrigin
};
MobileApp();
diff --git a/src/plugins/qt4projectmanager/wizards/mobileappwizardgenericoptionspage.ui b/src/plugins/qt4projectmanager/wizards/mobileappwizardgenericoptionspage.ui
new file mode 100644
index 0000000000..337fdbc7d3
--- /dev/null
+++ b/src/plugins/qt4projectmanager/wizards/mobileappwizardgenericoptionspage.ui
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MobileAppWizardGenericOptionsPage</class>
+ <widget class="QWizardPage" name="MobileAppWizardGenericOptionsPage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>396</width>
+ <height>115</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>WizardPage</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="orientationBehaviorLabel">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Orientation behavior:</string>
+ </property>
+ <property name="buddy">
+ <cstring>orientationBehaviorComboBox</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="orientationBehaviorComboBox"/>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>66</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/plugins/qt4projectmanager/wizards/mobileappwizardmaemooptionspage.ui b/src/plugins/qt4projectmanager/wizards/mobileappwizardmaemooptionspage.ui
new file mode 100644
index 0000000000..20f1f979d2
--- /dev/null
+++ b/src/plugins/qt4projectmanager/wizards/mobileappwizardmaemooptionspage.ui
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MobileAppWizardMaemoOptionsPage</class>
+ <widget class="QWizardPage" name="MobileAppWizardMaemoOptionsPage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>WizardPage</string>
+ </property>
+ <layout class="QFormLayout" name="formLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="appIconLabel">
+ <property name="text">
+ <string>Application icon (64x64):</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QToolButton" name="pngIconButton">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>64</width>
+ <height>64</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/plugins/qt4projectmanager/wizards/mobileappwizardoptionspage.ui b/src/plugins/qt4projectmanager/wizards/mobileappwizardoptionspage.ui
deleted file mode 100644
index 95a6bc5f1c..0000000000
--- a/src/plugins/qt4projectmanager/wizards/mobileappwizardoptionspage.ui
+++ /dev/null
@@ -1,233 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>MobileAppWizardOptionPage</class>
- <widget class="QWizardPage" name="MobileAppWizardOptionPage">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>404</width>
- <height>548</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>WizardPage</string>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <widget class="QGroupBox" name="groupBox_2">
- <property name="title">
- <string>General</string>
- </property>
- <layout class="QGridLayout" name="gridLayout_2">
- <property name="verticalSpacing">
- <number>12</number>
- </property>
- <item row="0" column="0">
- <widget class="QLabel" name="orientationBehaviorLabel">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Orientation behavior:</string>
- </property>
- <property name="buddy">
- <cstring>orientationBehaviorComboBox</cstring>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QComboBox" name="orientationBehaviorComboBox"/>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QTabWidget" name="platformsTabWidget">
- <property name="currentIndex">
- <number>0</number>
- </property>
- <widget class="QWidget" name="tab">
- <attribute name="title">
- <string>Symbian Specific</string>
- </attribute>
- <layout class="QFormLayout" name="formLayout">
- <item row="0" column="0">
- <widget class="QLabel" name="symbianAppIconLabel">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Application icon (.svg):</string>
- </property>
- <property name="buddy">
- <cstring>symbianAppIconLoadToolButton</cstring>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <widget class="QLabel" name="symbianAppIconPreview">
- <property name="minimumSize">
- <size>
- <width>45</width>
- <height>45</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>45</width>
- <height>45</height>
- </size>
- </property>
- <property name="frameShape">
- <enum>QFrame::Panel</enum>
- </property>
- <property name="frameShadow">
- <enum>QFrame::Sunken</enum>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QToolButton" name="symbianAppIconLoadToolButton">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="symbianTargetUid3Label">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Target UID3:</string>
- </property>
- <property name="buddy">
- <cstring>symbianTargetUid3LineEdit</cstring>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <item>
- <widget class="QLineEdit" name="symbianTargetUid3LineEdit"/>
- </item>
- <item>
- <spacer name="horizontalSpacer_2">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- <item row="2" column="0" colspan="2">
- <widget class="QCheckBox" name="symbianEnableNetworkChackBox">
- <property name="text">
- <string>Enable network access</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <widget class="QWidget" name="tab_2">
- <attribute name="title">
- <string>Maemo Specific</string>
- </attribute>
- <widget class="QLabel" name="maemoAppIconLabel">
- <property name="geometry">
- <rect>
- <x>9</x>
- <y>9</y>
- <width>155</width>
- <height>16</height>
- </rect>
- </property>
- <property name="text">
- <string>Application icon (64x64):</string>
- </property>
- </widget>
- <widget class="QToolButton" name="maemoPngIconButton">
- <property name="geometry">
- <rect>
- <x>171</x>
- <y>10</y>
- <width>71</width>
- <height>70</height>
- </rect>
- </property>
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>0</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>16777215</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string/>
- </property>
- <property name="iconSize">
- <size>
- <width>64</width>
- <height>64</height>
- </size>
- </property>
- </widget>
- </widget>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/src/plugins/qt4projectmanager/wizards/mobileappwizardpages.cpp b/src/plugins/qt4projectmanager/wizards/mobileappwizardpages.cpp
index 37162a4b3f..a681e39214 100644
--- a/src/plugins/qt4projectmanager/wizards/mobileappwizardpages.cpp
+++ b/src/plugins/qt4projectmanager/wizards/mobileappwizardpages.cpp
@@ -32,9 +32,12 @@
**************************************************************************/
#include "mobileappwizardpages.h"
-#include "ui_mobileappwizardoptionspage.h"
+#include "ui_mobileappwizardgenericoptionspage.h"
+#include "ui_mobileappwizardmaemooptionspage.h"
+#include "ui_mobileappwizardsymbianoptionspage.h"
#include <coreplugin/coreconstants.h>
+#include <QtCore/QTemporaryFile>
#include <QtGui/QDesktopServices>
#include <QtGui/QFileDialog>
#include <QtGui/QFileDialog>
@@ -43,26 +46,32 @@
namespace Qt4ProjectManager {
namespace Internal {
-class MobileAppWizardOptionsPagePrivate
+class MobileAppWizardGenericOptionsPagePrivate
{
- Ui::MobileAppWizardOptionPage ui;
- QString symbianSvgIcon;
- QString maemoPngIcon;
- friend class MobileAppWizardOptionsPage;
+ Ui::MobileAppWizardGenericOptionsPage ui;
+ friend class MobileAppWizardGenericOptionsPage;
};
-MobileAppWizardOptionsPage::MobileAppWizardOptionsPage(QWidget *parent)
- : QWizardPage(parent)
- , m_d(new MobileAppWizardOptionsPagePrivate)
+class MobileAppWizardSymbianOptionsPagePrivate
{
- m_d->ui.setupUi(this);
+ Ui::MobileAppWizardSymbianOptionsPage ui;
+ QString svgIcon;
+ friend class MobileAppWizardSymbianOptionsPage;
+};
+
+class MobileAppWizardMaemoOptionsPagePrivate
+{
+ Ui::MobileAppWizardMaemoOptionsPage ui;
+ QString pngIcon;
+ friend class MobileAppWizardMaemoOptionsPage;
+};
- const QIcon open = QApplication::style()->standardIcon(QStyle::SP_DirOpenIcon);
- m_d->ui.symbianAppIconLoadToolButton->setIcon(open);
- connect(m_d->ui.symbianAppIconLoadToolButton, SIGNAL(clicked()), SLOT(openSymbianSvgIcon()));
- connect(m_d->ui.maemoPngIconButton, SIGNAL(clicked()), this,
- SLOT(openMaemoPngIcon()));
+MobileAppWizardGenericOptionsPage::MobileAppWizardGenericOptionsPage(QWidget *parent)
+ : QWizardPage(parent)
+ , m_d(new MobileAppWizardGenericOptionsPagePrivate)
+{
+ m_d->ui.setupUi(this);
m_d->ui.orientationBehaviorComboBox->addItem(tr("Automatically Rotate Orientation"),
AbstractMobileApp::ScreenOrientationAuto);
m_d->ui.orientationBehaviorComboBox->addItem(tr("Lock to Landscape Orientation"),
@@ -71,12 +80,12 @@ MobileAppWizardOptionsPage::MobileAppWizardOptionsPage(QWidget *parent)
AbstractMobileApp::ScreenOrientationLockPortrait);
}
-MobileAppWizardOptionsPage::~MobileAppWizardOptionsPage()
+MobileAppWizardGenericOptionsPage::~MobileAppWizardGenericOptionsPage()
{
delete m_d;
}
-void MobileAppWizardOptionsPage::setOrientation(AbstractMobileApp::ScreenOrientation orientation)
+void MobileAppWizardGenericOptionsPage::setOrientation(AbstractMobileApp::ScreenOrientation orientation)
{
QComboBox *const comboBox = m_d->ui.orientationBehaviorComboBox;
for (int i = 0; i < comboBox->count(); ++i)
@@ -86,88 +95,139 @@ void MobileAppWizardOptionsPage::setOrientation(AbstractMobileApp::ScreenOrienta
}
}
-AbstractMobileApp::ScreenOrientation MobileAppWizardOptionsPage::orientation() const
+AbstractMobileApp::ScreenOrientation MobileAppWizardGenericOptionsPage::orientation() const
{
const int index = m_d->ui.orientationBehaviorComboBox->currentIndex();
return static_cast<AbstractMobileApp::ScreenOrientation>(m_d->ui.orientationBehaviorComboBox->itemData(index).toInt());
}
-QString MobileAppWizardOptionsPage::symbianSvgIcon() const
+
+MobileAppWizardSymbianOptionsPage::MobileAppWizardSymbianOptionsPage(QWidget *parent)
+ : QWizardPage(parent)
+ , m_d(new MobileAppWizardSymbianOptionsPagePrivate)
{
- return m_d->symbianSvgIcon;
+ m_d->ui.setupUi(this);
+ const QIcon open = QApplication::style()->standardIcon(QStyle::SP_DirOpenIcon);
+ m_d->ui.appIconLoadToolButton->setIcon(open);
+ connect(m_d->ui.appIconLoadToolButton, SIGNAL(clicked()), SLOT(openSvgIcon()));
}
-void MobileAppWizardOptionsPage::setSymbianSvgIcon(const QString &icon)
+MobileAppWizardSymbianOptionsPage::~MobileAppWizardSymbianOptionsPage()
{
- QPixmap iconPixmap(icon);
- if (!iconPixmap.isNull()) {
- const int symbianIconSize = 44;
- if (iconPixmap.height() > symbianIconSize || iconPixmap.width() > symbianIconSize)
- iconPixmap = iconPixmap.scaledToHeight(symbianIconSize, Qt::SmoothTransformation);
- m_d->ui.symbianAppIconPreview->setPixmap(iconPixmap);
- m_d->symbianSvgIcon = icon;
- }
+ delete m_d;
}
-QString MobileAppWizardOptionsPage::maemoPngIcon() const
+QString MobileAppWizardSymbianOptionsPage::svgIcon() const
{
- return m_d->maemoPngIcon;
+ return m_d->svgIcon;
}
-void MobileAppWizardOptionsPage::setMaemoPngIcon(const QString &icon)
+void MobileAppWizardSymbianOptionsPage::setSvgIcon(const QString &icon)
{
- QString error;
QPixmap iconPixmap(icon);
- if (iconPixmap.isNull())
- error = tr("The file is not a valid image.");
- else if (iconPixmap.size() != QSize(64, 64))
- error = tr("The icon has an invalid size.");
- if (!error.isEmpty()) {
- QMessageBox::warning(this, tr("Icon unusable"), error);
- } else {
- m_d->ui.maemoPngIconButton->setIcon(iconPixmap);
- m_d->maemoPngIcon = icon;
+ if (!iconPixmap.isNull()) {
+ const int symbianIconSize = 44;
+ if (iconPixmap.height() > symbianIconSize || iconPixmap.width() > symbianIconSize)
+ iconPixmap = iconPixmap.scaledToHeight(symbianIconSize, Qt::SmoothTransformation);
+ m_d->ui.appIconPreview->setPixmap(iconPixmap);
+ m_d->svgIcon = icon;
}
}
-QString MobileAppWizardOptionsPage::symbianUid() const
+QString MobileAppWizardSymbianOptionsPage::symbianUid() const
{
- return m_d->ui.symbianTargetUid3LineEdit->text();
+ return m_d->ui.uid3LineEdit->text();
}
-void MobileAppWizardOptionsPage::setSymbianUid(const QString &uid)
+void MobileAppWizardSymbianOptionsPage::setSymbianUid(const QString &uid)
{
- m_d->ui.symbianTargetUid3LineEdit->setText(uid);
+ m_d->ui.uid3LineEdit->setText(uid);
}
-void MobileAppWizardOptionsPage::setNetworkEnabled(bool enableIt)
+void MobileAppWizardSymbianOptionsPage::setNetworkEnabled(bool enableIt)
{
- m_d->ui.symbianEnableNetworkChackBox->setChecked(enableIt);
+ m_d->ui.enableNetworkCheckBox->setChecked(enableIt);
}
-bool MobileAppWizardOptionsPage::networkEnabled() const
+bool MobileAppWizardSymbianOptionsPage::networkEnabled() const
{
- return m_d->ui.symbianEnableNetworkChackBox->isChecked();
+ return m_d->ui.enableNetworkCheckBox->isChecked();
}
-void MobileAppWizardOptionsPage::openSymbianSvgIcon()
+void MobileAppWizardSymbianOptionsPage::openSvgIcon()
{
const QString svgIcon = QFileDialog::getOpenFileName(
this,
- m_d->ui.symbianAppIconLabel->text(),
+ m_d->ui.appIconLabel->text(),
QDesktopServices::storageLocation(QDesktopServices::PicturesLocation),
QLatin1String("*.svg"));
if (!svgIcon.isEmpty())
- setSymbianSvgIcon(svgIcon);
+ setSvgIcon(svgIcon);
+}
+
+
+MobileAppWizardMaemoOptionsPage::MobileAppWizardMaemoOptionsPage(QWidget *parent)
+ : QWizardPage(parent)
+ , m_d(new MobileAppWizardMaemoOptionsPagePrivate)
+{
+ m_d->ui.setupUi(this);
+ connect(m_d->ui.pngIconButton, SIGNAL(clicked()), this, SLOT(openPngIcon()));
+}
+
+MobileAppWizardMaemoOptionsPage::~MobileAppWizardMaemoOptionsPage()
+{
+ delete m_d;
+}
+
+QString MobileAppWizardMaemoOptionsPage::pngIcon() const
+{
+ return m_d->pngIcon;
+}
+
+void MobileAppWizardMaemoOptionsPage::setPngIcon(const QString &icon)
+{
+ QString error;
+ QPixmap iconPixmap(icon);
+ if (iconPixmap.isNull()) {
+ QMessageBox::critical(this, tr("Invalid Icon"),
+ tr("The file is not a valid image."));
+ return;
+ }
+
+ const QSize iconSize(64, 64);
+ QString actualIconPath;
+ if (iconPixmap.size() == iconSize) {
+ actualIconPath = icon;
+ } else {
+ const QMessageBox::StandardButton button = QMessageBox::warning(this,
+ tr("Wrong Icon Size"), tr("The icon needs to be 64x64 pixels big, "
+ "but is not. Do you want Creator to scale it?"),
+ QMessageBox::Ok | QMessageBox::Cancel);
+ if (button != QMessageBox::Ok)
+ return;
+ iconPixmap = iconPixmap.scaled(iconSize);
+ QTemporaryFile tmpFile;
+ tmpFile.setAutoRemove(false);
+ const char * const format = QFileInfo(icon).suffix().toAscii().data();
+ if (!tmpFile.open() || !iconPixmap.save(&tmpFile, format)) {
+ QMessageBox::critical(this, tr("File Error"),
+ tr("Could not copy icon file."));
+ return;
+ }
+ actualIconPath = tmpFile.fileName();
+ }
+
+ m_d->ui.pngIconButton->setIcon(iconPixmap);
+ m_d->pngIcon = actualIconPath;
}
-void MobileAppWizardOptionsPage::openMaemoPngIcon()
+void MobileAppWizardMaemoOptionsPage::openPngIcon()
{
const QString iconPath = QFileDialog::getOpenFileName(this,
- m_d->ui.maemoAppIconLabel->text(), m_d->maemoPngIcon,
+ m_d->ui.appIconLabel->text(), m_d->pngIcon,
QLatin1String("*.png"));
if (!iconPath.isEmpty())
- setMaemoPngIcon(iconPath);
+ setPngIcon(iconPath);
}
} // namespace Internal
diff --git a/src/plugins/qt4projectmanager/wizards/mobileappwizardpages.h b/src/plugins/qt4projectmanager/wizards/mobileappwizardpages.h
index 345fb9f29a..b48a7a16b0 100644
--- a/src/plugins/qt4projectmanager/wizards/mobileappwizardpages.h
+++ b/src/plugins/qt4projectmanager/wizards/mobileappwizardpages.h
@@ -41,32 +41,62 @@
namespace Qt4ProjectManager {
namespace Internal {
-class MobileAppWizardOptionsPage : public QWizardPage
+class MobileAppWizardGenericOptionsPage : public QWizardPage
{
Q_OBJECT
- Q_DISABLE_COPY(MobileAppWizardOptionsPage)
+ Q_DISABLE_COPY(MobileAppWizardGenericOptionsPage)
public:
- explicit MobileAppWizardOptionsPage(QWidget *parent = 0);
- virtual ~MobileAppWizardOptionsPage();
+ explicit MobileAppWizardGenericOptionsPage(QWidget *parent = 0);
+ virtual ~MobileAppWizardGenericOptionsPage();
void setOrientation(AbstractMobileApp::ScreenOrientation orientation);
AbstractMobileApp::ScreenOrientation orientation() const;
- QString symbianSvgIcon() const;
- void setSymbianSvgIcon(const QString &icon);
- QString maemoPngIcon() const;
- void setMaemoPngIcon(const QString &icon);
+
+private:
+ class MobileAppWizardGenericOptionsPagePrivate *m_d;
+};
+
+class MobileAppWizardSymbianOptionsPage : public QWizardPage
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(MobileAppWizardSymbianOptionsPage)
+
+public:
+ explicit MobileAppWizardSymbianOptionsPage(QWidget *parent = 0);
+ virtual ~MobileAppWizardSymbianOptionsPage();
+
+ QString svgIcon() const;
+ void setSvgIcon(const QString &icon);
QString symbianUid() const;
void setNetworkEnabled(bool enableIt);
bool networkEnabled() const;
void setSymbianUid(const QString &uid);
private slots:
- void openSymbianSvgIcon(); // Via file open dialog
- void openMaemoPngIcon();
+ void openSvgIcon(); // Via file open dialog
+
+private:
+ class MobileAppWizardSymbianOptionsPagePrivate *m_d;
+};
+
+class MobileAppWizardMaemoOptionsPage : public QWizardPage
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(MobileAppWizardMaemoOptionsPage)
+
+public:
+ explicit MobileAppWizardMaemoOptionsPage(QWidget *parent = 0);
+ virtual ~MobileAppWizardMaemoOptionsPage();
+
+ QString pngIcon() const;
+ void setPngIcon(const QString &icon);
+
+private slots:
+ void openPngIcon();
private:
- class MobileAppWizardOptionsPagePrivate *m_d;
+ class MobileAppWizardMaemoOptionsPagePrivate *m_d;
};
} // end of namespace Internal
diff --git a/src/plugins/qt4projectmanager/wizards/mobileappwizardsymbianoptionspage.ui b/src/plugins/qt4projectmanager/wizards/mobileappwizardsymbianoptionspage.ui
new file mode 100644
index 0000000000..48919f89d5
--- /dev/null
+++ b/src/plugins/qt4projectmanager/wizards/mobileappwizardsymbianoptionspage.ui
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MobileAppWizardSymbianOptionsPage</class>
+ <widget class="QWizardPage" name="MobileAppWizardSymbianOptionsPage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>WizardPage</string>
+ </property>
+ <layout class="QFormLayout" name="formLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="appIconLabel">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Application icon (.svg):</string>
+ </property>
+ <property name="buddy">
+ <cstring>appIconLoadToolButton</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="appIconPreview">
+ <property name="minimumSize">
+ <size>
+ <width>45</width>
+ <height>45</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>45</width>
+ <height>45</height>
+ </size>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::Panel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Sunken</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="appIconLoadToolButton">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="symbianTargetUid3Label">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Target UID3:</string>
+ </property>
+ <property name="buddy">
+ <cstring>uid3LineEdit</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QLineEdit" name="uid3LineEdit"/>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item row="2" column="0" colspan="2">
+ <widget class="QCheckBox" name="enableNetworkCheckBox">
+ <property name="text">
+ <string>Enable network access</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/plugins/qt4projectmanager/wizards/mobilelibraryparameters.cpp b/src/plugins/qt4projectmanager/wizards/mobilelibraryparameters.cpp
index 7f0ac8c83a..9cd1778341 100644
--- a/src/plugins/qt4projectmanager/wizards/mobilelibraryparameters.cpp
+++ b/src/plugins/qt4projectmanager/wizards/mobilelibraryparameters.cpp
@@ -95,11 +95,10 @@ void MobileLibraryParameters::writeProFile(QTextStream &str) const
void MobileLibraryParameters::writeSymbianProFile(QTextStream &str) const
{
if (libraryType != QtProjectParameters::SharedLibrary)
- return; //nothing to do when the library is not shared library
+ return; //nothing to do when the library is not a shared library
str << "\n"
"symbian {\n"
- " #Symbian specific definitions\n"
" MMP_RULES += EXPORTUNFROZEN\n"
" TARGET.UID3 = " + symbianUid + "\n"
" TARGET.CAPABILITY = " + generateCapabilitySet(symbianCapabilities).toAscii() + "\n"
@@ -117,7 +116,7 @@ void MobileLibraryParameters::writeMaemoProFile(QTextStream &str) const
" maemo5 {\n"
" target.path = /opt/usr/lib\n"
" } else {\n"
- " target.path = /usr/local/lib\n"
+ " target.path = /usr/lib\n"
" }\n"
" INSTALLS += target\n"
"}\n";
diff --git a/src/plugins/qt4projectmanager/wizards/qmlstandaloneapp.cpp b/src/plugins/qt4projectmanager/wizards/qmlstandaloneapp.cpp
index eae1aec8eb..3b5bd1fd6b 100644
--- a/src/plugins/qt4projectmanager/wizards/qmlstandaloneapp.cpp
+++ b/src/plugins/qt4projectmanager/wizards/qmlstandaloneapp.cpp
@@ -164,8 +164,9 @@ bool QmlStandaloneApp::setExternalModules(const QStringList &uris,
QString QmlStandaloneApp::pathExtended(int fileType) const
{
+ QString cleanProjectName = projectName().replace(QLatin1Char('-'), QString());
const QString qmlSubDir = QLatin1String("qml/")
- + (useExistingMainQml() ? m_mainQmlFile.dir().dirName() : projectName())
+ + (useExistingMainQml() ? m_mainQmlFile.dir().dirName() : cleanProjectName)
+ QLatin1Char('/');
const QString appViewerTargetSubDir = appViewerOriginsSubDir;
const QString mainQml = QLatin1String("main.qml");
diff --git a/src/plugins/qt4projectmanager/wizards/qmlstandaloneapp.h b/src/plugins/qt4projectmanager/wizards/qmlstandaloneapp.h
index 83ef0ed1ba..7a89560fd1 100644
--- a/src/plugins/qt4projectmanager/wizards/qmlstandaloneapp.h
+++ b/src/plugins/qt4projectmanager/wizards/qmlstandaloneapp.h
@@ -83,7 +83,7 @@ struct QmlAppGeneratedFileInfo : public AbstractGeneratedFileInfo
MainQmlFile = ExtendedFile,
AppViewerPriFile,
AppViewerCppFile,
- AppViewerHFile,
+ AppViewerHFile
};
QmlAppGeneratedFileInfo() : AbstractGeneratedFileInfo() {}
diff --git a/src/plugins/qt4projectmanager/wizards/qmlstandaloneappwizard.cpp b/src/plugins/qt4projectmanager/wizards/qmlstandaloneappwizard.cpp
index 9a53655f5b..9014bf1679 100644
--- a/src/plugins/qt4projectmanager/wizards/qmlstandaloneappwizard.cpp
+++ b/src/plugins/qt4projectmanager/wizards/qmlstandaloneappwizard.cpp
@@ -71,10 +71,10 @@ QmlStandaloneAppWizardDialog::QmlStandaloneAppWizardDialog(QWidget *parent)
setIntroDescription(tr("This wizard generates a Qt Quick application project."));
m_qmlSourcesPage = new QmlStandaloneAppWizardSourcesPage;
- const int qmlSourcesPagePageId = addPage(m_qmlSourcesPage);
- wizardProgress()->item(qmlSourcesPagePageId)->setTitle(tr("QML Sources"));
+ addPageWithTitle(m_qmlSourcesPage, tr("QML Sources"));
}
+
class QmlStandaloneAppWizardPrivate
{
class QmlStandaloneApp *standaloneApp;
diff --git a/src/plugins/qt4projectmanager/wizards/qtwizard.cpp b/src/plugins/qt4projectmanager/wizards/qtwizard.cpp
index d7fbe63a6c..fa42fd2b97 100644
--- a/src/plugins/qt4projectmanager/wizards/qtwizard.cpp
+++ b/src/plugins/qt4projectmanager/wizards/qtwizard.cpp
@@ -216,7 +216,7 @@ void BaseQt4ProjectWizardDialog::init(bool showModulesPage)
{
if (showModulesPage)
m_modulesPage = new ModulesPage;
- connect(this, SIGNAL(introPageLeft(QString,QString)),
+ connect(this, SIGNAL(projectParametersChanged(QString,QString)),
this, SLOT(generateProfileName(QString,QString)));
}
diff --git a/src/plugins/qt4projectmanager/wizards/subdirsprojectwizard.cpp b/src/plugins/qt4projectmanager/wizards/subdirsprojectwizard.cpp
new file mode 100644
index 0000000000..f9f0f76971
--- /dev/null
+++ b/src/plugins/qt4projectmanager/wizards/subdirsprojectwizard.cpp
@@ -0,0 +1,95 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "subdirsprojectwizard.h"
+
+#include "subdirsprojectwizarddialog.h"
+
+#include <projectexplorer/projectexplorerconstants.h>
+#include <coreplugin/icore.h>
+
+#include <QtGui/QIcon>
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+SubdirsProjectWizard::SubdirsProjectWizard()
+ : QtWizard(QLatin1String("U.Qt4Subdirs"),
+ QLatin1String(ProjectExplorer::Constants::PROJECT_WIZARD_CATEGORY),
+ QLatin1String(ProjectExplorer::Constants::PROJECT_WIZARD_TR_SCOPE),
+ QLatin1String(ProjectExplorer::Constants::PROJECT_WIZARD_TR_CATEGORY),
+ tr("Subdirs Project"),
+ tr("Creates a qmake-based subdirs project. This allows you to group "
+ "your projects in a tree structure."),
+ QIcon(QLatin1String(":/wizards/images/gui.png")))
+{
+}
+
+QWizard *SubdirsProjectWizard::createWizardDialog(QWidget *parent,
+ const QString &defaultPath,
+ const WizardPageList &extensionPages) const
+{
+ SubdirsProjectWizardDialog *dialog = new SubdirsProjectWizardDialog(displayName(), icon(), extensionPages, parent);
+ dialog->setPath(defaultPath);
+ dialog->setProjectName(SubdirsProjectWizardDialog::uniqueProjectName(defaultPath));
+ const QString buttonText = dialog->wizardStyle() == QWizard::MacStyle
+ ? tr("Done && Add Subproject") : tr("Finish && Add Subproject");
+ dialog->setButtonText(QWizard::FinishButton, buttonText);
+ return dialog;
+}
+
+Core::GeneratedFiles SubdirsProjectWizard::generateFiles(const QWizard *w,
+ QString * /*errorMessage*/) const
+{
+ const SubdirsProjectWizardDialog *wizard = qobject_cast< const SubdirsProjectWizardDialog *>(w);
+ const QtProjectParameters params = wizard->parameters();
+ const QString projectPath = params.projectPath();
+ const QString profileName = Core::BaseFileWizard::buildFileName(projectPath, params.fileName, profileSuffix());
+
+ Core::GeneratedFile profile(profileName);
+ profile.setAttributes(Core::GeneratedFile::OpenProjectAttribute | Core::GeneratedFile::OpenEditorAttribute);
+ profile.setContents(QLatin1String("TEMPLATE = subdirs\n"));
+ return Core::GeneratedFiles() << profile;
+}
+
+bool SubdirsProjectWizard::postGenerateFiles(const QWizard *w, const Core::GeneratedFiles &files, QString *errorMessage)
+{
+ const SubdirsProjectWizardDialog *wizard = qobject_cast< const SubdirsProjectWizardDialog *>(w);
+ if (QtWizard::qt4ProjectPostGenerateFiles(wizard, files, errorMessage)) {
+ Core::ICore::instance()->showNewItemDialog(tr("New Subproject", "Title of dialog"),
+ Core::IWizard::wizardsOfKind(Core::IWizard::ProjectWizard),
+ wizard->parameters().projectPath());
+ } else {
+ return false;
+ }
+ return true;
+}
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/wizards/subdirsprojectwizard.h b/src/plugins/qt4projectmanager/wizards/subdirsprojectwizard.h
new file mode 100644
index 0000000000..14f0f7707f
--- /dev/null
+++ b/src/plugins/qt4projectmanager/wizards/subdirsprojectwizard.h
@@ -0,0 +1,62 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** No Commercial Usage
+**
+** This file 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.
+**
+**************************************************************************/
+
+#ifndef SUBDIRSPROJECTWIZARD_H
+#define SUBDIRSPROJECTWIZARD_H
+
+#include "qtwizard.h"
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+class SubdirsProjectWizard : public QtWizard
+{
+ Q_OBJECT
+
+public:
+ SubdirsProjectWizard();
+
+protected:
+ virtual QWizard *createWizardDialog(QWidget *parent,
+ const QString &defaultPath,
+ const WizardPageList &extensionPages) const;
+
+ virtual Core::GeneratedFiles generateFiles(const QWizard *w,
+ QString *errorMessage) const;
+ virtual bool postGenerateFiles(const QWizard *, const Core::GeneratedFiles &l, QString *errorMessage);
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // SUBDIRSPROJECTWIZARD_H
diff --git a/src/plugins/qt4projectmanager/wizards/subdirsprojectwizarddialog.cpp b/src/plugins/qt4projectmanager/wizards/subdirsprojectwizarddialog.cpp
new file mode 100644
index 0000000000..06f88efad0
--- /dev/null
+++ b/src/plugins/qt4projectmanager/wizards/subdirsprojectwizarddialog.cpp
@@ -0,0 +1,68 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** No Commercial Usage
+**
+** This file 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.
+**
+**************************************************************************/
+
+#include "subdirsprojectwizarddialog.h"
+#include "qtprojectparameters.h"
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+SubdirsProjectWizardDialog::SubdirsProjectWizardDialog(const QString &templateName,
+ const QIcon &icon,
+ const QList<QWizardPage*> &extensionPages,
+ QWidget *parent) :
+ BaseQt4ProjectWizardDialog(parent)
+{
+ setWindowIcon(icon);
+ setWindowTitle(templateName);
+
+ setIntroDescription(tr("This wizard generates Qt4 subdirs project. "
+ "Add subprojects to it later on by using the other wizards."));
+
+ addTargetSetupPage();
+
+ foreach (QWizardPage *p, extensionPages)
+ Core::BaseFileWizard::applyExtensionPageShortTitle(this, addPage(p));
+}
+
+QtProjectParameters SubdirsProjectWizardDialog::parameters() const
+{
+ QtProjectParameters rc;
+ rc.type = QtProjectParameters::EmptyProject;
+ rc.fileName = projectName();
+ rc.path = path();
+ return rc;
+}
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/wizards/subdirsprojectwizarddialog.h b/src/plugins/qt4projectmanager/wizards/subdirsprojectwizarddialog.h
new file mode 100644
index 0000000000..d5a51e01b9
--- /dev/null
+++ b/src/plugins/qt4projectmanager/wizards/subdirsprojectwizarddialog.h
@@ -0,0 +1,55 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 SUBDIRSPROJECTWIZARDDIALOG_H
+#define SUBDIRSPROJECTWIZARDDIALOG_H
+
+#include "qtwizard.h"
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+struct QtProjectParameters;
+
+class SubdirsProjectWizardDialog : public BaseQt4ProjectWizardDialog
+{
+ Q_OBJECT
+public:
+ explicit SubdirsProjectWizardDialog(const QString &templateName,
+ const QIcon &icon,
+ const QList<QWizardPage*> &extensionPages,
+ QWidget *parent = 0);
+
+ QtProjectParameters parameters() const;
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // SUBDIRSPROJECTWIZARDDIALOG_H
diff --git a/src/plugins/qt4projectmanager/wizards/targetsetuppage.cpp b/src/plugins/qt4projectmanager/wizards/targetsetuppage.cpp
index 3a0b50c71f..0de0de6ab9 100644
--- a/src/plugins/qt4projectmanager/wizards/targetsetuppage.cpp
+++ b/src/plugins/qt4projectmanager/wizards/targetsetuppage.cpp
@@ -44,6 +44,7 @@
#include <projectexplorer/task.h>
#include <projectexplorer/taskhub.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <QtGui/QAction>
#include <QtGui/QFileDialog>
@@ -55,6 +56,7 @@
#include <QtGui/QPushButton>
#include <QtGui/QTreeWidget>
+using namespace Qt4ProjectManager;
using namespace Qt4ProjectManager::Internal;
namespace {
@@ -87,6 +89,15 @@ TargetSetupPage::TargetSetupPage(QWidget *parent) :
this, SLOT(handleDoubleClicks(QTreeWidgetItem*,int)));
connect(m_ui->versionTree, SIGNAL(customContextMenuRequested(QPoint)),
this, SLOT(contextMenuRequested(QPoint)));
+
+ setTitle(tr("Qt Versions"));
+}
+
+void TargetSetupPage::initializePage()
+{
+ // WORKAROUND: Somebody sets all buttons to autoDefault between the ctor and here!
+ m_ui->importButton->setAutoDefault(false);
+ m_ui->uncheckButton->setAutoDefault(false);
}
TargetSetupPage::~TargetSetupPage()
@@ -236,6 +247,10 @@ bool TargetSetupPage::setupProject(Qt4ProjectManager::Qt4Project *project)
Q_ASSERT(project->targets().isEmpty());
QtVersionManager *vm = QtVersionManager::instance();
+ // TODO remove again
+ Qt4TargetFactory *factory =
+ ExtensionSystem::PluginManager::instance()->getObject<Qt4TargetFactory>();
+
for (int i = 0; i < m_ui->versionTree->topLevelItemCount(); ++i) {
QTreeWidgetItem *current = m_ui->versionTree->topLevelItem(i);
QString targetId = current->data(NAME_COLUMN, Qt::UserRole).toString();
@@ -268,7 +283,7 @@ bool TargetSetupPage::setupProject(Qt4ProjectManager::Qt4Project *project)
// create the target:
Qt4Target *target = 0;
if (!targetInfos.isEmpty())
- target = project->targetFactory()->create(project, targetId, targetInfos);
+ target = factory->create(project, targetId, targetInfos);
if (target) {
project->addTarget(target);
@@ -279,7 +294,7 @@ bool TargetSetupPage::setupProject(Qt4ProjectManager::Qt4Project *project)
// Create the default target if nothing else was set up:
if (project->targets().isEmpty()) {
- Qt4Target *target = project->targetFactory()->create(project, Constants::DESKTOP_TARGET_ID);
+ Qt4Target *target = factory->create(project, Constants::DESKTOP_TARGET_ID);
if (target)
project->addTarget(target);
}
@@ -383,11 +398,11 @@ TargetSetupPage::recursivelyCheckDirectoryForBuild(const QString &directory, con
return results;
// Check for in-source builds first:
- QString qmakeBinary = QtVersionManager::findQMakeBinaryFromMakefile(directory);
+ QString qmakeBinary = QtVersionManager::findQMakeBinaryFromMakefile(directory + "/Makefile");
QDir dir(directory);
// Recurse into subdirectories:
- if (qmakeBinary.isNull() || !QtVersionManager::makefileIsFor(directory, proFile)) {
+ if (qmakeBinary.isNull() || !QtVersionManager::makefileIsFor(directory + "/Makefile", proFile)) {
QStringList subDirs = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
foreach (QString subDir, subDirs)
results.append(recursivelyCheckDirectoryForBuild(dir.absoluteFilePath(subDir),
@@ -412,21 +427,20 @@ TargetSetupPage::recursivelyCheckDirectoryForBuild(const QString &directory, con
info.isTemporary = true;
}
- QPair<QtVersion::QmakeBuildConfigs, QStringList> result =
- QtVersionManager::scanMakeFile(directory, info.version->defaultBuildConfig());
+ QPair<QtVersion::QmakeBuildConfigs, QString> result =
+ QtVersionManager::scanMakeFile(directory + "/Makefile", info.version->defaultBuildConfig());
info.buildConfig = result.first;
- info.additionalArguments = Qt4BuildConfiguration::removeSpecFromArgumentList(result.second);
-
- QString parsedSpec = Qt4BuildConfiguration::extractSpecFromArgumentList(result.second, directory, info.version);
+ QString aa = result.second;
+ QString parsedSpec = Qt4BuildConfiguration::extractSpecFromArguments(&aa, directory, info.version);
QString versionSpec = info.version->mkspec();
// Compare mkspecs and add to additional arguments
if (parsedSpec.isEmpty() || parsedSpec == versionSpec || parsedSpec == "default") {
// using the default spec, don't modify additional arguments
} else {
- info.additionalArguments.prepend(parsedSpec);
- info.additionalArguments.prepend("-spec");
+ info.additionalArguments = "-spec " + Utils::QtcProcess::quoteArg(parsedSpec);
}
+ Utils::QtcProcess::addArgs(&info.additionalArguments, aa);
results.append(info);
return results;
diff --git a/src/plugins/qt4projectmanager/wizards/targetsetuppage.h b/src/plugins/qt4projectmanager/wizards/targetsetuppage.h
index 57855b5118..413e6f5b67 100644
--- a/src/plugins/qt4projectmanager/wizards/targetsetuppage.h
+++ b/src/plugins/qt4projectmanager/wizards/targetsetuppage.h
@@ -91,7 +91,7 @@ public:
QtVersion *version;
bool isTemporary;
QtVersion::QmakeBuildConfigs buildConfig;
- QStringList additionalArguments;
+ QString additionalArguments;
QString directory;
bool isExistingBuild;
bool isShadowBuild;
@@ -100,6 +100,8 @@ public:
explicit TargetSetupPage(QWidget* parent = 0);
~TargetSetupPage();
+ void initializePage();
+
void setImportInfos(const QList<ImportInfo> &infos);
QList<ImportInfo> importInfos() const;
diff --git a/src/plugins/regexp/RegExp.pluginspec b/src/plugins/regexp/RegExp.pluginspec
deleted file mode 100644
index b15cc9ee44..0000000000
--- a/src/plugins/regexp/RegExp.pluginspec
+++ /dev/null
@@ -1,18 +0,0 @@
-<plugin name="RegExp" version="2.0.95" compatVersion="2.0.95">
- <vendor>Nokia Corporation</vendor>
- <copyright>(C) 2010 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>Regular Expression test widget.</description>
- <url>http://qt.nokia.com</url>
- <dependencyList>
- <dependency name="Core" version="2.0.95"/>
- </dependencyList>
-</plugin>
diff --git a/src/plugins/regexp/RegExp.pluginspec.in b/src/plugins/regexp/RegExp.pluginspec.in
new file mode 100644
index 0000000000..ff0059a677
--- /dev/null
+++ b/src/plugins/regexp/RegExp.pluginspec.in
@@ -0,0 +1,18 @@
+<plugin name=\"RegExp\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2010 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>Regular Expression test widget.</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/resourceeditor/ResourceEditor.pluginspec b/src/plugins/resourceeditor/ResourceEditor.pluginspec
deleted file mode 100644
index 33f3cfdd8b..0000000000
--- a/src/plugins/resourceeditor/ResourceEditor.pluginspec
+++ /dev/null
@@ -1,19 +0,0 @@
-<plugin name="ResourceEditor" version="2.0.95" compatVersion="2.0.95">
- <vendor>Nokia Corporation</vendor>
- <copyright>(C) 2010 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>
- <category>Qt Creator</category>
- <description>Editor for qrc files.</description>
- <url>http://qt.nokia.com</url>
- <dependencyList>
- <dependency name="Core" version="2.0.95"/>
- </dependencyList>
-</plugin>
diff --git a/src/plugins/resourceeditor/ResourceEditor.pluginspec.in b/src/plugins/resourceeditor/ResourceEditor.pluginspec.in
new file mode 100644
index 0000000000..bdc02381f6
--- /dev/null
+++ b/src/plugins/resourceeditor/ResourceEditor.pluginspec.in
@@ -0,0 +1,19 @@
+<plugin name=\"ResourceEditor\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2010 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>
+ <category>Qt Creator</category>
+ <description>Editor for qrc files.</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/resourceeditor/resourceeditor.pro b/src/plugins/resourceeditor/resourceeditor.pro
index 8d55df33f2..c300b4c5b6 100644
--- a/src/plugins/resourceeditor/resourceeditor.pro
+++ b/src/plugins/resourceeditor/resourceeditor.pro
@@ -22,5 +22,3 @@ resourcewizard.cpp \
resourceeditorw.cpp
RESOURCES += resourceeditor.qrc
-
-OTHER_FILES += ResourceEditor.pluginspec
diff --git a/src/plugins/resourceeditor/resourceeditorw.h b/src/plugins/resourceeditor/resourceeditorw.h
index 77976adfbe..0f44c189e5 100644
--- a/src/plugins/resourceeditor/resourceeditorw.h
+++ b/src/plugins/resourceeditor/resourceeditorw.h
@@ -93,7 +93,7 @@ public:
Core::IFile *file() { return m_resourceFile; }
QString id() const;
QString displayName() const { return m_displayName; }
- void setDisplayName(const QString &title) { m_displayName = title; }
+ void setDisplayName(const QString &title) { m_displayName = title; emit changed(); }
QWidget *toolBar() { return 0; }
QByteArray saveState() const { return QByteArray(); }
bool restoreState(const QByteArray &/*state*/) { return true; }
diff --git a/src/plugins/snippets/QMLSNIPPETS.TXT b/src/plugins/snippets/QMLSNIPPETS.TXT
deleted file mode 100644
index cd50273ed4..0000000000
--- a/src/plugins/snippets/QMLSNIPPETS.TXT
+++ /dev/null
@@ -1,96 +0,0 @@
-property <name> <name> : <name>
-if you delete the last name as you tab through it should also delete the : colon as that is not needed.
-
-----------------
-Item {
- id: <name>
-
- }
-If you delete the name maybe the 'id:' should be deleted as well.
-
-This is fine for most other QML elements such as Rectangle and MouseArea
-
-----------------
-
-BorderImage {
- id: <name>
- width: <name>; height: <name>
- border.left: <name>; border.top: <name>
- border.right: <name>; border.bottom: <name>
- source: "<name>"
-}
-
--------------------
-
-Image {
- id: <name>
- source: "<name>"
-}
-
-----------------
-
-Text {
- id: <name>
- text: "<name>"
-}
-
-----------------
-
-states: [
- State {
- name: "<name>"
- PropertyChanges {
- target: <name>
- <- cursor should end up here at the end?
- }
- }
-]
-
-------------------
-State {
- name: "<name>"
- PropertyChanges {
- target: <name>
- <- cursor should end up here at the end?
- }
-}
-
-
---------------------
-transitions: [
- Transition {
- from: "<name>"
- to: "<name>"
- <- cursor should end up here at the end?
- }
-]
-
------------------------
-
-Transition {
- from: "<name>"
- to: "<name>"
- <- cursor should end up here at the end?
-}
-
------------------------
-
-PropertyChanges {
- target: <name>
- <- cursor should end up here at the end?
- }
-
-NumberAnimation { matchTargets: "<name>"; matchProperties: "<name>"; duration: <int> }
-NumberAnimation { target: "<name>"; property: "<name>"; value: <name>; duration: <int> }
-PropertyAction { matchTargets: "<name>"; matchProperties: "<name>"; duration: <int> }
-PropertyAction { target: "<name>"; property: "<name>"; value: <name>; duration: <int> }
-PauseAnimation { duration: <name>}
-ColorAnimation { from: <name>; to: <name>; duration: <int> }
-effect: Colorize { color: "<name>" }
-effect: Blur { blurRadius: "<int>" }
-effect: DropShadow {
- blurRadius: <int>
- offset.x: <int>
- offset.y: <int>
- }
-
diff --git a/src/plugins/snippets/README b/src/plugins/snippets/README
deleted file mode 100644
index 0631c716c2..0000000000
--- a/src/plugins/snippets/README
+++ /dev/null
@@ -1 +0,0 @@
-This is dead code for now.
diff --git a/src/plugins/snippets/Snippets.pluginspec b/src/plugins/snippets/Snippets.pluginspec
deleted file mode 100644
index 9e4378fbf0..0000000000
--- a/src/plugins/snippets/Snippets.pluginspec
+++ /dev/null
@@ -1,20 +0,0 @@
-<plugin name="Snippets" version="2.0.95" compatVersion="2.0.95">
- <vendor>Nokia Corporation</vendor>
- <copyright>(C) 2010 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>Code snippet plugin.</description>
- <url>http://qt.nokia.com</url>
- <dependencyList>
- <dependency name="Core" version="2.0.95"/>
- <dependency name="TextEditor" version="2.0.95"/>
- <dependency name="ProjectExplorer" version="2.0.95"/>
- </dependencyList>
-</plugin>
diff --git a/src/plugins/snippets/images/dir.png b/src/plugins/snippets/images/dir.png
deleted file mode 100644
index 57cec6bcd3..0000000000
--- a/src/plugins/snippets/images/dir.png
+++ /dev/null
Binary files differ
diff --git a/src/plugins/snippets/images/diropen.png b/src/plugins/snippets/images/diropen.png
deleted file mode 100644
index 48fcb9b703..0000000000
--- a/src/plugins/snippets/images/diropen.png
+++ /dev/null
Binary files differ
diff --git a/src/plugins/snippets/images/file.png b/src/plugins/snippets/images/file.png
deleted file mode 100644
index 4a24ce3c2f..0000000000
--- a/src/plugins/snippets/images/file.png
+++ /dev/null
Binary files differ
diff --git a/src/plugins/snippets/images/snippets.png b/src/plugins/snippets/images/snippets.png
deleted file mode 100644
index b799041d61..0000000000
--- a/src/plugins/snippets/images/snippets.png
+++ /dev/null
Binary files differ
diff --git a/src/plugins/snippets/inputwidget.cpp b/src/plugins/snippets/inputwidget.cpp
deleted file mode 100644
index 9c9be9c5b0..0000000000
--- a/src/plugins/snippets/inputwidget.cpp
+++ /dev/null
@@ -1,135 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#include <QtCore/QDebug>
-#include <QtGui/QApplication>
-#include <QtGui/QLabel>
-#include <QtGui/QLineEdit>
-#include <QtGui/QHBoxLayout>
-#include <QtGui/QBitmap>
-#include <QtGui/QPainter>
-#include <QtGui/QResizeEvent>
-
-#include "inputwidget.h"
-
-using namespace Snippets::Internal;
-
-InputWidget::InputWidget(const QString &text, const QString &value)
- : QFrame(0, Qt::Popup)
-{
- setAttribute(Qt::WA_DeleteOnClose);
-
- m_label = new QLabel();
- m_label->setTextFormat(Qt::RichText);
- m_label->setText(text);
-
- m_lineEdit = new QLineEdit();
- m_lineEdit->setText(value);
- m_lineEdit->setSelection(0, value.length());
-
- qApp->installEventFilter(this);
-
- QHBoxLayout *layout = new QHBoxLayout;
- layout->addWidget(m_label);
- layout->addWidget(m_lineEdit);
- layout->setMargin(3);
-
- setLayout(layout);
- ensurePolished();
-
- setAutoFillBackground(false);
-}
-
-void InputWidget::resizeEvent(QResizeEvent *event)
-{
- int height = event->size().height();
- int width = event->size().width();
- qDebug() << event->size();
-
- QPalette pal = palette();
- QLinearGradient bg(0,0,0,height);
- bg.setColorAt(0, QColor(195,195,255));
- bg.setColorAt(1, QColor(230,230,255));
- pal.setBrush(QPalette::Background, QBrush(bg));
- setPalette(pal);
-
- QBitmap bm(width, height);
- bm.fill(Qt::color0);
- QPainter p(&bm);
- p.setBrush(QBrush(Qt::color1, Qt::SolidPattern));
- p.setPen(Qt::color1);
- int rw = (25 * height) / width;
- p.drawRoundRect(0,0,width,height, rw, 25);
- setMask(bm);
-}
-
-void InputWidget::showInputWidget(const QPoint &position)
-{
- move(position);
- show();
- m_lineEdit->setFocus();
-}
-
-bool InputWidget::eventFilter(QObject *o, QEvent *e)
-{
- if (o != m_lineEdit) {
- switch (e->type()) {
- case QEvent::MouseButtonPress:
- case QEvent::MouseButtonDblClick:
- closeInputWidget(true);
- default:
- break;
- }
- } else if (e->type() == QEvent::KeyPress) {
- QKeyEvent *ke = static_cast<QKeyEvent *>(e);
- switch (ke->key()) {
- case Qt::Key_Escape:
- qDebug() << "Escape";
- closeInputWidget(true);
- break;
- case Qt::Key_Enter:
- case Qt::Key_Return:
- qDebug() << "Enter";
- closeInputWidget(false);
- return true;
- }
- }
-
- return false;
-}
-
-void InputWidget::closeInputWidget(bool cancel)
-{
- emit finished(cancel, m_lineEdit->text());
- close();
-}
diff --git a/src/plugins/snippets/inputwidget.h b/src/plugins/snippets/inputwidget.h
deleted file mode 100644
index 5a88ce31b3..0000000000
--- a/src/plugins/snippets/inputwidget.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#ifndef INPUTWIDGET_H
-#define INPUTWIDGET_H
-
-#include <QtGui/QFrame>
-
-QT_BEGIN_NAMESPACE
-class QLabel;
-class QLineEdit;
-QT_END_NAMESPACE
-
-namespace Snippets {
-namespace Internal {
-
-class InputWidget : public QFrame
-{
- Q_OBJECT
-
-public:
- InputWidget(const QString &text, const QString &value);
- void showInputWidget(const QPoint &position);
-
-signals:
- void finished(bool canceled, const QString &value);
-
-protected:
- bool eventFilter(QObject *, QEvent *);
- void resizeEvent(QResizeEvent *event);
-
-private:
- void closeInputWidget(bool cancel);
- QLabel *m_label;
- QLineEdit *m_lineEdit;
-};
-
-} // namespace Internal
-} // namespace Snippets
-
-#endif // INPUTWIDGET_H
diff --git a/src/plugins/snippets/snippets.pro b/src/plugins/snippets/snippets.pro
deleted file mode 100644
index 8c6eb285cd..0000000000
--- a/src/plugins/snippets/snippets.pro
+++ /dev/null
@@ -1,24 +0,0 @@
-TEMPLATE = lib
-TARGET = Snippets
-QT += xml
-
-include(../../qtcreatorplugin.pri)
-include(../../plugins/projectexplorer/projectexplorer.pri)
-include(../../plugins/coreplugin/coreplugin.pri)
-include(../../plugins/texteditor/texteditor.pri)
-
-INCLUDEPATH += ../projectexplorer
-
-HEADERS += snippetsplugin.h \
- snippetswindow.h \
- snippetspec.h \
- snippetscompletion.h \
- inputwidget.h
-
-SOURCES += snippetsplugin.cpp \
- snippetswindow.cpp \
- snippetspec.cpp \
- snippetscompletion.cpp \
- inputwidget.cpp
-
-RESOURCES += snippets.qrc
diff --git a/src/plugins/snippets/snippets.qrc b/src/plugins/snippets/snippets.qrc
deleted file mode 100644
index b36585dcc5..0000000000
--- a/src/plugins/snippets/snippets.qrc
+++ /dev/null
@@ -1,8 +0,0 @@
-<RCC>
- <qresource prefix="/snippets" >
- <file>images/file.png</file>
- <file>images/dir.png</file>
- <file>images/diropen.png</file>
- <file>images/snippets.png</file>
- </qresource>
-</RCC>
diff --git a/src/plugins/snippets/snippetscompletion.cpp b/src/plugins/snippets/snippetscompletion.cpp
deleted file mode 100644
index 8180bf281f..0000000000
--- a/src/plugins/snippets/snippetscompletion.cpp
+++ /dev/null
@@ -1,168 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#include "snippetscompletion.h"
-#include "snippetswindow.h"
-#include "snippetspec.h"
-#include "snippetsplugin.h"
-
-#include <texteditor/itexteditable.h>
-
-#include <QtCore/QDebug>
-#include <QtCore/QMap>
-#include <QtGui/QAction>
-#include <QtGui/QKeyEvent>
-
-using namespace Snippets::Internal;
-
-const QIcon SnippetsCompletion::m_fileIcon = QIcon(":/snippets/images/file.png");
-
-SnippetsCompletion::SnippetsCompletion(QObject *parent)
- : ICompletionCollector(parent)
-{
- m_snippetsWindow = SnippetsPlugin::snippetsWindow();
-
- updateCompletions();
-}
-
-SnippetsCompletion::~SnippetsCompletion()
-{
- qDeleteAll(m_autoCompletions.values());
- m_autoCompletions.clear();
-}
-
-void SnippetsCompletion::updateCompletions()
-{
- qDeleteAll(m_autoCompletions.values());
- m_autoCompletions.clear();
-#if 0
- int index = 0;
- foreach (SnippetSpec *spec, m_snippetsWindow->snippets()) {
- if (!spec->completionShortcut().isEmpty()) {
- TextEditor::CompletionItem *item = new TextEditor::CompletionItem;
- item->m_key = spec->name();
- item->m_collector = this;
- item->m_index = index;
- item->m_relevance = 0;
- m_autoCompletions.insert(spec->completionShortcut(), item);
- ++index;
- }
- }
-#endif
-}
-
-bool SnippetsCompletion::triggersCompletion(TextEditor::ITextEditable *editor)
-{
- QString currentWord = editor->textAt(editor->position() - 3, 3);
- currentWord = currentWord.trimmed();
- return currentWord.length() == 2 && m_autoCompletions.contains(currentWord) &&
- !editor->characterAt(editor->position() - 1).isSpace();
-}
-
-int SnippetsCompletion::startCompletion(TextEditor::ITextEditable *editor)
-{
- m_editor = editor;
- m_startPosition = findStartOfName(m_editor);
- return m_startPosition;
-}
-
-#if 0
-void SnippetsCompletion::completions(const QList<TextEditor::CompletionItem *> &completions)
-{
- const int length = m_editor->position() - m_startPosition;
- if (length >= 2) {
- QString key = m_editor->textAt(m_startPosition, length);
- foreach (TextEditor::CompletionItem* item, m_autoCompletions.values()) {
- if (item->m_key.startsWith(key, Qt::CaseInsensitive))
- completions->append(item);
- }
- }
-}
-#endif
-
-QString SnippetsCompletion::text(TextEditor::CompletionItem *item) const
-{
-#if 0
- const SnippetSpec *spec = m_snippetsWindow->snippets().at(item->m_index);
- return spec->name();
-#endif
- return QString();
-}
-
-QString SnippetsCompletion::details(TextEditor::CompletionItem *item) const
-{
-#if 0
- const SnippetSpec *spec = m_snippetsWindow->snippets().at(item->m_index);
- return spec->description();
-#endif
- return QString();
-}
-
-QIcon SnippetsCompletion::icon(TextEditor::CompletionItem *) const
-{
- return m_fileIcon;
-}
-
-void SnippetsCompletion::complete(const TextEditor::CompletionItem &item)
-{
-#if 0
- SnippetSpec *spec = m_snippetsWindow->snippets().at(item->m_index);
-
- int length = m_editor->position() - m_startPosition;
- m_editor->setCurPos(m_startPosition);
- m_editor->remove(length);
-
- m_snippetsWindow->insertSnippet(m_editor, spec);
-#endif
-}
-
-bool SnippetsCompletion::partiallyComplete(const myns::QList<TextEditor::CompletionItem>&)
-{
- return false;
-}
-
-void SnippetsCompletion::cleanup()
-{
-}
-
-int SnippetsCompletion::findStartOfName(const TextEditor::ITextEditor *editor)
-{
- int pos = editor->position() - 1;
- QChar chr = editor->characterAt(pos);
-
- // Skip to the start of a name
- while (!chr.isSpace() && !chr.isNull())
- chr = editor->characterAt(--pos);
-
- return pos + 1;
-}
diff --git a/src/plugins/snippets/snippetscompletion.h b/src/plugins/snippets/snippetscompletion.h
deleted file mode 100644
index 33609a6446..0000000000
--- a/src/plugins/snippets/snippetscompletion.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#ifndef SNIPPETSCOMPLETION_H
-#define SNIPPETSCOMPLETION_H
-
-#include <texteditor/icompletioncollector.h>
-
-#include <QtCore/QDir>
-#include <QtCore/QMap>
-#include <QtCore/QObject>
-#include <QtGui/QIcon>
-
-namespace TextEditor {
-class ITextEditable;
-class ITextEditor;
-}
-
-namespace Snippets {
-namespace Internal {
-
-class SnippetsWindow;
-class SnippetSpec;
-
-class SnippetsCompletion : public TextEditor::ICompletionCollector
-{
- Q_OBJECT
-public:
- SnippetsCompletion(QObject *parent);
- ~SnippetsCompletion();
-
- // ICompletionCollector
- bool triggersCompletion(TextEditor::ITextEditable *editor);
- int startCompletion(TextEditor::ITextEditable *editor);
- void completions(QList<TextEditor::CompletionItem *> *completions);
-
- QString text(TextEditor::CompletionItem *item) const;
- QString details(TextEditor::CompletionItem *item) const;
- QIcon icon(TextEditor::CompletionItem *item) const;
-
- void complete(const TextEditor::CompletionItem &item);
- bool partiallyComplete(const QList<TextEditor::CompletionItem> &);
- void cleanup();
-
- void completions(QList<TextEditor::CompletionItem>*);
-
-private slots:
- void updateCompletions();
-
-private:
- static int findStartOfName(const TextEditor::ITextEditor *editor);
-
- TextEditor::ITextEditable *m_editor;
- int m_startPosition; // Position of the cursor from which completion started
-
- SnippetsWindow *m_snippetsWindow;
-
- QMultiMap<QString, TextEditor::CompletionItem *> m_autoCompletions;
-
- static const QIcon m_fileIcon;
-};
-
-} // namespace Internal
-} // namespace Snippets
-
-#endif // SNIPPETSCOMPLETION_H
-
diff --git a/src/plugins/snippets/snippetspec.cpp b/src/plugins/snippets/snippetspec.cpp
deleted file mode 100644
index 495a4791ee..0000000000
--- a/src/plugins/snippets/snippetspec.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#include "snippetspec.h"
-#include "persistentsettings.h"
-
-using namespace Snippets::Internal;
-using ProjectExplorer::PersistentSettingsReader;
-
-bool SnippetSpec::load(const QString &fileName)
-{
- PersistentSettingsReader reader;
- if (!reader.load(fileName))
- return false;
-
- m_contents = reader.restoreValue(QLatin1String("Contents")).toString();
- m_name = reader.restoreValue(QLatin1String("Name")).toString();
- m_description = reader.restoreValue(QLatin1String("Description")).toString();
- m_category = reader.restoreValue(QLatin1String("Category")).toString();
- m_completionShortcut = reader.restoreValue(QLatin1String("Shortcut")).toString();
-
- QMap<QString, QVariant> temp = reader.restoreValue(QLatin1String("Arguments")).toMap();
- QMap<QString, QVariant>::const_iterator it, end;
- end = temp.constEnd();
- for (it = temp.constBegin(); it != end; ++it) {
- m_argumentDescription.insert( it.key().toInt(), it.value().toString());
- }
-
- temp = reader.restoreValue(QLatin1String("ArgumentDefaults")).toMap();
- end = temp.constEnd();
- for (it = temp.constBegin(); it != end; ++it) {
- m_argumentDefault.insert(it.key().toInt(), it.value().toString());
- }
-
- return true;
-}
-
-QString SnippetSpec::contents() const
-{
- return m_contents;
-}
-
-QString SnippetSpec::name() const
-{
- return m_name;
-}
-
-QString SnippetSpec::description() const
-{
- return m_description;
-}
-
-QString SnippetSpec::category() const
-{
- return m_category;
-}
-
-QString SnippetSpec::completionShortcut() const
-{
- return m_completionShortcut;
-}
-
-QString SnippetSpec::argumentDescription(int id) const
-{
- return m_argumentDescription.value(id);
-}
-
-QString SnippetSpec::argumentDefault(int id) const
-{
- return m_argumentDefault.value(id);
-}
diff --git a/src/plugins/snippets/snippetspec.h b/src/plugins/snippets/snippetspec.h
deleted file mode 100644
index eac46e34ea..0000000000
--- a/src/plugins/snippets/snippetspec.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#ifndef SNIPPETSPEC_H
-#define SNIPPETSPEC_H
-
-#include <QtCore/QMap>
-#include <QtCore/QString>
-
-namespace Snippets {
-namespace Internal {
-
-class SnippetSpec
-{
-public:
- bool load(const QString &fileName);
-
- QString contents() const;
- QString name() const;
- QString description() const;
- QString category() const;
- QString completionShortcut() const;
- QString argumentDescription(int id) const;
- QString argumentDefault(int id) const;
-
-private:
- QString m_contents;
- QString m_name;
- QString m_description;
- QString m_category;
- QString m_completionShortcut;
- QMap<int, QString> m_argumentDescription;
- QMap<int, QString> m_argumentDefault;
-};
-
-} //namespace Internal
-} //namespace Snippets
-
-#endif // SNIPPETSPEC_H
diff --git a/src/plugins/snippets/snippetsplugin.cpp b/src/plugins/snippets/snippetsplugin.cpp
deleted file mode 100644
index 924e8d8f3b..0000000000
--- a/src/plugins/snippets/snippetsplugin.cpp
+++ /dev/null
@@ -1,126 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#include "snippetswindow.h"
-#include "snippetscompletion.h"
-#include "snippetsplugin.h"
-#include "snippetspec.h"
-
-#include <QtCore/QDebug>
-#include <QtCore/QtPlugin>
-#include <QtGui/QApplication>
-#include <QtGui/QShortcut>
-
-#include <extensionsystem/pluginmanager.h>
-#include <coreplugin/uniqueidmanager.h>
-#include <coreplugin/actionmanager/actionmanager.h>
-#include <coreplugin/editormanager/editormanager.h>
-#include <coreplugin/baseview.h>
-#include <coreplugin/icore.h>
-#include <coreplugin/iview.h>
-#include <texteditor/itexteditable.h>
-#include <texteditor/texteditorconstants.h>
-
-using namespace Snippets::Internal;
-
-SnippetsPlugin *SnippetsPlugin::m_instance = 0;
-
-SnippetsPlugin::SnippetsPlugin()
-{
- m_instance = this;
- m_snippetsCompletion = 0;
-}
-
-SnippetsPlugin::~SnippetsPlugin()
-{
- removeObject(m_snippetsCompletion);
- delete m_snippetsCompletion;
-}
-
-void SnippetsPlugin::extensionsInitialized()
-{
-}
-
-bool SnippetsPlugin::initialize(const QStringList &arguments, QString *)
-{
- Q_UNUSED(arguments)
- Core::ICore *core = Core::ICore::instance();
- Core::ActionManager *am = core->actionManager();
-
- QList<int> context;
- context << core->uniqueIDManager()->uniqueIdentifier(TextEditor::Constants::C_TEXTEDITOR);
-
- m_snippetWnd = new SnippetsWindow();
- Core::BaseView *view = new Core::BaseView;
- view->setUniqueViewName("Snippets");
- view->setWidget(m_snippetWnd);
- view->setContext(QList<int>()
- << core->uniqueIDManager()->uniqueIdentifier(QLatin1String("Snippets Window"))
- << core->uniqueIDManager()->uniqueIdentifier(TextEditor::Constants::C_TEXTEDITOR));
- //view->setDefaultPosition(Qt::RightDockWidgetArea));
- addAutoReleasedObject(view);
- m_snippetsCompletion = new SnippetsCompletion(this);
- addObject(m_snippetsCompletion);
-
- foreach (SnippetSpec *snippet, m_snippetWnd->snippets()) {
- QShortcut *sc = new QShortcut(m_snippetWnd);
- Core::Command *cmd = am->registerShortcut(sc, simplifySnippetName(snippet), context);
- cmd->setCategory(tr("Snippets"));
- connect(sc, SIGNAL(activated()), this, SLOT(snippetActivated()));
- m_shortcuts.insert(sc, snippet);
- }
-
- return true;
-}
-
-QString SnippetsPlugin::simplifySnippetName(SnippetSpec *snippet) const
-{
- return QLatin1String("Snippets.")
- + snippet->category().simplified().replace(QLatin1String(" "), QLatin1String(""))
- + QLatin1Char('.')
- + snippet->name().simplified().replace(QLatin1String(" "), QLatin1String(""));
-}
-
-void SnippetsPlugin::snippetActivated()
-{
- Core::ICore *core = Core::ICore::instance();
- SnippetSpec *snippet = m_shortcuts.value(sender());
- if (snippet && core->editorManager()->currentEditor()) {
- TextEditor::ITextEditable *te =
- qobject_cast<TextEditor::ITextEditable *>(
- core->editorManager()->currentEditor());
- m_snippetWnd->insertSnippet(te, snippet);
- }
-}
-
-Q_EXPORT_PLUGIN(SnippetsPlugin)
diff --git a/src/plugins/snippets/snippetsplugin.h b/src/plugins/snippets/snippetsplugin.h
deleted file mode 100644
index c46a3b39df..0000000000
--- a/src/plugins/snippets/snippetsplugin.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#ifndef SNIPPETS_H
-#define SNIPPETS_H
-
-#include <QtCore/QMap>
-#include <QtCore/QObject>
-#include <QtGui/QShortcut>
-
-#include <extensionsystem/iplugin.h>
-
-namespace Snippets {
-namespace Internal {
-
-class SnippetsWindow;
-class SnippetSpec;
-class SnippetsCompletion;
-
-class SnippetsPlugin : public ExtensionSystem::IPlugin
-{
- Q_OBJECT
-
-public:
- SnippetsPlugin();
- virtual ~SnippetsPlugin();
-
- static SnippetsPlugin *instance() { return m_instance; }
- static SnippetsWindow *snippetsWindow() { return m_instance->m_snippetWnd; }
-
- bool initialize(const QStringList &arguments, QString *errorMessage);
- void extensionsInitialized();
-
-private slots:
- void snippetActivated();
-
-private:
- static SnippetsPlugin *m_instance;
-
- QString simplifySnippetName(SnippetSpec *snippet) const;
- SnippetsCompletion *m_snippetsCompletion;
- SnippetsWindow *m_snippetWnd;
-
- int m_textContext;
- int m_snippetsMode;
- QShortcut *m_exitShortcut;
- QShortcut *m_modeShortcut;
- QMap<QObject*, SnippetSpec*> m_shortcuts;
-};
-
-} // namespace Internal
-} // namespace Snippets
-
-#endif // SNIPPETS_H
diff --git a/src/plugins/snippets/snippetswindow.cpp b/src/plugins/snippets/snippetswindow.cpp
deleted file mode 100644
index d8fccfc428..0000000000
--- a/src/plugins/snippets/snippetswindow.cpp
+++ /dev/null
@@ -1,433 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#include "snippetswindow.h"
-#include "snippetspec.h"
-#include "inputwidget.h"
-#include "snippetsplugin.h"
-
-#include <coreplugin/icore.h>
-#include <coreplugin/editormanager/editormanager.h>
-#include <texteditor/itexteditable.h>
-#include <texteditor/itexteditor.h>
-
-#include <QtCore/QDebug>
-#include <QtCore/QDir>
-#include <QtGui/QDragEnterEvent>
-#include <QtGui/QApplication>
-#include <QtGui/QLabel>
-#include <QtCore/QMimeData>
-#include <QtGui/QHeaderView>
-
-using namespace Snippets::Internal;
-
-const QIcon SnippetsWindow::m_fileIcon = QIcon(":/snippets/images/file.png");
-const QIcon SnippetsWindow::m_dirIcon = QIcon(":/snippets/images/dir.png");
-const QIcon SnippetsWindow::m_dirOpenIcon = QIcon(":/snippets/images/diropen.png");
-
-Q_DECLARE_METATYPE(Snippets::Internal::SnippetSpec *)
-
-SnippetsWindow::SnippetsWindow()
-{
- setWindowTitle(tr("Snippets"));
- setWindowIcon(QIcon(":/snippets/images/snippets.png"));
- setOrientation(Qt::Vertical);
-
- m_snippetsTree = new SnippetsTree(this);
- addWidget(m_snippetsTree);
-
- m_descLabel = new QLabel(this);
- m_descLabel->setAlignment(Qt::AlignTop|Qt::AlignLeft);
- m_descLabel->setFrameShape(QFrame::Panel);
- m_descLabel->setFrameShadow(QFrame::Raised);
- m_descLabel->setWordWrap(true);
- addWidget(m_descLabel);
-
- m_snippetsDir = QDir::home();
- if (!initSnippetsDir())
- setDisabled(true);
- else {
- QDir defaultDir(Core::ICore::instance()->resourcePath() + QLatin1String("/snippets"));
- if (defaultDir.exists())
- initSnippets(defaultDir);
- initSnippets(m_snippetsDir);
- }
-
- connect(m_snippetsTree, SIGNAL(itemCollapsed(QTreeWidgetItem *)),
- this, SLOT(setClosedIcon(QTreeWidgetItem *)));
-
- connect(m_snippetsTree, SIGNAL(itemExpanded(QTreeWidgetItem *)),
- this, SLOT(setOpenIcon(QTreeWidgetItem *)));
-
- connect(m_snippetsTree, SIGNAL(itemActivated(QTreeWidgetItem *, int)),
- this, SLOT(activateSnippet(QTreeWidgetItem *, int)));
-
- connect(m_snippetsTree, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
- this, SLOT(updateDescription(QTreeWidgetItem *)));
-}
-
-SnippetsWindow::~SnippetsWindow()
-{
- qDeleteAll(m_snippets);
-}
-
-
-void SnippetsWindow::activateSnippet(QTreeWidgetItem *item, int column)
-{
- if (!item->parent())
- return;
-
- TextEditor::ITextEditable *editor = 0;
- if (Core::ICore::instance()->editorManager()->currentEditor())
- editor = qobject_cast<TextEditor::ITextEditable *>(
- Core::ICore::instance()->editorManager()->currentEditor());
- if (editor) {
- SnippetSpec* spec = qVariantValue<SnippetSpec*>(item->data(0, Qt::UserRole));
- insertSnippet(editor, spec);
- }
-
- Q_UNUSED(column)
-}
-
-const QList<SnippetSpec *> &SnippetsWindow::snippets() const
-{
- return m_snippets;
-}
-
-void SnippetsWindow::initSnippets(const QDir &dir)
-{
- QString name;
- QString category;
-
- QMap<QString, QTreeWidgetItem *> categories;
- for (int i = 0; i < m_snippetsTree->topLevelItemCount(); ++i) {
- categories.insert(m_snippetsTree->topLevelItem(i)->text(0),
- m_snippetsTree->topLevelItem(i));
- }
-
- foreach (const QString &snippet, dir.entryList(QStringList("*.snp"))) {
- SnippetSpec *spec = new SnippetSpec();
- if (spec->load(dir.filePath(snippet))) {
- if (!categories.contains(spec->category())) {
- QTreeWidgetItem *citem = new QTreeWidgetItem(m_snippetsTree);
- citem->setText(0, spec->category());
- citem->setIcon(0, m_dirIcon);
- categories.insert(spec->category(), citem);
- }
-
- QTreeWidgetItem *item = new QTreeWidgetItem(
- categories.value(spec->category()));
- item->setText(0, spec->name());
- item->setIcon(0, m_fileIcon);
- QVariant v;
- qVariantSetValue<SnippetSpec *>(v, spec);
- item->setData(0, Qt::UserRole, v);
-
- m_snippets.append(spec);
- }
- }
-}
-
-QString SnippetsWindow::createUniqueFileName()
-{
- int fileNumber = 0;
- QString baseName = "snippet";
- while (m_snippetsDir.exists(baseName + QString::number(fileNumber) + ".snp")) {
- ++fileNumber;
- }
- return baseName + QString::number(fileNumber) + ".snp";
-}
-
-void SnippetsWindow::writeSnippet(const QMimeData *)
-{
-}
-
-bool SnippetsWindow::initSnippetsDir()
-{
- if (!m_snippetsDir.exists(".qworkbench"))
- m_snippetsDir.mkdir(".qworkbench");
- if (!m_snippetsDir.cd(".qworkbench"))
- return false;
-
- if (!m_snippetsDir.exists("snippets"))
- m_snippetsDir.mkdir("snippets");
- return m_snippetsDir.cd("snippets");
-}
-
-void SnippetsWindow::getArguments()
-{
- QString contents = m_currentSnippet->contents();
- int index = 0;
- bool pc = false;
- QString nrstr;
-
- QSet<int> requiredArgs;
- m_requiredArgs.clear();
- m_args.clear();
-
- while (index < contents.length()) {
- QChar c = contents.at(index);
- if (c == QLatin1Char('%')) {
- pc = !pc;
- } else if (pc) {
- if (c.isNumber()) {
- nrstr += c;
- } else {
- pc = false;
- }
- }
-
- if (!pc && !nrstr.isEmpty()) {
- requiredArgs << nrstr.toInt();
- nrstr.clear();
- }
-
- ++index;
- }
-
- m_requiredArgs = requiredArgs.toList();
- m_requiredArgs.prepend(-1);
-
- showInputWidget(false, QString());
-}
-
-void SnippetsWindow::showInputWidget(bool canceled, const QString &value)
-{
- if (canceled)
- return;
-
- TextEditor::ITextEditor *te = 0;
- if (Core::ICore::instance()->editorManager()->currentEditor())
- te = qobject_cast<TextEditor::ITextEditor*>(
- Core::ICore::instance()->editorManager()->currentEditor());
-
- int arg = m_requiredArgs.takeFirst();
- if (arg != -1)
- m_args << value;
-
- if (!te || m_requiredArgs.isEmpty()) {
- qDebug("replaceAndInsert");
- replaceAndInsert();
- } else {
- QString desc = m_currentSnippet->argumentDescription(m_requiredArgs.first());
- QString def = m_currentSnippet->argumentDefault(m_requiredArgs.first());
- foreach (const QString &arg, m_args) {
- desc = desc.arg(arg);
- def = def.arg(arg);
- }
-
- InputWidget *iw = new InputWidget(desc, def);
- connect(iw, SIGNAL(finished(bool, const QString &)),
- this, SLOT(showInputWidget(bool, const QString &)));
- iw->showInputWidget(te->cursorRect().bottomRight());
- }
-}
-
-void SnippetsWindow::replaceAndInsert()
-{
- QString result;
- QString keyWord;
- int setAnchor = -1;
- int setCursor = -1;
- int selLength = 0;
-
- //clean up selection
- int startPos = m_currentEditor->position(TextEditor::ITextEditable::Anchor);
- int endPos = m_currentEditor->position();
-
- if (startPos < 0) {
- startPos = endPos;
- } else {
- if (startPos > endPos) {
- int tmp = startPos;
- startPos = endPos;
- endPos = tmp;
- }
- selLength = endPos - startPos;
- }
-
- //parse the contents
- m_currentEditor->setCurPos(startPos);
- QString editorIndent = getCurrentIndent(m_currentEditor);
- QString content = m_currentSnippet->contents();
- foreach (const QString &arg, m_args) {
- content = content.arg(arg);
- }
-
- int startOfKey = -1;
- for (int i = 0; i<content.length(); ++i) {
- //handle windows,mac and linux new lines...
- if (content.at(i) == QLatin1Char('\n')) {
- if ((i <= 0) || content.at(i-1) != QLatin1Char('\r'))
- result += QLatin1Char('\n') + editorIndent;
- continue;
- } else if (content.at(i) == QLatin1Char('\r')) {
- result += QLatin1Char('\n') + editorIndent;
- continue;
- }
-
- if (content.at(i) == QChar('$')) {
- if (startOfKey != -1) {
- m_currentEditor->insert(result);
- if (keyWord == QLatin1String("selection")) {
- const QString &indent = indentOfString(content, i);
- int selStartPos = m_currentEditor->position();
- m_currentEditor->setCurPos(selStartPos + selLength);
- insertIdents(m_currentEditor, indent, selStartPos, m_currentEditor->position());
- } else if (keyWord == QLatin1String("anchor")) {
- setAnchor = m_currentEditor->position();
- } else if (keyWord == QLatin1String("cursor")) {
- setCursor = m_currentEditor->position();
- }
- result.clear();
- keyWord.clear();
- startOfKey = -1;
- } else {
- startOfKey = i;
- }
- } else {
- if (startOfKey != -1)
- keyWord += content.at(i).toLower();
- else
- result += content.at(i);
- }
- }
-
- m_currentEditor->insert(result);
-
- if (setAnchor != -1) {
- m_currentEditor->setCurPos(setAnchor);
- m_currentEditor->select(setCursor);
- } else if (setCursor != -1) {
- m_currentEditor->setCurPos(setCursor);
- }
-}
-
-void SnippetsWindow::insertSnippet(TextEditor::ITextEditable *editor, SnippetSpec *snippet)
-{
- m_currentEditor = editor;
- m_currentSnippet = snippet;
- getArguments();
-}
-
-QString SnippetsWindow::getCurrentIndent(TextEditor::ITextEditor *editor)
-{
- const int startPos = editor->position(TextEditor::ITextEditor::StartOfLine);
- const int endPos = editor->position(TextEditor::ITextEditor::EndOfLine);
- if (startPos < endPos)
- return indentOfString(editor->textAt(startPos, endPos - startPos));
- return QString();
-}
-
-void SnippetsWindow::insertIdents(TextEditor::ITextEditable *editor,
- const QString &indent, int fromPos, int toPos)
-{
- int offset = 0;
- const int startPos = editor->position();
- editor->setCurPos(toPos);
- int currentLinePos = editor->position(TextEditor::ITextEditor::StartOfLine);
- while (currentLinePos > fromPos) {
- editor->setCurPos(currentLinePos);
- editor->insert(indent);
- offset += indent.length();
- editor->setCurPos(currentLinePos-1);
- currentLinePos = editor->position(TextEditor::ITextEditor::StartOfLine);
- }
- editor->setCurPos(startPos + offset);
-}
-
-QString SnippetsWindow::indentOfString(const QString &str, int at)
-{
- QString result;
- int startAt = at;
- if (startAt < 0)
- startAt = str.length() - 1;
-
- // find start position
- while (startAt >= 0 && str.at(startAt) != QChar('\n')
- && str.at(startAt) != QChar('\r')) --startAt;
-
- for (int i = (startAt + 1); i < str.length(); ++i) {
- if (str.at(i) == QChar(' ') || str.at(i) == QChar('\t'))
- result += str.at(i);
- else
- break;
- }
-
- return result;
-}
-
-void SnippetsWindow::setOpenIcon(QTreeWidgetItem *item)
-{
- item->setIcon(0, m_dirOpenIcon);
-}
-
-void SnippetsWindow::setClosedIcon(QTreeWidgetItem *item)
-{
- item->setIcon(0, m_dirIcon);
-}
-
-void SnippetsWindow::updateDescription(QTreeWidgetItem *item)
-{
- const SnippetSpec* spec = qVariantValue<SnippetSpec*>(item->data(0, Qt::UserRole));
- if (spec) {
- m_descLabel->setText(QLatin1String("<b>") + spec->name() + QLatin1String("</b><br>")
- + spec->description());
- } else {
- m_descLabel->setText(QLatin1String("<b>") + item->text(0) + QLatin1String("</b><br>"));
- }
-}
-
-SnippetsTree::SnippetsTree(QWidget *parent)
- : QTreeWidget(parent)
-{
- setColumnCount(1);
- header()->setVisible(false);
- setAlternatingRowColors(true);
- setAcceptDrops(true);
-}
-
-void SnippetsTree::dropEvent(QDropEvent *)
-{
- //writeSnippet(event->mimeData());
-}
-
-void SnippetsTree::dragEnterEvent(QDragEnterEvent *event)
-{
- if (event->mimeData()->hasText())
- event->acceptProposedAction();
-}
-
-void SnippetsTree::dragMoveEvent(QDragMoveEvent *)
-{
-}
diff --git a/src/plugins/snippets/snippetswindow.h b/src/plugins/snippets/snippetswindow.h
deleted file mode 100644
index 3903ddde05..0000000000
--- a/src/plugins/snippets/snippetswindow.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#ifndef SNIPPETSWINDOW_H
-#define SNIPPETSWINDOW_H
-
-#include <QtCore/QDir>
-#include <QtGui/QTreeWidget>
-#include <QtGui/QSplitter>
-#include <QtGui/QIcon>
-
-QT_BEGIN_NAMESPACE
-class QDir;
-class QLabel;
-QT_END_NAMESPACE
-
-namespace TextEditor {
-class ITextEditable;
-class ITextEditor;
-}
-
-namespace Snippets {
-namespace Internal {
-
-class SnippetSpec;
-class SnippetsTree;
-class InputWidget;
-
-class SnippetsWindow : public QSplitter
-{
- Q_OBJECT
-
-public:
- SnippetsWindow();
- ~SnippetsWindow();
- const QList<SnippetSpec *> &snippets() const;
- void insertSnippet(TextEditor::ITextEditable *editor, SnippetSpec *snippet);
-
-private slots:
- void updateDescription(QTreeWidgetItem *item);
- void activateSnippet(QTreeWidgetItem *item, int column);
- void setOpenIcon(QTreeWidgetItem *item);
- void setClosedIcon(QTreeWidgetItem *item);
-
- void showInputWidget(bool canceled, const QString &value);
-
-private:
- void getArguments();
- void replaceAndInsert();
- QString indentOfString(const QString &str, int at = -1);
- void insertIdents(TextEditor::ITextEditable *editor,
- const QString &indent, int fromPos, int toPos);
- QString getCurrentIndent(TextEditor::ITextEditor *editor);
-
- QList<SnippetSpec *> m_snippets;
- QString createUniqueFileName();
- void writeSnippet(const QMimeData *mData);
- bool initSnippetsDir();
- void initSnippets(const QDir &dir);
-
- QList<int> m_requiredArgs;
- QStringList m_args;
- SnippetSpec *m_currentSnippet;
- TextEditor::ITextEditable *m_currentEditor;
-
- QDir m_snippetsDir;
-
- SnippetsTree *m_snippetsTree;
-
- QLabel *m_descLabel;
-
- static const QIcon m_fileIcon;
- static const QIcon m_dirIcon;
- static const QIcon m_dirOpenIcon;
-};
-
-class SnippetsTree : public QTreeWidget
-{
- Q_OBJECT
-
-public:
- SnippetsTree(QWidget *parent);
-
-protected:
- void dragMoveEvent(QDragMoveEvent * event);
- void dragEnterEvent(QDragEnterEvent *event);
- void dropEvent(QDropEvent *event);
-};
-
-} // namespace Internal
-} // namespace Snippets
-
-#endif // SNIPPETSWINDOW_H
-
diff --git a/src/plugins/subversion/Subversion.pluginspec b/src/plugins/subversion/Subversion.pluginspec
deleted file mode 100644
index 855fd92668..0000000000
--- a/src/plugins/subversion/Subversion.pluginspec
+++ /dev/null
@@ -1,22 +0,0 @@
-<plugin name="Subversion" version="2.0.95" compatVersion="2.0.95">
- <vendor>Nokia Corporation</vendor>
- <copyright>(C) 2010 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>
- <category>Version Control</category>
- <description>Subversion integration.</description>
- <url>http://qt.nokia.com</url>
- <dependencyList>
- <dependency name="TextEditor" version="2.0.95"/>
- <dependency name="ProjectExplorer" version="2.0.95"/>
- <dependency name="Core" version="2.0.95"/>
- <dependency name="VCSBase" version="2.0.95"/>
- </dependencyList>
-</plugin>
diff --git a/src/plugins/subversion/Subversion.pluginspec.in b/src/plugins/subversion/Subversion.pluginspec.in
new file mode 100644
index 0000000000..8058678064
--- /dev/null
+++ b/src/plugins/subversion/Subversion.pluginspec.in
@@ -0,0 +1,22 @@
+<plugin name=\"Subversion\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2010 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>
+ <category>Version Control</category>
+ <description>Subversion integration.</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name=\"TextEditor\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"ProjectExplorer\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"VCSBase\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/subversion/settingspage.cpp b/src/plugins/subversion/settingspage.cpp
index 67624b20d7..4378d93436 100644
--- a/src/plugins/subversion/settingspage.cpp
+++ b/src/plugins/subversion/settingspage.cpp
@@ -86,11 +86,19 @@ void SettingsPageWidget::setSettings(const SubversionSettings &s)
QString SettingsPageWidget::searchKeywords() const
{
QString rc;
- QTextStream(&rc) << m_ui.commandLabel->text()
- << ' ' << m_ui.usernameLabel->text()
- << ' ' << m_ui.passwordLabel->text()
- << ' ' << m_ui.userGroupBox->title()
- << ' ' << m_ui.spaceIgnorantAnnotationCheckBox->text();
+ QLatin1Char sep(' ');
+ QTextStream(&rc)
+ << sep << m_ui.generalGroupBox->title()
+ << sep << m_ui.commandLabel->text()
+ << sep << m_ui.userGroupBox->title()
+ << sep << m_ui.usernameLabel->text()
+ << sep << m_ui.passwordLabel->text()
+ << sep << m_ui.miscGroupBox->title()
+ << sep << m_ui.logCountLabel->text()
+ << sep << m_ui.timeOutLabel->text()
+ << sep << m_ui.promptToSubmitCheckBox->text()
+ << sep << m_ui.spaceIgnorantAnnotationCheckBox->text()
+ ;
rc.remove(QLatin1Char('&'));
return rc;
}
diff --git a/src/plugins/subversion/subversion.pro b/src/plugins/subversion/subversion.pro
index 3879d42568..6a46a3679a 100644
--- a/src/plugins/subversion/subversion.pro
+++ b/src/plugins/subversion/subversion.pro
@@ -31,5 +31,3 @@ SOURCES += annotationhighlighter.cpp \
FORMS += settingspage.ui
RESOURCES += subversion.qrc
-
-OTHER_FILES += Subversion.pluginspec
diff --git a/src/plugins/subversion/subversionplugin.cpp b/src/plugins/subversion/subversionplugin.cpp
index 7d24481ec7..f0b3813fdf 100644
--- a/src/plugins/subversion/subversionplugin.cpp
+++ b/src/plugins/subversion/subversionplugin.cpp
@@ -56,6 +56,7 @@
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/command.h>
+#include <coreplugin/uniqueidmanager.h>
#include <coreplugin/editormanager/editormanager.h>
#include <locator/commandlocator.h>
@@ -553,7 +554,7 @@ void SubversionPlugin::svnDiff(const QString &workingDir, const QStringList &fil
args << files;
const SubversionResponse response =
- runSvn(workingDir, args, m_settings.timeOutMS(), 0);
+ runSvn(workingDir, args, m_settings.timeOutMS(), 0, codec);
if (response.error)
return;
@@ -845,7 +846,6 @@ void SubversionPlugin::filelog(const QString &workingDir,
const QStringList &files,
bool enableAnnotationContextMenu)
{
- QTextCodec *codec = VCSBase::VCSBaseEditor::getCodec(workingDir, files);
// no need for temp file
QStringList args(QLatin1String("log"));
if (m_settings.logCount > 0)
@@ -853,9 +853,11 @@ void SubversionPlugin::filelog(const QString &workingDir,
foreach(const QString &file, files)
args.append(QDir::toNativeSeparators(file));
+ // subversion stores log in UTF-8 and returns it back in user system locale.
+ // So we do not need to encode it.
const SubversionResponse response =
runSvn(workingDir, args, m_settings.timeOutMS(),
- SshPasswordPrompt, codec);
+ SshPasswordPrompt, 0/*codec*/);
if (response.error)
return;
@@ -869,7 +871,7 @@ void SubversionPlugin::filelog(const QString &workingDir,
} else {
const QString title = QString::fromLatin1("svn log %1").arg(id);
const QString source = VCSBase::VCSBaseEditor::getSource(workingDir, files);
- Core::IEditor *newEditor = showOutputInEditor(title, response.stdOut, VCSBase::LogOutput, source, codec);
+ Core::IEditor *newEditor = showOutputInEditor(title, response.stdOut, VCSBase::LogOutput, source, /*codec*/0);
newEditor->setProperty("logFileName", id);
if (enableAnnotationContextMenu)
VCSBase::VCSBaseEditor::getVcsBaseEditor(newEditor)->setFileLogAnnotateEnabled(true);
@@ -915,7 +917,8 @@ void SubversionPlugin::vcsAnnotate(const QString &workingDir, const QString &fil
const QString &revision /* = QString() */,
int lineNumber /* = -1 */)
{
- QTextCodec *codec = VCSBase::VCSBaseEditor::getCodec(file);
+ const QString source = VCSBase::VCSBaseEditor::getSource(workingDir, file);
+ QTextCodec *codec = VCSBase::VCSBaseEditor::getCodec(source);
QStringList args(QLatin1String("annotate"));
if (m_settings.spaceIgnorantAnnotation)
@@ -927,13 +930,12 @@ void SubversionPlugin::vcsAnnotate(const QString &workingDir, const QString &fil
const SubversionResponse response =
runSvn(workingDir, args, m_settings.timeOutMS(),
- SshPasswordPrompt, codec);
+ SshPasswordPrompt|ForceCLocale, codec);
if (response.error)
return;
// Re-use an existing view if possible to support
// the common usage pattern of continuously changing and diffing a file
- const QString source = workingDir + QLatin1Char('/') + file;
if (lineNumber <= 0)
lineNumber = VCSBase::VCSBaseEditor::lineNumberOfCurrentEditor(source);
// Determine id
@@ -1221,11 +1223,9 @@ bool SubversionPlugin::vcsMove(const QString &workingDir, const QString &from, c
{
QStringList args(QLatin1String("move"));
args << QDir::toNativeSeparators(from) << QDir::toNativeSeparators(to);
- qDebug()<<args;
const SubversionResponse response =
runSvn(workingDir, args, m_settings.timeOutMS(),
- SshPasswordPrompt|ShowStdOutInLogWindow);
- qDebug() << response.stdOut << "\n"<<response.stdErr;
+ SshPasswordPrompt|ShowStdOutInLogWindow|FullySynchronously);
return !response.error;
}
diff --git a/src/plugins/tasklist/TaskList.pluginspec b/src/plugins/tasklist/TaskList.pluginspec
deleted file mode 100644
index eb40c9564b..0000000000
--- a/src/plugins/tasklist/TaskList.pluginspec
+++ /dev/null
@@ -1,19 +0,0 @@
-<plugin name="TaskList" version="2.0.95" compatVersion="2.0.95">
- <vendor>Nokia Corporation</vendor>
- <copyright>(C) 2010 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>Use .tasks-files to populate the build issues view.</description>
- <url>http://qt.nokia.com</url>
- <dependencyList>
- <dependency name="Core" version="2.0.95"/>
- <dependency name="ProjectExplorer" version="2.0.95"/>
- </dependencyList>
-</plugin>
diff --git a/src/plugins/tasklist/TaskList.pluginspec.in b/src/plugins/tasklist/TaskList.pluginspec.in
new file mode 100644
index 0000000000..c266cc3a48
--- /dev/null
+++ b/src/plugins/tasklist/TaskList.pluginspec.in
@@ -0,0 +1,19 @@
+<plugin name=\"TaskList\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2010 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>Use .tasks-files to populate the build issues view.</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"ProjectExplorer\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/tasklist/tasklist.pro b/src/plugins/tasklist/tasklist.pro
index 388800a000..9c35d6aea9 100644
--- a/src/plugins/tasklist/tasklist.pro
+++ b/src/plugins/tasklist/tasklist.pro
@@ -19,5 +19,4 @@ SOURCES += tasklistplugin.cpp \
RESOURCES += tasklist.qrc
-OTHER_FILES += TaskList.pluginspec \
- TaskList.mimetypes.xml
+OTHER_FILES += TaskList.mimetypes.xml
diff --git a/src/plugins/tasklist/tasklistplugin.cpp b/src/plugins/tasklist/tasklistplugin.cpp
index 5acfb2471e..345cf1a693 100644
--- a/src/plugins/tasklist/tasklistplugin.cpp
+++ b/src/plugins/tasklist/tasklistplugin.cpp
@@ -45,6 +45,7 @@
#include <projectexplorer/task.h>
#include <projectexplorer/taskhub.h>
+#include <QtCore/QDir>
#include <QtCore/QStringList>
#include <QtCore/QtPlugin>
@@ -109,6 +110,7 @@ public:
description = chunks.at(3);
}
if (!file.isEmpty()) {
+ file = QDir::fromNativeSeparators(file);
QFileInfo fi(file);
if (fi.isRelative() && context) {
QString fullPath = context->projectDirectory() + '/' + file;
diff --git a/src/plugins/texteditor/TextEditor.pluginspec b/src/plugins/texteditor/TextEditor.pluginspec
deleted file mode 100644
index bb08f9aa2c..0000000000
--- a/src/plugins/texteditor/TextEditor.pluginspec
+++ /dev/null
@@ -1,21 +0,0 @@
-<plugin name="TextEditor" version="2.0.95" compatVersion="2.0.95">
- <vendor>Nokia Corporation</vendor>
- <copyright>(C) 2010 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>
- <category>Qt Creator</category>
- <description>Text editor framework and the implementation of the basic text editor.</description>
- <url>http://qt.nokia.com</url>
- <dependencyList>
- <dependency name="Core" version="2.0.95"/>
- <dependency name="Find" version="2.0.95"/>
- <dependency name="Locator" version="2.0.95"/>
- </dependencyList>
-</plugin>
diff --git a/src/plugins/texteditor/TextEditor.pluginspec.in b/src/plugins/texteditor/TextEditor.pluginspec.in
new file mode 100644
index 0000000000..5f5bb70103
--- /dev/null
+++ b/src/plugins/texteditor/TextEditor.pluginspec.in
@@ -0,0 +1,21 @@
+<plugin name=\"TextEditor\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2010 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>
+ <category>Qt Creator</category>
+ <description>Text editor framework and the implementation of the basic text editor.</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"Find\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"Locator\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/texteditor/autocompleter.cpp b/src/plugins/texteditor/autocompleter.cpp
new file mode 100644
index 0000000000..538cb9f5e5
--- /dev/null
+++ b/src/plugins/texteditor/autocompleter.cpp
@@ -0,0 +1,348 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "autocompleter.h"
+#include "basetextdocumentlayout.h"
+#include "texteditorsettings.h"
+#include "tabsettings.h"
+
+#include <QtCore/QDebug>
+#include <QtGui/QTextCursor>
+
+using namespace TextEditor;
+
+AutoCompleter::AutoCompleter() :
+ m_allowSkippingOfBlockEnd(false),
+ m_surroundWithEnabled(true),
+ m_autoParenthesesEnabled(true)
+{}
+
+AutoCompleter::~AutoCompleter()
+{}
+
+void AutoCompleter::setAutoParenthesesEnabled(bool b)
+{
+ m_autoParenthesesEnabled = b;
+}
+
+bool AutoCompleter::isAutoParenthesesEnabled() const
+{
+ return m_autoParenthesesEnabled;
+}
+
+void AutoCompleter::setSurroundWithEnabled(bool b)
+{
+ m_surroundWithEnabled = b;
+}
+
+bool AutoCompleter::isSurroundWithEnabled() const
+{
+ return m_surroundWithEnabled;
+}
+
+void AutoCompleter::countBracket(QChar open, QChar close, QChar c, int *errors, int *stillopen)
+{
+ if (c == open)
+ ++*stillopen;
+ else if (c == close)
+ --*stillopen;
+
+ if (*stillopen < 0) {
+ *errors += -1 * (*stillopen);
+ *stillopen = 0;
+ }
+}
+
+void AutoCompleter::countBrackets(QTextCursor cursor,
+ int from,
+ int end,
+ QChar open,
+ QChar close,
+ int *errors,
+ int *stillopen)
+{
+ cursor.setPosition(from);
+ QTextBlock block = cursor.block();
+ while (block.isValid() && block.position() < end) {
+ TextEditor::Parentheses parenList = TextEditor::BaseTextDocumentLayout::parentheses(block);
+ if (!parenList.isEmpty() && !TextEditor::BaseTextDocumentLayout::ifdefedOut(block)) {
+ for (int i = 0; i < parenList.count(); ++i) {
+ TextEditor::Parenthesis paren = parenList.at(i);
+ int position = block.position() + paren.pos;
+ if (position < from || position >= end)
+ continue;
+ countBracket(open, close, paren.chr, errors, stillopen);
+ }
+ }
+ block = block.next();
+ }
+}
+
+QString AutoCompleter::autoComplete(QTextCursor &cursor, const QString &textToInsert) const
+{
+ const bool checkBlockEnd = m_allowSkippingOfBlockEnd;
+ m_allowSkippingOfBlockEnd = false; // consume blockEnd.
+
+ if (m_surroundWithEnabled && cursor.hasSelection()) {
+ if (textToInsert == QLatin1String("("))
+ return cursor.selectedText() + QLatin1String(")");
+ if (textToInsert == QLatin1String("{")) {
+ //If the text span multiple lines, insert on different lines
+ QString str = cursor.selectedText();
+ if (str.contains(QChar::ParagraphSeparator)) {
+ //Also, try to simulate auto-indent
+ str = (str.startsWith(QChar::ParagraphSeparator) ? QString() : QString(QChar::ParagraphSeparator)) +
+ str;
+ if (str.endsWith(QChar::ParagraphSeparator))
+ str += QLatin1String("}") + QString(QChar::ParagraphSeparator);
+ else
+ str += QString(QChar::ParagraphSeparator) + QLatin1String("}");
+ }
+ else {
+ str += QLatin1String("}");
+ }
+ return str;
+ }
+ if (textToInsert == QLatin1String("["))
+ return cursor.selectedText() + QLatin1String("]");
+ if (textToInsert == QLatin1String("\""))
+ return cursor.selectedText() + QLatin1String("\"");
+ if (textToInsert == QLatin1String("'"))
+ return cursor.selectedText() + QLatin1String("'");
+ }
+
+ if (!m_autoParenthesesEnabled)
+ return QString();
+
+ if (!contextAllowsAutoParentheses(cursor, textToInsert))
+ return QString();
+
+ QTextDocument *doc = cursor.document();
+ const QString text = textToInsert;
+ const QChar lookAhead = doc->characterAt(cursor.selectionEnd());
+
+ const QChar character = textToInsert.at(0);
+ const QString parentheses = QLatin1String("()");
+ const QString brackets = QLatin1String("[]");
+ if (parentheses.contains(character) || brackets.contains(character)) {
+ QTextCursor tmp= cursor;
+ bool foundBlockStart = TextEditor::TextBlockUserData::findPreviousBlockOpenParenthesis(&tmp);
+ int blockStart = foundBlockStart ? tmp.position() : 0;
+ tmp = cursor;
+ bool foundBlockEnd = TextEditor::TextBlockUserData::findNextBlockClosingParenthesis(&tmp);
+ int blockEnd = foundBlockEnd ? tmp.position() : (cursor.document()->characterCount() - 1);
+ const QChar openChar = parentheses.contains(character) ? QLatin1Char('(') : QLatin1Char('[');
+ const QChar closeChar = parentheses.contains(character) ? QLatin1Char(')') : QLatin1Char(']');
+
+ int errors = 0;
+ int stillopen = 0;
+ countBrackets(cursor, blockStart, blockEnd, openChar, closeChar, &errors, &stillopen);
+ int errorsBeforeInsertion = errors + stillopen;
+ errors = 0;
+ stillopen = 0;
+ countBrackets(cursor, blockStart, cursor.position(), openChar, closeChar, &errors, &stillopen);
+ countBracket(openChar, closeChar, character, &errors, &stillopen);
+ countBrackets(cursor, cursor.position(), blockEnd, openChar, closeChar, &errors, &stillopen);
+ int errorsAfterInsertion = errors + stillopen;
+ if (errorsAfterInsertion < errorsBeforeInsertion)
+ return QString(); // insertion fixes parentheses or bracket errors, do not auto complete
+ }
+
+ int skippedChars = 0;
+ const QString autoText = insertMatchingBrace(cursor, text, lookAhead, &skippedChars);
+
+ if (checkBlockEnd && textToInsert.at(0) == QLatin1Char('}')) {
+ if (textToInsert.length() > 1)
+ qWarning() << "*** handle event compression";
+
+ int startPos = cursor.selectionEnd(), pos = startPos;
+ while (doc->characterAt(pos).isSpace())
+ ++pos;
+
+ if (doc->characterAt(pos) == QLatin1Char('}'))
+ skippedChars += (pos - startPos) + 1;
+ }
+
+ if (skippedChars) {
+ const int pos = cursor.position();
+ cursor.setPosition(pos + skippedChars);
+ cursor.setPosition(pos, QTextCursor::KeepAnchor);
+ }
+
+ return autoText;
+}
+
+bool AutoCompleter::autoBackspace(QTextCursor &cursor)
+{
+ m_allowSkippingOfBlockEnd = false;
+
+ if (!m_autoParenthesesEnabled)
+ return false;
+
+ int pos = cursor.position();
+ if (pos == 0)
+ return false;
+ QTextCursor c = cursor;
+ c.setPosition(pos - 1);
+
+ QTextDocument *doc = cursor.document();
+ const QChar lookAhead = doc->characterAt(pos);
+ const QChar lookBehind = doc->characterAt(pos - 1);
+ const QChar lookFurtherBehind = doc->characterAt(pos - 2);
+
+ const QChar character = lookBehind;
+ if (character == QLatin1Char('(') || character == QLatin1Char('[')) {
+ QTextCursor tmp = cursor;
+ TextEditor::TextBlockUserData::findPreviousBlockOpenParenthesis(&tmp);
+ int blockStart = tmp.isNull() ? 0 : tmp.position();
+ tmp = cursor;
+ TextEditor::TextBlockUserData::findNextBlockClosingParenthesis(&tmp);
+ int blockEnd = tmp.isNull() ? (cursor.document()->characterCount()-1) : tmp.position();
+ QChar openChar = character;
+ QChar closeChar = (character == QLatin1Char('(')) ? QLatin1Char(')') : QLatin1Char(']');
+
+ int errors = 0;
+ int stillopen = 0;
+ countBrackets(cursor, blockStart, blockEnd, openChar, closeChar, &errors, &stillopen);
+ int errorsBeforeDeletion = errors + stillopen;
+ errors = 0;
+ stillopen = 0;
+ countBrackets(cursor, blockStart, pos - 1, openChar, closeChar, &errors, &stillopen);
+ countBrackets(cursor, pos, blockEnd, openChar, closeChar, &errors, &stillopen);
+ int errorsAfterDeletion = errors + stillopen;
+
+ if (errorsAfterDeletion < errorsBeforeDeletion)
+ return false; // insertion fixes parentheses or bracket errors, do not auto complete
+ }
+
+ // ### this code needs to be generalized
+ if ((lookBehind == QLatin1Char('(') && lookAhead == QLatin1Char(')'))
+ || (lookBehind == QLatin1Char('[') && lookAhead == QLatin1Char(']'))
+ || (lookBehind == QLatin1Char('"') && lookAhead == QLatin1Char('"')
+ && lookFurtherBehind != QLatin1Char('\\'))
+ || (lookBehind == QLatin1Char('\'') && lookAhead == QLatin1Char('\'')
+ && lookFurtherBehind != QLatin1Char('\\'))) {
+ if (! isInComment(c)) {
+ cursor.beginEditBlock();
+ cursor.deleteChar();
+ cursor.deletePreviousChar();
+ cursor.endEditBlock();
+ return true;
+ }
+ }
+ return false;
+}
+
+int AutoCompleter::paragraphSeparatorAboutToBeInserted(QTextCursor &cursor)
+{
+ if (!m_autoParenthesesEnabled)
+ return 0;
+
+ QTextDocument *doc = cursor.document();
+ if (doc->characterAt(cursor.position() - 1) != QLatin1Char('{'))
+ return 0;
+
+ if (!contextAllowsAutoParentheses(cursor))
+ return 0;
+
+ // verify that we indeed do have an extra opening brace in the document
+ int braceDepth = BaseTextDocumentLayout::braceDepth(doc->lastBlock());
+
+ if (braceDepth <= 0)
+ return 0; // braces are all balanced or worse, no need to do anything
+
+ // we have an extra brace , let's see if we should close it
+
+ /* verify that the next block is not further intended compared to the current block.
+ This covers the following case:
+
+ if (condition) {|
+ statement;
+ */
+ const TabSettings &ts = TextEditorSettings::instance()->tabSettings();
+ QTextBlock block = cursor.block();
+ int indentation = ts.indentationColumn(block.text());
+
+ if (block.next().isValid()) { // not the last block
+ block = block.next();
+ //skip all empty blocks
+ while (block.isValid() && ts.onlySpace(block.text()))
+ block = block.next();
+ if (block.isValid()
+ && ts.indentationColumn(block.text()) > indentation)
+ return 0;
+ }
+
+ const QString &textToInsert = insertParagraphSeparator(cursor);
+ int pos = cursor.position();
+ cursor.insertBlock();
+ cursor.insertText(textToInsert);
+ cursor.setPosition(pos);
+
+ m_allowSkippingOfBlockEnd = true;
+
+ return 1;
+}
+
+bool AutoCompleter::contextAllowsAutoParentheses(const QTextCursor &cursor,
+ const QString &textToInsert) const
+{
+ Q_UNUSED(cursor);
+ Q_UNUSED(textToInsert);
+ return false;
+}
+
+bool AutoCompleter::contextAllowsElectricCharacters(const QTextCursor &cursor) const
+{
+ return contextAllowsAutoParentheses(cursor);
+}
+
+bool AutoCompleter::isInComment(const QTextCursor &cursor) const
+{
+ Q_UNUSED(cursor);
+ return false;
+}
+
+QString AutoCompleter::insertMatchingBrace(const QTextCursor &cursor,
+ const QString &text,
+ QChar la,
+ int *skippedChars) const
+{
+ Q_UNUSED(cursor);
+ Q_UNUSED(text);
+ Q_UNUSED(la);
+ Q_UNUSED(skippedChars);
+ return QString();
+}
+
+QString AutoCompleter::insertParagraphSeparator(const QTextCursor &cursor) const
+{
+ Q_UNUSED(cursor);
+ return QString();
+}
diff --git a/src/plugins/texteditor/autocompleter.h b/src/plugins/texteditor/autocompleter.h
new file mode 100644
index 0000000000..f8ecc1ce49
--- /dev/null
+++ b/src/plugins/texteditor/autocompleter.h
@@ -0,0 +1,93 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 AUTOCOMPLETER_H
+#define AUTOCOMPLETER_H
+
+#include "texteditor_global.h"
+
+#include <QtCore/QChar>
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+class QTextCursor;
+QT_END_NAMESPACE
+
+namespace TextEditor {
+
+class TEXTEDITOR_EXPORT AutoCompleter
+{
+public:
+ AutoCompleter();
+ virtual ~AutoCompleter();
+
+ void setAutoParenthesesEnabled(bool b);
+ bool isAutoParenthesesEnabled() const;
+
+ void setSurroundWithEnabled(bool b);
+ bool isSurroundWithEnabled() const;
+
+ // Returns the text to complete at the cursor position, or an empty string
+ virtual QString autoComplete(QTextCursor &cursor, const QString &text) const;
+
+ // Handles backspace. When returning true, backspace processing is stopped
+ virtual bool autoBackspace(QTextCursor &cursor);
+
+ // Hook to insert special characters on enter. Returns the number of extra blocks inserted.
+ virtual int paragraphSeparatorAboutToBeInserted(QTextCursor &cursor);
+
+ virtual bool contextAllowsAutoParentheses(const QTextCursor &cursor,
+ const QString &textToInsert = QString()) const;
+ virtual bool contextAllowsElectricCharacters(const QTextCursor &cursor) const;
+
+ // Returns true if the cursor is inside a comment.
+ virtual bool isInComment(const QTextCursor &cursor) const;
+
+ virtual QString insertMatchingBrace(const QTextCursor &cursor, const
+ QString &text,
+ QChar la,
+ int *skippedChars) const;
+
+ // Returns the text that needs to be inserted
+ virtual QString insertParagraphSeparator(const QTextCursor &cursor) const;
+
+protected:
+ static void countBracket(QChar open, QChar close, QChar c, int *errors, int *stillopen);
+ static void countBrackets(QTextCursor cursor, int from, int end, QChar open, QChar close,
+ int *errors, int *stillopen);
+
+private:
+ mutable bool m_allowSkippingOfBlockEnd;
+ bool m_surroundWithEnabled;
+ bool m_autoParenthesesEnabled;
+};
+
+} // TextEditor
+
+#endif // AUTOCOMPLETER_H
diff --git a/src/plugins/texteditor/basefilefind.cpp b/src/plugins/texteditor/basefilefind.cpp
index 6db36045a1..a7f719e6f9 100644
--- a/src/plugins/texteditor/basefilefind.cpp
+++ b/src/plugins/texteditor/basefilefind.cpp
@@ -316,7 +316,7 @@ static void applyChanges(QTextDocument *doc, const QString &text, const QList<Fi
QStringList BaseFileFind::replaceAll(const QString &text,
const QList<Find::SearchResultItem> &items)
{
- if (text.isEmpty() || items.isEmpty())
+ if (items.isEmpty())
return QStringList();
QHash<QString, QList<Find::SearchResultItem> > changes;
diff --git a/src/plugins/texteditor/basefilefind.h b/src/plugins/texteditor/basefilefind.h
index aba43ca292..cb5493b0ee 100644
--- a/src/plugins/texteditor/basefilefind.h
+++ b/src/plugins/texteditor/basefilefind.h
@@ -77,7 +77,7 @@ public:
const QList<Find::SearchResultItem> &items);
protected:
- virtual Utils::FileIterator *files() = 0;
+ virtual Utils::FileIterator *files() const = 0;
void writeCommonSettings(QSettings *settings);
void readCommonSettings(QSettings *settings, const QString &defaultFilter);
QWidget *createPatternWidget();
diff --git a/src/plugins/texteditor/basetextdocument.cpp b/src/plugins/texteditor/basetextdocument.cpp
index d28931feb1..ea02444241 100644
--- a/src/plugins/texteditor/basetextdocument.cpp
+++ b/src/plugins/texteditor/basetextdocument.cpp
@@ -36,6 +36,7 @@
#include "basetextdocumentlayout.h"
#include "basetexteditor.h"
#include "storagesettings.h"
+#include "tabsettings.h"
#include "syntaxhighlighter.h"
#include <QtCore/QFile>
@@ -52,7 +53,25 @@
#include <utils/qtcassert.h>
#include <utils/reloadpromptutils.h>
-using namespace TextEditor;
+namespace TextEditor {
+namespace Internal {
+
+class DocumentMarker : public ITextMarkable
+{
+ Q_OBJECT
+public:
+ DocumentMarker(QTextDocument *);
+
+ // ITextMarkable
+ bool addMark(ITextMark *mark, int line);
+ TextMarks marksAt(int line) const;
+ void removeMark(ITextMark *mark);
+ bool hasMark(ITextMark *mark) const;
+ void updateMark(ITextMark *mark);
+
+private:
+ QTextDocument *document;
+};
DocumentMarker::DocumentMarker(QTextDocument *doc)
: ITextMarkable(doc), document(doc)
@@ -127,63 +146,189 @@ void DocumentMarker::updateMark(ITextMark *mark)
documentLayout->requestUpdate();
}
+} // namespace Internal
-BaseTextDocument::BaseTextDocument()
- : m_document(new QTextDocument(this)),
- m_highlighter(0)
+class BaseTextDocumentPrivate
{
- m_documentMarker = new DocumentMarker(m_document);
- m_lineTerminatorMode = NativeLineTerminator;
- m_fileIsReadOnly = false;
- m_isBinaryData = false;
- m_codec = QTextCodec::codecForLocale();
- QSettings *settings = Core::ICore::instance()->settings();
- if (QTextCodec *candidate = QTextCodec::codecForName(
- settings->value(QLatin1String("General/DefaultFileEncoding")).toByteArray()))
- m_codec = candidate;
+public:
+ explicit BaseTextDocumentPrivate(BaseTextDocument *q);
+
+ QString m_fileName;
+ QString m_defaultPath;
+ QString m_suggestedFileName;
+ QString m_mimeType;
+ StorageSettings m_storageSettings;
+ TabSettings m_tabSettings;
+ QTextDocument *m_document;
+ Internal::DocumentMarker *m_documentMarker;
+ SyntaxHighlighter *m_highlighter;
+
+ enum LineTerminatorMode {
+ LFLineTerminator,
+ CRLFLineTerminator,
+ NativeLineTerminator =
+#if defined (Q_OS_WIN)
+ CRLFLineTerminator
+#else
+ LFLineTerminator
+#endif
+ };
+ LineTerminatorMode m_lineTerminatorMode;
+ QTextCodec *m_codec;
+ bool m_fileHasUtf8Bom;
+
+ bool m_fileIsReadOnly;
+ bool m_isBinaryData;
+ bool m_hasDecodingError;
+ QByteArray m_decodingErrorSample;
+};
+
+BaseTextDocumentPrivate::BaseTextDocumentPrivate(BaseTextDocument *q) :
+ m_document(new QTextDocument(q)),
+ m_documentMarker(new Internal::DocumentMarker(m_document)),
+ m_highlighter(0),
+ m_lineTerminatorMode(NativeLineTerminator),
+ m_codec(Core::EditorManager::instance()->defaultTextEncoding()),
+ m_fileHasUtf8Bom(false),
+ m_fileIsReadOnly(false),
+ m_isBinaryData(false),
+ m_hasDecodingError(false)
+{
+}
- m_hasDecodingError = false;
+BaseTextDocument::BaseTextDocument() : d(new BaseTextDocumentPrivate(this))
+{
}
BaseTextDocument::~BaseTextDocument()
{
documentClosing();
-
- delete m_document;
- m_document = 0;
+ delete d->m_document;
+ d->m_document = 0;
+ delete d;
}
QString BaseTextDocument::mimeType() const
{
- return m_mimeType;
+ return d->m_mimeType;
}
void BaseTextDocument::setMimeType(const QString &mt)
{
- m_mimeType = mt;
+ d->m_mimeType = mt;
+}
+
+void BaseTextDocument::setStorageSettings(const StorageSettings &storageSettings)
+{
+ d->m_storageSettings = storageSettings;
+}
+
+const StorageSettings &BaseTextDocument::storageSettings() const
+{
+ return d->m_storageSettings;
+}
+
+void BaseTextDocument::setTabSettings(const TabSettings &tabSettings)
+{
+ d->m_tabSettings = tabSettings;
+}
+
+const TabSettings &BaseTextDocument::tabSettings() const
+{
+ return d->m_tabSettings;
+}
+
+QString BaseTextDocument::fileName() const
+{
+ return d->m_fileName;
+}
+
+bool BaseTextDocument::isSaveAsAllowed() const
+{
+ return true;
+}
+
+QString BaseTextDocument::defaultPath() const
+{
+ return d->m_defaultPath;
+}
+
+QString BaseTextDocument::suggestedFileName() const
+{
+ return d->m_suggestedFileName;
+}
+
+void BaseTextDocument::setDefaultPath(const QString &defaultPath)
+{
+ d->m_defaultPath = defaultPath;
+}
+
+void BaseTextDocument::setSuggestedFileName(const QString &suggestedFileName)
+{
+ d->m_suggestedFileName = suggestedFileName;
+}
+
+QTextDocument *BaseTextDocument::document() const
+{
+ return d->m_document;
+}
+
+SyntaxHighlighter *BaseTextDocument::syntaxHighlighter() const
+{
+ return d->m_highlighter;
+}
+
+bool BaseTextDocument::isBinaryData() const
+{
+ return d->m_isBinaryData;
+}
+
+bool BaseTextDocument::hasDecodingError() const
+{
+ return d->m_hasDecodingError || d->m_isBinaryData;
+}
+
+QTextCodec *BaseTextDocument::codec() const
+{
+ return d->m_codec;
+}
+
+void BaseTextDocument::setCodec(QTextCodec *c)
+{
+ d->m_codec = c;
+}
+
+QByteArray BaseTextDocument::decodingErrorSample() const
+{
+ return d->m_decodingErrorSample;
+}
+
+ITextMarkable *BaseTextDocument::documentMarker() const
+{
+ return d->m_documentMarker;
}
bool BaseTextDocument::save(const QString &fileName)
{
- QTextCursor cursor(m_document);
+ QTextCursor cursor(d->m_document);
// When saving the current editor, make sure to maintain the cursor position for undo
Core::IEditor *currentEditor = Core::EditorManager::instance()->currentEditor();
if (BaseTextEditorEditable *editable = qobject_cast<BaseTextEditorEditable*>(currentEditor)) {
- if (editable->file() == this)
+ if (editable->file() == this)
cursor.setPosition(editable->editor()->textCursor().position());
}
cursor.beginEditBlock();
cursor.movePosition(QTextCursor::Start);
- if (m_storageSettings.m_cleanWhitespace)
- cleanWhitespace(cursor, m_storageSettings.m_cleanIndentation, m_storageSettings.m_inEntireDocument);
- if (m_storageSettings.m_addFinalNewLine)
+ if (d->m_storageSettings.m_cleanWhitespace)
+ cleanWhitespace(cursor, d->m_storageSettings.m_cleanIndentation, d->m_storageSettings.m_inEntireDocument);
+ if (d->m_storageSettings.m_addFinalNewLine)
ensureFinalNewLine(cursor);
cursor.endEditBlock();
- QString fName = m_fileName;
+ QString fName = d->m_fileName;
if (!fileName.isEmpty())
fName = fileName;
@@ -191,26 +336,32 @@ bool BaseTextDocument::save(const QString &fileName)
if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate))
return false;
- QString plainText = m_document->toPlainText();
+ QString plainText = d->m_document->toPlainText();
- if (m_lineTerminatorMode == CRLFLineTerminator)
+ if (d->m_lineTerminatorMode == BaseTextDocumentPrivate::CRLFLineTerminator)
plainText.replace(QLatin1Char('\n'), QLatin1String("\r\n"));
- file.write(m_codec->fromUnicode(plainText));
+ Core::IFile::Utf8BomSetting utf8bomSetting = Core::EditorManager::instance()->utf8BomSetting();
+ if (d->m_codec->name() == "UTF-8" &&
+ (utf8bomSetting == Core::IFile::AlwaysAdd || (utf8bomSetting == Core::IFile::OnlyKeep && d->m_fileHasUtf8Bom))) {
+ file.write("\xef\xbb\xbf", 3);
+ }
+
+ file.write(d->m_codec->fromUnicode(plainText));
if (!file.flush())
return false;
file.close();
const QFileInfo fi(fName);
- m_fileName = QDir::cleanPath(fi.absoluteFilePath());
+ d->m_fileName = QDir::cleanPath(fi.absoluteFilePath());
- m_document->setModified(false);
+ d->m_document->setModified(false);
emit titleChanged(fi.fileName());
emit changed();
- m_isBinaryData = false;
- m_hasDecodingError = false;
- m_decodingErrorSample.clear();
+ d->m_isBinaryData = false;
+ d->m_hasDecodingError = false;
+ d->m_decodingErrorSample.clear();
return true;
}
@@ -218,35 +369,35 @@ bool BaseTextDocument::save(const QString &fileName)
void BaseTextDocument::rename(const QString &newName)
{
const QFileInfo fi(newName);
- m_fileName = QDir::cleanPath(fi.absoluteFilePath());
+ d->m_fileName = QDir::cleanPath(fi.absoluteFilePath());
emit titleChanged(fi.fileName());
emit changed();
}
bool BaseTextDocument::isReadOnly() const
{
- if (m_isBinaryData || m_hasDecodingError)
+ if (d->m_isBinaryData || d->m_hasDecodingError)
return true;
- if (m_fileName.isEmpty()) //have no corresponding file, so editing is ok
+ if (d->m_fileName.isEmpty()) //have no corresponding file, so editing is ok
return false;
- return m_fileIsReadOnly;
+ return d->m_fileIsReadOnly;
}
bool BaseTextDocument::isModified() const
{
- return m_document->isModified();
+ return d->m_document->isModified();
}
void BaseTextDocument::checkPermissions()
{
- bool previousReadOnly = m_fileIsReadOnly;
- if (!m_fileName.isEmpty()) {
- const QFileInfo fi(m_fileName);
- m_fileIsReadOnly = !fi.isWritable();
+ bool previousReadOnly = d->m_fileIsReadOnly;
+ if (!d->m_fileName.isEmpty()) {
+ const QFileInfo fi(d->m_fileName);
+ d->m_fileIsReadOnly = !fi.isWritable();
} else {
- m_fileIsReadOnly = false;
+ d->m_fileIsReadOnly = false;
}
- if (previousReadOnly != m_fileIsReadOnly)
+ if (previousReadOnly != d->m_fileIsReadOnly)
emit changed();
}
@@ -255,8 +406,8 @@ bool BaseTextDocument::open(const QString &fileName)
QString title = tr("untitled");
if (!fileName.isEmpty()) {
const QFileInfo fi(fileName);
- m_fileIsReadOnly = !fi.isWritable();
- m_fileName = QDir::cleanPath(fi.absoluteFilePath());
+ d->m_fileIsReadOnly = !fi.isWritable();
+ d->m_fileName = QDir::cleanPath(fi.absoluteFilePath());
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly))
@@ -267,7 +418,8 @@ bool BaseTextDocument::open(const QString &fileName)
QByteArray buf = file.readAll();
int bytesRead = buf.size();
- QTextCodec *codec = m_codec;
+ QTextCodec *codec = d->m_codec;
+ d->m_fileHasUtf8Bom = false;
// code taken from qtextstream
if (bytesRead >= 4 && ((uchar(buf[0]) == 0xff && uchar(buf[1]) == 0xfe && uchar(buf[2]) == 0 && uchar(buf[3]) == 0)
@@ -276,56 +428,59 @@ bool BaseTextDocument::open(const QString &fileName)
} else if (bytesRead >= 2 && ((uchar(buf[0]) == 0xff && uchar(buf[1]) == 0xfe)
|| (uchar(buf[0]) == 0xfe && uchar(buf[1]) == 0xff))) {
codec = QTextCodec::codecForName("UTF-16");
+ } else if (bytesRead >= 3 && ((uchar(buf[0]) == 0xef && uchar(buf[1]) == 0xbb) && uchar(buf[2]) == 0xbf)) {
+ codec = QTextCodec::codecForName("UTF-8");
+ d->m_fileHasUtf8Bom = true;
} else if (!codec) {
codec = QTextCodec::codecForLocale();
}
// end code taken from qtextstream
- m_codec = codec;
+ d->m_codec = codec;
#if 0 // should work, but does not, Qt bug with "system" codec
- QTextDecoder *decoder = m_codec->makeDecoder();
+ QTextDecoder *decoder = d->m_codec->makeDecoder();
QString text = decoder->toUnicode(buf);
- m_hasDecodingError = (decoder->hasFailure());
+ d->m_hasDecodingError = (decoder->hasFailure());
delete decoder;
#else
- QString text = m_codec->toUnicode(buf);
- QByteArray verifyBuf = m_codec->fromUnicode(text); // slow
+ QString text = d->m_codec->toUnicode(buf);
+ QByteArray verifyBuf = d->m_codec->fromUnicode(text); // slow
// the minSize trick lets us ignore unicode headers
int minSize = qMin(verifyBuf.size(), buf.size());
- m_hasDecodingError = (minSize < buf.size()- 4
+ d->m_hasDecodingError = (minSize < buf.size()- 4
|| memcmp(verifyBuf.constData() + verifyBuf.size() - minSize,
buf.constData() + buf.size() - minSize, minSize));
#endif
- if (m_hasDecodingError) {
+ if (d->m_hasDecodingError) {
int p = buf.indexOf('\n', 16384);
if (p < 0)
- m_decodingErrorSample = buf;
+ d->m_decodingErrorSample = buf;
else
- m_decodingErrorSample = buf.left(p);
+ d->m_decodingErrorSample = buf.left(p);
} else {
- m_decodingErrorSample.clear();
+ d->m_decodingErrorSample.clear();
}
int lf = text.indexOf('\n');
if (lf > 0 && text.at(lf-1) == QLatin1Char('\r')) {
- m_lineTerminatorMode = CRLFLineTerminator;
+ d->m_lineTerminatorMode = BaseTextDocumentPrivate::CRLFLineTerminator;
} else if (lf >= 0) {
- m_lineTerminatorMode = LFLineTerminator;
+ d->m_lineTerminatorMode = BaseTextDocumentPrivate::LFLineTerminator;
} else {
- m_lineTerminatorMode = NativeLineTerminator;
+ d->m_lineTerminatorMode = BaseTextDocumentPrivate::NativeLineTerminator;
}
- m_document->setModified(false);
- if (m_isBinaryData)
- m_document->setHtml(tr("<em>Binary data</em>"));
+ d->m_document->setModified(false);
+ if (d->m_isBinaryData)
+ d->m_document->setHtml(tr("<em>Binary data</em>"));
else
- m_document->setPlainText(text);
- BaseTextDocumentLayout *documentLayout = qobject_cast<BaseTextDocumentLayout*>(m_document->documentLayout());
+ d->m_document->setPlainText(text);
+ BaseTextDocumentLayout *documentLayout = qobject_cast<BaseTextDocumentLayout*>(d->m_document->documentLayout());
QTC_ASSERT(documentLayout, return true);
- documentLayout->lastSaveRevision = m_document->revision();
- m_document->setModified(false);
+ documentLayout->lastSaveRevision = d->m_document->revision();
+ d->m_document->setModified(false);
emit titleChanged(title);
emit changed();
}
@@ -335,7 +490,7 @@ bool BaseTextDocument::open(const QString &fileName)
void BaseTextDocument::reload(QTextCodec *codec)
{
QTC_ASSERT(codec, return);
- m_codec = codec;
+ d->m_codec = codec;
reload();
}
@@ -344,7 +499,7 @@ void BaseTextDocument::reload()
emit aboutToReload();
documentClosing(); // removes text marks non-permanently
- if (open(m_fileName))
+ if (open(d->m_fileName))
emit reloaded();
}
@@ -373,11 +528,11 @@ void BaseTextDocument::reload(ReloadFlag flag, ChangeType type)
void BaseTextDocument::setSyntaxHighlighter(SyntaxHighlighter *highlighter)
{
- if (m_highlighter)
- delete m_highlighter;
- m_highlighter = highlighter;
- m_highlighter->setParent(this);
- m_highlighter->setDocument(m_document);
+ if (d->m_highlighter)
+ delete d->m_highlighter;
+ d->m_highlighter = highlighter;
+ d->m_highlighter->setParent(this);
+ d->m_highlighter->setDocument(d->m_document);
}
@@ -396,34 +551,34 @@ void BaseTextDocument::cleanWhitespace(const QTextCursor &cursor)
void BaseTextDocument::cleanWhitespace(QTextCursor &cursor, bool cleanIndentation, bool inEntireDocument)
{
- BaseTextDocumentLayout *documentLayout = qobject_cast<BaseTextDocumentLayout*>(m_document->documentLayout());
+ BaseTextDocumentLayout *documentLayout = qobject_cast<BaseTextDocumentLayout*>(d->m_document->documentLayout());
Q_ASSERT(cursor.visualNavigation() == false);
- QTextBlock block = m_document->findBlock(cursor.selectionStart());
+ QTextBlock block = d->m_document->findBlock(cursor.selectionStart());
QTextBlock end;
if (cursor.hasSelection())
- end = m_document->findBlock(cursor.selectionEnd()-1).next();
+ end = d->m_document->findBlock(cursor.selectionEnd()-1).next();
while (block.isValid() && block != end) {
if (inEntireDocument || block.revision() != documentLayout->lastSaveRevision) {
QString blockText = block.text();
- if (int trailing = m_tabSettings.trailingWhitespaces(blockText)) {
+ if (int trailing = d->m_tabSettings.trailingWhitespaces(blockText)) {
cursor.setPosition(block.position() + block.length() - 1);
cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor, trailing);
cursor.removeSelectedText();
}
- if (cleanIndentation && !m_tabSettings.isIndentationClean(block)) {
+ if (cleanIndentation && !d->m_tabSettings.isIndentationClean(block)) {
cursor.setPosition(block.position());
- int firstNonSpace = m_tabSettings.firstNonSpace(blockText);
+ int firstNonSpace = d->m_tabSettings.firstNonSpace(blockText);
if (firstNonSpace == blockText.length()) {
cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
cursor.removeSelectedText();
} else {
- int column = m_tabSettings.columnAt(blockText, firstNonSpace);
+ int column = d->m_tabSettings.columnAt(blockText, firstNonSpace);
cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, firstNonSpace);
- QString indentationString = m_tabSettings.indentationString(0, column, block);
+ QString indentationString = d->m_tabSettings.indentationString(0, column, block);
cursor.insertText(indentationString);
}
}
@@ -447,10 +602,14 @@ void BaseTextDocument::ensureFinalNewLine(QTextCursor& cursor)
void BaseTextDocument::documentClosing()
{
- QTextBlock block = m_document->begin();
+ QTextBlock block = d->m_document->begin();
while (block.isValid()) {
if (TextBlockUserData *data = static_cast<TextBlockUserData *>(block.userData()))
data->documentClosing();
block = block.next();
}
}
+
+} // namespace TextEditor
+
+#include "basetextdocument.moc"
diff --git a/src/plugins/texteditor/basetextdocument.h b/src/plugins/texteditor/basetextdocument.h
index 3b0db81623..0a45f86f8e 100644
--- a/src/plugins/texteditor/basetextdocument.h
+++ b/src/plugins/texteditor/basetextdocument.h
@@ -35,9 +35,6 @@
#define BASETEXTDOCUMENT_H
#include "texteditor_global.h"
-#include "storagesettings.h"
-#include "itexteditor.h"
-#include "tabsettings.h"
#include <coreplugin/ifile.h>
@@ -47,26 +44,15 @@ class QTextDocument;
QT_END_NAMESPACE
namespace TextEditor {
+namespace Internal {
+class DocumentMarker;
+}
+class ITextMarkable;
+class StorageSettings;
+class TabSettings;
class SyntaxHighlighter;
-
-class DocumentMarker : public ITextMarkable
-{
- Q_OBJECT
-public:
- DocumentMarker(QTextDocument *);
-
- // ITextMarkable
- bool addMark(ITextMark *mark, int line);
- TextMarks marksAt(int line) const;
- void removeMark(ITextMark *mark);
- bool hasMark(ITextMark *mark) const;
- void updateMark(ITextMark *mark);
-
-private:
- QTextDocument *document;
-};
-
+class BaseTextDocumentPrivate;
class TEXTEDITOR_EXPORT BaseTextDocument : public Core::IFile
{
@@ -74,21 +60,22 @@ class TEXTEDITOR_EXPORT BaseTextDocument : public Core::IFile
public:
BaseTextDocument();
- ~BaseTextDocument();
- void setStorageSettings(const StorageSettings &storageSettings) { m_storageSettings = storageSettings; }
- void setTabSettings(const TabSettings &tabSettings) { m_tabSettings = tabSettings; }
+ virtual ~BaseTextDocument();
- inline const StorageSettings &storageSettings() const { return m_storageSettings; }
- inline const TabSettings &tabSettings() const { return m_tabSettings; }
+ void setStorageSettings(const StorageSettings &storageSettings);
+ void setTabSettings(const TabSettings &tabSettings);
- DocumentMarker *documentMarker() const { return m_documentMarker; }
+ const StorageSettings &storageSettings() const;
+ const TabSettings &tabSettings() const;
+
+ ITextMarkable *documentMarker() const;
//IFile
virtual bool save(const QString &fileName = QString());
- virtual QString fileName() const { return m_fileName; }
+ virtual QString fileName() const;
virtual bool isReadOnly() const;
virtual bool isModified() const;
- virtual bool isSaveAsAllowed() const { return true; }
+ virtual bool isSaveAsAllowed() const;
virtual void checkPermissions();
ReloadBehavior reloadBehavior(ChangeTrigger state, ChangeType type) const;
void reload(ReloadFlag flag, ChangeType type);
@@ -96,25 +83,25 @@ public:
void setMimeType(const QString &mt);
virtual void rename(const QString &newName);
- virtual QString defaultPath() const { return m_defaultPath; }
- virtual QString suggestedFileName() const { return m_suggestedFileName; }
+ virtual QString defaultPath() const;
+ virtual QString suggestedFileName() const;
- void setDefaultPath(const QString &defaultPath) { m_defaultPath = defaultPath; }
- void setSuggestedFileName(const QString &suggestedFileName) { m_suggestedFileName = suggestedFileName; }
+ void setDefaultPath(const QString &defaultPath);
+ void setSuggestedFileName(const QString &suggestedFileName);
virtual bool open(const QString &fileName = QString());
virtual void reload();
- QTextDocument *document() const { return m_document; }
+ QTextDocument *document() const;
void setSyntaxHighlighter(SyntaxHighlighter *highlighter);
- SyntaxHighlighter *syntaxHighlighter() const { return m_highlighter; }
+ SyntaxHighlighter *syntaxHighlighter() const;
- inline bool isBinaryData() const { return m_isBinaryData; }
- inline bool hasDecodingError() const { return m_hasDecodingError || m_isBinaryData; }
- inline QTextCodec *codec() const { return m_codec; }
- inline void setCodec(QTextCodec *c) { m_codec = c; }
- inline QByteArray decodingErrorSample() const { return m_decodingErrorSample; }
+ bool isBinaryData() const;
+ bool hasDecodingError() const;
+ QTextCodec *codec() const;
+ void setCodec(QTextCodec *c);
+ QByteArray decodingErrorSample() const;
void reload(QTextCodec *codec);
@@ -124,37 +111,11 @@ signals:
void titleChanged(QString title);
private:
- QString m_fileName;
- QString m_defaultPath;
- QString m_suggestedFileName;
- QString m_mimeType;
- StorageSettings m_storageSettings;
- TabSettings m_tabSettings;
- QTextDocument *m_document;
- DocumentMarker *m_documentMarker;
- SyntaxHighlighter *m_highlighter;
-
- enum LineTerminatorMode {
- LFLineTerminator,
- CRLFLineTerminator,
- NativeLineTerminator =
-#if defined (Q_OS_WIN)
- CRLFLineTerminator
-#else
- LFLineTerminator
-#endif
- };
- LineTerminatorMode m_lineTerminatorMode;
- QTextCodec *m_codec;
-
- bool m_fileIsReadOnly;
- bool m_isBinaryData;
- bool m_hasDecodingError;
- QByteArray m_decodingErrorSample;
-
void cleanWhitespace(QTextCursor& cursor, bool cleanIndentation, bool inEntireDocument);
void ensureFinalNewLine(QTextCursor& cursor);
void documentClosing();
+
+ BaseTextDocumentPrivate *d;
};
} // namespace TextEditor
diff --git a/src/plugins/texteditor/basetextdocumentlayout.h b/src/plugins/texteditor/basetextdocumentlayout.h
index 85be35688f..9e860b32a1 100644
--- a/src/plugins/texteditor/basetextdocumentlayout.h
+++ b/src/plugins/texteditor/basetextdocumentlayout.h
@@ -111,10 +111,19 @@ public:
static bool findPreviousBlockOpenParenthesis(QTextCursor *cursor, bool checkStartPosition = false);
static bool findNextBlockClosingParenthesis(QTextCursor *cursor);
+ // Get the code folding level
inline int foldingIndent() const { return m_foldingIndent; }
+ /* Set the code folding level.
+ *
+ * A code folding marker will appear the line *before* the one where the indention
+ * level increases. The code folding reagion will end in the last line that has the same
+ * indention level (or higher).
+ */
inline void setFoldingIndent(int indent) { m_foldingIndent = indent; }
+ // Set whether the first charater of the folded region will show when the code is folded.
inline void setFoldingStartIncluded(bool included) { m_foldingStartIncluded = included; }
inline bool foldingStartIncluded() const { return m_foldingStartIncluded; }
+ // Set whether the last charater of the folded region will show when the code is folded.
inline void setFoldingEndIncluded(bool included) { m_foldingEndIncluded = included; }
inline bool foldingEndIncluded() const { return m_foldingEndIncluded; }
inline int lexerState() const { return m_lexerState; }
diff --git a/src/plugins/texteditor/basetexteditor.cpp b/src/plugins/texteditor/basetexteditor.cpp
index 57299122f2..e5ee614c07 100644
--- a/src/plugins/texteditor/basetexteditor.cpp
+++ b/src/plugins/texteditor/basetexteditor.cpp
@@ -46,6 +46,9 @@
#include "syntaxhighlighter.h"
#include "tooltip.h"
#include "tipcontents.h"
+#include "indenter.h"
+#include "autocompleter.h"
+#include "snippet.h"
#include <aggregation/aggregate.h>
#include <coreplugin/actionmanager/actionmanager.h>
@@ -55,6 +58,7 @@
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/icore.h>
#include <coreplugin/manhattanstyle.h>
+#include <coreplugin/uniqueidmanager.h>
#include <extensionsystem/pluginmanager.h>
#include <find/basetextfind.h>
#include <utils/linecolumnlabel.h>
@@ -670,10 +674,7 @@ void BaseTextEditor::editorContentsChange(int position, int charsRemoved, int ch
if (d->m_snippetOverlay->isVisible()) {
QTextCursor cursor = textCursor();
cursor.setPosition(position);
- if (!d->m_snippetOverlay->hasCursorInSelection(cursor)) {
- d->m_snippetOverlay->hide();
- d->m_snippetOverlay->clear();
- }
+ d->snippetCheckCursor(cursor);
}
if (doc->isRedoAvailable())
@@ -812,6 +813,35 @@ void BaseTextEditor::gotoNextWordWithSelection()
moveCursor(QTextCursor::NextWord, QTextCursor::KeepAnchor);
}
+void BaseTextEditor::gotoPreviousWordCamelCase()
+{
+ QTextCursor c = textCursor();
+ camelCaseLeft(c, QTextCursor::MoveAnchor);
+ setTextCursor(c);
+}
+
+void BaseTextEditor::gotoPreviousWordCamelCaseWithSelection()
+{
+ QTextCursor c = textCursor();
+ camelCaseLeft(c, QTextCursor::KeepAnchor);
+ setTextCursor(c);
+}
+
+void BaseTextEditor::gotoNextWordCamelCase()
+{
+ qDebug() << Q_FUNC_INFO;
+ QTextCursor c = textCursor();
+ camelCaseRight(c, QTextCursor::MoveAnchor);
+ setTextCursor(c);
+}
+
+void BaseTextEditor::gotoNextWordCamelCaseWithSelection()
+{
+ QTextCursor c = textCursor();
+ camelCaseRight(c, QTextCursor::KeepAnchor);
+ setTextCursor(c);
+}
+
static QTextCursor flippedCursor(const QTextCursor &cursor)
@@ -1078,6 +1108,386 @@ void BaseTextEditor::cleanWhitespace()
d->m_document->cleanWhitespace(textCursor());
}
+
+// could go into QTextCursor...
+static QTextLine currentTextLine(const QTextCursor &cursor)
+{
+ const QTextBlock block = cursor.block();
+ if (!block.isValid())
+ return QTextLine();
+
+ const QTextLayout *layout = block.layout();
+ if (!layout)
+ return QTextLine();
+
+ const int relativePos = cursor.position() - block.position();
+ return layout->lineForTextPosition(relativePos);
+}
+
+bool BaseTextEditor::camelCaseLeft(QTextCursor &cursor, QTextCursor::MoveMode mode)
+{
+ int state = 0;
+ enum Input {
+ Input_U,
+ Input_l,
+ Input_underscore,
+ Input_space,
+ Input_other
+ };
+
+ if (!cursor.movePosition(QTextCursor::Left, mode))
+ return false;
+
+ forever {
+ QChar c = characterAt(cursor.position());
+ Input input = Input_other;
+ if (c.isUpper())
+ input = Input_U;
+ else if (c.isLower() || c.isDigit())
+ input = Input_l;
+ else if (c == QLatin1Char('_'))
+ input = Input_underscore;
+ else if (c.isSpace() && c != QChar::ParagraphSeparator)
+ input = Input_space;
+ else
+ input = Input_other;
+
+ switch (state) {
+ case 0:
+ switch (input) {
+ case Input_U:
+ state = 1;
+ break;
+ case Input_l:
+ state = 2;
+ break;
+ case Input_underscore:
+ state = 3;
+ break;
+ case Input_space:
+ state = 4;
+ break;
+ default:
+ cursor.movePosition(QTextCursor::Right, mode);
+ return cursor.movePosition(QTextCursor::WordLeft, mode);
+ }
+ break;
+ case 1:
+ switch (input) {
+ case Input_U:
+ break;
+ default:
+ cursor.movePosition(QTextCursor::Right, mode);
+ return true;
+ }
+ break;
+
+ case 2:
+ switch (input) {
+ case Input_U:
+ return true;
+ case Input_l:
+ break;
+ default:
+ cursor.movePosition(QTextCursor::Right, mode);
+ return true;
+ }
+ break;
+ case 3:
+ switch (input) {
+ case Input_underscore:
+ break;
+ case Input_U:
+ state = 1;
+ break;
+ case Input_l:
+ state = 2;
+ break;
+ default:
+ cursor.movePosition(QTextCursor::Right, mode);
+ return true;
+ }
+ break;
+ case 4:
+ switch (input) {
+ case Input_space:
+ break;
+ case Input_U:
+ state = 1;
+ break;
+ case Input_l:
+ state = 2;
+ break;
+ case Input_underscore:
+ state = 3;
+ break;
+ default:
+ cursor.movePosition(QTextCursor::Right, mode);
+ if (cursor.positionInBlock() == 0)
+ return true;
+ return cursor.movePosition(QTextCursor::WordLeft, mode);
+ }
+ }
+
+ if (!cursor.movePosition(QTextCursor::Left, mode))
+ return true;
+ }
+}
+
+bool BaseTextEditor::camelCaseRight(QTextCursor &cursor, QTextCursor::MoveMode mode)
+{
+ int state = 0;
+ enum Input {
+ Input_U,
+ Input_l,
+ Input_underscore,
+ Input_space,
+ Input_other
+ };
+
+ forever {
+ QChar c = characterAt(cursor.position());
+ Input input = Input_other;
+ if (c.isUpper())
+ input = Input_U;
+ else if (c.isLower() || c.isDigit())
+ input = Input_l;
+ else if (c == QLatin1Char('_'))
+ input = Input_underscore;
+ else if (c.isSpace() && c != QChar::ParagraphSeparator)
+ input = Input_space;
+ else
+ input = Input_other;
+
+ switch (state) {
+ case 0:
+ switch (input) {
+ case Input_U:
+ state = 4;
+ break;
+ case Input_l:
+ state = 1;
+ break;
+ case Input_underscore:
+ state = 6;
+ break;
+ default:
+ return cursor.movePosition(QTextCursor::WordRight, mode);
+ }
+ break;
+ case 1:
+ switch (input) {
+ case Input_U:
+ return true;
+ case Input_l:
+ break;
+ case Input_underscore:
+ state = 6;
+ break;
+ case Input_space:
+ state = 7;
+ break;
+ default:
+ return true;
+ }
+ break;
+ case 2:
+ switch (input) {
+ case Input_U:
+ break;
+ case Input_l:
+ cursor.movePosition(QTextCursor::Left, mode);
+ return true;
+ case Input_underscore:
+ state = 6;
+ break;
+ case Input_space:
+ state = 7;
+ break;
+ default:
+ return true;
+ }
+ break;
+ case 4:
+ switch (input) {
+ case Input_U:
+ state = 2;
+ break;
+ case Input_l:
+ state = 1;
+ break;
+ case Input_underscore:
+ state = 6;
+ break;
+ case Input_space:
+ state = 7;
+ break;
+ default:
+ return true;
+ }
+ break;
+ case 6:
+ switch (input) {
+ case Input_underscore:
+ break;
+ case Input_space:
+ state = 7;
+ break;
+ default:
+ return true;
+ }
+ break;
+ case 7:
+ switch (input) {
+ case Input_space:
+ break;
+ default:
+ return true;
+ }
+ break;
+ }
+ cursor.movePosition(QTextCursor::Right, mode);
+ }
+}
+
+bool BaseTextEditor::cursorMoveKeyEvent(QKeyEvent *e)
+{
+ QTextCursor cursor = textCursor();
+
+ QTextCursor::MoveMode mode = QTextCursor::MoveAnchor;
+ QTextCursor::MoveOperation op = QTextCursor::NoMove;
+
+ if (e == QKeySequence::MoveToNextChar) {
+ op = QTextCursor::Right;
+ }
+ else if (e == QKeySequence::MoveToPreviousChar) {
+ op = QTextCursor::Left;
+ }
+ else if (e == QKeySequence::SelectNextChar) {
+ op = QTextCursor::Right;
+ mode = QTextCursor::KeepAnchor;
+ }
+ else if (e == QKeySequence::SelectPreviousChar) {
+ op = QTextCursor::Left;
+ mode = QTextCursor::KeepAnchor;
+ }
+ else if (e == QKeySequence::SelectNextWord) {
+ op = QTextCursor::WordRight;
+ mode = QTextCursor::KeepAnchor;
+ }
+ else if (e == QKeySequence::SelectPreviousWord) {
+ op = QTextCursor::WordLeft;
+ mode = QTextCursor::KeepAnchor;
+ }
+ else if (e == QKeySequence::SelectStartOfLine) {
+ op = QTextCursor::StartOfLine;
+ mode = QTextCursor::KeepAnchor;
+ }
+ else if (e == QKeySequence::SelectEndOfLine) {
+ op = QTextCursor::EndOfLine;
+ mode = QTextCursor::KeepAnchor;
+ }
+ else if (e == QKeySequence::SelectStartOfBlock) {
+ op = QTextCursor::StartOfBlock;
+ mode = QTextCursor::KeepAnchor;
+ }
+ else if (e == QKeySequence::SelectEndOfBlock) {
+ op = QTextCursor::EndOfBlock;
+ mode = QTextCursor::KeepAnchor;
+ }
+ else if (e == QKeySequence::SelectStartOfDocument) {
+ op = QTextCursor::Start;
+ mode = QTextCursor::KeepAnchor;
+ }
+ else if (e == QKeySequence::SelectEndOfDocument) {
+ op = QTextCursor::End;
+ mode = QTextCursor::KeepAnchor;
+ }
+ else if (e == QKeySequence::SelectPreviousLine) {
+ op = QTextCursor::Up;
+ mode = QTextCursor::KeepAnchor;
+ }
+ else if (e == QKeySequence::SelectNextLine) {
+ op = QTextCursor::Down;
+ mode = QTextCursor::KeepAnchor;
+ {
+ QTextBlock block = cursor.block();
+ QTextLine line = currentTextLine(cursor);
+ if (!block.next().isValid()
+ && line.isValid()
+ && line.lineNumber() == block.layout()->lineCount() - 1)
+ op = QTextCursor::End;
+ }
+ }
+ else if (e == QKeySequence::MoveToNextWord) {
+ op = QTextCursor::WordRight;
+ }
+ else if (e == QKeySequence::MoveToPreviousWord) {
+ op = QTextCursor::WordLeft;
+ }
+ else if (e == QKeySequence::MoveToEndOfBlock) {
+ op = QTextCursor::EndOfBlock;
+ }
+ else if (e == QKeySequence::MoveToStartOfBlock) {
+ op = QTextCursor::StartOfBlock;
+ }
+ else if (e == QKeySequence::MoveToNextLine) {
+ op = QTextCursor::Down;
+ }
+ else if (e == QKeySequence::MoveToPreviousLine) {
+ op = QTextCursor::Up;
+ }
+ else if (e == QKeySequence::MoveToPreviousLine) {
+ op = QTextCursor::Up;
+ }
+ else if (e == QKeySequence::MoveToStartOfLine) {
+ op = QTextCursor::StartOfLine;
+ }
+ else if (e == QKeySequence::MoveToEndOfLine) {
+ op = QTextCursor::EndOfLine;
+ }
+ else if (e == QKeySequence::MoveToStartOfDocument) {
+ op = QTextCursor::Start;
+ }
+ else if (e == QKeySequence::MoveToEndOfDocument) {
+ op = QTextCursor::End;
+ }
+ else {
+ return false;
+ }
+
+
+// Except for pageup and pagedown, Mac OS X has very different behavior, we don't do it all, but
+// here's the breakdown:
+// Shift still works as an anchor, but only one of the other keys can be down Ctrl (Command),
+// Alt (Option), or Meta (Control).
+// Command/Control + Left/Right -- Move to left or right of the line
+// + Up/Down -- Move to top bottom of the file. (Control doesn't move the cursor)
+// Option + Left/Right -- Move one word Left/right.
+// + Up/Down -- Begin/End of Paragraph.
+// Home/End Top/Bottom of file. (usually don't move the cursor, but will select)
+
+ bool visualNavigation = cursor.visualNavigation();
+ cursor.setVisualNavigation(true);
+ bool moved = false;
+
+ if (op == QTextCursor::WordRight) {
+ moved = camelCaseRight(cursor, mode);
+ } else if (op == QTextCursor::WordLeft) {
+ moved = camelCaseLeft(cursor, mode);
+ } else {
+ moved = cursor.movePosition(op, mode);
+ }
+ cursor.setVisualNavigation(visualNavigation);
+
+ if (moved) {
+ setTextCursor(cursor);
+ ensureCursorVisible();
+ }
+ return true;
+}
+
+
void BaseTextEditor::keyPressEvent(QKeyEvent *e)
{
viewport()->setCursor(Qt::BlankCursor);
@@ -1144,8 +1554,9 @@ void BaseTextEditor::keyPressEvent(QKeyEvent *e)
const TabSettings &ts = d->m_document->tabSettings();
cursor.beginEditBlock();
- int extraBlocks = paragraphSeparatorAboutToBeInserted(cursor); // virtual
+ int extraBlocks = d->m_autoCompleter->paragraphSeparatorAboutToBeInserted(cursor);
+ QString previousIndentationString;
if (ts.m_autoIndent) {
cursor.insertBlock();
indent(document(), cursor, QChar::Null);
@@ -1153,8 +1564,10 @@ void BaseTextEditor::keyPressEvent(QKeyEvent *e)
cursor.insertBlock();
// After inserting the block, to avoid duplicating whitespace on the same line
- const QString previousBlockText = cursor.block().previous().text();
- cursor.insertText(ts.indentationString(previousBlockText));
+ const QString &previousBlockText = cursor.block().previous().text();
+ previousIndentationString = ts.indentationString(previousBlockText);
+ if (!previousIndentationString.isEmpty())
+ cursor.insertText(previousIndentationString);
}
cursor.endEditBlock();
e->accept();
@@ -1164,6 +1577,10 @@ void BaseTextEditor::keyPressEvent(QKeyEvent *e)
while (extraBlocks > 0) {
--extraBlocks;
ensureVisible.movePosition(QTextCursor::NextBlock);
+ if (ts.m_autoIndent)
+ indent(document(), ensureVisible, QChar::Null);
+ else if (!previousIndentationString.isEmpty())
+ ensureVisible.insertText(previousIndentationString);
}
setTextCursor(ensureVisible);
}
@@ -1202,7 +1619,7 @@ void BaseTextEditor::keyPressEvent(QKeyEvent *e)
e->accept();
QTextCursor c = textCursor();
int pos = c.position();
- c.movePosition(QTextCursor::PreviousWord);
+ camelCaseLeft(c, QTextCursor::MoveAnchor);
int targetpos = c.position();
forever {
handleBackspaceKey();
@@ -1212,6 +1629,18 @@ void BaseTextEditor::keyPressEvent(QKeyEvent *e)
pos = cpos;
}
return;
+ } else if (!ro && e == QKeySequence::DeleteStartOfWord && !textCursor().hasSelection()) {
+ e->accept();
+ QTextCursor c = textCursor();
+ camelCaseLeft(c, QTextCursor::KeepAnchor);
+ c.removeSelectedText();
+ return;
+ } else if (!ro && e == QKeySequence::DeleteEndOfWord && !textCursor().hasSelection()) {
+ e->accept();
+ QTextCursor c = textCursor();
+ camelCaseRight(c, QTextCursor::KeepAnchor);
+ c.removeSelectedText();
+ return;
} else switch (e->key()) {
@@ -1330,32 +1759,46 @@ void BaseTextEditor::keyPressEvent(QKeyEvent *e)
return;
}
- if (d->m_snippetOverlay->isVisible()
- && (e->key() == Qt::Key_Delete || e->key() == Qt::Key_Backspace)) {
- d->snippetCheckCursor(textCursor());
- }
-
if (ro || e->text().isEmpty() || !e->text().at(0).isPrint()) {
- QPlainTextEdit::keyPressEvent(e);
+ if (cursorMoveKeyEvent(e))
+ ;
+ else {
+ QTextCursor cursor = textCursor();
+ bool cursorWithinSnippet = false;
+ if (d->m_snippetOverlay->isVisible()
+ && (e->key() == Qt::Key_Delete || e->key() == Qt::Key_Backspace)) {
+ cursorWithinSnippet = d->snippetCheckCursor(cursor);
+ }
+ if (cursorWithinSnippet)
+ cursor.beginEditBlock();
+
+ QPlainTextEdit::keyPressEvent(e);
+
+ if (cursorWithinSnippet) {
+ cursor.endEditBlock();
+ d->m_snippetOverlay->updateEquivalentSelections(textCursor());
+ }
+ }
} else if ((e->modifiers() & (Qt::ControlModifier|Qt::AltModifier)) != Qt::ControlModifier){
QTextCursor cursor = textCursor();
QString text = e->text();
- QString autoText = autoComplete(cursor, text);
+ const QString &autoText = d->m_autoCompleter->autoComplete(cursor, text);
QChar electricChar;
if (d->m_document->tabSettings().m_autoIndent) {
foreach (QChar c, text) {
- if (isElectricCharacter(c)) {
+ if (d->m_indenter->isElectricCharacter(c)) {
electricChar = c;
break;
}
}
}
+ bool cursorWithinSnippet = false;
if (d->m_snippetOverlay->isVisible())
- d->snippetCheckCursor(cursor);
+ cursorWithinSnippet = d->snippetCheckCursor(cursor);
- bool doEditBlock = !(electricChar.isNull() && autoText.isEmpty());
+ bool doEditBlock = !electricChar.isNull() || !autoText.isEmpty() || cursorWithinSnippet;
if (doEditBlock)
cursor.beginEditBlock();
@@ -1364,13 +1807,22 @@ void BaseTextEditor::keyPressEvent(QKeyEvent *e)
if (!autoText.isEmpty()) {
int pos = cursor.position();
cursor.insertText(autoText);
- cursor.setPosition(pos);
+ //Select the inserted text, to be able to re-indent the inserted text
+ cursor.setPosition(pos, QTextCursor::KeepAnchor);
}
- if (!electricChar.isNull() && contextAllowsElectricCharacters(cursor))
+ if (!electricChar.isNull() && d->m_autoCompleter->contextAllowsElectricCharacters(cursor))
indent(document(), cursor, electricChar);
+ if (!autoText.isEmpty()) {
+ if (d->m_document->tabSettings().m_autoIndent)
+ reindent(document(), cursor);
+ cursor.setPosition(autoText.length() == 1 ? cursor.position() : cursor.anchor());
+ }
- if (doEditBlock)
+ if (doEditBlock) {
cursor.endEditBlock();
+ if (cursorWithinSnippet)
+ d->m_snippetOverlay->updateEquivalentSelections(textCursor());
+ }
setTextCursor(cursor);
}
@@ -1389,9 +1841,13 @@ void BaseTextEditor::keyPressEvent(QKeyEvent *e)
void BaseTextEditor::maybeRequestAutoCompletion(const QChar &ch)
{
if (ch.isLetterOrNumber() || ch == QLatin1Char('_')) {
- d->m_requestAutoCompletionRevision = document()->revision();
- d->m_requestAutoCompletionPosition = position();
- d->m_requestAutoCompletionTimer->start();
+ if (CompletionSupport::instance()->isActive())
+ d->m_requestAutoCompletionTimer->stop();
+ else {
+ d->m_requestAutoCompletionRevision = document()->revision();
+ d->m_requestAutoCompletionPosition = position();
+ d->m_requestAutoCompletionTimer->start();
+ }
} else {
d->m_requestAutoCompletionTimer->stop();
emit requestAutoCompletion(editableInterface(), false);
@@ -1412,7 +1868,7 @@ void BaseTextEditor::_q_requestAutoCompletion()
void BaseTextEditor::insertCodeSnippet(const QTextCursor &cursor_arg, const QString &snippet)
{
- if ((snippet.count('$') % 2) != 0) {
+ if ((snippet.count(Snippet::kVariableDelimiter) % 2) != 0) {
qWarning() << "invalid snippet";
return;
}
@@ -1428,21 +1884,21 @@ void BaseTextEditor::insertCodeSnippet(const QTextCursor &cursor_arg, const QStr
QMap<int, int> positions;
while (pos < snippet.size()) {
- if (snippet.at(pos) != QChar::ObjectReplacementCharacter) {
+ if (snippet.at(pos) != Snippet::kVariableDelimiter) {
const int start = pos;
do { ++pos; }
- while (pos < snippet.size() && snippet.at(pos) != QChar::ObjectReplacementCharacter);
+ while (pos < snippet.size() && snippet.at(pos) != Snippet::kVariableDelimiter);
cursor.insertText(snippet.mid(start, pos - start));
} else {
// the start of a place holder.
const int start = ++pos;
for (; pos < snippet.size(); ++pos) {
- if (snippet.at(pos) == QChar::ObjectReplacementCharacter)
+ if (snippet.at(pos) == Snippet::kVariableDelimiter)
break;
}
Q_ASSERT(pos < snippet.size());
- Q_ASSERT(snippet.at(pos) == QChar::ObjectReplacementCharacter);
+ Q_ASSERT(snippet.at(pos) == Snippet::kVariableDelimiter);
const QString textToInsert = snippet.mid(start, pos - start);
@@ -1621,6 +2077,7 @@ QString BaseTextEditor::displayName() const
void BaseTextEditor::setDisplayName(const QString &title)
{
d->m_displayName = title;
+ emit changed();
}
BaseTextDocument *BaseTextEditor::baseTextDocument() const
@@ -1748,16 +2205,6 @@ bool BaseTextEditor::isParenthesesMatchingEnabled() const
return d->m_parenthesesMatchingEnabled;
}
-void BaseTextEditor::setAutoParenthesesEnabled(bool b)
-{
- d->m_autoParenthesesEnabled = b;
-}
-
-bool BaseTextEditor::isAutoParenthesesEnabled() const
-{
- return d->m_autoParenthesesEnabled;
-}
-
void BaseTextEditor::setHighlightCurrentLine(bool b)
{
d->m_highlightCurrentLine = b;
@@ -1884,6 +2331,32 @@ int BaseTextEditor::visibleWrapColumn() const
return d->m_visibleWrapColumn;
}
+void BaseTextEditor::setIndenter(Indenter *indenter)
+{
+ // clear out existing code formatter data
+ for (QTextBlock it = document()->begin(); it.isValid(); it = it.next()) {
+ TextEditor::TextBlockUserData *userData = BaseTextDocumentLayout::testUserData(it);
+ if (userData)
+ userData->setCodeFormatterData(0);
+ }
+ d->m_indenter.reset(indenter);
+}
+
+Indenter *BaseTextEditor::indenter() const
+{
+ return d->m_indenter.data();
+}
+
+void BaseTextEditor::setAutoCompleter(AutoCompleter *autoCompleter)
+{
+ d->m_autoCompleter.reset(autoCompleter);
+}
+
+AutoCompleter *BaseTextEditor::autoCompleter() const
+{
+ return d->m_autoCompleter.data();
+}
+
//--------- BaseTextEditorPrivate -----------
BaseTextEditorPrivate::BaseTextEditorPrivate()
@@ -1893,10 +2366,8 @@ BaseTextEditorPrivate::BaseTextEditorPrivate()
q(0),
m_contentsChanged(false),
m_lastCursorChangeWasInteresting(false),
- m_allowSkippingOfBlockEnd(false),
m_document(new BaseTextDocument),
m_parenthesesMatchingEnabled(false),
- m_autoParenthesesEnabled(true),
m_updateTimer(0),
m_formatRange(false),
m_parenthesesMatchingTimer(0),
@@ -1932,7 +2403,9 @@ BaseTextEditorPrivate::BaseTextEditorPrivate()
m_requestAutoCompletionRevision(0),
m_requestAutoCompletionPosition(0),
m_requestAutoCompletionTimer(0),
- m_cursorBlockNumber(-1)
+ m_cursorBlockNumber(-1),
+ m_autoCompleter(new AutoCompleter),
+ m_indenter(new Indenter)
{
}
@@ -1977,20 +2450,23 @@ void BaseTextEditorPrivate::setupDocumentSignals(BaseTextDocument *document)
}
-void BaseTextEditorPrivate::snippetCheckCursor(const QTextCursor &cursor)
+bool BaseTextEditorPrivate::snippetCheckCursor(const QTextCursor &cursor)
{
if (!m_snippetOverlay->isVisible() || m_snippetOverlay->isEmpty())
- return;
+ return false;
QTextCursor start = cursor;
start.setPosition(cursor.selectionStart());
QTextCursor end = cursor;
end.setPosition(cursor.selectionEnd());
if (!m_snippetOverlay->hasCursorInSelection(start)
- || !m_snippetOverlay->hasCursorInSelection(end)) {
+ || !m_snippetOverlay->hasCursorInSelection(end)
+ || m_snippetOverlay->hasFirstSelectionBeginMoved()) {
m_snippetOverlay->setVisible(false);
m_snippetOverlay->clear();
+ return false;
}
+ return true;
}
void BaseTextEditorPrivate::snippetTabOrBacktab(bool forward)
@@ -2000,8 +2476,8 @@ void BaseTextEditorPrivate::snippetTabOrBacktab(bool forward)
QTextCursor cursor = q->textCursor();
OverlaySelection final;
if (forward) {
- for (int i = 0; i < m_snippetOverlay->m_selections.count(); ++i){
- const OverlaySelection &selection = m_snippetOverlay->m_selections.at(i);
+ for (int i = 0; i < m_snippetOverlay->selections().count(); ++i){
+ const OverlaySelection &selection = m_snippetOverlay->selections().at(i);
if (selection.m_cursor_begin.position() >= cursor.position()
&& selection.m_cursor_end.position() > cursor.position()) {
final = selection;
@@ -2009,8 +2485,8 @@ void BaseTextEditorPrivate::snippetTabOrBacktab(bool forward)
}
}
} else {
- for (int i = m_snippetOverlay->m_selections.count()-1; i >= 0; --i){
- const OverlaySelection &selection = m_snippetOverlay->m_selections.at(i);
+ for (int i = m_snippetOverlay->selections().count()-1; i >= 0; --i){
+ const OverlaySelection &selection = m_snippetOverlay->selections().at(i);
if (selection.m_cursor_end.position() < cursor.position()) {
final = selection;
break;
@@ -2019,7 +2495,7 @@ void BaseTextEditorPrivate::snippetTabOrBacktab(bool forward)
}
if (final.m_cursor_begin.isNull())
- final = forward ? m_snippetOverlay->m_selections.first() : m_snippetOverlay->m_selections.last();
+ final = forward ? m_snippetOverlay->selections().first() : m_snippetOverlay->selections().last();
if (final.m_cursor_begin.position() == final.m_cursor_end.position()) { // empty tab stop
cursor.setPosition(final.m_cursor_end.position());
@@ -2030,7 +2506,6 @@ void BaseTextEditorPrivate::snippetTabOrBacktab(bool forward)
q->setTextCursor(cursor);
}
-
bool BaseTextEditor::viewportEvent(QEvent *event)
{
d->m_contentsChanged = false;
@@ -2363,7 +2838,9 @@ void BaseTextEditor::paintEvent(QPaintEvent *e)
qreal lineX = 0;
if (d->m_visibleWrapColumn > 0) {
- lineX = fontMetrics().averageCharWidth() * d->m_visibleWrapColumn + offset.x() + 4;
+ // Don't use QFontMetricsF::averageCharWidth here, due to it returning
+ // a fractional size even when this is not supported by the platform.
+ lineX = QFontMetricsF(font()).width(QLatin1Char('x')) * d->m_visibleWrapColumn + offset.x() + 4;
if (lineX < viewportRect.width()) {
const QBrush background = d->m_ifdefedOutFormat.background();
@@ -2372,7 +2849,8 @@ void BaseTextEditor::paintEvent(QPaintEvent *e)
const QColor col = (palette().base().color().value() > 128) ? Qt::black : Qt::white;
const QPen pen = painter.pen();
- painter.setPen(blendColors(background.color(), col, 32));
+ painter.setPen(blendColors(background.isOpaque() ? background.color() : palette().base().color(),
+ col, 32));
painter.drawLine(QPointF(lineX, er.top()), QPointF(lineX, er.bottom()));
painter.setPen(pen);
}
@@ -2414,13 +2892,22 @@ void BaseTextEditor::paintEvent(QPaintEvent *e)
int count = d->m_highlightBlocksInfo.count();
if (count) {
- QRectF rr = r;
- rr.setWidth(viewport()->width());
- if (lineX > 0)
- rr.setRight(qMin(lineX, rr.right()));
for (int i = 0; i <= depth; ++i) {
+ const QColor &blendedColor = calcBlendColor(baseColor, i, count);
int vi = i > 0 ? d->m_highlightBlocksInfo.visualIndent.at(i-1) : 0;
- painter.fillRect(rr.adjusted(vi, 0, -8*i, 0), calcBlendColor(baseColor, i, count));
+ QRectF oneRect = r;
+ oneRect.setWidth(viewport()->width());
+ oneRect.adjust(vi, 0, -8*i, 0);
+ if (oneRect.left() >= oneRect.right())
+ continue;
+ if (lineX > 0 && oneRect.left() < lineX && oneRect.right() > lineX) {
+ QRectF otherRect = r;
+ otherRect.setLeft(lineX + 1);
+ otherRect.setRight(oneRect.right());
+ oneRect.setRight(lineX - 1);
+ painter.fillRect(otherRect, blendedColor);
+ }
+ painter.fillRect(oneRect, blendedColor);
}
}
offsetFP.ry() += r.height();
@@ -2436,19 +2923,6 @@ void BaseTextEditor::paintEvent(QPaintEvent *e)
}
}
- if (!d->m_findScopeStart.isNull() && d->m_findScopeVerticalBlockSelectionFirstColumn < 0) {
-
- TextEditorOverlay *overlay = new TextEditorOverlay(this);
- overlay->addOverlaySelection(d->m_findScopeStart.position(),
- d->m_findScopeEnd.position(),
- d->m_searchScopeFormat.foreground().color(),
- d->m_searchScopeFormat.background().color(),
- TextEditorOverlay::ExpandBegin);
- overlay->setAlpha(false);
- overlay->paint(&painter, e->rect());
- delete overlay;
- }
-
int blockSelectionIndex = -1;
if (d->m_inBlockSelectionMode
@@ -2493,11 +2967,40 @@ void BaseTextEditor::paintEvent(QPaintEvent *e)
} // end first pass
+ { // extra pass for ifdefed out blocks
+ QTextBlock blockIDO = block;
+ QPointF offsetIDO = offset;
+ while (blockIDO.isValid()) {
+
+ QRectF r = blockBoundingRect(blockIDO).translated(offsetIDO);
+
+ if (r.bottom() >= er.top() && r.top() <= er.bottom()) {
+ if (BaseTextDocumentLayout::ifdefedOut(blockIDO)) {
+ QRectF rr = r;
+ rr.setRight(viewportRect.width() - offset.x());
+ if (lineX > 0)
+ rr.setRight(qMin(lineX, rr.right()));
+ painter.fillRect(rr, d->m_ifdefedOutFormat.background());
+ }
+ }
+ offsetIDO.ry() += r.height();
+
+ if (offsetIDO.y() > viewportRect.height())
+ break;
+
+ blockIDO = blockIDO.next();
+ if (!blockIDO.isVisible()) {
+ // invisible blocks do have zero line count
+ blockIDO = doc->findBlockByLineNumber(blockIDO.firstLineNumber());
+ }
+
+ }
+ }
+
// possible extra pass for the block selection find scope
if (!d->m_findScopeStart.isNull() && d->m_findScopeVerticalBlockSelectionFirstColumn >= 0) {
QTextBlock blockFS = block;
QPointF offsetFS = offset;
-
while (blockFS.isValid()) {
QRectF r = blockBoundingRect(blockFS).translated(offsetFS);
@@ -2559,6 +3062,19 @@ void BaseTextEditor::paintEvent(QPaintEvent *e)
}
}
+ if (!d->m_findScopeStart.isNull() && d->m_findScopeVerticalBlockSelectionFirstColumn < 0) {
+
+ TextEditorOverlay *overlay = new TextEditorOverlay(this);
+ overlay->addOverlaySelection(d->m_findScopeStart.position(),
+ d->m_findScopeEnd.position(),
+ d->m_searchScopeFormat.foreground().color(),
+ d->m_searchScopeFormat.background().color(),
+ TextEditorOverlay::ExpandBegin);
+ overlay->setAlpha(false);
+ overlay->paint(&painter, e->rect());
+ delete overlay;
+ }
+
d->m_searchResultOverlay->fill(&painter,
@@ -2572,14 +3088,6 @@ void BaseTextEditor::paintEvent(QPaintEvent *e)
if (r.bottom() >= er.top() && r.top() <= er.bottom()) {
- if (BaseTextDocumentLayout::ifdefedOut(block)) {
- QRectF rr = r;
- rr.setRight(viewportRect.width() - offset.x());
- if (lineX > 0)
- rr.setRight(qMin(lineX, rr.right()));
- painter.fillRect(rr, d->m_ifdefedOutFormat.background());
- }
-
QTextLayout *layout = block.layout();
QTextOption option = layout->textOption();
@@ -3895,59 +4403,76 @@ void BaseTextEditor::handleHomeKey(bool anchor)
setTextCursor(cursor);
}
-
-#define SET_AND_RETURN(cursor) setTextCursor(cursor); return // make cursor visible and reset vertical x movement
void BaseTextEditor::handleBackspaceKey()
{
QTextCursor cursor = textCursor();
int pos = cursor.position();
QTC_ASSERT(!cursor.hasSelection(), return);
+ bool cursorWithinSnippet = false;
if (d->m_snippetOverlay->isVisible()) {
QTextCursor snippetCursor = cursor;
snippetCursor.movePosition(QTextCursor::Left);
- d->snippetCheckCursor(snippetCursor);
+ cursorWithinSnippet = d->snippetCheckCursor(snippetCursor);
}
const TextEditor::TabSettings &tabSettings = d->m_document->tabSettings();
- if (tabSettings.m_autoIndent && autoBackspace(cursor))
+ if (tabSettings.m_autoIndent && d->m_autoCompleter->autoBackspace(cursor))
return;
+ bool handled = false;
if (!tabSettings.m_smartBackspace) {
+ if (cursorWithinSnippet)
+ cursor.beginEditBlock();
cursor.deletePreviousChar();
- SET_AND_RETURN(cursor);
+ handled = true;
+ } else {
+ QTextBlock currentBlock = cursor.block();
+ int positionInBlock = pos - currentBlock.position();
+ const QString blockText = currentBlock.text();
+ if (cursor.atBlockStart() || tabSettings.firstNonSpace(blockText) < positionInBlock) {
+ if (cursorWithinSnippet)
+ cursor.beginEditBlock();
+ cursor.deletePreviousChar();
+ handled = true;
+ } else {
+ int previousIndent = 0;
+ const int indent = tabSettings.columnAt(blockText, positionInBlock);
+
+ for (QTextBlock previousNonEmptyBlock = currentBlock.previous();
+ previousNonEmptyBlock.isValid();
+ previousNonEmptyBlock = previousNonEmptyBlock.previous()) {
+ QString previousNonEmptyBlockText = previousNonEmptyBlock.text();
+ if (previousNonEmptyBlockText.trimmed().isEmpty())
+ continue;
+ previousIndent =
+ tabSettings.columnAt(previousNonEmptyBlockText,
+ tabSettings.firstNonSpace(previousNonEmptyBlockText));
+ if (previousIndent < indent) {
+ cursor.beginEditBlock();
+ cursor.setPosition(currentBlock.position(), QTextCursor::KeepAnchor);
+ cursor.insertText(tabSettings.indentationString(previousNonEmptyBlockText));
+ cursor.endEditBlock();
+ handled = true;
+ break;
+ }
+ }
+ }
}
- QTextBlock currentBlock = cursor.block();
- int positionInBlock = pos - currentBlock.position();
- const QString blockText = currentBlock.text();
- if (cursor.atBlockStart() || tabSettings.firstNonSpace(blockText) < positionInBlock) {
+ if (!handled) {
+ if (cursorWithinSnippet)
+ cursor.beginEditBlock();
cursor.deletePreviousChar();
- SET_AND_RETURN(cursor);
}
- int previousIndent = 0;
- const int indent = tabSettings.columnAt(blockText, positionInBlock);
-
- for (QTextBlock previousNonEmptyBlock = currentBlock.previous();
- previousNonEmptyBlock.isValid();
- previousNonEmptyBlock = previousNonEmptyBlock.previous()) {
- QString previousNonEmptyBlockText = previousNonEmptyBlock.text();
- if (previousNonEmptyBlockText.trimmed().isEmpty())
- continue;
- previousIndent = tabSettings.columnAt(previousNonEmptyBlockText,
- tabSettings.firstNonSpace(previousNonEmptyBlockText));
- if (previousIndent < indent) {
- cursor.beginEditBlock();
- cursor.setPosition(currentBlock.position(), QTextCursor::KeepAnchor);
- cursor.insertText(tabSettings.indentationString(previousNonEmptyBlockText));
- cursor.endEditBlock();
- SET_AND_RETURN(cursor);
- }
+ if (cursorWithinSnippet) {
+ cursor.endEditBlock();
+ d->m_snippetOverlay->updateEquivalentSelections(cursor);
}
- cursor.deletePreviousChar();
- SET_AND_RETURN(cursor);
+
+ setTextCursor(cursor);
}
void BaseTextEditor::wheelEvent(QWheelEvent *e)
@@ -3980,320 +4505,23 @@ void BaseTextEditor::zoomReset()
emit requestZoomReset();
}
-bool BaseTextEditor::isElectricCharacter(QChar) const
-{
- return false;
-}
-
void BaseTextEditor::indentInsertedText(const QTextCursor &tc)
{
indent(tc.document(), tc, QChar::Null);
}
-void BaseTextEditor::countBracket(QChar open, QChar close, QChar c, int *errors, int *stillopen)
-{
- if (c == open)
- ++*stillopen;
- else if (c == close)
- --*stillopen;
-
- if (*stillopen < 0) {
- *errors += -1 * (*stillopen);
- *stillopen = 0;
- }
-}
-
-void BaseTextEditor::countBrackets(QTextCursor cursor, int from, int end, QChar open, QChar close, int *errors, int *stillopen)
-{
- cursor.setPosition(from);
- QTextBlock block = cursor.block();
- while (block.isValid() && block.position() < end) {
- TextEditor::Parentheses parenList = TextEditor::BaseTextDocumentLayout::parentheses(block);
- if (!parenList.isEmpty() && !TextEditor::BaseTextDocumentLayout::ifdefedOut(block)) {
- for (int i = 0; i < parenList.count(); ++i) {
- TextEditor::Parenthesis paren = parenList.at(i);
- int position = block.position() + paren.pos;
- if (position < from || position >= end)
- continue;
- countBracket(open, close, paren.chr, errors, stillopen);
- }
- }
- block = block.next();
- }
-}
-
-bool BaseTextEditor::contextAllowsAutoParentheses(const QTextCursor &cursor,
- const QString &textToInsert) const
-{
- Q_UNUSED(cursor);
- Q_UNUSED(textToInsert);
- return false;
-}
-
-bool BaseTextEditor::contextAllowsElectricCharacters(const QTextCursor &cursor) const
-{
- return contextAllowsAutoParentheses(cursor);
-}
-
-bool BaseTextEditor::isInComment(const QTextCursor &cursor) const
-{
- Q_UNUSED(cursor);
- return false;
-}
-
-QString BaseTextEditor::insertMatchingBrace(const QTextCursor &tc, const QString &text,
- QChar la, int *skippedChars) const
-{
- Q_UNUSED(tc);
- Q_UNUSED(text);
- Q_UNUSED(la);
- Q_UNUSED(skippedChars);
- return QString();
-}
-
-QString BaseTextEditor::insertParagraphSeparator(const QTextCursor &tc) const
-{
- Q_UNUSED(tc);
- return QString();
-}
-
-QString BaseTextEditor::autoComplete(QTextCursor &cursor, const QString &textToInsert) const
-{
- const bool checkBlockEnd = d->m_allowSkippingOfBlockEnd;
- d->m_allowSkippingOfBlockEnd = false; // consume blockEnd.
-
- if (!d->m_autoParenthesesEnabled)
- return QString();
-
- if (!contextAllowsAutoParentheses(cursor, textToInsert))
- return QString();
-
- const QString text = textToInsert;
- const QChar lookAhead = characterAt(cursor.selectionEnd());
-
- const QChar character = textToInsert.at(0);
- const QString parentheses = QLatin1String("()");
- const QString brackets = QLatin1String("[]");
- if (parentheses.contains(character) || brackets.contains(character)) {
- QTextCursor tmp= cursor;
- bool foundBlockStart = TextEditor::TextBlockUserData::findPreviousBlockOpenParenthesis(&tmp);
- int blockStart = foundBlockStart ? tmp.position() : 0;
- tmp = cursor;
- bool foundBlockEnd = TextEditor::TextBlockUserData::findNextBlockClosingParenthesis(&tmp);
- int blockEnd = foundBlockEnd ? tmp.position() : (cursor.document()->characterCount() - 1);
- const QChar openChar = parentheses.contains(character) ? QLatin1Char('(') : QLatin1Char('[');
- const QChar closeChar = parentheses.contains(character) ? QLatin1Char(')') : QLatin1Char(']');
-
- int errors = 0;
- int stillopen = 0;
- countBrackets(cursor, blockStart, blockEnd, openChar, closeChar, &errors, &stillopen);
- int errorsBeforeInsertion = errors + stillopen;
- errors = 0;
- stillopen = 0;
- countBrackets(cursor, blockStart, cursor.position(), openChar, closeChar, &errors, &stillopen);
- countBracket(openChar, closeChar, character, &errors, &stillopen);
- countBrackets(cursor, cursor.position(), blockEnd, openChar, closeChar, &errors, &stillopen);
- int errorsAfterInsertion = errors + stillopen;
- if (errorsAfterInsertion < errorsBeforeInsertion)
- return QString(); // insertion fixes parentheses or bracket errors, do not auto complete
- }
-
- int skippedChars = 0;
- const QString autoText = insertMatchingBrace(cursor, text, lookAhead, &skippedChars);
-
- if (checkBlockEnd && textToInsert.at(0) == QLatin1Char('}')) {
- if (textToInsert.length() > 1)
- qWarning() << "*** handle event compression";
-
- int startPos = cursor.selectionEnd(), pos = startPos;
- while (characterAt(pos).isSpace())
- ++pos;
-
- if (characterAt(pos) == QLatin1Char('}'))
- skippedChars += (pos - startPos) + 1;
- }
-
- if (skippedChars) {
- const int pos = cursor.position();
- cursor.setPosition(pos + skippedChars);
- cursor.setPosition(pos, QTextCursor::KeepAnchor);
- }
-
- return autoText;
-}
-
-bool BaseTextEditor::autoBackspace(QTextCursor &cursor)
-{
- d->m_allowSkippingOfBlockEnd = false;
-
- if (!d->m_autoParenthesesEnabled)
- return false;
-
- int pos = cursor.position();
- if (pos == 0)
- return false;
- QTextCursor c = cursor;
- c.setPosition(pos - 1);
-
- const QChar lookAhead = characterAt(pos);
- const QChar lookBehind = characterAt(pos - 1);
- const QChar lookFurtherBehind = characterAt(pos - 2);
-
- const QChar character = lookBehind;
- if (character == QLatin1Char('(') || character == QLatin1Char('[')) {
- QTextCursor tmp = cursor;
- TextEditor::TextBlockUserData::findPreviousBlockOpenParenthesis(&tmp);
- int blockStart = tmp.isNull() ? 0 : tmp.position();
- tmp = cursor;
- TextEditor::TextBlockUserData::findNextBlockClosingParenthesis(&tmp);
- int blockEnd = tmp.isNull() ? (cursor.document()->characterCount()-1) : tmp.position();
- QChar openChar = character;
- QChar closeChar = (character == QLatin1Char('(')) ? QLatin1Char(')') : QLatin1Char(']');
-
- int errors = 0;
- int stillopen = 0;
- countBrackets(cursor, blockStart, blockEnd, openChar, closeChar, &errors, &stillopen);
- int errorsBeforeDeletion = errors + stillopen;
- errors = 0;
- stillopen = 0;
- countBrackets(cursor, blockStart, pos - 1, openChar, closeChar, &errors, &stillopen);
- countBrackets(cursor, pos, blockEnd, openChar, closeChar, &errors, &stillopen);
- int errorsAfterDeletion = errors + stillopen;
-
- if (errorsAfterDeletion < errorsBeforeDeletion)
- return false; // insertion fixes parentheses or bracket errors, do not auto complete
- }
-
- // ### this code needs to be generalized
- if ((lookBehind == QLatin1Char('(') && lookAhead == QLatin1Char(')'))
- || (lookBehind == QLatin1Char('[') && lookAhead == QLatin1Char(']'))
- || (lookBehind == QLatin1Char('"') && lookAhead == QLatin1Char('"')
- && lookFurtherBehind != QLatin1Char('\\'))
- || (lookBehind == QLatin1Char('\'') && lookAhead == QLatin1Char('\'')
- && lookFurtherBehind != QLatin1Char('\\'))) {
- if (! isInComment(c)) {
- cursor.beginEditBlock();
- cursor.deleteChar();
- cursor.deletePreviousChar();
- cursor.endEditBlock();
- return true;
- }
- }
- return false;
-}
-
-int BaseTextEditor::paragraphSeparatorAboutToBeInserted(QTextCursor &cursor)
-{
- if (!d->m_autoParenthesesEnabled)
- return 0;
-
- if (characterAt(cursor.position() - 1) != QLatin1Char('{'))
- return 0;
-
- if (!contextAllowsAutoParentheses(cursor))
- return 0;
-
- // verify that we indeed do have an extra opening brace in the document
- int braceDepth = BaseTextDocumentLayout::braceDepth(document()->lastBlock());
-
- if (braceDepth <= 0)
- return 0; // braces are all balanced or worse, no need to do anything
-
- // we have an extra brace , let's see if we should close it
-
-
- /* verify that the next block is not further intended compared to the current block.
- This covers the following case:
-
- if (condition) {|
- statement;
- */
- const TabSettings &ts = tabSettings();
- QTextBlock block = cursor.block();
- int indentation = ts.indentationColumn(block.text());
-
- if (block.next().isValid()) { // not the last block
- block = block.next();
- //skip all empty blocks
- while (block.isValid() && ts.onlySpace(block.text()))
- block = block.next();
- if (block.isValid()
- && ts.indentationColumn(block.text()) > indentation)
- return 0;
- }
-
- int pos = cursor.position();
-
- const QString textToInsert = insertParagraphSeparator(cursor);
-
- cursor.insertText(textToInsert);
- cursor.setPosition(pos);
- if (ts.m_autoIndent) {
- cursor.insertBlock();
- indent(document(), cursor, QChar::Null);
- } else {
- QString previousBlockText = cursor.block().text();
- cursor.insertBlock();
- cursor.insertText(ts.indentationString(previousBlockText));
- }
- cursor.setPosition(pos);
- d->m_allowSkippingOfBlockEnd = true;
- return 1;
-}
-
-void BaseTextEditor::indentBlock(QTextDocument *, QTextBlock, QChar)
-{
-}
-
void BaseTextEditor::indent(QTextDocument *doc, const QTextCursor &cursor, QChar typedChar)
{
maybeClearSomeExtraSelections(cursor);
- if (cursor.hasSelection()) {
- QTextBlock block = doc->findBlock(cursor.selectionStart());
- const QTextBlock end = doc->findBlock(cursor.selectionEnd()).next();
- do {
- indentBlock(doc, block, typedChar);
- block = block.next();
- } while (block.isValid() && block != end);
- } else {
- indentBlock(doc, cursor.block(), typedChar);
- }
+ d->m_indenter->indent(doc, cursor, typedChar, this);
}
void BaseTextEditor::reindent(QTextDocument *doc, const QTextCursor &cursor)
{
maybeClearSomeExtraSelections(cursor);
- if (cursor.hasSelection()) {
- QTextBlock block = doc->findBlock(cursor.selectionStart());
- const QTextBlock end = doc->findBlock(cursor.selectionEnd()).next();
-
- const TabSettings &ts = d->m_document->tabSettings();
-
- // skip empty blocks
- while (block.isValid() && block != end) {
- QString bt = block.text();
- if (ts.firstNonSpace(bt) < bt.size())
- break;
- indentBlock(doc, block, QChar::Null);
- block = block.next();
- }
-
- int previousIndentation = ts.indentationColumn(block.text());
- indentBlock(doc, block, QChar::Null);
- int currentIndentation = ts.indentationColumn(block.text());
- int delta = currentIndentation - previousIndentation;
-
- block = block.next();
- while (block.isValid() && block != end) {
- ts.reindentLine(block, delta);
- block = block.next();
- }
- } else {
- indentBlock(doc, cursor.block(), QChar::Null);
- }
+ d->m_indenter->reindent(doc, cursor, this);
}
-
BaseTextEditor::Link BaseTextEditor::findLinkAt(const QTextCursor &, bool)
{
return Link();
@@ -4312,7 +4540,9 @@ bool BaseTextEditor::openLink(const Link &link)
return true;
}
- return openEditorAt(link.fileName, link.line, link.column);
+ return openEditorAt(link.fileName, link.line, link.column, QString(),
+ Core::EditorManager::IgnoreNavigationHistory
+ | Core::EditorManager::ModeSwitch);
}
void BaseTextEditor::updateLink(QMouseEvent *e)
@@ -4805,6 +5035,7 @@ void BaseTextEditor::setExtraSelections(ExtraSelectionKind kind, const QList<QTe
selection.format.background().color(),
TextEditorOverlay::ExpandBegin);
}
+ d->m_snippetOverlay->mapEquivalentSelections();
d->m_snippetOverlay->setVisible(!d->m_snippetOverlay->isEmpty());
} else {
QList<QTextEdit::ExtraSelection> all;
@@ -5173,7 +5404,8 @@ void BaseTextEditor::setStorageSettings(const StorageSettings &storageSettings)
void BaseTextEditor::setCompletionSettings(const TextEditor::CompletionSettings &completionSettings)
{
- setAutoParenthesesEnabled(completionSettings.m_autoInsertBrackets);
+ d->m_autoCompleter->setAutoParenthesesEnabled(completionSettings.m_autoInsertBrackets);
+ d->m_autoCompleter->setSurroundWithEnabled(completionSettings.m_autoInsertBrackets);
}
void BaseTextEditor::fold()
@@ -5524,7 +5756,7 @@ BaseTextEditorEditable::BaseTextEditorEditable(BaseTextEditor *editor)
QWidget *w = new QWidget;
l->setMargin(0);
l->setContentsMargins(5, 0, 5, 0);
- l->addStretch(0);
+ // l->addStretch(0);
l->addWidget(m_cursorPositionLabel);
w->setLayout(l);
@@ -5660,10 +5892,10 @@ QString BaseTextEditorEditable::contextHelpId() const
void BaseTextEditor::setRefactorMarkers(const Internal::RefactorMarkers &markers)
{
- foreach (const Internal::RefactorMarker &marker, d->m_refactorOverlay->markers())
+ foreach (const RefactorMarker &marker, d->m_refactorOverlay->markers())
requestBlockUpdate(marker.cursor.block());
d->m_refactorOverlay->setMarkers(markers);
- foreach (const Internal::RefactorMarker &marker, markers)
+ foreach (const RefactorMarker &marker, markers)
requestBlockUpdate(marker.cursor.block());
}
diff --git a/src/plugins/texteditor/basetexteditor.h b/src/plugins/texteditor/basetexteditor.h
index e3eba39bda..174dadafcb 100644
--- a/src/plugins/texteditor/basetexteditor.h
+++ b/src/plugins/texteditor/basetexteditor.h
@@ -54,36 +54,13 @@ namespace Utils {
namespace TextEditor {
class TabSettings;
+class RefactorOverlay;
+struct RefactorMarker;
namespace Internal {
class BaseTextEditorPrivate;
class TextEditorOverlay;
- class RefactorOverlay;
- struct RefactorMarker;
typedef QList<RefactorMarker> RefactorMarkers;
-
- class TEXTEDITOR_EXPORT BaseTextBlockSelection
- {
- public:
-
- bool isValid() const{ return !firstBlock.isNull() && !lastBlock.isNull(); }
- void clear() { firstBlock = lastBlock = QTextCursor(); }
-
- QTextCursor firstBlock; // defines the first block
- QTextCursor lastBlock; // defines the last block
- int firstVisualColumn; // defines the first visual column of the selection
- int lastVisualColumn; // defines the last visual column of the selection
- enum Anchor {TopLeft = 0, TopRight, BottomLeft, BottomRight} anchor;
- BaseTextBlockSelection():firstVisualColumn(0), lastVisualColumn(0), anchor(BottomRight){}
- void moveAnchor(int blockNumber, int visualColumn);
- inline int anchorColumnNumber() const { return (anchor % 2) ? lastVisualColumn : firstVisualColumn; }
- inline int anchorBlockNumber() const {
- return (anchor <= TopRight ? firstBlock.blockNumber() : lastBlock.blockNumber()); }
- QTextCursor selection(const TabSettings &ts) const;
- void fromSelection(const TabSettings &ts, const QTextCursor &selection);
- };
-
-
}
class ITextMarkable;
@@ -95,6 +72,8 @@ class BehaviorSettings;
class CompletionSettings;
class DisplaySettings;
class StorageSettings;
+class Indenter;
+class AutoCompleter;
class TEXTEDITOR_EXPORT BaseTextEditorAnimator : public QObject
{
@@ -193,9 +172,6 @@ public:
void setParenthesesMatchingEnabled(bool b);
bool isParenthesesMatchingEnabled() const;
- void setAutoParenthesesEnabled(bool b);
- bool isAutoParenthesesEnabled() const;
-
void setHighlightCurrentLine(bool b);
bool highlightCurrentLine() const;
@@ -249,6 +225,12 @@ public:
QRegion translatedLineRegion(int lineStart, int lineEnd) const;
+ void setIndenter(Indenter *indenter);
+ Indenter *indenter() const;
+
+ void setAutoCompleter(AutoCompleter *autoCompleter);
+ AutoCompleter *autoCompleter() const;
+
public slots:
void setDisplayName(const QString &title);
@@ -287,6 +269,10 @@ public slots:
void gotoPreviousWordWithSelection();
void gotoNextWord();
void gotoNextWordWithSelection();
+ void gotoPreviousWordCamelCase();
+ void gotoPreviousWordCamelCaseWithSelection();
+ void gotoNextWordCamelCase();
+ void gotoNextWordCamelCaseWithSelection();
void selectBlockUp();
void selectBlockDown();
@@ -355,7 +341,7 @@ private:
Internal::BaseTextEditorPrivate *d;
friend class Internal::BaseTextEditorPrivate;
friend class Internal::TextEditorOverlay;
- friend class Internal::RefactorOverlay;
+ friend class RefactorOverlay;
public:
QWidget *extraArea() const;
@@ -391,7 +377,7 @@ public:
void setRefactorMarkers(const Internal::RefactorMarkers &markers);
signals:
- void refactorMarkerClicked(const TextEditor::Internal::RefactorMarker &marker);
+ void refactorMarkerClicked(const TextEditor::RefactorMarker &marker);
public:
@@ -436,42 +422,10 @@ protected:
void dragEnterEvent(QDragEnterEvent *e);
public:
- // Returns true if key triggers an indent.
- virtual bool isElectricCharacter(QChar ch) const;
-
void indentInsertedText(const QTextCursor &tc);
+ void indent(QTextDocument *doc, const QTextCursor &cursor, QChar typedChar);
+ void reindent(QTextDocument *doc, const QTextCursor &cursor);
- // Returns the text to complete at the cursor position, or an empty string
- virtual QString autoComplete(QTextCursor &cursor, const QString &text) const;
- // Handles backspace. When returning true, backspace processing is stopped
- virtual bool autoBackspace(QTextCursor &cursor);
- // Hook to insert special characters on enter. Returns the number of extra blocks inserted.
- virtual int paragraphSeparatorAboutToBeInserted(QTextCursor &cursor);
- // Indent a text block based on previous line. Default does nothing
- virtual void indentBlock(QTextDocument *doc, QTextBlock block, QChar typedChar);
- // Indent at cursor. Calls indentBlock for selection or current line.
- virtual void indent(QTextDocument *doc, const QTextCursor &cursor, QChar typedChar);
- // Reindent at cursor. Selection will be adjusted according to the indentation change of the first block
- virtual void reindent(QTextDocument *doc, const QTextCursor &cursor);
-
- virtual bool contextAllowsAutoParentheses(const QTextCursor &cursor, const QString &textToInsert = QString()) const;
- virtual bool contextAllowsElectricCharacters(const QTextCursor &cursor) const;
-
- // Returns true if the cursor is inside a comment.
- virtual bool isInComment(const QTextCursor &cursor) const;
-
- virtual QString insertMatchingBrace(const QTextCursor &tc, const QString &text, QChar la, int *skippedChars) const;
-
- // Returns the text that needs to be inserted
- virtual QString insertParagraphSeparator(const QTextCursor &tc) const;
-
-protected:
- static void countBracket(QChar open, QChar close, QChar c, int *errors, int *stillopen);
-
- static void countBrackets(QTextCursor cursor, int from, int end, QChar open, QChar close,
- int *errors, int *stillopen);
-
-public:
struct Link
{
Link(const QString &fileName = QString(),
@@ -562,6 +516,11 @@ private:
void universalHelper(); // test function for development
+ bool cursorMoveKeyEvent(QKeyEvent *e);
+ bool camelCaseRight(QTextCursor &cursor, QTextCursor::MoveMode mode);
+ bool camelCaseLeft(QTextCursor &cursor, QTextCursor::MoveMode mode);
+
+
private slots:
// auto completion
void _q_requestAutoCompletion();
@@ -597,11 +556,11 @@ public:
return e->open(fileName);
}
inline QString displayName() const { return e->displayName(); }
- inline void setDisplayName(const QString &title) { e->setDisplayName(title); }
+ inline void setDisplayName(const QString &title) { e->setDisplayName(title); emit changed(); }
inline QByteArray saveState() const { return e->saveState(); }
inline bool restoreState(const QByteArray &state) { return e->restoreState(state); }
- QWidget *toolBar();
+ virtual QWidget *toolBar();
// ITextEditor
int find(const QString &string) const;
@@ -652,4 +611,6 @@ private:
} // namespace TextEditor
+Q_DECLARE_METATYPE(TextEditor::BaseTextEditor::Link)
+
#endif // BASETEXTEDITOR_H
diff --git a/src/plugins/texteditor/basetexteditor_p.h b/src/plugins/texteditor/basetexteditor_p.h
index ea8a80b8e8..4aad699ca5 100644
--- a/src/plugins/texteditor/basetexteditor_p.h
+++ b/src/plugins/texteditor/basetexteditor_p.h
@@ -46,6 +46,7 @@
#include <QtCore/QBasicTimer>
#include <QtCore/QSharedData>
#include <QtCore/QPointer>
+#include <QtCore/QScopedPointer>
#include <QtGui/QPixmap>
#include <QtGui/QTextEdit>
@@ -57,6 +58,27 @@ class TextEditorActionHandler;
namespace Internal {
+class TEXTEDITOR_EXPORT BaseTextBlockSelection
+{
+public:
+
+ bool isValid() const{ return !firstBlock.isNull() && !lastBlock.isNull(); }
+ void clear() { firstBlock = lastBlock = QTextCursor(); }
+
+ QTextCursor firstBlock; // defines the first block
+ QTextCursor lastBlock; // defines the last block
+ int firstVisualColumn; // defines the first visual column of the selection
+ int lastVisualColumn; // defines the last visual column of the selection
+ enum Anchor {TopLeft = 0, TopRight, BottomLeft, BottomRight} anchor;
+ BaseTextBlockSelection():firstVisualColumn(0), lastVisualColumn(0), anchor(BottomRight){}
+ void moveAnchor(int blockNumber, int visualColumn);
+ inline int anchorColumnNumber() const { return (anchor % 2) ? lastVisualColumn : firstVisualColumn; }
+ inline int anchorBlockNumber() const {
+ return (anchor <= TopRight ? firstBlock.blockNumber() : lastBlock.blockNumber()); }
+ QTextCursor selection(const TabSettings &ts) const;
+ void fromSelection(const TabSettings &ts, const QTextCursor &selection);
+};
+
//========== Pointers with reference count ==========
template <class T> class QRefCountData : public QSharedData
@@ -162,7 +184,6 @@ public:
BaseTextEditor *q;
bool m_contentsChanged;
bool m_lastCursorChangeWasInteresting;
- bool m_allowSkippingOfBlockEnd;
QList<QTextEdit::ExtraSelection> m_syntaxHighlighterSelections;
QTextEdit::ExtraSelection m_lineSelection;
@@ -173,7 +194,6 @@ public:
QString m_displayName;
bool m_parenthesesMatchingEnabled;
- bool m_autoParenthesesEnabled;
QTimer *m_updateTimer;
Utils::ChangeSet m_changeSet;
@@ -199,7 +219,7 @@ public:
TextEditorOverlay *m_overlay;
TextEditorOverlay *m_snippetOverlay;
TextEditorOverlay *m_searchResultOverlay;
- void snippetCheckCursor(const QTextCursor &cursor);
+ bool snippetCheckCursor(const QTextCursor &cursor);
void snippetTabOrBacktab(bool forward);
QTextCharFormat m_occurrencesFormat;
QTextCharFormat m_occurrenceRenameFormat;
@@ -275,6 +295,9 @@ public:
QPointer<BaseTextEditorAnimator> m_animator;
int m_cursorBlockNumber;
+
+ QScopedPointer<AutoCompleter> m_autoCompleter;
+ QScopedPointer<Indenter> m_indenter;
};
} // namespace Internal
diff --git a/src/plugins/texteditor/basetextmark.cpp b/src/plugins/texteditor/basetextmark.cpp
index 52130ea2c5..6097f20975 100644
--- a/src/plugins/texteditor/basetextmark.cpp
+++ b/src/plugins/texteditor/basetextmark.cpp
@@ -32,16 +32,52 @@
**************************************************************************/
#include "basetextmark.h"
-
+#include "itexteditor.h"
#include "basetextdocument.h"
#include <coreplugin/editormanager/editormanager.h>
#include <extensionsystem/pluginmanager.h>
#include <QtCore/QTimer>
+#include <QtGui/QIcon>
+
+namespace TextEditor {
+namespace Internal {
+
+class InternalMark : public TextEditor::ITextMark
+{
+public:
+ explicit InternalMark(BaseTextMark *parent) : m_parent(parent) {}
+
+ virtual QIcon icon() const
+ {
+ return m_parent->icon();
+ }
+
+ virtual void updateLineNumber(int lineNumber)
+ {
+ return m_parent->updateLineNumber(lineNumber);
+ }
+
+ virtual void updateBlock(const QTextBlock &block)
+ {
+ return m_parent->updateBlock(block);
+ }
+
+ virtual void removedFromEditor()
+ {
+ m_parent->childRemovedFromEditor(this);
+ }
+
+ virtual void documentClosing()
+ {
+ m_parent->documentClosingFor(this);
+ }
+private:
+ BaseTextMark *m_parent;
+};
-using namespace TextEditor;
-using namespace TextEditor::Internal;
+} // namespace Internal
BaseTextMark::BaseTextMark(const QString &filename, int line)
: m_markableInterface(0)
@@ -84,7 +120,7 @@ void BaseTextMark::editorOpened(Core::IEditor *editor)
if (ITextEditor *textEditor = qobject_cast<ITextEditor *>(editor)) {
if (m_markableInterface == 0) { // We aren't added to something
m_markableInterface = textEditor->markableInterface();
- m_internalMark = new InternalMark(this);
+ m_internalMark = new Internal::InternalMark(this);
if (m_markableInterface->addMark(m_internalMark, m_line)) {
// Handle reload of text documents, readding the mark as necessary
@@ -107,13 +143,13 @@ void BaseTextMark::documentReloaded()
return;
m_markableInterface = doc->documentMarker();
- m_internalMark = new InternalMark(this);
+ m_internalMark = new Internal::InternalMark(this);
if (!m_markableInterface->addMark(m_internalMark, m_line))
removeInternalMark();
}
-void BaseTextMark::childRemovedFromEditor(InternalMark *mark)
+void BaseTextMark::childRemovedFromEditor(Internal::InternalMark *mark)
{
Q_UNUSED(mark)
// m_internalMark was removed from the editor
@@ -121,7 +157,7 @@ void BaseTextMark::childRemovedFromEditor(InternalMark *mark)
removedFromEditor();
}
-void BaseTextMark::documentClosingFor(InternalMark *mark)
+void BaseTextMark::documentClosingFor(Internal::InternalMark *mark)
{
Q_UNUSED(mark)
removeInternalMark();
@@ -159,3 +195,4 @@ void BaseTextMark::moveMark(const QString & /* filename */, int /* line */)
foreach (Core::IEditor *editor, em->openedEditors())
editorOpened(editor);
}
+} // namespace TextEditor
diff --git a/src/plugins/texteditor/basetextmark.h b/src/plugins/texteditor/basetextmark.h
index 5426d74ecb..544ab6c2a6 100644
--- a/src/plugins/texteditor/basetextmark.h
+++ b/src/plugins/texteditor/basetextmark.h
@@ -34,8 +34,17 @@
#ifndef BASETEXTMARK_H
#define BASETEXTMARK_H
-#include "itexteditor.h"
-#include <QtGui/QIcon>
+#include "texteditor_global.h"
+#include <QtCore/QObject>
+
+QT_BEGIN_NAMESPACE
+class QIcon;
+class QTextBlock;
+QT_END_NAMESPACE
+
+namespace Core {
+class IEditor;
+}
namespace TextEditor {
@@ -51,8 +60,8 @@ class TEXTEDITOR_EXPORT BaseTextMark : public QObject
Q_OBJECT
public:
- BaseTextMark(const QString &filename, int line);
- ~BaseTextMark();
+ explicit BaseTextMark(const QString &filename, int line);
+ virtual ~BaseTextMark();
// return your icon here
virtual QIcon icon() const = 0;
@@ -92,49 +101,6 @@ private:
bool m_init;
};
-namespace Internal {
-
-class InternalMark : public ITextMark
-{
-public:
- InternalMark(BaseTextMark *parent)
- : m_parent(parent)
- {
- }
-
- ~InternalMark()
- {
- }
-
- virtual QIcon icon() const
- {
- return m_parent->icon();
- }
-
- virtual void updateLineNumber(int lineNumber)
- {
- return m_parent->updateLineNumber(lineNumber);
- }
-
- virtual void updateBlock(const QTextBlock &block)
- {
- return m_parent->updateBlock(block);
- }
-
- virtual void removedFromEditor()
- {
- m_parent->childRemovedFromEditor(this);
- }
-
- virtual void documentClosing()
- {
- m_parent->documentClosingFor(this);
- }
-private:
- BaseTextMark *m_parent;
-};
-
-} // namespace Internal
} // namespace TextEditor
#endif // BASETEXTMARK_H
diff --git a/src/plugins/texteditor/behaviorsettingspage.cpp b/src/plugins/texteditor/behaviorsettingspage.cpp
index 53d772aa47..bc12035e88 100644
--- a/src/plugins/texteditor/behaviorsettingspage.cpp
+++ b/src/plugins/texteditor/behaviorsettingspage.cpp
@@ -39,8 +39,11 @@
#include "ui_behaviorsettingspage.h"
#include <coreplugin/icore.h>
+#include <coreplugin/coreconstants.h>
+#include <coreplugin/editormanager/editormanager.h>
#include <QtCore/QSettings>
+#include <QtCore/QTextCodec>
#include <QtCore/QTextStream>
using namespace TextEditor;
@@ -50,7 +53,7 @@ struct BehaviorSettingsPage::BehaviorSettingsPagePrivate
explicit BehaviorSettingsPagePrivate(const BehaviorSettingsPageParameters &p);
const BehaviorSettingsPageParameters m_parameters;
- Ui::BehaviorSettingsPage m_page;
+ Ui::BehaviorSettingsPage *m_page;
TabSettings m_tabSettings;
StorageSettings m_storageSettings;
@@ -61,7 +64,7 @@ struct BehaviorSettingsPage::BehaviorSettingsPagePrivate
BehaviorSettingsPage::BehaviorSettingsPagePrivate::BehaviorSettingsPagePrivate
(const BehaviorSettingsPageParameters &p)
- : m_parameters(p)
+ : m_parameters(p), m_page(0)
{
if (const QSettings *s = Core::ICore::instance()->settings()) {
m_tabSettings.fromSettings(m_parameters.settingsPrefix, s);
@@ -95,25 +98,70 @@ QString BehaviorSettingsPage::displayName() const
QWidget *BehaviorSettingsPage::createPage(QWidget *parent)
{
QWidget *w = new QWidget(parent);
- m_d->m_page.setupUi(w);
+ m_d->m_page = new Ui::BehaviorSettingsPage;
+ m_d->m_page->setupUi(w);
settingsToUI();
if (m_d->m_searchKeywords.isEmpty()) {
- QTextStream(&m_d->m_searchKeywords) << m_d->m_page.insertSpaces->text()
- << ' ' << m_d->m_page.smartBackspace->text()
- << ' ' << m_d->m_page.cleanWhitespace->text()
- << ' ' << m_d->m_page.addFinalNewLine->text()
- << ' ' << m_d->m_page.mouseNavigation->text()
- << ' ' << m_d->m_page.scrollWheelZooming->text()
- << ' ' << m_d->m_page.groupBoxTabAndIndentSettings->title()
- << ' ' << m_d->m_page.groupBoxStorageSettings->title()
- << ' ' << m_d->m_page.groupBoxMouse->title();
+ QLatin1Char sep(' ');
+ QTextStream(&m_d->m_searchKeywords)
+ << m_d->m_page->insertSpaces->text()
+ << sep << m_d->m_page->autoInsertSpaces->text()
+ << sep << m_d->m_page->autoIndent->text()
+ << sep << m_d->m_page->smartBackspace->text()
+ << sep << m_d->m_page->indentBlocksLabel->text()
+ << sep << m_d->m_page->continuationAlignLabel->text()
+ << sep << m_d->m_page->tabKeyIndentLabel->text()
+ << sep << m_d->m_page->cleanWhitespace->text()
+ << sep << m_d->m_page->inEntireDocument->text()
+ << sep << m_d->m_page->cleanIndentation->text()
+ << sep << m_d->m_page->addFinalNewLine->text()
+ << sep << m_d->m_page->encodingLabel->text()
+ << sep << m_d->m_page->utf8BomLabel->text()
+ << sep << m_d->m_page->mouseNavigation->text()
+ << sep << m_d->m_page->scrollWheelZooming->text()
+ << sep << m_d->m_page->groupBoxTabAndIndentSettings->title()
+ << sep << m_d->m_page->groupBoxStorageSettings->title()
+ << sep << m_d->m_page->groupBoxEncodings->title()
+ << sep << m_d->m_page->groupBoxMouse->title();
m_d->m_searchKeywords.remove(QLatin1Char('&'));
}
+
+ QSettings *settings = Core::ICore::instance()->settings();
+ QTextCodec *defaultTextCodec = QTextCodec::codecForLocale();
+ if (QTextCodec *candidate = QTextCodec::codecForName(
+ settings->value(QLatin1String(Core::Constants::SETTINGS_DEFAULTTEXTENCODING)).toByteArray()))
+ defaultTextCodec = candidate;
+ QList<int> mibs = QTextCodec::availableMibs();
+ qSort(mibs);
+ QList<int> sortedMibs;
+ foreach (int mib, mibs)
+ if (mib >= 0)
+ sortedMibs += mib;
+ foreach (int mib, mibs)
+ if (mib < 0)
+ sortedMibs += mib;
+ for (int i = 0; i < sortedMibs.count(); i++) {
+ QTextCodec *codec = QTextCodec::codecForMib(sortedMibs.at(i));
+ m_codecs += codec;
+ QString name = codec->name();
+ foreach (const QByteArray &alias, codec->aliases()) {
+ name += QLatin1String(" / ");
+ name += QString::fromLatin1(alias);
+ }
+ m_d->m_page->encodingBox->addItem(name);
+ if (defaultTextCodec == codec)
+ m_d->m_page->encodingBox->setCurrentIndex(i);
+ }
+
+ m_d->m_page->utf8BomBox->setCurrentIndex(Core::EditorManager::instance()->utf8BomSetting());
+
return w;
}
void BehaviorSettingsPage::apply()
{
+ if (!m_d->m_page) // page was never shown
+ return;
TabSettings newTabSettings;
StorageSettings newStorageSettings;
BehaviorSettings newBehaviorSettings;
@@ -146,57 +194,72 @@ void BehaviorSettingsPage::apply()
emit behaviorSettingsChanged(newBehaviorSettings);
}
+
+ QSettings* settings = Core::ICore::instance()->settings();
+ settings->setValue(QLatin1String(Core::Constants::SETTINGS_DEFAULTTEXTENCODING),
+ m_codecs.at(m_d->m_page->encodingBox->currentIndex())->name());
+
+ Core::EditorManager::instance()->setUtf8BomSetting(
+ Core::IFile::Utf8BomSetting(m_d->m_page->utf8BomBox->currentIndex()));
+}
+
+void BehaviorSettingsPage::finish()
+{
+ if (!m_d->m_page) // page was never shown
+ return;
+ delete m_d->m_page;
+ m_d->m_page = 0;
}
void BehaviorSettingsPage::settingsFromUI(TabSettings &tabSettings,
StorageSettings &storageSettings,
BehaviorSettings &behaviorSettings) const
{
- tabSettings.m_spacesForTabs = m_d->m_page.insertSpaces->isChecked();
- tabSettings.m_autoSpacesForTabs = m_d->m_page.autoInsertSpaces->isChecked();
- tabSettings.m_autoIndent = m_d->m_page.autoIndent->isChecked();
- tabSettings.m_smartBackspace = m_d->m_page.smartBackspace->isChecked();
- tabSettings.m_tabSize = m_d->m_page.tabSize->value();
- tabSettings.m_indentSize = m_d->m_page.indentSize->value();
- tabSettings.m_indentBraces = m_d->m_page.indentBlocksBehavior->currentIndex() >= 1;
- tabSettings.m_doubleIndentBlocks = m_d->m_page.indentBlocksBehavior->currentIndex() >= 2;
-
- tabSettings.m_tabKeyBehavior = (TabSettings::TabKeyBehavior)m_d->m_page.tabKeyBehavior->currentIndex();
- tabSettings.m_continuationAlignBehavior = (TabSettings::ContinuationAlignBehavior)m_d->m_page.continuationAlignBehavior->currentIndex();
-
- storageSettings.m_cleanWhitespace = m_d->m_page.cleanWhitespace->isChecked();
- storageSettings.m_inEntireDocument = m_d->m_page.inEntireDocument->isChecked();
- storageSettings.m_cleanIndentation = m_d->m_page.cleanIndentation->isChecked();
- storageSettings.m_addFinalNewLine = m_d->m_page.addFinalNewLine->isChecked();
-
- behaviorSettings.m_mouseNavigation = m_d->m_page.mouseNavigation->isChecked();
- behaviorSettings.m_scrollWheelZooming = m_d->m_page.scrollWheelZooming->isChecked();
+ tabSettings.m_spacesForTabs = m_d->m_page->insertSpaces->isChecked();
+ tabSettings.m_autoSpacesForTabs = m_d->m_page->autoInsertSpaces->isChecked();
+ tabSettings.m_autoIndent = m_d->m_page->autoIndent->isChecked();
+ tabSettings.m_smartBackspace = m_d->m_page->smartBackspace->isChecked();
+ tabSettings.m_tabSize = m_d->m_page->tabSize->value();
+ tabSettings.m_indentSize = m_d->m_page->indentSize->value();
+ tabSettings.m_indentBraces = m_d->m_page->indentBlocksBehavior->currentIndex() >= 1;
+ tabSettings.m_doubleIndentBlocks = m_d->m_page->indentBlocksBehavior->currentIndex() >= 2;
+
+ tabSettings.m_tabKeyBehavior = (TabSettings::TabKeyBehavior)m_d->m_page->tabKeyBehavior->currentIndex();
+ tabSettings.m_continuationAlignBehavior = (TabSettings::ContinuationAlignBehavior)m_d->m_page->continuationAlignBehavior->currentIndex();
+
+ storageSettings.m_cleanWhitespace = m_d->m_page->cleanWhitespace->isChecked();
+ storageSettings.m_inEntireDocument = m_d->m_page->inEntireDocument->isChecked();
+ storageSettings.m_cleanIndentation = m_d->m_page->cleanIndentation->isChecked();
+ storageSettings.m_addFinalNewLine = m_d->m_page->addFinalNewLine->isChecked();
+
+ behaviorSettings.m_mouseNavigation = m_d->m_page->mouseNavigation->isChecked();
+ behaviorSettings.m_scrollWheelZooming = m_d->m_page->scrollWheelZooming->isChecked();
}
void BehaviorSettingsPage::settingsToUI()
{
const TabSettings &tabSettings = m_d->m_tabSettings;
- m_d->m_page.insertSpaces->setChecked(tabSettings.m_spacesForTabs);
- m_d->m_page.autoInsertSpaces->setChecked(tabSettings.m_autoSpacesForTabs);
- m_d->m_page.autoIndent->setChecked(tabSettings.m_autoIndent);
- m_d->m_page.smartBackspace->setChecked(tabSettings.m_smartBackspace);
- m_d->m_page.tabSize->setValue(tabSettings.m_tabSize);
- m_d->m_page.indentSize->setValue(tabSettings.m_indentSize);
- m_d->m_page.indentBlocksBehavior->setCurrentIndex(tabSettings.m_indentBraces ?
+ m_d->m_page->insertSpaces->setChecked(tabSettings.m_spacesForTabs);
+ m_d->m_page->autoInsertSpaces->setChecked(tabSettings.m_autoSpacesForTabs);
+ m_d->m_page->autoIndent->setChecked(tabSettings.m_autoIndent);
+ m_d->m_page->smartBackspace->setChecked(tabSettings.m_smartBackspace);
+ m_d->m_page->tabSize->setValue(tabSettings.m_tabSize);
+ m_d->m_page->indentSize->setValue(tabSettings.m_indentSize);
+ m_d->m_page->indentBlocksBehavior->setCurrentIndex(tabSettings.m_indentBraces ?
(tabSettings.m_doubleIndentBlocks ? 2 : 1)
: 0);
- m_d->m_page.tabKeyBehavior->setCurrentIndex(tabSettings.m_tabKeyBehavior);
- m_d->m_page.continuationAlignBehavior->setCurrentIndex(tabSettings.m_continuationAlignBehavior);
+ m_d->m_page->tabKeyBehavior->setCurrentIndex(tabSettings.m_tabKeyBehavior);
+ m_d->m_page->continuationAlignBehavior->setCurrentIndex(tabSettings.m_continuationAlignBehavior);
const StorageSettings &storageSettings = m_d->m_storageSettings;
- m_d->m_page.cleanWhitespace->setChecked(storageSettings.m_cleanWhitespace);
- m_d->m_page.inEntireDocument->setChecked(storageSettings.m_inEntireDocument);
- m_d->m_page.cleanIndentation->setChecked(storageSettings.m_cleanIndentation);
- m_d->m_page.addFinalNewLine->setChecked(storageSettings.m_addFinalNewLine);
+ m_d->m_page->cleanWhitespace->setChecked(storageSettings.m_cleanWhitespace);
+ m_d->m_page->inEntireDocument->setChecked(storageSettings.m_inEntireDocument);
+ m_d->m_page->cleanIndentation->setChecked(storageSettings.m_cleanIndentation);
+ m_d->m_page->addFinalNewLine->setChecked(storageSettings.m_addFinalNewLine);
const BehaviorSettings &behaviorSettings = m_d->m_behaviorSettings;
- m_d->m_page.mouseNavigation->setChecked(behaviorSettings.m_mouseNavigation);
- m_d->m_page.scrollWheelZooming->setChecked(behaviorSettings.m_scrollWheelZooming);
+ m_d->m_page->mouseNavigation->setChecked(behaviorSettings.m_mouseNavigation);
+ m_d->m_page->scrollWheelZooming->setChecked(behaviorSettings.m_scrollWheelZooming);
}
const TabSettings &BehaviorSettingsPage::tabSettings() const
@@ -216,5 +279,5 @@ const BehaviorSettings &BehaviorSettingsPage::behaviorSettings() const
bool BehaviorSettingsPage::matches(const QString &s) const
{
- return m_d->m_searchKeywords.contains(s, Qt::CaseInsensitive);
+ return m_d->m_searchKeywords.contains(s, Qt::CaseInsensitive);
}
diff --git a/src/plugins/texteditor/behaviorsettingspage.h b/src/plugins/texteditor/behaviorsettingspage.h
index ec36b295d9..4952d5db0a 100644
--- a/src/plugins/texteditor/behaviorsettingspage.h
+++ b/src/plugins/texteditor/behaviorsettingspage.h
@@ -66,7 +66,7 @@ public:
QWidget *createPage(QWidget *parent);
void apply();
- void finish() { }
+ void finish();
bool matches(const QString &s) const;
const TabSettings &tabSettings() const;
@@ -83,6 +83,8 @@ private:
StorageSettings &storageSettings,
BehaviorSettings &behaviorSettings) const;
void settingsToUI();
+
+ QList<QTextCodec *> m_codecs;
struct BehaviorSettingsPagePrivate;
BehaviorSettingsPagePrivate *m_d;
};
diff --git a/src/plugins/texteditor/behaviorsettingspage.ui b/src/plugins/texteditor/behaviorsettingspage.ui
index 0a9e92ae08..102ce080b8 100644
--- a/src/plugins/texteditor/behaviorsettingspage.ui
+++ b/src/plugins/texteditor/behaviorsettingspage.ui
@@ -6,12 +6,12 @@
<rect>
<x>0</x>
<y>0</y>
- <width>576</width>
+ <width>662</width>
<height>538</height>
</rect>
</property>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
+ <layout class="QGridLayout" name="gridLayout_3">
+ <item row="0" column="0" colspan="2">
<widget class="QGroupBox" name="groupBoxTabAndIndentSettings">
<property name="title">
<string>Tabs and Indentation</string>
@@ -305,16 +305,19 @@ Influences the indentation of continuation lines.
</layout>
</widget>
</item>
- <item>
+ <item row="1" column="0">
<widget class="QGroupBox" name="groupBoxStorageSettings">
+ <property name="toolTip">
+ <string>Cleanup actions which are automatically performed right before the file is saved to disk.</string>
+ </property>
<property name="title">
- <string>Storage</string>
+ <string>Cleanups Upon Saving</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QCheckBox" name="cleanWhitespace">
<property name="toolTip">
- <string>Removes trailing whitespace on saving.</string>
+ <string>Removes trailing whitespace upon saving.</string>
</property>
<property name="text">
<string>&amp;Clean whitespace</string>
@@ -397,7 +400,7 @@ Influences the indentation of continuation lines.
</layout>
</widget>
</item>
- <item>
+ <item row="2" column="0" colspan="2">
<widget class="QGroupBox" name="groupBoxMouse">
<property name="title">
<string>Mouse</string>
@@ -420,7 +423,7 @@ Influences the indentation of continuation lines.
</layout>
</widget>
</item>
- <item>
+ <item row="3" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
@@ -433,6 +436,124 @@ Influences the indentation of continuation lines.
</property>
</spacer>
</item>
+ <item row="1" column="1">
+ <widget class="QGroupBox" name="groupBoxEncodings">
+ <property name="title">
+ <string>File Encodings</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_4">
+ <item row="0" column="0">
+ <widget class="QLabel" name="encodingLabel">
+ <property name="text">
+ <string>Default encoding: </string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout_6">
+ <item>
+ <widget class="QComboBox" name="encodingBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="sizeAdjustPolicy">
+ <enum>QComboBox::AdjustToMinimumContentsLengthWithIcon</enum>
+ </property>
+ <property name="minimumContentsLength">
+ <number>20</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_6">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>285</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="utf8BomLabel">
+ <property name="text">
+ <string>UTF-8 BOM:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout_4">
+ <item>
+ <widget class="QComboBox" name="utf8BomBox">
+ <property name="toolTip">
+ <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;How text editors should deal with UTF-8 Byte Order Marks. The options are:&lt;/p&gt;
+&lt;ul style=&quot;margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;&quot;&gt;&lt;li style=&quot; margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;Add If Encoding Is UTF-8:&lt;/span&gt; always add a BOM when saving a file in UTF-8 encoding. Note that this will not work if the encoding is &lt;span style=&quot; font-style:italic;&quot;&gt;System&lt;/span&gt;, as Qt Creator does not know what it actually is.&lt;/li&gt;
+&lt;li style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;Keep If Already Present: &lt;/span&gt;save the file with a BOM if it already had one when it was loaded.&lt;/li&gt;
+&lt;li style=&quot; margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;Always Delete:&lt;/span&gt; never write an UTF-8 BOM, possibly deleting a pre-existing one.&lt;/li&gt;&lt;/ul&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Note that UTF-8 BOMs are uncommon and treated incorrectly by some editors, so it usually makes little sense to add any.&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;This setting does &lt;span style=&quot; font-weight:600;&quot;&gt;not&lt;/span&gt; influence the use of UTF-16 and UTF-32 BOMs.&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <item>
+ <property name="text">
+ <string>Add If Encoding Is UTF-8</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Keep If Already Present</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Always Delete</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item row="2" column="0" colspan="2">
+ <spacer name="verticalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
</layout>
</widget>
<tabstops>
diff --git a/src/plugins/texteditor/completionsupport.cpp b/src/plugins/texteditor/completionsupport.cpp
index 0c14f8cf86..1dc48cb574 100644
--- a/src/plugins/texteditor/completionsupport.cpp
+++ b/src/plugins/texteditor/completionsupport.cpp
@@ -44,11 +44,7 @@
#include <QtCore/QString>
#include <QtCore/QList>
-#include <algorithm>
-
-using namespace TextEditor;
-using namespace TextEditor::Internal;
-
+namespace TextEditor {
CompletionSupport *CompletionSupport::instance()
{
@@ -58,48 +54,68 @@ CompletionSupport *CompletionSupport::instance()
return m_instance;
}
-CompletionSupport::CompletionSupport()
- : QObject(Core::ICore::instance()),
- m_completionList(0),
- m_startPosition(0),
- m_checkCompletionTrigger(false),
- m_editor(0),
- m_completionCollector(0)
+class CompletionSupportPrivate {
+public:
+ CompletionSupportPrivate();
+
+ Internal::CompletionWidget *m_completionList;
+ int m_startPosition;
+ bool m_checkCompletionTrigger; // Whether to check for completion trigger after cleanup
+ ITextEditable *m_editor;
+ const QList<ICompletionCollector *> m_completionCollectors;
+ ICompletionCollector *m_completionCollector;
+};
+
+CompletionSupportPrivate::CompletionSupportPrivate() :
+ m_completionList(0),
+ m_startPosition(0),
+ m_checkCompletionTrigger(false),
+ m_editor(0),
+ m_completionCollectors(ExtensionSystem::PluginManager::instance()
+ ->getObjects<ICompletionCollector>()),
+ m_completionCollector(0)
+{
+}
+
+CompletionSupport::CompletionSupport() :
+ QObject(Core::ICore::instance()), d(new CompletionSupportPrivate)
+{
+}
+
+CompletionSupport::~CompletionSupport()
{
- m_completionCollectors = ExtensionSystem::PluginManager::instance()
- ->getObjects<ICompletionCollector>();
}
void CompletionSupport::performCompletion(const CompletionItem &item)
{
- item.collector->complete(item, m_completionList->typedChar());
- m_checkCompletionTrigger = true;
+ item.collector->complete(item, d->m_completionList->typedChar());
+ d->m_checkCompletionTrigger = true;
}
void CompletionSupport::cleanupCompletions()
{
- if (m_completionList)
- disconnect(m_completionList, SIGNAL(destroyed(QObject*)),
+ if (d->m_completionList)
+ disconnect(d->m_completionList, SIGNAL(destroyed(QObject*)),
this, SLOT(cleanupCompletions()));
- if (m_checkCompletionTrigger)
- m_checkCompletionTrigger = m_completionCollector->shouldRestartCompletion();
+ if (d->m_checkCompletionTrigger)
+ d->m_checkCompletionTrigger = d->m_completionCollector->shouldRestartCompletion();
- m_completionList = 0;
- m_completionCollector->cleanup();
+ d->m_completionList = 0;
+ d->m_completionCollector->cleanup();
- if (m_checkCompletionTrigger) {
- m_checkCompletionTrigger = false;
+ if (d->m_checkCompletionTrigger) {
+ d->m_checkCompletionTrigger = false;
// Only check for completion trigger when some text was entered
- if (m_editor->position() > m_startPosition)
- autoComplete(m_editor, false);
+ if (d->m_editor->position() > d->m_startPosition)
+ autoComplete(d->m_editor, false);
}
}
bool CompletionSupport::isActive() const
{
- return m_completionList != 0;
+ return d->m_completionList != 0;
}
void CompletionSupport::autoComplete(ITextEditable *editor, bool forced)
@@ -117,68 +133,68 @@ void CompletionSupport::quickFix(ITextEditable *editor)
void CompletionSupport::autoComplete_helper(ITextEditable *editor, bool forced,
bool quickFix)
{
- m_completionCollector = 0;
+ d->m_completionCollector = 0;
- foreach (ICompletionCollector *collector, m_completionCollectors) {
+ foreach (ICompletionCollector *collector, d->m_completionCollectors) {
if (quickFix)
collector = qobject_cast<IQuickFixCollector *>(collector);
if (collector && collector->supportsEditor(editor)) {
- m_completionCollector = collector;
+ d->m_completionCollector = collector;
break;
}
}
- if (!m_completionCollector)
+ if (!d->m_completionCollector)
return;
- m_editor = editor;
+ d->m_editor = editor;
QList<CompletionItem> completionItems;
int currentIndex = 0;
- if (!m_completionList) {
+ if (!d->m_completionList) {
if (!forced) {
- const CompletionSettings &completionSettings = m_completionCollector->completionSettings();
+ const CompletionSettings &completionSettings = d->m_completionCollector->completionSettings();
if (completionSettings.m_completionTrigger == ManualCompletion)
return;
- if (!m_completionCollector->triggersCompletion(editor))
+ if (!d->m_completionCollector->triggersCompletion(editor))
return;
}
- m_startPosition = m_completionCollector->startCompletion(editor);
+ d->m_startPosition = d->m_completionCollector->startCompletion(editor);
completionItems = getCompletions();
- QTC_ASSERT(!(m_startPosition == -1 && completionItems.size() > 0), return);
+ QTC_ASSERT(!(d->m_startPosition == -1 && completionItems.size() > 0), return);
if (completionItems.isEmpty()) {
cleanupCompletions();
return;
}
- m_completionList = new CompletionWidget(this, editor);
- m_completionList->setQuickFix(quickFix);
+ d->m_completionList = new Internal::CompletionWidget(this, editor);
+ d->m_completionList->setQuickFix(quickFix);
- connect(m_completionList, SIGNAL(itemSelected(TextEditor::CompletionItem)),
+ connect(d->m_completionList, SIGNAL(itemSelected(TextEditor::CompletionItem)),
this, SLOT(performCompletion(TextEditor::CompletionItem)));
- connect(m_completionList, SIGNAL(completionListClosed()),
+ connect(d->m_completionList, SIGNAL(completionListClosed()),
this, SLOT(cleanupCompletions()));
// Make sure to clean up the completions if the list is destroyed without
// emitting completionListClosed (can happen when no focus out event is received,
// for example when switching applications on the Mac)
- connect(m_completionList, SIGNAL(destroyed(QObject*)),
+ connect(d->m_completionList, SIGNAL(destroyed(QObject*)),
this, SLOT(cleanupCompletions()));
} else {
completionItems = getCompletions();
if (completionItems.isEmpty()) {
- m_completionList->closeList();
+ d->m_completionList->closeList();
return;
}
- if (m_completionList->explicitlySelected()) {
- const int originalIndex = m_completionList->currentCompletionItem().originalIndex;
+ if (d->m_completionList->explicitlySelected()) {
+ const int originalIndex = d->m_completionList->currentCompletionItem().originalIndex;
for (int index = 0; index < completionItems.size(); ++index) {
if (completionItems.at(index).originalIndex == originalIndex) {
@@ -189,24 +205,26 @@ void CompletionSupport::autoComplete_helper(ITextEditable *editor, bool forced,
}
}
- m_completionList->setCompletionItems(completionItems);
+ d->m_completionList->setCompletionItems(completionItems);
if (currentIndex)
- m_completionList->setCurrentIndex(currentIndex);
+ d->m_completionList->setCurrentIndex(currentIndex);
// Partially complete when completion was forced
- if (forced && m_completionCollector->partiallyComplete(completionItems)) {
- m_checkCompletionTrigger = true;
- m_completionList->closeList();
+ if (forced && d->m_completionCollector->partiallyComplete(completionItems)) {
+ d->m_checkCompletionTrigger = true;
+ d->m_completionList->closeList();
} else {
- m_completionList->showCompletions(m_startPosition);
+ d->m_completionList->showCompletions(d->m_startPosition);
}
}
QList<CompletionItem> CompletionSupport::getCompletions() const
{
- if (m_completionCollector)
- return m_completionCollector->getCompletions();
+ if (d->m_completionCollector)
+ return d->m_completionCollector->getCompletions();
return QList<CompletionItem>();
}
+
+} // namespace TextEditor
diff --git a/src/plugins/texteditor/completionsupport.h b/src/plugins/texteditor/completionsupport.h
index 773dea0f66..4b8cc5408f 100644
--- a/src/plugins/texteditor/completionsupport.h
+++ b/src/plugins/texteditor/completionsupport.h
@@ -44,9 +44,7 @@ class CompletionItem;
class ICompletionCollector;
class ITextEditable;
-namespace Internal {
-
-class CompletionWidget;
+class CompletionSupportPrivate;
/* Completion support is responsible for querying the list of completion collectors
and popping up the CompletionWidget with the available completions.
@@ -56,7 +54,7 @@ class TEXTEDITOR_EXPORT CompletionSupport : public QObject
Q_OBJECT
public:
- CompletionSupport();
+ virtual ~CompletionSupport();
static CompletionSupport *instance();
@@ -71,18 +69,14 @@ private slots:
void cleanupCompletions();
private:
+ CompletionSupport();
+
QList<CompletionItem> getCompletions() const;
void autoComplete_helper(ITextEditable *editor, bool forced, bool quickFix);
- CompletionWidget *m_completionList;
- int m_startPosition;
- bool m_checkCompletionTrigger; // Whether to check for completion trigger after cleanup
- ITextEditable *m_editor;
- QList<ICompletionCollector *> m_completionCollectors;
- ICompletionCollector *m_completionCollector;
+ QScopedPointer<CompletionSupportPrivate> d;
};
-} // namespace Internal
} // namespace TextEditor
#endif // COMPLETIONSUPPORT_H
diff --git a/src/plugins/texteditor/completionwidget.h b/src/plugins/texteditor/completionwidget.h
index 00aeff3cd4..de5d3c1815 100644
--- a/src/plugins/texteditor/completionwidget.h
+++ b/src/plugins/texteditor/completionwidget.h
@@ -42,11 +42,11 @@ namespace TextEditor {
class CompletionItem;
class ITextEditable;
+class CompletionSupport;
namespace Internal {
class AutoCompletionModel;
-class CompletionSupport;
class CompletionListView;
class CompletionInfoFrame;
diff --git a/src/plugins/texteditor/displaysettingspage.cpp b/src/plugins/texteditor/displaysettingspage.cpp
index 69ade7a24d..6976a490ac 100644
--- a/src/plugins/texteditor/displaysettingspage.cpp
+++ b/src/plugins/texteditor/displaysettingspage.cpp
@@ -47,14 +47,14 @@ struct DisplaySettingsPage::DisplaySettingsPagePrivate
explicit DisplaySettingsPagePrivate(const DisplaySettingsPageParameters &p);
const DisplaySettingsPageParameters m_parameters;
- Ui::DisplaySettingsPage m_page;
+ Ui::DisplaySettingsPage *m_page;
DisplaySettings m_displaySettings;
QString m_searchKeywords;
};
DisplaySettingsPage::DisplaySettingsPagePrivate::DisplaySettingsPagePrivate
(const DisplaySettingsPageParameters &p)
- : m_parameters(p)
+ : m_parameters(p), m_page(0)
{
if (const QSettings *s = Core::ICore::instance()->settings()) {
m_displaySettings.fromSettings(m_parameters.settingsPrefix, s);
@@ -86,18 +86,19 @@ QString DisplaySettingsPage::displayName() const
QWidget *DisplaySettingsPage::createPage(QWidget *parent)
{
QWidget *w = new QWidget(parent);
- m_d->m_page.setupUi(w);
+ m_d->m_page = new Ui::DisplaySettingsPage;
+ m_d->m_page->setupUi(w);
settingsToUI();
if (m_d->m_searchKeywords.isEmpty()) {
- QTextStream(&m_d->m_searchKeywords) << m_d->m_page.displayLineNumbers->text()
- << ' ' << m_d->m_page.highlightCurrentLine->text()
- << ' ' << m_d->m_page.displayFoldingMarkers->text()
- << ' ' << m_d->m_page.highlightBlocks->text()
- << ' ' << m_d->m_page.visualizeWhitespace->text()
- << ' ' << m_d->m_page.animateMatchingParentheses->text()
- << ' ' << m_d->m_page.enableTextWrapping->text()
- << ' ' << m_d->m_page.autoFoldFirstComment->text()
- << ' ' << m_d->m_page.centerOnScroll->text();
+ QTextStream(&m_d->m_searchKeywords) << m_d->m_page->displayLineNumbers->text()
+ << ' ' << m_d->m_page->highlightCurrentLine->text()
+ << ' ' << m_d->m_page->displayFoldingMarkers->text()
+ << ' ' << m_d->m_page->highlightBlocks->text()
+ << ' ' << m_d->m_page->visualizeWhitespace->text()
+ << ' ' << m_d->m_page->animateMatchingParentheses->text()
+ << ' ' << m_d->m_page->enableTextWrapping->text()
+ << ' ' << m_d->m_page->autoFoldFirstComment->text()
+ << ' ' << m_d->m_page->centerOnScroll->text();
m_d->m_searchKeywords.remove(QLatin1Char('&'));
}
return w;
@@ -105,43 +106,53 @@ QWidget *DisplaySettingsPage::createPage(QWidget *parent)
void DisplaySettingsPage::apply()
{
+ if (!m_d->m_page) // page was never shown
+ return;
DisplaySettings newDisplaySettings;
settingsFromUI(newDisplaySettings);
setDisplaySettings(newDisplaySettings);
}
+void DisplaySettingsPage::finish()
+{
+ if (!m_d->m_page) // page was never shown
+ return;
+ delete m_d->m_page;
+ m_d->m_page = 0;
+}
+
void DisplaySettingsPage::settingsFromUI(DisplaySettings &displaySettings) const
{
- displaySettings.m_displayLineNumbers = m_d->m_page.displayLineNumbers->isChecked();
- displaySettings.m_textWrapping = m_d->m_page.enableTextWrapping->isChecked();
- displaySettings.m_showWrapColumn = m_d->m_page.showWrapColumn->isChecked();
- displaySettings.m_wrapColumn = m_d->m_page.wrapColumn->value();
- displaySettings.m_visualizeWhitespace = m_d->m_page.visualizeWhitespace->isChecked();
- displaySettings.m_displayFoldingMarkers = m_d->m_page.displayFoldingMarkers->isChecked();
- displaySettings.m_highlightCurrentLine = m_d->m_page.highlightCurrentLine->isChecked();
- displaySettings.m_highlightBlocks = m_d->m_page.highlightBlocks->isChecked();
- displaySettings.m_animateMatchingParentheses = m_d->m_page.animateMatchingParentheses->isChecked();
- displaySettings.m_markTextChanges = m_d->m_page.markTextChanges->isChecked();
- displaySettings.m_autoFoldFirstComment = m_d->m_page.autoFoldFirstComment->isChecked();
- displaySettings.m_centerCursorOnScroll = m_d->m_page.centerOnScroll->isChecked();
+ displaySettings.m_displayLineNumbers = m_d->m_page->displayLineNumbers->isChecked();
+ displaySettings.m_textWrapping = m_d->m_page->enableTextWrapping->isChecked();
+ displaySettings.m_showWrapColumn = m_d->m_page->showWrapColumn->isChecked();
+ displaySettings.m_wrapColumn = m_d->m_page->wrapColumn->value();
+ displaySettings.m_visualizeWhitespace = m_d->m_page->visualizeWhitespace->isChecked();
+ displaySettings.m_displayFoldingMarkers = m_d->m_page->displayFoldingMarkers->isChecked();
+ displaySettings.m_highlightCurrentLine = m_d->m_page->highlightCurrentLine->isChecked();
+ displaySettings.m_highlightBlocks = m_d->m_page->highlightBlocks->isChecked();
+ displaySettings.m_animateMatchingParentheses = m_d->m_page->animateMatchingParentheses->isChecked();
+ displaySettings.m_markTextChanges = m_d->m_page->markTextChanges->isChecked();
+ displaySettings.m_autoFoldFirstComment = m_d->m_page->autoFoldFirstComment->isChecked();
+ displaySettings.m_centerCursorOnScroll = m_d->m_page->centerOnScroll->isChecked();
}
void DisplaySettingsPage::settingsToUI()
{
const DisplaySettings &displaySettings = m_d->m_displaySettings;
- m_d->m_page.displayLineNumbers->setChecked(displaySettings.m_displayLineNumbers);
- m_d->m_page.enableTextWrapping->setChecked(displaySettings.m_textWrapping);
- m_d->m_page.showWrapColumn->setChecked(displaySettings.m_showWrapColumn);
- m_d->m_page.wrapColumn->setValue(displaySettings.m_wrapColumn);
- m_d->m_page.visualizeWhitespace->setChecked(displaySettings.m_visualizeWhitespace);
- m_d->m_page.displayFoldingMarkers->setChecked(displaySettings.m_displayFoldingMarkers);
- m_d->m_page.highlightCurrentLine->setChecked(displaySettings.m_highlightCurrentLine);
- m_d->m_page.highlightBlocks->setChecked(displaySettings.m_highlightBlocks);
- m_d->m_page.animateMatchingParentheses->setChecked(displaySettings.m_animateMatchingParentheses);
- m_d->m_page.markTextChanges->setChecked(displaySettings.m_markTextChanges);
- m_d->m_page.autoFoldFirstComment->setChecked(displaySettings.m_autoFoldFirstComment);
- m_d->m_page.centerOnScroll->setChecked(displaySettings.m_centerCursorOnScroll);
+ m_d->m_page->displayLineNumbers->setChecked(displaySettings.m_displayLineNumbers);
+ m_d->m_page->enableTextWrapping->setChecked(displaySettings.m_textWrapping);
+ m_d->m_page->showWrapColumn->setChecked(displaySettings.m_showWrapColumn);
+ m_d->m_page->wrapColumn->setValue(displaySettings.m_wrapColumn);
+ m_d->m_page->visualizeWhitespace->setChecked(displaySettings.m_visualizeWhitespace);
+ m_d->m_page->displayFoldingMarkers->setChecked(displaySettings.m_displayFoldingMarkers);
+ m_d->m_page->highlightCurrentLine->setChecked(displaySettings.m_highlightCurrentLine);
+ m_d->m_page->highlightBlocks->setChecked(displaySettings.m_highlightBlocks);
+ m_d->m_page->animateMatchingParentheses->setChecked(displaySettings.m_animateMatchingParentheses);
+ m_d->m_page->markTextChanges->setChecked(displaySettings.m_markTextChanges);
+ m_d->m_page->autoFoldFirstComment->setChecked(displaySettings.m_autoFoldFirstComment);
+ m_d->m_page->centerOnScroll->setChecked(displaySettings.m_centerCursorOnScroll);
}
const DisplaySettings &DisplaySettingsPage::displaySettings() const
diff --git a/src/plugins/texteditor/displaysettingspage.h b/src/plugins/texteditor/displaysettingspage.h
index d550bbe327..c494e35c44 100644
--- a/src/plugins/texteditor/displaysettingspage.h
+++ b/src/plugins/texteditor/displaysettingspage.h
@@ -64,7 +64,7 @@ public:
QWidget *createPage(QWidget *parent);
void apply();
- void finish() { }
+ void finish();
virtual bool matches(const QString &s) const;
const DisplaySettings &displaySettings() const;
diff --git a/src/plugins/texteditor/findincurrentfile.cpp b/src/plugins/texteditor/findincurrentfile.cpp
index e25e4091b1..5ebec0bb00 100644
--- a/src/plugins/texteditor/findincurrentfile.cpp
+++ b/src/plugins/texteditor/findincurrentfile.cpp
@@ -32,6 +32,7 @@
**************************************************************************/
#include "findincurrentfile.h"
+#include "itexteditor.h"
#include <coreplugin/icore.h>
#include <coreplugin/editormanager/editormanager.h>
@@ -44,6 +45,7 @@
#include <QtGui/QVBoxLayout>
using namespace Find;
+using namespace TextEditor;
using namespace TextEditor::Internal;
FindInCurrentFile::FindInCurrentFile(SearchResultWindow *resultWindow)
@@ -66,12 +68,15 @@ QString FindInCurrentFile::displayName() const
return tr("Current File");
}
-Utils::FileIterator *FindInCurrentFile::files()
+Utils::FileIterator *FindInCurrentFile::files() const
{
- QStringList fileList;
- if (isEnabled())
- fileList << m_currentFile->fileName();
- return new Utils::FileIterator(fileList);
+ Q_ASSERT(isEnabled());
+ QString fileName = m_currentFile->fileName();
+ QMap<QString, QTextCodec *> openEditorEncodings = ITextEditor::openedTextEditorsEncodings();
+ QTextCodec *codec = openEditorEncodings.value(fileName);
+ if (!codec)
+ codec = Core::EditorManager::instance()->defaultTextEncoding();
+ return new Utils::FileIterator(QStringList() << fileName, QList<QTextCodec *>() << codec);
}
bool FindInCurrentFile::isEnabled() const
diff --git a/src/plugins/texteditor/findincurrentfile.h b/src/plugins/texteditor/findincurrentfile.h
index 965f260342..18d1c38893 100644
--- a/src/plugins/texteditor/findincurrentfile.h
+++ b/src/plugins/texteditor/findincurrentfile.h
@@ -65,14 +65,14 @@ public:
void readSettings(QSettings *settings);
protected:
- Utils::FileIterator *files();
+ Utils::FileIterator *files() const;
private slots:
void handleFileChange(Core::IEditor *editor);
private:
QPointer<QWidget> m_configWidget;
- Core::IFile *m_currentFile;
+ QPointer<Core::IFile> m_currentFile;
};
} // namespace Internal
diff --git a/src/plugins/texteditor/findinfiles.cpp b/src/plugins/texteditor/findinfiles.cpp
index 3b5a6427f4..663c8aa510 100644
--- a/src/plugins/texteditor/findinfiles.cpp
+++ b/src/plugins/texteditor/findinfiles.cpp
@@ -33,6 +33,8 @@
#include "findinfiles.h"
+#include <coreplugin/editormanager/editormanager.h>
+
#include <QtCore/QtDebug>
#include <QtCore/QSettings>
#include <QtCore/QDir>
@@ -67,10 +69,11 @@ void FindInFiles::findAll(const QString &txt, Find::FindFlags findFlags)
BaseFileFind::findAll(txt, findFlags);
}
-Utils::FileIterator *FindInFiles::files()
+Utils::FileIterator *FindInFiles::files() const
{
return new Utils::SubDirFileIterator(QStringList() << m_directory->currentText(),
- fileNameFilters());
+ fileNameFilters(),
+ Core::EditorManager::instance()->defaultTextEncoding());
}
QWidget *FindInFiles::createConfigWidget()
diff --git a/src/plugins/texteditor/findinfiles.h b/src/plugins/texteditor/findinfiles.h
index fe900a41eb..b7dc55db48 100644
--- a/src/plugins/texteditor/findinfiles.h
+++ b/src/plugins/texteditor/findinfiles.h
@@ -63,7 +63,7 @@ public:
void readSettings(QSettings *settings);
protected:
- Utils::FileIterator *files();
+ Utils::FileIterator *files() const;
private slots:
void openFileBrowser();
diff --git a/src/plugins/texteditor/fontsettingspage.cpp b/src/plugins/texteditor/fontsettingspage.cpp
index 3327d0a9d2..419373b713 100644
--- a/src/plugins/texteditor/fontsettingspage.cpp
+++ b/src/plugins/texteditor/fontsettingspage.cpp
@@ -133,7 +133,7 @@ public:
TextEditor::FormatDescriptions m_descriptions;
FontSettings m_value;
FontSettings m_lastValue;
- Ui::FontSettingsPage ui;
+ Ui::FontSettingsPage *m_ui;
SchemeListModel *m_schemeListModel;
bool m_refreshingSchemeList;
QString m_searchKeywords;
@@ -184,6 +184,7 @@ FontSettingsPagePrivate::FontSettingsPagePrivate(const TextEditor::FormatDescrip
m_displayName(displayName),
m_settingsGroup(Utils::settingsKey(category)),
m_descriptions(fd),
+ m_ui(0),
m_schemeListModel(new SchemeListModel),
m_refreshingSchemeList(false)
{
@@ -335,42 +336,52 @@ QString FontSettingsPage::displayName() const
QWidget *FontSettingsPage::createPage(QWidget *parent)
{
QWidget *w = new QWidget(parent);
- d_ptr->ui.setupUi(w);
- d_ptr->ui.schemeComboBox->setModel(d_ptr->m_schemeListModel);
+ d_ptr->m_ui = new Ui::FontSettingsPage;
+ d_ptr->m_ui->setupUi(w);
+ d_ptr->m_ui->schemeComboBox->setModel(d_ptr->m_schemeListModel);
QFontDatabase db;
const QStringList families = db.families();
- d_ptr->ui.familyComboBox->addItems(families);
+ d_ptr->m_ui->familyComboBox->addItems(families);
const int idx = families.indexOf(d_ptr->m_value.family());
- d_ptr->ui.familyComboBox->setCurrentIndex(idx);
+ d_ptr->m_ui->familyComboBox->setCurrentIndex(idx);
- d_ptr->ui.antialias->setChecked(d_ptr->m_value.antialias());
- d_ptr->ui.zoomSpinBox->setValue(d_ptr->m_value.fontZoom());
+ d_ptr->m_ui->antialias->setChecked(d_ptr->m_value.antialias());
+ d_ptr->m_ui->zoomSpinBox->setValue(d_ptr->m_value.fontZoom());
- d_ptr->ui.schemeEdit->setFormatDescriptions(d_ptr->m_descriptions);
- d_ptr->ui.schemeEdit->setBaseFont(d_ptr->m_value.font());
- d_ptr->ui.schemeEdit->setColorScheme(d_ptr->m_value.colorScheme());
+ d_ptr->m_ui->schemeEdit->setFormatDescriptions(d_ptr->m_descriptions);
+ d_ptr->m_ui->schemeEdit->setBaseFont(d_ptr->m_value.font());
+ d_ptr->m_ui->schemeEdit->setColorScheme(d_ptr->m_value.colorScheme());
- connect(d_ptr->ui.familyComboBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(fontFamilySelected(QString)));
- connect(d_ptr->ui.sizeComboBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(fontSizeSelected(QString)));
- connect(d_ptr->ui.zoomSpinBox, SIGNAL(valueChanged(int)), this, SLOT(fontZoomChanged()));
- connect(d_ptr->ui.schemeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(colorSchemeSelected(int)));
- connect(d_ptr->ui.copyButton, SIGNAL(clicked()), this, SLOT(copyColorScheme()));
- connect(d_ptr->ui.deleteButton, SIGNAL(clicked()), this, SLOT(confirmDeleteColorScheme()));
+ connect(d_ptr->m_ui->familyComboBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(fontFamilySelected(QString)));
+ connect(d_ptr->m_ui->sizeComboBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(fontSizeSelected(QString)));
+ connect(d_ptr->m_ui->zoomSpinBox, SIGNAL(valueChanged(int)), this, SLOT(fontZoomChanged()));
+ connect(d_ptr->m_ui->schemeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(colorSchemeSelected(int)));
+ connect(d_ptr->m_ui->copyButton, SIGNAL(clicked()), this, SLOT(copyColorScheme()));
+ connect(d_ptr->m_ui->deleteButton, SIGNAL(clicked()), this, SLOT(confirmDeleteColorScheme()));
updatePointSizes();
refreshColorSchemeList();
d_ptr->m_lastValue = d_ptr->m_value;
- if (d_ptr->m_searchKeywords.isEmpty())
- d_ptr->m_searchKeywords = d_ptr->ui.fontGroupBox->title() + QLatin1Char(' ') + d_ptr->ui.colorSchemeGroupBox->title();
+ if (d_ptr->m_searchKeywords.isEmpty()) {
+ QLatin1Char sep(' ');
+ d_ptr->m_searchKeywords =
+ d_ptr->m_ui->fontGroupBox->title() + sep
+ + d_ptr->m_ui->familyLabel->text() + sep
+ + d_ptr->m_ui->sizeLabel->text() + sep
+ + d_ptr->m_ui->zoomLabel->text() + sep
+ + d_ptr->m_ui->antialias->text() + sep
+ + d_ptr->m_ui->colorSchemeGroupBox->title();
+ d_ptr->m_searchKeywords.remove(QLatin1Char('&'));
+ }
return w;
}
void FontSettingsPage::fontFamilySelected(const QString &family)
{
d_ptr->m_value.setFamily(family);
- d_ptr->ui.schemeEdit->setBaseFont(d_ptr->m_value.font());
+ d_ptr->m_ui->schemeEdit->setBaseFont(d_ptr->m_value.font());
updatePointSizes();
}
@@ -378,13 +389,13 @@ void FontSettingsPage::updatePointSizes()
{
// Update point sizes
const int oldSize = d_ptr->m_value.fontSize();
- if (d_ptr->ui.sizeComboBox->count()) {
- const QString curSize = d_ptr->ui.sizeComboBox->currentText();
+ if (d_ptr->m_ui->sizeComboBox->count()) {
+ const QString curSize = d_ptr->m_ui->sizeComboBox->currentText();
bool ok = true;
int oldSize = curSize.toInt(&ok);
if (!ok)
oldSize = d_ptr->m_value.fontSize();
- d_ptr->ui.sizeComboBox->clear();
+ d_ptr->m_ui->sizeComboBox->clear();
}
const QList<int> sizeLst = pointSizesForSelectedFont();
int idx = -1;
@@ -392,16 +403,16 @@ void FontSettingsPage::updatePointSizes()
for (; i < sizeLst.count(); ++i) {
if (idx == -1 && sizeLst.at(i) >= oldSize)
idx = i;
- d_ptr->ui.sizeComboBox->addItem(QString::number(sizeLst.at(i)));
+ d_ptr->m_ui->sizeComboBox->addItem(QString::number(sizeLst.at(i)));
}
if (idx != -1)
- d_ptr->ui.sizeComboBox->setCurrentIndex(idx);
+ d_ptr->m_ui->sizeComboBox->setCurrentIndex(idx);
}
QList<int> FontSettingsPage::pointSizesForSelectedFont() const
{
QFontDatabase db;
- const QString familyName = d_ptr->ui.familyComboBox->currentText();
+ const QString familyName = d_ptr->m_ui->familyComboBox->currentText();
QList<int> sizeLst = db.pointSizes(familyName);
if (!sizeLst.isEmpty())
return sizeLst;
@@ -421,13 +432,13 @@ void FontSettingsPage::fontSizeSelected(const QString &sizeString)
const int size = sizeString.toInt(&ok);
if (ok) {
d_ptr->m_value.setFontSize(size);
- d_ptr->ui.schemeEdit->setBaseFont(d_ptr->m_value.font());
+ d_ptr->m_ui->schemeEdit->setBaseFont(d_ptr->m_value.font());
}
}
void FontSettingsPage::fontZoomChanged()
{
- d_ptr->m_value.setFontZoom(d_ptr->ui.zoomSpinBox->value());
+ d_ptr->m_value.setFontZoom(d_ptr->m_ui->zoomSpinBox->value());
}
void FontSettingsPage::colorSchemeSelected(int index)
@@ -441,16 +452,16 @@ void FontSettingsPage::colorSchemeSelected(int index)
const ColorSchemeEntry &entry = d_ptr->m_schemeListModel->colorSchemeAt(index);
readOnly = entry.readOnly;
d_ptr->m_value.loadColorScheme(entry.fileName, d_ptr->m_descriptions);
- d_ptr->ui.schemeEdit->setColorScheme(d_ptr->m_value.colorScheme());
+ d_ptr->m_ui->schemeEdit->setColorScheme(d_ptr->m_value.colorScheme());
}
- d_ptr->ui.copyButton->setEnabled(index != -1);
- d_ptr->ui.deleteButton->setEnabled(!readOnly);
- d_ptr->ui.schemeEdit->setReadOnly(readOnly);
+ d_ptr->m_ui->copyButton->setEnabled(index != -1);
+ d_ptr->m_ui->deleteButton->setEnabled(!readOnly);
+ d_ptr->m_ui->schemeEdit->setReadOnly(readOnly);
}
void FontSettingsPage::copyColorScheme()
{
- QInputDialog *dialog = new QInputDialog(d_ptr->ui.copyButton->window());
+ QInputDialog *dialog = new QInputDialog(d_ptr->m_ui->copyButton->window());
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->setInputMode(QInputDialog::TextInput);
dialog->setWindowTitle(tr("Copy Color Scheme"));
@@ -463,7 +474,7 @@ void FontSettingsPage::copyColorScheme()
void FontSettingsPage::copyColorScheme(const QString &name)
{
- int index = d_ptr->ui.schemeComboBox->currentIndex();
+ int index = d_ptr->m_ui->schemeComboBox->currentIndex();
if (index == -1)
return;
@@ -478,7 +489,7 @@ void FontSettingsPage::copyColorScheme(const QString &name)
maybeSaveColorScheme();
// Make sure we're copying the current version
- d_ptr->m_value.setColorScheme(d_ptr->ui.schemeEdit->colorScheme());
+ d_ptr->m_value.setColorScheme(d_ptr->m_ui->schemeEdit->colorScheme());
ColorScheme scheme = d_ptr->m_value.colorScheme();
scheme.setDisplayName(name);
@@ -491,7 +502,7 @@ void FontSettingsPage::copyColorScheme(const QString &name)
void FontSettingsPage::confirmDeleteColorScheme()
{
- const int index = d_ptr->ui.schemeComboBox->currentIndex();
+ const int index = d_ptr->m_ui->schemeComboBox->currentIndex();
if (index == -1)
return;
@@ -503,7 +514,7 @@ void FontSettingsPage::confirmDeleteColorScheme()
tr("Delete Color Scheme"),
tr("Are you sure you want to delete this color scheme permanently?"),
QMessageBox::Discard | QMessageBox::Cancel,
- d_ptr->ui.deleteButton->window());
+ d_ptr->m_ui->deleteButton->window());
// Change the text and role of the discard button
QPushButton *deleteButton = static_cast<QPushButton*>(messageBox->button(QMessageBox::Discard));
@@ -519,7 +530,7 @@ void FontSettingsPage::confirmDeleteColorScheme()
void FontSettingsPage::deleteColorScheme()
{
- const int index = d_ptr->ui.schemeComboBox->currentIndex();
+ const int index = d_ptr->m_ui->schemeComboBox->currentIndex();
QTC_ASSERT(index != -1, return)
const ColorSchemeEntry &entry = d_ptr->m_schemeListModel->colorSchemeAt(index);
@@ -531,15 +542,15 @@ void FontSettingsPage::deleteColorScheme()
void FontSettingsPage::maybeSaveColorScheme()
{
- if (d_ptr->m_value.colorScheme() == d_ptr->ui.schemeEdit->colorScheme())
+ if (d_ptr->m_value.colorScheme() == d_ptr->m_ui->schemeEdit->colorScheme())
return;
QMessageBox *messageBox = new QMessageBox(QMessageBox::Warning,
tr("Color Scheme Changed"),
tr("The color scheme \"%1\" was modified, do you want to save the changes?")
- .arg(d_ptr->ui.schemeEdit->colorScheme().displayName()),
+ .arg(d_ptr->m_ui->schemeEdit->colorScheme().displayName()),
QMessageBox::Discard | QMessageBox::Save,
- d_ptr->ui.schemeComboBox->window());
+ d_ptr->m_ui->schemeComboBox->window());
// Change the text of the discard button
QPushButton *discardButton = static_cast<QPushButton*>(messageBox->button(QMessageBox::Discard));
@@ -548,7 +559,7 @@ void FontSettingsPage::maybeSaveColorScheme()
messageBox->setDefaultButton(QMessageBox::Save);
if (messageBox->exec() == QMessageBox::Save) {
- const ColorScheme &scheme = d_ptr->ui.schemeEdit->colorScheme();
+ const ColorScheme &scheme = d_ptr->m_ui->schemeEdit->colorScheme();
scheme.save(d_ptr->m_value.colorSchemeFileName());
}
}
@@ -589,7 +600,7 @@ void FontSettingsPage::refreshColorSchemeList()
d_ptr->m_refreshingSchemeList = true;
d_ptr->m_schemeListModel->setColorSchemes(colorSchemes);
- d_ptr->ui.schemeComboBox->setCurrentIndex(selected);
+ d_ptr->m_ui->schemeComboBox->setCurrentIndex(selected);
d_ptr->m_refreshingSchemeList = false;
}
@@ -600,16 +611,18 @@ void FontSettingsPage::delayedChange()
void FontSettingsPage::apply()
{
- d_ptr->m_value.setAntialias(d_ptr->ui.antialias->isChecked());
+ if (!d_ptr->m_ui) // page was never shown
+ return;
+ d_ptr->m_value.setAntialias(d_ptr->m_ui->antialias->isChecked());
- if (d_ptr->m_value.colorScheme() != d_ptr->ui.schemeEdit->colorScheme()) {
+ if (d_ptr->m_value.colorScheme() != d_ptr->m_ui->schemeEdit->colorScheme()) {
// Update the scheme and save it under the name it already has
- d_ptr->m_value.setColorScheme(d_ptr->ui.schemeEdit->colorScheme());
+ d_ptr->m_value.setColorScheme(d_ptr->m_ui->schemeEdit->colorScheme());
const ColorScheme &scheme = d_ptr->m_value.colorScheme();
scheme.save(d_ptr->m_value.colorSchemeFileName());
}
- int index = d_ptr->ui.schemeComboBox->currentIndex();
+ int index = d_ptr->m_ui->schemeComboBox->currentIndex();
if (index != -1) {
const ColorSchemeEntry &entry = d_ptr->m_schemeListModel->colorSchemeAt(index);
if (entry.fileName != d_ptr->m_value.colorSchemeFileName())
@@ -632,8 +645,12 @@ void FontSettingsPage::saveSettings()
void FontSettingsPage::finish()
{
+ if (!d_ptr->m_ui) // page was never shown
+ return;
// If changes were applied, these are equal. Otherwise restores last value.
d_ptr->m_value = d_ptr->m_lastValue;
+ delete d_ptr->m_ui;
+ d_ptr->m_ui = 0;
}
const FontSettings &FontSettingsPage::fontSettings() const
diff --git a/src/plugins/texteditor/fontsettingspage.ui b/src/plugins/texteditor/fontsettingspage.ui
index bef6cc789a..4e27fc00a6 100644
--- a/src/plugins/texteditor/fontsettingspage.ui
+++ b/src/plugins/texteditor/fontsettingspage.ui
@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
- <width>402</width>
+ <width>521</width>
<height>306</height>
</rect>
</property>
@@ -135,7 +135,7 @@
</spacer>
</item>
<item row="0" column="6">
- <widget class="QLabel" name="label">
+ <widget class="QLabel" name="zoomLabel">
<property name="text">
<string>Zoom:</string>
</property>
diff --git a/src/plugins/texteditor/generichighlighter/highlightdefinition.cpp b/src/plugins/texteditor/generichighlighter/highlightdefinition.cpp
index f70480d5db..57a06cc5da 100644
--- a/src/plugins/texteditor/generichighlighter/highlightdefinition.cpp
+++ b/src/plugins/texteditor/generichighlighter/highlightdefinition.cpp
@@ -44,11 +44,14 @@ using namespace TextEditor;
using namespace Internal;
HighlightDefinition::HighlightDefinition() :
- m_delimiters(QLatin1String(".():!+,-<=>%&/;?[]^{|}~\\*, \t")),
m_singleLineCommentAfterWhiteSpaces(false),
m_keywordCaseSensitivity(Qt::CaseSensitive),
m_indentationBasedFolding(false)
-{}
+{
+ QString s(QLatin1String(".():!+,-<=>%&/;?[]^{|}~\\*, \t"));
+ foreach (const QChar &c, s)
+ m_delimiters.insert(c);
+}
HighlightDefinition::~HighlightDefinition()
{}
@@ -151,7 +154,7 @@ void HighlightDefinition::addDelimiters(const QString &characters)
{
for (int i = 0; i < characters.length(); ++i) {
if (!m_delimiters.contains(characters.at(i)))
- m_delimiters.append(characters.at(i));
+ m_delimiters.insert(characters.at(i));
}
}
diff --git a/src/plugins/texteditor/generichighlighter/highlightdefinition.h b/src/plugins/texteditor/generichighlighter/highlightdefinition.h
index 39c7ef34d8..2666f25470 100644
--- a/src/plugins/texteditor/generichighlighter/highlightdefinition.h
+++ b/src/plugins/texteditor/generichighlighter/highlightdefinition.h
@@ -36,6 +36,7 @@
#include <QtCore/QString>
#include <QtCore/QHash>
+#include <QtCore/QSet>
#include <QtCore/QSharedPointer>
namespace TextEditor {
@@ -106,8 +107,6 @@ private:
QString m_initialContext;
- QString m_delimiters;
-
QString m_singleLineComment;
bool m_singleLineCommentAfterWhiteSpaces;
@@ -118,6 +117,8 @@ private:
Qt::CaseSensitivity m_keywordCaseSensitivity;
bool m_indentationBasedFolding;
+
+ QSet<QChar> m_delimiters;
};
} // namespace Internal
diff --git a/src/plugins/texteditor/generichighlighter/highlightersettings.cpp b/src/plugins/texteditor/generichighlighter/highlightersettings.cpp
index 611246e665..eb037009ec 100644
--- a/src/plugins/texteditor/generichighlighter/highlightersettings.cpp
+++ b/src/plugins/texteditor/generichighlighter/highlightersettings.cpp
@@ -53,7 +53,7 @@ QString findFallbackDefinitionsLocation()
QDir dir;
dir.setNameFilters(QStringList(QLatin1String("*.xml")));
-#ifdef Q_OS_UNIX
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
static const QLatin1String kateSyntax[] = {
QLatin1String("/share/apps/katepart/syntax"),
QLatin1String("/share/kde4/apps/katepart/syntax")
diff --git a/src/plugins/texteditor/generichighlighter/highlightersettingspage.cpp b/src/plugins/texteditor/generichighlighter/highlightersettingspage.cpp
index 8cb63cb40f..97571d51de 100644
--- a/src/plugins/texteditor/generichighlighter/highlightersettingspage.cpp
+++ b/src/plugins/texteditor/generichighlighter/highlightersettingspage.cpp
@@ -57,14 +57,15 @@ struct HighlighterSettingsPage::HighlighterSettingsPagePrivate
HighlighterSettings m_settings;
- Ui::HighlighterSettingsPage m_page;
+ Ui::HighlighterSettingsPage *m_page;
};
HighlighterSettingsPage::HighlighterSettingsPagePrivate::
HighlighterSettingsPagePrivate(const QString &id) :
m_id(id),
m_displayName(tr("Generic Highlighter")),
- m_settingsPrefix(QLatin1String("Text"))
+ m_settingsPrefix(QLatin1String("Text")),
+ m_page(0)
{}
HighlighterSettingsPage::HighlighterSettingsPage(const QString &id, QObject *parent) :
@@ -94,27 +95,28 @@ QString HighlighterSettingsPage::displayName() const
QWidget *HighlighterSettingsPage::createPage(QWidget *parent)
{
QWidget *w = new QWidget(parent);
- m_d->m_page.setupUi(w);
- m_d->m_page.definitionFilesPath->setExpectedKind(Utils::PathChooser::Directory);
- m_d->m_page.definitionFilesPath->addButton(tr("Download Definitions"), this,
+ m_d->m_page = new Ui::HighlighterSettingsPage;
+ m_d->m_page->setupUi(w);
+ m_d->m_page->definitionFilesPath->setExpectedKind(Utils::PathChooser::Directory);
+ m_d->m_page->definitionFilesPath->addButton(tr("Download Definitions"), this,
SLOT(requestAvailableDefinitionsMetaData()));
- m_d->m_page.fallbackDefinitionFilesPath->setExpectedKind(Utils::PathChooser::Directory);
- m_d->m_page.fallbackDefinitionFilesPath->addButton(tr("Autodetect"), this,
+ m_d->m_page->fallbackDefinitionFilesPath->setExpectedKind(Utils::PathChooser::Directory);
+ m_d->m_page->fallbackDefinitionFilesPath->addButton(tr("Autodetect"), this,
SLOT(resetDefinitionsLocation()));
settingsToUI();
if (m_d->m_searchKeywords.isEmpty()) {
- QTextStream(&m_d->m_searchKeywords) << m_d->m_page.definitionFilesGroupBox->title()
- << m_d->m_page.locationLabel->text()
- << m_d->m_page.alertWhenNoDefinition->text()
- << m_d->m_page.useFallbackLocation->text()
- << m_d->m_page.ignoreLabel->text();
+ QTextStream(&m_d->m_searchKeywords) << m_d->m_page->definitionFilesGroupBox->title()
+ << m_d->m_page->locationLabel->text()
+ << m_d->m_page->alertWhenNoDefinition->text()
+ << m_d->m_page->useFallbackLocation->text()
+ << m_d->m_page->ignoreLabel->text();
}
- connect(m_d->m_page.useFallbackLocation, SIGNAL(clicked(bool)),
+ connect(m_d->m_page->useFallbackLocation, SIGNAL(clicked(bool)),
this, SLOT(setFallbackLocationState(bool)));
- connect(m_d->m_page.definitionFilesPath, SIGNAL(validChanged(bool)),
+ connect(m_d->m_page->definitionFilesPath, SIGNAL(validChanged(bool)),
this, SLOT(setDownloadDefinitionsState(bool)));
connect(w, SIGNAL(destroyed()), this, SLOT(ignoreDownloadReply()));
@@ -123,6 +125,8 @@ QWidget *HighlighterSettingsPage::createPage(QWidget *parent)
void HighlighterSettingsPage::apply()
{
+ if (!m_d->m_page) // page was not shown
+ return;
if (settingsChanged())
settingsFromUI();
@@ -132,6 +136,14 @@ void HighlighterSettingsPage::apply()
}
}
+void HighlighterSettingsPage::finish()
+{
+ if (!m_d->m_page) // page was not shown
+ return;
+ delete m_d->m_page;
+ m_d->m_page = 0;
+}
+
bool HighlighterSettingsPage::matches(const QString &s) const
{
return m_d->m_searchKeywords.contains(s, Qt::CaseInsensitive);
@@ -143,34 +155,34 @@ const HighlighterSettings &HighlighterSettingsPage::highlighterSettings() const
}
void HighlighterSettingsPage::settingsFromUI()
-{
+{
if (!m_requestMimeTypeRegistration && (
- m_d->m_settings.definitionFilesPath() != m_d->m_page.definitionFilesPath->path() ||
+ m_d->m_settings.definitionFilesPath() != m_d->m_page->definitionFilesPath->path() ||
m_d->m_settings.fallbackDefinitionFilesPath() !=
- m_d->m_page.fallbackDefinitionFilesPath->path() ||
- m_d->m_settings.useFallbackLocation() != m_d->m_page.useFallbackLocation->isChecked())) {
+ m_d->m_page->fallbackDefinitionFilesPath->path() ||
+ m_d->m_settings.useFallbackLocation() != m_d->m_page->useFallbackLocation->isChecked())) {
m_requestMimeTypeRegistration = true;
}
- m_d->m_settings.setDefinitionFilesPath(m_d->m_page.definitionFilesPath->path());
- m_d->m_settings.setFallbackDefinitionFilesPath(m_d->m_page.fallbackDefinitionFilesPath->path());
- m_d->m_settings.setAlertWhenNoDefinition(m_d->m_page.alertWhenNoDefinition->isChecked());
- m_d->m_settings.setUseFallbackLocation(m_d->m_page.useFallbackLocation->isChecked());
- m_d->m_settings.setIgnoredFilesPatterns(m_d->m_page.ignoreEdit->text());
+ m_d->m_settings.setDefinitionFilesPath(m_d->m_page->definitionFilesPath->path());
+ m_d->m_settings.setFallbackDefinitionFilesPath(m_d->m_page->fallbackDefinitionFilesPath->path());
+ m_d->m_settings.setAlertWhenNoDefinition(m_d->m_page->alertWhenNoDefinition->isChecked());
+ m_d->m_settings.setUseFallbackLocation(m_d->m_page->useFallbackLocation->isChecked());
+ m_d->m_settings.setIgnoredFilesPatterns(m_d->m_page->ignoreEdit->text());
if (QSettings *s = Core::ICore::instance()->settings())
m_d->m_settings.toSettings(m_d->m_settingsPrefix, s);
}
void HighlighterSettingsPage::settingsToUI()
{
- m_d->m_page.definitionFilesPath->setPath(m_d->m_settings.definitionFilesPath());
- m_d->m_page.fallbackDefinitionFilesPath->setPath(m_d->m_settings.fallbackDefinitionFilesPath());
- m_d->m_page.alertWhenNoDefinition->setChecked(m_d->m_settings.alertWhenNoDefinition());
- m_d->m_page.useFallbackLocation->setChecked(m_d->m_settings.useFallbackLocation());
- m_d->m_page.ignoreEdit->setText(m_d->m_settings.ignoredFilesPatterns());
-
- setFallbackLocationState(m_d->m_page.useFallbackLocation->isChecked());
- setDownloadDefinitionsState(m_d->m_page.definitionFilesPath->isValid());
+ m_d->m_page->definitionFilesPath->setPath(m_d->m_settings.definitionFilesPath());
+ m_d->m_page->fallbackDefinitionFilesPath->setPath(m_d->m_settings.fallbackDefinitionFilesPath());
+ m_d->m_page->alertWhenNoDefinition->setChecked(m_d->m_settings.alertWhenNoDefinition());
+ m_d->m_page->useFallbackLocation->setChecked(m_d->m_settings.useFallbackLocation());
+ m_d->m_page->ignoreEdit->setText(m_d->m_settings.ignoredFilesPatterns());
+
+ setFallbackLocationState(m_d->m_page->useFallbackLocation->isChecked());
+ setDownloadDefinitionsState(m_d->m_page->definitionFilesPath->isValid());
}
void HighlighterSettingsPage::resetDefinitionsLocation()
@@ -180,7 +192,7 @@ void HighlighterSettingsPage::resetDefinitionsLocation()
QMessageBox::information(0, tr("Autodetect Definitions"),
tr("No pre-installed definitions could be found."));
else
- m_d->m_page.fallbackDefinitionFilesPath->setPath(location);
+ m_d->m_page->fallbackDefinitionFilesPath->setPath(location);
}
void HighlighterSettingsPage::requestAvailableDefinitionsMetaData()
@@ -210,43 +222,43 @@ void HighlighterSettingsPage::ignoreDownloadReply()
void HighlighterSettingsPage::manageDefinitions(const QList<HighlightDefinitionMetaData> &metaData)
{
ManageDefinitionsDialog dialog(metaData,
- m_d->m_page.definitionFilesPath->path() + QLatin1Char('/'),
- m_d->m_page.definitionFilesPath->buttonAtIndex(1)->window());
+ m_d->m_page->definitionFilesPath->path() + QLatin1Char('/'),
+ m_d->m_page->definitionFilesPath->buttonAtIndex(1)->window());
if (dialog.exec() && !m_requestMimeTypeRegistration)
m_requestMimeTypeRegistration = true;
- setDownloadDefinitionsState(m_d->m_page.definitionFilesPath->isValid());
+ setDownloadDefinitionsState(m_d->m_page->definitionFilesPath->isValid());
}
void HighlighterSettingsPage::showError()
{
- QMessageBox::critical(m_d->m_page.definitionFilesPath->buttonAtIndex(1)->window(),
+ QMessageBox::critical(m_d->m_page->definitionFilesPath->buttonAtIndex(1)->window(),
tr("Error connecting to server."),
tr("Not possible to retrieve data."));
- setDownloadDefinitionsState(m_d->m_page.definitionFilesPath->isValid());
+ setDownloadDefinitionsState(m_d->m_page->definitionFilesPath->isValid());
}
void HighlighterSettingsPage::setFallbackLocationState(bool checked)
{
- m_d->m_page.fallbackDefinitionFilesPath->setEnabled(checked);
+ m_d->m_page->fallbackDefinitionFilesPath->setEnabled(checked);
}
void HighlighterSettingsPage::setDownloadDefinitionsState(bool valid)
{
- m_d->m_page.definitionFilesPath->buttonAtIndex(1)->setEnabled(valid);
+ m_d->m_page->definitionFilesPath->buttonAtIndex(1)->setEnabled(valid);
}
bool HighlighterSettingsPage::settingsChanged() const
-{
- if (m_d->m_settings.definitionFilesPath() != m_d->m_page.definitionFilesPath->path())
+{
+ if (m_d->m_settings.definitionFilesPath() != m_d->m_page->definitionFilesPath->path())
return true;
if (m_d->m_settings.fallbackDefinitionFilesPath() !=
- m_d->m_page.fallbackDefinitionFilesPath->path())
+ m_d->m_page->fallbackDefinitionFilesPath->path())
return true;
- if (m_d->m_settings.alertWhenNoDefinition() != m_d->m_page.alertWhenNoDefinition->isChecked())
+ if (m_d->m_settings.alertWhenNoDefinition() != m_d->m_page->alertWhenNoDefinition->isChecked())
return true;
- if (m_d->m_settings.useFallbackLocation() != m_d->m_page.useFallbackLocation->isChecked())
+ if (m_d->m_settings.useFallbackLocation() != m_d->m_page->useFallbackLocation->isChecked())
return true;
- if (m_d->m_settings.ignoredFilesPatterns() != m_d->m_page.ignoreEdit->text())
+ if (m_d->m_settings.ignoredFilesPatterns() != m_d->m_page->ignoreEdit->text())
return true;
return false;
}
diff --git a/src/plugins/texteditor/generichighlighter/highlightersettingspage.h b/src/plugins/texteditor/generichighlighter/highlightersettingspage.h
index 37a12abb5d..0179d51c53 100644
--- a/src/plugins/texteditor/generichighlighter/highlightersettingspage.h
+++ b/src/plugins/texteditor/generichighlighter/highlightersettingspage.h
@@ -60,7 +60,7 @@ public:
QWidget *createPage(QWidget *parent);
void apply();
- void finish() {}
+ void finish();
bool matches(const QString &s) const;
const HighlighterSettings &highlighterSettings() const;
diff --git a/src/plugins/texteditor/generichighlighter/managedefinitionsdialog.ui b/src/plugins/texteditor/generichighlighter/managedefinitionsdialog.ui
index 5dece663dc..d6db77b033 100644
--- a/src/plugins/texteditor/generichighlighter/managedefinitionsdialog.ui
+++ b/src/plugins/texteditor/generichighlighter/managedefinitionsdialog.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>447</width>
- <height>445</height>
+ <width>586</width>
+ <height>280</height>
</rect>
</property>
<property name="windowTitle">
diff --git a/src/plugins/texteditor/generichighlighter/progressdata.cpp b/src/plugins/texteditor/generichighlighter/progressdata.cpp
index 5cc5bd2dec..348134e793 100644
--- a/src/plugins/texteditor/generichighlighter/progressdata.cpp
+++ b/src/plugins/texteditor/generichighlighter/progressdata.cpp
@@ -32,6 +32,7 @@
**************************************************************************/
#include "progressdata.h"
+#include "rule.h"
#include <QtCore/QtGlobal>
@@ -47,6 +48,12 @@ ProgressData::ProgressData() :
m_willContinueLine(false)
{}
+ProgressData::~ProgressData()
+{
+ foreach (Rule *rule, m_trackedRules)
+ rule->progressFinished();
+}
+
void ProgressData::setOffset(const int offset)
{ m_offset = offset; }
@@ -106,3 +113,8 @@ void ProgressData::setCaptures(const QStringList &captures)
const QStringList &ProgressData::captures() const
{ return m_captures; }
+
+void ProgressData::trackRule(Rule *rule)
+{
+ m_trackedRules.append(rule);
+}
diff --git a/src/plugins/texteditor/generichighlighter/progressdata.h b/src/plugins/texteditor/generichighlighter/progressdata.h
index a1132723ea..65017f8ac7 100644
--- a/src/plugins/texteditor/generichighlighter/progressdata.h
+++ b/src/plugins/texteditor/generichighlighter/progressdata.h
@@ -39,10 +39,13 @@
namespace TextEditor {
namespace Internal {
+class Rule;
+
class ProgressData
{
public:
ProgressData();
+ ~ProgressData();
void setOffset(const int offset);
int offset() const;
@@ -70,6 +73,8 @@ public:
void setCaptures(const QStringList &captures);
const QStringList &captures() const;
+ void trackRule(Rule *rule);
+
private:
int m_offset;
int m_savedOffset;
@@ -78,6 +83,7 @@ private:
bool m_closingBraceMatchAtNonEnd;
bool m_willContinueLine;
QStringList m_captures;
+ QList<Rule *> m_trackedRules;
};
} // namespace Internal
diff --git a/src/plugins/texteditor/generichighlighter/rule.cpp b/src/plugins/texteditor/generichighlighter/rule.cpp
index c23b7c2efa..35815d4384 100644
--- a/src/plugins/texteditor/generichighlighter/rule.cpp
+++ b/src/plugins/texteditor/generichighlighter/rule.cpp
@@ -166,7 +166,7 @@ bool Rule::charPredicateMatchSucceed(const QString &text,
return predicateMatchSucceed(text, length, progress, std::ptr_fun(predicate));
}
-bool Rule::matchSucceed(const QString &text, const int length, ProgressData *progress) const
+bool Rule::matchSucceed(const QString &text, const int length, ProgressData *progress)
{
if (m_firstNonSpace && !progress->isOnlySpacesSoFar())
return false;
@@ -191,6 +191,9 @@ bool Rule::matchSucceed(const QString &text, const int length, ProgressData *pro
Rule *Rule::clone() const
{ return doClone(); }
+void Rule::progressFinished()
+{ doProgressFinished(); }
+
bool Rule::matchCharacter(const QString &text,
const int length,
ProgressData *progress,
diff --git a/src/plugins/texteditor/generichighlighter/rule.h b/src/plugins/texteditor/generichighlighter/rule.h
index ef0b6e712a..c5e100c6da 100644
--- a/src/plugins/texteditor/generichighlighter/rule.h
+++ b/src/plugins/texteditor/generichighlighter/rule.h
@@ -78,10 +78,12 @@ public:
void setDefinition(const QSharedPointer<HighlightDefinition> &definition);
const QSharedPointer<HighlightDefinition> &definition() const;
- bool matchSucceed(const QString &text, const int length, ProgressData *progress) const;
+ bool matchSucceed(const QString &text, const int length, ProgressData *progress);
Rule *clone() const;
+ void progressFinished();
+
protected:
bool charPredicateMatchSucceed(const QString &text,
const int length,
@@ -132,12 +134,12 @@ protected:
static const QLatin1Char kClosingBrace;
private:
- virtual bool doMatchSucceed(const QString &text,
- const int length,
- ProgressData *progress) const = 0;
+ virtual bool doMatchSucceed(const QString &text, const int length, ProgressData *progress) = 0;
virtual Rule *doClone() const = 0;
+ virtual void doProgressFinished() {}
+
template <class predicate_t>
bool predicateMatchSucceed(const QString &text,
const int length,
diff --git a/src/plugins/texteditor/generichighlighter/specificrules.cpp b/src/plugins/texteditor/generichighlighter/specificrules.cpp
index 252328b6b4..2ce13baad2 100644
--- a/src/plugins/texteditor/generichighlighter/specificrules.cpp
+++ b/src/plugins/texteditor/generichighlighter/specificrules.cpp
@@ -88,7 +88,7 @@ void DetectCharRule::doReplaceExpressions(const QStringList &captures)
bool DetectCharRule::doMatchSucceed(const QString &text,
const int length,
- ProgressData *progress) const
+ ProgressData *progress)
{
if (matchCharacter(text, length, progress, m_char)) {
// This is to make code folding have a control flow style look in the case of braces.
@@ -119,7 +119,7 @@ void Detect2CharsRule::doReplaceExpressions(const QStringList &captures)
bool Detect2CharsRule::doMatchSucceed(const QString &text,
const int length,
- ProgressData *progress) const
+ ProgressData *progress)
{
if (matchCharacter(text, length, progress, m_char)) {
if (progress->offset() < length && matchCharacter(text, length, progress, m_char1, false))
@@ -137,7 +137,7 @@ void AnyCharRule::setCharacterSet(const QString &s)
bool AnyCharRule::doMatchSucceed(const QString &text,
const int length,
- ProgressData *progress) const
+ ProgressData *progress)
{
Q_UNUSED(length)
@@ -167,7 +167,7 @@ void StringDetectRule::doReplaceExpressions(const QStringList &captures)
bool StringDetectRule::doMatchSucceed(const QString &text,
const int length,
- ProgressData *progress) const
+ ProgressData *progress)
{
if (length - progress->offset() >= m_length) {
QString candidate = text.fromRawData(text.unicode() + progress->offset(), m_length);
@@ -182,7 +182,11 @@ bool StringDetectRule::doMatchSucceed(const QString &text,
// RegExpr
void RegExprRule::setPattern(const QString &pattern)
-{ m_expression.setPattern(pattern); }
+{
+ if (pattern.startsWith(QLatin1Char('^')))
+ m_onlyBegin = true;
+ m_expression.setPattern(pattern);
+}
void RegExprRule::setInsensitive(const QString &insensitive)
{ m_expression.setCaseSensitivity(toCaseSensitivity(!toBool(insensitive))); }
@@ -197,23 +201,50 @@ void RegExprRule::doReplaceExpressions(const QStringList &captures)
m_expression.setPattern(s);
}
+void RegExprRule::doProgressFinished()
+{
+ m_isCached = false;
+}
+
+bool RegExprRule::isExactMatch(ProgressData *progress)
+{
+ if (progress->offset() == m_offset && m_length > 0) {
+ progress->incrementOffset(m_length);
+ progress->setCaptures(m_captures);
+ return true;
+ }
+ return false;
+}
+
bool RegExprRule::doMatchSucceed(const QString &text,
const int length,
- ProgressData *progress) const
+ ProgressData *progress)
{
Q_UNUSED(length)
- // This is not documented but a regular expression match is considered valid if it starts
- // at the current position and if the match length is not zero.
+ // A regular expression match is considered valid if it happens at the current position
+ // and if the match length is not zero.
const int offset = progress->offset();
- if (m_expression.indexIn(text, offset, QRegExp::CaretAtZero) == offset) {
- if (m_expression.matchedLength() == 0)
+ if (offset > 0 && m_onlyBegin)
+ return false;
+
+ if (m_isCached) {
+ if (offset < m_offset || m_offset == -1 || m_length == 0)
return false;
- progress->incrementOffset(m_expression.matchedLength());
- progress->setCaptures(m_expression.capturedTexts());
- return true;
+ if (isExactMatch(progress))
+ return true;
}
+ m_offset = m_expression.indexIn(text, offset, QRegExp::CaretAtOffset);
+ m_length = m_expression.matchedLength();
+ m_captures = m_expression.capturedTexts();
+
+ if (isExactMatch(progress))
+ return true;
+
+ m_isCached = true;
+ progress->trackRule(this);
+
return false;
}
@@ -241,7 +272,7 @@ void KeywordRule::setList(const QString &listName)
bool KeywordRule::doMatchSucceed(const QString &text,
const int length,
- ProgressData *progress) const
+ ProgressData *progress)
{
int current = progress->offset();
@@ -267,7 +298,7 @@ bool KeywordRule::doMatchSucceed(const QString &text,
// Int
bool IntRule::doMatchSucceed(const QString &text,
const int length,
- ProgressData *progress) const
+ ProgressData *progress)
{
const int offset = progress->offset();
@@ -285,7 +316,7 @@ bool IntRule::doMatchSucceed(const QString &text,
}
// Float
-bool FloatRule::doMatchSucceed(const QString &text, const int length, ProgressData *progress) const
+bool FloatRule::doMatchSucceed(const QString &text, const int length, ProgressData *progress)
{
progress->saveOffset();
@@ -326,7 +357,7 @@ bool FloatRule::doMatchSucceed(const QString &text, const int length, ProgressDa
// COctal
bool HlCOctRule::doMatchSucceed(const QString &text,
const int length,
- ProgressData *progress) const
+ ProgressData *progress)
{
if (matchCharacter(text, length, progress, kZero)) {
// In the definition files the number matching rules which are more restrictive should
@@ -349,7 +380,7 @@ bool HlCOctRule::doMatchSucceed(const QString &text,
// CHex
bool HlCHexRule::doMatchSucceed(const QString &text,
const int length,
- ProgressData *progress) const
+ ProgressData *progress)
{
if (matchCharacter(text, length, progress, kZero)) {
const int offset = progress->offset();
@@ -371,7 +402,7 @@ bool HlCHexRule::doMatchSucceed(const QString &text,
// CString
bool HlCStringCharRule::doMatchSucceed(const QString &text,
const int length,
- ProgressData *progress) const
+ ProgressData *progress)
{
if (matchEscapeSequence(text, length, progress))
return true;
@@ -388,7 +419,7 @@ bool HlCStringCharRule::doMatchSucceed(const QString &text,
// CChar
bool HlCCharRule::doMatchSucceed(const QString &text,
const int length,
- ProgressData *progress) const
+ ProgressData *progress)
{
if (matchCharacter(text, length, progress, kSingleQuote)) {
if (progress->offset() < length) {
@@ -423,7 +454,7 @@ void RangeDetectRule::setChar1(const QString &character)
bool RangeDetectRule::doMatchSucceed(const QString &text,
const int length,
- ProgressData *progress) const
+ ProgressData *progress)
{
if (matchCharacter(text, length, progress, m_char)) {
while (progress->offset() < length) {
@@ -440,7 +471,7 @@ bool RangeDetectRule::doMatchSucceed(const QString &text,
// LineContinue
bool LineContinueRule::doMatchSucceed(const QString &text,
const int length,
- ProgressData *progress) const
+ ProgressData *progress)
{
if (progress->offset() != length - 1)
return false;
@@ -460,7 +491,7 @@ DetectSpacesRule::DetectSpacesRule() : Rule(false)
bool DetectSpacesRule::doMatchSucceed(const QString &text,
const int length,
- ProgressData *progress) const
+ ProgressData *progress)
{
return charPredicateMatchSucceed(text, length, progress, &QChar::isSpace);
}
@@ -468,7 +499,7 @@ bool DetectSpacesRule::doMatchSucceed(const QString &text,
// DetectIdentifier
bool DetectIdentifierRule::doMatchSucceed(const QString &text,
const int length,
- ProgressData *progress) const
+ ProgressData *progress)
{
// Identifiers are characterized by a letter or underscore as the first character and then
// zero or more word characters (\w*).
diff --git a/src/plugins/texteditor/generichighlighter/specificrules.h b/src/plugins/texteditor/generichighlighter/specificrules.h
index ddb07e6362..029257a802 100644
--- a/src/plugins/texteditor/generichighlighter/specificrules.h
+++ b/src/plugins/texteditor/generichighlighter/specificrules.h
@@ -38,7 +38,7 @@
#include "dynamicrule.h"
#include <QtCore/QChar>
-#include <QtCore/QString>
+#include <QtCore/QStringList>
#include <QtCore/QRegExp>
#include <QtCore/QSharedPointer>
@@ -58,7 +58,7 @@ public:
private:
virtual bool doMatchSucceed(const QString &text,
const int length,
- ProgressData *progress) const;
+ ProgressData *progress);
virtual DetectCharRule *doClone() const { return new DetectCharRule(*this); }
virtual void doReplaceExpressions(const QStringList &captures);
@@ -76,7 +76,7 @@ public:
private:
virtual bool doMatchSucceed(const QString &text,
const int length,
- ProgressData *progress) const;
+ ProgressData *progress);
virtual Detect2CharsRule *doClone() const { return new Detect2CharsRule(*this); }
virtual void doReplaceExpressions(const QStringList &captures);
@@ -94,7 +94,7 @@ public:
private:
virtual bool doMatchSucceed(const QString &text,
const int length,
- ProgressData *progress) const;
+ ProgressData *progress);
virtual AnyCharRule *doClone() const { return new AnyCharRule(*this); }
QString m_characterSet;
@@ -111,7 +111,7 @@ public:
private:
virtual bool doMatchSucceed(const QString &text,
const int length,
- ProgressData *progress) const;
+ ProgressData *progress);
virtual StringDetectRule *doClone() const { return new StringDetectRule(*this); }
virtual void doReplaceExpressions(const QStringList &captures);
@@ -123,6 +123,7 @@ private:
class RegExprRule : public DynamicRule
{
public:
+ RegExprRule() : m_onlyBegin(false), m_isCached(false) {}
virtual ~RegExprRule() {}
void setPattern(const QString &pattern);
@@ -132,10 +133,18 @@ public:
private:
virtual bool doMatchSucceed(const QString &text,
const int length,
- ProgressData *progress) const;
+ ProgressData *progress);
virtual RegExprRule *doClone() const { return new RegExprRule(*this); }
virtual void doReplaceExpressions(const QStringList &captures);
+ virtual void doProgressFinished();
+ bool isExactMatch(ProgressData *progress);
+
+ bool m_onlyBegin;
+ bool m_isCached;
+ int m_offset;
+ int m_length;
+ QStringList m_captures;
QRegExp m_expression;
};
@@ -151,7 +160,7 @@ public:
private:
virtual bool doMatchSucceed(const QString &text,
const int length,
- ProgressData *progress) const;
+ ProgressData *progress);
virtual KeywordRule *doClone() const { return new KeywordRule(*this); }
bool m_overrideGlobal;
@@ -167,7 +176,7 @@ public:
private:
virtual bool doMatchSucceed(const QString &text,
const int length,
- ProgressData *progress) const;
+ ProgressData *progress);
virtual IntRule *doClone() const { return new IntRule(*this); }
};
@@ -179,7 +188,7 @@ public:
private:
virtual bool doMatchSucceed(const QString &text,
const int length,
- ProgressData *progress) const;
+ ProgressData *progress);
virtual FloatRule *doClone() const { return new FloatRule(*this); }
};
@@ -191,7 +200,7 @@ public:
private:
virtual bool doMatchSucceed(const QString &text,
const int length,
- ProgressData *progress) const;
+ ProgressData *progress);
virtual HlCOctRule *doClone() const { return new HlCOctRule(*this); }
};
@@ -203,7 +212,7 @@ public:
private:
virtual bool doMatchSucceed(const QString &text,
const int length,
- ProgressData *progress) const;
+ ProgressData *progress);
virtual HlCHexRule *doClone() const { return new HlCHexRule(*this); }
};
@@ -215,7 +224,7 @@ public:
private:
virtual bool doMatchSucceed(const QString &text,
const int length,
- ProgressData *progress) const;
+ ProgressData *progress);
virtual HlCStringCharRule *doClone() const { return new HlCStringCharRule(*this); }
};
@@ -227,7 +236,7 @@ public:
private:
virtual bool doMatchSucceed(const QString &text,
const int length,
- ProgressData *progress) const;
+ ProgressData *progress);
virtual HlCCharRule *doClone() const { return new HlCCharRule(*this); }
};
@@ -242,7 +251,7 @@ public:
private:
virtual bool doMatchSucceed(const QString &text,
const int length,
- ProgressData *progress) const;
+ ProgressData *progress);
virtual RangeDetectRule *doClone() const { return new RangeDetectRule(*this); }
QChar m_char;
@@ -257,7 +266,7 @@ public:
private:
virtual bool doMatchSucceed(const QString &text,
const int length,
- ProgressData *progress) const;
+ ProgressData *progress);
virtual LineContinueRule *doClone() const { return new LineContinueRule(*this); }
};
@@ -270,7 +279,7 @@ public:
private:
virtual bool doMatchSucceed(const QString &text,
const int length,
- ProgressData *progress) const;
+ ProgressData *progress);
virtual DetectSpacesRule *doClone() const { return new DetectSpacesRule(*this); }
};
@@ -282,7 +291,7 @@ public:
private:
virtual bool doMatchSucceed(const QString &text,
const int length,
- ProgressData *progress) const;
+ ProgressData *progress);
virtual DetectIdentifierRule *doClone() const { return new DetectIdentifierRule(*this); }
};
diff --git a/src/plugins/texteditor/helpitem.cpp b/src/plugins/texteditor/helpitem.cpp
index 6ec2978df6..d0fd8301db 100644
--- a/src/plugins/texteditor/helpitem.cpp
+++ b/src/plugins/texteditor/helpitem.cpp
@@ -112,8 +112,11 @@ QString HelpItem::extractContent(bool extended) const
case Macro:
contents = htmlExtractor.getMacroDescription(html, m_docMark);
break;
- case QML:
- contents = htmlExtractor.getQMLItemDescription(html, m_docMark);
+ case QmlComponent:
+ contents = htmlExtractor.getQmlComponentDescription(html, m_docMark);
+ break;
+ case QmlProperty:
+ contents = htmlExtractor.getQmlPropertyDescription(html, m_docMark);
break;
default:
diff --git a/src/plugins/texteditor/helpitem.h b/src/plugins/texteditor/helpitem.h
index 9026c24967..3bee8bc610 100644
--- a/src/plugins/texteditor/helpitem.h
+++ b/src/plugins/texteditor/helpitem.h
@@ -50,7 +50,8 @@ public:
Macro,
Brief,
Function,
- QML,
+ QmlComponent,
+ QmlProperty,
Unknown
};
diff --git a/src/plugins/texteditor/indenter.cpp b/src/plugins/texteditor/indenter.cpp
index 4f9fd1888f..b100274eaa 100644
--- a/src/plugins/texteditor/indenter.cpp
+++ b/src/plugins/texteditor/indenter.cpp
@@ -32,6 +32,7 @@
**************************************************************************/
#include "indenter.h"
+#include "basetexteditor.h"
#include "tabsettings.h"
using namespace TextEditor;
@@ -42,10 +43,67 @@ Indenter::Indenter()
Indenter::~Indenter()
{}
+bool Indenter::isElectricCharacter(const QChar &) const
+{
+ return false;
+}
+
void Indenter::indentBlock(QTextDocument *doc,
- QTextBlock block,
- QChar typedChar,
- const TabSettings &ts)
+ const QTextBlock &block,
+ const QChar &typedChar,
+ BaseTextEditor *editor)
{
- doIndentBlock(doc, block, typedChar, ts);
+ Q_UNUSED(doc);
+ Q_UNUSED(block);
+ Q_UNUSED(typedChar);
+ Q_UNUSED(editor);
+}
+
+void Indenter::indent(QTextDocument *doc,
+ const QTextCursor &cursor,
+ const QChar &typedChar,
+ BaseTextEditor *editor)
+{
+ if (cursor.hasSelection()) {
+ QTextBlock block = doc->findBlock(cursor.selectionStart());
+ const QTextBlock end = doc->findBlock(cursor.selectionEnd()).next();
+ do {
+ indentBlock(doc, block, typedChar, editor);
+ block = block.next();
+ } while (block.isValid() && block != end);
+ } else {
+ indentBlock(doc, cursor.block(), typedChar, editor);
+ }
+}
+
+void Indenter::reindent(QTextDocument *doc, const QTextCursor &cursor, BaseTextEditor *editor)
+{
+ if (cursor.hasSelection()) {
+ QTextBlock block = doc->findBlock(cursor.selectionStart());
+ const QTextBlock end = doc->findBlock(cursor.selectionEnd()).next();
+
+ const TabSettings &ts = editor->tabSettings();
+
+ // skip empty blocks
+ while (block.isValid() && block != end) {
+ QString bt = block.text();
+ if (ts.firstNonSpace(bt) < bt.size())
+ break;
+ indentBlock(doc, block, QChar::Null, editor);
+ block = block.next();
+ }
+
+ int previousIndentation = ts.indentationColumn(block.text());
+ indentBlock(doc, block, QChar::Null, editor);
+ int currentIndentation = ts.indentationColumn(block.text());
+ int delta = currentIndentation - previousIndentation;
+
+ block = block.next();
+ while (block.isValid() && block != end) {
+ ts.reindentLine(block, delta);
+ block = block.next();
+ }
+ } else {
+ indentBlock(doc, cursor.block(), QChar::Null, editor);
+ }
}
diff --git a/src/plugins/texteditor/indenter.h b/src/plugins/texteditor/indenter.h
index 0d575286b6..96616a7317 100644
--- a/src/plugins/texteditor/indenter.h
+++ b/src/plugins/texteditor/indenter.h
@@ -41,11 +41,12 @@
QT_BEGIN_NAMESPACE
class QTextDocument;
+class QTextCursor;
QT_END_NAMESPACE
namespace TextEditor {
-class TabSettings;
+class BaseTextEditor;
class TEXTEDITOR_EXPORT Indenter
{
@@ -53,13 +54,24 @@ public:
Indenter();
virtual ~Indenter();
- void indentBlock(QTextDocument *doc, QTextBlock block, QChar typedChar, const TabSettings &ts);
+ // Returns true if key triggers an indent.
+ virtual bool isElectricCharacter(const QChar &ch) const;
-private:
- virtual void doIndentBlock(QTextDocument *doc,
- QTextBlock block,
- QChar typedChar,
- const TabSettings &ts) = 0;
+ // Indent a text block based on previous line. Default does nothing
+ virtual void indentBlock(QTextDocument *doc,
+ const QTextBlock &block,
+ const QChar &typedChar,
+ BaseTextEditor *editor);
+
+ // Indent at cursor. Calls indentBlock for selection or current line.
+ virtual void indent(QTextDocument *doc,
+ const QTextCursor &cursor,
+ const QChar &typedChar,
+ BaseTextEditor *editor);
+
+ // Reindent at cursor. Selection will be adjusted according to the indentation
+ // change of the first block.
+ virtual void reindent(QTextDocument *doc, const QTextCursor &cursor, BaseTextEditor *editor);
};
} // namespace TextEditor
diff --git a/src/plugins/texteditor/itexteditor.cpp b/src/plugins/texteditor/itexteditor.cpp
index 0f3dc5d3aa..ebe1e03a19 100644
--- a/src/plugins/texteditor/itexteditor.cpp
+++ b/src/plugins/texteditor/itexteditor.cpp
@@ -35,6 +35,8 @@
#include <coreplugin/editormanager/editormanager.h>
+#include <QtCore/QTextCodec>
+
using namespace TextEditor;
QMap<QString, QString> ITextEditor::openedTextEditorsContents()
@@ -49,3 +51,16 @@ QMap<QString, QString> ITextEditor::openedTextEditorsContents()
}
return workingCopy;
}
+
+QMap<QString, QTextCodec *> TextEditor::ITextEditor::openedTextEditorsEncodings()
+{
+ QMap<QString, QTextCodec *> workingCopy;
+ foreach (Core::IEditor *editor, Core::EditorManager::instance()->openedEditors()) {
+ ITextEditor *textEditor = qobject_cast<ITextEditor *>(editor);
+ if (!textEditor)
+ continue;
+ QString fileName = textEditor->file()->fileName();
+ workingCopy[fileName] = textEditor->textCodec();
+ }
+ return workingCopy;
+}
diff --git a/src/plugins/texteditor/itexteditor.h b/src/plugins/texteditor/itexteditor.h
index 8eb5422769..6d21c68702 100644
--- a/src/plugins/texteditor/itexteditor.h
+++ b/src/plugins/texteditor/itexteditor.h
@@ -123,6 +123,7 @@ public:
virtual QTextCodec *textCodec() const = 0;
static QMap<QString, QString> openedTextEditorsContents();
+ static QMap<QString, QTextCodec *> openedTextEditorsEncodings();
signals:
void contentsChanged();
diff --git a/src/plugins/texteditor/linenumberfilter.cpp b/src/plugins/texteditor/linenumberfilter.cpp
index 8aff6c7029..9a7d32cda6 100644
--- a/src/plugins/texteditor/linenumberfilter.cpp
+++ b/src/plugins/texteditor/linenumberfilter.cpp
@@ -70,7 +70,7 @@ void LineNumberFilter::accept(FilterEntry selection) const
editorManager->addCurrentPositionToNavigationHistory();
editor->gotoLine(selection.internalData.toInt());
editor->widget()->setFocus();
- Core::ModeManager::instance()->activateMode(Core::Constants::MODE_EDIT);
+ Core::ModeManager::instance()->activateModeType(Core::Constants::MODE_EDIT_TYPE);
}
}
diff --git a/src/plugins/texteditor/normalindenter.cpp b/src/plugins/texteditor/normalindenter.cpp
index 444c9ce0e9..44f9f8daef 100644
--- a/src/plugins/texteditor/normalindenter.cpp
+++ b/src/plugins/texteditor/normalindenter.cpp
@@ -33,6 +33,7 @@
#include "normalindenter.h"
#include "tabsettings.h"
+#include "basetexteditor.h"
#include <QtGui/QTextDocument>
@@ -63,10 +64,10 @@ NormalIndenter::~NormalIndenter()
// for additional block being inserted. It might be possible
// to do in 2 steps (indenting/wrapping)}
//
-void NormalIndenter::doIndentBlock(QTextDocument *doc,
- QTextBlock block,
- QChar typedChar,
- const TextEditor::TabSettings &ts)
+void NormalIndenter::indentBlock(QTextDocument *doc,
+ const QTextBlock &block,
+ const QChar &typedChar,
+ BaseTextEditor *editor)
{
Q_UNUSED(typedChar)
@@ -82,6 +83,7 @@ void NormalIndenter::doIndentBlock(QTextDocument *doc,
// Just use previous line.
// Skip blank characters when determining the indentation
+ const TabSettings &ts = editor->tabSettings();
int i = 0;
while (i < previousText.size()) {
if (!previousText.at(i).isSpace()) {
diff --git a/src/plugins/texteditor/normalindenter.h b/src/plugins/texteditor/normalindenter.h
index 4ec8ca4d9d..a5604dcea6 100644
--- a/src/plugins/texteditor/normalindenter.h
+++ b/src/plugins/texteditor/normalindenter.h
@@ -44,11 +44,10 @@ public:
NormalIndenter();
virtual ~NormalIndenter();
-private:
- virtual void doIndentBlock(QTextDocument *doc,
- QTextBlock block,
- QChar typedChar,
- const TabSettings &ts);
+ virtual void indentBlock(QTextDocument *doc,
+ const QTextBlock &block,
+ const QChar &typedChar,
+ BaseTextEditor *editor);
};
} // namespace TextEditor
diff --git a/src/plugins/texteditor/plaintexteditor.cpp b/src/plugins/texteditor/plaintexteditor.cpp
index bc7f009fdc..fcd29896de 100644
--- a/src/plugins/texteditor/plaintexteditor.cpp
+++ b/src/plugins/texteditor/plaintexteditor.cpp
@@ -67,13 +67,13 @@ PlainTextEditorEditable::PlainTextEditorEditable(PlainTextEditor *editor)
PlainTextEditor::PlainTextEditor(QWidget *parent)
: BaseTextEditor(parent),
m_isMissingSyntaxDefinition(false),
- m_ignoreMissingSyntaxDefinition(false),
- m_indenter(new NormalIndenter) // Currently only "normal" indentation is supported.
+ m_ignoreMissingSyntaxDefinition(false)
{
setRevisionsVisible(true);
setMarksVisible(true);
setRequestMarkEnabled(false);
setLineSeparatorsAllowed(true);
+ setIndenter(new NormalIndenter); // Currently only "normal" indentation is supported.
setMimeType(QLatin1String(TextEditor::Constants::C_TEXTEDITOR_MIMETYPE_TEXT));
setDisplayName(tr(Core::Constants::K_DEFAULT_TEXT_EDITOR_DISPLAY_NAME));
@@ -232,11 +232,6 @@ QString PlainTextEditor::findDefinitionId(const Core::MimeType &mimeType,
return definitionId;
}
-void PlainTextEditor::indentBlock(QTextDocument *doc, QTextBlock block, QChar typedChar)
-{
- m_indenter->indentBlock(doc, block, typedChar, tabSettings());
-}
-
void PlainTextEditor::acceptMissingSyntaxDefinitionInfo()
{
Core::ICore::instance()->showOptionsDialog(Constants::TEXT_EDITOR_SETTINGS_CATEGORY,
diff --git a/src/plugins/texteditor/plaintexteditor.h b/src/plugins/texteditor/plaintexteditor.h
index 5bf8f613a4..66a3717fe0 100644
--- a/src/plugins/texteditor/plaintexteditor.h
+++ b/src/plugins/texteditor/plaintexteditor.h
@@ -93,14 +93,12 @@ signals:
protected:
virtual BaseTextEditorEditable *createEditableInterface() { return new PlainTextEditorEditable(this); }
- virtual void indentBlock(QTextDocument *doc, QTextBlock block, QChar typedChar);
private:
QString findDefinitionId(const Core::MimeType &mimeType, bool considerParents) const;
bool m_isMissingSyntaxDefinition;
bool m_ignoreMissingSyntaxDefinition;
- QScopedPointer<Indenter> m_indenter;
Utils::CommentDefinition m_commentDefinition;
};
diff --git a/src/plugins/texteditor/refactoroverlay.cpp b/src/plugins/texteditor/refactoroverlay.cpp
index 07bd35bc6b..68d0f22a17 100644
--- a/src/plugins/texteditor/refactoroverlay.cpp
+++ b/src/plugins/texteditor/refactoroverlay.cpp
@@ -1,10 +1,42 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "refactoroverlay.h"
-#include <QPainter>
-#include <QTextBlock>
#include "basetextdocumentlayout.h"
-#include <QDebug>
+#include "basetexteditor.h"
+
+#include <QtGui/QPainter>
+#include <QtGui/QTextBlock>
-using namespace TextEditor::Internal;
+#include <QtCore/QDebug>
+
+namespace TextEditor {
RefactorOverlay::RefactorOverlay(TextEditor::BaseTextEditor *editor) :
QObject(editor),
@@ -62,4 +94,4 @@ void RefactorOverlay::paintMarker(const RefactorMarker& marker, QPainter *painte
m_maxWidth = qMax((qreal)m_maxWidth, x + sz.width() - offset.x());
}
-
+} // namespace TextEditor
diff --git a/src/plugins/texteditor/refactoroverlay.h b/src/plugins/texteditor/refactoroverlay.h
index 6e4c3898b5..8f2255ff31 100644
--- a/src/plugins/texteditor/refactoroverlay.h
+++ b/src/plugins/texteditor/refactoroverlay.h
@@ -1,13 +1,42 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 REFACTOROVERLAY_H
#define REFACTOROVERLAY_H
-#include "basetexteditor.h"
+#include "texteditor_global.h"
#include <QtGui/QTextCursor>
#include <QtGui/QIcon>
namespace TextEditor {
-namespace Internal {
+class BaseTextEditor;
struct TEXTEDITOR_EXPORT RefactorMarker {
inline bool isValid() const { return !cursor.isNull(); }
@@ -41,11 +70,9 @@ private:
RefactorMarkers m_markers;
BaseTextEditor *m_editor;
int m_maxWidth;
- QIcon m_icon;
-
+ const QIcon m_icon;
};
-}
-}
+} // namespace TextEditor
#endif // REFACTOROVERLAY_H
diff --git a/src/plugins/texteditor/snippets/isnippetprovider.cpp b/src/plugins/texteditor/snippets/isnippetprovider.cpp
new file mode 100644
index 0000000000..f438ad0b00
--- /dev/null
+++ b/src/plugins/texteditor/snippets/isnippetprovider.cpp
@@ -0,0 +1,38 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "isnippetprovider.h"
+
+using namespace TextEditor;
+
+ISnippetProvider::ISnippetProvider() : QObject()
+{}
+
+ISnippetProvider::~ISnippetProvider()
+{}
diff --git a/src/plugins/texteditor/snippets/isnippetprovider.h b/src/plugins/texteditor/snippets/isnippetprovider.h
new file mode 100644
index 0000000000..8f3a881e5f
--- /dev/null
+++ b/src/plugins/texteditor/snippets/isnippetprovider.h
@@ -0,0 +1,59 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 ISNIPPETEDITORDECORATOR_H
+#define ISNIPPETEDITORDECORATOR_H
+
+#include "snippet.h"
+
+#include <texteditor/texteditor_global.h>
+
+#include <QtCore/QObject>
+
+namespace TextEditor {
+
+class SnippetEditor;
+
+class TEXTEDITOR_EXPORT ISnippetProvider : public QObject
+{
+ Q_OBJECT
+public:
+ virtual ~ISnippetProvider();
+
+ virtual QString groupId() const = 0;
+ virtual QString displayName() const = 0;
+ virtual void decorateEditor(SnippetEditor *editor) const = 0;
+
+protected:
+ ISnippetProvider();
+};
+
+} // TextEditor
+
+#endif // ISNIPPETEDITORDECORATOR_H
diff --git a/src/plugins/texteditor/snippets/plaintextsnippetprovider.cpp b/src/plugins/texteditor/snippets/plaintextsnippetprovider.cpp
new file mode 100644
index 0000000000..a333e201db
--- /dev/null
+++ b/src/plugins/texteditor/snippets/plaintextsnippetprovider.cpp
@@ -0,0 +1,56 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "plaintextsnippetprovider.h"
+
+#include <texteditor/texteditorconstants.h>
+
+#include <QtCore/QLatin1String>
+
+using namespace TextEditor;
+using namespace Internal;
+
+PlainTextSnippetProvider::PlainTextSnippetProvider()
+{}
+
+PlainTextSnippetProvider::~PlainTextSnippetProvider()
+{}
+
+QString PlainTextSnippetProvider::groupId() const
+{
+ return QLatin1String(Constants::TEXT_SNIPPET_GROUP_ID);
+}
+
+QString PlainTextSnippetProvider::displayName() const
+{
+ return tr("Text");
+}
+
+void PlainTextSnippetProvider::decorateEditor(TextEditor::SnippetEditor *) const
+{}
diff --git a/src/plugins/texteditor/snippets/plaintextsnippetprovider.h b/src/plugins/texteditor/snippets/plaintextsnippetprovider.h
new file mode 100644
index 0000000000..176490aa42
--- /dev/null
+++ b/src/plugins/texteditor/snippets/plaintextsnippetprovider.h
@@ -0,0 +1,57 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** No Commercial Usage
+**
+** This file 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.
+**
+**************************************************************************/
+
+#ifndef PLAINTEXTSNIPPETPROVIDER_H
+#define PLAINTEXTSNIPPETPROVIDER_H
+
+#include "isnippetprovider.h"
+
+namespace TextEditor {
+namespace Internal {
+
+class PlainTextSnippetProvider : public ISnippetProvider
+{
+public:
+ PlainTextSnippetProvider();
+ virtual ~PlainTextSnippetProvider();
+
+public:
+ virtual QString groupId() const;
+ virtual QString displayName() const;
+ virtual void decorateEditor(TextEditor::SnippetEditor *editor) const;
+};
+
+} // Internal
+} // TextEditor
+
+#endif // PLAINTEXTSNIPPETPROVIDER_H
diff --git a/src/plugins/texteditor/snippets/reuse.h b/src/plugins/texteditor/snippets/reuse.h
new file mode 100644
index 0000000000..17c4a34888
--- /dev/null
+++ b/src/plugins/texteditor/snippets/reuse.h
@@ -0,0 +1,59 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 REUSE_H
+#define REUSE_H
+
+#include <QtCore/QString>
+#include <QtCore/QLatin1String>
+
+namespace TextEditor {
+namespace Internal {
+
+const QLatin1String kTrue("true");
+const QLatin1String kFalse("false");
+
+inline bool toBool(const QString &s)
+{
+ if (s == kTrue)
+ return true;
+ return false;
+}
+
+inline QString fromBool(bool b)
+{
+ if (b)
+ return kTrue;
+ return kFalse;
+}
+
+} // Internal
+} // TextEditor
+
+#endif // REUSE_H
diff --git a/src/plugins/texteditor/snippets/snippet.cpp b/src/plugins/texteditor/snippets/snippet.cpp
new file mode 100644
index 0000000000..7291e8084b
--- /dev/null
+++ b/src/plugins/texteditor/snippets/snippet.cpp
@@ -0,0 +1,144 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "snippet.h"
+
+#include <QtCore/QLatin1Char>
+#include <QtCore/QLatin1String>
+#include <QtGui/QTextDocument>
+
+using namespace TextEditor;
+
+const QChar Snippet::kVariableDelimiter(QLatin1Char('$'));
+
+Snippet::Snippet(const QString &groupId, const QString &id) :
+ m_isRemoved(false), m_isModified(false), m_groupId(groupId), m_id(id)
+{}
+
+Snippet::~Snippet()
+{}
+
+const QString &Snippet::id() const
+{
+ return m_id;
+}
+
+const QString &Snippet::groupId() const
+{
+ return m_groupId;
+}
+
+bool Snippet::isBuiltIn() const
+{
+ return !m_id.isEmpty();
+}
+
+void Snippet::setTrigger(const QString &trigger)
+{
+ m_trigger = trigger;
+}
+
+const QString &Snippet::trigger() const
+{
+ return m_trigger;
+}
+
+void Snippet::setContent(const QString &content)
+{
+ m_content = content;
+}
+
+const QString &Snippet::content() const
+{
+ return m_content;
+}
+
+void Snippet::setComplement(const QString &complement)
+{
+ m_complement = complement;
+}
+
+const QString &Snippet::complement() const
+{
+ return m_complement;
+}
+
+void Snippet::setIsRemoved(bool removed)
+{
+ m_isRemoved = removed;
+}
+
+bool Snippet::isRemoved() const
+{
+ return m_isRemoved;
+}
+
+void Snippet::setIsModified(bool modified)
+{
+ m_isModified = modified;
+}
+
+bool Snippet::isModified() const
+{
+ return m_isModified;
+}
+
+QString Snippet::generateTip() const
+{
+ static const QLatin1Char kNewLine('\n');
+ static const QLatin1Char kSpace(' ');
+ static const QLatin1String kBr("<br>");
+ static const QLatin1String kNbsp("&nbsp;");
+ static const QLatin1String kNoBr("<nobr>");
+ static const QLatin1String kOpenBold("<b>");
+ static const QLatin1String kCloseBold("</b>");
+ static const QLatin1String kEllipsis("...");
+
+ QString escapedContent(Qt::escape(m_content));
+ escapedContent.replace(kNewLine, kBr);
+ escapedContent.replace(kSpace, kNbsp);
+
+ QString tip(kNoBr);
+ int count = 0;
+ for (int i = 0; i < escapedContent.count(); ++i) {
+ if (escapedContent.at(i) != kVariableDelimiter) {
+ tip += escapedContent.at(i);
+ continue;
+ }
+ if (++count % 2) {
+ tip += kOpenBold;
+ } else {
+ if (escapedContent.at(i-1) == kVariableDelimiter)
+ tip += kEllipsis;
+ tip += kCloseBold;
+ }
+ }
+
+ return tip;
+}
diff --git a/src/plugins/texteditor/snippets/snippet.h b/src/plugins/texteditor/snippets/snippet.h
new file mode 100644
index 0000000000..2ec985408b
--- /dev/null
+++ b/src/plugins/texteditor/snippets/snippet.h
@@ -0,0 +1,82 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 SNIPPET_H
+#define SNIPPET_H
+
+#include <texteditor/texteditor_global.h>
+
+#include <QtCore/QChar>
+#include <QtCore/QString>
+
+namespace TextEditor {
+
+class TEXTEDITOR_EXPORT Snippet
+{
+public:
+ Snippet(const QString &groupId = QString(), const QString &id = QString());
+ ~Snippet();
+
+ const QString &id() const;
+ const QString &groupId() const;
+
+ bool isBuiltIn() const;
+
+ void setTrigger(const QString &trigger);
+ const QString &trigger() const;
+
+ void setContent(const QString &content);
+ const QString &content() const;
+
+ void setComplement(const QString &complement);
+ const QString &complement() const;
+
+ void setIsRemoved(bool removed);
+ bool isRemoved() const;
+
+ void setIsModified(bool modified);
+ bool isModified() const;
+
+ QString generateTip() const;
+
+ static const QChar kVariableDelimiter;
+
+private:
+ bool m_isRemoved;
+ bool m_isModified;
+ QString m_groupId;
+ QString m_id; // Only built-in snippets have an id.
+ QString m_trigger;
+ QString m_content;
+ QString m_complement;
+};
+
+} // TextEditor
+
+#endif // SNIPPET_H
diff --git a/src/plugins/texteditor/snippets/snippetcollector.cpp b/src/plugins/texteditor/snippets/snippetcollector.cpp
new file mode 100644
index 0000000000..cfe08cd5d4
--- /dev/null
+++ b/src/plugins/texteditor/snippets/snippetcollector.cpp
@@ -0,0 +1,76 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "snippetcollector.h"
+#include "snippetscollection.h"
+
+#include <texteditor/texteditorconstants.h>
+
+using namespace TextEditor;
+using namespace Internal;
+
+namespace {
+
+void appendSnippets(ICompletionCollector *collector,
+ QList<CompletionItem> *completionItems,
+ const QString &groupId,
+ const QIcon &icon,
+ int order)
+{
+ SnippetsCollection *collection = SnippetsCollection::instance();
+ const int size = collection->totalActiveSnippets(groupId);
+ for (int i = 0; i < size; ++i) {
+ const Snippet &snippet = collection->snippet(i, groupId);
+ CompletionItem item(collector);
+ item.text = snippet.trigger() + QLatin1Char(' ') + snippet.complement();
+ item.data = snippet.content();
+ item.details = snippet.generateTip();
+ item.icon = icon;
+ item.order = order;
+ item.isSnippet = true;
+ completionItems->append(item);
+ }
+}
+
+} // anonymous
+
+SnippetCollector::SnippetCollector(const QString &groupId, const QIcon &icon, int order) :
+ m_groupId(groupId), m_icon(icon), m_order(order)
+{}
+
+SnippetCollector::~SnippetCollector()
+{}
+
+QList<CompletionItem> SnippetCollector::getSnippets(ICompletionCollector *collector) const
+{
+ QList<CompletionItem> completionItems;
+ appendSnippets(collector, &completionItems, m_groupId, m_icon, m_order);
+ appendSnippets(collector, &completionItems, Constants::TEXT_SNIPPET_GROUP_ID, m_icon, m_order);
+ return completionItems;
+}
diff --git a/src/plugins/texteditor/snippets/snippetcollector.h b/src/plugins/texteditor/snippets/snippetcollector.h
new file mode 100644
index 0000000000..8b44b74edf
--- /dev/null
+++ b/src/plugins/texteditor/snippets/snippetcollector.h
@@ -0,0 +1,58 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 SNIPPETPROVIDER_H
+#define SNIPPETPROVIDER_H
+
+#include <texteditor/texteditor_global.h>
+#include <texteditor/icompletioncollector.h>
+
+#include <QtCore/QString>
+#include <QtCore/QList>
+#include <QtGui/QIcon>
+
+namespace TextEditor {
+
+class TEXTEDITOR_EXPORT SnippetCollector
+{
+public:
+ SnippetCollector(const QString &groupId, const QIcon &icon, int order = 0);
+ ~SnippetCollector();
+
+ QList<CompletionItem> getSnippets(ICompletionCollector *collector) const;
+
+private:
+ QString m_groupId;
+ QIcon m_icon;
+ int m_order;
+};
+
+} // TextEditor
+
+#endif // SNIPPETPROVIDER_H
diff --git a/src/plugins/texteditor/snippets/snippeteditor.cpp b/src/plugins/texteditor/snippets/snippeteditor.cpp
new file mode 100644
index 0000000000..96e979a800
--- /dev/null
+++ b/src/plugins/texteditor/snippets/snippeteditor.cpp
@@ -0,0 +1,79 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "snippeteditor.h"
+
+#include <texteditor/basetextdocument.h>
+#include <texteditor/texteditorconstants.h>
+#include <texteditor/normalindenter.h>
+
+#include <QtGui/QTextDocument>
+#include <QtGui/QFocusEvent>
+
+using namespace TextEditor;
+
+SnippetEditorEditable::SnippetEditorEditable(SnippetEditor *editor) :
+ BaseTextEditorEditable(editor),
+ m_context(Constants::SNIPPET_EDITOR_ID, Constants::C_TEXTEDITOR)
+{}
+
+SnippetEditorEditable::~SnippetEditorEditable()
+{}
+
+QString SnippetEditorEditable::id() const
+{
+ return Constants::SNIPPET_EDITOR_ID;
+}
+
+SnippetEditor::SnippetEditor(QWidget *parent) : BaseTextEditor(parent)
+{
+ setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
+ setHighlightCurrentLine(false);
+ setLineNumbersVisible(false);
+ setParenthesesMatchingEnabled(true);
+}
+
+SnippetEditor::~SnippetEditor()
+{}
+
+void SnippetEditor::setSyntaxHighlighter(TextEditor::SyntaxHighlighter *highlighter)
+{
+ baseTextDocument()->setSyntaxHighlighter(highlighter);
+}
+
+void SnippetEditor::focusOutEvent(QFocusEvent *event)
+{
+ if (event->reason() != Qt::ActiveWindowFocusReason && document()->isModified())
+ emit snippetContentChanged();
+}
+
+BaseTextEditorEditable *SnippetEditor::createEditableInterface()
+{
+ return new SnippetEditorEditable(this);
+}
diff --git a/src/plugins/texteditor/snippets/snippeteditor.h b/src/plugins/texteditor/snippets/snippeteditor.h
new file mode 100644
index 0000000000..dfd822f986
--- /dev/null
+++ b/src/plugins/texteditor/snippets/snippeteditor.h
@@ -0,0 +1,87 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 SNIPPETEDITOR_H
+#define SNIPPETEDITOR_H
+
+#include <texteditor/texteditor_global.h>
+#include <texteditor/basetexteditor.h>
+
+#include <QtCore/QScopedPointer>
+
+QT_FORWARD_DECLARE_CLASS(QFocusEvent)
+
+namespace TextEditor {
+
+class SnippetEditor;
+class SyntaxHighlighter;
+class Indenter;
+
+// Should not be necessary in this case, but the base text editor assumes a
+// valid editable interface.
+class TEXTEDITOR_EXPORT SnippetEditorEditable : public BaseTextEditorEditable
+{
+ Q_OBJECT
+public:
+ SnippetEditorEditable(SnippetEditor *editor);
+ virtual ~SnippetEditorEditable();
+
+ Core::Context context() const { return m_context; }
+
+ bool duplicateSupported() const { return false; }
+ Core::IEditor *duplicate(QWidget * /* parent */ ) { return 0; }
+ bool isTemporary() const { return false; }
+ virtual QString id() const;
+
+private:
+ const Core::Context m_context;
+};
+
+class TEXTEDITOR_EXPORT SnippetEditor : public BaseTextEditor
+{
+ Q_OBJECT
+public:
+ SnippetEditor(QWidget *parent);
+ virtual ~SnippetEditor();
+
+ void setSyntaxHighlighter(SyntaxHighlighter *highlighter);
+
+signals:
+ void snippetContentChanged();
+
+protected:
+ virtual void focusOutEvent(QFocusEvent *event);
+
+ virtual int extraAreaWidth(int * /* markWidthPtr */ = 0) const { return 0; }
+ virtual BaseTextEditorEditable *createEditableInterface();
+};
+
+} // TextEditor
+
+#endif // SNIPPETEDITOR_H
diff --git a/src/plugins/texteditor/snippets/snippetscollection.cpp b/src/plugins/texteditor/snippets/snippetscollection.cpp
new file mode 100644
index 0000000000..c368e16ddf
--- /dev/null
+++ b/src/plugins/texteditor/snippets/snippetscollection.cpp
@@ -0,0 +1,433 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "snippetscollection.h"
+#include "isnippetprovider.h"
+#include "reuse.h"
+
+#include <coreplugin/icore.h>
+#include <extensionsystem/pluginmanager.h>
+
+#include <QtCore/QLatin1String>
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+#include <QtCore/QDir>
+#include <QtCore/QDebug>
+#include <QtCore/QXmlStreamReader>
+#include <QtAlgorithms>
+
+#include <iterator>
+#include <algorithm>
+
+using namespace TextEditor;
+using namespace Internal;
+
+namespace {
+
+struct SnippetComp
+{
+ bool operator()(const Snippet &a, const Snippet &b) const
+ {
+ const int comp = a.trigger().toLower().localeAwareCompare(b.trigger().toLower());
+ if (comp < 0)
+ return true;
+ else if (comp == 0 &&
+ a.complement().toLower().localeAwareCompare(b.complement().toLower()) < 0)
+ return true;
+ return false;
+ }
+};
+SnippetComp snippetComp;
+
+struct RemovedSnippetPred
+{
+ bool operator()(const Snippet &s) const
+ {
+ return s.isRemoved();
+ }
+};
+RemovedSnippetPred removedSnippetPred;
+
+} // Anonymous
+
+const QLatin1String SnippetsCollection::kSnippet("snippet");
+const QLatin1String SnippetsCollection::kSnippets("snippets");
+const QLatin1String SnippetsCollection::kTrigger("trigger");
+const QLatin1String SnippetsCollection::kId("id");
+const QLatin1String SnippetsCollection::kComplement("complement");
+const QLatin1String SnippetsCollection::kGroup("group");
+const QLatin1String SnippetsCollection::kRemoved("removed");
+const QLatin1String SnippetsCollection::kModified("modified");
+
+// Hint
+SnippetsCollection::Hint::Hint(int index) : m_index(index)
+{}
+
+SnippetsCollection::Hint::Hint(int index, QList<Snippet>::iterator it) : m_index(index), m_it(it)
+{}
+
+int SnippetsCollection::Hint::index() const
+{
+ return m_index;
+}
+
+SnippetsCollection *SnippetsCollection::instance()
+{
+ static SnippetsCollection collection;
+ return &collection;
+}
+
+// SnippetsCollection
+SnippetsCollection::SnippetsCollection() :
+ m_userSnippetsPath(Core::ICore::instance()->userResourcePath() + QLatin1String("/snippets/")),
+ m_userSnippetsFile(QLatin1String("snippets.xml"))
+{
+ QDir dir(Core::ICore::instance()->resourcePath() + QLatin1String("/snippets/"));
+ dir.setNameFilters(QStringList(QLatin1String("*.xml")));
+ foreach (const QFileInfo &fi, dir.entryInfoList())
+ m_builtInSnippetsFiles.append(fi.absoluteFilePath());
+
+ connect(Core::ICore::instance(), SIGNAL(coreOpened()), this, SLOT(identifyGroups()));
+}
+
+SnippetsCollection::~SnippetsCollection()
+{}
+
+void SnippetsCollection::insertSnippet(const Snippet &snippet)
+{
+ insertSnippet(snippet, computeInsertionHint(snippet));
+}
+
+void SnippetsCollection::insertSnippet(const Snippet &snippet, const Hint &hint)
+{
+ const int group = groupIndex(snippet.groupId());
+ if (snippet.isBuiltIn() && snippet.isRemoved()) {
+ m_activeSnippetsEnd[group] = m_snippets[group].insert(m_activeSnippetsEnd[group], snippet);
+ } else {
+ m_snippets[group].insert(hint.m_it, snippet);
+ updateActiveSnippetsEnd(group);
+ }
+}
+
+SnippetsCollection::Hint SnippetsCollection::computeInsertionHint(const Snippet &snippet)
+{
+ const int group = groupIndex(snippet.groupId());
+ QList<Snippet> &snippets = m_snippets[group];
+ QList<Snippet>::iterator it = qUpperBound(
+ snippets.begin(), m_activeSnippetsEnd.at(group), snippet, snippetComp);
+ return Hint(static_cast<int>(std::distance(snippets.begin(), it)), it);
+}
+
+void SnippetsCollection::replaceSnippet(int index, const Snippet &snippet)
+{
+ replaceSnippet(index, snippet, computeReplacementHint(index, snippet));
+}
+
+void SnippetsCollection::replaceSnippet(int index, const Snippet &snippet, const Hint &hint)
+{
+ const int group = groupIndex(snippet.groupId());
+ Snippet replacement(snippet);
+ if (replacement.isBuiltIn() && !replacement.isModified())
+ replacement.setIsModified(true);
+
+ if (index == hint.index()) {
+ m_snippets[group][index] = replacement;
+ } else {
+ insertSnippet(replacement, hint);
+ // Consider whether the row moved up towards the beginning or down towards the end.
+ if (index < hint.index())
+ m_snippets[group].removeAt(index);
+ else
+ m_snippets[group].removeAt(index + 1);
+ updateActiveSnippetsEnd(group);
+ }
+}
+
+SnippetsCollection::Hint SnippetsCollection::computeReplacementHint(int index,
+ const Snippet &snippet)
+{
+ const int group = groupIndex(snippet.groupId());
+ QList<Snippet> &snippets = m_snippets[group];
+ QList<Snippet>::iterator it = qLowerBound(
+ snippets.begin(), m_activeSnippetsEnd.at(group), snippet, snippetComp);
+ int hintIndex = static_cast<int>(std::distance(snippets.begin(), it));
+ if (index < hintIndex - 1)
+ return Hint(hintIndex - 1, it);
+ it = qUpperBound(it, m_activeSnippetsEnd.at(group), snippet, snippetComp);
+ hintIndex = static_cast<int>(std::distance(snippets.begin(), it));
+ if (index > hintIndex)
+ return Hint(hintIndex, it);
+ // Even if the snipet is at a different index it is still inside a valid range.
+ return Hint(index);
+}
+
+void SnippetsCollection::removeSnippet(int index, const QString &groupId)
+{
+ const int group = groupIndex(groupId);
+ Snippet snippet(m_snippets.at(group).at(index));
+ m_snippets[group].removeAt(index);
+ if (snippet.isBuiltIn()) {
+ snippet.setIsRemoved(true);
+ m_activeSnippetsEnd[group] = m_snippets[group].insert(m_activeSnippetsEnd[group], snippet);
+ } else {
+ updateActiveSnippetsEnd(group);
+ }
+}
+
+const Snippet &SnippetsCollection::snippet(int index, const QString &groupId) const
+{
+ return m_snippets.at(groupIndex(groupId)).at(index);
+}
+
+void SnippetsCollection::setSnippetContent(int index,
+ const QString &groupId,
+ const QString &content)
+{
+ Snippet &snippet = m_snippets[groupIndex(groupId)][index];
+ snippet.setContent(content);
+ if (snippet.isBuiltIn() && !snippet.isModified())
+ snippet.setIsModified(true);
+}
+
+int SnippetsCollection::totalActiveSnippets(const QString &groupId) const
+{
+ const int group = groupIndex(groupId);
+ return std::distance<QList<Snippet>::const_iterator>(m_snippets.at(group).begin(),
+ m_activeSnippetsEnd.at(group));
+}
+
+int SnippetsCollection::totalSnippets(const QString &groupId) const
+{
+ return m_snippets.at(groupIndex(groupId)).size();
+}
+
+QList<QString> SnippetsCollection::groupIds() const
+{
+ return m_groupIndexById.keys();
+}
+
+void SnippetsCollection::clearSnippets()
+{
+ for (int group = 0; group < m_groupIndexById.size(); ++group)
+ clearSnippets(group);
+}
+
+void SnippetsCollection::clearSnippets(int groupIndex)
+{
+ m_snippets[groupIndex].clear();
+ m_activeSnippetsEnd[groupIndex] = m_snippets[groupIndex].end();
+}
+
+void SnippetsCollection::updateActiveSnippetsEnd(int groupIndex)
+{
+ m_activeSnippetsEnd[groupIndex] = std::find_if(m_snippets[groupIndex].begin(),
+ m_snippets[groupIndex].end(),
+ removedSnippetPred);
+}
+
+void SnippetsCollection::restoreRemovedSnippets(const QString &groupId)
+{
+ // The version restored contains the last modifications (if any) by the user.
+ // Reverting the snippet can still bring it to the original version
+ const int group = groupIndex(groupId);
+ QVector<Snippet> toRestore(std::distance(m_activeSnippetsEnd[group], m_snippets[group].end()));
+ qCopy(m_activeSnippetsEnd[group], m_snippets[group].end(), toRestore.begin());
+ m_snippets[group].erase(m_activeSnippetsEnd[group], m_snippets[group].end());
+ foreach (Snippet snippet, toRestore) {
+ snippet.setIsRemoved(false);
+ insertSnippet(snippet);
+ }
+}
+
+Snippet SnippetsCollection::revertedSnippet(int index, const QString &groupId) const
+{
+ const Snippet &candidate = snippet(index, groupId);
+ Q_ASSERT(candidate.isBuiltIn());
+
+ foreach (const QString &fileName, m_builtInSnippetsFiles) {
+ const QList<Snippet> &builtIn = readXML(fileName, candidate.id());
+ if (builtIn.size() == 1)
+ return builtIn.at(0);
+ }
+ return Snippet(groupId);
+}
+
+void SnippetsCollection::reset(const QString &groupId)
+{
+ clearSnippets(groupIndex(groupId));
+
+ const QList<Snippet> &builtInSnippets = allBuiltInSnippets();
+ foreach (const Snippet &snippet, builtInSnippets)
+ if (groupId == snippet.groupId())
+ insertSnippet(snippet);
+}
+
+void SnippetsCollection::reload()
+{
+ clearSnippets();
+
+ const QList<Snippet> &builtInSnippets = allBuiltInSnippets();
+ QHash<QString, Snippet> activeBuiltInSnippets;
+ foreach (const Snippet &snippet, builtInSnippets)
+ activeBuiltInSnippets.insert(snippet.id(), snippet);
+
+ const QList<Snippet> &userSnippets = readXML(m_userSnippetsPath + m_userSnippetsFile);
+ foreach (const Snippet &snippet, userSnippets) {
+ if (snippet.isBuiltIn())
+ // This user snippet overrides the corresponding built-in snippet.
+ activeBuiltInSnippets.remove(snippet.id());
+ insertSnippet(snippet);
+ }
+
+ foreach (const Snippet &snippet, activeBuiltInSnippets)
+ insertSnippet(snippet);
+}
+
+void SnippetsCollection::synchronize()
+{
+ if (QFile::exists(m_userSnippetsPath) || QDir().mkpath(m_userSnippetsPath)) {
+ QFile file(m_userSnippetsPath + m_userSnippetsFile);
+ if (file.open(QFile::WriteOnly | QFile::Truncate)) {
+ QXmlStreamWriter writer(&file);
+ writer.setAutoFormatting(true);
+ writer.writeStartDocument();
+ writer.writeStartElement(kSnippets);
+ foreach (const QString &groupId, m_groupIndexById.keys()) {
+ const int size = m_snippets.at(groupIndex(groupId)).size();
+ for (int i = 0; i < size; ++i) {
+ const Snippet &current = snippet(i, groupId);
+ if (!current.isBuiltIn() || current.isRemoved() || current.isModified())
+ writeSnippetXML(current, &writer);
+ }
+ }
+ writer.writeEndElement();
+ writer.writeEndDocument();
+ file.close();
+ }
+ }
+
+ reload();
+}
+
+void SnippetsCollection::writeSnippetXML(const Snippet &snippet, QXmlStreamWriter *writer) const
+{
+ writer->writeStartElement(kSnippet);
+ writer->writeAttribute(kGroup, snippet.groupId());
+ writer->writeAttribute(kTrigger, snippet.trigger());
+ writer->writeAttribute(kId, snippet.id());
+ writer->writeAttribute(kComplement, snippet.complement());
+ writer->writeAttribute(kRemoved, fromBool(snippet.isRemoved()));
+ writer->writeAttribute(kModified, fromBool(snippet.isModified()));
+ writer->writeCharacters(snippet.content());
+ writer->writeEndElement();
+}
+
+QList<Snippet> SnippetsCollection::readXML(const QString &fileName, const QString &snippetId) const
+{
+ QList<Snippet> snippets;
+ QFile file(fileName);
+ if (file.exists() && file.open(QIODevice::ReadOnly)) {
+ QXmlStreamReader xml(&file);
+ if (xml.readNextStartElement()) {
+ if (xml.name() == kSnippets) {
+ while (xml.readNextStartElement()) {
+ if (xml.name() == kSnippet) {
+ const QXmlStreamAttributes &atts = xml.attributes();
+ const QString &id = atts.value(kId).toString();
+ const QString &groupId = atts.value(kGroup).toString();
+ if (isGroupKnown(groupId) && (snippetId.isEmpty() || snippetId == id)) {
+ Snippet snippet(groupId, id);
+ snippet.setTrigger(atts.value(kTrigger).toString());
+ snippet.setComplement(atts.value(kComplement).toString());
+ snippet.setIsRemoved(toBool(atts.value(kRemoved).toString()));
+ snippet.setIsModified(toBool(atts.value(kModified).toString()));
+
+ QString content;
+ while (!xml.atEnd()) {
+ xml.readNext();
+ if (xml.isCharacters()) {
+ content += xml.text();
+ } else if (xml.isEndElement()) {
+ snippet.setContent(content);
+ snippets.append(snippet);
+ break;
+ }
+ }
+
+ if (!snippetId.isEmpty())
+ break;
+ } else {
+ xml.skipCurrentElement();
+ }
+ } else {
+ xml.skipCurrentElement();
+ }
+ }
+ }
+ }
+ if (xml.hasError())
+ qWarning() << fileName << xml.errorString() << xml.lineNumber() << xml.columnNumber();
+ file.close();
+ }
+
+ return snippets;
+}
+
+QList<Snippet> SnippetsCollection::allBuiltInSnippets() const
+{
+ QList<Snippet> builtInSnippets;
+ foreach (const QString &fileName, m_builtInSnippetsFiles)
+ builtInSnippets.append(readXML(fileName));
+ return builtInSnippets;
+}
+
+int SnippetsCollection::groupIndex(const QString &groupId) const
+{
+ return m_groupIndexById.value(groupId);
+}
+
+void SnippetsCollection::identifyGroups()
+{
+ const QList<ISnippetProvider *> &providers =
+ ExtensionSystem::PluginManager::instance()->getObjects<ISnippetProvider>();
+ foreach (ISnippetProvider *provider, providers) {
+ const int groupIndex = m_groupIndexById.size();
+ m_groupIndexById.insert(provider->groupId(), groupIndex);
+ m_snippets.resize(groupIndex + 1);
+ m_activeSnippetsEnd.resize(groupIndex + 1);
+ m_activeSnippetsEnd[groupIndex] = m_snippets[groupIndex].end();
+ }
+
+ reload();
+}
+
+bool SnippetsCollection::isGroupKnown(const QString &groupId) const
+{
+ return m_groupIndexById.value(groupId, -1) != -1;
+}
diff --git a/src/plugins/texteditor/snippets/snippetscollection.h b/src/plugins/texteditor/snippets/snippetscollection.h
new file mode 100644
index 0000000000..4c46356135
--- /dev/null
+++ b/src/plugins/texteditor/snippets/snippetscollection.h
@@ -0,0 +1,147 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 SNIPPETSCOLLECTION_H
+#define SNIPPETSCOLLECTION_H
+
+#include "snippet.h"
+
+#include <QtCore/QVector>
+#include <QtCore/QStringList>
+#include <QtCore/QHash>
+#include <QtCore/QXmlStreamWriter>
+
+namespace TextEditor {
+namespace Internal {
+
+// Characteristics of this collection:
+// - Store snippets by group.
+// - Keep groups of snippets sorted.
+// - Allow snippet insertion/replacement based on a hint.
+// - Allow modification of snippet members that are not sorting keys.
+// - Track removed/modified built-in snippets.
+// - Provide fast index access.
+// - Not thread-safe.
+
+class SnippetsCollection : public QObject
+{
+ Q_OBJECT
+public:
+ virtual ~SnippetsCollection();
+
+ static SnippetsCollection *instance();
+
+ class Hint
+ {
+ friend class SnippetsCollection;
+ public:
+ int index() const;
+ private:
+ explicit Hint(int index);
+ Hint(int index, QList<Snippet>::iterator it);
+ int m_index;
+ QList<Snippet>::iterator m_it;
+ };
+
+ void insertSnippet(const Snippet &snippet);
+ void insertSnippet(const Snippet &snippet, const Hint &hint);
+ Hint computeInsertionHint(const Snippet &snippet);
+
+ // Replace snippets only within the same group.
+ void replaceSnippet(int index, const Snippet &snippet);
+ void replaceSnippet(int index, const Snippet &snippet, const Hint &hint);
+ Hint computeReplacementHint(int index, const Snippet &snippet);
+
+ void removeSnippet(int index, const QString &groupId);
+ void restoreRemovedSnippets(const QString &groupId);
+
+ void setSnippetContent(int index, const QString &groupId, const QString &content);
+
+ const Snippet &snippet(int index, const QString &groupId) const;
+ Snippet revertedSnippet(int index, const QString &groupId) const;
+
+ void reset(const QString &groupId);
+
+ int totalActiveSnippets(const QString &groupId) const;
+ int totalSnippets(const QString &groupId) const;
+
+ QList<QString> groupIds() const;
+
+ void reload();
+ void synchronize();
+
+private slots:
+ void identifyGroups();
+
+private:
+ SnippetsCollection();
+ Q_DISABLE_COPY(SnippetsCollection)
+
+ int groupIndex(const QString &groupId) const;
+ bool isGroupKnown(const QString &groupId) const;
+
+ void clearSnippets();
+ void clearSnippets(int groupIndex);
+
+ void updateActiveSnippetsEnd(int groupIndex);
+
+ QList<Snippet> readXML(const QString &fileName, const QString &snippetId = QString()) const;
+ void writeSnippetXML(const Snippet &snippet, QXmlStreamWriter *writer) const;
+
+ QList<Snippet> allBuiltInSnippets() const;
+
+ static const QLatin1String kSnippet;
+ static const QLatin1String kSnippets;
+ static const QLatin1String kTrigger;
+ static const QLatin1String kId;
+ static const QLatin1String kComplement;
+ static const QLatin1String kGroup;
+ static const QLatin1String kRemoved;
+ static const QLatin1String kModified;
+
+ // Built-in snippets are specified in XMLs distributed in a system's folder. Snippets
+ // created or modified/removed (if they are built-ins) by the user are stored in user's
+ // folder.
+ QString m_userSnippetsPath;
+ QString m_userSnippetsFile;
+ QStringList m_builtInSnippetsFiles;
+
+ // Snippets for each group are kept in a list. However, not all of them are necessarily
+ // active. Specifically, removed built-in snippets are kept as the last ones (for each
+ // group there is a iterator that marks the logical end).
+ QVector<QList<Snippet> > m_snippets;
+ QVector<QList<Snippet>::iterator> m_activeSnippetsEnd;
+
+ QHash<QString, int> m_groupIndexById;
+};
+
+} // Internal
+} // TextEditor
+
+#endif // SNIPPETSCOLLECTION_H
diff --git a/src/plugins/texteditor/snippets/snippetssettings.cpp b/src/plugins/texteditor/snippets/snippetssettings.cpp
new file mode 100644
index 0000000000..7a58ea83d3
--- /dev/null
+++ b/src/plugins/texteditor/snippets/snippetssettings.cpp
@@ -0,0 +1,81 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** No Commercial Usage
+**
+** This file 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.
+**
+**************************************************************************/
+
+#include "snippetssettings.h"
+#include "reuse.h"
+
+#include <QtCore/QSettings>
+
+namespace {
+
+static const QLatin1String kGroupPostfix("SnippetsSettings");
+static const QLatin1String kLastUsedSnippetGroup("LastUsedSnippetGroup");
+
+} // Anonymous
+
+using namespace TextEditor;
+using namespace Internal;
+
+SnippetsSettings::SnippetsSettings()
+{}
+
+void SnippetsSettings::toSettings(const QString &category, QSettings *s) const
+{
+ const QString &group = category + kGroupPostfix;
+ s->beginGroup(group);
+ s->setValue(kLastUsedSnippetGroup, m_lastUsedSnippetGroup);
+ s->endGroup();
+}
+
+void SnippetsSettings::fromSettings(const QString &category, QSettings *s)
+{
+ const QString &group = category + kGroupPostfix;
+ s->beginGroup(group);
+ m_lastUsedSnippetGroup = s->value(kLastUsedSnippetGroup, QString()).toString();
+ s->endGroup();
+}
+
+void SnippetsSettings::setLastUsedSnippetGroup(const QString &lastUsed)
+{
+ m_lastUsedSnippetGroup = lastUsed;
+}
+
+const QString &SnippetsSettings::lastUsedSnippetGroup() const
+{
+ return m_lastUsedSnippetGroup;
+}
+
+bool SnippetsSettings::equals(const SnippetsSettings &snippetsSettings) const
+{
+ return m_lastUsedSnippetGroup == snippetsSettings.m_lastUsedSnippetGroup;
+}
diff --git a/src/plugins/texteditor/snippets/snippetssettings.h b/src/plugins/texteditor/snippets/snippetssettings.h
new file mode 100644
index 0000000000..c7765e821c
--- /dev/null
+++ b/src/plugins/texteditor/snippets/snippetssettings.h
@@ -0,0 +1,70 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** No Commercial Usage
+**
+** This file 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.
+**
+**************************************************************************/
+
+#ifndef SNIPPETSSETTINGS_H
+#define SNIPPETSSETTINGS_H
+
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+class QSettings;
+QT_END_NAMESPACE
+
+namespace TextEditor {
+
+class SnippetsSettings
+{
+public:
+ SnippetsSettings();
+
+ void toSettings(const QString &category, QSettings *s) const;
+ void fromSettings(const QString &category, QSettings *s);
+
+ void setLastUsedSnippetGroup(const QString &lastUsed);
+ const QString &lastUsedSnippetGroup() const;
+
+ bool equals(const SnippetsSettings &snippetsSettings) const;
+
+private:
+ QString m_lastUsedSnippetGroup;
+};
+
+inline bool operator==(const SnippetsSettings &a, const SnippetsSettings &b)
+{ return a.equals(b); }
+
+inline bool operator!=(const SnippetsSettings &a, const SnippetsSettings &b)
+{ return !a.equals(b); }
+
+} // TextEditor
+
+#endif // SNIPPETSSETTINGS_H
diff --git a/src/plugins/texteditor/snippets/snippetssettingspage.cpp b/src/plugins/texteditor/snippets/snippetssettingspage.cpp
new file mode 100644
index 0000000000..ddb151464c
--- /dev/null
+++ b/src/plugins/texteditor/snippets/snippetssettingspage.cpp
@@ -0,0 +1,574 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "snippetssettingspage.h"
+#include "snippeteditor.h"
+#include "isnippetprovider.h"
+#include "snippet.h"
+#include "snippetscollection.h"
+#include "snippetssettings.h"
+#include "reuse.h"
+#include "ui_snippetssettingspage.h"
+
+#include <coreplugin/icore.h>
+#include <extensionsystem/pluginmanager.h>
+
+#include <QtCore/QModelIndex>
+#include <QtCore/QAbstractTableModel>
+#include <QtCore/QList>
+#include <QtCore/QSettings>
+#include <QtCore/QTextStream>
+#include <QtCore/QHash>
+#include <QtGui/QMessageBox>
+
+namespace TextEditor {
+namespace Internal {
+
+// SnippetsTableModel
+class SnippetsTableModel : public QAbstractTableModel
+{
+ Q_OBJECT
+public:
+ SnippetsTableModel(QObject *parent);
+ virtual ~SnippetsTableModel() {}
+
+ virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ virtual int columnCount(const QModelIndex &parent = QModelIndex()) const;
+ virtual Qt::ItemFlags flags(const QModelIndex &modelIndex) const;
+ virtual QVariant data(const QModelIndex &modelIndex, int role = Qt::DisplayRole) const;
+ virtual bool setData(const QModelIndex &modelIndex, const QVariant &value,
+ int role = Qt::EditRole);
+ virtual QVariant headerData(int section, Qt::Orientation orientation,
+ int role = Qt::DisplayRole) const;
+
+ QList<QString> groupIds() const;
+ void load(const QString &groupId);
+
+ QModelIndex createSnippet();
+ QModelIndex insertSnippet(const Snippet &snippet);
+ void removeSnippet(const QModelIndex &modelIndex);
+ const Snippet &snippetAt(const QModelIndex &modelIndex) const;
+ void setSnippetContent(const QModelIndex &modelIndex, const QString &content);
+ void revertBuitInSnippet(const QModelIndex &modelIndex);
+ void restoreRemovedBuiltInSnippets();
+ void resetSnippets();
+
+private:
+ void replaceSnippet(const Snippet &snippet, const QModelIndex &modelIndex);
+ static bool isValidTrigger(const QString &s);
+
+ SnippetsCollection* m_collection;
+ QString m_activeGroupId;
+};
+
+SnippetsTableModel::SnippetsTableModel(QObject *parent) :
+ QAbstractTableModel(parent),
+ m_collection(SnippetsCollection::instance())
+{}
+
+int SnippetsTableModel::rowCount(const QModelIndex &) const
+{
+ return m_collection->totalActiveSnippets(m_activeGroupId);
+}
+
+int SnippetsTableModel::columnCount(const QModelIndex &) const
+{
+ return 2;
+}
+
+Qt::ItemFlags SnippetsTableModel::flags(const QModelIndex &index) const
+{
+ Qt::ItemFlags itemFlags = QAbstractTableModel::flags(index);
+ if (index.isValid())
+ itemFlags |= Qt::ItemIsEditable;
+ return itemFlags;
+}
+
+QVariant SnippetsTableModel::data(const QModelIndex &modelIndex, int role) const
+{
+ if (!modelIndex.isValid())
+ return QVariant();
+
+ if (role == Qt::DisplayRole || role == Qt::EditRole) {
+ const Snippet &snippet = m_collection->snippet(modelIndex.row(), m_activeGroupId);
+ if (modelIndex.column() == 0)
+ return snippet.trigger();
+ else
+ return snippet.complement();
+ } else {
+ return QVariant();
+ }
+}
+
+bool SnippetsTableModel::setData(const QModelIndex &modelIndex, const QVariant &value, int role)
+{
+ if (modelIndex.isValid() && role == Qt::EditRole) {
+ Snippet snippet(m_collection->snippet(modelIndex.row(), m_activeGroupId));
+ if (modelIndex.column() == 0) {
+ const QString &s = value.toString();
+ if (!isValidTrigger(s)) {
+ QMessageBox::critical(0, tr("Error"), tr("Not a valid trigger."));
+ if (snippet.trigger().isEmpty())
+ removeSnippet(modelIndex);
+ return false;
+ }
+ snippet.setTrigger(s);
+ } else {
+ snippet.setComplement(value.toString());
+ }
+
+ replaceSnippet(snippet, modelIndex);
+ return true;
+ }
+ return false;
+}
+
+QVariant SnippetsTableModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (role != Qt::DisplayRole || orientation != Qt::Horizontal)
+ return QVariant();
+
+ if (section == 0)
+ return tr("Trigger");
+ else
+ return tr("Complement");
+}
+
+void SnippetsTableModel::load(const QString &groupId)
+{
+ m_activeGroupId = groupId;
+ reset();
+}
+
+QList<QString> SnippetsTableModel::groupIds() const
+{
+ return m_collection->groupIds();
+}
+
+QModelIndex SnippetsTableModel::createSnippet()
+{
+ Snippet snippet(m_activeGroupId);
+ return insertSnippet(snippet);
+}
+
+QModelIndex SnippetsTableModel::insertSnippet(const Snippet &snippet)
+{
+ const SnippetsCollection::Hint &hint = m_collection->computeInsertionHint(snippet);
+ beginInsertRows(QModelIndex(), hint.index(), hint.index());
+ m_collection->insertSnippet(snippet, hint);
+ endInsertRows();
+
+ return index(hint.index(), 0);
+}
+
+void SnippetsTableModel::removeSnippet(const QModelIndex &modelIndex)
+{
+ beginRemoveRows(QModelIndex(), modelIndex.row(), modelIndex.row());
+ m_collection->removeSnippet(modelIndex.row(), m_activeGroupId);
+ endRemoveRows();
+}
+
+const Snippet &SnippetsTableModel::snippetAt(const QModelIndex &modelIndex) const
+{
+ return m_collection->snippet(modelIndex.row(), m_activeGroupId);
+}
+
+void SnippetsTableModel::setSnippetContent(const QModelIndex &modelIndex, const QString &content)
+{
+ m_collection->setSnippetContent(modelIndex.row(), m_activeGroupId, content);
+}
+
+void SnippetsTableModel::revertBuitInSnippet(const QModelIndex &modelIndex)
+{
+ const Snippet &snippet = m_collection->revertedSnippet(modelIndex.row(), m_activeGroupId);
+ if (snippet.id().isEmpty()) {
+ QMessageBox::critical(0, tr("Error"), tr("Error reverting snippet."));
+ return;
+ }
+ replaceSnippet(snippet, modelIndex);
+}
+
+void SnippetsTableModel::restoreRemovedBuiltInSnippets()
+{
+ m_collection->restoreRemovedSnippets(m_activeGroupId);
+ reset();
+}
+
+void SnippetsTableModel::resetSnippets()
+{
+ m_collection->reset(m_activeGroupId);
+ reset();
+}
+
+void SnippetsTableModel::replaceSnippet(const Snippet &snippet, const QModelIndex &modelIndex)
+{
+ const int row = modelIndex.row();
+ const SnippetsCollection::Hint &hint =
+ m_collection->computeReplacementHint(row, snippet);
+ if (modelIndex.row() == hint.index()) {
+ m_collection->replaceSnippet(row, snippet, hint);
+ if (modelIndex.column() == 0)
+ emit dataChanged(modelIndex, modelIndex.sibling(row, 1));
+ else
+ emit dataChanged(modelIndex.sibling(row, 0), modelIndex);
+ } else {
+ if (row < hint.index())
+ // Rows will be moved down.
+ beginMoveRows(QModelIndex(), row, row, QModelIndex(), hint.index() + 1);
+ else
+ beginMoveRows(QModelIndex(), row, row, QModelIndex(), hint.index());
+ m_collection->replaceSnippet(row, snippet, hint);
+ endMoveRows();
+ }
+}
+
+bool SnippetsTableModel::isValidTrigger(const QString &s)
+{
+ if (s.isEmpty())
+ return false;
+ for (int i = 0; i < s.length(); ++i)
+ if (!s.at(i).isLetter())
+ return false;
+ return true;
+}
+
+// SnippetsSettingsPagePrivate
+class SnippetsSettingsPagePrivate : public QObject
+{
+ Q_OBJECT
+public:
+ SnippetsSettingsPagePrivate(const QString &id);
+ ~SnippetsSettingsPagePrivate() { delete m_model; }
+
+ const QString &id() const { return m_id; }
+ const QString &displayName() const { return m_displayName; }
+ bool isKeyword(const QString &s) const { return m_keywords.contains(s, Qt::CaseInsensitive); }
+ void configureUi(QWidget *parent);
+
+ void apply();
+ void finish();
+
+private slots:
+ void loadSnippetGroup(int index);
+ void markSnippetsCollection();
+ void addSnippet();
+ void removeSnippet();
+ void revertBuiltInSnippet();
+ void restoreRemovedBuiltInSnippets();
+ void resetAllSnippets();
+ void selectSnippet(const QModelIndex &parent, int row);
+ void selectMovedSnippet(const QModelIndex &, int, int, const QModelIndex &, int row);
+ void setSnippetContent();
+ void updateCurrentSnippetDependent(const QModelIndex &modelIndex = QModelIndex());
+
+private:
+ SnippetEditor *currentEditor() const;
+ SnippetEditor *editorAt(int i) const;
+
+ void loadSettings();
+ bool settingsChanged() const;
+ void writeSettings();
+
+ const QString m_id;
+ const QString m_displayName;
+ const QString m_settingsPrefix;
+ SnippetsTableModel *m_model;
+ bool m_snippetsCollectionChanged;
+ QString m_keywords;
+ SnippetsSettings m_settings;
+ Ui::SnippetsSettingsPage m_ui;
+};
+
+SnippetsSettingsPagePrivate::SnippetsSettingsPagePrivate(const QString &id) :
+ m_id(id),
+ m_displayName(tr("Snippets")),
+ m_settingsPrefix(QLatin1String("Text")),
+ m_model(new SnippetsTableModel(0)),
+ m_snippetsCollectionChanged(false)
+{}
+
+SnippetEditor *SnippetsSettingsPagePrivate::currentEditor() const
+{
+ return editorAt(m_ui.snippetsEditorStack->currentIndex());
+}
+
+SnippetEditor *SnippetsSettingsPagePrivate::editorAt(int i) const
+{
+ return static_cast<SnippetEditor *>(m_ui.snippetsEditorStack->widget(i));
+}
+
+void SnippetsSettingsPagePrivate::configureUi(QWidget *w)
+{
+ m_ui.setupUi(w);
+
+ const QList<ISnippetProvider *> &providers =
+ ExtensionSystem::PluginManager::instance()->getObjects<ISnippetProvider>();
+ foreach (ISnippetProvider *provider, providers) {
+ m_ui.groupCombo->addItem(provider->displayName(), provider->groupId());
+ SnippetEditor *snippetEditor = new SnippetEditor(w);
+ provider->decorateEditor(snippetEditor);
+ m_ui.snippetsEditorStack->insertWidget(m_ui.groupCombo->count() - 1, snippetEditor);
+ connect(snippetEditor, SIGNAL(snippetContentChanged()), this, SLOT(setSnippetContent()));
+ }
+
+ m_ui.snippetsTable->setSelectionBehavior(QAbstractItemView::SelectRows);
+ m_ui.snippetsTable->setSelectionMode(QAbstractItemView::SingleSelection);
+ m_ui.snippetsTable->horizontalHeader()->setStretchLastSection(true);
+ m_ui.snippetsTable->horizontalHeader()->setHighlightSections(false);
+ m_ui.snippetsTable->verticalHeader()->setVisible(false);
+ m_ui.snippetsTable->verticalHeader()->setDefaultSectionSize(20);
+ m_ui.snippetsTable->setModel(m_model);
+
+ m_ui.revertButton->setEnabled(false);
+
+ QTextStream(&m_keywords) << m_displayName;
+
+ loadSettings();
+ loadSnippetGroup(m_ui.groupCombo->currentIndex());
+
+ connect(m_model, SIGNAL(rowsInserted(QModelIndex, int, int)),
+ this, SLOT(selectSnippet(QModelIndex,int)));
+ connect(m_model, SIGNAL(rowsInserted(QModelIndex, int, int)),
+ this, SLOT(markSnippetsCollection()));
+ connect(m_model, SIGNAL(rowsRemoved(QModelIndex, int, int)),
+ this, SLOT(markSnippetsCollection()));
+ connect(m_model, SIGNAL(rowsMoved(QModelIndex, int, int, QModelIndex, int)),
+ this, SLOT(selectMovedSnippet(QModelIndex,int,int,QModelIndex,int)));
+ connect(m_model, SIGNAL(rowsMoved(QModelIndex, int, int, QModelIndex, int)),
+ this, SLOT(markSnippetsCollection()));
+ connect(m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
+ this, SLOT(markSnippetsCollection()));
+ connect(m_model, SIGNAL(modelReset()), this, SLOT(updateCurrentSnippetDependent()));
+ connect(m_model, SIGNAL(modelReset()), this, SLOT(markSnippetsCollection()));
+
+ connect(m_ui.groupCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(loadSnippetGroup(int)));
+ connect(m_ui.addButton, SIGNAL(clicked()), this, SLOT(addSnippet()));
+ connect(m_ui.removeButton, SIGNAL(clicked()), this, SLOT(removeSnippet()));
+ connect(m_ui.resetAllButton, SIGNAL(clicked()), this, SLOT(resetAllSnippets()));
+ connect(m_ui.restoreRemovedButton, SIGNAL(clicked()),
+ this, SLOT(restoreRemovedBuiltInSnippets()));
+ connect(m_ui.revertButton, SIGNAL(clicked()), this, SLOT(revertBuiltInSnippet()));
+ connect(m_ui.snippetsTable->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
+ this, SLOT(updateCurrentSnippetDependent(QModelIndex)));
+}
+
+void SnippetsSettingsPagePrivate::apply()
+{
+ if (settingsChanged())
+ writeSettings();
+
+ if (m_snippetsCollectionChanged) {
+ SnippetsCollection::instance()->synchronize();
+ m_snippetsCollectionChanged = false;
+ }
+}
+
+void SnippetsSettingsPagePrivate::finish()
+{
+ if (m_snippetsCollectionChanged) {
+ SnippetsCollection::instance()->reload();
+ m_snippetsCollectionChanged = false;
+ }
+}
+
+void SnippetsSettingsPagePrivate::loadSettings()
+{
+ if (m_ui.groupCombo->count() == 0)
+ return;
+
+ if (QSettings *s = Core::ICore::instance()->settings()) {
+ m_settings.fromSettings(m_settingsPrefix, s);
+ const QString &lastGroupName = m_settings.lastUsedSnippetGroup();
+ const int index = m_ui.groupCombo->findText(lastGroupName);
+ if (index != -1)
+ m_ui.groupCombo->setCurrentIndex(index);
+ else
+ m_ui.groupCombo->setCurrentIndex(0);
+ }
+}
+
+void SnippetsSettingsPagePrivate::writeSettings()
+{
+ if (m_ui.groupCombo->count() == 0)
+ return;
+
+ if (QSettings *s = Core::ICore::instance()->settings()) {
+ m_settings.setLastUsedSnippetGroup(m_ui.groupCombo->currentText());
+ m_settings.toSettings(m_settingsPrefix, s);
+ }
+}
+
+bool SnippetsSettingsPagePrivate::settingsChanged() const
+{
+ if (m_settings.lastUsedSnippetGroup() != m_ui.groupCombo->currentText())
+ return true;
+ return false;
+}
+
+void SnippetsSettingsPagePrivate::loadSnippetGroup(int index)
+{
+ if (index == -1)
+ return;
+
+ m_ui.snippetsEditorStack->setCurrentIndex(index);
+ currentEditor()->clear();
+ m_model->load(m_ui.groupCombo->itemData(index).toString());
+}
+
+void SnippetsSettingsPagePrivate::markSnippetsCollection()
+{
+ if (!m_snippetsCollectionChanged)
+ m_snippetsCollectionChanged = true;
+}
+
+void SnippetsSettingsPagePrivate::addSnippet()
+{
+ const QModelIndex &modelIndex = m_model->createSnippet();
+ selectSnippet(QModelIndex(), modelIndex.row());
+ m_ui.snippetsTable->edit(modelIndex);
+}
+
+void SnippetsSettingsPagePrivate::removeSnippet()
+{
+ const QModelIndex &modelIndex = m_ui.snippetsTable->selectionModel()->currentIndex();
+ if (!modelIndex.isValid()) {
+ QMessageBox::critical(0, tr("Error"), tr("No snippet selected."));
+ return;
+ }
+ m_model->removeSnippet(modelIndex);
+}
+
+void SnippetsSettingsPagePrivate::restoreRemovedBuiltInSnippets()
+{
+ m_model->restoreRemovedBuiltInSnippets();
+}
+
+void SnippetsSettingsPagePrivate::revertBuiltInSnippet()
+{
+ m_model->revertBuitInSnippet(m_ui.snippetsTable->selectionModel()->currentIndex());
+}
+
+void SnippetsSettingsPagePrivate::resetAllSnippets()
+{
+ m_model->resetSnippets();
+}
+
+void SnippetsSettingsPagePrivate::selectSnippet(const QModelIndex &parent, int row)
+{
+ QModelIndex topLeft = m_model->index(row, 0, parent);
+ QModelIndex bottomRight = m_model->index(row, 1, parent);
+ QItemSelection selection(topLeft, bottomRight);
+ m_ui.snippetsTable->selectionModel()->select(selection, QItemSelectionModel::SelectCurrent);
+ m_ui.snippetsTable->setCurrentIndex(topLeft);
+ m_ui.snippetsTable->scrollTo(topLeft);
+}
+
+void SnippetsSettingsPagePrivate::selectMovedSnippet(const QModelIndex &,
+ int sourceRow,
+ int,
+ const QModelIndex &destinationParent,
+ int destinationRow)
+{
+ QModelIndex modelIndex;
+ if (sourceRow < destinationRow)
+ modelIndex = m_model->index(destinationRow - 1, 0, destinationParent);
+ else
+ modelIndex = m_model->index(destinationRow, 0, destinationParent);
+ m_ui.snippetsTable->scrollTo(modelIndex);
+ currentEditor()->setPlainText(m_model->snippetAt(modelIndex).content());
+}
+
+void SnippetsSettingsPagePrivate::updateCurrentSnippetDependent(const QModelIndex &modelIndex)
+{
+ if (modelIndex.isValid()) {
+ const Snippet &snippet = m_model->snippetAt(modelIndex);
+ currentEditor()->setPlainText(snippet.content());
+ m_ui.revertButton->setEnabled(snippet.isBuiltIn());
+ } else {
+ currentEditor()->clear();
+ m_ui.revertButton->setEnabled(false);
+ }
+}
+
+void SnippetsSettingsPagePrivate::setSnippetContent()
+{
+ const QModelIndex &modelIndex = m_ui.snippetsTable->selectionModel()->currentIndex();
+ if (modelIndex.isValid()) {
+ m_model->setSnippetContent(modelIndex, currentEditor()->toPlainText());
+ markSnippetsCollection();
+ }
+}
+
+// SnippetsSettingsPage
+SnippetsSettingsPage::SnippetsSettingsPage(const QString &id, QObject *parent) :
+ TextEditorOptionsPage(parent),
+ m_d(new SnippetsSettingsPagePrivate(id))
+{}
+
+SnippetsSettingsPage::~SnippetsSettingsPage()
+{
+ delete m_d;
+}
+
+QString SnippetsSettingsPage::id() const
+{
+ return m_d->id();
+}
+
+QString SnippetsSettingsPage::displayName() const
+{
+ return m_d->displayName();
+}
+
+bool SnippetsSettingsPage::matches(const QString &s) const
+{
+ return m_d->isKeyword(s);
+}
+
+QWidget *SnippetsSettingsPage::createPage(QWidget *parent)
+{
+ QWidget *w = new QWidget(parent);
+ m_d->configureUi(w);
+ return w;
+}
+
+void SnippetsSettingsPage::apply()
+{
+ m_d->apply();
+}
+
+void SnippetsSettingsPage::finish()
+{
+ m_d->finish();
+}
+
+} // Internal
+} // TextEditor
+
+#include "snippetssettingspage.moc"
diff --git a/src/plugins/texteditor/snippets/snippetssettingspage.h b/src/plugins/texteditor/snippets/snippetssettingspage.h
new file mode 100644
index 0000000000..cf39c77ea9
--- /dev/null
+++ b/src/plugins/texteditor/snippets/snippetssettingspage.h
@@ -0,0 +1,65 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** No Commercial Usage
+**
+** This file 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.
+**
+**************************************************************************/
+
+#ifndef SNIPPETSSETTINGSPAGE_H
+#define SNIPPETSSETTINGSPAGE_H
+
+#include "texteditoroptionspage.h"
+
+namespace TextEditor {
+namespace Internal {
+
+class SnippetsSettingsPagePrivate;
+
+class SnippetsSettingsPage : public TextEditorOptionsPage
+{
+ Q_OBJECT
+public:
+ SnippetsSettingsPage(const QString &id, QObject *parent);
+ virtual ~SnippetsSettingsPage();
+
+ virtual QString id() const;
+ virtual QString displayName() const;
+ virtual bool matches(const QString &s) const;
+ virtual QWidget *createPage(QWidget *parent);
+ virtual void apply();
+ virtual void finish();
+
+private:
+ SnippetsSettingsPagePrivate *m_d;
+};
+
+} // Internal
+} // TextEditor
+
+#endif // SNIPPETSSETTINGSPAGE_H
diff --git a/src/plugins/texteditor/snippets/snippetssettingspage.ui b/src/plugins/texteditor/snippets/snippetssettingspage.ui
new file mode 100644
index 0000000000..e95fa7afc7
--- /dev/null
+++ b/src/plugins/texteditor/snippets/snippetssettingspage.ui
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>SnippetsSettingsPage</class>
+ <widget class="QWidget" name="SnippetsSettingsPage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>684</width>
+ <height>554</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="groupLabel">
+ <property name="text">
+ <string>Group: </string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="groupCombo"/>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QTableView" name="snippetsTable">
+ <property name="editTriggers">
+ <set>QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QStackedWidget" name="snippetsEditorStack">
+ <property name="currentIndex">
+ <number>1</number>
+ </property>
+ <widget class="QWidget" name="page"/>
+ <widget class="QWidget" name="page_2"/>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QPushButton" name="addButton">
+ <property name="text">
+ <string>Add</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="removeButton">
+ <property name="text">
+ <string>Remove</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="revertButton">
+ <property name="text">
+ <string>Revert Built-in</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="restoreRemovedButton">
+ <property name="text">
+ <string>Restore Removed Built-ins</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="resetAllButton">
+ <property name="text">
+ <string>Reset All</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <tabstops>
+ <tabstop>groupCombo</tabstop>
+ <tabstop>addButton</tabstop>
+ <tabstop>removeButton</tabstop>
+ <tabstop>snippetsTable</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/plugins/texteditor/snippetsparser.cpp b/src/plugins/texteditor/snippetsparser.cpp
deleted file mode 100644
index 15d8d09f85..0000000000
--- a/src/plugins/texteditor/snippetsparser.cpp
+++ /dev/null
@@ -1,148 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#include "snippetsparser.h"
-
-#include <QtCore/QFile>
-#include <QtCore/QFileInfo>
-#include <QtCore/QLatin1String>
-#include <QtCore/QLatin1Char>
-#include <QtCore/QVariant>
-#include <QtCore/QXmlStreamReader>
-#include <QtCore/QDebug>
-#include <QtGui/QTextDocument>
-
-using namespace TextEditor;
-
-SnippetsParser::SnippetsParser(const QString &fileName) : m_fileName(fileName)
-{}
-
-const QList<CompletionItem> &SnippetsParser::execute(ICompletionCollector *collector,
- const QIcon &icon,
- int order)
-{
- if (!QFile::exists(m_fileName)) {
- m_snippets.clear();
- } else {
- const QDateTime &lastModified = QFileInfo(m_fileName).lastModified();
- if (m_lastTrackedFileChange.isNull() || m_lastTrackedFileChange != lastModified) {
- m_snippets.clear();
- QFile file(m_fileName);
- file.open(QIODevice::ReadOnly);
- QXmlStreamReader xml(&file);
- if (xml.readNextStartElement()) {
- if (xml.name() == QLatin1String("snippets")) {
- while (xml.readNextStartElement()) {
- if (xml.name() == QLatin1String("snippet")) {
- TextEditor::CompletionItem item(collector);
- QString title;
- QString data;
- QString description = xml.attributes().value("description").toString();
-
- while (!xml.atEnd()) {
- xml.readNext();
- if (xml.isEndElement()) {
- int i = 0;
- while (i < data.size() && data.at(i).isLetterOrNumber())
- ++i;
- title = data.left(i);
- item.text = title;
- if (!description.isEmpty()) {
- item.text += QLatin1Char(' ');
- item.text += description;
- }
- item.data = QVariant::fromValue(data.trimmed());
-
- QString infotip = data;
- while (infotip.size() && infotip.at(infotip.size()-1).isSpace())
- infotip.chop(1);
- infotip = Qt::escape(infotip);
- infotip.replace(QLatin1Char('\n'), QLatin1String("<br>"));
- infotip.replace(QLatin1Char(' '), QLatin1String("&nbsp;"));
- {
- QString s = QLatin1String("<nobr>");
- int count = 0;
- for (int i = 0; i < infotip.count(); ++i) {
- if (infotip.at(i) != QChar::ObjectReplacementCharacter) {
- s += infotip.at(i);
- continue;
- }
- if (++count % 2) {
- s += QLatin1String("<b>");
- } else {
- if (infotip.at(i-1) == QChar::ObjectReplacementCharacter)
- s += QLatin1String("...");
- s += QLatin1String("</b>");
- }
- }
- infotip = s;
- }
- item.details = infotip;
-
- item.icon = icon;
- item.order = order;
- item.isSnippet = true;
- m_snippets.append(item);
- break;
- }
-
- if (xml.isCharacters())
- data += xml.text();
- else if (xml.isStartElement()) {
- if (xml.name() != QLatin1String("tab"))
- xml.raiseError(QLatin1String("invalid snippets file"));
- else {
- data += QChar::ObjectReplacementCharacter;
- data += xml.readElementText();
- data += QChar::ObjectReplacementCharacter;
- }
- }
- }
- } else {
- xml.skipCurrentElement();
- }
- }
- } else {
- xml.skipCurrentElement();
- }
- }
- if (xml.hasError())
- qWarning() << m_fileName << xml.errorString() << xml.lineNumber() << xml.columnNumber();
- file.close();
-
- m_lastTrackedFileChange = lastModified;
- }
- }
-
- return m_snippets;
-}
diff --git a/src/plugins/texteditor/snippetsparser.h b/src/plugins/texteditor/snippetsparser.h
deleted file mode 100644
index 050baef2e0..0000000000
--- a/src/plugins/texteditor/snippetsparser.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#ifndef SNIPPETSPARSER_H
-#define SNIPPETSPARSER_H
-
-#include "texteditor_global.h"
-#include "icompletioncollector.h"
-
-#include <QtCore/QString>
-#include <QtCore/QList>
-#include <QtCore/QDateTime>
-#include <QtGui/QIcon>
-
-namespace TextEditor {
-
-class TEXTEDITOR_EXPORT SnippetsParser
-{
-public:
- SnippetsParser(const QString &fileName);
-
- const QList<CompletionItem> &execute(ICompletionCollector *collector,
- const QIcon &icon,
- int order = 0);
-
-private:
- QString m_fileName;
- QDateTime m_lastTrackedFileChange;
- QList<CompletionItem> m_snippets;
-};
-
-} // namespace TextEditor
-
-#endif // SNIPPETSPARSER_H
diff --git a/src/plugins/texteditor/texteditor.pri b/src/plugins/texteditor/texteditor.pri
index 9d3789b825..c1c3e7a19a 100644
--- a/src/plugins/texteditor/texteditor.pri
+++ b/src/plugins/texteditor/texteditor.pri
@@ -1,3 +1,3 @@
include(texteditor_dependencies.pri)
-LIBS *= -l$$qtLibraryTarget(TextEditor)
+LIBS *= -l$$qtLibraryName(TextEditor)
diff --git a/src/plugins/texteditor/texteditor.pro b/src/plugins/texteditor/texteditor.pro
index 21a4ba9952..70b93fc195 100644
--- a/src/plugins/texteditor/texteditor.pro
+++ b/src/plugins/texteditor/texteditor.pro
@@ -5,9 +5,11 @@ QT += xml network
include(../../qtcreatorplugin.pri)
include(texteditor_dependencies.pri)
INCLUDEPATH += generichighlighter \
- tooltip
+ tooltip \
+ snippets
DEPENDPATH += generichighlighter \
- tooltip
+ tooltip \
+ snippets
SOURCES += texteditorplugin.cpp \
textfilewizard.cpp \
plaintexteditor.cpp \
@@ -70,7 +72,15 @@ SOURCES += texteditorplugin.cpp \
tooltip/tipfactory.cpp \
basehoverhandler.cpp \
helpitem.cpp \
- snippetsparser.cpp
+ autocompleter.cpp \
+ snippets/snippetssettingspage.cpp \
+ snippets/snippet.cpp \
+ snippets/snippeteditor.cpp \
+ snippets/snippetscollection.cpp \
+ snippets/snippetssettings.cpp \
+ snippets/isnippetprovider.cpp \
+ snippets/snippetcollector.cpp \
+ snippets/plaintextsnippetprovider.cpp
HEADERS += texteditorplugin.h \
textfilewizard.h \
@@ -144,13 +154,23 @@ HEADERS += texteditorplugin.h \
tooltip/tipfactory.h \
basehoverhandler.h \
helpitem.h \
- snippetsparser.h
+ autocompleter.h \
+ snippets/snippetssettingspage.h \
+ snippets/snippet.h \
+ snippets/snippeteditor.h \
+ snippets/snippetscollection.h \
+ snippets/reuse.h \
+ snippets/snippetssettings.h \
+ snippets/isnippetprovider.h \
+ snippets/snippetcollector.h \
+ snippets/plaintextsnippetprovider.h
FORMS += behaviorsettingspage.ui \
displaysettingspage.ui \
fontsettingspage.ui \
colorschemeedit.ui \
generichighlighter/highlightersettingspage.ui \
- generichighlighter/managedefinitionsdialog.ui
+ generichighlighter/managedefinitionsdialog.ui \
+ snippets/snippetssettingspage.ui
RESOURCES += texteditor.qrc
-OTHER_FILES += TextEditor.pluginspec TextEditor.mimetypes.xml
+OTHER_FILES += TextEditor.mimetypes.xml
diff --git a/src/plugins/texteditor/texteditoractionhandler.cpp b/src/plugins/texteditor/texteditoractionhandler.cpp
index ba08d34c1e..0da2681fcb 100644
--- a/src/plugins/texteditor/texteditoractionhandler.cpp
+++ b/src/plugins/texteditor/texteditoractionhandler.cpp
@@ -46,6 +46,7 @@
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/uniqueidmanager.h>
#include <utils/qtcassert.h>
#include <QtCore/QSet>
@@ -330,6 +331,12 @@ void TextEditorActionHandler::createActions()
a = new QAction(tr("Goto Next Word"), this);
command = am->registerAction(a, Constants::GOTO_NEXT_WORD, m_contextId);
connect(a, SIGNAL(triggered()), this, SLOT(gotoNextWord()));
+ a = new QAction(tr("Goto Previous Word Camel Case"), this);
+ command = am->registerAction(a, Constants::GOTO_PREVIOUS_WORD_CAMEL_CASE, m_contextId);
+ connect(a, SIGNAL(triggered()), this, SLOT(gotoPreviousWordCamelCase()));
+ a = new QAction(tr("Goto Next Word Camel Case"), this);
+ command = am->registerAction(a, Constants::GOTO_NEXT_WORD_CAMEL_CASE, m_contextId);
+ connect(a, SIGNAL(triggered()), this, SLOT(gotoNextWordCamelCase()));
a = new QAction(tr("Goto Line Start With Selection"), this);
command = am->registerAction(a, Constants::GOTO_LINE_START_WITH_SELECTION, m_contextId);
@@ -355,6 +362,12 @@ void TextEditorActionHandler::createActions()
a = new QAction(tr("Goto Next Word With Selection"), this);
command = am->registerAction(a, Constants::GOTO_NEXT_WORD_WITH_SELECTION, m_contextId);
connect(a, SIGNAL(triggered()), this, SLOT(gotoNextWordWithSelection()));
+ a = new QAction(tr("Goto Previous Word Camel Case With Selection"), this);
+ command = am->registerAction(a, Constants::GOTO_PREVIOUS_WORD_CAMEL_CASE_WITH_SELECTION, m_contextId);
+ connect(a, SIGNAL(triggered()), this, SLOT(gotoPreviousWordCamelCaseWithSelection()));
+ a = new QAction(tr("Goto Next Word Camel Case With Selection"), this);
+ command = am->registerAction(a, Constants::GOTO_NEXT_WORD_CAMEL_CASE_WITH_SELECTION, m_contextId);
+ connect(a, SIGNAL(triggered()), this, SLOT(gotoNextWordCamelCaseWithSelection()));
}
@@ -535,8 +548,12 @@ FUNCTION(gotoNextCharacter)
FUNCTION(gotoNextCharacterWithSelection)
FUNCTION(gotoPreviousWord)
FUNCTION(gotoPreviousWordWithSelection)
+FUNCTION(gotoPreviousWordCamelCase)
+FUNCTION(gotoPreviousWordCamelCaseWithSelection)
FUNCTION(gotoNextWord)
FUNCTION(gotoNextWordWithSelection)
+FUNCTION(gotoNextWordCamelCase)
+FUNCTION(gotoNextWordCamelCaseWithSelection)
void TextEditorActionHandler::updateCurrentEditor(Core::IEditor *editor)
diff --git a/src/plugins/texteditor/texteditoractionhandler.h b/src/plugins/texteditor/texteditoractionhandler.h
index 5ef5dfe3e5..ec5c9ea8f1 100644
--- a/src/plugins/texteditor/texteditoractionhandler.h
+++ b/src/plugins/texteditor/texteditoractionhandler.h
@@ -140,6 +140,10 @@ private slots:
void gotoPreviousWordWithSelection();
void gotoNextWord();
void gotoNextWordWithSelection();
+ void gotoPreviousWordCamelCase();
+ void gotoPreviousWordCamelCaseWithSelection();
+ void gotoNextWordCamelCase();
+ void gotoNextWordCamelCaseWithSelection();
private:
diff --git a/src/plugins/texteditor/texteditorconstants.h b/src/plugins/texteditor/texteditorconstants.h
index 4fa955e849..7a8e7fb33e 100644
--- a/src/plugins/texteditor/texteditorconstants.h
+++ b/src/plugins/texteditor/texteditorconstants.h
@@ -82,6 +82,8 @@ const char * const GOTO_PREVIOUS_CHARACTER = "TextEditor.GotoPreviousCharacter";
const char * const GOTO_NEXT_CHARACTER = "TextEditor.GotoNextCharacter";
const char * const GOTO_PREVIOUS_WORD = "TextEditor.GotoPreviousWord";
const char * const GOTO_NEXT_WORD = "TextEditor.GotoNextWord";
+const char * const GOTO_PREVIOUS_WORD_CAMEL_CASE = "TextEditor.GotoPreviousWordCamelCase";
+const char * const GOTO_NEXT_WORD_CAMEL_CASE = "TextEditor.GotoNextWordCamelCase";
const char * const GOTO_LINE_START_WITH_SELECTION = "TextEditor.GotoLineStartWithSelection";
const char * const GOTO_LINE_END_WITH_SELECTION = "TextEditor.GotoLineEndWithSelection";
const char * const GOTO_NEXT_LINE_WITH_SELECTION = "TextEditor.GotoNextLineWithSelection";
@@ -90,6 +92,8 @@ const char * const GOTO_PREVIOUS_CHARACTER_WITH_SELECTION = "TextEditor.GotoPrev
const char * const GOTO_NEXT_CHARACTER_WITH_SELECTION = "TextEditor.GotoNextCharacterWithSelection";
const char * const GOTO_PREVIOUS_WORD_WITH_SELECTION = "TextEditor.GotoPreviousWordWithSelection";
const char * const GOTO_NEXT_WORD_WITH_SELECTION = "TextEditor.GotoNextWordWithSelection";
+const char * const GOTO_PREVIOUS_WORD_CAMEL_CASE_WITH_SELECTION = "TextEditor.GotoPreviousWordCamelCaseWithSelection";
+const char * const GOTO_NEXT_WORD_CAMEL_CASE_WITH_SELECTION = "TextEditor.GotoNextWordCamelCaseWithSelection";
const char * const C_TEXTEDITOR_MIMETYPE_TEXT = "text/plain";
const char * const INFO_SYNTAX_DEFINITION = "TextEditor.InfoSyntaxDefinition";
const char * const TASK_DOWNLOAD_DEFINITIONS = "TextEditor.Task.Download";
@@ -140,6 +144,10 @@ const char * const TEXT_EDITOR_FONT_SETTINGS = "A.FontSettings";
const char * const TEXT_EDITOR_BEHAVIOR_SETTINGS = "B.BehaviourSettings";
const char * const TEXT_EDITOR_DISPLAY_SETTINGS = "D.DisplaySettings";
const char * const TEXT_EDITOR_HIGHLIGHTER_SETTINGS = "E.HighlighterSettings";
+const char * const TEXT_EDITOR_SNIPPETS_SETTINGS = "F.SnippetsSettings";
+
+const char * const SNIPPET_EDITOR_ID = "TextEditor.SnippetEditor";
+const char * const TEXT_SNIPPET_GROUP_ID = "Text";
} // namespace Constants
} // namespace TextEditor
diff --git a/src/plugins/texteditor/texteditoroverlay.cpp b/src/plugins/texteditor/texteditoroverlay.cpp
index 2edcb9455f..12d630c395 100644
--- a/src/plugins/texteditor/texteditoroverlay.cpp
+++ b/src/plugins/texteditor/texteditoroverlay.cpp
@@ -32,23 +32,26 @@
**************************************************************************/
#include "texteditoroverlay.h"
+#include "basetexteditor.h"
+#include <QtCore/QDebug>
+#include <QtCore/QMap>
#include <QtGui/QPainter>
#include <QtGui/QTextBlock>
using namespace TextEditor;
using namespace TextEditor::Internal;
-
-
-TextEditorOverlay::TextEditorOverlay(BaseTextEditor *editor)
- :QObject(editor) {
- m_visible = false;
- m_borderWidth = 1;
- m_dropShadowWidth = 2;
- m_editor = editor;
- m_alpha = true;
- m_viewport = editor->viewport();
+TextEditorOverlay::TextEditorOverlay(BaseTextEditor *editor) :
+ QObject(editor),
+ m_visible(false),
+ m_borderWidth(1),
+ m_dropShadowWidth(2),
+ m_alpha(true),
+ m_firstSelectionOriginalBegin(-1),
+ m_editor(editor),
+ m_viewport(editor->viewport())
+{
}
void TextEditorOverlay::update()
@@ -72,6 +75,7 @@ void TextEditorOverlay::clear()
if (m_selections.isEmpty())
return;
m_selections.clear();
+ m_firstSelectionOriginalBegin = -1;
update();
}
@@ -97,13 +101,16 @@ void TextEditorOverlay::addOverlaySelection(int begin, int end,
}
}
-
if (overlaySelectionFlags & LockSize)
selection.m_fixedLength = (end - begin);
-
selection.m_dropShadow = (overlaySelectionFlags & DropShadow);
+ if (m_selections.isEmpty())
+ m_firstSelectionOriginalBegin = begin;
+ else if (begin < m_firstSelectionOriginalBegin)
+ qWarning() << "overlay selections not in order";
+
m_selections.append(selection);
update();
}
@@ -453,11 +460,85 @@ void TextEditorOverlay::fill(QPainter *painter, const QColor &color, const QRect
*/
bool TextEditorOverlay::hasCursorInSelection(const QTextCursor &cursor) const
{
+ if (selectionIndexForCursor(cursor) != -1)
+ return true;
+ return false;
+}
+
+int TextEditorOverlay::selectionIndexForCursor(const QTextCursor &cursor) const
+{
for (int i = 0; i < m_selections.size(); ++i) {
const OverlaySelection &selection = m_selections.at(i);
if (cursor.position() >= selection.m_cursor_begin.position()
&& cursor.position() <= selection.m_cursor_end.position())
- return true;
+ return i;
}
- return false;
+ return -1;
+}
+
+QString TextEditorOverlay::selectionText(int selectionIndex) const
+{
+ return assembleCursorForSelection(selectionIndex).selectedText();
+}
+
+QTextCursor TextEditorOverlay::assembleCursorForSelection(int selectionIndex) const
+{
+ const OverlaySelection &selection = m_selections.at(selectionIndex);
+ QTextCursor cursor(m_editor->document());
+ cursor.setPosition(selection.m_cursor_begin.position());
+ cursor.setPosition(selection.m_cursor_end.position(), QTextCursor::KeepAnchor);
+ return cursor;
+}
+
+void TextEditorOverlay::mapEquivalentSelections()
+{
+ m_equivalentSelections.clear();
+ m_equivalentSelections.resize(m_selections.size());
+
+ QMap<QString, int> all;
+ for (int i = 0; i < m_selections.size(); ++i)
+ all.insertMulti(selectionText(i), i);
+
+ const QList<QString> &uniqueKeys = all.uniqueKeys();
+ foreach (const QString &key, uniqueKeys) {
+ QList<int> indexes;
+ QMap<QString, int>::const_iterator lbit = all.lowerBound(key);
+ QMap<QString, int>::const_iterator ubit = all.upperBound(key);
+ while (lbit != ubit) {
+ indexes.append(lbit.value());
+ ++lbit;
+ }
+
+ foreach (int index, indexes)
+ m_equivalentSelections[index] = indexes;
+ }
+}
+
+void TextEditorOverlay::updateEquivalentSelections(const QTextCursor &cursor)
+{
+ int selectionIndex = selectionIndexForCursor(cursor);
+ if (selectionIndex == -1)
+ return;
+
+ const QString &currentText = selectionText(selectionIndex);
+ const QList<int> &equivalents = m_equivalentSelections.at(selectionIndex);
+ foreach (int i, equivalents) {
+ if (i == selectionIndex)
+ continue;
+ const QString &equivalentText = selectionText(i);
+ if (currentText != equivalentText) {
+ QTextCursor selectionCursor = assembleCursorForSelection(i);
+ selectionCursor.joinPreviousEditBlock();
+ selectionCursor.removeSelectedText();
+ selectionCursor.insertText(currentText);
+ selectionCursor.endEditBlock();
+ }
+ }
+}
+
+bool TextEditorOverlay::hasFirstSelectionBeginMoved() const
+{
+ if (m_firstSelectionOriginalBegin == -1 || m_selections.isEmpty())
+ return false;
+ return m_selections.at(0).m_cursor_begin.position() != m_firstSelectionOriginalBegin;
}
diff --git a/src/plugins/texteditor/texteditoroverlay.h b/src/plugins/texteditor/texteditoroverlay.h
index 2f1502c2c5..17045e521a 100644
--- a/src/plugins/texteditor/texteditoroverlay.h
+++ b/src/plugins/texteditor/texteditoroverlay.h
@@ -34,37 +34,34 @@
#ifndef TEXTEDITOROVERLAY_H
#define TEXTEDITOROVERLAY_H
-#include <QtGui/QWidget>
-#include "basetexteditor.h"
+#include <QtCore/QObject>
+#include <QtCore/QList>
+#include <QtCore/QVector>
+#include <QtGui/QTextCursor>
+#include <QtGui/QColor>
+
+QT_FORWARD_DECLARE_CLASS(QWidget)
namespace TextEditor {
+class BaseTextEditor;
+
namespace Internal {
-struct TEXTEDITOR_EXPORT OverlaySelection {
+struct OverlaySelection
+{
OverlaySelection():m_fixedLength(-1), m_dropShadow(false){}
+
QTextCursor m_cursor_begin;
QTextCursor m_cursor_end;
QColor m_fg;
QColor m_bg;
int m_fixedLength;
bool m_dropShadow;
- };
+};
-class TEXTEDITOR_EXPORT TextEditorOverlay : public QObject
+class TextEditorOverlay : public QObject
{
-Q_OBJECT
-BaseTextEditor *m_editor;
-QWidget *m_viewport;
-
-public:
-QList<OverlaySelection> m_selections;
-private:
-
-bool m_visible;
-int m_borderWidth;
-int m_dropShadowWidth;
-bool m_alpha;
-
+ Q_OBJECT
public:
TextEditorOverlay(BaseTextEditor *editor);
@@ -97,17 +94,36 @@ public:
void addOverlaySelection(int begin, int end, const QColor &fg, const QColor &bg,
uint overlaySelectionFlags = 0);
+ const QList<OverlaySelection> &selections() const { return m_selections; }
+
inline bool isEmpty() const { return m_selections.isEmpty(); }
inline int dropShadowWidth() const { return m_dropShadowWidth; }
bool hasCursorInSelection(const QTextCursor &cursor) const;
+ void mapEquivalentSelections();
+ void updateEquivalentSelections(const QTextCursor &cursor);
+
+ bool hasFirstSelectionBeginMoved() const;
+
private:
QPainterPath createSelectionPath(const QTextCursor &begin, const QTextCursor &end, const QRect& clip);
void paintSelection(QPainter *painter, const OverlaySelection &selection);
void fillSelection(QPainter *painter, const OverlaySelection &selection, const QColor &color);
-
+ int selectionIndexForCursor(const QTextCursor &cursor) const;
+ QString selectionText(int selectionIndex) const;
+ QTextCursor assembleCursorForSelection(int selectionIndex) const;
+
+ bool m_visible;
+ int m_borderWidth;
+ int m_dropShadowWidth;
+ bool m_alpha;
+ int m_firstSelectionOriginalBegin;
+ BaseTextEditor *m_editor;
+ QWidget *m_viewport;
+ QList<OverlaySelection> m_selections;
+ QVector<QList<int> > m_equivalentSelections;
};
} // namespace Internal
diff --git a/src/plugins/texteditor/texteditorplugin.cpp b/src/plugins/texteditor/texteditorplugin.cpp
index c46b7ab9d5..ccd9c4aae8 100644
--- a/src/plugins/texteditor/texteditorplugin.cpp
+++ b/src/plugins/texteditor/texteditorplugin.cpp
@@ -45,6 +45,7 @@
#include "storagesettings.h"
#include "manager.h"
#include "outlinefactory.h"
+#include "snippets/plaintextsnippetprovider.h"
#include <coreplugin/icore.h>
#include <coreplugin/coreconstants.h>
@@ -148,6 +149,9 @@ bool TextEditorPlugin::initialize(const QStringList &arguments, QString *errorMe
connect(Core::ICore::instance(), SIGNAL(coreOpened()),
Manager::instance(), SLOT(registerMimeTypes()));
+ // Add text snippet provider.
+ addAutoReleasedObject(new PlainTextSnippetProvider);
+
m_outlineFactory = new OutlineFactory;
addAutoReleasedObject(m_outlineFactory);
diff --git a/src/plugins/texteditor/texteditorsettings.cpp b/src/plugins/texteditor/texteditorsettings.cpp
index a267d102f7..5aae77f08a 100644
--- a/src/plugins/texteditor/texteditorsettings.cpp
+++ b/src/plugins/texteditor/texteditorsettings.cpp
@@ -45,6 +45,7 @@
#include "tabsettings.h"
#include "texteditorplugin.h"
#include "highlightersettingspage.h"
+#include "snippetssettingspage.h"
#include <extensionsystem/pluginmanager.h>
#include <coreplugin/icore.h>
@@ -66,6 +67,7 @@ public:
BehaviorSettingsPage *m_behaviorSettingsPage;
DisplaySettingsPage *m_displaySettingsPage;
HighlighterSettingsPage *m_highlighterSettingsPage;
+ SnippetsSettingsPage *m_snippetsSettingsPage;
CompletionSettings m_completionSettings;
@@ -178,6 +180,10 @@ TextEditorSettings::TextEditorSettings(QObject *parent)
new HighlighterSettingsPage(QLatin1String(Constants::TEXT_EDITOR_HIGHLIGHTER_SETTINGS), this);
pm->addObject(m_d->m_highlighterSettingsPage);
+ m_d->m_snippetsSettingsPage =
+ new SnippetsSettingsPage(QLatin1String(Constants::TEXT_EDITOR_SNIPPETS_SETTINGS), this);
+ pm->addObject(m_d->m_snippetsSettingsPage);
+
connect(m_d->m_fontSettingsPage, SIGNAL(changed(TextEditor::FontSettings)),
this, SIGNAL(fontSettingsChanged(TextEditor::FontSettings)));
connect(m_d->m_behaviorSettingsPage, SIGNAL(tabSettingsChanged(TextEditor::TabSettings)),
@@ -201,6 +207,7 @@ TextEditorSettings::~TextEditorSettings()
pm->removeObject(m_d->m_behaviorSettingsPage);
pm->removeObject(m_d->m_displaySettingsPage);
pm->removeObject(m_d->m_highlighterSettingsPage);
+ pm->removeObject(m_d->m_snippetsSettingsPage);
delete m_d;
diff --git a/src/plugins/texteditor/texteditorsettings.h b/src/plugins/texteditor/texteditorsettings.h
index 366d597365..abc66fd8f7 100644
--- a/src/plugins/texteditor/texteditorsettings.h
+++ b/src/plugins/texteditor/texteditorsettings.h
@@ -90,8 +90,8 @@ signals:
private:
Internal::TextEditorSettingsPrivate *m_d;
- Q_PRIVATE_SLOT(m_d, void fontZoomRequested(int pointSize));
- Q_PRIVATE_SLOT(m_d, void zoomResetRequested());
+ Q_PRIVATE_SLOT(m_d, void fontZoomRequested(int pointSize))
+ Q_PRIVATE_SLOT(m_d, void zoomResetRequested())
static TextEditorSettings *m_instance;
};
diff --git a/src/plugins/vcsbase/VCSBase.pluginspec b/src/plugins/vcsbase/VCSBase.pluginspec
deleted file mode 100644
index f9cb058868..0000000000
--- a/src/plugins/vcsbase/VCSBase.pluginspec
+++ /dev/null
@@ -1,21 +0,0 @@
-<plugin name="VCSBase" version="2.0.95" compatVersion="2.0.95">
- <vendor>Nokia Corporation</vendor>
- <copyright>(C) 2010 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>
- <category>Version Control</category>
- <description>Version Control System Base Plugin</description>
- <url>http://qt.nokia.com</url>
- <dependencyList>
- <dependency name="Core" version="2.0.95"/>
- <dependency name="TextEditor" version="2.0.95"/>
- <dependency name="ProjectExplorer" version="2.0.95"/>
- </dependencyList>
-</plugin>
diff --git a/src/plugins/vcsbase/VCSBase.pluginspec.in b/src/plugins/vcsbase/VCSBase.pluginspec.in
new file mode 100644
index 0000000000..16af539d2b
--- /dev/null
+++ b/src/plugins/vcsbase/VCSBase.pluginspec.in
@@ -0,0 +1,21 @@
+<plugin name=\"VCSBase\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2010 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>
+ <category>Version Control</category>
+ <description>Version Control System Base Plugin</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"TextEditor\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"ProjectExplorer\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/vcsbase/basecheckoutwizard.cpp b/src/plugins/vcsbase/basecheckoutwizard.cpp
index 2eedbc2160..67820d719d 100644
--- a/src/plugins/vcsbase/basecheckoutwizard.cpp
+++ b/src/plugins/vcsbase/basecheckoutwizard.cpp
@@ -37,7 +37,6 @@
#include "checkoutjobs.h"
#include <projectexplorer/projectexplorer.h>
-#include <projectexplorer/session.h>
#include <QtCore/QCoreApplication>
#include <QtCore/QFileInfo>
diff --git a/src/plugins/vcsbase/basecheckoutwizardpage.cpp b/src/plugins/vcsbase/basecheckoutwizardpage.cpp
index cc9d3f336a..7566ce352b 100644
--- a/src/plugins/vcsbase/basecheckoutwizardpage.cpp
+++ b/src/plugins/vcsbase/basecheckoutwizardpage.cpp
@@ -54,7 +54,7 @@ BaseCheckoutWizardPage::BaseCheckoutWizardPage(QWidget *parent) :
connect(d->ui.repositoryLineEdit, SIGNAL(textChanged(QString)), this, SLOT(slotRepositoryChanged(QString)));
- connect(d->ui.checkoutDirectoryLineEdit, SIGNAL(validChanged()),
+ connect(d->ui.checkoutDirectoryLineEdit, SIGNAL(textChanged(QString)),
this, SLOT(slotChanged()));
connect(d->ui.checkoutDirectoryLineEdit, SIGNAL(textEdited(QString)), this, SLOT(slotDirectoryEdited()));
connect(d->ui.branchComboBox, SIGNAL(currentIndexChanged(int)),
@@ -91,7 +91,7 @@ void BaseCheckoutWizardPage::addRepositoryControl(QWidget *w)
bool BaseCheckoutWizardPage::checkIsValid() const
{
return d->ui.pathChooser->isValid()
- && d->ui.checkoutDirectoryLineEdit->isValid()
+ && !d->ui.checkoutDirectoryLineEdit->text().isEmpty()
&& !d->ui.repositoryLineEdit->text().isEmpty();
}
diff --git a/src/plugins/vcsbase/basecheckoutwizardpage.ui b/src/plugins/vcsbase/basecheckoutwizardpage.ui
index f94995ccdf..46a58348e4 100644
--- a/src/plugins/vcsbase/basecheckoutwizardpage.ui
+++ b/src/plugins/vcsbase/basecheckoutwizardpage.ui
@@ -112,7 +112,7 @@
</widget>
</item>
<item row="1" column="1">
- <widget class="Utils::ProjectNameValidatingLineEdit" name="checkoutDirectoryLineEdit">
+ <widget class="QLineEdit" name="checkoutDirectoryLineEdit">
<property name="toolTip">
<string>The local directory that will contain the code after the checkout.</string>
</property>
@@ -141,11 +141,6 @@
</widget>
<customwidgets>
<customwidget>
- <class>Utils::ProjectNameValidatingLineEdit</class>
- <extends>QLineEdit</extends>
- <header location="global">utils/projectnamevalidatinglineedit.h</header>
- </customwidget>
- <customwidget>
<class>Utils::PathChooser</class>
<extends>QLineEdit</extends>
<header>utils/pathchooser.h</header>
diff --git a/src/plugins/vcsbase/commonsettingspage.cpp b/src/plugins/vcsbase/commonsettingspage.cpp
index 9711b7b867..947a568567 100644
--- a/src/plugins/vcsbase/commonsettingspage.cpp
+++ b/src/plugins/vcsbase/commonsettingspage.cpp
@@ -90,11 +90,12 @@ void CommonSettingsWidget::setSettings(const CommonVcsSettings &s)
QString CommonSettingsWidget::searchKeyWordMatchString() const
{
const QChar blank = QLatin1Char(' ');
- QString rc = m_ui->submitMessageCheckScriptLabel->text();
- rc += blank;
- rc += m_ui->nickNameMailMapLabel->text();
- rc += blank;
- rc += m_ui->nickNameFieldsFileLabel->text();
+ QString rc = m_ui->lineWrapCheckBox->text()
+ + blank + m_ui->submitMessageCheckScriptLabel->text()
+ + blank + m_ui->nickNameMailMapLabel->text()
+ + blank + m_ui->nickNameFieldsFileLabel->text()
+ + blank + m_ui->sshPromptLabel->text()
+ ;
rc.remove(QLatin1Char('&')); // Strip buddy markers.
return rc;
}
diff --git a/src/plugins/vcsbase/diffhighlighter.cpp b/src/plugins/vcsbase/diffhighlighter.cpp
index bd59f0438d..497d8c97bd 100644
--- a/src/plugins/vcsbase/diffhighlighter.cpp
+++ b/src/plugins/vcsbase/diffhighlighter.cpp
@@ -33,6 +33,8 @@
#include "diffhighlighter.h"
+#include <texteditor/basetextdocumentlayout.h>
+
#include <utils/qtcassert.h>
#include <QtCore/QDebug>
@@ -40,7 +42,12 @@
#include <QtCore/QRegExp>
#include <QtGui/QBrush>
+static const int BASE_LEVEL = 0;
+static const int FILE_LEVEL = 1;
+static const int LOCATION_LEVEL = 2;
+
namespace VCSBase {
+namespace Internal {
// Formats used by DiffHighlighter
enum DiffFormats {
@@ -52,8 +59,16 @@ enum DiffFormats {
NumDiffFormats
};
+enum FoldingState {
+ StartOfFile,
+ Header,
+ File,
+ Location
+};
+
// --- DiffHighlighterPrivate
-struct DiffHighlighterPrivate {
+class DiffHighlighterPrivate {
+public:
DiffHighlighterPrivate(const QRegExp &filePattern);
inline DiffFormats analyzeLine(const QString &block) const;
@@ -63,13 +78,16 @@ struct DiffHighlighterPrivate {
const QChar m_diffOutIndicator;
QTextCharFormat m_formats[NumDiffFormats];
QTextCharFormat m_addedTrailingWhiteSpaceFormat;
+
+ FoldingState m_foldingState;
};
DiffHighlighterPrivate::DiffHighlighterPrivate(const QRegExp &filePattern) :
m_filePattern(filePattern),
m_locationIndicator(QLatin1String("@@")),
m_diffInIndicator(QLatin1Char('+')),
- m_diffOutIndicator(QLatin1Char('-'))
+ m_diffOutIndicator(QLatin1Char('-')),
+ m_foldingState(StartOfFile)
{
QTC_ASSERT(filePattern.isValid(), /**/);
}
@@ -89,11 +107,13 @@ DiffFormats DiffHighlighterPrivate::analyzeLine(const QString &text) const
return DiffTextFormat;
}
+} // namespace Internal
+
// --- DiffHighlighter
DiffHighlighter::DiffHighlighter(const QRegExp &filePattern,
QTextDocument *document) :
TextEditor::SyntaxHighlighter(document),
- m_d(new DiffHighlighterPrivate(filePattern))
+ m_d(new Internal::DiffHighlighterPrivate(filePattern))
{
}
@@ -117,11 +137,11 @@ void DiffHighlighter::highlightBlock(const QString &text)
return;
const int length = text.length();
- const DiffFormats format = m_d->analyzeLine(text);
+ const Internal::DiffFormats format = m_d->analyzeLine(text);
switch (format) {
- case DiffTextFormat:
+ case Internal::DiffTextFormat:
break;
- case DiffInFormat: {
+ case Internal::DiffInFormat: {
// Mark trailing whitespace.
const int trimmedLen = trimmedLength(text);
setFormat(0, trimmedLen, m_d->m_formats[format]);
@@ -133,6 +153,61 @@ void DiffHighlighter::highlightBlock(const QString &text)
setFormat(0, length, m_d->m_formats[format]);
break;
}
+
+ // codefolding:
+ TextEditor::TextBlockUserData *data =
+ TextEditor::BaseTextDocumentLayout::userData(currentBlock());
+ Q_ASSERT(data);
+ if (!TextEditor::BaseTextDocumentLayout::testUserData(currentBlock().previous()))
+ m_d->m_foldingState = Internal::StartOfFile;
+
+ switch (m_d->m_foldingState) {
+ case Internal::StartOfFile:
+ case Internal::Header:
+ switch (format) {
+ case Internal::DiffFileFormat:
+ m_d->m_foldingState = Internal::File;
+ TextEditor::BaseTextDocumentLayout::setFoldingIndent(currentBlock(), BASE_LEVEL);
+ break;
+ case Internal::DiffLocationFormat:
+ m_d->m_foldingState = Internal::Location;
+ TextEditor::BaseTextDocumentLayout::setFoldingIndent(currentBlock(), FILE_LEVEL);
+ break;
+ default:
+ m_d->m_foldingState = Internal::Header;
+ TextEditor::BaseTextDocumentLayout::setFoldingIndent(currentBlock(), BASE_LEVEL);
+ break;
+ }
+ break;
+ case Internal::File:
+ switch (format) {
+ case Internal::DiffFileFormat:
+ TextEditor::BaseTextDocumentLayout::setFoldingIndent(currentBlock(), FILE_LEVEL);
+ break;
+ case Internal::DiffLocationFormat:
+ m_d->m_foldingState = Internal::Location;
+ TextEditor::BaseTextDocumentLayout::setFoldingIndent(currentBlock(), FILE_LEVEL);
+ break;
+ default:
+ TextEditor::BaseTextDocumentLayout::setFoldingIndent(currentBlock(), FILE_LEVEL);
+ break;
+ }
+ break;
+ case Internal::Location:
+ switch (format) {
+ case Internal::DiffFileFormat:
+ m_d->m_foldingState = Internal::File;
+ TextEditor::BaseTextDocumentLayout::setFoldingIndent(currentBlock(), BASE_LEVEL);
+ break;
+ case Internal::DiffLocationFormat:
+ TextEditor::BaseTextDocumentLayout::setFoldingIndent(currentBlock(), FILE_LEVEL);
+ break;
+ default:
+ TextEditor::BaseTextDocumentLayout::setFoldingIndent(currentBlock(), LOCATION_LEVEL);
+ break;
+ }
+ break;
+ }
}
static inline QTextCharFormat invertedColorFormat(const QTextCharFormat &in)
@@ -145,10 +220,11 @@ static inline QTextCharFormat invertedColorFormat(const QTextCharFormat &in)
void DiffHighlighter::setFormats(const QVector<QTextCharFormat> &s)
{
- if (s.size() == NumDiffFormats) {
+ if (s.size() == Internal::NumDiffFormats) {
qCopy(s.constBegin(), s.constEnd(), m_d->m_formats);
// Display trailing blanks with colors swapped
- m_d->m_addedTrailingWhiteSpaceFormat = invertedColorFormat(m_d->m_formats[DiffInFormat]);
+ m_d->m_addedTrailingWhiteSpaceFormat =
+ invertedColorFormat(m_d->m_formats[Internal::DiffInFormat]);
} else {
qWarning("%s: insufficient setting size: %d", Q_FUNC_INFO, s.size());
}
diff --git a/src/plugins/vcsbase/diffhighlighter.h b/src/plugins/vcsbase/diffhighlighter.h
index 354560daf4..4f6c806241 100644
--- a/src/plugins/vcsbase/diffhighlighter.h
+++ b/src/plugins/vcsbase/diffhighlighter.h
@@ -52,7 +52,9 @@ namespace TextEditor {
namespace VCSBase {
-struct DiffHighlighterPrivate;
+namespace Internal {
+class DiffHighlighterPrivate;
+} // namespace Internal
/* A highlighter for diffs. Parametrizable by the file indicator,
* which is for example '^====' in case of p4:
@@ -85,7 +87,7 @@ public:
QRegExp filePattern() const;
private:
- DiffHighlighterPrivate *m_d;
+ Internal::DiffHighlighterPrivate *m_d;
};
} // namespace VCSBase
diff --git a/src/plugins/vcsbase/vcsbase.pri b/src/plugins/vcsbase/vcsbase.pri
index 56f7418c66..7ac74218c8 100644
--- a/src/plugins/vcsbase/vcsbase.pri
+++ b/src/plugins/vcsbase/vcsbase.pri
@@ -1,3 +1,3 @@
include(vcsbase_dependencies.pri)
-LIBS *= -l$$qtLibraryTarget(VCSBase)
+LIBS *= -l$$qtLibraryName(VCSBase)
diff --git a/src/plugins/vcsbase/vcsbase.pro b/src/plugins/vcsbase/vcsbase.pro
index acf42be106..066deab63d 100644
--- a/src/plugins/vcsbase/vcsbase.pro
+++ b/src/plugins/vcsbase/vcsbase.pro
@@ -60,5 +60,3 @@ FORMS += commonsettingspage.ui \
checkoutprogresswizardpage.ui \
basecheckoutwizardpage.ui \
cleandialog.ui
-
-OTHER_FILES += VCSBase.pluginspec
diff --git a/src/plugins/vcsbase/vcsbaseeditor.cpp b/src/plugins/vcsbase/vcsbaseeditor.cpp
index 3d771894b0..0d7f21fe4e 100644
--- a/src/plugins/vcsbase/vcsbaseeditor.cpp
+++ b/src/plugins/vcsbase/vcsbaseeditor.cpp
@@ -135,7 +135,6 @@ VCSBaseDiffEditorEditable::VCSBaseDiffEditorEditable(VCSBaseEditor *e, const VCS
m_diffFileBrowseComboBox(new QComboBox(m_toolBar))
{
m_diffFileBrowseComboBox->setMinimumContentsLength(20);
- m_diffFileBrowseComboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
// Make the combo box prefer to expand
QSizePolicy policy = m_diffFileBrowseComboBox->sizePolicy();
policy.setHorizontalPolicy(QSizePolicy::Expanding);
@@ -167,6 +166,8 @@ struct VCSBaseEditorPrivate
QString m_annotatePreviousRevisionTextFormat;
QString m_copyRevisionTextFormat;
bool m_fileLogAnnotateEnabled;
+ QToolBar *m_toolBar;
+ QWidget *m_configurationWidget;
};
VCSBaseEditorPrivate::VCSBaseEditorPrivate(const VCSBaseEditorParameters *type) :
@@ -174,7 +175,9 @@ VCSBaseEditorPrivate::VCSBaseEditorPrivate(const VCSBaseEditorParameters *type)
m_cursorLine(-1),
m_annotateRevisionTextFormat(VCSBaseEditor::tr("Annotate \"%1\"")),
m_copyRevisionTextFormat(VCSBaseEditor::tr("Copy \"%1\"")),
- m_fileLogAnnotateEnabled(false)
+ m_fileLogAnnotateEnabled(false),
+ m_toolBar(0),
+ m_configurationWidget(0)
{
}
@@ -202,6 +205,7 @@ void VCSBaseEditor::init()
break;
case DiffOutput: {
DiffHighlighter *dh = createDiffHighlighter();
+ setCodeFoldingSupported(true);
baseTextDocument()->setSyntaxHighlighter(dh);
d->m_diffFilePattern = dh->filePattern();
connect(this, SIGNAL(textChanged()), this, SLOT(slotPopulateDiffBrowser()));
@@ -329,6 +333,8 @@ TextEditor::BaseTextEditorEditable *VCSBaseEditor::createEditableInterface()
} else {
editable = new VCSBaseEditorEditable(this, d->m_parameters);
}
+ d->m_toolBar = qobject_cast<QToolBar *>(editable->toolBar());
+
// Pass on signals.
connect(this, SIGNAL(describeRequested(QString,QString)),
editable, SIGNAL(describeRequested(QString,QString)));
@@ -833,6 +839,30 @@ QString VCSBaseEditor::getTitleId(const QString &workingDirectory,
return rc;
}
+bool VCSBaseEditor::setConfigurationWidget(QWidget *w)
+{
+ if (!d->m_toolBar || d->m_configurationWidget)
+ return false;
+
+ d->m_configurationWidget = w;
+ if (contentType() == AnnotateOutput) {
+ QList<QAction *> actions = d->m_toolBar->actions();
+ Q_ASSERT(actions.count() >= 1);
+ QWidget *spacer = new QWidget(d->m_toolBar);
+ spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
+ QAction *configAction = d->m_toolBar->insertWidget(actions.at(0), w);
+ d->m_toolBar->insertWidget(configAction, spacer);
+ } else {
+ d->m_toolBar->addWidget(w);
+ }
+ return true;
+}
+
+QWidget *VCSBaseEditor::configurationWidget() const
+{
+ return d->m_configurationWidget;
+}
+
// Find the complete file from a diff relative specification.
QString VCSBaseEditor::findDiffFile(const QString &f, Core::IVersionControl *control /* = 0 */) const
{
diff --git a/src/plugins/vcsbase/vcsbaseeditor.h b/src/plugins/vcsbase/vcsbaseeditor.h
index 7a018b95a1..5dec204bed 100644
--- a/src/plugins/vcsbase/vcsbaseeditor.h
+++ b/src/plugins/vcsbase/vcsbaseeditor.h
@@ -182,6 +182,10 @@ public:
static QString getTitleId(const QString &workingDirectory,
const QStringList &fileNames,
const QString &revision = QString());
+
+ bool setConfigurationWidget(QWidget *w);
+ QWidget *configurationWidget() const;
+
signals:
// These signals also exist in the opaque editable (IEditor) that is
// handled by the editor manager for convenience. They are emitted
diff --git a/src/plugins/vcsbase/vcsbaseplugin.cpp b/src/plugins/vcsbase/vcsbaseplugin.cpp
index c53b55cd00..7296be7bb0 100644
--- a/src/plugins/vcsbase/vcsbaseplugin.cpp
+++ b/src/plugins/vcsbase/vcsbaseplugin.cpp
@@ -54,6 +54,7 @@
#include <QtCore/QDir>
#include <QtCore/QSharedData>
#include <QtCore/QScopedPointer>
+#include <QtCore/QSharedPointer>
#include <QtCore/QProcessEnvironment>
#include <QtCore/QTextStream>
#include <QtCore/QTextCodec>
@@ -130,6 +131,7 @@ bool State::equals(const State &rhs) const
return currentFile == rhs.currentFile
&& currentFileName == rhs.currentFileName
&& currentPatchFile == rhs.currentPatchFile
+ && currentPatchFileDisplayName == rhs.currentPatchFileDisplayName
&& currentFileTopLevel == rhs.currentFileTopLevel
&& currentProjectPath == rhs.currentProjectPath
&& currentProjectName == rhs.currentProjectName
@@ -184,6 +186,8 @@ StateListener::StateListener(QObject *parent) :
Core::ICore *core = Core::ICore::instance();
connect(core->fileManager(), SIGNAL(currentFileChanged(QString)),
this, SLOT(slotStateChanged()));
+ connect(core->editorManager()->instance(), SIGNAL(currentEditorStateChanged(Core::IEditor*)),
+ this, SLOT(slotStateChanged()));
if (ProjectExplorer::ProjectExplorerPlugin *pe = ProjectExplorer::ProjectExplorerPlugin::instance())
connect(pe, SIGNAL(currentProjectChanged(ProjectExplorer::Project*)),
@@ -202,7 +206,7 @@ void StateListener::slotStateChanged()
{
const ProjectExplorer::ProjectExplorerPlugin *pe = ProjectExplorer::ProjectExplorerPlugin::instance();
const Core::ICore *core = Core::ICore::instance();
- Core::VCSManager *vcsManager = core->vcsManager();
+ Core::VcsManager *vcsManager = core->vcsManager();
// Get the current file. Are we on a temporary submit editor indicated by
// temporary path prefix or does the file contains a hash, indicating a project
@@ -231,6 +235,7 @@ void StateListener::slotStateChanged()
if (isTempFile || state.currentFile.contains(QLatin1Char('#')))
state.currentFile.clear();
}
+
// Get the file and its control. Do not use the file unless we find one
Core::IVersionControl *fileControl = 0;
if (!state.currentFile.isEmpty()) {
@@ -705,6 +710,72 @@ void VCSBasePlugin::setProcessEnvironment(QProcessEnvironment *e, bool forceCLoc
e->insert(QLatin1String("SSH_ASKPASS"), sshPromptBinary);
}
+// Run a process fully synchronously, returning Utils::SynchronousProcessResponse
+// response struct and using the VCSBasePlugin flags as applicable
+static Utils::SynchronousProcessResponse
+ runVCS_FullySynchronously(const QString &workingDir,
+ const QString &binary,
+ const QStringList &arguments,
+ int timeOutMS,
+ QProcessEnvironment env,
+ unsigned flags,
+ QTextCodec *outputCodec = 0)
+{
+ VCSBase::VCSBaseOutputWindow *outputWindow = VCSBase::VCSBaseOutputWindow::instance();
+
+ // Set up process
+ unsigned processFlags = 0;
+ if (VCSBasePlugin::isSshPromptConfigured() && (flags & VCSBasePlugin::SshPasswordPrompt))
+ processFlags |= Utils::SynchronousProcess::UnixTerminalDisabled;
+ QSharedPointer<QProcess> process = Utils::SynchronousProcess::createProcess(processFlags);
+ if (!workingDir.isEmpty())
+ process->setWorkingDirectory(workingDir);
+ process->setProcessEnvironment(env);
+ if (flags & VCSBasePlugin::MergeOutputChannels)
+ process->setProcessChannelMode(QProcess::MergedChannels);
+
+ // Start
+ process->start(binary, arguments);
+ Utils::SynchronousProcessResponse response;
+ if (!process->waitForStarted()) {
+ response.result = Utils::SynchronousProcessResponse::StartFailed;
+ return response;
+ }
+
+ // process output
+ QByteArray stdOut;
+ QByteArray stdErr;
+ const bool timedOut =
+ !Utils::SynchronousProcess::readDataFromProcess(*process.data(), timeOutMS,
+ &stdOut, &stdErr, true);
+
+ if (!stdErr.isEmpty()) {
+ response.stdErr = QString::fromLocal8Bit(stdErr).remove('\r');
+ if (!(flags & VCSBasePlugin::SuppressStdErrInLogWindow))
+ outputWindow->append(response.stdErr);
+ }
+
+ if (!stdOut.isEmpty()) {
+ response.stdOut = (outputCodec ? outputCodec->toUnicode(stdOut) : QString::fromLocal8Bit(stdOut))
+ .remove('\r');
+ if (flags & VCSBasePlugin::ShowStdOutInLogWindow)
+ outputWindow->append(response.stdOut);
+ }
+
+ // Result
+ if (timedOut) {
+ response.result = Utils::SynchronousProcessResponse::Hang;
+ } else if (process->exitStatus() != QProcess::NormalExit) {
+ response.result = Utils::SynchronousProcessResponse::TerminatedAbnormally;
+ } else {
+ response.result = process->exitCode() == 0 ?
+ Utils::SynchronousProcessResponse::Finished :
+ Utils::SynchronousProcessResponse::FinishedError;
+ }
+ return response;
+}
+
+
Utils::SynchronousProcessResponse
VCSBasePlugin::runVCS(const QString &workingDir,
const QString &binary,
@@ -751,56 +822,66 @@ Utils::SynchronousProcessResponse
nsp << "suppress_log";
if (flags & ForceCLocale)
nsp << "c_locale";
+ if (flags & FullySynchronously)
+ nsp << "fully_synchronously";
if (outputCodec)
nsp << " Codec: " << outputCodec->name();
}
- // Run, connect stderr to the output window
- Utils::SynchronousProcess process;
- if (!workingDir.isEmpty())
- process.setWorkingDirectory(workingDir);
-
VCSBase::VCSBasePlugin::setProcessEnvironment(&env, (flags & ForceCLocale));
- process.setProcessEnvironment(env);
- process.setTimeout(timeOutMS);
- if (outputCodec)
- process.setStdOutCodec(outputCodec);
-
- // Suppress terminal on UNIX for ssh prompts if it is configured.
- if (sshPromptConfigured && (flags & SshPasswordPrompt))
- process.setFlags(Utils::SynchronousProcess::UnixTerminalDisabled);
-
- // connect stderr to the output window if desired
- if (flags & MergeOutputChannels) {
- process.setProcessChannelMode(QProcess::MergedChannels);
+
+ Utils::SynchronousProcessResponse response;
+
+ if (flags & FullySynchronously) {
+ response = runVCS_FullySynchronously(workingDir, binary, arguments, timeOutMS,
+ env, flags, outputCodec);
} else {
- if (!(flags & SuppressStdErrInLogWindow)) {
- process.setStdErrBufferedSignalsEnabled(true);
- connect(&process, SIGNAL(stdErrBuffered(QString,bool)), outputWindow, SLOT(append(QString)));
+ // Run, connect stderr to the output window
+ Utils::SynchronousProcess process;
+ if (!workingDir.isEmpty())
+ process.setWorkingDirectory(workingDir);
+
+ process.setProcessEnvironment(env);
+ process.setTimeout(timeOutMS);
+ if (outputCodec)
+ process.setStdOutCodec(outputCodec);
+
+ // Suppress terminal on UNIX for ssh prompts if it is configured.
+ if (sshPromptConfigured && (flags & SshPasswordPrompt))
+ process.setFlags(Utils::SynchronousProcess::UnixTerminalDisabled);
+
+ // connect stderr to the output window if desired
+ if (flags & MergeOutputChannels) {
+ process.setProcessChannelMode(QProcess::MergedChannels);
+ } else {
+ if (!(flags & SuppressStdErrInLogWindow)) {
+ process.setStdErrBufferedSignalsEnabled(true);
+ connect(&process, SIGNAL(stdErrBuffered(QString,bool)), outputWindow, SLOT(append(QString)));
+ }
}
- }
- // connect stdout to the output window if desired
- if (flags & ShowStdOutInLogWindow) {
- process.setStdOutBufferedSignalsEnabled(true);
- connect(&process, SIGNAL(stdOutBuffered(QString,bool)), outputWindow, SLOT(append(QString)));
- }
+ // connect stdout to the output window if desired
+ if (flags & ShowStdOutInLogWindow) {
+ process.setStdOutBufferedSignalsEnabled(true);
+ connect(&process, SIGNAL(stdOutBuffered(QString,bool)), outputWindow, SLOT(append(QString)));
+ }
- process.setTimeOutMessageBoxEnabled(true);
+ process.setTimeOutMessageBoxEnabled(true);
- // Run!
- const Utils::SynchronousProcessResponse sp_resp = process.run(binary, arguments);
+ // Run!
+ response = process.run(binary, arguments);
+ }
// Success/Fail message in appropriate window?
- if (sp_resp.result == Utils::SynchronousProcessResponse::Finished) {
+ if (response.result == Utils::SynchronousProcessResponse::Finished) {
if (flags & ShowSuccessMessage)
- outputWindow->append(sp_resp.exitMessage(binary, timeOutMS));
+ outputWindow->append(response.exitMessage(binary, timeOutMS));
} else {
if (!(flags & SuppressFailMessageInLogWindow))
- outputWindow->appendError(sp_resp.exitMessage(binary, timeOutMS));
+ outputWindow->appendError(response.exitMessage(binary, timeOutMS));
}
- return sp_resp;
+ return response;
}
} // namespace VCSBase
diff --git a/src/plugins/vcsbase/vcsbaseplugin.h b/src/plugins/vcsbase/vcsbaseplugin.h
index a9de5200ac..914551abd8 100644
--- a/src/plugins/vcsbase/vcsbaseplugin.h
+++ b/src/plugins/vcsbase/vcsbaseplugin.h
@@ -196,7 +196,9 @@ public:
SuppressFailMessageInLogWindow = 0x10, // No message VCS about failure in VCS output window.
SuppressCommandLogging = 0x20, // No command log entry in VCS output window.
ShowSuccessMessage = 0x40, // Show message about successful completion in VCS output window.
- ForceCLocale = 0x80 // Force C-locale for commands whose output is parsed.
+ ForceCLocale = 0x80, // Force C-locale for commands whose output is parsed.
+ FullySynchronously = 0x100 // Suppress local event loop (in case UI actions are
+ // triggered by file watchers).
};
static Utils::SynchronousProcessResponse
diff --git a/src/plugins/vcsbase/vcsbasesubmiteditor.cpp b/src/plugins/vcsbase/vcsbasesubmiteditor.cpp
index e87142ee08..0d48bb682c 100644
--- a/src/plugins/vcsbase/vcsbasesubmiteditor.cpp
+++ b/src/plugins/vcsbase/vcsbasesubmiteditor.cpp
@@ -333,6 +333,7 @@ QString VCSBaseSubmitEditor::displayName() const
void VCSBaseSubmitEditor::setDisplayName(const QString &title)
{
m_d->m_displayName = title;
+ emit changed();
}
QString VCSBaseSubmitEditor::checkScriptWorkingDirectory() const
@@ -468,8 +469,12 @@ VCSBaseSubmitEditor::PromptSubmitResult
const QString &question,
const QString &checkFailureQuestion,
bool *promptSetting,
- bool forcePrompt) const
+ bool forcePrompt,
+ bool canCommitOnFailure) const
{
+ Utils::SubmitEditorWidget *submitWidget =
+ static_cast<Utils::SubmitEditorWidget *>(const_cast<VCSBaseSubmitEditor *>(this)->widget());
+
raiseSubmitEditor();
QString errorMessage;
@@ -480,7 +485,8 @@ VCSBaseSubmitEditor::PromptSubmitResult
QWidget *parent = Core::ICore::instance()->mainWindow();
// Pop up a message depending on whether the check succeeded and the
// user wants to be prompted
- if (checkSubmitMessage(&errorMessage)) {
+ bool canCommit = checkSubmitMessage(&errorMessage) && submitWidget->canSubmit();
+ if (canCommit) {
// Check ok, do prompt?
if (prompt) {
// Provide check box to turn off prompt ONLY if it was not forced
@@ -507,14 +513,26 @@ VCSBaseSubmitEditor::PromptSubmitResult
msgBox.setMinimumWidth(checkDialogMinimumWidth);
answer = static_cast<QMessageBox::StandardButton>(msgBox.exec());
}
- switch (answer) {
- case QMessageBox::No:
- return SubmitDiscarded;
- case QMessageBox::Yes:
- return SubmitConfirmed;
- default:
- break;
+ if (!canCommit && !canCommitOnFailure) {
+ switch (answer) {
+ case QMessageBox::No:
+ return SubmitDiscarded;
+ case QMessageBox::Yes:
+ return SubmitCanceled;
+ default:
+ break;
+ }
+ } else {
+ switch (answer) {
+ case QMessageBox::No:
+ return SubmitDiscarded;
+ case QMessageBox::Yes:
+ return SubmitConfirmed;
+ default:
+ break;
+ }
}
+
return SubmitCanceled;
}
diff --git a/src/plugins/vcsbase/vcsbasesubmiteditor.h b/src/plugins/vcsbase/vcsbasesubmiteditor.h
index 364787741d..61b19b3ed4 100644
--- a/src/plugins/vcsbase/vcsbasesubmiteditor.h
+++ b/src/plugins/vcsbase/vcsbasesubmiteditor.h
@@ -119,7 +119,8 @@ public:
PromptSubmitResult promptSubmit(const QString &title, const QString &question,
const QString &checkFailureQuestion,
bool *promptSetting,
- bool forcePrompt = false) const;
+ bool forcePrompt = false,
+ bool canCommitOnFailure = true) const;
int fileNameColumn() const;
void setFileNameColumn(int c);
diff --git a/src/plugins/welcome/Welcome.pluginspec b/src/plugins/welcome/Welcome.pluginspec
deleted file mode 100644
index 647bbd937d..0000000000
--- a/src/plugins/welcome/Welcome.pluginspec
+++ /dev/null
@@ -1,19 +0,0 @@
-<plugin name="Welcome" version="2.0.95" compatVersion="2.0.95">
- <vendor>Nokia Corporation</vendor>
- <copyright>(C) 2010 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>
- <category>Qt Creator</category>
- <description>Default Welcome Screen Plugin</description>
- <url>http://qt.nokia.com</url>
- <dependencyList>
- <dependency name="Core" version="2.0.95"/>
- </dependencyList>
-</plugin>
diff --git a/src/plugins/welcome/Welcome.pluginspec.in b/src/plugins/welcome/Welcome.pluginspec.in
new file mode 100644
index 0000000000..092bb2f263
--- /dev/null
+++ b/src/plugins/welcome/Welcome.pluginspec.in
@@ -0,0 +1,19 @@
+<plugin name=\"Welcome\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2010 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>
+ <category>Qt Creator</category>
+ <description>Default Welcome Screen Plugin</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/welcome/communitywelcomepagewidget.cpp b/src/plugins/welcome/communitywelcomepagewidget.cpp
index 82902b3cf1..1eb9a4b02b 100644
--- a/src/plugins/welcome/communitywelcomepagewidget.cpp
+++ b/src/plugins/welcome/communitywelcomepagewidget.cpp
@@ -41,8 +41,6 @@
#include <QtGui/QDesktopServices>
#include <QtGui/QTreeWidgetItem>
-using namespace Core::Internal;
-
struct Site {
const char *description;
const char *url;
@@ -86,7 +84,7 @@ static inline void populateWelcomeTreeWidget(const Site *sites, int count, Utils
CommunityWelcomePageWidget::CommunityWelcomePageWidget(QWidget *parent) :
QWidget(parent),
- m_rssFetcher(new RssFetcher(7)),
+ m_rssFetcher(new Core::RssFetcher(7)),
ui(new Ui::CommunityWelcomePageWidget)
{
ui->setupUi(this);
diff --git a/src/plugins/welcome/communitywelcomepagewidget.h b/src/plugins/welcome/communitywelcomepagewidget.h
index 7b3ab3ebdf..6a507a430d 100644
--- a/src/plugins/welcome/communitywelcomepagewidget.h
+++ b/src/plugins/welcome/communitywelcomepagewidget.h
@@ -41,9 +41,7 @@ class QUrl;
QT_END_NAMESPACE
namespace Core{
-namespace Internal {
- class RssFetcher;
-}
+class RssFetcher;
}
namespace Welcome {
@@ -69,7 +67,7 @@ private slots:
private:
- Core::Internal::RssFetcher *m_rssFetcher;
+ Core::RssFetcher *m_rssFetcher;
Ui::CommunityWelcomePageWidget *ui;
};
diff --git a/src/plugins/welcome/welcome.pro b/src/plugins/welcome/welcome.pro
index f5ad9bbe9f..9fcb3be5f9 100644
--- a/src/plugins/welcome/welcome.pro
+++ b/src/plugins/welcome/welcome.pro
@@ -17,4 +17,3 @@ FORMS += welcomemode.ui \
communitywelcomepagewidget.ui
RESOURCES += welcome.qrc
DEFINES += WELCOME_LIBRARY
-OTHER_FILES += Welcome.pluginspec
diff --git a/src/qtcreatorlibrary.pri b/src/qtcreatorlibrary.pri
index 35f2af4f24..9b35abb390 100644
--- a/src/qtcreatorlibrary.pri
+++ b/src/qtcreatorlibrary.pri
@@ -11,7 +11,7 @@ DESTDIR = $$IDE_LIBRARY_PATH
include(rpath.pri)
-TARGET = $$qtLibraryTarget($$TARGET)
+TARGET = $$qtLibraryName($$TARGET)
contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols
diff --git a/src/qtcreatorplugin.pri b/src/qtcreatorplugin.pri
index f18f4f5b9c..2b98eb9e3d 100644
--- a/src/qtcreatorplugin.pri
+++ b/src/qtcreatorplugin.pri
@@ -17,18 +17,37 @@ isEmpty(TARGET) {
error("qtcreatorplugin.pri: You must provide a TARGET")
}
-PLUGINSPECS = $${_PRO_FILE_PWD_}/$${TARGET}.pluginspec
-copy2build.input = PLUGINSPECS
-copy2build.output = $$DESTDIR/${QMAKE_FUNC_FILE_IN_stripSrcDir}
+defineReplace(stripOutDir) {
+ 1 ~= s|^$$re_escape($$OUT_PWD/)||$$i_flag
+ return($$1)
+}
+
+PLUGINSPEC = $$_PRO_FILE_PWD_/$${TARGET}.pluginspec
+PLUGINSPEC_IN = $${PLUGINSPEC}.in
+exists($$PLUGINSPEC_IN) {
+ OTHER_FILES += $$PLUGINSPEC_IN
+ PLUGINSPEC = $$OUT_PWD/$${TARGET}.pluginspec
+ QMAKE_SUBSTITUTES += $${PLUGINSPEC}.in
+ copy2build.output = $$DESTDIR/${QMAKE_FUNC_FILE_IN_stripOutDir}
+} else {
+ # need to support that for external plugins
+ OTHER_FILES += $$PLUGINSPEC
+ copy2build.output = $$DESTDIR/${QMAKE_FUNC_FILE_IN_stripSrcDir}
+}
+copy2build.input = PLUGINSPEC
isEmpty(vcproj):copy2build.variable_out = PRE_TARGETDEPS
copy2build.commands = $$QMAKE_COPY ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT}
copy2build.name = COPY ${QMAKE_FILE_IN}
copy2build.CONFIG += no_link
QMAKE_EXTRA_COMPILERS += copy2build
-
macx {
+ !isEmpty(TIGER_COMPAT_MODE) {
QMAKE_LFLAGS_SONAME = -Wl,-install_name,@executable_path/../PlugIns/$${PROVIDER}/
+ } else {
+ QMAKE_LFLAGS_SONAME = -Wl,-install_name,@rpath/PlugIns/$${PROVIDER}/
+ QMAKE_LFLAGS += -Wl,-rpath,@loader_path/../../
+ }
} else:linux-* {
#do the rpath by hand since it's not possible to use ORIGIN in QMAKE_RPATHDIR
QMAKE_RPATHDIR += \$\$ORIGIN
@@ -51,5 +70,5 @@ CONFIG += plugin plugin_with_soname
INSTALLS += target pluginspec
}
-TARGET = $$qtLibraryTarget($$TARGET)
+TARGET = $$qtLibraryName($$TARGET)
diff --git a/src/rpath.pri b/src/rpath.pri
index 750d0ed4d8..c0882c4115 100644
--- a/src/rpath.pri
+++ b/src/rpath.pri
@@ -1,5 +1,10 @@
macx {
- QMAKE_LFLAGS_SONAME = -Wl,-install_name,@executable_path/../PlugIns/
+ !isEmpty(TIGER_COMPAT_MODE) {
+ QMAKE_LFLAGS_SONAME = -Wl,-install_name,@executable_path/../PlugIns/
+ } else {
+ QMAKE_LFLAGS_SONAME = -Wl,-install_name,@rpath/PlugIns/
+ QMAKE_LFLAGS += -Wl,-rpath,@loader_path/../
+ }
} else:linux-* {
#do the rpath by hand since it's not possible to use ORIGIN in QMAKE_RPATHDIR
# this expands to $ORIGIN (after qmake and make), it does NOT read a qmake var
diff --git a/src/shared/cplusplus/AST.cpp b/src/shared/cplusplus/AST.cpp
index 04883c1193..1db8baadee 100644
--- a/src/shared/cplusplus/AST.cpp
+++ b/src/shared/cplusplus/AST.cpp
@@ -1111,6 +1111,8 @@ unsigned EnumSpecifierAST::firstToken() const
if (enumerator_list)
if (unsigned candidate = enumerator_list->firstToken())
return candidate;
+ if (stray_comma_token)
+ return stray_comma_token;
if (rbrace_token)
return rbrace_token;
return 0;
@@ -1121,6 +1123,8 @@ unsigned EnumSpecifierAST::lastToken() const
{
if (rbrace_token)
return rbrace_token + 1;
+ if (stray_comma_token)
+ return stray_comma_token + 1;
if (enumerator_list)
if (unsigned candidate = enumerator_list->lastToken())
return candidate;
diff --git a/src/shared/cplusplus/AST.h b/src/shared/cplusplus/AST.h
index 597998943a..cacf686da6 100644
--- a/src/shared/cplusplus/AST.h
+++ b/src/shared/cplusplus/AST.h
@@ -1625,6 +1625,7 @@ public:
NameAST *name;
unsigned lbrace_token;
EnumeratorListAST *enumerator_list;
+ unsigned stray_comma_token;
unsigned rbrace_token;
public: // annotations
@@ -1636,6 +1637,7 @@ public:
, name(0)
, lbrace_token(0)
, enumerator_list(0)
+ , stray_comma_token(0)
, rbrace_token(0)
, symbol(0)
{}
diff --git a/src/shared/cplusplus/ASTClone.cpp b/src/shared/cplusplus/ASTClone.cpp
index 6a19e66aea..3a7ac4782c 100644
--- a/src/shared/cplusplus/ASTClone.cpp
+++ b/src/shared/cplusplus/ASTClone.cpp
@@ -561,6 +561,7 @@ EnumSpecifierAST *EnumSpecifierAST::clone(MemoryPool *pool) const
for (EnumeratorListAST *iter = enumerator_list, **ast_iter = &ast->enumerator_list;
iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
*ast_iter = new (pool) EnumeratorListAST((iter->value) ? iter->value->clone(pool) : 0);
+ ast->stray_comma_token = stray_comma_token;
ast->rbrace_token = rbrace_token;
return ast;
}
diff --git a/src/shared/cplusplus/ASTMatcher.cpp b/src/shared/cplusplus/ASTMatcher.cpp
index 8c040c92ba..e14a79f3fb 100644
--- a/src/shared/cplusplus/ASTMatcher.cpp
+++ b/src/shared/cplusplus/ASTMatcher.cpp
@@ -930,6 +930,8 @@ bool ASTMatcher::match(EnumSpecifierAST *node, EnumSpecifierAST *pattern)
else if (! AST::match(node->enumerator_list, pattern->enumerator_list, this))
return false;
+ pattern->stray_comma_token = node->stray_comma_token;
+
pattern->rbrace_token = node->rbrace_token;
return true;
diff --git a/src/shared/cplusplus/Bind.cpp b/src/shared/cplusplus/Bind.cpp
index cf2e085189..307ad0ef66 100644
--- a/src/shared/cplusplus/Bind.cpp
+++ b/src/shared/cplusplus/Bind.cpp
@@ -1800,7 +1800,13 @@ bool Bind::visit(SimpleDeclarationAST *ast)
bool Bind::visit(EmptyDeclarationAST *ast)
{
(void) ast;
- // unsigned semicolon_token = ast->semicolon_token;
+ unsigned semicolon_token = ast->semicolon_token;
+ if (_scope && (_scope->isClass() || _scope->isNamespace())) {
+ const Token &tk = tokenAt(semicolon_token);
+
+ if (! tk.generated())
+ translationUnit()->warning(semicolon_token, "extra `;'");
+ }
return false;
}
@@ -2774,6 +2780,14 @@ bool Bind::visit(EnumSpecifierAST *ast)
for (EnumeratorListAST *it = ast->enumerator_list; it; it = it->next) {
this->enumerator(it->value, e);
}
+
+ if (ast->stray_comma_token /* && ! translationUnit()->cxx0xEnabled()*/) {
+ const Token &tk = tokenAt(ast->stray_comma_token);
+ if (! tk.generated())
+ translationUnit()->warning(ast->stray_comma_token,
+ "commas at the end of enumerator lists are a C++0x-specific feature");
+ }
+
(void) switchScope(previousScope);
return false;
}
diff --git a/src/shared/cplusplus/Control.cpp b/src/shared/cplusplus/Control.cpp
index 1b9b686ecf..a0308a7e68 100644
--- a/src/shared/cplusplus/Control.cpp
+++ b/src/shared/cplusplus/Control.cpp
@@ -555,6 +555,15 @@ DiagnosticClient *Control::diagnosticClient() const
void Control::setDiagnosticClient(DiagnosticClient *diagnosticClient)
{ d->diagnosticClient = diagnosticClient; }
+const OperatorNameId *Control::findOperatorNameId(OperatorNameId::Kind operatorId) const
+{
+ Table<OperatorNameId>::const_iterator i = d->operatorNameIds.find(operatorId);
+ if (i == d->operatorNameIds.end())
+ return 0;
+ else
+ return &*i;
+}
+
const Identifier *Control::findIdentifier(const char *chars, unsigned size) const
{ return d->identifiers.findLiteral(chars, size); }
@@ -754,6 +763,22 @@ const Identifier *Control::objcCopyId() const
const Identifier *Control::objcNonatomicId() const
{ return d->objcNonatomicId; }
+Symbol **Control::firstSymbol() const
+{
+ if (d->symbols.empty())
+ return 0;
+
+ return &*d->symbols.begin();
+}
+
+Symbol **Control::lastSymbol() const
+{
+ if (d->symbols.empty())
+ return 0;
+
+ return &*d->symbols.begin() + d->symbols.size();
+}
+
bool Control::hasSymbol(Symbol *symbol) const
{
return std::find(d->symbols.begin(), d->symbols.end(), symbol) != d->symbols.end();
diff --git a/src/shared/cplusplus/Control.h b/src/shared/cplusplus/Control.h
index 4bb8ad7d15..f3a547d8cf 100644
--- a/src/shared/cplusplus/Control.h
+++ b/src/shared/cplusplus/Control.h
@@ -191,6 +191,8 @@ public:
const Identifier *objcCopyId() const;
const Identifier *objcNonatomicId() const;
+ const OperatorNameId *findOperatorNameId(OperatorNameId::Kind operatorId) const;
+
const Identifier *findIdentifier(const char *chars, unsigned size) const;
const Identifier *identifier(const char *chars, unsigned size);
const Identifier *identifier(const char *chars);
@@ -214,6 +216,9 @@ public:
const NumericLiteral *numericLiteral(const char *chars, unsigned size);
const NumericLiteral *numericLiteral(const char *chars);
+ Symbol **firstSymbol() const;
+ Symbol **lastSymbol() const;
+
bool hasSymbol(Symbol *symbol) const;
void squeeze();
diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp
index 92fe46298a..4bd4a196aa 100644
--- a/src/shared/cplusplus/Parser.cpp
+++ b/src/shared/cplusplus/Parser.cpp
@@ -1550,6 +1550,9 @@ bool Parser::parseEnumSpecifier(SpecifierListAST *&node)
enumerator_ptr = &(*enumerator_ptr)->next;
}
+ if (LA() == T_COMMA && LA(2) == T_RBRACE)
+ ast->stray_comma_token = consumeToken();
+
if (LA() != T_RBRACE)
match(T_COMMA, &comma_token);
}
diff --git a/src/shared/cplusplus/Symbols.cpp b/src/shared/cplusplus/Symbols.cpp
index 3460180433..518ceab7de 100644
--- a/src/shared/cplusplus/Symbols.cpp
+++ b/src/shared/cplusplus/Symbols.cpp
@@ -291,6 +291,8 @@ bool Function::hasReturnType() const
unsigned Function::argumentCount() const
{
const unsigned c = memberCount();
+ if (c > 0 && memberAt(0)->type()->isVoidType())
+ return 0;
if (c > 0 && memberAt(c - 1)->isBlock())
return c - 1;
return c;
@@ -364,6 +366,30 @@ void Function::visitSymbol0(SymbolVisitor *visitor)
}
}
+bool Function::maybeValidPrototype(unsigned actualArgumentCount) const
+{
+ unsigned minNumberArguments = 0;
+
+ for (; minNumberArguments < this->argumentCount(); ++minNumberArguments) {
+ Argument *arg = this->argumentAt(minNumberArguments)->asArgument();
+
+ if (arg->hasInitializer())
+ break;
+ }
+
+ if (actualArgumentCount < minNumberArguments) {
+ // not enough arguments.
+ return false;
+
+ } else if (! this->isVariadic() && actualArgumentCount > this->argumentCount()) {
+ // too many arguments.
+ return false;
+ }
+
+ return true;
+}
+
+
Block::Block(TranslationUnit *translationUnit, unsigned sourceLocation)
: Scope(translationUnit, sourceLocation, /*name = */ 0)
{ }
diff --git a/src/shared/cplusplus/Symbols.h b/src/shared/cplusplus/Symbols.h
index d41022d61a..e7a2dec704 100644
--- a/src/shared/cplusplus/Symbols.h
+++ b/src/shared/cplusplus/Symbols.h
@@ -354,6 +354,8 @@ public:
bool isAmbiguous() const; // internal
void setAmbiguous(bool isAmbiguous); // internal
+ bool maybeValidPrototype(unsigned actualArgumentCount) const;
+
protected:
virtual void visitSymbol0(SymbolVisitor *visitor);
virtual void accept0(TypeVisitor *visitor);
diff --git a/src/shared/help/bookmarkmanager.cpp b/src/shared/help/bookmarkmanager.cpp
index e3cbb3909c..bf67269570 100644
--- a/src/shared/help/bookmarkmanager.cpp
+++ b/src/shared/help/bookmarkmanager.cpp
@@ -34,7 +34,7 @@
#include "bookmarkmanager.h"
#include "centralwidget.h"
-#include "helpmanager.h"
+#include "localhelpmanager.h"
#include "openpagesmanager.h"
#include <utils/filterlineedit.h>
diff --git a/src/shared/help/contentwindow.cpp b/src/shared/help/contentwindow.cpp
index b71abd68e6..c63921f36a 100644
--- a/src/shared/help/contentwindow.cpp
+++ b/src/shared/help/contentwindow.cpp
@@ -34,8 +34,8 @@
#include "contentwindow.h"
#include "centralwidget.h"
-#include "helpmanager.h"
#include "helpviewer.h"
+#include "localhelpmanager.h"
#include "openpagesmanager.h"
#include <QtGui/QLayout>
diff --git a/src/shared/help/indexwindow.cpp b/src/shared/help/indexwindow.cpp
index 6ed86b1480..dc804f0132 100644
--- a/src/shared/help/indexwindow.cpp
+++ b/src/shared/help/indexwindow.cpp
@@ -33,9 +33,9 @@
#include "centralwidget.h"
-#include "helpmanager.h"
#include "helpviewer.h"
#include "indexwindow.h"
+#include "localhelpmanager.h"
#include "openpagesmanager.h"
#include "topicchooser.h"
diff --git a/src/shared/proparser/ioutils.cpp b/src/shared/proparser/ioutils.cpp
index 82246c44c8..5b7ee40bf6 100644
--- a/src/shared/proparser/ioutils.cpp
+++ b/src/shared/proparser/ioutils.cpp
@@ -92,115 +92,60 @@ QString IoUtils::resolvePath(const QString &baseDir, const QString &fileName)
return QDir::cleanPath(baseDir + QLatin1Char('/') + fileName);
}
-#ifdef Q_OS_WIN
-
-// FIXME: Without this, quoting is not foolproof. But it needs support in the process setup, etc.
-//#define PERCENT_ESCAPE QLatin1String("%PERCENT_SIGN%")
-
-static QString quoteArgInternal(const QString &arg)
-{
- // Escape quotes, preceding backslashes are doubled. Surround with quotes.
- // Note that cmd does not understand quote escapes in quoted strings,
- // so the quoting needs to be "suspended".
- const QLatin1Char bs('\\'), dq('"');
- QString ret;
- bool inquote = false;
- int bslashes = 0;
- for (int p = 0; p < arg.length(); p++) {
- if (arg[p] == bs) {
- bslashes++;
- } else if (arg[p] == dq) {
- if (inquote) {
- ret.append(dq);
- inquote = false;
- }
- for (; bslashes; bslashes--)
- ret.append(QLatin1String("\\\\"));
- ret.append(QLatin1String("\\^\""));
- } else {
- if (!inquote) {
- ret.append(dq);
- inquote = true;
- }
- for (; bslashes; bslashes--)
- ret.append(bs);
- ret.append(arg[p]);
- }
- }
- //ret.replace(QLatin1Char('%'), PERCENT_ESCAPE);
- if (bslashes) {
- // Ensure that we don't have directly trailing backslashes,
- // so concatenating with another string won't cause surprises.
- if (!inquote)
- ret.append(dq);
- for (; bslashes; bslashes--)
- ret.append(QLatin1String("\\\\"));
- ret.append(dq);
- } else if (inquote) {
- ret.append(dq);
- }
- return ret;
-}
-
inline static bool isSpecialChar(ushort c)
{
// Chars that should be quoted (TM). This includes:
+#ifdef Q_OS_WIN
// - control chars & space
- // - the shell meta chars &()<>^|
+ // - the shell meta chars "&()<>^|
// - the potential separators ,;=
static const uchar iqm[] = {
- 0xff, 0xff, 0xff, 0xff, 0x41, 0x13, 0x00, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0x45, 0x13, 0x00, 0x78,
0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10
};
-
- return (c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7)));
-}
-
-QString IoUtils::shellQuote(const QString &arg)
-{
- if (arg.isEmpty())
- return QString::fromLatin1("\"\"");
-
- // Ensure that we don't have directly trailing backslashes,
- // so concatenating with another string won't cause surprises.
- if (arg.endsWith(QLatin1Char('\\')))
- return quoteArgInternal(arg);
-
- for (int x = arg.length() - 1; x >= 0; --x)
- if (isSpecialChar(arg[x].unicode()))
- return quoteArgInternal(arg);
-
- // Escape quotes. Preceding backslashes are doubled.
- // Note that the remaining string is not quoted.
- QString ret(arg);
- ret.replace(QRegExp(QLatin1String("(\\\\*)\"")), QLatin1String("\\1\\1\\^\""));
- //ret.replace('%', PERCENT_ESCAPE);
- return ret;
-}
-
-#else // Q_OS_WIN
-
-inline static bool isSpecial(QChar cUnicode)
-{
+#else
static const uchar iqm[] = {
0xff, 0xff, 0xff, 0xff, 0xdf, 0x07, 0x00, 0xd8,
0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x78
}; // 0-32 \'"$`<>|;&(){}*?#!~[]
+#endif
- uint c = cUnicode.unicode();
return (c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7)));
}
+inline static bool hasSpecialChars(const QString &arg)
+{
+ for (int x = arg.length() - 1; x >= 0; --x)
+ if (isSpecialChar(arg.unicode()[x].unicode()))
+ return true;
+ return false;
+}
+
QString IoUtils::shellQuote(const QString &arg)
{
if (!arg.length())
- return QString::fromLatin1("''");
- for (int i = 0; i < arg.length(); i++)
- if (isSpecial(arg.unicode()[i])) {
- const QLatin1Char q('\'');
- return q + QString(arg).replace(q, QLatin1String("'\\''")) + q;
- }
- return arg;
-}
+ return QString::fromLatin1("\"\"");
+ QString ret(arg);
+ if (hasSpecialChars(ret)) {
+#ifdef Q_OS_WIN
+ // Quotes are escaped and their preceding backslashes are doubled.
+ // It's impossible to escape anything inside a quoted string on cmd
+ // level, so the outer quoting must be "suspended".
+ ret.replace(QRegExp(QLatin1String("(\\\\*)\"")), QLatin1String("\"\\1\\1\\^\"\""));
+ // The argument must not end with a \ since this would be interpreted
+ // as escaping the quote -- rather put the \ behind the quote: e.g.
+ // rather use "foo"\ than "foo\"
+ int i = ret.length();
+ while (i > 0 && ret.at(i - 1) == QLatin1Char('\\'))
+ --i;
+ ret.insert(i, QLatin1Char('"'));
+ ret.prepend(QLatin1Char('"'));
+#else // Q_OS_WIN
+ ret.replace(QLatin1Char('\''), QLatin1String("'\\''"));
+ ret.prepend(QLatin1Char('\''));
+ ret.append(QLatin1Char('\''));
#endif // Q_OS_WIN
+ }
+ return ret;
+}
diff --git a/src/shared/proparser/profileevaluator.cpp b/src/shared/proparser/profileevaluator.cpp
index 9ab5458835..46124e6229 100644
--- a/src/shared/proparser/profileevaluator.cpp
+++ b/src/shared/proparser/profileevaluator.cpp
@@ -94,6 +94,18 @@ ProFileOption::ProFileOption()
#endif
qmakespec = QString::fromLocal8Bit(qgetenv("QMAKESPEC").data());
+ setHostTargetMode();
+#ifdef PROEVALUATOR_THREAD_SAFE
+ base_inProgress = false;
+#endif
+}
+
+ProFileOption::~ProFileOption()
+{
+}
+
+void ProFileOption::setHostTargetMode()
+{
#if defined(Q_OS_WIN32)
target_mode = TARG_WIN_MODE;
#elif defined(Q_OS_MAC)
@@ -103,15 +115,15 @@ ProFileOption::ProFileOption()
#else
target_mode = TARG_UNIX_MODE;
#endif
-
-#ifdef PROEVALUATOR_THREAD_SAFE
- base_inProgress = false;
-#endif
}
-ProFileOption::~ProFileOption()
-{
-}
+const struct ProFileOption::TargetModeMapElement ProFileOption::modeMap[] = {
+ { "-unix", TARG_UNIX_MODE },
+ { "-macx", TARG_MACX_MODE },
+ { "-win32", TARG_WIN_MODE }
+};
+const int ProFileOption::modeMapSize
+ = sizeof ProFileOption::modeMap / sizeof ProFileOption::modeMap[0];
///////////////////////////////////////////////////////////////////////
//
@@ -3228,6 +3240,19 @@ void ProFileEvaluator::setOutputDir(const QString &dir)
void ProFileEvaluator::setCommandLineArguments(const QStringList &args)
{
d->m_cmdArgs = args;
+
+ d->m_option->setHostTargetMode();
+ bool targetModeSet = false;
+ for (int i = args.count() - 1; !targetModeSet && i >= 0; --i) {
+ for (int j = 0; j < ProFileOption::modeMapSize; ++j) {
+ const ProFileOption::TargetModeMapElement &mapElem = ProFileOption::modeMap[j];
+ if (args.at(i) == QLatin1String(mapElem.qmakeOption)) {
+ d->m_option->target_mode = mapElem.targetMode;
+ targetModeSet = true;
+ break;
+ }
+ }
+ }
}
QT_END_NAMESPACE
diff --git a/src/shared/proparser/profileevaluator.h b/src/shared/proparser/profileevaluator.h
index 2219587f19..917a32ffbb 100644
--- a/src/shared/proparser/profileevaluator.h
+++ b/src/shared/proparser/profileevaluator.h
@@ -179,7 +179,15 @@ struct ProFileOption
//QString pro_ext;
//QString res_ext;
+ static const struct TargetModeMapElement {
+ const char * const qmakeOption;
+ const TARG_MODE targetMode;
+ } modeMap[];
+ static const int modeMapSize;
+
private:
+ void setHostTargetMode();
+
friend class ProFileEvaluator;
friend class ProFileEvaluator::Private;
QHash<ProString, ProStringList> base_valuemap; // Cached results of qmake.conf, .qmake.cache & default_pre.prf
diff --git a/src/shared/symbianutils/json.cpp b/src/shared/symbianutils/json.cpp
index 03027b390b..b405df96fd 100644
--- a/src/shared/symbianutils/json.cpp
+++ b/src/shared/symbianutils/json.cpp
@@ -92,6 +92,7 @@ QByteArray JsonValue::parseNumber(const char *&from, const char *to)
QByteArray JsonValue::parseCString(const char *&from, const char *to)
{
QByteArray result;
+ const char * const fromSaved = from;
JDEBUG("parseCString: " << QByteArray(from, to - from));
if (*from != '"') {
qDebug() << "JSON Parse Error, double quote expected";
@@ -109,7 +110,8 @@ QByteArray JsonValue::parseCString(const char *&from, const char *to)
if (*ptr == '\\') {
++ptr;
if (ptr == to) {
- qDebug() << "JSON Parse Error, unterminated backslash escape";
+ qWarning("JSON Parse Error, unterminated backslash escape in '%s'",
+ QByteArray(fromSaved, to - fromSaved).constData());
from = ptr; // So we don't hang
return QByteArray();
}
@@ -134,8 +136,24 @@ QByteArray JsonValue::parseCString(const char *&from, const char *to)
case 'v': *dst++ = '\v'; break;
case '"': *dst++ = '"'; break;
case '\\': *dst++ = '\\'; break;
- default:
- {
+ case 'u': { // 4 digit hex escape as in '\u000a'
+ if (end - src < 4) {
+ qWarning("JSON Parse Error, too few hex digits in \\u-escape in '%s' obtained from '%s'",
+ result.constData(), QByteArray(fromSaved, to - fromSaved).constData());
+ return QByteArray();
+ }
+ bool ok;
+ const uchar prod = QByteArray(src, 4).toUInt(&ok, 16);
+ if (!ok) {
+ qWarning("JSON Parse Error, invalid hex digits in \\u-escape in '%s' obtained from '%s'",
+ result.constData(), QByteArray(fromSaved, to - fromSaved).constData());
+ return QByteArray();
+ }
+ *dst++ = prod;
+ src += 4;
+ }
+ break;
+ default: { // Up to 3 decimal digits: Not sure if this is supported in JSON?
int chars = 0;
uchar prod = 0;
forever {
@@ -149,7 +167,8 @@ QByteArray JsonValue::parseCString(const char *&from, const char *to)
c = *src++;
}
if (!chars) {
- qDebug() << "JSON Parse Error, unrecognized backslash escape";
+ qWarning("JSON Parse Error, unrecognized backslash escape in string '%s' obtained from '%s'",
+ result.constData(), QByteArray(fromSaved, to - fromSaved).constData());
return QByteArray();
}
*dst++ = prod;
diff --git a/src/shared/symbianutils/json.h b/src/shared/symbianutils/json.h
index 6705f5fd79..0ff372e204 100644
--- a/src/shared/symbianutils/json.h
+++ b/src/shared/symbianutils/json.h
@@ -59,7 +59,7 @@ public:
Boolean,
Object,
NullObject,
- Array,
+ Array
};
Type m_type;
diff --git a/src/shared/symbianutils/launcher.cpp b/src/shared/symbianutils/launcher.cpp
index 46a56a2376..66f0707d30 100644
--- a/src/shared/symbianutils/launcher.cpp
+++ b/src/shared/symbianutils/launcher.cpp
@@ -110,7 +110,7 @@ struct LauncherPrivate {
CopyState m_copyState;
DownloadState m_downloadState;
QString m_fileName;
- QStringList m_commandLineArgs;
+ QString m_commandLineArgs;
QStringList m_installFileNames;
int m_currentInstallFileName;
int m_verbose;
@@ -222,7 +222,7 @@ void Launcher::setInstallFileNames(const QStringList &names)
d->m_currentInstallFileName = 0;
}
-void Launcher::setCommandLineArgs(const QStringList &args)
+void Launcher::setCommandLineArgs(const QString &args)
{
d->m_commandLineArgs = args;
}
@@ -271,7 +271,7 @@ bool Launcher::startServer(QString *errorMessage)
if (!d->m_fileName.isEmpty())
str << " Executable=" << d->m_fileName;
if (!d->m_commandLineArgs.isEmpty())
- str << " Arguments= " << d->m_commandLineArgs.join(QString(QLatin1Char(' ')));
+ str << " Arguments= " << d->m_commandLineArgs;
for (int i = 0; i < d->m_copyState.sourceFileNames.size(); ++i) {
str << " Package/Source=" << d->m_copyState.sourceFileNames.at(i);
str << " Remote Package/Destination=" << d->m_copyState.destinationFileNames.at(i);
@@ -959,7 +959,7 @@ void Launcher::handleInstallPackageFinished(const TrkResult &result)
}
QByteArray Launcher::startProcessMessage(const QString &executable,
- const QStringList &arguments)
+ const QString &arguments)
{
// It's not started yet
QByteArray ba;
@@ -969,7 +969,7 @@ QByteArray Launcher::startProcessMessage(const QString &executable,
QByteArray commandLineBa = executable.toLocal8Bit();
commandLineBa.append(char(0));
if (!arguments.isEmpty())
- commandLineBa.append(arguments.join(QString(QLatin1Char(' '))).toLocal8Bit());
+ commandLineBa.append(arguments.toLocal8Bit());
appendString(&ba, commandLineBa, TargetByteOrder, true);
return ba;
}
@@ -1026,7 +1026,10 @@ Launcher *Launcher::acquireFromDeviceManager(const QString &serverName,
SymbianUtils::SymbianDeviceManager *sdm = SymbianUtils::SymbianDeviceManager::instance();
const QSharedPointer<trk::TrkDevice> device = sdm->acquireDevice(serverName);
if (device.isNull()) {
- *errorMessage = tr("Unable to acquire a device for port '%1'. It appears to be in use.").arg(serverName);
+ if (serverName.isEmpty())
+ *errorMessage = tr("No device is connected. Please connect a device and try again.");
+ else
+ *errorMessage = tr("Unable to acquire a device for port '%1'. It appears to be in use.").arg(serverName);
return 0;
}
// Wire release signal.
diff --git a/src/shared/symbianutils/launcher.h b/src/shared/symbianutils/launcher.h
index eb537198ff..caff96ea0c 100644
--- a/src/shared/symbianutils/launcher.h
+++ b/src/shared/symbianutils/launcher.h
@@ -96,7 +96,7 @@ public:
void setCopyFileNames(const QStringList &srcName, const QStringList &dstName);
void setDownloadFileName(const QString &srcName, const QString &dstName);
void setInstallFileNames(const QStringList &names);
- void setCommandLineArgs(const QStringList &args);
+ void setCommandLineArgs(const QString &args);
bool startServer(QString *errorMessage);
void setInstallationMode(InstallationMode installation);
void setInstallationDrive(char drive);
@@ -126,7 +126,7 @@ public:
// Create Trk message to start a process.
static QByteArray startProcessMessage(const QString &executable,
- const QStringList &arguments);
+ const QString &arguments);
// Create Trk message to read memory
static QByteArray readMemoryMessage(uint pid, uint tid, uint from, uint len);
static QByteArray readRegistersMessage(uint pid, uint tid);
diff --git a/src/shared/symbianutils/tcftrkdevice.cpp b/src/shared/symbianutils/tcftrkdevice.cpp
index c3feaccb01..0a1e104e7a 100644
--- a/src/shared/symbianutils/tcftrkdevice.cpp
+++ b/src/shared/symbianutils/tcftrkdevice.cpp
@@ -33,6 +33,7 @@
#include "tcftrkdevice.h"
#include "json.h"
+#include "trkutils.h"
#include <QtNetwork/QAbstractSocket>
#include <QtCore/QDebug>
@@ -44,7 +45,70 @@
enum { debug = 0 };
-static const char messageTerminatorC[] = "\003\001";
+static const char tcpMessageTerminatorC[] = "\003\001";
+
+// Serial Ping: 0xfc,0x1f
+static const char serialPingC[] = "\xfc\x1f";
+// Serial Pong: 0xfc,0xf1, followed by version info
+static const char serialPongC[] = "\xfc\xf1";
+
+static const char locatorAnswerC[] = "E\0Locator\0Hello\0[\"Locator\"]";
+
+/* Serial messages > (1K - 2) have to chunked in order to pass the USB
+ * router as '0xfe char(chunkCount - 1) data' ... '0x0 char(chunkCount - 2) data'
+ * ... '0x0 0x0 last-data' */
+static const unsigned serialChunkLength = 0x400; // 1K max USB router
+static const int maxSerialMessageLength = 0x10000; // given chunking scheme
+
+static const unsigned char serialChunkingStart = 0xfe;
+static const unsigned char serialChunkingContinuation = 0x0;
+enum { SerialChunkHeaderSize = 2 };
+
+// Create USB router frame
+static inline void encodeSerialFrame(const QByteArray &data, QByteArray *target)
+{
+ target->append(char(0x01));
+ target->append(char(0x92)); // CODA serial message ID
+ appendShort(target, ushort(data.size()), trk::BigEndian);
+ target->append(data);
+}
+
+// Split in chunks of 1K according to CODA protocol chunking
+static inline QByteArray encodeUsbSerialMessage(const QByteArray &dataIn)
+{
+ // Reserve 2 header bytes
+ static const int chunkSize = serialChunkLength - SerialChunkHeaderSize;
+ const int size = dataIn.size();
+ QByteArray frame;
+ // Do we need to split?
+ if (size < chunkSize) { // Nope, all happy.
+ frame.reserve(size + 4);
+ encodeSerialFrame(dataIn, &frame);
+ return frame;
+ }
+ // Split.
+ unsigned chunkCount = size / chunkSize;
+ if (size % chunkSize)
+ chunkCount++;
+ if (debug)
+ qDebug("Serial: Splitting message of %d bytes into %u chunks of %d", size, chunkCount, chunkSize);
+
+ frame.reserve((4 + serialChunkLength) * chunkCount);
+ int pos = 0;
+ for (unsigned c = chunkCount - 1; pos < size ; c--) {
+ QByteArray chunk; // chunk with long message start/continuation code
+ chunk.reserve(serialChunkLength);
+ chunk.append(pos ? serialChunkingContinuation : serialChunkingStart);
+ chunk.append(char(static_cast<unsigned char>(c))); // Avoid any signedness issues.
+ const int chunkEnd = qMin(pos + chunkSize, size);
+ chunk.append(dataIn.mid(pos, chunkEnd - pos));
+ encodeSerialFrame(chunk, &frame);
+ pos = chunkEnd;
+ }
+ if (debug > 1)
+ qDebug("Serial chunked:\n%s", qPrintable(tcftrk::formatData(frame)));
+ return frame;
+}
namespace tcftrk {
// ------------- TcfTrkCommandError
@@ -61,13 +125,17 @@ void TcfTrkCommandError::clear()
alternativeOrganization.clear();
}
+QDateTime TcfTrkCommandResult::tcfTimeToQDateTime(quint64 tcfTimeMS)
+{
+ const QDateTime time(QDate(1970, 1, 1));
+ return time.addMSecs(tcfTimeMS);
+}
+
void TcfTrkCommandError::write(QTextStream &str) const
{
if (isError()) {
- if (timeMS) {
- const QDateTime time(QDate(1970, 1, 1));
- str << time.addMSecs(timeMS).toString(Qt::ISODate) << ": ";
- }
+ if (timeMS)
+ str << TcfTrkCommandResult::tcfTimeToQDateTime(timeMS).toString(Qt::ISODate) << ": ";
str << "Error code: " << code
<< " '" << format << '\'';
if (!alternativeOrganization.isEmpty())
@@ -99,9 +167,16 @@ bool TcfTrkCommandError::parse(const QVector<JsonValue> &values)
unsigned errorKeyCount = 0;
clear();
do {
- if (values.isEmpty() || values.back().type() != JsonValue::Object)
+ if (values.isEmpty())
break;
- foreach (const JsonValue &c, values.back().children()) {
+ // Errors are mostly appended, except for FileSystem::open, in which case
+ // a string "null" file handle (sic!) follows the error.
+ const int last = values.size() - 1;
+ const int checkIndex = last == 1 && values.at(last).data() == "null" ?
+ last - 1 : last;
+ if (values.at(checkIndex).type() != JsonValue::Object)
+ break;
+ foreach (const JsonValue &c, values.at(checkIndex).children()) {
if (c.name() == "Time") {
timeMS = c.data().toULongLong();
errorKeyCount++;
@@ -217,6 +292,10 @@ QString TcfTrkCommandResult::toString() const
return rc;
}
+TcfTrkStatResponse::TcfTrkStatResponse() : size(0)
+{
+}
+
// Entry for send queue.
enum SpecialHandlingFlags { None =0,
FakeRegisterGetMIntermediate = 0x1,
@@ -251,21 +330,24 @@ struct TcfTrkDevicePrivate {
TcfTrkDevicePrivate();
- const QByteArray m_messageTerminator;
+ const QByteArray m_tcpMessageTerminator;
IODevicePtr m_device;
unsigned m_verbose;
QByteArray m_readBuffer;
+ QByteArray m_serialBuffer; // for chunked messages
int m_token;
QQueue<TcfTrkSendQueueEntry> m_sendQueue;
TokenWrittenMessageMap m_writtenMessages;
QVector<QByteArray> m_registerNames;
QVector<QByteArray> m_fakeGetMRegisterValues;
+ bool m_serialFrame;
+ bool m_serialPingOnly;
};
TcfTrkDevicePrivate::TcfTrkDevicePrivate() :
- m_messageTerminator(messageTerminatorC),
- m_verbose(0), m_token(0)
+ m_tcpMessageTerminator(tcpMessageTerminatorC),
+ m_verbose(0), m_token(0), m_serialFrame(false), m_serialPingOnly(false)
{
}
@@ -369,7 +451,12 @@ void TcfTrkDevice::slotDeviceSocketStateChanged()
static inline QString debugMessage(QByteArray message, const char *prefix = 0)
{
- message.replace('\0', '|');
+ const bool isBinary = !message.isEmpty() && message.at(0) < 0;
+ if (isBinary) {
+ message = message.toHex(); // Some serial special message
+ } else {
+ message.replace('\0', '|');
+ }
const QString messageS = QString::fromLatin1(message);
return prefix ?
(QLatin1String(prefix) + messageS) : messageS;
@@ -377,30 +464,129 @@ static inline QString debugMessage(QByteArray message, const char *prefix = 0)
void TcfTrkDevice::slotDeviceReadyRead()
{
- d->m_readBuffer += d->m_device->readAll();
+ const QByteArray newData = d->m_device->readAll();
+ d->m_readBuffer += newData;
+ if (debug)
+ qDebug("ReadBuffer: %s", qPrintable(trk::stringFromArray(newData)));
+ if (d->m_serialFrame) {
+ deviceReadyReadSerial();
+ } else {
+ deviceReadyReadTcp();
+ }
+}
+
+// Find a serial header in input stream '0x1', '0x92', 'lenH', 'lenL'
+// and return message position and size.
+static inline QPair<int, int> findSerialHeader(const QByteArray &in)
+{
+ const int size = in.size();
+ const char header1 = 0x1;
+ const char header2 = char(0x92);
+ // Header should in theory always be at beginning of
+ // buffer. Warn if there are bogus data in-between.
+ for (int pos = 0; pos < size; ) {
+ if (pos + 4 < size && in.at(pos) == header1 && in.at(pos + 1) == header2) {
+ const int length = trk::extractShort(in.constData() + 2);
+ return QPair<int, int>(pos + 4, length);
+ }
+ // Find next
+ pos = in.indexOf(header1, pos + 1);
+ qWarning("Bogus data received on serial line: %s\n"
+ "Frame Header at: %d", qPrintable(trk::stringFromArray(in)), pos);
+ if (pos < 0)
+ break;
+ }
+ return QPair<int, int>(-1, -1);
+}
+
+void TcfTrkDevice::deviceReadyReadSerial()
+{
+ do {
+ // Extract message (pos,len)
+ const QPair<int, int> messagePos = findSerialHeader(d->m_readBuffer);
+ if (messagePos.first < 0)
+ break;
+ // Do we have the complete message?
+ const int messageEnd = messagePos.first + messagePos.second;
+ if (messageEnd > d->m_readBuffer.size())
+ break;
+ processSerialMessage(d->m_readBuffer.mid(messagePos.first, messagePos.second));
+ d->m_readBuffer.remove(0, messageEnd);
+ } while (d->m_readBuffer.isEmpty());
+ checkSendQueue(); // Send off further messages
+}
+
+void TcfTrkDevice::processSerialMessage(const QByteArray &message)
+{
+ if (debug > 1)
+ qDebug("Serial message: %s",qPrintable(trk::stringFromArray(message)));
+ if (message.isEmpty())
+ return;
+ // Is thing a ping/pong response
+ const int size = message.size();
+ if (message.startsWith(serialPongC)) {
+ const QString version = QString::fromLatin1(message.mid(sizeof(serialPongC) - 1));
+ emitLogMessage(QString::fromLatin1("Serial connection from '%1'").arg(version));
+ emit serialPong(version);
+ // Answer with locator.
+ if (!d->m_serialPingOnly)
+ writeMessage(QByteArray(locatorAnswerC, sizeof(locatorAnswerC)));
+ return;
+ }
+ // Check for long message (see top, '0xfe #number, data' or '0x0 #number, data')
+ // TODO: This is currently untested.
+ const unsigned char *dataU = reinterpret_cast<const unsigned char *>(message.constData());
+ const bool isLongMessageStart = size > SerialChunkHeaderSize
+ && *dataU == serialChunkingStart;
+ const bool isLongMessageContinuation = size > SerialChunkHeaderSize
+ && *dataU == serialChunkingContinuation;
+ if (isLongMessageStart || isLongMessageContinuation) {
+ const unsigned chunkNumber = *++dataU;
+ if (isLongMessageStart) { // Start new buffer
+ d->m_serialBuffer.clear();
+ d->m_serialBuffer.reserve( (chunkNumber + 1) * serialChunkLength);
+ }
+ d->m_serialBuffer.append(message.mid(SerialChunkHeaderSize, size - SerialChunkHeaderSize));
+ // Last chunk? - Process
+ if (!chunkNumber) {
+ processMessage(d->m_serialBuffer);
+ d->m_serialBuffer.clear();
+ d->m_serialBuffer.squeeze();
+ }
+ } else {
+ processMessage(message); // Normal, unchunked message
+ }
+}
+
+void TcfTrkDevice::deviceReadyReadTcp()
+{
// Take complete message off front of readbuffer.
do {
- const int messageEndPos = d->m_readBuffer.indexOf(d->m_messageTerminator);
+ const int messageEndPos = d->m_readBuffer.indexOf(d->m_tcpMessageTerminator);
if (messageEndPos == -1)
break;
if (messageEndPos == 0) {
// TCF TRK 4.0.5 emits empty messages on errors.
emitLogMessage(QString::fromLatin1("An empty TCF TRK message has been received."));
} else {
- const QByteArray message = d->m_readBuffer.left(messageEndPos);
- if (debug)
- qDebug("Read %d bytes:\n%s", message.size(), qPrintable(formatData(message)));
- if (const int errorCode = parseMessage(message)) {
- emitLogMessage(QString::fromLatin1("Parse error %1 : %2").
- arg(errorCode).arg(debugMessage(message)));
- if (debug)
- qDebug("Parse error %d for %d bytes:\n%s", errorCode,
- message.size(), qPrintable(formatData(message)));
- }
+ processMessage(d->m_readBuffer.left(messageEndPos));
}
- d->m_readBuffer.remove(0, messageEndPos + d->m_messageTerminator.size());
+ d->m_readBuffer.remove(0, messageEndPos + d->m_tcpMessageTerminator.size());
} while (!d->m_readBuffer.isEmpty());
- checkSendQueue(); // Send off further message
+ checkSendQueue(); // Send off further messages
+}
+
+void TcfTrkDevice::processMessage(const QByteArray &message)
+{
+ if (debug)
+ qDebug("Read %d bytes:\n%s", message.size(), qPrintable(formatData(message)));
+ if (const int errorCode = parseMessage(message)) {
+ emitLogMessage(QString::fromLatin1("Parse error %1 : %2").
+ arg(errorCode).arg(debugMessage(message)));
+ if (debug)
+ qDebug("Parse error %d for %d bytes:\n%s", errorCode,
+ message.size(), qPrintable(formatData(message)));
+ }
}
// Split \0-terminated message into tokens, skipping the initial type character
@@ -540,8 +726,6 @@ int TcfTrkDevice::parseTcfCommandReply(char type, const QVector<QByteArray> &tok
return 0;
}
-static const char locatorAnswerC[] = "E\0Locator\0Hello\0[\"Locator\"]";
-
int TcfTrkDevice::parseTcfEvent(const QVector<QByteArray> &tokens)
{
// Event: Ignore the periodical heartbeat event, answer 'Hello',
@@ -561,9 +745,10 @@ int TcfTrkDevice::parseTcfEvent(const QVector<QByteArray> &tokens)
// Parse known events, emit signals
QScopedPointer<TcfTrkEvent> knownEvent(TcfTrkEvent::parseEvent(service, tokens.at(1), values));
if (!knownEvent.isNull()) {
- // Answer hello event.
+ // Answer hello event (WLAN)
if (knownEvent->type() == TcfTrkEvent::LocatorHello)
- writeMessage(QByteArray(locatorAnswerC, sizeof(locatorAnswerC)));
+ if (!d->m_serialFrame)
+ writeMessage(QByteArray(locatorAnswerC, sizeof(locatorAnswerC)));
emit tcfEvent(*knownEvent);
}
emit genericTcfEvent(service, tokens.at(1), values);
@@ -589,6 +774,16 @@ unsigned TcfTrkDevice::verbose() const
return d->m_verbose;
}
+bool TcfTrkDevice::serialFrame() const
+{
+ return d->m_serialFrame;
+}
+
+void TcfTrkDevice::setSerialFrame(bool s)
+{
+ d->m_serialFrame = s;
+}
+
void TcfTrkDevice::setVerbose(unsigned v)
{
d->m_verbose = v;
@@ -614,6 +809,18 @@ bool TcfTrkDevice::checkOpen()
return true;
}
+void TcfTrkDevice::sendSerialPing(bool pingOnly)
+{
+ if (!checkOpen())
+ return;
+
+ d->m_serialPingOnly = pingOnly;
+ setSerialFrame(true);
+ writeMessage(QByteArray(serialPingC, qstrlen(serialPingC)), false);
+ if (d->m_verbose)
+ emitLogMessage(QLatin1String("Ping..."));
+}
+
void TcfTrkDevice::sendTcfTrkMessage(MessageType mt, Services service, const char *command,
const char *commandParameters, // may contain '\0'
int commandParametersLength,
@@ -662,18 +869,29 @@ void TcfTrkDevice::sendTcfTrkMessage(MessageType mt, Services service, const cha
}
// Enclose in message frame and write.
-void TcfTrkDevice::writeMessage(QByteArray data)
+void TcfTrkDevice::writeMessage(QByteArray data, bool ensureTerminating0)
{
if (!checkOpen())
return;
+ if (d->m_serialFrame && data.size() > maxSerialMessageLength) {
+ qCritical("Attempt to send large message (%d bytes) exceeding the "
+ "limit of %d bytes over serial channel. Skipping.",
+ data.size(), maxSerialMessageLength);
+ return;
+ }
+
if (d->m_verbose)
emitLogMessage(debugMessage(data, "TCF <-"));
// Ensure \0-termination which easily gets lost in QByteArray CT.
- if (!data.endsWith('\0'))
+ if (ensureTerminating0 && !data.endsWith('\0'))
data.append('\0');
- data += d->m_messageTerminator;
+ if (d->m_serialFrame) {
+ data = encodeUsbSerialMessage(data);
+ } else {
+ data += d->m_tcpMessageTerminator;
+ }
if (debug > 1)
qDebug("Writing:\n%s", qPrintable(formatData(data)));
@@ -957,6 +1175,25 @@ QVector<QByteArray> TcfTrkDevice::parseRegisterGetChildren(const TcfTrkCommandRe
return rc;
}
+TcfTrkStatResponse TcfTrkDevice::parseStat(const TcfTrkCommandResult &r)
+{
+ TcfTrkStatResponse rc;
+ if (!r || r.values.size() < 1 || r.values.front().type() != JsonValue::Object)
+ return rc;
+ foreach(const JsonValue &v, r.values.front().children()) {
+ if (v.name() == "Size") {
+ rc.size = v.data().toULongLong();
+ } else if (v.name() == "ATime") {
+ if (const quint64 atime = v.data().toULongLong())
+ rc.accessTime = TcfTrkCommandResult::tcfTimeToQDateTime(atime);
+ } else if (v.name() == "MTime") {
+ if (const quint64 mtime = v.data().toULongLong())
+ rc.modTime = TcfTrkCommandResult::tcfTimeToQDateTime(mtime);
+ }
+ }
+ return rc;
+}
+
void TcfTrkDevice::sendRegistersGetChildrenCommand(const TcfTrkCallback &callBack,
const QByteArray &contextId,
const QVariant &cookie)
@@ -1098,4 +1335,67 @@ void TcfTrkDevice::sendLoggingAddListenerCommand(const TcfTrkCallback &callBack,
sendTcfTrkMessage(MessageWithReply, LoggingService, "addListener", data, callBack, cookie);
}
+void tcftrk::TcfTrkDevice::sendFileSystemOpenCommand(const tcftrk::TcfTrkCallback &callBack,
+ const QByteArray &name,
+ unsigned flags,
+ const QVariant &cookie)
+{
+ QByteArray data;
+ JsonInputStream str(data);
+ str << name << '\0' << flags << '\0' << '{' << '}';
+ sendTcfTrkMessage(MessageWithReply, FileSystemService, "open", data, callBack, cookie);
+}
+
+void tcftrk::TcfTrkDevice::sendFileSystemFstatCommand(const TcfTrkCallback &callBack,
+ const QByteArray &handle,
+ const QVariant &cookie)
+{
+ QByteArray data;
+ JsonInputStream str(data);
+ str << handle;
+ sendTcfTrkMessage(MessageWithReply, FileSystemService, "fstat", data, callBack, cookie);
+}
+
+void tcftrk::TcfTrkDevice::sendFileSystemWriteCommand(const tcftrk::TcfTrkCallback &callBack,
+ const QByteArray &handle,
+ const QByteArray &dataIn,
+ unsigned offset,
+ const QVariant &cookie)
+{
+ QByteArray data;
+ JsonInputStream str(data);
+ str << handle << '\0' << offset << '\0' << dataIn.toBase64();
+ sendTcfTrkMessage(MessageWithReply, FileSystemService, "write", data, callBack, cookie);
+}
+
+void tcftrk::TcfTrkDevice::sendFileSystemCloseCommand(const tcftrk::TcfTrkCallback &callBack,
+ const QByteArray &handle,
+ const QVariant &cookie)
+{
+ QByteArray data;
+ JsonInputStream str(data);
+ str << handle;
+ sendTcfTrkMessage(MessageWithReply, FileSystemService, "close", data, callBack, cookie);
+}
+
+void tcftrk::TcfTrkDevice::sendSymbianInstallSilentInstallCommand(const tcftrk::TcfTrkCallback &callBack,
+ const QByteArray &file,
+ const QByteArray &targetDrive,
+ const QVariant &cookie)
+{
+ QByteArray data;
+ JsonInputStream str(data);
+ str << file << '\0' << targetDrive;
+ sendTcfTrkMessage(MessageWithReply, SymbianInstallService, "install", data, callBack, cookie);
+}
+
+void tcftrk::TcfTrkDevice::sendSymbianInstallUIInstallCommand(const tcftrk::TcfTrkCallback &callBack,
+ const QByteArray &file,
+ const QVariant &cookie)
+{
+ QByteArray data;
+ JsonInputStream str(data);
+ str << file;
+ sendTcfTrkMessage(MessageWithReply, SymbianInstallService, "installWithUI", data, callBack, cookie);
+}
} // namespace tcftrk
diff --git a/src/shared/symbianutils/tcftrkdevice.h b/src/shared/symbianutils/tcftrkdevice.h
index 8b52b27aa4..778f7ee541 100644
--- a/src/shared/symbianutils/tcftrkdevice.h
+++ b/src/shared/symbianutils/tcftrkdevice.h
@@ -44,6 +44,7 @@
#include <QtCore/QVector>
#include <QtCore/QVariant>
#include <QtCore/QStringList>
+#include <QtCore/QDateTime>
QT_BEGIN_NAMESPACE
class QIODevice;
@@ -83,7 +84,8 @@ struct SYMBIANUTILS_EXPORT TcfTrkCommandError {
/* Answer to a Tcf command passed to the callback. */
struct SYMBIANUTILS_EXPORT TcfTrkCommandResult {
- enum Type {
+ enum Type
+ {
SuccessReply, // 'R' and no error -> all happy.
CommandErrorReply, // 'R' with TcfTrkCommandError received
ProgressReply, // 'P', progress indicator
@@ -100,6 +102,8 @@ struct SYMBIANUTILS_EXPORT TcfTrkCommandResult {
QString errorString() const;
operator bool() const { return type == SuccessReply || type == ProgressReply; }
+ static QDateTime tcfTimeToQDateTime(quint64 tcfTimeMS);
+
Type type;
Services service;
QByteArray request;
@@ -108,6 +112,16 @@ struct SYMBIANUTILS_EXPORT TcfTrkCommandResult {
QVariant cookie;
};
+// Response to stat/fstat
+struct SYMBIANUTILS_EXPORT TcfTrkStatResponse
+{
+ TcfTrkStatResponse();
+
+ quint64 size;
+ QDateTime modTime;
+ QDateTime accessTime;
+};
+
typedef trk::Callback<const TcfTrkCommandResult &> TcfTrkCallback;
/* TcfTrkDevice: TCF communication helper using an asynchronous QIODevice
@@ -122,16 +136,39 @@ http://dev.eclipse.org/svnroot/dsdp/org.eclipse.tm.tcf/trunk/docs/TCF%20Services
* single commands. As soon as 'Registers::getm' is natively supported, all code
* related to 'FakeRegisterGetm' should be removed. The workaround requires that
* the register name is known.
-*/
+ * CODA notes:
+ * - Commands are accepted only after receiving the Locator Hello event
+ * - Serial communication initiation sequence:
+ * Send serial ping from host sendSerialPing() -> receive pong response with
+ * version information -> Send Locator Hello Event -> Receive Locator Hello Event
+ * -> Commands are accepted.
+ * - WLAN communication initiation sequence:
+ * Receive Locator Hello Event from CODA -> Commands are accepted.
+ */
class SYMBIANUTILS_EXPORT TcfTrkDevice : public QObject
{
Q_PROPERTY(unsigned verbose READ verbose WRITE setVerbose)
+ Q_PROPERTY(bool serialFrame READ serialFrame WRITE setSerialFrame)
Q_OBJECT
public:
- enum MessageType { MessageWithReply,
- MessageWithoutReply, /* Non-standard: "Settings:set" command does not reply */
- NoopMessage };
+ // Flags for FileSystem:open
+ enum FileSystemOpenFlags
+ {
+ FileSystem_TCF_O_READ = 0x00000001,
+ FileSystem_TCF_O_WRITE = 0x00000002,
+ FileSystem_TCF_O_APPEND = 0x00000004,
+ FileSystem_TCF_O_CREAT = 0x00000008,
+ FileSystem_TCF_O_TRUNC = 0x00000010,
+ FileSystem_TCF_O_EXCL = 0x00000020
+ };
+
+ enum MessageType
+ {
+ MessageWithReply,
+ MessageWithoutReply, /* Non-standard: "Settings:set" command does not reply */
+ NoopMessage
+ };
typedef QSharedPointer<QIODevice> IODevicePtr;
@@ -139,6 +176,8 @@ public:
virtual ~TcfTrkDevice();
unsigned verbose() const;
+ bool serialFrame() const;
+ void setSerialFrame(bool);
// Mapping of register names to indices for multi-requests.
// Register names can be retrieved via 'Registers:getChildren' (requires
@@ -150,6 +189,9 @@ public:
IODevicePtr takeDevice();
void setDevice(const IODevicePtr &dp);
+ // Serial Only: Initiate communication. Will emit serialPong() signal with version.
+ void sendSerialPing(bool pingOnly = false);
+
// Send with parameters from string (which may contain '\0').
void sendTcfTrkMessage(MessageType mt, Services service,
const char *command,
@@ -274,15 +316,47 @@ public:
const QByteArray &value, // binary value
const QVariant &cookie = QVariant());
+ // File System
+ void sendFileSystemOpenCommand(const TcfTrkCallback &callBack,
+ const QByteArray &name,
+ unsigned flags = FileSystem_TCF_O_READ,
+ const QVariant &cookie = QVariant());
+
+ void sendFileSystemFstatCommand(const TcfTrkCallback &callBack,
+ const QByteArray &handle,
+ const QVariant &cookie = QVariant());
+
+ void sendFileSystemWriteCommand(const TcfTrkCallback &callBack,
+ const QByteArray &handle,
+ const QByteArray &data,
+ unsigned offset = 0,
+ const QVariant &cookie = QVariant());
+
+ void sendFileSystemCloseCommand(const TcfTrkCallback &callBack,
+ const QByteArray &handle,
+ const QVariant &cookie = QVariant());
+
+ // Symbian Install
+ void sendSymbianInstallSilentInstallCommand(const TcfTrkCallback &callBack,
+ const QByteArray &file,
+ const QByteArray &targetDrive,
+ const QVariant &cookie = QVariant());
+
+ void sendSymbianInstallUIInstallCommand(const TcfTrkCallback &callBack,
+ const QByteArray &file,
+ const QVariant &cookie = QVariant());
+
void sendLoggingAddListenerCommand(const TcfTrkCallback &callBack,
const QVariant &cookie = QVariant());
static QByteArray parseMemoryGet(const TcfTrkCommandResult &r);
static QVector<QByteArray> parseRegisterGetChildren(const TcfTrkCommandResult &r);
+ static TcfTrkStatResponse parseStat(const TcfTrkCommandResult &r);
signals:
void genericTcfEvent(int service, const QByteArray &name, const QVector<tcftrk::JsonValue> &value);
void tcfEvent(const tcftrk::TcfTrkEvent &knownEvent);
+ void serialPong(const QString &codaVersion);
void logMessage(const QString &);
void error(const QString &);
@@ -296,11 +370,16 @@ private slots:
void slotDeviceReadyRead();
private:
+ void deviceReadyReadSerial();
+ void deviceReadyReadTcp();
+
bool checkOpen();
void checkSendQueue();
- void writeMessage(QByteArray data);
+ void writeMessage(QByteArray data, bool ensureTerminating0 = true);
void emitLogMessage(const QString &);
- int parseMessage(const QByteArray &);
+ inline int parseMessage(const QByteArray &);
+ void processMessage(const QByteArray &message);
+ inline void processSerialMessage(const QByteArray &message);
int parseTcfCommandReply(char type, const QVector<QByteArray> &tokens);
int parseTcfEvent(const QVector<QByteArray> &tokens);
// Send with parameters from string (which may contain '\0').
diff --git a/src/shared/symbianutils/tcftrkmessage.cpp b/src/shared/symbianutils/tcftrkmessage.cpp
index a817f6018d..05a9cfc727 100644
--- a/src/shared/symbianutils/tcftrkmessage.cpp
+++ b/src/shared/symbianutils/tcftrkmessage.cpp
@@ -40,7 +40,7 @@
// Names matching the enum
static const char *serviceNamesC[] =
{ "Locator", "RunControl", "Processes", "Memory", "Settings", "Breakpoints",
- "Registers", "Logging",
+ "Registers", "Logging", "FileSystem", "SymbianInstall",
"UnknownService"};
namespace tcftrk {
@@ -387,14 +387,20 @@ TcfTrkEvent *TcfTrkEvent::parseEvent(Services s, const QByteArray &nameBA, const
const QByteArray idBA = values.at(0).data();
const quint64 pc = values.at(1).data().toULongLong();
const QByteArray reasonBA = values.at(2).data();
+ QByteArray messageBA;
// Module load: Special
if (reasonBA == sharedLibrarySuspendReasonC) {
ModuleLoadEventInfo info;
if (!info.parse(values.at(3)))
return 0;
return new TcfTrkRunControlModuleLoadContextSuspendedEvent(idBA, reasonBA, pc, info);
+ } else {
+ // hash containing a 'message'-key with a verbose crash message.
+ if (values.at(3).type() == JsonValue::Object && values.at(3).childCount()
+ && values.at(3).children().at(0).type() == JsonValue::String)
+ messageBA = values.at(3).children().at(0).data();
}
- return new TcfTrkRunControlContextSuspendedEvent(idBA, reasonBA, pc);
+ return new TcfTrkRunControlContextSuspendedEvent(idBA, reasonBA, messageBA, pc);
} // "contextSuspended"
if (nameBA == "contextAdded")
return TcfTrkRunControlContextAddedEvent::parseEvent(values);
@@ -509,8 +515,9 @@ QString TcfTrkRunControlContextRemovedEvent::toString() const
// --------------- TcfTrkRunControlContextSuspendedEvent
TcfTrkRunControlContextSuspendedEvent::TcfTrkRunControlContextSuspendedEvent(const QByteArray &id,
const QByteArray &reason,
+ const QByteArray &message,
quint64 pc) :
- TcfTrkIdEvent(RunControlSuspended, id), m_pc(pc), m_reason(reason)
+ TcfTrkIdEvent(RunControlSuspended, id), m_pc(pc), m_reason(reason), m_message(message)
{
}
@@ -528,6 +535,8 @@ void TcfTrkRunControlContextSuspendedEvent::format(QTextStream &str) const
str << "RunControl: '" << idString() << "' suspended at 0x"
<< m_pc << ": '" << m_reason << "'.";
str.setIntegerBase(10);
+ if (!m_message.isEmpty())
+ str << " (" <<m_message << ')';
}
QString TcfTrkRunControlContextSuspendedEvent::toString() const
diff --git a/src/shared/symbianutils/tcftrkmessage.h b/src/shared/symbianutils/tcftrkmessage.h
index f66ab78e13..b91eda015b 100644
--- a/src/shared/symbianutils/tcftrkmessage.h
+++ b/src/shared/symbianutils/tcftrkmessage.h
@@ -57,6 +57,8 @@ enum Services {
BreakpointsService,
RegistersService,
LoggingService, // non-standard, trk specific
+ FileSystemService,
+ SymbianInstallService, // non-standard, trk specific
UnknownService
}; // Note: Check string array 'serviceNamesC' of same size when modifying this.
@@ -266,12 +268,14 @@ public:
explicit TcfTrkRunControlContextSuspendedEvent(const QByteArray &id,
const QByteArray &reason,
+ const QByteArray &message,
quint64 pc = 0);
virtual QString toString() const;
quint64 pc() const { return m_pc; }
QByteArray reasonID() const { return m_reason; }
Reason reason() const;
+ QByteArray message() const { return m_message; }
protected:
explicit TcfTrkRunControlContextSuspendedEvent(Type t,
@@ -283,6 +287,7 @@ protected:
private:
const quint64 m_pc;
const QByteArray m_reason;
+ const QByteArray m_message;
};
// RunControlContextSuspended due to module load
diff --git a/src/shared/symbianutils/trkdevice.cpp b/src/shared/symbianutils/trkdevice.cpp
index 4cc9383887..9f9670db21 100644
--- a/src/shared/symbianutils/trkdevice.cpp
+++ b/src/shared/symbianutils/trkdevice.cpp
@@ -183,7 +183,7 @@ public:
enum WriteResult {
WriteOk,
WriteFailedDiscard, // Discard failed message
- WriteFailedKeep, // Keep failed message
+ WriteFailedKeep // Keep failed message
};
void notifyWriteResult(WriteResult ok);
@@ -1095,7 +1095,7 @@ void TrkDevice::slotMessageReceived(const trk::TrkResult &result, const QByteArr
if (isOpen()) { // Might receive bytes after closing due to queued connections.
d->writerThread->slotHandleResult(result);
if (d->verbose > 1)
- qDebug() << "Received: " << result.toString();
+ qDebug() << "TRK DEVICE Received: " << result.toString();
emit messageReceived(result);
if (!rawData.isEmpty())
emit rawDataReceived(rawData);
diff --git a/src/shared/symbianutils/trkutils.h b/src/shared/symbianutils/trkutils.h
index 566ea20252..144ee0c485 100644
--- a/src/shared/symbianutils/trkutils.h
+++ b/src/shared/symbianutils/trkutils.h
@@ -137,7 +137,7 @@ enum DSOSItemTypes {
kDSOSProcAttachItem = 0x0005,
kDSOSThreadAttachItem = 0x0006,
kDSOSProcAttach2Item = 0x0007,
- kDSOSProcRunItem = 0x0008,
+ kDSOSProcRunItem = 0x0008
/* 0x0009 - 0x00ff reserved for general expansion */
/* 0x0100 - 0xffff available for target-specific use */
};
@@ -162,7 +162,7 @@ enum Endianness
{
LittleEndian,
BigEndian,
- TargetByteOrder = BigEndian,
+ TargetByteOrder = BigEndian
};
SYMBIANUTILS_EXPORT void appendShort(QByteArray *ba, ushort s, Endianness = TargetByteOrder);
diff --git a/src/tools/qml/qmldom/main.cpp b/src/tools/qml/qmldom/main.cpp
deleted file mode 100644
index 02a3924ef1..0000000000
--- a/src/tools/qml/qmldom/main.cpp
+++ /dev/null
@@ -1,177 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#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/qml/qmldom/qmldom.pro b/src/tools/qml/qmldom/qmldom.pro
deleted file mode 100644
index 47b5aa44f2..0000000000
--- a/src/tools/qml/qmldom/qmldom.pro
+++ /dev/null
@@ -1,21 +0,0 @@
-#-------------------------------------------------
-#
-# 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/qml/qmlmetatype/main.cpp b/src/tools/qml/qmlmetatype/main.cpp
deleted file mode 100644
index b6bf7ccbab..0000000000
--- a/src/tools/qml/qmlmetatype/main.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-#include <QtCore/QCoreApplication>
-#include <QtCore/QDebug>
-#include <QtCore/QMetaObject>
-#include <QtCore/QMetaProperty>
-#include <QtDeclarative/QmlMetaType>
-
- void messageOutput(QtMsgType type, const char *msg)
- {
- switch (type) {
- case QtDebugMsg:
- fprintf(stdout, "%s\n", 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 dumpProperty(QMetaProperty qProperty)
-{
- qDebug() << "\t\t" << qProperty.name() << "\t\t"
- << qProperty.typeName()
- << "readable=" << qProperty.isReadable()
- << "writable=" << qProperty.isWritable()
- << "resettable=" << qProperty.isResettable();
-}
-
-void dumpType(QmlType *type)
-{
- qDebug() << "Type:" << type->qmlTypeName() << type->majorVersion() << type->minorVersion() << "(C++: " << type->typeName() << ")";
-
- const QMetaObject *qMetaObject = type->metaObject();
- if (!qMetaObject) {
- qDebug() << "\tNo metaObject! Skipping ...";
- return;
- }
-
- qDebug() << "\tProperties (default property :" << QmlMetaType::defaultProperty(qMetaObject).typeName() << ")";
- for (int i = 0; i < qMetaObject->propertyCount(); ++i) {
- dumpProperty(qMetaObject->property(i));
- }
-
- qDebug() << "\tSuper Classes:";
- if (qMetaObject->superClass()) {
- if (QmlType *qmlParentType = QmlMetaType::qmlType(qMetaObject->superClass())) {
- if (!qmlParentType->qmlTypeName().isEmpty()) {
- qDebug() << "\t\t" << qmlParentType->qmlTypeName();
- } else {
- qDebug() << "\t\t" << "(no Qml Type name)" << qmlParentType->typeName();
- }
- } else {
- const QString parentClass = qMetaObject->superClass()->className();
- qDebug() << "\t\t" << "(no Qml Type)" << parentClass;
- }
- } else {
- qDebug() << "\t\t" << "no superclass";
- }
-}
-
-int main(int argc, char **argv)
-{
- QCoreApplication app(argc, argv);
-
- qInstallMsgHandler(messageOutput);
-
- qDebug() << "Registered qml meta types:\n\n";
- foreach (const QByteArray &typeName, QmlMetaType::qmlTypeNames()) {
- if (typeName.isEmpty()) {
- qDebug() << "Empty type name!!! Skipping ...";
- continue;
- }
- QmlType *qmlType = QmlMetaType::qmlType(typeName, 4, 6);
- Q_ASSERT(qmlType);
- dumpType(qmlType);
- }
- return 0;
-}
diff --git a/src/tools/qml/qmlmetatype/qmlmetatype.pro b/src/tools/qml/qmlmetatype/qmlmetatype.pro
deleted file mode 100644
index da49ff07fb..0000000000
--- a/src/tools/qml/qmlmetatype/qmlmetatype.pro
+++ /dev/null
@@ -1,17 +0,0 @@
-#-------------------------------------------------
-#
-# Project created by QtCreator 2009-04-09T15:54:21
-#
-#-------------------------------------------------
-
-QT -= gui
-QT += declarative
-
-TARGET = qmlmetatype
-CONFIG += console
-CONFIG -= app_bundle
-
-TEMPLATE = app
-
-
-SOURCES += main.cpp
diff --git a/src/tools/qmlpuppet/main.cpp b/src/tools/qmlpuppet/main.cpp
new file mode 100644
index 0000000000..b483d948e0
--- /dev/null
+++ b/src/tools/qmlpuppet/main.cpp
@@ -0,0 +1,51 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 <QApplication>
+#include <QStringList>
+
+#include <nodeinstanceclientproxy.h>
+
+int main(int argc, char *argv[])
+{
+ QApplication application(argc, argv);
+
+ if (application.arguments().count() != 2)
+ return -1;
+
+ QCoreApplication::setOrganizationName("Nokia");
+ QCoreApplication::setOrganizationDomain("nokia.com");
+ QCoreApplication::setApplicationName("QmlPuppet");
+
+ new QmlDesigner::NodeInstanceClientProxy(&application);
+
+ return application.exec();
+}
diff --git a/src/tools/qmlpuppet/qmlpuppet.pro b/src/tools/qmlpuppet/qmlpuppet.pro
new file mode 100644
index 0000000000..a5ce001a42
--- /dev/null
+++ b/src/tools/qmlpuppet/qmlpuppet.pro
@@ -0,0 +1,19 @@
+TARGET = qmlpuppet
+
+TEMPLATE = app
+
+QT += core gui declarative network webkit
+
+DEFINES += QWEAKPOINTER_ENABLE_ARROW
+
+include(../../../qtcreator.pri)
+include(../../private_headers.pri)
+DESTDIR = $$IDE_BIN_PATH
+include(../../rpath.pri)
+
+include (../../plugins/qmldesigner/designercore/instances/instances.pri)
+include (../../plugins/qmldesigner/designercore/exceptions/exceptions.pri)
+
+CONFIG -= app_bundle
+
+SOURCES += main.cpp
diff --git a/src/tools/qtpromaker/main.cpp b/src/tools/qtpromaker/main.cpp
new file mode 100644
index 0000000000..a4851218a7
--- /dev/null
+++ b/src/tools/qtpromaker/main.cpp
@@ -0,0 +1,396 @@
+
+#include <QCoreApplication>
+#include <QDebug>
+#include <QDir>
+#include <QDirIterator>
+#include <QFile>
+#include <QSet>
+#include <QMap>
+#include <QProcess>
+#include <QTextStream>
+#include <QVector>
+
+//
+// Command line options
+//
+
+// Put everything into a single project.
+static int targetDepth = 0;
+static bool forceOverWrite = false;
+static QString subProjectSeparator = "_";
+
+// FIXME: Make file classes configurable on the command line.
+static const char *defaultExtensions[] =
+{
+ "SOURCES", "cpp,c,C,cxx,c++",
+ "HEADERS", "hpp,h,H,hxx,h++",
+ "TRANSLATIONS", "ts",
+ "FORMS", "ui",
+};
+
+typedef QHash<QByteArray, QByteArray> Extensions;
+
+static QByteArray proExtension = "pro";
+
+
+class FileClass
+{
+public:
+ FileClass() {}
+
+ //! suffixes is a comma separated string of extensions.
+ FileClass(const QByteArray &suffixes, const QString &varName)
+ : m_suffixes(',' + suffixes + ','), m_varName(varName)
+ {}
+
+ static QByteArray prepareSuffix(const QByteArray &suffix)
+ {
+ return ',' + suffix + ',';
+ }
+
+ bool canHandle(const QByteArray &preparedSuffix) const
+ {
+ return m_suffixes.contains(preparedSuffix);
+ }
+
+ void addFile(const QFileInfo &fi)
+ {
+ m_files.insert(fi.filePath(), Dummy());
+ }
+
+ bool handleFile(const QFileInfo &fi, const QByteArray &preparedSuffix)
+ {
+ if (!canHandle(preparedSuffix))
+ return false;
+ addFile(fi);
+ return true;
+ }
+
+ void writeProBlock(QTextStream &ts) const
+ {
+ if (m_files.isEmpty())
+ return;
+ ts << '\n' << m_varName << " *=";
+ Files::ConstIterator it = m_files.begin();
+ Files::ConstIterator end = m_files.end();
+ for ( ; it != end; ++it)
+ ts << " \\\n " << it.key();
+ ts << "\n";
+ }
+
+private:
+ struct Dummy {};
+ typedef QMap<QString, Dummy> Files;
+
+ QByteArray m_suffixes;
+ QString m_varName;
+ Files m_files;
+};
+
+class ProMaker;
+
+class Project
+{
+ friend class ProMaker;
+ explicit Project(ProMaker *master)
+ : m_master(master)
+ {}
+
+public:
+ void setTreeLevel(int level) { m_treeLevel = level; }
+ int treeLevel() const { return m_treeLevel; }
+ void setPaths(const QStringList &paths);
+ void setOutputFileName(const QString &fileName) { m_outputFileName = fileName; }
+ void writeProFile();
+ void createFileLists();
+ void setExtensions(const Extensions &extensions);
+ Extensions extensions() const { return m_extensions; }
+
+private:
+ void handleItem(const QString &item);
+ void handleDir(const QString &item);
+ void handleBinary(const QString &item);
+
+ ProMaker *m_master;
+ QStringList m_items;
+ QVector<FileClass> m_fileClasses;
+ Extensions m_extensions;
+ QString m_outputFileName;
+ QStringList m_subdirs;
+ int m_treeLevel;
+};
+
+class ProMaker
+{
+public:
+ ProMaker() {}
+ ~ProMaker() { qDeleteAll(m_projects); }
+ Project *addEmptyProject();
+ void createContents();
+ void writeOutput();
+
+private:
+ QVector<Project *> m_projects;
+};
+
+void Project::setPaths(const QStringList &paths)
+{
+ foreach (const QString &path, paths)
+ m_items.append(path);
+}
+
+void Project::setExtensions(const Extensions &extensions)
+{
+ m_fileClasses.clear();
+ m_extensions = extensions;
+ Extensions::ConstIterator it = extensions.begin();
+ for ( ; it != extensions.end(); ++it)
+ m_fileClasses.append(FileClass(it.value(), it.key()));
+}
+
+void Project::createFileLists()
+{
+ for (int i = 0; i != m_items.size(); ++i)
+ handleItem(m_items.at(i));
+}
+
+void Project::handleItem(const QString &item)
+{
+ QFileInfo fi(item);
+ if (fi.isDir())
+ handleDir(item);
+ else
+ handleBinary(item);
+}
+
+void Project::handleBinary(const QString &item)
+{
+ QStringList args;
+ args.append("--batch-silent");
+ args.append("--nx");
+ args.append("--quiet");
+ args.append("-i");
+ args.append("mi");
+ args.append("--se=" + item);
+ args.append("-ex");
+ args.append("interpreter-exec mi -file-list-exec-source-files");
+ args.append("-ex");
+ args.append("quit");
+ QProcess proc;
+ proc.start("gdb", args);
+ if (!proc.waitForStarted()) {
+ qDebug() << "COULD NOT START";
+ return;
+ }
+ if (!proc.waitForFinished()) {
+ qDebug() << "COULD NOT FINISH";
+ return;
+ }
+ QByteArray ba = proc.readAllStandardOutput();
+ if (ba.isEmpty()) {
+ qDebug() << "NO OUTPUT";
+ return;
+ }
+ QString input = QString::fromLatin1(ba, ba.size());
+ // ^done,files=[{file="<<C++-namespaces>>",{file=...,fullname=}
+ // "}] (gdb)
+ int first = input.indexOf('{');
+ input = input.mid(first, input.lastIndexOf('}') - first);
+ foreach (QString item, input.split("},{")) {
+ //qDebug() << "ITEM: " << item;
+ int full = item.indexOf(",fullname=\"");
+ if (full != -1)
+ item = item.mid(full + 11);
+ else
+ item = item.mid(6);
+ item.chop(1);
+ //qDebug() << "ITEM: " << item;
+ QFileInfo fi(item);
+ const QByteArray ext = FileClass::prepareSuffix(fi.suffix().toUtf8());
+ for (int i = m_fileClasses.size(); --i >= 0; ) {
+ if (m_fileClasses[i].handleFile(fi, ext))
+ break;
+ }
+ }
+}
+
+void Project::handleDir(const QString &item)
+{
+ QDirIterator it(item);
+ while (it.hasNext()) {
+ it.next();
+ const QFileInfo fi = it.fileInfo();
+ if (fi.isDir()) {
+ if (fi.fileName() == ".." || fi.fileName() == ".")
+ continue;
+ const QString filePath = fi.filePath();
+ if (m_treeLevel < targetDepth) {
+ QString subName = m_outputFileName;
+ subName.insert(subName.size() - 1 - proExtension.size(),
+ subProjectSeparator + fi.fileName());
+ Project *child = m_master->addEmptyProject();
+ child->setTreeLevel(treeLevel() + 1);
+ child->setPaths(QStringList(filePath));
+ child->setOutputFileName(subName);
+ child->setExtensions(extensions());
+ m_subdirs.append(subName);
+ } else {
+ m_items.append(fi.filePath());
+ }
+ } else {
+ const QByteArray ext = FileClass::prepareSuffix(fi.suffix().toUtf8());
+ for (int i = m_fileClasses.size(); --i >= 0; ) {
+ if (m_fileClasses[i].handleFile(fi, ext))
+ break;
+ }
+ }
+ }
+}
+
+void Project::writeProFile()
+{
+ QFile file(m_outputFileName);
+ if (file.exists()) {
+ if (!forceOverWrite) {
+ qWarning("%s", qPrintable(QString(
+ "%1 not overwritten. Use -f if this should be done.")
+ .arg(m_outputFileName)));
+ return;
+ }
+ if (!file.remove()) {
+ qWarning("%s", qPrintable(QString(
+ "%1 could not be deleted.").arg(m_outputFileName)));
+ return;
+ }
+ }
+
+ if (!file.open(QIODevice::WriteOnly)) {
+ qWarning("%s", qPrintable(QString(
+ "%1 cannot be written").arg(m_outputFileName)));
+ return;
+ }
+
+
+ QTextStream ts(&file);
+ ts << "#####################################################################\n";
+ ts << "# Automatically generated by qtpromaker\n";
+ ts << "#####################################################################\n\n";
+
+ if (m_subdirs.isEmpty()) {
+ ts << "TEMPLATE = app\n";
+ ts << "TARGET = " << QFileInfo(m_outputFileName).baseName() << "\n";
+ foreach (const FileClass &fc, m_fileClasses)
+ fc.writeProBlock(ts);
+ ts << "\nPATHS *=";
+ foreach (const QDir &dir, m_items)
+ ts << " \\\n " << dir.path();
+ ts << "\n\nDEPENDPATH *= $$PATHS\n";
+ ts << "\nINCLUDEPATH *= $$PATHS\n";
+ } else {
+ ts << "TEMPLATE = subdirs\n";
+ ts << "SUBDIRS = ";
+ foreach (const QString &subdir, m_subdirs)
+ ts << " \\\n " << subdir;
+ ts << "\n";
+ }
+}
+
+void ProMaker::createContents()
+{
+ for (int i = 0; i != m_projects.size(); ++i)
+ m_projects[i]->createFileLists();
+}
+
+void ProMaker::writeOutput()
+{
+ for (int i = 0; i != m_projects.size(); ++i)
+ m_projects.at(i)->writeProFile();
+}
+
+Project *ProMaker::addEmptyProject()
+{
+ Project *project = new Project(this);
+ m_projects.append(project);
+ return project;
+}
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication app(argc, argv);
+ QStringList args = app.arguments();
+
+ // Set up default values.
+ QStringList paths;
+ Extensions extensions;
+ int extensionsCount = sizeof(defaultExtensions)/sizeof(defaultExtensions[0]);
+ for (int i = 0; i < extensionsCount; i += 2)
+ extensions[defaultExtensions[i]] = defaultExtensions[i + 1];
+
+ QString outputFileName;
+
+ // Override by command line.
+ for (int i = 1, n = args.size(); i < n; ++i) {
+ const QString arg = args.at(i);
+ if (arg == "-h" || arg == "--help" || arg == "-help") {
+ qWarning() << "Usage: " << qPrintable(args.at(0))
+ << " [-f] [-o out.pro] [dir...]"
+ << "\n\n"
+ << "Argumnents:\n"
+ << " -f, --force overwrite existing files\n"
+ << " -d, --depth <n> recursion depth for sub-projects\n"
+ << " -s, --separator <char> separator for sub-project names\n"
+ << " -o, --output <file> output to <file>\n"
+ << " -h, --help print this help\n";
+ return 1;
+ }
+
+ bool handled = true;
+ if (arg == "-f" || arg == "--force" || arg == "-force") {
+ forceOverWrite = true;
+ } else if (i < n - 1) {
+ if (arg == "-o" || arg == "--output" || arg == "-output")
+ outputFileName = args.at(++i);
+ else if (arg == "-d" || arg == "--depth" || arg == "-depth")
+ targetDepth = args.at(++i).toInt();
+ else if (arg == "-s" || arg == "--separator" || arg == "-separator")
+ subProjectSeparator = args.at(++i);
+ else
+ handled = false;
+ }
+
+ // Nothing know. Treat it as path.
+ if (!handled)
+ paths.append(args.at(i));
+ }
+
+
+ // Fallbacks.
+ if (paths.isEmpty()) {
+ QDir dir = QDir::currentPath();
+ outputFileName = dir.dirName() + '.' + proExtension;
+ paths.append(".");
+ }
+
+ if (outputFileName.isEmpty()) {
+ outputFileName = QDir(paths.at(0)).dirName() + '.' + proExtension;
+ }
+
+ if (targetDepth == -1)
+ targetDepth = 1000000; // "infinity"
+
+ //qDebug() << "DEPTH: " << targetDepth;
+ //qDebug() << "SEPARATOR: " << subProjectSeparator;
+
+ // Run the thing.
+ ProMaker pm;
+
+ Project *p = pm.addEmptyProject();
+ p->setExtensions(extensions);
+ p->setPaths(paths);
+ p->setOutputFileName(outputFileName);
+
+ pm.createContents();
+ pm.writeOutput();
+
+ return 0;
+}
diff --git a/src/tools/qtpromaker/qtpromaker.pro b/src/tools/qtpromaker/qtpromaker.pro
new file mode 100644
index 0000000000..9a92bd5b82
--- /dev/null
+++ b/src/tools/qtpromaker/qtpromaker.pro
@@ -0,0 +1,15 @@
+include(../../../qtcreator.pri)
+
+TEMPLATE = app
+TARGET = qtpromaker
+DESTDIR = $$IDE_LIBEXEC_PATH
+
+QT -= gui
+
+CONFIG += console warn_on
+CONFIG -= app_bundle
+
+SOURCES += main.cpp
+
+target.path = /bin # FIXME: libexec, more or less
+INSTALLS += target
diff --git a/src/tools/tools.pro b/src/tools/tools.pro
index 37d02cd708..204f0b6930 100644
--- a/src/tools/tools.pro
+++ b/src/tools/tools.pro
@@ -1,7 +1,17 @@
TEMPLATE = subdirs
+
win32:SUBDIRS = qtcdebugger
+SUBDIRS += qtpromaker
QT_BREAKPAD_ROOT_PATH = $$(QT_BREAKPAD_ROOT_PATH)
!isEmpty(QT_BREAKPAD_ROOT_PATH) {
SUBDIRS += qtcrashhandler
}
+
+include(../../qtcreator.pri)
+include(../private_headers.pri)
+exists($${QT_PRIVATE_HEADERS}/QtDeclarative/private/qdeclarativecontext_p.h) {
+ minQtVersion(4, 7, 1) {
+ SUBDIRS += qmlpuppet
+ }
+}
diff --git a/tests/auto/aggregation/aggregation.pro b/tests/auto/aggregation/aggregation.pro
index ae45e5f9d6..be0c499302 100644
--- a/tests/auto/aggregation/aggregation.pro
+++ b/tests/auto/aggregation/aggregation.pro
@@ -1,6 +1,4 @@
-CONFIG += qtestlib testcase
-TEMPLATE = app
-CONFIG -= app_bundle
+include(../qttest.pri)
DEFINES += AGGREGATION_LIBRARY
AGGREGATION_PATH = ../../../src/libs/aggregation
@@ -11,5 +9,3 @@ SOURCES += tst_aggregate.cpp \
$$AGGREGATION_PATH/aggregate.cpp
HEADERS += $$AGGREGATION_PATH/aggregate.h \
$$AGGREGATION_PATH/aggregation_global.h
-
-TARGET=tst_$$TARGET
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro
index 13a921daaf..92fe3c51f1 100644
--- a/tests/auto/auto.pro
+++ b/tests/auto/auto.pro
@@ -5,14 +5,17 @@ SUBDIRS += \
changeset \
cplusplus \
debugger \
+ extensionsystem \
+ environment \
fakevim \
generichighlighter \
# icheckbuild \
-# profilereader \
# profilewriter \
- qml \
- utils_stringutils
+ ioutils \
+ qtcprocess \
+ utils_stringutils \
+ filesearch
-contains (QT_CONFIG, declarative) {
-SUBDIRS += qml
-}
+#contains (QT_CONFIG, declarative) {
+#SUBDIRS += qml
+#}
diff --git a/tests/auto/changeset/changeset.pro b/tests/auto/changeset/changeset.pro
index 0d2522e880..73ca8da423 100644
--- a/tests/auto/changeset/changeset.pro
+++ b/tests/auto/changeset/changeset.pro
@@ -1,4 +1,4 @@
-CONFIG += qtestlib testcase
+include(../qttest.pri)
# Defines import symbol as empty
DEFINES+=QTCREATOR_UTILS_STATIC_LIB
@@ -13,5 +13,3 @@ HEADERS += \
$$UTILSDIR/utils/changeset.h
INCLUDEPATH += $$UTILSDIR
-
-TARGET=tst_$$TARGET
diff --git a/tests/auto/cplusplus/ast/ast.pro b/tests/auto/cplusplus/ast/ast.pro
index 13f11c7e2e..48658149b5 100644
--- a/tests/auto/cplusplus/ast/ast.pro
+++ b/tests/auto/cplusplus/ast/ast.pro
@@ -1,7 +1,4 @@
-TEMPLATE = app
-CONFIG += qt warn_on console depend_includepath
-CONFIG += qtestlib testcase
+include(../../qttest.pri)
include(../shared/shared.pri)
SOURCES += tst_ast.cpp
-TARGET=tst_$$TARGET
diff --git a/tests/auto/cplusplus/codeformatter/codeformatter.pro b/tests/auto/cplusplus/codeformatter/codeformatter.pro
index 6aa0259f58..e97b551231 100644
--- a/tests/auto/cplusplus/codeformatter/codeformatter.pro
+++ b/tests/auto/cplusplus/codeformatter/codeformatter.pro
@@ -1,20 +1,8 @@
-TEMPLATE = app
-CONFIG += qt warn_on console depend_includepath
-CONFIG += qtestlib testcase
-
+include(../../qttest.pri)
include(../shared/shared.pri)
SRCDIR = ../../../../src
-SOURCES += \
- tst_codeformatter.cpp \
- $$SRCDIR/plugins/cpptools/cppcodeformatter.cpp \
- $$SRCDIR/plugins/texteditor/basetextdocumentlayout.cpp
-
-HEADERS += \
- $$SRCDIR/plugins/cpptools/cppcodeformatter.h \
- $$SRCDIR/plugins/texteditor/basetextdocumentlayout.h
+SOURCES += tst_codeformatter.cpp
INCLUDEPATH += $$SRCDIR/plugins $$SRCDIR/libs
-
-TARGET=tst_$$TARGET
diff --git a/tests/auto/cplusplus/codeformatter/tst_codeformatter.cpp b/tests/auto/cplusplus/codeformatter/tst_codeformatter.cpp
index b319327ce5..3122b5d22c 100644
--- a/tests/auto/cplusplus/codeformatter/tst_codeformatter.cpp
+++ b/tests/auto/cplusplus/codeformatter/tst_codeformatter.cpp
@@ -33,6 +33,7 @@ private Q_SLOTS:
void classAccess();
void ternary();
void objcAtDeclarations();
+ void objcCall();
void objcCallAndFor();
void braceList();
void bug1();
@@ -53,6 +54,10 @@ private Q_SLOTS:
void macrosNoSemicolon2();
void renamedNamespace();
void cpp0xFor();
+ void gnuStyleSwitch();
+ void whitesmithsStyleSwitch();
+ void indentToNextToken();
+ void labels();
};
struct Line {
@@ -669,6 +674,20 @@ void tst_CodeFormatter::objcAtDeclarations()
checkIndent(data);
}
+void tst_CodeFormatter::objcCall()
+{
+ QList<Line> data;
+ data << Line("void foo() {")
+ << Line(" [NSApp windows];")
+ << Line(" [NSObject class];")
+ << Line(" if (a)")
+ << Line(" int a = [window drawers];")
+ << Line("}")
+ << Line("int y;")
+ ;
+ checkIndent(data);
+}
+
void tst_CodeFormatter::objcCallAndFor()
{
QList<Line> data;
@@ -805,6 +824,9 @@ void tst_CodeFormatter::gnuStyle()
<< Line(" if (b) {")
<< Line(" fpp;")
<< Line(" }")
+ << Line(" {")
+ << Line(" foo;")
+ << Line(" }")
<< Line(" }")
<< Line("};")
;
@@ -825,6 +847,9 @@ void tst_CodeFormatter::whitesmithsStyle()
<< Line(" if (b) {")
<< Line(" fpp;")
<< Line(" }")
+ << Line(" {")
+ << Line(" foo;")
+ << Line(" }")
<< Line(" }")
<< Line(" };")
;
@@ -1019,6 +1044,94 @@ void tst_CodeFormatter::cpp0xFor()
checkIndent(data);
}
+void tst_CodeFormatter::gnuStyleSwitch()
+{
+ QList<Line> data;
+ data << Line("void foo()")
+ << Line("{")
+ << Line(" switch (a)")
+ << Line(" {")
+ << Line(" case 1:")
+ << Line(" foo;")
+ << Line(" break;")
+ << Line(" case 2: {")
+ << Line(" bar;")
+ << Line(" continue;")
+ << Line(" }")
+ << Line(" case 3:")
+ << Line(" {")
+ << Line(" bar;")
+ << Line(" continue;")
+ << Line(" }")
+ << Line(" case 4:")
+ << Line(" case 5:")
+ << Line(" ;")
+ << Line(" }")
+ << Line("}")
+ ;
+ checkIndent(data, 1);
+}
+
+void tst_CodeFormatter::whitesmithsStyleSwitch()
+{
+ QList<Line> data;
+ data << Line("void foo()")
+ << Line(" {")
+ << Line(" switch (a)")
+ << Line(" {")
+ << Line(" case 1:")
+ << Line(" foo;")
+ << Line(" break;")
+ << Line(" case 2: {")
+ << Line(" bar;")
+ << Line(" continue;")
+ << Line(" }")
+ << Line(" case 3:")
+ << Line(" {")
+ << Line(" bar;")
+ << Line(" continue;")
+ << Line(" }")
+ << Line(" case 4:")
+ << Line(" case 5:")
+ << Line(" ;")
+ << Line(" }")
+ << Line(" }")
+ ;
+ checkIndent(data, 2);
+}
+
+void tst_CodeFormatter::indentToNextToken()
+{
+ QList<Line> data;
+ data << Line("void foo( int i,")
+ << Line("~ int j) {")
+ << Line(" a << foo + ")
+ << Line(" ~ bar;")
+ << Line(" if (a &&")
+ << Line(" ~ b) {")
+ << Line(" foo; }")
+ << Line(" if ( a &&")
+ << Line(" ~ b) {")
+ << Line(" foo; }")
+ ;
+ checkIndent(data);
+}
+
+void tst_CodeFormatter::labels()
+{
+ QList<Line> data;
+ data << Line("void foo() {")
+ << Line("lab:")
+ << Line(" int abc;")
+ << Line("def:")
+ << Line(" if (a)")
+ << Line("boo:")
+ << Line(" foo;")
+ << Line(" int j;")
+ ;
+ checkIndent(data);
+}
+
QTEST_APPLESS_MAIN(tst_CodeFormatter)
#include "tst_codeformatter.moc"
diff --git a/tests/auto/cplusplus/codegen/codegen.pro b/tests/auto/cplusplus/codegen/codegen.pro
index fa736489c7..6a56ec42d5 100644
--- a/tests/auto/cplusplus/codegen/codegen.pro
+++ b/tests/auto/cplusplus/codegen/codegen.pro
@@ -1,7 +1,5 @@
-TEMPLATE = app
-CONFIG += qt warn_on console depend_includepath
-CONFIG += qtestlib testcase
-CONFIG -= app_bundle
+include(../../qttest.pri)
include(../shared/shared.pri)
+INCLUDEPATH += $$IDE_SOURCE_TREE/src/plugins
SOURCES += tst_codegen.cpp
-TARGET=tst_$$TARGET
+
diff --git a/tests/auto/cplusplus/codegen/tst_codegen.cpp b/tests/auto/cplusplus/codegen/tst_codegen.cpp
index 336cf78062..4f2b745d07 100644
--- a/tests/auto/cplusplus/codegen/tst_codegen.cpp
+++ b/tests/auto/cplusplus/codegen/tst_codegen.cpp
@@ -2,12 +2,15 @@
#include <Control.h>
#include <CppDocument.h>
#include <DiagnosticClient.h>
-#include <InsertionPointLocator.h>
#include <Scope.h>
#include <TranslationUnit.h>
#include <Literals.h>
#include <Bind.h>
#include <Symbols.h>
+#include <cpptools/insertionpointlocator.h>
+#include <cpptools/cpprefactoringchanges.h>
+#include <cpptools/cpptoolsplugin.h>
+#include <extensionsystem/pluginmanager.h>
#include <QtTest>
#include <QtDebug>
@@ -20,12 +23,15 @@
tests the InsertionPointLocator.
*/
using namespace CPlusPlus;
+using namespace CppTools;
class tst_Codegen: public QObject
{
Q_OBJECT
private slots:
+ void initTestCase();
+ void cleanupTestCase();
void public_in_empty_class();
void public_in_nonempty_class();
void public_before_protected();
@@ -33,8 +39,26 @@ private slots:
void protected_in_nonempty_class();
void protected_betwee_public_and_private();
void qtdesigner_integration();
+private:
+ ExtensionSystem::PluginManager *pluginManager;
};
+void tst_Codegen::initTestCase()
+{
+ pluginManager = new ExtensionSystem::PluginManager;
+ QSettings *settings = new QSettings(QSettings::IniFormat, QSettings::UserScope,
+ QLatin1String("Nokia"), QLatin1String("QtCreator"));
+ pluginManager->setSettings(settings);
+ pluginManager->setFileExtension(QLatin1String("pluginspec"));
+ pluginManager->setPluginPaths(QStringList() << QLatin1String(Q_PLUGIN_PATH));
+ pluginManager->loadPlugins();
+}
+
+void tst_Codegen::cleanupTestCase()
+{
+ pluginManager->shutdown();
+ delete pluginManager;
+}
/*!
Should insert at line 3, column 1, with "public:\n" as prefix and without suffix.
*/
@@ -61,7 +85,8 @@ void tst_Codegen::public_in_empty_class()
Snapshot snapshot;
snapshot.insert(doc);
- InsertionPointLocator find(snapshot);
+ CppRefactoringChanges changes(snapshot);
+ InsertionPointLocator find(&changes);
InsertionLocation loc = find.methodDeclarationInClass(
doc->fileName(),
foo,
@@ -100,7 +125,8 @@ void tst_Codegen::public_in_nonempty_class()
Snapshot snapshot;
snapshot.insert(doc);
- InsertionPointLocator find(snapshot);
+ CppRefactoringChanges changes(snapshot);
+ InsertionPointLocator find(&changes);
InsertionLocation loc = find.methodDeclarationInClass(
doc->fileName(),
foo,
@@ -139,7 +165,8 @@ void tst_Codegen::public_before_protected()
Snapshot snapshot;
snapshot.insert(doc);
- InsertionPointLocator find(snapshot);
+ CppRefactoringChanges changes(snapshot);
+ InsertionPointLocator find(&changes);
InsertionLocation loc = find.methodDeclarationInClass(
doc->fileName(),
foo,
@@ -179,7 +206,8 @@ void tst_Codegen::private_after_protected()
Snapshot snapshot;
snapshot.insert(doc);
- InsertionPointLocator find(snapshot);
+ CppRefactoringChanges changes(snapshot);
+ InsertionPointLocator find(&changes);
InsertionLocation loc = find.methodDeclarationInClass(
doc->fileName(),
foo,
@@ -219,7 +247,8 @@ void tst_Codegen::protected_in_nonempty_class()
Snapshot snapshot;
snapshot.insert(doc);
- InsertionPointLocator find(snapshot);
+ CppRefactoringChanges changes(snapshot);
+ InsertionPointLocator find(&changes);
InsertionLocation loc = find.methodDeclarationInClass(
doc->fileName(),
foo,
@@ -259,7 +288,8 @@ void tst_Codegen::protected_betwee_public_and_private()
Snapshot snapshot;
snapshot.insert(doc);
- InsertionPointLocator find(snapshot);
+ CppRefactoringChanges changes(snapshot);
+ InsertionPointLocator find(&changes);
InsertionLocation loc = find.methodDeclarationInClass(
doc->fileName(),
foo,
@@ -319,7 +349,8 @@ void tst_Codegen::qtdesigner_integration()
Snapshot snapshot;
snapshot.insert(doc);
- InsertionPointLocator find(snapshot);
+ CppRefactoringChanges changes(snapshot);
+ InsertionPointLocator find(&changes);
InsertionLocation loc = find.methodDeclarationInClass(
doc->fileName(),
foo,
@@ -331,5 +362,5 @@ void tst_Codegen::qtdesigner_integration()
QCOMPARE(loc.column(), 1U);
}
-QTEST_APPLESS_MAIN(tst_Codegen)
+QTEST_MAIN(tst_Codegen)
#include "tst_codegen.moc"
diff --git a/tests/auto/cplusplus/cplusplus.pro b/tests/auto/cplusplus/cplusplus.pro
index 5e22168423..0c16c67028 100644
--- a/tests/auto/cplusplus/cplusplus.pro
+++ b/tests/auto/cplusplus/cplusplus.pro
@@ -9,4 +9,6 @@ SUBDIRS = \
lookup \
preprocessor \
semantic \
- typeprettyprinter
+ typeprettyprinter \
+ simplifytypes
+
diff --git a/tests/auto/cplusplus/findusages/findusages.pro b/tests/auto/cplusplus/findusages/findusages.pro
index c617661788..2643b84880 100644
--- a/tests/auto/cplusplus/findusages/findusages.pro
+++ b/tests/auto/cplusplus/findusages/findusages.pro
@@ -1,6 +1,3 @@
-TEMPLATE = app
-CONFIG += qt warn_on console depend_includepath
-CONFIG += qtestlib testcase
+include(../../qttest.pri)
include(../shared/shared.pri)
SOURCES += tst_findusages.cpp
-TARGET=tst_$$TARGET
diff --git a/tests/auto/cplusplus/lookup/lookup.pro b/tests/auto/cplusplus/lookup/lookup.pro
index 60aadad47e..d1eb14c6e6 100644
--- a/tests/auto/cplusplus/lookup/lookup.pro
+++ b/tests/auto/cplusplus/lookup/lookup.pro
@@ -1,6 +1,3 @@
-TEMPLATE = app
-CONFIG += qt warn_on console depend_includepath
-CONFIG += qtestlib testcase
+include(../../qttest.pri)
include(../shared/shared.pri)
SOURCES += tst_lookup.cpp
-TARGET=tst_$$TARGET
diff --git a/tests/auto/cplusplus/preprocessor/preprocessor.pro b/tests/auto/cplusplus/preprocessor/preprocessor.pro
index f471b51104..564c5b67ca 100644
--- a/tests/auto/cplusplus/preprocessor/preprocessor.pro
+++ b/tests/auto/cplusplus/preprocessor/preprocessor.pro
@@ -1,5 +1,3 @@
-TEMPLATE = app
-CONFIG += qt warn_on console depend_includepath
-CONFIG += qtestlib testcase
+include(../../qttest.pri)
include(../shared/shared.pri)
SOURCES += tst_preprocessor.cpp
diff --git a/tests/auto/cplusplus/semantic/semantic.pro b/tests/auto/cplusplus/semantic/semantic.pro
index 23a18cf37b..35f944950e 100644
--- a/tests/auto/cplusplus/semantic/semantic.pro
+++ b/tests/auto/cplusplus/semantic/semantic.pro
@@ -1,7 +1,3 @@
-TEMPLATE = app
-CONFIG += qt warn_on console depend_includepath
-CONFIG += qtestlib testcase
+include(../../qttest.pri)
include(../shared/shared.pri)
-
SOURCES += tst_semantic.cpp
-TARGET=tst_$$TARGET
diff --git a/tests/auto/cplusplus/shared/shared.pri b/tests/auto/cplusplus/shared/shared.pri
index f89b4c65f0..ae551666c6 100644
--- a/tests/auto/cplusplus/shared/shared.pri
+++ b/tests/auto/cplusplus/shared/shared.pri
@@ -1,5 +1,8 @@
DEFINES+=CPLUSPLUS_BUILD_STATIC_LIB
-include(../../../../qtcreator.pri)
INCLUDEPATH += $$IDE_SOURCE_TREE/src/libs/cplusplus
INCLUDEPATH += $$IDE_SOURCE_TREE/src/shared/cplusplus
-include($$PWD/../../../../src/libs/cplusplus/cplusplus-lib.pri)
+include($$IDE_SOURCE_TREE/src/plugins/cpptools/cpptools.pri)
+include($$IDE_SOURCE_TREE/src/rpath.pri)
+
+LIBS += -L$$IDE_PLUGIN_PATH/Nokia
+DEFINES += Q_PLUGIN_PATH=\"\\\"$$IDE_PLUGIN_PATH/Nokia\\\"\"
diff --git a/tests/auto/cplusplus/simplifytypes/simplifytypes.pro b/tests/auto/cplusplus/simplifytypes/simplifytypes.pro
new file mode 100644
index 0000000000..587abf8146
--- /dev/null
+++ b/tests/auto/cplusplus/simplifytypes/simplifytypes.pro
@@ -0,0 +1,3 @@
+include(../../qttest.pri)
+include(../shared/shared.pri)
+SOURCES += tst_simplifytypestest.cpp
diff --git a/tests/auto/cplusplus/simplifytypes/tst_simplifytypestest.cpp b/tests/auto/cplusplus/simplifytypes/tst_simplifytypestest.cpp
new file mode 100644
index 0000000000..aaa51bf5fd
--- /dev/null
+++ b/tests/auto/cplusplus/simplifytypes/tst_simplifytypestest.cpp
@@ -0,0 +1,139 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 <cplusplus/CppRewriter.h>
+
+#include <QtCore/QString>
+#include <QtTest/QtTest>
+
+const char *description[] =
+{
+ "g++_stdstring",
+ "g++_stdwstring",
+ "g++_stringmap",
+ "g++_wstringmap",
+ "g++_stringlist",
+ "g++_stringset",
+ "g++_stringvector",
+ "g++_wstringvector",
+ "msvc_stdstring",
+ "msvc_stdwstring",
+ "msvc_stringmap",
+ "msvc_wstringmap",
+ "msvc_stringlist",
+ "msvc_stringset",
+ "msvc_stringvector",
+ "msvc_wstringvector",
+};
+
+const char *input[] =
+{
+// g++
+"std::string",
+"std::wstring",
+"std::map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >",
+"std::map<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >, std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >, std::less<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >, std::allocator<std::pair<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > const, std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > > > >",
+"std::list<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >",
+"std::set<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >",
+"std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >",
+"std::vector<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >, std::allocator<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > > >",
+// MSVC
+"class std::basic_string<char,std::char_traits<char>,std::allocator<char> >",
+"class std::basic_string<unsigned short,std::char_traits<unsigned short>,std::allocator<unsigned short> >",
+"class std::map<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::less<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,std::allocator<std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> > const ,std::basic_string<char,std::char_traits<char>,std::allocator<char> > > > >",
+"class std::map<std::basic_string<unsigned short,std::char_traits<unsigned short>,std::allocator<unsigned short> >,std::basic_string<unsigned short,std::char_traits<unsigned short>,std::allocator<unsigned short> >,std::less<std::basic_string<unsigned short,std::char_traits<unsigned short>,std::allocator<unsigned short> > >,std::allocator<std::pair<std::basic_string<unsigned short,std::char_traits<unsigned short>,std::allocator<unsigned short> > const ,std::basic_string<unsigned short,std::char_traits<unsigned short>,std::allocator<unsigned short> > > > >",
+"class std::list<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::allocator<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > >",
+"class std::set<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::less<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,std::allocator<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > >",
+"class std::vector<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::allocator<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > >",
+"class std::vector<std::basic_string<unsigned short,std::char_traits<unsigned short>,std::allocator<unsigned short> >,std::allocator<std::basic_string<unsigned short,std::char_traits<unsigned short>,std::allocator<unsigned short> > > >"
+};
+
+const char *output[] =
+{
+ "std::string",
+ "std::wstring",
+ "std::map<std::string, std::string>",
+ "std::map<std::wstring, std::wstring>",
+ "std::list<std::string>",
+ "std::set<std::string>",
+ "std::vector<std::string>",
+ "std::vector<std::wstring>",
+ "std::string",
+ "std::wstring",
+ "std::map<std::string, std::string>",
+ "std::map<std::wstring, std::wstring>",
+ "std::list<std::string>",
+ "std::set<std::string>",
+ "std::vector<std::string>",
+ "std::vector<std::wstring>",
+};
+
+class SimplifyTypesTest : public QObject
+{
+ Q_OBJECT
+
+public:
+ SimplifyTypesTest();
+
+private Q_SLOTS:
+ void testCase1();
+ void testCase1_data();
+};
+
+SimplifyTypesTest::SimplifyTypesTest()
+{
+}
+
+void SimplifyTypesTest::testCase1()
+{
+ QFETCH(QString, input);
+ QFETCH(QString, expected);
+ const QString output = CPlusPlus::simplifySTLType(input);
+ const bool ok = output == expected;
+ if (!ok) {
+ const QString msg = QString::fromAscii("Failure: got '%1' where '%2' was expected for '%3'")
+ .arg(output, expected, input);
+ QWARN(qPrintable(msg));
+ }
+ QVERIFY2(ok, "Failure");
+}
+
+void SimplifyTypesTest::testCase1_data()
+{
+ QTest::addColumn<QString>("input");
+ QTest::addColumn<QString>("expected");
+ const size_t count = sizeof(input)/sizeof(const char *);
+ for (size_t i = 0; i < count; i++ )
+ QTest::newRow(description[i]) << QString::fromAscii(input[i])
+ << QString::fromAscii(output[i]);
+}
+
+QTEST_APPLESS_MAIN(SimplifyTypesTest);
+
+#include "tst_simplifytypestest.moc"
diff --git a/tests/auto/cplusplus/typeprettyprinter/typeprettyprinter.pro b/tests/auto/cplusplus/typeprettyprinter/typeprettyprinter.pro
index 2e884365c1..52cd07b60c 100644
--- a/tests/auto/cplusplus/typeprettyprinter/typeprettyprinter.pro
+++ b/tests/auto/cplusplus/typeprettyprinter/typeprettyprinter.pro
@@ -1,6 +1,3 @@
-TEMPLATE = app
-CONFIG += qt warn_on console depend_includepath
-CONFIG += qtestlib testcase
+include(../../qttest.pri)
include(../shared/shared.pri)
SOURCES += tst_typeprettyprinter.cpp
-TARGET=tst_$$TARGET
diff --git a/tests/auto/debugger/dumpers.pro b/tests/auto/debugger/dumpers.pro
index 8ba21aa017..6226deaf23 100644
--- a/tests/auto/debugger/dumpers.pro
+++ b/tests/auto/debugger/dumpers.pro
@@ -1,4 +1,4 @@
-CONFIG += qtestlib testcase
+include(../qttest.pri)
DEBUGGERDIR = ../../../src/plugins/debugger
UTILSDIR = ../../../src/libs
@@ -12,7 +12,7 @@ SOURCES += \
DEFINES += MACROSDEBUG
-INCLUDEPATH += $$DEBUGGERDIR $$UTILSDIR $$MACROSDIR
-
-TARGET = tst_$$TARGET
+DEFINES -= QT_USE_FAST_CONCATENATION QT_USE_FAST_OPERATOR_PLUS
+DEFINES -= QT_NO_CAST_TO_ASCII QT_NO_CAST_FROM_ASCII
+INCLUDEPATH += $$DEBUGGERDIR $$UTILSDIR $$MACROSDIR
diff --git a/tests/auto/debugger/gdb.pro b/tests/auto/debugger/gdb.pro
index d4b7503a78..d181290ad0 100644
--- a/tests/auto/debugger/gdb.pro
+++ b/tests/auto/debugger/gdb.pro
@@ -1,6 +1,4 @@
-CONFIG += qtestlib testcase
-
-QT -= gui
+include(../qttest.pri)
UTILSDIR = ../../../src/libs
@@ -11,6 +9,3 @@ INCLUDEPATH += $$DEBUGGERDIR $$UTILSDIR
SOURCES += \
tst_gdb.cpp \
$$DEBUGGERDIR/gdb/gdbmi.cpp \
-
-TARGET = tst_$$TARGET
-
diff --git a/tests/auto/debugger/plugin.pro b/tests/auto/debugger/plugin.pro
index 53936e2349..d1022b544f 100644
--- a/tests/auto/debugger/plugin.pro
+++ b/tests/auto/debugger/plugin.pro
@@ -1,4 +1,4 @@
-CONFIG += qtestlib testcase
+include(../qttest.pri)
DEBUGGERDIR = ../../../src/plugins/debugger
UTILSDIR = ../../../src/libs
@@ -10,6 +10,3 @@ SOURCES += \
DEFINES += MACROSDEBUG
INCLUDEPATH += $$DEBUGGERDIR $$UTILSDIR $$MACROSDIR
-
-TARGET = tst_$$TARGET
-
diff --git a/tests/auto/debugger/tst_gdb.cpp b/tests/auto/debugger/tst_gdb.cpp
index ec68c52a4c..41e7109970 100644
--- a/tests/auto/debugger/tst_gdb.cpp
+++ b/tests/auto/debugger/tst_gdb.cpp
@@ -71,7 +71,7 @@ bool checkUninitialized = false;
#ifdef Q_OS_WIN
QString gdbBinary = "c:\\MinGw\\bin\\gdb.exe";
#else
-QString gdbBinary = "./gdb";
+QString gdbBinary = "gdb";
#endif
void nothing() {}
@@ -456,9 +456,9 @@ void Thread::readStandardOutput()
return;
//qWarning() << "WAKE UP: " << m_output;
- //qDebug() << "\n2 ABOUT TO AQUIRE FREE ";
+ //qDebug() << "\n2 ABOUT TO ACQUIRE FREE ";
freeBytes.acquire();
- //qDebug() << "\n2 AQUIRED FREE ";
+ //qDebug() << "\n2 ACQUIRED FREE ";
buffer = m_output;
m_output.clear();
//m_waitCondition.wakeAll();
@@ -571,9 +571,9 @@ void tst_Gdb::check(const QByteArray &label, const QByteArray &expected0,
options += ",fancy";
writeToGdb("bb " + options + " " + expanded);
- //qDebug() << "\n1 ABOUT TO AQUIRE USED ";
+ //qDebug() << "\n1 ABOUT TO ACQUIRE USED ";
usedBytes.acquire();
- //qDebug() << "\n1 AQUIRED USED ";
+ //qDebug() << "\n1 ACQUIRED USED ";
QByteArray ba = buffer;
buffer.clear();
//qDebug() << "\n1 ABOUT TO RELEASE FREE ";
diff --git a/tests/auto/debugger/version.pro b/tests/auto/debugger/version.pro
index 9e8069c07d..f5b1cdd726 100644
--- a/tests/auto/debugger/version.pro
+++ b/tests/auto/debugger/version.pro
@@ -1,5 +1,4 @@
-CONFIG += qtestlib testcase
-QT -= gui
+include(../qttest.pri)
UTILSDIR = ../../../src/libs
@@ -11,5 +10,3 @@ SOURCES += \
tst_version.cpp \
$$DEBUGGERDIR/gdb/gdbmi.cpp \
-TARGET = tst_$$TARGET
-
diff --git a/tests/auto/environment/environment.pro b/tests/auto/environment/environment.pro
new file mode 100644
index 0000000000..a39d91d66a
--- /dev/null
+++ b/tests/auto/environment/environment.pro
@@ -0,0 +1,17 @@
+CONFIG += qtestlib testcase
+TEMPLATE = app
+CONFIG -= app_bundle
+DEFINES += QTCREATOR_UTILS_LIB
+
+UTILS_PATH = ../../../src/libs/utils
+
+INCLUDEPATH += $$UTILS_PATH/..
+
+SOURCES += \
+ tst_environment.cpp \
+ $$UTILS_PATH/environment.cpp
+HEADERS += \
+ $$UTILS_PATH/environment.h \
+ $$UTILS_PATH/utils_global.h
+
+TARGET = tst_$$TARGET
diff --git a/tests/auto/environment/tst_environment.cpp b/tests/auto/environment/tst_environment.cpp
new file mode 100644
index 0000000000..26d4b752b9
--- /dev/null
+++ b/tests/auto/environment/tst_environment.cpp
@@ -0,0 +1,107 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 <utils/environment.h>
+
+#include <QtTest/QtTest>
+
+using namespace Utils;
+
+class tst_Environment : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void initTestCase();
+ void environment_data();
+ void environment();
+
+private:
+ Environment env;
+};
+
+void tst_Environment::initTestCase()
+{
+ env.set("word", "hi");
+}
+
+void tst_Environment::environment_data()
+{
+ QTest::addColumn<QString>("in");
+ QTest::addColumn<QString>("out");
+
+ static const struct {
+ const char * const in;
+ const char * const out;
+ } vals[] = {
+#ifdef Q_OS_WIN
+ { "", "" },
+ { "hi", "hi" },
+ { "hi%", "hi%" },
+ { "hi% ho", "hi% ho" },
+ { "hi%here ho", "hi%here ho" },
+ { "hi%here%ho", "hi%here%ho" },
+ { "hi%word%", "hihi" },
+ { "hi%foo%word%", "hi%foohi" },
+ { "%word%word%ho", "hiword%ho" },
+ { "hi%word%x%word%ho", "hihixhiho" },
+ { "hi%word%xx%word%ho", "hihixxhiho" },
+ { "hi%word%%word%ho", "hihihiho" },
+#else
+ { "", "" },
+ { "hi", "hi" },
+ { "hi$", "hi$" },
+ { "hi${", "hi${" },
+ { "hi${word", "hi${word" },
+ { "hi${word}", "hihi" },
+ { "hi${word}ho", "hihiho" },
+ { "hi$wo", "hi$wo" },
+ { "hi$word", "hihi" },
+ { "hi$word ho", "hihi ho" },
+ { "$word", "hi" },
+ { "hi${word}$word", "hihihi" },
+#endif
+ };
+
+ for (unsigned i = 0; i < sizeof(vals)/sizeof(vals[0]); i++)
+ QTest::newRow(vals[i].in) << QString::fromLatin1(vals[i].in)
+ << QString::fromLatin1(vals[i].out);
+}
+
+void tst_Environment::environment()
+{
+ QFETCH(QString, in);
+ QFETCH(QString, out);
+
+ QCOMPARE(env.expandVariables(in), out);
+}
+
+QTEST_MAIN(tst_Environment)
+
+#include "tst_environment.moc"
diff --git a/tests/auto/extensionsystem/copy.pri b/tests/auto/extensionsystem/copy.pri
new file mode 100644
index 0000000000..9dc7f8dbd0
--- /dev/null
+++ b/tests/auto/extensionsystem/copy.pri
@@ -0,0 +1,12 @@
+#set COPYFILES and COPYDIR
+!equals(_PRO_FILE_PWD_, $$OUT_PWD) { #only do something in case of shadow build
+ # stolen from qtcreatorplugin.pri
+ copy2build.input = COPYFILES
+ copy2build.output = $$COPYDIR/${QMAKE_FUNC_FILE_IN_stripSrcDir}
+ isEmpty(vcproj):copy2build.variable_out = PRE_TARGETDEPS
+ copy2build.commands = $$QMAKE_COPY ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT}
+ copy2build.name = COPY ${QMAKE_FILE_IN}
+ copy2build.CONFIG += no_link
+ QMAKE_EXTRA_COMPILERS += copy2build
+}
+
diff --git a/tests/auto/extensionsystem/extensionsystem.pro b/tests/auto/extensionsystem/extensionsystem.pro
new file mode 100644
index 0000000000..f988a84e10
--- /dev/null
+++ b/tests/auto/extensionsystem/extensionsystem.pro
@@ -0,0 +1,4 @@
+TEMPLATE = subdirs
+SUBDIRS = pluginmanager \
+ pluginspec
+
diff --git a/src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/circularplugins.pro b/tests/auto/extensionsystem/pluginmanager/circularplugins/circularplugins.pro
index 21f257cf08..21f257cf08 100644
--- a/src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/circularplugins.pro
+++ b/tests/auto/extensionsystem/pluginmanager/circularplugins/circularplugins.pro
diff --git a/src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin1/plugin.xml b/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin1/plugin.xml
index db201f34c3..db201f34c3 100644
--- a/src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin1/plugin.xml
+++ b/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin1/plugin.xml
diff --git a/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin1/plugin1.cpp b/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin1/plugin1.cpp
new file mode 100644
index 0000000000..ca07c0cd13
--- /dev/null
+++ b/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin1/plugin1.cpp
@@ -0,0 +1,57 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** No Commercial Usage
+**
+** This file 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.
+**
+**************************************************************************/
+
+#include "plugin1.h"
+
+#include <QtCore/qplugin.h>
+#include <QStringList>
+
+using namespace Plugin1;
+
+MyPlugin1::MyPlugin1()
+{
+}
+
+bool MyPlugin1::initialize(const QStringList &arguments, QString *errorString)
+{
+ Q_UNUSED(arguments)
+ Q_UNUSED(errorString)
+ return true;
+}
+
+void MyPlugin1::extensionsInitialized()
+{
+}
+
+Q_EXPORT_PLUGIN(MyPlugin1)
+
diff --git a/src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin1/plugin1.h b/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin1/plugin1.h
index 27471aa2a0..27471aa2a0 100644
--- a/src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin1/plugin1.h
+++ b/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin1/plugin1.h
diff --git a/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin1/plugin1.pro b/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin1/plugin1.pro
new file mode 100644
index 0000000000..05e50cf8d4
--- /dev/null
+++ b/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin1/plugin1.pro
@@ -0,0 +1,19 @@
+TEMPLATE = lib
+
+SOURCES += plugin1.cpp
+HEADERS += plugin1.h
+
+OTHER_FILES = $$PWD/plugin.xml
+
+include(../../../../../../qtcreator.pri)
+include(../../../../../../src/libs/extensionsystem/extensionsystem.pri)
+include(../../../../qttestrpath.pri)
+
+COPYDIR = $$OUT_PWD
+COPYFILES = $$OTHER_FILES
+include(../../../copy.pri)
+
+TARGET = $$qtLibraryName(plugin1)
+
+DESTDIR = $$OUT_PWD/../lib
+LIBS += -L$$OUT_PWD/../lib
diff --git a/src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin2/plugin.xml b/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin2/plugin.xml
index 5436967a80..5436967a80 100644
--- a/src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin2/plugin.xml
+++ b/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin2/plugin.xml
diff --git a/src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin2/plugin2.cpp b/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin2/plugin2.cpp
index 550c6e7e7c..550c6e7e7c 100644
--- a/src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin2/plugin2.cpp
+++ b/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin2/plugin2.cpp
diff --git a/src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin2/plugin2.h b/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin2/plugin2.h
index 784997e051..784997e051 100644
--- a/src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin2/plugin2.h
+++ b/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin2/plugin2.h
diff --git a/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin2/plugin2.pro b/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin2/plugin2.pro
new file mode 100644
index 0000000000..cafef0b197
--- /dev/null
+++ b/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin2/plugin2.pro
@@ -0,0 +1,19 @@
+TEMPLATE = lib
+
+SOURCES += plugin2.cpp
+HEADERS += plugin2.h
+
+OTHER_FILES = $$PWD/plugin.xml
+
+include(../../../../../../qtcreator.pri)
+include(../../../../../../src/libs/extensionsystem/extensionsystem.pri)
+include(../../../../qttestrpath.pri)
+
+COPYDIR = $$OUT_PWD
+COPYFILES = $$OTHER_FILES
+include(../../../copy.pri)
+
+TARGET = $$qtLibraryName(plugin2)
+
+DESTDIR = $$OUT_PWD/../lib
+LIBS += -L$$OUT_PWD/../lib
diff --git a/src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin3/plugin.xml b/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin3/plugin.xml
index f7e90978ba..f7e90978ba 100644
--- a/src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin3/plugin.xml
+++ b/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin3/plugin.xml
diff --git a/src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin3/plugin3.cpp b/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin3/plugin3.cpp
index 90fb353f65..90fb353f65 100644
--- a/src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin3/plugin3.cpp
+++ b/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin3/plugin3.cpp
diff --git a/src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin3/plugin3.h b/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin3/plugin3.h
index bcff89d87c..bcff89d87c 100644
--- a/src/libs/extensionsystem/test/auto/pluginmanager/circularplugins/plugin3/plugin3.h
+++ b/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin3/plugin3.h
diff --git a/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin3/plugin3.pro b/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin3/plugin3.pro
new file mode 100644
index 0000000000..1cb438ddc9
--- /dev/null
+++ b/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin3/plugin3.pro
@@ -0,0 +1,19 @@
+TEMPLATE = lib
+
+SOURCES += plugin3.cpp
+HEADERS += plugin3.h
+
+OTHER_FILES = $$PWD/plugin.xml
+
+include(../../../../../../qtcreator.pri)
+include(../../../../../../src/libs/extensionsystem/extensionsystem.pri)
+include(../../../../qttestrpath.pri)
+
+COPYDIR = $$OUT_PWD
+COPYFILES = $$OTHER_FILES
+include(../../../copy.pri)
+
+TARGET = $$qtLibraryName(plugin3)
+
+DESTDIR = $$OUT_PWD/../lib
+LIBS += -L$$OUT_PWD/../lib
diff --git a/src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/correctplugins1.pro b/tests/auto/extensionsystem/pluginmanager/correctplugins1/correctplugins1.pro
index f0d76950e8..f0d76950e8 100644
--- a/src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/correctplugins1.pro
+++ b/tests/auto/extensionsystem/pluginmanager/correctplugins1/correctplugins1.pro
diff --git a/src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin1/plugin.spec b/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin1/plugin.spec
index db201f34c3..db201f34c3 100644
--- a/src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin1/plugin.spec
+++ b/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin1/plugin.spec
diff --git a/src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin1/plugin1.cpp b/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin1/plugin1.cpp
index 1298f93884..1298f93884 100644
--- a/src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin1/plugin1.cpp
+++ b/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin1/plugin1.cpp
diff --git a/src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin1/plugin1.h b/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin1/plugin1.h
index f2d339a96e..f2d339a96e 100644
--- a/src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin1/plugin1.h
+++ b/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin1/plugin1.h
diff --git a/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin1/plugin1.pro b/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin1/plugin1.pro
new file mode 100644
index 0000000000..30d319b29d
--- /dev/null
+++ b/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin1/plugin1.pro
@@ -0,0 +1,26 @@
+TEMPLATE = lib
+
+SOURCES += plugin1.cpp
+HEADERS += plugin1.h
+
+OTHER_FILES = $$PWD/plugin.spec
+
+include(../../../../../../qtcreator.pri)
+include(../../../../../../src/libs/extensionsystem/extensionsystem.pri)
+include(../../../../qttestrpath.pri)
+
+COPYDIR = $$OUT_PWD
+COPYFILES = $$OTHER_FILES
+include(../../../copy.pri)
+
+TARGET = $$qtLibraryName(plugin1)
+
+DESTDIR = $$OUT_PWD/../lib
+LIBS += -L$$OUT_PWD/../lib
+
+LIBS += -l$$qtLibraryName(plugin2) -l$$qtLibraryName(plugin3)
+
+macx {
+} else:unix {
+ QMAKE_RPATHDIR += $$OUT_PWD/../lib
+}
diff --git a/src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin2/plugin.spec b/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin2/plugin.spec
index 5436967a80..5436967a80 100644
--- a/src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin2/plugin.spec
+++ b/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin2/plugin.spec
diff --git a/src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin2/plugin2.cpp b/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin2/plugin2.cpp
index 696d7b5840..696d7b5840 100644
--- a/src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin2/plugin2.cpp
+++ b/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin2/plugin2.cpp
diff --git a/src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin2/plugin2.h b/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin2/plugin2.h
index e4effb15fb..e4effb15fb 100644
--- a/src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin2/plugin2.h
+++ b/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin2/plugin2.h
diff --git a/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin2/plugin2.pro b/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin2/plugin2.pro
new file mode 100644
index 0000000000..f264f9dd28
--- /dev/null
+++ b/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin2/plugin2.pro
@@ -0,0 +1,24 @@
+TEMPLATE = lib
+
+SOURCES += plugin2.cpp
+HEADERS += plugin2.h
+
+OTHER_FILES = $$PWD/plugin.spec
+
+include(../../../../../../qtcreator.pri)
+include(../../../../../../src/libs/extensionsystem/extensionsystem.pri)
+include(../../../../qttestrpath.pri)
+
+COPYDIR = $$OUT_PWD
+COPYFILES = $$OTHER_FILES
+include(../../../copy.pri)
+
+TARGET = $$qtLibraryName(plugin2)
+
+DESTDIR = $$OUT_PWD/../lib
+LIBS += -L$$OUT_PWD/../lib
+
+macx {
+ QMAKE_LFLAGS_SONAME = -Wl,-install_name,$${OUT_PWD}/
+}
+
diff --git a/src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin3/plugin.spec b/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin3/plugin.spec
index 234bf56ea2..234bf56ea2 100644
--- a/src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin3/plugin.spec
+++ b/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin3/plugin.spec
diff --git a/src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin3/plugin3.cpp b/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin3/plugin3.cpp
index 69f3f657d2..69f3f657d2 100644
--- a/src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin3/plugin3.cpp
+++ b/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin3/plugin3.cpp
diff --git a/src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin3/plugin3.h b/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin3/plugin3.h
index bbb8a4d5da..bbb8a4d5da 100644
--- a/src/libs/extensionsystem/test/auto/pluginmanager/correctplugins1/plugin3/plugin3.h
+++ b/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin3/plugin3.h
diff --git a/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin3/plugin3.pro b/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin3/plugin3.pro
new file mode 100644
index 0000000000..5dfa14fd5c
--- /dev/null
+++ b/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin3/plugin3.pro
@@ -0,0 +1,26 @@
+TEMPLATE = lib
+
+SOURCES += plugin3.cpp
+HEADERS += plugin3.h
+
+OTHER_FILES = $$PWD/plugin.spec
+
+include(../../../../../../qtcreator.pri)
+include(../../../../../../src/libs/extensionsystem/extensionsystem.pri)
+include(../../../../qttestrpath.pri)
+
+COPYDIR = $$OUT_PWD
+COPYFILES = $$OTHER_FILES
+include(../../../copy.pri)
+
+TARGET = $$qtLibraryName(plugin3)
+
+DESTDIR = $$OUT_PWD/../lib
+LIBS += -L$$OUT_PWD/../lib
+LIBS += -l$$qtLibraryName(plugin2)
+
+macx {
+ QMAKE_LFLAGS_SONAME = -Wl,-install_name,$${OUT_PWD}/
+} else:unix {
+ QMAKE_RPATHDIR += $OUT_PWD/../lib
+}
diff --git a/src/libs/extensionsystem/test/auto/pluginmanager/pluginmanager.pro b/tests/auto/extensionsystem/pluginmanager/pluginmanager.pro
index 57b026f5fb..57b026f5fb 100644
--- a/src/libs/extensionsystem/test/auto/pluginmanager/pluginmanager.pro
+++ b/tests/auto/extensionsystem/pluginmanager/pluginmanager.pro
diff --git a/src/libs/extensionsystem/test/auto/pluginmanager/plugins/myplug/myplug.xml b/tests/auto/extensionsystem/pluginmanager/plugins/myplug/myplug.xml
index c79b29780d..c79b29780d 100644
--- a/src/libs/extensionsystem/test/auto/pluginmanager/plugins/myplug/myplug.xml
+++ b/tests/auto/extensionsystem/pluginmanager/plugins/myplug/myplug.xml
diff --git a/src/libs/extensionsystem/test/auto/pluginmanager/plugins/otherplugin.xml b/tests/auto/extensionsystem/pluginmanager/plugins/otherplugin.xml
index 6f0483f0f8..6f0483f0f8 100644
--- a/src/libs/extensionsystem/test/auto/pluginmanager/plugins/otherplugin.xml
+++ b/tests/auto/extensionsystem/pluginmanager/plugins/otherplugin.xml
diff --git a/src/libs/extensionsystem/test/auto/pluginmanager/plugins/plugin1.xml b/tests/auto/extensionsystem/pluginmanager/plugins/plugin1.xml
index 6bd573957b..6bd573957b 100644
--- a/src/libs/extensionsystem/test/auto/pluginmanager/plugins/plugin1.xml
+++ b/tests/auto/extensionsystem/pluginmanager/plugins/plugin1.xml
diff --git a/tests/auto/extensionsystem/pluginmanager/test.pro b/tests/auto/extensionsystem/pluginmanager/test.pro
new file mode 100644
index 0000000000..f9047d1927
--- /dev/null
+++ b/tests/auto/extensionsystem/pluginmanager/test.pro
@@ -0,0 +1,20 @@
+######################################################################
+# Automatically generated by qmake (2.01a) Fr Jul 27 23:12:52 2007
+######################################################################
+
+TARGET = pluginmanager
+
+# Input
+
+include(../../qttest.pri)
+include(../../../../src/libs/extensionsystem/extensionsystem.pri)
+
+SOURCES += tst_pluginmanager.cpp
+
+OTHER_FILES = $$PWD/plugins/otherplugin.xml \
+ $$PWD/plugins/plugin1.xml \
+ $$PWD/plugins/myplug/myplug.xml
+
+COPYDIR = $$OUT_PWD
+COPYFILES = $$OTHER_FILES
+include(../copy.pri)
diff --git a/tests/auto/extensionsystem/pluginmanager/tst_pluginmanager.cpp b/tests/auto/extensionsystem/pluginmanager/tst_pluginmanager.cpp
new file mode 100644
index 0000000000..c6f98434e4
--- /dev/null
+++ b/tests/auto/extensionsystem/pluginmanager/tst_pluginmanager.cpp
@@ -0,0 +1,249 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** No Commercial Usage
+**
+** This file 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.
+**
+**************************************************************************/
+
+#include <extensionsystem/pluginmanager.h>
+#include <extensionsystem/pluginspec.h>
+#include <extensionsystem/iplugin.h>
+
+#include <QtTest/QtTest>
+
+#include <QtCore/QObject>
+
+using namespace ExtensionSystem;
+
+class SignalReceiver;
+
+class tst_PluginManager : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void init();
+ void cleanup();
+ void addRemoveObjects();
+ void getObject();
+ void getObjects();
+ void plugins();
+ void circularPlugins();
+ void correctPlugins1();
+
+private:
+ PluginManager *m_pm;
+ QSignalSpy *m_objectAdded;
+ QSignalSpy *m_aboutToRemoveObject;
+ QSignalSpy *m_pluginsChanged;
+};
+
+class MyClass1 : public QObject
+{
+ Q_OBJECT
+};
+
+class MyClass2 : public QObject
+{
+ Q_OBJECT
+};
+
+class MyClass11 : public MyClass1
+{
+ Q_OBJECT
+};
+
+void tst_PluginManager::init()
+{
+ m_pm = new PluginManager;
+ m_objectAdded = new QSignalSpy(m_pm, SIGNAL(objectAdded(QObject*)));
+ m_aboutToRemoveObject = new QSignalSpy(m_pm, SIGNAL(aboutToRemoveObject(QObject*)));
+ m_pluginsChanged = new QSignalSpy(m_pm, SIGNAL(pluginsChanged()));
+}
+
+void tst_PluginManager::cleanup()
+{
+ delete m_pm;
+ delete m_objectAdded;
+ delete m_aboutToRemoveObject;
+ delete m_pluginsChanged;
+}
+
+void tst_PluginManager::addRemoveObjects()
+{
+ QObject *object1 = new QObject;
+ QObject *object2 = new QObject;
+ QCOMPARE(m_pm->allObjects().size(), 0);
+ m_pm->addObject(object1);
+ QCOMPARE(m_objectAdded->count(), 1);
+ QCOMPARE(m_objectAdded->at(0).first().value<QObject *>(), object1);
+ QCOMPARE(m_aboutToRemoveObject->count(), 0);
+ QVERIFY(m_pm->allObjects().contains(object1));
+ QVERIFY(!m_pm->allObjects().contains(object2));
+ QCOMPARE(m_pm->allObjects().size(), 1);
+ m_pm->addObject(object2);
+ QCOMPARE(m_objectAdded->count(), 2);
+ QCOMPARE(m_objectAdded->at(1).first().value<QObject *>(), object2);
+ QCOMPARE(m_aboutToRemoveObject->count(), 0);
+ QVERIFY(m_pm->allObjects().contains(object1));
+ QVERIFY(m_pm->allObjects().contains(object2));
+ QCOMPARE(m_pm->allObjects().size(), 2);
+ m_pm->removeObject(object1);
+ QCOMPARE(m_objectAdded->count(), 2);
+ QCOMPARE(m_aboutToRemoveObject->count(), 1);
+ QCOMPARE(m_aboutToRemoveObject->at(0).first().value<QObject *>(), object1);
+ QVERIFY(!m_pm->allObjects().contains(object1));
+ QVERIFY(m_pm->allObjects().contains(object2));
+ QCOMPARE(m_pm->allObjects().size(), 1);
+ m_pm->removeObject(object2);
+ QCOMPARE(m_objectAdded->count(), 2);
+ QCOMPARE(m_aboutToRemoveObject->count(), 2);
+ QCOMPARE(m_aboutToRemoveObject->at(1).first().value<QObject *>(), object2);
+ QVERIFY(!m_pm->allObjects().contains(object1));
+ QVERIFY(!m_pm->allObjects().contains(object2));
+ QCOMPARE(m_pm->allObjects().size(), 0);
+ delete object1;
+ delete object2;
+}
+
+void tst_PluginManager::getObject()
+{
+ MyClass2 *object2 = new MyClass2;
+ MyClass11 *object11 = new MyClass11;
+ m_pm->addObject(object2);
+ QCOMPARE(m_pm->getObject<MyClass11>(), (MyClass11*)0);
+ QCOMPARE(m_pm->getObject<MyClass1>(), (MyClass1*)0);
+ QCOMPARE(m_pm->getObject<MyClass2>(), object2);
+ m_pm->addObject(object11);
+ QCOMPARE(m_pm->getObject<MyClass11>(), object11);
+ QCOMPARE(m_pm->getObject<MyClass1>(), qobject_cast<MyClass1*>(object11));
+ QCOMPARE(m_pm->getObject<MyClass2>(), object2);
+ m_pm->removeObject(object2);
+ m_pm->removeObject(object11);
+ delete object2;
+ delete object11;
+}
+
+void tst_PluginManager::getObjects()
+{
+ MyClass1 *object1 = new MyClass1;
+ MyClass2 *object2 = new MyClass2;
+ MyClass11 *object11 = new MyClass11;
+ m_pm->addObject(object2);
+ QCOMPARE(m_pm->getObjects<MyClass11>(), QList<MyClass11*>());
+ QCOMPARE(m_pm->getObjects<MyClass1>(), QList<MyClass1*>());
+ QCOMPARE(m_pm->getObjects<MyClass2>(), QList<MyClass2*>() << object2);
+ QCOMPARE(m_pm->allObjects(), QList<QObject*>() << object2);
+ m_pm->addObject(object11);
+ QCOMPARE(m_pm->getObjects<MyClass11>(), QList<MyClass11*>() << object11);
+ QCOMPARE(m_pm->getObjects<MyClass1>(), QList<MyClass1*>() << object11);
+ QCOMPARE(m_pm->getObjects<MyClass2>(), QList<MyClass2*>() << object2);
+ QCOMPARE(m_pm->allObjects(), QList<QObject*>() << object2 << object11);
+ m_pm->addObject(object1);
+ QCOMPARE(m_pm->getObjects<MyClass11>(), QList<MyClass11*>() << object11);
+ QCOMPARE(m_pm->getObjects<MyClass1>(), QList<MyClass1*>() << object11 << object1);
+ QCOMPARE(m_pm->getObjects<MyClass2>(), QList<MyClass2*>() << object2);
+ QCOMPARE(m_pm->allObjects(), QList<QObject*>() << object2 << object11 << object1);
+ m_pm->removeObject(object2);
+ m_pm->removeObject(object11);
+ m_pm->removeObject(object1);
+ delete object1;
+ delete object2;
+ delete object11;
+}
+
+void tst_PluginManager::plugins()
+{
+ m_pm->setPluginPaths(QStringList() << "plugins");
+ QCOMPARE(m_pluginsChanged->count(), 1);
+ QList<PluginSpec *> plugins = m_pm->plugins();
+ QCOMPARE(plugins.count(), 3);
+ foreach (const QString &expected, QStringList() << "helloworld" << "MyPlugin" << "dummyPlugin") {
+ bool found = false;
+ foreach (PluginSpec *spec, plugins) {
+ if (spec->name() == expected) {
+ found = true;
+ break;
+ }
+ }
+ QVERIFY2(found, QString("plugin '%1' not found").arg(expected).toLocal8Bit().constData());
+ }
+}
+
+void tst_PluginManager::circularPlugins()
+{
+ m_pm->setPluginPaths(QStringList() << "circularplugins");
+ m_pm->loadPlugins();
+ foreach (PluginSpec *spec, m_pm->plugins()) {
+ if (spec->name() == "plugin1") {
+ QVERIFY(spec->hasError());
+ QCOMPARE(spec->state(), PluginSpec::Resolved);
+ QCOMPARE(spec->plugin(), (IPlugin*)0);
+ } else if (spec->name() == "plugin2") {
+ QVERIFY(!spec->hasError());
+ QCOMPARE(spec->state(), PluginSpec::Running);
+ } else if (spec->name() == "plugin3") {
+ QVERIFY(spec->hasError());
+ QCOMPARE(spec->state(), PluginSpec::Resolved);
+ QCOMPARE(spec->plugin(), (IPlugin*)0);
+ }
+ }
+}
+
+void tst_PluginManager::correctPlugins1()
+{
+ m_pm->setFileExtension("spec");
+ m_pm->setPluginPaths(QStringList() << "correctplugins1");
+ m_pm->loadPlugins();
+ foreach (PluginSpec *spec, m_pm->plugins()) {
+ if (spec->hasError())
+ qDebug() << spec->errorString();
+ QVERIFY(!spec->hasError());
+ QCOMPARE(spec->state(), PluginSpec::Running);
+ }
+ bool plugin1running = false;
+ bool plugin2running = false;
+ bool plugin3running = false;
+ foreach (QObject *obj, m_pm->allObjects()) {
+ if (obj->objectName() == "MyPlugin1_running")
+ plugin1running = true;
+ else if (obj->objectName() == "MyPlugin2_running")
+ plugin2running = true;
+ else if (obj->objectName() == "MyPlugin3_running")
+ plugin3running = true;
+ }
+ QVERIFY(plugin1running);
+ QVERIFY(plugin2running);
+ QVERIFY(plugin3running);
+}
+
+QTEST_MAIN(tst_PluginManager)
+
+#include "tst_pluginmanager.moc"
+
diff --git a/src/libs/extensionsystem/test/auto/pluginspec/pluginspec.pro b/tests/auto/extensionsystem/pluginspec/pluginspec.pro
index d4b941b232..d4b941b232 100644
--- a/src/libs/extensionsystem/test/auto/pluginspec/pluginspec.pro
+++ b/tests/auto/extensionsystem/pluginspec/pluginspec.pro
diff --git a/tests/auto/extensionsystem/pluginspec/test.pro b/tests/auto/extensionsystem/pluginspec/test.pro
new file mode 100644
index 0000000000..2f86233cce
--- /dev/null
+++ b/tests/auto/extensionsystem/pluginspec/test.pro
@@ -0,0 +1,28 @@
+TARGET = pluginspec
+
+# Input
+SOURCES += tst_pluginspec.cpp
+
+OTHER_FILES += \
+ $$PWD/testspecs/simplespec.xml \
+ $$PWD/testspecs/simplespec_experimental.xml \
+ $$PWD/testspecs/spec1.xml \
+ $$PWD/testspecs/spec2.xml \
+ $$PWD/testspecs/spec_wrong1.xml \
+ $$PWD/testspecs/spec_wrong2.xml \
+ $$PWD/testspecs/spec_wrong3.xml \
+ $$PWD/testspecs/spec_wrong4.xml \
+ $$PWD/testspecs/spec_wrong5.xml \
+ $$PWD/testdependencies/spec1.xml \
+ $$PWD/testdependencies/spec2.xml \
+ $$PWD/testdependencies/spec3.xml \
+ $$PWD/testdependencies/spec4.xml \
+ $$PWD/testdependencies/spec5.xml \
+ $$PWD/testdir/spec.xml
+
+include(../../qttest.pri)
+include(../../../../src/libs/extensionsystem/extensionsystem.pri)
+
+COPYDIR = $$OUT_PWD
+COPYFILES = $$OTHER_FILES
+include(../copy.pri)
diff --git a/src/libs/extensionsystem/test/auto/pluginspec/testdependencies/spec1.xml b/tests/auto/extensionsystem/pluginspec/testdependencies/spec1.xml
index 137e1b494c..137e1b494c 100644
--- a/src/libs/extensionsystem/test/auto/pluginspec/testdependencies/spec1.xml
+++ b/tests/auto/extensionsystem/pluginspec/testdependencies/spec1.xml
diff --git a/src/libs/extensionsystem/test/auto/pluginspec/testdependencies/spec2.xml b/tests/auto/extensionsystem/pluginspec/testdependencies/spec2.xml
index 451f854185..451f854185 100644
--- a/src/libs/extensionsystem/test/auto/pluginspec/testdependencies/spec2.xml
+++ b/tests/auto/extensionsystem/pluginspec/testdependencies/spec2.xml
diff --git a/src/libs/extensionsystem/test/auto/pluginspec/testdependencies/spec3.xml b/tests/auto/extensionsystem/pluginspec/testdependencies/spec3.xml
index 9fa01a442f..9fa01a442f 100644
--- a/src/libs/extensionsystem/test/auto/pluginspec/testdependencies/spec3.xml
+++ b/tests/auto/extensionsystem/pluginspec/testdependencies/spec3.xml
diff --git a/src/libs/extensionsystem/test/auto/pluginspec/testdependencies/spec4.xml b/tests/auto/extensionsystem/pluginspec/testdependencies/spec4.xml
index b06bab2fa0..b06bab2fa0 100644
--- a/src/libs/extensionsystem/test/auto/pluginspec/testdependencies/spec4.xml
+++ b/tests/auto/extensionsystem/pluginspec/testdependencies/spec4.xml
diff --git a/src/libs/extensionsystem/test/auto/pluginspec/testdependencies/spec5.xml b/tests/auto/extensionsystem/pluginspec/testdependencies/spec5.xml
index aab8f424c3..aab8f424c3 100644
--- a/src/libs/extensionsystem/test/auto/pluginspec/testdependencies/spec5.xml
+++ b/tests/auto/extensionsystem/pluginspec/testdependencies/spec5.xml
diff --git a/src/libs/extensionsystem/test/auto/pluginspec/testdir/spec.xml b/tests/auto/extensionsystem/pluginspec/testdir/spec.xml
index 6bd573957b..6bd573957b 100644
--- a/src/libs/extensionsystem/test/auto/pluginspec/testdir/spec.xml
+++ b/tests/auto/extensionsystem/pluginspec/testdir/spec.xml
diff --git a/src/libs/extensionsystem/test/auto/pluginspec/testplugin/testplugin.cpp b/tests/auto/extensionsystem/pluginspec/testplugin/testplugin.cpp
index 7ac3d95eac..7ac3d95eac 100644
--- a/src/libs/extensionsystem/test/auto/pluginspec/testplugin/testplugin.cpp
+++ b/tests/auto/extensionsystem/pluginspec/testplugin/testplugin.cpp
diff --git a/tests/auto/extensionsystem/pluginspec/testplugin/testplugin.h b/tests/auto/extensionsystem/pluginspec/testplugin/testplugin.h
new file mode 100644
index 0000000000..958bcb3fec
--- /dev/null
+++ b/tests/auto/extensionsystem/pluginspec/testplugin/testplugin.h
@@ -0,0 +1,65 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** No Commercial Usage
+**
+** This file 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.
+**
+**************************************************************************/
+
+#ifndef TESTPLUGIN_H
+#define TESTPLUGIN_H
+
+#include "testplugin_global.h"
+#include <extensionsystem/iplugin.h>
+
+#include <QtCore/QObject>
+
+namespace MyPlugin {
+
+class MYPLUGIN_EXPORT MyPluginImpl : public ExtensionSystem::IPlugin
+{
+ Q_OBJECT
+
+public:
+ MyPluginImpl();
+
+ bool initialize(const QStringList &arguments, QString *errorString);
+ void extensionsInitialized();
+
+public slots:
+ bool isInitialized() { return m_isInitialized; }
+ bool isExtensionsInitialized() { return m_isExtensionsInitialized; }
+
+private:
+ bool m_isInitialized;
+ bool m_isExtensionsInitialized;
+};
+
+} // namespace
+
+#endif // TESTPLUGIN_H
diff --git a/tests/auto/extensionsystem/pluginspec/testplugin/testplugin.pro b/tests/auto/extensionsystem/pluginspec/testplugin/testplugin.pro
new file mode 100644
index 0000000000..4b3198fee0
--- /dev/null
+++ b/tests/auto/extensionsystem/pluginspec/testplugin/testplugin.pro
@@ -0,0 +1,16 @@
+TEMPLATE = lib
+DEFINES += MYPLUGIN_LIBRARY
+SOURCES += testplugin.cpp
+HEADERS += testplugin.h testplugin_global.h
+
+OTHER_FILES += testplugin.xml
+
+include(../../../../../qtcreator.pri)
+include(../../../../../src/libs/extensionsystem/extensionsystem.pri)
+include(../../../qttestrpath.pri)
+
+COPYDIR = $$OUT_PWD
+COPYFILES = $$PWD/testplugin.xml
+include(../../copy.pri)
+
+TARGET = $$qtLibraryName(test)
diff --git a/src/libs/extensionsystem/test/auto/pluginspec/testplugin/testplugin.xml b/tests/auto/extensionsystem/pluginspec/testplugin/testplugin.xml
index f8ab3f7a39..f8ab3f7a39 100644
--- a/src/libs/extensionsystem/test/auto/pluginspec/testplugin/testplugin.xml
+++ b/tests/auto/extensionsystem/pluginspec/testplugin/testplugin.xml
diff --git a/src/libs/extensionsystem/test/auto/pluginspec/testplugin/testplugin_global.h b/tests/auto/extensionsystem/pluginspec/testplugin/testplugin_global.h
index 6ae252a004..6ae252a004 100644
--- a/src/libs/extensionsystem/test/auto/pluginspec/testplugin/testplugin_global.h
+++ b/tests/auto/extensionsystem/pluginspec/testplugin/testplugin_global.h
diff --git a/src/libs/extensionsystem/test/auto/pluginspec/testspecs/simplespec.xml b/tests/auto/extensionsystem/pluginspec/testspecs/simplespec.xml
index 6bd573957b..6bd573957b 100644
--- a/src/libs/extensionsystem/test/auto/pluginspec/testspecs/simplespec.xml
+++ b/tests/auto/extensionsystem/pluginspec/testspecs/simplespec.xml
diff --git a/src/libs/extensionsystem/test/auto/pluginspec/testspecs/simplespec_experimental.xml b/tests/auto/extensionsystem/pluginspec/testspecs/simplespec_experimental.xml
index 69fe37c53e..69fe37c53e 100644
--- a/src/libs/extensionsystem/test/auto/pluginspec/testspecs/simplespec_experimental.xml
+++ b/tests/auto/extensionsystem/pluginspec/testspecs/simplespec_experimental.xml
diff --git a/src/libs/extensionsystem/test/auto/pluginspec/testspecs/spec1.xml b/tests/auto/extensionsystem/pluginspec/testspecs/spec1.xml
index 994f330bbe..994f330bbe 100644
--- a/src/libs/extensionsystem/test/auto/pluginspec/testspecs/spec1.xml
+++ b/tests/auto/extensionsystem/pluginspec/testspecs/spec1.xml
diff --git a/src/libs/extensionsystem/test/auto/pluginspec/testspecs/spec2.xml b/tests/auto/extensionsystem/pluginspec/testspecs/spec2.xml
index 454f58cb75..454f58cb75 100644
--- a/src/libs/extensionsystem/test/auto/pluginspec/testspecs/spec2.xml
+++ b/tests/auto/extensionsystem/pluginspec/testspecs/spec2.xml
diff --git a/src/libs/extensionsystem/test/auto/pluginspec/testspecs/spec_wrong1.xml b/tests/auto/extensionsystem/pluginspec/testspecs/spec_wrong1.xml
index ffcb61241e..ffcb61241e 100644
--- a/src/libs/extensionsystem/test/auto/pluginspec/testspecs/spec_wrong1.xml
+++ b/tests/auto/extensionsystem/pluginspec/testspecs/spec_wrong1.xml
diff --git a/src/libs/extensionsystem/test/auto/pluginspec/testspecs/spec_wrong2.xml b/tests/auto/extensionsystem/pluginspec/testspecs/spec_wrong2.xml
index 917acf78ad..917acf78ad 100644
--- a/src/libs/extensionsystem/test/auto/pluginspec/testspecs/spec_wrong2.xml
+++ b/tests/auto/extensionsystem/pluginspec/testspecs/spec_wrong2.xml
diff --git a/src/libs/extensionsystem/test/auto/pluginspec/testspecs/spec_wrong3.xml b/tests/auto/extensionsystem/pluginspec/testspecs/spec_wrong3.xml
index d79ab4492b..d79ab4492b 100644
--- a/src/libs/extensionsystem/test/auto/pluginspec/testspecs/spec_wrong3.xml
+++ b/tests/auto/extensionsystem/pluginspec/testspecs/spec_wrong3.xml
diff --git a/src/libs/extensionsystem/test/auto/pluginspec/testspecs/spec_wrong4.xml b/tests/auto/extensionsystem/pluginspec/testspecs/spec_wrong4.xml
index 849f165f9c..849f165f9c 100644
--- a/src/libs/extensionsystem/test/auto/pluginspec/testspecs/spec_wrong4.xml
+++ b/tests/auto/extensionsystem/pluginspec/testspecs/spec_wrong4.xml
diff --git a/src/libs/extensionsystem/test/auto/pluginspec/testspecs/spec_wrong5.xml b/tests/auto/extensionsystem/pluginspec/testspecs/spec_wrong5.xml
index 03936fd88c..03936fd88c 100644
--- a/src/libs/extensionsystem/test/auto/pluginspec/testspecs/spec_wrong5.xml
+++ b/tests/auto/extensionsystem/pluginspec/testspecs/spec_wrong5.xml
diff --git a/tests/auto/extensionsystem/pluginspec/tst_pluginspec.cpp b/tests/auto/extensionsystem/pluginspec/tst_pluginspec.cpp
new file mode 100644
index 0000000000..d3dda2c2ad
--- /dev/null
+++ b/tests/auto/extensionsystem/pluginspec/tst_pluginspec.cpp
@@ -0,0 +1,295 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** No Commercial Usage
+**
+** This file 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.
+**
+**************************************************************************/
+
+#include <extensionsystem/pluginspec.h>
+#include <extensionsystem/pluginspec_p.h>
+#include <extensionsystem/pluginmanager_p.h>
+#include <extensionsystem/pluginmanager.h>
+
+#include <QtCore/QObject>
+#include <QtCore/QMetaObject>
+#include <QtTest/QtTest>
+
+using namespace ExtensionSystem;
+
+class tst_PluginSpec : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void read();
+ void readError();
+ void isValidVersion();
+ void versionCompare();
+ void provides();
+ void experimental();
+ void locationAndPath();
+ void resolveDependencies();
+ void loadLibrary();
+ void initializePlugin();
+ void initializeExtensions();
+};
+
+void tst_PluginSpec::read()
+{
+ Internal::PluginSpecPrivate spec(0);
+ QCOMPARE(spec.state, PluginSpec::Invalid);
+ QVERIFY(spec.read("testspecs/spec1.xml"));
+ QCOMPARE(spec.state, PluginSpec::Read);
+ QVERIFY(!spec.hasError);
+ QVERIFY(spec.errorString.isEmpty());
+ QCOMPARE(spec.name, QString("test"));
+ QCOMPARE(spec.version, QString("1.0.1"));
+ QCOMPARE(spec.compatVersion, QString("1.0.0"));
+ QCOMPARE(spec.experimental, false);
+ QCOMPARE(spec.enabled, true);
+ QCOMPARE(spec.vendor, QString("Nokia Corporation"));
+ QCOMPARE(spec.copyright, QString("(C) 2007 Nokia Corporation"));
+ QCOMPARE(spec.license, QString("This is a default license bla\nblubbblubb\nend of terms"));
+ QCOMPARE(spec.description, QString("This plugin is just a test.\n it demonstrates the great use of the plugin spec."));
+ QCOMPARE(spec.url, QString("http://qt.noki.com"));
+ PluginDependency dep1;
+ dep1.name = QString("SomeOtherPlugin");
+ dep1.version = QString("2.3.0_2");
+ PluginDependency dep2;
+ dep2.name = QString("EvenOther");
+ dep2.version = QString("1.0.0");
+ QCOMPARE(spec.dependencies, QList<PluginDependency>() << dep1 << dep2);
+
+ // test missing compatVersion behavior
+ QVERIFY(spec.read("testspecs/spec2.xml"));
+ QCOMPARE(spec.version, QString("3.1.4_10"));
+ QCOMPARE(spec.compatVersion, QString("3.1.4_10"));
+}
+
+void tst_PluginSpec::readError()
+{
+ Internal::PluginSpecPrivate spec(0);
+ QCOMPARE(spec.state, PluginSpec::Invalid);
+ QVERIFY(!spec.read("non-existing-file.xml"));
+ QCOMPARE(spec.state, PluginSpec::Invalid);
+ QVERIFY(spec.hasError);
+ QVERIFY(!spec.errorString.isEmpty());
+ QVERIFY(!spec.read("testspecs/spec_wrong1.xml"));
+ QCOMPARE(spec.state, PluginSpec::Invalid);
+ QVERIFY(spec.hasError);
+ QVERIFY(!spec.errorString.isEmpty());
+ QVERIFY(!spec.read("testspecs/spec_wrong2.xml"));
+ QCOMPARE(spec.state, PluginSpec::Invalid);
+ QVERIFY(spec.hasError);
+ QVERIFY(!spec.errorString.isEmpty());
+ QVERIFY(!spec.read("testspecs/spec_wrong3.xml"));
+ QCOMPARE(spec.state, PluginSpec::Invalid);
+ QVERIFY(spec.hasError);
+ QVERIFY(!spec.errorString.isEmpty());
+ QVERIFY(!spec.read("testspecs/spec_wrong4.xml"));
+ QCOMPARE(spec.state, PluginSpec::Invalid);
+ QVERIFY(spec.hasError);
+ QVERIFY(!spec.errorString.isEmpty());
+ QVERIFY(!spec.read("testspecs/spec_wrong5.xml"));
+ QCOMPARE(spec.state, PluginSpec::Invalid);
+ QVERIFY(spec.hasError);
+ QVERIFY(!spec.errorString.isEmpty());
+}
+
+void tst_PluginSpec::isValidVersion()
+{
+ QVERIFY(Internal::PluginSpecPrivate::isValidVersion("2"));
+ QVERIFY(Internal::PluginSpecPrivate::isValidVersion("53"));
+ QVERIFY(Internal::PluginSpecPrivate::isValidVersion("52_1"));
+ QVERIFY(Internal::PluginSpecPrivate::isValidVersion("3.12"));
+ QVERIFY(Internal::PluginSpecPrivate::isValidVersion("31.1_12"));
+ QVERIFY(Internal::PluginSpecPrivate::isValidVersion("31.1.0"));
+ QVERIFY(Internal::PluginSpecPrivate::isValidVersion("1.0.2_1"));
+
+ QVERIFY(!Internal::PluginSpecPrivate::isValidVersion(""));
+ QVERIFY(!Internal::PluginSpecPrivate::isValidVersion("1..0"));
+ QVERIFY(!Internal::PluginSpecPrivate::isValidVersion("1.0_"));
+ QVERIFY(!Internal::PluginSpecPrivate::isValidVersion("1.0.0.0"));
+}
+
+void tst_PluginSpec::versionCompare()
+{
+ QVERIFY(Internal::PluginSpecPrivate::versionCompare("3", "3") == 0);
+ QVERIFY(Internal::PluginSpecPrivate::versionCompare("3.0.0", "3") == 0);
+ QVERIFY(Internal::PluginSpecPrivate::versionCompare("3.0", "3") == 0);
+ QVERIFY(Internal::PluginSpecPrivate::versionCompare("3.0.0_1", "3_1") == 0);
+ QVERIFY(Internal::PluginSpecPrivate::versionCompare("3.0_21", "3_21") == 0);
+
+ QVERIFY(Internal::PluginSpecPrivate::versionCompare("3", "1") > 0);
+ QVERIFY(Internal::PluginSpecPrivate::versionCompare("3", "1.0_12") > 0);
+ QVERIFY(Internal::PluginSpecPrivate::versionCompare("3_1", "3") > 0);
+ QVERIFY(Internal::PluginSpecPrivate::versionCompare("3.1.0_23", "3.1") > 0);
+ QVERIFY(Internal::PluginSpecPrivate::versionCompare("3.1_23", "3.1_12") > 0);
+
+ QVERIFY(Internal::PluginSpecPrivate::versionCompare("1", "3") < 0);
+ QVERIFY(Internal::PluginSpecPrivate::versionCompare("1.0_12", "3") < 0);
+ QVERIFY(Internal::PluginSpecPrivate::versionCompare("3", "3_1") < 0);
+ QVERIFY(Internal::PluginSpecPrivate::versionCompare("3.1", "3.1.0_23") < 0);
+ QVERIFY(Internal::PluginSpecPrivate::versionCompare("3.1_12", "3.1_23") < 0);
+}
+
+void tst_PluginSpec::provides()
+{
+ Internal::PluginSpecPrivate spec(0);
+ QVERIFY(spec.read("testspecs/simplespec.xml"));
+ QVERIFY(!spec.provides("SomeOtherPlugin", "2.2.3_9"));
+ QVERIFY(!spec.provides("MyPlugin", "2.2.3_10"));
+ QVERIFY(!spec.provides("MyPlugin", "2.2.4"));
+ QVERIFY(!spec.provides("MyPlugin", "2.3.11_1"));
+ QVERIFY(!spec.provides("MyPlugin", "2.3"));
+ QVERIFY(!spec.provides("MyPlugin", "3.0"));
+ QVERIFY(!spec.provides("MyPlugin", "1.9.9_99"));
+ QVERIFY(!spec.provides("MyPlugin", "1.9"));
+ QVERIFY(!spec.provides("MyPlugin", "0.9"));
+ QVERIFY(!spec.provides("MyPlugin", "1"));
+
+ QVERIFY(spec.provides("myplugin", "2.2.3_9"));
+ QVERIFY(spec.provides("MyPlugin", "2.2.3_9"));
+ QVERIFY(spec.provides("MyPlugin", "2.2.3_8"));
+ QVERIFY(spec.provides("MyPlugin", "2.2.3"));
+ QVERIFY(spec.provides("MyPlugin", "2.2.2"));
+ QVERIFY(spec.provides("MyPlugin", "2.1.2_10"));
+ QVERIFY(spec.provides("MyPlugin", "2.0_10"));
+ QVERIFY(spec.provides("MyPlugin", "2"));
+}
+
+void tst_PluginSpec::experimental()
+{
+ Internal::PluginSpecPrivate spec(0);
+ QVERIFY(spec.read("testspecs/simplespec_experimental.xml"));
+ QCOMPARE(spec.experimental, true);
+ QCOMPARE(spec.enabled, false);
+}
+
+void tst_PluginSpec::locationAndPath()
+{
+ Internal::PluginSpecPrivate spec(0);
+ QVERIFY(spec.read("testspecs/simplespec.xml"));
+ QCOMPARE(spec.location, QString(QDir::currentPath()+"/testspecs"));
+ QCOMPARE(spec.filePath, QString(QDir::currentPath()+"/testspecs/simplespec.xml"));
+ QVERIFY(spec.read("testdir/../testspecs/simplespec.xml"));
+ QCOMPARE(spec.location, QString(QDir::currentPath()+"/testspecs"));
+ QCOMPARE(spec.filePath, QString(QDir::currentPath()+"/testspecs/simplespec.xml"));
+ QVERIFY(spec.read("testdir/spec.xml"));
+ QCOMPARE(spec.location, QString(QDir::currentPath()+"/testdir"));
+ QCOMPARE(spec.filePath, QString(QDir::currentPath()+"/testdir/spec.xml"));
+}
+
+void tst_PluginSpec::resolveDependencies()
+{
+ QList<PluginSpec *> specs;
+ PluginSpec *spec1 = Internal::PluginManagerPrivate::createSpec();
+ specs.append(spec1);
+ Internal::PluginSpecPrivate *spec1Priv = Internal::PluginManagerPrivate::privateSpec(spec1);
+ spec1Priv->read("testdependencies/spec1.xml");
+ PluginSpec *spec2 = Internal::PluginManagerPrivate::createSpec();
+ specs.append(spec2);
+ Internal::PluginManagerPrivate::privateSpec(spec2)->read("testdependencies/spec2.xml");
+ PluginSpec *spec3 = Internal::PluginManagerPrivate::createSpec();
+ specs.append(spec3);
+ Internal::PluginManagerPrivate::privateSpec(spec3)->read("testdependencies/spec3.xml");
+ PluginSpec *spec4 = Internal::PluginManagerPrivate::createSpec();
+ specs.append(spec4);
+ Internal::PluginSpecPrivate *spec4Priv = Internal::PluginManagerPrivate::privateSpec(spec4);
+ spec4Priv->read("testdependencies/spec4.xml");
+ PluginSpec *spec5 = Internal::PluginManagerPrivate::createSpec();
+ specs.append(spec5);
+ Internal::PluginManagerPrivate::privateSpec(spec5)->read("testdependencies/spec5.xml");
+ QVERIFY(spec1Priv->resolveDependencies(specs));
+ QCOMPARE(spec1Priv->dependencySpecs.size(), 2);
+ QVERIFY(spec1Priv->dependencySpecs.contains(spec2));
+ QVERIFY(spec1Priv->dependencySpecs.contains(spec3));
+ QCOMPARE(spec1Priv->state, PluginSpec::Resolved);
+ QVERIFY(!spec4Priv->resolveDependencies(specs));
+ QVERIFY(spec4Priv->hasError);
+ QCOMPARE(spec4Priv->state, PluginSpec::Read);
+}
+
+void tst_PluginSpec::loadLibrary()
+{
+ PluginSpec *ps = Internal::PluginManagerPrivate::createSpec();
+ Internal::PluginSpecPrivate *spec = Internal::PluginManagerPrivate::privateSpec(ps);
+ PluginManager *manager = new PluginManager();
+ QVERIFY(spec->read("testplugin/testplugin.xml"));
+ QVERIFY(spec->resolveDependencies(QList<PluginSpec *>()));
+ QVERIFY(spec->loadLibrary());
+ QVERIFY(spec->plugin != 0);
+ QVERIFY(QString::fromLocal8Bit(spec->plugin->metaObject()->className()) == QString::fromLocal8Bit("MyPlugin::MyPluginImpl"));
+ QCOMPARE(spec->state, PluginSpec::Loaded);
+ QVERIFY(!spec->hasError);
+ QCOMPARE(spec->plugin->pluginSpec(), ps);
+ delete manager;
+ delete ps;
+}
+
+void tst_PluginSpec::initializePlugin()
+{
+ Internal::PluginSpecPrivate spec(0);
+ QVERIFY(spec.read("testplugin/testplugin.xml"));
+ QVERIFY(spec.resolveDependencies(QList<PluginSpec *>()));
+ QVERIFY(spec.loadLibrary());
+ bool isInitialized;
+ QMetaObject::invokeMethod(spec.plugin, "isInitialized",
+ Qt::DirectConnection, Q_RETURN_ARG(bool, isInitialized));
+ QVERIFY(!isInitialized);
+ QVERIFY(spec.initializePlugin());
+ QCOMPARE(spec.state, PluginSpec::Initialized);
+ QVERIFY(!spec.hasError);
+ QMetaObject::invokeMethod(spec.plugin, "isInitialized",
+ Qt::DirectConnection, Q_RETURN_ARG(bool, isInitialized));
+ QVERIFY(isInitialized);
+}
+
+void tst_PluginSpec::initializeExtensions()
+{
+ Internal::PluginSpecPrivate spec(0);
+ QVERIFY(spec.read("testplugin/testplugin.xml"));
+ QVERIFY(spec.resolveDependencies(QList<PluginSpec *>()));
+ QVERIFY(spec.loadLibrary());
+ bool isExtensionsInitialized;
+ QVERIFY(spec.initializePlugin());
+ QMetaObject::invokeMethod(spec.plugin, "isExtensionsInitialized",
+ Qt::DirectConnection, Q_RETURN_ARG(bool, isExtensionsInitialized));
+ QVERIFY(!isExtensionsInitialized);
+ QVERIFY(spec.initializeExtensions());
+ QCOMPARE(spec.state, PluginSpec::Running);
+ QVERIFY(!spec.hasError);
+ QMetaObject::invokeMethod(spec.plugin, "isExtensionsInitialized",
+ Qt::DirectConnection, Q_RETURN_ARG(bool, isExtensionsInitialized));
+ QVERIFY(isExtensionsInitialized);
+}
+
+QTEST_MAIN(tst_PluginSpec)
+
+#include "tst_pluginspec.moc"
diff --git a/tests/auto/fakevim/fakevim.pro b/tests/auto/fakevim/fakevim.pro
index 7bcd59a6d6..b01b54f468 100644
--- a/tests/auto/fakevim/fakevim.pro
+++ b/tests/auto/fakevim/fakevim.pro
@@ -1,28 +1,22 @@
-CONFIG += qtestlib testcase
+include(../qttest.pri)
# Defines import symbol as empty
DEFINES+=QTCREATOR_UTILS_STATIC_LIB
+include(../../../src/libs/utils/utils.pri)
+
FAKEVIMDIR = ../../../src/plugins/fakevim
UTILSDIR = ../../../src/libs
SOURCES += \
- $$FAKEVIMDIR/fakevimhandler.cpp \
- $$FAKEVIMDIR/fakevimactions.cpp \
- $$FAKEVIMDIR/fakevimsyntax.cpp \
- $$UTILSDIR/utils/environment.cpp \
- $$UTILSDIR/utils/savedaction.cpp \
- $$UTILSDIR/utils/pathchooser.cpp \
- $$UTILSDIR/utils/basevalidatinglineedit.cpp \
+ $$FAKEVIMDIR/fakevimhandler.cpp \
+ $$FAKEVIMDIR/fakevimactions.cpp \
+ $$FAKEVIMDIR/fakevimsyntax.cpp \
tst_fakevim.cpp
HEADERS += \
- $$FAKEVIMDIR/fakevimhandler.h \
- $$FAKEVIMDIR/fakevimactions.h \
- $$FAKEVIMDIR/fakevimsyntax.h \
- $$UTILSDIR/utils/environment.h \
- $$UTILSDIR/utils/savedaction.h \
- $$UTILSDIR/utils/pathchooser.h \
- $$UTILSDIR/utils/basevalidatinglineedit.h \
+ $$FAKEVIMDIR/fakevimhandler.h \
+ $$FAKEVIMDIR/fakevimactions.h \
+ $$FAKEVIMDIR/fakevimsyntax.h \
INCLUDEPATH += $$FAKEVIMDIR $$UTILSDIR
diff --git a/tests/auto/filesearch/filesearch.pro b/tests/auto/filesearch/filesearch.pro
new file mode 100644
index 0000000000..251541fc63
--- /dev/null
+++ b/tests/auto/filesearch/filesearch.pro
@@ -0,0 +1,22 @@
+CONFIG += qtestlib testcase
+TEMPLATE = app
+CONFIG -= app_bundle
+DEFINES += QTCREATOR_UTILS_LIB
+
+include(../../../qtcreator.pri)
+
+UTILS_PATH = $$IDE_SOURCE_TREE/src/libs/utils
+
+INCLUDEPATH += $$UTILS_PATH
+# Input
+SOURCES += tst_filesearch.cpp \
+ $$UTILS_PATH/filesearch.cpp
+HEADERS += $$UTILS_PATH/filesearch.h \
+ $$UTILS_PATH/utils_global.h
+
+TARGET=tst_$$TARGET
+
+OTHER_FILES += testfile.txt
+
+RESOURCES += \
+ tst_filesearch.qrc
diff --git a/tests/auto/filesearch/testfile.txt b/tests/auto/filesearch/testfile.txt
new file mode 100644
index 0000000000..b131ad179b
--- /dev/null
+++ b/tests/auto/filesearch/testfile.txt
@@ -0,0 +1,5 @@
+wholeWordAtStart bla foo blubb wholeWordAtEnd
+search to find multiple find results
+search CaseSensitively for casesensitive
+here you find another result
+wholeWordAtVeryEnd
diff --git a/tests/auto/filesearch/tst_filesearch.cpp b/tests/auto/filesearch/tst_filesearch.cpp
new file mode 100644
index 0000000000..23159150d0
--- /dev/null
+++ b/tests/auto/filesearch/tst_filesearch.cpp
@@ -0,0 +1,102 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 <filesearch.h>
+
+#include <QtTest/QtTest>
+
+bool operator==(const Utils::FileSearchResult &r1, const Utils::FileSearchResult &r2)
+{
+ return r1.fileName == r2.fileName
+ && r1.lineNumber == r2.lineNumber
+ && r1.matchingLine == r2.matchingLine
+ && r1.matchStart == r2.matchStart
+ && r1.matchLength == r2.matchLength
+ && r1.regexpCapturedTexts == r2.regexpCapturedTexts;
+}
+
+class tst_FileSearch : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void multipleResults();
+ void caseSensitive();
+ void caseInSensitive();
+};
+
+namespace {
+ const char * const FILENAME = ":/tst_filesearch/testfile.txt";
+
+ void test_helper(const Utils::FileSearchResultList &expectedResults,
+ const QString &term,
+ QTextDocument::FindFlags flags)
+ {
+ Utils::FileIterator *it = new Utils::FileIterator(QStringList() << QLatin1String(FILENAME), QList<QTextCodec *>() << QTextCodec::codecForLocale());
+ QFutureWatcher<Utils::FileSearchResultList> watcher;
+ QSignalSpy ready(&watcher, SIGNAL(resultsReadyAt(int,int)));
+ watcher.setFuture(Utils::findInFiles(term, it, flags));
+ watcher.future().waitForFinished();
+ QTest::qWait(100); // process events
+ QCOMPARE(ready.count(), 1);
+ Utils::FileSearchResultList results = watcher.resultAt(0);
+ QCOMPARE(results.count(), expectedResults.count());
+ for (int i = 0; i < expectedResults.size(); ++i) {
+ QCOMPARE(results.at(i), expectedResults.at(i));
+ }
+ }
+}
+
+void tst_FileSearch::multipleResults()
+{
+ Utils::FileSearchResultList expectedResults;
+ expectedResults << Utils::FileSearchResult(QLatin1String(FILENAME), 2, QLatin1String("search to find multiple find results"), 10, 4, QStringList());
+ expectedResults << Utils::FileSearchResult(QLatin1String(FILENAME), 2, QLatin1String("search to find multiple find results"), 24, 4, QStringList());
+ expectedResults << Utils::FileSearchResult(QLatin1String(FILENAME), 4, QLatin1String("here you find another result"), 9, 4, QStringList());
+ test_helper(expectedResults, QLatin1String("find"), QTextDocument::FindFlags(0));
+}
+
+void tst_FileSearch::caseSensitive()
+{
+ Utils::FileSearchResultList expectedResults;
+ expectedResults << Utils::FileSearchResult(QLatin1String(FILENAME), 3, QLatin1String("search CaseSensitively for casesensitive"), 7, 13, QStringList());
+ test_helper(expectedResults, QLatin1String("CaseSensitive"), QTextDocument::FindCaseSensitively);
+}
+
+void tst_FileSearch::caseInSensitive()
+{
+ Utils::FileSearchResultList expectedResults;
+ expectedResults << Utils::FileSearchResult(QLatin1String(FILENAME), 3, QLatin1String("search CaseSensitively for casesensitive"), 7, 13, QStringList());
+ expectedResults << Utils::FileSearchResult(QLatin1String(FILENAME), 3, QLatin1String("search CaseSensitively for casesensitive"), 27, 13, QStringList());
+ test_helper(expectedResults, QLatin1String("CaseSensitive"), QTextDocument::FindFlags(0));
+}
+
+QTEST_MAIN(tst_FileSearch)
+
+#include "tst_filesearch.moc"
diff --git a/tests/auto/filesearch/tst_filesearch.qrc b/tests/auto/filesearch/tst_filesearch.qrc
new file mode 100644
index 0000000000..ff0a6b7cdc
--- /dev/null
+++ b/tests/auto/filesearch/tst_filesearch.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/tst_filesearch">
+ <file>testfile.txt</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/generichighlighter/highlighterengine/highlighterengine.pro b/tests/auto/generichighlighter/highlighterengine/highlighterengine.pro
index 80991e37d4..8121e174cf 100644
--- a/tests/auto/generichighlighter/highlighterengine/highlighterengine.pro
+++ b/tests/auto/generichighlighter/highlighterengine/highlighterengine.pro
@@ -1,5 +1,5 @@
+include(../../qttest.pri)
QT += gui
-CONFIG += qtestlib testcase
PLUGINSDIR = ../../../../src/plugins
GENERICHIGHLIGHTERDIR = $$PLUGINSDIR/texteditor/generichighlighter
diff --git a/tests/auto/generichighlighter/highlighterengine/syntaxhighlighter.h b/tests/auto/generichighlighter/highlighterengine/syntaxhighlighter.h
index a254d54a9b..582c435c88 100644
--- a/tests/auto/generichighlighter/highlighterengine/syntaxhighlighter.h
+++ b/tests/auto/generichighlighter/highlighterengine/syntaxhighlighter.h
@@ -35,13 +35,24 @@
#define SYNTAXHIGHLIGHTER_H
// Replaces the "real" syntaxhighlighter.h file. The scope of this test is restricted to the
-// highlight definition's context engine. Using QSyntaxHighlighter as a base instead of the
-// real TextEditor::SyntaxHighlighter should not affect it.
+// highlight definition's context engine. Using a mock derived from QSyntaxHighlighter as a
+// base instead of the real TextEditor::SyntaxHighlighter should not affect it.
#include <QtGui/QSyntaxHighlighter>
namespace TextEditor {
- typedef QSyntaxHighlighter SyntaxHighlighter;
+
+class SyntaxHighlighter : public QSyntaxHighlighter
+{
+public:
+ SyntaxHighlighter(QTextDocument *parent) : QSyntaxHighlighter(parent) {}
+ virtual ~SyntaxHighlighter() {}
+
+protected:
+ void applyFormatToSpaces(const QString &, const QTextCharFormat &)
+ {}
+};
+
}
#endif //SYNTAXHIGHLIGHTER_H
diff --git a/tests/auto/generichighlighter/specificrules/specificrules.pro b/tests/auto/generichighlighter/specificrules/specificrules.pro
index 374456b33c..eea2d409e1 100644
--- a/tests/auto/generichighlighter/specificrules/specificrules.pro
+++ b/tests/auto/generichighlighter/specificrules/specificrules.pro
@@ -1,4 +1,4 @@
-CONFIG += qtestlib testcase
+include(../../qttest.pri)
PLUGINSDIR = ../../../../src/plugins
@@ -13,5 +13,3 @@ SOURCES += tst_specificrules.cpp \
$$PLUGINSDIR/texteditor/generichighlighter/itemdata.cpp
INCLUDEPATH += $$PLUGINSDIR
-
-TARGET=tst_$$TARGET
diff --git a/tests/auto/generichighlighter/specificrules/tst_specificrules.cpp b/tests/auto/generichighlighter/specificrules/tst_specificrules.cpp
index 606b0aa7db..cbc9f66962 100644
--- a/tests/auto/generichighlighter/specificrules/tst_specificrules.cpp
+++ b/tests/auto/generichighlighter/specificrules/tst_specificrules.cpp
@@ -109,8 +109,8 @@ private slots:
private:
void addCommonColumns() const;
- void testMatch(const Rule &rule) const;
- void testMatch(const Rule &rule, ProgressData *progress) const;
+ void testMatch(Rule *rule);
+ void testMatch(Rule *rule, ProgressData *progress);
void noMatchForInt() const;
void noMatchForFloat() const;
@@ -142,17 +142,17 @@ void tst_SpecificRules::addCommonColumns() const
QTest::addColumn<bool>("will continue");
}
-void tst_SpecificRules::testMatch(const Rule &rule) const
+void tst_SpecificRules::testMatch(Rule *rule)
{
ProgressData progress;
testMatch(rule, &progress);
}
-void tst_SpecificRules::testMatch(const Rule &rule, ProgressData *progress) const
+void tst_SpecificRules::testMatch(Rule *rule, ProgressData *progress)
{
QFETCH(QString, s);
- QTEST(rule.matchSucceed(s, s.length(), progress), "match");
+ QTEST(rule->matchSucceed(s, s.length(), progress), "match");
QTEST(progress->offset(), "offset");
QTEST(progress->isOnlySpacesSoFar(), "only spaces");
QTEST(progress->isWillContinueLine(), "will continue");
@@ -164,7 +164,7 @@ void tst_SpecificRules::testDetectChar()
DetectCharRule rule;
rule.setChar(c);
- testMatch(rule);
+ testMatch(&rule);
}
void tst_SpecificRules::testDetectChar_data()
@@ -190,7 +190,7 @@ void tst_SpecificRules::testDetect2Char()
rule.setChar(c);
rule.setChar1(c1);
- testMatch(rule);
+ testMatch(&rule);
}
void tst_SpecificRules::testDetect2Char_data()
@@ -218,7 +218,7 @@ void tst_SpecificRules::testAnyChar()
AnyCharRule rule;
rule.setCharacterSet(chars);
- testMatch(rule);
+ testMatch(&rule);
}
void tst_SpecificRules::testAnyChar_data()
@@ -249,7 +249,7 @@ void tst_SpecificRules::testStringDetect()
rule.setString(referenceString);
rule.setInsensitive(insensitive);
- testMatch(rule);
+ testMatch(&rule);
}
void tst_SpecificRules::testStringDetect_data()
@@ -281,7 +281,7 @@ void tst_SpecificRules::testRegExpr()
rule.setInsensitive(insensitive);
rule.setMinimal(minimal);
- testMatch(rule);
+ testMatch(&rule);
}
void tst_SpecificRules::testRegExpr_data()
@@ -326,7 +326,7 @@ void tst_SpecificRules::testRegExprOffsetIncremented()
ProgressData progress;
progress.setOffset(1);
- testMatch(rule, &progress);
+ testMatch(&rule, &progress);
}
void tst_SpecificRules::testRegExprOffsetIncremented_data()
@@ -392,7 +392,7 @@ void tst_SpecificRules::testKeywordGlobalSensitiveLocalSensitive()
rule.setInsensitive("false");
rule.setList("keywords");
- testMatch(rule);
+ testMatch(&rule);
}
void tst_SpecificRules::testKeywordGlobalSensitiveLocalSensitive_data()
@@ -414,7 +414,7 @@ void tst_SpecificRules::testKeywordGlobalSensitiveLocalInsensitive()
rule.setInsensitive("true");
rule.setList("keywords");
- testMatch(rule);
+ testMatch(&rule);
}
void tst_SpecificRules::testKeywordGlobalSensitiveLocalInsensitive_data()
@@ -436,7 +436,7 @@ void tst_SpecificRules::testKeywordGlobalInsensitiveLocalInsensitive()
rule.setInsensitive("true");
rule.setList("keywords");
- testMatch(rule);
+ testMatch(&rule);
}
void tst_SpecificRules::testKeywordGlobalInsensitiveLocalInsensitive_data()
@@ -451,7 +451,7 @@ void tst_SpecificRules::testKeywordGlobalInsensitiveLocalSensitive()
rule.setInsensitive("false");
rule.setList("keywords");
- testMatch(rule);
+ testMatch(&rule);
}
void tst_SpecificRules::testKeywordGlobalInsensitiveLocalSensitive_data()
@@ -514,7 +514,7 @@ void tst_SpecificRules::noMatchForNumber() const
void tst_SpecificRules::testInt()
{
IntRule rule;
- testMatch(rule);
+ testMatch(&rule);
}
void tst_SpecificRules::testInt_data()
@@ -538,7 +538,7 @@ void tst_SpecificRules::testInt_data()
void tst_SpecificRules::testFloat()
{
FloatRule rule;
- testMatch(rule);
+ testMatch(&rule);
}
void tst_SpecificRules::testFloat_data()
@@ -572,7 +572,7 @@ void tst_SpecificRules::testFloat_data()
void tst_SpecificRules::testCOctal()
{
HlCOctRule rule;
- testMatch(rule);
+ testMatch(&rule);
}
void tst_SpecificRules::testCOctal_data()
@@ -593,7 +593,7 @@ void tst_SpecificRules::testCOctal_data()
void tst_SpecificRules::testCHex()
{
HlCHexRule rule;
- testMatch(rule);
+ testMatch(&rule);
}
void tst_SpecificRules::testCHex_data()
@@ -613,7 +613,7 @@ void tst_SpecificRules::testCHex_data()
void tst_SpecificRules::testCString()
{
HlCStringCharRule rule;
- testMatch(rule);
+ testMatch(&rule);
}
void tst_SpecificRules::testCString_data()
@@ -660,7 +660,7 @@ void tst_SpecificRules::testCString_data()
void tst_SpecificRules::testCChar()
{
HlCCharRule rule;
- testMatch(rule);
+ testMatch(&rule);
}
void tst_SpecificRules::testCChar_data()
@@ -696,7 +696,7 @@ void tst_SpecificRules::testRangeDetect()
rule.setChar(c);
rule.setChar1(c1);
- testMatch(rule);
+ testMatch(&rule);
}
void tst_SpecificRules::testRangeDetect_data()
@@ -723,7 +723,7 @@ void tst_SpecificRules::testRangeDetect_data()
void tst_SpecificRules::testLineContinue()
{
LineContinueRule rule;
- testMatch(rule);
+ testMatch(&rule);
}
void tst_SpecificRules::testLineContinue_data()
@@ -741,7 +741,7 @@ void tst_SpecificRules::testLineContinue_data()
void tst_SpecificRules::testDetectSpaces()
{
DetectSpacesRule rule;
- testMatch(rule);
+ testMatch(&rule);
}
void tst_SpecificRules::testDetectSpaces_data()
@@ -758,7 +758,7 @@ void tst_SpecificRules::testDetectSpaces_data()
void tst_SpecificRules::testDetectIdentifier()
{
DetectIdentifierRule rule;
- testMatch(rule);
+ testMatch(&rule);
}
void tst_SpecificRules::testDetectIdentifier_data()
diff --git a/tests/auto/icheckbuild/parsemanager.h b/tests/auto/icheckbuild/parsemanager.h
index e04755c7d7..f6b60d68d1 100644
--- a/tests/auto/icheckbuild/parsemanager.h
+++ b/tests/auto/icheckbuild/parsemanager.h
@@ -52,7 +52,7 @@
** chParseManager->parse(chFilelist);
**
** if(!chParseManager->checkAllMetadatas(iParseManager)){
-** cout << "Folowing interface items are missing:" << endl;
+** cout << "Following interface items are missing:" << endl;
** QStringList errorlist = chParseManager->getErrorMsg();
** foreach(QString msg, errorlist){
** cout << (const char *)msg.toLatin1() << endl;
diff --git a/tests/auto/ioutils/ioutils.pro b/tests/auto/ioutils/ioutils.pro
new file mode 100644
index 0000000000..dfeb477134
--- /dev/null
+++ b/tests/auto/ioutils/ioutils.pro
@@ -0,0 +1,13 @@
+CONFIG += qtestlib testcase
+TEMPLATE = app
+CONFIG -= app_bundle
+
+UTILS_PATH = ../../../src/shared/proparser
+
+INCLUDEPATH += $$UTILS_PATH
+DEPENDPATH += $$UTILS_PATH
+
+SOURCES += \
+ tst_ioutils.cpp
+
+TARGET = tst_$$TARGET
diff --git a/tests/auto/ioutils/tst_ioutils.cpp b/tests/auto/ioutils/tst_ioutils.cpp
new file mode 100644
index 0000000000..50f9d05958
--- /dev/null
+++ b/tests/auto/ioutils/tst_ioutils.cpp
@@ -0,0 +1,87 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** No Commercial Usage
+**
+** This file 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.
+**
+**************************************************************************/
+
+#include "../../../src/shared/proparser/ioutils.cpp"
+
+#include <QtTest/QtTest>
+
+class tst_IoUtils : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void quoteArg_data();
+ void quoteArg();
+};
+
+void tst_IoUtils::quoteArg_data()
+{
+ QTest::addColumn<QString>("in");
+ QTest::addColumn<QString>("out");
+
+ static const struct {
+ const char * const in;
+ const char * const out;
+ } vals[] = {
+#ifdef Q_OS_WIN
+ { "", "\"\"" },
+ { "hallo", "hallo" },
+ { "hallo du", "\"hallo du\"" },
+ { "hallo\\", "hallo\\" },
+ { "hallo du\\", "\"hallo du\"\\" },
+ { "ha\"llo", "\"ha\"\\^\"\"llo\"" },
+ { "ha\\\"llo", "\"ha\"\\\\\\^\"\"llo\"" },
+#else
+ { "", "\"\"" },
+ { "hallo", "hallo" },
+ { "hallo du", "'hallo du'" },
+ { "ha'llo", "'ha'\\''llo'" },
+#endif
+ };
+
+ for (unsigned i = 0; i < sizeof(vals)/sizeof(vals[0]); i++)
+ QTest::newRow(vals[i].in) << QString::fromLatin1(vals[i].in)
+ << QString::fromLatin1(vals[i].out);
+}
+
+void tst_IoUtils::quoteArg()
+{
+ QFETCH(QString, in);
+ QFETCH(QString, out);
+
+ QCOMPARE(IoUtils::shellQuote(in), out);
+}
+
+QTEST_MAIN(tst_IoUtils)
+
+#include "tst_ioutils.moc"
diff --git a/tests/auto/profilereader/data/includefiles/pri.cpp b/tests/auto/profilereader/data/includefiles/pri.cpp
deleted file mode 100644
index e69de29bb2..0000000000
--- a/tests/auto/profilereader/data/includefiles/pri.cpp
+++ /dev/null
diff --git a/tests/auto/profilereader/data/includefiles/pro.cpp b/tests/auto/profilereader/data/includefiles/pro.cpp
deleted file mode 100644
index e69de29bb2..0000000000
--- a/tests/auto/profilereader/data/includefiles/pro.cpp
+++ /dev/null
diff --git a/tests/auto/profilereader/data/includefiles/test.pri b/tests/auto/profilereader/data/includefiles/test.pri
deleted file mode 100644
index 6a25f2a87a..0000000000
--- a/tests/auto/profilereader/data/includefiles/test.pri
+++ /dev/null
@@ -1 +0,0 @@
-SOURCES += pri.cpp
diff --git a/tests/auto/profilereader/data/includefiles/test.pro b/tests/auto/profilereader/data/includefiles/test.pro
deleted file mode 100644
index 2939b5fbfd..0000000000
--- a/tests/auto/profilereader/data/includefiles/test.pro
+++ /dev/null
@@ -1,6 +0,0 @@
-include(test.pri)
-
-SOURCES += pro.cpp
-
-CONFIG += testscope
-testscope:SCOPED_VARIABLE = 1
diff --git a/tests/auto/profilereader/profilecache.h b/tests/auto/profilereader/profilecache.h
deleted file mode 100644
index d17885be97..0000000000
--- a/tests/auto/profilereader/profilecache.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#ifndef PROFILECACHE_H
-#define PROFILECACHE_H
-
-#include <proitems.h>
-#include <QString>
-
-namespace Qt4ProjectManager {
-namespace Internal {
-
-class ProFileCache {
-public:
- ProFile *proFile(const QString &arg)
- { return new ProFile(arg); }
-};
-
-} // namespace Internal
-} // namespace Qt4ProjectManager
-
-#endif // PROFILECACHE_H
diff --git a/tests/auto/profilereader/profilereader.pro b/tests/auto/profilereader/profilereader.pro
deleted file mode 100644
index 3e807d1a17..0000000000
--- a/tests/auto/profilereader/profilereader.pro
+++ /dev/null
@@ -1,12 +0,0 @@
-TEMPLATE = app
-CONFIG += qt warn_on console depend_includepath
-CONFIG += qtestlib testcase
-
-SOURCES += \
- tst_profilereader.cpp
-
-HEADERS += \
- profilecache.h \
- qtversionmanager.h
-
-TARGET=tst_$$TARGET
diff --git a/tests/auto/profilereader/qtversionmanager.h b/tests/auto/profilereader/qtversionmanager.h
deleted file mode 100644
index 5385d823fa..0000000000
--- a/tests/auto/profilereader/qtversionmanager.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#ifndef QTVERSIONMANAGER_H
-#define QTVERSIONMANAGER_H
-
-#include <QtCore/QString>
-
-class QtVersion
-{
-public:
- QString path() { return QString(); }
- QString sourcePath() { return QString(); }
- QHash<QString, QString> versionInfo() { return QHash<QString, QString>(); }
-};
-
-#endif // QTVERSIONMANAGER_H
diff --git a/tests/auto/profilereader/sync b/tests/auto/profilereader/sync
deleted file mode 100755
index 9dcbc91dca..0000000000
--- a/tests/auto/profilereader/sync
+++ /dev/null
@@ -1,114 +0,0 @@
-#!/usr/bin/perl -w
-
-use strict;
-use Cwd;
-use File::Copy;
-use File::Basename;
-use IO::File;
-use File::Spec;
-use File::Path;
-
-# --------------------------------
-sub copyFiles
-{
- my ($srcDir, $destDir, @files) = @_;
- unless (-d $destDir) {
- mkpath $destDir;
- }
- die ('No directory ' . $srcDir) unless -d $srcDir;
- die ('No directory ' . $destDir) unless -d $destDir;
- foreach (@files) {
- my $src = File::Spec->catfile($srcDir, $_);
- print 'syncing ', $src, "...\n";
- my $dest = File::Spec->catfile($destDir, $_);
- if (-f $dest) {
- unlink($dest) or die ('Unable to delete existing ' . $dest . ' :' . $!);
- }
- copy($src, $dest) || die ($0 . ': Unable to copy ' . $src . ': ' . $! . "\n");
- chmod 0644, $destDir . $_;
- }
-}
-
-# -----------------------------------------
-sub showUsage
-{
- print "$0 usage:\n";
- print " -qtdir <dir> Set directory for Qt (default: use qmake to figure out)\n";
- print " -help This help\n";
- exit 0;
-}
-
-my $currentDir = getcwd;
-my @files;
-
-my $qtSrcTree = '';
-
-# Parse arguments
-while ( @ARGV ) {
- my $var = 0;
- my $val = 0;
-
- #parse
- my $arg = shift @ARGV;
- if ("$arg" eq "-h" || "$arg" eq "-help" || "$arg" eq "--help" || "$arg" eq "?" || "$arg" eq "/?" || "$arg" eq "-?") {
- showUsage();
- exit(0);
- } elsif ("$arg" eq "-qtdir") {
- $qtSrcTree = shift @ARGV;
- } else {
- print "Unknown option: $arg\n";
- showUsage();
- exit(1);
- }
-}
-
-# If QTDIR is not set, use qmake to figure it out
-if (!$qtSrcTree) {
- my $qmakeInfo = `qmake -v` or die "Couldn't run qmake!";
- chomp($qmakeInfo);
- $qmakeInfo =~ m/Using Qt version .* in (.*)lib$/;
- $qtSrcTree = $1;
- # read Qt source directory from .qmake.cache
- my $fh = IO::File->new();
- $fh->open($qtSrcTree . '.qmake.cache');
- while (defined (my $line = $fh->getline())) {
- # parse line
- # QT_SOURCE_TREE = $$quote(/home/kkoehne/dev/qt)
- if ($line =~ /^\s*QT_SOURCE_TREE\s*=/) {
- $qtSrcTree = $line;
- $qtSrcTree =~ s/^QT_SOURCE_TREE\s*=\s*(\$\$quote\()?//g;
- $qtSrcTree =~ s/\)?\n//g;
- }
- }
- print "Detected qt source directory: " . $qtSrcTree . "\n";
- $fh->close();
-}
-$qtSrcTree =~ s/\\/\//g;
-
-
-# if the sources can't be found, check for shadow builds.
-my $preprocessor_h = File::Spec->catfile($qtSrcTree, 'src', 'tools', 'moc', 'preprocessor.h');
-
-my $qtsrcdirEnv = $ENV{'QTSRCDIR'};
-if (defined $qtsrcdirEnv) {
- if ((! -e $preprocessor_h) && ($qtsrcdirEnv ne '')) {
- $qtSrcTree = $qtsrcdirEnv;
- }
-}
-
-# copy files for Qt4ProjectManager
-
-
-@files = ( 'proitems.h',
- 'abstractproitemvisitor.h',
- 'proparserutils.h',
- 'profileevaluator.h',
-
- 'proitems.cpp',
- 'profileevaluator.cpp' );
-
-copyFiles(File::Spec->catfile($qtSrcTree, 'tools', 'linguist', 'shared'), $currentDir,@files);
-
-@files = ( 'profilereader.h',
- 'profilereader.cpp');
-copyFiles(File::Spec->catfile('..', '..', '..', 'src', 'plugins', 'qt4projectmanager'), $currentDir, @files)
diff --git a/tests/auto/profilereader/tst_profilereader.cpp b/tests/auto/profilereader/tst_profilereader.cpp
deleted file mode 100644
index 65fc7b0f06..0000000000
--- a/tests/auto/profilereader/tst_profilereader.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#include "profilecache.h"
-
-#include <QtTest/QtTest>
-#include <QtCore/QSet>
-
-using Qt4ProjectManager::Internal::ProFileReader;
-using Qt4ProjectManager::Internal::ProFileCache;
-
-
-class tst_ProFileReader : public QObject
-{
- Q_OBJECT
-
-private slots:
- void readProFile();
- void includeFiles();
- void conditionalScopes();
-};
-
-void tst_ProFileReader::readProFile()
-{
- ProFileReader reader;
- QCOMPARE(reader.readProFile("nonexistant"), false);
- QCOMPARE(reader.readProFile("data/includefiles/test.pro"), true);
-}
-
-void tst_ProFileReader::includeFiles()
-{
- ProFileReader reader;
- QCOMPARE(reader.readProFile("data/includefiles/test.pro"), true);
- QCOMPARE(reader.includeFiles().size(), 2);
-}
-
-void tst_ProFileReader::conditionalScopes()
-{
- ProFileReader reader;
- QCOMPARE(reader.readProFile("data/includefiles/test.pro"), true);
-
- QStringList scopedVariable = reader.values("SCOPED_VARIABLE");
- QCOMPARE(scopedVariable.count(), 1);
- QCOMPARE(scopedVariable.first(), QLatin1String("1"));
-}
-
-QTEST_MAIN(tst_ProFileReader)
-#include "tst_profilereader.moc"
diff --git a/tests/auto/qml/codemodel/basic/basic.pro b/tests/auto/qml/codemodel/basic/basic.pro
new file mode 100644
index 0000000000..90072f8c6d
--- /dev/null
+++ b/tests/auto/qml/codemodel/basic/basic.pro
@@ -0,0 +1,45 @@
+TEMPLATE = app
+
+# this build works only in-source or inside a qtcreator shadow
+# build if the test's shadow build directory is QTC-BUILD/tests/auto/qml/codemodel/basic
+
+QTCREATOR_SOURCE=$$PWD/../../../../..
+QTCREATOR_BUILD=$$OUT_PWD/../../../../..
+# can we check that this is a valid build dir?
+
+OUT_PWD_SAVE=$$OUT_PWD
+OUT_PWD=QTCREATOR_BUILD
+include($$QTCREATOR_SOURCE/qtcreator.pri)
+OUT_PWD=$$OUT_PWD_SAVE
+
+
+LIBS += -L$$IDE_PLUGIN_PATH/Nokia
+
+unix: QMAKE_LFLAGS += \'-Wl,-rpath,$${IDE_LIBRARY_PATH}\' \'-Wl,-rpath,$${IDE_PLUGIN_PATH}/Nokia\'
+
+QT += core network
+
+CONFIG += qtestlib testcase
+
+# DEFINES+=QTCREATOR_UTILS_STATIC_LIB QML_BUILD_STATIC_LIB
+DEFINES+=QTCREATORDIR=\\\"$$IDE_SOURCE_TREE\\\"
+DEFINES+=QT_CREATOR QTCREATOR_TEST
+
+DEPENDPATH += .
+
+include($$IDE_SOURCE_TREE/src/libs/utils/utils.pri)
+include($$IDE_SOURCE_TREE/src/plugins/qmljstools/qmljstools.pri)
+
+
+TARGET = tst_codemodel_basic
+win32: DESTDIR = $$IDE_APP_PATH
+
+
+CONFIG += console
+CONFIG -= app_bundle
+HEADERS += \
+ metainfo.h
+
+SOURCES += \
+ tst_basic.cpp \
+ metainfo.cpp
diff --git a/tests/auto/qml/codemodel/basic/tst_basic.cpp b/tests/auto/qml/codemodel/basic/tst_basic.cpp
new file mode 100644
index 0000000000..dde6894a49
--- /dev/null
+++ b/tests/auto/qml/codemodel/basic/tst_basic.cpp
@@ -0,0 +1,244 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 <QScopedPointer>
+#include <QLatin1String>
+#include <QGraphicsObject>
+#include <QApplication>
+#include <QSettings>
+#include <QFileInfo>
+
+#include <qmljs/qmljsinterpreter.h>
+#include <qmljs/qmljsdocument.h>
+#include <qmljs/qmljsbind.h>
+#include <qmljs/qmljslookupcontext.h>
+#include <qmljs/parser/qmljsast_p.h>
+#include <qmljstools/qmljsrefactoringchanges.h>
+#include <qmljstools/qmljsmodelmanager.h>
+
+#include <QtTest>
+
+using namespace QmlJS;
+using namespace QmlJSTools;
+
+class tst_Basic : public QObject
+{
+ Q_OBJECT
+public:
+ tst_Basic();
+
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+ void basicObjectTests();
+ void testMetaInfo();
+};
+
+
+#ifdef Q_OS_MAC
+# define SHARE_PATH "/Resources"
+#else
+# define SHARE_PATH "/share/qtcreator"
+#endif
+
+
+QString resourcePath()
+{
+ return QDir::cleanPath(QTCREATORDIR + QLatin1String(SHARE_PATH));
+}
+
+class TestModelManager : public Internal::ModelManager
+{
+public:
+ TestModelManager() : Internal::ModelManager()
+ {
+ loadQmlTypeDescriptions(resourcePath());
+ }
+ void loadFile(QString fileName)
+ {
+ refreshSourceFiles(QStringList() << fileName, false).waitForFinished();
+ }
+};
+
+tst_Basic::tst_Basic()
+{
+}
+
+void tst_Basic::initTestCase()
+{
+}
+
+void tst_Basic::cleanupTestCase()
+{
+}
+
+void tst_Basic::basicObjectTests()
+{
+ TestModelManager modelManager;
+
+ modelManager.loadFile(QString(QTCREATORDIR) + "/tests/auto/qml/qmldesigner/data/fx/usingmybutton.qml");
+
+ Snapshot snapshot = modelManager.snapshot();
+ Document::Ptr doc = snapshot.document(QString(QTCREATORDIR) + "/tests/auto/qml/qmldesigner/data/fx/usingmybutton.qml");
+ QVERIFY(doc && doc->isQmlDocument());
+
+ LookupContext::Ptr lookupContext = LookupContext::create(doc, snapshot, QList<AST::Node*>());
+ QVERIFY(lookupContext);
+
+ QVERIFY(lookupContext->engine()->cppQmlTypes().types().value("QtQuick.Rectangle 1.0"));
+ QVERIFY(!lookupContext->engine()->cppQmlTypes().types().value("QtQuick.Rectangle 1.0")->isWritable("border"));
+ QVERIFY(lookupContext->engine()->cppQmlTypes().types().value("QtQuick.Rectangle 1.0")->hasProperty("border"));
+ QVERIFY(lookupContext->engine()->cppQmlTypes().types().value("QtQuick.Rectangle 1.0")->isPointer("border"));
+ QVERIFY(lookupContext->engine()->cppQmlTypes().types().value("QtQuick.Rectangle 1.0")->isWritable("color"));
+ QVERIFY(!lookupContext->engine()->cppQmlTypes().types().value("QtQuick.Rectangle 1.0")->isPointer("color"));
+
+ const Interpreter::ObjectValue *ovItem = lookupContext->context()->lookupType(doc.data(), QStringList() << "Item");
+ QCOMPARE(ovItem->className(), QString("Item"));
+ QCOMPARE(lookupContext->context()->scopeChain().qmlTypes->importInfo("Item", lookupContext->context()).name(), QString("Qt"));
+ const Interpreter::ObjectValue *ovButton = lookupContext->context()->lookupType(doc.data(), QStringList() << "MyButton");
+ QCOMPARE(ovButton->className(), QString("MyButton"));
+ QCOMPARE(ovButton->prototype(lookupContext->context())->className(), QString("Rectangle"));
+
+ const Interpreter::ObjectValue *ovProperty = lookupContext->context()->lookupType(doc.data(), QStringList() << "Item" << "states");
+ QVERIFY(ovProperty);
+ QCOMPARE(ovProperty->className(), QString("State"));
+
+ const Interpreter::QmlObjectValue * qmlItemValue = dynamic_cast<const Interpreter::QmlObjectValue *>(ovItem);
+ QVERIFY(qmlItemValue);
+ QCOMPARE(qmlItemValue->defaultPropertyName(), QString("data"));
+ QCOMPARE(qmlItemValue->propertyType("state"), QString("string"));
+
+ const Interpreter::ObjectValue *ovState = lookupContext->context()->lookupType(doc.data(), QStringList() << "State");
+ const Interpreter::QmlObjectValue * qmlState2Value = dynamic_cast<const Interpreter::QmlObjectValue *>(ovState);
+ QCOMPARE(qmlState2Value->className(), QString("State"));
+
+ const Interpreter::ObjectValue *ovImage = lookupContext->context()->lookupType(doc.data(), QStringList() << "Image");
+ const Interpreter::QmlObjectValue * qmlImageValue = dynamic_cast<const Interpreter::QmlObjectValue *>(ovImage);
+ QCOMPARE(qmlImageValue->className(), QString("Image"));
+ QCOMPARE(qmlImageValue->propertyType("source"), QString("QUrl"));
+}
+
+void tst_Basic::testMetaInfo()
+{
+ TestModelManager modelManager;
+
+ modelManager.loadFile(QString(QTCREATORDIR) + "/tests/auto/qml/qmldesigner/data/fx/usingmybutton.qml");
+
+ Snapshot snapshot = modelManager.snapshot();
+ Document::Ptr doc = snapshot.document(QString(QTCREATORDIR) + "/tests/auto/qml/qmldesigner/data/fx/usingmybutton.qml");
+ QVERIFY(doc && doc->isQmlDocument());
+
+ LookupContext::Ptr lookupContext = LookupContext::create(doc, snapshot, QList<AST::Node*>());
+
+ MetaInfo::setDocument(doc);
+ MetaInfo::setLookupContext(lookupContext);
+
+ MetaInfo item("Qt/Item", 4, 7);
+ MetaInfo myButton("MyButton");
+ MetaInfo textEdit("TextEdit");
+ MetaInfo super("Qt/Super", 4, 7);
+ MetaInfo maniac("Maniac");
+
+ QVERIFY(item.isValid());
+ QVERIFY(myButton.isValid());
+ QVERIFY(textEdit.isValid());
+
+ QVERIFY(!super.isValid());
+ QVERIFY(!maniac.isValid());
+
+ QVERIFY(textEdit.localProperties().contains("color"));
+ QVERIFY(textEdit.isPropertyWritable("color"));
+ MetaInfo text("Qt/Text", 4, 7);
+
+ QVERIFY(item.isValid());
+ QVERIFY(myButton.isValid());
+
+ QVERIFY(!item.isComponent());
+ QVERIFY(myButton.isComponent());
+
+ QVERIFY(myButton.properties().contains("text"));
+ QVERIFY(myButton.properties().contains("myNumber"));
+ QVERIFY(myButton.properties().contains("gradient"));
+ QVERIFY(myButton.properties().contains("border.width"));
+ QVERIFY(myButton.properties().contains("anchors.bottomMargin"));
+ QVERIFY(myButton.localProperties().contains("text"));
+ QVERIFY(myButton.localProperties().contains("myNumber"));
+ QVERIFY(!myButton.localProperties().contains("border.width"));
+
+ QVERIFY(!item.properties().contains("text"));
+ QVERIFY(!item.properties().contains("myNumber"));
+ QVERIFY(item.properties().contains("anchors.bottomMargin"));
+ QVERIFY(item.properties().contains("x"));
+ QVERIFY(!item.localProperties().contains("x"));
+ QVERIFY(!item.localProperties().contains("enabled"));
+ QVERIFY(item.localProperties().contains("anchors.bottomMargin"));
+ QVERIFY(item.localProperties().contains("states"));
+ QVERIFY(item.localProperties().contains("parent"));
+
+ QCOMPARE(myButton.propertyTypeName("text"), QString("string"));
+ QCOMPARE(myButton.propertyTypeName("myNumber"), QString("real"));
+ QCOMPARE(myButton.propertyTypeName("x"), QString("qreal"));
+ QCOMPARE(myButton.propertyTypeName("border.width"), QString("int"));
+ QCOMPARE(myButton.propertyTypeName("gradient"), QString("Qt/Gradient"));
+
+ QCOMPARE(myButton.defaultPropertyName(), QString("content"));
+ QCOMPARE(item.defaultPropertyName(), QString("data"));
+
+ QVERIFY(item.isPropertyList("children"));
+ QVERIFY(myButton.isPropertyList("children"));
+ QVERIFY(item.isPropertyList("data"));
+ QVERIFY(myButton.isPropertyList("data"));
+ QVERIFY(item.isPropertyList("states"));
+ QVERIFY(myButton.isPropertyList("states"));
+
+ QVERIFY(!item.isPropertyList("x"));
+ QVERIFY(!myButton.isPropertyList("x"));
+ QVERIFY(!item.isPropertyList("state"));
+ QVERIFY(!myButton.isPropertyList("state"));
+
+ QVERIFY(myButton.isPropertyPointer("parent"));
+ QVERIFY(text.localProperties().contains("font"));
+ QVERIFY(!text.isPropertyPointer("font"));
+ QVERIFY(myButton.isPropertyWritable("state"));
+ QVERIFY(!myButton.isPropertyWritable("border"));
+
+ QVERIFY(text.localProperties().contains("horizontalAlignment"));
+ QVERIFY(text.isPropertyEnum("horizontalAlignment"));
+
+ foreach (Interpreter::ImportInfo import, doc->bind()->imports()) {
+ QCOMPARE(import.name(), QString("Qt"));
+ }
+}
+
+QTEST_MAIN(tst_Basic);
+
+#include "tst_basic.moc"
diff --git a/tests/auto/qml/codemodel/codemodel.pro b/tests/auto/qml/codemodel/codemodel.pro
new file mode 100644
index 0000000000..25867e50d7
--- /dev/null
+++ b/tests/auto/qml/codemodel/codemodel.pro
@@ -0,0 +1,3 @@
+TEMPLATE = subdirs
+
+SUBDIRS += basic
diff --git a/tests/auto/qml/qml.pro b/tests/auto/qml/qml.pro
index 2a9535262d..ab1589b604 100644
--- a/tests/auto/qml/qml.pro
+++ b/tests/auto/qml/qml.pro
@@ -2,4 +2,5 @@ TEMPLATE = subdirs
SUBDIRS += qmldesigner \
# qmleditor \
- qmlprojectmanager
+ qmlprojectmanager \
+ codemodel
diff --git a/tests/auto/qml/qmldesigner/common/statichelpers.cpp b/tests/auto/qml/qmldesigner/common/statichelpers.cpp
index f2494c16bb..384cea05a3 100644
--- a/tests/auto/qml/qmldesigner/common/statichelpers.cpp
+++ b/tests/auto/qml/qmldesigner/common/statichelpers.cpp
@@ -123,7 +123,7 @@ static bool compareTree(const ModelNode &node1, const ModelNode &node2)
return false;
}
- // Compare list of childs
+ // Compare list of children
{
const QList<ModelNode> childList1 = node1.allDirectSubModelNodes();
const QList<ModelNode> childList2 = node2.allDirectSubModelNodes();
diff --git a/tests/auto/qml/qmldesigner/coretests/coretests.pro b/tests/auto/qml/qmldesigner/coretests/coretests.pro
index 0b323b24ba..f129c9d52a 100644
--- a/tests/auto/qml/qmldesigner/coretests/coretests.pro
+++ b/tests/auto/qml/qmldesigner/coretests/coretests.pro
@@ -1,14 +1,14 @@
-include(../../../../../qtcreator.pri)
+include(../../../qttest.pri)
+
include($$IDE_SOURCE_TREE/src/plugins/qmldesigner/config.pri)
QT += script \
network \
- declarative
-
-CONFIG += qtestlib testcase
+ declarative \
+ webkit
# DEFINES+=QTCREATOR_UTILS_STATIC_LIB QML_BUILD_STATIC_LIB
-DEFINES+=QTCREATORDIR=\\\"$$IDE_SOURCE_TREE\\\"
+DEFINES+=QTCREATORDIR=\\\"$$IDE_BUILD_TREE\\\"
DEFINES+=QT_CREATOR QTCREATOR_TEST
DEPENDPATH += ..
@@ -20,8 +20,6 @@ include($$IDE_SOURCE_TREE/src/plugins/qmldesigner/designercore/designercore.pri)
include($$IDE_SOURCE_TREE/src/libs/utils/utils-lib.pri)
include($$IDE_SOURCE_TREE/src/libs/qmljs/qmljs-lib.pri)
-TARGET = tst_qmldesigner_core
-
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
diff --git a/tests/auto/qml/qmldesigner/data/fx/MyButton.qml b/tests/auto/qml/qmldesigner/data/fx/MyButton.qml
index d6d32e4668..3ab43139cb 100644
--- a/tests/auto/qml/qmldesigner/data/fx/MyButton.qml
+++ b/tests/auto/qml/qmldesigner/data/fx/MyButton.qml
@@ -2,9 +2,12 @@ import Qt 4.7
Rectangle {
property string text: "test"
+ property real myNumber: 10
+ default property alias content: text.children
width: 200
height: 200
Text {
+ id: text
anchors.fill: parent
}
diff --git a/tests/auto/qml/qmldesigner/propertyeditortests/propertyeditortests.pro b/tests/auto/qml/qmldesigner/propertyeditortests/propertyeditortests.pro
index 7298d2675f..1abde74235 100644
--- a/tests/auto/qml/qmldesigner/propertyeditortests/propertyeditortests.pro
+++ b/tests/auto/qml/qmldesigner/propertyeditortests/propertyeditortests.pro
@@ -1,5 +1,5 @@
TEMPLATE = app
-QT += script declarative
+QT += script declarative webkit
CONFIG += qtestlib testcase
CONFIG += console
CONFIG -= app_bundle
diff --git a/tests/auto/qml/qmleditor/qmlcodeformatter/qmlcodeformatter.pro b/tests/auto/qml/qmleditor/qmlcodeformatter/qmlcodeformatter.pro
index 6464c16bb4..54797eb7ea 100644
--- a/tests/auto/qml/qmleditor/qmlcodeformatter/qmlcodeformatter.pro
+++ b/tests/auto/qml/qmleditor/qmlcodeformatter/qmlcodeformatter.pro
@@ -12,11 +12,11 @@ include($$SRCDIR/libs/utils/utils-lib.pri)
SOURCES += \
tst_qmlcodeformatter.cpp \
- $$SRCDIR/plugins/qmljseditor/qmljseditorcodeformatter.cpp \
+ $$SRCDIR/plugins/qmljstools/qmljsqtstylecodeformatter.cpp \
$$SRCDIR/plugins/texteditor/basetextdocumentlayout.cpp
HEADERS += \
- $$SRCDIR/plugins/qmljseditor/qmljseditorcodeformatter.h \
- $$SRCDIR/plugins/texteditor/basetextdocumentlayout.h \
+ $$SRCDIR/plugins/qmljstools/qmljseditorcodeformatter.h \
+ $$SRCDIR/plugins/texteditor/basetextdocumentlayout.h
INCLUDEPATH += $$SRCDIR/plugins $$SRCDIR/libs
diff --git a/tests/auto/qml/qmleditor/qmlcodeformatter/tst_qmlcodeformatter.cpp b/tests/auto/qml/qmleditor/qmlcodeformatter/tst_qmlcodeformatter.cpp
index 9b0d05d12e..a8b0c42240 100644
--- a/tests/auto/qml/qmleditor/qmlcodeformatter/tst_qmlcodeformatter.cpp
+++ b/tests/auto/qml/qmleditor/qmlcodeformatter/tst_qmlcodeformatter.cpp
@@ -4,9 +4,9 @@
#include <QTextDocument>
#include <QTextBlock>
-#include <qmljseditor/qmljseditorcodeformatter.h>
+#include <qmljstools/qmljsqtstylecodeformatter.h>
-using namespace QmlJSEditor;
+using namespace QmlJSTools;
class tst_QMLCodeFormatter: public QObject
{
@@ -27,6 +27,7 @@ private Q_SLOTS:
void signalDeclarations();
void ifBinding1();
void ifBinding2();
+ void ifBinding3();
void ifStatementWithoutBraces1();
void ifStatementWithoutBraces2();
void ifStatementWithBraces1();
@@ -431,6 +432,36 @@ void tst_QMLCodeFormatter::ifBinding2()
checkIndent(data);
}
+void tst_QMLCodeFormatter::ifBinding3()
+{
+ QList<Line> data;
+ data << Line("A.Rectangle {")
+ << Line(" foo: bar")
+ << Line(" x: if (a) 1")
+ << Line(" x: if (a)")
+ << Line(" 1")
+ << Line(" x: if (a) 1;")
+ << Line(" x: if (a)")
+ << Line(" 1;")
+ << Line(" x: if (a) 1; else 2")
+ << Line(" x: if (a) 1")
+ << Line(" else 2")
+ << Line(" x: if (a) 1;")
+ << Line(" else 2")
+ << Line(" x: if (a) 1;")
+ << Line(" else")
+ << Line(" 2")
+ << Line(" x: if (a)")
+ << Line(" 1")
+ << Line(" else")
+ << Line(" 2")
+ << Line(" x: if (a) 1; else 2;")
+ << Line(" x: 1")
+ << Line("}")
+ ;
+ checkIndent(data);
+}
+
void tst_QMLCodeFormatter::ifStatementWithoutBraces1()
{
QList<Line> data;
diff --git a/tests/auto/qml/qmlprojectmanager/fileformat/fileformat.pro b/tests/auto/qml/qmlprojectmanager/fileformat/fileformat.pro
index 650c12a68a..ec195534d9 100644
--- a/tests/auto/qml/qmlprojectmanager/fileformat/fileformat.pro
+++ b/tests/auto/qml/qmlprojectmanager/fileformat/fileformat.pro
@@ -1,8 +1,4 @@
-TEMPLATE = app
-
-CONFIG += qt warn_on console depend_includepath
-CONFIG -= app_bundle
-CONFIG += qtestlib testcase
+include(../../../qttest.pri)
QT += script \
declarative
@@ -13,8 +9,6 @@ include($$PLUGIN_DIR/fileformat/fileformat.pri)
INCLUDEPATH += $$PLUGIN_DIR/fileformat
-TARGET=tst_$$TARGET
-
DEFINES += SRCDIR=\\\"$$PWD\\\"
TEMPLATE = app
diff --git a/tests/auto/qml/qmlprojectmanager/fileformat/tst_fileformat.cpp b/tests/auto/qml/qmlprojectmanager/fileformat/tst_fileformat.cpp
index ac89ce956a..26df3cf7b5 100644
--- a/tests/auto/qml/qmlprojectmanager/fileformat/tst_fileformat.cpp
+++ b/tests/auto/qml/qmlprojectmanager/fileformat/tst_fileformat.cpp
@@ -20,6 +20,7 @@ private slots:
void testFileFilter();
void testMatchesFile();
void testLibraryPaths();
+ void testMainFile();
};
tst_FileFormat::tst_FileFormat()
@@ -208,6 +209,64 @@ void tst_FileFormat::testFileFilter()
qDebug() << project->files().toSet() << expectedFiles.toSet();
QCOMPARE(project->files().toSet(), expectedFiles.toSet());
}
+
+ //
+ // use wildcards
+ //
+ projectFile = QLatin1String(
+ "import QmlProject 1.0\n"
+ "Project {\n"
+ " ImageFiles {\n"
+ " filter: \"?mage.[gf]if\"\n"
+ " }\n"
+ "}\n");
+
+ {
+ QDeclarativeEngine engine;
+ QDeclarativeComponent component(&engine);
+ component.setData(projectFile.toUtf8(), QUrl());
+ if (!component.isReady())
+ qDebug() << component.errorString();
+ QVERIFY(component.isReady());
+
+ QmlProjectItem *project = qobject_cast<QmlProjectItem*>(component.create());
+ QVERIFY(project);
+
+ project->setSourceDirectory(testDataDir);
+
+ QStringList expectedFiles(QStringList() << testDataDir + "/image.gif");
+ qDebug() << project->files().toSet() << expectedFiles.toSet();
+ QCOMPARE(project->files().toSet(), expectedFiles.toSet());
+ }
+
+ //
+ // use Files element (1.1)
+ //
+ projectFile = QLatin1String(
+ "import QmlProject 1.1\n"
+ "Project {\n"
+ " Files {\n"
+ " filter: \"image.gif\"\n"
+ " }\n"
+ "}\n");
+
+ {
+ QDeclarativeEngine engine;
+ QDeclarativeComponent component(&engine);
+ component.setData(projectFile.toUtf8(), QUrl());
+ if (!component.isReady())
+ qDebug() << component.errorString();
+ QVERIFY(component.isReady());
+
+ QmlProjectItem *project = qobject_cast<QmlProjectItem*>(component.create());
+ QVERIFY(project);
+
+ project->setSourceDirectory(testDataDir);
+
+ QStringList expectedFiles(QStringList() << testDataDir + "/image.gif");
+ qDebug() << project->files().toSet() << expectedFiles.toSet();
+ QCOMPARE(project->files().toSet(), expectedFiles.toSet());
+ }
}
void tst_FileFormat::testMatchesFile()
@@ -269,12 +328,38 @@ void tst_FileFormat::testLibraryPaths()
project->setSourceDirectory(testDataDir);
- QStringList expectedPaths(QStringList() << "../otherLibrary"
- << "library");
+ QStringList expectedPaths(QStringList() << SRCDIR "/otherLibrary"
+ << SRCDIR "/data/library");
+ qDebug() << expectedPaths << project->importPaths();
QCOMPARE(project->importPaths().toSet(), expectedPaths.toSet());
}
}
+void tst_FileFormat::testMainFile()
+{
+ //
+ // search for qml files in local directory
+ //
+ QString projectFile = QLatin1String(
+ "import QmlProject 1.1\n"
+ "Project {\n"
+ " mainFile: \"file1.qml\"\n"
+ "}\n");
+
+ {
+ QDeclarativeEngine engine;
+ QDeclarativeComponent component(&engine);
+ component.setData(projectFile.toUtf8(), QUrl());
+ if (!component.isReady())
+ qDebug() << component.errorString();
+ QVERIFY(component.isReady());
+
+ QmlProjectItem *project = qobject_cast<QmlProjectItem*>(component.create());
+ QVERIFY(project);
+
+ QCOMPARE(project->mainFile(), QString("file1.qml"));
+ }
+}
QTEST_MAIN(tst_FileFormat);
#include "tst_fileformat.moc"
diff --git a/tests/auto/qtcprocess/qtcprocess.pro b/tests/auto/qtcprocess/qtcprocess.pro
new file mode 100644
index 0000000000..037015df4a
--- /dev/null
+++ b/tests/auto/qtcprocess/qtcprocess.pro
@@ -0,0 +1,22 @@
+CONFIG += qtestlib testcase
+TEMPLATE = app
+CONFIG -= app_bundle
+DEFINES += QTCREATOR_UTILS_LIB
+
+UTILS_PATH = ../../../src/libs/utils
+
+INCLUDEPATH += $$UTILS_PATH/..
+DEPENDPATH += $$UTILS_PATH/..
+
+SOURCES += \
+ tst_qtcprocess.cpp \
+ $$UTILS_PATH/qtcprocess.cpp \
+ $$UTILS_PATH/stringutils.cpp \
+ $$UTILS_PATH/environment.cpp
+HEADERS += \
+ $$UTILS_PATH/qtcprocess.h \
+ $$UTILS_PATH/environment.h \
+ $$UTILS_PATH/stringutils.h \
+ $$UTILS_PATH/utils_global.h
+
+TARGET = tst_$$TARGET
diff --git a/tests/auto/qtcprocess/tst_qtcprocess.cpp b/tests/auto/qtcprocess/tst_qtcprocess.cpp
new file mode 100644
index 0000000000..a6ef552914
--- /dev/null
+++ b/tests/auto/qtcprocess/tst_qtcprocess.cpp
@@ -0,0 +1,698 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 <utils/qtcprocess.h>
+#include <utils/stringutils.h>
+#include <utils/environment.h>
+
+#include <QtTest/QtTest>
+
+using namespace Utils;
+
+class MacroMapExpander : public AbstractQtcMacroExpander {
+public:
+ virtual bool resolveMacro(const QString &name, QString *ret)
+ {
+ QHash<QString, QString>::const_iterator it = m_map.constFind(name);
+ if (it != m_map.constEnd()) {
+ *ret = it.value();
+ return true;
+ }
+ return false;
+ }
+ void insert(const QString &key, const QString &value) { m_map.insert(key, value); }
+private:
+ QHash<QString, QString> m_map;
+};
+
+class tst_QtcProcess : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void initTestCase();
+ void splitArgs_data();
+ void splitArgs();
+ void prepareArgs_data();
+ void prepareArgs();
+ void prepareArgsEnv_data();
+ void prepareArgsEnv();
+ void expandMacros_data();
+ void expandMacros();
+ void iterations_data();
+ void iterations();
+ void iteratorEdits();
+
+private:
+ Environment env;
+ MacroMapExpander mx;
+};
+
+void tst_QtcProcess::initTestCase()
+{
+ env.set("empty", "");
+ env.set("word", "hi");
+ env.set("words", "hi ho");
+ env.set("spacedwords", " hi ho sucker ");
+
+#ifdef Q_OS_WIN
+ mx.insert("a", "hi");
+ mx.insert("aa", "hi ho");
+
+ mx.insert("b", "h\\i");
+ mx.insert("c", "\\hi");
+ mx.insert("d", "hi\\");
+ mx.insert("ba", "h\\i ho");
+ mx.insert("ca", "\\hi ho");
+ mx.insert("da", "hi ho\\");
+
+ mx.insert("e", "h\"i");
+ mx.insert("f", "\"hi");
+ mx.insert("g", "hi\"");
+
+ mx.insert("h", "h\\\"i");
+ mx.insert("i", "\\\"hi");
+ mx.insert("j", "hi\\\"");
+
+ mx.insert("k", "&special;");
+
+ mx.insert("x", "\\");
+ mx.insert("y", "\"");
+#else
+ mx.insert("a", "hi");
+ mx.insert("b", "hi ho");
+ mx.insert("c", "&special;");
+ mx.insert("d", "h\\i");
+ mx.insert("e", "h\"i");
+ mx.insert("f", "h'i");
+#endif
+ mx.insert("z", "");
+}
+
+Q_DECLARE_METATYPE(QtcProcess::SplitError)
+
+void tst_QtcProcess::splitArgs_data()
+{
+ QTest::addColumn<QString>("in");
+ QTest::addColumn<QString>("out");
+ QTest::addColumn<QtcProcess::SplitError>("err");
+
+ static const struct {
+ const char * const in;
+ const char * const out;
+ const QtcProcess::SplitError err;
+ } vals[] = {
+#ifdef Q_OS_WIN
+ { "", "", QtcProcess::SplitOk },
+ { " ", "", QtcProcess::SplitOk },
+ { "hi", "hi", QtcProcess::SplitOk },
+ { "hi ho", "hi ho", QtcProcess::SplitOk },
+ { " hi ho ", "hi ho", QtcProcess::SplitOk },
+ { "\"hi ho\" \"hi\" ho ", "\"hi ho\" hi ho", QtcProcess::SplitOk },
+ { "\\", "\\", QtcProcess::SplitOk },
+ { "\\\"", "\"\"\\^\"\"\"", QtcProcess::SplitOk },
+ { "\"hi\"\"\"ho\"", "\"hi\"\\^\"\"ho\"", QtcProcess::SplitOk },
+ { "\\\\\\\"", "\"\"\\\\\\^\"\"\"", QtcProcess::SplitOk },
+ { " ^^ ", "\"^^\"", QtcProcess::SplitOk },
+ { "hi\"", "", QtcProcess::BadQuoting },
+ { "hi\"dood", "", QtcProcess::BadQuoting },
+ { "%var%", "%var%", QtcProcess::SplitOk },
+#else
+ { "", "", QtcProcess::SplitOk },
+ { " ", "", QtcProcess::SplitOk },
+ { "hi", "hi", QtcProcess::SplitOk },
+ { "hi ho", "hi ho", QtcProcess::SplitOk },
+ { " hi ho ", "hi ho", QtcProcess::SplitOk },
+ { "'hi ho' \"hi\" ho ", "'hi ho' hi ho", QtcProcess::SplitOk },
+ { " \\ ", "' '", QtcProcess::SplitOk },
+ { " \\\" ", "'\"'", QtcProcess::SplitOk },
+ { " '\"' ", "'\"'", QtcProcess::SplitOk },
+ { " \"\\\"\" ", "'\"'", QtcProcess::SplitOk },
+ { "hi'", "", QtcProcess::BadQuoting },
+ { "hi\"dood", "", QtcProcess::BadQuoting },
+ { "$var", "'$var'", QtcProcess::SplitOk },
+#endif
+ };
+
+ for (unsigned i = 0; i < sizeof(vals)/sizeof(vals[0]); i++)
+ QTest::newRow(vals[i].in) << QString::fromLatin1(vals[i].in)
+ << QString::fromLatin1(vals[i].out)
+ << vals[i].err;
+}
+
+void tst_QtcProcess::splitArgs()
+{
+ QFETCH(QString, in);
+ QFETCH(QString, out);
+ QFETCH(QtcProcess::SplitError, err);
+
+ QtcProcess::SplitError outerr;
+ QString outstr = QtcProcess::joinArgs(QtcProcess::splitArgs(in, false, &outerr));
+ QCOMPARE(outerr, err);
+ if (err == QtcProcess::SplitOk)
+ QCOMPARE(outstr, out);
+}
+
+void tst_QtcProcess::prepareArgs_data()
+{
+ QTest::addColumn<QString>("in");
+ QTest::addColumn<QString>("out");
+ QTest::addColumn<QtcProcess::SplitError>("err");
+
+ static const struct {
+ const char * const in;
+ const char * const out;
+ const QtcProcess::SplitError err;
+ } vals[] = {
+#ifdef Q_OS_WIN
+ { "", "", QtcProcess::SplitOk },
+ { " ", " ", QtcProcess::SplitOk },
+ { "hi", "hi", QtcProcess::SplitOk },
+ { "hi ho", "hi ho", QtcProcess::SplitOk },
+ { " hi ho ", " hi ho ", QtcProcess::SplitOk },
+ { "\"hi ho\" \"hi\" ho ", "\"hi ho\" \"hi\" ho ", QtcProcess::SplitOk },
+ { "\\", "\\", QtcProcess::SplitOk },
+ { "\\\"", "\\\"", QtcProcess::SplitOk },
+ { "\"hi\"\"ho\"", "\"hi\"\"ho\"", QtcProcess::SplitOk },
+ { "\\\\\\\"", "\\\\\\\"", QtcProcess::SplitOk },
+ { "^^", "^", QtcProcess::SplitOk },
+ { "hi\"", "hi\"", QtcProcess::SplitOk },
+ { "hi\"dood", "hi\"dood", QtcProcess::SplitOk },
+ { "%var%", "", QtcProcess::FoundMeta },
+ { "echo hi > file", "", QtcProcess::FoundMeta },
+#else
+ { "", "", QtcProcess::SplitOk },
+ { " ", "", QtcProcess::SplitOk },
+ { "hi", "hi", QtcProcess::SplitOk },
+ { "hi ho", "hi ho", QtcProcess::SplitOk },
+ { " hi ho ", "hi ho", QtcProcess::SplitOk },
+ { "'hi ho' \"hi\" ho ", "'hi ho' hi ho", QtcProcess::SplitOk },
+ { " \\ ", "' '", QtcProcess::SplitOk },
+ { "hi'", "", QtcProcess::BadQuoting },
+ { "hi\"dood", "", QtcProcess::BadQuoting },
+ { "$var", "", QtcProcess::FoundMeta },
+#endif
+ };
+
+ for (unsigned i = 0; i < sizeof(vals)/sizeof(vals[0]); i++)
+ QTest::newRow(vals[i].in) << QString::fromLatin1(vals[i].in)
+ << QString::fromLatin1(vals[i].out)
+ << vals[i].err;
+}
+
+void tst_QtcProcess::prepareArgs()
+{
+ QFETCH(QString, in);
+ QFETCH(QString, out);
+ QFETCH(QtcProcess::SplitError, err);
+
+ QtcProcess::SplitError outerr;
+ QString outstr;
+#ifdef Q_OS_WIN
+ outstr = QtcProcess::prepareArgs(in, &outerr);
+#else
+ outstr = QtcProcess::joinArgs(QtcProcess::prepareArgs(in, &outerr));
+#endif
+ QCOMPARE(outerr, err);
+ if (err == QtcProcess::SplitOk)
+ QCOMPARE(outstr, out);
+}
+
+void tst_QtcProcess::prepareArgsEnv_data()
+{
+ QTest::addColumn<QString>("in");
+ QTest::addColumn<QString>("out");
+ QTest::addColumn<QtcProcess::SplitError>("err");
+
+ static const struct {
+ const char * const in;
+ const char * const out;
+ const QtcProcess::SplitError err;
+ } vals[] = {
+#ifdef Q_OS_WIN
+ { "", "", QtcProcess::SplitOk },
+ { " ", " ", QtcProcess::SplitOk },
+ { "hi", "hi", QtcProcess::SplitOk },
+ { "hi ho", "hi ho", QtcProcess::SplitOk },
+ { " hi ho ", " hi ho ", QtcProcess::SplitOk },
+ { "\"hi ho\" \"hi\" ho ", "\"hi ho\" \"hi\" ho ", QtcProcess::SplitOk },
+ { "\\", "\\", QtcProcess::SplitOk },
+ { "\\\"", "\\\"", QtcProcess::SplitOk },
+ { "\"hi\"\"ho\"", "\"hi\"\"ho\"", QtcProcess::SplitOk },
+ { "\\\\\\\"", "\\\\\\\"", QtcProcess::SplitOk },
+ { "^^", "^", QtcProcess::SplitOk },
+ { "hi\"", "hi\"", QtcProcess::SplitOk },
+ { "hi\"dood", "hi\"dood", QtcProcess::SplitOk },
+ { "%empty%", "%empty%", QtcProcess::SplitOk }, // Yep, no empty variables on Windows.
+ { "%word%", "hi", QtcProcess::SplitOk },
+ { " %word% ", " hi ", QtcProcess::SplitOk },
+ { "%words%", "hi ho", QtcProcess::SplitOk },
+ { "%nonsense%words%", "%nonsensehi ho", QtcProcess::SplitOk },
+ { "fail%nonsense%words%", "fail%nonsensehi ho", QtcProcess::SplitOk },
+ { "%words%words%", "hi howords%", QtcProcess::SplitOk },
+ { "%words%%words%", "hi hohi ho", QtcProcess::SplitOk },
+ { "echo hi > file", "", QtcProcess::FoundMeta },
+#else
+ { "", "", QtcProcess::SplitOk },
+ { " ", "", QtcProcess::SplitOk },
+ { "hi", "hi", QtcProcess::SplitOk },
+ { "hi ho", "hi ho", QtcProcess::SplitOk },
+ { " hi ho ", "hi ho", QtcProcess::SplitOk },
+ { "'hi ho' \"hi\" ho ", "'hi ho' hi ho", QtcProcess::SplitOk },
+ { " \\ ", "' '", QtcProcess::SplitOk },
+ { "hi'", "", QtcProcess::BadQuoting },
+ { "hi\"dood", "", QtcProcess::BadQuoting },
+ { "$empty", "", QtcProcess::SplitOk },
+ { "$word", "hi", QtcProcess::SplitOk },
+ { " $word ", "hi", QtcProcess::SplitOk },
+ { "${word}", "hi", QtcProcess::SplitOk },
+ { " ${word} ", "hi", QtcProcess::SplitOk },
+ { "$words", "hi ho", QtcProcess::SplitOk },
+ { "$spacedwords", "hi ho sucker", QtcProcess::SplitOk },
+ { "hi${empty}ho", "hiho", QtcProcess::SplitOk },
+ { "hi${words}ho", "hihi hoho", QtcProcess::SplitOk },
+ { "hi${spacedwords}ho", "hi hi ho sucker ho", QtcProcess::SplitOk },
+ { "${", "", QtcProcess::BadQuoting },
+ { "${var", "", QtcProcess::BadQuoting },
+ { "${var ", "", QtcProcess::FoundMeta },
+ { "\"hi${words}ho\"", "'hihi hoho'", QtcProcess::SplitOk },
+ { "\"hi${spacedwords}ho\"", "'hi hi ho sucker ho'", QtcProcess::SplitOk },
+ { "\"${", "", QtcProcess::BadQuoting },
+ { "\"${var", "", QtcProcess::BadQuoting },
+ { "\"${var ", "", QtcProcess::FoundMeta },
+#endif
+ };
+
+ for (unsigned i = 0; i < sizeof(vals)/sizeof(vals[0]); i++)
+ QTest::newRow(vals[i].in) << QString::fromLatin1(vals[i].in)
+ << QString::fromLatin1(vals[i].out)
+ << vals[i].err;
+}
+
+void tst_QtcProcess::prepareArgsEnv()
+{
+ QFETCH(QString, in);
+ QFETCH(QString, out);
+ QFETCH(QtcProcess::SplitError, err);
+
+ QtcProcess::SplitError outerr;
+ QString outstr;
+#ifdef Q_OS_WIN
+ outstr = QtcProcess::prepareArgs(in, &outerr, &env);
+#else
+ outstr = QtcProcess::joinArgs(QtcProcess::prepareArgs(in, &outerr, &env));
+#endif
+ QCOMPARE(outerr, err);
+ if (err == QtcProcess::SplitOk)
+ QCOMPARE(outstr, out);
+}
+
+void tst_QtcProcess::expandMacros_data()
+
+{
+ QTest::addColumn<QString>("in");
+ QTest::addColumn<QString>("out");
+ QChar sp(QLatin1Char(' '));
+
+ static const struct {
+ const char * const in;
+ const char * const out;
+ } vals[] = {
+#ifdef Q_OS_WIN
+ { "plain", 0 },
+ { "%{a}", "hi" },
+ { "%{aa}", "\"hi ho\"" },
+ { "%{b}", "h\\i" },
+ { "%{c}", "\\hi" },
+ { "%{d}", "hi\\" },
+ { "%{ba}", "\"h\\i ho\"" },
+ { "%{ca}", "\"\\hi ho\"" },
+ { "%{da}", "\"hi ho\\\\\"" }, // or "\"hi ho\"\\"
+ { "%{e}", "\"h\"\\^\"\"i\"" },
+ { "%{f}", "\"\"\\^\"\"hi\"" },
+ { "%{g}", "\"hi\"\\^\"\"\"" },
+ { "%{h}", "\"h\\\\\"\\^\"\"i\"" },
+ { "%{i}", "\"\\\\\"\\^\"\"hi\"" },
+ { "%{j}", "\"hi\\\\\"\\^\"\"\"" },
+ { "%{k}", "\"&special;\"" },
+ { "%{x}", "\\" },
+ { "%{y}", "\"\"\\^\"\"\"" },
+ { "%{z}", "\"\"" },
+ { "^%{z}%{z}", "^%{z}%{z}" }, // stupid user check
+
+ { "quoted", 0 },
+ { "\"%{a}\"", "\"hi\"" },
+ { "\"%{aa}\"", "\"hi ho\"" },
+ { "\"%{b}\"", "\"h\\i\"" },
+ { "\"%{c}\"", "\"\\hi\"" },
+ { "\"%{d}\"", "\"hi\\\\\"" },
+ { "\"%{ba}\"", "\"h\\i ho\"" },
+ { "\"%{ca}\"", "\"\\hi ho\"" },
+ { "\"%{da}\"", "\"hi ho\\\\\"" },
+ { "\"%{e}\"", "\"h\"\\^\"\"i\"" },
+ { "\"%{f}\"", "\"\"\\^\"\"hi\"" },
+ { "\"%{g}\"", "\"hi\"\\^\"\"\"" },
+ { "\"%{h}\"", "\"h\\\\\"\\^\"\"i\"" },
+ { "\"%{i}\"", "\"\\\\\"\\^\"\"hi\"" },
+ { "\"%{j}\"", "\"hi\\\\\"\\^\"\"\"" },
+ { "\"%{k}\"", "\"&special;\"" },
+ { "\"%{x}\"", "\"\\\\\"" },
+ { "\"%{y}\"", "\"\"\\^\"\"\"" },
+ { "\"%{z}\"", "\"\"" },
+
+ { "leading bs", 0 },
+ { "\\%{a}", "\\hi" },
+ { "\\%{aa}", "\\\\\"hi ho\"" },
+ { "\\%{b}", "\\h\\i" },
+ { "\\%{c}", "\\\\hi" },
+ { "\\%{d}", "\\hi\\" },
+ { "\\%{ba}", "\\\\\"h\\i ho\"" },
+ { "\\%{ca}", "\\\\\"\\hi ho\"" },
+ { "\\%{da}", "\\\\\"hi ho\\\\\"" },
+ { "\\%{e}", "\\\\\"h\"\\^\"\"i\"" },
+ { "\\%{f}", "\\\\\"\"\\^\"\"hi\"" },
+ { "\\%{g}", "\\\\\"hi\"\\^\"\"\"" },
+ { "\\%{h}", "\\\\\"h\\\\\"\\^\"\"i\"" },
+ { "\\%{i}", "\\\\\"\\\\\"\\^\"\"hi\"" },
+ { "\\%{j}", "\\\\\"hi\\\\\"\\^\"\"\"" },
+ { "\\%{x}", "\\\\" },
+ { "\\%{y}", "\\\\\"\"\\^\"\"\"" },
+ { "\\%{z}", "\\" },
+
+ { "trailing bs", 0 },
+ { "%{a}\\", "hi\\" },
+ { "%{aa}\\", "\"hi ho\"\\" },
+ { "%{b}\\", "h\\i\\" },
+ { "%{c}\\", "\\hi\\" },
+ { "%{d}\\", "hi\\\\" },
+ { "%{ba}\\", "\"h\\i ho\"\\" },
+ { "%{ca}\\", "\"\\hi ho\"\\" },
+ { "%{da}\\", "\"hi ho\\\\\"\\" },
+ { "%{e}\\", "\"h\"\\^\"\"i\"\\" },
+ { "%{f}\\", "\"\"\\^\"\"hi\"\\" },
+ { "%{g}\\", "\"hi\"\\^\"\"\"\\" },
+ { "%{h}\\", "\"h\\\\\"\\^\"\"i\"\\" },
+ { "%{i}\\", "\"\\\\\"\\^\"\"hi\"\\" },
+ { "%{j}\\", "\"hi\\\\\"\\^\"\"\"\\" },
+ { "%{x}\\", "\\\\" },
+ { "%{y}\\", "\"\"\\^\"\"\"\\" },
+ { "%{z}\\", "\\" },
+
+ { "bs-enclosed", 0 },
+ { "\\%{a}\\", "\\hi\\" },
+ { "\\%{aa}\\", "\\\\\"hi ho\"\\" },
+ { "\\%{b}\\", "\\h\\i\\" },
+ { "\\%{c}\\", "\\\\hi\\" },
+ { "\\%{d}\\", "\\hi\\\\" },
+ { "\\%{ba}\\", "\\\\\"h\\i ho\"\\" },
+ { "\\%{ca}\\", "\\\\\"\\hi ho\"\\" },
+ { "\\%{da}\\", "\\\\\"hi ho\\\\\"\\" },
+ { "\\%{e}\\", "\\\\\"h\"\\^\"\"i\"\\" },
+ { "\\%{f}\\", "\\\\\"\"\\^\"\"hi\"\\" },
+ { "\\%{g}\\", "\\\\\"hi\"\\^\"\"\"\\" },
+ { "\\%{h}\\", "\\\\\"h\\\\\"\\^\"\"i\"\\" },
+ { "\\%{i}\\", "\\\\\"\\\\\"\\^\"\"hi\"\\" },
+ { "\\%{j}\\", "\\\\\"hi\\\\\"\\^\"\"\"\\" },
+ { "\\%{x}\\", "\\\\\\" },
+ { "\\%{y}\\", "\\\\\"\"\\^\"\"\"\\" },
+ { "\\%{z}\\", "\\\\" },
+
+ { "bs-enclosed and trailing literal quote", 0 },
+ { "\\%{a}\\\\\\^\"", "\\hi\\\\\\^\"" },
+ { "\\%{aa}\\\\\\^\"", "\\\\\"hi ho\"\\\\\\^\"" },
+ { "\\%{b}\\\\\\^\"", "\\h\\i\\\\\\^\"" },
+ { "\\%{c}\\\\\\^\"", "\\\\hi\\\\\\^\"" },
+ { "\\%{d}\\\\\\^\"", "\\hi\\\\\\\\\\^\"" },
+ { "\\%{ba}\\\\\\^\"", "\\\\\"h\\i ho\"\\\\\\^\"" },
+ { "\\%{ca}\\\\\\^\"", "\\\\\"\\hi ho\"\\\\\\^\"" },
+ { "\\%{da}\\\\\\^\"", "\\\\\"hi ho\\\\\"\\\\\\^\"" },
+ { "\\%{e}\\\\\\^\"", "\\\\\"h\"\\^\"\"i\"\\\\\\^\"" },
+ { "\\%{f}\\\\\\^\"", "\\\\\"\"\\^\"\"hi\"\\\\\\^\"" },
+ { "\\%{g}\\\\\\^\"", "\\\\\"hi\"\\^\"\"\"\\\\\\^\"" },
+ { "\\%{h}\\\\\\^\"", "\\\\\"h\\\\\"\\^\"\"i\"\\\\\\^\"" },
+ { "\\%{i}\\\\\\^\"", "\\\\\"\\\\\"\\^\"\"hi\"\\\\\\^\"" },
+ { "\\%{j}\\\\\\^\"", "\\\\\"hi\\\\\"\\^\"\"\"\\\\\\^\"" },
+ { "\\%{x}\\\\\\^\"", "\\\\\\\\\\\\\\^\"" },
+ { "\\%{y}\\\\\\^\"", "\\\\\"\"\\^\"\"\"\\\\\\^\"" },
+ { "\\%{z}\\\\\\^\"", "\\\\\\\\\\^\"" },
+
+ { "bs-enclosed and trailing unclosed quote", 0 },
+ { "\\%{a}\\\\\"", "\\hi\\\\\"" },
+ { "\\%{aa}\\\\\"", "\\\\\"hi ho\"\\\\\"" },
+ { "\\%{b}\\\\\"", "\\h\\i\\\\\"" },
+ { "\\%{c}\\\\\"", "\\\\hi\\\\\"" },
+ { "\\%{d}\\\\\"", "\\hi\\\\\\\\\"" },
+ { "\\%{ba}\\\\\"", "\\\\\"h\\i ho\"\\\\\"" },
+ { "\\%{ca}\\\\\"", "\\\\\"\\hi ho\"\\\\\"" },
+ { "\\%{da}\\\\\"", "\\\\\"hi ho\\\\\"\\\\\"" },
+ { "\\%{e}\\\\\"", "\\\\\"h\"\\^\"\"i\"\\\\\"" },
+ { "\\%{f}\\\\\"", "\\\\\"\"\\^\"\"hi\"\\\\\"" },
+ { "\\%{g}\\\\\"", "\\\\\"hi\"\\^\"\"\"\\\\\"" },
+ { "\\%{h}\\\\\"", "\\\\\"h\\\\\"\\^\"\"i\"\\\\\"" },
+ { "\\%{i}\\\\\"", "\\\\\"\\\\\"\\^\"\"hi\"\\\\\"" },
+ { "\\%{j}\\\\\"", "\\\\\"hi\\\\\"\\^\"\"\"\\\\\"" },
+ { "\\%{x}\\\\\"", "\\\\\\\\\\\\\"" },
+ { "\\%{y}\\\\\"", "\\\\\"\"\\^\"\"\"\\\\\"" },
+ { "\\%{z}\\\\\"", "\\\\\\\\\"" },
+
+ { "multi-var", 0 },
+ { "%{x}%{y}%{z}", "\\\\\"\"\\^\"\"\"" },
+ { "%{x}%{z}%{y}%{z}", "\\\\\"\"\\^\"\"\"" },
+ { "%{x}%{z}%{y}", "\\\\\"\"\\^\"\"\"" },
+ { "%{x}\\^\"%{z}", "\\\\\\^\"" },
+ { "%{x}%{z}\\^\"%{z}", "\\\\\\^\"" },
+ { "%{x}%{z}\\^\"", "\\\\\\^\"" },
+ { "%{x}\\%{z}", "\\\\" },
+ { "%{x}%{z}\\%{z}", "\\\\" },
+ { "%{x}%{z}\\", "\\\\" },
+ { "%{aa}%{a}", "\"hi hohi\"" },
+ { "%{aa}%{aa}", "\"hi hohi ho\"" },
+ { "%{aa}:%{aa}", "\"hi ho\":\"hi ho\"" },
+ { "hallo ^|%{aa}^|", "hallo ^|\"hi ho\"^|" },
+
+ { "quoted multi-var", 0 },
+ { "\"%{x}%{y}%{z}\"", "\"\\\\\"\\^\"\"\"" },
+ { "\"%{x}%{z}%{y}%{z}\"", "\"\\\\\"\\^\"\"\"" },
+ { "\"%{x}%{z}%{y}\"", "\"\\\\\"\\^\"\"\"" },
+ { "\"%{x}\"^\"\"%{z}\"", "\"\\\\\"^\"\"\"" },
+ { "\"%{x}%{z}\"^\"\"%{z}\"", "\"\\\\\"^\"\"\"" },
+ { "\"%{x}%{z}\"^\"\"\"", "\"\\\\\"^\"\"\"" },
+ { "\"%{x}\\%{z}\"", "\"\\\\\\\\\"" },
+ { "\"%{x}%{z}\\%{z}\"", "\"\\\\\\\\\"" },
+ { "\"%{x}%{z}\\\\\"", "\"\\\\\\\\\"" },
+ { "\"%{aa}%{a}\"", "\"hi hohi\"" },
+ { "\"%{aa}%{aa}\"", "\"hi hohi ho\"" },
+ { "\"%{aa}:%{aa}\"", "\"hi ho:hi ho\"" },
+#else
+ { "plain", 0 },
+ { "%{a}", "hi" },
+ { "%{b}", "'hi ho'" },
+ { "%{c}", "'&special;'" },
+ { "%{d}", "'h\\i'" },
+ { "%{e}", "'h\"i'" },
+ { "%{f}", "'h'\\''i'" },
+ { "%{z}", "''" },
+ { "\\%{z}%{z}", "\\%{z}%{z}" }, // stupid user check
+
+ { "single-quoted", 0 },
+ { "'%{a}'", "'hi'" },
+ { "'%{b}'", "'hi ho'" },
+ { "'%{c}'", "'&special;'" },
+ { "'%{d}'", "'h\\i'" },
+ { "'%{e}'", "'h\"i'" },
+ { "'%{f}'", "'h'\\''i'" },
+ { "'%{z}'", "''" },
+
+ { "double-quoted", 0 },
+ { "\"%{a}\"", "\"hi\"" },
+ { "\"%{b}\"", "\"hi ho\"" },
+ { "\"%{c}\"", "\"&special;\"" },
+ { "\"%{d}\"", "\"h\\\\i\"" },
+ { "\"%{e}\"", "\"h\\\"i\"" },
+ { "\"%{f}\"", "\"h'i\"" },
+ { "\"%{z}\"", "\"\"" },
+
+ { "complex", 0 },
+ { "echo \"$(echo %{a})\"", "echo \"$(echo hi)\"" },
+ { "echo \"$(echo %{b})\"", "echo \"$(echo 'hi ho')\"" },
+ { "echo \"$(echo \"%{a}\")\"", "echo \"$(echo \"hi\")\"" },
+ // These make no sense shell-wise, but they test expando nesting
+ { "echo \"%{echo %{a}}\"", "echo \"%{echo hi}\"" },
+ { "echo \"%{echo %{b}}\"", "echo \"%{echo hi ho}\"" },
+ { "echo \"%{echo \"%{a}\"}\"", "echo \"%{echo \"hi\"}\"" },
+#endif
+ };
+
+ const char *title = 0;
+ for (unsigned i = 0; i < sizeof(vals)/sizeof(vals[0]); i++) {
+ if (!vals[i].out) {
+ title = vals[i].in;
+ } else {
+ char buf[80];
+ sprintf(buf, "%s: %s", title, vals[i].in);
+ QTest::newRow(buf) << QString::fromLatin1(vals[i].in)
+ << QString::fromLatin1(vals[i].out);
+ sprintf(buf, "padded %s: %s", title, vals[i].in);
+ QTest::newRow(buf) << (sp + QString::fromLatin1(vals[i].in) + sp)
+ << (sp + QString::fromLatin1(vals[i].out) + sp);
+ }
+ }
+}
+
+void tst_QtcProcess::expandMacros()
+{
+ QFETCH(QString, in);
+ QFETCH(QString, out);
+
+ QtcProcess::expandMacros(&in, &mx);
+ QCOMPARE(in, out);
+}
+
+void tst_QtcProcess::iterations_data()
+{
+ QTest::addColumn<QString>("in");
+ QTest::addColumn<QString>("out");
+
+ static const struct {
+ const char * const in;
+ const char * const out;
+ } vals[] = {
+#ifdef Q_OS_WIN
+ { "", "" },
+ { "hi", "hi" },
+ { " hi ", "hi" },
+ { "hi ho", "hi ho" },
+ { "\"hi ho\" sucker", "\"hi ho\" sucker" },
+ { "\"hi\"^\"\"ho\" sucker", "\"hi\"\\^\"\"ho\" sucker" },
+ { "\"hi\"\\^\"\"ho\" sucker", "\"hi\"\\^\"\"ho\" sucker" },
+ { "hi^|ho", "\"hi|ho\"" },
+ { "c:\\", "c:\\" },
+ { "\"c:\\\\\"", "c:\\" },
+ { "\\hi\\ho", "\\hi\\ho" },
+ { "hi null%", "hi null%" },
+ { "hi null% ho", "hi null% ho" },
+ { "hi null%here ho", "hi null%here ho" },
+ { "hi null%here%too ho", "hi {} ho" },
+ { "echo hello | more", "echo hello" },
+ { "echo hello| more", "echo hello" },
+#else
+ { "", "" },
+ { " ", "" },
+ { "hi", "hi" },
+ { " hi ", "hi" },
+ { "'hi'", "hi" },
+ { "hi ho", "hi ho" },
+ { "\"hi ho\" sucker", "'hi ho' sucker" },
+ { "\"hi\\\"ho\" sucker", "'hi\"ho' sucker" },
+ { "\"hi'ho\" sucker", "'hi'\\''ho' sucker" },
+ { "'hi ho' sucker", "'hi ho' sucker" },
+ { "\\\\", "'\\'" },
+ { "'\\'", "'\\'" },
+ { "hi 'null${here}too' ho", "hi 'null${here}too' ho" },
+ { "hi null${here}too ho", "hi {} ho" },
+ { "hi $(echo $dollar cent) ho", "hi {} ho" },
+ { "hi `echo $dollar \\`echo cent\\` | cat` ho", "hi {} ho" },
+ { "echo hello | more", "echo hello" },
+ { "echo hello| more", "echo hello" },
+#endif
+ };
+
+ for (unsigned i = 0; i < sizeof(vals)/sizeof(vals[0]); i++)
+ QTest::newRow(vals[i].in) << QString::fromLatin1(vals[i].in)
+ << QString::fromLatin1(vals[i].out);
+}
+
+void tst_QtcProcess::iterations()
+{
+ QFETCH(QString, in);
+ QFETCH(QString, out);
+
+ QString outstr;
+ for (QtcProcess::ArgIterator ait(&in); ait.next(); )
+ if (ait.isSimple())
+ QtcProcess::addArg(&outstr, ait.value());
+ else
+ QtcProcess::addArgs(&outstr, "{}");
+ QCOMPARE(outstr, out);
+}
+
+void tst_QtcProcess::iteratorEdits()
+{
+ QString in1 = "one two three", in2 = in1, in3 = in1, in4 = in1, in5 = in1;
+
+ QtcProcess::ArgIterator ait1(&in1);
+ QVERIFY(ait1.next());
+ ait1.deleteArg();
+ QVERIFY(ait1.next());
+ QVERIFY(ait1.next());
+ QVERIFY(!ait1.next());
+ QCOMPARE(in1, QString::fromLatin1("two three"));
+ ait1.appendArg("four");
+ QCOMPARE(in1, QString::fromLatin1("two three four"));
+
+ QtcProcess::ArgIterator ait2(&in2);
+ QVERIFY(ait2.next());
+ QVERIFY(ait2.next());
+ ait2.deleteArg();
+ QVERIFY(ait2.next());
+ ait2.appendArg("four");
+ QVERIFY(!ait2.next());
+ QCOMPARE(in2, QString::fromLatin1("one three four"));
+
+ QtcProcess::ArgIterator ait3(&in3);
+ QVERIFY(ait3.next());
+ ait3.appendArg("one-b");
+ QVERIFY(ait3.next());
+ QVERIFY(ait3.next());
+ ait3.deleteArg();
+ QVERIFY(!ait3.next());
+ QCOMPARE(in3, QString::fromLatin1("one one-b two"));
+
+ QtcProcess::ArgIterator ait4(&in4);
+ ait4.appendArg("pre-one");
+ QVERIFY(ait4.next());
+ QVERIFY(ait4.next());
+ QVERIFY(ait4.next());
+ ait4.deleteArg();
+ QVERIFY(!ait4.next());
+ QCOMPARE(in4, QString::fromLatin1("pre-one one two"));
+
+ QtcProcess::ArgIterator ait5(&in5);
+ QVERIFY(ait5.next());
+ QVERIFY(ait5.next());
+ QVERIFY(ait5.next());
+ QVERIFY(!ait5.next());
+ ait5.deleteArg();
+ QVERIFY(!ait5.next());
+ QCOMPARE(in5, QString::fromLatin1("one two"));
+}
+
+QTEST_MAIN(tst_QtcProcess)
+
+#include "tst_qtcprocess.moc"
diff --git a/tests/auto/qttest.pri b/tests/auto/qttest.pri
new file mode 100644
index 0000000000..440ad138e5
--- /dev/null
+++ b/tests/auto/qttest.pri
@@ -0,0 +1,17 @@
+include(../../qtcreator.pri)
+
+isEmpty(TEMPLATE):TEMPLATE=app
+CONFIG += qt warn_on console depend_includepath testcase qtestlib
+CONFIG -= app_bundle
+
+symbian:{
+ TARGET.EPOCHEAPSIZE = 0x100000 0x2000000
+# DEFINES += QTEST_NO_SPECIALIZATIONS
+ TARGET.CAPABILITY="None"
+ RSS_RULES ="group_name=\"QtTests\";"
+}
+
+include(qttestrpath.pri)
+
+# prefix test binary with tst_
+!contains(TARGET, ^tst_.*):TARGET = $$join(TARGET,,"tst_")
diff --git a/tests/auto/qttestrpath.pri b/tests/auto/qttestrpath.pri
new file mode 100644
index 0000000000..fc9ab92307
--- /dev/null
+++ b/tests/auto/qttestrpath.pri
@@ -0,0 +1,11 @@
+linux-* {
+ QMAKE_RPATHDIR += $$IDE_BUILD_TREE/$$IDE_LIBRARY_BASENAME/qtcreator
+ QMAKE_RPATHDIR += $$IDE_PLUGIN_PATH/Nokia
+
+ IDE_PLUGIN_RPATH = $$join(QMAKE_RPATHDIR, ":")
+
+ QMAKE_LFLAGS += -Wl,-z,origin \'-Wl,-rpath,$${IDE_PLUGIN_RPATH}\'
+} else:macx {
+ QMAKE_LFLAGS += -Wl,-rpath,\"$$IDE_BIN_PATH/../\"
+}
+
diff --git a/tests/auto/utils_stringutils/tst_stringutils.cpp b/tests/auto/utils_stringutils/tst_stringutils.cpp
index 5d3c9c6fc1..25e0d6a3d3 100644
--- a/tests/auto/utils_stringutils/tst_stringutils.cpp
+++ b/tests/auto/utils_stringutils/tst_stringutils.cpp
@@ -37,46 +37,96 @@
//TESTED_COMPONENT=src/libs/utils
+class TestMacroExpander : public Utils::AbstractQtcMacroExpander
+{
+public:
+ virtual bool resolveMacro(const QString &name, QString *ret)
+ {
+ if (name == QLatin1String("a")) {
+ *ret = QLatin1String("hi");
+ return true;
+ }
+ return false;
+ }
+};
+
class tst_StringUtils : public QObject
{
Q_OBJECT
private slots:
void testWithTildeHomePath();
+ void testMacroExpander_data();
+ void testMacroExpander();
+private:
+ TestMacroExpander mx;
};
void tst_StringUtils::testWithTildeHomePath()
{
#ifndef Q_OS_WIN
// home path itself
- QCOMPARE(Utils::withTildeHomePath(QDir::homePath()), QLatin1String("~"));
+ QCOMPARE(Utils::withTildeHomePath(QDir::homePath()), QString::fromLatin1("~"));
QCOMPARE(Utils::withTildeHomePath(QDir::homePath() + QLatin1Char('/')),
- QLatin1String("~"));
- QCOMPARE(Utils::withTildeHomePath(QLatin1String("/unclean/..") + QDir::homePath()),
- QLatin1String("~"));
+ QString::fromLatin1("~"));
+ QCOMPARE(Utils::withTildeHomePath(QString::fromLatin1("/unclean/..") + QDir::homePath()),
+ QString::fromLatin1("~"));
// sub of home path
- QCOMPARE(Utils::withTildeHomePath(QDir::homePath() + QLatin1String("/foo")),
- QLatin1String("~/foo"));
- QCOMPARE(Utils::withTildeHomePath(QDir::homePath() + QLatin1String("/foo/")),
- QLatin1String("~/foo"));
- QCOMPARE(Utils::withTildeHomePath(QDir::homePath() + QLatin1String("/some/path/file.txt")),
- QLatin1String("~/some/path/file.txt"));
- QCOMPARE(Utils::withTildeHomePath(QDir::homePath() + QLatin1String("/some/unclean/../path/file.txt")),
- QLatin1String("~/some/path/file.txt"));
+ QCOMPARE(Utils::withTildeHomePath(QDir::homePath() + QString::fromLatin1("/foo")),
+ QString::fromLatin1("~/foo"));
+ QCOMPARE(Utils::withTildeHomePath(QDir::homePath() + QString::fromLatin1("/foo/")),
+ QString::fromLatin1("~/foo"));
+ QCOMPARE(Utils::withTildeHomePath(QDir::homePath() + QString::fromLatin1("/some/path/file.txt")),
+ QString::fromLatin1("~/some/path/file.txt"));
+ QCOMPARE(Utils::withTildeHomePath(QDir::homePath() + QString::fromLatin1("/some/unclean/../path/file.txt")),
+ QString::fromLatin1("~/some/path/file.txt"));
// not sub of home path
- QCOMPARE(Utils::withTildeHomePath(QDir::homePath() + QLatin1String("/../foo")),
- QDir::homePath() + QLatin1String("/../foo"));
+ QCOMPARE(Utils::withTildeHomePath(QDir::homePath() + QString::fromLatin1("/../foo")),
+ QString(QDir::homePath() + QString::fromLatin1("/../foo")));
#else
// windows: should return same as input
QCOMPARE(Utils::withTildeHomePath(QDir::homePath()), QDir::homePath());
- QCOMPARE(Utils::withTildeHomePath(QDir::homePath() + QLatin1String("/foo")),
- QDir::homePath() + QLatin1String("/foo"));
- QCOMPARE(Utils::withTildeHomePath(QDir::homePath() + QLatin1String("/../foo")),
- Utils::withTildeHomePath(QDir::homePath() + QLatin1String("/../foo")));
+ QCOMPARE(Utils::withTildeHomePath(QDir::homePath() + QString::fromLatin1("/foo")),
+ QDir::homePath() + QString::fromLatin1("/foo"));
+ QCOMPARE(Utils::withTildeHomePath(QDir::homePath() + QString::fromLatin1("/../foo")),
+ Utils::withTildeHomePath(QDir::homePath() + QString::fromLatin1("/../foo")));
#endif
}
+void tst_StringUtils::testMacroExpander_data()
+
+{
+ QTest::addColumn<QString>("in");
+ QTest::addColumn<QString>("out");
+
+ static const struct {
+ const char * const in;
+ const char * const out;
+ } vals[] = {
+ { "text", "text" },
+ { "%{a}", "hi" },
+ { "pre%{a}", "prehi" },
+ { "%{a}post", "hipost" },
+ { "pre%{a}post", "prehipost" },
+ { "%{a}%{a}", "hihi" },
+ { "%{a}text%{a}", "hitexthi" },
+ };
+
+ for (unsigned i = 0; i < sizeof(vals)/sizeof(vals[0]); i++)
+ QTest::newRow(vals[i].in) << QString::fromLatin1(vals[i].in)
+ << QString::fromLatin1(vals[i].out);
+}
+
+void tst_StringUtils::testMacroExpander()
+{
+ QFETCH(QString, in);
+ QFETCH(QString, out);
+
+ Utils::expandMacros(&in, &mx);
+ QCOMPARE(in, out);
+}
+
QTEST_MAIN(tst_StringUtils)
#include "tst_stringutils.moc"
diff --git a/tests/auto/utils_stringutils/utils_stringutils.pro b/tests/auto/utils_stringutils/utils_stringutils.pro
index 3c0d6552f4..41a576f5da 100644
--- a/tests/auto/utils_stringutils/utils_stringutils.pro
+++ b/tests/auto/utils_stringutils/utils_stringutils.pro
@@ -1,15 +1,13 @@
-CONFIG += qtestlib testcase
-TEMPLATE = app
-CONFIG -= app_bundle
+include(../qttest.pri)
DEFINES += QTCREATOR_UTILS_LIB
UTILS_PATH = ../../../src/libs/utils
+DEFINES -= QT_USE_FAST_OPERATOR_PLUS QT_USE_FAST_CONCATENATION
+
INCLUDEPATH += $$UTILS_PATH
# Input
SOURCES += tst_stringutils.cpp \
$$UTILS_PATH/stringutils.cpp
HEADERS += $$UTILS_PATH/stringutils.h \
$$UTILS_PATH/utils_global.h
-
-TARGET=tst_$$TARGET
diff --git a/tests/manual/ccdb/ccdb.pro b/tests/manual/ccdb/ccdb.pro
deleted file mode 100644
index 6021878be3..0000000000
--- a/tests/manual/ccdb/ccdb.pro
+++ /dev/null
@@ -1,29 +0,0 @@
-# -------------------------------------------------
-# Project created by QtCreator 2010-01-22T10:11:10
-# -------------------------------------------------
-QT += core
-TARGET = ccdb
-CONFIG += console
-CONFIG -= app_bundle
-TEMPLATE = app
-
-# -- Add CDB core engine
-CDB_CORE = ../../../src/plugins/debugger/cdb
-include($$CDB_CORE/cdbcore.pri)
-INCLUDEPATH *= $$CDB_CORE
-
-# -- Add creator 'utils' lib
-CREATOR_LIB_LIB = ../../../lib/qtcreator
-LIBS *= -L$$CREATOR_LIB_LIB
-LIBS *= -l$$qtLibraryTarget(Utilsd)
-CREATOR_LIB_SRC = ../../../src/libs
-INCLUDEPATH *= $$CREATOR_LIB_SRC
-
-# -- App sources
-SOURCES += main.cpp \
- cdbapplication.cpp \
- debugeventcallback.cpp \
- cdbpromptthread.cpp
-HEADERS += cdbapplication.h \
- debugeventcallback.h \
- cdbpromptthread.h
diff --git a/tests/manual/ccdb/main.cpp b/tests/manual/ccdb/main.cpp
deleted file mode 100644
index 963d5cc41d..0000000000
--- a/tests/manual/ccdb/main.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#include "cdbapplication.h"
-#include <QtCore/QString>
-
-int main(int argc, char *argv[])
-{
- CdbApplication app(argc, argv);
- int rc = 0;
-
- switch (app.init()) {
- case CdbApplication::InitOk:
- rc = app.exec();
- break;
- case CdbApplication::InitFailed:
- rc = 1;
- break;
- case CdbApplication::InitUsageShown:
- break;
- }
- return rc;
-}
diff --git a/tests/manual/cplusplus-dump/cplusplus-dump.pro b/tests/manual/cplusplus-dump/cplusplus-dump.pro
deleted file mode 100644
index 4964d9c5ea..0000000000
--- a/tests/manual/cplusplus-dump/cplusplus-dump.pro
+++ /dev/null
@@ -1,19 +0,0 @@
-QT = core gui
-macx:CONFIG -= app_bundle
-TARGET = cplusplus0
-
-include(../../../src/libs/cplusplus/cplusplus-lib.pri)
-
-# Input
-SOURCES += main.cpp
-
-unix {
- debug:OBJECTS_DIR = $${OUT_PWD}/.obj/debug-shared
- release:OBJECTS_DIR = $${OUT_PWD}/.obj/release-shared
-
- debug:MOC_DIR = $${OUT_PWD}/.moc/debug-shared
- release:MOC_DIR = $${OUT_PWD}/.moc/release-shared
-
- RCC_DIR = $${OUT_PWD}/.rcc/
- UI_DIR = $${OUT_PWD}/.uic/
-}
diff --git a/tests/manual/cplusplus-dump/dumpers.inc b/tests/manual/cplusplus-dump/dumpers.inc
deleted file mode 100644
index a7a5af0106..0000000000
--- a/tests/manual/cplusplus-dump/dumpers.inc
+++ /dev/null
@@ -1,1619 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is automatically generated.
-// Changes will be lost.
-//
-
-
-virtual bool visit(ObjCSelectorArgumentAST *ast)
-{
- if (ast->name_token)
- terminal(ast->name_token, ast);
- if (ast->colon_token)
- terminal(ast->colon_token, ast);
- return false;
-}
-
-virtual bool visit(ObjCSelectorAST *ast)
-{
- for (ObjCSelectorArgumentListAST *iter = ast->selector_argument_list; iter; iter = iter->next)
- nonterminal(iter->value);
- return false;
-}
-
-virtual bool visit(SimpleSpecifierAST *ast)
-{
- if (ast->specifier_token)
- terminal(ast->specifier_token, ast);
- return false;
-}
-
-virtual bool visit(AttributeSpecifierAST *ast)
-{
- if (ast->attribute_token)
- terminal(ast->attribute_token, ast);
- if (ast->first_lparen_token)
- terminal(ast->first_lparen_token, ast);
- if (ast->second_lparen_token)
- terminal(ast->second_lparen_token, ast);
- for (AttributeListAST *iter = ast->attribute_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->first_rparen_token)
- terminal(ast->first_rparen_token, ast);
- if (ast->second_rparen_token)
- terminal(ast->second_rparen_token, ast);
- return false;
-}
-
-virtual bool visit(AttributeAST *ast)
-{
- if (ast->identifier_token)
- terminal(ast->identifier_token, ast);
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- if (ast->tag_token)
- terminal(ast->tag_token, ast);
- for (ExpressionListAST *iter = ast->expression_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- return false;
-}
-
-virtual bool visit(TypeofSpecifierAST *ast)
-{
- if (ast->typeof_token)
- terminal(ast->typeof_token, ast);
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- nonterminal(ast->expression);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- return false;
-}
-
-virtual bool visit(DeclaratorAST *ast)
-{
- for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next)
- nonterminal(iter->value);
- for (PtrOperatorListAST *iter = ast->ptr_operator_list; iter; iter = iter->next)
- nonterminal(iter->value);
- nonterminal(ast->core_declarator);
- for (PostfixDeclaratorListAST *iter = ast->postfix_declarator_list; iter; iter = iter->next)
- nonterminal(iter->value);
- for (SpecifierListAST *iter = ast->post_attribute_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->equal_token)
- terminal(ast->equal_token, ast);
- nonterminal(ast->initializer);
- return false;
-}
-
-virtual bool visit(SimpleDeclarationAST *ast)
-{
- if (ast->qt_invokable_token)
- terminal(ast->qt_invokable_token, ast);
- for (SpecifierListAST *iter = ast->decl_specifier_list; iter; iter = iter->next)
- nonterminal(iter->value);
- for (DeclaratorListAST *iter = ast->declarator_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->semicolon_token)
- terminal(ast->semicolon_token, ast);
- return false;
-}
-
-virtual bool visit(EmptyDeclarationAST *ast)
-{
- if (ast->semicolon_token)
- terminal(ast->semicolon_token, ast);
- return false;
-}
-
-virtual bool visit(AccessDeclarationAST *ast)
-{
- if (ast->access_specifier_token)
- terminal(ast->access_specifier_token, ast);
- if (ast->slots_token)
- terminal(ast->slots_token, ast);
- if (ast->colon_token)
- terminal(ast->colon_token, ast);
- return false;
-}
-
-virtual bool visit(QtObjectTagAST *ast)
-{
- if (ast->q_object_token)
- terminal(ast->q_object_token, ast);
- return false;
-}
-
-virtual bool visit(QtPrivateSlotAST *ast)
-{
- if (ast->q_private_slot_token)
- terminal(ast->q_private_slot_token, ast);
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- if (ast->dptr_token)
- terminal(ast->dptr_token, ast);
- if (ast->dptr_lparen_token)
- terminal(ast->dptr_lparen_token, ast);
- if (ast->dptr_rparen_token)
- terminal(ast->dptr_rparen_token, ast);
- if (ast->comma_token)
- terminal(ast->comma_token, ast);
- for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next)
- nonterminal(iter->value);
- nonterminal(ast->declarator);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- return false;
-}
-
-virtual bool visit(QtPropertyDeclarationItemAST *ast)
-{
- if (ast->item_name_token)
- terminal(ast->item_name_token, ast);
- nonterminal(ast->expression);
- return false;
-}
-
-virtual bool visit(QtPropertyDeclarationAST *ast)
-{
- if (ast->property_specifier_token)
- terminal(ast->property_specifier_token, ast);
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- nonterminal(ast->type_id);
- nonterminal(ast->property_name);
- for (QtPropertyDeclarationItemListAST *iter = ast->property_declaration_item_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- return false;
-}
-
-virtual bool visit(QtEnumDeclarationAST *ast)
-{
- if (ast->enum_specifier_token)
- terminal(ast->enum_specifier_token, ast);
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- for (NameListAST *iter = ast->enumerator_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- return false;
-}
-
-virtual bool visit(QtFlagsDeclarationAST *ast)
-{
- if (ast->flags_specifier_token)
- terminal(ast->flags_specifier_token, ast);
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- for (NameListAST *iter = ast->flag_enums_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- return false;
-}
-
-virtual bool visit(QtInterfaceNameAST *ast)
-{
- nonterminal(ast->interface_name);
- for (NameListAST *iter = ast->constraint_list; iter; iter = iter->next)
- nonterminal(iter->value);
- return false;
-}
-
-virtual bool visit(QtInterfacesDeclarationAST *ast)
-{
- if (ast->interfaces_token)
- terminal(ast->interfaces_token, ast);
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- for (QtInterfaceNameListAST *iter = ast->interface_name_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- return false;
-}
-
-virtual bool visit(AsmDefinitionAST *ast)
-{
- if (ast->asm_token)
- terminal(ast->asm_token, ast);
- if (ast->volatile_token)
- terminal(ast->volatile_token, ast);
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- if (ast->semicolon_token)
- terminal(ast->semicolon_token, ast);
- return false;
-}
-
-virtual bool visit(BaseSpecifierAST *ast)
-{
- if (ast->virtual_token)
- terminal(ast->virtual_token, ast);
- if (ast->access_specifier_token)
- terminal(ast->access_specifier_token, ast);
- nonterminal(ast->name);
- return false;
-}
-
-virtual bool visit(IdExpressionAST *ast)
-{
- nonterminal(ast->name);
- return false;
-}
-
-virtual bool visit(CompoundExpressionAST *ast)
-{
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- nonterminal(ast->statement);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- return false;
-}
-
-virtual bool visit(CompoundLiteralAST *ast)
-{
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- nonterminal(ast->type_id);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- nonterminal(ast->initializer);
- return false;
-}
-
-virtual bool visit(QtMethodAST *ast)
-{
- if (ast->method_token)
- terminal(ast->method_token, ast);
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- nonterminal(ast->declarator);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- return false;
-}
-
-virtual bool visit(QtMemberDeclarationAST *ast)
-{
- if (ast->q_token)
- terminal(ast->q_token, ast);
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- nonterminal(ast->type_id);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- return false;
-}
-
-virtual bool visit(BinaryExpressionAST *ast)
-{
- nonterminal(ast->left_expression);
- if (ast->binary_op_token)
- terminal(ast->binary_op_token, ast);
- nonterminal(ast->right_expression);
- return false;
-}
-
-virtual bool visit(CastExpressionAST *ast)
-{
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- nonterminal(ast->type_id);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- nonterminal(ast->expression);
- return false;
-}
-
-virtual bool visit(ClassSpecifierAST *ast)
-{
- if (ast->classkey_token)
- terminal(ast->classkey_token, ast);
- for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next)
- nonterminal(iter->value);
- nonterminal(ast->name);
- if (ast->colon_token)
- terminal(ast->colon_token, ast);
- for (BaseSpecifierListAST *iter = ast->base_clause_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->dot_dot_dot_token)
- terminal(ast->dot_dot_dot_token, ast);
- if (ast->lbrace_token)
- terminal(ast->lbrace_token, ast);
- for (DeclarationListAST *iter = ast->member_specifier_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->rbrace_token)
- terminal(ast->rbrace_token, ast);
- return false;
-}
-
-virtual bool visit(CaseStatementAST *ast)
-{
- if (ast->case_token)
- terminal(ast->case_token, ast);
- nonterminal(ast->expression);
- if (ast->colon_token)
- terminal(ast->colon_token, ast);
- nonterminal(ast->statement);
- return false;
-}
-
-virtual bool visit(CompoundStatementAST *ast)
-{
- if (ast->lbrace_token)
- terminal(ast->lbrace_token, ast);
- for (StatementListAST *iter = ast->statement_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->rbrace_token)
- terminal(ast->rbrace_token, ast);
- return false;
-}
-
-virtual bool visit(ConditionAST *ast)
-{
- for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next)
- nonterminal(iter->value);
- nonterminal(ast->declarator);
- return false;
-}
-
-virtual bool visit(ConditionalExpressionAST *ast)
-{
- nonterminal(ast->condition);
- if (ast->question_token)
- terminal(ast->question_token, ast);
- nonterminal(ast->left_expression);
- if (ast->colon_token)
- terminal(ast->colon_token, ast);
- nonterminal(ast->right_expression);
- return false;
-}
-
-virtual bool visit(CppCastExpressionAST *ast)
-{
- if (ast->cast_token)
- terminal(ast->cast_token, ast);
- if (ast->less_token)
- terminal(ast->less_token, ast);
- nonterminal(ast->type_id);
- if (ast->greater_token)
- terminal(ast->greater_token, ast);
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- nonterminal(ast->expression);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- return false;
-}
-
-virtual bool visit(CtorInitializerAST *ast)
-{
- if (ast->colon_token)
- terminal(ast->colon_token, ast);
- for (MemInitializerListAST *iter = ast->member_initializer_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->dot_dot_dot_token)
- terminal(ast->dot_dot_dot_token, ast);
- return false;
-}
-
-virtual bool visit(DeclarationStatementAST *ast)
-{
- nonterminal(ast->declaration);
- return false;
-}
-
-virtual bool visit(DeclaratorIdAST *ast)
-{
- if (ast->dot_dot_dot_token)
- terminal(ast->dot_dot_dot_token, ast);
- nonterminal(ast->name);
- return false;
-}
-
-virtual bool visit(NestedDeclaratorAST *ast)
-{
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- nonterminal(ast->declarator);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- return false;
-}
-
-virtual bool visit(FunctionDeclaratorAST *ast)
-{
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- nonterminal(ast->parameter_declaration_clause);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- for (SpecifierListAST *iter = ast->cv_qualifier_list; iter; iter = iter->next)
- nonterminal(iter->value);
- nonterminal(ast->exception_specification);
- nonterminal(ast->trailing_return_type);
- nonterminal(ast->as_cpp_initializer);
- return false;
-}
-
-virtual bool visit(ArrayDeclaratorAST *ast)
-{
- if (ast->lbracket_token)
- terminal(ast->lbracket_token, ast);
- nonterminal(ast->expression);
- if (ast->rbracket_token)
- terminal(ast->rbracket_token, ast);
- return false;
-}
-
-virtual bool visit(DeleteExpressionAST *ast)
-{
- if (ast->scope_token)
- terminal(ast->scope_token, ast);
- if (ast->delete_token)
- terminal(ast->delete_token, ast);
- if (ast->lbracket_token)
- terminal(ast->lbracket_token, ast);
- if (ast->rbracket_token)
- terminal(ast->rbracket_token, ast);
- nonterminal(ast->expression);
- return false;
-}
-
-virtual bool visit(DoStatementAST *ast)
-{
- if (ast->do_token)
- terminal(ast->do_token, ast);
- nonterminal(ast->statement);
- if (ast->while_token)
- terminal(ast->while_token, ast);
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- nonterminal(ast->expression);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- if (ast->semicolon_token)
- terminal(ast->semicolon_token, ast);
- return false;
-}
-
-virtual bool visit(NamedTypeSpecifierAST *ast)
-{
- nonterminal(ast->name);
- return false;
-}
-
-virtual bool visit(ElaboratedTypeSpecifierAST *ast)
-{
- if (ast->classkey_token)
- terminal(ast->classkey_token, ast);
- for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next)
- nonterminal(iter->value);
- nonterminal(ast->name);
- return false;
-}
-
-virtual bool visit(EnumSpecifierAST *ast)
-{
- if (ast->enum_token)
- terminal(ast->enum_token, ast);
- nonterminal(ast->name);
- if (ast->lbrace_token)
- terminal(ast->lbrace_token, ast);
- for (EnumeratorListAST *iter = ast->enumerator_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->rbrace_token)
- terminal(ast->rbrace_token, ast);
- return false;
-}
-
-virtual bool visit(EnumeratorAST *ast)
-{
- if (ast->identifier_token)
- terminal(ast->identifier_token, ast);
- if (ast->equal_token)
- terminal(ast->equal_token, ast);
- nonterminal(ast->expression);
- return false;
-}
-
-virtual bool visit(ExceptionDeclarationAST *ast)
-{
- for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next)
- nonterminal(iter->value);
- nonterminal(ast->declarator);
- if (ast->dot_dot_dot_token)
- terminal(ast->dot_dot_dot_token, ast);
- return false;
-}
-
-virtual bool visit(ExceptionSpecificationAST *ast)
-{
- if (ast->throw_token)
- terminal(ast->throw_token, ast);
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- if (ast->dot_dot_dot_token)
- terminal(ast->dot_dot_dot_token, ast);
- for (ExpressionListAST *iter = ast->type_id_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- return false;
-}
-
-virtual bool visit(ExpressionOrDeclarationStatementAST *ast)
-{
- nonterminal(ast->expression);
- nonterminal(ast->declaration);
- return false;
-}
-
-virtual bool visit(ExpressionStatementAST *ast)
-{
- nonterminal(ast->expression);
- if (ast->semicolon_token)
- terminal(ast->semicolon_token, ast);
- return false;
-}
-
-virtual bool visit(FunctionDefinitionAST *ast)
-{
- if (ast->qt_invokable_token)
- terminal(ast->qt_invokable_token, ast);
- for (SpecifierListAST *iter = ast->decl_specifier_list; iter; iter = iter->next)
- nonterminal(iter->value);
- nonterminal(ast->declarator);
- nonterminal(ast->ctor_initializer);
- nonterminal(ast->function_body);
- return false;
-}
-
-virtual bool visit(ForeachStatementAST *ast)
-{
- if (ast->foreach_token)
- terminal(ast->foreach_token, ast);
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next)
- nonterminal(iter->value);
- nonterminal(ast->declarator);
- nonterminal(ast->initializer);
- if (ast->comma_token)
- terminal(ast->comma_token, ast);
- nonterminal(ast->expression);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- nonterminal(ast->statement);
- return false;
-}
-
-virtual bool visit(ForStatementAST *ast)
-{
- if (ast->for_token)
- terminal(ast->for_token, ast);
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- nonterminal(ast->initializer);
- nonterminal(ast->condition);
- if (ast->semicolon_token)
- terminal(ast->semicolon_token, ast);
- nonterminal(ast->expression);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- nonterminal(ast->statement);
- return false;
-}
-
-virtual bool visit(IfStatementAST *ast)
-{
- if (ast->if_token)
- terminal(ast->if_token, ast);
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- nonterminal(ast->condition);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- nonterminal(ast->statement);
- if (ast->else_token)
- terminal(ast->else_token, ast);
- nonterminal(ast->else_statement);
- return false;
-}
-
-virtual bool visit(ArrayInitializerAST *ast)
-{
- if (ast->lbrace_token)
- terminal(ast->lbrace_token, ast);
- for (ExpressionListAST *iter = ast->expression_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->rbrace_token)
- terminal(ast->rbrace_token, ast);
- return false;
-}
-
-virtual bool visit(LabeledStatementAST *ast)
-{
- if (ast->label_token)
- terminal(ast->label_token, ast);
- if (ast->colon_token)
- terminal(ast->colon_token, ast);
- nonterminal(ast->statement);
- return false;
-}
-
-virtual bool visit(LinkageBodyAST *ast)
-{
- if (ast->lbrace_token)
- terminal(ast->lbrace_token, ast);
- for (DeclarationListAST *iter = ast->declaration_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->rbrace_token)
- terminal(ast->rbrace_token, ast);
- return false;
-}
-
-virtual bool visit(LinkageSpecificationAST *ast)
-{
- if (ast->extern_token)
- terminal(ast->extern_token, ast);
- if (ast->extern_type_token)
- terminal(ast->extern_type_token, ast);
- nonterminal(ast->declaration);
- return false;
-}
-
-virtual bool visit(MemInitializerAST *ast)
-{
- nonterminal(ast->name);
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- for (ExpressionListAST *iter = ast->expression_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- return false;
-}
-
-virtual bool visit(NestedNameSpecifierAST *ast)
-{
- nonterminal(ast->class_or_namespace_name);
- if (ast->scope_token)
- terminal(ast->scope_token, ast);
- return false;
-}
-
-virtual bool visit(QualifiedNameAST *ast)
-{
- if (ast->global_scope_token)
- terminal(ast->global_scope_token, ast);
- for (NestedNameSpecifierListAST *iter = ast->nested_name_specifier_list; iter; iter = iter->next)
- nonterminal(iter->value);
- nonterminal(ast->unqualified_name);
- return false;
-}
-
-virtual bool visit(OperatorFunctionIdAST *ast)
-{
- if (ast->operator_token)
- terminal(ast->operator_token, ast);
- nonterminal(ast->op);
- return false;
-}
-
-virtual bool visit(ConversionFunctionIdAST *ast)
-{
- if (ast->operator_token)
- terminal(ast->operator_token, ast);
- for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next)
- nonterminal(iter->value);
- for (PtrOperatorListAST *iter = ast->ptr_operator_list; iter; iter = iter->next)
- nonterminal(iter->value);
- return false;
-}
-
-virtual bool visit(SimpleNameAST *ast)
-{
- if (ast->identifier_token)
- terminal(ast->identifier_token, ast);
- return false;
-}
-
-virtual bool visit(DestructorNameAST *ast)
-{
- if (ast->tilde_token)
- terminal(ast->tilde_token, ast);
- if (ast->identifier_token)
- terminal(ast->identifier_token, ast);
- return false;
-}
-
-virtual bool visit(TemplateIdAST *ast)
-{
- if (ast->template_token)
- terminal(ast->template_token, ast);
- if (ast->identifier_token)
- terminal(ast->identifier_token, ast);
- if (ast->less_token)
- terminal(ast->less_token, ast);
- for (ExpressionListAST *iter = ast->template_argument_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->greater_token)
- terminal(ast->greater_token, ast);
- return false;
-}
-
-virtual bool visit(NamespaceAST *ast)
-{
- if (ast->namespace_token)
- terminal(ast->namespace_token, ast);
- if (ast->identifier_token)
- terminal(ast->identifier_token, ast);
- for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next)
- nonterminal(iter->value);
- nonterminal(ast->linkage_body);
- return false;
-}
-
-virtual bool visit(NamespaceAliasDefinitionAST *ast)
-{
- if (ast->namespace_token)
- terminal(ast->namespace_token, ast);
- if (ast->namespace_name_token)
- terminal(ast->namespace_name_token, ast);
- if (ast->equal_token)
- terminal(ast->equal_token, ast);
- nonterminal(ast->name);
- if (ast->semicolon_token)
- terminal(ast->semicolon_token, ast);
- return false;
-}
-
-virtual bool visit(NewPlacementAST *ast)
-{
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- for (ExpressionListAST *iter = ast->expression_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- return false;
-}
-
-virtual bool visit(NewArrayDeclaratorAST *ast)
-{
- if (ast->lbracket_token)
- terminal(ast->lbracket_token, ast);
- nonterminal(ast->expression);
- if (ast->rbracket_token)
- terminal(ast->rbracket_token, ast);
- return false;
-}
-
-virtual bool visit(NewExpressionAST *ast)
-{
- if (ast->scope_token)
- terminal(ast->scope_token, ast);
- if (ast->new_token)
- terminal(ast->new_token, ast);
- nonterminal(ast->new_placement);
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- nonterminal(ast->type_id);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- nonterminal(ast->new_type_id);
- nonterminal(ast->new_initializer);
- return false;
-}
-
-virtual bool visit(NewInitializerAST *ast)
-{
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- nonterminal(ast->expression);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- return false;
-}
-
-virtual bool visit(NewTypeIdAST *ast)
-{
- for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next)
- nonterminal(iter->value);
- for (PtrOperatorListAST *iter = ast->ptr_operator_list; iter; iter = iter->next)
- nonterminal(iter->value);
- for (NewArrayDeclaratorListAST *iter = ast->new_array_declarator_list; iter; iter = iter->next)
- nonterminal(iter->value);
- return false;
-}
-
-virtual bool visit(OperatorAST *ast)
-{
- if (ast->op_token)
- terminal(ast->op_token, ast);
- if (ast->open_token)
- terminal(ast->open_token, ast);
- if (ast->close_token)
- terminal(ast->close_token, ast);
- return false;
-}
-
-virtual bool visit(ParameterDeclarationAST *ast)
-{
- for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next)
- nonterminal(iter->value);
- nonterminal(ast->declarator);
- if (ast->equal_token)
- terminal(ast->equal_token, ast);
- nonterminal(ast->expression);
- return false;
-}
-
-virtual bool visit(ParameterDeclarationClauseAST *ast)
-{
- for (ParameterDeclarationListAST *iter = ast->parameter_declaration_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->dot_dot_dot_token)
- terminal(ast->dot_dot_dot_token, ast);
- return false;
-}
-
-virtual bool visit(CallAST *ast)
-{
- nonterminal(ast->base_expression);
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- for (ExpressionListAST *iter = ast->expression_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- return false;
-}
-
-virtual bool visit(ArrayAccessAST *ast)
-{
- nonterminal(ast->base_expression);
- if (ast->lbracket_token)
- terminal(ast->lbracket_token, ast);
- nonterminal(ast->expression);
- if (ast->rbracket_token)
- terminal(ast->rbracket_token, ast);
- return false;
-}
-
-virtual bool visit(PostIncrDecrAST *ast)
-{
- nonterminal(ast->base_expression);
- if (ast->incr_decr_token)
- terminal(ast->incr_decr_token, ast);
- return false;
-}
-
-virtual bool visit(MemberAccessAST *ast)
-{
- nonterminal(ast->base_expression);
- if (ast->access_token)
- terminal(ast->access_token, ast);
- if (ast->template_token)
- terminal(ast->template_token, ast);
- nonterminal(ast->member_name);
- return false;
-}
-
-virtual bool visit(TypeidExpressionAST *ast)
-{
- if (ast->typeid_token)
- terminal(ast->typeid_token, ast);
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- nonterminal(ast->expression);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- return false;
-}
-
-virtual bool visit(TypenameCallExpressionAST *ast)
-{
- if (ast->typename_token)
- terminal(ast->typename_token, ast);
- nonterminal(ast->name);
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- for (ExpressionListAST *iter = ast->expression_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- return false;
-}
-
-virtual bool visit(TypeConstructorCallAST *ast)
-{
- for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- for (ExpressionListAST *iter = ast->expression_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- return false;
-}
-
-virtual bool visit(PointerToMemberAST *ast)
-{
- if (ast->global_scope_token)
- terminal(ast->global_scope_token, ast);
- for (NestedNameSpecifierListAST *iter = ast->nested_name_specifier_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->star_token)
- terminal(ast->star_token, ast);
- for (SpecifierListAST *iter = ast->cv_qualifier_list; iter; iter = iter->next)
- nonterminal(iter->value);
- return false;
-}
-
-virtual bool visit(PointerAST *ast)
-{
- if (ast->star_token)
- terminal(ast->star_token, ast);
- for (SpecifierListAST *iter = ast->cv_qualifier_list; iter; iter = iter->next)
- nonterminal(iter->value);
- return false;
-}
-
-virtual bool visit(ReferenceAST *ast)
-{
- if (ast->reference_token)
- terminal(ast->reference_token, ast);
- return false;
-}
-
-virtual bool visit(BreakStatementAST *ast)
-{
- if (ast->break_token)
- terminal(ast->break_token, ast);
- if (ast->semicolon_token)
- terminal(ast->semicolon_token, ast);
- return false;
-}
-
-virtual bool visit(ContinueStatementAST *ast)
-{
- if (ast->continue_token)
- terminal(ast->continue_token, ast);
- if (ast->semicolon_token)
- terminal(ast->semicolon_token, ast);
- return false;
-}
-
-virtual bool visit(GotoStatementAST *ast)
-{
- if (ast->goto_token)
- terminal(ast->goto_token, ast);
- if (ast->identifier_token)
- terminal(ast->identifier_token, ast);
- if (ast->semicolon_token)
- terminal(ast->semicolon_token, ast);
- return false;
-}
-
-virtual bool visit(ReturnStatementAST *ast)
-{
- if (ast->return_token)
- terminal(ast->return_token, ast);
- nonterminal(ast->expression);
- if (ast->semicolon_token)
- terminal(ast->semicolon_token, ast);
- return false;
-}
-
-virtual bool visit(SizeofExpressionAST *ast)
-{
- if (ast->sizeof_token)
- terminal(ast->sizeof_token, ast);
- if (ast->dot_dot_dot_token)
- terminal(ast->dot_dot_dot_token, ast);
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- nonterminal(ast->expression);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- return false;
-}
-
-virtual bool visit(NumericLiteralAST *ast)
-{
- if (ast->literal_token)
- terminal(ast->literal_token, ast);
- return false;
-}
-
-virtual bool visit(BoolLiteralAST *ast)
-{
- if (ast->literal_token)
- terminal(ast->literal_token, ast);
- return false;
-}
-
-virtual bool visit(ThisExpressionAST *ast)
-{
- if (ast->this_token)
- terminal(ast->this_token, ast);
- return false;
-}
-
-virtual bool visit(NestedExpressionAST *ast)
-{
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- nonterminal(ast->expression);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- return false;
-}
-
-virtual bool visit(StringLiteralAST *ast)
-{
- if (ast->literal_token)
- terminal(ast->literal_token, ast);
- nonterminal(ast->next);
- return false;
-}
-
-virtual bool visit(SwitchStatementAST *ast)
-{
- if (ast->switch_token)
- terminal(ast->switch_token, ast);
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- nonterminal(ast->condition);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- nonterminal(ast->statement);
- return false;
-}
-
-virtual bool visit(TemplateDeclarationAST *ast)
-{
- if (ast->export_token)
- terminal(ast->export_token, ast);
- if (ast->template_token)
- terminal(ast->template_token, ast);
- if (ast->less_token)
- terminal(ast->less_token, ast);
- for (DeclarationListAST *iter = ast->template_parameter_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->greater_token)
- terminal(ast->greater_token, ast);
- nonterminal(ast->declaration);
- return false;
-}
-
-virtual bool visit(ThrowExpressionAST *ast)
-{
- if (ast->throw_token)
- terminal(ast->throw_token, ast);
- nonterminal(ast->expression);
- return false;
-}
-
-virtual bool visit(TranslationUnitAST *ast)
-{
- for (DeclarationListAST *iter = ast->declaration_list; iter; iter = iter->next)
- nonterminal(iter->value);
- return false;
-}
-
-virtual bool visit(TryBlockStatementAST *ast)
-{
- if (ast->try_token)
- terminal(ast->try_token, ast);
- nonterminal(ast->statement);
- for (CatchClauseListAST *iter = ast->catch_clause_list; iter; iter = iter->next)
- nonterminal(iter->value);
- return false;
-}
-
-virtual bool visit(CatchClauseAST *ast)
-{
- if (ast->catch_token)
- terminal(ast->catch_token, ast);
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- nonterminal(ast->exception_declaration);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- nonterminal(ast->statement);
- return false;
-}
-
-virtual bool visit(TypeIdAST *ast)
-{
- for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next)
- nonterminal(iter->value);
- nonterminal(ast->declarator);
- return false;
-}
-
-virtual bool visit(TypenameTypeParameterAST *ast)
-{
- if (ast->classkey_token)
- terminal(ast->classkey_token, ast);
- if (ast->dot_dot_dot_token)
- terminal(ast->dot_dot_dot_token, ast);
- nonterminal(ast->name);
- if (ast->equal_token)
- terminal(ast->equal_token, ast);
- nonterminal(ast->type_id);
- return false;
-}
-
-virtual bool visit(TemplateTypeParameterAST *ast)
-{
- if (ast->template_token)
- terminal(ast->template_token, ast);
- if (ast->less_token)
- terminal(ast->less_token, ast);
- for (DeclarationListAST *iter = ast->template_parameter_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->greater_token)
- terminal(ast->greater_token, ast);
- if (ast->class_token)
- terminal(ast->class_token, ast);
- if (ast->dot_dot_dot_token)
- terminal(ast->dot_dot_dot_token, ast);
- nonterminal(ast->name);
- if (ast->equal_token)
- terminal(ast->equal_token, ast);
- nonterminal(ast->type_id);
- return false;
-}
-
-virtual bool visit(UnaryExpressionAST *ast)
-{
- if (ast->unary_op_token)
- terminal(ast->unary_op_token, ast);
- nonterminal(ast->expression);
- return false;
-}
-
-virtual bool visit(UsingAST *ast)
-{
- if (ast->using_token)
- terminal(ast->using_token, ast);
- if (ast->typename_token)
- terminal(ast->typename_token, ast);
- nonterminal(ast->name);
- if (ast->semicolon_token)
- terminal(ast->semicolon_token, ast);
- return false;
-}
-
-virtual bool visit(UsingDirectiveAST *ast)
-{
- if (ast->using_token)
- terminal(ast->using_token, ast);
- if (ast->namespace_token)
- terminal(ast->namespace_token, ast);
- nonterminal(ast->name);
- if (ast->semicolon_token)
- terminal(ast->semicolon_token, ast);
- return false;
-}
-
-virtual bool visit(WhileStatementAST *ast)
-{
- if (ast->while_token)
- terminal(ast->while_token, ast);
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- nonterminal(ast->condition);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- nonterminal(ast->statement);
- return false;
-}
-
-virtual bool visit(ObjCClassForwardDeclarationAST *ast)
-{
- for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->class_token)
- terminal(ast->class_token, ast);
- for (NameListAST *iter = ast->identifier_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->semicolon_token)
- terminal(ast->semicolon_token, ast);
- return false;
-}
-
-virtual bool visit(ObjCClassDeclarationAST *ast)
-{
- for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->interface_token)
- terminal(ast->interface_token, ast);
- if (ast->implementation_token)
- terminal(ast->implementation_token, ast);
- nonterminal(ast->class_name);
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- nonterminal(ast->category_name);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- if (ast->colon_token)
- terminal(ast->colon_token, ast);
- nonterminal(ast->superclass);
- nonterminal(ast->protocol_refs);
- nonterminal(ast->inst_vars_decl);
- for (DeclarationListAST *iter = ast->member_declaration_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->end_token)
- terminal(ast->end_token, ast);
- return false;
-}
-
-virtual bool visit(ObjCProtocolForwardDeclarationAST *ast)
-{
- for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->protocol_token)
- terminal(ast->protocol_token, ast);
- for (NameListAST *iter = ast->identifier_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->semicolon_token)
- terminal(ast->semicolon_token, ast);
- return false;
-}
-
-virtual bool visit(ObjCProtocolDeclarationAST *ast)
-{
- for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->protocol_token)
- terminal(ast->protocol_token, ast);
- nonterminal(ast->name);
- nonterminal(ast->protocol_refs);
- for (DeclarationListAST *iter = ast->member_declaration_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->end_token)
- terminal(ast->end_token, ast);
- return false;
-}
-
-virtual bool visit(ObjCProtocolRefsAST *ast)
-{
- if (ast->less_token)
- terminal(ast->less_token, ast);
- for (NameListAST *iter = ast->identifier_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->greater_token)
- terminal(ast->greater_token, ast);
- return false;
-}
-
-virtual bool visit(ObjCMessageArgumentAST *ast)
-{
- nonterminal(ast->parameter_value_expression);
- return false;
-}
-
-virtual bool visit(ObjCMessageExpressionAST *ast)
-{
- if (ast->lbracket_token)
- terminal(ast->lbracket_token, ast);
- nonterminal(ast->receiver_expression);
- nonterminal(ast->selector);
- for (ObjCMessageArgumentListAST *iter = ast->argument_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->rbracket_token)
- terminal(ast->rbracket_token, ast);
- return false;
-}
-
-virtual bool visit(ObjCProtocolExpressionAST *ast)
-{
- if (ast->protocol_token)
- terminal(ast->protocol_token, ast);
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- if (ast->identifier_token)
- terminal(ast->identifier_token, ast);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- return false;
-}
-
-virtual bool visit(ObjCTypeNameAST *ast)
-{
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- if (ast->type_qualifier_token)
- terminal(ast->type_qualifier_token, ast);
- nonterminal(ast->type_id);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- return false;
-}
-
-virtual bool visit(ObjCEncodeExpressionAST *ast)
-{
- if (ast->encode_token)
- terminal(ast->encode_token, ast);
- nonterminal(ast->type_name);
- return false;
-}
-
-virtual bool visit(ObjCSelectorExpressionAST *ast)
-{
- if (ast->selector_token)
- terminal(ast->selector_token, ast);
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- nonterminal(ast->selector);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- return false;
-}
-
-virtual bool visit(ObjCInstanceVariablesDeclarationAST *ast)
-{
- if (ast->lbrace_token)
- terminal(ast->lbrace_token, ast);
- for (DeclarationListAST *iter = ast->instance_variable_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->rbrace_token)
- terminal(ast->rbrace_token, ast);
- return false;
-}
-
-virtual bool visit(ObjCVisibilityDeclarationAST *ast)
-{
- if (ast->visibility_token)
- terminal(ast->visibility_token, ast);
- return false;
-}
-
-virtual bool visit(ObjCPropertyAttributeAST *ast)
-{
- if (ast->attribute_identifier_token)
- terminal(ast->attribute_identifier_token, ast);
- if (ast->equals_token)
- terminal(ast->equals_token, ast);
- nonterminal(ast->method_selector);
- return false;
-}
-
-virtual bool visit(ObjCPropertyDeclarationAST *ast)
-{
- for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->property_token)
- terminal(ast->property_token, ast);
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- for (ObjCPropertyAttributeListAST *iter = ast->property_attribute_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- nonterminal(ast->simple_declaration);
- return false;
-}
-
-virtual bool visit(ObjCMessageArgumentDeclarationAST *ast)
-{
- nonterminal(ast->type_name);
- for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next)
- nonterminal(iter->value);
- nonterminal(ast->param_name);
- return false;
-}
-
-virtual bool visit(ObjCMethodPrototypeAST *ast)
-{
- if (ast->method_type_token)
- terminal(ast->method_type_token, ast);
- nonterminal(ast->type_name);
- nonterminal(ast->selector);
- for (ObjCMessageArgumentDeclarationListAST *iter = ast->argument_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->dot_dot_dot_token)
- terminal(ast->dot_dot_dot_token, ast);
- for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next)
- nonterminal(iter->value);
- return false;
-}
-
-virtual bool visit(ObjCMethodDeclarationAST *ast)
-{
- nonterminal(ast->method_prototype);
- nonterminal(ast->function_body);
- if (ast->semicolon_token)
- terminal(ast->semicolon_token, ast);
- return false;
-}
-
-virtual bool visit(ObjCSynthesizedPropertyAST *ast)
-{
- if (ast->property_identifier_token)
- terminal(ast->property_identifier_token, ast);
- if (ast->equals_token)
- terminal(ast->equals_token, ast);
- if (ast->alias_identifier_token)
- terminal(ast->alias_identifier_token, ast);
- return false;
-}
-
-virtual bool visit(ObjCSynthesizedPropertiesDeclarationAST *ast)
-{
- if (ast->synthesized_token)
- terminal(ast->synthesized_token, ast);
- for (ObjCSynthesizedPropertyListAST *iter = ast->property_identifier_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->semicolon_token)
- terminal(ast->semicolon_token, ast);
- return false;
-}
-
-virtual bool visit(ObjCDynamicPropertiesDeclarationAST *ast)
-{
- if (ast->dynamic_token)
- terminal(ast->dynamic_token, ast);
- for (NameListAST *iter = ast->property_identifier_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->semicolon_token)
- terminal(ast->semicolon_token, ast);
- return false;
-}
-
-virtual bool visit(ObjCFastEnumerationAST *ast)
-{
- if (ast->for_token)
- terminal(ast->for_token, ast);
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next)
- nonterminal(iter->value);
- nonterminal(ast->declarator);
- nonterminal(ast->initializer);
- if (ast->in_token)
- terminal(ast->in_token, ast);
- nonterminal(ast->fast_enumeratable_expression);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- nonterminal(ast->statement);
- return false;
-}
-
-virtual bool visit(ObjCSynchronizedStatementAST *ast)
-{
- if (ast->synchronized_token)
- terminal(ast->synchronized_token, ast);
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- nonterminal(ast->synchronized_object);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- nonterminal(ast->statement);
- return false;
-}
-
-virtual bool visit(LambdaExpressionAST *ast)
-{
- nonterminal(ast->lambda_introducer);
- nonterminal(ast->lambda_declarator);
- nonterminal(ast->statement);
- return false;
-}
-
-virtual bool visit(LambdaIntroducerAST *ast)
-{
- if (ast->lbracket_token)
- terminal(ast->lbracket_token, ast);
- nonterminal(ast->lambda_capture);
- if (ast->rbracket_token)
- terminal(ast->rbracket_token, ast);
- return false;
-}
-
-virtual bool visit(LambdaCaptureAST *ast)
-{
- if (ast->default_capture_token)
- terminal(ast->default_capture_token, ast);
- for (CaptureListAST *iter = ast->capture_list; iter; iter = iter->next)
- nonterminal(iter->value);
- return false;
-}
-
-virtual bool visit(CaptureAST *ast)
-{
- return false;
-}
-
-virtual bool visit(LambdaDeclaratorAST *ast)
-{
- if (ast->lparen_token)
- terminal(ast->lparen_token, ast);
- nonterminal(ast->parameter_declaration_clause);
- if (ast->rparen_token)
- terminal(ast->rparen_token, ast);
- for (SpecifierListAST *iter = ast->attributes; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->mutable_token)
- terminal(ast->mutable_token, ast);
- nonterminal(ast->exception_specification);
- nonterminal(ast->trailing_return_type);
- return false;
-}
-
-virtual bool visit(TrailingReturnTypeAST *ast)
-{
- if (ast->arrow_token)
- terminal(ast->arrow_token, ast);
- for (SpecifierListAST *iter = ast->attributes; iter; iter = iter->next)
- nonterminal(iter->value);
- for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next)
- nonterminal(iter->value);
- nonterminal(ast->declarator);
- return false;
-}
-
-virtual bool visit(BracedInitializerAST *ast)
-{
- if (ast->lbrace_token)
- terminal(ast->lbrace_token, ast);
- for (ExpressionListAST *iter = ast->expression_list; iter; iter = iter->next)
- nonterminal(iter->value);
- if (ast->comma_token)
- terminal(ast->comma_token, ast);
- if (ast->rbrace_token)
- terminal(ast->rbrace_token, ast);
- return false;
-}
-
diff --git a/tests/manual/cplusplus-frontend/cplusplus-frontend.pro b/tests/manual/cplusplus-frontend/cplusplus-frontend.pro
index 4964d9c5ea..8169adfe91 100644
--- a/tests/manual/cplusplus-frontend/cplusplus-frontend.pro
+++ b/tests/manual/cplusplus-frontend/cplusplus-frontend.pro
@@ -1,8 +1,8 @@
QT = core gui
macx:CONFIG -= app_bundle
TARGET = cplusplus0
-
-include(../../../src/libs/cplusplus/cplusplus-lib.pri)
+include(../../../qtcreator.pri)
+include(../../../src/libs/cplusplus/cplusplus.pri)
# Input
SOURCES += main.cpp
diff --git a/tests/manual/cplusplus-tools/cplusplus-tools.pro b/tests/manual/cplusplus-tools/cplusplus-tools.pro
new file mode 100644
index 0000000000..5645f72ff0
--- /dev/null
+++ b/tests/manual/cplusplus-tools/cplusplus-tools.pro
@@ -0,0 +1,24 @@
+#-------------------------------------------------
+#
+# Project created by QtCreator 2010-10-01T13:24:32
+#
+#-------------------------------------------------
+
+QT += core
+
+QT -= gui
+
+TARGET = cplusplus-tools
+CONFIG += console
+CONFIG -= app_bundle
+
+TEMPLATE = app
+
+
+SOURCES += main.cpp \
+ dummy.cpp \
+ detail/source.cpp
+
+HEADERS += \
+ dummy.h \
+ detail/header.h
diff --git a/tests/manual/cplusplus-tools/detail/header.h b/tests/manual/cplusplus-tools/detail/header.h
new file mode 100644
index 0000000000..2bce9d04bc
--- /dev/null
+++ b/tests/manual/cplusplus-tools/detail/header.h
@@ -0,0 +1,30 @@
+#ifndef HEADER_H
+#define HEADER_H
+
+#include <QtGlobal>
+
+QT_BEGIN_NAMESPACE
+class QString;
+QT_END_NAMESPACE
+
+struct A {};
+struct B : virtual A {};
+struct C : virtual A {};
+struct D : B, C {};
+
+inline int freefunc1()
+{ return 1; }
+
+int freefunc2(int);
+int freefunc2(double);
+int freefunc2(const QString &);
+
+template <class T>
+void freefunc3(T)
+{}
+
+template <class T>
+void freefunc3(T, int)
+{}
+
+#endif //HEADER_H
diff --git a/tests/manual/cplusplus-tools/detail/source.cpp b/tests/manual/cplusplus-tools/detail/source.cpp
new file mode 100644
index 0000000000..81af534013
--- /dev/null
+++ b/tests/manual/cplusplus-tools/detail/source.cpp
@@ -0,0 +1,19 @@
+#include "header.h"
+#include "dummy.h"
+
+#include <QtCore/QString>
+
+int xi = 10;
+
+int freefunc2(int a) { return a; }
+
+int freefunc2(double)
+{ return 1; }
+
+int freefunc2(const QString &)
+{ return 1; }
+
+void here() {
+ test::Dummy d;
+ d;
+}
diff --git a/tests/manual/cplusplus-tools/dummy.cpp b/tests/manual/cplusplus-tools/dummy.cpp
new file mode 100644
index 0000000000..4700050d44
--- /dev/null
+++ b/tests/manual/cplusplus-tools/dummy.cpp
@@ -0,0 +1,32 @@
+#include "dummy.h"
+#include "detail/header.h"
+
+using namespace test;
+
+extern int xi;
+
+Dummy::Dummy()
+{}
+
+Dummy::Dummy(int)
+{
+ xi = 0;
+ freefunc2(1.0);
+}
+
+void Dummy::bla(int)
+{}
+
+void Dummy::bla(const QString &)
+{}
+
+void Dummy::bla(const QString &) const
+{}
+
+void Dummy::bla(int, const QString &) const
+{}
+
+void Dummy::sfunc()
+{}
+
+const double Dummy::PI = 3.14;
diff --git a/tests/manual/cplusplus-tools/dummy.h b/tests/manual/cplusplus-tools/dummy.h
new file mode 100644
index 0000000000..0ae7756ad4
--- /dev/null
+++ b/tests/manual/cplusplus-tools/dummy.h
@@ -0,0 +1,50 @@
+#ifndef DUMMY_H
+#define DUMMY_H
+
+#include <QString>
+
+namespace test {
+
+class Dummy
+{
+public:
+ Dummy();
+ Dummy(int a);
+
+ typedef int INT;
+
+ enum Values {
+ v1,
+ v2,
+ v3
+ };
+
+ static const int ONE = 1;
+ static const double PI;
+
+ static void sfunc();
+
+ struct Internal
+ {
+ QString one;
+ typedef double DOUBLE;
+ };
+
+ void bla(int);
+ void bla(const QString &);
+ void bla(const QString &) const;
+ void bla(int, const QString &) const;
+
+ void foo(int) const {}
+ void foo(const QString &) const {}
+
+ QString one;
+};
+
+class ChildDummy : public Dummy {};
+
+class GrandChildDummy : public Dummy {};
+
+} // namespace test
+
+#endif // DUMMY_H
diff --git a/tests/manual/cplusplus-tools/main.cpp b/tests/manual/cplusplus-tools/main.cpp
new file mode 100644
index 0000000000..6e5948a833
--- /dev/null
+++ b/tests/manual/cplusplus-tools/main.cpp
@@ -0,0 +1,175 @@
+/*
+ * Below are some basic test suggestions. Trying them in a larger
+ * project (Qt Creator, for example) is also valid.
+ */
+
+/*
+ Folow includes
+ */
+#include <QDebug>
+#include <QtCore/QString>
+#include <iostream>
+#include <vector>
+#include <cstdio>
+//#include <Windows.h>
+//#include <linux/version.h>
+#include "dummy.h"
+#include "detail/header.h"
+
+/*
+ Complete includes
+ */
+//#include <QDe
+//#include <QtCor
+//#include <QtCore/QXmlStream
+
+//#include <ios
+//#include <vec
+//#include <cstd
+
+//#include <Win
+//#include <lin
+
+//#include "dum
+//#include "deta
+//#include "detail/hea
+
+
+using namespace test;
+
+int fi = 10;
+extern int xi;
+const int ci = 1;
+
+namespace {
+int ai = 100;
+int afunc() {
+ return fi * xi + ai + ci;
+}
+}
+
+/*
+ Follow symbols
+ - Expect some issues when finding the best function overload and with templates.
+ - Try using a local namespace directive instead of the global one.
+ */
+using namespace test;
+void testFollowSymbols()
+{
+ //using namespace test;
+
+ Dummy dummy;
+ Dummy::sfunc();
+ Dummy::ONE;
+ Dummy::PI;
+ dummy.bla(fi);
+ dummy.bla("bla");
+ dummy.one = "one";
+ Dummy::Internal internal;
+ internal.one = "one";
+ Dummy::INT i;
+ Dummy::Values V;
+ Dummy::v1;
+ freefunc1();
+ freefunc2(10);
+ freefunc2("s");
+ freefunc3(dummy);
+ freefunc3(dummy, 10);
+ freefunc3(10, 10);
+ freefunc3(1.0);
+ afunc();
+ i;
+ V;
+}
+
+/*
+ Complete symbols
+ - Check function arguments.
+ */
+void testCompleteSymbols()
+{
+ test::Dummy dummy;
+ test::Dummy::Internal internal;
+
+// in
+// Dum
+// Dummy::s
+// Dummy::O
+// Dummy::P
+// dummy.
+// dummy.b
+// dummy.bla(
+// dummy.o
+// Dummy::In
+// internal.o
+// Dummy::Internal::
+// freefunc2
+// using namespace st
+// afun
+}
+
+/*
+ Complete snippets
+ */
+void testCompleteSnippets()
+{
+// for
+// class
+// whil
+}
+
+/*
+ Find usages
+ - Go to other files for more options.
+ */
+void testFindUsages()
+{
+ Dummy();
+ Dummy::sfunc();
+ Dummy::ONE;
+ xi;
+ fi;
+ ci;
+ ai;
+ afunc();
+ freefunc1();
+ freefunc2("s");
+}
+
+/*
+ Rename
+ - Compile to make sure.
+ - Go to other files for more options.
+ */
+void testRename()
+{
+ fi;
+ ci;
+ ai;
+ afunc();
+ testCompleteSnippets();
+}
+
+/*
+ Type hierarchy
+ */
+void testTypeHierarchy()
+{
+ test::GrandChildDummy();
+ D();
+}
+
+/*
+ Switch declaration/definition
+ - Use methods from Dummy.
+ */
+
+/*
+ Switch header/source
+ - Use dummy.h and dummy.cpp.
+ */
+
+int main()
+{
+ return 0;
+}
diff --git a/tests/manual/cppquickfix/convertnumericliteral.cpp b/tests/manual/cppquickfix/convertnumericliteral.cpp
index 6d64c98e7f..38bee62303 100644
--- a/tests/manual/cppquickfix/convertnumericliteral.cpp
+++ b/tests/manual/cppquickfix/convertnumericliteral.cpp
@@ -10,7 +10,7 @@ int main()
0xFA0Bu;
// uppercase X
0X856A;
- // negativ values
+ // negative values
-199;
-017;
// not integer, do nothing
diff --git a/tests/manual/fakevim/README b/tests/manual/fakevim/README
new file mode 100644
index 0000000000..3c83dcbec9
--- /dev/null
+++ b/tests/manual/fakevim/README
@@ -0,0 +1,2 @@
+This is not part of the test suite. It only serves as a target for remote
+debugging and proof that fakevim is independent from Creator core.
diff --git a/tests/manual/fakevim/fakevim.pro b/tests/manual/fakevim/fakevim.pro
index f3b5c0d662..df177d3a71 100644
--- a/tests/manual/fakevim/fakevim.pro
+++ b/tests/manual/fakevim/fakevim.pro
@@ -1,26 +1,17 @@
+include(../../../qtcreator.pri)
+include(../../../src/libs/utils/utils.pri)
-FAKEVIMHOME = ../../../src/plugins/fakevim
-UTILSDIR = ../../../src/libs
+FAKEVIMDIR = $$IDE_SOURCE_TREE/src/plugins/fakevim
+LIBSDIR = $$IDE_SOURCE_TREE/src/libs
-DEFINES += QTCREATOR_UTILS_STATIC_LIB
-SOURCES += \
- main.cpp \
- $$FAKEVIMHOME/fakevimhandler.cpp \
- $$FAKEVIMHOME/fakevimactions.cpp \
- $$FAKEVIMHOME/fakevimsyntax.cpp \
- $$UTILSDIR/utils/savedaction.cpp \
- $$UTILSDIR/utils/pathchooser.cpp \
- $$UTILSDIR/utils/environment.cpp \
- $$UTILSDIR/utils/basevalidatinglineedit.cpp \
+SOURCES += main.cpp \
+ $$FAKEVIMDIR/fakevimhandler.cpp \
+ $$FAKEVIMDIR/fakevimactions.cpp \
+ $$FAKEVIMDIR/fakevimsyntax.cpp \
-HEADERS += \
- $$FAKEVIMHOME/fakevimhandler.h \
- $$FAKEVIMHOME/fakevimactions.h \
- $$FAKEVIMHOME/fakevimsyntax.h \
- $$UTILSDIR/utils/savedaction.h \
- $$UTILSDIR/utils/pathchooser.h \
- $$UTILSDIR/utils/environment.h \
- $$UTILSDIR/utils/basevalidatinglineedit.h \
+HEADERS += $$FAKEVIMDIR/fakevimhandler.h \
+ $$FAKEVIMDIR/fakevimactions.h \
+ $$FAKEVIMDIR/fakevimsyntax.h \
-INCLUDEPATH += $$FAKEVIMHOME $$UTILSDIR
+INCLUDEPATH += $$FAKEVIMDIR $$LIBSDIR
diff --git a/tests/manual/gdbdebugger/gui/mainwindow.cpp b/tests/manual/gdbdebugger/gui/mainwindow.cpp
index 938ed42662..5fe6478763 100644
--- a/tests/manual/gdbdebugger/gui/mainwindow.cpp
+++ b/tests/manual/gdbdebugger/gui/mainwindow.cpp
@@ -37,9 +37,17 @@
#define _USE_MATH_DEFINES
#include <math.h>
#include <QDebug>
+#include <QRect>
+#include <QRectF>
+#include <QLine>
+#include <QLineF>
+#include <QPoint>
+#include <QPointF>
+#include <QSize>
+#include <QSizeF>
+
#include <QThread>
#include <string>
-#include <list>
#include <set>
#include <QLibrary>
#include <QLibraryInfo>
@@ -82,9 +90,10 @@ void MainWindow::simpleBP(int inc, const QString &inx)
{
int array[2] = {1,2};
m_w++;
- QString x = "h\"allo";
+ QString x = QLatin1String("h\344all\366");
QString *xp = &x;
qDebug() << inc << inx << *xp;
+ Q_UNUSED(array)
}
void MainWindow::on_actionDialog_triggered()
@@ -152,6 +161,22 @@ void MainWindow::complexBP(int *inc, QString inx)
qDebug() << inc << inx << dir.absoluteFilePath();
//statusBar()->showMessage(x);
+ Q_UNUSED(cc)
+ Q_UNUSED(np)
+ Q_UNUSED(c)
+ Q_UNUSED(uc)
+ Q_UNUSED(s)
+ Q_UNUSED(us)
+ Q_UNUSED(ip)
+ Q_UNUSED(ipc)
+ Q_UNUSED(ui)
+ Q_UNUSED(l)
+ Q_UNUSED(ul)
+ Q_UNUSED(i64)
+ Q_UNUSED(iu64)
+ Q_UNUSED(r)
+ Q_UNUSED(d)
+ Q_UNUSED(xr)
}
void MainWindow::on_actionCrash_triggered()
@@ -309,6 +334,7 @@ void MainWindow::on_actionExtTypes_triggered()
stringSet.insert("S1");
stringSet.insert("S2");
qDebug() << *(spsl.front()) << hidden;
+ Q_UNUSED(wwr)
}
void MainWindow::on_actionForeach_triggered()
@@ -333,10 +359,12 @@ void Foo::MainWindow::on_actionScopes_triggered()
int x = 0;
if (x == 0) {
int x = 1;
+ Q_UNUSED(x)
} else {
int x = 2;
+ Q_UNUSED(x)
}
- qDebug() << x;
+ qDebug() << x;
}
void Foo::MainWindow::on_actionLongString_triggered()
@@ -347,4 +375,36 @@ void Foo::MainWindow::on_actionLongString_triggered()
s += incr;
qDebug() <<s;
}
+
+}
+
+void Foo::MainWindow::on_actionStdTypes_triggered()
+{
+ std::string stdString = "s";
+ std::wstring stdWString = L"ws";
+ std::map<std::string, std::string> stdStringStringMap;
+ stdStringStringMap.insert(std::map<std::string, std::string>::value_type(stdString, stdString));
+ std::map<std::wstring, std::wstring> stdStringWStringMap;
+ stdStringWStringMap.insert(std::map<std::wstring, std::wstring>::value_type(stdWString, stdWString));
+ std::set<std::string> stringSet;
+ std::list<std::string> stringList;
+ std::vector<std::string> stringVector(1, "bla");
+ std::vector<std::wstring> wStringVector(1, L"bla");
+}
+
+void Foo::MainWindow::on_actionVariousQtTypes_triggered()
+{
+ const QByteArray ba = "hallo\t";
+ QSize size = QSize(42, 43);
+ QSizeF sizeF(size);
+ QPoint p1 = QPoint(42, 43);
+ QPoint p2 = QPoint(100, 100);
+ QLine line(p1, p2);
+ QPointF p1f(p1);
+ QPointF p2f(p2);
+ QLineF linef(p1f, p2f);
+ QRect rect(p1, p2);
+ QRectF rectf(rect);
+ qDebug() << sizeF << linef << rectf;
+
}
diff --git a/tests/manual/gdbdebugger/gui/mainwindow.h b/tests/manual/gdbdebugger/gui/mainwindow.h
index 1473c107b0..0cc04f8c59 100644
--- a/tests/manual/gdbdebugger/gui/mainwindow.h
+++ b/tests/manual/gdbdebugger/gui/mainwindow.h
@@ -73,6 +73,10 @@ private slots:
void on_actionCrash_triggered();
void on_actionSimpleBP_triggered();
+ void on_actionStdTypes_triggered();
+
+ void on_actionVariousQtTypes_triggered();
+
private:
void terminateThread();
int m_w;
diff --git a/tests/manual/gdbdebugger/gui/mainwindow.ui b/tests/manual/gdbdebugger/gui/mainwindow.ui
index 6c3a9da11d..639fd6c998 100644
--- a/tests/manual/gdbdebugger/gui/mainwindow.ui
+++ b/tests/manual/gdbdebugger/gui/mainwindow.ui
@@ -20,7 +20,7 @@
<x>0</x>
<y>0</y>
<width>600</width>
- <height>23</height>
+ <height>26</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
@@ -46,6 +46,8 @@
<addaction name="actionAssert"/>
<addaction name="actionScopes"/>
<addaction name="actionLongString"/>
+ <addaction name="actionStdTypes"/>
+ <addaction name="actionVariousQtTypes"/>
</widget>
<widget class="QStatusBar" name="statusBar"/>
<widget class="QToolBar" name="toolBar">
@@ -151,6 +153,16 @@
<string>LongString</string>
</property>
</action>
+ <action name="actionStdTypes">
+ <property name="text">
+ <string>stdTypes</string>
+ </property>
+ </action>
+ <action name="actionVariousQtTypes">
+ <property name="text">
+ <string>variousQtTypes</string>
+ </property>
+ </action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
diff --git a/tests/manual/gdbdebugger/simple/simple_gdbtest_app.cpp b/tests/manual/gdbdebugger/simple/simple_gdbtest_app.cpp
index ed5419dddf..9789ccb96c 100644
--- a/tests/manual/gdbdebugger/simple/simple_gdbtest_app.cpp
+++ b/tests/manual/gdbdebugger/simple/simple_gdbtest_app.cpp
@@ -66,6 +66,8 @@
#include <QtGui/QPainterPath>
#include <QtGui/QRegion>
#include <QtGui/QStandardItemModel>
+#include <QtGui/QTextCursor>
+#include <QtGui/QTextDocument>
#include <QtNetwork/QHostAddress>
@@ -90,6 +92,11 @@
#undef max
#endif
+#ifdef Q_OS_LINUX
+#include <xmmintrin.h>
+#include <stddef.h>
+#endif
+
Q_DECLARE_METATYPE(QHostAddress)
Q_DECLARE_METATYPE(QList<int>)
Q_DECLARE_METATYPE(QStringList)
@@ -411,6 +418,8 @@ static void throwit()
int testCatchThrow()
{
+ // Set a breakpoint on "throw" in the BreakWindow context menu
+ // before stepping further.
int gotit = 0;
try {
throwit();
@@ -1061,6 +1070,7 @@ void stringRefTest(const QString &refstring)
void testStdDeque()
{
+ // This is not supposed to work with the compiled dumpers.
std::deque<int *> plist1;
plist1.push_back(new int(1));
plist1.push_back(0);
@@ -1084,6 +1094,7 @@ void testStdDeque()
void testStdHashSet()
{
+ // This is not supposed to work with the compiled dumpers.
#if USE_GCC_EXT
using namespace __gnu_cxx;
hash_set<int> h;
@@ -1098,6 +1109,7 @@ void testStdHashSet()
std::list<int> testStdList()
{
+ // This is not supposed to work with the compiled dumpers.
std::list<int> big;
for (int i = 0; i < 10000; ++i)
big.push_back(i);
@@ -1142,6 +1154,7 @@ std::list<int> testStdList()
void testStdMap()
{
+ // This is not supposed to work with the compiled dumpers.
#if 0
std::map<QString, Foo> gg3;
gg3["22.0"] = Foo(22);
@@ -1200,6 +1213,7 @@ void testStdMap()
std::set<int> testStdSet()
{
+ // This is not supposed to work with the compiled dumpers.
std::set<int> hgg0;
hgg0.insert(11);
hgg0.insert(22);
@@ -1218,7 +1232,7 @@ std::set<int> testStdSet()
std::stack<int> testStdStack()
{
- // only works with Python dumper
+ // This is not supposed to work with the compiled dumpers.
std::stack<int *> plist1;
plist1.push(new int(1));
plist1.push(0);
@@ -1369,12 +1383,34 @@ QStack<int> testQStack()
return result;
}
-void testQString()
+
+void testQUrl()
{
QUrl url(QString("http://www.nokia.com"));
+ (void) url;
+}
+
+
+#ifdef FOP
+
+int xxxx()
+{
+}
+
+#else
+
+void xxxx()
+{
+}
+
+
+#endif
+
+
+void testQString()
+{
QImage im;
- // Could be broken due to Return Value Optimzation
QString str = "Hello ";
str += " big, ";
str += " fat ";
@@ -1467,6 +1503,21 @@ private:
int m_id;
};
+void testQTextCursor()
+{
+ //int argc = 0;
+ //char *argv[] = { "xxx", 0 };
+ //QApplication app(argc, argv);
+ QTextDocument doc;
+ doc.setPlainText("Hallo\nWorld");
+ QTextCursor tc;
+ tc = doc.find("all");
+ int pos = tc.position();
+ int anc = tc.anchor();
+ Q_UNUSED(pos);
+ Q_UNUSED(anc);
+}
+
void testQThread()
{
Thread thread1(1);
@@ -1499,7 +1550,9 @@ QVariant testQVariant2()
*(QString*)value.data() = QString("XXX");
int i = 1;
- Q_UNUSED(i);
+ ++i;
+ ++i;
+ ++i;
#if 1
QVariant var;
var.setValue(1);
@@ -1617,6 +1670,7 @@ typedef QList<Goo> GooList;
void testNoArgumentName(int i, int, int k)
{
+ // This is not supposed to work with the compiled dumpers.
GooList list;
list.append(Goo("Hello", 1));
list.append(Goo("World", 2));
@@ -1732,12 +1786,12 @@ void testHidden()
int n = 1;
n = 2;
n = 3;
- n = 3;
- n = 3;
- n = 3;
- n = 3;
- n = 3;
- n = 3;
+ n = 4;
+ n = 4;
+ n = 5;
+ n = 6;
+ n = 7;
+ n = 8;
{
QString n = "2";
n = "3";
@@ -1809,6 +1863,13 @@ public:
Foo *f;
};
+void testMemoryView()
+{
+ int a[20];
+ for (int i = 0; i != 20; ++i)
+ a[i] = i;
+}
+
void testUninitialized()
{
QString s;
@@ -1838,6 +1899,9 @@ void testEndlessRecursion()
int testEndlessLoop()
{
qlonglong a = 1;
+ // gdb:
+ // Breakpoint at "while" will stop only once
+ // Hitting "Pause" button might show backtrace of different thread
while (a > 0)
++a;
return a;
@@ -1916,6 +1980,16 @@ void testConditional(const QString &str)
res += "x";
}
+void testChar()
+{
+ char s[5];
+ s[0] = 0;
+ strcat(s,"\""); // add a quote
+ strcat(s,"\""); // add a quote
+ strcat(s,"\""); // add a quote
+ strcat(s,"\""); // add a quote
+}
+
void testStuff()
{
testConditional("foo");
@@ -2019,6 +2093,24 @@ void testWCout0()
cerr << "EEEEEE" << endl;
}
+void testSSE()
+{
+#ifdef Q_OS_LINUX
+ float a[4];
+ float b[4];
+ int i;
+ for (i = 0; i < 4; i++) {
+ a[i] = 2 * i;
+ b[i] = 2 * i;
+ }
+ __m128 sseA, sseB;
+ sseA = _mm_loadu_ps(a);
+ sseB = _mm_loadu_ps(b);
+ ++i;
+#endif
+}
+
+
void testQSettings()
{
// Note: Construct a QCoreApplication first.
@@ -2030,13 +2122,16 @@ void testQSettings()
int main(int argc, char *argv[])
{
+ testMemoryView();
//testQSettings();
//testWCout0();
//testWCout();
+ testSSE();
testQLocale();
testColor();
testQRegion();
testTypedef();
+ testChar();
testStuff();
testPeekAndPoke3();
testFunctionPointer();
@@ -2072,6 +2167,7 @@ int main(int argc, char *argv[])
testFunction();
testQImage();
testNoArgumentName(1, 2, 3);
+ testQTextCursor();
testInput();
testOutput();
testHidden();
@@ -2100,6 +2196,7 @@ int main(int argc, char *argv[])
testQMap();
testQMultiMap();
testQString();
+ testQUrl();
testQSet();
# if QT_VERSION >= 0x040500
testQSharedPointer();
diff --git a/tests/manual/gdbdebugger/simple/simple_gdbtest_app.pro b/tests/manual/gdbdebugger/simple/simple_gdbtest_app.pro
index 2b4389eb34..d911cad896 100644
--- a/tests/manual/gdbdebugger/simple/simple_gdbtest_app.pro
+++ b/tests/manual/gdbdebugger/simple/simple_gdbtest_app.pro
@@ -1,13 +1,11 @@
TEMPLATE = app
TARGET = simple_gdbtest_app
DEPENDPATH += .
-INCLUDEPATH += .
DESTDIR = .
-# Input
-SOURCES += \
- simple_gdbtest_app.cpp
+SOURCES += simple_gdbtest_app.cpp
-# SOURCES += ../../../share/qtcreator/gdbmacros/gdbmacros.cpp
QT += network
+unix: QMAKE_CXXFLAGS += -msse2
+
message("this says <foo & bar>")
diff --git a/tests/manual/manual.pro b/tests/manual/manual.pro
index e0fd58773a..67725f9663 100644
--- a/tests/manual/manual.pro
+++ b/tests/manual/manual.pro
@@ -2,17 +2,10 @@ TEMPLATE=subdirs
SUBDIRS= \
cplusplus-frontend \
-cplusplus-dump \
fakevim \
gdbdebugger \
preprocessor \
-subdir_proparser \
-trklauncher
-
-win32 {
-# Uses CDB debugger
- SUBDIRS += ccdb
-}
+subdir_proparser
unix {
# Uses popen
diff --git a/tests/manual/preprocessor/preprocessor.pro b/tests/manual/preprocessor/preprocessor.pro
index b01a09bd49..8b17b43cee 100644
--- a/tests/manual/preprocessor/preprocessor.pro
+++ b/tests/manual/preprocessor/preprocessor.pro
@@ -2,7 +2,8 @@ QT = core
macx:CONFIG -= app_bundle
TARGET = pp
-include(../../../src/libs/cplusplus/cplusplus-lib.pri)
+include(../../../qtcreator.pri)
+include(../../../src/libs/cplusplus/cplusplus.pri)
# Input
SOURCES += main.cpp
diff --git a/tests/manual/process/process.pro b/tests/manual/process/process.pro
index 05c5e4a48c..9f91dbbac5 100644
--- a/tests/manual/process/process.pro
+++ b/tests/manual/process/process.pro
@@ -8,13 +8,11 @@
QT += core
QT += gui
+include(../../../qtcreator.pri)
+
# -- Add creator 'utils' lib
-CREATOR_LIB_LIB = ../../../lib/qtcreator
-LIBS *= -L$$CREATOR_LIB_LIB
-LIBS *= -l$$qtLibraryTarget(Utils)
-QMAKE_RPATHDIR*=$$CREATOR_LIB_LIB
-CREATOR_LIB_SRC = ../../../src/libs
-INCLUDEPATH *= $$CREATOR_LIB_SRC
+macx:QMAKE_LFLAGS += -Wl,-rpath,\"$$IDE_BIN_PATH/..\"
+LIBS *= -l$$qtLibraryName(Utils)
TARGET = process
CONFIG += console
diff --git a/tests/manual/qml-ast2dot/main.cpp b/tests/manual/qml-ast2dot/main.cpp
deleted file mode 100644
index b6d53a796a..0000000000
--- a/tests/manual/qml-ast2dot/main.cpp
+++ /dev/null
@@ -1,367 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#include <qmljs/parser/qmljsast_p.h>
-#include <qmljs/parser/qmljsastvisitor_p.h>
-#include <qmljs/qmljsdocument.h>
-
-#include <QFile>
-#include <QList>
-#include <QCoreApplication>
-#include <QStringList>
-#include <QFileInfo>
-#include <QTime>
-#include <QtDebug>
-
-#include <cstdio>
-#include <cstdlib>
-#include <fstream>
-#include <iostream>
-#ifdef __GNUC__
-# include <cxxabi.h>
-#endif
-
-using namespace QmlJS;
-using namespace QmlJS::AST;
-using namespace std;
-
-class ASTDump: protected Visitor
-{
-public:
- void operator()(const QString &fileName, const QByteArray &src, Node *ast) {
- _src = src;
- QString basename = fileName;
- int dotIdx = basename.lastIndexOf('.');
- if (dotIdx != -1)
- basename.truncate(dotIdx);
- basename.append(QLatin1String(".ast.dot"));
- out.open(basename.toUtf8().constData());
-
- out << "digraph AST { ordering=out;" << endl;
- // cout << "rankdir = \"LR\";" << endl;
- Node::accept(ast, this);
-
- typedef QPair<QByteArray, QByteArray> Pair;
-
- foreach (const Pair &conn, _connections)
- out << conn.first.constData() << " -> " << conn.second.constData() << endl;
-
- alignTerminals();
-
- out << "}" << endl;
- out.close();
- cout << qPrintable(basename) << endl;
- }
-
-protected:
- void alignTerminals() {
- out<<"{ rank=same;" << endl;
- foreach (const QByteArray &terminalShape, _terminalShapes) {
- out << " " << string(terminalShape) << ";" << endl;
- }
- out<<"}"<<endl;
- }
-
- static QByteArray name(Node *ast) {
-#ifdef __GNUC__
- QByteArray name = abi::__cxa_demangle(typeid(*ast).name(), 0, 0, 0) + 12;
-#else
- QByteArray name = typeid(*ast).name();
-#endif
- return name;
- }
-
- QString spell(const SourceLocation &token) {
- return _src.mid(token.offset, token.length).replace('\'', "\\\\").replace('"', "\\\"");
- }
-
- void terminal(const SourceLocation &token) {
- if (!token.isValid())
- return;
-
- static int count = 1;
- QByteArray id = 't' + QByteArray::number(count++);
- Node *node = _stack.last();
- _connections.append(qMakePair(_id[node], id));
-
- QByteArray t;
- t.append(id);
- t.append(" [label = \"");
- t.append(spell(token));
- t.append("\" shape=rect]");
- _terminalShapes.append(t);
- }
-
- virtual void nonterminal(Node *ast) {
- Node::accept(ast, this);
- }
-
- virtual void node(Node *ast) {
- out << _id[ast].constData() << " [label=\"" << name(ast).constData() << "\"];" << endl;
- }
-
- virtual bool preVisit(Node *ast) {
- static int count = 1;
- const QByteArray id = 'n' + QByteArray::number(count++);
- _id[ast] = id;
-
-
- if (! _stack.isEmpty())
- _connections.append(qMakePair(_id[_stack.last()], id));
-
- _stack.append(ast);
-
- node(ast);
-
- return true;
- }
-
- virtual void postVisit(Node *) {
- _stack.removeLast();
- }
-
-protected: // visiting methods:
- virtual bool visit(UiImport *ast) {
- terminal(ast->importToken);
-
- if (ast->importUri)
- nonterminal(ast->importUri);
- else
- terminal(ast->fileNameToken);
-
- terminal(ast->versionToken);
- terminal(ast->asToken);
- terminal(ast->importIdToken);
- terminal(ast->semicolonToken);
- return false;
- }
-
- virtual bool visit(UiObjectBinding *ast) {
- if (ast->hasOnToken) {
- nonterminal(ast->qualifiedTypeNameId);
- terminal(ast->colonToken);
- nonterminal(ast->qualifiedId);
- } else {
- nonterminal(ast->qualifiedId);
- terminal(ast->colonToken);
- nonterminal(ast->qualifiedTypeNameId);
- }
- nonterminal(ast->initializer);
- return false;
- }
-
- virtual bool visit(UiObjectDefinition *ast) {
- nonterminal(ast->qualifiedTypeNameId);
- nonterminal(ast->initializer);
- return false;
- }
-
- virtual bool visit(UiObjectInitializer *ast) {
- terminal(ast->lbraceToken);
- nonterminal(ast->members);
- terminal(ast->rbraceToken);
- return false;
- }
-
- virtual bool visit(UiScriptBinding *ast) {
- nonterminal(ast->qualifiedId);
- terminal(ast->colonToken);
- nonterminal(ast->statement);
- return false;
- }
-
- virtual bool visit(UiArrayBinding *ast) {
- nonterminal(ast->qualifiedId);
- terminal(ast->colonToken);
- terminal(ast->lbracketToken);
- nonterminal(ast->members);
- terminal(ast->rbracketToken);
- return false;
- }
-
- virtual bool visit(UiArrayMemberList *ast) {
- terminal(ast->commaToken);
- nonterminal(ast->member);
- nonterminal(ast->next);
- return false;
- }
-
- virtual bool visit(UiQualifiedId *ast) {
- terminal(ast->identifierToken);
- nonterminal(ast->next);
- return false;
- }
-
- virtual bool visit(UiPublicMember *ast) {
- // TODO: place the paramters...
-// UiParameterList *parameters;
-
- terminal(ast->defaultToken);
- terminal(ast->readonlyToken);
- terminal(ast->propertyToken);
- terminal(ast->typeModifierToken);
- terminal(ast->typeToken);
- terminal(ast->identifierToken);
- terminal(ast->colonToken);
- nonterminal(ast->expression);
- nonterminal(ast->binding);
- terminal(ast->semicolonToken);
- return false;
- }
-
- virtual bool visit(UiFormal *ast) { terminal(ast->identifierToken); terminal(ast->asToken); terminal(ast->aliasToken); return false; }
- virtual bool visit(UiSignature *ast) { terminal(ast->lparenToken); nonterminal(ast->formals); terminal(ast->rparenToken); return false; }
-
- virtual bool visit(StringLiteral *ast) { terminal(ast->literalToken); return false; }
- virtual bool visit(NumericLiteral *ast) { terminal(ast->literalToken); return false; }
- virtual bool visit(TrueLiteral *ast) { terminal(ast->trueToken); return false; }
- virtual bool visit(FalseLiteral *ast) { terminal(ast->falseToken); return false; }
- virtual bool visit(IdentifierExpression *ast) { terminal(ast->identifierToken); return false; }
- virtual bool visit(FieldMemberExpression *ast) { nonterminal(ast->base); terminal(ast->dotToken); terminal(ast->identifierToken); return false; }
- virtual bool visit(BinaryExpression *ast) { nonterminal(ast->left); terminal(ast->operatorToken); nonterminal(ast->right); return false; }
- virtual bool visit(UnaryPlusExpression *ast) { terminal(ast->plusToken); nonterminal(ast->expression); return false; }
- virtual bool visit(UnaryMinusExpression *ast) { terminal(ast->minusToken); nonterminal(ast->expression); return false; }
- virtual bool visit(NestedExpression *ast) { terminal(ast->lparenToken); nonterminal(ast->expression); terminal(ast->rparenToken); return false; }
- virtual bool visit(ThisExpression *ast) { terminal(ast->thisToken); return false; }
- virtual bool visit(NullExpression *ast) { terminal(ast->nullToken); return false; }
- virtual bool visit(RegExpLiteral *ast) { terminal(ast->literalToken); return false; }
- virtual bool visit(ArrayLiteral *ast) { terminal(ast->lbracketToken); nonterminal(ast->elements); terminal(ast->commaToken); nonterminal(ast->elision); terminal(ast->rbracketToken); return false; }
- virtual bool visit(ObjectLiteral *ast) { terminal(ast->lbraceToken); nonterminal(ast->properties); terminal(ast->rbraceToken); return false; }
- virtual bool visit(ElementList *ast) { nonterminal(ast->next); terminal(ast->commaToken); nonterminal(ast->elision); nonterminal(ast->expression); return false; }
- virtual bool visit(Elision *ast) { nonterminal(ast->next); terminal(ast->commaToken); return false; }
- virtual bool visit(PropertyNameAndValueList *ast) { nonterminal(ast->name); terminal(ast->colonToken); nonterminal(ast->value); terminal(ast->commaToken); nonterminal(ast->next); return false; }
- virtual bool visit(IdentifierPropertyName *ast) { terminal(ast->propertyNameToken); return false; }
- virtual bool visit(StringLiteralPropertyName *ast) { terminal(ast->propertyNameToken); return false; }
- virtual bool visit(NumericLiteralPropertyName *ast) { terminal(ast->propertyNameToken); return false; }
- virtual bool visit(ArrayMemberExpression *ast) { nonterminal(ast->base); terminal(ast->lbracketToken); nonterminal(ast->expression); terminal(ast->rbracketToken); return false; }
- virtual bool visit(NewMemberExpression *ast) { terminal(ast->newToken); nonterminal(ast->base); terminal(ast->lparenToken); nonterminal(ast->arguments); terminal(ast->rparenToken); return false; }
- virtual bool visit(NewExpression *ast) { terminal(ast->newToken); nonterminal(ast->expression); return false; }
- virtual bool visit(CallExpression *ast) { nonterminal(ast->base); terminal(ast->lparenToken); nonterminal(ast->arguments); terminal(ast->rparenToken); return false; }
- virtual bool visit(ArgumentList *ast) { nonterminal(ast->expression); terminal(ast->commaToken); nonterminal(ast->next); return false; }
- virtual bool visit(PostIncrementExpression *ast) { nonterminal(ast->base); terminal(ast->incrementToken); return false; }
- virtual bool visit(PostDecrementExpression *ast) { nonterminal(ast->base); terminal(ast->decrementToken); return false; }
- virtual bool visit(DeleteExpression *ast) { terminal(ast->deleteToken); nonterminal(ast->expression); return false; }
- virtual bool visit(VoidExpression *ast) { terminal(ast->voidToken); nonterminal(ast->expression); return false; }
- virtual bool visit(TypeOfExpression *ast) { terminal(ast->typeofToken); nonterminal(ast->expression); return false; }
- virtual bool visit(PreIncrementExpression *ast) { terminal(ast->incrementToken); nonterminal(ast->expression); return false; }
- virtual bool visit(PreDecrementExpression *ast) { terminal(ast->decrementToken); nonterminal(ast->expression); return false; }
- virtual bool visit(TildeExpression *ast) { terminal(ast->tildeToken); nonterminal(ast->expression); return false; }
- virtual bool visit(NotExpression *ast) { terminal(ast->notToken); nonterminal(ast->expression); return false; }
- virtual bool visit(ConditionalExpression *ast) { nonterminal(ast->expression); terminal(ast->questionToken); nonterminal(ast->ok); terminal(ast->colonToken); nonterminal(ast->ko); return false; }
- virtual bool visit(Expression *ast) { nonterminal(ast->left); terminal(ast->commaToken); nonterminal(ast->right); return false; }
- virtual bool visit(Block *ast) { terminal(ast->lbraceToken); nonterminal(ast->statements); terminal(ast->rbraceToken); return false; }
- virtual bool visit(VariableStatement *ast) { terminal(ast->declarationKindToken); nonterminal(ast->declarations); terminal(ast->semicolonToken); return false; }
- virtual bool visit(VariableDeclaration *ast) { terminal(ast->identifierToken); nonterminal(ast->expression); return false; }
- virtual bool visit(VariableDeclarationList *ast) { nonterminal(ast->declaration); terminal(ast->commaToken); nonterminal(ast->next); return false; }
- virtual bool visit(EmptyStatement* ast) { terminal(ast->semicolonToken); return false; }
- virtual bool visit(ExpressionStatement *ast) { nonterminal(ast->expression); terminal(ast->semicolonToken); return false; }
- virtual bool visit(IfStatement *ast) { terminal(ast->ifToken); terminal(ast->lparenToken); nonterminal(ast->expression); terminal(ast->rparenToken); nonterminal(ast->ok); terminal(ast->elseToken); nonterminal(ast->ko); return false; }
- virtual bool visit(DoWhileStatement *ast) { terminal(ast->doToken); nonterminal(ast->statement); terminal(ast->whileToken); terminal(ast->lparenToken); nonterminal(ast->expression); terminal(ast->rparenToken); terminal(ast->semicolonToken); return false; }
-
-// TODO: visitors for:
-// WhileStatement
-// ForStatement
-// LocalForStatement
-// ForEachStatement
-// LocalForEachStatement
-// ContinueStatement
-// BreakStatement
-// ReturnStatement
-// WithStatement
-// CaseBlock
-// SwitchStatement
-// CaseClause
-// DefaultClause
-// LabelledStatement
-// ThrowStatement
-// Catch
-// Finally
-// TryStatement
-// FunctionExpression
-// FunctionDeclaration
-// DebuggerStatement
-// UiParameterList
-
-private:
- QHash<Node *, QByteArray> _id;
- QList<QPair<QByteArray, QByteArray> > _connections;
- QList<Node *> _stack;
- QList<QByteArray> _terminalShapes;
- ofstream out;
- QByteArray _src;
-};
-
-int main(int argc, char *argv[])
-{
- QCoreApplication app(argc, argv);
-
- QStringList files = app.arguments();
- files.removeFirst();
-
- foreach (const QString &fileName, files) {
- QFile file(fileName);
- if (! file.open(QFile::ReadOnly)) {
- cerr << "Cannot open \"" << qPrintable(fileName)
- << "\", skipping it." << endl;
- continue;
- }
-
- const QByteArray source = file.readAll();
- file.close();
-
- Document::Ptr doc = Document::create(fileName);
- doc->setSource(source);
- doc->parseQml();
-
- foreach (const DiagnosticMessage &m, doc->diagnosticMessages()) {
- ostream *os;
- if (m.isError()) {
- os = &cerr;
- *os << "Error:";
- } else {
- os = &cout;
- *os << "Warning:";
- }
-
- if (m.loc.isValid())
- *os << m.loc.startLine << ':' << m.loc.startColumn << ':';
- *os << ' ';
- *os << qPrintable(m.message) << endl;
- }
-
- ASTDump dump;
- dump(fileName, source, doc->qmlProgram());
- }
-
- return EXIT_SUCCESS;
-}
diff --git a/tests/manual/qml-ast2dot/qml-ast2dot.pro b/tests/manual/qml-ast2dot/qml-ast2dot.pro
deleted file mode 100644
index 7ee4c66f62..0000000000
--- a/tests/manual/qml-ast2dot/qml-ast2dot.pro
+++ /dev/null
@@ -1,22 +0,0 @@
-QT = core gui
-macx:CONFIG -= app_bundle
-TARGET = qml-ast2dot
-
-include(../../../src/libs/qmljs/qmljs-lib.pri)
-
-SOURCES += ../../../src/libs/utils/changeset.cpp
-HEADERS += ../../../src/libs/utils/changeset.h
-
-# Input
-SOURCES += main.cpp
-
-unix {
- debug:OBJECTS_DIR = $${OUT_PWD}/.obj/debug-shared
- release:OBJECTS_DIR = $${OUT_PWD}/.obj/release-shared
-
- debug:MOC_DIR = $${OUT_PWD}/.moc/debug-shared
- release:MOC_DIR = $${OUT_PWD}/.moc/release-shared
-
- RCC_DIR = $${OUT_PWD}/.rcc/
- UI_DIR = $${OUT_PWD}/.uic/
-}
diff --git a/tests/manual/qmlstandalone/helpers.cpp b/tests/manual/qmlstandalone/helpers.cpp
new file mode 100644
index 0000000000..36e30f1d0b
--- /dev/null
+++ b/tests/manual/qmlstandalone/helpers.cpp
@@ -0,0 +1,33 @@
+#include "qmlstandaloneapp.h"
+#include <QtCore>
+
+using namespace Qt4ProjectManager::Internal;
+
+static bool writeFile(const QByteArray &data, const QString &targetFile)
+{
+ const QFileInfo fileInfo(targetFile);
+ QDir().mkpath(fileInfo.absolutePath());
+ QFile file(fileInfo.absoluteFilePath());
+ file.open(QIODevice::WriteOnly);
+ Q_ASSERT(file.isOpen());
+ return file.write(data) != -1;
+}
+
+bool QmlStandaloneApp::generateFiles(QString *errorMessage) const
+{
+ return writeFile(generateFile(QmlAppGeneratedFileInfo::MainCppFile, errorMessage), path(MainCpp))
+ && writeFile(generateFile(QmlAppGeneratedFileInfo::AppProFile, errorMessage), path(AppPro))
+ && (useExistingMainQml() ? true : writeFile(generateFile(QmlAppGeneratedFileInfo::MainQmlFile, errorMessage), path(MainQml)))
+ && writeFile(generateFile(QmlAppGeneratedFileInfo::AppViewerPriFile, errorMessage), path(AppViewerPri))
+ && writeFile(generateFile(QmlAppGeneratedFileInfo::AppViewerCppFile, errorMessage), path(AppViewerCpp))
+ && writeFile(generateFile(QmlAppGeneratedFileInfo::AppViewerHFile, errorMessage), path(AppViewerH))
+ && writeFile(generateFile(QmlAppGeneratedFileInfo::SymbianSvgIconFile, errorMessage), path(SymbianSvgIcon))
+ && writeFile(generateFile(QmlAppGeneratedFileInfo::MaemoPngIconFile, errorMessage), path(MaemoPngIcon))
+ && writeFile(generateFile(QmlAppGeneratedFileInfo::DesktopFile, errorMessage), path(Desktop));
+}
+
+QString AbstractMobileApp::templatesRoot()
+{
+ return QLatin1String("../../../share/qtcreator/templates/");
+}
+
diff --git a/tests/manual/qmlstandalone/main.cpp b/tests/manual/qmlstandalone/main.cpp
index 137da42e52..1ecb43070d 100644
--- a/tests/manual/qmlstandalone/main.cpp
+++ b/tests/manual/qmlstandalone/main.cpp
@@ -36,34 +36,6 @@
using namespace Qt4ProjectManager::Internal;
-static bool writeFile(const QByteArray &data, const QString &targetFile)
-{
- const QFileInfo fileInfo(targetFile);
- QDir().mkpath(fileInfo.absolutePath());
- QFile file(fileInfo.absoluteFilePath());
- file.open(QIODevice::WriteOnly);
- Q_ASSERT(file.isOpen());
- return file.write(data) != -1;
-}
-
-bool QmlStandaloneApp::generateFiles(QString *errorMessage) const
-{
- return writeFile(generateFile(QmlAppGeneratedFileInfo::MainCppFile, errorMessage), path(MainCpp))
- && writeFile(generateFile(QmlAppGeneratedFileInfo::AppProFile, errorMessage), path(AppPro))
- && (useExistingMainQml() ? true : writeFile(generateFile(QmlAppGeneratedFileInfo::MainQmlFile, errorMessage), path(MainQml)))
- && writeFile(generateFile(QmlAppGeneratedFileInfo::AppViewerPriFile, errorMessage), path(AppViewerPri))
- && writeFile(generateFile(QmlAppGeneratedFileInfo::AppViewerCppFile, errorMessage), path(AppViewerCpp))
- && writeFile(generateFile(QmlAppGeneratedFileInfo::AppViewerHFile, errorMessage), path(AppViewerH))
- && writeFile(generateFile(QmlAppGeneratedFileInfo::SymbianSvgIconFile, errorMessage), path(SymbianSvgIcon))
- && writeFile(generateFile(QmlAppGeneratedFileInfo::MaemoPngIconFile, errorMessage), path(MaemoPngIcon))
- && writeFile(generateFile(QmlAppGeneratedFileInfo::DesktopFile, errorMessage), path(Desktop));
-}
-
-QString AbstractMobileApp::templatesRoot()
-{
- return QLatin1String("../../../share/qtcreator/templates/");
-}
-
int main(int argc, char *argv[])
{
QString errorMessage;
diff --git a/tests/manual/qmlstandalone/qmlstandalone.pro b/tests/manual/qmlstandalone/qmlstandalone.pro
index bc0b188035..d589bf826e 100644
--- a/tests/manual/qmlstandalone/qmlstandalone.pro
+++ b/tests/manual/qmlstandalone/qmlstandalone.pro
@@ -9,5 +9,6 @@ HEADERS += \
SOURCES += \
$$APPSOURCEDIR/qmlstandaloneapp.cpp \
$$APPSOURCEDIR/abstractmobileapp.cpp \
- main.cpp
+ main.cpp \
+ helpers.cpp
INCLUDEPATH += $$APPSOURCEDIR
diff --git a/tests/manual/search/latin1.txt b/tests/manual/search/latin1.txt
new file mode 100644
index 0000000000..09044014b3
--- /dev/null
+++ b/tests/manual/search/latin1.txt
@@ -0,0 +1 @@
+äöüÄÖÜß
diff --git a/tests/manual/search/search.pro b/tests/manual/search/search.pro
new file mode 100644
index 0000000000..7c382caa32
--- /dev/null
+++ b/tests/manual/search/search.pro
@@ -0,0 +1 @@
+OTHER_FILES = latin1.txt
diff --git a/tests/manual/ssh/errorhandling/main.cpp b/tests/manual/ssh/errorhandling/main.cpp
index ef1dcd8318..994ddf5ce1 100644
--- a/tests/manual/ssh/errorhandling/main.cpp
+++ b/tests/manual/ssh/errorhandling/main.cpp
@@ -27,12 +27,12 @@ public:
if (m_connection->createSftpChannel())
qDebug("Error: Unconnected SSH connection creates SFTP channel.");
- SshConnectionParameters noHost(SshConnectionParameters::DefaultProxy);
+ SshConnectionParameters noHost=SshConnectionParameters(SshConnectionParameters::DefaultProxy);
noHost.host = QLatin1String("hgdfxgfhgxfhxgfchxgcf");
noHost.port = 12345;
noHost.timeout = 10;
- SshConnectionParameters noUser(SshConnectionParameters::DefaultProxy);;
+ SshConnectionParameters noUser=SshConnectionParameters(SshConnectionParameters::DefaultProxy);
noUser.host = QLatin1String("localhost");
noUser.port = 22;
noUser.timeout = 30;
@@ -40,7 +40,7 @@ public:
noUser.uname = QLatin1String("dumdidumpuffpuff");
noUser.uname = QLatin1String("whatever");
- SshConnectionParameters wrongPwd(SshConnectionParameters::DefaultProxy);;
+ SshConnectionParameters wrongPwd=SshConnectionParameters(SshConnectionParameters::DefaultProxy);
wrongPwd.host = QLatin1String("localhost");
wrongPwd.port = 22;
wrongPwd.timeout = 30;
@@ -48,7 +48,7 @@ public:
wrongPwd.uname = QLatin1String("root");
noUser.uname = QLatin1String("thiscantpossiblybeapasswordcanit");
- SshConnectionParameters invalidKeyFile(SshConnectionParameters::DefaultProxy);;
+ SshConnectionParameters invalidKeyFile=SshConnectionParameters(SshConnectionParameters::DefaultProxy);
invalidKeyFile.host = QLatin1String("localhost");
invalidKeyFile.port = 22;
invalidKeyFile.timeout = 30;
diff --git a/tests/manual/ssh/remoteprocess/argumentscollector.cpp b/tests/manual/ssh/remoteprocess/argumentscollector.cpp
new file mode 100644
index 0000000000..87b765b472
--- /dev/null
+++ b/tests/manual/ssh/remoteprocess/argumentscollector.cpp
@@ -0,0 +1,129 @@
+#include "argumentscollector.h"
+
+#include <iostream>
+
+using namespace std;
+using namespace Core;
+
+ArgumentsCollector::ArgumentsCollector(const QStringList &args)
+ : m_arguments(args)
+{
+}
+
+Core::SshConnectionParameters ArgumentsCollector::collect(bool &success) const
+{
+ SshConnectionParameters parameters(Core::SshConnectionParameters::NoProxy);
+ try {
+ bool authTypeGiven = false;
+ bool portGiven = false;
+ bool timeoutGiven = false;
+ bool proxySettingGiven = false;
+ int pos;
+ int port;
+ for (pos = 1; pos < m_arguments.count() - 1; ++pos) {
+ if (checkAndSetStringArg(pos, parameters.host, "-h")
+ || checkAndSetStringArg(pos, parameters.uname, "-u"))
+ continue;
+ if (checkAndSetIntArg(pos, port, portGiven, "-p")
+ || checkAndSetIntArg(pos, parameters.timeout, timeoutGiven, "-t"))
+ continue;
+ if (checkAndSetStringArg(pos, parameters.pwd, "-pwd")) {
+ if (!parameters.privateKeyFile.isEmpty())
+ throw ArgumentErrorException(QLatin1String("-pwd and -k are mutually exclusive."));
+ parameters.authType
+ = SshConnectionParameters::AuthByPwd;
+ authTypeGiven = true;
+ continue;
+ }
+ if (checkAndSetStringArg(pos, parameters.privateKeyFile, "-k")) {
+ if (!parameters.pwd.isEmpty())
+ throw ArgumentErrorException(QLatin1String("-pwd and -k are mutually exclusive."));
+ parameters.authType
+ = SshConnectionParameters::AuthByKey;
+ authTypeGiven = true;
+ continue;
+ }
+ if (!checkForNoProxy(pos, parameters.proxyType, proxySettingGiven))
+ throw ArgumentErrorException(QLatin1String("unknown option ") + m_arguments.at(pos));
+ }
+
+ Q_ASSERT(pos <= m_arguments.count());
+ if (pos == m_arguments.count() - 1) {
+ if (!checkForNoProxy(pos, parameters.proxyType, proxySettingGiven))
+ throw ArgumentErrorException(QLatin1String("unknown option ") + m_arguments.at(pos));
+ }
+
+ if (!authTypeGiven)
+ throw ArgumentErrorException(QLatin1String("No authentication argument given."));
+ if (parameters.host.isEmpty())
+ throw ArgumentErrorException(QLatin1String("No host given."));
+ if (parameters.uname.isEmpty())
+ throw ArgumentErrorException(QLatin1String("No user name given."));
+
+ parameters.port = portGiven ? port : 22;
+ if (!timeoutGiven)
+ parameters.timeout = 30;
+ success = true;
+ } catch (ArgumentErrorException &ex) {
+ cerr << "Error: " << qPrintable(ex.error) << endl;
+ printUsage();
+ success = false;
+ }
+ return parameters;
+}
+
+void ArgumentsCollector::printUsage() const
+{
+ cerr << "Usage: " << qPrintable(m_arguments.first())
+ << " -h <host> -u <user> "
+ << "-pwd <password> | -k <private key file> [ -p <port> ] "
+ << "[ -t <timeout> ] [ -no-proxy ]" << endl;
+}
+
+bool ArgumentsCollector::checkAndSetStringArg(int &pos, QString &arg, const char *opt) const
+{
+ if (m_arguments.at(pos) == QLatin1String(opt)) {
+ if (!arg.isEmpty()) {
+ throw ArgumentErrorException(QLatin1String("option ") + opt
+ + QLatin1String(" was given twice."));
+ }
+ arg = m_arguments.at(++pos);
+ if (arg.isEmpty() && QLatin1String(opt) != QLatin1String("-pwd"))
+ throw ArgumentErrorException(QLatin1String("empty argument not allowed here."));
+ return true;
+ }
+ return false;
+}
+
+bool ArgumentsCollector::checkAndSetIntArg(int &pos, int &val,
+ bool &alreadyGiven, const char *opt) const
+{
+ if (m_arguments.at(pos) == QLatin1String(opt)) {
+ if (alreadyGiven) {
+ throw ArgumentErrorException(QLatin1String("option ") + opt
+ + QLatin1String(" was given twice."));
+ }
+ bool isNumber;
+ val = m_arguments.at(++pos).toInt(&isNumber);
+ if (!isNumber) {
+ throw ArgumentErrorException(QLatin1String("option ") + opt
+ + QLatin1String(" needs integer argument"));
+ }
+ alreadyGiven = true;
+ return true;
+ }
+ return false;
+}
+
+bool ArgumentsCollector::checkForNoProxy(int &pos,
+ SshConnectionParameters::ProxyType &type, bool &alreadyGiven) const
+{
+ if (m_arguments.at(pos) == QLatin1String("-no-proxy")) {
+ if (alreadyGiven)
+ throw ArgumentErrorException(QLatin1String("proxy setting given twice."));
+ type = SshConnectionParameters::NoProxy;
+ alreadyGiven = true;
+ return true;
+ }
+ return false;
+}
diff --git a/tests/manual/ssh/remoteprocess/argumentscollector.h b/tests/manual/ssh/remoteprocess/argumentscollector.h
new file mode 100644
index 0000000000..f7ba749a4b
--- /dev/null
+++ b/tests/manual/ssh/remoteprocess/argumentscollector.h
@@ -0,0 +1,31 @@
+#ifndef ARGUMENTSCOLLECTOR_H
+#define ARGUMENTSCOLLECTOR_H
+
+#include <coreplugin/ssh/sshconnection.h>
+
+#include <QtCore/QStringList>
+
+class ArgumentsCollector
+{
+public:
+ ArgumentsCollector(const QStringList &args);
+ Core::SshConnectionParameters collect(bool &success) const;
+private:
+ struct ArgumentErrorException
+ {
+ ArgumentErrorException(const QString &error) : error(error) {}
+ const QString error;
+ };
+
+ void printUsage() const;
+ bool checkAndSetStringArg(int &pos, QString &arg, const char *opt) const;
+ bool checkAndSetIntArg(int &pos, int &val, bool &alreadyGiven,
+ const char *opt) const;
+ bool checkForNoProxy(int &pos,
+ Core::SshConnectionParameters::ProxyType &type,
+ bool &alreadyGiven) const;
+
+ const QStringList m_arguments;
+};
+
+#endif // ARGUMENTSCOLLECTOR_H
diff --git a/tests/manual/ssh/remoteprocess/main.cpp b/tests/manual/ssh/remoteprocess/main.cpp
new file mode 100644
index 0000000000..e2c4afcd2d
--- /dev/null
+++ b/tests/manual/ssh/remoteprocess/main.cpp
@@ -0,0 +1,26 @@
+#include "argumentscollector.h"
+#include "remoteprocesstest.h"
+
+#include <coreplugin/ssh/sshconnection.h>
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QObject>
+#include <QtCore/QStringList>
+
+#include <cstdlib>
+#include <iostream>
+
+using namespace Core;
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication app(argc, argv);
+ bool parseSuccess;
+ const Core::SshConnectionParameters &parameters
+ = ArgumentsCollector(app.arguments()).collect(parseSuccess);
+ if (!parseSuccess)
+ return EXIT_FAILURE;
+ RemoteProcessTest remoteProcessTest(parameters);
+ remoteProcessTest.run();
+ return app.exec();
+}
diff --git a/tests/manual/ssh/remoteprocess/remoteprocess.pro b/tests/manual/ssh/remoteprocess/remoteprocess.pro
new file mode 100644
index 0000000000..96c272268a
--- /dev/null
+++ b/tests/manual/ssh/remoteprocess/remoteprocess.pro
@@ -0,0 +1,6 @@
+include(../ssh.pri)
+
+TARGET=remoteprocess
+SOURCES=main.cpp remoteprocesstest.cpp argumentscollector.cpp
+HEADERS=remoteprocesstest.h argumentscollector.h
+
diff --git a/tests/manual/ssh/remoteprocess/remoteprocesstest.cpp b/tests/manual/ssh/remoteprocess/remoteprocesstest.cpp
new file mode 100644
index 0000000000..bb61b1cb58
--- /dev/null
+++ b/tests/manual/ssh/remoteprocess/remoteprocesstest.cpp
@@ -0,0 +1,184 @@
+#include "remoteprocesstest.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QTimer>
+
+#include <iostream>
+
+using namespace Core;
+
+RemoteProcessTest::RemoteProcessTest(const SshConnectionParameters &params)
+ : m_timeoutTimer(new QTimer(this)),
+ m_remoteRunner(SshRemoteProcessRunner::create(params)),
+ m_state(Inactive)
+{
+ m_timeoutTimer->setInterval(5000);
+ connect(m_timeoutTimer, SIGNAL(timeout()), SLOT(handleTimeout()));
+}
+
+RemoteProcessTest::~RemoteProcessTest() { }
+
+void RemoteProcessTest::run()
+{
+ connect(m_remoteRunner.data(), SIGNAL(connectionError(Core::SshError)),
+ SLOT(handleConnectionError()));
+ connect(m_remoteRunner.data(), SIGNAL(processStarted()),
+ SLOT(handleProcessStarted()));
+ connect(m_remoteRunner.data(), SIGNAL(processOutputAvailable(QByteArray)),
+ SLOT(handleProcessStdout(QByteArray)));
+ connect(m_remoteRunner.data(),
+ SIGNAL(processErrorOutputAvailable(QByteArray)),
+ SLOT(handleProcessStderr(QByteArray)));
+ connect(m_remoteRunner.data(), SIGNAL(processClosed(int)),
+ SLOT(handleProcessClosed(int)));
+
+ std::cout << "Testing successful remote process..." << std::endl;
+ m_state = TestingSuccess;
+ m_started = false;
+ m_timeoutTimer->start();
+ m_remoteRunner->run("ls -a /tmp");
+}
+
+void RemoteProcessTest::handleConnectionError()
+{
+ std::cerr << "Error: Connection failure ("
+ << qPrintable(m_remoteRunner->connection()->errorString()) << ")."
+ << std::endl;
+ qApp->quit();
+}
+
+void RemoteProcessTest::handleProcessStarted()
+{
+ if (m_started) {
+ std::cerr << "Error: Received started() signal again." << std::endl;
+ qApp->quit();
+ } else {
+ m_started = true;
+ if (m_state == TestingCrash) {
+ Core::SshRemoteProcess::Ptr killer
+ = m_remoteRunner->connection()->createRemoteProcess("pkill -9 sleep");
+ killer->start();
+ }
+ }
+}
+
+void RemoteProcessTest::handleProcessStdout(const QByteArray &output)
+{
+ if (!m_started) {
+ std::cerr << "Error: Remote output from non-started process."
+ << std::endl;
+ qApp->quit();
+ } else if (m_state != TestingSuccess) {
+ std::cerr << "Error: Got remote standard output in state " << m_state
+ << "." << std::endl;
+ qApp->quit();
+ } else {
+ m_remoteStdout += output;
+ }
+}
+
+void RemoteProcessTest::handleProcessStderr(const QByteArray &output)
+{
+ if (!m_started) {
+ std::cerr << "Error: Remote error output from non-started process."
+ << std::endl;
+ qApp->quit();
+ } else if (m_state == TestingSuccess) {
+ std::cerr << "Error: Unexpected remote standard error output."
+ << std::endl;
+ qApp->quit();
+ } else {
+ m_remoteStderr += output;
+ }
+}
+
+void RemoteProcessTest::handleProcessClosed(int exitStatus)
+{
+ switch (exitStatus) {
+ case SshRemoteProcess::ExitedNormally:
+ if (!m_started) {
+ std::cerr << "Error: Process exited without starting." << std::endl;
+ qApp->quit();
+ return;
+ }
+ switch (m_state) {
+ case TestingSuccess: {
+ const int exitCode = m_remoteRunner->process()->exitCode();
+ if (exitCode != 0) {
+ std::cerr << "Error: exit code is " << exitCode
+ << ", expected zero." << std::endl;
+ qApp->quit();
+ return;
+ }
+ if (m_remoteStdout.isEmpty()) {
+ std::cerr << "Error: Command did not produce output."
+ << std::endl;
+ qApp->quit();
+ return;
+ }
+
+ std::cout << "Ok. Testing unsuccessful remote process..."
+ << std::endl;
+ m_state = TestingFailure;
+ m_started = false;
+ m_timeoutTimer->start();
+ m_remoteRunner->run("ls /wedontexepectsuchafiletoexist");
+ break;
+ }
+ case TestingFailure: {
+ const int exitCode = m_remoteRunner->process()->exitCode();
+ if (exitCode == 0) {
+ std::cerr << "Error: exit code is zero, expected non-zero."
+ << std::endl;
+ qApp->quit();
+ return;
+ }
+ if (m_remoteStderr.isEmpty()) {
+ std::cerr << "Error: Command did not produce error output."
+ << std::endl;
+ qApp->quit();
+ return;
+ }
+
+ std::cout << "Ok. Testing crashing remote process..."
+ << std::endl;
+ m_state = TestingCrash;
+ m_started = false;
+ m_timeoutTimer->start();
+ m_remoteRunner->run("sleep 100");
+ break;
+ }
+ case TestingCrash:
+ std::cerr << "Error: Successful exit from process that was "
+ "supposed to crash." << std::endl;
+ qApp->quit();
+ return;
+ case Inactive:
+ Q_ASSERT(false);
+ }
+ break;
+ case SshRemoteProcess::FailedToStart:
+ if (m_started) {
+ std::cerr << "Error: Got 'failed to start' signal for process "
+ "that has not started yet." << std::endl;
+ } else {
+ std::cerr << "Error: Process failed to start." << std::endl;
+ }
+ qApp->quit();
+ break;
+ case SshRemoteProcess::KilledBySignal:
+ if (m_state != TestingCrash) {
+ std::cerr << "Error: Unexpected crash." << std::endl;
+ qApp->quit();
+ return;
+ }
+ std::cout << "Ok. All tests succeeded." << std::endl;
+ qApp->quit();
+ }
+}
+
+void RemoteProcessTest::handleTimeout()
+{
+ std::cerr << "Error: Timeout waiting for progress." << std::endl;
+ qApp->quit();
+}
diff --git a/tests/manual/ssh/remoteprocess/remoteprocesstest.h b/tests/manual/ssh/remoteprocess/remoteprocesstest.h
new file mode 100644
index 0000000000..a9a2219c7e
--- /dev/null
+++ b/tests/manual/ssh/remoteprocess/remoteprocesstest.h
@@ -0,0 +1,37 @@
+#ifndef SFTPTEST_H
+#define SFTPTEST_H
+
+#include <coreplugin/ssh/sshremoteprocessrunner.h>
+
+QT_FORWARD_DECLARE_CLASS(QTimer);
+#include <QtCore/QObject>
+
+class RemoteProcessTest : public QObject
+{
+ Q_OBJECT
+public:
+ RemoteProcessTest(const Core::SshConnectionParameters &params);
+ ~RemoteProcessTest();
+ void run();
+
+private slots:
+ void handleConnectionError();
+ void handleProcessStarted();
+ void handleProcessStdout(const QByteArray &output);
+ void handleProcessStderr(const QByteArray &output);
+ void handleProcessClosed(int exitStatus);
+ void handleTimeout();
+
+private:
+ enum State { Inactive, TestingSuccess, TestingFailure, TestingCrash };
+
+ QTimer * const m_timeoutTimer;
+ const Core::SshRemoteProcessRunner::Ptr m_remoteRunner;
+ QByteArray m_remoteStdout;
+ QByteArray m_remoteStderr;
+ State m_state;
+ bool m_started;
+};
+
+
+#endif // SFTPTEST_H
diff --git a/tests/manual/ssh/ssh.pri b/tests/manual/ssh/ssh.pri
index cdbe6778b4..fab9b5d4e6 100644
--- a/tests/manual/ssh/ssh.pri
+++ b/tests/manual/ssh/ssh.pri
@@ -1,14 +1,16 @@
-INCLUDEPATH += ../../../../src/plugins
-CREATORLIBPATH = ../../../../lib/qtcreator
-PLUGINPATH=$$CREATORLIBPATH/plugins/Nokia
-LIBS *= -L$$PLUGINPATH -lCore
-LIBS *= -L$$CREATORLIBPATH
include (../../../qtcreator.pri)
-include (../../../src/plugins/coreplugin/coreplugin_dependencies.pri)
+include (../../../src/plugins/coreplugin/coreplugin.pri)
+
+LIBS += -L$$IDE_PLUGIN_PATH/Nokia
+
+macx:QMAKE_LFLAGS += -Wl,-rpath,\"$$IDE_BIN_PATH/..\"
+INCLUDEPATH *= $$IDE_SOURCE_TREE/src/plugins
+LIBS *= -L$$IDE_LIBRARY_PATH/Nokia
+
QT += core
QT -= gui
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
DEPENDPATH+=.
-INCLUDEPATH+=. \ No newline at end of file
+INCLUDEPATH+=.
diff --git a/tests/manual/ssh/ssh.pro b/tests/manual/ssh/ssh.pro
index 432f8f192b..a722b3d543 100644
--- a/tests/manual/ssh/ssh.pro
+++ b/tests/manual/ssh/ssh.pro
@@ -5,4 +5,4 @@
#-------------------------------------------------
TEMPLATE = subdirs
-SUBDIRS = errorhandling sftp
+SUBDIRS = errorhandling sftp remoteprocess
diff --git a/tests/manual/trk/README b/tests/manual/trk/README
deleted file mode 100644
index f8b1232945..0000000000
--- a/tests/manual/trk/README
+++ /dev/null
@@ -1,47 +0,0 @@
-Run ./run.sh in one terminal.
-Run ./welsh-gdb or ./symbianelf-gdb in a second terminal.
-Note that welsh-gdb does not handle 'set remote noack-packet on'
-
-The following items "work":
-
-- "stop" at E32Main
-- manual relocation on the gdb side using
- add-symbol-file filebrowseapp.sym 0x786A4000
-- disassembly at stopped location
-- p <functionname>
-- p $pc
-- one level of 'bt'
-
-To do:
-
-- figure out why the result of the qOffsets query is not honoured
- _or_ how to have gdb doing the relocation automatically
-- setting breakpoints by filename:line
-- signaling of stopped/single step end. SIGTRAP? SIGSTOP?
-- run it against the red brick
-
-
-Setting up TRK on Linux with Bluetooth
-
-Enter the following commands in a terminal (all as root, adjust device
-permissions as required to work as user):
-
-
-sdptool add SP # announce Serial Port Profile via Service Discovery Protocol
-sudo mknod --mode=666 /dev/rfcomm0 c 216 0 # Creates a Bluetooth Serial Device
-
-rfcomm listen /dev/rfcomm0 1 $PWD/trklauncher -v -f {}
-
-#This should print the Trk/CPU versions. The option -f tells the command to
-#disable the serial frames message encapsulation for BlueTooth.
-
-#The same with the debug adapter:
-
-rfcomm listen /dev/rfcomm0 1 $PWD/run.pl -af -av -w {}
-rfcomm listen /dev/rfcomm0 1 $PWD/runner -af -av -w {}
-
-#Important options: -w wait for adapter, -af omit serial frame.
-
-cp /data5/dev/debugger/symbian-codesourcery-welsh/cs-gdb/build/gdb/gdb cs-gdb
-cp /data5/dev/trk/filebrowseapp* .
-cp /home/f*/dev/creator/tests/manual/trk/*.bin .
diff --git a/tests/manual/trk/run.pl b/tests/manual/trk/run.pl
deleted file mode 100755
index 2a3993fe5f..0000000000
--- a/tests/manual/trk/run.pl
+++ /dev/null
@@ -1,164 +0,0 @@
-#!/usr/bin/perl -w
-
-use strict;
-use English; # gives us $OSNAME
-use File::Temp;
-use File::Spec;
-use Cwd;
-
-my @ADAPTER_OPTIONS = ();
-my @TRKSERVEROPTIONS = ();
-my $DUMP_POSTFIX ='.bin';
-my $ENDIANESS ='little';
-
-my $isUnix = $OSNAME eq 'linux' ? 1 : 0;
-my $MAKE= $isUnix ? 'make' : 'nmake';
-my $trkservername;
-my $runTrkServer = 1;
-my $waitAdapter = 0;
-
-my $usage=<<EOF;
-Usage: run.pl -w -av -aq -au -tv -tq -l [COM]
-Options:
- -av Adapter verbose
- -aq Adapter quiet
- -au Adapter turn off buffered memory read
- -af Adapter turn off serial frame
- -w Wait for termination of Adapter (Bluetooth)
- -tv TrkServer verbose
- -tq TrkServer quiet
-
- trkserver simulator will be run unless COM is specified
-
-Bluetooth:
- rfcomm listen /dev/rfcomm0 1 \$PWD/run.pl -av -af -w {}
-
-EOF
-
-# ------- Parse arguments
-my $argCount = scalar(@ARGV);
-for (my $i = 0; $i < $argCount; $i++) {
- my $a = $ARGV[$i];
- if ($a =~ /^-/) {
- if ($a eq '-av') {
- push(@ADAPTER_OPTIONS, '-v');
- } elsif ($a eq '-aq') {
- push(@ADAPTER_OPTIONS, '-q');
- } elsif ($a eq '-af') {
- push(@ADAPTER_OPTIONS, '-f');
- } elsif ($a eq '-au') {
- push(@ADAPTER_OPTIONS, '-u');
- } elsif ($a eq '-w') {
- $waitAdapter = 1;
- } elsif ($a eq '-tv') {
- push(@TRKSERVEROPTIONS, '-v');
- } elsif ($a eq '-tq') {
- push(@TRKSERVEROPTIONS, '-q');
- } elsif ($a eq '-h') {
- print $usage;
- exit(0);
- } else {
- print $usage;
- exit(1);
- }
- } else {
- $trkservername = $a;
- $runTrkServer = 0;
- }
-}
-
-# ------- Ensure build is up to date
-print "### Building\n";
-system($MAKE);
-die('Make failed: ' . $!) unless $? == 0;
-
-if ($isUnix != 0) {
- system('killall', '-s', 'USR1', 'adapter', 'trkserver');
- system('killall', 'adapter', 'trkserver');
-}
-
-my $userid=$>;
-$trkservername = ('TRKSERVER-' . $userid) unless defined $trkservername;
-my $gdbserverip= '127.0.0.1';
-my $gdbserverport= 2222 + $userid;
-
-print "Serverport: $gdbserverport\n" ;
-
-system('fuser', '-n', 'tcp', '-k', $gdbserverport) if ($isUnix);
-
-# Who writes that?
-my $tempFile = File::Spec->catfile(File::Temp::tempdir(), $trkservername);
-unlink ($tempFile) if -f $tempFile;
-
-# ------- Launch trkserver
-if ($runTrkServer) {
- my $MEMORYDUMP='TrkDump-78-6a-40-00' . $DUMP_POSTFIX;
- my @ADDITIONAL_DUMPS=('0x00402000' . $DUMP_POSTFIX, '0x786a4000' . $DUMP_POSTFIX, '0x00600000' . $DUMP_POSTFIX);
-
- my @TRKSERVER_ARGS;
- if ($isUnix) {
- push(@TRKSERVER_ARGS, File::Spec->catfile(File::Spec->curdir(), 'trkserver'));
- } else {
- push(@TRKSERVER_ARGS, 'cmd.exe', '/c', 'start', File::Spec->catfile(File::Spec->curdir(), 'debug', 'trkserver.exe'));
- }
-
- push(@TRKSERVER_ARGS, @TRKSERVEROPTIONS, $trkservername, $MEMORYDUMP, @ADDITIONAL_DUMPS);
-
- print '### Executing: ', join(' ', @TRKSERVER_ARGS), "\n";
- my $trkserverpid = fork();
- if ($trkserverpid == 0) {
- exec(@TRKSERVER_ARGS);
- exit(0);
- }
-
- push(@ADAPTER_OPTIONS, '-s');
-
- sleep(1);
-}
-
-# ------- Launch adapter
-my @ADAPTER_ARGS;
-if ($isUnix) {
- push(@ADAPTER_ARGS, File::Spec->catfile(File::Spec->curdir(), 'adapter'));
-} else {
- push(@ADAPTER_ARGS, 'cmd.exe', '/c', 'start', File::Spec->catfile(File::Spec->curdir(), 'debug', 'adapter.exe'));
-}
-
-push(@ADAPTER_ARGS, @ADAPTER_OPTIONS, $trkservername, $gdbserverip . ':' . $gdbserverport);
-print '### Executing: ', join(' ', @ADAPTER_ARGS), "\n";
-my $adapterpid=fork();
-if ($adapterpid == 0) {
- exec(@ADAPTER_ARGS);
- exit(0);
-}
-die ('Unable to launch adapter') if $adapterpid == -1;
-
-if ($waitAdapter > 0) {
- print '### kill -USR1 ',$adapterpid,"\n";
- waitpid($adapterpid, 0);
-}
-# ------- Write out .gdbinit
-my $gdbInit = <<EOF;
-# This is generated. Changes will be lost.
-#set remote noack-packet on
-set confirm off
-set endian $ENDIANESS
-#set debug remote 1
-#target remote $gdbserverip:$gdbserverport
-target extended-remote $gdbserverip:$gdbserverport
-#file filebrowseapp.sym
-add-symbol-file filebrowseapp.sym 0x786A4000
-symbol-file filebrowseapp.sym
-print E32Main
-break E32Main
-#continue
-#info files
-#file filebrowseapp.sym -readnow
-#add-symbol-file filebrowseapp.sym 0x786A4000
-EOF
-
-my $gdbInitFile = '.gdbinit';
-print '### Writing: ',$gdbInitFile, "\n";
-open (GDB_INIT, '>' . $gdbInitFile) or die ('Cannot write to ' . $gdbInitFile . ' ' . $!);
-print GDB_INIT $gdbInit;
-close( GDB_INIT);
diff --git a/tests/manual/trk/runner.cpp b/tests/manual/trk/runner.cpp
deleted file mode 100755
index 81fba1c30b..0000000000
--- a/tests/manual/trk/runner.cpp
+++ /dev/null
@@ -1,245 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#include "trkgdbadapter.h"
-#include "trkoptions.h"
-
-#include <QtCore/QDebug>
-
-#include <QtGui/QAction>
-#include <QtGui/QApplication>
-#include <QtGui/QMainWindow>
-#include <QtGui/QKeyEvent>
-#include <QtGui/QTextBlock>
-#include <QtGui/QTextEdit>
-#include <QtGui/QToolBar>
-#include <QtCore/QSharedPointer>
-#include <QtCore/QTimer>
-#include <QtCore/QDir>
-
-///////////////////////////////////////////////////////////////////////
-//
-// RunnerGui
-//
-///////////////////////////////////////////////////////////////////////
-
-class TextEdit : public QTextEdit
-{
- Q_OBJECT
-
-signals:
- void executeCommand(QString);
-
-public slots:
- void handleOutput(const QString &str0)
- {
- QString str = str0;
- str.replace("\\t", QString(QChar(0x09)));
- str.replace("\\n", QString("\n"));
- append(str);
-
- QTextCursor tc = textCursor();
- tc.movePosition(QTextCursor::End);
- setTextCursor(tc);
- /*
- int pos1 = str.indexOf("#");
- int pos2 = str.indexOf(")", pos1);
- if (pos1 != -1 && pos2 != -1)
- str = str.left(pos1) + "<b>" + str.mid(pos1, pos2 - pos1 + 1)
- + "</b> " + str.mid(pos2 + 1);
- insertHtml(str + "\n");
- */
- setCurrentCharFormat(QTextCharFormat());
- ensureCursorVisible();
- }
-
- void keyPressEvent(QKeyEvent *ev)
- {
- if (ev->modifiers() == Qt::ControlModifier && ev->key() == Qt::Key_Return)
- emit executeCommand(textCursor().block().text());
- else
- QTextEdit::keyPressEvent(ev);
- }
-};
-
-///////////////////////////////////////////////////////////////////////
-//
-// RunnerGui
-//
-///////////////////////////////////////////////////////////////////////
-
-using namespace Debugger::Internal;
-
-class RunnerGui : public QMainWindow
-{
- Q_OBJECT
-
-public:
- RunnerGui(TrkGdbAdapter *adapter);
-
-private slots:
- void executeStepICommand() { executeCommand("-exec-step-instruction"); }
- void executeStepCommand() { executeCommand("-exec-step"); }
- void executeNextICommand() { executeCommand("-exec-next-instruction"); }
- void executeNextCommand() { executeCommand("-exec-next"); }
- void executeContinueCommand() { executeCommand("-exec-continue"); }
- void executeDisassICommand() { executeCommand("disass $pc $pc+4"); }
- void executeStopCommand() { executeCommand("I"); }
-
- void handleReadyReadStandardError();
- void handleReadyReadStandardOutput();
-
- void run();
- void started();
-
-private:
- void executeCommand(const QString &cmd) { m_adapter->executeCommand(cmd); }
- void connectAction(QAction *&, QString name, const char *slot);
-
- TrkGdbAdapter *m_adapter;
- TextEdit m_textEdit;
- QToolBar m_toolBar;
- QAction *m_stopAction;
- QAction *m_stepIAction;
- QAction *m_stepAction;
- QAction *m_nextIAction;
- QAction *m_nextAction;
- QAction *m_disassIAction;
- QAction *m_continueAction;
-};
-
-RunnerGui::RunnerGui(TrkGdbAdapter *adapter)
- : m_adapter(adapter)
-{
- resize(1200, 1000);
- setCentralWidget(&m_textEdit);
-
- addToolBar(&m_toolBar);
-
- connectAction(m_stepIAction, "Step Inst", SLOT(executeStepICommand()));
- connectAction(m_stepAction, "Step", SLOT(executeStepCommand()));
- connectAction(m_nextIAction, "Next Inst", SLOT(executeNextICommand()));
- connectAction(m_nextAction, "Next", SLOT(executeNextCommand()));
- connectAction(m_disassIAction, "Disass Inst", SLOT(executeDisassICommand()));
- connectAction(m_continueAction, "Continue", SLOT(executeContinueCommand()));
- connectAction(m_stopAction, "Stop", SLOT(executeStopCommand()));
-
- connect(adapter, SIGNAL(output(QString)),
- &m_textEdit, SLOT(handleOutput(QString)));
- connect(&m_textEdit, SIGNAL(executeCommand(QString)),
- m_adapter, SLOT(executeCommand(QString)));
-
- connect(adapter, SIGNAL(readyReadStandardError()),
- this, SLOT(handleReadyReadStandardError()));
- connect(adapter, SIGNAL(readyReadStandardOutput()),
- this, SLOT(handleReadyReadStandardOutput()));
- connect(adapter, SIGNAL(started()),
- this, SLOT(started()));
-}
-
-void RunnerGui::connectAction(QAction *&action, QString name, const char *slot)
-{
- action = new QAction(this);
- action->setText(name);
- m_toolBar.addAction(action);
- connect(action, SIGNAL(triggered()), this, slot);
-}
-
-void RunnerGui::handleReadyReadStandardError()
-{
- QByteArray ba = m_adapter->readAllStandardError();
- qDebug() << ba;
- m_textEdit.handleOutput(ba);
-}
-
-void RunnerGui::handleReadyReadStandardOutput()
-{
- QByteArray ba = m_adapter->readAllStandardOutput();
- qDebug() << ba;
- m_textEdit.handleOutput("-> GDB: " + ba);
-}
-
-void RunnerGui::run()
-{
- m_adapter->run();
-}
-
-void RunnerGui::started()
-{
- qDebug() << "\nSTARTED\n";
- executeCommand("set confirm off"); // confirm potentially dangerous operations?
- executeCommand("set endian little");
- executeCommand("set remotebreak on");
- executeCommand("set breakpoint pending on");
- executeCommand("set trust-readonly-sections on");
- //executeCommand("mem 0 ~0ll rw 8 cache");
-
- // FIXME: "remote noack" does not seem to be supported on cs-gdb?
- //executeCommand("set remote noack-packet");
-
- // FIXME: creates a lot of noise a la '&"putpkt: Junk: Ack " &'
- // even though the communication seems sane
- //executeCommand("set debug remote 1"); // creates l
-
- executeCommand("add-symbol-file filebrowseapp.sym "
- + trk::hexxNumber(m_adapter->session().codeseg));
- executeCommand("symbol-file filebrowseapp.sym");
-
- //executeCommand("info address CFileBrowseAppUi::HandleCommandL",
- // GdbCB(handleInfoMainAddress));
-
- executeCommand("-break-insert filebrowseappui.cpp:39");
- executeCommand("target remote " + m_adapter->gdbServerName());
- executeCommand("-exec-continue");
-}
-
-///////////////////////////////////////////////////////////////////////
-//
-// main
-//
-///////////////////////////////////////////////////////////////////////
-
-int main(int argc, char *argv[])
-{
- QApplication app(argc, argv);
- QSharedPointer<TrkOptions> options(new TrkOptions);
- options->gdb = QDir::currentPath() + QLatin1String("/cs-gdb");
- TrkGdbAdapter adapter(options);
- adapter.setVerbose(2);
- RunnerGui gui(&adapter);
- gui.show();
- QTimer::singleShot(0, &gui, SLOT(run()));
- return app.exec();
-}
-
-#include "runner.moc"
diff --git a/tests/manual/trk/runner.pro b/tests/manual/trk/runner.pro
deleted file mode 100644
index 91a27d01c0..0000000000
--- a/tests/manual/trk/runner.pro
+++ /dev/null
@@ -1,24 +0,0 @@
-
-TEMPLATE = app
-
-TRK_DIR=../../../src/shared/trk
-include($$TRK_DIR/trk.pri)
-DEBUGGERHOME = ../../../src/plugins/debugger/gdb
-INCLUDEPATH *= $$TRK_DIR
-INCLUDEPATH *= $$DEBUGGERHOME
-
-DEFINES += STANDALONE_RUNNER
-
-QT += network
-
-win32:CONFIG+=console
-
-HEADERS += \
- $$DEBUGGERHOME/abstractgdbadapter.h \
- $$DEBUGGERHOME/trkoptions.h \
- $$DEBUGGERHOME/trkgdbadapter.h \
-
-SOURCES += \
- $$DEBUGGERHOME/trkgdbadapter.cpp \
- $$DEBUGGERHOME/trkoptions.cpp \
- $$PWD/runner.cpp \
diff --git a/tests/manual/trk/swapendian.cpp b/tests/manual/trk/swapendian.cpp
deleted file mode 100644
index 4b6dd5cb1c..0000000000
--- a/tests/manual/trk/swapendian.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-#include <QtCore>
-
-int main(int argc, char *argv[])
-{
- QFile file1(argv[1]);
- file1.open(QIODevice::ReadOnly);
-
- QByteArray ba = file1.readAll();
- file1.close();
-
- for (int i = 0; i < ba.size(); i += 4) {
- char c = ba[i]; ba[i] = ba[i + 3]; ba[i + 3] = c;
- c = ba[i + 1]; ba[i + 1] = ba[i + 2]; ba[i + 2] = c;
- }
-
- QFile file2(argv[2]);
- file2.open(QIODevice::WriteOnly);
- file2.write(ba);
- file2.close();
-}
-
diff --git a/tests/manual/trk/swapendian.pro b/tests/manual/trk/swapendian.pro
deleted file mode 100644
index 2290f2b533..0000000000
--- a/tests/manual/trk/swapendian.pro
+++ /dev/null
@@ -1,9 +0,0 @@
-
-TEMPLATE = app
-MAKEFILE = Makefile.swapendian
-QT = core
-
-HEADERS += \
-
-SOURCES += \
- swapendian.cpp
diff --git a/tests/manual/trk/trk.pro b/tests/manual/trk/trk.pro
deleted file mode 100644
index c859c905c2..0000000000
--- a/tests/manual/trk/trk.pro
+++ /dev/null
@@ -1,7 +0,0 @@
-
-TEMPLATE = subdirs
-
-SUBDIRS = trkserver swapendian runner.pro
-
-trkserver.file = trkserver.pro
-swapendian.file = swapendian.pro
diff --git a/tests/manual/trk/trklauncher.pri b/tests/manual/trk/trklauncher.pri
deleted file mode 100644
index a9abc53895..0000000000
--- a/tests/manual/trk/trklauncher.pri
+++ /dev/null
@@ -1,15 +0,0 @@
-DEFINES += DEBUG_TRK=0
-TRK_DIR = ../../../src/plugins/debugger/gdb
-
-INCLUDEPATH *= $$PWD $$TRK_DIR
-
-SOURCES += \
- $$TRK_DIR/trkutils.cpp \
- $$PWD/trkdevice.cpp \
- $$PWD/launcher.cpp \
-
-HEADERS += \
- $$TRK_DIR/trkutils.h \
- $$TRK_DIR/callback.h \
- $$PWD/trkdevice.h \
- $$PWD/launcher.h
diff --git a/tests/manual/trk/trkolddevice.cpp b/tests/manual/trk/trkolddevice.cpp
deleted file mode 100644
index 25407edbbf..0000000000
--- a/tests/manual/trk/trkolddevice.cpp
+++ /dev/null
@@ -1,694 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#include "trkolddevice.h"
-#include "trkutils.h"
-
-#include <QtCore/QString>
-#include <QtCore/QDebug>
-#include <QtCore/QQueue>
-#include <QtCore/QHash>
-#include <QtCore/QMap>
-#include <QtCore/QSharedPointer>
-
-#ifdef Q_OS_WIN
-# include <windows.h>
-#else
-# include <QtCore/QFile>
-
-# include <stdio.h>
-# include <sys/ioctl.h>
-# include <termios.h>
-# include <errno.h>
-# include <string.h>
-# include <unistd.h>
-#endif
-
-enum { TimerInterval = 100 };
-
-#ifdef Q_OS_WIN
-
-// Format windows error from GetLastError() value: TODO: Use the one provided by the utisl lib.
-static QString winErrorMessage(unsigned long error)
-{
- QString rc = QString::fromLatin1("#%1: ").arg(error);
- ushort *lpMsgBuf;
-
- const int len = FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, error, 0, (LPTSTR)&lpMsgBuf, 0, NULL);
- if (len) {
- rc = QString::fromUtf16(lpMsgBuf, len);
- LocalFree(lpMsgBuf);
- } else {
- rc += QString::fromLatin1("<unknown error>");
- }
- return rc;
-}
-
-// Non-blocking replacement for win-api ReadFile function
-static BOOL WINAPI TryReadFile(HANDLE hFile,
- LPVOID lpBuffer,
- DWORD nNumberOfBytesToRead,
- LPDWORD lpNumberOfBytesRead,
- LPOVERLAPPED lpOverlapped)
-{
- COMSTAT comStat;
- if (!ClearCommError(hFile, NULL, &comStat)){
- qDebug()<<("ClearCommError() failed");
- return FALSE;
- }
- if (comStat.cbInQue == 0) {
- *lpNumberOfBytesRead = 0;
- return FALSE;
- }
- return ReadFile(hFile,
- lpBuffer,
- qMin(comStat.cbInQue, nNumberOfBytesToRead),
- lpNumberOfBytesRead,
- lpOverlapped);
-}
-#endif
-
-namespace trkold {
-
-struct TrkDevicePrivate {
- TrkDevicePrivate();
-#ifdef Q_OS_WIN
- HANDLE hdevice;
-#else
- QFile file;
-#endif
-
- QByteArray trkReadBuffer;
- bool trkWriteBusy;
- int timerId;
- bool serialFrame;
- bool verbose;
- QString errorString;
-};
-
-TrkDevicePrivate::TrkDevicePrivate() :
-#ifdef Q_OS_WIN
- hdevice(INVALID_HANDLE_VALUE),
-#endif
- trkWriteBusy(false),
- timerId(-1),
- serialFrame(true),
- verbose(false)
-{
-
-}
-
-TrkDevice::TrkDevice(QObject *parent) :
- QObject(parent),
- d(new TrkDevicePrivate)
-{
-}
-
-bool TrkDevice::open(const QString &port, QString *errorMessage)
-{
- close();
-#ifdef Q_OS_WIN
- d->hdevice = CreateFile(port.toStdWString().c_str(),
- GENERIC_READ | GENERIC_WRITE,
- 0,
- NULL,
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
-
- if (INVALID_HANDLE_VALUE == d->hdevice) {
- *errorMessage = QString::fromLatin1("Could not open device '%1': %2").arg(port, winErrorMessage(GetLastError()));
- return false;
- }
- d->timerId = startTimer(TimerInterval);
- return true;
-#else
- d->file.setFileName(port);
- if (!d->file.open(QIODevice::ReadWrite|QIODevice::Unbuffered)) {
- *errorMessage = QString::fromLatin1("Cannot open %1: %2").arg(port, d->file.errorString());
- return false;
- }
-
- struct termios termInfo;
- if (tcgetattr(d->file.handle(), &termInfo) < 0) {
- *errorMessage = QString::fromLatin1("Unable to retrieve terminal settings: %1 %2").arg(errno).arg(QString::fromAscii(strerror(errno)));
- return false;
- }
- // Turn off terminal echo as not get messages back, among other things
- termInfo.c_cflag|=CREAD|CLOCAL;
- termInfo.c_lflag&=(~(ICANON|ECHO|ECHOE|ECHOK|ECHONL|ISIG));
- termInfo.c_iflag&=(~(INPCK|IGNPAR|PARMRK|ISTRIP|ICRNL|IXANY));
- termInfo.c_oflag&=(~OPOST);
- termInfo.c_cc[VMIN]=0;
- termInfo.c_cc[VINTR] = _POSIX_VDISABLE;
- termInfo.c_cc[VQUIT] = _POSIX_VDISABLE;
- termInfo.c_cc[VSTART] = _POSIX_VDISABLE;
- termInfo.c_cc[VSTOP] = _POSIX_VDISABLE;
- termInfo.c_cc[VSUSP] = _POSIX_VDISABLE;
- if (tcsetattr(d->file.handle(), TCSAFLUSH, &termInfo) < 0) {
- *errorMessage = QString::fromLatin1("Unable to apply terminal settings: %1 %2").arg(errno).arg(QString::fromAscii(strerror(errno)));
- return false;
- }
- d->timerId = startTimer(TimerInterval);
- return true;
-#endif
-}
-
-
-TrkDevice::~TrkDevice()
-{
- close();
- delete d;
-}
-
-void TrkDevice::close()
-{
- if (!isOpen())
- return;
- if (d->timerId != -1) {
- killTimer(d->timerId);
- d->timerId = -1;
- }
-#ifdef Q_OS_WIN
- CloseHandle(d->hdevice);
- d->hdevice = INVALID_HANDLE_VALUE;
-#else
- d->file.close();
-#endif
- if (verbose())
- logMessage("Close");
-}
-
-bool TrkDevice::isOpen() const
-{
-#ifdef Q_OS_WIN
- return d->hdevice != INVALID_HANDLE_VALUE;
-#else
- return d->file.isOpen();
-#endif
-}
-
-QString TrkDevice::errorString() const
-{
- return d->errorString;
-}
-
-bool TrkDevice::serialFrame() const
-{
- return d->serialFrame;
-}
-
-void TrkDevice::setSerialFrame(bool f)
-{
- d->serialFrame = f;
-}
-
-bool TrkDevice::verbose() const
-{
- return true || d->verbose;
-}
-
-void TrkDevice::setVerbose(bool b)
-{
- d->verbose = b;
-}
-
-bool TrkDevice::write(const QByteArray &data, QString *errorMessage)
-{
- if (verbose())
- logMessage("XWRITE " + data.toHex());
-#ifdef Q_OS_WIN
- DWORD charsWritten;
- if (!WriteFile(d->hdevice, data.data(), data.size(), &charsWritten, NULL)) {
- *errorMessage = QString::fromLatin1("Error writing data: %1").arg(winErrorMessage(GetLastError()));
- return false;
- }
- FlushFileBuffers(d->hdevice);
- return true;
-#else
- if (d->file.write(data) == -1 || !d->file.flush()) {
- *errorMessage = QString::fromLatin1("Cannot write: %1").arg(d->file.errorString());
- return false;
- }
- return true;
-#endif
-}
-
-#ifndef Q_OS_WIN
-static inline int bytesAvailable(int fileNo)
-{
- int numBytes;
- const int rc = ioctl(fileNo, FIONREAD, &numBytes);
- if (rc < 0)
- numBytes=0;
- return numBytes;
-}
-#endif
-
-void TrkDevice::tryTrkRead()
-{
-#ifdef Q_OS_WIN
- const DWORD BUFFERSIZE = 1024;
- char buffer[BUFFERSIZE];
- DWORD charsRead;
- DWORD totalCharsRead = 0;
-
- while (TryReadFile(d->hdevice, buffer, BUFFERSIZE, &charsRead, NULL)) {
- totalCharsRead += charsRead;
- d->trkReadBuffer.append(buffer, charsRead);
- if (isValidTrkResult(d->trkReadBuffer, d->serialFrame))
- break;
- }
- if (verbose() && totalCharsRead)
- logMessage("Read" + d->trkReadBuffer.toHex());
- if (!totalCharsRead)
- return;
- const ushort len = trk::isValidTrkResult(d->trkReadBuffer, d->serialFrame);
- if (!len) {
- const QString msg = QString::fromLatin1("Partial message: %1").arg(stringFromArray(d->trkReadBuffer));
- emitError(msg);
- return;
- }
-#else
- const int size = bytesAvailable(d->file.handle());
- if (!size)
- return;
- const QByteArray data = d->file.read(size);
- if (verbose())
- logMessage("READ " + data.toHex());
- d->trkReadBuffer.append(data);
- const ushort len = trk::isValidTrkResult(d->trkReadBuffer, d->serialFrame);
- if (!len) {
- if (d->trkReadBuffer.size() > 10) {
- const QString msg = QString::fromLatin1("Unable to extract message from '%1' '%2'").
- arg(QLatin1String(d->trkReadBuffer.toHex())).arg(QString::fromAscii(d->trkReadBuffer));
- emitError(msg);
- }
- return;
- }
-#endif // Q_OS_WIN
- trk::TrkResult r;
- QByteArray rawData;
- while (extractResult(&d->trkReadBuffer, d->serialFrame, &r, &rawData)) {
- if (verbose())
- logMessage("Read TrkResult " + r.data.toHex());
- emit messageReceived(r);
- if (!rawData.isEmpty())
- emit rawDataReceived(rawData);
- }
-}
-
-void TrkDevice::timerEvent(QTimerEvent *)
-{
- tryTrkRead();
-}
-
-void TrkDevice::emitError(const QString &s)
-{
- d->errorString = s;
- qWarning("%s\n", qPrintable(s));
- emit error(s);
-}
-
-/* A message to be send to TRK, triggering a callback on receipt
- * of the answer. */
-typedef trk::Callback<const trk::TrkResult &> TrkCallback;
-struct TrkMessage {
- explicit TrkMessage(unsigned char code = 0u,
- unsigned char token = 0u,
- TrkCallback callback = TrkCallback());
-
- unsigned char code;
- unsigned char token;
- QByteArray data;
- QVariant cookie;
- TrkCallback callback;
- bool invokeOnNAK;
-};
-
-TrkMessage::TrkMessage(unsigned char c,
- unsigned char t,
- TrkCallback cb) :
- code(c),
- token(t),
- callback(cb),
- invokeOnNAK(false)
-{
-}
-
-// ------- TrkWriteQueueDevice
-typedef QSharedPointer<TrkMessage> SharedPointerTrkMessage;
-
-/* Mixin class that manages a write queue of Trk messages. */
-
-class TrkWriteQueue {
-public:
- TrkWriteQueue();
-
- // Enqueue messages.
- void queueTrkMessage(unsigned char code, TrkCallback callback,
- const QByteArray &data, const QVariant &cookie,
- bool invokeOnNAK);
- void queueTrkInitialPing();
-
- // Call this from the device read notification with the results.
- void slotHandleResult(const trk::TrkResult &result);
-
- // This can be called periodically in a timer to retrieve
- // the pending messages to be sent.
- bool pendingMessage(SharedPointerTrkMessage *message = 0);
- // Notify the queue about the success of the write operation
- // after taking the pendingMessage off.
- void notifyWriteResult(bool ok);
-
- // Factory function for ack message
- static SharedPointerTrkMessage trkAck(unsigned char token);
-
-private:
- typedef QMap<unsigned char, SharedPointerTrkMessage> TokenMessageMap;
-
- unsigned char nextTrkWriteToken();
-
- unsigned char trkWriteToken;
- QQueue<SharedPointerTrkMessage> trkWriteQueue;
- TokenMessageMap writtenTrkMessages;
- bool trkWriteBusy;
-};
-
-TrkWriteQueue::TrkWriteQueue() :
- trkWriteToken(0),
- trkWriteBusy(false)
-{
-}
-
-unsigned char TrkWriteQueue::nextTrkWriteToken()
-{
- ++trkWriteToken;
- if (trkWriteToken == 0)
- ++trkWriteToken;
- return trkWriteToken;
-}
-
-void TrkWriteQueue::queueTrkMessage(unsigned char code, TrkCallback callback,
- const QByteArray &data, const QVariant &cookie,
- bool invokeOnNAK)
-{
- const unsigned char token = code == TRK_WRITE_QUEUE_NOOP_CODE ?
- (unsigned char)(0) : nextTrkWriteToken();
- SharedPointerTrkMessage msg(new TrkMessage(code, token, callback));
- msg->data = data;
- msg->cookie = cookie;
- msg->invokeOnNAK = invokeOnNAK;
- trkWriteQueue.append(msg);
-}
-
-bool TrkWriteQueue::pendingMessage(SharedPointerTrkMessage *message)
-{
- // Invoked from timer, try to flush out message queue
- if (trkWriteBusy || trkWriteQueue.isEmpty())
- return false;
- // Handle the noop message, just invoke CB
- if (trkWriteQueue.front()->code == TRK_WRITE_QUEUE_NOOP_CODE) {
- const SharedPointerTrkMessage noopMessage = trkWriteQueue.dequeue();
- if (noopMessage->callback) {
- trk::TrkResult result;
- result.code = noopMessage->code;
- result.token = noopMessage->token;
- result.data = noopMessage->data;
- result.cookie = noopMessage->cookie;
- noopMessage->callback(result);
- }
- }
- // Check again for real messages
- if (trkWriteQueue.isEmpty())
- return false;
- if (message)
- *message = trkWriteQueue.front();
- return true;
-}
-
-void TrkWriteQueue::notifyWriteResult(bool ok)
-{
- // On success, dequeue message and await result
- if (ok) {
- const SharedPointerTrkMessage firstMsg = trkWriteQueue.dequeue();
- writtenTrkMessages.insert(firstMsg->token, firstMsg);
- trkWriteBusy = true;
- }
-}
-
-void TrkWriteQueue::slotHandleResult(const trk::TrkResult &result)
-{
- trkWriteBusy = false;
- if (result.code != trk::TrkNotifyAck && result.code != trk::TrkNotifyNak)
- return;
- // Find which request the message belongs to and invoke callback
- // if ACK or on NAK if desired.
- const TokenMessageMap::iterator it = writtenTrkMessages.find(result.token);
- if (it == writtenTrkMessages.end())
- return;
- const bool invokeCB = it.value()->callback
- && (result.code == trk::TrkNotifyAck || it.value()->invokeOnNAK);
-
- if (invokeCB) {
- trk::TrkResult result1 = result;
- result1.cookie = it.value()->cookie;
- it.value()->callback(result1);
- }
- writtenTrkMessages.erase(it);
-}
-
-SharedPointerTrkMessage TrkWriteQueue::trkAck(unsigned char token)
-{
- SharedPointerTrkMessage msg(new TrkMessage(0x80, token));
- msg->token = token;
- msg->data.append('\0');
- return msg;
-}
-
-void TrkWriteQueue::queueTrkInitialPing()
-{
- const SharedPointerTrkMessage msg(new TrkMessage(0, 0)); // Ping, reset sequence count
- trkWriteQueue.append(msg);
-}
-
-// -----------------------
-TrkWriteQueueDevice::TrkWriteQueueDevice(QObject *parent) :
- TrkDevice(parent),
- qd(new TrkWriteQueue)
-{
- connect(this, SIGNAL(messageReceived(trk::TrkResult)), this, SLOT(slotHandleResult(trk::TrkResult)));
-}
-
-TrkWriteQueueDevice::~TrkWriteQueueDevice()
-{
- delete qd;
-}
-
-void TrkWriteQueueDevice::sendTrkMessage(unsigned char code, TrkCallback callback,
- const QByteArray &data, const QVariant &cookie,
- bool invokeOnNAK)
-{
- qd->queueTrkMessage(code, callback, data, cookie, invokeOnNAK);
-}
-
-void TrkWriteQueueDevice::sendTrkInitialPing()
-{
- qd->queueTrkInitialPing();
-}
-
-bool TrkWriteQueueDevice::sendTrkAck(unsigned char token)
-{
- // The acknowledgement must not be queued!
- const SharedPointerTrkMessage ack = TrkWriteQueue::trkAck(token);
- return trkWriteRawMessage(*ack);
- // 01 90 00 07 7e 80 01 00 7d 5e 7e
-}
-
-void TrkWriteQueueDevice::tryTrkWrite()
-{
- if (!qd->pendingMessage())
- return;
- SharedPointerTrkMessage message;
- qd->pendingMessage(&message);
- const bool success = trkWriteRawMessage(*message);
- qd->notifyWriteResult(success);
-}
-
-bool TrkWriteQueueDevice::trkWriteRawMessage(const TrkMessage &msg)
-{
- const QByteArray ba = trk::frameMessage(msg.code, msg.token, msg.data, serialFrame());
- if (verbose())
- logMessage("WRITE: " + trk::stringFromArray(ba));
- QString errorMessage;
- const bool rc = write(ba, &errorMessage);
- if (!rc)
- emitError(errorMessage);
- return rc;
-}
-
-void TrkWriteQueueDevice::timerEvent(QTimerEvent *ev)
-{
- tryTrkWrite();
- TrkDevice::timerEvent(ev);
-}
-
-void TrkWriteQueueDevice::slotHandleResult(const trk::TrkResult &result)
-{
- qd->slotHandleResult(result);
-}
-
-// ----------- TrkWriteQueueDevice
-
-struct TrkWriteQueueIODevicePrivate {
- TrkWriteQueueIODevicePrivate(const QSharedPointer<QIODevice> &d);
-
- const QSharedPointer<QIODevice> device;
- TrkWriteQueue queue;
- QByteArray readBuffer;
- bool serialFrame;
- bool verbose;
-};
-
-TrkWriteQueueIODevicePrivate::TrkWriteQueueIODevicePrivate(const QSharedPointer<QIODevice> &d) :
- device(d),
- serialFrame(true),
- verbose(false)
-{
-}
-
-TrkWriteQueueIODevice::TrkWriteQueueIODevice(const QSharedPointer<QIODevice> &device,
- QObject *parent) :
- QObject(parent),
- d(new TrkWriteQueueIODevicePrivate(device))
-{
- startTimer(TimerInterval);
-}
-
-TrkWriteQueueIODevice::~TrkWriteQueueIODevice()
-{
- delete d;
-}
-
-bool TrkWriteQueueIODevice::serialFrame() const
-{
- return d->serialFrame;
-}
-
-void TrkWriteQueueIODevice::setSerialFrame(bool f)
-{
- d->serialFrame = f;
-}
-
-bool TrkWriteQueueIODevice::verbose() const
-{
- return true || d->verbose;
-}
-
-void TrkWriteQueueIODevice::setVerbose(bool b)
-{
- d->verbose = b;
-}
-
-void TrkWriteQueueIODevice::sendTrkMessage(unsigned char code, TrkCallback callback,
- const QByteArray &data, const QVariant &cookie,
- bool invokeOnNAK)
-{
- d->queue.queueTrkMessage(code, callback, data, cookie, invokeOnNAK);
-}
-
-void TrkWriteQueueIODevice::sendTrkInitialPing()
-{
- d->queue.queueTrkInitialPing();
-}
-
-bool TrkWriteQueueIODevice::sendTrkAck(unsigned char token)
-{
- // The acknowledgement must not be queued!
- const SharedPointerTrkMessage ack = TrkWriteQueue::trkAck(token);
- return trkWriteRawMessage(*ack);
- // 01 90 00 07 7e 80 01 00 7d 5e 7e
-}
-
-
-void TrkWriteQueueIODevice::timerEvent(QTimerEvent *)
-{
- tryTrkWrite();
- tryTrkRead();
-}
-
-void TrkWriteQueueIODevice::tryTrkWrite()
-{
- if (!d->queue.pendingMessage())
- return;
- SharedPointerTrkMessage message;
- d->queue.pendingMessage(&message);
- const bool success = trkWriteRawMessage(*message);
- d->queue.notifyWriteResult(success);
-}
-
-bool TrkWriteQueueIODevice::trkWriteRawMessage(const TrkMessage &msg)
-{
- const QByteArray ba = trk::frameMessage(msg.code, msg.token, msg.data, serialFrame());
- if (verbose())
- logMessage("WRITE: " + trk::stringFromArray(ba));
- const bool ok = d->device->write(ba) != -1;
- if (!ok) {
- const QString msg = QString::fromLatin1("Unable to write %1 bytes: %2:").arg(ba.size()).arg(d->device->errorString());
- qWarning("%s\n", qPrintable(msg));
- }
- return ok;
-}
-
-void TrkWriteQueueIODevice::tryTrkRead()
-{
- const quint64 bytesAvailable = d->device->bytesAvailable();
- if (!bytesAvailable)
- return;
- const QByteArray newData = d->device->read(bytesAvailable);
- //if (verbose())
- logMessage("READ " + newData.toHex());
- d->readBuffer.append(newData);
- trk::TrkResult r;
- QByteArray rawData;
- while (trk::extractResult(&(d->readBuffer), d->serialFrame, &r, &rawData)) {
- d->queue.slotHandleResult(r);
- emit messageReceived(r);
- if (!rawData.isEmpty())
- emit rawDataReceived(rawData);
- }
-}
-
-} // namespace trkold
diff --git a/tests/manual/trk/trkolddevice.h b/tests/manual/trk/trkolddevice.h
deleted file mode 100644
index b51200a41b..0000000000
--- a/tests/manual/trk/trkolddevice.h
+++ /dev/null
@@ -1,206 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#ifndef TRKOLDDEVICE_H
-#define TRKOLDDEVICE_H
-
-#include "callback.h"
-
-#include <QtCore/QObject>
-#include <QtCore/QVariant>
-#include <QtCore/QByteArray>
-#include <QtCore/QSharedPointer>
-
-QT_BEGIN_NAMESPACE
-class QIODevice;
-QT_END_NAMESPACE
-
-
-namespace trk {
- struct TrkResult;
-}
-
-namespace trkold {
-
-struct TrkMessage;
-struct TrkDevicePrivate;
-class TrkWriteQueue;
-struct TrkWriteQueueIODevicePrivate;
-
-/* TrkDevice: Implements a Windows COM or Linux device for
- * Trk communications. Provides synchronous write and asynchronous
- * read operation.
- * The serialFrames property specifies whether packets are encapsulated in
- * "0x90 <length>" frames, which is currently the case for serial ports. */
-
-class TrkDevice : public QObject
-{
- Q_DISABLE_COPY(TrkDevice)
- Q_OBJECT
- Q_PROPERTY(bool serialFrame READ serialFrame WRITE setSerialFrame)
- Q_PROPERTY(bool verbose READ verbose WRITE setVerbose)
-public:
- explicit TrkDevice(QObject *parent = 0);
- virtual ~TrkDevice();
-
- bool open(const QString &port, QString *errorMessage);
- bool isOpen() const;
- void close();
-
- QString errorString() const;
-
- bool serialFrame() const;
- void setSerialFrame(bool f);
-
- bool verbose() const;
- void setVerbose(bool b);
-
- bool write(const QByteArray &data, QString *errorMessage);
-
-signals:
- void messageReceived(const trk::TrkResult &result);
- // Emitted with the contents of messages enclosed in 07e, not for log output
- void rawDataReceived(const QByteArray &data);
- void error(const QString &msg);
- void logMessage(const QString &msg);
-
-protected:
- void emitError(const QString &msg);
- virtual void timerEvent(QTimerEvent *ev);
-
-private:
- void tryTrkRead();
-
- TrkDevicePrivate *d;
-};
-
-/* TrkWriteQueueDevice: Extends TrkDevice by write message queue allowing
- * for queueing messages with a notification callback. If the message receives
- * an ACK, the callback is invoked.
- * The special message TRK_WRITE_QUEUE_NOOP_CODE code can be used for synchronisation.
- * The respective message will not be sent, the callback is just invoked. */
-
-enum { TRK_WRITE_QUEUE_NOOP_CODE = 0x7f };
-
-class TrkWriteQueueDevice : public TrkDevice
-{
- Q_OBJECT
-public:
- explicit TrkWriteQueueDevice(QObject *parent = 0);
- virtual ~TrkWriteQueueDevice();
-
- // Construct as 'TrkWriteQueueDevice::TrkCallback(instance, &Class::method);'
- typedef trk::Callback<const trk::TrkResult &> TrkCallback;
-
- // Enqueue a message with a notification callback.
- void sendTrkMessage(unsigned char code,
- TrkCallback callBack = TrkCallback(),
- const QByteArray &data = QByteArray(),
- const QVariant &cookie = QVariant(),
- // Invoke callback on receiving NAK, too.
- bool invokeOnNAK = false);
-
- // Enqeue an initial ping
- void sendTrkInitialPing();
-
- // Send an Ack synchronously, bypassing the queue
- bool sendTrkAck(unsigned char token);
-
-signals:
- void logMessage(const QString &msg);
-
-private slots:
- void slotHandleResult(const trk::TrkResult &);
-
-protected:
- virtual void timerEvent(QTimerEvent *ev);
-
-private:
- void tryTrkWrite();
- bool trkWriteRawMessage(const TrkMessage &msg);
-
- TrkWriteQueue *qd;
-};
-
-/* A Trk queueing device wrapping around a QIODevice (otherwise
- * mimicking TrkWriteQueueDevice).
- * Can be used to forward Trk over a network or to simulate things. */
-
-class TrkWriteQueueIODevice : public QObject
-{
- Q_OBJECT
- Q_DISABLE_COPY(TrkWriteQueueIODevice)
- Q_PROPERTY(bool serialFrame READ serialFrame WRITE setSerialFrame)
- Q_PROPERTY(bool verbose READ verbose WRITE setVerbose)
-public:
- typedef trk::Callback<const trk::TrkResult &> TrkCallback;
-
- explicit TrkWriteQueueIODevice(const QSharedPointer<QIODevice> &device,
- QObject *parent = 0);
- virtual ~TrkWriteQueueIODevice();
-
- bool serialFrame() const;
- void setSerialFrame(bool f);
-
- bool verbose() const;
- void setVerbose(bool b);
-
- void sendTrkMessage(unsigned char code,
- TrkCallback callback = TrkCallback(),
- const QByteArray &data = QByteArray(),
- const QVariant &cookie = QVariant(),
- bool invokeOnNAK = false);
- void sendTrkInitialPing();
- bool sendTrkAck(unsigned char token);
-
-signals:
- void messageReceived(const trk::TrkResult&);
- // Emitted with the contents of messages enclosed in 07e, not for log output
- void rawDataReceived(const QByteArray &data);
- void logMessage(const QString &msg);
-
-
-protected:
- virtual void timerEvent(QTimerEvent *ev);
-
-private:
- void tryTrkRead();
- void tryTrkWrite();
- bool trkWriteRawMessage(const TrkMessage &msg);
-
- TrkWriteQueueIODevicePrivate *d;
-};
-
-} // namespace trkold
-
-#endif // TRKOLDDEVICE_H
diff --git a/tests/manual/trk/trkserver.cpp b/tests/manual/trk/trkserver.cpp
deleted file mode 100644
index ea1b20e9b6..0000000000
--- a/tests/manual/trk/trkserver.cpp
+++ /dev/null
@@ -1,517 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** No Commercial Usage
-**
-** This file 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.
-**
-**************************************************************************/
-
-#include "trkutils.h"
-
-#include <QtCore/QCoreApplication>
-#include <QtCore/QFile>
-#include <QtCore/QStringList>
-#include <QtCore/QFileInfo>
-
-#include <QtNetwork/QLocalServer>
-#include <QtNetwork/QLocalSocket>
-
-
-#ifdef Q_OS_UNIX
-
-#include <signal.h>
-
-void signalHandler(int)
-{
- qApp->exit(1);
-}
-
-#endif
-
-using namespace trk;
-
-struct TrkOptions {
- TrkOptions() : verbose(1), serialFrame(true) {}
-
- int verbose;
- bool serialFrame;
- QString serverName;
- QString dumpName;
- QStringList additionalDumps;
-};
-
-
-// Format of the replay source is something like
-// ---IDE------------------------------------------------------
-// Command: 0x05 Support Mask
-// [05 02]
-//---TRK------------------------------------------------------
-// Command: 0x80 Acknowledge
-// Error: 0x0
-// [80 02 00 7E 00 4F 5F 01 00 00 00 0F 1F 00 00 00
-// 00 00 00 01 00 11 00 03 00 00 00 00 00 03 00 00...]
-
-struct MemorySegment {
- MemorySegment(const QString &n = QString()) : name(n), address(0) {}
-
- bool readDump(const QString &fileName, uint address /* = 0*/, QString *errorMessage);
- bool readMemory(uint addr, ushort len, QByteArray *ba) const;
-
- QString name;
- uint address;
- QByteArray data;
-};
-
-// Determine address from filename using the "0xa5453.bin" convention
-
-static int addressFromFileName(const QString &fn)
-{
- QString baseName = QFileInfo(fn).fileName();
- if (!baseName.startsWith(QLatin1String("0x")))
- return -1;
- baseName.remove(0, 2);
- int sepPos = baseName.indexOf(QLatin1Char('_'));
- if (sepPos == -1)
- sepPos = baseName.indexOf(QLatin1Char('-'));
- if (sepPos == -1)
- sepPos = baseName.indexOf(QLatin1Char('.'));
- if (sepPos == -1)
- return -1;
- baseName.truncate(sepPos);
- bool ok;
- const int value = baseName.toInt(&ok, 16);
- return ok ? value : -1;
-}
-
-// Read a chunk of memory from file. Use address unless it is 0,
-// in which case the filename is used for matching "0xa5453.bin"
-bool MemorySegment::readDump(const QString &fileName, uint addressIn /* = 0*/, QString *errorMessage)
-{
- QFile file(fileName);
- if (!file.open(QIODevice::ReadOnly)) {
- *errorMessage = QString::fromLatin1("Unable to read %1: %2").arg(fileName, file.errorString());
- return false;
- }
- data = file.readAll();
- file.close();
- if (addressIn) {
- address = addressIn;
- } else {
- const int addressInt = addressFromFileName(fileName);
- if (addressInt == -1) {
- *errorMessage = QString::fromLatin1("Unable to determine address from %1").arg(fileName);
- return false;
- }
- address = addressInt;
- }
- *errorMessage = QString::fromLatin1("Read %1 bytes of data starting at 0x%2 from %3").arg(data.size()).arg(address, 0, 16).arg(fileName);
- return true;
-}
-
-bool MemorySegment::readMemory(uint addr, ushort len, QByteArray *ba) const
-{
- if (addr < address)
- return false;
- const int requestStart = addr - address;
- const int requestEnd = requestStart + len;
- if (requestEnd > data.size())
- return false;
- for (int i = requestStart; i != requestEnd; ++i)
- appendByte(ba, data.at(i));
- return true;
-}
-
-struct Inferior
-{
- Inferior();
- uint pid;
- uint tid;
- uint codeseg;
- uint dataseg;
-
- uint registers[RegisterCount];
- QList<MemorySegment> memorySegments;
-};
-
-Inferior::Inferior()
-{
- pid = 0x000008F5;
- tid = 0x000008F6;
-
- codeseg = 0x786A4000;
- dataseg = 0x00400000;
-
- registers[0] = 0x00000000;
- registers[1] = 0xC92D7FBC;
- registers[2] = 0x00000000;
- registers[3] = 0x00600000;
- registers[4] = 0x00000000;
- registers[5] = 0x786A7970;
- registers[6] = 0x00000000;
- registers[7] = 0x00000000;
- registers[8] = 0x00000012;
- registers[9] = 0x00000040;
- registers[10] = 0xC82AF210;
- registers[11] = 0x00000000;
- registers[12] = 0xC8000548;
- registers[13] = 0x00403ED0;
- registers[14] = 0x786A6BD8;
- registers[15] = 0x786A4CC8;
- registers[16] = 0x68000010; // that's reg 25 on chip?
-}
-
-class TrkServer : public QObject
-{
- Q_OBJECT
-
-public:
- TrkServer();
- ~TrkServer();
-
- void setServerName(const QString &name) { m_serverName = name; }
- void setMemoryDumpName(const QString &source) { m_memoryDumpName = source; }
- void setVerbose(int v) { m_verbose = v; }
- void setSerialFrame(bool b) { m_serialFrame = b; }
- bool readDump(const QString &fn);
- bool startServer();
-
-private slots:
- void handleConnection();
- void readFromAdapter();
- void writeToAdapter(byte command, byte token, const QByteArray &data);
-
- void handleAdapterMessage(const TrkResult &result);
-
-private:
- void logMessage(const QString &msg, bool force = 0) const;
- bool handleMemoryRequest(uint addr, ushort len, byte option, QByteArray *ba) const;
- byte nextNotificationToken();
-
- QString m_serverName;
- QString m_memoryDumpName;
-
- QByteArray m_adapterReadBuffer;
-
- QByteArray m_memoryData;
- QLocalServer m_server;
- int m_lastSent;
- QLocalSocket *m_adapterConnection;
- Inferior m_inferior;
- byte m_notificationToken;
- int m_verbose;
- bool m_serialFrame;
-};
-
-TrkServer::TrkServer() :
- m_adapterConnection(0),
- m_notificationToken(0),
- m_verbose(1),
- m_serialFrame(true)
-{
-}
-
-TrkServer::~TrkServer()
-{
- logMessage("Shutting down.\n");
- m_server.close();
-}
-
-bool TrkServer::readDump(const QString &fn)
-{
- QString msg;
- MemorySegment segment(QLatin1String("data"));
- if (!segment.readDump(fn, 0, &msg)) {
- logMessage(msg, true);
- return false;
- }
- m_inferior.memorySegments.push_back(segment);
- logMessage(msg, true);
- return true;
-}
-
-bool TrkServer::startServer()
-{
- QString msg;
- MemorySegment codeSegment(QLatin1String("code"));
- if (!codeSegment.readDump(m_memoryDumpName, 0x786A4000, &msg)) {
- logMessage(msg, true);
- return false;
- }
- m_inferior.memorySegments.push_front(codeSegment);
- logMessage(msg, true);
-
- m_lastSent = 0;
- if (!m_server.listen(m_serverName)) {
- logMessage(QString("Error: Unable to start the TRK server %1: %2.")
- .arg(m_serverName).arg(m_server.errorString()), true);
- return false;
- }
-
- logMessage("The TRK server '" + m_serverName + "'is running. Run the adapter now.", true);
- connect(&m_server, SIGNAL(newConnection()), this, SLOT(handleConnection()));
- return true;
-}
-
-void TrkServer::logMessage(const QString &msg, bool force) const
-{
- if (m_verbose || force)
- qDebug("TRKSERVER: %s", qPrintable(msg));
-}
-
-void TrkServer::handleConnection()
-{
- m_adapterConnection = m_server.nextPendingConnection();
- connect(m_adapterConnection, SIGNAL(disconnected()),
- m_adapterConnection, SLOT(deleteLater()));
- connect(m_adapterConnection, SIGNAL(readyRead()),
- this, SLOT(readFromAdapter()));
-}
-
-void TrkServer::readFromAdapter()
-{
- QByteArray packet = m_adapterConnection->readAll();
- m_adapterReadBuffer.append(packet);
-
- logMessage("trk: -> " + stringFromArray(packet));
-
- if (packet != m_adapterReadBuffer)
- logMessage("buffer: " + stringFromArray(m_adapterReadBuffer));
-
- while (!m_adapterReadBuffer.isEmpty()) {
- TrkResult r;
- while (extractResult(&m_adapterReadBuffer, m_serialFrame, &r))
- handleAdapterMessage(r);
- }
-}
-
-void TrkServer::writeToAdapter(byte command, byte token, const QByteArray &data)
-{
- QByteArray msg = frameMessage(command, token, data, m_serialFrame);
- logMessage("trk: <- " + stringFromArray(msg));
- m_adapterConnection->write(msg);
-}
-
-bool TrkServer::handleMemoryRequest(uint addr, ushort len, byte option, QByteArray *ba) const
-{
- Q_UNUSED(option);
- foreach (const MemorySegment &s, m_inferior.memorySegments) {
- if (s.readMemory(addr, len, ba)) {
- if (m_verbose)
- logMessage(QString::fromLatin1("Read memory %1 bytes from 0x%2 from segment %3.").arg(len).arg(addr, 0, 16).arg(s.name));
- return true;
- }
- }
- logMessage(QString::fromLatin1("ADDRESS OUTSIDE ANY SEGMENTS: 0X%1").arg(addr, 0, 16), true);
- return false;
-}
-
-void TrkServer::handleAdapterMessage(const TrkResult &result)
-{
- QByteArray data;
- data.append(char(0x00)); // No error
- switch (result.code) {
- case 0x00: { // Ping
- m_notificationToken = 0;
- writeToAdapter(0x80, 0x00, data);
- break;
- }
- case 0x01: { // Connect
- writeToAdapter(0x80, result.token, data);
- break;
- }
- case 0x10: { // Read Memory
- const char *p = result.data.data();
- byte option = p[0];
- Q_UNUSED(option);
- const ushort len = extractShort(p + 1);
- const uint addr = extractInt(p + 3);;
- if (handleMemoryRequest(addr, len, option, &data)) {
- writeToAdapter(0x80, result.token, data);
- } else {
- data[0] = 32; // NAK, bad hair day
- writeToAdapter(0x80, result.token, data);
- }
- break;
- }
- case 0x12: { // Read Registers
- for (int i = 0; i < RegisterCount; ++i)
- appendInt(&data, m_inferior.registers[i], BigEndian);
- writeToAdapter(0x80, result.token, data);
- break;
- }
- case 0x18: { // Continue
- writeToAdapter(0x80, result.token, data); // ACK Package
-
- if (1) { // Fake "Stop"
- QByteArray note;
- appendInt(&note, 0); // FIXME: use proper address
- appendInt(&note, m_inferior.pid);
- appendInt(&note, m_inferior.tid);
- appendByte(&note, 0x00);
- appendByte(&note, 0x00);
- writeToAdapter(0x90, nextNotificationToken(), note);
- }
-
- break;
- }
- case 0x19: { // Step
- const char *p = result.data.data();
- //byte option = *p;
- uint startaddr = extractInt(p + 1);
- uint endaddr = extractInt(p + 5);
- uint pid = extractInt(p + 9);
- //uint tid = extractInt(p + 13);
- if (startaddr != m_inferior.registers[RegisterPC])
- logMessage("addr mismatch:" + hexNumber(startaddr) + " " +
- hexNumber(m_inferior.registers[RegisterPC]));
- if (pid != m_inferior.pid)
- logMessage("pid mismatch:" + hexNumber(pid) + " " +
- hexNumber(m_inferior.pid));
- writeToAdapter(0x80, result.token, data);
-
- // Fake "step"
- m_inferior.registers[RegisterPC] = endaddr;
-
- if (1) { // Fake "Stop"
- QByteArray note;
- appendInt(&note, 0); // FIXME: use proper address
- appendInt(&note, m_inferior.pid);
- appendInt(&note, m_inferior.tid);
- appendByte(&note, 0x00);
- appendByte(&note, 0x00);
- writeToAdapter(0x90, nextNotificationToken(), note);
- }
- break;
- }
- case 0x40: { // Create Item
- appendInt(&data, m_inferior.pid, BigEndian);
- appendInt(&data, m_inferior.tid, BigEndian);
- appendInt(&data, m_inferior.codeseg, BigEndian);
- appendInt(&data, m_inferior.dataseg, BigEndian);
- writeToAdapter(0x80, result.token, data);
- break;
- }
- case 0x41: { // Delete Item
- writeToAdapter(0x80, result.token, data);
- // A Process?
- // Command: 0xA1 Notify Deleted
- //[A1 02 00 00 00 00 00 00 00 00 01 B5]
- QByteArray note; // FIXME
- appendByte(&note, 0);
- appendByte(&note, 0);
- appendInt(&note, 0);
- appendInt(&note, m_inferior.pid);
- writeToAdapter(0xA1, nextNotificationToken(), note);
- break;
- }
- case 0x1B: { // Set Break
- static int breakpointNumber = 10; // Trk does that
- appendInt(&data, breakpointNumber++);
- writeToAdapter(0x80, result.token, data);
- break;
- }
- default: {
- data[0] = 0x10; // Command not supported
- writeToAdapter(0xff, result.token, data);
- break;
- }
- }
-}
-
-byte TrkServer::nextNotificationToken()
-{
- ++m_notificationToken;
- if (m_notificationToken == 0)
- ++m_notificationToken;
- return m_notificationToken;
-}
-
-static bool readTrkArgs(const QStringList &args, TrkOptions *o)
-{
- int argNumber = 0;
- const QStringList::const_iterator cend = args.constEnd();
- QStringList::const_iterator it = args.constBegin();
- for (++it; it != cend; ++it) {
- if (it->startsWith(QLatin1Char('-'))) {
- if (*it == QLatin1String("-v")) {
- o->verbose++;
- } else if (*it == QLatin1String("-q")) {
- o->verbose = 0;
- } else if (*it == QLatin1String("-f")) {
- o->serialFrame= false;
- }
-
- } else {
- switch (argNumber++) {
- case 0:
- o->serverName = *it;
- break;
- case 1:
- o->dumpName = *it;
- break;
- default:
- o->additionalDumps.push_back(*it);
- break;
- }
- }
- }
- return !o->dumpName.isEmpty();
-}
-
-int main(int argc, char *argv[])
-{
-#ifdef Q_OS_UNIX
- signal(SIGUSR1, signalHandler);
-#endif
-
- QCoreApplication app(argc, argv);
- TrkOptions options;
- if (!readTrkArgs(app.arguments(), &options)) {
- qWarning("Usage: %s [-v|-q] <trkservername> <replaysource> [additional dumps]\n"
- "Options: -v verbose\n"
- " -f Turn serial message frame off\n"
- " -q quiet\n"
- " Additional dump names must follow the naming convention '0x4AD.bin", argv[0]);
- return 1;
- }
-
- TrkServer server;
- server.setServerName(options.serverName);
- server.setMemoryDumpName(options.dumpName);
- server.setSerialFrame(options.serialFrame);
- foreach(const QString &ad, options.additionalDumps)
- if (!server.readDump(ad))
- return -1;
- server.setVerbose(options.verbose);
- if (!server.startServer())
- return -1;
-
- return app.exec();
-}
-
-#include "trkserver.moc"
diff --git a/tests/manual/trk/trkserver.pro b/tests/manual/trk/trkserver.pro
deleted file mode 100644
index 17f7c91741..0000000000
--- a/tests/manual/trk/trkserver.pro
+++ /dev/null
@@ -1,10 +0,0 @@
-
-TEMPLATE = app
-
-include(../../../src/shared/trk/trk.pri)
-
-QT = core network
-win32:CONFIG+=console
-
-SOURCES += \
- $$PWD/trkserver.cpp
diff --git a/tests/manual/trklauncher/main.cpp b/tests/manual/trklauncher/main.cpp
deleted file mode 100644
index eb699e3574..0000000000
--- a/tests/manual/trklauncher/main.cpp
+++ /dev/null
@@ -1,208 +0,0 @@
-#include "launcher.h"
-#include "communicationstarter.h"
-
-#include <QtCore/QCoreApplication>
-#include <QtCore/QSharedPointer>
-#include <QtCore/QDebug>
-#include <QtCore/QStringList>
-
-static const char usageC[] =
-"\n"
-"Usage: %1 [options] <trk_port_name>\n"
-" %1 [options] <trk_port_name> <remote_executable_name> [-- args]\n"
-" %1 [options] -i <trk_port_name> remote_sis_file\n"
-" %1 [options] -I local_sis_file remote_sis_file] [<remote_executable_name>] [-- args]\n"
-" %1 [options] -c local_file remote_file\n"
-" %1 [options] -C remote_file [local_file|-]\n"
-"\nOptions:\n -v verbose\n"
- " -q quiet\n"
- " -b Prompt for Bluetooth connect (Linux only)\n"
- " -f turn serial message frame off (Bluetooth)\n"
-"\nPing:\n"
-"%1 COM5\n"
-"\nRemote launch:\n"
-"%1 COM5 C:\\sys\\bin\\test.exe\n"
-"\nInstallation:\n"
-"%1 -i COM5 C:\\Data\\test_gcce_udeb.sisx\n"
-"\nInstallation and remote launch:\n"
-"%1 -i COM5 C:\\Data\\test_gcce_udeb.sisx C:\\sys\\bin\\test.exe\n"
-"\nCopy from local file, installation:\n"
-"%1 -I COM5 C:\\Projects\\test\\test_gcce_udeb.sisx C:\\Data\\test_gcce_udeb.sisx\n"
-"\nCopy from local file, installation and remote launch:\n"
-"%1 -I COM5 C:\\Projects\\test\\test_gcce_udeb.sisx C:\\Data\\test_gcce_udeb.sisx C:\\sys\\bin\\test.exe\n"
-"\nCopy from local file\n"
-"%1 -c COM5 c:\\foo.dat C:\\Data\\foo.dat\n"
-"\nCopy to local file\n"
-"%1 -C COM5 C:\\Data\\foo.dat c:\\foo.dat\n";
-
-static void usage()
-{
- const QString msg = QString::fromLatin1(usageC).arg(QCoreApplication::applicationName());
- qWarning("%s", qPrintable(msg));
-}
-
-typedef QSharedPointer<trk::Launcher> TrkLauncherPtr;
-
-// Parse arguments, return pointer or a null none.
-
-static inline TrkLauncherPtr createLauncher(trk::Launcher::Actions actions,
- const QString &serverName,
- bool serialFrame,
- int verbosity)
-{
- TrkLauncherPtr launcher(new trk::Launcher(actions));
- launcher->setTrkServerName(serverName);
- launcher->setSerialFrame(serialFrame);
- launcher->setVerbose(verbosity);
- return launcher;
-}
-
-static TrkLauncherPtr parseArguments(const QStringList &arguments, bool *bluetooth)
-{
- enum Mode { Ping, RemoteLaunch, Install, CustomInstall, Copy, Download };
- // Parse away options
- Mode mode = Ping;
- bool serialFrame = true;
- const int argCount = arguments.size();
- int verbosity = 1;
- *bluetooth = false;
- QStringList remoteArguments;
- trk::Launcher::Actions actions = trk::Launcher::ActionPingOnly;
- int a = 1;
- for ( ; a < argCount; a++) {
- const QString option = arguments.at(a);
- if (!option.startsWith(QLatin1Char('-')))
- break;
- if (option.size() != 2)
- return TrkLauncherPtr();
- switch (option.at(1).toAscii()) {
- case 'v':
- verbosity++;
- break;
- case 'q':
- verbosity = 0;
- break;
- case 'f':
- serialFrame = false;
- break;
- case 'b':
- *bluetooth = true;
- break;
- case 'i':
- mode = Install;
- actions = trk::Launcher::ActionInstall;
- break;
- case 'I':
- mode = CustomInstall;
- actions = trk::Launcher::ActionCopyInstall;
- break;
- case 'c':
- mode = Copy;
- actions = trk::Launcher::ActionCopy;
- break;
- case 'C':
- mode = Download;
- actions = trk::Launcher::ActionDownload;
- break;
- default:
- return TrkLauncherPtr();
- }
- }
- // Parse for '--' delimiter for remote executable argunment
- int pastArguments = a;
- for ( ; pastArguments < argCount && arguments.at(pastArguments) != QLatin1String("--"); pastArguments++) ;
- if (pastArguments != argCount)
- for (int ra = pastArguments + 1; ra < argCount; ra++)
- remoteArguments.push_back(arguments.at(ra));
- // Evaluate arguments
- const int remainingArgsCount = pastArguments -a ;
- // Ping and launch are only distinguishable by argument counts
- if (mode == Ping && remainingArgsCount > 1)
- mode = RemoteLaunch;
- switch (mode) {
- case Ping:
- if (remainingArgsCount == 1)
- return createLauncher(actions, arguments.at(a), serialFrame, verbosity);
- break;
- case RemoteLaunch:
- if (remainingArgsCount == 2) {
- // remote exec
- TrkLauncherPtr launcher = createLauncher(actions, arguments.at(a), serialFrame, verbosity);
- launcher->addStartupActions(trk::Launcher::ActionRun);
- launcher->setFileName(arguments.at(a + 1));
- launcher->setCommandLineArgs(remoteArguments);
- return launcher;
-
- }
- break;
- case Install:
- if (remainingArgsCount == 3 || remainingArgsCount == 2) {
- TrkLauncherPtr launcher = createLauncher(actions, arguments.at(a), serialFrame, verbosity);
- launcher->setInstallFileNames(QStringList() << arguments.at(a + 1));
- if (remainingArgsCount == 3) {
- launcher->addStartupActions(trk::Launcher::ActionRun);
- launcher->setFileName(arguments.at(a + 2));
- launcher->setCommandLineArgs(remoteArguments);
- }
- return launcher;
- }
- break;
- case CustomInstall:
- if (remainingArgsCount == 4 || remainingArgsCount == 3) {
- TrkLauncherPtr launcher = createLauncher(actions, arguments.at(a), serialFrame, verbosity);
- launcher->setCopyFileNames(QStringList() << arguments.at(a + 1), QStringList() << arguments.at(a + 2));
- launcher->setInstallFileNames(QStringList() << arguments.at(a + 2));
- if (remainingArgsCount == 4) {
- launcher->addStartupActions(trk::Launcher::ActionRun);
- launcher->setFileName(arguments.at(a + 3));
- launcher->setCommandLineArgs(remoteArguments);
- }
- return launcher;
- }
- break;
- case Copy:
- if (remainingArgsCount == 3) {
- TrkLauncherPtr launcher = createLauncher(actions, arguments.at(a), serialFrame, verbosity);
- launcher->setCopyFileNames(QStringList() << arguments.at(a + 1), QStringList() << arguments.at(a + 2));
- return launcher;
- }
- break;
- case Download:
- if (remainingArgsCount == 3) {
- TrkLauncherPtr launcher = createLauncher(actions, arguments.at(a), serialFrame, verbosity);
- launcher->setDownloadFileName(arguments.at(a + 1), arguments.at(a + 2));
- return launcher;
- }
- break;
- }
- return TrkLauncherPtr();
-}
-
-int main(int argc, char *argv[])
-{
- QCoreApplication app(argc, argv);
- QCoreApplication::setApplicationName(QLatin1String("trklauncher"));
- QCoreApplication::setOrganizationName(QLatin1String("Nokia"));
-
- bool bluetooth;
- const TrkLauncherPtr launcher = parseArguments(app.arguments(), &bluetooth);
- if (launcher.isNull()) {
- usage();
- return 1;
- }
- QObject::connect(launcher.data(), SIGNAL(finished()), &app, SLOT(quit()));
- QObject::connect(launcher.data(), SIGNAL(processStopped(uint,uint,uint,QString)),
- launcher.data(), SLOT(terminate()));
- // BLuetooth: Open with prompt
- QString errorMessage;
- if (bluetooth && !trk::ConsoleBluetoothStarter::startBluetooth(launcher->trkDevice(),
- launcher.data(),
- 30, &errorMessage)) {
- qWarning("%s\n", qPrintable(errorMessage));
- return -1;
- }
- if (launcher->startServer(&errorMessage))
- return app.exec();
- qWarning("%s\n", qPrintable(errorMessage));
- return 4;
-}
diff --git a/tests/tests.pro b/tests/tests.pro
index 465f192eca..78b78c8452 100644
--- a/tests/tests.pro
+++ b/tests/tests.pro
@@ -1,3 +1,2 @@
TEMPLATE=subdirs
-SUBDIRS += auto \
- manual
+SUBDIRS += auto manual tools
diff --git a/tests/manual/ccdb/README b/tests/tools/ccdb/README
index 56e3426f2f..56e3426f2f 100644
--- a/tests/manual/ccdb/README
+++ b/tests/tools/ccdb/README
diff --git a/tests/tools/ccdb/ccdb.pro b/tests/tools/ccdb/ccdb.pro
new file mode 100644
index 0000000000..fc6de24eb0
--- /dev/null
+++ b/tests/tools/ccdb/ccdb.pro
@@ -0,0 +1,32 @@
+# -------------------------------------------------
+# Project created by QtCreator 2010-01-22T10:11:10
+# -------------------------------------------------
+QT += core
+TARGET = ccdb
+CONFIG += console
+CONFIG -= app_bundle
+TEMPLATE = app
+
+DEFINES += TEST_COMPILE
+# -- Add CDB core engine
+CDB_CORE = ../../../src/plugins/debugger/cdb
+include($$CDB_CORE/cdbcore.pri)
+INCLUDEPATH *= $$CDB_CORE
+
+include(../../../qtcreator.pri)
+
+# -- Add creator 'utils' lib
+CREATOR_LIB_LIB = ../../../lib/qtcreator
+LIBS *= -L$$CREATOR_LIB_LIB
+LIBS *= -l$$qtLibraryName(Utils)
+CREATOR_LIB_SRC = ../../../src/libs
+INCLUDEPATH *= $$CREATOR_LIB_SRC
+
+# -- App sources
+SOURCES += main.cpp \
+ cdbapplication.cpp \
+ debugeventcallback.cpp \
+ cdbpromptthread.cpp
+HEADERS += cdbapplication.h \
+ debugeventcallback.h \
+ cdbpromptthread.h
diff --git a/tests/manual/ccdb/cdbapplication.cpp b/tests/tools/ccdb/cdbapplication.cpp
index b886652d7b..b886652d7b 100644
--- a/tests/manual/ccdb/cdbapplication.cpp
+++ b/tests/tools/ccdb/cdbapplication.cpp
diff --git a/tests/manual/ccdb/cdbapplication.h b/tests/tools/ccdb/cdbapplication.h
index df497a4ff0..df497a4ff0 100644
--- a/tests/manual/ccdb/cdbapplication.h
+++ b/tests/tools/ccdb/cdbapplication.h
diff --git a/tests/manual/ccdb/cdbpromptthread.cpp b/tests/tools/ccdb/cdbpromptthread.cpp
index 414c616166..414c616166 100644
--- a/tests/manual/ccdb/cdbpromptthread.cpp
+++ b/tests/tools/ccdb/cdbpromptthread.cpp
diff --git a/tests/manual/ccdb/cdbpromptthread.h b/tests/tools/ccdb/cdbpromptthread.h
index 78b323140a..78b323140a 100644
--- a/tests/manual/ccdb/cdbpromptthread.h
+++ b/tests/tools/ccdb/cdbpromptthread.h
diff --git a/tests/manual/ccdb/debugeventcallback.cpp b/tests/tools/ccdb/debugeventcallback.cpp
index 12ec1ba8d7..12ec1ba8d7 100644
--- a/tests/manual/ccdb/debugeventcallback.cpp
+++ b/tests/tools/ccdb/debugeventcallback.cpp
diff --git a/tests/manual/ccdb/debugeventcallback.h b/tests/tools/ccdb/debugeventcallback.h
index b28521c854..b28521c854 100644
--- a/tests/manual/ccdb/debugeventcallback.h
+++ b/tests/tools/ccdb/debugeventcallback.h
diff --git a/tests/tools/ccdb/main.cpp b/tests/tools/ccdb/main.cpp
new file mode 100644
index 0000000000..5c62b9f9e7
--- /dev/null
+++ b/tests/tools/ccdb/main.cpp
@@ -0,0 +1,49 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "cdbapplication.h"
+#include <QtCore/QString>
+
+int main(int argc, char *argv[])
+{
+ CdbApplication app(argc, argv);
+ int rc = 0;
+
+ switch (app.init()) {
+ case CdbApplication::InitOk:
+ rc = app.exec();
+ break;
+ case CdbApplication::InitFailed:
+ rc = 1;
+ break;
+ case CdbApplication::InitUsageShown:
+ break;
+ }
+ return rc;
+}
diff --git a/tests/tools/codaclient/codaclient.pro b/tests/tools/codaclient/codaclient.pro
new file mode 100644
index 0000000000..3c579b4342
--- /dev/null
+++ b/tests/tools/codaclient/codaclient.pro
@@ -0,0 +1,15 @@
+DEFINES += SYMBIANUTILS_INCLUDE_PRI
+
+include(../../../qtcreator.pri)
+include(../../../src/shared/symbianutils/symbianutils.pri)
+# include(../../../src/libs/3rdparty/qextserialport/qextserialport.pri)
+
+QT += core gui network
+TARGET = codaclient
+TEMPLATE = app
+CONFIG += console
+
+SOURCES += main.cpp \
+ codaclientapplication.cpp
+
+HEADERS += codaclientapplication.h
diff --git a/tests/tools/codaclient/codaclientapplication.cpp b/tests/tools/codaclient/codaclientapplication.cpp
new file mode 100644
index 0000000000..0091844022
--- /dev/null
+++ b/tests/tools/codaclient/codaclientapplication.cpp
@@ -0,0 +1,593 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 "codaclientapplication.h"
+
+#ifdef HAS_SERIALPORT
+# include <qextserialport/qextserialport.h>
+#endif
+
+#include "tcftrkdevice.h"
+#include <QtNetwork/QTcpSocket>
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+
+#include <cstdio>
+
+static const char usageC[] =
+"\n%1 v0.1 built "__DATE__"\n\n"
+"Test client for Symbian CODA\n\n"
+"Usage:\n"
+"%1 ping connection Note: For serial connections ONLY.\n"
+"%1 launch [-d] connection binary uid [--] [arguments]\n"
+"%1 install[-s] connection remote-sis-file [targetdrive]\n"
+"%1 put [c size] connection local-file remote-file\n"
+"%1 stat connection remote-file\n\n"
+"'connection': address[:port] or serial-port\n\n"
+"Options:\n"
+"-d Launch: Launch under Debug control (wait for termination)\n"
+"-c [size] Put: Chunk size in KB (default %2KB)\n"
+"-s Install: Silent installation\n\n"
+"Notes:\n"
+"UIDs take the form '0xfdaa278'. The target directory for sis-files on a\n"
+"device typically is 'c:\\data'. CODA's default port is %3.\n\n"
+"Example session:\n"
+"%1 put 192.168.0.42 test.sis c:\\data\\test.sis\n"
+"%1 stat 192.168.0.42 c:\\data\\test.sis\n"
+"%1 install 192.168.0.42 c:\\data\\test.sis c:\n"
+"%1 launch 192.168.0.42 c:\\sys\\bin\\test.exe 0x34f2b\n"
+"%1 ping /dev/ttyUSB1\n";
+
+static const unsigned short defaultPort = 65029;
+static const quint64 defaultChunkSize = 10240;
+
+static inline bool isSerialPort(const QString &address)
+{
+ return address.startsWith(QLatin1String("/dev"))
+ || address.startsWith(QLatin1String("com"), Qt::CaseInsensitive)
+ || address.startsWith(QLatin1String("tty"), Qt::CaseInsensitive)
+ || address.startsWith(QLatin1Char('\\'));
+}
+
+static inline QString fixSlashes(QString s)
+{
+ s.replace(QLatin1Char('/'), QLatin1Char('\\'));
+ return s;
+}
+
+CodaClientApplication::CodaClientApplication(int &argc, char **argv) :
+ QCoreApplication(argc, argv),
+ m_mode(Invalid),
+ m_port(defaultPort),
+ m_launchUID(0),
+ m_launchDebug(false),
+ m_installTargetDrive(QLatin1String("C:")),
+ m_installSilently(false),
+ m_putWriteOk(false),
+ m_statFstatOk(false),
+ m_putLastChunkSize(0),
+ m_putChunkSize(defaultChunkSize),
+ m_verbose(0)
+{
+ setApplicationName(QLatin1String("codaclient"));
+}
+
+CodaClientApplication::~CodaClientApplication()
+{
+}
+
+QString CodaClientApplication::usage()
+{
+ return QString::fromLatin1(usageC)
+ .arg(QCoreApplication::applicationName())
+ .arg(defaultChunkSize / 1024).arg(defaultPort);
+}
+
+static inline CodaClientApplication::Mode modeArg(const QString &a)
+{
+ if (a == QLatin1String("launch"))
+ return CodaClientApplication::Launch;
+ if (a == QLatin1String("ping"))
+ return CodaClientApplication::Ping;
+ if (a == QLatin1String("install"))
+ return CodaClientApplication::Install;
+ if (a == QLatin1String("put"))
+ return CodaClientApplication::Put;
+ if (a == QLatin1String("stat"))
+ return CodaClientApplication::Stat;
+ return CodaClientApplication::Invalid;
+}
+
+bool CodaClientApplication::parseArgument(const QString &a, int argNumber, QString *errorMessage)
+{
+ switch (argNumber) {
+ case 1:
+ m_mode = modeArg(a);
+ if (m_mode == Invalid) {
+ *errorMessage = QLatin1String("Invalid mode");
+ return false;
+ }
+ return true;
+ case 2: { // Address/port
+ m_address = a;
+ const int colonPos = m_address.indexOf(':');
+ if (colonPos != -1) {
+ m_port = m_address.mid(colonPos + 1).toUInt();
+ m_address.truncate(colonPos);
+ }
+ }
+ break;
+ case 3:
+ switch (m_mode) {
+ case Launch:
+ m_launchBinary = fixSlashes(a);
+ break;
+ case Install:
+ m_installSisFile = a;
+ break;
+ case Put:
+ m_putLocalFile = a;
+ break;
+ case Stat:
+ m_statRemoteFile = fixSlashes(a);
+ break;
+ default:
+ break;
+ }
+ return true;
+ case 4:
+ switch (m_mode) {
+ case Launch:
+ m_launchUID = a.toUInt(0, 0);
+ if (!m_launchUID) {
+ *errorMessage = QLatin1String("Invalid UID");
+ return false;
+ }
+ break;
+ case Install:
+ m_installTargetDrive = a;
+ break;
+ case Put:
+ m_putRemoteFile = fixSlashes(a);
+ break;
+ default:
+ break;
+ }
+ return true;
+
+ default:
+ if (m_mode == Launch)
+ m_launchArgs.push_back(a);
+ break;
+ }
+ return true;
+}
+
+CodaClientApplication::ParseArgsResult CodaClientApplication::parseArguments(QString *errorMessage)
+{
+ int argNumber = 1;
+ const QStringList args = QCoreApplication::arguments();
+ const QStringList::const_iterator cend = args.constEnd();
+ QStringList::const_iterator it = args.constBegin();
+ bool optionsEnd = false;
+ for (++it; it != cend; ++it) {
+ if (!optionsEnd && *it == QLatin1String("--")) {
+ optionsEnd = true;
+ continue;
+ }
+ if (!optionsEnd && it->startsWith(QLatin1Char('-')) && it->size() == 2) {
+ switch (it->at(1).toAscii()) {
+ case 'v':
+ m_verbose++;
+ break;
+ case 'd':
+ m_launchDebug = true;
+ break;
+ case 's':
+ m_installSilently = true;
+ break;
+ case 'c':
+ if (++it == cend) {
+ *errorMessage = QString::fromLatin1("Parameter missing for -c");
+ return ParseArgsError;
+ }
+ m_putChunkSize = it->toULongLong() * 1024;
+ if (!m_putChunkSize) {
+ *errorMessage = QString::fromLatin1("Invalid chunk size.");
+ return ParseArgsError;
+ }
+ break;
+ default:
+ *errorMessage = QString::fromLatin1("Invalid option %1").arg(*it);
+ return ParseArgsError;
+ }
+ } else {
+ if (!parseArgument(*it, argNumber++, errorMessage))
+ return ParseArgsError;
+ }
+ } //for loop
+ // Basic Check & init
+ switch (m_mode) {
+ case Invalid:
+ return ParseArgsError;
+ case Launch:
+ if (m_address.isEmpty() || !m_launchUID || m_launchBinary.isEmpty()) {
+ *errorMessage = QString::fromLatin1("Not enough parameters for launch.");
+ return ParseInitError;
+ }
+ break;
+ case Ping:
+ if (m_address.isEmpty()) {
+ *errorMessage = QString::fromLatin1("Not enough parameters for ping.");
+ return ParseInitError;
+ }
+ if (!isSerialPort(m_address)) {
+ *errorMessage = QString::fromLatin1("'ping' not supported for TCP/IP.");
+ return ParseInitError;
+ }
+ break;
+ case Install:
+ if (m_address.isEmpty() || m_installSisFile.isEmpty()) {
+ *errorMessage = QString::fromLatin1("Not enough parameters for install.");
+ return ParseInitError;
+ }
+ break;
+ case Put: {
+ if (m_address.isEmpty() || m_putLocalFile.isEmpty() || m_putRemoteFile.isEmpty()) {
+ *errorMessage = QString::fromLatin1("Not enough parameters for put.");
+ return ParseInitError;
+ }
+ const QFileInfo fi(m_putLocalFile);
+ if (!fi.isFile() || !fi.isReadable()) {
+ *errorMessage = QString::fromLatin1("Local file '%1' not readable.").arg(m_putLocalFile);
+ return ParseInitError;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ return ParseArgsOk;
+}
+
+bool CodaClientApplication::start()
+{
+ m_startTime.start();
+ switch (m_mode) {
+ case Ping:
+ break;
+ case Launch: {
+ const QString args = m_launchArgs.join(QString(QLatin1Char(' ')));
+ std::printf("Launching 0x%x '%s '%s' (debug: %d)\n",
+ m_launchUID, qPrintable(m_launchBinary),
+ qPrintable(args), m_launchDebug);
+ }
+ break;
+ case Install:
+ std::printf("Installing '%s' to '%s'\n",
+ qPrintable(m_installSisFile), qPrintable(m_installTargetDrive));
+ break;
+ case Put:
+ std::printf("Copying '%s' to '%s' in chunks of %lluKB\n",
+ qPrintable(m_putLocalFile), qPrintable(m_putRemoteFile),
+ m_putChunkSize / 1024);
+ break;
+ case Stat:
+ std::printf("Retrieving attributes of '%s'\n", qPrintable(m_statRemoteFile));
+ break;
+ case Invalid:
+ break;
+ }
+ // Start connection
+ m_trkDevice.reset(new tcftrk::TcfTrkDevice);
+ m_trkDevice->setVerbose(m_verbose);
+ connect(m_trkDevice.data(), SIGNAL(error(QString)),
+ this, SLOT(slotError(QString)));
+ connect(m_trkDevice.data(), SIGNAL(logMessage(QString)),
+ this, SLOT(slotTrkLogMessage(QString)));
+ connect(m_trkDevice.data(), SIGNAL(tcfEvent(tcftrk::TcfTrkEvent)),
+ this, SLOT(slotTcftrkEvent(tcftrk::TcfTrkEvent)));
+ connect(m_trkDevice.data(), SIGNAL(serialPong(QString)),
+ this, SLOT(slotSerialPong(QString)));
+ if (isSerialPort(m_address)) {
+#ifdef HAS_SERIALPORT
+ // Serial
+#ifdef Q_OS_WIN
+ const QString fullPort = QextSerialPort::fullPortNameWin(m_address);
+#else
+ const QString fullPort = m_address;
+#endif
+ const QSharedPointer<QextSerialPort>
+ serialPort(new QextSerialPort(fullPort, QextSerialPort::EventDriven));
+ std::printf("Opening port %s...\n", qPrintable(fullPort));
+
+ // Magic USB serial parameters
+ serialPort->setTimeout(2000);
+ serialPort->setBaudRate(BAUD115200);
+ serialPort->setFlowControl(FLOW_OFF);
+ serialPort->setParity(PAR_NONE);
+ serialPort->setDataBits(DATA_8);
+ serialPort->setStopBits(STOP_1);
+
+ m_trkDevice->setSerialFrame(true);
+ m_trkDevice->setDevice(serialPort); // Grab all data from start
+ if (!serialPort->open(QIODevice::ReadWrite|QIODevice::Unbuffered)) {
+ std::fprintf(stderr, "Cannot open port: %s", qPrintable(serialPort->errorString()));
+ return false;
+ }
+ // Initiate communication
+ m_trkDevice->sendSerialPing(m_mode == Ping);
+ serialPort->flush();
+#else
+ std::fprintf(stderr, "Not implemented\n");
+ return false;
+#endif
+ } else {
+ // TCP/IP
+ const QSharedPointer<QTcpSocket> tcfTrkSocket(new QTcpSocket);
+ m_trkDevice->setDevice(tcfTrkSocket);
+ tcfTrkSocket->connectToHost(m_address, m_port);
+ std::printf("Connecting to %s:%hu...\n", qPrintable(m_address), m_port);
+ }
+ return true;
+}
+
+void CodaClientApplication::slotError(const QString &e)
+{
+ std::fprintf(stderr, "Error: %s\n", qPrintable(e));
+ doExit(-1);
+}
+
+void CodaClientApplication::slotTrkLogMessage(const QString &m)
+{
+ printTimeStamp();
+ std::printf("%s\n", qPrintable(m));
+}
+
+void CodaClientApplication::handleCreateProcess(const tcftrk::TcfTrkCommandResult &result)
+{
+ const bool ok = result.type == tcftrk::TcfTrkCommandResult::SuccessReply;
+ if (ok) {
+ printTimeStamp();
+ std::printf("Launch succeeded: %s\n", qPrintable(result.toString()));
+ if (!m_launchDebug)
+ doExit(0);
+ } else {
+ std::fprintf(stderr, "Launch failed: %s\n", qPrintable(result.toString()));
+ doExit(-1);
+ }
+}
+
+void CodaClientApplication::handleFileSystemOpen(const tcftrk::TcfTrkCommandResult &result)
+{
+ if (result.type != tcftrk::TcfTrkCommandResult::SuccessReply) {
+ std::fprintf(stderr, "Open remote file failed: %s\n", qPrintable(result.toString()));
+ doExit(-1);
+ return;
+ }
+
+ if (result.values.size() < 1 || result.values.at(0).data().isEmpty()) {
+ std::fprintf(stderr, "Internal error: No filehandle obtained\n");
+ doExit(-1);
+ return;
+ }
+
+ m_remoteFileHandle = result.values.at(0).data();
+
+ if (m_mode == Stat) {
+ m_trkDevice->sendFileSystemFstatCommand(tcftrk::TcfTrkCallback(this, &CodaClientApplication::handleFileSystemFStat),
+ m_remoteFileHandle);
+ return;
+ }
+ // Put.
+ m_putFile.reset(new QFile(m_putLocalFile));
+ if (!m_putFile->open(QIODevice::ReadOnly)) { // Should not fail, was checked before
+ std::fprintf(stderr, "Open local file failed: %s\n", qPrintable(m_putFile->errorString()));
+ doExit(-1);
+ return;
+ }
+ putSendNextChunk();
+}
+
+void CodaClientApplication::putSendNextChunk()
+{
+ // Read and send off next chunk
+ const quint64 pos = m_putFile->pos();
+ const QByteArray data = m_putFile->read(m_putChunkSize);
+ if (data.isEmpty()) {
+ m_putWriteOk = true;
+ closeRemoteFile();
+ } else {
+ m_putLastChunkSize = data.size();
+ printTimeStamp();
+ std::printf("Writing %llu bytes to remote file '%s' at %llu\n",
+ m_putLastChunkSize,
+ m_remoteFileHandle.constData(), pos);
+ m_trkDevice->sendFileSystemWriteCommand(tcftrk::TcfTrkCallback(this, &CodaClientApplication::handleFileSystemWrite),
+ m_remoteFileHandle, data, unsigned(pos));
+ }
+}
+
+void CodaClientApplication::closeRemoteFile()
+{
+ m_trkDevice->sendFileSystemCloseCommand(tcftrk::TcfTrkCallback(this, &CodaClientApplication::handleFileSystemClose),
+ m_remoteFileHandle);
+}
+
+void CodaClientApplication::handleFileSystemWrite(const tcftrk::TcfTrkCommandResult &result)
+{
+ // Close remote file even if copy fails
+ m_putWriteOk = result;
+ if (!m_putWriteOk)
+ std::fprintf(stderr, "Writing data failed: %s\n", qPrintable(result.toString()));
+ if (!m_putWriteOk || m_putLastChunkSize < m_putChunkSize) {
+ closeRemoteFile();
+ } else {
+ putSendNextChunk();
+ }
+}
+
+void CodaClientApplication::handleFileSystemFStat(const tcftrk::TcfTrkCommandResult &result)
+{
+ m_statFstatOk = result.type == tcftrk::TcfTrkCommandResult::SuccessReply;
+ // Close remote file even if copy fails
+ if (m_statFstatOk) {
+ const tcftrk::TcfTrkStatResponse statr = tcftrk::TcfTrkDevice::parseStat(result);
+ printTimeStamp();
+ std::printf("File: %s\nSize: %llu bytes\nAccessed: %s\nModified: %s\n",
+ qPrintable(m_statRemoteFile), statr.size,
+ qPrintable(statr.accessTime.toString(Qt::LocalDate)),
+ qPrintable(statr.modTime.toString(Qt::LocalDate)));
+ } else {
+ std::fprintf(stderr, "FStat failed: %s\n", qPrintable(result.toString()));
+ }
+ closeRemoteFile();
+}
+
+void CodaClientApplication::handleFileSystemClose(const tcftrk::TcfTrkCommandResult &result)
+{
+ if (result.type == tcftrk::TcfTrkCommandResult::SuccessReply) {
+ printTimeStamp();
+ std::printf("File closed.\n");
+ const bool ok = m_mode == Put ? m_putWriteOk : m_statFstatOk;
+ doExit(ok ? 0 : -1);
+ } else {
+ std::fprintf(stderr, "File close failed: %s\n", qPrintable(result.toString()));
+ doExit(-1);
+ }
+}
+
+void CodaClientApplication::handleSymbianInstall(const tcftrk::TcfTrkCommandResult &result)
+{
+ if (result.type == tcftrk::TcfTrkCommandResult::SuccessReply) {
+ printTimeStamp();
+ std::printf("Installation succeeded\n.");
+ doExit(0);
+ } else {
+ std::fprintf(stderr, "Installation failed: %s\n", qPrintable(result.toString()));
+ doExit(-1);
+ }
+}
+
+void CodaClientApplication::slotTcftrkEvent (const tcftrk::TcfTrkEvent &ev)
+{
+ printTimeStamp();
+ std::printf("Event: %s\n", qPrintable(ev.toString()));
+ switch (ev.type()) {
+ case tcftrk::TcfTrkEvent::LocatorHello: // Commands accepted now
+ switch (m_mode) {
+ case Ping:
+ break;
+ case Launch:
+ m_trkDevice->sendProcessStartCommand(tcftrk::TcfTrkCallback(this, &CodaClientApplication::handleCreateProcess),
+ m_launchBinary, m_launchUID, m_launchArgs, QString(), m_launchDebug);
+ break;
+ case Install:
+ if (m_installSilently) {
+ m_trkDevice->sendSymbianInstallSilentInstallCommand(tcftrk::TcfTrkCallback(this, &CodaClientApplication::handleSymbianInstall),
+ m_installSisFile.toAscii(), m_installTargetDrive.toAscii());
+ } else {
+ m_trkDevice->sendSymbianInstallUIInstallCommand(tcftrk::TcfTrkCallback(this, &CodaClientApplication::handleSymbianInstall),
+ m_installSisFile.toAscii());
+ }
+ break;
+ case Put: {
+ const unsigned flags =
+ tcftrk::TcfTrkDevice::FileSystem_TCF_O_WRITE
+ |tcftrk::TcfTrkDevice::FileSystem_TCF_O_CREAT
+ |tcftrk::TcfTrkDevice::FileSystem_TCF_O_TRUNC;
+ m_putWriteOk = false;
+ m_trkDevice->sendFileSystemOpenCommand(tcftrk::TcfTrkCallback(this, &CodaClientApplication::handleFileSystemOpen),
+ m_putRemoteFile.toAscii(), flags);
+}
+ break;
+ case Stat: {
+ const unsigned flags = tcftrk::TcfTrkDevice::FileSystem_TCF_O_READ;
+ m_statFstatOk = false;
+ m_trkDevice->sendFileSystemOpenCommand(tcftrk::TcfTrkCallback(this, &CodaClientApplication::handleFileSystemOpen),
+ m_statRemoteFile.toAscii(), flags);
+}
+ break;
+ case Invalid:
+ break;
+ }
+ break;
+ case tcftrk::TcfTrkEvent::RunControlModuleLoadSuspended: {
+ // Debug mode start: Continue:
+ const tcftrk::TcfTrkRunControlModuleLoadContextSuspendedEvent &me =
+ static_cast<const tcftrk::TcfTrkRunControlModuleLoadContextSuspendedEvent &>(ev);
+ if (me.info().requireResume) {
+ printTimeStamp();
+ std::printf("Continuing...\n");
+ m_trkDevice->sendRunControlResumeCommand(tcftrk::TcfTrkCallback(), me.id());
+ }
+ }
+ break;
+ case tcftrk::TcfTrkEvent::RunControlContextRemoved: // App terminated in debug mode
+ doExit(0);
+ break;
+ default:
+ break;
+ }
+}
+
+void CodaClientApplication::slotSerialPong(const QString &v)
+{
+ printTimeStamp();
+ std::printf("Pong from '%s'\n", qPrintable(v));
+ if (m_mode == Ping)
+ doExit(0);
+}
+
+void CodaClientApplication::doExit(int ex)
+{
+ if (!m_trkDevice.isNull()) {
+ const QSharedPointer<QIODevice> dev = m_trkDevice->device();
+ if (!dev.isNull()) {
+ if (QAbstractSocket *socket = qobject_cast<QAbstractSocket *>(dev.data())) {
+ if (socket->state() == QAbstractSocket::ConnectedState)
+ socket->disconnectFromHost();
+ } else {
+ if (dev->isOpen())
+ dev->close();
+ }
+ }
+ }
+ printTimeStamp();
+ std::printf("Exiting (%d)\n", ex);
+ exit(ex);
+}
+
+void CodaClientApplication::printTimeStamp()
+{
+ const int elapsedMS = m_startTime.elapsed();
+ const int secs = elapsedMS / 1000;
+ const int msecs = elapsedMS % 1000;
+ std::printf("%4d.%03ds: ", secs, msecs);
+}
diff --git a/tests/tools/codaclient/codaclientapplication.h b/tests/tools/codaclient/codaclientapplication.h
new file mode 100644
index 0000000000..5837efdbeb
--- /dev/null
+++ b/tests/tools/codaclient/codaclientapplication.h
@@ -0,0 +1,105 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.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 CODACLIENTAPPLICATION_H
+#define CODACLIENTAPPLICATION_H
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QStringList>
+#include <QtCore/QSharedPointer>
+#include <QtCore/QTime>
+
+QT_FORWARD_DECLARE_CLASS(QFile)
+
+namespace tcftrk {
+ struct TcfTrkCommandResult;
+ class TcfTrkDevice;
+ class TcfTrkEvent;
+}
+
+class CodaClientApplication : public QCoreApplication
+{
+ Q_OBJECT
+public:
+ enum Mode { Invalid, Ping, Launch, Put, Stat, Install };
+
+ explicit CodaClientApplication(int &argc, char **argv);
+ ~CodaClientApplication();
+
+ enum ParseArgsResult { ParseArgsOk, ParseArgsError, ParseInitError, ParseArgsHelp };
+ ParseArgsResult parseArguments(QString *errorMessage);
+
+ bool start();
+
+ static QString usage();
+
+private slots:
+ void slotError(const QString &);
+ void slotTrkLogMessage(const QString &);
+ void slotTcftrkEvent(const tcftrk::TcfTrkEvent &);
+ void slotSerialPong(const QString &);
+
+private:
+ void printTimeStamp();
+ bool parseArgument(const QString &a, int argNumber, QString *errorMessage);
+ void handleCreateProcess(const tcftrk::TcfTrkCommandResult &result);
+ void handleFileSystemOpen(const tcftrk::TcfTrkCommandResult &result);
+ void handleFileSystemWrite(const tcftrk::TcfTrkCommandResult &result);
+ void handleFileSystemClose(const tcftrk::TcfTrkCommandResult &result);
+ void handleFileSystemFStat(const tcftrk::TcfTrkCommandResult &result);
+ void handleSymbianInstall(const tcftrk::TcfTrkCommandResult &result);
+ void doExit(int ex);
+ void putSendNextChunk();
+ void closeRemoteFile();
+
+ Mode m_mode;
+ QString m_address;
+ unsigned short m_port;
+ QString m_launchBinary;
+ QStringList m_launchArgs;
+ unsigned m_launchUID;
+ bool m_launchDebug;
+ QString m_installSisFile;
+ QString m_installTargetDrive;
+ bool m_installSilently;
+ QString m_putLocalFile;
+ QString m_putRemoteFile;
+ bool m_putWriteOk;
+ bool m_statFstatOk;
+ QScopedPointer<QFile> m_putFile;
+ quint64 m_putLastChunkSize;
+ QString m_statRemoteFile;
+ QByteArray m_remoteFileHandle;
+ quint64 m_putChunkSize;
+ unsigned m_verbose;
+ QTime m_startTime;
+ QScopedPointer<tcftrk::TcfTrkDevice> m_trkDevice;
+};
+
+#endif // CODACLIENTAPPLICATION_H
diff --git a/tests/tools/codaclient/main.cpp b/tests/tools/codaclient/main.cpp
new file mode 100644
index 0000000000..f6a9821bc7
--- /dev/null
+++ b/tests/tools/codaclient/main.cpp
@@ -0,0 +1,59 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** No Commercial Usage
+**
+** This file 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.
+**
+**************************************************************************/
+
+#include "codaclientapplication.h"
+
+#include <cstdio>
+
+int main(int argc, char *argv[])
+{
+ CodaClientApplication app(argc, argv);
+
+ QString errorMessage;
+ const CodaClientApplication::ParseArgsResult ar = app.parseArguments(&errorMessage);
+ if (!errorMessage.isEmpty())
+ std::fprintf(stderr, "\nError: %s\n\n", qPrintable(errorMessage));
+ switch (ar) {
+ case CodaClientApplication::ParseArgsError:
+ std::printf("%s", qPrintable(CodaClientApplication::usage()));
+ return -1;
+ case CodaClientApplication::ParseArgsHelp:
+ std::printf("%s", qPrintable(CodaClientApplication::usage()));
+ return 0;
+ case CodaClientApplication::ParseInitError:
+ return -1;
+ case CodaClientApplication::ParseArgsOk:
+ break;
+ }
+ return app.start() ? app.exec() : 0;
+}
diff --git a/tests/manual/cplusplus-dump/c++ b/tests/tools/cplusplus-dump/c++
index a5908b79ff..a5908b79ff 100755
--- a/tests/manual/cplusplus-dump/c++
+++ b/tests/tools/cplusplus-dump/c++
diff --git a/tests/manual/cplusplus-dump/conf.c++ b/tests/tools/cplusplus-dump/conf.c++
index 69bafe0459..69bafe0459 100644
--- a/tests/manual/cplusplus-dump/conf.c++
+++ b/tests/tools/cplusplus-dump/conf.c++
diff --git a/tests/tools/cplusplus-dump/cplusplus-dump.pro b/tests/tools/cplusplus-dump/cplusplus-dump.pro
new file mode 100644
index 0000000000..cd6525119e
--- /dev/null
+++ b/tests/tools/cplusplus-dump/cplusplus-dump.pro
@@ -0,0 +1,20 @@
+QT = core gui
+macx:CONFIG -= app_bundle
+TARGET = cplusplus0
+
+include(../../../qtcreator.pri)
+include(../../../src/libs/cplusplus/cplusplus.pri)
+
+# Input
+SOURCES += main.cpp
+
+unix {
+ debug:OBJECTS_DIR = $${OUT_PWD}/.obj/debug-shared
+ release:OBJECTS_DIR = $${OUT_PWD}/.obj/release-shared
+
+ debug:MOC_DIR = $${OUT_PWD}/.moc/debug-shared
+ release:MOC_DIR = $${OUT_PWD}/.moc/release-shared
+
+ RCC_DIR = $${OUT_PWD}/.rcc/
+ UI_DIR = $${OUT_PWD}/.uic/
+}
diff --git a/tests/tools/cplusplus-dump/dumpers.inc b/tests/tools/cplusplus-dump/dumpers.inc
new file mode 100644
index 0000000000..ec49d7aced
--- /dev/null
+++ b/tests/tools/cplusplus-dump/dumpers.inc
@@ -0,0 +1,1621 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** No Commercial Usage
+**
+** This file 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.
+**
+**************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is automatically generated.
+// Changes will be lost.
+//
+
+
+virtual bool visit(ObjCSelectorArgumentAST *ast)
+{
+ if (ast->name_token)
+ terminal(ast->name_token, ast);
+ if (ast->colon_token)
+ terminal(ast->colon_token, ast);
+ return false;
+}
+
+virtual bool visit(ObjCSelectorAST *ast)
+{
+ for (ObjCSelectorArgumentListAST *iter = ast->selector_argument_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ return false;
+}
+
+virtual bool visit(SimpleSpecifierAST *ast)
+{
+ if (ast->specifier_token)
+ terminal(ast->specifier_token, ast);
+ return false;
+}
+
+virtual bool visit(AttributeSpecifierAST *ast)
+{
+ if (ast->attribute_token)
+ terminal(ast->attribute_token, ast);
+ if (ast->first_lparen_token)
+ terminal(ast->first_lparen_token, ast);
+ if (ast->second_lparen_token)
+ terminal(ast->second_lparen_token, ast);
+ for (AttributeListAST *iter = ast->attribute_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->first_rparen_token)
+ terminal(ast->first_rparen_token, ast);
+ if (ast->second_rparen_token)
+ terminal(ast->second_rparen_token, ast);
+ return false;
+}
+
+virtual bool visit(AttributeAST *ast)
+{
+ if (ast->identifier_token)
+ terminal(ast->identifier_token, ast);
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ if (ast->tag_token)
+ terminal(ast->tag_token, ast);
+ for (ExpressionListAST *iter = ast->expression_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ return false;
+}
+
+virtual bool visit(TypeofSpecifierAST *ast)
+{
+ if (ast->typeof_token)
+ terminal(ast->typeof_token, ast);
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ nonterminal(ast->expression);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ return false;
+}
+
+virtual bool visit(DeclaratorAST *ast)
+{
+ for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ for (PtrOperatorListAST *iter = ast->ptr_operator_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ nonterminal(ast->core_declarator);
+ for (PostfixDeclaratorListAST *iter = ast->postfix_declarator_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ for (SpecifierListAST *iter = ast->post_attribute_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->equal_token)
+ terminal(ast->equal_token, ast);
+ nonterminal(ast->initializer);
+ return false;
+}
+
+virtual bool visit(SimpleDeclarationAST *ast)
+{
+ if (ast->qt_invokable_token)
+ terminal(ast->qt_invokable_token, ast);
+ for (SpecifierListAST *iter = ast->decl_specifier_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ for (DeclaratorListAST *iter = ast->declarator_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->semicolon_token)
+ terminal(ast->semicolon_token, ast);
+ return false;
+}
+
+virtual bool visit(EmptyDeclarationAST *ast)
+{
+ if (ast->semicolon_token)
+ terminal(ast->semicolon_token, ast);
+ return false;
+}
+
+virtual bool visit(AccessDeclarationAST *ast)
+{
+ if (ast->access_specifier_token)
+ terminal(ast->access_specifier_token, ast);
+ if (ast->slots_token)
+ terminal(ast->slots_token, ast);
+ if (ast->colon_token)
+ terminal(ast->colon_token, ast);
+ return false;
+}
+
+virtual bool visit(QtObjectTagAST *ast)
+{
+ if (ast->q_object_token)
+ terminal(ast->q_object_token, ast);
+ return false;
+}
+
+virtual bool visit(QtPrivateSlotAST *ast)
+{
+ if (ast->q_private_slot_token)
+ terminal(ast->q_private_slot_token, ast);
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ if (ast->dptr_token)
+ terminal(ast->dptr_token, ast);
+ if (ast->dptr_lparen_token)
+ terminal(ast->dptr_lparen_token, ast);
+ if (ast->dptr_rparen_token)
+ terminal(ast->dptr_rparen_token, ast);
+ if (ast->comma_token)
+ terminal(ast->comma_token, ast);
+ for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ nonterminal(ast->declarator);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ return false;
+}
+
+virtual bool visit(QtPropertyDeclarationItemAST *ast)
+{
+ if (ast->item_name_token)
+ terminal(ast->item_name_token, ast);
+ nonterminal(ast->expression);
+ return false;
+}
+
+virtual bool visit(QtPropertyDeclarationAST *ast)
+{
+ if (ast->property_specifier_token)
+ terminal(ast->property_specifier_token, ast);
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ nonterminal(ast->type_id);
+ nonterminal(ast->property_name);
+ for (QtPropertyDeclarationItemListAST *iter = ast->property_declaration_item_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ return false;
+}
+
+virtual bool visit(QtEnumDeclarationAST *ast)
+{
+ if (ast->enum_specifier_token)
+ terminal(ast->enum_specifier_token, ast);
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ for (NameListAST *iter = ast->enumerator_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ return false;
+}
+
+virtual bool visit(QtFlagsDeclarationAST *ast)
+{
+ if (ast->flags_specifier_token)
+ terminal(ast->flags_specifier_token, ast);
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ for (NameListAST *iter = ast->flag_enums_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ return false;
+}
+
+virtual bool visit(QtInterfaceNameAST *ast)
+{
+ nonterminal(ast->interface_name);
+ for (NameListAST *iter = ast->constraint_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ return false;
+}
+
+virtual bool visit(QtInterfacesDeclarationAST *ast)
+{
+ if (ast->interfaces_token)
+ terminal(ast->interfaces_token, ast);
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ for (QtInterfaceNameListAST *iter = ast->interface_name_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ return false;
+}
+
+virtual bool visit(AsmDefinitionAST *ast)
+{
+ if (ast->asm_token)
+ terminal(ast->asm_token, ast);
+ if (ast->volatile_token)
+ terminal(ast->volatile_token, ast);
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ if (ast->semicolon_token)
+ terminal(ast->semicolon_token, ast);
+ return false;
+}
+
+virtual bool visit(BaseSpecifierAST *ast)
+{
+ if (ast->virtual_token)
+ terminal(ast->virtual_token, ast);
+ if (ast->access_specifier_token)
+ terminal(ast->access_specifier_token, ast);
+ nonterminal(ast->name);
+ return false;
+}
+
+virtual bool visit(IdExpressionAST *ast)
+{
+ nonterminal(ast->name);
+ return false;
+}
+
+virtual bool visit(CompoundExpressionAST *ast)
+{
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ nonterminal(ast->statement);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ return false;
+}
+
+virtual bool visit(CompoundLiteralAST *ast)
+{
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ nonterminal(ast->type_id);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ nonterminal(ast->initializer);
+ return false;
+}
+
+virtual bool visit(QtMethodAST *ast)
+{
+ if (ast->method_token)
+ terminal(ast->method_token, ast);
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ nonterminal(ast->declarator);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ return false;
+}
+
+virtual bool visit(QtMemberDeclarationAST *ast)
+{
+ if (ast->q_token)
+ terminal(ast->q_token, ast);
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ nonterminal(ast->type_id);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ return false;
+}
+
+virtual bool visit(BinaryExpressionAST *ast)
+{
+ nonterminal(ast->left_expression);
+ if (ast->binary_op_token)
+ terminal(ast->binary_op_token, ast);
+ nonterminal(ast->right_expression);
+ return false;
+}
+
+virtual bool visit(CastExpressionAST *ast)
+{
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ nonterminal(ast->type_id);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ nonterminal(ast->expression);
+ return false;
+}
+
+virtual bool visit(ClassSpecifierAST *ast)
+{
+ if (ast->classkey_token)
+ terminal(ast->classkey_token, ast);
+ for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ nonterminal(ast->name);
+ if (ast->colon_token)
+ terminal(ast->colon_token, ast);
+ for (BaseSpecifierListAST *iter = ast->base_clause_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->dot_dot_dot_token)
+ terminal(ast->dot_dot_dot_token, ast);
+ if (ast->lbrace_token)
+ terminal(ast->lbrace_token, ast);
+ for (DeclarationListAST *iter = ast->member_specifier_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->rbrace_token)
+ terminal(ast->rbrace_token, ast);
+ return false;
+}
+
+virtual bool visit(CaseStatementAST *ast)
+{
+ if (ast->case_token)
+ terminal(ast->case_token, ast);
+ nonterminal(ast->expression);
+ if (ast->colon_token)
+ terminal(ast->colon_token, ast);
+ nonterminal(ast->statement);
+ return false;
+}
+
+virtual bool visit(CompoundStatementAST *ast)
+{
+ if (ast->lbrace_token)
+ terminal(ast->lbrace_token, ast);
+ for (StatementListAST *iter = ast->statement_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->rbrace_token)
+ terminal(ast->rbrace_token, ast);
+ return false;
+}
+
+virtual bool visit(ConditionAST *ast)
+{
+ for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ nonterminal(ast->declarator);
+ return false;
+}
+
+virtual bool visit(ConditionalExpressionAST *ast)
+{
+ nonterminal(ast->condition);
+ if (ast->question_token)
+ terminal(ast->question_token, ast);
+ nonterminal(ast->left_expression);
+ if (ast->colon_token)
+ terminal(ast->colon_token, ast);
+ nonterminal(ast->right_expression);
+ return false;
+}
+
+virtual bool visit(CppCastExpressionAST *ast)
+{
+ if (ast->cast_token)
+ terminal(ast->cast_token, ast);
+ if (ast->less_token)
+ terminal(ast->less_token, ast);
+ nonterminal(ast->type_id);
+ if (ast->greater_token)
+ terminal(ast->greater_token, ast);
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ nonterminal(ast->expression);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ return false;
+}
+
+virtual bool visit(CtorInitializerAST *ast)
+{
+ if (ast->colon_token)
+ terminal(ast->colon_token, ast);
+ for (MemInitializerListAST *iter = ast->member_initializer_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->dot_dot_dot_token)
+ terminal(ast->dot_dot_dot_token, ast);
+ return false;
+}
+
+virtual bool visit(DeclarationStatementAST *ast)
+{
+ nonterminal(ast->declaration);
+ return false;
+}
+
+virtual bool visit(DeclaratorIdAST *ast)
+{
+ if (ast->dot_dot_dot_token)
+ terminal(ast->dot_dot_dot_token, ast);
+ nonterminal(ast->name);
+ return false;
+}
+
+virtual bool visit(NestedDeclaratorAST *ast)
+{
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ nonterminal(ast->declarator);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ return false;
+}
+
+virtual bool visit(FunctionDeclaratorAST *ast)
+{
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ nonterminal(ast->parameter_declaration_clause);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ for (SpecifierListAST *iter = ast->cv_qualifier_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ nonterminal(ast->exception_specification);
+ nonterminal(ast->trailing_return_type);
+ nonterminal(ast->as_cpp_initializer);
+ return false;
+}
+
+virtual bool visit(ArrayDeclaratorAST *ast)
+{
+ if (ast->lbracket_token)
+ terminal(ast->lbracket_token, ast);
+ nonterminal(ast->expression);
+ if (ast->rbracket_token)
+ terminal(ast->rbracket_token, ast);
+ return false;
+}
+
+virtual bool visit(DeleteExpressionAST *ast)
+{
+ if (ast->scope_token)
+ terminal(ast->scope_token, ast);
+ if (ast->delete_token)
+ terminal(ast->delete_token, ast);
+ if (ast->lbracket_token)
+ terminal(ast->lbracket_token, ast);
+ if (ast->rbracket_token)
+ terminal(ast->rbracket_token, ast);
+ nonterminal(ast->expression);
+ return false;
+}
+
+virtual bool visit(DoStatementAST *ast)
+{
+ if (ast->do_token)
+ terminal(ast->do_token, ast);
+ nonterminal(ast->statement);
+ if (ast->while_token)
+ terminal(ast->while_token, ast);
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ nonterminal(ast->expression);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ if (ast->semicolon_token)
+ terminal(ast->semicolon_token, ast);
+ return false;
+}
+
+virtual bool visit(NamedTypeSpecifierAST *ast)
+{
+ nonterminal(ast->name);
+ return false;
+}
+
+virtual bool visit(ElaboratedTypeSpecifierAST *ast)
+{
+ if (ast->classkey_token)
+ terminal(ast->classkey_token, ast);
+ for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ nonterminal(ast->name);
+ return false;
+}
+
+virtual bool visit(EnumSpecifierAST *ast)
+{
+ if (ast->enum_token)
+ terminal(ast->enum_token, ast);
+ nonterminal(ast->name);
+ if (ast->lbrace_token)
+ terminal(ast->lbrace_token, ast);
+ for (EnumeratorListAST *iter = ast->enumerator_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->stray_comma_token)
+ terminal(ast->stray_comma_token, ast);
+ if (ast->rbrace_token)
+ terminal(ast->rbrace_token, ast);
+ return false;
+}
+
+virtual bool visit(EnumeratorAST *ast)
+{
+ if (ast->identifier_token)
+ terminal(ast->identifier_token, ast);
+ if (ast->equal_token)
+ terminal(ast->equal_token, ast);
+ nonterminal(ast->expression);
+ return false;
+}
+
+virtual bool visit(ExceptionDeclarationAST *ast)
+{
+ for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ nonterminal(ast->declarator);
+ if (ast->dot_dot_dot_token)
+ terminal(ast->dot_dot_dot_token, ast);
+ return false;
+}
+
+virtual bool visit(ExceptionSpecificationAST *ast)
+{
+ if (ast->throw_token)
+ terminal(ast->throw_token, ast);
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ if (ast->dot_dot_dot_token)
+ terminal(ast->dot_dot_dot_token, ast);
+ for (ExpressionListAST *iter = ast->type_id_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ return false;
+}
+
+virtual bool visit(ExpressionOrDeclarationStatementAST *ast)
+{
+ nonterminal(ast->expression);
+ nonterminal(ast->declaration);
+ return false;
+}
+
+virtual bool visit(ExpressionStatementAST *ast)
+{
+ nonterminal(ast->expression);
+ if (ast->semicolon_token)
+ terminal(ast->semicolon_token, ast);
+ return false;
+}
+
+virtual bool visit(FunctionDefinitionAST *ast)
+{
+ if (ast->qt_invokable_token)
+ terminal(ast->qt_invokable_token, ast);
+ for (SpecifierListAST *iter = ast->decl_specifier_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ nonterminal(ast->declarator);
+ nonterminal(ast->ctor_initializer);
+ nonterminal(ast->function_body);
+ return false;
+}
+
+virtual bool visit(ForeachStatementAST *ast)
+{
+ if (ast->foreach_token)
+ terminal(ast->foreach_token, ast);
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ nonterminal(ast->declarator);
+ nonterminal(ast->initializer);
+ if (ast->comma_token)
+ terminal(ast->comma_token, ast);
+ nonterminal(ast->expression);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ nonterminal(ast->statement);
+ return false;
+}
+
+virtual bool visit(ForStatementAST *ast)
+{
+ if (ast->for_token)
+ terminal(ast->for_token, ast);
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ nonterminal(ast->initializer);
+ nonterminal(ast->condition);
+ if (ast->semicolon_token)
+ terminal(ast->semicolon_token, ast);
+ nonterminal(ast->expression);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ nonterminal(ast->statement);
+ return false;
+}
+
+virtual bool visit(IfStatementAST *ast)
+{
+ if (ast->if_token)
+ terminal(ast->if_token, ast);
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ nonterminal(ast->condition);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ nonterminal(ast->statement);
+ if (ast->else_token)
+ terminal(ast->else_token, ast);
+ nonterminal(ast->else_statement);
+ return false;
+}
+
+virtual bool visit(ArrayInitializerAST *ast)
+{
+ if (ast->lbrace_token)
+ terminal(ast->lbrace_token, ast);
+ for (ExpressionListAST *iter = ast->expression_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->rbrace_token)
+ terminal(ast->rbrace_token, ast);
+ return false;
+}
+
+virtual bool visit(LabeledStatementAST *ast)
+{
+ if (ast->label_token)
+ terminal(ast->label_token, ast);
+ if (ast->colon_token)
+ terminal(ast->colon_token, ast);
+ nonterminal(ast->statement);
+ return false;
+}
+
+virtual bool visit(LinkageBodyAST *ast)
+{
+ if (ast->lbrace_token)
+ terminal(ast->lbrace_token, ast);
+ for (DeclarationListAST *iter = ast->declaration_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->rbrace_token)
+ terminal(ast->rbrace_token, ast);
+ return false;
+}
+
+virtual bool visit(LinkageSpecificationAST *ast)
+{
+ if (ast->extern_token)
+ terminal(ast->extern_token, ast);
+ if (ast->extern_type_token)
+ terminal(ast->extern_type_token, ast);
+ nonterminal(ast->declaration);
+ return false;
+}
+
+virtual bool visit(MemInitializerAST *ast)
+{
+ nonterminal(ast->name);
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ for (ExpressionListAST *iter = ast->expression_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ return false;
+}
+
+virtual bool visit(NestedNameSpecifierAST *ast)
+{
+ nonterminal(ast->class_or_namespace_name);
+ if (ast->scope_token)
+ terminal(ast->scope_token, ast);
+ return false;
+}
+
+virtual bool visit(QualifiedNameAST *ast)
+{
+ if (ast->global_scope_token)
+ terminal(ast->global_scope_token, ast);
+ for (NestedNameSpecifierListAST *iter = ast->nested_name_specifier_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ nonterminal(ast->unqualified_name);
+ return false;
+}
+
+virtual bool visit(OperatorFunctionIdAST *ast)
+{
+ if (ast->operator_token)
+ terminal(ast->operator_token, ast);
+ nonterminal(ast->op);
+ return false;
+}
+
+virtual bool visit(ConversionFunctionIdAST *ast)
+{
+ if (ast->operator_token)
+ terminal(ast->operator_token, ast);
+ for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ for (PtrOperatorListAST *iter = ast->ptr_operator_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ return false;
+}
+
+virtual bool visit(SimpleNameAST *ast)
+{
+ if (ast->identifier_token)
+ terminal(ast->identifier_token, ast);
+ return false;
+}
+
+virtual bool visit(DestructorNameAST *ast)
+{
+ if (ast->tilde_token)
+ terminal(ast->tilde_token, ast);
+ if (ast->identifier_token)
+ terminal(ast->identifier_token, ast);
+ return false;
+}
+
+virtual bool visit(TemplateIdAST *ast)
+{
+ if (ast->template_token)
+ terminal(ast->template_token, ast);
+ if (ast->identifier_token)
+ terminal(ast->identifier_token, ast);
+ if (ast->less_token)
+ terminal(ast->less_token, ast);
+ for (ExpressionListAST *iter = ast->template_argument_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->greater_token)
+ terminal(ast->greater_token, ast);
+ return false;
+}
+
+virtual bool visit(NamespaceAST *ast)
+{
+ if (ast->namespace_token)
+ terminal(ast->namespace_token, ast);
+ if (ast->identifier_token)
+ terminal(ast->identifier_token, ast);
+ for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ nonterminal(ast->linkage_body);
+ return false;
+}
+
+virtual bool visit(NamespaceAliasDefinitionAST *ast)
+{
+ if (ast->namespace_token)
+ terminal(ast->namespace_token, ast);
+ if (ast->namespace_name_token)
+ terminal(ast->namespace_name_token, ast);
+ if (ast->equal_token)
+ terminal(ast->equal_token, ast);
+ nonterminal(ast->name);
+ if (ast->semicolon_token)
+ terminal(ast->semicolon_token, ast);
+ return false;
+}
+
+virtual bool visit(NewPlacementAST *ast)
+{
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ for (ExpressionListAST *iter = ast->expression_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ return false;
+}
+
+virtual bool visit(NewArrayDeclaratorAST *ast)
+{
+ if (ast->lbracket_token)
+ terminal(ast->lbracket_token, ast);
+ nonterminal(ast->expression);
+ if (ast->rbracket_token)
+ terminal(ast->rbracket_token, ast);
+ return false;
+}
+
+virtual bool visit(NewExpressionAST *ast)
+{
+ if (ast->scope_token)
+ terminal(ast->scope_token, ast);
+ if (ast->new_token)
+ terminal(ast->new_token, ast);
+ nonterminal(ast->new_placement);
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ nonterminal(ast->type_id);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ nonterminal(ast->new_type_id);
+ nonterminal(ast->new_initializer);
+ return false;
+}
+
+virtual bool visit(NewInitializerAST *ast)
+{
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ nonterminal(ast->expression);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ return false;
+}
+
+virtual bool visit(NewTypeIdAST *ast)
+{
+ for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ for (PtrOperatorListAST *iter = ast->ptr_operator_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ for (NewArrayDeclaratorListAST *iter = ast->new_array_declarator_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ return false;
+}
+
+virtual bool visit(OperatorAST *ast)
+{
+ if (ast->op_token)
+ terminal(ast->op_token, ast);
+ if (ast->open_token)
+ terminal(ast->open_token, ast);
+ if (ast->close_token)
+ terminal(ast->close_token, ast);
+ return false;
+}
+
+virtual bool visit(ParameterDeclarationAST *ast)
+{
+ for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ nonterminal(ast->declarator);
+ if (ast->equal_token)
+ terminal(ast->equal_token, ast);
+ nonterminal(ast->expression);
+ return false;
+}
+
+virtual bool visit(ParameterDeclarationClauseAST *ast)
+{
+ for (ParameterDeclarationListAST *iter = ast->parameter_declaration_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->dot_dot_dot_token)
+ terminal(ast->dot_dot_dot_token, ast);
+ return false;
+}
+
+virtual bool visit(CallAST *ast)
+{
+ nonterminal(ast->base_expression);
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ for (ExpressionListAST *iter = ast->expression_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ return false;
+}
+
+virtual bool visit(ArrayAccessAST *ast)
+{
+ nonterminal(ast->base_expression);
+ if (ast->lbracket_token)
+ terminal(ast->lbracket_token, ast);
+ nonterminal(ast->expression);
+ if (ast->rbracket_token)
+ terminal(ast->rbracket_token, ast);
+ return false;
+}
+
+virtual bool visit(PostIncrDecrAST *ast)
+{
+ nonterminal(ast->base_expression);
+ if (ast->incr_decr_token)
+ terminal(ast->incr_decr_token, ast);
+ return false;
+}
+
+virtual bool visit(MemberAccessAST *ast)
+{
+ nonterminal(ast->base_expression);
+ if (ast->access_token)
+ terminal(ast->access_token, ast);
+ if (ast->template_token)
+ terminal(ast->template_token, ast);
+ nonterminal(ast->member_name);
+ return false;
+}
+
+virtual bool visit(TypeidExpressionAST *ast)
+{
+ if (ast->typeid_token)
+ terminal(ast->typeid_token, ast);
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ nonterminal(ast->expression);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ return false;
+}
+
+virtual bool visit(TypenameCallExpressionAST *ast)
+{
+ if (ast->typename_token)
+ terminal(ast->typename_token, ast);
+ nonterminal(ast->name);
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ for (ExpressionListAST *iter = ast->expression_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ return false;
+}
+
+virtual bool visit(TypeConstructorCallAST *ast)
+{
+ for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ for (ExpressionListAST *iter = ast->expression_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ return false;
+}
+
+virtual bool visit(PointerToMemberAST *ast)
+{
+ if (ast->global_scope_token)
+ terminal(ast->global_scope_token, ast);
+ for (NestedNameSpecifierListAST *iter = ast->nested_name_specifier_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->star_token)
+ terminal(ast->star_token, ast);
+ for (SpecifierListAST *iter = ast->cv_qualifier_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ return false;
+}
+
+virtual bool visit(PointerAST *ast)
+{
+ if (ast->star_token)
+ terminal(ast->star_token, ast);
+ for (SpecifierListAST *iter = ast->cv_qualifier_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ return false;
+}
+
+virtual bool visit(ReferenceAST *ast)
+{
+ if (ast->reference_token)
+ terminal(ast->reference_token, ast);
+ return false;
+}
+
+virtual bool visit(BreakStatementAST *ast)
+{
+ if (ast->break_token)
+ terminal(ast->break_token, ast);
+ if (ast->semicolon_token)
+ terminal(ast->semicolon_token, ast);
+ return false;
+}
+
+virtual bool visit(ContinueStatementAST *ast)
+{
+ if (ast->continue_token)
+ terminal(ast->continue_token, ast);
+ if (ast->semicolon_token)
+ terminal(ast->semicolon_token, ast);
+ return false;
+}
+
+virtual bool visit(GotoStatementAST *ast)
+{
+ if (ast->goto_token)
+ terminal(ast->goto_token, ast);
+ if (ast->identifier_token)
+ terminal(ast->identifier_token, ast);
+ if (ast->semicolon_token)
+ terminal(ast->semicolon_token, ast);
+ return false;
+}
+
+virtual bool visit(ReturnStatementAST *ast)
+{
+ if (ast->return_token)
+ terminal(ast->return_token, ast);
+ nonterminal(ast->expression);
+ if (ast->semicolon_token)
+ terminal(ast->semicolon_token, ast);
+ return false;
+}
+
+virtual bool visit(SizeofExpressionAST *ast)
+{
+ if (ast->sizeof_token)
+ terminal(ast->sizeof_token, ast);
+ if (ast->dot_dot_dot_token)
+ terminal(ast->dot_dot_dot_token, ast);
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ nonterminal(ast->expression);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ return false;
+}
+
+virtual bool visit(NumericLiteralAST *ast)
+{
+ if (ast->literal_token)
+ terminal(ast->literal_token, ast);
+ return false;
+}
+
+virtual bool visit(BoolLiteralAST *ast)
+{
+ if (ast->literal_token)
+ terminal(ast->literal_token, ast);
+ return false;
+}
+
+virtual bool visit(ThisExpressionAST *ast)
+{
+ if (ast->this_token)
+ terminal(ast->this_token, ast);
+ return false;
+}
+
+virtual bool visit(NestedExpressionAST *ast)
+{
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ nonterminal(ast->expression);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ return false;
+}
+
+virtual bool visit(StringLiteralAST *ast)
+{
+ if (ast->literal_token)
+ terminal(ast->literal_token, ast);
+ nonterminal(ast->next);
+ return false;
+}
+
+virtual bool visit(SwitchStatementAST *ast)
+{
+ if (ast->switch_token)
+ terminal(ast->switch_token, ast);
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ nonterminal(ast->condition);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ nonterminal(ast->statement);
+ return false;
+}
+
+virtual bool visit(TemplateDeclarationAST *ast)
+{
+ if (ast->export_token)
+ terminal(ast->export_token, ast);
+ if (ast->template_token)
+ terminal(ast->template_token, ast);
+ if (ast->less_token)
+ terminal(ast->less_token, ast);
+ for (DeclarationListAST *iter = ast->template_parameter_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->greater_token)
+ terminal(ast->greater_token, ast);
+ nonterminal(ast->declaration);
+ return false;
+}
+
+virtual bool visit(ThrowExpressionAST *ast)
+{
+ if (ast->throw_token)
+ terminal(ast->throw_token, ast);
+ nonterminal(ast->expression);
+ return false;
+}
+
+virtual bool visit(TranslationUnitAST *ast)
+{
+ for (DeclarationListAST *iter = ast->declaration_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ return false;
+}
+
+virtual bool visit(TryBlockStatementAST *ast)
+{
+ if (ast->try_token)
+ terminal(ast->try_token, ast);
+ nonterminal(ast->statement);
+ for (CatchClauseListAST *iter = ast->catch_clause_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ return false;
+}
+
+virtual bool visit(CatchClauseAST *ast)
+{
+ if (ast->catch_token)
+ terminal(ast->catch_token, ast);
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ nonterminal(ast->exception_declaration);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ nonterminal(ast->statement);
+ return false;
+}
+
+virtual bool visit(TypeIdAST *ast)
+{
+ for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ nonterminal(ast->declarator);
+ return false;
+}
+
+virtual bool visit(TypenameTypeParameterAST *ast)
+{
+ if (ast->classkey_token)
+ terminal(ast->classkey_token, ast);
+ if (ast->dot_dot_dot_token)
+ terminal(ast->dot_dot_dot_token, ast);
+ nonterminal(ast->name);
+ if (ast->equal_token)
+ terminal(ast->equal_token, ast);
+ nonterminal(ast->type_id);
+ return false;
+}
+
+virtual bool visit(TemplateTypeParameterAST *ast)
+{
+ if (ast->template_token)
+ terminal(ast->template_token, ast);
+ if (ast->less_token)
+ terminal(ast->less_token, ast);
+ for (DeclarationListAST *iter = ast->template_parameter_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->greater_token)
+ terminal(ast->greater_token, ast);
+ if (ast->class_token)
+ terminal(ast->class_token, ast);
+ if (ast->dot_dot_dot_token)
+ terminal(ast->dot_dot_dot_token, ast);
+ nonterminal(ast->name);
+ if (ast->equal_token)
+ terminal(ast->equal_token, ast);
+ nonterminal(ast->type_id);
+ return false;
+}
+
+virtual bool visit(UnaryExpressionAST *ast)
+{
+ if (ast->unary_op_token)
+ terminal(ast->unary_op_token, ast);
+ nonterminal(ast->expression);
+ return false;
+}
+
+virtual bool visit(UsingAST *ast)
+{
+ if (ast->using_token)
+ terminal(ast->using_token, ast);
+ if (ast->typename_token)
+ terminal(ast->typename_token, ast);
+ nonterminal(ast->name);
+ if (ast->semicolon_token)
+ terminal(ast->semicolon_token, ast);
+ return false;
+}
+
+virtual bool visit(UsingDirectiveAST *ast)
+{
+ if (ast->using_token)
+ terminal(ast->using_token, ast);
+ if (ast->namespace_token)
+ terminal(ast->namespace_token, ast);
+ nonterminal(ast->name);
+ if (ast->semicolon_token)
+ terminal(ast->semicolon_token, ast);
+ return false;
+}
+
+virtual bool visit(WhileStatementAST *ast)
+{
+ if (ast->while_token)
+ terminal(ast->while_token, ast);
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ nonterminal(ast->condition);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ nonterminal(ast->statement);
+ return false;
+}
+
+virtual bool visit(ObjCClassForwardDeclarationAST *ast)
+{
+ for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->class_token)
+ terminal(ast->class_token, ast);
+ for (NameListAST *iter = ast->identifier_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->semicolon_token)
+ terminal(ast->semicolon_token, ast);
+ return false;
+}
+
+virtual bool visit(ObjCClassDeclarationAST *ast)
+{
+ for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->interface_token)
+ terminal(ast->interface_token, ast);
+ if (ast->implementation_token)
+ terminal(ast->implementation_token, ast);
+ nonterminal(ast->class_name);
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ nonterminal(ast->category_name);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ if (ast->colon_token)
+ terminal(ast->colon_token, ast);
+ nonterminal(ast->superclass);
+ nonterminal(ast->protocol_refs);
+ nonterminal(ast->inst_vars_decl);
+ for (DeclarationListAST *iter = ast->member_declaration_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->end_token)
+ terminal(ast->end_token, ast);
+ return false;
+}
+
+virtual bool visit(ObjCProtocolForwardDeclarationAST *ast)
+{
+ for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->protocol_token)
+ terminal(ast->protocol_token, ast);
+ for (NameListAST *iter = ast->identifier_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->semicolon_token)
+ terminal(ast->semicolon_token, ast);
+ return false;
+}
+
+virtual bool visit(ObjCProtocolDeclarationAST *ast)
+{
+ for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->protocol_token)
+ terminal(ast->protocol_token, ast);
+ nonterminal(ast->name);
+ nonterminal(ast->protocol_refs);
+ for (DeclarationListAST *iter = ast->member_declaration_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->end_token)
+ terminal(ast->end_token, ast);
+ return false;
+}
+
+virtual bool visit(ObjCProtocolRefsAST *ast)
+{
+ if (ast->less_token)
+ terminal(ast->less_token, ast);
+ for (NameListAST *iter = ast->identifier_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->greater_token)
+ terminal(ast->greater_token, ast);
+ return false;
+}
+
+virtual bool visit(ObjCMessageArgumentAST *ast)
+{
+ nonterminal(ast->parameter_value_expression);
+ return false;
+}
+
+virtual bool visit(ObjCMessageExpressionAST *ast)
+{
+ if (ast->lbracket_token)
+ terminal(ast->lbracket_token, ast);
+ nonterminal(ast->receiver_expression);
+ nonterminal(ast->selector);
+ for (ObjCMessageArgumentListAST *iter = ast->argument_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->rbracket_token)
+ terminal(ast->rbracket_token, ast);
+ return false;
+}
+
+virtual bool visit(ObjCProtocolExpressionAST *ast)
+{
+ if (ast->protocol_token)
+ terminal(ast->protocol_token, ast);
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ if (ast->identifier_token)
+ terminal(ast->identifier_token, ast);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ return false;
+}
+
+virtual bool visit(ObjCTypeNameAST *ast)
+{
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ if (ast->type_qualifier_token)
+ terminal(ast->type_qualifier_token, ast);
+ nonterminal(ast->type_id);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ return false;
+}
+
+virtual bool visit(ObjCEncodeExpressionAST *ast)
+{
+ if (ast->encode_token)
+ terminal(ast->encode_token, ast);
+ nonterminal(ast->type_name);
+ return false;
+}
+
+virtual bool visit(ObjCSelectorExpressionAST *ast)
+{
+ if (ast->selector_token)
+ terminal(ast->selector_token, ast);
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ nonterminal(ast->selector);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ return false;
+}
+
+virtual bool visit(ObjCInstanceVariablesDeclarationAST *ast)
+{
+ if (ast->lbrace_token)
+ terminal(ast->lbrace_token, ast);
+ for (DeclarationListAST *iter = ast->instance_variable_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->rbrace_token)
+ terminal(ast->rbrace_token, ast);
+ return false;
+}
+
+virtual bool visit(ObjCVisibilityDeclarationAST *ast)
+{
+ if (ast->visibility_token)
+ terminal(ast->visibility_token, ast);
+ return false;
+}
+
+virtual bool visit(ObjCPropertyAttributeAST *ast)
+{
+ if (ast->attribute_identifier_token)
+ terminal(ast->attribute_identifier_token, ast);
+ if (ast->equals_token)
+ terminal(ast->equals_token, ast);
+ nonterminal(ast->method_selector);
+ return false;
+}
+
+virtual bool visit(ObjCPropertyDeclarationAST *ast)
+{
+ for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->property_token)
+ terminal(ast->property_token, ast);
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ for (ObjCPropertyAttributeListAST *iter = ast->property_attribute_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ nonterminal(ast->simple_declaration);
+ return false;
+}
+
+virtual bool visit(ObjCMessageArgumentDeclarationAST *ast)
+{
+ nonterminal(ast->type_name);
+ for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ nonterminal(ast->param_name);
+ return false;
+}
+
+virtual bool visit(ObjCMethodPrototypeAST *ast)
+{
+ if (ast->method_type_token)
+ terminal(ast->method_type_token, ast);
+ nonterminal(ast->type_name);
+ nonterminal(ast->selector);
+ for (ObjCMessageArgumentDeclarationListAST *iter = ast->argument_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->dot_dot_dot_token)
+ terminal(ast->dot_dot_dot_token, ast);
+ for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ return false;
+}
+
+virtual bool visit(ObjCMethodDeclarationAST *ast)
+{
+ nonterminal(ast->method_prototype);
+ nonterminal(ast->function_body);
+ if (ast->semicolon_token)
+ terminal(ast->semicolon_token, ast);
+ return false;
+}
+
+virtual bool visit(ObjCSynthesizedPropertyAST *ast)
+{
+ if (ast->property_identifier_token)
+ terminal(ast->property_identifier_token, ast);
+ if (ast->equals_token)
+ terminal(ast->equals_token, ast);
+ if (ast->alias_identifier_token)
+ terminal(ast->alias_identifier_token, ast);
+ return false;
+}
+
+virtual bool visit(ObjCSynthesizedPropertiesDeclarationAST *ast)
+{
+ if (ast->synthesized_token)
+ terminal(ast->synthesized_token, ast);
+ for (ObjCSynthesizedPropertyListAST *iter = ast->property_identifier_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->semicolon_token)
+ terminal(ast->semicolon_token, ast);
+ return false;
+}
+
+virtual bool visit(ObjCDynamicPropertiesDeclarationAST *ast)
+{
+ if (ast->dynamic_token)
+ terminal(ast->dynamic_token, ast);
+ for (NameListAST *iter = ast->property_identifier_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->semicolon_token)
+ terminal(ast->semicolon_token, ast);
+ return false;
+}
+
+virtual bool visit(ObjCFastEnumerationAST *ast)
+{
+ if (ast->for_token)
+ terminal(ast->for_token, ast);
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ nonterminal(ast->declarator);
+ nonterminal(ast->initializer);
+ if (ast->in_token)
+ terminal(ast->in_token, ast);
+ nonterminal(ast->fast_enumeratable_expression);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ nonterminal(ast->statement);
+ return false;
+}
+
+virtual bool visit(ObjCSynchronizedStatementAST *ast)
+{
+ if (ast->synchronized_token)
+ terminal(ast->synchronized_token, ast);
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ nonterminal(ast->synchronized_object);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ nonterminal(ast->statement);
+ return false;
+}
+
+virtual bool visit(LambdaExpressionAST *ast)
+{
+ nonterminal(ast->lambda_introducer);
+ nonterminal(ast->lambda_declarator);
+ nonterminal(ast->statement);
+ return false;
+}
+
+virtual bool visit(LambdaIntroducerAST *ast)
+{
+ if (ast->lbracket_token)
+ terminal(ast->lbracket_token, ast);
+ nonterminal(ast->lambda_capture);
+ if (ast->rbracket_token)
+ terminal(ast->rbracket_token, ast);
+ return false;
+}
+
+virtual bool visit(LambdaCaptureAST *ast)
+{
+ if (ast->default_capture_token)
+ terminal(ast->default_capture_token, ast);
+ for (CaptureListAST *iter = ast->capture_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ return false;
+}
+
+virtual bool visit(CaptureAST *ast)
+{
+ return false;
+}
+
+virtual bool visit(LambdaDeclaratorAST *ast)
+{
+ if (ast->lparen_token)
+ terminal(ast->lparen_token, ast);
+ nonterminal(ast->parameter_declaration_clause);
+ if (ast->rparen_token)
+ terminal(ast->rparen_token, ast);
+ for (SpecifierListAST *iter = ast->attributes; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->mutable_token)
+ terminal(ast->mutable_token, ast);
+ nonterminal(ast->exception_specification);
+ nonterminal(ast->trailing_return_type);
+ return false;
+}
+
+virtual bool visit(TrailingReturnTypeAST *ast)
+{
+ if (ast->arrow_token)
+ terminal(ast->arrow_token, ast);
+ for (SpecifierListAST *iter = ast->attributes; iter; iter = iter->next)
+ nonterminal(iter->value);
+ for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ nonterminal(ast->declarator);
+ return false;
+}
+
+virtual bool visit(BracedInitializerAST *ast)
+{
+ if (ast->lbrace_token)
+ terminal(ast->lbrace_token, ast);
+ for (ExpressionListAST *iter = ast->expression_list; iter; iter = iter->next)
+ nonterminal(iter->value);
+ if (ast->comma_token)
+ terminal(ast->comma_token, ast);
+ if (ast->rbrace_token)
+ terminal(ast->rbrace_token, ast);
+ return false;
+}
+
diff --git a/tests/manual/cplusplus-dump/main.cpp b/tests/tools/cplusplus-dump/main.cpp
index cc56895443..cc56895443 100644
--- a/tests/manual/cplusplus-dump/main.cpp
+++ b/tests/tools/cplusplus-dump/main.cpp
diff --git a/tests/manual/cplusplus-dump/tests/templ01.cpp b/tests/tools/cplusplus-dump/tests/templ01.cpp
index dcabffae59..dcabffae59 100644
--- a/tests/manual/cplusplus-dump/tests/templ01.cpp
+++ b/tests/tools/cplusplus-dump/tests/templ01.cpp
diff --git a/tests/tools/qml-ast2dot/main.cpp b/tests/tools/qml-ast2dot/main.cpp
new file mode 100644
index 0000000000..5d242d9d80
--- /dev/null
+++ b/tests/tools/qml-ast2dot/main.cpp
@@ -0,0 +1,367 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** No Commercial Usage
+**
+** This file 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.
+**
+**************************************************************************/
+
+#include <qmljs/parser/qmljsast_p.h>
+#include <qmljs/parser/qmljsastvisitor_p.h>
+#include <qmljs/qmljsdocument.h>
+
+#include <QFile>
+#include <QList>
+#include <QCoreApplication>
+#include <QStringList>
+#include <QFileInfo>
+#include <QTime>
+#include <QtDebug>
+
+#include <cstdio>
+#include <cstdlib>
+#include <fstream>
+#include <iostream>
+#ifdef __GNUC__
+# include <cxxabi.h>
+#endif
+
+using namespace QmlJS;
+using namespace QmlJS::AST;
+using namespace std;
+
+class ASTDump: protected Visitor
+{
+public:
+ void operator()(const QString &fileName, const QByteArray &src, Node *ast) {
+ _src = src;
+ QString basename = fileName;
+ int dotIdx = basename.lastIndexOf('.');
+ if (dotIdx != -1)
+ basename.truncate(dotIdx);
+ basename.append(QLatin1String(".ast.dot"));
+ out.open(basename.toUtf8().constData());
+
+ out << "digraph AST { ordering=out;" << endl;
+ // cout << "rankdir = \"LR\";" << endl;
+ Node::accept(ast, this);
+
+ typedef QPair<QByteArray, QByteArray> Pair;
+
+ foreach (const Pair &conn, _connections)
+ out << conn.first.constData() << " -> " << conn.second.constData() << endl;
+
+ alignTerminals();
+
+ out << "}" << endl;
+ out.close();
+ cout << qPrintable(basename) << endl;
+ }
+
+protected:
+ void alignTerminals() {
+ out<<"{ rank=same;" << endl;
+ foreach (const QByteArray &terminalShape, _terminalShapes) {
+ out << " " << string(terminalShape) << ";" << endl;
+ }
+ out<<"}"<<endl;
+ }
+
+ static QByteArray name(Node *ast) {
+#ifdef __GNUC__
+ QByteArray name = abi::__cxa_demangle(typeid(*ast).name(), 0, 0, 0) + 12;
+#else
+ QByteArray name = typeid(*ast).name();
+#endif
+ return name;
+ }
+
+ QString spell(const SourceLocation &token) {
+ return _src.mid(token.offset, token.length).replace('\'', "\\\\").replace('"', "\\\"");
+ }
+
+ void terminal(const SourceLocation &token) {
+ if (!token.isValid())
+ return;
+
+ static int count = 1;
+ QByteArray id = 't' + QByteArray::number(count++);
+ Node *node = _stack.last();
+ _connections.append(qMakePair(_id[node], id));
+
+ QByteArray t;
+ t.append(id);
+ t.append(" [label = \"");
+ t.append(spell(token).toUtf8());
+ t.append("\" shape=rect]");
+ _terminalShapes.append(t);
+ }
+
+ virtual void nonterminal(Node *ast) {
+ Node::accept(ast, this);
+ }
+
+ virtual void node(Node *ast) {
+ out << _id[ast].constData() << " [label=\"" << name(ast).constData() << "\"];" << endl;
+ }
+
+ virtual bool preVisit(Node *ast) {
+ static int count = 1;
+ const QByteArray id = 'n' + QByteArray::number(count++);
+ _id[ast] = id;
+
+
+ if (! _stack.isEmpty())
+ _connections.append(qMakePair(_id[_stack.last()], id));
+
+ _stack.append(ast);
+
+ node(ast);
+
+ return true;
+ }
+
+ virtual void postVisit(Node *) {
+ _stack.removeLast();
+ }
+
+protected: // visiting methods:
+ virtual bool visit(UiImport *ast) {
+ terminal(ast->importToken);
+
+ if (ast->importUri)
+ nonterminal(ast->importUri);
+ else
+ terminal(ast->fileNameToken);
+
+ terminal(ast->versionToken);
+ terminal(ast->asToken);
+ terminal(ast->importIdToken);
+ terminal(ast->semicolonToken);
+ return false;
+ }
+
+ virtual bool visit(UiObjectBinding *ast) {
+ if (ast->hasOnToken) {
+ nonterminal(ast->qualifiedTypeNameId);
+ terminal(ast->colonToken);
+ nonterminal(ast->qualifiedId);
+ } else {
+ nonterminal(ast->qualifiedId);
+ terminal(ast->colonToken);
+ nonterminal(ast->qualifiedTypeNameId);
+ }
+ nonterminal(ast->initializer);
+ return false;
+ }
+
+ virtual bool visit(UiObjectDefinition *ast) {
+ nonterminal(ast->qualifiedTypeNameId);
+ nonterminal(ast->initializer);
+ return false;
+ }
+
+ virtual bool visit(UiObjectInitializer *ast) {
+ terminal(ast->lbraceToken);
+ nonterminal(ast->members);
+ terminal(ast->rbraceToken);
+ return false;
+ }
+
+ virtual bool visit(UiScriptBinding *ast) {
+ nonterminal(ast->qualifiedId);
+ terminal(ast->colonToken);
+ nonterminal(ast->statement);
+ return false;
+ }
+
+ virtual bool visit(UiArrayBinding *ast) {
+ nonterminal(ast->qualifiedId);
+ terminal(ast->colonToken);
+ terminal(ast->lbracketToken);
+ nonterminal(ast->members);
+ terminal(ast->rbracketToken);
+ return false;
+ }
+
+ virtual bool visit(UiArrayMemberList *ast) {
+ terminal(ast->commaToken);
+ nonterminal(ast->member);
+ nonterminal(ast->next);
+ return false;
+ }
+
+ virtual bool visit(UiQualifiedId *ast) {
+ terminal(ast->identifierToken);
+ nonterminal(ast->next);
+ return false;
+ }
+
+ virtual bool visit(UiPublicMember *ast) {
+ // TODO: place the parameters...
+// UiParameterList *parameters;
+
+ terminal(ast->defaultToken);
+ terminal(ast->readonlyToken);
+ terminal(ast->propertyToken);
+ terminal(ast->typeModifierToken);
+ terminal(ast->typeToken);
+ terminal(ast->identifierToken);
+ terminal(ast->colonToken);
+ nonterminal(ast->expression);
+ nonterminal(ast->binding);
+ terminal(ast->semicolonToken);
+ return false;
+ }
+
+ virtual bool visit(UiFormal *ast) { terminal(ast->identifierToken); terminal(ast->asToken); terminal(ast->aliasToken); return false; }
+ virtual bool visit(UiSignature *ast) { terminal(ast->lparenToken); nonterminal(ast->formals); terminal(ast->rparenToken); return false; }
+
+ virtual bool visit(StringLiteral *ast) { terminal(ast->literalToken); return false; }
+ virtual bool visit(NumericLiteral *ast) { terminal(ast->literalToken); return false; }
+ virtual bool visit(TrueLiteral *ast) { terminal(ast->trueToken); return false; }
+ virtual bool visit(FalseLiteral *ast) { terminal(ast->falseToken); return false; }
+ virtual bool visit(IdentifierExpression *ast) { terminal(ast->identifierToken); return false; }
+ virtual bool visit(FieldMemberExpression *ast) { nonterminal(ast->base); terminal(ast->dotToken); terminal(ast->identifierToken); return false; }
+ virtual bool visit(BinaryExpression *ast) { nonterminal(ast->left); terminal(ast->operatorToken); nonterminal(ast->right); return false; }
+ virtual bool visit(UnaryPlusExpression *ast) { terminal(ast->plusToken); nonterminal(ast->expression); return false; }
+ virtual bool visit(UnaryMinusExpression *ast) { terminal(ast->minusToken); nonterminal(ast->expression); return false; }
+ virtual bool visit(NestedExpression *ast) { terminal(ast->lparenToken); nonterminal(ast->expression); terminal(ast->rparenToken); return false; }
+ virtual bool visit(ThisExpression *ast) { terminal(ast->thisToken); return false; }
+ virtual bool visit(NullExpression *ast) { terminal(ast->nullToken); return false; }
+ virtual bool visit(RegExpLiteral *ast) { terminal(ast->literalToken); return false; }
+ virtual bool visit(ArrayLiteral *ast) { terminal(ast->lbracketToken); nonterminal(ast->elements); terminal(ast->commaToken); nonterminal(ast->elision); terminal(ast->rbracketToken); return false; }
+ virtual bool visit(ObjectLiteral *ast) { terminal(ast->lbraceToken); nonterminal(ast->properties); terminal(ast->rbraceToken); return false; }
+ virtual bool visit(ElementList *ast) { nonterminal(ast->next); terminal(ast->commaToken); nonterminal(ast->elision); nonterminal(ast->expression); return false; }
+ virtual bool visit(Elision *ast) { nonterminal(ast->next); terminal(ast->commaToken); return false; }
+ virtual bool visit(PropertyNameAndValueList *ast) { nonterminal(ast->name); terminal(ast->colonToken); nonterminal(ast->value); terminal(ast->commaToken); nonterminal(ast->next); return false; }
+ virtual bool visit(IdentifierPropertyName *ast) { terminal(ast->propertyNameToken); return false; }
+ virtual bool visit(StringLiteralPropertyName *ast) { terminal(ast->propertyNameToken); return false; }
+ virtual bool visit(NumericLiteralPropertyName *ast) { terminal(ast->propertyNameToken); return false; }
+ virtual bool visit(ArrayMemberExpression *ast) { nonterminal(ast->base); terminal(ast->lbracketToken); nonterminal(ast->expression); terminal(ast->rbracketToken); return false; }
+ virtual bool visit(NewMemberExpression *ast) { terminal(ast->newToken); nonterminal(ast->base); terminal(ast->lparenToken); nonterminal(ast->arguments); terminal(ast->rparenToken); return false; }
+ virtual bool visit(NewExpression *ast) { terminal(ast->newToken); nonterminal(ast->expression); return false; }
+ virtual bool visit(CallExpression *ast) { nonterminal(ast->base); terminal(ast->lparenToken); nonterminal(ast->arguments); terminal(ast->rparenToken); return false; }
+ virtual bool visit(ArgumentList *ast) { nonterminal(ast->expression); terminal(ast->commaToken); nonterminal(ast->next); return false; }
+ virtual bool visit(PostIncrementExpression *ast) { nonterminal(ast->base); terminal(ast->incrementToken); return false; }
+ virtual bool visit(PostDecrementExpression *ast) { nonterminal(ast->base); terminal(ast->decrementToken); return false; }
+ virtual bool visit(DeleteExpression *ast) { terminal(ast->deleteToken); nonterminal(ast->expression); return false; }
+ virtual bool visit(VoidExpression *ast) { terminal(ast->voidToken); nonterminal(ast->expression); return false; }
+ virtual bool visit(TypeOfExpression *ast) { terminal(ast->typeofToken); nonterminal(ast->expression); return false; }
+ virtual bool visit(PreIncrementExpression *ast) { terminal(ast->incrementToken); nonterminal(ast->expression); return false; }
+ virtual bool visit(PreDecrementExpression *ast) { terminal(ast->decrementToken); nonterminal(ast->expression); return false; }
+ virtual bool visit(TildeExpression *ast) { terminal(ast->tildeToken); nonterminal(ast->expression); return false; }
+ virtual bool visit(NotExpression *ast) { terminal(ast->notToken); nonterminal(ast->expression); return false; }
+ virtual bool visit(ConditionalExpression *ast) { nonterminal(ast->expression); terminal(ast->questionToken); nonterminal(ast->ok); terminal(ast->colonToken); nonterminal(ast->ko); return false; }
+ virtual bool visit(Expression *ast) { nonterminal(ast->left); terminal(ast->commaToken); nonterminal(ast->right); return false; }
+ virtual bool visit(Block *ast) { terminal(ast->lbraceToken); nonterminal(ast->statements); terminal(ast->rbraceToken); return false; }
+ virtual bool visit(VariableStatement *ast) { terminal(ast->declarationKindToken); nonterminal(ast->declarations); terminal(ast->semicolonToken); return false; }
+ virtual bool visit(VariableDeclaration *ast) { terminal(ast->identifierToken); nonterminal(ast->expression); return false; }
+ virtual bool visit(VariableDeclarationList *ast) { nonterminal(ast->declaration); terminal(ast->commaToken); nonterminal(ast->next); return false; }
+ virtual bool visit(EmptyStatement* ast) { terminal(ast->semicolonToken); return false; }
+ virtual bool visit(ExpressionStatement *ast) { nonterminal(ast->expression); terminal(ast->semicolonToken); return false; }
+ virtual bool visit(IfStatement *ast) { terminal(ast->ifToken); terminal(ast->lparenToken); nonterminal(ast->expression); terminal(ast->rparenToken); nonterminal(ast->ok); terminal(ast->elseToken); nonterminal(ast->ko); return false; }
+ virtual bool visit(DoWhileStatement *ast) { terminal(ast->doToken); nonterminal(ast->statement); terminal(ast->whileToken); terminal(ast->lparenToken); nonterminal(ast->expression); terminal(ast->rparenToken); terminal(ast->semicolonToken); return false; }
+
+// TODO: visitors for:
+// WhileStatement
+// ForStatement
+// LocalForStatement
+// ForEachStatement
+// LocalForEachStatement
+// ContinueStatement
+// BreakStatement
+// ReturnStatement
+// WithStatement
+// CaseBlock
+// SwitchStatement
+// CaseClause
+// DefaultClause
+// LabelledStatement
+// ThrowStatement
+// Catch
+// Finally
+// TryStatement
+// FunctionExpression
+// FunctionDeclaration
+// DebuggerStatement
+// UiParameterList
+
+private:
+ QHash<Node *, QByteArray> _id;
+ QList<QPair<QByteArray, QByteArray> > _connections;
+ QList<Node *> _stack;
+ QList<QByteArray> _terminalShapes;
+ ofstream out;
+ QByteArray _src;
+};
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication app(argc, argv);
+
+ QStringList files = app.arguments();
+ files.removeFirst();
+
+ foreach (const QString &fileName, files) {
+ QFile file(fileName);
+ if (! file.open(QFile::ReadOnly)) {
+ cerr << "Cannot open \"" << qPrintable(fileName)
+ << "\", skipping it." << endl;
+ continue;
+ }
+
+ const QByteArray source = file.readAll();
+ file.close();
+
+ Document::Ptr doc = Document::create(fileName);
+ doc->setSource(source);
+ doc->parseQml();
+
+ foreach (const DiagnosticMessage &m, doc->diagnosticMessages()) {
+ ostream *os;
+ if (m.isError()) {
+ os = &cerr;
+ *os << "Error:";
+ } else {
+ os = &cout;
+ *os << "Warning:";
+ }
+
+ if (m.loc.isValid())
+ *os << m.loc.startLine << ':' << m.loc.startColumn << ':';
+ *os << ' ';
+ *os << qPrintable(m.message) << endl;
+ }
+
+ ASTDump dump;
+ dump(fileName, source, doc->qmlProgram());
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/tests/tools/qml-ast2dot/qml-ast2dot.pro b/tests/tools/qml-ast2dot/qml-ast2dot.pro
new file mode 100644
index 0000000000..dc83ce9686
--- /dev/null
+++ b/tests/tools/qml-ast2dot/qml-ast2dot.pro
@@ -0,0 +1,21 @@
+include(../../../qtcreator.pri)
+QT = core gui
+macx:CONFIG -= app_bundle
+TARGET = qml-ast2dot
+
+include($$IDE_SOURCE_TREE/src/libs/qmljs/qmljs.pri)
+include($$IDE_SOURCE_TREE/src/libs/utils/utils.pri)
+
+# Input
+SOURCES += main.cpp
+
+unix {
+ debug:OBJECTS_DIR = $${OUT_PWD}/.obj/debug-shared
+ release:OBJECTS_DIR = $${OUT_PWD}/.obj/release-shared
+
+ debug:MOC_DIR = $${OUT_PWD}/.moc/debug-shared
+ release:MOC_DIR = $${OUT_PWD}/.moc/release-shared
+
+ RCC_DIR = $${OUT_PWD}/.rcc/
+ UI_DIR = $${OUT_PWD}/.uic/
+}
diff --git a/tests/tools/qtquickappblaster/main.cpp b/tests/tools/qtquickappblaster/main.cpp
new file mode 100644
index 0000000000..9ac3896d53
--- /dev/null
+++ b/tests/tools/qtquickappblaster/main.cpp
@@ -0,0 +1,102 @@
+#include "qmlstandaloneapp.h"
+#include <QtCore>
+
+using namespace Qt4ProjectManager::Internal;
+
+bool processXmlFile(const QString &xmlFile)
+{
+ QFile file(xmlFile);
+ if (!file.open(QIODevice::ReadOnly))
+ return false;
+
+ const QLatin1String tag_app("app");
+ const QLatin1String attrib_mainQmlFile("mainqmlfile");
+ const QLatin1String attrib_projectPath("projectpath");
+ const QLatin1String attrib_projectName("projectname");
+ const QLatin1String attrib_screenOrientation("screenorientation");
+ const QLatin1String value_screenOrientationLockLandscape("LockLandscape");
+ const QLatin1String value_screenOrientationLockPortrait("LockPortrait");
+ const QLatin1String attrib_networkAccess("networkaccess");
+
+ static const QString qtDir =
+ QLibraryInfo::location(QLibraryInfo::PrefixPath) + QLatin1Char('/');
+
+ QXmlStreamReader reader(&file);
+ while (!reader.atEnd()) {
+ const QXmlStreamReader::TokenType token = reader.readNext();
+ switch (token) {
+ case QXmlStreamReader::StartElement:
+ if (reader.name() == tag_app) {
+ QmlStandaloneApp qmlApp;
+ QFileInfo projectPath;
+ if (!reader.attributes().hasAttribute(attrib_projectPath)) {
+ qDebug() << "Project without path found";
+ continue;
+ }
+ projectPath = qtDir + reader.attributes().value(attrib_projectPath).toString();
+ qmlApp.setProjectPath(projectPath.absoluteFilePath());
+ if (reader.attributes().hasAttribute(attrib_mainQmlFile)) {
+ const QFileInfo qmlFileOrigin(
+ qtDir + reader.attributes().value(attrib_mainQmlFile).toString());
+ if (!qmlFileOrigin.exists()) {
+ qDebug() << "Cannot find" <<
+ QDir::toNativeSeparators(qmlFileOrigin.absoluteFilePath());
+ continue;
+ }
+ const QFileInfo qmlTargetPath(QString(projectPath.absoluteFilePath()
+ + QLatin1Char('/') + qmlFileOrigin.baseName()
+ + QLatin1String("/qml")));
+#ifdef Q_OS_WIN
+ const QString sourcePath =
+ QDir::toNativeSeparators(qmlFileOrigin.canonicalPath() + QLatin1String("/*"));
+ const QString targetPath =
+ QDir::toNativeSeparators(qmlTargetPath.absoluteFilePath() + QLatin1Char('/'));
+ QProcess xcopy;
+ QStringList parameters;
+ parameters << QLatin1String("/E") << sourcePath << targetPath;
+ xcopy.start(QLatin1String("xcopy.exe"), parameters);
+ if (!xcopy.waitForStarted() || !xcopy.waitForFinished()) {
+ qDebug() << "Could not copy" <<
+ QDir::toNativeSeparators(sourcePath);
+ continue;
+ }
+#else // Q_OS_WIN
+ // Implement me!
+#endif // Q_OS_WIN
+ qmlApp.setMainQmlFile(qmlTargetPath.absoluteFilePath()
+ + QLatin1Char('/') + qmlFileOrigin.fileName());
+ }
+ qmlApp.setProjectName(reader.attributes().hasAttribute(attrib_projectName)
+ ? reader.attributes().value(attrib_projectName).toString()
+ : QFileInfo(qmlApp.mainQmlFile()).baseName());
+ if (reader.attributes().hasAttribute(attrib_screenOrientation)) {
+ const QStringRef orientation = reader.attributes().value(attrib_screenOrientation);
+ qmlApp.setOrientation(orientation == value_screenOrientationLockLandscape ?
+ AbstractMobileApp::ScreenOrientationLockLandscape
+ : orientation == value_screenOrientationLockPortrait ?
+ AbstractMobileApp::ScreenOrientationLockPortrait
+ : AbstractMobileApp::ScreenOrientationAuto);
+ }
+ if (reader.attributes().hasAttribute(attrib_networkAccess))
+ qmlApp.setNetworkEnabled(
+ reader.attributes().value(attrib_networkAccess).toString() == QLatin1String("true"));
+ if (!qmlApp.generateFiles(0))
+ qDebug() << "Unable to generate the files for" << qmlApp.projectName();
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return true;
+}
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication a(argc, argv);
+
+ if (!processXmlFile(QLatin1String(":/qtquickapps.xml")))
+ return 1;
+
+ return 0;
+}
diff --git a/tests/tools/qtquickappblaster/qtquickappblaster.pro b/tests/tools/qtquickappblaster/qtquickappblaster.pro
new file mode 100644
index 0000000000..1d2628fa8f
--- /dev/null
+++ b/tests/tools/qtquickappblaster/qtquickappblaster.pro
@@ -0,0 +1,17 @@
+CREATORSOURCEDIR = ../../../
+
+DEFINES += \
+ CREATORLESSTEST
+APPSOURCEDIR = $$CREATORSOURCEDIR/src/plugins/qt4projectmanager/wizards
+HEADERS += \
+ $$APPSOURCEDIR/qmlstandaloneapp.h \
+ $$APPSOURCEDIR/abstractmobileapp.h
+SOURCES += \
+ $$APPSOURCEDIR/qmlstandaloneapp.cpp \
+ $$APPSOURCEDIR/abstractmobileapp.cpp \
+ main.cpp \
+ $$CREATORSOURCEDIR/tests/manual/qmlstandalone/helpers.cpp
+INCLUDEPATH += $$APPSOURCEDIR
+OTHER_FILES = qtquickapps.xml
+RESOURCES += \
+ qtquickappblaster.qrc
diff --git a/tests/tools/qtquickappblaster/qtquickappblaster.qrc b/tests/tools/qtquickappblaster/qtquickappblaster.qrc
new file mode 100644
index 0000000000..108222b952
--- /dev/null
+++ b/tests/tools/qtquickappblaster/qtquickappblaster.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>qtquickapps.xml</file>
+ </qresource>
+</RCC>
diff --git a/tests/tools/qtquickappblaster/qtquickapps.xml b/tests/tools/qtquickappblaster/qtquickapps.xml
new file mode 100644
index 0000000000..8e40ce4a3e
--- /dev/null
+++ b/tests/tools/qtquickappblaster/qtquickapps.xml
@@ -0,0 +1,268 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<qmlapps>
+<!--
+ <app
+ mainqmlfile="demos/declarative/calculator/calculator.qml"
+ projectpath="../examples/declarative/demos"
+ />
+ <app
+ mainqmlfile="demos/declarative/flickr/flickr.qml"
+ projectpath="../examples/declarative/demos"
+ networkaccess="true"
+ screenorientation="LockPortrait"
+ />
+ <app
+ mainqmlfile="demos/declarative/photoviewer/photoviewer.qml"
+ projectpath="../examples/declarative/demos"
+ networkaccess="true"
+ screenorientation="LockPortrait"
+ />
+ <app
+ mainqmlfile="demos/declarative/rssnews/rssnews.qml"
+ projectpath="../examples/declarative/demos"
+ networkaccess="true"
+ screenorientation="LockLandscape"
+ />
+ <app
+ mainqmlfile="demos/declarative/samegame/samegame.qml"
+ projectpath="../examples/declarative/demos"
+ screenorientation="LockPortrait"
+ />
+ <app
+ mainqmlfile="demos/declarative/twitter/twitter.qml"
+ projectpath="../examples/declarative/demos"
+ networkaccess="true"
+ screenorientation="LockPortrait"
+ />
+ <app
+ mainqmlfile="demos/declarative/webbrowser/webbrowser.qml"
+ projectpath="../examples/declarative/demos"
+ networkaccess="true"
+ screenorientation="LockPortrait"
+ />
+-->
+ <app
+ mainqmlfile="examples/declarative/animation/basics/property-animation.qml"
+ projectpath="../examples/declarative/animation/basics"
+ />
+ <app
+ mainqmlfile="examples/declarative/animation/basics/color-animation.qml"
+ projectpath="../examples/declarative/animation/basics"
+ />
+ <app
+ mainqmlfile="examples/declarative/animation/behaviors/behavior-example.qml"
+ projectpath="../examples/declarative/animation/behaviors"
+ />
+ <app
+ mainqmlfile="examples/declarative/animation/easing/easing.qml"
+ projectpath="../examples/declarative/animation"
+ screenorientation="LockLandscape"
+ />
+ <app
+ mainqmlfile="examples/declarative/animation/states/states.qml"
+ projectpath="../examples/declarative/animation"
+ />
+ <app
+ mainqmlfile="examples/declarative/imageelements/borderimage/borderimage.qml"
+ projectpath="../examples/declarative/imageelements"
+ screenorientation="LockLandscape"
+ />
+ <app
+ mainqmlfile="examples/declarative/imageelements/borderimage/shadows.qml"
+ projectpath="../examples/declarative/imageelements"
+ screenorientation="LockLandscape"
+ />
+ <app
+ mainqmlfile="examples/declarative/imageelements/image/image.qml"
+ projectpath="../examples/declarative/imageelements"
+ screenorientation="LockLandscape"
+ />
+ <app
+ mainqmlfile="examples/declarative/text/fonts/availableFonts.qml"
+ projectpath="../examples/declarative/text/fonts"
+ screenorientation="LockLandscape"
+ />
+ <app
+ mainqmlfile="examples/declarative/text/fonts/banner.qml"
+ projectpath="../examples/declarative/text/fonts"
+ screenorientation="LockLandscape"
+ />
+ <app
+ mainqmlfile="examples/declarative/text/fonts/fonts.qml"
+ projectpath="../examples/declarative/text/fonts/"
+ screenorientation="LockLandscape"
+ />
+ <app
+ mainqmlfile="examples/declarative/text/fonts/hello.qml"
+ projectpath="../examples/declarative/text/fonts/"
+ screenorientation="LockLandscape"
+ />
+ <app
+ mainqmlfile="examples/declarative/text/textselection/textselection.qml"
+ projectpath="../examples/declarative/text"
+ />
+ <app
+ mainqmlfile="examples/declarative/positioners/positioners.qml"
+ projectpath="../examples/declarative"
+ />
+ <app
+ mainqmlfile="examples/declarative/keyinteraction/focus/focus.qml"
+ projectpath="../examples/declarative/keyinteraction"
+ screenorientation="LockLandscape"
+ />
+ <app
+ mainqmlfile="examples/declarative/touchinteraction/gestures/experimental-gestures.qml"
+ projectpath="../examples/declarative/touchinteraction/gestures"
+ />
+ <app
+ mainqmlfile="examples/declarative/touchinteraction/mousearea/mousearea-example.qml"
+ projectpath="../examples/declarative/touchinteraction/mousearea"
+ screenorientation="LockLandscape"
+ />
+ <app
+ mainqmlfile="examples/declarative/ui-components/dialcontrol/dialcontrol.qml"
+ projectpath="../examples/declarative/ui-components"
+ />
+ <app
+ mainqmlfile="examples/declarative/ui-components/flipable/flipable.qml"
+ projectpath="../examples/declarative/ui-components"
+ />
+ <app
+ mainqmlfile="examples/declarative/ui-components/progressbar/main.qml"
+ projectpath="../examples/declarative/ui-components"
+ projectname="progressbar"
+ />
+ <app
+ mainqmlfile="examples/declarative/ui-components/scrollbar/main.qml"
+ projectpath="../examples/declarative/ui-components"
+ />
+ <app
+ mainqmlfile="examples/declarative/ui-components/searchbox/main.qml"
+ projectpath="../examples/declarative/ui-components"
+ />
+ <app
+ mainqmlfile="examples/declarative/ui-components/slideswitch/slideswitch.qml"
+ projectpath="../examples/declarative/ui-components"
+ screenorientation="LockLandscape"
+ />
+ <app
+ mainqmlfile="examples/declarative/ui-components/spinner/main.qml"
+ projectpath="../examples/declarative/ui-components"
+ screenorientation="LockPortrait"
+ />
+ <app
+ mainqmlfile="examples/declarative/ui-components/tabwidget/main.qml"
+ projectpath="../examples/declarative/ui-components"
+ screenorientation="LockLandscape"
+ />
+ <app
+ mainqmlfile="examples/declarative/toys/clocks/clocks.qml"
+ projectpath="../examples/declarative/toys"
+ screenorientation="LockLandscape"
+ />
+ <app
+ mainqmlfile="examples/declarative/toys/corkboards/corkboards.qml"
+ projectpath="../examples/declarative/toys"
+ screenorientation="LockLandscape"
+ />
+ <app
+ mainqmlfile="examples/declarative/toys/dynamicscene/dynamicscene.qml"
+ projectpath="../examples/declarative/toys"
+ screenorientation="LockLandscape"
+ />
+ <app
+ mainqmlfile="examples/declarative/toys/tic-tac-toe/tic-tac-toe.qml"
+ projectpath="../examples/declarative/toys/"
+ screenorientation="LockLandscape"
+ />
+ <app
+ mainqmlfile="examples/declarative/toys/tvtennis/tvtennis.qml"
+ projectpath="../examples/declarative/toys"
+ screenorientation="LockLandscape"
+ />
+ <app
+ mainqmlfile="examples/declarative/modelviews/gridview/gridview-example.qml"
+ projectpath="../examples/declarative/modelviews"
+ />
+ <app
+ mainqmlfile="examples/declarative/modelviews/listview/dynamiclist.qml"
+ projectpath="../examples/declarative/modelviews/listview"
+ />
+ <app
+ mainqmlfile="examples/declarative/modelviews/listview/expandingdelegates.qml"
+ projectpath="../examples/declarative/modelviews/listview"
+ />
+ <app
+ mainqmlfile="examples/declarative/modelviews/listview/highlight.qml"
+ projectpath="../examples/declarative/modelviews/listview"
+ screenorientation="LockPortrait"
+ />
+ <app
+ mainqmlfile="examples/declarative/modelviews/listview/highlightranges.qml"
+ projectpath="../examples/declarative/modelviews/listview"
+ screenorientation="LockLandscape"
+ />
+ <app
+ mainqmlfile="examples/declarative/modelviews/listview/sections.qml"
+ projectpath="../examples/declarative/modelviews/listview"
+ screenorientation="LockPortrait"
+ />
+ <app
+ mainqmlfile="examples/declarative/modelviews/pathview/pathview-example.qml"
+ projectpath="../examples/declarative/modelviews"
+ screenorientation="LockLandscape"
+ />
+ <app
+ mainqmlfile="examples/declarative/modelviews/package/Delegate.qml"
+ projectpath="../examples/declarative/modelviews"
+ screenorientation="LockLandscape"
+ />
+<!--
+ <app
+ mainqmlfile="examples/declarative/modelviews/parallax/parallax.qml"
+ projectpath="../examples/declarative/modelviews"
+ screenorientation="LockLandscape"
+ />
+-->
+ <app
+ mainqmlfile="examples/declarative/modelviews/visualitemmodel/visualitemmodel.qml"
+ projectpath="../examples/declarative/modelviews"
+ />
+ <app
+ mainqmlfile="examples/declarative/modelviews/webview/alerts.qml"
+ projectpath="../examples/declarative/modelviews/webview"
+ networkaccess="true"
+ />
+ <app
+ mainqmlfile="examples/declarative/modelviews/webview/autosize.qml"
+ projectpath="../examples/declarative/modelviews/webview"
+ screenorientation="LockPortrait"
+ networkaccess="true"
+ />
+ <app
+ mainqmlfile="examples/declarative/modelviews/webview/googlemaps.qml"
+ projectpath="../examples/declarative/modelviews/webview"
+ networkaccess="true"
+ />
+ <app
+ mainqmlfile="examples/declarative/modelviews/webview/inlinehtml.qml"
+ projectpath="../examples/declarative/modelviews/webview"
+ networkaccess="true"
+ />
+ <app
+ mainqmlfile="examples/declarative/modelviews/webview/newwindows.qml"
+ projectpath="../examples/declarative/modelviews/webview"
+ networkaccess="true"
+ />
+ <app
+ mainqmlfile="examples/declarative/xml/xmlhttprequest/xmlhttprequest-example.qml"
+ projectpath="../examples/declarative/xml"
+ screenorientation="LockLandscape"
+ networkaccess="true"
+ />
+ <app
+ mainqmlfile="examples/declarative/i18n/i18n.qml"
+ projectpath="../examples/declarative"
+ screenorientation="LockLandscape"
+ />
+</qmlapps>
diff --git a/tests/tools/tools.pro b/tests/tools/tools.pro
new file mode 100644
index 0000000000..81a1a0d710
--- /dev/null
+++ b/tests/tools/tools.pro
@@ -0,0 +1,7 @@
+TEMPLATE=subdirs
+
+SUBDIRS= \
+trklauncher \
+cplusplus-dump \
+qml-ast2dot \
+codaclient
diff --git a/tests/tools/trklauncher/main.cpp b/tests/tools/trklauncher/main.cpp
new file mode 100644
index 0000000000..6f353db777
--- /dev/null
+++ b/tests/tools/trklauncher/main.cpp
@@ -0,0 +1,208 @@
+#include "launcher.h"
+#include "communicationstarter.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QSharedPointer>
+#include <QtCore/QDebug>
+#include <QtCore/QStringList>
+
+static const char usageC[] =
+"\n"
+"Usage: %1 [options] <trk_port_name>\n"
+" %1 [options] <trk_port_name> <remote_executable_name> [-- args]\n"
+" %1 [options] -i <trk_port_name> remote_sis_file\n"
+" %1 [options] -I local_sis_file remote_sis_file] [<remote_executable_name>] [-- args]\n"
+" %1 [options] -c local_file remote_file\n"
+" %1 [options] -C remote_file [local_file|-]\n"
+"\nOptions:\n -v verbose\n"
+ " -q quiet\n"
+ " -b Prompt for Bluetooth connect (Linux only)\n"
+ " -f turn serial message frame off (Bluetooth)\n"
+"\nPing:\n"
+"%1 COM5\n"
+"\nRemote launch:\n"
+"%1 COM5 C:\\sys\\bin\\test.exe\n"
+"\nInstallation:\n"
+"%1 -i COM5 C:\\Data\\test_gcce_udeb.sisx\n"
+"\nInstallation and remote launch:\n"
+"%1 -i COM5 C:\\Data\\test_gcce_udeb.sisx C:\\sys\\bin\\test.exe\n"
+"\nCopy from local file, installation:\n"
+"%1 -I COM5 C:\\Projects\\test\\test_gcce_udeb.sisx C:\\Data\\test_gcce_udeb.sisx\n"
+"\nCopy from local file, installation and remote launch:\n"
+"%1 -I COM5 C:\\Projects\\test\\test_gcce_udeb.sisx C:\\Data\\test_gcce_udeb.sisx C:\\sys\\bin\\test.exe\n"
+"\nCopy from local file\n"
+"%1 -c COM5 c:\\foo.dat C:\\Data\\foo.dat\n"
+"\nCopy to local file\n"
+"%1 -C COM5 C:\\Data\\foo.dat c:\\foo.dat\n";
+
+static void usage()
+{
+ const QString msg = QString::fromLatin1(usageC).arg(QCoreApplication::applicationName());
+ qWarning("%s", qPrintable(msg));
+}
+
+typedef QSharedPointer<trk::Launcher> TrkLauncherPtr;
+
+// Parse arguments, return pointer or a null none.
+
+static inline TrkLauncherPtr createLauncher(trk::Launcher::Actions actions,
+ const QString &serverName,
+ bool serialFrame,
+ int verbosity)
+{
+ TrkLauncherPtr launcher(new trk::Launcher(actions));
+ launcher->setTrkServerName(serverName);
+ launcher->setSerialFrame(serialFrame);
+ launcher->setVerbose(verbosity);
+ return launcher;
+}
+
+static TrkLauncherPtr parseArguments(const QStringList &arguments, bool *bluetooth)
+{
+ enum Mode { Ping, RemoteLaunch, Install, CustomInstall, Copy, Download };
+ // Parse away options
+ Mode mode = Ping;
+ bool serialFrame = true;
+ const int argCount = arguments.size();
+ int verbosity = 1;
+ *bluetooth = false;
+ QStringList remoteArguments;
+ trk::Launcher::Actions actions = trk::Launcher::ActionPingOnly;
+ int a = 1;
+ for ( ; a < argCount; a++) {
+ const QString option = arguments.at(a);
+ if (!option.startsWith(QLatin1Char('-')))
+ break;
+ if (option.size() != 2)
+ return TrkLauncherPtr();
+ switch (option.at(1).toAscii()) {
+ case 'v':
+ verbosity++;
+ break;
+ case 'q':
+ verbosity = 0;
+ break;
+ case 'f':
+ serialFrame = false;
+ break;
+ case 'b':
+ *bluetooth = true;
+ break;
+ case 'i':
+ mode = Install;
+ actions = trk::Launcher::ActionInstall;
+ break;
+ case 'I':
+ mode = CustomInstall;
+ actions = trk::Launcher::ActionCopyInstall;
+ break;
+ case 'c':
+ mode = Copy;
+ actions = trk::Launcher::ActionCopy;
+ break;
+ case 'C':
+ mode = Download;
+ actions = trk::Launcher::ActionDownload;
+ break;
+ default:
+ return TrkLauncherPtr();
+ }
+ }
+ // Parse for '--' delimiter for remote executable argunment
+ int pastArguments = a;
+ for ( ; pastArguments < argCount && arguments.at(pastArguments) != QLatin1String("--"); pastArguments++) ;
+ if (pastArguments != argCount)
+ for (int ra = pastArguments + 1; ra < argCount; ra++)
+ remoteArguments.push_back(arguments.at(ra));
+ // Evaluate arguments
+ const int remainingArgsCount = pastArguments -a ;
+ // Ping and launch are only distinguishable by argument counts
+ if (mode == Ping && remainingArgsCount > 1)
+ mode = RemoteLaunch;
+ switch (mode) {
+ case Ping:
+ if (remainingArgsCount == 1)
+ return createLauncher(actions, arguments.at(a), serialFrame, verbosity);
+ break;
+ case RemoteLaunch:
+ if (remainingArgsCount == 2) {
+ // remote exec
+ TrkLauncherPtr launcher = createLauncher(actions, arguments.at(a), serialFrame, verbosity);
+ launcher->addStartupActions(trk::Launcher::ActionRun);
+ launcher->setFileName(arguments.at(a + 1));
+ launcher->setCommandLineArgs(remoteArguments.join(" "));
+ return launcher;
+
+ }
+ break;
+ case Install:
+ if (remainingArgsCount == 3 || remainingArgsCount == 2) {
+ TrkLauncherPtr launcher = createLauncher(actions, arguments.at(a), serialFrame, verbosity);
+ launcher->setInstallFileNames(QStringList() << arguments.at(a + 1));
+ if (remainingArgsCount == 3) {
+ launcher->addStartupActions(trk::Launcher::ActionRun);
+ launcher->setFileName(arguments.at(a + 2));
+ launcher->setCommandLineArgs(remoteArguments.join(" "));
+ }
+ return launcher;
+ }
+ break;
+ case CustomInstall:
+ if (remainingArgsCount == 4 || remainingArgsCount == 3) {
+ TrkLauncherPtr launcher = createLauncher(actions, arguments.at(a), serialFrame, verbosity);
+ launcher->setCopyFileNames(QStringList() << arguments.at(a + 1), QStringList() << arguments.at(a + 2));
+ launcher->setInstallFileNames(QStringList() << arguments.at(a + 2));
+ if (remainingArgsCount == 4) {
+ launcher->addStartupActions(trk::Launcher::ActionRun);
+ launcher->setFileName(arguments.at(a + 3));
+ launcher->setCommandLineArgs(remoteArguments.join(" "));
+ }
+ return launcher;
+ }
+ break;
+ case Copy:
+ if (remainingArgsCount == 3) {
+ TrkLauncherPtr launcher = createLauncher(actions, arguments.at(a), serialFrame, verbosity);
+ launcher->setCopyFileNames(QStringList() << arguments.at(a + 1), QStringList() << arguments.at(a + 2));
+ return launcher;
+ }
+ break;
+ case Download:
+ if (remainingArgsCount == 3) {
+ TrkLauncherPtr launcher = createLauncher(actions, arguments.at(a), serialFrame, verbosity);
+ launcher->setDownloadFileName(arguments.at(a + 1), arguments.at(a + 2));
+ return launcher;
+ }
+ break;
+ }
+ return TrkLauncherPtr();
+}
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication app(argc, argv);
+ QCoreApplication::setApplicationName(QLatin1String("trklauncher"));
+ QCoreApplication::setOrganizationName(QLatin1String("Nokia"));
+
+ bool bluetooth;
+ const TrkLauncherPtr launcher = parseArguments(app.arguments(), &bluetooth);
+ if (launcher.isNull()) {
+ usage();
+ return 1;
+ }
+ QObject::connect(launcher.data(), SIGNAL(finished()), &app, SLOT(quit()));
+ QObject::connect(launcher.data(), SIGNAL(processStopped(uint,uint,uint,QString)),
+ launcher.data(), SLOT(terminate()));
+ // BLuetooth: Open with prompt
+ QString errorMessage;
+ if (bluetooth && !trk::ConsoleBluetoothStarter::startBluetooth(launcher->trkDevice(),
+ launcher.data(),
+ 30, &errorMessage)) {
+ qWarning("%s\n", qPrintable(errorMessage));
+ return -1;
+ }
+ if (launcher->startServer(&errorMessage))
+ return app.exec();
+ qWarning("%s\n", qPrintable(errorMessage));
+ return 4;
+}
diff --git a/tests/manual/trklauncher/trklauncher.pro b/tests/tools/trklauncher/trklauncher.pro
index 00fd429acb..00fd429acb 100644
--- a/tests/manual/trklauncher/trklauncher.pro
+++ b/tests/tools/trklauncher/trklauncher.pro